|
|
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 "exec-all.h"
31: #include "disas.h"
1.1.1.7 root 32: #include "tcg-op.h"
33: #include "qemu-common.h"
34:
35: #include "helper.h"
36: #define GEN_HELPER 1
37: #include "helper.h"
1.1 root 38:
1.1.1.2 root 39: //#define MIPS_DEBUG_DISAS
1.1.1.5 root 40: //#define MIPS_DEBUG_SIGN_EXTENSIONS
1.1 root 41:
1.1.1.5 root 42: /* MIPS major opcodes */
43: #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
1.1 root 44:
45: enum {
46: /* indirect opcode tables */
1.1.1.5 root 47: OPC_SPECIAL = (0x00 << 26),
48: OPC_REGIMM = (0x01 << 26),
49: OPC_CP0 = (0x10 << 26),
50: OPC_CP1 = (0x11 << 26),
51: OPC_CP2 = (0x12 << 26),
52: OPC_CP3 = (0x13 << 26),
53: OPC_SPECIAL2 = (0x1C << 26),
54: OPC_SPECIAL3 = (0x1F << 26),
1.1 root 55: /* arithmetic with immediate */
1.1.1.5 root 56: OPC_ADDI = (0x08 << 26),
57: OPC_ADDIU = (0x09 << 26),
58: OPC_SLTI = (0x0A << 26),
59: OPC_SLTIU = (0x0B << 26),
1.1.1.8 root 60: /* logic with immediate */
1.1.1.5 root 61: OPC_ANDI = (0x0C << 26),
62: OPC_ORI = (0x0D << 26),
63: OPC_XORI = (0x0E << 26),
64: OPC_LUI = (0x0F << 26),
1.1.1.8 root 65: /* arithmetic with immediate */
1.1.1.5 root 66: OPC_DADDI = (0x18 << 26),
67: OPC_DADDIU = (0x19 << 26),
1.1 root 68: /* Jump and branches */
1.1.1.5 root 69: OPC_J = (0x02 << 26),
70: OPC_JAL = (0x03 << 26),
1.1.1.12 root 71: OPC_JALS = OPC_JAL | 0x5,
1.1.1.5 root 72: OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
73: OPC_BEQL = (0x14 << 26),
74: OPC_BNE = (0x05 << 26),
75: OPC_BNEL = (0x15 << 26),
76: OPC_BLEZ = (0x06 << 26),
77: OPC_BLEZL = (0x16 << 26),
78: OPC_BGTZ = (0x07 << 26),
79: OPC_BGTZL = (0x17 << 26),
80: OPC_JALX = (0x1D << 26), /* MIPS 16 only */
1.1.1.12 root 81: OPC_JALXS = OPC_JALX | 0x5,
1.1 root 82: /* Load and stores */
1.1.1.5 root 83: OPC_LDL = (0x1A << 26),
84: OPC_LDR = (0x1B << 26),
85: OPC_LB = (0x20 << 26),
86: OPC_LH = (0x21 << 26),
87: OPC_LWL = (0x22 << 26),
88: OPC_LW = (0x23 << 26),
1.1.1.12 root 89: OPC_LWPC = OPC_LW | 0x5,
1.1.1.5 root 90: OPC_LBU = (0x24 << 26),
91: OPC_LHU = (0x25 << 26),
92: OPC_LWR = (0x26 << 26),
93: OPC_LWU = (0x27 << 26),
94: OPC_SB = (0x28 << 26),
95: OPC_SH = (0x29 << 26),
96: OPC_SWL = (0x2A << 26),
97: OPC_SW = (0x2B << 26),
98: OPC_SDL = (0x2C << 26),
99: OPC_SDR = (0x2D << 26),
100: OPC_SWR = (0x2E << 26),
101: OPC_LL = (0x30 << 26),
102: OPC_LLD = (0x34 << 26),
103: OPC_LD = (0x37 << 26),
1.1.1.12 root 104: OPC_LDPC = OPC_LD | 0x5,
1.1.1.5 root 105: OPC_SC = (0x38 << 26),
106: OPC_SCD = (0x3C << 26),
107: OPC_SD = (0x3F << 26),
1.1 root 108: /* Floating point load/store */
1.1.1.5 root 109: OPC_LWC1 = (0x31 << 26),
110: OPC_LWC2 = (0x32 << 26),
111: OPC_LDC1 = (0x35 << 26),
112: OPC_LDC2 = (0x36 << 26),
113: OPC_SWC1 = (0x39 << 26),
114: OPC_SWC2 = (0x3A << 26),
115: OPC_SDC1 = (0x3D << 26),
116: OPC_SDC2 = (0x3E << 26),
117: /* MDMX ASE specific */
118: OPC_MDMX = (0x1E << 26),
1.1 root 119: /* Cache and prefetch */
1.1.1.5 root 120: OPC_CACHE = (0x2F << 26),
121: OPC_PREF = (0x33 << 26),
122: /* Reserved major opcode */
123: OPC_MAJOR3B_RESERVED = (0x3B << 26),
1.1 root 124: };
125:
126: /* MIPS special opcodes */
1.1.1.5 root 127: #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
128:
1.1 root 129: enum {
130: /* Shifts */
1.1.1.5 root 131: OPC_SLL = 0x00 | OPC_SPECIAL,
1.1 root 132: /* NOP is SLL r0, r0, 0 */
133: /* SSNOP is SLL r0, r0, 1 */
1.1.1.5 root 134: /* EHB is SLL r0, r0, 3 */
135: OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
1.1.1.12 root 136: OPC_ROTR = OPC_SRL | (1 << 21),
1.1.1.5 root 137: OPC_SRA = 0x03 | OPC_SPECIAL,
138: OPC_SLLV = 0x04 | OPC_SPECIAL,
1.1.1.6 root 139: OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
1.1.1.12 root 140: OPC_ROTRV = OPC_SRLV | (1 << 6),
1.1.1.5 root 141: OPC_SRAV = 0x07 | OPC_SPECIAL,
142: OPC_DSLLV = 0x14 | OPC_SPECIAL,
143: OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
1.1.1.12 root 144: OPC_DROTRV = OPC_DSRLV | (1 << 6),
1.1.1.5 root 145: OPC_DSRAV = 0x17 | OPC_SPECIAL,
146: OPC_DSLL = 0x38 | OPC_SPECIAL,
147: OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
1.1.1.12 root 148: OPC_DROTR = OPC_DSRL | (1 << 21),
1.1.1.5 root 149: OPC_DSRA = 0x3B | OPC_SPECIAL,
150: OPC_DSLL32 = 0x3C | OPC_SPECIAL,
151: OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
1.1.1.12 root 152: OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
1.1.1.5 root 153: OPC_DSRA32 = 0x3F | OPC_SPECIAL,
1.1 root 154: /* Multiplication / division */
1.1.1.5 root 155: OPC_MULT = 0x18 | OPC_SPECIAL,
156: OPC_MULTU = 0x19 | OPC_SPECIAL,
157: OPC_DIV = 0x1A | OPC_SPECIAL,
158: OPC_DIVU = 0x1B | OPC_SPECIAL,
159: OPC_DMULT = 0x1C | OPC_SPECIAL,
160: OPC_DMULTU = 0x1D | OPC_SPECIAL,
161: OPC_DDIV = 0x1E | OPC_SPECIAL,
162: OPC_DDIVU = 0x1F | OPC_SPECIAL,
1.1 root 163: /* 2 registers arithmetic / logic */
1.1.1.5 root 164: OPC_ADD = 0x20 | OPC_SPECIAL,
165: OPC_ADDU = 0x21 | OPC_SPECIAL,
166: OPC_SUB = 0x22 | OPC_SPECIAL,
167: OPC_SUBU = 0x23 | OPC_SPECIAL,
168: OPC_AND = 0x24 | OPC_SPECIAL,
169: OPC_OR = 0x25 | OPC_SPECIAL,
170: OPC_XOR = 0x26 | OPC_SPECIAL,
171: OPC_NOR = 0x27 | OPC_SPECIAL,
172: OPC_SLT = 0x2A | OPC_SPECIAL,
173: OPC_SLTU = 0x2B | OPC_SPECIAL,
174: OPC_DADD = 0x2C | OPC_SPECIAL,
175: OPC_DADDU = 0x2D | OPC_SPECIAL,
176: OPC_DSUB = 0x2E | OPC_SPECIAL,
177: OPC_DSUBU = 0x2F | OPC_SPECIAL,
1.1 root 178: /* Jumps */
1.1.1.5 root 179: OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
180: OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
1.1.1.12 root 181: OPC_JALRC = OPC_JALR | (0x5 << 6),
182: OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
1.1 root 183: /* Traps */
1.1.1.5 root 184: OPC_TGE = 0x30 | OPC_SPECIAL,
185: OPC_TGEU = 0x31 | OPC_SPECIAL,
186: OPC_TLT = 0x32 | OPC_SPECIAL,
187: OPC_TLTU = 0x33 | OPC_SPECIAL,
188: OPC_TEQ = 0x34 | OPC_SPECIAL,
189: OPC_TNE = 0x36 | OPC_SPECIAL,
1.1 root 190: /* HI / LO registers load & stores */
1.1.1.5 root 191: OPC_MFHI = 0x10 | OPC_SPECIAL,
192: OPC_MTHI = 0x11 | OPC_SPECIAL,
193: OPC_MFLO = 0x12 | OPC_SPECIAL,
194: OPC_MTLO = 0x13 | OPC_SPECIAL,
1.1 root 195: /* Conditional moves */
1.1.1.5 root 196: OPC_MOVZ = 0x0A | OPC_SPECIAL,
197: OPC_MOVN = 0x0B | OPC_SPECIAL,
1.1 root 198:
1.1.1.5 root 199: OPC_MOVCI = 0x01 | OPC_SPECIAL,
1.1 root 200:
201: /* Special */
1.1.1.9 root 202: OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
1.1.1.5 root 203: OPC_SYSCALL = 0x0C | OPC_SPECIAL,
204: OPC_BREAK = 0x0D | OPC_SPECIAL,
1.1.1.9 root 205: OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
1.1.1.5 root 206: OPC_SYNC = 0x0F | OPC_SPECIAL,
207:
208: OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
209: OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
210: OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
211: OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
212: OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
213: OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
214: OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
215: };
216:
1.1.1.6 root 217: /* Multiplication variants of the vr54xx. */
218: #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
219:
220: enum {
221: OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
222: OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
223: OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
224: OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
225: OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
226: OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
227: OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
228: OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
229: OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
230: OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
231: OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
232: OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
233: OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
234: OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
235: };
236:
1.1.1.5 root 237: /* REGIMM (rt field) opcodes */
238: #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
239:
240: enum {
241: OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
242: OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
243: OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
244: OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
245: OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
1.1.1.12 root 246: OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
1.1.1.5 root 247: OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
248: OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
1.1.1.12 root 249: OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
1.1.1.5 root 250: OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
251: OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
252: OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
253: OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
254: OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
255: OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
256: OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
257: OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
1.1 root 258: };
259:
1.1.1.5 root 260: /* Special2 opcodes */
261: #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
262:
1.1 root 263: enum {
1.1.1.5 root 264: /* Multiply & xxx operations */
265: OPC_MADD = 0x00 | OPC_SPECIAL2,
266: OPC_MADDU = 0x01 | OPC_SPECIAL2,
267: OPC_MUL = 0x02 | OPC_SPECIAL2,
268: OPC_MSUB = 0x04 | OPC_SPECIAL2,
269: OPC_MSUBU = 0x05 | OPC_SPECIAL2,
1.1.1.12 root 270: /* Loongson 2F */
271: OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
272: OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
273: OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
274: OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
275: OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
276: OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
277: OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
278: OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
279: OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
280: OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
281: OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
282: OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
1.1 root 283: /* Misc */
1.1.1.5 root 284: OPC_CLZ = 0x20 | OPC_SPECIAL2,
285: OPC_CLO = 0x21 | OPC_SPECIAL2,
286: OPC_DCLZ = 0x24 | OPC_SPECIAL2,
287: OPC_DCLO = 0x25 | OPC_SPECIAL2,
1.1 root 288: /* Special */
1.1.1.5 root 289: OPC_SDBBP = 0x3F | OPC_SPECIAL2,
290: };
291:
292: /* Special3 opcodes */
293: #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
294:
295: enum {
296: OPC_EXT = 0x00 | OPC_SPECIAL3,
297: OPC_DEXTM = 0x01 | OPC_SPECIAL3,
298: OPC_DEXTU = 0x02 | OPC_SPECIAL3,
299: OPC_DEXT = 0x03 | OPC_SPECIAL3,
300: OPC_INS = 0x04 | OPC_SPECIAL3,
301: OPC_DINSM = 0x05 | OPC_SPECIAL3,
302: OPC_DINSU = 0x06 | OPC_SPECIAL3,
303: OPC_DINS = 0x07 | OPC_SPECIAL3,
1.1.1.6 root 304: OPC_FORK = 0x08 | OPC_SPECIAL3,
305: OPC_YIELD = 0x09 | OPC_SPECIAL3,
1.1.1.5 root 306: OPC_BSHFL = 0x20 | OPC_SPECIAL3,
307: OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
308: OPC_RDHWR = 0x3B | OPC_SPECIAL3,
1.1.1.12 root 309:
310: /* Loongson 2E */
311: OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
312: OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
313: OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
314: OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
315: OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
316: OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
317: OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
318: OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
319: OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
320: OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
321: OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
322: OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
1.1 root 323: };
324:
1.1.1.5 root 325: /* BSHFL opcodes */
326: #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
327:
1.1 root 328: enum {
1.1.1.5 root 329: OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
330: OPC_SEB = (0x10 << 6) | OPC_BSHFL,
331: OPC_SEH = (0x18 << 6) | OPC_BSHFL,
1.1 root 332: };
333:
1.1.1.5 root 334: /* DBSHFL opcodes */
335: #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
336:
1.1 root 337: enum {
1.1.1.5 root 338: OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
339: OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
1.1 root 340: };
341:
1.1.1.5 root 342: /* Coprocessor 0 (rs field) */
343: #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
344:
1.1.1.4 root 345: enum {
1.1.1.5 root 346: OPC_MFC0 = (0x00 << 21) | OPC_CP0,
347: OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
348: OPC_MTC0 = (0x04 << 21) | OPC_CP0,
349: OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
1.1.1.6 root 350: OPC_MFTR = (0x08 << 21) | OPC_CP0,
1.1.1.5 root 351: OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
352: OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
1.1.1.6 root 353: OPC_MTTR = (0x0C << 21) | OPC_CP0,
1.1.1.5 root 354: OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
355: OPC_C0 = (0x10 << 21) | OPC_CP0,
356: OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
357: OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
1.1.1.4 root 358: };
1.1.1.5 root 359:
360: /* MFMC0 opcodes */
1.1.1.6 root 361: #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
1.1.1.5 root 362:
363: enum {
1.1.1.6 root 364: OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
365: OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
366: OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
367: OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
1.1.1.5 root 368: OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
369: OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
370: };
371:
372: /* Coprocessor 0 (with rs == C0) */
373: #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
374:
375: enum {
376: OPC_TLBR = 0x01 | OPC_C0,
377: OPC_TLBWI = 0x02 | OPC_C0,
378: OPC_TLBWR = 0x06 | OPC_C0,
379: OPC_TLBP = 0x08 | OPC_C0,
380: OPC_RFE = 0x10 | OPC_C0,
381: OPC_ERET = 0x18 | OPC_C0,
382: OPC_DERET = 0x1F | OPC_C0,
383: OPC_WAIT = 0x20 | OPC_C0,
384: };
385:
386: /* Coprocessor 1 (rs field) */
387: #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
388:
1.1.1.12 root 389: /* Values for the fmt field in FP instructions */
390: enum {
391: /* 0 - 15 are reserved */
392: FMT_S = 16, /* single fp */
393: FMT_D = 17, /* double fp */
394: FMT_E = 18, /* extended fp */
395: FMT_Q = 19, /* quad fp */
396: FMT_W = 20, /* 32-bit fixed */
397: FMT_L = 21, /* 64-bit fixed */
398: FMT_PS = 22, /* paired single fp */
399: /* 23 - 31 are reserved */
400: };
401:
1.1.1.5 root 402: enum {
403: OPC_MFC1 = (0x00 << 21) | OPC_CP1,
404: OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
405: OPC_CFC1 = (0x02 << 21) | OPC_CP1,
1.1.1.6 root 406: OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
1.1.1.5 root 407: OPC_MTC1 = (0x04 << 21) | OPC_CP1,
408: OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
409: OPC_CTC1 = (0x06 << 21) | OPC_CP1,
1.1.1.6 root 410: OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
1.1.1.5 root 411: OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
1.1.1.6 root 412: OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
413: OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
1.1.1.12 root 414: OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
415: OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
416: OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
417: OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
418: OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
419: OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
420: OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
1.1.1.5 root 421: };
422:
1.1.1.6 root 423: #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
424: #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
425:
1.1.1.5 root 426: enum {
427: OPC_BC1F = (0x00 << 16) | OPC_BC1,
428: OPC_BC1T = (0x01 << 16) | OPC_BC1,
429: OPC_BC1FL = (0x02 << 16) | OPC_BC1,
430: OPC_BC1TL = (0x03 << 16) | OPC_BC1,
431: };
432:
1.1.1.6 root 433: enum {
434: OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
435: OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
436: };
437:
438: enum {
439: OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
440: OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
441: };
1.1.1.5 root 442:
443: #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1.1.1.6 root 444:
445: enum {
446: OPC_MFC2 = (0x00 << 21) | OPC_CP2,
447: OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
448: OPC_CFC2 = (0x02 << 21) | OPC_CP2,
449: OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
450: OPC_MTC2 = (0x04 << 21) | OPC_CP2,
451: OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
452: OPC_CTC2 = (0x06 << 21) | OPC_CP2,
453: OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
454: OPC_BC2 = (0x08 << 21) | OPC_CP2,
455: };
456:
457: #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
458:
459: enum {
460: OPC_LWXC1 = 0x00 | OPC_CP3,
461: OPC_LDXC1 = 0x01 | OPC_CP3,
462: OPC_LUXC1 = 0x05 | OPC_CP3,
463: OPC_SWXC1 = 0x08 | OPC_CP3,
464: OPC_SDXC1 = 0x09 | OPC_CP3,
465: OPC_SUXC1 = 0x0D | OPC_CP3,
466: OPC_PREFX = 0x0F | OPC_CP3,
467: OPC_ALNV_PS = 0x1E | OPC_CP3,
468: OPC_MADD_S = 0x20 | OPC_CP3,
469: OPC_MADD_D = 0x21 | OPC_CP3,
470: OPC_MADD_PS = 0x26 | OPC_CP3,
471: OPC_MSUB_S = 0x28 | OPC_CP3,
472: OPC_MSUB_D = 0x29 | OPC_CP3,
473: OPC_MSUB_PS = 0x2E | OPC_CP3,
474: OPC_NMADD_S = 0x30 | OPC_CP3,
475: OPC_NMADD_D = 0x31 | OPC_CP3,
476: OPC_NMADD_PS= 0x36 | OPC_CP3,
477: OPC_NMSUB_S = 0x38 | OPC_CP3,
478: OPC_NMSUB_D = 0x39 | OPC_CP3,
479: OPC_NMSUB_PS= 0x3E | OPC_CP3,
480: };
481:
1.1.1.7 root 482: /* global register indices */
483: static TCGv_ptr cpu_env;
484: static TCGv cpu_gpr[32], cpu_PC;
485: static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
1.1.1.8 root 486: static TCGv cpu_dspctrl, btarget, bcond;
487: static TCGv_i32 hflags;
1.1.1.7 root 488: static TCGv_i32 fpu_fcr0, fpu_fcr31;
489:
1.1.1.12 root 490: static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
491:
1.1.1.7 root 492: #include "gen-icount.h"
493:
494: #define gen_helper_0i(name, arg) do { \
495: TCGv_i32 helper_tmp = tcg_const_i32(arg); \
496: gen_helper_##name(helper_tmp); \
497: tcg_temp_free_i32(helper_tmp); \
498: } while(0)
1.1.1.4 root 499:
1.1.1.7 root 500: #define gen_helper_1i(name, arg1, arg2) do { \
501: TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
502: gen_helper_##name(arg1, helper_tmp); \
503: tcg_temp_free_i32(helper_tmp); \
504: } while(0)
1.1.1.4 root 505:
1.1.1.7 root 506: #define gen_helper_2i(name, arg1, arg2, arg3) do { \
507: TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
508: gen_helper_##name(arg1, arg2, helper_tmp); \
509: tcg_temp_free_i32(helper_tmp); \
510: } while(0)
1.1.1.4 root 511:
1.1.1.7 root 512: #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
513: TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
514: gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
515: tcg_temp_free_i32(helper_tmp); \
516: } while(0)
1.1.1.4 root 517:
1.1 root 518: typedef struct DisasContext {
519: struct TranslationBlock *tb;
520: target_ulong pc, saved_pc;
521: uint32_t opcode;
1.1.1.9 root 522: int singlestep_enabled;
1.1 root 523: /* Routine used to access memory */
524: int mem_idx;
525: uint32_t hflags, saved_hflags;
526: int bstate;
527: target_ulong btarget;
528: } DisasContext;
529:
530: enum {
531: BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1.1.1.7 root 532: * exception condition */
1.1 root 533: BS_STOP = 1, /* We want to stop translation for any reason */
534: BS_BRANCH = 2, /* We reached a branch condition */
535: BS_EXCP = 3, /* We reached an exception condition */
536: };
537:
1.1.1.7 root 538: static const char *regnames[] =
539: { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
540: "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
541: "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
542: "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
543:
544: static const char *regnames_HI[] =
545: { "HI0", "HI1", "HI2", "HI3", };
546:
547: static const char *regnames_LO[] =
548: { "LO0", "LO1", "LO2", "LO3", };
549:
550: static const char *regnames_ACX[] =
551: { "ACX0", "ACX1", "ACX2", "ACX3", };
552:
553: static const char *fregnames[] =
554: { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
555: "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
556: "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
557: "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
558:
1.1.1.6 root 559: #ifdef MIPS_DEBUG_DISAS
1.1.1.8 root 560: #define MIPS_DEBUG(fmt, ...) \
1.1.1.7 root 561: qemu_log_mask(CPU_LOG_TB_IN_ASM, \
562: TARGET_FMT_lx ": %08x " fmt "\n", \
1.1.1.8 root 563: ctx->pc, ctx->opcode , ## __VA_ARGS__)
1.1.1.7 root 564: #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
1.1 root 565: #else
1.1.1.8 root 566: #define MIPS_DEBUG(fmt, ...) do { } while(0)
1.1.1.7 root 567: #define LOG_DISAS(...) do { } while (0)
1.1 root 568: #endif
569:
570: #define MIPS_INVAL(op) \
571: do { \
572: MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
573: ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
574: } while (0)
575:
1.1.1.7 root 576: /* General purpose registers moves. */
577: static inline void gen_load_gpr (TCGv t, int reg)
578: {
579: if (reg == 0)
580: tcg_gen_movi_tl(t, 0);
581: else
582: tcg_gen_mov_tl(t, cpu_gpr[reg]);
583: }
1.1.1.6 root 584:
1.1.1.7 root 585: static inline void gen_store_gpr (TCGv t, int reg)
586: {
587: if (reg != 0)
588: tcg_gen_mov_tl(cpu_gpr[reg], t);
589: }
1.1.1.6 root 590:
1.1.1.7 root 591: /* Moves to/from ACX register. */
592: static inline void gen_load_ACX (TCGv t, int reg)
593: {
594: tcg_gen_mov_tl(t, cpu_ACX[reg]);
595: }
1.1.1.6 root 596:
1.1.1.7 root 597: static inline void gen_store_ACX (TCGv t, int reg)
598: {
599: tcg_gen_mov_tl(cpu_ACX[reg], t);
600: }
1.1 root 601:
1.1.1.7 root 602: /* Moves to/from shadow registers. */
603: static inline void gen_load_srsgpr (int from, int to)
604: {
1.1.1.8 root 605: TCGv t0 = tcg_temp_new();
1.1.1.6 root 606:
1.1.1.7 root 607: if (from == 0)
1.1.1.8 root 608: tcg_gen_movi_tl(t0, 0);
1.1.1.7 root 609: else {
1.1.1.8 root 610: TCGv_i32 t2 = tcg_temp_new_i32();
1.1.1.7 root 611: TCGv_ptr addr = tcg_temp_new_ptr();
1.1.1.6 root 612:
1.1.1.8 root 613: tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
614: tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
615: tcg_gen_andi_i32(t2, t2, 0xf);
616: tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
617: tcg_gen_ext_i32_ptr(addr, t2);
1.1.1.7 root 618: tcg_gen_add_ptr(addr, cpu_env, addr);
1.1 root 619:
1.1.1.8 root 620: tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1.1.1.7 root 621: tcg_temp_free_ptr(addr);
1.1.1.8 root 622: tcg_temp_free_i32(t2);
1.1.1.7 root 623: }
1.1.1.8 root 624: gen_store_gpr(t0, to);
625: tcg_temp_free(t0);
1.1.1.7 root 626: }
1.1 root 627:
1.1.1.7 root 628: static inline void gen_store_srsgpr (int from, int to)
629: {
630: if (to != 0) {
1.1.1.8 root 631: TCGv t0 = tcg_temp_new();
632: TCGv_i32 t2 = tcg_temp_new_i32();
1.1.1.7 root 633: TCGv_ptr addr = tcg_temp_new_ptr();
1.1.1.4 root 634:
1.1.1.8 root 635: gen_load_gpr(t0, from);
636: tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
637: tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
638: tcg_gen_andi_i32(t2, t2, 0xf);
639: tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
640: tcg_gen_ext_i32_ptr(addr, t2);
1.1.1.7 root 641: tcg_gen_add_ptr(addr, cpu_env, addr);
1.1.1.4 root 642:
1.1.1.8 root 643: tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1.1.1.7 root 644: tcg_temp_free_ptr(addr);
1.1.1.8 root 645: tcg_temp_free_i32(t2);
646: tcg_temp_free(t0);
1.1.1.6 root 647: }
648: }
649:
1.1.1.7 root 650: /* Floating point register moves. */
651: static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
1.1.1.6 root 652: {
1.1.1.8 root 653: tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
1.1.1.7 root 654: }
655:
656: static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
657: {
1.1.1.8 root 658: tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
1.1.1.7 root 659: }
660:
1.1.1.8 root 661: static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
1.1.1.7 root 662: {
1.1.1.8 root 663: tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
1.1.1.6 root 664: }
665:
1.1.1.8 root 666: static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
1.1 root 667: {
1.1.1.8 root 668: tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
1.1.1.7 root 669: }
670:
1.1.1.8 root 671: static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
1.1.1.7 root 672: {
1.1.1.8 root 673: if (ctx->hflags & MIPS_HFLAG_F64) {
674: tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
675: } else {
676: TCGv_i32 t0 = tcg_temp_new_i32();
677: TCGv_i32 t1 = tcg_temp_new_i32();
678: gen_load_fpr32(t0, reg & ~1);
679: gen_load_fpr32(t1, reg | 1);
680: tcg_gen_concat_i32_i64(t, t0, t1);
681: tcg_temp_free_i32(t0);
682: tcg_temp_free_i32(t1);
683: }
1.1.1.7 root 684: }
685:
1.1.1.8 root 686: static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
1.1.1.7 root 687: {
1.1.1.8 root 688: if (ctx->hflags & MIPS_HFLAG_F64) {
689: tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
690: } else {
691: TCGv_i64 t0 = tcg_temp_new_i64();
692: TCGv_i32 t1 = tcg_temp_new_i32();
693: tcg_gen_trunc_i64_i32(t1, t);
694: gen_store_fpr32(t1, reg & ~1);
695: tcg_gen_shri_i64(t0, t, 32);
696: tcg_gen_trunc_i64_i32(t1, t0);
697: gen_store_fpr32(t1, reg | 1);
698: tcg_temp_free_i32(t1);
699: tcg_temp_free_i64(t0);
700: }
1.1.1.7 root 701: }
702:
1.1.1.8 root 703: static inline int get_fp_bit (int cc)
1.1.1.7 root 704: {
1.1.1.8 root 705: if (cc)
706: return 24 + cc;
707: else
708: return 23;
1.1.1.7 root 709: }
710:
711: /* Tests */
712: static inline void gen_save_pc(target_ulong pc)
713: {
714: tcg_gen_movi_tl(cpu_PC, pc);
715: }
716:
717: static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
718: {
719: LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1.1 root 720: if (do_save_pc && ctx->pc != ctx->saved_pc) {
1.1.1.6 root 721: gen_save_pc(ctx->pc);
1.1 root 722: ctx->saved_pc = ctx->pc;
723: }
724: if (ctx->hflags != ctx->saved_hflags) {
1.1.1.8 root 725: tcg_gen_movi_i32(hflags, ctx->hflags);
1.1 root 726: ctx->saved_hflags = ctx->hflags;
1.1.1.12 root 727: switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1.1.1.6 root 728: case MIPS_HFLAG_BR:
729: break;
730: case MIPS_HFLAG_BC:
731: case MIPS_HFLAG_BL:
732: case MIPS_HFLAG_B:
1.1.1.7 root 733: tcg_gen_movi_tl(btarget, ctx->btarget);
1.1.1.6 root 734: break;
1.1 root 735: }
736: }
737: }
738:
1.1.1.7 root 739: static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
1.1.1.6 root 740: {
741: ctx->saved_hflags = ctx->hflags;
1.1.1.12 root 742: switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1.1.1.6 root 743: case MIPS_HFLAG_BR:
744: break;
745: case MIPS_HFLAG_BC:
746: case MIPS_HFLAG_BL:
1.1.1.7 root 747: case MIPS_HFLAG_B:
1.1.1.6 root 748: ctx->btarget = env->btarget;
749: break;
750: }
751: }
752:
1.1.1.7 root 753: static inline void
754: generate_exception_err (DisasContext *ctx, int excp, int err)
1.1 root 755: {
1.1.1.7 root 756: TCGv_i32 texcp = tcg_const_i32(excp);
757: TCGv_i32 terr = tcg_const_i32(err);
1.1 root 758: save_cpu_state(ctx, 1);
1.1.1.7 root 759: gen_helper_raise_exception_err(texcp, terr);
760: tcg_temp_free_i32(terr);
761: tcg_temp_free_i32(texcp);
762: }
763:
764: static inline void
765: generate_exception (DisasContext *ctx, int excp)
766: {
767: save_cpu_state(ctx, 1);
768: gen_helper_0i(raise_exception, excp);
1.1 root 769: }
770:
1.1.1.7 root 771: /* Addresses computation */
1.1.1.9 root 772: static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1.1.1.2 root 773: {
1.1.1.9 root 774: tcg_gen_add_tl(ret, arg0, arg1);
1.1.1.7 root 775:
776: #if defined(TARGET_MIPS64)
777: /* For compatibility with 32-bit code, data reference in user mode
778: with Status_UX = 0 should be casted to 32-bit and sign extended.
779: See the MIPS64 PRA manual, section 4.10. */
780: if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
781: !(ctx->hflags & MIPS_HFLAG_UX)) {
1.1.1.9 root 782: tcg_gen_ext32s_i64(ret, ret);
1.1.1.7 root 783: }
784: #endif
1.1.1.2 root 785: }
786:
1.1.1.7 root 787: static inline void check_cp0_enabled(DisasContext *ctx)
1.1.1.6 root 788: {
789: if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1.1.1.10 root 790: generate_exception_err(ctx, EXCP_CpU, 0);
1.1.1.6 root 791: }
792:
1.1.1.7 root 793: static inline void check_cp1_enabled(DisasContext *ctx)
1.1.1.6 root 794: {
795: if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
796: generate_exception_err(ctx, EXCP_CpU, 1);
797: }
798:
799: /* Verify that the processor is running with COP1X instructions enabled.
800: This is associated with the nabla symbol in the MIPS32 and MIPS64
801: opcode tables. */
802:
1.1.1.7 root 803: static inline void check_cop1x(DisasContext *ctx)
1.1.1.6 root 804: {
805: if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
806: generate_exception(ctx, EXCP_RI);
807: }
808:
809: /* Verify that the processor is running with 64-bit floating-point
810: operations enabled. */
811:
1.1.1.7 root 812: static inline void check_cp1_64bitmode(DisasContext *ctx)
1.1.1.6 root 813: {
814: if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
815: generate_exception(ctx, EXCP_RI);
816: }
817:
818: /*
819: * Verify if floating point register is valid; an operation is not defined
820: * if bit 0 of any register specification is set and the FR bit in the
821: * Status register equals zero, since the register numbers specify an
822: * even-odd pair of adjacent coprocessor general registers. When the FR bit
823: * in the Status register equals one, both even and odd register numbers
824: * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
825: *
826: * Multiple 64 bit wide registers can be checked by calling
827: * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
828: */
1.1.1.7 root 829: static inline void check_cp1_registers(DisasContext *ctx, int regs)
1.1.1.6 root 830: {
831: if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
832: generate_exception(ctx, EXCP_RI);
833: }
834:
835: /* This code generates a "reserved instruction" exception if the
836: CPU does not support the instruction set corresponding to flags. */
1.1.1.7 root 837: static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
1.1.1.6 root 838: {
839: if (unlikely(!(env->insn_flags & flags)))
840: generate_exception(ctx, EXCP_RI);
841: }
842:
843: /* This code generates a "reserved instruction" exception if 64-bit
844: instructions are not enabled. */
1.1.1.7 root 845: static inline void check_mips_64(DisasContext *ctx)
1.1.1.6 root 846: {
847: if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
848: generate_exception(ctx, EXCP_RI);
849: }
850:
1.1.1.12 root 851: /* Define small wrappers for gen_load_fpr* so that we have a uniform
852: calling interface for 32 and 64-bit FPRs. No sense in changing
853: all callers for gen_load_fpr32 when we need the CTX parameter for
854: this one use. */
855: #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
856: #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
857: #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
858: static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
859: int ft, int fs, int cc) \
860: { \
861: TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
862: TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
863: switch (ifmt) { \
864: case FMT_PS: \
865: check_cp1_64bitmode(ctx); \
866: break; \
867: case FMT_D: \
868: if (abs) { \
869: check_cop1x(ctx); \
870: } \
871: check_cp1_registers(ctx, fs | ft); \
872: break; \
873: case FMT_S: \
874: if (abs) { \
875: check_cop1x(ctx); \
876: } \
877: break; \
878: } \
879: gen_ldcmp_fpr##bits (ctx, fp0, fs); \
880: gen_ldcmp_fpr##bits (ctx, fp1, ft); \
881: switch (n) { \
882: case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
883: case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
884: case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
885: case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
886: case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
887: case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
888: case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
889: case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
890: case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
891: case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
892: case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
893: case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
894: case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
895: case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
896: case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
897: case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
898: default: abort(); \
899: } \
900: tcg_temp_free_i##bits (fp0); \
901: tcg_temp_free_i##bits (fp1); \
902: }
903:
904: FOP_CONDS(, 0, d, FMT_D, 64)
905: FOP_CONDS(abs, 1, d, FMT_D, 64)
906: FOP_CONDS(, 0, s, FMT_S, 32)
907: FOP_CONDS(abs, 1, s, FMT_S, 32)
908: FOP_CONDS(, 0, ps, FMT_PS, 64)
909: FOP_CONDS(abs, 1, ps, FMT_PS, 64)
910: #undef FOP_CONDS
911: #undef gen_ldcmp_fpr32
912: #undef gen_ldcmp_fpr64
913:
1.1.1.7 root 914: /* load/store instructions. */
1.1.1.8 root 915: #define OP_LD(insn,fname) \
1.1.1.12 root 916: static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1.1.1.8 root 917: { \
918: tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1.1.1.7 root 919: }
920: OP_LD(lb,ld8s);
921: OP_LD(lbu,ld8u);
922: OP_LD(lh,ld16s);
923: OP_LD(lhu,ld16u);
924: OP_LD(lw,ld32s);
925: #if defined(TARGET_MIPS64)
926: OP_LD(lwu,ld32u);
927: OP_LD(ld,ld64);
928: #endif
929: #undef OP_LD
930:
1.1.1.8 root 931: #define OP_ST(insn,fname) \
1.1.1.12 root 932: static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
1.1.1.8 root 933: { \
934: tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
1.1.1.7 root 935: }
936: OP_ST(sb,st8);
937: OP_ST(sh,st16);
938: OP_ST(sw,st32);
939: #if defined(TARGET_MIPS64)
940: OP_ST(sd,st64);
941: #endif
942: #undef OP_ST
943:
1.1.1.9 root 944: #ifdef CONFIG_USER_ONLY
1.1.1.8 root 945: #define OP_LD_ATOMIC(insn,fname) \
1.1.1.12 root 946: static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1.1.1.8 root 947: { \
948: TCGv t0 = tcg_temp_new(); \
949: tcg_gen_mov_tl(t0, arg1); \
950: tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1.1.1.9 root 951: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
1.1.1.8 root 952: tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
953: tcg_temp_free(t0); \
1.1 root 954: }
1.1.1.9 root 955: #else
956: #define OP_LD_ATOMIC(insn,fname) \
1.1.1.12 root 957: static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1.1.1.9 root 958: { \
959: gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
960: }
961: #endif
1.1.1.7 root 962: OP_LD_ATOMIC(ll,ld32s);
963: #if defined(TARGET_MIPS64)
964: OP_LD_ATOMIC(lld,ld64);
1.1 root 965: #endif
1.1.1.7 root 966: #undef OP_LD_ATOMIC
1.1 root 967:
1.1.1.8 root 968: #ifdef CONFIG_USER_ONLY
969: #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1.1.1.12 root 970: static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1.1.1.8 root 971: { \
972: TCGv t0 = tcg_temp_new(); \
973: int l1 = gen_new_label(); \
974: int l2 = gen_new_label(); \
975: \
976: tcg_gen_andi_tl(t0, arg2, almask); \
977: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
978: tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
979: generate_exception(ctx, EXCP_AdES); \
980: gen_set_label(l1); \
1.1.1.9 root 981: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
1.1.1.8 root 982: tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
983: tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
984: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
985: tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
986: gen_helper_0i(raise_exception, EXCP_SC); \
987: gen_set_label(l2); \
988: tcg_gen_movi_tl(t0, 0); \
989: gen_store_gpr(t0, rt); \
990: tcg_temp_free(t0); \
991: }
992: #else
993: #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1.1.1.12 root 994: static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1.1.1.8 root 995: { \
996: TCGv t0 = tcg_temp_new(); \
1.1.1.9 root 997: gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
1.1.1.8 root 998: gen_store_gpr(t0, rt); \
999: tcg_temp_free(t0); \
1.1.1.7 root 1000: }
1.1.1.8 root 1001: #endif
1002: OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1.1.1.6 root 1003: #if defined(TARGET_MIPS64)
1.1.1.8 root 1004: OP_ST_ATOMIC(scd,st64,ld64,0x7);
1.1 root 1005: #endif
1.1.1.7 root 1006: #undef OP_ST_ATOMIC
1.1 root 1007:
1.1.1.12 root 1008: static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1009: int base, int16_t offset)
1.1 root 1010: {
1011: if (base == 0) {
1.1.1.12 root 1012: tcg_gen_movi_tl(addr, offset);
1.1 root 1013: } else if (offset == 0) {
1.1.1.12 root 1014: gen_load_gpr(addr, base);
1.1 root 1015: } else {
1.1.1.12 root 1016: tcg_gen_movi_tl(addr, offset);
1017: gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1.1 root 1018: }
1.1.1.12 root 1019: }
1020:
1021: static target_ulong pc_relative_pc (DisasContext *ctx)
1022: {
1023: target_ulong pc = ctx->pc;
1024:
1025: if (ctx->hflags & MIPS_HFLAG_BMASK) {
1026: int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1027:
1028: pc -= branch_bytes;
1029: }
1030:
1031: pc &= ~(target_ulong)3;
1032: return pc;
1033: }
1034:
1035: /* Load */
1036: static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
1037: int rt, int base, int16_t offset)
1038: {
1039: const char *opn = "ld";
1040: TCGv t0, t1;
1041:
1042: if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1043: /* Loongson CPU uses a load to zero register for prefetch.
1044: We emulate it as a NOP. On other CPU we must perform the
1045: actual memory access. */
1046: MIPS_DEBUG("NOP");
1047: return;
1048: }
1049:
1050: t0 = tcg_temp_new();
1051: t1 = tcg_temp_new();
1052: gen_base_offset_addr(ctx, t0, base, offset);
1053:
1.1 root 1054: switch (opc) {
1.1.1.6 root 1055: #if defined(TARGET_MIPS64)
1056: case OPC_LWU:
1.1.1.8 root 1057: save_cpu_state(ctx, 0);
1.1.1.12 root 1058: op_ld_lwu(t0, t0, ctx);
1.1.1.7 root 1059: gen_store_gpr(t0, rt);
1.1.1.6 root 1060: opn = "lwu";
1061: break;
1.1 root 1062: case OPC_LD:
1.1.1.8 root 1063: save_cpu_state(ctx, 0);
1.1.1.12 root 1064: op_ld_ld(t0, t0, ctx);
1.1.1.7 root 1065: gen_store_gpr(t0, rt);
1.1 root 1066: opn = "ld";
1067: break;
1.1.1.5 root 1068: case OPC_LLD:
1.1.1.13! root 1069: save_cpu_state(ctx, 1);
1.1.1.12 root 1070: op_ld_lld(t0, t0, ctx);
1.1.1.7 root 1071: gen_store_gpr(t0, rt);
1.1.1.5 root 1072: opn = "lld";
1073: break;
1.1 root 1074: case OPC_LDL:
1.1.1.7 root 1075: save_cpu_state(ctx, 1);
1076: gen_load_gpr(t1, rt);
1.1.1.8 root 1077: gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1078: gen_store_gpr(t1, rt);
1.1 root 1079: opn = "ldl";
1080: break;
1081: case OPC_LDR:
1.1.1.7 root 1082: save_cpu_state(ctx, 1);
1083: gen_load_gpr(t1, rt);
1.1.1.8 root 1084: gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1085: gen_store_gpr(t1, rt);
1.1 root 1086: opn = "ldr";
1087: break;
1.1.1.12 root 1088: case OPC_LDPC:
1.1.1.13! root 1089: save_cpu_state(ctx, 0);
1.1.1.12 root 1090: tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1091: gen_op_addr_add(ctx, t0, t0, t1);
1092: op_ld_ld(t0, t0, ctx);
1093: gen_store_gpr(t0, rt);
1094: opn = "ldpc";
1.1 root 1095: break;
1096: #endif
1.1.1.12 root 1097: case OPC_LWPC:
1.1.1.13! root 1098: save_cpu_state(ctx, 0);
1.1.1.12 root 1099: tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1100: gen_op_addr_add(ctx, t0, t0, t1);
1101: op_ld_lw(t0, t0, ctx);
1102: gen_store_gpr(t0, rt);
1103: opn = "lwpc";
1104: break;
1.1 root 1105: case OPC_LW:
1.1.1.8 root 1106: save_cpu_state(ctx, 0);
1.1.1.12 root 1107: op_ld_lw(t0, t0, ctx);
1.1.1.7 root 1108: gen_store_gpr(t0, rt);
1.1 root 1109: opn = "lw";
1110: break;
1111: case OPC_LH:
1.1.1.8 root 1112: save_cpu_state(ctx, 0);
1.1.1.12 root 1113: op_ld_lh(t0, t0, ctx);
1.1.1.7 root 1114: gen_store_gpr(t0, rt);
1.1 root 1115: opn = "lh";
1116: break;
1117: case OPC_LHU:
1.1.1.8 root 1118: save_cpu_state(ctx, 0);
1.1.1.12 root 1119: op_ld_lhu(t0, t0, ctx);
1.1.1.7 root 1120: gen_store_gpr(t0, rt);
1.1 root 1121: opn = "lhu";
1122: break;
1123: case OPC_LB:
1.1.1.8 root 1124: save_cpu_state(ctx, 0);
1.1.1.12 root 1125: op_ld_lb(t0, t0, ctx);
1.1.1.7 root 1126: gen_store_gpr(t0, rt);
1.1 root 1127: opn = "lb";
1128: break;
1129: case OPC_LBU:
1.1.1.8 root 1130: save_cpu_state(ctx, 0);
1.1.1.12 root 1131: op_ld_lbu(t0, t0, ctx);
1.1.1.7 root 1132: gen_store_gpr(t0, rt);
1.1 root 1133: opn = "lbu";
1134: break;
1135: case OPC_LWL:
1.1.1.7 root 1136: save_cpu_state(ctx, 1);
1137: gen_load_gpr(t1, rt);
1.1.1.8 root 1138: gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1139: gen_store_gpr(t1, rt);
1.1 root 1140: opn = "lwl";
1141: break;
1142: case OPC_LWR:
1.1.1.7 root 1143: save_cpu_state(ctx, 1);
1144: gen_load_gpr(t1, rt);
1.1.1.8 root 1145: gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1.1.1.7 root 1146: gen_store_gpr(t1, rt);
1.1 root 1147: opn = "lwr";
1148: break;
1149: case OPC_LL:
1.1.1.9 root 1150: save_cpu_state(ctx, 1);
1.1.1.12 root 1151: op_ld_ll(t0, t0, ctx);
1.1.1.7 root 1152: gen_store_gpr(t0, rt);
1.1 root 1153: opn = "ll";
1154: break;
1.1.1.8 root 1155: }
1.1.1.13! root 1156: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1157: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1158: tcg_temp_free(t0);
1159: tcg_temp_free(t1);
1160: }
1161:
1.1.1.12 root 1162: /* Store */
1163: static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1164: int base, int16_t offset)
1165: {
1166: const char *opn = "st";
1167: TCGv t0 = tcg_temp_new();
1168: TCGv t1 = tcg_temp_new();
1169:
1170: gen_base_offset_addr(ctx, t0, base, offset);
1171: gen_load_gpr(t1, rt);
1172: switch (opc) {
1173: #if defined(TARGET_MIPS64)
1174: case OPC_SD:
1175: save_cpu_state(ctx, 0);
1176: op_st_sd(t1, t0, ctx);
1177: opn = "sd";
1178: break;
1179: case OPC_SDL:
1180: save_cpu_state(ctx, 1);
1181: gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1182: opn = "sdl";
1183: break;
1184: case OPC_SDR:
1185: save_cpu_state(ctx, 1);
1186: gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1187: opn = "sdr";
1188: break;
1189: #endif
1190: case OPC_SW:
1191: save_cpu_state(ctx, 0);
1192: op_st_sw(t1, t0, ctx);
1193: opn = "sw";
1194: break;
1195: case OPC_SH:
1196: save_cpu_state(ctx, 0);
1197: op_st_sh(t1, t0, ctx);
1198: opn = "sh";
1199: break;
1200: case OPC_SB:
1201: save_cpu_state(ctx, 0);
1202: op_st_sb(t1, t0, ctx);
1203: opn = "sb";
1204: break;
1205: case OPC_SWL:
1206: save_cpu_state(ctx, 1);
1207: gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1208: opn = "swl";
1209: break;
1210: case OPC_SWR:
1211: save_cpu_state(ctx, 1);
1212: gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1213: opn = "swr";
1214: break;
1215: }
1.1.1.13! root 1216: (void)opn; /* avoid a compiler warning */
1.1.1.12 root 1217: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1218: tcg_temp_free(t0);
1219: tcg_temp_free(t1);
1220: }
1221:
1222:
1.1.1.8 root 1223: /* Store conditional */
1224: static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1225: int base, int16_t offset)
1226: {
1227: const char *opn = "st_cond";
1228: TCGv t0, t1;
1229:
1230: t0 = tcg_temp_local_new();
1231:
1.1.1.12 root 1232: gen_base_offset_addr(ctx, t0, base, offset);
1.1.1.8 root 1233: /* Don't do NOP if destination is zero: we must perform the actual
1234: memory access. */
1235:
1236: t1 = tcg_temp_local_new();
1237: gen_load_gpr(t1, rt);
1238: switch (opc) {
1239: #if defined(TARGET_MIPS64)
1240: case OPC_SCD:
1.1.1.13! root 1241: save_cpu_state(ctx, 1);
1.1.1.12 root 1242: op_st_scd(t1, t0, rt, ctx);
1.1.1.8 root 1243: opn = "scd";
1244: break;
1245: #endif
1.1 root 1246: case OPC_SC:
1.1.1.9 root 1247: save_cpu_state(ctx, 1);
1.1.1.12 root 1248: op_st_sc(t1, t0, rt, ctx);
1.1 root 1249: opn = "sc";
1250: break;
1251: }
1.1.1.13! root 1252: (void)opn; /* avoid a compiler warning */
1.1 root 1253: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1.1.1.7 root 1254: tcg_temp_free(t1);
1.1.1.8 root 1255: tcg_temp_free(t0);
1.1 root 1256: }
1257:
1.1.1.4 root 1258: /* Load and store */
1.1.1.5 root 1259: static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1.1.1.7 root 1260: int base, int16_t offset)
1.1.1.4 root 1261: {
1.1.1.6 root 1262: const char *opn = "flt_ldst";
1.1.1.8 root 1263: TCGv t0 = tcg_temp_new();
1.1.1.4 root 1264:
1.1.1.12 root 1265: gen_base_offset_addr(ctx, t0, base, offset);
1.1.1.4 root 1266: /* Don't do NOP if destination is zero: we must perform the actual
1.1.1.6 root 1267: memory access. */
1.1.1.4 root 1268: switch (opc) {
1269: case OPC_LWC1:
1.1.1.7 root 1270: {
1271: TCGv_i32 fp0 = tcg_temp_new_i32();
1272:
1.1.1.8 root 1273: tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1274: tcg_gen_trunc_tl_i32(fp0, t0);
1.1.1.7 root 1275: gen_store_fpr32(fp0, ft);
1276: tcg_temp_free_i32(fp0);
1277: }
1.1.1.4 root 1278: opn = "lwc1";
1279: break;
1280: case OPC_SWC1:
1.1.1.7 root 1281: {
1282: TCGv_i32 fp0 = tcg_temp_new_i32();
1283: TCGv t1 = tcg_temp_new();
1284:
1285: gen_load_fpr32(fp0, ft);
1286: tcg_gen_extu_i32_tl(t1, fp0);
1287: tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1288: tcg_temp_free(t1);
1289: tcg_temp_free_i32(fp0);
1290: }
1.1.1.4 root 1291: opn = "swc1";
1292: break;
1293: case OPC_LDC1:
1.1.1.7 root 1294: {
1295: TCGv_i64 fp0 = tcg_temp_new_i64();
1296:
1297: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1298: gen_store_fpr64(ctx, fp0, ft);
1299: tcg_temp_free_i64(fp0);
1300: }
1.1.1.4 root 1301: opn = "ldc1";
1302: break;
1303: case OPC_SDC1:
1.1.1.7 root 1304: {
1305: TCGv_i64 fp0 = tcg_temp_new_i64();
1306:
1307: gen_load_fpr64(ctx, fp0, ft);
1308: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1309: tcg_temp_free_i64(fp0);
1310: }
1.1.1.4 root 1311: opn = "sdc1";
1312: break;
1313: default:
1.1.1.6 root 1314: MIPS_INVAL(opn);
1315: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 1316: goto out;
1.1.1.4 root 1317: }
1.1.1.13! root 1318: (void)opn; /* avoid a compiler warning */
1.1.1.4 root 1319: MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1.1.1.7 root 1320: out:
1321: tcg_temp_free(t0);
1.1.1.4 root 1322: }
1.1.1.5 root 1323:
1.1.1.12 root 1324: static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
1325: uint32_t op, int rt, int rs, int16_t imm)
1326: {
1327: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1328: check_cp1_enabled(ctx);
1329: gen_flt_ldst(ctx, op, rt, rs, imm);
1330: } else {
1331: generate_exception_err(ctx, EXCP_CpU, 1);
1332: }
1333: }
1334:
1.1 root 1335: /* Arithmetic with immediate operand */
1.1.1.6 root 1336: static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1337: int rt, int rs, int16_t imm)
1.1 root 1338: {
1.1.1.8 root 1339: target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1.1.1.6 root 1340: const char *opn = "imm arith";
1.1 root 1341:
1.1.1.5 root 1342: if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1.1.1.6 root 1343: /* If no destination, treat it as a NOP.
1344: For addi, we must generate the overflow exception when needed. */
1.1 root 1345: MIPS_DEBUG("NOP");
1.1.1.8 root 1346: return;
1.1 root 1347: }
1348: switch (opc) {
1349: case OPC_ADDI:
1.1.1.7 root 1350: {
1.1.1.8 root 1351: TCGv t0 = tcg_temp_local_new();
1352: TCGv t1 = tcg_temp_new();
1353: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1354: int l1 = gen_new_label();
1355:
1.1.1.8 root 1356: gen_load_gpr(t1, rs);
1357: tcg_gen_addi_tl(t0, t1, uimm);
1358: tcg_gen_ext32s_tl(t0, t0);
1.1.1.7 root 1359:
1.1.1.8 root 1360: tcg_gen_xori_tl(t1, t1, ~uimm);
1361: tcg_gen_xori_tl(t2, t0, uimm);
1362: tcg_gen_and_tl(t1, t1, t2);
1363: tcg_temp_free(t2);
1364: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1365: tcg_temp_free(t1);
1.1.1.7 root 1366: /* operands of same sign, result different sign */
1367: generate_exception(ctx, EXCP_OVERFLOW);
1368: gen_set_label(l1);
1369: tcg_gen_ext32s_tl(t0, t0);
1.1.1.8 root 1370: gen_store_gpr(t0, rt);
1371: tcg_temp_free(t0);
1.1.1.7 root 1372: }
1.1 root 1373: opn = "addi";
1374: break;
1375: case OPC_ADDIU:
1.1.1.8 root 1376: if (rs != 0) {
1377: tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1378: tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1379: } else {
1380: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1381: }
1.1 root 1382: opn = "addiu";
1383: break;
1.1.1.6 root 1384: #if defined(TARGET_MIPS64)
1.1.1.5 root 1385: case OPC_DADDI:
1.1.1.7 root 1386: {
1.1.1.8 root 1387: TCGv t0 = tcg_temp_local_new();
1388: TCGv t1 = tcg_temp_new();
1389: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1390: int l1 = gen_new_label();
1391:
1.1.1.8 root 1392: gen_load_gpr(t1, rs);
1393: tcg_gen_addi_tl(t0, t1, uimm);
1.1.1.7 root 1394:
1.1.1.8 root 1395: tcg_gen_xori_tl(t1, t1, ~uimm);
1396: tcg_gen_xori_tl(t2, t0, uimm);
1397: tcg_gen_and_tl(t1, t1, t2);
1398: tcg_temp_free(t2);
1399: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1400: tcg_temp_free(t1);
1.1.1.7 root 1401: /* operands of same sign, result different sign */
1402: generate_exception(ctx, EXCP_OVERFLOW);
1403: gen_set_label(l1);
1.1.1.8 root 1404: gen_store_gpr(t0, rt);
1405: tcg_temp_free(t0);
1.1.1.7 root 1406: }
1.1.1.5 root 1407: opn = "daddi";
1408: break;
1409: case OPC_DADDIU:
1.1.1.8 root 1410: if (rs != 0) {
1411: tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1412: } else {
1413: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1414: }
1.1.1.5 root 1415: opn = "daddiu";
1416: break;
1417: #endif
1.1.1.8 root 1418: }
1.1.1.13! root 1419: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1420: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1421: }
1422:
1423: /* Logic with immediate operand */
1424: static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1425: {
1426: target_ulong uimm;
1427: const char *opn = "imm logic";
1428:
1429: if (rt == 0) {
1430: /* If no destination, treat it as a NOP. */
1431: MIPS_DEBUG("NOP");
1432: return;
1433: }
1434: uimm = (uint16_t)imm;
1435: switch (opc) {
1.1 root 1436: case OPC_ANDI:
1.1.1.8 root 1437: if (likely(rs != 0))
1438: tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1439: else
1440: tcg_gen_movi_tl(cpu_gpr[rt], 0);
1.1 root 1441: opn = "andi";
1442: break;
1443: case OPC_ORI:
1.1.1.8 root 1444: if (rs != 0)
1445: tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1446: else
1447: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1.1 root 1448: opn = "ori";
1449: break;
1450: case OPC_XORI:
1.1.1.8 root 1451: if (likely(rs != 0))
1452: tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1453: else
1454: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1.1 root 1455: opn = "xori";
1456: break;
1457: case OPC_LUI:
1.1.1.8 root 1458: tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1.1 root 1459: opn = "lui";
1460: break;
1.1.1.8 root 1461: }
1.1.1.13! root 1462: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1463: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1464: }
1465:
1466: /* Set on less than with immediate operand */
1467: static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1468: {
1469: target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1470: const char *opn = "imm arith";
1471: TCGv t0;
1472:
1473: if (rt == 0) {
1474: /* If no destination, treat it as a NOP. */
1475: MIPS_DEBUG("NOP");
1476: return;
1477: }
1478: t0 = tcg_temp_new();
1479: gen_load_gpr(t0, rs);
1480: switch (opc) {
1481: case OPC_SLTI:
1.1.1.12 root 1482: tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1.1.1.8 root 1483: opn = "slti";
1484: break;
1485: case OPC_SLTIU:
1.1.1.12 root 1486: tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1.1.1.8 root 1487: opn = "sltiu";
1488: break;
1489: }
1.1.1.13! root 1490: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1491: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1492: tcg_temp_free(t0);
1493: }
1494:
1495: /* Shifts with immediate operand */
1496: static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1497: int rt, int rs, int16_t imm)
1498: {
1499: target_ulong uimm = ((uint16_t)imm) & 0x1f;
1500: const char *opn = "imm shift";
1501: TCGv t0;
1502:
1503: if (rt == 0) {
1504: /* If no destination, treat it as a NOP. */
1505: MIPS_DEBUG("NOP");
1506: return;
1507: }
1508:
1509: t0 = tcg_temp_new();
1510: gen_load_gpr(t0, rs);
1511: switch (opc) {
1.1 root 1512: case OPC_SLL:
1.1.1.7 root 1513: tcg_gen_shli_tl(t0, t0, uimm);
1.1.1.8 root 1514: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1.1 root 1515: opn = "sll";
1516: break;
1517: case OPC_SRA:
1.1.1.8 root 1518: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1.1 root 1519: opn = "sra";
1520: break;
1521: case OPC_SRL:
1.1.1.12 root 1522: if (uimm != 0) {
1523: tcg_gen_ext32u_tl(t0, t0);
1524: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1525: } else {
1526: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1527: }
1528: opn = "srl";
1529: break;
1530: case OPC_ROTR:
1531: if (uimm != 0) {
1532: TCGv_i32 t1 = tcg_temp_new_i32();
1.1.1.7 root 1533:
1.1.1.12 root 1534: tcg_gen_trunc_tl_i32(t1, t0);
1535: tcg_gen_rotri_i32(t1, t1, uimm);
1536: tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1537: tcg_temp_free_i32(t1);
1538: } else {
1539: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1.1.1.6 root 1540: }
1.1.1.12 root 1541: opn = "rotr";
1.1.1.5 root 1542: break;
1.1.1.6 root 1543: #if defined(TARGET_MIPS64)
1.1.1.5 root 1544: case OPC_DSLL:
1.1.1.8 root 1545: tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1.1.1.5 root 1546: opn = "dsll";
1547: break;
1548: case OPC_DSRA:
1.1.1.8 root 1549: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1.1.1.5 root 1550: opn = "dsra";
1551: break;
1552: case OPC_DSRL:
1.1.1.12 root 1553: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1554: opn = "dsrl";
1555: break;
1556: case OPC_DROTR:
1557: if (uimm != 0) {
1558: tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1559: } else {
1560: tcg_gen_mov_tl(cpu_gpr[rt], t0);
1.1.1.6 root 1561: }
1.1.1.12 root 1562: opn = "drotr";
1.1.1.5 root 1563: break;
1564: case OPC_DSLL32:
1.1.1.8 root 1565: tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1.1.1.5 root 1566: opn = "dsll32";
1567: break;
1568: case OPC_DSRA32:
1.1.1.8 root 1569: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1.1.1.5 root 1570: opn = "dsra32";
1571: break;
1572: case OPC_DSRL32:
1.1.1.12 root 1573: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1574: opn = "dsrl32";
1575: break;
1576: case OPC_DROTR32:
1577: tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1578: opn = "drotr32";
1.1 root 1579: break;
1.1.1.5 root 1580: #endif
1.1 root 1581: }
1.1.1.13! root 1582: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 1583: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1.1.1.7 root 1584: tcg_temp_free(t0);
1.1 root 1585: }
1586:
1587: /* Arithmetic */
1.1.1.6 root 1588: static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1.1 root 1589: int rd, int rs, int rt)
1590: {
1.1.1.6 root 1591: const char *opn = "arith";
1.1 root 1592:
1.1.1.5 root 1593: if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1594: && opc != OPC_DADD && opc != OPC_DSUB) {
1.1.1.6 root 1595: /* If no destination, treat it as a NOP.
1596: For add & sub, we must generate the overflow exception when needed. */
1.1 root 1597: MIPS_DEBUG("NOP");
1.1.1.8 root 1598: return;
1.1.1.6 root 1599: }
1.1.1.8 root 1600:
1.1 root 1601: switch (opc) {
1602: case OPC_ADD:
1.1.1.7 root 1603: {
1.1.1.8 root 1604: TCGv t0 = tcg_temp_local_new();
1605: TCGv t1 = tcg_temp_new();
1606: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1607: int l1 = gen_new_label();
1608:
1.1.1.8 root 1609: gen_load_gpr(t1, rs);
1610: gen_load_gpr(t2, rt);
1611: tcg_gen_add_tl(t0, t1, t2);
1612: tcg_gen_ext32s_tl(t0, t0);
1613: tcg_gen_xor_tl(t1, t1, t2);
1614: tcg_gen_xor_tl(t2, t0, t2);
1.1.1.12 root 1615: tcg_gen_andc_tl(t1, t2, t1);
1.1.1.8 root 1616: tcg_temp_free(t2);
1617: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1618: tcg_temp_free(t1);
1.1.1.7 root 1619: /* operands of same sign, result different sign */
1620: generate_exception(ctx, EXCP_OVERFLOW);
1621: gen_set_label(l1);
1.1.1.8 root 1622: gen_store_gpr(t0, rd);
1623: tcg_temp_free(t0);
1.1.1.7 root 1624: }
1.1 root 1625: opn = "add";
1626: break;
1627: case OPC_ADDU:
1.1.1.8 root 1628: if (rs != 0 && rt != 0) {
1629: tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1630: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1631: } else if (rs == 0 && rt != 0) {
1632: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1633: } else if (rs != 0 && rt == 0) {
1634: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1635: } else {
1636: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1637: }
1.1 root 1638: opn = "addu";
1639: break;
1640: case OPC_SUB:
1.1.1.7 root 1641: {
1.1.1.8 root 1642: TCGv t0 = tcg_temp_local_new();
1643: TCGv t1 = tcg_temp_new();
1644: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1645: int l1 = gen_new_label();
1646:
1.1.1.8 root 1647: gen_load_gpr(t1, rs);
1648: gen_load_gpr(t2, rt);
1649: tcg_gen_sub_tl(t0, t1, t2);
1650: tcg_gen_ext32s_tl(t0, t0);
1651: tcg_gen_xor_tl(t2, t1, t2);
1652: tcg_gen_xor_tl(t1, t0, t1);
1653: tcg_gen_and_tl(t1, t1, t2);
1654: tcg_temp_free(t2);
1655: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1656: tcg_temp_free(t1);
1.1.1.9 root 1657: /* operands of different sign, first operand and result different sign */
1.1.1.7 root 1658: generate_exception(ctx, EXCP_OVERFLOW);
1659: gen_set_label(l1);
1.1.1.8 root 1660: gen_store_gpr(t0, rd);
1661: tcg_temp_free(t0);
1.1.1.7 root 1662: }
1.1 root 1663: opn = "sub";
1664: break;
1665: case OPC_SUBU:
1.1.1.8 root 1666: if (rs != 0 && rt != 0) {
1667: tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1668: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1669: } else if (rs == 0 && rt != 0) {
1670: tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1671: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1672: } else if (rs != 0 && rt == 0) {
1673: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1674: } else {
1675: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1676: }
1.1 root 1677: opn = "subu";
1678: break;
1.1.1.6 root 1679: #if defined(TARGET_MIPS64)
1.1.1.5 root 1680: case OPC_DADD:
1.1.1.7 root 1681: {
1.1.1.8 root 1682: TCGv t0 = tcg_temp_local_new();
1683: TCGv t1 = tcg_temp_new();
1684: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1685: int l1 = gen_new_label();
1686:
1.1.1.8 root 1687: gen_load_gpr(t1, rs);
1688: gen_load_gpr(t2, rt);
1689: tcg_gen_add_tl(t0, t1, t2);
1690: tcg_gen_xor_tl(t1, t1, t2);
1691: tcg_gen_xor_tl(t2, t0, t2);
1.1.1.12 root 1692: tcg_gen_andc_tl(t1, t2, t1);
1.1.1.8 root 1693: tcg_temp_free(t2);
1694: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1695: tcg_temp_free(t1);
1.1.1.7 root 1696: /* operands of same sign, result different sign */
1697: generate_exception(ctx, EXCP_OVERFLOW);
1698: gen_set_label(l1);
1.1.1.8 root 1699: gen_store_gpr(t0, rd);
1700: tcg_temp_free(t0);
1.1.1.7 root 1701: }
1.1.1.5 root 1702: opn = "dadd";
1703: break;
1704: case OPC_DADDU:
1.1.1.8 root 1705: if (rs != 0 && rt != 0) {
1706: tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1707: } else if (rs == 0 && rt != 0) {
1708: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1709: } else if (rs != 0 && rt == 0) {
1710: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1711: } else {
1712: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1713: }
1.1.1.5 root 1714: opn = "daddu";
1715: break;
1716: case OPC_DSUB:
1.1.1.7 root 1717: {
1.1.1.8 root 1718: TCGv t0 = tcg_temp_local_new();
1719: TCGv t1 = tcg_temp_new();
1720: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1721: int l1 = gen_new_label();
1722:
1.1.1.8 root 1723: gen_load_gpr(t1, rs);
1724: gen_load_gpr(t2, rt);
1725: tcg_gen_sub_tl(t0, t1, t2);
1726: tcg_gen_xor_tl(t2, t1, t2);
1727: tcg_gen_xor_tl(t1, t0, t1);
1728: tcg_gen_and_tl(t1, t1, t2);
1729: tcg_temp_free(t2);
1730: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1731: tcg_temp_free(t1);
1.1.1.9 root 1732: /* operands of different sign, first operand and result different sign */
1.1.1.7 root 1733: generate_exception(ctx, EXCP_OVERFLOW);
1734: gen_set_label(l1);
1.1.1.8 root 1735: gen_store_gpr(t0, rd);
1736: tcg_temp_free(t0);
1.1.1.7 root 1737: }
1.1.1.5 root 1738: opn = "dsub";
1739: break;
1740: case OPC_DSUBU:
1.1.1.8 root 1741: if (rs != 0 && rt != 0) {
1742: tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1743: } else if (rs == 0 && rt != 0) {
1744: tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1745: } else if (rs != 0 && rt == 0) {
1746: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1747: } else {
1748: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1749: }
1.1.1.5 root 1750: opn = "dsubu";
1751: break;
1752: #endif
1.1.1.8 root 1753: case OPC_MUL:
1754: if (likely(rs != 0 && rt != 0)) {
1755: tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1756: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1757: } else {
1758: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1759: }
1760: opn = "mul";
1.1 root 1761: break;
1.1.1.8 root 1762: }
1.1.1.13! root 1763: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1764: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1765: }
1766:
1767: /* Conditional move */
1768: static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1769: {
1770: const char *opn = "cond move";
1771: int l1;
1772:
1773: if (rd == 0) {
1774: /* If no destination, treat it as a NOP.
1775: For add & sub, we must generate the overflow exception when needed. */
1776: MIPS_DEBUG("NOP");
1777: return;
1778: }
1779:
1780: l1 = gen_new_label();
1781: switch (opc) {
1782: case OPC_MOVN:
1783: if (likely(rt != 0))
1784: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1785: else
1786: tcg_gen_br(l1);
1787: opn = "movn";
1.1 root 1788: break;
1.1.1.8 root 1789: case OPC_MOVZ:
1790: if (likely(rt != 0))
1791: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1792: opn = "movz";
1793: break;
1794: }
1795: if (rs != 0)
1796: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1797: else
1798: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1799: gen_set_label(l1);
1800:
1.1.1.13! root 1801: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1802: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1803: }
1804:
1805: /* Logic */
1806: static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1807: {
1808: const char *opn = "logic";
1809:
1810: if (rd == 0) {
1811: /* If no destination, treat it as a NOP. */
1812: MIPS_DEBUG("NOP");
1813: return;
1814: }
1815:
1816: switch (opc) {
1.1 root 1817: case OPC_AND:
1.1.1.8 root 1818: if (likely(rs != 0 && rt != 0)) {
1819: tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1820: } else {
1821: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1822: }
1.1 root 1823: opn = "and";
1824: break;
1825: case OPC_NOR:
1.1.1.8 root 1826: if (rs != 0 && rt != 0) {
1827: tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1828: } else if (rs == 0 && rt != 0) {
1829: tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1830: } else if (rs != 0 && rt == 0) {
1831: tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1832: } else {
1833: tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1834: }
1.1 root 1835: opn = "nor";
1836: break;
1837: case OPC_OR:
1.1.1.8 root 1838: if (likely(rs != 0 && rt != 0)) {
1839: tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1840: } else if (rs == 0 && rt != 0) {
1841: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1842: } else if (rs != 0 && rt == 0) {
1843: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1844: } else {
1845: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1846: }
1.1 root 1847: opn = "or";
1848: break;
1849: case OPC_XOR:
1.1.1.8 root 1850: if (likely(rs != 0 && rt != 0)) {
1851: tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1852: } else if (rs == 0 && rt != 0) {
1853: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1854: } else if (rs != 0 && rt == 0) {
1855: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1856: } else {
1857: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1858: }
1.1 root 1859: opn = "xor";
1860: break;
1.1.1.8 root 1861: }
1.1.1.13! root 1862: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1863: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1864: }
1865:
1866: /* Set on lower than */
1867: static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1868: {
1869: const char *opn = "slt";
1870: TCGv t0, t1;
1871:
1872: if (rd == 0) {
1873: /* If no destination, treat it as a NOP. */
1874: MIPS_DEBUG("NOP");
1875: return;
1876: }
1877:
1878: t0 = tcg_temp_new();
1879: t1 = tcg_temp_new();
1880: gen_load_gpr(t0, rs);
1881: gen_load_gpr(t1, rt);
1882: switch (opc) {
1883: case OPC_SLT:
1.1.1.12 root 1884: tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
1.1.1.8 root 1885: opn = "slt";
1.1 root 1886: break;
1.1.1.8 root 1887: case OPC_SLTU:
1.1.1.12 root 1888: tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
1.1.1.8 root 1889: opn = "sltu";
1890: break;
1891: }
1.1.1.13! root 1892: (void)opn; /* avoid a compiler warning */
1.1.1.8 root 1893: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1894: tcg_temp_free(t0);
1895: tcg_temp_free(t1);
1896: }
1.1.1.7 root 1897:
1.1.1.8 root 1898: /* Shifts */
1899: static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1900: int rd, int rs, int rt)
1901: {
1902: const char *opn = "shifts";
1903: TCGv t0, t1;
1.1.1.7 root 1904:
1.1.1.8 root 1905: if (rd == 0) {
1906: /* If no destination, treat it as a NOP.
1907: For add & sub, we must generate the overflow exception when needed. */
1908: MIPS_DEBUG("NOP");
1909: return;
1910: }
1911:
1912: t0 = tcg_temp_new();
1913: t1 = tcg_temp_new();
1914: gen_load_gpr(t0, rs);
1915: gen_load_gpr(t1, rt);
1916: switch (opc) {
1.1 root 1917: case OPC_SLLV:
1.1.1.7 root 1918: tcg_gen_andi_tl(t0, t0, 0x1f);
1919: tcg_gen_shl_tl(t0, t1, t0);
1.1.1.8 root 1920: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1.1 root 1921: opn = "sllv";
1922: break;
1923: case OPC_SRAV:
1.1.1.7 root 1924: tcg_gen_andi_tl(t0, t0, 0x1f);
1.1.1.8 root 1925: tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1.1 root 1926: opn = "srav";
1927: break;
1928: case OPC_SRLV:
1.1.1.12 root 1929: tcg_gen_ext32u_tl(t1, t1);
1930: tcg_gen_andi_tl(t0, t0, 0x1f);
1931: tcg_gen_shr_tl(t0, t1, t0);
1932: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1933: opn = "srlv";
1934: break;
1935: case OPC_ROTRV:
1936: {
1937: TCGv_i32 t2 = tcg_temp_new_i32();
1938: TCGv_i32 t3 = tcg_temp_new_i32();
1939:
1940: tcg_gen_trunc_tl_i32(t2, t0);
1941: tcg_gen_trunc_tl_i32(t3, t1);
1942: tcg_gen_andi_i32(t2, t2, 0x1f);
1943: tcg_gen_rotr_i32(t2, t3, t2);
1944: tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1945: tcg_temp_free_i32(t2);
1946: tcg_temp_free_i32(t3);
1947: opn = "rotrv";
1.1.1.6 root 1948: }
1.1.1.5 root 1949: break;
1.1.1.6 root 1950: #if defined(TARGET_MIPS64)
1.1.1.5 root 1951: case OPC_DSLLV:
1.1.1.7 root 1952: tcg_gen_andi_tl(t0, t0, 0x3f);
1.1.1.8 root 1953: tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1.1.1.5 root 1954: opn = "dsllv";
1955: break;
1956: case OPC_DSRAV:
1.1.1.7 root 1957: tcg_gen_andi_tl(t0, t0, 0x3f);
1.1.1.8 root 1958: tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1.1.1.5 root 1959: opn = "dsrav";
1960: break;
1961: case OPC_DSRLV:
1.1.1.12 root 1962: tcg_gen_andi_tl(t0, t0, 0x3f);
1963: tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1964: opn = "dsrlv";
1965: break;
1966: case OPC_DROTRV:
1967: tcg_gen_andi_tl(t0, t0, 0x3f);
1968: tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1969: opn = "drotrv";
1.1 root 1970: break;
1.1.1.5 root 1971: #endif
1.1 root 1972: }
1.1.1.13! root 1973: (void)opn; /* avoid a compiler warning */
1.1 root 1974: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1.1.1.7 root 1975: tcg_temp_free(t0);
1976: tcg_temp_free(t1);
1.1 root 1977: }
1978:
1979: /* Arithmetic on HI/LO registers */
1.1.1.5 root 1980: static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1.1 root 1981: {
1.1.1.6 root 1982: const char *opn = "hilo";
1.1 root 1983:
1984: if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1.1.1.6 root 1985: /* Treat as NOP. */
1.1 root 1986: MIPS_DEBUG("NOP");
1.1.1.8 root 1987: return;
1.1 root 1988: }
1989: switch (opc) {
1990: case OPC_MFHI:
1.1.1.8 root 1991: tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1.1 root 1992: opn = "mfhi";
1993: break;
1994: case OPC_MFLO:
1.1.1.8 root 1995: tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1.1 root 1996: opn = "mflo";
1997: break;
1998: case OPC_MTHI:
1.1.1.8 root 1999: if (reg != 0)
2000: tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
2001: else
2002: tcg_gen_movi_tl(cpu_HI[0], 0);
1.1 root 2003: opn = "mthi";
2004: break;
2005: case OPC_MTLO:
1.1.1.8 root 2006: if (reg != 0)
2007: tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2008: else
2009: tcg_gen_movi_tl(cpu_LO[0], 0);
1.1 root 2010: opn = "mtlo";
2011: break;
2012: }
1.1.1.13! root 2013: (void)opn; /* avoid a compiler warning */
1.1 root 2014: MIPS_DEBUG("%s %s", opn, regnames[reg]);
2015: }
2016:
1.1.1.5 root 2017: static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1.1 root 2018: int rs, int rt)
2019: {
1.1.1.6 root 2020: const char *opn = "mul/div";
1.1.1.8 root 2021: TCGv t0, t1;
2022:
2023: switch (opc) {
2024: case OPC_DIV:
2025: case OPC_DIVU:
2026: #if defined(TARGET_MIPS64)
2027: case OPC_DDIV:
2028: case OPC_DDIVU:
2029: #endif
2030: t0 = tcg_temp_local_new();
2031: t1 = tcg_temp_local_new();
2032: break;
2033: default:
2034: t0 = tcg_temp_new();
2035: t1 = tcg_temp_new();
2036: break;
2037: }
1.1 root 2038:
1.1.1.7 root 2039: gen_load_gpr(t0, rs);
2040: gen_load_gpr(t1, rt);
1.1 root 2041: switch (opc) {
2042: case OPC_DIV:
1.1.1.7 root 2043: {
2044: int l1 = gen_new_label();
1.1.1.8 root 2045: int l2 = gen_new_label();
1.1.1.7 root 2046:
1.1.1.8 root 2047: tcg_gen_ext32s_tl(t0, t0);
2048: tcg_gen_ext32s_tl(t1, t1);
1.1.1.7 root 2049: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2050: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2051: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2052:
2053: tcg_gen_mov_tl(cpu_LO[0], t0);
2054: tcg_gen_movi_tl(cpu_HI[0], 0);
2055: tcg_gen_br(l1);
2056: gen_set_label(l2);
2057: tcg_gen_div_tl(cpu_LO[0], t0, t1);
2058: tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2059: tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2060: tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1.1.1.7 root 2061: gen_set_label(l1);
2062: }
1.1 root 2063: opn = "div";
2064: break;
2065: case OPC_DIVU:
1.1.1.7 root 2066: {
2067: int l1 = gen_new_label();
2068:
1.1.1.8 root 2069: tcg_gen_ext32u_tl(t0, t0);
2070: tcg_gen_ext32u_tl(t1, t1);
1.1.1.7 root 2071: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2072: tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2073: tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2074: tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2075: tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1.1.1.7 root 2076: gen_set_label(l1);
2077: }
1.1 root 2078: opn = "divu";
2079: break;
2080: case OPC_MULT:
1.1.1.7 root 2081: {
1.1.1.8 root 2082: TCGv_i64 t2 = tcg_temp_new_i64();
2083: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2084:
1.1.1.8 root 2085: tcg_gen_ext_tl_i64(t2, t0);
2086: tcg_gen_ext_tl_i64(t3, t1);
2087: tcg_gen_mul_i64(t2, t2, t3);
2088: tcg_temp_free_i64(t3);
2089: tcg_gen_trunc_i64_tl(t0, t2);
2090: tcg_gen_shri_i64(t2, t2, 32);
2091: tcg_gen_trunc_i64_tl(t1, t2);
2092: tcg_temp_free_i64(t2);
1.1.1.7 root 2093: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2094: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2095: }
1.1 root 2096: opn = "mult";
2097: break;
2098: case OPC_MULTU:
1.1.1.7 root 2099: {
1.1.1.8 root 2100: TCGv_i64 t2 = tcg_temp_new_i64();
2101: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2102:
2103: tcg_gen_ext32u_tl(t0, t0);
2104: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2105: tcg_gen_extu_tl_i64(t2, t0);
2106: tcg_gen_extu_tl_i64(t3, t1);
2107: tcg_gen_mul_i64(t2, t2, t3);
2108: tcg_temp_free_i64(t3);
2109: tcg_gen_trunc_i64_tl(t0, t2);
2110: tcg_gen_shri_i64(t2, t2, 32);
2111: tcg_gen_trunc_i64_tl(t1, t2);
2112: tcg_temp_free_i64(t2);
1.1.1.7 root 2113: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2114: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2115: }
1.1 root 2116: opn = "multu";
2117: break;
1.1.1.6 root 2118: #if defined(TARGET_MIPS64)
1.1.1.5 root 2119: case OPC_DDIV:
1.1.1.7 root 2120: {
2121: int l1 = gen_new_label();
1.1.1.8 root 2122: int l2 = gen_new_label();
1.1.1.7 root 2123:
2124: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2125: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2126: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2127: tcg_gen_mov_tl(cpu_LO[0], t0);
2128: tcg_gen_movi_tl(cpu_HI[0], 0);
2129: tcg_gen_br(l1);
2130: gen_set_label(l2);
2131: tcg_gen_div_i64(cpu_LO[0], t0, t1);
2132: tcg_gen_rem_i64(cpu_HI[0], t0, t1);
1.1.1.7 root 2133: gen_set_label(l1);
2134: }
1.1.1.5 root 2135: opn = "ddiv";
2136: break;
2137: case OPC_DDIVU:
1.1.1.7 root 2138: {
2139: int l1 = gen_new_label();
2140:
2141: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2142: tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2143: tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2144: gen_set_label(l1);
2145: }
1.1.1.5 root 2146: opn = "ddivu";
2147: break;
2148: case OPC_DMULT:
1.1.1.7 root 2149: gen_helper_dmult(t0, t1);
1.1.1.5 root 2150: opn = "dmult";
2151: break;
2152: case OPC_DMULTU:
1.1.1.7 root 2153: gen_helper_dmultu(t0, t1);
1.1.1.5 root 2154: opn = "dmultu";
2155: break;
2156: #endif
1.1 root 2157: case OPC_MADD:
1.1.1.7 root 2158: {
1.1.1.8 root 2159: TCGv_i64 t2 = tcg_temp_new_i64();
2160: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2161:
1.1.1.8 root 2162: tcg_gen_ext_tl_i64(t2, t0);
2163: tcg_gen_ext_tl_i64(t3, t1);
2164: tcg_gen_mul_i64(t2, t2, t3);
2165: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2166: tcg_gen_add_i64(t2, t2, t3);
2167: tcg_temp_free_i64(t3);
2168: tcg_gen_trunc_i64_tl(t0, t2);
2169: tcg_gen_shri_i64(t2, t2, 32);
2170: tcg_gen_trunc_i64_tl(t1, t2);
2171: tcg_temp_free_i64(t2);
1.1.1.7 root 2172: tcg_gen_ext32s_tl(cpu_LO[0], t0);
1.1.1.8 root 2173: tcg_gen_ext32s_tl(cpu_HI[0], t1);
1.1.1.7 root 2174: }
1.1 root 2175: opn = "madd";
2176: break;
2177: case OPC_MADDU:
1.1.1.7 root 2178: {
1.1.1.8 root 2179: TCGv_i64 t2 = tcg_temp_new_i64();
2180: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2181:
2182: tcg_gen_ext32u_tl(t0, t0);
2183: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2184: tcg_gen_extu_tl_i64(t2, t0);
2185: tcg_gen_extu_tl_i64(t3, t1);
2186: tcg_gen_mul_i64(t2, t2, t3);
2187: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2188: tcg_gen_add_i64(t2, t2, t3);
2189: tcg_temp_free_i64(t3);
2190: tcg_gen_trunc_i64_tl(t0, t2);
2191: tcg_gen_shri_i64(t2, t2, 32);
2192: tcg_gen_trunc_i64_tl(t1, t2);
2193: tcg_temp_free_i64(t2);
1.1.1.7 root 2194: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2195: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2196: }
1.1 root 2197: opn = "maddu";
2198: break;
2199: case OPC_MSUB:
1.1.1.7 root 2200: {
1.1.1.8 root 2201: TCGv_i64 t2 = tcg_temp_new_i64();
2202: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2203:
1.1.1.8 root 2204: tcg_gen_ext_tl_i64(t2, t0);
2205: tcg_gen_ext_tl_i64(t3, t1);
2206: tcg_gen_mul_i64(t2, t2, t3);
2207: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2208: tcg_gen_sub_i64(t2, t3, t2);
2209: tcg_temp_free_i64(t3);
2210: tcg_gen_trunc_i64_tl(t0, t2);
2211: tcg_gen_shri_i64(t2, t2, 32);
2212: tcg_gen_trunc_i64_tl(t1, t2);
2213: tcg_temp_free_i64(t2);
1.1.1.7 root 2214: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2215: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2216: }
1.1 root 2217: opn = "msub";
2218: break;
2219: case OPC_MSUBU:
1.1.1.7 root 2220: {
1.1.1.8 root 2221: TCGv_i64 t2 = tcg_temp_new_i64();
2222: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2223:
2224: tcg_gen_ext32u_tl(t0, t0);
2225: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2226: tcg_gen_extu_tl_i64(t2, t0);
2227: tcg_gen_extu_tl_i64(t3, t1);
2228: tcg_gen_mul_i64(t2, t2, t3);
2229: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2230: tcg_gen_sub_i64(t2, t3, t2);
2231: tcg_temp_free_i64(t3);
2232: tcg_gen_trunc_i64_tl(t0, t2);
2233: tcg_gen_shri_i64(t2, t2, 32);
2234: tcg_gen_trunc_i64_tl(t1, t2);
2235: tcg_temp_free_i64(t2);
1.1.1.7 root 2236: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2237: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2238: }
1.1 root 2239: opn = "msubu";
2240: break;
2241: default:
1.1.1.6 root 2242: MIPS_INVAL(opn);
1.1 root 2243: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2244: goto out;
1.1 root 2245: }
1.1.1.13! root 2246: (void)opn; /* avoid a compiler warning */
1.1 root 2247: MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1.1.1.7 root 2248: out:
2249: tcg_temp_free(t0);
2250: tcg_temp_free(t1);
1.1 root 2251: }
2252:
1.1.1.6 root 2253: static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2254: int rd, int rs, int rt)
2255: {
2256: const char *opn = "mul vr54xx";
1.1.1.8 root 2257: TCGv t0 = tcg_temp_new();
2258: TCGv t1 = tcg_temp_new();
1.1.1.6 root 2259:
1.1.1.7 root 2260: gen_load_gpr(t0, rs);
2261: gen_load_gpr(t1, rt);
1.1.1.6 root 2262:
2263: switch (opc) {
2264: case OPC_VR54XX_MULS:
1.1.1.7 root 2265: gen_helper_muls(t0, t0, t1);
1.1.1.6 root 2266: opn = "muls";
1.1.1.7 root 2267: break;
1.1.1.6 root 2268: case OPC_VR54XX_MULSU:
1.1.1.7 root 2269: gen_helper_mulsu(t0, t0, t1);
1.1.1.6 root 2270: opn = "mulsu";
1.1.1.7 root 2271: break;
1.1.1.6 root 2272: case OPC_VR54XX_MACC:
1.1.1.7 root 2273: gen_helper_macc(t0, t0, t1);
1.1.1.6 root 2274: opn = "macc";
1.1.1.7 root 2275: break;
1.1.1.6 root 2276: case OPC_VR54XX_MACCU:
1.1.1.7 root 2277: gen_helper_maccu(t0, t0, t1);
1.1.1.6 root 2278: opn = "maccu";
1.1.1.7 root 2279: break;
1.1.1.6 root 2280: case OPC_VR54XX_MSAC:
1.1.1.7 root 2281: gen_helper_msac(t0, t0, t1);
1.1.1.6 root 2282: opn = "msac";
1.1.1.7 root 2283: break;
1.1.1.6 root 2284: case OPC_VR54XX_MSACU:
1.1.1.7 root 2285: gen_helper_msacu(t0, t0, t1);
1.1.1.6 root 2286: opn = "msacu";
1.1.1.7 root 2287: break;
1.1.1.6 root 2288: case OPC_VR54XX_MULHI:
1.1.1.7 root 2289: gen_helper_mulhi(t0, t0, t1);
1.1.1.6 root 2290: opn = "mulhi";
1.1.1.7 root 2291: break;
1.1.1.6 root 2292: case OPC_VR54XX_MULHIU:
1.1.1.7 root 2293: gen_helper_mulhiu(t0, t0, t1);
1.1.1.6 root 2294: opn = "mulhiu";
1.1.1.7 root 2295: break;
1.1.1.6 root 2296: case OPC_VR54XX_MULSHI:
1.1.1.7 root 2297: gen_helper_mulshi(t0, t0, t1);
1.1.1.6 root 2298: opn = "mulshi";
1.1.1.7 root 2299: break;
1.1.1.6 root 2300: case OPC_VR54XX_MULSHIU:
1.1.1.7 root 2301: gen_helper_mulshiu(t0, t0, t1);
1.1.1.6 root 2302: opn = "mulshiu";
1.1.1.7 root 2303: break;
1.1.1.6 root 2304: case OPC_VR54XX_MACCHI:
1.1.1.7 root 2305: gen_helper_macchi(t0, t0, t1);
1.1.1.6 root 2306: opn = "macchi";
1.1.1.7 root 2307: break;
1.1.1.6 root 2308: case OPC_VR54XX_MACCHIU:
1.1.1.7 root 2309: gen_helper_macchiu(t0, t0, t1);
1.1.1.6 root 2310: opn = "macchiu";
1.1.1.7 root 2311: break;
1.1.1.6 root 2312: case OPC_VR54XX_MSACHI:
1.1.1.7 root 2313: gen_helper_msachi(t0, t0, t1);
1.1.1.6 root 2314: opn = "msachi";
1.1.1.7 root 2315: break;
1.1.1.6 root 2316: case OPC_VR54XX_MSACHIU:
1.1.1.7 root 2317: gen_helper_msachiu(t0, t0, t1);
1.1.1.6 root 2318: opn = "msachiu";
1.1.1.7 root 2319: break;
1.1.1.6 root 2320: default:
2321: MIPS_INVAL("mul vr54xx");
2322: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2323: goto out;
1.1.1.6 root 2324: }
1.1.1.7 root 2325: gen_store_gpr(t0, rd);
1.1.1.13! root 2326: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 2327: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1.1.1.7 root 2328:
2329: out:
2330: tcg_temp_free(t0);
2331: tcg_temp_free(t1);
1.1.1.6 root 2332: }
2333:
1.1.1.5 root 2334: static void gen_cl (DisasContext *ctx, uint32_t opc,
1.1 root 2335: int rd, int rs)
2336: {
1.1.1.6 root 2337: const char *opn = "CLx";
1.1.1.8 root 2338: TCGv t0;
1.1.1.7 root 2339:
1.1 root 2340: if (rd == 0) {
1.1.1.6 root 2341: /* Treat as NOP. */
1.1 root 2342: MIPS_DEBUG("NOP");
1.1.1.8 root 2343: return;
1.1 root 2344: }
1.1.1.8 root 2345: t0 = tcg_temp_new();
1.1.1.7 root 2346: gen_load_gpr(t0, rs);
1.1 root 2347: switch (opc) {
2348: case OPC_CLO:
1.1.1.8 root 2349: gen_helper_clo(cpu_gpr[rd], t0);
1.1 root 2350: opn = "clo";
2351: break;
2352: case OPC_CLZ:
1.1.1.8 root 2353: gen_helper_clz(cpu_gpr[rd], t0);
1.1 root 2354: opn = "clz";
2355: break;
1.1.1.6 root 2356: #if defined(TARGET_MIPS64)
1.1.1.5 root 2357: case OPC_DCLO:
1.1.1.8 root 2358: gen_helper_dclo(cpu_gpr[rd], t0);
1.1.1.5 root 2359: opn = "dclo";
2360: break;
2361: case OPC_DCLZ:
1.1.1.8 root 2362: gen_helper_dclz(cpu_gpr[rd], t0);
1.1.1.5 root 2363: opn = "dclz";
2364: break;
2365: #endif
1.1 root 2366: }
1.1.1.13! root 2367: (void)opn; /* avoid a compiler warning */
1.1 root 2368: MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1.1.1.7 root 2369: tcg_temp_free(t0);
1.1 root 2370: }
2371:
1.1.1.12 root 2372: /* Godson integer instructions */
2373: static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
2374: int rd, int rs, int rt)
2375: {
2376: const char *opn = "loongson";
2377: TCGv t0, t1;
2378:
2379: if (rd == 0) {
2380: /* Treat as NOP. */
2381: MIPS_DEBUG("NOP");
2382: return;
2383: }
2384:
2385: switch (opc) {
2386: case OPC_MULT_G_2E:
2387: case OPC_MULT_G_2F:
2388: case OPC_MULTU_G_2E:
2389: case OPC_MULTU_G_2F:
2390: #if defined(TARGET_MIPS64)
2391: case OPC_DMULT_G_2E:
2392: case OPC_DMULT_G_2F:
2393: case OPC_DMULTU_G_2E:
2394: case OPC_DMULTU_G_2F:
2395: #endif
2396: t0 = tcg_temp_new();
2397: t1 = tcg_temp_new();
2398: break;
2399: default:
2400: t0 = tcg_temp_local_new();
2401: t1 = tcg_temp_local_new();
2402: break;
2403: }
2404:
2405: gen_load_gpr(t0, rs);
2406: gen_load_gpr(t1, rt);
2407:
2408: switch (opc) {
2409: case OPC_MULT_G_2E:
2410: case OPC_MULT_G_2F:
2411: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2412: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2413: opn = "mult.g";
2414: break;
2415: case OPC_MULTU_G_2E:
2416: case OPC_MULTU_G_2F:
2417: tcg_gen_ext32u_tl(t0, t0);
2418: tcg_gen_ext32u_tl(t1, t1);
2419: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2420: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2421: opn = "multu.g";
2422: break;
2423: case OPC_DIV_G_2E:
2424: case OPC_DIV_G_2F:
2425: {
2426: int l1 = gen_new_label();
2427: int l2 = gen_new_label();
2428: int l3 = gen_new_label();
2429: tcg_gen_ext32s_tl(t0, t0);
2430: tcg_gen_ext32s_tl(t1, t1);
2431: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2432: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2433: tcg_gen_br(l3);
2434: gen_set_label(l1);
2435: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2436: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2437: tcg_gen_mov_tl(cpu_gpr[rd], t0);
2438: tcg_gen_br(l3);
2439: gen_set_label(l2);
2440: tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2441: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2442: gen_set_label(l3);
2443: }
2444: opn = "div.g";
2445: break;
2446: case OPC_DIVU_G_2E:
2447: case OPC_DIVU_G_2F:
2448: {
2449: int l1 = gen_new_label();
2450: int l2 = gen_new_label();
2451: tcg_gen_ext32u_tl(t0, t0);
2452: tcg_gen_ext32u_tl(t1, t1);
2453: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2454: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2455: tcg_gen_br(l2);
2456: gen_set_label(l1);
2457: tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2458: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2459: gen_set_label(l2);
2460: }
2461: opn = "divu.g";
2462: break;
2463: case OPC_MOD_G_2E:
2464: case OPC_MOD_G_2F:
2465: {
2466: int l1 = gen_new_label();
2467: int l2 = gen_new_label();
2468: int l3 = gen_new_label();
2469: tcg_gen_ext32u_tl(t0, t0);
2470: tcg_gen_ext32u_tl(t1, t1);
2471: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2472: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2473: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2474: gen_set_label(l1);
2475: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2476: tcg_gen_br(l3);
2477: gen_set_label(l2);
2478: tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2479: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2480: gen_set_label(l3);
2481: }
2482: opn = "mod.g";
2483: break;
2484: case OPC_MODU_G_2E:
2485: case OPC_MODU_G_2F:
2486: {
2487: int l1 = gen_new_label();
2488: int l2 = gen_new_label();
2489: tcg_gen_ext32u_tl(t0, t0);
2490: tcg_gen_ext32u_tl(t1, t1);
2491: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2492: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2493: tcg_gen_br(l2);
2494: gen_set_label(l1);
2495: tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2496: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2497: gen_set_label(l2);
2498: }
2499: opn = "modu.g";
2500: break;
2501: #if defined(TARGET_MIPS64)
2502: case OPC_DMULT_G_2E:
2503: case OPC_DMULT_G_2F:
2504: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2505: opn = "dmult.g";
2506: break;
2507: case OPC_DMULTU_G_2E:
2508: case OPC_DMULTU_G_2F:
2509: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2510: opn = "dmultu.g";
2511: break;
2512: case OPC_DDIV_G_2E:
2513: case OPC_DDIV_G_2F:
2514: {
2515: int l1 = gen_new_label();
2516: int l2 = gen_new_label();
2517: int l3 = gen_new_label();
2518: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2519: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2520: tcg_gen_br(l3);
2521: gen_set_label(l1);
2522: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2523: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2524: tcg_gen_mov_tl(cpu_gpr[rd], t0);
2525: tcg_gen_br(l3);
2526: gen_set_label(l2);
2527: tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2528: gen_set_label(l3);
2529: }
2530: opn = "ddiv.g";
2531: break;
2532: case OPC_DDIVU_G_2E:
2533: case OPC_DDIVU_G_2F:
2534: {
2535: int l1 = gen_new_label();
2536: int l2 = gen_new_label();
2537: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2538: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2539: tcg_gen_br(l2);
2540: gen_set_label(l1);
2541: tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2542: gen_set_label(l2);
2543: }
2544: opn = "ddivu.g";
2545: break;
2546: case OPC_DMOD_G_2E:
2547: case OPC_DMOD_G_2F:
2548: {
2549: int l1 = gen_new_label();
2550: int l2 = gen_new_label();
2551: int l3 = gen_new_label();
2552: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2553: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2554: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2555: gen_set_label(l1);
2556: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2557: tcg_gen_br(l3);
2558: gen_set_label(l2);
2559: tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2560: gen_set_label(l3);
2561: }
2562: opn = "dmod.g";
2563: break;
2564: case OPC_DMODU_G_2E:
2565: case OPC_DMODU_G_2F:
2566: {
2567: int l1 = gen_new_label();
2568: int l2 = gen_new_label();
2569: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2570: tcg_gen_movi_tl(cpu_gpr[rd], 0);
2571: tcg_gen_br(l2);
2572: gen_set_label(l1);
2573: tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2574: gen_set_label(l2);
2575: }
2576: opn = "dmodu.g";
2577: break;
2578: #endif
2579: }
2580:
1.1.1.13! root 2581: (void)opn; /* avoid a compiler warning */
1.1.1.12 root 2582: MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2583: tcg_temp_free(t0);
2584: tcg_temp_free(t1);
2585: }
2586:
2587: /* Traps */
1.1.1.5 root 2588: static void gen_trap (DisasContext *ctx, uint32_t opc,
1.1 root 2589: int rs, int rt, int16_t imm)
2590: {
2591: int cond;
1.1.1.8 root 2592: TCGv t0 = tcg_temp_new();
2593: TCGv t1 = tcg_temp_new();
1.1 root 2594:
2595: cond = 0;
2596: /* Load needed operands */
2597: switch (opc) {
2598: case OPC_TEQ:
2599: case OPC_TGE:
2600: case OPC_TGEU:
2601: case OPC_TLT:
2602: case OPC_TLTU:
2603: case OPC_TNE:
2604: /* Compare two registers */
2605: if (rs != rt) {
1.1.1.7 root 2606: gen_load_gpr(t0, rs);
2607: gen_load_gpr(t1, rt);
1.1 root 2608: cond = 1;
2609: }
1.1.1.5 root 2610: break;
1.1 root 2611: case OPC_TEQI:
2612: case OPC_TGEI:
2613: case OPC_TGEIU:
2614: case OPC_TLTI:
2615: case OPC_TLTIU:
2616: case OPC_TNEI:
2617: /* Compare register to immediate */
2618: if (rs != 0 || imm != 0) {
1.1.1.7 root 2619: gen_load_gpr(t0, rs);
2620: tcg_gen_movi_tl(t1, (int32_t)imm);
1.1 root 2621: cond = 1;
2622: }
2623: break;
2624: }
2625: if (cond == 0) {
2626: switch (opc) {
2627: case OPC_TEQ: /* rs == rs */
2628: case OPC_TEQI: /* r0 == 0 */
2629: case OPC_TGE: /* rs >= rs */
2630: case OPC_TGEI: /* r0 >= 0 */
2631: case OPC_TGEU: /* rs >= rs unsigned */
2632: case OPC_TGEIU: /* r0 >= 0 unsigned */
2633: /* Always trap */
1.1.1.8 root 2634: generate_exception(ctx, EXCP_TRAP);
1.1 root 2635: break;
2636: case OPC_TLT: /* rs < rs */
2637: case OPC_TLTI: /* r0 < 0 */
2638: case OPC_TLTU: /* rs < rs unsigned */
2639: case OPC_TLTIU: /* r0 < 0 unsigned */
2640: case OPC_TNE: /* rs != rs */
2641: case OPC_TNEI: /* r0 != 0 */
1.1.1.6 root 2642: /* Never trap: treat as NOP. */
1.1.1.8 root 2643: break;
1.1 root 2644: }
2645: } else {
1.1.1.8 root 2646: int l1 = gen_new_label();
2647:
1.1 root 2648: switch (opc) {
2649: case OPC_TEQ:
2650: case OPC_TEQI:
1.1.1.8 root 2651: tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
1.1 root 2652: break;
2653: case OPC_TGE:
2654: case OPC_TGEI:
1.1.1.8 root 2655: tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
1.1 root 2656: break;
2657: case OPC_TGEU:
2658: case OPC_TGEIU:
1.1.1.8 root 2659: tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
1.1 root 2660: break;
2661: case OPC_TLT:
2662: case OPC_TLTI:
1.1.1.8 root 2663: tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
1.1 root 2664: break;
2665: case OPC_TLTU:
2666: case OPC_TLTIU:
1.1.1.8 root 2667: tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
1.1 root 2668: break;
2669: case OPC_TNE:
2670: case OPC_TNEI:
1.1.1.8 root 2671: tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
1.1 root 2672: break;
2673: }
1.1.1.8 root 2674: generate_exception(ctx, EXCP_TRAP);
1.1.1.7 root 2675: gen_set_label(l1);
2676: }
2677: tcg_temp_free(t0);
2678: tcg_temp_free(t1);
1.1 root 2679: }
2680:
1.1.1.7 root 2681: static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1.1.1.2 root 2682: {
2683: TranslationBlock *tb;
2684: tb = ctx->tb;
1.1.1.9 root 2685: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2686: likely(!ctx->singlestep_enabled)) {
1.1.1.7 root 2687: tcg_gen_goto_tb(n);
1.1.1.6 root 2688: gen_save_pc(dest);
1.1.1.7 root 2689: tcg_gen_exit_tb((long)tb + n);
1.1.1.2 root 2690: } else {
1.1.1.6 root 2691: gen_save_pc(dest);
1.1.1.9 root 2692: if (ctx->singlestep_enabled) {
2693: save_cpu_state(ctx, 0);
2694: gen_helper_0i(raise_exception, EXCP_DEBUG);
2695: }
1.1.1.7 root 2696: tcg_gen_exit_tb(0);
1.1.1.2 root 2697: }
2698: }
2699:
1.1 root 2700: /* Branches (before delay slot) */
1.1.1.5 root 2701: static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1.1.1.12 root 2702: int insn_bytes,
1.1 root 2703: int rs, int rt, int32_t offset)
2704: {
1.1.1.7 root 2705: target_ulong btgt = -1;
1.1.1.6 root 2706: int blink = 0;
1.1.1.7 root 2707: int bcond_compute = 0;
1.1.1.8 root 2708: TCGv t0 = tcg_temp_new();
2709: TCGv t1 = tcg_temp_new();
1.1 root 2710:
1.1.1.6 root 2711: if (ctx->hflags & MIPS_HFLAG_BMASK) {
2712: #ifdef MIPS_DEBUG_DISAS
1.1.1.7 root 2713: LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
1.1.1.6 root 2714: #endif
2715: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2716: goto out;
1.1.1.6 root 2717: }
2718:
2719: /* Load needed operands */
2720: switch (opc) {
2721: case OPC_BEQ:
2722: case OPC_BEQL:
2723: case OPC_BNE:
2724: case OPC_BNEL:
1.1 root 2725: /* Compare two registers */
2726: if (rs != rt) {
1.1.1.7 root 2727: gen_load_gpr(t0, rs);
2728: gen_load_gpr(t1, rt);
2729: bcond_compute = 1;
1.1 root 2730: }
1.1.1.12 root 2731: btgt = ctx->pc + insn_bytes + offset;
1.1 root 2732: break;
2733: case OPC_BGEZ:
2734: case OPC_BGEZAL:
1.1.1.12 root 2735: case OPC_BGEZALS:
1.1 root 2736: case OPC_BGEZALL:
2737: case OPC_BGEZL:
2738: case OPC_BGTZ:
2739: case OPC_BGTZL:
2740: case OPC_BLEZ:
2741: case OPC_BLEZL:
2742: case OPC_BLTZ:
2743: case OPC_BLTZAL:
1.1.1.12 root 2744: case OPC_BLTZALS:
1.1 root 2745: case OPC_BLTZALL:
2746: case OPC_BLTZL:
2747: /* Compare to zero */
2748: if (rs != 0) {
1.1.1.7 root 2749: gen_load_gpr(t0, rs);
2750: bcond_compute = 1;
1.1 root 2751: }
1.1.1.12 root 2752: btgt = ctx->pc + insn_bytes + offset;
1.1 root 2753: break;
2754: case OPC_J:
2755: case OPC_JAL:
1.1.1.12 root 2756: case OPC_JALX:
2757: case OPC_JALS:
2758: case OPC_JALXS:
1.1 root 2759: /* Jump to immediate */
1.1.1.12 root 2760: btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
1.1 root 2761: break;
2762: case OPC_JR:
2763: case OPC_JALR:
1.1.1.12 root 2764: case OPC_JALRC:
2765: case OPC_JALRS:
1.1 root 2766: /* Jump to register */
1.1.1.5 root 2767: if (offset != 0 && offset != 16) {
2768: /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1.1.1.6 root 2769: others are reserved. */
2770: MIPS_INVAL("jump hint");
1.1 root 2771: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2772: goto out;
1.1 root 2773: }
1.1.1.7 root 2774: gen_load_gpr(btarget, rs);
1.1 root 2775: break;
2776: default:
2777: MIPS_INVAL("branch/jump");
2778: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2779: goto out;
1.1 root 2780: }
1.1.1.7 root 2781: if (bcond_compute == 0) {
1.1 root 2782: /* No condition to be computed */
2783: switch (opc) {
2784: case OPC_BEQ: /* rx == rx */
2785: case OPC_BEQL: /* rx == rx likely */
2786: case OPC_BGEZ: /* 0 >= 0 */
2787: case OPC_BGEZL: /* 0 >= 0 likely */
2788: case OPC_BLEZ: /* 0 <= 0 */
2789: case OPC_BLEZL: /* 0 <= 0 likely */
2790: /* Always take */
1.1.1.2 root 2791: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 2792: MIPS_DEBUG("balways");
2793: break;
1.1.1.12 root 2794: case OPC_BGEZALS:
1.1 root 2795: case OPC_BGEZAL: /* 0 >= 0 */
2796: case OPC_BGEZALL: /* 0 >= 0 likely */
1.1.1.12 root 2797: ctx->hflags |= (opc == OPC_BGEZALS
2798: ? MIPS_HFLAG_BDS16
2799: : MIPS_HFLAG_BDS32);
1.1 root 2800: /* Always take and link */
2801: blink = 31;
1.1.1.2 root 2802: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 2803: MIPS_DEBUG("balways and link");
2804: break;
2805: case OPC_BNE: /* rx != rx */
2806: case OPC_BGTZ: /* 0 > 0 */
2807: case OPC_BLTZ: /* 0 < 0 */
1.1.1.6 root 2808: /* Treat as NOP. */
1.1 root 2809: MIPS_DEBUG("bnever (NOP)");
1.1.1.7 root 2810: goto out;
1.1.1.12 root 2811: case OPC_BLTZALS:
1.1.1.2 root 2812: case OPC_BLTZAL: /* 0 < 0 */
1.1.1.12 root 2813: ctx->hflags |= (opc == OPC_BLTZALS
2814: ? MIPS_HFLAG_BDS16
2815: : MIPS_HFLAG_BDS32);
2816: /* Handle as an unconditional branch to get correct delay
2817: slot checking. */
2818: blink = 31;
2819: btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
2820: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.6 root 2821: MIPS_DEBUG("bnever and link");
1.1.1.12 root 2822: break;
1.1.1.2 root 2823: case OPC_BLTZALL: /* 0 < 0 likely */
1.1.1.8 root 2824: tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
1.1.1.6 root 2825: /* Skip the instruction in the delay slot */
2826: MIPS_DEBUG("bnever, link and skip");
2827: ctx->pc += 4;
1.1.1.7 root 2828: goto out;
1.1 root 2829: case OPC_BNEL: /* rx != rx likely */
2830: case OPC_BGTZL: /* 0 > 0 likely */
2831: case OPC_BLTZL: /* 0 < 0 likely */
2832: /* Skip the instruction in the delay slot */
2833: MIPS_DEBUG("bnever and skip");
1.1.1.6 root 2834: ctx->pc += 4;
1.1.1.7 root 2835: goto out;
1.1 root 2836: case OPC_J:
1.1.1.2 root 2837: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.7 root 2838: MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
1.1 root 2839: break;
1.1.1.12 root 2840: case OPC_JALXS:
2841: case OPC_JALX:
2842: ctx->hflags |= MIPS_HFLAG_BX;
2843: /* Fallthrough */
2844: case OPC_JALS:
1.1 root 2845: case OPC_JAL:
2846: blink = 31;
1.1.1.2 root 2847: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.12 root 2848: ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
2849: ? MIPS_HFLAG_BDS16
2850: : MIPS_HFLAG_BDS32);
1.1.1.7 root 2851: MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
1.1 root 2852: break;
2853: case OPC_JR:
1.1.1.2 root 2854: ctx->hflags |= MIPS_HFLAG_BR;
1.1.1.12 root 2855: if (insn_bytes == 4)
2856: ctx->hflags |= MIPS_HFLAG_BDS32;
1.1 root 2857: MIPS_DEBUG("jr %s", regnames[rs]);
2858: break;
1.1.1.12 root 2859: case OPC_JALRS:
1.1 root 2860: case OPC_JALR:
1.1.1.12 root 2861: case OPC_JALRC:
1.1 root 2862: blink = rt;
1.1.1.2 root 2863: ctx->hflags |= MIPS_HFLAG_BR;
1.1.1.12 root 2864: ctx->hflags |= (opc == OPC_JALRS
2865: ? MIPS_HFLAG_BDS16
2866: : MIPS_HFLAG_BDS32);
1.1 root 2867: MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2868: break;
2869: default:
2870: MIPS_INVAL("branch/jump");
2871: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2872: goto out;
1.1 root 2873: }
2874: } else {
2875: switch (opc) {
2876: case OPC_BEQ:
1.1.1.12 root 2877: tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
1.1.1.6 root 2878: MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2879: regnames[rs], regnames[rt], btgt);
1.1 root 2880: goto not_likely;
2881: case OPC_BEQL:
1.1.1.12 root 2882: tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
1.1.1.6 root 2883: MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2884: regnames[rs], regnames[rt], btgt);
1.1 root 2885: goto likely;
2886: case OPC_BNE:
1.1.1.12 root 2887: tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
1.1.1.6 root 2888: MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2889: regnames[rs], regnames[rt], btgt);
1.1 root 2890: goto not_likely;
2891: case OPC_BNEL:
1.1.1.12 root 2892: tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
1.1.1.6 root 2893: MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2894: regnames[rs], regnames[rt], btgt);
1.1 root 2895: goto likely;
2896: case OPC_BGEZ:
1.1.1.12 root 2897: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2898: MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2899: goto not_likely;
2900: case OPC_BGEZL:
1.1.1.12 root 2901: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2902: MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2903: goto likely;
1.1.1.12 root 2904: case OPC_BGEZALS:
1.1 root 2905: case OPC_BGEZAL:
1.1.1.12 root 2906: ctx->hflags |= (opc == OPC_BGEZALS
2907: ? MIPS_HFLAG_BDS16
2908: : MIPS_HFLAG_BDS32);
2909: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2910: MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2911: blink = 31;
2912: goto not_likely;
2913: case OPC_BGEZALL:
1.1.1.12 root 2914: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1 root 2915: blink = 31;
1.1.1.7 root 2916: MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2917: goto likely;
2918: case OPC_BGTZ:
1.1.1.12 root 2919: tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
1.1.1.7 root 2920: MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2921: goto not_likely;
2922: case OPC_BGTZL:
1.1.1.12 root 2923: tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
1.1.1.7 root 2924: MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2925: goto likely;
2926: case OPC_BLEZ:
1.1.1.12 root 2927: tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
1.1.1.7 root 2928: MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2929: goto not_likely;
2930: case OPC_BLEZL:
1.1.1.12 root 2931: tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
1.1.1.7 root 2932: MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2933: goto likely;
2934: case OPC_BLTZ:
1.1.1.12 root 2935: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1.1.7 root 2936: MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2937: goto not_likely;
2938: case OPC_BLTZL:
1.1.1.12 root 2939: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1.1.7 root 2940: MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2941: goto likely;
1.1.1.12 root 2942: case OPC_BLTZALS:
1.1 root 2943: case OPC_BLTZAL:
1.1.1.12 root 2944: ctx->hflags |= (opc == OPC_BLTZALS
2945: ? MIPS_HFLAG_BDS16
2946: : MIPS_HFLAG_BDS32);
2947: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1 root 2948: blink = 31;
1.1.1.7 root 2949: MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2950: not_likely:
1.1.1.2 root 2951: ctx->hflags |= MIPS_HFLAG_BC;
1.1 root 2952: break;
2953: case OPC_BLTZALL:
1.1.1.12 root 2954: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1 root 2955: blink = 31;
1.1.1.7 root 2956: MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2957: likely:
1.1.1.2 root 2958: ctx->hflags |= MIPS_HFLAG_BL;
1.1 root 2959: break;
1.1.1.6 root 2960: default:
2961: MIPS_INVAL("conditional branch/jump");
2962: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2963: goto out;
1.1 root 2964: }
2965: }
1.1.1.6 root 2966: MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
1.1.1.7 root 2967: blink, ctx->hflags, btgt);
1.1.1.6 root 2968:
1.1.1.7 root 2969: ctx->btarget = btgt;
1.1 root 2970: if (blink > 0) {
1.1.1.12 root 2971: int post_delay = insn_bytes;
2972: int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2973:
2974: if (opc != OPC_JALRC)
2975: post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2976:
2977: tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
1.1 root 2978: }
1.1.1.7 root 2979:
2980: out:
1.1.1.12 root 2981: if (insn_bytes == 2)
2982: ctx->hflags |= MIPS_HFLAG_B16;
1.1.1.7 root 2983: tcg_temp_free(t0);
2984: tcg_temp_free(t1);
1.1 root 2985: }
2986:
1.1.1.5 root 2987: /* special3 bitfield operations */
2988: static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1.1.1.7 root 2989: int rs, int lsb, int msb)
1.1 root 2990: {
1.1.1.7 root 2991: TCGv t0 = tcg_temp_new();
2992: TCGv t1 = tcg_temp_new();
2993: target_ulong mask;
2994:
2995: gen_load_gpr(t1, rs);
1.1.1.5 root 2996: switch (opc) {
2997: case OPC_EXT:
2998: if (lsb + msb > 31)
2999: goto fail;
1.1.1.7 root 3000: tcg_gen_shri_tl(t0, t1, lsb);
3001: if (msb != 31) {
3002: tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3003: } else {
3004: tcg_gen_ext32s_tl(t0, t0);
3005: }
1.1.1.5 root 3006: break;
1.1.1.6 root 3007: #if defined(TARGET_MIPS64)
1.1.1.5 root 3008: case OPC_DEXTM:
1.1.1.7 root 3009: tcg_gen_shri_tl(t0, t1, lsb);
3010: if (msb != 31) {
3011: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3012: }
1.1.1.5 root 3013: break;
3014: case OPC_DEXTU:
1.1.1.7 root 3015: tcg_gen_shri_tl(t0, t1, lsb + 32);
3016: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
1.1.1.5 root 3017: break;
3018: case OPC_DEXT:
1.1.1.7 root 3019: tcg_gen_shri_tl(t0, t1, lsb);
3020: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
1.1.1.5 root 3021: break;
1.1.1.6 root 3022: #endif
1.1.1.5 root 3023: case OPC_INS:
3024: if (lsb > msb)
3025: goto fail;
1.1.1.7 root 3026: mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
3027: gen_load_gpr(t0, rt);
3028: tcg_gen_andi_tl(t0, t0, ~mask);
3029: tcg_gen_shli_tl(t1, t1, lsb);
3030: tcg_gen_andi_tl(t1, t1, mask);
3031: tcg_gen_or_tl(t0, t0, t1);
3032: tcg_gen_ext32s_tl(t0, t0);
1.1.1.5 root 3033: break;
1.1.1.6 root 3034: #if defined(TARGET_MIPS64)
1.1.1.5 root 3035: case OPC_DINSM:
3036: if (lsb > msb)
3037: goto fail;
1.1.1.7 root 3038: mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
3039: gen_load_gpr(t0, rt);
3040: tcg_gen_andi_tl(t0, t0, ~mask);
3041: tcg_gen_shli_tl(t1, t1, lsb);
3042: tcg_gen_andi_tl(t1, t1, mask);
3043: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3044: break;
3045: case OPC_DINSU:
3046: if (lsb > msb)
3047: goto fail;
1.1.1.11 root 3048: mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
1.1.1.7 root 3049: gen_load_gpr(t0, rt);
3050: tcg_gen_andi_tl(t0, t0, ~mask);
3051: tcg_gen_shli_tl(t1, t1, lsb + 32);
3052: tcg_gen_andi_tl(t1, t1, mask);
3053: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3054: break;
3055: case OPC_DINS:
3056: if (lsb > msb)
3057: goto fail;
1.1.1.7 root 3058: gen_load_gpr(t0, rt);
3059: mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3060: gen_load_gpr(t0, rt);
3061: tcg_gen_andi_tl(t0, t0, ~mask);
3062: tcg_gen_shli_tl(t1, t1, lsb);
3063: tcg_gen_andi_tl(t1, t1, mask);
3064: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3065: break;
1.1.1.6 root 3066: #endif
1.1.1.5 root 3067: default:
3068: fail:
3069: MIPS_INVAL("bitops");
3070: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 3071: tcg_temp_free(t0);
3072: tcg_temp_free(t1);
1.1 root 3073: return;
3074: }
1.1.1.7 root 3075: gen_store_gpr(t0, rt);
3076: tcg_temp_free(t0);
3077: tcg_temp_free(t1);
3078: }
3079:
3080: static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3081: {
1.1.1.8 root 3082: TCGv t0;
1.1.1.7 root 3083:
1.1.1.8 root 3084: if (rd == 0) {
3085: /* If no destination, treat it as a NOP. */
3086: MIPS_DEBUG("NOP");
3087: return;
3088: }
3089:
3090: t0 = tcg_temp_new();
3091: gen_load_gpr(t0, rt);
1.1.1.7 root 3092: switch (op2) {
3093: case OPC_WSBH:
1.1.1.8 root 3094: {
3095: TCGv t1 = tcg_temp_new();
3096:
3097: tcg_gen_shri_tl(t1, t0, 8);
3098: tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3099: tcg_gen_shli_tl(t0, t0, 8);
3100: tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3101: tcg_gen_or_tl(t0, t0, t1);
3102: tcg_temp_free(t1);
3103: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3104: }
1.1.1.7 root 3105: break;
3106: case OPC_SEB:
1.1.1.8 root 3107: tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
1.1.1.7 root 3108: break;
3109: case OPC_SEH:
1.1.1.8 root 3110: tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
1.1.1.7 root 3111: break;
3112: #if defined(TARGET_MIPS64)
3113: case OPC_DSBH:
1.1.1.8 root 3114: {
3115: TCGv t1 = tcg_temp_new();
3116:
3117: tcg_gen_shri_tl(t1, t0, 8);
3118: tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3119: tcg_gen_shli_tl(t0, t0, 8);
3120: tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3121: tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3122: tcg_temp_free(t1);
3123: }
1.1.1.7 root 3124: break;
3125: case OPC_DSHD:
1.1.1.8 root 3126: {
3127: TCGv t1 = tcg_temp_new();
3128:
3129: tcg_gen_shri_tl(t1, t0, 16);
3130: tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3131: tcg_gen_shli_tl(t0, t0, 16);
3132: tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3133: tcg_gen_or_tl(t0, t0, t1);
3134: tcg_gen_shri_tl(t1, t0, 32);
3135: tcg_gen_shli_tl(t0, t0, 32);
3136: tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3137: tcg_temp_free(t1);
3138: }
1.1.1.7 root 3139: break;
3140: #endif
3141: default:
3142: MIPS_INVAL("bsfhl");
3143: generate_exception(ctx, EXCP_RI);
3144: tcg_temp_free(t0);
3145: return;
3146: }
3147: tcg_temp_free(t0);
1.1.1.5 root 3148: }
1.1.1.4 root 3149:
1.1.1.7 root 3150: #ifndef CONFIG_USER_ONLY
1.1.1.5 root 3151: /* CP0 (MMU and control) */
1.1.1.8 root 3152: static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
1.1.1.7 root 3153: {
1.1.1.8 root 3154: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 3155:
1.1.1.8 root 3156: tcg_gen_ld_i32(t0, cpu_env, off);
3157: tcg_gen_ext_i32_tl(arg, t0);
3158: tcg_temp_free_i32(t0);
1.1.1.7 root 3159: }
3160:
1.1.1.8 root 3161: static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
1.1.1.7 root 3162: {
1.1.1.8 root 3163: tcg_gen_ld_tl(arg, cpu_env, off);
3164: tcg_gen_ext32s_tl(arg, arg);
1.1.1.7 root 3165: }
3166:
1.1.1.8 root 3167: static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
1.1.1.7 root 3168: {
1.1.1.8 root 3169: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 3170:
1.1.1.8 root 3171: tcg_gen_trunc_tl_i32(t0, arg);
3172: tcg_gen_st_i32(t0, cpu_env, off);
3173: tcg_temp_free_i32(t0);
1.1.1.7 root 3174: }
3175:
1.1.1.8 root 3176: static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
1.1.1.7 root 3177: {
1.1.1.8 root 3178: tcg_gen_ext32s_tl(arg, arg);
3179: tcg_gen_st_tl(arg, cpu_env, off);
1.1.1.7 root 3180: }
3181:
1.1.1.8 root 3182: static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 3183: {
3184: const char *rn = "invalid";
3185:
1.1.1.6 root 3186: if (sel != 0)
3187: check_insn(env, ctx, ISA_MIPS32);
3188:
1.1.1.5 root 3189: switch (reg) {
3190: case 0:
3191: switch (sel) {
3192: case 0:
1.1.1.8 root 3193: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
1.1.1.5 root 3194: rn = "Index";
3195: break;
3196: case 1:
1.1.1.6 root 3197: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3198: gen_helper_mfc0_mvpcontrol(arg);
1.1.1.5 root 3199: rn = "MVPControl";
1.1.1.6 root 3200: break;
1.1.1.5 root 3201: case 2:
1.1.1.6 root 3202: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3203: gen_helper_mfc0_mvpconf0(arg);
1.1.1.5 root 3204: rn = "MVPConf0";
1.1.1.6 root 3205: break;
1.1.1.5 root 3206: case 3:
1.1.1.6 root 3207: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3208: gen_helper_mfc0_mvpconf1(arg);
1.1.1.5 root 3209: rn = "MVPConf1";
1.1.1.6 root 3210: break;
1.1.1.5 root 3211: default:
3212: goto die;
1.1 root 3213: }
3214: break;
1.1.1.5 root 3215: case 1:
3216: switch (sel) {
3217: case 0:
1.1.1.8 root 3218: gen_helper_mfc0_random(arg);
1.1.1.5 root 3219: rn = "Random";
1.1.1.6 root 3220: break;
1.1.1.5 root 3221: case 1:
1.1.1.6 root 3222: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3223: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
1.1.1.5 root 3224: rn = "VPEControl";
1.1.1.6 root 3225: break;
1.1.1.5 root 3226: case 2:
1.1.1.6 root 3227: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3228: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
1.1.1.5 root 3229: rn = "VPEConf0";
1.1.1.6 root 3230: break;
1.1.1.5 root 3231: case 3:
1.1.1.6 root 3232: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3233: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
1.1.1.5 root 3234: rn = "VPEConf1";
1.1.1.6 root 3235: break;
1.1.1.5 root 3236: case 4:
1.1.1.6 root 3237: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3238: gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
1.1.1.5 root 3239: rn = "YQMask";
1.1.1.6 root 3240: break;
1.1.1.5 root 3241: case 5:
1.1.1.6 root 3242: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3243: gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 3244: rn = "VPESchedule";
1.1.1.6 root 3245: break;
1.1.1.5 root 3246: case 6:
1.1.1.6 root 3247: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3248: gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 3249: rn = "VPEScheFBack";
1.1.1.6 root 3250: break;
1.1.1.5 root 3251: case 7:
1.1.1.6 root 3252: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3253: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
1.1.1.5 root 3254: rn = "VPEOpt";
1.1.1.6 root 3255: break;
1.1.1.5 root 3256: default:
3257: goto die;
3258: }
1.1 root 3259: break;
1.1.1.5 root 3260: case 2:
3261: switch (sel) {
3262: case 0:
1.1.1.8 root 3263: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
3264: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3265: rn = "EntryLo0";
3266: break;
3267: case 1:
3268: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3269: gen_helper_mfc0_tcstatus(arg);
1.1.1.6 root 3270: rn = "TCStatus";
3271: break;
3272: case 2:
3273: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3274: gen_helper_mfc0_tcbind(arg);
1.1.1.6 root 3275: rn = "TCBind";
3276: break;
1.1.1.5 root 3277: case 3:
1.1.1.6 root 3278: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3279: gen_helper_mfc0_tcrestart(arg);
1.1.1.6 root 3280: rn = "TCRestart";
3281: break;
1.1.1.5 root 3282: case 4:
1.1.1.6 root 3283: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3284: gen_helper_mfc0_tchalt(arg);
1.1.1.6 root 3285: rn = "TCHalt";
3286: break;
1.1.1.5 root 3287: case 5:
1.1.1.6 root 3288: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3289: gen_helper_mfc0_tccontext(arg);
1.1.1.6 root 3290: rn = "TCContext";
3291: break;
1.1.1.5 root 3292: case 6:
1.1.1.6 root 3293: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3294: gen_helper_mfc0_tcschedule(arg);
1.1.1.6 root 3295: rn = "TCSchedule";
3296: break;
1.1.1.5 root 3297: case 7:
1.1.1.6 root 3298: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3299: gen_helper_mfc0_tcschefback(arg);
1.1.1.6 root 3300: rn = "TCScheFBack";
3301: break;
1.1.1.5 root 3302: default:
3303: goto die;
3304: }
1.1 root 3305: break;
1.1.1.5 root 3306: case 3:
3307: switch (sel) {
3308: case 0:
1.1.1.8 root 3309: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
3310: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3311: rn = "EntryLo1";
3312: break;
1.1.1.5 root 3313: default:
3314: goto die;
1.1.1.6 root 3315: }
1.1 root 3316: break;
1.1.1.5 root 3317: case 4:
3318: switch (sel) {
3319: case 0:
1.1.1.8 root 3320: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3321: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3322: rn = "Context";
3323: break;
3324: case 1:
1.1.1.8 root 3325: // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 3326: rn = "ContextConfig";
3327: // break;
1.1.1.5 root 3328: default:
3329: goto die;
1.1.1.6 root 3330: }
1.1 root 3331: break;
1.1.1.5 root 3332: case 5:
3333: switch (sel) {
3334: case 0:
1.1.1.8 root 3335: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
1.1.1.6 root 3336: rn = "PageMask";
3337: break;
3338: case 1:
3339: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3340: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
1.1.1.6 root 3341: rn = "PageGrain";
3342: break;
1.1.1.5 root 3343: default:
3344: goto die;
1.1.1.6 root 3345: }
1.1 root 3346: break;
1.1.1.5 root 3347: case 6:
3348: switch (sel) {
3349: case 0:
1.1.1.8 root 3350: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
1.1.1.6 root 3351: rn = "Wired";
3352: break;
3353: case 1:
3354: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3355: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
1.1.1.6 root 3356: rn = "SRSConf0";
3357: break;
3358: case 2:
3359: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3360: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
1.1.1.6 root 3361: rn = "SRSConf1";
3362: break;
1.1.1.5 root 3363: case 3:
1.1.1.6 root 3364: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3365: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
1.1.1.6 root 3366: rn = "SRSConf2";
3367: break;
1.1.1.5 root 3368: case 4:
1.1.1.6 root 3369: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3370: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
1.1.1.6 root 3371: rn = "SRSConf3";
3372: break;
1.1.1.5 root 3373: case 5:
1.1.1.6 root 3374: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3375: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
1.1.1.6 root 3376: rn = "SRSConf4";
3377: break;
1.1.1.5 root 3378: default:
3379: goto die;
1.1.1.6 root 3380: }
1.1 root 3381: break;
1.1.1.5 root 3382: case 7:
3383: switch (sel) {
3384: case 0:
1.1.1.6 root 3385: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3386: gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
1.1.1.6 root 3387: rn = "HWREna";
3388: break;
1.1.1.5 root 3389: default:
3390: goto die;
1.1.1.6 root 3391: }
1.1 root 3392: break;
1.1.1.5 root 3393: case 8:
3394: switch (sel) {
3395: case 0:
1.1.1.8 root 3396: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3397: tcg_gen_ext32s_tl(arg, arg);
1.1.1.7 root 3398: rn = "BadVAddr";
1.1.1.6 root 3399: break;
1.1.1.5 root 3400: default:
3401: goto die;
3402: }
1.1.1.2 root 3403: break;
1.1.1.5 root 3404: case 9:
3405: switch (sel) {
3406: case 0:
1.1.1.7 root 3407: /* Mark as an IO operation because we read the time. */
3408: if (use_icount)
3409: gen_io_start();
1.1.1.8 root 3410: gen_helper_mfc0_count(arg);
1.1.1.7 root 3411: if (use_icount) {
3412: gen_io_end();
3413: }
1.1.1.13! root 3414: /* Break the TB to be able to take timer interrupts immediately
! 3415: after reading count. */
! 3416: ctx->bstate = BS_STOP;
1.1.1.6 root 3417: rn = "Count";
3418: break;
3419: /* 6,7 are implementation dependent */
1.1.1.5 root 3420: default:
3421: goto die;
1.1.1.6 root 3422: }
1.1.1.5 root 3423: break;
3424: case 10:
3425: switch (sel) {
3426: case 0:
1.1.1.8 root 3427: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3428: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3429: rn = "EntryHi";
3430: break;
1.1.1.5 root 3431: default:
3432: goto die;
1.1.1.6 root 3433: }
1.1.1.5 root 3434: break;
3435: case 11:
3436: switch (sel) {
3437: case 0:
1.1.1.8 root 3438: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
1.1.1.6 root 3439: rn = "Compare";
3440: break;
3441: /* 6,7 are implementation dependent */
1.1.1.5 root 3442: default:
3443: goto die;
1.1.1.6 root 3444: }
1.1.1.5 root 3445: break;
3446: case 12:
3447: switch (sel) {
3448: case 0:
1.1.1.8 root 3449: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
1.1.1.6 root 3450: rn = "Status";
3451: break;
3452: case 1:
3453: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3454: gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
1.1.1.6 root 3455: rn = "IntCtl";
3456: break;
3457: case 2:
3458: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3459: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
1.1.1.6 root 3460: rn = "SRSCtl";
3461: break;
1.1.1.5 root 3462: case 3:
1.1.1.6 root 3463: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3464: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 3465: rn = "SRSMap";
3466: break;
1.1.1.5 root 3467: default:
3468: goto die;
3469: }
3470: break;
3471: case 13:
3472: switch (sel) {
3473: case 0:
1.1.1.8 root 3474: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
1.1.1.6 root 3475: rn = "Cause";
3476: break;
1.1.1.5 root 3477: default:
3478: goto die;
3479: }
3480: break;
3481: case 14:
3482: switch (sel) {
3483: case 0:
1.1.1.8 root 3484: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3485: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3486: rn = "EPC";
3487: break;
1.1.1.5 root 3488: default:
3489: goto die;
1.1.1.6 root 3490: }
1.1.1.5 root 3491: break;
3492: case 15:
3493: switch (sel) {
3494: case 0:
1.1.1.8 root 3495: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
1.1.1.6 root 3496: rn = "PRid";
3497: break;
3498: case 1:
3499: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3500: gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
1.1.1.6 root 3501: rn = "EBase";
3502: break;
1.1.1.5 root 3503: default:
3504: goto die;
3505: }
3506: break;
3507: case 16:
3508: switch (sel) {
3509: case 0:
1.1.1.8 root 3510: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
1.1.1.5 root 3511: rn = "Config";
3512: break;
3513: case 1:
1.1.1.8 root 3514: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
1.1.1.5 root 3515: rn = "Config1";
3516: break;
3517: case 2:
1.1.1.8 root 3518: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
1.1.1.5 root 3519: rn = "Config2";
3520: break;
3521: case 3:
1.1.1.8 root 3522: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
1.1.1.5 root 3523: rn = "Config3";
3524: break;
1.1.1.6 root 3525: /* 4,5 are reserved */
3526: /* 6,7 are implementation dependent */
3527: case 6:
1.1.1.8 root 3528: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
1.1.1.6 root 3529: rn = "Config6";
3530: break;
3531: case 7:
1.1.1.8 root 3532: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
1.1.1.6 root 3533: rn = "Config7";
3534: break;
1.1.1.5 root 3535: default:
3536: goto die;
1.1 root 3537: }
1.1.1.4 root 3538: break;
1.1.1.5 root 3539: case 17:
3540: switch (sel) {
3541: case 0:
1.1.1.8 root 3542: gen_helper_mfc0_lladdr(arg);
1.1.1.6 root 3543: rn = "LLAddr";
3544: break;
1.1.1.5 root 3545: default:
3546: goto die;
3547: }
1.1.1.4 root 3548: break;
1.1.1.5 root 3549: case 18:
3550: switch (sel) {
1.1.1.6 root 3551: case 0 ... 7:
1.1.1.8 root 3552: gen_helper_1i(mfc0_watchlo, arg, sel);
1.1.1.6 root 3553: rn = "WatchLo";
3554: break;
1.1.1.5 root 3555: default:
3556: goto die;
3557: }
1.1.1.4 root 3558: break;
1.1.1.5 root 3559: case 19:
3560: switch (sel) {
1.1.1.6 root 3561: case 0 ...7:
1.1.1.8 root 3562: gen_helper_1i(mfc0_watchhi, arg, sel);
1.1.1.6 root 3563: rn = "WatchHi";
3564: break;
1.1.1.5 root 3565: default:
3566: goto die;
3567: }
1.1.1.4 root 3568: break;
1.1.1.5 root 3569: case 20:
3570: switch (sel) {
3571: case 0:
1.1.1.6 root 3572: #if defined(TARGET_MIPS64)
3573: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 3574: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3575: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3576: rn = "XContext";
3577: break;
3578: #endif
1.1.1.5 root 3579: default:
3580: goto die;
1.1.1.4 root 3581: }
3582: break;
1.1.1.5 root 3583: case 21:
3584: /* Officially reserved, but sel 0 is used for R1x000 framemask */
3585: switch (sel) {
3586: case 0:
1.1.1.8 root 3587: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
1.1.1.6 root 3588: rn = "Framemask";
3589: break;
1.1.1.5 root 3590: default:
3591: goto die;
1.1.1.4 root 3592: }
3593: break;
1.1.1.5 root 3594: case 22:
1.1.1.8 root 3595: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 3596: rn = "'Diagnostic"; /* implementation dependent */
3597: break;
1.1.1.5 root 3598: case 23:
3599: switch (sel) {
3600: case 0:
1.1.1.8 root 3601: gen_helper_mfc0_debug(arg); /* EJTAG support */
1.1.1.6 root 3602: rn = "Debug";
3603: break;
3604: case 1:
1.1.1.8 root 3605: // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 3606: rn = "TraceControl";
3607: // break;
3608: case 2:
1.1.1.8 root 3609: // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 3610: rn = "TraceControl2";
3611: // break;
1.1.1.5 root 3612: case 3:
1.1.1.8 root 3613: // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 3614: rn = "UserTraceData";
3615: // break;
1.1.1.5 root 3616: case 4:
1.1.1.8 root 3617: // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 3618: rn = "TraceBPC";
3619: // break;
1.1.1.5 root 3620: default:
3621: goto die;
1.1.1.4 root 3622: }
1.1.1.5 root 3623: break;
3624: case 24:
3625: switch (sel) {
3626: case 0:
1.1.1.7 root 3627: /* EJTAG support */
1.1.1.8 root 3628: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3629: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3630: rn = "DEPC";
3631: break;
1.1.1.5 root 3632: default:
3633: goto die;
3634: }
3635: break;
3636: case 25:
3637: switch (sel) {
3638: case 0:
1.1.1.8 root 3639: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
1.1.1.6 root 3640: rn = "Performance0";
1.1.1.5 root 3641: break;
3642: case 1:
1.1.1.8 root 3643: // gen_helper_mfc0_performance1(arg);
1.1.1.6 root 3644: rn = "Performance1";
3645: // break;
1.1.1.5 root 3646: case 2:
1.1.1.8 root 3647: // gen_helper_mfc0_performance2(arg);
1.1.1.6 root 3648: rn = "Performance2";
3649: // break;
1.1.1.5 root 3650: case 3:
1.1.1.8 root 3651: // gen_helper_mfc0_performance3(arg);
1.1.1.6 root 3652: rn = "Performance3";
3653: // break;
1.1.1.5 root 3654: case 4:
1.1.1.8 root 3655: // gen_helper_mfc0_performance4(arg);
1.1.1.6 root 3656: rn = "Performance4";
3657: // break;
1.1.1.5 root 3658: case 5:
1.1.1.8 root 3659: // gen_helper_mfc0_performance5(arg);
1.1.1.6 root 3660: rn = "Performance5";
3661: // break;
1.1.1.5 root 3662: case 6:
1.1.1.8 root 3663: // gen_helper_mfc0_performance6(arg);
1.1.1.6 root 3664: rn = "Performance6";
3665: // break;
1.1.1.5 root 3666: case 7:
1.1.1.8 root 3667: // gen_helper_mfc0_performance7(arg);
1.1.1.6 root 3668: rn = "Performance7";
3669: // break;
1.1.1.5 root 3670: default:
3671: goto die;
3672: }
3673: break;
3674: case 26:
1.1.1.8 root 3675: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.7 root 3676: rn = "ECC";
3677: break;
1.1.1.5 root 3678: case 27:
3679: switch (sel) {
3680: case 0 ... 3:
1.1.1.8 root 3681: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 3682: rn = "CacheErr";
3683: break;
1.1.1.5 root 3684: default:
3685: goto die;
3686: }
3687: break;
3688: case 28:
3689: switch (sel) {
3690: case 0:
3691: case 2:
3692: case 4:
3693: case 6:
1.1.1.8 root 3694: gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
1.1.1.5 root 3695: rn = "TagLo";
3696: break;
3697: case 1:
3698: case 3:
3699: case 5:
3700: case 7:
1.1.1.8 root 3701: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
1.1.1.5 root 3702: rn = "DataLo";
3703: break;
3704: default:
3705: goto die;
3706: }
3707: break;
3708: case 29:
3709: switch (sel) {
3710: case 0:
3711: case 2:
3712: case 4:
3713: case 6:
1.1.1.8 root 3714: gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
1.1.1.5 root 3715: rn = "TagHi";
3716: break;
3717: case 1:
3718: case 3:
3719: case 5:
3720: case 7:
1.1.1.8 root 3721: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
1.1.1.5 root 3722: rn = "DataHi";
3723: break;
3724: default:
3725: goto die;
3726: }
3727: break;
3728: case 30:
3729: switch (sel) {
3730: case 0:
1.1.1.8 root 3731: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3732: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3733: rn = "ErrorEPC";
3734: break;
1.1.1.5 root 3735: default:
3736: goto die;
3737: }
3738: break;
3739: case 31:
3740: switch (sel) {
3741: case 0:
1.1.1.7 root 3742: /* EJTAG support */
1.1.1.8 root 3743: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 3744: rn = "DESAVE";
3745: break;
1.1.1.5 root 3746: default:
3747: goto die;
3748: }
3749: break;
3750: default:
3751: goto die;
3752: }
1.1.1.13! root 3753: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 3754: LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 3755: return;
3756:
3757: die:
1.1.1.7 root 3758: LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 3759: generate_exception(ctx, EXCP_RI);
3760: }
3761:
1.1.1.8 root 3762: static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 3763: {
3764: const char *rn = "invalid";
3765:
1.1.1.6 root 3766: if (sel != 0)
3767: check_insn(env, ctx, ISA_MIPS32);
3768:
1.1.1.7 root 3769: if (use_icount)
3770: gen_io_start();
3771:
1.1.1.5 root 3772: switch (reg) {
3773: case 0:
3774: switch (sel) {
3775: case 0:
1.1.1.8 root 3776: gen_helper_mtc0_index(arg);
1.1.1.5 root 3777: rn = "Index";
3778: break;
3779: case 1:
1.1.1.6 root 3780: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3781: gen_helper_mtc0_mvpcontrol(arg);
1.1.1.5 root 3782: rn = "MVPControl";
1.1.1.6 root 3783: break;
1.1.1.5 root 3784: case 2:
1.1.1.6 root 3785: check_insn(env, ctx, ASE_MT);
3786: /* ignored */
1.1.1.5 root 3787: rn = "MVPConf0";
1.1.1.6 root 3788: break;
1.1.1.5 root 3789: case 3:
1.1.1.6 root 3790: check_insn(env, ctx, ASE_MT);
3791: /* ignored */
1.1.1.5 root 3792: rn = "MVPConf1";
1.1.1.6 root 3793: break;
1.1.1.5 root 3794: default:
3795: goto die;
3796: }
3797: break;
3798: case 1:
3799: switch (sel) {
3800: case 0:
1.1.1.6 root 3801: /* ignored */
1.1.1.5 root 3802: rn = "Random";
1.1.1.6 root 3803: break;
1.1.1.5 root 3804: case 1:
1.1.1.6 root 3805: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3806: gen_helper_mtc0_vpecontrol(arg);
1.1.1.5 root 3807: rn = "VPEControl";
1.1.1.6 root 3808: break;
1.1.1.5 root 3809: case 2:
1.1.1.6 root 3810: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3811: gen_helper_mtc0_vpeconf0(arg);
1.1.1.5 root 3812: rn = "VPEConf0";
1.1.1.6 root 3813: break;
1.1.1.5 root 3814: case 3:
1.1.1.6 root 3815: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3816: gen_helper_mtc0_vpeconf1(arg);
1.1.1.5 root 3817: rn = "VPEConf1";
1.1.1.6 root 3818: break;
1.1.1.5 root 3819: case 4:
1.1.1.6 root 3820: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3821: gen_helper_mtc0_yqmask(arg);
1.1.1.5 root 3822: rn = "YQMask";
1.1.1.6 root 3823: break;
1.1.1.5 root 3824: case 5:
1.1.1.6 root 3825: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3826: gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 3827: rn = "VPESchedule";
1.1.1.6 root 3828: break;
1.1.1.5 root 3829: case 6:
1.1.1.6 root 3830: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3831: gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 3832: rn = "VPEScheFBack";
1.1.1.6 root 3833: break;
1.1.1.5 root 3834: case 7:
1.1.1.6 root 3835: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3836: gen_helper_mtc0_vpeopt(arg);
1.1.1.5 root 3837: rn = "VPEOpt";
1.1.1.6 root 3838: break;
1.1.1.5 root 3839: default:
3840: goto die;
3841: }
3842: break;
3843: case 2:
3844: switch (sel) {
3845: case 0:
1.1.1.8 root 3846: gen_helper_mtc0_entrylo0(arg);
1.1.1.6 root 3847: rn = "EntryLo0";
3848: break;
3849: case 1:
3850: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3851: gen_helper_mtc0_tcstatus(arg);
1.1.1.6 root 3852: rn = "TCStatus";
3853: break;
3854: case 2:
3855: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3856: gen_helper_mtc0_tcbind(arg);
1.1.1.6 root 3857: rn = "TCBind";
3858: break;
1.1.1.5 root 3859: case 3:
1.1.1.6 root 3860: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3861: gen_helper_mtc0_tcrestart(arg);
1.1.1.6 root 3862: rn = "TCRestart";
3863: break;
1.1.1.5 root 3864: case 4:
1.1.1.6 root 3865: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3866: gen_helper_mtc0_tchalt(arg);
1.1.1.6 root 3867: rn = "TCHalt";
3868: break;
1.1.1.5 root 3869: case 5:
1.1.1.6 root 3870: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3871: gen_helper_mtc0_tccontext(arg);
1.1.1.6 root 3872: rn = "TCContext";
3873: break;
1.1.1.5 root 3874: case 6:
1.1.1.6 root 3875: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3876: gen_helper_mtc0_tcschedule(arg);
1.1.1.6 root 3877: rn = "TCSchedule";
3878: break;
1.1.1.5 root 3879: case 7:
1.1.1.6 root 3880: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3881: gen_helper_mtc0_tcschefback(arg);
1.1.1.6 root 3882: rn = "TCScheFBack";
3883: break;
1.1.1.5 root 3884: default:
3885: goto die;
3886: }
3887: break;
3888: case 3:
3889: switch (sel) {
3890: case 0:
1.1.1.8 root 3891: gen_helper_mtc0_entrylo1(arg);
1.1.1.6 root 3892: rn = "EntryLo1";
3893: break;
1.1.1.5 root 3894: default:
3895: goto die;
1.1.1.6 root 3896: }
1.1.1.5 root 3897: break;
3898: case 4:
3899: switch (sel) {
3900: case 0:
1.1.1.8 root 3901: gen_helper_mtc0_context(arg);
1.1.1.6 root 3902: rn = "Context";
3903: break;
3904: case 1:
1.1.1.8 root 3905: // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 3906: rn = "ContextConfig";
3907: // break;
1.1.1.5 root 3908: default:
3909: goto die;
1.1.1.6 root 3910: }
1.1.1.5 root 3911: break;
3912: case 5:
3913: switch (sel) {
3914: case 0:
1.1.1.8 root 3915: gen_helper_mtc0_pagemask(arg);
1.1.1.6 root 3916: rn = "PageMask";
3917: break;
3918: case 1:
3919: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3920: gen_helper_mtc0_pagegrain(arg);
1.1.1.6 root 3921: rn = "PageGrain";
3922: break;
1.1.1.5 root 3923: default:
3924: goto die;
1.1.1.6 root 3925: }
1.1.1.5 root 3926: break;
3927: case 6:
3928: switch (sel) {
3929: case 0:
1.1.1.8 root 3930: gen_helper_mtc0_wired(arg);
1.1.1.6 root 3931: rn = "Wired";
3932: break;
3933: case 1:
3934: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3935: gen_helper_mtc0_srsconf0(arg);
1.1.1.6 root 3936: rn = "SRSConf0";
3937: break;
3938: case 2:
3939: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3940: gen_helper_mtc0_srsconf1(arg);
1.1.1.6 root 3941: rn = "SRSConf1";
3942: break;
1.1.1.5 root 3943: case 3:
1.1.1.6 root 3944: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3945: gen_helper_mtc0_srsconf2(arg);
1.1.1.6 root 3946: rn = "SRSConf2";
3947: break;
1.1.1.5 root 3948: case 4:
1.1.1.6 root 3949: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3950: gen_helper_mtc0_srsconf3(arg);
1.1.1.6 root 3951: rn = "SRSConf3";
3952: break;
1.1.1.5 root 3953: case 5:
1.1.1.6 root 3954: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3955: gen_helper_mtc0_srsconf4(arg);
1.1.1.6 root 3956: rn = "SRSConf4";
3957: break;
1.1.1.5 root 3958: default:
3959: goto die;
1.1.1.6 root 3960: }
1.1.1.5 root 3961: break;
3962: case 7:
3963: switch (sel) {
3964: case 0:
1.1.1.6 root 3965: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3966: gen_helper_mtc0_hwrena(arg);
1.1.1.6 root 3967: rn = "HWREna";
3968: break;
1.1.1.5 root 3969: default:
3970: goto die;
1.1.1.6 root 3971: }
1.1.1.5 root 3972: break;
3973: case 8:
3974: /* ignored */
1.1.1.7 root 3975: rn = "BadVAddr";
1.1.1.5 root 3976: break;
3977: case 9:
3978: switch (sel) {
3979: case 0:
1.1.1.8 root 3980: gen_helper_mtc0_count(arg);
1.1.1.6 root 3981: rn = "Count";
3982: break;
3983: /* 6,7 are implementation dependent */
1.1.1.5 root 3984: default:
3985: goto die;
1.1.1.6 root 3986: }
1.1.1.5 root 3987: break;
3988: case 10:
3989: switch (sel) {
3990: case 0:
1.1.1.8 root 3991: gen_helper_mtc0_entryhi(arg);
1.1.1.6 root 3992: rn = "EntryHi";
3993: break;
1.1.1.5 root 3994: default:
3995: goto die;
1.1.1.6 root 3996: }
1.1.1.5 root 3997: break;
3998: case 11:
3999: switch (sel) {
4000: case 0:
1.1.1.8 root 4001: gen_helper_mtc0_compare(arg);
1.1.1.6 root 4002: rn = "Compare";
4003: break;
4004: /* 6,7 are implementation dependent */
1.1.1.5 root 4005: default:
4006: goto die;
1.1.1.6 root 4007: }
1.1.1.5 root 4008: break;
4009: case 12:
4010: switch (sel) {
4011: case 0:
1.1.1.8 root 4012: save_cpu_state(ctx, 1);
4013: gen_helper_mtc0_status(arg);
1.1.1.6 root 4014: /* BS_STOP isn't good enough here, hflags may have changed. */
4015: gen_save_pc(ctx->pc + 4);
4016: ctx->bstate = BS_EXCP;
4017: rn = "Status";
4018: break;
4019: case 1:
4020: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4021: gen_helper_mtc0_intctl(arg);
1.1.1.6 root 4022: /* Stop translation as we may have switched the execution mode */
4023: ctx->bstate = BS_STOP;
4024: rn = "IntCtl";
4025: break;
4026: case 2:
4027: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4028: gen_helper_mtc0_srsctl(arg);
1.1.1.6 root 4029: /* Stop translation as we may have switched the execution mode */
4030: ctx->bstate = BS_STOP;
4031: rn = "SRSCtl";
4032: break;
1.1.1.5 root 4033: case 3:
1.1.1.6 root 4034: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4035: gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 4036: /* Stop translation as we may have switched the execution mode */
4037: ctx->bstate = BS_STOP;
4038: rn = "SRSMap";
4039: break;
1.1.1.5 root 4040: default:
4041: goto die;
1.1.1.6 root 4042: }
1.1.1.5 root 4043: break;
4044: case 13:
4045: switch (sel) {
4046: case 0:
1.1.1.8 root 4047: save_cpu_state(ctx, 1);
4048: gen_helper_mtc0_cause(arg);
1.1.1.6 root 4049: rn = "Cause";
4050: break;
1.1.1.5 root 4051: default:
4052: goto die;
1.1.1.6 root 4053: }
1.1.1.5 root 4054: break;
4055: case 14:
4056: switch (sel) {
4057: case 0:
1.1.1.8 root 4058: gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 4059: rn = "EPC";
4060: break;
1.1.1.5 root 4061: default:
4062: goto die;
1.1.1.6 root 4063: }
1.1.1.5 root 4064: break;
4065: case 15:
4066: switch (sel) {
4067: case 0:
1.1.1.6 root 4068: /* ignored */
4069: rn = "PRid";
4070: break;
4071: case 1:
4072: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4073: gen_helper_mtc0_ebase(arg);
1.1.1.6 root 4074: rn = "EBase";
4075: break;
1.1.1.5 root 4076: default:
4077: goto die;
1.1.1.6 root 4078: }
1.1.1.5 root 4079: break;
4080: case 16:
4081: switch (sel) {
4082: case 0:
1.1.1.8 root 4083: gen_helper_mtc0_config0(arg);
1.1.1.5 root 4084: rn = "Config";
1.1.1.6 root 4085: /* Stop translation as we may have switched the execution mode */
4086: ctx->bstate = BS_STOP;
1.1.1.5 root 4087: break;
4088: case 1:
1.1.1.6 root 4089: /* ignored, read only */
1.1.1.5 root 4090: rn = "Config1";
4091: break;
4092: case 2:
1.1.1.8 root 4093: gen_helper_mtc0_config2(arg);
1.1.1.5 root 4094: rn = "Config2";
1.1.1.6 root 4095: /* Stop translation as we may have switched the execution mode */
4096: ctx->bstate = BS_STOP;
1.1.1.5 root 4097: break;
4098: case 3:
1.1.1.6 root 4099: /* ignored, read only */
1.1.1.5 root 4100: rn = "Config3";
4101: break;
1.1.1.6 root 4102: /* 4,5 are reserved */
4103: /* 6,7 are implementation dependent */
4104: case 6:
4105: /* ignored */
4106: rn = "Config6";
4107: break;
4108: case 7:
4109: /* ignored */
4110: rn = "Config7";
4111: break;
1.1.1.5 root 4112: default:
4113: rn = "Invalid config selector";
4114: goto die;
4115: }
4116: break;
4117: case 17:
4118: switch (sel) {
4119: case 0:
1.1.1.9 root 4120: gen_helper_mtc0_lladdr(arg);
1.1.1.6 root 4121: rn = "LLAddr";
4122: break;
1.1.1.5 root 4123: default:
4124: goto die;
4125: }
4126: break;
4127: case 18:
4128: switch (sel) {
1.1.1.6 root 4129: case 0 ... 7:
1.1.1.8 root 4130: gen_helper_1i(mtc0_watchlo, arg, sel);
1.1.1.6 root 4131: rn = "WatchLo";
4132: break;
1.1.1.5 root 4133: default:
4134: goto die;
4135: }
4136: break;
4137: case 19:
4138: switch (sel) {
1.1.1.6 root 4139: case 0 ... 7:
1.1.1.8 root 4140: gen_helper_1i(mtc0_watchhi, arg, sel);
1.1.1.6 root 4141: rn = "WatchHi";
4142: break;
1.1.1.5 root 4143: default:
4144: goto die;
4145: }
4146: break;
4147: case 20:
4148: switch (sel) {
4149: case 0:
1.1.1.6 root 4150: #if defined(TARGET_MIPS64)
4151: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 4152: gen_helper_mtc0_xcontext(arg);
1.1.1.6 root 4153: rn = "XContext";
4154: break;
4155: #endif
1.1.1.5 root 4156: default:
4157: goto die;
4158: }
4159: break;
4160: case 21:
4161: /* Officially reserved, but sel 0 is used for R1x000 framemask */
4162: switch (sel) {
4163: case 0:
1.1.1.8 root 4164: gen_helper_mtc0_framemask(arg);
1.1.1.6 root 4165: rn = "Framemask";
4166: break;
1.1.1.5 root 4167: default:
4168: goto die;
4169: }
4170: break;
4171: case 22:
4172: /* ignored */
4173: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 root 4174: break;
1.1.1.5 root 4175: case 23:
4176: switch (sel) {
4177: case 0:
1.1.1.8 root 4178: gen_helper_mtc0_debug(arg); /* EJTAG support */
1.1.1.6 root 4179: /* BS_STOP isn't good enough here, hflags may have changed. */
4180: gen_save_pc(ctx->pc + 4);
4181: ctx->bstate = BS_EXCP;
4182: rn = "Debug";
4183: break;
4184: case 1:
1.1.1.8 root 4185: // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 4186: rn = "TraceControl";
4187: /* Stop translation as we may have switched the execution mode */
4188: ctx->bstate = BS_STOP;
4189: // break;
4190: case 2:
1.1.1.8 root 4191: // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 4192: rn = "TraceControl2";
4193: /* Stop translation as we may have switched the execution mode */
4194: ctx->bstate = BS_STOP;
4195: // break;
4196: case 3:
4197: /* Stop translation as we may have switched the execution mode */
4198: ctx->bstate = BS_STOP;
1.1.1.8 root 4199: // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 4200: rn = "UserTraceData";
4201: /* Stop translation as we may have switched the execution mode */
4202: ctx->bstate = BS_STOP;
4203: // break;
1.1.1.5 root 4204: case 4:
1.1.1.8 root 4205: // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 4206: /* Stop translation as we may have switched the execution mode */
4207: ctx->bstate = BS_STOP;
4208: rn = "TraceBPC";
4209: // break;
1.1.1.5 root 4210: default:
4211: goto die;
4212: }
4213: break;
4214: case 24:
4215: switch (sel) {
4216: case 0:
1.1.1.7 root 4217: /* EJTAG support */
1.1.1.8 root 4218: gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 4219: rn = "DEPC";
4220: break;
1.1.1.5 root 4221: default:
4222: goto die;
4223: }
4224: break;
4225: case 25:
4226: switch (sel) {
4227: case 0:
1.1.1.8 root 4228: gen_helper_mtc0_performance0(arg);
1.1.1.6 root 4229: rn = "Performance0";
4230: break;
4231: case 1:
1.1.1.8 root 4232: // gen_helper_mtc0_performance1(arg);
1.1.1.6 root 4233: rn = "Performance1";
4234: // break;
4235: case 2:
1.1.1.8 root 4236: // gen_helper_mtc0_performance2(arg);
1.1.1.6 root 4237: rn = "Performance2";
4238: // break;
4239: case 3:
1.1.1.8 root 4240: // gen_helper_mtc0_performance3(arg);
1.1.1.6 root 4241: rn = "Performance3";
4242: // break;
1.1.1.5 root 4243: case 4:
1.1.1.8 root 4244: // gen_helper_mtc0_performance4(arg);
1.1.1.6 root 4245: rn = "Performance4";
4246: // break;
1.1.1.5 root 4247: case 5:
1.1.1.8 root 4248: // gen_helper_mtc0_performance5(arg);
1.1.1.6 root 4249: rn = "Performance5";
4250: // break;
1.1.1.5 root 4251: case 6:
1.1.1.8 root 4252: // gen_helper_mtc0_performance6(arg);
1.1.1.6 root 4253: rn = "Performance6";
4254: // break;
1.1.1.5 root 4255: case 7:
1.1.1.8 root 4256: // gen_helper_mtc0_performance7(arg);
1.1.1.6 root 4257: rn = "Performance7";
4258: // break;
1.1.1.5 root 4259: default:
4260: goto die;
4261: }
4262: break;
4263: case 26:
1.1.1.6 root 4264: /* ignored */
1.1.1.5 root 4265: rn = "ECC";
1.1.1.6 root 4266: break;
1.1.1.5 root 4267: case 27:
4268: switch (sel) {
4269: case 0 ... 3:
1.1.1.6 root 4270: /* ignored */
4271: rn = "CacheErr";
4272: break;
1.1.1.5 root 4273: default:
4274: goto die;
4275: }
4276: break;
4277: case 28:
4278: switch (sel) {
4279: case 0:
4280: case 2:
4281: case 4:
4282: case 6:
1.1.1.8 root 4283: gen_helper_mtc0_taglo(arg);
1.1.1.5 root 4284: rn = "TagLo";
4285: break;
4286: case 1:
4287: case 3:
4288: case 5:
4289: case 7:
1.1.1.8 root 4290: gen_helper_mtc0_datalo(arg);
1.1.1.5 root 4291: rn = "DataLo";
4292: break;
4293: default:
4294: goto die;
4295: }
4296: break;
4297: case 29:
4298: switch (sel) {
4299: case 0:
4300: case 2:
4301: case 4:
4302: case 6:
1.1.1.8 root 4303: gen_helper_mtc0_taghi(arg);
1.1.1.5 root 4304: rn = "TagHi";
4305: break;
4306: case 1:
4307: case 3:
4308: case 5:
4309: case 7:
1.1.1.8 root 4310: gen_helper_mtc0_datahi(arg);
1.1.1.5 root 4311: rn = "DataHi";
4312: break;
4313: default:
4314: rn = "invalid sel";
4315: goto die;
4316: }
4317: break;
4318: case 30:
4319: switch (sel) {
4320: case 0:
1.1.1.8 root 4321: gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 4322: rn = "ErrorEPC";
4323: break;
1.1.1.5 root 4324: default:
4325: goto die;
4326: }
4327: break;
4328: case 31:
4329: switch (sel) {
4330: case 0:
1.1.1.7 root 4331: /* EJTAG support */
1.1.1.8 root 4332: gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 4333: rn = "DESAVE";
4334: break;
1.1.1.5 root 4335: default:
4336: goto die;
4337: }
1.1.1.6 root 4338: /* Stop translation as we may have switched the execution mode */
4339: ctx->bstate = BS_STOP;
1.1.1.5 root 4340: break;
4341: default:
4342: goto die;
4343: }
1.1.1.13! root 4344: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 4345: LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4346: /* For simplicity assume that all writes can cause interrupts. */
4347: if (use_icount) {
4348: gen_io_end();
4349: ctx->bstate = BS_STOP;
1.1.1.5 root 4350: }
4351: return;
4352:
4353: die:
1.1.1.7 root 4354: LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4355: generate_exception(ctx, EXCP_RI);
4356: }
4357:
1.1.1.6 root 4358: #if defined(TARGET_MIPS64)
1.1.1.8 root 4359: static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 4360: {
4361: const char *rn = "invalid";
4362:
1.1.1.6 root 4363: if (sel != 0)
4364: check_insn(env, ctx, ISA_MIPS64);
4365:
1.1.1.5 root 4366: switch (reg) {
4367: case 0:
4368: switch (sel) {
4369: case 0:
1.1.1.8 root 4370: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
1.1.1.5 root 4371: rn = "Index";
4372: break;
4373: case 1:
1.1.1.6 root 4374: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4375: gen_helper_mfc0_mvpcontrol(arg);
1.1.1.5 root 4376: rn = "MVPControl";
1.1.1.6 root 4377: break;
1.1.1.5 root 4378: case 2:
1.1.1.6 root 4379: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4380: gen_helper_mfc0_mvpconf0(arg);
1.1.1.5 root 4381: rn = "MVPConf0";
1.1.1.6 root 4382: break;
1.1.1.5 root 4383: case 3:
1.1.1.6 root 4384: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4385: gen_helper_mfc0_mvpconf1(arg);
1.1.1.5 root 4386: rn = "MVPConf1";
1.1.1.6 root 4387: break;
1.1.1.5 root 4388: default:
4389: goto die;
4390: }
4391: break;
4392: case 1:
4393: switch (sel) {
4394: case 0:
1.1.1.8 root 4395: gen_helper_mfc0_random(arg);
1.1.1.5 root 4396: rn = "Random";
1.1.1.6 root 4397: break;
1.1.1.5 root 4398: case 1:
1.1.1.6 root 4399: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4400: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
1.1.1.5 root 4401: rn = "VPEControl";
1.1.1.6 root 4402: break;
1.1.1.5 root 4403: case 2:
1.1.1.6 root 4404: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4405: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
1.1.1.5 root 4406: rn = "VPEConf0";
1.1.1.6 root 4407: break;
1.1.1.5 root 4408: case 3:
1.1.1.6 root 4409: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4410: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
1.1.1.5 root 4411: rn = "VPEConf1";
1.1.1.6 root 4412: break;
1.1.1.5 root 4413: case 4:
1.1.1.6 root 4414: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4415: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
1.1.1.5 root 4416: rn = "YQMask";
1.1.1.6 root 4417: break;
1.1.1.5 root 4418: case 5:
1.1.1.6 root 4419: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4420: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 4421: rn = "VPESchedule";
1.1.1.6 root 4422: break;
1.1.1.5 root 4423: case 6:
1.1.1.6 root 4424: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4425: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 4426: rn = "VPEScheFBack";
1.1.1.6 root 4427: break;
1.1.1.5 root 4428: case 7:
1.1.1.6 root 4429: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4430: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
1.1.1.5 root 4431: rn = "VPEOpt";
1.1.1.6 root 4432: break;
1.1.1.5 root 4433: default:
4434: goto die;
4435: }
4436: break;
4437: case 2:
4438: switch (sel) {
4439: case 0:
1.1.1.8 root 4440: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
1.1.1.6 root 4441: rn = "EntryLo0";
4442: break;
4443: case 1:
4444: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4445: gen_helper_mfc0_tcstatus(arg);
1.1.1.6 root 4446: rn = "TCStatus";
4447: break;
4448: case 2:
4449: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4450: gen_helper_mfc0_tcbind(arg);
1.1.1.6 root 4451: rn = "TCBind";
4452: break;
1.1.1.5 root 4453: case 3:
1.1.1.6 root 4454: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4455: gen_helper_dmfc0_tcrestart(arg);
1.1.1.6 root 4456: rn = "TCRestart";
4457: break;
1.1.1.5 root 4458: case 4:
1.1.1.6 root 4459: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4460: gen_helper_dmfc0_tchalt(arg);
1.1.1.6 root 4461: rn = "TCHalt";
4462: break;
1.1.1.5 root 4463: case 5:
1.1.1.6 root 4464: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4465: gen_helper_dmfc0_tccontext(arg);
1.1.1.6 root 4466: rn = "TCContext";
4467: break;
1.1.1.5 root 4468: case 6:
1.1.1.6 root 4469: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4470: gen_helper_dmfc0_tcschedule(arg);
1.1.1.6 root 4471: rn = "TCSchedule";
4472: break;
1.1.1.5 root 4473: case 7:
1.1.1.6 root 4474: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4475: gen_helper_dmfc0_tcschefback(arg);
1.1.1.6 root 4476: rn = "TCScheFBack";
4477: break;
1.1.1.5 root 4478: default:
4479: goto die;
4480: }
4481: break;
4482: case 3:
4483: switch (sel) {
4484: case 0:
1.1.1.8 root 4485: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
1.1.1.6 root 4486: rn = "EntryLo1";
4487: break;
1.1.1.5 root 4488: default:
4489: goto die;
1.1.1.6 root 4490: }
1.1.1.5 root 4491: break;
4492: case 4:
4493: switch (sel) {
4494: case 0:
1.1.1.8 root 4495: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
1.1.1.6 root 4496: rn = "Context";
4497: break;
4498: case 1:
1.1.1.8 root 4499: // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 4500: rn = "ContextConfig";
4501: // break;
1.1.1.5 root 4502: default:
4503: goto die;
1.1.1.6 root 4504: }
1.1.1.5 root 4505: break;
4506: case 5:
4507: switch (sel) {
4508: case 0:
1.1.1.8 root 4509: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
1.1.1.6 root 4510: rn = "PageMask";
4511: break;
4512: case 1:
4513: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4514: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
1.1.1.6 root 4515: rn = "PageGrain";
4516: break;
1.1.1.5 root 4517: default:
4518: goto die;
1.1.1.6 root 4519: }
1.1.1.5 root 4520: break;
4521: case 6:
4522: switch (sel) {
4523: case 0:
1.1.1.8 root 4524: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
1.1.1.6 root 4525: rn = "Wired";
4526: break;
4527: case 1:
4528: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4529: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
1.1.1.6 root 4530: rn = "SRSConf0";
4531: break;
4532: case 2:
4533: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4534: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
1.1.1.6 root 4535: rn = "SRSConf1";
4536: break;
1.1.1.5 root 4537: case 3:
1.1.1.6 root 4538: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4539: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
1.1.1.6 root 4540: rn = "SRSConf2";
4541: break;
1.1.1.5 root 4542: case 4:
1.1.1.6 root 4543: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4544: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
1.1.1.6 root 4545: rn = "SRSConf3";
4546: break;
1.1.1.5 root 4547: case 5:
1.1.1.6 root 4548: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4549: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
1.1.1.6 root 4550: rn = "SRSConf4";
4551: break;
1.1.1.5 root 4552: default:
4553: goto die;
1.1.1.6 root 4554: }
1.1.1.5 root 4555: break;
4556: case 7:
4557: switch (sel) {
4558: case 0:
1.1.1.6 root 4559: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4560: gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
1.1.1.6 root 4561: rn = "HWREna";
4562: break;
1.1.1.5 root 4563: default:
4564: goto die;
1.1.1.6 root 4565: }
1.1.1.5 root 4566: break;
4567: case 8:
4568: switch (sel) {
4569: case 0:
1.1.1.8 root 4570: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
1.1.1.7 root 4571: rn = "BadVAddr";
1.1.1.6 root 4572: break;
1.1.1.5 root 4573: default:
4574: goto die;
1.1.1.6 root 4575: }
1.1.1.5 root 4576: break;
4577: case 9:
4578: switch (sel) {
4579: case 0:
1.1.1.7 root 4580: /* Mark as an IO operation because we read the time. */
4581: if (use_icount)
4582: gen_io_start();
1.1.1.8 root 4583: gen_helper_mfc0_count(arg);
1.1.1.7 root 4584: if (use_icount) {
4585: gen_io_end();
4586: }
1.1.1.13! root 4587: /* Break the TB to be able to take timer interrupts immediately
! 4588: after reading count. */
! 4589: ctx->bstate = BS_STOP;
1.1.1.6 root 4590: rn = "Count";
4591: break;
4592: /* 6,7 are implementation dependent */
1.1.1.5 root 4593: default:
4594: goto die;
1.1.1.6 root 4595: }
1.1.1.5 root 4596: break;
4597: case 10:
4598: switch (sel) {
4599: case 0:
1.1.1.8 root 4600: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
1.1.1.6 root 4601: rn = "EntryHi";
4602: break;
1.1.1.5 root 4603: default:
4604: goto die;
1.1.1.6 root 4605: }
1.1.1.5 root 4606: break;
4607: case 11:
4608: switch (sel) {
4609: case 0:
1.1.1.8 root 4610: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
1.1.1.6 root 4611: rn = "Compare";
4612: break;
4613: /* 6,7 are implementation dependent */
1.1.1.5 root 4614: default:
4615: goto die;
1.1.1.6 root 4616: }
1.1.1.5 root 4617: break;
4618: case 12:
4619: switch (sel) {
4620: case 0:
1.1.1.8 root 4621: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
1.1.1.6 root 4622: rn = "Status";
4623: break;
4624: case 1:
4625: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4626: gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
1.1.1.6 root 4627: rn = "IntCtl";
4628: break;
4629: case 2:
4630: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4631: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
1.1.1.6 root 4632: rn = "SRSCtl";
4633: break;
1.1.1.5 root 4634: case 3:
1.1.1.6 root 4635: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4636: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 4637: rn = "SRSMap";
4638: break;
1.1.1.5 root 4639: default:
4640: goto die;
1.1.1.6 root 4641: }
1.1.1.5 root 4642: break;
4643: case 13:
4644: switch (sel) {
4645: case 0:
1.1.1.8 root 4646: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
1.1.1.6 root 4647: rn = "Cause";
4648: break;
1.1.1.5 root 4649: default:
4650: goto die;
1.1.1.6 root 4651: }
1.1.1.5 root 4652: break;
4653: case 14:
4654: switch (sel) {
4655: case 0:
1.1.1.8 root 4656: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 4657: rn = "EPC";
4658: break;
1.1.1.5 root 4659: default:
4660: goto die;
1.1.1.6 root 4661: }
1.1.1.5 root 4662: break;
4663: case 15:
4664: switch (sel) {
4665: case 0:
1.1.1.8 root 4666: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
1.1.1.6 root 4667: rn = "PRid";
4668: break;
4669: case 1:
4670: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4671: gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
1.1.1.6 root 4672: rn = "EBase";
4673: break;
1.1.1.5 root 4674: default:
4675: goto die;
1.1.1.6 root 4676: }
1.1.1.5 root 4677: break;
4678: case 16:
4679: switch (sel) {
4680: case 0:
1.1.1.8 root 4681: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
1.1.1.5 root 4682: rn = "Config";
4683: break;
4684: case 1:
1.1.1.8 root 4685: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
1.1.1.5 root 4686: rn = "Config1";
4687: break;
4688: case 2:
1.1.1.8 root 4689: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
1.1.1.5 root 4690: rn = "Config2";
4691: break;
4692: case 3:
1.1.1.8 root 4693: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
1.1.1.5 root 4694: rn = "Config3";
4695: break;
4696: /* 6,7 are implementation dependent */
1.1.1.7 root 4697: case 6:
1.1.1.8 root 4698: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
1.1.1.7 root 4699: rn = "Config6";
4700: break;
4701: case 7:
1.1.1.8 root 4702: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
1.1.1.7 root 4703: rn = "Config7";
4704: break;
1.1.1.5 root 4705: default:
4706: goto die;
4707: }
4708: break;
4709: case 17:
4710: switch (sel) {
4711: case 0:
1.1.1.8 root 4712: gen_helper_dmfc0_lladdr(arg);
1.1.1.6 root 4713: rn = "LLAddr";
4714: break;
1.1.1.5 root 4715: default:
4716: goto die;
4717: }
4718: break;
4719: case 18:
4720: switch (sel) {
1.1.1.6 root 4721: case 0 ... 7:
1.1.1.8 root 4722: gen_helper_1i(dmfc0_watchlo, arg, sel);
1.1.1.6 root 4723: rn = "WatchLo";
4724: break;
1.1.1.5 root 4725: default:
4726: goto die;
4727: }
4728: break;
4729: case 19:
4730: switch (sel) {
1.1.1.6 root 4731: case 0 ... 7:
1.1.1.8 root 4732: gen_helper_1i(mfc0_watchhi, arg, sel);
1.1.1.6 root 4733: rn = "WatchHi";
4734: break;
1.1.1.5 root 4735: default:
4736: goto die;
4737: }
4738: break;
4739: case 20:
4740: switch (sel) {
4741: case 0:
1.1.1.6 root 4742: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 4743: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
1.1.1.6 root 4744: rn = "XContext";
4745: break;
1.1.1.5 root 4746: default:
4747: goto die;
4748: }
4749: break;
4750: case 21:
4751: /* Officially reserved, but sel 0 is used for R1x000 framemask */
4752: switch (sel) {
4753: case 0:
1.1.1.8 root 4754: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
1.1.1.6 root 4755: rn = "Framemask";
4756: break;
1.1.1.5 root 4757: default:
4758: goto die;
4759: }
4760: break;
4761: case 22:
1.1.1.8 root 4762: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 4763: rn = "'Diagnostic"; /* implementation dependent */
4764: break;
1.1.1.5 root 4765: case 23:
4766: switch (sel) {
4767: case 0:
1.1.1.8 root 4768: gen_helper_mfc0_debug(arg); /* EJTAG support */
1.1.1.6 root 4769: rn = "Debug";
4770: break;
4771: case 1:
1.1.1.8 root 4772: // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 4773: rn = "TraceControl";
4774: // break;
4775: case 2:
1.1.1.8 root 4776: // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 4777: rn = "TraceControl2";
4778: // break;
1.1.1.5 root 4779: case 3:
1.1.1.8 root 4780: // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 4781: rn = "UserTraceData";
4782: // break;
1.1.1.5 root 4783: case 4:
1.1.1.8 root 4784: // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 4785: rn = "TraceBPC";
4786: // break;
1.1.1.5 root 4787: default:
4788: goto die;
4789: }
4790: break;
4791: case 24:
4792: switch (sel) {
4793: case 0:
1.1.1.7 root 4794: /* EJTAG support */
1.1.1.8 root 4795: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 4796: rn = "DEPC";
4797: break;
1.1.1.5 root 4798: default:
4799: goto die;
4800: }
4801: break;
4802: case 25:
4803: switch (sel) {
4804: case 0:
1.1.1.8 root 4805: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
1.1.1.6 root 4806: rn = "Performance0";
1.1.1.5 root 4807: break;
4808: case 1:
1.1.1.8 root 4809: // gen_helper_dmfc0_performance1(arg);
1.1.1.6 root 4810: rn = "Performance1";
4811: // break;
1.1.1.5 root 4812: case 2:
1.1.1.8 root 4813: // gen_helper_dmfc0_performance2(arg);
1.1.1.6 root 4814: rn = "Performance2";
4815: // break;
1.1.1.5 root 4816: case 3:
1.1.1.8 root 4817: // gen_helper_dmfc0_performance3(arg);
1.1.1.6 root 4818: rn = "Performance3";
4819: // break;
1.1.1.5 root 4820: case 4:
1.1.1.8 root 4821: // gen_helper_dmfc0_performance4(arg);
1.1.1.6 root 4822: rn = "Performance4";
4823: // break;
1.1.1.5 root 4824: case 5:
1.1.1.8 root 4825: // gen_helper_dmfc0_performance5(arg);
1.1.1.6 root 4826: rn = "Performance5";
4827: // break;
1.1.1.5 root 4828: case 6:
1.1.1.8 root 4829: // gen_helper_dmfc0_performance6(arg);
1.1.1.6 root 4830: rn = "Performance6";
4831: // break;
1.1.1.5 root 4832: case 7:
1.1.1.8 root 4833: // gen_helper_dmfc0_performance7(arg);
1.1.1.6 root 4834: rn = "Performance7";
4835: // break;
1.1.1.5 root 4836: default:
4837: goto die;
4838: }
4839: break;
4840: case 26:
1.1.1.8 root 4841: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.7 root 4842: rn = "ECC";
4843: break;
1.1.1.5 root 4844: case 27:
4845: switch (sel) {
4846: /* ignored */
4847: case 0 ... 3:
1.1.1.8 root 4848: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 4849: rn = "CacheErr";
4850: break;
1.1.1.5 root 4851: default:
4852: goto die;
4853: }
4854: break;
4855: case 28:
4856: switch (sel) {
4857: case 0:
4858: case 2:
4859: case 4:
4860: case 6:
1.1.1.8 root 4861: gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
1.1.1.5 root 4862: rn = "TagLo";
4863: break;
4864: case 1:
4865: case 3:
4866: case 5:
4867: case 7:
1.1.1.8 root 4868: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
1.1.1.5 root 4869: rn = "DataLo";
4870: break;
4871: default:
4872: goto die;
4873: }
4874: break;
4875: case 29:
4876: switch (sel) {
4877: case 0:
4878: case 2:
4879: case 4:
4880: case 6:
1.1.1.8 root 4881: gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
1.1.1.5 root 4882: rn = "TagHi";
4883: break;
4884: case 1:
4885: case 3:
4886: case 5:
4887: case 7:
1.1.1.8 root 4888: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
1.1.1.5 root 4889: rn = "DataHi";
4890: break;
4891: default:
4892: goto die;
4893: }
4894: break;
4895: case 30:
4896: switch (sel) {
4897: case 0:
1.1.1.8 root 4898: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 4899: rn = "ErrorEPC";
4900: break;
1.1.1.5 root 4901: default:
4902: goto die;
4903: }
4904: break;
4905: case 31:
4906: switch (sel) {
4907: case 0:
1.1.1.7 root 4908: /* EJTAG support */
1.1.1.8 root 4909: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 4910: rn = "DESAVE";
4911: break;
1.1.1.5 root 4912: default:
4913: goto die;
4914: }
4915: break;
4916: default:
1.1.1.6 root 4917: goto die;
1.1.1.5 root 4918: }
1.1.1.13! root 4919: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 4920: LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4921: return;
4922:
4923: die:
1.1.1.7 root 4924: LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4925: generate_exception(ctx, EXCP_RI);
4926: }
4927:
1.1.1.8 root 4928: static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 4929: {
4930: const char *rn = "invalid";
4931:
1.1.1.6 root 4932: if (sel != 0)
4933: check_insn(env, ctx, ISA_MIPS64);
4934:
1.1.1.7 root 4935: if (use_icount)
4936: gen_io_start();
4937:
1.1.1.5 root 4938: switch (reg) {
4939: case 0:
4940: switch (sel) {
4941: case 0:
1.1.1.8 root 4942: gen_helper_mtc0_index(arg);
1.1.1.5 root 4943: rn = "Index";
4944: break;
4945: case 1:
1.1.1.6 root 4946: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4947: gen_helper_mtc0_mvpcontrol(arg);
1.1.1.5 root 4948: rn = "MVPControl";
1.1.1.6 root 4949: break;
1.1.1.5 root 4950: case 2:
1.1.1.6 root 4951: check_insn(env, ctx, ASE_MT);
4952: /* ignored */
1.1.1.5 root 4953: rn = "MVPConf0";
1.1.1.6 root 4954: break;
1.1.1.5 root 4955: case 3:
1.1.1.6 root 4956: check_insn(env, ctx, ASE_MT);
4957: /* ignored */
1.1.1.5 root 4958: rn = "MVPConf1";
1.1.1.6 root 4959: break;
1.1.1.5 root 4960: default:
4961: goto die;
4962: }
4963: break;
4964: case 1:
4965: switch (sel) {
4966: case 0:
1.1.1.6 root 4967: /* ignored */
1.1.1.5 root 4968: rn = "Random";
1.1.1.6 root 4969: break;
1.1.1.5 root 4970: case 1:
1.1.1.6 root 4971: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4972: gen_helper_mtc0_vpecontrol(arg);
1.1.1.5 root 4973: rn = "VPEControl";
1.1.1.6 root 4974: break;
1.1.1.5 root 4975: case 2:
1.1.1.6 root 4976: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4977: gen_helper_mtc0_vpeconf0(arg);
1.1.1.5 root 4978: rn = "VPEConf0";
1.1.1.6 root 4979: break;
1.1.1.5 root 4980: case 3:
1.1.1.6 root 4981: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4982: gen_helper_mtc0_vpeconf1(arg);
1.1.1.5 root 4983: rn = "VPEConf1";
1.1.1.6 root 4984: break;
1.1.1.5 root 4985: case 4:
1.1.1.6 root 4986: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4987: gen_helper_mtc0_yqmask(arg);
1.1.1.5 root 4988: rn = "YQMask";
1.1.1.6 root 4989: break;
1.1.1.5 root 4990: case 5:
1.1.1.6 root 4991: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4992: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 4993: rn = "VPESchedule";
1.1.1.6 root 4994: break;
1.1.1.5 root 4995: case 6:
1.1.1.6 root 4996: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4997: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 4998: rn = "VPEScheFBack";
1.1.1.6 root 4999: break;
1.1.1.5 root 5000: case 7:
1.1.1.6 root 5001: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5002: gen_helper_mtc0_vpeopt(arg);
1.1.1.5 root 5003: rn = "VPEOpt";
1.1.1.6 root 5004: break;
1.1.1.5 root 5005: default:
5006: goto die;
5007: }
5008: break;
5009: case 2:
5010: switch (sel) {
5011: case 0:
1.1.1.8 root 5012: gen_helper_mtc0_entrylo0(arg);
1.1.1.6 root 5013: rn = "EntryLo0";
5014: break;
5015: case 1:
5016: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5017: gen_helper_mtc0_tcstatus(arg);
1.1.1.6 root 5018: rn = "TCStatus";
5019: break;
5020: case 2:
5021: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5022: gen_helper_mtc0_tcbind(arg);
1.1.1.6 root 5023: rn = "TCBind";
5024: break;
1.1.1.5 root 5025: case 3:
1.1.1.6 root 5026: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5027: gen_helper_mtc0_tcrestart(arg);
1.1.1.6 root 5028: rn = "TCRestart";
5029: break;
1.1.1.5 root 5030: case 4:
1.1.1.6 root 5031: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5032: gen_helper_mtc0_tchalt(arg);
1.1.1.6 root 5033: rn = "TCHalt";
5034: break;
1.1.1.5 root 5035: case 5:
1.1.1.6 root 5036: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5037: gen_helper_mtc0_tccontext(arg);
1.1.1.6 root 5038: rn = "TCContext";
5039: break;
1.1.1.5 root 5040: case 6:
1.1.1.6 root 5041: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5042: gen_helper_mtc0_tcschedule(arg);
1.1.1.6 root 5043: rn = "TCSchedule";
5044: break;
1.1.1.5 root 5045: case 7:
1.1.1.6 root 5046: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5047: gen_helper_mtc0_tcschefback(arg);
1.1.1.6 root 5048: rn = "TCScheFBack";
5049: break;
1.1.1.5 root 5050: default:
5051: goto die;
5052: }
5053: break;
5054: case 3:
5055: switch (sel) {
5056: case 0:
1.1.1.8 root 5057: gen_helper_mtc0_entrylo1(arg);
1.1.1.6 root 5058: rn = "EntryLo1";
5059: break;
1.1.1.5 root 5060: default:
5061: goto die;
1.1.1.6 root 5062: }
1.1.1.5 root 5063: break;
5064: case 4:
5065: switch (sel) {
5066: case 0:
1.1.1.8 root 5067: gen_helper_mtc0_context(arg);
1.1.1.6 root 5068: rn = "Context";
5069: break;
5070: case 1:
1.1.1.8 root 5071: // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 5072: rn = "ContextConfig";
5073: // break;
1.1.1.5 root 5074: default:
5075: goto die;
1.1.1.6 root 5076: }
1.1.1.5 root 5077: break;
5078: case 5:
5079: switch (sel) {
5080: case 0:
1.1.1.8 root 5081: gen_helper_mtc0_pagemask(arg);
1.1.1.6 root 5082: rn = "PageMask";
5083: break;
5084: case 1:
5085: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5086: gen_helper_mtc0_pagegrain(arg);
1.1.1.6 root 5087: rn = "PageGrain";
5088: break;
1.1.1.5 root 5089: default:
5090: goto die;
1.1.1.6 root 5091: }
1.1.1.5 root 5092: break;
5093: case 6:
5094: switch (sel) {
5095: case 0:
1.1.1.8 root 5096: gen_helper_mtc0_wired(arg);
1.1.1.6 root 5097: rn = "Wired";
5098: break;
5099: case 1:
5100: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5101: gen_helper_mtc0_srsconf0(arg);
1.1.1.6 root 5102: rn = "SRSConf0";
5103: break;
5104: case 2:
5105: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5106: gen_helper_mtc0_srsconf1(arg);
1.1.1.6 root 5107: rn = "SRSConf1";
5108: break;
1.1.1.5 root 5109: case 3:
1.1.1.6 root 5110: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5111: gen_helper_mtc0_srsconf2(arg);
1.1.1.6 root 5112: rn = "SRSConf2";
5113: break;
1.1.1.5 root 5114: case 4:
1.1.1.6 root 5115: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5116: gen_helper_mtc0_srsconf3(arg);
1.1.1.6 root 5117: rn = "SRSConf3";
5118: break;
1.1.1.5 root 5119: case 5:
1.1.1.6 root 5120: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5121: gen_helper_mtc0_srsconf4(arg);
1.1.1.6 root 5122: rn = "SRSConf4";
5123: break;
1.1.1.5 root 5124: default:
5125: goto die;
1.1.1.6 root 5126: }
1.1.1.5 root 5127: break;
5128: case 7:
5129: switch (sel) {
5130: case 0:
1.1.1.6 root 5131: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5132: gen_helper_mtc0_hwrena(arg);
1.1.1.6 root 5133: rn = "HWREna";
5134: break;
1.1.1.5 root 5135: default:
5136: goto die;
1.1.1.6 root 5137: }
1.1.1.5 root 5138: break;
5139: case 8:
5140: /* ignored */
1.1.1.7 root 5141: rn = "BadVAddr";
1.1.1.5 root 5142: break;
5143: case 9:
5144: switch (sel) {
5145: case 0:
1.1.1.8 root 5146: gen_helper_mtc0_count(arg);
1.1.1.6 root 5147: rn = "Count";
5148: break;
5149: /* 6,7 are implementation dependent */
1.1.1.5 root 5150: default:
5151: goto die;
1.1.1.6 root 5152: }
5153: /* Stop translation as we may have switched the execution mode */
5154: ctx->bstate = BS_STOP;
1.1.1.5 root 5155: break;
5156: case 10:
5157: switch (sel) {
5158: case 0:
1.1.1.8 root 5159: gen_helper_mtc0_entryhi(arg);
1.1.1.6 root 5160: rn = "EntryHi";
5161: break;
1.1.1.5 root 5162: default:
5163: goto die;
1.1.1.6 root 5164: }
1.1.1.5 root 5165: break;
5166: case 11:
5167: switch (sel) {
5168: case 0:
1.1.1.8 root 5169: gen_helper_mtc0_compare(arg);
1.1.1.6 root 5170: rn = "Compare";
5171: break;
5172: /* 6,7 are implementation dependent */
1.1.1.5 root 5173: default:
5174: goto die;
1.1.1.6 root 5175: }
5176: /* Stop translation as we may have switched the execution mode */
5177: ctx->bstate = BS_STOP;
1.1.1.5 root 5178: break;
5179: case 12:
5180: switch (sel) {
5181: case 0:
1.1.1.8 root 5182: save_cpu_state(ctx, 1);
5183: gen_helper_mtc0_status(arg);
1.1.1.6 root 5184: /* BS_STOP isn't good enough here, hflags may have changed. */
5185: gen_save_pc(ctx->pc + 4);
5186: ctx->bstate = BS_EXCP;
5187: rn = "Status";
5188: break;
5189: case 1:
5190: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5191: gen_helper_mtc0_intctl(arg);
1.1.1.6 root 5192: /* Stop translation as we may have switched the execution mode */
5193: ctx->bstate = BS_STOP;
5194: rn = "IntCtl";
5195: break;
5196: case 2:
5197: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5198: gen_helper_mtc0_srsctl(arg);
1.1.1.6 root 5199: /* Stop translation as we may have switched the execution mode */
5200: ctx->bstate = BS_STOP;
5201: rn = "SRSCtl";
5202: break;
1.1.1.5 root 5203: case 3:
1.1.1.6 root 5204: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5205: gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 5206: /* Stop translation as we may have switched the execution mode */
5207: ctx->bstate = BS_STOP;
5208: rn = "SRSMap";
5209: break;
1.1.1.5 root 5210: default:
5211: goto die;
1.1.1.6 root 5212: }
1.1.1.5 root 5213: break;
5214: case 13:
5215: switch (sel) {
5216: case 0:
1.1.1.8 root 5217: save_cpu_state(ctx, 1);
1.1.1.12 root 5218: /* Mark as an IO operation because we may trigger a software
5219: interrupt. */
5220: if (use_icount) {
5221: gen_io_start();
5222: }
1.1.1.8 root 5223: gen_helper_mtc0_cause(arg);
1.1.1.12 root 5224: if (use_icount) {
5225: gen_io_end();
5226: }
5227: /* Stop translation as we may have triggered an intetrupt */
5228: ctx->bstate = BS_STOP;
1.1.1.6 root 5229: rn = "Cause";
5230: break;
1.1.1.5 root 5231: default:
5232: goto die;
1.1.1.6 root 5233: }
1.1.1.5 root 5234: break;
5235: case 14:
5236: switch (sel) {
5237: case 0:
1.1.1.8 root 5238: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 5239: rn = "EPC";
5240: break;
1.1.1.5 root 5241: default:
5242: goto die;
1.1.1.6 root 5243: }
1.1.1.5 root 5244: break;
5245: case 15:
5246: switch (sel) {
5247: case 0:
1.1.1.6 root 5248: /* ignored */
5249: rn = "PRid";
5250: break;
5251: case 1:
5252: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5253: gen_helper_mtc0_ebase(arg);
1.1.1.6 root 5254: rn = "EBase";
5255: break;
1.1.1.5 root 5256: default:
5257: goto die;
1.1.1.6 root 5258: }
1.1.1.5 root 5259: break;
5260: case 16:
5261: switch (sel) {
5262: case 0:
1.1.1.8 root 5263: gen_helper_mtc0_config0(arg);
1.1.1.5 root 5264: rn = "Config";
1.1.1.6 root 5265: /* Stop translation as we may have switched the execution mode */
5266: ctx->bstate = BS_STOP;
1.1.1.5 root 5267: break;
5268: case 1:
1.1.1.8 root 5269: /* ignored, read only */
1.1.1.5 root 5270: rn = "Config1";
5271: break;
5272: case 2:
1.1.1.8 root 5273: gen_helper_mtc0_config2(arg);
1.1.1.5 root 5274: rn = "Config2";
1.1.1.6 root 5275: /* Stop translation as we may have switched the execution mode */
5276: ctx->bstate = BS_STOP;
1.1.1.5 root 5277: break;
5278: case 3:
1.1.1.6 root 5279: /* ignored */
1.1.1.5 root 5280: rn = "Config3";
5281: break;
5282: /* 6,7 are implementation dependent */
5283: default:
5284: rn = "Invalid config selector";
5285: goto die;
5286: }
5287: break;
5288: case 17:
5289: switch (sel) {
5290: case 0:
1.1.1.9 root 5291: gen_helper_mtc0_lladdr(arg);
1.1.1.6 root 5292: rn = "LLAddr";
5293: break;
1.1.1.5 root 5294: default:
5295: goto die;
5296: }
5297: break;
5298: case 18:
5299: switch (sel) {
1.1.1.6 root 5300: case 0 ... 7:
1.1.1.8 root 5301: gen_helper_1i(mtc0_watchlo, arg, sel);
1.1.1.6 root 5302: rn = "WatchLo";
5303: break;
1.1.1.5 root 5304: default:
5305: goto die;
5306: }
5307: break;
5308: case 19:
5309: switch (sel) {
1.1.1.6 root 5310: case 0 ... 7:
1.1.1.8 root 5311: gen_helper_1i(mtc0_watchhi, arg, sel);
1.1.1.6 root 5312: rn = "WatchHi";
5313: break;
1.1.1.5 root 5314: default:
5315: goto die;
5316: }
5317: break;
5318: case 20:
5319: switch (sel) {
5320: case 0:
1.1.1.6 root 5321: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 5322: gen_helper_mtc0_xcontext(arg);
1.1.1.6 root 5323: rn = "XContext";
5324: break;
1.1.1.5 root 5325: default:
5326: goto die;
5327: }
5328: break;
5329: case 21:
5330: /* Officially reserved, but sel 0 is used for R1x000 framemask */
5331: switch (sel) {
5332: case 0:
1.1.1.8 root 5333: gen_helper_mtc0_framemask(arg);
1.1.1.6 root 5334: rn = "Framemask";
5335: break;
1.1.1.5 root 5336: default:
5337: goto die;
5338: }
5339: break;
5340: case 22:
5341: /* ignored */
5342: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 root 5343: break;
1.1.1.5 root 5344: case 23:
5345: switch (sel) {
5346: case 0:
1.1.1.8 root 5347: gen_helper_mtc0_debug(arg); /* EJTAG support */
1.1.1.6 root 5348: /* BS_STOP isn't good enough here, hflags may have changed. */
5349: gen_save_pc(ctx->pc + 4);
5350: ctx->bstate = BS_EXCP;
5351: rn = "Debug";
5352: break;
5353: case 1:
1.1.1.8 root 5354: // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 5355: /* Stop translation as we may have switched the execution mode */
5356: ctx->bstate = BS_STOP;
5357: rn = "TraceControl";
5358: // break;
5359: case 2:
1.1.1.8 root 5360: // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 5361: /* Stop translation as we may have switched the execution mode */
5362: ctx->bstate = BS_STOP;
5363: rn = "TraceControl2";
5364: // break;
5365: case 3:
1.1.1.8 root 5366: // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 5367: /* Stop translation as we may have switched the execution mode */
5368: ctx->bstate = BS_STOP;
5369: rn = "UserTraceData";
5370: // break;
1.1.1.5 root 5371: case 4:
1.1.1.8 root 5372: // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 5373: /* Stop translation as we may have switched the execution mode */
5374: ctx->bstate = BS_STOP;
5375: rn = "TraceBPC";
5376: // break;
1.1.1.5 root 5377: default:
5378: goto die;
5379: }
5380: break;
5381: case 24:
5382: switch (sel) {
5383: case 0:
1.1.1.7 root 5384: /* EJTAG support */
1.1.1.8 root 5385: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 5386: rn = "DEPC";
5387: break;
1.1.1.5 root 5388: default:
5389: goto die;
5390: }
5391: break;
5392: case 25:
5393: switch (sel) {
5394: case 0:
1.1.1.8 root 5395: gen_helper_mtc0_performance0(arg);
1.1.1.6 root 5396: rn = "Performance0";
5397: break;
5398: case 1:
1.1.1.8 root 5399: // gen_helper_mtc0_performance1(arg);
1.1.1.6 root 5400: rn = "Performance1";
5401: // break;
5402: case 2:
1.1.1.8 root 5403: // gen_helper_mtc0_performance2(arg);
1.1.1.6 root 5404: rn = "Performance2";
5405: // break;
1.1.1.5 root 5406: case 3:
1.1.1.8 root 5407: // gen_helper_mtc0_performance3(arg);
1.1.1.6 root 5408: rn = "Performance3";
5409: // break;
1.1.1.5 root 5410: case 4:
1.1.1.8 root 5411: // gen_helper_mtc0_performance4(arg);
1.1.1.6 root 5412: rn = "Performance4";
5413: // break;
1.1.1.5 root 5414: case 5:
1.1.1.8 root 5415: // gen_helper_mtc0_performance5(arg);
1.1.1.6 root 5416: rn = "Performance5";
5417: // break;
1.1.1.5 root 5418: case 6:
1.1.1.8 root 5419: // gen_helper_mtc0_performance6(arg);
1.1.1.6 root 5420: rn = "Performance6";
5421: // break;
1.1.1.5 root 5422: case 7:
1.1.1.8 root 5423: // gen_helper_mtc0_performance7(arg);
1.1.1.6 root 5424: rn = "Performance7";
5425: // break;
1.1.1.5 root 5426: default:
5427: goto die;
5428: }
1.1.1.6 root 5429: break;
1.1.1.5 root 5430: case 26:
1.1.1.6 root 5431: /* ignored */
1.1.1.5 root 5432: rn = "ECC";
1.1.1.6 root 5433: break;
1.1.1.5 root 5434: case 27:
5435: switch (sel) {
5436: case 0 ... 3:
1.1.1.6 root 5437: /* ignored */
5438: rn = "CacheErr";
5439: break;
1.1.1.5 root 5440: default:
5441: goto die;
5442: }
1.1.1.6 root 5443: break;
1.1.1.5 root 5444: case 28:
5445: switch (sel) {
5446: case 0:
5447: case 2:
5448: case 4:
5449: case 6:
1.1.1.8 root 5450: gen_helper_mtc0_taglo(arg);
1.1.1.5 root 5451: rn = "TagLo";
5452: break;
5453: case 1:
5454: case 3:
5455: case 5:
5456: case 7:
1.1.1.8 root 5457: gen_helper_mtc0_datalo(arg);
1.1.1.5 root 5458: rn = "DataLo";
5459: break;
5460: default:
5461: goto die;
5462: }
5463: break;
5464: case 29:
5465: switch (sel) {
5466: case 0:
5467: case 2:
5468: case 4:
5469: case 6:
1.1.1.8 root 5470: gen_helper_mtc0_taghi(arg);
1.1.1.5 root 5471: rn = "TagHi";
5472: break;
5473: case 1:
5474: case 3:
5475: case 5:
5476: case 7:
1.1.1.8 root 5477: gen_helper_mtc0_datahi(arg);
1.1.1.5 root 5478: rn = "DataHi";
5479: break;
5480: default:
5481: rn = "invalid sel";
5482: goto die;
5483: }
1.1.1.6 root 5484: break;
1.1.1.5 root 5485: case 30:
5486: switch (sel) {
5487: case 0:
1.1.1.8 root 5488: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 5489: rn = "ErrorEPC";
5490: break;
1.1.1.5 root 5491: default:
5492: goto die;
5493: }
5494: break;
5495: case 31:
5496: switch (sel) {
5497: case 0:
1.1.1.7 root 5498: /* EJTAG support */
1.1.1.8 root 5499: gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 5500: rn = "DESAVE";
5501: break;
1.1.1.5 root 5502: default:
5503: goto die;
5504: }
1.1.1.6 root 5505: /* Stop translation as we may have switched the execution mode */
5506: ctx->bstate = BS_STOP;
1.1.1.5 root 5507: break;
5508: default:
1.1.1.6 root 5509: goto die;
1.1.1.5 root 5510: }
1.1.1.13! root 5511: (void)rn; /* avoid a compiler warning */
1.1.1.7 root 5512: LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5513: /* For simplicity assume that all writes can cause interrupts. */
5514: if (use_icount) {
5515: gen_io_end();
5516: ctx->bstate = BS_STOP;
1.1.1.5 root 5517: }
5518: return;
5519:
5520: die:
1.1.1.7 root 5521: LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 5522: generate_exception(ctx, EXCP_RI);
5523: }
1.1.1.6 root 5524: #endif /* TARGET_MIPS64 */
1.1.1.5 root 5525:
1.1.1.7 root 5526: static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
1.1.1.6 root 5527: int u, int sel, int h)
1.1.1.5 root 5528: {
1.1.1.6 root 5529: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.7 root 5530: TCGv t0 = tcg_temp_local_new();
1.1.1.5 root 5531:
1.1.1.6 root 5532: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
1.1.1.7 root 5533: ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5534: (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5535: tcg_gen_movi_tl(t0, -1);
1.1.1.6 root 5536: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5537: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1.1.1.7 root 5538: tcg_gen_movi_tl(t0, -1);
1.1.1.6 root 5539: else if (u == 0) {
5540: switch (rt) {
5541: case 2:
5542: switch (sel) {
5543: case 1:
1.1.1.7 root 5544: gen_helper_mftc0_tcstatus(t0);
1.1.1.6 root 5545: break;
5546: case 2:
1.1.1.7 root 5547: gen_helper_mftc0_tcbind(t0);
1.1.1.6 root 5548: break;
5549: case 3:
1.1.1.7 root 5550: gen_helper_mftc0_tcrestart(t0);
1.1.1.6 root 5551: break;
5552: case 4:
1.1.1.7 root 5553: gen_helper_mftc0_tchalt(t0);
1.1.1.6 root 5554: break;
5555: case 5:
1.1.1.7 root 5556: gen_helper_mftc0_tccontext(t0);
1.1.1.6 root 5557: break;
5558: case 6:
1.1.1.7 root 5559: gen_helper_mftc0_tcschedule(t0);
1.1.1.6 root 5560: break;
5561: case 7:
1.1.1.7 root 5562: gen_helper_mftc0_tcschefback(t0);
1.1.1.6 root 5563: break;
5564: default:
1.1.1.7 root 5565: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5566: break;
5567: }
5568: break;
5569: case 10:
5570: switch (sel) {
5571: case 0:
1.1.1.7 root 5572: gen_helper_mftc0_entryhi(t0);
1.1.1.6 root 5573: break;
5574: default:
1.1.1.7 root 5575: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5576: break;
5577: }
5578: case 12:
5579: switch (sel) {
5580: case 0:
1.1.1.7 root 5581: gen_helper_mftc0_status(t0);
1.1.1.6 root 5582: break;
5583: default:
1.1.1.7 root 5584: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5585: break;
5586: }
5587: case 23:
5588: switch (sel) {
5589: case 0:
1.1.1.7 root 5590: gen_helper_mftc0_debug(t0);
1.1.1.6 root 5591: break;
5592: default:
1.1.1.7 root 5593: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5594: break;
5595: }
5596: break;
5597: default:
1.1.1.7 root 5598: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5599: }
5600: } else switch (sel) {
5601: /* GPR registers. */
5602: case 0:
1.1.1.7 root 5603: gen_helper_1i(mftgpr, t0, rt);
1.1.1.6 root 5604: break;
5605: /* Auxiliary CPU registers */
5606: case 1:
5607: switch (rt) {
5608: case 0:
1.1.1.7 root 5609: gen_helper_1i(mftlo, t0, 0);
1.1.1.6 root 5610: break;
5611: case 1:
1.1.1.7 root 5612: gen_helper_1i(mfthi, t0, 0);
1.1.1.6 root 5613: break;
5614: case 2:
1.1.1.7 root 5615: gen_helper_1i(mftacx, t0, 0);
1.1.1.6 root 5616: break;
5617: case 4:
1.1.1.7 root 5618: gen_helper_1i(mftlo, t0, 1);
1.1.1.6 root 5619: break;
5620: case 5:
1.1.1.7 root 5621: gen_helper_1i(mfthi, t0, 1);
1.1.1.6 root 5622: break;
5623: case 6:
1.1.1.7 root 5624: gen_helper_1i(mftacx, t0, 1);
1.1.1.6 root 5625: break;
5626: case 8:
1.1.1.7 root 5627: gen_helper_1i(mftlo, t0, 2);
1.1.1.6 root 5628: break;
5629: case 9:
1.1.1.7 root 5630: gen_helper_1i(mfthi, t0, 2);
1.1.1.6 root 5631: break;
5632: case 10:
1.1.1.7 root 5633: gen_helper_1i(mftacx, t0, 2);
1.1.1.6 root 5634: break;
5635: case 12:
1.1.1.7 root 5636: gen_helper_1i(mftlo, t0, 3);
1.1.1.6 root 5637: break;
5638: case 13:
1.1.1.7 root 5639: gen_helper_1i(mfthi, t0, 3);
1.1.1.6 root 5640: break;
5641: case 14:
1.1.1.7 root 5642: gen_helper_1i(mftacx, t0, 3);
1.1.1.6 root 5643: break;
5644: case 16:
1.1.1.7 root 5645: gen_helper_mftdsp(t0);
1.1.1.6 root 5646: break;
5647: default:
5648: goto die;
5649: }
5650: break;
5651: /* Floating point (COP1). */
5652: case 2:
5653: /* XXX: For now we support only a single FPU context. */
5654: if (h == 0) {
1.1.1.7 root 5655: TCGv_i32 fp0 = tcg_temp_new_i32();
5656:
5657: gen_load_fpr32(fp0, rt);
5658: tcg_gen_ext_i32_tl(t0, fp0);
5659: tcg_temp_free_i32(fp0);
1.1.1.6 root 5660: } else {
1.1.1.7 root 5661: TCGv_i32 fp0 = tcg_temp_new_i32();
5662:
5663: gen_load_fpr32h(fp0, rt);
5664: tcg_gen_ext_i32_tl(t0, fp0);
5665: tcg_temp_free_i32(fp0);
1.1.1.6 root 5666: }
5667: break;
5668: case 3:
5669: /* XXX: For now we support only a single FPU context. */
1.1.1.7 root 5670: gen_helper_1i(cfc1, t0, rt);
1.1.1.6 root 5671: break;
5672: /* COP2: Not implemented. */
5673: case 4:
5674: case 5:
5675: /* fall through */
5676: default:
5677: goto die;
5678: }
1.1.1.7 root 5679: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5680: gen_store_gpr(t0, rd);
5681: tcg_temp_free(t0);
1.1.1.6 root 5682: return;
5683:
5684: die:
1.1.1.7 root 5685: tcg_temp_free(t0);
5686: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1.1.1.6 root 5687: generate_exception(ctx, EXCP_RI);
5688: }
5689:
1.1.1.7 root 5690: static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
1.1.1.6 root 5691: int u, int sel, int h)
5692: {
5693: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.7 root 5694: TCGv t0 = tcg_temp_local_new();
1.1.1.6 root 5695:
1.1.1.7 root 5696: gen_load_gpr(t0, rt);
1.1.1.6 root 5697: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
1.1.1.7 root 5698: ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5699: (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1.1.1.6 root 5700: /* NOP */ ;
5701: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5702: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5703: /* NOP */ ;
5704: else if (u == 0) {
5705: switch (rd) {
5706: case 2:
5707: switch (sel) {
5708: case 1:
1.1.1.7 root 5709: gen_helper_mttc0_tcstatus(t0);
1.1.1.6 root 5710: break;
5711: case 2:
1.1.1.7 root 5712: gen_helper_mttc0_tcbind(t0);
1.1.1.6 root 5713: break;
5714: case 3:
1.1.1.7 root 5715: gen_helper_mttc0_tcrestart(t0);
1.1.1.6 root 5716: break;
5717: case 4:
1.1.1.7 root 5718: gen_helper_mttc0_tchalt(t0);
1.1.1.6 root 5719: break;
5720: case 5:
1.1.1.7 root 5721: gen_helper_mttc0_tccontext(t0);
1.1.1.6 root 5722: break;
5723: case 6:
1.1.1.7 root 5724: gen_helper_mttc0_tcschedule(t0);
1.1.1.6 root 5725: break;
5726: case 7:
1.1.1.7 root 5727: gen_helper_mttc0_tcschefback(t0);
1.1.1.6 root 5728: break;
5729: default:
1.1.1.7 root 5730: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5731: break;
5732: }
5733: break;
5734: case 10:
5735: switch (sel) {
5736: case 0:
1.1.1.7 root 5737: gen_helper_mttc0_entryhi(t0);
1.1.1.6 root 5738: break;
5739: default:
1.1.1.7 root 5740: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5741: break;
5742: }
5743: case 12:
5744: switch (sel) {
5745: case 0:
1.1.1.7 root 5746: gen_helper_mttc0_status(t0);
1.1.1.6 root 5747: break;
5748: default:
1.1.1.7 root 5749: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5750: break;
5751: }
5752: case 23:
5753: switch (sel) {
5754: case 0:
1.1.1.7 root 5755: gen_helper_mttc0_debug(t0);
1.1.1.6 root 5756: break;
5757: default:
1.1.1.7 root 5758: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5759: break;
5760: }
5761: break;
5762: default:
1.1.1.7 root 5763: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5764: }
5765: } else switch (sel) {
5766: /* GPR registers. */
5767: case 0:
1.1.1.7 root 5768: gen_helper_1i(mttgpr, t0, rd);
1.1.1.6 root 5769: break;
5770: /* Auxiliary CPU registers */
5771: case 1:
5772: switch (rd) {
5773: case 0:
1.1.1.7 root 5774: gen_helper_1i(mttlo, t0, 0);
1.1.1.6 root 5775: break;
5776: case 1:
1.1.1.7 root 5777: gen_helper_1i(mtthi, t0, 0);
1.1.1.6 root 5778: break;
5779: case 2:
1.1.1.7 root 5780: gen_helper_1i(mttacx, t0, 0);
1.1.1.6 root 5781: break;
5782: case 4:
1.1.1.7 root 5783: gen_helper_1i(mttlo, t0, 1);
1.1.1.6 root 5784: break;
5785: case 5:
1.1.1.7 root 5786: gen_helper_1i(mtthi, t0, 1);
1.1.1.6 root 5787: break;
5788: case 6:
1.1.1.7 root 5789: gen_helper_1i(mttacx, t0, 1);
1.1.1.6 root 5790: break;
5791: case 8:
1.1.1.7 root 5792: gen_helper_1i(mttlo, t0, 2);
1.1.1.6 root 5793: break;
5794: case 9:
1.1.1.7 root 5795: gen_helper_1i(mtthi, t0, 2);
1.1.1.6 root 5796: break;
5797: case 10:
1.1.1.7 root 5798: gen_helper_1i(mttacx, t0, 2);
1.1.1.6 root 5799: break;
5800: case 12:
1.1.1.7 root 5801: gen_helper_1i(mttlo, t0, 3);
1.1.1.6 root 5802: break;
5803: case 13:
1.1.1.7 root 5804: gen_helper_1i(mtthi, t0, 3);
1.1.1.6 root 5805: break;
5806: case 14:
1.1.1.7 root 5807: gen_helper_1i(mttacx, t0, 3);
1.1.1.6 root 5808: break;
5809: case 16:
1.1.1.7 root 5810: gen_helper_mttdsp(t0);
1.1.1.6 root 5811: break;
5812: default:
5813: goto die;
5814: }
5815: break;
5816: /* Floating point (COP1). */
5817: case 2:
5818: /* XXX: For now we support only a single FPU context. */
5819: if (h == 0) {
1.1.1.7 root 5820: TCGv_i32 fp0 = tcg_temp_new_i32();
5821:
5822: tcg_gen_trunc_tl_i32(fp0, t0);
5823: gen_store_fpr32(fp0, rd);
5824: tcg_temp_free_i32(fp0);
1.1.1.6 root 5825: } else {
1.1.1.7 root 5826: TCGv_i32 fp0 = tcg_temp_new_i32();
5827:
5828: tcg_gen_trunc_tl_i32(fp0, t0);
5829: gen_store_fpr32h(fp0, rd);
5830: tcg_temp_free_i32(fp0);
1.1.1.6 root 5831: }
5832: break;
5833: case 3:
5834: /* XXX: For now we support only a single FPU context. */
1.1.1.7 root 5835: gen_helper_1i(ctc1, t0, rd);
1.1.1.6 root 5836: break;
5837: /* COP2: Not implemented. */
5838: case 4:
5839: case 5:
5840: /* fall through */
5841: default:
5842: goto die;
5843: }
1.1.1.7 root 5844: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5845: tcg_temp_free(t0);
1.1.1.6 root 5846: return;
5847:
5848: die:
1.1.1.7 root 5849: tcg_temp_free(t0);
5850: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1.1.1.6 root 5851: generate_exception(ctx, EXCP_RI);
5852: }
5853:
5854: static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5855: {
5856: const char *opn = "ldst";
1.1.1.5 root 5857:
5858: switch (opc) {
5859: case OPC_MFC0:
5860: if (rt == 0) {
1.1.1.6 root 5861: /* Treat as NOP. */
1.1.1.5 root 5862: return;
5863: }
1.1.1.8 root 5864: gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
1.1.1.5 root 5865: opn = "mfc0";
5866: break;
5867: case OPC_MTC0:
1.1.1.7 root 5868: {
1.1.1.8 root 5869: TCGv t0 = tcg_temp_new();
1.1.1.7 root 5870:
5871: gen_load_gpr(t0, rt);
5872: gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5873: tcg_temp_free(t0);
5874: }
1.1.1.5 root 5875: opn = "mtc0";
5876: break;
1.1.1.6 root 5877: #if defined(TARGET_MIPS64)
1.1.1.5 root 5878: case OPC_DMFC0:
1.1.1.6 root 5879: check_insn(env, ctx, ISA_MIPS3);
1.1.1.5 root 5880: if (rt == 0) {
1.1.1.6 root 5881: /* Treat as NOP. */
1.1.1.5 root 5882: return;
5883: }
1.1.1.8 root 5884: gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
1.1.1.5 root 5885: opn = "dmfc0";
5886: break;
5887: case OPC_DMTC0:
1.1.1.6 root 5888: check_insn(env, ctx, ISA_MIPS3);
1.1.1.7 root 5889: {
1.1.1.8 root 5890: TCGv t0 = tcg_temp_new();
1.1.1.7 root 5891:
5892: gen_load_gpr(t0, rt);
5893: gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5894: tcg_temp_free(t0);
5895: }
1.1.1.5 root 5896: opn = "dmtc0";
5897: break;
1.1.1.6 root 5898: #endif
5899: case OPC_MFTR:
5900: check_insn(env, ctx, ASE_MT);
5901: if (rd == 0) {
5902: /* Treat as NOP. */
5903: return;
5904: }
1.1.1.7 root 5905: gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5906: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5907: opn = "mftr";
5908: break;
5909: case OPC_MTTR:
5910: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 5911: gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5912: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5913: opn = "mttr";
5914: break;
1.1.1.5 root 5915: case OPC_TLBWI:
5916: opn = "tlbwi";
1.1.1.8 root 5917: if (!env->tlb->helper_tlbwi)
1.1.1.6 root 5918: goto die;
1.1.1.7 root 5919: gen_helper_tlbwi();
1.1.1.5 root 5920: break;
5921: case OPC_TLBWR:
5922: opn = "tlbwr";
1.1.1.8 root 5923: if (!env->tlb->helper_tlbwr)
1.1.1.6 root 5924: goto die;
1.1.1.7 root 5925: gen_helper_tlbwr();
1.1.1.5 root 5926: break;
5927: case OPC_TLBP:
5928: opn = "tlbp";
1.1.1.8 root 5929: if (!env->tlb->helper_tlbp)
1.1.1.6 root 5930: goto die;
1.1.1.7 root 5931: gen_helper_tlbp();
1.1.1.5 root 5932: break;
5933: case OPC_TLBR:
5934: opn = "tlbr";
1.1.1.8 root 5935: if (!env->tlb->helper_tlbr)
1.1.1.6 root 5936: goto die;
1.1.1.7 root 5937: gen_helper_tlbr();
1.1.1.5 root 5938: break;
5939: case OPC_ERET:
5940: opn = "eret";
1.1.1.6 root 5941: check_insn(env, ctx, ISA_MIPS2);
1.1.1.7 root 5942: gen_helper_eret();
1.1.1.5 root 5943: ctx->bstate = BS_EXCP;
5944: break;
5945: case OPC_DERET:
5946: opn = "deret";
1.1.1.6 root 5947: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 5948: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1.1.1.6 root 5949: MIPS_INVAL(opn);
1.1.1.5 root 5950: generate_exception(ctx, EXCP_RI);
5951: } else {
1.1.1.7 root 5952: gen_helper_deret();
1.1.1.5 root 5953: ctx->bstate = BS_EXCP;
5954: }
5955: break;
5956: case OPC_WAIT:
5957: opn = "wait";
1.1.1.6 root 5958: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
1.1.1.5 root 5959: /* If we get an exception, we want to restart at next instruction */
5960: ctx->pc += 4;
5961: save_cpu_state(ctx, 1);
5962: ctx->pc -= 4;
1.1.1.7 root 5963: gen_helper_wait();
1.1.1.5 root 5964: ctx->bstate = BS_EXCP;
5965: break;
5966: default:
1.1.1.6 root 5967: die:
5968: MIPS_INVAL(opn);
1.1.1.5 root 5969: generate_exception(ctx, EXCP_RI);
5970: return;
5971: }
1.1.1.13! root 5972: (void)opn; /* avoid a compiler warning */
1.1.1.5 root 5973: MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5974: }
1.1.1.7 root 5975: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 5976:
5977: /* CP1 Branches (before delay slot) */
1.1.1.6 root 5978: static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5979: int32_t cc, int32_t offset)
1.1.1.5 root 5980: {
5981: target_ulong btarget;
1.1.1.6 root 5982: const char *opn = "cp1 cond branch";
1.1.1.7 root 5983: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.6 root 5984:
5985: if (cc != 0)
5986: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
1.1.1.5 root 5987:
5988: btarget = ctx->pc + 4 + offset;
5989:
5990: switch (op) {
5991: case OPC_BC1F:
1.1.1.8 root 5992: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5993: tcg_gen_not_i32(t0, t0);
5994: tcg_gen_andi_i32(t0, t0, 1);
5995: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 5996: opn = "bc1f";
1.1.1.5 root 5997: goto not_likely;
5998: case OPC_BC1FL:
1.1.1.8 root 5999: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6000: tcg_gen_not_i32(t0, t0);
6001: tcg_gen_andi_i32(t0, t0, 1);
6002: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6003: opn = "bc1fl";
1.1.1.5 root 6004: goto likely;
6005: case OPC_BC1T:
1.1.1.8 root 6006: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6007: tcg_gen_andi_i32(t0, t0, 1);
6008: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6009: opn = "bc1t";
6010: goto not_likely;
1.1.1.5 root 6011: case OPC_BC1TL:
1.1.1.8 root 6012: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6013: tcg_gen_andi_i32(t0, t0, 1);
6014: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 6015: opn = "bc1tl";
1.1.1.5 root 6016: likely:
6017: ctx->hflags |= MIPS_HFLAG_BL;
1.1.1.6 root 6018: break;
6019: case OPC_BC1FANY2:
1.1.1.7 root 6020: {
1.1.1.8 root 6021: TCGv_i32 t1 = tcg_temp_new_i32();
6022: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6023: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
1.1.1.12 root 6024: tcg_gen_nor_i32(t0, t0, t1);
1.1.1.8 root 6025: tcg_temp_free_i32(t1);
6026: tcg_gen_andi_i32(t0, t0, 1);
6027: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6028: }
1.1.1.6 root 6029: opn = "bc1any2f";
6030: goto not_likely;
6031: case OPC_BC1TANY2:
1.1.1.7 root 6032: {
1.1.1.8 root 6033: TCGv_i32 t1 = tcg_temp_new_i32();
6034: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6035: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6036: tcg_gen_or_i32(t0, t0, t1);
6037: tcg_temp_free_i32(t1);
6038: tcg_gen_andi_i32(t0, t0, 1);
6039: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6040: }
1.1.1.6 root 6041: opn = "bc1any2t";
6042: goto not_likely;
6043: case OPC_BC1FANY4:
1.1.1.7 root 6044: {
1.1.1.8 root 6045: TCGv_i32 t1 = tcg_temp_new_i32();
6046: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6047: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6048: tcg_gen_or_i32(t0, t0, t1);
6049: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6050: tcg_gen_or_i32(t0, t0, t1);
6051: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
1.1.1.12 root 6052: tcg_gen_nor_i32(t0, t0, t1);
1.1.1.8 root 6053: tcg_temp_free_i32(t1);
6054: tcg_gen_andi_i32(t0, t0, 1);
6055: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6056: }
1.1.1.6 root 6057: opn = "bc1any4f";
6058: goto not_likely;
6059: case OPC_BC1TANY4:
1.1.1.7 root 6060: {
1.1.1.8 root 6061: TCGv_i32 t1 = tcg_temp_new_i32();
6062: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6063: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6064: tcg_gen_or_i32(t0, t0, t1);
6065: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6066: tcg_gen_or_i32(t0, t0, t1);
6067: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6068: tcg_gen_or_i32(t0, t0, t1);
6069: tcg_temp_free_i32(t1);
6070: tcg_gen_andi_i32(t0, t0, 1);
6071: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6072: }
1.1.1.6 root 6073: opn = "bc1any4t";
6074: not_likely:
6075: ctx->hflags |= MIPS_HFLAG_BC;
1.1.1.5 root 6076: break;
1.1.1.6 root 6077: default:
6078: MIPS_INVAL(opn);
6079: generate_exception (ctx, EXCP_RI);
1.1.1.7 root 6080: goto out;
1.1.1.5 root 6081: }
1.1.1.13! root 6082: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 6083: MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
1.1.1.5 root 6084: ctx->hflags, btarget);
6085: ctx->btarget = btarget;
1.1.1.7 root 6086:
6087: out:
6088: tcg_temp_free_i32(t0);
1.1.1.5 root 6089: }
6090:
6091: /* Coprocessor 1 (FPU) */
1.1.1.6 root 6092:
6093: #define FOP(func, fmt) (((fmt) << 21) | (func))
6094:
1.1.1.12 root 6095: enum fopcode {
6096: OPC_ADD_S = FOP(0, FMT_S),
6097: OPC_SUB_S = FOP(1, FMT_S),
6098: OPC_MUL_S = FOP(2, FMT_S),
6099: OPC_DIV_S = FOP(3, FMT_S),
6100: OPC_SQRT_S = FOP(4, FMT_S),
6101: OPC_ABS_S = FOP(5, FMT_S),
6102: OPC_MOV_S = FOP(6, FMT_S),
6103: OPC_NEG_S = FOP(7, FMT_S),
6104: OPC_ROUND_L_S = FOP(8, FMT_S),
6105: OPC_TRUNC_L_S = FOP(9, FMT_S),
6106: OPC_CEIL_L_S = FOP(10, FMT_S),
6107: OPC_FLOOR_L_S = FOP(11, FMT_S),
6108: OPC_ROUND_W_S = FOP(12, FMT_S),
6109: OPC_TRUNC_W_S = FOP(13, FMT_S),
6110: OPC_CEIL_W_S = FOP(14, FMT_S),
6111: OPC_FLOOR_W_S = FOP(15, FMT_S),
6112: OPC_MOVCF_S = FOP(17, FMT_S),
6113: OPC_MOVZ_S = FOP(18, FMT_S),
6114: OPC_MOVN_S = FOP(19, FMT_S),
6115: OPC_RECIP_S = FOP(21, FMT_S),
6116: OPC_RSQRT_S = FOP(22, FMT_S),
6117: OPC_RECIP2_S = FOP(28, FMT_S),
6118: OPC_RECIP1_S = FOP(29, FMT_S),
6119: OPC_RSQRT1_S = FOP(30, FMT_S),
6120: OPC_RSQRT2_S = FOP(31, FMT_S),
6121: OPC_CVT_D_S = FOP(33, FMT_S),
6122: OPC_CVT_W_S = FOP(36, FMT_S),
6123: OPC_CVT_L_S = FOP(37, FMT_S),
6124: OPC_CVT_PS_S = FOP(38, FMT_S),
6125: OPC_CMP_F_S = FOP (48, FMT_S),
6126: OPC_CMP_UN_S = FOP (49, FMT_S),
6127: OPC_CMP_EQ_S = FOP (50, FMT_S),
6128: OPC_CMP_UEQ_S = FOP (51, FMT_S),
6129: OPC_CMP_OLT_S = FOP (52, FMT_S),
6130: OPC_CMP_ULT_S = FOP (53, FMT_S),
6131: OPC_CMP_OLE_S = FOP (54, FMT_S),
6132: OPC_CMP_ULE_S = FOP (55, FMT_S),
6133: OPC_CMP_SF_S = FOP (56, FMT_S),
6134: OPC_CMP_NGLE_S = FOP (57, FMT_S),
6135: OPC_CMP_SEQ_S = FOP (58, FMT_S),
6136: OPC_CMP_NGL_S = FOP (59, FMT_S),
6137: OPC_CMP_LT_S = FOP (60, FMT_S),
6138: OPC_CMP_NGE_S = FOP (61, FMT_S),
6139: OPC_CMP_LE_S = FOP (62, FMT_S),
6140: OPC_CMP_NGT_S = FOP (63, FMT_S),
6141:
6142: OPC_ADD_D = FOP(0, FMT_D),
6143: OPC_SUB_D = FOP(1, FMT_D),
6144: OPC_MUL_D = FOP(2, FMT_D),
6145: OPC_DIV_D = FOP(3, FMT_D),
6146: OPC_SQRT_D = FOP(4, FMT_D),
6147: OPC_ABS_D = FOP(5, FMT_D),
6148: OPC_MOV_D = FOP(6, FMT_D),
6149: OPC_NEG_D = FOP(7, FMT_D),
6150: OPC_ROUND_L_D = FOP(8, FMT_D),
6151: OPC_TRUNC_L_D = FOP(9, FMT_D),
6152: OPC_CEIL_L_D = FOP(10, FMT_D),
6153: OPC_FLOOR_L_D = FOP(11, FMT_D),
6154: OPC_ROUND_W_D = FOP(12, FMT_D),
6155: OPC_TRUNC_W_D = FOP(13, FMT_D),
6156: OPC_CEIL_W_D = FOP(14, FMT_D),
6157: OPC_FLOOR_W_D = FOP(15, FMT_D),
6158: OPC_MOVCF_D = FOP(17, FMT_D),
6159: OPC_MOVZ_D = FOP(18, FMT_D),
6160: OPC_MOVN_D = FOP(19, FMT_D),
6161: OPC_RECIP_D = FOP(21, FMT_D),
6162: OPC_RSQRT_D = FOP(22, FMT_D),
6163: OPC_RECIP2_D = FOP(28, FMT_D),
6164: OPC_RECIP1_D = FOP(29, FMT_D),
6165: OPC_RSQRT1_D = FOP(30, FMT_D),
6166: OPC_RSQRT2_D = FOP(31, FMT_D),
6167: OPC_CVT_S_D = FOP(32, FMT_D),
6168: OPC_CVT_W_D = FOP(36, FMT_D),
6169: OPC_CVT_L_D = FOP(37, FMT_D),
6170: OPC_CMP_F_D = FOP (48, FMT_D),
6171: OPC_CMP_UN_D = FOP (49, FMT_D),
6172: OPC_CMP_EQ_D = FOP (50, FMT_D),
6173: OPC_CMP_UEQ_D = FOP (51, FMT_D),
6174: OPC_CMP_OLT_D = FOP (52, FMT_D),
6175: OPC_CMP_ULT_D = FOP (53, FMT_D),
6176: OPC_CMP_OLE_D = FOP (54, FMT_D),
6177: OPC_CMP_ULE_D = FOP (55, FMT_D),
6178: OPC_CMP_SF_D = FOP (56, FMT_D),
6179: OPC_CMP_NGLE_D = FOP (57, FMT_D),
6180: OPC_CMP_SEQ_D = FOP (58, FMT_D),
6181: OPC_CMP_NGL_D = FOP (59, FMT_D),
6182: OPC_CMP_LT_D = FOP (60, FMT_D),
6183: OPC_CMP_NGE_D = FOP (61, FMT_D),
6184: OPC_CMP_LE_D = FOP (62, FMT_D),
6185: OPC_CMP_NGT_D = FOP (63, FMT_D),
6186:
6187: OPC_CVT_S_W = FOP(32, FMT_W),
6188: OPC_CVT_D_W = FOP(33, FMT_W),
6189: OPC_CVT_S_L = FOP(32, FMT_L),
6190: OPC_CVT_D_L = FOP(33, FMT_L),
6191: OPC_CVT_PS_PW = FOP(38, FMT_W),
6192:
6193: OPC_ADD_PS = FOP(0, FMT_PS),
6194: OPC_SUB_PS = FOP(1, FMT_PS),
6195: OPC_MUL_PS = FOP(2, FMT_PS),
6196: OPC_DIV_PS = FOP(3, FMT_PS),
6197: OPC_ABS_PS = FOP(5, FMT_PS),
6198: OPC_MOV_PS = FOP(6, FMT_PS),
6199: OPC_NEG_PS = FOP(7, FMT_PS),
6200: OPC_MOVCF_PS = FOP(17, FMT_PS),
6201: OPC_MOVZ_PS = FOP(18, FMT_PS),
6202: OPC_MOVN_PS = FOP(19, FMT_PS),
6203: OPC_ADDR_PS = FOP(24, FMT_PS),
6204: OPC_MULR_PS = FOP(26, FMT_PS),
6205: OPC_RECIP2_PS = FOP(28, FMT_PS),
6206: OPC_RECIP1_PS = FOP(29, FMT_PS),
6207: OPC_RSQRT1_PS = FOP(30, FMT_PS),
6208: OPC_RSQRT2_PS = FOP(31, FMT_PS),
6209:
6210: OPC_CVT_S_PU = FOP(32, FMT_PS),
6211: OPC_CVT_PW_PS = FOP(36, FMT_PS),
6212: OPC_CVT_S_PL = FOP(40, FMT_PS),
6213: OPC_PLL_PS = FOP(44, FMT_PS),
6214: OPC_PLU_PS = FOP(45, FMT_PS),
6215: OPC_PUL_PS = FOP(46, FMT_PS),
6216: OPC_PUU_PS = FOP(47, FMT_PS),
6217: OPC_CMP_F_PS = FOP (48, FMT_PS),
6218: OPC_CMP_UN_PS = FOP (49, FMT_PS),
6219: OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6220: OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6221: OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6222: OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6223: OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6224: OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6225: OPC_CMP_SF_PS = FOP (56, FMT_PS),
6226: OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6227: OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6228: OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6229: OPC_CMP_LT_PS = FOP (60, FMT_PS),
6230: OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6231: OPC_CMP_LE_PS = FOP (62, FMT_PS),
6232: OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6233: };
6234:
1.1.1.5 root 6235: static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6236: {
1.1.1.6 root 6237: const char *opn = "cp1 move";
1.1.1.8 root 6238: TCGv t0 = tcg_temp_new();
1.1.1.5 root 6239:
6240: switch (opc) {
6241: case OPC_MFC1:
1.1.1.7 root 6242: {
6243: TCGv_i32 fp0 = tcg_temp_new_i32();
6244:
6245: gen_load_fpr32(fp0, fs);
6246: tcg_gen_ext_i32_tl(t0, fp0);
6247: tcg_temp_free_i32(fp0);
6248: }
6249: gen_store_gpr(t0, rt);
1.1.1.5 root 6250: opn = "mfc1";
6251: break;
6252: case OPC_MTC1:
1.1.1.7 root 6253: gen_load_gpr(t0, rt);
6254: {
6255: TCGv_i32 fp0 = tcg_temp_new_i32();
6256:
6257: tcg_gen_trunc_tl_i32(fp0, t0);
6258: gen_store_fpr32(fp0, fs);
6259: tcg_temp_free_i32(fp0);
6260: }
1.1.1.5 root 6261: opn = "mtc1";
6262: break;
6263: case OPC_CFC1:
1.1.1.7 root 6264: gen_helper_1i(cfc1, t0, fs);
6265: gen_store_gpr(t0, rt);
1.1.1.5 root 6266: opn = "cfc1";
6267: break;
6268: case OPC_CTC1:
1.1.1.7 root 6269: gen_load_gpr(t0, rt);
6270: gen_helper_1i(ctc1, t0, fs);
1.1.1.5 root 6271: opn = "ctc1";
6272: break;
1.1.1.8 root 6273: #if defined(TARGET_MIPS64)
1.1.1.5 root 6274: case OPC_DMFC1:
1.1.1.8 root 6275: gen_load_fpr64(ctx, t0, fs);
1.1.1.7 root 6276: gen_store_gpr(t0, rt);
1.1.1.6 root 6277: opn = "dmfc1";
6278: break;
1.1.1.5 root 6279: case OPC_DMTC1:
1.1.1.7 root 6280: gen_load_gpr(t0, rt);
1.1.1.8 root 6281: gen_store_fpr64(ctx, t0, fs);
1.1.1.6 root 6282: opn = "dmtc1";
6283: break;
1.1.1.8 root 6284: #endif
1.1.1.6 root 6285: case OPC_MFHC1:
1.1.1.7 root 6286: {
6287: TCGv_i32 fp0 = tcg_temp_new_i32();
6288:
6289: gen_load_fpr32h(fp0, fs);
6290: tcg_gen_ext_i32_tl(t0, fp0);
6291: tcg_temp_free_i32(fp0);
6292: }
6293: gen_store_gpr(t0, rt);
1.1.1.6 root 6294: opn = "mfhc1";
6295: break;
6296: case OPC_MTHC1:
1.1.1.7 root 6297: gen_load_gpr(t0, rt);
6298: {
6299: TCGv_i32 fp0 = tcg_temp_new_i32();
6300:
6301: tcg_gen_trunc_tl_i32(fp0, t0);
6302: gen_store_fpr32h(fp0, fs);
6303: tcg_temp_free_i32(fp0);
6304: }
1.1.1.6 root 6305: opn = "mthc1";
6306: break;
1.1.1.5 root 6307: default:
1.1.1.6 root 6308: MIPS_INVAL(opn);
6309: generate_exception (ctx, EXCP_RI);
1.1.1.7 root 6310: goto out;
1.1.1.4 root 6311: }
1.1.1.13! root 6312: (void)opn; /* avoid a compiler warning */
1.1.1.4 root 6313: MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
1.1.1.7 root 6314:
6315: out:
6316: tcg_temp_free(t0);
1.1.1.4 root 6317: }
6318:
1.1.1.6 root 6319: static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6320: {
1.1.1.8 root 6321: int l1;
1.1.1.7 root 6322: TCGCond cond;
1.1.1.8 root 6323: TCGv_i32 t0;
6324:
6325: if (rd == 0) {
6326: /* Treat as NOP. */
6327: return;
6328: }
1.1.1.7 root 6329:
6330: if (tf)
6331: cond = TCG_COND_EQ;
6332: else
6333: cond = TCG_COND_NE;
6334:
1.1.1.8 root 6335: l1 = gen_new_label();
6336: t0 = tcg_temp_new_i32();
6337: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6338: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6339: tcg_temp_free_i32(t0);
6340: if (rs == 0) {
6341: tcg_gen_movi_tl(cpu_gpr[rd], 0);
6342: } else {
6343: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6344: }
1.1.1.7 root 6345: gen_set_label(l1);
6346: }
6347:
6348: static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6349: {
6350: int cond;
1.1.1.8 root 6351: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 6352: int l1 = gen_new_label();
6353:
6354: if (tf)
6355: cond = TCG_COND_EQ;
6356: else
6357: cond = TCG_COND_NE;
6358:
1.1.1.8 root 6359: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6360: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6361: gen_load_fpr32(t0, fs);
6362: gen_store_fpr32(t0, fd);
1.1.1.7 root 6363: gen_set_label(l1);
1.1.1.8 root 6364: tcg_temp_free_i32(t0);
1.1.1.7 root 6365: }
6366:
6367: static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6368: {
6369: int cond;
1.1.1.8 root 6370: TCGv_i32 t0 = tcg_temp_new_i32();
6371: TCGv_i64 fp0;
1.1.1.7 root 6372: int l1 = gen_new_label();
6373:
6374: if (tf)
6375: cond = TCG_COND_EQ;
6376: else
6377: cond = TCG_COND_NE;
6378:
1.1.1.8 root 6379: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6380: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6381: tcg_temp_free_i32(t0);
6382: fp0 = tcg_temp_new_i64();
1.1.1.7 root 6383: gen_load_fpr64(ctx, fp0, fs);
6384: gen_store_fpr64(ctx, fp0, fd);
6385: tcg_temp_free_i64(fp0);
1.1.1.8 root 6386: gen_set_label(l1);
1.1.1.7 root 6387: }
6388:
6389: static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6390: {
6391: int cond;
1.1.1.8 root 6392: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 6393: int l1 = gen_new_label();
6394: int l2 = gen_new_label();
1.1.1.4 root 6395:
1.1.1.7 root 6396: if (tf)
6397: cond = TCG_COND_EQ;
1.1.1.6 root 6398: else
1.1.1.7 root 6399: cond = TCG_COND_NE;
6400:
1.1.1.8 root 6401: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6402: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6403: gen_load_fpr32(t0, fs);
6404: gen_store_fpr32(t0, fd);
1.1.1.7 root 6405: gen_set_label(l1);
6406:
1.1.1.8 root 6407: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
6408: tcg_gen_brcondi_i32(cond, t0, 0, l2);
6409: gen_load_fpr32h(t0, fs);
6410: gen_store_fpr32h(t0, fd);
6411: tcg_temp_free_i32(t0);
1.1.1.7 root 6412: gen_set_label(l2);
1.1.1.6 root 6413: }
6414:
1.1.1.4 root 6415:
1.1.1.12 root 6416: static void gen_farith (DisasContext *ctx, enum fopcode op1,
1.1.1.6 root 6417: int ft, int fs, int fd, int cc)
1.1.1.4 root 6418: {
1.1.1.6 root 6419: const char *opn = "farith";
1.1.1.4 root 6420: const char *condnames[] = {
6421: "c.f",
6422: "c.un",
6423: "c.eq",
6424: "c.ueq",
6425: "c.olt",
6426: "c.ult",
6427: "c.ole",
6428: "c.ule",
6429: "c.sf",
6430: "c.ngle",
6431: "c.seq",
6432: "c.ngl",
6433: "c.lt",
6434: "c.nge",
6435: "c.le",
6436: "c.ngt",
6437: };
1.1.1.6 root 6438: const char *condnames_abs[] = {
6439: "cabs.f",
6440: "cabs.un",
6441: "cabs.eq",
6442: "cabs.ueq",
6443: "cabs.olt",
6444: "cabs.ult",
6445: "cabs.ole",
6446: "cabs.ule",
6447: "cabs.sf",
6448: "cabs.ngle",
6449: "cabs.seq",
6450: "cabs.ngl",
6451: "cabs.lt",
6452: "cabs.nge",
6453: "cabs.le",
6454: "cabs.ngt",
6455: };
6456: enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
1.1.1.5 root 6457: uint32_t func = ctx->opcode & 0x3f;
6458:
1.1.1.12 root 6459: switch (op1) {
6460: case OPC_ADD_S:
1.1.1.7 root 6461: {
6462: TCGv_i32 fp0 = tcg_temp_new_i32();
6463: TCGv_i32 fp1 = tcg_temp_new_i32();
6464:
6465: gen_load_fpr32(fp0, fs);
6466: gen_load_fpr32(fp1, ft);
6467: gen_helper_float_add_s(fp0, fp0, fp1);
6468: tcg_temp_free_i32(fp1);
6469: gen_store_fpr32(fp0, fd);
6470: tcg_temp_free_i32(fp0);
6471: }
1.1.1.6 root 6472: opn = "add.s";
6473: optype = BINOP;
6474: break;
1.1.1.12 root 6475: case OPC_SUB_S:
1.1.1.7 root 6476: {
6477: TCGv_i32 fp0 = tcg_temp_new_i32();
6478: TCGv_i32 fp1 = tcg_temp_new_i32();
6479:
6480: gen_load_fpr32(fp0, fs);
6481: gen_load_fpr32(fp1, ft);
6482: gen_helper_float_sub_s(fp0, fp0, fp1);
6483: tcg_temp_free_i32(fp1);
6484: gen_store_fpr32(fp0, fd);
6485: tcg_temp_free_i32(fp0);
6486: }
1.1.1.6 root 6487: opn = "sub.s";
6488: optype = BINOP;
6489: break;
1.1.1.12 root 6490: case OPC_MUL_S:
1.1.1.7 root 6491: {
6492: TCGv_i32 fp0 = tcg_temp_new_i32();
6493: TCGv_i32 fp1 = tcg_temp_new_i32();
6494:
6495: gen_load_fpr32(fp0, fs);
6496: gen_load_fpr32(fp1, ft);
6497: gen_helper_float_mul_s(fp0, fp0, fp1);
6498: tcg_temp_free_i32(fp1);
6499: gen_store_fpr32(fp0, fd);
6500: tcg_temp_free_i32(fp0);
6501: }
1.1.1.6 root 6502: opn = "mul.s";
6503: optype = BINOP;
6504: break;
1.1.1.12 root 6505: case OPC_DIV_S:
1.1.1.7 root 6506: {
6507: TCGv_i32 fp0 = tcg_temp_new_i32();
6508: TCGv_i32 fp1 = tcg_temp_new_i32();
6509:
6510: gen_load_fpr32(fp0, fs);
6511: gen_load_fpr32(fp1, ft);
6512: gen_helper_float_div_s(fp0, fp0, fp1);
6513: tcg_temp_free_i32(fp1);
6514: gen_store_fpr32(fp0, fd);
6515: tcg_temp_free_i32(fp0);
6516: }
1.1.1.6 root 6517: opn = "div.s";
6518: optype = BINOP;
6519: break;
1.1.1.12 root 6520: case OPC_SQRT_S:
1.1.1.7 root 6521: {
6522: TCGv_i32 fp0 = tcg_temp_new_i32();
6523:
6524: gen_load_fpr32(fp0, fs);
6525: gen_helper_float_sqrt_s(fp0, fp0);
6526: gen_store_fpr32(fp0, fd);
6527: tcg_temp_free_i32(fp0);
6528: }
1.1.1.6 root 6529: opn = "sqrt.s";
6530: break;
1.1.1.12 root 6531: case OPC_ABS_S:
1.1.1.7 root 6532: {
6533: TCGv_i32 fp0 = tcg_temp_new_i32();
6534:
6535: gen_load_fpr32(fp0, fs);
6536: gen_helper_float_abs_s(fp0, fp0);
6537: gen_store_fpr32(fp0, fd);
6538: tcg_temp_free_i32(fp0);
6539: }
1.1.1.6 root 6540: opn = "abs.s";
6541: break;
1.1.1.12 root 6542: case OPC_MOV_S:
1.1.1.7 root 6543: {
6544: TCGv_i32 fp0 = tcg_temp_new_i32();
6545:
6546: gen_load_fpr32(fp0, fs);
6547: gen_store_fpr32(fp0, fd);
6548: tcg_temp_free_i32(fp0);
6549: }
1.1.1.6 root 6550: opn = "mov.s";
6551: break;
1.1.1.12 root 6552: case OPC_NEG_S:
1.1.1.7 root 6553: {
6554: TCGv_i32 fp0 = tcg_temp_new_i32();
6555:
6556: gen_load_fpr32(fp0, fs);
6557: gen_helper_float_chs_s(fp0, fp0);
6558: gen_store_fpr32(fp0, fd);
6559: tcg_temp_free_i32(fp0);
6560: }
1.1.1.6 root 6561: opn = "neg.s";
6562: break;
1.1.1.12 root 6563: case OPC_ROUND_L_S:
1.1.1.6 root 6564: check_cp1_64bitmode(ctx);
1.1.1.7 root 6565: {
6566: TCGv_i32 fp32 = tcg_temp_new_i32();
6567: TCGv_i64 fp64 = tcg_temp_new_i64();
6568:
6569: gen_load_fpr32(fp32, fs);
6570: gen_helper_float_roundl_s(fp64, fp32);
6571: tcg_temp_free_i32(fp32);
6572: gen_store_fpr64(ctx, fp64, fd);
6573: tcg_temp_free_i64(fp64);
6574: }
1.1.1.6 root 6575: opn = "round.l.s";
6576: break;
1.1.1.12 root 6577: case OPC_TRUNC_L_S:
1.1.1.6 root 6578: check_cp1_64bitmode(ctx);
1.1.1.7 root 6579: {
6580: TCGv_i32 fp32 = tcg_temp_new_i32();
6581: TCGv_i64 fp64 = tcg_temp_new_i64();
6582:
6583: gen_load_fpr32(fp32, fs);
6584: gen_helper_float_truncl_s(fp64, fp32);
6585: tcg_temp_free_i32(fp32);
6586: gen_store_fpr64(ctx, fp64, fd);
6587: tcg_temp_free_i64(fp64);
6588: }
1.1.1.6 root 6589: opn = "trunc.l.s";
6590: break;
1.1.1.12 root 6591: case OPC_CEIL_L_S:
1.1.1.6 root 6592: check_cp1_64bitmode(ctx);
1.1.1.7 root 6593: {
6594: TCGv_i32 fp32 = tcg_temp_new_i32();
6595: TCGv_i64 fp64 = tcg_temp_new_i64();
6596:
6597: gen_load_fpr32(fp32, fs);
6598: gen_helper_float_ceill_s(fp64, fp32);
6599: tcg_temp_free_i32(fp32);
6600: gen_store_fpr64(ctx, fp64, fd);
6601: tcg_temp_free_i64(fp64);
6602: }
1.1.1.6 root 6603: opn = "ceil.l.s";
6604: break;
1.1.1.12 root 6605: case OPC_FLOOR_L_S:
1.1.1.6 root 6606: check_cp1_64bitmode(ctx);
1.1.1.7 root 6607: {
6608: TCGv_i32 fp32 = tcg_temp_new_i32();
6609: TCGv_i64 fp64 = tcg_temp_new_i64();
6610:
6611: gen_load_fpr32(fp32, fs);
6612: gen_helper_float_floorl_s(fp64, fp32);
6613: tcg_temp_free_i32(fp32);
6614: gen_store_fpr64(ctx, fp64, fd);
6615: tcg_temp_free_i64(fp64);
6616: }
1.1.1.6 root 6617: opn = "floor.l.s";
6618: break;
1.1.1.12 root 6619: case OPC_ROUND_W_S:
1.1.1.7 root 6620: {
6621: TCGv_i32 fp0 = tcg_temp_new_i32();
6622:
6623: gen_load_fpr32(fp0, fs);
6624: gen_helper_float_roundw_s(fp0, fp0);
6625: gen_store_fpr32(fp0, fd);
6626: tcg_temp_free_i32(fp0);
6627: }
1.1.1.6 root 6628: opn = "round.w.s";
6629: break;
1.1.1.12 root 6630: case OPC_TRUNC_W_S:
1.1.1.7 root 6631: {
6632: TCGv_i32 fp0 = tcg_temp_new_i32();
6633:
6634: gen_load_fpr32(fp0, fs);
6635: gen_helper_float_truncw_s(fp0, fp0);
6636: gen_store_fpr32(fp0, fd);
6637: tcg_temp_free_i32(fp0);
6638: }
1.1.1.6 root 6639: opn = "trunc.w.s";
6640: break;
1.1.1.12 root 6641: case OPC_CEIL_W_S:
1.1.1.7 root 6642: {
6643: TCGv_i32 fp0 = tcg_temp_new_i32();
6644:
6645: gen_load_fpr32(fp0, fs);
6646: gen_helper_float_ceilw_s(fp0, fp0);
6647: gen_store_fpr32(fp0, fd);
6648: tcg_temp_free_i32(fp0);
6649: }
1.1.1.6 root 6650: opn = "ceil.w.s";
6651: break;
1.1.1.12 root 6652: case OPC_FLOOR_W_S:
1.1.1.7 root 6653: {
6654: TCGv_i32 fp0 = tcg_temp_new_i32();
6655:
6656: gen_load_fpr32(fp0, fs);
6657: gen_helper_float_floorw_s(fp0, fp0);
6658: gen_store_fpr32(fp0, fd);
6659: tcg_temp_free_i32(fp0);
6660: }
1.1.1.6 root 6661: opn = "floor.w.s";
6662: break;
1.1.1.12 root 6663: case OPC_MOVCF_S:
1.1.1.7 root 6664: gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 6665: opn = "movcf.s";
6666: break;
1.1.1.12 root 6667: case OPC_MOVZ_S:
1.1.1.7 root 6668: {
6669: int l1 = gen_new_label();
1.1.1.8 root 6670: TCGv_i32 fp0;
1.1.1.7 root 6671:
1.1.1.8 root 6672: if (ft != 0) {
6673: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6674: }
6675: fp0 = tcg_temp_new_i32();
1.1.1.7 root 6676: gen_load_fpr32(fp0, fs);
6677: gen_store_fpr32(fp0, fd);
6678: tcg_temp_free_i32(fp0);
6679: gen_set_label(l1);
6680: }
1.1.1.6 root 6681: opn = "movz.s";
6682: break;
1.1.1.12 root 6683: case OPC_MOVN_S:
1.1.1.7 root 6684: {
6685: int l1 = gen_new_label();
1.1.1.8 root 6686: TCGv_i32 fp0;
1.1.1.7 root 6687:
1.1.1.8 root 6688: if (ft != 0) {
6689: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6690: fp0 = tcg_temp_new_i32();
6691: gen_load_fpr32(fp0, fs);
6692: gen_store_fpr32(fp0, fd);
6693: tcg_temp_free_i32(fp0);
6694: gen_set_label(l1);
6695: }
1.1.1.7 root 6696: }
1.1.1.6 root 6697: opn = "movn.s";
6698: break;
1.1.1.12 root 6699: case OPC_RECIP_S:
1.1.1.6 root 6700: check_cop1x(ctx);
1.1.1.7 root 6701: {
6702: TCGv_i32 fp0 = tcg_temp_new_i32();
6703:
6704: gen_load_fpr32(fp0, fs);
6705: gen_helper_float_recip_s(fp0, fp0);
6706: gen_store_fpr32(fp0, fd);
6707: tcg_temp_free_i32(fp0);
6708: }
1.1.1.6 root 6709: opn = "recip.s";
6710: break;
1.1.1.12 root 6711: case OPC_RSQRT_S:
1.1.1.6 root 6712: check_cop1x(ctx);
1.1.1.7 root 6713: {
6714: TCGv_i32 fp0 = tcg_temp_new_i32();
6715:
6716: gen_load_fpr32(fp0, fs);
6717: gen_helper_float_rsqrt_s(fp0, fp0);
6718: gen_store_fpr32(fp0, fd);
6719: tcg_temp_free_i32(fp0);
6720: }
1.1.1.6 root 6721: opn = "rsqrt.s";
6722: break;
1.1.1.12 root 6723: case OPC_RECIP2_S:
1.1.1.6 root 6724: check_cp1_64bitmode(ctx);
1.1.1.7 root 6725: {
6726: TCGv_i32 fp0 = tcg_temp_new_i32();
6727: TCGv_i32 fp1 = tcg_temp_new_i32();
6728:
6729: gen_load_fpr32(fp0, fs);
6730: gen_load_fpr32(fp1, fd);
6731: gen_helper_float_recip2_s(fp0, fp0, fp1);
6732: tcg_temp_free_i32(fp1);
6733: gen_store_fpr32(fp0, fd);
6734: tcg_temp_free_i32(fp0);
6735: }
1.1.1.6 root 6736: opn = "recip2.s";
6737: break;
1.1.1.12 root 6738: case OPC_RECIP1_S:
1.1.1.6 root 6739: check_cp1_64bitmode(ctx);
1.1.1.7 root 6740: {
6741: TCGv_i32 fp0 = tcg_temp_new_i32();
6742:
6743: gen_load_fpr32(fp0, fs);
6744: gen_helper_float_recip1_s(fp0, fp0);
6745: gen_store_fpr32(fp0, fd);
6746: tcg_temp_free_i32(fp0);
6747: }
1.1.1.6 root 6748: opn = "recip1.s";
6749: break;
1.1.1.12 root 6750: case OPC_RSQRT1_S:
1.1.1.6 root 6751: check_cp1_64bitmode(ctx);
1.1.1.7 root 6752: {
6753: TCGv_i32 fp0 = tcg_temp_new_i32();
6754:
6755: gen_load_fpr32(fp0, fs);
6756: gen_helper_float_rsqrt1_s(fp0, fp0);
6757: gen_store_fpr32(fp0, fd);
6758: tcg_temp_free_i32(fp0);
6759: }
1.1.1.6 root 6760: opn = "rsqrt1.s";
6761: break;
1.1.1.12 root 6762: case OPC_RSQRT2_S:
1.1.1.6 root 6763: check_cp1_64bitmode(ctx);
1.1.1.7 root 6764: {
6765: TCGv_i32 fp0 = tcg_temp_new_i32();
6766: TCGv_i32 fp1 = tcg_temp_new_i32();
6767:
6768: gen_load_fpr32(fp0, fs);
6769: gen_load_fpr32(fp1, ft);
6770: gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6771: tcg_temp_free_i32(fp1);
6772: gen_store_fpr32(fp0, fd);
6773: tcg_temp_free_i32(fp0);
6774: }
1.1.1.6 root 6775: opn = "rsqrt2.s";
6776: break;
1.1.1.12 root 6777: case OPC_CVT_D_S:
1.1.1.6 root 6778: check_cp1_registers(ctx, fd);
1.1.1.7 root 6779: {
6780: TCGv_i32 fp32 = tcg_temp_new_i32();
6781: TCGv_i64 fp64 = tcg_temp_new_i64();
6782:
6783: gen_load_fpr32(fp32, fs);
6784: gen_helper_float_cvtd_s(fp64, fp32);
6785: tcg_temp_free_i32(fp32);
6786: gen_store_fpr64(ctx, fp64, fd);
6787: tcg_temp_free_i64(fp64);
6788: }
1.1.1.6 root 6789: opn = "cvt.d.s";
6790: break;
1.1.1.12 root 6791: case OPC_CVT_W_S:
1.1.1.7 root 6792: {
6793: TCGv_i32 fp0 = tcg_temp_new_i32();
6794:
6795: gen_load_fpr32(fp0, fs);
6796: gen_helper_float_cvtw_s(fp0, fp0);
6797: gen_store_fpr32(fp0, fd);
6798: tcg_temp_free_i32(fp0);
6799: }
1.1.1.6 root 6800: opn = "cvt.w.s";
6801: break;
1.1.1.12 root 6802: case OPC_CVT_L_S:
1.1.1.6 root 6803: check_cp1_64bitmode(ctx);
1.1.1.7 root 6804: {
6805: TCGv_i32 fp32 = tcg_temp_new_i32();
6806: TCGv_i64 fp64 = tcg_temp_new_i64();
6807:
6808: gen_load_fpr32(fp32, fs);
6809: gen_helper_float_cvtl_s(fp64, fp32);
6810: tcg_temp_free_i32(fp32);
6811: gen_store_fpr64(ctx, fp64, fd);
6812: tcg_temp_free_i64(fp64);
6813: }
1.1.1.6 root 6814: opn = "cvt.l.s";
6815: break;
1.1.1.12 root 6816: case OPC_CVT_PS_S:
1.1.1.6 root 6817: check_cp1_64bitmode(ctx);
1.1.1.7 root 6818: {
6819: TCGv_i64 fp64 = tcg_temp_new_i64();
6820: TCGv_i32 fp32_0 = tcg_temp_new_i32();
6821: TCGv_i32 fp32_1 = tcg_temp_new_i32();
6822:
6823: gen_load_fpr32(fp32_0, fs);
6824: gen_load_fpr32(fp32_1, ft);
6825: tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6826: tcg_temp_free_i32(fp32_1);
6827: tcg_temp_free_i32(fp32_0);
6828: gen_store_fpr64(ctx, fp64, fd);
6829: tcg_temp_free_i64(fp64);
6830: }
1.1.1.6 root 6831: opn = "cvt.ps.s";
6832: break;
1.1.1.12 root 6833: case OPC_CMP_F_S:
6834: case OPC_CMP_UN_S:
6835: case OPC_CMP_EQ_S:
6836: case OPC_CMP_UEQ_S:
6837: case OPC_CMP_OLT_S:
6838: case OPC_CMP_ULT_S:
6839: case OPC_CMP_OLE_S:
6840: case OPC_CMP_ULE_S:
6841: case OPC_CMP_SF_S:
6842: case OPC_CMP_NGLE_S:
6843: case OPC_CMP_SEQ_S:
6844: case OPC_CMP_NGL_S:
6845: case OPC_CMP_LT_S:
6846: case OPC_CMP_NGE_S:
6847: case OPC_CMP_LE_S:
6848: case OPC_CMP_NGT_S:
6849: if (ctx->opcode & (1 << 6)) {
6850: gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6851: opn = condnames_abs[func-48];
6852: } else {
6853: gen_cmp_s(ctx, func-48, ft, fs, cc);
6854: opn = condnames[func-48];
1.1.1.6 root 6855: }
6856: break;
1.1.1.12 root 6857: case OPC_ADD_D:
1.1.1.6 root 6858: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6859: {
6860: TCGv_i64 fp0 = tcg_temp_new_i64();
6861: TCGv_i64 fp1 = tcg_temp_new_i64();
6862:
6863: gen_load_fpr64(ctx, fp0, fs);
6864: gen_load_fpr64(ctx, fp1, ft);
6865: gen_helper_float_add_d(fp0, fp0, fp1);
6866: tcg_temp_free_i64(fp1);
6867: gen_store_fpr64(ctx, fp0, fd);
6868: tcg_temp_free_i64(fp0);
6869: }
1.1.1.4 root 6870: opn = "add.d";
1.1.1.6 root 6871: optype = BINOP;
1.1.1.4 root 6872: break;
1.1.1.12 root 6873: case OPC_SUB_D:
1.1.1.6 root 6874: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6875: {
6876: TCGv_i64 fp0 = tcg_temp_new_i64();
6877: TCGv_i64 fp1 = tcg_temp_new_i64();
6878:
6879: gen_load_fpr64(ctx, fp0, fs);
6880: gen_load_fpr64(ctx, fp1, ft);
6881: gen_helper_float_sub_d(fp0, fp0, fp1);
6882: tcg_temp_free_i64(fp1);
6883: gen_store_fpr64(ctx, fp0, fd);
6884: tcg_temp_free_i64(fp0);
6885: }
1.1.1.4 root 6886: opn = "sub.d";
1.1.1.6 root 6887: optype = BINOP;
1.1.1.4 root 6888: break;
1.1.1.12 root 6889: case OPC_MUL_D:
1.1.1.6 root 6890: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6891: {
6892: TCGv_i64 fp0 = tcg_temp_new_i64();
6893: TCGv_i64 fp1 = tcg_temp_new_i64();
6894:
6895: gen_load_fpr64(ctx, fp0, fs);
6896: gen_load_fpr64(ctx, fp1, ft);
6897: gen_helper_float_mul_d(fp0, fp0, fp1);
6898: tcg_temp_free_i64(fp1);
6899: gen_store_fpr64(ctx, fp0, fd);
6900: tcg_temp_free_i64(fp0);
6901: }
1.1.1.4 root 6902: opn = "mul.d";
1.1.1.6 root 6903: optype = BINOP;
1.1.1.4 root 6904: break;
1.1.1.12 root 6905: case OPC_DIV_D:
1.1.1.6 root 6906: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6907: {
6908: TCGv_i64 fp0 = tcg_temp_new_i64();
6909: TCGv_i64 fp1 = tcg_temp_new_i64();
6910:
6911: gen_load_fpr64(ctx, fp0, fs);
6912: gen_load_fpr64(ctx, fp1, ft);
6913: gen_helper_float_div_d(fp0, fp0, fp1);
6914: tcg_temp_free_i64(fp1);
6915: gen_store_fpr64(ctx, fp0, fd);
6916: tcg_temp_free_i64(fp0);
6917: }
1.1.1.4 root 6918: opn = "div.d";
1.1.1.6 root 6919: optype = BINOP;
1.1.1.4 root 6920: break;
1.1.1.12 root 6921: case OPC_SQRT_D:
1.1.1.6 root 6922: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6923: {
6924: TCGv_i64 fp0 = tcg_temp_new_i64();
6925:
6926: gen_load_fpr64(ctx, fp0, fs);
6927: gen_helper_float_sqrt_d(fp0, fp0);
6928: gen_store_fpr64(ctx, fp0, fd);
6929: tcg_temp_free_i64(fp0);
6930: }
1.1.1.4 root 6931: opn = "sqrt.d";
6932: break;
1.1.1.12 root 6933: case OPC_ABS_D:
1.1.1.6 root 6934: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6935: {
6936: TCGv_i64 fp0 = tcg_temp_new_i64();
6937:
6938: gen_load_fpr64(ctx, fp0, fs);
6939: gen_helper_float_abs_d(fp0, fp0);
6940: gen_store_fpr64(ctx, fp0, fd);
6941: tcg_temp_free_i64(fp0);
6942: }
1.1.1.4 root 6943: opn = "abs.d";
6944: break;
1.1.1.12 root 6945: case OPC_MOV_D:
1.1.1.6 root 6946: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6947: {
6948: TCGv_i64 fp0 = tcg_temp_new_i64();
6949:
6950: gen_load_fpr64(ctx, fp0, fs);
6951: gen_store_fpr64(ctx, fp0, fd);
6952: tcg_temp_free_i64(fp0);
6953: }
1.1.1.4 root 6954: opn = "mov.d";
6955: break;
1.1.1.12 root 6956: case OPC_NEG_D:
1.1.1.6 root 6957: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6958: {
6959: TCGv_i64 fp0 = tcg_temp_new_i64();
6960:
6961: gen_load_fpr64(ctx, fp0, fs);
6962: gen_helper_float_chs_d(fp0, fp0);
6963: gen_store_fpr64(ctx, fp0, fd);
6964: tcg_temp_free_i64(fp0);
6965: }
1.1.1.4 root 6966: opn = "neg.d";
6967: break;
1.1.1.12 root 6968: case OPC_ROUND_L_D:
1.1.1.6 root 6969: check_cp1_64bitmode(ctx);
1.1.1.7 root 6970: {
6971: TCGv_i64 fp0 = tcg_temp_new_i64();
6972:
6973: gen_load_fpr64(ctx, fp0, fs);
6974: gen_helper_float_roundl_d(fp0, fp0);
6975: gen_store_fpr64(ctx, fp0, fd);
6976: tcg_temp_free_i64(fp0);
6977: }
1.1.1.6 root 6978: opn = "round.l.d";
6979: break;
1.1.1.12 root 6980: case OPC_TRUNC_L_D:
1.1.1.6 root 6981: check_cp1_64bitmode(ctx);
1.1.1.7 root 6982: {
6983: TCGv_i64 fp0 = tcg_temp_new_i64();
6984:
6985: gen_load_fpr64(ctx, fp0, fs);
6986: gen_helper_float_truncl_d(fp0, fp0);
6987: gen_store_fpr64(ctx, fp0, fd);
6988: tcg_temp_free_i64(fp0);
6989: }
1.1.1.6 root 6990: opn = "trunc.l.d";
6991: break;
1.1.1.12 root 6992: case OPC_CEIL_L_D:
1.1.1.6 root 6993: check_cp1_64bitmode(ctx);
1.1.1.7 root 6994: {
6995: TCGv_i64 fp0 = tcg_temp_new_i64();
6996:
6997: gen_load_fpr64(ctx, fp0, fs);
6998: gen_helper_float_ceill_d(fp0, fp0);
6999: gen_store_fpr64(ctx, fp0, fd);
7000: tcg_temp_free_i64(fp0);
7001: }
1.1.1.6 root 7002: opn = "ceil.l.d";
7003: break;
1.1.1.12 root 7004: case OPC_FLOOR_L_D:
1.1.1.6 root 7005: check_cp1_64bitmode(ctx);
1.1.1.7 root 7006: {
7007: TCGv_i64 fp0 = tcg_temp_new_i64();
7008:
7009: gen_load_fpr64(ctx, fp0, fs);
7010: gen_helper_float_floorl_d(fp0, fp0);
7011: gen_store_fpr64(ctx, fp0, fd);
7012: tcg_temp_free_i64(fp0);
7013: }
1.1.1.6 root 7014: opn = "floor.l.d";
7015: break;
1.1.1.12 root 7016: case OPC_ROUND_W_D:
1.1.1.6 root 7017: check_cp1_registers(ctx, fs);
1.1.1.7 root 7018: {
7019: TCGv_i32 fp32 = tcg_temp_new_i32();
7020: TCGv_i64 fp64 = tcg_temp_new_i64();
7021:
7022: gen_load_fpr64(ctx, fp64, fs);
7023: gen_helper_float_roundw_d(fp32, fp64);
7024: tcg_temp_free_i64(fp64);
7025: gen_store_fpr32(fp32, fd);
7026: tcg_temp_free_i32(fp32);
7027: }
1.1.1.4 root 7028: opn = "round.w.d";
7029: break;
1.1.1.12 root 7030: case OPC_TRUNC_W_D:
1.1.1.6 root 7031: check_cp1_registers(ctx, fs);
1.1.1.7 root 7032: {
7033: TCGv_i32 fp32 = tcg_temp_new_i32();
7034: TCGv_i64 fp64 = tcg_temp_new_i64();
7035:
7036: gen_load_fpr64(ctx, fp64, fs);
7037: gen_helper_float_truncw_d(fp32, fp64);
7038: tcg_temp_free_i64(fp64);
7039: gen_store_fpr32(fp32, fd);
7040: tcg_temp_free_i32(fp32);
7041: }
1.1.1.4 root 7042: opn = "trunc.w.d";
7043: break;
1.1.1.12 root 7044: case OPC_CEIL_W_D:
1.1.1.6 root 7045: check_cp1_registers(ctx, fs);
1.1.1.7 root 7046: {
7047: TCGv_i32 fp32 = tcg_temp_new_i32();
7048: TCGv_i64 fp64 = tcg_temp_new_i64();
7049:
7050: gen_load_fpr64(ctx, fp64, fs);
7051: gen_helper_float_ceilw_d(fp32, fp64);
7052: tcg_temp_free_i64(fp64);
7053: gen_store_fpr32(fp32, fd);
7054: tcg_temp_free_i32(fp32);
7055: }
1.1.1.4 root 7056: opn = "ceil.w.d";
7057: break;
1.1.1.12 root 7058: case OPC_FLOOR_W_D:
1.1.1.6 root 7059: check_cp1_registers(ctx, fs);
1.1.1.7 root 7060: {
7061: TCGv_i32 fp32 = tcg_temp_new_i32();
7062: TCGv_i64 fp64 = tcg_temp_new_i64();
7063:
7064: gen_load_fpr64(ctx, fp64, fs);
7065: gen_helper_float_floorw_d(fp32, fp64);
7066: tcg_temp_free_i64(fp64);
7067: gen_store_fpr32(fp32, fd);
7068: tcg_temp_free_i32(fp32);
7069: }
1.1.1.5 root 7070: opn = "floor.w.d";
7071: break;
1.1.1.12 root 7072: case OPC_MOVCF_D:
1.1.1.7 root 7073: gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 7074: opn = "movcf.d";
1.1.1.4 root 7075: break;
1.1.1.12 root 7076: case OPC_MOVZ_D:
1.1.1.7 root 7077: {
7078: int l1 = gen_new_label();
1.1.1.8 root 7079: TCGv_i64 fp0;
1.1.1.7 root 7080:
1.1.1.8 root 7081: if (ft != 0) {
7082: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7083: }
7084: fp0 = tcg_temp_new_i64();
1.1.1.7 root 7085: gen_load_fpr64(ctx, fp0, fs);
7086: gen_store_fpr64(ctx, fp0, fd);
7087: tcg_temp_free_i64(fp0);
7088: gen_set_label(l1);
7089: }
1.1.1.6 root 7090: opn = "movz.d";
7091: break;
1.1.1.12 root 7092: case OPC_MOVN_D:
1.1.1.7 root 7093: {
7094: int l1 = gen_new_label();
1.1.1.8 root 7095: TCGv_i64 fp0;
1.1.1.7 root 7096:
1.1.1.8 root 7097: if (ft != 0) {
7098: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7099: fp0 = tcg_temp_new_i64();
7100: gen_load_fpr64(ctx, fp0, fs);
7101: gen_store_fpr64(ctx, fp0, fd);
7102: tcg_temp_free_i64(fp0);
7103: gen_set_label(l1);
7104: }
1.1.1.7 root 7105: }
1.1.1.6 root 7106: opn = "movn.d";
7107: break;
1.1.1.12 root 7108: case OPC_RECIP_D:
1.1.1.6 root 7109: check_cp1_64bitmode(ctx);
1.1.1.7 root 7110: {
7111: TCGv_i64 fp0 = tcg_temp_new_i64();
7112:
7113: gen_load_fpr64(ctx, fp0, fs);
7114: gen_helper_float_recip_d(fp0, fp0);
7115: gen_store_fpr64(ctx, fp0, fd);
7116: tcg_temp_free_i64(fp0);
7117: }
1.1.1.6 root 7118: opn = "recip.d";
7119: break;
1.1.1.12 root 7120: case OPC_RSQRT_D:
1.1.1.6 root 7121: check_cp1_64bitmode(ctx);
1.1.1.7 root 7122: {
7123: TCGv_i64 fp0 = tcg_temp_new_i64();
7124:
7125: gen_load_fpr64(ctx, fp0, fs);
7126: gen_helper_float_rsqrt_d(fp0, fp0);
7127: gen_store_fpr64(ctx, fp0, fd);
7128: tcg_temp_free_i64(fp0);
7129: }
1.1.1.6 root 7130: opn = "rsqrt.d";
7131: break;
1.1.1.12 root 7132: case OPC_RECIP2_D:
1.1.1.6 root 7133: check_cp1_64bitmode(ctx);
1.1.1.7 root 7134: {
7135: TCGv_i64 fp0 = tcg_temp_new_i64();
7136: TCGv_i64 fp1 = tcg_temp_new_i64();
7137:
7138: gen_load_fpr64(ctx, fp0, fs);
7139: gen_load_fpr64(ctx, fp1, ft);
7140: gen_helper_float_recip2_d(fp0, fp0, fp1);
7141: tcg_temp_free_i64(fp1);
7142: gen_store_fpr64(ctx, fp0, fd);
7143: tcg_temp_free_i64(fp0);
7144: }
1.1.1.6 root 7145: opn = "recip2.d";
7146: break;
1.1.1.12 root 7147: case OPC_RECIP1_D:
1.1.1.6 root 7148: check_cp1_64bitmode(ctx);
1.1.1.7 root 7149: {
7150: TCGv_i64 fp0 = tcg_temp_new_i64();
7151:
7152: gen_load_fpr64(ctx, fp0, fs);
7153: gen_helper_float_recip1_d(fp0, fp0);
7154: gen_store_fpr64(ctx, fp0, fd);
7155: tcg_temp_free_i64(fp0);
7156: }
1.1.1.6 root 7157: opn = "recip1.d";
7158: break;
1.1.1.12 root 7159: case OPC_RSQRT1_D:
1.1.1.6 root 7160: check_cp1_64bitmode(ctx);
1.1.1.7 root 7161: {
7162: TCGv_i64 fp0 = tcg_temp_new_i64();
7163:
7164: gen_load_fpr64(ctx, fp0, fs);
7165: gen_helper_float_rsqrt1_d(fp0, fp0);
7166: gen_store_fpr64(ctx, fp0, fd);
7167: tcg_temp_free_i64(fp0);
7168: }
1.1.1.6 root 7169: opn = "rsqrt1.d";
7170: break;
1.1.1.12 root 7171: case OPC_RSQRT2_D:
1.1.1.6 root 7172: check_cp1_64bitmode(ctx);
1.1.1.7 root 7173: {
7174: TCGv_i64 fp0 = tcg_temp_new_i64();
7175: TCGv_i64 fp1 = tcg_temp_new_i64();
7176:
7177: gen_load_fpr64(ctx, fp0, fs);
7178: gen_load_fpr64(ctx, fp1, ft);
7179: gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
7180: tcg_temp_free_i64(fp1);
7181: gen_store_fpr64(ctx, fp0, fd);
7182: tcg_temp_free_i64(fp0);
7183: }
1.1.1.6 root 7184: opn = "rsqrt2.d";
1.1.1.4 root 7185: break;
1.1.1.12 root 7186: case OPC_CMP_F_D:
7187: case OPC_CMP_UN_D:
7188: case OPC_CMP_EQ_D:
7189: case OPC_CMP_UEQ_D:
7190: case OPC_CMP_OLT_D:
7191: case OPC_CMP_ULT_D:
7192: case OPC_CMP_OLE_D:
7193: case OPC_CMP_ULE_D:
7194: case OPC_CMP_SF_D:
7195: case OPC_CMP_NGLE_D:
7196: case OPC_CMP_SEQ_D:
7197: case OPC_CMP_NGL_D:
7198: case OPC_CMP_LT_D:
7199: case OPC_CMP_NGE_D:
7200: case OPC_CMP_LE_D:
7201: case OPC_CMP_NGT_D:
7202: if (ctx->opcode & (1 << 6)) {
7203: gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7204: opn = condnames_abs[func-48];
7205: } else {
7206: gen_cmp_d(ctx, func-48, ft, fs, cc);
7207: opn = condnames[func-48];
1.1.1.6 root 7208: }
7209: break;
1.1.1.12 root 7210: case OPC_CVT_S_D:
1.1.1.6 root 7211: check_cp1_registers(ctx, fs);
1.1.1.7 root 7212: {
7213: TCGv_i32 fp32 = tcg_temp_new_i32();
7214: TCGv_i64 fp64 = tcg_temp_new_i64();
7215:
7216: gen_load_fpr64(ctx, fp64, fs);
7217: gen_helper_float_cvts_d(fp32, fp64);
7218: tcg_temp_free_i64(fp64);
7219: gen_store_fpr32(fp32, fd);
7220: tcg_temp_free_i32(fp32);
7221: }
1.1.1.6 root 7222: opn = "cvt.s.d";
7223: break;
1.1.1.12 root 7224: case OPC_CVT_W_D:
1.1.1.6 root 7225: check_cp1_registers(ctx, fs);
1.1.1.7 root 7226: {
7227: TCGv_i32 fp32 = tcg_temp_new_i32();
7228: TCGv_i64 fp64 = tcg_temp_new_i64();
7229:
7230: gen_load_fpr64(ctx, fp64, fs);
7231: gen_helper_float_cvtw_d(fp32, fp64);
7232: tcg_temp_free_i64(fp64);
7233: gen_store_fpr32(fp32, fd);
7234: tcg_temp_free_i32(fp32);
7235: }
1.1.1.6 root 7236: opn = "cvt.w.d";
7237: break;
1.1.1.12 root 7238: case OPC_CVT_L_D:
1.1.1.6 root 7239: check_cp1_64bitmode(ctx);
1.1.1.7 root 7240: {
7241: TCGv_i64 fp0 = tcg_temp_new_i64();
7242:
7243: gen_load_fpr64(ctx, fp0, fs);
7244: gen_helper_float_cvtl_d(fp0, fp0);
7245: gen_store_fpr64(ctx, fp0, fd);
7246: tcg_temp_free_i64(fp0);
7247: }
1.1.1.6 root 7248: opn = "cvt.l.d";
7249: break;
1.1.1.12 root 7250: case OPC_CVT_S_W:
1.1.1.7 root 7251: {
7252: TCGv_i32 fp0 = tcg_temp_new_i32();
7253:
7254: gen_load_fpr32(fp0, fs);
7255: gen_helper_float_cvts_w(fp0, fp0);
7256: gen_store_fpr32(fp0, fd);
7257: tcg_temp_free_i32(fp0);
7258: }
1.1.1.6 root 7259: opn = "cvt.s.w";
7260: break;
1.1.1.12 root 7261: case OPC_CVT_D_W:
1.1.1.6 root 7262: check_cp1_registers(ctx, fd);
1.1.1.7 root 7263: {
7264: TCGv_i32 fp32 = tcg_temp_new_i32();
7265: TCGv_i64 fp64 = tcg_temp_new_i64();
7266:
7267: gen_load_fpr32(fp32, fs);
7268: gen_helper_float_cvtd_w(fp64, fp32);
7269: tcg_temp_free_i32(fp32);
7270: gen_store_fpr64(ctx, fp64, fd);
7271: tcg_temp_free_i64(fp64);
7272: }
1.1.1.6 root 7273: opn = "cvt.d.w";
7274: break;
1.1.1.12 root 7275: case OPC_CVT_S_L:
1.1.1.6 root 7276: check_cp1_64bitmode(ctx);
1.1.1.7 root 7277: {
7278: TCGv_i32 fp32 = tcg_temp_new_i32();
7279: TCGv_i64 fp64 = tcg_temp_new_i64();
7280:
7281: gen_load_fpr64(ctx, fp64, fs);
7282: gen_helper_float_cvts_l(fp32, fp64);
7283: tcg_temp_free_i64(fp64);
7284: gen_store_fpr32(fp32, fd);
7285: tcg_temp_free_i32(fp32);
7286: }
1.1.1.6 root 7287: opn = "cvt.s.l";
7288: break;
1.1.1.12 root 7289: case OPC_CVT_D_L:
1.1.1.6 root 7290: check_cp1_64bitmode(ctx);
1.1.1.7 root 7291: {
7292: TCGv_i64 fp0 = tcg_temp_new_i64();
7293:
7294: gen_load_fpr64(ctx, fp0, fs);
7295: gen_helper_float_cvtd_l(fp0, fp0);
7296: gen_store_fpr64(ctx, fp0, fd);
7297: tcg_temp_free_i64(fp0);
7298: }
1.1.1.6 root 7299: opn = "cvt.d.l";
7300: break;
1.1.1.12 root 7301: case OPC_CVT_PS_PW:
1.1.1.6 root 7302: check_cp1_64bitmode(ctx);
1.1.1.7 root 7303: {
7304: TCGv_i64 fp0 = tcg_temp_new_i64();
7305:
7306: gen_load_fpr64(ctx, fp0, fs);
7307: gen_helper_float_cvtps_pw(fp0, fp0);
7308: gen_store_fpr64(ctx, fp0, fd);
7309: tcg_temp_free_i64(fp0);
7310: }
1.1.1.6 root 7311: opn = "cvt.ps.pw";
7312: break;
1.1.1.12 root 7313: case OPC_ADD_PS:
1.1.1.6 root 7314: check_cp1_64bitmode(ctx);
1.1.1.7 root 7315: {
7316: TCGv_i64 fp0 = tcg_temp_new_i64();
7317: TCGv_i64 fp1 = tcg_temp_new_i64();
7318:
7319: gen_load_fpr64(ctx, fp0, fs);
7320: gen_load_fpr64(ctx, fp1, ft);
7321: gen_helper_float_add_ps(fp0, fp0, fp1);
7322: tcg_temp_free_i64(fp1);
7323: gen_store_fpr64(ctx, fp0, fd);
7324: tcg_temp_free_i64(fp0);
7325: }
1.1.1.6 root 7326: opn = "add.ps";
7327: break;
1.1.1.12 root 7328: case OPC_SUB_PS:
1.1.1.6 root 7329: check_cp1_64bitmode(ctx);
1.1.1.7 root 7330: {
7331: TCGv_i64 fp0 = tcg_temp_new_i64();
7332: TCGv_i64 fp1 = tcg_temp_new_i64();
7333:
7334: gen_load_fpr64(ctx, fp0, fs);
7335: gen_load_fpr64(ctx, fp1, ft);
7336: gen_helper_float_sub_ps(fp0, fp0, fp1);
7337: tcg_temp_free_i64(fp1);
7338: gen_store_fpr64(ctx, fp0, fd);
7339: tcg_temp_free_i64(fp0);
7340: }
1.1.1.6 root 7341: opn = "sub.ps";
7342: break;
1.1.1.12 root 7343: case OPC_MUL_PS:
1.1.1.6 root 7344: check_cp1_64bitmode(ctx);
1.1.1.7 root 7345: {
7346: TCGv_i64 fp0 = tcg_temp_new_i64();
7347: TCGv_i64 fp1 = tcg_temp_new_i64();
7348:
7349: gen_load_fpr64(ctx, fp0, fs);
7350: gen_load_fpr64(ctx, fp1, ft);
7351: gen_helper_float_mul_ps(fp0, fp0, fp1);
7352: tcg_temp_free_i64(fp1);
7353: gen_store_fpr64(ctx, fp0, fd);
7354: tcg_temp_free_i64(fp0);
7355: }
1.1.1.6 root 7356: opn = "mul.ps";
7357: break;
1.1.1.12 root 7358: case OPC_ABS_PS:
1.1.1.6 root 7359: check_cp1_64bitmode(ctx);
1.1.1.7 root 7360: {
7361: TCGv_i64 fp0 = tcg_temp_new_i64();
7362:
7363: gen_load_fpr64(ctx, fp0, fs);
7364: gen_helper_float_abs_ps(fp0, fp0);
7365: gen_store_fpr64(ctx, fp0, fd);
7366: tcg_temp_free_i64(fp0);
7367: }
1.1.1.6 root 7368: opn = "abs.ps";
7369: break;
1.1.1.12 root 7370: case OPC_MOV_PS:
1.1.1.6 root 7371: check_cp1_64bitmode(ctx);
1.1.1.7 root 7372: {
7373: TCGv_i64 fp0 = tcg_temp_new_i64();
7374:
7375: gen_load_fpr64(ctx, fp0, fs);
7376: gen_store_fpr64(ctx, fp0, fd);
7377: tcg_temp_free_i64(fp0);
7378: }
1.1.1.6 root 7379: opn = "mov.ps";
7380: break;
1.1.1.12 root 7381: case OPC_NEG_PS:
1.1.1.6 root 7382: check_cp1_64bitmode(ctx);
1.1.1.7 root 7383: {
7384: TCGv_i64 fp0 = tcg_temp_new_i64();
7385:
7386: gen_load_fpr64(ctx, fp0, fs);
7387: gen_helper_float_chs_ps(fp0, fp0);
7388: gen_store_fpr64(ctx, fp0, fd);
7389: tcg_temp_free_i64(fp0);
7390: }
1.1.1.6 root 7391: opn = "neg.ps";
7392: break;
1.1.1.12 root 7393: case OPC_MOVCF_PS:
1.1.1.6 root 7394: check_cp1_64bitmode(ctx);
1.1.1.7 root 7395: gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 7396: opn = "movcf.ps";
7397: break;
1.1.1.12 root 7398: case OPC_MOVZ_PS:
1.1.1.6 root 7399: check_cp1_64bitmode(ctx);
1.1.1.7 root 7400: {
7401: int l1 = gen_new_label();
1.1.1.8 root 7402: TCGv_i64 fp0;
1.1.1.7 root 7403:
1.1.1.8 root 7404: if (ft != 0)
7405: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7406: fp0 = tcg_temp_new_i64();
7407: gen_load_fpr64(ctx, fp0, fs);
7408: gen_store_fpr64(ctx, fp0, fd);
7409: tcg_temp_free_i64(fp0);
1.1.1.7 root 7410: gen_set_label(l1);
7411: }
1.1.1.6 root 7412: opn = "movz.ps";
7413: break;
1.1.1.12 root 7414: case OPC_MOVN_PS:
1.1.1.6 root 7415: check_cp1_64bitmode(ctx);
1.1.1.7 root 7416: {
7417: int l1 = gen_new_label();
1.1.1.8 root 7418: TCGv_i64 fp0;
1.1.1.7 root 7419:
1.1.1.8 root 7420: if (ft != 0) {
7421: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7422: fp0 = tcg_temp_new_i64();
7423: gen_load_fpr64(ctx, fp0, fs);
7424: gen_store_fpr64(ctx, fp0, fd);
7425: tcg_temp_free_i64(fp0);
7426: gen_set_label(l1);
7427: }
1.1.1.7 root 7428: }
1.1.1.6 root 7429: opn = "movn.ps";
7430: break;
1.1.1.12 root 7431: case OPC_ADDR_PS:
1.1.1.6 root 7432: check_cp1_64bitmode(ctx);
1.1.1.7 root 7433: {
7434: TCGv_i64 fp0 = tcg_temp_new_i64();
7435: TCGv_i64 fp1 = tcg_temp_new_i64();
7436:
7437: gen_load_fpr64(ctx, fp0, ft);
7438: gen_load_fpr64(ctx, fp1, fs);
7439: gen_helper_float_addr_ps(fp0, fp0, fp1);
7440: tcg_temp_free_i64(fp1);
7441: gen_store_fpr64(ctx, fp0, fd);
7442: tcg_temp_free_i64(fp0);
7443: }
1.1.1.6 root 7444: opn = "addr.ps";
7445: break;
1.1.1.12 root 7446: case OPC_MULR_PS:
1.1.1.6 root 7447: check_cp1_64bitmode(ctx);
1.1.1.7 root 7448: {
7449: TCGv_i64 fp0 = tcg_temp_new_i64();
7450: TCGv_i64 fp1 = tcg_temp_new_i64();
7451:
7452: gen_load_fpr64(ctx, fp0, ft);
7453: gen_load_fpr64(ctx, fp1, fs);
7454: gen_helper_float_mulr_ps(fp0, fp0, fp1);
7455: tcg_temp_free_i64(fp1);
7456: gen_store_fpr64(ctx, fp0, fd);
7457: tcg_temp_free_i64(fp0);
7458: }
1.1.1.6 root 7459: opn = "mulr.ps";
7460: break;
1.1.1.12 root 7461: case OPC_RECIP2_PS:
1.1.1.6 root 7462: check_cp1_64bitmode(ctx);
1.1.1.7 root 7463: {
7464: TCGv_i64 fp0 = tcg_temp_new_i64();
7465: TCGv_i64 fp1 = tcg_temp_new_i64();
7466:
7467: gen_load_fpr64(ctx, fp0, fs);
7468: gen_load_fpr64(ctx, fp1, fd);
7469: gen_helper_float_recip2_ps(fp0, fp0, fp1);
7470: tcg_temp_free_i64(fp1);
7471: gen_store_fpr64(ctx, fp0, fd);
7472: tcg_temp_free_i64(fp0);
7473: }
1.1.1.6 root 7474: opn = "recip2.ps";
7475: break;
1.1.1.12 root 7476: case OPC_RECIP1_PS:
1.1.1.6 root 7477: check_cp1_64bitmode(ctx);
1.1.1.7 root 7478: {
7479: TCGv_i64 fp0 = tcg_temp_new_i64();
7480:
7481: gen_load_fpr64(ctx, fp0, fs);
7482: gen_helper_float_recip1_ps(fp0, fp0);
7483: gen_store_fpr64(ctx, fp0, fd);
7484: tcg_temp_free_i64(fp0);
7485: }
1.1.1.6 root 7486: opn = "recip1.ps";
7487: break;
1.1.1.12 root 7488: case OPC_RSQRT1_PS:
1.1.1.6 root 7489: check_cp1_64bitmode(ctx);
1.1.1.7 root 7490: {
7491: TCGv_i64 fp0 = tcg_temp_new_i64();
7492:
7493: gen_load_fpr64(ctx, fp0, fs);
7494: gen_helper_float_rsqrt1_ps(fp0, fp0);
7495: gen_store_fpr64(ctx, fp0, fd);
7496: tcg_temp_free_i64(fp0);
7497: }
1.1.1.6 root 7498: opn = "rsqrt1.ps";
7499: break;
1.1.1.12 root 7500: case OPC_RSQRT2_PS:
1.1.1.6 root 7501: check_cp1_64bitmode(ctx);
1.1.1.7 root 7502: {
7503: TCGv_i64 fp0 = tcg_temp_new_i64();
7504: TCGv_i64 fp1 = tcg_temp_new_i64();
7505:
7506: gen_load_fpr64(ctx, fp0, fs);
7507: gen_load_fpr64(ctx, fp1, ft);
7508: gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7509: tcg_temp_free_i64(fp1);
7510: gen_store_fpr64(ctx, fp0, fd);
7511: tcg_temp_free_i64(fp0);
7512: }
1.1.1.6 root 7513: opn = "rsqrt2.ps";
7514: break;
1.1.1.12 root 7515: case OPC_CVT_S_PU:
1.1.1.6 root 7516: check_cp1_64bitmode(ctx);
1.1.1.7 root 7517: {
7518: TCGv_i32 fp0 = tcg_temp_new_i32();
7519:
7520: gen_load_fpr32h(fp0, fs);
7521: gen_helper_float_cvts_pu(fp0, fp0);
7522: gen_store_fpr32(fp0, fd);
7523: tcg_temp_free_i32(fp0);
7524: }
1.1.1.6 root 7525: opn = "cvt.s.pu";
7526: break;
1.1.1.12 root 7527: case OPC_CVT_PW_PS:
1.1.1.6 root 7528: check_cp1_64bitmode(ctx);
1.1.1.7 root 7529: {
7530: TCGv_i64 fp0 = tcg_temp_new_i64();
7531:
7532: gen_load_fpr64(ctx, fp0, fs);
7533: gen_helper_float_cvtpw_ps(fp0, fp0);
7534: gen_store_fpr64(ctx, fp0, fd);
7535: tcg_temp_free_i64(fp0);
7536: }
1.1.1.6 root 7537: opn = "cvt.pw.ps";
1.1.1.4 root 7538: break;
1.1.1.12 root 7539: case OPC_CVT_S_PL:
1.1.1.6 root 7540: check_cp1_64bitmode(ctx);
1.1.1.7 root 7541: {
7542: TCGv_i32 fp0 = tcg_temp_new_i32();
7543:
7544: gen_load_fpr32(fp0, fs);
7545: gen_helper_float_cvts_pl(fp0, fp0);
7546: gen_store_fpr32(fp0, fd);
7547: tcg_temp_free_i32(fp0);
7548: }
1.1.1.6 root 7549: opn = "cvt.s.pl";
1.1.1.4 root 7550: break;
1.1.1.12 root 7551: case OPC_PLL_PS:
1.1.1.6 root 7552: check_cp1_64bitmode(ctx);
1.1.1.7 root 7553: {
7554: TCGv_i32 fp0 = tcg_temp_new_i32();
7555: TCGv_i32 fp1 = tcg_temp_new_i32();
7556:
7557: gen_load_fpr32(fp0, fs);
7558: gen_load_fpr32(fp1, ft);
7559: gen_store_fpr32h(fp0, fd);
7560: gen_store_fpr32(fp1, fd);
7561: tcg_temp_free_i32(fp0);
7562: tcg_temp_free_i32(fp1);
7563: }
1.1.1.6 root 7564: opn = "pll.ps";
1.1.1.4 root 7565: break;
1.1.1.12 root 7566: case OPC_PLU_PS:
1.1.1.6 root 7567: check_cp1_64bitmode(ctx);
1.1.1.7 root 7568: {
7569: TCGv_i32 fp0 = tcg_temp_new_i32();
7570: TCGv_i32 fp1 = tcg_temp_new_i32();
7571:
7572: gen_load_fpr32(fp0, fs);
7573: gen_load_fpr32h(fp1, ft);
7574: gen_store_fpr32(fp1, fd);
7575: gen_store_fpr32h(fp0, fd);
7576: tcg_temp_free_i32(fp0);
7577: tcg_temp_free_i32(fp1);
7578: }
1.1.1.6 root 7579: opn = "plu.ps";
7580: break;
1.1.1.12 root 7581: case OPC_PUL_PS:
1.1.1.6 root 7582: check_cp1_64bitmode(ctx);
1.1.1.7 root 7583: {
7584: TCGv_i32 fp0 = tcg_temp_new_i32();
7585: TCGv_i32 fp1 = tcg_temp_new_i32();
7586:
7587: gen_load_fpr32h(fp0, fs);
7588: gen_load_fpr32(fp1, ft);
7589: gen_store_fpr32(fp1, fd);
7590: gen_store_fpr32h(fp0, fd);
7591: tcg_temp_free_i32(fp0);
7592: tcg_temp_free_i32(fp1);
7593: }
1.1.1.6 root 7594: opn = "pul.ps";
1.1.1.4 root 7595: break;
1.1.1.12 root 7596: case OPC_PUU_PS:
1.1.1.6 root 7597: check_cp1_64bitmode(ctx);
1.1.1.7 root 7598: {
7599: TCGv_i32 fp0 = tcg_temp_new_i32();
7600: TCGv_i32 fp1 = tcg_temp_new_i32();
7601:
7602: gen_load_fpr32h(fp0, fs);
7603: gen_load_fpr32h(fp1, ft);
7604: gen_store_fpr32(fp1, fd);
7605: gen_store_fpr32h(fp0, fd);
7606: tcg_temp_free_i32(fp0);
7607: tcg_temp_free_i32(fp1);
7608: }
1.1.1.6 root 7609: opn = "puu.ps";
7610: break;
1.1.1.12 root 7611: case OPC_CMP_F_PS:
7612: case OPC_CMP_UN_PS:
7613: case OPC_CMP_EQ_PS:
7614: case OPC_CMP_UEQ_PS:
7615: case OPC_CMP_OLT_PS:
7616: case OPC_CMP_ULT_PS:
7617: case OPC_CMP_OLE_PS:
7618: case OPC_CMP_ULE_PS:
7619: case OPC_CMP_SF_PS:
7620: case OPC_CMP_NGLE_PS:
7621: case OPC_CMP_SEQ_PS:
7622: case OPC_CMP_NGL_PS:
7623: case OPC_CMP_LT_PS:
7624: case OPC_CMP_NGE_PS:
7625: case OPC_CMP_LE_PS:
7626: case OPC_CMP_NGT_PS:
7627: if (ctx->opcode & (1 << 6)) {
7628: gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7629: opn = condnames_abs[func-48];
7630: } else {
7631: gen_cmp_ps(ctx, func-48, ft, fs, cc);
7632: opn = condnames[func-48];
1.1.1.6 root 7633: }
1.1.1.4 root 7634: break;
1.1.1.6 root 7635: default:
7636: MIPS_INVAL(opn);
7637: generate_exception (ctx, EXCP_RI);
7638: return;
7639: }
1.1.1.13! root 7640: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 7641: switch (optype) {
7642: case BINOP:
7643: MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7644: break;
7645: case CMPOP:
7646: MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7647: break;
7648: default:
7649: MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7650: break;
7651: }
7652: }
7653:
7654: /* Coprocessor 3 (FPU) */
7655: static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7656: int fd, int fs, int base, int index)
7657: {
7658: const char *opn = "extended float load/store";
7659: int store = 0;
1.1.1.8 root 7660: TCGv t0 = tcg_temp_new();
1.1.1.6 root 7661:
7662: if (base == 0) {
1.1.1.7 root 7663: gen_load_gpr(t0, index);
1.1.1.6 root 7664: } else if (index == 0) {
1.1.1.7 root 7665: gen_load_gpr(t0, base);
1.1.1.6 root 7666: } else {
1.1.1.7 root 7667: gen_load_gpr(t0, index);
1.1.1.9 root 7668: gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
1.1.1.6 root 7669: }
7670: /* Don't do NOP if destination is zero: we must perform the actual
7671: memory access. */
1.1.1.8 root 7672: save_cpu_state(ctx, 0);
1.1.1.6 root 7673: switch (opc) {
7674: case OPC_LWXC1:
7675: check_cop1x(ctx);
1.1.1.7 root 7676: {
7677: TCGv_i32 fp0 = tcg_temp_new_i32();
7678:
1.1.1.8 root 7679: tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7680: tcg_gen_trunc_tl_i32(fp0, t0);
1.1.1.7 root 7681: gen_store_fpr32(fp0, fd);
7682: tcg_temp_free_i32(fp0);
7683: }
1.1.1.6 root 7684: opn = "lwxc1";
7685: break;
7686: case OPC_LDXC1:
7687: check_cop1x(ctx);
7688: check_cp1_registers(ctx, fd);
1.1.1.7 root 7689: {
7690: TCGv_i64 fp0 = tcg_temp_new_i64();
7691:
7692: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7693: gen_store_fpr64(ctx, fp0, fd);
7694: tcg_temp_free_i64(fp0);
7695: }
1.1.1.6 root 7696: opn = "ldxc1";
7697: break;
7698: case OPC_LUXC1:
7699: check_cp1_64bitmode(ctx);
1.1.1.7 root 7700: tcg_gen_andi_tl(t0, t0, ~0x7);
7701: {
7702: TCGv_i64 fp0 = tcg_temp_new_i64();
7703:
7704: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7705: gen_store_fpr64(ctx, fp0, fd);
7706: tcg_temp_free_i64(fp0);
7707: }
1.1.1.6 root 7708: opn = "luxc1";
7709: break;
7710: case OPC_SWXC1:
7711: check_cop1x(ctx);
1.1.1.7 root 7712: {
7713: TCGv_i32 fp0 = tcg_temp_new_i32();
1.1.1.8 root 7714: TCGv t1 = tcg_temp_new();
1.1.1.7 root 7715:
7716: gen_load_fpr32(fp0, fs);
7717: tcg_gen_extu_i32_tl(t1, fp0);
7718: tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7719: tcg_temp_free_i32(fp0);
1.1.1.8 root 7720: tcg_temp_free(t1);
1.1.1.7 root 7721: }
1.1.1.6 root 7722: opn = "swxc1";
7723: store = 1;
1.1.1.4 root 7724: break;
1.1.1.6 root 7725: case OPC_SDXC1:
7726: check_cop1x(ctx);
7727: check_cp1_registers(ctx, fs);
1.1.1.7 root 7728: {
7729: TCGv_i64 fp0 = tcg_temp_new_i64();
7730:
7731: gen_load_fpr64(ctx, fp0, fs);
7732: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7733: tcg_temp_free_i64(fp0);
7734: }
1.1.1.6 root 7735: opn = "sdxc1";
7736: store = 1;
7737: break;
7738: case OPC_SUXC1:
7739: check_cp1_64bitmode(ctx);
1.1.1.7 root 7740: tcg_gen_andi_tl(t0, t0, ~0x7);
7741: {
7742: TCGv_i64 fp0 = tcg_temp_new_i64();
7743:
7744: gen_load_fpr64(ctx, fp0, fs);
7745: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7746: tcg_temp_free_i64(fp0);
7747: }
1.1.1.6 root 7748: opn = "suxc1";
7749: store = 1;
7750: break;
7751: }
1.1.1.7 root 7752: tcg_temp_free(t0);
1.1.1.13! root 7753: (void)opn; (void)store; /* avoid compiler warnings */
1.1.1.6 root 7754: MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7755: regnames[index], regnames[base]);
7756: }
7757:
7758: static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7759: int fd, int fr, int fs, int ft)
7760: {
7761: const char *opn = "flt3_arith";
7762:
7763: switch (opc) {
7764: case OPC_ALNV_PS:
7765: check_cp1_64bitmode(ctx);
1.1.1.7 root 7766: {
7767: TCGv t0 = tcg_temp_local_new();
1.1.1.8 root 7768: TCGv_i32 fp = tcg_temp_new_i32();
7769: TCGv_i32 fph = tcg_temp_new_i32();
1.1.1.7 root 7770: int l1 = gen_new_label();
7771: int l2 = gen_new_label();
7772:
7773: gen_load_gpr(t0, fr);
7774: tcg_gen_andi_tl(t0, t0, 0x7);
7775:
7776: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
1.1.1.8 root 7777: gen_load_fpr32(fp, fs);
7778: gen_load_fpr32h(fph, fs);
7779: gen_store_fpr32(fp, fd);
7780: gen_store_fpr32h(fph, fd);
1.1.1.7 root 7781: tcg_gen_br(l2);
7782: gen_set_label(l1);
7783: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7784: tcg_temp_free(t0);
7785: #ifdef TARGET_WORDS_BIGENDIAN
1.1.1.8 root 7786: gen_load_fpr32(fp, fs);
7787: gen_load_fpr32h(fph, ft);
7788: gen_store_fpr32h(fp, fd);
7789: gen_store_fpr32(fph, fd);
1.1.1.7 root 7790: #else
1.1.1.8 root 7791: gen_load_fpr32h(fph, fs);
7792: gen_load_fpr32(fp, ft);
7793: gen_store_fpr32(fph, fd);
7794: gen_store_fpr32h(fp, fd);
1.1.1.7 root 7795: #endif
7796: gen_set_label(l2);
1.1.1.8 root 7797: tcg_temp_free_i32(fp);
7798: tcg_temp_free_i32(fph);
1.1.1.7 root 7799: }
1.1.1.6 root 7800: opn = "alnv.ps";
7801: break;
7802: case OPC_MADD_S:
7803: check_cop1x(ctx);
1.1.1.7 root 7804: {
7805: TCGv_i32 fp0 = tcg_temp_new_i32();
7806: TCGv_i32 fp1 = tcg_temp_new_i32();
7807: TCGv_i32 fp2 = tcg_temp_new_i32();
7808:
7809: gen_load_fpr32(fp0, fs);
7810: gen_load_fpr32(fp1, ft);
7811: gen_load_fpr32(fp2, fr);
7812: gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7813: tcg_temp_free_i32(fp0);
7814: tcg_temp_free_i32(fp1);
7815: gen_store_fpr32(fp2, fd);
7816: tcg_temp_free_i32(fp2);
7817: }
1.1.1.6 root 7818: opn = "madd.s";
1.1.1.4 root 7819: break;
1.1.1.6 root 7820: case OPC_MADD_D:
7821: check_cop1x(ctx);
7822: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7823: {
7824: TCGv_i64 fp0 = tcg_temp_new_i64();
7825: TCGv_i64 fp1 = tcg_temp_new_i64();
7826: TCGv_i64 fp2 = tcg_temp_new_i64();
7827:
7828: gen_load_fpr64(ctx, fp0, fs);
7829: gen_load_fpr64(ctx, fp1, ft);
7830: gen_load_fpr64(ctx, fp2, fr);
7831: gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7832: tcg_temp_free_i64(fp0);
7833: tcg_temp_free_i64(fp1);
7834: gen_store_fpr64(ctx, fp2, fd);
7835: tcg_temp_free_i64(fp2);
7836: }
1.1.1.6 root 7837: opn = "madd.d";
7838: break;
7839: case OPC_MADD_PS:
7840: check_cp1_64bitmode(ctx);
1.1.1.7 root 7841: {
7842: TCGv_i64 fp0 = tcg_temp_new_i64();
7843: TCGv_i64 fp1 = tcg_temp_new_i64();
7844: TCGv_i64 fp2 = tcg_temp_new_i64();
7845:
7846: gen_load_fpr64(ctx, fp0, fs);
7847: gen_load_fpr64(ctx, fp1, ft);
7848: gen_load_fpr64(ctx, fp2, fr);
7849: gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7850: tcg_temp_free_i64(fp0);
7851: tcg_temp_free_i64(fp1);
7852: gen_store_fpr64(ctx, fp2, fd);
7853: tcg_temp_free_i64(fp2);
7854: }
1.1.1.6 root 7855: opn = "madd.ps";
1.1.1.4 root 7856: break;
1.1.1.6 root 7857: case OPC_MSUB_S:
7858: check_cop1x(ctx);
1.1.1.7 root 7859: {
7860: TCGv_i32 fp0 = tcg_temp_new_i32();
7861: TCGv_i32 fp1 = tcg_temp_new_i32();
7862: TCGv_i32 fp2 = tcg_temp_new_i32();
7863:
7864: gen_load_fpr32(fp0, fs);
7865: gen_load_fpr32(fp1, ft);
7866: gen_load_fpr32(fp2, fr);
7867: gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7868: tcg_temp_free_i32(fp0);
7869: tcg_temp_free_i32(fp1);
7870: gen_store_fpr32(fp2, fd);
7871: tcg_temp_free_i32(fp2);
7872: }
1.1.1.6 root 7873: opn = "msub.s";
1.1.1.4 root 7874: break;
1.1.1.6 root 7875: case OPC_MSUB_D:
7876: check_cop1x(ctx);
7877: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7878: {
7879: TCGv_i64 fp0 = tcg_temp_new_i64();
7880: TCGv_i64 fp1 = tcg_temp_new_i64();
7881: TCGv_i64 fp2 = tcg_temp_new_i64();
7882:
7883: gen_load_fpr64(ctx, fp0, fs);
7884: gen_load_fpr64(ctx, fp1, ft);
7885: gen_load_fpr64(ctx, fp2, fr);
7886: gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7887: tcg_temp_free_i64(fp0);
7888: tcg_temp_free_i64(fp1);
7889: gen_store_fpr64(ctx, fp2, fd);
7890: tcg_temp_free_i64(fp2);
7891: }
1.1.1.6 root 7892: opn = "msub.d";
7893: break;
7894: case OPC_MSUB_PS:
7895: check_cp1_64bitmode(ctx);
1.1.1.7 root 7896: {
7897: TCGv_i64 fp0 = tcg_temp_new_i64();
7898: TCGv_i64 fp1 = tcg_temp_new_i64();
7899: TCGv_i64 fp2 = tcg_temp_new_i64();
7900:
7901: gen_load_fpr64(ctx, fp0, fs);
7902: gen_load_fpr64(ctx, fp1, ft);
7903: gen_load_fpr64(ctx, fp2, fr);
7904: gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7905: tcg_temp_free_i64(fp0);
7906: tcg_temp_free_i64(fp1);
7907: gen_store_fpr64(ctx, fp2, fd);
7908: tcg_temp_free_i64(fp2);
7909: }
1.1.1.6 root 7910: opn = "msub.ps";
1.1.1.4 root 7911: break;
1.1.1.6 root 7912: case OPC_NMADD_S:
7913: check_cop1x(ctx);
1.1.1.7 root 7914: {
7915: TCGv_i32 fp0 = tcg_temp_new_i32();
7916: TCGv_i32 fp1 = tcg_temp_new_i32();
7917: TCGv_i32 fp2 = tcg_temp_new_i32();
7918:
7919: gen_load_fpr32(fp0, fs);
7920: gen_load_fpr32(fp1, ft);
7921: gen_load_fpr32(fp2, fr);
7922: gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7923: tcg_temp_free_i32(fp0);
7924: tcg_temp_free_i32(fp1);
7925: gen_store_fpr32(fp2, fd);
7926: tcg_temp_free_i32(fp2);
7927: }
1.1.1.6 root 7928: opn = "nmadd.s";
1.1.1.4 root 7929: break;
1.1.1.6 root 7930: case OPC_NMADD_D:
7931: check_cop1x(ctx);
7932: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7933: {
7934: TCGv_i64 fp0 = tcg_temp_new_i64();
7935: TCGv_i64 fp1 = tcg_temp_new_i64();
7936: TCGv_i64 fp2 = tcg_temp_new_i64();
7937:
7938: gen_load_fpr64(ctx, fp0, fs);
7939: gen_load_fpr64(ctx, fp1, ft);
7940: gen_load_fpr64(ctx, fp2, fr);
7941: gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7942: tcg_temp_free_i64(fp0);
7943: tcg_temp_free_i64(fp1);
7944: gen_store_fpr64(ctx, fp2, fd);
7945: tcg_temp_free_i64(fp2);
7946: }
1.1.1.6 root 7947: opn = "nmadd.d";
1.1.1.5 root 7948: break;
1.1.1.6 root 7949: case OPC_NMADD_PS:
7950: check_cp1_64bitmode(ctx);
1.1.1.7 root 7951: {
7952: TCGv_i64 fp0 = tcg_temp_new_i64();
7953: TCGv_i64 fp1 = tcg_temp_new_i64();
7954: TCGv_i64 fp2 = tcg_temp_new_i64();
7955:
7956: gen_load_fpr64(ctx, fp0, fs);
7957: gen_load_fpr64(ctx, fp1, ft);
7958: gen_load_fpr64(ctx, fp2, fr);
7959: gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7960: tcg_temp_free_i64(fp0);
7961: tcg_temp_free_i64(fp1);
7962: gen_store_fpr64(ctx, fp2, fd);
7963: tcg_temp_free_i64(fp2);
7964: }
1.1.1.6 root 7965: opn = "nmadd.ps";
1.1.1.4 root 7966: break;
1.1.1.6 root 7967: case OPC_NMSUB_S:
7968: check_cop1x(ctx);
1.1.1.7 root 7969: {
7970: TCGv_i32 fp0 = tcg_temp_new_i32();
7971: TCGv_i32 fp1 = tcg_temp_new_i32();
7972: TCGv_i32 fp2 = tcg_temp_new_i32();
7973:
7974: gen_load_fpr32(fp0, fs);
7975: gen_load_fpr32(fp1, ft);
7976: gen_load_fpr32(fp2, fr);
7977: gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7978: tcg_temp_free_i32(fp0);
7979: tcg_temp_free_i32(fp1);
7980: gen_store_fpr32(fp2, fd);
7981: tcg_temp_free_i32(fp2);
7982: }
1.1.1.6 root 7983: opn = "nmsub.s";
1.1.1.4 root 7984: break;
1.1.1.6 root 7985: case OPC_NMSUB_D:
7986: check_cop1x(ctx);
7987: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7988: {
7989: TCGv_i64 fp0 = tcg_temp_new_i64();
7990: TCGv_i64 fp1 = tcg_temp_new_i64();
7991: TCGv_i64 fp2 = tcg_temp_new_i64();
7992:
7993: gen_load_fpr64(ctx, fp0, fs);
7994: gen_load_fpr64(ctx, fp1, ft);
7995: gen_load_fpr64(ctx, fp2, fr);
7996: gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7997: tcg_temp_free_i64(fp0);
7998: tcg_temp_free_i64(fp1);
7999: gen_store_fpr64(ctx, fp2, fd);
8000: tcg_temp_free_i64(fp2);
8001: }
1.1.1.6 root 8002: opn = "nmsub.d";
1.1.1.4 root 8003: break;
1.1.1.6 root 8004: case OPC_NMSUB_PS:
8005: check_cp1_64bitmode(ctx);
1.1.1.7 root 8006: {
8007: TCGv_i64 fp0 = tcg_temp_new_i64();
8008: TCGv_i64 fp1 = tcg_temp_new_i64();
8009: TCGv_i64 fp2 = tcg_temp_new_i64();
8010:
8011: gen_load_fpr64(ctx, fp0, fs);
8012: gen_load_fpr64(ctx, fp1, ft);
8013: gen_load_fpr64(ctx, fp2, fr);
8014: gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
8015: tcg_temp_free_i64(fp0);
8016: tcg_temp_free_i64(fp1);
8017: gen_store_fpr64(ctx, fp2, fd);
8018: tcg_temp_free_i64(fp2);
8019: }
1.1.1.6 root 8020: opn = "nmsub.ps";
1.1.1.4 root 8021: break;
1.1.1.6 root 8022: default:
8023: MIPS_INVAL(opn);
8024: generate_exception (ctx, EXCP_RI);
1.1.1.4 root 8025: return;
8026: }
1.1.1.13! root 8027: (void)opn; /* avoid a compiler warning */
1.1.1.6 root 8028: MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8029: fregnames[fs], fregnames[ft]);
1.1 root 8030: }
8031:
1.1.1.12 root 8032: static void
8033: gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
8034: {
8035: TCGv t0;
1.1 root 8036:
1.1.1.12 root 8037: check_insn(env, ctx, ISA_MIPS32R2);
8038: t0 = tcg_temp_new();
1.1 root 8039:
1.1.1.12 root 8040: switch (rd) {
8041: case 0:
8042: save_cpu_state(ctx, 1);
8043: gen_helper_rdhwr_cpunum(t0);
8044: gen_store_gpr(t0, rt);
8045: break;
8046: case 1:
8047: save_cpu_state(ctx, 1);
8048: gen_helper_rdhwr_synci_step(t0);
8049: gen_store_gpr(t0, rt);
8050: break;
8051: case 2:
8052: save_cpu_state(ctx, 1);
8053: gen_helper_rdhwr_cc(t0);
8054: gen_store_gpr(t0, rt);
8055: break;
8056: case 3:
8057: save_cpu_state(ctx, 1);
8058: gen_helper_rdhwr_ccres(t0);
8059: gen_store_gpr(t0, rt);
8060: break;
8061: case 29:
8062: #if defined(CONFIG_USER_ONLY)
8063: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
8064: gen_store_gpr(t0, rt);
8065: break;
8066: #else
8067: /* XXX: Some CPUs implement this in hardware.
8068: Not supported yet. */
1.1 root 8069: #endif
1.1.1.12 root 8070: default: /* Invalid */
8071: MIPS_INVAL("rdhwr");
8072: generate_exception(ctx, EXCP_RI);
8073: break;
1.1.1.4 root 8074: }
1.1.1.12 root 8075: tcg_temp_free(t0);
8076: }
1.1.1.4 root 8077:
1.1.1.12 root 8078: static void handle_delay_slot (CPUState *env, DisasContext *ctx,
8079: int insn_bytes)
8080: {
8081: if (ctx->hflags & MIPS_HFLAG_BMASK) {
8082: int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8083: /* Branches completion */
8084: ctx->hflags &= ~MIPS_HFLAG_BMASK;
8085: ctx->bstate = BS_BRANCH;
8086: save_cpu_state(ctx, 0);
8087: /* FIXME: Need to clear can_do_io. */
8088: switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
8089: case MIPS_HFLAG_B:
8090: /* unconditional branch */
8091: MIPS_DEBUG("unconditional branch");
8092: if (proc_hflags & MIPS_HFLAG_BX) {
8093: tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8094: }
8095: gen_goto_tb(ctx, 0, ctx->btarget);
8096: break;
8097: case MIPS_HFLAG_BL:
8098: /* blikely taken case */
8099: MIPS_DEBUG("blikely branch taken");
8100: gen_goto_tb(ctx, 0, ctx->btarget);
8101: break;
8102: case MIPS_HFLAG_BC:
8103: /* Conditional branch */
8104: MIPS_DEBUG("conditional branch");
8105: {
8106: int l1 = gen_new_label();
1.1.1.7 root 8107:
1.1.1.12 root 8108: tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8109: gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8110: gen_set_label(l1);
8111: gen_goto_tb(ctx, 0, ctx->btarget);
8112: }
8113: break;
8114: case MIPS_HFLAG_BR:
8115: /* unconditional branch to register */
8116: MIPS_DEBUG("branch to register");
8117: if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
8118: TCGv t0 = tcg_temp_new();
8119: TCGv_i32 t1 = tcg_temp_new_i32();
8120:
8121: tcg_gen_andi_tl(t0, btarget, 0x1);
8122: tcg_gen_trunc_tl_i32(t1, t0);
8123: tcg_temp_free(t0);
8124: tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8125: tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8126: tcg_gen_or_i32(hflags, hflags, t1);
8127: tcg_temp_free_i32(t1);
8128:
8129: tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8130: } else {
8131: tcg_gen_mov_tl(cpu_PC, btarget);
8132: }
8133: if (ctx->singlestep_enabled) {
8134: save_cpu_state(ctx, 0);
8135: gen_helper_0i(raise_exception, EXCP_DEBUG);
8136: }
8137: tcg_gen_exit_tb(0);
8138: break;
8139: default:
8140: MIPS_DEBUG("unknown branch");
8141: break;
8142: }
8143: }
8144: }
8145:
8146: /* ISA extensions (ASEs) */
8147: /* MIPS16 extension to MIPS32 */
8148:
8149: /* MIPS16 major opcodes */
8150: enum {
8151: M16_OPC_ADDIUSP = 0x00,
8152: M16_OPC_ADDIUPC = 0x01,
8153: M16_OPC_B = 0x02,
8154: M16_OPC_JAL = 0x03,
8155: M16_OPC_BEQZ = 0x04,
8156: M16_OPC_BNEQZ = 0x05,
8157: M16_OPC_SHIFT = 0x06,
8158: M16_OPC_LD = 0x07,
8159: M16_OPC_RRIA = 0x08,
8160: M16_OPC_ADDIU8 = 0x09,
8161: M16_OPC_SLTI = 0x0a,
8162: M16_OPC_SLTIU = 0x0b,
8163: M16_OPC_I8 = 0x0c,
8164: M16_OPC_LI = 0x0d,
8165: M16_OPC_CMPI = 0x0e,
8166: M16_OPC_SD = 0x0f,
8167: M16_OPC_LB = 0x10,
8168: M16_OPC_LH = 0x11,
8169: M16_OPC_LWSP = 0x12,
8170: M16_OPC_LW = 0x13,
8171: M16_OPC_LBU = 0x14,
8172: M16_OPC_LHU = 0x15,
8173: M16_OPC_LWPC = 0x16,
8174: M16_OPC_LWU = 0x17,
8175: M16_OPC_SB = 0x18,
8176: M16_OPC_SH = 0x19,
8177: M16_OPC_SWSP = 0x1a,
8178: M16_OPC_SW = 0x1b,
8179: M16_OPC_RRR = 0x1c,
8180: M16_OPC_RR = 0x1d,
8181: M16_OPC_EXTEND = 0x1e,
8182: M16_OPC_I64 = 0x1f
8183: };
8184:
8185: /* I8 funct field */
8186: enum {
8187: I8_BTEQZ = 0x0,
8188: I8_BTNEZ = 0x1,
8189: I8_SWRASP = 0x2,
8190: I8_ADJSP = 0x3,
8191: I8_SVRS = 0x4,
8192: I8_MOV32R = 0x5,
8193: I8_MOVR32 = 0x7
8194: };
8195:
8196: /* RRR f field */
8197: enum {
8198: RRR_DADDU = 0x0,
8199: RRR_ADDU = 0x1,
8200: RRR_DSUBU = 0x2,
8201: RRR_SUBU = 0x3
8202: };
8203:
8204: /* RR funct field */
8205: enum {
8206: RR_JR = 0x00,
8207: RR_SDBBP = 0x01,
8208: RR_SLT = 0x02,
8209: RR_SLTU = 0x03,
8210: RR_SLLV = 0x04,
8211: RR_BREAK = 0x05,
8212: RR_SRLV = 0x06,
8213: RR_SRAV = 0x07,
8214: RR_DSRL = 0x08,
8215: RR_CMP = 0x0a,
8216: RR_NEG = 0x0b,
8217: RR_AND = 0x0c,
8218: RR_OR = 0x0d,
8219: RR_XOR = 0x0e,
8220: RR_NOT = 0x0f,
8221: RR_MFHI = 0x10,
8222: RR_CNVT = 0x11,
8223: RR_MFLO = 0x12,
8224: RR_DSRA = 0x13,
8225: RR_DSLLV = 0x14,
8226: RR_DSRLV = 0x16,
8227: RR_DSRAV = 0x17,
8228: RR_MULT = 0x18,
8229: RR_MULTU = 0x19,
8230: RR_DIV = 0x1a,
8231: RR_DIVU = 0x1b,
8232: RR_DMULT = 0x1c,
8233: RR_DMULTU = 0x1d,
8234: RR_DDIV = 0x1e,
8235: RR_DDIVU = 0x1f
8236: };
8237:
8238: /* I64 funct field */
8239: enum {
8240: I64_LDSP = 0x0,
8241: I64_SDSP = 0x1,
8242: I64_SDRASP = 0x2,
8243: I64_DADJSP = 0x3,
8244: I64_LDPC = 0x4,
8245: I64_DADDIU5 = 0x5,
8246: I64_DADDIUPC = 0x6,
8247: I64_DADDIUSP = 0x7
8248: };
8249:
8250: /* RR ry field for CNVT */
8251: enum {
8252: RR_RY_CNVT_ZEB = 0x0,
8253: RR_RY_CNVT_ZEH = 0x1,
8254: RR_RY_CNVT_ZEW = 0x2,
8255: RR_RY_CNVT_SEB = 0x4,
8256: RR_RY_CNVT_SEH = 0x5,
8257: RR_RY_CNVT_SEW = 0x6,
8258: };
8259:
8260: static int xlat (int r)
8261: {
8262: static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8263:
8264: return map[r];
8265: }
8266:
8267: static void gen_mips16_save (DisasContext *ctx,
8268: int xsregs, int aregs,
8269: int do_ra, int do_s0, int do_s1,
8270: int framesize)
8271: {
8272: TCGv t0 = tcg_temp_new();
8273: TCGv t1 = tcg_temp_new();
8274: int args, astatic;
8275:
8276: switch (aregs) {
8277: case 0:
8278: case 1:
8279: case 2:
8280: case 3:
8281: case 11:
8282: args = 0;
8283: break;
8284: case 4:
8285: case 5:
8286: case 6:
8287: case 7:
8288: args = 1;
8289: break;
8290: case 8:
8291: case 9:
8292: case 10:
8293: args = 2;
8294: break;
8295: case 12:
8296: case 13:
8297: args = 3;
8298: break;
8299: case 14:
8300: args = 4;
8301: break;
8302: default:
8303: generate_exception(ctx, EXCP_RI);
8304: return;
8305: }
8306:
8307: switch (args) {
8308: case 4:
8309: gen_base_offset_addr(ctx, t0, 29, 12);
8310: gen_load_gpr(t1, 7);
8311: op_st_sw(t1, t0, ctx);
8312: /* Fall through */
8313: case 3:
8314: gen_base_offset_addr(ctx, t0, 29, 8);
8315: gen_load_gpr(t1, 6);
8316: op_st_sw(t1, t0, ctx);
8317: /* Fall through */
8318: case 2:
8319: gen_base_offset_addr(ctx, t0, 29, 4);
8320: gen_load_gpr(t1, 5);
8321: op_st_sw(t1, t0, ctx);
8322: /* Fall through */
8323: case 1:
8324: gen_base_offset_addr(ctx, t0, 29, 0);
8325: gen_load_gpr(t1, 4);
8326: op_st_sw(t1, t0, ctx);
8327: }
8328:
8329: gen_load_gpr(t0, 29);
8330:
8331: #define DECR_AND_STORE(reg) do { \
8332: tcg_gen_subi_tl(t0, t0, 4); \
8333: gen_load_gpr(t1, reg); \
8334: op_st_sw(t1, t0, ctx); \
8335: } while (0)
8336:
8337: if (do_ra) {
8338: DECR_AND_STORE(31);
8339: }
8340:
8341: switch (xsregs) {
8342: case 7:
8343: DECR_AND_STORE(30);
8344: /* Fall through */
8345: case 6:
8346: DECR_AND_STORE(23);
8347: /* Fall through */
8348: case 5:
8349: DECR_AND_STORE(22);
8350: /* Fall through */
8351: case 4:
8352: DECR_AND_STORE(21);
8353: /* Fall through */
8354: case 3:
8355: DECR_AND_STORE(20);
8356: /* Fall through */
8357: case 2:
8358: DECR_AND_STORE(19);
8359: /* Fall through */
8360: case 1:
8361: DECR_AND_STORE(18);
8362: }
8363:
8364: if (do_s1) {
8365: DECR_AND_STORE(17);
8366: }
8367: if (do_s0) {
8368: DECR_AND_STORE(16);
8369: }
8370:
8371: switch (aregs) {
8372: case 0:
8373: case 4:
8374: case 8:
8375: case 12:
8376: case 14:
8377: astatic = 0;
8378: break;
8379: case 1:
8380: case 5:
8381: case 9:
8382: case 13:
8383: astatic = 1;
8384: break;
8385: case 2:
8386: case 6:
8387: case 10:
8388: astatic = 2;
8389: break;
8390: case 3:
8391: case 7:
8392: astatic = 3;
8393: break;
8394: case 11:
8395: astatic = 4;
8396: break;
8397: default:
8398: generate_exception(ctx, EXCP_RI);
8399: return;
8400: }
8401:
8402: if (astatic > 0) {
8403: DECR_AND_STORE(7);
8404: if (astatic > 1) {
8405: DECR_AND_STORE(6);
8406: if (astatic > 2) {
8407: DECR_AND_STORE(5);
8408: if (astatic > 3) {
8409: DECR_AND_STORE(4);
8410: }
8411: }
8412: }
8413: }
8414: #undef DECR_AND_STORE
8415:
8416: tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8417: tcg_temp_free(t0);
8418: tcg_temp_free(t1);
8419: }
8420:
8421: static void gen_mips16_restore (DisasContext *ctx,
8422: int xsregs, int aregs,
8423: int do_ra, int do_s0, int do_s1,
8424: int framesize)
8425: {
8426: int astatic;
8427: TCGv t0 = tcg_temp_new();
8428: TCGv t1 = tcg_temp_new();
8429:
8430: tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8431:
8432: #define DECR_AND_LOAD(reg) do { \
8433: tcg_gen_subi_tl(t0, t0, 4); \
8434: op_ld_lw(t1, t0, ctx); \
8435: gen_store_gpr(t1, reg); \
8436: } while (0)
8437:
8438: if (do_ra) {
8439: DECR_AND_LOAD(31);
8440: }
8441:
8442: switch (xsregs) {
8443: case 7:
8444: DECR_AND_LOAD(30);
8445: /* Fall through */
8446: case 6:
8447: DECR_AND_LOAD(23);
8448: /* Fall through */
8449: case 5:
8450: DECR_AND_LOAD(22);
8451: /* Fall through */
8452: case 4:
8453: DECR_AND_LOAD(21);
8454: /* Fall through */
8455: case 3:
8456: DECR_AND_LOAD(20);
8457: /* Fall through */
8458: case 2:
8459: DECR_AND_LOAD(19);
8460: /* Fall through */
8461: case 1:
8462: DECR_AND_LOAD(18);
8463: }
8464:
8465: if (do_s1) {
8466: DECR_AND_LOAD(17);
8467: }
8468: if (do_s0) {
8469: DECR_AND_LOAD(16);
8470: }
8471:
8472: switch (aregs) {
8473: case 0:
8474: case 4:
8475: case 8:
8476: case 12:
8477: case 14:
8478: astatic = 0;
8479: break;
8480: case 1:
8481: case 5:
8482: case 9:
8483: case 13:
8484: astatic = 1;
8485: break;
8486: case 2:
8487: case 6:
8488: case 10:
8489: astatic = 2;
8490: break;
8491: case 3:
8492: case 7:
8493: astatic = 3;
8494: break;
8495: case 11:
8496: astatic = 4;
8497: break;
8498: default:
8499: generate_exception(ctx, EXCP_RI);
8500: return;
8501: }
8502:
8503: if (astatic > 0) {
8504: DECR_AND_LOAD(7);
8505: if (astatic > 1) {
8506: DECR_AND_LOAD(6);
8507: if (astatic > 2) {
8508: DECR_AND_LOAD(5);
8509: if (astatic > 3) {
8510: DECR_AND_LOAD(4);
8511: }
8512: }
8513: }
8514: }
8515: #undef DECR_AND_LOAD
8516:
8517: tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8518: tcg_temp_free(t0);
8519: tcg_temp_free(t1);
8520: }
8521:
8522: static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8523: int is_64_bit, int extended)
8524: {
8525: TCGv t0;
8526:
8527: if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8528: generate_exception(ctx, EXCP_RI);
8529: return;
8530: }
8531:
8532: t0 = tcg_temp_new();
8533:
8534: tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8535: tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8536: if (!is_64_bit) {
8537: tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8538: }
8539:
8540: tcg_temp_free(t0);
8541: }
8542:
8543: #if defined(TARGET_MIPS64)
8544: static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
8545: int ry, int funct, int16_t offset,
8546: int extended)
8547: {
8548: switch (funct) {
8549: case I64_LDSP:
8550: check_mips_64(ctx);
8551: offset = extended ? offset : offset << 3;
8552: gen_ld(env, ctx, OPC_LD, ry, 29, offset);
8553: break;
8554: case I64_SDSP:
8555: check_mips_64(ctx);
8556: offset = extended ? offset : offset << 3;
8557: gen_st(ctx, OPC_SD, ry, 29, offset);
8558: break;
8559: case I64_SDRASP:
8560: check_mips_64(ctx);
8561: offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8562: gen_st(ctx, OPC_SD, 31, 29, offset);
8563: break;
8564: case I64_DADJSP:
8565: check_mips_64(ctx);
8566: offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8567: gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8568: break;
8569: case I64_LDPC:
8570: if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8571: generate_exception(ctx, EXCP_RI);
8572: } else {
8573: offset = extended ? offset : offset << 3;
8574: gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
8575: }
8576: break;
8577: case I64_DADDIU5:
8578: check_mips_64(ctx);
8579: offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8580: gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8581: break;
8582: case I64_DADDIUPC:
8583: check_mips_64(ctx);
8584: offset = extended ? offset : offset << 2;
8585: gen_addiupc(ctx, ry, offset, 1, extended);
8586: break;
8587: case I64_DADDIUSP:
8588: check_mips_64(ctx);
8589: offset = extended ? offset : offset << 2;
8590: gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8591: break;
8592: }
8593: }
8594: #endif
8595:
8596: static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8597: int *is_branch)
8598: {
8599: int extend = lduw_code(ctx->pc + 2);
8600: int op, rx, ry, funct, sa;
8601: int16_t imm, offset;
8602:
8603: ctx->opcode = (ctx->opcode << 16) | extend;
8604: op = (ctx->opcode >> 11) & 0x1f;
8605: sa = (ctx->opcode >> 22) & 0x1f;
8606: funct = (ctx->opcode >> 8) & 0x7;
8607: rx = xlat((ctx->opcode >> 8) & 0x7);
8608: ry = xlat((ctx->opcode >> 5) & 0x7);
8609: offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8610: | ((ctx->opcode >> 21) & 0x3f) << 5
8611: | (ctx->opcode & 0x1f));
8612:
8613: /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8614: counterparts. */
8615: switch (op) {
8616: case M16_OPC_ADDIUSP:
8617: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8618: break;
8619: case M16_OPC_ADDIUPC:
8620: gen_addiupc(ctx, rx, imm, 0, 1);
8621: break;
8622: case M16_OPC_B:
8623: gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8624: /* No delay slot, so just process as a normal instruction */
8625: break;
8626: case M16_OPC_BEQZ:
8627: gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8628: /* No delay slot, so just process as a normal instruction */
8629: break;
8630: case M16_OPC_BNEQZ:
8631: gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8632: /* No delay slot, so just process as a normal instruction */
8633: break;
8634: case M16_OPC_SHIFT:
8635: switch (ctx->opcode & 0x3) {
8636: case 0x0:
8637: gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8638: break;
8639: case 0x1:
8640: #if defined(TARGET_MIPS64)
8641: check_mips_64(ctx);
8642: gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8643: #else
8644: generate_exception(ctx, EXCP_RI);
8645: #endif
8646: break;
8647: case 0x2:
8648: gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8649: break;
8650: case 0x3:
8651: gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8652: break;
8653: }
8654: break;
8655: #if defined(TARGET_MIPS64)
8656: case M16_OPC_LD:
8657: check_mips_64(ctx);
8658: gen_ld(env, ctx, OPC_LD, ry, rx, offset);
8659: break;
8660: #endif
8661: case M16_OPC_RRIA:
8662: imm = ctx->opcode & 0xf;
8663: imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8664: imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8665: imm = (int16_t) (imm << 1) >> 1;
8666: if ((ctx->opcode >> 4) & 0x1) {
8667: #if defined(TARGET_MIPS64)
8668: check_mips_64(ctx);
8669: gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8670: #else
8671: generate_exception(ctx, EXCP_RI);
8672: #endif
8673: } else {
8674: gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8675: }
8676: break;
8677: case M16_OPC_ADDIU8:
8678: gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8679: break;
8680: case M16_OPC_SLTI:
8681: gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8682: break;
8683: case M16_OPC_SLTIU:
8684: gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8685: break;
8686: case M16_OPC_I8:
8687: switch (funct) {
8688: case I8_BTEQZ:
8689: gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8690: break;
8691: case I8_BTNEZ:
8692: gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8693: break;
8694: case I8_SWRASP:
8695: gen_st(ctx, OPC_SW, 31, 29, imm);
8696: break;
8697: case I8_ADJSP:
8698: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8699: break;
8700: case I8_SVRS:
8701: {
8702: int xsregs = (ctx->opcode >> 24) & 0x7;
8703: int aregs = (ctx->opcode >> 16) & 0xf;
8704: int do_ra = (ctx->opcode >> 6) & 0x1;
8705: int do_s0 = (ctx->opcode >> 5) & 0x1;
8706: int do_s1 = (ctx->opcode >> 4) & 0x1;
8707: int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8708: | (ctx->opcode & 0xf)) << 3;
8709:
8710: if (ctx->opcode & (1 << 7)) {
8711: gen_mips16_save(ctx, xsregs, aregs,
8712: do_ra, do_s0, do_s1,
8713: framesize);
8714: } else {
8715: gen_mips16_restore(ctx, xsregs, aregs,
8716: do_ra, do_s0, do_s1,
8717: framesize);
8718: }
8719: }
8720: break;
8721: default:
8722: generate_exception(ctx, EXCP_RI);
8723: break;
8724: }
8725: break;
8726: case M16_OPC_LI:
8727: tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8728: break;
8729: case M16_OPC_CMPI:
8730: tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8731: break;
8732: #if defined(TARGET_MIPS64)
8733: case M16_OPC_SD:
8734: gen_st(ctx, OPC_SD, ry, rx, offset);
8735: break;
8736: #endif
8737: case M16_OPC_LB:
8738: gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8739: break;
8740: case M16_OPC_LH:
8741: gen_ld(env, ctx, OPC_LH, ry, rx, offset);
8742: break;
8743: case M16_OPC_LWSP:
8744: gen_ld(env, ctx, OPC_LW, rx, 29, offset);
8745: break;
8746: case M16_OPC_LW:
8747: gen_ld(env, ctx, OPC_LW, ry, rx, offset);
8748: break;
8749: case M16_OPC_LBU:
8750: gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
8751: break;
8752: case M16_OPC_LHU:
8753: gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
8754: break;
8755: case M16_OPC_LWPC:
8756: gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
8757: break;
8758: #if defined(TARGET_MIPS64)
8759: case M16_OPC_LWU:
8760: gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
8761: break;
8762: #endif
8763: case M16_OPC_SB:
8764: gen_st(ctx, OPC_SB, ry, rx, offset);
8765: break;
8766: case M16_OPC_SH:
8767: gen_st(ctx, OPC_SH, ry, rx, offset);
8768: break;
8769: case M16_OPC_SWSP:
8770: gen_st(ctx, OPC_SW, rx, 29, offset);
8771: break;
8772: case M16_OPC_SW:
8773: gen_st(ctx, OPC_SW, ry, rx, offset);
8774: break;
8775: #if defined(TARGET_MIPS64)
8776: case M16_OPC_I64:
8777: decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8778: break;
8779: #endif
8780: default:
8781: generate_exception(ctx, EXCP_RI);
8782: break;
8783: }
8784:
8785: return 4;
8786: }
8787:
8788: static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8789: int *is_branch)
8790: {
8791: int rx, ry;
8792: int sa;
8793: int op, cnvt_op, op1, offset;
8794: int funct;
8795: int n_bytes;
8796:
8797: op = (ctx->opcode >> 11) & 0x1f;
8798: sa = (ctx->opcode >> 2) & 0x7;
8799: sa = sa == 0 ? 8 : sa;
8800: rx = xlat((ctx->opcode >> 8) & 0x7);
8801: cnvt_op = (ctx->opcode >> 5) & 0x7;
8802: ry = xlat((ctx->opcode >> 5) & 0x7);
8803: op1 = offset = ctx->opcode & 0x1f;
8804:
8805: n_bytes = 2;
8806:
8807: switch (op) {
8808: case M16_OPC_ADDIUSP:
8809: {
8810: int16_t imm = ((uint8_t) ctx->opcode) << 2;
8811:
8812: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8813: }
8814: break;
8815: case M16_OPC_ADDIUPC:
8816: gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8817: break;
8818: case M16_OPC_B:
8819: offset = (ctx->opcode & 0x7ff) << 1;
8820: offset = (int16_t)(offset << 4) >> 4;
8821: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8822: /* No delay slot, so just process as a normal instruction */
8823: break;
8824: case M16_OPC_JAL:
8825: offset = lduw_code(ctx->pc + 2);
8826: offset = (((ctx->opcode & 0x1f) << 21)
8827: | ((ctx->opcode >> 5) & 0x1f) << 16
8828: | offset) << 2;
8829: op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
8830: gen_compute_branch(ctx, op, 4, rx, ry, offset);
8831: n_bytes = 4;
8832: *is_branch = 1;
8833: break;
8834: case M16_OPC_BEQZ:
8835: gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8836: /* No delay slot, so just process as a normal instruction */
8837: break;
8838: case M16_OPC_BNEQZ:
8839: gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8840: /* No delay slot, so just process as a normal instruction */
8841: break;
8842: case M16_OPC_SHIFT:
8843: switch (ctx->opcode & 0x3) {
8844: case 0x0:
8845: gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8846: break;
8847: case 0x1:
8848: #if defined(TARGET_MIPS64)
8849: check_mips_64(ctx);
8850: gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8851: #else
8852: generate_exception(ctx, EXCP_RI);
8853: #endif
8854: break;
8855: case 0x2:
8856: gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8857: break;
8858: case 0x3:
8859: gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8860: break;
8861: }
8862: break;
8863: #if defined(TARGET_MIPS64)
8864: case M16_OPC_LD:
8865: check_mips_64(ctx);
8866: gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
8867: break;
8868: #endif
8869: case M16_OPC_RRIA:
8870: {
8871: int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8872:
8873: if ((ctx->opcode >> 4) & 1) {
8874: #if defined(TARGET_MIPS64)
8875: check_mips_64(ctx);
8876: gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8877: #else
8878: generate_exception(ctx, EXCP_RI);
8879: #endif
8880: } else {
8881: gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8882: }
8883: }
8884: break;
8885: case M16_OPC_ADDIU8:
8886: {
8887: int16_t imm = (int8_t) ctx->opcode;
8888:
8889: gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8890: }
8891: break;
8892: case M16_OPC_SLTI:
8893: {
8894: int16_t imm = (uint8_t) ctx->opcode;
8895:
8896: gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8897: }
8898: break;
8899: case M16_OPC_SLTIU:
8900: {
8901: int16_t imm = (uint8_t) ctx->opcode;
8902:
8903: gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8904: }
8905: break;
8906: case M16_OPC_I8:
8907: {
8908: int reg32;
8909:
8910: funct = (ctx->opcode >> 8) & 0x7;
8911: switch (funct) {
8912: case I8_BTEQZ:
8913: gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8914: ((int8_t)ctx->opcode) << 1);
8915: break;
8916: case I8_BTNEZ:
8917: gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8918: ((int8_t)ctx->opcode) << 1);
8919: break;
8920: case I8_SWRASP:
8921: gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
8922: break;
8923: case I8_ADJSP:
8924: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
8925: ((int8_t)ctx->opcode) << 3);
8926: break;
8927: case I8_SVRS:
8928: {
8929: int do_ra = ctx->opcode & (1 << 6);
8930: int do_s0 = ctx->opcode & (1 << 5);
8931: int do_s1 = ctx->opcode & (1 << 4);
8932: int framesize = ctx->opcode & 0xf;
8933:
8934: if (framesize == 0) {
8935: framesize = 128;
8936: } else {
8937: framesize = framesize << 3;
8938: }
8939:
8940: if (ctx->opcode & (1 << 7)) {
8941: gen_mips16_save(ctx, 0, 0,
8942: do_ra, do_s0, do_s1, framesize);
8943: } else {
8944: gen_mips16_restore(ctx, 0, 0,
8945: do_ra, do_s0, do_s1, framesize);
8946: }
8947: }
8948: break;
8949: case I8_MOV32R:
8950: {
8951: int rz = xlat(ctx->opcode & 0x7);
8952:
8953: reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
8954: ((ctx->opcode >> 5) & 0x7);
8955: gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
8956: }
8957: break;
8958: case I8_MOVR32:
8959: reg32 = ctx->opcode & 0x1f;
8960: gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
8961: break;
8962: default:
8963: generate_exception(ctx, EXCP_RI);
8964: break;
8965: }
8966: }
8967: break;
8968: case M16_OPC_LI:
8969: {
8970: int16_t imm = (uint8_t) ctx->opcode;
8971:
8972: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
8973: }
8974: break;
8975: case M16_OPC_CMPI:
8976: {
8977: int16_t imm = (uint8_t) ctx->opcode;
8978:
8979: gen_logic_imm(env, OPC_XORI, 24, rx, imm);
8980: }
8981: break;
8982: #if defined(TARGET_MIPS64)
8983: case M16_OPC_SD:
8984: check_mips_64(ctx);
8985: gen_st(ctx, OPC_SD, ry, rx, offset << 3);
8986: break;
8987: #endif
8988: case M16_OPC_LB:
8989: gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8990: break;
8991: case M16_OPC_LH:
8992: gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
8993: break;
8994: case M16_OPC_LWSP:
8995: gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8996: break;
8997: case M16_OPC_LW:
8998: gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
8999: break;
9000: case M16_OPC_LBU:
9001: gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
9002: break;
9003: case M16_OPC_LHU:
9004: gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
9005: break;
9006: case M16_OPC_LWPC:
9007: gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
9008: break;
9009: #if defined (TARGET_MIPS64)
9010: case M16_OPC_LWU:
9011: check_mips_64(ctx);
9012: gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
9013: break;
9014: #endif
9015: case M16_OPC_SB:
9016: gen_st(ctx, OPC_SB, ry, rx, offset);
9017: break;
9018: case M16_OPC_SH:
9019: gen_st(ctx, OPC_SH, ry, rx, offset << 1);
9020: break;
9021: case M16_OPC_SWSP:
9022: gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9023: break;
9024: case M16_OPC_SW:
9025: gen_st(ctx, OPC_SW, ry, rx, offset << 2);
9026: break;
9027: case M16_OPC_RRR:
9028: {
9029: int rz = xlat((ctx->opcode >> 2) & 0x7);
9030: int mips32_op;
9031:
9032: switch (ctx->opcode & 0x3) {
9033: case RRR_ADDU:
9034: mips32_op = OPC_ADDU;
9035: break;
9036: case RRR_SUBU:
9037: mips32_op = OPC_SUBU;
9038: break;
9039: #if defined(TARGET_MIPS64)
9040: case RRR_DADDU:
9041: mips32_op = OPC_DADDU;
9042: check_mips_64(ctx);
9043: break;
9044: case RRR_DSUBU:
9045: mips32_op = OPC_DSUBU;
9046: check_mips_64(ctx);
9047: break;
9048: #endif
9049: default:
9050: generate_exception(ctx, EXCP_RI);
9051: goto done;
9052: }
9053:
9054: gen_arith(env, ctx, mips32_op, rz, rx, ry);
9055: done:
9056: ;
9057: }
9058: break;
9059: case M16_OPC_RR:
9060: switch (op1) {
9061: case RR_JR:
9062: {
9063: int nd = (ctx->opcode >> 7) & 0x1;
9064: int link = (ctx->opcode >> 6) & 0x1;
9065: int ra = (ctx->opcode >> 5) & 0x1;
9066:
9067: if (link) {
9068: op = nd ? OPC_JALRC : OPC_JALRS;
9069: } else {
9070: op = OPC_JR;
9071: }
9072:
9073: gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9074: if (!nd) {
9075: *is_branch = 1;
9076: }
9077: }
9078: break;
9079: case RR_SDBBP:
9080: /* XXX: not clear which exception should be raised
9081: * when in debug mode...
9082: */
9083: check_insn(env, ctx, ISA_MIPS32);
9084: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9085: generate_exception(ctx, EXCP_DBp);
9086: } else {
9087: generate_exception(ctx, EXCP_DBp);
9088: }
9089: break;
9090: case RR_SLT:
9091: gen_slt(env, OPC_SLT, 24, rx, ry);
9092: break;
9093: case RR_SLTU:
9094: gen_slt(env, OPC_SLTU, 24, rx, ry);
9095: break;
9096: case RR_BREAK:
9097: generate_exception(ctx, EXCP_BREAK);
9098: break;
9099: case RR_SLLV:
9100: gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9101: break;
9102: case RR_SRLV:
9103: gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9104: break;
9105: case RR_SRAV:
9106: gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9107: break;
9108: #if defined (TARGET_MIPS64)
9109: case RR_DSRL:
9110: check_mips_64(ctx);
9111: gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9112: break;
9113: #endif
9114: case RR_CMP:
9115: gen_logic(env, OPC_XOR, 24, rx, ry);
9116: break;
9117: case RR_NEG:
9118: gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9119: break;
9120: case RR_AND:
9121: gen_logic(env, OPC_AND, rx, rx, ry);
9122: break;
9123: case RR_OR:
9124: gen_logic(env, OPC_OR, rx, rx, ry);
9125: break;
9126: case RR_XOR:
9127: gen_logic(env, OPC_XOR, rx, rx, ry);
9128: break;
9129: case RR_NOT:
9130: gen_logic(env, OPC_NOR, rx, ry, 0);
9131: break;
9132: case RR_MFHI:
9133: gen_HILO(ctx, OPC_MFHI, rx);
9134: break;
9135: case RR_CNVT:
9136: switch (cnvt_op) {
9137: case RR_RY_CNVT_ZEB:
9138: tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9139: break;
9140: case RR_RY_CNVT_ZEH:
9141: tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9142: break;
9143: case RR_RY_CNVT_SEB:
9144: tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9145: break;
9146: case RR_RY_CNVT_SEH:
9147: tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9148: break;
9149: #if defined (TARGET_MIPS64)
9150: case RR_RY_CNVT_ZEW:
9151: check_mips_64(ctx);
9152: tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9153: break;
9154: case RR_RY_CNVT_SEW:
9155: check_mips_64(ctx);
9156: tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9157: break;
9158: #endif
9159: default:
9160: generate_exception(ctx, EXCP_RI);
9161: break;
9162: }
9163: break;
9164: case RR_MFLO:
9165: gen_HILO(ctx, OPC_MFLO, rx);
9166: break;
9167: #if defined (TARGET_MIPS64)
9168: case RR_DSRA:
9169: check_mips_64(ctx);
9170: gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9171: break;
9172: case RR_DSLLV:
9173: check_mips_64(ctx);
9174: gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9175: break;
9176: case RR_DSRLV:
9177: check_mips_64(ctx);
9178: gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9179: break;
9180: case RR_DSRAV:
9181: check_mips_64(ctx);
9182: gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9183: break;
9184: #endif
9185: case RR_MULT:
9186: gen_muldiv(ctx, OPC_MULT, rx, ry);
9187: break;
9188: case RR_MULTU:
9189: gen_muldiv(ctx, OPC_MULTU, rx, ry);
9190: break;
9191: case RR_DIV:
9192: gen_muldiv(ctx, OPC_DIV, rx, ry);
9193: break;
9194: case RR_DIVU:
9195: gen_muldiv(ctx, OPC_DIVU, rx, ry);
9196: break;
9197: #if defined (TARGET_MIPS64)
9198: case RR_DMULT:
9199: check_mips_64(ctx);
9200: gen_muldiv(ctx, OPC_DMULT, rx, ry);
9201: break;
9202: case RR_DMULTU:
9203: check_mips_64(ctx);
9204: gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9205: break;
9206: case RR_DDIV:
9207: check_mips_64(ctx);
9208: gen_muldiv(ctx, OPC_DDIV, rx, ry);
9209: break;
9210: case RR_DDIVU:
9211: check_mips_64(ctx);
9212: gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9213: break;
9214: #endif
9215: default:
9216: generate_exception(ctx, EXCP_RI);
9217: break;
9218: }
9219: break;
9220: case M16_OPC_EXTEND:
9221: decode_extended_mips16_opc(env, ctx, is_branch);
9222: n_bytes = 4;
9223: break;
9224: #if defined(TARGET_MIPS64)
9225: case M16_OPC_I64:
9226: funct = (ctx->opcode >> 8) & 0x7;
9227: decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9228: break;
9229: #endif
9230: default:
9231: generate_exception(ctx, EXCP_RI);
9232: break;
9233: }
9234:
9235: return n_bytes;
9236: }
9237:
9238: /* microMIPS extension to MIPS32 */
9239:
9240: /* microMIPS32 major opcodes */
9241:
9242: enum {
9243: POOL32A = 0x00,
9244: POOL16A = 0x01,
9245: LBU16 = 0x02,
9246: MOVE16 = 0x03,
9247: ADDI32 = 0x04,
9248: LBU32 = 0x05,
9249: SB32 = 0x06,
9250: LB32 = 0x07,
9251:
9252: POOL32B = 0x08,
9253: POOL16B = 0x09,
9254: LHU16 = 0x0a,
9255: ANDI16 = 0x0b,
9256: ADDIU32 = 0x0c,
9257: LHU32 = 0x0d,
9258: SH32 = 0x0e,
9259: LH32 = 0x0f,
9260:
9261: POOL32I = 0x10,
9262: POOL16C = 0x11,
9263: LWSP16 = 0x12,
9264: POOL16D = 0x13,
9265: ORI32 = 0x14,
9266: POOL32F = 0x15,
9267: POOL32S = 0x16,
9268: DADDIU32 = 0x17,
9269:
9270: POOL32C = 0x18,
9271: LWGP16 = 0x19,
9272: LW16 = 0x1a,
9273: POOL16E = 0x1b,
9274: XORI32 = 0x1c,
9275: JALS32 = 0x1d,
9276: ADDIUPC = 0x1e,
9277: POOL48A = 0x1f,
9278:
9279: /* 0x20 is reserved */
9280: RES_20 = 0x20,
9281: POOL16F = 0x21,
9282: SB16 = 0x22,
9283: BEQZ16 = 0x23,
9284: SLTI32 = 0x24,
9285: BEQ32 = 0x25,
9286: SWC132 = 0x26,
9287: LWC132 = 0x27,
9288:
9289: /* 0x28 and 0x29 are reserved */
9290: RES_28 = 0x28,
9291: RES_29 = 0x29,
9292: SH16 = 0x2a,
9293: BNEZ16 = 0x2b,
9294: SLTIU32 = 0x2c,
9295: BNE32 = 0x2d,
9296: SDC132 = 0x2e,
9297: LDC132 = 0x2f,
9298:
9299: /* 0x30 and 0x31 are reserved */
9300: RES_30 = 0x30,
9301: RES_31 = 0x31,
9302: SWSP16 = 0x32,
9303: B16 = 0x33,
9304: ANDI32 = 0x34,
9305: J32 = 0x35,
9306: SD32 = 0x36,
9307: LD32 = 0x37,
9308:
9309: /* 0x38 and 0x39 are reserved */
9310: RES_38 = 0x38,
9311: RES_39 = 0x39,
9312: SW16 = 0x3a,
9313: LI16 = 0x3b,
9314: JALX32 = 0x3c,
9315: JAL32 = 0x3d,
9316: SW32 = 0x3e,
9317: LW32 = 0x3f
9318: };
9319:
9320: /* POOL32A encoding of minor opcode field */
9321:
9322: enum {
9323: /* These opcodes are distinguished only by bits 9..6; those bits are
9324: * what are recorded below. */
9325: SLL32 = 0x0,
9326: SRL32 = 0x1,
9327: SRA = 0x2,
9328: ROTR = 0x3,
9329:
9330: SLLV = 0x0,
9331: SRLV = 0x1,
9332: SRAV = 0x2,
9333: ROTRV = 0x3,
9334: ADD = 0x4,
9335: ADDU32 = 0x5,
9336: SUB = 0x6,
9337: SUBU32 = 0x7,
9338: MUL = 0x8,
9339: AND = 0x9,
9340: OR32 = 0xa,
9341: NOR = 0xb,
9342: XOR32 = 0xc,
9343: SLT = 0xd,
9344: SLTU = 0xe,
9345:
9346: MOVN = 0x0,
9347: MOVZ = 0x1,
9348: LWXS = 0x4,
9349:
9350: /* The following can be distinguished by their lower 6 bits. */
9351: INS = 0x0c,
9352: EXT = 0x2c,
9353: POOL32AXF = 0x3c
9354: };
9355:
9356: /* POOL32AXF encoding of minor opcode field extension */
9357:
9358: enum {
9359: /* bits 11..6 */
9360: TEQ = 0x00,
9361: TGE = 0x08,
9362: TGEU = 0x10,
9363: TLT = 0x20,
9364: TLTU = 0x28,
9365: TNE = 0x30,
9366:
9367: MFC0 = 0x03,
9368: MTC0 = 0x0b,
9369:
9370: /* bits 13..12 for 0x01 */
9371: MFHI_ACC = 0x0,
9372: MFLO_ACC = 0x1,
9373: MTHI_ACC = 0x2,
9374: MTLO_ACC = 0x3,
9375:
9376: /* bits 13..12 for 0x2a */
9377: MADD_ACC = 0x0,
9378: MADDU_ACC = 0x1,
9379: MSUB_ACC = 0x2,
9380: MSUBU_ACC = 0x3,
9381:
9382: /* bits 13..12 for 0x32 */
9383: MULT_ACC = 0x0,
9384: MULTU_ACC = 0x0,
9385:
9386: /* bits 15..12 for 0x2c */
9387: SEB = 0x2,
9388: SEH = 0x3,
9389: CLO = 0x4,
9390: CLZ = 0x5,
9391: RDHWR = 0x6,
9392: WSBH = 0x7,
9393: MULT = 0x8,
9394: MULTU = 0x9,
9395: DIV = 0xa,
9396: DIVU = 0xb,
9397: MADD = 0xc,
9398: MADDU = 0xd,
9399: MSUB = 0xe,
9400: MSUBU = 0xf,
9401:
9402: /* bits 15..12 for 0x34 */
9403: MFC2 = 0x4,
9404: MTC2 = 0x5,
9405: MFHC2 = 0x8,
9406: MTHC2 = 0x9,
9407: CFC2 = 0xc,
9408: CTC2 = 0xd,
9409:
9410: /* bits 15..12 for 0x3c */
9411: JALR = 0x0,
9412: JR = 0x0, /* alias */
9413: JALR_HB = 0x1,
9414: JALRS = 0x4,
9415: JALRS_HB = 0x5,
9416:
9417: /* bits 15..12 for 0x05 */
9418: RDPGPR = 0xe,
9419: WRPGPR = 0xf,
9420:
9421: /* bits 15..12 for 0x0d */
9422: TLBP = 0x0,
9423: TLBR = 0x1,
9424: TLBWI = 0x2,
9425: TLBWR = 0x3,
9426: WAIT = 0x9,
9427: IRET = 0xd,
9428: DERET = 0xe,
9429: ERET = 0xf,
9430:
9431: /* bits 15..12 for 0x15 */
9432: DMT = 0x0,
9433: DVPE = 0x1,
9434: EMT = 0x2,
9435: EVPE = 0x3,
9436:
9437: /* bits 15..12 for 0x1d */
9438: DI = 0x4,
9439: EI = 0x5,
9440:
9441: /* bits 15..12 for 0x2d */
9442: SYNC = 0x6,
9443: SYSCALL = 0x8,
9444: SDBBP = 0xd,
9445:
9446: /* bits 15..12 for 0x35 */
9447: MFHI32 = 0x0,
9448: MFLO32 = 0x1,
9449: MTHI32 = 0x2,
9450: MTLO32 = 0x3,
9451: };
9452:
9453: /* POOL32B encoding of minor opcode field (bits 15..12) */
9454:
9455: enum {
9456: LWC2 = 0x0,
9457: LWP = 0x1,
9458: LDP = 0x4,
9459: LWM32 = 0x5,
9460: CACHE = 0x6,
9461: LDM = 0x7,
9462: SWC2 = 0x8,
9463: SWP = 0x9,
9464: SDP = 0xc,
9465: SWM32 = 0xd,
9466: SDM = 0xf
9467: };
9468:
9469: /* POOL32C encoding of minor opcode field (bits 15..12) */
9470:
9471: enum {
9472: LWL = 0x0,
9473: SWL = 0x8,
9474: LWR = 0x1,
9475: SWR = 0x9,
9476: PREF = 0x2,
9477: /* 0xa is reserved */
9478: LL = 0x3,
9479: SC = 0xb,
9480: LDL = 0x4,
9481: SDL = 0xc,
9482: LDR = 0x5,
9483: SDR = 0xd,
9484: /* 0x6 is reserved */
9485: LWU = 0xe,
9486: LLD = 0x7,
9487: SCD = 0xf
9488: };
9489:
9490: /* POOL32F encoding of minor opcode field (bits 5..0) */
9491:
9492: enum {
9493: /* These are the bit 7..6 values */
9494: ADD_FMT = 0x0,
9495: MOVN_FMT = 0x0,
9496:
9497: SUB_FMT = 0x1,
9498: MOVZ_FMT = 0x1,
9499:
9500: MUL_FMT = 0x2,
9501:
9502: DIV_FMT = 0x3,
9503:
9504: /* These are the bit 8..6 values */
9505: RSQRT2_FMT = 0x0,
9506: MOVF_FMT = 0x0,
9507:
9508: LWXC1 = 0x1,
9509: MOVT_FMT = 0x1,
9510:
9511: PLL_PS = 0x2,
9512: SWXC1 = 0x2,
9513:
9514: PLU_PS = 0x3,
9515: LDXC1 = 0x3,
9516:
9517: PUL_PS = 0x4,
9518: SDXC1 = 0x4,
9519: RECIP2_FMT = 0x4,
9520:
9521: PUU_PS = 0x5,
9522: LUXC1 = 0x5,
9523:
9524: CVT_PS_S = 0x6,
9525: SUXC1 = 0x6,
9526: ADDR_PS = 0x6,
9527: PREFX = 0x6,
9528:
9529: MULR_PS = 0x7,
9530:
9531: MADD_S = 0x01,
9532: MADD_D = 0x09,
9533: MADD_PS = 0x11,
9534: ALNV_PS = 0x19,
9535: MSUB_S = 0x21,
9536: MSUB_D = 0x29,
9537: MSUB_PS = 0x31,
9538:
9539: NMADD_S = 0x02,
9540: NMADD_D = 0x0a,
9541: NMADD_PS = 0x12,
9542: NMSUB_S = 0x22,
9543: NMSUB_D = 0x2a,
9544: NMSUB_PS = 0x32,
9545:
9546: POOL32FXF = 0x3b,
9547:
9548: CABS_COND_FMT = 0x1c, /* MIPS3D */
9549: C_COND_FMT = 0x3c
9550: };
9551:
9552: /* POOL32Fxf encoding of minor opcode extension field */
9553:
9554: enum {
9555: CVT_L = 0x04,
9556: RSQRT_FMT = 0x08,
9557: FLOOR_L = 0x0c,
9558: CVT_PW_PS = 0x1c,
9559: CVT_W = 0x24,
9560: SQRT_FMT = 0x28,
9561: FLOOR_W = 0x2c,
9562: CVT_PS_PW = 0x3c,
9563: CFC1 = 0x40,
9564: RECIP_FMT = 0x48,
9565: CEIL_L = 0x4c,
9566: CTC1 = 0x60,
9567: CEIL_W = 0x6c,
9568: MFC1 = 0x80,
9569: CVT_S_PL = 0x84,
9570: TRUNC_L = 0x8c,
9571: MTC1 = 0xa0,
9572: CVT_S_PU = 0xa4,
9573: TRUNC_W = 0xac,
9574: MFHC1 = 0xc0,
9575: ROUND_L = 0xcc,
9576: MTHC1 = 0xe0,
9577: ROUND_W = 0xec,
9578:
9579: MOV_FMT = 0x01,
9580: MOVF = 0x05,
9581: ABS_FMT = 0x0d,
9582: RSQRT1_FMT = 0x1d,
9583: MOVT = 0x25,
9584: NEG_FMT = 0x2d,
9585: CVT_D = 0x4d,
9586: RECIP1_FMT = 0x5d,
9587: CVT_S = 0x6d
9588: };
9589:
9590: /* POOL32I encoding of minor opcode field (bits 25..21) */
9591:
9592: enum {
9593: BLTZ = 0x00,
9594: BLTZAL = 0x01,
9595: BGEZ = 0x02,
9596: BGEZAL = 0x03,
9597: BLEZ = 0x04,
9598: BNEZC = 0x05,
9599: BGTZ = 0x06,
9600: BEQZC = 0x07,
9601: TLTI = 0x08,
9602: TGEI = 0x09,
9603: TLTIU = 0x0a,
9604: TGEIU = 0x0b,
9605: TNEI = 0x0c,
9606: LUI = 0x0d,
9607: TEQI = 0x0e,
9608: SYNCI = 0x10,
9609: BLTZALS = 0x11,
9610: BGEZALS = 0x13,
9611: BC2F = 0x14,
9612: BC2T = 0x15,
9613: BPOSGE64 = 0x1a,
9614: BPOSGE32 = 0x1b,
9615: /* These overlap and are distinguished by bit16 of the instruction */
9616: BC1F = 0x1c,
9617: BC1T = 0x1d,
9618: BC1ANY2F = 0x1c,
9619: BC1ANY2T = 0x1d,
9620: BC1ANY4F = 0x1e,
9621: BC1ANY4T = 0x1f
9622: };
9623:
9624: /* POOL16A encoding of minor opcode field */
9625:
9626: enum {
9627: ADDU16 = 0x0,
9628: SUBU16 = 0x1
9629: };
9630:
9631: /* POOL16B encoding of minor opcode field */
9632:
9633: enum {
9634: SLL16 = 0x0,
9635: SRL16 = 0x1
9636: };
9637:
9638: /* POOL16C encoding of minor opcode field */
9639:
9640: enum {
9641: NOT16 = 0x00,
9642: XOR16 = 0x04,
9643: AND16 = 0x08,
9644: OR16 = 0x0c,
9645: LWM16 = 0x10,
9646: SWM16 = 0x14,
9647: JR16 = 0x18,
9648: JRC16 = 0x1a,
9649: JALR16 = 0x1c,
9650: JALR16S = 0x1e,
9651: MFHI16 = 0x20,
9652: MFLO16 = 0x24,
9653: BREAK16 = 0x28,
9654: SDBBP16 = 0x2c,
9655: JRADDIUSP = 0x30
9656: };
9657:
9658: /* POOL16D encoding of minor opcode field */
9659:
9660: enum {
9661: ADDIUS5 = 0x0,
9662: ADDIUSP = 0x1
9663: };
9664:
9665: /* POOL16E encoding of minor opcode field */
9666:
9667: enum {
9668: ADDIUR2 = 0x0,
9669: ADDIUR1SP = 0x1
9670: };
9671:
9672: static int mmreg (int r)
9673: {
9674: static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9675:
9676: return map[r];
9677: }
9678:
9679: /* Used for 16-bit store instructions. */
9680: static int mmreg2 (int r)
9681: {
9682: static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
9683:
9684: return map[r];
9685: }
9686:
9687: #define uMIPS_RD(op) ((op >> 7) & 0x7)
9688: #define uMIPS_RS(op) ((op >> 4) & 0x7)
9689: #define uMIPS_RS2(op) uMIPS_RS(op)
9690: #define uMIPS_RS1(op) ((op >> 1) & 0x7)
9691: #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
9692: #define uMIPS_RS5(op) (op & 0x1f)
9693:
9694: /* Signed immediate */
9695: #define SIMM(op, start, width) \
9696: ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
9697: << (32-width)) \
9698: >> (32-width))
9699: /* Zero-extended immediate */
9700: #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
9701:
9702: static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
9703: {
9704: int rd = mmreg(uMIPS_RD(ctx->opcode));
9705:
9706: gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
9707: }
9708:
9709: static void gen_addiur2 (CPUState *env, DisasContext *ctx)
9710: {
9711: static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
9712: int rd = mmreg(uMIPS_RD(ctx->opcode));
9713: int rs = mmreg(uMIPS_RS(ctx->opcode));
9714:
9715: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
9716: }
9717:
9718: static void gen_addiusp (CPUState *env, DisasContext *ctx)
9719: {
9720: int encoded = ZIMM(ctx->opcode, 1, 9);
9721: int decoded;
9722:
9723: if (encoded <= 1) {
9724: decoded = 256 + encoded;
9725: } else if (encoded <= 255) {
9726: decoded = encoded;
9727: } else if (encoded <= 509) {
9728: decoded = encoded - 512;
9729: } else {
9730: decoded = encoded - 768;
9731: }
9732:
9733: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
9734: }
9735:
9736: static void gen_addius5 (CPUState *env, DisasContext *ctx)
9737: {
9738: int imm = SIMM(ctx->opcode, 1, 4);
9739: int rd = (ctx->opcode >> 5) & 0x1f;
9740:
9741: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
9742: }
9743:
9744: static void gen_andi16 (CPUState *env, DisasContext *ctx)
9745: {
9746: static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
9747: 31, 32, 63, 64, 255, 32768, 65535 };
9748: int rd = mmreg(uMIPS_RD(ctx->opcode));
9749: int rs = mmreg(uMIPS_RS(ctx->opcode));
9750: int encoded = ZIMM(ctx->opcode, 0, 4);
9751:
9752: gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
9753: }
9754:
9755: static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
9756: int base, int16_t offset)
9757: {
9758: TCGv t0, t1;
9759: TCGv_i32 t2;
9760:
9761: if (ctx->hflags & MIPS_HFLAG_BMASK) {
9762: generate_exception(ctx, EXCP_RI);
9763: return;
9764: }
9765:
9766: t0 = tcg_temp_new();
9767:
9768: gen_base_offset_addr(ctx, t0, base, offset);
9769:
9770: t1 = tcg_const_tl(reglist);
9771: t2 = tcg_const_i32(ctx->mem_idx);
9772:
9773: save_cpu_state(ctx, 1);
9774: switch (opc) {
9775: case LWM32:
9776: gen_helper_lwm(t0, t1, t2);
9777: break;
9778: case SWM32:
9779: gen_helper_swm(t0, t1, t2);
9780: break;
9781: #ifdef TARGET_MIPS64
9782: case LDM:
9783: gen_helper_ldm(t0, t1, t2);
9784: break;
9785: case SDM:
9786: gen_helper_sdm(t0, t1, t2);
9787: break;
9788: #endif
9789: }
9790: MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
9791: tcg_temp_free(t0);
9792: tcg_temp_free(t1);
9793: tcg_temp_free_i32(t2);
9794: }
9795:
9796:
9797: static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
9798: {
9799: int rd = mmreg((ctx->opcode >> 3) & 0x7);
9800: int rs = mmreg(ctx->opcode & 0x7);
9801: int opc;
9802:
9803: switch (((ctx->opcode) >> 4) & 0x3f) {
9804: case NOT16 + 0:
9805: case NOT16 + 1:
9806: case NOT16 + 2:
9807: case NOT16 + 3:
9808: gen_logic(env, OPC_NOR, rd, rs, 0);
9809: break;
9810: case XOR16 + 0:
9811: case XOR16 + 1:
9812: case XOR16 + 2:
9813: case XOR16 + 3:
9814: gen_logic(env, OPC_XOR, rd, rd, rs);
9815: break;
9816: case AND16 + 0:
9817: case AND16 + 1:
9818: case AND16 + 2:
9819: case AND16 + 3:
9820: gen_logic(env, OPC_AND, rd, rd, rs);
9821: break;
9822: case OR16 + 0:
9823: case OR16 + 1:
9824: case OR16 + 2:
9825: case OR16 + 3:
9826: gen_logic(env, OPC_OR, rd, rd, rs);
9827: break;
9828: case LWM16 + 0:
9829: case LWM16 + 1:
9830: case LWM16 + 2:
9831: case LWM16 + 3:
9832: {
9833: static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9834: int offset = ZIMM(ctx->opcode, 0, 4);
9835:
9836: gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
9837: 29, offset << 2);
9838: }
9839: break;
9840: case SWM16 + 0:
9841: case SWM16 + 1:
9842: case SWM16 + 2:
9843: case SWM16 + 3:
9844: {
9845: static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9846: int offset = ZIMM(ctx->opcode, 0, 4);
9847:
9848: gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
9849: 29, offset << 2);
9850: }
9851: break;
9852: case JR16 + 0:
9853: case JR16 + 1:
9854: {
9855: int reg = ctx->opcode & 0x1f;
9856:
9857: gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9858: }
9859: *is_branch = 1;
9860: break;
9861: case JRC16 + 0:
9862: case JRC16 + 1:
9863: {
9864: int reg = ctx->opcode & 0x1f;
9865:
9866: gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9867: /* Let normal delay slot handling in our caller take us
9868: to the branch target. */
9869: }
9870: break;
9871: case JALR16 + 0:
9872: case JALR16 + 1:
9873: opc = OPC_JALR;
9874: goto do_jalr;
9875: case JALR16S + 0:
9876: case JALR16S + 1:
9877: opc = OPC_JALRS;
9878: do_jalr:
9879: {
9880: int reg = ctx->opcode & 0x1f;
9881:
9882: gen_compute_branch(ctx, opc, 2, reg, 31, 0);
9883: }
9884: *is_branch = 1;
9885: break;
9886: case MFHI16 + 0:
9887: case MFHI16 + 1:
9888: gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
9889: break;
9890: case MFLO16 + 0:
9891: case MFLO16 + 1:
9892: gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
9893: break;
9894: case BREAK16:
9895: generate_exception(ctx, EXCP_BREAK);
9896: break;
9897: case SDBBP16:
9898: /* XXX: not clear which exception should be raised
9899: * when in debug mode...
9900: */
9901: check_insn(env, ctx, ISA_MIPS32);
9902: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9903: generate_exception(ctx, EXCP_DBp);
9904: } else {
9905: generate_exception(ctx, EXCP_DBp);
9906: }
9907: break;
9908: case JRADDIUSP + 0:
9909: case JRADDIUSP + 1:
9910: {
9911: int imm = ZIMM(ctx->opcode, 0, 5);
9912:
9913: gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
9914: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
9915: /* Let normal delay slot handling in our caller take us
9916: to the branch target. */
9917: }
9918: break;
9919: default:
9920: generate_exception(ctx, EXCP_RI);
9921: break;
9922: }
9923: }
9924:
9925: static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
9926: {
9927: TCGv t0 = tcg_temp_new();
9928: TCGv t1 = tcg_temp_new();
9929:
9930: gen_load_gpr(t0, base);
9931:
9932: if (index != 0) {
9933: gen_load_gpr(t1, index);
9934: tcg_gen_shli_tl(t1, t1, 2);
9935: gen_op_addr_add(ctx, t0, t1, t0);
9936: }
9937:
9938: save_cpu_state(ctx, 0);
9939: op_ld_lw(t1, t0, ctx);
9940: gen_store_gpr(t1, rd);
9941:
9942: tcg_temp_free(t0);
9943: tcg_temp_free(t1);
9944: }
9945:
9946: static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
9947: int base, int16_t offset)
9948: {
9949: const char *opn = "ldst_pair";
9950: TCGv t0, t1;
9951:
9952: if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
9953: generate_exception(ctx, EXCP_RI);
9954: return;
9955: }
9956:
9957: t0 = tcg_temp_new();
9958: t1 = tcg_temp_new();
9959:
9960: gen_base_offset_addr(ctx, t0, base, offset);
9961:
9962: switch (opc) {
9963: case LWP:
9964: save_cpu_state(ctx, 0);
9965: op_ld_lw(t1, t0, ctx);
9966: gen_store_gpr(t1, rd);
9967: tcg_gen_movi_tl(t1, 4);
9968: gen_op_addr_add(ctx, t0, t0, t1);
9969: op_ld_lw(t1, t0, ctx);
9970: gen_store_gpr(t1, rd+1);
9971: opn = "lwp";
9972: break;
9973: case SWP:
1.1.1.13! root 9974: save_cpu_state(ctx, 0);
1.1.1.12 root 9975: gen_load_gpr(t1, rd);
9976: op_st_sw(t1, t0, ctx);
9977: tcg_gen_movi_tl(t1, 4);
9978: gen_op_addr_add(ctx, t0, t0, t1);
9979: gen_load_gpr(t1, rd+1);
9980: op_st_sw(t1, t0, ctx);
9981: opn = "swp";
9982: break;
9983: #ifdef TARGET_MIPS64
9984: case LDP:
9985: save_cpu_state(ctx, 0);
9986: op_ld_ld(t1, t0, ctx);
9987: gen_store_gpr(t1, rd);
9988: tcg_gen_movi_tl(t1, 8);
9989: gen_op_addr_add(ctx, t0, t0, t1);
9990: op_ld_ld(t1, t0, ctx);
9991: gen_store_gpr(t1, rd+1);
9992: opn = "ldp";
9993: break;
9994: case SDP:
1.1.1.13! root 9995: save_cpu_state(ctx, 0);
1.1.1.12 root 9996: gen_load_gpr(t1, rd);
9997: op_st_sd(t1, t0, ctx);
9998: tcg_gen_movi_tl(t1, 8);
9999: gen_op_addr_add(ctx, t0, t0, t1);
10000: gen_load_gpr(t1, rd+1);
10001: op_st_sd(t1, t0, ctx);
10002: opn = "sdp";
10003: break;
10004: #endif
10005: }
1.1.1.13! root 10006: (void)opn; /* avoid a compiler warning */
1.1.1.12 root 10007: MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10008: tcg_temp_free(t0);
10009: tcg_temp_free(t1);
10010: }
10011:
10012: static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
10013: int *is_branch)
10014: {
10015: int extension = (ctx->opcode >> 6) & 0x3f;
10016: int minor = (ctx->opcode >> 12) & 0xf;
10017: uint32_t mips32_op;
10018:
10019: switch (extension) {
10020: case TEQ:
10021: mips32_op = OPC_TEQ;
10022: goto do_trap;
10023: case TGE:
10024: mips32_op = OPC_TGE;
10025: goto do_trap;
10026: case TGEU:
10027: mips32_op = OPC_TGEU;
10028: goto do_trap;
10029: case TLT:
10030: mips32_op = OPC_TLT;
10031: goto do_trap;
10032: case TLTU:
10033: mips32_op = OPC_TLTU;
10034: goto do_trap;
10035: case TNE:
10036: mips32_op = OPC_TNE;
10037: do_trap:
10038: gen_trap(ctx, mips32_op, rs, rt, -1);
10039: break;
10040: #ifndef CONFIG_USER_ONLY
10041: case MFC0:
10042: case MFC0 + 32:
10043: if (rt == 0) {
10044: /* Treat as NOP. */
10045: break;
10046: }
10047: gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10048: break;
10049: case MTC0:
10050: case MTC0 + 32:
10051: {
10052: TCGv t0 = tcg_temp_new();
10053:
10054: gen_load_gpr(t0, rt);
10055: gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10056: tcg_temp_free(t0);
10057: }
10058: break;
10059: #endif
10060: case 0x2c:
10061: switch (minor) {
10062: case SEB:
10063: gen_bshfl(ctx, OPC_SEB, rs, rt);
10064: break;
10065: case SEH:
10066: gen_bshfl(ctx, OPC_SEH, rs, rt);
10067: break;
10068: case CLO:
10069: mips32_op = OPC_CLO;
10070: goto do_cl;
10071: case CLZ:
10072: mips32_op = OPC_CLZ;
10073: do_cl:
10074: check_insn(env, ctx, ISA_MIPS32);
10075: gen_cl(ctx, mips32_op, rt, rs);
10076: break;
10077: case RDHWR:
10078: gen_rdhwr(env, ctx, rt, rs);
10079: break;
10080: case WSBH:
10081: gen_bshfl(ctx, OPC_WSBH, rs, rt);
10082: break;
10083: case MULT:
10084: mips32_op = OPC_MULT;
10085: goto do_muldiv;
10086: case MULTU:
10087: mips32_op = OPC_MULTU;
10088: goto do_muldiv;
10089: case DIV:
10090: mips32_op = OPC_DIV;
10091: goto do_muldiv;
10092: case DIVU:
10093: mips32_op = OPC_DIVU;
10094: goto do_muldiv;
10095: case MADD:
10096: mips32_op = OPC_MADD;
10097: goto do_muldiv;
10098: case MADDU:
10099: mips32_op = OPC_MADDU;
10100: goto do_muldiv;
10101: case MSUB:
10102: mips32_op = OPC_MSUB;
10103: goto do_muldiv;
10104: case MSUBU:
10105: mips32_op = OPC_MSUBU;
10106: do_muldiv:
10107: check_insn(env, ctx, ISA_MIPS32);
10108: gen_muldiv(ctx, mips32_op, rs, rt);
10109: break;
10110: default:
10111: goto pool32axf_invalid;
10112: }
10113: break;
10114: case 0x34:
10115: switch (minor) {
10116: case MFC2:
10117: case MTC2:
10118: case MFHC2:
10119: case MTHC2:
10120: case CFC2:
10121: case CTC2:
10122: generate_exception_err(ctx, EXCP_CpU, 2);
10123: break;
10124: default:
10125: goto pool32axf_invalid;
10126: }
10127: break;
10128: case 0x3c:
10129: switch (minor) {
10130: case JALR:
10131: case JALR_HB:
10132: gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10133: *is_branch = 1;
10134: break;
10135: case JALRS:
10136: case JALRS_HB:
10137: gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10138: *is_branch = 1;
10139: break;
10140: default:
10141: goto pool32axf_invalid;
10142: }
10143: break;
10144: case 0x05:
10145: switch (minor) {
10146: case RDPGPR:
10147: check_insn(env, ctx, ISA_MIPS32R2);
10148: gen_load_srsgpr(rt, rs);
10149: break;
10150: case WRPGPR:
10151: check_insn(env, ctx, ISA_MIPS32R2);
10152: gen_store_srsgpr(rt, rs);
10153: break;
10154: default:
10155: goto pool32axf_invalid;
10156: }
10157: break;
10158: #ifndef CONFIG_USER_ONLY
10159: case 0x0d:
10160: switch (minor) {
10161: case TLBP:
10162: mips32_op = OPC_TLBP;
10163: goto do_cp0;
10164: case TLBR:
10165: mips32_op = OPC_TLBR;
10166: goto do_cp0;
10167: case TLBWI:
10168: mips32_op = OPC_TLBWI;
10169: goto do_cp0;
10170: case TLBWR:
10171: mips32_op = OPC_TLBWR;
10172: goto do_cp0;
10173: case WAIT:
10174: mips32_op = OPC_WAIT;
10175: goto do_cp0;
10176: case DERET:
10177: mips32_op = OPC_DERET;
10178: goto do_cp0;
10179: case ERET:
10180: mips32_op = OPC_ERET;
10181: do_cp0:
10182: gen_cp0(env, ctx, mips32_op, rt, rs);
10183: break;
10184: default:
10185: goto pool32axf_invalid;
10186: }
10187: break;
10188: case 0x1d:
10189: switch (minor) {
10190: case DI:
10191: {
10192: TCGv t0 = tcg_temp_new();
10193:
10194: save_cpu_state(ctx, 1);
10195: gen_helper_di(t0);
10196: gen_store_gpr(t0, rs);
10197: /* Stop translation as we may have switched the execution mode */
10198: ctx->bstate = BS_STOP;
10199: tcg_temp_free(t0);
10200: }
10201: break;
10202: case EI:
10203: {
10204: TCGv t0 = tcg_temp_new();
10205:
10206: save_cpu_state(ctx, 1);
10207: gen_helper_ei(t0);
10208: gen_store_gpr(t0, rs);
10209: /* Stop translation as we may have switched the execution mode */
10210: ctx->bstate = BS_STOP;
10211: tcg_temp_free(t0);
10212: }
10213: break;
10214: default:
10215: goto pool32axf_invalid;
10216: }
10217: break;
10218: #endif
10219: case 0x2d:
10220: switch (minor) {
10221: case SYNC:
10222: /* NOP */
10223: break;
10224: case SYSCALL:
10225: generate_exception(ctx, EXCP_SYSCALL);
10226: ctx->bstate = BS_STOP;
10227: break;
10228: case SDBBP:
10229: check_insn(env, ctx, ISA_MIPS32);
10230: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10231: generate_exception(ctx, EXCP_DBp);
10232: } else {
10233: generate_exception(ctx, EXCP_DBp);
10234: }
10235: break;
10236: default:
10237: goto pool32axf_invalid;
10238: }
10239: break;
10240: case 0x35:
10241: switch (minor) {
10242: case MFHI32:
10243: gen_HILO(ctx, OPC_MFHI, rs);
10244: break;
10245: case MFLO32:
10246: gen_HILO(ctx, OPC_MFLO, rs);
10247: break;
10248: case MTHI32:
10249: gen_HILO(ctx, OPC_MTHI, rs);
10250: break;
10251: case MTLO32:
10252: gen_HILO(ctx, OPC_MTLO, rs);
10253: break;
10254: default:
10255: goto pool32axf_invalid;
10256: }
10257: break;
10258: default:
10259: pool32axf_invalid:
10260: MIPS_INVAL("pool32axf");
10261: generate_exception(ctx, EXCP_RI);
10262: break;
10263: }
10264: }
10265:
10266: /* Values for microMIPS fmt field. Variable-width, depending on which
10267: formats the instruction supports. */
10268:
10269: enum {
10270: FMT_SD_S = 0,
10271: FMT_SD_D = 1,
10272:
10273: FMT_SDPS_S = 0,
10274: FMT_SDPS_D = 1,
10275: FMT_SDPS_PS = 2,
10276:
10277: FMT_SWL_S = 0,
10278: FMT_SWL_W = 1,
10279: FMT_SWL_L = 2,
10280:
10281: FMT_DWL_D = 0,
10282: FMT_DWL_W = 1,
10283: FMT_DWL_L = 2
10284: };
10285:
10286: static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
10287: {
10288: int extension = (ctx->opcode >> 6) & 0x3ff;
10289: uint32_t mips32_op;
10290:
10291: #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10292: #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10293: #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10294:
10295: switch (extension) {
10296: case FLOAT_1BIT_FMT(CFC1, 0):
10297: mips32_op = OPC_CFC1;
10298: goto do_cp1;
10299: case FLOAT_1BIT_FMT(CTC1, 0):
10300: mips32_op = OPC_CTC1;
10301: goto do_cp1;
10302: case FLOAT_1BIT_FMT(MFC1, 0):
10303: mips32_op = OPC_MFC1;
10304: goto do_cp1;
10305: case FLOAT_1BIT_FMT(MTC1, 0):
10306: mips32_op = OPC_MTC1;
10307: goto do_cp1;
10308: case FLOAT_1BIT_FMT(MFHC1, 0):
10309: mips32_op = OPC_MFHC1;
10310: goto do_cp1;
10311: case FLOAT_1BIT_FMT(MTHC1, 0):
10312: mips32_op = OPC_MTHC1;
10313: do_cp1:
10314: gen_cp1(ctx, mips32_op, rt, rs);
10315: break;
10316:
10317: /* Reciprocal square root */
10318: case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10319: mips32_op = OPC_RSQRT_S;
10320: goto do_unaryfp;
10321: case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10322: mips32_op = OPC_RSQRT_D;
10323: goto do_unaryfp;
10324:
10325: /* Square root */
10326: case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10327: mips32_op = OPC_SQRT_S;
10328: goto do_unaryfp;
10329: case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10330: mips32_op = OPC_SQRT_D;
10331: goto do_unaryfp;
10332:
10333: /* Reciprocal */
10334: case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10335: mips32_op = OPC_RECIP_S;
10336: goto do_unaryfp;
10337: case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10338: mips32_op = OPC_RECIP_D;
10339: goto do_unaryfp;
10340:
10341: /* Floor */
10342: case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10343: mips32_op = OPC_FLOOR_L_S;
10344: goto do_unaryfp;
10345: case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10346: mips32_op = OPC_FLOOR_L_D;
10347: goto do_unaryfp;
10348: case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10349: mips32_op = OPC_FLOOR_W_S;
10350: goto do_unaryfp;
10351: case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10352: mips32_op = OPC_FLOOR_W_D;
10353: goto do_unaryfp;
10354:
10355: /* Ceiling */
10356: case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10357: mips32_op = OPC_CEIL_L_S;
10358: goto do_unaryfp;
10359: case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10360: mips32_op = OPC_CEIL_L_D;
10361: goto do_unaryfp;
10362: case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10363: mips32_op = OPC_CEIL_W_S;
10364: goto do_unaryfp;
10365: case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10366: mips32_op = OPC_CEIL_W_D;
10367: goto do_unaryfp;
10368:
10369: /* Truncation */
10370: case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10371: mips32_op = OPC_TRUNC_L_S;
10372: goto do_unaryfp;
10373: case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10374: mips32_op = OPC_TRUNC_L_D;
10375: goto do_unaryfp;
10376: case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10377: mips32_op = OPC_TRUNC_W_S;
10378: goto do_unaryfp;
10379: case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10380: mips32_op = OPC_TRUNC_W_D;
10381: goto do_unaryfp;
10382:
10383: /* Round */
10384: case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10385: mips32_op = OPC_ROUND_L_S;
10386: goto do_unaryfp;
10387: case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10388: mips32_op = OPC_ROUND_L_D;
10389: goto do_unaryfp;
10390: case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10391: mips32_op = OPC_ROUND_W_S;
10392: goto do_unaryfp;
10393: case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10394: mips32_op = OPC_ROUND_W_D;
10395: goto do_unaryfp;
10396:
10397: /* Integer to floating-point conversion */
10398: case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10399: mips32_op = OPC_CVT_L_S;
10400: goto do_unaryfp;
10401: case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10402: mips32_op = OPC_CVT_L_D;
10403: goto do_unaryfp;
10404: case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10405: mips32_op = OPC_CVT_W_S;
10406: goto do_unaryfp;
10407: case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10408: mips32_op = OPC_CVT_W_D;
10409: goto do_unaryfp;
10410:
10411: /* Paired-foo conversions */
10412: case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10413: mips32_op = OPC_CVT_S_PL;
10414: goto do_unaryfp;
10415: case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10416: mips32_op = OPC_CVT_S_PU;
10417: goto do_unaryfp;
10418: case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10419: mips32_op = OPC_CVT_PW_PS;
10420: goto do_unaryfp;
10421: case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10422: mips32_op = OPC_CVT_PS_PW;
10423: goto do_unaryfp;
10424:
10425: /* Floating-point moves */
10426: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10427: mips32_op = OPC_MOV_S;
10428: goto do_unaryfp;
10429: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10430: mips32_op = OPC_MOV_D;
10431: goto do_unaryfp;
10432: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10433: mips32_op = OPC_MOV_PS;
10434: goto do_unaryfp;
10435:
10436: /* Absolute value */
10437: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10438: mips32_op = OPC_ABS_S;
10439: goto do_unaryfp;
10440: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10441: mips32_op = OPC_ABS_D;
10442: goto do_unaryfp;
10443: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10444: mips32_op = OPC_ABS_PS;
10445: goto do_unaryfp;
10446:
10447: /* Negation */
10448: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10449: mips32_op = OPC_NEG_S;
10450: goto do_unaryfp;
10451: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10452: mips32_op = OPC_NEG_D;
10453: goto do_unaryfp;
10454: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10455: mips32_op = OPC_NEG_PS;
10456: goto do_unaryfp;
10457:
10458: /* Reciprocal square root step */
10459: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10460: mips32_op = OPC_RSQRT1_S;
10461: goto do_unaryfp;
10462: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10463: mips32_op = OPC_RSQRT1_D;
10464: goto do_unaryfp;
10465: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10466: mips32_op = OPC_RSQRT1_PS;
10467: goto do_unaryfp;
10468:
10469: /* Reciprocal step */
10470: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10471: mips32_op = OPC_RECIP1_S;
10472: goto do_unaryfp;
10473: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10474: mips32_op = OPC_RECIP1_S;
10475: goto do_unaryfp;
10476: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10477: mips32_op = OPC_RECIP1_PS;
10478: goto do_unaryfp;
10479:
10480: /* Conversions from double */
10481: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10482: mips32_op = OPC_CVT_D_S;
10483: goto do_unaryfp;
10484: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10485: mips32_op = OPC_CVT_D_W;
10486: goto do_unaryfp;
10487: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10488: mips32_op = OPC_CVT_D_L;
10489: goto do_unaryfp;
10490:
10491: /* Conversions from single */
10492: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10493: mips32_op = OPC_CVT_S_D;
10494: goto do_unaryfp;
10495: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10496: mips32_op = OPC_CVT_S_W;
10497: goto do_unaryfp;
10498: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10499: mips32_op = OPC_CVT_S_L;
10500: do_unaryfp:
10501: gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10502: break;
10503:
10504: /* Conditional moves on floating-point codes */
10505: case COND_FLOAT_MOV(MOVT, 0):
10506: case COND_FLOAT_MOV(MOVT, 1):
10507: case COND_FLOAT_MOV(MOVT, 2):
10508: case COND_FLOAT_MOV(MOVT, 3):
10509: case COND_FLOAT_MOV(MOVT, 4):
10510: case COND_FLOAT_MOV(MOVT, 5):
10511: case COND_FLOAT_MOV(MOVT, 6):
10512: case COND_FLOAT_MOV(MOVT, 7):
10513: gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
10514: break;
10515: case COND_FLOAT_MOV(MOVF, 0):
10516: case COND_FLOAT_MOV(MOVF, 1):
10517: case COND_FLOAT_MOV(MOVF, 2):
10518: case COND_FLOAT_MOV(MOVF, 3):
10519: case COND_FLOAT_MOV(MOVF, 4):
10520: case COND_FLOAT_MOV(MOVF, 5):
10521: case COND_FLOAT_MOV(MOVF, 6):
10522: case COND_FLOAT_MOV(MOVF, 7):
10523: gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
10524: break;
10525: default:
10526: MIPS_INVAL("pool32fxf");
10527: generate_exception(ctx, EXCP_RI);
10528: break;
10529: }
10530: }
10531:
10532: static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
10533: uint16_t insn_hw1, int *is_branch)
10534: {
10535: int32_t offset;
10536: uint16_t insn;
10537: int rt, rs, rd, rr;
10538: int16_t imm;
10539: uint32_t op, minor, mips32_op;
10540: uint32_t cond, fmt, cc;
10541:
10542: insn = lduw_code(ctx->pc + 2);
10543: ctx->opcode = (ctx->opcode << 16) | insn;
10544:
10545: rt = (ctx->opcode >> 21) & 0x1f;
10546: rs = (ctx->opcode >> 16) & 0x1f;
10547: rd = (ctx->opcode >> 11) & 0x1f;
10548: rr = (ctx->opcode >> 6) & 0x1f;
10549: imm = (int16_t) ctx->opcode;
10550:
10551: op = (ctx->opcode >> 26) & 0x3f;
10552: switch (op) {
10553: case POOL32A:
10554: minor = ctx->opcode & 0x3f;
10555: switch (minor) {
10556: case 0x00:
10557: minor = (ctx->opcode >> 6) & 0xf;
10558: switch (minor) {
10559: case SLL32:
10560: mips32_op = OPC_SLL;
10561: goto do_shifti;
10562: case SRA:
10563: mips32_op = OPC_SRA;
10564: goto do_shifti;
10565: case SRL32:
10566: mips32_op = OPC_SRL;
10567: goto do_shifti;
10568: case ROTR:
10569: mips32_op = OPC_ROTR;
10570: do_shifti:
10571: gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
10572: break;
10573: default:
10574: goto pool32a_invalid;
10575: }
10576: break;
10577: case 0x10:
10578: minor = (ctx->opcode >> 6) & 0xf;
10579: switch (minor) {
10580: /* Arithmetic */
10581: case ADD:
10582: mips32_op = OPC_ADD;
10583: goto do_arith;
10584: case ADDU32:
10585: mips32_op = OPC_ADDU;
10586: goto do_arith;
10587: case SUB:
10588: mips32_op = OPC_SUB;
10589: goto do_arith;
10590: case SUBU32:
10591: mips32_op = OPC_SUBU;
10592: goto do_arith;
10593: case MUL:
10594: mips32_op = OPC_MUL;
10595: do_arith:
10596: gen_arith(env, ctx, mips32_op, rd, rs, rt);
10597: break;
10598: /* Shifts */
10599: case SLLV:
10600: mips32_op = OPC_SLLV;
10601: goto do_shift;
10602: case SRLV:
10603: mips32_op = OPC_SRLV;
10604: goto do_shift;
10605: case SRAV:
10606: mips32_op = OPC_SRAV;
10607: goto do_shift;
10608: case ROTRV:
10609: mips32_op = OPC_ROTRV;
10610: do_shift:
10611: gen_shift(env, ctx, mips32_op, rd, rs, rt);
10612: break;
10613: /* Logical operations */
10614: case AND:
10615: mips32_op = OPC_AND;
10616: goto do_logic;
10617: case OR32:
10618: mips32_op = OPC_OR;
10619: goto do_logic;
10620: case NOR:
10621: mips32_op = OPC_NOR;
10622: goto do_logic;
10623: case XOR32:
10624: mips32_op = OPC_XOR;
10625: do_logic:
10626: gen_logic(env, mips32_op, rd, rs, rt);
10627: break;
10628: /* Set less than */
10629: case SLT:
10630: mips32_op = OPC_SLT;
10631: goto do_slt;
10632: case SLTU:
10633: mips32_op = OPC_SLTU;
10634: do_slt:
10635: gen_slt(env, mips32_op, rd, rs, rt);
10636: break;
10637: default:
10638: goto pool32a_invalid;
10639: }
10640: break;
10641: case 0x18:
10642: minor = (ctx->opcode >> 6) & 0xf;
10643: switch (minor) {
10644: /* Conditional moves */
10645: case MOVN:
10646: mips32_op = OPC_MOVN;
10647: goto do_cmov;
10648: case MOVZ:
10649: mips32_op = OPC_MOVZ;
10650: do_cmov:
10651: gen_cond_move(env, mips32_op, rd, rs, rt);
10652: break;
10653: case LWXS:
10654: gen_ldxs(ctx, rs, rt, rd);
10655: break;
10656: default:
10657: goto pool32a_invalid;
10658: }
10659: break;
10660: case INS:
10661: gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
10662: return;
10663: case EXT:
10664: gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
10665: return;
10666: case POOL32AXF:
10667: gen_pool32axf(env, ctx, rt, rs, is_branch);
10668: break;
10669: case 0x07:
10670: generate_exception(ctx, EXCP_BREAK);
10671: break;
10672: default:
10673: pool32a_invalid:
10674: MIPS_INVAL("pool32a");
10675: generate_exception(ctx, EXCP_RI);
10676: break;
10677: }
10678: break;
10679: case POOL32B:
10680: minor = (ctx->opcode >> 12) & 0xf;
10681: switch (minor) {
10682: case CACHE:
10683: /* Treat as no-op. */
10684: break;
10685: case LWC2:
10686: case SWC2:
10687: /* COP2: Not implemented. */
10688: generate_exception_err(ctx, EXCP_CpU, 2);
10689: break;
10690: case LWP:
10691: case SWP:
10692: #ifdef TARGET_MIPS64
10693: case LDP:
10694: case SDP:
10695: #endif
10696: gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10697: break;
10698: case LWM32:
10699: case SWM32:
10700: #ifdef TARGET_MIPS64
10701: case LDM:
10702: case SDM:
10703: #endif
10704: gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10705: break;
10706: default:
10707: MIPS_INVAL("pool32b");
10708: generate_exception(ctx, EXCP_RI);
10709: break;
10710: }
10711: break;
10712: case POOL32F:
10713: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
10714: minor = ctx->opcode & 0x3f;
10715: check_cp1_enabled(ctx);
10716: switch (minor) {
10717: case ALNV_PS:
10718: mips32_op = OPC_ALNV_PS;
10719: goto do_madd;
10720: case MADD_S:
10721: mips32_op = OPC_MADD_S;
10722: goto do_madd;
10723: case MADD_D:
10724: mips32_op = OPC_MADD_D;
10725: goto do_madd;
10726: case MADD_PS:
10727: mips32_op = OPC_MADD_PS;
10728: goto do_madd;
10729: case MSUB_S:
10730: mips32_op = OPC_MSUB_S;
10731: goto do_madd;
10732: case MSUB_D:
10733: mips32_op = OPC_MSUB_D;
10734: goto do_madd;
10735: case MSUB_PS:
10736: mips32_op = OPC_MSUB_PS;
10737: goto do_madd;
10738: case NMADD_S:
10739: mips32_op = OPC_NMADD_S;
10740: goto do_madd;
10741: case NMADD_D:
10742: mips32_op = OPC_NMADD_D;
10743: goto do_madd;
10744: case NMADD_PS:
10745: mips32_op = OPC_NMADD_PS;
10746: goto do_madd;
10747: case NMSUB_S:
10748: mips32_op = OPC_NMSUB_S;
10749: goto do_madd;
10750: case NMSUB_D:
10751: mips32_op = OPC_NMSUB_D;
10752: goto do_madd;
10753: case NMSUB_PS:
10754: mips32_op = OPC_NMSUB_PS;
10755: do_madd:
10756: gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
10757: break;
10758: case CABS_COND_FMT:
10759: cond = (ctx->opcode >> 6) & 0xf;
10760: cc = (ctx->opcode >> 13) & 0x7;
10761: fmt = (ctx->opcode >> 10) & 0x3;
10762: switch (fmt) {
10763: case 0x0:
10764: gen_cmpabs_s(ctx, cond, rt, rs, cc);
10765: break;
10766: case 0x1:
10767: gen_cmpabs_d(ctx, cond, rt, rs, cc);
10768: break;
10769: case 0x2:
10770: gen_cmpabs_ps(ctx, cond, rt, rs, cc);
10771: break;
10772: default:
10773: goto pool32f_invalid;
10774: }
10775: break;
10776: case C_COND_FMT:
10777: cond = (ctx->opcode >> 6) & 0xf;
10778: cc = (ctx->opcode >> 13) & 0x7;
10779: fmt = (ctx->opcode >> 10) & 0x3;
10780: switch (fmt) {
10781: case 0x0:
10782: gen_cmp_s(ctx, cond, rt, rs, cc);
10783: break;
10784: case 0x1:
10785: gen_cmp_d(ctx, cond, rt, rs, cc);
10786: break;
10787: case 0x2:
10788: gen_cmp_ps(ctx, cond, rt, rs, cc);
10789: break;
10790: default:
10791: goto pool32f_invalid;
10792: }
10793: break;
10794: case POOL32FXF:
10795: gen_pool32fxf(env, ctx, rt, rs);
10796: break;
10797: case 0x00:
10798: /* PLL foo */
10799: switch ((ctx->opcode >> 6) & 0x7) {
10800: case PLL_PS:
10801: mips32_op = OPC_PLL_PS;
10802: goto do_ps;
10803: case PLU_PS:
10804: mips32_op = OPC_PLU_PS;
10805: goto do_ps;
10806: case PUL_PS:
10807: mips32_op = OPC_PUL_PS;
10808: goto do_ps;
10809: case PUU_PS:
10810: mips32_op = OPC_PUU_PS;
10811: goto do_ps;
10812: case CVT_PS_S:
10813: mips32_op = OPC_CVT_PS_S;
10814: do_ps:
10815: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10816: break;
10817: default:
10818: goto pool32f_invalid;
10819: }
10820: break;
10821: case 0x08:
10822: /* [LS][WDU]XC1 */
10823: switch ((ctx->opcode >> 6) & 0x7) {
10824: case LWXC1:
10825: mips32_op = OPC_LWXC1;
10826: goto do_ldst_cp1;
10827: case SWXC1:
10828: mips32_op = OPC_SWXC1;
10829: goto do_ldst_cp1;
10830: case LDXC1:
10831: mips32_op = OPC_LDXC1;
10832: goto do_ldst_cp1;
10833: case SDXC1:
10834: mips32_op = OPC_SDXC1;
10835: goto do_ldst_cp1;
10836: case LUXC1:
10837: mips32_op = OPC_LUXC1;
10838: goto do_ldst_cp1;
10839: case SUXC1:
10840: mips32_op = OPC_SUXC1;
10841: do_ldst_cp1:
10842: gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
10843: break;
10844: default:
10845: goto pool32f_invalid;
10846: }
10847: break;
10848: case 0x18:
10849: /* 3D insns */
10850: fmt = (ctx->opcode >> 9) & 0x3;
10851: switch ((ctx->opcode >> 6) & 0x7) {
10852: case RSQRT2_FMT:
10853: switch (fmt) {
10854: case FMT_SDPS_S:
10855: mips32_op = OPC_RSQRT2_S;
10856: goto do_3d;
10857: case FMT_SDPS_D:
10858: mips32_op = OPC_RSQRT2_D;
10859: goto do_3d;
10860: case FMT_SDPS_PS:
10861: mips32_op = OPC_RSQRT2_PS;
10862: goto do_3d;
10863: default:
10864: goto pool32f_invalid;
10865: }
10866: break;
10867: case RECIP2_FMT:
10868: switch (fmt) {
10869: case FMT_SDPS_S:
10870: mips32_op = OPC_RECIP2_S;
10871: goto do_3d;
10872: case FMT_SDPS_D:
10873: mips32_op = OPC_RECIP2_D;
10874: goto do_3d;
10875: case FMT_SDPS_PS:
10876: mips32_op = OPC_RECIP2_PS;
10877: goto do_3d;
10878: default:
10879: goto pool32f_invalid;
10880: }
10881: break;
10882: case ADDR_PS:
10883: mips32_op = OPC_ADDR_PS;
10884: goto do_3d;
10885: case MULR_PS:
10886: mips32_op = OPC_MULR_PS;
10887: do_3d:
10888: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10889: break;
10890: default:
10891: goto pool32f_invalid;
10892: }
10893: break;
10894: case 0x20:
10895: /* MOV[FT].fmt and PREFX */
10896: cc = (ctx->opcode >> 13) & 0x7;
10897: fmt = (ctx->opcode >> 9) & 0x3;
10898: switch ((ctx->opcode >> 6) & 0x7) {
10899: case MOVF_FMT:
10900: switch (fmt) {
10901: case FMT_SDPS_S:
10902: gen_movcf_s(rs, rt, cc, 0);
10903: break;
10904: case FMT_SDPS_D:
10905: gen_movcf_d(ctx, rs, rt, cc, 0);
10906: break;
10907: case FMT_SDPS_PS:
10908: gen_movcf_ps(rs, rt, cc, 0);
10909: break;
10910: default:
10911: goto pool32f_invalid;
10912: }
10913: break;
10914: case MOVT_FMT:
10915: switch (fmt) {
10916: case FMT_SDPS_S:
10917: gen_movcf_s(rs, rt, cc, 1);
10918: break;
10919: case FMT_SDPS_D:
10920: gen_movcf_d(ctx, rs, rt, cc, 1);
10921: break;
10922: case FMT_SDPS_PS:
10923: gen_movcf_ps(rs, rt, cc, 1);
10924: break;
10925: default:
10926: goto pool32f_invalid;
10927: }
10928: break;
10929: case PREFX:
10930: break;
10931: default:
10932: goto pool32f_invalid;
10933: }
10934: break;
10935: #define FINSN_3ARG_SDPS(prfx) \
10936: switch ((ctx->opcode >> 8) & 0x3) { \
10937: case FMT_SDPS_S: \
10938: mips32_op = OPC_##prfx##_S; \
10939: goto do_fpop; \
10940: case FMT_SDPS_D: \
10941: mips32_op = OPC_##prfx##_D; \
10942: goto do_fpop; \
10943: case FMT_SDPS_PS: \
10944: mips32_op = OPC_##prfx##_PS; \
10945: goto do_fpop; \
10946: default: \
10947: goto pool32f_invalid; \
10948: }
10949: case 0x30:
10950: /* regular FP ops */
10951: switch ((ctx->opcode >> 6) & 0x3) {
10952: case ADD_FMT:
10953: FINSN_3ARG_SDPS(ADD);
10954: break;
10955: case SUB_FMT:
10956: FINSN_3ARG_SDPS(SUB);
10957: break;
10958: case MUL_FMT:
10959: FINSN_3ARG_SDPS(MUL);
10960: break;
10961: case DIV_FMT:
10962: fmt = (ctx->opcode >> 8) & 0x3;
10963: if (fmt == 1) {
10964: mips32_op = OPC_DIV_D;
10965: } else if (fmt == 0) {
10966: mips32_op = OPC_DIV_S;
10967: } else {
10968: goto pool32f_invalid;
10969: }
10970: goto do_fpop;
10971: default:
10972: goto pool32f_invalid;
10973: }
10974: break;
10975: case 0x38:
10976: /* cmovs */
10977: switch ((ctx->opcode >> 6) & 0x3) {
10978: case MOVN_FMT:
10979: FINSN_3ARG_SDPS(MOVN);
10980: break;
10981: case MOVZ_FMT:
10982: FINSN_3ARG_SDPS(MOVZ);
10983: break;
10984: default:
10985: goto pool32f_invalid;
10986: }
10987: break;
10988: do_fpop:
10989: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10990: break;
10991: default:
10992: pool32f_invalid:
10993: MIPS_INVAL("pool32f");
10994: generate_exception(ctx, EXCP_RI);
10995: break;
10996: }
10997: } else {
10998: generate_exception_err(ctx, EXCP_CpU, 1);
10999: }
11000: break;
11001: case POOL32I:
11002: minor = (ctx->opcode >> 21) & 0x1f;
11003: switch (minor) {
11004: case BLTZ:
11005: mips32_op = OPC_BLTZ;
11006: goto do_branch;
11007: case BLTZAL:
11008: mips32_op = OPC_BLTZAL;
11009: goto do_branch;
11010: case BLTZALS:
11011: mips32_op = OPC_BLTZALS;
11012: goto do_branch;
11013: case BGEZ:
11014: mips32_op = OPC_BGEZ;
11015: goto do_branch;
11016: case BGEZAL:
11017: mips32_op = OPC_BGEZAL;
11018: goto do_branch;
11019: case BGEZALS:
11020: mips32_op = OPC_BGEZALS;
11021: goto do_branch;
11022: case BLEZ:
11023: mips32_op = OPC_BLEZ;
11024: goto do_branch;
11025: case BGTZ:
11026: mips32_op = OPC_BGTZ;
11027: do_branch:
11028: gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11029: *is_branch = 1;
11030: break;
11031:
11032: /* Traps */
11033: case TLTI:
11034: mips32_op = OPC_TLTI;
11035: goto do_trapi;
11036: case TGEI:
11037: mips32_op = OPC_TGEI;
11038: goto do_trapi;
11039: case TLTIU:
11040: mips32_op = OPC_TLTIU;
11041: goto do_trapi;
11042: case TGEIU:
11043: mips32_op = OPC_TGEIU;
11044: goto do_trapi;
11045: case TNEI:
11046: mips32_op = OPC_TNEI;
11047: goto do_trapi;
11048: case TEQI:
11049: mips32_op = OPC_TEQI;
11050: do_trapi:
11051: gen_trap(ctx, mips32_op, rs, -1, imm);
11052: break;
11053:
11054: case BNEZC:
11055: case BEQZC:
11056: gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11057: 4, rs, 0, imm << 1);
11058: /* Compact branches don't have a delay slot, so just let
11059: the normal delay slot handling take us to the branch
11060: target. */
11061: break;
11062: case LUI:
11063: gen_logic_imm(env, OPC_LUI, rs, -1, imm);
11064: break;
11065: case SYNCI:
11066: break;
11067: case BC2F:
11068: case BC2T:
11069: /* COP2: Not implemented. */
11070: generate_exception_err(ctx, EXCP_CpU, 2);
11071: break;
11072: case BC1F:
11073: mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11074: goto do_cp1branch;
11075: case BC1T:
11076: mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11077: goto do_cp1branch;
11078: case BC1ANY4F:
11079: mips32_op = OPC_BC1FANY4;
11080: goto do_cp1mips3d;
11081: case BC1ANY4T:
11082: mips32_op = OPC_BC1TANY4;
11083: do_cp1mips3d:
11084: check_cop1x(ctx);
11085: check_insn(env, ctx, ASE_MIPS3D);
11086: /* Fall through */
11087: do_cp1branch:
11088: gen_compute_branch1(env, ctx, mips32_op,
11089: (ctx->opcode >> 18) & 0x7, imm << 1);
11090: *is_branch = 1;
11091: break;
11092: case BPOSGE64:
11093: case BPOSGE32:
11094: /* MIPS DSP: not implemented */
11095: /* Fall through */
11096: default:
11097: MIPS_INVAL("pool32i");
11098: generate_exception(ctx, EXCP_RI);
11099: break;
11100: }
11101: break;
11102: case POOL32C:
11103: minor = (ctx->opcode >> 12) & 0xf;
11104: switch (minor) {
11105: case LWL:
11106: mips32_op = OPC_LWL;
11107: goto do_ld_lr;
11108: case SWL:
11109: mips32_op = OPC_SWL;
11110: goto do_st_lr;
11111: case LWR:
11112: mips32_op = OPC_LWR;
11113: goto do_ld_lr;
11114: case SWR:
11115: mips32_op = OPC_SWR;
11116: goto do_st_lr;
11117: #if defined(TARGET_MIPS64)
11118: case LDL:
11119: mips32_op = OPC_LDL;
11120: goto do_ld_lr;
11121: case SDL:
11122: mips32_op = OPC_SDL;
11123: goto do_st_lr;
11124: case LDR:
11125: mips32_op = OPC_LDR;
11126: goto do_ld_lr;
11127: case SDR:
11128: mips32_op = OPC_SDR;
11129: goto do_st_lr;
11130: case LWU:
11131: mips32_op = OPC_LWU;
11132: goto do_ld_lr;
11133: case LLD:
11134: mips32_op = OPC_LLD;
11135: goto do_ld_lr;
11136: #endif
11137: case LL:
11138: mips32_op = OPC_LL;
11139: goto do_ld_lr;
11140: do_ld_lr:
11141: gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11142: break;
11143: do_st_lr:
11144: gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11145: break;
11146: case SC:
11147: gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11148: break;
11149: #if defined(TARGET_MIPS64)
11150: case SCD:
11151: gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11152: break;
11153: #endif
11154: case PREF:
11155: /* Treat as no-op */
11156: break;
11157: default:
11158: MIPS_INVAL("pool32c");
11159: generate_exception(ctx, EXCP_RI);
11160: break;
11161: }
11162: break;
11163: case ADDI32:
11164: mips32_op = OPC_ADDI;
11165: goto do_addi;
11166: case ADDIU32:
11167: mips32_op = OPC_ADDIU;
11168: do_addi:
11169: gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11170: break;
11171:
11172: /* Logical operations */
11173: case ORI32:
11174: mips32_op = OPC_ORI;
11175: goto do_logici;
11176: case XORI32:
11177: mips32_op = OPC_XORI;
11178: goto do_logici;
11179: case ANDI32:
11180: mips32_op = OPC_ANDI;
11181: do_logici:
11182: gen_logic_imm(env, mips32_op, rt, rs, imm);
11183: break;
11184:
11185: /* Set less than immediate */
11186: case SLTI32:
11187: mips32_op = OPC_SLTI;
11188: goto do_slti;
11189: case SLTIU32:
11190: mips32_op = OPC_SLTIU;
11191: do_slti:
11192: gen_slt_imm(env, mips32_op, rt, rs, imm);
11193: break;
11194: case JALX32:
11195: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11196: gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11197: *is_branch = 1;
11198: break;
11199: case JALS32:
11200: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11201: gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11202: *is_branch = 1;
11203: break;
11204: case BEQ32:
11205: gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11206: *is_branch = 1;
11207: break;
11208: case BNE32:
11209: gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11210: *is_branch = 1;
11211: break;
11212: case J32:
11213: gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11214: (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11215: *is_branch = 1;
11216: break;
11217: case JAL32:
11218: gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11219: (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11220: *is_branch = 1;
11221: break;
11222: /* Floating point (COP1) */
11223: case LWC132:
11224: mips32_op = OPC_LWC1;
11225: goto do_cop1;
11226: case LDC132:
11227: mips32_op = OPC_LDC1;
11228: goto do_cop1;
11229: case SWC132:
11230: mips32_op = OPC_SWC1;
11231: goto do_cop1;
11232: case SDC132:
11233: mips32_op = OPC_SDC1;
11234: do_cop1:
11235: gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11236: break;
11237: case ADDIUPC:
11238: {
11239: int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11240: int offset = SIMM(ctx->opcode, 0, 23) << 2;
11241:
11242: gen_addiupc(ctx, reg, offset, 0, 0);
11243: }
11244: break;
11245: /* Loads and stores */
11246: case LB32:
11247: mips32_op = OPC_LB;
11248: goto do_ld;
11249: case LBU32:
11250: mips32_op = OPC_LBU;
11251: goto do_ld;
11252: case LH32:
11253: mips32_op = OPC_LH;
11254: goto do_ld;
11255: case LHU32:
11256: mips32_op = OPC_LHU;
11257: goto do_ld;
11258: case LW32:
11259: mips32_op = OPC_LW;
11260: goto do_ld;
11261: #ifdef TARGET_MIPS64
11262: case LD32:
11263: mips32_op = OPC_LD;
11264: goto do_ld;
11265: case SD32:
11266: mips32_op = OPC_SD;
11267: goto do_st;
11268: #endif
11269: case SB32:
11270: mips32_op = OPC_SB;
11271: goto do_st;
11272: case SH32:
11273: mips32_op = OPC_SH;
11274: goto do_st;
11275: case SW32:
11276: mips32_op = OPC_SW;
11277: goto do_st;
11278: do_ld:
11279: gen_ld(env, ctx, mips32_op, rt, rs, imm);
11280: break;
11281: do_st:
11282: gen_st(ctx, mips32_op, rt, rs, imm);
11283: break;
11284: default:
11285: generate_exception(ctx, EXCP_RI);
11286: break;
11287: }
11288: }
11289:
11290: static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11291: {
11292: uint32_t op;
11293:
11294: /* make sure instructions are on a halfword boundary */
11295: if (ctx->pc & 0x1) {
11296: env->CP0_BadVAddr = ctx->pc;
11297: generate_exception(ctx, EXCP_AdEL);
11298: ctx->bstate = BS_STOP;
11299: return 2;
11300: }
11301:
11302: op = (ctx->opcode >> 10) & 0x3f;
11303: /* Enforce properly-sized instructions in a delay slot */
11304: if (ctx->hflags & MIPS_HFLAG_BMASK) {
11305: int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11306:
11307: switch (op) {
11308: case POOL32A:
11309: case POOL32B:
11310: case POOL32I:
11311: case POOL32C:
11312: case ADDI32:
11313: case ADDIU32:
11314: case ORI32:
11315: case XORI32:
11316: case SLTI32:
11317: case SLTIU32:
11318: case ANDI32:
11319: case JALX32:
11320: case LBU32:
11321: case LHU32:
11322: case POOL32F:
11323: case JALS32:
11324: case BEQ32:
11325: case BNE32:
11326: case J32:
11327: case JAL32:
11328: case SB32:
11329: case SH32:
11330: case POOL32S:
11331: case ADDIUPC:
11332: case SWC132:
11333: case SDC132:
11334: case SD32:
11335: case SW32:
11336: case LB32:
11337: case LH32:
11338: case DADDIU32:
11339: case POOL48A: /* ??? */
11340: case LWC132:
11341: case LDC132:
11342: case LD32:
11343: case LW32:
11344: if (bits & MIPS_HFLAG_BDS16) {
11345: generate_exception(ctx, EXCP_RI);
11346: /* Just stop translation; the user is confused. */
11347: ctx->bstate = BS_STOP;
11348: return 2;
11349: }
11350: break;
11351: case POOL16A:
11352: case POOL16B:
11353: case POOL16C:
11354: case LWGP16:
11355: case POOL16F:
11356: case LBU16:
11357: case LHU16:
11358: case LWSP16:
11359: case LW16:
11360: case SB16:
11361: case SH16:
11362: case SWSP16:
11363: case SW16:
11364: case MOVE16:
11365: case ANDI16:
11366: case POOL16D:
11367: case POOL16E:
11368: case BEQZ16:
11369: case BNEZ16:
11370: case B16:
11371: case LI16:
11372: if (bits & MIPS_HFLAG_BDS32) {
11373: generate_exception(ctx, EXCP_RI);
11374: /* Just stop translation; the user is confused. */
11375: ctx->bstate = BS_STOP;
11376: return 2;
11377: }
11378: break;
11379: default:
11380: break;
11381: }
11382: }
11383: switch (op) {
11384: case POOL16A:
11385: {
11386: int rd = mmreg(uMIPS_RD(ctx->opcode));
11387: int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11388: int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11389: uint32_t opc = 0;
11390:
11391: switch (ctx->opcode & 0x1) {
11392: case ADDU16:
11393: opc = OPC_ADDU;
11394: break;
11395: case SUBU16:
11396: opc = OPC_SUBU;
11397: break;
11398: }
11399:
11400: gen_arith(env, ctx, opc, rd, rs1, rs2);
11401: }
11402: break;
11403: case POOL16B:
11404: {
11405: int rd = mmreg(uMIPS_RD(ctx->opcode));
11406: int rs = mmreg(uMIPS_RS(ctx->opcode));
11407: int amount = (ctx->opcode >> 1) & 0x7;
11408: uint32_t opc = 0;
11409: amount = amount == 0 ? 8 : amount;
11410:
11411: switch (ctx->opcode & 0x1) {
11412: case SLL16:
11413: opc = OPC_SLL;
11414: break;
11415: case SRL16:
11416: opc = OPC_SRL;
11417: break;
11418: }
11419:
11420: gen_shift_imm(env, ctx, opc, rd, rs, amount);
11421: }
11422: break;
11423: case POOL16C:
11424: gen_pool16c_insn(env, ctx, is_branch);
11425: break;
11426: case LWGP16:
11427: {
11428: int rd = mmreg(uMIPS_RD(ctx->opcode));
11429: int rb = 28; /* GP */
11430: int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11431:
11432: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11433: }
11434: break;
11435: case POOL16F:
11436: if (ctx->opcode & 1) {
11437: generate_exception(ctx, EXCP_RI);
11438: } else {
11439: /* MOVEP */
11440: int enc_dest = uMIPS_RD(ctx->opcode);
11441: int enc_rt = uMIPS_RS2(ctx->opcode);
11442: int enc_rs = uMIPS_RS1(ctx->opcode);
11443: int rd, rs, re, rt;
11444: static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11445: static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11446: static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11447:
11448: rd = rd_enc[enc_dest];
11449: re = re_enc[enc_dest];
11450: rs = rs_rt_enc[enc_rs];
11451: rt = rs_rt_enc[enc_rt];
11452:
11453: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11454: gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11455: }
11456: break;
11457: case LBU16:
11458: {
11459: int rd = mmreg(uMIPS_RD(ctx->opcode));
11460: int rb = mmreg(uMIPS_RS(ctx->opcode));
11461: int16_t offset = ZIMM(ctx->opcode, 0, 4);
11462: offset = (offset == 0xf ? -1 : offset);
11463:
11464: gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
11465: }
11466: break;
11467: case LHU16:
11468: {
11469: int rd = mmreg(uMIPS_RD(ctx->opcode));
11470: int rb = mmreg(uMIPS_RS(ctx->opcode));
11471: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11472:
11473: gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
11474: }
11475: break;
11476: case LWSP16:
11477: {
11478: int rd = (ctx->opcode >> 5) & 0x1f;
11479: int rb = 29; /* SP */
11480: int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11481:
11482: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11483: }
11484: break;
11485: case LW16:
11486: {
11487: int rd = mmreg(uMIPS_RD(ctx->opcode));
11488: int rb = mmreg(uMIPS_RS(ctx->opcode));
11489: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11490:
11491: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11492: }
11493: break;
11494: case SB16:
11495: {
11496: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11497: int rb = mmreg(uMIPS_RS(ctx->opcode));
11498: int16_t offset = ZIMM(ctx->opcode, 0, 4);
11499:
11500: gen_st(ctx, OPC_SB, rd, rb, offset);
11501: }
11502: break;
11503: case SH16:
11504: {
11505: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11506: int rb = mmreg(uMIPS_RS(ctx->opcode));
11507: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11508:
11509: gen_st(ctx, OPC_SH, rd, rb, offset);
11510: }
11511: break;
11512: case SWSP16:
11513: {
11514: int rd = (ctx->opcode >> 5) & 0x1f;
11515: int rb = 29; /* SP */
11516: int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11517:
11518: gen_st(ctx, OPC_SW, rd, rb, offset);
11519: }
11520: break;
11521: case SW16:
11522: {
11523: int rd = mmreg2(uMIPS_RD(ctx->opcode));
11524: int rb = mmreg(uMIPS_RS(ctx->opcode));
11525: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11526:
11527: gen_st(ctx, OPC_SW, rd, rb, offset);
11528: }
11529: break;
11530: case MOVE16:
11531: {
11532: int rd = uMIPS_RD5(ctx->opcode);
11533: int rs = uMIPS_RS5(ctx->opcode);
11534:
11535: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11536: }
11537: break;
11538: case ANDI16:
11539: gen_andi16(env, ctx);
11540: break;
11541: case POOL16D:
11542: switch (ctx->opcode & 0x1) {
11543: case ADDIUS5:
11544: gen_addius5(env, ctx);
11545: break;
11546: case ADDIUSP:
11547: gen_addiusp(env, ctx);
11548: break;
11549: }
11550: break;
11551: case POOL16E:
11552: switch (ctx->opcode & 0x1) {
11553: case ADDIUR2:
11554: gen_addiur2(env, ctx);
11555: break;
11556: case ADDIUR1SP:
11557: gen_addiur1sp(env, ctx);
11558: break;
11559: }
11560: break;
11561: case B16:
11562: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
11563: SIMM(ctx->opcode, 0, 10) << 1);
11564: *is_branch = 1;
11565: break;
11566: case BNEZ16:
11567: case BEQZ16:
11568: gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
11569: mmreg(uMIPS_RD(ctx->opcode)),
11570: 0, SIMM(ctx->opcode, 0, 7) << 1);
11571: *is_branch = 1;
11572: break;
11573: case LI16:
11574: {
11575: int reg = mmreg(uMIPS_RD(ctx->opcode));
11576: int imm = ZIMM(ctx->opcode, 0, 7);
11577:
11578: imm = (imm == 0x7f ? -1 : imm);
11579: tcg_gen_movi_tl(cpu_gpr[reg], imm);
11580: }
11581: break;
11582: case RES_20:
11583: case RES_28:
11584: case RES_29:
11585: case RES_30:
11586: case RES_31:
11587: case RES_38:
11588: case RES_39:
11589: generate_exception(ctx, EXCP_RI);
11590: break;
11591: default:
11592: decode_micromips32_opc (env, ctx, op, is_branch);
11593: return 4;
11594: }
11595:
11596: return 2;
11597: }
11598:
11599: /* SmartMIPS extension to MIPS32 */
11600:
11601: #if defined(TARGET_MIPS64)
11602:
11603: /* MDMX extension to MIPS64 */
11604:
11605: #endif
11606:
11607: static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11608: {
11609: int32_t offset;
11610: int rs, rt, rd, sa;
11611: uint32_t op, op1, op2;
11612: int16_t imm;
11613:
11614: /* make sure instructions are on a word boundary */
11615: if (ctx->pc & 0x3) {
11616: env->CP0_BadVAddr = ctx->pc;
11617: generate_exception(ctx, EXCP_AdEL);
11618: return;
11619: }
11620:
11621: /* Handle blikely not taken case */
11622: if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
11623: int l1 = gen_new_label();
11624:
11625: MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
1.1.1.8 root 11626: tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11627: tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
1.1.1.6 root 11628: gen_goto_tb(ctx, 1, ctx->pc + 4);
11629: gen_set_label(l1);
1.1 root 11630: }
1.1.1.9 root 11631:
11632: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11633: tcg_gen_debug_insn_start(ctx->pc);
11634:
1.1.1.5 root 11635: op = MASK_OP_MAJOR(ctx->opcode);
11636: rs = (ctx->opcode >> 21) & 0x1f;
11637: rt = (ctx->opcode >> 16) & 0x1f;
11638: rd = (ctx->opcode >> 11) & 0x1f;
11639: sa = (ctx->opcode >> 6) & 0x1f;
1.1 root 11640: imm = (int16_t)ctx->opcode;
11641: switch (op) {
1.1.1.5 root 11642: case OPC_SPECIAL:
11643: op1 = MASK_SPECIAL(ctx->opcode);
1.1 root 11644: switch (op1) {
1.1.1.8 root 11645: case OPC_SLL: /* Shift with immediate */
11646: case OPC_SRA:
11647: gen_shift_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 11648: break;
1.1.1.12 root 11649: case OPC_SRL:
11650: switch ((ctx->opcode >> 21) & 0x1f) {
11651: case 1:
11652: /* rotr is decoded as srl on non-R2 CPUs */
11653: if (env->insn_flags & ISA_MIPS32R2) {
11654: op1 = OPC_ROTR;
11655: }
11656: /* Fallthrough */
11657: case 0:
11658: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11659: break;
11660: default:
11661: generate_exception(ctx, EXCP_RI);
11662: break;
11663: }
11664: break;
1.1.1.8 root 11665: case OPC_MOVN: /* Conditional move */
11666: case OPC_MOVZ:
1.1.1.12 root 11667: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
11668: INSN_LOONGSON2E | INSN_LOONGSON2F);
1.1.1.8 root 11669: gen_cond_move(env, op1, rd, rs, rt);
11670: break;
11671: case OPC_ADD ... OPC_SUBU:
1.1.1.6 root 11672: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 11673: break;
1.1.1.8 root 11674: case OPC_SLLV: /* Shifts */
11675: case OPC_SRAV:
11676: gen_shift(env, ctx, op1, rd, rs, rt);
11677: break;
1.1.1.12 root 11678: case OPC_SRLV:
11679: switch ((ctx->opcode >> 6) & 0x1f) {
11680: case 1:
11681: /* rotrv is decoded as srlv on non-R2 CPUs */
11682: if (env->insn_flags & ISA_MIPS32R2) {
11683: op1 = OPC_ROTRV;
11684: }
11685: /* Fallthrough */
11686: case 0:
11687: gen_shift(env, ctx, op1, rd, rs, rt);
11688: break;
11689: default:
11690: generate_exception(ctx, EXCP_RI);
11691: break;
11692: }
11693: break;
1.1.1.8 root 11694: case OPC_SLT: /* Set on less than */
11695: case OPC_SLTU:
11696: gen_slt(env, op1, rd, rs, rt);
11697: break;
11698: case OPC_AND: /* Logic*/
11699: case OPC_OR:
11700: case OPC_NOR:
11701: case OPC_XOR:
11702: gen_logic(env, op1, rd, rs, rt);
11703: break;
1.1.1.5 root 11704: case OPC_MULT ... OPC_DIVU:
1.1.1.6 root 11705: if (sa) {
11706: check_insn(env, ctx, INSN_VR54XX);
11707: op1 = MASK_MUL_VR54XX(ctx->opcode);
11708: gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11709: } else
11710: gen_muldiv(ctx, op1, rs, rt);
1.1 root 11711: break;
1.1.1.5 root 11712: case OPC_JR ... OPC_JALR:
1.1.1.12 root 11713: gen_compute_branch(ctx, op1, 4, rs, rd, sa);
11714: *is_branch = 1;
11715: break;
1.1.1.5 root 11716: case OPC_TGE ... OPC_TEQ: /* Traps */
11717: case OPC_TNE:
11718: gen_trap(ctx, op1, rs, rt, -1);
11719: break;
11720: case OPC_MFHI: /* Move from HI/LO */
11721: case OPC_MFLO:
11722: gen_HILO(ctx, op1, rd);
1.1 root 11723: break;
1.1.1.5 root 11724: case OPC_MTHI:
11725: case OPC_MTLO: /* Move to HI/LO */
11726: gen_HILO(ctx, op1, rs);
11727: break;
1.1.1.6 root 11728: case OPC_PMON: /* Pmon entry point, also R4010 selsl */
11729: #ifdef MIPS_STRICT_STANDARD
11730: MIPS_INVAL("PMON / selsl");
11731: generate_exception(ctx, EXCP_RI);
11732: #else
1.1.1.7 root 11733: gen_helper_0i(pmon, sa);
1.1.1.6 root 11734: #endif
1.1.1.5 root 11735: break;
11736: case OPC_SYSCALL:
1.1 root 11737: generate_exception(ctx, EXCP_SYSCALL);
1.1.1.8 root 11738: ctx->bstate = BS_STOP;
1.1 root 11739: break;
1.1.1.5 root 11740: case OPC_BREAK:
1.1 root 11741: generate_exception(ctx, EXCP_BREAK);
11742: break;
1.1.1.6 root 11743: case OPC_SPIM:
11744: #ifdef MIPS_STRICT_STANDARD
11745: MIPS_INVAL("SPIM");
11746: generate_exception(ctx, EXCP_RI);
11747: #else
1.1.1.5 root 11748: /* Implemented as RI exception for now. */
11749: MIPS_INVAL("spim (unofficial)");
11750: generate_exception(ctx, EXCP_RI);
1.1.1.6 root 11751: #endif
1.1 root 11752: break;
1.1.1.5 root 11753: case OPC_SYNC:
1.1.1.6 root 11754: /* Treat as NOP. */
1.1 root 11755: break;
1.1.1.2 root 11756:
1.1.1.5 root 11757: case OPC_MOVCI:
1.1.1.6 root 11758: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
11759: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11760: check_cp1_enabled(ctx);
11761: gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11762: (ctx->opcode >> 16) & 1);
11763: } else {
11764: generate_exception_err(ctx, EXCP_CpU, 1);
11765: }
1.1.1.2 root 11766: break;
11767:
1.1.1.6 root 11768: #if defined(TARGET_MIPS64)
1.1.1.5 root 11769: /* MIPS64 specific opcodes */
11770: case OPC_DSLL:
1.1.1.8 root 11771: case OPC_DSRA:
1.1.1.5 root 11772: case OPC_DSLL32:
1.1.1.8 root 11773: case OPC_DSRA32:
1.1.1.6 root 11774: check_insn(env, ctx, ISA_MIPS3);
11775: check_mips_64(ctx);
1.1.1.8 root 11776: gen_shift_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 11777: break;
1.1.1.12 root 11778: case OPC_DSRL:
11779: switch ((ctx->opcode >> 21) & 0x1f) {
11780: case 1:
11781: /* drotr is decoded as dsrl on non-R2 CPUs */
11782: if (env->insn_flags & ISA_MIPS32R2) {
11783: op1 = OPC_DROTR;
11784: }
11785: /* Fallthrough */
11786: case 0:
11787: check_insn(env, ctx, ISA_MIPS3);
11788: check_mips_64(ctx);
11789: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11790: break;
11791: default:
11792: generate_exception(ctx, EXCP_RI);
11793: break;
11794: }
11795: break;
11796: case OPC_DSRL32:
11797: switch ((ctx->opcode >> 21) & 0x1f) {
11798: case 1:
11799: /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
11800: if (env->insn_flags & ISA_MIPS32R2) {
11801: op1 = OPC_DROTR32;
11802: }
11803: /* Fallthrough */
11804: case 0:
11805: check_insn(env, ctx, ISA_MIPS3);
11806: check_mips_64(ctx);
11807: gen_shift_imm(env, ctx, op1, rd, rt, sa);
11808: break;
11809: default:
11810: generate_exception(ctx, EXCP_RI);
11811: break;
11812: }
11813: break;
1.1.1.5 root 11814: case OPC_DADD ... OPC_DSUBU:
1.1.1.6 root 11815: check_insn(env, ctx, ISA_MIPS3);
11816: check_mips_64(ctx);
11817: gen_arith(env, ctx, op1, rd, rs, rt);
1.1.1.5 root 11818: break;
1.1.1.8 root 11819: case OPC_DSLLV:
11820: case OPC_DSRAV:
11821: check_insn(env, ctx, ISA_MIPS3);
11822: check_mips_64(ctx);
11823: gen_shift(env, ctx, op1, rd, rs, rt);
11824: break;
1.1.1.12 root 11825: case OPC_DSRLV:
11826: switch ((ctx->opcode >> 6) & 0x1f) {
11827: case 1:
11828: /* drotrv is decoded as dsrlv on non-R2 CPUs */
11829: if (env->insn_flags & ISA_MIPS32R2) {
11830: op1 = OPC_DROTRV;
11831: }
11832: /* Fallthrough */
11833: case 0:
11834: check_insn(env, ctx, ISA_MIPS3);
11835: check_mips_64(ctx);
11836: gen_shift(env, ctx, op1, rd, rs, rt);
11837: break;
11838: default:
11839: generate_exception(ctx, EXCP_RI);
11840: break;
11841: }
11842: break;
1.1.1.5 root 11843: case OPC_DMULT ... OPC_DDIVU:
1.1.1.6 root 11844: check_insn(env, ctx, ISA_MIPS3);
11845: check_mips_64(ctx);
1.1.1.5 root 11846: gen_muldiv(ctx, op1, rs, rt);
11847: break;
1.1 root 11848: #endif
11849: default: /* Invalid */
11850: MIPS_INVAL("special");
11851: generate_exception(ctx, EXCP_RI);
11852: break;
11853: }
11854: break;
1.1.1.5 root 11855: case OPC_SPECIAL2:
11856: op1 = MASK_SPECIAL2(ctx->opcode);
1.1 root 11857: switch (op1) {
1.1.1.5 root 11858: case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11859: case OPC_MSUB ... OPC_MSUBU:
1.1.1.6 root 11860: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 11861: gen_muldiv(ctx, op1, rs, rt);
1.1 root 11862: break;
1.1.1.5 root 11863: case OPC_MUL:
1.1.1.6 root 11864: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 11865: break;
1.1.1.8 root 11866: case OPC_CLO:
11867: case OPC_CLZ:
1.1.1.6 root 11868: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 11869: gen_cl(ctx, op1, rd, rs);
1.1 root 11870: break;
1.1.1.5 root 11871: case OPC_SDBBP:
1.1 root 11872: /* XXX: not clear which exception should be raised
11873: * when in debug mode...
11874: */
1.1.1.6 root 11875: check_insn(env, ctx, ISA_MIPS32);
1.1 root 11876: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11877: generate_exception(ctx, EXCP_DBp);
11878: } else {
11879: generate_exception(ctx, EXCP_DBp);
11880: }
1.1.1.6 root 11881: /* Treat as NOP. */
1.1 root 11882: break;
1.1.1.12 root 11883: case OPC_DIV_G_2F:
11884: case OPC_DIVU_G_2F:
11885: case OPC_MULT_G_2F:
11886: case OPC_MULTU_G_2F:
11887: case OPC_MOD_G_2F:
11888: case OPC_MODU_G_2F:
11889: check_insn(env, ctx, INSN_LOONGSON2F);
11890: gen_loongson_integer(ctx, op1, rd, rs, rt);
11891: break;
1.1.1.6 root 11892: #if defined(TARGET_MIPS64)
1.1.1.8 root 11893: case OPC_DCLO:
11894: case OPC_DCLZ:
1.1.1.6 root 11895: check_insn(env, ctx, ISA_MIPS64);
11896: check_mips_64(ctx);
1.1.1.5 root 11897: gen_cl(ctx, op1, rd, rs);
11898: break;
1.1.1.12 root 11899: case OPC_DMULT_G_2F:
11900: case OPC_DMULTU_G_2F:
11901: case OPC_DDIV_G_2F:
11902: case OPC_DDIVU_G_2F:
11903: case OPC_DMOD_G_2F:
11904: case OPC_DMODU_G_2F:
11905: check_insn(env, ctx, INSN_LOONGSON2F);
11906: gen_loongson_integer(ctx, op1, rd, rs, rt);
11907: break;
1.1.1.5 root 11908: #endif
1.1 root 11909: default: /* Invalid */
11910: MIPS_INVAL("special2");
11911: generate_exception(ctx, EXCP_RI);
11912: break;
11913: }
11914: break;
1.1.1.5 root 11915: case OPC_SPECIAL3:
1.1.1.7 root 11916: op1 = MASK_SPECIAL3(ctx->opcode);
11917: switch (op1) {
11918: case OPC_EXT:
11919: case OPC_INS:
11920: check_insn(env, ctx, ISA_MIPS32R2);
11921: gen_bitops(ctx, op1, rt, rs, sa, rd);
11922: break;
11923: case OPC_BSHFL:
11924: check_insn(env, ctx, ISA_MIPS32R2);
11925: op2 = MASK_BSHFL(ctx->opcode);
11926: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 11927: break;
11928: case OPC_RDHWR:
1.1.1.12 root 11929: gen_rdhwr(env, ctx, rt, rd);
1.1.1.6 root 11930: break;
11931: case OPC_FORK:
11932: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 11933: {
1.1.1.8 root 11934: TCGv t0 = tcg_temp_new();
11935: TCGv t1 = tcg_temp_new();
1.1.1.7 root 11936:
11937: gen_load_gpr(t0, rt);
11938: gen_load_gpr(t1, rs);
11939: gen_helper_fork(t0, t1);
11940: tcg_temp_free(t0);
11941: tcg_temp_free(t1);
11942: }
1.1.1.6 root 11943: break;
11944: case OPC_YIELD:
11945: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 11946: {
1.1.1.8 root 11947: TCGv t0 = tcg_temp_new();
1.1.1.7 root 11948:
1.1.1.8 root 11949: save_cpu_state(ctx, 1);
1.1.1.7 root 11950: gen_load_gpr(t0, rs);
11951: gen_helper_yield(t0, t0);
11952: gen_store_gpr(t0, rd);
11953: tcg_temp_free(t0);
11954: }
1.1.1.6 root 11955: break;
1.1.1.12 root 11956: case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
11957: case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
11958: case OPC_MOD_G_2E ... OPC_MODU_G_2E:
11959: check_insn(env, ctx, INSN_LOONGSON2E);
11960: gen_loongson_integer(ctx, op1, rd, rs, rt);
11961: break;
1.1.1.6 root 11962: #if defined(TARGET_MIPS64)
11963: case OPC_DEXTM ... OPC_DEXT:
11964: case OPC_DINSM ... OPC_DINS:
11965: check_insn(env, ctx, ISA_MIPS64R2);
11966: check_mips_64(ctx);
1.1.1.5 root 11967: gen_bitops(ctx, op1, rt, rs, sa, rd);
11968: break;
1.1.1.6 root 11969: case OPC_DBSHFL:
11970: check_insn(env, ctx, ISA_MIPS64R2);
11971: check_mips_64(ctx);
11972: op2 = MASK_DBSHFL(ctx->opcode);
1.1.1.7 root 11973: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 11974: break;
1.1.1.12 root 11975: case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
11976: case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
11977: case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
11978: check_insn(env, ctx, INSN_LOONGSON2E);
11979: gen_loongson_integer(ctx, op1, rd, rs, rt);
11980: break;
1.1.1.5 root 11981: #endif
11982: default: /* Invalid */
11983: MIPS_INVAL("special3");
11984: generate_exception(ctx, EXCP_RI);
11985: break;
11986: }
11987: break;
11988: case OPC_REGIMM:
11989: op1 = MASK_REGIMM(ctx->opcode);
1.1 root 11990: switch (op1) {
1.1.1.5 root 11991: case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
11992: case OPC_BLTZAL ... OPC_BGEZALL:
1.1.1.12 root 11993: gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
11994: *is_branch = 1;
11995: break;
1.1.1.5 root 11996: case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
11997: case OPC_TNEI:
11998: gen_trap(ctx, op1, rs, -1, imm);
11999: break;
12000: case OPC_SYNCI:
1.1.1.6 root 12001: check_insn(env, ctx, ISA_MIPS32R2);
12002: /* Treat as NOP. */
1.1 root 12003: break;
12004: default: /* Invalid */
1.1.1.6 root 12005: MIPS_INVAL("regimm");
1.1 root 12006: generate_exception(ctx, EXCP_RI);
12007: break;
12008: }
12009: break;
1.1.1.5 root 12010: case OPC_CP0:
1.1.1.6 root 12011: check_cp0_enabled(ctx);
1.1.1.5 root 12012: op1 = MASK_CP0(ctx->opcode);
1.1 root 12013: switch (op1) {
1.1.1.5 root 12014: case OPC_MFC0:
12015: case OPC_MTC0:
1.1.1.6 root 12016: case OPC_MFTR:
12017: case OPC_MTTR:
12018: #if defined(TARGET_MIPS64)
1.1.1.5 root 12019: case OPC_DMFC0:
12020: case OPC_DMTC0:
12021: #endif
1.1.1.7 root 12022: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 12023: gen_cp0(env, ctx, op1, rt, rd);
1.1.1.7 root 12024: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 12025: break;
12026: case OPC_C0_FIRST ... OPC_C0_LAST:
1.1.1.7 root 12027: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 12028: gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
1.1.1.7 root 12029: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 12030: break;
12031: case OPC_MFMC0:
1.1.1.7 root 12032: #ifndef CONFIG_USER_ONLY
12033: {
1.1.1.8 root 12034: TCGv t0 = tcg_temp_new();
1.1.1.7 root 12035:
12036: op2 = MASK_MFMC0(ctx->opcode);
12037: switch (op2) {
12038: case OPC_DMT:
12039: check_insn(env, ctx, ASE_MT);
1.1.1.13! root 12040: gen_helper_dmt(t0);
1.1.1.8 root 12041: gen_store_gpr(t0, rt);
1.1.1.7 root 12042: break;
12043: case OPC_EMT:
12044: check_insn(env, ctx, ASE_MT);
1.1.1.13! root 12045: gen_helper_emt(t0);
1.1.1.8 root 12046: gen_store_gpr(t0, rt);
1.1.1.7 root 12047: break;
12048: case OPC_DVPE:
12049: check_insn(env, ctx, ASE_MT);
1.1.1.13! root 12050: gen_helper_dvpe(t0);
1.1.1.8 root 12051: gen_store_gpr(t0, rt);
1.1.1.7 root 12052: break;
12053: case OPC_EVPE:
12054: check_insn(env, ctx, ASE_MT);
1.1.1.13! root 12055: gen_helper_evpe(t0);
1.1.1.8 root 12056: gen_store_gpr(t0, rt);
1.1.1.7 root 12057: break;
12058: case OPC_DI:
12059: check_insn(env, ctx, ISA_MIPS32R2);
12060: save_cpu_state(ctx, 1);
12061: gen_helper_di(t0);
1.1.1.8 root 12062: gen_store_gpr(t0, rt);
1.1.1.7 root 12063: /* Stop translation as we may have switched the execution mode */
12064: ctx->bstate = BS_STOP;
12065: break;
12066: case OPC_EI:
12067: check_insn(env, ctx, ISA_MIPS32R2);
12068: save_cpu_state(ctx, 1);
12069: gen_helper_ei(t0);
1.1.1.8 root 12070: gen_store_gpr(t0, rt);
1.1.1.7 root 12071: /* Stop translation as we may have switched the execution mode */
12072: ctx->bstate = BS_STOP;
12073: break;
12074: default: /* Invalid */
12075: MIPS_INVAL("mfmc0");
12076: generate_exception(ctx, EXCP_RI);
12077: break;
12078: }
12079: tcg_temp_free(t0);
1.1.1.5 root 12080: }
1.1.1.7 root 12081: #endif /* !CONFIG_USER_ONLY */
1.1 root 12082: break;
1.1.1.5 root 12083: case OPC_RDPGPR:
1.1.1.6 root 12084: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 root 12085: gen_load_srsgpr(rt, rd);
1.1.1.6 root 12086: break;
1.1.1.5 root 12087: case OPC_WRPGPR:
1.1.1.6 root 12088: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 root 12089: gen_store_srsgpr(rt, rd);
1.1.1.6 root 12090: break;
1.1 root 12091: default:
1.1.1.6 root 12092: MIPS_INVAL("cp0");
1.1.1.5 root 12093: generate_exception(ctx, EXCP_RI);
1.1 root 12094: break;
12095: }
12096: break;
1.1.1.8 root 12097: case OPC_ADDI: /* Arithmetic with immediate opcode */
12098: case OPC_ADDIU:
1.1.1.6 root 12099: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 12100: break;
1.1.1.8 root 12101: case OPC_SLTI: /* Set on less than with immediate opcode */
12102: case OPC_SLTIU:
12103: gen_slt_imm(env, op, rt, rs, imm);
12104: break;
12105: case OPC_ANDI: /* Arithmetic with immediate opcode */
12106: case OPC_LUI:
12107: case OPC_ORI:
12108: case OPC_XORI:
12109: gen_logic_imm(env, op, rt, rs, imm);
12110: break;
1.1.1.5 root 12111: case OPC_J ... OPC_JAL: /* Jump */
12112: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
1.1.1.12 root 12113: gen_compute_branch(ctx, op, 4, rs, rt, offset);
12114: *is_branch = 1;
12115: break;
1.1.1.5 root 12116: case OPC_BEQ ... OPC_BGTZ: /* Branch */
12117: case OPC_BEQL ... OPC_BGTZL:
1.1.1.12 root 12118: gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
12119: *is_branch = 1;
12120: break;
1.1.1.5 root 12121: case OPC_LB ... OPC_LWR: /* Load and stores */
1.1.1.12 root 12122: case OPC_LL:
12123: gen_ld(env, ctx, op, rt, rs, imm);
12124: break;
1.1.1.5 root 12125: case OPC_SB ... OPC_SW:
12126: case OPC_SWR:
1.1.1.12 root 12127: gen_st(ctx, op, rt, rs, imm);
1.1.1.5 root 12128: break;
1.1.1.8 root 12129: case OPC_SC:
12130: gen_st_cond(ctx, op, rt, rs, imm);
12131: break;
1.1.1.5 root 12132: case OPC_CACHE:
1.1.1.6 root 12133: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
12134: /* Treat as NOP. */
12135: break;
1.1.1.5 root 12136: case OPC_PREF:
1.1.1.6 root 12137: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
12138: /* Treat as NOP. */
1.1 root 12139: break;
1.1.1.2 root 12140:
1.1.1.6 root 12141: /* Floating point (COP1). */
1.1.1.5 root 12142: case OPC_LWC1:
12143: case OPC_LDC1:
12144: case OPC_SWC1:
12145: case OPC_SDC1:
1.1.1.12 root 12146: gen_cop1_ldst(env, ctx, op, rt, rs, imm);
1.1.1.4 root 12147: break;
12148:
1.1.1.5 root 12149: case OPC_CP1:
1.1.1.6 root 12150: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12151: check_cp1_enabled(ctx);
12152: op1 = MASK_CP1(ctx->opcode);
12153: switch (op1) {
12154: case OPC_MFHC1:
12155: case OPC_MTHC1:
12156: check_insn(env, ctx, ISA_MIPS32R2);
12157: case OPC_MFC1:
12158: case OPC_CFC1:
12159: case OPC_MTC1:
12160: case OPC_CTC1:
12161: gen_cp1(ctx, op1, rt, rd);
12162: break;
12163: #if defined(TARGET_MIPS64)
12164: case OPC_DMFC1:
12165: case OPC_DMTC1:
12166: check_insn(env, ctx, ISA_MIPS3);
12167: gen_cp1(ctx, op1, rt, rd);
12168: break;
1.1.1.5 root 12169: #endif
1.1.1.6 root 12170: case OPC_BC1ANY2:
12171: case OPC_BC1ANY4:
12172: check_cop1x(ctx);
12173: check_insn(env, ctx, ASE_MIPS3D);
12174: /* fall through */
12175: case OPC_BC1:
12176: gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
12177: (rt >> 2) & 0x7, imm << 2);
1.1.1.12 root 12178: *is_branch = 1;
12179: break;
1.1.1.6 root 12180: case OPC_S_FMT:
12181: case OPC_D_FMT:
12182: case OPC_W_FMT:
12183: case OPC_L_FMT:
12184: case OPC_PS_FMT:
1.1.1.12 root 12185: gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
1.1.1.6 root 12186: (imm >> 8) & 0x7);
12187: break;
12188: default:
12189: MIPS_INVAL("cp1");
12190: generate_exception (ctx, EXCP_RI);
12191: break;
12192: }
12193: } else {
12194: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.4 root 12195: }
1.1.1.2 root 12196: break;
12197:
12198: /* COP2. */
1.1.1.5 root 12199: case OPC_LWC2:
12200: case OPC_LDC2:
12201: case OPC_SWC2:
12202: case OPC_SDC2:
12203: case OPC_CP2:
12204: /* COP2: Not implemented. */
1.1.1.2 root 12205: generate_exception_err(ctx, EXCP_CpU, 2);
12206: break;
12207:
1.1.1.5 root 12208: case OPC_CP3:
1.1.1.6 root 12209: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12210: check_cp1_enabled(ctx);
12211: op1 = MASK_CP3(ctx->opcode);
12212: switch (op1) {
12213: case OPC_LWXC1:
12214: case OPC_LDXC1:
12215: case OPC_LUXC1:
12216: case OPC_SWXC1:
12217: case OPC_SDXC1:
12218: case OPC_SUXC1:
12219: gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
12220: break;
12221: case OPC_PREFX:
12222: /* Treat as NOP. */
12223: break;
12224: case OPC_ALNV_PS:
12225: case OPC_MADD_S:
12226: case OPC_MADD_D:
12227: case OPC_MADD_PS:
12228: case OPC_MSUB_S:
12229: case OPC_MSUB_D:
12230: case OPC_MSUB_PS:
12231: case OPC_NMADD_S:
12232: case OPC_NMADD_D:
12233: case OPC_NMADD_PS:
12234: case OPC_NMSUB_S:
12235: case OPC_NMSUB_D:
12236: case OPC_NMSUB_PS:
12237: gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12238: break;
12239: default:
12240: MIPS_INVAL("cp3");
12241: generate_exception (ctx, EXCP_RI);
12242: break;
12243: }
12244: } else {
12245: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.5 root 12246: }
1.1.1.2 root 12247: break;
12248:
1.1.1.6 root 12249: #if defined(TARGET_MIPS64)
1.1.1.5 root 12250: /* MIPS64 opcodes */
12251: case OPC_LWU:
12252: case OPC_LDL ... OPC_LDR:
12253: case OPC_LLD:
12254: case OPC_LD:
1.1.1.12 root 12255: check_insn(env, ctx, ISA_MIPS3);
12256: check_mips_64(ctx);
12257: gen_ld(env, ctx, op, rt, rs, imm);
12258: break;
12259: case OPC_SDL ... OPC_SDR:
1.1.1.5 root 12260: case OPC_SD:
1.1.1.6 root 12261: check_insn(env, ctx, ISA_MIPS3);
12262: check_mips_64(ctx);
1.1.1.12 root 12263: gen_st(ctx, op, rt, rs, imm);
1.1.1.5 root 12264: break;
1.1.1.8 root 12265: case OPC_SCD:
12266: check_insn(env, ctx, ISA_MIPS3);
12267: check_mips_64(ctx);
12268: gen_st_cond(ctx, op, rt, rs, imm);
12269: break;
12270: case OPC_DADDI:
12271: case OPC_DADDIU:
1.1.1.6 root 12272: check_insn(env, ctx, ISA_MIPS3);
12273: check_mips_64(ctx);
12274: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 12275: break;
12276: #endif
12277: case OPC_JALX:
1.1.1.12 root 12278: check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
12279: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12280: gen_compute_branch(ctx, op, 4, rs, rt, offset);
12281: *is_branch = 1;
12282: break;
1.1.1.5 root 12283: case OPC_MDMX:
1.1.1.6 root 12284: check_insn(env, ctx, ASE_MDMX);
1.1.1.5 root 12285: /* MDMX: Not implemented. */
1.1 root 12286: default: /* Invalid */
1.1.1.6 root 12287: MIPS_INVAL("major opcode");
1.1 root 12288: generate_exception(ctx, EXCP_RI);
12289: break;
12290: }
12291: }
12292:
1.1.1.7 root 12293: static inline void
1.1.1.6 root 12294: gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
12295: int search_pc)
1.1 root 12296: {
1.1.1.6 root 12297: DisasContext ctx;
1.1 root 12298: target_ulong pc_start;
12299: uint16_t *gen_opc_end;
1.1.1.7 root 12300: CPUBreakpoint *bp;
1.1 root 12301: int j, lj = -1;
1.1.1.7 root 12302: int num_insns;
12303: int max_insns;
1.1.1.12 root 12304: int insn_bytes;
12305: int is_branch;
1.1 root 12306:
1.1.1.7 root 12307: if (search_pc)
12308: qemu_log("search pc %d\n", search_pc);
1.1.1.2 root 12309:
1.1 root 12310: pc_start = tb->pc;
1.1.1.9 root 12311: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1.1 root 12312: ctx.pc = pc_start;
1.1.1.2 root 12313: ctx.saved_pc = -1;
1.1.1.9 root 12314: ctx.singlestep_enabled = env->singlestep_enabled;
1.1 root 12315: ctx.tb = tb;
12316: ctx.bstate = BS_NONE;
1.1.1.2 root 12317: /* Restore delay slot state from the tb context. */
1.1.1.6 root 12318: ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
12319: restore_cpu_state(env, &ctx);
1.1.1.7 root 12320: #ifdef CONFIG_USER_ONLY
12321: ctx.mem_idx = MIPS_HFLAG_UM;
1.1 root 12322: #else
1.1.1.7 root 12323: ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
1.1 root 12324: #endif
1.1.1.7 root 12325: num_insns = 0;
12326: max_insns = tb->cflags & CF_COUNT_MASK;
12327: if (max_insns == 0)
12328: max_insns = CF_COUNT_MASK;
12329: LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
12330: gen_icount_start();
12331: while (ctx.bstate == BS_NONE) {
1.1.1.9 root 12332: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12333: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1.1.7 root 12334: if (bp->pc == ctx.pc) {
1.1.1.6 root 12335: save_cpu_state(&ctx, 1);
1.1.1.2 root 12336: ctx.bstate = BS_BRANCH;
1.1.1.7 root 12337: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 12338: /* Include the breakpoint location or the tb won't
12339: * be flushed when it must be. */
12340: ctx.pc += 4;
1.1.1.2 root 12341: goto done_generating;
12342: }
12343: }
12344: }
12345:
1.1 root 12346: if (search_pc) {
12347: j = gen_opc_ptr - gen_opc_buf;
12348: if (lj < j) {
12349: lj++;
12350: while (lj < j)
12351: gen_opc_instr_start[lj++] = 0;
12352: }
1.1.1.2 root 12353: gen_opc_pc[lj] = ctx.pc;
12354: gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12355: gen_opc_instr_start[lj] = 1;
1.1.1.7 root 12356: gen_opc_icount[lj] = num_insns;
1.1 root 12357: }
1.1.1.7 root 12358: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12359: gen_io_start();
1.1.1.12 root 12360:
12361: is_branch = 0;
12362: if (!(ctx.hflags & MIPS_HFLAG_M16)) {
12363: ctx.opcode = ldl_code(ctx.pc);
12364: insn_bytes = 4;
12365: decode_opc(env, &ctx, &is_branch);
12366: } else if (env->insn_flags & ASE_MICROMIPS) {
12367: ctx.opcode = lduw_code(ctx.pc);
12368: insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
12369: } else if (env->insn_flags & ASE_MIPS16) {
12370: ctx.opcode = lduw_code(ctx.pc);
12371: insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
12372: } else {
12373: generate_exception(&ctx, EXCP_RI);
12374: ctx.bstate = BS_STOP;
12375: break;
12376: }
12377: if (!is_branch) {
12378: handle_delay_slot(env, &ctx, insn_bytes);
12379: }
12380: ctx.pc += insn_bytes;
12381:
1.1.1.7 root 12382: num_insns++;
1.1.1.2 root 12383:
1.1.1.9 root 12384: /* Execute a branch and its delay slot as a single instruction.
12385: This is what GDB expects and is consistent with what the
12386: hardware does (e.g. if a delay slot instruction faults, the
12387: reported PC is the PC of the branch). */
12388: if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
1.1.1.2 root 12389: break;
12390:
1.1 root 12391: if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12392: break;
1.1.1.2 root 12393:
1.1.1.7 root 12394: if (gen_opc_ptr >= gen_opc_end)
12395: break;
12396:
12397: if (num_insns >= max_insns)
12398: break;
1.1.1.8 root 12399:
12400: if (singlestep)
12401: break;
1.1 root 12402: }
1.1.1.7 root 12403: if (tb->cflags & CF_LAST_IO)
12404: gen_io_end();
1.1.1.9 root 12405: if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
1.1.1.6 root 12406: save_cpu_state(&ctx, ctx.bstate == BS_NONE);
1.1.1.7 root 12407: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 12408: } else {
1.1.1.7 root 12409: switch (ctx.bstate) {
1.1.1.6 root 12410: case BS_STOP:
12411: gen_goto_tb(&ctx, 0, ctx.pc);
12412: break;
12413: case BS_NONE:
12414: save_cpu_state(&ctx, 0);
12415: gen_goto_tb(&ctx, 0, ctx.pc);
12416: break;
12417: case BS_EXCP:
1.1.1.7 root 12418: tcg_gen_exit_tb(0);
1.1.1.6 root 12419: break;
12420: case BS_BRANCH:
12421: default:
12422: break;
1.1.1.7 root 12423: }
1.1 root 12424: }
1.1.1.2 root 12425: done_generating:
1.1.1.7 root 12426: gen_icount_end(tb, num_insns);
1.1 root 12427: *gen_opc_ptr = INDEX_op_end;
12428: if (search_pc) {
12429: j = gen_opc_ptr - gen_opc_buf;
12430: lj++;
12431: while (lj <= j)
12432: gen_opc_instr_start[lj++] = 0;
12433: } else {
12434: tb->size = ctx.pc - pc_start;
1.1.1.7 root 12435: tb->icount = num_insns;
1.1 root 12436: }
12437: #ifdef DEBUG_DISAS
1.1.1.7 root 12438: LOG_DISAS("\n");
12439: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
12440: qemu_log("IN: %s\n", lookup_symbol(pc_start));
12441: log_target_disas(pc_start, ctx.pc - pc_start, 0);
12442: qemu_log("\n");
1.1 root 12443: }
12444: #endif
12445: }
12446:
1.1.1.7 root 12447: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1.1 root 12448: {
1.1.1.7 root 12449: gen_intermediate_code_internal(env, tb, 0);
1.1 root 12450: }
12451:
1.1.1.7 root 12452: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1.1 root 12453: {
1.1.1.7 root 12454: gen_intermediate_code_internal(env, tb, 1);
1.1 root 12455: }
12456:
1.1.1.13! root 12457: static void fpu_dump_state(CPUState *env, FILE *f, fprintf_function fpu_fprintf,
1.1.1.7 root 12458: int flags)
1.1.1.4 root 12459: {
12460: int i;
1.1.1.6 root 12461: int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
1.1.1.4 root 12462:
1.1.1.12 root 12463: #define printfpr(fp) \
12464: do { \
12465: if (is_fpu64) \
12466: fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12467: " fd:%13g fs:%13g psu: %13g\n", \
12468: (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12469: (double)(fp)->fd, \
12470: (double)(fp)->fs[FP_ENDIAN_IDX], \
12471: (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12472: else { \
12473: fpr_t tmp; \
12474: tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12475: tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12476: fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12477: " fd:%13g fs:%13g psu:%13g\n", \
12478: tmp.w[FP_ENDIAN_IDX], tmp.d, \
12479: (double)tmp.fd, \
12480: (double)tmp.fs[FP_ENDIAN_IDX], \
12481: (double)tmp.fs[!FP_ENDIAN_IDX]); \
12482: } \
1.1.1.4 root 12483: } while(0)
12484:
1.1.1.6 root 12485:
1.1.1.13! root 12486: fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
! 12487: env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
1.1.1.7 root 12488: get_float_exception_flags(&env->active_fpu.fp_status));
1.1.1.6 root 12489: for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12490: fpu_fprintf(f, "%3s: ", fregnames[i]);
1.1.1.7 root 12491: printfpr(&env->active_fpu.fpr[i]);
1.1.1.4 root 12492: }
12493:
12494: #undef printfpr
12495: }
12496:
1.1.1.6 root 12497: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 12498: /* Debug help: The architecture requires 32bit code to maintain proper
1.1.1.7 root 12499: sign-extended values on 64bit machines. */
1.1.1.5 root 12500:
12501: #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12502:
1.1.1.7 root 12503: static void
12504: cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
1.1.1.13! root 12505: fprintf_function cpu_fprintf,
1.1.1.7 root 12506: int flags)
1.1.1.5 root 12507: {
12508: int i;
12509:
1.1.1.7 root 12510: if (!SIGN_EXT_P(env->active_tc.PC))
12511: cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12512: if (!SIGN_EXT_P(env->active_tc.HI[0]))
12513: cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12514: if (!SIGN_EXT_P(env->active_tc.LO[0]))
12515: cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
1.1.1.5 root 12516: if (!SIGN_EXT_P(env->btarget))
1.1.1.6 root 12517: cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
1.1.1.5 root 12518:
12519: for (i = 0; i < 32; i++) {
1.1.1.7 root 12520: if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12521: cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
1.1.1.5 root 12522: }
12523:
12524: if (!SIGN_EXT_P(env->CP0_EPC))
1.1.1.6 root 12525: cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
1.1.1.9 root 12526: if (!SIGN_EXT_P(env->lladdr))
12527: cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
1.1.1.5 root 12528: }
12529: #endif
12530:
1.1.1.13! root 12531: void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1.1 root 12532: int flags)
12533: {
12534: int i;
1.1.1.6 root 12535:
1.1.1.12 root 12536: cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
12537: " LO=0x" TARGET_FMT_lx " ds %04x "
12538: TARGET_FMT_lx " " TARGET_FMT_ld "\n",
1.1.1.7 root 12539: env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12540: env->hflags, env->btarget, env->bcond);
1.1 root 12541: for (i = 0; i < 32; i++) {
12542: if ((i & 3) == 0)
12543: cpu_fprintf(f, "GPR%02d:", i);
1.1.1.7 root 12544: cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
1.1 root 12545: if ((i & 3) == 3)
12546: cpu_fprintf(f, "\n");
12547: }
12548:
1.1.1.6 root 12549: cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
12550: env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
12551: cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
1.1.1.9 root 12552: env->CP0_Config0, env->CP0_Config1, env->lladdr);
1.1.1.6 root 12553: if (env->hflags & MIPS_HFLAG_FPU)
1.1.1.5 root 12554: fpu_dump_state(env, f, cpu_fprintf, flags);
1.1.1.6 root 12555: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 12556: cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
1.1.1.4 root 12557: #endif
1.1 root 12558: }
12559:
1.1.1.7 root 12560: static void mips_tcg_init(void)
12561: {
12562: int i;
12563: static int inited;
12564:
12565: /* Initialize various static tables. */
12566: if (inited)
12567: return;
12568:
12569: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1.1.1.8 root 12570: TCGV_UNUSED(cpu_gpr[0]);
12571: for (i = 1; i < 32; i++)
1.1.1.7 root 12572: cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
12573: offsetof(CPUState, active_tc.gpr[i]),
12574: regnames[i]);
12575: cpu_PC = tcg_global_mem_new(TCG_AREG0,
12576: offsetof(CPUState, active_tc.PC), "PC");
12577: for (i = 0; i < MIPS_DSP_ACC; i++) {
12578: cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
12579: offsetof(CPUState, active_tc.HI[i]),
12580: regnames_HI[i]);
12581: cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
12582: offsetof(CPUState, active_tc.LO[i]),
12583: regnames_LO[i]);
12584: cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
12585: offsetof(CPUState, active_tc.ACX[i]),
12586: regnames_ACX[i]);
12587: }
12588: cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
12589: offsetof(CPUState, active_tc.DSPControl),
12590: "DSPControl");
1.1.1.8 root 12591: bcond = tcg_global_mem_new(TCG_AREG0,
12592: offsetof(CPUState, bcond), "bcond");
1.1.1.7 root 12593: btarget = tcg_global_mem_new(TCG_AREG0,
12594: offsetof(CPUState, btarget), "btarget");
1.1.1.8 root 12595: hflags = tcg_global_mem_new_i32(TCG_AREG0,
12596: offsetof(CPUState, hflags), "hflags");
12597:
1.1.1.7 root 12598: fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
12599: offsetof(CPUState, active_fpu.fcr0),
12600: "fcr0");
12601: fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
12602: offsetof(CPUState, active_fpu.fcr31),
12603: "fcr31");
12604:
12605: /* register helpers */
12606: #define GEN_HELPER 2
12607: #include "helper.h"
12608:
12609: inited = 1;
12610: }
12611:
1.1.1.6 root 12612: #include "translate_init.c"
12613:
12614: CPUMIPSState *cpu_mips_init (const char *cpu_model)
1.1 root 12615: {
12616: CPUMIPSState *env;
1.1.1.6 root 12617: const mips_def_t *def;
1.1 root 12618:
1.1.1.6 root 12619: def = cpu_mips_find_by_name(cpu_model);
12620: if (!def)
12621: return NULL;
1.1 root 12622: env = qemu_mallocz(sizeof(CPUMIPSState));
1.1.1.6 root 12623: env->cpu_model = def;
1.1.1.9 root 12624: env->cpu_model_str = cpu_model;
1.1.1.6 root 12625:
1.1.1.2 root 12626: cpu_exec_init(env);
1.1.1.9 root 12627: #ifndef CONFIG_USER_ONLY
12628: mmu_init(env, def);
12629: #endif
12630: fpu_init(env, def);
12631: mvp_init(env, def);
1.1.1.7 root 12632: mips_tcg_init();
1.1.1.5 root 12633: cpu_reset(env);
1.1.1.8 root 12634: qemu_init_vcpu(env);
1.1.1.5 root 12635: return env;
12636: }
12637:
12638: void cpu_reset (CPUMIPSState *env)
12639: {
1.1.1.7 root 12640: if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12641: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12642: log_cpu_state(env, 0);
12643: }
12644:
1.1.1.5 root 12645: memset(env, 0, offsetof(CPUMIPSState, breakpoints));
1.1 root 12646: tlb_flush(env, 1);
1.1.1.5 root 12647:
1.1.1.9 root 12648: /* Reset registers to their default values */
12649: env->CP0_PRid = env->cpu_model->CP0_PRid;
12650: env->CP0_Config0 = env->cpu_model->CP0_Config0;
12651: #ifdef TARGET_WORDS_BIGENDIAN
12652: env->CP0_Config0 |= (1 << CP0C0_BE);
12653: #endif
12654: env->CP0_Config1 = env->cpu_model->CP0_Config1;
12655: env->CP0_Config2 = env->cpu_model->CP0_Config2;
12656: env->CP0_Config3 = env->cpu_model->CP0_Config3;
12657: env->CP0_Config6 = env->cpu_model->CP0_Config6;
12658: env->CP0_Config7 = env->cpu_model->CP0_Config7;
12659: env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12660: << env->cpu_model->CP0_LLAddr_shift;
12661: env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
12662: env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12663: env->CCRes = env->cpu_model->CCRes;
12664: env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12665: env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12666: env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12667: env->current_tc = 0;
12668: env->SEGBITS = env->cpu_model->SEGBITS;
12669: env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12670: #if defined(TARGET_MIPS64)
12671: if (env->cpu_model->insn_flags & ISA_MIPS3) {
12672: env->SEGMask |= 3ULL << 62;
12673: }
12674: #endif
12675: env->PABITS = env->cpu_model->PABITS;
12676: env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12677: env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12678: env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12679: env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12680: env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12681: env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12682: env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12683: env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12684: env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12685: env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12686: env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
12687: env->insn_flags = env->cpu_model->insn_flags;
12688:
1.1.1.7 root 12689: #if defined(CONFIG_USER_ONLY)
12690: env->hflags = MIPS_HFLAG_UM;
1.1.1.8 root 12691: /* Enable access to the SYNCI_Step register. */
12692: env->CP0_HWREna |= (1 << 1);
1.1.1.9 root 12693: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12694: env->hflags |= MIPS_HFLAG_FPU;
12695: }
12696: #ifdef TARGET_MIPS64
12697: if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
12698: env->hflags |= MIPS_HFLAG_F64;
12699: }
12700: #endif
1.1.1.7 root 12701: #else
1.1.1.5 root 12702: if (env->hflags & MIPS_HFLAG_BMASK) {
12703: /* If the exception was raised from a delay slot,
1.1.1.7 root 12704: come back to the jump. */
12705: env->CP0_ErrorEPC = env->active_tc.PC - 4;
1.1.1.5 root 12706: } else {
1.1.1.7 root 12707: env->CP0_ErrorEPC = env->active_tc.PC;
1.1.1.5 root 12708: }
1.1.1.7 root 12709: env->active_tc.PC = (int32_t)0xBFC00000;
1.1.1.9 root 12710: env->CP0_Random = env->tlb->nb_tlb - 1;
12711: env->tlb->tlb_in_use = env->tlb->nb_tlb;
1.1 root 12712: env->CP0_Wired = 0;
1.1.1.13! root 12713: env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
1.1.1.5 root 12714: env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
1.1.1.6 root 12715: /* vectored interrupts not implemented, timer on int 7,
12716: no performance counters. */
12717: env->CP0_IntCtl = 0xe0000000;
12718: {
12719: int i;
12720:
12721: for (i = 0; i < 7; i++) {
12722: env->CP0_WatchLo[i] = 0;
12723: env->CP0_WatchHi[i] = 0x80000000;
12724: }
12725: env->CP0_WatchLo[7] = 0;
12726: env->CP0_WatchHi[7] = 0;
12727: }
1.1 root 12728: /* Count register increments in debug mode, EJTAG version 1 */
12729: env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
1.1.1.6 root 12730: env->hflags = MIPS_HFLAG_CP0;
1.1.1.2 root 12731: #endif
1.1.1.9 root 12732: #if defined(TARGET_MIPS64)
12733: if (env->cpu_model->insn_flags & ISA_MIPS3) {
12734: env->hflags |= MIPS_HFLAG_64;
12735: }
12736: #endif
1.1.1.7 root 12737: env->exception_index = EXCP_NONE;
1.1 root 12738: }
1.1.1.7 root 12739:
12740: void gen_pc_load(CPUState *env, TranslationBlock *tb,
12741: unsigned long searched_pc, int pc_pos, void *puc)
12742: {
12743: env->active_tc.PC = gen_opc_pc[pc_pos];
12744: env->hflags &= ~MIPS_HFLAG_BMASK;
12745: env->hflags |= gen_opc_hflags[pc_pos];
12746: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.