|
|
1.1 root 1: /*
2: * MIPS32 emulation for qemu: main translation routines.
1.1.1.6 root 3: *
1.1 root 4: * Copyright (c) 2004-2005 Jocelyn Mayer
1.1.1.4 root 5: * Copyright (c) 2006 Marius Groeger (FPU operations)
1.1.1.5 root 6: * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
1.1.1.12 root 7: * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
1.1 root 8: *
9: * This library is free software; you can redistribute it and/or
10: * modify it under the terms of the GNU Lesser General Public
11: * License as published by the Free Software Foundation; either
12: * version 2 of the License, or (at your option) any later version.
13: *
14: * This library is distributed in the hope that it will be useful,
15: * but WITHOUT ANY WARRANTY; without even the implied warranty of
16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17: * Lesser General Public License for more details.
18: *
19: * You should have received a copy of the GNU Lesser General Public
1.1.1.8 root 20: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 21: */
22:
23: #include "cpu.h"
24: #include "disas.h"
1.1.1.7 root 25: #include "tcg-op.h"
26:
27: #include "helper.h"
28: #define GEN_HELPER 1
29: #include "helper.h"
1.1 root 30:
1.1.1.2 root 31: //#define MIPS_DEBUG_DISAS
1.1.1.5 root 32: //#define MIPS_DEBUG_SIGN_EXTENSIONS
1.1 root 33:
1.1.1.5 root 34: /* MIPS major opcodes */
35: #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
1.1 root 36:
37: enum {
38: /* indirect opcode tables */
1.1.1.5 root 39: OPC_SPECIAL = (0x00 << 26),
40: OPC_REGIMM = (0x01 << 26),
41: OPC_CP0 = (0x10 << 26),
42: OPC_CP1 = (0x11 << 26),
43: OPC_CP2 = (0x12 << 26),
44: OPC_CP3 = (0x13 << 26),
45: OPC_SPECIAL2 = (0x1C << 26),
46: OPC_SPECIAL3 = (0x1F << 26),
1.1 root 47: /* arithmetic with immediate */
1.1.1.5 root 48: OPC_ADDI = (0x08 << 26),
49: OPC_ADDIU = (0x09 << 26),
50: OPC_SLTI = (0x0A << 26),
51: OPC_SLTIU = (0x0B << 26),
1.1.1.8 root 52: /* logic with immediate */
1.1.1.5 root 53: OPC_ANDI = (0x0C << 26),
54: OPC_ORI = (0x0D << 26),
55: OPC_XORI = (0x0E << 26),
56: OPC_LUI = (0x0F << 26),
1.1.1.8 root 57: /* arithmetic with immediate */
1.1.1.5 root 58: OPC_DADDI = (0x18 << 26),
59: OPC_DADDIU = (0x19 << 26),
1.1 root 60: /* Jump and branches */
1.1.1.5 root 61: OPC_J = (0x02 << 26),
62: OPC_JAL = (0x03 << 26),
1.1.1.12 root 63: OPC_JALS = OPC_JAL | 0x5,
1.1.1.5 root 64: OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
65: OPC_BEQL = (0x14 << 26),
66: OPC_BNE = (0x05 << 26),
67: OPC_BNEL = (0x15 << 26),
68: OPC_BLEZ = (0x06 << 26),
69: OPC_BLEZL = (0x16 << 26),
70: OPC_BGTZ = (0x07 << 26),
71: OPC_BGTZL = (0x17 << 26),
72: OPC_JALX = (0x1D << 26), /* MIPS 16 only */
1.1.1.12 root 73: OPC_JALXS = OPC_JALX | 0x5,
1.1 root 74: /* Load and stores */
1.1.1.5 root 75: OPC_LDL = (0x1A << 26),
76: OPC_LDR = (0x1B << 26),
77: OPC_LB = (0x20 << 26),
78: OPC_LH = (0x21 << 26),
79: OPC_LWL = (0x22 << 26),
80: OPC_LW = (0x23 << 26),
1.1.1.12 root 81: OPC_LWPC = OPC_LW | 0x5,
1.1.1.5 root 82: OPC_LBU = (0x24 << 26),
83: OPC_LHU = (0x25 << 26),
84: OPC_LWR = (0x26 << 26),
85: OPC_LWU = (0x27 << 26),
86: OPC_SB = (0x28 << 26),
87: OPC_SH = (0x29 << 26),
88: OPC_SWL = (0x2A << 26),
89: OPC_SW = (0x2B << 26),
90: OPC_SDL = (0x2C << 26),
91: OPC_SDR = (0x2D << 26),
92: OPC_SWR = (0x2E << 26),
93: OPC_LL = (0x30 << 26),
94: OPC_LLD = (0x34 << 26),
95: OPC_LD = (0x37 << 26),
1.1.1.12 root 96: OPC_LDPC = OPC_LD | 0x5,
1.1.1.5 root 97: OPC_SC = (0x38 << 26),
98: OPC_SCD = (0x3C << 26),
99: OPC_SD = (0x3F << 26),
1.1 root 100: /* Floating point load/store */
1.1.1.5 root 101: OPC_LWC1 = (0x31 << 26),
102: OPC_LWC2 = (0x32 << 26),
103: OPC_LDC1 = (0x35 << 26),
104: OPC_LDC2 = (0x36 << 26),
105: OPC_SWC1 = (0x39 << 26),
106: OPC_SWC2 = (0x3A << 26),
107: OPC_SDC1 = (0x3D << 26),
108: OPC_SDC2 = (0x3E << 26),
109: /* MDMX ASE specific */
110: OPC_MDMX = (0x1E << 26),
1.1 root 111: /* Cache and prefetch */
1.1.1.5 root 112: OPC_CACHE = (0x2F << 26),
113: OPC_PREF = (0x33 << 26),
114: /* Reserved major opcode */
115: OPC_MAJOR3B_RESERVED = (0x3B << 26),
1.1 root 116: };
117:
118: /* MIPS special opcodes */
1.1.1.5 root 119: #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
120:
1.1 root 121: enum {
122: /* Shifts */
1.1.1.5 root 123: OPC_SLL = 0x00 | OPC_SPECIAL,
1.1 root 124: /* NOP is SLL r0, r0, 0 */
125: /* SSNOP is SLL r0, r0, 1 */
1.1.1.5 root 126: /* EHB is SLL r0, r0, 3 */
127: OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
1.1.1.12 root 128: OPC_ROTR = OPC_SRL | (1 << 21),
1.1.1.5 root 129: OPC_SRA = 0x03 | OPC_SPECIAL,
130: OPC_SLLV = 0x04 | OPC_SPECIAL,
1.1.1.6 root 131: OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
1.1.1.12 root 132: OPC_ROTRV = OPC_SRLV | (1 << 6),
1.1.1.5 root 133: OPC_SRAV = 0x07 | OPC_SPECIAL,
134: OPC_DSLLV = 0x14 | OPC_SPECIAL,
135: OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
1.1.1.12 root 136: OPC_DROTRV = OPC_DSRLV | (1 << 6),
1.1.1.5 root 137: OPC_DSRAV = 0x17 | OPC_SPECIAL,
138: OPC_DSLL = 0x38 | OPC_SPECIAL,
139: OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
1.1.1.12 root 140: OPC_DROTR = OPC_DSRL | (1 << 21),
1.1.1.5 root 141: OPC_DSRA = 0x3B | OPC_SPECIAL,
142: OPC_DSLL32 = 0x3C | OPC_SPECIAL,
143: OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
1.1.1.12 root 144: OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
1.1.1.5 root 145: OPC_DSRA32 = 0x3F | OPC_SPECIAL,
1.1 root 146: /* Multiplication / division */
1.1.1.5 root 147: OPC_MULT = 0x18 | OPC_SPECIAL,
148: OPC_MULTU = 0x19 | OPC_SPECIAL,
149: OPC_DIV = 0x1A | OPC_SPECIAL,
150: OPC_DIVU = 0x1B | OPC_SPECIAL,
151: OPC_DMULT = 0x1C | OPC_SPECIAL,
152: OPC_DMULTU = 0x1D | OPC_SPECIAL,
153: OPC_DDIV = 0x1E | OPC_SPECIAL,
154: OPC_DDIVU = 0x1F | OPC_SPECIAL,
1.1 root 155: /* 2 registers arithmetic / logic */
1.1.1.5 root 156: OPC_ADD = 0x20 | OPC_SPECIAL,
157: OPC_ADDU = 0x21 | OPC_SPECIAL,
158: OPC_SUB = 0x22 | OPC_SPECIAL,
159: OPC_SUBU = 0x23 | OPC_SPECIAL,
160: OPC_AND = 0x24 | OPC_SPECIAL,
161: OPC_OR = 0x25 | OPC_SPECIAL,
162: OPC_XOR = 0x26 | OPC_SPECIAL,
163: OPC_NOR = 0x27 | OPC_SPECIAL,
164: OPC_SLT = 0x2A | OPC_SPECIAL,
165: OPC_SLTU = 0x2B | OPC_SPECIAL,
166: OPC_DADD = 0x2C | OPC_SPECIAL,
167: OPC_DADDU = 0x2D | OPC_SPECIAL,
168: OPC_DSUB = 0x2E | OPC_SPECIAL,
169: OPC_DSUBU = 0x2F | OPC_SPECIAL,
1.1 root 170: /* Jumps */
1.1.1.5 root 171: OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
172: OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
1.1.1.12 root 173: OPC_JALRC = OPC_JALR | (0x5 << 6),
174: OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
1.1 root 175: /* Traps */
1.1.1.5 root 176: OPC_TGE = 0x30 | OPC_SPECIAL,
177: OPC_TGEU = 0x31 | OPC_SPECIAL,
178: OPC_TLT = 0x32 | OPC_SPECIAL,
179: OPC_TLTU = 0x33 | OPC_SPECIAL,
180: OPC_TEQ = 0x34 | OPC_SPECIAL,
181: OPC_TNE = 0x36 | OPC_SPECIAL,
1.1 root 182: /* HI / LO registers load & stores */
1.1.1.5 root 183: OPC_MFHI = 0x10 | OPC_SPECIAL,
184: OPC_MTHI = 0x11 | OPC_SPECIAL,
185: OPC_MFLO = 0x12 | OPC_SPECIAL,
186: OPC_MTLO = 0x13 | OPC_SPECIAL,
1.1 root 187: /* Conditional moves */
1.1.1.5 root 188: OPC_MOVZ = 0x0A | OPC_SPECIAL,
189: OPC_MOVN = 0x0B | OPC_SPECIAL,
1.1 root 190:
1.1.1.5 root 191: OPC_MOVCI = 0x01 | OPC_SPECIAL,
1.1 root 192:
193: /* Special */
1.1.1.9 root 194: OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
1.1.1.5 root 195: OPC_SYSCALL = 0x0C | OPC_SPECIAL,
196: OPC_BREAK = 0x0D | OPC_SPECIAL,
1.1.1.9 root 197: OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
1.1.1.5 root 198: OPC_SYNC = 0x0F | OPC_SPECIAL,
199:
200: OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
201: OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
202: OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
203: OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
204: OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
205: OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
206: OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
207: };
208:
1.1.1.6 root 209: /* Multiplication variants of the vr54xx. */
210: #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
211:
212: enum {
213: OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
214: OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
215: OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
216: OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
217: OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
218: OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
219: OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
220: OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
221: OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
222: OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
223: OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
224: OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
225: OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
226: OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
227: };
228:
1.1.1.5 root 229: /* REGIMM (rt field) opcodes */
230: #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
231:
232: enum {
233: OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
234: OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
235: OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
236: OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
237: OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
1.1.1.12 root 238: OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
1.1.1.5 root 239: OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
240: OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
1.1.1.12 root 241: OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
1.1.1.5 root 242: OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
243: OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
244: OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
245: OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
246: OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
247: OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
248: OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
249: OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
1.1 root 250: };
251:
1.1.1.5 root 252: /* Special2 opcodes */
253: #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
254:
1.1 root 255: enum {
1.1.1.5 root 256: /* Multiply & xxx operations */
257: OPC_MADD = 0x00 | OPC_SPECIAL2,
258: OPC_MADDU = 0x01 | OPC_SPECIAL2,
259: OPC_MUL = 0x02 | OPC_SPECIAL2,
260: OPC_MSUB = 0x04 | OPC_SPECIAL2,
261: OPC_MSUBU = 0x05 | OPC_SPECIAL2,
1.1.1.12 root 262: /* Loongson 2F */
263: OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
264: OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
265: OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
266: OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
267: OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
268: OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
269: OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
270: OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
271: OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
272: OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
273: OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
274: OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
1.1 root 275: /* Misc */
1.1.1.5 root 276: OPC_CLZ = 0x20 | OPC_SPECIAL2,
277: OPC_CLO = 0x21 | OPC_SPECIAL2,
278: OPC_DCLZ = 0x24 | OPC_SPECIAL2,
279: OPC_DCLO = 0x25 | OPC_SPECIAL2,
1.1 root 280: /* Special */
1.1.1.5 root 281: OPC_SDBBP = 0x3F | OPC_SPECIAL2,
282: };
283:
284: /* Special3 opcodes */
285: #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
286:
287: enum {
288: OPC_EXT = 0x00 | OPC_SPECIAL3,
289: OPC_DEXTM = 0x01 | OPC_SPECIAL3,
290: OPC_DEXTU = 0x02 | OPC_SPECIAL3,
291: OPC_DEXT = 0x03 | OPC_SPECIAL3,
292: OPC_INS = 0x04 | OPC_SPECIAL3,
293: OPC_DINSM = 0x05 | OPC_SPECIAL3,
294: OPC_DINSU = 0x06 | OPC_SPECIAL3,
295: OPC_DINS = 0x07 | OPC_SPECIAL3,
1.1.1.6 root 296: OPC_FORK = 0x08 | OPC_SPECIAL3,
297: OPC_YIELD = 0x09 | OPC_SPECIAL3,
1.1.1.5 root 298: OPC_BSHFL = 0x20 | OPC_SPECIAL3,
299: OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
300: OPC_RDHWR = 0x3B | OPC_SPECIAL3,
1.1.1.12 root 301:
302: /* Loongson 2E */
303: OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
304: OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
305: OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
306: OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
307: OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
308: OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
309: OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
310: OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
311: OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
312: OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
313: OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
314: OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
1.1 root 315: };
316:
1.1.1.5 root 317: /* BSHFL opcodes */
318: #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
319:
1.1 root 320: enum {
1.1.1.5 root 321: OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
322: OPC_SEB = (0x10 << 6) | OPC_BSHFL,
323: OPC_SEH = (0x18 << 6) | OPC_BSHFL,
1.1 root 324: };
325:
1.1.1.5 root 326: /* DBSHFL opcodes */
327: #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
328:
1.1 root 329: enum {
1.1.1.5 root 330: OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
331: OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
1.1 root 332: };
333:
1.1.1.5 root 334: /* Coprocessor 0 (rs field) */
335: #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
336:
1.1.1.4 root 337: enum {
1.1.1.5 root 338: OPC_MFC0 = (0x00 << 21) | OPC_CP0,
339: OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
340: OPC_MTC0 = (0x04 << 21) | OPC_CP0,
341: OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
1.1.1.6 root 342: OPC_MFTR = (0x08 << 21) | OPC_CP0,
1.1.1.5 root 343: OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
344: OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
1.1.1.6 root 345: OPC_MTTR = (0x0C << 21) | OPC_CP0,
1.1.1.5 root 346: OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
347: OPC_C0 = (0x10 << 21) | OPC_CP0,
348: OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
349: OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
1.1.1.4 root 350: };
1.1.1.5 root 351:
352: /* MFMC0 opcodes */
1.1.1.6 root 353: #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
1.1.1.5 root 354:
355: enum {
1.1.1.6 root 356: OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
357: OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
358: OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
359: OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
1.1.1.5 root 360: OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
361: OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
362: };
363:
364: /* Coprocessor 0 (with rs == C0) */
365: #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
366:
367: enum {
368: OPC_TLBR = 0x01 | OPC_C0,
369: OPC_TLBWI = 0x02 | OPC_C0,
370: OPC_TLBWR = 0x06 | OPC_C0,
371: OPC_TLBP = 0x08 | OPC_C0,
372: OPC_RFE = 0x10 | OPC_C0,
373: OPC_ERET = 0x18 | OPC_C0,
374: OPC_DERET = 0x1F | OPC_C0,
375: OPC_WAIT = 0x20 | OPC_C0,
376: };
377:
378: /* Coprocessor 1 (rs field) */
379: #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
380:
1.1.1.12 root 381: /* Values for the fmt field in FP instructions */
382: enum {
383: /* 0 - 15 are reserved */
384: FMT_S = 16, /* single fp */
385: FMT_D = 17, /* double fp */
386: FMT_E = 18, /* extended fp */
387: FMT_Q = 19, /* quad fp */
388: FMT_W = 20, /* 32-bit fixed */
389: FMT_L = 21, /* 64-bit fixed */
390: FMT_PS = 22, /* paired single fp */
391: /* 23 - 31 are reserved */
392: };
393:
1.1.1.5 root 394: enum {
395: OPC_MFC1 = (0x00 << 21) | OPC_CP1,
396: OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
397: OPC_CFC1 = (0x02 << 21) | OPC_CP1,
1.1.1.6 root 398: OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
1.1.1.5 root 399: OPC_MTC1 = (0x04 << 21) | OPC_CP1,
400: OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
401: OPC_CTC1 = (0x06 << 21) | OPC_CP1,
1.1.1.6 root 402: OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
1.1.1.5 root 403: OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
1.1.1.6 root 404: OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
405: OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
1.1.1.12 root 406: OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
407: OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
408: OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
409: OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
410: OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
411: OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
412: OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
1.1.1.5 root 413: };
414:
1.1.1.6 root 415: #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
416: #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
417:
1.1.1.5 root 418: enum {
419: OPC_BC1F = (0x00 << 16) | OPC_BC1,
420: OPC_BC1T = (0x01 << 16) | OPC_BC1,
421: OPC_BC1FL = (0x02 << 16) | OPC_BC1,
422: OPC_BC1TL = (0x03 << 16) | OPC_BC1,
423: };
424:
1.1.1.6 root 425: enum {
426: OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
427: OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
428: };
429:
430: enum {
431: OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
432: OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
433: };
1.1.1.5 root 434:
435: #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1.1.1.6 root 436:
437: enum {
438: OPC_MFC2 = (0x00 << 21) | OPC_CP2,
439: OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
440: OPC_CFC2 = (0x02 << 21) | OPC_CP2,
441: OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
442: OPC_MTC2 = (0x04 << 21) | OPC_CP2,
443: OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
444: OPC_CTC2 = (0x06 << 21) | OPC_CP2,
445: OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
446: OPC_BC2 = (0x08 << 21) | OPC_CP2,
447: };
448:
449: #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
450:
451: enum {
452: OPC_LWXC1 = 0x00 | OPC_CP3,
453: OPC_LDXC1 = 0x01 | OPC_CP3,
454: OPC_LUXC1 = 0x05 | OPC_CP3,
455: OPC_SWXC1 = 0x08 | OPC_CP3,
456: OPC_SDXC1 = 0x09 | OPC_CP3,
457: OPC_SUXC1 = 0x0D | OPC_CP3,
458: OPC_PREFX = 0x0F | OPC_CP3,
459: OPC_ALNV_PS = 0x1E | OPC_CP3,
460: OPC_MADD_S = 0x20 | OPC_CP3,
461: OPC_MADD_D = 0x21 | OPC_CP3,
462: OPC_MADD_PS = 0x26 | OPC_CP3,
463: OPC_MSUB_S = 0x28 | OPC_CP3,
464: OPC_MSUB_D = 0x29 | OPC_CP3,
465: OPC_MSUB_PS = 0x2E | OPC_CP3,
466: OPC_NMADD_S = 0x30 | OPC_CP3,
467: OPC_NMADD_D = 0x31 | OPC_CP3,
468: OPC_NMADD_PS= 0x36 | OPC_CP3,
469: OPC_NMSUB_S = 0x38 | OPC_CP3,
470: OPC_NMSUB_D = 0x39 | OPC_CP3,
471: OPC_NMSUB_PS= 0x3E | OPC_CP3,
472: };
473:
1.1.1.7 root 474: /* global register indices */
475: static TCGv_ptr cpu_env;
476: static TCGv cpu_gpr[32], cpu_PC;
477: static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
1.1.1.8 root 478: static TCGv cpu_dspctrl, btarget, bcond;
479: static TCGv_i32 hflags;
1.1.1.7 root 480: static TCGv_i32 fpu_fcr0, fpu_fcr31;
481:
1.1.1.12 root 482: static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
483:
1.1.1.7 root 484: #include "gen-icount.h"
485:
486: #define gen_helper_0i(name, arg) do { \
487: TCGv_i32 helper_tmp = tcg_const_i32(arg); \
488: gen_helper_##name(helper_tmp); \
489: tcg_temp_free_i32(helper_tmp); \
490: } while(0)
1.1.1.4 root 491:
1.1.1.7 root 492: #define gen_helper_1i(name, arg1, arg2) do { \
493: TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
494: gen_helper_##name(arg1, helper_tmp); \
495: tcg_temp_free_i32(helper_tmp); \
496: } while(0)
1.1.1.4 root 497:
1.1.1.7 root 498: #define gen_helper_2i(name, arg1, arg2, arg3) do { \
499: TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
500: gen_helper_##name(arg1, arg2, helper_tmp); \
501: tcg_temp_free_i32(helper_tmp); \
502: } while(0)
1.1.1.4 root 503:
1.1.1.7 root 504: #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
505: TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
506: gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
507: tcg_temp_free_i32(helper_tmp); \
508: } while(0)
1.1.1.4 root 509:
1.1 root 510: typedef struct DisasContext {
511: struct TranslationBlock *tb;
512: target_ulong pc, saved_pc;
513: uint32_t opcode;
1.1.1.9 root 514: int singlestep_enabled;
1.1 root 515: /* Routine used to access memory */
516: int mem_idx;
517: uint32_t hflags, saved_hflags;
518: int bstate;
519: target_ulong btarget;
520: } DisasContext;
521:
522: enum {
523: BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1.1.1.7 root 524: * exception condition */
1.1 root 525: BS_STOP = 1, /* We want to stop translation for any reason */
526: BS_BRANCH = 2, /* We reached a branch condition */
527: BS_EXCP = 3, /* We reached an exception condition */
528: };
529:
1.1.1.7 root 530: static const char *regnames[] =
531: { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
532: "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
533: "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
534: "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
535:
536: static const char *regnames_HI[] =
537: { "HI0", "HI1", "HI2", "HI3", };
538:
539: static const char *regnames_LO[] =
540: { "LO0", "LO1", "LO2", "LO3", };
541:
542: static const char *regnames_ACX[] =
543: { "ACX0", "ACX1", "ACX2", "ACX3", };
544:
545: static const char *fregnames[] =
546: { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
547: "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
548: "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
549: "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
550:
1.1.1.6 root 551: #ifdef MIPS_DEBUG_DISAS
1.1.1.8 root 552: #define MIPS_DEBUG(fmt, ...) \
1.1.1.7 root 553: qemu_log_mask(CPU_LOG_TB_IN_ASM, \
554: TARGET_FMT_lx ": %08x " fmt "\n", \
1.1.1.8 root 555: ctx->pc, ctx->opcode , ## __VA_ARGS__)
1.1.1.7 root 556: #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
1.1 root 557: #else
1.1.1.8 root 558: #define MIPS_DEBUG(fmt, ...) do { } while(0)
1.1.1.7 root 559: #define LOG_DISAS(...) do { } while (0)
1.1 root 560: #endif
561:
562: #define MIPS_INVAL(op) \
563: do { \
564: MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
565: ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
566: } while (0)
567:
1.1.1.7 root 568: /* General purpose registers moves. */
569: static inline void gen_load_gpr (TCGv t, int reg)
570: {
571: if (reg == 0)
572: tcg_gen_movi_tl(t, 0);
573: else
574: tcg_gen_mov_tl(t, cpu_gpr[reg]);
575: }
1.1.1.6 root 576:
1.1.1.7 root 577: static inline void gen_store_gpr (TCGv t, int reg)
578: {
579: if (reg != 0)
580: tcg_gen_mov_tl(cpu_gpr[reg], t);
581: }
1.1.1.6 root 582:
1.1.1.7 root 583: /* Moves to/from ACX register. */
584: static inline void gen_load_ACX (TCGv t, int reg)
585: {
586: tcg_gen_mov_tl(t, cpu_ACX[reg]);
587: }
1.1.1.6 root 588:
1.1.1.7 root 589: static inline void gen_store_ACX (TCGv t, int reg)
590: {
591: tcg_gen_mov_tl(cpu_ACX[reg], t);
592: }
1.1 root 593:
1.1.1.7 root 594: /* Moves to/from shadow registers. */
595: static inline void gen_load_srsgpr (int from, int to)
596: {
1.1.1.8 root 597: TCGv t0 = tcg_temp_new();
1.1.1.6 root 598:
1.1.1.7 root 599: if (from == 0)
1.1.1.8 root 600: tcg_gen_movi_tl(t0, 0);
1.1.1.7 root 601: else {
1.1.1.8 root 602: TCGv_i32 t2 = tcg_temp_new_i32();
1.1.1.7 root 603: TCGv_ptr addr = tcg_temp_new_ptr();
1.1.1.6 root 604:
1.1.1.16! root 605: tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1.1.1.8 root 606: tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
607: tcg_gen_andi_i32(t2, t2, 0xf);
608: tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
609: tcg_gen_ext_i32_ptr(addr, t2);
1.1.1.7 root 610: tcg_gen_add_ptr(addr, cpu_env, addr);
1.1 root 611:
1.1.1.8 root 612: tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1.1.1.7 root 613: tcg_temp_free_ptr(addr);
1.1.1.8 root 614: tcg_temp_free_i32(t2);
1.1.1.7 root 615: }
1.1.1.8 root 616: gen_store_gpr(t0, to);
617: tcg_temp_free(t0);
1.1.1.7 root 618: }
1.1 root 619:
1.1.1.7 root 620: static inline void gen_store_srsgpr (int from, int to)
621: {
622: if (to != 0) {
1.1.1.8 root 623: TCGv t0 = tcg_temp_new();
624: TCGv_i32 t2 = tcg_temp_new_i32();
1.1.1.7 root 625: TCGv_ptr addr = tcg_temp_new_ptr();
1.1.1.4 root 626:
1.1.1.8 root 627: gen_load_gpr(t0, from);
1.1.1.16! root 628: tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1.1.1.8 root 629: tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
630: tcg_gen_andi_i32(t2, t2, 0xf);
631: tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
632: tcg_gen_ext_i32_ptr(addr, t2);
1.1.1.7 root 633: tcg_gen_add_ptr(addr, cpu_env, addr);
1.1.1.4 root 634:
1.1.1.8 root 635: tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1.1.1.7 root 636: tcg_temp_free_ptr(addr);
1.1.1.8 root 637: tcg_temp_free_i32(t2);
638: tcg_temp_free(t0);
1.1.1.6 root 639: }
640: }
641:
1.1.1.7 root 642: /* Floating point register moves. */
643: static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
1.1.1.6 root 644: {
1.1.1.16! root 645: tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
1.1.1.7 root 646: }
647:
648: static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
649: {
1.1.1.16! root 650: tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
1.1.1.7 root 651: }
652:
1.1.1.8 root 653: static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
1.1.1.7 root 654: {
1.1.1.16! root 655: tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
1.1.1.6 root 656: }
657:
1.1.1.8 root 658: static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
1.1 root 659: {
1.1.1.16! root 660: tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
1.1.1.7 root 661: }
662:
1.1.1.8 root 663: static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
1.1.1.7 root 664: {
1.1.1.8 root 665: if (ctx->hflags & MIPS_HFLAG_F64) {
1.1.1.16! root 666: tcg_gen_ld_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
1.1.1.8 root 667: } else {
668: TCGv_i32 t0 = tcg_temp_new_i32();
669: TCGv_i32 t1 = tcg_temp_new_i32();
670: gen_load_fpr32(t0, reg & ~1);
671: gen_load_fpr32(t1, reg | 1);
672: tcg_gen_concat_i32_i64(t, t0, t1);
673: tcg_temp_free_i32(t0);
674: tcg_temp_free_i32(t1);
675: }
1.1.1.7 root 676: }
677:
1.1.1.8 root 678: static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
1.1.1.7 root 679: {
1.1.1.8 root 680: if (ctx->hflags & MIPS_HFLAG_F64) {
1.1.1.16! root 681: tcg_gen_st_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
1.1.1.8 root 682: } else {
683: TCGv_i64 t0 = tcg_temp_new_i64();
684: TCGv_i32 t1 = tcg_temp_new_i32();
685: tcg_gen_trunc_i64_i32(t1, t);
686: gen_store_fpr32(t1, reg & ~1);
687: tcg_gen_shri_i64(t0, t, 32);
688: tcg_gen_trunc_i64_i32(t1, t0);
689: gen_store_fpr32(t1, reg | 1);
690: tcg_temp_free_i32(t1);
691: tcg_temp_free_i64(t0);
692: }
1.1.1.7 root 693: }
694:
1.1.1.8 root 695: static inline int get_fp_bit (int cc)
1.1.1.7 root 696: {
1.1.1.8 root 697: if (cc)
698: return 24 + cc;
699: else
700: return 23;
1.1.1.7 root 701: }
702:
703: /* Tests */
704: static inline void gen_save_pc(target_ulong pc)
705: {
706: tcg_gen_movi_tl(cpu_PC, pc);
707: }
708:
709: static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
710: {
711: LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1.1 root 712: if (do_save_pc && ctx->pc != ctx->saved_pc) {
1.1.1.6 root 713: gen_save_pc(ctx->pc);
1.1 root 714: ctx->saved_pc = ctx->pc;
715: }
716: if (ctx->hflags != ctx->saved_hflags) {
1.1.1.8 root 717: tcg_gen_movi_i32(hflags, ctx->hflags);
1.1 root 718: ctx->saved_hflags = ctx->hflags;
1.1.1.12 root 719: switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1.1.1.6 root 720: case MIPS_HFLAG_BR:
721: break;
722: case MIPS_HFLAG_BC:
723: case MIPS_HFLAG_BL:
724: case MIPS_HFLAG_B:
1.1.1.7 root 725: tcg_gen_movi_tl(btarget, ctx->btarget);
1.1.1.6 root 726: break;
1.1 root 727: }
728: }
729: }
730:
1.1.1.16! root 731: static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
1.1.1.6 root 732: {
733: ctx->saved_hflags = ctx->hflags;
1.1.1.12 root 734: switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1.1.1.6 root 735: case MIPS_HFLAG_BR:
736: break;
737: case MIPS_HFLAG_BC:
738: case MIPS_HFLAG_BL:
1.1.1.7 root 739: case MIPS_HFLAG_B:
1.1.1.6 root 740: ctx->btarget = env->btarget;
741: break;
742: }
743: }
744:
1.1.1.7 root 745: static inline void
746: generate_exception_err (DisasContext *ctx, int excp, int err)
1.1 root 747: {
1.1.1.7 root 748: TCGv_i32 texcp = tcg_const_i32(excp);
749: TCGv_i32 terr = tcg_const_i32(err);
1.1 root 750: save_cpu_state(ctx, 1);
1.1.1.7 root 751: gen_helper_raise_exception_err(texcp, terr);
752: tcg_temp_free_i32(terr);
753: tcg_temp_free_i32(texcp);
754: }
755:
756: static inline void
757: generate_exception (DisasContext *ctx, int excp)
758: {
759: save_cpu_state(ctx, 1);
760: gen_helper_0i(raise_exception, excp);
1.1 root 761: }
762:
1.1.1.7 root 763: /* Addresses computation */
1.1.1.9 root 764: static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1.1.1.2 root 765: {
1.1.1.9 root 766: tcg_gen_add_tl(ret, arg0, arg1);
1.1.1.7 root 767:
768: #if defined(TARGET_MIPS64)
769: /* For compatibility with 32-bit code, data reference in user mode
770: with Status_UX = 0 should be casted to 32-bit and sign extended.
771: See the MIPS64 PRA manual, section 4.10. */
772: if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
773: !(ctx->hflags & MIPS_HFLAG_UX)) {
1.1.1.9 root 774: tcg_gen_ext32s_i64(ret, ret);
1.1.1.7 root 775: }
776: #endif
1.1.1.2 root 777: }
778:
1.1.1.7 root 779: static inline void check_cp0_enabled(DisasContext *ctx)
1.1.1.6 root 780: {
781: if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1.1.1.10 root 782: generate_exception_err(ctx, EXCP_CpU, 0);
1.1.1.6 root 783: }
784:
1.1.1.7 root 785: static inline void check_cp1_enabled(DisasContext *ctx)
1.1.1.6 root 786: {
787: if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
788: generate_exception_err(ctx, EXCP_CpU, 1);
789: }
790:
791: /* Verify that the processor is running with COP1X instructions enabled.
792: This is associated with the nabla symbol in the MIPS32 and MIPS64
793: opcode tables. */
794:
1.1.1.7 root 795: static inline void check_cop1x(DisasContext *ctx)
1.1.1.6 root 796: {
797: if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
798: generate_exception(ctx, EXCP_RI);
799: }
800:
801: /* Verify that the processor is running with 64-bit floating-point
802: operations enabled. */
803:
1.1.1.7 root 804: static inline void check_cp1_64bitmode(DisasContext *ctx)
1.1.1.6 root 805: {
806: if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
807: generate_exception(ctx, EXCP_RI);
808: }
809:
810: /*
811: * Verify if floating point register is valid; an operation is not defined
812: * if bit 0 of any register specification is set and the FR bit in the
813: * Status register equals zero, since the register numbers specify an
814: * even-odd pair of adjacent coprocessor general registers. When the FR bit
815: * in the Status register equals one, both even and odd register numbers
816: * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
817: *
818: * Multiple 64 bit wide registers can be checked by calling
819: * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
820: */
1.1.1.7 root 821: static inline void check_cp1_registers(DisasContext *ctx, int regs)
1.1.1.6 root 822: {
823: if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
824: generate_exception(ctx, EXCP_RI);
825: }
826:
827: /* This code generates a "reserved instruction" exception if the
828: CPU does not support the instruction set corresponding to flags. */
1.1.1.16! root 829: static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
1.1.1.6 root 830: {
831: if (unlikely(!(env->insn_flags & flags)))
832: generate_exception(ctx, EXCP_RI);
833: }
834:
835: /* This code generates a "reserved instruction" exception if 64-bit
836: instructions are not enabled. */
1.1.1.7 root 837: static inline void check_mips_64(DisasContext *ctx)
1.1.1.6 root 838: {
839: if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
840: generate_exception(ctx, EXCP_RI);
841: }
842:
1.1.1.12 root 843: /* Define small wrappers for gen_load_fpr* so that we have a uniform
844: calling interface for 32 and 64-bit FPRs. No sense in changing
845: all callers for gen_load_fpr32 when we need the CTX parameter for
846: this one use. */
847: #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
848: #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
849: #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
850: static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
851: int ft, int fs, int cc) \
852: { \
853: TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
854: TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
855: switch (ifmt) { \
856: case FMT_PS: \
857: check_cp1_64bitmode(ctx); \
858: break; \
859: case FMT_D: \
860: if (abs) { \
861: check_cop1x(ctx); \
862: } \
863: check_cp1_registers(ctx, fs | ft); \
864: break; \
865: case FMT_S: \
866: if (abs) { \
867: check_cop1x(ctx); \
868: } \
869: break; \
870: } \
871: gen_ldcmp_fpr##bits (ctx, fp0, fs); \
872: gen_ldcmp_fpr##bits (ctx, fp1, ft); \
873: switch (n) { \
874: case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
875: case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
876: case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
877: case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
878: case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
879: case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
880: case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
881: case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
882: case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
883: case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
884: case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
885: case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
886: case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
887: case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
888: case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
889: case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
890: default: abort(); \
891: } \
892: tcg_temp_free_i##bits (fp0); \
893: tcg_temp_free_i##bits (fp1); \
894: }
895:
896: FOP_CONDS(, 0, d, FMT_D, 64)
897: FOP_CONDS(abs, 1, d, FMT_D, 64)
898: FOP_CONDS(, 0, s, FMT_S, 32)
899: FOP_CONDS(abs, 1, s, FMT_S, 32)
900: FOP_CONDS(, 0, ps, FMT_PS, 64)
901: FOP_CONDS(abs, 1, ps, FMT_PS, 64)
902: #undef FOP_CONDS
903: #undef gen_ldcmp_fpr32
904: #undef gen_ldcmp_fpr64
905:
1.1.1.7 root 906: /* load/store instructions. */
1.1.1.8 root 907: #define OP_LD(insn,fname) \
1.1.1.12 root 908: static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1.1.1.8 root 909: { \
910: tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1.1.1.7 root 911: }
912: OP_LD(lb,ld8s);
913: OP_LD(lbu,ld8u);
914: OP_LD(lh,ld16s);
915: OP_LD(lhu,ld16u);
916: OP_LD(lw,ld32s);
917: #if defined(TARGET_MIPS64)
918: OP_LD(lwu,ld32u);
919: OP_LD(ld,ld64);
920: #endif
921: #undef OP_LD
922:
1.1.1.8 root 923: #define OP_ST(insn,fname) \
1.1.1.12 root 924: static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
1.1.1.8 root 925: { \
926: tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
1.1.1.7 root 927: }
928: OP_ST(sb,st8);
929: OP_ST(sh,st16);
930: OP_ST(sw,st32);
931: #if defined(TARGET_MIPS64)
932: OP_ST(sd,st64);
933: #endif
934: #undef OP_ST
935:
1.1.1.9 root 936: #ifdef CONFIG_USER_ONLY
1.1.1.8 root 937: #define OP_LD_ATOMIC(insn,fname) \
1.1.1.12 root 938: static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1.1.1.8 root 939: { \
940: TCGv t0 = tcg_temp_new(); \
941: tcg_gen_mov_tl(t0, arg1); \
942: tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1.1.1.16! root 943: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
! 944: tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
1.1.1.8 root 945: tcg_temp_free(t0); \
1.1 root 946: }
1.1.1.9 root 947: #else
948: #define OP_LD_ATOMIC(insn,fname) \
1.1.1.12 root 949: static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1.1.1.9 root 950: { \
951: gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
952: }
953: #endif
1.1.1.7 root 954: OP_LD_ATOMIC(ll,ld32s);
955: #if defined(TARGET_MIPS64)
956: OP_LD_ATOMIC(lld,ld64);
1.1 root 957: #endif
1.1.1.7 root 958: #undef OP_LD_ATOMIC
1.1 root 959:
1.1.1.8 root 960: #ifdef CONFIG_USER_ONLY
961: #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1.1.1.12 root 962: static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1.1.1.8 root 963: { \
964: TCGv t0 = tcg_temp_new(); \
965: int l1 = gen_new_label(); \
966: int l2 = gen_new_label(); \
967: \
968: tcg_gen_andi_tl(t0, arg2, almask); \
969: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
1.1.1.16! root 970: tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
1.1.1.8 root 971: generate_exception(ctx, EXCP_AdES); \
972: gen_set_label(l1); \
1.1.1.16! root 973: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1.1.1.8 root 974: tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
975: tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
1.1.1.16! root 976: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
! 977: tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
1.1.1.8 root 978: gen_helper_0i(raise_exception, EXCP_SC); \
979: gen_set_label(l2); \
980: tcg_gen_movi_tl(t0, 0); \
981: gen_store_gpr(t0, rt); \
982: tcg_temp_free(t0); \
983: }
984: #else
985: #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1.1.1.12 root 986: static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1.1.1.8 root 987: { \
988: TCGv t0 = tcg_temp_new(); \
1.1.1.9 root 989: gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
1.1.1.8 root 990: gen_store_gpr(t0, rt); \
991: tcg_temp_free(t0); \
1.1.1.7 root 992: }
1.1.1.8 root 993: #endif
994: OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1.1.1.6 root 995: #if defined(TARGET_MIPS64)
1.1.1.8 root 996: OP_ST_ATOMIC(scd,st64,ld64,0x7);
1.1 root 997: #endif
1.1.1.7 root 998: #undef OP_ST_ATOMIC
1.1 root 999:
1.1.1.12 root 1000: static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1001: int base, int16_t offset)
1.1 root 1002: {
1003: if (base == 0) {
1.1.1.12 root 1004: tcg_gen_movi_tl(addr, offset);
1.1 root 1005: } else if (offset == 0) {
1.1.1.12 root 1006: gen_load_gpr(addr, base);
1.1 root 1007: } else {
1.1.1.12 root 1008: tcg_gen_movi_tl(addr, offset);
1009: gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1.1 root 1010: }
1.1.1.12 root 1011: }
1012:
1013: static target_ulong pc_relative_pc (DisasContext *ctx)
1014: {
1015: target_ulong pc = ctx->pc;
1016:
1017: if (ctx->hflags & MIPS_HFLAG_BMASK) {
1018: int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1019:
1020: pc -= branch_bytes;
1021: }
1022:
1023: pc &= ~(target_ulong)3;
1024: return pc;
1025: }
1026:
1027: /* Load */
1.1.1.16! root 1028: static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1.1.1.12 root 1029: int rt, int base, int16_t offset)
1030: {
1031: const char *opn = "ld";
1032: TCGv t0, t1;
1033:
1034: if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1035: /* Loongson CPU uses a load to zero register for prefetch.
1036: We emulate it as a NOP. On other CPU we must perform the
1037: actual memory access. */
1038: MIPS_DEBUG("NOP");
1039: return;
1040: }
1041:
1042: t0 = tcg_temp_new();
1043: t1 = tcg_temp_new();
1044: gen_base_offset_addr(ctx, t0, base, offset);
1045:
1.1 root 1046: switch (opc) {
1.1.1.6 root 1047: #if defined(TARGET_MIPS64)
1048: case OPC_LWU:
1.1.1.8 root 1049: save_cpu_state(ctx, 0);
1.1.1.12 root 1050: op_ld_lwu(t0, t0, ctx);
1.1.1.7 root 1051: gen_store_gpr(t0, rt);
1.1.1.6 root 1052: opn = "lwu";
1053: break;
1.1 root 1054: case OPC_LD:
1.1.1.8 root 1055: save_cpu_state(ctx, 0);
1.1.1.12 root 1056: op_ld_ld(t0, t0, ctx);
1.1.1.7 root 1057: gen_store_gpr(t0, rt);
1.1 root 1058: opn = "ld";
1059: break;
1.1.1.5 root 1060: case OPC_LLD:
1.1.1.13 root 1061: save_cpu_state(ctx, 1);
1.1.1.12 root 1062: op_ld_lld(t0, t0, ctx);
1.1.1.7 root 1063: gen_store_gpr(t0, rt);
1.1.1.5 root 1064: opn = "lld";
1065: break;
1.1 root 1066: case OPC_LDL:
1.1.1.7 root 1067: save_cpu_state(ctx, 1);
1068: gen_load_gpr(t1, rt);
1.1.1.8 root 1069: gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1070: gen_store_gpr(t1, rt);
1.1 root 1071: opn = "ldl";
1072: break;
1073: case OPC_LDR:
1.1.1.7 root 1074: save_cpu_state(ctx, 1);
1075: gen_load_gpr(t1, rt);
1.1.1.8 root 1076: gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1077: gen_store_gpr(t1, rt);
1.1 root 1078: opn = "ldr";
1079: break;
1.1.1.12 root 1080: case OPC_LDPC:
1.1.1.13 root 1081: save_cpu_state(ctx, 0);
1.1.1.12 root 1082: tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1083: gen_op_addr_add(ctx, t0, t0, t1);
1084: op_ld_ld(t0, t0, ctx);
1085: gen_store_gpr(t0, rt);
1086: opn = "ldpc";
1.1 root 1087: break;
1088: #endif
1.1.1.12 root 1089: case OPC_LWPC:
1.1.1.13 root 1090: save_cpu_state(ctx, 0);
1.1.1.12 root 1091: tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1092: gen_op_addr_add(ctx, t0, t0, t1);
1093: op_ld_lw(t0, t0, ctx);
1094: gen_store_gpr(t0, rt);
1095: opn = "lwpc";
1096: break;
1.1 root 1097: case OPC_LW:
1.1.1.8 root 1098: save_cpu_state(ctx, 0);
1.1.1.12 root 1099: op_ld_lw(t0, t0, ctx);
1.1.1.7 root 1100: gen_store_gpr(t0, rt);
1.1 root 1101: opn = "lw";
1102: break;
1103: case OPC_LH:
1.1.1.8 root 1104: save_cpu_state(ctx, 0);
1.1.1.12 root 1105: op_ld_lh(t0, t0, ctx);
1.1.1.7 root 1106: gen_store_gpr(t0, rt);
1.1 root 1107: opn = "lh";
1108: break;
1109: case OPC_LHU:
1.1.1.8 root 1110: save_cpu_state(ctx, 0);
1.1.1.12 root 1111: op_ld_lhu(t0, t0, ctx);
1.1.1.7 root 1112: gen_store_gpr(t0, rt);
1.1 root 1113: opn = "lhu";
1114: break;
1115: case OPC_LB:
1.1.1.8 root 1116: save_cpu_state(ctx, 0);
1.1.1.12 root 1117: op_ld_lb(t0, t0, ctx);
1.1.1.7 root 1118: gen_store_gpr(t0, rt);
1.1 root 1119: opn = "lb";
1120: break;
1121: case OPC_LBU:
1.1.1.8 root 1122: save_cpu_state(ctx, 0);
1.1.1.12 root 1123: op_ld_lbu(t0, t0, ctx);
1.1.1.7 root 1124: gen_store_gpr(t0, rt);
1.1 root 1125: opn = "lbu";
1126: break;
1127: case OPC_LWL:
1.1.1.7 root 1128: save_cpu_state(ctx, 1);
1129: gen_load_gpr(t1, rt);
1.1.1.8 root 1130: gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1131: gen_store_gpr(t1, rt);
1.1 root 1132: opn = "lwl";
1133: break;
1134: case OPC_LWR:
1.1.1.7 root 1135: save_cpu_state(ctx, 1);
1136: gen_load_gpr(t1, rt);
1.1.1.8 root 1137: gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1138: gen_store_gpr(t1, rt);
1.1 root 1139: opn = "lwr";
1140: break;
1141: case OPC_LL:
1.1.1.9 root 1142: save_cpu_state(ctx, 1);
1.1.1.12 root 1143: op_ld_ll(t0, t0, ctx);
1.1.1.7 root 1144: gen_store_gpr(t0, rt);
1.1 root 1145: opn = "ll";
1146: break;
1.1.1.8 root 1147: }
1.1.1.13 root 1148: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1149: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1150: tcg_temp_free(t0);
1151: tcg_temp_free(t1);
1152: }
1153:
1.1.1.12 root 1154: /* Store */
1155: static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1156: int base, int16_t offset)
1157: {
1158: const char *opn = "st";
1159: TCGv t0 = tcg_temp_new();
1160: TCGv t1 = tcg_temp_new();
1161:
1162: gen_base_offset_addr(ctx, t0, base, offset);
1163: gen_load_gpr(t1, rt);
1164: switch (opc) {
1165: #if defined(TARGET_MIPS64)
1166: case OPC_SD:
1167: save_cpu_state(ctx, 0);
1168: op_st_sd(t1, t0, ctx);
1169: opn = "sd";
1170: break;
1171: case OPC_SDL:
1172: save_cpu_state(ctx, 1);
1173: gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1174: opn = "sdl";
1175: break;
1176: case OPC_SDR:
1177: save_cpu_state(ctx, 1);
1178: gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1179: opn = "sdr";
1180: break;
1181: #endif
1182: case OPC_SW:
1183: save_cpu_state(ctx, 0);
1184: op_st_sw(t1, t0, ctx);
1185: opn = "sw";
1186: break;
1187: case OPC_SH:
1188: save_cpu_state(ctx, 0);
1189: op_st_sh(t1, t0, ctx);
1190: opn = "sh";
1191: break;
1192: case OPC_SB:
1193: save_cpu_state(ctx, 0);
1194: op_st_sb(t1, t0, ctx);
1195: opn = "sb";
1196: break;
1197: case OPC_SWL:
1198: save_cpu_state(ctx, 1);
1199: gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1200: opn = "swl";
1201: break;
1202: case OPC_SWR:
1203: save_cpu_state(ctx, 1);
1204: gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1205: opn = "swr";
1206: break;
1207: }
1.1.1.13 root 1208: (void)opn; /* avoid a compiler warning */
1.1.1.12 root 1209: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1210: tcg_temp_free(t0);
1211: tcg_temp_free(t1);
1212: }
1213:
1214:
1.1.1.8 root 1215: /* Store conditional */
1216: static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1217: int base, int16_t offset)
1218: {
1219: const char *opn = "st_cond";
1220: TCGv t0, t1;
1221:
1222: t0 = tcg_temp_local_new();
1223:
1.1.1.12 root 1224: gen_base_offset_addr(ctx, t0, base, offset);
1.1.1.8 root 1225: /* Don't do NOP if destination is zero: we must perform the actual
1226: memory access. */
1227:
1228: t1 = tcg_temp_local_new();
1229: gen_load_gpr(t1, rt);
1230: switch (opc) {
1231: #if defined(TARGET_MIPS64)
1232: case OPC_SCD:
1.1.1.13 root 1233: save_cpu_state(ctx, 1);
1.1.1.12 root 1234: op_st_scd(t1, t0, rt, ctx);
1.1.1.8 root 1235: opn = "scd";
1236: break;
1237: #endif
1.1 root 1238: case OPC_SC:
1.1.1.9 root 1239: save_cpu_state(ctx, 1);
1.1.1.12 root 1240: op_st_sc(t1, t0, rt, ctx);
1.1 root 1241: opn = "sc";
1242: break;
1243: }
1.1.1.13 root 1244: (void)opn; /* avoid a compiler warning */
1.1 root 1245: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1.1.1.7 root 1246: tcg_temp_free(t1);
1.1.1.8 root 1247: tcg_temp_free(t0);
1.1 root 1248: }
1249:
1.1.1.4 root 1250: /* Load and store */
1.1.1.5 root 1251: static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1.1.1.7 root 1252: int base, int16_t offset)
1.1.1.4 root 1253: {
1.1.1.6 root 1254: const char *opn = "flt_ldst";
1.1.1.8 root 1255: TCGv t0 = tcg_temp_new();
1.1.1.4 root 1256:
1.1.1.12 root 1257: gen_base_offset_addr(ctx, t0, base, offset);
1.1.1.4 root 1258: /* Don't do NOP if destination is zero: we must perform the actual
1.1.1.6 root 1259: memory access. */
1.1.1.4 root 1260: switch (opc) {
1261: case OPC_LWC1:
1.1.1.7 root 1262: {
1263: TCGv_i32 fp0 = tcg_temp_new_i32();
1264:
1.1.1.8 root 1265: tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1266: tcg_gen_trunc_tl_i32(fp0, t0);
1.1.1.7 root 1267: gen_store_fpr32(fp0, ft);
1268: tcg_temp_free_i32(fp0);
1269: }
1.1.1.4 root 1270: opn = "lwc1";
1271: break;
1272: case OPC_SWC1:
1.1.1.7 root 1273: {
1274: TCGv_i32 fp0 = tcg_temp_new_i32();
1275: TCGv t1 = tcg_temp_new();
1276:
1277: gen_load_fpr32(fp0, ft);
1278: tcg_gen_extu_i32_tl(t1, fp0);
1279: tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1280: tcg_temp_free(t1);
1281: tcg_temp_free_i32(fp0);
1282: }
1.1.1.4 root 1283: opn = "swc1";
1284: break;
1285: case OPC_LDC1:
1.1.1.7 root 1286: {
1287: TCGv_i64 fp0 = tcg_temp_new_i64();
1288:
1289: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1290: gen_store_fpr64(ctx, fp0, ft);
1291: tcg_temp_free_i64(fp0);
1292: }
1.1.1.4 root 1293: opn = "ldc1";
1294: break;
1295: case OPC_SDC1:
1.1.1.7 root 1296: {
1297: TCGv_i64 fp0 = tcg_temp_new_i64();
1298:
1299: gen_load_fpr64(ctx, fp0, ft);
1300: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1301: tcg_temp_free_i64(fp0);
1302: }
1.1.1.4 root 1303: opn = "sdc1";
1304: break;
1305: default:
1.1.1.6 root 1306: MIPS_INVAL(opn);
1307: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 1308: goto out;
1.1.1.4 root 1309: }
1.1.1.13 root 1310: (void)opn; /* avoid a compiler warning */
1.1.1.4 root 1311: MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1.1.1.7 root 1312: out:
1313: tcg_temp_free(t0);
1.1.1.4 root 1314: }
1.1.1.5 root 1315:
1.1.1.16! root 1316: static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
1.1.1.12 root 1317: uint32_t op, int rt, int rs, int16_t imm)
1318: {
1319: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1320: check_cp1_enabled(ctx);
1321: gen_flt_ldst(ctx, op, rt, rs, imm);
1322: } else {
1323: generate_exception_err(ctx, EXCP_CpU, 1);
1324: }
1325: }
1326:
1.1 root 1327: /* Arithmetic with immediate operand */
1.1.1.16! root 1328: static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1.1.1.6 root 1329: int rt, int rs, int16_t imm)
1.1 root 1330: {
1.1.1.8 root 1331: target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1.1.1.6 root 1332: const char *opn = "imm arith";
1.1 root 1333:
1.1.1.5 root 1334: if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1.1.1.6 root 1335: /* If no destination, treat it as a NOP.
1336: For addi, we must generate the overflow exception when needed. */
1.1 root 1337: MIPS_DEBUG("NOP");
1.1.1.8 root 1338: return;
1.1 root 1339: }
1340: switch (opc) {
1341: case OPC_ADDI:
1.1.1.7 root 1342: {
1.1.1.8 root 1343: TCGv t0 = tcg_temp_local_new();
1344: TCGv t1 = tcg_temp_new();
1345: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1346: int l1 = gen_new_label();
1347:
1.1.1.8 root 1348: gen_load_gpr(t1, rs);
1349: tcg_gen_addi_tl(t0, t1, uimm);
1350: tcg_gen_ext32s_tl(t0, t0);
1.1.1.7 root 1351:
1.1.1.8 root 1352: tcg_gen_xori_tl(t1, t1, ~uimm);
1353: tcg_gen_xori_tl(t2, t0, uimm);
1354: tcg_gen_and_tl(t1, t1, t2);
1355: tcg_temp_free(t2);
1356: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1357: tcg_temp_free(t1);
1.1.1.7 root 1358: /* operands of same sign, result different sign */
1359: generate_exception(ctx, EXCP_OVERFLOW);
1360: gen_set_label(l1);
1361: tcg_gen_ext32s_tl(t0, t0);
1.1.1.8 root 1362: gen_store_gpr(t0, rt);
1363: tcg_temp_free(t0);
1.1.1.7 root 1364: }
1.1 root 1365: opn = "addi";
1366: break;
1367: case OPC_ADDIU:
1.1.1.8 root 1368: if (rs != 0) {
1369: tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1370: tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1371: } else {
1372: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1373: }
1.1 root 1374: opn = "addiu";
1375: break;
1.1.1.6 root 1376: #if defined(TARGET_MIPS64)
1.1.1.5 root 1377: case OPC_DADDI:
1.1.1.7 root 1378: {
1.1.1.8 root 1379: TCGv t0 = tcg_temp_local_new();
1380: TCGv t1 = tcg_temp_new();
1381: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1382: int l1 = gen_new_label();
1383:
1.1.1.8 root 1384: gen_load_gpr(t1, rs);
1385: tcg_gen_addi_tl(t0, t1, uimm);
1.1.1.7 root 1386:
1.1.1.8 root 1387: tcg_gen_xori_tl(t1, t1, ~uimm);
1388: tcg_gen_xori_tl(t2, t0, uimm);
1389: tcg_gen_and_tl(t1, t1, t2);
1390: tcg_temp_free(t2);
1391: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1392: tcg_temp_free(t1);
1.1.1.7 root 1393: /* operands of same sign, result different sign */
1394: generate_exception(ctx, EXCP_OVERFLOW);
1395: gen_set_label(l1);
1.1.1.8 root 1396: gen_store_gpr(t0, rt);
1397: tcg_temp_free(t0);
1.1.1.7 root 1398: }
1.1.1.5 root 1399: opn = "daddi";
1400: break;
1401: case OPC_DADDIU:
1.1.1.8 root 1402: if (rs != 0) {
1403: tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1404: } else {
1405: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1406: }
1.1.1.5 root 1407: opn = "daddiu";
1408: break;
1409: #endif
1.1.1.8 root 1410: }
1.1.1.13 root 1411: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1412: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1413: }
1414:
1415: /* Logic with immediate operand */
1.1.1.16! root 1416: static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
1.1.1.8 root 1417: {
1418: target_ulong uimm;
1419: const char *opn = "imm logic";
1420:
1421: if (rt == 0) {
1422: /* If no destination, treat it as a NOP. */
1423: MIPS_DEBUG("NOP");
1424: return;
1425: }
1426: uimm = (uint16_t)imm;
1427: switch (opc) {
1.1 root 1428: case OPC_ANDI:
1.1.1.8 root 1429: if (likely(rs != 0))
1430: tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1431: else
1432: tcg_gen_movi_tl(cpu_gpr[rt], 0);
1.1 root 1433: opn = "andi";
1434: break;
1435: case OPC_ORI:
1.1.1.8 root 1436: if (rs != 0)
1437: tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1438: else
1439: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1.1 root 1440: opn = "ori";
1441: break;
1442: case OPC_XORI:
1.1.1.8 root 1443: if (likely(rs != 0))
1444: tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1445: else
1446: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1.1 root 1447: opn = "xori";
1448: break;
1449: case OPC_LUI:
1.1.1.8 root 1450: tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1.1 root 1451: opn = "lui";
1452: break;
1.1.1.8 root 1453: }
1.1.1.13 root 1454: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1455: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1456: }
1457:
1458: /* Set on less than with immediate operand */
1.1.1.16! root 1459: static void gen_slt_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
1.1.1.8 root 1460: {
1461: target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1462: const char *opn = "imm arith";
1463: TCGv t0;
1464:
1465: if (rt == 0) {
1466: /* If no destination, treat it as a NOP. */
1467: MIPS_DEBUG("NOP");
1468: return;
1469: }
1470: t0 = tcg_temp_new();
1471: gen_load_gpr(t0, rs);
1472: switch (opc) {
1473: case OPC_SLTI:
1.1.1.12 root 1474: tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1.1.1.8 root 1475: opn = "slti";
1476: break;
1477: case OPC_SLTIU:
1.1.1.12 root 1478: tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1.1.1.8 root 1479: opn = "sltiu";
1480: break;
1481: }
1.1.1.13 root 1482: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1483: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1484: tcg_temp_free(t0);
1485: }
1486:
1487: /* Shifts with immediate operand */
1.1.1.16! root 1488: static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1.1.1.8 root 1489: int rt, int rs, int16_t imm)
1490: {
1491: target_ulong uimm = ((uint16_t)imm) & 0x1f;
1492: const char *opn = "imm shift";
1493: TCGv t0;
1494:
1495: if (rt == 0) {
1496: /* If no destination, treat it as a NOP. */
1497: MIPS_DEBUG("NOP");
1498: return;
1499: }
1500:
1501: t0 = tcg_temp_new();
1502: gen_load_gpr(t0, rs);
1503: switch (opc) {
1.1 root 1504: case OPC_SLL:
1.1.1.7 root 1505: tcg_gen_shli_tl(t0, t0, uimm);
1.1.1.8 root 1506: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1.1 root 1507: opn = "sll";
1508: break;
1509: case OPC_SRA:
1.1.1.8 root 1510: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1.1 root 1511: opn = "sra";
1512: break;
1513: case OPC_SRL:
1.1.1.12 root 1514: if (uimm != 0) {
1515: tcg_gen_ext32u_tl(t0, t0);
1516: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1517: } else {
1518: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1519: }
1520: opn = "srl";
1521: break;
1522: case OPC_ROTR:
1523: if (uimm != 0) {
1524: TCGv_i32 t1 = tcg_temp_new_i32();
1.1.1.7 root 1525:
1.1.1.12 root 1526: tcg_gen_trunc_tl_i32(t1, t0);
1527: tcg_gen_rotri_i32(t1, t1, uimm);
1528: tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1529: tcg_temp_free_i32(t1);
1530: } else {
1531: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1.1.1.6 root 1532: }
1.1.1.12 root 1533: opn = "rotr";
1.1.1.5 root 1534: break;
1.1.1.6 root 1535: #if defined(TARGET_MIPS64)
1.1.1.5 root 1536: case OPC_DSLL:
1.1.1.8 root 1537: tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1.1.1.5 root 1538: opn = "dsll";
1539: break;
1540: case OPC_DSRA:
1.1.1.8 root 1541: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1.1.1.5 root 1542: opn = "dsra";
1543: break;
1544: case OPC_DSRL:
1.1.1.12 root 1545: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1546: opn = "dsrl";
1547: break;
1548: case OPC_DROTR:
1549: if (uimm != 0) {
1550: tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1551: } else {
1552: tcg_gen_mov_tl(cpu_gpr[rt], t0);
1.1.1.6 root 1553: }
1.1.1.12 root 1554: opn = "drotr";
1.1.1.5 root 1555: break;
1556: case OPC_DSLL32:
1.1.1.8 root 1557: tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1.1.1.5 root 1558: opn = "dsll32";
1559: break;
1560: case OPC_DSRA32:
1.1.1.8 root 1561: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1.1.1.5 root 1562: opn = "dsra32";
1563: break;
1564: case OPC_DSRL32:
1.1.1.12 root 1565: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1566: opn = "dsrl32";
1567: break;
1568: case OPC_DROTR32:
1569: tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1570: opn = "drotr32";
1.1 root 1571: break;
1.1.1.5 root 1572: #endif
1.1 root 1573: }
1.1.1.13 root 1574: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 1575: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1.1.1.7 root 1576: tcg_temp_free(t0);
1.1 root 1577: }
1578:
1579: /* Arithmetic */
1.1.1.16! root 1580: static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1.1 root 1581: int rd, int rs, int rt)
1582: {
1.1.1.6 root 1583: const char *opn = "arith";
1.1 root 1584:
1.1.1.5 root 1585: if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1586: && opc != OPC_DADD && opc != OPC_DSUB) {
1.1.1.6 root 1587: /* If no destination, treat it as a NOP.
1588: For add & sub, we must generate the overflow exception when needed. */
1.1 root 1589: MIPS_DEBUG("NOP");
1.1.1.8 root 1590: return;
1.1.1.6 root 1591: }
1.1.1.8 root 1592:
1.1 root 1593: switch (opc) {
1594: case OPC_ADD:
1.1.1.7 root 1595: {
1.1.1.8 root 1596: TCGv t0 = tcg_temp_local_new();
1597: TCGv t1 = tcg_temp_new();
1598: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1599: int l1 = gen_new_label();
1600:
1.1.1.8 root 1601: gen_load_gpr(t1, rs);
1602: gen_load_gpr(t2, rt);
1603: tcg_gen_add_tl(t0, t1, t2);
1604: tcg_gen_ext32s_tl(t0, t0);
1605: tcg_gen_xor_tl(t1, t1, t2);
1606: tcg_gen_xor_tl(t2, t0, t2);
1.1.1.12 root 1607: tcg_gen_andc_tl(t1, t2, t1);
1.1.1.8 root 1608: tcg_temp_free(t2);
1609: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1610: tcg_temp_free(t1);
1.1.1.7 root 1611: /* operands of same sign, result different sign */
1612: generate_exception(ctx, EXCP_OVERFLOW);
1613: gen_set_label(l1);
1.1.1.8 root 1614: gen_store_gpr(t0, rd);
1615: tcg_temp_free(t0);
1.1.1.7 root 1616: }
1.1 root 1617: opn = "add";
1618: break;
1619: case OPC_ADDU:
1.1.1.8 root 1620: if (rs != 0 && rt != 0) {
1621: tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1622: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1623: } else if (rs == 0 && rt != 0) {
1624: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1625: } else if (rs != 0 && rt == 0) {
1626: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1627: } else {
1628: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1629: }
1.1 root 1630: opn = "addu";
1631: break;
1632: case OPC_SUB:
1.1.1.7 root 1633: {
1.1.1.8 root 1634: TCGv t0 = tcg_temp_local_new();
1635: TCGv t1 = tcg_temp_new();
1636: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1637: int l1 = gen_new_label();
1638:
1.1.1.8 root 1639: gen_load_gpr(t1, rs);
1640: gen_load_gpr(t2, rt);
1641: tcg_gen_sub_tl(t0, t1, t2);
1642: tcg_gen_ext32s_tl(t0, t0);
1643: tcg_gen_xor_tl(t2, t1, t2);
1644: tcg_gen_xor_tl(t1, t0, t1);
1645: tcg_gen_and_tl(t1, t1, t2);
1646: tcg_temp_free(t2);
1647: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1648: tcg_temp_free(t1);
1.1.1.9 root 1649: /* operands of different sign, first operand and result different sign */
1.1.1.7 root 1650: generate_exception(ctx, EXCP_OVERFLOW);
1651: gen_set_label(l1);
1.1.1.8 root 1652: gen_store_gpr(t0, rd);
1653: tcg_temp_free(t0);
1.1.1.7 root 1654: }
1.1 root 1655: opn = "sub";
1656: break;
1657: case OPC_SUBU:
1.1.1.8 root 1658: if (rs != 0 && rt != 0) {
1659: tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1660: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1661: } else if (rs == 0 && rt != 0) {
1662: tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1663: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1664: } else if (rs != 0 && rt == 0) {
1665: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1666: } else {
1667: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1668: }
1.1 root 1669: opn = "subu";
1670: break;
1.1.1.6 root 1671: #if defined(TARGET_MIPS64)
1.1.1.5 root 1672: case OPC_DADD:
1.1.1.7 root 1673: {
1.1.1.8 root 1674: TCGv t0 = tcg_temp_local_new();
1675: TCGv t1 = tcg_temp_new();
1676: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1677: int l1 = gen_new_label();
1678:
1.1.1.8 root 1679: gen_load_gpr(t1, rs);
1680: gen_load_gpr(t2, rt);
1681: tcg_gen_add_tl(t0, t1, t2);
1682: tcg_gen_xor_tl(t1, t1, t2);
1683: tcg_gen_xor_tl(t2, t0, t2);
1.1.1.12 root 1684: tcg_gen_andc_tl(t1, t2, t1);
1.1.1.8 root 1685: tcg_temp_free(t2);
1686: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1687: tcg_temp_free(t1);
1.1.1.7 root 1688: /* operands of same sign, result different sign */
1689: generate_exception(ctx, EXCP_OVERFLOW);
1690: gen_set_label(l1);
1.1.1.8 root 1691: gen_store_gpr(t0, rd);
1692: tcg_temp_free(t0);
1.1.1.7 root 1693: }
1.1.1.5 root 1694: opn = "dadd";
1695: break;
1696: case OPC_DADDU:
1.1.1.8 root 1697: if (rs != 0 && rt != 0) {
1698: tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1699: } else if (rs == 0 && rt != 0) {
1700: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1701: } else if (rs != 0 && rt == 0) {
1702: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1703: } else {
1704: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1705: }
1.1.1.5 root 1706: opn = "daddu";
1707: break;
1708: case OPC_DSUB:
1.1.1.7 root 1709: {
1.1.1.8 root 1710: TCGv t0 = tcg_temp_local_new();
1711: TCGv t1 = tcg_temp_new();
1712: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1713: int l1 = gen_new_label();
1714:
1.1.1.8 root 1715: gen_load_gpr(t1, rs);
1716: gen_load_gpr(t2, rt);
1717: tcg_gen_sub_tl(t0, t1, t2);
1718: tcg_gen_xor_tl(t2, t1, t2);
1719: tcg_gen_xor_tl(t1, t0, t1);
1720: tcg_gen_and_tl(t1, t1, t2);
1721: tcg_temp_free(t2);
1722: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1723: tcg_temp_free(t1);
1.1.1.9 root 1724: /* operands of different sign, first operand and result different sign */
1.1.1.7 root 1725: generate_exception(ctx, EXCP_OVERFLOW);
1726: gen_set_label(l1);
1.1.1.8 root 1727: gen_store_gpr(t0, rd);
1728: tcg_temp_free(t0);
1.1.1.7 root 1729: }
1.1.1.5 root 1730: opn = "dsub";
1731: break;
1732: case OPC_DSUBU:
1.1.1.8 root 1733: if (rs != 0 && rt != 0) {
1734: tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1735: } else if (rs == 0 && rt != 0) {
1736: tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1737: } else if (rs != 0 && rt == 0) {
1738: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1739: } else {
1740: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1741: }
1.1.1.5 root 1742: opn = "dsubu";
1743: break;
1744: #endif
1.1.1.8 root 1745: case OPC_MUL:
1746: if (likely(rs != 0 && rt != 0)) {
1747: tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1748: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1749: } else {
1750: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1751: }
1752: opn = "mul";
1.1 root 1753: break;
1.1.1.8 root 1754: }
1.1.1.13 root 1755: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1756: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1757: }
1758:
1759: /* Conditional move */
1.1.1.16! root 1760: static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
1.1.1.8 root 1761: {
1762: const char *opn = "cond move";
1763: int l1;
1764:
1765: if (rd == 0) {
1766: /* If no destination, treat it as a NOP.
1767: For add & sub, we must generate the overflow exception when needed. */
1768: MIPS_DEBUG("NOP");
1769: return;
1770: }
1771:
1772: l1 = gen_new_label();
1773: switch (opc) {
1774: case OPC_MOVN:
1775: if (likely(rt != 0))
1776: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1777: else
1778: tcg_gen_br(l1);
1779: opn = "movn";
1.1 root 1780: break;
1.1.1.8 root 1781: case OPC_MOVZ:
1782: if (likely(rt != 0))
1783: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1784: opn = "movz";
1785: break;
1786: }
1787: if (rs != 0)
1788: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1789: else
1790: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1791: gen_set_label(l1);
1792:
1.1.1.13 root 1793: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1794: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1795: }
1796:
1797: /* Logic */
1.1.1.16! root 1798: static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
1.1.1.8 root 1799: {
1800: const char *opn = "logic";
1801:
1802: if (rd == 0) {
1803: /* If no destination, treat it as a NOP. */
1804: MIPS_DEBUG("NOP");
1805: return;
1806: }
1807:
1808: switch (opc) {
1.1 root 1809: case OPC_AND:
1.1.1.8 root 1810: if (likely(rs != 0 && rt != 0)) {
1811: tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1812: } else {
1813: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1814: }
1.1 root 1815: opn = "and";
1816: break;
1817: case OPC_NOR:
1.1.1.8 root 1818: if (rs != 0 && rt != 0) {
1819: tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1820: } else if (rs == 0 && rt != 0) {
1821: tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1822: } else if (rs != 0 && rt == 0) {
1823: tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1824: } else {
1825: tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1826: }
1.1 root 1827: opn = "nor";
1828: break;
1829: case OPC_OR:
1.1.1.8 root 1830: if (likely(rs != 0 && rt != 0)) {
1831: tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1832: } else if (rs == 0 && rt != 0) {
1833: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1834: } else if (rs != 0 && rt == 0) {
1835: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1836: } else {
1837: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1838: }
1.1 root 1839: opn = "or";
1840: break;
1841: case OPC_XOR:
1.1.1.8 root 1842: if (likely(rs != 0 && rt != 0)) {
1843: tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1844: } else if (rs == 0 && rt != 0) {
1845: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1846: } else if (rs != 0 && rt == 0) {
1847: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1848: } else {
1849: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1850: }
1.1 root 1851: opn = "xor";
1852: break;
1.1.1.8 root 1853: }
1.1.1.13 root 1854: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1855: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1856: }
1857:
1858: /* Set on lower than */
1.1.1.16! root 1859: static void gen_slt (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
1.1.1.8 root 1860: {
1861: const char *opn = "slt";
1862: TCGv t0, t1;
1863:
1864: if (rd == 0) {
1865: /* If no destination, treat it as a NOP. */
1866: MIPS_DEBUG("NOP");
1867: return;
1868: }
1869:
1870: t0 = tcg_temp_new();
1871: t1 = tcg_temp_new();
1872: gen_load_gpr(t0, rs);
1873: gen_load_gpr(t1, rt);
1874: switch (opc) {
1875: case OPC_SLT:
1.1.1.12 root 1876: tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
1.1.1.8 root 1877: opn = "slt";
1.1 root 1878: break;
1.1.1.8 root 1879: case OPC_SLTU:
1.1.1.12 root 1880: tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
1.1.1.8 root 1881: opn = "sltu";
1882: break;
1883: }
1.1.1.13 root 1884: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1885: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1886: tcg_temp_free(t0);
1887: tcg_temp_free(t1);
1888: }
1.1.1.7 root 1889:
1.1.1.8 root 1890: /* Shifts */
1.1.1.16! root 1891: static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1.1.1.8 root 1892: int rd, int rs, int rt)
1893: {
1894: const char *opn = "shifts";
1895: TCGv t0, t1;
1.1.1.7 root 1896:
1.1.1.8 root 1897: if (rd == 0) {
1898: /* If no destination, treat it as a NOP.
1899: For add & sub, we must generate the overflow exception when needed. */
1900: MIPS_DEBUG("NOP");
1901: return;
1902: }
1903:
1904: t0 = tcg_temp_new();
1905: t1 = tcg_temp_new();
1906: gen_load_gpr(t0, rs);
1907: gen_load_gpr(t1, rt);
1908: switch (opc) {
1.1 root 1909: case OPC_SLLV:
1.1.1.7 root 1910: tcg_gen_andi_tl(t0, t0, 0x1f);
1911: tcg_gen_shl_tl(t0, t1, t0);
1.1.1.8 root 1912: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1.1 root 1913: opn = "sllv";
1914: break;
1915: case OPC_SRAV:
1.1.1.7 root 1916: tcg_gen_andi_tl(t0, t0, 0x1f);
1.1.1.8 root 1917: tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1.1 root 1918: opn = "srav";
1919: break;
1920: case OPC_SRLV:
1.1.1.12 root 1921: tcg_gen_ext32u_tl(t1, t1);
1922: tcg_gen_andi_tl(t0, t0, 0x1f);
1923: tcg_gen_shr_tl(t0, t1, t0);
1924: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1925: opn = "srlv";
1926: break;
1927: case OPC_ROTRV:
1928: {
1929: TCGv_i32 t2 = tcg_temp_new_i32();
1930: TCGv_i32 t3 = tcg_temp_new_i32();
1931:
1932: tcg_gen_trunc_tl_i32(t2, t0);
1933: tcg_gen_trunc_tl_i32(t3, t1);
1934: tcg_gen_andi_i32(t2, t2, 0x1f);
1935: tcg_gen_rotr_i32(t2, t3, t2);
1936: tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1937: tcg_temp_free_i32(t2);
1938: tcg_temp_free_i32(t3);
1939: opn = "rotrv";
1.1.1.6 root 1940: }
1.1.1.5 root 1941: break;
1.1.1.6 root 1942: #if defined(TARGET_MIPS64)
1.1.1.5 root 1943: case OPC_DSLLV:
1.1.1.7 root 1944: tcg_gen_andi_tl(t0, t0, 0x3f);
1.1.1.8 root 1945: tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1.1.1.5 root 1946: opn = "dsllv";
1947: break;
1948: case OPC_DSRAV:
1.1.1.7 root 1949: tcg_gen_andi_tl(t0, t0, 0x3f);
1.1.1.8 root 1950: tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1.1.1.5 root 1951: opn = "dsrav";
1952: break;
1953: case OPC_DSRLV:
1.1.1.12 root 1954: tcg_gen_andi_tl(t0, t0, 0x3f);
1955: tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1956: opn = "dsrlv";
1957: break;
1958: case OPC_DROTRV:
1959: tcg_gen_andi_tl(t0, t0, 0x3f);
1960: tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1961: opn = "drotrv";
1.1 root 1962: break;
1.1.1.5 root 1963: #endif
1.1 root 1964: }
1.1.1.13 root 1965: (void)opn; /* avoid a compiler warning */
1.1 root 1966: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1.1.1.7 root 1967: tcg_temp_free(t0);
1968: tcg_temp_free(t1);
1.1 root 1969: }
1970:
1971: /* Arithmetic on HI/LO registers */
1.1.1.5 root 1972: static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1.1 root 1973: {
1.1.1.6 root 1974: const char *opn = "hilo";
1.1 root 1975:
1976: if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1.1.1.6 root 1977: /* Treat as NOP. */
1.1 root 1978: MIPS_DEBUG("NOP");
1.1.1.8 root 1979: return;
1.1 root 1980: }
1981: switch (opc) {
1982: case OPC_MFHI:
1.1.1.8 root 1983: tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1.1 root 1984: opn = "mfhi";
1985: break;
1986: case OPC_MFLO:
1.1.1.8 root 1987: tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1.1 root 1988: opn = "mflo";
1989: break;
1990: case OPC_MTHI:
1.1.1.8 root 1991: if (reg != 0)
1992: tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1993: else
1994: tcg_gen_movi_tl(cpu_HI[0], 0);
1.1 root 1995: opn = "mthi";
1996: break;
1997: case OPC_MTLO:
1.1.1.8 root 1998: if (reg != 0)
1999: tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2000: else
2001: tcg_gen_movi_tl(cpu_LO[0], 0);
1.1 root 2002: opn = "mtlo";
2003: break;
2004: }
1.1.1.13 root 2005: (void)opn; /* avoid a compiler warning */
1.1 root 2006: MIPS_DEBUG("%s %s", opn, regnames[reg]);
2007: }
2008:
1.1.1.5 root 2009: static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1.1 root 2010: int rs, int rt)
2011: {
1.1.1.6 root 2012: const char *opn = "mul/div";
1.1.1.8 root 2013: TCGv t0, t1;
2014:
2015: switch (opc) {
2016: case OPC_DIV:
2017: case OPC_DIVU:
2018: #if defined(TARGET_MIPS64)
2019: case OPC_DDIV:
2020: case OPC_DDIVU:
2021: #endif
2022: t0 = tcg_temp_local_new();
2023: t1 = tcg_temp_local_new();
2024: break;
2025: default:
2026: t0 = tcg_temp_new();
2027: t1 = tcg_temp_new();
2028: break;
2029: }
1.1 root 2030:
1.1.1.7 root 2031: gen_load_gpr(t0, rs);
2032: gen_load_gpr(t1, rt);
1.1 root 2033: switch (opc) {
2034: case OPC_DIV:
1.1.1.7 root 2035: {
2036: int l1 = gen_new_label();
1.1.1.8 root 2037: int l2 = gen_new_label();
1.1.1.7 root 2038:
1.1.1.8 root 2039: tcg_gen_ext32s_tl(t0, t0);
2040: tcg_gen_ext32s_tl(t1, t1);
1.1.1.7 root 2041: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2042: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2043: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2044:
2045: tcg_gen_mov_tl(cpu_LO[0], t0);
2046: tcg_gen_movi_tl(cpu_HI[0], 0);
2047: tcg_gen_br(l1);
2048: gen_set_label(l2);
2049: tcg_gen_div_tl(cpu_LO[0], t0, t1);
2050: tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2051: tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2052: tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1.1.1.7 root 2053: gen_set_label(l1);
2054: }
1.1 root 2055: opn = "div";
2056: break;
2057: case OPC_DIVU:
1.1.1.7 root 2058: {
2059: int l1 = gen_new_label();
2060:
1.1.1.8 root 2061: tcg_gen_ext32u_tl(t0, t0);
2062: tcg_gen_ext32u_tl(t1, t1);
1.1.1.7 root 2063: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2064: tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2065: tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2066: tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2067: tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1.1.1.7 root 2068: gen_set_label(l1);
2069: }
1.1 root 2070: opn = "divu";
2071: break;
2072: case OPC_MULT:
1.1.1.7 root 2073: {
1.1.1.8 root 2074: TCGv_i64 t2 = tcg_temp_new_i64();
2075: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2076:
1.1.1.8 root 2077: tcg_gen_ext_tl_i64(t2, t0);
2078: tcg_gen_ext_tl_i64(t3, t1);
2079: tcg_gen_mul_i64(t2, t2, t3);
2080: tcg_temp_free_i64(t3);
2081: tcg_gen_trunc_i64_tl(t0, t2);
2082: tcg_gen_shri_i64(t2, t2, 32);
2083: tcg_gen_trunc_i64_tl(t1, t2);
2084: tcg_temp_free_i64(t2);
1.1.1.7 root 2085: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2086: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2087: }
1.1 root 2088: opn = "mult";
2089: break;
2090: case OPC_MULTU:
1.1.1.7 root 2091: {
1.1.1.8 root 2092: TCGv_i64 t2 = tcg_temp_new_i64();
2093: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2094:
2095: tcg_gen_ext32u_tl(t0, t0);
2096: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2097: tcg_gen_extu_tl_i64(t2, t0);
2098: tcg_gen_extu_tl_i64(t3, t1);
2099: tcg_gen_mul_i64(t2, t2, t3);
2100: tcg_temp_free_i64(t3);
2101: tcg_gen_trunc_i64_tl(t0, t2);
2102: tcg_gen_shri_i64(t2, t2, 32);
2103: tcg_gen_trunc_i64_tl(t1, t2);
2104: tcg_temp_free_i64(t2);
1.1.1.7 root 2105: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2106: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2107: }
1.1 root 2108: opn = "multu";
2109: break;
1.1.1.6 root 2110: #if defined(TARGET_MIPS64)
1.1.1.5 root 2111: case OPC_DDIV:
1.1.1.7 root 2112: {
2113: int l1 = gen_new_label();
1.1.1.8 root 2114: int l2 = gen_new_label();
1.1.1.7 root 2115:
2116: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2117: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2118: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2119: tcg_gen_mov_tl(cpu_LO[0], t0);
2120: tcg_gen_movi_tl(cpu_HI[0], 0);
2121: tcg_gen_br(l1);
2122: gen_set_label(l2);
2123: tcg_gen_div_i64(cpu_LO[0], t0, t1);
2124: tcg_gen_rem_i64(cpu_HI[0], t0, t1);
1.1.1.7 root 2125: gen_set_label(l1);
2126: }
1.1.1.5 root 2127: opn = "ddiv";
2128: break;
2129: case OPC_DDIVU:
1.1.1.7 root 2130: {
2131: int l1 = gen_new_label();
2132:
2133: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2134: tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2135: tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2136: gen_set_label(l1);
2137: }
1.1.1.5 root 2138: opn = "ddivu";
2139: break;
2140: case OPC_DMULT:
1.1.1.7 root 2141: gen_helper_dmult(t0, t1);
1.1.1.5 root 2142: opn = "dmult";
2143: break;
2144: case OPC_DMULTU:
1.1.1.7 root 2145: gen_helper_dmultu(t0, t1);
1.1.1.5 root 2146: opn = "dmultu";
2147: break;
2148: #endif
1.1 root 2149: case OPC_MADD:
1.1.1.7 root 2150: {
1.1.1.8 root 2151: TCGv_i64 t2 = tcg_temp_new_i64();
2152: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2153:
1.1.1.8 root 2154: tcg_gen_ext_tl_i64(t2, t0);
2155: tcg_gen_ext_tl_i64(t3, t1);
2156: tcg_gen_mul_i64(t2, t2, t3);
2157: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2158: tcg_gen_add_i64(t2, t2, t3);
2159: tcg_temp_free_i64(t3);
2160: tcg_gen_trunc_i64_tl(t0, t2);
2161: tcg_gen_shri_i64(t2, t2, 32);
2162: tcg_gen_trunc_i64_tl(t1, t2);
2163: tcg_temp_free_i64(t2);
1.1.1.7 root 2164: tcg_gen_ext32s_tl(cpu_LO[0], t0);
1.1.1.8 root 2165: tcg_gen_ext32s_tl(cpu_HI[0], t1);
1.1.1.7 root 2166: }
1.1 root 2167: opn = "madd";
2168: break;
2169: case OPC_MADDU:
1.1.1.7 root 2170: {
1.1.1.8 root 2171: TCGv_i64 t2 = tcg_temp_new_i64();
2172: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2173:
2174: tcg_gen_ext32u_tl(t0, t0);
2175: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2176: tcg_gen_extu_tl_i64(t2, t0);
2177: tcg_gen_extu_tl_i64(t3, t1);
2178: tcg_gen_mul_i64(t2, t2, t3);
2179: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2180: tcg_gen_add_i64(t2, t2, t3);
2181: tcg_temp_free_i64(t3);
2182: tcg_gen_trunc_i64_tl(t0, t2);
2183: tcg_gen_shri_i64(t2, t2, 32);
2184: tcg_gen_trunc_i64_tl(t1, t2);
2185: tcg_temp_free_i64(t2);
1.1.1.7 root 2186: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2187: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2188: }
1.1 root 2189: opn = "maddu";
2190: break;
2191: case OPC_MSUB:
1.1.1.7 root 2192: {
1.1.1.8 root 2193: TCGv_i64 t2 = tcg_temp_new_i64();
2194: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2195:
1.1.1.8 root 2196: tcg_gen_ext_tl_i64(t2, t0);
2197: tcg_gen_ext_tl_i64(t3, t1);
2198: tcg_gen_mul_i64(t2, t2, t3);
2199: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2200: tcg_gen_sub_i64(t2, t3, t2);
2201: tcg_temp_free_i64(t3);
2202: tcg_gen_trunc_i64_tl(t0, t2);
2203: tcg_gen_shri_i64(t2, t2, 32);
2204: tcg_gen_trunc_i64_tl(t1, t2);
2205: tcg_temp_free_i64(t2);
1.1.1.7 root 2206: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2207: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2208: }
1.1 root 2209: opn = "msub";
2210: break;
2211: case OPC_MSUBU:
1.1.1.7 root 2212: {
1.1.1.8 root 2213: TCGv_i64 t2 = tcg_temp_new_i64();
2214: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2215:
2216: tcg_gen_ext32u_tl(t0, t0);
2217: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2218: tcg_gen_extu_tl_i64(t2, t0);
2219: tcg_gen_extu_tl_i64(t3, t1);
2220: tcg_gen_mul_i64(t2, t2, t3);
2221: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2222: tcg_gen_sub_i64(t2, t3, t2);
2223: tcg_temp_free_i64(t3);
2224: tcg_gen_trunc_i64_tl(t0, t2);
2225: tcg_gen_shri_i64(t2, t2, 32);
2226: tcg_gen_trunc_i64_tl(t1, t2);
2227: tcg_temp_free_i64(t2);
1.1.1.7 root 2228: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2229: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2230: }
1.1 root 2231: opn = "msubu";
2232: break;
2233: default:
1.1.1.6 root 2234: MIPS_INVAL(opn);
1.1 root 2235: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2236: goto out;
1.1 root 2237: }
1.1.1.13 root 2238: (void)opn; /* avoid a compiler warning */
1.1 root 2239: MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1.1.1.7 root 2240: out:
2241: tcg_temp_free(t0);
2242: tcg_temp_free(t1);
1.1 root 2243: }
2244:
1.1.1.6 root 2245: static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2246: int rd, int rs, int rt)
2247: {
2248: const char *opn = "mul vr54xx";
1.1.1.8 root 2249: TCGv t0 = tcg_temp_new();
2250: TCGv t1 = tcg_temp_new();
1.1.1.6 root 2251:
1.1.1.7 root 2252: gen_load_gpr(t0, rs);
2253: gen_load_gpr(t1, rt);
1.1.1.6 root 2254:
2255: switch (opc) {
2256: case OPC_VR54XX_MULS:
1.1.1.7 root 2257: gen_helper_muls(t0, t0, t1);
1.1.1.6 root 2258: opn = "muls";
1.1.1.7 root 2259: break;
1.1.1.6 root 2260: case OPC_VR54XX_MULSU:
1.1.1.7 root 2261: gen_helper_mulsu(t0, t0, t1);
1.1.1.6 root 2262: opn = "mulsu";
1.1.1.7 root 2263: break;
1.1.1.6 root 2264: case OPC_VR54XX_MACC:
1.1.1.7 root 2265: gen_helper_macc(t0, t0, t1);
1.1.1.6 root 2266: opn = "macc";
1.1.1.7 root 2267: break;
1.1.1.6 root 2268: case OPC_VR54XX_MACCU:
1.1.1.7 root 2269: gen_helper_maccu(t0, t0, t1);
1.1.1.6 root 2270: opn = "maccu";
1.1.1.7 root 2271: break;
1.1.1.6 root 2272: case OPC_VR54XX_MSAC:
1.1.1.7 root 2273: gen_helper_msac(t0, t0, t1);
1.1.1.6 root 2274: opn = "msac";
1.1.1.7 root 2275: break;
1.1.1.6 root 2276: case OPC_VR54XX_MSACU:
1.1.1.7 root 2277: gen_helper_msacu(t0, t0, t1);
1.1.1.6 root 2278: opn = "msacu";
1.1.1.7 root 2279: break;
1.1.1.6 root 2280: case OPC_VR54XX_MULHI:
1.1.1.7 root 2281: gen_helper_mulhi(t0, t0, t1);
1.1.1.6 root 2282: opn = "mulhi";
1.1.1.7 root 2283: break;
1.1.1.6 root 2284: case OPC_VR54XX_MULHIU:
1.1.1.7 root 2285: gen_helper_mulhiu(t0, t0, t1);
1.1.1.6 root 2286: opn = "mulhiu";
1.1.1.7 root 2287: break;
1.1.1.6 root 2288: case OPC_VR54XX_MULSHI:
1.1.1.7 root 2289: gen_helper_mulshi(t0, t0, t1);
1.1.1.6 root 2290: opn = "mulshi";
1.1.1.7 root 2291: break;
1.1.1.6 root 2292: case OPC_VR54XX_MULSHIU:
1.1.1.7 root 2293: gen_helper_mulshiu(t0, t0, t1);
1.1.1.6 root 2294: opn = "mulshiu";
1.1.1.7 root 2295: break;
1.1.1.6 root 2296: case OPC_VR54XX_MACCHI:
1.1.1.7 root 2297: gen_helper_macchi(t0, t0, t1);
1.1.1.6 root 2298: opn = "macchi";
1.1.1.7 root 2299: break;
1.1.1.6 root 2300: case OPC_VR54XX_MACCHIU:
1.1.1.7 root 2301: gen_helper_macchiu(t0, t0, t1);
1.1.1.6 root 2302: opn = "macchiu";
1.1.1.7 root 2303: break;
1.1.1.6 root 2304: case OPC_VR54XX_MSACHI:
1.1.1.7 root 2305: gen_helper_msachi(t0, t0, t1);
1.1.1.6 root 2306: opn = "msachi";
1.1.1.7 root 2307: break;
1.1.1.6 root 2308: case OPC_VR54XX_MSACHIU:
1.1.1.7 root 2309: gen_helper_msachiu(t0, t0, t1);
1.1.1.6 root 2310: opn = "msachiu";
1.1.1.7 root 2311: break;
1.1.1.6 root 2312: default:
2313: MIPS_INVAL("mul vr54xx");
2314: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2315: goto out;
1.1.1.6 root 2316: }
1.1.1.7 root 2317: gen_store_gpr(t0, rd);
1.1.1.13 root 2318: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 2319: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1.1.1.7 root 2320:
2321: out:
2322: tcg_temp_free(t0);
2323: tcg_temp_free(t1);
1.1.1.6 root 2324: }
2325:
1.1.1.5 root 2326: static void gen_cl (DisasContext *ctx, uint32_t opc,
1.1 root 2327: int rd, int rs)
2328: {
1.1.1.6 root 2329: const char *opn = "CLx";
1.1.1.8 root 2330: TCGv t0;
1.1.1.7 root 2331:
1.1 root 2332: if (rd == 0) {
1.1.1.6 root 2333: /* Treat as NOP. */
1.1 root 2334: MIPS_DEBUG("NOP");
1.1.1.8 root 2335: return;
1.1 root 2336: }
1.1.1.8 root 2337: t0 = tcg_temp_new();
1.1.1.7 root 2338: gen_load_gpr(t0, rs);
1.1 root 2339: switch (opc) {
2340: case OPC_CLO:
1.1.1.8 root 2341: gen_helper_clo(cpu_gpr[rd], t0);
1.1 root 2342: opn = "clo";
2343: break;
2344: case OPC_CLZ:
1.1.1.8 root 2345: gen_helper_clz(cpu_gpr[rd], t0);
1.1 root 2346: opn = "clz";
2347: break;
1.1.1.6 root 2348: #if defined(TARGET_MIPS64)
1.1.1.5 root 2349: case OPC_DCLO:
1.1.1.8 root 2350: gen_helper_dclo(cpu_gpr[rd], t0);
1.1.1.5 root 2351: opn = "dclo";
2352: break;
2353: case OPC_DCLZ:
1.1.1.8 root 2354: gen_helper_dclz(cpu_gpr[rd], t0);
1.1.1.5 root 2355: opn = "dclz";
2356: break;
2357: #endif
1.1 root 2358: }
1.1.1.13 root 2359: (void)opn; /* avoid a compiler warning */
1.1 root 2360: MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1.1.1.7 root 2361: tcg_temp_free(t0);
1.1 root 2362: }
2363:
1.1.1.12 root 2364: /* Godson integer instructions */
2365: static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
2366: int rd, int rs, int rt)
2367: {
2368: const char *opn = "loongson";
2369: TCGv t0, t1;
2370:
2371: if (rd == 0) {
2372: /* Treat as NOP. */
2373: MIPS_DEBUG("NOP");
2374: return;
2375: }
2376:
2377: switch (opc) {
2378: case OPC_MULT_G_2E:
2379: case OPC_MULT_G_2F:
2380: case OPC_MULTU_G_2E:
2381: case OPC_MULTU_G_2F:
2382: #if defined(TARGET_MIPS64)
2383: case OPC_DMULT_G_2E:
2384: case OPC_DMULT_G_2F:
2385: case OPC_DMULTU_G_2E:
2386: case OPC_DMULTU_G_2F:
2387: #endif
2388: t0 = tcg_temp_new();
2389: t1 = tcg_temp_new();
2390: break;
2391: default:
2392: t0 = tcg_temp_local_new();
2393: t1 = tcg_temp_local_new();
2394: break;
2395: }
2396:
2397: gen_load_gpr(t0, rs);
2398: gen_load_gpr(t1, rt);
2399:
2400: switch (opc) {
2401: case OPC_MULT_G_2E:
2402: case OPC_MULT_G_2F:
2403: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2404: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2405: opn = "mult.g";
2406: break;
2407: case OPC_MULTU_G_2E:
2408: case OPC_MULTU_G_2F:
2409: tcg_gen_ext32u_tl(t0, t0);
2410: tcg_gen_ext32u_tl(t1, t1);
2411: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2412: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2413: opn = "multu.g";
2414: break;
2415: case OPC_DIV_G_2E:
2416: case OPC_DIV_G_2F:
2417: {
2418: int l1 = gen_new_label();
2419: int l2 = gen_new_label();
2420: int l3 = gen_new_label();
2421: tcg_gen_ext32s_tl(t0, t0);
2422: tcg_gen_ext32s_tl(t1, t1);
2423: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2424: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2425: tcg_gen_br(l3);
2426: gen_set_label(l1);
2427: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2428: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2429: tcg_gen_mov_tl(cpu_gpr[rd], t0);
2430: tcg_gen_br(l3);
2431: gen_set_label(l2);
2432: tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2433: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2434: gen_set_label(l3);
2435: }
2436: opn = "div.g";
2437: break;
2438: case OPC_DIVU_G_2E:
2439: case OPC_DIVU_G_2F:
2440: {
2441: int l1 = gen_new_label();
2442: int l2 = gen_new_label();
2443: tcg_gen_ext32u_tl(t0, t0);
2444: tcg_gen_ext32u_tl(t1, t1);
2445: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2446: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2447: tcg_gen_br(l2);
2448: gen_set_label(l1);
2449: tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2450: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2451: gen_set_label(l2);
2452: }
2453: opn = "divu.g";
2454: break;
2455: case OPC_MOD_G_2E:
2456: case OPC_MOD_G_2F:
2457: {
2458: int l1 = gen_new_label();
2459: int l2 = gen_new_label();
2460: int l3 = gen_new_label();
2461: tcg_gen_ext32u_tl(t0, t0);
2462: tcg_gen_ext32u_tl(t1, t1);
2463: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2464: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2465: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2466: gen_set_label(l1);
2467: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2468: tcg_gen_br(l3);
2469: gen_set_label(l2);
2470: tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2471: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2472: gen_set_label(l3);
2473: }
2474: opn = "mod.g";
2475: break;
2476: case OPC_MODU_G_2E:
2477: case OPC_MODU_G_2F:
2478: {
2479: int l1 = gen_new_label();
2480: int l2 = gen_new_label();
2481: tcg_gen_ext32u_tl(t0, t0);
2482: tcg_gen_ext32u_tl(t1, t1);
2483: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2484: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2485: tcg_gen_br(l2);
2486: gen_set_label(l1);
2487: tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2488: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2489: gen_set_label(l2);
2490: }
2491: opn = "modu.g";
2492: break;
2493: #if defined(TARGET_MIPS64)
2494: case OPC_DMULT_G_2E:
2495: case OPC_DMULT_G_2F:
2496: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2497: opn = "dmult.g";
2498: break;
2499: case OPC_DMULTU_G_2E:
2500: case OPC_DMULTU_G_2F:
2501: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2502: opn = "dmultu.g";
2503: break;
2504: case OPC_DDIV_G_2E:
2505: case OPC_DDIV_G_2F:
2506: {
2507: int l1 = gen_new_label();
2508: int l2 = gen_new_label();
2509: int l3 = gen_new_label();
2510: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2511: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2512: tcg_gen_br(l3);
2513: gen_set_label(l1);
2514: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2515: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2516: tcg_gen_mov_tl(cpu_gpr[rd], t0);
2517: tcg_gen_br(l3);
2518: gen_set_label(l2);
2519: tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2520: gen_set_label(l3);
2521: }
2522: opn = "ddiv.g";
2523: break;
2524: case OPC_DDIVU_G_2E:
2525: case OPC_DDIVU_G_2F:
2526: {
2527: int l1 = gen_new_label();
2528: int l2 = gen_new_label();
2529: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2530: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2531: tcg_gen_br(l2);
2532: gen_set_label(l1);
2533: tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2534: gen_set_label(l2);
2535: }
2536: opn = "ddivu.g";
2537: break;
2538: case OPC_DMOD_G_2E:
2539: case OPC_DMOD_G_2F:
2540: {
2541: int l1 = gen_new_label();
2542: int l2 = gen_new_label();
2543: int l3 = gen_new_label();
2544: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2545: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2546: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2547: gen_set_label(l1);
2548: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2549: tcg_gen_br(l3);
2550: gen_set_label(l2);
2551: tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2552: gen_set_label(l3);
2553: }
2554: opn = "dmod.g";
2555: break;
2556: case OPC_DMODU_G_2E:
2557: case OPC_DMODU_G_2F:
2558: {
2559: int l1 = gen_new_label();
2560: int l2 = gen_new_label();
2561: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2562: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2563: tcg_gen_br(l2);
2564: gen_set_label(l1);
2565: tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2566: gen_set_label(l2);
2567: }
2568: opn = "dmodu.g";
2569: break;
2570: #endif
2571: }
2572:
1.1.1.13 root 2573: (void)opn; /* avoid a compiler warning */
1.1.1.12 root 2574: MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2575: tcg_temp_free(t0);
2576: tcg_temp_free(t1);
2577: }
2578:
2579: /* Traps */
1.1.1.5 root 2580: static void gen_trap (DisasContext *ctx, uint32_t opc,
1.1 root 2581: int rs, int rt, int16_t imm)
2582: {
2583: int cond;
1.1.1.8 root 2584: TCGv t0 = tcg_temp_new();
2585: TCGv t1 = tcg_temp_new();
1.1 root 2586:
2587: cond = 0;
2588: /* Load needed operands */
2589: switch (opc) {
2590: case OPC_TEQ:
2591: case OPC_TGE:
2592: case OPC_TGEU:
2593: case OPC_TLT:
2594: case OPC_TLTU:
2595: case OPC_TNE:
2596: /* Compare two registers */
2597: if (rs != rt) {
1.1.1.7 root 2598: gen_load_gpr(t0, rs);
2599: gen_load_gpr(t1, rt);
1.1 root 2600: cond = 1;
2601: }
1.1.1.5 root 2602: break;
1.1 root 2603: case OPC_TEQI:
2604: case OPC_TGEI:
2605: case OPC_TGEIU:
2606: case OPC_TLTI:
2607: case OPC_TLTIU:
2608: case OPC_TNEI:
2609: /* Compare register to immediate */
2610: if (rs != 0 || imm != 0) {
1.1.1.7 root 2611: gen_load_gpr(t0, rs);
2612: tcg_gen_movi_tl(t1, (int32_t)imm);
1.1 root 2613: cond = 1;
2614: }
2615: break;
2616: }
2617: if (cond == 0) {
2618: switch (opc) {
2619: case OPC_TEQ: /* rs == rs */
2620: case OPC_TEQI: /* r0 == 0 */
2621: case OPC_TGE: /* rs >= rs */
2622: case OPC_TGEI: /* r0 >= 0 */
2623: case OPC_TGEU: /* rs >= rs unsigned */
2624: case OPC_TGEIU: /* r0 >= 0 unsigned */
2625: /* Always trap */
1.1.1.8 root 2626: generate_exception(ctx, EXCP_TRAP);
1.1 root 2627: break;
2628: case OPC_TLT: /* rs < rs */
2629: case OPC_TLTI: /* r0 < 0 */
2630: case OPC_TLTU: /* rs < rs unsigned */
2631: case OPC_TLTIU: /* r0 < 0 unsigned */
2632: case OPC_TNE: /* rs != rs */
2633: case OPC_TNEI: /* r0 != 0 */
1.1.1.6 root 2634: /* Never trap: treat as NOP. */
1.1.1.8 root 2635: break;
1.1 root 2636: }
2637: } else {
1.1.1.8 root 2638: int l1 = gen_new_label();
2639:
1.1 root 2640: switch (opc) {
2641: case OPC_TEQ:
2642: case OPC_TEQI:
1.1.1.8 root 2643: tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
1.1 root 2644: break;
2645: case OPC_TGE:
2646: case OPC_TGEI:
1.1.1.8 root 2647: tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
1.1 root 2648: break;
2649: case OPC_TGEU:
2650: case OPC_TGEIU:
1.1.1.8 root 2651: tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
1.1 root 2652: break;
2653: case OPC_TLT:
2654: case OPC_TLTI:
1.1.1.8 root 2655: tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
1.1 root 2656: break;
2657: case OPC_TLTU:
2658: case OPC_TLTIU:
1.1.1.8 root 2659: tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
1.1 root 2660: break;
2661: case OPC_TNE:
2662: case OPC_TNEI:
1.1.1.8 root 2663: tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
1.1 root 2664: break;
2665: }
1.1.1.8 root 2666: generate_exception(ctx, EXCP_TRAP);
1.1.1.7 root 2667: gen_set_label(l1);
2668: }
2669: tcg_temp_free(t0);
2670: tcg_temp_free(t1);
1.1 root 2671: }
2672:
1.1.1.7 root 2673: static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1.1.1.2 root 2674: {
2675: TranslationBlock *tb;
2676: tb = ctx->tb;
1.1.1.9 root 2677: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2678: likely(!ctx->singlestep_enabled)) {
1.1.1.7 root 2679: tcg_gen_goto_tb(n);
1.1.1.6 root 2680: gen_save_pc(dest);
1.1.1.14 root 2681: tcg_gen_exit_tb((tcg_target_long)tb + n);
1.1.1.2 root 2682: } else {
1.1.1.6 root 2683: gen_save_pc(dest);
1.1.1.9 root 2684: if (ctx->singlestep_enabled) {
2685: save_cpu_state(ctx, 0);
2686: gen_helper_0i(raise_exception, EXCP_DEBUG);
2687: }
1.1.1.7 root 2688: tcg_gen_exit_tb(0);
1.1.1.2 root 2689: }
2690: }
2691:
1.1 root 2692: /* Branches (before delay slot) */
1.1.1.5 root 2693: static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1.1.1.12 root 2694: int insn_bytes,
1.1 root 2695: int rs, int rt, int32_t offset)
2696: {
1.1.1.7 root 2697: target_ulong btgt = -1;
1.1.1.6 root 2698: int blink = 0;
1.1.1.7 root 2699: int bcond_compute = 0;
1.1.1.8 root 2700: TCGv t0 = tcg_temp_new();
2701: TCGv t1 = tcg_temp_new();
1.1 root 2702:
1.1.1.6 root 2703: if (ctx->hflags & MIPS_HFLAG_BMASK) {
2704: #ifdef MIPS_DEBUG_DISAS
1.1.1.7 root 2705: LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
1.1.1.6 root 2706: #endif
2707: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2708: goto out;
1.1.1.6 root 2709: }
2710:
2711: /* Load needed operands */
2712: switch (opc) {
2713: case OPC_BEQ:
2714: case OPC_BEQL:
2715: case OPC_BNE:
2716: case OPC_BNEL:
1.1 root 2717: /* Compare two registers */
2718: if (rs != rt) {
1.1.1.7 root 2719: gen_load_gpr(t0, rs);
2720: gen_load_gpr(t1, rt);
2721: bcond_compute = 1;
1.1 root 2722: }
1.1.1.12 root 2723: btgt = ctx->pc + insn_bytes + offset;
1.1 root 2724: break;
2725: case OPC_BGEZ:
2726: case OPC_BGEZAL:
1.1.1.12 root 2727: case OPC_BGEZALS:
1.1 root 2728: case OPC_BGEZALL:
2729: case OPC_BGEZL:
2730: case OPC_BGTZ:
2731: case OPC_BGTZL:
2732: case OPC_BLEZ:
2733: case OPC_BLEZL:
2734: case OPC_BLTZ:
2735: case OPC_BLTZAL:
1.1.1.12 root 2736: case OPC_BLTZALS:
1.1 root 2737: case OPC_BLTZALL:
2738: case OPC_BLTZL:
2739: /* Compare to zero */
2740: if (rs != 0) {
1.1.1.7 root 2741: gen_load_gpr(t0, rs);
2742: bcond_compute = 1;
1.1 root 2743: }
1.1.1.12 root 2744: btgt = ctx->pc + insn_bytes + offset;
1.1 root 2745: break;
2746: case OPC_J:
2747: case OPC_JAL:
1.1.1.12 root 2748: case OPC_JALX:
2749: case OPC_JALS:
2750: case OPC_JALXS:
1.1 root 2751: /* Jump to immediate */
1.1.1.12 root 2752: btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
1.1 root 2753: break;
2754: case OPC_JR:
2755: case OPC_JALR:
1.1.1.12 root 2756: case OPC_JALRC:
2757: case OPC_JALRS:
1.1 root 2758: /* Jump to register */
1.1.1.5 root 2759: if (offset != 0 && offset != 16) {
2760: /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1.1.1.6 root 2761: others are reserved. */
2762: MIPS_INVAL("jump hint");
1.1 root 2763: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2764: goto out;
1.1 root 2765: }
1.1.1.7 root 2766: gen_load_gpr(btarget, rs);
1.1 root 2767: break;
2768: default:
2769: MIPS_INVAL("branch/jump");
2770: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2771: goto out;
1.1 root 2772: }
1.1.1.7 root 2773: if (bcond_compute == 0) {
1.1 root 2774: /* No condition to be computed */
2775: switch (opc) {
2776: case OPC_BEQ: /* rx == rx */
2777: case OPC_BEQL: /* rx == rx likely */
2778: case OPC_BGEZ: /* 0 >= 0 */
2779: case OPC_BGEZL: /* 0 >= 0 likely */
2780: case OPC_BLEZ: /* 0 <= 0 */
2781: case OPC_BLEZL: /* 0 <= 0 likely */
2782: /* Always take */
1.1.1.2 root 2783: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 2784: MIPS_DEBUG("balways");
2785: break;
1.1.1.12 root 2786: case OPC_BGEZALS:
1.1 root 2787: case OPC_BGEZAL: /* 0 >= 0 */
2788: case OPC_BGEZALL: /* 0 >= 0 likely */
1.1.1.12 root 2789: ctx->hflags |= (opc == OPC_BGEZALS
2790: ? MIPS_HFLAG_BDS16
2791: : MIPS_HFLAG_BDS32);
1.1 root 2792: /* Always take and link */
2793: blink = 31;
1.1.1.2 root 2794: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 2795: MIPS_DEBUG("balways and link");
2796: break;
2797: case OPC_BNE: /* rx != rx */
2798: case OPC_BGTZ: /* 0 > 0 */
2799: case OPC_BLTZ: /* 0 < 0 */
1.1.1.6 root 2800: /* Treat as NOP. */
1.1 root 2801: MIPS_DEBUG("bnever (NOP)");
1.1.1.7 root 2802: goto out;
1.1.1.12 root 2803: case OPC_BLTZALS:
1.1.1.2 root 2804: case OPC_BLTZAL: /* 0 < 0 */
1.1.1.12 root 2805: ctx->hflags |= (opc == OPC_BLTZALS
2806: ? MIPS_HFLAG_BDS16
2807: : MIPS_HFLAG_BDS32);
2808: /* Handle as an unconditional branch to get correct delay
2809: slot checking. */
2810: blink = 31;
2811: btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
2812: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.6 root 2813: MIPS_DEBUG("bnever and link");
1.1.1.12 root 2814: break;
1.1.1.2 root 2815: case OPC_BLTZALL: /* 0 < 0 likely */
1.1.1.8 root 2816: tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
1.1.1.6 root 2817: /* Skip the instruction in the delay slot */
2818: MIPS_DEBUG("bnever, link and skip");
2819: ctx->pc += 4;
1.1.1.7 root 2820: goto out;
1.1 root 2821: case OPC_BNEL: /* rx != rx likely */
2822: case OPC_BGTZL: /* 0 > 0 likely */
2823: case OPC_BLTZL: /* 0 < 0 likely */
2824: /* Skip the instruction in the delay slot */
2825: MIPS_DEBUG("bnever and skip");
1.1.1.6 root 2826: ctx->pc += 4;
1.1.1.7 root 2827: goto out;
1.1 root 2828: case OPC_J:
1.1.1.2 root 2829: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.7 root 2830: MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
1.1 root 2831: break;
1.1.1.12 root 2832: case OPC_JALXS:
2833: case OPC_JALX:
2834: ctx->hflags |= MIPS_HFLAG_BX;
2835: /* Fallthrough */
2836: case OPC_JALS:
1.1 root 2837: case OPC_JAL:
2838: blink = 31;
1.1.1.2 root 2839: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.12 root 2840: ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
2841: ? MIPS_HFLAG_BDS16
2842: : MIPS_HFLAG_BDS32);
1.1.1.7 root 2843: MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
1.1 root 2844: break;
2845: case OPC_JR:
1.1.1.2 root 2846: ctx->hflags |= MIPS_HFLAG_BR;
1.1.1.12 root 2847: if (insn_bytes == 4)
2848: ctx->hflags |= MIPS_HFLAG_BDS32;
1.1 root 2849: MIPS_DEBUG("jr %s", regnames[rs]);
2850: break;
1.1.1.12 root 2851: case OPC_JALRS:
1.1 root 2852: case OPC_JALR:
1.1.1.12 root 2853: case OPC_JALRC:
1.1 root 2854: blink = rt;
1.1.1.2 root 2855: ctx->hflags |= MIPS_HFLAG_BR;
1.1.1.12 root 2856: ctx->hflags |= (opc == OPC_JALRS
2857: ? MIPS_HFLAG_BDS16
2858: : MIPS_HFLAG_BDS32);
1.1 root 2859: MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2860: break;
2861: default:
2862: MIPS_INVAL("branch/jump");
2863: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2864: goto out;
1.1 root 2865: }
2866: } else {
2867: switch (opc) {
2868: case OPC_BEQ:
1.1.1.12 root 2869: tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
1.1.1.6 root 2870: MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2871: regnames[rs], regnames[rt], btgt);
1.1 root 2872: goto not_likely;
2873: case OPC_BEQL:
1.1.1.12 root 2874: tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
1.1.1.6 root 2875: MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2876: regnames[rs], regnames[rt], btgt);
1.1 root 2877: goto likely;
2878: case OPC_BNE:
1.1.1.12 root 2879: tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
1.1.1.6 root 2880: MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2881: regnames[rs], regnames[rt], btgt);
1.1 root 2882: goto not_likely;
2883: case OPC_BNEL:
1.1.1.12 root 2884: tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
1.1.1.6 root 2885: MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2886: regnames[rs], regnames[rt], btgt);
1.1 root 2887: goto likely;
2888: case OPC_BGEZ:
1.1.1.12 root 2889: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2890: MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2891: goto not_likely;
2892: case OPC_BGEZL:
1.1.1.12 root 2893: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2894: MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2895: goto likely;
1.1.1.12 root 2896: case OPC_BGEZALS:
1.1 root 2897: case OPC_BGEZAL:
1.1.1.12 root 2898: ctx->hflags |= (opc == OPC_BGEZALS
2899: ? MIPS_HFLAG_BDS16
2900: : MIPS_HFLAG_BDS32);
2901: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2902: MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2903: blink = 31;
2904: goto not_likely;
2905: case OPC_BGEZALL:
1.1.1.12 root 2906: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1 root 2907: blink = 31;
1.1.1.7 root 2908: MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2909: goto likely;
2910: case OPC_BGTZ:
1.1.1.12 root 2911: tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
1.1.1.7 root 2912: MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2913: goto not_likely;
2914: case OPC_BGTZL:
1.1.1.12 root 2915: tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
1.1.1.7 root 2916: MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2917: goto likely;
2918: case OPC_BLEZ:
1.1.1.12 root 2919: tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
1.1.1.7 root 2920: MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2921: goto not_likely;
2922: case OPC_BLEZL:
1.1.1.12 root 2923: tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
1.1.1.7 root 2924: MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2925: goto likely;
2926: case OPC_BLTZ:
1.1.1.12 root 2927: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1.1.7 root 2928: MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2929: goto not_likely;
2930: case OPC_BLTZL:
1.1.1.12 root 2931: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1.1.7 root 2932: MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2933: goto likely;
1.1.1.12 root 2934: case OPC_BLTZALS:
1.1 root 2935: case OPC_BLTZAL:
1.1.1.12 root 2936: ctx->hflags |= (opc == OPC_BLTZALS
2937: ? MIPS_HFLAG_BDS16
2938: : MIPS_HFLAG_BDS32);
2939: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1 root 2940: blink = 31;
1.1.1.7 root 2941: MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2942: not_likely:
1.1.1.2 root 2943: ctx->hflags |= MIPS_HFLAG_BC;
1.1 root 2944: break;
2945: case OPC_BLTZALL:
1.1.1.12 root 2946: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1 root 2947: blink = 31;
1.1.1.7 root 2948: MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2949: likely:
1.1.1.2 root 2950: ctx->hflags |= MIPS_HFLAG_BL;
1.1 root 2951: break;
1.1.1.6 root 2952: default:
2953: MIPS_INVAL("conditional branch/jump");
2954: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2955: goto out;
1.1 root 2956: }
2957: }
1.1.1.6 root 2958: MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
1.1.1.7 root 2959: blink, ctx->hflags, btgt);
1.1.1.6 root 2960:
1.1.1.7 root 2961: ctx->btarget = btgt;
1.1 root 2962: if (blink > 0) {
1.1.1.12 root 2963: int post_delay = insn_bytes;
2964: int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2965:
2966: if (opc != OPC_JALRC)
2967: post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2968:
2969: tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
1.1 root 2970: }
1.1.1.7 root 2971:
2972: out:
1.1.1.12 root 2973: if (insn_bytes == 2)
2974: ctx->hflags |= MIPS_HFLAG_B16;
1.1.1.7 root 2975: tcg_temp_free(t0);
2976: tcg_temp_free(t1);
1.1 root 2977: }
2978:
1.1.1.5 root 2979: /* special3 bitfield operations */
2980: static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1.1.1.7 root 2981: int rs, int lsb, int msb)
1.1 root 2982: {
1.1.1.7 root 2983: TCGv t0 = tcg_temp_new();
2984: TCGv t1 = tcg_temp_new();
2985: target_ulong mask;
2986:
2987: gen_load_gpr(t1, rs);
1.1.1.5 root 2988: switch (opc) {
2989: case OPC_EXT:
2990: if (lsb + msb > 31)
2991: goto fail;
1.1.1.7 root 2992: tcg_gen_shri_tl(t0, t1, lsb);
2993: if (msb != 31) {
2994: tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2995: } else {
2996: tcg_gen_ext32s_tl(t0, t0);
2997: }
1.1.1.5 root 2998: break;
1.1.1.6 root 2999: #if defined(TARGET_MIPS64)
1.1.1.5 root 3000: case OPC_DEXTM:
1.1.1.7 root 3001: tcg_gen_shri_tl(t0, t1, lsb);
3002: if (msb != 31) {
3003: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3004: }
1.1.1.5 root 3005: break;
3006: case OPC_DEXTU:
1.1.1.7 root 3007: tcg_gen_shri_tl(t0, t1, lsb + 32);
3008: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
1.1.1.5 root 3009: break;
3010: case OPC_DEXT:
1.1.1.7 root 3011: tcg_gen_shri_tl(t0, t1, lsb);
3012: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
1.1.1.5 root 3013: break;
1.1.1.6 root 3014: #endif
1.1.1.5 root 3015: case OPC_INS:
3016: if (lsb > msb)
3017: goto fail;
1.1.1.7 root 3018: mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
3019: gen_load_gpr(t0, rt);
3020: tcg_gen_andi_tl(t0, t0, ~mask);
3021: tcg_gen_shli_tl(t1, t1, lsb);
3022: tcg_gen_andi_tl(t1, t1, mask);
3023: tcg_gen_or_tl(t0, t0, t1);
3024: tcg_gen_ext32s_tl(t0, t0);
1.1.1.5 root 3025: break;
1.1.1.6 root 3026: #if defined(TARGET_MIPS64)
1.1.1.5 root 3027: case OPC_DINSM:
3028: if (lsb > msb)
3029: goto fail;
1.1.1.7 root 3030: mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
3031: gen_load_gpr(t0, rt);
3032: tcg_gen_andi_tl(t0, t0, ~mask);
3033: tcg_gen_shli_tl(t1, t1, lsb);
3034: tcg_gen_andi_tl(t1, t1, mask);
3035: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3036: break;
3037: case OPC_DINSU:
3038: if (lsb > msb)
3039: goto fail;
1.1.1.11 root 3040: mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
1.1.1.7 root 3041: gen_load_gpr(t0, rt);
3042: tcg_gen_andi_tl(t0, t0, ~mask);
3043: tcg_gen_shli_tl(t1, t1, lsb + 32);
3044: tcg_gen_andi_tl(t1, t1, mask);
3045: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3046: break;
3047: case OPC_DINS:
3048: if (lsb > msb)
3049: goto fail;
1.1.1.7 root 3050: gen_load_gpr(t0, rt);
3051: mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3052: gen_load_gpr(t0, rt);
3053: tcg_gen_andi_tl(t0, t0, ~mask);
3054: tcg_gen_shli_tl(t1, t1, lsb);
3055: tcg_gen_andi_tl(t1, t1, mask);
3056: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3057: break;
1.1.1.6 root 3058: #endif
1.1.1.5 root 3059: default:
3060: fail:
3061: MIPS_INVAL("bitops");
3062: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 3063: tcg_temp_free(t0);
3064: tcg_temp_free(t1);
1.1 root 3065: return;
3066: }
1.1.1.7 root 3067: gen_store_gpr(t0, rt);
3068: tcg_temp_free(t0);
3069: tcg_temp_free(t1);
3070: }
3071:
3072: static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3073: {
1.1.1.8 root 3074: TCGv t0;
1.1.1.7 root 3075:
1.1.1.8 root 3076: if (rd == 0) {
3077: /* If no destination, treat it as a NOP. */
3078: MIPS_DEBUG("NOP");
3079: return;
3080: }
3081:
3082: t0 = tcg_temp_new();
3083: gen_load_gpr(t0, rt);
1.1.1.7 root 3084: switch (op2) {
3085: case OPC_WSBH:
1.1.1.8 root 3086: {
3087: TCGv t1 = tcg_temp_new();
3088:
3089: tcg_gen_shri_tl(t1, t0, 8);
3090: tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3091: tcg_gen_shli_tl(t0, t0, 8);
3092: tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3093: tcg_gen_or_tl(t0, t0, t1);
3094: tcg_temp_free(t1);
3095: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3096: }
1.1.1.7 root 3097: break;
3098: case OPC_SEB:
1.1.1.8 root 3099: tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
1.1.1.7 root 3100: break;
3101: case OPC_SEH:
1.1.1.8 root 3102: tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
1.1.1.7 root 3103: break;
3104: #if defined(TARGET_MIPS64)
3105: case OPC_DSBH:
1.1.1.8 root 3106: {
3107: TCGv t1 = tcg_temp_new();
3108:
3109: tcg_gen_shri_tl(t1, t0, 8);
3110: tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3111: tcg_gen_shli_tl(t0, t0, 8);
3112: tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3113: tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3114: tcg_temp_free(t1);
3115: }
1.1.1.7 root 3116: break;
3117: case OPC_DSHD:
1.1.1.8 root 3118: {
3119: TCGv t1 = tcg_temp_new();
3120:
3121: tcg_gen_shri_tl(t1, t0, 16);
3122: tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3123: tcg_gen_shli_tl(t0, t0, 16);
3124: tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3125: tcg_gen_or_tl(t0, t0, t1);
3126: tcg_gen_shri_tl(t1, t0, 32);
3127: tcg_gen_shli_tl(t0, t0, 32);
3128: tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3129: tcg_temp_free(t1);
3130: }
1.1.1.7 root 3131: break;
3132: #endif
3133: default:
3134: MIPS_INVAL("bsfhl");
3135: generate_exception(ctx, EXCP_RI);
3136: tcg_temp_free(t0);
3137: return;
3138: }
3139: tcg_temp_free(t0);
1.1.1.5 root 3140: }
1.1.1.4 root 3141:
1.1.1.7 root 3142: #ifndef CONFIG_USER_ONLY
1.1.1.5 root 3143: /* CP0 (MMU and control) */
1.1.1.8 root 3144: static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
1.1.1.7 root 3145: {
1.1.1.8 root 3146: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 3147:
1.1.1.8 root 3148: tcg_gen_ld_i32(t0, cpu_env, off);
3149: tcg_gen_ext_i32_tl(arg, t0);
3150: tcg_temp_free_i32(t0);
1.1.1.7 root 3151: }
3152:
1.1.1.8 root 3153: static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
1.1.1.7 root 3154: {
1.1.1.8 root 3155: tcg_gen_ld_tl(arg, cpu_env, off);
3156: tcg_gen_ext32s_tl(arg, arg);
1.1.1.7 root 3157: }
3158:
1.1.1.8 root 3159: static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
1.1.1.7 root 3160: {
1.1.1.8 root 3161: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 3162:
1.1.1.8 root 3163: tcg_gen_trunc_tl_i32(t0, arg);
3164: tcg_gen_st_i32(t0, cpu_env, off);
3165: tcg_temp_free_i32(t0);
1.1.1.7 root 3166: }
3167:
1.1.1.8 root 3168: static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
1.1.1.7 root 3169: {
1.1.1.8 root 3170: tcg_gen_ext32s_tl(arg, arg);
3171: tcg_gen_st_tl(arg, cpu_env, off);
1.1.1.7 root 3172: }
3173:
1.1.1.16! root 3174: static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 3175: {
3176: const char *rn = "invalid";
3177:
1.1.1.6 root 3178: if (sel != 0)
3179: check_insn(env, ctx, ISA_MIPS32);
3180:
1.1.1.5 root 3181: switch (reg) {
3182: case 0:
3183: switch (sel) {
3184: case 0:
1.1.1.16! root 3185: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
1.1.1.5 root 3186: rn = "Index";
3187: break;
3188: case 1:
1.1.1.6 root 3189: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3190: gen_helper_mfc0_mvpcontrol(arg);
1.1.1.5 root 3191: rn = "MVPControl";
1.1.1.6 root 3192: break;
1.1.1.5 root 3193: case 2:
1.1.1.6 root 3194: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3195: gen_helper_mfc0_mvpconf0(arg);
1.1.1.5 root 3196: rn = "MVPConf0";
1.1.1.6 root 3197: break;
1.1.1.5 root 3198: case 3:
1.1.1.6 root 3199: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3200: gen_helper_mfc0_mvpconf1(arg);
1.1.1.5 root 3201: rn = "MVPConf1";
1.1.1.6 root 3202: break;
1.1.1.5 root 3203: default:
3204: goto die;
1.1 root 3205: }
3206: break;
1.1.1.5 root 3207: case 1:
3208: switch (sel) {
3209: case 0:
1.1.1.8 root 3210: gen_helper_mfc0_random(arg);
1.1.1.5 root 3211: rn = "Random";
1.1.1.6 root 3212: break;
1.1.1.5 root 3213: case 1:
1.1.1.6 root 3214: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 3215: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
1.1.1.5 root 3216: rn = "VPEControl";
1.1.1.6 root 3217: break;
1.1.1.5 root 3218: case 2:
1.1.1.6 root 3219: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 3220: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
1.1.1.5 root 3221: rn = "VPEConf0";
1.1.1.6 root 3222: break;
1.1.1.5 root 3223: case 3:
1.1.1.6 root 3224: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 3225: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
1.1.1.5 root 3226: rn = "VPEConf1";
1.1.1.6 root 3227: break;
1.1.1.5 root 3228: case 4:
1.1.1.6 root 3229: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 3230: gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
1.1.1.5 root 3231: rn = "YQMask";
1.1.1.6 root 3232: break;
1.1.1.5 root 3233: case 5:
1.1.1.6 root 3234: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 3235: gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
1.1.1.5 root 3236: rn = "VPESchedule";
1.1.1.6 root 3237: break;
1.1.1.5 root 3238: case 6:
1.1.1.6 root 3239: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 3240: gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
1.1.1.5 root 3241: rn = "VPEScheFBack";
1.1.1.6 root 3242: break;
1.1.1.5 root 3243: case 7:
1.1.1.6 root 3244: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 3245: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
1.1.1.5 root 3246: rn = "VPEOpt";
1.1.1.6 root 3247: break;
1.1.1.5 root 3248: default:
3249: goto die;
3250: }
1.1 root 3251: break;
1.1.1.5 root 3252: case 2:
3253: switch (sel) {
3254: case 0:
1.1.1.16! root 3255: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
1.1.1.8 root 3256: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3257: rn = "EntryLo0";
3258: break;
3259: case 1:
3260: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3261: gen_helper_mfc0_tcstatus(arg);
1.1.1.6 root 3262: rn = "TCStatus";
3263: break;
3264: case 2:
3265: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3266: gen_helper_mfc0_tcbind(arg);
1.1.1.6 root 3267: rn = "TCBind";
3268: break;
1.1.1.5 root 3269: case 3:
1.1.1.6 root 3270: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3271: gen_helper_mfc0_tcrestart(arg);
1.1.1.6 root 3272: rn = "TCRestart";
3273: break;
1.1.1.5 root 3274: case 4:
1.1.1.6 root 3275: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3276: gen_helper_mfc0_tchalt(arg);
1.1.1.6 root 3277: rn = "TCHalt";
3278: break;
1.1.1.5 root 3279: case 5:
1.1.1.6 root 3280: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3281: gen_helper_mfc0_tccontext(arg);
1.1.1.6 root 3282: rn = "TCContext";
3283: break;
1.1.1.5 root 3284: case 6:
1.1.1.6 root 3285: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3286: gen_helper_mfc0_tcschedule(arg);
1.1.1.6 root 3287: rn = "TCSchedule";
3288: break;
1.1.1.5 root 3289: case 7:
1.1.1.6 root 3290: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3291: gen_helper_mfc0_tcschefback(arg);
1.1.1.6 root 3292: rn = "TCScheFBack";
3293: break;
1.1.1.5 root 3294: default:
3295: goto die;
3296: }
1.1 root 3297: break;
1.1.1.5 root 3298: case 3:
3299: switch (sel) {
3300: case 0:
1.1.1.16! root 3301: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
1.1.1.8 root 3302: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3303: rn = "EntryLo1";
3304: break;
1.1.1.5 root 3305: default:
3306: goto die;
1.1.1.6 root 3307: }
1.1 root 3308: break;
1.1.1.5 root 3309: case 4:
3310: switch (sel) {
3311: case 0:
1.1.1.16! root 3312: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
1.1.1.8 root 3313: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3314: rn = "Context";
3315: break;
3316: case 1:
1.1.1.8 root 3317: // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 3318: rn = "ContextConfig";
3319: // break;
1.1.1.5 root 3320: default:
3321: goto die;
1.1.1.6 root 3322: }
1.1 root 3323: break;
1.1.1.5 root 3324: case 5:
3325: switch (sel) {
3326: case 0:
1.1.1.16! root 3327: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
1.1.1.6 root 3328: rn = "PageMask";
3329: break;
3330: case 1:
3331: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 3332: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
1.1.1.6 root 3333: rn = "PageGrain";
3334: break;
1.1.1.5 root 3335: default:
3336: goto die;
1.1.1.6 root 3337: }
1.1 root 3338: break;
1.1.1.5 root 3339: case 6:
3340: switch (sel) {
3341: case 0:
1.1.1.16! root 3342: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
1.1.1.6 root 3343: rn = "Wired";
3344: break;
3345: case 1:
3346: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 3347: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
1.1.1.6 root 3348: rn = "SRSConf0";
3349: break;
3350: case 2:
3351: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 3352: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
1.1.1.6 root 3353: rn = "SRSConf1";
3354: break;
1.1.1.5 root 3355: case 3:
1.1.1.6 root 3356: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 3357: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
1.1.1.6 root 3358: rn = "SRSConf2";
3359: break;
1.1.1.5 root 3360: case 4:
1.1.1.6 root 3361: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 3362: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
1.1.1.6 root 3363: rn = "SRSConf3";
3364: break;
1.1.1.5 root 3365: case 5:
1.1.1.6 root 3366: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 3367: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
1.1.1.6 root 3368: rn = "SRSConf4";
3369: break;
1.1.1.5 root 3370: default:
3371: goto die;
1.1.1.6 root 3372: }
1.1 root 3373: break;
1.1.1.5 root 3374: case 7:
3375: switch (sel) {
3376: case 0:
1.1.1.6 root 3377: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 3378: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
1.1.1.6 root 3379: rn = "HWREna";
3380: break;
1.1.1.5 root 3381: default:
3382: goto die;
1.1.1.6 root 3383: }
1.1 root 3384: break;
1.1.1.5 root 3385: case 8:
3386: switch (sel) {
3387: case 0:
1.1.1.16! root 3388: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
1.1.1.8 root 3389: tcg_gen_ext32s_tl(arg, arg);
1.1.1.7 root 3390: rn = "BadVAddr";
1.1.1.6 root 3391: break;
1.1.1.5 root 3392: default:
3393: goto die;
3394: }
1.1.1.2 root 3395: break;
1.1.1.5 root 3396: case 9:
3397: switch (sel) {
3398: case 0:
1.1.1.7 root 3399: /* Mark as an IO operation because we read the time. */
3400: if (use_icount)
3401: gen_io_start();
1.1.1.8 root 3402: gen_helper_mfc0_count(arg);
1.1.1.7 root 3403: if (use_icount) {
3404: gen_io_end();
3405: }
1.1.1.13 root 3406: /* Break the TB to be able to take timer interrupts immediately
3407: after reading count. */
3408: ctx->bstate = BS_STOP;
1.1.1.6 root 3409: rn = "Count";
3410: break;
3411: /* 6,7 are implementation dependent */
1.1.1.5 root 3412: default:
3413: goto die;
1.1.1.6 root 3414: }
1.1.1.5 root 3415: break;
3416: case 10:
3417: switch (sel) {
3418: case 0:
1.1.1.16! root 3419: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
1.1.1.8 root 3420: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3421: rn = "EntryHi";
3422: break;
1.1.1.5 root 3423: default:
3424: goto die;
1.1.1.6 root 3425: }
1.1.1.5 root 3426: break;
3427: case 11:
3428: switch (sel) {
3429: case 0:
1.1.1.16! root 3430: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
1.1.1.6 root 3431: rn = "Compare";
3432: break;
3433: /* 6,7 are implementation dependent */
1.1.1.5 root 3434: default:
3435: goto die;
1.1.1.6 root 3436: }
1.1.1.5 root 3437: break;
3438: case 12:
3439: switch (sel) {
3440: case 0:
1.1.1.16! root 3441: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
1.1.1.6 root 3442: rn = "Status";
3443: break;
3444: case 1:
3445: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 3446: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
1.1.1.6 root 3447: rn = "IntCtl";
3448: break;
3449: case 2:
3450: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 3451: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
1.1.1.6 root 3452: rn = "SRSCtl";
3453: break;
1.1.1.5 root 3454: case 3:
1.1.1.6 root 3455: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 3456: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
1.1.1.6 root 3457: rn = "SRSMap";
3458: break;
1.1.1.5 root 3459: default:
3460: goto die;
3461: }
3462: break;
3463: case 13:
3464: switch (sel) {
3465: case 0:
1.1.1.16! root 3466: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
1.1.1.6 root 3467: rn = "Cause";
3468: break;
1.1.1.5 root 3469: default:
3470: goto die;
3471: }
3472: break;
3473: case 14:
3474: switch (sel) {
3475: case 0:
1.1.1.16! root 3476: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
1.1.1.8 root 3477: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3478: rn = "EPC";
3479: break;
1.1.1.5 root 3480: default:
3481: goto die;
1.1.1.6 root 3482: }
1.1.1.5 root 3483: break;
3484: case 15:
3485: switch (sel) {
3486: case 0:
1.1.1.16! root 3487: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
1.1.1.6 root 3488: rn = "PRid";
3489: break;
3490: case 1:
3491: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 3492: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
1.1.1.6 root 3493: rn = "EBase";
3494: break;
1.1.1.5 root 3495: default:
3496: goto die;
3497: }
3498: break;
3499: case 16:
3500: switch (sel) {
3501: case 0:
1.1.1.16! root 3502: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
1.1.1.5 root 3503: rn = "Config";
3504: break;
3505: case 1:
1.1.1.16! root 3506: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
1.1.1.5 root 3507: rn = "Config1";
3508: break;
3509: case 2:
1.1.1.16! root 3510: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
1.1.1.5 root 3511: rn = "Config2";
3512: break;
3513: case 3:
1.1.1.16! root 3514: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
1.1.1.5 root 3515: rn = "Config3";
3516: break;
1.1.1.6 root 3517: /* 4,5 are reserved */
3518: /* 6,7 are implementation dependent */
3519: case 6:
1.1.1.16! root 3520: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
1.1.1.6 root 3521: rn = "Config6";
3522: break;
3523: case 7:
1.1.1.16! root 3524: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
1.1.1.6 root 3525: rn = "Config7";
3526: break;
1.1.1.5 root 3527: default:
3528: goto die;
1.1 root 3529: }
1.1.1.4 root 3530: break;
1.1.1.5 root 3531: case 17:
3532: switch (sel) {
3533: case 0:
1.1.1.8 root 3534: gen_helper_mfc0_lladdr(arg);
1.1.1.6 root 3535: rn = "LLAddr";
3536: break;
1.1.1.5 root 3537: default:
3538: goto die;
3539: }
1.1.1.4 root 3540: break;
1.1.1.5 root 3541: case 18:
3542: switch (sel) {
1.1.1.6 root 3543: case 0 ... 7:
1.1.1.8 root 3544: gen_helper_1i(mfc0_watchlo, arg, sel);
1.1.1.6 root 3545: rn = "WatchLo";
3546: break;
1.1.1.5 root 3547: default:
3548: goto die;
3549: }
1.1.1.4 root 3550: break;
1.1.1.5 root 3551: case 19:
3552: switch (sel) {
1.1.1.6 root 3553: case 0 ...7:
1.1.1.8 root 3554: gen_helper_1i(mfc0_watchhi, arg, sel);
1.1.1.6 root 3555: rn = "WatchHi";
3556: break;
1.1.1.5 root 3557: default:
3558: goto die;
3559: }
1.1.1.4 root 3560: break;
1.1.1.5 root 3561: case 20:
3562: switch (sel) {
3563: case 0:
1.1.1.6 root 3564: #if defined(TARGET_MIPS64)
3565: check_insn(env, ctx, ISA_MIPS3);
1.1.1.16! root 3566: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
1.1.1.8 root 3567: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3568: rn = "XContext";
3569: break;
3570: #endif
1.1.1.5 root 3571: default:
3572: goto die;
1.1.1.4 root 3573: }
3574: break;
1.1.1.5 root 3575: case 21:
3576: /* Officially reserved, but sel 0 is used for R1x000 framemask */
3577: switch (sel) {
3578: case 0:
1.1.1.16! root 3579: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
1.1.1.6 root 3580: rn = "Framemask";
3581: break;
1.1.1.5 root 3582: default:
3583: goto die;
1.1.1.4 root 3584: }
3585: break;
1.1.1.5 root 3586: case 22:
1.1.1.8 root 3587: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 3588: rn = "'Diagnostic"; /* implementation dependent */
3589: break;
1.1.1.5 root 3590: case 23:
3591: switch (sel) {
3592: case 0:
1.1.1.8 root 3593: gen_helper_mfc0_debug(arg); /* EJTAG support */
1.1.1.6 root 3594: rn = "Debug";
3595: break;
3596: case 1:
1.1.1.8 root 3597: // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 3598: rn = "TraceControl";
3599: // break;
3600: case 2:
1.1.1.8 root 3601: // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 3602: rn = "TraceControl2";
3603: // break;
1.1.1.5 root 3604: case 3:
1.1.1.8 root 3605: // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 3606: rn = "UserTraceData";
3607: // break;
1.1.1.5 root 3608: case 4:
1.1.1.8 root 3609: // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 3610: rn = "TraceBPC";
3611: // break;
1.1.1.5 root 3612: default:
3613: goto die;
1.1.1.4 root 3614: }
1.1.1.5 root 3615: break;
3616: case 24:
3617: switch (sel) {
3618: case 0:
1.1.1.7 root 3619: /* EJTAG support */
1.1.1.16! root 3620: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
1.1.1.8 root 3621: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3622: rn = "DEPC";
3623: break;
1.1.1.5 root 3624: default:
3625: goto die;
3626: }
3627: break;
3628: case 25:
3629: switch (sel) {
3630: case 0:
1.1.1.16! root 3631: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
1.1.1.6 root 3632: rn = "Performance0";
1.1.1.5 root 3633: break;
3634: case 1:
1.1.1.8 root 3635: // gen_helper_mfc0_performance1(arg);
1.1.1.6 root 3636: rn = "Performance1";
3637: // break;
1.1.1.5 root 3638: case 2:
1.1.1.8 root 3639: // gen_helper_mfc0_performance2(arg);
1.1.1.6 root 3640: rn = "Performance2";
3641: // break;
1.1.1.5 root 3642: case 3:
1.1.1.8 root 3643: // gen_helper_mfc0_performance3(arg);
1.1.1.6 root 3644: rn = "Performance3";
3645: // break;
1.1.1.5 root 3646: case 4:
1.1.1.8 root 3647: // gen_helper_mfc0_performance4(arg);
1.1.1.6 root 3648: rn = "Performance4";
3649: // break;
1.1.1.5 root 3650: case 5:
1.1.1.8 root 3651: // gen_helper_mfc0_performance5(arg);
1.1.1.6 root 3652: rn = "Performance5";
3653: // break;
1.1.1.5 root 3654: case 6:
1.1.1.8 root 3655: // gen_helper_mfc0_performance6(arg);
1.1.1.6 root 3656: rn = "Performance6";
3657: // break;
1.1.1.5 root 3658: case 7:
1.1.1.8 root 3659: // gen_helper_mfc0_performance7(arg);
1.1.1.6 root 3660: rn = "Performance7";
3661: // break;
1.1.1.5 root 3662: default:
3663: goto die;
3664: }
3665: break;
3666: case 26:
1.1.1.8 root 3667: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.7 root 3668: rn = "ECC";
3669: break;
1.1.1.5 root 3670: case 27:
3671: switch (sel) {
3672: case 0 ... 3:
1.1.1.8 root 3673: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 3674: rn = "CacheErr";
3675: break;
1.1.1.5 root 3676: default:
3677: goto die;
3678: }
3679: break;
3680: case 28:
3681: switch (sel) {
3682: case 0:
3683: case 2:
3684: case 4:
3685: case 6:
1.1.1.16! root 3686: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
1.1.1.5 root 3687: rn = "TagLo";
3688: break;
3689: case 1:
3690: case 3:
3691: case 5:
3692: case 7:
1.1.1.16! root 3693: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
1.1.1.5 root 3694: rn = "DataLo";
3695: break;
3696: default:
3697: goto die;
3698: }
3699: break;
3700: case 29:
3701: switch (sel) {
3702: case 0:
3703: case 2:
3704: case 4:
3705: case 6:
1.1.1.16! root 3706: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
1.1.1.5 root 3707: rn = "TagHi";
3708: break;
3709: case 1:
3710: case 3:
3711: case 5:
3712: case 7:
1.1.1.16! root 3713: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
1.1.1.5 root 3714: rn = "DataHi";
3715: break;
3716: default:
3717: goto die;
3718: }
3719: break;
3720: case 30:
3721: switch (sel) {
3722: case 0:
1.1.1.16! root 3723: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
1.1.1.8 root 3724: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3725: rn = "ErrorEPC";
3726: break;
1.1.1.5 root 3727: default:
3728: goto die;
3729: }
3730: break;
3731: case 31:
3732: switch (sel) {
3733: case 0:
1.1.1.7 root 3734: /* EJTAG support */
1.1.1.16! root 3735: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
1.1.1.6 root 3736: rn = "DESAVE";
3737: break;
1.1.1.5 root 3738: default:
3739: goto die;
3740: }
3741: break;
3742: default:
3743: goto die;
3744: }
1.1.1.13 root 3745: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 3746: LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 3747: return;
3748:
3749: die:
1.1.1.7 root 3750: LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 3751: generate_exception(ctx, EXCP_RI);
3752: }
3753:
1.1.1.16! root 3754: static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 3755: {
3756: const char *rn = "invalid";
3757:
1.1.1.6 root 3758: if (sel != 0)
3759: check_insn(env, ctx, ISA_MIPS32);
3760:
1.1.1.7 root 3761: if (use_icount)
3762: gen_io_start();
3763:
1.1.1.5 root 3764: switch (reg) {
3765: case 0:
3766: switch (sel) {
3767: case 0:
1.1.1.8 root 3768: gen_helper_mtc0_index(arg);
1.1.1.5 root 3769: rn = "Index";
3770: break;
3771: case 1:
1.1.1.6 root 3772: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3773: gen_helper_mtc0_mvpcontrol(arg);
1.1.1.5 root 3774: rn = "MVPControl";
1.1.1.6 root 3775: break;
1.1.1.5 root 3776: case 2:
1.1.1.6 root 3777: check_insn(env, ctx, ASE_MT);
3778: /* ignored */
1.1.1.5 root 3779: rn = "MVPConf0";
1.1.1.6 root 3780: break;
1.1.1.5 root 3781: case 3:
1.1.1.6 root 3782: check_insn(env, ctx, ASE_MT);
3783: /* ignored */
1.1.1.5 root 3784: rn = "MVPConf1";
1.1.1.6 root 3785: break;
1.1.1.5 root 3786: default:
3787: goto die;
3788: }
3789: break;
3790: case 1:
3791: switch (sel) {
3792: case 0:
1.1.1.6 root 3793: /* ignored */
1.1.1.5 root 3794: rn = "Random";
1.1.1.6 root 3795: break;
1.1.1.5 root 3796: case 1:
1.1.1.6 root 3797: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3798: gen_helper_mtc0_vpecontrol(arg);
1.1.1.5 root 3799: rn = "VPEControl";
1.1.1.6 root 3800: break;
1.1.1.5 root 3801: case 2:
1.1.1.6 root 3802: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3803: gen_helper_mtc0_vpeconf0(arg);
1.1.1.5 root 3804: rn = "VPEConf0";
1.1.1.6 root 3805: break;
1.1.1.5 root 3806: case 3:
1.1.1.6 root 3807: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3808: gen_helper_mtc0_vpeconf1(arg);
1.1.1.5 root 3809: rn = "VPEConf1";
1.1.1.6 root 3810: break;
1.1.1.5 root 3811: case 4:
1.1.1.6 root 3812: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3813: gen_helper_mtc0_yqmask(arg);
1.1.1.5 root 3814: rn = "YQMask";
1.1.1.6 root 3815: break;
1.1.1.5 root 3816: case 5:
1.1.1.6 root 3817: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 3818: gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
1.1.1.5 root 3819: rn = "VPESchedule";
1.1.1.6 root 3820: break;
1.1.1.5 root 3821: case 6:
1.1.1.6 root 3822: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 3823: gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
1.1.1.5 root 3824: rn = "VPEScheFBack";
1.1.1.6 root 3825: break;
1.1.1.5 root 3826: case 7:
1.1.1.6 root 3827: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3828: gen_helper_mtc0_vpeopt(arg);
1.1.1.5 root 3829: rn = "VPEOpt";
1.1.1.6 root 3830: break;
1.1.1.5 root 3831: default:
3832: goto die;
3833: }
3834: break;
3835: case 2:
3836: switch (sel) {
3837: case 0:
1.1.1.8 root 3838: gen_helper_mtc0_entrylo0(arg);
1.1.1.6 root 3839: rn = "EntryLo0";
3840: break;
3841: case 1:
3842: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3843: gen_helper_mtc0_tcstatus(arg);
1.1.1.6 root 3844: rn = "TCStatus";
3845: break;
3846: case 2:
3847: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3848: gen_helper_mtc0_tcbind(arg);
1.1.1.6 root 3849: rn = "TCBind";
3850: break;
1.1.1.5 root 3851: case 3:
1.1.1.6 root 3852: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3853: gen_helper_mtc0_tcrestart(arg);
1.1.1.6 root 3854: rn = "TCRestart";
3855: break;
1.1.1.5 root 3856: case 4:
1.1.1.6 root 3857: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3858: gen_helper_mtc0_tchalt(arg);
1.1.1.6 root 3859: rn = "TCHalt";
3860: break;
1.1.1.5 root 3861: case 5:
1.1.1.6 root 3862: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3863: gen_helper_mtc0_tccontext(arg);
1.1.1.6 root 3864: rn = "TCContext";
3865: break;
1.1.1.5 root 3866: case 6:
1.1.1.6 root 3867: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3868: gen_helper_mtc0_tcschedule(arg);
1.1.1.6 root 3869: rn = "TCSchedule";
3870: break;
1.1.1.5 root 3871: case 7:
1.1.1.6 root 3872: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3873: gen_helper_mtc0_tcschefback(arg);
1.1.1.6 root 3874: rn = "TCScheFBack";
3875: break;
1.1.1.5 root 3876: default:
3877: goto die;
3878: }
3879: break;
3880: case 3:
3881: switch (sel) {
3882: case 0:
1.1.1.8 root 3883: gen_helper_mtc0_entrylo1(arg);
1.1.1.6 root 3884: rn = "EntryLo1";
3885: break;
1.1.1.5 root 3886: default:
3887: goto die;
1.1.1.6 root 3888: }
1.1.1.5 root 3889: break;
3890: case 4:
3891: switch (sel) {
3892: case 0:
1.1.1.8 root 3893: gen_helper_mtc0_context(arg);
1.1.1.6 root 3894: rn = "Context";
3895: break;
3896: case 1:
1.1.1.8 root 3897: // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 3898: rn = "ContextConfig";
3899: // break;
1.1.1.5 root 3900: default:
3901: goto die;
1.1.1.6 root 3902: }
1.1.1.5 root 3903: break;
3904: case 5:
3905: switch (sel) {
3906: case 0:
1.1.1.8 root 3907: gen_helper_mtc0_pagemask(arg);
1.1.1.6 root 3908: rn = "PageMask";
3909: break;
3910: case 1:
3911: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3912: gen_helper_mtc0_pagegrain(arg);
1.1.1.6 root 3913: rn = "PageGrain";
3914: break;
1.1.1.5 root 3915: default:
3916: goto die;
1.1.1.6 root 3917: }
1.1.1.5 root 3918: break;
3919: case 6:
3920: switch (sel) {
3921: case 0:
1.1.1.8 root 3922: gen_helper_mtc0_wired(arg);
1.1.1.6 root 3923: rn = "Wired";
3924: break;
3925: case 1:
3926: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3927: gen_helper_mtc0_srsconf0(arg);
1.1.1.6 root 3928: rn = "SRSConf0";
3929: break;
3930: case 2:
3931: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3932: gen_helper_mtc0_srsconf1(arg);
1.1.1.6 root 3933: rn = "SRSConf1";
3934: break;
1.1.1.5 root 3935: case 3:
1.1.1.6 root 3936: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3937: gen_helper_mtc0_srsconf2(arg);
1.1.1.6 root 3938: rn = "SRSConf2";
3939: break;
1.1.1.5 root 3940: case 4:
1.1.1.6 root 3941: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3942: gen_helper_mtc0_srsconf3(arg);
1.1.1.6 root 3943: rn = "SRSConf3";
3944: break;
1.1.1.5 root 3945: case 5:
1.1.1.6 root 3946: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3947: gen_helper_mtc0_srsconf4(arg);
1.1.1.6 root 3948: rn = "SRSConf4";
3949: break;
1.1.1.5 root 3950: default:
3951: goto die;
1.1.1.6 root 3952: }
1.1.1.5 root 3953: break;
3954: case 7:
3955: switch (sel) {
3956: case 0:
1.1.1.6 root 3957: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3958: gen_helper_mtc0_hwrena(arg);
1.1.1.6 root 3959: rn = "HWREna";
3960: break;
1.1.1.5 root 3961: default:
3962: goto die;
1.1.1.6 root 3963: }
1.1.1.5 root 3964: break;
3965: case 8:
3966: /* ignored */
1.1.1.7 root 3967: rn = "BadVAddr";
1.1.1.5 root 3968: break;
3969: case 9:
3970: switch (sel) {
3971: case 0:
1.1.1.8 root 3972: gen_helper_mtc0_count(arg);
1.1.1.6 root 3973: rn = "Count";
3974: break;
3975: /* 6,7 are implementation dependent */
1.1.1.5 root 3976: default:
3977: goto die;
1.1.1.6 root 3978: }
1.1.1.5 root 3979: break;
3980: case 10:
3981: switch (sel) {
3982: case 0:
1.1.1.8 root 3983: gen_helper_mtc0_entryhi(arg);
1.1.1.6 root 3984: rn = "EntryHi";
3985: break;
1.1.1.5 root 3986: default:
3987: goto die;
1.1.1.6 root 3988: }
1.1.1.5 root 3989: break;
3990: case 11:
3991: switch (sel) {
3992: case 0:
1.1.1.8 root 3993: gen_helper_mtc0_compare(arg);
1.1.1.6 root 3994: rn = "Compare";
3995: break;
3996: /* 6,7 are implementation dependent */
1.1.1.5 root 3997: default:
3998: goto die;
1.1.1.6 root 3999: }
1.1.1.5 root 4000: break;
4001: case 12:
4002: switch (sel) {
4003: case 0:
1.1.1.8 root 4004: save_cpu_state(ctx, 1);
4005: gen_helper_mtc0_status(arg);
1.1.1.6 root 4006: /* BS_STOP isn't good enough here, hflags may have changed. */
4007: gen_save_pc(ctx->pc + 4);
4008: ctx->bstate = BS_EXCP;
4009: rn = "Status";
4010: break;
4011: case 1:
4012: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4013: gen_helper_mtc0_intctl(arg);
1.1.1.6 root 4014: /* Stop translation as we may have switched the execution mode */
4015: ctx->bstate = BS_STOP;
4016: rn = "IntCtl";
4017: break;
4018: case 2:
4019: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4020: gen_helper_mtc0_srsctl(arg);
1.1.1.6 root 4021: /* Stop translation as we may have switched the execution mode */
4022: ctx->bstate = BS_STOP;
4023: rn = "SRSCtl";
4024: break;
1.1.1.5 root 4025: case 3:
1.1.1.6 root 4026: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4027: gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
1.1.1.6 root 4028: /* Stop translation as we may have switched the execution mode */
4029: ctx->bstate = BS_STOP;
4030: rn = "SRSMap";
4031: break;
1.1.1.5 root 4032: default:
4033: goto die;
1.1.1.6 root 4034: }
1.1.1.5 root 4035: break;
4036: case 13:
4037: switch (sel) {
4038: case 0:
1.1.1.8 root 4039: save_cpu_state(ctx, 1);
4040: gen_helper_mtc0_cause(arg);
1.1.1.6 root 4041: rn = "Cause";
4042: break;
1.1.1.5 root 4043: default:
4044: goto die;
1.1.1.6 root 4045: }
1.1.1.5 root 4046: break;
4047: case 14:
4048: switch (sel) {
4049: case 0:
1.1.1.16! root 4050: gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
1.1.1.6 root 4051: rn = "EPC";
4052: break;
1.1.1.5 root 4053: default:
4054: goto die;
1.1.1.6 root 4055: }
1.1.1.5 root 4056: break;
4057: case 15:
4058: switch (sel) {
4059: case 0:
1.1.1.6 root 4060: /* ignored */
4061: rn = "PRid";
4062: break;
4063: case 1:
4064: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4065: gen_helper_mtc0_ebase(arg);
1.1.1.6 root 4066: rn = "EBase";
4067: break;
1.1.1.5 root 4068: default:
4069: goto die;
1.1.1.6 root 4070: }
1.1.1.5 root 4071: break;
4072: case 16:
4073: switch (sel) {
4074: case 0:
1.1.1.8 root 4075: gen_helper_mtc0_config0(arg);
1.1.1.5 root 4076: rn = "Config";
1.1.1.6 root 4077: /* Stop translation as we may have switched the execution mode */
4078: ctx->bstate = BS_STOP;
1.1.1.5 root 4079: break;
4080: case 1:
1.1.1.6 root 4081: /* ignored, read only */
1.1.1.5 root 4082: rn = "Config1";
4083: break;
4084: case 2:
1.1.1.8 root 4085: gen_helper_mtc0_config2(arg);
1.1.1.5 root 4086: rn = "Config2";
1.1.1.6 root 4087: /* Stop translation as we may have switched the execution mode */
4088: ctx->bstate = BS_STOP;
1.1.1.5 root 4089: break;
4090: case 3:
1.1.1.6 root 4091: /* ignored, read only */
1.1.1.5 root 4092: rn = "Config3";
4093: break;
1.1.1.6 root 4094: /* 4,5 are reserved */
4095: /* 6,7 are implementation dependent */
4096: case 6:
4097: /* ignored */
4098: rn = "Config6";
4099: break;
4100: case 7:
4101: /* ignored */
4102: rn = "Config7";
4103: break;
1.1.1.5 root 4104: default:
4105: rn = "Invalid config selector";
4106: goto die;
4107: }
4108: break;
4109: case 17:
4110: switch (sel) {
4111: case 0:
1.1.1.9 root 4112: gen_helper_mtc0_lladdr(arg);
1.1.1.6 root 4113: rn = "LLAddr";
4114: break;
1.1.1.5 root 4115: default:
4116: goto die;
4117: }
4118: break;
4119: case 18:
4120: switch (sel) {
1.1.1.6 root 4121: case 0 ... 7:
1.1.1.8 root 4122: gen_helper_1i(mtc0_watchlo, arg, sel);
1.1.1.6 root 4123: rn = "WatchLo";
4124: break;
1.1.1.5 root 4125: default:
4126: goto die;
4127: }
4128: break;
4129: case 19:
4130: switch (sel) {
1.1.1.6 root 4131: case 0 ... 7:
1.1.1.8 root 4132: gen_helper_1i(mtc0_watchhi, arg, sel);
1.1.1.6 root 4133: rn = "WatchHi";
4134: break;
1.1.1.5 root 4135: default:
4136: goto die;
4137: }
4138: break;
4139: case 20:
4140: switch (sel) {
4141: case 0:
1.1.1.6 root 4142: #if defined(TARGET_MIPS64)
4143: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 4144: gen_helper_mtc0_xcontext(arg);
1.1.1.6 root 4145: rn = "XContext";
4146: break;
4147: #endif
1.1.1.5 root 4148: default:
4149: goto die;
4150: }
4151: break;
4152: case 21:
4153: /* Officially reserved, but sel 0 is used for R1x000 framemask */
4154: switch (sel) {
4155: case 0:
1.1.1.8 root 4156: gen_helper_mtc0_framemask(arg);
1.1.1.6 root 4157: rn = "Framemask";
4158: break;
1.1.1.5 root 4159: default:
4160: goto die;
4161: }
4162: break;
4163: case 22:
4164: /* ignored */
4165: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 root 4166: break;
1.1.1.5 root 4167: case 23:
4168: switch (sel) {
4169: case 0:
1.1.1.8 root 4170: gen_helper_mtc0_debug(arg); /* EJTAG support */
1.1.1.6 root 4171: /* BS_STOP isn't good enough here, hflags may have changed. */
4172: gen_save_pc(ctx->pc + 4);
4173: ctx->bstate = BS_EXCP;
4174: rn = "Debug";
4175: break;
4176: case 1:
1.1.1.8 root 4177: // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 4178: rn = "TraceControl";
4179: /* Stop translation as we may have switched the execution mode */
4180: ctx->bstate = BS_STOP;
4181: // break;
4182: case 2:
1.1.1.8 root 4183: // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 4184: rn = "TraceControl2";
4185: /* Stop translation as we may have switched the execution mode */
4186: ctx->bstate = BS_STOP;
4187: // break;
4188: case 3:
4189: /* Stop translation as we may have switched the execution mode */
4190: ctx->bstate = BS_STOP;
1.1.1.8 root 4191: // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 4192: rn = "UserTraceData";
4193: /* Stop translation as we may have switched the execution mode */
4194: ctx->bstate = BS_STOP;
4195: // break;
1.1.1.5 root 4196: case 4:
1.1.1.8 root 4197: // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 4198: /* Stop translation as we may have switched the execution mode */
4199: ctx->bstate = BS_STOP;
4200: rn = "TraceBPC";
4201: // break;
1.1.1.5 root 4202: default:
4203: goto die;
4204: }
4205: break;
4206: case 24:
4207: switch (sel) {
4208: case 0:
1.1.1.7 root 4209: /* EJTAG support */
1.1.1.16! root 4210: gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
1.1.1.6 root 4211: rn = "DEPC";
4212: break;
1.1.1.5 root 4213: default:
4214: goto die;
4215: }
4216: break;
4217: case 25:
4218: switch (sel) {
4219: case 0:
1.1.1.8 root 4220: gen_helper_mtc0_performance0(arg);
1.1.1.6 root 4221: rn = "Performance0";
4222: break;
4223: case 1:
1.1.1.8 root 4224: // gen_helper_mtc0_performance1(arg);
1.1.1.6 root 4225: rn = "Performance1";
4226: // break;
4227: case 2:
1.1.1.8 root 4228: // gen_helper_mtc0_performance2(arg);
1.1.1.6 root 4229: rn = "Performance2";
4230: // break;
4231: case 3:
1.1.1.8 root 4232: // gen_helper_mtc0_performance3(arg);
1.1.1.6 root 4233: rn = "Performance3";
4234: // break;
1.1.1.5 root 4235: case 4:
1.1.1.8 root 4236: // gen_helper_mtc0_performance4(arg);
1.1.1.6 root 4237: rn = "Performance4";
4238: // break;
1.1.1.5 root 4239: case 5:
1.1.1.8 root 4240: // gen_helper_mtc0_performance5(arg);
1.1.1.6 root 4241: rn = "Performance5";
4242: // break;
1.1.1.5 root 4243: case 6:
1.1.1.8 root 4244: // gen_helper_mtc0_performance6(arg);
1.1.1.6 root 4245: rn = "Performance6";
4246: // break;
1.1.1.5 root 4247: case 7:
1.1.1.8 root 4248: // gen_helper_mtc0_performance7(arg);
1.1.1.6 root 4249: rn = "Performance7";
4250: // break;
1.1.1.5 root 4251: default:
4252: goto die;
4253: }
4254: break;
4255: case 26:
1.1.1.6 root 4256: /* ignored */
1.1.1.5 root 4257: rn = "ECC";
1.1.1.6 root 4258: break;
1.1.1.5 root 4259: case 27:
4260: switch (sel) {
4261: case 0 ... 3:
1.1.1.6 root 4262: /* ignored */
4263: rn = "CacheErr";
4264: break;
1.1.1.5 root 4265: default:
4266: goto die;
4267: }
4268: break;
4269: case 28:
4270: switch (sel) {
4271: case 0:
4272: case 2:
4273: case 4:
4274: case 6:
1.1.1.8 root 4275: gen_helper_mtc0_taglo(arg);
1.1.1.5 root 4276: rn = "TagLo";
4277: break;
4278: case 1:
4279: case 3:
4280: case 5:
4281: case 7:
1.1.1.8 root 4282: gen_helper_mtc0_datalo(arg);
1.1.1.5 root 4283: rn = "DataLo";
4284: break;
4285: default:
4286: goto die;
4287: }
4288: break;
4289: case 29:
4290: switch (sel) {
4291: case 0:
4292: case 2:
4293: case 4:
4294: case 6:
1.1.1.8 root 4295: gen_helper_mtc0_taghi(arg);
1.1.1.5 root 4296: rn = "TagHi";
4297: break;
4298: case 1:
4299: case 3:
4300: case 5:
4301: case 7:
1.1.1.8 root 4302: gen_helper_mtc0_datahi(arg);
1.1.1.5 root 4303: rn = "DataHi";
4304: break;
4305: default:
4306: rn = "invalid sel";
4307: goto die;
4308: }
4309: break;
4310: case 30:
4311: switch (sel) {
4312: case 0:
1.1.1.16! root 4313: gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
1.1.1.6 root 4314: rn = "ErrorEPC";
4315: break;
1.1.1.5 root 4316: default:
4317: goto die;
4318: }
4319: break;
4320: case 31:
4321: switch (sel) {
4322: case 0:
1.1.1.7 root 4323: /* EJTAG support */
1.1.1.16! root 4324: gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
1.1.1.6 root 4325: rn = "DESAVE";
4326: break;
1.1.1.5 root 4327: default:
4328: goto die;
4329: }
1.1.1.6 root 4330: /* Stop translation as we may have switched the execution mode */
4331: ctx->bstate = BS_STOP;
1.1.1.5 root 4332: break;
4333: default:
4334: goto die;
4335: }
1.1.1.13 root 4336: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 4337: LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4338: /* For simplicity assume that all writes can cause interrupts. */
4339: if (use_icount) {
4340: gen_io_end();
4341: ctx->bstate = BS_STOP;
1.1.1.5 root 4342: }
4343: return;
4344:
4345: die:
1.1.1.7 root 4346: LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4347: generate_exception(ctx, EXCP_RI);
4348: }
4349:
1.1.1.6 root 4350: #if defined(TARGET_MIPS64)
1.1.1.16! root 4351: static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 4352: {
4353: const char *rn = "invalid";
4354:
1.1.1.6 root 4355: if (sel != 0)
4356: check_insn(env, ctx, ISA_MIPS64);
4357:
1.1.1.5 root 4358: switch (reg) {
4359: case 0:
4360: switch (sel) {
4361: case 0:
1.1.1.16! root 4362: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
1.1.1.5 root 4363: rn = "Index";
4364: break;
4365: case 1:
1.1.1.6 root 4366: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4367: gen_helper_mfc0_mvpcontrol(arg);
1.1.1.5 root 4368: rn = "MVPControl";
1.1.1.6 root 4369: break;
1.1.1.5 root 4370: case 2:
1.1.1.6 root 4371: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4372: gen_helper_mfc0_mvpconf0(arg);
1.1.1.5 root 4373: rn = "MVPConf0";
1.1.1.6 root 4374: break;
1.1.1.5 root 4375: case 3:
1.1.1.6 root 4376: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4377: gen_helper_mfc0_mvpconf1(arg);
1.1.1.5 root 4378: rn = "MVPConf1";
1.1.1.6 root 4379: break;
1.1.1.5 root 4380: default:
4381: goto die;
4382: }
4383: break;
4384: case 1:
4385: switch (sel) {
4386: case 0:
1.1.1.8 root 4387: gen_helper_mfc0_random(arg);
1.1.1.5 root 4388: rn = "Random";
1.1.1.6 root 4389: break;
1.1.1.5 root 4390: case 1:
1.1.1.6 root 4391: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 4392: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
1.1.1.5 root 4393: rn = "VPEControl";
1.1.1.6 root 4394: break;
1.1.1.5 root 4395: case 2:
1.1.1.6 root 4396: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 4397: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
1.1.1.5 root 4398: rn = "VPEConf0";
1.1.1.6 root 4399: break;
1.1.1.5 root 4400: case 3:
1.1.1.6 root 4401: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 4402: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
1.1.1.5 root 4403: rn = "VPEConf1";
1.1.1.6 root 4404: break;
1.1.1.5 root 4405: case 4:
1.1.1.6 root 4406: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 4407: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
1.1.1.5 root 4408: rn = "YQMask";
1.1.1.6 root 4409: break;
1.1.1.5 root 4410: case 5:
1.1.1.6 root 4411: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 4412: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
1.1.1.5 root 4413: rn = "VPESchedule";
1.1.1.6 root 4414: break;
1.1.1.5 root 4415: case 6:
1.1.1.6 root 4416: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 4417: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
1.1.1.5 root 4418: rn = "VPEScheFBack";
1.1.1.6 root 4419: break;
1.1.1.5 root 4420: case 7:
1.1.1.6 root 4421: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 4422: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
1.1.1.5 root 4423: rn = "VPEOpt";
1.1.1.6 root 4424: break;
1.1.1.5 root 4425: default:
4426: goto die;
4427: }
4428: break;
4429: case 2:
4430: switch (sel) {
4431: case 0:
1.1.1.16! root 4432: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
1.1.1.6 root 4433: rn = "EntryLo0";
4434: break;
4435: case 1:
4436: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4437: gen_helper_mfc0_tcstatus(arg);
1.1.1.6 root 4438: rn = "TCStatus";
4439: break;
4440: case 2:
4441: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4442: gen_helper_mfc0_tcbind(arg);
1.1.1.6 root 4443: rn = "TCBind";
4444: break;
1.1.1.5 root 4445: case 3:
1.1.1.6 root 4446: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4447: gen_helper_dmfc0_tcrestart(arg);
1.1.1.6 root 4448: rn = "TCRestart";
4449: break;
1.1.1.5 root 4450: case 4:
1.1.1.6 root 4451: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4452: gen_helper_dmfc0_tchalt(arg);
1.1.1.6 root 4453: rn = "TCHalt";
4454: break;
1.1.1.5 root 4455: case 5:
1.1.1.6 root 4456: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4457: gen_helper_dmfc0_tccontext(arg);
1.1.1.6 root 4458: rn = "TCContext";
4459: break;
1.1.1.5 root 4460: case 6:
1.1.1.6 root 4461: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4462: gen_helper_dmfc0_tcschedule(arg);
1.1.1.6 root 4463: rn = "TCSchedule";
4464: break;
1.1.1.5 root 4465: case 7:
1.1.1.6 root 4466: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4467: gen_helper_dmfc0_tcschefback(arg);
1.1.1.6 root 4468: rn = "TCScheFBack";
4469: break;
1.1.1.5 root 4470: default:
4471: goto die;
4472: }
4473: break;
4474: case 3:
4475: switch (sel) {
4476: case 0:
1.1.1.16! root 4477: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
1.1.1.6 root 4478: rn = "EntryLo1";
4479: break;
1.1.1.5 root 4480: default:
4481: goto die;
1.1.1.6 root 4482: }
1.1.1.5 root 4483: break;
4484: case 4:
4485: switch (sel) {
4486: case 0:
1.1.1.16! root 4487: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
1.1.1.6 root 4488: rn = "Context";
4489: break;
4490: case 1:
1.1.1.8 root 4491: // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 4492: rn = "ContextConfig";
4493: // break;
1.1.1.5 root 4494: default:
4495: goto die;
1.1.1.6 root 4496: }
1.1.1.5 root 4497: break;
4498: case 5:
4499: switch (sel) {
4500: case 0:
1.1.1.16! root 4501: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
1.1.1.6 root 4502: rn = "PageMask";
4503: break;
4504: case 1:
4505: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4506: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
1.1.1.6 root 4507: rn = "PageGrain";
4508: break;
1.1.1.5 root 4509: default:
4510: goto die;
1.1.1.6 root 4511: }
1.1.1.5 root 4512: break;
4513: case 6:
4514: switch (sel) {
4515: case 0:
1.1.1.16! root 4516: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
1.1.1.6 root 4517: rn = "Wired";
4518: break;
4519: case 1:
4520: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4521: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
1.1.1.6 root 4522: rn = "SRSConf0";
4523: break;
4524: case 2:
4525: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4526: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
1.1.1.6 root 4527: rn = "SRSConf1";
4528: break;
1.1.1.5 root 4529: case 3:
1.1.1.6 root 4530: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4531: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
1.1.1.6 root 4532: rn = "SRSConf2";
4533: break;
1.1.1.5 root 4534: case 4:
1.1.1.6 root 4535: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4536: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
1.1.1.6 root 4537: rn = "SRSConf3";
4538: break;
1.1.1.5 root 4539: case 5:
1.1.1.6 root 4540: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4541: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
1.1.1.6 root 4542: rn = "SRSConf4";
4543: break;
1.1.1.5 root 4544: default:
4545: goto die;
1.1.1.6 root 4546: }
1.1.1.5 root 4547: break;
4548: case 7:
4549: switch (sel) {
4550: case 0:
1.1.1.6 root 4551: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4552: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
1.1.1.6 root 4553: rn = "HWREna";
4554: break;
1.1.1.5 root 4555: default:
4556: goto die;
1.1.1.6 root 4557: }
1.1.1.5 root 4558: break;
4559: case 8:
4560: switch (sel) {
4561: case 0:
1.1.1.16! root 4562: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
1.1.1.7 root 4563: rn = "BadVAddr";
1.1.1.6 root 4564: break;
1.1.1.5 root 4565: default:
4566: goto die;
1.1.1.6 root 4567: }
1.1.1.5 root 4568: break;
4569: case 9:
4570: switch (sel) {
4571: case 0:
1.1.1.7 root 4572: /* Mark as an IO operation because we read the time. */
4573: if (use_icount)
4574: gen_io_start();
1.1.1.8 root 4575: gen_helper_mfc0_count(arg);
1.1.1.7 root 4576: if (use_icount) {
4577: gen_io_end();
4578: }
1.1.1.13 root 4579: /* Break the TB to be able to take timer interrupts immediately
4580: after reading count. */
4581: ctx->bstate = BS_STOP;
1.1.1.6 root 4582: rn = "Count";
4583: break;
4584: /* 6,7 are implementation dependent */
1.1.1.5 root 4585: default:
4586: goto die;
1.1.1.6 root 4587: }
1.1.1.5 root 4588: break;
4589: case 10:
4590: switch (sel) {
4591: case 0:
1.1.1.16! root 4592: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
1.1.1.6 root 4593: rn = "EntryHi";
4594: break;
1.1.1.5 root 4595: default:
4596: goto die;
1.1.1.6 root 4597: }
1.1.1.5 root 4598: break;
4599: case 11:
4600: switch (sel) {
4601: case 0:
1.1.1.16! root 4602: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
1.1.1.6 root 4603: rn = "Compare";
4604: break;
4605: /* 6,7 are implementation dependent */
1.1.1.5 root 4606: default:
4607: goto die;
1.1.1.6 root 4608: }
1.1.1.5 root 4609: break;
4610: case 12:
4611: switch (sel) {
4612: case 0:
1.1.1.16! root 4613: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
1.1.1.6 root 4614: rn = "Status";
4615: break;
4616: case 1:
4617: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4618: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
1.1.1.6 root 4619: rn = "IntCtl";
4620: break;
4621: case 2:
4622: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4623: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
1.1.1.6 root 4624: rn = "SRSCtl";
4625: break;
1.1.1.5 root 4626: case 3:
1.1.1.6 root 4627: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4628: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
1.1.1.6 root 4629: rn = "SRSMap";
4630: break;
1.1.1.5 root 4631: default:
4632: goto die;
1.1.1.6 root 4633: }
1.1.1.5 root 4634: break;
4635: case 13:
4636: switch (sel) {
4637: case 0:
1.1.1.16! root 4638: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
1.1.1.6 root 4639: rn = "Cause";
4640: break;
1.1.1.5 root 4641: default:
4642: goto die;
1.1.1.6 root 4643: }
1.1.1.5 root 4644: break;
4645: case 14:
4646: switch (sel) {
4647: case 0:
1.1.1.16! root 4648: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
1.1.1.6 root 4649: rn = "EPC";
4650: break;
1.1.1.5 root 4651: default:
4652: goto die;
1.1.1.6 root 4653: }
1.1.1.5 root 4654: break;
4655: case 15:
4656: switch (sel) {
4657: case 0:
1.1.1.16! root 4658: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
1.1.1.6 root 4659: rn = "PRid";
4660: break;
4661: case 1:
4662: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 4663: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
1.1.1.6 root 4664: rn = "EBase";
4665: break;
1.1.1.5 root 4666: default:
4667: goto die;
1.1.1.6 root 4668: }
1.1.1.5 root 4669: break;
4670: case 16:
4671: switch (sel) {
4672: case 0:
1.1.1.16! root 4673: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
1.1.1.5 root 4674: rn = "Config";
4675: break;
4676: case 1:
1.1.1.16! root 4677: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
1.1.1.5 root 4678: rn = "Config1";
4679: break;
4680: case 2:
1.1.1.16! root 4681: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
1.1.1.5 root 4682: rn = "Config2";
4683: break;
4684: case 3:
1.1.1.16! root 4685: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
1.1.1.5 root 4686: rn = "Config3";
4687: break;
4688: /* 6,7 are implementation dependent */
1.1.1.7 root 4689: case 6:
1.1.1.16! root 4690: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
1.1.1.7 root 4691: rn = "Config6";
4692: break;
4693: case 7:
1.1.1.16! root 4694: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
1.1.1.7 root 4695: rn = "Config7";
4696: break;
1.1.1.5 root 4697: default:
4698: goto die;
4699: }
4700: break;
4701: case 17:
4702: switch (sel) {
4703: case 0:
1.1.1.8 root 4704: gen_helper_dmfc0_lladdr(arg);
1.1.1.6 root 4705: rn = "LLAddr";
4706: break;
1.1.1.5 root 4707: default:
4708: goto die;
4709: }
4710: break;
4711: case 18:
4712: switch (sel) {
1.1.1.6 root 4713: case 0 ... 7:
1.1.1.8 root 4714: gen_helper_1i(dmfc0_watchlo, arg, sel);
1.1.1.6 root 4715: rn = "WatchLo";
4716: break;
1.1.1.5 root 4717: default:
4718: goto die;
4719: }
4720: break;
4721: case 19:
4722: switch (sel) {
1.1.1.6 root 4723: case 0 ... 7:
1.1.1.8 root 4724: gen_helper_1i(mfc0_watchhi, arg, sel);
1.1.1.6 root 4725: rn = "WatchHi";
4726: break;
1.1.1.5 root 4727: default:
4728: goto die;
4729: }
4730: break;
4731: case 20:
4732: switch (sel) {
4733: case 0:
1.1.1.6 root 4734: check_insn(env, ctx, ISA_MIPS3);
1.1.1.16! root 4735: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
1.1.1.6 root 4736: rn = "XContext";
4737: break;
1.1.1.5 root 4738: default:
4739: goto die;
4740: }
4741: break;
4742: case 21:
4743: /* Officially reserved, but sel 0 is used for R1x000 framemask */
4744: switch (sel) {
4745: case 0:
1.1.1.16! root 4746: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
1.1.1.6 root 4747: rn = "Framemask";
4748: break;
1.1.1.5 root 4749: default:
4750: goto die;
4751: }
4752: break;
4753: case 22:
1.1.1.8 root 4754: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 4755: rn = "'Diagnostic"; /* implementation dependent */
4756: break;
1.1.1.5 root 4757: case 23:
4758: switch (sel) {
4759: case 0:
1.1.1.8 root 4760: gen_helper_mfc0_debug(arg); /* EJTAG support */
1.1.1.6 root 4761: rn = "Debug";
4762: break;
4763: case 1:
1.1.1.8 root 4764: // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 4765: rn = "TraceControl";
4766: // break;
4767: case 2:
1.1.1.8 root 4768: // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 4769: rn = "TraceControl2";
4770: // break;
1.1.1.5 root 4771: case 3:
1.1.1.8 root 4772: // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 4773: rn = "UserTraceData";
4774: // break;
1.1.1.5 root 4775: case 4:
1.1.1.8 root 4776: // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 4777: rn = "TraceBPC";
4778: // break;
1.1.1.5 root 4779: default:
4780: goto die;
4781: }
4782: break;
4783: case 24:
4784: switch (sel) {
4785: case 0:
1.1.1.7 root 4786: /* EJTAG support */
1.1.1.16! root 4787: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
1.1.1.6 root 4788: rn = "DEPC";
4789: break;
1.1.1.5 root 4790: default:
4791: goto die;
4792: }
4793: break;
4794: case 25:
4795: switch (sel) {
4796: case 0:
1.1.1.16! root 4797: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
1.1.1.6 root 4798: rn = "Performance0";
1.1.1.5 root 4799: break;
4800: case 1:
1.1.1.8 root 4801: // gen_helper_dmfc0_performance1(arg);
1.1.1.6 root 4802: rn = "Performance1";
4803: // break;
1.1.1.5 root 4804: case 2:
1.1.1.8 root 4805: // gen_helper_dmfc0_performance2(arg);
1.1.1.6 root 4806: rn = "Performance2";
4807: // break;
1.1.1.5 root 4808: case 3:
1.1.1.8 root 4809: // gen_helper_dmfc0_performance3(arg);
1.1.1.6 root 4810: rn = "Performance3";
4811: // break;
1.1.1.5 root 4812: case 4:
1.1.1.8 root 4813: // gen_helper_dmfc0_performance4(arg);
1.1.1.6 root 4814: rn = "Performance4";
4815: // break;
1.1.1.5 root 4816: case 5:
1.1.1.8 root 4817: // gen_helper_dmfc0_performance5(arg);
1.1.1.6 root 4818: rn = "Performance5";
4819: // break;
1.1.1.5 root 4820: case 6:
1.1.1.8 root 4821: // gen_helper_dmfc0_performance6(arg);
1.1.1.6 root 4822: rn = "Performance6";
4823: // break;
1.1.1.5 root 4824: case 7:
1.1.1.8 root 4825: // gen_helper_dmfc0_performance7(arg);
1.1.1.6 root 4826: rn = "Performance7";
4827: // break;
1.1.1.5 root 4828: default:
4829: goto die;
4830: }
4831: break;
4832: case 26:
1.1.1.8 root 4833: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.7 root 4834: rn = "ECC";
4835: break;
1.1.1.5 root 4836: case 27:
4837: switch (sel) {
4838: /* ignored */
4839: case 0 ... 3:
1.1.1.8 root 4840: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 4841: rn = "CacheErr";
4842: break;
1.1.1.5 root 4843: default:
4844: goto die;
4845: }
4846: break;
4847: case 28:
4848: switch (sel) {
4849: case 0:
4850: case 2:
4851: case 4:
4852: case 6:
1.1.1.16! root 4853: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
1.1.1.5 root 4854: rn = "TagLo";
4855: break;
4856: case 1:
4857: case 3:
4858: case 5:
4859: case 7:
1.1.1.16! root 4860: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
1.1.1.5 root 4861: rn = "DataLo";
4862: break;
4863: default:
4864: goto die;
4865: }
4866: break;
4867: case 29:
4868: switch (sel) {
4869: case 0:
4870: case 2:
4871: case 4:
4872: case 6:
1.1.1.16! root 4873: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
1.1.1.5 root 4874: rn = "TagHi";
4875: break;
4876: case 1:
4877: case 3:
4878: case 5:
4879: case 7:
1.1.1.16! root 4880: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
1.1.1.5 root 4881: rn = "DataHi";
4882: break;
4883: default:
4884: goto die;
4885: }
4886: break;
4887: case 30:
4888: switch (sel) {
4889: case 0:
1.1.1.16! root 4890: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
1.1.1.6 root 4891: rn = "ErrorEPC";
4892: break;
1.1.1.5 root 4893: default:
4894: goto die;
4895: }
4896: break;
4897: case 31:
4898: switch (sel) {
4899: case 0:
1.1.1.7 root 4900: /* EJTAG support */
1.1.1.16! root 4901: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
1.1.1.6 root 4902: rn = "DESAVE";
4903: break;
1.1.1.5 root 4904: default:
4905: goto die;
4906: }
4907: break;
4908: default:
1.1.1.6 root 4909: goto die;
1.1.1.5 root 4910: }
1.1.1.13 root 4911: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 4912: LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4913: return;
4914:
4915: die:
1.1.1.7 root 4916: LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4917: generate_exception(ctx, EXCP_RI);
4918: }
4919:
1.1.1.16! root 4920: static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 4921: {
4922: const char *rn = "invalid";
4923:
1.1.1.6 root 4924: if (sel != 0)
4925: check_insn(env, ctx, ISA_MIPS64);
4926:
1.1.1.7 root 4927: if (use_icount)
4928: gen_io_start();
4929:
1.1.1.5 root 4930: switch (reg) {
4931: case 0:
4932: switch (sel) {
4933: case 0:
1.1.1.8 root 4934: gen_helper_mtc0_index(arg);
1.1.1.5 root 4935: rn = "Index";
4936: break;
4937: case 1:
1.1.1.6 root 4938: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4939: gen_helper_mtc0_mvpcontrol(arg);
1.1.1.5 root 4940: rn = "MVPControl";
1.1.1.6 root 4941: break;
1.1.1.5 root 4942: case 2:
1.1.1.6 root 4943: check_insn(env, ctx, ASE_MT);
4944: /* ignored */
1.1.1.5 root 4945: rn = "MVPConf0";
1.1.1.6 root 4946: break;
1.1.1.5 root 4947: case 3:
1.1.1.6 root 4948: check_insn(env, ctx, ASE_MT);
4949: /* ignored */
1.1.1.5 root 4950: rn = "MVPConf1";
1.1.1.6 root 4951: break;
1.1.1.5 root 4952: default:
4953: goto die;
4954: }
4955: break;
4956: case 1:
4957: switch (sel) {
4958: case 0:
1.1.1.6 root 4959: /* ignored */
1.1.1.5 root 4960: rn = "Random";
1.1.1.6 root 4961: break;
1.1.1.5 root 4962: case 1:
1.1.1.6 root 4963: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4964: gen_helper_mtc0_vpecontrol(arg);
1.1.1.5 root 4965: rn = "VPEControl";
1.1.1.6 root 4966: break;
1.1.1.5 root 4967: case 2:
1.1.1.6 root 4968: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4969: gen_helper_mtc0_vpeconf0(arg);
1.1.1.5 root 4970: rn = "VPEConf0";
1.1.1.6 root 4971: break;
1.1.1.5 root 4972: case 3:
1.1.1.6 root 4973: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4974: gen_helper_mtc0_vpeconf1(arg);
1.1.1.5 root 4975: rn = "VPEConf1";
1.1.1.6 root 4976: break;
1.1.1.5 root 4977: case 4:
1.1.1.6 root 4978: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4979: gen_helper_mtc0_yqmask(arg);
1.1.1.5 root 4980: rn = "YQMask";
1.1.1.6 root 4981: break;
1.1.1.5 root 4982: case 5:
1.1.1.6 root 4983: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 4984: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
1.1.1.5 root 4985: rn = "VPESchedule";
1.1.1.6 root 4986: break;
1.1.1.5 root 4987: case 6:
1.1.1.6 root 4988: check_insn(env, ctx, ASE_MT);
1.1.1.16! root 4989: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
1.1.1.5 root 4990: rn = "VPEScheFBack";
1.1.1.6 root 4991: break;
1.1.1.5 root 4992: case 7:
1.1.1.6 root 4993: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4994: gen_helper_mtc0_vpeopt(arg);
1.1.1.5 root 4995: rn = "VPEOpt";
1.1.1.6 root 4996: break;
1.1.1.5 root 4997: default:
4998: goto die;
4999: }
5000: break;
5001: case 2:
5002: switch (sel) {
5003: case 0:
1.1.1.8 root 5004: gen_helper_mtc0_entrylo0(arg);
1.1.1.6 root 5005: rn = "EntryLo0";
5006: break;
5007: case 1:
5008: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5009: gen_helper_mtc0_tcstatus(arg);
1.1.1.6 root 5010: rn = "TCStatus";
5011: break;
5012: case 2:
5013: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5014: gen_helper_mtc0_tcbind(arg);
1.1.1.6 root 5015: rn = "TCBind";
5016: break;
1.1.1.5 root 5017: case 3:
1.1.1.6 root 5018: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5019: gen_helper_mtc0_tcrestart(arg);
1.1.1.6 root 5020: rn = "TCRestart";
5021: break;
1.1.1.5 root 5022: case 4:
1.1.1.6 root 5023: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5024: gen_helper_mtc0_tchalt(arg);
1.1.1.6 root 5025: rn = "TCHalt";
5026: break;
1.1.1.5 root 5027: case 5:
1.1.1.6 root 5028: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5029: gen_helper_mtc0_tccontext(arg);
1.1.1.6 root 5030: rn = "TCContext";
5031: break;
1.1.1.5 root 5032: case 6:
1.1.1.6 root 5033: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5034: gen_helper_mtc0_tcschedule(arg);
1.1.1.6 root 5035: rn = "TCSchedule";
5036: break;
1.1.1.5 root 5037: case 7:
1.1.1.6 root 5038: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5039: gen_helper_mtc0_tcschefback(arg);
1.1.1.6 root 5040: rn = "TCScheFBack";
5041: break;
1.1.1.5 root 5042: default:
5043: goto die;
5044: }
5045: break;
5046: case 3:
5047: switch (sel) {
5048: case 0:
1.1.1.8 root 5049: gen_helper_mtc0_entrylo1(arg);
1.1.1.6 root 5050: rn = "EntryLo1";
5051: break;
1.1.1.5 root 5052: default:
5053: goto die;
1.1.1.6 root 5054: }
1.1.1.5 root 5055: break;
5056: case 4:
5057: switch (sel) {
5058: case 0:
1.1.1.8 root 5059: gen_helper_mtc0_context(arg);
1.1.1.6 root 5060: rn = "Context";
5061: break;
5062: case 1:
1.1.1.8 root 5063: // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 5064: rn = "ContextConfig";
5065: // break;
1.1.1.5 root 5066: default:
5067: goto die;
1.1.1.6 root 5068: }
1.1.1.5 root 5069: break;
5070: case 5:
5071: switch (sel) {
5072: case 0:
1.1.1.8 root 5073: gen_helper_mtc0_pagemask(arg);
1.1.1.6 root 5074: rn = "PageMask";
5075: break;
5076: case 1:
5077: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5078: gen_helper_mtc0_pagegrain(arg);
1.1.1.6 root 5079: rn = "PageGrain";
5080: break;
1.1.1.5 root 5081: default:
5082: goto die;
1.1.1.6 root 5083: }
1.1.1.5 root 5084: break;
5085: case 6:
5086: switch (sel) {
5087: case 0:
1.1.1.8 root 5088: gen_helper_mtc0_wired(arg);
1.1.1.6 root 5089: rn = "Wired";
5090: break;
5091: case 1:
5092: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5093: gen_helper_mtc0_srsconf0(arg);
1.1.1.6 root 5094: rn = "SRSConf0";
5095: break;
5096: case 2:
5097: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5098: gen_helper_mtc0_srsconf1(arg);
1.1.1.6 root 5099: rn = "SRSConf1";
5100: break;
1.1.1.5 root 5101: case 3:
1.1.1.6 root 5102: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5103: gen_helper_mtc0_srsconf2(arg);
1.1.1.6 root 5104: rn = "SRSConf2";
5105: break;
1.1.1.5 root 5106: case 4:
1.1.1.6 root 5107: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5108: gen_helper_mtc0_srsconf3(arg);
1.1.1.6 root 5109: rn = "SRSConf3";
5110: break;
1.1.1.5 root 5111: case 5:
1.1.1.6 root 5112: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5113: gen_helper_mtc0_srsconf4(arg);
1.1.1.6 root 5114: rn = "SRSConf4";
5115: break;
1.1.1.5 root 5116: default:
5117: goto die;
1.1.1.6 root 5118: }
1.1.1.5 root 5119: break;
5120: case 7:
5121: switch (sel) {
5122: case 0:
1.1.1.6 root 5123: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5124: gen_helper_mtc0_hwrena(arg);
1.1.1.6 root 5125: rn = "HWREna";
5126: break;
1.1.1.5 root 5127: default:
5128: goto die;
1.1.1.6 root 5129: }
1.1.1.5 root 5130: break;
5131: case 8:
5132: /* ignored */
1.1.1.7 root 5133: rn = "BadVAddr";
1.1.1.5 root 5134: break;
5135: case 9:
5136: switch (sel) {
5137: case 0:
1.1.1.8 root 5138: gen_helper_mtc0_count(arg);
1.1.1.6 root 5139: rn = "Count";
5140: break;
5141: /* 6,7 are implementation dependent */
1.1.1.5 root 5142: default:
5143: goto die;
1.1.1.6 root 5144: }
5145: /* Stop translation as we may have switched the execution mode */
5146: ctx->bstate = BS_STOP;
1.1.1.5 root 5147: break;
5148: case 10:
5149: switch (sel) {
5150: case 0:
1.1.1.8 root 5151: gen_helper_mtc0_entryhi(arg);
1.1.1.6 root 5152: rn = "EntryHi";
5153: break;
1.1.1.5 root 5154: default:
5155: goto die;
1.1.1.6 root 5156: }
1.1.1.5 root 5157: break;
5158: case 11:
5159: switch (sel) {
5160: case 0:
1.1.1.8 root 5161: gen_helper_mtc0_compare(arg);
1.1.1.6 root 5162: rn = "Compare";
5163: break;
5164: /* 6,7 are implementation dependent */
1.1.1.5 root 5165: default:
5166: goto die;
1.1.1.6 root 5167: }
5168: /* Stop translation as we may have switched the execution mode */
5169: ctx->bstate = BS_STOP;
1.1.1.5 root 5170: break;
5171: case 12:
5172: switch (sel) {
5173: case 0:
1.1.1.8 root 5174: save_cpu_state(ctx, 1);
5175: gen_helper_mtc0_status(arg);
1.1.1.6 root 5176: /* BS_STOP isn't good enough here, hflags may have changed. */
5177: gen_save_pc(ctx->pc + 4);
5178: ctx->bstate = BS_EXCP;
5179: rn = "Status";
5180: break;
5181: case 1:
5182: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5183: gen_helper_mtc0_intctl(arg);
1.1.1.6 root 5184: /* Stop translation as we may have switched the execution mode */
5185: ctx->bstate = BS_STOP;
5186: rn = "IntCtl";
5187: break;
5188: case 2:
5189: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5190: gen_helper_mtc0_srsctl(arg);
1.1.1.6 root 5191: /* Stop translation as we may have switched the execution mode */
5192: ctx->bstate = BS_STOP;
5193: rn = "SRSCtl";
5194: break;
1.1.1.5 root 5195: case 3:
1.1.1.6 root 5196: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.16! root 5197: gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
1.1.1.6 root 5198: /* Stop translation as we may have switched the execution mode */
5199: ctx->bstate = BS_STOP;
5200: rn = "SRSMap";
5201: break;
1.1.1.5 root 5202: default:
5203: goto die;
1.1.1.6 root 5204: }
1.1.1.5 root 5205: break;
5206: case 13:
5207: switch (sel) {
5208: case 0:
1.1.1.8 root 5209: save_cpu_state(ctx, 1);
1.1.1.12 root 5210: /* Mark as an IO operation because we may trigger a software
5211: interrupt. */
5212: if (use_icount) {
5213: gen_io_start();
5214: }
1.1.1.8 root 5215: gen_helper_mtc0_cause(arg);
1.1.1.12 root 5216: if (use_icount) {
5217: gen_io_end();
5218: }
5219: /* Stop translation as we may have triggered an intetrupt */
5220: ctx->bstate = BS_STOP;
1.1.1.6 root 5221: rn = "Cause";
5222: break;
1.1.1.5 root 5223: default:
5224: goto die;
1.1.1.6 root 5225: }
1.1.1.5 root 5226: break;
5227: case 14:
5228: switch (sel) {
5229: case 0:
1.1.1.16! root 5230: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
1.1.1.6 root 5231: rn = "EPC";
5232: break;
1.1.1.5 root 5233: default:
5234: goto die;
1.1.1.6 root 5235: }
1.1.1.5 root 5236: break;
5237: case 15:
5238: switch (sel) {
5239: case 0:
1.1.1.6 root 5240: /* ignored */
5241: rn = "PRid";
5242: break;
5243: case 1:
5244: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5245: gen_helper_mtc0_ebase(arg);
1.1.1.6 root 5246: rn = "EBase";
5247: break;
1.1.1.5 root 5248: default:
5249: goto die;
1.1.1.6 root 5250: }
1.1.1.5 root 5251: break;
5252: case 16:
5253: switch (sel) {
5254: case 0:
1.1.1.8 root 5255: gen_helper_mtc0_config0(arg);
1.1.1.5 root 5256: rn = "Config";
1.1.1.6 root 5257: /* Stop translation as we may have switched the execution mode */
5258: ctx->bstate = BS_STOP;
1.1.1.5 root 5259: break;
5260: case 1:
1.1.1.8 root 5261: /* ignored, read only */
1.1.1.5 root 5262: rn = "Config1";
5263: break;
5264: case 2:
1.1.1.8 root 5265: gen_helper_mtc0_config2(arg);
1.1.1.5 root 5266: rn = "Config2";
1.1.1.6 root 5267: /* Stop translation as we may have switched the execution mode */
5268: ctx->bstate = BS_STOP;
1.1.1.5 root 5269: break;
5270: case 3:
1.1.1.6 root 5271: /* ignored */
1.1.1.5 root 5272: rn = "Config3";
5273: break;
5274: /* 6,7 are implementation dependent */
5275: default:
5276: rn = "Invalid config selector";
5277: goto die;
5278: }
5279: break;
5280: case 17:
5281: switch (sel) {
5282: case 0:
1.1.1.9 root 5283: gen_helper_mtc0_lladdr(arg);
1.1.1.6 root 5284: rn = "LLAddr";
5285: break;
1.1.1.5 root 5286: default:
5287: goto die;
5288: }
5289: break;
5290: case 18:
5291: switch (sel) {
1.1.1.6 root 5292: case 0 ... 7:
1.1.1.8 root 5293: gen_helper_1i(mtc0_watchlo, arg, sel);
1.1.1.6 root 5294: rn = "WatchLo";
5295: break;
1.1.1.5 root 5296: default:
5297: goto die;
5298: }
5299: break;
5300: case 19:
5301: switch (sel) {
1.1.1.6 root 5302: case 0 ... 7:
1.1.1.8 root 5303: gen_helper_1i(mtc0_watchhi, arg, sel);
1.1.1.6 root 5304: rn = "WatchHi";
5305: break;
1.1.1.5 root 5306: default:
5307: goto die;
5308: }
5309: break;
5310: case 20:
5311: switch (sel) {
5312: case 0:
1.1.1.6 root 5313: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 5314: gen_helper_mtc0_xcontext(arg);
1.1.1.6 root 5315: rn = "XContext";
5316: break;
1.1.1.5 root 5317: default:
5318: goto die;
5319: }
5320: break;
5321: case 21:
5322: /* Officially reserved, but sel 0 is used for R1x000 framemask */
5323: switch (sel) {
5324: case 0:
1.1.1.8 root 5325: gen_helper_mtc0_framemask(arg);
1.1.1.6 root 5326: rn = "Framemask";
5327: break;
1.1.1.5 root 5328: default:
5329: goto die;
5330: }
5331: break;
5332: case 22:
5333: /* ignored */
5334: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 root 5335: break;
1.1.1.5 root 5336: case 23:
5337: switch (sel) {
5338: case 0:
1.1.1.8 root 5339: gen_helper_mtc0_debug(arg); /* EJTAG support */
1.1.1.6 root 5340: /* BS_STOP isn't good enough here, hflags may have changed. */
5341: gen_save_pc(ctx->pc + 4);
5342: ctx->bstate = BS_EXCP;
5343: rn = "Debug";
5344: break;
5345: case 1:
1.1.1.8 root 5346: // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 5347: /* Stop translation as we may have switched the execution mode */
5348: ctx->bstate = BS_STOP;
5349: rn = "TraceControl";
5350: // break;
5351: case 2:
1.1.1.8 root 5352: // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 5353: /* Stop translation as we may have switched the execution mode */
5354: ctx->bstate = BS_STOP;
5355: rn = "TraceControl2";
5356: // break;
5357: case 3:
1.1.1.8 root 5358: // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 5359: /* Stop translation as we may have switched the execution mode */
5360: ctx->bstate = BS_STOP;
5361: rn = "UserTraceData";
5362: // break;
1.1.1.5 root 5363: case 4:
1.1.1.8 root 5364: // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 5365: /* Stop translation as we may have switched the execution mode */
5366: ctx->bstate = BS_STOP;
5367: rn = "TraceBPC";
5368: // break;
1.1.1.5 root 5369: default:
5370: goto die;
5371: }
5372: break;
5373: case 24:
5374: switch (sel) {
5375: case 0:
1.1.1.7 root 5376: /* EJTAG support */
1.1.1.16! root 5377: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
1.1.1.6 root 5378: rn = "DEPC";
5379: break;
1.1.1.5 root 5380: default:
5381: goto die;
5382: }
5383: break;
5384: case 25:
5385: switch (sel) {
5386: case 0:
1.1.1.8 root 5387: gen_helper_mtc0_performance0(arg);
1.1.1.6 root 5388: rn = "Performance0";
5389: break;
5390: case 1:
1.1.1.8 root 5391: // gen_helper_mtc0_performance1(arg);
1.1.1.6 root 5392: rn = "Performance1";
5393: // break;
5394: case 2:
1.1.1.8 root 5395: // gen_helper_mtc0_performance2(arg);
1.1.1.6 root 5396: rn = "Performance2";
5397: // break;
1.1.1.5 root 5398: case 3:
1.1.1.8 root 5399: // gen_helper_mtc0_performance3(arg);
1.1.1.6 root 5400: rn = "Performance3";
5401: // break;
1.1.1.5 root 5402: case 4:
1.1.1.8 root 5403: // gen_helper_mtc0_performance4(arg);
1.1.1.6 root 5404: rn = "Performance4";
5405: // break;
1.1.1.5 root 5406: case 5:
1.1.1.8 root 5407: // gen_helper_mtc0_performance5(arg);
1.1.1.6 root 5408: rn = "Performance5";
5409: // break;
1.1.1.5 root 5410: case 6:
1.1.1.8 root 5411: // gen_helper_mtc0_performance6(arg);
1.1.1.6 root 5412: rn = "Performance6";
5413: // break;
1.1.1.5 root 5414: case 7:
1.1.1.8 root 5415: // gen_helper_mtc0_performance7(arg);
1.1.1.6 root 5416: rn = "Performance7";
5417: // break;
1.1.1.5 root 5418: default:
5419: goto die;
5420: }
1.1.1.6 root 5421: break;
1.1.1.5 root 5422: case 26:
1.1.1.6 root 5423: /* ignored */
1.1.1.5 root 5424: rn = "ECC";
1.1.1.6 root 5425: break;
1.1.1.5 root 5426: case 27:
5427: switch (sel) {
5428: case 0 ... 3:
1.1.1.6 root 5429: /* ignored */
5430: rn = "CacheErr";
5431: break;
1.1.1.5 root 5432: default:
5433: goto die;
5434: }
1.1.1.6 root 5435: break;
1.1.1.5 root 5436: case 28:
5437: switch (sel) {
5438: case 0:
5439: case 2:
5440: case 4:
5441: case 6:
1.1.1.8 root 5442: gen_helper_mtc0_taglo(arg);
1.1.1.5 root 5443: rn = "TagLo";
5444: break;
5445: case 1:
5446: case 3:
5447: case 5:
5448: case 7:
1.1.1.8 root 5449: gen_helper_mtc0_datalo(arg);
1.1.1.5 root 5450: rn = "DataLo";
5451: break;
5452: default:
5453: goto die;
5454: }
5455: break;
5456: case 29:
5457: switch (sel) {
5458: case 0:
5459: case 2:
5460: case 4:
5461: case 6:
1.1.1.8 root 5462: gen_helper_mtc0_taghi(arg);
1.1.1.5 root 5463: rn = "TagHi";
5464: break;
5465: case 1:
5466: case 3:
5467: case 5:
5468: case 7:
1.1.1.8 root 5469: gen_helper_mtc0_datahi(arg);
1.1.1.5 root 5470: rn = "DataHi";
5471: break;
5472: default:
5473: rn = "invalid sel";
5474: goto die;
5475: }
1.1.1.6 root 5476: break;
1.1.1.5 root 5477: case 30:
5478: switch (sel) {
5479: case 0:
1.1.1.16! root 5480: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
1.1.1.6 root 5481: rn = "ErrorEPC";
5482: break;
1.1.1.5 root 5483: default:
5484: goto die;
5485: }
5486: break;
5487: case 31:
5488: switch (sel) {
5489: case 0:
1.1.1.7 root 5490: /* EJTAG support */
1.1.1.16! root 5491: gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
1.1.1.6 root 5492: rn = "DESAVE";
5493: break;
1.1.1.5 root 5494: default:
5495: goto die;
5496: }
1.1.1.6 root 5497: /* Stop translation as we may have switched the execution mode */
5498: ctx->bstate = BS_STOP;
1.1.1.5 root 5499: break;
5500: default:
1.1.1.6 root 5501: goto die;
1.1.1.5 root 5502: }
1.1.1.13 root 5503: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 5504: LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5505: /* For simplicity assume that all writes can cause interrupts. */
5506: if (use_icount) {
5507: gen_io_end();
5508: ctx->bstate = BS_STOP;
1.1.1.5 root 5509: }
5510: return;
5511:
5512: die:
1.1.1.7 root 5513: LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 5514: generate_exception(ctx, EXCP_RI);
5515: }
1.1.1.6 root 5516: #endif /* TARGET_MIPS64 */
1.1.1.5 root 5517:
1.1.1.16! root 5518: static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
1.1.1.6 root 5519: int u, int sel, int h)
1.1.1.5 root 5520: {
1.1.1.6 root 5521: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.7 root 5522: TCGv t0 = tcg_temp_local_new();
1.1.1.5 root 5523:
1.1.1.6 root 5524: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
1.1.1.7 root 5525: ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5526: (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5527: tcg_gen_movi_tl(t0, -1);
1.1.1.6 root 5528: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5529: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1.1.1.7 root 5530: tcg_gen_movi_tl(t0, -1);
1.1.1.6 root 5531: else if (u == 0) {
5532: switch (rt) {
1.1.1.15 root 5533: case 1:
5534: switch (sel) {
5535: case 1:
5536: gen_helper_mftc0_vpecontrol(t0);
5537: break;
5538: case 2:
5539: gen_helper_mftc0_vpeconf0(t0);
5540: break;
5541: default:
5542: goto die;
5543: break;
5544: }
5545: break;
1.1.1.6 root 5546: case 2:
5547: switch (sel) {
5548: case 1:
1.1.1.7 root 5549: gen_helper_mftc0_tcstatus(t0);
1.1.1.6 root 5550: break;
5551: case 2:
1.1.1.7 root 5552: gen_helper_mftc0_tcbind(t0);
1.1.1.6 root 5553: break;
5554: case 3:
1.1.1.7 root 5555: gen_helper_mftc0_tcrestart(t0);
1.1.1.6 root 5556: break;
5557: case 4:
1.1.1.7 root 5558: gen_helper_mftc0_tchalt(t0);
1.1.1.6 root 5559: break;
5560: case 5:
1.1.1.7 root 5561: gen_helper_mftc0_tccontext(t0);
1.1.1.6 root 5562: break;
5563: case 6:
1.1.1.7 root 5564: gen_helper_mftc0_tcschedule(t0);
1.1.1.6 root 5565: break;
5566: case 7:
1.1.1.7 root 5567: gen_helper_mftc0_tcschefback(t0);
1.1.1.6 root 5568: break;
5569: default:
1.1.1.7 root 5570: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5571: break;
5572: }
5573: break;
5574: case 10:
5575: switch (sel) {
5576: case 0:
1.1.1.7 root 5577: gen_helper_mftc0_entryhi(t0);
1.1.1.6 root 5578: break;
5579: default:
1.1.1.7 root 5580: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5581: break;
5582: }
5583: case 12:
5584: switch (sel) {
5585: case 0:
1.1.1.7 root 5586: gen_helper_mftc0_status(t0);
1.1.1.6 root 5587: break;
5588: default:
1.1.1.7 root 5589: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5590: break;
5591: }
1.1.1.15 root 5592: case 13:
5593: switch (sel) {
5594: case 0:
5595: gen_helper_mftc0_cause(t0);
5596: break;
5597: default:
5598: goto die;
5599: break;
5600: }
5601: break;
5602: case 14:
5603: switch (sel) {
5604: case 0:
5605: gen_helper_mftc0_epc(t0);
5606: break;
5607: default:
5608: goto die;
5609: break;
5610: }
5611: break;
5612: case 15:
5613: switch (sel) {
5614: case 1:
5615: gen_helper_mftc0_ebase(t0);
5616: break;
5617: default:
5618: goto die;
5619: break;
5620: }
5621: break;
5622: case 16:
5623: switch (sel) {
5624: case 0 ... 7:
5625: gen_helper_mftc0_configx(t0, tcg_const_tl(sel));
5626: break;
5627: default:
5628: goto die;
5629: break;
5630: }
5631: break;
1.1.1.6 root 5632: case 23:
5633: switch (sel) {
5634: case 0:
1.1.1.7 root 5635: gen_helper_mftc0_debug(t0);
1.1.1.6 root 5636: break;
5637: default:
1.1.1.7 root 5638: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5639: break;
5640: }
5641: break;
5642: default:
1.1.1.7 root 5643: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5644: }
5645: } else switch (sel) {
5646: /* GPR registers. */
5647: case 0:
1.1.1.7 root 5648: gen_helper_1i(mftgpr, t0, rt);
1.1.1.6 root 5649: break;
5650: /* Auxiliary CPU registers */
5651: case 1:
5652: switch (rt) {
5653: case 0:
1.1.1.7 root 5654: gen_helper_1i(mftlo, t0, 0);
1.1.1.6 root 5655: break;
5656: case 1:
1.1.1.7 root 5657: gen_helper_1i(mfthi, t0, 0);
1.1.1.6 root 5658: break;
5659: case 2:
1.1.1.7 root 5660: gen_helper_1i(mftacx, t0, 0);
1.1.1.6 root 5661: break;
5662: case 4:
1.1.1.7 root 5663: gen_helper_1i(mftlo, t0, 1);
1.1.1.6 root 5664: break;
5665: case 5:
1.1.1.7 root 5666: gen_helper_1i(mfthi, t0, 1);
1.1.1.6 root 5667: break;
5668: case 6:
1.1.1.7 root 5669: gen_helper_1i(mftacx, t0, 1);
1.1.1.6 root 5670: break;
5671: case 8:
1.1.1.7 root 5672: gen_helper_1i(mftlo, t0, 2);
1.1.1.6 root 5673: break;
5674: case 9:
1.1.1.7 root 5675: gen_helper_1i(mfthi, t0, 2);
1.1.1.6 root 5676: break;
5677: case 10:
1.1.1.7 root 5678: gen_helper_1i(mftacx, t0, 2);
1.1.1.6 root 5679: break;
5680: case 12:
1.1.1.7 root 5681: gen_helper_1i(mftlo, t0, 3);
1.1.1.6 root 5682: break;
5683: case 13:
1.1.1.7 root 5684: gen_helper_1i(mfthi, t0, 3);
1.1.1.6 root 5685: break;
5686: case 14:
1.1.1.7 root 5687: gen_helper_1i(mftacx, t0, 3);
1.1.1.6 root 5688: break;
5689: case 16:
1.1.1.7 root 5690: gen_helper_mftdsp(t0);
1.1.1.6 root 5691: break;
5692: default:
5693: goto die;
5694: }
5695: break;
5696: /* Floating point (COP1). */
5697: case 2:
5698: /* XXX: For now we support only a single FPU context. */
5699: if (h == 0) {
1.1.1.7 root 5700: TCGv_i32 fp0 = tcg_temp_new_i32();
5701:
5702: gen_load_fpr32(fp0, rt);
5703: tcg_gen_ext_i32_tl(t0, fp0);
5704: tcg_temp_free_i32(fp0);
1.1.1.6 root 5705: } else {
1.1.1.7 root 5706: TCGv_i32 fp0 = tcg_temp_new_i32();
5707:
5708: gen_load_fpr32h(fp0, rt);
5709: tcg_gen_ext_i32_tl(t0, fp0);
5710: tcg_temp_free_i32(fp0);
1.1.1.6 root 5711: }
5712: break;
5713: case 3:
5714: /* XXX: For now we support only a single FPU context. */
1.1.1.7 root 5715: gen_helper_1i(cfc1, t0, rt);
1.1.1.6 root 5716: break;
5717: /* COP2: Not implemented. */
5718: case 4:
5719: case 5:
5720: /* fall through */
5721: default:
5722: goto die;
5723: }
1.1.1.7 root 5724: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5725: gen_store_gpr(t0, rd);
5726: tcg_temp_free(t0);
1.1.1.6 root 5727: return;
5728:
5729: die:
1.1.1.7 root 5730: tcg_temp_free(t0);
5731: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1.1.1.6 root 5732: generate_exception(ctx, EXCP_RI);
5733: }
5734:
1.1.1.16! root 5735: static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
1.1.1.6 root 5736: int u, int sel, int h)
5737: {
5738: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.7 root 5739: TCGv t0 = tcg_temp_local_new();
1.1.1.6 root 5740:
1.1.1.7 root 5741: gen_load_gpr(t0, rt);
1.1.1.6 root 5742: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
1.1.1.7 root 5743: ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5744: (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1.1.1.6 root 5745: /* NOP */ ;
5746: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5747: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5748: /* NOP */ ;
5749: else if (u == 0) {
5750: switch (rd) {
1.1.1.15 root 5751: case 1:
5752: switch (sel) {
5753: case 1:
5754: gen_helper_mttc0_vpecontrol(t0);
5755: break;
5756: case 2:
5757: gen_helper_mttc0_vpeconf0(t0);
5758: break;
5759: default:
5760: goto die;
5761: break;
5762: }
5763: break;
1.1.1.6 root 5764: case 2:
5765: switch (sel) {
5766: case 1:
1.1.1.7 root 5767: gen_helper_mttc0_tcstatus(t0);
1.1.1.6 root 5768: break;
5769: case 2:
1.1.1.7 root 5770: gen_helper_mttc0_tcbind(t0);
1.1.1.6 root 5771: break;
5772: case 3:
1.1.1.7 root 5773: gen_helper_mttc0_tcrestart(t0);
1.1.1.6 root 5774: break;
5775: case 4:
1.1.1.7 root 5776: gen_helper_mttc0_tchalt(t0);
1.1.1.6 root 5777: break;
5778: case 5:
1.1.1.7 root 5779: gen_helper_mttc0_tccontext(t0);
1.1.1.6 root 5780: break;
5781: case 6:
1.1.1.7 root 5782: gen_helper_mttc0_tcschedule(t0);
1.1.1.6 root 5783: break;
5784: case 7:
1.1.1.7 root 5785: gen_helper_mttc0_tcschefback(t0);
1.1.1.6 root 5786: break;
5787: default:
1.1.1.7 root 5788: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5789: break;
5790: }
5791: break;
5792: case 10:
5793: switch (sel) {
5794: case 0:
1.1.1.7 root 5795: gen_helper_mttc0_entryhi(t0);
1.1.1.6 root 5796: break;
5797: default:
1.1.1.7 root 5798: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5799: break;
5800: }
5801: case 12:
5802: switch (sel) {
5803: case 0:
1.1.1.7 root 5804: gen_helper_mttc0_status(t0);
1.1.1.6 root 5805: break;
5806: default:
1.1.1.7 root 5807: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5808: break;
5809: }
1.1.1.15 root 5810: case 13:
5811: switch (sel) {
5812: case 0:
5813: gen_helper_mttc0_cause(t0);
5814: break;
5815: default:
5816: goto die;
5817: break;
5818: }
5819: break;
5820: case 15:
5821: switch (sel) {
5822: case 1:
5823: gen_helper_mttc0_ebase(t0);
5824: break;
5825: default:
5826: goto die;
5827: break;
5828: }
5829: break;
1.1.1.6 root 5830: case 23:
5831: switch (sel) {
5832: case 0:
1.1.1.7 root 5833: gen_helper_mttc0_debug(t0);
1.1.1.6 root 5834: break;
5835: default:
1.1.1.7 root 5836: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5837: break;
5838: }
5839: break;
5840: default:
1.1.1.7 root 5841: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5842: }
5843: } else switch (sel) {
5844: /* GPR registers. */
5845: case 0:
1.1.1.7 root 5846: gen_helper_1i(mttgpr, t0, rd);
1.1.1.6 root 5847: break;
5848: /* Auxiliary CPU registers */
5849: case 1:
5850: switch (rd) {
5851: case 0:
1.1.1.7 root 5852: gen_helper_1i(mttlo, t0, 0);
1.1.1.6 root 5853: break;
5854: case 1:
1.1.1.7 root 5855: gen_helper_1i(mtthi, t0, 0);
1.1.1.6 root 5856: break;
5857: case 2:
1.1.1.7 root 5858: gen_helper_1i(mttacx, t0, 0);
1.1.1.6 root 5859: break;
5860: case 4:
1.1.1.7 root 5861: gen_helper_1i(mttlo, t0, 1);
1.1.1.6 root 5862: break;
5863: case 5:
1.1.1.7 root 5864: gen_helper_1i(mtthi, t0, 1);
1.1.1.6 root 5865: break;
5866: case 6:
1.1.1.7 root 5867: gen_helper_1i(mttacx, t0, 1);
1.1.1.6 root 5868: break;
5869: case 8:
1.1.1.7 root 5870: gen_helper_1i(mttlo, t0, 2);
1.1.1.6 root 5871: break;
5872: case 9:
1.1.1.7 root 5873: gen_helper_1i(mtthi, t0, 2);
1.1.1.6 root 5874: break;
5875: case 10:
1.1.1.7 root 5876: gen_helper_1i(mttacx, t0, 2);
1.1.1.6 root 5877: break;
5878: case 12:
1.1.1.7 root 5879: gen_helper_1i(mttlo, t0, 3);
1.1.1.6 root 5880: break;
5881: case 13:
1.1.1.7 root 5882: gen_helper_1i(mtthi, t0, 3);
1.1.1.6 root 5883: break;
5884: case 14:
1.1.1.7 root 5885: gen_helper_1i(mttacx, t0, 3);
1.1.1.6 root 5886: break;
5887: case 16:
1.1.1.7 root 5888: gen_helper_mttdsp(t0);
1.1.1.6 root 5889: break;
5890: default:
5891: goto die;
5892: }
5893: break;
5894: /* Floating point (COP1). */
5895: case 2:
5896: /* XXX: For now we support only a single FPU context. */
5897: if (h == 0) {
1.1.1.7 root 5898: TCGv_i32 fp0 = tcg_temp_new_i32();
5899:
5900: tcg_gen_trunc_tl_i32(fp0, t0);
5901: gen_store_fpr32(fp0, rd);
5902: tcg_temp_free_i32(fp0);
1.1.1.6 root 5903: } else {
1.1.1.7 root 5904: TCGv_i32 fp0 = tcg_temp_new_i32();
5905:
5906: tcg_gen_trunc_tl_i32(fp0, t0);
5907: gen_store_fpr32h(fp0, rd);
5908: tcg_temp_free_i32(fp0);
1.1.1.6 root 5909: }
5910: break;
5911: case 3:
5912: /* XXX: For now we support only a single FPU context. */
1.1.1.7 root 5913: gen_helper_1i(ctc1, t0, rd);
1.1.1.6 root 5914: break;
5915: /* COP2: Not implemented. */
5916: case 4:
5917: case 5:
5918: /* fall through */
5919: default:
5920: goto die;
5921: }
1.1.1.7 root 5922: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5923: tcg_temp_free(t0);
1.1.1.6 root 5924: return;
5925:
5926: die:
1.1.1.7 root 5927: tcg_temp_free(t0);
5928: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1.1.1.6 root 5929: generate_exception(ctx, EXCP_RI);
5930: }
5931:
1.1.1.16! root 5932: static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
1.1.1.6 root 5933: {
5934: const char *opn = "ldst";
1.1.1.5 root 5935:
5936: switch (opc) {
5937: case OPC_MFC0:
5938: if (rt == 0) {
1.1.1.6 root 5939: /* Treat as NOP. */
1.1.1.5 root 5940: return;
5941: }
1.1.1.8 root 5942: gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
1.1.1.5 root 5943: opn = "mfc0";
5944: break;
5945: case OPC_MTC0:
1.1.1.7 root 5946: {
1.1.1.8 root 5947: TCGv t0 = tcg_temp_new();
1.1.1.7 root 5948:
5949: gen_load_gpr(t0, rt);
5950: gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5951: tcg_temp_free(t0);
5952: }
1.1.1.5 root 5953: opn = "mtc0";
5954: break;
1.1.1.6 root 5955: #if defined(TARGET_MIPS64)
1.1.1.5 root 5956: case OPC_DMFC0:
1.1.1.6 root 5957: check_insn(env, ctx, ISA_MIPS3);
1.1.1.5 root 5958: if (rt == 0) {
1.1.1.6 root 5959: /* Treat as NOP. */
1.1.1.5 root 5960: return;
5961: }
1.1.1.8 root 5962: gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
1.1.1.5 root 5963: opn = "dmfc0";
5964: break;
5965: case OPC_DMTC0:
1.1.1.6 root 5966: check_insn(env, ctx, ISA_MIPS3);
1.1.1.7 root 5967: {
1.1.1.8 root 5968: TCGv t0 = tcg_temp_new();
1.1.1.7 root 5969:
5970: gen_load_gpr(t0, rt);
5971: gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5972: tcg_temp_free(t0);
5973: }
1.1.1.5 root 5974: opn = "dmtc0";
5975: break;
1.1.1.6 root 5976: #endif
5977: case OPC_MFTR:
5978: check_insn(env, ctx, ASE_MT);
5979: if (rd == 0) {
5980: /* Treat as NOP. */
5981: return;
5982: }
1.1.1.7 root 5983: gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5984: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5985: opn = "mftr";
5986: break;
5987: case OPC_MTTR:
5988: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 5989: gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5990: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5991: opn = "mttr";
5992: break;
1.1.1.5 root 5993: case OPC_TLBWI:
5994: opn = "tlbwi";
1.1.1.8 root 5995: if (!env->tlb->helper_tlbwi)
1.1.1.6 root 5996: goto die;
1.1.1.7 root 5997: gen_helper_tlbwi();
1.1.1.5 root 5998: break;
5999: case OPC_TLBWR:
6000: opn = "tlbwr";
1.1.1.8 root 6001: if (!env->tlb->helper_tlbwr)
1.1.1.6 root 6002: goto die;
1.1.1.7 root 6003: gen_helper_tlbwr();
1.1.1.5 root 6004: break;
6005: case OPC_TLBP:
6006: opn = "tlbp";
1.1.1.8 root 6007: if (!env->tlb->helper_tlbp)
1.1.1.6 root 6008: goto die;
1.1.1.7 root 6009: gen_helper_tlbp();
1.1.1.5 root 6010: break;
6011: case OPC_TLBR:
6012: opn = "tlbr";
1.1.1.8 root 6013: if (!env->tlb->helper_tlbr)
1.1.1.6 root 6014: goto die;
1.1.1.7 root 6015: gen_helper_tlbr();
1.1.1.5 root 6016: break;
6017: case OPC_ERET:
6018: opn = "eret";
1.1.1.6 root 6019: check_insn(env, ctx, ISA_MIPS2);
1.1.1.7 root 6020: gen_helper_eret();
1.1.1.5 root 6021: ctx->bstate = BS_EXCP;
6022: break;
6023: case OPC_DERET:
6024: opn = "deret";
1.1.1.6 root 6025: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 6026: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1.1.1.6 root 6027: MIPS_INVAL(opn);
1.1.1.5 root 6028: generate_exception(ctx, EXCP_RI);
6029: } else {
1.1.1.7 root 6030: gen_helper_deret();
1.1.1.5 root 6031: ctx->bstate = BS_EXCP;
6032: }
6033: break;
6034: case OPC_WAIT:
6035: opn = "wait";
1.1.1.6 root 6036: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
1.1.1.5 root 6037: /* If we get an exception, we want to restart at next instruction */
6038: ctx->pc += 4;
6039: save_cpu_state(ctx, 1);
6040: ctx->pc -= 4;
1.1.1.7 root 6041: gen_helper_wait();
1.1.1.5 root 6042: ctx->bstate = BS_EXCP;
6043: break;
6044: default:
1.1.1.6 root 6045: die:
6046: MIPS_INVAL(opn);
1.1.1.5 root 6047: generate_exception(ctx, EXCP_RI);
6048: return;
6049: }
1.1.1.13 root 6050: (void)opn; /* avoid a compiler warning */
1.1.1.5 root 6051: MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
6052: }
1.1.1.7 root 6053: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 6054:
6055: /* CP1 Branches (before delay slot) */
1.1.1.16! root 6056: static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
1.1.1.6 root 6057: int32_t cc, int32_t offset)
1.1.1.5 root 6058: {
6059: target_ulong btarget;
1.1.1.6 root 6060: const char *opn = "cp1 cond branch";
1.1.1.7 root 6061: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.6 root 6062:
6063: if (cc != 0)
6064: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
1.1.1.5 root 6065:
6066: btarget = ctx->pc + 4 + offset;
6067:
6068: switch (op) {
6069: case OPC_BC1F:
1.1.1.8 root 6070: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6071: tcg_gen_not_i32(t0, t0);
6072: tcg_gen_andi_i32(t0, t0, 1);
6073: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6074: opn = "bc1f";
1.1.1.5 root 6075: goto not_likely;
6076: case OPC_BC1FL:
1.1.1.8 root 6077: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6078: tcg_gen_not_i32(t0, t0);
6079: tcg_gen_andi_i32(t0, t0, 1);
6080: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6081: opn = "bc1fl";
1.1.1.5 root 6082: goto likely;
6083: case OPC_BC1T:
1.1.1.8 root 6084: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6085: tcg_gen_andi_i32(t0, t0, 1);
6086: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6087: opn = "bc1t";
6088: goto not_likely;
1.1.1.5 root 6089: case OPC_BC1TL:
1.1.1.8 root 6090: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6091: tcg_gen_andi_i32(t0, t0, 1);
6092: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6093: opn = "bc1tl";
1.1.1.5 root 6094: likely:
6095: ctx->hflags |= MIPS_HFLAG_BL;
1.1.1.6 root 6096: break;
6097: case OPC_BC1FANY2:
1.1.1.7 root 6098: {
1.1.1.8 root 6099: TCGv_i32 t1 = tcg_temp_new_i32();
6100: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6101: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
1.1.1.16! root 6102: tcg_gen_nand_i32(t0, t0, t1);
1.1.1.8 root 6103: tcg_temp_free_i32(t1);
6104: tcg_gen_andi_i32(t0, t0, 1);
6105: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6106: }
1.1.1.6 root 6107: opn = "bc1any2f";
6108: goto not_likely;
6109: case OPC_BC1TANY2:
1.1.1.7 root 6110: {
1.1.1.8 root 6111: TCGv_i32 t1 = tcg_temp_new_i32();
6112: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6113: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6114: tcg_gen_or_i32(t0, t0, t1);
6115: tcg_temp_free_i32(t1);
6116: tcg_gen_andi_i32(t0, t0, 1);
6117: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6118: }
1.1.1.6 root 6119: opn = "bc1any2t";
6120: goto not_likely;
6121: case OPC_BC1FANY4:
1.1.1.7 root 6122: {
1.1.1.8 root 6123: TCGv_i32 t1 = tcg_temp_new_i32();
6124: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6125: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
1.1.1.16! root 6126: tcg_gen_and_i32(t0, t0, t1);
1.1.1.8 root 6127: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
1.1.1.16! root 6128: tcg_gen_and_i32(t0, t0, t1);
1.1.1.8 root 6129: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
1.1.1.16! root 6130: tcg_gen_nand_i32(t0, t0, t1);
1.1.1.8 root 6131: tcg_temp_free_i32(t1);
6132: tcg_gen_andi_i32(t0, t0, 1);
6133: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6134: }
1.1.1.6 root 6135: opn = "bc1any4f";
6136: goto not_likely;
6137: case OPC_BC1TANY4:
1.1.1.7 root 6138: {
1.1.1.8 root 6139: TCGv_i32 t1 = tcg_temp_new_i32();
6140: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6141: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6142: tcg_gen_or_i32(t0, t0, t1);
6143: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6144: tcg_gen_or_i32(t0, t0, t1);
6145: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6146: tcg_gen_or_i32(t0, t0, t1);
6147: tcg_temp_free_i32(t1);
6148: tcg_gen_andi_i32(t0, t0, 1);
6149: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6150: }
1.1.1.6 root 6151: opn = "bc1any4t";
6152: not_likely:
6153: ctx->hflags |= MIPS_HFLAG_BC;
1.1.1.5 root 6154: break;
1.1.1.6 root 6155: default:
6156: MIPS_INVAL(opn);
6157: generate_exception (ctx, EXCP_RI);
1.1.1.7 root 6158: goto out;
1.1.1.5 root 6159: }
1.1.1.13 root 6160: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 6161: MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
1.1.1.5 root 6162: ctx->hflags, btarget);
6163: ctx->btarget = btarget;
1.1.1.7 root 6164:
6165: out:
6166: tcg_temp_free_i32(t0);
1.1.1.5 root 6167: }
6168:
6169: /* Coprocessor 1 (FPU) */
1.1.1.6 root 6170:
6171: #define FOP(func, fmt) (((fmt) << 21) | (func))
6172:
1.1.1.12 root 6173: enum fopcode {
6174: OPC_ADD_S = FOP(0, FMT_S),
6175: OPC_SUB_S = FOP(1, FMT_S),
6176: OPC_MUL_S = FOP(2, FMT_S),
6177: OPC_DIV_S = FOP(3, FMT_S),
6178: OPC_SQRT_S = FOP(4, FMT_S),
6179: OPC_ABS_S = FOP(5, FMT_S),
6180: OPC_MOV_S = FOP(6, FMT_S),
6181: OPC_NEG_S = FOP(7, FMT_S),
6182: OPC_ROUND_L_S = FOP(8, FMT_S),
6183: OPC_TRUNC_L_S = FOP(9, FMT_S),
6184: OPC_CEIL_L_S = FOP(10, FMT_S),
6185: OPC_FLOOR_L_S = FOP(11, FMT_S),
6186: OPC_ROUND_W_S = FOP(12, FMT_S),
6187: OPC_TRUNC_W_S = FOP(13, FMT_S),
6188: OPC_CEIL_W_S = FOP(14, FMT_S),
6189: OPC_FLOOR_W_S = FOP(15, FMT_S),
6190: OPC_MOVCF_S = FOP(17, FMT_S),
6191: OPC_MOVZ_S = FOP(18, FMT_S),
6192: OPC_MOVN_S = FOP(19, FMT_S),
6193: OPC_RECIP_S = FOP(21, FMT_S),
6194: OPC_RSQRT_S = FOP(22, FMT_S),
6195: OPC_RECIP2_S = FOP(28, FMT_S),
6196: OPC_RECIP1_S = FOP(29, FMT_S),
6197: OPC_RSQRT1_S = FOP(30, FMT_S),
6198: OPC_RSQRT2_S = FOP(31, FMT_S),
6199: OPC_CVT_D_S = FOP(33, FMT_S),
6200: OPC_CVT_W_S = FOP(36, FMT_S),
6201: OPC_CVT_L_S = FOP(37, FMT_S),
6202: OPC_CVT_PS_S = FOP(38, FMT_S),
6203: OPC_CMP_F_S = FOP (48, FMT_S),
6204: OPC_CMP_UN_S = FOP (49, FMT_S),
6205: OPC_CMP_EQ_S = FOP (50, FMT_S),
6206: OPC_CMP_UEQ_S = FOP (51, FMT_S),
6207: OPC_CMP_OLT_S = FOP (52, FMT_S),
6208: OPC_CMP_ULT_S = FOP (53, FMT_S),
6209: OPC_CMP_OLE_S = FOP (54, FMT_S),
6210: OPC_CMP_ULE_S = FOP (55, FMT_S),
6211: OPC_CMP_SF_S = FOP (56, FMT_S),
6212: OPC_CMP_NGLE_S = FOP (57, FMT_S),
6213: OPC_CMP_SEQ_S = FOP (58, FMT_S),
6214: OPC_CMP_NGL_S = FOP (59, FMT_S),
6215: OPC_CMP_LT_S = FOP (60, FMT_S),
6216: OPC_CMP_NGE_S = FOP (61, FMT_S),
6217: OPC_CMP_LE_S = FOP (62, FMT_S),
6218: OPC_CMP_NGT_S = FOP (63, FMT_S),
6219:
6220: OPC_ADD_D = FOP(0, FMT_D),
6221: OPC_SUB_D = FOP(1, FMT_D),
6222: OPC_MUL_D = FOP(2, FMT_D),
6223: OPC_DIV_D = FOP(3, FMT_D),
6224: OPC_SQRT_D = FOP(4, FMT_D),
6225: OPC_ABS_D = FOP(5, FMT_D),
6226: OPC_MOV_D = FOP(6, FMT_D),
6227: OPC_NEG_D = FOP(7, FMT_D),
6228: OPC_ROUND_L_D = FOP(8, FMT_D),
6229: OPC_TRUNC_L_D = FOP(9, FMT_D),
6230: OPC_CEIL_L_D = FOP(10, FMT_D),
6231: OPC_FLOOR_L_D = FOP(11, FMT_D),
6232: OPC_ROUND_W_D = FOP(12, FMT_D),
6233: OPC_TRUNC_W_D = FOP(13, FMT_D),
6234: OPC_CEIL_W_D = FOP(14, FMT_D),
6235: OPC_FLOOR_W_D = FOP(15, FMT_D),
6236: OPC_MOVCF_D = FOP(17, FMT_D),
6237: OPC_MOVZ_D = FOP(18, FMT_D),
6238: OPC_MOVN_D = FOP(19, FMT_D),
6239: OPC_RECIP_D = FOP(21, FMT_D),
6240: OPC_RSQRT_D = FOP(22, FMT_D),
6241: OPC_RECIP2_D = FOP(28, FMT_D),
6242: OPC_RECIP1_D = FOP(29, FMT_D),
6243: OPC_RSQRT1_D = FOP(30, FMT_D),
6244: OPC_RSQRT2_D = FOP(31, FMT_D),
6245: OPC_CVT_S_D = FOP(32, FMT_D),
6246: OPC_CVT_W_D = FOP(36, FMT_D),
6247: OPC_CVT_L_D = FOP(37, FMT_D),
6248: OPC_CMP_F_D = FOP (48, FMT_D),
6249: OPC_CMP_UN_D = FOP (49, FMT_D),
6250: OPC_CMP_EQ_D = FOP (50, FMT_D),
6251: OPC_CMP_UEQ_D = FOP (51, FMT_D),
6252: OPC_CMP_OLT_D = FOP (52, FMT_D),
6253: OPC_CMP_ULT_D = FOP (53, FMT_D),
6254: OPC_CMP_OLE_D = FOP (54, FMT_D),
6255: OPC_CMP_ULE_D = FOP (55, FMT_D),
6256: OPC_CMP_SF_D = FOP (56, FMT_D),
6257: OPC_CMP_NGLE_D = FOP (57, FMT_D),
6258: OPC_CMP_SEQ_D = FOP (58, FMT_D),
6259: OPC_CMP_NGL_D = FOP (59, FMT_D),
6260: OPC_CMP_LT_D = FOP (60, FMT_D),
6261: OPC_CMP_NGE_D = FOP (61, FMT_D),
6262: OPC_CMP_LE_D = FOP (62, FMT_D),
6263: OPC_CMP_NGT_D = FOP (63, FMT_D),
6264:
6265: OPC_CVT_S_W = FOP(32, FMT_W),
6266: OPC_CVT_D_W = FOP(33, FMT_W),
6267: OPC_CVT_S_L = FOP(32, FMT_L),
6268: OPC_CVT_D_L = FOP(33, FMT_L),
6269: OPC_CVT_PS_PW = FOP(38, FMT_W),
6270:
6271: OPC_ADD_PS = FOP(0, FMT_PS),
6272: OPC_SUB_PS = FOP(1, FMT_PS),
6273: OPC_MUL_PS = FOP(2, FMT_PS),
6274: OPC_DIV_PS = FOP(3, FMT_PS),
6275: OPC_ABS_PS = FOP(5, FMT_PS),
6276: OPC_MOV_PS = FOP(6, FMT_PS),
6277: OPC_NEG_PS = FOP(7, FMT_PS),
6278: OPC_MOVCF_PS = FOP(17, FMT_PS),
6279: OPC_MOVZ_PS = FOP(18, FMT_PS),
6280: OPC_MOVN_PS = FOP(19, FMT_PS),
6281: OPC_ADDR_PS = FOP(24, FMT_PS),
6282: OPC_MULR_PS = FOP(26, FMT_PS),
6283: OPC_RECIP2_PS = FOP(28, FMT_PS),
6284: OPC_RECIP1_PS = FOP(29, FMT_PS),
6285: OPC_RSQRT1_PS = FOP(30, FMT_PS),
6286: OPC_RSQRT2_PS = FOP(31, FMT_PS),
6287:
6288: OPC_CVT_S_PU = FOP(32, FMT_PS),
6289: OPC_CVT_PW_PS = FOP(36, FMT_PS),
6290: OPC_CVT_S_PL = FOP(40, FMT_PS),
6291: OPC_PLL_PS = FOP(44, FMT_PS),
6292: OPC_PLU_PS = FOP(45, FMT_PS),
6293: OPC_PUL_PS = FOP(46, FMT_PS),
6294: OPC_PUU_PS = FOP(47, FMT_PS),
6295: OPC_CMP_F_PS = FOP (48, FMT_PS),
6296: OPC_CMP_UN_PS = FOP (49, FMT_PS),
6297: OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6298: OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6299: OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6300: OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6301: OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6302: OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6303: OPC_CMP_SF_PS = FOP (56, FMT_PS),
6304: OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6305: OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6306: OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6307: OPC_CMP_LT_PS = FOP (60, FMT_PS),
6308: OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6309: OPC_CMP_LE_PS = FOP (62, FMT_PS),
6310: OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6311: };
6312:
1.1.1.5 root 6313: static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6314: {
1.1.1.6 root 6315: const char *opn = "cp1 move";
1.1.1.8 root 6316: TCGv t0 = tcg_temp_new();
1.1.1.5 root 6317:
6318: switch (opc) {
6319: case OPC_MFC1:
1.1.1.7 root 6320: {
6321: TCGv_i32 fp0 = tcg_temp_new_i32();
6322:
6323: gen_load_fpr32(fp0, fs);
6324: tcg_gen_ext_i32_tl(t0, fp0);
6325: tcg_temp_free_i32(fp0);
6326: }
6327: gen_store_gpr(t0, rt);
1.1.1.5 root 6328: opn = "mfc1";
6329: break;
6330: case OPC_MTC1:
1.1.1.7 root 6331: gen_load_gpr(t0, rt);
6332: {
6333: TCGv_i32 fp0 = tcg_temp_new_i32();
6334:
6335: tcg_gen_trunc_tl_i32(fp0, t0);
6336: gen_store_fpr32(fp0, fs);
6337: tcg_temp_free_i32(fp0);
6338: }
1.1.1.5 root 6339: opn = "mtc1";
6340: break;
6341: case OPC_CFC1:
1.1.1.7 root 6342: gen_helper_1i(cfc1, t0, fs);
6343: gen_store_gpr(t0, rt);
1.1.1.5 root 6344: opn = "cfc1";
6345: break;
6346: case OPC_CTC1:
1.1.1.7 root 6347: gen_load_gpr(t0, rt);
6348: gen_helper_1i(ctc1, t0, fs);
1.1.1.5 root 6349: opn = "ctc1";
6350: break;
1.1.1.8 root 6351: #if defined(TARGET_MIPS64)
1.1.1.5 root 6352: case OPC_DMFC1:
1.1.1.8 root 6353: gen_load_fpr64(ctx, t0, fs);
1.1.1.7 root 6354: gen_store_gpr(t0, rt);
1.1.1.6 root 6355: opn = "dmfc1";
6356: break;
1.1.1.5 root 6357: case OPC_DMTC1:
1.1.1.7 root 6358: gen_load_gpr(t0, rt);
1.1.1.8 root 6359: gen_store_fpr64(ctx, t0, fs);
1.1.1.6 root 6360: opn = "dmtc1";
6361: break;
1.1.1.8 root 6362: #endif
1.1.1.6 root 6363: case OPC_MFHC1:
1.1.1.7 root 6364: {
6365: TCGv_i32 fp0 = tcg_temp_new_i32();
6366:
6367: gen_load_fpr32h(fp0, fs);
6368: tcg_gen_ext_i32_tl(t0, fp0);
6369: tcg_temp_free_i32(fp0);
6370: }
6371: gen_store_gpr(t0, rt);
1.1.1.6 root 6372: opn = "mfhc1";
6373: break;
6374: case OPC_MTHC1:
1.1.1.7 root 6375: gen_load_gpr(t0, rt);
6376: {
6377: TCGv_i32 fp0 = tcg_temp_new_i32();
6378:
6379: tcg_gen_trunc_tl_i32(fp0, t0);
6380: gen_store_fpr32h(fp0, fs);
6381: tcg_temp_free_i32(fp0);
6382: }
1.1.1.6 root 6383: opn = "mthc1";
6384: break;
1.1.1.5 root 6385: default:
1.1.1.6 root 6386: MIPS_INVAL(opn);
6387: generate_exception (ctx, EXCP_RI);
1.1.1.7 root 6388: goto out;
1.1.1.4 root 6389: }
1.1.1.13 root 6390: (void)opn; /* avoid a compiler warning */
1.1.1.4 root 6391: MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
1.1.1.7 root 6392:
6393: out:
6394: tcg_temp_free(t0);
1.1.1.4 root 6395: }
6396:
1.1.1.6 root 6397: static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6398: {
1.1.1.8 root 6399: int l1;
1.1.1.7 root 6400: TCGCond cond;
1.1.1.8 root 6401: TCGv_i32 t0;
6402:
6403: if (rd == 0) {
6404: /* Treat as NOP. */
6405: return;
6406: }
1.1.1.7 root 6407:
6408: if (tf)
6409: cond = TCG_COND_EQ;
6410: else
6411: cond = TCG_COND_NE;
6412:
1.1.1.8 root 6413: l1 = gen_new_label();
6414: t0 = tcg_temp_new_i32();
6415: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6416: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6417: tcg_temp_free_i32(t0);
6418: if (rs == 0) {
6419: tcg_gen_movi_tl(cpu_gpr[rd], 0);
6420: } else {
6421: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6422: }
1.1.1.7 root 6423: gen_set_label(l1);
6424: }
6425:
6426: static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6427: {
6428: int cond;
1.1.1.8 root 6429: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 6430: int l1 = gen_new_label();
6431:
6432: if (tf)
6433: cond = TCG_COND_EQ;
6434: else
6435: cond = TCG_COND_NE;
6436:
1.1.1.8 root 6437: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6438: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6439: gen_load_fpr32(t0, fs);
6440: gen_store_fpr32(t0, fd);
1.1.1.7 root 6441: gen_set_label(l1);
1.1.1.8 root 6442: tcg_temp_free_i32(t0);
1.1.1.7 root 6443: }
6444:
6445: static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6446: {
6447: int cond;
1.1.1.8 root 6448: TCGv_i32 t0 = tcg_temp_new_i32();
6449: TCGv_i64 fp0;
1.1.1.7 root 6450: int l1 = gen_new_label();
6451:
6452: if (tf)
6453: cond = TCG_COND_EQ;
6454: else
6455: cond = TCG_COND_NE;
6456:
1.1.1.8 root 6457: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6458: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6459: tcg_temp_free_i32(t0);
6460: fp0 = tcg_temp_new_i64();
1.1.1.7 root 6461: gen_load_fpr64(ctx, fp0, fs);
6462: gen_store_fpr64(ctx, fp0, fd);
6463: tcg_temp_free_i64(fp0);
1.1.1.8 root 6464: gen_set_label(l1);
1.1.1.7 root 6465: }
6466:
6467: static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6468: {
6469: int cond;
1.1.1.8 root 6470: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 6471: int l1 = gen_new_label();
6472: int l2 = gen_new_label();
1.1.1.4 root 6473:
1.1.1.7 root 6474: if (tf)
6475: cond = TCG_COND_EQ;
1.1.1.6 root 6476: else
1.1.1.7 root 6477: cond = TCG_COND_NE;
6478:
1.1.1.8 root 6479: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6480: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6481: gen_load_fpr32(t0, fs);
6482: gen_store_fpr32(t0, fd);
1.1.1.7 root 6483: gen_set_label(l1);
6484:
1.1.1.8 root 6485: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
6486: tcg_gen_brcondi_i32(cond, t0, 0, l2);
6487: gen_load_fpr32h(t0, fs);
6488: gen_store_fpr32h(t0, fd);
6489: tcg_temp_free_i32(t0);
1.1.1.7 root 6490: gen_set_label(l2);
1.1.1.6 root 6491: }
6492:
1.1.1.4 root 6493:
1.1.1.12 root 6494: static void gen_farith (DisasContext *ctx, enum fopcode op1,
1.1.1.6 root 6495: int ft, int fs, int fd, int cc)
1.1.1.4 root 6496: {
1.1.1.6 root 6497: const char *opn = "farith";
1.1.1.4 root 6498: const char *condnames[] = {
6499: "c.f",
6500: "c.un",
6501: "c.eq",
6502: "c.ueq",
6503: "c.olt",
6504: "c.ult",
6505: "c.ole",
6506: "c.ule",
6507: "c.sf",
6508: "c.ngle",
6509: "c.seq",
6510: "c.ngl",
6511: "c.lt",
6512: "c.nge",
6513: "c.le",
6514: "c.ngt",
6515: };
1.1.1.6 root 6516: const char *condnames_abs[] = {
6517: "cabs.f",
6518: "cabs.un",
6519: "cabs.eq",
6520: "cabs.ueq",
6521: "cabs.olt",
6522: "cabs.ult",
6523: "cabs.ole",
6524: "cabs.ule",
6525: "cabs.sf",
6526: "cabs.ngle",
6527: "cabs.seq",
6528: "cabs.ngl",
6529: "cabs.lt",
6530: "cabs.nge",
6531: "cabs.le",
6532: "cabs.ngt",
6533: };
6534: enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
1.1.1.5 root 6535: uint32_t func = ctx->opcode & 0x3f;
6536:
1.1.1.12 root 6537: switch (op1) {
6538: case OPC_ADD_S:
1.1.1.7 root 6539: {
6540: TCGv_i32 fp0 = tcg_temp_new_i32();
6541: TCGv_i32 fp1 = tcg_temp_new_i32();
6542:
6543: gen_load_fpr32(fp0, fs);
6544: gen_load_fpr32(fp1, ft);
6545: gen_helper_float_add_s(fp0, fp0, fp1);
6546: tcg_temp_free_i32(fp1);
6547: gen_store_fpr32(fp0, fd);
6548: tcg_temp_free_i32(fp0);
6549: }
1.1.1.6 root 6550: opn = "add.s";
6551: optype = BINOP;
6552: break;
1.1.1.12 root 6553: case OPC_SUB_S:
1.1.1.7 root 6554: {
6555: TCGv_i32 fp0 = tcg_temp_new_i32();
6556: TCGv_i32 fp1 = tcg_temp_new_i32();
6557:
6558: gen_load_fpr32(fp0, fs);
6559: gen_load_fpr32(fp1, ft);
6560: gen_helper_float_sub_s(fp0, fp0, fp1);
6561: tcg_temp_free_i32(fp1);
6562: gen_store_fpr32(fp0, fd);
6563: tcg_temp_free_i32(fp0);
6564: }
1.1.1.6 root 6565: opn = "sub.s";
6566: optype = BINOP;
6567: break;
1.1.1.12 root 6568: case OPC_MUL_S:
1.1.1.7 root 6569: {
6570: TCGv_i32 fp0 = tcg_temp_new_i32();
6571: TCGv_i32 fp1 = tcg_temp_new_i32();
6572:
6573: gen_load_fpr32(fp0, fs);
6574: gen_load_fpr32(fp1, ft);
6575: gen_helper_float_mul_s(fp0, fp0, fp1);
6576: tcg_temp_free_i32(fp1);
6577: gen_store_fpr32(fp0, fd);
6578: tcg_temp_free_i32(fp0);
6579: }
1.1.1.6 root 6580: opn = "mul.s";
6581: optype = BINOP;
6582: break;
1.1.1.12 root 6583: case OPC_DIV_S:
1.1.1.7 root 6584: {
6585: TCGv_i32 fp0 = tcg_temp_new_i32();
6586: TCGv_i32 fp1 = tcg_temp_new_i32();
6587:
6588: gen_load_fpr32(fp0, fs);
6589: gen_load_fpr32(fp1, ft);
6590: gen_helper_float_div_s(fp0, fp0, fp1);
6591: tcg_temp_free_i32(fp1);
6592: gen_store_fpr32(fp0, fd);
6593: tcg_temp_free_i32(fp0);
6594: }
1.1.1.6 root 6595: opn = "div.s";
6596: optype = BINOP;
6597: break;
1.1.1.12 root 6598: case OPC_SQRT_S:
1.1.1.7 root 6599: {
6600: TCGv_i32 fp0 = tcg_temp_new_i32();
6601:
6602: gen_load_fpr32(fp0, fs);
6603: gen_helper_float_sqrt_s(fp0, fp0);
6604: gen_store_fpr32(fp0, fd);
6605: tcg_temp_free_i32(fp0);
6606: }
1.1.1.6 root 6607: opn = "sqrt.s";
6608: break;
1.1.1.12 root 6609: case OPC_ABS_S:
1.1.1.7 root 6610: {
6611: TCGv_i32 fp0 = tcg_temp_new_i32();
6612:
6613: gen_load_fpr32(fp0, fs);
6614: gen_helper_float_abs_s(fp0, fp0);
6615: gen_store_fpr32(fp0, fd);
6616: tcg_temp_free_i32(fp0);
6617: }
1.1.1.6 root 6618: opn = "abs.s";
6619: break;
1.1.1.12 root 6620: case OPC_MOV_S:
1.1.1.7 root 6621: {
6622: TCGv_i32 fp0 = tcg_temp_new_i32();
6623:
6624: gen_load_fpr32(fp0, fs);
6625: gen_store_fpr32(fp0, fd);
6626: tcg_temp_free_i32(fp0);
6627: }
1.1.1.6 root 6628: opn = "mov.s";
6629: break;
1.1.1.12 root 6630: case OPC_NEG_S:
1.1.1.7 root 6631: {
6632: TCGv_i32 fp0 = tcg_temp_new_i32();
6633:
6634: gen_load_fpr32(fp0, fs);
6635: gen_helper_float_chs_s(fp0, fp0);
6636: gen_store_fpr32(fp0, fd);
6637: tcg_temp_free_i32(fp0);
6638: }
1.1.1.6 root 6639: opn = "neg.s";
6640: break;
1.1.1.12 root 6641: case OPC_ROUND_L_S:
1.1.1.6 root 6642: check_cp1_64bitmode(ctx);
1.1.1.7 root 6643: {
6644: TCGv_i32 fp32 = tcg_temp_new_i32();
6645: TCGv_i64 fp64 = tcg_temp_new_i64();
6646:
6647: gen_load_fpr32(fp32, fs);
6648: gen_helper_float_roundl_s(fp64, fp32);
6649: tcg_temp_free_i32(fp32);
6650: gen_store_fpr64(ctx, fp64, fd);
6651: tcg_temp_free_i64(fp64);
6652: }
1.1.1.6 root 6653: opn = "round.l.s";
6654: break;
1.1.1.12 root 6655: case OPC_TRUNC_L_S:
1.1.1.6 root 6656: check_cp1_64bitmode(ctx);
1.1.1.7 root 6657: {
6658: TCGv_i32 fp32 = tcg_temp_new_i32();
6659: TCGv_i64 fp64 = tcg_temp_new_i64();
6660:
6661: gen_load_fpr32(fp32, fs);
6662: gen_helper_float_truncl_s(fp64, fp32);
6663: tcg_temp_free_i32(fp32);
6664: gen_store_fpr64(ctx, fp64, fd);
6665: tcg_temp_free_i64(fp64);
6666: }
1.1.1.6 root 6667: opn = "trunc.l.s";
6668: break;
1.1.1.12 root 6669: case OPC_CEIL_L_S:
1.1.1.6 root 6670: check_cp1_64bitmode(ctx);
1.1.1.7 root 6671: {
6672: TCGv_i32 fp32 = tcg_temp_new_i32();
6673: TCGv_i64 fp64 = tcg_temp_new_i64();
6674:
6675: gen_load_fpr32(fp32, fs);
6676: gen_helper_float_ceill_s(fp64, fp32);
6677: tcg_temp_free_i32(fp32);
6678: gen_store_fpr64(ctx, fp64, fd);
6679: tcg_temp_free_i64(fp64);
6680: }
1.1.1.6 root 6681: opn = "ceil.l.s";
6682: break;
1.1.1.12 root 6683: case OPC_FLOOR_L_S:
1.1.1.6 root 6684: check_cp1_64bitmode(ctx);
1.1.1.7 root 6685: {
6686: TCGv_i32 fp32 = tcg_temp_new_i32();
6687: TCGv_i64 fp64 = tcg_temp_new_i64();
6688:
6689: gen_load_fpr32(fp32, fs);
6690: gen_helper_float_floorl_s(fp64, fp32);
6691: tcg_temp_free_i32(fp32);
6692: gen_store_fpr64(ctx, fp64, fd);
6693: tcg_temp_free_i64(fp64);
6694: }
1.1.1.6 root 6695: opn = "floor.l.s";
6696: break;
1.1.1.12 root 6697: case OPC_ROUND_W_S:
1.1.1.7 root 6698: {
6699: TCGv_i32 fp0 = tcg_temp_new_i32();
6700:
6701: gen_load_fpr32(fp0, fs);
6702: gen_helper_float_roundw_s(fp0, fp0);
6703: gen_store_fpr32(fp0, fd);
6704: tcg_temp_free_i32(fp0);
6705: }
1.1.1.6 root 6706: opn = "round.w.s";
6707: break;
1.1.1.12 root 6708: case OPC_TRUNC_W_S:
1.1.1.7 root 6709: {
6710: TCGv_i32 fp0 = tcg_temp_new_i32();
6711:
6712: gen_load_fpr32(fp0, fs);
6713: gen_helper_float_truncw_s(fp0, fp0);
6714: gen_store_fpr32(fp0, fd);
6715: tcg_temp_free_i32(fp0);
6716: }
1.1.1.6 root 6717: opn = "trunc.w.s";
6718: break;
1.1.1.12 root 6719: case OPC_CEIL_W_S:
1.1.1.7 root 6720: {
6721: TCGv_i32 fp0 = tcg_temp_new_i32();
6722:
6723: gen_load_fpr32(fp0, fs);
6724: gen_helper_float_ceilw_s(fp0, fp0);
6725: gen_store_fpr32(fp0, fd);
6726: tcg_temp_free_i32(fp0);
6727: }
1.1.1.6 root 6728: opn = "ceil.w.s";
6729: break;
1.1.1.12 root 6730: case OPC_FLOOR_W_S:
1.1.1.7 root 6731: {
6732: TCGv_i32 fp0 = tcg_temp_new_i32();
6733:
6734: gen_load_fpr32(fp0, fs);
6735: gen_helper_float_floorw_s(fp0, fp0);
6736: gen_store_fpr32(fp0, fd);
6737: tcg_temp_free_i32(fp0);
6738: }
1.1.1.6 root 6739: opn = "floor.w.s";
6740: break;
1.1.1.12 root 6741: case OPC_MOVCF_S:
1.1.1.7 root 6742: gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 6743: opn = "movcf.s";
6744: break;
1.1.1.12 root 6745: case OPC_MOVZ_S:
1.1.1.7 root 6746: {
6747: int l1 = gen_new_label();
1.1.1.8 root 6748: TCGv_i32 fp0;
1.1.1.7 root 6749:
1.1.1.8 root 6750: if (ft != 0) {
6751: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6752: }
6753: fp0 = tcg_temp_new_i32();
1.1.1.7 root 6754: gen_load_fpr32(fp0, fs);
6755: gen_store_fpr32(fp0, fd);
6756: tcg_temp_free_i32(fp0);
6757: gen_set_label(l1);
6758: }
1.1.1.6 root 6759: opn = "movz.s";
6760: break;
1.1.1.12 root 6761: case OPC_MOVN_S:
1.1.1.7 root 6762: {
6763: int l1 = gen_new_label();
1.1.1.8 root 6764: TCGv_i32 fp0;
1.1.1.7 root 6765:
1.1.1.8 root 6766: if (ft != 0) {
6767: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6768: fp0 = tcg_temp_new_i32();
6769: gen_load_fpr32(fp0, fs);
6770: gen_store_fpr32(fp0, fd);
6771: tcg_temp_free_i32(fp0);
6772: gen_set_label(l1);
6773: }
1.1.1.7 root 6774: }
1.1.1.6 root 6775: opn = "movn.s";
6776: break;
1.1.1.12 root 6777: case OPC_RECIP_S:
1.1.1.6 root 6778: check_cop1x(ctx);
1.1.1.7 root 6779: {
6780: TCGv_i32 fp0 = tcg_temp_new_i32();
6781:
6782: gen_load_fpr32(fp0, fs);
6783: gen_helper_float_recip_s(fp0, fp0);
6784: gen_store_fpr32(fp0, fd);
6785: tcg_temp_free_i32(fp0);
6786: }
1.1.1.6 root 6787: opn = "recip.s";
6788: break;
1.1.1.12 root 6789: case OPC_RSQRT_S:
1.1.1.6 root 6790: check_cop1x(ctx);
1.1.1.7 root 6791: {
6792: TCGv_i32 fp0 = tcg_temp_new_i32();
6793:
6794: gen_load_fpr32(fp0, fs);
6795: gen_helper_float_rsqrt_s(fp0, fp0);
6796: gen_store_fpr32(fp0, fd);
6797: tcg_temp_free_i32(fp0);
6798: }
1.1.1.6 root 6799: opn = "rsqrt.s";
6800: break;
1.1.1.12 root 6801: case OPC_RECIP2_S:
1.1.1.6 root 6802: check_cp1_64bitmode(ctx);
1.1.1.7 root 6803: {
6804: TCGv_i32 fp0 = tcg_temp_new_i32();
6805: TCGv_i32 fp1 = tcg_temp_new_i32();
6806:
6807: gen_load_fpr32(fp0, fs);
6808: gen_load_fpr32(fp1, fd);
6809: gen_helper_float_recip2_s(fp0, fp0, fp1);
6810: tcg_temp_free_i32(fp1);
6811: gen_store_fpr32(fp0, fd);
6812: tcg_temp_free_i32(fp0);
6813: }
1.1.1.6 root 6814: opn = "recip2.s";
6815: break;
1.1.1.12 root 6816: case OPC_RECIP1_S:
1.1.1.6 root 6817: check_cp1_64bitmode(ctx);
1.1.1.7 root 6818: {
6819: TCGv_i32 fp0 = tcg_temp_new_i32();
6820:
6821: gen_load_fpr32(fp0, fs);
6822: gen_helper_float_recip1_s(fp0, fp0);
6823: gen_store_fpr32(fp0, fd);
6824: tcg_temp_free_i32(fp0);
6825: }
1.1.1.6 root 6826: opn = "recip1.s";
6827: break;
1.1.1.12 root 6828: case OPC_RSQRT1_S:
1.1.1.6 root 6829: check_cp1_64bitmode(ctx);
1.1.1.7 root 6830: {
6831: TCGv_i32 fp0 = tcg_temp_new_i32();
6832:
6833: gen_load_fpr32(fp0, fs);
6834: gen_helper_float_rsqrt1_s(fp0, fp0);
6835: gen_store_fpr32(fp0, fd);
6836: tcg_temp_free_i32(fp0);
6837: }
1.1.1.6 root 6838: opn = "rsqrt1.s";
6839: break;
1.1.1.12 root 6840: case OPC_RSQRT2_S:
1.1.1.6 root 6841: check_cp1_64bitmode(ctx);
1.1.1.7 root 6842: {
6843: TCGv_i32 fp0 = tcg_temp_new_i32();
6844: TCGv_i32 fp1 = tcg_temp_new_i32();
6845:
6846: gen_load_fpr32(fp0, fs);
6847: gen_load_fpr32(fp1, ft);
6848: gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6849: tcg_temp_free_i32(fp1);
6850: gen_store_fpr32(fp0, fd);
6851: tcg_temp_free_i32(fp0);
6852: }
1.1.1.6 root 6853: opn = "rsqrt2.s";
6854: break;
1.1.1.12 root 6855: case OPC_CVT_D_S:
1.1.1.6 root 6856: check_cp1_registers(ctx, fd);
1.1.1.7 root 6857: {
6858: TCGv_i32 fp32 = tcg_temp_new_i32();
6859: TCGv_i64 fp64 = tcg_temp_new_i64();
6860:
6861: gen_load_fpr32(fp32, fs);
6862: gen_helper_float_cvtd_s(fp64, fp32);
6863: tcg_temp_free_i32(fp32);
6864: gen_store_fpr64(ctx, fp64, fd);
6865: tcg_temp_free_i64(fp64);
6866: }
1.1.1.6 root 6867: opn = "cvt.d.s";
6868: break;
1.1.1.12 root 6869: case OPC_CVT_W_S:
1.1.1.7 root 6870: {
6871: TCGv_i32 fp0 = tcg_temp_new_i32();
6872:
6873: gen_load_fpr32(fp0, fs);
6874: gen_helper_float_cvtw_s(fp0, fp0);
6875: gen_store_fpr32(fp0, fd);
6876: tcg_temp_free_i32(fp0);
6877: }
1.1.1.6 root 6878: opn = "cvt.w.s";
6879: break;
1.1.1.12 root 6880: case OPC_CVT_L_S:
1.1.1.6 root 6881: check_cp1_64bitmode(ctx);
1.1.1.7 root 6882: {
6883: TCGv_i32 fp32 = tcg_temp_new_i32();
6884: TCGv_i64 fp64 = tcg_temp_new_i64();
6885:
6886: gen_load_fpr32(fp32, fs);
6887: gen_helper_float_cvtl_s(fp64, fp32);
6888: tcg_temp_free_i32(fp32);
6889: gen_store_fpr64(ctx, fp64, fd);
6890: tcg_temp_free_i64(fp64);
6891: }
1.1.1.6 root 6892: opn = "cvt.l.s";
6893: break;
1.1.1.12 root 6894: case OPC_CVT_PS_S:
1.1.1.6 root 6895: check_cp1_64bitmode(ctx);
1.1.1.7 root 6896: {
6897: TCGv_i64 fp64 = tcg_temp_new_i64();
6898: TCGv_i32 fp32_0 = tcg_temp_new_i32();
6899: TCGv_i32 fp32_1 = tcg_temp_new_i32();
6900:
6901: gen_load_fpr32(fp32_0, fs);
6902: gen_load_fpr32(fp32_1, ft);
6903: tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6904: tcg_temp_free_i32(fp32_1);
6905: tcg_temp_free_i32(fp32_0);
6906: gen_store_fpr64(ctx, fp64, fd);
6907: tcg_temp_free_i64(fp64);
6908: }
1.1.1.6 root 6909: opn = "cvt.ps.s";
6910: break;
1.1.1.12 root 6911: case OPC_CMP_F_S:
6912: case OPC_CMP_UN_S:
6913: case OPC_CMP_EQ_S:
6914: case OPC_CMP_UEQ_S:
6915: case OPC_CMP_OLT_S:
6916: case OPC_CMP_ULT_S:
6917: case OPC_CMP_OLE_S:
6918: case OPC_CMP_ULE_S:
6919: case OPC_CMP_SF_S:
6920: case OPC_CMP_NGLE_S:
6921: case OPC_CMP_SEQ_S:
6922: case OPC_CMP_NGL_S:
6923: case OPC_CMP_LT_S:
6924: case OPC_CMP_NGE_S:
6925: case OPC_CMP_LE_S:
6926: case OPC_CMP_NGT_S:
6927: if (ctx->opcode & (1 << 6)) {
6928: gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6929: opn = condnames_abs[func-48];
6930: } else {
6931: gen_cmp_s(ctx, func-48, ft, fs, cc);
6932: opn = condnames[func-48];
1.1.1.6 root 6933: }
6934: break;
1.1.1.12 root 6935: case OPC_ADD_D:
1.1.1.6 root 6936: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6937: {
6938: TCGv_i64 fp0 = tcg_temp_new_i64();
6939: TCGv_i64 fp1 = tcg_temp_new_i64();
6940:
6941: gen_load_fpr64(ctx, fp0, fs);
6942: gen_load_fpr64(ctx, fp1, ft);
6943: gen_helper_float_add_d(fp0, fp0, fp1);
6944: tcg_temp_free_i64(fp1);
6945: gen_store_fpr64(ctx, fp0, fd);
6946: tcg_temp_free_i64(fp0);
6947: }
1.1.1.4 root 6948: opn = "add.d";
1.1.1.6 root 6949: optype = BINOP;
1.1.1.4 root 6950: break;
1.1.1.12 root 6951: case OPC_SUB_D:
1.1.1.6 root 6952: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6953: {
6954: TCGv_i64 fp0 = tcg_temp_new_i64();
6955: TCGv_i64 fp1 = tcg_temp_new_i64();
6956:
6957: gen_load_fpr64(ctx, fp0, fs);
6958: gen_load_fpr64(ctx, fp1, ft);
6959: gen_helper_float_sub_d(fp0, fp0, fp1);
6960: tcg_temp_free_i64(fp1);
6961: gen_store_fpr64(ctx, fp0, fd);
6962: tcg_temp_free_i64(fp0);
6963: }
1.1.1.4 root 6964: opn = "sub.d";
1.1.1.6 root 6965: optype = BINOP;
1.1.1.4 root 6966: break;
1.1.1.12 root 6967: case OPC_MUL_D:
1.1.1.6 root 6968: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6969: {
6970: TCGv_i64 fp0 = tcg_temp_new_i64();
6971: TCGv_i64 fp1 = tcg_temp_new_i64();
6972:
6973: gen_load_fpr64(ctx, fp0, fs);
6974: gen_load_fpr64(ctx, fp1, ft);
6975: gen_helper_float_mul_d(fp0, fp0, fp1);
6976: tcg_temp_free_i64(fp1);
6977: gen_store_fpr64(ctx, fp0, fd);
6978: tcg_temp_free_i64(fp0);
6979: }
1.1.1.4 root 6980: opn = "mul.d";
1.1.1.6 root 6981: optype = BINOP;
1.1.1.4 root 6982: break;
1.1.1.12 root 6983: case OPC_DIV_D:
1.1.1.6 root 6984: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6985: {
6986: TCGv_i64 fp0 = tcg_temp_new_i64();
6987: TCGv_i64 fp1 = tcg_temp_new_i64();
6988:
6989: gen_load_fpr64(ctx, fp0, fs);
6990: gen_load_fpr64(ctx, fp1, ft);
6991: gen_helper_float_div_d(fp0, fp0, fp1);
6992: tcg_temp_free_i64(fp1);
6993: gen_store_fpr64(ctx, fp0, fd);
6994: tcg_temp_free_i64(fp0);
6995: }
1.1.1.4 root 6996: opn = "div.d";
1.1.1.6 root 6997: optype = BINOP;
1.1.1.4 root 6998: break;
1.1.1.12 root 6999: case OPC_SQRT_D:
1.1.1.6 root 7000: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 7001: {
7002: TCGv_i64 fp0 = tcg_temp_new_i64();
7003:
7004: gen_load_fpr64(ctx, fp0, fs);
7005: gen_helper_float_sqrt_d(fp0, fp0);
7006: gen_store_fpr64(ctx, fp0, fd);
7007: tcg_temp_free_i64(fp0);
7008: }
1.1.1.4 root 7009: opn = "sqrt.d";
7010: break;
1.1.1.12 root 7011: case OPC_ABS_D:
1.1.1.6 root 7012: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 7013: {
7014: TCGv_i64 fp0 = tcg_temp_new_i64();
7015:
7016: gen_load_fpr64(ctx, fp0, fs);
7017: gen_helper_float_abs_d(fp0, fp0);
7018: gen_store_fpr64(ctx, fp0, fd);
7019: tcg_temp_free_i64(fp0);
7020: }
1.1.1.4 root 7021: opn = "abs.d";
7022: break;
1.1.1.12 root 7023: case OPC_MOV_D:
1.1.1.6 root 7024: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 7025: {
7026: TCGv_i64 fp0 = tcg_temp_new_i64();
7027:
7028: gen_load_fpr64(ctx, fp0, fs);
7029: gen_store_fpr64(ctx, fp0, fd);
7030: tcg_temp_free_i64(fp0);
7031: }
1.1.1.4 root 7032: opn = "mov.d";
7033: break;
1.1.1.12 root 7034: case OPC_NEG_D:
1.1.1.6 root 7035: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 7036: {
7037: TCGv_i64 fp0 = tcg_temp_new_i64();
7038:
7039: gen_load_fpr64(ctx, fp0, fs);
7040: gen_helper_float_chs_d(fp0, fp0);
7041: gen_store_fpr64(ctx, fp0, fd);
7042: tcg_temp_free_i64(fp0);
7043: }
1.1.1.4 root 7044: opn = "neg.d";
7045: break;
1.1.1.12 root 7046: case OPC_ROUND_L_D:
1.1.1.6 root 7047: check_cp1_64bitmode(ctx);
1.1.1.7 root 7048: {
7049: TCGv_i64 fp0 = tcg_temp_new_i64();
7050:
7051: gen_load_fpr64(ctx, fp0, fs);
7052: gen_helper_float_roundl_d(fp0, fp0);
7053: gen_store_fpr64(ctx, fp0, fd);
7054: tcg_temp_free_i64(fp0);
7055: }
1.1.1.6 root 7056: opn = "round.l.d";
7057: break;
1.1.1.12 root 7058: case OPC_TRUNC_L_D:
1.1.1.6 root 7059: check_cp1_64bitmode(ctx);
1.1.1.7 root 7060: {
7061: TCGv_i64 fp0 = tcg_temp_new_i64();
7062:
7063: gen_load_fpr64(ctx, fp0, fs);
7064: gen_helper_float_truncl_d(fp0, fp0);
7065: gen_store_fpr64(ctx, fp0, fd);
7066: tcg_temp_free_i64(fp0);
7067: }
1.1.1.6 root 7068: opn = "trunc.l.d";
7069: break;
1.1.1.12 root 7070: case OPC_CEIL_L_D:
1.1.1.6 root 7071: check_cp1_64bitmode(ctx);
1.1.1.7 root 7072: {
7073: TCGv_i64 fp0 = tcg_temp_new_i64();
7074:
7075: gen_load_fpr64(ctx, fp0, fs);
7076: gen_helper_float_ceill_d(fp0, fp0);
7077: gen_store_fpr64(ctx, fp0, fd);
7078: tcg_temp_free_i64(fp0);
7079: }
1.1.1.6 root 7080: opn = "ceil.l.d";
7081: break;
1.1.1.12 root 7082: case OPC_FLOOR_L_D:
1.1.1.6 root 7083: check_cp1_64bitmode(ctx);
1.1.1.7 root 7084: {
7085: TCGv_i64 fp0 = tcg_temp_new_i64();
7086:
7087: gen_load_fpr64(ctx, fp0, fs);
7088: gen_helper_float_floorl_d(fp0, fp0);
7089: gen_store_fpr64(ctx, fp0, fd);
7090: tcg_temp_free_i64(fp0);
7091: }
1.1.1.6 root 7092: opn = "floor.l.d";
7093: break;
1.1.1.12 root 7094: case OPC_ROUND_W_D:
1.1.1.6 root 7095: check_cp1_registers(ctx, fs);
1.1.1.7 root 7096: {
7097: TCGv_i32 fp32 = tcg_temp_new_i32();
7098: TCGv_i64 fp64 = tcg_temp_new_i64();
7099:
7100: gen_load_fpr64(ctx, fp64, fs);
7101: gen_helper_float_roundw_d(fp32, fp64);
7102: tcg_temp_free_i64(fp64);
7103: gen_store_fpr32(fp32, fd);
7104: tcg_temp_free_i32(fp32);
7105: }
1.1.1.4 root 7106: opn = "round.w.d";
7107: break;
1.1.1.12 root 7108: case OPC_TRUNC_W_D:
1.1.1.6 root 7109: check_cp1_registers(ctx, fs);
1.1.1.7 root 7110: {
7111: TCGv_i32 fp32 = tcg_temp_new_i32();
7112: TCGv_i64 fp64 = tcg_temp_new_i64();
7113:
7114: gen_load_fpr64(ctx, fp64, fs);
7115: gen_helper_float_truncw_d(fp32, fp64);
7116: tcg_temp_free_i64(fp64);
7117: gen_store_fpr32(fp32, fd);
7118: tcg_temp_free_i32(fp32);
7119: }
1.1.1.4 root 7120: opn = "trunc.w.d";
7121: break;
1.1.1.12 root 7122: case OPC_CEIL_W_D:
1.1.1.6 root 7123: check_cp1_registers(ctx, fs);
1.1.1.7 root 7124: {
7125: TCGv_i32 fp32 = tcg_temp_new_i32();
7126: TCGv_i64 fp64 = tcg_temp_new_i64();
7127:
7128: gen_load_fpr64(ctx, fp64, fs);
7129: gen_helper_float_ceilw_d(fp32, fp64);
7130: tcg_temp_free_i64(fp64);
7131: gen_store_fpr32(fp32, fd);
7132: tcg_temp_free_i32(fp32);
7133: }
1.1.1.4 root 7134: opn = "ceil.w.d";
7135: break;
1.1.1.12 root 7136: case OPC_FLOOR_W_D:
1.1.1.6 root 7137: check_cp1_registers(ctx, fs);
1.1.1.7 root 7138: {
7139: TCGv_i32 fp32 = tcg_temp_new_i32();
7140: TCGv_i64 fp64 = tcg_temp_new_i64();
7141:
7142: gen_load_fpr64(ctx, fp64, fs);
7143: gen_helper_float_floorw_d(fp32, fp64);
7144: tcg_temp_free_i64(fp64);
7145: gen_store_fpr32(fp32, fd);
7146: tcg_temp_free_i32(fp32);
7147: }
1.1.1.5 root 7148: opn = "floor.w.d";
7149: break;
1.1.1.12 root 7150: case OPC_MOVCF_D:
1.1.1.7 root 7151: gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 7152: opn = "movcf.d";
1.1.1.4 root 7153: break;
1.1.1.12 root 7154: case OPC_MOVZ_D:
1.1.1.7 root 7155: {
7156: int l1 = gen_new_label();
1.1.1.8 root 7157: TCGv_i64 fp0;
1.1.1.7 root 7158:
1.1.1.8 root 7159: if (ft != 0) {
7160: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7161: }
7162: fp0 = tcg_temp_new_i64();
1.1.1.7 root 7163: gen_load_fpr64(ctx, fp0, fs);
7164: gen_store_fpr64(ctx, fp0, fd);
7165: tcg_temp_free_i64(fp0);
7166: gen_set_label(l1);
7167: }
1.1.1.6 root 7168: opn = "movz.d";
7169: break;
1.1.1.12 root 7170: case OPC_MOVN_D:
1.1.1.7 root 7171: {
7172: int l1 = gen_new_label();
1.1.1.8 root 7173: TCGv_i64 fp0;
1.1.1.7 root 7174:
1.1.1.8 root 7175: if (ft != 0) {
7176: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7177: fp0 = tcg_temp_new_i64();
7178: gen_load_fpr64(ctx, fp0, fs);
7179: gen_store_fpr64(ctx, fp0, fd);
7180: tcg_temp_free_i64(fp0);
7181: gen_set_label(l1);
7182: }
1.1.1.7 root 7183: }
1.1.1.6 root 7184: opn = "movn.d";
7185: break;
1.1.1.12 root 7186: case OPC_RECIP_D:
1.1.1.6 root 7187: check_cp1_64bitmode(ctx);
1.1.1.7 root 7188: {
7189: TCGv_i64 fp0 = tcg_temp_new_i64();
7190:
7191: gen_load_fpr64(ctx, fp0, fs);
7192: gen_helper_float_recip_d(fp0, fp0);
7193: gen_store_fpr64(ctx, fp0, fd);
7194: tcg_temp_free_i64(fp0);
7195: }
1.1.1.6 root 7196: opn = "recip.d";
7197: break;
1.1.1.12 root 7198: case OPC_RSQRT_D:
1.1.1.6 root 7199: check_cp1_64bitmode(ctx);
1.1.1.7 root 7200: {
7201: TCGv_i64 fp0 = tcg_temp_new_i64();
7202:
7203: gen_load_fpr64(ctx, fp0, fs);
7204: gen_helper_float_rsqrt_d(fp0, fp0);
7205: gen_store_fpr64(ctx, fp0, fd);
7206: tcg_temp_free_i64(fp0);
7207: }
1.1.1.6 root 7208: opn = "rsqrt.d";
7209: break;
1.1.1.12 root 7210: case OPC_RECIP2_D:
1.1.1.6 root 7211: check_cp1_64bitmode(ctx);
1.1.1.7 root 7212: {
7213: TCGv_i64 fp0 = tcg_temp_new_i64();
7214: TCGv_i64 fp1 = tcg_temp_new_i64();
7215:
7216: gen_load_fpr64(ctx, fp0, fs);
7217: gen_load_fpr64(ctx, fp1, ft);
7218: gen_helper_float_recip2_d(fp0, fp0, fp1);
7219: tcg_temp_free_i64(fp1);
7220: gen_store_fpr64(ctx, fp0, fd);
7221: tcg_temp_free_i64(fp0);
7222: }
1.1.1.6 root 7223: opn = "recip2.d";
7224: break;
1.1.1.12 root 7225: case OPC_RECIP1_D:
1.1.1.6 root 7226: check_cp1_64bitmode(ctx);
1.1.1.7 root 7227: {
7228: TCGv_i64 fp0 = tcg_temp_new_i64();
7229:
7230: gen_load_fpr64(ctx, fp0, fs);
7231: gen_helper_float_recip1_d(fp0, fp0);
7232: gen_store_fpr64(ctx, fp0, fd);
7233: tcg_temp_free_i64(fp0);
7234: }
1.1.1.6 root 7235: opn = "recip1.d";
7236: break;
1.1.1.12 root 7237: case OPC_RSQRT1_D:
1.1.1.6 root 7238: check_cp1_64bitmode(ctx);
1.1.1.7 root 7239: {
7240: TCGv_i64 fp0 = tcg_temp_new_i64();
7241:
7242: gen_load_fpr64(ctx, fp0, fs);
7243: gen_helper_float_rsqrt1_d(fp0, fp0);
7244: gen_store_fpr64(ctx, fp0, fd);
7245: tcg_temp_free_i64(fp0);
7246: }
1.1.1.6 root 7247: opn = "rsqrt1.d";
7248: break;
1.1.1.12 root 7249: case OPC_RSQRT2_D:
1.1.1.6 root 7250: check_cp1_64bitmode(ctx);
1.1.1.7 root 7251: {
7252: TCGv_i64 fp0 = tcg_temp_new_i64();
7253: TCGv_i64 fp1 = tcg_temp_new_i64();
7254:
7255: gen_load_fpr64(ctx, fp0, fs);
7256: gen_load_fpr64(ctx, fp1, ft);
7257: gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
7258: tcg_temp_free_i64(fp1);
7259: gen_store_fpr64(ctx, fp0, fd);
7260: tcg_temp_free_i64(fp0);
7261: }
1.1.1.6 root 7262: opn = "rsqrt2.d";
1.1.1.4 root 7263: break;
1.1.1.12 root 7264: case OPC_CMP_F_D:
7265: case OPC_CMP_UN_D:
7266: case OPC_CMP_EQ_D:
7267: case OPC_CMP_UEQ_D:
7268: case OPC_CMP_OLT_D:
7269: case OPC_CMP_ULT_D:
7270: case OPC_CMP_OLE_D:
7271: case OPC_CMP_ULE_D:
7272: case OPC_CMP_SF_D:
7273: case OPC_CMP_NGLE_D:
7274: case OPC_CMP_SEQ_D:
7275: case OPC_CMP_NGL_D:
7276: case OPC_CMP_LT_D:
7277: case OPC_CMP_NGE_D:
7278: case OPC_CMP_LE_D:
7279: case OPC_CMP_NGT_D:
7280: if (ctx->opcode & (1 << 6)) {
7281: gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7282: opn = condnames_abs[func-48];
7283: } else {
7284: gen_cmp_d(ctx, func-48, ft, fs, cc);
7285: opn = condnames[func-48];
1.1.1.6 root 7286: }
7287: break;
1.1.1.12 root 7288: case OPC_CVT_S_D:
1.1.1.6 root 7289: check_cp1_registers(ctx, fs);
1.1.1.7 root 7290: {
7291: TCGv_i32 fp32 = tcg_temp_new_i32();
7292: TCGv_i64 fp64 = tcg_temp_new_i64();
7293:
7294: gen_load_fpr64(ctx, fp64, fs);
7295: gen_helper_float_cvts_d(fp32, fp64);
7296: tcg_temp_free_i64(fp64);
7297: gen_store_fpr32(fp32, fd);
7298: tcg_temp_free_i32(fp32);
7299: }
1.1.1.6 root 7300: opn = "cvt.s.d";
7301: break;
1.1.1.12 root 7302: case OPC_CVT_W_D:
1.1.1.6 root 7303: check_cp1_registers(ctx, fs);
1.1.1.7 root 7304: {
7305: TCGv_i32 fp32 = tcg_temp_new_i32();
7306: TCGv_i64 fp64 = tcg_temp_new_i64();
7307:
7308: gen_load_fpr64(ctx, fp64, fs);
7309: gen_helper_float_cvtw_d(fp32, fp64);
7310: tcg_temp_free_i64(fp64);
7311: gen_store_fpr32(fp32, fd);
7312: tcg_temp_free_i32(fp32);
7313: }
1.1.1.6 root 7314: opn = "cvt.w.d";
7315: break;
1.1.1.12 root 7316: case OPC_CVT_L_D:
1.1.1.6 root 7317: check_cp1_64bitmode(ctx);
1.1.1.7 root 7318: {
7319: TCGv_i64 fp0 = tcg_temp_new_i64();
7320:
7321: gen_load_fpr64(ctx, fp0, fs);
7322: gen_helper_float_cvtl_d(fp0, fp0);
7323: gen_store_fpr64(ctx, fp0, fd);
7324: tcg_temp_free_i64(fp0);
7325: }
1.1.1.6 root 7326: opn = "cvt.l.d";
7327: break;
1.1.1.12 root 7328: case OPC_CVT_S_W:
1.1.1.7 root 7329: {
7330: TCGv_i32 fp0 = tcg_temp_new_i32();
7331:
7332: gen_load_fpr32(fp0, fs);
7333: gen_helper_float_cvts_w(fp0, fp0);
7334: gen_store_fpr32(fp0, fd);
7335: tcg_temp_free_i32(fp0);
7336: }
1.1.1.6 root 7337: opn = "cvt.s.w";
7338: break;
1.1.1.12 root 7339: case OPC_CVT_D_W:
1.1.1.6 root 7340: check_cp1_registers(ctx, fd);
1.1.1.7 root 7341: {
7342: TCGv_i32 fp32 = tcg_temp_new_i32();
7343: TCGv_i64 fp64 = tcg_temp_new_i64();
7344:
7345: gen_load_fpr32(fp32, fs);
7346: gen_helper_float_cvtd_w(fp64, fp32);
7347: tcg_temp_free_i32(fp32);
7348: gen_store_fpr64(ctx, fp64, fd);
7349: tcg_temp_free_i64(fp64);
7350: }
1.1.1.6 root 7351: opn = "cvt.d.w";
7352: break;
1.1.1.12 root 7353: case OPC_CVT_S_L:
1.1.1.6 root 7354: check_cp1_64bitmode(ctx);
1.1.1.7 root 7355: {
7356: TCGv_i32 fp32 = tcg_temp_new_i32();
7357: TCGv_i64 fp64 = tcg_temp_new_i64();
7358:
7359: gen_load_fpr64(ctx, fp64, fs);
7360: gen_helper_float_cvts_l(fp32, fp64);
7361: tcg_temp_free_i64(fp64);
7362: gen_store_fpr32(fp32, fd);
7363: tcg_temp_free_i32(fp32);
7364: }
1.1.1.6 root 7365: opn = "cvt.s.l";
7366: break;
1.1.1.12 root 7367: case OPC_CVT_D_L:
1.1.1.6 root 7368: check_cp1_64bitmode(ctx);
1.1.1.7 root 7369: {
7370: TCGv_i64 fp0 = tcg_temp_new_i64();
7371:
7372: gen_load_fpr64(ctx, fp0, fs);
7373: gen_helper_float_cvtd_l(fp0, fp0);
7374: gen_store_fpr64(ctx, fp0, fd);
7375: tcg_temp_free_i64(fp0);
7376: }
1.1.1.6 root 7377: opn = "cvt.d.l";
7378: break;
1.1.1.12 root 7379: case OPC_CVT_PS_PW:
1.1.1.6 root 7380: check_cp1_64bitmode(ctx);
1.1.1.7 root 7381: {
7382: TCGv_i64 fp0 = tcg_temp_new_i64();
7383:
7384: gen_load_fpr64(ctx, fp0, fs);
7385: gen_helper_float_cvtps_pw(fp0, fp0);
7386: gen_store_fpr64(ctx, fp0, fd);
7387: tcg_temp_free_i64(fp0);
7388: }
1.1.1.6 root 7389: opn = "cvt.ps.pw";
7390: break;
1.1.1.12 root 7391: case OPC_ADD_PS:
1.1.1.6 root 7392: check_cp1_64bitmode(ctx);
1.1.1.7 root 7393: {
7394: TCGv_i64 fp0 = tcg_temp_new_i64();
7395: TCGv_i64 fp1 = tcg_temp_new_i64();
7396:
7397: gen_load_fpr64(ctx, fp0, fs);
7398: gen_load_fpr64(ctx, fp1, ft);
7399: gen_helper_float_add_ps(fp0, fp0, fp1);
7400: tcg_temp_free_i64(fp1);
7401: gen_store_fpr64(ctx, fp0, fd);
7402: tcg_temp_free_i64(fp0);
7403: }
1.1.1.6 root 7404: opn = "add.ps";
7405: break;
1.1.1.12 root 7406: case OPC_SUB_PS:
1.1.1.6 root 7407: check_cp1_64bitmode(ctx);
1.1.1.7 root 7408: {
7409: TCGv_i64 fp0 = tcg_temp_new_i64();
7410: TCGv_i64 fp1 = tcg_temp_new_i64();
7411:
7412: gen_load_fpr64(ctx, fp0, fs);
7413: gen_load_fpr64(ctx, fp1, ft);
7414: gen_helper_float_sub_ps(fp0, fp0, fp1);
7415: tcg_temp_free_i64(fp1);
7416: gen_store_fpr64(ctx, fp0, fd);
7417: tcg_temp_free_i64(fp0);
7418: }
1.1.1.6 root 7419: opn = "sub.ps";
7420: break;
1.1.1.12 root 7421: case OPC_MUL_PS:
1.1.1.6 root 7422: check_cp1_64bitmode(ctx);
1.1.1.7 root 7423: {
7424: TCGv_i64 fp0 = tcg_temp_new_i64();
7425: TCGv_i64 fp1 = tcg_temp_new_i64();
7426:
7427: gen_load_fpr64(ctx, fp0, fs);
7428: gen_load_fpr64(ctx, fp1, ft);
7429: gen_helper_float_mul_ps(fp0, fp0, fp1);
7430: tcg_temp_free_i64(fp1);
7431: gen_store_fpr64(ctx, fp0, fd);
7432: tcg_temp_free_i64(fp0);
7433: }
1.1.1.6 root 7434: opn = "mul.ps";
7435: break;
1.1.1.12 root 7436: case OPC_ABS_PS:
1.1.1.6 root 7437: check_cp1_64bitmode(ctx);
1.1.1.7 root 7438: {
7439: TCGv_i64 fp0 = tcg_temp_new_i64();
7440:
7441: gen_load_fpr64(ctx, fp0, fs);
7442: gen_helper_float_abs_ps(fp0, fp0);
7443: gen_store_fpr64(ctx, fp0, fd);
7444: tcg_temp_free_i64(fp0);
7445: }
1.1.1.6 root 7446: opn = "abs.ps";
7447: break;
1.1.1.12 root 7448: case OPC_MOV_PS:
1.1.1.6 root 7449: check_cp1_64bitmode(ctx);
1.1.1.7 root 7450: {
7451: TCGv_i64 fp0 = tcg_temp_new_i64();
7452:
7453: gen_load_fpr64(ctx, fp0, fs);
7454: gen_store_fpr64(ctx, fp0, fd);
7455: tcg_temp_free_i64(fp0);
7456: }
1.1.1.6 root 7457: opn = "mov.ps";
7458: break;
1.1.1.12 root 7459: case OPC_NEG_PS:
1.1.1.6 root 7460: check_cp1_64bitmode(ctx);
1.1.1.7 root 7461: {
7462: TCGv_i64 fp0 = tcg_temp_new_i64();
7463:
7464: gen_load_fpr64(ctx, fp0, fs);
7465: gen_helper_float_chs_ps(fp0, fp0);
7466: gen_store_fpr64(ctx, fp0, fd);
7467: tcg_temp_free_i64(fp0);
7468: }
1.1.1.6 root 7469: opn = "neg.ps";
7470: break;
1.1.1.12 root 7471: case OPC_MOVCF_PS:
1.1.1.6 root 7472: check_cp1_64bitmode(ctx);
1.1.1.7 root 7473: gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 7474: opn = "movcf.ps";
7475: break;
1.1.1.12 root 7476: case OPC_MOVZ_PS:
1.1.1.6 root 7477: check_cp1_64bitmode(ctx);
1.1.1.7 root 7478: {
7479: int l1 = gen_new_label();
1.1.1.8 root 7480: TCGv_i64 fp0;
1.1.1.7 root 7481:
1.1.1.8 root 7482: if (ft != 0)
7483: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7484: fp0 = tcg_temp_new_i64();
7485: gen_load_fpr64(ctx, fp0, fs);
7486: gen_store_fpr64(ctx, fp0, fd);
7487: tcg_temp_free_i64(fp0);
1.1.1.7 root 7488: gen_set_label(l1);
7489: }
1.1.1.6 root 7490: opn = "movz.ps";
7491: break;
1.1.1.12 root 7492: case OPC_MOVN_PS:
1.1.1.6 root 7493: check_cp1_64bitmode(ctx);
1.1.1.7 root 7494: {
7495: int l1 = gen_new_label();
1.1.1.8 root 7496: TCGv_i64 fp0;
1.1.1.7 root 7497:
1.1.1.8 root 7498: if (ft != 0) {
7499: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7500: fp0 = tcg_temp_new_i64();
7501: gen_load_fpr64(ctx, fp0, fs);
7502: gen_store_fpr64(ctx, fp0, fd);
7503: tcg_temp_free_i64(fp0);
7504: gen_set_label(l1);
7505: }
1.1.1.7 root 7506: }
1.1.1.6 root 7507: opn = "movn.ps";
7508: break;
1.1.1.12 root 7509: case OPC_ADDR_PS:
1.1.1.6 root 7510: check_cp1_64bitmode(ctx);
1.1.1.7 root 7511: {
7512: TCGv_i64 fp0 = tcg_temp_new_i64();
7513: TCGv_i64 fp1 = tcg_temp_new_i64();
7514:
7515: gen_load_fpr64(ctx, fp0, ft);
7516: gen_load_fpr64(ctx, fp1, fs);
7517: gen_helper_float_addr_ps(fp0, fp0, fp1);
7518: tcg_temp_free_i64(fp1);
7519: gen_store_fpr64(ctx, fp0, fd);
7520: tcg_temp_free_i64(fp0);
7521: }
1.1.1.6 root 7522: opn = "addr.ps";
7523: break;
1.1.1.12 root 7524: case OPC_MULR_PS:
1.1.1.6 root 7525: check_cp1_64bitmode(ctx);
1.1.1.7 root 7526: {
7527: TCGv_i64 fp0 = tcg_temp_new_i64();
7528: TCGv_i64 fp1 = tcg_temp_new_i64();
7529:
7530: gen_load_fpr64(ctx, fp0, ft);
7531: gen_load_fpr64(ctx, fp1, fs);
7532: gen_helper_float_mulr_ps(fp0, fp0, fp1);
7533: tcg_temp_free_i64(fp1);
7534: gen_store_fpr64(ctx, fp0, fd);
7535: tcg_temp_free_i64(fp0);
7536: }
1.1.1.6 root 7537: opn = "mulr.ps";
7538: break;
1.1.1.12 root 7539: case OPC_RECIP2_PS:
1.1.1.6 root 7540: check_cp1_64bitmode(ctx);
1.1.1.7 root 7541: {
7542: TCGv_i64 fp0 = tcg_temp_new_i64();
7543: TCGv_i64 fp1 = tcg_temp_new_i64();
7544:
7545: gen_load_fpr64(ctx, fp0, fs);
7546: gen_load_fpr64(ctx, fp1, fd);
7547: gen_helper_float_recip2_ps(fp0, fp0, fp1);
7548: tcg_temp_free_i64(fp1);
7549: gen_store_fpr64(ctx, fp0, fd);
7550: tcg_temp_free_i64(fp0);
7551: }
1.1.1.6 root 7552: opn = "recip2.ps";
7553: break;
1.1.1.12 root 7554: case OPC_RECIP1_PS:
1.1.1.6 root 7555: check_cp1_64bitmode(ctx);
1.1.1.7 root 7556: {
7557: TCGv_i64 fp0 = tcg_temp_new_i64();
7558:
7559: gen_load_fpr64(ctx, fp0, fs);
7560: gen_helper_float_recip1_ps(fp0, fp0);
7561: gen_store_fpr64(ctx, fp0, fd);
7562: tcg_temp_free_i64(fp0);
7563: }
1.1.1.6 root 7564: opn = "recip1.ps";
7565: break;
1.1.1.12 root 7566: case OPC_RSQRT1_PS:
1.1.1.6 root 7567: check_cp1_64bitmode(ctx);
1.1.1.7 root 7568: {
7569: TCGv_i64 fp0 = tcg_temp_new_i64();
7570:
7571: gen_load_fpr64(ctx, fp0, fs);
7572: gen_helper_float_rsqrt1_ps(fp0, fp0);
7573: gen_store_fpr64(ctx, fp0, fd);
7574: tcg_temp_free_i64(fp0);
7575: }
1.1.1.6 root 7576: opn = "rsqrt1.ps";
7577: break;
1.1.1.12 root 7578: case OPC_RSQRT2_PS:
1.1.1.6 root 7579: check_cp1_64bitmode(ctx);
1.1.1.7 root 7580: {
7581: TCGv_i64 fp0 = tcg_temp_new_i64();
7582: TCGv_i64 fp1 = tcg_temp_new_i64();
7583:
7584: gen_load_fpr64(ctx, fp0, fs);
7585: gen_load_fpr64(ctx, fp1, ft);
7586: gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7587: tcg_temp_free_i64(fp1);
7588: gen_store_fpr64(ctx, fp0, fd);
7589: tcg_temp_free_i64(fp0);
7590: }
1.1.1.6 root 7591: opn = "rsqrt2.ps";
7592: break;
1.1.1.12 root 7593: case OPC_CVT_S_PU:
1.1.1.6 root 7594: check_cp1_64bitmode(ctx);
1.1.1.7 root 7595: {
7596: TCGv_i32 fp0 = tcg_temp_new_i32();
7597:
7598: gen_load_fpr32h(fp0, fs);
7599: gen_helper_float_cvts_pu(fp0, fp0);
7600: gen_store_fpr32(fp0, fd);
7601: tcg_temp_free_i32(fp0);
7602: }
1.1.1.6 root 7603: opn = "cvt.s.pu";
7604: break;
1.1.1.12 root 7605: case OPC_CVT_PW_PS:
1.1.1.6 root 7606: check_cp1_64bitmode(ctx);
1.1.1.7 root 7607: {
7608: TCGv_i64 fp0 = tcg_temp_new_i64();
7609:
7610: gen_load_fpr64(ctx, fp0, fs);
7611: gen_helper_float_cvtpw_ps(fp0, fp0);
7612: gen_store_fpr64(ctx, fp0, fd);
7613: tcg_temp_free_i64(fp0);
7614: }
1.1.1.6 root 7615: opn = "cvt.pw.ps";
1.1.1.4 root 7616: break;
1.1.1.12 root 7617: case OPC_CVT_S_PL:
1.1.1.6 root 7618: check_cp1_64bitmode(ctx);
1.1.1.7 root 7619: {
7620: TCGv_i32 fp0 = tcg_temp_new_i32();
7621:
7622: gen_load_fpr32(fp0, fs);
7623: gen_helper_float_cvts_pl(fp0, fp0);
7624: gen_store_fpr32(fp0, fd);
7625: tcg_temp_free_i32(fp0);
7626: }
1.1.1.6 root 7627: opn = "cvt.s.pl";
1.1.1.4 root 7628: break;
1.1.1.12 root 7629: case OPC_PLL_PS:
1.1.1.6 root 7630: check_cp1_64bitmode(ctx);
1.1.1.7 root 7631: {
7632: TCGv_i32 fp0 = tcg_temp_new_i32();
7633: TCGv_i32 fp1 = tcg_temp_new_i32();
7634:
7635: gen_load_fpr32(fp0, fs);
7636: gen_load_fpr32(fp1, ft);
7637: gen_store_fpr32h(fp0, fd);
7638: gen_store_fpr32(fp1, fd);
7639: tcg_temp_free_i32(fp0);
7640: tcg_temp_free_i32(fp1);
7641: }
1.1.1.6 root 7642: opn = "pll.ps";
1.1.1.4 root 7643: break;
1.1.1.12 root 7644: case OPC_PLU_PS:
1.1.1.6 root 7645: check_cp1_64bitmode(ctx);
1.1.1.7 root 7646: {
7647: TCGv_i32 fp0 = tcg_temp_new_i32();
7648: TCGv_i32 fp1 = tcg_temp_new_i32();
7649:
7650: gen_load_fpr32(fp0, fs);
7651: gen_load_fpr32h(fp1, ft);
7652: gen_store_fpr32(fp1, fd);
7653: gen_store_fpr32h(fp0, fd);
7654: tcg_temp_free_i32(fp0);
7655: tcg_temp_free_i32(fp1);
7656: }
1.1.1.6 root 7657: opn = "plu.ps";
7658: break;
1.1.1.12 root 7659: case OPC_PUL_PS:
1.1.1.6 root 7660: check_cp1_64bitmode(ctx);
1.1.1.7 root 7661: {
7662: TCGv_i32 fp0 = tcg_temp_new_i32();
7663: TCGv_i32 fp1 = tcg_temp_new_i32();
7664:
7665: gen_load_fpr32h(fp0, fs);
7666: gen_load_fpr32(fp1, ft);
7667: gen_store_fpr32(fp1, fd);
7668: gen_store_fpr32h(fp0, fd);
7669: tcg_temp_free_i32(fp0);
7670: tcg_temp_free_i32(fp1);
7671: }
1.1.1.6 root 7672: opn = "pul.ps";
1.1.1.4 root 7673: break;
1.1.1.12 root 7674: case OPC_PUU_PS:
1.1.1.6 root 7675: check_cp1_64bitmode(ctx);
1.1.1.7 root 7676: {
7677: TCGv_i32 fp0 = tcg_temp_new_i32();
7678: TCGv_i32 fp1 = tcg_temp_new_i32();
7679:
7680: gen_load_fpr32h(fp0, fs);
7681: gen_load_fpr32h(fp1, ft);
7682: gen_store_fpr32(fp1, fd);
7683: gen_store_fpr32h(fp0, fd);
7684: tcg_temp_free_i32(fp0);
7685: tcg_temp_free_i32(fp1);
7686: }
1.1.1.6 root 7687: opn = "puu.ps";
7688: break;
1.1.1.12 root 7689: case OPC_CMP_F_PS:
7690: case OPC_CMP_UN_PS:
7691: case OPC_CMP_EQ_PS:
7692: case OPC_CMP_UEQ_PS:
7693: case OPC_CMP_OLT_PS:
7694: case OPC_CMP_ULT_PS:
7695: case OPC_CMP_OLE_PS:
7696: case OPC_CMP_ULE_PS:
7697: case OPC_CMP_SF_PS:
7698: case OPC_CMP_NGLE_PS:
7699: case OPC_CMP_SEQ_PS:
7700: case OPC_CMP_NGL_PS:
7701: case OPC_CMP_LT_PS:
7702: case OPC_CMP_NGE_PS:
7703: case OPC_CMP_LE_PS:
7704: case OPC_CMP_NGT_PS:
7705: if (ctx->opcode & (1 << 6)) {
7706: gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7707: opn = condnames_abs[func-48];
7708: } else {
7709: gen_cmp_ps(ctx, func-48, ft, fs, cc);
7710: opn = condnames[func-48];
1.1.1.6 root 7711: }
1.1.1.4 root 7712: break;
1.1.1.6 root 7713: default:
7714: MIPS_INVAL(opn);
7715: generate_exception (ctx, EXCP_RI);
7716: return;
7717: }
1.1.1.13 root 7718: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 7719: switch (optype) {
7720: case BINOP:
7721: MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7722: break;
7723: case CMPOP:
7724: MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7725: break;
7726: default:
7727: MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7728: break;
7729: }
7730: }
7731:
7732: /* Coprocessor 3 (FPU) */
7733: static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7734: int fd, int fs, int base, int index)
7735: {
7736: const char *opn = "extended float load/store";
7737: int store = 0;
1.1.1.8 root 7738: TCGv t0 = tcg_temp_new();
1.1.1.6 root 7739:
7740: if (base == 0) {
1.1.1.7 root 7741: gen_load_gpr(t0, index);
1.1.1.6 root 7742: } else if (index == 0) {
1.1.1.7 root 7743: gen_load_gpr(t0, base);
1.1.1.6 root 7744: } else {
1.1.1.7 root 7745: gen_load_gpr(t0, index);
1.1.1.9 root 7746: gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
1.1.1.6 root 7747: }
7748: /* Don't do NOP if destination is zero: we must perform the actual
7749: memory access. */
1.1.1.8 root 7750: save_cpu_state(ctx, 0);
1.1.1.6 root 7751: switch (opc) {
7752: case OPC_LWXC1:
7753: check_cop1x(ctx);
1.1.1.7 root 7754: {
7755: TCGv_i32 fp0 = tcg_temp_new_i32();
7756:
1.1.1.8 root 7757: tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7758: tcg_gen_trunc_tl_i32(fp0, t0);
1.1.1.7 root 7759: gen_store_fpr32(fp0, fd);
7760: tcg_temp_free_i32(fp0);
7761: }
1.1.1.6 root 7762: opn = "lwxc1";
7763: break;
7764: case OPC_LDXC1:
7765: check_cop1x(ctx);
7766: check_cp1_registers(ctx, fd);
1.1.1.7 root 7767: {
7768: TCGv_i64 fp0 = tcg_temp_new_i64();
7769:
7770: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7771: gen_store_fpr64(ctx, fp0, fd);
7772: tcg_temp_free_i64(fp0);
7773: }
1.1.1.6 root 7774: opn = "ldxc1";
7775: break;
7776: case OPC_LUXC1:
7777: check_cp1_64bitmode(ctx);
1.1.1.7 root 7778: tcg_gen_andi_tl(t0, t0, ~0x7);
7779: {
7780: TCGv_i64 fp0 = tcg_temp_new_i64();
7781:
7782: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7783: gen_store_fpr64(ctx, fp0, fd);
7784: tcg_temp_free_i64(fp0);
7785: }
1.1.1.6 root 7786: opn = "luxc1";
7787: break;
7788: case OPC_SWXC1:
7789: check_cop1x(ctx);
1.1.1.7 root 7790: {
7791: TCGv_i32 fp0 = tcg_temp_new_i32();
1.1.1.8 root 7792: TCGv t1 = tcg_temp_new();
1.1.1.7 root 7793:
7794: gen_load_fpr32(fp0, fs);
7795: tcg_gen_extu_i32_tl(t1, fp0);
7796: tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7797: tcg_temp_free_i32(fp0);
1.1.1.8 root 7798: tcg_temp_free(t1);
1.1.1.7 root 7799: }
1.1.1.6 root 7800: opn = "swxc1";
7801: store = 1;
1.1.1.4 root 7802: break;
1.1.1.6 root 7803: case OPC_SDXC1:
7804: check_cop1x(ctx);
7805: check_cp1_registers(ctx, fs);
1.1.1.7 root 7806: {
7807: TCGv_i64 fp0 = tcg_temp_new_i64();
7808:
7809: gen_load_fpr64(ctx, fp0, fs);
7810: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7811: tcg_temp_free_i64(fp0);
7812: }
1.1.1.6 root 7813: opn = "sdxc1";
7814: store = 1;
7815: break;
7816: case OPC_SUXC1:
7817: check_cp1_64bitmode(ctx);
1.1.1.7 root 7818: tcg_gen_andi_tl(t0, t0, ~0x7);
7819: {
7820: TCGv_i64 fp0 = tcg_temp_new_i64();
7821:
7822: gen_load_fpr64(ctx, fp0, fs);
7823: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7824: tcg_temp_free_i64(fp0);
7825: }
1.1.1.6 root 7826: opn = "suxc1";
7827: store = 1;
7828: break;
7829: }
1.1.1.7 root 7830: tcg_temp_free(t0);
1.1.1.13 root 7831: (void)opn; (void)store; /* avoid compiler warnings */
1.1.1.6 root 7832: MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7833: regnames[index], regnames[base]);
7834: }
7835:
7836: static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7837: int fd, int fr, int fs, int ft)
7838: {
7839: const char *opn = "flt3_arith";
7840:
7841: switch (opc) {
7842: case OPC_ALNV_PS:
7843: check_cp1_64bitmode(ctx);
1.1.1.7 root 7844: {
7845: TCGv t0 = tcg_temp_local_new();
1.1.1.8 root 7846: TCGv_i32 fp = tcg_temp_new_i32();
7847: TCGv_i32 fph = tcg_temp_new_i32();
1.1.1.7 root 7848: int l1 = gen_new_label();
7849: int l2 = gen_new_label();
7850:
7851: gen_load_gpr(t0, fr);
7852: tcg_gen_andi_tl(t0, t0, 0x7);
7853:
7854: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
1.1.1.8 root 7855: gen_load_fpr32(fp, fs);
7856: gen_load_fpr32h(fph, fs);
7857: gen_store_fpr32(fp, fd);
7858: gen_store_fpr32h(fph, fd);
1.1.1.7 root 7859: tcg_gen_br(l2);
7860: gen_set_label(l1);
7861: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7862: tcg_temp_free(t0);
7863: #ifdef TARGET_WORDS_BIGENDIAN
1.1.1.8 root 7864: gen_load_fpr32(fp, fs);
7865: gen_load_fpr32h(fph, ft);
7866: gen_store_fpr32h(fp, fd);
7867: gen_store_fpr32(fph, fd);
1.1.1.7 root 7868: #else
1.1.1.8 root 7869: gen_load_fpr32h(fph, fs);
7870: gen_load_fpr32(fp, ft);
7871: gen_store_fpr32(fph, fd);
7872: gen_store_fpr32h(fp, fd);
1.1.1.7 root 7873: #endif
7874: gen_set_label(l2);
1.1.1.8 root 7875: tcg_temp_free_i32(fp);
7876: tcg_temp_free_i32(fph);
1.1.1.7 root 7877: }
1.1.1.6 root 7878: opn = "alnv.ps";
7879: break;
7880: case OPC_MADD_S:
7881: check_cop1x(ctx);
1.1.1.7 root 7882: {
7883: TCGv_i32 fp0 = tcg_temp_new_i32();
7884: TCGv_i32 fp1 = tcg_temp_new_i32();
7885: TCGv_i32 fp2 = tcg_temp_new_i32();
7886:
7887: gen_load_fpr32(fp0, fs);
7888: gen_load_fpr32(fp1, ft);
7889: gen_load_fpr32(fp2, fr);
7890: gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7891: tcg_temp_free_i32(fp0);
7892: tcg_temp_free_i32(fp1);
7893: gen_store_fpr32(fp2, fd);
7894: tcg_temp_free_i32(fp2);
7895: }
1.1.1.6 root 7896: opn = "madd.s";
1.1.1.4 root 7897: break;
1.1.1.6 root 7898: case OPC_MADD_D:
7899: check_cop1x(ctx);
7900: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7901: {
7902: TCGv_i64 fp0 = tcg_temp_new_i64();
7903: TCGv_i64 fp1 = tcg_temp_new_i64();
7904: TCGv_i64 fp2 = tcg_temp_new_i64();
7905:
7906: gen_load_fpr64(ctx, fp0, fs);
7907: gen_load_fpr64(ctx, fp1, ft);
7908: gen_load_fpr64(ctx, fp2, fr);
7909: gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7910: tcg_temp_free_i64(fp0);
7911: tcg_temp_free_i64(fp1);
7912: gen_store_fpr64(ctx, fp2, fd);
7913: tcg_temp_free_i64(fp2);
7914: }
1.1.1.6 root 7915: opn = "madd.d";
7916: break;
7917: case OPC_MADD_PS:
7918: check_cp1_64bitmode(ctx);
1.1.1.7 root 7919: {
7920: TCGv_i64 fp0 = tcg_temp_new_i64();
7921: TCGv_i64 fp1 = tcg_temp_new_i64();
7922: TCGv_i64 fp2 = tcg_temp_new_i64();
7923:
7924: gen_load_fpr64(ctx, fp0, fs);
7925: gen_load_fpr64(ctx, fp1, ft);
7926: gen_load_fpr64(ctx, fp2, fr);
7927: gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7928: tcg_temp_free_i64(fp0);
7929: tcg_temp_free_i64(fp1);
7930: gen_store_fpr64(ctx, fp2, fd);
7931: tcg_temp_free_i64(fp2);
7932: }
1.1.1.6 root 7933: opn = "madd.ps";
1.1.1.4 root 7934: break;
1.1.1.6 root 7935: case OPC_MSUB_S:
7936: check_cop1x(ctx);
1.1.1.7 root 7937: {
7938: TCGv_i32 fp0 = tcg_temp_new_i32();
7939: TCGv_i32 fp1 = tcg_temp_new_i32();
7940: TCGv_i32 fp2 = tcg_temp_new_i32();
7941:
7942: gen_load_fpr32(fp0, fs);
7943: gen_load_fpr32(fp1, ft);
7944: gen_load_fpr32(fp2, fr);
7945: gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7946: tcg_temp_free_i32(fp0);
7947: tcg_temp_free_i32(fp1);
7948: gen_store_fpr32(fp2, fd);
7949: tcg_temp_free_i32(fp2);
7950: }
1.1.1.6 root 7951: opn = "msub.s";
1.1.1.4 root 7952: break;
1.1.1.6 root 7953: case OPC_MSUB_D:
7954: check_cop1x(ctx);
7955: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7956: {
7957: TCGv_i64 fp0 = tcg_temp_new_i64();
7958: TCGv_i64 fp1 = tcg_temp_new_i64();
7959: TCGv_i64 fp2 = tcg_temp_new_i64();
7960:
7961: gen_load_fpr64(ctx, fp0, fs);
7962: gen_load_fpr64(ctx, fp1, ft);
7963: gen_load_fpr64(ctx, fp2, fr);
7964: gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7965: tcg_temp_free_i64(fp0);
7966: tcg_temp_free_i64(fp1);
7967: gen_store_fpr64(ctx, fp2, fd);
7968: tcg_temp_free_i64(fp2);
7969: }
1.1.1.6 root 7970: opn = "msub.d";
7971: break;
7972: case OPC_MSUB_PS:
7973: check_cp1_64bitmode(ctx);
1.1.1.7 root 7974: {
7975: TCGv_i64 fp0 = tcg_temp_new_i64();
7976: TCGv_i64 fp1 = tcg_temp_new_i64();
7977: TCGv_i64 fp2 = tcg_temp_new_i64();
7978:
7979: gen_load_fpr64(ctx, fp0, fs);
7980: gen_load_fpr64(ctx, fp1, ft);
7981: gen_load_fpr64(ctx, fp2, fr);
7982: gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7983: tcg_temp_free_i64(fp0);
7984: tcg_temp_free_i64(fp1);
7985: gen_store_fpr64(ctx, fp2, fd);
7986: tcg_temp_free_i64(fp2);
7987: }
1.1.1.6 root 7988: opn = "msub.ps";
1.1.1.4 root 7989: break;
1.1.1.6 root 7990: case OPC_NMADD_S:
7991: check_cop1x(ctx);
1.1.1.7 root 7992: {
7993: TCGv_i32 fp0 = tcg_temp_new_i32();
7994: TCGv_i32 fp1 = tcg_temp_new_i32();
7995: TCGv_i32 fp2 = tcg_temp_new_i32();
7996:
7997: gen_load_fpr32(fp0, fs);
7998: gen_load_fpr32(fp1, ft);
7999: gen_load_fpr32(fp2, fr);
8000: gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
8001: tcg_temp_free_i32(fp0);
8002: tcg_temp_free_i32(fp1);
8003: gen_store_fpr32(fp2, fd);
8004: tcg_temp_free_i32(fp2);
8005: }
1.1.1.6 root 8006: opn = "nmadd.s";
1.1.1.4 root 8007: break;
1.1.1.6 root 8008: case OPC_NMADD_D:
8009: check_cop1x(ctx);
8010: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 8011: {
8012: TCGv_i64 fp0 = tcg_temp_new_i64();
8013: TCGv_i64 fp1 = tcg_temp_new_i64();
8014: TCGv_i64 fp2 = tcg_temp_new_i64();
8015:
8016: gen_load_fpr64(ctx, fp0, fs);
8017: gen_load_fpr64(ctx, fp1, ft);
8018: gen_load_fpr64(ctx, fp2, fr);
8019: gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
8020: tcg_temp_free_i64(fp0);
8021: tcg_temp_free_i64(fp1);
8022: gen_store_fpr64(ctx, fp2, fd);
8023: tcg_temp_free_i64(fp2);
8024: }
1.1.1.6 root 8025: opn = "nmadd.d";
1.1.1.5 root 8026: break;
1.1.1.6 root 8027: case OPC_NMADD_PS:
8028: check_cp1_64bitmode(ctx);
1.1.1.7 root 8029: {
8030: TCGv_i64 fp0 = tcg_temp_new_i64();
8031: TCGv_i64 fp1 = tcg_temp_new_i64();
8032: TCGv_i64 fp2 = tcg_temp_new_i64();
8033:
8034: gen_load_fpr64(ctx, fp0, fs);
8035: gen_load_fpr64(ctx, fp1, ft);
8036: gen_load_fpr64(ctx, fp2, fr);
8037: gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
8038: tcg_temp_free_i64(fp0);
8039: tcg_temp_free_i64(fp1);
8040: gen_store_fpr64(ctx, fp2, fd);
8041: tcg_temp_free_i64(fp2);
8042: }
1.1.1.6 root 8043: opn = "nmadd.ps";
1.1.1.4 root 8044: break;
1.1.1.6 root 8045: case OPC_NMSUB_S:
8046: check_cop1x(ctx);
1.1.1.7 root 8047: {
8048: TCGv_i32 fp0 = tcg_temp_new_i32();
8049: TCGv_i32 fp1 = tcg_temp_new_i32();
8050: TCGv_i32 fp2 = tcg_temp_new_i32();
8051:
8052: gen_load_fpr32(fp0, fs);
8053: gen_load_fpr32(fp1, ft);
8054: gen_load_fpr32(fp2, fr);
8055: gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
8056: tcg_temp_free_i32(fp0);
8057: tcg_temp_free_i32(fp1);
8058: gen_store_fpr32(fp2, fd);
8059: tcg_temp_free_i32(fp2);
8060: }
1.1.1.6 root 8061: opn = "nmsub.s";
1.1.1.4 root 8062: break;
1.1.1.6 root 8063: case OPC_NMSUB_D:
8064: check_cop1x(ctx);
8065: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 8066: {
8067: TCGv_i64 fp0 = tcg_temp_new_i64();
8068: TCGv_i64 fp1 = tcg_temp_new_i64();
8069: TCGv_i64 fp2 = tcg_temp_new_i64();
8070:
8071: gen_load_fpr64(ctx, fp0, fs);
8072: gen_load_fpr64(ctx, fp1, ft);
8073: gen_load_fpr64(ctx, fp2, fr);
8074: gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
8075: tcg_temp_free_i64(fp0);
8076: tcg_temp_free_i64(fp1);
8077: gen_store_fpr64(ctx, fp2, fd);
8078: tcg_temp_free_i64(fp2);
8079: }
1.1.1.6 root 8080: opn = "nmsub.d";
1.1.1.4 root 8081: break;
1.1.1.6 root 8082: case OPC_NMSUB_PS:
8083: check_cp1_64bitmode(ctx);
1.1.1.7 root 8084: {
8085: TCGv_i64 fp0 = tcg_temp_new_i64();
8086: TCGv_i64 fp1 = tcg_temp_new_i64();
8087: TCGv_i64 fp2 = tcg_temp_new_i64();
8088:
8089: gen_load_fpr64(ctx, fp0, fs);
8090: gen_load_fpr64(ctx, fp1, ft);
8091: gen_load_fpr64(ctx, fp2, fr);
8092: gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
8093: tcg_temp_free_i64(fp0);
8094: tcg_temp_free_i64(fp1);
8095: gen_store_fpr64(ctx, fp2, fd);
8096: tcg_temp_free_i64(fp2);
8097: }
1.1.1.6 root 8098: opn = "nmsub.ps";
1.1.1.4 root 8099: break;
1.1.1.6 root 8100: default:
8101: MIPS_INVAL(opn);
8102: generate_exception (ctx, EXCP_RI);
1.1.1.4 root 8103: return;
8104: }
1.1.1.13 root 8105: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 8106: MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8107: fregnames[fs], fregnames[ft]);
1.1 root 8108: }
8109:
1.1.1.12 root 8110: static void
1.1.1.16! root 8111: gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
1.1.1.12 root 8112: {
8113: TCGv t0;
1.1 root 8114:
1.1.1.12 root 8115: check_insn(env, ctx, ISA_MIPS32R2);
8116: t0 = tcg_temp_new();
1.1 root 8117:
1.1.1.12 root 8118: switch (rd) {
8119: case 0:
8120: save_cpu_state(ctx, 1);
8121: gen_helper_rdhwr_cpunum(t0);
8122: gen_store_gpr(t0, rt);
8123: break;
8124: case 1:
8125: save_cpu_state(ctx, 1);
8126: gen_helper_rdhwr_synci_step(t0);
8127: gen_store_gpr(t0, rt);
8128: break;
8129: case 2:
8130: save_cpu_state(ctx, 1);
8131: gen_helper_rdhwr_cc(t0);
8132: gen_store_gpr(t0, rt);
8133: break;
8134: case 3:
8135: save_cpu_state(ctx, 1);
8136: gen_helper_rdhwr_ccres(t0);
8137: gen_store_gpr(t0, rt);
8138: break;
8139: case 29:
8140: #if defined(CONFIG_USER_ONLY)
1.1.1.16! root 8141: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
1.1.1.12 root 8142: gen_store_gpr(t0, rt);
8143: break;
8144: #else
8145: /* XXX: Some CPUs implement this in hardware.
8146: Not supported yet. */
1.1 root 8147: #endif
1.1.1.12 root 8148: default: /* Invalid */
8149: MIPS_INVAL("rdhwr");
8150: generate_exception(ctx, EXCP_RI);
8151: break;
1.1.1.4 root 8152: }
1.1.1.12 root 8153: tcg_temp_free(t0);
8154: }
1.1.1.4 root 8155:
1.1.1.16! root 8156: static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
1.1.1.12 root 8157: int insn_bytes)
8158: {
8159: if (ctx->hflags & MIPS_HFLAG_BMASK) {
8160: int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8161: /* Branches completion */
8162: ctx->hflags &= ~MIPS_HFLAG_BMASK;
8163: ctx->bstate = BS_BRANCH;
8164: save_cpu_state(ctx, 0);
8165: /* FIXME: Need to clear can_do_io. */
8166: switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
8167: case MIPS_HFLAG_B:
8168: /* unconditional branch */
8169: MIPS_DEBUG("unconditional branch");
8170: if (proc_hflags & MIPS_HFLAG_BX) {
8171: tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8172: }
8173: gen_goto_tb(ctx, 0, ctx->btarget);
8174: break;
8175: case MIPS_HFLAG_BL:
8176: /* blikely taken case */
8177: MIPS_DEBUG("blikely branch taken");
8178: gen_goto_tb(ctx, 0, ctx->btarget);
8179: break;
8180: case MIPS_HFLAG_BC:
8181: /* Conditional branch */
8182: MIPS_DEBUG("conditional branch");
8183: {
8184: int l1 = gen_new_label();
1.1.1.7 root 8185:
1.1.1.12 root 8186: tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8187: gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8188: gen_set_label(l1);
8189: gen_goto_tb(ctx, 0, ctx->btarget);
8190: }
8191: break;
8192: case MIPS_HFLAG_BR:
8193: /* unconditional branch to register */
8194: MIPS_DEBUG("branch to register");
8195: if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
8196: TCGv t0 = tcg_temp_new();
8197: TCGv_i32 t1 = tcg_temp_new_i32();
8198:
8199: tcg_gen_andi_tl(t0, btarget, 0x1);
8200: tcg_gen_trunc_tl_i32(t1, t0);
8201: tcg_temp_free(t0);
8202: tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8203: tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8204: tcg_gen_or_i32(hflags, hflags, t1);
8205: tcg_temp_free_i32(t1);
8206:
8207: tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8208: } else {
8209: tcg_gen_mov_tl(cpu_PC, btarget);
8210: }
8211: if (ctx->singlestep_enabled) {
8212: save_cpu_state(ctx, 0);
8213: gen_helper_0i(raise_exception, EXCP_DEBUG);
8214: }
8215: tcg_gen_exit_tb(0);
8216: break;
8217: default:
8218: MIPS_DEBUG("unknown branch");
8219: break;
8220: }
8221: }
8222: }
8223:
8224: /* ISA extensions (ASEs) */
8225: /* MIPS16 extension to MIPS32 */
8226:
8227: /* MIPS16 major opcodes */
8228: enum {
8229: M16_OPC_ADDIUSP = 0x00,
8230: M16_OPC_ADDIUPC = 0x01,
8231: M16_OPC_B = 0x02,
8232: M16_OPC_JAL = 0x03,
8233: M16_OPC_BEQZ = 0x04,
8234: M16_OPC_BNEQZ = 0x05,
8235: M16_OPC_SHIFT = 0x06,
8236: M16_OPC_LD = 0x07,
8237: M16_OPC_RRIA = 0x08,
8238: M16_OPC_ADDIU8 = 0x09,
8239: M16_OPC_SLTI = 0x0a,
8240: M16_OPC_SLTIU = 0x0b,
8241: M16_OPC_I8 = 0x0c,
8242: M16_OPC_LI = 0x0d,
8243: M16_OPC_CMPI = 0x0e,
8244: M16_OPC_SD = 0x0f,
8245: M16_OPC_LB = 0x10,
8246: M16_OPC_LH = 0x11,
8247: M16_OPC_LWSP = 0x12,
8248: M16_OPC_LW = 0x13,
8249: M16_OPC_LBU = 0x14,
8250: M16_OPC_LHU = 0x15,
8251: M16_OPC_LWPC = 0x16,
8252: M16_OPC_LWU = 0x17,
8253: M16_OPC_SB = 0x18,
8254: M16_OPC_SH = 0x19,
8255: M16_OPC_SWSP = 0x1a,
8256: M16_OPC_SW = 0x1b,
8257: M16_OPC_RRR = 0x1c,
8258: M16_OPC_RR = 0x1d,
8259: M16_OPC_EXTEND = 0x1e,
8260: M16_OPC_I64 = 0x1f
8261: };
8262:
8263: /* I8 funct field */
8264: enum {
8265: I8_BTEQZ = 0x0,
8266: I8_BTNEZ = 0x1,
8267: I8_SWRASP = 0x2,
8268: I8_ADJSP = 0x3,
8269: I8_SVRS = 0x4,
8270: I8_MOV32R = 0x5,
8271: I8_MOVR32 = 0x7
8272: };
8273:
8274: /* RRR f field */
8275: enum {
8276: RRR_DADDU = 0x0,
8277: RRR_ADDU = 0x1,
8278: RRR_DSUBU = 0x2,
8279: RRR_SUBU = 0x3
8280: };
8281:
8282: /* RR funct field */
8283: enum {
8284: RR_JR = 0x00,
8285: RR_SDBBP = 0x01,
8286: RR_SLT = 0x02,
8287: RR_SLTU = 0x03,
8288: RR_SLLV = 0x04,
8289: RR_BREAK = 0x05,
8290: RR_SRLV = 0x06,
8291: RR_SRAV = 0x07,
8292: RR_DSRL = 0x08,
8293: RR_CMP = 0x0a,
8294: RR_NEG = 0x0b,
8295: RR_AND = 0x0c,
8296: RR_OR = 0x0d,
8297: RR_XOR = 0x0e,
8298: RR_NOT = 0x0f,
8299: RR_MFHI = 0x10,
8300: RR_CNVT = 0x11,
8301: RR_MFLO = 0x12,
8302: RR_DSRA = 0x13,
8303: RR_DSLLV = 0x14,
8304: RR_DSRLV = 0x16,
8305: RR_DSRAV = 0x17,
8306: RR_MULT = 0x18,
8307: RR_MULTU = 0x19,
8308: RR_DIV = 0x1a,
8309: RR_DIVU = 0x1b,
8310: RR_DMULT = 0x1c,
8311: RR_DMULTU = 0x1d,
8312: RR_DDIV = 0x1e,
8313: RR_DDIVU = 0x1f
8314: };
8315:
8316: /* I64 funct field */
8317: enum {
8318: I64_LDSP = 0x0,
8319: I64_SDSP = 0x1,
8320: I64_SDRASP = 0x2,
8321: I64_DADJSP = 0x3,
8322: I64_LDPC = 0x4,
8323: I64_DADDIU5 = 0x5,
8324: I64_DADDIUPC = 0x6,
8325: I64_DADDIUSP = 0x7
8326: };
8327:
8328: /* RR ry field for CNVT */
8329: enum {
8330: RR_RY_CNVT_ZEB = 0x0,
8331: RR_RY_CNVT_ZEH = 0x1,
8332: RR_RY_CNVT_ZEW = 0x2,
8333: RR_RY_CNVT_SEB = 0x4,
8334: RR_RY_CNVT_SEH = 0x5,
8335: RR_RY_CNVT_SEW = 0x6,
8336: };
8337:
8338: static int xlat (int r)
8339: {
8340: static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8341:
8342: return map[r];
8343: }
8344:
8345: static void gen_mips16_save (DisasContext *ctx,
8346: int xsregs, int aregs,
8347: int do_ra, int do_s0, int do_s1,
8348: int framesize)
8349: {
8350: TCGv t0 = tcg_temp_new();
8351: TCGv t1 = tcg_temp_new();
8352: int args, astatic;
8353:
8354: switch (aregs) {
8355: case 0:
8356: case 1:
8357: case 2:
8358: case 3:
8359: case 11:
8360: args = 0;
8361: break;
8362: case 4:
8363: case 5:
8364: case 6:
8365: case 7:
8366: args = 1;
8367: break;
8368: case 8:
8369: case 9:
8370: case 10:
8371: args = 2;
8372: break;
8373: case 12:
8374: case 13:
8375: args = 3;
8376: break;
8377: case 14:
8378: args = 4;
8379: break;
8380: default:
8381: generate_exception(ctx, EXCP_RI);
8382: return;
8383: }
8384:
8385: switch (args) {
8386: case 4:
8387: gen_base_offset_addr(ctx, t0, 29, 12);
8388: gen_load_gpr(t1, 7);
8389: op_st_sw(t1, t0, ctx);
8390: /* Fall through */
8391: case 3:
8392: gen_base_offset_addr(ctx, t0, 29, 8);
8393: gen_load_gpr(t1, 6);
8394: op_st_sw(t1, t0, ctx);
8395: /* Fall through */
8396: case 2:
8397: gen_base_offset_addr(ctx, t0, 29, 4);
8398: gen_load_gpr(t1, 5);
8399: op_st_sw(t1, t0, ctx);
8400: /* Fall through */
8401: case 1:
8402: gen_base_offset_addr(ctx, t0, 29, 0);
8403: gen_load_gpr(t1, 4);
8404: op_st_sw(t1, t0, ctx);
8405: }
8406:
8407: gen_load_gpr(t0, 29);
8408:
8409: #define DECR_AND_STORE(reg) do { \
8410: tcg_gen_subi_tl(t0, t0, 4); \
8411: gen_load_gpr(t1, reg); \
8412: op_st_sw(t1, t0, ctx); \
8413: } while (0)
8414:
8415: if (do_ra) {
8416: DECR_AND_STORE(31);
8417: }
8418:
8419: switch (xsregs) {
8420: case 7:
8421: DECR_AND_STORE(30);
8422: /* Fall through */
8423: case 6:
8424: DECR_AND_STORE(23);
8425: /* Fall through */
8426: case 5:
8427: DECR_AND_STORE(22);
8428: /* Fall through */
8429: case 4:
8430: DECR_AND_STORE(21);
8431: /* Fall through */
8432: case 3:
8433: DECR_AND_STORE(20);
8434: /* Fall through */
8435: case 2:
8436: DECR_AND_STORE(19);
8437: /* Fall through */
8438: case 1:
8439: DECR_AND_STORE(18);
8440: }
8441:
8442: if (do_s1) {
8443: DECR_AND_STORE(17);
8444: }
8445: if (do_s0) {
8446: DECR_AND_STORE(16);
8447: }
8448:
8449: switch (aregs) {
8450: case 0:
8451: case 4:
8452: case 8:
8453: case 12:
8454: case 14:
8455: astatic = 0;
8456: break;
8457: case 1:
8458: case 5:
8459: case 9:
8460: case 13:
8461: astatic = 1;
8462: break;
8463: case 2:
8464: case 6:
8465: case 10:
8466: astatic = 2;
8467: break;
8468: case 3:
8469: case 7:
8470: astatic = 3;
8471: break;
8472: case 11:
8473: astatic = 4;
8474: break;
8475: default:
8476: generate_exception(ctx, EXCP_RI);
8477: return;
8478: }
8479:
8480: if (astatic > 0) {
8481: DECR_AND_STORE(7);
8482: if (astatic > 1) {
8483: DECR_AND_STORE(6);
8484: if (astatic > 2) {
8485: DECR_AND_STORE(5);
8486: if (astatic > 3) {
8487: DECR_AND_STORE(4);
8488: }
8489: }
8490: }
8491: }
8492: #undef DECR_AND_STORE
8493:
8494: tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8495: tcg_temp_free(t0);
8496: tcg_temp_free(t1);
8497: }
8498:
8499: static void gen_mips16_restore (DisasContext *ctx,
8500: int xsregs, int aregs,
8501: int do_ra, int do_s0, int do_s1,
8502: int framesize)
8503: {
8504: int astatic;
8505: TCGv t0 = tcg_temp_new();
8506: TCGv t1 = tcg_temp_new();
8507:
8508: tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8509:
8510: #define DECR_AND_LOAD(reg) do { \
8511: tcg_gen_subi_tl(t0, t0, 4); \
8512: op_ld_lw(t1, t0, ctx); \
8513: gen_store_gpr(t1, reg); \
8514: } while (0)
8515:
8516: if (do_ra) {
8517: DECR_AND_LOAD(31);
8518: }
8519:
8520: switch (xsregs) {
8521: case 7:
8522: DECR_AND_LOAD(30);
8523: /* Fall through */
8524: case 6:
8525: DECR_AND_LOAD(23);
8526: /* Fall through */
8527: case 5:
8528: DECR_AND_LOAD(22);
8529: /* Fall through */
8530: case 4:
8531: DECR_AND_LOAD(21);
8532: /* Fall through */
8533: case 3:
8534: DECR_AND_LOAD(20);
8535: /* Fall through */
8536: case 2:
8537: DECR_AND_LOAD(19);
8538: /* Fall through */
8539: case 1:
8540: DECR_AND_LOAD(18);
8541: }
8542:
8543: if (do_s1) {
8544: DECR_AND_LOAD(17);
8545: }
8546: if (do_s0) {
8547: DECR_AND_LOAD(16);
8548: }
8549:
8550: switch (aregs) {
8551: case 0:
8552: case 4:
8553: case 8:
8554: case 12:
8555: case 14:
8556: astatic = 0;
8557: break;
8558: case 1:
8559: case 5:
8560: case 9:
8561: case 13:
8562: astatic = 1;
8563: break;
8564: case 2:
8565: case 6:
8566: case 10:
8567: astatic = 2;
8568: break;
8569: case 3:
8570: case 7:
8571: astatic = 3;
8572: break;
8573: case 11:
8574: astatic = 4;
8575: break;
8576: default:
8577: generate_exception(ctx, EXCP_RI);
8578: return;
8579: }
8580:
8581: if (astatic > 0) {
8582: DECR_AND_LOAD(7);
8583: if (astatic > 1) {
8584: DECR_AND_LOAD(6);
8585: if (astatic > 2) {
8586: DECR_AND_LOAD(5);
8587: if (astatic > 3) {
8588: DECR_AND_LOAD(4);
8589: }
8590: }
8591: }
8592: }
8593: #undef DECR_AND_LOAD
8594:
8595: tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8596: tcg_temp_free(t0);
8597: tcg_temp_free(t1);
8598: }
8599:
8600: static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8601: int is_64_bit, int extended)
8602: {
8603: TCGv t0;
8604:
8605: if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8606: generate_exception(ctx, EXCP_RI);
8607: return;
8608: }
8609:
8610: t0 = tcg_temp_new();
8611:
8612: tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8613: tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8614: if (!is_64_bit) {
8615: tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8616: }
8617:
8618: tcg_temp_free(t0);
8619: }
8620:
8621: #if defined(TARGET_MIPS64)
1.1.1.16! root 8622: static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
1.1.1.12 root 8623: int ry, int funct, int16_t offset,
8624: int extended)
8625: {
8626: switch (funct) {
8627: case I64_LDSP:
8628: check_mips_64(ctx);
8629: offset = extended ? offset : offset << 3;
8630: gen_ld(env, ctx, OPC_LD, ry, 29, offset);
8631: break;
8632: case I64_SDSP:
8633: check_mips_64(ctx);
8634: offset = extended ? offset : offset << 3;
8635: gen_st(ctx, OPC_SD, ry, 29, offset);
8636: break;
8637: case I64_SDRASP:
8638: check_mips_64(ctx);
8639: offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8640: gen_st(ctx, OPC_SD, 31, 29, offset);
8641: break;
8642: case I64_DADJSP:
8643: check_mips_64(ctx);
8644: offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8645: gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8646: break;
8647: case I64_LDPC:
8648: if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8649: generate_exception(ctx, EXCP_RI);
8650: } else {
8651: offset = extended ? offset : offset << 3;
8652: gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
8653: }
8654: break;
8655: case I64_DADDIU5:
8656: check_mips_64(ctx);
8657: offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8658: gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8659: break;
8660: case I64_DADDIUPC:
8661: check_mips_64(ctx);
8662: offset = extended ? offset : offset << 2;
8663: gen_addiupc(ctx, ry, offset, 1, extended);
8664: break;
8665: case I64_DADDIUSP:
8666: check_mips_64(ctx);
8667: offset = extended ? offset : offset << 2;
8668: gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8669: break;
8670: }
8671: }
8672: #endif
8673:
1.1.1.16! root 8674: static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
1.1.1.12 root 8675: int *is_branch)
8676: {
8677: int extend = lduw_code(ctx->pc + 2);
8678: int op, rx, ry, funct, sa;
8679: int16_t imm, offset;
8680:
8681: ctx->opcode = (ctx->opcode << 16) | extend;
8682: op = (ctx->opcode >> 11) & 0x1f;
8683: sa = (ctx->opcode >> 22) & 0x1f;
8684: funct = (ctx->opcode >> 8) & 0x7;
8685: rx = xlat((ctx->opcode >> 8) & 0x7);
8686: ry = xlat((ctx->opcode >> 5) & 0x7);
8687: offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8688: | ((ctx->opcode >> 21) & 0x3f) << 5
8689: | (ctx->opcode & 0x1f));
8690:
8691: /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8692: counterparts. */
8693: switch (op) {
8694: case M16_OPC_ADDIUSP:
8695: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8696: break;
8697: case M16_OPC_ADDIUPC:
8698: gen_addiupc(ctx, rx, imm, 0, 1);
8699: break;
8700: case M16_OPC_B:
8701: gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8702: /* No delay slot, so just process as a normal instruction */
8703: break;
8704: case M16_OPC_BEQZ:
8705: gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8706: /* No delay slot, so just process as a normal instruction */
8707: break;
8708: case M16_OPC_BNEQZ:
8709: gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8710: /* No delay slot, so just process as a normal instruction */
8711: break;
8712: case M16_OPC_SHIFT:
8713: switch (ctx->opcode & 0x3) {
8714: case 0x0:
8715: gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8716: break;
8717: case 0x1:
8718: #if defined(TARGET_MIPS64)
8719: check_mips_64(ctx);
8720: gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8721: #else
8722: generate_exception(ctx, EXCP_RI);
8723: #endif
8724: break;
8725: case 0x2:
8726: gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8727: break;
8728: case 0x3:
8729: gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8730: break;
8731: }
8732: break;
8733: #if defined(TARGET_MIPS64)
8734: case M16_OPC_LD:
8735: check_mips_64(ctx);
8736: gen_ld(env, ctx, OPC_LD, ry, rx, offset);
8737: break;
8738: #endif
8739: case M16_OPC_RRIA:
8740: imm = ctx->opcode & 0xf;
8741: imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8742: imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8743: imm = (int16_t) (imm << 1) >> 1;
8744: if ((ctx->opcode >> 4) & 0x1) {
8745: #if defined(TARGET_MIPS64)
8746: check_mips_64(ctx);
8747: gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8748: #else
8749: generate_exception(ctx, EXCP_RI);
8750: #endif
8751: } else {
8752: gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8753: }
8754: break;
8755: case M16_OPC_ADDIU8:
8756: gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8757: break;
8758: case M16_OPC_SLTI:
8759: gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8760: break;
8761: case M16_OPC_SLTIU:
8762: gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8763: break;
8764: case M16_OPC_I8:
8765: switch (funct) {
8766: case I8_BTEQZ:
8767: gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8768: break;
8769: case I8_BTNEZ:
8770: gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8771: break;
8772: case I8_SWRASP:
8773: gen_st(ctx, OPC_SW, 31, 29, imm);
8774: break;
8775: case I8_ADJSP:
8776: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8777: break;
8778: case I8_SVRS:
8779: {
8780: int xsregs = (ctx->opcode >> 24) & 0x7;
8781: int aregs = (ctx->opcode >> 16) & 0xf;
8782: int do_ra = (ctx->opcode >> 6) & 0x1;
8783: int do_s0 = (ctx->opcode >> 5) & 0x1;
8784: int do_s1 = (ctx->opcode >> 4) & 0x1;
8785: int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8786: | (ctx->opcode & 0xf)) << 3;
8787:
8788: if (ctx->opcode & (1 << 7)) {
8789: gen_mips16_save(ctx, xsregs, aregs,
8790: do_ra, do_s0, do_s1,
8791: framesize);
8792: } else {
8793: gen_mips16_restore(ctx, xsregs, aregs,
8794: do_ra, do_s0, do_s1,
8795: framesize);
8796: }
8797: }
8798: break;
8799: default:
8800: generate_exception(ctx, EXCP_RI);
8801: break;
8802: }
8803: break;
8804: case M16_OPC_LI:
8805: tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8806: break;
8807: case M16_OPC_CMPI:
8808: tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8809: break;
8810: #if defined(TARGET_MIPS64)
8811: case M16_OPC_SD:
8812: gen_st(ctx, OPC_SD, ry, rx, offset);
8813: break;
8814: #endif
8815: case M16_OPC_LB:
8816: gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8817: break;
8818: case M16_OPC_LH:
8819: gen_ld(env, ctx, OPC_LH, ry, rx, offset);
8820: break;
8821: case M16_OPC_LWSP:
8822: gen_ld(env, ctx, OPC_LW, rx, 29, offset);
8823: break;
8824: case M16_OPC_LW:
8825: gen_ld(env, ctx, OPC_LW, ry, rx, offset);
8826: break;
8827: case M16_OPC_LBU:
8828: gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
8829: break;
8830: case M16_OPC_LHU:
8831: gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
8832: break;
8833: case M16_OPC_LWPC:
8834: gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
8835: break;
8836: #if defined(TARGET_MIPS64)
8837: case M16_OPC_LWU:
8838: gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
8839: break;
8840: #endif
8841: case M16_OPC_SB:
8842: gen_st(ctx, OPC_SB, ry, rx, offset);
8843: break;
8844: case M16_OPC_SH:
8845: gen_st(ctx, OPC_SH, ry, rx, offset);
8846: break;
8847: case M16_OPC_SWSP:
8848: gen_st(ctx, OPC_SW, rx, 29, offset);
8849: break;
8850: case M16_OPC_SW:
8851: gen_st(ctx, OPC_SW, ry, rx, offset);
8852: break;
8853: #if defined(TARGET_MIPS64)
8854: case M16_OPC_I64:
8855: decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8856: break;
8857: #endif
8858: default:
8859: generate_exception(ctx, EXCP_RI);
8860: break;
8861: }
8862:
8863: return 4;
8864: }
8865:
1.1.1.16! root 8866: static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
1.1.1.12 root 8867: int *is_branch)
8868: {
8869: int rx, ry;
8870: int sa;
8871: int op, cnvt_op, op1, offset;
8872: int funct;
8873: int n_bytes;
8874:
8875: op = (ctx->opcode >> 11) & 0x1f;
8876: sa = (ctx->opcode >> 2) & 0x7;
8877: sa = sa == 0 ? 8 : sa;
8878: rx = xlat((ctx->opcode >> 8) & 0x7);
8879: cnvt_op = (ctx->opcode >> 5) & 0x7;
8880: ry = xlat((ctx->opcode >> 5) & 0x7);
8881: op1 = offset = ctx->opcode & 0x1f;
8882:
8883: n_bytes = 2;
8884:
8885: switch (op) {
8886: case M16_OPC_ADDIUSP:
8887: {
8888: int16_t imm = ((uint8_t) ctx->opcode) << 2;
8889:
8890: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8891: }
8892: break;
8893: case M16_OPC_ADDIUPC:
8894: gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8895: break;
8896: case M16_OPC_B:
8897: offset = (ctx->opcode & 0x7ff) << 1;
8898: offset = (int16_t)(offset << 4) >> 4;
8899: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8900: /* No delay slot, so just process as a normal instruction */
8901: break;
8902: case M16_OPC_JAL:
8903: offset = lduw_code(ctx->pc + 2);
8904: offset = (((ctx->opcode & 0x1f) << 21)
8905: | ((ctx->opcode >> 5) & 0x1f) << 16
8906: | offset) << 2;
8907: op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
8908: gen_compute_branch(ctx, op, 4, rx, ry, offset);
8909: n_bytes = 4;
8910: *is_branch = 1;
8911: break;
8912: case M16_OPC_BEQZ:
8913: gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8914: /* No delay slot, so just process as a normal instruction */
8915: break;
8916: case M16_OPC_BNEQZ:
8917: gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8918: /* No delay slot, so just process as a normal instruction */
8919: break;
8920: case M16_OPC_SHIFT:
8921: switch (ctx->opcode & 0x3) {
8922: case 0x0:
8923: gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8924: break;
8925: case 0x1:
8926: #if defined(TARGET_MIPS64)
8927: check_mips_64(ctx);
8928: gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8929: #else
8930: generate_exception(ctx, EXCP_RI);
8931: #endif
8932: break;
8933: case 0x2:
8934: gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8935: break;
8936: case 0x3:
8937: gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8938: break;
8939: }
8940: break;
8941: #if defined(TARGET_MIPS64)
8942: case M16_OPC_LD:
8943: check_mips_64(ctx);
8944: gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
8945: break;
8946: #endif
8947: case M16_OPC_RRIA:
8948: {
8949: int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8950:
8951: if ((ctx->opcode >> 4) & 1) {
8952: #if defined(TARGET_MIPS64)
8953: check_mips_64(ctx);
8954: gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8955: #else
8956: generate_exception(ctx, EXCP_RI);
8957: #endif
8958: } else {
8959: gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8960: }
8961: }
8962: break;
8963: case M16_OPC_ADDIU8:
8964: {
8965: int16_t imm = (int8_t) ctx->opcode;
8966:
8967: gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8968: }
8969: break;
8970: case M16_OPC_SLTI:
8971: {
8972: int16_t imm = (uint8_t) ctx->opcode;
8973:
8974: gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8975: }
8976: break;
8977: case M16_OPC_SLTIU:
8978: {
8979: int16_t imm = (uint8_t) ctx->opcode;
8980:
8981: gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8982: }
8983: break;
8984: case M16_OPC_I8:
8985: {
8986: int reg32;
8987:
8988: funct = (ctx->opcode >> 8) & 0x7;
8989: switch (funct) {
8990: case I8_BTEQZ:
8991: gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8992: ((int8_t)ctx->opcode) << 1);
8993: break;
8994: case I8_BTNEZ:
8995: gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8996: ((int8_t)ctx->opcode) << 1);
8997: break;
8998: case I8_SWRASP:
8999: gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
9000: break;
9001: case I8_ADJSP:
9002: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
9003: ((int8_t)ctx->opcode) << 3);
9004: break;
9005: case I8_SVRS:
9006: {
9007: int do_ra = ctx->opcode & (1 << 6);
9008: int do_s0 = ctx->opcode & (1 << 5);
9009: int do_s1 = ctx->opcode & (1 << 4);
9010: int framesize = ctx->opcode & 0xf;
9011:
9012: if (framesize == 0) {
9013: framesize = 128;
9014: } else {
9015: framesize = framesize << 3;
9016: }
9017:
9018: if (ctx->opcode & (1 << 7)) {
9019: gen_mips16_save(ctx, 0, 0,
9020: do_ra, do_s0, do_s1, framesize);
9021: } else {
9022: gen_mips16_restore(ctx, 0, 0,
9023: do_ra, do_s0, do_s1, framesize);
9024: }
9025: }
9026: break;
9027: case I8_MOV32R:
9028: {
9029: int rz = xlat(ctx->opcode & 0x7);
9030:
9031: reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9032: ((ctx->opcode >> 5) & 0x7);
9033: gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
9034: }
9035: break;
9036: case I8_MOVR32:
9037: reg32 = ctx->opcode & 0x1f;
9038: gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
9039: break;
9040: default:
9041: generate_exception(ctx, EXCP_RI);
9042: break;
9043: }
9044: }
9045: break;
9046: case M16_OPC_LI:
9047: {
9048: int16_t imm = (uint8_t) ctx->opcode;
9049:
9050: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
9051: }
9052: break;
9053: case M16_OPC_CMPI:
9054: {
9055: int16_t imm = (uint8_t) ctx->opcode;
9056:
9057: gen_logic_imm(env, OPC_XORI, 24, rx, imm);
9058: }
9059: break;
9060: #if defined(TARGET_MIPS64)
9061: case M16_OPC_SD:
9062: check_mips_64(ctx);
9063: gen_st(ctx, OPC_SD, ry, rx, offset << 3);
9064: break;
9065: #endif
9066: case M16_OPC_LB:
9067: gen_ld(env, ctx, OPC_LB, ry, rx, offset);
9068: break;
9069: case M16_OPC_LH:
9070: gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
9071: break;
9072: case M16_OPC_LWSP:
9073: gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9074: break;
9075: case M16_OPC_LW:
9076: gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
9077: break;
9078: case M16_OPC_LBU:
9079: gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
9080: break;
9081: case M16_OPC_LHU:
9082: gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
9083: break;
9084: case M16_OPC_LWPC:
9085: gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
9086: break;
9087: #if defined (TARGET_MIPS64)
9088: case M16_OPC_LWU:
9089: check_mips_64(ctx);
9090: gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
9091: break;
9092: #endif
9093: case M16_OPC_SB:
9094: gen_st(ctx, OPC_SB, ry, rx, offset);
9095: break;
9096: case M16_OPC_SH:
9097: gen_st(ctx, OPC_SH, ry, rx, offset << 1);
9098: break;
9099: case M16_OPC_SWSP:
9100: gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9101: break;
9102: case M16_OPC_SW:
9103: gen_st(ctx, OPC_SW, ry, rx, offset << 2);
9104: break;
9105: case M16_OPC_RRR:
9106: {
9107: int rz = xlat((ctx->opcode >> 2) & 0x7);
9108: int mips32_op;
9109:
9110: switch (ctx->opcode & 0x3) {
9111: case RRR_ADDU:
9112: mips32_op = OPC_ADDU;
9113: break;
9114: case RRR_SUBU:
9115: mips32_op = OPC_SUBU;
9116: break;
9117: #if defined(TARGET_MIPS64)
9118: case RRR_DADDU:
9119: mips32_op = OPC_DADDU;
9120: check_mips_64(ctx);
9121: break;
9122: case RRR_DSUBU:
9123: mips32_op = OPC_DSUBU;
9124: check_mips_64(ctx);
9125: break;
9126: #endif
9127: default:
9128: generate_exception(ctx, EXCP_RI);
9129: goto done;
9130: }
9131:
9132: gen_arith(env, ctx, mips32_op, rz, rx, ry);
9133: done:
9134: ;
9135: }
9136: break;
9137: case M16_OPC_RR:
9138: switch (op1) {
9139: case RR_JR:
9140: {
9141: int nd = (ctx->opcode >> 7) & 0x1;
9142: int link = (ctx->opcode >> 6) & 0x1;
9143: int ra = (ctx->opcode >> 5) & 0x1;
9144:
9145: if (link) {
9146: op = nd ? OPC_JALRC : OPC_JALRS;
9147: } else {
9148: op = OPC_JR;
9149: }
9150:
9151: gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9152: if (!nd) {
9153: *is_branch = 1;
9154: }
9155: }
9156: break;
9157: case RR_SDBBP:
9158: /* XXX: not clear which exception should be raised
9159: * when in debug mode...
9160: */
9161: check_insn(env, ctx, ISA_MIPS32);
9162: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9163: generate_exception(ctx, EXCP_DBp);
9164: } else {
9165: generate_exception(ctx, EXCP_DBp);
9166: }
9167: break;
9168: case RR_SLT:
9169: gen_slt(env, OPC_SLT, 24, rx, ry);
9170: break;
9171: case RR_SLTU:
9172: gen_slt(env, OPC_SLTU, 24, rx, ry);
9173: break;
9174: case RR_BREAK:
9175: generate_exception(ctx, EXCP_BREAK);
9176: break;
9177: case RR_SLLV:
9178: gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9179: break;
9180: case RR_SRLV:
9181: gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9182: break;
9183: case RR_SRAV:
9184: gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9185: break;
9186: #if defined (TARGET_MIPS64)
9187: case RR_DSRL:
9188: check_mips_64(ctx);
9189: gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9190: break;
9191: #endif
9192: case RR_CMP:
9193: gen_logic(env, OPC_XOR, 24, rx, ry);
9194: break;
9195: case RR_NEG:
9196: gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9197: break;
9198: case RR_AND:
9199: gen_logic(env, OPC_AND, rx, rx, ry);
9200: break;
9201: case RR_OR:
9202: gen_logic(env, OPC_OR, rx, rx, ry);
9203: break;
9204: case RR_XOR:
9205: gen_logic(env, OPC_XOR, rx, rx, ry);
9206: break;
9207: case RR_NOT:
9208: gen_logic(env, OPC_NOR, rx, ry, 0);
9209: break;
9210: case RR_MFHI:
9211: gen_HILO(ctx, OPC_MFHI, rx);
9212: break;
9213: case RR_CNVT:
9214: switch (cnvt_op) {
9215: case RR_RY_CNVT_ZEB:
9216: tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9217: break;
9218: case RR_RY_CNVT_ZEH:
9219: tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9220: break;
9221: case RR_RY_CNVT_SEB:
9222: tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9223: break;
9224: case RR_RY_CNVT_SEH:
9225: tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9226: break;
9227: #if defined (TARGET_MIPS64)
9228: case RR_RY_CNVT_ZEW:
9229: check_mips_64(ctx);
9230: tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9231: break;
9232: case RR_RY_CNVT_SEW:
9233: check_mips_64(ctx);
9234: tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9235: break;
9236: #endif
9237: default:
9238: generate_exception(ctx, EXCP_RI);
9239: break;
9240: }
9241: break;
9242: case RR_MFLO:
9243: gen_HILO(ctx, OPC_MFLO, rx);
9244: break;
9245: #if defined (TARGET_MIPS64)
9246: case RR_DSRA:
9247: check_mips_64(ctx);
9248: gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9249: break;
9250: case RR_DSLLV:
9251: check_mips_64(ctx);
9252: gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9253: break;
9254: case RR_DSRLV:
9255: check_mips_64(ctx);
9256: gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9257: break;
9258: case RR_DSRAV:
9259: check_mips_64(ctx);
9260: gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9261: break;
9262: #endif
9263: case RR_MULT:
9264: gen_muldiv(ctx, OPC_MULT, rx, ry);
9265: break;
9266: case RR_MULTU:
9267: gen_muldiv(ctx, OPC_MULTU, rx, ry);
9268: break;
9269: case RR_DIV:
9270: gen_muldiv(ctx, OPC_DIV, rx, ry);
9271: break;
9272: case RR_DIVU:
9273: gen_muldiv(ctx, OPC_DIVU, rx, ry);
9274: break;
9275: #if defined (TARGET_MIPS64)
9276: case RR_DMULT:
9277: check_mips_64(ctx);
9278: gen_muldiv(ctx, OPC_DMULT, rx, ry);
9279: break;
9280: case RR_DMULTU:
9281: check_mips_64(ctx);
9282: gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9283: break;
9284: case RR_DDIV:
9285: check_mips_64(ctx);
9286: gen_muldiv(ctx, OPC_DDIV, rx, ry);
9287: break;
9288: case RR_DDIVU:
9289: check_mips_64(ctx);
9290: gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9291: break;
9292: #endif
9293: default:
9294: generate_exception(ctx, EXCP_RI);
9295: break;
9296: }
9297: break;
9298: case M16_OPC_EXTEND:
9299: decode_extended_mips16_opc(env, ctx, is_branch);
9300: n_bytes = 4;
9301: break;
9302: #if defined(TARGET_MIPS64)
9303: case M16_OPC_I64:
9304: funct = (ctx->opcode >> 8) & 0x7;
9305: decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9306: break;
9307: #endif
9308: default:
9309: generate_exception(ctx, EXCP_RI);
9310: break;
9311: }
9312:
9313: return n_bytes;
9314: }
9315:
9316: /* microMIPS extension to MIPS32 */
9317:
9318: /* microMIPS32 major opcodes */
9319:
9320: enum {
9321: POOL32A = 0x00,
9322: POOL16A = 0x01,
9323: LBU16 = 0x02,
9324: MOVE16 = 0x03,
9325: ADDI32 = 0x04,
9326: LBU32 = 0x05,
9327: SB32 = 0x06,
9328: LB32 = 0x07,
9329:
9330: POOL32B = 0x08,
9331: POOL16B = 0x09,
9332: LHU16 = 0x0a,
9333: ANDI16 = 0x0b,
9334: ADDIU32 = 0x0c,
9335: LHU32 = 0x0d,
9336: SH32 = 0x0e,
9337: LH32 = 0x0f,
9338:
9339: POOL32I = 0x10,
9340: POOL16C = 0x11,
9341: LWSP16 = 0x12,
9342: POOL16D = 0x13,
9343: ORI32 = 0x14,
9344: POOL32F = 0x15,
9345: POOL32S = 0x16,
9346: DADDIU32 = 0x17,
9347:
9348: POOL32C = 0x18,
9349: LWGP16 = 0x19,
9350: LW16 = 0x1a,
9351: POOL16E = 0x1b,
9352: XORI32 = 0x1c,
9353: JALS32 = 0x1d,
9354: ADDIUPC = 0x1e,
9355: POOL48A = 0x1f,
9356:
9357: /* 0x20 is reserved */
9358: RES_20 = 0x20,
9359: POOL16F = 0x21,
9360: SB16 = 0x22,
9361: BEQZ16 = 0x23,
9362: SLTI32 = 0x24,
9363: BEQ32 = 0x25,
9364: SWC132 = 0x26,
9365: LWC132 = 0x27,
9366:
9367: /* 0x28 and 0x29 are reserved */
9368: RES_28 = 0x28,
9369: RES_29 = 0x29,
9370: SH16 = 0x2a,
9371: BNEZ16 = 0x2b,
9372: SLTIU32 = 0x2c,
9373: BNE32 = 0x2d,
9374: SDC132 = 0x2e,
9375: LDC132 = 0x2f,
9376:
9377: /* 0x30 and 0x31 are reserved */
9378: RES_30 = 0x30,
9379: RES_31 = 0x31,
9380: SWSP16 = 0x32,
9381: B16 = 0x33,
9382: ANDI32 = 0x34,
9383: J32 = 0x35,
9384: SD32 = 0x36,
9385: LD32 = 0x37,
9386:
9387: /* 0x38 and 0x39 are reserved */
9388: RES_38 = 0x38,
9389: RES_39 = 0x39,
9390: SW16 = 0x3a,
9391: LI16 = 0x3b,
9392: JALX32 = 0x3c,
9393: JAL32 = 0x3d,
9394: SW32 = 0x3e,
9395: LW32 = 0x3f
9396: };
9397:
9398: /* POOL32A encoding of minor opcode field */
9399:
9400: enum {
9401: /* These opcodes are distinguished only by bits 9..6; those bits are
9402: * what are recorded below. */
9403: SLL32 = 0x0,
9404: SRL32 = 0x1,
9405: SRA = 0x2,
9406: ROTR = 0x3,
9407:
9408: SLLV = 0x0,
9409: SRLV = 0x1,
9410: SRAV = 0x2,
9411: ROTRV = 0x3,
9412: ADD = 0x4,
9413: ADDU32 = 0x5,
9414: SUB = 0x6,
9415: SUBU32 = 0x7,
9416: MUL = 0x8,
9417: AND = 0x9,
9418: OR32 = 0xa,
9419: NOR = 0xb,
9420: XOR32 = 0xc,
9421: SLT = 0xd,
9422: SLTU = 0xe,
9423:
9424: MOVN = 0x0,
9425: MOVZ = 0x1,
9426: LWXS = 0x4,
9427:
9428: /* The following can be distinguished by their lower 6 bits. */
9429: INS = 0x0c,
9430: EXT = 0x2c,
9431: POOL32AXF = 0x3c
9432: };
9433:
9434: /* POOL32AXF encoding of minor opcode field extension */
9435:
9436: enum {
9437: /* bits 11..6 */
9438: TEQ = 0x00,
9439: TGE = 0x08,
9440: TGEU = 0x10,
9441: TLT = 0x20,
9442: TLTU = 0x28,
9443: TNE = 0x30,
9444:
9445: MFC0 = 0x03,
9446: MTC0 = 0x0b,
9447:
9448: /* bits 13..12 for 0x01 */
9449: MFHI_ACC = 0x0,
9450: MFLO_ACC = 0x1,
9451: MTHI_ACC = 0x2,
9452: MTLO_ACC = 0x3,
9453:
9454: /* bits 13..12 for 0x2a */
9455: MADD_ACC = 0x0,
9456: MADDU_ACC = 0x1,
9457: MSUB_ACC = 0x2,
9458: MSUBU_ACC = 0x3,
9459:
9460: /* bits 13..12 for 0x32 */
9461: MULT_ACC = 0x0,
9462: MULTU_ACC = 0x0,
9463:
9464: /* bits 15..12 for 0x2c */
9465: SEB = 0x2,
9466: SEH = 0x3,
9467: CLO = 0x4,
9468: CLZ = 0x5,
9469: RDHWR = 0x6,
9470: WSBH = 0x7,
9471: MULT = 0x8,
9472: MULTU = 0x9,
9473: DIV = 0xa,
9474: DIVU = 0xb,
9475: MADD = 0xc,
9476: MADDU = 0xd,
9477: MSUB = 0xe,
9478: MSUBU = 0xf,
9479:
9480: /* bits 15..12 for 0x34 */
9481: MFC2 = 0x4,
9482: MTC2 = 0x5,
9483: MFHC2 = 0x8,
9484: MTHC2 = 0x9,
9485: CFC2 = 0xc,
9486: CTC2 = 0xd,
9487:
9488: /* bits 15..12 for 0x3c */
9489: JALR = 0x0,
9490: JR = 0x0, /* alias */
9491: JALR_HB = 0x1,
9492: JALRS = 0x4,
9493: JALRS_HB = 0x5,
9494:
9495: /* bits 15..12 for 0x05 */
9496: RDPGPR = 0xe,
9497: WRPGPR = 0xf,
9498:
9499: /* bits 15..12 for 0x0d */
9500: TLBP = 0x0,
9501: TLBR = 0x1,
9502: TLBWI = 0x2,
9503: TLBWR = 0x3,
9504: WAIT = 0x9,
9505: IRET = 0xd,
9506: DERET = 0xe,
9507: ERET = 0xf,
9508:
9509: /* bits 15..12 for 0x15 */
9510: DMT = 0x0,
9511: DVPE = 0x1,
9512: EMT = 0x2,
9513: EVPE = 0x3,
9514:
9515: /* bits 15..12 for 0x1d */
9516: DI = 0x4,
9517: EI = 0x5,
9518:
9519: /* bits 15..12 for 0x2d */
9520: SYNC = 0x6,
9521: SYSCALL = 0x8,
9522: SDBBP = 0xd,
9523:
9524: /* bits 15..12 for 0x35 */
9525: MFHI32 = 0x0,
9526: MFLO32 = 0x1,
9527: MTHI32 = 0x2,
9528: MTLO32 = 0x3,
9529: };
9530:
9531: /* POOL32B encoding of minor opcode field (bits 15..12) */
9532:
9533: enum {
9534: LWC2 = 0x0,
9535: LWP = 0x1,
9536: LDP = 0x4,
9537: LWM32 = 0x5,
9538: CACHE = 0x6,
9539: LDM = 0x7,
9540: SWC2 = 0x8,
9541: SWP = 0x9,
9542: SDP = 0xc,
9543: SWM32 = 0xd,
9544: SDM = 0xf
9545: };
9546:
9547: /* POOL32C encoding of minor opcode field (bits 15..12) */
9548:
9549: enum {
9550: LWL = 0x0,
9551: SWL = 0x8,
9552: LWR = 0x1,
9553: SWR = 0x9,
9554: PREF = 0x2,
9555: /* 0xa is reserved */
9556: LL = 0x3,
9557: SC = 0xb,
9558: LDL = 0x4,
9559: SDL = 0xc,
9560: LDR = 0x5,
9561: SDR = 0xd,
9562: /* 0x6 is reserved */
9563: LWU = 0xe,
9564: LLD = 0x7,
9565: SCD = 0xf
9566: };
9567:
9568: /* POOL32F encoding of minor opcode field (bits 5..0) */
9569:
9570: enum {
9571: /* These are the bit 7..6 values */
9572: ADD_FMT = 0x0,
9573: MOVN_FMT = 0x0,
9574:
9575: SUB_FMT = 0x1,
9576: MOVZ_FMT = 0x1,
9577:
9578: MUL_FMT = 0x2,
9579:
9580: DIV_FMT = 0x3,
9581:
9582: /* These are the bit 8..6 values */
9583: RSQRT2_FMT = 0x0,
9584: MOVF_FMT = 0x0,
9585:
9586: LWXC1 = 0x1,
9587: MOVT_FMT = 0x1,
9588:
9589: PLL_PS = 0x2,
9590: SWXC1 = 0x2,
9591:
9592: PLU_PS = 0x3,
9593: LDXC1 = 0x3,
9594:
9595: PUL_PS = 0x4,
9596: SDXC1 = 0x4,
9597: RECIP2_FMT = 0x4,
9598:
9599: PUU_PS = 0x5,
9600: LUXC1 = 0x5,
9601:
9602: CVT_PS_S = 0x6,
9603: SUXC1 = 0x6,
9604: ADDR_PS = 0x6,
9605: PREFX = 0x6,
9606:
9607: MULR_PS = 0x7,
9608:
9609: MADD_S = 0x01,
9610: MADD_D = 0x09,
9611: MADD_PS = 0x11,
9612: ALNV_PS = 0x19,
9613: MSUB_S = 0x21,
9614: MSUB_D = 0x29,
9615: MSUB_PS = 0x31,
9616:
9617: NMADD_S = 0x02,
9618: NMADD_D = 0x0a,
9619: NMADD_PS = 0x12,
9620: NMSUB_S = 0x22,
9621: NMSUB_D = 0x2a,
9622: NMSUB_PS = 0x32,
9623:
9624: POOL32FXF = 0x3b,
9625:
9626: CABS_COND_FMT = 0x1c, /* MIPS3D */
9627: C_COND_FMT = 0x3c
9628: };
9629:
9630: /* POOL32Fxf encoding of minor opcode extension field */
9631:
9632: enum {
9633: CVT_L = 0x04,
9634: RSQRT_FMT = 0x08,
9635: FLOOR_L = 0x0c,
9636: CVT_PW_PS = 0x1c,
9637: CVT_W = 0x24,
9638: SQRT_FMT = 0x28,
9639: FLOOR_W = 0x2c,
9640: CVT_PS_PW = 0x3c,
9641: CFC1 = 0x40,
9642: RECIP_FMT = 0x48,
9643: CEIL_L = 0x4c,
9644: CTC1 = 0x60,
9645: CEIL_W = 0x6c,
9646: MFC1 = 0x80,
9647: CVT_S_PL = 0x84,
9648: TRUNC_L = 0x8c,
9649: MTC1 = 0xa0,
9650: CVT_S_PU = 0xa4,
9651: TRUNC_W = 0xac,
9652: MFHC1 = 0xc0,
9653: ROUND_L = 0xcc,
9654: MTHC1 = 0xe0,
9655: ROUND_W = 0xec,
9656:
9657: MOV_FMT = 0x01,
9658: MOVF = 0x05,
9659: ABS_FMT = 0x0d,
9660: RSQRT1_FMT = 0x1d,
9661: MOVT = 0x25,
9662: NEG_FMT = 0x2d,
9663: CVT_D = 0x4d,
9664: RECIP1_FMT = 0x5d,
9665: CVT_S = 0x6d
9666: };
9667:
9668: /* POOL32I encoding of minor opcode field (bits 25..21) */
9669:
9670: enum {
9671: BLTZ = 0x00,
9672: BLTZAL = 0x01,
9673: BGEZ = 0x02,
9674: BGEZAL = 0x03,
9675: BLEZ = 0x04,
9676: BNEZC = 0x05,
9677: BGTZ = 0x06,
9678: BEQZC = 0x07,
9679: TLTI = 0x08,
9680: TGEI = 0x09,
9681: TLTIU = 0x0a,
9682: TGEIU = 0x0b,
9683: TNEI = 0x0c,
9684: LUI = 0x0d,
9685: TEQI = 0x0e,
9686: SYNCI = 0x10,
9687: BLTZALS = 0x11,
9688: BGEZALS = 0x13,
9689: BC2F = 0x14,
9690: BC2T = 0x15,
9691: BPOSGE64 = 0x1a,
9692: BPOSGE32 = 0x1b,
9693: /* These overlap and are distinguished by bit16 of the instruction */
9694: BC1F = 0x1c,
9695: BC1T = 0x1d,
9696: BC1ANY2F = 0x1c,
9697: BC1ANY2T = 0x1d,
9698: BC1ANY4F = 0x1e,
9699: BC1ANY4T = 0x1f
9700: };
9701:
9702: /* POOL16A encoding of minor opcode field */
9703:
9704: enum {
9705: ADDU16 = 0x0,
9706: SUBU16 = 0x1
9707: };
9708:
9709: /* POOL16B encoding of minor opcode field */
9710:
9711: enum {
9712: SLL16 = 0x0,
9713: SRL16 = 0x1
9714: };
9715:
9716: /* POOL16C encoding of minor opcode field */
9717:
9718: enum {
9719: NOT16 = 0x00,
9720: XOR16 = 0x04,
9721: AND16 = 0x08,
9722: OR16 = 0x0c,
9723: LWM16 = 0x10,
9724: SWM16 = 0x14,
9725: JR16 = 0x18,
9726: JRC16 = 0x1a,
9727: JALR16 = 0x1c,
9728: JALR16S = 0x1e,
9729: MFHI16 = 0x20,
9730: MFLO16 = 0x24,
9731: BREAK16 = 0x28,
9732: SDBBP16 = 0x2c,
9733: JRADDIUSP = 0x30
9734: };
9735:
9736: /* POOL16D encoding of minor opcode field */
9737:
9738: enum {
9739: ADDIUS5 = 0x0,
9740: ADDIUSP = 0x1
9741: };
9742:
9743: /* POOL16E encoding of minor opcode field */
9744:
9745: enum {
9746: ADDIUR2 = 0x0,
9747: ADDIUR1SP = 0x1
9748: };
9749:
9750: static int mmreg (int r)
9751: {
9752: static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9753:
9754: return map[r];
9755: }
9756:
9757: /* Used for 16-bit store instructions. */
9758: static int mmreg2 (int r)
9759: {
9760: static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
9761:
9762: return map[r];
9763: }
9764:
9765: #define uMIPS_RD(op) ((op >> 7) & 0x7)
9766: #define uMIPS_RS(op) ((op >> 4) & 0x7)
9767: #define uMIPS_RS2(op) uMIPS_RS(op)
9768: #define uMIPS_RS1(op) ((op >> 1) & 0x7)
9769: #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
9770: #define uMIPS_RS5(op) (op & 0x1f)
9771:
9772: /* Signed immediate */
9773: #define SIMM(op, start, width) \
9774: ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
9775: << (32-width)) \
9776: >> (32-width))
9777: /* Zero-extended immediate */
9778: #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
9779:
1.1.1.16! root 9780: static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
1.1.1.12 root 9781: {
9782: int rd = mmreg(uMIPS_RD(ctx->opcode));
9783:
9784: gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
9785: }
9786:
1.1.1.16! root 9787: static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
1.1.1.12 root 9788: {
9789: static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
9790: int rd = mmreg(uMIPS_RD(ctx->opcode));
9791: int rs = mmreg(uMIPS_RS(ctx->opcode));
9792:
9793: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
9794: }
9795:
1.1.1.16! root 9796: static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
1.1.1.12 root 9797: {
9798: int encoded = ZIMM(ctx->opcode, 1, 9);
9799: int decoded;
9800:
9801: if (encoded <= 1) {
9802: decoded = 256 + encoded;
9803: } else if (encoded <= 255) {
9804: decoded = encoded;
9805: } else if (encoded <= 509) {
9806: decoded = encoded - 512;
9807: } else {
9808: decoded = encoded - 768;
9809: }
9810:
9811: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
9812: }
9813:
1.1.1.16! root 9814: static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
1.1.1.12 root 9815: {
9816: int imm = SIMM(ctx->opcode, 1, 4);
9817: int rd = (ctx->opcode >> 5) & 0x1f;
9818:
9819: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
9820: }
9821:
1.1.1.16! root 9822: static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
1.1.1.12 root 9823: {
9824: static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
9825: 31, 32, 63, 64, 255, 32768, 65535 };
9826: int rd = mmreg(uMIPS_RD(ctx->opcode));
9827: int rs = mmreg(uMIPS_RS(ctx->opcode));
9828: int encoded = ZIMM(ctx->opcode, 0, 4);
9829:
9830: gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
9831: }
9832:
9833: static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
9834: int base, int16_t offset)
9835: {
9836: TCGv t0, t1;
9837: TCGv_i32 t2;
9838:
9839: if (ctx->hflags & MIPS_HFLAG_BMASK) {
9840: generate_exception(ctx, EXCP_RI);
9841: return;
9842: }
9843:
9844: t0 = tcg_temp_new();
9845:
9846: gen_base_offset_addr(ctx, t0, base, offset);
9847:
9848: t1 = tcg_const_tl(reglist);
9849: t2 = tcg_const_i32(ctx->mem_idx);
9850:
9851: save_cpu_state(ctx, 1);
9852: switch (opc) {
9853: case LWM32:
9854: gen_helper_lwm(t0, t1, t2);
9855: break;
9856: case SWM32:
9857: gen_helper_swm(t0, t1, t2);
9858: break;
9859: #ifdef TARGET_MIPS64
9860: case LDM:
9861: gen_helper_ldm(t0, t1, t2);
9862: break;
9863: case SDM:
9864: gen_helper_sdm(t0, t1, t2);
9865: break;
9866: #endif
9867: }
9868: MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
9869: tcg_temp_free(t0);
9870: tcg_temp_free(t1);
9871: tcg_temp_free_i32(t2);
9872: }
9873:
9874:
1.1.1.16! root 9875: static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
1.1.1.12 root 9876: {
9877: int rd = mmreg((ctx->opcode >> 3) & 0x7);
9878: int rs = mmreg(ctx->opcode & 0x7);
9879: int opc;
9880:
9881: switch (((ctx->opcode) >> 4) & 0x3f) {
9882: case NOT16 + 0:
9883: case NOT16 + 1:
9884: case NOT16 + 2:
9885: case NOT16 + 3:
9886: gen_logic(env, OPC_NOR, rd, rs, 0);
9887: break;
9888: case XOR16 + 0:
9889: case XOR16 + 1:
9890: case XOR16 + 2:
9891: case XOR16 + 3:
9892: gen_logic(env, OPC_XOR, rd, rd, rs);
9893: break;
9894: case AND16 + 0:
9895: case AND16 + 1:
9896: case AND16 + 2:
9897: case AND16 + 3:
9898: gen_logic(env, OPC_AND, rd, rd, rs);
9899: break;
9900: case OR16 + 0:
9901: case OR16 + 1:
9902: case OR16 + 2:
9903: case OR16 + 3:
9904: gen_logic(env, OPC_OR, rd, rd, rs);
9905: break;
9906: case LWM16 + 0:
9907: case LWM16 + 1:
9908: case LWM16 + 2:
9909: case LWM16 + 3:
9910: {
9911: static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9912: int offset = ZIMM(ctx->opcode, 0, 4);
9913:
9914: gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
9915: 29, offset << 2);
9916: }
9917: break;
9918: case SWM16 + 0:
9919: case SWM16 + 1:
9920: case SWM16 + 2:
9921: case SWM16 + 3:
9922: {
9923: static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9924: int offset = ZIMM(ctx->opcode, 0, 4);
9925:
9926: gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
9927: 29, offset << 2);
9928: }
9929: break;
9930: case JR16 + 0:
9931: case JR16 + 1:
9932: {
9933: int reg = ctx->opcode & 0x1f;
9934:
9935: gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9936: }
9937: *is_branch = 1;
9938: break;
9939: case JRC16 + 0:
9940: case JRC16 + 1:
9941: {
9942: int reg = ctx->opcode & 0x1f;
9943:
9944: gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9945: /* Let normal delay slot handling in our caller take us
9946: to the branch target. */
9947: }
9948: break;
9949: case JALR16 + 0:
9950: case JALR16 + 1:
9951: opc = OPC_JALR;
9952: goto do_jalr;
9953: case JALR16S + 0:
9954: case JALR16S + 1:
9955: opc = OPC_JALRS;
9956: do_jalr:
9957: {
9958: int reg = ctx->opcode & 0x1f;
9959:
9960: gen_compute_branch(ctx, opc, 2, reg, 31, 0);
9961: }
9962: *is_branch = 1;
9963: break;
9964: case MFHI16 + 0:
9965: case MFHI16 + 1:
9966: gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
9967: break;
9968: case MFLO16 + 0:
9969: case MFLO16 + 1:
9970: gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
9971: break;
9972: case BREAK16:
9973: generate_exception(ctx, EXCP_BREAK);
9974: break;
9975: case SDBBP16:
9976: /* XXX: not clear which exception should be raised
9977: * when in debug mode...
9978: */
9979: check_insn(env, ctx, ISA_MIPS32);
9980: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9981: generate_exception(ctx, EXCP_DBp);
9982: } else {
9983: generate_exception(ctx, EXCP_DBp);
9984: }
9985: break;
9986: case JRADDIUSP + 0:
9987: case JRADDIUSP + 1:
9988: {
9989: int imm = ZIMM(ctx->opcode, 0, 5);
9990:
9991: gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
9992: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
9993: /* Let normal delay slot handling in our caller take us
9994: to the branch target. */
9995: }
9996: break;
9997: default:
9998: generate_exception(ctx, EXCP_RI);
9999: break;
10000: }
10001: }
10002:
10003: static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10004: {
10005: TCGv t0 = tcg_temp_new();
10006: TCGv t1 = tcg_temp_new();
10007:
10008: gen_load_gpr(t0, base);
10009:
10010: if (index != 0) {
10011: gen_load_gpr(t1, index);
10012: tcg_gen_shli_tl(t1, t1, 2);
10013: gen_op_addr_add(ctx, t0, t1, t0);
10014: }
10015:
10016: save_cpu_state(ctx, 0);
10017: op_ld_lw(t1, t0, ctx);
10018: gen_store_gpr(t1, rd);
10019:
10020: tcg_temp_free(t0);
10021: tcg_temp_free(t1);
10022: }
10023:
10024: static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
10025: int base, int16_t offset)
10026: {
10027: const char *opn = "ldst_pair";
10028: TCGv t0, t1;
10029:
10030: if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
10031: generate_exception(ctx, EXCP_RI);
10032: return;
10033: }
10034:
10035: t0 = tcg_temp_new();
10036: t1 = tcg_temp_new();
10037:
10038: gen_base_offset_addr(ctx, t0, base, offset);
10039:
10040: switch (opc) {
10041: case LWP:
10042: save_cpu_state(ctx, 0);
10043: op_ld_lw(t1, t0, ctx);
10044: gen_store_gpr(t1, rd);
10045: tcg_gen_movi_tl(t1, 4);
10046: gen_op_addr_add(ctx, t0, t0, t1);
10047: op_ld_lw(t1, t0, ctx);
10048: gen_store_gpr(t1, rd+1);
10049: opn = "lwp";
10050: break;
10051: case SWP:
1.1.1.13 root 10052: save_cpu_state(ctx, 0);
1.1.1.12 root 10053: gen_load_gpr(t1, rd);
10054: op_st_sw(t1, t0, ctx);
10055: tcg_gen_movi_tl(t1, 4);
10056: gen_op_addr_add(ctx, t0, t0, t1);
10057: gen_load_gpr(t1, rd+1);
10058: op_st_sw(t1, t0, ctx);
10059: opn = "swp";
10060: break;
10061: #ifdef TARGET_MIPS64
10062: case LDP:
10063: save_cpu_state(ctx, 0);
10064: op_ld_ld(t1, t0, ctx);
10065: gen_store_gpr(t1, rd);
10066: tcg_gen_movi_tl(t1, 8);
10067: gen_op_addr_add(ctx, t0, t0, t1);
10068: op_ld_ld(t1, t0, ctx);
10069: gen_store_gpr(t1, rd+1);
10070: opn = "ldp";
10071: break;
10072: case SDP:
1.1.1.13 root 10073: save_cpu_state(ctx, 0);
1.1.1.12 root 10074: gen_load_gpr(t1, rd);
10075: op_st_sd(t1, t0, ctx);
10076: tcg_gen_movi_tl(t1, 8);
10077: gen_op_addr_add(ctx, t0, t0, t1);
10078: gen_load_gpr(t1, rd+1);
10079: op_st_sd(t1, t0, ctx);
10080: opn = "sdp";
10081: break;
10082: #endif
10083: }
1.1.1.13 root 10084: (void)opn; /* avoid a compiler warning */
1.1.1.12 root 10085: MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10086: tcg_temp_free(t0);
10087: tcg_temp_free(t1);
10088: }
10089:
1.1.1.16! root 10090: static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
1.1.1.12 root 10091: int *is_branch)
10092: {
10093: int extension = (ctx->opcode >> 6) & 0x3f;
10094: int minor = (ctx->opcode >> 12) & 0xf;
10095: uint32_t mips32_op;
10096:
10097: switch (extension) {
10098: case TEQ:
10099: mips32_op = OPC_TEQ;
10100: goto do_trap;
10101: case TGE:
10102: mips32_op = OPC_TGE;
10103: goto do_trap;
10104: case TGEU:
10105: mips32_op = OPC_TGEU;
10106: goto do_trap;
10107: case TLT:
10108: mips32_op = OPC_TLT;
10109: goto do_trap;
10110: case TLTU:
10111: mips32_op = OPC_TLTU;
10112: goto do_trap;
10113: case TNE:
10114: mips32_op = OPC_TNE;
10115: do_trap:
10116: gen_trap(ctx, mips32_op, rs, rt, -1);
10117: break;
10118: #ifndef CONFIG_USER_ONLY
10119: case MFC0:
10120: case MFC0 + 32:
10121: if (rt == 0) {
10122: /* Treat as NOP. */
10123: break;
10124: }
10125: gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10126: break;
10127: case MTC0:
10128: case MTC0 + 32:
10129: {
10130: TCGv t0 = tcg_temp_new();
10131:
10132: gen_load_gpr(t0, rt);
10133: gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10134: tcg_temp_free(t0);
10135: }
10136: break;
10137: #endif
10138: case 0x2c:
10139: switch (minor) {
10140: case SEB:
10141: gen_bshfl(ctx, OPC_SEB, rs, rt);
10142: break;
10143: case SEH:
10144: gen_bshfl(ctx, OPC_SEH, rs, rt);
10145: break;
10146: case CLO:
10147: mips32_op = OPC_CLO;
10148: goto do_cl;
10149: case CLZ:
10150: mips32_op = OPC_CLZ;
10151: do_cl:
10152: check_insn(env, ctx, ISA_MIPS32);
10153: gen_cl(ctx, mips32_op, rt, rs);
10154: break;
10155: case RDHWR:
10156: gen_rdhwr(env, ctx, rt, rs);
10157: break;
10158: case WSBH:
10159: gen_bshfl(ctx, OPC_WSBH, rs, rt);
10160: break;
10161: case MULT:
10162: mips32_op = OPC_MULT;
10163: goto do_muldiv;
10164: case MULTU:
10165: mips32_op = OPC_MULTU;
10166: goto do_muldiv;
10167: case DIV:
10168: mips32_op = OPC_DIV;
10169: goto do_muldiv;
10170: case DIVU:
10171: mips32_op = OPC_DIVU;
10172: goto do_muldiv;
10173: case MADD:
10174: mips32_op = OPC_MADD;
10175: goto do_muldiv;
10176: case MADDU:
10177: mips32_op = OPC_MADDU;
10178: goto do_muldiv;
10179: case MSUB:
10180: mips32_op = OPC_MSUB;
10181: goto do_muldiv;
10182: case MSUBU:
10183: mips32_op = OPC_MSUBU;
10184: do_muldiv:
10185: check_insn(env, ctx, ISA_MIPS32);
10186: gen_muldiv(ctx, mips32_op, rs, rt);
10187: break;
10188: default:
10189: goto pool32axf_invalid;
10190: }
10191: break;
10192: case 0x34:
10193: switch (minor) {
10194: case MFC2:
10195: case MTC2:
10196: case MFHC2:
10197: case MTHC2:
10198: case CFC2:
10199: case CTC2:
10200: generate_exception_err(ctx, EXCP_CpU, 2);
10201: break;
10202: default:
10203: goto pool32axf_invalid;
10204: }
10205: break;
10206: case 0x3c:
10207: switch (minor) {
10208: case JALR:
10209: case JALR_HB:
10210: gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10211: *is_branch = 1;
10212: break;
10213: case JALRS:
10214: case JALRS_HB:
10215: gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10216: *is_branch = 1;
10217: break;
10218: default:
10219: goto pool32axf_invalid;
10220: }
10221: break;
10222: case 0x05:
10223: switch (minor) {
10224: case RDPGPR:
10225: check_insn(env, ctx, ISA_MIPS32R2);
10226: gen_load_srsgpr(rt, rs);
10227: break;
10228: case WRPGPR:
10229: check_insn(env, ctx, ISA_MIPS32R2);
10230: gen_store_srsgpr(rt, rs);
10231: break;
10232: default:
10233: goto pool32axf_invalid;
10234: }
10235: break;
10236: #ifndef CONFIG_USER_ONLY
10237: case 0x0d:
10238: switch (minor) {
10239: case TLBP:
10240: mips32_op = OPC_TLBP;
10241: goto do_cp0;
10242: case TLBR:
10243: mips32_op = OPC_TLBR;
10244: goto do_cp0;
10245: case TLBWI:
10246: mips32_op = OPC_TLBWI;
10247: goto do_cp0;
10248: case TLBWR:
10249: mips32_op = OPC_TLBWR;
10250: goto do_cp0;
10251: case WAIT:
10252: mips32_op = OPC_WAIT;
10253: goto do_cp0;
10254: case DERET:
10255: mips32_op = OPC_DERET;
10256: goto do_cp0;
10257: case ERET:
10258: mips32_op = OPC_ERET;
10259: do_cp0:
10260: gen_cp0(env, ctx, mips32_op, rt, rs);
10261: break;
10262: default:
10263: goto pool32axf_invalid;
10264: }
10265: break;
10266: case 0x1d:
10267: switch (minor) {
10268: case DI:
10269: {
10270: TCGv t0 = tcg_temp_new();
10271:
10272: save_cpu_state(ctx, 1);
10273: gen_helper_di(t0);
10274: gen_store_gpr(t0, rs);
10275: /* Stop translation as we may have switched the execution mode */
10276: ctx->bstate = BS_STOP;
10277: tcg_temp_free(t0);
10278: }
10279: break;
10280: case EI:
10281: {
10282: TCGv t0 = tcg_temp_new();
10283:
10284: save_cpu_state(ctx, 1);
10285: gen_helper_ei(t0);
10286: gen_store_gpr(t0, rs);
10287: /* Stop translation as we may have switched the execution mode */
10288: ctx->bstate = BS_STOP;
10289: tcg_temp_free(t0);
10290: }
10291: break;
10292: default:
10293: goto pool32axf_invalid;
10294: }
10295: break;
10296: #endif
10297: case 0x2d:
10298: switch (minor) {
10299: case SYNC:
10300: /* NOP */
10301: break;
10302: case SYSCALL:
10303: generate_exception(ctx, EXCP_SYSCALL);
10304: ctx->bstate = BS_STOP;
10305: break;
10306: case SDBBP:
10307: check_insn(env, ctx, ISA_MIPS32);
10308: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10309: generate_exception(ctx, EXCP_DBp);
10310: } else {
10311: generate_exception(ctx, EXCP_DBp);
10312: }
10313: break;
10314: default:
10315: goto pool32axf_invalid;
10316: }
10317: break;
10318: case 0x35:
10319: switch (minor) {
10320: case MFHI32:
10321: gen_HILO(ctx, OPC_MFHI, rs);
10322: break;
10323: case MFLO32:
10324: gen_HILO(ctx, OPC_MFLO, rs);
10325: break;
10326: case MTHI32:
10327: gen_HILO(ctx, OPC_MTHI, rs);
10328: break;
10329: case MTLO32:
10330: gen_HILO(ctx, OPC_MTLO, rs);
10331: break;
10332: default:
10333: goto pool32axf_invalid;
10334: }
10335: break;
10336: default:
10337: pool32axf_invalid:
10338: MIPS_INVAL("pool32axf");
10339: generate_exception(ctx, EXCP_RI);
10340: break;
10341: }
10342: }
10343:
10344: /* Values for microMIPS fmt field. Variable-width, depending on which
10345: formats the instruction supports. */
10346:
10347: enum {
10348: FMT_SD_S = 0,
10349: FMT_SD_D = 1,
10350:
10351: FMT_SDPS_S = 0,
10352: FMT_SDPS_D = 1,
10353: FMT_SDPS_PS = 2,
10354:
10355: FMT_SWL_S = 0,
10356: FMT_SWL_W = 1,
10357: FMT_SWL_L = 2,
10358:
10359: FMT_DWL_D = 0,
10360: FMT_DWL_W = 1,
10361: FMT_DWL_L = 2
10362: };
10363:
1.1.1.16! root 10364: static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
1.1.1.12 root 10365: {
10366: int extension = (ctx->opcode >> 6) & 0x3ff;
10367: uint32_t mips32_op;
10368:
10369: #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10370: #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10371: #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10372:
10373: switch (extension) {
10374: case FLOAT_1BIT_FMT(CFC1, 0):
10375: mips32_op = OPC_CFC1;
10376: goto do_cp1;
10377: case FLOAT_1BIT_FMT(CTC1, 0):
10378: mips32_op = OPC_CTC1;
10379: goto do_cp1;
10380: case FLOAT_1BIT_FMT(MFC1, 0):
10381: mips32_op = OPC_MFC1;
10382: goto do_cp1;
10383: case FLOAT_1BIT_FMT(MTC1, 0):
10384: mips32_op = OPC_MTC1;
10385: goto do_cp1;
10386: case FLOAT_1BIT_FMT(MFHC1, 0):
10387: mips32_op = OPC_MFHC1;
10388: goto do_cp1;
10389: case FLOAT_1BIT_FMT(MTHC1, 0):
10390: mips32_op = OPC_MTHC1;
10391: do_cp1:
10392: gen_cp1(ctx, mips32_op, rt, rs);
10393: break;
10394:
10395: /* Reciprocal square root */
10396: case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10397: mips32_op = OPC_RSQRT_S;
10398: goto do_unaryfp;
10399: case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10400: mips32_op = OPC_RSQRT_D;
10401: goto do_unaryfp;
10402:
10403: /* Square root */
10404: case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10405: mips32_op = OPC_SQRT_S;
10406: goto do_unaryfp;
10407: case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10408: mips32_op = OPC_SQRT_D;
10409: goto do_unaryfp;
10410:
10411: /* Reciprocal */
10412: case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10413: mips32_op = OPC_RECIP_S;
10414: goto do_unaryfp;
10415: case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10416: mips32_op = OPC_RECIP_D;
10417: goto do_unaryfp;
10418:
10419: /* Floor */
10420: case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10421: mips32_op = OPC_FLOOR_L_S;
10422: goto do_unaryfp;
10423: case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10424: mips32_op = OPC_FLOOR_L_D;
10425: goto do_unaryfp;
10426: case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10427: mips32_op = OPC_FLOOR_W_S;
10428: goto do_unaryfp;
10429: case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10430: mips32_op = OPC_FLOOR_W_D;
10431: goto do_unaryfp;
10432:
10433: /* Ceiling */
10434: case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10435: mips32_op = OPC_CEIL_L_S;
10436: goto do_unaryfp;
10437: case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10438: mips32_op = OPC_CEIL_L_D;
10439: goto do_unaryfp;
10440: case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10441: mips32_op = OPC_CEIL_W_S;
10442: goto do_unaryfp;
10443: case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10444: mips32_op = OPC_CEIL_W_D;
10445: goto do_unaryfp;
10446:
10447: /* Truncation */
10448: case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10449: mips32_op = OPC_TRUNC_L_S;
10450: goto do_unaryfp;
10451: case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10452: mips32_op = OPC_TRUNC_L_D;
10453: goto do_unaryfp;
10454: case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10455: mips32_op = OPC_TRUNC_W_S;
10456: goto do_unaryfp;
10457: case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10458: mips32_op = OPC_TRUNC_W_D;
10459: goto do_unaryfp;
10460:
10461: /* Round */
10462: case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10463: mips32_op = OPC_ROUND_L_S;
10464: goto do_unaryfp;
10465: case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10466: mips32_op = OPC_ROUND_L_D;
10467: goto do_unaryfp;
10468: case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10469: mips32_op = OPC_ROUND_W_S;
10470: goto do_unaryfp;
10471: case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10472: mips32_op = OPC_ROUND_W_D;
10473: goto do_unaryfp;
10474:
10475: /* Integer to floating-point conversion */
10476: case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10477: mips32_op = OPC_CVT_L_S;
10478: goto do_unaryfp;
10479: case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10480: mips32_op = OPC_CVT_L_D;
10481: goto do_unaryfp;
10482: case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10483: mips32_op = OPC_CVT_W_S;
10484: goto do_unaryfp;
10485: case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10486: mips32_op = OPC_CVT_W_D;
10487: goto do_unaryfp;
10488:
10489: /* Paired-foo conversions */
10490: case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10491: mips32_op = OPC_CVT_S_PL;
10492: goto do_unaryfp;
10493: case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10494: mips32_op = OPC_CVT_S_PU;
10495: goto do_unaryfp;
10496: case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10497: mips32_op = OPC_CVT_PW_PS;
10498: goto do_unaryfp;
10499: case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10500: mips32_op = OPC_CVT_PS_PW;
10501: goto do_unaryfp;
10502:
10503: /* Floating-point moves */
10504: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10505: mips32_op = OPC_MOV_S;
10506: goto do_unaryfp;
10507: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10508: mips32_op = OPC_MOV_D;
10509: goto do_unaryfp;
10510: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10511: mips32_op = OPC_MOV_PS;
10512: goto do_unaryfp;
10513:
10514: /* Absolute value */
10515: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10516: mips32_op = OPC_ABS_S;
10517: goto do_unaryfp;
10518: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10519: mips32_op = OPC_ABS_D;
10520: goto do_unaryfp;
10521: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10522: mips32_op = OPC_ABS_PS;
10523: goto do_unaryfp;
10524:
10525: /* Negation */
10526: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10527: mips32_op = OPC_NEG_S;
10528: goto do_unaryfp;
10529: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10530: mips32_op = OPC_NEG_D;
10531: goto do_unaryfp;
10532: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10533: mips32_op = OPC_NEG_PS;
10534: goto do_unaryfp;
10535:
10536: /* Reciprocal square root step */
10537: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10538: mips32_op = OPC_RSQRT1_S;
10539: goto do_unaryfp;
10540: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10541: mips32_op = OPC_RSQRT1_D;
10542: goto do_unaryfp;
10543: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10544: mips32_op = OPC_RSQRT1_PS;
10545: goto do_unaryfp;
10546:
10547: /* Reciprocal step */
10548: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10549: mips32_op = OPC_RECIP1_S;
10550: goto do_unaryfp;
10551: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10552: mips32_op = OPC_RECIP1_S;
10553: goto do_unaryfp;
10554: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10555: mips32_op = OPC_RECIP1_PS;
10556: goto do_unaryfp;
10557:
10558: /* Conversions from double */
10559: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10560: mips32_op = OPC_CVT_D_S;
10561: goto do_unaryfp;
10562: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10563: mips32_op = OPC_CVT_D_W;
10564: goto do_unaryfp;
10565: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10566: mips32_op = OPC_CVT_D_L;
10567: goto do_unaryfp;
10568:
10569: /* Conversions from single */
10570: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10571: mips32_op = OPC_CVT_S_D;
10572: goto do_unaryfp;
10573: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10574: mips32_op = OPC_CVT_S_W;
10575: goto do_unaryfp;
10576: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10577: mips32_op = OPC_CVT_S_L;
10578: do_unaryfp:
10579: gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10580: break;
10581:
10582: /* Conditional moves on floating-point codes */
10583: case COND_FLOAT_MOV(MOVT, 0):
10584: case COND_FLOAT_MOV(MOVT, 1):
10585: case COND_FLOAT_MOV(MOVT, 2):
10586: case COND_FLOAT_MOV(MOVT, 3):
10587: case COND_FLOAT_MOV(MOVT, 4):
10588: case COND_FLOAT_MOV(MOVT, 5):
10589: case COND_FLOAT_MOV(MOVT, 6):
10590: case COND_FLOAT_MOV(MOVT, 7):
10591: gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
10592: break;
10593: case COND_FLOAT_MOV(MOVF, 0):
10594: case COND_FLOAT_MOV(MOVF, 1):
10595: case COND_FLOAT_MOV(MOVF, 2):
10596: case COND_FLOAT_MOV(MOVF, 3):
10597: case COND_FLOAT_MOV(MOVF, 4):
10598: case COND_FLOAT_MOV(MOVF, 5):
10599: case COND_FLOAT_MOV(MOVF, 6):
10600: case COND_FLOAT_MOV(MOVF, 7):
10601: gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
10602: break;
10603: default:
10604: MIPS_INVAL("pool32fxf");
10605: generate_exception(ctx, EXCP_RI);
10606: break;
10607: }
10608: }
10609:
1.1.1.16! root 10610: static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
1.1.1.12 root 10611: uint16_t insn_hw1, int *is_branch)
10612: {
10613: int32_t offset;
10614: uint16_t insn;
10615: int rt, rs, rd, rr;
10616: int16_t imm;
10617: uint32_t op, minor, mips32_op;
10618: uint32_t cond, fmt, cc;
10619:
10620: insn = lduw_code(ctx->pc + 2);
10621: ctx->opcode = (ctx->opcode << 16) | insn;
10622:
10623: rt = (ctx->opcode >> 21) & 0x1f;
10624: rs = (ctx->opcode >> 16) & 0x1f;
10625: rd = (ctx->opcode >> 11) & 0x1f;
10626: rr = (ctx->opcode >> 6) & 0x1f;
10627: imm = (int16_t) ctx->opcode;
10628:
10629: op = (ctx->opcode >> 26) & 0x3f;
10630: switch (op) {
10631: case POOL32A:
10632: minor = ctx->opcode & 0x3f;
10633: switch (minor) {
10634: case 0x00:
10635: minor = (ctx->opcode >> 6) & 0xf;
10636: switch (minor) {
10637: case SLL32:
10638: mips32_op = OPC_SLL;
10639: goto do_shifti;
10640: case SRA:
10641: mips32_op = OPC_SRA;
10642: goto do_shifti;
10643: case SRL32:
10644: mips32_op = OPC_SRL;
10645: goto do_shifti;
10646: case ROTR:
10647: mips32_op = OPC_ROTR;
10648: do_shifti:
10649: gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
10650: break;
10651: default:
10652: goto pool32a_invalid;
10653: }
10654: break;
10655: case 0x10:
10656: minor = (ctx->opcode >> 6) & 0xf;
10657: switch (minor) {
10658: /* Arithmetic */
10659: case ADD:
10660: mips32_op = OPC_ADD;
10661: goto do_arith;
10662: case ADDU32:
10663: mips32_op = OPC_ADDU;
10664: goto do_arith;
10665: case SUB:
10666: mips32_op = OPC_SUB;
10667: goto do_arith;
10668: case SUBU32:
10669: mips32_op = OPC_SUBU;
10670: goto do_arith;
10671: case MUL:
10672: mips32_op = OPC_MUL;
10673: do_arith:
10674: gen_arith(env, ctx, mips32_op, rd, rs, rt);
10675: break;
10676: /* Shifts */
10677: case SLLV:
10678: mips32_op = OPC_SLLV;
10679: goto do_shift;
10680: case SRLV:
10681: mips32_op = OPC_SRLV;
10682: goto do_shift;
10683: case SRAV:
10684: mips32_op = OPC_SRAV;
10685: goto do_shift;
10686: case ROTRV:
10687: mips32_op = OPC_ROTRV;
10688: do_shift:
10689: gen_shift(env, ctx, mips32_op, rd, rs, rt);
10690: break;
10691: /* Logical operations */
10692: case AND:
10693: mips32_op = OPC_AND;
10694: goto do_logic;
10695: case OR32:
10696: mips32_op = OPC_OR;
10697: goto do_logic;
10698: case NOR:
10699: mips32_op = OPC_NOR;
10700: goto do_logic;
10701: case XOR32:
10702: mips32_op = OPC_XOR;
10703: do_logic:
10704: gen_logic(env, mips32_op, rd, rs, rt);
10705: break;
10706: /* Set less than */
10707: case SLT:
10708: mips32_op = OPC_SLT;
10709: goto do_slt;
10710: case SLTU:
10711: mips32_op = OPC_SLTU;
10712: do_slt:
10713: gen_slt(env, mips32_op, rd, rs, rt);
10714: break;
10715: default:
10716: goto pool32a_invalid;
10717: }
10718: break;
10719: case 0x18:
10720: minor = (ctx->opcode >> 6) & 0xf;
10721: switch (minor) {
10722: /* Conditional moves */
10723: case MOVN:
10724: mips32_op = OPC_MOVN;
10725: goto do_cmov;
10726: case MOVZ:
10727: mips32_op = OPC_MOVZ;
10728: do_cmov:
10729: gen_cond_move(env, mips32_op, rd, rs, rt);
10730: break;
10731: case LWXS:
10732: gen_ldxs(ctx, rs, rt, rd);
10733: break;
10734: default:
10735: goto pool32a_invalid;
10736: }
10737: break;
10738: case INS:
10739: gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
10740: return;
10741: case EXT:
10742: gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
10743: return;
10744: case POOL32AXF:
10745: gen_pool32axf(env, ctx, rt, rs, is_branch);
10746: break;
10747: case 0x07:
10748: generate_exception(ctx, EXCP_BREAK);
10749: break;
10750: default:
10751: pool32a_invalid:
10752: MIPS_INVAL("pool32a");
10753: generate_exception(ctx, EXCP_RI);
10754: break;
10755: }
10756: break;
10757: case POOL32B:
10758: minor = (ctx->opcode >> 12) & 0xf;
10759: switch (minor) {
10760: case CACHE:
10761: /* Treat as no-op. */
10762: break;
10763: case LWC2:
10764: case SWC2:
10765: /* COP2: Not implemented. */
10766: generate_exception_err(ctx, EXCP_CpU, 2);
10767: break;
10768: case LWP:
10769: case SWP:
10770: #ifdef TARGET_MIPS64
10771: case LDP:
10772: case SDP:
10773: #endif
10774: gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10775: break;
10776: case LWM32:
10777: case SWM32:
10778: #ifdef TARGET_MIPS64
10779: case LDM:
10780: case SDM:
10781: #endif
10782: gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10783: break;
10784: default:
10785: MIPS_INVAL("pool32b");
10786: generate_exception(ctx, EXCP_RI);
10787: break;
10788: }
10789: break;
10790: case POOL32F:
10791: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
10792: minor = ctx->opcode & 0x3f;
10793: check_cp1_enabled(ctx);
10794: switch (minor) {
10795: case ALNV_PS:
10796: mips32_op = OPC_ALNV_PS;
10797: goto do_madd;
10798: case MADD_S:
10799: mips32_op = OPC_MADD_S;
10800: goto do_madd;
10801: case MADD_D:
10802: mips32_op = OPC_MADD_D;
10803: goto do_madd;
10804: case MADD_PS:
10805: mips32_op = OPC_MADD_PS;
10806: goto do_madd;
10807: case MSUB_S:
10808: mips32_op = OPC_MSUB_S;
10809: goto do_madd;
10810: case MSUB_D:
10811: mips32_op = OPC_MSUB_D;
10812: goto do_madd;
10813: case MSUB_PS:
10814: mips32_op = OPC_MSUB_PS;
10815: goto do_madd;
10816: case NMADD_S:
10817: mips32_op = OPC_NMADD_S;
10818: goto do_madd;
10819: case NMADD_D:
10820: mips32_op = OPC_NMADD_D;
10821: goto do_madd;
10822: case NMADD_PS:
10823: mips32_op = OPC_NMADD_PS;
10824: goto do_madd;
10825: case NMSUB_S:
10826: mips32_op = OPC_NMSUB_S;
10827: goto do_madd;
10828: case NMSUB_D:
10829: mips32_op = OPC_NMSUB_D;
10830: goto do_madd;
10831: case NMSUB_PS:
10832: mips32_op = OPC_NMSUB_PS;
10833: do_madd:
10834: gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
10835: break;
10836: case CABS_COND_FMT:
10837: cond = (ctx->opcode >> 6) & 0xf;
10838: cc = (ctx->opcode >> 13) & 0x7;
10839: fmt = (ctx->opcode >> 10) & 0x3;
10840: switch (fmt) {
10841: case 0x0:
10842: gen_cmpabs_s(ctx, cond, rt, rs, cc);
10843: break;
10844: case 0x1:
10845: gen_cmpabs_d(ctx, cond, rt, rs, cc);
10846: break;
10847: case 0x2:
10848: gen_cmpabs_ps(ctx, cond, rt, rs, cc);
10849: break;
10850: default:
10851: goto pool32f_invalid;
10852: }
10853: break;
10854: case C_COND_FMT:
10855: cond = (ctx->opcode >> 6) & 0xf;
10856: cc = (ctx->opcode >> 13) & 0x7;
10857: fmt = (ctx->opcode >> 10) & 0x3;
10858: switch (fmt) {
10859: case 0x0:
10860: gen_cmp_s(ctx, cond, rt, rs, cc);
10861: break;
10862: case 0x1:
10863: gen_cmp_d(ctx, cond, rt, rs, cc);
10864: break;
10865: case 0x2:
10866: gen_cmp_ps(ctx, cond, rt, rs, cc);
10867: break;
10868: default:
10869: goto pool32f_invalid;
10870: }
10871: break;
10872: case POOL32FXF:
10873: gen_pool32fxf(env, ctx, rt, rs);
10874: break;
10875: case 0x00:
10876: /* PLL foo */
10877: switch ((ctx->opcode >> 6) & 0x7) {
10878: case PLL_PS:
10879: mips32_op = OPC_PLL_PS;
10880: goto do_ps;
10881: case PLU_PS:
10882: mips32_op = OPC_PLU_PS;
10883: goto do_ps;
10884: case PUL_PS:
10885: mips32_op = OPC_PUL_PS;
10886: goto do_ps;
10887: case PUU_PS:
10888: mips32_op = OPC_PUU_PS;
10889: goto do_ps;
10890: case CVT_PS_S:
10891: mips32_op = OPC_CVT_PS_S;
10892: do_ps:
10893: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10894: break;
10895: default:
10896: goto pool32f_invalid;
10897: }
10898: break;
10899: case 0x08:
10900: /* [LS][WDU]XC1 */
10901: switch ((ctx->opcode >> 6) & 0x7) {
10902: case LWXC1:
10903: mips32_op = OPC_LWXC1;
10904: goto do_ldst_cp1;
10905: case SWXC1:
10906: mips32_op = OPC_SWXC1;
10907: goto do_ldst_cp1;
10908: case LDXC1:
10909: mips32_op = OPC_LDXC1;
10910: goto do_ldst_cp1;
10911: case SDXC1:
10912: mips32_op = OPC_SDXC1;
10913: goto do_ldst_cp1;
10914: case LUXC1:
10915: mips32_op = OPC_LUXC1;
10916: goto do_ldst_cp1;
10917: case SUXC1:
10918: mips32_op = OPC_SUXC1;
10919: do_ldst_cp1:
10920: gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
10921: break;
10922: default:
10923: goto pool32f_invalid;
10924: }
10925: break;
10926: case 0x18:
10927: /* 3D insns */
10928: fmt = (ctx->opcode >> 9) & 0x3;
10929: switch ((ctx->opcode >> 6) & 0x7) {
10930: case RSQRT2_FMT:
10931: switch (fmt) {
10932: case FMT_SDPS_S:
10933: mips32_op = OPC_RSQRT2_S;
10934: goto do_3d;
10935: case FMT_SDPS_D:
10936: mips32_op = OPC_RSQRT2_D;
10937: goto do_3d;
10938: case FMT_SDPS_PS:
10939: mips32_op = OPC_RSQRT2_PS;
10940: goto do_3d;
10941: default:
10942: goto pool32f_invalid;
10943: }
10944: break;
10945: case RECIP2_FMT:
10946: switch (fmt) {
10947: case FMT_SDPS_S:
10948: mips32_op = OPC_RECIP2_S;
10949: goto do_3d;
10950: case FMT_SDPS_D:
10951: mips32_op = OPC_RECIP2_D;
10952: goto do_3d;
10953: case FMT_SDPS_PS:
10954: mips32_op = OPC_RECIP2_PS;
10955: goto do_3d;
10956: default:
10957: goto pool32f_invalid;
10958: }
10959: break;
10960: case ADDR_PS:
10961: mips32_op = OPC_ADDR_PS;
10962: goto do_3d;
10963: case MULR_PS:
10964: mips32_op = OPC_MULR_PS;
10965: do_3d:
10966: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10967: break;
10968: default:
10969: goto pool32f_invalid;
10970: }
10971: break;
10972: case 0x20:
10973: /* MOV[FT].fmt and PREFX */
10974: cc = (ctx->opcode >> 13) & 0x7;
10975: fmt = (ctx->opcode >> 9) & 0x3;
10976: switch ((ctx->opcode >> 6) & 0x7) {
10977: case MOVF_FMT:
10978: switch (fmt) {
10979: case FMT_SDPS_S:
10980: gen_movcf_s(rs, rt, cc, 0);
10981: break;
10982: case FMT_SDPS_D:
10983: gen_movcf_d(ctx, rs, rt, cc, 0);
10984: break;
10985: case FMT_SDPS_PS:
10986: gen_movcf_ps(rs, rt, cc, 0);
10987: break;
10988: default:
10989: goto pool32f_invalid;
10990: }
10991: break;
10992: case MOVT_FMT:
10993: switch (fmt) {
10994: case FMT_SDPS_S:
10995: gen_movcf_s(rs, rt, cc, 1);
10996: break;
10997: case FMT_SDPS_D:
10998: gen_movcf_d(ctx, rs, rt, cc, 1);
10999: break;
11000: case FMT_SDPS_PS:
11001: gen_movcf_ps(rs, rt, cc, 1);
11002: break;
11003: default:
11004: goto pool32f_invalid;
11005: }
11006: break;
11007: case PREFX:
11008: break;
11009: default:
11010: goto pool32f_invalid;
11011: }
11012: break;
11013: #define FINSN_3ARG_SDPS(prfx) \
11014: switch ((ctx->opcode >> 8) & 0x3) { \
11015: case FMT_SDPS_S: \
11016: mips32_op = OPC_##prfx##_S; \
11017: goto do_fpop; \
11018: case FMT_SDPS_D: \
11019: mips32_op = OPC_##prfx##_D; \
11020: goto do_fpop; \
11021: case FMT_SDPS_PS: \
11022: mips32_op = OPC_##prfx##_PS; \
11023: goto do_fpop; \
11024: default: \
11025: goto pool32f_invalid; \
11026: }
11027: case 0x30:
11028: /* regular FP ops */
11029: switch ((ctx->opcode >> 6) & 0x3) {
11030: case ADD_FMT:
11031: FINSN_3ARG_SDPS(ADD);
11032: break;
11033: case SUB_FMT:
11034: FINSN_3ARG_SDPS(SUB);
11035: break;
11036: case MUL_FMT:
11037: FINSN_3ARG_SDPS(MUL);
11038: break;
11039: case DIV_FMT:
11040: fmt = (ctx->opcode >> 8) & 0x3;
11041: if (fmt == 1) {
11042: mips32_op = OPC_DIV_D;
11043: } else if (fmt == 0) {
11044: mips32_op = OPC_DIV_S;
11045: } else {
11046: goto pool32f_invalid;
11047: }
11048: goto do_fpop;
11049: default:
11050: goto pool32f_invalid;
11051: }
11052: break;
11053: case 0x38:
11054: /* cmovs */
11055: switch ((ctx->opcode >> 6) & 0x3) {
11056: case MOVN_FMT:
11057: FINSN_3ARG_SDPS(MOVN);
11058: break;
11059: case MOVZ_FMT:
11060: FINSN_3ARG_SDPS(MOVZ);
11061: break;
11062: default:
11063: goto pool32f_invalid;
11064: }
11065: break;
11066: do_fpop:
11067: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11068: break;
11069: default:
11070: pool32f_invalid:
11071: MIPS_INVAL("pool32f");
11072: generate_exception(ctx, EXCP_RI);
11073: break;
11074: }
11075: } else {
11076: generate_exception_err(ctx, EXCP_CpU, 1);
11077: }
11078: break;
11079: case POOL32I:
11080: minor = (ctx->opcode >> 21) & 0x1f;
11081: switch (minor) {
11082: case BLTZ:
11083: mips32_op = OPC_BLTZ;
11084: goto do_branch;
11085: case BLTZAL:
11086: mips32_op = OPC_BLTZAL;
11087: goto do_branch;
11088: case BLTZALS:
11089: mips32_op = OPC_BLTZALS;
11090: goto do_branch;
11091: case BGEZ:
11092: mips32_op = OPC_BGEZ;
11093: goto do_branch;
11094: case BGEZAL:
11095: mips32_op = OPC_BGEZAL;
11096: goto do_branch;
11097: case BGEZALS:
11098: mips32_op = OPC_BGEZALS;
11099: goto do_branch;
11100: case BLEZ:
11101: mips32_op = OPC_BLEZ;
11102: goto do_branch;
11103: case BGTZ:
11104: mips32_op = OPC_BGTZ;
11105: do_branch:
11106: gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11107: *is_branch = 1;
11108: break;
11109:
11110: /* Traps */
11111: case TLTI:
11112: mips32_op = OPC_TLTI;
11113: goto do_trapi;
11114: case TGEI:
11115: mips32_op = OPC_TGEI;
11116: goto do_trapi;
11117: case TLTIU:
11118: mips32_op = OPC_TLTIU;
11119: goto do_trapi;
11120: case TGEIU:
11121: mips32_op = OPC_TGEIU;
11122: goto do_trapi;
11123: case TNEI:
11124: mips32_op = OPC_TNEI;
11125: goto do_trapi;
11126: case TEQI:
11127: mips32_op = OPC_TEQI;
11128: do_trapi:
11129: gen_trap(ctx, mips32_op, rs, -1, imm);
11130: break;
11131:
11132: case BNEZC:
11133: case BEQZC:
11134: gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11135: 4, rs, 0, imm << 1);
11136: /* Compact branches don't have a delay slot, so just let
11137: the normal delay slot handling take us to the branch
11138: target. */
11139: break;
11140: case LUI:
11141: gen_logic_imm(env, OPC_LUI, rs, -1, imm);
11142: break;
11143: case SYNCI:
11144: break;
11145: case BC2F:
11146: case BC2T:
11147: /* COP2: Not implemented. */
11148: generate_exception_err(ctx, EXCP_CpU, 2);
11149: break;
11150: case BC1F:
11151: mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11152: goto do_cp1branch;
11153: case BC1T:
11154: mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11155: goto do_cp1branch;
11156: case BC1ANY4F:
11157: mips32_op = OPC_BC1FANY4;
11158: goto do_cp1mips3d;
11159: case BC1ANY4T:
11160: mips32_op = OPC_BC1TANY4;
11161: do_cp1mips3d:
11162: check_cop1x(ctx);
11163: check_insn(env, ctx, ASE_MIPS3D);
11164: /* Fall through */
11165: do_cp1branch:
11166: gen_compute_branch1(env, ctx, mips32_op,
11167: (ctx->opcode >> 18) & 0x7, imm << 1);
11168: *is_branch = 1;
11169: break;
11170: case BPOSGE64:
11171: case BPOSGE32:
11172: /* MIPS DSP: not implemented */
11173: /* Fall through */
11174: default:
11175: MIPS_INVAL("pool32i");
11176: generate_exception(ctx, EXCP_RI);
11177: break;
11178: }
11179: break;
11180: case POOL32C:
11181: minor = (ctx->opcode >> 12) & 0xf;
11182: switch (minor) {
11183: case LWL:
11184: mips32_op = OPC_LWL;
11185: goto do_ld_lr;
11186: case SWL:
11187: mips32_op = OPC_SWL;
11188: goto do_st_lr;
11189: case LWR:
11190: mips32_op = OPC_LWR;
11191: goto do_ld_lr;
11192: case SWR:
11193: mips32_op = OPC_SWR;
11194: goto do_st_lr;
11195: #if defined(TARGET_MIPS64)
11196: case LDL:
11197: mips32_op = OPC_LDL;
11198: goto do_ld_lr;
11199: case SDL:
11200: mips32_op = OPC_SDL;
11201: goto do_st_lr;
11202: case LDR:
11203: mips32_op = OPC_LDR;
11204: goto do_ld_lr;
11205: case SDR:
11206: mips32_op = OPC_SDR;
11207: goto do_st_lr;
11208: case LWU:
11209: mips32_op = OPC_LWU;
11210: goto do_ld_lr;
11211: case LLD:
11212: mips32_op = OPC_LLD;
11213: goto do_ld_lr;
11214: #endif
11215: case LL:
11216: mips32_op = OPC_LL;
11217: goto do_ld_lr;
11218: do_ld_lr:
11219: gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11220: break;
11221: do_st_lr:
11222: gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11223: break;
11224: case SC:
11225: gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11226: break;
11227: #if defined(TARGET_MIPS64)
11228: case SCD:
11229: gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11230: break;
11231: #endif
11232: case PREF:
11233: /* Treat as no-op */
11234: break;
11235: default:
11236: MIPS_INVAL("pool32c");
11237: generate_exception(ctx, EXCP_RI);
11238: break;
11239: }
11240: break;
11241: case ADDI32:
11242: mips32_op = OPC_ADDI;
11243: goto do_addi;
11244: case ADDIU32:
11245: mips32_op = OPC_ADDIU;
11246: do_addi:
11247: gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11248: break;
11249:
11250: /* Logical operations */
11251: case ORI32:
11252: mips32_op = OPC_ORI;
11253: goto do_logici;
11254: case XORI32:
11255: mips32_op = OPC_XORI;
11256: goto do_logici;
11257: case ANDI32:
11258: mips32_op = OPC_ANDI;
11259: do_logici:
11260: gen_logic_imm(env, mips32_op, rt, rs, imm);
11261: break;
11262:
11263: /* Set less than immediate */
11264: case SLTI32:
11265: mips32_op = OPC_SLTI;
11266: goto do_slti;
11267: case SLTIU32:
11268: mips32_op = OPC_SLTIU;
11269: do_slti:
11270: gen_slt_imm(env, mips32_op, rt, rs, imm);
11271: break;
11272: case JALX32:
11273: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11274: gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11275: *is_branch = 1;
11276: break;
11277: case JALS32:
11278: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11279: gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11280: *is_branch = 1;
11281: break;
11282: case BEQ32:
11283: gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11284: *is_branch = 1;
11285: break;
11286: case BNE32:
11287: gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11288: *is_branch = 1;
11289: break;
11290: case J32:
11291: gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11292: (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11293: *is_branch = 1;
11294: break;
11295: case JAL32:
11296: gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11297: (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11298: *is_branch = 1;
11299: break;
11300: /* Floating point (COP1) */
11301: case LWC132:
11302: mips32_op = OPC_LWC1;
11303: goto do_cop1;
11304: case LDC132:
11305: mips32_op = OPC_LDC1;
11306: goto do_cop1;
11307: case SWC132:
11308: mips32_op = OPC_SWC1;
11309: goto do_cop1;
11310: case SDC132:
11311: mips32_op = OPC_SDC1;
11312: do_cop1:
11313: gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11314: break;
11315: case ADDIUPC:
11316: {
11317: int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11318: int offset = SIMM(ctx->opcode, 0, 23) << 2;
11319:
11320: gen_addiupc(ctx, reg, offset, 0, 0);
11321: }
11322: break;
11323: /* Loads and stores */
11324: case LB32:
11325: mips32_op = OPC_LB;
11326: goto do_ld;
11327: case LBU32:
11328: mips32_op = OPC_LBU;
11329: goto do_ld;
11330: case LH32:
11331: mips32_op = OPC_LH;
11332: goto do_ld;
11333: case LHU32:
11334: mips32_op = OPC_LHU;
11335: goto do_ld;
11336: case LW32:
11337: mips32_op = OPC_LW;
11338: goto do_ld;
11339: #ifdef TARGET_MIPS64
11340: case LD32:
11341: mips32_op = OPC_LD;
11342: goto do_ld;
11343: case SD32:
11344: mips32_op = OPC_SD;
11345: goto do_st;
11346: #endif
11347: case SB32:
11348: mips32_op = OPC_SB;
11349: goto do_st;
11350: case SH32:
11351: mips32_op = OPC_SH;
11352: goto do_st;
11353: case SW32:
11354: mips32_op = OPC_SW;
11355: goto do_st;
11356: do_ld:
11357: gen_ld(env, ctx, mips32_op, rt, rs, imm);
11358: break;
11359: do_st:
11360: gen_st(ctx, mips32_op, rt, rs, imm);
11361: break;
11362: default:
11363: generate_exception(ctx, EXCP_RI);
11364: break;
11365: }
11366: }
11367:
1.1.1.16! root 11368: static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
1.1.1.12 root 11369: {
11370: uint32_t op;
11371:
11372: /* make sure instructions are on a halfword boundary */
11373: if (ctx->pc & 0x1) {
11374: env->CP0_BadVAddr = ctx->pc;
11375: generate_exception(ctx, EXCP_AdEL);
11376: ctx->bstate = BS_STOP;
11377: return 2;
11378: }
11379:
11380: op = (ctx->opcode >> 10) & 0x3f;
11381: /* Enforce properly-sized instructions in a delay slot */
11382: if (ctx->hflags & MIPS_HFLAG_BMASK) {
11383: int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11384:
11385: switch (op) {
11386: case POOL32A:
11387: case POOL32B:
11388: case POOL32I:
11389: case POOL32C:
11390: case ADDI32:
11391: case ADDIU32:
11392: case ORI32:
11393: case XORI32:
11394: case SLTI32:
11395: case SLTIU32:
11396: case ANDI32:
11397: case JALX32:
11398: case LBU32:
11399: case LHU32:
11400: case POOL32F:
11401: case JALS32:
11402: case BEQ32:
11403: case BNE32:
11404: case J32:
11405: case JAL32:
11406: case SB32:
11407: case SH32:
11408: case POOL32S:
11409: case ADDIUPC:
11410: case SWC132:
11411: case SDC132:
11412: case SD32:
11413: case SW32:
11414: case LB32:
11415: case LH32:
11416: case DADDIU32:
11417: case POOL48A: /* ??? */
11418: case LWC132:
11419: case LDC132:
11420: case LD32:
11421: case LW32:
11422: if (bits & MIPS_HFLAG_BDS16) {
11423: generate_exception(ctx, EXCP_RI);
11424: /* Just stop translation; the user is confused. */
11425: ctx->bstate = BS_STOP;
11426: return 2;
11427: }
11428: break;
11429: case POOL16A:
11430: case POOL16B:
11431: case POOL16C:
11432: case LWGP16:
11433: case POOL16F:
11434: case LBU16:
11435: case LHU16:
11436: case LWSP16:
11437: case LW16:
11438: case SB16:
11439: case SH16:
11440: case SWSP16:
11441: case SW16:
11442: case MOVE16:
11443: case ANDI16:
11444: case POOL16D:
11445: case POOL16E:
11446: case BEQZ16:
11447: case BNEZ16:
11448: case B16:
11449: case LI16:
11450: if (bits & MIPS_HFLAG_BDS32) {
11451: generate_exception(ctx, EXCP_RI);
11452: /* Just stop translation; the user is confused. */
11453: ctx->bstate = BS_STOP;
11454: return 2;
11455: }
11456: break;
11457: default:
11458: break;
11459: }
11460: }
11461: switch (op) {
11462: case POOL16A:
11463: {
11464: int rd = mmreg(uMIPS_RD(ctx->opcode));
11465: int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11466: int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11467: uint32_t opc = 0;
11468:
11469: switch (ctx->opcode & 0x1) {
11470: case ADDU16:
11471: opc = OPC_ADDU;
11472: break;
11473: case SUBU16:
11474: opc = OPC_SUBU;
11475: break;
11476: }
11477:
11478: gen_arith(env, ctx, opc, rd, rs1, rs2);
11479: }
11480: break;
11481: case POOL16B:
11482: {
11483: int rd = mmreg(uMIPS_RD(ctx->opcode));
11484: int rs = mmreg(uMIPS_RS(ctx->opcode));
11485: int amount = (ctx->opcode >> 1) & 0x7;
11486: uint32_t opc = 0;
11487: amount = amount == 0 ? 8 : amount;
11488:
11489: switch (ctx->opcode & 0x1) {
11490: case SLL16:
11491: opc = OPC_SLL;
11492: break;
11493: case SRL16:
11494: opc = OPC_SRL;
11495: break;
11496: }
11497:
11498: gen_shift_imm(env, ctx, opc, rd, rs, amount);
11499: }
11500: break;
11501: case POOL16C:
11502: gen_pool16c_insn(env, ctx, is_branch);
11503: break;
11504: case LWGP16:
11505: {
11506: int rd = mmreg(uMIPS_RD(ctx->opcode));
11507: int rb = 28; /* GP */
11508: int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11509:
11510: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11511: }
11512: break;
11513: case POOL16F:
11514: if (ctx->opcode & 1) {
11515: generate_exception(ctx, EXCP_RI);
11516: } else {
11517: /* MOVEP */
11518: int enc_dest = uMIPS_RD(ctx->opcode);
11519: int enc_rt = uMIPS_RS2(ctx->opcode);
11520: int enc_rs = uMIPS_RS1(ctx->opcode);
11521: int rd, rs, re, rt;
11522: static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11523: static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11524: static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11525:
11526: rd = rd_enc[enc_dest];
11527: re = re_enc[enc_dest];
11528: rs = rs_rt_enc[enc_rs];
11529: rt = rs_rt_enc[enc_rt];
11530:
11531: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11532: gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11533: }
11534: break;
11535: case LBU16:
11536: {
11537: int rd = mmreg(uMIPS_RD(ctx->opcode));
11538: int rb = mmreg(uMIPS_RS(ctx->opcode));
11539: int16_t offset = ZIMM(ctx->opcode, 0, 4);
11540: offset = (offset == 0xf ? -1 : offset);
11541:
11542: gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
11543: }
11544: break;
11545: case LHU16:
11546: {
11547: int rd = mmreg(uMIPS_RD(ctx->opcode));
11548: int rb = mmreg(uMIPS_RS(ctx->opcode));
11549: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11550:
11551: gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
11552: }
11553: break;
11554: case LWSP16:
11555: {
11556: int rd = (ctx->opcode >> 5) & 0x1f;
11557: int rb = 29; /* SP */
11558: int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11559:
11560: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11561: }
11562: break;
11563: case LW16:
11564: {
11565: int rd = mmreg(uMIPS_RD(ctx->opcode));
11566: int rb = mmreg(uMIPS_RS(ctx->opcode));
11567: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11568:
11569: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11570: }
11571: break;
11572: case SB16:
11573: {
11574: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11575: int rb = mmreg(uMIPS_RS(ctx->opcode));
11576: int16_t offset = ZIMM(ctx->opcode, 0, 4);
11577:
11578: gen_st(ctx, OPC_SB, rd, rb, offset);
11579: }
11580: break;
11581: case SH16:
11582: {
11583: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11584: int rb = mmreg(uMIPS_RS(ctx->opcode));
11585: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11586:
11587: gen_st(ctx, OPC_SH, rd, rb, offset);
11588: }
11589: break;
11590: case SWSP16:
11591: {
11592: int rd = (ctx->opcode >> 5) & 0x1f;
11593: int rb = 29; /* SP */
11594: int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11595:
11596: gen_st(ctx, OPC_SW, rd, rb, offset);
11597: }
11598: break;
11599: case SW16:
11600: {
11601: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11602: int rb = mmreg(uMIPS_RS(ctx->opcode));
11603: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11604:
11605: gen_st(ctx, OPC_SW, rd, rb, offset);
11606: }
11607: break;
11608: case MOVE16:
11609: {
11610: int rd = uMIPS_RD5(ctx->opcode);
11611: int rs = uMIPS_RS5(ctx->opcode);
11612:
11613: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11614: }
11615: break;
11616: case ANDI16:
11617: gen_andi16(env, ctx);
11618: break;
11619: case POOL16D:
11620: switch (ctx->opcode & 0x1) {
11621: case ADDIUS5:
11622: gen_addius5(env, ctx);
11623: break;
11624: case ADDIUSP:
11625: gen_addiusp(env, ctx);
11626: break;
11627: }
11628: break;
11629: case POOL16E:
11630: switch (ctx->opcode & 0x1) {
11631: case ADDIUR2:
11632: gen_addiur2(env, ctx);
11633: break;
11634: case ADDIUR1SP:
11635: gen_addiur1sp(env, ctx);
11636: break;
11637: }
11638: break;
11639: case B16:
11640: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
11641: SIMM(ctx->opcode, 0, 10) << 1);
11642: *is_branch = 1;
11643: break;
11644: case BNEZ16:
11645: case BEQZ16:
11646: gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
11647: mmreg(uMIPS_RD(ctx->opcode)),
11648: 0, SIMM(ctx->opcode, 0, 7) << 1);
11649: *is_branch = 1;
11650: break;
11651: case LI16:
11652: {
11653: int reg = mmreg(uMIPS_RD(ctx->opcode));
11654: int imm = ZIMM(ctx->opcode, 0, 7);
11655:
11656: imm = (imm == 0x7f ? -1 : imm);
11657: tcg_gen_movi_tl(cpu_gpr[reg], imm);
11658: }
11659: break;
11660: case RES_20:
11661: case RES_28:
11662: case RES_29:
11663: case RES_30:
11664: case RES_31:
11665: case RES_38:
11666: case RES_39:
11667: generate_exception(ctx, EXCP_RI);
11668: break;
11669: default:
11670: decode_micromips32_opc (env, ctx, op, is_branch);
11671: return 4;
11672: }
11673:
11674: return 2;
11675: }
11676:
11677: /* SmartMIPS extension to MIPS32 */
11678:
11679: #if defined(TARGET_MIPS64)
11680:
11681: /* MDMX extension to MIPS64 */
11682:
11683: #endif
11684:
1.1.1.16! root 11685: static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
1.1.1.12 root 11686: {
11687: int32_t offset;
11688: int rs, rt, rd, sa;
11689: uint32_t op, op1, op2;
11690: int16_t imm;
11691:
11692: /* make sure instructions are on a word boundary */
11693: if (ctx->pc & 0x3) {
11694: env->CP0_BadVAddr = ctx->pc;
11695: generate_exception(ctx, EXCP_AdEL);
11696: return;
11697: }
11698:
11699: /* Handle blikely not taken case */
11700: if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
11701: int l1 = gen_new_label();
11702:
11703: MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
1.1.1.8 root 11704: tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11705: tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
1.1.1.6 root 11706: gen_goto_tb(ctx, 1, ctx->pc + 4);
11707: gen_set_label(l1);
1.1 root 11708: }
1.1.1.9 root 11709:
11710: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11711: tcg_gen_debug_insn_start(ctx->pc);
11712:
1.1.1.5 root 11713: op = MASK_OP_MAJOR(ctx->opcode);
11714: rs = (ctx->opcode >> 21) & 0x1f;
11715: rt = (ctx->opcode >> 16) & 0x1f;
11716: rd = (ctx->opcode >> 11) & 0x1f;
11717: sa = (ctx->opcode >> 6) & 0x1f;
1.1 root 11718: imm = (int16_t)ctx->opcode;
11719: switch (op) {
1.1.1.5 root 11720: case OPC_SPECIAL:
11721: op1 = MASK_SPECIAL(ctx->opcode);
1.1 root 11722: switch (op1) {
1.1.1.8 root 11723: case OPC_SLL: /* Shift with immediate */
11724: case OPC_SRA:
11725: gen_shift_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 11726: break;
1.1.1.12 root 11727: case OPC_SRL:
11728: switch ((ctx->opcode >> 21) & 0x1f) {
11729: case 1:
11730: /* rotr is decoded as srl on non-R2 CPUs */
11731: if (env->insn_flags & ISA_MIPS32R2) {
11732: op1 = OPC_ROTR;
11733: }
11734: /* Fallthrough */
11735: case 0:
11736: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11737: break;
11738: default:
11739: generate_exception(ctx, EXCP_RI);
11740: break;
11741: }
11742: break;
1.1.1.8 root 11743: case OPC_MOVN: /* Conditional move */
11744: case OPC_MOVZ:
1.1.1.12 root 11745: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
11746: INSN_LOONGSON2E | INSN_LOONGSON2F);
1.1.1.8 root 11747: gen_cond_move(env, op1, rd, rs, rt);
11748: break;
11749: case OPC_ADD ... OPC_SUBU:
1.1.1.6 root 11750: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 11751: break;
1.1.1.8 root 11752: case OPC_SLLV: /* Shifts */
11753: case OPC_SRAV:
11754: gen_shift(env, ctx, op1, rd, rs, rt);
11755: break;
1.1.1.12 root 11756: case OPC_SRLV:
11757: switch ((ctx->opcode >> 6) & 0x1f) {
11758: case 1:
11759: /* rotrv is decoded as srlv on non-R2 CPUs */
11760: if (env->insn_flags & ISA_MIPS32R2) {
11761: op1 = OPC_ROTRV;
11762: }
11763: /* Fallthrough */
11764: case 0:
11765: gen_shift(env, ctx, op1, rd, rs, rt);
11766: break;
11767: default:
11768: generate_exception(ctx, EXCP_RI);
11769: break;
11770: }
11771: break;
1.1.1.8 root 11772: case OPC_SLT: /* Set on less than */
11773: case OPC_SLTU:
11774: gen_slt(env, op1, rd, rs, rt);
11775: break;
11776: case OPC_AND: /* Logic*/
11777: case OPC_OR:
11778: case OPC_NOR:
11779: case OPC_XOR:
11780: gen_logic(env, op1, rd, rs, rt);
11781: break;
1.1.1.5 root 11782: case OPC_MULT ... OPC_DIVU:
1.1.1.6 root 11783: if (sa) {
11784: check_insn(env, ctx, INSN_VR54XX);
11785: op1 = MASK_MUL_VR54XX(ctx->opcode);
11786: gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11787: } else
11788: gen_muldiv(ctx, op1, rs, rt);
1.1 root 11789: break;
1.1.1.5 root 11790: case OPC_JR ... OPC_JALR:
1.1.1.12 root 11791: gen_compute_branch(ctx, op1, 4, rs, rd, sa);
11792: *is_branch = 1;
11793: break;
1.1.1.5 root 11794: case OPC_TGE ... OPC_TEQ: /* Traps */
11795: case OPC_TNE:
11796: gen_trap(ctx, op1, rs, rt, -1);
11797: break;
11798: case OPC_MFHI: /* Move from HI/LO */
11799: case OPC_MFLO:
11800: gen_HILO(ctx, op1, rd);
1.1 root 11801: break;
1.1.1.5 root 11802: case OPC_MTHI:
11803: case OPC_MTLO: /* Move to HI/LO */
11804: gen_HILO(ctx, op1, rs);
11805: break;
1.1.1.6 root 11806: case OPC_PMON: /* Pmon entry point, also R4010 selsl */
11807: #ifdef MIPS_STRICT_STANDARD
11808: MIPS_INVAL("PMON / selsl");
11809: generate_exception(ctx, EXCP_RI);
11810: #else
1.1.1.7 root 11811: gen_helper_0i(pmon, sa);
1.1.1.6 root 11812: #endif
1.1.1.5 root 11813: break;
11814: case OPC_SYSCALL:
1.1 root 11815: generate_exception(ctx, EXCP_SYSCALL);
1.1.1.8 root 11816: ctx->bstate = BS_STOP;
1.1 root 11817: break;
1.1.1.5 root 11818: case OPC_BREAK:
1.1 root 11819: generate_exception(ctx, EXCP_BREAK);
11820: break;
1.1.1.6 root 11821: case OPC_SPIM:
11822: #ifdef MIPS_STRICT_STANDARD
11823: MIPS_INVAL("SPIM");
11824: generate_exception(ctx, EXCP_RI);
11825: #else
1.1.1.5 root 11826: /* Implemented as RI exception for now. */
11827: MIPS_INVAL("spim (unofficial)");
11828: generate_exception(ctx, EXCP_RI);
1.1.1.6 root 11829: #endif
1.1 root 11830: break;
1.1.1.5 root 11831: case OPC_SYNC:
1.1.1.6 root 11832: /* Treat as NOP. */
1.1 root 11833: break;
1.1.1.2 root 11834:
1.1.1.5 root 11835: case OPC_MOVCI:
1.1.1.6 root 11836: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
11837: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11838: check_cp1_enabled(ctx);
11839: gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11840: (ctx->opcode >> 16) & 1);
11841: } else {
11842: generate_exception_err(ctx, EXCP_CpU, 1);
11843: }
1.1.1.2 root 11844: break;
11845:
1.1.1.6 root 11846: #if defined(TARGET_MIPS64)
1.1.1.5 root 11847: /* MIPS64 specific opcodes */
11848: case OPC_DSLL:
1.1.1.8 root 11849: case OPC_DSRA:
1.1.1.5 root 11850: case OPC_DSLL32:
1.1.1.8 root 11851: case OPC_DSRA32:
1.1.1.6 root 11852: check_insn(env, ctx, ISA_MIPS3);
11853: check_mips_64(ctx);
1.1.1.8 root 11854: gen_shift_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 11855: break;
1.1.1.12 root 11856: case OPC_DSRL:
11857: switch ((ctx->opcode >> 21) & 0x1f) {
11858: case 1:
11859: /* drotr is decoded as dsrl on non-R2 CPUs */
11860: if (env->insn_flags & ISA_MIPS32R2) {
11861: op1 = OPC_DROTR;
11862: }
11863: /* Fallthrough */
11864: case 0:
11865: check_insn(env, ctx, ISA_MIPS3);
11866: check_mips_64(ctx);
11867: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11868: break;
11869: default:
11870: generate_exception(ctx, EXCP_RI);
11871: break;
11872: }
11873: break;
11874: case OPC_DSRL32:
11875: switch ((ctx->opcode >> 21) & 0x1f) {
11876: case 1:
11877: /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
11878: if (env->insn_flags & ISA_MIPS32R2) {
11879: op1 = OPC_DROTR32;
11880: }
11881: /* Fallthrough */
11882: case 0:
11883: check_insn(env, ctx, ISA_MIPS3);
11884: check_mips_64(ctx);
11885: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11886: break;
11887: default:
11888: generate_exception(ctx, EXCP_RI);
11889: break;
11890: }
11891: break;
1.1.1.5 root 11892: case OPC_DADD ... OPC_DSUBU:
1.1.1.6 root 11893: check_insn(env, ctx, ISA_MIPS3);
11894: check_mips_64(ctx);
11895: gen_arith(env, ctx, op1, rd, rs, rt);
1.1.1.5 root 11896: break;
1.1.1.8 root 11897: case OPC_DSLLV:
11898: case OPC_DSRAV:
11899: check_insn(env, ctx, ISA_MIPS3);
11900: check_mips_64(ctx);
11901: gen_shift(env, ctx, op1, rd, rs, rt);
11902: break;
1.1.1.12 root 11903: case OPC_DSRLV:
11904: switch ((ctx->opcode >> 6) & 0x1f) {
11905: case 1:
11906: /* drotrv is decoded as dsrlv on non-R2 CPUs */
11907: if (env->insn_flags & ISA_MIPS32R2) {
11908: op1 = OPC_DROTRV;
11909: }
11910: /* Fallthrough */
11911: case 0:
11912: check_insn(env, ctx, ISA_MIPS3);
11913: check_mips_64(ctx);
11914: gen_shift(env, ctx, op1, rd, rs, rt);
11915: break;
11916: default:
11917: generate_exception(ctx, EXCP_RI);
11918: break;
11919: }
11920: break;
1.1.1.5 root 11921: case OPC_DMULT ... OPC_DDIVU:
1.1.1.6 root 11922: check_insn(env, ctx, ISA_MIPS3);
11923: check_mips_64(ctx);
1.1.1.5 root 11924: gen_muldiv(ctx, op1, rs, rt);
11925: break;
1.1 root 11926: #endif
11927: default: /* Invalid */
11928: MIPS_INVAL("special");
11929: generate_exception(ctx, EXCP_RI);
11930: break;
11931: }
11932: break;
1.1.1.5 root 11933: case OPC_SPECIAL2:
11934: op1 = MASK_SPECIAL2(ctx->opcode);
1.1 root 11935: switch (op1) {
1.1.1.5 root 11936: case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11937: case OPC_MSUB ... OPC_MSUBU:
1.1.1.6 root 11938: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 11939: gen_muldiv(ctx, op1, rs, rt);
1.1 root 11940: break;
1.1.1.5 root 11941: case OPC_MUL:
1.1.1.6 root 11942: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 11943: break;
1.1.1.8 root 11944: case OPC_CLO:
11945: case OPC_CLZ:
1.1.1.6 root 11946: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 11947: gen_cl(ctx, op1, rd, rs);
1.1 root 11948: break;
1.1.1.5 root 11949: case OPC_SDBBP:
1.1 root 11950: /* XXX: not clear which exception should be raised
11951: * when in debug mode...
11952: */
1.1.1.6 root 11953: check_insn(env, ctx, ISA_MIPS32);
1.1 root 11954: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11955: generate_exception(ctx, EXCP_DBp);
11956: } else {
11957: generate_exception(ctx, EXCP_DBp);
11958: }
1.1.1.6 root 11959: /* Treat as NOP. */
1.1 root 11960: break;
1.1.1.12 root 11961: case OPC_DIV_G_2F:
11962: case OPC_DIVU_G_2F:
11963: case OPC_MULT_G_2F:
11964: case OPC_MULTU_G_2F:
11965: case OPC_MOD_G_2F:
11966: case OPC_MODU_G_2F:
11967: check_insn(env, ctx, INSN_LOONGSON2F);
11968: gen_loongson_integer(ctx, op1, rd, rs, rt);
11969: break;
1.1.1.6 root 11970: #if defined(TARGET_MIPS64)
1.1.1.8 root 11971: case OPC_DCLO:
11972: case OPC_DCLZ:
1.1.1.6 root 11973: check_insn(env, ctx, ISA_MIPS64);
11974: check_mips_64(ctx);
1.1.1.5 root 11975: gen_cl(ctx, op1, rd, rs);
11976: break;
1.1.1.12 root 11977: case OPC_DMULT_G_2F:
11978: case OPC_DMULTU_G_2F:
11979: case OPC_DDIV_G_2F:
11980: case OPC_DDIVU_G_2F:
11981: case OPC_DMOD_G_2F:
11982: case OPC_DMODU_G_2F:
11983: check_insn(env, ctx, INSN_LOONGSON2F);
11984: gen_loongson_integer(ctx, op1, rd, rs, rt);
11985: break;
1.1.1.5 root 11986: #endif
1.1 root 11987: default: /* Invalid */
11988: MIPS_INVAL("special2");
11989: generate_exception(ctx, EXCP_RI);
11990: break;
11991: }
11992: break;
1.1.1.5 root 11993: case OPC_SPECIAL3:
1.1.1.7 root 11994: op1 = MASK_SPECIAL3(ctx->opcode);
11995: switch (op1) {
11996: case OPC_EXT:
11997: case OPC_INS:
11998: check_insn(env, ctx, ISA_MIPS32R2);
11999: gen_bitops(ctx, op1, rt, rs, sa, rd);
12000: break;
12001: case OPC_BSHFL:
12002: check_insn(env, ctx, ISA_MIPS32R2);
12003: op2 = MASK_BSHFL(ctx->opcode);
12004: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 12005: break;
12006: case OPC_RDHWR:
1.1.1.12 root 12007: gen_rdhwr(env, ctx, rt, rd);
1.1.1.6 root 12008: break;
12009: case OPC_FORK:
12010: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 12011: {
1.1.1.8 root 12012: TCGv t0 = tcg_temp_new();
12013: TCGv t1 = tcg_temp_new();
1.1.1.7 root 12014:
12015: gen_load_gpr(t0, rt);
12016: gen_load_gpr(t1, rs);
12017: gen_helper_fork(t0, t1);
12018: tcg_temp_free(t0);
12019: tcg_temp_free(t1);
12020: }
1.1.1.6 root 12021: break;
12022: case OPC_YIELD:
12023: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 12024: {
1.1.1.8 root 12025: TCGv t0 = tcg_temp_new();
1.1.1.7 root 12026:
1.1.1.8 root 12027: save_cpu_state(ctx, 1);
1.1.1.7 root 12028: gen_load_gpr(t0, rs);
12029: gen_helper_yield(t0, t0);
12030: gen_store_gpr(t0, rd);
12031: tcg_temp_free(t0);
12032: }
1.1.1.6 root 12033: break;
1.1.1.12 root 12034: case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
12035: case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
12036: case OPC_MOD_G_2E ... OPC_MODU_G_2E:
12037: check_insn(env, ctx, INSN_LOONGSON2E);
12038: gen_loongson_integer(ctx, op1, rd, rs, rt);
12039: break;
1.1.1.6 root 12040: #if defined(TARGET_MIPS64)
12041: case OPC_DEXTM ... OPC_DEXT:
12042: case OPC_DINSM ... OPC_DINS:
12043: check_insn(env, ctx, ISA_MIPS64R2);
12044: check_mips_64(ctx);
1.1.1.5 root 12045: gen_bitops(ctx, op1, rt, rs, sa, rd);
12046: break;
1.1.1.6 root 12047: case OPC_DBSHFL:
12048: check_insn(env, ctx, ISA_MIPS64R2);
12049: check_mips_64(ctx);
12050: op2 = MASK_DBSHFL(ctx->opcode);
1.1.1.7 root 12051: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 12052: break;
1.1.1.12 root 12053: case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
12054: case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
12055: case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
12056: check_insn(env, ctx, INSN_LOONGSON2E);
12057: gen_loongson_integer(ctx, op1, rd, rs, rt);
12058: break;
1.1.1.5 root 12059: #endif
12060: default: /* Invalid */
12061: MIPS_INVAL("special3");
12062: generate_exception(ctx, EXCP_RI);
12063: break;
12064: }
12065: break;
12066: case OPC_REGIMM:
12067: op1 = MASK_REGIMM(ctx->opcode);
1.1 root 12068: switch (op1) {
1.1.1.5 root 12069: case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
12070: case OPC_BLTZAL ... OPC_BGEZALL:
1.1.1.12 root 12071: gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
12072: *is_branch = 1;
12073: break;
1.1.1.5 root 12074: case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
12075: case OPC_TNEI:
12076: gen_trap(ctx, op1, rs, -1, imm);
12077: break;
12078: case OPC_SYNCI:
1.1.1.6 root 12079: check_insn(env, ctx, ISA_MIPS32R2);
12080: /* Treat as NOP. */
1.1 root 12081: break;
12082: default: /* Invalid */
1.1.1.6 root 12083: MIPS_INVAL("regimm");
1.1 root 12084: generate_exception(ctx, EXCP_RI);
12085: break;
12086: }
12087: break;
1.1.1.5 root 12088: case OPC_CP0:
1.1.1.6 root 12089: check_cp0_enabled(ctx);
1.1.1.5 root 12090: op1 = MASK_CP0(ctx->opcode);
1.1 root 12091: switch (op1) {
1.1.1.5 root 12092: case OPC_MFC0:
12093: case OPC_MTC0:
1.1.1.6 root 12094: case OPC_MFTR:
12095: case OPC_MTTR:
12096: #if defined(TARGET_MIPS64)
1.1.1.5 root 12097: case OPC_DMFC0:
12098: case OPC_DMTC0:
12099: #endif
1.1.1.7 root 12100: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 12101: gen_cp0(env, ctx, op1, rt, rd);
1.1.1.7 root 12102: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 12103: break;
12104: case OPC_C0_FIRST ... OPC_C0_LAST:
1.1.1.7 root 12105: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 12106: gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
1.1.1.7 root 12107: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 12108: break;
12109: case OPC_MFMC0:
1.1.1.7 root 12110: #ifndef CONFIG_USER_ONLY
12111: {
1.1.1.8 root 12112: TCGv t0 = tcg_temp_new();
1.1.1.7 root 12113:
12114: op2 = MASK_MFMC0(ctx->opcode);
12115: switch (op2) {
12116: case OPC_DMT:
12117: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12118: gen_helper_dmt(t0);
1.1.1.8 root 12119: gen_store_gpr(t0, rt);
1.1.1.7 root 12120: break;
12121: case OPC_EMT:
12122: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12123: gen_helper_emt(t0);
1.1.1.8 root 12124: gen_store_gpr(t0, rt);
1.1.1.7 root 12125: break;
12126: case OPC_DVPE:
12127: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12128: gen_helper_dvpe(t0);
1.1.1.8 root 12129: gen_store_gpr(t0, rt);
1.1.1.7 root 12130: break;
12131: case OPC_EVPE:
12132: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12133: gen_helper_evpe(t0);
1.1.1.8 root 12134: gen_store_gpr(t0, rt);
1.1.1.7 root 12135: break;
12136: case OPC_DI:
12137: check_insn(env, ctx, ISA_MIPS32R2);
12138: save_cpu_state(ctx, 1);
12139: gen_helper_di(t0);
1.1.1.8 root 12140: gen_store_gpr(t0, rt);
1.1.1.7 root 12141: /* Stop translation as we may have switched the execution mode */
12142: ctx->bstate = BS_STOP;
12143: break;
12144: case OPC_EI:
12145: check_insn(env, ctx, ISA_MIPS32R2);
12146: save_cpu_state(ctx, 1);
12147: gen_helper_ei(t0);
1.1.1.8 root 12148: gen_store_gpr(t0, rt);
1.1.1.7 root 12149: /* Stop translation as we may have switched the execution mode */
12150: ctx->bstate = BS_STOP;
12151: break;
12152: default: /* Invalid */
12153: MIPS_INVAL("mfmc0");
12154: generate_exception(ctx, EXCP_RI);
12155: break;
12156: }
12157: tcg_temp_free(t0);
1.1.1.5 root 12158: }
1.1.1.7 root 12159: #endif /* !CONFIG_USER_ONLY */
1.1 root 12160: break;
1.1.1.5 root 12161: case OPC_RDPGPR:
1.1.1.6 root 12162: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 root 12163: gen_load_srsgpr(rt, rd);
1.1.1.6 root 12164: break;
1.1.1.5 root 12165: case OPC_WRPGPR:
1.1.1.6 root 12166: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 root 12167: gen_store_srsgpr(rt, rd);
1.1.1.6 root 12168: break;
1.1 root 12169: default:
1.1.1.6 root 12170: MIPS_INVAL("cp0");
1.1.1.5 root 12171: generate_exception(ctx, EXCP_RI);
1.1 root 12172: break;
12173: }
12174: break;
1.1.1.8 root 12175: case OPC_ADDI: /* Arithmetic with immediate opcode */
12176: case OPC_ADDIU:
1.1.1.6 root 12177: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 12178: break;
1.1.1.8 root 12179: case OPC_SLTI: /* Set on less than with immediate opcode */
12180: case OPC_SLTIU:
12181: gen_slt_imm(env, op, rt, rs, imm);
12182: break;
12183: case OPC_ANDI: /* Arithmetic with immediate opcode */
12184: case OPC_LUI:
12185: case OPC_ORI:
12186: case OPC_XORI:
12187: gen_logic_imm(env, op, rt, rs, imm);
12188: break;
1.1.1.5 root 12189: case OPC_J ... OPC_JAL: /* Jump */
12190: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
1.1.1.12 root 12191: gen_compute_branch(ctx, op, 4, rs, rt, offset);
12192: *is_branch = 1;
12193: break;
1.1.1.5 root 12194: case OPC_BEQ ... OPC_BGTZ: /* Branch */
12195: case OPC_BEQL ... OPC_BGTZL:
1.1.1.12 root 12196: gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
12197: *is_branch = 1;
12198: break;
1.1.1.5 root 12199: case OPC_LB ... OPC_LWR: /* Load and stores */
1.1.1.12 root 12200: case OPC_LL:
12201: gen_ld(env, ctx, op, rt, rs, imm);
12202: break;
1.1.1.5 root 12203: case OPC_SB ... OPC_SW:
12204: case OPC_SWR:
1.1.1.12 root 12205: gen_st(ctx, op, rt, rs, imm);
1.1.1.5 root 12206: break;
1.1.1.8 root 12207: case OPC_SC:
12208: gen_st_cond(ctx, op, rt, rs, imm);
12209: break;
1.1.1.5 root 12210: case OPC_CACHE:
1.1.1.6 root 12211: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
12212: /* Treat as NOP. */
12213: break;
1.1.1.5 root 12214: case OPC_PREF:
1.1.1.6 root 12215: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
12216: /* Treat as NOP. */
1.1 root 12217: break;
1.1.1.2 root 12218:
1.1.1.6 root 12219: /* Floating point (COP1). */
1.1.1.5 root 12220: case OPC_LWC1:
12221: case OPC_LDC1:
12222: case OPC_SWC1:
12223: case OPC_SDC1:
1.1.1.12 root 12224: gen_cop1_ldst(env, ctx, op, rt, rs, imm);
1.1.1.4 root 12225: break;
12226:
1.1.1.5 root 12227: case OPC_CP1:
1.1.1.6 root 12228: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12229: check_cp1_enabled(ctx);
12230: op1 = MASK_CP1(ctx->opcode);
12231: switch (op1) {
12232: case OPC_MFHC1:
12233: case OPC_MTHC1:
12234: check_insn(env, ctx, ISA_MIPS32R2);
12235: case OPC_MFC1:
12236: case OPC_CFC1:
12237: case OPC_MTC1:
12238: case OPC_CTC1:
12239: gen_cp1(ctx, op1, rt, rd);
12240: break;
12241: #if defined(TARGET_MIPS64)
12242: case OPC_DMFC1:
12243: case OPC_DMTC1:
12244: check_insn(env, ctx, ISA_MIPS3);
12245: gen_cp1(ctx, op1, rt, rd);
12246: break;
1.1.1.5 root 12247: #endif
1.1.1.6 root 12248: case OPC_BC1ANY2:
12249: case OPC_BC1ANY4:
12250: check_cop1x(ctx);
12251: check_insn(env, ctx, ASE_MIPS3D);
12252: /* fall through */
12253: case OPC_BC1:
12254: gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
12255: (rt >> 2) & 0x7, imm << 2);
1.1.1.12 root 12256: *is_branch = 1;
12257: break;
1.1.1.6 root 12258: case OPC_S_FMT:
12259: case OPC_D_FMT:
12260: case OPC_W_FMT:
12261: case OPC_L_FMT:
12262: case OPC_PS_FMT:
1.1.1.12 root 12263: gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
1.1.1.6 root 12264: (imm >> 8) & 0x7);
12265: break;
12266: default:
12267: MIPS_INVAL("cp1");
12268: generate_exception (ctx, EXCP_RI);
12269: break;
12270: }
12271: } else {
12272: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.4 root 12273: }
1.1.1.2 root 12274: break;
12275:
12276: /* COP2. */
1.1.1.5 root 12277: case OPC_LWC2:
12278: case OPC_LDC2:
12279: case OPC_SWC2:
12280: case OPC_SDC2:
12281: case OPC_CP2:
12282: /* COP2: Not implemented. */
1.1.1.2 root 12283: generate_exception_err(ctx, EXCP_CpU, 2);
12284: break;
12285:
1.1.1.5 root 12286: case OPC_CP3:
1.1.1.6 root 12287: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12288: check_cp1_enabled(ctx);
12289: op1 = MASK_CP3(ctx->opcode);
12290: switch (op1) {
12291: case OPC_LWXC1:
12292: case OPC_LDXC1:
12293: case OPC_LUXC1:
12294: case OPC_SWXC1:
12295: case OPC_SDXC1:
12296: case OPC_SUXC1:
12297: gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
12298: break;
12299: case OPC_PREFX:
12300: /* Treat as NOP. */
12301: break;
12302: case OPC_ALNV_PS:
12303: case OPC_MADD_S:
12304: case OPC_MADD_D:
12305: case OPC_MADD_PS:
12306: case OPC_MSUB_S:
12307: case OPC_MSUB_D:
12308: case OPC_MSUB_PS:
12309: case OPC_NMADD_S:
12310: case OPC_NMADD_D:
12311: case OPC_NMADD_PS:
12312: case OPC_NMSUB_S:
12313: case OPC_NMSUB_D:
12314: case OPC_NMSUB_PS:
12315: gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12316: break;
12317: default:
12318: MIPS_INVAL("cp3");
12319: generate_exception (ctx, EXCP_RI);
12320: break;
12321: }
12322: } else {
12323: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.5 root 12324: }
1.1.1.2 root 12325: break;
12326:
1.1.1.6 root 12327: #if defined(TARGET_MIPS64)
1.1.1.5 root 12328: /* MIPS64 opcodes */
12329: case OPC_LWU:
12330: case OPC_LDL ... OPC_LDR:
12331: case OPC_LLD:
12332: case OPC_LD:
1.1.1.12 root 12333: check_insn(env, ctx, ISA_MIPS3);
12334: check_mips_64(ctx);
12335: gen_ld(env, ctx, op, rt, rs, imm);
12336: break;
12337: case OPC_SDL ... OPC_SDR:
1.1.1.5 root 12338: case OPC_SD:
1.1.1.6 root 12339: check_insn(env, ctx, ISA_MIPS3);
12340: check_mips_64(ctx);
1.1.1.12 root 12341: gen_st(ctx, op, rt, rs, imm);
1.1.1.5 root 12342: break;
1.1.1.8 root 12343: case OPC_SCD:
12344: check_insn(env, ctx, ISA_MIPS3);
12345: check_mips_64(ctx);
12346: gen_st_cond(ctx, op, rt, rs, imm);
12347: break;
12348: case OPC_DADDI:
12349: case OPC_DADDIU:
1.1.1.6 root 12350: check_insn(env, ctx, ISA_MIPS3);
12351: check_mips_64(ctx);
12352: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 12353: break;
12354: #endif
12355: case OPC_JALX:
1.1.1.12 root 12356: check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
12357: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12358: gen_compute_branch(ctx, op, 4, rs, rt, offset);
12359: *is_branch = 1;
12360: break;
1.1.1.5 root 12361: case OPC_MDMX:
1.1.1.6 root 12362: check_insn(env, ctx, ASE_MDMX);
1.1.1.5 root 12363: /* MDMX: Not implemented. */
1.1 root 12364: default: /* Invalid */
1.1.1.6 root 12365: MIPS_INVAL("major opcode");
1.1 root 12366: generate_exception(ctx, EXCP_RI);
12367: break;
12368: }
12369: }
12370:
1.1.1.7 root 12371: static inline void
1.1.1.16! root 12372: gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
1.1.1.6 root 12373: int search_pc)
1.1 root 12374: {
1.1.1.6 root 12375: DisasContext ctx;
1.1 root 12376: target_ulong pc_start;
12377: uint16_t *gen_opc_end;
1.1.1.7 root 12378: CPUBreakpoint *bp;
1.1 root 12379: int j, lj = -1;
1.1.1.7 root 12380: int num_insns;
12381: int max_insns;
1.1.1.12 root 12382: int insn_bytes;
12383: int is_branch;
1.1 root 12384:
1.1.1.7 root 12385: if (search_pc)
12386: qemu_log("search pc %d\n", search_pc);
1.1.1.2 root 12387:
1.1 root 12388: pc_start = tb->pc;
1.1.1.9 root 12389: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1.1 root 12390: ctx.pc = pc_start;
1.1.1.2 root 12391: ctx.saved_pc = -1;
1.1.1.9 root 12392: ctx.singlestep_enabled = env->singlestep_enabled;
1.1 root 12393: ctx.tb = tb;
12394: ctx.bstate = BS_NONE;
1.1.1.2 root 12395: /* Restore delay slot state from the tb context. */
1.1.1.6 root 12396: ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
12397: restore_cpu_state(env, &ctx);
1.1.1.7 root 12398: #ifdef CONFIG_USER_ONLY
12399: ctx.mem_idx = MIPS_HFLAG_UM;
1.1 root 12400: #else
1.1.1.7 root 12401: ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
1.1 root 12402: #endif
1.1.1.7 root 12403: num_insns = 0;
12404: max_insns = tb->cflags & CF_COUNT_MASK;
12405: if (max_insns == 0)
12406: max_insns = CF_COUNT_MASK;
12407: LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
12408: gen_icount_start();
12409: while (ctx.bstate == BS_NONE) {
1.1.1.9 root 12410: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12411: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1.1.7 root 12412: if (bp->pc == ctx.pc) {
1.1.1.6 root 12413: save_cpu_state(&ctx, 1);
1.1.1.2 root 12414: ctx.bstate = BS_BRANCH;
1.1.1.7 root 12415: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 12416: /* Include the breakpoint location or the tb won't
12417: * be flushed when it must be. */
12418: ctx.pc += 4;
1.1.1.2 root 12419: goto done_generating;
12420: }
12421: }
12422: }
12423:
1.1 root 12424: if (search_pc) {
12425: j = gen_opc_ptr - gen_opc_buf;
12426: if (lj < j) {
12427: lj++;
12428: while (lj < j)
12429: gen_opc_instr_start[lj++] = 0;
12430: }
1.1.1.2 root 12431: gen_opc_pc[lj] = ctx.pc;
12432: gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12433: gen_opc_instr_start[lj] = 1;
1.1.1.7 root 12434: gen_opc_icount[lj] = num_insns;
1.1 root 12435: }
1.1.1.7 root 12436: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12437: gen_io_start();
1.1.1.12 root 12438:
12439: is_branch = 0;
12440: if (!(ctx.hflags & MIPS_HFLAG_M16)) {
12441: ctx.opcode = ldl_code(ctx.pc);
12442: insn_bytes = 4;
12443: decode_opc(env, &ctx, &is_branch);
12444: } else if (env->insn_flags & ASE_MICROMIPS) {
12445: ctx.opcode = lduw_code(ctx.pc);
12446: insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
12447: } else if (env->insn_flags & ASE_MIPS16) {
12448: ctx.opcode = lduw_code(ctx.pc);
12449: insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
12450: } else {
12451: generate_exception(&ctx, EXCP_RI);
12452: ctx.bstate = BS_STOP;
12453: break;
12454: }
12455: if (!is_branch) {
12456: handle_delay_slot(env, &ctx, insn_bytes);
12457: }
12458: ctx.pc += insn_bytes;
12459:
1.1.1.7 root 12460: num_insns++;
1.1.1.2 root 12461:
1.1.1.9 root 12462: /* Execute a branch and its delay slot as a single instruction.
12463: This is what GDB expects and is consistent with what the
12464: hardware does (e.g. if a delay slot instruction faults, the
12465: reported PC is the PC of the branch). */
12466: if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
1.1.1.2 root 12467: break;
12468:
1.1 root 12469: if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12470: break;
1.1.1.2 root 12471:
1.1.1.7 root 12472: if (gen_opc_ptr >= gen_opc_end)
12473: break;
12474:
12475: if (num_insns >= max_insns)
12476: break;
1.1.1.8 root 12477:
12478: if (singlestep)
12479: break;
1.1 root 12480: }
1.1.1.7 root 12481: if (tb->cflags & CF_LAST_IO)
12482: gen_io_end();
1.1.1.9 root 12483: if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
1.1.1.6 root 12484: save_cpu_state(&ctx, ctx.bstate == BS_NONE);
1.1.1.7 root 12485: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 12486: } else {
1.1.1.7 root 12487: switch (ctx.bstate) {
1.1.1.6 root 12488: case BS_STOP:
12489: gen_goto_tb(&ctx, 0, ctx.pc);
12490: break;
12491: case BS_NONE:
12492: save_cpu_state(&ctx, 0);
12493: gen_goto_tb(&ctx, 0, ctx.pc);
12494: break;
12495: case BS_EXCP:
1.1.1.7 root 12496: tcg_gen_exit_tb(0);
1.1.1.6 root 12497: break;
12498: case BS_BRANCH:
12499: default:
12500: break;
1.1.1.7 root 12501: }
1.1 root 12502: }
1.1.1.2 root 12503: done_generating:
1.1.1.7 root 12504: gen_icount_end(tb, num_insns);
1.1 root 12505: *gen_opc_ptr = INDEX_op_end;
12506: if (search_pc) {
12507: j = gen_opc_ptr - gen_opc_buf;
12508: lj++;
12509: while (lj <= j)
12510: gen_opc_instr_start[lj++] = 0;
12511: } else {
12512: tb->size = ctx.pc - pc_start;
1.1.1.7 root 12513: tb->icount = num_insns;
1.1 root 12514: }
12515: #ifdef DEBUG_DISAS
1.1.1.7 root 12516: LOG_DISAS("\n");
12517: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
12518: qemu_log("IN: %s\n", lookup_symbol(pc_start));
12519: log_target_disas(pc_start, ctx.pc - pc_start, 0);
12520: qemu_log("\n");
1.1 root 12521: }
12522: #endif
12523: }
12524:
1.1.1.16! root 12525: void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
1.1 root 12526: {
1.1.1.7 root 12527: gen_intermediate_code_internal(env, tb, 0);
1.1 root 12528: }
12529:
1.1.1.16! root 12530: void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
1.1 root 12531: {
1.1.1.7 root 12532: gen_intermediate_code_internal(env, tb, 1);
1.1 root 12533: }
12534:
1.1.1.16! root 12535: static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
1.1.1.7 root 12536: int flags)
1.1.1.4 root 12537: {
12538: int i;
1.1.1.6 root 12539: int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
1.1.1.4 root 12540:
1.1.1.12 root 12541: #define printfpr(fp) \
12542: do { \
12543: if (is_fpu64) \
12544: fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12545: " fd:%13g fs:%13g psu: %13g\n", \
12546: (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12547: (double)(fp)->fd, \
12548: (double)(fp)->fs[FP_ENDIAN_IDX], \
12549: (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12550: else { \
12551: fpr_t tmp; \
12552: tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12553: tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12554: fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12555: " fd:%13g fs:%13g psu:%13g\n", \
12556: tmp.w[FP_ENDIAN_IDX], tmp.d, \
12557: (double)tmp.fd, \
12558: (double)tmp.fs[FP_ENDIAN_IDX], \
12559: (double)tmp.fs[!FP_ENDIAN_IDX]); \
12560: } \
1.1.1.4 root 12561: } while(0)
12562:
1.1.1.6 root 12563:
1.1.1.13 root 12564: fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
12565: env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
1.1.1.7 root 12566: get_float_exception_flags(&env->active_fpu.fp_status));
1.1.1.6 root 12567: for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12568: fpu_fprintf(f, "%3s: ", fregnames[i]);
1.1.1.7 root 12569: printfpr(&env->active_fpu.fpr[i]);
1.1.1.4 root 12570: }
12571:
12572: #undef printfpr
12573: }
12574:
1.1.1.6 root 12575: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 12576: /* Debug help: The architecture requires 32bit code to maintain proper
1.1.1.7 root 12577: sign-extended values on 64bit machines. */
1.1.1.5 root 12578:
12579: #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12580:
1.1.1.7 root 12581: static void
1.1.1.16! root 12582: cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
1.1.1.13 root 12583: fprintf_function cpu_fprintf,
1.1.1.7 root 12584: int flags)
1.1.1.5 root 12585: {
12586: int i;
12587:
1.1.1.7 root 12588: if (!SIGN_EXT_P(env->active_tc.PC))
12589: cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12590: if (!SIGN_EXT_P(env->active_tc.HI[0]))
12591: cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12592: if (!SIGN_EXT_P(env->active_tc.LO[0]))
12593: cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
1.1.1.5 root 12594: if (!SIGN_EXT_P(env->btarget))
1.1.1.6 root 12595: cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
1.1.1.5 root 12596:
12597: for (i = 0; i < 32; i++) {
1.1.1.7 root 12598: if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12599: cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
1.1.1.5 root 12600: }
12601:
12602: if (!SIGN_EXT_P(env->CP0_EPC))
1.1.1.6 root 12603: cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
1.1.1.9 root 12604: if (!SIGN_EXT_P(env->lladdr))
12605: cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
1.1.1.5 root 12606: }
12607: #endif
12608:
1.1.1.16! root 12609: void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
1.1 root 12610: int flags)
12611: {
12612: int i;
1.1.1.6 root 12613:
1.1.1.12 root 12614: cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
12615: " LO=0x" TARGET_FMT_lx " ds %04x "
12616: TARGET_FMT_lx " " TARGET_FMT_ld "\n",
1.1.1.7 root 12617: env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12618: env->hflags, env->btarget, env->bcond);
1.1 root 12619: for (i = 0; i < 32; i++) {
12620: if ((i & 3) == 0)
12621: cpu_fprintf(f, "GPR%02d:", i);
1.1.1.7 root 12622: cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
1.1 root 12623: if ((i & 3) == 3)
12624: cpu_fprintf(f, "\n");
12625: }
12626:
1.1.1.6 root 12627: cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
12628: env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
12629: cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
1.1.1.9 root 12630: env->CP0_Config0, env->CP0_Config1, env->lladdr);
1.1.1.6 root 12631: if (env->hflags & MIPS_HFLAG_FPU)
1.1.1.5 root 12632: fpu_dump_state(env, f, cpu_fprintf, flags);
1.1.1.6 root 12633: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 12634: cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
1.1.1.4 root 12635: #endif
1.1 root 12636: }
12637:
1.1.1.7 root 12638: static void mips_tcg_init(void)
12639: {
12640: int i;
12641: static int inited;
12642:
12643: /* Initialize various static tables. */
12644: if (inited)
12645: return;
12646:
12647: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1.1.1.8 root 12648: TCGV_UNUSED(cpu_gpr[0]);
12649: for (i = 1; i < 32; i++)
1.1.1.7 root 12650: cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
1.1.1.16! root 12651: offsetof(CPUMIPSState, active_tc.gpr[i]),
1.1.1.7 root 12652: regnames[i]);
12653: cpu_PC = tcg_global_mem_new(TCG_AREG0,
1.1.1.16! root 12654: offsetof(CPUMIPSState, active_tc.PC), "PC");
1.1.1.7 root 12655: for (i = 0; i < MIPS_DSP_ACC; i++) {
12656: cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
1.1.1.16! root 12657: offsetof(CPUMIPSState, active_tc.HI[i]),
1.1.1.7 root 12658: regnames_HI[i]);
12659: cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
1.1.1.16! root 12660: offsetof(CPUMIPSState, active_tc.LO[i]),
1.1.1.7 root 12661: regnames_LO[i]);
12662: cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
1.1.1.16! root 12663: offsetof(CPUMIPSState, active_tc.ACX[i]),
1.1.1.7 root 12664: regnames_ACX[i]);
12665: }
12666: cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
1.1.1.16! root 12667: offsetof(CPUMIPSState, active_tc.DSPControl),
1.1.1.7 root 12668: "DSPControl");
1.1.1.8 root 12669: bcond = tcg_global_mem_new(TCG_AREG0,
1.1.1.16! root 12670: offsetof(CPUMIPSState, bcond), "bcond");
1.1.1.7 root 12671: btarget = tcg_global_mem_new(TCG_AREG0,
1.1.1.16! root 12672: offsetof(CPUMIPSState, btarget), "btarget");
1.1.1.8 root 12673: hflags = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.16! root 12674: offsetof(CPUMIPSState, hflags), "hflags");
1.1.1.8 root 12675:
1.1.1.7 root 12676: fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.16! root 12677: offsetof(CPUMIPSState, active_fpu.fcr0),
1.1.1.7 root 12678: "fcr0");
12679: fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.16! root 12680: offsetof(CPUMIPSState, active_fpu.fcr31),
1.1.1.7 root 12681: "fcr31");
12682:
12683: /* register helpers */
12684: #define GEN_HELPER 2
12685: #include "helper.h"
12686:
12687: inited = 1;
12688: }
12689:
1.1.1.6 root 12690: #include "translate_init.c"
12691:
12692: CPUMIPSState *cpu_mips_init (const char *cpu_model)
1.1 root 12693: {
1.1.1.16! root 12694: MIPSCPU *cpu;
1.1 root 12695: CPUMIPSState *env;
1.1.1.6 root 12696: const mips_def_t *def;
1.1 root 12697:
1.1.1.6 root 12698: def = cpu_mips_find_by_name(cpu_model);
12699: if (!def)
12700: return NULL;
1.1.1.16! root 12701: cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
! 12702: env = &cpu->env;
1.1.1.6 root 12703: env->cpu_model = def;
1.1.1.9 root 12704: env->cpu_model_str = cpu_model;
1.1.1.6 root 12705:
1.1.1.9 root 12706: #ifndef CONFIG_USER_ONLY
12707: mmu_init(env, def);
12708: #endif
12709: fpu_init(env, def);
12710: mvp_init(env, def);
1.1.1.7 root 12711: mips_tcg_init();
1.1.1.16! root 12712: cpu_state_reset(env);
1.1.1.8 root 12713: qemu_init_vcpu(env);
1.1.1.5 root 12714: return env;
12715: }
12716:
1.1.1.16! root 12717: void cpu_state_reset(CPUMIPSState *env)
1.1.1.5 root 12718: {
1.1.1.7 root 12719: if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12720: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12721: log_cpu_state(env, 0);
12722: }
12723:
1.1.1.5 root 12724: memset(env, 0, offsetof(CPUMIPSState, breakpoints));
1.1 root 12725: tlb_flush(env, 1);
1.1.1.5 root 12726:
1.1.1.9 root 12727: /* Reset registers to their default values */
12728: env->CP0_PRid = env->cpu_model->CP0_PRid;
12729: env->CP0_Config0 = env->cpu_model->CP0_Config0;
12730: #ifdef TARGET_WORDS_BIGENDIAN
12731: env->CP0_Config0 |= (1 << CP0C0_BE);
12732: #endif
12733: env->CP0_Config1 = env->cpu_model->CP0_Config1;
12734: env->CP0_Config2 = env->cpu_model->CP0_Config2;
12735: env->CP0_Config3 = env->cpu_model->CP0_Config3;
12736: env->CP0_Config6 = env->cpu_model->CP0_Config6;
12737: env->CP0_Config7 = env->cpu_model->CP0_Config7;
12738: env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12739: << env->cpu_model->CP0_LLAddr_shift;
12740: env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
12741: env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12742: env->CCRes = env->cpu_model->CCRes;
12743: env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12744: env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12745: env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12746: env->current_tc = 0;
12747: env->SEGBITS = env->cpu_model->SEGBITS;
12748: env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12749: #if defined(TARGET_MIPS64)
12750: if (env->cpu_model->insn_flags & ISA_MIPS3) {
12751: env->SEGMask |= 3ULL << 62;
12752: }
12753: #endif
12754: env->PABITS = env->cpu_model->PABITS;
12755: env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12756: env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12757: env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12758: env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12759: env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12760: env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12761: env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12762: env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12763: env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12764: env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12765: env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
12766: env->insn_flags = env->cpu_model->insn_flags;
12767:
1.1.1.7 root 12768: #if defined(CONFIG_USER_ONLY)
12769: env->hflags = MIPS_HFLAG_UM;
1.1.1.8 root 12770: /* Enable access to the SYNCI_Step register. */
12771: env->CP0_HWREna |= (1 << 1);
1.1.1.9 root 12772: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12773: env->hflags |= MIPS_HFLAG_FPU;
12774: }
12775: #ifdef TARGET_MIPS64
12776: if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
12777: env->hflags |= MIPS_HFLAG_F64;
12778: }
12779: #endif
1.1.1.7 root 12780: #else
1.1.1.5 root 12781: if (env->hflags & MIPS_HFLAG_BMASK) {
12782: /* If the exception was raised from a delay slot,
1.1.1.7 root 12783: come back to the jump. */
12784: env->CP0_ErrorEPC = env->active_tc.PC - 4;
1.1.1.5 root 12785: } else {
1.1.1.7 root 12786: env->CP0_ErrorEPC = env->active_tc.PC;
1.1.1.5 root 12787: }
1.1.1.7 root 12788: env->active_tc.PC = (int32_t)0xBFC00000;
1.1.1.9 root 12789: env->CP0_Random = env->tlb->nb_tlb - 1;
12790: env->tlb->tlb_in_use = env->tlb->nb_tlb;
1.1 root 12791: env->CP0_Wired = 0;
1.1.1.13 root 12792: env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
1.1.1.5 root 12793: env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
1.1.1.6 root 12794: /* vectored interrupts not implemented, timer on int 7,
12795: no performance counters. */
12796: env->CP0_IntCtl = 0xe0000000;
12797: {
12798: int i;
12799:
12800: for (i = 0; i < 7; i++) {
12801: env->CP0_WatchLo[i] = 0;
12802: env->CP0_WatchHi[i] = 0x80000000;
12803: }
12804: env->CP0_WatchLo[7] = 0;
12805: env->CP0_WatchHi[7] = 0;
12806: }
1.1 root 12807: /* Count register increments in debug mode, EJTAG version 1 */
12808: env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
1.1.1.6 root 12809: env->hflags = MIPS_HFLAG_CP0;
1.1.1.15 root 12810:
12811: if (env->CP0_Config3 & (1 << CP0C3_MT)) {
12812: int i;
12813:
12814: /* Only TC0 on VPE 0 starts as active. */
12815: for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
12816: env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
12817: env->tcs[i].CP0_TCHalt = 1;
12818: }
12819: env->active_tc.CP0_TCHalt = 1;
12820: env->halted = 1;
12821:
12822: if (!env->cpu_index) {
12823: /* VPE0 starts up enabled. */
12824: env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
12825: env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
12826:
12827: /* TC0 starts up unhalted. */
12828: env->halted = 0;
12829: env->active_tc.CP0_TCHalt = 0;
12830: env->tcs[0].CP0_TCHalt = 0;
12831: /* With thread 0 active. */
12832: env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
12833: env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
12834: }
12835: }
1.1.1.2 root 12836: #endif
1.1.1.9 root 12837: #if defined(TARGET_MIPS64)
12838: if (env->cpu_model->insn_flags & ISA_MIPS3) {
12839: env->hflags |= MIPS_HFLAG_64;
12840: }
12841: #endif
1.1.1.7 root 12842: env->exception_index = EXCP_NONE;
1.1 root 12843: }
1.1.1.7 root 12844:
1.1.1.16! root 12845: void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
1.1.1.7 root 12846: {
12847: env->active_tc.PC = gen_opc_pc[pc_pos];
12848: env->hflags &= ~MIPS_HFLAG_BMASK;
12849: env->hflags |= gen_opc_hflags[pc_pos];
12850: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.