|
|
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 <stdarg.h>
24: #include <stdlib.h>
25: #include <stdio.h>
26: #include <string.h>
27: #include <inttypes.h>
28:
29: #include "cpu.h"
30: #include "disas.h"
1.1.1.7 root 31: #include "tcg-op.h"
32: #include "qemu-common.h"
33:
34: #include "helper.h"
35: #define GEN_HELPER 1
36: #include "helper.h"
1.1 root 37:
1.1.1.2 root 38: //#define MIPS_DEBUG_DISAS
1.1.1.5 root 39: //#define MIPS_DEBUG_SIGN_EXTENSIONS
1.1 root 40:
1.1.1.5 root 41: /* MIPS major opcodes */
42: #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
1.1 root 43:
44: enum {
45: /* indirect opcode tables */
1.1.1.5 root 46: OPC_SPECIAL = (0x00 << 26),
47: OPC_REGIMM = (0x01 << 26),
48: OPC_CP0 = (0x10 << 26),
49: OPC_CP1 = (0x11 << 26),
50: OPC_CP2 = (0x12 << 26),
51: OPC_CP3 = (0x13 << 26),
52: OPC_SPECIAL2 = (0x1C << 26),
53: OPC_SPECIAL3 = (0x1F << 26),
1.1 root 54: /* arithmetic with immediate */
1.1.1.5 root 55: OPC_ADDI = (0x08 << 26),
56: OPC_ADDIU = (0x09 << 26),
57: OPC_SLTI = (0x0A << 26),
58: OPC_SLTIU = (0x0B << 26),
1.1.1.8 root 59: /* logic with immediate */
1.1.1.5 root 60: OPC_ANDI = (0x0C << 26),
61: OPC_ORI = (0x0D << 26),
62: OPC_XORI = (0x0E << 26),
63: OPC_LUI = (0x0F << 26),
1.1.1.8 root 64: /* arithmetic with immediate */
1.1.1.5 root 65: OPC_DADDI = (0x18 << 26),
66: OPC_DADDIU = (0x19 << 26),
1.1 root 67: /* Jump and branches */
1.1.1.5 root 68: OPC_J = (0x02 << 26),
69: OPC_JAL = (0x03 << 26),
1.1.1.12 root 70: OPC_JALS = OPC_JAL | 0x5,
1.1.1.5 root 71: OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
72: OPC_BEQL = (0x14 << 26),
73: OPC_BNE = (0x05 << 26),
74: OPC_BNEL = (0x15 << 26),
75: OPC_BLEZ = (0x06 << 26),
76: OPC_BLEZL = (0x16 << 26),
77: OPC_BGTZ = (0x07 << 26),
78: OPC_BGTZL = (0x17 << 26),
79: OPC_JALX = (0x1D << 26), /* MIPS 16 only */
1.1.1.12 root 80: OPC_JALXS = OPC_JALX | 0x5,
1.1 root 81: /* Load and stores */
1.1.1.5 root 82: OPC_LDL = (0x1A << 26),
83: OPC_LDR = (0x1B << 26),
84: OPC_LB = (0x20 << 26),
85: OPC_LH = (0x21 << 26),
86: OPC_LWL = (0x22 << 26),
87: OPC_LW = (0x23 << 26),
1.1.1.12 root 88: OPC_LWPC = OPC_LW | 0x5,
1.1.1.5 root 89: OPC_LBU = (0x24 << 26),
90: OPC_LHU = (0x25 << 26),
91: OPC_LWR = (0x26 << 26),
92: OPC_LWU = (0x27 << 26),
93: OPC_SB = (0x28 << 26),
94: OPC_SH = (0x29 << 26),
95: OPC_SWL = (0x2A << 26),
96: OPC_SW = (0x2B << 26),
97: OPC_SDL = (0x2C << 26),
98: OPC_SDR = (0x2D << 26),
99: OPC_SWR = (0x2E << 26),
100: OPC_LL = (0x30 << 26),
101: OPC_LLD = (0x34 << 26),
102: OPC_LD = (0x37 << 26),
1.1.1.12 root 103: OPC_LDPC = OPC_LD | 0x5,
1.1.1.5 root 104: OPC_SC = (0x38 << 26),
105: OPC_SCD = (0x3C << 26),
106: OPC_SD = (0x3F << 26),
1.1 root 107: /* Floating point load/store */
1.1.1.5 root 108: OPC_LWC1 = (0x31 << 26),
109: OPC_LWC2 = (0x32 << 26),
110: OPC_LDC1 = (0x35 << 26),
111: OPC_LDC2 = (0x36 << 26),
112: OPC_SWC1 = (0x39 << 26),
113: OPC_SWC2 = (0x3A << 26),
114: OPC_SDC1 = (0x3D << 26),
115: OPC_SDC2 = (0x3E << 26),
116: /* MDMX ASE specific */
117: OPC_MDMX = (0x1E << 26),
1.1 root 118: /* Cache and prefetch */
1.1.1.5 root 119: OPC_CACHE = (0x2F << 26),
120: OPC_PREF = (0x33 << 26),
121: /* Reserved major opcode */
122: OPC_MAJOR3B_RESERVED = (0x3B << 26),
1.1 root 123: };
124:
125: /* MIPS special opcodes */
1.1.1.5 root 126: #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
127:
1.1 root 128: enum {
129: /* Shifts */
1.1.1.5 root 130: OPC_SLL = 0x00 | OPC_SPECIAL,
1.1 root 131: /* NOP is SLL r0, r0, 0 */
132: /* SSNOP is SLL r0, r0, 1 */
1.1.1.5 root 133: /* EHB is SLL r0, r0, 3 */
134: OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
1.1.1.12 root 135: OPC_ROTR = OPC_SRL | (1 << 21),
1.1.1.5 root 136: OPC_SRA = 0x03 | OPC_SPECIAL,
137: OPC_SLLV = 0x04 | OPC_SPECIAL,
1.1.1.6 root 138: OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
1.1.1.12 root 139: OPC_ROTRV = OPC_SRLV | (1 << 6),
1.1.1.5 root 140: OPC_SRAV = 0x07 | OPC_SPECIAL,
141: OPC_DSLLV = 0x14 | OPC_SPECIAL,
142: OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
1.1.1.12 root 143: OPC_DROTRV = OPC_DSRLV | (1 << 6),
1.1.1.5 root 144: OPC_DSRAV = 0x17 | OPC_SPECIAL,
145: OPC_DSLL = 0x38 | OPC_SPECIAL,
146: OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
1.1.1.12 root 147: OPC_DROTR = OPC_DSRL | (1 << 21),
1.1.1.5 root 148: OPC_DSRA = 0x3B | OPC_SPECIAL,
149: OPC_DSLL32 = 0x3C | OPC_SPECIAL,
150: OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
1.1.1.12 root 151: OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
1.1.1.5 root 152: OPC_DSRA32 = 0x3F | OPC_SPECIAL,
1.1 root 153: /* Multiplication / division */
1.1.1.5 root 154: OPC_MULT = 0x18 | OPC_SPECIAL,
155: OPC_MULTU = 0x19 | OPC_SPECIAL,
156: OPC_DIV = 0x1A | OPC_SPECIAL,
157: OPC_DIVU = 0x1B | OPC_SPECIAL,
158: OPC_DMULT = 0x1C | OPC_SPECIAL,
159: OPC_DMULTU = 0x1D | OPC_SPECIAL,
160: OPC_DDIV = 0x1E | OPC_SPECIAL,
161: OPC_DDIVU = 0x1F | OPC_SPECIAL,
1.1 root 162: /* 2 registers arithmetic / logic */
1.1.1.5 root 163: OPC_ADD = 0x20 | OPC_SPECIAL,
164: OPC_ADDU = 0x21 | OPC_SPECIAL,
165: OPC_SUB = 0x22 | OPC_SPECIAL,
166: OPC_SUBU = 0x23 | OPC_SPECIAL,
167: OPC_AND = 0x24 | OPC_SPECIAL,
168: OPC_OR = 0x25 | OPC_SPECIAL,
169: OPC_XOR = 0x26 | OPC_SPECIAL,
170: OPC_NOR = 0x27 | OPC_SPECIAL,
171: OPC_SLT = 0x2A | OPC_SPECIAL,
172: OPC_SLTU = 0x2B | OPC_SPECIAL,
173: OPC_DADD = 0x2C | OPC_SPECIAL,
174: OPC_DADDU = 0x2D | OPC_SPECIAL,
175: OPC_DSUB = 0x2E | OPC_SPECIAL,
176: OPC_DSUBU = 0x2F | OPC_SPECIAL,
1.1 root 177: /* Jumps */
1.1.1.5 root 178: OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
179: OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
1.1.1.12 root 180: OPC_JALRC = OPC_JALR | (0x5 << 6),
181: OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
1.1 root 182: /* Traps */
1.1.1.5 root 183: OPC_TGE = 0x30 | OPC_SPECIAL,
184: OPC_TGEU = 0x31 | OPC_SPECIAL,
185: OPC_TLT = 0x32 | OPC_SPECIAL,
186: OPC_TLTU = 0x33 | OPC_SPECIAL,
187: OPC_TEQ = 0x34 | OPC_SPECIAL,
188: OPC_TNE = 0x36 | OPC_SPECIAL,
1.1 root 189: /* HI / LO registers load & stores */
1.1.1.5 root 190: OPC_MFHI = 0x10 | OPC_SPECIAL,
191: OPC_MTHI = 0x11 | OPC_SPECIAL,
192: OPC_MFLO = 0x12 | OPC_SPECIAL,
193: OPC_MTLO = 0x13 | OPC_SPECIAL,
1.1 root 194: /* Conditional moves */
1.1.1.5 root 195: OPC_MOVZ = 0x0A | OPC_SPECIAL,
196: OPC_MOVN = 0x0B | OPC_SPECIAL,
1.1 root 197:
1.1.1.5 root 198: OPC_MOVCI = 0x01 | OPC_SPECIAL,
1.1 root 199:
200: /* Special */
1.1.1.9 root 201: OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
1.1.1.5 root 202: OPC_SYSCALL = 0x0C | OPC_SPECIAL,
203: OPC_BREAK = 0x0D | OPC_SPECIAL,
1.1.1.9 root 204: OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
1.1.1.5 root 205: OPC_SYNC = 0x0F | OPC_SPECIAL,
206:
207: OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
208: OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
209: OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
210: OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
211: OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
212: OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
213: OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
214: };
215:
1.1.1.6 root 216: /* Multiplication variants of the vr54xx. */
217: #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
218:
219: enum {
220: OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
221: OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
222: OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
223: OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
224: OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
225: OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
226: OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
227: OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
228: OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
229: OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
230: OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
231: OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
232: OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
233: OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
234: };
235:
1.1.1.5 root 236: /* REGIMM (rt field) opcodes */
237: #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
238:
239: enum {
240: OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
241: OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
242: OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
243: OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
244: OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
1.1.1.12 root 245: OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
1.1.1.5 root 246: OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
247: OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
1.1.1.12 root 248: OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
1.1.1.5 root 249: OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
250: OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
251: OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
252: OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
253: OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
254: OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
255: OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
256: OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
1.1 root 257: };
258:
1.1.1.5 root 259: /* Special2 opcodes */
260: #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
261:
1.1 root 262: enum {
1.1.1.5 root 263: /* Multiply & xxx operations */
264: OPC_MADD = 0x00 | OPC_SPECIAL2,
265: OPC_MADDU = 0x01 | OPC_SPECIAL2,
266: OPC_MUL = 0x02 | OPC_SPECIAL2,
267: OPC_MSUB = 0x04 | OPC_SPECIAL2,
268: OPC_MSUBU = 0x05 | OPC_SPECIAL2,
1.1.1.12 root 269: /* Loongson 2F */
270: OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
271: OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
272: OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
273: OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
274: OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
275: OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
276: OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
277: OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
278: OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
279: OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
280: OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
281: OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
1.1 root 282: /* Misc */
1.1.1.5 root 283: OPC_CLZ = 0x20 | OPC_SPECIAL2,
284: OPC_CLO = 0x21 | OPC_SPECIAL2,
285: OPC_DCLZ = 0x24 | OPC_SPECIAL2,
286: OPC_DCLO = 0x25 | OPC_SPECIAL2,
1.1 root 287: /* Special */
1.1.1.5 root 288: OPC_SDBBP = 0x3F | OPC_SPECIAL2,
289: };
290:
291: /* Special3 opcodes */
292: #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
293:
294: enum {
295: OPC_EXT = 0x00 | OPC_SPECIAL3,
296: OPC_DEXTM = 0x01 | OPC_SPECIAL3,
297: OPC_DEXTU = 0x02 | OPC_SPECIAL3,
298: OPC_DEXT = 0x03 | OPC_SPECIAL3,
299: OPC_INS = 0x04 | OPC_SPECIAL3,
300: OPC_DINSM = 0x05 | OPC_SPECIAL3,
301: OPC_DINSU = 0x06 | OPC_SPECIAL3,
302: OPC_DINS = 0x07 | OPC_SPECIAL3,
1.1.1.6 root 303: OPC_FORK = 0x08 | OPC_SPECIAL3,
304: OPC_YIELD = 0x09 | OPC_SPECIAL3,
1.1.1.5 root 305: OPC_BSHFL = 0x20 | OPC_SPECIAL3,
306: OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
307: OPC_RDHWR = 0x3B | OPC_SPECIAL3,
1.1.1.12 root 308:
309: /* Loongson 2E */
310: OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
311: OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
312: OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
313: OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
314: OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
315: OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
316: OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
317: OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
318: OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
319: OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
320: OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
321: OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
1.1 root 322: };
323:
1.1.1.5 root 324: /* BSHFL opcodes */
325: #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
326:
1.1 root 327: enum {
1.1.1.5 root 328: OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
329: OPC_SEB = (0x10 << 6) | OPC_BSHFL,
330: OPC_SEH = (0x18 << 6) | OPC_BSHFL,
1.1 root 331: };
332:
1.1.1.5 root 333: /* DBSHFL opcodes */
334: #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
335:
1.1 root 336: enum {
1.1.1.5 root 337: OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
338: OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
1.1 root 339: };
340:
1.1.1.5 root 341: /* Coprocessor 0 (rs field) */
342: #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
343:
1.1.1.4 root 344: enum {
1.1.1.5 root 345: OPC_MFC0 = (0x00 << 21) | OPC_CP0,
346: OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
347: OPC_MTC0 = (0x04 << 21) | OPC_CP0,
348: OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
1.1.1.6 root 349: OPC_MFTR = (0x08 << 21) | OPC_CP0,
1.1.1.5 root 350: OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
351: OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
1.1.1.6 root 352: OPC_MTTR = (0x0C << 21) | OPC_CP0,
1.1.1.5 root 353: OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
354: OPC_C0 = (0x10 << 21) | OPC_CP0,
355: OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
356: OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
1.1.1.4 root 357: };
1.1.1.5 root 358:
359: /* MFMC0 opcodes */
1.1.1.6 root 360: #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
1.1.1.5 root 361:
362: enum {
1.1.1.6 root 363: OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
364: OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
365: OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
366: OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
1.1.1.5 root 367: OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
368: OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
369: };
370:
371: /* Coprocessor 0 (with rs == C0) */
372: #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
373:
374: enum {
375: OPC_TLBR = 0x01 | OPC_C0,
376: OPC_TLBWI = 0x02 | OPC_C0,
377: OPC_TLBWR = 0x06 | OPC_C0,
378: OPC_TLBP = 0x08 | OPC_C0,
379: OPC_RFE = 0x10 | OPC_C0,
380: OPC_ERET = 0x18 | OPC_C0,
381: OPC_DERET = 0x1F | OPC_C0,
382: OPC_WAIT = 0x20 | OPC_C0,
383: };
384:
385: /* Coprocessor 1 (rs field) */
386: #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
387:
1.1.1.12 root 388: /* Values for the fmt field in FP instructions */
389: enum {
390: /* 0 - 15 are reserved */
391: FMT_S = 16, /* single fp */
392: FMT_D = 17, /* double fp */
393: FMT_E = 18, /* extended fp */
394: FMT_Q = 19, /* quad fp */
395: FMT_W = 20, /* 32-bit fixed */
396: FMT_L = 21, /* 64-bit fixed */
397: FMT_PS = 22, /* paired single fp */
398: /* 23 - 31 are reserved */
399: };
400:
1.1.1.5 root 401: enum {
402: OPC_MFC1 = (0x00 << 21) | OPC_CP1,
403: OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
404: OPC_CFC1 = (0x02 << 21) | OPC_CP1,
1.1.1.6 root 405: OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
1.1.1.5 root 406: OPC_MTC1 = (0x04 << 21) | OPC_CP1,
407: OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
408: OPC_CTC1 = (0x06 << 21) | OPC_CP1,
1.1.1.6 root 409: OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
1.1.1.5 root 410: OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
1.1.1.6 root 411: OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
412: OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
1.1.1.12 root 413: OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
414: OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
415: OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
416: OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
417: OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
418: OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
419: OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
1.1.1.5 root 420: };
421:
1.1.1.6 root 422: #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
423: #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
424:
1.1.1.5 root 425: enum {
426: OPC_BC1F = (0x00 << 16) | OPC_BC1,
427: OPC_BC1T = (0x01 << 16) | OPC_BC1,
428: OPC_BC1FL = (0x02 << 16) | OPC_BC1,
429: OPC_BC1TL = (0x03 << 16) | OPC_BC1,
430: };
431:
1.1.1.6 root 432: enum {
433: OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
434: OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
435: };
436:
437: enum {
438: OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
439: OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
440: };
1.1.1.5 root 441:
442: #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1.1.1.6 root 443:
444: enum {
445: OPC_MFC2 = (0x00 << 21) | OPC_CP2,
446: OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
447: OPC_CFC2 = (0x02 << 21) | OPC_CP2,
448: OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
449: OPC_MTC2 = (0x04 << 21) | OPC_CP2,
450: OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
451: OPC_CTC2 = (0x06 << 21) | OPC_CP2,
452: OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
453: OPC_BC2 = (0x08 << 21) | OPC_CP2,
454: };
455:
456: #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
457:
458: enum {
459: OPC_LWXC1 = 0x00 | OPC_CP3,
460: OPC_LDXC1 = 0x01 | OPC_CP3,
461: OPC_LUXC1 = 0x05 | OPC_CP3,
462: OPC_SWXC1 = 0x08 | OPC_CP3,
463: OPC_SDXC1 = 0x09 | OPC_CP3,
464: OPC_SUXC1 = 0x0D | OPC_CP3,
465: OPC_PREFX = 0x0F | OPC_CP3,
466: OPC_ALNV_PS = 0x1E | OPC_CP3,
467: OPC_MADD_S = 0x20 | OPC_CP3,
468: OPC_MADD_D = 0x21 | OPC_CP3,
469: OPC_MADD_PS = 0x26 | OPC_CP3,
470: OPC_MSUB_S = 0x28 | OPC_CP3,
471: OPC_MSUB_D = 0x29 | OPC_CP3,
472: OPC_MSUB_PS = 0x2E | OPC_CP3,
473: OPC_NMADD_S = 0x30 | OPC_CP3,
474: OPC_NMADD_D = 0x31 | OPC_CP3,
475: OPC_NMADD_PS= 0x36 | OPC_CP3,
476: OPC_NMSUB_S = 0x38 | OPC_CP3,
477: OPC_NMSUB_D = 0x39 | OPC_CP3,
478: OPC_NMSUB_PS= 0x3E | OPC_CP3,
479: };
480:
1.1.1.7 root 481: /* global register indices */
482: static TCGv_ptr cpu_env;
483: static TCGv cpu_gpr[32], cpu_PC;
484: static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
1.1.1.8 root 485: static TCGv cpu_dspctrl, btarget, bcond;
486: static TCGv_i32 hflags;
1.1.1.7 root 487: static TCGv_i32 fpu_fcr0, fpu_fcr31;
488:
1.1.1.12 root 489: static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
490:
1.1.1.7 root 491: #include "gen-icount.h"
492:
493: #define gen_helper_0i(name, arg) do { \
494: TCGv_i32 helper_tmp = tcg_const_i32(arg); \
495: gen_helper_##name(helper_tmp); \
496: tcg_temp_free_i32(helper_tmp); \
497: } while(0)
1.1.1.4 root 498:
1.1.1.7 root 499: #define gen_helper_1i(name, arg1, arg2) do { \
500: TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
501: gen_helper_##name(arg1, helper_tmp); \
502: tcg_temp_free_i32(helper_tmp); \
503: } while(0)
1.1.1.4 root 504:
1.1.1.7 root 505: #define gen_helper_2i(name, arg1, arg2, arg3) do { \
506: TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
507: gen_helper_##name(arg1, arg2, helper_tmp); \
508: tcg_temp_free_i32(helper_tmp); \
509: } while(0)
1.1.1.4 root 510:
1.1.1.7 root 511: #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
512: TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
513: gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
514: tcg_temp_free_i32(helper_tmp); \
515: } while(0)
1.1.1.4 root 516:
1.1 root 517: typedef struct DisasContext {
518: struct TranslationBlock *tb;
519: target_ulong pc, saved_pc;
520: uint32_t opcode;
1.1.1.9 root 521: int singlestep_enabled;
1.1 root 522: /* Routine used to access memory */
523: int mem_idx;
524: uint32_t hflags, saved_hflags;
525: int bstate;
526: target_ulong btarget;
527: } DisasContext;
528:
529: enum {
530: BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1.1.1.7 root 531: * exception condition */
1.1 root 532: BS_STOP = 1, /* We want to stop translation for any reason */
533: BS_BRANCH = 2, /* We reached a branch condition */
534: BS_EXCP = 3, /* We reached an exception condition */
535: };
536:
1.1.1.7 root 537: static const char *regnames[] =
538: { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
539: "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
540: "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
541: "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
542:
543: static const char *regnames_HI[] =
544: { "HI0", "HI1", "HI2", "HI3", };
545:
546: static const char *regnames_LO[] =
547: { "LO0", "LO1", "LO2", "LO3", };
548:
549: static const char *regnames_ACX[] =
550: { "ACX0", "ACX1", "ACX2", "ACX3", };
551:
552: static const char *fregnames[] =
553: { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
554: "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
555: "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
556: "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
557:
1.1.1.6 root 558: #ifdef MIPS_DEBUG_DISAS
1.1.1.8 root 559: #define MIPS_DEBUG(fmt, ...) \
1.1.1.7 root 560: qemu_log_mask(CPU_LOG_TB_IN_ASM, \
561: TARGET_FMT_lx ": %08x " fmt "\n", \
1.1.1.8 root 562: ctx->pc, ctx->opcode , ## __VA_ARGS__)
1.1.1.7 root 563: #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
1.1 root 564: #else
1.1.1.8 root 565: #define MIPS_DEBUG(fmt, ...) do { } while(0)
1.1.1.7 root 566: #define LOG_DISAS(...) do { } while (0)
1.1 root 567: #endif
568:
569: #define MIPS_INVAL(op) \
570: do { \
571: MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
572: ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
573: } while (0)
574:
1.1.1.7 root 575: /* General purpose registers moves. */
576: static inline void gen_load_gpr (TCGv t, int reg)
577: {
578: if (reg == 0)
579: tcg_gen_movi_tl(t, 0);
580: else
581: tcg_gen_mov_tl(t, cpu_gpr[reg]);
582: }
1.1.1.6 root 583:
1.1.1.7 root 584: static inline void gen_store_gpr (TCGv t, int reg)
585: {
586: if (reg != 0)
587: tcg_gen_mov_tl(cpu_gpr[reg], t);
588: }
1.1.1.6 root 589:
1.1.1.7 root 590: /* Moves to/from ACX register. */
591: static inline void gen_load_ACX (TCGv t, int reg)
592: {
593: tcg_gen_mov_tl(t, cpu_ACX[reg]);
594: }
1.1.1.6 root 595:
1.1.1.7 root 596: static inline void gen_store_ACX (TCGv t, int reg)
597: {
598: tcg_gen_mov_tl(cpu_ACX[reg], t);
599: }
1.1 root 600:
1.1.1.7 root 601: /* Moves to/from shadow registers. */
602: static inline void gen_load_srsgpr (int from, int to)
603: {
1.1.1.8 root 604: TCGv t0 = tcg_temp_new();
1.1.1.6 root 605:
1.1.1.7 root 606: if (from == 0)
1.1.1.8 root 607: tcg_gen_movi_tl(t0, 0);
1.1.1.7 root 608: else {
1.1.1.8 root 609: TCGv_i32 t2 = tcg_temp_new_i32();
1.1.1.7 root 610: TCGv_ptr addr = tcg_temp_new_ptr();
1.1.1.6 root 611:
1.1.1.8 root 612: tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
613: tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
614: tcg_gen_andi_i32(t2, t2, 0xf);
615: tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
616: tcg_gen_ext_i32_ptr(addr, t2);
1.1.1.7 root 617: tcg_gen_add_ptr(addr, cpu_env, addr);
1.1 root 618:
1.1.1.8 root 619: tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1.1.1.7 root 620: tcg_temp_free_ptr(addr);
1.1.1.8 root 621: tcg_temp_free_i32(t2);
1.1.1.7 root 622: }
1.1.1.8 root 623: gen_store_gpr(t0, to);
624: tcg_temp_free(t0);
1.1.1.7 root 625: }
1.1 root 626:
1.1.1.7 root 627: static inline void gen_store_srsgpr (int from, int to)
628: {
629: if (to != 0) {
1.1.1.8 root 630: TCGv t0 = tcg_temp_new();
631: TCGv_i32 t2 = tcg_temp_new_i32();
1.1.1.7 root 632: TCGv_ptr addr = tcg_temp_new_ptr();
1.1.1.4 root 633:
1.1.1.8 root 634: gen_load_gpr(t0, from);
635: tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
636: tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
637: tcg_gen_andi_i32(t2, t2, 0xf);
638: tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
639: tcg_gen_ext_i32_ptr(addr, t2);
1.1.1.7 root 640: tcg_gen_add_ptr(addr, cpu_env, addr);
1.1.1.4 root 641:
1.1.1.8 root 642: tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1.1.1.7 root 643: tcg_temp_free_ptr(addr);
1.1.1.8 root 644: tcg_temp_free_i32(t2);
645: tcg_temp_free(t0);
1.1.1.6 root 646: }
647: }
648:
1.1.1.7 root 649: /* Floating point register moves. */
650: static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
1.1.1.6 root 651: {
1.1.1.8 root 652: tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
1.1.1.7 root 653: }
654:
655: static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
656: {
1.1.1.8 root 657: tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
1.1.1.7 root 658: }
659:
1.1.1.8 root 660: static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
1.1.1.7 root 661: {
1.1.1.8 root 662: tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
1.1.1.6 root 663: }
664:
1.1.1.8 root 665: static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
1.1 root 666: {
1.1.1.8 root 667: tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
1.1.1.7 root 668: }
669:
1.1.1.8 root 670: static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
1.1.1.7 root 671: {
1.1.1.8 root 672: if (ctx->hflags & MIPS_HFLAG_F64) {
673: tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
674: } else {
675: TCGv_i32 t0 = tcg_temp_new_i32();
676: TCGv_i32 t1 = tcg_temp_new_i32();
677: gen_load_fpr32(t0, reg & ~1);
678: gen_load_fpr32(t1, reg | 1);
679: tcg_gen_concat_i32_i64(t, t0, t1);
680: tcg_temp_free_i32(t0);
681: tcg_temp_free_i32(t1);
682: }
1.1.1.7 root 683: }
684:
1.1.1.8 root 685: static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
1.1.1.7 root 686: {
1.1.1.8 root 687: if (ctx->hflags & MIPS_HFLAG_F64) {
688: tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
689: } else {
690: TCGv_i64 t0 = tcg_temp_new_i64();
691: TCGv_i32 t1 = tcg_temp_new_i32();
692: tcg_gen_trunc_i64_i32(t1, t);
693: gen_store_fpr32(t1, reg & ~1);
694: tcg_gen_shri_i64(t0, t, 32);
695: tcg_gen_trunc_i64_i32(t1, t0);
696: gen_store_fpr32(t1, reg | 1);
697: tcg_temp_free_i32(t1);
698: tcg_temp_free_i64(t0);
699: }
1.1.1.7 root 700: }
701:
1.1.1.8 root 702: static inline int get_fp_bit (int cc)
1.1.1.7 root 703: {
1.1.1.8 root 704: if (cc)
705: return 24 + cc;
706: else
707: return 23;
1.1.1.7 root 708: }
709:
710: /* Tests */
711: static inline void gen_save_pc(target_ulong pc)
712: {
713: tcg_gen_movi_tl(cpu_PC, pc);
714: }
715:
716: static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
717: {
718: LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1.1 root 719: if (do_save_pc && ctx->pc != ctx->saved_pc) {
1.1.1.6 root 720: gen_save_pc(ctx->pc);
1.1 root 721: ctx->saved_pc = ctx->pc;
722: }
723: if (ctx->hflags != ctx->saved_hflags) {
1.1.1.8 root 724: tcg_gen_movi_i32(hflags, ctx->hflags);
1.1 root 725: ctx->saved_hflags = ctx->hflags;
1.1.1.12 root 726: switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1.1.1.6 root 727: case MIPS_HFLAG_BR:
728: break;
729: case MIPS_HFLAG_BC:
730: case MIPS_HFLAG_BL:
731: case MIPS_HFLAG_B:
1.1.1.7 root 732: tcg_gen_movi_tl(btarget, ctx->btarget);
1.1.1.6 root 733: break;
1.1 root 734: }
735: }
736: }
737:
1.1.1.7 root 738: static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
1.1.1.6 root 739: {
740: ctx->saved_hflags = ctx->hflags;
1.1.1.12 root 741: switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1.1.1.6 root 742: case MIPS_HFLAG_BR:
743: break;
744: case MIPS_HFLAG_BC:
745: case MIPS_HFLAG_BL:
1.1.1.7 root 746: case MIPS_HFLAG_B:
1.1.1.6 root 747: ctx->btarget = env->btarget;
748: break;
749: }
750: }
751:
1.1.1.7 root 752: static inline void
753: generate_exception_err (DisasContext *ctx, int excp, int err)
1.1 root 754: {
1.1.1.7 root 755: TCGv_i32 texcp = tcg_const_i32(excp);
756: TCGv_i32 terr = tcg_const_i32(err);
1.1 root 757: save_cpu_state(ctx, 1);
1.1.1.7 root 758: gen_helper_raise_exception_err(texcp, terr);
759: tcg_temp_free_i32(terr);
760: tcg_temp_free_i32(texcp);
761: }
762:
763: static inline void
764: generate_exception (DisasContext *ctx, int excp)
765: {
766: save_cpu_state(ctx, 1);
767: gen_helper_0i(raise_exception, excp);
1.1 root 768: }
769:
1.1.1.7 root 770: /* Addresses computation */
1.1.1.9 root 771: static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1.1.1.2 root 772: {
1.1.1.9 root 773: tcg_gen_add_tl(ret, arg0, arg1);
1.1.1.7 root 774:
775: #if defined(TARGET_MIPS64)
776: /* For compatibility with 32-bit code, data reference in user mode
777: with Status_UX = 0 should be casted to 32-bit and sign extended.
778: See the MIPS64 PRA manual, section 4.10. */
779: if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
780: !(ctx->hflags & MIPS_HFLAG_UX)) {
1.1.1.9 root 781: tcg_gen_ext32s_i64(ret, ret);
1.1.1.7 root 782: }
783: #endif
1.1.1.2 root 784: }
785:
1.1.1.7 root 786: static inline void check_cp0_enabled(DisasContext *ctx)
1.1.1.6 root 787: {
788: if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1.1.1.10 root 789: generate_exception_err(ctx, EXCP_CpU, 0);
1.1.1.6 root 790: }
791:
1.1.1.7 root 792: static inline void check_cp1_enabled(DisasContext *ctx)
1.1.1.6 root 793: {
794: if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
795: generate_exception_err(ctx, EXCP_CpU, 1);
796: }
797:
798: /* Verify that the processor is running with COP1X instructions enabled.
799: This is associated with the nabla symbol in the MIPS32 and MIPS64
800: opcode tables. */
801:
1.1.1.7 root 802: static inline void check_cop1x(DisasContext *ctx)
1.1.1.6 root 803: {
804: if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
805: generate_exception(ctx, EXCP_RI);
806: }
807:
808: /* Verify that the processor is running with 64-bit floating-point
809: operations enabled. */
810:
1.1.1.7 root 811: static inline void check_cp1_64bitmode(DisasContext *ctx)
1.1.1.6 root 812: {
813: if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
814: generate_exception(ctx, EXCP_RI);
815: }
816:
817: /*
818: * Verify if floating point register is valid; an operation is not defined
819: * if bit 0 of any register specification is set and the FR bit in the
820: * Status register equals zero, since the register numbers specify an
821: * even-odd pair of adjacent coprocessor general registers. When the FR bit
822: * in the Status register equals one, both even and odd register numbers
823: * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
824: *
825: * Multiple 64 bit wide registers can be checked by calling
826: * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
827: */
1.1.1.7 root 828: static inline void check_cp1_registers(DisasContext *ctx, int regs)
1.1.1.6 root 829: {
830: if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
831: generate_exception(ctx, EXCP_RI);
832: }
833:
834: /* This code generates a "reserved instruction" exception if the
835: CPU does not support the instruction set corresponding to flags. */
1.1.1.7 root 836: static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
1.1.1.6 root 837: {
838: if (unlikely(!(env->insn_flags & flags)))
839: generate_exception(ctx, EXCP_RI);
840: }
841:
842: /* This code generates a "reserved instruction" exception if 64-bit
843: instructions are not enabled. */
1.1.1.7 root 844: static inline void check_mips_64(DisasContext *ctx)
1.1.1.6 root 845: {
846: if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
847: generate_exception(ctx, EXCP_RI);
848: }
849:
1.1.1.12 root 850: /* Define small wrappers for gen_load_fpr* so that we have a uniform
851: calling interface for 32 and 64-bit FPRs. No sense in changing
852: all callers for gen_load_fpr32 when we need the CTX parameter for
853: this one use. */
854: #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
855: #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
856: #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
857: static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
858: int ft, int fs, int cc) \
859: { \
860: TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
861: TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
862: switch (ifmt) { \
863: case FMT_PS: \
864: check_cp1_64bitmode(ctx); \
865: break; \
866: case FMT_D: \
867: if (abs) { \
868: check_cop1x(ctx); \
869: } \
870: check_cp1_registers(ctx, fs | ft); \
871: break; \
872: case FMT_S: \
873: if (abs) { \
874: check_cop1x(ctx); \
875: } \
876: break; \
877: } \
878: gen_ldcmp_fpr##bits (ctx, fp0, fs); \
879: gen_ldcmp_fpr##bits (ctx, fp1, ft); \
880: switch (n) { \
881: case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
882: case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
883: case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
884: case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
885: case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
886: case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
887: case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
888: case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
889: case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
890: case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
891: case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
892: case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
893: case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
894: case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
895: case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
896: case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
897: default: abort(); \
898: } \
899: tcg_temp_free_i##bits (fp0); \
900: tcg_temp_free_i##bits (fp1); \
901: }
902:
903: FOP_CONDS(, 0, d, FMT_D, 64)
904: FOP_CONDS(abs, 1, d, FMT_D, 64)
905: FOP_CONDS(, 0, s, FMT_S, 32)
906: FOP_CONDS(abs, 1, s, FMT_S, 32)
907: FOP_CONDS(, 0, ps, FMT_PS, 64)
908: FOP_CONDS(abs, 1, ps, FMT_PS, 64)
909: #undef FOP_CONDS
910: #undef gen_ldcmp_fpr32
911: #undef gen_ldcmp_fpr64
912:
1.1.1.7 root 913: /* load/store instructions. */
1.1.1.8 root 914: #define OP_LD(insn,fname) \
1.1.1.12 root 915: static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1.1.1.8 root 916: { \
917: tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1.1.1.7 root 918: }
919: OP_LD(lb,ld8s);
920: OP_LD(lbu,ld8u);
921: OP_LD(lh,ld16s);
922: OP_LD(lhu,ld16u);
923: OP_LD(lw,ld32s);
924: #if defined(TARGET_MIPS64)
925: OP_LD(lwu,ld32u);
926: OP_LD(ld,ld64);
927: #endif
928: #undef OP_LD
929:
1.1.1.8 root 930: #define OP_ST(insn,fname) \
1.1.1.12 root 931: static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
1.1.1.8 root 932: { \
933: tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
1.1.1.7 root 934: }
935: OP_ST(sb,st8);
936: OP_ST(sh,st16);
937: OP_ST(sw,st32);
938: #if defined(TARGET_MIPS64)
939: OP_ST(sd,st64);
940: #endif
941: #undef OP_ST
942:
1.1.1.9 root 943: #ifdef CONFIG_USER_ONLY
1.1.1.8 root 944: #define OP_LD_ATOMIC(insn,fname) \
1.1.1.12 root 945: static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1.1.1.8 root 946: { \
947: TCGv t0 = tcg_temp_new(); \
948: tcg_gen_mov_tl(t0, arg1); \
949: tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1.1.1.9 root 950: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
1.1.1.8 root 951: tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
952: tcg_temp_free(t0); \
1.1 root 953: }
1.1.1.9 root 954: #else
955: #define OP_LD_ATOMIC(insn,fname) \
1.1.1.12 root 956: static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1.1.1.9 root 957: { \
958: gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
959: }
960: #endif
1.1.1.7 root 961: OP_LD_ATOMIC(ll,ld32s);
962: #if defined(TARGET_MIPS64)
963: OP_LD_ATOMIC(lld,ld64);
1.1 root 964: #endif
1.1.1.7 root 965: #undef OP_LD_ATOMIC
1.1 root 966:
1.1.1.8 root 967: #ifdef CONFIG_USER_ONLY
968: #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1.1.1.12 root 969: static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1.1.1.8 root 970: { \
971: TCGv t0 = tcg_temp_new(); \
972: int l1 = gen_new_label(); \
973: int l2 = gen_new_label(); \
974: \
975: tcg_gen_andi_tl(t0, arg2, almask); \
976: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
977: tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
978: generate_exception(ctx, EXCP_AdES); \
979: gen_set_label(l1); \
1.1.1.9 root 980: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
1.1.1.8 root 981: tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
982: tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
983: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
984: tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
985: gen_helper_0i(raise_exception, EXCP_SC); \
986: gen_set_label(l2); \
987: tcg_gen_movi_tl(t0, 0); \
988: gen_store_gpr(t0, rt); \
989: tcg_temp_free(t0); \
990: }
991: #else
992: #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1.1.1.12 root 993: static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1.1.1.8 root 994: { \
995: TCGv t0 = tcg_temp_new(); \
1.1.1.9 root 996: gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
1.1.1.8 root 997: gen_store_gpr(t0, rt); \
998: tcg_temp_free(t0); \
1.1.1.7 root 999: }
1.1.1.8 root 1000: #endif
1001: OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1.1.1.6 root 1002: #if defined(TARGET_MIPS64)
1.1.1.8 root 1003: OP_ST_ATOMIC(scd,st64,ld64,0x7);
1.1 root 1004: #endif
1.1.1.7 root 1005: #undef OP_ST_ATOMIC
1.1 root 1006:
1.1.1.12 root 1007: static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1008: int base, int16_t offset)
1.1 root 1009: {
1010: if (base == 0) {
1.1.1.12 root 1011: tcg_gen_movi_tl(addr, offset);
1.1 root 1012: } else if (offset == 0) {
1.1.1.12 root 1013: gen_load_gpr(addr, base);
1.1 root 1014: } else {
1.1.1.12 root 1015: tcg_gen_movi_tl(addr, offset);
1016: gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1.1 root 1017: }
1.1.1.12 root 1018: }
1019:
1020: static target_ulong pc_relative_pc (DisasContext *ctx)
1021: {
1022: target_ulong pc = ctx->pc;
1023:
1024: if (ctx->hflags & MIPS_HFLAG_BMASK) {
1025: int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1026:
1027: pc -= branch_bytes;
1028: }
1029:
1030: pc &= ~(target_ulong)3;
1031: return pc;
1032: }
1033:
1034: /* Load */
1035: static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
1036: int rt, int base, int16_t offset)
1037: {
1038: const char *opn = "ld";
1039: TCGv t0, t1;
1040:
1041: if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1042: /* Loongson CPU uses a load to zero register for prefetch.
1043: We emulate it as a NOP. On other CPU we must perform the
1044: actual memory access. */
1045: MIPS_DEBUG("NOP");
1046: return;
1047: }
1048:
1049: t0 = tcg_temp_new();
1050: t1 = tcg_temp_new();
1051: gen_base_offset_addr(ctx, t0, base, offset);
1052:
1.1 root 1053: switch (opc) {
1.1.1.6 root 1054: #if defined(TARGET_MIPS64)
1055: case OPC_LWU:
1.1.1.8 root 1056: save_cpu_state(ctx, 0);
1.1.1.12 root 1057: op_ld_lwu(t0, t0, ctx);
1.1.1.7 root 1058: gen_store_gpr(t0, rt);
1.1.1.6 root 1059: opn = "lwu";
1060: break;
1.1 root 1061: case OPC_LD:
1.1.1.8 root 1062: save_cpu_state(ctx, 0);
1.1.1.12 root 1063: op_ld_ld(t0, t0, ctx);
1.1.1.7 root 1064: gen_store_gpr(t0, rt);
1.1 root 1065: opn = "ld";
1066: break;
1.1.1.5 root 1067: case OPC_LLD:
1.1.1.13 root 1068: save_cpu_state(ctx, 1);
1.1.1.12 root 1069: op_ld_lld(t0, t0, ctx);
1.1.1.7 root 1070: gen_store_gpr(t0, rt);
1.1.1.5 root 1071: opn = "lld";
1072: break;
1.1 root 1073: case OPC_LDL:
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(ldl, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1077: gen_store_gpr(t1, rt);
1.1 root 1078: opn = "ldl";
1079: break;
1080: case OPC_LDR:
1.1.1.7 root 1081: save_cpu_state(ctx, 1);
1082: gen_load_gpr(t1, rt);
1.1.1.8 root 1083: gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1084: gen_store_gpr(t1, rt);
1.1 root 1085: opn = "ldr";
1086: break;
1.1.1.12 root 1087: case OPC_LDPC:
1.1.1.13 root 1088: save_cpu_state(ctx, 0);
1.1.1.12 root 1089: tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1090: gen_op_addr_add(ctx, t0, t0, t1);
1091: op_ld_ld(t0, t0, ctx);
1092: gen_store_gpr(t0, rt);
1093: opn = "ldpc";
1.1 root 1094: break;
1095: #endif
1.1.1.12 root 1096: case OPC_LWPC:
1.1.1.13 root 1097: save_cpu_state(ctx, 0);
1.1.1.12 root 1098: tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1099: gen_op_addr_add(ctx, t0, t0, t1);
1100: op_ld_lw(t0, t0, ctx);
1101: gen_store_gpr(t0, rt);
1102: opn = "lwpc";
1103: break;
1.1 root 1104: case OPC_LW:
1.1.1.8 root 1105: save_cpu_state(ctx, 0);
1.1.1.12 root 1106: op_ld_lw(t0, t0, ctx);
1.1.1.7 root 1107: gen_store_gpr(t0, rt);
1.1 root 1108: opn = "lw";
1109: break;
1110: case OPC_LH:
1.1.1.8 root 1111: save_cpu_state(ctx, 0);
1.1.1.12 root 1112: op_ld_lh(t0, t0, ctx);
1.1.1.7 root 1113: gen_store_gpr(t0, rt);
1.1 root 1114: opn = "lh";
1115: break;
1116: case OPC_LHU:
1.1.1.8 root 1117: save_cpu_state(ctx, 0);
1.1.1.12 root 1118: op_ld_lhu(t0, t0, ctx);
1.1.1.7 root 1119: gen_store_gpr(t0, rt);
1.1 root 1120: opn = "lhu";
1121: break;
1122: case OPC_LB:
1.1.1.8 root 1123: save_cpu_state(ctx, 0);
1.1.1.12 root 1124: op_ld_lb(t0, t0, ctx);
1.1.1.7 root 1125: gen_store_gpr(t0, rt);
1.1 root 1126: opn = "lb";
1127: break;
1128: case OPC_LBU:
1.1.1.8 root 1129: save_cpu_state(ctx, 0);
1.1.1.12 root 1130: op_ld_lbu(t0, t0, ctx);
1.1.1.7 root 1131: gen_store_gpr(t0, rt);
1.1 root 1132: opn = "lbu";
1133: break;
1134: case OPC_LWL:
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(lwl, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1138: gen_store_gpr(t1, rt);
1.1 root 1139: opn = "lwl";
1140: break;
1141: case OPC_LWR:
1.1.1.7 root 1142: save_cpu_state(ctx, 1);
1143: gen_load_gpr(t1, rt);
1.1.1.8 root 1144: gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1145: gen_store_gpr(t1, rt);
1.1 root 1146: opn = "lwr";
1147: break;
1148: case OPC_LL:
1.1.1.9 root 1149: save_cpu_state(ctx, 1);
1.1.1.12 root 1150: op_ld_ll(t0, t0, ctx);
1.1.1.7 root 1151: gen_store_gpr(t0, rt);
1.1 root 1152: opn = "ll";
1153: break;
1.1.1.8 root 1154: }
1.1.1.13 root 1155: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1156: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1157: tcg_temp_free(t0);
1158: tcg_temp_free(t1);
1159: }
1160:
1.1.1.12 root 1161: /* Store */
1162: static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1163: int base, int16_t offset)
1164: {
1165: const char *opn = "st";
1166: TCGv t0 = tcg_temp_new();
1167: TCGv t1 = tcg_temp_new();
1168:
1169: gen_base_offset_addr(ctx, t0, base, offset);
1170: gen_load_gpr(t1, rt);
1171: switch (opc) {
1172: #if defined(TARGET_MIPS64)
1173: case OPC_SD:
1174: save_cpu_state(ctx, 0);
1175: op_st_sd(t1, t0, ctx);
1176: opn = "sd";
1177: break;
1178: case OPC_SDL:
1179: save_cpu_state(ctx, 1);
1180: gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1181: opn = "sdl";
1182: break;
1183: case OPC_SDR:
1184: save_cpu_state(ctx, 1);
1185: gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1186: opn = "sdr";
1187: break;
1188: #endif
1189: case OPC_SW:
1190: save_cpu_state(ctx, 0);
1191: op_st_sw(t1, t0, ctx);
1192: opn = "sw";
1193: break;
1194: case OPC_SH:
1195: save_cpu_state(ctx, 0);
1196: op_st_sh(t1, t0, ctx);
1197: opn = "sh";
1198: break;
1199: case OPC_SB:
1200: save_cpu_state(ctx, 0);
1201: op_st_sb(t1, t0, ctx);
1202: opn = "sb";
1203: break;
1204: case OPC_SWL:
1205: save_cpu_state(ctx, 1);
1206: gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1207: opn = "swl";
1208: break;
1209: case OPC_SWR:
1210: save_cpu_state(ctx, 1);
1211: gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1212: opn = "swr";
1213: break;
1214: }
1.1.1.13 root 1215: (void)opn; /* avoid a compiler warning */
1.1.1.12 root 1216: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1217: tcg_temp_free(t0);
1218: tcg_temp_free(t1);
1219: }
1220:
1221:
1.1.1.8 root 1222: /* Store conditional */
1223: static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1224: int base, int16_t offset)
1225: {
1226: const char *opn = "st_cond";
1227: TCGv t0, t1;
1228:
1229: t0 = tcg_temp_local_new();
1230:
1.1.1.12 root 1231: gen_base_offset_addr(ctx, t0, base, offset);
1.1.1.8 root 1232: /* Don't do NOP if destination is zero: we must perform the actual
1233: memory access. */
1234:
1235: t1 = tcg_temp_local_new();
1236: gen_load_gpr(t1, rt);
1237: switch (opc) {
1238: #if defined(TARGET_MIPS64)
1239: case OPC_SCD:
1.1.1.13 root 1240: save_cpu_state(ctx, 1);
1.1.1.12 root 1241: op_st_scd(t1, t0, rt, ctx);
1.1.1.8 root 1242: opn = "scd";
1243: break;
1244: #endif
1.1 root 1245: case OPC_SC:
1.1.1.9 root 1246: save_cpu_state(ctx, 1);
1.1.1.12 root 1247: op_st_sc(t1, t0, rt, ctx);
1.1 root 1248: opn = "sc";
1249: break;
1250: }
1.1.1.13 root 1251: (void)opn; /* avoid a compiler warning */
1.1 root 1252: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1.1.1.7 root 1253: tcg_temp_free(t1);
1.1.1.8 root 1254: tcg_temp_free(t0);
1.1 root 1255: }
1256:
1.1.1.4 root 1257: /* Load and store */
1.1.1.5 root 1258: static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1.1.1.7 root 1259: int base, int16_t offset)
1.1.1.4 root 1260: {
1.1.1.6 root 1261: const char *opn = "flt_ldst";
1.1.1.8 root 1262: TCGv t0 = tcg_temp_new();
1.1.1.4 root 1263:
1.1.1.12 root 1264: gen_base_offset_addr(ctx, t0, base, offset);
1.1.1.4 root 1265: /* Don't do NOP if destination is zero: we must perform the actual
1.1.1.6 root 1266: memory access. */
1.1.1.4 root 1267: switch (opc) {
1268: case OPC_LWC1:
1.1.1.7 root 1269: {
1270: TCGv_i32 fp0 = tcg_temp_new_i32();
1271:
1.1.1.8 root 1272: tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1273: tcg_gen_trunc_tl_i32(fp0, t0);
1.1.1.7 root 1274: gen_store_fpr32(fp0, ft);
1275: tcg_temp_free_i32(fp0);
1276: }
1.1.1.4 root 1277: opn = "lwc1";
1278: break;
1279: case OPC_SWC1:
1.1.1.7 root 1280: {
1281: TCGv_i32 fp0 = tcg_temp_new_i32();
1282: TCGv t1 = tcg_temp_new();
1283:
1284: gen_load_fpr32(fp0, ft);
1285: tcg_gen_extu_i32_tl(t1, fp0);
1286: tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1287: tcg_temp_free(t1);
1288: tcg_temp_free_i32(fp0);
1289: }
1.1.1.4 root 1290: opn = "swc1";
1291: break;
1292: case OPC_LDC1:
1.1.1.7 root 1293: {
1294: TCGv_i64 fp0 = tcg_temp_new_i64();
1295:
1296: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1297: gen_store_fpr64(ctx, fp0, ft);
1298: tcg_temp_free_i64(fp0);
1299: }
1.1.1.4 root 1300: opn = "ldc1";
1301: break;
1302: case OPC_SDC1:
1.1.1.7 root 1303: {
1304: TCGv_i64 fp0 = tcg_temp_new_i64();
1305:
1306: gen_load_fpr64(ctx, fp0, ft);
1307: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1308: tcg_temp_free_i64(fp0);
1309: }
1.1.1.4 root 1310: opn = "sdc1";
1311: break;
1312: default:
1.1.1.6 root 1313: MIPS_INVAL(opn);
1314: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 1315: goto out;
1.1.1.4 root 1316: }
1.1.1.13 root 1317: (void)opn; /* avoid a compiler warning */
1.1.1.4 root 1318: MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1.1.1.7 root 1319: out:
1320: tcg_temp_free(t0);
1.1.1.4 root 1321: }
1.1.1.5 root 1322:
1.1.1.12 root 1323: static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
1324: uint32_t op, int rt, int rs, int16_t imm)
1325: {
1326: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1327: check_cp1_enabled(ctx);
1328: gen_flt_ldst(ctx, op, rt, rs, imm);
1329: } else {
1330: generate_exception_err(ctx, EXCP_CpU, 1);
1331: }
1332: }
1333:
1.1 root 1334: /* Arithmetic with immediate operand */
1.1.1.6 root 1335: static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1336: int rt, int rs, int16_t imm)
1.1 root 1337: {
1.1.1.8 root 1338: target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1.1.1.6 root 1339: const char *opn = "imm arith";
1.1 root 1340:
1.1.1.5 root 1341: if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1.1.1.6 root 1342: /* If no destination, treat it as a NOP.
1343: For addi, we must generate the overflow exception when needed. */
1.1 root 1344: MIPS_DEBUG("NOP");
1.1.1.8 root 1345: return;
1.1 root 1346: }
1347: switch (opc) {
1348: case OPC_ADDI:
1.1.1.7 root 1349: {
1.1.1.8 root 1350: TCGv t0 = tcg_temp_local_new();
1351: TCGv t1 = tcg_temp_new();
1352: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1353: int l1 = gen_new_label();
1354:
1.1.1.8 root 1355: gen_load_gpr(t1, rs);
1356: tcg_gen_addi_tl(t0, t1, uimm);
1357: tcg_gen_ext32s_tl(t0, t0);
1.1.1.7 root 1358:
1.1.1.8 root 1359: tcg_gen_xori_tl(t1, t1, ~uimm);
1360: tcg_gen_xori_tl(t2, t0, uimm);
1361: tcg_gen_and_tl(t1, t1, t2);
1362: tcg_temp_free(t2);
1363: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1364: tcg_temp_free(t1);
1.1.1.7 root 1365: /* operands of same sign, result different sign */
1366: generate_exception(ctx, EXCP_OVERFLOW);
1367: gen_set_label(l1);
1368: tcg_gen_ext32s_tl(t0, t0);
1.1.1.8 root 1369: gen_store_gpr(t0, rt);
1370: tcg_temp_free(t0);
1.1.1.7 root 1371: }
1.1 root 1372: opn = "addi";
1373: break;
1374: case OPC_ADDIU:
1.1.1.8 root 1375: if (rs != 0) {
1376: tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1377: tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1378: } else {
1379: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1380: }
1.1 root 1381: opn = "addiu";
1382: break;
1.1.1.6 root 1383: #if defined(TARGET_MIPS64)
1.1.1.5 root 1384: case OPC_DADDI:
1.1.1.7 root 1385: {
1.1.1.8 root 1386: TCGv t0 = tcg_temp_local_new();
1387: TCGv t1 = tcg_temp_new();
1388: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1389: int l1 = gen_new_label();
1390:
1.1.1.8 root 1391: gen_load_gpr(t1, rs);
1392: tcg_gen_addi_tl(t0, t1, uimm);
1.1.1.7 root 1393:
1.1.1.8 root 1394: tcg_gen_xori_tl(t1, t1, ~uimm);
1395: tcg_gen_xori_tl(t2, t0, uimm);
1396: tcg_gen_and_tl(t1, t1, t2);
1397: tcg_temp_free(t2);
1398: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1399: tcg_temp_free(t1);
1.1.1.7 root 1400: /* operands of same sign, result different sign */
1401: generate_exception(ctx, EXCP_OVERFLOW);
1402: gen_set_label(l1);
1.1.1.8 root 1403: gen_store_gpr(t0, rt);
1404: tcg_temp_free(t0);
1.1.1.7 root 1405: }
1.1.1.5 root 1406: opn = "daddi";
1407: break;
1408: case OPC_DADDIU:
1.1.1.8 root 1409: if (rs != 0) {
1410: tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1411: } else {
1412: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1413: }
1.1.1.5 root 1414: opn = "daddiu";
1415: break;
1416: #endif
1.1.1.8 root 1417: }
1.1.1.13 root 1418: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1419: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1420: }
1421:
1422: /* Logic with immediate operand */
1423: static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1424: {
1425: target_ulong uimm;
1426: const char *opn = "imm logic";
1427:
1428: if (rt == 0) {
1429: /* If no destination, treat it as a NOP. */
1430: MIPS_DEBUG("NOP");
1431: return;
1432: }
1433: uimm = (uint16_t)imm;
1434: switch (opc) {
1.1 root 1435: case OPC_ANDI:
1.1.1.8 root 1436: if (likely(rs != 0))
1437: tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1438: else
1439: tcg_gen_movi_tl(cpu_gpr[rt], 0);
1.1 root 1440: opn = "andi";
1441: break;
1442: case OPC_ORI:
1.1.1.8 root 1443: if (rs != 0)
1444: tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1445: else
1446: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1.1 root 1447: opn = "ori";
1448: break;
1449: case OPC_XORI:
1.1.1.8 root 1450: if (likely(rs != 0))
1451: tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1452: else
1453: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1.1 root 1454: opn = "xori";
1455: break;
1456: case OPC_LUI:
1.1.1.8 root 1457: tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1.1 root 1458: opn = "lui";
1459: break;
1.1.1.8 root 1460: }
1.1.1.13 root 1461: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1462: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1463: }
1464:
1465: /* Set on less than with immediate operand */
1466: static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1467: {
1468: target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1469: const char *opn = "imm arith";
1470: TCGv t0;
1471:
1472: if (rt == 0) {
1473: /* If no destination, treat it as a NOP. */
1474: MIPS_DEBUG("NOP");
1475: return;
1476: }
1477: t0 = tcg_temp_new();
1478: gen_load_gpr(t0, rs);
1479: switch (opc) {
1480: case OPC_SLTI:
1.1.1.12 root 1481: tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1.1.1.8 root 1482: opn = "slti";
1483: break;
1484: case OPC_SLTIU:
1.1.1.12 root 1485: tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1.1.1.8 root 1486: opn = "sltiu";
1487: break;
1488: }
1.1.1.13 root 1489: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1490: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1491: tcg_temp_free(t0);
1492: }
1493:
1494: /* Shifts with immediate operand */
1495: static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1496: int rt, int rs, int16_t imm)
1497: {
1498: target_ulong uimm = ((uint16_t)imm) & 0x1f;
1499: const char *opn = "imm shift";
1500: TCGv t0;
1501:
1502: if (rt == 0) {
1503: /* If no destination, treat it as a NOP. */
1504: MIPS_DEBUG("NOP");
1505: return;
1506: }
1507:
1508: t0 = tcg_temp_new();
1509: gen_load_gpr(t0, rs);
1510: switch (opc) {
1.1 root 1511: case OPC_SLL:
1.1.1.7 root 1512: tcg_gen_shli_tl(t0, t0, uimm);
1.1.1.8 root 1513: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1.1 root 1514: opn = "sll";
1515: break;
1516: case OPC_SRA:
1.1.1.8 root 1517: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1.1 root 1518: opn = "sra";
1519: break;
1520: case OPC_SRL:
1.1.1.12 root 1521: if (uimm != 0) {
1522: tcg_gen_ext32u_tl(t0, t0);
1523: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1524: } else {
1525: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1526: }
1527: opn = "srl";
1528: break;
1529: case OPC_ROTR:
1530: if (uimm != 0) {
1531: TCGv_i32 t1 = tcg_temp_new_i32();
1.1.1.7 root 1532:
1.1.1.12 root 1533: tcg_gen_trunc_tl_i32(t1, t0);
1534: tcg_gen_rotri_i32(t1, t1, uimm);
1535: tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1536: tcg_temp_free_i32(t1);
1537: } else {
1538: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1.1.1.6 root 1539: }
1.1.1.12 root 1540: opn = "rotr";
1.1.1.5 root 1541: break;
1.1.1.6 root 1542: #if defined(TARGET_MIPS64)
1.1.1.5 root 1543: case OPC_DSLL:
1.1.1.8 root 1544: tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1.1.1.5 root 1545: opn = "dsll";
1546: break;
1547: case OPC_DSRA:
1.1.1.8 root 1548: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1.1.1.5 root 1549: opn = "dsra";
1550: break;
1551: case OPC_DSRL:
1.1.1.12 root 1552: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1553: opn = "dsrl";
1554: break;
1555: case OPC_DROTR:
1556: if (uimm != 0) {
1557: tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1558: } else {
1559: tcg_gen_mov_tl(cpu_gpr[rt], t0);
1.1.1.6 root 1560: }
1.1.1.12 root 1561: opn = "drotr";
1.1.1.5 root 1562: break;
1563: case OPC_DSLL32:
1.1.1.8 root 1564: tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1.1.1.5 root 1565: opn = "dsll32";
1566: break;
1567: case OPC_DSRA32:
1.1.1.8 root 1568: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1.1.1.5 root 1569: opn = "dsra32";
1570: break;
1571: case OPC_DSRL32:
1.1.1.12 root 1572: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1573: opn = "dsrl32";
1574: break;
1575: case OPC_DROTR32:
1576: tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1577: opn = "drotr32";
1.1 root 1578: break;
1.1.1.5 root 1579: #endif
1.1 root 1580: }
1.1.1.13 root 1581: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 1582: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1.1.1.7 root 1583: tcg_temp_free(t0);
1.1 root 1584: }
1585:
1586: /* Arithmetic */
1.1.1.6 root 1587: static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1.1 root 1588: int rd, int rs, int rt)
1589: {
1.1.1.6 root 1590: const char *opn = "arith";
1.1 root 1591:
1.1.1.5 root 1592: if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1593: && opc != OPC_DADD && opc != OPC_DSUB) {
1.1.1.6 root 1594: /* If no destination, treat it as a NOP.
1595: For add & sub, we must generate the overflow exception when needed. */
1.1 root 1596: MIPS_DEBUG("NOP");
1.1.1.8 root 1597: return;
1.1.1.6 root 1598: }
1.1.1.8 root 1599:
1.1 root 1600: switch (opc) {
1601: case OPC_ADD:
1.1.1.7 root 1602: {
1.1.1.8 root 1603: TCGv t0 = tcg_temp_local_new();
1604: TCGv t1 = tcg_temp_new();
1605: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1606: int l1 = gen_new_label();
1607:
1.1.1.8 root 1608: gen_load_gpr(t1, rs);
1609: gen_load_gpr(t2, rt);
1610: tcg_gen_add_tl(t0, t1, t2);
1611: tcg_gen_ext32s_tl(t0, t0);
1612: tcg_gen_xor_tl(t1, t1, t2);
1613: tcg_gen_xor_tl(t2, t0, t2);
1.1.1.12 root 1614: tcg_gen_andc_tl(t1, t2, t1);
1.1.1.8 root 1615: tcg_temp_free(t2);
1616: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1617: tcg_temp_free(t1);
1.1.1.7 root 1618: /* operands of same sign, result different sign */
1619: generate_exception(ctx, EXCP_OVERFLOW);
1620: gen_set_label(l1);
1.1.1.8 root 1621: gen_store_gpr(t0, rd);
1622: tcg_temp_free(t0);
1.1.1.7 root 1623: }
1.1 root 1624: opn = "add";
1625: break;
1626: case OPC_ADDU:
1.1.1.8 root 1627: if (rs != 0 && rt != 0) {
1628: tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1629: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1630: } else if (rs == 0 && rt != 0) {
1631: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1632: } else if (rs != 0 && rt == 0) {
1633: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1634: } else {
1635: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1636: }
1.1 root 1637: opn = "addu";
1638: break;
1639: case OPC_SUB:
1.1.1.7 root 1640: {
1.1.1.8 root 1641: TCGv t0 = tcg_temp_local_new();
1642: TCGv t1 = tcg_temp_new();
1643: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1644: int l1 = gen_new_label();
1645:
1.1.1.8 root 1646: gen_load_gpr(t1, rs);
1647: gen_load_gpr(t2, rt);
1648: tcg_gen_sub_tl(t0, t1, t2);
1649: tcg_gen_ext32s_tl(t0, t0);
1650: tcg_gen_xor_tl(t2, t1, t2);
1651: tcg_gen_xor_tl(t1, t0, t1);
1652: tcg_gen_and_tl(t1, t1, t2);
1653: tcg_temp_free(t2);
1654: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1655: tcg_temp_free(t1);
1.1.1.9 root 1656: /* operands of different sign, first operand and result different sign */
1.1.1.7 root 1657: generate_exception(ctx, EXCP_OVERFLOW);
1658: gen_set_label(l1);
1.1.1.8 root 1659: gen_store_gpr(t0, rd);
1660: tcg_temp_free(t0);
1.1.1.7 root 1661: }
1.1 root 1662: opn = "sub";
1663: break;
1664: case OPC_SUBU:
1.1.1.8 root 1665: if (rs != 0 && rt != 0) {
1666: tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1667: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1668: } else if (rs == 0 && rt != 0) {
1669: tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1670: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1671: } else if (rs != 0 && rt == 0) {
1672: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1673: } else {
1674: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1675: }
1.1 root 1676: opn = "subu";
1677: break;
1.1.1.6 root 1678: #if defined(TARGET_MIPS64)
1.1.1.5 root 1679: case OPC_DADD:
1.1.1.7 root 1680: {
1.1.1.8 root 1681: TCGv t0 = tcg_temp_local_new();
1682: TCGv t1 = tcg_temp_new();
1683: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1684: int l1 = gen_new_label();
1685:
1.1.1.8 root 1686: gen_load_gpr(t1, rs);
1687: gen_load_gpr(t2, rt);
1688: tcg_gen_add_tl(t0, t1, t2);
1689: tcg_gen_xor_tl(t1, t1, t2);
1690: tcg_gen_xor_tl(t2, t0, t2);
1.1.1.12 root 1691: tcg_gen_andc_tl(t1, t2, t1);
1.1.1.8 root 1692: tcg_temp_free(t2);
1693: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1694: tcg_temp_free(t1);
1.1.1.7 root 1695: /* operands of same sign, result different sign */
1696: generate_exception(ctx, EXCP_OVERFLOW);
1697: gen_set_label(l1);
1.1.1.8 root 1698: gen_store_gpr(t0, rd);
1699: tcg_temp_free(t0);
1.1.1.7 root 1700: }
1.1.1.5 root 1701: opn = "dadd";
1702: break;
1703: case OPC_DADDU:
1.1.1.8 root 1704: if (rs != 0 && rt != 0) {
1705: tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1706: } else if (rs == 0 && rt != 0) {
1707: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1708: } else if (rs != 0 && rt == 0) {
1709: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1710: } else {
1711: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1712: }
1.1.1.5 root 1713: opn = "daddu";
1714: break;
1715: case OPC_DSUB:
1.1.1.7 root 1716: {
1.1.1.8 root 1717: TCGv t0 = tcg_temp_local_new();
1718: TCGv t1 = tcg_temp_new();
1719: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1720: int l1 = gen_new_label();
1721:
1.1.1.8 root 1722: gen_load_gpr(t1, rs);
1723: gen_load_gpr(t2, rt);
1724: tcg_gen_sub_tl(t0, t1, t2);
1725: tcg_gen_xor_tl(t2, t1, t2);
1726: tcg_gen_xor_tl(t1, t0, t1);
1727: tcg_gen_and_tl(t1, t1, t2);
1728: tcg_temp_free(t2);
1729: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1730: tcg_temp_free(t1);
1.1.1.9 root 1731: /* operands of different sign, first operand and result different sign */
1.1.1.7 root 1732: generate_exception(ctx, EXCP_OVERFLOW);
1733: gen_set_label(l1);
1.1.1.8 root 1734: gen_store_gpr(t0, rd);
1735: tcg_temp_free(t0);
1.1.1.7 root 1736: }
1.1.1.5 root 1737: opn = "dsub";
1738: break;
1739: case OPC_DSUBU:
1.1.1.8 root 1740: if (rs != 0 && rt != 0) {
1741: tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1742: } else if (rs == 0 && rt != 0) {
1743: tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1744: } else if (rs != 0 && rt == 0) {
1745: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1746: } else {
1747: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1748: }
1.1.1.5 root 1749: opn = "dsubu";
1750: break;
1751: #endif
1.1.1.8 root 1752: case OPC_MUL:
1753: if (likely(rs != 0 && rt != 0)) {
1754: tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1755: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1756: } else {
1757: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1758: }
1759: opn = "mul";
1.1 root 1760: break;
1.1.1.8 root 1761: }
1.1.1.13 root 1762: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1763: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1764: }
1765:
1766: /* Conditional move */
1767: static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1768: {
1769: const char *opn = "cond move";
1770: int l1;
1771:
1772: if (rd == 0) {
1773: /* If no destination, treat it as a NOP.
1774: For add & sub, we must generate the overflow exception when needed. */
1775: MIPS_DEBUG("NOP");
1776: return;
1777: }
1778:
1779: l1 = gen_new_label();
1780: switch (opc) {
1781: case OPC_MOVN:
1782: if (likely(rt != 0))
1783: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1784: else
1785: tcg_gen_br(l1);
1786: opn = "movn";
1.1 root 1787: break;
1.1.1.8 root 1788: case OPC_MOVZ:
1789: if (likely(rt != 0))
1790: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1791: opn = "movz";
1792: break;
1793: }
1794: if (rs != 0)
1795: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1796: else
1797: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1798: gen_set_label(l1);
1799:
1.1.1.13 root 1800: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1801: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1802: }
1803:
1804: /* Logic */
1805: static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1806: {
1807: const char *opn = "logic";
1808:
1809: if (rd == 0) {
1810: /* If no destination, treat it as a NOP. */
1811: MIPS_DEBUG("NOP");
1812: return;
1813: }
1814:
1815: switch (opc) {
1.1 root 1816: case OPC_AND:
1.1.1.8 root 1817: if (likely(rs != 0 && rt != 0)) {
1818: tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1819: } else {
1820: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1821: }
1.1 root 1822: opn = "and";
1823: break;
1824: case OPC_NOR:
1.1.1.8 root 1825: if (rs != 0 && rt != 0) {
1826: tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1827: } else if (rs == 0 && rt != 0) {
1828: tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1829: } else if (rs != 0 && rt == 0) {
1830: tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1831: } else {
1832: tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1833: }
1.1 root 1834: opn = "nor";
1835: break;
1836: case OPC_OR:
1.1.1.8 root 1837: if (likely(rs != 0 && rt != 0)) {
1838: tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1839: } else if (rs == 0 && rt != 0) {
1840: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1841: } else if (rs != 0 && rt == 0) {
1842: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1843: } else {
1844: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1845: }
1.1 root 1846: opn = "or";
1847: break;
1848: case OPC_XOR:
1.1.1.8 root 1849: if (likely(rs != 0 && rt != 0)) {
1850: tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1851: } else if (rs == 0 && rt != 0) {
1852: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1853: } else if (rs != 0 && rt == 0) {
1854: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1855: } else {
1856: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1857: }
1.1 root 1858: opn = "xor";
1859: break;
1.1.1.8 root 1860: }
1.1.1.13 root 1861: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1862: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1863: }
1864:
1865: /* Set on lower than */
1866: static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1867: {
1868: const char *opn = "slt";
1869: TCGv t0, t1;
1870:
1871: if (rd == 0) {
1872: /* If no destination, treat it as a NOP. */
1873: MIPS_DEBUG("NOP");
1874: return;
1875: }
1876:
1877: t0 = tcg_temp_new();
1878: t1 = tcg_temp_new();
1879: gen_load_gpr(t0, rs);
1880: gen_load_gpr(t1, rt);
1881: switch (opc) {
1882: case OPC_SLT:
1.1.1.12 root 1883: tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
1.1.1.8 root 1884: opn = "slt";
1.1 root 1885: break;
1.1.1.8 root 1886: case OPC_SLTU:
1.1.1.12 root 1887: tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
1.1.1.8 root 1888: opn = "sltu";
1889: break;
1890: }
1.1.1.13 root 1891: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1892: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1893: tcg_temp_free(t0);
1894: tcg_temp_free(t1);
1895: }
1.1.1.7 root 1896:
1.1.1.8 root 1897: /* Shifts */
1898: static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1899: int rd, int rs, int rt)
1900: {
1901: const char *opn = "shifts";
1902: TCGv t0, t1;
1.1.1.7 root 1903:
1.1.1.8 root 1904: if (rd == 0) {
1905: /* If no destination, treat it as a NOP.
1906: For add & sub, we must generate the overflow exception when needed. */
1907: MIPS_DEBUG("NOP");
1908: return;
1909: }
1910:
1911: t0 = tcg_temp_new();
1912: t1 = tcg_temp_new();
1913: gen_load_gpr(t0, rs);
1914: gen_load_gpr(t1, rt);
1915: switch (opc) {
1.1 root 1916: case OPC_SLLV:
1.1.1.7 root 1917: tcg_gen_andi_tl(t0, t0, 0x1f);
1918: tcg_gen_shl_tl(t0, t1, t0);
1.1.1.8 root 1919: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1.1 root 1920: opn = "sllv";
1921: break;
1922: case OPC_SRAV:
1.1.1.7 root 1923: tcg_gen_andi_tl(t0, t0, 0x1f);
1.1.1.8 root 1924: tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1.1 root 1925: opn = "srav";
1926: break;
1927: case OPC_SRLV:
1.1.1.12 root 1928: tcg_gen_ext32u_tl(t1, t1);
1929: tcg_gen_andi_tl(t0, t0, 0x1f);
1930: tcg_gen_shr_tl(t0, t1, t0);
1931: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1932: opn = "srlv";
1933: break;
1934: case OPC_ROTRV:
1935: {
1936: TCGv_i32 t2 = tcg_temp_new_i32();
1937: TCGv_i32 t3 = tcg_temp_new_i32();
1938:
1939: tcg_gen_trunc_tl_i32(t2, t0);
1940: tcg_gen_trunc_tl_i32(t3, t1);
1941: tcg_gen_andi_i32(t2, t2, 0x1f);
1942: tcg_gen_rotr_i32(t2, t3, t2);
1943: tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1944: tcg_temp_free_i32(t2);
1945: tcg_temp_free_i32(t3);
1946: opn = "rotrv";
1.1.1.6 root 1947: }
1.1.1.5 root 1948: break;
1.1.1.6 root 1949: #if defined(TARGET_MIPS64)
1.1.1.5 root 1950: case OPC_DSLLV:
1.1.1.7 root 1951: tcg_gen_andi_tl(t0, t0, 0x3f);
1.1.1.8 root 1952: tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1.1.1.5 root 1953: opn = "dsllv";
1954: break;
1955: case OPC_DSRAV:
1.1.1.7 root 1956: tcg_gen_andi_tl(t0, t0, 0x3f);
1.1.1.8 root 1957: tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1.1.1.5 root 1958: opn = "dsrav";
1959: break;
1960: case OPC_DSRLV:
1.1.1.12 root 1961: tcg_gen_andi_tl(t0, t0, 0x3f);
1962: tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1963: opn = "dsrlv";
1964: break;
1965: case OPC_DROTRV:
1966: tcg_gen_andi_tl(t0, t0, 0x3f);
1967: tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1968: opn = "drotrv";
1.1 root 1969: break;
1.1.1.5 root 1970: #endif
1.1 root 1971: }
1.1.1.13 root 1972: (void)opn; /* avoid a compiler warning */
1.1 root 1973: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1.1.1.7 root 1974: tcg_temp_free(t0);
1975: tcg_temp_free(t1);
1.1 root 1976: }
1977:
1978: /* Arithmetic on HI/LO registers */
1.1.1.5 root 1979: static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1.1 root 1980: {
1.1.1.6 root 1981: const char *opn = "hilo";
1.1 root 1982:
1983: if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1.1.1.6 root 1984: /* Treat as NOP. */
1.1 root 1985: MIPS_DEBUG("NOP");
1.1.1.8 root 1986: return;
1.1 root 1987: }
1988: switch (opc) {
1989: case OPC_MFHI:
1.1.1.8 root 1990: tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1.1 root 1991: opn = "mfhi";
1992: break;
1993: case OPC_MFLO:
1.1.1.8 root 1994: tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1.1 root 1995: opn = "mflo";
1996: break;
1997: case OPC_MTHI:
1.1.1.8 root 1998: if (reg != 0)
1999: tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
2000: else
2001: tcg_gen_movi_tl(cpu_HI[0], 0);
1.1 root 2002: opn = "mthi";
2003: break;
2004: case OPC_MTLO:
1.1.1.8 root 2005: if (reg != 0)
2006: tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2007: else
2008: tcg_gen_movi_tl(cpu_LO[0], 0);
1.1 root 2009: opn = "mtlo";
2010: break;
2011: }
1.1.1.13 root 2012: (void)opn; /* avoid a compiler warning */
1.1 root 2013: MIPS_DEBUG("%s %s", opn, regnames[reg]);
2014: }
2015:
1.1.1.5 root 2016: static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1.1 root 2017: int rs, int rt)
2018: {
1.1.1.6 root 2019: const char *opn = "mul/div";
1.1.1.8 root 2020: TCGv t0, t1;
2021:
2022: switch (opc) {
2023: case OPC_DIV:
2024: case OPC_DIVU:
2025: #if defined(TARGET_MIPS64)
2026: case OPC_DDIV:
2027: case OPC_DDIVU:
2028: #endif
2029: t0 = tcg_temp_local_new();
2030: t1 = tcg_temp_local_new();
2031: break;
2032: default:
2033: t0 = tcg_temp_new();
2034: t1 = tcg_temp_new();
2035: break;
2036: }
1.1 root 2037:
1.1.1.7 root 2038: gen_load_gpr(t0, rs);
2039: gen_load_gpr(t1, rt);
1.1 root 2040: switch (opc) {
2041: case OPC_DIV:
1.1.1.7 root 2042: {
2043: int l1 = gen_new_label();
1.1.1.8 root 2044: int l2 = gen_new_label();
1.1.1.7 root 2045:
1.1.1.8 root 2046: tcg_gen_ext32s_tl(t0, t0);
2047: tcg_gen_ext32s_tl(t1, t1);
1.1.1.7 root 2048: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2049: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2050: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2051:
2052: tcg_gen_mov_tl(cpu_LO[0], t0);
2053: tcg_gen_movi_tl(cpu_HI[0], 0);
2054: tcg_gen_br(l1);
2055: gen_set_label(l2);
2056: tcg_gen_div_tl(cpu_LO[0], t0, t1);
2057: tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2058: tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2059: tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1.1.1.7 root 2060: gen_set_label(l1);
2061: }
1.1 root 2062: opn = "div";
2063: break;
2064: case OPC_DIVU:
1.1.1.7 root 2065: {
2066: int l1 = gen_new_label();
2067:
1.1.1.8 root 2068: tcg_gen_ext32u_tl(t0, t0);
2069: tcg_gen_ext32u_tl(t1, t1);
1.1.1.7 root 2070: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2071: tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2072: tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2073: tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2074: tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1.1.1.7 root 2075: gen_set_label(l1);
2076: }
1.1 root 2077: opn = "divu";
2078: break;
2079: case OPC_MULT:
1.1.1.7 root 2080: {
1.1.1.8 root 2081: TCGv_i64 t2 = tcg_temp_new_i64();
2082: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2083:
1.1.1.8 root 2084: tcg_gen_ext_tl_i64(t2, t0);
2085: tcg_gen_ext_tl_i64(t3, t1);
2086: tcg_gen_mul_i64(t2, t2, t3);
2087: tcg_temp_free_i64(t3);
2088: tcg_gen_trunc_i64_tl(t0, t2);
2089: tcg_gen_shri_i64(t2, t2, 32);
2090: tcg_gen_trunc_i64_tl(t1, t2);
2091: tcg_temp_free_i64(t2);
1.1.1.7 root 2092: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2093: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2094: }
1.1 root 2095: opn = "mult";
2096: break;
2097: case OPC_MULTU:
1.1.1.7 root 2098: {
1.1.1.8 root 2099: TCGv_i64 t2 = tcg_temp_new_i64();
2100: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2101:
2102: tcg_gen_ext32u_tl(t0, t0);
2103: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2104: tcg_gen_extu_tl_i64(t2, t0);
2105: tcg_gen_extu_tl_i64(t3, t1);
2106: tcg_gen_mul_i64(t2, t2, t3);
2107: tcg_temp_free_i64(t3);
2108: tcg_gen_trunc_i64_tl(t0, t2);
2109: tcg_gen_shri_i64(t2, t2, 32);
2110: tcg_gen_trunc_i64_tl(t1, t2);
2111: tcg_temp_free_i64(t2);
1.1.1.7 root 2112: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2113: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2114: }
1.1 root 2115: opn = "multu";
2116: break;
1.1.1.6 root 2117: #if defined(TARGET_MIPS64)
1.1.1.5 root 2118: case OPC_DDIV:
1.1.1.7 root 2119: {
2120: int l1 = gen_new_label();
1.1.1.8 root 2121: int l2 = gen_new_label();
1.1.1.7 root 2122:
2123: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2124: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2125: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2126: tcg_gen_mov_tl(cpu_LO[0], t0);
2127: tcg_gen_movi_tl(cpu_HI[0], 0);
2128: tcg_gen_br(l1);
2129: gen_set_label(l2);
2130: tcg_gen_div_i64(cpu_LO[0], t0, t1);
2131: tcg_gen_rem_i64(cpu_HI[0], t0, t1);
1.1.1.7 root 2132: gen_set_label(l1);
2133: }
1.1.1.5 root 2134: opn = "ddiv";
2135: break;
2136: case OPC_DDIVU:
1.1.1.7 root 2137: {
2138: int l1 = gen_new_label();
2139:
2140: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2141: tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2142: tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2143: gen_set_label(l1);
2144: }
1.1.1.5 root 2145: opn = "ddivu";
2146: break;
2147: case OPC_DMULT:
1.1.1.7 root 2148: gen_helper_dmult(t0, t1);
1.1.1.5 root 2149: opn = "dmult";
2150: break;
2151: case OPC_DMULTU:
1.1.1.7 root 2152: gen_helper_dmultu(t0, t1);
1.1.1.5 root 2153: opn = "dmultu";
2154: break;
2155: #endif
1.1 root 2156: case OPC_MADD:
1.1.1.7 root 2157: {
1.1.1.8 root 2158: TCGv_i64 t2 = tcg_temp_new_i64();
2159: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2160:
1.1.1.8 root 2161: tcg_gen_ext_tl_i64(t2, t0);
2162: tcg_gen_ext_tl_i64(t3, t1);
2163: tcg_gen_mul_i64(t2, t2, t3);
2164: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2165: tcg_gen_add_i64(t2, t2, t3);
2166: tcg_temp_free_i64(t3);
2167: tcg_gen_trunc_i64_tl(t0, t2);
2168: tcg_gen_shri_i64(t2, t2, 32);
2169: tcg_gen_trunc_i64_tl(t1, t2);
2170: tcg_temp_free_i64(t2);
1.1.1.7 root 2171: tcg_gen_ext32s_tl(cpu_LO[0], t0);
1.1.1.8 root 2172: tcg_gen_ext32s_tl(cpu_HI[0], t1);
1.1.1.7 root 2173: }
1.1 root 2174: opn = "madd";
2175: break;
2176: case OPC_MADDU:
1.1.1.7 root 2177: {
1.1.1.8 root 2178: TCGv_i64 t2 = tcg_temp_new_i64();
2179: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2180:
2181: tcg_gen_ext32u_tl(t0, t0);
2182: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2183: tcg_gen_extu_tl_i64(t2, t0);
2184: tcg_gen_extu_tl_i64(t3, t1);
2185: tcg_gen_mul_i64(t2, t2, t3);
2186: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2187: tcg_gen_add_i64(t2, t2, t3);
2188: tcg_temp_free_i64(t3);
2189: tcg_gen_trunc_i64_tl(t0, t2);
2190: tcg_gen_shri_i64(t2, t2, 32);
2191: tcg_gen_trunc_i64_tl(t1, t2);
2192: tcg_temp_free_i64(t2);
1.1.1.7 root 2193: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2194: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2195: }
1.1 root 2196: opn = "maddu";
2197: break;
2198: case OPC_MSUB:
1.1.1.7 root 2199: {
1.1.1.8 root 2200: TCGv_i64 t2 = tcg_temp_new_i64();
2201: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2202:
1.1.1.8 root 2203: tcg_gen_ext_tl_i64(t2, t0);
2204: tcg_gen_ext_tl_i64(t3, t1);
2205: tcg_gen_mul_i64(t2, t2, t3);
2206: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2207: tcg_gen_sub_i64(t2, t3, t2);
2208: tcg_temp_free_i64(t3);
2209: tcg_gen_trunc_i64_tl(t0, t2);
2210: tcg_gen_shri_i64(t2, t2, 32);
2211: tcg_gen_trunc_i64_tl(t1, t2);
2212: tcg_temp_free_i64(t2);
1.1.1.7 root 2213: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2214: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2215: }
1.1 root 2216: opn = "msub";
2217: break;
2218: case OPC_MSUBU:
1.1.1.7 root 2219: {
1.1.1.8 root 2220: TCGv_i64 t2 = tcg_temp_new_i64();
2221: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2222:
2223: tcg_gen_ext32u_tl(t0, t0);
2224: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2225: tcg_gen_extu_tl_i64(t2, t0);
2226: tcg_gen_extu_tl_i64(t3, t1);
2227: tcg_gen_mul_i64(t2, t2, t3);
2228: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2229: tcg_gen_sub_i64(t2, t3, t2);
2230: tcg_temp_free_i64(t3);
2231: tcg_gen_trunc_i64_tl(t0, t2);
2232: tcg_gen_shri_i64(t2, t2, 32);
2233: tcg_gen_trunc_i64_tl(t1, t2);
2234: tcg_temp_free_i64(t2);
1.1.1.7 root 2235: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2236: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2237: }
1.1 root 2238: opn = "msubu";
2239: break;
2240: default:
1.1.1.6 root 2241: MIPS_INVAL(opn);
1.1 root 2242: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2243: goto out;
1.1 root 2244: }
1.1.1.13 root 2245: (void)opn; /* avoid a compiler warning */
1.1 root 2246: MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1.1.1.7 root 2247: out:
2248: tcg_temp_free(t0);
2249: tcg_temp_free(t1);
1.1 root 2250: }
2251:
1.1.1.6 root 2252: static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2253: int rd, int rs, int rt)
2254: {
2255: const char *opn = "mul vr54xx";
1.1.1.8 root 2256: TCGv t0 = tcg_temp_new();
2257: TCGv t1 = tcg_temp_new();
1.1.1.6 root 2258:
1.1.1.7 root 2259: gen_load_gpr(t0, rs);
2260: gen_load_gpr(t1, rt);
1.1.1.6 root 2261:
2262: switch (opc) {
2263: case OPC_VR54XX_MULS:
1.1.1.7 root 2264: gen_helper_muls(t0, t0, t1);
1.1.1.6 root 2265: opn = "muls";
1.1.1.7 root 2266: break;
1.1.1.6 root 2267: case OPC_VR54XX_MULSU:
1.1.1.7 root 2268: gen_helper_mulsu(t0, t0, t1);
1.1.1.6 root 2269: opn = "mulsu";
1.1.1.7 root 2270: break;
1.1.1.6 root 2271: case OPC_VR54XX_MACC:
1.1.1.7 root 2272: gen_helper_macc(t0, t0, t1);
1.1.1.6 root 2273: opn = "macc";
1.1.1.7 root 2274: break;
1.1.1.6 root 2275: case OPC_VR54XX_MACCU:
1.1.1.7 root 2276: gen_helper_maccu(t0, t0, t1);
1.1.1.6 root 2277: opn = "maccu";
1.1.1.7 root 2278: break;
1.1.1.6 root 2279: case OPC_VR54XX_MSAC:
1.1.1.7 root 2280: gen_helper_msac(t0, t0, t1);
1.1.1.6 root 2281: opn = "msac";
1.1.1.7 root 2282: break;
1.1.1.6 root 2283: case OPC_VR54XX_MSACU:
1.1.1.7 root 2284: gen_helper_msacu(t0, t0, t1);
1.1.1.6 root 2285: opn = "msacu";
1.1.1.7 root 2286: break;
1.1.1.6 root 2287: case OPC_VR54XX_MULHI:
1.1.1.7 root 2288: gen_helper_mulhi(t0, t0, t1);
1.1.1.6 root 2289: opn = "mulhi";
1.1.1.7 root 2290: break;
1.1.1.6 root 2291: case OPC_VR54XX_MULHIU:
1.1.1.7 root 2292: gen_helper_mulhiu(t0, t0, t1);
1.1.1.6 root 2293: opn = "mulhiu";
1.1.1.7 root 2294: break;
1.1.1.6 root 2295: case OPC_VR54XX_MULSHI:
1.1.1.7 root 2296: gen_helper_mulshi(t0, t0, t1);
1.1.1.6 root 2297: opn = "mulshi";
1.1.1.7 root 2298: break;
1.1.1.6 root 2299: case OPC_VR54XX_MULSHIU:
1.1.1.7 root 2300: gen_helper_mulshiu(t0, t0, t1);
1.1.1.6 root 2301: opn = "mulshiu";
1.1.1.7 root 2302: break;
1.1.1.6 root 2303: case OPC_VR54XX_MACCHI:
1.1.1.7 root 2304: gen_helper_macchi(t0, t0, t1);
1.1.1.6 root 2305: opn = "macchi";
1.1.1.7 root 2306: break;
1.1.1.6 root 2307: case OPC_VR54XX_MACCHIU:
1.1.1.7 root 2308: gen_helper_macchiu(t0, t0, t1);
1.1.1.6 root 2309: opn = "macchiu";
1.1.1.7 root 2310: break;
1.1.1.6 root 2311: case OPC_VR54XX_MSACHI:
1.1.1.7 root 2312: gen_helper_msachi(t0, t0, t1);
1.1.1.6 root 2313: opn = "msachi";
1.1.1.7 root 2314: break;
1.1.1.6 root 2315: case OPC_VR54XX_MSACHIU:
1.1.1.7 root 2316: gen_helper_msachiu(t0, t0, t1);
1.1.1.6 root 2317: opn = "msachiu";
1.1.1.7 root 2318: break;
1.1.1.6 root 2319: default:
2320: MIPS_INVAL("mul vr54xx");
2321: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2322: goto out;
1.1.1.6 root 2323: }
1.1.1.7 root 2324: gen_store_gpr(t0, rd);
1.1.1.13 root 2325: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 2326: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1.1.1.7 root 2327:
2328: out:
2329: tcg_temp_free(t0);
2330: tcg_temp_free(t1);
1.1.1.6 root 2331: }
2332:
1.1.1.5 root 2333: static void gen_cl (DisasContext *ctx, uint32_t opc,
1.1 root 2334: int rd, int rs)
2335: {
1.1.1.6 root 2336: const char *opn = "CLx";
1.1.1.8 root 2337: TCGv t0;
1.1.1.7 root 2338:
1.1 root 2339: if (rd == 0) {
1.1.1.6 root 2340: /* Treat as NOP. */
1.1 root 2341: MIPS_DEBUG("NOP");
1.1.1.8 root 2342: return;
1.1 root 2343: }
1.1.1.8 root 2344: t0 = tcg_temp_new();
1.1.1.7 root 2345: gen_load_gpr(t0, rs);
1.1 root 2346: switch (opc) {
2347: case OPC_CLO:
1.1.1.8 root 2348: gen_helper_clo(cpu_gpr[rd], t0);
1.1 root 2349: opn = "clo";
2350: break;
2351: case OPC_CLZ:
1.1.1.8 root 2352: gen_helper_clz(cpu_gpr[rd], t0);
1.1 root 2353: opn = "clz";
2354: break;
1.1.1.6 root 2355: #if defined(TARGET_MIPS64)
1.1.1.5 root 2356: case OPC_DCLO:
1.1.1.8 root 2357: gen_helper_dclo(cpu_gpr[rd], t0);
1.1.1.5 root 2358: opn = "dclo";
2359: break;
2360: case OPC_DCLZ:
1.1.1.8 root 2361: gen_helper_dclz(cpu_gpr[rd], t0);
1.1.1.5 root 2362: opn = "dclz";
2363: break;
2364: #endif
1.1 root 2365: }
1.1.1.13 root 2366: (void)opn; /* avoid a compiler warning */
1.1 root 2367: MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1.1.1.7 root 2368: tcg_temp_free(t0);
1.1 root 2369: }
2370:
1.1.1.12 root 2371: /* Godson integer instructions */
2372: static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
2373: int rd, int rs, int rt)
2374: {
2375: const char *opn = "loongson";
2376: TCGv t0, t1;
2377:
2378: if (rd == 0) {
2379: /* Treat as NOP. */
2380: MIPS_DEBUG("NOP");
2381: return;
2382: }
2383:
2384: switch (opc) {
2385: case OPC_MULT_G_2E:
2386: case OPC_MULT_G_2F:
2387: case OPC_MULTU_G_2E:
2388: case OPC_MULTU_G_2F:
2389: #if defined(TARGET_MIPS64)
2390: case OPC_DMULT_G_2E:
2391: case OPC_DMULT_G_2F:
2392: case OPC_DMULTU_G_2E:
2393: case OPC_DMULTU_G_2F:
2394: #endif
2395: t0 = tcg_temp_new();
2396: t1 = tcg_temp_new();
2397: break;
2398: default:
2399: t0 = tcg_temp_local_new();
2400: t1 = tcg_temp_local_new();
2401: break;
2402: }
2403:
2404: gen_load_gpr(t0, rs);
2405: gen_load_gpr(t1, rt);
2406:
2407: switch (opc) {
2408: case OPC_MULT_G_2E:
2409: case OPC_MULT_G_2F:
2410: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2411: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2412: opn = "mult.g";
2413: break;
2414: case OPC_MULTU_G_2E:
2415: case OPC_MULTU_G_2F:
2416: tcg_gen_ext32u_tl(t0, t0);
2417: tcg_gen_ext32u_tl(t1, t1);
2418: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2419: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2420: opn = "multu.g";
2421: break;
2422: case OPC_DIV_G_2E:
2423: case OPC_DIV_G_2F:
2424: {
2425: int l1 = gen_new_label();
2426: int l2 = gen_new_label();
2427: int l3 = gen_new_label();
2428: tcg_gen_ext32s_tl(t0, t0);
2429: tcg_gen_ext32s_tl(t1, t1);
2430: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2431: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2432: tcg_gen_br(l3);
2433: gen_set_label(l1);
2434: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2435: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2436: tcg_gen_mov_tl(cpu_gpr[rd], t0);
2437: tcg_gen_br(l3);
2438: gen_set_label(l2);
2439: tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2440: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2441: gen_set_label(l3);
2442: }
2443: opn = "div.g";
2444: break;
2445: case OPC_DIVU_G_2E:
2446: case OPC_DIVU_G_2F:
2447: {
2448: int l1 = gen_new_label();
2449: int l2 = gen_new_label();
2450: tcg_gen_ext32u_tl(t0, t0);
2451: tcg_gen_ext32u_tl(t1, t1);
2452: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2453: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2454: tcg_gen_br(l2);
2455: gen_set_label(l1);
2456: tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2457: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2458: gen_set_label(l2);
2459: }
2460: opn = "divu.g";
2461: break;
2462: case OPC_MOD_G_2E:
2463: case OPC_MOD_G_2F:
2464: {
2465: int l1 = gen_new_label();
2466: int l2 = gen_new_label();
2467: int l3 = gen_new_label();
2468: tcg_gen_ext32u_tl(t0, t0);
2469: tcg_gen_ext32u_tl(t1, t1);
2470: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2471: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2472: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2473: gen_set_label(l1);
2474: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2475: tcg_gen_br(l3);
2476: gen_set_label(l2);
2477: tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2478: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2479: gen_set_label(l3);
2480: }
2481: opn = "mod.g";
2482: break;
2483: case OPC_MODU_G_2E:
2484: case OPC_MODU_G_2F:
2485: {
2486: int l1 = gen_new_label();
2487: int l2 = gen_new_label();
2488: tcg_gen_ext32u_tl(t0, t0);
2489: tcg_gen_ext32u_tl(t1, t1);
2490: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2491: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2492: tcg_gen_br(l2);
2493: gen_set_label(l1);
2494: tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2495: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2496: gen_set_label(l2);
2497: }
2498: opn = "modu.g";
2499: break;
2500: #if defined(TARGET_MIPS64)
2501: case OPC_DMULT_G_2E:
2502: case OPC_DMULT_G_2F:
2503: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2504: opn = "dmult.g";
2505: break;
2506: case OPC_DMULTU_G_2E:
2507: case OPC_DMULTU_G_2F:
2508: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2509: opn = "dmultu.g";
2510: break;
2511: case OPC_DDIV_G_2E:
2512: case OPC_DDIV_G_2F:
2513: {
2514: int l1 = gen_new_label();
2515: int l2 = gen_new_label();
2516: int l3 = gen_new_label();
2517: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2518: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2519: tcg_gen_br(l3);
2520: gen_set_label(l1);
2521: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2522: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2523: tcg_gen_mov_tl(cpu_gpr[rd], t0);
2524: tcg_gen_br(l3);
2525: gen_set_label(l2);
2526: tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2527: gen_set_label(l3);
2528: }
2529: opn = "ddiv.g";
2530: break;
2531: case OPC_DDIVU_G_2E:
2532: case OPC_DDIVU_G_2F:
2533: {
2534: int l1 = gen_new_label();
2535: int l2 = gen_new_label();
2536: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2537: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2538: tcg_gen_br(l2);
2539: gen_set_label(l1);
2540: tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2541: gen_set_label(l2);
2542: }
2543: opn = "ddivu.g";
2544: break;
2545: case OPC_DMOD_G_2E:
2546: case OPC_DMOD_G_2F:
2547: {
2548: int l1 = gen_new_label();
2549: int l2 = gen_new_label();
2550: int l3 = gen_new_label();
2551: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2552: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2553: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2554: gen_set_label(l1);
2555: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2556: tcg_gen_br(l3);
2557: gen_set_label(l2);
2558: tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2559: gen_set_label(l3);
2560: }
2561: opn = "dmod.g";
2562: break;
2563: case OPC_DMODU_G_2E:
2564: case OPC_DMODU_G_2F:
2565: {
2566: int l1 = gen_new_label();
2567: int l2 = gen_new_label();
2568: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2569: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2570: tcg_gen_br(l2);
2571: gen_set_label(l1);
2572: tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2573: gen_set_label(l2);
2574: }
2575: opn = "dmodu.g";
2576: break;
2577: #endif
2578: }
2579:
1.1.1.13 root 2580: (void)opn; /* avoid a compiler warning */
1.1.1.12 root 2581: MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2582: tcg_temp_free(t0);
2583: tcg_temp_free(t1);
2584: }
2585:
2586: /* Traps */
1.1.1.5 root 2587: static void gen_trap (DisasContext *ctx, uint32_t opc,
1.1 root 2588: int rs, int rt, int16_t imm)
2589: {
2590: int cond;
1.1.1.8 root 2591: TCGv t0 = tcg_temp_new();
2592: TCGv t1 = tcg_temp_new();
1.1 root 2593:
2594: cond = 0;
2595: /* Load needed operands */
2596: switch (opc) {
2597: case OPC_TEQ:
2598: case OPC_TGE:
2599: case OPC_TGEU:
2600: case OPC_TLT:
2601: case OPC_TLTU:
2602: case OPC_TNE:
2603: /* Compare two registers */
2604: if (rs != rt) {
1.1.1.7 root 2605: gen_load_gpr(t0, rs);
2606: gen_load_gpr(t1, rt);
1.1 root 2607: cond = 1;
2608: }
1.1.1.5 root 2609: break;
1.1 root 2610: case OPC_TEQI:
2611: case OPC_TGEI:
2612: case OPC_TGEIU:
2613: case OPC_TLTI:
2614: case OPC_TLTIU:
2615: case OPC_TNEI:
2616: /* Compare register to immediate */
2617: if (rs != 0 || imm != 0) {
1.1.1.7 root 2618: gen_load_gpr(t0, rs);
2619: tcg_gen_movi_tl(t1, (int32_t)imm);
1.1 root 2620: cond = 1;
2621: }
2622: break;
2623: }
2624: if (cond == 0) {
2625: switch (opc) {
2626: case OPC_TEQ: /* rs == rs */
2627: case OPC_TEQI: /* r0 == 0 */
2628: case OPC_TGE: /* rs >= rs */
2629: case OPC_TGEI: /* r0 >= 0 */
2630: case OPC_TGEU: /* rs >= rs unsigned */
2631: case OPC_TGEIU: /* r0 >= 0 unsigned */
2632: /* Always trap */
1.1.1.8 root 2633: generate_exception(ctx, EXCP_TRAP);
1.1 root 2634: break;
2635: case OPC_TLT: /* rs < rs */
2636: case OPC_TLTI: /* r0 < 0 */
2637: case OPC_TLTU: /* rs < rs unsigned */
2638: case OPC_TLTIU: /* r0 < 0 unsigned */
2639: case OPC_TNE: /* rs != rs */
2640: case OPC_TNEI: /* r0 != 0 */
1.1.1.6 root 2641: /* Never trap: treat as NOP. */
1.1.1.8 root 2642: break;
1.1 root 2643: }
2644: } else {
1.1.1.8 root 2645: int l1 = gen_new_label();
2646:
1.1 root 2647: switch (opc) {
2648: case OPC_TEQ:
2649: case OPC_TEQI:
1.1.1.8 root 2650: tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
1.1 root 2651: break;
2652: case OPC_TGE:
2653: case OPC_TGEI:
1.1.1.8 root 2654: tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
1.1 root 2655: break;
2656: case OPC_TGEU:
2657: case OPC_TGEIU:
1.1.1.8 root 2658: tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
1.1 root 2659: break;
2660: case OPC_TLT:
2661: case OPC_TLTI:
1.1.1.8 root 2662: tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
1.1 root 2663: break;
2664: case OPC_TLTU:
2665: case OPC_TLTIU:
1.1.1.8 root 2666: tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
1.1 root 2667: break;
2668: case OPC_TNE:
2669: case OPC_TNEI:
1.1.1.8 root 2670: tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
1.1 root 2671: break;
2672: }
1.1.1.8 root 2673: generate_exception(ctx, EXCP_TRAP);
1.1.1.7 root 2674: gen_set_label(l1);
2675: }
2676: tcg_temp_free(t0);
2677: tcg_temp_free(t1);
1.1 root 2678: }
2679:
1.1.1.7 root 2680: static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1.1.1.2 root 2681: {
2682: TranslationBlock *tb;
2683: tb = ctx->tb;
1.1.1.9 root 2684: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2685: likely(!ctx->singlestep_enabled)) {
1.1.1.7 root 2686: tcg_gen_goto_tb(n);
1.1.1.6 root 2687: gen_save_pc(dest);
1.1.1.14 root 2688: tcg_gen_exit_tb((tcg_target_long)tb + n);
1.1.1.2 root 2689: } else {
1.1.1.6 root 2690: gen_save_pc(dest);
1.1.1.9 root 2691: if (ctx->singlestep_enabled) {
2692: save_cpu_state(ctx, 0);
2693: gen_helper_0i(raise_exception, EXCP_DEBUG);
2694: }
1.1.1.7 root 2695: tcg_gen_exit_tb(0);
1.1.1.2 root 2696: }
2697: }
2698:
1.1 root 2699: /* Branches (before delay slot) */
1.1.1.5 root 2700: static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1.1.1.12 root 2701: int insn_bytes,
1.1 root 2702: int rs, int rt, int32_t offset)
2703: {
1.1.1.7 root 2704: target_ulong btgt = -1;
1.1.1.6 root 2705: int blink = 0;
1.1.1.7 root 2706: int bcond_compute = 0;
1.1.1.8 root 2707: TCGv t0 = tcg_temp_new();
2708: TCGv t1 = tcg_temp_new();
1.1 root 2709:
1.1.1.6 root 2710: if (ctx->hflags & MIPS_HFLAG_BMASK) {
2711: #ifdef MIPS_DEBUG_DISAS
1.1.1.7 root 2712: LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
1.1.1.6 root 2713: #endif
2714: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2715: goto out;
1.1.1.6 root 2716: }
2717:
2718: /* Load needed operands */
2719: switch (opc) {
2720: case OPC_BEQ:
2721: case OPC_BEQL:
2722: case OPC_BNE:
2723: case OPC_BNEL:
1.1 root 2724: /* Compare two registers */
2725: if (rs != rt) {
1.1.1.7 root 2726: gen_load_gpr(t0, rs);
2727: gen_load_gpr(t1, rt);
2728: bcond_compute = 1;
1.1 root 2729: }
1.1.1.12 root 2730: btgt = ctx->pc + insn_bytes + offset;
1.1 root 2731: break;
2732: case OPC_BGEZ:
2733: case OPC_BGEZAL:
1.1.1.12 root 2734: case OPC_BGEZALS:
1.1 root 2735: case OPC_BGEZALL:
2736: case OPC_BGEZL:
2737: case OPC_BGTZ:
2738: case OPC_BGTZL:
2739: case OPC_BLEZ:
2740: case OPC_BLEZL:
2741: case OPC_BLTZ:
2742: case OPC_BLTZAL:
1.1.1.12 root 2743: case OPC_BLTZALS:
1.1 root 2744: case OPC_BLTZALL:
2745: case OPC_BLTZL:
2746: /* Compare to zero */
2747: if (rs != 0) {
1.1.1.7 root 2748: gen_load_gpr(t0, rs);
2749: bcond_compute = 1;
1.1 root 2750: }
1.1.1.12 root 2751: btgt = ctx->pc + insn_bytes + offset;
1.1 root 2752: break;
2753: case OPC_J:
2754: case OPC_JAL:
1.1.1.12 root 2755: case OPC_JALX:
2756: case OPC_JALS:
2757: case OPC_JALXS:
1.1 root 2758: /* Jump to immediate */
1.1.1.12 root 2759: btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
1.1 root 2760: break;
2761: case OPC_JR:
2762: case OPC_JALR:
1.1.1.12 root 2763: case OPC_JALRC:
2764: case OPC_JALRS:
1.1 root 2765: /* Jump to register */
1.1.1.5 root 2766: if (offset != 0 && offset != 16) {
2767: /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1.1.1.6 root 2768: others are reserved. */
2769: MIPS_INVAL("jump hint");
1.1 root 2770: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2771: goto out;
1.1 root 2772: }
1.1.1.7 root 2773: gen_load_gpr(btarget, rs);
1.1 root 2774: break;
2775: default:
2776: MIPS_INVAL("branch/jump");
2777: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2778: goto out;
1.1 root 2779: }
1.1.1.7 root 2780: if (bcond_compute == 0) {
1.1 root 2781: /* No condition to be computed */
2782: switch (opc) {
2783: case OPC_BEQ: /* rx == rx */
2784: case OPC_BEQL: /* rx == rx likely */
2785: case OPC_BGEZ: /* 0 >= 0 */
2786: case OPC_BGEZL: /* 0 >= 0 likely */
2787: case OPC_BLEZ: /* 0 <= 0 */
2788: case OPC_BLEZL: /* 0 <= 0 likely */
2789: /* Always take */
1.1.1.2 root 2790: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 2791: MIPS_DEBUG("balways");
2792: break;
1.1.1.12 root 2793: case OPC_BGEZALS:
1.1 root 2794: case OPC_BGEZAL: /* 0 >= 0 */
2795: case OPC_BGEZALL: /* 0 >= 0 likely */
1.1.1.12 root 2796: ctx->hflags |= (opc == OPC_BGEZALS
2797: ? MIPS_HFLAG_BDS16
2798: : MIPS_HFLAG_BDS32);
1.1 root 2799: /* Always take and link */
2800: blink = 31;
1.1.1.2 root 2801: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 2802: MIPS_DEBUG("balways and link");
2803: break;
2804: case OPC_BNE: /* rx != rx */
2805: case OPC_BGTZ: /* 0 > 0 */
2806: case OPC_BLTZ: /* 0 < 0 */
1.1.1.6 root 2807: /* Treat as NOP. */
1.1 root 2808: MIPS_DEBUG("bnever (NOP)");
1.1.1.7 root 2809: goto out;
1.1.1.12 root 2810: case OPC_BLTZALS:
1.1.1.2 root 2811: case OPC_BLTZAL: /* 0 < 0 */
1.1.1.12 root 2812: ctx->hflags |= (opc == OPC_BLTZALS
2813: ? MIPS_HFLAG_BDS16
2814: : MIPS_HFLAG_BDS32);
2815: /* Handle as an unconditional branch to get correct delay
2816: slot checking. */
2817: blink = 31;
2818: btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
2819: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.6 root 2820: MIPS_DEBUG("bnever and link");
1.1.1.12 root 2821: break;
1.1.1.2 root 2822: case OPC_BLTZALL: /* 0 < 0 likely */
1.1.1.8 root 2823: tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
1.1.1.6 root 2824: /* Skip the instruction in the delay slot */
2825: MIPS_DEBUG("bnever, link and skip");
2826: ctx->pc += 4;
1.1.1.7 root 2827: goto out;
1.1 root 2828: case OPC_BNEL: /* rx != rx likely */
2829: case OPC_BGTZL: /* 0 > 0 likely */
2830: case OPC_BLTZL: /* 0 < 0 likely */
2831: /* Skip the instruction in the delay slot */
2832: MIPS_DEBUG("bnever and skip");
1.1.1.6 root 2833: ctx->pc += 4;
1.1.1.7 root 2834: goto out;
1.1 root 2835: case OPC_J:
1.1.1.2 root 2836: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.7 root 2837: MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
1.1 root 2838: break;
1.1.1.12 root 2839: case OPC_JALXS:
2840: case OPC_JALX:
2841: ctx->hflags |= MIPS_HFLAG_BX;
2842: /* Fallthrough */
2843: case OPC_JALS:
1.1 root 2844: case OPC_JAL:
2845: blink = 31;
1.1.1.2 root 2846: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.12 root 2847: ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
2848: ? MIPS_HFLAG_BDS16
2849: : MIPS_HFLAG_BDS32);
1.1.1.7 root 2850: MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
1.1 root 2851: break;
2852: case OPC_JR:
1.1.1.2 root 2853: ctx->hflags |= MIPS_HFLAG_BR;
1.1.1.12 root 2854: if (insn_bytes == 4)
2855: ctx->hflags |= MIPS_HFLAG_BDS32;
1.1 root 2856: MIPS_DEBUG("jr %s", regnames[rs]);
2857: break;
1.1.1.12 root 2858: case OPC_JALRS:
1.1 root 2859: case OPC_JALR:
1.1.1.12 root 2860: case OPC_JALRC:
1.1 root 2861: blink = rt;
1.1.1.2 root 2862: ctx->hflags |= MIPS_HFLAG_BR;
1.1.1.12 root 2863: ctx->hflags |= (opc == OPC_JALRS
2864: ? MIPS_HFLAG_BDS16
2865: : MIPS_HFLAG_BDS32);
1.1 root 2866: MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2867: break;
2868: default:
2869: MIPS_INVAL("branch/jump");
2870: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2871: goto out;
1.1 root 2872: }
2873: } else {
2874: switch (opc) {
2875: case OPC_BEQ:
1.1.1.12 root 2876: tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
1.1.1.6 root 2877: MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2878: regnames[rs], regnames[rt], btgt);
1.1 root 2879: goto not_likely;
2880: case OPC_BEQL:
1.1.1.12 root 2881: tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
1.1.1.6 root 2882: MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2883: regnames[rs], regnames[rt], btgt);
1.1 root 2884: goto likely;
2885: case OPC_BNE:
1.1.1.12 root 2886: tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
1.1.1.6 root 2887: MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2888: regnames[rs], regnames[rt], btgt);
1.1 root 2889: goto not_likely;
2890: case OPC_BNEL:
1.1.1.12 root 2891: tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
1.1.1.6 root 2892: MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2893: regnames[rs], regnames[rt], btgt);
1.1 root 2894: goto likely;
2895: case OPC_BGEZ:
1.1.1.12 root 2896: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2897: MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2898: goto not_likely;
2899: case OPC_BGEZL:
1.1.1.12 root 2900: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2901: MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2902: goto likely;
1.1.1.12 root 2903: case OPC_BGEZALS:
1.1 root 2904: case OPC_BGEZAL:
1.1.1.12 root 2905: ctx->hflags |= (opc == OPC_BGEZALS
2906: ? MIPS_HFLAG_BDS16
2907: : MIPS_HFLAG_BDS32);
2908: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2909: MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2910: blink = 31;
2911: goto not_likely;
2912: case OPC_BGEZALL:
1.1.1.12 root 2913: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1 root 2914: blink = 31;
1.1.1.7 root 2915: MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2916: goto likely;
2917: case OPC_BGTZ:
1.1.1.12 root 2918: tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
1.1.1.7 root 2919: MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2920: goto not_likely;
2921: case OPC_BGTZL:
1.1.1.12 root 2922: tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
1.1.1.7 root 2923: MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2924: goto likely;
2925: case OPC_BLEZ:
1.1.1.12 root 2926: tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
1.1.1.7 root 2927: MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2928: goto not_likely;
2929: case OPC_BLEZL:
1.1.1.12 root 2930: tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
1.1.1.7 root 2931: MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2932: goto likely;
2933: case OPC_BLTZ:
1.1.1.12 root 2934: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1.1.7 root 2935: MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2936: goto not_likely;
2937: case OPC_BLTZL:
1.1.1.12 root 2938: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1.1.7 root 2939: MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2940: goto likely;
1.1.1.12 root 2941: case OPC_BLTZALS:
1.1 root 2942: case OPC_BLTZAL:
1.1.1.12 root 2943: ctx->hflags |= (opc == OPC_BLTZALS
2944: ? MIPS_HFLAG_BDS16
2945: : MIPS_HFLAG_BDS32);
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("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2949: not_likely:
1.1.1.2 root 2950: ctx->hflags |= MIPS_HFLAG_BC;
1.1 root 2951: break;
2952: case OPC_BLTZALL:
1.1.1.12 root 2953: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1 root 2954: blink = 31;
1.1.1.7 root 2955: MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2956: likely:
1.1.1.2 root 2957: ctx->hflags |= MIPS_HFLAG_BL;
1.1 root 2958: break;
1.1.1.6 root 2959: default:
2960: MIPS_INVAL("conditional branch/jump");
2961: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2962: goto out;
1.1 root 2963: }
2964: }
1.1.1.6 root 2965: MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
1.1.1.7 root 2966: blink, ctx->hflags, btgt);
1.1.1.6 root 2967:
1.1.1.7 root 2968: ctx->btarget = btgt;
1.1 root 2969: if (blink > 0) {
1.1.1.12 root 2970: int post_delay = insn_bytes;
2971: int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2972:
2973: if (opc != OPC_JALRC)
2974: post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2975:
2976: tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
1.1 root 2977: }
1.1.1.7 root 2978:
2979: out:
1.1.1.12 root 2980: if (insn_bytes == 2)
2981: ctx->hflags |= MIPS_HFLAG_B16;
1.1.1.7 root 2982: tcg_temp_free(t0);
2983: tcg_temp_free(t1);
1.1 root 2984: }
2985:
1.1.1.5 root 2986: /* special3 bitfield operations */
2987: static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1.1.1.7 root 2988: int rs, int lsb, int msb)
1.1 root 2989: {
1.1.1.7 root 2990: TCGv t0 = tcg_temp_new();
2991: TCGv t1 = tcg_temp_new();
2992: target_ulong mask;
2993:
2994: gen_load_gpr(t1, rs);
1.1.1.5 root 2995: switch (opc) {
2996: case OPC_EXT:
2997: if (lsb + msb > 31)
2998: goto fail;
1.1.1.7 root 2999: tcg_gen_shri_tl(t0, t1, lsb);
3000: if (msb != 31) {
3001: tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3002: } else {
3003: tcg_gen_ext32s_tl(t0, t0);
3004: }
1.1.1.5 root 3005: break;
1.1.1.6 root 3006: #if defined(TARGET_MIPS64)
1.1.1.5 root 3007: case OPC_DEXTM:
1.1.1.7 root 3008: tcg_gen_shri_tl(t0, t1, lsb);
3009: if (msb != 31) {
3010: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3011: }
1.1.1.5 root 3012: break;
3013: case OPC_DEXTU:
1.1.1.7 root 3014: tcg_gen_shri_tl(t0, t1, lsb + 32);
3015: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
1.1.1.5 root 3016: break;
3017: case OPC_DEXT:
1.1.1.7 root 3018: tcg_gen_shri_tl(t0, t1, lsb);
3019: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
1.1.1.5 root 3020: break;
1.1.1.6 root 3021: #endif
1.1.1.5 root 3022: case OPC_INS:
3023: if (lsb > msb)
3024: goto fail;
1.1.1.7 root 3025: mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
3026: gen_load_gpr(t0, rt);
3027: tcg_gen_andi_tl(t0, t0, ~mask);
3028: tcg_gen_shli_tl(t1, t1, lsb);
3029: tcg_gen_andi_tl(t1, t1, mask);
3030: tcg_gen_or_tl(t0, t0, t1);
3031: tcg_gen_ext32s_tl(t0, t0);
1.1.1.5 root 3032: break;
1.1.1.6 root 3033: #if defined(TARGET_MIPS64)
1.1.1.5 root 3034: case OPC_DINSM:
3035: if (lsb > msb)
3036: goto fail;
1.1.1.7 root 3037: mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
3038: gen_load_gpr(t0, rt);
3039: tcg_gen_andi_tl(t0, t0, ~mask);
3040: tcg_gen_shli_tl(t1, t1, lsb);
3041: tcg_gen_andi_tl(t1, t1, mask);
3042: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3043: break;
3044: case OPC_DINSU:
3045: if (lsb > msb)
3046: goto fail;
1.1.1.11 root 3047: mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
1.1.1.7 root 3048: gen_load_gpr(t0, rt);
3049: tcg_gen_andi_tl(t0, t0, ~mask);
3050: tcg_gen_shli_tl(t1, t1, lsb + 32);
3051: tcg_gen_andi_tl(t1, t1, mask);
3052: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3053: break;
3054: case OPC_DINS:
3055: if (lsb > msb)
3056: goto fail;
1.1.1.7 root 3057: gen_load_gpr(t0, rt);
3058: mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3059: gen_load_gpr(t0, rt);
3060: tcg_gen_andi_tl(t0, t0, ~mask);
3061: tcg_gen_shli_tl(t1, t1, lsb);
3062: tcg_gen_andi_tl(t1, t1, mask);
3063: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3064: break;
1.1.1.6 root 3065: #endif
1.1.1.5 root 3066: default:
3067: fail:
3068: MIPS_INVAL("bitops");
3069: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 3070: tcg_temp_free(t0);
3071: tcg_temp_free(t1);
1.1 root 3072: return;
3073: }
1.1.1.7 root 3074: gen_store_gpr(t0, rt);
3075: tcg_temp_free(t0);
3076: tcg_temp_free(t1);
3077: }
3078:
3079: static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3080: {
1.1.1.8 root 3081: TCGv t0;
1.1.1.7 root 3082:
1.1.1.8 root 3083: if (rd == 0) {
3084: /* If no destination, treat it as a NOP. */
3085: MIPS_DEBUG("NOP");
3086: return;
3087: }
3088:
3089: t0 = tcg_temp_new();
3090: gen_load_gpr(t0, rt);
1.1.1.7 root 3091: switch (op2) {
3092: case OPC_WSBH:
1.1.1.8 root 3093: {
3094: TCGv t1 = tcg_temp_new();
3095:
3096: tcg_gen_shri_tl(t1, t0, 8);
3097: tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3098: tcg_gen_shli_tl(t0, t0, 8);
3099: tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3100: tcg_gen_or_tl(t0, t0, t1);
3101: tcg_temp_free(t1);
3102: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3103: }
1.1.1.7 root 3104: break;
3105: case OPC_SEB:
1.1.1.8 root 3106: tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
1.1.1.7 root 3107: break;
3108: case OPC_SEH:
1.1.1.8 root 3109: tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
1.1.1.7 root 3110: break;
3111: #if defined(TARGET_MIPS64)
3112: case OPC_DSBH:
1.1.1.8 root 3113: {
3114: TCGv t1 = tcg_temp_new();
3115:
3116: tcg_gen_shri_tl(t1, t0, 8);
3117: tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3118: tcg_gen_shli_tl(t0, t0, 8);
3119: tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3120: tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3121: tcg_temp_free(t1);
3122: }
1.1.1.7 root 3123: break;
3124: case OPC_DSHD:
1.1.1.8 root 3125: {
3126: TCGv t1 = tcg_temp_new();
3127:
3128: tcg_gen_shri_tl(t1, t0, 16);
3129: tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3130: tcg_gen_shli_tl(t0, t0, 16);
3131: tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3132: tcg_gen_or_tl(t0, t0, t1);
3133: tcg_gen_shri_tl(t1, t0, 32);
3134: tcg_gen_shli_tl(t0, t0, 32);
3135: tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3136: tcg_temp_free(t1);
3137: }
1.1.1.7 root 3138: break;
3139: #endif
3140: default:
3141: MIPS_INVAL("bsfhl");
3142: generate_exception(ctx, EXCP_RI);
3143: tcg_temp_free(t0);
3144: return;
3145: }
3146: tcg_temp_free(t0);
1.1.1.5 root 3147: }
1.1.1.4 root 3148:
1.1.1.7 root 3149: #ifndef CONFIG_USER_ONLY
1.1.1.5 root 3150: /* CP0 (MMU and control) */
1.1.1.8 root 3151: static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
1.1.1.7 root 3152: {
1.1.1.8 root 3153: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 3154:
1.1.1.8 root 3155: tcg_gen_ld_i32(t0, cpu_env, off);
3156: tcg_gen_ext_i32_tl(arg, t0);
3157: tcg_temp_free_i32(t0);
1.1.1.7 root 3158: }
3159:
1.1.1.8 root 3160: static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
1.1.1.7 root 3161: {
1.1.1.8 root 3162: tcg_gen_ld_tl(arg, cpu_env, off);
3163: tcg_gen_ext32s_tl(arg, arg);
1.1.1.7 root 3164: }
3165:
1.1.1.8 root 3166: static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
1.1.1.7 root 3167: {
1.1.1.8 root 3168: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 3169:
1.1.1.8 root 3170: tcg_gen_trunc_tl_i32(t0, arg);
3171: tcg_gen_st_i32(t0, cpu_env, off);
3172: tcg_temp_free_i32(t0);
1.1.1.7 root 3173: }
3174:
1.1.1.8 root 3175: static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
1.1.1.7 root 3176: {
1.1.1.8 root 3177: tcg_gen_ext32s_tl(arg, arg);
3178: tcg_gen_st_tl(arg, cpu_env, off);
1.1.1.7 root 3179: }
3180:
1.1.1.8 root 3181: static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 3182: {
3183: const char *rn = "invalid";
3184:
1.1.1.6 root 3185: if (sel != 0)
3186: check_insn(env, ctx, ISA_MIPS32);
3187:
1.1.1.5 root 3188: switch (reg) {
3189: case 0:
3190: switch (sel) {
3191: case 0:
1.1.1.8 root 3192: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
1.1.1.5 root 3193: rn = "Index";
3194: break;
3195: case 1:
1.1.1.6 root 3196: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3197: gen_helper_mfc0_mvpcontrol(arg);
1.1.1.5 root 3198: rn = "MVPControl";
1.1.1.6 root 3199: break;
1.1.1.5 root 3200: case 2:
1.1.1.6 root 3201: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3202: gen_helper_mfc0_mvpconf0(arg);
1.1.1.5 root 3203: rn = "MVPConf0";
1.1.1.6 root 3204: break;
1.1.1.5 root 3205: case 3:
1.1.1.6 root 3206: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3207: gen_helper_mfc0_mvpconf1(arg);
1.1.1.5 root 3208: rn = "MVPConf1";
1.1.1.6 root 3209: break;
1.1.1.5 root 3210: default:
3211: goto die;
1.1 root 3212: }
3213: break;
1.1.1.5 root 3214: case 1:
3215: switch (sel) {
3216: case 0:
1.1.1.8 root 3217: gen_helper_mfc0_random(arg);
1.1.1.5 root 3218: rn = "Random";
1.1.1.6 root 3219: break;
1.1.1.5 root 3220: case 1:
1.1.1.6 root 3221: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3222: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
1.1.1.5 root 3223: rn = "VPEControl";
1.1.1.6 root 3224: break;
1.1.1.5 root 3225: case 2:
1.1.1.6 root 3226: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3227: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
1.1.1.5 root 3228: rn = "VPEConf0";
1.1.1.6 root 3229: break;
1.1.1.5 root 3230: case 3:
1.1.1.6 root 3231: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3232: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
1.1.1.5 root 3233: rn = "VPEConf1";
1.1.1.6 root 3234: break;
1.1.1.5 root 3235: case 4:
1.1.1.6 root 3236: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3237: gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
1.1.1.5 root 3238: rn = "YQMask";
1.1.1.6 root 3239: break;
1.1.1.5 root 3240: case 5:
1.1.1.6 root 3241: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3242: gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 3243: rn = "VPESchedule";
1.1.1.6 root 3244: break;
1.1.1.5 root 3245: case 6:
1.1.1.6 root 3246: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3247: gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 3248: rn = "VPEScheFBack";
1.1.1.6 root 3249: break;
1.1.1.5 root 3250: case 7:
1.1.1.6 root 3251: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3252: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
1.1.1.5 root 3253: rn = "VPEOpt";
1.1.1.6 root 3254: break;
1.1.1.5 root 3255: default:
3256: goto die;
3257: }
1.1 root 3258: break;
1.1.1.5 root 3259: case 2:
3260: switch (sel) {
3261: case 0:
1.1.1.8 root 3262: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
3263: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3264: rn = "EntryLo0";
3265: break;
3266: case 1:
3267: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3268: gen_helper_mfc0_tcstatus(arg);
1.1.1.6 root 3269: rn = "TCStatus";
3270: break;
3271: case 2:
3272: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3273: gen_helper_mfc0_tcbind(arg);
1.1.1.6 root 3274: rn = "TCBind";
3275: break;
1.1.1.5 root 3276: case 3:
1.1.1.6 root 3277: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3278: gen_helper_mfc0_tcrestart(arg);
1.1.1.6 root 3279: rn = "TCRestart";
3280: break;
1.1.1.5 root 3281: case 4:
1.1.1.6 root 3282: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3283: gen_helper_mfc0_tchalt(arg);
1.1.1.6 root 3284: rn = "TCHalt";
3285: break;
1.1.1.5 root 3286: case 5:
1.1.1.6 root 3287: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3288: gen_helper_mfc0_tccontext(arg);
1.1.1.6 root 3289: rn = "TCContext";
3290: break;
1.1.1.5 root 3291: case 6:
1.1.1.6 root 3292: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3293: gen_helper_mfc0_tcschedule(arg);
1.1.1.6 root 3294: rn = "TCSchedule";
3295: break;
1.1.1.5 root 3296: case 7:
1.1.1.6 root 3297: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3298: gen_helper_mfc0_tcschefback(arg);
1.1.1.6 root 3299: rn = "TCScheFBack";
3300: break;
1.1.1.5 root 3301: default:
3302: goto die;
3303: }
1.1 root 3304: break;
1.1.1.5 root 3305: case 3:
3306: switch (sel) {
3307: case 0:
1.1.1.8 root 3308: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
3309: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3310: rn = "EntryLo1";
3311: break;
1.1.1.5 root 3312: default:
3313: goto die;
1.1.1.6 root 3314: }
1.1 root 3315: break;
1.1.1.5 root 3316: case 4:
3317: switch (sel) {
3318: case 0:
1.1.1.8 root 3319: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3320: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3321: rn = "Context";
3322: break;
3323: case 1:
1.1.1.8 root 3324: // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 3325: rn = "ContextConfig";
3326: // break;
1.1.1.5 root 3327: default:
3328: goto die;
1.1.1.6 root 3329: }
1.1 root 3330: break;
1.1.1.5 root 3331: case 5:
3332: switch (sel) {
3333: case 0:
1.1.1.8 root 3334: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
1.1.1.6 root 3335: rn = "PageMask";
3336: break;
3337: case 1:
3338: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3339: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
1.1.1.6 root 3340: rn = "PageGrain";
3341: break;
1.1.1.5 root 3342: default:
3343: goto die;
1.1.1.6 root 3344: }
1.1 root 3345: break;
1.1.1.5 root 3346: case 6:
3347: switch (sel) {
3348: case 0:
1.1.1.8 root 3349: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
1.1.1.6 root 3350: rn = "Wired";
3351: break;
3352: case 1:
3353: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3354: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
1.1.1.6 root 3355: rn = "SRSConf0";
3356: break;
3357: case 2:
3358: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3359: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
1.1.1.6 root 3360: rn = "SRSConf1";
3361: break;
1.1.1.5 root 3362: case 3:
1.1.1.6 root 3363: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3364: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
1.1.1.6 root 3365: rn = "SRSConf2";
3366: break;
1.1.1.5 root 3367: case 4:
1.1.1.6 root 3368: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3369: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
1.1.1.6 root 3370: rn = "SRSConf3";
3371: break;
1.1.1.5 root 3372: case 5:
1.1.1.6 root 3373: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3374: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
1.1.1.6 root 3375: rn = "SRSConf4";
3376: break;
1.1.1.5 root 3377: default:
3378: goto die;
1.1.1.6 root 3379: }
1.1 root 3380: break;
1.1.1.5 root 3381: case 7:
3382: switch (sel) {
3383: case 0:
1.1.1.6 root 3384: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3385: gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
1.1.1.6 root 3386: rn = "HWREna";
3387: break;
1.1.1.5 root 3388: default:
3389: goto die;
1.1.1.6 root 3390: }
1.1 root 3391: break;
1.1.1.5 root 3392: case 8:
3393: switch (sel) {
3394: case 0:
1.1.1.8 root 3395: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3396: tcg_gen_ext32s_tl(arg, arg);
1.1.1.7 root 3397: rn = "BadVAddr";
1.1.1.6 root 3398: break;
1.1.1.5 root 3399: default:
3400: goto die;
3401: }
1.1.1.2 root 3402: break;
1.1.1.5 root 3403: case 9:
3404: switch (sel) {
3405: case 0:
1.1.1.7 root 3406: /* Mark as an IO operation because we read the time. */
3407: if (use_icount)
3408: gen_io_start();
1.1.1.8 root 3409: gen_helper_mfc0_count(arg);
1.1.1.7 root 3410: if (use_icount) {
3411: gen_io_end();
3412: }
1.1.1.13 root 3413: /* Break the TB to be able to take timer interrupts immediately
3414: after reading count. */
3415: ctx->bstate = BS_STOP;
1.1.1.6 root 3416: rn = "Count";
3417: break;
3418: /* 6,7 are implementation dependent */
1.1.1.5 root 3419: default:
3420: goto die;
1.1.1.6 root 3421: }
1.1.1.5 root 3422: break;
3423: case 10:
3424: switch (sel) {
3425: case 0:
1.1.1.8 root 3426: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3427: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3428: rn = "EntryHi";
3429: break;
1.1.1.5 root 3430: default:
3431: goto die;
1.1.1.6 root 3432: }
1.1.1.5 root 3433: break;
3434: case 11:
3435: switch (sel) {
3436: case 0:
1.1.1.8 root 3437: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
1.1.1.6 root 3438: rn = "Compare";
3439: break;
3440: /* 6,7 are implementation dependent */
1.1.1.5 root 3441: default:
3442: goto die;
1.1.1.6 root 3443: }
1.1.1.5 root 3444: break;
3445: case 12:
3446: switch (sel) {
3447: case 0:
1.1.1.8 root 3448: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
1.1.1.6 root 3449: rn = "Status";
3450: break;
3451: case 1:
3452: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3453: gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
1.1.1.6 root 3454: rn = "IntCtl";
3455: break;
3456: case 2:
3457: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3458: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
1.1.1.6 root 3459: rn = "SRSCtl";
3460: break;
1.1.1.5 root 3461: case 3:
1.1.1.6 root 3462: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3463: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 3464: rn = "SRSMap";
3465: break;
1.1.1.5 root 3466: default:
3467: goto die;
3468: }
3469: break;
3470: case 13:
3471: switch (sel) {
3472: case 0:
1.1.1.8 root 3473: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
1.1.1.6 root 3474: rn = "Cause";
3475: break;
1.1.1.5 root 3476: default:
3477: goto die;
3478: }
3479: break;
3480: case 14:
3481: switch (sel) {
3482: case 0:
1.1.1.8 root 3483: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3484: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3485: rn = "EPC";
3486: break;
1.1.1.5 root 3487: default:
3488: goto die;
1.1.1.6 root 3489: }
1.1.1.5 root 3490: break;
3491: case 15:
3492: switch (sel) {
3493: case 0:
1.1.1.8 root 3494: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
1.1.1.6 root 3495: rn = "PRid";
3496: break;
3497: case 1:
3498: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3499: gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
1.1.1.6 root 3500: rn = "EBase";
3501: break;
1.1.1.5 root 3502: default:
3503: goto die;
3504: }
3505: break;
3506: case 16:
3507: switch (sel) {
3508: case 0:
1.1.1.8 root 3509: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
1.1.1.5 root 3510: rn = "Config";
3511: break;
3512: case 1:
1.1.1.8 root 3513: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
1.1.1.5 root 3514: rn = "Config1";
3515: break;
3516: case 2:
1.1.1.8 root 3517: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
1.1.1.5 root 3518: rn = "Config2";
3519: break;
3520: case 3:
1.1.1.8 root 3521: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
1.1.1.5 root 3522: rn = "Config3";
3523: break;
1.1.1.6 root 3524: /* 4,5 are reserved */
3525: /* 6,7 are implementation dependent */
3526: case 6:
1.1.1.8 root 3527: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
1.1.1.6 root 3528: rn = "Config6";
3529: break;
3530: case 7:
1.1.1.8 root 3531: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
1.1.1.6 root 3532: rn = "Config7";
3533: break;
1.1.1.5 root 3534: default:
3535: goto die;
1.1 root 3536: }
1.1.1.4 root 3537: break;
1.1.1.5 root 3538: case 17:
3539: switch (sel) {
3540: case 0:
1.1.1.8 root 3541: gen_helper_mfc0_lladdr(arg);
1.1.1.6 root 3542: rn = "LLAddr";
3543: break;
1.1.1.5 root 3544: default:
3545: goto die;
3546: }
1.1.1.4 root 3547: break;
1.1.1.5 root 3548: case 18:
3549: switch (sel) {
1.1.1.6 root 3550: case 0 ... 7:
1.1.1.8 root 3551: gen_helper_1i(mfc0_watchlo, arg, sel);
1.1.1.6 root 3552: rn = "WatchLo";
3553: break;
1.1.1.5 root 3554: default:
3555: goto die;
3556: }
1.1.1.4 root 3557: break;
1.1.1.5 root 3558: case 19:
3559: switch (sel) {
1.1.1.6 root 3560: case 0 ...7:
1.1.1.8 root 3561: gen_helper_1i(mfc0_watchhi, arg, sel);
1.1.1.6 root 3562: rn = "WatchHi";
3563: break;
1.1.1.5 root 3564: default:
3565: goto die;
3566: }
1.1.1.4 root 3567: break;
1.1.1.5 root 3568: case 20:
3569: switch (sel) {
3570: case 0:
1.1.1.6 root 3571: #if defined(TARGET_MIPS64)
3572: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 3573: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3574: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3575: rn = "XContext";
3576: break;
3577: #endif
1.1.1.5 root 3578: default:
3579: goto die;
1.1.1.4 root 3580: }
3581: break;
1.1.1.5 root 3582: case 21:
3583: /* Officially reserved, but sel 0 is used for R1x000 framemask */
3584: switch (sel) {
3585: case 0:
1.1.1.8 root 3586: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
1.1.1.6 root 3587: rn = "Framemask";
3588: break;
1.1.1.5 root 3589: default:
3590: goto die;
1.1.1.4 root 3591: }
3592: break;
1.1.1.5 root 3593: case 22:
1.1.1.8 root 3594: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 3595: rn = "'Diagnostic"; /* implementation dependent */
3596: break;
1.1.1.5 root 3597: case 23:
3598: switch (sel) {
3599: case 0:
1.1.1.8 root 3600: gen_helper_mfc0_debug(arg); /* EJTAG support */
1.1.1.6 root 3601: rn = "Debug";
3602: break;
3603: case 1:
1.1.1.8 root 3604: // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 3605: rn = "TraceControl";
3606: // break;
3607: case 2:
1.1.1.8 root 3608: // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 3609: rn = "TraceControl2";
3610: // break;
1.1.1.5 root 3611: case 3:
1.1.1.8 root 3612: // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 3613: rn = "UserTraceData";
3614: // break;
1.1.1.5 root 3615: case 4:
1.1.1.8 root 3616: // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 3617: rn = "TraceBPC";
3618: // break;
1.1.1.5 root 3619: default:
3620: goto die;
1.1.1.4 root 3621: }
1.1.1.5 root 3622: break;
3623: case 24:
3624: switch (sel) {
3625: case 0:
1.1.1.7 root 3626: /* EJTAG support */
1.1.1.8 root 3627: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3628: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3629: rn = "DEPC";
3630: break;
1.1.1.5 root 3631: default:
3632: goto die;
3633: }
3634: break;
3635: case 25:
3636: switch (sel) {
3637: case 0:
1.1.1.8 root 3638: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
1.1.1.6 root 3639: rn = "Performance0";
1.1.1.5 root 3640: break;
3641: case 1:
1.1.1.8 root 3642: // gen_helper_mfc0_performance1(arg);
1.1.1.6 root 3643: rn = "Performance1";
3644: // break;
1.1.1.5 root 3645: case 2:
1.1.1.8 root 3646: // gen_helper_mfc0_performance2(arg);
1.1.1.6 root 3647: rn = "Performance2";
3648: // break;
1.1.1.5 root 3649: case 3:
1.1.1.8 root 3650: // gen_helper_mfc0_performance3(arg);
1.1.1.6 root 3651: rn = "Performance3";
3652: // break;
1.1.1.5 root 3653: case 4:
1.1.1.8 root 3654: // gen_helper_mfc0_performance4(arg);
1.1.1.6 root 3655: rn = "Performance4";
3656: // break;
1.1.1.5 root 3657: case 5:
1.1.1.8 root 3658: // gen_helper_mfc0_performance5(arg);
1.1.1.6 root 3659: rn = "Performance5";
3660: // break;
1.1.1.5 root 3661: case 6:
1.1.1.8 root 3662: // gen_helper_mfc0_performance6(arg);
1.1.1.6 root 3663: rn = "Performance6";
3664: // break;
1.1.1.5 root 3665: case 7:
1.1.1.8 root 3666: // gen_helper_mfc0_performance7(arg);
1.1.1.6 root 3667: rn = "Performance7";
3668: // break;
1.1.1.5 root 3669: default:
3670: goto die;
3671: }
3672: break;
3673: case 26:
1.1.1.8 root 3674: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.7 root 3675: rn = "ECC";
3676: break;
1.1.1.5 root 3677: case 27:
3678: switch (sel) {
3679: case 0 ... 3:
1.1.1.8 root 3680: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 3681: rn = "CacheErr";
3682: break;
1.1.1.5 root 3683: default:
3684: goto die;
3685: }
3686: break;
3687: case 28:
3688: switch (sel) {
3689: case 0:
3690: case 2:
3691: case 4:
3692: case 6:
1.1.1.8 root 3693: gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
1.1.1.5 root 3694: rn = "TagLo";
3695: break;
3696: case 1:
3697: case 3:
3698: case 5:
3699: case 7:
1.1.1.8 root 3700: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
1.1.1.5 root 3701: rn = "DataLo";
3702: break;
3703: default:
3704: goto die;
3705: }
3706: break;
3707: case 29:
3708: switch (sel) {
3709: case 0:
3710: case 2:
3711: case 4:
3712: case 6:
1.1.1.8 root 3713: gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
1.1.1.5 root 3714: rn = "TagHi";
3715: break;
3716: case 1:
3717: case 3:
3718: case 5:
3719: case 7:
1.1.1.8 root 3720: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
1.1.1.5 root 3721: rn = "DataHi";
3722: break;
3723: default:
3724: goto die;
3725: }
3726: break;
3727: case 30:
3728: switch (sel) {
3729: case 0:
1.1.1.8 root 3730: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3731: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3732: rn = "ErrorEPC";
3733: break;
1.1.1.5 root 3734: default:
3735: goto die;
3736: }
3737: break;
3738: case 31:
3739: switch (sel) {
3740: case 0:
1.1.1.7 root 3741: /* EJTAG support */
1.1.1.8 root 3742: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 3743: rn = "DESAVE";
3744: break;
1.1.1.5 root 3745: default:
3746: goto die;
3747: }
3748: break;
3749: default:
3750: goto die;
3751: }
1.1.1.13 root 3752: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 3753: LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 3754: return;
3755:
3756: die:
1.1.1.7 root 3757: LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 3758: generate_exception(ctx, EXCP_RI);
3759: }
3760:
1.1.1.8 root 3761: static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 3762: {
3763: const char *rn = "invalid";
3764:
1.1.1.6 root 3765: if (sel != 0)
3766: check_insn(env, ctx, ISA_MIPS32);
3767:
1.1.1.7 root 3768: if (use_icount)
3769: gen_io_start();
3770:
1.1.1.5 root 3771: switch (reg) {
3772: case 0:
3773: switch (sel) {
3774: case 0:
1.1.1.8 root 3775: gen_helper_mtc0_index(arg);
1.1.1.5 root 3776: rn = "Index";
3777: break;
3778: case 1:
1.1.1.6 root 3779: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3780: gen_helper_mtc0_mvpcontrol(arg);
1.1.1.5 root 3781: rn = "MVPControl";
1.1.1.6 root 3782: break;
1.1.1.5 root 3783: case 2:
1.1.1.6 root 3784: check_insn(env, ctx, ASE_MT);
3785: /* ignored */
1.1.1.5 root 3786: rn = "MVPConf0";
1.1.1.6 root 3787: break;
1.1.1.5 root 3788: case 3:
1.1.1.6 root 3789: check_insn(env, ctx, ASE_MT);
3790: /* ignored */
1.1.1.5 root 3791: rn = "MVPConf1";
1.1.1.6 root 3792: break;
1.1.1.5 root 3793: default:
3794: goto die;
3795: }
3796: break;
3797: case 1:
3798: switch (sel) {
3799: case 0:
1.1.1.6 root 3800: /* ignored */
1.1.1.5 root 3801: rn = "Random";
1.1.1.6 root 3802: break;
1.1.1.5 root 3803: case 1:
1.1.1.6 root 3804: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3805: gen_helper_mtc0_vpecontrol(arg);
1.1.1.5 root 3806: rn = "VPEControl";
1.1.1.6 root 3807: break;
1.1.1.5 root 3808: case 2:
1.1.1.6 root 3809: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3810: gen_helper_mtc0_vpeconf0(arg);
1.1.1.5 root 3811: rn = "VPEConf0";
1.1.1.6 root 3812: break;
1.1.1.5 root 3813: case 3:
1.1.1.6 root 3814: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3815: gen_helper_mtc0_vpeconf1(arg);
1.1.1.5 root 3816: rn = "VPEConf1";
1.1.1.6 root 3817: break;
1.1.1.5 root 3818: case 4:
1.1.1.6 root 3819: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3820: gen_helper_mtc0_yqmask(arg);
1.1.1.5 root 3821: rn = "YQMask";
1.1.1.6 root 3822: break;
1.1.1.5 root 3823: case 5:
1.1.1.6 root 3824: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3825: gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 3826: rn = "VPESchedule";
1.1.1.6 root 3827: break;
1.1.1.5 root 3828: case 6:
1.1.1.6 root 3829: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3830: gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 3831: rn = "VPEScheFBack";
1.1.1.6 root 3832: break;
1.1.1.5 root 3833: case 7:
1.1.1.6 root 3834: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3835: gen_helper_mtc0_vpeopt(arg);
1.1.1.5 root 3836: rn = "VPEOpt";
1.1.1.6 root 3837: break;
1.1.1.5 root 3838: default:
3839: goto die;
3840: }
3841: break;
3842: case 2:
3843: switch (sel) {
3844: case 0:
1.1.1.8 root 3845: gen_helper_mtc0_entrylo0(arg);
1.1.1.6 root 3846: rn = "EntryLo0";
3847: break;
3848: case 1:
3849: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3850: gen_helper_mtc0_tcstatus(arg);
1.1.1.6 root 3851: rn = "TCStatus";
3852: break;
3853: case 2:
3854: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3855: gen_helper_mtc0_tcbind(arg);
1.1.1.6 root 3856: rn = "TCBind";
3857: break;
1.1.1.5 root 3858: case 3:
1.1.1.6 root 3859: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3860: gen_helper_mtc0_tcrestart(arg);
1.1.1.6 root 3861: rn = "TCRestart";
3862: break;
1.1.1.5 root 3863: case 4:
1.1.1.6 root 3864: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3865: gen_helper_mtc0_tchalt(arg);
1.1.1.6 root 3866: rn = "TCHalt";
3867: break;
1.1.1.5 root 3868: case 5:
1.1.1.6 root 3869: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3870: gen_helper_mtc0_tccontext(arg);
1.1.1.6 root 3871: rn = "TCContext";
3872: break;
1.1.1.5 root 3873: case 6:
1.1.1.6 root 3874: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3875: gen_helper_mtc0_tcschedule(arg);
1.1.1.6 root 3876: rn = "TCSchedule";
3877: break;
1.1.1.5 root 3878: case 7:
1.1.1.6 root 3879: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3880: gen_helper_mtc0_tcschefback(arg);
1.1.1.6 root 3881: rn = "TCScheFBack";
3882: break;
1.1.1.5 root 3883: default:
3884: goto die;
3885: }
3886: break;
3887: case 3:
3888: switch (sel) {
3889: case 0:
1.1.1.8 root 3890: gen_helper_mtc0_entrylo1(arg);
1.1.1.6 root 3891: rn = "EntryLo1";
3892: break;
1.1.1.5 root 3893: default:
3894: goto die;
1.1.1.6 root 3895: }
1.1.1.5 root 3896: break;
3897: case 4:
3898: switch (sel) {
3899: case 0:
1.1.1.8 root 3900: gen_helper_mtc0_context(arg);
1.1.1.6 root 3901: rn = "Context";
3902: break;
3903: case 1:
1.1.1.8 root 3904: // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 3905: rn = "ContextConfig";
3906: // break;
1.1.1.5 root 3907: default:
3908: goto die;
1.1.1.6 root 3909: }
1.1.1.5 root 3910: break;
3911: case 5:
3912: switch (sel) {
3913: case 0:
1.1.1.8 root 3914: gen_helper_mtc0_pagemask(arg);
1.1.1.6 root 3915: rn = "PageMask";
3916: break;
3917: case 1:
3918: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3919: gen_helper_mtc0_pagegrain(arg);
1.1.1.6 root 3920: rn = "PageGrain";
3921: break;
1.1.1.5 root 3922: default:
3923: goto die;
1.1.1.6 root 3924: }
1.1.1.5 root 3925: break;
3926: case 6:
3927: switch (sel) {
3928: case 0:
1.1.1.8 root 3929: gen_helper_mtc0_wired(arg);
1.1.1.6 root 3930: rn = "Wired";
3931: break;
3932: case 1:
3933: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3934: gen_helper_mtc0_srsconf0(arg);
1.1.1.6 root 3935: rn = "SRSConf0";
3936: break;
3937: case 2:
3938: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3939: gen_helper_mtc0_srsconf1(arg);
1.1.1.6 root 3940: rn = "SRSConf1";
3941: break;
1.1.1.5 root 3942: case 3:
1.1.1.6 root 3943: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3944: gen_helper_mtc0_srsconf2(arg);
1.1.1.6 root 3945: rn = "SRSConf2";
3946: break;
1.1.1.5 root 3947: case 4:
1.1.1.6 root 3948: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3949: gen_helper_mtc0_srsconf3(arg);
1.1.1.6 root 3950: rn = "SRSConf3";
3951: break;
1.1.1.5 root 3952: case 5:
1.1.1.6 root 3953: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3954: gen_helper_mtc0_srsconf4(arg);
1.1.1.6 root 3955: rn = "SRSConf4";
3956: break;
1.1.1.5 root 3957: default:
3958: goto die;
1.1.1.6 root 3959: }
1.1.1.5 root 3960: break;
3961: case 7:
3962: switch (sel) {
3963: case 0:
1.1.1.6 root 3964: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3965: gen_helper_mtc0_hwrena(arg);
1.1.1.6 root 3966: rn = "HWREna";
3967: break;
1.1.1.5 root 3968: default:
3969: goto die;
1.1.1.6 root 3970: }
1.1.1.5 root 3971: break;
3972: case 8:
3973: /* ignored */
1.1.1.7 root 3974: rn = "BadVAddr";
1.1.1.5 root 3975: break;
3976: case 9:
3977: switch (sel) {
3978: case 0:
1.1.1.8 root 3979: gen_helper_mtc0_count(arg);
1.1.1.6 root 3980: rn = "Count";
3981: break;
3982: /* 6,7 are implementation dependent */
1.1.1.5 root 3983: default:
3984: goto die;
1.1.1.6 root 3985: }
1.1.1.5 root 3986: break;
3987: case 10:
3988: switch (sel) {
3989: case 0:
1.1.1.8 root 3990: gen_helper_mtc0_entryhi(arg);
1.1.1.6 root 3991: rn = "EntryHi";
3992: break;
1.1.1.5 root 3993: default:
3994: goto die;
1.1.1.6 root 3995: }
1.1.1.5 root 3996: break;
3997: case 11:
3998: switch (sel) {
3999: case 0:
1.1.1.8 root 4000: gen_helper_mtc0_compare(arg);
1.1.1.6 root 4001: rn = "Compare";
4002: break;
4003: /* 6,7 are implementation dependent */
1.1.1.5 root 4004: default:
4005: goto die;
1.1.1.6 root 4006: }
1.1.1.5 root 4007: break;
4008: case 12:
4009: switch (sel) {
4010: case 0:
1.1.1.8 root 4011: save_cpu_state(ctx, 1);
4012: gen_helper_mtc0_status(arg);
1.1.1.6 root 4013: /* BS_STOP isn't good enough here, hflags may have changed. */
4014: gen_save_pc(ctx->pc + 4);
4015: ctx->bstate = BS_EXCP;
4016: rn = "Status";
4017: break;
4018: case 1:
4019: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4020: gen_helper_mtc0_intctl(arg);
1.1.1.6 root 4021: /* Stop translation as we may have switched the execution mode */
4022: ctx->bstate = BS_STOP;
4023: rn = "IntCtl";
4024: break;
4025: case 2:
4026: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4027: gen_helper_mtc0_srsctl(arg);
1.1.1.6 root 4028: /* Stop translation as we may have switched the execution mode */
4029: ctx->bstate = BS_STOP;
4030: rn = "SRSCtl";
4031: break;
1.1.1.5 root 4032: case 3:
1.1.1.6 root 4033: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4034: gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 4035: /* Stop translation as we may have switched the execution mode */
4036: ctx->bstate = BS_STOP;
4037: rn = "SRSMap";
4038: break;
1.1.1.5 root 4039: default:
4040: goto die;
1.1.1.6 root 4041: }
1.1.1.5 root 4042: break;
4043: case 13:
4044: switch (sel) {
4045: case 0:
1.1.1.8 root 4046: save_cpu_state(ctx, 1);
4047: gen_helper_mtc0_cause(arg);
1.1.1.6 root 4048: rn = "Cause";
4049: break;
1.1.1.5 root 4050: default:
4051: goto die;
1.1.1.6 root 4052: }
1.1.1.5 root 4053: break;
4054: case 14:
4055: switch (sel) {
4056: case 0:
1.1.1.8 root 4057: gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 4058: rn = "EPC";
4059: break;
1.1.1.5 root 4060: default:
4061: goto die;
1.1.1.6 root 4062: }
1.1.1.5 root 4063: break;
4064: case 15:
4065: switch (sel) {
4066: case 0:
1.1.1.6 root 4067: /* ignored */
4068: rn = "PRid";
4069: break;
4070: case 1:
4071: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4072: gen_helper_mtc0_ebase(arg);
1.1.1.6 root 4073: rn = "EBase";
4074: break;
1.1.1.5 root 4075: default:
4076: goto die;
1.1.1.6 root 4077: }
1.1.1.5 root 4078: break;
4079: case 16:
4080: switch (sel) {
4081: case 0:
1.1.1.8 root 4082: gen_helper_mtc0_config0(arg);
1.1.1.5 root 4083: rn = "Config";
1.1.1.6 root 4084: /* Stop translation as we may have switched the execution mode */
4085: ctx->bstate = BS_STOP;
1.1.1.5 root 4086: break;
4087: case 1:
1.1.1.6 root 4088: /* ignored, read only */
1.1.1.5 root 4089: rn = "Config1";
4090: break;
4091: case 2:
1.1.1.8 root 4092: gen_helper_mtc0_config2(arg);
1.1.1.5 root 4093: rn = "Config2";
1.1.1.6 root 4094: /* Stop translation as we may have switched the execution mode */
4095: ctx->bstate = BS_STOP;
1.1.1.5 root 4096: break;
4097: case 3:
1.1.1.6 root 4098: /* ignored, read only */
1.1.1.5 root 4099: rn = "Config3";
4100: break;
1.1.1.6 root 4101: /* 4,5 are reserved */
4102: /* 6,7 are implementation dependent */
4103: case 6:
4104: /* ignored */
4105: rn = "Config6";
4106: break;
4107: case 7:
4108: /* ignored */
4109: rn = "Config7";
4110: break;
1.1.1.5 root 4111: default:
4112: rn = "Invalid config selector";
4113: goto die;
4114: }
4115: break;
4116: case 17:
4117: switch (sel) {
4118: case 0:
1.1.1.9 root 4119: gen_helper_mtc0_lladdr(arg);
1.1.1.6 root 4120: rn = "LLAddr";
4121: break;
1.1.1.5 root 4122: default:
4123: goto die;
4124: }
4125: break;
4126: case 18:
4127: switch (sel) {
1.1.1.6 root 4128: case 0 ... 7:
1.1.1.8 root 4129: gen_helper_1i(mtc0_watchlo, arg, sel);
1.1.1.6 root 4130: rn = "WatchLo";
4131: break;
1.1.1.5 root 4132: default:
4133: goto die;
4134: }
4135: break;
4136: case 19:
4137: switch (sel) {
1.1.1.6 root 4138: case 0 ... 7:
1.1.1.8 root 4139: gen_helper_1i(mtc0_watchhi, arg, sel);
1.1.1.6 root 4140: rn = "WatchHi";
4141: break;
1.1.1.5 root 4142: default:
4143: goto die;
4144: }
4145: break;
4146: case 20:
4147: switch (sel) {
4148: case 0:
1.1.1.6 root 4149: #if defined(TARGET_MIPS64)
4150: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 4151: gen_helper_mtc0_xcontext(arg);
1.1.1.6 root 4152: rn = "XContext";
4153: break;
4154: #endif
1.1.1.5 root 4155: default:
4156: goto die;
4157: }
4158: break;
4159: case 21:
4160: /* Officially reserved, but sel 0 is used for R1x000 framemask */
4161: switch (sel) {
4162: case 0:
1.1.1.8 root 4163: gen_helper_mtc0_framemask(arg);
1.1.1.6 root 4164: rn = "Framemask";
4165: break;
1.1.1.5 root 4166: default:
4167: goto die;
4168: }
4169: break;
4170: case 22:
4171: /* ignored */
4172: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 root 4173: break;
1.1.1.5 root 4174: case 23:
4175: switch (sel) {
4176: case 0:
1.1.1.8 root 4177: gen_helper_mtc0_debug(arg); /* EJTAG support */
1.1.1.6 root 4178: /* BS_STOP isn't good enough here, hflags may have changed. */
4179: gen_save_pc(ctx->pc + 4);
4180: ctx->bstate = BS_EXCP;
4181: rn = "Debug";
4182: break;
4183: case 1:
1.1.1.8 root 4184: // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 4185: rn = "TraceControl";
4186: /* Stop translation as we may have switched the execution mode */
4187: ctx->bstate = BS_STOP;
4188: // break;
4189: case 2:
1.1.1.8 root 4190: // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 4191: rn = "TraceControl2";
4192: /* Stop translation as we may have switched the execution mode */
4193: ctx->bstate = BS_STOP;
4194: // break;
4195: case 3:
4196: /* Stop translation as we may have switched the execution mode */
4197: ctx->bstate = BS_STOP;
1.1.1.8 root 4198: // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 4199: rn = "UserTraceData";
4200: /* Stop translation as we may have switched the execution mode */
4201: ctx->bstate = BS_STOP;
4202: // break;
1.1.1.5 root 4203: case 4:
1.1.1.8 root 4204: // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 4205: /* Stop translation as we may have switched the execution mode */
4206: ctx->bstate = BS_STOP;
4207: rn = "TraceBPC";
4208: // break;
1.1.1.5 root 4209: default:
4210: goto die;
4211: }
4212: break;
4213: case 24:
4214: switch (sel) {
4215: case 0:
1.1.1.7 root 4216: /* EJTAG support */
1.1.1.8 root 4217: gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 4218: rn = "DEPC";
4219: break;
1.1.1.5 root 4220: default:
4221: goto die;
4222: }
4223: break;
4224: case 25:
4225: switch (sel) {
4226: case 0:
1.1.1.8 root 4227: gen_helper_mtc0_performance0(arg);
1.1.1.6 root 4228: rn = "Performance0";
4229: break;
4230: case 1:
1.1.1.8 root 4231: // gen_helper_mtc0_performance1(arg);
1.1.1.6 root 4232: rn = "Performance1";
4233: // break;
4234: case 2:
1.1.1.8 root 4235: // gen_helper_mtc0_performance2(arg);
1.1.1.6 root 4236: rn = "Performance2";
4237: // break;
4238: case 3:
1.1.1.8 root 4239: // gen_helper_mtc0_performance3(arg);
1.1.1.6 root 4240: rn = "Performance3";
4241: // break;
1.1.1.5 root 4242: case 4:
1.1.1.8 root 4243: // gen_helper_mtc0_performance4(arg);
1.1.1.6 root 4244: rn = "Performance4";
4245: // break;
1.1.1.5 root 4246: case 5:
1.1.1.8 root 4247: // gen_helper_mtc0_performance5(arg);
1.1.1.6 root 4248: rn = "Performance5";
4249: // break;
1.1.1.5 root 4250: case 6:
1.1.1.8 root 4251: // gen_helper_mtc0_performance6(arg);
1.1.1.6 root 4252: rn = "Performance6";
4253: // break;
1.1.1.5 root 4254: case 7:
1.1.1.8 root 4255: // gen_helper_mtc0_performance7(arg);
1.1.1.6 root 4256: rn = "Performance7";
4257: // break;
1.1.1.5 root 4258: default:
4259: goto die;
4260: }
4261: break;
4262: case 26:
1.1.1.6 root 4263: /* ignored */
1.1.1.5 root 4264: rn = "ECC";
1.1.1.6 root 4265: break;
1.1.1.5 root 4266: case 27:
4267: switch (sel) {
4268: case 0 ... 3:
1.1.1.6 root 4269: /* ignored */
4270: rn = "CacheErr";
4271: break;
1.1.1.5 root 4272: default:
4273: goto die;
4274: }
4275: break;
4276: case 28:
4277: switch (sel) {
4278: case 0:
4279: case 2:
4280: case 4:
4281: case 6:
1.1.1.8 root 4282: gen_helper_mtc0_taglo(arg);
1.1.1.5 root 4283: rn = "TagLo";
4284: break;
4285: case 1:
4286: case 3:
4287: case 5:
4288: case 7:
1.1.1.8 root 4289: gen_helper_mtc0_datalo(arg);
1.1.1.5 root 4290: rn = "DataLo";
4291: break;
4292: default:
4293: goto die;
4294: }
4295: break;
4296: case 29:
4297: switch (sel) {
4298: case 0:
4299: case 2:
4300: case 4:
4301: case 6:
1.1.1.8 root 4302: gen_helper_mtc0_taghi(arg);
1.1.1.5 root 4303: rn = "TagHi";
4304: break;
4305: case 1:
4306: case 3:
4307: case 5:
4308: case 7:
1.1.1.8 root 4309: gen_helper_mtc0_datahi(arg);
1.1.1.5 root 4310: rn = "DataHi";
4311: break;
4312: default:
4313: rn = "invalid sel";
4314: goto die;
4315: }
4316: break;
4317: case 30:
4318: switch (sel) {
4319: case 0:
1.1.1.8 root 4320: gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 4321: rn = "ErrorEPC";
4322: break;
1.1.1.5 root 4323: default:
4324: goto die;
4325: }
4326: break;
4327: case 31:
4328: switch (sel) {
4329: case 0:
1.1.1.7 root 4330: /* EJTAG support */
1.1.1.8 root 4331: gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 4332: rn = "DESAVE";
4333: break;
1.1.1.5 root 4334: default:
4335: goto die;
4336: }
1.1.1.6 root 4337: /* Stop translation as we may have switched the execution mode */
4338: ctx->bstate = BS_STOP;
1.1.1.5 root 4339: break;
4340: default:
4341: goto die;
4342: }
1.1.1.13 root 4343: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 4344: LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4345: /* For simplicity assume that all writes can cause interrupts. */
4346: if (use_icount) {
4347: gen_io_end();
4348: ctx->bstate = BS_STOP;
1.1.1.5 root 4349: }
4350: return;
4351:
4352: die:
1.1.1.7 root 4353: LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4354: generate_exception(ctx, EXCP_RI);
4355: }
4356:
1.1.1.6 root 4357: #if defined(TARGET_MIPS64)
1.1.1.8 root 4358: static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 4359: {
4360: const char *rn = "invalid";
4361:
1.1.1.6 root 4362: if (sel != 0)
4363: check_insn(env, ctx, ISA_MIPS64);
4364:
1.1.1.5 root 4365: switch (reg) {
4366: case 0:
4367: switch (sel) {
4368: case 0:
1.1.1.8 root 4369: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
1.1.1.5 root 4370: rn = "Index";
4371: break;
4372: case 1:
1.1.1.6 root 4373: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4374: gen_helper_mfc0_mvpcontrol(arg);
1.1.1.5 root 4375: rn = "MVPControl";
1.1.1.6 root 4376: break;
1.1.1.5 root 4377: case 2:
1.1.1.6 root 4378: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4379: gen_helper_mfc0_mvpconf0(arg);
1.1.1.5 root 4380: rn = "MVPConf0";
1.1.1.6 root 4381: break;
1.1.1.5 root 4382: case 3:
1.1.1.6 root 4383: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4384: gen_helper_mfc0_mvpconf1(arg);
1.1.1.5 root 4385: rn = "MVPConf1";
1.1.1.6 root 4386: break;
1.1.1.5 root 4387: default:
4388: goto die;
4389: }
4390: break;
4391: case 1:
4392: switch (sel) {
4393: case 0:
1.1.1.8 root 4394: gen_helper_mfc0_random(arg);
1.1.1.5 root 4395: rn = "Random";
1.1.1.6 root 4396: break;
1.1.1.5 root 4397: case 1:
1.1.1.6 root 4398: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4399: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
1.1.1.5 root 4400: rn = "VPEControl";
1.1.1.6 root 4401: break;
1.1.1.5 root 4402: case 2:
1.1.1.6 root 4403: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4404: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
1.1.1.5 root 4405: rn = "VPEConf0";
1.1.1.6 root 4406: break;
1.1.1.5 root 4407: case 3:
1.1.1.6 root 4408: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4409: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
1.1.1.5 root 4410: rn = "VPEConf1";
1.1.1.6 root 4411: break;
1.1.1.5 root 4412: case 4:
1.1.1.6 root 4413: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4414: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
1.1.1.5 root 4415: rn = "YQMask";
1.1.1.6 root 4416: break;
1.1.1.5 root 4417: case 5:
1.1.1.6 root 4418: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4419: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 4420: rn = "VPESchedule";
1.1.1.6 root 4421: break;
1.1.1.5 root 4422: case 6:
1.1.1.6 root 4423: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4424: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 4425: rn = "VPEScheFBack";
1.1.1.6 root 4426: break;
1.1.1.5 root 4427: case 7:
1.1.1.6 root 4428: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4429: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
1.1.1.5 root 4430: rn = "VPEOpt";
1.1.1.6 root 4431: break;
1.1.1.5 root 4432: default:
4433: goto die;
4434: }
4435: break;
4436: case 2:
4437: switch (sel) {
4438: case 0:
1.1.1.8 root 4439: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
1.1.1.6 root 4440: rn = "EntryLo0";
4441: break;
4442: case 1:
4443: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4444: gen_helper_mfc0_tcstatus(arg);
1.1.1.6 root 4445: rn = "TCStatus";
4446: break;
4447: case 2:
4448: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4449: gen_helper_mfc0_tcbind(arg);
1.1.1.6 root 4450: rn = "TCBind";
4451: break;
1.1.1.5 root 4452: case 3:
1.1.1.6 root 4453: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4454: gen_helper_dmfc0_tcrestart(arg);
1.1.1.6 root 4455: rn = "TCRestart";
4456: break;
1.1.1.5 root 4457: case 4:
1.1.1.6 root 4458: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4459: gen_helper_dmfc0_tchalt(arg);
1.1.1.6 root 4460: rn = "TCHalt";
4461: break;
1.1.1.5 root 4462: case 5:
1.1.1.6 root 4463: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4464: gen_helper_dmfc0_tccontext(arg);
1.1.1.6 root 4465: rn = "TCContext";
4466: break;
1.1.1.5 root 4467: case 6:
1.1.1.6 root 4468: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4469: gen_helper_dmfc0_tcschedule(arg);
1.1.1.6 root 4470: rn = "TCSchedule";
4471: break;
1.1.1.5 root 4472: case 7:
1.1.1.6 root 4473: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4474: gen_helper_dmfc0_tcschefback(arg);
1.1.1.6 root 4475: rn = "TCScheFBack";
4476: break;
1.1.1.5 root 4477: default:
4478: goto die;
4479: }
4480: break;
4481: case 3:
4482: switch (sel) {
4483: case 0:
1.1.1.8 root 4484: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
1.1.1.6 root 4485: rn = "EntryLo1";
4486: break;
1.1.1.5 root 4487: default:
4488: goto die;
1.1.1.6 root 4489: }
1.1.1.5 root 4490: break;
4491: case 4:
4492: switch (sel) {
4493: case 0:
1.1.1.8 root 4494: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
1.1.1.6 root 4495: rn = "Context";
4496: break;
4497: case 1:
1.1.1.8 root 4498: // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 4499: rn = "ContextConfig";
4500: // break;
1.1.1.5 root 4501: default:
4502: goto die;
1.1.1.6 root 4503: }
1.1.1.5 root 4504: break;
4505: case 5:
4506: switch (sel) {
4507: case 0:
1.1.1.8 root 4508: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
1.1.1.6 root 4509: rn = "PageMask";
4510: break;
4511: case 1:
4512: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4513: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
1.1.1.6 root 4514: rn = "PageGrain";
4515: break;
1.1.1.5 root 4516: default:
4517: goto die;
1.1.1.6 root 4518: }
1.1.1.5 root 4519: break;
4520: case 6:
4521: switch (sel) {
4522: case 0:
1.1.1.8 root 4523: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
1.1.1.6 root 4524: rn = "Wired";
4525: break;
4526: case 1:
4527: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4528: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
1.1.1.6 root 4529: rn = "SRSConf0";
4530: break;
4531: case 2:
4532: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4533: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
1.1.1.6 root 4534: rn = "SRSConf1";
4535: break;
1.1.1.5 root 4536: case 3:
1.1.1.6 root 4537: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4538: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
1.1.1.6 root 4539: rn = "SRSConf2";
4540: break;
1.1.1.5 root 4541: case 4:
1.1.1.6 root 4542: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4543: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
1.1.1.6 root 4544: rn = "SRSConf3";
4545: break;
1.1.1.5 root 4546: case 5:
1.1.1.6 root 4547: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4548: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
1.1.1.6 root 4549: rn = "SRSConf4";
4550: break;
1.1.1.5 root 4551: default:
4552: goto die;
1.1.1.6 root 4553: }
1.1.1.5 root 4554: break;
4555: case 7:
4556: switch (sel) {
4557: case 0:
1.1.1.6 root 4558: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4559: gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
1.1.1.6 root 4560: rn = "HWREna";
4561: break;
1.1.1.5 root 4562: default:
4563: goto die;
1.1.1.6 root 4564: }
1.1.1.5 root 4565: break;
4566: case 8:
4567: switch (sel) {
4568: case 0:
1.1.1.8 root 4569: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
1.1.1.7 root 4570: rn = "BadVAddr";
1.1.1.6 root 4571: break;
1.1.1.5 root 4572: default:
4573: goto die;
1.1.1.6 root 4574: }
1.1.1.5 root 4575: break;
4576: case 9:
4577: switch (sel) {
4578: case 0:
1.1.1.7 root 4579: /* Mark as an IO operation because we read the time. */
4580: if (use_icount)
4581: gen_io_start();
1.1.1.8 root 4582: gen_helper_mfc0_count(arg);
1.1.1.7 root 4583: if (use_icount) {
4584: gen_io_end();
4585: }
1.1.1.13 root 4586: /* Break the TB to be able to take timer interrupts immediately
4587: after reading count. */
4588: ctx->bstate = BS_STOP;
1.1.1.6 root 4589: rn = "Count";
4590: break;
4591: /* 6,7 are implementation dependent */
1.1.1.5 root 4592: default:
4593: goto die;
1.1.1.6 root 4594: }
1.1.1.5 root 4595: break;
4596: case 10:
4597: switch (sel) {
4598: case 0:
1.1.1.8 root 4599: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
1.1.1.6 root 4600: rn = "EntryHi";
4601: break;
1.1.1.5 root 4602: default:
4603: goto die;
1.1.1.6 root 4604: }
1.1.1.5 root 4605: break;
4606: case 11:
4607: switch (sel) {
4608: case 0:
1.1.1.8 root 4609: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
1.1.1.6 root 4610: rn = "Compare";
4611: break;
4612: /* 6,7 are implementation dependent */
1.1.1.5 root 4613: default:
4614: goto die;
1.1.1.6 root 4615: }
1.1.1.5 root 4616: break;
4617: case 12:
4618: switch (sel) {
4619: case 0:
1.1.1.8 root 4620: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
1.1.1.6 root 4621: rn = "Status";
4622: break;
4623: case 1:
4624: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4625: gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
1.1.1.6 root 4626: rn = "IntCtl";
4627: break;
4628: case 2:
4629: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4630: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
1.1.1.6 root 4631: rn = "SRSCtl";
4632: break;
1.1.1.5 root 4633: case 3:
1.1.1.6 root 4634: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4635: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 4636: rn = "SRSMap";
4637: break;
1.1.1.5 root 4638: default:
4639: goto die;
1.1.1.6 root 4640: }
1.1.1.5 root 4641: break;
4642: case 13:
4643: switch (sel) {
4644: case 0:
1.1.1.8 root 4645: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
1.1.1.6 root 4646: rn = "Cause";
4647: break;
1.1.1.5 root 4648: default:
4649: goto die;
1.1.1.6 root 4650: }
1.1.1.5 root 4651: break;
4652: case 14:
4653: switch (sel) {
4654: case 0:
1.1.1.8 root 4655: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 4656: rn = "EPC";
4657: break;
1.1.1.5 root 4658: default:
4659: goto die;
1.1.1.6 root 4660: }
1.1.1.5 root 4661: break;
4662: case 15:
4663: switch (sel) {
4664: case 0:
1.1.1.8 root 4665: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
1.1.1.6 root 4666: rn = "PRid";
4667: break;
4668: case 1:
4669: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4670: gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
1.1.1.6 root 4671: rn = "EBase";
4672: break;
1.1.1.5 root 4673: default:
4674: goto die;
1.1.1.6 root 4675: }
1.1.1.5 root 4676: break;
4677: case 16:
4678: switch (sel) {
4679: case 0:
1.1.1.8 root 4680: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
1.1.1.5 root 4681: rn = "Config";
4682: break;
4683: case 1:
1.1.1.8 root 4684: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
1.1.1.5 root 4685: rn = "Config1";
4686: break;
4687: case 2:
1.1.1.8 root 4688: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
1.1.1.5 root 4689: rn = "Config2";
4690: break;
4691: case 3:
1.1.1.8 root 4692: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
1.1.1.5 root 4693: rn = "Config3";
4694: break;
4695: /* 6,7 are implementation dependent */
1.1.1.7 root 4696: case 6:
1.1.1.8 root 4697: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
1.1.1.7 root 4698: rn = "Config6";
4699: break;
4700: case 7:
1.1.1.8 root 4701: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
1.1.1.7 root 4702: rn = "Config7";
4703: break;
1.1.1.5 root 4704: default:
4705: goto die;
4706: }
4707: break;
4708: case 17:
4709: switch (sel) {
4710: case 0:
1.1.1.8 root 4711: gen_helper_dmfc0_lladdr(arg);
1.1.1.6 root 4712: rn = "LLAddr";
4713: break;
1.1.1.5 root 4714: default:
4715: goto die;
4716: }
4717: break;
4718: case 18:
4719: switch (sel) {
1.1.1.6 root 4720: case 0 ... 7:
1.1.1.8 root 4721: gen_helper_1i(dmfc0_watchlo, arg, sel);
1.1.1.6 root 4722: rn = "WatchLo";
4723: break;
1.1.1.5 root 4724: default:
4725: goto die;
4726: }
4727: break;
4728: case 19:
4729: switch (sel) {
1.1.1.6 root 4730: case 0 ... 7:
1.1.1.8 root 4731: gen_helper_1i(mfc0_watchhi, arg, sel);
1.1.1.6 root 4732: rn = "WatchHi";
4733: break;
1.1.1.5 root 4734: default:
4735: goto die;
4736: }
4737: break;
4738: case 20:
4739: switch (sel) {
4740: case 0:
1.1.1.6 root 4741: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 4742: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
1.1.1.6 root 4743: rn = "XContext";
4744: break;
1.1.1.5 root 4745: default:
4746: goto die;
4747: }
4748: break;
4749: case 21:
4750: /* Officially reserved, but sel 0 is used for R1x000 framemask */
4751: switch (sel) {
4752: case 0:
1.1.1.8 root 4753: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
1.1.1.6 root 4754: rn = "Framemask";
4755: break;
1.1.1.5 root 4756: default:
4757: goto die;
4758: }
4759: break;
4760: case 22:
1.1.1.8 root 4761: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 4762: rn = "'Diagnostic"; /* implementation dependent */
4763: break;
1.1.1.5 root 4764: case 23:
4765: switch (sel) {
4766: case 0:
1.1.1.8 root 4767: gen_helper_mfc0_debug(arg); /* EJTAG support */
1.1.1.6 root 4768: rn = "Debug";
4769: break;
4770: case 1:
1.1.1.8 root 4771: // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 4772: rn = "TraceControl";
4773: // break;
4774: case 2:
1.1.1.8 root 4775: // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 4776: rn = "TraceControl2";
4777: // break;
1.1.1.5 root 4778: case 3:
1.1.1.8 root 4779: // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 4780: rn = "UserTraceData";
4781: // break;
1.1.1.5 root 4782: case 4:
1.1.1.8 root 4783: // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 4784: rn = "TraceBPC";
4785: // break;
1.1.1.5 root 4786: default:
4787: goto die;
4788: }
4789: break;
4790: case 24:
4791: switch (sel) {
4792: case 0:
1.1.1.7 root 4793: /* EJTAG support */
1.1.1.8 root 4794: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 4795: rn = "DEPC";
4796: break;
1.1.1.5 root 4797: default:
4798: goto die;
4799: }
4800: break;
4801: case 25:
4802: switch (sel) {
4803: case 0:
1.1.1.8 root 4804: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
1.1.1.6 root 4805: rn = "Performance0";
1.1.1.5 root 4806: break;
4807: case 1:
1.1.1.8 root 4808: // gen_helper_dmfc0_performance1(arg);
1.1.1.6 root 4809: rn = "Performance1";
4810: // break;
1.1.1.5 root 4811: case 2:
1.1.1.8 root 4812: // gen_helper_dmfc0_performance2(arg);
1.1.1.6 root 4813: rn = "Performance2";
4814: // break;
1.1.1.5 root 4815: case 3:
1.1.1.8 root 4816: // gen_helper_dmfc0_performance3(arg);
1.1.1.6 root 4817: rn = "Performance3";
4818: // break;
1.1.1.5 root 4819: case 4:
1.1.1.8 root 4820: // gen_helper_dmfc0_performance4(arg);
1.1.1.6 root 4821: rn = "Performance4";
4822: // break;
1.1.1.5 root 4823: case 5:
1.1.1.8 root 4824: // gen_helper_dmfc0_performance5(arg);
1.1.1.6 root 4825: rn = "Performance5";
4826: // break;
1.1.1.5 root 4827: case 6:
1.1.1.8 root 4828: // gen_helper_dmfc0_performance6(arg);
1.1.1.6 root 4829: rn = "Performance6";
4830: // break;
1.1.1.5 root 4831: case 7:
1.1.1.8 root 4832: // gen_helper_dmfc0_performance7(arg);
1.1.1.6 root 4833: rn = "Performance7";
4834: // break;
1.1.1.5 root 4835: default:
4836: goto die;
4837: }
4838: break;
4839: case 26:
1.1.1.8 root 4840: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.7 root 4841: rn = "ECC";
4842: break;
1.1.1.5 root 4843: case 27:
4844: switch (sel) {
4845: /* ignored */
4846: case 0 ... 3:
1.1.1.8 root 4847: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 4848: rn = "CacheErr";
4849: break;
1.1.1.5 root 4850: default:
4851: goto die;
4852: }
4853: break;
4854: case 28:
4855: switch (sel) {
4856: case 0:
4857: case 2:
4858: case 4:
4859: case 6:
1.1.1.8 root 4860: gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
1.1.1.5 root 4861: rn = "TagLo";
4862: break;
4863: case 1:
4864: case 3:
4865: case 5:
4866: case 7:
1.1.1.8 root 4867: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
1.1.1.5 root 4868: rn = "DataLo";
4869: break;
4870: default:
4871: goto die;
4872: }
4873: break;
4874: case 29:
4875: switch (sel) {
4876: case 0:
4877: case 2:
4878: case 4:
4879: case 6:
1.1.1.8 root 4880: gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
1.1.1.5 root 4881: rn = "TagHi";
4882: break;
4883: case 1:
4884: case 3:
4885: case 5:
4886: case 7:
1.1.1.8 root 4887: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
1.1.1.5 root 4888: rn = "DataHi";
4889: break;
4890: default:
4891: goto die;
4892: }
4893: break;
4894: case 30:
4895: switch (sel) {
4896: case 0:
1.1.1.8 root 4897: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 4898: rn = "ErrorEPC";
4899: break;
1.1.1.5 root 4900: default:
4901: goto die;
4902: }
4903: break;
4904: case 31:
4905: switch (sel) {
4906: case 0:
1.1.1.7 root 4907: /* EJTAG support */
1.1.1.8 root 4908: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 4909: rn = "DESAVE";
4910: break;
1.1.1.5 root 4911: default:
4912: goto die;
4913: }
4914: break;
4915: default:
1.1.1.6 root 4916: goto die;
1.1.1.5 root 4917: }
1.1.1.13 root 4918: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 4919: LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4920: return;
4921:
4922: die:
1.1.1.7 root 4923: LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4924: generate_exception(ctx, EXCP_RI);
4925: }
4926:
1.1.1.8 root 4927: static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 4928: {
4929: const char *rn = "invalid";
4930:
1.1.1.6 root 4931: if (sel != 0)
4932: check_insn(env, ctx, ISA_MIPS64);
4933:
1.1.1.7 root 4934: if (use_icount)
4935: gen_io_start();
4936:
1.1.1.5 root 4937: switch (reg) {
4938: case 0:
4939: switch (sel) {
4940: case 0:
1.1.1.8 root 4941: gen_helper_mtc0_index(arg);
1.1.1.5 root 4942: rn = "Index";
4943: break;
4944: case 1:
1.1.1.6 root 4945: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4946: gen_helper_mtc0_mvpcontrol(arg);
1.1.1.5 root 4947: rn = "MVPControl";
1.1.1.6 root 4948: break;
1.1.1.5 root 4949: case 2:
1.1.1.6 root 4950: check_insn(env, ctx, ASE_MT);
4951: /* ignored */
1.1.1.5 root 4952: rn = "MVPConf0";
1.1.1.6 root 4953: break;
1.1.1.5 root 4954: case 3:
1.1.1.6 root 4955: check_insn(env, ctx, ASE_MT);
4956: /* ignored */
1.1.1.5 root 4957: rn = "MVPConf1";
1.1.1.6 root 4958: break;
1.1.1.5 root 4959: default:
4960: goto die;
4961: }
4962: break;
4963: case 1:
4964: switch (sel) {
4965: case 0:
1.1.1.6 root 4966: /* ignored */
1.1.1.5 root 4967: rn = "Random";
1.1.1.6 root 4968: break;
1.1.1.5 root 4969: case 1:
1.1.1.6 root 4970: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4971: gen_helper_mtc0_vpecontrol(arg);
1.1.1.5 root 4972: rn = "VPEControl";
1.1.1.6 root 4973: break;
1.1.1.5 root 4974: case 2:
1.1.1.6 root 4975: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4976: gen_helper_mtc0_vpeconf0(arg);
1.1.1.5 root 4977: rn = "VPEConf0";
1.1.1.6 root 4978: break;
1.1.1.5 root 4979: case 3:
1.1.1.6 root 4980: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4981: gen_helper_mtc0_vpeconf1(arg);
1.1.1.5 root 4982: rn = "VPEConf1";
1.1.1.6 root 4983: break;
1.1.1.5 root 4984: case 4:
1.1.1.6 root 4985: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4986: gen_helper_mtc0_yqmask(arg);
1.1.1.5 root 4987: rn = "YQMask";
1.1.1.6 root 4988: break;
1.1.1.5 root 4989: case 5:
1.1.1.6 root 4990: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4991: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 4992: rn = "VPESchedule";
1.1.1.6 root 4993: break;
1.1.1.5 root 4994: case 6:
1.1.1.6 root 4995: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4996: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 4997: rn = "VPEScheFBack";
1.1.1.6 root 4998: break;
1.1.1.5 root 4999: case 7:
1.1.1.6 root 5000: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5001: gen_helper_mtc0_vpeopt(arg);
1.1.1.5 root 5002: rn = "VPEOpt";
1.1.1.6 root 5003: break;
1.1.1.5 root 5004: default:
5005: goto die;
5006: }
5007: break;
5008: case 2:
5009: switch (sel) {
5010: case 0:
1.1.1.8 root 5011: gen_helper_mtc0_entrylo0(arg);
1.1.1.6 root 5012: rn = "EntryLo0";
5013: break;
5014: case 1:
5015: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5016: gen_helper_mtc0_tcstatus(arg);
1.1.1.6 root 5017: rn = "TCStatus";
5018: break;
5019: case 2:
5020: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5021: gen_helper_mtc0_tcbind(arg);
1.1.1.6 root 5022: rn = "TCBind";
5023: break;
1.1.1.5 root 5024: case 3:
1.1.1.6 root 5025: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5026: gen_helper_mtc0_tcrestart(arg);
1.1.1.6 root 5027: rn = "TCRestart";
5028: break;
1.1.1.5 root 5029: case 4:
1.1.1.6 root 5030: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5031: gen_helper_mtc0_tchalt(arg);
1.1.1.6 root 5032: rn = "TCHalt";
5033: break;
1.1.1.5 root 5034: case 5:
1.1.1.6 root 5035: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5036: gen_helper_mtc0_tccontext(arg);
1.1.1.6 root 5037: rn = "TCContext";
5038: break;
1.1.1.5 root 5039: case 6:
1.1.1.6 root 5040: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5041: gen_helper_mtc0_tcschedule(arg);
1.1.1.6 root 5042: rn = "TCSchedule";
5043: break;
1.1.1.5 root 5044: case 7:
1.1.1.6 root 5045: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5046: gen_helper_mtc0_tcschefback(arg);
1.1.1.6 root 5047: rn = "TCScheFBack";
5048: break;
1.1.1.5 root 5049: default:
5050: goto die;
5051: }
5052: break;
5053: case 3:
5054: switch (sel) {
5055: case 0:
1.1.1.8 root 5056: gen_helper_mtc0_entrylo1(arg);
1.1.1.6 root 5057: rn = "EntryLo1";
5058: break;
1.1.1.5 root 5059: default:
5060: goto die;
1.1.1.6 root 5061: }
1.1.1.5 root 5062: break;
5063: case 4:
5064: switch (sel) {
5065: case 0:
1.1.1.8 root 5066: gen_helper_mtc0_context(arg);
1.1.1.6 root 5067: rn = "Context";
5068: break;
5069: case 1:
1.1.1.8 root 5070: // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 5071: rn = "ContextConfig";
5072: // break;
1.1.1.5 root 5073: default:
5074: goto die;
1.1.1.6 root 5075: }
1.1.1.5 root 5076: break;
5077: case 5:
5078: switch (sel) {
5079: case 0:
1.1.1.8 root 5080: gen_helper_mtc0_pagemask(arg);
1.1.1.6 root 5081: rn = "PageMask";
5082: break;
5083: case 1:
5084: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5085: gen_helper_mtc0_pagegrain(arg);
1.1.1.6 root 5086: rn = "PageGrain";
5087: break;
1.1.1.5 root 5088: default:
5089: goto die;
1.1.1.6 root 5090: }
1.1.1.5 root 5091: break;
5092: case 6:
5093: switch (sel) {
5094: case 0:
1.1.1.8 root 5095: gen_helper_mtc0_wired(arg);
1.1.1.6 root 5096: rn = "Wired";
5097: break;
5098: case 1:
5099: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5100: gen_helper_mtc0_srsconf0(arg);
1.1.1.6 root 5101: rn = "SRSConf0";
5102: break;
5103: case 2:
5104: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5105: gen_helper_mtc0_srsconf1(arg);
1.1.1.6 root 5106: rn = "SRSConf1";
5107: break;
1.1.1.5 root 5108: case 3:
1.1.1.6 root 5109: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5110: gen_helper_mtc0_srsconf2(arg);
1.1.1.6 root 5111: rn = "SRSConf2";
5112: break;
1.1.1.5 root 5113: case 4:
1.1.1.6 root 5114: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5115: gen_helper_mtc0_srsconf3(arg);
1.1.1.6 root 5116: rn = "SRSConf3";
5117: break;
1.1.1.5 root 5118: case 5:
1.1.1.6 root 5119: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5120: gen_helper_mtc0_srsconf4(arg);
1.1.1.6 root 5121: rn = "SRSConf4";
5122: break;
1.1.1.5 root 5123: default:
5124: goto die;
1.1.1.6 root 5125: }
1.1.1.5 root 5126: break;
5127: case 7:
5128: switch (sel) {
5129: case 0:
1.1.1.6 root 5130: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5131: gen_helper_mtc0_hwrena(arg);
1.1.1.6 root 5132: rn = "HWREna";
5133: break;
1.1.1.5 root 5134: default:
5135: goto die;
1.1.1.6 root 5136: }
1.1.1.5 root 5137: break;
5138: case 8:
5139: /* ignored */
1.1.1.7 root 5140: rn = "BadVAddr";
1.1.1.5 root 5141: break;
5142: case 9:
5143: switch (sel) {
5144: case 0:
1.1.1.8 root 5145: gen_helper_mtc0_count(arg);
1.1.1.6 root 5146: rn = "Count";
5147: break;
5148: /* 6,7 are implementation dependent */
1.1.1.5 root 5149: default:
5150: goto die;
1.1.1.6 root 5151: }
5152: /* Stop translation as we may have switched the execution mode */
5153: ctx->bstate = BS_STOP;
1.1.1.5 root 5154: break;
5155: case 10:
5156: switch (sel) {
5157: case 0:
1.1.1.8 root 5158: gen_helper_mtc0_entryhi(arg);
1.1.1.6 root 5159: rn = "EntryHi";
5160: break;
1.1.1.5 root 5161: default:
5162: goto die;
1.1.1.6 root 5163: }
1.1.1.5 root 5164: break;
5165: case 11:
5166: switch (sel) {
5167: case 0:
1.1.1.8 root 5168: gen_helper_mtc0_compare(arg);
1.1.1.6 root 5169: rn = "Compare";
5170: break;
5171: /* 6,7 are implementation dependent */
1.1.1.5 root 5172: default:
5173: goto die;
1.1.1.6 root 5174: }
5175: /* Stop translation as we may have switched the execution mode */
5176: ctx->bstate = BS_STOP;
1.1.1.5 root 5177: break;
5178: case 12:
5179: switch (sel) {
5180: case 0:
1.1.1.8 root 5181: save_cpu_state(ctx, 1);
5182: gen_helper_mtc0_status(arg);
1.1.1.6 root 5183: /* BS_STOP isn't good enough here, hflags may have changed. */
5184: gen_save_pc(ctx->pc + 4);
5185: ctx->bstate = BS_EXCP;
5186: rn = "Status";
5187: break;
5188: case 1:
5189: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5190: gen_helper_mtc0_intctl(arg);
1.1.1.6 root 5191: /* Stop translation as we may have switched the execution mode */
5192: ctx->bstate = BS_STOP;
5193: rn = "IntCtl";
5194: break;
5195: case 2:
5196: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5197: gen_helper_mtc0_srsctl(arg);
1.1.1.6 root 5198: /* Stop translation as we may have switched the execution mode */
5199: ctx->bstate = BS_STOP;
5200: rn = "SRSCtl";
5201: break;
1.1.1.5 root 5202: case 3:
1.1.1.6 root 5203: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5204: gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 5205: /* Stop translation as we may have switched the execution mode */
5206: ctx->bstate = BS_STOP;
5207: rn = "SRSMap";
5208: break;
1.1.1.5 root 5209: default:
5210: goto die;
1.1.1.6 root 5211: }
1.1.1.5 root 5212: break;
5213: case 13:
5214: switch (sel) {
5215: case 0:
1.1.1.8 root 5216: save_cpu_state(ctx, 1);
1.1.1.12 root 5217: /* Mark as an IO operation because we may trigger a software
5218: interrupt. */
5219: if (use_icount) {
5220: gen_io_start();
5221: }
1.1.1.8 root 5222: gen_helper_mtc0_cause(arg);
1.1.1.12 root 5223: if (use_icount) {
5224: gen_io_end();
5225: }
5226: /* Stop translation as we may have triggered an intetrupt */
5227: ctx->bstate = BS_STOP;
1.1.1.6 root 5228: rn = "Cause";
5229: break;
1.1.1.5 root 5230: default:
5231: goto die;
1.1.1.6 root 5232: }
1.1.1.5 root 5233: break;
5234: case 14:
5235: switch (sel) {
5236: case 0:
1.1.1.8 root 5237: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 5238: rn = "EPC";
5239: break;
1.1.1.5 root 5240: default:
5241: goto die;
1.1.1.6 root 5242: }
1.1.1.5 root 5243: break;
5244: case 15:
5245: switch (sel) {
5246: case 0:
1.1.1.6 root 5247: /* ignored */
5248: rn = "PRid";
5249: break;
5250: case 1:
5251: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5252: gen_helper_mtc0_ebase(arg);
1.1.1.6 root 5253: rn = "EBase";
5254: break;
1.1.1.5 root 5255: default:
5256: goto die;
1.1.1.6 root 5257: }
1.1.1.5 root 5258: break;
5259: case 16:
5260: switch (sel) {
5261: case 0:
1.1.1.8 root 5262: gen_helper_mtc0_config0(arg);
1.1.1.5 root 5263: rn = "Config";
1.1.1.6 root 5264: /* Stop translation as we may have switched the execution mode */
5265: ctx->bstate = BS_STOP;
1.1.1.5 root 5266: break;
5267: case 1:
1.1.1.8 root 5268: /* ignored, read only */
1.1.1.5 root 5269: rn = "Config1";
5270: break;
5271: case 2:
1.1.1.8 root 5272: gen_helper_mtc0_config2(arg);
1.1.1.5 root 5273: rn = "Config2";
1.1.1.6 root 5274: /* Stop translation as we may have switched the execution mode */
5275: ctx->bstate = BS_STOP;
1.1.1.5 root 5276: break;
5277: case 3:
1.1.1.6 root 5278: /* ignored */
1.1.1.5 root 5279: rn = "Config3";
5280: break;
5281: /* 6,7 are implementation dependent */
5282: default:
5283: rn = "Invalid config selector";
5284: goto die;
5285: }
5286: break;
5287: case 17:
5288: switch (sel) {
5289: case 0:
1.1.1.9 root 5290: gen_helper_mtc0_lladdr(arg);
1.1.1.6 root 5291: rn = "LLAddr";
5292: break;
1.1.1.5 root 5293: default:
5294: goto die;
5295: }
5296: break;
5297: case 18:
5298: switch (sel) {
1.1.1.6 root 5299: case 0 ... 7:
1.1.1.8 root 5300: gen_helper_1i(mtc0_watchlo, arg, sel);
1.1.1.6 root 5301: rn = "WatchLo";
5302: break;
1.1.1.5 root 5303: default:
5304: goto die;
5305: }
5306: break;
5307: case 19:
5308: switch (sel) {
1.1.1.6 root 5309: case 0 ... 7:
1.1.1.8 root 5310: gen_helper_1i(mtc0_watchhi, arg, sel);
1.1.1.6 root 5311: rn = "WatchHi";
5312: break;
1.1.1.5 root 5313: default:
5314: goto die;
5315: }
5316: break;
5317: case 20:
5318: switch (sel) {
5319: case 0:
1.1.1.6 root 5320: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 5321: gen_helper_mtc0_xcontext(arg);
1.1.1.6 root 5322: rn = "XContext";
5323: break;
1.1.1.5 root 5324: default:
5325: goto die;
5326: }
5327: break;
5328: case 21:
5329: /* Officially reserved, but sel 0 is used for R1x000 framemask */
5330: switch (sel) {
5331: case 0:
1.1.1.8 root 5332: gen_helper_mtc0_framemask(arg);
1.1.1.6 root 5333: rn = "Framemask";
5334: break;
1.1.1.5 root 5335: default:
5336: goto die;
5337: }
5338: break;
5339: case 22:
5340: /* ignored */
5341: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 root 5342: break;
1.1.1.5 root 5343: case 23:
5344: switch (sel) {
5345: case 0:
1.1.1.8 root 5346: gen_helper_mtc0_debug(arg); /* EJTAG support */
1.1.1.6 root 5347: /* BS_STOP isn't good enough here, hflags may have changed. */
5348: gen_save_pc(ctx->pc + 4);
5349: ctx->bstate = BS_EXCP;
5350: rn = "Debug";
5351: break;
5352: case 1:
1.1.1.8 root 5353: // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 5354: /* Stop translation as we may have switched the execution mode */
5355: ctx->bstate = BS_STOP;
5356: rn = "TraceControl";
5357: // break;
5358: case 2:
1.1.1.8 root 5359: // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 5360: /* Stop translation as we may have switched the execution mode */
5361: ctx->bstate = BS_STOP;
5362: rn = "TraceControl2";
5363: // break;
5364: case 3:
1.1.1.8 root 5365: // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 5366: /* Stop translation as we may have switched the execution mode */
5367: ctx->bstate = BS_STOP;
5368: rn = "UserTraceData";
5369: // break;
1.1.1.5 root 5370: case 4:
1.1.1.8 root 5371: // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 5372: /* Stop translation as we may have switched the execution mode */
5373: ctx->bstate = BS_STOP;
5374: rn = "TraceBPC";
5375: // break;
1.1.1.5 root 5376: default:
5377: goto die;
5378: }
5379: break;
5380: case 24:
5381: switch (sel) {
5382: case 0:
1.1.1.7 root 5383: /* EJTAG support */
1.1.1.8 root 5384: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 5385: rn = "DEPC";
5386: break;
1.1.1.5 root 5387: default:
5388: goto die;
5389: }
5390: break;
5391: case 25:
5392: switch (sel) {
5393: case 0:
1.1.1.8 root 5394: gen_helper_mtc0_performance0(arg);
1.1.1.6 root 5395: rn = "Performance0";
5396: break;
5397: case 1:
1.1.1.8 root 5398: // gen_helper_mtc0_performance1(arg);
1.1.1.6 root 5399: rn = "Performance1";
5400: // break;
5401: case 2:
1.1.1.8 root 5402: // gen_helper_mtc0_performance2(arg);
1.1.1.6 root 5403: rn = "Performance2";
5404: // break;
1.1.1.5 root 5405: case 3:
1.1.1.8 root 5406: // gen_helper_mtc0_performance3(arg);
1.1.1.6 root 5407: rn = "Performance3";
5408: // break;
1.1.1.5 root 5409: case 4:
1.1.1.8 root 5410: // gen_helper_mtc0_performance4(arg);
1.1.1.6 root 5411: rn = "Performance4";
5412: // break;
1.1.1.5 root 5413: case 5:
1.1.1.8 root 5414: // gen_helper_mtc0_performance5(arg);
1.1.1.6 root 5415: rn = "Performance5";
5416: // break;
1.1.1.5 root 5417: case 6:
1.1.1.8 root 5418: // gen_helper_mtc0_performance6(arg);
1.1.1.6 root 5419: rn = "Performance6";
5420: // break;
1.1.1.5 root 5421: case 7:
1.1.1.8 root 5422: // gen_helper_mtc0_performance7(arg);
1.1.1.6 root 5423: rn = "Performance7";
5424: // break;
1.1.1.5 root 5425: default:
5426: goto die;
5427: }
1.1.1.6 root 5428: break;
1.1.1.5 root 5429: case 26:
1.1.1.6 root 5430: /* ignored */
1.1.1.5 root 5431: rn = "ECC";
1.1.1.6 root 5432: break;
1.1.1.5 root 5433: case 27:
5434: switch (sel) {
5435: case 0 ... 3:
1.1.1.6 root 5436: /* ignored */
5437: rn = "CacheErr";
5438: break;
1.1.1.5 root 5439: default:
5440: goto die;
5441: }
1.1.1.6 root 5442: break;
1.1.1.5 root 5443: case 28:
5444: switch (sel) {
5445: case 0:
5446: case 2:
5447: case 4:
5448: case 6:
1.1.1.8 root 5449: gen_helper_mtc0_taglo(arg);
1.1.1.5 root 5450: rn = "TagLo";
5451: break;
5452: case 1:
5453: case 3:
5454: case 5:
5455: case 7:
1.1.1.8 root 5456: gen_helper_mtc0_datalo(arg);
1.1.1.5 root 5457: rn = "DataLo";
5458: break;
5459: default:
5460: goto die;
5461: }
5462: break;
5463: case 29:
5464: switch (sel) {
5465: case 0:
5466: case 2:
5467: case 4:
5468: case 6:
1.1.1.8 root 5469: gen_helper_mtc0_taghi(arg);
1.1.1.5 root 5470: rn = "TagHi";
5471: break;
5472: case 1:
5473: case 3:
5474: case 5:
5475: case 7:
1.1.1.8 root 5476: gen_helper_mtc0_datahi(arg);
1.1.1.5 root 5477: rn = "DataHi";
5478: break;
5479: default:
5480: rn = "invalid sel";
5481: goto die;
5482: }
1.1.1.6 root 5483: break;
1.1.1.5 root 5484: case 30:
5485: switch (sel) {
5486: case 0:
1.1.1.8 root 5487: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 5488: rn = "ErrorEPC";
5489: break;
1.1.1.5 root 5490: default:
5491: goto die;
5492: }
5493: break;
5494: case 31:
5495: switch (sel) {
5496: case 0:
1.1.1.7 root 5497: /* EJTAG support */
1.1.1.8 root 5498: gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 5499: rn = "DESAVE";
5500: break;
1.1.1.5 root 5501: default:
5502: goto die;
5503: }
1.1.1.6 root 5504: /* Stop translation as we may have switched the execution mode */
5505: ctx->bstate = BS_STOP;
1.1.1.5 root 5506: break;
5507: default:
1.1.1.6 root 5508: goto die;
1.1.1.5 root 5509: }
1.1.1.13 root 5510: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 5511: LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5512: /* For simplicity assume that all writes can cause interrupts. */
5513: if (use_icount) {
5514: gen_io_end();
5515: ctx->bstate = BS_STOP;
1.1.1.5 root 5516: }
5517: return;
5518:
5519: die:
1.1.1.7 root 5520: LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 5521: generate_exception(ctx, EXCP_RI);
5522: }
1.1.1.6 root 5523: #endif /* TARGET_MIPS64 */
1.1.1.5 root 5524:
1.1.1.7 root 5525: static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
1.1.1.6 root 5526: int u, int sel, int h)
1.1.1.5 root 5527: {
1.1.1.6 root 5528: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.7 root 5529: TCGv t0 = tcg_temp_local_new();
1.1.1.5 root 5530:
1.1.1.6 root 5531: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
1.1.1.7 root 5532: ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5533: (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5534: tcg_gen_movi_tl(t0, -1);
1.1.1.6 root 5535: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5536: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1.1.1.7 root 5537: tcg_gen_movi_tl(t0, -1);
1.1.1.6 root 5538: else if (u == 0) {
5539: switch (rt) {
1.1.1.15! root 5540: case 1:
! 5541: switch (sel) {
! 5542: case 1:
! 5543: gen_helper_mftc0_vpecontrol(t0);
! 5544: break;
! 5545: case 2:
! 5546: gen_helper_mftc0_vpeconf0(t0);
! 5547: break;
! 5548: default:
! 5549: goto die;
! 5550: break;
! 5551: }
! 5552: break;
1.1.1.6 root 5553: case 2:
5554: switch (sel) {
5555: case 1:
1.1.1.7 root 5556: gen_helper_mftc0_tcstatus(t0);
1.1.1.6 root 5557: break;
5558: case 2:
1.1.1.7 root 5559: gen_helper_mftc0_tcbind(t0);
1.1.1.6 root 5560: break;
5561: case 3:
1.1.1.7 root 5562: gen_helper_mftc0_tcrestart(t0);
1.1.1.6 root 5563: break;
5564: case 4:
1.1.1.7 root 5565: gen_helper_mftc0_tchalt(t0);
1.1.1.6 root 5566: break;
5567: case 5:
1.1.1.7 root 5568: gen_helper_mftc0_tccontext(t0);
1.1.1.6 root 5569: break;
5570: case 6:
1.1.1.7 root 5571: gen_helper_mftc0_tcschedule(t0);
1.1.1.6 root 5572: break;
5573: case 7:
1.1.1.7 root 5574: gen_helper_mftc0_tcschefback(t0);
1.1.1.6 root 5575: break;
5576: default:
1.1.1.7 root 5577: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5578: break;
5579: }
5580: break;
5581: case 10:
5582: switch (sel) {
5583: case 0:
1.1.1.7 root 5584: gen_helper_mftc0_entryhi(t0);
1.1.1.6 root 5585: break;
5586: default:
1.1.1.7 root 5587: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5588: break;
5589: }
5590: case 12:
5591: switch (sel) {
5592: case 0:
1.1.1.7 root 5593: gen_helper_mftc0_status(t0);
1.1.1.6 root 5594: break;
5595: default:
1.1.1.7 root 5596: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5597: break;
5598: }
1.1.1.15! root 5599: case 13:
! 5600: switch (sel) {
! 5601: case 0:
! 5602: gen_helper_mftc0_cause(t0);
! 5603: break;
! 5604: default:
! 5605: goto die;
! 5606: break;
! 5607: }
! 5608: break;
! 5609: case 14:
! 5610: switch (sel) {
! 5611: case 0:
! 5612: gen_helper_mftc0_epc(t0);
! 5613: break;
! 5614: default:
! 5615: goto die;
! 5616: break;
! 5617: }
! 5618: break;
! 5619: case 15:
! 5620: switch (sel) {
! 5621: case 1:
! 5622: gen_helper_mftc0_ebase(t0);
! 5623: break;
! 5624: default:
! 5625: goto die;
! 5626: break;
! 5627: }
! 5628: break;
! 5629: case 16:
! 5630: switch (sel) {
! 5631: case 0 ... 7:
! 5632: gen_helper_mftc0_configx(t0, tcg_const_tl(sel));
! 5633: break;
! 5634: default:
! 5635: goto die;
! 5636: break;
! 5637: }
! 5638: break;
1.1.1.6 root 5639: case 23:
5640: switch (sel) {
5641: case 0:
1.1.1.7 root 5642: gen_helper_mftc0_debug(t0);
1.1.1.6 root 5643: break;
5644: default:
1.1.1.7 root 5645: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5646: break;
5647: }
5648: break;
5649: default:
1.1.1.7 root 5650: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5651: }
5652: } else switch (sel) {
5653: /* GPR registers. */
5654: case 0:
1.1.1.7 root 5655: gen_helper_1i(mftgpr, t0, rt);
1.1.1.6 root 5656: break;
5657: /* Auxiliary CPU registers */
5658: case 1:
5659: switch (rt) {
5660: case 0:
1.1.1.7 root 5661: gen_helper_1i(mftlo, t0, 0);
1.1.1.6 root 5662: break;
5663: case 1:
1.1.1.7 root 5664: gen_helper_1i(mfthi, t0, 0);
1.1.1.6 root 5665: break;
5666: case 2:
1.1.1.7 root 5667: gen_helper_1i(mftacx, t0, 0);
1.1.1.6 root 5668: break;
5669: case 4:
1.1.1.7 root 5670: gen_helper_1i(mftlo, t0, 1);
1.1.1.6 root 5671: break;
5672: case 5:
1.1.1.7 root 5673: gen_helper_1i(mfthi, t0, 1);
1.1.1.6 root 5674: break;
5675: case 6:
1.1.1.7 root 5676: gen_helper_1i(mftacx, t0, 1);
1.1.1.6 root 5677: break;
5678: case 8:
1.1.1.7 root 5679: gen_helper_1i(mftlo, t0, 2);
1.1.1.6 root 5680: break;
5681: case 9:
1.1.1.7 root 5682: gen_helper_1i(mfthi, t0, 2);
1.1.1.6 root 5683: break;
5684: case 10:
1.1.1.7 root 5685: gen_helper_1i(mftacx, t0, 2);
1.1.1.6 root 5686: break;
5687: case 12:
1.1.1.7 root 5688: gen_helper_1i(mftlo, t0, 3);
1.1.1.6 root 5689: break;
5690: case 13:
1.1.1.7 root 5691: gen_helper_1i(mfthi, t0, 3);
1.1.1.6 root 5692: break;
5693: case 14:
1.1.1.7 root 5694: gen_helper_1i(mftacx, t0, 3);
1.1.1.6 root 5695: break;
5696: case 16:
1.1.1.7 root 5697: gen_helper_mftdsp(t0);
1.1.1.6 root 5698: break;
5699: default:
5700: goto die;
5701: }
5702: break;
5703: /* Floating point (COP1). */
5704: case 2:
5705: /* XXX: For now we support only a single FPU context. */
5706: if (h == 0) {
1.1.1.7 root 5707: TCGv_i32 fp0 = tcg_temp_new_i32();
5708:
5709: gen_load_fpr32(fp0, rt);
5710: tcg_gen_ext_i32_tl(t0, fp0);
5711: tcg_temp_free_i32(fp0);
1.1.1.6 root 5712: } else {
1.1.1.7 root 5713: TCGv_i32 fp0 = tcg_temp_new_i32();
5714:
5715: gen_load_fpr32h(fp0, rt);
5716: tcg_gen_ext_i32_tl(t0, fp0);
5717: tcg_temp_free_i32(fp0);
1.1.1.6 root 5718: }
5719: break;
5720: case 3:
5721: /* XXX: For now we support only a single FPU context. */
1.1.1.7 root 5722: gen_helper_1i(cfc1, t0, rt);
1.1.1.6 root 5723: break;
5724: /* COP2: Not implemented. */
5725: case 4:
5726: case 5:
5727: /* fall through */
5728: default:
5729: goto die;
5730: }
1.1.1.7 root 5731: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5732: gen_store_gpr(t0, rd);
5733: tcg_temp_free(t0);
1.1.1.6 root 5734: return;
5735:
5736: die:
1.1.1.7 root 5737: tcg_temp_free(t0);
5738: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1.1.1.6 root 5739: generate_exception(ctx, EXCP_RI);
5740: }
5741:
1.1.1.7 root 5742: static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
1.1.1.6 root 5743: int u, int sel, int h)
5744: {
5745: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.7 root 5746: TCGv t0 = tcg_temp_local_new();
1.1.1.6 root 5747:
1.1.1.7 root 5748: gen_load_gpr(t0, rt);
1.1.1.6 root 5749: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
1.1.1.7 root 5750: ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5751: (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1.1.1.6 root 5752: /* NOP */ ;
5753: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5754: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5755: /* NOP */ ;
5756: else if (u == 0) {
5757: switch (rd) {
1.1.1.15! root 5758: case 1:
! 5759: switch (sel) {
! 5760: case 1:
! 5761: gen_helper_mttc0_vpecontrol(t0);
! 5762: break;
! 5763: case 2:
! 5764: gen_helper_mttc0_vpeconf0(t0);
! 5765: break;
! 5766: default:
! 5767: goto die;
! 5768: break;
! 5769: }
! 5770: break;
1.1.1.6 root 5771: case 2:
5772: switch (sel) {
5773: case 1:
1.1.1.7 root 5774: gen_helper_mttc0_tcstatus(t0);
1.1.1.6 root 5775: break;
5776: case 2:
1.1.1.7 root 5777: gen_helper_mttc0_tcbind(t0);
1.1.1.6 root 5778: break;
5779: case 3:
1.1.1.7 root 5780: gen_helper_mttc0_tcrestart(t0);
1.1.1.6 root 5781: break;
5782: case 4:
1.1.1.7 root 5783: gen_helper_mttc0_tchalt(t0);
1.1.1.6 root 5784: break;
5785: case 5:
1.1.1.7 root 5786: gen_helper_mttc0_tccontext(t0);
1.1.1.6 root 5787: break;
5788: case 6:
1.1.1.7 root 5789: gen_helper_mttc0_tcschedule(t0);
1.1.1.6 root 5790: break;
5791: case 7:
1.1.1.7 root 5792: gen_helper_mttc0_tcschefback(t0);
1.1.1.6 root 5793: break;
5794: default:
1.1.1.7 root 5795: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5796: break;
5797: }
5798: break;
5799: case 10:
5800: switch (sel) {
5801: case 0:
1.1.1.7 root 5802: gen_helper_mttc0_entryhi(t0);
1.1.1.6 root 5803: break;
5804: default:
1.1.1.7 root 5805: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5806: break;
5807: }
5808: case 12:
5809: switch (sel) {
5810: case 0:
1.1.1.7 root 5811: gen_helper_mttc0_status(t0);
1.1.1.6 root 5812: break;
5813: default:
1.1.1.7 root 5814: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5815: break;
5816: }
1.1.1.15! root 5817: case 13:
! 5818: switch (sel) {
! 5819: case 0:
! 5820: gen_helper_mttc0_cause(t0);
! 5821: break;
! 5822: default:
! 5823: goto die;
! 5824: break;
! 5825: }
! 5826: break;
! 5827: case 15:
! 5828: switch (sel) {
! 5829: case 1:
! 5830: gen_helper_mttc0_ebase(t0);
! 5831: break;
! 5832: default:
! 5833: goto die;
! 5834: break;
! 5835: }
! 5836: break;
1.1.1.6 root 5837: case 23:
5838: switch (sel) {
5839: case 0:
1.1.1.7 root 5840: gen_helper_mttc0_debug(t0);
1.1.1.6 root 5841: break;
5842: default:
1.1.1.7 root 5843: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5844: break;
5845: }
5846: break;
5847: default:
1.1.1.7 root 5848: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5849: }
5850: } else switch (sel) {
5851: /* GPR registers. */
5852: case 0:
1.1.1.7 root 5853: gen_helper_1i(mttgpr, t0, rd);
1.1.1.6 root 5854: break;
5855: /* Auxiliary CPU registers */
5856: case 1:
5857: switch (rd) {
5858: case 0:
1.1.1.7 root 5859: gen_helper_1i(mttlo, t0, 0);
1.1.1.6 root 5860: break;
5861: case 1:
1.1.1.7 root 5862: gen_helper_1i(mtthi, t0, 0);
1.1.1.6 root 5863: break;
5864: case 2:
1.1.1.7 root 5865: gen_helper_1i(mttacx, t0, 0);
1.1.1.6 root 5866: break;
5867: case 4:
1.1.1.7 root 5868: gen_helper_1i(mttlo, t0, 1);
1.1.1.6 root 5869: break;
5870: case 5:
1.1.1.7 root 5871: gen_helper_1i(mtthi, t0, 1);
1.1.1.6 root 5872: break;
5873: case 6:
1.1.1.7 root 5874: gen_helper_1i(mttacx, t0, 1);
1.1.1.6 root 5875: break;
5876: case 8:
1.1.1.7 root 5877: gen_helper_1i(mttlo, t0, 2);
1.1.1.6 root 5878: break;
5879: case 9:
1.1.1.7 root 5880: gen_helper_1i(mtthi, t0, 2);
1.1.1.6 root 5881: break;
5882: case 10:
1.1.1.7 root 5883: gen_helper_1i(mttacx, t0, 2);
1.1.1.6 root 5884: break;
5885: case 12:
1.1.1.7 root 5886: gen_helper_1i(mttlo, t0, 3);
1.1.1.6 root 5887: break;
5888: case 13:
1.1.1.7 root 5889: gen_helper_1i(mtthi, t0, 3);
1.1.1.6 root 5890: break;
5891: case 14:
1.1.1.7 root 5892: gen_helper_1i(mttacx, t0, 3);
1.1.1.6 root 5893: break;
5894: case 16:
1.1.1.7 root 5895: gen_helper_mttdsp(t0);
1.1.1.6 root 5896: break;
5897: default:
5898: goto die;
5899: }
5900: break;
5901: /* Floating point (COP1). */
5902: case 2:
5903: /* XXX: For now we support only a single FPU context. */
5904: if (h == 0) {
1.1.1.7 root 5905: TCGv_i32 fp0 = tcg_temp_new_i32();
5906:
5907: tcg_gen_trunc_tl_i32(fp0, t0);
5908: gen_store_fpr32(fp0, rd);
5909: tcg_temp_free_i32(fp0);
1.1.1.6 root 5910: } else {
1.1.1.7 root 5911: TCGv_i32 fp0 = tcg_temp_new_i32();
5912:
5913: tcg_gen_trunc_tl_i32(fp0, t0);
5914: gen_store_fpr32h(fp0, rd);
5915: tcg_temp_free_i32(fp0);
1.1.1.6 root 5916: }
5917: break;
5918: case 3:
5919: /* XXX: For now we support only a single FPU context. */
1.1.1.7 root 5920: gen_helper_1i(ctc1, t0, rd);
1.1.1.6 root 5921: break;
5922: /* COP2: Not implemented. */
5923: case 4:
5924: case 5:
5925: /* fall through */
5926: default:
5927: goto die;
5928: }
1.1.1.7 root 5929: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5930: tcg_temp_free(t0);
1.1.1.6 root 5931: return;
5932:
5933: die:
1.1.1.7 root 5934: tcg_temp_free(t0);
5935: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1.1.1.6 root 5936: generate_exception(ctx, EXCP_RI);
5937: }
5938:
5939: static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5940: {
5941: const char *opn = "ldst";
1.1.1.5 root 5942:
5943: switch (opc) {
5944: case OPC_MFC0:
5945: if (rt == 0) {
1.1.1.6 root 5946: /* Treat as NOP. */
1.1.1.5 root 5947: return;
5948: }
1.1.1.8 root 5949: gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
1.1.1.5 root 5950: opn = "mfc0";
5951: break;
5952: case OPC_MTC0:
1.1.1.7 root 5953: {
1.1.1.8 root 5954: TCGv t0 = tcg_temp_new();
1.1.1.7 root 5955:
5956: gen_load_gpr(t0, rt);
5957: gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5958: tcg_temp_free(t0);
5959: }
1.1.1.5 root 5960: opn = "mtc0";
5961: break;
1.1.1.6 root 5962: #if defined(TARGET_MIPS64)
1.1.1.5 root 5963: case OPC_DMFC0:
1.1.1.6 root 5964: check_insn(env, ctx, ISA_MIPS3);
1.1.1.5 root 5965: if (rt == 0) {
1.1.1.6 root 5966: /* Treat as NOP. */
1.1.1.5 root 5967: return;
5968: }
1.1.1.8 root 5969: gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
1.1.1.5 root 5970: opn = "dmfc0";
5971: break;
5972: case OPC_DMTC0:
1.1.1.6 root 5973: check_insn(env, ctx, ISA_MIPS3);
1.1.1.7 root 5974: {
1.1.1.8 root 5975: TCGv t0 = tcg_temp_new();
1.1.1.7 root 5976:
5977: gen_load_gpr(t0, rt);
5978: gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5979: tcg_temp_free(t0);
5980: }
1.1.1.5 root 5981: opn = "dmtc0";
5982: break;
1.1.1.6 root 5983: #endif
5984: case OPC_MFTR:
5985: check_insn(env, ctx, ASE_MT);
5986: if (rd == 0) {
5987: /* Treat as NOP. */
5988: return;
5989: }
1.1.1.7 root 5990: gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5991: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5992: opn = "mftr";
5993: break;
5994: case OPC_MTTR:
5995: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 5996: gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5997: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5998: opn = "mttr";
5999: break;
1.1.1.5 root 6000: case OPC_TLBWI:
6001: opn = "tlbwi";
1.1.1.8 root 6002: if (!env->tlb->helper_tlbwi)
1.1.1.6 root 6003: goto die;
1.1.1.7 root 6004: gen_helper_tlbwi();
1.1.1.5 root 6005: break;
6006: case OPC_TLBWR:
6007: opn = "tlbwr";
1.1.1.8 root 6008: if (!env->tlb->helper_tlbwr)
1.1.1.6 root 6009: goto die;
1.1.1.7 root 6010: gen_helper_tlbwr();
1.1.1.5 root 6011: break;
6012: case OPC_TLBP:
6013: opn = "tlbp";
1.1.1.8 root 6014: if (!env->tlb->helper_tlbp)
1.1.1.6 root 6015: goto die;
1.1.1.7 root 6016: gen_helper_tlbp();
1.1.1.5 root 6017: break;
6018: case OPC_TLBR:
6019: opn = "tlbr";
1.1.1.8 root 6020: if (!env->tlb->helper_tlbr)
1.1.1.6 root 6021: goto die;
1.1.1.7 root 6022: gen_helper_tlbr();
1.1.1.5 root 6023: break;
6024: case OPC_ERET:
6025: opn = "eret";
1.1.1.6 root 6026: check_insn(env, ctx, ISA_MIPS2);
1.1.1.7 root 6027: gen_helper_eret();
1.1.1.5 root 6028: ctx->bstate = BS_EXCP;
6029: break;
6030: case OPC_DERET:
6031: opn = "deret";
1.1.1.6 root 6032: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 6033: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1.1.1.6 root 6034: MIPS_INVAL(opn);
1.1.1.5 root 6035: generate_exception(ctx, EXCP_RI);
6036: } else {
1.1.1.7 root 6037: gen_helper_deret();
1.1.1.5 root 6038: ctx->bstate = BS_EXCP;
6039: }
6040: break;
6041: case OPC_WAIT:
6042: opn = "wait";
1.1.1.6 root 6043: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
1.1.1.5 root 6044: /* If we get an exception, we want to restart at next instruction */
6045: ctx->pc += 4;
6046: save_cpu_state(ctx, 1);
6047: ctx->pc -= 4;
1.1.1.7 root 6048: gen_helper_wait();
1.1.1.5 root 6049: ctx->bstate = BS_EXCP;
6050: break;
6051: default:
1.1.1.6 root 6052: die:
6053: MIPS_INVAL(opn);
1.1.1.5 root 6054: generate_exception(ctx, EXCP_RI);
6055: return;
6056: }
1.1.1.13 root 6057: (void)opn; /* avoid a compiler warning */
1.1.1.5 root 6058: MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
6059: }
1.1.1.7 root 6060: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 6061:
6062: /* CP1 Branches (before delay slot) */
1.1.1.6 root 6063: static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
6064: int32_t cc, int32_t offset)
1.1.1.5 root 6065: {
6066: target_ulong btarget;
1.1.1.6 root 6067: const char *opn = "cp1 cond branch";
1.1.1.7 root 6068: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.6 root 6069:
6070: if (cc != 0)
6071: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
1.1.1.5 root 6072:
6073: btarget = ctx->pc + 4 + offset;
6074:
6075: switch (op) {
6076: case OPC_BC1F:
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 = "bc1f";
1.1.1.5 root 6082: goto not_likely;
6083: case OPC_BC1FL:
1.1.1.8 root 6084: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6085: tcg_gen_not_i32(t0, t0);
6086: tcg_gen_andi_i32(t0, t0, 1);
6087: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6088: opn = "bc1fl";
1.1.1.5 root 6089: goto likely;
6090: case OPC_BC1T:
1.1.1.8 root 6091: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6092: tcg_gen_andi_i32(t0, t0, 1);
6093: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6094: opn = "bc1t";
6095: goto not_likely;
1.1.1.5 root 6096: case OPC_BC1TL:
1.1.1.8 root 6097: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6098: tcg_gen_andi_i32(t0, t0, 1);
6099: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6100: opn = "bc1tl";
1.1.1.5 root 6101: likely:
6102: ctx->hflags |= MIPS_HFLAG_BL;
1.1.1.6 root 6103: break;
6104: case OPC_BC1FANY2:
1.1.1.7 root 6105: {
1.1.1.8 root 6106: TCGv_i32 t1 = tcg_temp_new_i32();
6107: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6108: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
1.1.1.12 root 6109: tcg_gen_nor_i32(t0, t0, t1);
1.1.1.8 root 6110: tcg_temp_free_i32(t1);
6111: tcg_gen_andi_i32(t0, t0, 1);
6112: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6113: }
1.1.1.6 root 6114: opn = "bc1any2f";
6115: goto not_likely;
6116: case OPC_BC1TANY2:
1.1.1.7 root 6117: {
1.1.1.8 root 6118: TCGv_i32 t1 = tcg_temp_new_i32();
6119: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6120: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6121: tcg_gen_or_i32(t0, t0, t1);
6122: tcg_temp_free_i32(t1);
6123: tcg_gen_andi_i32(t0, t0, 1);
6124: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6125: }
1.1.1.6 root 6126: opn = "bc1any2t";
6127: goto not_likely;
6128: case OPC_BC1FANY4:
1.1.1.7 root 6129: {
1.1.1.8 root 6130: TCGv_i32 t1 = tcg_temp_new_i32();
6131: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6132: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6133: tcg_gen_or_i32(t0, t0, t1);
6134: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6135: tcg_gen_or_i32(t0, t0, t1);
6136: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
1.1.1.12 root 6137: tcg_gen_nor_i32(t0, t0, t1);
1.1.1.8 root 6138: tcg_temp_free_i32(t1);
6139: tcg_gen_andi_i32(t0, t0, 1);
6140: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6141: }
1.1.1.6 root 6142: opn = "bc1any4f";
6143: goto not_likely;
6144: case OPC_BC1TANY4:
1.1.1.7 root 6145: {
1.1.1.8 root 6146: TCGv_i32 t1 = tcg_temp_new_i32();
6147: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6148: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6149: tcg_gen_or_i32(t0, t0, t1);
6150: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6151: tcg_gen_or_i32(t0, t0, t1);
6152: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6153: tcg_gen_or_i32(t0, t0, t1);
6154: tcg_temp_free_i32(t1);
6155: tcg_gen_andi_i32(t0, t0, 1);
6156: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6157: }
1.1.1.6 root 6158: opn = "bc1any4t";
6159: not_likely:
6160: ctx->hflags |= MIPS_HFLAG_BC;
1.1.1.5 root 6161: break;
1.1.1.6 root 6162: default:
6163: MIPS_INVAL(opn);
6164: generate_exception (ctx, EXCP_RI);
1.1.1.7 root 6165: goto out;
1.1.1.5 root 6166: }
1.1.1.13 root 6167: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 6168: MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
1.1.1.5 root 6169: ctx->hflags, btarget);
6170: ctx->btarget = btarget;
1.1.1.7 root 6171:
6172: out:
6173: tcg_temp_free_i32(t0);
1.1.1.5 root 6174: }
6175:
6176: /* Coprocessor 1 (FPU) */
1.1.1.6 root 6177:
6178: #define FOP(func, fmt) (((fmt) << 21) | (func))
6179:
1.1.1.12 root 6180: enum fopcode {
6181: OPC_ADD_S = FOP(0, FMT_S),
6182: OPC_SUB_S = FOP(1, FMT_S),
6183: OPC_MUL_S = FOP(2, FMT_S),
6184: OPC_DIV_S = FOP(3, FMT_S),
6185: OPC_SQRT_S = FOP(4, FMT_S),
6186: OPC_ABS_S = FOP(5, FMT_S),
6187: OPC_MOV_S = FOP(6, FMT_S),
6188: OPC_NEG_S = FOP(7, FMT_S),
6189: OPC_ROUND_L_S = FOP(8, FMT_S),
6190: OPC_TRUNC_L_S = FOP(9, FMT_S),
6191: OPC_CEIL_L_S = FOP(10, FMT_S),
6192: OPC_FLOOR_L_S = FOP(11, FMT_S),
6193: OPC_ROUND_W_S = FOP(12, FMT_S),
6194: OPC_TRUNC_W_S = FOP(13, FMT_S),
6195: OPC_CEIL_W_S = FOP(14, FMT_S),
6196: OPC_FLOOR_W_S = FOP(15, FMT_S),
6197: OPC_MOVCF_S = FOP(17, FMT_S),
6198: OPC_MOVZ_S = FOP(18, FMT_S),
6199: OPC_MOVN_S = FOP(19, FMT_S),
6200: OPC_RECIP_S = FOP(21, FMT_S),
6201: OPC_RSQRT_S = FOP(22, FMT_S),
6202: OPC_RECIP2_S = FOP(28, FMT_S),
6203: OPC_RECIP1_S = FOP(29, FMT_S),
6204: OPC_RSQRT1_S = FOP(30, FMT_S),
6205: OPC_RSQRT2_S = FOP(31, FMT_S),
6206: OPC_CVT_D_S = FOP(33, FMT_S),
6207: OPC_CVT_W_S = FOP(36, FMT_S),
6208: OPC_CVT_L_S = FOP(37, FMT_S),
6209: OPC_CVT_PS_S = FOP(38, FMT_S),
6210: OPC_CMP_F_S = FOP (48, FMT_S),
6211: OPC_CMP_UN_S = FOP (49, FMT_S),
6212: OPC_CMP_EQ_S = FOP (50, FMT_S),
6213: OPC_CMP_UEQ_S = FOP (51, FMT_S),
6214: OPC_CMP_OLT_S = FOP (52, FMT_S),
6215: OPC_CMP_ULT_S = FOP (53, FMT_S),
6216: OPC_CMP_OLE_S = FOP (54, FMT_S),
6217: OPC_CMP_ULE_S = FOP (55, FMT_S),
6218: OPC_CMP_SF_S = FOP (56, FMT_S),
6219: OPC_CMP_NGLE_S = FOP (57, FMT_S),
6220: OPC_CMP_SEQ_S = FOP (58, FMT_S),
6221: OPC_CMP_NGL_S = FOP (59, FMT_S),
6222: OPC_CMP_LT_S = FOP (60, FMT_S),
6223: OPC_CMP_NGE_S = FOP (61, FMT_S),
6224: OPC_CMP_LE_S = FOP (62, FMT_S),
6225: OPC_CMP_NGT_S = FOP (63, FMT_S),
6226:
6227: OPC_ADD_D = FOP(0, FMT_D),
6228: OPC_SUB_D = FOP(1, FMT_D),
6229: OPC_MUL_D = FOP(2, FMT_D),
6230: OPC_DIV_D = FOP(3, FMT_D),
6231: OPC_SQRT_D = FOP(4, FMT_D),
6232: OPC_ABS_D = FOP(5, FMT_D),
6233: OPC_MOV_D = FOP(6, FMT_D),
6234: OPC_NEG_D = FOP(7, FMT_D),
6235: OPC_ROUND_L_D = FOP(8, FMT_D),
6236: OPC_TRUNC_L_D = FOP(9, FMT_D),
6237: OPC_CEIL_L_D = FOP(10, FMT_D),
6238: OPC_FLOOR_L_D = FOP(11, FMT_D),
6239: OPC_ROUND_W_D = FOP(12, FMT_D),
6240: OPC_TRUNC_W_D = FOP(13, FMT_D),
6241: OPC_CEIL_W_D = FOP(14, FMT_D),
6242: OPC_FLOOR_W_D = FOP(15, FMT_D),
6243: OPC_MOVCF_D = FOP(17, FMT_D),
6244: OPC_MOVZ_D = FOP(18, FMT_D),
6245: OPC_MOVN_D = FOP(19, FMT_D),
6246: OPC_RECIP_D = FOP(21, FMT_D),
6247: OPC_RSQRT_D = FOP(22, FMT_D),
6248: OPC_RECIP2_D = FOP(28, FMT_D),
6249: OPC_RECIP1_D = FOP(29, FMT_D),
6250: OPC_RSQRT1_D = FOP(30, FMT_D),
6251: OPC_RSQRT2_D = FOP(31, FMT_D),
6252: OPC_CVT_S_D = FOP(32, FMT_D),
6253: OPC_CVT_W_D = FOP(36, FMT_D),
6254: OPC_CVT_L_D = FOP(37, FMT_D),
6255: OPC_CMP_F_D = FOP (48, FMT_D),
6256: OPC_CMP_UN_D = FOP (49, FMT_D),
6257: OPC_CMP_EQ_D = FOP (50, FMT_D),
6258: OPC_CMP_UEQ_D = FOP (51, FMT_D),
6259: OPC_CMP_OLT_D = FOP (52, FMT_D),
6260: OPC_CMP_ULT_D = FOP (53, FMT_D),
6261: OPC_CMP_OLE_D = FOP (54, FMT_D),
6262: OPC_CMP_ULE_D = FOP (55, FMT_D),
6263: OPC_CMP_SF_D = FOP (56, FMT_D),
6264: OPC_CMP_NGLE_D = FOP (57, FMT_D),
6265: OPC_CMP_SEQ_D = FOP (58, FMT_D),
6266: OPC_CMP_NGL_D = FOP (59, FMT_D),
6267: OPC_CMP_LT_D = FOP (60, FMT_D),
6268: OPC_CMP_NGE_D = FOP (61, FMT_D),
6269: OPC_CMP_LE_D = FOP (62, FMT_D),
6270: OPC_CMP_NGT_D = FOP (63, FMT_D),
6271:
6272: OPC_CVT_S_W = FOP(32, FMT_W),
6273: OPC_CVT_D_W = FOP(33, FMT_W),
6274: OPC_CVT_S_L = FOP(32, FMT_L),
6275: OPC_CVT_D_L = FOP(33, FMT_L),
6276: OPC_CVT_PS_PW = FOP(38, FMT_W),
6277:
6278: OPC_ADD_PS = FOP(0, FMT_PS),
6279: OPC_SUB_PS = FOP(1, FMT_PS),
6280: OPC_MUL_PS = FOP(2, FMT_PS),
6281: OPC_DIV_PS = FOP(3, FMT_PS),
6282: OPC_ABS_PS = FOP(5, FMT_PS),
6283: OPC_MOV_PS = FOP(6, FMT_PS),
6284: OPC_NEG_PS = FOP(7, FMT_PS),
6285: OPC_MOVCF_PS = FOP(17, FMT_PS),
6286: OPC_MOVZ_PS = FOP(18, FMT_PS),
6287: OPC_MOVN_PS = FOP(19, FMT_PS),
6288: OPC_ADDR_PS = FOP(24, FMT_PS),
6289: OPC_MULR_PS = FOP(26, FMT_PS),
6290: OPC_RECIP2_PS = FOP(28, FMT_PS),
6291: OPC_RECIP1_PS = FOP(29, FMT_PS),
6292: OPC_RSQRT1_PS = FOP(30, FMT_PS),
6293: OPC_RSQRT2_PS = FOP(31, FMT_PS),
6294:
6295: OPC_CVT_S_PU = FOP(32, FMT_PS),
6296: OPC_CVT_PW_PS = FOP(36, FMT_PS),
6297: OPC_CVT_S_PL = FOP(40, FMT_PS),
6298: OPC_PLL_PS = FOP(44, FMT_PS),
6299: OPC_PLU_PS = FOP(45, FMT_PS),
6300: OPC_PUL_PS = FOP(46, FMT_PS),
6301: OPC_PUU_PS = FOP(47, FMT_PS),
6302: OPC_CMP_F_PS = FOP (48, FMT_PS),
6303: OPC_CMP_UN_PS = FOP (49, FMT_PS),
6304: OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6305: OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6306: OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6307: OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6308: OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6309: OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6310: OPC_CMP_SF_PS = FOP (56, FMT_PS),
6311: OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6312: OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6313: OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6314: OPC_CMP_LT_PS = FOP (60, FMT_PS),
6315: OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6316: OPC_CMP_LE_PS = FOP (62, FMT_PS),
6317: OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6318: };
6319:
1.1.1.5 root 6320: static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6321: {
1.1.1.6 root 6322: const char *opn = "cp1 move";
1.1.1.8 root 6323: TCGv t0 = tcg_temp_new();
1.1.1.5 root 6324:
6325: switch (opc) {
6326: case OPC_MFC1:
1.1.1.7 root 6327: {
6328: TCGv_i32 fp0 = tcg_temp_new_i32();
6329:
6330: gen_load_fpr32(fp0, fs);
6331: tcg_gen_ext_i32_tl(t0, fp0);
6332: tcg_temp_free_i32(fp0);
6333: }
6334: gen_store_gpr(t0, rt);
1.1.1.5 root 6335: opn = "mfc1";
6336: break;
6337: case OPC_MTC1:
1.1.1.7 root 6338: gen_load_gpr(t0, rt);
6339: {
6340: TCGv_i32 fp0 = tcg_temp_new_i32();
6341:
6342: tcg_gen_trunc_tl_i32(fp0, t0);
6343: gen_store_fpr32(fp0, fs);
6344: tcg_temp_free_i32(fp0);
6345: }
1.1.1.5 root 6346: opn = "mtc1";
6347: break;
6348: case OPC_CFC1:
1.1.1.7 root 6349: gen_helper_1i(cfc1, t0, fs);
6350: gen_store_gpr(t0, rt);
1.1.1.5 root 6351: opn = "cfc1";
6352: break;
6353: case OPC_CTC1:
1.1.1.7 root 6354: gen_load_gpr(t0, rt);
6355: gen_helper_1i(ctc1, t0, fs);
1.1.1.5 root 6356: opn = "ctc1";
6357: break;
1.1.1.8 root 6358: #if defined(TARGET_MIPS64)
1.1.1.5 root 6359: case OPC_DMFC1:
1.1.1.8 root 6360: gen_load_fpr64(ctx, t0, fs);
1.1.1.7 root 6361: gen_store_gpr(t0, rt);
1.1.1.6 root 6362: opn = "dmfc1";
6363: break;
1.1.1.5 root 6364: case OPC_DMTC1:
1.1.1.7 root 6365: gen_load_gpr(t0, rt);
1.1.1.8 root 6366: gen_store_fpr64(ctx, t0, fs);
1.1.1.6 root 6367: opn = "dmtc1";
6368: break;
1.1.1.8 root 6369: #endif
1.1.1.6 root 6370: case OPC_MFHC1:
1.1.1.7 root 6371: {
6372: TCGv_i32 fp0 = tcg_temp_new_i32();
6373:
6374: gen_load_fpr32h(fp0, fs);
6375: tcg_gen_ext_i32_tl(t0, fp0);
6376: tcg_temp_free_i32(fp0);
6377: }
6378: gen_store_gpr(t0, rt);
1.1.1.6 root 6379: opn = "mfhc1";
6380: break;
6381: case OPC_MTHC1:
1.1.1.7 root 6382: gen_load_gpr(t0, rt);
6383: {
6384: TCGv_i32 fp0 = tcg_temp_new_i32();
6385:
6386: tcg_gen_trunc_tl_i32(fp0, t0);
6387: gen_store_fpr32h(fp0, fs);
6388: tcg_temp_free_i32(fp0);
6389: }
1.1.1.6 root 6390: opn = "mthc1";
6391: break;
1.1.1.5 root 6392: default:
1.1.1.6 root 6393: MIPS_INVAL(opn);
6394: generate_exception (ctx, EXCP_RI);
1.1.1.7 root 6395: goto out;
1.1.1.4 root 6396: }
1.1.1.13 root 6397: (void)opn; /* avoid a compiler warning */
1.1.1.4 root 6398: MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
1.1.1.7 root 6399:
6400: out:
6401: tcg_temp_free(t0);
1.1.1.4 root 6402: }
6403:
1.1.1.6 root 6404: static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6405: {
1.1.1.8 root 6406: int l1;
1.1.1.7 root 6407: TCGCond cond;
1.1.1.8 root 6408: TCGv_i32 t0;
6409:
6410: if (rd == 0) {
6411: /* Treat as NOP. */
6412: return;
6413: }
1.1.1.7 root 6414:
6415: if (tf)
6416: cond = TCG_COND_EQ;
6417: else
6418: cond = TCG_COND_NE;
6419:
1.1.1.8 root 6420: l1 = gen_new_label();
6421: t0 = tcg_temp_new_i32();
6422: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6423: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6424: tcg_temp_free_i32(t0);
6425: if (rs == 0) {
6426: tcg_gen_movi_tl(cpu_gpr[rd], 0);
6427: } else {
6428: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6429: }
1.1.1.7 root 6430: gen_set_label(l1);
6431: }
6432:
6433: static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6434: {
6435: int cond;
1.1.1.8 root 6436: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 6437: int l1 = gen_new_label();
6438:
6439: if (tf)
6440: cond = TCG_COND_EQ;
6441: else
6442: cond = TCG_COND_NE;
6443:
1.1.1.8 root 6444: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6445: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6446: gen_load_fpr32(t0, fs);
6447: gen_store_fpr32(t0, fd);
1.1.1.7 root 6448: gen_set_label(l1);
1.1.1.8 root 6449: tcg_temp_free_i32(t0);
1.1.1.7 root 6450: }
6451:
6452: static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6453: {
6454: int cond;
1.1.1.8 root 6455: TCGv_i32 t0 = tcg_temp_new_i32();
6456: TCGv_i64 fp0;
1.1.1.7 root 6457: int l1 = gen_new_label();
6458:
6459: if (tf)
6460: cond = TCG_COND_EQ;
6461: else
6462: cond = TCG_COND_NE;
6463:
1.1.1.8 root 6464: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6465: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6466: tcg_temp_free_i32(t0);
6467: fp0 = tcg_temp_new_i64();
1.1.1.7 root 6468: gen_load_fpr64(ctx, fp0, fs);
6469: gen_store_fpr64(ctx, fp0, fd);
6470: tcg_temp_free_i64(fp0);
1.1.1.8 root 6471: gen_set_label(l1);
1.1.1.7 root 6472: }
6473:
6474: static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6475: {
6476: int cond;
1.1.1.8 root 6477: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 6478: int l1 = gen_new_label();
6479: int l2 = gen_new_label();
1.1.1.4 root 6480:
1.1.1.7 root 6481: if (tf)
6482: cond = TCG_COND_EQ;
1.1.1.6 root 6483: else
1.1.1.7 root 6484: cond = TCG_COND_NE;
6485:
1.1.1.8 root 6486: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6487: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6488: gen_load_fpr32(t0, fs);
6489: gen_store_fpr32(t0, fd);
1.1.1.7 root 6490: gen_set_label(l1);
6491:
1.1.1.8 root 6492: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
6493: tcg_gen_brcondi_i32(cond, t0, 0, l2);
6494: gen_load_fpr32h(t0, fs);
6495: gen_store_fpr32h(t0, fd);
6496: tcg_temp_free_i32(t0);
1.1.1.7 root 6497: gen_set_label(l2);
1.1.1.6 root 6498: }
6499:
1.1.1.4 root 6500:
1.1.1.12 root 6501: static void gen_farith (DisasContext *ctx, enum fopcode op1,
1.1.1.6 root 6502: int ft, int fs, int fd, int cc)
1.1.1.4 root 6503: {
1.1.1.6 root 6504: const char *opn = "farith";
1.1.1.4 root 6505: const char *condnames[] = {
6506: "c.f",
6507: "c.un",
6508: "c.eq",
6509: "c.ueq",
6510: "c.olt",
6511: "c.ult",
6512: "c.ole",
6513: "c.ule",
6514: "c.sf",
6515: "c.ngle",
6516: "c.seq",
6517: "c.ngl",
6518: "c.lt",
6519: "c.nge",
6520: "c.le",
6521: "c.ngt",
6522: };
1.1.1.6 root 6523: const char *condnames_abs[] = {
6524: "cabs.f",
6525: "cabs.un",
6526: "cabs.eq",
6527: "cabs.ueq",
6528: "cabs.olt",
6529: "cabs.ult",
6530: "cabs.ole",
6531: "cabs.ule",
6532: "cabs.sf",
6533: "cabs.ngle",
6534: "cabs.seq",
6535: "cabs.ngl",
6536: "cabs.lt",
6537: "cabs.nge",
6538: "cabs.le",
6539: "cabs.ngt",
6540: };
6541: enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
1.1.1.5 root 6542: uint32_t func = ctx->opcode & 0x3f;
6543:
1.1.1.12 root 6544: switch (op1) {
6545: case OPC_ADD_S:
1.1.1.7 root 6546: {
6547: TCGv_i32 fp0 = tcg_temp_new_i32();
6548: TCGv_i32 fp1 = tcg_temp_new_i32();
6549:
6550: gen_load_fpr32(fp0, fs);
6551: gen_load_fpr32(fp1, ft);
6552: gen_helper_float_add_s(fp0, fp0, fp1);
6553: tcg_temp_free_i32(fp1);
6554: gen_store_fpr32(fp0, fd);
6555: tcg_temp_free_i32(fp0);
6556: }
1.1.1.6 root 6557: opn = "add.s";
6558: optype = BINOP;
6559: break;
1.1.1.12 root 6560: case OPC_SUB_S:
1.1.1.7 root 6561: {
6562: TCGv_i32 fp0 = tcg_temp_new_i32();
6563: TCGv_i32 fp1 = tcg_temp_new_i32();
6564:
6565: gen_load_fpr32(fp0, fs);
6566: gen_load_fpr32(fp1, ft);
6567: gen_helper_float_sub_s(fp0, fp0, fp1);
6568: tcg_temp_free_i32(fp1);
6569: gen_store_fpr32(fp0, fd);
6570: tcg_temp_free_i32(fp0);
6571: }
1.1.1.6 root 6572: opn = "sub.s";
6573: optype = BINOP;
6574: break;
1.1.1.12 root 6575: case OPC_MUL_S:
1.1.1.7 root 6576: {
6577: TCGv_i32 fp0 = tcg_temp_new_i32();
6578: TCGv_i32 fp1 = tcg_temp_new_i32();
6579:
6580: gen_load_fpr32(fp0, fs);
6581: gen_load_fpr32(fp1, ft);
6582: gen_helper_float_mul_s(fp0, fp0, fp1);
6583: tcg_temp_free_i32(fp1);
6584: gen_store_fpr32(fp0, fd);
6585: tcg_temp_free_i32(fp0);
6586: }
1.1.1.6 root 6587: opn = "mul.s";
6588: optype = BINOP;
6589: break;
1.1.1.12 root 6590: case OPC_DIV_S:
1.1.1.7 root 6591: {
6592: TCGv_i32 fp0 = tcg_temp_new_i32();
6593: TCGv_i32 fp1 = tcg_temp_new_i32();
6594:
6595: gen_load_fpr32(fp0, fs);
6596: gen_load_fpr32(fp1, ft);
6597: gen_helper_float_div_s(fp0, fp0, fp1);
6598: tcg_temp_free_i32(fp1);
6599: gen_store_fpr32(fp0, fd);
6600: tcg_temp_free_i32(fp0);
6601: }
1.1.1.6 root 6602: opn = "div.s";
6603: optype = BINOP;
6604: break;
1.1.1.12 root 6605: case OPC_SQRT_S:
1.1.1.7 root 6606: {
6607: TCGv_i32 fp0 = tcg_temp_new_i32();
6608:
6609: gen_load_fpr32(fp0, fs);
6610: gen_helper_float_sqrt_s(fp0, fp0);
6611: gen_store_fpr32(fp0, fd);
6612: tcg_temp_free_i32(fp0);
6613: }
1.1.1.6 root 6614: opn = "sqrt.s";
6615: break;
1.1.1.12 root 6616: case OPC_ABS_S:
1.1.1.7 root 6617: {
6618: TCGv_i32 fp0 = tcg_temp_new_i32();
6619:
6620: gen_load_fpr32(fp0, fs);
6621: gen_helper_float_abs_s(fp0, fp0);
6622: gen_store_fpr32(fp0, fd);
6623: tcg_temp_free_i32(fp0);
6624: }
1.1.1.6 root 6625: opn = "abs.s";
6626: break;
1.1.1.12 root 6627: case OPC_MOV_S:
1.1.1.7 root 6628: {
6629: TCGv_i32 fp0 = tcg_temp_new_i32();
6630:
6631: gen_load_fpr32(fp0, fs);
6632: gen_store_fpr32(fp0, fd);
6633: tcg_temp_free_i32(fp0);
6634: }
1.1.1.6 root 6635: opn = "mov.s";
6636: break;
1.1.1.12 root 6637: case OPC_NEG_S:
1.1.1.7 root 6638: {
6639: TCGv_i32 fp0 = tcg_temp_new_i32();
6640:
6641: gen_load_fpr32(fp0, fs);
6642: gen_helper_float_chs_s(fp0, fp0);
6643: gen_store_fpr32(fp0, fd);
6644: tcg_temp_free_i32(fp0);
6645: }
1.1.1.6 root 6646: opn = "neg.s";
6647: break;
1.1.1.12 root 6648: case OPC_ROUND_L_S:
1.1.1.6 root 6649: check_cp1_64bitmode(ctx);
1.1.1.7 root 6650: {
6651: TCGv_i32 fp32 = tcg_temp_new_i32();
6652: TCGv_i64 fp64 = tcg_temp_new_i64();
6653:
6654: gen_load_fpr32(fp32, fs);
6655: gen_helper_float_roundl_s(fp64, fp32);
6656: tcg_temp_free_i32(fp32);
6657: gen_store_fpr64(ctx, fp64, fd);
6658: tcg_temp_free_i64(fp64);
6659: }
1.1.1.6 root 6660: opn = "round.l.s";
6661: break;
1.1.1.12 root 6662: case OPC_TRUNC_L_S:
1.1.1.6 root 6663: check_cp1_64bitmode(ctx);
1.1.1.7 root 6664: {
6665: TCGv_i32 fp32 = tcg_temp_new_i32();
6666: TCGv_i64 fp64 = tcg_temp_new_i64();
6667:
6668: gen_load_fpr32(fp32, fs);
6669: gen_helper_float_truncl_s(fp64, fp32);
6670: tcg_temp_free_i32(fp32);
6671: gen_store_fpr64(ctx, fp64, fd);
6672: tcg_temp_free_i64(fp64);
6673: }
1.1.1.6 root 6674: opn = "trunc.l.s";
6675: break;
1.1.1.12 root 6676: case OPC_CEIL_L_S:
1.1.1.6 root 6677: check_cp1_64bitmode(ctx);
1.1.1.7 root 6678: {
6679: TCGv_i32 fp32 = tcg_temp_new_i32();
6680: TCGv_i64 fp64 = tcg_temp_new_i64();
6681:
6682: gen_load_fpr32(fp32, fs);
6683: gen_helper_float_ceill_s(fp64, fp32);
6684: tcg_temp_free_i32(fp32);
6685: gen_store_fpr64(ctx, fp64, fd);
6686: tcg_temp_free_i64(fp64);
6687: }
1.1.1.6 root 6688: opn = "ceil.l.s";
6689: break;
1.1.1.12 root 6690: case OPC_FLOOR_L_S:
1.1.1.6 root 6691: check_cp1_64bitmode(ctx);
1.1.1.7 root 6692: {
6693: TCGv_i32 fp32 = tcg_temp_new_i32();
6694: TCGv_i64 fp64 = tcg_temp_new_i64();
6695:
6696: gen_load_fpr32(fp32, fs);
6697: gen_helper_float_floorl_s(fp64, fp32);
6698: tcg_temp_free_i32(fp32);
6699: gen_store_fpr64(ctx, fp64, fd);
6700: tcg_temp_free_i64(fp64);
6701: }
1.1.1.6 root 6702: opn = "floor.l.s";
6703: break;
1.1.1.12 root 6704: case OPC_ROUND_W_S:
1.1.1.7 root 6705: {
6706: TCGv_i32 fp0 = tcg_temp_new_i32();
6707:
6708: gen_load_fpr32(fp0, fs);
6709: gen_helper_float_roundw_s(fp0, fp0);
6710: gen_store_fpr32(fp0, fd);
6711: tcg_temp_free_i32(fp0);
6712: }
1.1.1.6 root 6713: opn = "round.w.s";
6714: break;
1.1.1.12 root 6715: case OPC_TRUNC_W_S:
1.1.1.7 root 6716: {
6717: TCGv_i32 fp0 = tcg_temp_new_i32();
6718:
6719: gen_load_fpr32(fp0, fs);
6720: gen_helper_float_truncw_s(fp0, fp0);
6721: gen_store_fpr32(fp0, fd);
6722: tcg_temp_free_i32(fp0);
6723: }
1.1.1.6 root 6724: opn = "trunc.w.s";
6725: break;
1.1.1.12 root 6726: case OPC_CEIL_W_S:
1.1.1.7 root 6727: {
6728: TCGv_i32 fp0 = tcg_temp_new_i32();
6729:
6730: gen_load_fpr32(fp0, fs);
6731: gen_helper_float_ceilw_s(fp0, fp0);
6732: gen_store_fpr32(fp0, fd);
6733: tcg_temp_free_i32(fp0);
6734: }
1.1.1.6 root 6735: opn = "ceil.w.s";
6736: break;
1.1.1.12 root 6737: case OPC_FLOOR_W_S:
1.1.1.7 root 6738: {
6739: TCGv_i32 fp0 = tcg_temp_new_i32();
6740:
6741: gen_load_fpr32(fp0, fs);
6742: gen_helper_float_floorw_s(fp0, fp0);
6743: gen_store_fpr32(fp0, fd);
6744: tcg_temp_free_i32(fp0);
6745: }
1.1.1.6 root 6746: opn = "floor.w.s";
6747: break;
1.1.1.12 root 6748: case OPC_MOVCF_S:
1.1.1.7 root 6749: gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 6750: opn = "movcf.s";
6751: break;
1.1.1.12 root 6752: case OPC_MOVZ_S:
1.1.1.7 root 6753: {
6754: int l1 = gen_new_label();
1.1.1.8 root 6755: TCGv_i32 fp0;
1.1.1.7 root 6756:
1.1.1.8 root 6757: if (ft != 0) {
6758: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6759: }
6760: fp0 = tcg_temp_new_i32();
1.1.1.7 root 6761: gen_load_fpr32(fp0, fs);
6762: gen_store_fpr32(fp0, fd);
6763: tcg_temp_free_i32(fp0);
6764: gen_set_label(l1);
6765: }
1.1.1.6 root 6766: opn = "movz.s";
6767: break;
1.1.1.12 root 6768: case OPC_MOVN_S:
1.1.1.7 root 6769: {
6770: int l1 = gen_new_label();
1.1.1.8 root 6771: TCGv_i32 fp0;
1.1.1.7 root 6772:
1.1.1.8 root 6773: if (ft != 0) {
6774: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6775: fp0 = tcg_temp_new_i32();
6776: gen_load_fpr32(fp0, fs);
6777: gen_store_fpr32(fp0, fd);
6778: tcg_temp_free_i32(fp0);
6779: gen_set_label(l1);
6780: }
1.1.1.7 root 6781: }
1.1.1.6 root 6782: opn = "movn.s";
6783: break;
1.1.1.12 root 6784: case OPC_RECIP_S:
1.1.1.6 root 6785: check_cop1x(ctx);
1.1.1.7 root 6786: {
6787: TCGv_i32 fp0 = tcg_temp_new_i32();
6788:
6789: gen_load_fpr32(fp0, fs);
6790: gen_helper_float_recip_s(fp0, fp0);
6791: gen_store_fpr32(fp0, fd);
6792: tcg_temp_free_i32(fp0);
6793: }
1.1.1.6 root 6794: opn = "recip.s";
6795: break;
1.1.1.12 root 6796: case OPC_RSQRT_S:
1.1.1.6 root 6797: check_cop1x(ctx);
1.1.1.7 root 6798: {
6799: TCGv_i32 fp0 = tcg_temp_new_i32();
6800:
6801: gen_load_fpr32(fp0, fs);
6802: gen_helper_float_rsqrt_s(fp0, fp0);
6803: gen_store_fpr32(fp0, fd);
6804: tcg_temp_free_i32(fp0);
6805: }
1.1.1.6 root 6806: opn = "rsqrt.s";
6807: break;
1.1.1.12 root 6808: case OPC_RECIP2_S:
1.1.1.6 root 6809: check_cp1_64bitmode(ctx);
1.1.1.7 root 6810: {
6811: TCGv_i32 fp0 = tcg_temp_new_i32();
6812: TCGv_i32 fp1 = tcg_temp_new_i32();
6813:
6814: gen_load_fpr32(fp0, fs);
6815: gen_load_fpr32(fp1, fd);
6816: gen_helper_float_recip2_s(fp0, fp0, fp1);
6817: tcg_temp_free_i32(fp1);
6818: gen_store_fpr32(fp0, fd);
6819: tcg_temp_free_i32(fp0);
6820: }
1.1.1.6 root 6821: opn = "recip2.s";
6822: break;
1.1.1.12 root 6823: case OPC_RECIP1_S:
1.1.1.6 root 6824: check_cp1_64bitmode(ctx);
1.1.1.7 root 6825: {
6826: TCGv_i32 fp0 = tcg_temp_new_i32();
6827:
6828: gen_load_fpr32(fp0, fs);
6829: gen_helper_float_recip1_s(fp0, fp0);
6830: gen_store_fpr32(fp0, fd);
6831: tcg_temp_free_i32(fp0);
6832: }
1.1.1.6 root 6833: opn = "recip1.s";
6834: break;
1.1.1.12 root 6835: case OPC_RSQRT1_S:
1.1.1.6 root 6836: check_cp1_64bitmode(ctx);
1.1.1.7 root 6837: {
6838: TCGv_i32 fp0 = tcg_temp_new_i32();
6839:
6840: gen_load_fpr32(fp0, fs);
6841: gen_helper_float_rsqrt1_s(fp0, fp0);
6842: gen_store_fpr32(fp0, fd);
6843: tcg_temp_free_i32(fp0);
6844: }
1.1.1.6 root 6845: opn = "rsqrt1.s";
6846: break;
1.1.1.12 root 6847: case OPC_RSQRT2_S:
1.1.1.6 root 6848: check_cp1_64bitmode(ctx);
1.1.1.7 root 6849: {
6850: TCGv_i32 fp0 = tcg_temp_new_i32();
6851: TCGv_i32 fp1 = tcg_temp_new_i32();
6852:
6853: gen_load_fpr32(fp0, fs);
6854: gen_load_fpr32(fp1, ft);
6855: gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6856: tcg_temp_free_i32(fp1);
6857: gen_store_fpr32(fp0, fd);
6858: tcg_temp_free_i32(fp0);
6859: }
1.1.1.6 root 6860: opn = "rsqrt2.s";
6861: break;
1.1.1.12 root 6862: case OPC_CVT_D_S:
1.1.1.6 root 6863: check_cp1_registers(ctx, fd);
1.1.1.7 root 6864: {
6865: TCGv_i32 fp32 = tcg_temp_new_i32();
6866: TCGv_i64 fp64 = tcg_temp_new_i64();
6867:
6868: gen_load_fpr32(fp32, fs);
6869: gen_helper_float_cvtd_s(fp64, fp32);
6870: tcg_temp_free_i32(fp32);
6871: gen_store_fpr64(ctx, fp64, fd);
6872: tcg_temp_free_i64(fp64);
6873: }
1.1.1.6 root 6874: opn = "cvt.d.s";
6875: break;
1.1.1.12 root 6876: case OPC_CVT_W_S:
1.1.1.7 root 6877: {
6878: TCGv_i32 fp0 = tcg_temp_new_i32();
6879:
6880: gen_load_fpr32(fp0, fs);
6881: gen_helper_float_cvtw_s(fp0, fp0);
6882: gen_store_fpr32(fp0, fd);
6883: tcg_temp_free_i32(fp0);
6884: }
1.1.1.6 root 6885: opn = "cvt.w.s";
6886: break;
1.1.1.12 root 6887: case OPC_CVT_L_S:
1.1.1.6 root 6888: check_cp1_64bitmode(ctx);
1.1.1.7 root 6889: {
6890: TCGv_i32 fp32 = tcg_temp_new_i32();
6891: TCGv_i64 fp64 = tcg_temp_new_i64();
6892:
6893: gen_load_fpr32(fp32, fs);
6894: gen_helper_float_cvtl_s(fp64, fp32);
6895: tcg_temp_free_i32(fp32);
6896: gen_store_fpr64(ctx, fp64, fd);
6897: tcg_temp_free_i64(fp64);
6898: }
1.1.1.6 root 6899: opn = "cvt.l.s";
6900: break;
1.1.1.12 root 6901: case OPC_CVT_PS_S:
1.1.1.6 root 6902: check_cp1_64bitmode(ctx);
1.1.1.7 root 6903: {
6904: TCGv_i64 fp64 = tcg_temp_new_i64();
6905: TCGv_i32 fp32_0 = tcg_temp_new_i32();
6906: TCGv_i32 fp32_1 = tcg_temp_new_i32();
6907:
6908: gen_load_fpr32(fp32_0, fs);
6909: gen_load_fpr32(fp32_1, ft);
6910: tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6911: tcg_temp_free_i32(fp32_1);
6912: tcg_temp_free_i32(fp32_0);
6913: gen_store_fpr64(ctx, fp64, fd);
6914: tcg_temp_free_i64(fp64);
6915: }
1.1.1.6 root 6916: opn = "cvt.ps.s";
6917: break;
1.1.1.12 root 6918: case OPC_CMP_F_S:
6919: case OPC_CMP_UN_S:
6920: case OPC_CMP_EQ_S:
6921: case OPC_CMP_UEQ_S:
6922: case OPC_CMP_OLT_S:
6923: case OPC_CMP_ULT_S:
6924: case OPC_CMP_OLE_S:
6925: case OPC_CMP_ULE_S:
6926: case OPC_CMP_SF_S:
6927: case OPC_CMP_NGLE_S:
6928: case OPC_CMP_SEQ_S:
6929: case OPC_CMP_NGL_S:
6930: case OPC_CMP_LT_S:
6931: case OPC_CMP_NGE_S:
6932: case OPC_CMP_LE_S:
6933: case OPC_CMP_NGT_S:
6934: if (ctx->opcode & (1 << 6)) {
6935: gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6936: opn = condnames_abs[func-48];
6937: } else {
6938: gen_cmp_s(ctx, func-48, ft, fs, cc);
6939: opn = condnames[func-48];
1.1.1.6 root 6940: }
6941: break;
1.1.1.12 root 6942: case OPC_ADD_D:
1.1.1.6 root 6943: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6944: {
6945: TCGv_i64 fp0 = tcg_temp_new_i64();
6946: TCGv_i64 fp1 = tcg_temp_new_i64();
6947:
6948: gen_load_fpr64(ctx, fp0, fs);
6949: gen_load_fpr64(ctx, fp1, ft);
6950: gen_helper_float_add_d(fp0, fp0, fp1);
6951: tcg_temp_free_i64(fp1);
6952: gen_store_fpr64(ctx, fp0, fd);
6953: tcg_temp_free_i64(fp0);
6954: }
1.1.1.4 root 6955: opn = "add.d";
1.1.1.6 root 6956: optype = BINOP;
1.1.1.4 root 6957: break;
1.1.1.12 root 6958: case OPC_SUB_D:
1.1.1.6 root 6959: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6960: {
6961: TCGv_i64 fp0 = tcg_temp_new_i64();
6962: TCGv_i64 fp1 = tcg_temp_new_i64();
6963:
6964: gen_load_fpr64(ctx, fp0, fs);
6965: gen_load_fpr64(ctx, fp1, ft);
6966: gen_helper_float_sub_d(fp0, fp0, fp1);
6967: tcg_temp_free_i64(fp1);
6968: gen_store_fpr64(ctx, fp0, fd);
6969: tcg_temp_free_i64(fp0);
6970: }
1.1.1.4 root 6971: opn = "sub.d";
1.1.1.6 root 6972: optype = BINOP;
1.1.1.4 root 6973: break;
1.1.1.12 root 6974: case OPC_MUL_D:
1.1.1.6 root 6975: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6976: {
6977: TCGv_i64 fp0 = tcg_temp_new_i64();
6978: TCGv_i64 fp1 = tcg_temp_new_i64();
6979:
6980: gen_load_fpr64(ctx, fp0, fs);
6981: gen_load_fpr64(ctx, fp1, ft);
6982: gen_helper_float_mul_d(fp0, fp0, fp1);
6983: tcg_temp_free_i64(fp1);
6984: gen_store_fpr64(ctx, fp0, fd);
6985: tcg_temp_free_i64(fp0);
6986: }
1.1.1.4 root 6987: opn = "mul.d";
1.1.1.6 root 6988: optype = BINOP;
1.1.1.4 root 6989: break;
1.1.1.12 root 6990: case OPC_DIV_D:
1.1.1.6 root 6991: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6992: {
6993: TCGv_i64 fp0 = tcg_temp_new_i64();
6994: TCGv_i64 fp1 = tcg_temp_new_i64();
6995:
6996: gen_load_fpr64(ctx, fp0, fs);
6997: gen_load_fpr64(ctx, fp1, ft);
6998: gen_helper_float_div_d(fp0, fp0, fp1);
6999: tcg_temp_free_i64(fp1);
7000: gen_store_fpr64(ctx, fp0, fd);
7001: tcg_temp_free_i64(fp0);
7002: }
1.1.1.4 root 7003: opn = "div.d";
1.1.1.6 root 7004: optype = BINOP;
1.1.1.4 root 7005: break;
1.1.1.12 root 7006: case OPC_SQRT_D:
1.1.1.6 root 7007: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 7008: {
7009: TCGv_i64 fp0 = tcg_temp_new_i64();
7010:
7011: gen_load_fpr64(ctx, fp0, fs);
7012: gen_helper_float_sqrt_d(fp0, fp0);
7013: gen_store_fpr64(ctx, fp0, fd);
7014: tcg_temp_free_i64(fp0);
7015: }
1.1.1.4 root 7016: opn = "sqrt.d";
7017: break;
1.1.1.12 root 7018: case OPC_ABS_D:
1.1.1.6 root 7019: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 7020: {
7021: TCGv_i64 fp0 = tcg_temp_new_i64();
7022:
7023: gen_load_fpr64(ctx, fp0, fs);
7024: gen_helper_float_abs_d(fp0, fp0);
7025: gen_store_fpr64(ctx, fp0, fd);
7026: tcg_temp_free_i64(fp0);
7027: }
1.1.1.4 root 7028: opn = "abs.d";
7029: break;
1.1.1.12 root 7030: case OPC_MOV_D:
1.1.1.6 root 7031: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 7032: {
7033: TCGv_i64 fp0 = tcg_temp_new_i64();
7034:
7035: gen_load_fpr64(ctx, fp0, fs);
7036: gen_store_fpr64(ctx, fp0, fd);
7037: tcg_temp_free_i64(fp0);
7038: }
1.1.1.4 root 7039: opn = "mov.d";
7040: break;
1.1.1.12 root 7041: case OPC_NEG_D:
1.1.1.6 root 7042: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 7043: {
7044: TCGv_i64 fp0 = tcg_temp_new_i64();
7045:
7046: gen_load_fpr64(ctx, fp0, fs);
7047: gen_helper_float_chs_d(fp0, fp0);
7048: gen_store_fpr64(ctx, fp0, fd);
7049: tcg_temp_free_i64(fp0);
7050: }
1.1.1.4 root 7051: opn = "neg.d";
7052: break;
1.1.1.12 root 7053: case OPC_ROUND_L_D:
1.1.1.6 root 7054: check_cp1_64bitmode(ctx);
1.1.1.7 root 7055: {
7056: TCGv_i64 fp0 = tcg_temp_new_i64();
7057:
7058: gen_load_fpr64(ctx, fp0, fs);
7059: gen_helper_float_roundl_d(fp0, fp0);
7060: gen_store_fpr64(ctx, fp0, fd);
7061: tcg_temp_free_i64(fp0);
7062: }
1.1.1.6 root 7063: opn = "round.l.d";
7064: break;
1.1.1.12 root 7065: case OPC_TRUNC_L_D:
1.1.1.6 root 7066: check_cp1_64bitmode(ctx);
1.1.1.7 root 7067: {
7068: TCGv_i64 fp0 = tcg_temp_new_i64();
7069:
7070: gen_load_fpr64(ctx, fp0, fs);
7071: gen_helper_float_truncl_d(fp0, fp0);
7072: gen_store_fpr64(ctx, fp0, fd);
7073: tcg_temp_free_i64(fp0);
7074: }
1.1.1.6 root 7075: opn = "trunc.l.d";
7076: break;
1.1.1.12 root 7077: case OPC_CEIL_L_D:
1.1.1.6 root 7078: check_cp1_64bitmode(ctx);
1.1.1.7 root 7079: {
7080: TCGv_i64 fp0 = tcg_temp_new_i64();
7081:
7082: gen_load_fpr64(ctx, fp0, fs);
7083: gen_helper_float_ceill_d(fp0, fp0);
7084: gen_store_fpr64(ctx, fp0, fd);
7085: tcg_temp_free_i64(fp0);
7086: }
1.1.1.6 root 7087: opn = "ceil.l.d";
7088: break;
1.1.1.12 root 7089: case OPC_FLOOR_L_D:
1.1.1.6 root 7090: check_cp1_64bitmode(ctx);
1.1.1.7 root 7091: {
7092: TCGv_i64 fp0 = tcg_temp_new_i64();
7093:
7094: gen_load_fpr64(ctx, fp0, fs);
7095: gen_helper_float_floorl_d(fp0, fp0);
7096: gen_store_fpr64(ctx, fp0, fd);
7097: tcg_temp_free_i64(fp0);
7098: }
1.1.1.6 root 7099: opn = "floor.l.d";
7100: break;
1.1.1.12 root 7101: case OPC_ROUND_W_D:
1.1.1.6 root 7102: check_cp1_registers(ctx, fs);
1.1.1.7 root 7103: {
7104: TCGv_i32 fp32 = tcg_temp_new_i32();
7105: TCGv_i64 fp64 = tcg_temp_new_i64();
7106:
7107: gen_load_fpr64(ctx, fp64, fs);
7108: gen_helper_float_roundw_d(fp32, fp64);
7109: tcg_temp_free_i64(fp64);
7110: gen_store_fpr32(fp32, fd);
7111: tcg_temp_free_i32(fp32);
7112: }
1.1.1.4 root 7113: opn = "round.w.d";
7114: break;
1.1.1.12 root 7115: case OPC_TRUNC_W_D:
1.1.1.6 root 7116: check_cp1_registers(ctx, fs);
1.1.1.7 root 7117: {
7118: TCGv_i32 fp32 = tcg_temp_new_i32();
7119: TCGv_i64 fp64 = tcg_temp_new_i64();
7120:
7121: gen_load_fpr64(ctx, fp64, fs);
7122: gen_helper_float_truncw_d(fp32, fp64);
7123: tcg_temp_free_i64(fp64);
7124: gen_store_fpr32(fp32, fd);
7125: tcg_temp_free_i32(fp32);
7126: }
1.1.1.4 root 7127: opn = "trunc.w.d";
7128: break;
1.1.1.12 root 7129: case OPC_CEIL_W_D:
1.1.1.6 root 7130: check_cp1_registers(ctx, fs);
1.1.1.7 root 7131: {
7132: TCGv_i32 fp32 = tcg_temp_new_i32();
7133: TCGv_i64 fp64 = tcg_temp_new_i64();
7134:
7135: gen_load_fpr64(ctx, fp64, fs);
7136: gen_helper_float_ceilw_d(fp32, fp64);
7137: tcg_temp_free_i64(fp64);
7138: gen_store_fpr32(fp32, fd);
7139: tcg_temp_free_i32(fp32);
7140: }
1.1.1.4 root 7141: opn = "ceil.w.d";
7142: break;
1.1.1.12 root 7143: case OPC_FLOOR_W_D:
1.1.1.6 root 7144: check_cp1_registers(ctx, fs);
1.1.1.7 root 7145: {
7146: TCGv_i32 fp32 = tcg_temp_new_i32();
7147: TCGv_i64 fp64 = tcg_temp_new_i64();
7148:
7149: gen_load_fpr64(ctx, fp64, fs);
7150: gen_helper_float_floorw_d(fp32, fp64);
7151: tcg_temp_free_i64(fp64);
7152: gen_store_fpr32(fp32, fd);
7153: tcg_temp_free_i32(fp32);
7154: }
1.1.1.5 root 7155: opn = "floor.w.d";
7156: break;
1.1.1.12 root 7157: case OPC_MOVCF_D:
1.1.1.7 root 7158: gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 7159: opn = "movcf.d";
1.1.1.4 root 7160: break;
1.1.1.12 root 7161: case OPC_MOVZ_D:
1.1.1.7 root 7162: {
7163: int l1 = gen_new_label();
1.1.1.8 root 7164: TCGv_i64 fp0;
1.1.1.7 root 7165:
1.1.1.8 root 7166: if (ft != 0) {
7167: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7168: }
7169: fp0 = tcg_temp_new_i64();
1.1.1.7 root 7170: gen_load_fpr64(ctx, fp0, fs);
7171: gen_store_fpr64(ctx, fp0, fd);
7172: tcg_temp_free_i64(fp0);
7173: gen_set_label(l1);
7174: }
1.1.1.6 root 7175: opn = "movz.d";
7176: break;
1.1.1.12 root 7177: case OPC_MOVN_D:
1.1.1.7 root 7178: {
7179: int l1 = gen_new_label();
1.1.1.8 root 7180: TCGv_i64 fp0;
1.1.1.7 root 7181:
1.1.1.8 root 7182: if (ft != 0) {
7183: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7184: fp0 = tcg_temp_new_i64();
7185: gen_load_fpr64(ctx, fp0, fs);
7186: gen_store_fpr64(ctx, fp0, fd);
7187: tcg_temp_free_i64(fp0);
7188: gen_set_label(l1);
7189: }
1.1.1.7 root 7190: }
1.1.1.6 root 7191: opn = "movn.d";
7192: break;
1.1.1.12 root 7193: case OPC_RECIP_D:
1.1.1.6 root 7194: check_cp1_64bitmode(ctx);
1.1.1.7 root 7195: {
7196: TCGv_i64 fp0 = tcg_temp_new_i64();
7197:
7198: gen_load_fpr64(ctx, fp0, fs);
7199: gen_helper_float_recip_d(fp0, fp0);
7200: gen_store_fpr64(ctx, fp0, fd);
7201: tcg_temp_free_i64(fp0);
7202: }
1.1.1.6 root 7203: opn = "recip.d";
7204: break;
1.1.1.12 root 7205: case OPC_RSQRT_D:
1.1.1.6 root 7206: check_cp1_64bitmode(ctx);
1.1.1.7 root 7207: {
7208: TCGv_i64 fp0 = tcg_temp_new_i64();
7209:
7210: gen_load_fpr64(ctx, fp0, fs);
7211: gen_helper_float_rsqrt_d(fp0, fp0);
7212: gen_store_fpr64(ctx, fp0, fd);
7213: tcg_temp_free_i64(fp0);
7214: }
1.1.1.6 root 7215: opn = "rsqrt.d";
7216: break;
1.1.1.12 root 7217: case OPC_RECIP2_D:
1.1.1.6 root 7218: check_cp1_64bitmode(ctx);
1.1.1.7 root 7219: {
7220: TCGv_i64 fp0 = tcg_temp_new_i64();
7221: TCGv_i64 fp1 = tcg_temp_new_i64();
7222:
7223: gen_load_fpr64(ctx, fp0, fs);
7224: gen_load_fpr64(ctx, fp1, ft);
7225: gen_helper_float_recip2_d(fp0, fp0, fp1);
7226: tcg_temp_free_i64(fp1);
7227: gen_store_fpr64(ctx, fp0, fd);
7228: tcg_temp_free_i64(fp0);
7229: }
1.1.1.6 root 7230: opn = "recip2.d";
7231: break;
1.1.1.12 root 7232: case OPC_RECIP1_D:
1.1.1.6 root 7233: check_cp1_64bitmode(ctx);
1.1.1.7 root 7234: {
7235: TCGv_i64 fp0 = tcg_temp_new_i64();
7236:
7237: gen_load_fpr64(ctx, fp0, fs);
7238: gen_helper_float_recip1_d(fp0, fp0);
7239: gen_store_fpr64(ctx, fp0, fd);
7240: tcg_temp_free_i64(fp0);
7241: }
1.1.1.6 root 7242: opn = "recip1.d";
7243: break;
1.1.1.12 root 7244: case OPC_RSQRT1_D:
1.1.1.6 root 7245: check_cp1_64bitmode(ctx);
1.1.1.7 root 7246: {
7247: TCGv_i64 fp0 = tcg_temp_new_i64();
7248:
7249: gen_load_fpr64(ctx, fp0, fs);
7250: gen_helper_float_rsqrt1_d(fp0, fp0);
7251: gen_store_fpr64(ctx, fp0, fd);
7252: tcg_temp_free_i64(fp0);
7253: }
1.1.1.6 root 7254: opn = "rsqrt1.d";
7255: break;
1.1.1.12 root 7256: case OPC_RSQRT2_D:
1.1.1.6 root 7257: check_cp1_64bitmode(ctx);
1.1.1.7 root 7258: {
7259: TCGv_i64 fp0 = tcg_temp_new_i64();
7260: TCGv_i64 fp1 = tcg_temp_new_i64();
7261:
7262: gen_load_fpr64(ctx, fp0, fs);
7263: gen_load_fpr64(ctx, fp1, ft);
7264: gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
7265: tcg_temp_free_i64(fp1);
7266: gen_store_fpr64(ctx, fp0, fd);
7267: tcg_temp_free_i64(fp0);
7268: }
1.1.1.6 root 7269: opn = "rsqrt2.d";
1.1.1.4 root 7270: break;
1.1.1.12 root 7271: case OPC_CMP_F_D:
7272: case OPC_CMP_UN_D:
7273: case OPC_CMP_EQ_D:
7274: case OPC_CMP_UEQ_D:
7275: case OPC_CMP_OLT_D:
7276: case OPC_CMP_ULT_D:
7277: case OPC_CMP_OLE_D:
7278: case OPC_CMP_ULE_D:
7279: case OPC_CMP_SF_D:
7280: case OPC_CMP_NGLE_D:
7281: case OPC_CMP_SEQ_D:
7282: case OPC_CMP_NGL_D:
7283: case OPC_CMP_LT_D:
7284: case OPC_CMP_NGE_D:
7285: case OPC_CMP_LE_D:
7286: case OPC_CMP_NGT_D:
7287: if (ctx->opcode & (1 << 6)) {
7288: gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7289: opn = condnames_abs[func-48];
7290: } else {
7291: gen_cmp_d(ctx, func-48, ft, fs, cc);
7292: opn = condnames[func-48];
1.1.1.6 root 7293: }
7294: break;
1.1.1.12 root 7295: case OPC_CVT_S_D:
1.1.1.6 root 7296: check_cp1_registers(ctx, fs);
1.1.1.7 root 7297: {
7298: TCGv_i32 fp32 = tcg_temp_new_i32();
7299: TCGv_i64 fp64 = tcg_temp_new_i64();
7300:
7301: gen_load_fpr64(ctx, fp64, fs);
7302: gen_helper_float_cvts_d(fp32, fp64);
7303: tcg_temp_free_i64(fp64);
7304: gen_store_fpr32(fp32, fd);
7305: tcg_temp_free_i32(fp32);
7306: }
1.1.1.6 root 7307: opn = "cvt.s.d";
7308: break;
1.1.1.12 root 7309: case OPC_CVT_W_D:
1.1.1.6 root 7310: check_cp1_registers(ctx, fs);
1.1.1.7 root 7311: {
7312: TCGv_i32 fp32 = tcg_temp_new_i32();
7313: TCGv_i64 fp64 = tcg_temp_new_i64();
7314:
7315: gen_load_fpr64(ctx, fp64, fs);
7316: gen_helper_float_cvtw_d(fp32, fp64);
7317: tcg_temp_free_i64(fp64);
7318: gen_store_fpr32(fp32, fd);
7319: tcg_temp_free_i32(fp32);
7320: }
1.1.1.6 root 7321: opn = "cvt.w.d";
7322: break;
1.1.1.12 root 7323: case OPC_CVT_L_D:
1.1.1.6 root 7324: check_cp1_64bitmode(ctx);
1.1.1.7 root 7325: {
7326: TCGv_i64 fp0 = tcg_temp_new_i64();
7327:
7328: gen_load_fpr64(ctx, fp0, fs);
7329: gen_helper_float_cvtl_d(fp0, fp0);
7330: gen_store_fpr64(ctx, fp0, fd);
7331: tcg_temp_free_i64(fp0);
7332: }
1.1.1.6 root 7333: opn = "cvt.l.d";
7334: break;
1.1.1.12 root 7335: case OPC_CVT_S_W:
1.1.1.7 root 7336: {
7337: TCGv_i32 fp0 = tcg_temp_new_i32();
7338:
7339: gen_load_fpr32(fp0, fs);
7340: gen_helper_float_cvts_w(fp0, fp0);
7341: gen_store_fpr32(fp0, fd);
7342: tcg_temp_free_i32(fp0);
7343: }
1.1.1.6 root 7344: opn = "cvt.s.w";
7345: break;
1.1.1.12 root 7346: case OPC_CVT_D_W:
1.1.1.6 root 7347: check_cp1_registers(ctx, fd);
1.1.1.7 root 7348: {
7349: TCGv_i32 fp32 = tcg_temp_new_i32();
7350: TCGv_i64 fp64 = tcg_temp_new_i64();
7351:
7352: gen_load_fpr32(fp32, fs);
7353: gen_helper_float_cvtd_w(fp64, fp32);
7354: tcg_temp_free_i32(fp32);
7355: gen_store_fpr64(ctx, fp64, fd);
7356: tcg_temp_free_i64(fp64);
7357: }
1.1.1.6 root 7358: opn = "cvt.d.w";
7359: break;
1.1.1.12 root 7360: case OPC_CVT_S_L:
1.1.1.6 root 7361: check_cp1_64bitmode(ctx);
1.1.1.7 root 7362: {
7363: TCGv_i32 fp32 = tcg_temp_new_i32();
7364: TCGv_i64 fp64 = tcg_temp_new_i64();
7365:
7366: gen_load_fpr64(ctx, fp64, fs);
7367: gen_helper_float_cvts_l(fp32, fp64);
7368: tcg_temp_free_i64(fp64);
7369: gen_store_fpr32(fp32, fd);
7370: tcg_temp_free_i32(fp32);
7371: }
1.1.1.6 root 7372: opn = "cvt.s.l";
7373: break;
1.1.1.12 root 7374: case OPC_CVT_D_L:
1.1.1.6 root 7375: check_cp1_64bitmode(ctx);
1.1.1.7 root 7376: {
7377: TCGv_i64 fp0 = tcg_temp_new_i64();
7378:
7379: gen_load_fpr64(ctx, fp0, fs);
7380: gen_helper_float_cvtd_l(fp0, fp0);
7381: gen_store_fpr64(ctx, fp0, fd);
7382: tcg_temp_free_i64(fp0);
7383: }
1.1.1.6 root 7384: opn = "cvt.d.l";
7385: break;
1.1.1.12 root 7386: case OPC_CVT_PS_PW:
1.1.1.6 root 7387: check_cp1_64bitmode(ctx);
1.1.1.7 root 7388: {
7389: TCGv_i64 fp0 = tcg_temp_new_i64();
7390:
7391: gen_load_fpr64(ctx, fp0, fs);
7392: gen_helper_float_cvtps_pw(fp0, fp0);
7393: gen_store_fpr64(ctx, fp0, fd);
7394: tcg_temp_free_i64(fp0);
7395: }
1.1.1.6 root 7396: opn = "cvt.ps.pw";
7397: break;
1.1.1.12 root 7398: case OPC_ADD_PS:
1.1.1.6 root 7399: check_cp1_64bitmode(ctx);
1.1.1.7 root 7400: {
7401: TCGv_i64 fp0 = tcg_temp_new_i64();
7402: TCGv_i64 fp1 = tcg_temp_new_i64();
7403:
7404: gen_load_fpr64(ctx, fp0, fs);
7405: gen_load_fpr64(ctx, fp1, ft);
7406: gen_helper_float_add_ps(fp0, fp0, fp1);
7407: tcg_temp_free_i64(fp1);
7408: gen_store_fpr64(ctx, fp0, fd);
7409: tcg_temp_free_i64(fp0);
7410: }
1.1.1.6 root 7411: opn = "add.ps";
7412: break;
1.1.1.12 root 7413: case OPC_SUB_PS:
1.1.1.6 root 7414: check_cp1_64bitmode(ctx);
1.1.1.7 root 7415: {
7416: TCGv_i64 fp0 = tcg_temp_new_i64();
7417: TCGv_i64 fp1 = tcg_temp_new_i64();
7418:
7419: gen_load_fpr64(ctx, fp0, fs);
7420: gen_load_fpr64(ctx, fp1, ft);
7421: gen_helper_float_sub_ps(fp0, fp0, fp1);
7422: tcg_temp_free_i64(fp1);
7423: gen_store_fpr64(ctx, fp0, fd);
7424: tcg_temp_free_i64(fp0);
7425: }
1.1.1.6 root 7426: opn = "sub.ps";
7427: break;
1.1.1.12 root 7428: case OPC_MUL_PS:
1.1.1.6 root 7429: check_cp1_64bitmode(ctx);
1.1.1.7 root 7430: {
7431: TCGv_i64 fp0 = tcg_temp_new_i64();
7432: TCGv_i64 fp1 = tcg_temp_new_i64();
7433:
7434: gen_load_fpr64(ctx, fp0, fs);
7435: gen_load_fpr64(ctx, fp1, ft);
7436: gen_helper_float_mul_ps(fp0, fp0, fp1);
7437: tcg_temp_free_i64(fp1);
7438: gen_store_fpr64(ctx, fp0, fd);
7439: tcg_temp_free_i64(fp0);
7440: }
1.1.1.6 root 7441: opn = "mul.ps";
7442: break;
1.1.1.12 root 7443: case OPC_ABS_PS:
1.1.1.6 root 7444: check_cp1_64bitmode(ctx);
1.1.1.7 root 7445: {
7446: TCGv_i64 fp0 = tcg_temp_new_i64();
7447:
7448: gen_load_fpr64(ctx, fp0, fs);
7449: gen_helper_float_abs_ps(fp0, fp0);
7450: gen_store_fpr64(ctx, fp0, fd);
7451: tcg_temp_free_i64(fp0);
7452: }
1.1.1.6 root 7453: opn = "abs.ps";
7454: break;
1.1.1.12 root 7455: case OPC_MOV_PS:
1.1.1.6 root 7456: check_cp1_64bitmode(ctx);
1.1.1.7 root 7457: {
7458: TCGv_i64 fp0 = tcg_temp_new_i64();
7459:
7460: gen_load_fpr64(ctx, fp0, fs);
7461: gen_store_fpr64(ctx, fp0, fd);
7462: tcg_temp_free_i64(fp0);
7463: }
1.1.1.6 root 7464: opn = "mov.ps";
7465: break;
1.1.1.12 root 7466: case OPC_NEG_PS:
1.1.1.6 root 7467: check_cp1_64bitmode(ctx);
1.1.1.7 root 7468: {
7469: TCGv_i64 fp0 = tcg_temp_new_i64();
7470:
7471: gen_load_fpr64(ctx, fp0, fs);
7472: gen_helper_float_chs_ps(fp0, fp0);
7473: gen_store_fpr64(ctx, fp0, fd);
7474: tcg_temp_free_i64(fp0);
7475: }
1.1.1.6 root 7476: opn = "neg.ps";
7477: break;
1.1.1.12 root 7478: case OPC_MOVCF_PS:
1.1.1.6 root 7479: check_cp1_64bitmode(ctx);
1.1.1.7 root 7480: gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 7481: opn = "movcf.ps";
7482: break;
1.1.1.12 root 7483: case OPC_MOVZ_PS:
1.1.1.6 root 7484: check_cp1_64bitmode(ctx);
1.1.1.7 root 7485: {
7486: int l1 = gen_new_label();
1.1.1.8 root 7487: TCGv_i64 fp0;
1.1.1.7 root 7488:
1.1.1.8 root 7489: if (ft != 0)
7490: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7491: fp0 = tcg_temp_new_i64();
7492: gen_load_fpr64(ctx, fp0, fs);
7493: gen_store_fpr64(ctx, fp0, fd);
7494: tcg_temp_free_i64(fp0);
1.1.1.7 root 7495: gen_set_label(l1);
7496: }
1.1.1.6 root 7497: opn = "movz.ps";
7498: break;
1.1.1.12 root 7499: case OPC_MOVN_PS:
1.1.1.6 root 7500: check_cp1_64bitmode(ctx);
1.1.1.7 root 7501: {
7502: int l1 = gen_new_label();
1.1.1.8 root 7503: TCGv_i64 fp0;
1.1.1.7 root 7504:
1.1.1.8 root 7505: if (ft != 0) {
7506: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7507: fp0 = tcg_temp_new_i64();
7508: gen_load_fpr64(ctx, fp0, fs);
7509: gen_store_fpr64(ctx, fp0, fd);
7510: tcg_temp_free_i64(fp0);
7511: gen_set_label(l1);
7512: }
1.1.1.7 root 7513: }
1.1.1.6 root 7514: opn = "movn.ps";
7515: break;
1.1.1.12 root 7516: case OPC_ADDR_PS:
1.1.1.6 root 7517: check_cp1_64bitmode(ctx);
1.1.1.7 root 7518: {
7519: TCGv_i64 fp0 = tcg_temp_new_i64();
7520: TCGv_i64 fp1 = tcg_temp_new_i64();
7521:
7522: gen_load_fpr64(ctx, fp0, ft);
7523: gen_load_fpr64(ctx, fp1, fs);
7524: gen_helper_float_addr_ps(fp0, fp0, fp1);
7525: tcg_temp_free_i64(fp1);
7526: gen_store_fpr64(ctx, fp0, fd);
7527: tcg_temp_free_i64(fp0);
7528: }
1.1.1.6 root 7529: opn = "addr.ps";
7530: break;
1.1.1.12 root 7531: case OPC_MULR_PS:
1.1.1.6 root 7532: check_cp1_64bitmode(ctx);
1.1.1.7 root 7533: {
7534: TCGv_i64 fp0 = tcg_temp_new_i64();
7535: TCGv_i64 fp1 = tcg_temp_new_i64();
7536:
7537: gen_load_fpr64(ctx, fp0, ft);
7538: gen_load_fpr64(ctx, fp1, fs);
7539: gen_helper_float_mulr_ps(fp0, fp0, fp1);
7540: tcg_temp_free_i64(fp1);
7541: gen_store_fpr64(ctx, fp0, fd);
7542: tcg_temp_free_i64(fp0);
7543: }
1.1.1.6 root 7544: opn = "mulr.ps";
7545: break;
1.1.1.12 root 7546: case OPC_RECIP2_PS:
1.1.1.6 root 7547: check_cp1_64bitmode(ctx);
1.1.1.7 root 7548: {
7549: TCGv_i64 fp0 = tcg_temp_new_i64();
7550: TCGv_i64 fp1 = tcg_temp_new_i64();
7551:
7552: gen_load_fpr64(ctx, fp0, fs);
7553: gen_load_fpr64(ctx, fp1, fd);
7554: gen_helper_float_recip2_ps(fp0, fp0, fp1);
7555: tcg_temp_free_i64(fp1);
7556: gen_store_fpr64(ctx, fp0, fd);
7557: tcg_temp_free_i64(fp0);
7558: }
1.1.1.6 root 7559: opn = "recip2.ps";
7560: break;
1.1.1.12 root 7561: case OPC_RECIP1_PS:
1.1.1.6 root 7562: check_cp1_64bitmode(ctx);
1.1.1.7 root 7563: {
7564: TCGv_i64 fp0 = tcg_temp_new_i64();
7565:
7566: gen_load_fpr64(ctx, fp0, fs);
7567: gen_helper_float_recip1_ps(fp0, fp0);
7568: gen_store_fpr64(ctx, fp0, fd);
7569: tcg_temp_free_i64(fp0);
7570: }
1.1.1.6 root 7571: opn = "recip1.ps";
7572: break;
1.1.1.12 root 7573: case OPC_RSQRT1_PS:
1.1.1.6 root 7574: check_cp1_64bitmode(ctx);
1.1.1.7 root 7575: {
7576: TCGv_i64 fp0 = tcg_temp_new_i64();
7577:
7578: gen_load_fpr64(ctx, fp0, fs);
7579: gen_helper_float_rsqrt1_ps(fp0, fp0);
7580: gen_store_fpr64(ctx, fp0, fd);
7581: tcg_temp_free_i64(fp0);
7582: }
1.1.1.6 root 7583: opn = "rsqrt1.ps";
7584: break;
1.1.1.12 root 7585: case OPC_RSQRT2_PS:
1.1.1.6 root 7586: check_cp1_64bitmode(ctx);
1.1.1.7 root 7587: {
7588: TCGv_i64 fp0 = tcg_temp_new_i64();
7589: TCGv_i64 fp1 = tcg_temp_new_i64();
7590:
7591: gen_load_fpr64(ctx, fp0, fs);
7592: gen_load_fpr64(ctx, fp1, ft);
7593: gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7594: tcg_temp_free_i64(fp1);
7595: gen_store_fpr64(ctx, fp0, fd);
7596: tcg_temp_free_i64(fp0);
7597: }
1.1.1.6 root 7598: opn = "rsqrt2.ps";
7599: break;
1.1.1.12 root 7600: case OPC_CVT_S_PU:
1.1.1.6 root 7601: check_cp1_64bitmode(ctx);
1.1.1.7 root 7602: {
7603: TCGv_i32 fp0 = tcg_temp_new_i32();
7604:
7605: gen_load_fpr32h(fp0, fs);
7606: gen_helper_float_cvts_pu(fp0, fp0);
7607: gen_store_fpr32(fp0, fd);
7608: tcg_temp_free_i32(fp0);
7609: }
1.1.1.6 root 7610: opn = "cvt.s.pu";
7611: break;
1.1.1.12 root 7612: case OPC_CVT_PW_PS:
1.1.1.6 root 7613: check_cp1_64bitmode(ctx);
1.1.1.7 root 7614: {
7615: TCGv_i64 fp0 = tcg_temp_new_i64();
7616:
7617: gen_load_fpr64(ctx, fp0, fs);
7618: gen_helper_float_cvtpw_ps(fp0, fp0);
7619: gen_store_fpr64(ctx, fp0, fd);
7620: tcg_temp_free_i64(fp0);
7621: }
1.1.1.6 root 7622: opn = "cvt.pw.ps";
1.1.1.4 root 7623: break;
1.1.1.12 root 7624: case OPC_CVT_S_PL:
1.1.1.6 root 7625: check_cp1_64bitmode(ctx);
1.1.1.7 root 7626: {
7627: TCGv_i32 fp0 = tcg_temp_new_i32();
7628:
7629: gen_load_fpr32(fp0, fs);
7630: gen_helper_float_cvts_pl(fp0, fp0);
7631: gen_store_fpr32(fp0, fd);
7632: tcg_temp_free_i32(fp0);
7633: }
1.1.1.6 root 7634: opn = "cvt.s.pl";
1.1.1.4 root 7635: break;
1.1.1.12 root 7636: case OPC_PLL_PS:
1.1.1.6 root 7637: check_cp1_64bitmode(ctx);
1.1.1.7 root 7638: {
7639: TCGv_i32 fp0 = tcg_temp_new_i32();
7640: TCGv_i32 fp1 = tcg_temp_new_i32();
7641:
7642: gen_load_fpr32(fp0, fs);
7643: gen_load_fpr32(fp1, ft);
7644: gen_store_fpr32h(fp0, fd);
7645: gen_store_fpr32(fp1, fd);
7646: tcg_temp_free_i32(fp0);
7647: tcg_temp_free_i32(fp1);
7648: }
1.1.1.6 root 7649: opn = "pll.ps";
1.1.1.4 root 7650: break;
1.1.1.12 root 7651: case OPC_PLU_PS:
1.1.1.6 root 7652: check_cp1_64bitmode(ctx);
1.1.1.7 root 7653: {
7654: TCGv_i32 fp0 = tcg_temp_new_i32();
7655: TCGv_i32 fp1 = tcg_temp_new_i32();
7656:
7657: gen_load_fpr32(fp0, fs);
7658: gen_load_fpr32h(fp1, ft);
7659: gen_store_fpr32(fp1, fd);
7660: gen_store_fpr32h(fp0, fd);
7661: tcg_temp_free_i32(fp0);
7662: tcg_temp_free_i32(fp1);
7663: }
1.1.1.6 root 7664: opn = "plu.ps";
7665: break;
1.1.1.12 root 7666: case OPC_PUL_PS:
1.1.1.6 root 7667: check_cp1_64bitmode(ctx);
1.1.1.7 root 7668: {
7669: TCGv_i32 fp0 = tcg_temp_new_i32();
7670: TCGv_i32 fp1 = tcg_temp_new_i32();
7671:
7672: gen_load_fpr32h(fp0, fs);
7673: gen_load_fpr32(fp1, ft);
7674: gen_store_fpr32(fp1, fd);
7675: gen_store_fpr32h(fp0, fd);
7676: tcg_temp_free_i32(fp0);
7677: tcg_temp_free_i32(fp1);
7678: }
1.1.1.6 root 7679: opn = "pul.ps";
1.1.1.4 root 7680: break;
1.1.1.12 root 7681: case OPC_PUU_PS:
1.1.1.6 root 7682: check_cp1_64bitmode(ctx);
1.1.1.7 root 7683: {
7684: TCGv_i32 fp0 = tcg_temp_new_i32();
7685: TCGv_i32 fp1 = tcg_temp_new_i32();
7686:
7687: gen_load_fpr32h(fp0, fs);
7688: gen_load_fpr32h(fp1, ft);
7689: gen_store_fpr32(fp1, fd);
7690: gen_store_fpr32h(fp0, fd);
7691: tcg_temp_free_i32(fp0);
7692: tcg_temp_free_i32(fp1);
7693: }
1.1.1.6 root 7694: opn = "puu.ps";
7695: break;
1.1.1.12 root 7696: case OPC_CMP_F_PS:
7697: case OPC_CMP_UN_PS:
7698: case OPC_CMP_EQ_PS:
7699: case OPC_CMP_UEQ_PS:
7700: case OPC_CMP_OLT_PS:
7701: case OPC_CMP_ULT_PS:
7702: case OPC_CMP_OLE_PS:
7703: case OPC_CMP_ULE_PS:
7704: case OPC_CMP_SF_PS:
7705: case OPC_CMP_NGLE_PS:
7706: case OPC_CMP_SEQ_PS:
7707: case OPC_CMP_NGL_PS:
7708: case OPC_CMP_LT_PS:
7709: case OPC_CMP_NGE_PS:
7710: case OPC_CMP_LE_PS:
7711: case OPC_CMP_NGT_PS:
7712: if (ctx->opcode & (1 << 6)) {
7713: gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7714: opn = condnames_abs[func-48];
7715: } else {
7716: gen_cmp_ps(ctx, func-48, ft, fs, cc);
7717: opn = condnames[func-48];
1.1.1.6 root 7718: }
1.1.1.4 root 7719: break;
1.1.1.6 root 7720: default:
7721: MIPS_INVAL(opn);
7722: generate_exception (ctx, EXCP_RI);
7723: return;
7724: }
1.1.1.13 root 7725: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 7726: switch (optype) {
7727: case BINOP:
7728: MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7729: break;
7730: case CMPOP:
7731: MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7732: break;
7733: default:
7734: MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7735: break;
7736: }
7737: }
7738:
7739: /* Coprocessor 3 (FPU) */
7740: static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7741: int fd, int fs, int base, int index)
7742: {
7743: const char *opn = "extended float load/store";
7744: int store = 0;
1.1.1.8 root 7745: TCGv t0 = tcg_temp_new();
1.1.1.6 root 7746:
7747: if (base == 0) {
1.1.1.7 root 7748: gen_load_gpr(t0, index);
1.1.1.6 root 7749: } else if (index == 0) {
1.1.1.7 root 7750: gen_load_gpr(t0, base);
1.1.1.6 root 7751: } else {
1.1.1.7 root 7752: gen_load_gpr(t0, index);
1.1.1.9 root 7753: gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
1.1.1.6 root 7754: }
7755: /* Don't do NOP if destination is zero: we must perform the actual
7756: memory access. */
1.1.1.8 root 7757: save_cpu_state(ctx, 0);
1.1.1.6 root 7758: switch (opc) {
7759: case OPC_LWXC1:
7760: check_cop1x(ctx);
1.1.1.7 root 7761: {
7762: TCGv_i32 fp0 = tcg_temp_new_i32();
7763:
1.1.1.8 root 7764: tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7765: tcg_gen_trunc_tl_i32(fp0, t0);
1.1.1.7 root 7766: gen_store_fpr32(fp0, fd);
7767: tcg_temp_free_i32(fp0);
7768: }
1.1.1.6 root 7769: opn = "lwxc1";
7770: break;
7771: case OPC_LDXC1:
7772: check_cop1x(ctx);
7773: check_cp1_registers(ctx, fd);
1.1.1.7 root 7774: {
7775: TCGv_i64 fp0 = tcg_temp_new_i64();
7776:
7777: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7778: gen_store_fpr64(ctx, fp0, fd);
7779: tcg_temp_free_i64(fp0);
7780: }
1.1.1.6 root 7781: opn = "ldxc1";
7782: break;
7783: case OPC_LUXC1:
7784: check_cp1_64bitmode(ctx);
1.1.1.7 root 7785: tcg_gen_andi_tl(t0, t0, ~0x7);
7786: {
7787: TCGv_i64 fp0 = tcg_temp_new_i64();
7788:
7789: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7790: gen_store_fpr64(ctx, fp0, fd);
7791: tcg_temp_free_i64(fp0);
7792: }
1.1.1.6 root 7793: opn = "luxc1";
7794: break;
7795: case OPC_SWXC1:
7796: check_cop1x(ctx);
1.1.1.7 root 7797: {
7798: TCGv_i32 fp0 = tcg_temp_new_i32();
1.1.1.8 root 7799: TCGv t1 = tcg_temp_new();
1.1.1.7 root 7800:
7801: gen_load_fpr32(fp0, fs);
7802: tcg_gen_extu_i32_tl(t1, fp0);
7803: tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7804: tcg_temp_free_i32(fp0);
1.1.1.8 root 7805: tcg_temp_free(t1);
1.1.1.7 root 7806: }
1.1.1.6 root 7807: opn = "swxc1";
7808: store = 1;
1.1.1.4 root 7809: break;
1.1.1.6 root 7810: case OPC_SDXC1:
7811: check_cop1x(ctx);
7812: check_cp1_registers(ctx, fs);
1.1.1.7 root 7813: {
7814: TCGv_i64 fp0 = tcg_temp_new_i64();
7815:
7816: gen_load_fpr64(ctx, fp0, fs);
7817: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7818: tcg_temp_free_i64(fp0);
7819: }
1.1.1.6 root 7820: opn = "sdxc1";
7821: store = 1;
7822: break;
7823: case OPC_SUXC1:
7824: check_cp1_64bitmode(ctx);
1.1.1.7 root 7825: tcg_gen_andi_tl(t0, t0, ~0x7);
7826: {
7827: TCGv_i64 fp0 = tcg_temp_new_i64();
7828:
7829: gen_load_fpr64(ctx, fp0, fs);
7830: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7831: tcg_temp_free_i64(fp0);
7832: }
1.1.1.6 root 7833: opn = "suxc1";
7834: store = 1;
7835: break;
7836: }
1.1.1.7 root 7837: tcg_temp_free(t0);
1.1.1.13 root 7838: (void)opn; (void)store; /* avoid compiler warnings */
1.1.1.6 root 7839: MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7840: regnames[index], regnames[base]);
7841: }
7842:
7843: static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7844: int fd, int fr, int fs, int ft)
7845: {
7846: const char *opn = "flt3_arith";
7847:
7848: switch (opc) {
7849: case OPC_ALNV_PS:
7850: check_cp1_64bitmode(ctx);
1.1.1.7 root 7851: {
7852: TCGv t0 = tcg_temp_local_new();
1.1.1.8 root 7853: TCGv_i32 fp = tcg_temp_new_i32();
7854: TCGv_i32 fph = tcg_temp_new_i32();
1.1.1.7 root 7855: int l1 = gen_new_label();
7856: int l2 = gen_new_label();
7857:
7858: gen_load_gpr(t0, fr);
7859: tcg_gen_andi_tl(t0, t0, 0x7);
7860:
7861: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
1.1.1.8 root 7862: gen_load_fpr32(fp, fs);
7863: gen_load_fpr32h(fph, fs);
7864: gen_store_fpr32(fp, fd);
7865: gen_store_fpr32h(fph, fd);
1.1.1.7 root 7866: tcg_gen_br(l2);
7867: gen_set_label(l1);
7868: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7869: tcg_temp_free(t0);
7870: #ifdef TARGET_WORDS_BIGENDIAN
1.1.1.8 root 7871: gen_load_fpr32(fp, fs);
7872: gen_load_fpr32h(fph, ft);
7873: gen_store_fpr32h(fp, fd);
7874: gen_store_fpr32(fph, fd);
1.1.1.7 root 7875: #else
1.1.1.8 root 7876: gen_load_fpr32h(fph, fs);
7877: gen_load_fpr32(fp, ft);
7878: gen_store_fpr32(fph, fd);
7879: gen_store_fpr32h(fp, fd);
1.1.1.7 root 7880: #endif
7881: gen_set_label(l2);
1.1.1.8 root 7882: tcg_temp_free_i32(fp);
7883: tcg_temp_free_i32(fph);
1.1.1.7 root 7884: }
1.1.1.6 root 7885: opn = "alnv.ps";
7886: break;
7887: case OPC_MADD_S:
7888: check_cop1x(ctx);
1.1.1.7 root 7889: {
7890: TCGv_i32 fp0 = tcg_temp_new_i32();
7891: TCGv_i32 fp1 = tcg_temp_new_i32();
7892: TCGv_i32 fp2 = tcg_temp_new_i32();
7893:
7894: gen_load_fpr32(fp0, fs);
7895: gen_load_fpr32(fp1, ft);
7896: gen_load_fpr32(fp2, fr);
7897: gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7898: tcg_temp_free_i32(fp0);
7899: tcg_temp_free_i32(fp1);
7900: gen_store_fpr32(fp2, fd);
7901: tcg_temp_free_i32(fp2);
7902: }
1.1.1.6 root 7903: opn = "madd.s";
1.1.1.4 root 7904: break;
1.1.1.6 root 7905: case OPC_MADD_D:
7906: check_cop1x(ctx);
7907: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7908: {
7909: TCGv_i64 fp0 = tcg_temp_new_i64();
7910: TCGv_i64 fp1 = tcg_temp_new_i64();
7911: TCGv_i64 fp2 = tcg_temp_new_i64();
7912:
7913: gen_load_fpr64(ctx, fp0, fs);
7914: gen_load_fpr64(ctx, fp1, ft);
7915: gen_load_fpr64(ctx, fp2, fr);
7916: gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7917: tcg_temp_free_i64(fp0);
7918: tcg_temp_free_i64(fp1);
7919: gen_store_fpr64(ctx, fp2, fd);
7920: tcg_temp_free_i64(fp2);
7921: }
1.1.1.6 root 7922: opn = "madd.d";
7923: break;
7924: case OPC_MADD_PS:
7925: check_cp1_64bitmode(ctx);
1.1.1.7 root 7926: {
7927: TCGv_i64 fp0 = tcg_temp_new_i64();
7928: TCGv_i64 fp1 = tcg_temp_new_i64();
7929: TCGv_i64 fp2 = tcg_temp_new_i64();
7930:
7931: gen_load_fpr64(ctx, fp0, fs);
7932: gen_load_fpr64(ctx, fp1, ft);
7933: gen_load_fpr64(ctx, fp2, fr);
7934: gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7935: tcg_temp_free_i64(fp0);
7936: tcg_temp_free_i64(fp1);
7937: gen_store_fpr64(ctx, fp2, fd);
7938: tcg_temp_free_i64(fp2);
7939: }
1.1.1.6 root 7940: opn = "madd.ps";
1.1.1.4 root 7941: break;
1.1.1.6 root 7942: case OPC_MSUB_S:
7943: check_cop1x(ctx);
1.1.1.7 root 7944: {
7945: TCGv_i32 fp0 = tcg_temp_new_i32();
7946: TCGv_i32 fp1 = tcg_temp_new_i32();
7947: TCGv_i32 fp2 = tcg_temp_new_i32();
7948:
7949: gen_load_fpr32(fp0, fs);
7950: gen_load_fpr32(fp1, ft);
7951: gen_load_fpr32(fp2, fr);
7952: gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7953: tcg_temp_free_i32(fp0);
7954: tcg_temp_free_i32(fp1);
7955: gen_store_fpr32(fp2, fd);
7956: tcg_temp_free_i32(fp2);
7957: }
1.1.1.6 root 7958: opn = "msub.s";
1.1.1.4 root 7959: break;
1.1.1.6 root 7960: case OPC_MSUB_D:
7961: check_cop1x(ctx);
7962: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7963: {
7964: TCGv_i64 fp0 = tcg_temp_new_i64();
7965: TCGv_i64 fp1 = tcg_temp_new_i64();
7966: TCGv_i64 fp2 = tcg_temp_new_i64();
7967:
7968: gen_load_fpr64(ctx, fp0, fs);
7969: gen_load_fpr64(ctx, fp1, ft);
7970: gen_load_fpr64(ctx, fp2, fr);
7971: gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7972: tcg_temp_free_i64(fp0);
7973: tcg_temp_free_i64(fp1);
7974: gen_store_fpr64(ctx, fp2, fd);
7975: tcg_temp_free_i64(fp2);
7976: }
1.1.1.6 root 7977: opn = "msub.d";
7978: break;
7979: case OPC_MSUB_PS:
7980: check_cp1_64bitmode(ctx);
1.1.1.7 root 7981: {
7982: TCGv_i64 fp0 = tcg_temp_new_i64();
7983: TCGv_i64 fp1 = tcg_temp_new_i64();
7984: TCGv_i64 fp2 = tcg_temp_new_i64();
7985:
7986: gen_load_fpr64(ctx, fp0, fs);
7987: gen_load_fpr64(ctx, fp1, ft);
7988: gen_load_fpr64(ctx, fp2, fr);
7989: gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7990: tcg_temp_free_i64(fp0);
7991: tcg_temp_free_i64(fp1);
7992: gen_store_fpr64(ctx, fp2, fd);
7993: tcg_temp_free_i64(fp2);
7994: }
1.1.1.6 root 7995: opn = "msub.ps";
1.1.1.4 root 7996: break;
1.1.1.6 root 7997: case OPC_NMADD_S:
7998: check_cop1x(ctx);
1.1.1.7 root 7999: {
8000: TCGv_i32 fp0 = tcg_temp_new_i32();
8001: TCGv_i32 fp1 = tcg_temp_new_i32();
8002: TCGv_i32 fp2 = tcg_temp_new_i32();
8003:
8004: gen_load_fpr32(fp0, fs);
8005: gen_load_fpr32(fp1, ft);
8006: gen_load_fpr32(fp2, fr);
8007: gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
8008: tcg_temp_free_i32(fp0);
8009: tcg_temp_free_i32(fp1);
8010: gen_store_fpr32(fp2, fd);
8011: tcg_temp_free_i32(fp2);
8012: }
1.1.1.6 root 8013: opn = "nmadd.s";
1.1.1.4 root 8014: break;
1.1.1.6 root 8015: case OPC_NMADD_D:
8016: check_cop1x(ctx);
8017: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 8018: {
8019: TCGv_i64 fp0 = tcg_temp_new_i64();
8020: TCGv_i64 fp1 = tcg_temp_new_i64();
8021: TCGv_i64 fp2 = tcg_temp_new_i64();
8022:
8023: gen_load_fpr64(ctx, fp0, fs);
8024: gen_load_fpr64(ctx, fp1, ft);
8025: gen_load_fpr64(ctx, fp2, fr);
8026: gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
8027: tcg_temp_free_i64(fp0);
8028: tcg_temp_free_i64(fp1);
8029: gen_store_fpr64(ctx, fp2, fd);
8030: tcg_temp_free_i64(fp2);
8031: }
1.1.1.6 root 8032: opn = "nmadd.d";
1.1.1.5 root 8033: break;
1.1.1.6 root 8034: case OPC_NMADD_PS:
8035: check_cp1_64bitmode(ctx);
1.1.1.7 root 8036: {
8037: TCGv_i64 fp0 = tcg_temp_new_i64();
8038: TCGv_i64 fp1 = tcg_temp_new_i64();
8039: TCGv_i64 fp2 = tcg_temp_new_i64();
8040:
8041: gen_load_fpr64(ctx, fp0, fs);
8042: gen_load_fpr64(ctx, fp1, ft);
8043: gen_load_fpr64(ctx, fp2, fr);
8044: gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
8045: tcg_temp_free_i64(fp0);
8046: tcg_temp_free_i64(fp1);
8047: gen_store_fpr64(ctx, fp2, fd);
8048: tcg_temp_free_i64(fp2);
8049: }
1.1.1.6 root 8050: opn = "nmadd.ps";
1.1.1.4 root 8051: break;
1.1.1.6 root 8052: case OPC_NMSUB_S:
8053: check_cop1x(ctx);
1.1.1.7 root 8054: {
8055: TCGv_i32 fp0 = tcg_temp_new_i32();
8056: TCGv_i32 fp1 = tcg_temp_new_i32();
8057: TCGv_i32 fp2 = tcg_temp_new_i32();
8058:
8059: gen_load_fpr32(fp0, fs);
8060: gen_load_fpr32(fp1, ft);
8061: gen_load_fpr32(fp2, fr);
8062: gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
8063: tcg_temp_free_i32(fp0);
8064: tcg_temp_free_i32(fp1);
8065: gen_store_fpr32(fp2, fd);
8066: tcg_temp_free_i32(fp2);
8067: }
1.1.1.6 root 8068: opn = "nmsub.s";
1.1.1.4 root 8069: break;
1.1.1.6 root 8070: case OPC_NMSUB_D:
8071: check_cop1x(ctx);
8072: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 8073: {
8074: TCGv_i64 fp0 = tcg_temp_new_i64();
8075: TCGv_i64 fp1 = tcg_temp_new_i64();
8076: TCGv_i64 fp2 = tcg_temp_new_i64();
8077:
8078: gen_load_fpr64(ctx, fp0, fs);
8079: gen_load_fpr64(ctx, fp1, ft);
8080: gen_load_fpr64(ctx, fp2, fr);
8081: gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
8082: tcg_temp_free_i64(fp0);
8083: tcg_temp_free_i64(fp1);
8084: gen_store_fpr64(ctx, fp2, fd);
8085: tcg_temp_free_i64(fp2);
8086: }
1.1.1.6 root 8087: opn = "nmsub.d";
1.1.1.4 root 8088: break;
1.1.1.6 root 8089: case OPC_NMSUB_PS:
8090: check_cp1_64bitmode(ctx);
1.1.1.7 root 8091: {
8092: TCGv_i64 fp0 = tcg_temp_new_i64();
8093: TCGv_i64 fp1 = tcg_temp_new_i64();
8094: TCGv_i64 fp2 = tcg_temp_new_i64();
8095:
8096: gen_load_fpr64(ctx, fp0, fs);
8097: gen_load_fpr64(ctx, fp1, ft);
8098: gen_load_fpr64(ctx, fp2, fr);
8099: gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
8100: tcg_temp_free_i64(fp0);
8101: tcg_temp_free_i64(fp1);
8102: gen_store_fpr64(ctx, fp2, fd);
8103: tcg_temp_free_i64(fp2);
8104: }
1.1.1.6 root 8105: opn = "nmsub.ps";
1.1.1.4 root 8106: break;
1.1.1.6 root 8107: default:
8108: MIPS_INVAL(opn);
8109: generate_exception (ctx, EXCP_RI);
1.1.1.4 root 8110: return;
8111: }
1.1.1.13 root 8112: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 8113: MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8114: fregnames[fs], fregnames[ft]);
1.1 root 8115: }
8116:
1.1.1.12 root 8117: static void
8118: gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
8119: {
8120: TCGv t0;
1.1 root 8121:
1.1.1.12 root 8122: check_insn(env, ctx, ISA_MIPS32R2);
8123: t0 = tcg_temp_new();
1.1 root 8124:
1.1.1.12 root 8125: switch (rd) {
8126: case 0:
8127: save_cpu_state(ctx, 1);
8128: gen_helper_rdhwr_cpunum(t0);
8129: gen_store_gpr(t0, rt);
8130: break;
8131: case 1:
8132: save_cpu_state(ctx, 1);
8133: gen_helper_rdhwr_synci_step(t0);
8134: gen_store_gpr(t0, rt);
8135: break;
8136: case 2:
8137: save_cpu_state(ctx, 1);
8138: gen_helper_rdhwr_cc(t0);
8139: gen_store_gpr(t0, rt);
8140: break;
8141: case 3:
8142: save_cpu_state(ctx, 1);
8143: gen_helper_rdhwr_ccres(t0);
8144: gen_store_gpr(t0, rt);
8145: break;
8146: case 29:
8147: #if defined(CONFIG_USER_ONLY)
8148: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
8149: gen_store_gpr(t0, rt);
8150: break;
8151: #else
8152: /* XXX: Some CPUs implement this in hardware.
8153: Not supported yet. */
1.1 root 8154: #endif
1.1.1.12 root 8155: default: /* Invalid */
8156: MIPS_INVAL("rdhwr");
8157: generate_exception(ctx, EXCP_RI);
8158: break;
1.1.1.4 root 8159: }
1.1.1.12 root 8160: tcg_temp_free(t0);
8161: }
1.1.1.4 root 8162:
1.1.1.12 root 8163: static void handle_delay_slot (CPUState *env, DisasContext *ctx,
8164: int insn_bytes)
8165: {
8166: if (ctx->hflags & MIPS_HFLAG_BMASK) {
8167: int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8168: /* Branches completion */
8169: ctx->hflags &= ~MIPS_HFLAG_BMASK;
8170: ctx->bstate = BS_BRANCH;
8171: save_cpu_state(ctx, 0);
8172: /* FIXME: Need to clear can_do_io. */
8173: switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
8174: case MIPS_HFLAG_B:
8175: /* unconditional branch */
8176: MIPS_DEBUG("unconditional branch");
8177: if (proc_hflags & MIPS_HFLAG_BX) {
8178: tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8179: }
8180: gen_goto_tb(ctx, 0, ctx->btarget);
8181: break;
8182: case MIPS_HFLAG_BL:
8183: /* blikely taken case */
8184: MIPS_DEBUG("blikely branch taken");
8185: gen_goto_tb(ctx, 0, ctx->btarget);
8186: break;
8187: case MIPS_HFLAG_BC:
8188: /* Conditional branch */
8189: MIPS_DEBUG("conditional branch");
8190: {
8191: int l1 = gen_new_label();
1.1.1.7 root 8192:
1.1.1.12 root 8193: tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8194: gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8195: gen_set_label(l1);
8196: gen_goto_tb(ctx, 0, ctx->btarget);
8197: }
8198: break;
8199: case MIPS_HFLAG_BR:
8200: /* unconditional branch to register */
8201: MIPS_DEBUG("branch to register");
8202: if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
8203: TCGv t0 = tcg_temp_new();
8204: TCGv_i32 t1 = tcg_temp_new_i32();
8205:
8206: tcg_gen_andi_tl(t0, btarget, 0x1);
8207: tcg_gen_trunc_tl_i32(t1, t0);
8208: tcg_temp_free(t0);
8209: tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8210: tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8211: tcg_gen_or_i32(hflags, hflags, t1);
8212: tcg_temp_free_i32(t1);
8213:
8214: tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8215: } else {
8216: tcg_gen_mov_tl(cpu_PC, btarget);
8217: }
8218: if (ctx->singlestep_enabled) {
8219: save_cpu_state(ctx, 0);
8220: gen_helper_0i(raise_exception, EXCP_DEBUG);
8221: }
8222: tcg_gen_exit_tb(0);
8223: break;
8224: default:
8225: MIPS_DEBUG("unknown branch");
8226: break;
8227: }
8228: }
8229: }
8230:
8231: /* ISA extensions (ASEs) */
8232: /* MIPS16 extension to MIPS32 */
8233:
8234: /* MIPS16 major opcodes */
8235: enum {
8236: M16_OPC_ADDIUSP = 0x00,
8237: M16_OPC_ADDIUPC = 0x01,
8238: M16_OPC_B = 0x02,
8239: M16_OPC_JAL = 0x03,
8240: M16_OPC_BEQZ = 0x04,
8241: M16_OPC_BNEQZ = 0x05,
8242: M16_OPC_SHIFT = 0x06,
8243: M16_OPC_LD = 0x07,
8244: M16_OPC_RRIA = 0x08,
8245: M16_OPC_ADDIU8 = 0x09,
8246: M16_OPC_SLTI = 0x0a,
8247: M16_OPC_SLTIU = 0x0b,
8248: M16_OPC_I8 = 0x0c,
8249: M16_OPC_LI = 0x0d,
8250: M16_OPC_CMPI = 0x0e,
8251: M16_OPC_SD = 0x0f,
8252: M16_OPC_LB = 0x10,
8253: M16_OPC_LH = 0x11,
8254: M16_OPC_LWSP = 0x12,
8255: M16_OPC_LW = 0x13,
8256: M16_OPC_LBU = 0x14,
8257: M16_OPC_LHU = 0x15,
8258: M16_OPC_LWPC = 0x16,
8259: M16_OPC_LWU = 0x17,
8260: M16_OPC_SB = 0x18,
8261: M16_OPC_SH = 0x19,
8262: M16_OPC_SWSP = 0x1a,
8263: M16_OPC_SW = 0x1b,
8264: M16_OPC_RRR = 0x1c,
8265: M16_OPC_RR = 0x1d,
8266: M16_OPC_EXTEND = 0x1e,
8267: M16_OPC_I64 = 0x1f
8268: };
8269:
8270: /* I8 funct field */
8271: enum {
8272: I8_BTEQZ = 0x0,
8273: I8_BTNEZ = 0x1,
8274: I8_SWRASP = 0x2,
8275: I8_ADJSP = 0x3,
8276: I8_SVRS = 0x4,
8277: I8_MOV32R = 0x5,
8278: I8_MOVR32 = 0x7
8279: };
8280:
8281: /* RRR f field */
8282: enum {
8283: RRR_DADDU = 0x0,
8284: RRR_ADDU = 0x1,
8285: RRR_DSUBU = 0x2,
8286: RRR_SUBU = 0x3
8287: };
8288:
8289: /* RR funct field */
8290: enum {
8291: RR_JR = 0x00,
8292: RR_SDBBP = 0x01,
8293: RR_SLT = 0x02,
8294: RR_SLTU = 0x03,
8295: RR_SLLV = 0x04,
8296: RR_BREAK = 0x05,
8297: RR_SRLV = 0x06,
8298: RR_SRAV = 0x07,
8299: RR_DSRL = 0x08,
8300: RR_CMP = 0x0a,
8301: RR_NEG = 0x0b,
8302: RR_AND = 0x0c,
8303: RR_OR = 0x0d,
8304: RR_XOR = 0x0e,
8305: RR_NOT = 0x0f,
8306: RR_MFHI = 0x10,
8307: RR_CNVT = 0x11,
8308: RR_MFLO = 0x12,
8309: RR_DSRA = 0x13,
8310: RR_DSLLV = 0x14,
8311: RR_DSRLV = 0x16,
8312: RR_DSRAV = 0x17,
8313: RR_MULT = 0x18,
8314: RR_MULTU = 0x19,
8315: RR_DIV = 0x1a,
8316: RR_DIVU = 0x1b,
8317: RR_DMULT = 0x1c,
8318: RR_DMULTU = 0x1d,
8319: RR_DDIV = 0x1e,
8320: RR_DDIVU = 0x1f
8321: };
8322:
8323: /* I64 funct field */
8324: enum {
8325: I64_LDSP = 0x0,
8326: I64_SDSP = 0x1,
8327: I64_SDRASP = 0x2,
8328: I64_DADJSP = 0x3,
8329: I64_LDPC = 0x4,
8330: I64_DADDIU5 = 0x5,
8331: I64_DADDIUPC = 0x6,
8332: I64_DADDIUSP = 0x7
8333: };
8334:
8335: /* RR ry field for CNVT */
8336: enum {
8337: RR_RY_CNVT_ZEB = 0x0,
8338: RR_RY_CNVT_ZEH = 0x1,
8339: RR_RY_CNVT_ZEW = 0x2,
8340: RR_RY_CNVT_SEB = 0x4,
8341: RR_RY_CNVT_SEH = 0x5,
8342: RR_RY_CNVT_SEW = 0x6,
8343: };
8344:
8345: static int xlat (int r)
8346: {
8347: static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8348:
8349: return map[r];
8350: }
8351:
8352: static void gen_mips16_save (DisasContext *ctx,
8353: int xsregs, int aregs,
8354: int do_ra, int do_s0, int do_s1,
8355: int framesize)
8356: {
8357: TCGv t0 = tcg_temp_new();
8358: TCGv t1 = tcg_temp_new();
8359: int args, astatic;
8360:
8361: switch (aregs) {
8362: case 0:
8363: case 1:
8364: case 2:
8365: case 3:
8366: case 11:
8367: args = 0;
8368: break;
8369: case 4:
8370: case 5:
8371: case 6:
8372: case 7:
8373: args = 1;
8374: break;
8375: case 8:
8376: case 9:
8377: case 10:
8378: args = 2;
8379: break;
8380: case 12:
8381: case 13:
8382: args = 3;
8383: break;
8384: case 14:
8385: args = 4;
8386: break;
8387: default:
8388: generate_exception(ctx, EXCP_RI);
8389: return;
8390: }
8391:
8392: switch (args) {
8393: case 4:
8394: gen_base_offset_addr(ctx, t0, 29, 12);
8395: gen_load_gpr(t1, 7);
8396: op_st_sw(t1, t0, ctx);
8397: /* Fall through */
8398: case 3:
8399: gen_base_offset_addr(ctx, t0, 29, 8);
8400: gen_load_gpr(t1, 6);
8401: op_st_sw(t1, t0, ctx);
8402: /* Fall through */
8403: case 2:
8404: gen_base_offset_addr(ctx, t0, 29, 4);
8405: gen_load_gpr(t1, 5);
8406: op_st_sw(t1, t0, ctx);
8407: /* Fall through */
8408: case 1:
8409: gen_base_offset_addr(ctx, t0, 29, 0);
8410: gen_load_gpr(t1, 4);
8411: op_st_sw(t1, t0, ctx);
8412: }
8413:
8414: gen_load_gpr(t0, 29);
8415:
8416: #define DECR_AND_STORE(reg) do { \
8417: tcg_gen_subi_tl(t0, t0, 4); \
8418: gen_load_gpr(t1, reg); \
8419: op_st_sw(t1, t0, ctx); \
8420: } while (0)
8421:
8422: if (do_ra) {
8423: DECR_AND_STORE(31);
8424: }
8425:
8426: switch (xsregs) {
8427: case 7:
8428: DECR_AND_STORE(30);
8429: /* Fall through */
8430: case 6:
8431: DECR_AND_STORE(23);
8432: /* Fall through */
8433: case 5:
8434: DECR_AND_STORE(22);
8435: /* Fall through */
8436: case 4:
8437: DECR_AND_STORE(21);
8438: /* Fall through */
8439: case 3:
8440: DECR_AND_STORE(20);
8441: /* Fall through */
8442: case 2:
8443: DECR_AND_STORE(19);
8444: /* Fall through */
8445: case 1:
8446: DECR_AND_STORE(18);
8447: }
8448:
8449: if (do_s1) {
8450: DECR_AND_STORE(17);
8451: }
8452: if (do_s0) {
8453: DECR_AND_STORE(16);
8454: }
8455:
8456: switch (aregs) {
8457: case 0:
8458: case 4:
8459: case 8:
8460: case 12:
8461: case 14:
8462: astatic = 0;
8463: break;
8464: case 1:
8465: case 5:
8466: case 9:
8467: case 13:
8468: astatic = 1;
8469: break;
8470: case 2:
8471: case 6:
8472: case 10:
8473: astatic = 2;
8474: break;
8475: case 3:
8476: case 7:
8477: astatic = 3;
8478: break;
8479: case 11:
8480: astatic = 4;
8481: break;
8482: default:
8483: generate_exception(ctx, EXCP_RI);
8484: return;
8485: }
8486:
8487: if (astatic > 0) {
8488: DECR_AND_STORE(7);
8489: if (astatic > 1) {
8490: DECR_AND_STORE(6);
8491: if (astatic > 2) {
8492: DECR_AND_STORE(5);
8493: if (astatic > 3) {
8494: DECR_AND_STORE(4);
8495: }
8496: }
8497: }
8498: }
8499: #undef DECR_AND_STORE
8500:
8501: tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8502: tcg_temp_free(t0);
8503: tcg_temp_free(t1);
8504: }
8505:
8506: static void gen_mips16_restore (DisasContext *ctx,
8507: int xsregs, int aregs,
8508: int do_ra, int do_s0, int do_s1,
8509: int framesize)
8510: {
8511: int astatic;
8512: TCGv t0 = tcg_temp_new();
8513: TCGv t1 = tcg_temp_new();
8514:
8515: tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8516:
8517: #define DECR_AND_LOAD(reg) do { \
8518: tcg_gen_subi_tl(t0, t0, 4); \
8519: op_ld_lw(t1, t0, ctx); \
8520: gen_store_gpr(t1, reg); \
8521: } while (0)
8522:
8523: if (do_ra) {
8524: DECR_AND_LOAD(31);
8525: }
8526:
8527: switch (xsregs) {
8528: case 7:
8529: DECR_AND_LOAD(30);
8530: /* Fall through */
8531: case 6:
8532: DECR_AND_LOAD(23);
8533: /* Fall through */
8534: case 5:
8535: DECR_AND_LOAD(22);
8536: /* Fall through */
8537: case 4:
8538: DECR_AND_LOAD(21);
8539: /* Fall through */
8540: case 3:
8541: DECR_AND_LOAD(20);
8542: /* Fall through */
8543: case 2:
8544: DECR_AND_LOAD(19);
8545: /* Fall through */
8546: case 1:
8547: DECR_AND_LOAD(18);
8548: }
8549:
8550: if (do_s1) {
8551: DECR_AND_LOAD(17);
8552: }
8553: if (do_s0) {
8554: DECR_AND_LOAD(16);
8555: }
8556:
8557: switch (aregs) {
8558: case 0:
8559: case 4:
8560: case 8:
8561: case 12:
8562: case 14:
8563: astatic = 0;
8564: break;
8565: case 1:
8566: case 5:
8567: case 9:
8568: case 13:
8569: astatic = 1;
8570: break;
8571: case 2:
8572: case 6:
8573: case 10:
8574: astatic = 2;
8575: break;
8576: case 3:
8577: case 7:
8578: astatic = 3;
8579: break;
8580: case 11:
8581: astatic = 4;
8582: break;
8583: default:
8584: generate_exception(ctx, EXCP_RI);
8585: return;
8586: }
8587:
8588: if (astatic > 0) {
8589: DECR_AND_LOAD(7);
8590: if (astatic > 1) {
8591: DECR_AND_LOAD(6);
8592: if (astatic > 2) {
8593: DECR_AND_LOAD(5);
8594: if (astatic > 3) {
8595: DECR_AND_LOAD(4);
8596: }
8597: }
8598: }
8599: }
8600: #undef DECR_AND_LOAD
8601:
8602: tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8603: tcg_temp_free(t0);
8604: tcg_temp_free(t1);
8605: }
8606:
8607: static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8608: int is_64_bit, int extended)
8609: {
8610: TCGv t0;
8611:
8612: if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8613: generate_exception(ctx, EXCP_RI);
8614: return;
8615: }
8616:
8617: t0 = tcg_temp_new();
8618:
8619: tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8620: tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8621: if (!is_64_bit) {
8622: tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8623: }
8624:
8625: tcg_temp_free(t0);
8626: }
8627:
8628: #if defined(TARGET_MIPS64)
8629: static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
8630: int ry, int funct, int16_t offset,
8631: int extended)
8632: {
8633: switch (funct) {
8634: case I64_LDSP:
8635: check_mips_64(ctx);
8636: offset = extended ? offset : offset << 3;
8637: gen_ld(env, ctx, OPC_LD, ry, 29, offset);
8638: break;
8639: case I64_SDSP:
8640: check_mips_64(ctx);
8641: offset = extended ? offset : offset << 3;
8642: gen_st(ctx, OPC_SD, ry, 29, offset);
8643: break;
8644: case I64_SDRASP:
8645: check_mips_64(ctx);
8646: offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8647: gen_st(ctx, OPC_SD, 31, 29, offset);
8648: break;
8649: case I64_DADJSP:
8650: check_mips_64(ctx);
8651: offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8652: gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8653: break;
8654: case I64_LDPC:
8655: if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8656: generate_exception(ctx, EXCP_RI);
8657: } else {
8658: offset = extended ? offset : offset << 3;
8659: gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
8660: }
8661: break;
8662: case I64_DADDIU5:
8663: check_mips_64(ctx);
8664: offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8665: gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8666: break;
8667: case I64_DADDIUPC:
8668: check_mips_64(ctx);
8669: offset = extended ? offset : offset << 2;
8670: gen_addiupc(ctx, ry, offset, 1, extended);
8671: break;
8672: case I64_DADDIUSP:
8673: check_mips_64(ctx);
8674: offset = extended ? offset : offset << 2;
8675: gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8676: break;
8677: }
8678: }
8679: #endif
8680:
8681: static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8682: int *is_branch)
8683: {
8684: int extend = lduw_code(ctx->pc + 2);
8685: int op, rx, ry, funct, sa;
8686: int16_t imm, offset;
8687:
8688: ctx->opcode = (ctx->opcode << 16) | extend;
8689: op = (ctx->opcode >> 11) & 0x1f;
8690: sa = (ctx->opcode >> 22) & 0x1f;
8691: funct = (ctx->opcode >> 8) & 0x7;
8692: rx = xlat((ctx->opcode >> 8) & 0x7);
8693: ry = xlat((ctx->opcode >> 5) & 0x7);
8694: offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8695: | ((ctx->opcode >> 21) & 0x3f) << 5
8696: | (ctx->opcode & 0x1f));
8697:
8698: /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8699: counterparts. */
8700: switch (op) {
8701: case M16_OPC_ADDIUSP:
8702: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8703: break;
8704: case M16_OPC_ADDIUPC:
8705: gen_addiupc(ctx, rx, imm, 0, 1);
8706: break;
8707: case M16_OPC_B:
8708: gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8709: /* No delay slot, so just process as a normal instruction */
8710: break;
8711: case M16_OPC_BEQZ:
8712: gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8713: /* No delay slot, so just process as a normal instruction */
8714: break;
8715: case M16_OPC_BNEQZ:
8716: gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8717: /* No delay slot, so just process as a normal instruction */
8718: break;
8719: case M16_OPC_SHIFT:
8720: switch (ctx->opcode & 0x3) {
8721: case 0x0:
8722: gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8723: break;
8724: case 0x1:
8725: #if defined(TARGET_MIPS64)
8726: check_mips_64(ctx);
8727: gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8728: #else
8729: generate_exception(ctx, EXCP_RI);
8730: #endif
8731: break;
8732: case 0x2:
8733: gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8734: break;
8735: case 0x3:
8736: gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8737: break;
8738: }
8739: break;
8740: #if defined(TARGET_MIPS64)
8741: case M16_OPC_LD:
8742: check_mips_64(ctx);
8743: gen_ld(env, ctx, OPC_LD, ry, rx, offset);
8744: break;
8745: #endif
8746: case M16_OPC_RRIA:
8747: imm = ctx->opcode & 0xf;
8748: imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8749: imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8750: imm = (int16_t) (imm << 1) >> 1;
8751: if ((ctx->opcode >> 4) & 0x1) {
8752: #if defined(TARGET_MIPS64)
8753: check_mips_64(ctx);
8754: gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8755: #else
8756: generate_exception(ctx, EXCP_RI);
8757: #endif
8758: } else {
8759: gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8760: }
8761: break;
8762: case M16_OPC_ADDIU8:
8763: gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8764: break;
8765: case M16_OPC_SLTI:
8766: gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8767: break;
8768: case M16_OPC_SLTIU:
8769: gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8770: break;
8771: case M16_OPC_I8:
8772: switch (funct) {
8773: case I8_BTEQZ:
8774: gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8775: break;
8776: case I8_BTNEZ:
8777: gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8778: break;
8779: case I8_SWRASP:
8780: gen_st(ctx, OPC_SW, 31, 29, imm);
8781: break;
8782: case I8_ADJSP:
8783: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8784: break;
8785: case I8_SVRS:
8786: {
8787: int xsregs = (ctx->opcode >> 24) & 0x7;
8788: int aregs = (ctx->opcode >> 16) & 0xf;
8789: int do_ra = (ctx->opcode >> 6) & 0x1;
8790: int do_s0 = (ctx->opcode >> 5) & 0x1;
8791: int do_s1 = (ctx->opcode >> 4) & 0x1;
8792: int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8793: | (ctx->opcode & 0xf)) << 3;
8794:
8795: if (ctx->opcode & (1 << 7)) {
8796: gen_mips16_save(ctx, xsregs, aregs,
8797: do_ra, do_s0, do_s1,
8798: framesize);
8799: } else {
8800: gen_mips16_restore(ctx, xsregs, aregs,
8801: do_ra, do_s0, do_s1,
8802: framesize);
8803: }
8804: }
8805: break;
8806: default:
8807: generate_exception(ctx, EXCP_RI);
8808: break;
8809: }
8810: break;
8811: case M16_OPC_LI:
8812: tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8813: break;
8814: case M16_OPC_CMPI:
8815: tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8816: break;
8817: #if defined(TARGET_MIPS64)
8818: case M16_OPC_SD:
8819: gen_st(ctx, OPC_SD, ry, rx, offset);
8820: break;
8821: #endif
8822: case M16_OPC_LB:
8823: gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8824: break;
8825: case M16_OPC_LH:
8826: gen_ld(env, ctx, OPC_LH, ry, rx, offset);
8827: break;
8828: case M16_OPC_LWSP:
8829: gen_ld(env, ctx, OPC_LW, rx, 29, offset);
8830: break;
8831: case M16_OPC_LW:
8832: gen_ld(env, ctx, OPC_LW, ry, rx, offset);
8833: break;
8834: case M16_OPC_LBU:
8835: gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
8836: break;
8837: case M16_OPC_LHU:
8838: gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
8839: break;
8840: case M16_OPC_LWPC:
8841: gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
8842: break;
8843: #if defined(TARGET_MIPS64)
8844: case M16_OPC_LWU:
8845: gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
8846: break;
8847: #endif
8848: case M16_OPC_SB:
8849: gen_st(ctx, OPC_SB, ry, rx, offset);
8850: break;
8851: case M16_OPC_SH:
8852: gen_st(ctx, OPC_SH, ry, rx, offset);
8853: break;
8854: case M16_OPC_SWSP:
8855: gen_st(ctx, OPC_SW, rx, 29, offset);
8856: break;
8857: case M16_OPC_SW:
8858: gen_st(ctx, OPC_SW, ry, rx, offset);
8859: break;
8860: #if defined(TARGET_MIPS64)
8861: case M16_OPC_I64:
8862: decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8863: break;
8864: #endif
8865: default:
8866: generate_exception(ctx, EXCP_RI);
8867: break;
8868: }
8869:
8870: return 4;
8871: }
8872:
8873: static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8874: int *is_branch)
8875: {
8876: int rx, ry;
8877: int sa;
8878: int op, cnvt_op, op1, offset;
8879: int funct;
8880: int n_bytes;
8881:
8882: op = (ctx->opcode >> 11) & 0x1f;
8883: sa = (ctx->opcode >> 2) & 0x7;
8884: sa = sa == 0 ? 8 : sa;
8885: rx = xlat((ctx->opcode >> 8) & 0x7);
8886: cnvt_op = (ctx->opcode >> 5) & 0x7;
8887: ry = xlat((ctx->opcode >> 5) & 0x7);
8888: op1 = offset = ctx->opcode & 0x1f;
8889:
8890: n_bytes = 2;
8891:
8892: switch (op) {
8893: case M16_OPC_ADDIUSP:
8894: {
8895: int16_t imm = ((uint8_t) ctx->opcode) << 2;
8896:
8897: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8898: }
8899: break;
8900: case M16_OPC_ADDIUPC:
8901: gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8902: break;
8903: case M16_OPC_B:
8904: offset = (ctx->opcode & 0x7ff) << 1;
8905: offset = (int16_t)(offset << 4) >> 4;
8906: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8907: /* No delay slot, so just process as a normal instruction */
8908: break;
8909: case M16_OPC_JAL:
8910: offset = lduw_code(ctx->pc + 2);
8911: offset = (((ctx->opcode & 0x1f) << 21)
8912: | ((ctx->opcode >> 5) & 0x1f) << 16
8913: | offset) << 2;
8914: op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
8915: gen_compute_branch(ctx, op, 4, rx, ry, offset);
8916: n_bytes = 4;
8917: *is_branch = 1;
8918: break;
8919: case M16_OPC_BEQZ:
8920: gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8921: /* No delay slot, so just process as a normal instruction */
8922: break;
8923: case M16_OPC_BNEQZ:
8924: gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8925: /* No delay slot, so just process as a normal instruction */
8926: break;
8927: case M16_OPC_SHIFT:
8928: switch (ctx->opcode & 0x3) {
8929: case 0x0:
8930: gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8931: break;
8932: case 0x1:
8933: #if defined(TARGET_MIPS64)
8934: check_mips_64(ctx);
8935: gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8936: #else
8937: generate_exception(ctx, EXCP_RI);
8938: #endif
8939: break;
8940: case 0x2:
8941: gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8942: break;
8943: case 0x3:
8944: gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8945: break;
8946: }
8947: break;
8948: #if defined(TARGET_MIPS64)
8949: case M16_OPC_LD:
8950: check_mips_64(ctx);
8951: gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
8952: break;
8953: #endif
8954: case M16_OPC_RRIA:
8955: {
8956: int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8957:
8958: if ((ctx->opcode >> 4) & 1) {
8959: #if defined(TARGET_MIPS64)
8960: check_mips_64(ctx);
8961: gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8962: #else
8963: generate_exception(ctx, EXCP_RI);
8964: #endif
8965: } else {
8966: gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8967: }
8968: }
8969: break;
8970: case M16_OPC_ADDIU8:
8971: {
8972: int16_t imm = (int8_t) ctx->opcode;
8973:
8974: gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8975: }
8976: break;
8977: case M16_OPC_SLTI:
8978: {
8979: int16_t imm = (uint8_t) ctx->opcode;
8980:
8981: gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8982: }
8983: break;
8984: case M16_OPC_SLTIU:
8985: {
8986: int16_t imm = (uint8_t) ctx->opcode;
8987:
8988: gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8989: }
8990: break;
8991: case M16_OPC_I8:
8992: {
8993: int reg32;
8994:
8995: funct = (ctx->opcode >> 8) & 0x7;
8996: switch (funct) {
8997: case I8_BTEQZ:
8998: gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8999: ((int8_t)ctx->opcode) << 1);
9000: break;
9001: case I8_BTNEZ:
9002: gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
9003: ((int8_t)ctx->opcode) << 1);
9004: break;
9005: case I8_SWRASP:
9006: gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
9007: break;
9008: case I8_ADJSP:
9009: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
9010: ((int8_t)ctx->opcode) << 3);
9011: break;
9012: case I8_SVRS:
9013: {
9014: int do_ra = ctx->opcode & (1 << 6);
9015: int do_s0 = ctx->opcode & (1 << 5);
9016: int do_s1 = ctx->opcode & (1 << 4);
9017: int framesize = ctx->opcode & 0xf;
9018:
9019: if (framesize == 0) {
9020: framesize = 128;
9021: } else {
9022: framesize = framesize << 3;
9023: }
9024:
9025: if (ctx->opcode & (1 << 7)) {
9026: gen_mips16_save(ctx, 0, 0,
9027: do_ra, do_s0, do_s1, framesize);
9028: } else {
9029: gen_mips16_restore(ctx, 0, 0,
9030: do_ra, do_s0, do_s1, framesize);
9031: }
9032: }
9033: break;
9034: case I8_MOV32R:
9035: {
9036: int rz = xlat(ctx->opcode & 0x7);
9037:
9038: reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9039: ((ctx->opcode >> 5) & 0x7);
9040: gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
9041: }
9042: break;
9043: case I8_MOVR32:
9044: reg32 = ctx->opcode & 0x1f;
9045: gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
9046: break;
9047: default:
9048: generate_exception(ctx, EXCP_RI);
9049: break;
9050: }
9051: }
9052: break;
9053: case M16_OPC_LI:
9054: {
9055: int16_t imm = (uint8_t) ctx->opcode;
9056:
9057: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
9058: }
9059: break;
9060: case M16_OPC_CMPI:
9061: {
9062: int16_t imm = (uint8_t) ctx->opcode;
9063:
9064: gen_logic_imm(env, OPC_XORI, 24, rx, imm);
9065: }
9066: break;
9067: #if defined(TARGET_MIPS64)
9068: case M16_OPC_SD:
9069: check_mips_64(ctx);
9070: gen_st(ctx, OPC_SD, ry, rx, offset << 3);
9071: break;
9072: #endif
9073: case M16_OPC_LB:
9074: gen_ld(env, ctx, OPC_LB, ry, rx, offset);
9075: break;
9076: case M16_OPC_LH:
9077: gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
9078: break;
9079: case M16_OPC_LWSP:
9080: gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9081: break;
9082: case M16_OPC_LW:
9083: gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
9084: break;
9085: case M16_OPC_LBU:
9086: gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
9087: break;
9088: case M16_OPC_LHU:
9089: gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
9090: break;
9091: case M16_OPC_LWPC:
9092: gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
9093: break;
9094: #if defined (TARGET_MIPS64)
9095: case M16_OPC_LWU:
9096: check_mips_64(ctx);
9097: gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
9098: break;
9099: #endif
9100: case M16_OPC_SB:
9101: gen_st(ctx, OPC_SB, ry, rx, offset);
9102: break;
9103: case M16_OPC_SH:
9104: gen_st(ctx, OPC_SH, ry, rx, offset << 1);
9105: break;
9106: case M16_OPC_SWSP:
9107: gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9108: break;
9109: case M16_OPC_SW:
9110: gen_st(ctx, OPC_SW, ry, rx, offset << 2);
9111: break;
9112: case M16_OPC_RRR:
9113: {
9114: int rz = xlat((ctx->opcode >> 2) & 0x7);
9115: int mips32_op;
9116:
9117: switch (ctx->opcode & 0x3) {
9118: case RRR_ADDU:
9119: mips32_op = OPC_ADDU;
9120: break;
9121: case RRR_SUBU:
9122: mips32_op = OPC_SUBU;
9123: break;
9124: #if defined(TARGET_MIPS64)
9125: case RRR_DADDU:
9126: mips32_op = OPC_DADDU;
9127: check_mips_64(ctx);
9128: break;
9129: case RRR_DSUBU:
9130: mips32_op = OPC_DSUBU;
9131: check_mips_64(ctx);
9132: break;
9133: #endif
9134: default:
9135: generate_exception(ctx, EXCP_RI);
9136: goto done;
9137: }
9138:
9139: gen_arith(env, ctx, mips32_op, rz, rx, ry);
9140: done:
9141: ;
9142: }
9143: break;
9144: case M16_OPC_RR:
9145: switch (op1) {
9146: case RR_JR:
9147: {
9148: int nd = (ctx->opcode >> 7) & 0x1;
9149: int link = (ctx->opcode >> 6) & 0x1;
9150: int ra = (ctx->opcode >> 5) & 0x1;
9151:
9152: if (link) {
9153: op = nd ? OPC_JALRC : OPC_JALRS;
9154: } else {
9155: op = OPC_JR;
9156: }
9157:
9158: gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9159: if (!nd) {
9160: *is_branch = 1;
9161: }
9162: }
9163: break;
9164: case RR_SDBBP:
9165: /* XXX: not clear which exception should be raised
9166: * when in debug mode...
9167: */
9168: check_insn(env, ctx, ISA_MIPS32);
9169: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9170: generate_exception(ctx, EXCP_DBp);
9171: } else {
9172: generate_exception(ctx, EXCP_DBp);
9173: }
9174: break;
9175: case RR_SLT:
9176: gen_slt(env, OPC_SLT, 24, rx, ry);
9177: break;
9178: case RR_SLTU:
9179: gen_slt(env, OPC_SLTU, 24, rx, ry);
9180: break;
9181: case RR_BREAK:
9182: generate_exception(ctx, EXCP_BREAK);
9183: break;
9184: case RR_SLLV:
9185: gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9186: break;
9187: case RR_SRLV:
9188: gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9189: break;
9190: case RR_SRAV:
9191: gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9192: break;
9193: #if defined (TARGET_MIPS64)
9194: case RR_DSRL:
9195: check_mips_64(ctx);
9196: gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9197: break;
9198: #endif
9199: case RR_CMP:
9200: gen_logic(env, OPC_XOR, 24, rx, ry);
9201: break;
9202: case RR_NEG:
9203: gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9204: break;
9205: case RR_AND:
9206: gen_logic(env, OPC_AND, rx, rx, ry);
9207: break;
9208: case RR_OR:
9209: gen_logic(env, OPC_OR, rx, rx, ry);
9210: break;
9211: case RR_XOR:
9212: gen_logic(env, OPC_XOR, rx, rx, ry);
9213: break;
9214: case RR_NOT:
9215: gen_logic(env, OPC_NOR, rx, ry, 0);
9216: break;
9217: case RR_MFHI:
9218: gen_HILO(ctx, OPC_MFHI, rx);
9219: break;
9220: case RR_CNVT:
9221: switch (cnvt_op) {
9222: case RR_RY_CNVT_ZEB:
9223: tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9224: break;
9225: case RR_RY_CNVT_ZEH:
9226: tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9227: break;
9228: case RR_RY_CNVT_SEB:
9229: tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9230: break;
9231: case RR_RY_CNVT_SEH:
9232: tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9233: break;
9234: #if defined (TARGET_MIPS64)
9235: case RR_RY_CNVT_ZEW:
9236: check_mips_64(ctx);
9237: tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9238: break;
9239: case RR_RY_CNVT_SEW:
9240: check_mips_64(ctx);
9241: tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9242: break;
9243: #endif
9244: default:
9245: generate_exception(ctx, EXCP_RI);
9246: break;
9247: }
9248: break;
9249: case RR_MFLO:
9250: gen_HILO(ctx, OPC_MFLO, rx);
9251: break;
9252: #if defined (TARGET_MIPS64)
9253: case RR_DSRA:
9254: check_mips_64(ctx);
9255: gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9256: break;
9257: case RR_DSLLV:
9258: check_mips_64(ctx);
9259: gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9260: break;
9261: case RR_DSRLV:
9262: check_mips_64(ctx);
9263: gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9264: break;
9265: case RR_DSRAV:
9266: check_mips_64(ctx);
9267: gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9268: break;
9269: #endif
9270: case RR_MULT:
9271: gen_muldiv(ctx, OPC_MULT, rx, ry);
9272: break;
9273: case RR_MULTU:
9274: gen_muldiv(ctx, OPC_MULTU, rx, ry);
9275: break;
9276: case RR_DIV:
9277: gen_muldiv(ctx, OPC_DIV, rx, ry);
9278: break;
9279: case RR_DIVU:
9280: gen_muldiv(ctx, OPC_DIVU, rx, ry);
9281: break;
9282: #if defined (TARGET_MIPS64)
9283: case RR_DMULT:
9284: check_mips_64(ctx);
9285: gen_muldiv(ctx, OPC_DMULT, rx, ry);
9286: break;
9287: case RR_DMULTU:
9288: check_mips_64(ctx);
9289: gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9290: break;
9291: case RR_DDIV:
9292: check_mips_64(ctx);
9293: gen_muldiv(ctx, OPC_DDIV, rx, ry);
9294: break;
9295: case RR_DDIVU:
9296: check_mips_64(ctx);
9297: gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9298: break;
9299: #endif
9300: default:
9301: generate_exception(ctx, EXCP_RI);
9302: break;
9303: }
9304: break;
9305: case M16_OPC_EXTEND:
9306: decode_extended_mips16_opc(env, ctx, is_branch);
9307: n_bytes = 4;
9308: break;
9309: #if defined(TARGET_MIPS64)
9310: case M16_OPC_I64:
9311: funct = (ctx->opcode >> 8) & 0x7;
9312: decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9313: break;
9314: #endif
9315: default:
9316: generate_exception(ctx, EXCP_RI);
9317: break;
9318: }
9319:
9320: return n_bytes;
9321: }
9322:
9323: /* microMIPS extension to MIPS32 */
9324:
9325: /* microMIPS32 major opcodes */
9326:
9327: enum {
9328: POOL32A = 0x00,
9329: POOL16A = 0x01,
9330: LBU16 = 0x02,
9331: MOVE16 = 0x03,
9332: ADDI32 = 0x04,
9333: LBU32 = 0x05,
9334: SB32 = 0x06,
9335: LB32 = 0x07,
9336:
9337: POOL32B = 0x08,
9338: POOL16B = 0x09,
9339: LHU16 = 0x0a,
9340: ANDI16 = 0x0b,
9341: ADDIU32 = 0x0c,
9342: LHU32 = 0x0d,
9343: SH32 = 0x0e,
9344: LH32 = 0x0f,
9345:
9346: POOL32I = 0x10,
9347: POOL16C = 0x11,
9348: LWSP16 = 0x12,
9349: POOL16D = 0x13,
9350: ORI32 = 0x14,
9351: POOL32F = 0x15,
9352: POOL32S = 0x16,
9353: DADDIU32 = 0x17,
9354:
9355: POOL32C = 0x18,
9356: LWGP16 = 0x19,
9357: LW16 = 0x1a,
9358: POOL16E = 0x1b,
9359: XORI32 = 0x1c,
9360: JALS32 = 0x1d,
9361: ADDIUPC = 0x1e,
9362: POOL48A = 0x1f,
9363:
9364: /* 0x20 is reserved */
9365: RES_20 = 0x20,
9366: POOL16F = 0x21,
9367: SB16 = 0x22,
9368: BEQZ16 = 0x23,
9369: SLTI32 = 0x24,
9370: BEQ32 = 0x25,
9371: SWC132 = 0x26,
9372: LWC132 = 0x27,
9373:
9374: /* 0x28 and 0x29 are reserved */
9375: RES_28 = 0x28,
9376: RES_29 = 0x29,
9377: SH16 = 0x2a,
9378: BNEZ16 = 0x2b,
9379: SLTIU32 = 0x2c,
9380: BNE32 = 0x2d,
9381: SDC132 = 0x2e,
9382: LDC132 = 0x2f,
9383:
9384: /* 0x30 and 0x31 are reserved */
9385: RES_30 = 0x30,
9386: RES_31 = 0x31,
9387: SWSP16 = 0x32,
9388: B16 = 0x33,
9389: ANDI32 = 0x34,
9390: J32 = 0x35,
9391: SD32 = 0x36,
9392: LD32 = 0x37,
9393:
9394: /* 0x38 and 0x39 are reserved */
9395: RES_38 = 0x38,
9396: RES_39 = 0x39,
9397: SW16 = 0x3a,
9398: LI16 = 0x3b,
9399: JALX32 = 0x3c,
9400: JAL32 = 0x3d,
9401: SW32 = 0x3e,
9402: LW32 = 0x3f
9403: };
9404:
9405: /* POOL32A encoding of minor opcode field */
9406:
9407: enum {
9408: /* These opcodes are distinguished only by bits 9..6; those bits are
9409: * what are recorded below. */
9410: SLL32 = 0x0,
9411: SRL32 = 0x1,
9412: SRA = 0x2,
9413: ROTR = 0x3,
9414:
9415: SLLV = 0x0,
9416: SRLV = 0x1,
9417: SRAV = 0x2,
9418: ROTRV = 0x3,
9419: ADD = 0x4,
9420: ADDU32 = 0x5,
9421: SUB = 0x6,
9422: SUBU32 = 0x7,
9423: MUL = 0x8,
9424: AND = 0x9,
9425: OR32 = 0xa,
9426: NOR = 0xb,
9427: XOR32 = 0xc,
9428: SLT = 0xd,
9429: SLTU = 0xe,
9430:
9431: MOVN = 0x0,
9432: MOVZ = 0x1,
9433: LWXS = 0x4,
9434:
9435: /* The following can be distinguished by their lower 6 bits. */
9436: INS = 0x0c,
9437: EXT = 0x2c,
9438: POOL32AXF = 0x3c
9439: };
9440:
9441: /* POOL32AXF encoding of minor opcode field extension */
9442:
9443: enum {
9444: /* bits 11..6 */
9445: TEQ = 0x00,
9446: TGE = 0x08,
9447: TGEU = 0x10,
9448: TLT = 0x20,
9449: TLTU = 0x28,
9450: TNE = 0x30,
9451:
9452: MFC0 = 0x03,
9453: MTC0 = 0x0b,
9454:
9455: /* bits 13..12 for 0x01 */
9456: MFHI_ACC = 0x0,
9457: MFLO_ACC = 0x1,
9458: MTHI_ACC = 0x2,
9459: MTLO_ACC = 0x3,
9460:
9461: /* bits 13..12 for 0x2a */
9462: MADD_ACC = 0x0,
9463: MADDU_ACC = 0x1,
9464: MSUB_ACC = 0x2,
9465: MSUBU_ACC = 0x3,
9466:
9467: /* bits 13..12 for 0x32 */
9468: MULT_ACC = 0x0,
9469: MULTU_ACC = 0x0,
9470:
9471: /* bits 15..12 for 0x2c */
9472: SEB = 0x2,
9473: SEH = 0x3,
9474: CLO = 0x4,
9475: CLZ = 0x5,
9476: RDHWR = 0x6,
9477: WSBH = 0x7,
9478: MULT = 0x8,
9479: MULTU = 0x9,
9480: DIV = 0xa,
9481: DIVU = 0xb,
9482: MADD = 0xc,
9483: MADDU = 0xd,
9484: MSUB = 0xe,
9485: MSUBU = 0xf,
9486:
9487: /* bits 15..12 for 0x34 */
9488: MFC2 = 0x4,
9489: MTC2 = 0x5,
9490: MFHC2 = 0x8,
9491: MTHC2 = 0x9,
9492: CFC2 = 0xc,
9493: CTC2 = 0xd,
9494:
9495: /* bits 15..12 for 0x3c */
9496: JALR = 0x0,
9497: JR = 0x0, /* alias */
9498: JALR_HB = 0x1,
9499: JALRS = 0x4,
9500: JALRS_HB = 0x5,
9501:
9502: /* bits 15..12 for 0x05 */
9503: RDPGPR = 0xe,
9504: WRPGPR = 0xf,
9505:
9506: /* bits 15..12 for 0x0d */
9507: TLBP = 0x0,
9508: TLBR = 0x1,
9509: TLBWI = 0x2,
9510: TLBWR = 0x3,
9511: WAIT = 0x9,
9512: IRET = 0xd,
9513: DERET = 0xe,
9514: ERET = 0xf,
9515:
9516: /* bits 15..12 for 0x15 */
9517: DMT = 0x0,
9518: DVPE = 0x1,
9519: EMT = 0x2,
9520: EVPE = 0x3,
9521:
9522: /* bits 15..12 for 0x1d */
9523: DI = 0x4,
9524: EI = 0x5,
9525:
9526: /* bits 15..12 for 0x2d */
9527: SYNC = 0x6,
9528: SYSCALL = 0x8,
9529: SDBBP = 0xd,
9530:
9531: /* bits 15..12 for 0x35 */
9532: MFHI32 = 0x0,
9533: MFLO32 = 0x1,
9534: MTHI32 = 0x2,
9535: MTLO32 = 0x3,
9536: };
9537:
9538: /* POOL32B encoding of minor opcode field (bits 15..12) */
9539:
9540: enum {
9541: LWC2 = 0x0,
9542: LWP = 0x1,
9543: LDP = 0x4,
9544: LWM32 = 0x5,
9545: CACHE = 0x6,
9546: LDM = 0x7,
9547: SWC2 = 0x8,
9548: SWP = 0x9,
9549: SDP = 0xc,
9550: SWM32 = 0xd,
9551: SDM = 0xf
9552: };
9553:
9554: /* POOL32C encoding of minor opcode field (bits 15..12) */
9555:
9556: enum {
9557: LWL = 0x0,
9558: SWL = 0x8,
9559: LWR = 0x1,
9560: SWR = 0x9,
9561: PREF = 0x2,
9562: /* 0xa is reserved */
9563: LL = 0x3,
9564: SC = 0xb,
9565: LDL = 0x4,
9566: SDL = 0xc,
9567: LDR = 0x5,
9568: SDR = 0xd,
9569: /* 0x6 is reserved */
9570: LWU = 0xe,
9571: LLD = 0x7,
9572: SCD = 0xf
9573: };
9574:
9575: /* POOL32F encoding of minor opcode field (bits 5..0) */
9576:
9577: enum {
9578: /* These are the bit 7..6 values */
9579: ADD_FMT = 0x0,
9580: MOVN_FMT = 0x0,
9581:
9582: SUB_FMT = 0x1,
9583: MOVZ_FMT = 0x1,
9584:
9585: MUL_FMT = 0x2,
9586:
9587: DIV_FMT = 0x3,
9588:
9589: /* These are the bit 8..6 values */
9590: RSQRT2_FMT = 0x0,
9591: MOVF_FMT = 0x0,
9592:
9593: LWXC1 = 0x1,
9594: MOVT_FMT = 0x1,
9595:
9596: PLL_PS = 0x2,
9597: SWXC1 = 0x2,
9598:
9599: PLU_PS = 0x3,
9600: LDXC1 = 0x3,
9601:
9602: PUL_PS = 0x4,
9603: SDXC1 = 0x4,
9604: RECIP2_FMT = 0x4,
9605:
9606: PUU_PS = 0x5,
9607: LUXC1 = 0x5,
9608:
9609: CVT_PS_S = 0x6,
9610: SUXC1 = 0x6,
9611: ADDR_PS = 0x6,
9612: PREFX = 0x6,
9613:
9614: MULR_PS = 0x7,
9615:
9616: MADD_S = 0x01,
9617: MADD_D = 0x09,
9618: MADD_PS = 0x11,
9619: ALNV_PS = 0x19,
9620: MSUB_S = 0x21,
9621: MSUB_D = 0x29,
9622: MSUB_PS = 0x31,
9623:
9624: NMADD_S = 0x02,
9625: NMADD_D = 0x0a,
9626: NMADD_PS = 0x12,
9627: NMSUB_S = 0x22,
9628: NMSUB_D = 0x2a,
9629: NMSUB_PS = 0x32,
9630:
9631: POOL32FXF = 0x3b,
9632:
9633: CABS_COND_FMT = 0x1c, /* MIPS3D */
9634: C_COND_FMT = 0x3c
9635: };
9636:
9637: /* POOL32Fxf encoding of minor opcode extension field */
9638:
9639: enum {
9640: CVT_L = 0x04,
9641: RSQRT_FMT = 0x08,
9642: FLOOR_L = 0x0c,
9643: CVT_PW_PS = 0x1c,
9644: CVT_W = 0x24,
9645: SQRT_FMT = 0x28,
9646: FLOOR_W = 0x2c,
9647: CVT_PS_PW = 0x3c,
9648: CFC1 = 0x40,
9649: RECIP_FMT = 0x48,
9650: CEIL_L = 0x4c,
9651: CTC1 = 0x60,
9652: CEIL_W = 0x6c,
9653: MFC1 = 0x80,
9654: CVT_S_PL = 0x84,
9655: TRUNC_L = 0x8c,
9656: MTC1 = 0xa0,
9657: CVT_S_PU = 0xa4,
9658: TRUNC_W = 0xac,
9659: MFHC1 = 0xc0,
9660: ROUND_L = 0xcc,
9661: MTHC1 = 0xe0,
9662: ROUND_W = 0xec,
9663:
9664: MOV_FMT = 0x01,
9665: MOVF = 0x05,
9666: ABS_FMT = 0x0d,
9667: RSQRT1_FMT = 0x1d,
9668: MOVT = 0x25,
9669: NEG_FMT = 0x2d,
9670: CVT_D = 0x4d,
9671: RECIP1_FMT = 0x5d,
9672: CVT_S = 0x6d
9673: };
9674:
9675: /* POOL32I encoding of minor opcode field (bits 25..21) */
9676:
9677: enum {
9678: BLTZ = 0x00,
9679: BLTZAL = 0x01,
9680: BGEZ = 0x02,
9681: BGEZAL = 0x03,
9682: BLEZ = 0x04,
9683: BNEZC = 0x05,
9684: BGTZ = 0x06,
9685: BEQZC = 0x07,
9686: TLTI = 0x08,
9687: TGEI = 0x09,
9688: TLTIU = 0x0a,
9689: TGEIU = 0x0b,
9690: TNEI = 0x0c,
9691: LUI = 0x0d,
9692: TEQI = 0x0e,
9693: SYNCI = 0x10,
9694: BLTZALS = 0x11,
9695: BGEZALS = 0x13,
9696: BC2F = 0x14,
9697: BC2T = 0x15,
9698: BPOSGE64 = 0x1a,
9699: BPOSGE32 = 0x1b,
9700: /* These overlap and are distinguished by bit16 of the instruction */
9701: BC1F = 0x1c,
9702: BC1T = 0x1d,
9703: BC1ANY2F = 0x1c,
9704: BC1ANY2T = 0x1d,
9705: BC1ANY4F = 0x1e,
9706: BC1ANY4T = 0x1f
9707: };
9708:
9709: /* POOL16A encoding of minor opcode field */
9710:
9711: enum {
9712: ADDU16 = 0x0,
9713: SUBU16 = 0x1
9714: };
9715:
9716: /* POOL16B encoding of minor opcode field */
9717:
9718: enum {
9719: SLL16 = 0x0,
9720: SRL16 = 0x1
9721: };
9722:
9723: /* POOL16C encoding of minor opcode field */
9724:
9725: enum {
9726: NOT16 = 0x00,
9727: XOR16 = 0x04,
9728: AND16 = 0x08,
9729: OR16 = 0x0c,
9730: LWM16 = 0x10,
9731: SWM16 = 0x14,
9732: JR16 = 0x18,
9733: JRC16 = 0x1a,
9734: JALR16 = 0x1c,
9735: JALR16S = 0x1e,
9736: MFHI16 = 0x20,
9737: MFLO16 = 0x24,
9738: BREAK16 = 0x28,
9739: SDBBP16 = 0x2c,
9740: JRADDIUSP = 0x30
9741: };
9742:
9743: /* POOL16D encoding of minor opcode field */
9744:
9745: enum {
9746: ADDIUS5 = 0x0,
9747: ADDIUSP = 0x1
9748: };
9749:
9750: /* POOL16E encoding of minor opcode field */
9751:
9752: enum {
9753: ADDIUR2 = 0x0,
9754: ADDIUR1SP = 0x1
9755: };
9756:
9757: static int mmreg (int r)
9758: {
9759: static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9760:
9761: return map[r];
9762: }
9763:
9764: /* Used for 16-bit store instructions. */
9765: static int mmreg2 (int r)
9766: {
9767: static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
9768:
9769: return map[r];
9770: }
9771:
9772: #define uMIPS_RD(op) ((op >> 7) & 0x7)
9773: #define uMIPS_RS(op) ((op >> 4) & 0x7)
9774: #define uMIPS_RS2(op) uMIPS_RS(op)
9775: #define uMIPS_RS1(op) ((op >> 1) & 0x7)
9776: #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
9777: #define uMIPS_RS5(op) (op & 0x1f)
9778:
9779: /* Signed immediate */
9780: #define SIMM(op, start, width) \
9781: ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
9782: << (32-width)) \
9783: >> (32-width))
9784: /* Zero-extended immediate */
9785: #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
9786:
9787: static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
9788: {
9789: int rd = mmreg(uMIPS_RD(ctx->opcode));
9790:
9791: gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
9792: }
9793:
9794: static void gen_addiur2 (CPUState *env, DisasContext *ctx)
9795: {
9796: static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
9797: int rd = mmreg(uMIPS_RD(ctx->opcode));
9798: int rs = mmreg(uMIPS_RS(ctx->opcode));
9799:
9800: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
9801: }
9802:
9803: static void gen_addiusp (CPUState *env, DisasContext *ctx)
9804: {
9805: int encoded = ZIMM(ctx->opcode, 1, 9);
9806: int decoded;
9807:
9808: if (encoded <= 1) {
9809: decoded = 256 + encoded;
9810: } else if (encoded <= 255) {
9811: decoded = encoded;
9812: } else if (encoded <= 509) {
9813: decoded = encoded - 512;
9814: } else {
9815: decoded = encoded - 768;
9816: }
9817:
9818: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
9819: }
9820:
9821: static void gen_addius5 (CPUState *env, DisasContext *ctx)
9822: {
9823: int imm = SIMM(ctx->opcode, 1, 4);
9824: int rd = (ctx->opcode >> 5) & 0x1f;
9825:
9826: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
9827: }
9828:
9829: static void gen_andi16 (CPUState *env, DisasContext *ctx)
9830: {
9831: static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
9832: 31, 32, 63, 64, 255, 32768, 65535 };
9833: int rd = mmreg(uMIPS_RD(ctx->opcode));
9834: int rs = mmreg(uMIPS_RS(ctx->opcode));
9835: int encoded = ZIMM(ctx->opcode, 0, 4);
9836:
9837: gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
9838: }
9839:
9840: static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
9841: int base, int16_t offset)
9842: {
9843: TCGv t0, t1;
9844: TCGv_i32 t2;
9845:
9846: if (ctx->hflags & MIPS_HFLAG_BMASK) {
9847: generate_exception(ctx, EXCP_RI);
9848: return;
9849: }
9850:
9851: t0 = tcg_temp_new();
9852:
9853: gen_base_offset_addr(ctx, t0, base, offset);
9854:
9855: t1 = tcg_const_tl(reglist);
9856: t2 = tcg_const_i32(ctx->mem_idx);
9857:
9858: save_cpu_state(ctx, 1);
9859: switch (opc) {
9860: case LWM32:
9861: gen_helper_lwm(t0, t1, t2);
9862: break;
9863: case SWM32:
9864: gen_helper_swm(t0, t1, t2);
9865: break;
9866: #ifdef TARGET_MIPS64
9867: case LDM:
9868: gen_helper_ldm(t0, t1, t2);
9869: break;
9870: case SDM:
9871: gen_helper_sdm(t0, t1, t2);
9872: break;
9873: #endif
9874: }
9875: MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
9876: tcg_temp_free(t0);
9877: tcg_temp_free(t1);
9878: tcg_temp_free_i32(t2);
9879: }
9880:
9881:
9882: static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
9883: {
9884: int rd = mmreg((ctx->opcode >> 3) & 0x7);
9885: int rs = mmreg(ctx->opcode & 0x7);
9886: int opc;
9887:
9888: switch (((ctx->opcode) >> 4) & 0x3f) {
9889: case NOT16 + 0:
9890: case NOT16 + 1:
9891: case NOT16 + 2:
9892: case NOT16 + 3:
9893: gen_logic(env, OPC_NOR, rd, rs, 0);
9894: break;
9895: case XOR16 + 0:
9896: case XOR16 + 1:
9897: case XOR16 + 2:
9898: case XOR16 + 3:
9899: gen_logic(env, OPC_XOR, rd, rd, rs);
9900: break;
9901: case AND16 + 0:
9902: case AND16 + 1:
9903: case AND16 + 2:
9904: case AND16 + 3:
9905: gen_logic(env, OPC_AND, rd, rd, rs);
9906: break;
9907: case OR16 + 0:
9908: case OR16 + 1:
9909: case OR16 + 2:
9910: case OR16 + 3:
9911: gen_logic(env, OPC_OR, rd, rd, rs);
9912: break;
9913: case LWM16 + 0:
9914: case LWM16 + 1:
9915: case LWM16 + 2:
9916: case LWM16 + 3:
9917: {
9918: static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9919: int offset = ZIMM(ctx->opcode, 0, 4);
9920:
9921: gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
9922: 29, offset << 2);
9923: }
9924: break;
9925: case SWM16 + 0:
9926: case SWM16 + 1:
9927: case SWM16 + 2:
9928: case SWM16 + 3:
9929: {
9930: static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9931: int offset = ZIMM(ctx->opcode, 0, 4);
9932:
9933: gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
9934: 29, offset << 2);
9935: }
9936: break;
9937: case JR16 + 0:
9938: case JR16 + 1:
9939: {
9940: int reg = ctx->opcode & 0x1f;
9941:
9942: gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9943: }
9944: *is_branch = 1;
9945: break;
9946: case JRC16 + 0:
9947: case JRC16 + 1:
9948: {
9949: int reg = ctx->opcode & 0x1f;
9950:
9951: gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9952: /* Let normal delay slot handling in our caller take us
9953: to the branch target. */
9954: }
9955: break;
9956: case JALR16 + 0:
9957: case JALR16 + 1:
9958: opc = OPC_JALR;
9959: goto do_jalr;
9960: case JALR16S + 0:
9961: case JALR16S + 1:
9962: opc = OPC_JALRS;
9963: do_jalr:
9964: {
9965: int reg = ctx->opcode & 0x1f;
9966:
9967: gen_compute_branch(ctx, opc, 2, reg, 31, 0);
9968: }
9969: *is_branch = 1;
9970: break;
9971: case MFHI16 + 0:
9972: case MFHI16 + 1:
9973: gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
9974: break;
9975: case MFLO16 + 0:
9976: case MFLO16 + 1:
9977: gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
9978: break;
9979: case BREAK16:
9980: generate_exception(ctx, EXCP_BREAK);
9981: break;
9982: case SDBBP16:
9983: /* XXX: not clear which exception should be raised
9984: * when in debug mode...
9985: */
9986: check_insn(env, ctx, ISA_MIPS32);
9987: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9988: generate_exception(ctx, EXCP_DBp);
9989: } else {
9990: generate_exception(ctx, EXCP_DBp);
9991: }
9992: break;
9993: case JRADDIUSP + 0:
9994: case JRADDIUSP + 1:
9995: {
9996: int imm = ZIMM(ctx->opcode, 0, 5);
9997:
9998: gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
9999: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
10000: /* Let normal delay slot handling in our caller take us
10001: to the branch target. */
10002: }
10003: break;
10004: default:
10005: generate_exception(ctx, EXCP_RI);
10006: break;
10007: }
10008: }
10009:
10010: static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10011: {
10012: TCGv t0 = tcg_temp_new();
10013: TCGv t1 = tcg_temp_new();
10014:
10015: gen_load_gpr(t0, base);
10016:
10017: if (index != 0) {
10018: gen_load_gpr(t1, index);
10019: tcg_gen_shli_tl(t1, t1, 2);
10020: gen_op_addr_add(ctx, t0, t1, t0);
10021: }
10022:
10023: save_cpu_state(ctx, 0);
10024: op_ld_lw(t1, t0, ctx);
10025: gen_store_gpr(t1, rd);
10026:
10027: tcg_temp_free(t0);
10028: tcg_temp_free(t1);
10029: }
10030:
10031: static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
10032: int base, int16_t offset)
10033: {
10034: const char *opn = "ldst_pair";
10035: TCGv t0, t1;
10036:
10037: if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
10038: generate_exception(ctx, EXCP_RI);
10039: return;
10040: }
10041:
10042: t0 = tcg_temp_new();
10043: t1 = tcg_temp_new();
10044:
10045: gen_base_offset_addr(ctx, t0, base, offset);
10046:
10047: switch (opc) {
10048: case LWP:
10049: save_cpu_state(ctx, 0);
10050: op_ld_lw(t1, t0, ctx);
10051: gen_store_gpr(t1, rd);
10052: tcg_gen_movi_tl(t1, 4);
10053: gen_op_addr_add(ctx, t0, t0, t1);
10054: op_ld_lw(t1, t0, ctx);
10055: gen_store_gpr(t1, rd+1);
10056: opn = "lwp";
10057: break;
10058: case SWP:
1.1.1.13 root 10059: save_cpu_state(ctx, 0);
1.1.1.12 root 10060: gen_load_gpr(t1, rd);
10061: op_st_sw(t1, t0, ctx);
10062: tcg_gen_movi_tl(t1, 4);
10063: gen_op_addr_add(ctx, t0, t0, t1);
10064: gen_load_gpr(t1, rd+1);
10065: op_st_sw(t1, t0, ctx);
10066: opn = "swp";
10067: break;
10068: #ifdef TARGET_MIPS64
10069: case LDP:
10070: save_cpu_state(ctx, 0);
10071: op_ld_ld(t1, t0, ctx);
10072: gen_store_gpr(t1, rd);
10073: tcg_gen_movi_tl(t1, 8);
10074: gen_op_addr_add(ctx, t0, t0, t1);
10075: op_ld_ld(t1, t0, ctx);
10076: gen_store_gpr(t1, rd+1);
10077: opn = "ldp";
10078: break;
10079: case SDP:
1.1.1.13 root 10080: save_cpu_state(ctx, 0);
1.1.1.12 root 10081: gen_load_gpr(t1, rd);
10082: op_st_sd(t1, t0, ctx);
10083: tcg_gen_movi_tl(t1, 8);
10084: gen_op_addr_add(ctx, t0, t0, t1);
10085: gen_load_gpr(t1, rd+1);
10086: op_st_sd(t1, t0, ctx);
10087: opn = "sdp";
10088: break;
10089: #endif
10090: }
1.1.1.13 root 10091: (void)opn; /* avoid a compiler warning */
1.1.1.12 root 10092: MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10093: tcg_temp_free(t0);
10094: tcg_temp_free(t1);
10095: }
10096:
10097: static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
10098: int *is_branch)
10099: {
10100: int extension = (ctx->opcode >> 6) & 0x3f;
10101: int minor = (ctx->opcode >> 12) & 0xf;
10102: uint32_t mips32_op;
10103:
10104: switch (extension) {
10105: case TEQ:
10106: mips32_op = OPC_TEQ;
10107: goto do_trap;
10108: case TGE:
10109: mips32_op = OPC_TGE;
10110: goto do_trap;
10111: case TGEU:
10112: mips32_op = OPC_TGEU;
10113: goto do_trap;
10114: case TLT:
10115: mips32_op = OPC_TLT;
10116: goto do_trap;
10117: case TLTU:
10118: mips32_op = OPC_TLTU;
10119: goto do_trap;
10120: case TNE:
10121: mips32_op = OPC_TNE;
10122: do_trap:
10123: gen_trap(ctx, mips32_op, rs, rt, -1);
10124: break;
10125: #ifndef CONFIG_USER_ONLY
10126: case MFC0:
10127: case MFC0 + 32:
10128: if (rt == 0) {
10129: /* Treat as NOP. */
10130: break;
10131: }
10132: gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10133: break;
10134: case MTC0:
10135: case MTC0 + 32:
10136: {
10137: TCGv t0 = tcg_temp_new();
10138:
10139: gen_load_gpr(t0, rt);
10140: gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10141: tcg_temp_free(t0);
10142: }
10143: break;
10144: #endif
10145: case 0x2c:
10146: switch (minor) {
10147: case SEB:
10148: gen_bshfl(ctx, OPC_SEB, rs, rt);
10149: break;
10150: case SEH:
10151: gen_bshfl(ctx, OPC_SEH, rs, rt);
10152: break;
10153: case CLO:
10154: mips32_op = OPC_CLO;
10155: goto do_cl;
10156: case CLZ:
10157: mips32_op = OPC_CLZ;
10158: do_cl:
10159: check_insn(env, ctx, ISA_MIPS32);
10160: gen_cl(ctx, mips32_op, rt, rs);
10161: break;
10162: case RDHWR:
10163: gen_rdhwr(env, ctx, rt, rs);
10164: break;
10165: case WSBH:
10166: gen_bshfl(ctx, OPC_WSBH, rs, rt);
10167: break;
10168: case MULT:
10169: mips32_op = OPC_MULT;
10170: goto do_muldiv;
10171: case MULTU:
10172: mips32_op = OPC_MULTU;
10173: goto do_muldiv;
10174: case DIV:
10175: mips32_op = OPC_DIV;
10176: goto do_muldiv;
10177: case DIVU:
10178: mips32_op = OPC_DIVU;
10179: goto do_muldiv;
10180: case MADD:
10181: mips32_op = OPC_MADD;
10182: goto do_muldiv;
10183: case MADDU:
10184: mips32_op = OPC_MADDU;
10185: goto do_muldiv;
10186: case MSUB:
10187: mips32_op = OPC_MSUB;
10188: goto do_muldiv;
10189: case MSUBU:
10190: mips32_op = OPC_MSUBU;
10191: do_muldiv:
10192: check_insn(env, ctx, ISA_MIPS32);
10193: gen_muldiv(ctx, mips32_op, rs, rt);
10194: break;
10195: default:
10196: goto pool32axf_invalid;
10197: }
10198: break;
10199: case 0x34:
10200: switch (minor) {
10201: case MFC2:
10202: case MTC2:
10203: case MFHC2:
10204: case MTHC2:
10205: case CFC2:
10206: case CTC2:
10207: generate_exception_err(ctx, EXCP_CpU, 2);
10208: break;
10209: default:
10210: goto pool32axf_invalid;
10211: }
10212: break;
10213: case 0x3c:
10214: switch (minor) {
10215: case JALR:
10216: case JALR_HB:
10217: gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10218: *is_branch = 1;
10219: break;
10220: case JALRS:
10221: case JALRS_HB:
10222: gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10223: *is_branch = 1;
10224: break;
10225: default:
10226: goto pool32axf_invalid;
10227: }
10228: break;
10229: case 0x05:
10230: switch (minor) {
10231: case RDPGPR:
10232: check_insn(env, ctx, ISA_MIPS32R2);
10233: gen_load_srsgpr(rt, rs);
10234: break;
10235: case WRPGPR:
10236: check_insn(env, ctx, ISA_MIPS32R2);
10237: gen_store_srsgpr(rt, rs);
10238: break;
10239: default:
10240: goto pool32axf_invalid;
10241: }
10242: break;
10243: #ifndef CONFIG_USER_ONLY
10244: case 0x0d:
10245: switch (minor) {
10246: case TLBP:
10247: mips32_op = OPC_TLBP;
10248: goto do_cp0;
10249: case TLBR:
10250: mips32_op = OPC_TLBR;
10251: goto do_cp0;
10252: case TLBWI:
10253: mips32_op = OPC_TLBWI;
10254: goto do_cp0;
10255: case TLBWR:
10256: mips32_op = OPC_TLBWR;
10257: goto do_cp0;
10258: case WAIT:
10259: mips32_op = OPC_WAIT;
10260: goto do_cp0;
10261: case DERET:
10262: mips32_op = OPC_DERET;
10263: goto do_cp0;
10264: case ERET:
10265: mips32_op = OPC_ERET;
10266: do_cp0:
10267: gen_cp0(env, ctx, mips32_op, rt, rs);
10268: break;
10269: default:
10270: goto pool32axf_invalid;
10271: }
10272: break;
10273: case 0x1d:
10274: switch (minor) {
10275: case DI:
10276: {
10277: TCGv t0 = tcg_temp_new();
10278:
10279: save_cpu_state(ctx, 1);
10280: gen_helper_di(t0);
10281: gen_store_gpr(t0, rs);
10282: /* Stop translation as we may have switched the execution mode */
10283: ctx->bstate = BS_STOP;
10284: tcg_temp_free(t0);
10285: }
10286: break;
10287: case EI:
10288: {
10289: TCGv t0 = tcg_temp_new();
10290:
10291: save_cpu_state(ctx, 1);
10292: gen_helper_ei(t0);
10293: gen_store_gpr(t0, rs);
10294: /* Stop translation as we may have switched the execution mode */
10295: ctx->bstate = BS_STOP;
10296: tcg_temp_free(t0);
10297: }
10298: break;
10299: default:
10300: goto pool32axf_invalid;
10301: }
10302: break;
10303: #endif
10304: case 0x2d:
10305: switch (minor) {
10306: case SYNC:
10307: /* NOP */
10308: break;
10309: case SYSCALL:
10310: generate_exception(ctx, EXCP_SYSCALL);
10311: ctx->bstate = BS_STOP;
10312: break;
10313: case SDBBP:
10314: check_insn(env, ctx, ISA_MIPS32);
10315: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10316: generate_exception(ctx, EXCP_DBp);
10317: } else {
10318: generate_exception(ctx, EXCP_DBp);
10319: }
10320: break;
10321: default:
10322: goto pool32axf_invalid;
10323: }
10324: break;
10325: case 0x35:
10326: switch (minor) {
10327: case MFHI32:
10328: gen_HILO(ctx, OPC_MFHI, rs);
10329: break;
10330: case MFLO32:
10331: gen_HILO(ctx, OPC_MFLO, rs);
10332: break;
10333: case MTHI32:
10334: gen_HILO(ctx, OPC_MTHI, rs);
10335: break;
10336: case MTLO32:
10337: gen_HILO(ctx, OPC_MTLO, rs);
10338: break;
10339: default:
10340: goto pool32axf_invalid;
10341: }
10342: break;
10343: default:
10344: pool32axf_invalid:
10345: MIPS_INVAL("pool32axf");
10346: generate_exception(ctx, EXCP_RI);
10347: break;
10348: }
10349: }
10350:
10351: /* Values for microMIPS fmt field. Variable-width, depending on which
10352: formats the instruction supports. */
10353:
10354: enum {
10355: FMT_SD_S = 0,
10356: FMT_SD_D = 1,
10357:
10358: FMT_SDPS_S = 0,
10359: FMT_SDPS_D = 1,
10360: FMT_SDPS_PS = 2,
10361:
10362: FMT_SWL_S = 0,
10363: FMT_SWL_W = 1,
10364: FMT_SWL_L = 2,
10365:
10366: FMT_DWL_D = 0,
10367: FMT_DWL_W = 1,
10368: FMT_DWL_L = 2
10369: };
10370:
10371: static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
10372: {
10373: int extension = (ctx->opcode >> 6) & 0x3ff;
10374: uint32_t mips32_op;
10375:
10376: #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10377: #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10378: #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10379:
10380: switch (extension) {
10381: case FLOAT_1BIT_FMT(CFC1, 0):
10382: mips32_op = OPC_CFC1;
10383: goto do_cp1;
10384: case FLOAT_1BIT_FMT(CTC1, 0):
10385: mips32_op = OPC_CTC1;
10386: goto do_cp1;
10387: case FLOAT_1BIT_FMT(MFC1, 0):
10388: mips32_op = OPC_MFC1;
10389: goto do_cp1;
10390: case FLOAT_1BIT_FMT(MTC1, 0):
10391: mips32_op = OPC_MTC1;
10392: goto do_cp1;
10393: case FLOAT_1BIT_FMT(MFHC1, 0):
10394: mips32_op = OPC_MFHC1;
10395: goto do_cp1;
10396: case FLOAT_1BIT_FMT(MTHC1, 0):
10397: mips32_op = OPC_MTHC1;
10398: do_cp1:
10399: gen_cp1(ctx, mips32_op, rt, rs);
10400: break;
10401:
10402: /* Reciprocal square root */
10403: case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10404: mips32_op = OPC_RSQRT_S;
10405: goto do_unaryfp;
10406: case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10407: mips32_op = OPC_RSQRT_D;
10408: goto do_unaryfp;
10409:
10410: /* Square root */
10411: case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10412: mips32_op = OPC_SQRT_S;
10413: goto do_unaryfp;
10414: case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10415: mips32_op = OPC_SQRT_D;
10416: goto do_unaryfp;
10417:
10418: /* Reciprocal */
10419: case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10420: mips32_op = OPC_RECIP_S;
10421: goto do_unaryfp;
10422: case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10423: mips32_op = OPC_RECIP_D;
10424: goto do_unaryfp;
10425:
10426: /* Floor */
10427: case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10428: mips32_op = OPC_FLOOR_L_S;
10429: goto do_unaryfp;
10430: case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10431: mips32_op = OPC_FLOOR_L_D;
10432: goto do_unaryfp;
10433: case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10434: mips32_op = OPC_FLOOR_W_S;
10435: goto do_unaryfp;
10436: case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10437: mips32_op = OPC_FLOOR_W_D;
10438: goto do_unaryfp;
10439:
10440: /* Ceiling */
10441: case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10442: mips32_op = OPC_CEIL_L_S;
10443: goto do_unaryfp;
10444: case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10445: mips32_op = OPC_CEIL_L_D;
10446: goto do_unaryfp;
10447: case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10448: mips32_op = OPC_CEIL_W_S;
10449: goto do_unaryfp;
10450: case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10451: mips32_op = OPC_CEIL_W_D;
10452: goto do_unaryfp;
10453:
10454: /* Truncation */
10455: case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10456: mips32_op = OPC_TRUNC_L_S;
10457: goto do_unaryfp;
10458: case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10459: mips32_op = OPC_TRUNC_L_D;
10460: goto do_unaryfp;
10461: case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10462: mips32_op = OPC_TRUNC_W_S;
10463: goto do_unaryfp;
10464: case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10465: mips32_op = OPC_TRUNC_W_D;
10466: goto do_unaryfp;
10467:
10468: /* Round */
10469: case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10470: mips32_op = OPC_ROUND_L_S;
10471: goto do_unaryfp;
10472: case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10473: mips32_op = OPC_ROUND_L_D;
10474: goto do_unaryfp;
10475: case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10476: mips32_op = OPC_ROUND_W_S;
10477: goto do_unaryfp;
10478: case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10479: mips32_op = OPC_ROUND_W_D;
10480: goto do_unaryfp;
10481:
10482: /* Integer to floating-point conversion */
10483: case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10484: mips32_op = OPC_CVT_L_S;
10485: goto do_unaryfp;
10486: case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10487: mips32_op = OPC_CVT_L_D;
10488: goto do_unaryfp;
10489: case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10490: mips32_op = OPC_CVT_W_S;
10491: goto do_unaryfp;
10492: case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10493: mips32_op = OPC_CVT_W_D;
10494: goto do_unaryfp;
10495:
10496: /* Paired-foo conversions */
10497: case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10498: mips32_op = OPC_CVT_S_PL;
10499: goto do_unaryfp;
10500: case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10501: mips32_op = OPC_CVT_S_PU;
10502: goto do_unaryfp;
10503: case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10504: mips32_op = OPC_CVT_PW_PS;
10505: goto do_unaryfp;
10506: case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10507: mips32_op = OPC_CVT_PS_PW;
10508: goto do_unaryfp;
10509:
10510: /* Floating-point moves */
10511: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10512: mips32_op = OPC_MOV_S;
10513: goto do_unaryfp;
10514: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10515: mips32_op = OPC_MOV_D;
10516: goto do_unaryfp;
10517: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10518: mips32_op = OPC_MOV_PS;
10519: goto do_unaryfp;
10520:
10521: /* Absolute value */
10522: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10523: mips32_op = OPC_ABS_S;
10524: goto do_unaryfp;
10525: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10526: mips32_op = OPC_ABS_D;
10527: goto do_unaryfp;
10528: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10529: mips32_op = OPC_ABS_PS;
10530: goto do_unaryfp;
10531:
10532: /* Negation */
10533: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10534: mips32_op = OPC_NEG_S;
10535: goto do_unaryfp;
10536: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10537: mips32_op = OPC_NEG_D;
10538: goto do_unaryfp;
10539: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10540: mips32_op = OPC_NEG_PS;
10541: goto do_unaryfp;
10542:
10543: /* Reciprocal square root step */
10544: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10545: mips32_op = OPC_RSQRT1_S;
10546: goto do_unaryfp;
10547: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10548: mips32_op = OPC_RSQRT1_D;
10549: goto do_unaryfp;
10550: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10551: mips32_op = OPC_RSQRT1_PS;
10552: goto do_unaryfp;
10553:
10554: /* Reciprocal step */
10555: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10556: mips32_op = OPC_RECIP1_S;
10557: goto do_unaryfp;
10558: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10559: mips32_op = OPC_RECIP1_S;
10560: goto do_unaryfp;
10561: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10562: mips32_op = OPC_RECIP1_PS;
10563: goto do_unaryfp;
10564:
10565: /* Conversions from double */
10566: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10567: mips32_op = OPC_CVT_D_S;
10568: goto do_unaryfp;
10569: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10570: mips32_op = OPC_CVT_D_W;
10571: goto do_unaryfp;
10572: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10573: mips32_op = OPC_CVT_D_L;
10574: goto do_unaryfp;
10575:
10576: /* Conversions from single */
10577: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10578: mips32_op = OPC_CVT_S_D;
10579: goto do_unaryfp;
10580: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10581: mips32_op = OPC_CVT_S_W;
10582: goto do_unaryfp;
10583: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10584: mips32_op = OPC_CVT_S_L;
10585: do_unaryfp:
10586: gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10587: break;
10588:
10589: /* Conditional moves on floating-point codes */
10590: case COND_FLOAT_MOV(MOVT, 0):
10591: case COND_FLOAT_MOV(MOVT, 1):
10592: case COND_FLOAT_MOV(MOVT, 2):
10593: case COND_FLOAT_MOV(MOVT, 3):
10594: case COND_FLOAT_MOV(MOVT, 4):
10595: case COND_FLOAT_MOV(MOVT, 5):
10596: case COND_FLOAT_MOV(MOVT, 6):
10597: case COND_FLOAT_MOV(MOVT, 7):
10598: gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
10599: break;
10600: case COND_FLOAT_MOV(MOVF, 0):
10601: case COND_FLOAT_MOV(MOVF, 1):
10602: case COND_FLOAT_MOV(MOVF, 2):
10603: case COND_FLOAT_MOV(MOVF, 3):
10604: case COND_FLOAT_MOV(MOVF, 4):
10605: case COND_FLOAT_MOV(MOVF, 5):
10606: case COND_FLOAT_MOV(MOVF, 6):
10607: case COND_FLOAT_MOV(MOVF, 7):
10608: gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
10609: break;
10610: default:
10611: MIPS_INVAL("pool32fxf");
10612: generate_exception(ctx, EXCP_RI);
10613: break;
10614: }
10615: }
10616:
10617: static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
10618: uint16_t insn_hw1, int *is_branch)
10619: {
10620: int32_t offset;
10621: uint16_t insn;
10622: int rt, rs, rd, rr;
10623: int16_t imm;
10624: uint32_t op, minor, mips32_op;
10625: uint32_t cond, fmt, cc;
10626:
10627: insn = lduw_code(ctx->pc + 2);
10628: ctx->opcode = (ctx->opcode << 16) | insn;
10629:
10630: rt = (ctx->opcode >> 21) & 0x1f;
10631: rs = (ctx->opcode >> 16) & 0x1f;
10632: rd = (ctx->opcode >> 11) & 0x1f;
10633: rr = (ctx->opcode >> 6) & 0x1f;
10634: imm = (int16_t) ctx->opcode;
10635:
10636: op = (ctx->opcode >> 26) & 0x3f;
10637: switch (op) {
10638: case POOL32A:
10639: minor = ctx->opcode & 0x3f;
10640: switch (minor) {
10641: case 0x00:
10642: minor = (ctx->opcode >> 6) & 0xf;
10643: switch (minor) {
10644: case SLL32:
10645: mips32_op = OPC_SLL;
10646: goto do_shifti;
10647: case SRA:
10648: mips32_op = OPC_SRA;
10649: goto do_shifti;
10650: case SRL32:
10651: mips32_op = OPC_SRL;
10652: goto do_shifti;
10653: case ROTR:
10654: mips32_op = OPC_ROTR;
10655: do_shifti:
10656: gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
10657: break;
10658: default:
10659: goto pool32a_invalid;
10660: }
10661: break;
10662: case 0x10:
10663: minor = (ctx->opcode >> 6) & 0xf;
10664: switch (minor) {
10665: /* Arithmetic */
10666: case ADD:
10667: mips32_op = OPC_ADD;
10668: goto do_arith;
10669: case ADDU32:
10670: mips32_op = OPC_ADDU;
10671: goto do_arith;
10672: case SUB:
10673: mips32_op = OPC_SUB;
10674: goto do_arith;
10675: case SUBU32:
10676: mips32_op = OPC_SUBU;
10677: goto do_arith;
10678: case MUL:
10679: mips32_op = OPC_MUL;
10680: do_arith:
10681: gen_arith(env, ctx, mips32_op, rd, rs, rt);
10682: break;
10683: /* Shifts */
10684: case SLLV:
10685: mips32_op = OPC_SLLV;
10686: goto do_shift;
10687: case SRLV:
10688: mips32_op = OPC_SRLV;
10689: goto do_shift;
10690: case SRAV:
10691: mips32_op = OPC_SRAV;
10692: goto do_shift;
10693: case ROTRV:
10694: mips32_op = OPC_ROTRV;
10695: do_shift:
10696: gen_shift(env, ctx, mips32_op, rd, rs, rt);
10697: break;
10698: /* Logical operations */
10699: case AND:
10700: mips32_op = OPC_AND;
10701: goto do_logic;
10702: case OR32:
10703: mips32_op = OPC_OR;
10704: goto do_logic;
10705: case NOR:
10706: mips32_op = OPC_NOR;
10707: goto do_logic;
10708: case XOR32:
10709: mips32_op = OPC_XOR;
10710: do_logic:
10711: gen_logic(env, mips32_op, rd, rs, rt);
10712: break;
10713: /* Set less than */
10714: case SLT:
10715: mips32_op = OPC_SLT;
10716: goto do_slt;
10717: case SLTU:
10718: mips32_op = OPC_SLTU;
10719: do_slt:
10720: gen_slt(env, mips32_op, rd, rs, rt);
10721: break;
10722: default:
10723: goto pool32a_invalid;
10724: }
10725: break;
10726: case 0x18:
10727: minor = (ctx->opcode >> 6) & 0xf;
10728: switch (minor) {
10729: /* Conditional moves */
10730: case MOVN:
10731: mips32_op = OPC_MOVN;
10732: goto do_cmov;
10733: case MOVZ:
10734: mips32_op = OPC_MOVZ;
10735: do_cmov:
10736: gen_cond_move(env, mips32_op, rd, rs, rt);
10737: break;
10738: case LWXS:
10739: gen_ldxs(ctx, rs, rt, rd);
10740: break;
10741: default:
10742: goto pool32a_invalid;
10743: }
10744: break;
10745: case INS:
10746: gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
10747: return;
10748: case EXT:
10749: gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
10750: return;
10751: case POOL32AXF:
10752: gen_pool32axf(env, ctx, rt, rs, is_branch);
10753: break;
10754: case 0x07:
10755: generate_exception(ctx, EXCP_BREAK);
10756: break;
10757: default:
10758: pool32a_invalid:
10759: MIPS_INVAL("pool32a");
10760: generate_exception(ctx, EXCP_RI);
10761: break;
10762: }
10763: break;
10764: case POOL32B:
10765: minor = (ctx->opcode >> 12) & 0xf;
10766: switch (minor) {
10767: case CACHE:
10768: /* Treat as no-op. */
10769: break;
10770: case LWC2:
10771: case SWC2:
10772: /* COP2: Not implemented. */
10773: generate_exception_err(ctx, EXCP_CpU, 2);
10774: break;
10775: case LWP:
10776: case SWP:
10777: #ifdef TARGET_MIPS64
10778: case LDP:
10779: case SDP:
10780: #endif
10781: gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10782: break;
10783: case LWM32:
10784: case SWM32:
10785: #ifdef TARGET_MIPS64
10786: case LDM:
10787: case SDM:
10788: #endif
10789: gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10790: break;
10791: default:
10792: MIPS_INVAL("pool32b");
10793: generate_exception(ctx, EXCP_RI);
10794: break;
10795: }
10796: break;
10797: case POOL32F:
10798: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
10799: minor = ctx->opcode & 0x3f;
10800: check_cp1_enabled(ctx);
10801: switch (minor) {
10802: case ALNV_PS:
10803: mips32_op = OPC_ALNV_PS;
10804: goto do_madd;
10805: case MADD_S:
10806: mips32_op = OPC_MADD_S;
10807: goto do_madd;
10808: case MADD_D:
10809: mips32_op = OPC_MADD_D;
10810: goto do_madd;
10811: case MADD_PS:
10812: mips32_op = OPC_MADD_PS;
10813: goto do_madd;
10814: case MSUB_S:
10815: mips32_op = OPC_MSUB_S;
10816: goto do_madd;
10817: case MSUB_D:
10818: mips32_op = OPC_MSUB_D;
10819: goto do_madd;
10820: case MSUB_PS:
10821: mips32_op = OPC_MSUB_PS;
10822: goto do_madd;
10823: case NMADD_S:
10824: mips32_op = OPC_NMADD_S;
10825: goto do_madd;
10826: case NMADD_D:
10827: mips32_op = OPC_NMADD_D;
10828: goto do_madd;
10829: case NMADD_PS:
10830: mips32_op = OPC_NMADD_PS;
10831: goto do_madd;
10832: case NMSUB_S:
10833: mips32_op = OPC_NMSUB_S;
10834: goto do_madd;
10835: case NMSUB_D:
10836: mips32_op = OPC_NMSUB_D;
10837: goto do_madd;
10838: case NMSUB_PS:
10839: mips32_op = OPC_NMSUB_PS;
10840: do_madd:
10841: gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
10842: break;
10843: case CABS_COND_FMT:
10844: cond = (ctx->opcode >> 6) & 0xf;
10845: cc = (ctx->opcode >> 13) & 0x7;
10846: fmt = (ctx->opcode >> 10) & 0x3;
10847: switch (fmt) {
10848: case 0x0:
10849: gen_cmpabs_s(ctx, cond, rt, rs, cc);
10850: break;
10851: case 0x1:
10852: gen_cmpabs_d(ctx, cond, rt, rs, cc);
10853: break;
10854: case 0x2:
10855: gen_cmpabs_ps(ctx, cond, rt, rs, cc);
10856: break;
10857: default:
10858: goto pool32f_invalid;
10859: }
10860: break;
10861: case C_COND_FMT:
10862: cond = (ctx->opcode >> 6) & 0xf;
10863: cc = (ctx->opcode >> 13) & 0x7;
10864: fmt = (ctx->opcode >> 10) & 0x3;
10865: switch (fmt) {
10866: case 0x0:
10867: gen_cmp_s(ctx, cond, rt, rs, cc);
10868: break;
10869: case 0x1:
10870: gen_cmp_d(ctx, cond, rt, rs, cc);
10871: break;
10872: case 0x2:
10873: gen_cmp_ps(ctx, cond, rt, rs, cc);
10874: break;
10875: default:
10876: goto pool32f_invalid;
10877: }
10878: break;
10879: case POOL32FXF:
10880: gen_pool32fxf(env, ctx, rt, rs);
10881: break;
10882: case 0x00:
10883: /* PLL foo */
10884: switch ((ctx->opcode >> 6) & 0x7) {
10885: case PLL_PS:
10886: mips32_op = OPC_PLL_PS;
10887: goto do_ps;
10888: case PLU_PS:
10889: mips32_op = OPC_PLU_PS;
10890: goto do_ps;
10891: case PUL_PS:
10892: mips32_op = OPC_PUL_PS;
10893: goto do_ps;
10894: case PUU_PS:
10895: mips32_op = OPC_PUU_PS;
10896: goto do_ps;
10897: case CVT_PS_S:
10898: mips32_op = OPC_CVT_PS_S;
10899: do_ps:
10900: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10901: break;
10902: default:
10903: goto pool32f_invalid;
10904: }
10905: break;
10906: case 0x08:
10907: /* [LS][WDU]XC1 */
10908: switch ((ctx->opcode >> 6) & 0x7) {
10909: case LWXC1:
10910: mips32_op = OPC_LWXC1;
10911: goto do_ldst_cp1;
10912: case SWXC1:
10913: mips32_op = OPC_SWXC1;
10914: goto do_ldst_cp1;
10915: case LDXC1:
10916: mips32_op = OPC_LDXC1;
10917: goto do_ldst_cp1;
10918: case SDXC1:
10919: mips32_op = OPC_SDXC1;
10920: goto do_ldst_cp1;
10921: case LUXC1:
10922: mips32_op = OPC_LUXC1;
10923: goto do_ldst_cp1;
10924: case SUXC1:
10925: mips32_op = OPC_SUXC1;
10926: do_ldst_cp1:
10927: gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
10928: break;
10929: default:
10930: goto pool32f_invalid;
10931: }
10932: break;
10933: case 0x18:
10934: /* 3D insns */
10935: fmt = (ctx->opcode >> 9) & 0x3;
10936: switch ((ctx->opcode >> 6) & 0x7) {
10937: case RSQRT2_FMT:
10938: switch (fmt) {
10939: case FMT_SDPS_S:
10940: mips32_op = OPC_RSQRT2_S;
10941: goto do_3d;
10942: case FMT_SDPS_D:
10943: mips32_op = OPC_RSQRT2_D;
10944: goto do_3d;
10945: case FMT_SDPS_PS:
10946: mips32_op = OPC_RSQRT2_PS;
10947: goto do_3d;
10948: default:
10949: goto pool32f_invalid;
10950: }
10951: break;
10952: case RECIP2_FMT:
10953: switch (fmt) {
10954: case FMT_SDPS_S:
10955: mips32_op = OPC_RECIP2_S;
10956: goto do_3d;
10957: case FMT_SDPS_D:
10958: mips32_op = OPC_RECIP2_D;
10959: goto do_3d;
10960: case FMT_SDPS_PS:
10961: mips32_op = OPC_RECIP2_PS;
10962: goto do_3d;
10963: default:
10964: goto pool32f_invalid;
10965: }
10966: break;
10967: case ADDR_PS:
10968: mips32_op = OPC_ADDR_PS;
10969: goto do_3d;
10970: case MULR_PS:
10971: mips32_op = OPC_MULR_PS;
10972: do_3d:
10973: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10974: break;
10975: default:
10976: goto pool32f_invalid;
10977: }
10978: break;
10979: case 0x20:
10980: /* MOV[FT].fmt and PREFX */
10981: cc = (ctx->opcode >> 13) & 0x7;
10982: fmt = (ctx->opcode >> 9) & 0x3;
10983: switch ((ctx->opcode >> 6) & 0x7) {
10984: case MOVF_FMT:
10985: switch (fmt) {
10986: case FMT_SDPS_S:
10987: gen_movcf_s(rs, rt, cc, 0);
10988: break;
10989: case FMT_SDPS_D:
10990: gen_movcf_d(ctx, rs, rt, cc, 0);
10991: break;
10992: case FMT_SDPS_PS:
10993: gen_movcf_ps(rs, rt, cc, 0);
10994: break;
10995: default:
10996: goto pool32f_invalid;
10997: }
10998: break;
10999: case MOVT_FMT:
11000: switch (fmt) {
11001: case FMT_SDPS_S:
11002: gen_movcf_s(rs, rt, cc, 1);
11003: break;
11004: case FMT_SDPS_D:
11005: gen_movcf_d(ctx, rs, rt, cc, 1);
11006: break;
11007: case FMT_SDPS_PS:
11008: gen_movcf_ps(rs, rt, cc, 1);
11009: break;
11010: default:
11011: goto pool32f_invalid;
11012: }
11013: break;
11014: case PREFX:
11015: break;
11016: default:
11017: goto pool32f_invalid;
11018: }
11019: break;
11020: #define FINSN_3ARG_SDPS(prfx) \
11021: switch ((ctx->opcode >> 8) & 0x3) { \
11022: case FMT_SDPS_S: \
11023: mips32_op = OPC_##prfx##_S; \
11024: goto do_fpop; \
11025: case FMT_SDPS_D: \
11026: mips32_op = OPC_##prfx##_D; \
11027: goto do_fpop; \
11028: case FMT_SDPS_PS: \
11029: mips32_op = OPC_##prfx##_PS; \
11030: goto do_fpop; \
11031: default: \
11032: goto pool32f_invalid; \
11033: }
11034: case 0x30:
11035: /* regular FP ops */
11036: switch ((ctx->opcode >> 6) & 0x3) {
11037: case ADD_FMT:
11038: FINSN_3ARG_SDPS(ADD);
11039: break;
11040: case SUB_FMT:
11041: FINSN_3ARG_SDPS(SUB);
11042: break;
11043: case MUL_FMT:
11044: FINSN_3ARG_SDPS(MUL);
11045: break;
11046: case DIV_FMT:
11047: fmt = (ctx->opcode >> 8) & 0x3;
11048: if (fmt == 1) {
11049: mips32_op = OPC_DIV_D;
11050: } else if (fmt == 0) {
11051: mips32_op = OPC_DIV_S;
11052: } else {
11053: goto pool32f_invalid;
11054: }
11055: goto do_fpop;
11056: default:
11057: goto pool32f_invalid;
11058: }
11059: break;
11060: case 0x38:
11061: /* cmovs */
11062: switch ((ctx->opcode >> 6) & 0x3) {
11063: case MOVN_FMT:
11064: FINSN_3ARG_SDPS(MOVN);
11065: break;
11066: case MOVZ_FMT:
11067: FINSN_3ARG_SDPS(MOVZ);
11068: break;
11069: default:
11070: goto pool32f_invalid;
11071: }
11072: break;
11073: do_fpop:
11074: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11075: break;
11076: default:
11077: pool32f_invalid:
11078: MIPS_INVAL("pool32f");
11079: generate_exception(ctx, EXCP_RI);
11080: break;
11081: }
11082: } else {
11083: generate_exception_err(ctx, EXCP_CpU, 1);
11084: }
11085: break;
11086: case POOL32I:
11087: minor = (ctx->opcode >> 21) & 0x1f;
11088: switch (minor) {
11089: case BLTZ:
11090: mips32_op = OPC_BLTZ;
11091: goto do_branch;
11092: case BLTZAL:
11093: mips32_op = OPC_BLTZAL;
11094: goto do_branch;
11095: case BLTZALS:
11096: mips32_op = OPC_BLTZALS;
11097: goto do_branch;
11098: case BGEZ:
11099: mips32_op = OPC_BGEZ;
11100: goto do_branch;
11101: case BGEZAL:
11102: mips32_op = OPC_BGEZAL;
11103: goto do_branch;
11104: case BGEZALS:
11105: mips32_op = OPC_BGEZALS;
11106: goto do_branch;
11107: case BLEZ:
11108: mips32_op = OPC_BLEZ;
11109: goto do_branch;
11110: case BGTZ:
11111: mips32_op = OPC_BGTZ;
11112: do_branch:
11113: gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11114: *is_branch = 1;
11115: break;
11116:
11117: /* Traps */
11118: case TLTI:
11119: mips32_op = OPC_TLTI;
11120: goto do_trapi;
11121: case TGEI:
11122: mips32_op = OPC_TGEI;
11123: goto do_trapi;
11124: case TLTIU:
11125: mips32_op = OPC_TLTIU;
11126: goto do_trapi;
11127: case TGEIU:
11128: mips32_op = OPC_TGEIU;
11129: goto do_trapi;
11130: case TNEI:
11131: mips32_op = OPC_TNEI;
11132: goto do_trapi;
11133: case TEQI:
11134: mips32_op = OPC_TEQI;
11135: do_trapi:
11136: gen_trap(ctx, mips32_op, rs, -1, imm);
11137: break;
11138:
11139: case BNEZC:
11140: case BEQZC:
11141: gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11142: 4, rs, 0, imm << 1);
11143: /* Compact branches don't have a delay slot, so just let
11144: the normal delay slot handling take us to the branch
11145: target. */
11146: break;
11147: case LUI:
11148: gen_logic_imm(env, OPC_LUI, rs, -1, imm);
11149: break;
11150: case SYNCI:
11151: break;
11152: case BC2F:
11153: case BC2T:
11154: /* COP2: Not implemented. */
11155: generate_exception_err(ctx, EXCP_CpU, 2);
11156: break;
11157: case BC1F:
11158: mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11159: goto do_cp1branch;
11160: case BC1T:
11161: mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11162: goto do_cp1branch;
11163: case BC1ANY4F:
11164: mips32_op = OPC_BC1FANY4;
11165: goto do_cp1mips3d;
11166: case BC1ANY4T:
11167: mips32_op = OPC_BC1TANY4;
11168: do_cp1mips3d:
11169: check_cop1x(ctx);
11170: check_insn(env, ctx, ASE_MIPS3D);
11171: /* Fall through */
11172: do_cp1branch:
11173: gen_compute_branch1(env, ctx, mips32_op,
11174: (ctx->opcode >> 18) & 0x7, imm << 1);
11175: *is_branch = 1;
11176: break;
11177: case BPOSGE64:
11178: case BPOSGE32:
11179: /* MIPS DSP: not implemented */
11180: /* Fall through */
11181: default:
11182: MIPS_INVAL("pool32i");
11183: generate_exception(ctx, EXCP_RI);
11184: break;
11185: }
11186: break;
11187: case POOL32C:
11188: minor = (ctx->opcode >> 12) & 0xf;
11189: switch (minor) {
11190: case LWL:
11191: mips32_op = OPC_LWL;
11192: goto do_ld_lr;
11193: case SWL:
11194: mips32_op = OPC_SWL;
11195: goto do_st_lr;
11196: case LWR:
11197: mips32_op = OPC_LWR;
11198: goto do_ld_lr;
11199: case SWR:
11200: mips32_op = OPC_SWR;
11201: goto do_st_lr;
11202: #if defined(TARGET_MIPS64)
11203: case LDL:
11204: mips32_op = OPC_LDL;
11205: goto do_ld_lr;
11206: case SDL:
11207: mips32_op = OPC_SDL;
11208: goto do_st_lr;
11209: case LDR:
11210: mips32_op = OPC_LDR;
11211: goto do_ld_lr;
11212: case SDR:
11213: mips32_op = OPC_SDR;
11214: goto do_st_lr;
11215: case LWU:
11216: mips32_op = OPC_LWU;
11217: goto do_ld_lr;
11218: case LLD:
11219: mips32_op = OPC_LLD;
11220: goto do_ld_lr;
11221: #endif
11222: case LL:
11223: mips32_op = OPC_LL;
11224: goto do_ld_lr;
11225: do_ld_lr:
11226: gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11227: break;
11228: do_st_lr:
11229: gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11230: break;
11231: case SC:
11232: gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11233: break;
11234: #if defined(TARGET_MIPS64)
11235: case SCD:
11236: gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11237: break;
11238: #endif
11239: case PREF:
11240: /* Treat as no-op */
11241: break;
11242: default:
11243: MIPS_INVAL("pool32c");
11244: generate_exception(ctx, EXCP_RI);
11245: break;
11246: }
11247: break;
11248: case ADDI32:
11249: mips32_op = OPC_ADDI;
11250: goto do_addi;
11251: case ADDIU32:
11252: mips32_op = OPC_ADDIU;
11253: do_addi:
11254: gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11255: break;
11256:
11257: /* Logical operations */
11258: case ORI32:
11259: mips32_op = OPC_ORI;
11260: goto do_logici;
11261: case XORI32:
11262: mips32_op = OPC_XORI;
11263: goto do_logici;
11264: case ANDI32:
11265: mips32_op = OPC_ANDI;
11266: do_logici:
11267: gen_logic_imm(env, mips32_op, rt, rs, imm);
11268: break;
11269:
11270: /* Set less than immediate */
11271: case SLTI32:
11272: mips32_op = OPC_SLTI;
11273: goto do_slti;
11274: case SLTIU32:
11275: mips32_op = OPC_SLTIU;
11276: do_slti:
11277: gen_slt_imm(env, mips32_op, rt, rs, imm);
11278: break;
11279: case JALX32:
11280: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11281: gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11282: *is_branch = 1;
11283: break;
11284: case JALS32:
11285: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11286: gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11287: *is_branch = 1;
11288: break;
11289: case BEQ32:
11290: gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11291: *is_branch = 1;
11292: break;
11293: case BNE32:
11294: gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11295: *is_branch = 1;
11296: break;
11297: case J32:
11298: gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11299: (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11300: *is_branch = 1;
11301: break;
11302: case JAL32:
11303: gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11304: (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11305: *is_branch = 1;
11306: break;
11307: /* Floating point (COP1) */
11308: case LWC132:
11309: mips32_op = OPC_LWC1;
11310: goto do_cop1;
11311: case LDC132:
11312: mips32_op = OPC_LDC1;
11313: goto do_cop1;
11314: case SWC132:
11315: mips32_op = OPC_SWC1;
11316: goto do_cop1;
11317: case SDC132:
11318: mips32_op = OPC_SDC1;
11319: do_cop1:
11320: gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11321: break;
11322: case ADDIUPC:
11323: {
11324: int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11325: int offset = SIMM(ctx->opcode, 0, 23) << 2;
11326:
11327: gen_addiupc(ctx, reg, offset, 0, 0);
11328: }
11329: break;
11330: /* Loads and stores */
11331: case LB32:
11332: mips32_op = OPC_LB;
11333: goto do_ld;
11334: case LBU32:
11335: mips32_op = OPC_LBU;
11336: goto do_ld;
11337: case LH32:
11338: mips32_op = OPC_LH;
11339: goto do_ld;
11340: case LHU32:
11341: mips32_op = OPC_LHU;
11342: goto do_ld;
11343: case LW32:
11344: mips32_op = OPC_LW;
11345: goto do_ld;
11346: #ifdef TARGET_MIPS64
11347: case LD32:
11348: mips32_op = OPC_LD;
11349: goto do_ld;
11350: case SD32:
11351: mips32_op = OPC_SD;
11352: goto do_st;
11353: #endif
11354: case SB32:
11355: mips32_op = OPC_SB;
11356: goto do_st;
11357: case SH32:
11358: mips32_op = OPC_SH;
11359: goto do_st;
11360: case SW32:
11361: mips32_op = OPC_SW;
11362: goto do_st;
11363: do_ld:
11364: gen_ld(env, ctx, mips32_op, rt, rs, imm);
11365: break;
11366: do_st:
11367: gen_st(ctx, mips32_op, rt, rs, imm);
11368: break;
11369: default:
11370: generate_exception(ctx, EXCP_RI);
11371: break;
11372: }
11373: }
11374:
11375: static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11376: {
11377: uint32_t op;
11378:
11379: /* make sure instructions are on a halfword boundary */
11380: if (ctx->pc & 0x1) {
11381: env->CP0_BadVAddr = ctx->pc;
11382: generate_exception(ctx, EXCP_AdEL);
11383: ctx->bstate = BS_STOP;
11384: return 2;
11385: }
11386:
11387: op = (ctx->opcode >> 10) & 0x3f;
11388: /* Enforce properly-sized instructions in a delay slot */
11389: if (ctx->hflags & MIPS_HFLAG_BMASK) {
11390: int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11391:
11392: switch (op) {
11393: case POOL32A:
11394: case POOL32B:
11395: case POOL32I:
11396: case POOL32C:
11397: case ADDI32:
11398: case ADDIU32:
11399: case ORI32:
11400: case XORI32:
11401: case SLTI32:
11402: case SLTIU32:
11403: case ANDI32:
11404: case JALX32:
11405: case LBU32:
11406: case LHU32:
11407: case POOL32F:
11408: case JALS32:
11409: case BEQ32:
11410: case BNE32:
11411: case J32:
11412: case JAL32:
11413: case SB32:
11414: case SH32:
11415: case POOL32S:
11416: case ADDIUPC:
11417: case SWC132:
11418: case SDC132:
11419: case SD32:
11420: case SW32:
11421: case LB32:
11422: case LH32:
11423: case DADDIU32:
11424: case POOL48A: /* ??? */
11425: case LWC132:
11426: case LDC132:
11427: case LD32:
11428: case LW32:
11429: if (bits & MIPS_HFLAG_BDS16) {
11430: generate_exception(ctx, EXCP_RI);
11431: /* Just stop translation; the user is confused. */
11432: ctx->bstate = BS_STOP;
11433: return 2;
11434: }
11435: break;
11436: case POOL16A:
11437: case POOL16B:
11438: case POOL16C:
11439: case LWGP16:
11440: case POOL16F:
11441: case LBU16:
11442: case LHU16:
11443: case LWSP16:
11444: case LW16:
11445: case SB16:
11446: case SH16:
11447: case SWSP16:
11448: case SW16:
11449: case MOVE16:
11450: case ANDI16:
11451: case POOL16D:
11452: case POOL16E:
11453: case BEQZ16:
11454: case BNEZ16:
11455: case B16:
11456: case LI16:
11457: if (bits & MIPS_HFLAG_BDS32) {
11458: generate_exception(ctx, EXCP_RI);
11459: /* Just stop translation; the user is confused. */
11460: ctx->bstate = BS_STOP;
11461: return 2;
11462: }
11463: break;
11464: default:
11465: break;
11466: }
11467: }
11468: switch (op) {
11469: case POOL16A:
11470: {
11471: int rd = mmreg(uMIPS_RD(ctx->opcode));
11472: int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11473: int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11474: uint32_t opc = 0;
11475:
11476: switch (ctx->opcode & 0x1) {
11477: case ADDU16:
11478: opc = OPC_ADDU;
11479: break;
11480: case SUBU16:
11481: opc = OPC_SUBU;
11482: break;
11483: }
11484:
11485: gen_arith(env, ctx, opc, rd, rs1, rs2);
11486: }
11487: break;
11488: case POOL16B:
11489: {
11490: int rd = mmreg(uMIPS_RD(ctx->opcode));
11491: int rs = mmreg(uMIPS_RS(ctx->opcode));
11492: int amount = (ctx->opcode >> 1) & 0x7;
11493: uint32_t opc = 0;
11494: amount = amount == 0 ? 8 : amount;
11495:
11496: switch (ctx->opcode & 0x1) {
11497: case SLL16:
11498: opc = OPC_SLL;
11499: break;
11500: case SRL16:
11501: opc = OPC_SRL;
11502: break;
11503: }
11504:
11505: gen_shift_imm(env, ctx, opc, rd, rs, amount);
11506: }
11507: break;
11508: case POOL16C:
11509: gen_pool16c_insn(env, ctx, is_branch);
11510: break;
11511: case LWGP16:
11512: {
11513: int rd = mmreg(uMIPS_RD(ctx->opcode));
11514: int rb = 28; /* GP */
11515: int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11516:
11517: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11518: }
11519: break;
11520: case POOL16F:
11521: if (ctx->opcode & 1) {
11522: generate_exception(ctx, EXCP_RI);
11523: } else {
11524: /* MOVEP */
11525: int enc_dest = uMIPS_RD(ctx->opcode);
11526: int enc_rt = uMIPS_RS2(ctx->opcode);
11527: int enc_rs = uMIPS_RS1(ctx->opcode);
11528: int rd, rs, re, rt;
11529: static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11530: static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11531: static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11532:
11533: rd = rd_enc[enc_dest];
11534: re = re_enc[enc_dest];
11535: rs = rs_rt_enc[enc_rs];
11536: rt = rs_rt_enc[enc_rt];
11537:
11538: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11539: gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11540: }
11541: break;
11542: case LBU16:
11543: {
11544: int rd = mmreg(uMIPS_RD(ctx->opcode));
11545: int rb = mmreg(uMIPS_RS(ctx->opcode));
11546: int16_t offset = ZIMM(ctx->opcode, 0, 4);
11547: offset = (offset == 0xf ? -1 : offset);
11548:
11549: gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
11550: }
11551: break;
11552: case LHU16:
11553: {
11554: int rd = mmreg(uMIPS_RD(ctx->opcode));
11555: int rb = mmreg(uMIPS_RS(ctx->opcode));
11556: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11557:
11558: gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
11559: }
11560: break;
11561: case LWSP16:
11562: {
11563: int rd = (ctx->opcode >> 5) & 0x1f;
11564: int rb = 29; /* SP */
11565: int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11566:
11567: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11568: }
11569: break;
11570: case LW16:
11571: {
11572: int rd = mmreg(uMIPS_RD(ctx->opcode));
11573: int rb = mmreg(uMIPS_RS(ctx->opcode));
11574: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11575:
11576: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11577: }
11578: break;
11579: case SB16:
11580: {
11581: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11582: int rb = mmreg(uMIPS_RS(ctx->opcode));
11583: int16_t offset = ZIMM(ctx->opcode, 0, 4);
11584:
11585: gen_st(ctx, OPC_SB, rd, rb, offset);
11586: }
11587: break;
11588: case SH16:
11589: {
11590: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11591: int rb = mmreg(uMIPS_RS(ctx->opcode));
11592: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11593:
11594: gen_st(ctx, OPC_SH, rd, rb, offset);
11595: }
11596: break;
11597: case SWSP16:
11598: {
11599: int rd = (ctx->opcode >> 5) & 0x1f;
11600: int rb = 29; /* SP */
11601: int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11602:
11603: gen_st(ctx, OPC_SW, rd, rb, offset);
11604: }
11605: break;
11606: case SW16:
11607: {
11608: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11609: int rb = mmreg(uMIPS_RS(ctx->opcode));
11610: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11611:
11612: gen_st(ctx, OPC_SW, rd, rb, offset);
11613: }
11614: break;
11615: case MOVE16:
11616: {
11617: int rd = uMIPS_RD5(ctx->opcode);
11618: int rs = uMIPS_RS5(ctx->opcode);
11619:
11620: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11621: }
11622: break;
11623: case ANDI16:
11624: gen_andi16(env, ctx);
11625: break;
11626: case POOL16D:
11627: switch (ctx->opcode & 0x1) {
11628: case ADDIUS5:
11629: gen_addius5(env, ctx);
11630: break;
11631: case ADDIUSP:
11632: gen_addiusp(env, ctx);
11633: break;
11634: }
11635: break;
11636: case POOL16E:
11637: switch (ctx->opcode & 0x1) {
11638: case ADDIUR2:
11639: gen_addiur2(env, ctx);
11640: break;
11641: case ADDIUR1SP:
11642: gen_addiur1sp(env, ctx);
11643: break;
11644: }
11645: break;
11646: case B16:
11647: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
11648: SIMM(ctx->opcode, 0, 10) << 1);
11649: *is_branch = 1;
11650: break;
11651: case BNEZ16:
11652: case BEQZ16:
11653: gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
11654: mmreg(uMIPS_RD(ctx->opcode)),
11655: 0, SIMM(ctx->opcode, 0, 7) << 1);
11656: *is_branch = 1;
11657: break;
11658: case LI16:
11659: {
11660: int reg = mmreg(uMIPS_RD(ctx->opcode));
11661: int imm = ZIMM(ctx->opcode, 0, 7);
11662:
11663: imm = (imm == 0x7f ? -1 : imm);
11664: tcg_gen_movi_tl(cpu_gpr[reg], imm);
11665: }
11666: break;
11667: case RES_20:
11668: case RES_28:
11669: case RES_29:
11670: case RES_30:
11671: case RES_31:
11672: case RES_38:
11673: case RES_39:
11674: generate_exception(ctx, EXCP_RI);
11675: break;
11676: default:
11677: decode_micromips32_opc (env, ctx, op, is_branch);
11678: return 4;
11679: }
11680:
11681: return 2;
11682: }
11683:
11684: /* SmartMIPS extension to MIPS32 */
11685:
11686: #if defined(TARGET_MIPS64)
11687:
11688: /* MDMX extension to MIPS64 */
11689:
11690: #endif
11691:
11692: static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11693: {
11694: int32_t offset;
11695: int rs, rt, rd, sa;
11696: uint32_t op, op1, op2;
11697: int16_t imm;
11698:
11699: /* make sure instructions are on a word boundary */
11700: if (ctx->pc & 0x3) {
11701: env->CP0_BadVAddr = ctx->pc;
11702: generate_exception(ctx, EXCP_AdEL);
11703: return;
11704: }
11705:
11706: /* Handle blikely not taken case */
11707: if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
11708: int l1 = gen_new_label();
11709:
11710: MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
1.1.1.8 root 11711: tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11712: tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
1.1.1.6 root 11713: gen_goto_tb(ctx, 1, ctx->pc + 4);
11714: gen_set_label(l1);
1.1 root 11715: }
1.1.1.9 root 11716:
11717: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11718: tcg_gen_debug_insn_start(ctx->pc);
11719:
1.1.1.5 root 11720: op = MASK_OP_MAJOR(ctx->opcode);
11721: rs = (ctx->opcode >> 21) & 0x1f;
11722: rt = (ctx->opcode >> 16) & 0x1f;
11723: rd = (ctx->opcode >> 11) & 0x1f;
11724: sa = (ctx->opcode >> 6) & 0x1f;
1.1 root 11725: imm = (int16_t)ctx->opcode;
11726: switch (op) {
1.1.1.5 root 11727: case OPC_SPECIAL:
11728: op1 = MASK_SPECIAL(ctx->opcode);
1.1 root 11729: switch (op1) {
1.1.1.8 root 11730: case OPC_SLL: /* Shift with immediate */
11731: case OPC_SRA:
11732: gen_shift_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 11733: break;
1.1.1.12 root 11734: case OPC_SRL:
11735: switch ((ctx->opcode >> 21) & 0x1f) {
11736: case 1:
11737: /* rotr is decoded as srl on non-R2 CPUs */
11738: if (env->insn_flags & ISA_MIPS32R2) {
11739: op1 = OPC_ROTR;
11740: }
11741: /* Fallthrough */
11742: case 0:
11743: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11744: break;
11745: default:
11746: generate_exception(ctx, EXCP_RI);
11747: break;
11748: }
11749: break;
1.1.1.8 root 11750: case OPC_MOVN: /* Conditional move */
11751: case OPC_MOVZ:
1.1.1.12 root 11752: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
11753: INSN_LOONGSON2E | INSN_LOONGSON2F);
1.1.1.8 root 11754: gen_cond_move(env, op1, rd, rs, rt);
11755: break;
11756: case OPC_ADD ... OPC_SUBU:
1.1.1.6 root 11757: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 11758: break;
1.1.1.8 root 11759: case OPC_SLLV: /* Shifts */
11760: case OPC_SRAV:
11761: gen_shift(env, ctx, op1, rd, rs, rt);
11762: break;
1.1.1.12 root 11763: case OPC_SRLV:
11764: switch ((ctx->opcode >> 6) & 0x1f) {
11765: case 1:
11766: /* rotrv is decoded as srlv on non-R2 CPUs */
11767: if (env->insn_flags & ISA_MIPS32R2) {
11768: op1 = OPC_ROTRV;
11769: }
11770: /* Fallthrough */
11771: case 0:
11772: gen_shift(env, ctx, op1, rd, rs, rt);
11773: break;
11774: default:
11775: generate_exception(ctx, EXCP_RI);
11776: break;
11777: }
11778: break;
1.1.1.8 root 11779: case OPC_SLT: /* Set on less than */
11780: case OPC_SLTU:
11781: gen_slt(env, op1, rd, rs, rt);
11782: break;
11783: case OPC_AND: /* Logic*/
11784: case OPC_OR:
11785: case OPC_NOR:
11786: case OPC_XOR:
11787: gen_logic(env, op1, rd, rs, rt);
11788: break;
1.1.1.5 root 11789: case OPC_MULT ... OPC_DIVU:
1.1.1.6 root 11790: if (sa) {
11791: check_insn(env, ctx, INSN_VR54XX);
11792: op1 = MASK_MUL_VR54XX(ctx->opcode);
11793: gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11794: } else
11795: gen_muldiv(ctx, op1, rs, rt);
1.1 root 11796: break;
1.1.1.5 root 11797: case OPC_JR ... OPC_JALR:
1.1.1.12 root 11798: gen_compute_branch(ctx, op1, 4, rs, rd, sa);
11799: *is_branch = 1;
11800: break;
1.1.1.5 root 11801: case OPC_TGE ... OPC_TEQ: /* Traps */
11802: case OPC_TNE:
11803: gen_trap(ctx, op1, rs, rt, -1);
11804: break;
11805: case OPC_MFHI: /* Move from HI/LO */
11806: case OPC_MFLO:
11807: gen_HILO(ctx, op1, rd);
1.1 root 11808: break;
1.1.1.5 root 11809: case OPC_MTHI:
11810: case OPC_MTLO: /* Move to HI/LO */
11811: gen_HILO(ctx, op1, rs);
11812: break;
1.1.1.6 root 11813: case OPC_PMON: /* Pmon entry point, also R4010 selsl */
11814: #ifdef MIPS_STRICT_STANDARD
11815: MIPS_INVAL("PMON / selsl");
11816: generate_exception(ctx, EXCP_RI);
11817: #else
1.1.1.7 root 11818: gen_helper_0i(pmon, sa);
1.1.1.6 root 11819: #endif
1.1.1.5 root 11820: break;
11821: case OPC_SYSCALL:
1.1 root 11822: generate_exception(ctx, EXCP_SYSCALL);
1.1.1.8 root 11823: ctx->bstate = BS_STOP;
1.1 root 11824: break;
1.1.1.5 root 11825: case OPC_BREAK:
1.1 root 11826: generate_exception(ctx, EXCP_BREAK);
11827: break;
1.1.1.6 root 11828: case OPC_SPIM:
11829: #ifdef MIPS_STRICT_STANDARD
11830: MIPS_INVAL("SPIM");
11831: generate_exception(ctx, EXCP_RI);
11832: #else
1.1.1.5 root 11833: /* Implemented as RI exception for now. */
11834: MIPS_INVAL("spim (unofficial)");
11835: generate_exception(ctx, EXCP_RI);
1.1.1.6 root 11836: #endif
1.1 root 11837: break;
1.1.1.5 root 11838: case OPC_SYNC:
1.1.1.6 root 11839: /* Treat as NOP. */
1.1 root 11840: break;
1.1.1.2 root 11841:
1.1.1.5 root 11842: case OPC_MOVCI:
1.1.1.6 root 11843: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
11844: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11845: check_cp1_enabled(ctx);
11846: gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11847: (ctx->opcode >> 16) & 1);
11848: } else {
11849: generate_exception_err(ctx, EXCP_CpU, 1);
11850: }
1.1.1.2 root 11851: break;
11852:
1.1.1.6 root 11853: #if defined(TARGET_MIPS64)
1.1.1.5 root 11854: /* MIPS64 specific opcodes */
11855: case OPC_DSLL:
1.1.1.8 root 11856: case OPC_DSRA:
1.1.1.5 root 11857: case OPC_DSLL32:
1.1.1.8 root 11858: case OPC_DSRA32:
1.1.1.6 root 11859: check_insn(env, ctx, ISA_MIPS3);
11860: check_mips_64(ctx);
1.1.1.8 root 11861: gen_shift_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 11862: break;
1.1.1.12 root 11863: case OPC_DSRL:
11864: switch ((ctx->opcode >> 21) & 0x1f) {
11865: case 1:
11866: /* drotr is decoded as dsrl on non-R2 CPUs */
11867: if (env->insn_flags & ISA_MIPS32R2) {
11868: op1 = OPC_DROTR;
11869: }
11870: /* Fallthrough */
11871: case 0:
11872: check_insn(env, ctx, ISA_MIPS3);
11873: check_mips_64(ctx);
11874: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11875: break;
11876: default:
11877: generate_exception(ctx, EXCP_RI);
11878: break;
11879: }
11880: break;
11881: case OPC_DSRL32:
11882: switch ((ctx->opcode >> 21) & 0x1f) {
11883: case 1:
11884: /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
11885: if (env->insn_flags & ISA_MIPS32R2) {
11886: op1 = OPC_DROTR32;
11887: }
11888: /* Fallthrough */
11889: case 0:
11890: check_insn(env, ctx, ISA_MIPS3);
11891: check_mips_64(ctx);
11892: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11893: break;
11894: default:
11895: generate_exception(ctx, EXCP_RI);
11896: break;
11897: }
11898: break;
1.1.1.5 root 11899: case OPC_DADD ... OPC_DSUBU:
1.1.1.6 root 11900: check_insn(env, ctx, ISA_MIPS3);
11901: check_mips_64(ctx);
11902: gen_arith(env, ctx, op1, rd, rs, rt);
1.1.1.5 root 11903: break;
1.1.1.8 root 11904: case OPC_DSLLV:
11905: case OPC_DSRAV:
11906: check_insn(env, ctx, ISA_MIPS3);
11907: check_mips_64(ctx);
11908: gen_shift(env, ctx, op1, rd, rs, rt);
11909: break;
1.1.1.12 root 11910: case OPC_DSRLV:
11911: switch ((ctx->opcode >> 6) & 0x1f) {
11912: case 1:
11913: /* drotrv is decoded as dsrlv on non-R2 CPUs */
11914: if (env->insn_flags & ISA_MIPS32R2) {
11915: op1 = OPC_DROTRV;
11916: }
11917: /* Fallthrough */
11918: case 0:
11919: check_insn(env, ctx, ISA_MIPS3);
11920: check_mips_64(ctx);
11921: gen_shift(env, ctx, op1, rd, rs, rt);
11922: break;
11923: default:
11924: generate_exception(ctx, EXCP_RI);
11925: break;
11926: }
11927: break;
1.1.1.5 root 11928: case OPC_DMULT ... OPC_DDIVU:
1.1.1.6 root 11929: check_insn(env, ctx, ISA_MIPS3);
11930: check_mips_64(ctx);
1.1.1.5 root 11931: gen_muldiv(ctx, op1, rs, rt);
11932: break;
1.1 root 11933: #endif
11934: default: /* Invalid */
11935: MIPS_INVAL("special");
11936: generate_exception(ctx, EXCP_RI);
11937: break;
11938: }
11939: break;
1.1.1.5 root 11940: case OPC_SPECIAL2:
11941: op1 = MASK_SPECIAL2(ctx->opcode);
1.1 root 11942: switch (op1) {
1.1.1.5 root 11943: case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11944: case OPC_MSUB ... OPC_MSUBU:
1.1.1.6 root 11945: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 11946: gen_muldiv(ctx, op1, rs, rt);
1.1 root 11947: break;
1.1.1.5 root 11948: case OPC_MUL:
1.1.1.6 root 11949: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 11950: break;
1.1.1.8 root 11951: case OPC_CLO:
11952: case OPC_CLZ:
1.1.1.6 root 11953: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 11954: gen_cl(ctx, op1, rd, rs);
1.1 root 11955: break;
1.1.1.5 root 11956: case OPC_SDBBP:
1.1 root 11957: /* XXX: not clear which exception should be raised
11958: * when in debug mode...
11959: */
1.1.1.6 root 11960: check_insn(env, ctx, ISA_MIPS32);
1.1 root 11961: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11962: generate_exception(ctx, EXCP_DBp);
11963: } else {
11964: generate_exception(ctx, EXCP_DBp);
11965: }
1.1.1.6 root 11966: /* Treat as NOP. */
1.1 root 11967: break;
1.1.1.12 root 11968: case OPC_DIV_G_2F:
11969: case OPC_DIVU_G_2F:
11970: case OPC_MULT_G_2F:
11971: case OPC_MULTU_G_2F:
11972: case OPC_MOD_G_2F:
11973: case OPC_MODU_G_2F:
11974: check_insn(env, ctx, INSN_LOONGSON2F);
11975: gen_loongson_integer(ctx, op1, rd, rs, rt);
11976: break;
1.1.1.6 root 11977: #if defined(TARGET_MIPS64)
1.1.1.8 root 11978: case OPC_DCLO:
11979: case OPC_DCLZ:
1.1.1.6 root 11980: check_insn(env, ctx, ISA_MIPS64);
11981: check_mips_64(ctx);
1.1.1.5 root 11982: gen_cl(ctx, op1, rd, rs);
11983: break;
1.1.1.12 root 11984: case OPC_DMULT_G_2F:
11985: case OPC_DMULTU_G_2F:
11986: case OPC_DDIV_G_2F:
11987: case OPC_DDIVU_G_2F:
11988: case OPC_DMOD_G_2F:
11989: case OPC_DMODU_G_2F:
11990: check_insn(env, ctx, INSN_LOONGSON2F);
11991: gen_loongson_integer(ctx, op1, rd, rs, rt);
11992: break;
1.1.1.5 root 11993: #endif
1.1 root 11994: default: /* Invalid */
11995: MIPS_INVAL("special2");
11996: generate_exception(ctx, EXCP_RI);
11997: break;
11998: }
11999: break;
1.1.1.5 root 12000: case OPC_SPECIAL3:
1.1.1.7 root 12001: op1 = MASK_SPECIAL3(ctx->opcode);
12002: switch (op1) {
12003: case OPC_EXT:
12004: case OPC_INS:
12005: check_insn(env, ctx, ISA_MIPS32R2);
12006: gen_bitops(ctx, op1, rt, rs, sa, rd);
12007: break;
12008: case OPC_BSHFL:
12009: check_insn(env, ctx, ISA_MIPS32R2);
12010: op2 = MASK_BSHFL(ctx->opcode);
12011: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 12012: break;
12013: case OPC_RDHWR:
1.1.1.12 root 12014: gen_rdhwr(env, ctx, rt, rd);
1.1.1.6 root 12015: break;
12016: case OPC_FORK:
12017: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 12018: {
1.1.1.8 root 12019: TCGv t0 = tcg_temp_new();
12020: TCGv t1 = tcg_temp_new();
1.1.1.7 root 12021:
12022: gen_load_gpr(t0, rt);
12023: gen_load_gpr(t1, rs);
12024: gen_helper_fork(t0, t1);
12025: tcg_temp_free(t0);
12026: tcg_temp_free(t1);
12027: }
1.1.1.6 root 12028: break;
12029: case OPC_YIELD:
12030: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 12031: {
1.1.1.8 root 12032: TCGv t0 = tcg_temp_new();
1.1.1.7 root 12033:
1.1.1.8 root 12034: save_cpu_state(ctx, 1);
1.1.1.7 root 12035: gen_load_gpr(t0, rs);
12036: gen_helper_yield(t0, t0);
12037: gen_store_gpr(t0, rd);
12038: tcg_temp_free(t0);
12039: }
1.1.1.6 root 12040: break;
1.1.1.12 root 12041: case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
12042: case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
12043: case OPC_MOD_G_2E ... OPC_MODU_G_2E:
12044: check_insn(env, ctx, INSN_LOONGSON2E);
12045: gen_loongson_integer(ctx, op1, rd, rs, rt);
12046: break;
1.1.1.6 root 12047: #if defined(TARGET_MIPS64)
12048: case OPC_DEXTM ... OPC_DEXT:
12049: case OPC_DINSM ... OPC_DINS:
12050: check_insn(env, ctx, ISA_MIPS64R2);
12051: check_mips_64(ctx);
1.1.1.5 root 12052: gen_bitops(ctx, op1, rt, rs, sa, rd);
12053: break;
1.1.1.6 root 12054: case OPC_DBSHFL:
12055: check_insn(env, ctx, ISA_MIPS64R2);
12056: check_mips_64(ctx);
12057: op2 = MASK_DBSHFL(ctx->opcode);
1.1.1.7 root 12058: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 12059: break;
1.1.1.12 root 12060: case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
12061: case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
12062: case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
12063: check_insn(env, ctx, INSN_LOONGSON2E);
12064: gen_loongson_integer(ctx, op1, rd, rs, rt);
12065: break;
1.1.1.5 root 12066: #endif
12067: default: /* Invalid */
12068: MIPS_INVAL("special3");
12069: generate_exception(ctx, EXCP_RI);
12070: break;
12071: }
12072: break;
12073: case OPC_REGIMM:
12074: op1 = MASK_REGIMM(ctx->opcode);
1.1 root 12075: switch (op1) {
1.1.1.5 root 12076: case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
12077: case OPC_BLTZAL ... OPC_BGEZALL:
1.1.1.12 root 12078: gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
12079: *is_branch = 1;
12080: break;
1.1.1.5 root 12081: case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
12082: case OPC_TNEI:
12083: gen_trap(ctx, op1, rs, -1, imm);
12084: break;
12085: case OPC_SYNCI:
1.1.1.6 root 12086: check_insn(env, ctx, ISA_MIPS32R2);
12087: /* Treat as NOP. */
1.1 root 12088: break;
12089: default: /* Invalid */
1.1.1.6 root 12090: MIPS_INVAL("regimm");
1.1 root 12091: generate_exception(ctx, EXCP_RI);
12092: break;
12093: }
12094: break;
1.1.1.5 root 12095: case OPC_CP0:
1.1.1.6 root 12096: check_cp0_enabled(ctx);
1.1.1.5 root 12097: op1 = MASK_CP0(ctx->opcode);
1.1 root 12098: switch (op1) {
1.1.1.5 root 12099: case OPC_MFC0:
12100: case OPC_MTC0:
1.1.1.6 root 12101: case OPC_MFTR:
12102: case OPC_MTTR:
12103: #if defined(TARGET_MIPS64)
1.1.1.5 root 12104: case OPC_DMFC0:
12105: case OPC_DMTC0:
12106: #endif
1.1.1.7 root 12107: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 12108: gen_cp0(env, ctx, op1, rt, rd);
1.1.1.7 root 12109: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 12110: break;
12111: case OPC_C0_FIRST ... OPC_C0_LAST:
1.1.1.7 root 12112: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 12113: gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
1.1.1.7 root 12114: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 12115: break;
12116: case OPC_MFMC0:
1.1.1.7 root 12117: #ifndef CONFIG_USER_ONLY
12118: {
1.1.1.8 root 12119: TCGv t0 = tcg_temp_new();
1.1.1.7 root 12120:
12121: op2 = MASK_MFMC0(ctx->opcode);
12122: switch (op2) {
12123: case OPC_DMT:
12124: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12125: gen_helper_dmt(t0);
1.1.1.8 root 12126: gen_store_gpr(t0, rt);
1.1.1.7 root 12127: break;
12128: case OPC_EMT:
12129: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12130: gen_helper_emt(t0);
1.1.1.8 root 12131: gen_store_gpr(t0, rt);
1.1.1.7 root 12132: break;
12133: case OPC_DVPE:
12134: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12135: gen_helper_dvpe(t0);
1.1.1.8 root 12136: gen_store_gpr(t0, rt);
1.1.1.7 root 12137: break;
12138: case OPC_EVPE:
12139: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12140: gen_helper_evpe(t0);
1.1.1.8 root 12141: gen_store_gpr(t0, rt);
1.1.1.7 root 12142: break;
12143: case OPC_DI:
12144: check_insn(env, ctx, ISA_MIPS32R2);
12145: save_cpu_state(ctx, 1);
12146: gen_helper_di(t0);
1.1.1.8 root 12147: gen_store_gpr(t0, rt);
1.1.1.7 root 12148: /* Stop translation as we may have switched the execution mode */
12149: ctx->bstate = BS_STOP;
12150: break;
12151: case OPC_EI:
12152: check_insn(env, ctx, ISA_MIPS32R2);
12153: save_cpu_state(ctx, 1);
12154: gen_helper_ei(t0);
1.1.1.8 root 12155: gen_store_gpr(t0, rt);
1.1.1.7 root 12156: /* Stop translation as we may have switched the execution mode */
12157: ctx->bstate = BS_STOP;
12158: break;
12159: default: /* Invalid */
12160: MIPS_INVAL("mfmc0");
12161: generate_exception(ctx, EXCP_RI);
12162: break;
12163: }
12164: tcg_temp_free(t0);
1.1.1.5 root 12165: }
1.1.1.7 root 12166: #endif /* !CONFIG_USER_ONLY */
1.1 root 12167: break;
1.1.1.5 root 12168: case OPC_RDPGPR:
1.1.1.6 root 12169: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 root 12170: gen_load_srsgpr(rt, rd);
1.1.1.6 root 12171: break;
1.1.1.5 root 12172: case OPC_WRPGPR:
1.1.1.6 root 12173: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 root 12174: gen_store_srsgpr(rt, rd);
1.1.1.6 root 12175: break;
1.1 root 12176: default:
1.1.1.6 root 12177: MIPS_INVAL("cp0");
1.1.1.5 root 12178: generate_exception(ctx, EXCP_RI);
1.1 root 12179: break;
12180: }
12181: break;
1.1.1.8 root 12182: case OPC_ADDI: /* Arithmetic with immediate opcode */
12183: case OPC_ADDIU:
1.1.1.6 root 12184: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 12185: break;
1.1.1.8 root 12186: case OPC_SLTI: /* Set on less than with immediate opcode */
12187: case OPC_SLTIU:
12188: gen_slt_imm(env, op, rt, rs, imm);
12189: break;
12190: case OPC_ANDI: /* Arithmetic with immediate opcode */
12191: case OPC_LUI:
12192: case OPC_ORI:
12193: case OPC_XORI:
12194: gen_logic_imm(env, op, rt, rs, imm);
12195: break;
1.1.1.5 root 12196: case OPC_J ... OPC_JAL: /* Jump */
12197: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
1.1.1.12 root 12198: gen_compute_branch(ctx, op, 4, rs, rt, offset);
12199: *is_branch = 1;
12200: break;
1.1.1.5 root 12201: case OPC_BEQ ... OPC_BGTZ: /* Branch */
12202: case OPC_BEQL ... OPC_BGTZL:
1.1.1.12 root 12203: gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
12204: *is_branch = 1;
12205: break;
1.1.1.5 root 12206: case OPC_LB ... OPC_LWR: /* Load and stores */
1.1.1.12 root 12207: case OPC_LL:
12208: gen_ld(env, ctx, op, rt, rs, imm);
12209: break;
1.1.1.5 root 12210: case OPC_SB ... OPC_SW:
12211: case OPC_SWR:
1.1.1.12 root 12212: gen_st(ctx, op, rt, rs, imm);
1.1.1.5 root 12213: break;
1.1.1.8 root 12214: case OPC_SC:
12215: gen_st_cond(ctx, op, rt, rs, imm);
12216: break;
1.1.1.5 root 12217: case OPC_CACHE:
1.1.1.6 root 12218: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
12219: /* Treat as NOP. */
12220: break;
1.1.1.5 root 12221: case OPC_PREF:
1.1.1.6 root 12222: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
12223: /* Treat as NOP. */
1.1 root 12224: break;
1.1.1.2 root 12225:
1.1.1.6 root 12226: /* Floating point (COP1). */
1.1.1.5 root 12227: case OPC_LWC1:
12228: case OPC_LDC1:
12229: case OPC_SWC1:
12230: case OPC_SDC1:
1.1.1.12 root 12231: gen_cop1_ldst(env, ctx, op, rt, rs, imm);
1.1.1.4 root 12232: break;
12233:
1.1.1.5 root 12234: case OPC_CP1:
1.1.1.6 root 12235: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12236: check_cp1_enabled(ctx);
12237: op1 = MASK_CP1(ctx->opcode);
12238: switch (op1) {
12239: case OPC_MFHC1:
12240: case OPC_MTHC1:
12241: check_insn(env, ctx, ISA_MIPS32R2);
12242: case OPC_MFC1:
12243: case OPC_CFC1:
12244: case OPC_MTC1:
12245: case OPC_CTC1:
12246: gen_cp1(ctx, op1, rt, rd);
12247: break;
12248: #if defined(TARGET_MIPS64)
12249: case OPC_DMFC1:
12250: case OPC_DMTC1:
12251: check_insn(env, ctx, ISA_MIPS3);
12252: gen_cp1(ctx, op1, rt, rd);
12253: break;
1.1.1.5 root 12254: #endif
1.1.1.6 root 12255: case OPC_BC1ANY2:
12256: case OPC_BC1ANY4:
12257: check_cop1x(ctx);
12258: check_insn(env, ctx, ASE_MIPS3D);
12259: /* fall through */
12260: case OPC_BC1:
12261: gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
12262: (rt >> 2) & 0x7, imm << 2);
1.1.1.12 root 12263: *is_branch = 1;
12264: break;
1.1.1.6 root 12265: case OPC_S_FMT:
12266: case OPC_D_FMT:
12267: case OPC_W_FMT:
12268: case OPC_L_FMT:
12269: case OPC_PS_FMT:
1.1.1.12 root 12270: gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
1.1.1.6 root 12271: (imm >> 8) & 0x7);
12272: break;
12273: default:
12274: MIPS_INVAL("cp1");
12275: generate_exception (ctx, EXCP_RI);
12276: break;
12277: }
12278: } else {
12279: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.4 root 12280: }
1.1.1.2 root 12281: break;
12282:
12283: /* COP2. */
1.1.1.5 root 12284: case OPC_LWC2:
12285: case OPC_LDC2:
12286: case OPC_SWC2:
12287: case OPC_SDC2:
12288: case OPC_CP2:
12289: /* COP2: Not implemented. */
1.1.1.2 root 12290: generate_exception_err(ctx, EXCP_CpU, 2);
12291: break;
12292:
1.1.1.5 root 12293: case OPC_CP3:
1.1.1.6 root 12294: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12295: check_cp1_enabled(ctx);
12296: op1 = MASK_CP3(ctx->opcode);
12297: switch (op1) {
12298: case OPC_LWXC1:
12299: case OPC_LDXC1:
12300: case OPC_LUXC1:
12301: case OPC_SWXC1:
12302: case OPC_SDXC1:
12303: case OPC_SUXC1:
12304: gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
12305: break;
12306: case OPC_PREFX:
12307: /* Treat as NOP. */
12308: break;
12309: case OPC_ALNV_PS:
12310: case OPC_MADD_S:
12311: case OPC_MADD_D:
12312: case OPC_MADD_PS:
12313: case OPC_MSUB_S:
12314: case OPC_MSUB_D:
12315: case OPC_MSUB_PS:
12316: case OPC_NMADD_S:
12317: case OPC_NMADD_D:
12318: case OPC_NMADD_PS:
12319: case OPC_NMSUB_S:
12320: case OPC_NMSUB_D:
12321: case OPC_NMSUB_PS:
12322: gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12323: break;
12324: default:
12325: MIPS_INVAL("cp3");
12326: generate_exception (ctx, EXCP_RI);
12327: break;
12328: }
12329: } else {
12330: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.5 root 12331: }
1.1.1.2 root 12332: break;
12333:
1.1.1.6 root 12334: #if defined(TARGET_MIPS64)
1.1.1.5 root 12335: /* MIPS64 opcodes */
12336: case OPC_LWU:
12337: case OPC_LDL ... OPC_LDR:
12338: case OPC_LLD:
12339: case OPC_LD:
1.1.1.12 root 12340: check_insn(env, ctx, ISA_MIPS3);
12341: check_mips_64(ctx);
12342: gen_ld(env, ctx, op, rt, rs, imm);
12343: break;
12344: case OPC_SDL ... OPC_SDR:
1.1.1.5 root 12345: case OPC_SD:
1.1.1.6 root 12346: check_insn(env, ctx, ISA_MIPS3);
12347: check_mips_64(ctx);
1.1.1.12 root 12348: gen_st(ctx, op, rt, rs, imm);
1.1.1.5 root 12349: break;
1.1.1.8 root 12350: case OPC_SCD:
12351: check_insn(env, ctx, ISA_MIPS3);
12352: check_mips_64(ctx);
12353: gen_st_cond(ctx, op, rt, rs, imm);
12354: break;
12355: case OPC_DADDI:
12356: case OPC_DADDIU:
1.1.1.6 root 12357: check_insn(env, ctx, ISA_MIPS3);
12358: check_mips_64(ctx);
12359: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 12360: break;
12361: #endif
12362: case OPC_JALX:
1.1.1.12 root 12363: check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
12364: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12365: gen_compute_branch(ctx, op, 4, rs, rt, offset);
12366: *is_branch = 1;
12367: break;
1.1.1.5 root 12368: case OPC_MDMX:
1.1.1.6 root 12369: check_insn(env, ctx, ASE_MDMX);
1.1.1.5 root 12370: /* MDMX: Not implemented. */
1.1 root 12371: default: /* Invalid */
1.1.1.6 root 12372: MIPS_INVAL("major opcode");
1.1 root 12373: generate_exception(ctx, EXCP_RI);
12374: break;
12375: }
12376: }
12377:
1.1.1.7 root 12378: static inline void
1.1.1.6 root 12379: gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
12380: int search_pc)
1.1 root 12381: {
1.1.1.6 root 12382: DisasContext ctx;
1.1 root 12383: target_ulong pc_start;
12384: uint16_t *gen_opc_end;
1.1.1.7 root 12385: CPUBreakpoint *bp;
1.1 root 12386: int j, lj = -1;
1.1.1.7 root 12387: int num_insns;
12388: int max_insns;
1.1.1.12 root 12389: int insn_bytes;
12390: int is_branch;
1.1 root 12391:
1.1.1.7 root 12392: if (search_pc)
12393: qemu_log("search pc %d\n", search_pc);
1.1.1.2 root 12394:
1.1 root 12395: pc_start = tb->pc;
1.1.1.9 root 12396: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1.1 root 12397: ctx.pc = pc_start;
1.1.1.2 root 12398: ctx.saved_pc = -1;
1.1.1.9 root 12399: ctx.singlestep_enabled = env->singlestep_enabled;
1.1 root 12400: ctx.tb = tb;
12401: ctx.bstate = BS_NONE;
1.1.1.2 root 12402: /* Restore delay slot state from the tb context. */
1.1.1.6 root 12403: ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
12404: restore_cpu_state(env, &ctx);
1.1.1.7 root 12405: #ifdef CONFIG_USER_ONLY
12406: ctx.mem_idx = MIPS_HFLAG_UM;
1.1 root 12407: #else
1.1.1.7 root 12408: ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
1.1 root 12409: #endif
1.1.1.7 root 12410: num_insns = 0;
12411: max_insns = tb->cflags & CF_COUNT_MASK;
12412: if (max_insns == 0)
12413: max_insns = CF_COUNT_MASK;
12414: LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
12415: gen_icount_start();
12416: while (ctx.bstate == BS_NONE) {
1.1.1.9 root 12417: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12418: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1.1.7 root 12419: if (bp->pc == ctx.pc) {
1.1.1.6 root 12420: save_cpu_state(&ctx, 1);
1.1.1.2 root 12421: ctx.bstate = BS_BRANCH;
1.1.1.7 root 12422: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 12423: /* Include the breakpoint location or the tb won't
12424: * be flushed when it must be. */
12425: ctx.pc += 4;
1.1.1.2 root 12426: goto done_generating;
12427: }
12428: }
12429: }
12430:
1.1 root 12431: if (search_pc) {
12432: j = gen_opc_ptr - gen_opc_buf;
12433: if (lj < j) {
12434: lj++;
12435: while (lj < j)
12436: gen_opc_instr_start[lj++] = 0;
12437: }
1.1.1.2 root 12438: gen_opc_pc[lj] = ctx.pc;
12439: gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12440: gen_opc_instr_start[lj] = 1;
1.1.1.7 root 12441: gen_opc_icount[lj] = num_insns;
1.1 root 12442: }
1.1.1.7 root 12443: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12444: gen_io_start();
1.1.1.12 root 12445:
12446: is_branch = 0;
12447: if (!(ctx.hflags & MIPS_HFLAG_M16)) {
12448: ctx.opcode = ldl_code(ctx.pc);
12449: insn_bytes = 4;
12450: decode_opc(env, &ctx, &is_branch);
12451: } else if (env->insn_flags & ASE_MICROMIPS) {
12452: ctx.opcode = lduw_code(ctx.pc);
12453: insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
12454: } else if (env->insn_flags & ASE_MIPS16) {
12455: ctx.opcode = lduw_code(ctx.pc);
12456: insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
12457: } else {
12458: generate_exception(&ctx, EXCP_RI);
12459: ctx.bstate = BS_STOP;
12460: break;
12461: }
12462: if (!is_branch) {
12463: handle_delay_slot(env, &ctx, insn_bytes);
12464: }
12465: ctx.pc += insn_bytes;
12466:
1.1.1.7 root 12467: num_insns++;
1.1.1.2 root 12468:
1.1.1.9 root 12469: /* Execute a branch and its delay slot as a single instruction.
12470: This is what GDB expects and is consistent with what the
12471: hardware does (e.g. if a delay slot instruction faults, the
12472: reported PC is the PC of the branch). */
12473: if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
1.1.1.2 root 12474: break;
12475:
1.1 root 12476: if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12477: break;
1.1.1.2 root 12478:
1.1.1.7 root 12479: if (gen_opc_ptr >= gen_opc_end)
12480: break;
12481:
12482: if (num_insns >= max_insns)
12483: break;
1.1.1.8 root 12484:
12485: if (singlestep)
12486: break;
1.1 root 12487: }
1.1.1.7 root 12488: if (tb->cflags & CF_LAST_IO)
12489: gen_io_end();
1.1.1.9 root 12490: if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
1.1.1.6 root 12491: save_cpu_state(&ctx, ctx.bstate == BS_NONE);
1.1.1.7 root 12492: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 12493: } else {
1.1.1.7 root 12494: switch (ctx.bstate) {
1.1.1.6 root 12495: case BS_STOP:
12496: gen_goto_tb(&ctx, 0, ctx.pc);
12497: break;
12498: case BS_NONE:
12499: save_cpu_state(&ctx, 0);
12500: gen_goto_tb(&ctx, 0, ctx.pc);
12501: break;
12502: case BS_EXCP:
1.1.1.7 root 12503: tcg_gen_exit_tb(0);
1.1.1.6 root 12504: break;
12505: case BS_BRANCH:
12506: default:
12507: break;
1.1.1.7 root 12508: }
1.1 root 12509: }
1.1.1.2 root 12510: done_generating:
1.1.1.7 root 12511: gen_icount_end(tb, num_insns);
1.1 root 12512: *gen_opc_ptr = INDEX_op_end;
12513: if (search_pc) {
12514: j = gen_opc_ptr - gen_opc_buf;
12515: lj++;
12516: while (lj <= j)
12517: gen_opc_instr_start[lj++] = 0;
12518: } else {
12519: tb->size = ctx.pc - pc_start;
1.1.1.7 root 12520: tb->icount = num_insns;
1.1 root 12521: }
12522: #ifdef DEBUG_DISAS
1.1.1.7 root 12523: LOG_DISAS("\n");
12524: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
12525: qemu_log("IN: %s\n", lookup_symbol(pc_start));
12526: log_target_disas(pc_start, ctx.pc - pc_start, 0);
12527: qemu_log("\n");
1.1 root 12528: }
12529: #endif
12530: }
12531:
1.1.1.7 root 12532: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1.1 root 12533: {
1.1.1.7 root 12534: gen_intermediate_code_internal(env, tb, 0);
1.1 root 12535: }
12536:
1.1.1.7 root 12537: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1.1 root 12538: {
1.1.1.7 root 12539: gen_intermediate_code_internal(env, tb, 1);
1.1 root 12540: }
12541:
1.1.1.13 root 12542: static void fpu_dump_state(CPUState *env, FILE *f, fprintf_function fpu_fprintf,
1.1.1.7 root 12543: int flags)
1.1.1.4 root 12544: {
12545: int i;
1.1.1.6 root 12546: int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
1.1.1.4 root 12547:
1.1.1.12 root 12548: #define printfpr(fp) \
12549: do { \
12550: if (is_fpu64) \
12551: fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12552: " fd:%13g fs:%13g psu: %13g\n", \
12553: (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12554: (double)(fp)->fd, \
12555: (double)(fp)->fs[FP_ENDIAN_IDX], \
12556: (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12557: else { \
12558: fpr_t tmp; \
12559: tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12560: tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12561: fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12562: " fd:%13g fs:%13g psu:%13g\n", \
12563: tmp.w[FP_ENDIAN_IDX], tmp.d, \
12564: (double)tmp.fd, \
12565: (double)tmp.fs[FP_ENDIAN_IDX], \
12566: (double)tmp.fs[!FP_ENDIAN_IDX]); \
12567: } \
1.1.1.4 root 12568: } while(0)
12569:
1.1.1.6 root 12570:
1.1.1.13 root 12571: fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
12572: env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
1.1.1.7 root 12573: get_float_exception_flags(&env->active_fpu.fp_status));
1.1.1.6 root 12574: for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12575: fpu_fprintf(f, "%3s: ", fregnames[i]);
1.1.1.7 root 12576: printfpr(&env->active_fpu.fpr[i]);
1.1.1.4 root 12577: }
12578:
12579: #undef printfpr
12580: }
12581:
1.1.1.6 root 12582: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 12583: /* Debug help: The architecture requires 32bit code to maintain proper
1.1.1.7 root 12584: sign-extended values on 64bit machines. */
1.1.1.5 root 12585:
12586: #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12587:
1.1.1.7 root 12588: static void
12589: cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
1.1.1.13 root 12590: fprintf_function cpu_fprintf,
1.1.1.7 root 12591: int flags)
1.1.1.5 root 12592: {
12593: int i;
12594:
1.1.1.7 root 12595: if (!SIGN_EXT_P(env->active_tc.PC))
12596: cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12597: if (!SIGN_EXT_P(env->active_tc.HI[0]))
12598: cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12599: if (!SIGN_EXT_P(env->active_tc.LO[0]))
12600: cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
1.1.1.5 root 12601: if (!SIGN_EXT_P(env->btarget))
1.1.1.6 root 12602: cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
1.1.1.5 root 12603:
12604: for (i = 0; i < 32; i++) {
1.1.1.7 root 12605: if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12606: cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
1.1.1.5 root 12607: }
12608:
12609: if (!SIGN_EXT_P(env->CP0_EPC))
1.1.1.6 root 12610: cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
1.1.1.9 root 12611: if (!SIGN_EXT_P(env->lladdr))
12612: cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
1.1.1.5 root 12613: }
12614: #endif
12615:
1.1.1.13 root 12616: void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1.1 root 12617: int flags)
12618: {
12619: int i;
1.1.1.6 root 12620:
1.1.1.12 root 12621: cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
12622: " LO=0x" TARGET_FMT_lx " ds %04x "
12623: TARGET_FMT_lx " " TARGET_FMT_ld "\n",
1.1.1.7 root 12624: env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12625: env->hflags, env->btarget, env->bcond);
1.1 root 12626: for (i = 0; i < 32; i++) {
12627: if ((i & 3) == 0)
12628: cpu_fprintf(f, "GPR%02d:", i);
1.1.1.7 root 12629: cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
1.1 root 12630: if ((i & 3) == 3)
12631: cpu_fprintf(f, "\n");
12632: }
12633:
1.1.1.6 root 12634: cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
12635: env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
12636: cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
1.1.1.9 root 12637: env->CP0_Config0, env->CP0_Config1, env->lladdr);
1.1.1.6 root 12638: if (env->hflags & MIPS_HFLAG_FPU)
1.1.1.5 root 12639: fpu_dump_state(env, f, cpu_fprintf, flags);
1.1.1.6 root 12640: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 12641: cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
1.1.1.4 root 12642: #endif
1.1 root 12643: }
12644:
1.1.1.7 root 12645: static void mips_tcg_init(void)
12646: {
12647: int i;
12648: static int inited;
12649:
12650: /* Initialize various static tables. */
12651: if (inited)
12652: return;
12653:
12654: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1.1.1.8 root 12655: TCGV_UNUSED(cpu_gpr[0]);
12656: for (i = 1; i < 32; i++)
1.1.1.7 root 12657: cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
12658: offsetof(CPUState, active_tc.gpr[i]),
12659: regnames[i]);
12660: cpu_PC = tcg_global_mem_new(TCG_AREG0,
12661: offsetof(CPUState, active_tc.PC), "PC");
12662: for (i = 0; i < MIPS_DSP_ACC; i++) {
12663: cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
12664: offsetof(CPUState, active_tc.HI[i]),
12665: regnames_HI[i]);
12666: cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
12667: offsetof(CPUState, active_tc.LO[i]),
12668: regnames_LO[i]);
12669: cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
12670: offsetof(CPUState, active_tc.ACX[i]),
12671: regnames_ACX[i]);
12672: }
12673: cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
12674: offsetof(CPUState, active_tc.DSPControl),
12675: "DSPControl");
1.1.1.8 root 12676: bcond = tcg_global_mem_new(TCG_AREG0,
12677: offsetof(CPUState, bcond), "bcond");
1.1.1.7 root 12678: btarget = tcg_global_mem_new(TCG_AREG0,
12679: offsetof(CPUState, btarget), "btarget");
1.1.1.8 root 12680: hflags = tcg_global_mem_new_i32(TCG_AREG0,
12681: offsetof(CPUState, hflags), "hflags");
12682:
1.1.1.7 root 12683: fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
12684: offsetof(CPUState, active_fpu.fcr0),
12685: "fcr0");
12686: fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
12687: offsetof(CPUState, active_fpu.fcr31),
12688: "fcr31");
12689:
12690: /* register helpers */
12691: #define GEN_HELPER 2
12692: #include "helper.h"
12693:
12694: inited = 1;
12695: }
12696:
1.1.1.6 root 12697: #include "translate_init.c"
12698:
12699: CPUMIPSState *cpu_mips_init (const char *cpu_model)
1.1 root 12700: {
12701: CPUMIPSState *env;
1.1.1.6 root 12702: const mips_def_t *def;
1.1 root 12703:
1.1.1.6 root 12704: def = cpu_mips_find_by_name(cpu_model);
12705: if (!def)
12706: return NULL;
1.1.1.15! root 12707: env = g_malloc0(sizeof(CPUMIPSState));
1.1.1.6 root 12708: env->cpu_model = def;
1.1.1.9 root 12709: env->cpu_model_str = cpu_model;
1.1.1.6 root 12710:
1.1.1.2 root 12711: cpu_exec_init(env);
1.1.1.9 root 12712: #ifndef CONFIG_USER_ONLY
12713: mmu_init(env, def);
12714: #endif
12715: fpu_init(env, def);
12716: mvp_init(env, def);
1.1.1.7 root 12717: mips_tcg_init();
1.1.1.5 root 12718: cpu_reset(env);
1.1.1.8 root 12719: qemu_init_vcpu(env);
1.1.1.5 root 12720: return env;
12721: }
12722:
12723: void cpu_reset (CPUMIPSState *env)
12724: {
1.1.1.7 root 12725: if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12726: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12727: log_cpu_state(env, 0);
12728: }
12729:
1.1.1.5 root 12730: memset(env, 0, offsetof(CPUMIPSState, breakpoints));
1.1 root 12731: tlb_flush(env, 1);
1.1.1.5 root 12732:
1.1.1.9 root 12733: /* Reset registers to their default values */
12734: env->CP0_PRid = env->cpu_model->CP0_PRid;
12735: env->CP0_Config0 = env->cpu_model->CP0_Config0;
12736: #ifdef TARGET_WORDS_BIGENDIAN
12737: env->CP0_Config0 |= (1 << CP0C0_BE);
12738: #endif
12739: env->CP0_Config1 = env->cpu_model->CP0_Config1;
12740: env->CP0_Config2 = env->cpu_model->CP0_Config2;
12741: env->CP0_Config3 = env->cpu_model->CP0_Config3;
12742: env->CP0_Config6 = env->cpu_model->CP0_Config6;
12743: env->CP0_Config7 = env->cpu_model->CP0_Config7;
12744: env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12745: << env->cpu_model->CP0_LLAddr_shift;
12746: env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
12747: env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12748: env->CCRes = env->cpu_model->CCRes;
12749: env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12750: env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12751: env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12752: env->current_tc = 0;
12753: env->SEGBITS = env->cpu_model->SEGBITS;
12754: env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12755: #if defined(TARGET_MIPS64)
12756: if (env->cpu_model->insn_flags & ISA_MIPS3) {
12757: env->SEGMask |= 3ULL << 62;
12758: }
12759: #endif
12760: env->PABITS = env->cpu_model->PABITS;
12761: env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12762: env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12763: env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12764: env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12765: env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12766: env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12767: env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12768: env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12769: env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12770: env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12771: env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
12772: env->insn_flags = env->cpu_model->insn_flags;
12773:
1.1.1.7 root 12774: #if defined(CONFIG_USER_ONLY)
12775: env->hflags = MIPS_HFLAG_UM;
1.1.1.8 root 12776: /* Enable access to the SYNCI_Step register. */
12777: env->CP0_HWREna |= (1 << 1);
1.1.1.9 root 12778: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12779: env->hflags |= MIPS_HFLAG_FPU;
12780: }
12781: #ifdef TARGET_MIPS64
12782: if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
12783: env->hflags |= MIPS_HFLAG_F64;
12784: }
12785: #endif
1.1.1.7 root 12786: #else
1.1.1.5 root 12787: if (env->hflags & MIPS_HFLAG_BMASK) {
12788: /* If the exception was raised from a delay slot,
1.1.1.7 root 12789: come back to the jump. */
12790: env->CP0_ErrorEPC = env->active_tc.PC - 4;
1.1.1.5 root 12791: } else {
1.1.1.7 root 12792: env->CP0_ErrorEPC = env->active_tc.PC;
1.1.1.5 root 12793: }
1.1.1.7 root 12794: env->active_tc.PC = (int32_t)0xBFC00000;
1.1.1.9 root 12795: env->CP0_Random = env->tlb->nb_tlb - 1;
12796: env->tlb->tlb_in_use = env->tlb->nb_tlb;
1.1 root 12797: env->CP0_Wired = 0;
1.1.1.13 root 12798: env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
1.1.1.5 root 12799: env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
1.1.1.6 root 12800: /* vectored interrupts not implemented, timer on int 7,
12801: no performance counters. */
12802: env->CP0_IntCtl = 0xe0000000;
12803: {
12804: int i;
12805:
12806: for (i = 0; i < 7; i++) {
12807: env->CP0_WatchLo[i] = 0;
12808: env->CP0_WatchHi[i] = 0x80000000;
12809: }
12810: env->CP0_WatchLo[7] = 0;
12811: env->CP0_WatchHi[7] = 0;
12812: }
1.1 root 12813: /* Count register increments in debug mode, EJTAG version 1 */
12814: env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
1.1.1.6 root 12815: env->hflags = MIPS_HFLAG_CP0;
1.1.1.15! root 12816:
! 12817: if (env->CP0_Config3 & (1 << CP0C3_MT)) {
! 12818: int i;
! 12819:
! 12820: /* Only TC0 on VPE 0 starts as active. */
! 12821: for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
! 12822: env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
! 12823: env->tcs[i].CP0_TCHalt = 1;
! 12824: }
! 12825: env->active_tc.CP0_TCHalt = 1;
! 12826: env->halted = 1;
! 12827:
! 12828: if (!env->cpu_index) {
! 12829: /* VPE0 starts up enabled. */
! 12830: env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
! 12831: env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
! 12832:
! 12833: /* TC0 starts up unhalted. */
! 12834: env->halted = 0;
! 12835: env->active_tc.CP0_TCHalt = 0;
! 12836: env->tcs[0].CP0_TCHalt = 0;
! 12837: /* With thread 0 active. */
! 12838: env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
! 12839: env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
! 12840: }
! 12841: }
1.1.1.2 root 12842: #endif
1.1.1.9 root 12843: #if defined(TARGET_MIPS64)
12844: if (env->cpu_model->insn_flags & ISA_MIPS3) {
12845: env->hflags |= MIPS_HFLAG_64;
12846: }
12847: #endif
1.1.1.7 root 12848: env->exception_index = EXCP_NONE;
1.1 root 12849: }
1.1.1.7 root 12850:
1.1.1.14 root 12851: void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
1.1.1.7 root 12852: {
12853: env->active_tc.PC = gen_opc_pc[pc_pos];
12854: env->hflags &= ~MIPS_HFLAG_BMASK;
12855: env->hflags |= gen_opc_hflags[pc_pos];
12856: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.