|
|
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) {
5540: case 2:
5541: switch (sel) {
5542: case 1:
1.1.1.7 root 5543: gen_helper_mftc0_tcstatus(t0);
1.1.1.6 root 5544: break;
5545: case 2:
1.1.1.7 root 5546: gen_helper_mftc0_tcbind(t0);
1.1.1.6 root 5547: break;
5548: case 3:
1.1.1.7 root 5549: gen_helper_mftc0_tcrestart(t0);
1.1.1.6 root 5550: break;
5551: case 4:
1.1.1.7 root 5552: gen_helper_mftc0_tchalt(t0);
1.1.1.6 root 5553: break;
5554: case 5:
1.1.1.7 root 5555: gen_helper_mftc0_tccontext(t0);
1.1.1.6 root 5556: break;
5557: case 6:
1.1.1.7 root 5558: gen_helper_mftc0_tcschedule(t0);
1.1.1.6 root 5559: break;
5560: case 7:
1.1.1.7 root 5561: gen_helper_mftc0_tcschefback(t0);
1.1.1.6 root 5562: break;
5563: default:
1.1.1.7 root 5564: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5565: break;
5566: }
5567: break;
5568: case 10:
5569: switch (sel) {
5570: case 0:
1.1.1.7 root 5571: gen_helper_mftc0_entryhi(t0);
1.1.1.6 root 5572: break;
5573: default:
1.1.1.7 root 5574: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5575: break;
5576: }
5577: case 12:
5578: switch (sel) {
5579: case 0:
1.1.1.7 root 5580: gen_helper_mftc0_status(t0);
1.1.1.6 root 5581: break;
5582: default:
1.1.1.7 root 5583: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5584: break;
5585: }
5586: case 23:
5587: switch (sel) {
5588: case 0:
1.1.1.7 root 5589: gen_helper_mftc0_debug(t0);
1.1.1.6 root 5590: break;
5591: default:
1.1.1.7 root 5592: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5593: break;
5594: }
5595: break;
5596: default:
1.1.1.7 root 5597: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5598: }
5599: } else switch (sel) {
5600: /* GPR registers. */
5601: case 0:
1.1.1.7 root 5602: gen_helper_1i(mftgpr, t0, rt);
1.1.1.6 root 5603: break;
5604: /* Auxiliary CPU registers */
5605: case 1:
5606: switch (rt) {
5607: case 0:
1.1.1.7 root 5608: gen_helper_1i(mftlo, t0, 0);
1.1.1.6 root 5609: break;
5610: case 1:
1.1.1.7 root 5611: gen_helper_1i(mfthi, t0, 0);
1.1.1.6 root 5612: break;
5613: case 2:
1.1.1.7 root 5614: gen_helper_1i(mftacx, t0, 0);
1.1.1.6 root 5615: break;
5616: case 4:
1.1.1.7 root 5617: gen_helper_1i(mftlo, t0, 1);
1.1.1.6 root 5618: break;
5619: case 5:
1.1.1.7 root 5620: gen_helper_1i(mfthi, t0, 1);
1.1.1.6 root 5621: break;
5622: case 6:
1.1.1.7 root 5623: gen_helper_1i(mftacx, t0, 1);
1.1.1.6 root 5624: break;
5625: case 8:
1.1.1.7 root 5626: gen_helper_1i(mftlo, t0, 2);
1.1.1.6 root 5627: break;
5628: case 9:
1.1.1.7 root 5629: gen_helper_1i(mfthi, t0, 2);
1.1.1.6 root 5630: break;
5631: case 10:
1.1.1.7 root 5632: gen_helper_1i(mftacx, t0, 2);
1.1.1.6 root 5633: break;
5634: case 12:
1.1.1.7 root 5635: gen_helper_1i(mftlo, t0, 3);
1.1.1.6 root 5636: break;
5637: case 13:
1.1.1.7 root 5638: gen_helper_1i(mfthi, t0, 3);
1.1.1.6 root 5639: break;
5640: case 14:
1.1.1.7 root 5641: gen_helper_1i(mftacx, t0, 3);
1.1.1.6 root 5642: break;
5643: case 16:
1.1.1.7 root 5644: gen_helper_mftdsp(t0);
1.1.1.6 root 5645: break;
5646: default:
5647: goto die;
5648: }
5649: break;
5650: /* Floating point (COP1). */
5651: case 2:
5652: /* XXX: For now we support only a single FPU context. */
5653: if (h == 0) {
1.1.1.7 root 5654: TCGv_i32 fp0 = tcg_temp_new_i32();
5655:
5656: gen_load_fpr32(fp0, rt);
5657: tcg_gen_ext_i32_tl(t0, fp0);
5658: tcg_temp_free_i32(fp0);
1.1.1.6 root 5659: } else {
1.1.1.7 root 5660: TCGv_i32 fp0 = tcg_temp_new_i32();
5661:
5662: gen_load_fpr32h(fp0, rt);
5663: tcg_gen_ext_i32_tl(t0, fp0);
5664: tcg_temp_free_i32(fp0);
1.1.1.6 root 5665: }
5666: break;
5667: case 3:
5668: /* XXX: For now we support only a single FPU context. */
1.1.1.7 root 5669: gen_helper_1i(cfc1, t0, rt);
1.1.1.6 root 5670: break;
5671: /* COP2: Not implemented. */
5672: case 4:
5673: case 5:
5674: /* fall through */
5675: default:
5676: goto die;
5677: }
1.1.1.7 root 5678: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5679: gen_store_gpr(t0, rd);
5680: tcg_temp_free(t0);
1.1.1.6 root 5681: return;
5682:
5683: die:
1.1.1.7 root 5684: tcg_temp_free(t0);
5685: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1.1.1.6 root 5686: generate_exception(ctx, EXCP_RI);
5687: }
5688:
1.1.1.7 root 5689: static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
1.1.1.6 root 5690: int u, int sel, int h)
5691: {
5692: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.7 root 5693: TCGv t0 = tcg_temp_local_new();
1.1.1.6 root 5694:
1.1.1.7 root 5695: gen_load_gpr(t0, rt);
1.1.1.6 root 5696: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
1.1.1.7 root 5697: ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5698: (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1.1.1.6 root 5699: /* NOP */ ;
5700: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5701: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5702: /* NOP */ ;
5703: else if (u == 0) {
5704: switch (rd) {
5705: case 2:
5706: switch (sel) {
5707: case 1:
1.1.1.7 root 5708: gen_helper_mttc0_tcstatus(t0);
1.1.1.6 root 5709: break;
5710: case 2:
1.1.1.7 root 5711: gen_helper_mttc0_tcbind(t0);
1.1.1.6 root 5712: break;
5713: case 3:
1.1.1.7 root 5714: gen_helper_mttc0_tcrestart(t0);
1.1.1.6 root 5715: break;
5716: case 4:
1.1.1.7 root 5717: gen_helper_mttc0_tchalt(t0);
1.1.1.6 root 5718: break;
5719: case 5:
1.1.1.7 root 5720: gen_helper_mttc0_tccontext(t0);
1.1.1.6 root 5721: break;
5722: case 6:
1.1.1.7 root 5723: gen_helper_mttc0_tcschedule(t0);
1.1.1.6 root 5724: break;
5725: case 7:
1.1.1.7 root 5726: gen_helper_mttc0_tcschefback(t0);
1.1.1.6 root 5727: break;
5728: default:
1.1.1.7 root 5729: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5730: break;
5731: }
5732: break;
5733: case 10:
5734: switch (sel) {
5735: case 0:
1.1.1.7 root 5736: gen_helper_mttc0_entryhi(t0);
1.1.1.6 root 5737: break;
5738: default:
1.1.1.7 root 5739: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5740: break;
5741: }
5742: case 12:
5743: switch (sel) {
5744: case 0:
1.1.1.7 root 5745: gen_helper_mttc0_status(t0);
1.1.1.6 root 5746: break;
5747: default:
1.1.1.7 root 5748: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5749: break;
5750: }
5751: case 23:
5752: switch (sel) {
5753: case 0:
1.1.1.7 root 5754: gen_helper_mttc0_debug(t0);
1.1.1.6 root 5755: break;
5756: default:
1.1.1.7 root 5757: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5758: break;
5759: }
5760: break;
5761: default:
1.1.1.7 root 5762: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5763: }
5764: } else switch (sel) {
5765: /* GPR registers. */
5766: case 0:
1.1.1.7 root 5767: gen_helper_1i(mttgpr, t0, rd);
1.1.1.6 root 5768: break;
5769: /* Auxiliary CPU registers */
5770: case 1:
5771: switch (rd) {
5772: case 0:
1.1.1.7 root 5773: gen_helper_1i(mttlo, t0, 0);
1.1.1.6 root 5774: break;
5775: case 1:
1.1.1.7 root 5776: gen_helper_1i(mtthi, t0, 0);
1.1.1.6 root 5777: break;
5778: case 2:
1.1.1.7 root 5779: gen_helper_1i(mttacx, t0, 0);
1.1.1.6 root 5780: break;
5781: case 4:
1.1.1.7 root 5782: gen_helper_1i(mttlo, t0, 1);
1.1.1.6 root 5783: break;
5784: case 5:
1.1.1.7 root 5785: gen_helper_1i(mtthi, t0, 1);
1.1.1.6 root 5786: break;
5787: case 6:
1.1.1.7 root 5788: gen_helper_1i(mttacx, t0, 1);
1.1.1.6 root 5789: break;
5790: case 8:
1.1.1.7 root 5791: gen_helper_1i(mttlo, t0, 2);
1.1.1.6 root 5792: break;
5793: case 9:
1.1.1.7 root 5794: gen_helper_1i(mtthi, t0, 2);
1.1.1.6 root 5795: break;
5796: case 10:
1.1.1.7 root 5797: gen_helper_1i(mttacx, t0, 2);
1.1.1.6 root 5798: break;
5799: case 12:
1.1.1.7 root 5800: gen_helper_1i(mttlo, t0, 3);
1.1.1.6 root 5801: break;
5802: case 13:
1.1.1.7 root 5803: gen_helper_1i(mtthi, t0, 3);
1.1.1.6 root 5804: break;
5805: case 14:
1.1.1.7 root 5806: gen_helper_1i(mttacx, t0, 3);
1.1.1.6 root 5807: break;
5808: case 16:
1.1.1.7 root 5809: gen_helper_mttdsp(t0);
1.1.1.6 root 5810: break;
5811: default:
5812: goto die;
5813: }
5814: break;
5815: /* Floating point (COP1). */
5816: case 2:
5817: /* XXX: For now we support only a single FPU context. */
5818: if (h == 0) {
1.1.1.7 root 5819: TCGv_i32 fp0 = tcg_temp_new_i32();
5820:
5821: tcg_gen_trunc_tl_i32(fp0, t0);
5822: gen_store_fpr32(fp0, rd);
5823: tcg_temp_free_i32(fp0);
1.1.1.6 root 5824: } else {
1.1.1.7 root 5825: TCGv_i32 fp0 = tcg_temp_new_i32();
5826:
5827: tcg_gen_trunc_tl_i32(fp0, t0);
5828: gen_store_fpr32h(fp0, rd);
5829: tcg_temp_free_i32(fp0);
1.1.1.6 root 5830: }
5831: break;
5832: case 3:
5833: /* XXX: For now we support only a single FPU context. */
1.1.1.7 root 5834: gen_helper_1i(ctc1, t0, rd);
1.1.1.6 root 5835: break;
5836: /* COP2: Not implemented. */
5837: case 4:
5838: case 5:
5839: /* fall through */
5840: default:
5841: goto die;
5842: }
1.1.1.7 root 5843: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5844: tcg_temp_free(t0);
1.1.1.6 root 5845: return;
5846:
5847: die:
1.1.1.7 root 5848: tcg_temp_free(t0);
5849: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1.1.1.6 root 5850: generate_exception(ctx, EXCP_RI);
5851: }
5852:
5853: static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5854: {
5855: const char *opn = "ldst";
1.1.1.5 root 5856:
5857: switch (opc) {
5858: case OPC_MFC0:
5859: if (rt == 0) {
1.1.1.6 root 5860: /* Treat as NOP. */
1.1.1.5 root 5861: return;
5862: }
1.1.1.8 root 5863: gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
1.1.1.5 root 5864: opn = "mfc0";
5865: break;
5866: case OPC_MTC0:
1.1.1.7 root 5867: {
1.1.1.8 root 5868: TCGv t0 = tcg_temp_new();
1.1.1.7 root 5869:
5870: gen_load_gpr(t0, rt);
5871: gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5872: tcg_temp_free(t0);
5873: }
1.1.1.5 root 5874: opn = "mtc0";
5875: break;
1.1.1.6 root 5876: #if defined(TARGET_MIPS64)
1.1.1.5 root 5877: case OPC_DMFC0:
1.1.1.6 root 5878: check_insn(env, ctx, ISA_MIPS3);
1.1.1.5 root 5879: if (rt == 0) {
1.1.1.6 root 5880: /* Treat as NOP. */
1.1.1.5 root 5881: return;
5882: }
1.1.1.8 root 5883: gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
1.1.1.5 root 5884: opn = "dmfc0";
5885: break;
5886: case OPC_DMTC0:
1.1.1.6 root 5887: check_insn(env, ctx, ISA_MIPS3);
1.1.1.7 root 5888: {
1.1.1.8 root 5889: TCGv t0 = tcg_temp_new();
1.1.1.7 root 5890:
5891: gen_load_gpr(t0, rt);
5892: gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5893: tcg_temp_free(t0);
5894: }
1.1.1.5 root 5895: opn = "dmtc0";
5896: break;
1.1.1.6 root 5897: #endif
5898: case OPC_MFTR:
5899: check_insn(env, ctx, ASE_MT);
5900: if (rd == 0) {
5901: /* Treat as NOP. */
5902: return;
5903: }
1.1.1.7 root 5904: gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5905: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5906: opn = "mftr";
5907: break;
5908: case OPC_MTTR:
5909: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 5910: gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5911: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5912: opn = "mttr";
5913: break;
1.1.1.5 root 5914: case OPC_TLBWI:
5915: opn = "tlbwi";
1.1.1.8 root 5916: if (!env->tlb->helper_tlbwi)
1.1.1.6 root 5917: goto die;
1.1.1.7 root 5918: gen_helper_tlbwi();
1.1.1.5 root 5919: break;
5920: case OPC_TLBWR:
5921: opn = "tlbwr";
1.1.1.8 root 5922: if (!env->tlb->helper_tlbwr)
1.1.1.6 root 5923: goto die;
1.1.1.7 root 5924: gen_helper_tlbwr();
1.1.1.5 root 5925: break;
5926: case OPC_TLBP:
5927: opn = "tlbp";
1.1.1.8 root 5928: if (!env->tlb->helper_tlbp)
1.1.1.6 root 5929: goto die;
1.1.1.7 root 5930: gen_helper_tlbp();
1.1.1.5 root 5931: break;
5932: case OPC_TLBR:
5933: opn = "tlbr";
1.1.1.8 root 5934: if (!env->tlb->helper_tlbr)
1.1.1.6 root 5935: goto die;
1.1.1.7 root 5936: gen_helper_tlbr();
1.1.1.5 root 5937: break;
5938: case OPC_ERET:
5939: opn = "eret";
1.1.1.6 root 5940: check_insn(env, ctx, ISA_MIPS2);
1.1.1.7 root 5941: gen_helper_eret();
1.1.1.5 root 5942: ctx->bstate = BS_EXCP;
5943: break;
5944: case OPC_DERET:
5945: opn = "deret";
1.1.1.6 root 5946: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 5947: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1.1.1.6 root 5948: MIPS_INVAL(opn);
1.1.1.5 root 5949: generate_exception(ctx, EXCP_RI);
5950: } else {
1.1.1.7 root 5951: gen_helper_deret();
1.1.1.5 root 5952: ctx->bstate = BS_EXCP;
5953: }
5954: break;
5955: case OPC_WAIT:
5956: opn = "wait";
1.1.1.6 root 5957: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
1.1.1.5 root 5958: /* If we get an exception, we want to restart at next instruction */
5959: ctx->pc += 4;
5960: save_cpu_state(ctx, 1);
5961: ctx->pc -= 4;
1.1.1.7 root 5962: gen_helper_wait();
1.1.1.5 root 5963: ctx->bstate = BS_EXCP;
5964: break;
5965: default:
1.1.1.6 root 5966: die:
5967: MIPS_INVAL(opn);
1.1.1.5 root 5968: generate_exception(ctx, EXCP_RI);
5969: return;
5970: }
1.1.1.13 root 5971: (void)opn; /* avoid a compiler warning */
1.1.1.5 root 5972: MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5973: }
1.1.1.7 root 5974: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 5975:
5976: /* CP1 Branches (before delay slot) */
1.1.1.6 root 5977: static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5978: int32_t cc, int32_t offset)
1.1.1.5 root 5979: {
5980: target_ulong btarget;
1.1.1.6 root 5981: const char *opn = "cp1 cond branch";
1.1.1.7 root 5982: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.6 root 5983:
5984: if (cc != 0)
5985: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
1.1.1.5 root 5986:
5987: btarget = ctx->pc + 4 + offset;
5988:
5989: switch (op) {
5990: case OPC_BC1F:
1.1.1.8 root 5991: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5992: tcg_gen_not_i32(t0, t0);
5993: tcg_gen_andi_i32(t0, t0, 1);
5994: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 5995: opn = "bc1f";
1.1.1.5 root 5996: goto not_likely;
5997: case OPC_BC1FL:
1.1.1.8 root 5998: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5999: tcg_gen_not_i32(t0, t0);
6000: tcg_gen_andi_i32(t0, t0, 1);
6001: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6002: opn = "bc1fl";
1.1.1.5 root 6003: goto likely;
6004: case OPC_BC1T:
1.1.1.8 root 6005: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6006: tcg_gen_andi_i32(t0, t0, 1);
6007: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6008: opn = "bc1t";
6009: goto not_likely;
1.1.1.5 root 6010: case OPC_BC1TL:
1.1.1.8 root 6011: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6012: tcg_gen_andi_i32(t0, t0, 1);
6013: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6014: opn = "bc1tl";
1.1.1.5 root 6015: likely:
6016: ctx->hflags |= MIPS_HFLAG_BL;
1.1.1.6 root 6017: break;
6018: case OPC_BC1FANY2:
1.1.1.7 root 6019: {
1.1.1.8 root 6020: TCGv_i32 t1 = tcg_temp_new_i32();
6021: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6022: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
1.1.1.12 root 6023: tcg_gen_nor_i32(t0, t0, t1);
1.1.1.8 root 6024: tcg_temp_free_i32(t1);
6025: tcg_gen_andi_i32(t0, t0, 1);
6026: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6027: }
1.1.1.6 root 6028: opn = "bc1any2f";
6029: goto not_likely;
6030: case OPC_BC1TANY2:
1.1.1.7 root 6031: {
1.1.1.8 root 6032: TCGv_i32 t1 = tcg_temp_new_i32();
6033: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6034: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6035: tcg_gen_or_i32(t0, t0, t1);
6036: tcg_temp_free_i32(t1);
6037: tcg_gen_andi_i32(t0, t0, 1);
6038: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6039: }
1.1.1.6 root 6040: opn = "bc1any2t";
6041: goto not_likely;
6042: case OPC_BC1FANY4:
1.1.1.7 root 6043: {
1.1.1.8 root 6044: TCGv_i32 t1 = tcg_temp_new_i32();
6045: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6046: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6047: tcg_gen_or_i32(t0, t0, t1);
6048: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6049: tcg_gen_or_i32(t0, t0, t1);
6050: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
1.1.1.12 root 6051: tcg_gen_nor_i32(t0, t0, t1);
1.1.1.8 root 6052: tcg_temp_free_i32(t1);
6053: tcg_gen_andi_i32(t0, t0, 1);
6054: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6055: }
1.1.1.6 root 6056: opn = "bc1any4f";
6057: goto not_likely;
6058: case OPC_BC1TANY4:
1.1.1.7 root 6059: {
1.1.1.8 root 6060: TCGv_i32 t1 = tcg_temp_new_i32();
6061: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6062: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6063: tcg_gen_or_i32(t0, t0, t1);
6064: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6065: tcg_gen_or_i32(t0, t0, t1);
6066: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6067: tcg_gen_or_i32(t0, t0, t1);
6068: tcg_temp_free_i32(t1);
6069: tcg_gen_andi_i32(t0, t0, 1);
6070: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6071: }
1.1.1.6 root 6072: opn = "bc1any4t";
6073: not_likely:
6074: ctx->hflags |= MIPS_HFLAG_BC;
1.1.1.5 root 6075: break;
1.1.1.6 root 6076: default:
6077: MIPS_INVAL(opn);
6078: generate_exception (ctx, EXCP_RI);
1.1.1.7 root 6079: goto out;
1.1.1.5 root 6080: }
1.1.1.13 root 6081: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 6082: MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
1.1.1.5 root 6083: ctx->hflags, btarget);
6084: ctx->btarget = btarget;
1.1.1.7 root 6085:
6086: out:
6087: tcg_temp_free_i32(t0);
1.1.1.5 root 6088: }
6089:
6090: /* Coprocessor 1 (FPU) */
1.1.1.6 root 6091:
6092: #define FOP(func, fmt) (((fmt) << 21) | (func))
6093:
1.1.1.12 root 6094: enum fopcode {
6095: OPC_ADD_S = FOP(0, FMT_S),
6096: OPC_SUB_S = FOP(1, FMT_S),
6097: OPC_MUL_S = FOP(2, FMT_S),
6098: OPC_DIV_S = FOP(3, FMT_S),
6099: OPC_SQRT_S = FOP(4, FMT_S),
6100: OPC_ABS_S = FOP(5, FMT_S),
6101: OPC_MOV_S = FOP(6, FMT_S),
6102: OPC_NEG_S = FOP(7, FMT_S),
6103: OPC_ROUND_L_S = FOP(8, FMT_S),
6104: OPC_TRUNC_L_S = FOP(9, FMT_S),
6105: OPC_CEIL_L_S = FOP(10, FMT_S),
6106: OPC_FLOOR_L_S = FOP(11, FMT_S),
6107: OPC_ROUND_W_S = FOP(12, FMT_S),
6108: OPC_TRUNC_W_S = FOP(13, FMT_S),
6109: OPC_CEIL_W_S = FOP(14, FMT_S),
6110: OPC_FLOOR_W_S = FOP(15, FMT_S),
6111: OPC_MOVCF_S = FOP(17, FMT_S),
6112: OPC_MOVZ_S = FOP(18, FMT_S),
6113: OPC_MOVN_S = FOP(19, FMT_S),
6114: OPC_RECIP_S = FOP(21, FMT_S),
6115: OPC_RSQRT_S = FOP(22, FMT_S),
6116: OPC_RECIP2_S = FOP(28, FMT_S),
6117: OPC_RECIP1_S = FOP(29, FMT_S),
6118: OPC_RSQRT1_S = FOP(30, FMT_S),
6119: OPC_RSQRT2_S = FOP(31, FMT_S),
6120: OPC_CVT_D_S = FOP(33, FMT_S),
6121: OPC_CVT_W_S = FOP(36, FMT_S),
6122: OPC_CVT_L_S = FOP(37, FMT_S),
6123: OPC_CVT_PS_S = FOP(38, FMT_S),
6124: OPC_CMP_F_S = FOP (48, FMT_S),
6125: OPC_CMP_UN_S = FOP (49, FMT_S),
6126: OPC_CMP_EQ_S = FOP (50, FMT_S),
6127: OPC_CMP_UEQ_S = FOP (51, FMT_S),
6128: OPC_CMP_OLT_S = FOP (52, FMT_S),
6129: OPC_CMP_ULT_S = FOP (53, FMT_S),
6130: OPC_CMP_OLE_S = FOP (54, FMT_S),
6131: OPC_CMP_ULE_S = FOP (55, FMT_S),
6132: OPC_CMP_SF_S = FOP (56, FMT_S),
6133: OPC_CMP_NGLE_S = FOP (57, FMT_S),
6134: OPC_CMP_SEQ_S = FOP (58, FMT_S),
6135: OPC_CMP_NGL_S = FOP (59, FMT_S),
6136: OPC_CMP_LT_S = FOP (60, FMT_S),
6137: OPC_CMP_NGE_S = FOP (61, FMT_S),
6138: OPC_CMP_LE_S = FOP (62, FMT_S),
6139: OPC_CMP_NGT_S = FOP (63, FMT_S),
6140:
6141: OPC_ADD_D = FOP(0, FMT_D),
6142: OPC_SUB_D = FOP(1, FMT_D),
6143: OPC_MUL_D = FOP(2, FMT_D),
6144: OPC_DIV_D = FOP(3, FMT_D),
6145: OPC_SQRT_D = FOP(4, FMT_D),
6146: OPC_ABS_D = FOP(5, FMT_D),
6147: OPC_MOV_D = FOP(6, FMT_D),
6148: OPC_NEG_D = FOP(7, FMT_D),
6149: OPC_ROUND_L_D = FOP(8, FMT_D),
6150: OPC_TRUNC_L_D = FOP(9, FMT_D),
6151: OPC_CEIL_L_D = FOP(10, FMT_D),
6152: OPC_FLOOR_L_D = FOP(11, FMT_D),
6153: OPC_ROUND_W_D = FOP(12, FMT_D),
6154: OPC_TRUNC_W_D = FOP(13, FMT_D),
6155: OPC_CEIL_W_D = FOP(14, FMT_D),
6156: OPC_FLOOR_W_D = FOP(15, FMT_D),
6157: OPC_MOVCF_D = FOP(17, FMT_D),
6158: OPC_MOVZ_D = FOP(18, FMT_D),
6159: OPC_MOVN_D = FOP(19, FMT_D),
6160: OPC_RECIP_D = FOP(21, FMT_D),
6161: OPC_RSQRT_D = FOP(22, FMT_D),
6162: OPC_RECIP2_D = FOP(28, FMT_D),
6163: OPC_RECIP1_D = FOP(29, FMT_D),
6164: OPC_RSQRT1_D = FOP(30, FMT_D),
6165: OPC_RSQRT2_D = FOP(31, FMT_D),
6166: OPC_CVT_S_D = FOP(32, FMT_D),
6167: OPC_CVT_W_D = FOP(36, FMT_D),
6168: OPC_CVT_L_D = FOP(37, FMT_D),
6169: OPC_CMP_F_D = FOP (48, FMT_D),
6170: OPC_CMP_UN_D = FOP (49, FMT_D),
6171: OPC_CMP_EQ_D = FOP (50, FMT_D),
6172: OPC_CMP_UEQ_D = FOP (51, FMT_D),
6173: OPC_CMP_OLT_D = FOP (52, FMT_D),
6174: OPC_CMP_ULT_D = FOP (53, FMT_D),
6175: OPC_CMP_OLE_D = FOP (54, FMT_D),
6176: OPC_CMP_ULE_D = FOP (55, FMT_D),
6177: OPC_CMP_SF_D = FOP (56, FMT_D),
6178: OPC_CMP_NGLE_D = FOP (57, FMT_D),
6179: OPC_CMP_SEQ_D = FOP (58, FMT_D),
6180: OPC_CMP_NGL_D = FOP (59, FMT_D),
6181: OPC_CMP_LT_D = FOP (60, FMT_D),
6182: OPC_CMP_NGE_D = FOP (61, FMT_D),
6183: OPC_CMP_LE_D = FOP (62, FMT_D),
6184: OPC_CMP_NGT_D = FOP (63, FMT_D),
6185:
6186: OPC_CVT_S_W = FOP(32, FMT_W),
6187: OPC_CVT_D_W = FOP(33, FMT_W),
6188: OPC_CVT_S_L = FOP(32, FMT_L),
6189: OPC_CVT_D_L = FOP(33, FMT_L),
6190: OPC_CVT_PS_PW = FOP(38, FMT_W),
6191:
6192: OPC_ADD_PS = FOP(0, FMT_PS),
6193: OPC_SUB_PS = FOP(1, FMT_PS),
6194: OPC_MUL_PS = FOP(2, FMT_PS),
6195: OPC_DIV_PS = FOP(3, FMT_PS),
6196: OPC_ABS_PS = FOP(5, FMT_PS),
6197: OPC_MOV_PS = FOP(6, FMT_PS),
6198: OPC_NEG_PS = FOP(7, FMT_PS),
6199: OPC_MOVCF_PS = FOP(17, FMT_PS),
6200: OPC_MOVZ_PS = FOP(18, FMT_PS),
6201: OPC_MOVN_PS = FOP(19, FMT_PS),
6202: OPC_ADDR_PS = FOP(24, FMT_PS),
6203: OPC_MULR_PS = FOP(26, FMT_PS),
6204: OPC_RECIP2_PS = FOP(28, FMT_PS),
6205: OPC_RECIP1_PS = FOP(29, FMT_PS),
6206: OPC_RSQRT1_PS = FOP(30, FMT_PS),
6207: OPC_RSQRT2_PS = FOP(31, FMT_PS),
6208:
6209: OPC_CVT_S_PU = FOP(32, FMT_PS),
6210: OPC_CVT_PW_PS = FOP(36, FMT_PS),
6211: OPC_CVT_S_PL = FOP(40, FMT_PS),
6212: OPC_PLL_PS = FOP(44, FMT_PS),
6213: OPC_PLU_PS = FOP(45, FMT_PS),
6214: OPC_PUL_PS = FOP(46, FMT_PS),
6215: OPC_PUU_PS = FOP(47, FMT_PS),
6216: OPC_CMP_F_PS = FOP (48, FMT_PS),
6217: OPC_CMP_UN_PS = FOP (49, FMT_PS),
6218: OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6219: OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6220: OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6221: OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6222: OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6223: OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6224: OPC_CMP_SF_PS = FOP (56, FMT_PS),
6225: OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6226: OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6227: OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6228: OPC_CMP_LT_PS = FOP (60, FMT_PS),
6229: OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6230: OPC_CMP_LE_PS = FOP (62, FMT_PS),
6231: OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6232: };
6233:
1.1.1.5 root 6234: static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6235: {
1.1.1.6 root 6236: const char *opn = "cp1 move";
1.1.1.8 root 6237: TCGv t0 = tcg_temp_new();
1.1.1.5 root 6238:
6239: switch (opc) {
6240: case OPC_MFC1:
1.1.1.7 root 6241: {
6242: TCGv_i32 fp0 = tcg_temp_new_i32();
6243:
6244: gen_load_fpr32(fp0, fs);
6245: tcg_gen_ext_i32_tl(t0, fp0);
6246: tcg_temp_free_i32(fp0);
6247: }
6248: gen_store_gpr(t0, rt);
1.1.1.5 root 6249: opn = "mfc1";
6250: break;
6251: case OPC_MTC1:
1.1.1.7 root 6252: gen_load_gpr(t0, rt);
6253: {
6254: TCGv_i32 fp0 = tcg_temp_new_i32();
6255:
6256: tcg_gen_trunc_tl_i32(fp0, t0);
6257: gen_store_fpr32(fp0, fs);
6258: tcg_temp_free_i32(fp0);
6259: }
1.1.1.5 root 6260: opn = "mtc1";
6261: break;
6262: case OPC_CFC1:
1.1.1.7 root 6263: gen_helper_1i(cfc1, t0, fs);
6264: gen_store_gpr(t0, rt);
1.1.1.5 root 6265: opn = "cfc1";
6266: break;
6267: case OPC_CTC1:
1.1.1.7 root 6268: gen_load_gpr(t0, rt);
6269: gen_helper_1i(ctc1, t0, fs);
1.1.1.5 root 6270: opn = "ctc1";
6271: break;
1.1.1.8 root 6272: #if defined(TARGET_MIPS64)
1.1.1.5 root 6273: case OPC_DMFC1:
1.1.1.8 root 6274: gen_load_fpr64(ctx, t0, fs);
1.1.1.7 root 6275: gen_store_gpr(t0, rt);
1.1.1.6 root 6276: opn = "dmfc1";
6277: break;
1.1.1.5 root 6278: case OPC_DMTC1:
1.1.1.7 root 6279: gen_load_gpr(t0, rt);
1.1.1.8 root 6280: gen_store_fpr64(ctx, t0, fs);
1.1.1.6 root 6281: opn = "dmtc1";
6282: break;
1.1.1.8 root 6283: #endif
1.1.1.6 root 6284: case OPC_MFHC1:
1.1.1.7 root 6285: {
6286: TCGv_i32 fp0 = tcg_temp_new_i32();
6287:
6288: gen_load_fpr32h(fp0, fs);
6289: tcg_gen_ext_i32_tl(t0, fp0);
6290: tcg_temp_free_i32(fp0);
6291: }
6292: gen_store_gpr(t0, rt);
1.1.1.6 root 6293: opn = "mfhc1";
6294: break;
6295: case OPC_MTHC1:
1.1.1.7 root 6296: gen_load_gpr(t0, rt);
6297: {
6298: TCGv_i32 fp0 = tcg_temp_new_i32();
6299:
6300: tcg_gen_trunc_tl_i32(fp0, t0);
6301: gen_store_fpr32h(fp0, fs);
6302: tcg_temp_free_i32(fp0);
6303: }
1.1.1.6 root 6304: opn = "mthc1";
6305: break;
1.1.1.5 root 6306: default:
1.1.1.6 root 6307: MIPS_INVAL(opn);
6308: generate_exception (ctx, EXCP_RI);
1.1.1.7 root 6309: goto out;
1.1.1.4 root 6310: }
1.1.1.13 root 6311: (void)opn; /* avoid a compiler warning */
1.1.1.4 root 6312: MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
1.1.1.7 root 6313:
6314: out:
6315: tcg_temp_free(t0);
1.1.1.4 root 6316: }
6317:
1.1.1.6 root 6318: static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6319: {
1.1.1.8 root 6320: int l1;
1.1.1.7 root 6321: TCGCond cond;
1.1.1.8 root 6322: TCGv_i32 t0;
6323:
6324: if (rd == 0) {
6325: /* Treat as NOP. */
6326: return;
6327: }
1.1.1.7 root 6328:
6329: if (tf)
6330: cond = TCG_COND_EQ;
6331: else
6332: cond = TCG_COND_NE;
6333:
1.1.1.8 root 6334: l1 = gen_new_label();
6335: t0 = tcg_temp_new_i32();
6336: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6337: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6338: tcg_temp_free_i32(t0);
6339: if (rs == 0) {
6340: tcg_gen_movi_tl(cpu_gpr[rd], 0);
6341: } else {
6342: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6343: }
1.1.1.7 root 6344: gen_set_label(l1);
6345: }
6346:
6347: static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6348: {
6349: int cond;
1.1.1.8 root 6350: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 6351: int l1 = gen_new_label();
6352:
6353: if (tf)
6354: cond = TCG_COND_EQ;
6355: else
6356: cond = TCG_COND_NE;
6357:
1.1.1.8 root 6358: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6359: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6360: gen_load_fpr32(t0, fs);
6361: gen_store_fpr32(t0, fd);
1.1.1.7 root 6362: gen_set_label(l1);
1.1.1.8 root 6363: tcg_temp_free_i32(t0);
1.1.1.7 root 6364: }
6365:
6366: static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6367: {
6368: int cond;
1.1.1.8 root 6369: TCGv_i32 t0 = tcg_temp_new_i32();
6370: TCGv_i64 fp0;
1.1.1.7 root 6371: int l1 = gen_new_label();
6372:
6373: if (tf)
6374: cond = TCG_COND_EQ;
6375: else
6376: cond = TCG_COND_NE;
6377:
1.1.1.8 root 6378: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6379: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6380: tcg_temp_free_i32(t0);
6381: fp0 = tcg_temp_new_i64();
1.1.1.7 root 6382: gen_load_fpr64(ctx, fp0, fs);
6383: gen_store_fpr64(ctx, fp0, fd);
6384: tcg_temp_free_i64(fp0);
1.1.1.8 root 6385: gen_set_label(l1);
1.1.1.7 root 6386: }
6387:
6388: static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6389: {
6390: int cond;
1.1.1.8 root 6391: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 6392: int l1 = gen_new_label();
6393: int l2 = gen_new_label();
1.1.1.4 root 6394:
1.1.1.7 root 6395: if (tf)
6396: cond = TCG_COND_EQ;
1.1.1.6 root 6397: else
1.1.1.7 root 6398: cond = TCG_COND_NE;
6399:
1.1.1.8 root 6400: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6401: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6402: gen_load_fpr32(t0, fs);
6403: gen_store_fpr32(t0, fd);
1.1.1.7 root 6404: gen_set_label(l1);
6405:
1.1.1.8 root 6406: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
6407: tcg_gen_brcondi_i32(cond, t0, 0, l2);
6408: gen_load_fpr32h(t0, fs);
6409: gen_store_fpr32h(t0, fd);
6410: tcg_temp_free_i32(t0);
1.1.1.7 root 6411: gen_set_label(l2);
1.1.1.6 root 6412: }
6413:
1.1.1.4 root 6414:
1.1.1.12 root 6415: static void gen_farith (DisasContext *ctx, enum fopcode op1,
1.1.1.6 root 6416: int ft, int fs, int fd, int cc)
1.1.1.4 root 6417: {
1.1.1.6 root 6418: const char *opn = "farith";
1.1.1.4 root 6419: const char *condnames[] = {
6420: "c.f",
6421: "c.un",
6422: "c.eq",
6423: "c.ueq",
6424: "c.olt",
6425: "c.ult",
6426: "c.ole",
6427: "c.ule",
6428: "c.sf",
6429: "c.ngle",
6430: "c.seq",
6431: "c.ngl",
6432: "c.lt",
6433: "c.nge",
6434: "c.le",
6435: "c.ngt",
6436: };
1.1.1.6 root 6437: const char *condnames_abs[] = {
6438: "cabs.f",
6439: "cabs.un",
6440: "cabs.eq",
6441: "cabs.ueq",
6442: "cabs.olt",
6443: "cabs.ult",
6444: "cabs.ole",
6445: "cabs.ule",
6446: "cabs.sf",
6447: "cabs.ngle",
6448: "cabs.seq",
6449: "cabs.ngl",
6450: "cabs.lt",
6451: "cabs.nge",
6452: "cabs.le",
6453: "cabs.ngt",
6454: };
6455: enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
1.1.1.5 root 6456: uint32_t func = ctx->opcode & 0x3f;
6457:
1.1.1.12 root 6458: switch (op1) {
6459: case OPC_ADD_S:
1.1.1.7 root 6460: {
6461: TCGv_i32 fp0 = tcg_temp_new_i32();
6462: TCGv_i32 fp1 = tcg_temp_new_i32();
6463:
6464: gen_load_fpr32(fp0, fs);
6465: gen_load_fpr32(fp1, ft);
6466: gen_helper_float_add_s(fp0, fp0, fp1);
6467: tcg_temp_free_i32(fp1);
6468: gen_store_fpr32(fp0, fd);
6469: tcg_temp_free_i32(fp0);
6470: }
1.1.1.6 root 6471: opn = "add.s";
6472: optype = BINOP;
6473: break;
1.1.1.12 root 6474: case OPC_SUB_S:
1.1.1.7 root 6475: {
6476: TCGv_i32 fp0 = tcg_temp_new_i32();
6477: TCGv_i32 fp1 = tcg_temp_new_i32();
6478:
6479: gen_load_fpr32(fp0, fs);
6480: gen_load_fpr32(fp1, ft);
6481: gen_helper_float_sub_s(fp0, fp0, fp1);
6482: tcg_temp_free_i32(fp1);
6483: gen_store_fpr32(fp0, fd);
6484: tcg_temp_free_i32(fp0);
6485: }
1.1.1.6 root 6486: opn = "sub.s";
6487: optype = BINOP;
6488: break;
1.1.1.12 root 6489: case OPC_MUL_S:
1.1.1.7 root 6490: {
6491: TCGv_i32 fp0 = tcg_temp_new_i32();
6492: TCGv_i32 fp1 = tcg_temp_new_i32();
6493:
6494: gen_load_fpr32(fp0, fs);
6495: gen_load_fpr32(fp1, ft);
6496: gen_helper_float_mul_s(fp0, fp0, fp1);
6497: tcg_temp_free_i32(fp1);
6498: gen_store_fpr32(fp0, fd);
6499: tcg_temp_free_i32(fp0);
6500: }
1.1.1.6 root 6501: opn = "mul.s";
6502: optype = BINOP;
6503: break;
1.1.1.12 root 6504: case OPC_DIV_S:
1.1.1.7 root 6505: {
6506: TCGv_i32 fp0 = tcg_temp_new_i32();
6507: TCGv_i32 fp1 = tcg_temp_new_i32();
6508:
6509: gen_load_fpr32(fp0, fs);
6510: gen_load_fpr32(fp1, ft);
6511: gen_helper_float_div_s(fp0, fp0, fp1);
6512: tcg_temp_free_i32(fp1);
6513: gen_store_fpr32(fp0, fd);
6514: tcg_temp_free_i32(fp0);
6515: }
1.1.1.6 root 6516: opn = "div.s";
6517: optype = BINOP;
6518: break;
1.1.1.12 root 6519: case OPC_SQRT_S:
1.1.1.7 root 6520: {
6521: TCGv_i32 fp0 = tcg_temp_new_i32();
6522:
6523: gen_load_fpr32(fp0, fs);
6524: gen_helper_float_sqrt_s(fp0, fp0);
6525: gen_store_fpr32(fp0, fd);
6526: tcg_temp_free_i32(fp0);
6527: }
1.1.1.6 root 6528: opn = "sqrt.s";
6529: break;
1.1.1.12 root 6530: case OPC_ABS_S:
1.1.1.7 root 6531: {
6532: TCGv_i32 fp0 = tcg_temp_new_i32();
6533:
6534: gen_load_fpr32(fp0, fs);
6535: gen_helper_float_abs_s(fp0, fp0);
6536: gen_store_fpr32(fp0, fd);
6537: tcg_temp_free_i32(fp0);
6538: }
1.1.1.6 root 6539: opn = "abs.s";
6540: break;
1.1.1.12 root 6541: case OPC_MOV_S:
1.1.1.7 root 6542: {
6543: TCGv_i32 fp0 = tcg_temp_new_i32();
6544:
6545: gen_load_fpr32(fp0, fs);
6546: gen_store_fpr32(fp0, fd);
6547: tcg_temp_free_i32(fp0);
6548: }
1.1.1.6 root 6549: opn = "mov.s";
6550: break;
1.1.1.12 root 6551: case OPC_NEG_S:
1.1.1.7 root 6552: {
6553: TCGv_i32 fp0 = tcg_temp_new_i32();
6554:
6555: gen_load_fpr32(fp0, fs);
6556: gen_helper_float_chs_s(fp0, fp0);
6557: gen_store_fpr32(fp0, fd);
6558: tcg_temp_free_i32(fp0);
6559: }
1.1.1.6 root 6560: opn = "neg.s";
6561: break;
1.1.1.12 root 6562: case OPC_ROUND_L_S:
1.1.1.6 root 6563: check_cp1_64bitmode(ctx);
1.1.1.7 root 6564: {
6565: TCGv_i32 fp32 = tcg_temp_new_i32();
6566: TCGv_i64 fp64 = tcg_temp_new_i64();
6567:
6568: gen_load_fpr32(fp32, fs);
6569: gen_helper_float_roundl_s(fp64, fp32);
6570: tcg_temp_free_i32(fp32);
6571: gen_store_fpr64(ctx, fp64, fd);
6572: tcg_temp_free_i64(fp64);
6573: }
1.1.1.6 root 6574: opn = "round.l.s";
6575: break;
1.1.1.12 root 6576: case OPC_TRUNC_L_S:
1.1.1.6 root 6577: check_cp1_64bitmode(ctx);
1.1.1.7 root 6578: {
6579: TCGv_i32 fp32 = tcg_temp_new_i32();
6580: TCGv_i64 fp64 = tcg_temp_new_i64();
6581:
6582: gen_load_fpr32(fp32, fs);
6583: gen_helper_float_truncl_s(fp64, fp32);
6584: tcg_temp_free_i32(fp32);
6585: gen_store_fpr64(ctx, fp64, fd);
6586: tcg_temp_free_i64(fp64);
6587: }
1.1.1.6 root 6588: opn = "trunc.l.s";
6589: break;
1.1.1.12 root 6590: case OPC_CEIL_L_S:
1.1.1.6 root 6591: check_cp1_64bitmode(ctx);
1.1.1.7 root 6592: {
6593: TCGv_i32 fp32 = tcg_temp_new_i32();
6594: TCGv_i64 fp64 = tcg_temp_new_i64();
6595:
6596: gen_load_fpr32(fp32, fs);
6597: gen_helper_float_ceill_s(fp64, fp32);
6598: tcg_temp_free_i32(fp32);
6599: gen_store_fpr64(ctx, fp64, fd);
6600: tcg_temp_free_i64(fp64);
6601: }
1.1.1.6 root 6602: opn = "ceil.l.s";
6603: break;
1.1.1.12 root 6604: case OPC_FLOOR_L_S:
1.1.1.6 root 6605: check_cp1_64bitmode(ctx);
1.1.1.7 root 6606: {
6607: TCGv_i32 fp32 = tcg_temp_new_i32();
6608: TCGv_i64 fp64 = tcg_temp_new_i64();
6609:
6610: gen_load_fpr32(fp32, fs);
6611: gen_helper_float_floorl_s(fp64, fp32);
6612: tcg_temp_free_i32(fp32);
6613: gen_store_fpr64(ctx, fp64, fd);
6614: tcg_temp_free_i64(fp64);
6615: }
1.1.1.6 root 6616: opn = "floor.l.s";
6617: break;
1.1.1.12 root 6618: case OPC_ROUND_W_S:
1.1.1.7 root 6619: {
6620: TCGv_i32 fp0 = tcg_temp_new_i32();
6621:
6622: gen_load_fpr32(fp0, fs);
6623: gen_helper_float_roundw_s(fp0, fp0);
6624: gen_store_fpr32(fp0, fd);
6625: tcg_temp_free_i32(fp0);
6626: }
1.1.1.6 root 6627: opn = "round.w.s";
6628: break;
1.1.1.12 root 6629: case OPC_TRUNC_W_S:
1.1.1.7 root 6630: {
6631: TCGv_i32 fp0 = tcg_temp_new_i32();
6632:
6633: gen_load_fpr32(fp0, fs);
6634: gen_helper_float_truncw_s(fp0, fp0);
6635: gen_store_fpr32(fp0, fd);
6636: tcg_temp_free_i32(fp0);
6637: }
1.1.1.6 root 6638: opn = "trunc.w.s";
6639: break;
1.1.1.12 root 6640: case OPC_CEIL_W_S:
1.1.1.7 root 6641: {
6642: TCGv_i32 fp0 = tcg_temp_new_i32();
6643:
6644: gen_load_fpr32(fp0, fs);
6645: gen_helper_float_ceilw_s(fp0, fp0);
6646: gen_store_fpr32(fp0, fd);
6647: tcg_temp_free_i32(fp0);
6648: }
1.1.1.6 root 6649: opn = "ceil.w.s";
6650: break;
1.1.1.12 root 6651: case OPC_FLOOR_W_S:
1.1.1.7 root 6652: {
6653: TCGv_i32 fp0 = tcg_temp_new_i32();
6654:
6655: gen_load_fpr32(fp0, fs);
6656: gen_helper_float_floorw_s(fp0, fp0);
6657: gen_store_fpr32(fp0, fd);
6658: tcg_temp_free_i32(fp0);
6659: }
1.1.1.6 root 6660: opn = "floor.w.s";
6661: break;
1.1.1.12 root 6662: case OPC_MOVCF_S:
1.1.1.7 root 6663: gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 6664: opn = "movcf.s";
6665: break;
1.1.1.12 root 6666: case OPC_MOVZ_S:
1.1.1.7 root 6667: {
6668: int l1 = gen_new_label();
1.1.1.8 root 6669: TCGv_i32 fp0;
1.1.1.7 root 6670:
1.1.1.8 root 6671: if (ft != 0) {
6672: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6673: }
6674: fp0 = tcg_temp_new_i32();
1.1.1.7 root 6675: gen_load_fpr32(fp0, fs);
6676: gen_store_fpr32(fp0, fd);
6677: tcg_temp_free_i32(fp0);
6678: gen_set_label(l1);
6679: }
1.1.1.6 root 6680: opn = "movz.s";
6681: break;
1.1.1.12 root 6682: case OPC_MOVN_S:
1.1.1.7 root 6683: {
6684: int l1 = gen_new_label();
1.1.1.8 root 6685: TCGv_i32 fp0;
1.1.1.7 root 6686:
1.1.1.8 root 6687: if (ft != 0) {
6688: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6689: fp0 = tcg_temp_new_i32();
6690: gen_load_fpr32(fp0, fs);
6691: gen_store_fpr32(fp0, fd);
6692: tcg_temp_free_i32(fp0);
6693: gen_set_label(l1);
6694: }
1.1.1.7 root 6695: }
1.1.1.6 root 6696: opn = "movn.s";
6697: break;
1.1.1.12 root 6698: case OPC_RECIP_S:
1.1.1.6 root 6699: check_cop1x(ctx);
1.1.1.7 root 6700: {
6701: TCGv_i32 fp0 = tcg_temp_new_i32();
6702:
6703: gen_load_fpr32(fp0, fs);
6704: gen_helper_float_recip_s(fp0, fp0);
6705: gen_store_fpr32(fp0, fd);
6706: tcg_temp_free_i32(fp0);
6707: }
1.1.1.6 root 6708: opn = "recip.s";
6709: break;
1.1.1.12 root 6710: case OPC_RSQRT_S:
1.1.1.6 root 6711: check_cop1x(ctx);
1.1.1.7 root 6712: {
6713: TCGv_i32 fp0 = tcg_temp_new_i32();
6714:
6715: gen_load_fpr32(fp0, fs);
6716: gen_helper_float_rsqrt_s(fp0, fp0);
6717: gen_store_fpr32(fp0, fd);
6718: tcg_temp_free_i32(fp0);
6719: }
1.1.1.6 root 6720: opn = "rsqrt.s";
6721: break;
1.1.1.12 root 6722: case OPC_RECIP2_S:
1.1.1.6 root 6723: check_cp1_64bitmode(ctx);
1.1.1.7 root 6724: {
6725: TCGv_i32 fp0 = tcg_temp_new_i32();
6726: TCGv_i32 fp1 = tcg_temp_new_i32();
6727:
6728: gen_load_fpr32(fp0, fs);
6729: gen_load_fpr32(fp1, fd);
6730: gen_helper_float_recip2_s(fp0, fp0, fp1);
6731: tcg_temp_free_i32(fp1);
6732: gen_store_fpr32(fp0, fd);
6733: tcg_temp_free_i32(fp0);
6734: }
1.1.1.6 root 6735: opn = "recip2.s";
6736: break;
1.1.1.12 root 6737: case OPC_RECIP1_S:
1.1.1.6 root 6738: check_cp1_64bitmode(ctx);
1.1.1.7 root 6739: {
6740: TCGv_i32 fp0 = tcg_temp_new_i32();
6741:
6742: gen_load_fpr32(fp0, fs);
6743: gen_helper_float_recip1_s(fp0, fp0);
6744: gen_store_fpr32(fp0, fd);
6745: tcg_temp_free_i32(fp0);
6746: }
1.1.1.6 root 6747: opn = "recip1.s";
6748: break;
1.1.1.12 root 6749: case OPC_RSQRT1_S:
1.1.1.6 root 6750: check_cp1_64bitmode(ctx);
1.1.1.7 root 6751: {
6752: TCGv_i32 fp0 = tcg_temp_new_i32();
6753:
6754: gen_load_fpr32(fp0, fs);
6755: gen_helper_float_rsqrt1_s(fp0, fp0);
6756: gen_store_fpr32(fp0, fd);
6757: tcg_temp_free_i32(fp0);
6758: }
1.1.1.6 root 6759: opn = "rsqrt1.s";
6760: break;
1.1.1.12 root 6761: case OPC_RSQRT2_S:
1.1.1.6 root 6762: check_cp1_64bitmode(ctx);
1.1.1.7 root 6763: {
6764: TCGv_i32 fp0 = tcg_temp_new_i32();
6765: TCGv_i32 fp1 = tcg_temp_new_i32();
6766:
6767: gen_load_fpr32(fp0, fs);
6768: gen_load_fpr32(fp1, ft);
6769: gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6770: tcg_temp_free_i32(fp1);
6771: gen_store_fpr32(fp0, fd);
6772: tcg_temp_free_i32(fp0);
6773: }
1.1.1.6 root 6774: opn = "rsqrt2.s";
6775: break;
1.1.1.12 root 6776: case OPC_CVT_D_S:
1.1.1.6 root 6777: check_cp1_registers(ctx, fd);
1.1.1.7 root 6778: {
6779: TCGv_i32 fp32 = tcg_temp_new_i32();
6780: TCGv_i64 fp64 = tcg_temp_new_i64();
6781:
6782: gen_load_fpr32(fp32, fs);
6783: gen_helper_float_cvtd_s(fp64, fp32);
6784: tcg_temp_free_i32(fp32);
6785: gen_store_fpr64(ctx, fp64, fd);
6786: tcg_temp_free_i64(fp64);
6787: }
1.1.1.6 root 6788: opn = "cvt.d.s";
6789: break;
1.1.1.12 root 6790: case OPC_CVT_W_S:
1.1.1.7 root 6791: {
6792: TCGv_i32 fp0 = tcg_temp_new_i32();
6793:
6794: gen_load_fpr32(fp0, fs);
6795: gen_helper_float_cvtw_s(fp0, fp0);
6796: gen_store_fpr32(fp0, fd);
6797: tcg_temp_free_i32(fp0);
6798: }
1.1.1.6 root 6799: opn = "cvt.w.s";
6800: break;
1.1.1.12 root 6801: case OPC_CVT_L_S:
1.1.1.6 root 6802: check_cp1_64bitmode(ctx);
1.1.1.7 root 6803: {
6804: TCGv_i32 fp32 = tcg_temp_new_i32();
6805: TCGv_i64 fp64 = tcg_temp_new_i64();
6806:
6807: gen_load_fpr32(fp32, fs);
6808: gen_helper_float_cvtl_s(fp64, fp32);
6809: tcg_temp_free_i32(fp32);
6810: gen_store_fpr64(ctx, fp64, fd);
6811: tcg_temp_free_i64(fp64);
6812: }
1.1.1.6 root 6813: opn = "cvt.l.s";
6814: break;
1.1.1.12 root 6815: case OPC_CVT_PS_S:
1.1.1.6 root 6816: check_cp1_64bitmode(ctx);
1.1.1.7 root 6817: {
6818: TCGv_i64 fp64 = tcg_temp_new_i64();
6819: TCGv_i32 fp32_0 = tcg_temp_new_i32();
6820: TCGv_i32 fp32_1 = tcg_temp_new_i32();
6821:
6822: gen_load_fpr32(fp32_0, fs);
6823: gen_load_fpr32(fp32_1, ft);
6824: tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6825: tcg_temp_free_i32(fp32_1);
6826: tcg_temp_free_i32(fp32_0);
6827: gen_store_fpr64(ctx, fp64, fd);
6828: tcg_temp_free_i64(fp64);
6829: }
1.1.1.6 root 6830: opn = "cvt.ps.s";
6831: break;
1.1.1.12 root 6832: case OPC_CMP_F_S:
6833: case OPC_CMP_UN_S:
6834: case OPC_CMP_EQ_S:
6835: case OPC_CMP_UEQ_S:
6836: case OPC_CMP_OLT_S:
6837: case OPC_CMP_ULT_S:
6838: case OPC_CMP_OLE_S:
6839: case OPC_CMP_ULE_S:
6840: case OPC_CMP_SF_S:
6841: case OPC_CMP_NGLE_S:
6842: case OPC_CMP_SEQ_S:
6843: case OPC_CMP_NGL_S:
6844: case OPC_CMP_LT_S:
6845: case OPC_CMP_NGE_S:
6846: case OPC_CMP_LE_S:
6847: case OPC_CMP_NGT_S:
6848: if (ctx->opcode & (1 << 6)) {
6849: gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6850: opn = condnames_abs[func-48];
6851: } else {
6852: gen_cmp_s(ctx, func-48, ft, fs, cc);
6853: opn = condnames[func-48];
1.1.1.6 root 6854: }
6855: break;
1.1.1.12 root 6856: case OPC_ADD_D:
1.1.1.6 root 6857: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6858: {
6859: TCGv_i64 fp0 = tcg_temp_new_i64();
6860: TCGv_i64 fp1 = tcg_temp_new_i64();
6861:
6862: gen_load_fpr64(ctx, fp0, fs);
6863: gen_load_fpr64(ctx, fp1, ft);
6864: gen_helper_float_add_d(fp0, fp0, fp1);
6865: tcg_temp_free_i64(fp1);
6866: gen_store_fpr64(ctx, fp0, fd);
6867: tcg_temp_free_i64(fp0);
6868: }
1.1.1.4 root 6869: opn = "add.d";
1.1.1.6 root 6870: optype = BINOP;
1.1.1.4 root 6871: break;
1.1.1.12 root 6872: case OPC_SUB_D:
1.1.1.6 root 6873: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6874: {
6875: TCGv_i64 fp0 = tcg_temp_new_i64();
6876: TCGv_i64 fp1 = tcg_temp_new_i64();
6877:
6878: gen_load_fpr64(ctx, fp0, fs);
6879: gen_load_fpr64(ctx, fp1, ft);
6880: gen_helper_float_sub_d(fp0, fp0, fp1);
6881: tcg_temp_free_i64(fp1);
6882: gen_store_fpr64(ctx, fp0, fd);
6883: tcg_temp_free_i64(fp0);
6884: }
1.1.1.4 root 6885: opn = "sub.d";
1.1.1.6 root 6886: optype = BINOP;
1.1.1.4 root 6887: break;
1.1.1.12 root 6888: case OPC_MUL_D:
1.1.1.6 root 6889: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6890: {
6891: TCGv_i64 fp0 = tcg_temp_new_i64();
6892: TCGv_i64 fp1 = tcg_temp_new_i64();
6893:
6894: gen_load_fpr64(ctx, fp0, fs);
6895: gen_load_fpr64(ctx, fp1, ft);
6896: gen_helper_float_mul_d(fp0, fp0, fp1);
6897: tcg_temp_free_i64(fp1);
6898: gen_store_fpr64(ctx, fp0, fd);
6899: tcg_temp_free_i64(fp0);
6900: }
1.1.1.4 root 6901: opn = "mul.d";
1.1.1.6 root 6902: optype = BINOP;
1.1.1.4 root 6903: break;
1.1.1.12 root 6904: case OPC_DIV_D:
1.1.1.6 root 6905: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6906: {
6907: TCGv_i64 fp0 = tcg_temp_new_i64();
6908: TCGv_i64 fp1 = tcg_temp_new_i64();
6909:
6910: gen_load_fpr64(ctx, fp0, fs);
6911: gen_load_fpr64(ctx, fp1, ft);
6912: gen_helper_float_div_d(fp0, fp0, fp1);
6913: tcg_temp_free_i64(fp1);
6914: gen_store_fpr64(ctx, fp0, fd);
6915: tcg_temp_free_i64(fp0);
6916: }
1.1.1.4 root 6917: opn = "div.d";
1.1.1.6 root 6918: optype = BINOP;
1.1.1.4 root 6919: break;
1.1.1.12 root 6920: case OPC_SQRT_D:
1.1.1.6 root 6921: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6922: {
6923: TCGv_i64 fp0 = tcg_temp_new_i64();
6924:
6925: gen_load_fpr64(ctx, fp0, fs);
6926: gen_helper_float_sqrt_d(fp0, fp0);
6927: gen_store_fpr64(ctx, fp0, fd);
6928: tcg_temp_free_i64(fp0);
6929: }
1.1.1.4 root 6930: opn = "sqrt.d";
6931: break;
1.1.1.12 root 6932: case OPC_ABS_D:
1.1.1.6 root 6933: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6934: {
6935: TCGv_i64 fp0 = tcg_temp_new_i64();
6936:
6937: gen_load_fpr64(ctx, fp0, fs);
6938: gen_helper_float_abs_d(fp0, fp0);
6939: gen_store_fpr64(ctx, fp0, fd);
6940: tcg_temp_free_i64(fp0);
6941: }
1.1.1.4 root 6942: opn = "abs.d";
6943: break;
1.1.1.12 root 6944: case OPC_MOV_D:
1.1.1.6 root 6945: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6946: {
6947: TCGv_i64 fp0 = tcg_temp_new_i64();
6948:
6949: gen_load_fpr64(ctx, fp0, fs);
6950: gen_store_fpr64(ctx, fp0, fd);
6951: tcg_temp_free_i64(fp0);
6952: }
1.1.1.4 root 6953: opn = "mov.d";
6954: break;
1.1.1.12 root 6955: case OPC_NEG_D:
1.1.1.6 root 6956: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6957: {
6958: TCGv_i64 fp0 = tcg_temp_new_i64();
6959:
6960: gen_load_fpr64(ctx, fp0, fs);
6961: gen_helper_float_chs_d(fp0, fp0);
6962: gen_store_fpr64(ctx, fp0, fd);
6963: tcg_temp_free_i64(fp0);
6964: }
1.1.1.4 root 6965: opn = "neg.d";
6966: break;
1.1.1.12 root 6967: case OPC_ROUND_L_D:
1.1.1.6 root 6968: check_cp1_64bitmode(ctx);
1.1.1.7 root 6969: {
6970: TCGv_i64 fp0 = tcg_temp_new_i64();
6971:
6972: gen_load_fpr64(ctx, fp0, fs);
6973: gen_helper_float_roundl_d(fp0, fp0);
6974: gen_store_fpr64(ctx, fp0, fd);
6975: tcg_temp_free_i64(fp0);
6976: }
1.1.1.6 root 6977: opn = "round.l.d";
6978: break;
1.1.1.12 root 6979: case OPC_TRUNC_L_D:
1.1.1.6 root 6980: check_cp1_64bitmode(ctx);
1.1.1.7 root 6981: {
6982: TCGv_i64 fp0 = tcg_temp_new_i64();
6983:
6984: gen_load_fpr64(ctx, fp0, fs);
6985: gen_helper_float_truncl_d(fp0, fp0);
6986: gen_store_fpr64(ctx, fp0, fd);
6987: tcg_temp_free_i64(fp0);
6988: }
1.1.1.6 root 6989: opn = "trunc.l.d";
6990: break;
1.1.1.12 root 6991: case OPC_CEIL_L_D:
1.1.1.6 root 6992: check_cp1_64bitmode(ctx);
1.1.1.7 root 6993: {
6994: TCGv_i64 fp0 = tcg_temp_new_i64();
6995:
6996: gen_load_fpr64(ctx, fp0, fs);
6997: gen_helper_float_ceill_d(fp0, fp0);
6998: gen_store_fpr64(ctx, fp0, fd);
6999: tcg_temp_free_i64(fp0);
7000: }
1.1.1.6 root 7001: opn = "ceil.l.d";
7002: break;
1.1.1.12 root 7003: case OPC_FLOOR_L_D:
1.1.1.6 root 7004: check_cp1_64bitmode(ctx);
1.1.1.7 root 7005: {
7006: TCGv_i64 fp0 = tcg_temp_new_i64();
7007:
7008: gen_load_fpr64(ctx, fp0, fs);
7009: gen_helper_float_floorl_d(fp0, fp0);
7010: gen_store_fpr64(ctx, fp0, fd);
7011: tcg_temp_free_i64(fp0);
7012: }
1.1.1.6 root 7013: opn = "floor.l.d";
7014: break;
1.1.1.12 root 7015: case OPC_ROUND_W_D:
1.1.1.6 root 7016: check_cp1_registers(ctx, fs);
1.1.1.7 root 7017: {
7018: TCGv_i32 fp32 = tcg_temp_new_i32();
7019: TCGv_i64 fp64 = tcg_temp_new_i64();
7020:
7021: gen_load_fpr64(ctx, fp64, fs);
7022: gen_helper_float_roundw_d(fp32, fp64);
7023: tcg_temp_free_i64(fp64);
7024: gen_store_fpr32(fp32, fd);
7025: tcg_temp_free_i32(fp32);
7026: }
1.1.1.4 root 7027: opn = "round.w.d";
7028: break;
1.1.1.12 root 7029: case OPC_TRUNC_W_D:
1.1.1.6 root 7030: check_cp1_registers(ctx, fs);
1.1.1.7 root 7031: {
7032: TCGv_i32 fp32 = tcg_temp_new_i32();
7033: TCGv_i64 fp64 = tcg_temp_new_i64();
7034:
7035: gen_load_fpr64(ctx, fp64, fs);
7036: gen_helper_float_truncw_d(fp32, fp64);
7037: tcg_temp_free_i64(fp64);
7038: gen_store_fpr32(fp32, fd);
7039: tcg_temp_free_i32(fp32);
7040: }
1.1.1.4 root 7041: opn = "trunc.w.d";
7042: break;
1.1.1.12 root 7043: case OPC_CEIL_W_D:
1.1.1.6 root 7044: check_cp1_registers(ctx, fs);
1.1.1.7 root 7045: {
7046: TCGv_i32 fp32 = tcg_temp_new_i32();
7047: TCGv_i64 fp64 = tcg_temp_new_i64();
7048:
7049: gen_load_fpr64(ctx, fp64, fs);
7050: gen_helper_float_ceilw_d(fp32, fp64);
7051: tcg_temp_free_i64(fp64);
7052: gen_store_fpr32(fp32, fd);
7053: tcg_temp_free_i32(fp32);
7054: }
1.1.1.4 root 7055: opn = "ceil.w.d";
7056: break;
1.1.1.12 root 7057: case OPC_FLOOR_W_D:
1.1.1.6 root 7058: check_cp1_registers(ctx, fs);
1.1.1.7 root 7059: {
7060: TCGv_i32 fp32 = tcg_temp_new_i32();
7061: TCGv_i64 fp64 = tcg_temp_new_i64();
7062:
7063: gen_load_fpr64(ctx, fp64, fs);
7064: gen_helper_float_floorw_d(fp32, fp64);
7065: tcg_temp_free_i64(fp64);
7066: gen_store_fpr32(fp32, fd);
7067: tcg_temp_free_i32(fp32);
7068: }
1.1.1.5 root 7069: opn = "floor.w.d";
7070: break;
1.1.1.12 root 7071: case OPC_MOVCF_D:
1.1.1.7 root 7072: gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 7073: opn = "movcf.d";
1.1.1.4 root 7074: break;
1.1.1.12 root 7075: case OPC_MOVZ_D:
1.1.1.7 root 7076: {
7077: int l1 = gen_new_label();
1.1.1.8 root 7078: TCGv_i64 fp0;
1.1.1.7 root 7079:
1.1.1.8 root 7080: if (ft != 0) {
7081: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7082: }
7083: fp0 = tcg_temp_new_i64();
1.1.1.7 root 7084: gen_load_fpr64(ctx, fp0, fs);
7085: gen_store_fpr64(ctx, fp0, fd);
7086: tcg_temp_free_i64(fp0);
7087: gen_set_label(l1);
7088: }
1.1.1.6 root 7089: opn = "movz.d";
7090: break;
1.1.1.12 root 7091: case OPC_MOVN_D:
1.1.1.7 root 7092: {
7093: int l1 = gen_new_label();
1.1.1.8 root 7094: TCGv_i64 fp0;
1.1.1.7 root 7095:
1.1.1.8 root 7096: if (ft != 0) {
7097: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7098: fp0 = tcg_temp_new_i64();
7099: gen_load_fpr64(ctx, fp0, fs);
7100: gen_store_fpr64(ctx, fp0, fd);
7101: tcg_temp_free_i64(fp0);
7102: gen_set_label(l1);
7103: }
1.1.1.7 root 7104: }
1.1.1.6 root 7105: opn = "movn.d";
7106: break;
1.1.1.12 root 7107: case OPC_RECIP_D:
1.1.1.6 root 7108: check_cp1_64bitmode(ctx);
1.1.1.7 root 7109: {
7110: TCGv_i64 fp0 = tcg_temp_new_i64();
7111:
7112: gen_load_fpr64(ctx, fp0, fs);
7113: gen_helper_float_recip_d(fp0, fp0);
7114: gen_store_fpr64(ctx, fp0, fd);
7115: tcg_temp_free_i64(fp0);
7116: }
1.1.1.6 root 7117: opn = "recip.d";
7118: break;
1.1.1.12 root 7119: case OPC_RSQRT_D:
1.1.1.6 root 7120: check_cp1_64bitmode(ctx);
1.1.1.7 root 7121: {
7122: TCGv_i64 fp0 = tcg_temp_new_i64();
7123:
7124: gen_load_fpr64(ctx, fp0, fs);
7125: gen_helper_float_rsqrt_d(fp0, fp0);
7126: gen_store_fpr64(ctx, fp0, fd);
7127: tcg_temp_free_i64(fp0);
7128: }
1.1.1.6 root 7129: opn = "rsqrt.d";
7130: break;
1.1.1.12 root 7131: case OPC_RECIP2_D:
1.1.1.6 root 7132: check_cp1_64bitmode(ctx);
1.1.1.7 root 7133: {
7134: TCGv_i64 fp0 = tcg_temp_new_i64();
7135: TCGv_i64 fp1 = tcg_temp_new_i64();
7136:
7137: gen_load_fpr64(ctx, fp0, fs);
7138: gen_load_fpr64(ctx, fp1, ft);
7139: gen_helper_float_recip2_d(fp0, fp0, fp1);
7140: tcg_temp_free_i64(fp1);
7141: gen_store_fpr64(ctx, fp0, fd);
7142: tcg_temp_free_i64(fp0);
7143: }
1.1.1.6 root 7144: opn = "recip2.d";
7145: break;
1.1.1.12 root 7146: case OPC_RECIP1_D:
1.1.1.6 root 7147: check_cp1_64bitmode(ctx);
1.1.1.7 root 7148: {
7149: TCGv_i64 fp0 = tcg_temp_new_i64();
7150:
7151: gen_load_fpr64(ctx, fp0, fs);
7152: gen_helper_float_recip1_d(fp0, fp0);
7153: gen_store_fpr64(ctx, fp0, fd);
7154: tcg_temp_free_i64(fp0);
7155: }
1.1.1.6 root 7156: opn = "recip1.d";
7157: break;
1.1.1.12 root 7158: case OPC_RSQRT1_D:
1.1.1.6 root 7159: check_cp1_64bitmode(ctx);
1.1.1.7 root 7160: {
7161: TCGv_i64 fp0 = tcg_temp_new_i64();
7162:
7163: gen_load_fpr64(ctx, fp0, fs);
7164: gen_helper_float_rsqrt1_d(fp0, fp0);
7165: gen_store_fpr64(ctx, fp0, fd);
7166: tcg_temp_free_i64(fp0);
7167: }
1.1.1.6 root 7168: opn = "rsqrt1.d";
7169: break;
1.1.1.12 root 7170: case OPC_RSQRT2_D:
1.1.1.6 root 7171: check_cp1_64bitmode(ctx);
1.1.1.7 root 7172: {
7173: TCGv_i64 fp0 = tcg_temp_new_i64();
7174: TCGv_i64 fp1 = tcg_temp_new_i64();
7175:
7176: gen_load_fpr64(ctx, fp0, fs);
7177: gen_load_fpr64(ctx, fp1, ft);
7178: gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
7179: tcg_temp_free_i64(fp1);
7180: gen_store_fpr64(ctx, fp0, fd);
7181: tcg_temp_free_i64(fp0);
7182: }
1.1.1.6 root 7183: opn = "rsqrt2.d";
1.1.1.4 root 7184: break;
1.1.1.12 root 7185: case OPC_CMP_F_D:
7186: case OPC_CMP_UN_D:
7187: case OPC_CMP_EQ_D:
7188: case OPC_CMP_UEQ_D:
7189: case OPC_CMP_OLT_D:
7190: case OPC_CMP_ULT_D:
7191: case OPC_CMP_OLE_D:
7192: case OPC_CMP_ULE_D:
7193: case OPC_CMP_SF_D:
7194: case OPC_CMP_NGLE_D:
7195: case OPC_CMP_SEQ_D:
7196: case OPC_CMP_NGL_D:
7197: case OPC_CMP_LT_D:
7198: case OPC_CMP_NGE_D:
7199: case OPC_CMP_LE_D:
7200: case OPC_CMP_NGT_D:
7201: if (ctx->opcode & (1 << 6)) {
7202: gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7203: opn = condnames_abs[func-48];
7204: } else {
7205: gen_cmp_d(ctx, func-48, ft, fs, cc);
7206: opn = condnames[func-48];
1.1.1.6 root 7207: }
7208: break;
1.1.1.12 root 7209: case OPC_CVT_S_D:
1.1.1.6 root 7210: check_cp1_registers(ctx, fs);
1.1.1.7 root 7211: {
7212: TCGv_i32 fp32 = tcg_temp_new_i32();
7213: TCGv_i64 fp64 = tcg_temp_new_i64();
7214:
7215: gen_load_fpr64(ctx, fp64, fs);
7216: gen_helper_float_cvts_d(fp32, fp64);
7217: tcg_temp_free_i64(fp64);
7218: gen_store_fpr32(fp32, fd);
7219: tcg_temp_free_i32(fp32);
7220: }
1.1.1.6 root 7221: opn = "cvt.s.d";
7222: break;
1.1.1.12 root 7223: case OPC_CVT_W_D:
1.1.1.6 root 7224: check_cp1_registers(ctx, fs);
1.1.1.7 root 7225: {
7226: TCGv_i32 fp32 = tcg_temp_new_i32();
7227: TCGv_i64 fp64 = tcg_temp_new_i64();
7228:
7229: gen_load_fpr64(ctx, fp64, fs);
7230: gen_helper_float_cvtw_d(fp32, fp64);
7231: tcg_temp_free_i64(fp64);
7232: gen_store_fpr32(fp32, fd);
7233: tcg_temp_free_i32(fp32);
7234: }
1.1.1.6 root 7235: opn = "cvt.w.d";
7236: break;
1.1.1.12 root 7237: case OPC_CVT_L_D:
1.1.1.6 root 7238: check_cp1_64bitmode(ctx);
1.1.1.7 root 7239: {
7240: TCGv_i64 fp0 = tcg_temp_new_i64();
7241:
7242: gen_load_fpr64(ctx, fp0, fs);
7243: gen_helper_float_cvtl_d(fp0, fp0);
7244: gen_store_fpr64(ctx, fp0, fd);
7245: tcg_temp_free_i64(fp0);
7246: }
1.1.1.6 root 7247: opn = "cvt.l.d";
7248: break;
1.1.1.12 root 7249: case OPC_CVT_S_W:
1.1.1.7 root 7250: {
7251: TCGv_i32 fp0 = tcg_temp_new_i32();
7252:
7253: gen_load_fpr32(fp0, fs);
7254: gen_helper_float_cvts_w(fp0, fp0);
7255: gen_store_fpr32(fp0, fd);
7256: tcg_temp_free_i32(fp0);
7257: }
1.1.1.6 root 7258: opn = "cvt.s.w";
7259: break;
1.1.1.12 root 7260: case OPC_CVT_D_W:
1.1.1.6 root 7261: check_cp1_registers(ctx, fd);
1.1.1.7 root 7262: {
7263: TCGv_i32 fp32 = tcg_temp_new_i32();
7264: TCGv_i64 fp64 = tcg_temp_new_i64();
7265:
7266: gen_load_fpr32(fp32, fs);
7267: gen_helper_float_cvtd_w(fp64, fp32);
7268: tcg_temp_free_i32(fp32);
7269: gen_store_fpr64(ctx, fp64, fd);
7270: tcg_temp_free_i64(fp64);
7271: }
1.1.1.6 root 7272: opn = "cvt.d.w";
7273: break;
1.1.1.12 root 7274: case OPC_CVT_S_L:
1.1.1.6 root 7275: check_cp1_64bitmode(ctx);
1.1.1.7 root 7276: {
7277: TCGv_i32 fp32 = tcg_temp_new_i32();
7278: TCGv_i64 fp64 = tcg_temp_new_i64();
7279:
7280: gen_load_fpr64(ctx, fp64, fs);
7281: gen_helper_float_cvts_l(fp32, fp64);
7282: tcg_temp_free_i64(fp64);
7283: gen_store_fpr32(fp32, fd);
7284: tcg_temp_free_i32(fp32);
7285: }
1.1.1.6 root 7286: opn = "cvt.s.l";
7287: break;
1.1.1.12 root 7288: case OPC_CVT_D_L:
1.1.1.6 root 7289: check_cp1_64bitmode(ctx);
1.1.1.7 root 7290: {
7291: TCGv_i64 fp0 = tcg_temp_new_i64();
7292:
7293: gen_load_fpr64(ctx, fp0, fs);
7294: gen_helper_float_cvtd_l(fp0, fp0);
7295: gen_store_fpr64(ctx, fp0, fd);
7296: tcg_temp_free_i64(fp0);
7297: }
1.1.1.6 root 7298: opn = "cvt.d.l";
7299: break;
1.1.1.12 root 7300: case OPC_CVT_PS_PW:
1.1.1.6 root 7301: check_cp1_64bitmode(ctx);
1.1.1.7 root 7302: {
7303: TCGv_i64 fp0 = tcg_temp_new_i64();
7304:
7305: gen_load_fpr64(ctx, fp0, fs);
7306: gen_helper_float_cvtps_pw(fp0, fp0);
7307: gen_store_fpr64(ctx, fp0, fd);
7308: tcg_temp_free_i64(fp0);
7309: }
1.1.1.6 root 7310: opn = "cvt.ps.pw";
7311: break;
1.1.1.12 root 7312: case OPC_ADD_PS:
1.1.1.6 root 7313: check_cp1_64bitmode(ctx);
1.1.1.7 root 7314: {
7315: TCGv_i64 fp0 = tcg_temp_new_i64();
7316: TCGv_i64 fp1 = tcg_temp_new_i64();
7317:
7318: gen_load_fpr64(ctx, fp0, fs);
7319: gen_load_fpr64(ctx, fp1, ft);
7320: gen_helper_float_add_ps(fp0, fp0, fp1);
7321: tcg_temp_free_i64(fp1);
7322: gen_store_fpr64(ctx, fp0, fd);
7323: tcg_temp_free_i64(fp0);
7324: }
1.1.1.6 root 7325: opn = "add.ps";
7326: break;
1.1.1.12 root 7327: case OPC_SUB_PS:
1.1.1.6 root 7328: check_cp1_64bitmode(ctx);
1.1.1.7 root 7329: {
7330: TCGv_i64 fp0 = tcg_temp_new_i64();
7331: TCGv_i64 fp1 = tcg_temp_new_i64();
7332:
7333: gen_load_fpr64(ctx, fp0, fs);
7334: gen_load_fpr64(ctx, fp1, ft);
7335: gen_helper_float_sub_ps(fp0, fp0, fp1);
7336: tcg_temp_free_i64(fp1);
7337: gen_store_fpr64(ctx, fp0, fd);
7338: tcg_temp_free_i64(fp0);
7339: }
1.1.1.6 root 7340: opn = "sub.ps";
7341: break;
1.1.1.12 root 7342: case OPC_MUL_PS:
1.1.1.6 root 7343: check_cp1_64bitmode(ctx);
1.1.1.7 root 7344: {
7345: TCGv_i64 fp0 = tcg_temp_new_i64();
7346: TCGv_i64 fp1 = tcg_temp_new_i64();
7347:
7348: gen_load_fpr64(ctx, fp0, fs);
7349: gen_load_fpr64(ctx, fp1, ft);
7350: gen_helper_float_mul_ps(fp0, fp0, fp1);
7351: tcg_temp_free_i64(fp1);
7352: gen_store_fpr64(ctx, fp0, fd);
7353: tcg_temp_free_i64(fp0);
7354: }
1.1.1.6 root 7355: opn = "mul.ps";
7356: break;
1.1.1.12 root 7357: case OPC_ABS_PS:
1.1.1.6 root 7358: check_cp1_64bitmode(ctx);
1.1.1.7 root 7359: {
7360: TCGv_i64 fp0 = tcg_temp_new_i64();
7361:
7362: gen_load_fpr64(ctx, fp0, fs);
7363: gen_helper_float_abs_ps(fp0, fp0);
7364: gen_store_fpr64(ctx, fp0, fd);
7365: tcg_temp_free_i64(fp0);
7366: }
1.1.1.6 root 7367: opn = "abs.ps";
7368: break;
1.1.1.12 root 7369: case OPC_MOV_PS:
1.1.1.6 root 7370: check_cp1_64bitmode(ctx);
1.1.1.7 root 7371: {
7372: TCGv_i64 fp0 = tcg_temp_new_i64();
7373:
7374: gen_load_fpr64(ctx, fp0, fs);
7375: gen_store_fpr64(ctx, fp0, fd);
7376: tcg_temp_free_i64(fp0);
7377: }
1.1.1.6 root 7378: opn = "mov.ps";
7379: break;
1.1.1.12 root 7380: case OPC_NEG_PS:
1.1.1.6 root 7381: check_cp1_64bitmode(ctx);
1.1.1.7 root 7382: {
7383: TCGv_i64 fp0 = tcg_temp_new_i64();
7384:
7385: gen_load_fpr64(ctx, fp0, fs);
7386: gen_helper_float_chs_ps(fp0, fp0);
7387: gen_store_fpr64(ctx, fp0, fd);
7388: tcg_temp_free_i64(fp0);
7389: }
1.1.1.6 root 7390: opn = "neg.ps";
7391: break;
1.1.1.12 root 7392: case OPC_MOVCF_PS:
1.1.1.6 root 7393: check_cp1_64bitmode(ctx);
1.1.1.7 root 7394: gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 7395: opn = "movcf.ps";
7396: break;
1.1.1.12 root 7397: case OPC_MOVZ_PS:
1.1.1.6 root 7398: check_cp1_64bitmode(ctx);
1.1.1.7 root 7399: {
7400: int l1 = gen_new_label();
1.1.1.8 root 7401: TCGv_i64 fp0;
1.1.1.7 root 7402:
1.1.1.8 root 7403: if (ft != 0)
7404: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7405: fp0 = tcg_temp_new_i64();
7406: gen_load_fpr64(ctx, fp0, fs);
7407: gen_store_fpr64(ctx, fp0, fd);
7408: tcg_temp_free_i64(fp0);
1.1.1.7 root 7409: gen_set_label(l1);
7410: }
1.1.1.6 root 7411: opn = "movz.ps";
7412: break;
1.1.1.12 root 7413: case OPC_MOVN_PS:
1.1.1.6 root 7414: check_cp1_64bitmode(ctx);
1.1.1.7 root 7415: {
7416: int l1 = gen_new_label();
1.1.1.8 root 7417: TCGv_i64 fp0;
1.1.1.7 root 7418:
1.1.1.8 root 7419: if (ft != 0) {
7420: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7421: fp0 = tcg_temp_new_i64();
7422: gen_load_fpr64(ctx, fp0, fs);
7423: gen_store_fpr64(ctx, fp0, fd);
7424: tcg_temp_free_i64(fp0);
7425: gen_set_label(l1);
7426: }
1.1.1.7 root 7427: }
1.1.1.6 root 7428: opn = "movn.ps";
7429: break;
1.1.1.12 root 7430: case OPC_ADDR_PS:
1.1.1.6 root 7431: check_cp1_64bitmode(ctx);
1.1.1.7 root 7432: {
7433: TCGv_i64 fp0 = tcg_temp_new_i64();
7434: TCGv_i64 fp1 = tcg_temp_new_i64();
7435:
7436: gen_load_fpr64(ctx, fp0, ft);
7437: gen_load_fpr64(ctx, fp1, fs);
7438: gen_helper_float_addr_ps(fp0, fp0, fp1);
7439: tcg_temp_free_i64(fp1);
7440: gen_store_fpr64(ctx, fp0, fd);
7441: tcg_temp_free_i64(fp0);
7442: }
1.1.1.6 root 7443: opn = "addr.ps";
7444: break;
1.1.1.12 root 7445: case OPC_MULR_PS:
1.1.1.6 root 7446: check_cp1_64bitmode(ctx);
1.1.1.7 root 7447: {
7448: TCGv_i64 fp0 = tcg_temp_new_i64();
7449: TCGv_i64 fp1 = tcg_temp_new_i64();
7450:
7451: gen_load_fpr64(ctx, fp0, ft);
7452: gen_load_fpr64(ctx, fp1, fs);
7453: gen_helper_float_mulr_ps(fp0, fp0, fp1);
7454: tcg_temp_free_i64(fp1);
7455: gen_store_fpr64(ctx, fp0, fd);
7456: tcg_temp_free_i64(fp0);
7457: }
1.1.1.6 root 7458: opn = "mulr.ps";
7459: break;
1.1.1.12 root 7460: case OPC_RECIP2_PS:
1.1.1.6 root 7461: check_cp1_64bitmode(ctx);
1.1.1.7 root 7462: {
7463: TCGv_i64 fp0 = tcg_temp_new_i64();
7464: TCGv_i64 fp1 = tcg_temp_new_i64();
7465:
7466: gen_load_fpr64(ctx, fp0, fs);
7467: gen_load_fpr64(ctx, fp1, fd);
7468: gen_helper_float_recip2_ps(fp0, fp0, fp1);
7469: tcg_temp_free_i64(fp1);
7470: gen_store_fpr64(ctx, fp0, fd);
7471: tcg_temp_free_i64(fp0);
7472: }
1.1.1.6 root 7473: opn = "recip2.ps";
7474: break;
1.1.1.12 root 7475: case OPC_RECIP1_PS:
1.1.1.6 root 7476: check_cp1_64bitmode(ctx);
1.1.1.7 root 7477: {
7478: TCGv_i64 fp0 = tcg_temp_new_i64();
7479:
7480: gen_load_fpr64(ctx, fp0, fs);
7481: gen_helper_float_recip1_ps(fp0, fp0);
7482: gen_store_fpr64(ctx, fp0, fd);
7483: tcg_temp_free_i64(fp0);
7484: }
1.1.1.6 root 7485: opn = "recip1.ps";
7486: break;
1.1.1.12 root 7487: case OPC_RSQRT1_PS:
1.1.1.6 root 7488: check_cp1_64bitmode(ctx);
1.1.1.7 root 7489: {
7490: TCGv_i64 fp0 = tcg_temp_new_i64();
7491:
7492: gen_load_fpr64(ctx, fp0, fs);
7493: gen_helper_float_rsqrt1_ps(fp0, fp0);
7494: gen_store_fpr64(ctx, fp0, fd);
7495: tcg_temp_free_i64(fp0);
7496: }
1.1.1.6 root 7497: opn = "rsqrt1.ps";
7498: break;
1.1.1.12 root 7499: case OPC_RSQRT2_PS:
1.1.1.6 root 7500: check_cp1_64bitmode(ctx);
1.1.1.7 root 7501: {
7502: TCGv_i64 fp0 = tcg_temp_new_i64();
7503: TCGv_i64 fp1 = tcg_temp_new_i64();
7504:
7505: gen_load_fpr64(ctx, fp0, fs);
7506: gen_load_fpr64(ctx, fp1, ft);
7507: gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7508: tcg_temp_free_i64(fp1);
7509: gen_store_fpr64(ctx, fp0, fd);
7510: tcg_temp_free_i64(fp0);
7511: }
1.1.1.6 root 7512: opn = "rsqrt2.ps";
7513: break;
1.1.1.12 root 7514: case OPC_CVT_S_PU:
1.1.1.6 root 7515: check_cp1_64bitmode(ctx);
1.1.1.7 root 7516: {
7517: TCGv_i32 fp0 = tcg_temp_new_i32();
7518:
7519: gen_load_fpr32h(fp0, fs);
7520: gen_helper_float_cvts_pu(fp0, fp0);
7521: gen_store_fpr32(fp0, fd);
7522: tcg_temp_free_i32(fp0);
7523: }
1.1.1.6 root 7524: opn = "cvt.s.pu";
7525: break;
1.1.1.12 root 7526: case OPC_CVT_PW_PS:
1.1.1.6 root 7527: check_cp1_64bitmode(ctx);
1.1.1.7 root 7528: {
7529: TCGv_i64 fp0 = tcg_temp_new_i64();
7530:
7531: gen_load_fpr64(ctx, fp0, fs);
7532: gen_helper_float_cvtpw_ps(fp0, fp0);
7533: gen_store_fpr64(ctx, fp0, fd);
7534: tcg_temp_free_i64(fp0);
7535: }
1.1.1.6 root 7536: opn = "cvt.pw.ps";
1.1.1.4 root 7537: break;
1.1.1.12 root 7538: case OPC_CVT_S_PL:
1.1.1.6 root 7539: check_cp1_64bitmode(ctx);
1.1.1.7 root 7540: {
7541: TCGv_i32 fp0 = tcg_temp_new_i32();
7542:
7543: gen_load_fpr32(fp0, fs);
7544: gen_helper_float_cvts_pl(fp0, fp0);
7545: gen_store_fpr32(fp0, fd);
7546: tcg_temp_free_i32(fp0);
7547: }
1.1.1.6 root 7548: opn = "cvt.s.pl";
1.1.1.4 root 7549: break;
1.1.1.12 root 7550: case OPC_PLL_PS:
1.1.1.6 root 7551: check_cp1_64bitmode(ctx);
1.1.1.7 root 7552: {
7553: TCGv_i32 fp0 = tcg_temp_new_i32();
7554: TCGv_i32 fp1 = tcg_temp_new_i32();
7555:
7556: gen_load_fpr32(fp0, fs);
7557: gen_load_fpr32(fp1, ft);
7558: gen_store_fpr32h(fp0, fd);
7559: gen_store_fpr32(fp1, fd);
7560: tcg_temp_free_i32(fp0);
7561: tcg_temp_free_i32(fp1);
7562: }
1.1.1.6 root 7563: opn = "pll.ps";
1.1.1.4 root 7564: break;
1.1.1.12 root 7565: case OPC_PLU_PS:
1.1.1.6 root 7566: check_cp1_64bitmode(ctx);
1.1.1.7 root 7567: {
7568: TCGv_i32 fp0 = tcg_temp_new_i32();
7569: TCGv_i32 fp1 = tcg_temp_new_i32();
7570:
7571: gen_load_fpr32(fp0, fs);
7572: gen_load_fpr32h(fp1, ft);
7573: gen_store_fpr32(fp1, fd);
7574: gen_store_fpr32h(fp0, fd);
7575: tcg_temp_free_i32(fp0);
7576: tcg_temp_free_i32(fp1);
7577: }
1.1.1.6 root 7578: opn = "plu.ps";
7579: break;
1.1.1.12 root 7580: case OPC_PUL_PS:
1.1.1.6 root 7581: check_cp1_64bitmode(ctx);
1.1.1.7 root 7582: {
7583: TCGv_i32 fp0 = tcg_temp_new_i32();
7584: TCGv_i32 fp1 = tcg_temp_new_i32();
7585:
7586: gen_load_fpr32h(fp0, fs);
7587: gen_load_fpr32(fp1, ft);
7588: gen_store_fpr32(fp1, fd);
7589: gen_store_fpr32h(fp0, fd);
7590: tcg_temp_free_i32(fp0);
7591: tcg_temp_free_i32(fp1);
7592: }
1.1.1.6 root 7593: opn = "pul.ps";
1.1.1.4 root 7594: break;
1.1.1.12 root 7595: case OPC_PUU_PS:
1.1.1.6 root 7596: check_cp1_64bitmode(ctx);
1.1.1.7 root 7597: {
7598: TCGv_i32 fp0 = tcg_temp_new_i32();
7599: TCGv_i32 fp1 = tcg_temp_new_i32();
7600:
7601: gen_load_fpr32h(fp0, fs);
7602: gen_load_fpr32h(fp1, ft);
7603: gen_store_fpr32(fp1, fd);
7604: gen_store_fpr32h(fp0, fd);
7605: tcg_temp_free_i32(fp0);
7606: tcg_temp_free_i32(fp1);
7607: }
1.1.1.6 root 7608: opn = "puu.ps";
7609: break;
1.1.1.12 root 7610: case OPC_CMP_F_PS:
7611: case OPC_CMP_UN_PS:
7612: case OPC_CMP_EQ_PS:
7613: case OPC_CMP_UEQ_PS:
7614: case OPC_CMP_OLT_PS:
7615: case OPC_CMP_ULT_PS:
7616: case OPC_CMP_OLE_PS:
7617: case OPC_CMP_ULE_PS:
7618: case OPC_CMP_SF_PS:
7619: case OPC_CMP_NGLE_PS:
7620: case OPC_CMP_SEQ_PS:
7621: case OPC_CMP_NGL_PS:
7622: case OPC_CMP_LT_PS:
7623: case OPC_CMP_NGE_PS:
7624: case OPC_CMP_LE_PS:
7625: case OPC_CMP_NGT_PS:
7626: if (ctx->opcode & (1 << 6)) {
7627: gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7628: opn = condnames_abs[func-48];
7629: } else {
7630: gen_cmp_ps(ctx, func-48, ft, fs, cc);
7631: opn = condnames[func-48];
1.1.1.6 root 7632: }
1.1.1.4 root 7633: break;
1.1.1.6 root 7634: default:
7635: MIPS_INVAL(opn);
7636: generate_exception (ctx, EXCP_RI);
7637: return;
7638: }
1.1.1.13 root 7639: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 7640: switch (optype) {
7641: case BINOP:
7642: MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7643: break;
7644: case CMPOP:
7645: MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7646: break;
7647: default:
7648: MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7649: break;
7650: }
7651: }
7652:
7653: /* Coprocessor 3 (FPU) */
7654: static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7655: int fd, int fs, int base, int index)
7656: {
7657: const char *opn = "extended float load/store";
7658: int store = 0;
1.1.1.8 root 7659: TCGv t0 = tcg_temp_new();
1.1.1.6 root 7660:
7661: if (base == 0) {
1.1.1.7 root 7662: gen_load_gpr(t0, index);
1.1.1.6 root 7663: } else if (index == 0) {
1.1.1.7 root 7664: gen_load_gpr(t0, base);
1.1.1.6 root 7665: } else {
1.1.1.7 root 7666: gen_load_gpr(t0, index);
1.1.1.9 root 7667: gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
1.1.1.6 root 7668: }
7669: /* Don't do NOP if destination is zero: we must perform the actual
7670: memory access. */
1.1.1.8 root 7671: save_cpu_state(ctx, 0);
1.1.1.6 root 7672: switch (opc) {
7673: case OPC_LWXC1:
7674: check_cop1x(ctx);
1.1.1.7 root 7675: {
7676: TCGv_i32 fp0 = tcg_temp_new_i32();
7677:
1.1.1.8 root 7678: tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7679: tcg_gen_trunc_tl_i32(fp0, t0);
1.1.1.7 root 7680: gen_store_fpr32(fp0, fd);
7681: tcg_temp_free_i32(fp0);
7682: }
1.1.1.6 root 7683: opn = "lwxc1";
7684: break;
7685: case OPC_LDXC1:
7686: check_cop1x(ctx);
7687: check_cp1_registers(ctx, fd);
1.1.1.7 root 7688: {
7689: TCGv_i64 fp0 = tcg_temp_new_i64();
7690:
7691: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7692: gen_store_fpr64(ctx, fp0, fd);
7693: tcg_temp_free_i64(fp0);
7694: }
1.1.1.6 root 7695: opn = "ldxc1";
7696: break;
7697: case OPC_LUXC1:
7698: check_cp1_64bitmode(ctx);
1.1.1.7 root 7699: tcg_gen_andi_tl(t0, t0, ~0x7);
7700: {
7701: TCGv_i64 fp0 = tcg_temp_new_i64();
7702:
7703: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7704: gen_store_fpr64(ctx, fp0, fd);
7705: tcg_temp_free_i64(fp0);
7706: }
1.1.1.6 root 7707: opn = "luxc1";
7708: break;
7709: case OPC_SWXC1:
7710: check_cop1x(ctx);
1.1.1.7 root 7711: {
7712: TCGv_i32 fp0 = tcg_temp_new_i32();
1.1.1.8 root 7713: TCGv t1 = tcg_temp_new();
1.1.1.7 root 7714:
7715: gen_load_fpr32(fp0, fs);
7716: tcg_gen_extu_i32_tl(t1, fp0);
7717: tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7718: tcg_temp_free_i32(fp0);
1.1.1.8 root 7719: tcg_temp_free(t1);
1.1.1.7 root 7720: }
1.1.1.6 root 7721: opn = "swxc1";
7722: store = 1;
1.1.1.4 root 7723: break;
1.1.1.6 root 7724: case OPC_SDXC1:
7725: check_cop1x(ctx);
7726: check_cp1_registers(ctx, fs);
1.1.1.7 root 7727: {
7728: TCGv_i64 fp0 = tcg_temp_new_i64();
7729:
7730: gen_load_fpr64(ctx, fp0, fs);
7731: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7732: tcg_temp_free_i64(fp0);
7733: }
1.1.1.6 root 7734: opn = "sdxc1";
7735: store = 1;
7736: break;
7737: case OPC_SUXC1:
7738: check_cp1_64bitmode(ctx);
1.1.1.7 root 7739: tcg_gen_andi_tl(t0, t0, ~0x7);
7740: {
7741: TCGv_i64 fp0 = tcg_temp_new_i64();
7742:
7743: gen_load_fpr64(ctx, fp0, fs);
7744: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7745: tcg_temp_free_i64(fp0);
7746: }
1.1.1.6 root 7747: opn = "suxc1";
7748: store = 1;
7749: break;
7750: }
1.1.1.7 root 7751: tcg_temp_free(t0);
1.1.1.13 root 7752: (void)opn; (void)store; /* avoid compiler warnings */
1.1.1.6 root 7753: MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7754: regnames[index], regnames[base]);
7755: }
7756:
7757: static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7758: int fd, int fr, int fs, int ft)
7759: {
7760: const char *opn = "flt3_arith";
7761:
7762: switch (opc) {
7763: case OPC_ALNV_PS:
7764: check_cp1_64bitmode(ctx);
1.1.1.7 root 7765: {
7766: TCGv t0 = tcg_temp_local_new();
1.1.1.8 root 7767: TCGv_i32 fp = tcg_temp_new_i32();
7768: TCGv_i32 fph = tcg_temp_new_i32();
1.1.1.7 root 7769: int l1 = gen_new_label();
7770: int l2 = gen_new_label();
7771:
7772: gen_load_gpr(t0, fr);
7773: tcg_gen_andi_tl(t0, t0, 0x7);
7774:
7775: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
1.1.1.8 root 7776: gen_load_fpr32(fp, fs);
7777: gen_load_fpr32h(fph, fs);
7778: gen_store_fpr32(fp, fd);
7779: gen_store_fpr32h(fph, fd);
1.1.1.7 root 7780: tcg_gen_br(l2);
7781: gen_set_label(l1);
7782: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7783: tcg_temp_free(t0);
7784: #ifdef TARGET_WORDS_BIGENDIAN
1.1.1.8 root 7785: gen_load_fpr32(fp, fs);
7786: gen_load_fpr32h(fph, ft);
7787: gen_store_fpr32h(fp, fd);
7788: gen_store_fpr32(fph, fd);
1.1.1.7 root 7789: #else
1.1.1.8 root 7790: gen_load_fpr32h(fph, fs);
7791: gen_load_fpr32(fp, ft);
7792: gen_store_fpr32(fph, fd);
7793: gen_store_fpr32h(fp, fd);
1.1.1.7 root 7794: #endif
7795: gen_set_label(l2);
1.1.1.8 root 7796: tcg_temp_free_i32(fp);
7797: tcg_temp_free_i32(fph);
1.1.1.7 root 7798: }
1.1.1.6 root 7799: opn = "alnv.ps";
7800: break;
7801: case OPC_MADD_S:
7802: check_cop1x(ctx);
1.1.1.7 root 7803: {
7804: TCGv_i32 fp0 = tcg_temp_new_i32();
7805: TCGv_i32 fp1 = tcg_temp_new_i32();
7806: TCGv_i32 fp2 = tcg_temp_new_i32();
7807:
7808: gen_load_fpr32(fp0, fs);
7809: gen_load_fpr32(fp1, ft);
7810: gen_load_fpr32(fp2, fr);
7811: gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7812: tcg_temp_free_i32(fp0);
7813: tcg_temp_free_i32(fp1);
7814: gen_store_fpr32(fp2, fd);
7815: tcg_temp_free_i32(fp2);
7816: }
1.1.1.6 root 7817: opn = "madd.s";
1.1.1.4 root 7818: break;
1.1.1.6 root 7819: case OPC_MADD_D:
7820: check_cop1x(ctx);
7821: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7822: {
7823: TCGv_i64 fp0 = tcg_temp_new_i64();
7824: TCGv_i64 fp1 = tcg_temp_new_i64();
7825: TCGv_i64 fp2 = tcg_temp_new_i64();
7826:
7827: gen_load_fpr64(ctx, fp0, fs);
7828: gen_load_fpr64(ctx, fp1, ft);
7829: gen_load_fpr64(ctx, fp2, fr);
7830: gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7831: tcg_temp_free_i64(fp0);
7832: tcg_temp_free_i64(fp1);
7833: gen_store_fpr64(ctx, fp2, fd);
7834: tcg_temp_free_i64(fp2);
7835: }
1.1.1.6 root 7836: opn = "madd.d";
7837: break;
7838: case OPC_MADD_PS:
7839: check_cp1_64bitmode(ctx);
1.1.1.7 root 7840: {
7841: TCGv_i64 fp0 = tcg_temp_new_i64();
7842: TCGv_i64 fp1 = tcg_temp_new_i64();
7843: TCGv_i64 fp2 = tcg_temp_new_i64();
7844:
7845: gen_load_fpr64(ctx, fp0, fs);
7846: gen_load_fpr64(ctx, fp1, ft);
7847: gen_load_fpr64(ctx, fp2, fr);
7848: gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7849: tcg_temp_free_i64(fp0);
7850: tcg_temp_free_i64(fp1);
7851: gen_store_fpr64(ctx, fp2, fd);
7852: tcg_temp_free_i64(fp2);
7853: }
1.1.1.6 root 7854: opn = "madd.ps";
1.1.1.4 root 7855: break;
1.1.1.6 root 7856: case OPC_MSUB_S:
7857: check_cop1x(ctx);
1.1.1.7 root 7858: {
7859: TCGv_i32 fp0 = tcg_temp_new_i32();
7860: TCGv_i32 fp1 = tcg_temp_new_i32();
7861: TCGv_i32 fp2 = tcg_temp_new_i32();
7862:
7863: gen_load_fpr32(fp0, fs);
7864: gen_load_fpr32(fp1, ft);
7865: gen_load_fpr32(fp2, fr);
7866: gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7867: tcg_temp_free_i32(fp0);
7868: tcg_temp_free_i32(fp1);
7869: gen_store_fpr32(fp2, fd);
7870: tcg_temp_free_i32(fp2);
7871: }
1.1.1.6 root 7872: opn = "msub.s";
1.1.1.4 root 7873: break;
1.1.1.6 root 7874: case OPC_MSUB_D:
7875: check_cop1x(ctx);
7876: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7877: {
7878: TCGv_i64 fp0 = tcg_temp_new_i64();
7879: TCGv_i64 fp1 = tcg_temp_new_i64();
7880: TCGv_i64 fp2 = tcg_temp_new_i64();
7881:
7882: gen_load_fpr64(ctx, fp0, fs);
7883: gen_load_fpr64(ctx, fp1, ft);
7884: gen_load_fpr64(ctx, fp2, fr);
7885: gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7886: tcg_temp_free_i64(fp0);
7887: tcg_temp_free_i64(fp1);
7888: gen_store_fpr64(ctx, fp2, fd);
7889: tcg_temp_free_i64(fp2);
7890: }
1.1.1.6 root 7891: opn = "msub.d";
7892: break;
7893: case OPC_MSUB_PS:
7894: check_cp1_64bitmode(ctx);
1.1.1.7 root 7895: {
7896: TCGv_i64 fp0 = tcg_temp_new_i64();
7897: TCGv_i64 fp1 = tcg_temp_new_i64();
7898: TCGv_i64 fp2 = tcg_temp_new_i64();
7899:
7900: gen_load_fpr64(ctx, fp0, fs);
7901: gen_load_fpr64(ctx, fp1, ft);
7902: gen_load_fpr64(ctx, fp2, fr);
7903: gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7904: tcg_temp_free_i64(fp0);
7905: tcg_temp_free_i64(fp1);
7906: gen_store_fpr64(ctx, fp2, fd);
7907: tcg_temp_free_i64(fp2);
7908: }
1.1.1.6 root 7909: opn = "msub.ps";
1.1.1.4 root 7910: break;
1.1.1.6 root 7911: case OPC_NMADD_S:
7912: check_cop1x(ctx);
1.1.1.7 root 7913: {
7914: TCGv_i32 fp0 = tcg_temp_new_i32();
7915: TCGv_i32 fp1 = tcg_temp_new_i32();
7916: TCGv_i32 fp2 = tcg_temp_new_i32();
7917:
7918: gen_load_fpr32(fp0, fs);
7919: gen_load_fpr32(fp1, ft);
7920: gen_load_fpr32(fp2, fr);
7921: gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7922: tcg_temp_free_i32(fp0);
7923: tcg_temp_free_i32(fp1);
7924: gen_store_fpr32(fp2, fd);
7925: tcg_temp_free_i32(fp2);
7926: }
1.1.1.6 root 7927: opn = "nmadd.s";
1.1.1.4 root 7928: break;
1.1.1.6 root 7929: case OPC_NMADD_D:
7930: check_cop1x(ctx);
7931: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7932: {
7933: TCGv_i64 fp0 = tcg_temp_new_i64();
7934: TCGv_i64 fp1 = tcg_temp_new_i64();
7935: TCGv_i64 fp2 = tcg_temp_new_i64();
7936:
7937: gen_load_fpr64(ctx, fp0, fs);
7938: gen_load_fpr64(ctx, fp1, ft);
7939: gen_load_fpr64(ctx, fp2, fr);
7940: gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7941: tcg_temp_free_i64(fp0);
7942: tcg_temp_free_i64(fp1);
7943: gen_store_fpr64(ctx, fp2, fd);
7944: tcg_temp_free_i64(fp2);
7945: }
1.1.1.6 root 7946: opn = "nmadd.d";
1.1.1.5 root 7947: break;
1.1.1.6 root 7948: case OPC_NMADD_PS:
7949: check_cp1_64bitmode(ctx);
1.1.1.7 root 7950: {
7951: TCGv_i64 fp0 = tcg_temp_new_i64();
7952: TCGv_i64 fp1 = tcg_temp_new_i64();
7953: TCGv_i64 fp2 = tcg_temp_new_i64();
7954:
7955: gen_load_fpr64(ctx, fp0, fs);
7956: gen_load_fpr64(ctx, fp1, ft);
7957: gen_load_fpr64(ctx, fp2, fr);
7958: gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7959: tcg_temp_free_i64(fp0);
7960: tcg_temp_free_i64(fp1);
7961: gen_store_fpr64(ctx, fp2, fd);
7962: tcg_temp_free_i64(fp2);
7963: }
1.1.1.6 root 7964: opn = "nmadd.ps";
1.1.1.4 root 7965: break;
1.1.1.6 root 7966: case OPC_NMSUB_S:
7967: check_cop1x(ctx);
1.1.1.7 root 7968: {
7969: TCGv_i32 fp0 = tcg_temp_new_i32();
7970: TCGv_i32 fp1 = tcg_temp_new_i32();
7971: TCGv_i32 fp2 = tcg_temp_new_i32();
7972:
7973: gen_load_fpr32(fp0, fs);
7974: gen_load_fpr32(fp1, ft);
7975: gen_load_fpr32(fp2, fr);
7976: gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7977: tcg_temp_free_i32(fp0);
7978: tcg_temp_free_i32(fp1);
7979: gen_store_fpr32(fp2, fd);
7980: tcg_temp_free_i32(fp2);
7981: }
1.1.1.6 root 7982: opn = "nmsub.s";
1.1.1.4 root 7983: break;
1.1.1.6 root 7984: case OPC_NMSUB_D:
7985: check_cop1x(ctx);
7986: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7987: {
7988: TCGv_i64 fp0 = tcg_temp_new_i64();
7989: TCGv_i64 fp1 = tcg_temp_new_i64();
7990: TCGv_i64 fp2 = tcg_temp_new_i64();
7991:
7992: gen_load_fpr64(ctx, fp0, fs);
7993: gen_load_fpr64(ctx, fp1, ft);
7994: gen_load_fpr64(ctx, fp2, fr);
7995: gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7996: tcg_temp_free_i64(fp0);
7997: tcg_temp_free_i64(fp1);
7998: gen_store_fpr64(ctx, fp2, fd);
7999: tcg_temp_free_i64(fp2);
8000: }
1.1.1.6 root 8001: opn = "nmsub.d";
1.1.1.4 root 8002: break;
1.1.1.6 root 8003: case OPC_NMSUB_PS:
8004: check_cp1_64bitmode(ctx);
1.1.1.7 root 8005: {
8006: TCGv_i64 fp0 = tcg_temp_new_i64();
8007: TCGv_i64 fp1 = tcg_temp_new_i64();
8008: TCGv_i64 fp2 = tcg_temp_new_i64();
8009:
8010: gen_load_fpr64(ctx, fp0, fs);
8011: gen_load_fpr64(ctx, fp1, ft);
8012: gen_load_fpr64(ctx, fp2, fr);
8013: gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
8014: tcg_temp_free_i64(fp0);
8015: tcg_temp_free_i64(fp1);
8016: gen_store_fpr64(ctx, fp2, fd);
8017: tcg_temp_free_i64(fp2);
8018: }
1.1.1.6 root 8019: opn = "nmsub.ps";
1.1.1.4 root 8020: break;
1.1.1.6 root 8021: default:
8022: MIPS_INVAL(opn);
8023: generate_exception (ctx, EXCP_RI);
1.1.1.4 root 8024: return;
8025: }
1.1.1.13 root 8026: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 8027: MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8028: fregnames[fs], fregnames[ft]);
1.1 root 8029: }
8030:
1.1.1.12 root 8031: static void
8032: gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
8033: {
8034: TCGv t0;
1.1 root 8035:
1.1.1.12 root 8036: check_insn(env, ctx, ISA_MIPS32R2);
8037: t0 = tcg_temp_new();
1.1 root 8038:
1.1.1.12 root 8039: switch (rd) {
8040: case 0:
8041: save_cpu_state(ctx, 1);
8042: gen_helper_rdhwr_cpunum(t0);
8043: gen_store_gpr(t0, rt);
8044: break;
8045: case 1:
8046: save_cpu_state(ctx, 1);
8047: gen_helper_rdhwr_synci_step(t0);
8048: gen_store_gpr(t0, rt);
8049: break;
8050: case 2:
8051: save_cpu_state(ctx, 1);
8052: gen_helper_rdhwr_cc(t0);
8053: gen_store_gpr(t0, rt);
8054: break;
8055: case 3:
8056: save_cpu_state(ctx, 1);
8057: gen_helper_rdhwr_ccres(t0);
8058: gen_store_gpr(t0, rt);
8059: break;
8060: case 29:
8061: #if defined(CONFIG_USER_ONLY)
8062: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
8063: gen_store_gpr(t0, rt);
8064: break;
8065: #else
8066: /* XXX: Some CPUs implement this in hardware.
8067: Not supported yet. */
1.1 root 8068: #endif
1.1.1.12 root 8069: default: /* Invalid */
8070: MIPS_INVAL("rdhwr");
8071: generate_exception(ctx, EXCP_RI);
8072: break;
1.1.1.4 root 8073: }
1.1.1.12 root 8074: tcg_temp_free(t0);
8075: }
1.1.1.4 root 8076:
1.1.1.12 root 8077: static void handle_delay_slot (CPUState *env, DisasContext *ctx,
8078: int insn_bytes)
8079: {
8080: if (ctx->hflags & MIPS_HFLAG_BMASK) {
8081: int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8082: /* Branches completion */
8083: ctx->hflags &= ~MIPS_HFLAG_BMASK;
8084: ctx->bstate = BS_BRANCH;
8085: save_cpu_state(ctx, 0);
8086: /* FIXME: Need to clear can_do_io. */
8087: switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
8088: case MIPS_HFLAG_B:
8089: /* unconditional branch */
8090: MIPS_DEBUG("unconditional branch");
8091: if (proc_hflags & MIPS_HFLAG_BX) {
8092: tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8093: }
8094: gen_goto_tb(ctx, 0, ctx->btarget);
8095: break;
8096: case MIPS_HFLAG_BL:
8097: /* blikely taken case */
8098: MIPS_DEBUG("blikely branch taken");
8099: gen_goto_tb(ctx, 0, ctx->btarget);
8100: break;
8101: case MIPS_HFLAG_BC:
8102: /* Conditional branch */
8103: MIPS_DEBUG("conditional branch");
8104: {
8105: int l1 = gen_new_label();
1.1.1.7 root 8106:
1.1.1.12 root 8107: tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8108: gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8109: gen_set_label(l1);
8110: gen_goto_tb(ctx, 0, ctx->btarget);
8111: }
8112: break;
8113: case MIPS_HFLAG_BR:
8114: /* unconditional branch to register */
8115: MIPS_DEBUG("branch to register");
8116: if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
8117: TCGv t0 = tcg_temp_new();
8118: TCGv_i32 t1 = tcg_temp_new_i32();
8119:
8120: tcg_gen_andi_tl(t0, btarget, 0x1);
8121: tcg_gen_trunc_tl_i32(t1, t0);
8122: tcg_temp_free(t0);
8123: tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8124: tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8125: tcg_gen_or_i32(hflags, hflags, t1);
8126: tcg_temp_free_i32(t1);
8127:
8128: tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8129: } else {
8130: tcg_gen_mov_tl(cpu_PC, btarget);
8131: }
8132: if (ctx->singlestep_enabled) {
8133: save_cpu_state(ctx, 0);
8134: gen_helper_0i(raise_exception, EXCP_DEBUG);
8135: }
8136: tcg_gen_exit_tb(0);
8137: break;
8138: default:
8139: MIPS_DEBUG("unknown branch");
8140: break;
8141: }
8142: }
8143: }
8144:
8145: /* ISA extensions (ASEs) */
8146: /* MIPS16 extension to MIPS32 */
8147:
8148: /* MIPS16 major opcodes */
8149: enum {
8150: M16_OPC_ADDIUSP = 0x00,
8151: M16_OPC_ADDIUPC = 0x01,
8152: M16_OPC_B = 0x02,
8153: M16_OPC_JAL = 0x03,
8154: M16_OPC_BEQZ = 0x04,
8155: M16_OPC_BNEQZ = 0x05,
8156: M16_OPC_SHIFT = 0x06,
8157: M16_OPC_LD = 0x07,
8158: M16_OPC_RRIA = 0x08,
8159: M16_OPC_ADDIU8 = 0x09,
8160: M16_OPC_SLTI = 0x0a,
8161: M16_OPC_SLTIU = 0x0b,
8162: M16_OPC_I8 = 0x0c,
8163: M16_OPC_LI = 0x0d,
8164: M16_OPC_CMPI = 0x0e,
8165: M16_OPC_SD = 0x0f,
8166: M16_OPC_LB = 0x10,
8167: M16_OPC_LH = 0x11,
8168: M16_OPC_LWSP = 0x12,
8169: M16_OPC_LW = 0x13,
8170: M16_OPC_LBU = 0x14,
8171: M16_OPC_LHU = 0x15,
8172: M16_OPC_LWPC = 0x16,
8173: M16_OPC_LWU = 0x17,
8174: M16_OPC_SB = 0x18,
8175: M16_OPC_SH = 0x19,
8176: M16_OPC_SWSP = 0x1a,
8177: M16_OPC_SW = 0x1b,
8178: M16_OPC_RRR = 0x1c,
8179: M16_OPC_RR = 0x1d,
8180: M16_OPC_EXTEND = 0x1e,
8181: M16_OPC_I64 = 0x1f
8182: };
8183:
8184: /* I8 funct field */
8185: enum {
8186: I8_BTEQZ = 0x0,
8187: I8_BTNEZ = 0x1,
8188: I8_SWRASP = 0x2,
8189: I8_ADJSP = 0x3,
8190: I8_SVRS = 0x4,
8191: I8_MOV32R = 0x5,
8192: I8_MOVR32 = 0x7
8193: };
8194:
8195: /* RRR f field */
8196: enum {
8197: RRR_DADDU = 0x0,
8198: RRR_ADDU = 0x1,
8199: RRR_DSUBU = 0x2,
8200: RRR_SUBU = 0x3
8201: };
8202:
8203: /* RR funct field */
8204: enum {
8205: RR_JR = 0x00,
8206: RR_SDBBP = 0x01,
8207: RR_SLT = 0x02,
8208: RR_SLTU = 0x03,
8209: RR_SLLV = 0x04,
8210: RR_BREAK = 0x05,
8211: RR_SRLV = 0x06,
8212: RR_SRAV = 0x07,
8213: RR_DSRL = 0x08,
8214: RR_CMP = 0x0a,
8215: RR_NEG = 0x0b,
8216: RR_AND = 0x0c,
8217: RR_OR = 0x0d,
8218: RR_XOR = 0x0e,
8219: RR_NOT = 0x0f,
8220: RR_MFHI = 0x10,
8221: RR_CNVT = 0x11,
8222: RR_MFLO = 0x12,
8223: RR_DSRA = 0x13,
8224: RR_DSLLV = 0x14,
8225: RR_DSRLV = 0x16,
8226: RR_DSRAV = 0x17,
8227: RR_MULT = 0x18,
8228: RR_MULTU = 0x19,
8229: RR_DIV = 0x1a,
8230: RR_DIVU = 0x1b,
8231: RR_DMULT = 0x1c,
8232: RR_DMULTU = 0x1d,
8233: RR_DDIV = 0x1e,
8234: RR_DDIVU = 0x1f
8235: };
8236:
8237: /* I64 funct field */
8238: enum {
8239: I64_LDSP = 0x0,
8240: I64_SDSP = 0x1,
8241: I64_SDRASP = 0x2,
8242: I64_DADJSP = 0x3,
8243: I64_LDPC = 0x4,
8244: I64_DADDIU5 = 0x5,
8245: I64_DADDIUPC = 0x6,
8246: I64_DADDIUSP = 0x7
8247: };
8248:
8249: /* RR ry field for CNVT */
8250: enum {
8251: RR_RY_CNVT_ZEB = 0x0,
8252: RR_RY_CNVT_ZEH = 0x1,
8253: RR_RY_CNVT_ZEW = 0x2,
8254: RR_RY_CNVT_SEB = 0x4,
8255: RR_RY_CNVT_SEH = 0x5,
8256: RR_RY_CNVT_SEW = 0x6,
8257: };
8258:
8259: static int xlat (int r)
8260: {
8261: static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8262:
8263: return map[r];
8264: }
8265:
8266: static void gen_mips16_save (DisasContext *ctx,
8267: int xsregs, int aregs,
8268: int do_ra, int do_s0, int do_s1,
8269: int framesize)
8270: {
8271: TCGv t0 = tcg_temp_new();
8272: TCGv t1 = tcg_temp_new();
8273: int args, astatic;
8274:
8275: switch (aregs) {
8276: case 0:
8277: case 1:
8278: case 2:
8279: case 3:
8280: case 11:
8281: args = 0;
8282: break;
8283: case 4:
8284: case 5:
8285: case 6:
8286: case 7:
8287: args = 1;
8288: break;
8289: case 8:
8290: case 9:
8291: case 10:
8292: args = 2;
8293: break;
8294: case 12:
8295: case 13:
8296: args = 3;
8297: break;
8298: case 14:
8299: args = 4;
8300: break;
8301: default:
8302: generate_exception(ctx, EXCP_RI);
8303: return;
8304: }
8305:
8306: switch (args) {
8307: case 4:
8308: gen_base_offset_addr(ctx, t0, 29, 12);
8309: gen_load_gpr(t1, 7);
8310: op_st_sw(t1, t0, ctx);
8311: /* Fall through */
8312: case 3:
8313: gen_base_offset_addr(ctx, t0, 29, 8);
8314: gen_load_gpr(t1, 6);
8315: op_st_sw(t1, t0, ctx);
8316: /* Fall through */
8317: case 2:
8318: gen_base_offset_addr(ctx, t0, 29, 4);
8319: gen_load_gpr(t1, 5);
8320: op_st_sw(t1, t0, ctx);
8321: /* Fall through */
8322: case 1:
8323: gen_base_offset_addr(ctx, t0, 29, 0);
8324: gen_load_gpr(t1, 4);
8325: op_st_sw(t1, t0, ctx);
8326: }
8327:
8328: gen_load_gpr(t0, 29);
8329:
8330: #define DECR_AND_STORE(reg) do { \
8331: tcg_gen_subi_tl(t0, t0, 4); \
8332: gen_load_gpr(t1, reg); \
8333: op_st_sw(t1, t0, ctx); \
8334: } while (0)
8335:
8336: if (do_ra) {
8337: DECR_AND_STORE(31);
8338: }
8339:
8340: switch (xsregs) {
8341: case 7:
8342: DECR_AND_STORE(30);
8343: /* Fall through */
8344: case 6:
8345: DECR_AND_STORE(23);
8346: /* Fall through */
8347: case 5:
8348: DECR_AND_STORE(22);
8349: /* Fall through */
8350: case 4:
8351: DECR_AND_STORE(21);
8352: /* Fall through */
8353: case 3:
8354: DECR_AND_STORE(20);
8355: /* Fall through */
8356: case 2:
8357: DECR_AND_STORE(19);
8358: /* Fall through */
8359: case 1:
8360: DECR_AND_STORE(18);
8361: }
8362:
8363: if (do_s1) {
8364: DECR_AND_STORE(17);
8365: }
8366: if (do_s0) {
8367: DECR_AND_STORE(16);
8368: }
8369:
8370: switch (aregs) {
8371: case 0:
8372: case 4:
8373: case 8:
8374: case 12:
8375: case 14:
8376: astatic = 0;
8377: break;
8378: case 1:
8379: case 5:
8380: case 9:
8381: case 13:
8382: astatic = 1;
8383: break;
8384: case 2:
8385: case 6:
8386: case 10:
8387: astatic = 2;
8388: break;
8389: case 3:
8390: case 7:
8391: astatic = 3;
8392: break;
8393: case 11:
8394: astatic = 4;
8395: break;
8396: default:
8397: generate_exception(ctx, EXCP_RI);
8398: return;
8399: }
8400:
8401: if (astatic > 0) {
8402: DECR_AND_STORE(7);
8403: if (astatic > 1) {
8404: DECR_AND_STORE(6);
8405: if (astatic > 2) {
8406: DECR_AND_STORE(5);
8407: if (astatic > 3) {
8408: DECR_AND_STORE(4);
8409: }
8410: }
8411: }
8412: }
8413: #undef DECR_AND_STORE
8414:
8415: tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8416: tcg_temp_free(t0);
8417: tcg_temp_free(t1);
8418: }
8419:
8420: static void gen_mips16_restore (DisasContext *ctx,
8421: int xsregs, int aregs,
8422: int do_ra, int do_s0, int do_s1,
8423: int framesize)
8424: {
8425: int astatic;
8426: TCGv t0 = tcg_temp_new();
8427: TCGv t1 = tcg_temp_new();
8428:
8429: tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8430:
8431: #define DECR_AND_LOAD(reg) do { \
8432: tcg_gen_subi_tl(t0, t0, 4); \
8433: op_ld_lw(t1, t0, ctx); \
8434: gen_store_gpr(t1, reg); \
8435: } while (0)
8436:
8437: if (do_ra) {
8438: DECR_AND_LOAD(31);
8439: }
8440:
8441: switch (xsregs) {
8442: case 7:
8443: DECR_AND_LOAD(30);
8444: /* Fall through */
8445: case 6:
8446: DECR_AND_LOAD(23);
8447: /* Fall through */
8448: case 5:
8449: DECR_AND_LOAD(22);
8450: /* Fall through */
8451: case 4:
8452: DECR_AND_LOAD(21);
8453: /* Fall through */
8454: case 3:
8455: DECR_AND_LOAD(20);
8456: /* Fall through */
8457: case 2:
8458: DECR_AND_LOAD(19);
8459: /* Fall through */
8460: case 1:
8461: DECR_AND_LOAD(18);
8462: }
8463:
8464: if (do_s1) {
8465: DECR_AND_LOAD(17);
8466: }
8467: if (do_s0) {
8468: DECR_AND_LOAD(16);
8469: }
8470:
8471: switch (aregs) {
8472: case 0:
8473: case 4:
8474: case 8:
8475: case 12:
8476: case 14:
8477: astatic = 0;
8478: break;
8479: case 1:
8480: case 5:
8481: case 9:
8482: case 13:
8483: astatic = 1;
8484: break;
8485: case 2:
8486: case 6:
8487: case 10:
8488: astatic = 2;
8489: break;
8490: case 3:
8491: case 7:
8492: astatic = 3;
8493: break;
8494: case 11:
8495: astatic = 4;
8496: break;
8497: default:
8498: generate_exception(ctx, EXCP_RI);
8499: return;
8500: }
8501:
8502: if (astatic > 0) {
8503: DECR_AND_LOAD(7);
8504: if (astatic > 1) {
8505: DECR_AND_LOAD(6);
8506: if (astatic > 2) {
8507: DECR_AND_LOAD(5);
8508: if (astatic > 3) {
8509: DECR_AND_LOAD(4);
8510: }
8511: }
8512: }
8513: }
8514: #undef DECR_AND_LOAD
8515:
8516: tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8517: tcg_temp_free(t0);
8518: tcg_temp_free(t1);
8519: }
8520:
8521: static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8522: int is_64_bit, int extended)
8523: {
8524: TCGv t0;
8525:
8526: if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8527: generate_exception(ctx, EXCP_RI);
8528: return;
8529: }
8530:
8531: t0 = tcg_temp_new();
8532:
8533: tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8534: tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8535: if (!is_64_bit) {
8536: tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8537: }
8538:
8539: tcg_temp_free(t0);
8540: }
8541:
8542: #if defined(TARGET_MIPS64)
8543: static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
8544: int ry, int funct, int16_t offset,
8545: int extended)
8546: {
8547: switch (funct) {
8548: case I64_LDSP:
8549: check_mips_64(ctx);
8550: offset = extended ? offset : offset << 3;
8551: gen_ld(env, ctx, OPC_LD, ry, 29, offset);
8552: break;
8553: case I64_SDSP:
8554: check_mips_64(ctx);
8555: offset = extended ? offset : offset << 3;
8556: gen_st(ctx, OPC_SD, ry, 29, offset);
8557: break;
8558: case I64_SDRASP:
8559: check_mips_64(ctx);
8560: offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8561: gen_st(ctx, OPC_SD, 31, 29, offset);
8562: break;
8563: case I64_DADJSP:
8564: check_mips_64(ctx);
8565: offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8566: gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8567: break;
8568: case I64_LDPC:
8569: if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8570: generate_exception(ctx, EXCP_RI);
8571: } else {
8572: offset = extended ? offset : offset << 3;
8573: gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
8574: }
8575: break;
8576: case I64_DADDIU5:
8577: check_mips_64(ctx);
8578: offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8579: gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8580: break;
8581: case I64_DADDIUPC:
8582: check_mips_64(ctx);
8583: offset = extended ? offset : offset << 2;
8584: gen_addiupc(ctx, ry, offset, 1, extended);
8585: break;
8586: case I64_DADDIUSP:
8587: check_mips_64(ctx);
8588: offset = extended ? offset : offset << 2;
8589: gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8590: break;
8591: }
8592: }
8593: #endif
8594:
8595: static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8596: int *is_branch)
8597: {
8598: int extend = lduw_code(ctx->pc + 2);
8599: int op, rx, ry, funct, sa;
8600: int16_t imm, offset;
8601:
8602: ctx->opcode = (ctx->opcode << 16) | extend;
8603: op = (ctx->opcode >> 11) & 0x1f;
8604: sa = (ctx->opcode >> 22) & 0x1f;
8605: funct = (ctx->opcode >> 8) & 0x7;
8606: rx = xlat((ctx->opcode >> 8) & 0x7);
8607: ry = xlat((ctx->opcode >> 5) & 0x7);
8608: offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8609: | ((ctx->opcode >> 21) & 0x3f) << 5
8610: | (ctx->opcode & 0x1f));
8611:
8612: /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8613: counterparts. */
8614: switch (op) {
8615: case M16_OPC_ADDIUSP:
8616: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8617: break;
8618: case M16_OPC_ADDIUPC:
8619: gen_addiupc(ctx, rx, imm, 0, 1);
8620: break;
8621: case M16_OPC_B:
8622: gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8623: /* No delay slot, so just process as a normal instruction */
8624: break;
8625: case M16_OPC_BEQZ:
8626: gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8627: /* No delay slot, so just process as a normal instruction */
8628: break;
8629: case M16_OPC_BNEQZ:
8630: gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8631: /* No delay slot, so just process as a normal instruction */
8632: break;
8633: case M16_OPC_SHIFT:
8634: switch (ctx->opcode & 0x3) {
8635: case 0x0:
8636: gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8637: break;
8638: case 0x1:
8639: #if defined(TARGET_MIPS64)
8640: check_mips_64(ctx);
8641: gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8642: #else
8643: generate_exception(ctx, EXCP_RI);
8644: #endif
8645: break;
8646: case 0x2:
8647: gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8648: break;
8649: case 0x3:
8650: gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8651: break;
8652: }
8653: break;
8654: #if defined(TARGET_MIPS64)
8655: case M16_OPC_LD:
8656: check_mips_64(ctx);
8657: gen_ld(env, ctx, OPC_LD, ry, rx, offset);
8658: break;
8659: #endif
8660: case M16_OPC_RRIA:
8661: imm = ctx->opcode & 0xf;
8662: imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8663: imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8664: imm = (int16_t) (imm << 1) >> 1;
8665: if ((ctx->opcode >> 4) & 0x1) {
8666: #if defined(TARGET_MIPS64)
8667: check_mips_64(ctx);
8668: gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8669: #else
8670: generate_exception(ctx, EXCP_RI);
8671: #endif
8672: } else {
8673: gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8674: }
8675: break;
8676: case M16_OPC_ADDIU8:
8677: gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8678: break;
8679: case M16_OPC_SLTI:
8680: gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8681: break;
8682: case M16_OPC_SLTIU:
8683: gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8684: break;
8685: case M16_OPC_I8:
8686: switch (funct) {
8687: case I8_BTEQZ:
8688: gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8689: break;
8690: case I8_BTNEZ:
8691: gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8692: break;
8693: case I8_SWRASP:
8694: gen_st(ctx, OPC_SW, 31, 29, imm);
8695: break;
8696: case I8_ADJSP:
8697: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8698: break;
8699: case I8_SVRS:
8700: {
8701: int xsregs = (ctx->opcode >> 24) & 0x7;
8702: int aregs = (ctx->opcode >> 16) & 0xf;
8703: int do_ra = (ctx->opcode >> 6) & 0x1;
8704: int do_s0 = (ctx->opcode >> 5) & 0x1;
8705: int do_s1 = (ctx->opcode >> 4) & 0x1;
8706: int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8707: | (ctx->opcode & 0xf)) << 3;
8708:
8709: if (ctx->opcode & (1 << 7)) {
8710: gen_mips16_save(ctx, xsregs, aregs,
8711: do_ra, do_s0, do_s1,
8712: framesize);
8713: } else {
8714: gen_mips16_restore(ctx, xsregs, aregs,
8715: do_ra, do_s0, do_s1,
8716: framesize);
8717: }
8718: }
8719: break;
8720: default:
8721: generate_exception(ctx, EXCP_RI);
8722: break;
8723: }
8724: break;
8725: case M16_OPC_LI:
8726: tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8727: break;
8728: case M16_OPC_CMPI:
8729: tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8730: break;
8731: #if defined(TARGET_MIPS64)
8732: case M16_OPC_SD:
8733: gen_st(ctx, OPC_SD, ry, rx, offset);
8734: break;
8735: #endif
8736: case M16_OPC_LB:
8737: gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8738: break;
8739: case M16_OPC_LH:
8740: gen_ld(env, ctx, OPC_LH, ry, rx, offset);
8741: break;
8742: case M16_OPC_LWSP:
8743: gen_ld(env, ctx, OPC_LW, rx, 29, offset);
8744: break;
8745: case M16_OPC_LW:
8746: gen_ld(env, ctx, OPC_LW, ry, rx, offset);
8747: break;
8748: case M16_OPC_LBU:
8749: gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
8750: break;
8751: case M16_OPC_LHU:
8752: gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
8753: break;
8754: case M16_OPC_LWPC:
8755: gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
8756: break;
8757: #if defined(TARGET_MIPS64)
8758: case M16_OPC_LWU:
8759: gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
8760: break;
8761: #endif
8762: case M16_OPC_SB:
8763: gen_st(ctx, OPC_SB, ry, rx, offset);
8764: break;
8765: case M16_OPC_SH:
8766: gen_st(ctx, OPC_SH, ry, rx, offset);
8767: break;
8768: case M16_OPC_SWSP:
8769: gen_st(ctx, OPC_SW, rx, 29, offset);
8770: break;
8771: case M16_OPC_SW:
8772: gen_st(ctx, OPC_SW, ry, rx, offset);
8773: break;
8774: #if defined(TARGET_MIPS64)
8775: case M16_OPC_I64:
8776: decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8777: break;
8778: #endif
8779: default:
8780: generate_exception(ctx, EXCP_RI);
8781: break;
8782: }
8783:
8784: return 4;
8785: }
8786:
8787: static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8788: int *is_branch)
8789: {
8790: int rx, ry;
8791: int sa;
8792: int op, cnvt_op, op1, offset;
8793: int funct;
8794: int n_bytes;
8795:
8796: op = (ctx->opcode >> 11) & 0x1f;
8797: sa = (ctx->opcode >> 2) & 0x7;
8798: sa = sa == 0 ? 8 : sa;
8799: rx = xlat((ctx->opcode >> 8) & 0x7);
8800: cnvt_op = (ctx->opcode >> 5) & 0x7;
8801: ry = xlat((ctx->opcode >> 5) & 0x7);
8802: op1 = offset = ctx->opcode & 0x1f;
8803:
8804: n_bytes = 2;
8805:
8806: switch (op) {
8807: case M16_OPC_ADDIUSP:
8808: {
8809: int16_t imm = ((uint8_t) ctx->opcode) << 2;
8810:
8811: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8812: }
8813: break;
8814: case M16_OPC_ADDIUPC:
8815: gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8816: break;
8817: case M16_OPC_B:
8818: offset = (ctx->opcode & 0x7ff) << 1;
8819: offset = (int16_t)(offset << 4) >> 4;
8820: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8821: /* No delay slot, so just process as a normal instruction */
8822: break;
8823: case M16_OPC_JAL:
8824: offset = lduw_code(ctx->pc + 2);
8825: offset = (((ctx->opcode & 0x1f) << 21)
8826: | ((ctx->opcode >> 5) & 0x1f) << 16
8827: | offset) << 2;
8828: op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
8829: gen_compute_branch(ctx, op, 4, rx, ry, offset);
8830: n_bytes = 4;
8831: *is_branch = 1;
8832: break;
8833: case M16_OPC_BEQZ:
8834: gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8835: /* No delay slot, so just process as a normal instruction */
8836: break;
8837: case M16_OPC_BNEQZ:
8838: gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8839: /* No delay slot, so just process as a normal instruction */
8840: break;
8841: case M16_OPC_SHIFT:
8842: switch (ctx->opcode & 0x3) {
8843: case 0x0:
8844: gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8845: break;
8846: case 0x1:
8847: #if defined(TARGET_MIPS64)
8848: check_mips_64(ctx);
8849: gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8850: #else
8851: generate_exception(ctx, EXCP_RI);
8852: #endif
8853: break;
8854: case 0x2:
8855: gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8856: break;
8857: case 0x3:
8858: gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8859: break;
8860: }
8861: break;
8862: #if defined(TARGET_MIPS64)
8863: case M16_OPC_LD:
8864: check_mips_64(ctx);
8865: gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
8866: break;
8867: #endif
8868: case M16_OPC_RRIA:
8869: {
8870: int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8871:
8872: if ((ctx->opcode >> 4) & 1) {
8873: #if defined(TARGET_MIPS64)
8874: check_mips_64(ctx);
8875: gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8876: #else
8877: generate_exception(ctx, EXCP_RI);
8878: #endif
8879: } else {
8880: gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8881: }
8882: }
8883: break;
8884: case M16_OPC_ADDIU8:
8885: {
8886: int16_t imm = (int8_t) ctx->opcode;
8887:
8888: gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8889: }
8890: break;
8891: case M16_OPC_SLTI:
8892: {
8893: int16_t imm = (uint8_t) ctx->opcode;
8894:
8895: gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8896: }
8897: break;
8898: case M16_OPC_SLTIU:
8899: {
8900: int16_t imm = (uint8_t) ctx->opcode;
8901:
8902: gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8903: }
8904: break;
8905: case M16_OPC_I8:
8906: {
8907: int reg32;
8908:
8909: funct = (ctx->opcode >> 8) & 0x7;
8910: switch (funct) {
8911: case I8_BTEQZ:
8912: gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8913: ((int8_t)ctx->opcode) << 1);
8914: break;
8915: case I8_BTNEZ:
8916: gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8917: ((int8_t)ctx->opcode) << 1);
8918: break;
8919: case I8_SWRASP:
8920: gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
8921: break;
8922: case I8_ADJSP:
8923: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
8924: ((int8_t)ctx->opcode) << 3);
8925: break;
8926: case I8_SVRS:
8927: {
8928: int do_ra = ctx->opcode & (1 << 6);
8929: int do_s0 = ctx->opcode & (1 << 5);
8930: int do_s1 = ctx->opcode & (1 << 4);
8931: int framesize = ctx->opcode & 0xf;
8932:
8933: if (framesize == 0) {
8934: framesize = 128;
8935: } else {
8936: framesize = framesize << 3;
8937: }
8938:
8939: if (ctx->opcode & (1 << 7)) {
8940: gen_mips16_save(ctx, 0, 0,
8941: do_ra, do_s0, do_s1, framesize);
8942: } else {
8943: gen_mips16_restore(ctx, 0, 0,
8944: do_ra, do_s0, do_s1, framesize);
8945: }
8946: }
8947: break;
8948: case I8_MOV32R:
8949: {
8950: int rz = xlat(ctx->opcode & 0x7);
8951:
8952: reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
8953: ((ctx->opcode >> 5) & 0x7);
8954: gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
8955: }
8956: break;
8957: case I8_MOVR32:
8958: reg32 = ctx->opcode & 0x1f;
8959: gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
8960: break;
8961: default:
8962: generate_exception(ctx, EXCP_RI);
8963: break;
8964: }
8965: }
8966: break;
8967: case M16_OPC_LI:
8968: {
8969: int16_t imm = (uint8_t) ctx->opcode;
8970:
8971: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
8972: }
8973: break;
8974: case M16_OPC_CMPI:
8975: {
8976: int16_t imm = (uint8_t) ctx->opcode;
8977:
8978: gen_logic_imm(env, OPC_XORI, 24, rx, imm);
8979: }
8980: break;
8981: #if defined(TARGET_MIPS64)
8982: case M16_OPC_SD:
8983: check_mips_64(ctx);
8984: gen_st(ctx, OPC_SD, ry, rx, offset << 3);
8985: break;
8986: #endif
8987: case M16_OPC_LB:
8988: gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8989: break;
8990: case M16_OPC_LH:
8991: gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
8992: break;
8993: case M16_OPC_LWSP:
8994: gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8995: break;
8996: case M16_OPC_LW:
8997: gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
8998: break;
8999: case M16_OPC_LBU:
9000: gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
9001: break;
9002: case M16_OPC_LHU:
9003: gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
9004: break;
9005: case M16_OPC_LWPC:
9006: gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
9007: break;
9008: #if defined (TARGET_MIPS64)
9009: case M16_OPC_LWU:
9010: check_mips_64(ctx);
9011: gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
9012: break;
9013: #endif
9014: case M16_OPC_SB:
9015: gen_st(ctx, OPC_SB, ry, rx, offset);
9016: break;
9017: case M16_OPC_SH:
9018: gen_st(ctx, OPC_SH, ry, rx, offset << 1);
9019: break;
9020: case M16_OPC_SWSP:
9021: gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9022: break;
9023: case M16_OPC_SW:
9024: gen_st(ctx, OPC_SW, ry, rx, offset << 2);
9025: break;
9026: case M16_OPC_RRR:
9027: {
9028: int rz = xlat((ctx->opcode >> 2) & 0x7);
9029: int mips32_op;
9030:
9031: switch (ctx->opcode & 0x3) {
9032: case RRR_ADDU:
9033: mips32_op = OPC_ADDU;
9034: break;
9035: case RRR_SUBU:
9036: mips32_op = OPC_SUBU;
9037: break;
9038: #if defined(TARGET_MIPS64)
9039: case RRR_DADDU:
9040: mips32_op = OPC_DADDU;
9041: check_mips_64(ctx);
9042: break;
9043: case RRR_DSUBU:
9044: mips32_op = OPC_DSUBU;
9045: check_mips_64(ctx);
9046: break;
9047: #endif
9048: default:
9049: generate_exception(ctx, EXCP_RI);
9050: goto done;
9051: }
9052:
9053: gen_arith(env, ctx, mips32_op, rz, rx, ry);
9054: done:
9055: ;
9056: }
9057: break;
9058: case M16_OPC_RR:
9059: switch (op1) {
9060: case RR_JR:
9061: {
9062: int nd = (ctx->opcode >> 7) & 0x1;
9063: int link = (ctx->opcode >> 6) & 0x1;
9064: int ra = (ctx->opcode >> 5) & 0x1;
9065:
9066: if (link) {
9067: op = nd ? OPC_JALRC : OPC_JALRS;
9068: } else {
9069: op = OPC_JR;
9070: }
9071:
9072: gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9073: if (!nd) {
9074: *is_branch = 1;
9075: }
9076: }
9077: break;
9078: case RR_SDBBP:
9079: /* XXX: not clear which exception should be raised
9080: * when in debug mode...
9081: */
9082: check_insn(env, ctx, ISA_MIPS32);
9083: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9084: generate_exception(ctx, EXCP_DBp);
9085: } else {
9086: generate_exception(ctx, EXCP_DBp);
9087: }
9088: break;
9089: case RR_SLT:
9090: gen_slt(env, OPC_SLT, 24, rx, ry);
9091: break;
9092: case RR_SLTU:
9093: gen_slt(env, OPC_SLTU, 24, rx, ry);
9094: break;
9095: case RR_BREAK:
9096: generate_exception(ctx, EXCP_BREAK);
9097: break;
9098: case RR_SLLV:
9099: gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9100: break;
9101: case RR_SRLV:
9102: gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9103: break;
9104: case RR_SRAV:
9105: gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9106: break;
9107: #if defined (TARGET_MIPS64)
9108: case RR_DSRL:
9109: check_mips_64(ctx);
9110: gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9111: break;
9112: #endif
9113: case RR_CMP:
9114: gen_logic(env, OPC_XOR, 24, rx, ry);
9115: break;
9116: case RR_NEG:
9117: gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9118: break;
9119: case RR_AND:
9120: gen_logic(env, OPC_AND, rx, rx, ry);
9121: break;
9122: case RR_OR:
9123: gen_logic(env, OPC_OR, rx, rx, ry);
9124: break;
9125: case RR_XOR:
9126: gen_logic(env, OPC_XOR, rx, rx, ry);
9127: break;
9128: case RR_NOT:
9129: gen_logic(env, OPC_NOR, rx, ry, 0);
9130: break;
9131: case RR_MFHI:
9132: gen_HILO(ctx, OPC_MFHI, rx);
9133: break;
9134: case RR_CNVT:
9135: switch (cnvt_op) {
9136: case RR_RY_CNVT_ZEB:
9137: tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9138: break;
9139: case RR_RY_CNVT_ZEH:
9140: tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9141: break;
9142: case RR_RY_CNVT_SEB:
9143: tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9144: break;
9145: case RR_RY_CNVT_SEH:
9146: tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9147: break;
9148: #if defined (TARGET_MIPS64)
9149: case RR_RY_CNVT_ZEW:
9150: check_mips_64(ctx);
9151: tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9152: break;
9153: case RR_RY_CNVT_SEW:
9154: check_mips_64(ctx);
9155: tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9156: break;
9157: #endif
9158: default:
9159: generate_exception(ctx, EXCP_RI);
9160: break;
9161: }
9162: break;
9163: case RR_MFLO:
9164: gen_HILO(ctx, OPC_MFLO, rx);
9165: break;
9166: #if defined (TARGET_MIPS64)
9167: case RR_DSRA:
9168: check_mips_64(ctx);
9169: gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9170: break;
9171: case RR_DSLLV:
9172: check_mips_64(ctx);
9173: gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9174: break;
9175: case RR_DSRLV:
9176: check_mips_64(ctx);
9177: gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9178: break;
9179: case RR_DSRAV:
9180: check_mips_64(ctx);
9181: gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9182: break;
9183: #endif
9184: case RR_MULT:
9185: gen_muldiv(ctx, OPC_MULT, rx, ry);
9186: break;
9187: case RR_MULTU:
9188: gen_muldiv(ctx, OPC_MULTU, rx, ry);
9189: break;
9190: case RR_DIV:
9191: gen_muldiv(ctx, OPC_DIV, rx, ry);
9192: break;
9193: case RR_DIVU:
9194: gen_muldiv(ctx, OPC_DIVU, rx, ry);
9195: break;
9196: #if defined (TARGET_MIPS64)
9197: case RR_DMULT:
9198: check_mips_64(ctx);
9199: gen_muldiv(ctx, OPC_DMULT, rx, ry);
9200: break;
9201: case RR_DMULTU:
9202: check_mips_64(ctx);
9203: gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9204: break;
9205: case RR_DDIV:
9206: check_mips_64(ctx);
9207: gen_muldiv(ctx, OPC_DDIV, rx, ry);
9208: break;
9209: case RR_DDIVU:
9210: check_mips_64(ctx);
9211: gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9212: break;
9213: #endif
9214: default:
9215: generate_exception(ctx, EXCP_RI);
9216: break;
9217: }
9218: break;
9219: case M16_OPC_EXTEND:
9220: decode_extended_mips16_opc(env, ctx, is_branch);
9221: n_bytes = 4;
9222: break;
9223: #if defined(TARGET_MIPS64)
9224: case M16_OPC_I64:
9225: funct = (ctx->opcode >> 8) & 0x7;
9226: decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9227: break;
9228: #endif
9229: default:
9230: generate_exception(ctx, EXCP_RI);
9231: break;
9232: }
9233:
9234: return n_bytes;
9235: }
9236:
9237: /* microMIPS extension to MIPS32 */
9238:
9239: /* microMIPS32 major opcodes */
9240:
9241: enum {
9242: POOL32A = 0x00,
9243: POOL16A = 0x01,
9244: LBU16 = 0x02,
9245: MOVE16 = 0x03,
9246: ADDI32 = 0x04,
9247: LBU32 = 0x05,
9248: SB32 = 0x06,
9249: LB32 = 0x07,
9250:
9251: POOL32B = 0x08,
9252: POOL16B = 0x09,
9253: LHU16 = 0x0a,
9254: ANDI16 = 0x0b,
9255: ADDIU32 = 0x0c,
9256: LHU32 = 0x0d,
9257: SH32 = 0x0e,
9258: LH32 = 0x0f,
9259:
9260: POOL32I = 0x10,
9261: POOL16C = 0x11,
9262: LWSP16 = 0x12,
9263: POOL16D = 0x13,
9264: ORI32 = 0x14,
9265: POOL32F = 0x15,
9266: POOL32S = 0x16,
9267: DADDIU32 = 0x17,
9268:
9269: POOL32C = 0x18,
9270: LWGP16 = 0x19,
9271: LW16 = 0x1a,
9272: POOL16E = 0x1b,
9273: XORI32 = 0x1c,
9274: JALS32 = 0x1d,
9275: ADDIUPC = 0x1e,
9276: POOL48A = 0x1f,
9277:
9278: /* 0x20 is reserved */
9279: RES_20 = 0x20,
9280: POOL16F = 0x21,
9281: SB16 = 0x22,
9282: BEQZ16 = 0x23,
9283: SLTI32 = 0x24,
9284: BEQ32 = 0x25,
9285: SWC132 = 0x26,
9286: LWC132 = 0x27,
9287:
9288: /* 0x28 and 0x29 are reserved */
9289: RES_28 = 0x28,
9290: RES_29 = 0x29,
9291: SH16 = 0x2a,
9292: BNEZ16 = 0x2b,
9293: SLTIU32 = 0x2c,
9294: BNE32 = 0x2d,
9295: SDC132 = 0x2e,
9296: LDC132 = 0x2f,
9297:
9298: /* 0x30 and 0x31 are reserved */
9299: RES_30 = 0x30,
9300: RES_31 = 0x31,
9301: SWSP16 = 0x32,
9302: B16 = 0x33,
9303: ANDI32 = 0x34,
9304: J32 = 0x35,
9305: SD32 = 0x36,
9306: LD32 = 0x37,
9307:
9308: /* 0x38 and 0x39 are reserved */
9309: RES_38 = 0x38,
9310: RES_39 = 0x39,
9311: SW16 = 0x3a,
9312: LI16 = 0x3b,
9313: JALX32 = 0x3c,
9314: JAL32 = 0x3d,
9315: SW32 = 0x3e,
9316: LW32 = 0x3f
9317: };
9318:
9319: /* POOL32A encoding of minor opcode field */
9320:
9321: enum {
9322: /* These opcodes are distinguished only by bits 9..6; those bits are
9323: * what are recorded below. */
9324: SLL32 = 0x0,
9325: SRL32 = 0x1,
9326: SRA = 0x2,
9327: ROTR = 0x3,
9328:
9329: SLLV = 0x0,
9330: SRLV = 0x1,
9331: SRAV = 0x2,
9332: ROTRV = 0x3,
9333: ADD = 0x4,
9334: ADDU32 = 0x5,
9335: SUB = 0x6,
9336: SUBU32 = 0x7,
9337: MUL = 0x8,
9338: AND = 0x9,
9339: OR32 = 0xa,
9340: NOR = 0xb,
9341: XOR32 = 0xc,
9342: SLT = 0xd,
9343: SLTU = 0xe,
9344:
9345: MOVN = 0x0,
9346: MOVZ = 0x1,
9347: LWXS = 0x4,
9348:
9349: /* The following can be distinguished by their lower 6 bits. */
9350: INS = 0x0c,
9351: EXT = 0x2c,
9352: POOL32AXF = 0x3c
9353: };
9354:
9355: /* POOL32AXF encoding of minor opcode field extension */
9356:
9357: enum {
9358: /* bits 11..6 */
9359: TEQ = 0x00,
9360: TGE = 0x08,
9361: TGEU = 0x10,
9362: TLT = 0x20,
9363: TLTU = 0x28,
9364: TNE = 0x30,
9365:
9366: MFC0 = 0x03,
9367: MTC0 = 0x0b,
9368:
9369: /* bits 13..12 for 0x01 */
9370: MFHI_ACC = 0x0,
9371: MFLO_ACC = 0x1,
9372: MTHI_ACC = 0x2,
9373: MTLO_ACC = 0x3,
9374:
9375: /* bits 13..12 for 0x2a */
9376: MADD_ACC = 0x0,
9377: MADDU_ACC = 0x1,
9378: MSUB_ACC = 0x2,
9379: MSUBU_ACC = 0x3,
9380:
9381: /* bits 13..12 for 0x32 */
9382: MULT_ACC = 0x0,
9383: MULTU_ACC = 0x0,
9384:
9385: /* bits 15..12 for 0x2c */
9386: SEB = 0x2,
9387: SEH = 0x3,
9388: CLO = 0x4,
9389: CLZ = 0x5,
9390: RDHWR = 0x6,
9391: WSBH = 0x7,
9392: MULT = 0x8,
9393: MULTU = 0x9,
9394: DIV = 0xa,
9395: DIVU = 0xb,
9396: MADD = 0xc,
9397: MADDU = 0xd,
9398: MSUB = 0xe,
9399: MSUBU = 0xf,
9400:
9401: /* bits 15..12 for 0x34 */
9402: MFC2 = 0x4,
9403: MTC2 = 0x5,
9404: MFHC2 = 0x8,
9405: MTHC2 = 0x9,
9406: CFC2 = 0xc,
9407: CTC2 = 0xd,
9408:
9409: /* bits 15..12 for 0x3c */
9410: JALR = 0x0,
9411: JR = 0x0, /* alias */
9412: JALR_HB = 0x1,
9413: JALRS = 0x4,
9414: JALRS_HB = 0x5,
9415:
9416: /* bits 15..12 for 0x05 */
9417: RDPGPR = 0xe,
9418: WRPGPR = 0xf,
9419:
9420: /* bits 15..12 for 0x0d */
9421: TLBP = 0x0,
9422: TLBR = 0x1,
9423: TLBWI = 0x2,
9424: TLBWR = 0x3,
9425: WAIT = 0x9,
9426: IRET = 0xd,
9427: DERET = 0xe,
9428: ERET = 0xf,
9429:
9430: /* bits 15..12 for 0x15 */
9431: DMT = 0x0,
9432: DVPE = 0x1,
9433: EMT = 0x2,
9434: EVPE = 0x3,
9435:
9436: /* bits 15..12 for 0x1d */
9437: DI = 0x4,
9438: EI = 0x5,
9439:
9440: /* bits 15..12 for 0x2d */
9441: SYNC = 0x6,
9442: SYSCALL = 0x8,
9443: SDBBP = 0xd,
9444:
9445: /* bits 15..12 for 0x35 */
9446: MFHI32 = 0x0,
9447: MFLO32 = 0x1,
9448: MTHI32 = 0x2,
9449: MTLO32 = 0x3,
9450: };
9451:
9452: /* POOL32B encoding of minor opcode field (bits 15..12) */
9453:
9454: enum {
9455: LWC2 = 0x0,
9456: LWP = 0x1,
9457: LDP = 0x4,
9458: LWM32 = 0x5,
9459: CACHE = 0x6,
9460: LDM = 0x7,
9461: SWC2 = 0x8,
9462: SWP = 0x9,
9463: SDP = 0xc,
9464: SWM32 = 0xd,
9465: SDM = 0xf
9466: };
9467:
9468: /* POOL32C encoding of minor opcode field (bits 15..12) */
9469:
9470: enum {
9471: LWL = 0x0,
9472: SWL = 0x8,
9473: LWR = 0x1,
9474: SWR = 0x9,
9475: PREF = 0x2,
9476: /* 0xa is reserved */
9477: LL = 0x3,
9478: SC = 0xb,
9479: LDL = 0x4,
9480: SDL = 0xc,
9481: LDR = 0x5,
9482: SDR = 0xd,
9483: /* 0x6 is reserved */
9484: LWU = 0xe,
9485: LLD = 0x7,
9486: SCD = 0xf
9487: };
9488:
9489: /* POOL32F encoding of minor opcode field (bits 5..0) */
9490:
9491: enum {
9492: /* These are the bit 7..6 values */
9493: ADD_FMT = 0x0,
9494: MOVN_FMT = 0x0,
9495:
9496: SUB_FMT = 0x1,
9497: MOVZ_FMT = 0x1,
9498:
9499: MUL_FMT = 0x2,
9500:
9501: DIV_FMT = 0x3,
9502:
9503: /* These are the bit 8..6 values */
9504: RSQRT2_FMT = 0x0,
9505: MOVF_FMT = 0x0,
9506:
9507: LWXC1 = 0x1,
9508: MOVT_FMT = 0x1,
9509:
9510: PLL_PS = 0x2,
9511: SWXC1 = 0x2,
9512:
9513: PLU_PS = 0x3,
9514: LDXC1 = 0x3,
9515:
9516: PUL_PS = 0x4,
9517: SDXC1 = 0x4,
9518: RECIP2_FMT = 0x4,
9519:
9520: PUU_PS = 0x5,
9521: LUXC1 = 0x5,
9522:
9523: CVT_PS_S = 0x6,
9524: SUXC1 = 0x6,
9525: ADDR_PS = 0x6,
9526: PREFX = 0x6,
9527:
9528: MULR_PS = 0x7,
9529:
9530: MADD_S = 0x01,
9531: MADD_D = 0x09,
9532: MADD_PS = 0x11,
9533: ALNV_PS = 0x19,
9534: MSUB_S = 0x21,
9535: MSUB_D = 0x29,
9536: MSUB_PS = 0x31,
9537:
9538: NMADD_S = 0x02,
9539: NMADD_D = 0x0a,
9540: NMADD_PS = 0x12,
9541: NMSUB_S = 0x22,
9542: NMSUB_D = 0x2a,
9543: NMSUB_PS = 0x32,
9544:
9545: POOL32FXF = 0x3b,
9546:
9547: CABS_COND_FMT = 0x1c, /* MIPS3D */
9548: C_COND_FMT = 0x3c
9549: };
9550:
9551: /* POOL32Fxf encoding of minor opcode extension field */
9552:
9553: enum {
9554: CVT_L = 0x04,
9555: RSQRT_FMT = 0x08,
9556: FLOOR_L = 0x0c,
9557: CVT_PW_PS = 0x1c,
9558: CVT_W = 0x24,
9559: SQRT_FMT = 0x28,
9560: FLOOR_W = 0x2c,
9561: CVT_PS_PW = 0x3c,
9562: CFC1 = 0x40,
9563: RECIP_FMT = 0x48,
9564: CEIL_L = 0x4c,
9565: CTC1 = 0x60,
9566: CEIL_W = 0x6c,
9567: MFC1 = 0x80,
9568: CVT_S_PL = 0x84,
9569: TRUNC_L = 0x8c,
9570: MTC1 = 0xa0,
9571: CVT_S_PU = 0xa4,
9572: TRUNC_W = 0xac,
9573: MFHC1 = 0xc0,
9574: ROUND_L = 0xcc,
9575: MTHC1 = 0xe0,
9576: ROUND_W = 0xec,
9577:
9578: MOV_FMT = 0x01,
9579: MOVF = 0x05,
9580: ABS_FMT = 0x0d,
9581: RSQRT1_FMT = 0x1d,
9582: MOVT = 0x25,
9583: NEG_FMT = 0x2d,
9584: CVT_D = 0x4d,
9585: RECIP1_FMT = 0x5d,
9586: CVT_S = 0x6d
9587: };
9588:
9589: /* POOL32I encoding of minor opcode field (bits 25..21) */
9590:
9591: enum {
9592: BLTZ = 0x00,
9593: BLTZAL = 0x01,
9594: BGEZ = 0x02,
9595: BGEZAL = 0x03,
9596: BLEZ = 0x04,
9597: BNEZC = 0x05,
9598: BGTZ = 0x06,
9599: BEQZC = 0x07,
9600: TLTI = 0x08,
9601: TGEI = 0x09,
9602: TLTIU = 0x0a,
9603: TGEIU = 0x0b,
9604: TNEI = 0x0c,
9605: LUI = 0x0d,
9606: TEQI = 0x0e,
9607: SYNCI = 0x10,
9608: BLTZALS = 0x11,
9609: BGEZALS = 0x13,
9610: BC2F = 0x14,
9611: BC2T = 0x15,
9612: BPOSGE64 = 0x1a,
9613: BPOSGE32 = 0x1b,
9614: /* These overlap and are distinguished by bit16 of the instruction */
9615: BC1F = 0x1c,
9616: BC1T = 0x1d,
9617: BC1ANY2F = 0x1c,
9618: BC1ANY2T = 0x1d,
9619: BC1ANY4F = 0x1e,
9620: BC1ANY4T = 0x1f
9621: };
9622:
9623: /* POOL16A encoding of minor opcode field */
9624:
9625: enum {
9626: ADDU16 = 0x0,
9627: SUBU16 = 0x1
9628: };
9629:
9630: /* POOL16B encoding of minor opcode field */
9631:
9632: enum {
9633: SLL16 = 0x0,
9634: SRL16 = 0x1
9635: };
9636:
9637: /* POOL16C encoding of minor opcode field */
9638:
9639: enum {
9640: NOT16 = 0x00,
9641: XOR16 = 0x04,
9642: AND16 = 0x08,
9643: OR16 = 0x0c,
9644: LWM16 = 0x10,
9645: SWM16 = 0x14,
9646: JR16 = 0x18,
9647: JRC16 = 0x1a,
9648: JALR16 = 0x1c,
9649: JALR16S = 0x1e,
9650: MFHI16 = 0x20,
9651: MFLO16 = 0x24,
9652: BREAK16 = 0x28,
9653: SDBBP16 = 0x2c,
9654: JRADDIUSP = 0x30
9655: };
9656:
9657: /* POOL16D encoding of minor opcode field */
9658:
9659: enum {
9660: ADDIUS5 = 0x0,
9661: ADDIUSP = 0x1
9662: };
9663:
9664: /* POOL16E encoding of minor opcode field */
9665:
9666: enum {
9667: ADDIUR2 = 0x0,
9668: ADDIUR1SP = 0x1
9669: };
9670:
9671: static int mmreg (int r)
9672: {
9673: static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9674:
9675: return map[r];
9676: }
9677:
9678: /* Used for 16-bit store instructions. */
9679: static int mmreg2 (int r)
9680: {
9681: static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
9682:
9683: return map[r];
9684: }
9685:
9686: #define uMIPS_RD(op) ((op >> 7) & 0x7)
9687: #define uMIPS_RS(op) ((op >> 4) & 0x7)
9688: #define uMIPS_RS2(op) uMIPS_RS(op)
9689: #define uMIPS_RS1(op) ((op >> 1) & 0x7)
9690: #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
9691: #define uMIPS_RS5(op) (op & 0x1f)
9692:
9693: /* Signed immediate */
9694: #define SIMM(op, start, width) \
9695: ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
9696: << (32-width)) \
9697: >> (32-width))
9698: /* Zero-extended immediate */
9699: #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
9700:
9701: static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
9702: {
9703: int rd = mmreg(uMIPS_RD(ctx->opcode));
9704:
9705: gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
9706: }
9707:
9708: static void gen_addiur2 (CPUState *env, DisasContext *ctx)
9709: {
9710: static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
9711: int rd = mmreg(uMIPS_RD(ctx->opcode));
9712: int rs = mmreg(uMIPS_RS(ctx->opcode));
9713:
9714: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
9715: }
9716:
9717: static void gen_addiusp (CPUState *env, DisasContext *ctx)
9718: {
9719: int encoded = ZIMM(ctx->opcode, 1, 9);
9720: int decoded;
9721:
9722: if (encoded <= 1) {
9723: decoded = 256 + encoded;
9724: } else if (encoded <= 255) {
9725: decoded = encoded;
9726: } else if (encoded <= 509) {
9727: decoded = encoded - 512;
9728: } else {
9729: decoded = encoded - 768;
9730: }
9731:
9732: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
9733: }
9734:
9735: static void gen_addius5 (CPUState *env, DisasContext *ctx)
9736: {
9737: int imm = SIMM(ctx->opcode, 1, 4);
9738: int rd = (ctx->opcode >> 5) & 0x1f;
9739:
9740: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
9741: }
9742:
9743: static void gen_andi16 (CPUState *env, DisasContext *ctx)
9744: {
9745: static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
9746: 31, 32, 63, 64, 255, 32768, 65535 };
9747: int rd = mmreg(uMIPS_RD(ctx->opcode));
9748: int rs = mmreg(uMIPS_RS(ctx->opcode));
9749: int encoded = ZIMM(ctx->opcode, 0, 4);
9750:
9751: gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
9752: }
9753:
9754: static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
9755: int base, int16_t offset)
9756: {
9757: TCGv t0, t1;
9758: TCGv_i32 t2;
9759:
9760: if (ctx->hflags & MIPS_HFLAG_BMASK) {
9761: generate_exception(ctx, EXCP_RI);
9762: return;
9763: }
9764:
9765: t0 = tcg_temp_new();
9766:
9767: gen_base_offset_addr(ctx, t0, base, offset);
9768:
9769: t1 = tcg_const_tl(reglist);
9770: t2 = tcg_const_i32(ctx->mem_idx);
9771:
9772: save_cpu_state(ctx, 1);
9773: switch (opc) {
9774: case LWM32:
9775: gen_helper_lwm(t0, t1, t2);
9776: break;
9777: case SWM32:
9778: gen_helper_swm(t0, t1, t2);
9779: break;
9780: #ifdef TARGET_MIPS64
9781: case LDM:
9782: gen_helper_ldm(t0, t1, t2);
9783: break;
9784: case SDM:
9785: gen_helper_sdm(t0, t1, t2);
9786: break;
9787: #endif
9788: }
9789: MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
9790: tcg_temp_free(t0);
9791: tcg_temp_free(t1);
9792: tcg_temp_free_i32(t2);
9793: }
9794:
9795:
9796: static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
9797: {
9798: int rd = mmreg((ctx->opcode >> 3) & 0x7);
9799: int rs = mmreg(ctx->opcode & 0x7);
9800: int opc;
9801:
9802: switch (((ctx->opcode) >> 4) & 0x3f) {
9803: case NOT16 + 0:
9804: case NOT16 + 1:
9805: case NOT16 + 2:
9806: case NOT16 + 3:
9807: gen_logic(env, OPC_NOR, rd, rs, 0);
9808: break;
9809: case XOR16 + 0:
9810: case XOR16 + 1:
9811: case XOR16 + 2:
9812: case XOR16 + 3:
9813: gen_logic(env, OPC_XOR, rd, rd, rs);
9814: break;
9815: case AND16 + 0:
9816: case AND16 + 1:
9817: case AND16 + 2:
9818: case AND16 + 3:
9819: gen_logic(env, OPC_AND, rd, rd, rs);
9820: break;
9821: case OR16 + 0:
9822: case OR16 + 1:
9823: case OR16 + 2:
9824: case OR16 + 3:
9825: gen_logic(env, OPC_OR, rd, rd, rs);
9826: break;
9827: case LWM16 + 0:
9828: case LWM16 + 1:
9829: case LWM16 + 2:
9830: case LWM16 + 3:
9831: {
9832: static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9833: int offset = ZIMM(ctx->opcode, 0, 4);
9834:
9835: gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
9836: 29, offset << 2);
9837: }
9838: break;
9839: case SWM16 + 0:
9840: case SWM16 + 1:
9841: case SWM16 + 2:
9842: case SWM16 + 3:
9843: {
9844: static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9845: int offset = ZIMM(ctx->opcode, 0, 4);
9846:
9847: gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
9848: 29, offset << 2);
9849: }
9850: break;
9851: case JR16 + 0:
9852: case JR16 + 1:
9853: {
9854: int reg = ctx->opcode & 0x1f;
9855:
9856: gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9857: }
9858: *is_branch = 1;
9859: break;
9860: case JRC16 + 0:
9861: case JRC16 + 1:
9862: {
9863: int reg = ctx->opcode & 0x1f;
9864:
9865: gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9866: /* Let normal delay slot handling in our caller take us
9867: to the branch target. */
9868: }
9869: break;
9870: case JALR16 + 0:
9871: case JALR16 + 1:
9872: opc = OPC_JALR;
9873: goto do_jalr;
9874: case JALR16S + 0:
9875: case JALR16S + 1:
9876: opc = OPC_JALRS;
9877: do_jalr:
9878: {
9879: int reg = ctx->opcode & 0x1f;
9880:
9881: gen_compute_branch(ctx, opc, 2, reg, 31, 0);
9882: }
9883: *is_branch = 1;
9884: break;
9885: case MFHI16 + 0:
9886: case MFHI16 + 1:
9887: gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
9888: break;
9889: case MFLO16 + 0:
9890: case MFLO16 + 1:
9891: gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
9892: break;
9893: case BREAK16:
9894: generate_exception(ctx, EXCP_BREAK);
9895: break;
9896: case SDBBP16:
9897: /* XXX: not clear which exception should be raised
9898: * when in debug mode...
9899: */
9900: check_insn(env, ctx, ISA_MIPS32);
9901: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9902: generate_exception(ctx, EXCP_DBp);
9903: } else {
9904: generate_exception(ctx, EXCP_DBp);
9905: }
9906: break;
9907: case JRADDIUSP + 0:
9908: case JRADDIUSP + 1:
9909: {
9910: int imm = ZIMM(ctx->opcode, 0, 5);
9911:
9912: gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
9913: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
9914: /* Let normal delay slot handling in our caller take us
9915: to the branch target. */
9916: }
9917: break;
9918: default:
9919: generate_exception(ctx, EXCP_RI);
9920: break;
9921: }
9922: }
9923:
9924: static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
9925: {
9926: TCGv t0 = tcg_temp_new();
9927: TCGv t1 = tcg_temp_new();
9928:
9929: gen_load_gpr(t0, base);
9930:
9931: if (index != 0) {
9932: gen_load_gpr(t1, index);
9933: tcg_gen_shli_tl(t1, t1, 2);
9934: gen_op_addr_add(ctx, t0, t1, t0);
9935: }
9936:
9937: save_cpu_state(ctx, 0);
9938: op_ld_lw(t1, t0, ctx);
9939: gen_store_gpr(t1, rd);
9940:
9941: tcg_temp_free(t0);
9942: tcg_temp_free(t1);
9943: }
9944:
9945: static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
9946: int base, int16_t offset)
9947: {
9948: const char *opn = "ldst_pair";
9949: TCGv t0, t1;
9950:
9951: if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
9952: generate_exception(ctx, EXCP_RI);
9953: return;
9954: }
9955:
9956: t0 = tcg_temp_new();
9957: t1 = tcg_temp_new();
9958:
9959: gen_base_offset_addr(ctx, t0, base, offset);
9960:
9961: switch (opc) {
9962: case LWP:
9963: save_cpu_state(ctx, 0);
9964: op_ld_lw(t1, t0, ctx);
9965: gen_store_gpr(t1, rd);
9966: tcg_gen_movi_tl(t1, 4);
9967: gen_op_addr_add(ctx, t0, t0, t1);
9968: op_ld_lw(t1, t0, ctx);
9969: gen_store_gpr(t1, rd+1);
9970: opn = "lwp";
9971: break;
9972: case SWP:
1.1.1.13 root 9973: save_cpu_state(ctx, 0);
1.1.1.12 root 9974: gen_load_gpr(t1, rd);
9975: op_st_sw(t1, t0, ctx);
9976: tcg_gen_movi_tl(t1, 4);
9977: gen_op_addr_add(ctx, t0, t0, t1);
9978: gen_load_gpr(t1, rd+1);
9979: op_st_sw(t1, t0, ctx);
9980: opn = "swp";
9981: break;
9982: #ifdef TARGET_MIPS64
9983: case LDP:
9984: save_cpu_state(ctx, 0);
9985: op_ld_ld(t1, t0, ctx);
9986: gen_store_gpr(t1, rd);
9987: tcg_gen_movi_tl(t1, 8);
9988: gen_op_addr_add(ctx, t0, t0, t1);
9989: op_ld_ld(t1, t0, ctx);
9990: gen_store_gpr(t1, rd+1);
9991: opn = "ldp";
9992: break;
9993: case SDP:
1.1.1.13 root 9994: save_cpu_state(ctx, 0);
1.1.1.12 root 9995: gen_load_gpr(t1, rd);
9996: op_st_sd(t1, t0, ctx);
9997: tcg_gen_movi_tl(t1, 8);
9998: gen_op_addr_add(ctx, t0, t0, t1);
9999: gen_load_gpr(t1, rd+1);
10000: op_st_sd(t1, t0, ctx);
10001: opn = "sdp";
10002: break;
10003: #endif
10004: }
1.1.1.13 root 10005: (void)opn; /* avoid a compiler warning */
1.1.1.12 root 10006: MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10007: tcg_temp_free(t0);
10008: tcg_temp_free(t1);
10009: }
10010:
10011: static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
10012: int *is_branch)
10013: {
10014: int extension = (ctx->opcode >> 6) & 0x3f;
10015: int minor = (ctx->opcode >> 12) & 0xf;
10016: uint32_t mips32_op;
10017:
10018: switch (extension) {
10019: case TEQ:
10020: mips32_op = OPC_TEQ;
10021: goto do_trap;
10022: case TGE:
10023: mips32_op = OPC_TGE;
10024: goto do_trap;
10025: case TGEU:
10026: mips32_op = OPC_TGEU;
10027: goto do_trap;
10028: case TLT:
10029: mips32_op = OPC_TLT;
10030: goto do_trap;
10031: case TLTU:
10032: mips32_op = OPC_TLTU;
10033: goto do_trap;
10034: case TNE:
10035: mips32_op = OPC_TNE;
10036: do_trap:
10037: gen_trap(ctx, mips32_op, rs, rt, -1);
10038: break;
10039: #ifndef CONFIG_USER_ONLY
10040: case MFC0:
10041: case MFC0 + 32:
10042: if (rt == 0) {
10043: /* Treat as NOP. */
10044: break;
10045: }
10046: gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10047: break;
10048: case MTC0:
10049: case MTC0 + 32:
10050: {
10051: TCGv t0 = tcg_temp_new();
10052:
10053: gen_load_gpr(t0, rt);
10054: gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10055: tcg_temp_free(t0);
10056: }
10057: break;
10058: #endif
10059: case 0x2c:
10060: switch (minor) {
10061: case SEB:
10062: gen_bshfl(ctx, OPC_SEB, rs, rt);
10063: break;
10064: case SEH:
10065: gen_bshfl(ctx, OPC_SEH, rs, rt);
10066: break;
10067: case CLO:
10068: mips32_op = OPC_CLO;
10069: goto do_cl;
10070: case CLZ:
10071: mips32_op = OPC_CLZ;
10072: do_cl:
10073: check_insn(env, ctx, ISA_MIPS32);
10074: gen_cl(ctx, mips32_op, rt, rs);
10075: break;
10076: case RDHWR:
10077: gen_rdhwr(env, ctx, rt, rs);
10078: break;
10079: case WSBH:
10080: gen_bshfl(ctx, OPC_WSBH, rs, rt);
10081: break;
10082: case MULT:
10083: mips32_op = OPC_MULT;
10084: goto do_muldiv;
10085: case MULTU:
10086: mips32_op = OPC_MULTU;
10087: goto do_muldiv;
10088: case DIV:
10089: mips32_op = OPC_DIV;
10090: goto do_muldiv;
10091: case DIVU:
10092: mips32_op = OPC_DIVU;
10093: goto do_muldiv;
10094: case MADD:
10095: mips32_op = OPC_MADD;
10096: goto do_muldiv;
10097: case MADDU:
10098: mips32_op = OPC_MADDU;
10099: goto do_muldiv;
10100: case MSUB:
10101: mips32_op = OPC_MSUB;
10102: goto do_muldiv;
10103: case MSUBU:
10104: mips32_op = OPC_MSUBU;
10105: do_muldiv:
10106: check_insn(env, ctx, ISA_MIPS32);
10107: gen_muldiv(ctx, mips32_op, rs, rt);
10108: break;
10109: default:
10110: goto pool32axf_invalid;
10111: }
10112: break;
10113: case 0x34:
10114: switch (minor) {
10115: case MFC2:
10116: case MTC2:
10117: case MFHC2:
10118: case MTHC2:
10119: case CFC2:
10120: case CTC2:
10121: generate_exception_err(ctx, EXCP_CpU, 2);
10122: break;
10123: default:
10124: goto pool32axf_invalid;
10125: }
10126: break;
10127: case 0x3c:
10128: switch (minor) {
10129: case JALR:
10130: case JALR_HB:
10131: gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10132: *is_branch = 1;
10133: break;
10134: case JALRS:
10135: case JALRS_HB:
10136: gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10137: *is_branch = 1;
10138: break;
10139: default:
10140: goto pool32axf_invalid;
10141: }
10142: break;
10143: case 0x05:
10144: switch (minor) {
10145: case RDPGPR:
10146: check_insn(env, ctx, ISA_MIPS32R2);
10147: gen_load_srsgpr(rt, rs);
10148: break;
10149: case WRPGPR:
10150: check_insn(env, ctx, ISA_MIPS32R2);
10151: gen_store_srsgpr(rt, rs);
10152: break;
10153: default:
10154: goto pool32axf_invalid;
10155: }
10156: break;
10157: #ifndef CONFIG_USER_ONLY
10158: case 0x0d:
10159: switch (minor) {
10160: case TLBP:
10161: mips32_op = OPC_TLBP;
10162: goto do_cp0;
10163: case TLBR:
10164: mips32_op = OPC_TLBR;
10165: goto do_cp0;
10166: case TLBWI:
10167: mips32_op = OPC_TLBWI;
10168: goto do_cp0;
10169: case TLBWR:
10170: mips32_op = OPC_TLBWR;
10171: goto do_cp0;
10172: case WAIT:
10173: mips32_op = OPC_WAIT;
10174: goto do_cp0;
10175: case DERET:
10176: mips32_op = OPC_DERET;
10177: goto do_cp0;
10178: case ERET:
10179: mips32_op = OPC_ERET;
10180: do_cp0:
10181: gen_cp0(env, ctx, mips32_op, rt, rs);
10182: break;
10183: default:
10184: goto pool32axf_invalid;
10185: }
10186: break;
10187: case 0x1d:
10188: switch (minor) {
10189: case DI:
10190: {
10191: TCGv t0 = tcg_temp_new();
10192:
10193: save_cpu_state(ctx, 1);
10194: gen_helper_di(t0);
10195: gen_store_gpr(t0, rs);
10196: /* Stop translation as we may have switched the execution mode */
10197: ctx->bstate = BS_STOP;
10198: tcg_temp_free(t0);
10199: }
10200: break;
10201: case EI:
10202: {
10203: TCGv t0 = tcg_temp_new();
10204:
10205: save_cpu_state(ctx, 1);
10206: gen_helper_ei(t0);
10207: gen_store_gpr(t0, rs);
10208: /* Stop translation as we may have switched the execution mode */
10209: ctx->bstate = BS_STOP;
10210: tcg_temp_free(t0);
10211: }
10212: break;
10213: default:
10214: goto pool32axf_invalid;
10215: }
10216: break;
10217: #endif
10218: case 0x2d:
10219: switch (minor) {
10220: case SYNC:
10221: /* NOP */
10222: break;
10223: case SYSCALL:
10224: generate_exception(ctx, EXCP_SYSCALL);
10225: ctx->bstate = BS_STOP;
10226: break;
10227: case SDBBP:
10228: check_insn(env, ctx, ISA_MIPS32);
10229: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10230: generate_exception(ctx, EXCP_DBp);
10231: } else {
10232: generate_exception(ctx, EXCP_DBp);
10233: }
10234: break;
10235: default:
10236: goto pool32axf_invalid;
10237: }
10238: break;
10239: case 0x35:
10240: switch (minor) {
10241: case MFHI32:
10242: gen_HILO(ctx, OPC_MFHI, rs);
10243: break;
10244: case MFLO32:
10245: gen_HILO(ctx, OPC_MFLO, rs);
10246: break;
10247: case MTHI32:
10248: gen_HILO(ctx, OPC_MTHI, rs);
10249: break;
10250: case MTLO32:
10251: gen_HILO(ctx, OPC_MTLO, rs);
10252: break;
10253: default:
10254: goto pool32axf_invalid;
10255: }
10256: break;
10257: default:
10258: pool32axf_invalid:
10259: MIPS_INVAL("pool32axf");
10260: generate_exception(ctx, EXCP_RI);
10261: break;
10262: }
10263: }
10264:
10265: /* Values for microMIPS fmt field. Variable-width, depending on which
10266: formats the instruction supports. */
10267:
10268: enum {
10269: FMT_SD_S = 0,
10270: FMT_SD_D = 1,
10271:
10272: FMT_SDPS_S = 0,
10273: FMT_SDPS_D = 1,
10274: FMT_SDPS_PS = 2,
10275:
10276: FMT_SWL_S = 0,
10277: FMT_SWL_W = 1,
10278: FMT_SWL_L = 2,
10279:
10280: FMT_DWL_D = 0,
10281: FMT_DWL_W = 1,
10282: FMT_DWL_L = 2
10283: };
10284:
10285: static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
10286: {
10287: int extension = (ctx->opcode >> 6) & 0x3ff;
10288: uint32_t mips32_op;
10289:
10290: #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10291: #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10292: #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10293:
10294: switch (extension) {
10295: case FLOAT_1BIT_FMT(CFC1, 0):
10296: mips32_op = OPC_CFC1;
10297: goto do_cp1;
10298: case FLOAT_1BIT_FMT(CTC1, 0):
10299: mips32_op = OPC_CTC1;
10300: goto do_cp1;
10301: case FLOAT_1BIT_FMT(MFC1, 0):
10302: mips32_op = OPC_MFC1;
10303: goto do_cp1;
10304: case FLOAT_1BIT_FMT(MTC1, 0):
10305: mips32_op = OPC_MTC1;
10306: goto do_cp1;
10307: case FLOAT_1BIT_FMT(MFHC1, 0):
10308: mips32_op = OPC_MFHC1;
10309: goto do_cp1;
10310: case FLOAT_1BIT_FMT(MTHC1, 0):
10311: mips32_op = OPC_MTHC1;
10312: do_cp1:
10313: gen_cp1(ctx, mips32_op, rt, rs);
10314: break;
10315:
10316: /* Reciprocal square root */
10317: case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10318: mips32_op = OPC_RSQRT_S;
10319: goto do_unaryfp;
10320: case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10321: mips32_op = OPC_RSQRT_D;
10322: goto do_unaryfp;
10323:
10324: /* Square root */
10325: case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10326: mips32_op = OPC_SQRT_S;
10327: goto do_unaryfp;
10328: case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10329: mips32_op = OPC_SQRT_D;
10330: goto do_unaryfp;
10331:
10332: /* Reciprocal */
10333: case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10334: mips32_op = OPC_RECIP_S;
10335: goto do_unaryfp;
10336: case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10337: mips32_op = OPC_RECIP_D;
10338: goto do_unaryfp;
10339:
10340: /* Floor */
10341: case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10342: mips32_op = OPC_FLOOR_L_S;
10343: goto do_unaryfp;
10344: case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10345: mips32_op = OPC_FLOOR_L_D;
10346: goto do_unaryfp;
10347: case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10348: mips32_op = OPC_FLOOR_W_S;
10349: goto do_unaryfp;
10350: case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10351: mips32_op = OPC_FLOOR_W_D;
10352: goto do_unaryfp;
10353:
10354: /* Ceiling */
10355: case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10356: mips32_op = OPC_CEIL_L_S;
10357: goto do_unaryfp;
10358: case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10359: mips32_op = OPC_CEIL_L_D;
10360: goto do_unaryfp;
10361: case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10362: mips32_op = OPC_CEIL_W_S;
10363: goto do_unaryfp;
10364: case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10365: mips32_op = OPC_CEIL_W_D;
10366: goto do_unaryfp;
10367:
10368: /* Truncation */
10369: case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10370: mips32_op = OPC_TRUNC_L_S;
10371: goto do_unaryfp;
10372: case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10373: mips32_op = OPC_TRUNC_L_D;
10374: goto do_unaryfp;
10375: case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10376: mips32_op = OPC_TRUNC_W_S;
10377: goto do_unaryfp;
10378: case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10379: mips32_op = OPC_TRUNC_W_D;
10380: goto do_unaryfp;
10381:
10382: /* Round */
10383: case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10384: mips32_op = OPC_ROUND_L_S;
10385: goto do_unaryfp;
10386: case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10387: mips32_op = OPC_ROUND_L_D;
10388: goto do_unaryfp;
10389: case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10390: mips32_op = OPC_ROUND_W_S;
10391: goto do_unaryfp;
10392: case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10393: mips32_op = OPC_ROUND_W_D;
10394: goto do_unaryfp;
10395:
10396: /* Integer to floating-point conversion */
10397: case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10398: mips32_op = OPC_CVT_L_S;
10399: goto do_unaryfp;
10400: case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10401: mips32_op = OPC_CVT_L_D;
10402: goto do_unaryfp;
10403: case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10404: mips32_op = OPC_CVT_W_S;
10405: goto do_unaryfp;
10406: case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10407: mips32_op = OPC_CVT_W_D;
10408: goto do_unaryfp;
10409:
10410: /* Paired-foo conversions */
10411: case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10412: mips32_op = OPC_CVT_S_PL;
10413: goto do_unaryfp;
10414: case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10415: mips32_op = OPC_CVT_S_PU;
10416: goto do_unaryfp;
10417: case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10418: mips32_op = OPC_CVT_PW_PS;
10419: goto do_unaryfp;
10420: case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10421: mips32_op = OPC_CVT_PS_PW;
10422: goto do_unaryfp;
10423:
10424: /* Floating-point moves */
10425: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10426: mips32_op = OPC_MOV_S;
10427: goto do_unaryfp;
10428: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10429: mips32_op = OPC_MOV_D;
10430: goto do_unaryfp;
10431: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10432: mips32_op = OPC_MOV_PS;
10433: goto do_unaryfp;
10434:
10435: /* Absolute value */
10436: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10437: mips32_op = OPC_ABS_S;
10438: goto do_unaryfp;
10439: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10440: mips32_op = OPC_ABS_D;
10441: goto do_unaryfp;
10442: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10443: mips32_op = OPC_ABS_PS;
10444: goto do_unaryfp;
10445:
10446: /* Negation */
10447: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10448: mips32_op = OPC_NEG_S;
10449: goto do_unaryfp;
10450: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10451: mips32_op = OPC_NEG_D;
10452: goto do_unaryfp;
10453: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10454: mips32_op = OPC_NEG_PS;
10455: goto do_unaryfp;
10456:
10457: /* Reciprocal square root step */
10458: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10459: mips32_op = OPC_RSQRT1_S;
10460: goto do_unaryfp;
10461: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10462: mips32_op = OPC_RSQRT1_D;
10463: goto do_unaryfp;
10464: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10465: mips32_op = OPC_RSQRT1_PS;
10466: goto do_unaryfp;
10467:
10468: /* Reciprocal step */
10469: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10470: mips32_op = OPC_RECIP1_S;
10471: goto do_unaryfp;
10472: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10473: mips32_op = OPC_RECIP1_S;
10474: goto do_unaryfp;
10475: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10476: mips32_op = OPC_RECIP1_PS;
10477: goto do_unaryfp;
10478:
10479: /* Conversions from double */
10480: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10481: mips32_op = OPC_CVT_D_S;
10482: goto do_unaryfp;
10483: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10484: mips32_op = OPC_CVT_D_W;
10485: goto do_unaryfp;
10486: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10487: mips32_op = OPC_CVT_D_L;
10488: goto do_unaryfp;
10489:
10490: /* Conversions from single */
10491: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10492: mips32_op = OPC_CVT_S_D;
10493: goto do_unaryfp;
10494: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10495: mips32_op = OPC_CVT_S_W;
10496: goto do_unaryfp;
10497: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10498: mips32_op = OPC_CVT_S_L;
10499: do_unaryfp:
10500: gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10501: break;
10502:
10503: /* Conditional moves on floating-point codes */
10504: case COND_FLOAT_MOV(MOVT, 0):
10505: case COND_FLOAT_MOV(MOVT, 1):
10506: case COND_FLOAT_MOV(MOVT, 2):
10507: case COND_FLOAT_MOV(MOVT, 3):
10508: case COND_FLOAT_MOV(MOVT, 4):
10509: case COND_FLOAT_MOV(MOVT, 5):
10510: case COND_FLOAT_MOV(MOVT, 6):
10511: case COND_FLOAT_MOV(MOVT, 7):
10512: gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
10513: break;
10514: case COND_FLOAT_MOV(MOVF, 0):
10515: case COND_FLOAT_MOV(MOVF, 1):
10516: case COND_FLOAT_MOV(MOVF, 2):
10517: case COND_FLOAT_MOV(MOVF, 3):
10518: case COND_FLOAT_MOV(MOVF, 4):
10519: case COND_FLOAT_MOV(MOVF, 5):
10520: case COND_FLOAT_MOV(MOVF, 6):
10521: case COND_FLOAT_MOV(MOVF, 7):
10522: gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
10523: break;
10524: default:
10525: MIPS_INVAL("pool32fxf");
10526: generate_exception(ctx, EXCP_RI);
10527: break;
10528: }
10529: }
10530:
10531: static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
10532: uint16_t insn_hw1, int *is_branch)
10533: {
10534: int32_t offset;
10535: uint16_t insn;
10536: int rt, rs, rd, rr;
10537: int16_t imm;
10538: uint32_t op, minor, mips32_op;
10539: uint32_t cond, fmt, cc;
10540:
10541: insn = lduw_code(ctx->pc + 2);
10542: ctx->opcode = (ctx->opcode << 16) | insn;
10543:
10544: rt = (ctx->opcode >> 21) & 0x1f;
10545: rs = (ctx->opcode >> 16) & 0x1f;
10546: rd = (ctx->opcode >> 11) & 0x1f;
10547: rr = (ctx->opcode >> 6) & 0x1f;
10548: imm = (int16_t) ctx->opcode;
10549:
10550: op = (ctx->opcode >> 26) & 0x3f;
10551: switch (op) {
10552: case POOL32A:
10553: minor = ctx->opcode & 0x3f;
10554: switch (minor) {
10555: case 0x00:
10556: minor = (ctx->opcode >> 6) & 0xf;
10557: switch (minor) {
10558: case SLL32:
10559: mips32_op = OPC_SLL;
10560: goto do_shifti;
10561: case SRA:
10562: mips32_op = OPC_SRA;
10563: goto do_shifti;
10564: case SRL32:
10565: mips32_op = OPC_SRL;
10566: goto do_shifti;
10567: case ROTR:
10568: mips32_op = OPC_ROTR;
10569: do_shifti:
10570: gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
10571: break;
10572: default:
10573: goto pool32a_invalid;
10574: }
10575: break;
10576: case 0x10:
10577: minor = (ctx->opcode >> 6) & 0xf;
10578: switch (minor) {
10579: /* Arithmetic */
10580: case ADD:
10581: mips32_op = OPC_ADD;
10582: goto do_arith;
10583: case ADDU32:
10584: mips32_op = OPC_ADDU;
10585: goto do_arith;
10586: case SUB:
10587: mips32_op = OPC_SUB;
10588: goto do_arith;
10589: case SUBU32:
10590: mips32_op = OPC_SUBU;
10591: goto do_arith;
10592: case MUL:
10593: mips32_op = OPC_MUL;
10594: do_arith:
10595: gen_arith(env, ctx, mips32_op, rd, rs, rt);
10596: break;
10597: /* Shifts */
10598: case SLLV:
10599: mips32_op = OPC_SLLV;
10600: goto do_shift;
10601: case SRLV:
10602: mips32_op = OPC_SRLV;
10603: goto do_shift;
10604: case SRAV:
10605: mips32_op = OPC_SRAV;
10606: goto do_shift;
10607: case ROTRV:
10608: mips32_op = OPC_ROTRV;
10609: do_shift:
10610: gen_shift(env, ctx, mips32_op, rd, rs, rt);
10611: break;
10612: /* Logical operations */
10613: case AND:
10614: mips32_op = OPC_AND;
10615: goto do_logic;
10616: case OR32:
10617: mips32_op = OPC_OR;
10618: goto do_logic;
10619: case NOR:
10620: mips32_op = OPC_NOR;
10621: goto do_logic;
10622: case XOR32:
10623: mips32_op = OPC_XOR;
10624: do_logic:
10625: gen_logic(env, mips32_op, rd, rs, rt);
10626: break;
10627: /* Set less than */
10628: case SLT:
10629: mips32_op = OPC_SLT;
10630: goto do_slt;
10631: case SLTU:
10632: mips32_op = OPC_SLTU;
10633: do_slt:
10634: gen_slt(env, mips32_op, rd, rs, rt);
10635: break;
10636: default:
10637: goto pool32a_invalid;
10638: }
10639: break;
10640: case 0x18:
10641: minor = (ctx->opcode >> 6) & 0xf;
10642: switch (minor) {
10643: /* Conditional moves */
10644: case MOVN:
10645: mips32_op = OPC_MOVN;
10646: goto do_cmov;
10647: case MOVZ:
10648: mips32_op = OPC_MOVZ;
10649: do_cmov:
10650: gen_cond_move(env, mips32_op, rd, rs, rt);
10651: break;
10652: case LWXS:
10653: gen_ldxs(ctx, rs, rt, rd);
10654: break;
10655: default:
10656: goto pool32a_invalid;
10657: }
10658: break;
10659: case INS:
10660: gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
10661: return;
10662: case EXT:
10663: gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
10664: return;
10665: case POOL32AXF:
10666: gen_pool32axf(env, ctx, rt, rs, is_branch);
10667: break;
10668: case 0x07:
10669: generate_exception(ctx, EXCP_BREAK);
10670: break;
10671: default:
10672: pool32a_invalid:
10673: MIPS_INVAL("pool32a");
10674: generate_exception(ctx, EXCP_RI);
10675: break;
10676: }
10677: break;
10678: case POOL32B:
10679: minor = (ctx->opcode >> 12) & 0xf;
10680: switch (minor) {
10681: case CACHE:
10682: /* Treat as no-op. */
10683: break;
10684: case LWC2:
10685: case SWC2:
10686: /* COP2: Not implemented. */
10687: generate_exception_err(ctx, EXCP_CpU, 2);
10688: break;
10689: case LWP:
10690: case SWP:
10691: #ifdef TARGET_MIPS64
10692: case LDP:
10693: case SDP:
10694: #endif
10695: gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10696: break;
10697: case LWM32:
10698: case SWM32:
10699: #ifdef TARGET_MIPS64
10700: case LDM:
10701: case SDM:
10702: #endif
10703: gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10704: break;
10705: default:
10706: MIPS_INVAL("pool32b");
10707: generate_exception(ctx, EXCP_RI);
10708: break;
10709: }
10710: break;
10711: case POOL32F:
10712: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
10713: minor = ctx->opcode & 0x3f;
10714: check_cp1_enabled(ctx);
10715: switch (minor) {
10716: case ALNV_PS:
10717: mips32_op = OPC_ALNV_PS;
10718: goto do_madd;
10719: case MADD_S:
10720: mips32_op = OPC_MADD_S;
10721: goto do_madd;
10722: case MADD_D:
10723: mips32_op = OPC_MADD_D;
10724: goto do_madd;
10725: case MADD_PS:
10726: mips32_op = OPC_MADD_PS;
10727: goto do_madd;
10728: case MSUB_S:
10729: mips32_op = OPC_MSUB_S;
10730: goto do_madd;
10731: case MSUB_D:
10732: mips32_op = OPC_MSUB_D;
10733: goto do_madd;
10734: case MSUB_PS:
10735: mips32_op = OPC_MSUB_PS;
10736: goto do_madd;
10737: case NMADD_S:
10738: mips32_op = OPC_NMADD_S;
10739: goto do_madd;
10740: case NMADD_D:
10741: mips32_op = OPC_NMADD_D;
10742: goto do_madd;
10743: case NMADD_PS:
10744: mips32_op = OPC_NMADD_PS;
10745: goto do_madd;
10746: case NMSUB_S:
10747: mips32_op = OPC_NMSUB_S;
10748: goto do_madd;
10749: case NMSUB_D:
10750: mips32_op = OPC_NMSUB_D;
10751: goto do_madd;
10752: case NMSUB_PS:
10753: mips32_op = OPC_NMSUB_PS;
10754: do_madd:
10755: gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
10756: break;
10757: case CABS_COND_FMT:
10758: cond = (ctx->opcode >> 6) & 0xf;
10759: cc = (ctx->opcode >> 13) & 0x7;
10760: fmt = (ctx->opcode >> 10) & 0x3;
10761: switch (fmt) {
10762: case 0x0:
10763: gen_cmpabs_s(ctx, cond, rt, rs, cc);
10764: break;
10765: case 0x1:
10766: gen_cmpabs_d(ctx, cond, rt, rs, cc);
10767: break;
10768: case 0x2:
10769: gen_cmpabs_ps(ctx, cond, rt, rs, cc);
10770: break;
10771: default:
10772: goto pool32f_invalid;
10773: }
10774: break;
10775: case C_COND_FMT:
10776: cond = (ctx->opcode >> 6) & 0xf;
10777: cc = (ctx->opcode >> 13) & 0x7;
10778: fmt = (ctx->opcode >> 10) & 0x3;
10779: switch (fmt) {
10780: case 0x0:
10781: gen_cmp_s(ctx, cond, rt, rs, cc);
10782: break;
10783: case 0x1:
10784: gen_cmp_d(ctx, cond, rt, rs, cc);
10785: break;
10786: case 0x2:
10787: gen_cmp_ps(ctx, cond, rt, rs, cc);
10788: break;
10789: default:
10790: goto pool32f_invalid;
10791: }
10792: break;
10793: case POOL32FXF:
10794: gen_pool32fxf(env, ctx, rt, rs);
10795: break;
10796: case 0x00:
10797: /* PLL foo */
10798: switch ((ctx->opcode >> 6) & 0x7) {
10799: case PLL_PS:
10800: mips32_op = OPC_PLL_PS;
10801: goto do_ps;
10802: case PLU_PS:
10803: mips32_op = OPC_PLU_PS;
10804: goto do_ps;
10805: case PUL_PS:
10806: mips32_op = OPC_PUL_PS;
10807: goto do_ps;
10808: case PUU_PS:
10809: mips32_op = OPC_PUU_PS;
10810: goto do_ps;
10811: case CVT_PS_S:
10812: mips32_op = OPC_CVT_PS_S;
10813: do_ps:
10814: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10815: break;
10816: default:
10817: goto pool32f_invalid;
10818: }
10819: break;
10820: case 0x08:
10821: /* [LS][WDU]XC1 */
10822: switch ((ctx->opcode >> 6) & 0x7) {
10823: case LWXC1:
10824: mips32_op = OPC_LWXC1;
10825: goto do_ldst_cp1;
10826: case SWXC1:
10827: mips32_op = OPC_SWXC1;
10828: goto do_ldst_cp1;
10829: case LDXC1:
10830: mips32_op = OPC_LDXC1;
10831: goto do_ldst_cp1;
10832: case SDXC1:
10833: mips32_op = OPC_SDXC1;
10834: goto do_ldst_cp1;
10835: case LUXC1:
10836: mips32_op = OPC_LUXC1;
10837: goto do_ldst_cp1;
10838: case SUXC1:
10839: mips32_op = OPC_SUXC1;
10840: do_ldst_cp1:
10841: gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
10842: break;
10843: default:
10844: goto pool32f_invalid;
10845: }
10846: break;
10847: case 0x18:
10848: /* 3D insns */
10849: fmt = (ctx->opcode >> 9) & 0x3;
10850: switch ((ctx->opcode >> 6) & 0x7) {
10851: case RSQRT2_FMT:
10852: switch (fmt) {
10853: case FMT_SDPS_S:
10854: mips32_op = OPC_RSQRT2_S;
10855: goto do_3d;
10856: case FMT_SDPS_D:
10857: mips32_op = OPC_RSQRT2_D;
10858: goto do_3d;
10859: case FMT_SDPS_PS:
10860: mips32_op = OPC_RSQRT2_PS;
10861: goto do_3d;
10862: default:
10863: goto pool32f_invalid;
10864: }
10865: break;
10866: case RECIP2_FMT:
10867: switch (fmt) {
10868: case FMT_SDPS_S:
10869: mips32_op = OPC_RECIP2_S;
10870: goto do_3d;
10871: case FMT_SDPS_D:
10872: mips32_op = OPC_RECIP2_D;
10873: goto do_3d;
10874: case FMT_SDPS_PS:
10875: mips32_op = OPC_RECIP2_PS;
10876: goto do_3d;
10877: default:
10878: goto pool32f_invalid;
10879: }
10880: break;
10881: case ADDR_PS:
10882: mips32_op = OPC_ADDR_PS;
10883: goto do_3d;
10884: case MULR_PS:
10885: mips32_op = OPC_MULR_PS;
10886: do_3d:
10887: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10888: break;
10889: default:
10890: goto pool32f_invalid;
10891: }
10892: break;
10893: case 0x20:
10894: /* MOV[FT].fmt and PREFX */
10895: cc = (ctx->opcode >> 13) & 0x7;
10896: fmt = (ctx->opcode >> 9) & 0x3;
10897: switch ((ctx->opcode >> 6) & 0x7) {
10898: case MOVF_FMT:
10899: switch (fmt) {
10900: case FMT_SDPS_S:
10901: gen_movcf_s(rs, rt, cc, 0);
10902: break;
10903: case FMT_SDPS_D:
10904: gen_movcf_d(ctx, rs, rt, cc, 0);
10905: break;
10906: case FMT_SDPS_PS:
10907: gen_movcf_ps(rs, rt, cc, 0);
10908: break;
10909: default:
10910: goto pool32f_invalid;
10911: }
10912: break;
10913: case MOVT_FMT:
10914: switch (fmt) {
10915: case FMT_SDPS_S:
10916: gen_movcf_s(rs, rt, cc, 1);
10917: break;
10918: case FMT_SDPS_D:
10919: gen_movcf_d(ctx, rs, rt, cc, 1);
10920: break;
10921: case FMT_SDPS_PS:
10922: gen_movcf_ps(rs, rt, cc, 1);
10923: break;
10924: default:
10925: goto pool32f_invalid;
10926: }
10927: break;
10928: case PREFX:
10929: break;
10930: default:
10931: goto pool32f_invalid;
10932: }
10933: break;
10934: #define FINSN_3ARG_SDPS(prfx) \
10935: switch ((ctx->opcode >> 8) & 0x3) { \
10936: case FMT_SDPS_S: \
10937: mips32_op = OPC_##prfx##_S; \
10938: goto do_fpop; \
10939: case FMT_SDPS_D: \
10940: mips32_op = OPC_##prfx##_D; \
10941: goto do_fpop; \
10942: case FMT_SDPS_PS: \
10943: mips32_op = OPC_##prfx##_PS; \
10944: goto do_fpop; \
10945: default: \
10946: goto pool32f_invalid; \
10947: }
10948: case 0x30:
10949: /* regular FP ops */
10950: switch ((ctx->opcode >> 6) & 0x3) {
10951: case ADD_FMT:
10952: FINSN_3ARG_SDPS(ADD);
10953: break;
10954: case SUB_FMT:
10955: FINSN_3ARG_SDPS(SUB);
10956: break;
10957: case MUL_FMT:
10958: FINSN_3ARG_SDPS(MUL);
10959: break;
10960: case DIV_FMT:
10961: fmt = (ctx->opcode >> 8) & 0x3;
10962: if (fmt == 1) {
10963: mips32_op = OPC_DIV_D;
10964: } else if (fmt == 0) {
10965: mips32_op = OPC_DIV_S;
10966: } else {
10967: goto pool32f_invalid;
10968: }
10969: goto do_fpop;
10970: default:
10971: goto pool32f_invalid;
10972: }
10973: break;
10974: case 0x38:
10975: /* cmovs */
10976: switch ((ctx->opcode >> 6) & 0x3) {
10977: case MOVN_FMT:
10978: FINSN_3ARG_SDPS(MOVN);
10979: break;
10980: case MOVZ_FMT:
10981: FINSN_3ARG_SDPS(MOVZ);
10982: break;
10983: default:
10984: goto pool32f_invalid;
10985: }
10986: break;
10987: do_fpop:
10988: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10989: break;
10990: default:
10991: pool32f_invalid:
10992: MIPS_INVAL("pool32f");
10993: generate_exception(ctx, EXCP_RI);
10994: break;
10995: }
10996: } else {
10997: generate_exception_err(ctx, EXCP_CpU, 1);
10998: }
10999: break;
11000: case POOL32I:
11001: minor = (ctx->opcode >> 21) & 0x1f;
11002: switch (minor) {
11003: case BLTZ:
11004: mips32_op = OPC_BLTZ;
11005: goto do_branch;
11006: case BLTZAL:
11007: mips32_op = OPC_BLTZAL;
11008: goto do_branch;
11009: case BLTZALS:
11010: mips32_op = OPC_BLTZALS;
11011: goto do_branch;
11012: case BGEZ:
11013: mips32_op = OPC_BGEZ;
11014: goto do_branch;
11015: case BGEZAL:
11016: mips32_op = OPC_BGEZAL;
11017: goto do_branch;
11018: case BGEZALS:
11019: mips32_op = OPC_BGEZALS;
11020: goto do_branch;
11021: case BLEZ:
11022: mips32_op = OPC_BLEZ;
11023: goto do_branch;
11024: case BGTZ:
11025: mips32_op = OPC_BGTZ;
11026: do_branch:
11027: gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11028: *is_branch = 1;
11029: break;
11030:
11031: /* Traps */
11032: case TLTI:
11033: mips32_op = OPC_TLTI;
11034: goto do_trapi;
11035: case TGEI:
11036: mips32_op = OPC_TGEI;
11037: goto do_trapi;
11038: case TLTIU:
11039: mips32_op = OPC_TLTIU;
11040: goto do_trapi;
11041: case TGEIU:
11042: mips32_op = OPC_TGEIU;
11043: goto do_trapi;
11044: case TNEI:
11045: mips32_op = OPC_TNEI;
11046: goto do_trapi;
11047: case TEQI:
11048: mips32_op = OPC_TEQI;
11049: do_trapi:
11050: gen_trap(ctx, mips32_op, rs, -1, imm);
11051: break;
11052:
11053: case BNEZC:
11054: case BEQZC:
11055: gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11056: 4, rs, 0, imm << 1);
11057: /* Compact branches don't have a delay slot, so just let
11058: the normal delay slot handling take us to the branch
11059: target. */
11060: break;
11061: case LUI:
11062: gen_logic_imm(env, OPC_LUI, rs, -1, imm);
11063: break;
11064: case SYNCI:
11065: break;
11066: case BC2F:
11067: case BC2T:
11068: /* COP2: Not implemented. */
11069: generate_exception_err(ctx, EXCP_CpU, 2);
11070: break;
11071: case BC1F:
11072: mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11073: goto do_cp1branch;
11074: case BC1T:
11075: mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11076: goto do_cp1branch;
11077: case BC1ANY4F:
11078: mips32_op = OPC_BC1FANY4;
11079: goto do_cp1mips3d;
11080: case BC1ANY4T:
11081: mips32_op = OPC_BC1TANY4;
11082: do_cp1mips3d:
11083: check_cop1x(ctx);
11084: check_insn(env, ctx, ASE_MIPS3D);
11085: /* Fall through */
11086: do_cp1branch:
11087: gen_compute_branch1(env, ctx, mips32_op,
11088: (ctx->opcode >> 18) & 0x7, imm << 1);
11089: *is_branch = 1;
11090: break;
11091: case BPOSGE64:
11092: case BPOSGE32:
11093: /* MIPS DSP: not implemented */
11094: /* Fall through */
11095: default:
11096: MIPS_INVAL("pool32i");
11097: generate_exception(ctx, EXCP_RI);
11098: break;
11099: }
11100: break;
11101: case POOL32C:
11102: minor = (ctx->opcode >> 12) & 0xf;
11103: switch (minor) {
11104: case LWL:
11105: mips32_op = OPC_LWL;
11106: goto do_ld_lr;
11107: case SWL:
11108: mips32_op = OPC_SWL;
11109: goto do_st_lr;
11110: case LWR:
11111: mips32_op = OPC_LWR;
11112: goto do_ld_lr;
11113: case SWR:
11114: mips32_op = OPC_SWR;
11115: goto do_st_lr;
11116: #if defined(TARGET_MIPS64)
11117: case LDL:
11118: mips32_op = OPC_LDL;
11119: goto do_ld_lr;
11120: case SDL:
11121: mips32_op = OPC_SDL;
11122: goto do_st_lr;
11123: case LDR:
11124: mips32_op = OPC_LDR;
11125: goto do_ld_lr;
11126: case SDR:
11127: mips32_op = OPC_SDR;
11128: goto do_st_lr;
11129: case LWU:
11130: mips32_op = OPC_LWU;
11131: goto do_ld_lr;
11132: case LLD:
11133: mips32_op = OPC_LLD;
11134: goto do_ld_lr;
11135: #endif
11136: case LL:
11137: mips32_op = OPC_LL;
11138: goto do_ld_lr;
11139: do_ld_lr:
11140: gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11141: break;
11142: do_st_lr:
11143: gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11144: break;
11145: case SC:
11146: gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11147: break;
11148: #if defined(TARGET_MIPS64)
11149: case SCD:
11150: gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11151: break;
11152: #endif
11153: case PREF:
11154: /* Treat as no-op */
11155: break;
11156: default:
11157: MIPS_INVAL("pool32c");
11158: generate_exception(ctx, EXCP_RI);
11159: break;
11160: }
11161: break;
11162: case ADDI32:
11163: mips32_op = OPC_ADDI;
11164: goto do_addi;
11165: case ADDIU32:
11166: mips32_op = OPC_ADDIU;
11167: do_addi:
11168: gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11169: break;
11170:
11171: /* Logical operations */
11172: case ORI32:
11173: mips32_op = OPC_ORI;
11174: goto do_logici;
11175: case XORI32:
11176: mips32_op = OPC_XORI;
11177: goto do_logici;
11178: case ANDI32:
11179: mips32_op = OPC_ANDI;
11180: do_logici:
11181: gen_logic_imm(env, mips32_op, rt, rs, imm);
11182: break;
11183:
11184: /* Set less than immediate */
11185: case SLTI32:
11186: mips32_op = OPC_SLTI;
11187: goto do_slti;
11188: case SLTIU32:
11189: mips32_op = OPC_SLTIU;
11190: do_slti:
11191: gen_slt_imm(env, mips32_op, rt, rs, imm);
11192: break;
11193: case JALX32:
11194: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11195: gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11196: *is_branch = 1;
11197: break;
11198: case JALS32:
11199: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11200: gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11201: *is_branch = 1;
11202: break;
11203: case BEQ32:
11204: gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11205: *is_branch = 1;
11206: break;
11207: case BNE32:
11208: gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11209: *is_branch = 1;
11210: break;
11211: case J32:
11212: gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11213: (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11214: *is_branch = 1;
11215: break;
11216: case JAL32:
11217: gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11218: (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11219: *is_branch = 1;
11220: break;
11221: /* Floating point (COP1) */
11222: case LWC132:
11223: mips32_op = OPC_LWC1;
11224: goto do_cop1;
11225: case LDC132:
11226: mips32_op = OPC_LDC1;
11227: goto do_cop1;
11228: case SWC132:
11229: mips32_op = OPC_SWC1;
11230: goto do_cop1;
11231: case SDC132:
11232: mips32_op = OPC_SDC1;
11233: do_cop1:
11234: gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11235: break;
11236: case ADDIUPC:
11237: {
11238: int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11239: int offset = SIMM(ctx->opcode, 0, 23) << 2;
11240:
11241: gen_addiupc(ctx, reg, offset, 0, 0);
11242: }
11243: break;
11244: /* Loads and stores */
11245: case LB32:
11246: mips32_op = OPC_LB;
11247: goto do_ld;
11248: case LBU32:
11249: mips32_op = OPC_LBU;
11250: goto do_ld;
11251: case LH32:
11252: mips32_op = OPC_LH;
11253: goto do_ld;
11254: case LHU32:
11255: mips32_op = OPC_LHU;
11256: goto do_ld;
11257: case LW32:
11258: mips32_op = OPC_LW;
11259: goto do_ld;
11260: #ifdef TARGET_MIPS64
11261: case LD32:
11262: mips32_op = OPC_LD;
11263: goto do_ld;
11264: case SD32:
11265: mips32_op = OPC_SD;
11266: goto do_st;
11267: #endif
11268: case SB32:
11269: mips32_op = OPC_SB;
11270: goto do_st;
11271: case SH32:
11272: mips32_op = OPC_SH;
11273: goto do_st;
11274: case SW32:
11275: mips32_op = OPC_SW;
11276: goto do_st;
11277: do_ld:
11278: gen_ld(env, ctx, mips32_op, rt, rs, imm);
11279: break;
11280: do_st:
11281: gen_st(ctx, mips32_op, rt, rs, imm);
11282: break;
11283: default:
11284: generate_exception(ctx, EXCP_RI);
11285: break;
11286: }
11287: }
11288:
11289: static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11290: {
11291: uint32_t op;
11292:
11293: /* make sure instructions are on a halfword boundary */
11294: if (ctx->pc & 0x1) {
11295: env->CP0_BadVAddr = ctx->pc;
11296: generate_exception(ctx, EXCP_AdEL);
11297: ctx->bstate = BS_STOP;
11298: return 2;
11299: }
11300:
11301: op = (ctx->opcode >> 10) & 0x3f;
11302: /* Enforce properly-sized instructions in a delay slot */
11303: if (ctx->hflags & MIPS_HFLAG_BMASK) {
11304: int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11305:
11306: switch (op) {
11307: case POOL32A:
11308: case POOL32B:
11309: case POOL32I:
11310: case POOL32C:
11311: case ADDI32:
11312: case ADDIU32:
11313: case ORI32:
11314: case XORI32:
11315: case SLTI32:
11316: case SLTIU32:
11317: case ANDI32:
11318: case JALX32:
11319: case LBU32:
11320: case LHU32:
11321: case POOL32F:
11322: case JALS32:
11323: case BEQ32:
11324: case BNE32:
11325: case J32:
11326: case JAL32:
11327: case SB32:
11328: case SH32:
11329: case POOL32S:
11330: case ADDIUPC:
11331: case SWC132:
11332: case SDC132:
11333: case SD32:
11334: case SW32:
11335: case LB32:
11336: case LH32:
11337: case DADDIU32:
11338: case POOL48A: /* ??? */
11339: case LWC132:
11340: case LDC132:
11341: case LD32:
11342: case LW32:
11343: if (bits & MIPS_HFLAG_BDS16) {
11344: generate_exception(ctx, EXCP_RI);
11345: /* Just stop translation; the user is confused. */
11346: ctx->bstate = BS_STOP;
11347: return 2;
11348: }
11349: break;
11350: case POOL16A:
11351: case POOL16B:
11352: case POOL16C:
11353: case LWGP16:
11354: case POOL16F:
11355: case LBU16:
11356: case LHU16:
11357: case LWSP16:
11358: case LW16:
11359: case SB16:
11360: case SH16:
11361: case SWSP16:
11362: case SW16:
11363: case MOVE16:
11364: case ANDI16:
11365: case POOL16D:
11366: case POOL16E:
11367: case BEQZ16:
11368: case BNEZ16:
11369: case B16:
11370: case LI16:
11371: if (bits & MIPS_HFLAG_BDS32) {
11372: generate_exception(ctx, EXCP_RI);
11373: /* Just stop translation; the user is confused. */
11374: ctx->bstate = BS_STOP;
11375: return 2;
11376: }
11377: break;
11378: default:
11379: break;
11380: }
11381: }
11382: switch (op) {
11383: case POOL16A:
11384: {
11385: int rd = mmreg(uMIPS_RD(ctx->opcode));
11386: int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11387: int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11388: uint32_t opc = 0;
11389:
11390: switch (ctx->opcode & 0x1) {
11391: case ADDU16:
11392: opc = OPC_ADDU;
11393: break;
11394: case SUBU16:
11395: opc = OPC_SUBU;
11396: break;
11397: }
11398:
11399: gen_arith(env, ctx, opc, rd, rs1, rs2);
11400: }
11401: break;
11402: case POOL16B:
11403: {
11404: int rd = mmreg(uMIPS_RD(ctx->opcode));
11405: int rs = mmreg(uMIPS_RS(ctx->opcode));
11406: int amount = (ctx->opcode >> 1) & 0x7;
11407: uint32_t opc = 0;
11408: amount = amount == 0 ? 8 : amount;
11409:
11410: switch (ctx->opcode & 0x1) {
11411: case SLL16:
11412: opc = OPC_SLL;
11413: break;
11414: case SRL16:
11415: opc = OPC_SRL;
11416: break;
11417: }
11418:
11419: gen_shift_imm(env, ctx, opc, rd, rs, amount);
11420: }
11421: break;
11422: case POOL16C:
11423: gen_pool16c_insn(env, ctx, is_branch);
11424: break;
11425: case LWGP16:
11426: {
11427: int rd = mmreg(uMIPS_RD(ctx->opcode));
11428: int rb = 28; /* GP */
11429: int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11430:
11431: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11432: }
11433: break;
11434: case POOL16F:
11435: if (ctx->opcode & 1) {
11436: generate_exception(ctx, EXCP_RI);
11437: } else {
11438: /* MOVEP */
11439: int enc_dest = uMIPS_RD(ctx->opcode);
11440: int enc_rt = uMIPS_RS2(ctx->opcode);
11441: int enc_rs = uMIPS_RS1(ctx->opcode);
11442: int rd, rs, re, rt;
11443: static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11444: static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11445: static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11446:
11447: rd = rd_enc[enc_dest];
11448: re = re_enc[enc_dest];
11449: rs = rs_rt_enc[enc_rs];
11450: rt = rs_rt_enc[enc_rt];
11451:
11452: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11453: gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11454: }
11455: break;
11456: case LBU16:
11457: {
11458: int rd = mmreg(uMIPS_RD(ctx->opcode));
11459: int rb = mmreg(uMIPS_RS(ctx->opcode));
11460: int16_t offset = ZIMM(ctx->opcode, 0, 4);
11461: offset = (offset == 0xf ? -1 : offset);
11462:
11463: gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
11464: }
11465: break;
11466: case LHU16:
11467: {
11468: int rd = mmreg(uMIPS_RD(ctx->opcode));
11469: int rb = mmreg(uMIPS_RS(ctx->opcode));
11470: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11471:
11472: gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
11473: }
11474: break;
11475: case LWSP16:
11476: {
11477: int rd = (ctx->opcode >> 5) & 0x1f;
11478: int rb = 29; /* SP */
11479: int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11480:
11481: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11482: }
11483: break;
11484: case LW16:
11485: {
11486: int rd = mmreg(uMIPS_RD(ctx->opcode));
11487: int rb = mmreg(uMIPS_RS(ctx->opcode));
11488: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11489:
11490: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11491: }
11492: break;
11493: case SB16:
11494: {
11495: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11496: int rb = mmreg(uMIPS_RS(ctx->opcode));
11497: int16_t offset = ZIMM(ctx->opcode, 0, 4);
11498:
11499: gen_st(ctx, OPC_SB, rd, rb, offset);
11500: }
11501: break;
11502: case SH16:
11503: {
11504: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11505: int rb = mmreg(uMIPS_RS(ctx->opcode));
11506: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11507:
11508: gen_st(ctx, OPC_SH, rd, rb, offset);
11509: }
11510: break;
11511: case SWSP16:
11512: {
11513: int rd = (ctx->opcode >> 5) & 0x1f;
11514: int rb = 29; /* SP */
11515: int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11516:
11517: gen_st(ctx, OPC_SW, rd, rb, offset);
11518: }
11519: break;
11520: case SW16:
11521: {
11522: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11523: int rb = mmreg(uMIPS_RS(ctx->opcode));
11524: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11525:
11526: gen_st(ctx, OPC_SW, rd, rb, offset);
11527: }
11528: break;
11529: case MOVE16:
11530: {
11531: int rd = uMIPS_RD5(ctx->opcode);
11532: int rs = uMIPS_RS5(ctx->opcode);
11533:
11534: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11535: }
11536: break;
11537: case ANDI16:
11538: gen_andi16(env, ctx);
11539: break;
11540: case POOL16D:
11541: switch (ctx->opcode & 0x1) {
11542: case ADDIUS5:
11543: gen_addius5(env, ctx);
11544: break;
11545: case ADDIUSP:
11546: gen_addiusp(env, ctx);
11547: break;
11548: }
11549: break;
11550: case POOL16E:
11551: switch (ctx->opcode & 0x1) {
11552: case ADDIUR2:
11553: gen_addiur2(env, ctx);
11554: break;
11555: case ADDIUR1SP:
11556: gen_addiur1sp(env, ctx);
11557: break;
11558: }
11559: break;
11560: case B16:
11561: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
11562: SIMM(ctx->opcode, 0, 10) << 1);
11563: *is_branch = 1;
11564: break;
11565: case BNEZ16:
11566: case BEQZ16:
11567: gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
11568: mmreg(uMIPS_RD(ctx->opcode)),
11569: 0, SIMM(ctx->opcode, 0, 7) << 1);
11570: *is_branch = 1;
11571: break;
11572: case LI16:
11573: {
11574: int reg = mmreg(uMIPS_RD(ctx->opcode));
11575: int imm = ZIMM(ctx->opcode, 0, 7);
11576:
11577: imm = (imm == 0x7f ? -1 : imm);
11578: tcg_gen_movi_tl(cpu_gpr[reg], imm);
11579: }
11580: break;
11581: case RES_20:
11582: case RES_28:
11583: case RES_29:
11584: case RES_30:
11585: case RES_31:
11586: case RES_38:
11587: case RES_39:
11588: generate_exception(ctx, EXCP_RI);
11589: break;
11590: default:
11591: decode_micromips32_opc (env, ctx, op, is_branch);
11592: return 4;
11593: }
11594:
11595: return 2;
11596: }
11597:
11598: /* SmartMIPS extension to MIPS32 */
11599:
11600: #if defined(TARGET_MIPS64)
11601:
11602: /* MDMX extension to MIPS64 */
11603:
11604: #endif
11605:
11606: static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11607: {
11608: int32_t offset;
11609: int rs, rt, rd, sa;
11610: uint32_t op, op1, op2;
11611: int16_t imm;
11612:
11613: /* make sure instructions are on a word boundary */
11614: if (ctx->pc & 0x3) {
11615: env->CP0_BadVAddr = ctx->pc;
11616: generate_exception(ctx, EXCP_AdEL);
11617: return;
11618: }
11619:
11620: /* Handle blikely not taken case */
11621: if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
11622: int l1 = gen_new_label();
11623:
11624: MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
1.1.1.8 root 11625: tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11626: tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
1.1.1.6 root 11627: gen_goto_tb(ctx, 1, ctx->pc + 4);
11628: gen_set_label(l1);
1.1 root 11629: }
1.1.1.9 root 11630:
11631: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11632: tcg_gen_debug_insn_start(ctx->pc);
11633:
1.1.1.5 root 11634: op = MASK_OP_MAJOR(ctx->opcode);
11635: rs = (ctx->opcode >> 21) & 0x1f;
11636: rt = (ctx->opcode >> 16) & 0x1f;
11637: rd = (ctx->opcode >> 11) & 0x1f;
11638: sa = (ctx->opcode >> 6) & 0x1f;
1.1 root 11639: imm = (int16_t)ctx->opcode;
11640: switch (op) {
1.1.1.5 root 11641: case OPC_SPECIAL:
11642: op1 = MASK_SPECIAL(ctx->opcode);
1.1 root 11643: switch (op1) {
1.1.1.8 root 11644: case OPC_SLL: /* Shift with immediate */
11645: case OPC_SRA:
11646: gen_shift_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 11647: break;
1.1.1.12 root 11648: case OPC_SRL:
11649: switch ((ctx->opcode >> 21) & 0x1f) {
11650: case 1:
11651: /* rotr is decoded as srl on non-R2 CPUs */
11652: if (env->insn_flags & ISA_MIPS32R2) {
11653: op1 = OPC_ROTR;
11654: }
11655: /* Fallthrough */
11656: case 0:
11657: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11658: break;
11659: default:
11660: generate_exception(ctx, EXCP_RI);
11661: break;
11662: }
11663: break;
1.1.1.8 root 11664: case OPC_MOVN: /* Conditional move */
11665: case OPC_MOVZ:
1.1.1.12 root 11666: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
11667: INSN_LOONGSON2E | INSN_LOONGSON2F);
1.1.1.8 root 11668: gen_cond_move(env, op1, rd, rs, rt);
11669: break;
11670: case OPC_ADD ... OPC_SUBU:
1.1.1.6 root 11671: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 11672: break;
1.1.1.8 root 11673: case OPC_SLLV: /* Shifts */
11674: case OPC_SRAV:
11675: gen_shift(env, ctx, op1, rd, rs, rt);
11676: break;
1.1.1.12 root 11677: case OPC_SRLV:
11678: switch ((ctx->opcode >> 6) & 0x1f) {
11679: case 1:
11680: /* rotrv is decoded as srlv on non-R2 CPUs */
11681: if (env->insn_flags & ISA_MIPS32R2) {
11682: op1 = OPC_ROTRV;
11683: }
11684: /* Fallthrough */
11685: case 0:
11686: gen_shift(env, ctx, op1, rd, rs, rt);
11687: break;
11688: default:
11689: generate_exception(ctx, EXCP_RI);
11690: break;
11691: }
11692: break;
1.1.1.8 root 11693: case OPC_SLT: /* Set on less than */
11694: case OPC_SLTU:
11695: gen_slt(env, op1, rd, rs, rt);
11696: break;
11697: case OPC_AND: /* Logic*/
11698: case OPC_OR:
11699: case OPC_NOR:
11700: case OPC_XOR:
11701: gen_logic(env, op1, rd, rs, rt);
11702: break;
1.1.1.5 root 11703: case OPC_MULT ... OPC_DIVU:
1.1.1.6 root 11704: if (sa) {
11705: check_insn(env, ctx, INSN_VR54XX);
11706: op1 = MASK_MUL_VR54XX(ctx->opcode);
11707: gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11708: } else
11709: gen_muldiv(ctx, op1, rs, rt);
1.1 root 11710: break;
1.1.1.5 root 11711: case OPC_JR ... OPC_JALR:
1.1.1.12 root 11712: gen_compute_branch(ctx, op1, 4, rs, rd, sa);
11713: *is_branch = 1;
11714: break;
1.1.1.5 root 11715: case OPC_TGE ... OPC_TEQ: /* Traps */
11716: case OPC_TNE:
11717: gen_trap(ctx, op1, rs, rt, -1);
11718: break;
11719: case OPC_MFHI: /* Move from HI/LO */
11720: case OPC_MFLO:
11721: gen_HILO(ctx, op1, rd);
1.1 root 11722: break;
1.1.1.5 root 11723: case OPC_MTHI:
11724: case OPC_MTLO: /* Move to HI/LO */
11725: gen_HILO(ctx, op1, rs);
11726: break;
1.1.1.6 root 11727: case OPC_PMON: /* Pmon entry point, also R4010 selsl */
11728: #ifdef MIPS_STRICT_STANDARD
11729: MIPS_INVAL("PMON / selsl");
11730: generate_exception(ctx, EXCP_RI);
11731: #else
1.1.1.7 root 11732: gen_helper_0i(pmon, sa);
1.1.1.6 root 11733: #endif
1.1.1.5 root 11734: break;
11735: case OPC_SYSCALL:
1.1 root 11736: generate_exception(ctx, EXCP_SYSCALL);
1.1.1.8 root 11737: ctx->bstate = BS_STOP;
1.1 root 11738: break;
1.1.1.5 root 11739: case OPC_BREAK:
1.1 root 11740: generate_exception(ctx, EXCP_BREAK);
11741: break;
1.1.1.6 root 11742: case OPC_SPIM:
11743: #ifdef MIPS_STRICT_STANDARD
11744: MIPS_INVAL("SPIM");
11745: generate_exception(ctx, EXCP_RI);
11746: #else
1.1.1.5 root 11747: /* Implemented as RI exception for now. */
11748: MIPS_INVAL("spim (unofficial)");
11749: generate_exception(ctx, EXCP_RI);
1.1.1.6 root 11750: #endif
1.1 root 11751: break;
1.1.1.5 root 11752: case OPC_SYNC:
1.1.1.6 root 11753: /* Treat as NOP. */
1.1 root 11754: break;
1.1.1.2 root 11755:
1.1.1.5 root 11756: case OPC_MOVCI:
1.1.1.6 root 11757: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
11758: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11759: check_cp1_enabled(ctx);
11760: gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11761: (ctx->opcode >> 16) & 1);
11762: } else {
11763: generate_exception_err(ctx, EXCP_CpU, 1);
11764: }
1.1.1.2 root 11765: break;
11766:
1.1.1.6 root 11767: #if defined(TARGET_MIPS64)
1.1.1.5 root 11768: /* MIPS64 specific opcodes */
11769: case OPC_DSLL:
1.1.1.8 root 11770: case OPC_DSRA:
1.1.1.5 root 11771: case OPC_DSLL32:
1.1.1.8 root 11772: case OPC_DSRA32:
1.1.1.6 root 11773: check_insn(env, ctx, ISA_MIPS3);
11774: check_mips_64(ctx);
1.1.1.8 root 11775: gen_shift_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 11776: break;
1.1.1.12 root 11777: case OPC_DSRL:
11778: switch ((ctx->opcode >> 21) & 0x1f) {
11779: case 1:
11780: /* drotr is decoded as dsrl on non-R2 CPUs */
11781: if (env->insn_flags & ISA_MIPS32R2) {
11782: op1 = OPC_DROTR;
11783: }
11784: /* Fallthrough */
11785: case 0:
11786: check_insn(env, ctx, ISA_MIPS3);
11787: check_mips_64(ctx);
11788: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11789: break;
11790: default:
11791: generate_exception(ctx, EXCP_RI);
11792: break;
11793: }
11794: break;
11795: case OPC_DSRL32:
11796: switch ((ctx->opcode >> 21) & 0x1f) {
11797: case 1:
11798: /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
11799: if (env->insn_flags & ISA_MIPS32R2) {
11800: op1 = OPC_DROTR32;
11801: }
11802: /* Fallthrough */
11803: case 0:
11804: check_insn(env, ctx, ISA_MIPS3);
11805: check_mips_64(ctx);
11806: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11807: break;
11808: default:
11809: generate_exception(ctx, EXCP_RI);
11810: break;
11811: }
11812: break;
1.1.1.5 root 11813: case OPC_DADD ... OPC_DSUBU:
1.1.1.6 root 11814: check_insn(env, ctx, ISA_MIPS3);
11815: check_mips_64(ctx);
11816: gen_arith(env, ctx, op1, rd, rs, rt);
1.1.1.5 root 11817: break;
1.1.1.8 root 11818: case OPC_DSLLV:
11819: case OPC_DSRAV:
11820: check_insn(env, ctx, ISA_MIPS3);
11821: check_mips_64(ctx);
11822: gen_shift(env, ctx, op1, rd, rs, rt);
11823: break;
1.1.1.12 root 11824: case OPC_DSRLV:
11825: switch ((ctx->opcode >> 6) & 0x1f) {
11826: case 1:
11827: /* drotrv is decoded as dsrlv on non-R2 CPUs */
11828: if (env->insn_flags & ISA_MIPS32R2) {
11829: op1 = OPC_DROTRV;
11830: }
11831: /* Fallthrough */
11832: case 0:
11833: check_insn(env, ctx, ISA_MIPS3);
11834: check_mips_64(ctx);
11835: gen_shift(env, ctx, op1, rd, rs, rt);
11836: break;
11837: default:
11838: generate_exception(ctx, EXCP_RI);
11839: break;
11840: }
11841: break;
1.1.1.5 root 11842: case OPC_DMULT ... OPC_DDIVU:
1.1.1.6 root 11843: check_insn(env, ctx, ISA_MIPS3);
11844: check_mips_64(ctx);
1.1.1.5 root 11845: gen_muldiv(ctx, op1, rs, rt);
11846: break;
1.1 root 11847: #endif
11848: default: /* Invalid */
11849: MIPS_INVAL("special");
11850: generate_exception(ctx, EXCP_RI);
11851: break;
11852: }
11853: break;
1.1.1.5 root 11854: case OPC_SPECIAL2:
11855: op1 = MASK_SPECIAL2(ctx->opcode);
1.1 root 11856: switch (op1) {
1.1.1.5 root 11857: case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11858: case OPC_MSUB ... OPC_MSUBU:
1.1.1.6 root 11859: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 11860: gen_muldiv(ctx, op1, rs, rt);
1.1 root 11861: break;
1.1.1.5 root 11862: case OPC_MUL:
1.1.1.6 root 11863: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 11864: break;
1.1.1.8 root 11865: case OPC_CLO:
11866: case OPC_CLZ:
1.1.1.6 root 11867: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 11868: gen_cl(ctx, op1, rd, rs);
1.1 root 11869: break;
1.1.1.5 root 11870: case OPC_SDBBP:
1.1 root 11871: /* XXX: not clear which exception should be raised
11872: * when in debug mode...
11873: */
1.1.1.6 root 11874: check_insn(env, ctx, ISA_MIPS32);
1.1 root 11875: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11876: generate_exception(ctx, EXCP_DBp);
11877: } else {
11878: generate_exception(ctx, EXCP_DBp);
11879: }
1.1.1.6 root 11880: /* Treat as NOP. */
1.1 root 11881: break;
1.1.1.12 root 11882: case OPC_DIV_G_2F:
11883: case OPC_DIVU_G_2F:
11884: case OPC_MULT_G_2F:
11885: case OPC_MULTU_G_2F:
11886: case OPC_MOD_G_2F:
11887: case OPC_MODU_G_2F:
11888: check_insn(env, ctx, INSN_LOONGSON2F);
11889: gen_loongson_integer(ctx, op1, rd, rs, rt);
11890: break;
1.1.1.6 root 11891: #if defined(TARGET_MIPS64)
1.1.1.8 root 11892: case OPC_DCLO:
11893: case OPC_DCLZ:
1.1.1.6 root 11894: check_insn(env, ctx, ISA_MIPS64);
11895: check_mips_64(ctx);
1.1.1.5 root 11896: gen_cl(ctx, op1, rd, rs);
11897: break;
1.1.1.12 root 11898: case OPC_DMULT_G_2F:
11899: case OPC_DMULTU_G_2F:
11900: case OPC_DDIV_G_2F:
11901: case OPC_DDIVU_G_2F:
11902: case OPC_DMOD_G_2F:
11903: case OPC_DMODU_G_2F:
11904: check_insn(env, ctx, INSN_LOONGSON2F);
11905: gen_loongson_integer(ctx, op1, rd, rs, rt);
11906: break;
1.1.1.5 root 11907: #endif
1.1 root 11908: default: /* Invalid */
11909: MIPS_INVAL("special2");
11910: generate_exception(ctx, EXCP_RI);
11911: break;
11912: }
11913: break;
1.1.1.5 root 11914: case OPC_SPECIAL3:
1.1.1.7 root 11915: op1 = MASK_SPECIAL3(ctx->opcode);
11916: switch (op1) {
11917: case OPC_EXT:
11918: case OPC_INS:
11919: check_insn(env, ctx, ISA_MIPS32R2);
11920: gen_bitops(ctx, op1, rt, rs, sa, rd);
11921: break;
11922: case OPC_BSHFL:
11923: check_insn(env, ctx, ISA_MIPS32R2);
11924: op2 = MASK_BSHFL(ctx->opcode);
11925: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 11926: break;
11927: case OPC_RDHWR:
1.1.1.12 root 11928: gen_rdhwr(env, ctx, rt, rd);
1.1.1.6 root 11929: break;
11930: case OPC_FORK:
11931: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 11932: {
1.1.1.8 root 11933: TCGv t0 = tcg_temp_new();
11934: TCGv t1 = tcg_temp_new();
1.1.1.7 root 11935:
11936: gen_load_gpr(t0, rt);
11937: gen_load_gpr(t1, rs);
11938: gen_helper_fork(t0, t1);
11939: tcg_temp_free(t0);
11940: tcg_temp_free(t1);
11941: }
1.1.1.6 root 11942: break;
11943: case OPC_YIELD:
11944: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 11945: {
1.1.1.8 root 11946: TCGv t0 = tcg_temp_new();
1.1.1.7 root 11947:
1.1.1.8 root 11948: save_cpu_state(ctx, 1);
1.1.1.7 root 11949: gen_load_gpr(t0, rs);
11950: gen_helper_yield(t0, t0);
11951: gen_store_gpr(t0, rd);
11952: tcg_temp_free(t0);
11953: }
1.1.1.6 root 11954: break;
1.1.1.12 root 11955: case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
11956: case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
11957: case OPC_MOD_G_2E ... OPC_MODU_G_2E:
11958: check_insn(env, ctx, INSN_LOONGSON2E);
11959: gen_loongson_integer(ctx, op1, rd, rs, rt);
11960: break;
1.1.1.6 root 11961: #if defined(TARGET_MIPS64)
11962: case OPC_DEXTM ... OPC_DEXT:
11963: case OPC_DINSM ... OPC_DINS:
11964: check_insn(env, ctx, ISA_MIPS64R2);
11965: check_mips_64(ctx);
1.1.1.5 root 11966: gen_bitops(ctx, op1, rt, rs, sa, rd);
11967: break;
1.1.1.6 root 11968: case OPC_DBSHFL:
11969: check_insn(env, ctx, ISA_MIPS64R2);
11970: check_mips_64(ctx);
11971: op2 = MASK_DBSHFL(ctx->opcode);
1.1.1.7 root 11972: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 11973: break;
1.1.1.12 root 11974: case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
11975: case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
11976: case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
11977: check_insn(env, ctx, INSN_LOONGSON2E);
11978: gen_loongson_integer(ctx, op1, rd, rs, rt);
11979: break;
1.1.1.5 root 11980: #endif
11981: default: /* Invalid */
11982: MIPS_INVAL("special3");
11983: generate_exception(ctx, EXCP_RI);
11984: break;
11985: }
11986: break;
11987: case OPC_REGIMM:
11988: op1 = MASK_REGIMM(ctx->opcode);
1.1 root 11989: switch (op1) {
1.1.1.5 root 11990: case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
11991: case OPC_BLTZAL ... OPC_BGEZALL:
1.1.1.12 root 11992: gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
11993: *is_branch = 1;
11994: break;
1.1.1.5 root 11995: case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
11996: case OPC_TNEI:
11997: gen_trap(ctx, op1, rs, -1, imm);
11998: break;
11999: case OPC_SYNCI:
1.1.1.6 root 12000: check_insn(env, ctx, ISA_MIPS32R2);
12001: /* Treat as NOP. */
1.1 root 12002: break;
12003: default: /* Invalid */
1.1.1.6 root 12004: MIPS_INVAL("regimm");
1.1 root 12005: generate_exception(ctx, EXCP_RI);
12006: break;
12007: }
12008: break;
1.1.1.5 root 12009: case OPC_CP0:
1.1.1.6 root 12010: check_cp0_enabled(ctx);
1.1.1.5 root 12011: op1 = MASK_CP0(ctx->opcode);
1.1 root 12012: switch (op1) {
1.1.1.5 root 12013: case OPC_MFC0:
12014: case OPC_MTC0:
1.1.1.6 root 12015: case OPC_MFTR:
12016: case OPC_MTTR:
12017: #if defined(TARGET_MIPS64)
1.1.1.5 root 12018: case OPC_DMFC0:
12019: case OPC_DMTC0:
12020: #endif
1.1.1.7 root 12021: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 12022: gen_cp0(env, ctx, op1, rt, rd);
1.1.1.7 root 12023: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 12024: break;
12025: case OPC_C0_FIRST ... OPC_C0_LAST:
1.1.1.7 root 12026: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 12027: gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
1.1.1.7 root 12028: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 12029: break;
12030: case OPC_MFMC0:
1.1.1.7 root 12031: #ifndef CONFIG_USER_ONLY
12032: {
1.1.1.8 root 12033: TCGv t0 = tcg_temp_new();
1.1.1.7 root 12034:
12035: op2 = MASK_MFMC0(ctx->opcode);
12036: switch (op2) {
12037: case OPC_DMT:
12038: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12039: gen_helper_dmt(t0);
1.1.1.8 root 12040: gen_store_gpr(t0, rt);
1.1.1.7 root 12041: break;
12042: case OPC_EMT:
12043: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12044: gen_helper_emt(t0);
1.1.1.8 root 12045: gen_store_gpr(t0, rt);
1.1.1.7 root 12046: break;
12047: case OPC_DVPE:
12048: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12049: gen_helper_dvpe(t0);
1.1.1.8 root 12050: gen_store_gpr(t0, rt);
1.1.1.7 root 12051: break;
12052: case OPC_EVPE:
12053: check_insn(env, ctx, ASE_MT);
1.1.1.13 root 12054: gen_helper_evpe(t0);
1.1.1.8 root 12055: gen_store_gpr(t0, rt);
1.1.1.7 root 12056: break;
12057: case OPC_DI:
12058: check_insn(env, ctx, ISA_MIPS32R2);
12059: save_cpu_state(ctx, 1);
12060: gen_helper_di(t0);
1.1.1.8 root 12061: gen_store_gpr(t0, rt);
1.1.1.7 root 12062: /* Stop translation as we may have switched the execution mode */
12063: ctx->bstate = BS_STOP;
12064: break;
12065: case OPC_EI:
12066: check_insn(env, ctx, ISA_MIPS32R2);
12067: save_cpu_state(ctx, 1);
12068: gen_helper_ei(t0);
1.1.1.8 root 12069: gen_store_gpr(t0, rt);
1.1.1.7 root 12070: /* Stop translation as we may have switched the execution mode */
12071: ctx->bstate = BS_STOP;
12072: break;
12073: default: /* Invalid */
12074: MIPS_INVAL("mfmc0");
12075: generate_exception(ctx, EXCP_RI);
12076: break;
12077: }
12078: tcg_temp_free(t0);
1.1.1.5 root 12079: }
1.1.1.7 root 12080: #endif /* !CONFIG_USER_ONLY */
1.1 root 12081: break;
1.1.1.5 root 12082: case OPC_RDPGPR:
1.1.1.6 root 12083: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 root 12084: gen_load_srsgpr(rt, rd);
1.1.1.6 root 12085: break;
1.1.1.5 root 12086: case OPC_WRPGPR:
1.1.1.6 root 12087: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 root 12088: gen_store_srsgpr(rt, rd);
1.1.1.6 root 12089: break;
1.1 root 12090: default:
1.1.1.6 root 12091: MIPS_INVAL("cp0");
1.1.1.5 root 12092: generate_exception(ctx, EXCP_RI);
1.1 root 12093: break;
12094: }
12095: break;
1.1.1.8 root 12096: case OPC_ADDI: /* Arithmetic with immediate opcode */
12097: case OPC_ADDIU:
1.1.1.6 root 12098: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 12099: break;
1.1.1.8 root 12100: case OPC_SLTI: /* Set on less than with immediate opcode */
12101: case OPC_SLTIU:
12102: gen_slt_imm(env, op, rt, rs, imm);
12103: break;
12104: case OPC_ANDI: /* Arithmetic with immediate opcode */
12105: case OPC_LUI:
12106: case OPC_ORI:
12107: case OPC_XORI:
12108: gen_logic_imm(env, op, rt, rs, imm);
12109: break;
1.1.1.5 root 12110: case OPC_J ... OPC_JAL: /* Jump */
12111: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
1.1.1.12 root 12112: gen_compute_branch(ctx, op, 4, rs, rt, offset);
12113: *is_branch = 1;
12114: break;
1.1.1.5 root 12115: case OPC_BEQ ... OPC_BGTZ: /* Branch */
12116: case OPC_BEQL ... OPC_BGTZL:
1.1.1.12 root 12117: gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
12118: *is_branch = 1;
12119: break;
1.1.1.5 root 12120: case OPC_LB ... OPC_LWR: /* Load and stores */
1.1.1.12 root 12121: case OPC_LL:
12122: gen_ld(env, ctx, op, rt, rs, imm);
12123: break;
1.1.1.5 root 12124: case OPC_SB ... OPC_SW:
12125: case OPC_SWR:
1.1.1.12 root 12126: gen_st(ctx, op, rt, rs, imm);
1.1.1.5 root 12127: break;
1.1.1.8 root 12128: case OPC_SC:
12129: gen_st_cond(ctx, op, rt, rs, imm);
12130: break;
1.1.1.5 root 12131: case OPC_CACHE:
1.1.1.6 root 12132: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
12133: /* Treat as NOP. */
12134: break;
1.1.1.5 root 12135: case OPC_PREF:
1.1.1.6 root 12136: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
12137: /* Treat as NOP. */
1.1 root 12138: break;
1.1.1.2 root 12139:
1.1.1.6 root 12140: /* Floating point (COP1). */
1.1.1.5 root 12141: case OPC_LWC1:
12142: case OPC_LDC1:
12143: case OPC_SWC1:
12144: case OPC_SDC1:
1.1.1.12 root 12145: gen_cop1_ldst(env, ctx, op, rt, rs, imm);
1.1.1.4 root 12146: break;
12147:
1.1.1.5 root 12148: case OPC_CP1:
1.1.1.6 root 12149: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12150: check_cp1_enabled(ctx);
12151: op1 = MASK_CP1(ctx->opcode);
12152: switch (op1) {
12153: case OPC_MFHC1:
12154: case OPC_MTHC1:
12155: check_insn(env, ctx, ISA_MIPS32R2);
12156: case OPC_MFC1:
12157: case OPC_CFC1:
12158: case OPC_MTC1:
12159: case OPC_CTC1:
12160: gen_cp1(ctx, op1, rt, rd);
12161: break;
12162: #if defined(TARGET_MIPS64)
12163: case OPC_DMFC1:
12164: case OPC_DMTC1:
12165: check_insn(env, ctx, ISA_MIPS3);
12166: gen_cp1(ctx, op1, rt, rd);
12167: break;
1.1.1.5 root 12168: #endif
1.1.1.6 root 12169: case OPC_BC1ANY2:
12170: case OPC_BC1ANY4:
12171: check_cop1x(ctx);
12172: check_insn(env, ctx, ASE_MIPS3D);
12173: /* fall through */
12174: case OPC_BC1:
12175: gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
12176: (rt >> 2) & 0x7, imm << 2);
1.1.1.12 root 12177: *is_branch = 1;
12178: break;
1.1.1.6 root 12179: case OPC_S_FMT:
12180: case OPC_D_FMT:
12181: case OPC_W_FMT:
12182: case OPC_L_FMT:
12183: case OPC_PS_FMT:
1.1.1.12 root 12184: gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
1.1.1.6 root 12185: (imm >> 8) & 0x7);
12186: break;
12187: default:
12188: MIPS_INVAL("cp1");
12189: generate_exception (ctx, EXCP_RI);
12190: break;
12191: }
12192: } else {
12193: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.4 root 12194: }
1.1.1.2 root 12195: break;
12196:
12197: /* COP2. */
1.1.1.5 root 12198: case OPC_LWC2:
12199: case OPC_LDC2:
12200: case OPC_SWC2:
12201: case OPC_SDC2:
12202: case OPC_CP2:
12203: /* COP2: Not implemented. */
1.1.1.2 root 12204: generate_exception_err(ctx, EXCP_CpU, 2);
12205: break;
12206:
1.1.1.5 root 12207: case OPC_CP3:
1.1.1.6 root 12208: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12209: check_cp1_enabled(ctx);
12210: op1 = MASK_CP3(ctx->opcode);
12211: switch (op1) {
12212: case OPC_LWXC1:
12213: case OPC_LDXC1:
12214: case OPC_LUXC1:
12215: case OPC_SWXC1:
12216: case OPC_SDXC1:
12217: case OPC_SUXC1:
12218: gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
12219: break;
12220: case OPC_PREFX:
12221: /* Treat as NOP. */
12222: break;
12223: case OPC_ALNV_PS:
12224: case OPC_MADD_S:
12225: case OPC_MADD_D:
12226: case OPC_MADD_PS:
12227: case OPC_MSUB_S:
12228: case OPC_MSUB_D:
12229: case OPC_MSUB_PS:
12230: case OPC_NMADD_S:
12231: case OPC_NMADD_D:
12232: case OPC_NMADD_PS:
12233: case OPC_NMSUB_S:
12234: case OPC_NMSUB_D:
12235: case OPC_NMSUB_PS:
12236: gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12237: break;
12238: default:
12239: MIPS_INVAL("cp3");
12240: generate_exception (ctx, EXCP_RI);
12241: break;
12242: }
12243: } else {
12244: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.5 root 12245: }
1.1.1.2 root 12246: break;
12247:
1.1.1.6 root 12248: #if defined(TARGET_MIPS64)
1.1.1.5 root 12249: /* MIPS64 opcodes */
12250: case OPC_LWU:
12251: case OPC_LDL ... OPC_LDR:
12252: case OPC_LLD:
12253: case OPC_LD:
1.1.1.12 root 12254: check_insn(env, ctx, ISA_MIPS3);
12255: check_mips_64(ctx);
12256: gen_ld(env, ctx, op, rt, rs, imm);
12257: break;
12258: case OPC_SDL ... OPC_SDR:
1.1.1.5 root 12259: case OPC_SD:
1.1.1.6 root 12260: check_insn(env, ctx, ISA_MIPS3);
12261: check_mips_64(ctx);
1.1.1.12 root 12262: gen_st(ctx, op, rt, rs, imm);
1.1.1.5 root 12263: break;
1.1.1.8 root 12264: case OPC_SCD:
12265: check_insn(env, ctx, ISA_MIPS3);
12266: check_mips_64(ctx);
12267: gen_st_cond(ctx, op, rt, rs, imm);
12268: break;
12269: case OPC_DADDI:
12270: case OPC_DADDIU:
1.1.1.6 root 12271: check_insn(env, ctx, ISA_MIPS3);
12272: check_mips_64(ctx);
12273: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 12274: break;
12275: #endif
12276: case OPC_JALX:
1.1.1.12 root 12277: check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
12278: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12279: gen_compute_branch(ctx, op, 4, rs, rt, offset);
12280: *is_branch = 1;
12281: break;
1.1.1.5 root 12282: case OPC_MDMX:
1.1.1.6 root 12283: check_insn(env, ctx, ASE_MDMX);
1.1.1.5 root 12284: /* MDMX: Not implemented. */
1.1 root 12285: default: /* Invalid */
1.1.1.6 root 12286: MIPS_INVAL("major opcode");
1.1 root 12287: generate_exception(ctx, EXCP_RI);
12288: break;
12289: }
12290: }
12291:
1.1.1.7 root 12292: static inline void
1.1.1.6 root 12293: gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
12294: int search_pc)
1.1 root 12295: {
1.1.1.6 root 12296: DisasContext ctx;
1.1 root 12297: target_ulong pc_start;
12298: uint16_t *gen_opc_end;
1.1.1.7 root 12299: CPUBreakpoint *bp;
1.1 root 12300: int j, lj = -1;
1.1.1.7 root 12301: int num_insns;
12302: int max_insns;
1.1.1.12 root 12303: int insn_bytes;
12304: int is_branch;
1.1 root 12305:
1.1.1.7 root 12306: if (search_pc)
12307: qemu_log("search pc %d\n", search_pc);
1.1.1.2 root 12308:
1.1 root 12309: pc_start = tb->pc;
1.1.1.9 root 12310: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1.1 root 12311: ctx.pc = pc_start;
1.1.1.2 root 12312: ctx.saved_pc = -1;
1.1.1.9 root 12313: ctx.singlestep_enabled = env->singlestep_enabled;
1.1 root 12314: ctx.tb = tb;
12315: ctx.bstate = BS_NONE;
1.1.1.2 root 12316: /* Restore delay slot state from the tb context. */
1.1.1.6 root 12317: ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
12318: restore_cpu_state(env, &ctx);
1.1.1.7 root 12319: #ifdef CONFIG_USER_ONLY
12320: ctx.mem_idx = MIPS_HFLAG_UM;
1.1 root 12321: #else
1.1.1.7 root 12322: ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
1.1 root 12323: #endif
1.1.1.7 root 12324: num_insns = 0;
12325: max_insns = tb->cflags & CF_COUNT_MASK;
12326: if (max_insns == 0)
12327: max_insns = CF_COUNT_MASK;
12328: LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
12329: gen_icount_start();
12330: while (ctx.bstate == BS_NONE) {
1.1.1.9 root 12331: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12332: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1.1.7 root 12333: if (bp->pc == ctx.pc) {
1.1.1.6 root 12334: save_cpu_state(&ctx, 1);
1.1.1.2 root 12335: ctx.bstate = BS_BRANCH;
1.1.1.7 root 12336: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 12337: /* Include the breakpoint location or the tb won't
12338: * be flushed when it must be. */
12339: ctx.pc += 4;
1.1.1.2 root 12340: goto done_generating;
12341: }
12342: }
12343: }
12344:
1.1 root 12345: if (search_pc) {
12346: j = gen_opc_ptr - gen_opc_buf;
12347: if (lj < j) {
12348: lj++;
12349: while (lj < j)
12350: gen_opc_instr_start[lj++] = 0;
12351: }
1.1.1.2 root 12352: gen_opc_pc[lj] = ctx.pc;
12353: gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12354: gen_opc_instr_start[lj] = 1;
1.1.1.7 root 12355: gen_opc_icount[lj] = num_insns;
1.1 root 12356: }
1.1.1.7 root 12357: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12358: gen_io_start();
1.1.1.12 root 12359:
12360: is_branch = 0;
12361: if (!(ctx.hflags & MIPS_HFLAG_M16)) {
12362: ctx.opcode = ldl_code(ctx.pc);
12363: insn_bytes = 4;
12364: decode_opc(env, &ctx, &is_branch);
12365: } else if (env->insn_flags & ASE_MICROMIPS) {
12366: ctx.opcode = lduw_code(ctx.pc);
12367: insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
12368: } else if (env->insn_flags & ASE_MIPS16) {
12369: ctx.opcode = lduw_code(ctx.pc);
12370: insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
12371: } else {
12372: generate_exception(&ctx, EXCP_RI);
12373: ctx.bstate = BS_STOP;
12374: break;
12375: }
12376: if (!is_branch) {
12377: handle_delay_slot(env, &ctx, insn_bytes);
12378: }
12379: ctx.pc += insn_bytes;
12380:
1.1.1.7 root 12381: num_insns++;
1.1.1.2 root 12382:
1.1.1.9 root 12383: /* Execute a branch and its delay slot as a single instruction.
12384: This is what GDB expects and is consistent with what the
12385: hardware does (e.g. if a delay slot instruction faults, the
12386: reported PC is the PC of the branch). */
12387: if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
1.1.1.2 root 12388: break;
12389:
1.1 root 12390: if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12391: break;
1.1.1.2 root 12392:
1.1.1.7 root 12393: if (gen_opc_ptr >= gen_opc_end)
12394: break;
12395:
12396: if (num_insns >= max_insns)
12397: break;
1.1.1.8 root 12398:
12399: if (singlestep)
12400: break;
1.1 root 12401: }
1.1.1.7 root 12402: if (tb->cflags & CF_LAST_IO)
12403: gen_io_end();
1.1.1.9 root 12404: if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
1.1.1.6 root 12405: save_cpu_state(&ctx, ctx.bstate == BS_NONE);
1.1.1.7 root 12406: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 12407: } else {
1.1.1.7 root 12408: switch (ctx.bstate) {
1.1.1.6 root 12409: case BS_STOP:
12410: gen_goto_tb(&ctx, 0, ctx.pc);
12411: break;
12412: case BS_NONE:
12413: save_cpu_state(&ctx, 0);
12414: gen_goto_tb(&ctx, 0, ctx.pc);
12415: break;
12416: case BS_EXCP:
1.1.1.7 root 12417: tcg_gen_exit_tb(0);
1.1.1.6 root 12418: break;
12419: case BS_BRANCH:
12420: default:
12421: break;
1.1.1.7 root 12422: }
1.1 root 12423: }
1.1.1.2 root 12424: done_generating:
1.1.1.7 root 12425: gen_icount_end(tb, num_insns);
1.1 root 12426: *gen_opc_ptr = INDEX_op_end;
12427: if (search_pc) {
12428: j = gen_opc_ptr - gen_opc_buf;
12429: lj++;
12430: while (lj <= j)
12431: gen_opc_instr_start[lj++] = 0;
12432: } else {
12433: tb->size = ctx.pc - pc_start;
1.1.1.7 root 12434: tb->icount = num_insns;
1.1 root 12435: }
12436: #ifdef DEBUG_DISAS
1.1.1.7 root 12437: LOG_DISAS("\n");
12438: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
12439: qemu_log("IN: %s\n", lookup_symbol(pc_start));
12440: log_target_disas(pc_start, ctx.pc - pc_start, 0);
12441: qemu_log("\n");
1.1 root 12442: }
12443: #endif
12444: }
12445:
1.1.1.7 root 12446: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1.1 root 12447: {
1.1.1.7 root 12448: gen_intermediate_code_internal(env, tb, 0);
1.1 root 12449: }
12450:
1.1.1.7 root 12451: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1.1 root 12452: {
1.1.1.7 root 12453: gen_intermediate_code_internal(env, tb, 1);
1.1 root 12454: }
12455:
1.1.1.13 root 12456: static void fpu_dump_state(CPUState *env, FILE *f, fprintf_function fpu_fprintf,
1.1.1.7 root 12457: int flags)
1.1.1.4 root 12458: {
12459: int i;
1.1.1.6 root 12460: int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
1.1.1.4 root 12461:
1.1.1.12 root 12462: #define printfpr(fp) \
12463: do { \
12464: if (is_fpu64) \
12465: fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12466: " fd:%13g fs:%13g psu: %13g\n", \
12467: (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12468: (double)(fp)->fd, \
12469: (double)(fp)->fs[FP_ENDIAN_IDX], \
12470: (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12471: else { \
12472: fpr_t tmp; \
12473: tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12474: tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12475: fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12476: " fd:%13g fs:%13g psu:%13g\n", \
12477: tmp.w[FP_ENDIAN_IDX], tmp.d, \
12478: (double)tmp.fd, \
12479: (double)tmp.fs[FP_ENDIAN_IDX], \
12480: (double)tmp.fs[!FP_ENDIAN_IDX]); \
12481: } \
1.1.1.4 root 12482: } while(0)
12483:
1.1.1.6 root 12484:
1.1.1.13 root 12485: fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
12486: env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
1.1.1.7 root 12487: get_float_exception_flags(&env->active_fpu.fp_status));
1.1.1.6 root 12488: for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12489: fpu_fprintf(f, "%3s: ", fregnames[i]);
1.1.1.7 root 12490: printfpr(&env->active_fpu.fpr[i]);
1.1.1.4 root 12491: }
12492:
12493: #undef printfpr
12494: }
12495:
1.1.1.6 root 12496: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 12497: /* Debug help: The architecture requires 32bit code to maintain proper
1.1.1.7 root 12498: sign-extended values on 64bit machines. */
1.1.1.5 root 12499:
12500: #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12501:
1.1.1.7 root 12502: static void
12503: cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
1.1.1.13 root 12504: fprintf_function cpu_fprintf,
1.1.1.7 root 12505: int flags)
1.1.1.5 root 12506: {
12507: int i;
12508:
1.1.1.7 root 12509: if (!SIGN_EXT_P(env->active_tc.PC))
12510: cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12511: if (!SIGN_EXT_P(env->active_tc.HI[0]))
12512: cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12513: if (!SIGN_EXT_P(env->active_tc.LO[0]))
12514: cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
1.1.1.5 root 12515: if (!SIGN_EXT_P(env->btarget))
1.1.1.6 root 12516: cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
1.1.1.5 root 12517:
12518: for (i = 0; i < 32; i++) {
1.1.1.7 root 12519: if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12520: cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
1.1.1.5 root 12521: }
12522:
12523: if (!SIGN_EXT_P(env->CP0_EPC))
1.1.1.6 root 12524: cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
1.1.1.9 root 12525: if (!SIGN_EXT_P(env->lladdr))
12526: cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
1.1.1.5 root 12527: }
12528: #endif
12529:
1.1.1.13 root 12530: void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1.1 root 12531: int flags)
12532: {
12533: int i;
1.1.1.6 root 12534:
1.1.1.12 root 12535: cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
12536: " LO=0x" TARGET_FMT_lx " ds %04x "
12537: TARGET_FMT_lx " " TARGET_FMT_ld "\n",
1.1.1.7 root 12538: env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12539: env->hflags, env->btarget, env->bcond);
1.1 root 12540: for (i = 0; i < 32; i++) {
12541: if ((i & 3) == 0)
12542: cpu_fprintf(f, "GPR%02d:", i);
1.1.1.7 root 12543: cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
1.1 root 12544: if ((i & 3) == 3)
12545: cpu_fprintf(f, "\n");
12546: }
12547:
1.1.1.6 root 12548: cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
12549: env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
12550: cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
1.1.1.9 root 12551: env->CP0_Config0, env->CP0_Config1, env->lladdr);
1.1.1.6 root 12552: if (env->hflags & MIPS_HFLAG_FPU)
1.1.1.5 root 12553: fpu_dump_state(env, f, cpu_fprintf, flags);
1.1.1.6 root 12554: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 12555: cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
1.1.1.4 root 12556: #endif
1.1 root 12557: }
12558:
1.1.1.7 root 12559: static void mips_tcg_init(void)
12560: {
12561: int i;
12562: static int inited;
12563:
12564: /* Initialize various static tables. */
12565: if (inited)
12566: return;
12567:
12568: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1.1.1.8 root 12569: TCGV_UNUSED(cpu_gpr[0]);
12570: for (i = 1; i < 32; i++)
1.1.1.7 root 12571: cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
12572: offsetof(CPUState, active_tc.gpr[i]),
12573: regnames[i]);
12574: cpu_PC = tcg_global_mem_new(TCG_AREG0,
12575: offsetof(CPUState, active_tc.PC), "PC");
12576: for (i = 0; i < MIPS_DSP_ACC; i++) {
12577: cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
12578: offsetof(CPUState, active_tc.HI[i]),
12579: regnames_HI[i]);
12580: cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
12581: offsetof(CPUState, active_tc.LO[i]),
12582: regnames_LO[i]);
12583: cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
12584: offsetof(CPUState, active_tc.ACX[i]),
12585: regnames_ACX[i]);
12586: }
12587: cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
12588: offsetof(CPUState, active_tc.DSPControl),
12589: "DSPControl");
1.1.1.8 root 12590: bcond = tcg_global_mem_new(TCG_AREG0,
12591: offsetof(CPUState, bcond), "bcond");
1.1.1.7 root 12592: btarget = tcg_global_mem_new(TCG_AREG0,
12593: offsetof(CPUState, btarget), "btarget");
1.1.1.8 root 12594: hflags = tcg_global_mem_new_i32(TCG_AREG0,
12595: offsetof(CPUState, hflags), "hflags");
12596:
1.1.1.7 root 12597: fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
12598: offsetof(CPUState, active_fpu.fcr0),
12599: "fcr0");
12600: fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
12601: offsetof(CPUState, active_fpu.fcr31),
12602: "fcr31");
12603:
12604: /* register helpers */
12605: #define GEN_HELPER 2
12606: #include "helper.h"
12607:
12608: inited = 1;
12609: }
12610:
1.1.1.6 root 12611: #include "translate_init.c"
12612:
12613: CPUMIPSState *cpu_mips_init (const char *cpu_model)
1.1 root 12614: {
12615: CPUMIPSState *env;
1.1.1.6 root 12616: const mips_def_t *def;
1.1 root 12617:
1.1.1.6 root 12618: def = cpu_mips_find_by_name(cpu_model);
12619: if (!def)
12620: return NULL;
1.1 root 12621: env = qemu_mallocz(sizeof(CPUMIPSState));
1.1.1.6 root 12622: env->cpu_model = def;
1.1.1.9 root 12623: env->cpu_model_str = cpu_model;
1.1.1.6 root 12624:
1.1.1.2 root 12625: cpu_exec_init(env);
1.1.1.9 root 12626: #ifndef CONFIG_USER_ONLY
12627: mmu_init(env, def);
12628: #endif
12629: fpu_init(env, def);
12630: mvp_init(env, def);
1.1.1.7 root 12631: mips_tcg_init();
1.1.1.5 root 12632: cpu_reset(env);
1.1.1.8 root 12633: qemu_init_vcpu(env);
1.1.1.5 root 12634: return env;
12635: }
12636:
12637: void cpu_reset (CPUMIPSState *env)
12638: {
1.1.1.7 root 12639: if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12640: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12641: log_cpu_state(env, 0);
12642: }
12643:
1.1.1.5 root 12644: memset(env, 0, offsetof(CPUMIPSState, breakpoints));
1.1 root 12645: tlb_flush(env, 1);
1.1.1.5 root 12646:
1.1.1.9 root 12647: /* Reset registers to their default values */
12648: env->CP0_PRid = env->cpu_model->CP0_PRid;
12649: env->CP0_Config0 = env->cpu_model->CP0_Config0;
12650: #ifdef TARGET_WORDS_BIGENDIAN
12651: env->CP0_Config0 |= (1 << CP0C0_BE);
12652: #endif
12653: env->CP0_Config1 = env->cpu_model->CP0_Config1;
12654: env->CP0_Config2 = env->cpu_model->CP0_Config2;
12655: env->CP0_Config3 = env->cpu_model->CP0_Config3;
12656: env->CP0_Config6 = env->cpu_model->CP0_Config6;
12657: env->CP0_Config7 = env->cpu_model->CP0_Config7;
12658: env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12659: << env->cpu_model->CP0_LLAddr_shift;
12660: env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
12661: env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12662: env->CCRes = env->cpu_model->CCRes;
12663: env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12664: env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12665: env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12666: env->current_tc = 0;
12667: env->SEGBITS = env->cpu_model->SEGBITS;
12668: env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12669: #if defined(TARGET_MIPS64)
12670: if (env->cpu_model->insn_flags & ISA_MIPS3) {
12671: env->SEGMask |= 3ULL << 62;
12672: }
12673: #endif
12674: env->PABITS = env->cpu_model->PABITS;
12675: env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12676: env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12677: env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12678: env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12679: env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12680: env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12681: env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12682: env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12683: env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12684: env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12685: env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
12686: env->insn_flags = env->cpu_model->insn_flags;
12687:
1.1.1.7 root 12688: #if defined(CONFIG_USER_ONLY)
12689: env->hflags = MIPS_HFLAG_UM;
1.1.1.8 root 12690: /* Enable access to the SYNCI_Step register. */
12691: env->CP0_HWREna |= (1 << 1);
1.1.1.9 root 12692: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12693: env->hflags |= MIPS_HFLAG_FPU;
12694: }
12695: #ifdef TARGET_MIPS64
12696: if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
12697: env->hflags |= MIPS_HFLAG_F64;
12698: }
12699: #endif
1.1.1.7 root 12700: #else
1.1.1.5 root 12701: if (env->hflags & MIPS_HFLAG_BMASK) {
12702: /* If the exception was raised from a delay slot,
1.1.1.7 root 12703: come back to the jump. */
12704: env->CP0_ErrorEPC = env->active_tc.PC - 4;
1.1.1.5 root 12705: } else {
1.1.1.7 root 12706: env->CP0_ErrorEPC = env->active_tc.PC;
1.1.1.5 root 12707: }
1.1.1.7 root 12708: env->active_tc.PC = (int32_t)0xBFC00000;
1.1.1.9 root 12709: env->CP0_Random = env->tlb->nb_tlb - 1;
12710: env->tlb->tlb_in_use = env->tlb->nb_tlb;
1.1 root 12711: env->CP0_Wired = 0;
1.1.1.13 root 12712: env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
1.1.1.5 root 12713: env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
1.1.1.6 root 12714: /* vectored interrupts not implemented, timer on int 7,
12715: no performance counters. */
12716: env->CP0_IntCtl = 0xe0000000;
12717: {
12718: int i;
12719:
12720: for (i = 0; i < 7; i++) {
12721: env->CP0_WatchLo[i] = 0;
12722: env->CP0_WatchHi[i] = 0x80000000;
12723: }
12724: env->CP0_WatchLo[7] = 0;
12725: env->CP0_WatchHi[7] = 0;
12726: }
1.1 root 12727: /* Count register increments in debug mode, EJTAG version 1 */
12728: env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
1.1.1.6 root 12729: env->hflags = MIPS_HFLAG_CP0;
1.1.1.2 root 12730: #endif
1.1.1.9 root 12731: #if defined(TARGET_MIPS64)
12732: if (env->cpu_model->insn_flags & ISA_MIPS3) {
12733: env->hflags |= MIPS_HFLAG_64;
12734: }
12735: #endif
1.1.1.7 root 12736: env->exception_index = EXCP_NONE;
1.1 root 12737: }
1.1.1.7 root 12738:
1.1.1.14! root 12739: void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
1.1.1.7 root 12740: {
12741: env->active_tc.PC = gen_opc_pc[pc_pos];
12742: env->hflags &= ~MIPS_HFLAG_BMASK;
12743: env->hflags |= gen_opc_hflags[pc_pos];
12744: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.