|
|
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.8 root 1069: save_cpu_state(ctx, 0);
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.7 root 1089: save_cpu_state(ctx, 1);
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:
! 1098: save_cpu_state(ctx, 1);
! 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: }
1156: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1157: tcg_temp_free(t0);
1158: tcg_temp_free(t1);
1159: }
1160:
1.1.1.12! root 1161: /* Store */
! 1162: static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
! 1163: int base, int16_t offset)
! 1164: {
! 1165: const char *opn = "st";
! 1166: TCGv t0 = tcg_temp_new();
! 1167: TCGv t1 = tcg_temp_new();
! 1168:
! 1169: gen_base_offset_addr(ctx, t0, base, offset);
! 1170: gen_load_gpr(t1, rt);
! 1171: switch (opc) {
! 1172: #if defined(TARGET_MIPS64)
! 1173: case OPC_SD:
! 1174: save_cpu_state(ctx, 0);
! 1175: op_st_sd(t1, t0, ctx);
! 1176: opn = "sd";
! 1177: break;
! 1178: case OPC_SDL:
! 1179: save_cpu_state(ctx, 1);
! 1180: gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
! 1181: opn = "sdl";
! 1182: break;
! 1183: case OPC_SDR:
! 1184: save_cpu_state(ctx, 1);
! 1185: gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
! 1186: opn = "sdr";
! 1187: break;
! 1188: #endif
! 1189: case OPC_SW:
! 1190: save_cpu_state(ctx, 0);
! 1191: op_st_sw(t1, t0, ctx);
! 1192: opn = "sw";
! 1193: break;
! 1194: case OPC_SH:
! 1195: save_cpu_state(ctx, 0);
! 1196: op_st_sh(t1, t0, ctx);
! 1197: opn = "sh";
! 1198: break;
! 1199: case OPC_SB:
! 1200: save_cpu_state(ctx, 0);
! 1201: op_st_sb(t1, t0, ctx);
! 1202: opn = "sb";
! 1203: break;
! 1204: case OPC_SWL:
! 1205: save_cpu_state(ctx, 1);
! 1206: gen_helper_2i(swl, t1, t0, ctx->mem_idx);
! 1207: opn = "swl";
! 1208: break;
! 1209: case OPC_SWR:
! 1210: save_cpu_state(ctx, 1);
! 1211: gen_helper_2i(swr, t1, t0, ctx->mem_idx);
! 1212: opn = "swr";
! 1213: break;
! 1214: }
! 1215: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
! 1216: tcg_temp_free(t0);
! 1217: tcg_temp_free(t1);
! 1218: }
! 1219:
! 1220:
1.1.1.8 root 1221: /* Store conditional */
1222: static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1223: int base, int16_t offset)
1224: {
1225: const char *opn = "st_cond";
1226: TCGv t0, t1;
1227:
1228: t0 = tcg_temp_local_new();
1229:
1.1.1.12! root 1230: gen_base_offset_addr(ctx, t0, base, offset);
1.1.1.8 root 1231: /* Don't do NOP if destination is zero: we must perform the actual
1232: memory access. */
1233:
1234: t1 = tcg_temp_local_new();
1235: gen_load_gpr(t1, rt);
1236: switch (opc) {
1237: #if defined(TARGET_MIPS64)
1238: case OPC_SCD:
1239: save_cpu_state(ctx, 0);
1.1.1.12! root 1240: op_st_scd(t1, t0, rt, ctx);
1.1.1.8 root 1241: opn = "scd";
1242: break;
1243: #endif
1.1 root 1244: case OPC_SC:
1.1.1.9 root 1245: save_cpu_state(ctx, 1);
1.1.1.12! root 1246: op_st_sc(t1, t0, rt, ctx);
1.1 root 1247: opn = "sc";
1248: break;
1249: }
1250: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1.1.1.7 root 1251: tcg_temp_free(t1);
1.1.1.8 root 1252: tcg_temp_free(t0);
1.1 root 1253: }
1254:
1.1.1.4 root 1255: /* Load and store */
1.1.1.5 root 1256: static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1.1.1.7 root 1257: int base, int16_t offset)
1.1.1.4 root 1258: {
1.1.1.6 root 1259: const char *opn = "flt_ldst";
1.1.1.8 root 1260: TCGv t0 = tcg_temp_new();
1.1.1.4 root 1261:
1.1.1.12! root 1262: gen_base_offset_addr(ctx, t0, base, offset);
1.1.1.4 root 1263: /* Don't do NOP if destination is zero: we must perform the actual
1.1.1.6 root 1264: memory access. */
1.1.1.4 root 1265: switch (opc) {
1266: case OPC_LWC1:
1.1.1.7 root 1267: {
1268: TCGv_i32 fp0 = tcg_temp_new_i32();
1269:
1.1.1.8 root 1270: tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1271: tcg_gen_trunc_tl_i32(fp0, t0);
1.1.1.7 root 1272: gen_store_fpr32(fp0, ft);
1273: tcg_temp_free_i32(fp0);
1274: }
1.1.1.4 root 1275: opn = "lwc1";
1276: break;
1277: case OPC_SWC1:
1.1.1.7 root 1278: {
1279: TCGv_i32 fp0 = tcg_temp_new_i32();
1280: TCGv t1 = tcg_temp_new();
1281:
1282: gen_load_fpr32(fp0, ft);
1283: tcg_gen_extu_i32_tl(t1, fp0);
1284: tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1285: tcg_temp_free(t1);
1286: tcg_temp_free_i32(fp0);
1287: }
1.1.1.4 root 1288: opn = "swc1";
1289: break;
1290: case OPC_LDC1:
1.1.1.7 root 1291: {
1292: TCGv_i64 fp0 = tcg_temp_new_i64();
1293:
1294: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1295: gen_store_fpr64(ctx, fp0, ft);
1296: tcg_temp_free_i64(fp0);
1297: }
1.1.1.4 root 1298: opn = "ldc1";
1299: break;
1300: case OPC_SDC1:
1.1.1.7 root 1301: {
1302: TCGv_i64 fp0 = tcg_temp_new_i64();
1303:
1304: gen_load_fpr64(ctx, fp0, ft);
1305: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1306: tcg_temp_free_i64(fp0);
1307: }
1.1.1.4 root 1308: opn = "sdc1";
1309: break;
1310: default:
1.1.1.6 root 1311: MIPS_INVAL(opn);
1312: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 1313: goto out;
1.1.1.4 root 1314: }
1315: MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1.1.1.7 root 1316: out:
1317: tcg_temp_free(t0);
1.1.1.4 root 1318: }
1.1.1.5 root 1319:
1.1.1.12! root 1320: static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
! 1321: uint32_t op, int rt, int rs, int16_t imm)
! 1322: {
! 1323: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
! 1324: check_cp1_enabled(ctx);
! 1325: gen_flt_ldst(ctx, op, rt, rs, imm);
! 1326: } else {
! 1327: generate_exception_err(ctx, EXCP_CpU, 1);
! 1328: }
! 1329: }
! 1330:
1.1 root 1331: /* Arithmetic with immediate operand */
1.1.1.6 root 1332: static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1333: int rt, int rs, int16_t imm)
1.1 root 1334: {
1.1.1.8 root 1335: target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1.1.1.6 root 1336: const char *opn = "imm arith";
1.1 root 1337:
1.1.1.5 root 1338: if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1.1.1.6 root 1339: /* If no destination, treat it as a NOP.
1340: For addi, we must generate the overflow exception when needed. */
1.1 root 1341: MIPS_DEBUG("NOP");
1.1.1.8 root 1342: return;
1.1 root 1343: }
1344: switch (opc) {
1345: case OPC_ADDI:
1.1.1.7 root 1346: {
1.1.1.8 root 1347: TCGv t0 = tcg_temp_local_new();
1348: TCGv t1 = tcg_temp_new();
1349: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1350: int l1 = gen_new_label();
1351:
1.1.1.8 root 1352: gen_load_gpr(t1, rs);
1353: tcg_gen_addi_tl(t0, t1, uimm);
1354: tcg_gen_ext32s_tl(t0, t0);
1.1.1.7 root 1355:
1.1.1.8 root 1356: tcg_gen_xori_tl(t1, t1, ~uimm);
1357: tcg_gen_xori_tl(t2, t0, uimm);
1358: tcg_gen_and_tl(t1, t1, t2);
1359: tcg_temp_free(t2);
1360: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1361: tcg_temp_free(t1);
1.1.1.7 root 1362: /* operands of same sign, result different sign */
1363: generate_exception(ctx, EXCP_OVERFLOW);
1364: gen_set_label(l1);
1365: tcg_gen_ext32s_tl(t0, t0);
1.1.1.8 root 1366: gen_store_gpr(t0, rt);
1367: tcg_temp_free(t0);
1.1.1.7 root 1368: }
1.1 root 1369: opn = "addi";
1370: break;
1371: case OPC_ADDIU:
1.1.1.8 root 1372: if (rs != 0) {
1373: tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1374: tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1375: } else {
1376: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1377: }
1.1 root 1378: opn = "addiu";
1379: break;
1.1.1.6 root 1380: #if defined(TARGET_MIPS64)
1.1.1.5 root 1381: case OPC_DADDI:
1.1.1.7 root 1382: {
1.1.1.8 root 1383: TCGv t0 = tcg_temp_local_new();
1384: TCGv t1 = tcg_temp_new();
1385: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1386: int l1 = gen_new_label();
1387:
1.1.1.8 root 1388: gen_load_gpr(t1, rs);
1389: tcg_gen_addi_tl(t0, t1, uimm);
1.1.1.7 root 1390:
1.1.1.8 root 1391: tcg_gen_xori_tl(t1, t1, ~uimm);
1392: tcg_gen_xori_tl(t2, t0, uimm);
1393: tcg_gen_and_tl(t1, t1, t2);
1394: tcg_temp_free(t2);
1395: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1396: tcg_temp_free(t1);
1.1.1.7 root 1397: /* operands of same sign, result different sign */
1398: generate_exception(ctx, EXCP_OVERFLOW);
1399: gen_set_label(l1);
1.1.1.8 root 1400: gen_store_gpr(t0, rt);
1401: tcg_temp_free(t0);
1.1.1.7 root 1402: }
1.1.1.5 root 1403: opn = "daddi";
1404: break;
1405: case OPC_DADDIU:
1.1.1.8 root 1406: if (rs != 0) {
1407: tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1408: } else {
1409: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1410: }
1.1.1.5 root 1411: opn = "daddiu";
1412: break;
1413: #endif
1.1.1.8 root 1414: }
1415: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1416: }
1417:
1418: /* Logic with immediate operand */
1419: static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1420: {
1421: target_ulong uimm;
1422: const char *opn = "imm logic";
1423:
1424: if (rt == 0) {
1425: /* If no destination, treat it as a NOP. */
1426: MIPS_DEBUG("NOP");
1427: return;
1428: }
1429: uimm = (uint16_t)imm;
1430: switch (opc) {
1.1 root 1431: case OPC_ANDI:
1.1.1.8 root 1432: if (likely(rs != 0))
1433: tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1434: else
1435: tcg_gen_movi_tl(cpu_gpr[rt], 0);
1.1 root 1436: opn = "andi";
1437: break;
1438: case OPC_ORI:
1.1.1.8 root 1439: if (rs != 0)
1440: tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1441: else
1442: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1.1 root 1443: opn = "ori";
1444: break;
1445: case OPC_XORI:
1.1.1.8 root 1446: if (likely(rs != 0))
1447: tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1448: else
1449: tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1.1 root 1450: opn = "xori";
1451: break;
1452: case OPC_LUI:
1.1.1.8 root 1453: tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1.1 root 1454: opn = "lui";
1455: break;
1.1.1.8 root 1456: }
1457: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1458: }
1459:
1460: /* Set on less than with immediate operand */
1461: static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1462: {
1463: target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1464: const char *opn = "imm arith";
1465: TCGv t0;
1466:
1467: if (rt == 0) {
1468: /* If no destination, treat it as a NOP. */
1469: MIPS_DEBUG("NOP");
1470: return;
1471: }
1472: t0 = tcg_temp_new();
1473: gen_load_gpr(t0, rs);
1474: switch (opc) {
1475: case OPC_SLTI:
1.1.1.12! root 1476: tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1.1.1.8 root 1477: opn = "slti";
1478: break;
1479: case OPC_SLTIU:
1.1.1.12! root 1480: tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1.1.1.8 root 1481: opn = "sltiu";
1482: break;
1483: }
1484: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1485: tcg_temp_free(t0);
1486: }
1487:
1488: /* Shifts with immediate operand */
1489: static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1490: int rt, int rs, int16_t imm)
1491: {
1492: target_ulong uimm = ((uint16_t)imm) & 0x1f;
1493: const char *opn = "imm shift";
1494: TCGv t0;
1495:
1496: if (rt == 0) {
1497: /* If no destination, treat it as a NOP. */
1498: MIPS_DEBUG("NOP");
1499: return;
1500: }
1501:
1502: t0 = tcg_temp_new();
1503: gen_load_gpr(t0, rs);
1504: switch (opc) {
1.1 root 1505: case OPC_SLL:
1.1.1.7 root 1506: tcg_gen_shli_tl(t0, t0, uimm);
1.1.1.8 root 1507: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1.1 root 1508: opn = "sll";
1509: break;
1510: case OPC_SRA:
1.1.1.8 root 1511: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1.1 root 1512: opn = "sra";
1513: break;
1514: case OPC_SRL:
1.1.1.12! root 1515: if (uimm != 0) {
! 1516: tcg_gen_ext32u_tl(t0, t0);
! 1517: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
! 1518: } else {
! 1519: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
! 1520: }
! 1521: opn = "srl";
! 1522: break;
! 1523: case OPC_ROTR:
! 1524: if (uimm != 0) {
! 1525: TCGv_i32 t1 = tcg_temp_new_i32();
1.1.1.7 root 1526:
1.1.1.12! root 1527: tcg_gen_trunc_tl_i32(t1, t0);
! 1528: tcg_gen_rotri_i32(t1, t1, uimm);
! 1529: tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
! 1530: tcg_temp_free_i32(t1);
! 1531: } else {
! 1532: tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1.1.1.6 root 1533: }
1.1.1.12! root 1534: opn = "rotr";
1.1.1.5 root 1535: break;
1.1.1.6 root 1536: #if defined(TARGET_MIPS64)
1.1.1.5 root 1537: case OPC_DSLL:
1.1.1.8 root 1538: tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1.1.1.5 root 1539: opn = "dsll";
1540: break;
1541: case OPC_DSRA:
1.1.1.8 root 1542: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1.1.1.5 root 1543: opn = "dsra";
1544: break;
1545: case OPC_DSRL:
1.1.1.12! root 1546: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
! 1547: opn = "dsrl";
! 1548: break;
! 1549: case OPC_DROTR:
! 1550: if (uimm != 0) {
! 1551: tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
! 1552: } else {
! 1553: tcg_gen_mov_tl(cpu_gpr[rt], t0);
1.1.1.6 root 1554: }
1.1.1.12! root 1555: opn = "drotr";
1.1.1.5 root 1556: break;
1557: case OPC_DSLL32:
1.1.1.8 root 1558: tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1.1.1.5 root 1559: opn = "dsll32";
1560: break;
1561: case OPC_DSRA32:
1.1.1.8 root 1562: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1.1.1.5 root 1563: opn = "dsra32";
1564: break;
1565: case OPC_DSRL32:
1.1.1.12! root 1566: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
! 1567: opn = "dsrl32";
! 1568: break;
! 1569: case OPC_DROTR32:
! 1570: tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
! 1571: opn = "drotr32";
1.1 root 1572: break;
1.1.1.5 root 1573: #endif
1.1 root 1574: }
1.1.1.6 root 1575: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1.1.1.7 root 1576: tcg_temp_free(t0);
1.1 root 1577: }
1578:
1579: /* Arithmetic */
1.1.1.6 root 1580: static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1.1 root 1581: int rd, int rs, int rt)
1582: {
1.1.1.6 root 1583: const char *opn = "arith";
1.1 root 1584:
1.1.1.5 root 1585: if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1586: && opc != OPC_DADD && opc != OPC_DSUB) {
1.1.1.6 root 1587: /* If no destination, treat it as a NOP.
1588: For add & sub, we must generate the overflow exception when needed. */
1.1 root 1589: MIPS_DEBUG("NOP");
1.1.1.8 root 1590: return;
1.1.1.6 root 1591: }
1.1.1.8 root 1592:
1.1 root 1593: switch (opc) {
1594: case OPC_ADD:
1.1.1.7 root 1595: {
1.1.1.8 root 1596: TCGv t0 = tcg_temp_local_new();
1597: TCGv t1 = tcg_temp_new();
1598: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1599: int l1 = gen_new_label();
1600:
1.1.1.8 root 1601: gen_load_gpr(t1, rs);
1602: gen_load_gpr(t2, rt);
1603: tcg_gen_add_tl(t0, t1, t2);
1604: tcg_gen_ext32s_tl(t0, t0);
1605: tcg_gen_xor_tl(t1, t1, t2);
1606: tcg_gen_xor_tl(t2, t0, t2);
1.1.1.12! root 1607: tcg_gen_andc_tl(t1, t2, t1);
1.1.1.8 root 1608: tcg_temp_free(t2);
1609: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1610: tcg_temp_free(t1);
1.1.1.7 root 1611: /* operands of same sign, result different sign */
1612: generate_exception(ctx, EXCP_OVERFLOW);
1613: gen_set_label(l1);
1.1.1.8 root 1614: gen_store_gpr(t0, rd);
1615: tcg_temp_free(t0);
1.1.1.7 root 1616: }
1.1 root 1617: opn = "add";
1618: break;
1619: case OPC_ADDU:
1.1.1.8 root 1620: if (rs != 0 && rt != 0) {
1621: tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1622: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1623: } else if (rs == 0 && rt != 0) {
1624: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1625: } else if (rs != 0 && rt == 0) {
1626: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1627: } else {
1628: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1629: }
1.1 root 1630: opn = "addu";
1631: break;
1632: case OPC_SUB:
1.1.1.7 root 1633: {
1.1.1.8 root 1634: TCGv t0 = tcg_temp_local_new();
1635: TCGv t1 = tcg_temp_new();
1636: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1637: int l1 = gen_new_label();
1638:
1.1.1.8 root 1639: gen_load_gpr(t1, rs);
1640: gen_load_gpr(t2, rt);
1641: tcg_gen_sub_tl(t0, t1, t2);
1642: tcg_gen_ext32s_tl(t0, t0);
1643: tcg_gen_xor_tl(t2, t1, t2);
1644: tcg_gen_xor_tl(t1, t0, t1);
1645: tcg_gen_and_tl(t1, t1, t2);
1646: tcg_temp_free(t2);
1647: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1648: tcg_temp_free(t1);
1.1.1.9 root 1649: /* operands of different sign, first operand and result different sign */
1.1.1.7 root 1650: generate_exception(ctx, EXCP_OVERFLOW);
1651: gen_set_label(l1);
1.1.1.8 root 1652: gen_store_gpr(t0, rd);
1653: tcg_temp_free(t0);
1.1.1.7 root 1654: }
1.1 root 1655: opn = "sub";
1656: break;
1657: case OPC_SUBU:
1.1.1.8 root 1658: if (rs != 0 && rt != 0) {
1659: tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1660: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1661: } else if (rs == 0 && rt != 0) {
1662: tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1663: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1664: } else if (rs != 0 && rt == 0) {
1665: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1666: } else {
1667: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1668: }
1.1 root 1669: opn = "subu";
1670: break;
1.1.1.6 root 1671: #if defined(TARGET_MIPS64)
1.1.1.5 root 1672: case OPC_DADD:
1.1.1.7 root 1673: {
1.1.1.8 root 1674: TCGv t0 = tcg_temp_local_new();
1675: TCGv t1 = tcg_temp_new();
1676: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1677: int l1 = gen_new_label();
1678:
1.1.1.8 root 1679: gen_load_gpr(t1, rs);
1680: gen_load_gpr(t2, rt);
1681: tcg_gen_add_tl(t0, t1, t2);
1682: tcg_gen_xor_tl(t1, t1, t2);
1683: tcg_gen_xor_tl(t2, t0, t2);
1.1.1.12! root 1684: tcg_gen_andc_tl(t1, t2, t1);
1.1.1.8 root 1685: tcg_temp_free(t2);
1686: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1687: tcg_temp_free(t1);
1.1.1.7 root 1688: /* operands of same sign, result different sign */
1689: generate_exception(ctx, EXCP_OVERFLOW);
1690: gen_set_label(l1);
1.1.1.8 root 1691: gen_store_gpr(t0, rd);
1692: tcg_temp_free(t0);
1.1.1.7 root 1693: }
1.1.1.5 root 1694: opn = "dadd";
1695: break;
1696: case OPC_DADDU:
1.1.1.8 root 1697: if (rs != 0 && rt != 0) {
1698: tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1699: } else if (rs == 0 && rt != 0) {
1700: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1701: } else if (rs != 0 && rt == 0) {
1702: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1703: } else {
1704: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1705: }
1.1.1.5 root 1706: opn = "daddu";
1707: break;
1708: case OPC_DSUB:
1.1.1.7 root 1709: {
1.1.1.8 root 1710: TCGv t0 = tcg_temp_local_new();
1711: TCGv t1 = tcg_temp_new();
1712: TCGv t2 = tcg_temp_new();
1.1.1.7 root 1713: int l1 = gen_new_label();
1714:
1.1.1.8 root 1715: gen_load_gpr(t1, rs);
1716: gen_load_gpr(t2, rt);
1717: tcg_gen_sub_tl(t0, t1, t2);
1718: tcg_gen_xor_tl(t2, t1, t2);
1719: tcg_gen_xor_tl(t1, t0, t1);
1720: tcg_gen_and_tl(t1, t1, t2);
1721: tcg_temp_free(t2);
1722: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1723: tcg_temp_free(t1);
1.1.1.9 root 1724: /* operands of different sign, first operand and result different sign */
1.1.1.7 root 1725: generate_exception(ctx, EXCP_OVERFLOW);
1726: gen_set_label(l1);
1.1.1.8 root 1727: gen_store_gpr(t0, rd);
1728: tcg_temp_free(t0);
1.1.1.7 root 1729: }
1.1.1.5 root 1730: opn = "dsub";
1731: break;
1732: case OPC_DSUBU:
1.1.1.8 root 1733: if (rs != 0 && rt != 0) {
1734: tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1735: } else if (rs == 0 && rt != 0) {
1736: tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1737: } else if (rs != 0 && rt == 0) {
1738: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1739: } else {
1740: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1741: }
1.1.1.5 root 1742: opn = "dsubu";
1743: break;
1744: #endif
1.1.1.8 root 1745: case OPC_MUL:
1746: if (likely(rs != 0 && rt != 0)) {
1747: tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1748: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1749: } else {
1750: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1751: }
1752: opn = "mul";
1.1 root 1753: break;
1.1.1.8 root 1754: }
1755: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1756: }
1757:
1758: /* Conditional move */
1759: static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1760: {
1761: const char *opn = "cond move";
1762: int l1;
1763:
1764: if (rd == 0) {
1765: /* If no destination, treat it as a NOP.
1766: For add & sub, we must generate the overflow exception when needed. */
1767: MIPS_DEBUG("NOP");
1768: return;
1769: }
1770:
1771: l1 = gen_new_label();
1772: switch (opc) {
1773: case OPC_MOVN:
1774: if (likely(rt != 0))
1775: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1776: else
1777: tcg_gen_br(l1);
1778: opn = "movn";
1.1 root 1779: break;
1.1.1.8 root 1780: case OPC_MOVZ:
1781: if (likely(rt != 0))
1782: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1783: opn = "movz";
1784: break;
1785: }
1786: if (rs != 0)
1787: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1788: else
1789: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1790: gen_set_label(l1);
1791:
1792: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1793: }
1794:
1795: /* Logic */
1796: static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1797: {
1798: const char *opn = "logic";
1799:
1800: if (rd == 0) {
1801: /* If no destination, treat it as a NOP. */
1802: MIPS_DEBUG("NOP");
1803: return;
1804: }
1805:
1806: switch (opc) {
1.1 root 1807: case OPC_AND:
1.1.1.8 root 1808: if (likely(rs != 0 && rt != 0)) {
1809: tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1810: } else {
1811: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1812: }
1.1 root 1813: opn = "and";
1814: break;
1815: case OPC_NOR:
1.1.1.8 root 1816: if (rs != 0 && rt != 0) {
1817: tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1818: } else if (rs == 0 && rt != 0) {
1819: tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1820: } else if (rs != 0 && rt == 0) {
1821: tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1822: } else {
1823: tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1824: }
1.1 root 1825: opn = "nor";
1826: break;
1827: case OPC_OR:
1.1.1.8 root 1828: if (likely(rs != 0 && rt != 0)) {
1829: tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1830: } else if (rs == 0 && rt != 0) {
1831: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1832: } else if (rs != 0 && rt == 0) {
1833: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1834: } else {
1835: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1836: }
1.1 root 1837: opn = "or";
1838: break;
1839: case OPC_XOR:
1.1.1.8 root 1840: if (likely(rs != 0 && rt != 0)) {
1841: tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1842: } else if (rs == 0 && rt != 0) {
1843: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1844: } else if (rs != 0 && rt == 0) {
1845: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1846: } else {
1847: tcg_gen_movi_tl(cpu_gpr[rd], 0);
1848: }
1.1 root 1849: opn = "xor";
1850: break;
1.1.1.8 root 1851: }
1852: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1853: }
1854:
1855: /* Set on lower than */
1856: static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1857: {
1858: const char *opn = "slt";
1859: TCGv t0, t1;
1860:
1861: if (rd == 0) {
1862: /* If no destination, treat it as a NOP. */
1863: MIPS_DEBUG("NOP");
1864: return;
1865: }
1866:
1867: t0 = tcg_temp_new();
1868: t1 = tcg_temp_new();
1869: gen_load_gpr(t0, rs);
1870: gen_load_gpr(t1, rt);
1871: switch (opc) {
1872: case OPC_SLT:
1.1.1.12! root 1873: tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
1.1.1.8 root 1874: opn = "slt";
1.1 root 1875: break;
1.1.1.8 root 1876: case OPC_SLTU:
1.1.1.12! root 1877: tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
1.1.1.8 root 1878: opn = "sltu";
1879: break;
1880: }
1881: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1882: tcg_temp_free(t0);
1883: tcg_temp_free(t1);
1884: }
1.1.1.7 root 1885:
1.1.1.8 root 1886: /* Shifts */
1887: static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1888: int rd, int rs, int rt)
1889: {
1890: const char *opn = "shifts";
1891: TCGv t0, t1;
1.1.1.7 root 1892:
1.1.1.8 root 1893: if (rd == 0) {
1894: /* If no destination, treat it as a NOP.
1895: For add & sub, we must generate the overflow exception when needed. */
1896: MIPS_DEBUG("NOP");
1897: return;
1898: }
1899:
1900: t0 = tcg_temp_new();
1901: t1 = tcg_temp_new();
1902: gen_load_gpr(t0, rs);
1903: gen_load_gpr(t1, rt);
1904: switch (opc) {
1.1 root 1905: case OPC_SLLV:
1.1.1.7 root 1906: tcg_gen_andi_tl(t0, t0, 0x1f);
1907: tcg_gen_shl_tl(t0, t1, t0);
1.1.1.8 root 1908: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1.1 root 1909: opn = "sllv";
1910: break;
1911: case OPC_SRAV:
1.1.1.7 root 1912: tcg_gen_andi_tl(t0, t0, 0x1f);
1.1.1.8 root 1913: tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1.1 root 1914: opn = "srav";
1915: break;
1916: case OPC_SRLV:
1.1.1.12! root 1917: tcg_gen_ext32u_tl(t1, t1);
! 1918: tcg_gen_andi_tl(t0, t0, 0x1f);
! 1919: tcg_gen_shr_tl(t0, t1, t0);
! 1920: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
! 1921: opn = "srlv";
! 1922: break;
! 1923: case OPC_ROTRV:
! 1924: {
! 1925: TCGv_i32 t2 = tcg_temp_new_i32();
! 1926: TCGv_i32 t3 = tcg_temp_new_i32();
! 1927:
! 1928: tcg_gen_trunc_tl_i32(t2, t0);
! 1929: tcg_gen_trunc_tl_i32(t3, t1);
! 1930: tcg_gen_andi_i32(t2, t2, 0x1f);
! 1931: tcg_gen_rotr_i32(t2, t3, t2);
! 1932: tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
! 1933: tcg_temp_free_i32(t2);
! 1934: tcg_temp_free_i32(t3);
! 1935: opn = "rotrv";
1.1.1.6 root 1936: }
1.1.1.5 root 1937: break;
1.1.1.6 root 1938: #if defined(TARGET_MIPS64)
1.1.1.5 root 1939: case OPC_DSLLV:
1.1.1.7 root 1940: tcg_gen_andi_tl(t0, t0, 0x3f);
1.1.1.8 root 1941: tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1.1.1.5 root 1942: opn = "dsllv";
1943: break;
1944: case OPC_DSRAV:
1.1.1.7 root 1945: tcg_gen_andi_tl(t0, t0, 0x3f);
1.1.1.8 root 1946: tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1.1.1.5 root 1947: opn = "dsrav";
1948: break;
1949: case OPC_DSRLV:
1.1.1.12! root 1950: tcg_gen_andi_tl(t0, t0, 0x3f);
! 1951: tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
! 1952: opn = "dsrlv";
! 1953: break;
! 1954: case OPC_DROTRV:
! 1955: tcg_gen_andi_tl(t0, t0, 0x3f);
! 1956: tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
! 1957: opn = "drotrv";
1.1 root 1958: break;
1.1.1.5 root 1959: #endif
1.1 root 1960: }
1961: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1.1.1.7 root 1962: tcg_temp_free(t0);
1963: tcg_temp_free(t1);
1.1 root 1964: }
1965:
1966: /* Arithmetic on HI/LO registers */
1.1.1.5 root 1967: static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1.1 root 1968: {
1.1.1.6 root 1969: const char *opn = "hilo";
1.1 root 1970:
1971: if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1.1.1.6 root 1972: /* Treat as NOP. */
1.1 root 1973: MIPS_DEBUG("NOP");
1.1.1.8 root 1974: return;
1.1 root 1975: }
1976: switch (opc) {
1977: case OPC_MFHI:
1.1.1.8 root 1978: tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1.1 root 1979: opn = "mfhi";
1980: break;
1981: case OPC_MFLO:
1.1.1.8 root 1982: tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1.1 root 1983: opn = "mflo";
1984: break;
1985: case OPC_MTHI:
1.1.1.8 root 1986: if (reg != 0)
1987: tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1988: else
1989: tcg_gen_movi_tl(cpu_HI[0], 0);
1.1 root 1990: opn = "mthi";
1991: break;
1992: case OPC_MTLO:
1.1.1.8 root 1993: if (reg != 0)
1994: tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1995: else
1996: tcg_gen_movi_tl(cpu_LO[0], 0);
1.1 root 1997: opn = "mtlo";
1998: break;
1999: }
2000: MIPS_DEBUG("%s %s", opn, regnames[reg]);
2001: }
2002:
1.1.1.5 root 2003: static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1.1 root 2004: int rs, int rt)
2005: {
1.1.1.6 root 2006: const char *opn = "mul/div";
1.1.1.8 root 2007: TCGv t0, t1;
2008:
2009: switch (opc) {
2010: case OPC_DIV:
2011: case OPC_DIVU:
2012: #if defined(TARGET_MIPS64)
2013: case OPC_DDIV:
2014: case OPC_DDIVU:
2015: #endif
2016: t0 = tcg_temp_local_new();
2017: t1 = tcg_temp_local_new();
2018: break;
2019: default:
2020: t0 = tcg_temp_new();
2021: t1 = tcg_temp_new();
2022: break;
2023: }
1.1 root 2024:
1.1.1.7 root 2025: gen_load_gpr(t0, rs);
2026: gen_load_gpr(t1, rt);
1.1 root 2027: switch (opc) {
2028: case OPC_DIV:
1.1.1.7 root 2029: {
2030: int l1 = gen_new_label();
1.1.1.8 root 2031: int l2 = gen_new_label();
1.1.1.7 root 2032:
1.1.1.8 root 2033: tcg_gen_ext32s_tl(t0, t0);
2034: tcg_gen_ext32s_tl(t1, t1);
1.1.1.7 root 2035: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2036: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2037: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2038:
2039: tcg_gen_mov_tl(cpu_LO[0], t0);
2040: tcg_gen_movi_tl(cpu_HI[0], 0);
2041: tcg_gen_br(l1);
2042: gen_set_label(l2);
2043: tcg_gen_div_tl(cpu_LO[0], t0, t1);
2044: tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2045: tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2046: tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1.1.1.7 root 2047: gen_set_label(l1);
2048: }
1.1 root 2049: opn = "div";
2050: break;
2051: case OPC_DIVU:
1.1.1.7 root 2052: {
2053: int l1 = gen_new_label();
2054:
1.1.1.8 root 2055: tcg_gen_ext32u_tl(t0, t0);
2056: tcg_gen_ext32u_tl(t1, t1);
1.1.1.7 root 2057: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2058: tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2059: tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2060: tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2061: tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1.1.1.7 root 2062: gen_set_label(l1);
2063: }
1.1 root 2064: opn = "divu";
2065: break;
2066: case OPC_MULT:
1.1.1.7 root 2067: {
1.1.1.8 root 2068: TCGv_i64 t2 = tcg_temp_new_i64();
2069: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2070:
1.1.1.8 root 2071: tcg_gen_ext_tl_i64(t2, t0);
2072: tcg_gen_ext_tl_i64(t3, t1);
2073: tcg_gen_mul_i64(t2, t2, t3);
2074: tcg_temp_free_i64(t3);
2075: tcg_gen_trunc_i64_tl(t0, t2);
2076: tcg_gen_shri_i64(t2, t2, 32);
2077: tcg_gen_trunc_i64_tl(t1, t2);
2078: tcg_temp_free_i64(t2);
1.1.1.7 root 2079: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2080: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2081: }
1.1 root 2082: opn = "mult";
2083: break;
2084: case OPC_MULTU:
1.1.1.7 root 2085: {
1.1.1.8 root 2086: TCGv_i64 t2 = tcg_temp_new_i64();
2087: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2088:
2089: tcg_gen_ext32u_tl(t0, t0);
2090: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2091: tcg_gen_extu_tl_i64(t2, t0);
2092: tcg_gen_extu_tl_i64(t3, t1);
2093: tcg_gen_mul_i64(t2, t2, t3);
2094: tcg_temp_free_i64(t3);
2095: tcg_gen_trunc_i64_tl(t0, t2);
2096: tcg_gen_shri_i64(t2, t2, 32);
2097: tcg_gen_trunc_i64_tl(t1, t2);
2098: tcg_temp_free_i64(t2);
1.1.1.7 root 2099: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2100: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2101: }
1.1 root 2102: opn = "multu";
2103: break;
1.1.1.6 root 2104: #if defined(TARGET_MIPS64)
1.1.1.5 root 2105: case OPC_DDIV:
1.1.1.7 root 2106: {
2107: int l1 = gen_new_label();
1.1.1.8 root 2108: int l2 = gen_new_label();
1.1.1.7 root 2109:
2110: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1.1.1.8 root 2111: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2112: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2113: tcg_gen_mov_tl(cpu_LO[0], t0);
2114: tcg_gen_movi_tl(cpu_HI[0], 0);
2115: tcg_gen_br(l1);
2116: gen_set_label(l2);
2117: tcg_gen_div_i64(cpu_LO[0], t0, t1);
2118: tcg_gen_rem_i64(cpu_HI[0], t0, t1);
1.1.1.7 root 2119: gen_set_label(l1);
2120: }
1.1.1.5 root 2121: opn = "ddiv";
2122: break;
2123: case OPC_DDIVU:
1.1.1.7 root 2124: {
2125: int l1 = gen_new_label();
2126:
2127: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2128: tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2129: tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2130: gen_set_label(l1);
2131: }
1.1.1.5 root 2132: opn = "ddivu";
2133: break;
2134: case OPC_DMULT:
1.1.1.7 root 2135: gen_helper_dmult(t0, t1);
1.1.1.5 root 2136: opn = "dmult";
2137: break;
2138: case OPC_DMULTU:
1.1.1.7 root 2139: gen_helper_dmultu(t0, t1);
1.1.1.5 root 2140: opn = "dmultu";
2141: break;
2142: #endif
1.1 root 2143: case OPC_MADD:
1.1.1.7 root 2144: {
1.1.1.8 root 2145: TCGv_i64 t2 = tcg_temp_new_i64();
2146: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2147:
1.1.1.8 root 2148: tcg_gen_ext_tl_i64(t2, t0);
2149: tcg_gen_ext_tl_i64(t3, t1);
2150: tcg_gen_mul_i64(t2, t2, t3);
2151: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2152: tcg_gen_add_i64(t2, t2, t3);
2153: tcg_temp_free_i64(t3);
2154: tcg_gen_trunc_i64_tl(t0, t2);
2155: tcg_gen_shri_i64(t2, t2, 32);
2156: tcg_gen_trunc_i64_tl(t1, t2);
2157: tcg_temp_free_i64(t2);
1.1.1.7 root 2158: tcg_gen_ext32s_tl(cpu_LO[0], t0);
1.1.1.8 root 2159: tcg_gen_ext32s_tl(cpu_HI[0], t1);
1.1.1.7 root 2160: }
1.1 root 2161: opn = "madd";
2162: break;
2163: case OPC_MADDU:
1.1.1.7 root 2164: {
1.1.1.8 root 2165: TCGv_i64 t2 = tcg_temp_new_i64();
2166: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2167:
2168: tcg_gen_ext32u_tl(t0, t0);
2169: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2170: tcg_gen_extu_tl_i64(t2, t0);
2171: tcg_gen_extu_tl_i64(t3, t1);
2172: tcg_gen_mul_i64(t2, t2, t3);
2173: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2174: tcg_gen_add_i64(t2, t2, t3);
2175: tcg_temp_free_i64(t3);
2176: tcg_gen_trunc_i64_tl(t0, t2);
2177: tcg_gen_shri_i64(t2, t2, 32);
2178: tcg_gen_trunc_i64_tl(t1, t2);
2179: tcg_temp_free_i64(t2);
1.1.1.7 root 2180: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2181: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2182: }
1.1 root 2183: opn = "maddu";
2184: break;
2185: case OPC_MSUB:
1.1.1.7 root 2186: {
1.1.1.8 root 2187: TCGv_i64 t2 = tcg_temp_new_i64();
2188: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2189:
1.1.1.8 root 2190: tcg_gen_ext_tl_i64(t2, t0);
2191: tcg_gen_ext_tl_i64(t3, t1);
2192: tcg_gen_mul_i64(t2, t2, t3);
2193: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2194: tcg_gen_sub_i64(t2, t3, t2);
2195: tcg_temp_free_i64(t3);
2196: tcg_gen_trunc_i64_tl(t0, t2);
2197: tcg_gen_shri_i64(t2, t2, 32);
2198: tcg_gen_trunc_i64_tl(t1, t2);
2199: tcg_temp_free_i64(t2);
1.1.1.7 root 2200: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2201: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2202: }
1.1 root 2203: opn = "msub";
2204: break;
2205: case OPC_MSUBU:
1.1.1.7 root 2206: {
1.1.1.8 root 2207: TCGv_i64 t2 = tcg_temp_new_i64();
2208: TCGv_i64 t3 = tcg_temp_new_i64();
1.1.1.7 root 2209:
2210: tcg_gen_ext32u_tl(t0, t0);
2211: tcg_gen_ext32u_tl(t1, t1);
1.1.1.8 root 2212: tcg_gen_extu_tl_i64(t2, t0);
2213: tcg_gen_extu_tl_i64(t3, t1);
2214: tcg_gen_mul_i64(t2, t2, t3);
2215: tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2216: tcg_gen_sub_i64(t2, t3, t2);
2217: tcg_temp_free_i64(t3);
2218: tcg_gen_trunc_i64_tl(t0, t2);
2219: tcg_gen_shri_i64(t2, t2, 32);
2220: tcg_gen_trunc_i64_tl(t1, t2);
2221: tcg_temp_free_i64(t2);
1.1.1.7 root 2222: tcg_gen_ext32s_tl(cpu_LO[0], t0);
2223: tcg_gen_ext32s_tl(cpu_HI[0], t1);
2224: }
1.1 root 2225: opn = "msubu";
2226: break;
2227: default:
1.1.1.6 root 2228: MIPS_INVAL(opn);
1.1 root 2229: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2230: goto out;
1.1 root 2231: }
2232: MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1.1.1.7 root 2233: out:
2234: tcg_temp_free(t0);
2235: tcg_temp_free(t1);
1.1 root 2236: }
2237:
1.1.1.6 root 2238: static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2239: int rd, int rs, int rt)
2240: {
2241: const char *opn = "mul vr54xx";
1.1.1.8 root 2242: TCGv t0 = tcg_temp_new();
2243: TCGv t1 = tcg_temp_new();
1.1.1.6 root 2244:
1.1.1.7 root 2245: gen_load_gpr(t0, rs);
2246: gen_load_gpr(t1, rt);
1.1.1.6 root 2247:
2248: switch (opc) {
2249: case OPC_VR54XX_MULS:
1.1.1.7 root 2250: gen_helper_muls(t0, t0, t1);
1.1.1.6 root 2251: opn = "muls";
1.1.1.7 root 2252: break;
1.1.1.6 root 2253: case OPC_VR54XX_MULSU:
1.1.1.7 root 2254: gen_helper_mulsu(t0, t0, t1);
1.1.1.6 root 2255: opn = "mulsu";
1.1.1.7 root 2256: break;
1.1.1.6 root 2257: case OPC_VR54XX_MACC:
1.1.1.7 root 2258: gen_helper_macc(t0, t0, t1);
1.1.1.6 root 2259: opn = "macc";
1.1.1.7 root 2260: break;
1.1.1.6 root 2261: case OPC_VR54XX_MACCU:
1.1.1.7 root 2262: gen_helper_maccu(t0, t0, t1);
1.1.1.6 root 2263: opn = "maccu";
1.1.1.7 root 2264: break;
1.1.1.6 root 2265: case OPC_VR54XX_MSAC:
1.1.1.7 root 2266: gen_helper_msac(t0, t0, t1);
1.1.1.6 root 2267: opn = "msac";
1.1.1.7 root 2268: break;
1.1.1.6 root 2269: case OPC_VR54XX_MSACU:
1.1.1.7 root 2270: gen_helper_msacu(t0, t0, t1);
1.1.1.6 root 2271: opn = "msacu";
1.1.1.7 root 2272: break;
1.1.1.6 root 2273: case OPC_VR54XX_MULHI:
1.1.1.7 root 2274: gen_helper_mulhi(t0, t0, t1);
1.1.1.6 root 2275: opn = "mulhi";
1.1.1.7 root 2276: break;
1.1.1.6 root 2277: case OPC_VR54XX_MULHIU:
1.1.1.7 root 2278: gen_helper_mulhiu(t0, t0, t1);
1.1.1.6 root 2279: opn = "mulhiu";
1.1.1.7 root 2280: break;
1.1.1.6 root 2281: case OPC_VR54XX_MULSHI:
1.1.1.7 root 2282: gen_helper_mulshi(t0, t0, t1);
1.1.1.6 root 2283: opn = "mulshi";
1.1.1.7 root 2284: break;
1.1.1.6 root 2285: case OPC_VR54XX_MULSHIU:
1.1.1.7 root 2286: gen_helper_mulshiu(t0, t0, t1);
1.1.1.6 root 2287: opn = "mulshiu";
1.1.1.7 root 2288: break;
1.1.1.6 root 2289: case OPC_VR54XX_MACCHI:
1.1.1.7 root 2290: gen_helper_macchi(t0, t0, t1);
1.1.1.6 root 2291: opn = "macchi";
1.1.1.7 root 2292: break;
1.1.1.6 root 2293: case OPC_VR54XX_MACCHIU:
1.1.1.7 root 2294: gen_helper_macchiu(t0, t0, t1);
1.1.1.6 root 2295: opn = "macchiu";
1.1.1.7 root 2296: break;
1.1.1.6 root 2297: case OPC_VR54XX_MSACHI:
1.1.1.7 root 2298: gen_helper_msachi(t0, t0, t1);
1.1.1.6 root 2299: opn = "msachi";
1.1.1.7 root 2300: break;
1.1.1.6 root 2301: case OPC_VR54XX_MSACHIU:
1.1.1.7 root 2302: gen_helper_msachiu(t0, t0, t1);
1.1.1.6 root 2303: opn = "msachiu";
1.1.1.7 root 2304: break;
1.1.1.6 root 2305: default:
2306: MIPS_INVAL("mul vr54xx");
2307: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2308: goto out;
1.1.1.6 root 2309: }
1.1.1.7 root 2310: gen_store_gpr(t0, rd);
1.1.1.6 root 2311: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1.1.1.7 root 2312:
2313: out:
2314: tcg_temp_free(t0);
2315: tcg_temp_free(t1);
1.1.1.6 root 2316: }
2317:
1.1.1.5 root 2318: static void gen_cl (DisasContext *ctx, uint32_t opc,
1.1 root 2319: int rd, int rs)
2320: {
1.1.1.6 root 2321: const char *opn = "CLx";
1.1.1.8 root 2322: TCGv t0;
1.1.1.7 root 2323:
1.1 root 2324: if (rd == 0) {
1.1.1.6 root 2325: /* Treat as NOP. */
1.1 root 2326: MIPS_DEBUG("NOP");
1.1.1.8 root 2327: return;
1.1 root 2328: }
1.1.1.8 root 2329: t0 = tcg_temp_new();
1.1.1.7 root 2330: gen_load_gpr(t0, rs);
1.1 root 2331: switch (opc) {
2332: case OPC_CLO:
1.1.1.8 root 2333: gen_helper_clo(cpu_gpr[rd], t0);
1.1 root 2334: opn = "clo";
2335: break;
2336: case OPC_CLZ:
1.1.1.8 root 2337: gen_helper_clz(cpu_gpr[rd], t0);
1.1 root 2338: opn = "clz";
2339: break;
1.1.1.6 root 2340: #if defined(TARGET_MIPS64)
1.1.1.5 root 2341: case OPC_DCLO:
1.1.1.8 root 2342: gen_helper_dclo(cpu_gpr[rd], t0);
1.1.1.5 root 2343: opn = "dclo";
2344: break;
2345: case OPC_DCLZ:
1.1.1.8 root 2346: gen_helper_dclz(cpu_gpr[rd], t0);
1.1.1.5 root 2347: opn = "dclz";
2348: break;
2349: #endif
1.1 root 2350: }
2351: MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1.1.1.7 root 2352: tcg_temp_free(t0);
1.1 root 2353: }
2354:
1.1.1.12! root 2355: /* Godson integer instructions */
! 2356: static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
! 2357: int rd, int rs, int rt)
! 2358: {
! 2359: const char *opn = "loongson";
! 2360: TCGv t0, t1;
! 2361:
! 2362: if (rd == 0) {
! 2363: /* Treat as NOP. */
! 2364: MIPS_DEBUG("NOP");
! 2365: return;
! 2366: }
! 2367:
! 2368: switch (opc) {
! 2369: case OPC_MULT_G_2E:
! 2370: case OPC_MULT_G_2F:
! 2371: case OPC_MULTU_G_2E:
! 2372: case OPC_MULTU_G_2F:
! 2373: #if defined(TARGET_MIPS64)
! 2374: case OPC_DMULT_G_2E:
! 2375: case OPC_DMULT_G_2F:
! 2376: case OPC_DMULTU_G_2E:
! 2377: case OPC_DMULTU_G_2F:
! 2378: #endif
! 2379: t0 = tcg_temp_new();
! 2380: t1 = tcg_temp_new();
! 2381: break;
! 2382: default:
! 2383: t0 = tcg_temp_local_new();
! 2384: t1 = tcg_temp_local_new();
! 2385: break;
! 2386: }
! 2387:
! 2388: gen_load_gpr(t0, rs);
! 2389: gen_load_gpr(t1, rt);
! 2390:
! 2391: switch (opc) {
! 2392: case OPC_MULT_G_2E:
! 2393: case OPC_MULT_G_2F:
! 2394: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
! 2395: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
! 2396: opn = "mult.g";
! 2397: break;
! 2398: case OPC_MULTU_G_2E:
! 2399: case OPC_MULTU_G_2F:
! 2400: tcg_gen_ext32u_tl(t0, t0);
! 2401: tcg_gen_ext32u_tl(t1, t1);
! 2402: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
! 2403: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
! 2404: opn = "multu.g";
! 2405: break;
! 2406: case OPC_DIV_G_2E:
! 2407: case OPC_DIV_G_2F:
! 2408: {
! 2409: int l1 = gen_new_label();
! 2410: int l2 = gen_new_label();
! 2411: int l3 = gen_new_label();
! 2412: tcg_gen_ext32s_tl(t0, t0);
! 2413: tcg_gen_ext32s_tl(t1, t1);
! 2414: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
! 2415: tcg_gen_movi_tl(cpu_gpr[rd], 0);
! 2416: tcg_gen_br(l3);
! 2417: gen_set_label(l1);
! 2418: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
! 2419: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
! 2420: tcg_gen_mov_tl(cpu_gpr[rd], t0);
! 2421: tcg_gen_br(l3);
! 2422: gen_set_label(l2);
! 2423: tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
! 2424: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
! 2425: gen_set_label(l3);
! 2426: }
! 2427: opn = "div.g";
! 2428: break;
! 2429: case OPC_DIVU_G_2E:
! 2430: case OPC_DIVU_G_2F:
! 2431: {
! 2432: int l1 = gen_new_label();
! 2433: int l2 = gen_new_label();
! 2434: tcg_gen_ext32u_tl(t0, t0);
! 2435: tcg_gen_ext32u_tl(t1, t1);
! 2436: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
! 2437: tcg_gen_movi_tl(cpu_gpr[rd], 0);
! 2438: tcg_gen_br(l2);
! 2439: gen_set_label(l1);
! 2440: tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
! 2441: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
! 2442: gen_set_label(l2);
! 2443: }
! 2444: opn = "divu.g";
! 2445: break;
! 2446: case OPC_MOD_G_2E:
! 2447: case OPC_MOD_G_2F:
! 2448: {
! 2449: int l1 = gen_new_label();
! 2450: int l2 = gen_new_label();
! 2451: int l3 = gen_new_label();
! 2452: tcg_gen_ext32u_tl(t0, t0);
! 2453: tcg_gen_ext32u_tl(t1, t1);
! 2454: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
! 2455: tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
! 2456: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
! 2457: gen_set_label(l1);
! 2458: tcg_gen_movi_tl(cpu_gpr[rd], 0);
! 2459: tcg_gen_br(l3);
! 2460: gen_set_label(l2);
! 2461: tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
! 2462: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
! 2463: gen_set_label(l3);
! 2464: }
! 2465: opn = "mod.g";
! 2466: break;
! 2467: case OPC_MODU_G_2E:
! 2468: case OPC_MODU_G_2F:
! 2469: {
! 2470: int l1 = gen_new_label();
! 2471: int l2 = gen_new_label();
! 2472: tcg_gen_ext32u_tl(t0, t0);
! 2473: tcg_gen_ext32u_tl(t1, t1);
! 2474: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
! 2475: tcg_gen_movi_tl(cpu_gpr[rd], 0);
! 2476: tcg_gen_br(l2);
! 2477: gen_set_label(l1);
! 2478: tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
! 2479: tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
! 2480: gen_set_label(l2);
! 2481: }
! 2482: opn = "modu.g";
! 2483: break;
! 2484: #if defined(TARGET_MIPS64)
! 2485: case OPC_DMULT_G_2E:
! 2486: case OPC_DMULT_G_2F:
! 2487: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
! 2488: opn = "dmult.g";
! 2489: break;
! 2490: case OPC_DMULTU_G_2E:
! 2491: case OPC_DMULTU_G_2F:
! 2492: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
! 2493: opn = "dmultu.g";
! 2494: break;
! 2495: case OPC_DDIV_G_2E:
! 2496: case OPC_DDIV_G_2F:
! 2497: {
! 2498: int l1 = gen_new_label();
! 2499: int l2 = gen_new_label();
! 2500: int l3 = gen_new_label();
! 2501: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
! 2502: tcg_gen_movi_tl(cpu_gpr[rd], 0);
! 2503: tcg_gen_br(l3);
! 2504: gen_set_label(l1);
! 2505: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
! 2506: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
! 2507: tcg_gen_mov_tl(cpu_gpr[rd], t0);
! 2508: tcg_gen_br(l3);
! 2509: gen_set_label(l2);
! 2510: tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
! 2511: gen_set_label(l3);
! 2512: }
! 2513: opn = "ddiv.g";
! 2514: break;
! 2515: case OPC_DDIVU_G_2E:
! 2516: case OPC_DDIVU_G_2F:
! 2517: {
! 2518: int l1 = gen_new_label();
! 2519: int l2 = gen_new_label();
! 2520: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
! 2521: tcg_gen_movi_tl(cpu_gpr[rd], 0);
! 2522: tcg_gen_br(l2);
! 2523: gen_set_label(l1);
! 2524: tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
! 2525: gen_set_label(l2);
! 2526: }
! 2527: opn = "ddivu.g";
! 2528: break;
! 2529: case OPC_DMOD_G_2E:
! 2530: case OPC_DMOD_G_2F:
! 2531: {
! 2532: int l1 = gen_new_label();
! 2533: int l2 = gen_new_label();
! 2534: int l3 = gen_new_label();
! 2535: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
! 2536: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
! 2537: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
! 2538: gen_set_label(l1);
! 2539: tcg_gen_movi_tl(cpu_gpr[rd], 0);
! 2540: tcg_gen_br(l3);
! 2541: gen_set_label(l2);
! 2542: tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
! 2543: gen_set_label(l3);
! 2544: }
! 2545: opn = "dmod.g";
! 2546: break;
! 2547: case OPC_DMODU_G_2E:
! 2548: case OPC_DMODU_G_2F:
! 2549: {
! 2550: int l1 = gen_new_label();
! 2551: int l2 = gen_new_label();
! 2552: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
! 2553: tcg_gen_movi_tl(cpu_gpr[rd], 0);
! 2554: tcg_gen_br(l2);
! 2555: gen_set_label(l1);
! 2556: tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
! 2557: gen_set_label(l2);
! 2558: }
! 2559: opn = "dmodu.g";
! 2560: break;
! 2561: #endif
! 2562: }
! 2563:
! 2564: MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
! 2565: tcg_temp_free(t0);
! 2566: tcg_temp_free(t1);
! 2567: }
! 2568:
! 2569: /* Traps */
1.1.1.5 root 2570: static void gen_trap (DisasContext *ctx, uint32_t opc,
1.1 root 2571: int rs, int rt, int16_t imm)
2572: {
2573: int cond;
1.1.1.8 root 2574: TCGv t0 = tcg_temp_new();
2575: TCGv t1 = tcg_temp_new();
1.1 root 2576:
2577: cond = 0;
2578: /* Load needed operands */
2579: switch (opc) {
2580: case OPC_TEQ:
2581: case OPC_TGE:
2582: case OPC_TGEU:
2583: case OPC_TLT:
2584: case OPC_TLTU:
2585: case OPC_TNE:
2586: /* Compare two registers */
2587: if (rs != rt) {
1.1.1.7 root 2588: gen_load_gpr(t0, rs);
2589: gen_load_gpr(t1, rt);
1.1 root 2590: cond = 1;
2591: }
1.1.1.5 root 2592: break;
1.1 root 2593: case OPC_TEQI:
2594: case OPC_TGEI:
2595: case OPC_TGEIU:
2596: case OPC_TLTI:
2597: case OPC_TLTIU:
2598: case OPC_TNEI:
2599: /* Compare register to immediate */
2600: if (rs != 0 || imm != 0) {
1.1.1.7 root 2601: gen_load_gpr(t0, rs);
2602: tcg_gen_movi_tl(t1, (int32_t)imm);
1.1 root 2603: cond = 1;
2604: }
2605: break;
2606: }
2607: if (cond == 0) {
2608: switch (opc) {
2609: case OPC_TEQ: /* rs == rs */
2610: case OPC_TEQI: /* r0 == 0 */
2611: case OPC_TGE: /* rs >= rs */
2612: case OPC_TGEI: /* r0 >= 0 */
2613: case OPC_TGEU: /* rs >= rs unsigned */
2614: case OPC_TGEIU: /* r0 >= 0 unsigned */
2615: /* Always trap */
1.1.1.8 root 2616: generate_exception(ctx, EXCP_TRAP);
1.1 root 2617: break;
2618: case OPC_TLT: /* rs < rs */
2619: case OPC_TLTI: /* r0 < 0 */
2620: case OPC_TLTU: /* rs < rs unsigned */
2621: case OPC_TLTIU: /* r0 < 0 unsigned */
2622: case OPC_TNE: /* rs != rs */
2623: case OPC_TNEI: /* r0 != 0 */
1.1.1.6 root 2624: /* Never trap: treat as NOP. */
1.1.1.8 root 2625: break;
1.1 root 2626: }
2627: } else {
1.1.1.8 root 2628: int l1 = gen_new_label();
2629:
1.1 root 2630: switch (opc) {
2631: case OPC_TEQ:
2632: case OPC_TEQI:
1.1.1.8 root 2633: tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
1.1 root 2634: break;
2635: case OPC_TGE:
2636: case OPC_TGEI:
1.1.1.8 root 2637: tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
1.1 root 2638: break;
2639: case OPC_TGEU:
2640: case OPC_TGEIU:
1.1.1.8 root 2641: tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
1.1 root 2642: break;
2643: case OPC_TLT:
2644: case OPC_TLTI:
1.1.1.8 root 2645: tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
1.1 root 2646: break;
2647: case OPC_TLTU:
2648: case OPC_TLTIU:
1.1.1.8 root 2649: tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
1.1 root 2650: break;
2651: case OPC_TNE:
2652: case OPC_TNEI:
1.1.1.8 root 2653: tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
1.1 root 2654: break;
2655: }
1.1.1.8 root 2656: generate_exception(ctx, EXCP_TRAP);
1.1.1.7 root 2657: gen_set_label(l1);
2658: }
2659: tcg_temp_free(t0);
2660: tcg_temp_free(t1);
1.1 root 2661: }
2662:
1.1.1.7 root 2663: static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1.1.1.2 root 2664: {
2665: TranslationBlock *tb;
2666: tb = ctx->tb;
1.1.1.9 root 2667: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2668: likely(!ctx->singlestep_enabled)) {
1.1.1.7 root 2669: tcg_gen_goto_tb(n);
1.1.1.6 root 2670: gen_save_pc(dest);
1.1.1.7 root 2671: tcg_gen_exit_tb((long)tb + n);
1.1.1.2 root 2672: } else {
1.1.1.6 root 2673: gen_save_pc(dest);
1.1.1.9 root 2674: if (ctx->singlestep_enabled) {
2675: save_cpu_state(ctx, 0);
2676: gen_helper_0i(raise_exception, EXCP_DEBUG);
2677: }
1.1.1.7 root 2678: tcg_gen_exit_tb(0);
1.1.1.2 root 2679: }
2680: }
2681:
1.1 root 2682: /* Branches (before delay slot) */
1.1.1.5 root 2683: static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1.1.1.12! root 2684: int insn_bytes,
1.1 root 2685: int rs, int rt, int32_t offset)
2686: {
1.1.1.7 root 2687: target_ulong btgt = -1;
1.1.1.6 root 2688: int blink = 0;
1.1.1.7 root 2689: int bcond_compute = 0;
1.1.1.8 root 2690: TCGv t0 = tcg_temp_new();
2691: TCGv t1 = tcg_temp_new();
1.1 root 2692:
1.1.1.6 root 2693: if (ctx->hflags & MIPS_HFLAG_BMASK) {
2694: #ifdef MIPS_DEBUG_DISAS
1.1.1.7 root 2695: LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
1.1.1.6 root 2696: #endif
2697: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2698: goto out;
1.1.1.6 root 2699: }
2700:
2701: /* Load needed operands */
2702: switch (opc) {
2703: case OPC_BEQ:
2704: case OPC_BEQL:
2705: case OPC_BNE:
2706: case OPC_BNEL:
1.1 root 2707: /* Compare two registers */
2708: if (rs != rt) {
1.1.1.7 root 2709: gen_load_gpr(t0, rs);
2710: gen_load_gpr(t1, rt);
2711: bcond_compute = 1;
1.1 root 2712: }
1.1.1.12! root 2713: btgt = ctx->pc + insn_bytes + offset;
1.1 root 2714: break;
2715: case OPC_BGEZ:
2716: case OPC_BGEZAL:
1.1.1.12! root 2717: case OPC_BGEZALS:
1.1 root 2718: case OPC_BGEZALL:
2719: case OPC_BGEZL:
2720: case OPC_BGTZ:
2721: case OPC_BGTZL:
2722: case OPC_BLEZ:
2723: case OPC_BLEZL:
2724: case OPC_BLTZ:
2725: case OPC_BLTZAL:
1.1.1.12! root 2726: case OPC_BLTZALS:
1.1 root 2727: case OPC_BLTZALL:
2728: case OPC_BLTZL:
2729: /* Compare to zero */
2730: if (rs != 0) {
1.1.1.7 root 2731: gen_load_gpr(t0, rs);
2732: bcond_compute = 1;
1.1 root 2733: }
1.1.1.12! root 2734: btgt = ctx->pc + insn_bytes + offset;
1.1 root 2735: break;
2736: case OPC_J:
2737: case OPC_JAL:
1.1.1.12! root 2738: case OPC_JALX:
! 2739: case OPC_JALS:
! 2740: case OPC_JALXS:
1.1 root 2741: /* Jump to immediate */
1.1.1.12! root 2742: btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
1.1 root 2743: break;
2744: case OPC_JR:
2745: case OPC_JALR:
1.1.1.12! root 2746: case OPC_JALRC:
! 2747: case OPC_JALRS:
1.1 root 2748: /* Jump to register */
1.1.1.5 root 2749: if (offset != 0 && offset != 16) {
2750: /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1.1.1.6 root 2751: others are reserved. */
2752: MIPS_INVAL("jump hint");
1.1 root 2753: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2754: goto out;
1.1 root 2755: }
1.1.1.7 root 2756: gen_load_gpr(btarget, rs);
1.1 root 2757: break;
2758: default:
2759: MIPS_INVAL("branch/jump");
2760: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2761: goto out;
1.1 root 2762: }
1.1.1.7 root 2763: if (bcond_compute == 0) {
1.1 root 2764: /* No condition to be computed */
2765: switch (opc) {
2766: case OPC_BEQ: /* rx == rx */
2767: case OPC_BEQL: /* rx == rx likely */
2768: case OPC_BGEZ: /* 0 >= 0 */
2769: case OPC_BGEZL: /* 0 >= 0 likely */
2770: case OPC_BLEZ: /* 0 <= 0 */
2771: case OPC_BLEZL: /* 0 <= 0 likely */
2772: /* Always take */
1.1.1.2 root 2773: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 2774: MIPS_DEBUG("balways");
2775: break;
1.1.1.12! root 2776: case OPC_BGEZALS:
1.1 root 2777: case OPC_BGEZAL: /* 0 >= 0 */
2778: case OPC_BGEZALL: /* 0 >= 0 likely */
1.1.1.12! root 2779: ctx->hflags |= (opc == OPC_BGEZALS
! 2780: ? MIPS_HFLAG_BDS16
! 2781: : MIPS_HFLAG_BDS32);
1.1 root 2782: /* Always take and link */
2783: blink = 31;
1.1.1.2 root 2784: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 2785: MIPS_DEBUG("balways and link");
2786: break;
2787: case OPC_BNE: /* rx != rx */
2788: case OPC_BGTZ: /* 0 > 0 */
2789: case OPC_BLTZ: /* 0 < 0 */
1.1.1.6 root 2790: /* Treat as NOP. */
1.1 root 2791: MIPS_DEBUG("bnever (NOP)");
1.1.1.7 root 2792: goto out;
1.1.1.12! root 2793: case OPC_BLTZALS:
1.1.1.2 root 2794: case OPC_BLTZAL: /* 0 < 0 */
1.1.1.12! root 2795: ctx->hflags |= (opc == OPC_BLTZALS
! 2796: ? MIPS_HFLAG_BDS16
! 2797: : MIPS_HFLAG_BDS32);
! 2798: /* Handle as an unconditional branch to get correct delay
! 2799: slot checking. */
! 2800: blink = 31;
! 2801: btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
! 2802: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.6 root 2803: MIPS_DEBUG("bnever and link");
1.1.1.12! root 2804: break;
1.1.1.2 root 2805: case OPC_BLTZALL: /* 0 < 0 likely */
1.1.1.8 root 2806: tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
1.1.1.6 root 2807: /* Skip the instruction in the delay slot */
2808: MIPS_DEBUG("bnever, link and skip");
2809: ctx->pc += 4;
1.1.1.7 root 2810: goto out;
1.1 root 2811: case OPC_BNEL: /* rx != rx likely */
2812: case OPC_BGTZL: /* 0 > 0 likely */
2813: case OPC_BLTZL: /* 0 < 0 likely */
2814: /* Skip the instruction in the delay slot */
2815: MIPS_DEBUG("bnever and skip");
1.1.1.6 root 2816: ctx->pc += 4;
1.1.1.7 root 2817: goto out;
1.1 root 2818: case OPC_J:
1.1.1.2 root 2819: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.7 root 2820: MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
1.1 root 2821: break;
1.1.1.12! root 2822: case OPC_JALXS:
! 2823: case OPC_JALX:
! 2824: ctx->hflags |= MIPS_HFLAG_BX;
! 2825: /* Fallthrough */
! 2826: case OPC_JALS:
1.1 root 2827: case OPC_JAL:
2828: blink = 31;
1.1.1.2 root 2829: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.12! root 2830: ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
! 2831: ? MIPS_HFLAG_BDS16
! 2832: : MIPS_HFLAG_BDS32);
1.1.1.7 root 2833: MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
1.1 root 2834: break;
2835: case OPC_JR:
1.1.1.2 root 2836: ctx->hflags |= MIPS_HFLAG_BR;
1.1.1.12! root 2837: if (insn_bytes == 4)
! 2838: ctx->hflags |= MIPS_HFLAG_BDS32;
1.1 root 2839: MIPS_DEBUG("jr %s", regnames[rs]);
2840: break;
1.1.1.12! root 2841: case OPC_JALRS:
1.1 root 2842: case OPC_JALR:
1.1.1.12! root 2843: case OPC_JALRC:
1.1 root 2844: blink = rt;
1.1.1.2 root 2845: ctx->hflags |= MIPS_HFLAG_BR;
1.1.1.12! root 2846: ctx->hflags |= (opc == OPC_JALRS
! 2847: ? MIPS_HFLAG_BDS16
! 2848: : MIPS_HFLAG_BDS32);
1.1 root 2849: MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2850: break;
2851: default:
2852: MIPS_INVAL("branch/jump");
2853: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2854: goto out;
1.1 root 2855: }
2856: } else {
2857: switch (opc) {
2858: case OPC_BEQ:
1.1.1.12! root 2859: tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
1.1.1.6 root 2860: MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2861: regnames[rs], regnames[rt], btgt);
1.1 root 2862: goto not_likely;
2863: case OPC_BEQL:
1.1.1.12! root 2864: tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
1.1.1.6 root 2865: MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2866: regnames[rs], regnames[rt], btgt);
1.1 root 2867: goto likely;
2868: case OPC_BNE:
1.1.1.12! root 2869: tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
1.1.1.6 root 2870: MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2871: regnames[rs], regnames[rt], btgt);
1.1 root 2872: goto not_likely;
2873: case OPC_BNEL:
1.1.1.12! root 2874: tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
1.1.1.6 root 2875: MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
1.1.1.7 root 2876: regnames[rs], regnames[rt], btgt);
1.1 root 2877: goto likely;
2878: case OPC_BGEZ:
1.1.1.12! root 2879: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2880: MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2881: goto not_likely;
2882: case OPC_BGEZL:
1.1.1.12! root 2883: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2884: MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2885: goto likely;
1.1.1.12! root 2886: case OPC_BGEZALS:
1.1 root 2887: case OPC_BGEZAL:
1.1.1.12! root 2888: ctx->hflags |= (opc == OPC_BGEZALS
! 2889: ? MIPS_HFLAG_BDS16
! 2890: : MIPS_HFLAG_BDS32);
! 2891: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1.1.7 root 2892: MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2893: blink = 31;
2894: goto not_likely;
2895: case OPC_BGEZALL:
1.1.1.12! root 2896: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
1.1 root 2897: blink = 31;
1.1.1.7 root 2898: MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2899: goto likely;
2900: case OPC_BGTZ:
1.1.1.12! root 2901: tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
1.1.1.7 root 2902: MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2903: goto not_likely;
2904: case OPC_BGTZL:
1.1.1.12! root 2905: tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
1.1.1.7 root 2906: MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2907: goto likely;
2908: case OPC_BLEZ:
1.1.1.12! root 2909: tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
1.1.1.7 root 2910: MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2911: goto not_likely;
2912: case OPC_BLEZL:
1.1.1.12! root 2913: tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
1.1.1.7 root 2914: MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2915: goto likely;
2916: case OPC_BLTZ:
1.1.1.12! root 2917: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1.1.7 root 2918: MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2919: goto not_likely;
2920: case OPC_BLTZL:
1.1.1.12! root 2921: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1.1.7 root 2922: MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2923: goto likely;
1.1.1.12! root 2924: case OPC_BLTZALS:
1.1 root 2925: case OPC_BLTZAL:
1.1.1.12! root 2926: ctx->hflags |= (opc == OPC_BLTZALS
! 2927: ? MIPS_HFLAG_BDS16
! 2928: : MIPS_HFLAG_BDS32);
! 2929: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1 root 2930: blink = 31;
1.1.1.7 root 2931: MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2932: not_likely:
1.1.1.2 root 2933: ctx->hflags |= MIPS_HFLAG_BC;
1.1 root 2934: break;
2935: case OPC_BLTZALL:
1.1.1.12! root 2936: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
1.1 root 2937: blink = 31;
1.1.1.7 root 2938: MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2939: likely:
1.1.1.2 root 2940: ctx->hflags |= MIPS_HFLAG_BL;
1.1 root 2941: break;
1.1.1.6 root 2942: default:
2943: MIPS_INVAL("conditional branch/jump");
2944: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 2945: goto out;
1.1 root 2946: }
2947: }
1.1.1.6 root 2948: MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
1.1.1.7 root 2949: blink, ctx->hflags, btgt);
1.1.1.6 root 2950:
1.1.1.7 root 2951: ctx->btarget = btgt;
1.1 root 2952: if (blink > 0) {
1.1.1.12! root 2953: int post_delay = insn_bytes;
! 2954: int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
! 2955:
! 2956: if (opc != OPC_JALRC)
! 2957: post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
! 2958:
! 2959: tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
1.1 root 2960: }
1.1.1.7 root 2961:
2962: out:
1.1.1.12! root 2963: if (insn_bytes == 2)
! 2964: ctx->hflags |= MIPS_HFLAG_B16;
1.1.1.7 root 2965: tcg_temp_free(t0);
2966: tcg_temp_free(t1);
1.1 root 2967: }
2968:
1.1.1.5 root 2969: /* special3 bitfield operations */
2970: static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1.1.1.7 root 2971: int rs, int lsb, int msb)
1.1 root 2972: {
1.1.1.7 root 2973: TCGv t0 = tcg_temp_new();
2974: TCGv t1 = tcg_temp_new();
2975: target_ulong mask;
2976:
2977: gen_load_gpr(t1, rs);
1.1.1.5 root 2978: switch (opc) {
2979: case OPC_EXT:
2980: if (lsb + msb > 31)
2981: goto fail;
1.1.1.7 root 2982: tcg_gen_shri_tl(t0, t1, lsb);
2983: if (msb != 31) {
2984: tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2985: } else {
2986: tcg_gen_ext32s_tl(t0, t0);
2987: }
1.1.1.5 root 2988: break;
1.1.1.6 root 2989: #if defined(TARGET_MIPS64)
1.1.1.5 root 2990: case OPC_DEXTM:
1.1.1.7 root 2991: tcg_gen_shri_tl(t0, t1, lsb);
2992: if (msb != 31) {
2993: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2994: }
1.1.1.5 root 2995: break;
2996: case OPC_DEXTU:
1.1.1.7 root 2997: tcg_gen_shri_tl(t0, t1, lsb + 32);
2998: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
1.1.1.5 root 2999: break;
3000: case OPC_DEXT:
1.1.1.7 root 3001: tcg_gen_shri_tl(t0, t1, lsb);
3002: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
1.1.1.5 root 3003: break;
1.1.1.6 root 3004: #endif
1.1.1.5 root 3005: case OPC_INS:
3006: if (lsb > msb)
3007: goto fail;
1.1.1.7 root 3008: mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
3009: gen_load_gpr(t0, rt);
3010: tcg_gen_andi_tl(t0, t0, ~mask);
3011: tcg_gen_shli_tl(t1, t1, lsb);
3012: tcg_gen_andi_tl(t1, t1, mask);
3013: tcg_gen_or_tl(t0, t0, t1);
3014: tcg_gen_ext32s_tl(t0, t0);
1.1.1.5 root 3015: break;
1.1.1.6 root 3016: #if defined(TARGET_MIPS64)
1.1.1.5 root 3017: case OPC_DINSM:
3018: if (lsb > msb)
3019: goto fail;
1.1.1.7 root 3020: mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
3021: gen_load_gpr(t0, rt);
3022: tcg_gen_andi_tl(t0, t0, ~mask);
3023: tcg_gen_shli_tl(t1, t1, lsb);
3024: tcg_gen_andi_tl(t1, t1, mask);
3025: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3026: break;
3027: case OPC_DINSU:
3028: if (lsb > msb)
3029: goto fail;
1.1.1.11 root 3030: mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
1.1.1.7 root 3031: gen_load_gpr(t0, rt);
3032: tcg_gen_andi_tl(t0, t0, ~mask);
3033: tcg_gen_shli_tl(t1, t1, lsb + 32);
3034: tcg_gen_andi_tl(t1, t1, mask);
3035: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3036: break;
3037: case OPC_DINS:
3038: if (lsb > msb)
3039: goto fail;
1.1.1.7 root 3040: gen_load_gpr(t0, rt);
3041: mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3042: gen_load_gpr(t0, rt);
3043: tcg_gen_andi_tl(t0, t0, ~mask);
3044: tcg_gen_shli_tl(t1, t1, lsb);
3045: tcg_gen_andi_tl(t1, t1, mask);
3046: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 3047: break;
1.1.1.6 root 3048: #endif
1.1.1.5 root 3049: default:
3050: fail:
3051: MIPS_INVAL("bitops");
3052: generate_exception(ctx, EXCP_RI);
1.1.1.7 root 3053: tcg_temp_free(t0);
3054: tcg_temp_free(t1);
1.1 root 3055: return;
3056: }
1.1.1.7 root 3057: gen_store_gpr(t0, rt);
3058: tcg_temp_free(t0);
3059: tcg_temp_free(t1);
3060: }
3061:
3062: static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3063: {
1.1.1.8 root 3064: TCGv t0;
1.1.1.7 root 3065:
1.1.1.8 root 3066: if (rd == 0) {
3067: /* If no destination, treat it as a NOP. */
3068: MIPS_DEBUG("NOP");
3069: return;
3070: }
3071:
3072: t0 = tcg_temp_new();
3073: gen_load_gpr(t0, rt);
1.1.1.7 root 3074: switch (op2) {
3075: case OPC_WSBH:
1.1.1.8 root 3076: {
3077: TCGv t1 = tcg_temp_new();
3078:
3079: tcg_gen_shri_tl(t1, t0, 8);
3080: tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3081: tcg_gen_shli_tl(t0, t0, 8);
3082: tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3083: tcg_gen_or_tl(t0, t0, t1);
3084: tcg_temp_free(t1);
3085: tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3086: }
1.1.1.7 root 3087: break;
3088: case OPC_SEB:
1.1.1.8 root 3089: tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
1.1.1.7 root 3090: break;
3091: case OPC_SEH:
1.1.1.8 root 3092: tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
1.1.1.7 root 3093: break;
3094: #if defined(TARGET_MIPS64)
3095: case OPC_DSBH:
1.1.1.8 root 3096: {
3097: TCGv t1 = tcg_temp_new();
3098:
3099: tcg_gen_shri_tl(t1, t0, 8);
3100: tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3101: tcg_gen_shli_tl(t0, t0, 8);
3102: tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3103: tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3104: tcg_temp_free(t1);
3105: }
1.1.1.7 root 3106: break;
3107: case OPC_DSHD:
1.1.1.8 root 3108: {
3109: TCGv t1 = tcg_temp_new();
3110:
3111: tcg_gen_shri_tl(t1, t0, 16);
3112: tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3113: tcg_gen_shli_tl(t0, t0, 16);
3114: tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3115: tcg_gen_or_tl(t0, t0, t1);
3116: tcg_gen_shri_tl(t1, t0, 32);
3117: tcg_gen_shli_tl(t0, t0, 32);
3118: tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3119: tcg_temp_free(t1);
3120: }
1.1.1.7 root 3121: break;
3122: #endif
3123: default:
3124: MIPS_INVAL("bsfhl");
3125: generate_exception(ctx, EXCP_RI);
3126: tcg_temp_free(t0);
3127: return;
3128: }
3129: tcg_temp_free(t0);
1.1.1.5 root 3130: }
1.1.1.4 root 3131:
1.1.1.7 root 3132: #ifndef CONFIG_USER_ONLY
1.1.1.5 root 3133: /* CP0 (MMU and control) */
1.1.1.8 root 3134: static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
1.1.1.7 root 3135: {
1.1.1.8 root 3136: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 3137:
1.1.1.8 root 3138: tcg_gen_ld_i32(t0, cpu_env, off);
3139: tcg_gen_ext_i32_tl(arg, t0);
3140: tcg_temp_free_i32(t0);
1.1.1.7 root 3141: }
3142:
1.1.1.8 root 3143: static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
1.1.1.7 root 3144: {
1.1.1.8 root 3145: tcg_gen_ld_tl(arg, cpu_env, off);
3146: tcg_gen_ext32s_tl(arg, arg);
1.1.1.7 root 3147: }
3148:
1.1.1.8 root 3149: static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
1.1.1.7 root 3150: {
1.1.1.8 root 3151: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 3152:
1.1.1.8 root 3153: tcg_gen_trunc_tl_i32(t0, arg);
3154: tcg_gen_st_i32(t0, cpu_env, off);
3155: tcg_temp_free_i32(t0);
1.1.1.7 root 3156: }
3157:
1.1.1.8 root 3158: static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
1.1.1.7 root 3159: {
1.1.1.8 root 3160: tcg_gen_ext32s_tl(arg, arg);
3161: tcg_gen_st_tl(arg, cpu_env, off);
1.1.1.7 root 3162: }
3163:
1.1.1.8 root 3164: static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 3165: {
3166: const char *rn = "invalid";
3167:
1.1.1.6 root 3168: if (sel != 0)
3169: check_insn(env, ctx, ISA_MIPS32);
3170:
1.1.1.5 root 3171: switch (reg) {
3172: case 0:
3173: switch (sel) {
3174: case 0:
1.1.1.8 root 3175: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
1.1.1.5 root 3176: rn = "Index";
3177: break;
3178: case 1:
1.1.1.6 root 3179: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3180: gen_helper_mfc0_mvpcontrol(arg);
1.1.1.5 root 3181: rn = "MVPControl";
1.1.1.6 root 3182: break;
1.1.1.5 root 3183: case 2:
1.1.1.6 root 3184: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3185: gen_helper_mfc0_mvpconf0(arg);
1.1.1.5 root 3186: rn = "MVPConf0";
1.1.1.6 root 3187: break;
1.1.1.5 root 3188: case 3:
1.1.1.6 root 3189: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3190: gen_helper_mfc0_mvpconf1(arg);
1.1.1.5 root 3191: rn = "MVPConf1";
1.1.1.6 root 3192: break;
1.1.1.5 root 3193: default:
3194: goto die;
1.1 root 3195: }
3196: break;
1.1.1.5 root 3197: case 1:
3198: switch (sel) {
3199: case 0:
1.1.1.8 root 3200: gen_helper_mfc0_random(arg);
1.1.1.5 root 3201: rn = "Random";
1.1.1.6 root 3202: break;
1.1.1.5 root 3203: case 1:
1.1.1.6 root 3204: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3205: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
1.1.1.5 root 3206: rn = "VPEControl";
1.1.1.6 root 3207: break;
1.1.1.5 root 3208: case 2:
1.1.1.6 root 3209: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3210: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
1.1.1.5 root 3211: rn = "VPEConf0";
1.1.1.6 root 3212: break;
1.1.1.5 root 3213: case 3:
1.1.1.6 root 3214: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3215: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
1.1.1.5 root 3216: rn = "VPEConf1";
1.1.1.6 root 3217: break;
1.1.1.5 root 3218: case 4:
1.1.1.6 root 3219: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3220: gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
1.1.1.5 root 3221: rn = "YQMask";
1.1.1.6 root 3222: break;
1.1.1.5 root 3223: case 5:
1.1.1.6 root 3224: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3225: gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 3226: rn = "VPESchedule";
1.1.1.6 root 3227: break;
1.1.1.5 root 3228: case 6:
1.1.1.6 root 3229: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3230: gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 3231: rn = "VPEScheFBack";
1.1.1.6 root 3232: break;
1.1.1.5 root 3233: case 7:
1.1.1.6 root 3234: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3235: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
1.1.1.5 root 3236: rn = "VPEOpt";
1.1.1.6 root 3237: break;
1.1.1.5 root 3238: default:
3239: goto die;
3240: }
1.1 root 3241: break;
1.1.1.5 root 3242: case 2:
3243: switch (sel) {
3244: case 0:
1.1.1.8 root 3245: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
3246: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3247: rn = "EntryLo0";
3248: break;
3249: case 1:
3250: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3251: gen_helper_mfc0_tcstatus(arg);
1.1.1.6 root 3252: rn = "TCStatus";
3253: break;
3254: case 2:
3255: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3256: gen_helper_mfc0_tcbind(arg);
1.1.1.6 root 3257: rn = "TCBind";
3258: break;
1.1.1.5 root 3259: case 3:
1.1.1.6 root 3260: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3261: gen_helper_mfc0_tcrestart(arg);
1.1.1.6 root 3262: rn = "TCRestart";
3263: break;
1.1.1.5 root 3264: case 4:
1.1.1.6 root 3265: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3266: gen_helper_mfc0_tchalt(arg);
1.1.1.6 root 3267: rn = "TCHalt";
3268: break;
1.1.1.5 root 3269: case 5:
1.1.1.6 root 3270: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3271: gen_helper_mfc0_tccontext(arg);
1.1.1.6 root 3272: rn = "TCContext";
3273: break;
1.1.1.5 root 3274: case 6:
1.1.1.6 root 3275: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3276: gen_helper_mfc0_tcschedule(arg);
1.1.1.6 root 3277: rn = "TCSchedule";
3278: break;
1.1.1.5 root 3279: case 7:
1.1.1.6 root 3280: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3281: gen_helper_mfc0_tcschefback(arg);
1.1.1.6 root 3282: rn = "TCScheFBack";
3283: break;
1.1.1.5 root 3284: default:
3285: goto die;
3286: }
1.1 root 3287: break;
1.1.1.5 root 3288: case 3:
3289: switch (sel) {
3290: case 0:
1.1.1.8 root 3291: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
3292: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3293: rn = "EntryLo1";
3294: break;
1.1.1.5 root 3295: default:
3296: goto die;
1.1.1.6 root 3297: }
1.1 root 3298: break;
1.1.1.5 root 3299: case 4:
3300: switch (sel) {
3301: case 0:
1.1.1.8 root 3302: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3303: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3304: rn = "Context";
3305: break;
3306: case 1:
1.1.1.8 root 3307: // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 3308: rn = "ContextConfig";
3309: // break;
1.1.1.5 root 3310: default:
3311: goto die;
1.1.1.6 root 3312: }
1.1 root 3313: break;
1.1.1.5 root 3314: case 5:
3315: switch (sel) {
3316: case 0:
1.1.1.8 root 3317: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
1.1.1.6 root 3318: rn = "PageMask";
3319: break;
3320: case 1:
3321: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3322: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
1.1.1.6 root 3323: rn = "PageGrain";
3324: break;
1.1.1.5 root 3325: default:
3326: goto die;
1.1.1.6 root 3327: }
1.1 root 3328: break;
1.1.1.5 root 3329: case 6:
3330: switch (sel) {
3331: case 0:
1.1.1.8 root 3332: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
1.1.1.6 root 3333: rn = "Wired";
3334: break;
3335: case 1:
3336: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3337: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
1.1.1.6 root 3338: rn = "SRSConf0";
3339: break;
3340: case 2:
3341: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3342: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
1.1.1.6 root 3343: rn = "SRSConf1";
3344: break;
1.1.1.5 root 3345: case 3:
1.1.1.6 root 3346: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3347: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
1.1.1.6 root 3348: rn = "SRSConf2";
3349: break;
1.1.1.5 root 3350: case 4:
1.1.1.6 root 3351: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3352: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
1.1.1.6 root 3353: rn = "SRSConf3";
3354: break;
1.1.1.5 root 3355: case 5:
1.1.1.6 root 3356: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3357: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
1.1.1.6 root 3358: rn = "SRSConf4";
3359: break;
1.1.1.5 root 3360: default:
3361: goto die;
1.1.1.6 root 3362: }
1.1 root 3363: break;
1.1.1.5 root 3364: case 7:
3365: switch (sel) {
3366: case 0:
1.1.1.6 root 3367: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3368: gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
1.1.1.6 root 3369: rn = "HWREna";
3370: break;
1.1.1.5 root 3371: default:
3372: goto die;
1.1.1.6 root 3373: }
1.1 root 3374: break;
1.1.1.5 root 3375: case 8:
3376: switch (sel) {
3377: case 0:
1.1.1.8 root 3378: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3379: tcg_gen_ext32s_tl(arg, arg);
1.1.1.7 root 3380: rn = "BadVAddr";
1.1.1.6 root 3381: break;
1.1.1.5 root 3382: default:
3383: goto die;
3384: }
1.1.1.2 root 3385: break;
1.1.1.5 root 3386: case 9:
3387: switch (sel) {
3388: case 0:
1.1.1.7 root 3389: /* Mark as an IO operation because we read the time. */
3390: if (use_icount)
3391: gen_io_start();
1.1.1.8 root 3392: gen_helper_mfc0_count(arg);
1.1.1.7 root 3393: if (use_icount) {
3394: gen_io_end();
3395: ctx->bstate = BS_STOP;
3396: }
1.1.1.6 root 3397: rn = "Count";
3398: break;
3399: /* 6,7 are implementation dependent */
1.1.1.5 root 3400: default:
3401: goto die;
1.1.1.6 root 3402: }
1.1.1.5 root 3403: break;
3404: case 10:
3405: switch (sel) {
3406: case 0:
1.1.1.8 root 3407: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3408: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3409: rn = "EntryHi";
3410: break;
1.1.1.5 root 3411: default:
3412: goto die;
1.1.1.6 root 3413: }
1.1.1.5 root 3414: break;
3415: case 11:
3416: switch (sel) {
3417: case 0:
1.1.1.8 root 3418: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
1.1.1.6 root 3419: rn = "Compare";
3420: break;
3421: /* 6,7 are implementation dependent */
1.1.1.5 root 3422: default:
3423: goto die;
1.1.1.6 root 3424: }
1.1.1.5 root 3425: break;
3426: case 12:
3427: switch (sel) {
3428: case 0:
1.1.1.8 root 3429: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
1.1.1.6 root 3430: rn = "Status";
3431: break;
3432: case 1:
3433: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3434: gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
1.1.1.6 root 3435: rn = "IntCtl";
3436: break;
3437: case 2:
3438: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3439: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
1.1.1.6 root 3440: rn = "SRSCtl";
3441: break;
1.1.1.5 root 3442: case 3:
1.1.1.6 root 3443: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3444: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 3445: rn = "SRSMap";
3446: break;
1.1.1.5 root 3447: default:
3448: goto die;
3449: }
3450: break;
3451: case 13:
3452: switch (sel) {
3453: case 0:
1.1.1.8 root 3454: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
1.1.1.6 root 3455: rn = "Cause";
3456: break;
1.1.1.5 root 3457: default:
3458: goto die;
3459: }
3460: break;
3461: case 14:
3462: switch (sel) {
3463: case 0:
1.1.1.8 root 3464: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3465: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3466: rn = "EPC";
3467: break;
1.1.1.5 root 3468: default:
3469: goto die;
1.1.1.6 root 3470: }
1.1.1.5 root 3471: break;
3472: case 15:
3473: switch (sel) {
3474: case 0:
1.1.1.8 root 3475: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
1.1.1.6 root 3476: rn = "PRid";
3477: break;
3478: case 1:
3479: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3480: gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
1.1.1.6 root 3481: rn = "EBase";
3482: break;
1.1.1.5 root 3483: default:
3484: goto die;
3485: }
3486: break;
3487: case 16:
3488: switch (sel) {
3489: case 0:
1.1.1.8 root 3490: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
1.1.1.5 root 3491: rn = "Config";
3492: break;
3493: case 1:
1.1.1.8 root 3494: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
1.1.1.5 root 3495: rn = "Config1";
3496: break;
3497: case 2:
1.1.1.8 root 3498: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
1.1.1.5 root 3499: rn = "Config2";
3500: break;
3501: case 3:
1.1.1.8 root 3502: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
1.1.1.5 root 3503: rn = "Config3";
3504: break;
1.1.1.6 root 3505: /* 4,5 are reserved */
3506: /* 6,7 are implementation dependent */
3507: case 6:
1.1.1.8 root 3508: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
1.1.1.6 root 3509: rn = "Config6";
3510: break;
3511: case 7:
1.1.1.8 root 3512: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
1.1.1.6 root 3513: rn = "Config7";
3514: break;
1.1.1.5 root 3515: default:
3516: goto die;
1.1 root 3517: }
1.1.1.4 root 3518: break;
1.1.1.5 root 3519: case 17:
3520: switch (sel) {
3521: case 0:
1.1.1.8 root 3522: gen_helper_mfc0_lladdr(arg);
1.1.1.6 root 3523: rn = "LLAddr";
3524: break;
1.1.1.5 root 3525: default:
3526: goto die;
3527: }
1.1.1.4 root 3528: break;
1.1.1.5 root 3529: case 18:
3530: switch (sel) {
1.1.1.6 root 3531: case 0 ... 7:
1.1.1.8 root 3532: gen_helper_1i(mfc0_watchlo, arg, sel);
1.1.1.6 root 3533: rn = "WatchLo";
3534: break;
1.1.1.5 root 3535: default:
3536: goto die;
3537: }
1.1.1.4 root 3538: break;
1.1.1.5 root 3539: case 19:
3540: switch (sel) {
1.1.1.6 root 3541: case 0 ...7:
1.1.1.8 root 3542: gen_helper_1i(mfc0_watchhi, arg, sel);
1.1.1.6 root 3543: rn = "WatchHi";
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 20:
3550: switch (sel) {
3551: case 0:
1.1.1.6 root 3552: #if defined(TARGET_MIPS64)
3553: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 3554: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3555: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3556: rn = "XContext";
3557: break;
3558: #endif
1.1.1.5 root 3559: default:
3560: goto die;
1.1.1.4 root 3561: }
3562: break;
1.1.1.5 root 3563: case 21:
3564: /* Officially reserved, but sel 0 is used for R1x000 framemask */
3565: switch (sel) {
3566: case 0:
1.1.1.8 root 3567: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
1.1.1.6 root 3568: rn = "Framemask";
3569: break;
1.1.1.5 root 3570: default:
3571: goto die;
1.1.1.4 root 3572: }
3573: break;
1.1.1.5 root 3574: case 22:
1.1.1.8 root 3575: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 3576: rn = "'Diagnostic"; /* implementation dependent */
3577: break;
1.1.1.5 root 3578: case 23:
3579: switch (sel) {
3580: case 0:
1.1.1.8 root 3581: gen_helper_mfc0_debug(arg); /* EJTAG support */
1.1.1.6 root 3582: rn = "Debug";
3583: break;
3584: case 1:
1.1.1.8 root 3585: // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 3586: rn = "TraceControl";
3587: // break;
3588: case 2:
1.1.1.8 root 3589: // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 3590: rn = "TraceControl2";
3591: // break;
1.1.1.5 root 3592: case 3:
1.1.1.8 root 3593: // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 3594: rn = "UserTraceData";
3595: // break;
1.1.1.5 root 3596: case 4:
1.1.1.8 root 3597: // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 3598: rn = "TraceBPC";
3599: // break;
1.1.1.5 root 3600: default:
3601: goto die;
1.1.1.4 root 3602: }
1.1.1.5 root 3603: break;
3604: case 24:
3605: switch (sel) {
3606: case 0:
1.1.1.7 root 3607: /* EJTAG support */
1.1.1.8 root 3608: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3609: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3610: rn = "DEPC";
3611: break;
1.1.1.5 root 3612: default:
3613: goto die;
3614: }
3615: break;
3616: case 25:
3617: switch (sel) {
3618: case 0:
1.1.1.8 root 3619: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
1.1.1.6 root 3620: rn = "Performance0";
1.1.1.5 root 3621: break;
3622: case 1:
1.1.1.8 root 3623: // gen_helper_mfc0_performance1(arg);
1.1.1.6 root 3624: rn = "Performance1";
3625: // break;
1.1.1.5 root 3626: case 2:
1.1.1.8 root 3627: // gen_helper_mfc0_performance2(arg);
1.1.1.6 root 3628: rn = "Performance2";
3629: // break;
1.1.1.5 root 3630: case 3:
1.1.1.8 root 3631: // gen_helper_mfc0_performance3(arg);
1.1.1.6 root 3632: rn = "Performance3";
3633: // break;
1.1.1.5 root 3634: case 4:
1.1.1.8 root 3635: // gen_helper_mfc0_performance4(arg);
1.1.1.6 root 3636: rn = "Performance4";
3637: // break;
1.1.1.5 root 3638: case 5:
1.1.1.8 root 3639: // gen_helper_mfc0_performance5(arg);
1.1.1.6 root 3640: rn = "Performance5";
3641: // break;
1.1.1.5 root 3642: case 6:
1.1.1.8 root 3643: // gen_helper_mfc0_performance6(arg);
1.1.1.6 root 3644: rn = "Performance6";
3645: // break;
1.1.1.5 root 3646: case 7:
1.1.1.8 root 3647: // gen_helper_mfc0_performance7(arg);
1.1.1.6 root 3648: rn = "Performance7";
3649: // break;
1.1.1.5 root 3650: default:
3651: goto die;
3652: }
3653: break;
3654: case 26:
1.1.1.8 root 3655: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.7 root 3656: rn = "ECC";
3657: break;
1.1.1.5 root 3658: case 27:
3659: switch (sel) {
3660: case 0 ... 3:
1.1.1.8 root 3661: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 3662: rn = "CacheErr";
3663: break;
1.1.1.5 root 3664: default:
3665: goto die;
3666: }
3667: break;
3668: case 28:
3669: switch (sel) {
3670: case 0:
3671: case 2:
3672: case 4:
3673: case 6:
1.1.1.8 root 3674: gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
1.1.1.5 root 3675: rn = "TagLo";
3676: break;
3677: case 1:
3678: case 3:
3679: case 5:
3680: case 7:
1.1.1.8 root 3681: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
1.1.1.5 root 3682: rn = "DataLo";
3683: break;
3684: default:
3685: goto die;
3686: }
3687: break;
3688: case 29:
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_TagHi));
1.1.1.5 root 3695: rn = "TagHi";
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_DataHi));
1.1.1.5 root 3702: rn = "DataHi";
3703: break;
3704: default:
3705: goto die;
3706: }
3707: break;
3708: case 30:
3709: switch (sel) {
3710: case 0:
1.1.1.8 root 3711: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3712: tcg_gen_ext32s_tl(arg, arg);
1.1.1.6 root 3713: rn = "ErrorEPC";
3714: break;
1.1.1.5 root 3715: default:
3716: goto die;
3717: }
3718: break;
3719: case 31:
3720: switch (sel) {
3721: case 0:
1.1.1.7 root 3722: /* EJTAG support */
1.1.1.8 root 3723: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 3724: rn = "DESAVE";
3725: break;
1.1.1.5 root 3726: default:
3727: goto die;
3728: }
3729: break;
3730: default:
3731: goto die;
3732: }
1.1.1.7 root 3733: LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 3734: return;
3735:
3736: die:
1.1.1.7 root 3737: LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 3738: generate_exception(ctx, EXCP_RI);
3739: }
3740:
1.1.1.8 root 3741: static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 3742: {
3743: const char *rn = "invalid";
3744:
1.1.1.6 root 3745: if (sel != 0)
3746: check_insn(env, ctx, ISA_MIPS32);
3747:
1.1.1.7 root 3748: if (use_icount)
3749: gen_io_start();
3750:
1.1.1.5 root 3751: switch (reg) {
3752: case 0:
3753: switch (sel) {
3754: case 0:
1.1.1.8 root 3755: gen_helper_mtc0_index(arg);
1.1.1.5 root 3756: rn = "Index";
3757: break;
3758: case 1:
1.1.1.6 root 3759: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3760: gen_helper_mtc0_mvpcontrol(arg);
1.1.1.5 root 3761: rn = "MVPControl";
1.1.1.6 root 3762: break;
1.1.1.5 root 3763: case 2:
1.1.1.6 root 3764: check_insn(env, ctx, ASE_MT);
3765: /* ignored */
1.1.1.5 root 3766: rn = "MVPConf0";
1.1.1.6 root 3767: break;
1.1.1.5 root 3768: case 3:
1.1.1.6 root 3769: check_insn(env, ctx, ASE_MT);
3770: /* ignored */
1.1.1.5 root 3771: rn = "MVPConf1";
1.1.1.6 root 3772: break;
1.1.1.5 root 3773: default:
3774: goto die;
3775: }
3776: break;
3777: case 1:
3778: switch (sel) {
3779: case 0:
1.1.1.6 root 3780: /* ignored */
1.1.1.5 root 3781: rn = "Random";
1.1.1.6 root 3782: break;
1.1.1.5 root 3783: case 1:
1.1.1.6 root 3784: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3785: gen_helper_mtc0_vpecontrol(arg);
1.1.1.5 root 3786: rn = "VPEControl";
1.1.1.6 root 3787: break;
1.1.1.5 root 3788: case 2:
1.1.1.6 root 3789: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3790: gen_helper_mtc0_vpeconf0(arg);
1.1.1.5 root 3791: rn = "VPEConf0";
1.1.1.6 root 3792: break;
1.1.1.5 root 3793: case 3:
1.1.1.6 root 3794: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3795: gen_helper_mtc0_vpeconf1(arg);
1.1.1.5 root 3796: rn = "VPEConf1";
1.1.1.6 root 3797: break;
1.1.1.5 root 3798: case 4:
1.1.1.6 root 3799: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3800: gen_helper_mtc0_yqmask(arg);
1.1.1.5 root 3801: rn = "YQMask";
1.1.1.6 root 3802: break;
1.1.1.5 root 3803: case 5:
1.1.1.6 root 3804: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3805: gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 3806: rn = "VPESchedule";
1.1.1.6 root 3807: break;
1.1.1.5 root 3808: case 6:
1.1.1.6 root 3809: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3810: gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 3811: rn = "VPEScheFBack";
1.1.1.6 root 3812: break;
1.1.1.5 root 3813: case 7:
1.1.1.6 root 3814: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3815: gen_helper_mtc0_vpeopt(arg);
1.1.1.5 root 3816: rn = "VPEOpt";
1.1.1.6 root 3817: break;
1.1.1.5 root 3818: default:
3819: goto die;
3820: }
3821: break;
3822: case 2:
3823: switch (sel) {
3824: case 0:
1.1.1.8 root 3825: gen_helper_mtc0_entrylo0(arg);
1.1.1.6 root 3826: rn = "EntryLo0";
3827: break;
3828: case 1:
3829: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3830: gen_helper_mtc0_tcstatus(arg);
1.1.1.6 root 3831: rn = "TCStatus";
3832: break;
3833: case 2:
3834: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3835: gen_helper_mtc0_tcbind(arg);
1.1.1.6 root 3836: rn = "TCBind";
3837: break;
1.1.1.5 root 3838: case 3:
1.1.1.6 root 3839: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3840: gen_helper_mtc0_tcrestart(arg);
1.1.1.6 root 3841: rn = "TCRestart";
3842: break;
1.1.1.5 root 3843: case 4:
1.1.1.6 root 3844: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3845: gen_helper_mtc0_tchalt(arg);
1.1.1.6 root 3846: rn = "TCHalt";
3847: break;
1.1.1.5 root 3848: case 5:
1.1.1.6 root 3849: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3850: gen_helper_mtc0_tccontext(arg);
1.1.1.6 root 3851: rn = "TCContext";
3852: break;
1.1.1.5 root 3853: case 6:
1.1.1.6 root 3854: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3855: gen_helper_mtc0_tcschedule(arg);
1.1.1.6 root 3856: rn = "TCSchedule";
3857: break;
1.1.1.5 root 3858: case 7:
1.1.1.6 root 3859: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 3860: gen_helper_mtc0_tcschefback(arg);
1.1.1.6 root 3861: rn = "TCScheFBack";
3862: break;
1.1.1.5 root 3863: default:
3864: goto die;
3865: }
3866: break;
3867: case 3:
3868: switch (sel) {
3869: case 0:
1.1.1.8 root 3870: gen_helper_mtc0_entrylo1(arg);
1.1.1.6 root 3871: rn = "EntryLo1";
3872: break;
1.1.1.5 root 3873: default:
3874: goto die;
1.1.1.6 root 3875: }
1.1.1.5 root 3876: break;
3877: case 4:
3878: switch (sel) {
3879: case 0:
1.1.1.8 root 3880: gen_helper_mtc0_context(arg);
1.1.1.6 root 3881: rn = "Context";
3882: break;
3883: case 1:
1.1.1.8 root 3884: // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 3885: rn = "ContextConfig";
3886: // break;
1.1.1.5 root 3887: default:
3888: goto die;
1.1.1.6 root 3889: }
1.1.1.5 root 3890: break;
3891: case 5:
3892: switch (sel) {
3893: case 0:
1.1.1.8 root 3894: gen_helper_mtc0_pagemask(arg);
1.1.1.6 root 3895: rn = "PageMask";
3896: break;
3897: case 1:
3898: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3899: gen_helper_mtc0_pagegrain(arg);
1.1.1.6 root 3900: rn = "PageGrain";
3901: break;
1.1.1.5 root 3902: default:
3903: goto die;
1.1.1.6 root 3904: }
1.1.1.5 root 3905: break;
3906: case 6:
3907: switch (sel) {
3908: case 0:
1.1.1.8 root 3909: gen_helper_mtc0_wired(arg);
1.1.1.6 root 3910: rn = "Wired";
3911: break;
3912: case 1:
3913: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3914: gen_helper_mtc0_srsconf0(arg);
1.1.1.6 root 3915: rn = "SRSConf0";
3916: break;
3917: case 2:
3918: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3919: gen_helper_mtc0_srsconf1(arg);
1.1.1.6 root 3920: rn = "SRSConf1";
3921: break;
1.1.1.5 root 3922: case 3:
1.1.1.6 root 3923: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3924: gen_helper_mtc0_srsconf2(arg);
1.1.1.6 root 3925: rn = "SRSConf2";
3926: break;
1.1.1.5 root 3927: case 4:
1.1.1.6 root 3928: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3929: gen_helper_mtc0_srsconf3(arg);
1.1.1.6 root 3930: rn = "SRSConf3";
3931: break;
1.1.1.5 root 3932: case 5:
1.1.1.6 root 3933: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3934: gen_helper_mtc0_srsconf4(arg);
1.1.1.6 root 3935: rn = "SRSConf4";
3936: break;
1.1.1.5 root 3937: default:
3938: goto die;
1.1.1.6 root 3939: }
1.1.1.5 root 3940: break;
3941: case 7:
3942: switch (sel) {
3943: case 0:
1.1.1.6 root 3944: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 3945: gen_helper_mtc0_hwrena(arg);
1.1.1.6 root 3946: rn = "HWREna";
3947: break;
1.1.1.5 root 3948: default:
3949: goto die;
1.1.1.6 root 3950: }
1.1.1.5 root 3951: break;
3952: case 8:
3953: /* ignored */
1.1.1.7 root 3954: rn = "BadVAddr";
1.1.1.5 root 3955: break;
3956: case 9:
3957: switch (sel) {
3958: case 0:
1.1.1.8 root 3959: gen_helper_mtc0_count(arg);
1.1.1.6 root 3960: rn = "Count";
3961: break;
3962: /* 6,7 are implementation dependent */
1.1.1.5 root 3963: default:
3964: goto die;
1.1.1.6 root 3965: }
1.1.1.5 root 3966: break;
3967: case 10:
3968: switch (sel) {
3969: case 0:
1.1.1.8 root 3970: gen_helper_mtc0_entryhi(arg);
1.1.1.6 root 3971: rn = "EntryHi";
3972: break;
1.1.1.5 root 3973: default:
3974: goto die;
1.1.1.6 root 3975: }
1.1.1.5 root 3976: break;
3977: case 11:
3978: switch (sel) {
3979: case 0:
1.1.1.8 root 3980: gen_helper_mtc0_compare(arg);
1.1.1.6 root 3981: rn = "Compare";
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 12:
3989: switch (sel) {
3990: case 0:
1.1.1.8 root 3991: save_cpu_state(ctx, 1);
3992: gen_helper_mtc0_status(arg);
1.1.1.6 root 3993: /* BS_STOP isn't good enough here, hflags may have changed. */
3994: gen_save_pc(ctx->pc + 4);
3995: ctx->bstate = BS_EXCP;
3996: rn = "Status";
3997: break;
3998: case 1:
3999: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4000: gen_helper_mtc0_intctl(arg);
1.1.1.6 root 4001: /* Stop translation as we may have switched the execution mode */
4002: ctx->bstate = BS_STOP;
4003: rn = "IntCtl";
4004: break;
4005: case 2:
4006: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4007: gen_helper_mtc0_srsctl(arg);
1.1.1.6 root 4008: /* Stop translation as we may have switched the execution mode */
4009: ctx->bstate = BS_STOP;
4010: rn = "SRSCtl";
4011: break;
1.1.1.5 root 4012: case 3:
1.1.1.6 root 4013: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4014: gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 4015: /* Stop translation as we may have switched the execution mode */
4016: ctx->bstate = BS_STOP;
4017: rn = "SRSMap";
4018: break;
1.1.1.5 root 4019: default:
4020: goto die;
1.1.1.6 root 4021: }
1.1.1.5 root 4022: break;
4023: case 13:
4024: switch (sel) {
4025: case 0:
1.1.1.8 root 4026: save_cpu_state(ctx, 1);
4027: gen_helper_mtc0_cause(arg);
1.1.1.6 root 4028: rn = "Cause";
4029: break;
1.1.1.5 root 4030: default:
4031: goto die;
1.1.1.6 root 4032: }
1.1.1.5 root 4033: break;
4034: case 14:
4035: switch (sel) {
4036: case 0:
1.1.1.8 root 4037: gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 4038: rn = "EPC";
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 15:
4045: switch (sel) {
4046: case 0:
1.1.1.6 root 4047: /* ignored */
4048: rn = "PRid";
4049: break;
4050: case 1:
4051: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4052: gen_helper_mtc0_ebase(arg);
1.1.1.6 root 4053: rn = "EBase";
4054: break;
1.1.1.5 root 4055: default:
4056: goto die;
1.1.1.6 root 4057: }
1.1.1.5 root 4058: break;
4059: case 16:
4060: switch (sel) {
4061: case 0:
1.1.1.8 root 4062: gen_helper_mtc0_config0(arg);
1.1.1.5 root 4063: rn = "Config";
1.1.1.6 root 4064: /* Stop translation as we may have switched the execution mode */
4065: ctx->bstate = BS_STOP;
1.1.1.5 root 4066: break;
4067: case 1:
1.1.1.6 root 4068: /* ignored, read only */
1.1.1.5 root 4069: rn = "Config1";
4070: break;
4071: case 2:
1.1.1.8 root 4072: gen_helper_mtc0_config2(arg);
1.1.1.5 root 4073: rn = "Config2";
1.1.1.6 root 4074: /* Stop translation as we may have switched the execution mode */
4075: ctx->bstate = BS_STOP;
1.1.1.5 root 4076: break;
4077: case 3:
1.1.1.6 root 4078: /* ignored, read only */
1.1.1.5 root 4079: rn = "Config3";
4080: break;
1.1.1.6 root 4081: /* 4,5 are reserved */
4082: /* 6,7 are implementation dependent */
4083: case 6:
4084: /* ignored */
4085: rn = "Config6";
4086: break;
4087: case 7:
4088: /* ignored */
4089: rn = "Config7";
4090: break;
1.1.1.5 root 4091: default:
4092: rn = "Invalid config selector";
4093: goto die;
4094: }
4095: break;
4096: case 17:
4097: switch (sel) {
4098: case 0:
1.1.1.9 root 4099: gen_helper_mtc0_lladdr(arg);
1.1.1.6 root 4100: rn = "LLAddr";
4101: break;
1.1.1.5 root 4102: default:
4103: goto die;
4104: }
4105: break;
4106: case 18:
4107: switch (sel) {
1.1.1.6 root 4108: case 0 ... 7:
1.1.1.8 root 4109: gen_helper_1i(mtc0_watchlo, arg, sel);
1.1.1.6 root 4110: rn = "WatchLo";
4111: break;
1.1.1.5 root 4112: default:
4113: goto die;
4114: }
4115: break;
4116: case 19:
4117: switch (sel) {
1.1.1.6 root 4118: case 0 ... 7:
1.1.1.8 root 4119: gen_helper_1i(mtc0_watchhi, arg, sel);
1.1.1.6 root 4120: rn = "WatchHi";
4121: break;
1.1.1.5 root 4122: default:
4123: goto die;
4124: }
4125: break;
4126: case 20:
4127: switch (sel) {
4128: case 0:
1.1.1.6 root 4129: #if defined(TARGET_MIPS64)
4130: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 4131: gen_helper_mtc0_xcontext(arg);
1.1.1.6 root 4132: rn = "XContext";
4133: break;
4134: #endif
1.1.1.5 root 4135: default:
4136: goto die;
4137: }
4138: break;
4139: case 21:
4140: /* Officially reserved, but sel 0 is used for R1x000 framemask */
4141: switch (sel) {
4142: case 0:
1.1.1.8 root 4143: gen_helper_mtc0_framemask(arg);
1.1.1.6 root 4144: rn = "Framemask";
4145: break;
1.1.1.5 root 4146: default:
4147: goto die;
4148: }
4149: break;
4150: case 22:
4151: /* ignored */
4152: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 root 4153: break;
1.1.1.5 root 4154: case 23:
4155: switch (sel) {
4156: case 0:
1.1.1.8 root 4157: gen_helper_mtc0_debug(arg); /* EJTAG support */
1.1.1.6 root 4158: /* BS_STOP isn't good enough here, hflags may have changed. */
4159: gen_save_pc(ctx->pc + 4);
4160: ctx->bstate = BS_EXCP;
4161: rn = "Debug";
4162: break;
4163: case 1:
1.1.1.8 root 4164: // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 4165: rn = "TraceControl";
4166: /* Stop translation as we may have switched the execution mode */
4167: ctx->bstate = BS_STOP;
4168: // break;
4169: case 2:
1.1.1.8 root 4170: // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 4171: rn = "TraceControl2";
4172: /* Stop translation as we may have switched the execution mode */
4173: ctx->bstate = BS_STOP;
4174: // break;
4175: case 3:
4176: /* Stop translation as we may have switched the execution mode */
4177: ctx->bstate = BS_STOP;
1.1.1.8 root 4178: // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 4179: rn = "UserTraceData";
4180: /* Stop translation as we may have switched the execution mode */
4181: ctx->bstate = BS_STOP;
4182: // break;
1.1.1.5 root 4183: case 4:
1.1.1.8 root 4184: // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 4185: /* Stop translation as we may have switched the execution mode */
4186: ctx->bstate = BS_STOP;
4187: rn = "TraceBPC";
4188: // break;
1.1.1.5 root 4189: default:
4190: goto die;
4191: }
4192: break;
4193: case 24:
4194: switch (sel) {
4195: case 0:
1.1.1.7 root 4196: /* EJTAG support */
1.1.1.8 root 4197: gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 4198: rn = "DEPC";
4199: break;
1.1.1.5 root 4200: default:
4201: goto die;
4202: }
4203: break;
4204: case 25:
4205: switch (sel) {
4206: case 0:
1.1.1.8 root 4207: gen_helper_mtc0_performance0(arg);
1.1.1.6 root 4208: rn = "Performance0";
4209: break;
4210: case 1:
1.1.1.8 root 4211: // gen_helper_mtc0_performance1(arg);
1.1.1.6 root 4212: rn = "Performance1";
4213: // break;
4214: case 2:
1.1.1.8 root 4215: // gen_helper_mtc0_performance2(arg);
1.1.1.6 root 4216: rn = "Performance2";
4217: // break;
4218: case 3:
1.1.1.8 root 4219: // gen_helper_mtc0_performance3(arg);
1.1.1.6 root 4220: rn = "Performance3";
4221: // break;
1.1.1.5 root 4222: case 4:
1.1.1.8 root 4223: // gen_helper_mtc0_performance4(arg);
1.1.1.6 root 4224: rn = "Performance4";
4225: // break;
1.1.1.5 root 4226: case 5:
1.1.1.8 root 4227: // gen_helper_mtc0_performance5(arg);
1.1.1.6 root 4228: rn = "Performance5";
4229: // break;
1.1.1.5 root 4230: case 6:
1.1.1.8 root 4231: // gen_helper_mtc0_performance6(arg);
1.1.1.6 root 4232: rn = "Performance6";
4233: // break;
1.1.1.5 root 4234: case 7:
1.1.1.8 root 4235: // gen_helper_mtc0_performance7(arg);
1.1.1.6 root 4236: rn = "Performance7";
4237: // break;
1.1.1.5 root 4238: default:
4239: goto die;
4240: }
4241: break;
4242: case 26:
1.1.1.6 root 4243: /* ignored */
1.1.1.5 root 4244: rn = "ECC";
1.1.1.6 root 4245: break;
1.1.1.5 root 4246: case 27:
4247: switch (sel) {
4248: case 0 ... 3:
1.1.1.6 root 4249: /* ignored */
4250: rn = "CacheErr";
4251: break;
1.1.1.5 root 4252: default:
4253: goto die;
4254: }
4255: break;
4256: case 28:
4257: switch (sel) {
4258: case 0:
4259: case 2:
4260: case 4:
4261: case 6:
1.1.1.8 root 4262: gen_helper_mtc0_taglo(arg);
1.1.1.5 root 4263: rn = "TagLo";
4264: break;
4265: case 1:
4266: case 3:
4267: case 5:
4268: case 7:
1.1.1.8 root 4269: gen_helper_mtc0_datalo(arg);
1.1.1.5 root 4270: rn = "DataLo";
4271: break;
4272: default:
4273: goto die;
4274: }
4275: break;
4276: case 29:
4277: switch (sel) {
4278: case 0:
4279: case 2:
4280: case 4:
4281: case 6:
1.1.1.8 root 4282: gen_helper_mtc0_taghi(arg);
1.1.1.5 root 4283: rn = "TagHi";
4284: break;
4285: case 1:
4286: case 3:
4287: case 5:
4288: case 7:
1.1.1.8 root 4289: gen_helper_mtc0_datahi(arg);
1.1.1.5 root 4290: rn = "DataHi";
4291: break;
4292: default:
4293: rn = "invalid sel";
4294: goto die;
4295: }
4296: break;
4297: case 30:
4298: switch (sel) {
4299: case 0:
1.1.1.8 root 4300: gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 4301: rn = "ErrorEPC";
4302: break;
1.1.1.5 root 4303: default:
4304: goto die;
4305: }
4306: break;
4307: case 31:
4308: switch (sel) {
4309: case 0:
1.1.1.7 root 4310: /* EJTAG support */
1.1.1.8 root 4311: gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 4312: rn = "DESAVE";
4313: break;
1.1.1.5 root 4314: default:
4315: goto die;
4316: }
1.1.1.6 root 4317: /* Stop translation as we may have switched the execution mode */
4318: ctx->bstate = BS_STOP;
1.1.1.5 root 4319: break;
4320: default:
4321: goto die;
4322: }
1.1.1.7 root 4323: LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4324: /* For simplicity assume that all writes can cause interrupts. */
4325: if (use_icount) {
4326: gen_io_end();
4327: ctx->bstate = BS_STOP;
1.1.1.5 root 4328: }
4329: return;
4330:
4331: die:
1.1.1.7 root 4332: LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4333: generate_exception(ctx, EXCP_RI);
4334: }
4335:
1.1.1.6 root 4336: #if defined(TARGET_MIPS64)
1.1.1.8 root 4337: static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 4338: {
4339: const char *rn = "invalid";
4340:
1.1.1.6 root 4341: if (sel != 0)
4342: check_insn(env, ctx, ISA_MIPS64);
4343:
1.1.1.5 root 4344: switch (reg) {
4345: case 0:
4346: switch (sel) {
4347: case 0:
1.1.1.8 root 4348: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
1.1.1.5 root 4349: rn = "Index";
4350: break;
4351: case 1:
1.1.1.6 root 4352: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4353: gen_helper_mfc0_mvpcontrol(arg);
1.1.1.5 root 4354: rn = "MVPControl";
1.1.1.6 root 4355: break;
1.1.1.5 root 4356: case 2:
1.1.1.6 root 4357: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4358: gen_helper_mfc0_mvpconf0(arg);
1.1.1.5 root 4359: rn = "MVPConf0";
1.1.1.6 root 4360: break;
1.1.1.5 root 4361: case 3:
1.1.1.6 root 4362: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4363: gen_helper_mfc0_mvpconf1(arg);
1.1.1.5 root 4364: rn = "MVPConf1";
1.1.1.6 root 4365: break;
1.1.1.5 root 4366: default:
4367: goto die;
4368: }
4369: break;
4370: case 1:
4371: switch (sel) {
4372: case 0:
1.1.1.8 root 4373: gen_helper_mfc0_random(arg);
1.1.1.5 root 4374: rn = "Random";
1.1.1.6 root 4375: break;
1.1.1.5 root 4376: case 1:
1.1.1.6 root 4377: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4378: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
1.1.1.5 root 4379: rn = "VPEControl";
1.1.1.6 root 4380: break;
1.1.1.5 root 4381: case 2:
1.1.1.6 root 4382: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4383: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
1.1.1.5 root 4384: rn = "VPEConf0";
1.1.1.6 root 4385: break;
1.1.1.5 root 4386: case 3:
1.1.1.6 root 4387: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4388: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
1.1.1.5 root 4389: rn = "VPEConf1";
1.1.1.6 root 4390: break;
1.1.1.5 root 4391: case 4:
1.1.1.6 root 4392: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4393: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
1.1.1.5 root 4394: rn = "YQMask";
1.1.1.6 root 4395: break;
1.1.1.5 root 4396: case 5:
1.1.1.6 root 4397: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4398: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 4399: rn = "VPESchedule";
1.1.1.6 root 4400: break;
1.1.1.5 root 4401: case 6:
1.1.1.6 root 4402: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4403: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 4404: rn = "VPEScheFBack";
1.1.1.6 root 4405: break;
1.1.1.5 root 4406: case 7:
1.1.1.6 root 4407: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4408: gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
1.1.1.5 root 4409: rn = "VPEOpt";
1.1.1.6 root 4410: break;
1.1.1.5 root 4411: default:
4412: goto die;
4413: }
4414: break;
4415: case 2:
4416: switch (sel) {
4417: case 0:
1.1.1.8 root 4418: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
1.1.1.6 root 4419: rn = "EntryLo0";
4420: break;
4421: case 1:
4422: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4423: gen_helper_mfc0_tcstatus(arg);
1.1.1.6 root 4424: rn = "TCStatus";
4425: break;
4426: case 2:
4427: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4428: gen_helper_mfc0_tcbind(arg);
1.1.1.6 root 4429: rn = "TCBind";
4430: break;
1.1.1.5 root 4431: case 3:
1.1.1.6 root 4432: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4433: gen_helper_dmfc0_tcrestart(arg);
1.1.1.6 root 4434: rn = "TCRestart";
4435: break;
1.1.1.5 root 4436: case 4:
1.1.1.6 root 4437: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4438: gen_helper_dmfc0_tchalt(arg);
1.1.1.6 root 4439: rn = "TCHalt";
4440: break;
1.1.1.5 root 4441: case 5:
1.1.1.6 root 4442: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4443: gen_helper_dmfc0_tccontext(arg);
1.1.1.6 root 4444: rn = "TCContext";
4445: break;
1.1.1.5 root 4446: case 6:
1.1.1.6 root 4447: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4448: gen_helper_dmfc0_tcschedule(arg);
1.1.1.6 root 4449: rn = "TCSchedule";
4450: break;
1.1.1.5 root 4451: case 7:
1.1.1.6 root 4452: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4453: gen_helper_dmfc0_tcschefback(arg);
1.1.1.6 root 4454: rn = "TCScheFBack";
4455: break;
1.1.1.5 root 4456: default:
4457: goto die;
4458: }
4459: break;
4460: case 3:
4461: switch (sel) {
4462: case 0:
1.1.1.8 root 4463: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
1.1.1.6 root 4464: rn = "EntryLo1";
4465: break;
1.1.1.5 root 4466: default:
4467: goto die;
1.1.1.6 root 4468: }
1.1.1.5 root 4469: break;
4470: case 4:
4471: switch (sel) {
4472: case 0:
1.1.1.8 root 4473: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
1.1.1.6 root 4474: rn = "Context";
4475: break;
4476: case 1:
1.1.1.8 root 4477: // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 4478: rn = "ContextConfig";
4479: // break;
1.1.1.5 root 4480: default:
4481: goto die;
1.1.1.6 root 4482: }
1.1.1.5 root 4483: break;
4484: case 5:
4485: switch (sel) {
4486: case 0:
1.1.1.8 root 4487: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
1.1.1.6 root 4488: rn = "PageMask";
4489: break;
4490: case 1:
4491: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4492: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
1.1.1.6 root 4493: rn = "PageGrain";
4494: break;
1.1.1.5 root 4495: default:
4496: goto die;
1.1.1.6 root 4497: }
1.1.1.5 root 4498: break;
4499: case 6:
4500: switch (sel) {
4501: case 0:
1.1.1.8 root 4502: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
1.1.1.6 root 4503: rn = "Wired";
4504: break;
4505: case 1:
4506: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4507: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
1.1.1.6 root 4508: rn = "SRSConf0";
4509: break;
4510: case 2:
4511: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4512: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
1.1.1.6 root 4513: rn = "SRSConf1";
4514: break;
1.1.1.5 root 4515: case 3:
1.1.1.6 root 4516: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4517: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
1.1.1.6 root 4518: rn = "SRSConf2";
4519: break;
1.1.1.5 root 4520: case 4:
1.1.1.6 root 4521: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4522: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
1.1.1.6 root 4523: rn = "SRSConf3";
4524: break;
1.1.1.5 root 4525: case 5:
1.1.1.6 root 4526: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4527: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
1.1.1.6 root 4528: rn = "SRSConf4";
4529: break;
1.1.1.5 root 4530: default:
4531: goto die;
1.1.1.6 root 4532: }
1.1.1.5 root 4533: break;
4534: case 7:
4535: switch (sel) {
4536: case 0:
1.1.1.6 root 4537: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4538: gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
1.1.1.6 root 4539: rn = "HWREna";
4540: break;
1.1.1.5 root 4541: default:
4542: goto die;
1.1.1.6 root 4543: }
1.1.1.5 root 4544: break;
4545: case 8:
4546: switch (sel) {
4547: case 0:
1.1.1.8 root 4548: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
1.1.1.7 root 4549: rn = "BadVAddr";
1.1.1.6 root 4550: break;
1.1.1.5 root 4551: default:
4552: goto die;
1.1.1.6 root 4553: }
1.1.1.5 root 4554: break;
4555: case 9:
4556: switch (sel) {
4557: case 0:
1.1.1.7 root 4558: /* Mark as an IO operation because we read the time. */
4559: if (use_icount)
4560: gen_io_start();
1.1.1.8 root 4561: gen_helper_mfc0_count(arg);
1.1.1.7 root 4562: if (use_icount) {
4563: gen_io_end();
4564: ctx->bstate = BS_STOP;
4565: }
1.1.1.6 root 4566: rn = "Count";
4567: break;
4568: /* 6,7 are implementation dependent */
1.1.1.5 root 4569: default:
4570: goto die;
1.1.1.6 root 4571: }
1.1.1.5 root 4572: break;
4573: case 10:
4574: switch (sel) {
4575: case 0:
1.1.1.8 root 4576: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
1.1.1.6 root 4577: rn = "EntryHi";
4578: break;
1.1.1.5 root 4579: default:
4580: goto die;
1.1.1.6 root 4581: }
1.1.1.5 root 4582: break;
4583: case 11:
4584: switch (sel) {
4585: case 0:
1.1.1.8 root 4586: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
1.1.1.6 root 4587: rn = "Compare";
4588: break;
4589: /* 6,7 are implementation dependent */
1.1.1.5 root 4590: default:
4591: goto die;
1.1.1.6 root 4592: }
1.1.1.5 root 4593: break;
4594: case 12:
4595: switch (sel) {
4596: case 0:
1.1.1.8 root 4597: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
1.1.1.6 root 4598: rn = "Status";
4599: break;
4600: case 1:
4601: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4602: gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
1.1.1.6 root 4603: rn = "IntCtl";
4604: break;
4605: case 2:
4606: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4607: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
1.1.1.6 root 4608: rn = "SRSCtl";
4609: break;
1.1.1.5 root 4610: case 3:
1.1.1.6 root 4611: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4612: gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 4613: rn = "SRSMap";
4614: break;
1.1.1.5 root 4615: default:
4616: goto die;
1.1.1.6 root 4617: }
1.1.1.5 root 4618: break;
4619: case 13:
4620: switch (sel) {
4621: case 0:
1.1.1.8 root 4622: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
1.1.1.6 root 4623: rn = "Cause";
4624: break;
1.1.1.5 root 4625: default:
4626: goto die;
1.1.1.6 root 4627: }
1.1.1.5 root 4628: break;
4629: case 14:
4630: switch (sel) {
4631: case 0:
1.1.1.8 root 4632: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 4633: rn = "EPC";
4634: break;
1.1.1.5 root 4635: default:
4636: goto die;
1.1.1.6 root 4637: }
1.1.1.5 root 4638: break;
4639: case 15:
4640: switch (sel) {
4641: case 0:
1.1.1.8 root 4642: gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
1.1.1.6 root 4643: rn = "PRid";
4644: break;
4645: case 1:
4646: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 4647: gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
1.1.1.6 root 4648: rn = "EBase";
4649: break;
1.1.1.5 root 4650: default:
4651: goto die;
1.1.1.6 root 4652: }
1.1.1.5 root 4653: break;
4654: case 16:
4655: switch (sel) {
4656: case 0:
1.1.1.8 root 4657: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
1.1.1.5 root 4658: rn = "Config";
4659: break;
4660: case 1:
1.1.1.8 root 4661: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
1.1.1.5 root 4662: rn = "Config1";
4663: break;
4664: case 2:
1.1.1.8 root 4665: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
1.1.1.5 root 4666: rn = "Config2";
4667: break;
4668: case 3:
1.1.1.8 root 4669: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
1.1.1.5 root 4670: rn = "Config3";
4671: break;
4672: /* 6,7 are implementation dependent */
1.1.1.7 root 4673: case 6:
1.1.1.8 root 4674: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
1.1.1.7 root 4675: rn = "Config6";
4676: break;
4677: case 7:
1.1.1.8 root 4678: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
1.1.1.7 root 4679: rn = "Config7";
4680: break;
1.1.1.5 root 4681: default:
4682: goto die;
4683: }
4684: break;
4685: case 17:
4686: switch (sel) {
4687: case 0:
1.1.1.8 root 4688: gen_helper_dmfc0_lladdr(arg);
1.1.1.6 root 4689: rn = "LLAddr";
4690: break;
1.1.1.5 root 4691: default:
4692: goto die;
4693: }
4694: break;
4695: case 18:
4696: switch (sel) {
1.1.1.6 root 4697: case 0 ... 7:
1.1.1.8 root 4698: gen_helper_1i(dmfc0_watchlo, arg, sel);
1.1.1.6 root 4699: rn = "WatchLo";
4700: break;
1.1.1.5 root 4701: default:
4702: goto die;
4703: }
4704: break;
4705: case 19:
4706: switch (sel) {
1.1.1.6 root 4707: case 0 ... 7:
1.1.1.8 root 4708: gen_helper_1i(mfc0_watchhi, arg, sel);
1.1.1.6 root 4709: rn = "WatchHi";
4710: break;
1.1.1.5 root 4711: default:
4712: goto die;
4713: }
4714: break;
4715: case 20:
4716: switch (sel) {
4717: case 0:
1.1.1.6 root 4718: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 4719: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
1.1.1.6 root 4720: rn = "XContext";
4721: break;
1.1.1.5 root 4722: default:
4723: goto die;
4724: }
4725: break;
4726: case 21:
4727: /* Officially reserved, but sel 0 is used for R1x000 framemask */
4728: switch (sel) {
4729: case 0:
1.1.1.8 root 4730: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
1.1.1.6 root 4731: rn = "Framemask";
4732: break;
1.1.1.5 root 4733: default:
4734: goto die;
4735: }
4736: break;
4737: case 22:
1.1.1.8 root 4738: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 4739: rn = "'Diagnostic"; /* implementation dependent */
4740: break;
1.1.1.5 root 4741: case 23:
4742: switch (sel) {
4743: case 0:
1.1.1.8 root 4744: gen_helper_mfc0_debug(arg); /* EJTAG support */
1.1.1.6 root 4745: rn = "Debug";
4746: break;
4747: case 1:
1.1.1.8 root 4748: // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 4749: rn = "TraceControl";
4750: // break;
4751: case 2:
1.1.1.8 root 4752: // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 4753: rn = "TraceControl2";
4754: // break;
1.1.1.5 root 4755: case 3:
1.1.1.8 root 4756: // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 4757: rn = "UserTraceData";
4758: // break;
1.1.1.5 root 4759: case 4:
1.1.1.8 root 4760: // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 4761: rn = "TraceBPC";
4762: // break;
1.1.1.5 root 4763: default:
4764: goto die;
4765: }
4766: break;
4767: case 24:
4768: switch (sel) {
4769: case 0:
1.1.1.7 root 4770: /* EJTAG support */
1.1.1.8 root 4771: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 4772: rn = "DEPC";
4773: break;
1.1.1.5 root 4774: default:
4775: goto die;
4776: }
4777: break;
4778: case 25:
4779: switch (sel) {
4780: case 0:
1.1.1.8 root 4781: gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
1.1.1.6 root 4782: rn = "Performance0";
1.1.1.5 root 4783: break;
4784: case 1:
1.1.1.8 root 4785: // gen_helper_dmfc0_performance1(arg);
1.1.1.6 root 4786: rn = "Performance1";
4787: // break;
1.1.1.5 root 4788: case 2:
1.1.1.8 root 4789: // gen_helper_dmfc0_performance2(arg);
1.1.1.6 root 4790: rn = "Performance2";
4791: // break;
1.1.1.5 root 4792: case 3:
1.1.1.8 root 4793: // gen_helper_dmfc0_performance3(arg);
1.1.1.6 root 4794: rn = "Performance3";
4795: // break;
1.1.1.5 root 4796: case 4:
1.1.1.8 root 4797: // gen_helper_dmfc0_performance4(arg);
1.1.1.6 root 4798: rn = "Performance4";
4799: // break;
1.1.1.5 root 4800: case 5:
1.1.1.8 root 4801: // gen_helper_dmfc0_performance5(arg);
1.1.1.6 root 4802: rn = "Performance5";
4803: // break;
1.1.1.5 root 4804: case 6:
1.1.1.8 root 4805: // gen_helper_dmfc0_performance6(arg);
1.1.1.6 root 4806: rn = "Performance6";
4807: // break;
1.1.1.5 root 4808: case 7:
1.1.1.8 root 4809: // gen_helper_dmfc0_performance7(arg);
1.1.1.6 root 4810: rn = "Performance7";
4811: // break;
1.1.1.5 root 4812: default:
4813: goto die;
4814: }
4815: break;
4816: case 26:
1.1.1.8 root 4817: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.7 root 4818: rn = "ECC";
4819: break;
1.1.1.5 root 4820: case 27:
4821: switch (sel) {
4822: /* ignored */
4823: case 0 ... 3:
1.1.1.8 root 4824: tcg_gen_movi_tl(arg, 0); /* unimplemented */
1.1.1.6 root 4825: rn = "CacheErr";
4826: break;
1.1.1.5 root 4827: default:
4828: goto die;
4829: }
4830: break;
4831: case 28:
4832: switch (sel) {
4833: case 0:
4834: case 2:
4835: case 4:
4836: case 6:
1.1.1.8 root 4837: gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
1.1.1.5 root 4838: rn = "TagLo";
4839: break;
4840: case 1:
4841: case 3:
4842: case 5:
4843: case 7:
1.1.1.8 root 4844: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
1.1.1.5 root 4845: rn = "DataLo";
4846: break;
4847: default:
4848: goto die;
4849: }
4850: break;
4851: case 29:
4852: switch (sel) {
4853: case 0:
4854: case 2:
4855: case 4:
4856: case 6:
1.1.1.8 root 4857: gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
1.1.1.5 root 4858: rn = "TagHi";
4859: break;
4860: case 1:
4861: case 3:
4862: case 5:
4863: case 7:
1.1.1.8 root 4864: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
1.1.1.5 root 4865: rn = "DataHi";
4866: break;
4867: default:
4868: goto die;
4869: }
4870: break;
4871: case 30:
4872: switch (sel) {
4873: case 0:
1.1.1.8 root 4874: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 4875: rn = "ErrorEPC";
4876: break;
1.1.1.5 root 4877: default:
4878: goto die;
4879: }
4880: break;
4881: case 31:
4882: switch (sel) {
4883: case 0:
1.1.1.7 root 4884: /* EJTAG support */
1.1.1.8 root 4885: gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 4886: rn = "DESAVE";
4887: break;
1.1.1.5 root 4888: default:
4889: goto die;
4890: }
4891: break;
4892: default:
1.1.1.6 root 4893: goto die;
1.1.1.5 root 4894: }
1.1.1.7 root 4895: LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4896: return;
4897:
4898: die:
1.1.1.7 root 4899: LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4900: generate_exception(ctx, EXCP_RI);
4901: }
4902:
1.1.1.8 root 4903: static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
1.1.1.5 root 4904: {
4905: const char *rn = "invalid";
4906:
1.1.1.6 root 4907: if (sel != 0)
4908: check_insn(env, ctx, ISA_MIPS64);
4909:
1.1.1.7 root 4910: if (use_icount)
4911: gen_io_start();
4912:
1.1.1.5 root 4913: switch (reg) {
4914: case 0:
4915: switch (sel) {
4916: case 0:
1.1.1.8 root 4917: gen_helper_mtc0_index(arg);
1.1.1.5 root 4918: rn = "Index";
4919: break;
4920: case 1:
1.1.1.6 root 4921: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4922: gen_helper_mtc0_mvpcontrol(arg);
1.1.1.5 root 4923: rn = "MVPControl";
1.1.1.6 root 4924: break;
1.1.1.5 root 4925: case 2:
1.1.1.6 root 4926: check_insn(env, ctx, ASE_MT);
4927: /* ignored */
1.1.1.5 root 4928: rn = "MVPConf0";
1.1.1.6 root 4929: break;
1.1.1.5 root 4930: case 3:
1.1.1.6 root 4931: check_insn(env, ctx, ASE_MT);
4932: /* ignored */
1.1.1.5 root 4933: rn = "MVPConf1";
1.1.1.6 root 4934: break;
1.1.1.5 root 4935: default:
4936: goto die;
4937: }
4938: break;
4939: case 1:
4940: switch (sel) {
4941: case 0:
1.1.1.6 root 4942: /* ignored */
1.1.1.5 root 4943: rn = "Random";
1.1.1.6 root 4944: break;
1.1.1.5 root 4945: case 1:
1.1.1.6 root 4946: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4947: gen_helper_mtc0_vpecontrol(arg);
1.1.1.5 root 4948: rn = "VPEControl";
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);
1.1.1.8 root 4952: gen_helper_mtc0_vpeconf0(arg);
1.1.1.5 root 4953: rn = "VPEConf0";
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);
1.1.1.8 root 4957: gen_helper_mtc0_vpeconf1(arg);
1.1.1.5 root 4958: rn = "VPEConf1";
1.1.1.6 root 4959: break;
1.1.1.5 root 4960: case 4:
1.1.1.6 root 4961: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4962: gen_helper_mtc0_yqmask(arg);
1.1.1.5 root 4963: rn = "YQMask";
1.1.1.6 root 4964: break;
1.1.1.5 root 4965: case 5:
1.1.1.6 root 4966: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4967: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 4968: rn = "VPESchedule";
1.1.1.6 root 4969: break;
1.1.1.5 root 4970: case 6:
1.1.1.6 root 4971: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4972: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 4973: rn = "VPEScheFBack";
1.1.1.6 root 4974: break;
1.1.1.5 root 4975: case 7:
1.1.1.6 root 4976: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4977: gen_helper_mtc0_vpeopt(arg);
1.1.1.5 root 4978: rn = "VPEOpt";
1.1.1.6 root 4979: break;
1.1.1.5 root 4980: default:
4981: goto die;
4982: }
4983: break;
4984: case 2:
4985: switch (sel) {
4986: case 0:
1.1.1.8 root 4987: gen_helper_mtc0_entrylo0(arg);
1.1.1.6 root 4988: rn = "EntryLo0";
4989: break;
4990: case 1:
4991: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4992: gen_helper_mtc0_tcstatus(arg);
1.1.1.6 root 4993: rn = "TCStatus";
4994: break;
4995: case 2:
4996: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 4997: gen_helper_mtc0_tcbind(arg);
1.1.1.6 root 4998: rn = "TCBind";
4999: break;
1.1.1.5 root 5000: case 3:
1.1.1.6 root 5001: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5002: gen_helper_mtc0_tcrestart(arg);
1.1.1.6 root 5003: rn = "TCRestart";
5004: break;
1.1.1.5 root 5005: case 4:
1.1.1.6 root 5006: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5007: gen_helper_mtc0_tchalt(arg);
1.1.1.6 root 5008: rn = "TCHalt";
5009: break;
1.1.1.5 root 5010: case 5:
1.1.1.6 root 5011: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5012: gen_helper_mtc0_tccontext(arg);
1.1.1.6 root 5013: rn = "TCContext";
5014: break;
1.1.1.5 root 5015: case 6:
1.1.1.6 root 5016: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5017: gen_helper_mtc0_tcschedule(arg);
1.1.1.6 root 5018: rn = "TCSchedule";
5019: break;
1.1.1.5 root 5020: case 7:
1.1.1.6 root 5021: check_insn(env, ctx, ASE_MT);
1.1.1.8 root 5022: gen_helper_mtc0_tcschefback(arg);
1.1.1.6 root 5023: rn = "TCScheFBack";
5024: break;
1.1.1.5 root 5025: default:
5026: goto die;
5027: }
5028: break;
5029: case 3:
5030: switch (sel) {
5031: case 0:
1.1.1.8 root 5032: gen_helper_mtc0_entrylo1(arg);
1.1.1.6 root 5033: rn = "EntryLo1";
5034: break;
1.1.1.5 root 5035: default:
5036: goto die;
1.1.1.6 root 5037: }
1.1.1.5 root 5038: break;
5039: case 4:
5040: switch (sel) {
5041: case 0:
1.1.1.8 root 5042: gen_helper_mtc0_context(arg);
1.1.1.6 root 5043: rn = "Context";
5044: break;
5045: case 1:
1.1.1.8 root 5046: // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
1.1.1.6 root 5047: rn = "ContextConfig";
5048: // break;
1.1.1.5 root 5049: default:
5050: goto die;
1.1.1.6 root 5051: }
1.1.1.5 root 5052: break;
5053: case 5:
5054: switch (sel) {
5055: case 0:
1.1.1.8 root 5056: gen_helper_mtc0_pagemask(arg);
1.1.1.6 root 5057: rn = "PageMask";
5058: break;
5059: case 1:
5060: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5061: gen_helper_mtc0_pagegrain(arg);
1.1.1.6 root 5062: rn = "PageGrain";
5063: break;
1.1.1.5 root 5064: default:
5065: goto die;
1.1.1.6 root 5066: }
1.1.1.5 root 5067: break;
5068: case 6:
5069: switch (sel) {
5070: case 0:
1.1.1.8 root 5071: gen_helper_mtc0_wired(arg);
1.1.1.6 root 5072: rn = "Wired";
5073: break;
5074: case 1:
5075: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5076: gen_helper_mtc0_srsconf0(arg);
1.1.1.6 root 5077: rn = "SRSConf0";
5078: break;
5079: case 2:
5080: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5081: gen_helper_mtc0_srsconf1(arg);
1.1.1.6 root 5082: rn = "SRSConf1";
5083: break;
1.1.1.5 root 5084: case 3:
1.1.1.6 root 5085: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5086: gen_helper_mtc0_srsconf2(arg);
1.1.1.6 root 5087: rn = "SRSConf2";
5088: break;
1.1.1.5 root 5089: case 4:
1.1.1.6 root 5090: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5091: gen_helper_mtc0_srsconf3(arg);
1.1.1.6 root 5092: rn = "SRSConf3";
5093: break;
1.1.1.5 root 5094: case 5:
1.1.1.6 root 5095: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5096: gen_helper_mtc0_srsconf4(arg);
1.1.1.6 root 5097: rn = "SRSConf4";
5098: break;
1.1.1.5 root 5099: default:
5100: goto die;
1.1.1.6 root 5101: }
1.1.1.5 root 5102: break;
5103: case 7:
5104: switch (sel) {
5105: case 0:
1.1.1.6 root 5106: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5107: gen_helper_mtc0_hwrena(arg);
1.1.1.6 root 5108: rn = "HWREna";
5109: break;
1.1.1.5 root 5110: default:
5111: goto die;
1.1.1.6 root 5112: }
1.1.1.5 root 5113: break;
5114: case 8:
5115: /* ignored */
1.1.1.7 root 5116: rn = "BadVAddr";
1.1.1.5 root 5117: break;
5118: case 9:
5119: switch (sel) {
5120: case 0:
1.1.1.8 root 5121: gen_helper_mtc0_count(arg);
1.1.1.6 root 5122: rn = "Count";
5123: break;
5124: /* 6,7 are implementation dependent */
1.1.1.5 root 5125: default:
5126: goto die;
1.1.1.6 root 5127: }
5128: /* Stop translation as we may have switched the execution mode */
5129: ctx->bstate = BS_STOP;
1.1.1.5 root 5130: break;
5131: case 10:
5132: switch (sel) {
5133: case 0:
1.1.1.8 root 5134: gen_helper_mtc0_entryhi(arg);
1.1.1.6 root 5135: rn = "EntryHi";
5136: break;
1.1.1.5 root 5137: default:
5138: goto die;
1.1.1.6 root 5139: }
1.1.1.5 root 5140: break;
5141: case 11:
5142: switch (sel) {
5143: case 0:
1.1.1.8 root 5144: gen_helper_mtc0_compare(arg);
1.1.1.6 root 5145: rn = "Compare";
5146: break;
5147: /* 6,7 are implementation dependent */
1.1.1.5 root 5148: default:
5149: goto die;
1.1.1.6 root 5150: }
5151: /* Stop translation as we may have switched the execution mode */
5152: ctx->bstate = BS_STOP;
1.1.1.5 root 5153: break;
5154: case 12:
5155: switch (sel) {
5156: case 0:
1.1.1.8 root 5157: save_cpu_state(ctx, 1);
5158: gen_helper_mtc0_status(arg);
1.1.1.6 root 5159: /* BS_STOP isn't good enough here, hflags may have changed. */
5160: gen_save_pc(ctx->pc + 4);
5161: ctx->bstate = BS_EXCP;
5162: rn = "Status";
5163: break;
5164: case 1:
5165: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5166: gen_helper_mtc0_intctl(arg);
1.1.1.6 root 5167: /* Stop translation as we may have switched the execution mode */
5168: ctx->bstate = BS_STOP;
5169: rn = "IntCtl";
5170: break;
5171: case 2:
5172: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5173: gen_helper_mtc0_srsctl(arg);
1.1.1.6 root 5174: /* Stop translation as we may have switched the execution mode */
5175: ctx->bstate = BS_STOP;
5176: rn = "SRSCtl";
5177: break;
1.1.1.5 root 5178: case 3:
1.1.1.6 root 5179: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5180: gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 5181: /* Stop translation as we may have switched the execution mode */
5182: ctx->bstate = BS_STOP;
5183: rn = "SRSMap";
5184: break;
1.1.1.5 root 5185: default:
5186: goto die;
1.1.1.6 root 5187: }
1.1.1.5 root 5188: break;
5189: case 13:
5190: switch (sel) {
5191: case 0:
1.1.1.8 root 5192: save_cpu_state(ctx, 1);
1.1.1.12! root 5193: /* Mark as an IO operation because we may trigger a software
! 5194: interrupt. */
! 5195: if (use_icount) {
! 5196: gen_io_start();
! 5197: }
1.1.1.8 root 5198: gen_helper_mtc0_cause(arg);
1.1.1.12! root 5199: if (use_icount) {
! 5200: gen_io_end();
! 5201: }
! 5202: /* Stop translation as we may have triggered an intetrupt */
! 5203: ctx->bstate = BS_STOP;
1.1.1.6 root 5204: rn = "Cause";
5205: break;
1.1.1.5 root 5206: default:
5207: goto die;
1.1.1.6 root 5208: }
1.1.1.5 root 5209: break;
5210: case 14:
5211: switch (sel) {
5212: case 0:
1.1.1.8 root 5213: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 5214: rn = "EPC";
5215: break;
1.1.1.5 root 5216: default:
5217: goto die;
1.1.1.6 root 5218: }
1.1.1.5 root 5219: break;
5220: case 15:
5221: switch (sel) {
5222: case 0:
1.1.1.6 root 5223: /* ignored */
5224: rn = "PRid";
5225: break;
5226: case 1:
5227: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.8 root 5228: gen_helper_mtc0_ebase(arg);
1.1.1.6 root 5229: rn = "EBase";
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 16:
5236: switch (sel) {
5237: case 0:
1.1.1.8 root 5238: gen_helper_mtc0_config0(arg);
1.1.1.5 root 5239: rn = "Config";
1.1.1.6 root 5240: /* Stop translation as we may have switched the execution mode */
5241: ctx->bstate = BS_STOP;
1.1.1.5 root 5242: break;
5243: case 1:
1.1.1.8 root 5244: /* ignored, read only */
1.1.1.5 root 5245: rn = "Config1";
5246: break;
5247: case 2:
1.1.1.8 root 5248: gen_helper_mtc0_config2(arg);
1.1.1.5 root 5249: rn = "Config2";
1.1.1.6 root 5250: /* Stop translation as we may have switched the execution mode */
5251: ctx->bstate = BS_STOP;
1.1.1.5 root 5252: break;
5253: case 3:
1.1.1.6 root 5254: /* ignored */
1.1.1.5 root 5255: rn = "Config3";
5256: break;
5257: /* 6,7 are implementation dependent */
5258: default:
5259: rn = "Invalid config selector";
5260: goto die;
5261: }
5262: break;
5263: case 17:
5264: switch (sel) {
5265: case 0:
1.1.1.9 root 5266: gen_helper_mtc0_lladdr(arg);
1.1.1.6 root 5267: rn = "LLAddr";
5268: break;
1.1.1.5 root 5269: default:
5270: goto die;
5271: }
5272: break;
5273: case 18:
5274: switch (sel) {
1.1.1.6 root 5275: case 0 ... 7:
1.1.1.8 root 5276: gen_helper_1i(mtc0_watchlo, arg, sel);
1.1.1.6 root 5277: rn = "WatchLo";
5278: break;
1.1.1.5 root 5279: default:
5280: goto die;
5281: }
5282: break;
5283: case 19:
5284: switch (sel) {
1.1.1.6 root 5285: case 0 ... 7:
1.1.1.8 root 5286: gen_helper_1i(mtc0_watchhi, arg, sel);
1.1.1.6 root 5287: rn = "WatchHi";
5288: break;
1.1.1.5 root 5289: default:
5290: goto die;
5291: }
5292: break;
5293: case 20:
5294: switch (sel) {
5295: case 0:
1.1.1.6 root 5296: check_insn(env, ctx, ISA_MIPS3);
1.1.1.8 root 5297: gen_helper_mtc0_xcontext(arg);
1.1.1.6 root 5298: rn = "XContext";
5299: break;
1.1.1.5 root 5300: default:
5301: goto die;
5302: }
5303: break;
5304: case 21:
5305: /* Officially reserved, but sel 0 is used for R1x000 framemask */
5306: switch (sel) {
5307: case 0:
1.1.1.8 root 5308: gen_helper_mtc0_framemask(arg);
1.1.1.6 root 5309: rn = "Framemask";
5310: break;
1.1.1.5 root 5311: default:
5312: goto die;
5313: }
5314: break;
5315: case 22:
5316: /* ignored */
5317: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 root 5318: break;
1.1.1.5 root 5319: case 23:
5320: switch (sel) {
5321: case 0:
1.1.1.8 root 5322: gen_helper_mtc0_debug(arg); /* EJTAG support */
1.1.1.6 root 5323: /* BS_STOP isn't good enough here, hflags may have changed. */
5324: gen_save_pc(ctx->pc + 4);
5325: ctx->bstate = BS_EXCP;
5326: rn = "Debug";
5327: break;
5328: case 1:
1.1.1.8 root 5329: // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
1.1.1.6 root 5330: /* Stop translation as we may have switched the execution mode */
5331: ctx->bstate = BS_STOP;
5332: rn = "TraceControl";
5333: // break;
5334: case 2:
1.1.1.8 root 5335: // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
1.1.1.6 root 5336: /* Stop translation as we may have switched the execution mode */
5337: ctx->bstate = BS_STOP;
5338: rn = "TraceControl2";
5339: // break;
5340: case 3:
1.1.1.8 root 5341: // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
1.1.1.6 root 5342: /* Stop translation as we may have switched the execution mode */
5343: ctx->bstate = BS_STOP;
5344: rn = "UserTraceData";
5345: // break;
1.1.1.5 root 5346: case 4:
1.1.1.8 root 5347: // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
1.1.1.6 root 5348: /* Stop translation as we may have switched the execution mode */
5349: ctx->bstate = BS_STOP;
5350: rn = "TraceBPC";
5351: // break;
1.1.1.5 root 5352: default:
5353: goto die;
5354: }
5355: break;
5356: case 24:
5357: switch (sel) {
5358: case 0:
1.1.1.7 root 5359: /* EJTAG support */
1.1.1.8 root 5360: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 5361: rn = "DEPC";
5362: break;
1.1.1.5 root 5363: default:
5364: goto die;
5365: }
5366: break;
5367: case 25:
5368: switch (sel) {
5369: case 0:
1.1.1.8 root 5370: gen_helper_mtc0_performance0(arg);
1.1.1.6 root 5371: rn = "Performance0";
5372: break;
5373: case 1:
1.1.1.8 root 5374: // gen_helper_mtc0_performance1(arg);
1.1.1.6 root 5375: rn = "Performance1";
5376: // break;
5377: case 2:
1.1.1.8 root 5378: // gen_helper_mtc0_performance2(arg);
1.1.1.6 root 5379: rn = "Performance2";
5380: // break;
1.1.1.5 root 5381: case 3:
1.1.1.8 root 5382: // gen_helper_mtc0_performance3(arg);
1.1.1.6 root 5383: rn = "Performance3";
5384: // break;
1.1.1.5 root 5385: case 4:
1.1.1.8 root 5386: // gen_helper_mtc0_performance4(arg);
1.1.1.6 root 5387: rn = "Performance4";
5388: // break;
1.1.1.5 root 5389: case 5:
1.1.1.8 root 5390: // gen_helper_mtc0_performance5(arg);
1.1.1.6 root 5391: rn = "Performance5";
5392: // break;
1.1.1.5 root 5393: case 6:
1.1.1.8 root 5394: // gen_helper_mtc0_performance6(arg);
1.1.1.6 root 5395: rn = "Performance6";
5396: // break;
1.1.1.5 root 5397: case 7:
1.1.1.8 root 5398: // gen_helper_mtc0_performance7(arg);
1.1.1.6 root 5399: rn = "Performance7";
5400: // break;
1.1.1.5 root 5401: default:
5402: goto die;
5403: }
1.1.1.6 root 5404: break;
1.1.1.5 root 5405: case 26:
1.1.1.6 root 5406: /* ignored */
1.1.1.5 root 5407: rn = "ECC";
1.1.1.6 root 5408: break;
1.1.1.5 root 5409: case 27:
5410: switch (sel) {
5411: case 0 ... 3:
1.1.1.6 root 5412: /* ignored */
5413: rn = "CacheErr";
5414: break;
1.1.1.5 root 5415: default:
5416: goto die;
5417: }
1.1.1.6 root 5418: break;
1.1.1.5 root 5419: case 28:
5420: switch (sel) {
5421: case 0:
5422: case 2:
5423: case 4:
5424: case 6:
1.1.1.8 root 5425: gen_helper_mtc0_taglo(arg);
1.1.1.5 root 5426: rn = "TagLo";
5427: break;
5428: case 1:
5429: case 3:
5430: case 5:
5431: case 7:
1.1.1.8 root 5432: gen_helper_mtc0_datalo(arg);
1.1.1.5 root 5433: rn = "DataLo";
5434: break;
5435: default:
5436: goto die;
5437: }
5438: break;
5439: case 29:
5440: switch (sel) {
5441: case 0:
5442: case 2:
5443: case 4:
5444: case 6:
1.1.1.8 root 5445: gen_helper_mtc0_taghi(arg);
1.1.1.5 root 5446: rn = "TagHi";
5447: break;
5448: case 1:
5449: case 3:
5450: case 5:
5451: case 7:
1.1.1.8 root 5452: gen_helper_mtc0_datahi(arg);
1.1.1.5 root 5453: rn = "DataHi";
5454: break;
5455: default:
5456: rn = "invalid sel";
5457: goto die;
5458: }
1.1.1.6 root 5459: break;
1.1.1.5 root 5460: case 30:
5461: switch (sel) {
5462: case 0:
1.1.1.8 root 5463: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 5464: rn = "ErrorEPC";
5465: break;
1.1.1.5 root 5466: default:
5467: goto die;
5468: }
5469: break;
5470: case 31:
5471: switch (sel) {
5472: case 0:
1.1.1.7 root 5473: /* EJTAG support */
1.1.1.8 root 5474: gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 5475: rn = "DESAVE";
5476: break;
1.1.1.5 root 5477: default:
5478: goto die;
5479: }
1.1.1.6 root 5480: /* Stop translation as we may have switched the execution mode */
5481: ctx->bstate = BS_STOP;
1.1.1.5 root 5482: break;
5483: default:
1.1.1.6 root 5484: goto die;
1.1.1.5 root 5485: }
1.1.1.7 root 5486: LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5487: /* For simplicity assume that all writes can cause interrupts. */
5488: if (use_icount) {
5489: gen_io_end();
5490: ctx->bstate = BS_STOP;
1.1.1.5 root 5491: }
5492: return;
5493:
5494: die:
1.1.1.7 root 5495: LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 5496: generate_exception(ctx, EXCP_RI);
5497: }
1.1.1.6 root 5498: #endif /* TARGET_MIPS64 */
1.1.1.5 root 5499:
1.1.1.7 root 5500: static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
1.1.1.6 root 5501: int u, int sel, int h)
1.1.1.5 root 5502: {
1.1.1.6 root 5503: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.7 root 5504: TCGv t0 = tcg_temp_local_new();
1.1.1.5 root 5505:
1.1.1.6 root 5506: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
1.1.1.7 root 5507: ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5508: (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5509: tcg_gen_movi_tl(t0, -1);
1.1.1.6 root 5510: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5511: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1.1.1.7 root 5512: tcg_gen_movi_tl(t0, -1);
1.1.1.6 root 5513: else if (u == 0) {
5514: switch (rt) {
5515: case 2:
5516: switch (sel) {
5517: case 1:
1.1.1.7 root 5518: gen_helper_mftc0_tcstatus(t0);
1.1.1.6 root 5519: break;
5520: case 2:
1.1.1.7 root 5521: gen_helper_mftc0_tcbind(t0);
1.1.1.6 root 5522: break;
5523: case 3:
1.1.1.7 root 5524: gen_helper_mftc0_tcrestart(t0);
1.1.1.6 root 5525: break;
5526: case 4:
1.1.1.7 root 5527: gen_helper_mftc0_tchalt(t0);
1.1.1.6 root 5528: break;
5529: case 5:
1.1.1.7 root 5530: gen_helper_mftc0_tccontext(t0);
1.1.1.6 root 5531: break;
5532: case 6:
1.1.1.7 root 5533: gen_helper_mftc0_tcschedule(t0);
1.1.1.6 root 5534: break;
5535: case 7:
1.1.1.7 root 5536: gen_helper_mftc0_tcschefback(t0);
1.1.1.6 root 5537: break;
5538: default:
1.1.1.7 root 5539: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5540: break;
5541: }
5542: break;
5543: case 10:
5544: switch (sel) {
5545: case 0:
1.1.1.7 root 5546: gen_helper_mftc0_entryhi(t0);
1.1.1.6 root 5547: break;
5548: default:
1.1.1.7 root 5549: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5550: break;
5551: }
5552: case 12:
5553: switch (sel) {
5554: case 0:
1.1.1.7 root 5555: gen_helper_mftc0_status(t0);
1.1.1.6 root 5556: break;
5557: default:
1.1.1.7 root 5558: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5559: break;
5560: }
5561: case 23:
5562: switch (sel) {
5563: case 0:
1.1.1.7 root 5564: gen_helper_mftc0_debug(t0);
1.1.1.6 root 5565: break;
5566: default:
1.1.1.7 root 5567: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5568: break;
5569: }
5570: break;
5571: default:
1.1.1.7 root 5572: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5573: }
5574: } else switch (sel) {
5575: /* GPR registers. */
5576: case 0:
1.1.1.7 root 5577: gen_helper_1i(mftgpr, t0, rt);
1.1.1.6 root 5578: break;
5579: /* Auxiliary CPU registers */
5580: case 1:
5581: switch (rt) {
5582: case 0:
1.1.1.7 root 5583: gen_helper_1i(mftlo, t0, 0);
1.1.1.6 root 5584: break;
5585: case 1:
1.1.1.7 root 5586: gen_helper_1i(mfthi, t0, 0);
1.1.1.6 root 5587: break;
5588: case 2:
1.1.1.7 root 5589: gen_helper_1i(mftacx, t0, 0);
1.1.1.6 root 5590: break;
5591: case 4:
1.1.1.7 root 5592: gen_helper_1i(mftlo, t0, 1);
1.1.1.6 root 5593: break;
5594: case 5:
1.1.1.7 root 5595: gen_helper_1i(mfthi, t0, 1);
1.1.1.6 root 5596: break;
5597: case 6:
1.1.1.7 root 5598: gen_helper_1i(mftacx, t0, 1);
1.1.1.6 root 5599: break;
5600: case 8:
1.1.1.7 root 5601: gen_helper_1i(mftlo, t0, 2);
1.1.1.6 root 5602: break;
5603: case 9:
1.1.1.7 root 5604: gen_helper_1i(mfthi, t0, 2);
1.1.1.6 root 5605: break;
5606: case 10:
1.1.1.7 root 5607: gen_helper_1i(mftacx, t0, 2);
1.1.1.6 root 5608: break;
5609: case 12:
1.1.1.7 root 5610: gen_helper_1i(mftlo, t0, 3);
1.1.1.6 root 5611: break;
5612: case 13:
1.1.1.7 root 5613: gen_helper_1i(mfthi, t0, 3);
1.1.1.6 root 5614: break;
5615: case 14:
1.1.1.7 root 5616: gen_helper_1i(mftacx, t0, 3);
1.1.1.6 root 5617: break;
5618: case 16:
1.1.1.7 root 5619: gen_helper_mftdsp(t0);
1.1.1.6 root 5620: break;
5621: default:
5622: goto die;
5623: }
5624: break;
5625: /* Floating point (COP1). */
5626: case 2:
5627: /* XXX: For now we support only a single FPU context. */
5628: if (h == 0) {
1.1.1.7 root 5629: TCGv_i32 fp0 = tcg_temp_new_i32();
5630:
5631: gen_load_fpr32(fp0, rt);
5632: tcg_gen_ext_i32_tl(t0, fp0);
5633: tcg_temp_free_i32(fp0);
1.1.1.6 root 5634: } else {
1.1.1.7 root 5635: TCGv_i32 fp0 = tcg_temp_new_i32();
5636:
5637: gen_load_fpr32h(fp0, rt);
5638: tcg_gen_ext_i32_tl(t0, fp0);
5639: tcg_temp_free_i32(fp0);
1.1.1.6 root 5640: }
5641: break;
5642: case 3:
5643: /* XXX: For now we support only a single FPU context. */
1.1.1.7 root 5644: gen_helper_1i(cfc1, t0, rt);
1.1.1.6 root 5645: break;
5646: /* COP2: Not implemented. */
5647: case 4:
5648: case 5:
5649: /* fall through */
5650: default:
5651: goto die;
5652: }
1.1.1.7 root 5653: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5654: gen_store_gpr(t0, rd);
5655: tcg_temp_free(t0);
1.1.1.6 root 5656: return;
5657:
5658: die:
1.1.1.7 root 5659: tcg_temp_free(t0);
5660: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1.1.1.6 root 5661: generate_exception(ctx, EXCP_RI);
5662: }
5663:
1.1.1.7 root 5664: static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
1.1.1.6 root 5665: int u, int sel, int h)
5666: {
5667: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.7 root 5668: TCGv t0 = tcg_temp_local_new();
1.1.1.6 root 5669:
1.1.1.7 root 5670: gen_load_gpr(t0, rt);
1.1.1.6 root 5671: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
1.1.1.7 root 5672: ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5673: (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1.1.1.6 root 5674: /* NOP */ ;
5675: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5676: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5677: /* NOP */ ;
5678: else if (u == 0) {
5679: switch (rd) {
5680: case 2:
5681: switch (sel) {
5682: case 1:
1.1.1.7 root 5683: gen_helper_mttc0_tcstatus(t0);
1.1.1.6 root 5684: break;
5685: case 2:
1.1.1.7 root 5686: gen_helper_mttc0_tcbind(t0);
1.1.1.6 root 5687: break;
5688: case 3:
1.1.1.7 root 5689: gen_helper_mttc0_tcrestart(t0);
1.1.1.6 root 5690: break;
5691: case 4:
1.1.1.7 root 5692: gen_helper_mttc0_tchalt(t0);
1.1.1.6 root 5693: break;
5694: case 5:
1.1.1.7 root 5695: gen_helper_mttc0_tccontext(t0);
1.1.1.6 root 5696: break;
5697: case 6:
1.1.1.7 root 5698: gen_helper_mttc0_tcschedule(t0);
1.1.1.6 root 5699: break;
5700: case 7:
1.1.1.7 root 5701: gen_helper_mttc0_tcschefback(t0);
1.1.1.6 root 5702: break;
5703: default:
1.1.1.7 root 5704: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5705: break;
5706: }
5707: break;
5708: case 10:
5709: switch (sel) {
5710: case 0:
1.1.1.7 root 5711: gen_helper_mttc0_entryhi(t0);
1.1.1.6 root 5712: break;
5713: default:
1.1.1.7 root 5714: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5715: break;
5716: }
5717: case 12:
5718: switch (sel) {
5719: case 0:
1.1.1.7 root 5720: gen_helper_mttc0_status(t0);
1.1.1.6 root 5721: break;
5722: default:
1.1.1.7 root 5723: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5724: break;
5725: }
5726: case 23:
5727: switch (sel) {
5728: case 0:
1.1.1.7 root 5729: gen_helper_mttc0_debug(t0);
1.1.1.6 root 5730: break;
5731: default:
1.1.1.7 root 5732: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5733: break;
5734: }
5735: break;
5736: default:
1.1.1.7 root 5737: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5738: }
5739: } else switch (sel) {
5740: /* GPR registers. */
5741: case 0:
1.1.1.7 root 5742: gen_helper_1i(mttgpr, t0, rd);
1.1.1.6 root 5743: break;
5744: /* Auxiliary CPU registers */
5745: case 1:
5746: switch (rd) {
5747: case 0:
1.1.1.7 root 5748: gen_helper_1i(mttlo, t0, 0);
1.1.1.6 root 5749: break;
5750: case 1:
1.1.1.7 root 5751: gen_helper_1i(mtthi, t0, 0);
1.1.1.6 root 5752: break;
5753: case 2:
1.1.1.7 root 5754: gen_helper_1i(mttacx, t0, 0);
1.1.1.6 root 5755: break;
5756: case 4:
1.1.1.7 root 5757: gen_helper_1i(mttlo, t0, 1);
1.1.1.6 root 5758: break;
5759: case 5:
1.1.1.7 root 5760: gen_helper_1i(mtthi, t0, 1);
1.1.1.6 root 5761: break;
5762: case 6:
1.1.1.7 root 5763: gen_helper_1i(mttacx, t0, 1);
1.1.1.6 root 5764: break;
5765: case 8:
1.1.1.7 root 5766: gen_helper_1i(mttlo, t0, 2);
1.1.1.6 root 5767: break;
5768: case 9:
1.1.1.7 root 5769: gen_helper_1i(mtthi, t0, 2);
1.1.1.6 root 5770: break;
5771: case 10:
1.1.1.7 root 5772: gen_helper_1i(mttacx, t0, 2);
1.1.1.6 root 5773: break;
5774: case 12:
1.1.1.7 root 5775: gen_helper_1i(mttlo, t0, 3);
1.1.1.6 root 5776: break;
5777: case 13:
1.1.1.7 root 5778: gen_helper_1i(mtthi, t0, 3);
1.1.1.6 root 5779: break;
5780: case 14:
1.1.1.7 root 5781: gen_helper_1i(mttacx, t0, 3);
1.1.1.6 root 5782: break;
5783: case 16:
1.1.1.7 root 5784: gen_helper_mttdsp(t0);
1.1.1.6 root 5785: break;
5786: default:
5787: goto die;
5788: }
5789: break;
5790: /* Floating point (COP1). */
5791: case 2:
5792: /* XXX: For now we support only a single FPU context. */
5793: if (h == 0) {
1.1.1.7 root 5794: TCGv_i32 fp0 = tcg_temp_new_i32();
5795:
5796: tcg_gen_trunc_tl_i32(fp0, t0);
5797: gen_store_fpr32(fp0, rd);
5798: tcg_temp_free_i32(fp0);
1.1.1.6 root 5799: } else {
1.1.1.7 root 5800: TCGv_i32 fp0 = tcg_temp_new_i32();
5801:
5802: tcg_gen_trunc_tl_i32(fp0, t0);
5803: gen_store_fpr32h(fp0, rd);
5804: tcg_temp_free_i32(fp0);
1.1.1.6 root 5805: }
5806: break;
5807: case 3:
5808: /* XXX: For now we support only a single FPU context. */
1.1.1.7 root 5809: gen_helper_1i(ctc1, t0, rd);
1.1.1.6 root 5810: break;
5811: /* COP2: Not implemented. */
5812: case 4:
5813: case 5:
5814: /* fall through */
5815: default:
5816: goto die;
5817: }
1.1.1.7 root 5818: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5819: tcg_temp_free(t0);
1.1.1.6 root 5820: return;
5821:
5822: die:
1.1.1.7 root 5823: tcg_temp_free(t0);
5824: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1.1.1.6 root 5825: generate_exception(ctx, EXCP_RI);
5826: }
5827:
5828: static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5829: {
5830: const char *opn = "ldst";
1.1.1.5 root 5831:
5832: switch (opc) {
5833: case OPC_MFC0:
5834: if (rt == 0) {
1.1.1.6 root 5835: /* Treat as NOP. */
1.1.1.5 root 5836: return;
5837: }
1.1.1.8 root 5838: gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
1.1.1.5 root 5839: opn = "mfc0";
5840: break;
5841: case OPC_MTC0:
1.1.1.7 root 5842: {
1.1.1.8 root 5843: TCGv t0 = tcg_temp_new();
1.1.1.7 root 5844:
5845: gen_load_gpr(t0, rt);
5846: gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5847: tcg_temp_free(t0);
5848: }
1.1.1.5 root 5849: opn = "mtc0";
5850: break;
1.1.1.6 root 5851: #if defined(TARGET_MIPS64)
1.1.1.5 root 5852: case OPC_DMFC0:
1.1.1.6 root 5853: check_insn(env, ctx, ISA_MIPS3);
1.1.1.5 root 5854: if (rt == 0) {
1.1.1.6 root 5855: /* Treat as NOP. */
1.1.1.5 root 5856: return;
5857: }
1.1.1.8 root 5858: gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
1.1.1.5 root 5859: opn = "dmfc0";
5860: break;
5861: case OPC_DMTC0:
1.1.1.6 root 5862: check_insn(env, ctx, ISA_MIPS3);
1.1.1.7 root 5863: {
1.1.1.8 root 5864: TCGv t0 = tcg_temp_new();
1.1.1.7 root 5865:
5866: gen_load_gpr(t0, rt);
5867: gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5868: tcg_temp_free(t0);
5869: }
1.1.1.5 root 5870: opn = "dmtc0";
5871: break;
1.1.1.6 root 5872: #endif
5873: case OPC_MFTR:
5874: check_insn(env, ctx, ASE_MT);
5875: if (rd == 0) {
5876: /* Treat as NOP. */
5877: return;
5878: }
1.1.1.7 root 5879: gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5880: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5881: opn = "mftr";
5882: break;
5883: case OPC_MTTR:
5884: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 5885: gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5886: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5887: opn = "mttr";
5888: break;
1.1.1.5 root 5889: case OPC_TLBWI:
5890: opn = "tlbwi";
1.1.1.8 root 5891: if (!env->tlb->helper_tlbwi)
1.1.1.6 root 5892: goto die;
1.1.1.7 root 5893: gen_helper_tlbwi();
1.1.1.5 root 5894: break;
5895: case OPC_TLBWR:
5896: opn = "tlbwr";
1.1.1.8 root 5897: if (!env->tlb->helper_tlbwr)
1.1.1.6 root 5898: goto die;
1.1.1.7 root 5899: gen_helper_tlbwr();
1.1.1.5 root 5900: break;
5901: case OPC_TLBP:
5902: opn = "tlbp";
1.1.1.8 root 5903: if (!env->tlb->helper_tlbp)
1.1.1.6 root 5904: goto die;
1.1.1.7 root 5905: gen_helper_tlbp();
1.1.1.5 root 5906: break;
5907: case OPC_TLBR:
5908: opn = "tlbr";
1.1.1.8 root 5909: if (!env->tlb->helper_tlbr)
1.1.1.6 root 5910: goto die;
1.1.1.7 root 5911: gen_helper_tlbr();
1.1.1.5 root 5912: break;
5913: case OPC_ERET:
5914: opn = "eret";
1.1.1.6 root 5915: check_insn(env, ctx, ISA_MIPS2);
1.1.1.7 root 5916: gen_helper_eret();
1.1.1.5 root 5917: ctx->bstate = BS_EXCP;
5918: break;
5919: case OPC_DERET:
5920: opn = "deret";
1.1.1.6 root 5921: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 5922: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1.1.1.6 root 5923: MIPS_INVAL(opn);
1.1.1.5 root 5924: generate_exception(ctx, EXCP_RI);
5925: } else {
1.1.1.7 root 5926: gen_helper_deret();
1.1.1.5 root 5927: ctx->bstate = BS_EXCP;
5928: }
5929: break;
5930: case OPC_WAIT:
5931: opn = "wait";
1.1.1.6 root 5932: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
1.1.1.5 root 5933: /* If we get an exception, we want to restart at next instruction */
5934: ctx->pc += 4;
5935: save_cpu_state(ctx, 1);
5936: ctx->pc -= 4;
1.1.1.7 root 5937: gen_helper_wait();
1.1.1.5 root 5938: ctx->bstate = BS_EXCP;
5939: break;
5940: default:
1.1.1.6 root 5941: die:
5942: MIPS_INVAL(opn);
1.1.1.5 root 5943: generate_exception(ctx, EXCP_RI);
5944: return;
5945: }
5946: MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5947: }
1.1.1.7 root 5948: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 5949:
5950: /* CP1 Branches (before delay slot) */
1.1.1.6 root 5951: static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5952: int32_t cc, int32_t offset)
1.1.1.5 root 5953: {
5954: target_ulong btarget;
1.1.1.6 root 5955: const char *opn = "cp1 cond branch";
1.1.1.7 root 5956: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.6 root 5957:
5958: if (cc != 0)
5959: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
1.1.1.5 root 5960:
5961: btarget = ctx->pc + 4 + offset;
5962:
5963: switch (op) {
5964: case OPC_BC1F:
1.1.1.8 root 5965: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5966: tcg_gen_not_i32(t0, t0);
5967: tcg_gen_andi_i32(t0, t0, 1);
5968: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 5969: opn = "bc1f";
1.1.1.5 root 5970: goto not_likely;
5971: case OPC_BC1FL:
1.1.1.8 root 5972: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5973: tcg_gen_not_i32(t0, t0);
5974: tcg_gen_andi_i32(t0, t0, 1);
5975: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 5976: opn = "bc1fl";
1.1.1.5 root 5977: goto likely;
5978: case OPC_BC1T:
1.1.1.8 root 5979: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5980: tcg_gen_andi_i32(t0, t0, 1);
5981: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 5982: opn = "bc1t";
5983: goto not_likely;
1.1.1.5 root 5984: case OPC_BC1TL:
1.1.1.8 root 5985: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5986: tcg_gen_andi_i32(t0, t0, 1);
5987: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.6 root 5988: opn = "bc1tl";
1.1.1.5 root 5989: likely:
5990: ctx->hflags |= MIPS_HFLAG_BL;
1.1.1.6 root 5991: break;
5992: case OPC_BC1FANY2:
1.1.1.7 root 5993: {
1.1.1.8 root 5994: TCGv_i32 t1 = tcg_temp_new_i32();
5995: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5996: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
1.1.1.12! root 5997: tcg_gen_nor_i32(t0, t0, t1);
1.1.1.8 root 5998: tcg_temp_free_i32(t1);
5999: tcg_gen_andi_i32(t0, t0, 1);
6000: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6001: }
1.1.1.6 root 6002: opn = "bc1any2f";
6003: goto not_likely;
6004: case OPC_BC1TANY2:
1.1.1.7 root 6005: {
1.1.1.8 root 6006: TCGv_i32 t1 = tcg_temp_new_i32();
6007: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6008: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6009: tcg_gen_or_i32(t0, t0, t1);
6010: tcg_temp_free_i32(t1);
6011: tcg_gen_andi_i32(t0, t0, 1);
6012: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6013: }
1.1.1.6 root 6014: opn = "bc1any2t";
6015: goto not_likely;
6016: case OPC_BC1FANY4:
1.1.1.7 root 6017: {
1.1.1.8 root 6018: TCGv_i32 t1 = tcg_temp_new_i32();
6019: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6020: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6021: tcg_gen_or_i32(t0, t0, t1);
6022: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6023: tcg_gen_or_i32(t0, t0, t1);
6024: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
1.1.1.12! root 6025: tcg_gen_nor_i32(t0, t0, t1);
1.1.1.8 root 6026: tcg_temp_free_i32(t1);
6027: tcg_gen_andi_i32(t0, t0, 1);
6028: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6029: }
1.1.1.6 root 6030: opn = "bc1any4f";
6031: goto not_likely;
6032: case OPC_BC1TANY4:
1.1.1.7 root 6033: {
1.1.1.8 root 6034: TCGv_i32 t1 = tcg_temp_new_i32();
6035: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6036: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6037: tcg_gen_or_i32(t0, t0, t1);
6038: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6039: tcg_gen_or_i32(t0, t0, t1);
6040: tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6041: tcg_gen_or_i32(t0, t0, t1);
6042: tcg_temp_free_i32(t1);
6043: tcg_gen_andi_i32(t0, t0, 1);
6044: tcg_gen_extu_i32_tl(bcond, t0);
1.1.1.7 root 6045: }
1.1.1.6 root 6046: opn = "bc1any4t";
6047: not_likely:
6048: ctx->hflags |= MIPS_HFLAG_BC;
1.1.1.5 root 6049: break;
1.1.1.6 root 6050: default:
6051: MIPS_INVAL(opn);
6052: generate_exception (ctx, EXCP_RI);
1.1.1.7 root 6053: goto out;
1.1.1.5 root 6054: }
1.1.1.6 root 6055: MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
1.1.1.5 root 6056: ctx->hflags, btarget);
6057: ctx->btarget = btarget;
1.1.1.7 root 6058:
6059: out:
6060: tcg_temp_free_i32(t0);
1.1.1.5 root 6061: }
6062:
6063: /* Coprocessor 1 (FPU) */
1.1.1.6 root 6064:
6065: #define FOP(func, fmt) (((fmt) << 21) | (func))
6066:
1.1.1.12! root 6067: enum fopcode {
! 6068: OPC_ADD_S = FOP(0, FMT_S),
! 6069: OPC_SUB_S = FOP(1, FMT_S),
! 6070: OPC_MUL_S = FOP(2, FMT_S),
! 6071: OPC_DIV_S = FOP(3, FMT_S),
! 6072: OPC_SQRT_S = FOP(4, FMT_S),
! 6073: OPC_ABS_S = FOP(5, FMT_S),
! 6074: OPC_MOV_S = FOP(6, FMT_S),
! 6075: OPC_NEG_S = FOP(7, FMT_S),
! 6076: OPC_ROUND_L_S = FOP(8, FMT_S),
! 6077: OPC_TRUNC_L_S = FOP(9, FMT_S),
! 6078: OPC_CEIL_L_S = FOP(10, FMT_S),
! 6079: OPC_FLOOR_L_S = FOP(11, FMT_S),
! 6080: OPC_ROUND_W_S = FOP(12, FMT_S),
! 6081: OPC_TRUNC_W_S = FOP(13, FMT_S),
! 6082: OPC_CEIL_W_S = FOP(14, FMT_S),
! 6083: OPC_FLOOR_W_S = FOP(15, FMT_S),
! 6084: OPC_MOVCF_S = FOP(17, FMT_S),
! 6085: OPC_MOVZ_S = FOP(18, FMT_S),
! 6086: OPC_MOVN_S = FOP(19, FMT_S),
! 6087: OPC_RECIP_S = FOP(21, FMT_S),
! 6088: OPC_RSQRT_S = FOP(22, FMT_S),
! 6089: OPC_RECIP2_S = FOP(28, FMT_S),
! 6090: OPC_RECIP1_S = FOP(29, FMT_S),
! 6091: OPC_RSQRT1_S = FOP(30, FMT_S),
! 6092: OPC_RSQRT2_S = FOP(31, FMT_S),
! 6093: OPC_CVT_D_S = FOP(33, FMT_S),
! 6094: OPC_CVT_W_S = FOP(36, FMT_S),
! 6095: OPC_CVT_L_S = FOP(37, FMT_S),
! 6096: OPC_CVT_PS_S = FOP(38, FMT_S),
! 6097: OPC_CMP_F_S = FOP (48, FMT_S),
! 6098: OPC_CMP_UN_S = FOP (49, FMT_S),
! 6099: OPC_CMP_EQ_S = FOP (50, FMT_S),
! 6100: OPC_CMP_UEQ_S = FOP (51, FMT_S),
! 6101: OPC_CMP_OLT_S = FOP (52, FMT_S),
! 6102: OPC_CMP_ULT_S = FOP (53, FMT_S),
! 6103: OPC_CMP_OLE_S = FOP (54, FMT_S),
! 6104: OPC_CMP_ULE_S = FOP (55, FMT_S),
! 6105: OPC_CMP_SF_S = FOP (56, FMT_S),
! 6106: OPC_CMP_NGLE_S = FOP (57, FMT_S),
! 6107: OPC_CMP_SEQ_S = FOP (58, FMT_S),
! 6108: OPC_CMP_NGL_S = FOP (59, FMT_S),
! 6109: OPC_CMP_LT_S = FOP (60, FMT_S),
! 6110: OPC_CMP_NGE_S = FOP (61, FMT_S),
! 6111: OPC_CMP_LE_S = FOP (62, FMT_S),
! 6112: OPC_CMP_NGT_S = FOP (63, FMT_S),
! 6113:
! 6114: OPC_ADD_D = FOP(0, FMT_D),
! 6115: OPC_SUB_D = FOP(1, FMT_D),
! 6116: OPC_MUL_D = FOP(2, FMT_D),
! 6117: OPC_DIV_D = FOP(3, FMT_D),
! 6118: OPC_SQRT_D = FOP(4, FMT_D),
! 6119: OPC_ABS_D = FOP(5, FMT_D),
! 6120: OPC_MOV_D = FOP(6, FMT_D),
! 6121: OPC_NEG_D = FOP(7, FMT_D),
! 6122: OPC_ROUND_L_D = FOP(8, FMT_D),
! 6123: OPC_TRUNC_L_D = FOP(9, FMT_D),
! 6124: OPC_CEIL_L_D = FOP(10, FMT_D),
! 6125: OPC_FLOOR_L_D = FOP(11, FMT_D),
! 6126: OPC_ROUND_W_D = FOP(12, FMT_D),
! 6127: OPC_TRUNC_W_D = FOP(13, FMT_D),
! 6128: OPC_CEIL_W_D = FOP(14, FMT_D),
! 6129: OPC_FLOOR_W_D = FOP(15, FMT_D),
! 6130: OPC_MOVCF_D = FOP(17, FMT_D),
! 6131: OPC_MOVZ_D = FOP(18, FMT_D),
! 6132: OPC_MOVN_D = FOP(19, FMT_D),
! 6133: OPC_RECIP_D = FOP(21, FMT_D),
! 6134: OPC_RSQRT_D = FOP(22, FMT_D),
! 6135: OPC_RECIP2_D = FOP(28, FMT_D),
! 6136: OPC_RECIP1_D = FOP(29, FMT_D),
! 6137: OPC_RSQRT1_D = FOP(30, FMT_D),
! 6138: OPC_RSQRT2_D = FOP(31, FMT_D),
! 6139: OPC_CVT_S_D = FOP(32, FMT_D),
! 6140: OPC_CVT_W_D = FOP(36, FMT_D),
! 6141: OPC_CVT_L_D = FOP(37, FMT_D),
! 6142: OPC_CMP_F_D = FOP (48, FMT_D),
! 6143: OPC_CMP_UN_D = FOP (49, FMT_D),
! 6144: OPC_CMP_EQ_D = FOP (50, FMT_D),
! 6145: OPC_CMP_UEQ_D = FOP (51, FMT_D),
! 6146: OPC_CMP_OLT_D = FOP (52, FMT_D),
! 6147: OPC_CMP_ULT_D = FOP (53, FMT_D),
! 6148: OPC_CMP_OLE_D = FOP (54, FMT_D),
! 6149: OPC_CMP_ULE_D = FOP (55, FMT_D),
! 6150: OPC_CMP_SF_D = FOP (56, FMT_D),
! 6151: OPC_CMP_NGLE_D = FOP (57, FMT_D),
! 6152: OPC_CMP_SEQ_D = FOP (58, FMT_D),
! 6153: OPC_CMP_NGL_D = FOP (59, FMT_D),
! 6154: OPC_CMP_LT_D = FOP (60, FMT_D),
! 6155: OPC_CMP_NGE_D = FOP (61, FMT_D),
! 6156: OPC_CMP_LE_D = FOP (62, FMT_D),
! 6157: OPC_CMP_NGT_D = FOP (63, FMT_D),
! 6158:
! 6159: OPC_CVT_S_W = FOP(32, FMT_W),
! 6160: OPC_CVT_D_W = FOP(33, FMT_W),
! 6161: OPC_CVT_S_L = FOP(32, FMT_L),
! 6162: OPC_CVT_D_L = FOP(33, FMT_L),
! 6163: OPC_CVT_PS_PW = FOP(38, FMT_W),
! 6164:
! 6165: OPC_ADD_PS = FOP(0, FMT_PS),
! 6166: OPC_SUB_PS = FOP(1, FMT_PS),
! 6167: OPC_MUL_PS = FOP(2, FMT_PS),
! 6168: OPC_DIV_PS = FOP(3, FMT_PS),
! 6169: OPC_ABS_PS = FOP(5, FMT_PS),
! 6170: OPC_MOV_PS = FOP(6, FMT_PS),
! 6171: OPC_NEG_PS = FOP(7, FMT_PS),
! 6172: OPC_MOVCF_PS = FOP(17, FMT_PS),
! 6173: OPC_MOVZ_PS = FOP(18, FMT_PS),
! 6174: OPC_MOVN_PS = FOP(19, FMT_PS),
! 6175: OPC_ADDR_PS = FOP(24, FMT_PS),
! 6176: OPC_MULR_PS = FOP(26, FMT_PS),
! 6177: OPC_RECIP2_PS = FOP(28, FMT_PS),
! 6178: OPC_RECIP1_PS = FOP(29, FMT_PS),
! 6179: OPC_RSQRT1_PS = FOP(30, FMT_PS),
! 6180: OPC_RSQRT2_PS = FOP(31, FMT_PS),
! 6181:
! 6182: OPC_CVT_S_PU = FOP(32, FMT_PS),
! 6183: OPC_CVT_PW_PS = FOP(36, FMT_PS),
! 6184: OPC_CVT_S_PL = FOP(40, FMT_PS),
! 6185: OPC_PLL_PS = FOP(44, FMT_PS),
! 6186: OPC_PLU_PS = FOP(45, FMT_PS),
! 6187: OPC_PUL_PS = FOP(46, FMT_PS),
! 6188: OPC_PUU_PS = FOP(47, FMT_PS),
! 6189: OPC_CMP_F_PS = FOP (48, FMT_PS),
! 6190: OPC_CMP_UN_PS = FOP (49, FMT_PS),
! 6191: OPC_CMP_EQ_PS = FOP (50, FMT_PS),
! 6192: OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
! 6193: OPC_CMP_OLT_PS = FOP (52, FMT_PS),
! 6194: OPC_CMP_ULT_PS = FOP (53, FMT_PS),
! 6195: OPC_CMP_OLE_PS = FOP (54, FMT_PS),
! 6196: OPC_CMP_ULE_PS = FOP (55, FMT_PS),
! 6197: OPC_CMP_SF_PS = FOP (56, FMT_PS),
! 6198: OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
! 6199: OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
! 6200: OPC_CMP_NGL_PS = FOP (59, FMT_PS),
! 6201: OPC_CMP_LT_PS = FOP (60, FMT_PS),
! 6202: OPC_CMP_NGE_PS = FOP (61, FMT_PS),
! 6203: OPC_CMP_LE_PS = FOP (62, FMT_PS),
! 6204: OPC_CMP_NGT_PS = FOP (63, FMT_PS),
! 6205: };
! 6206:
1.1.1.5 root 6207: static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6208: {
1.1.1.6 root 6209: const char *opn = "cp1 move";
1.1.1.8 root 6210: TCGv t0 = tcg_temp_new();
1.1.1.5 root 6211:
6212: switch (opc) {
6213: case OPC_MFC1:
1.1.1.7 root 6214: {
6215: TCGv_i32 fp0 = tcg_temp_new_i32();
6216:
6217: gen_load_fpr32(fp0, fs);
6218: tcg_gen_ext_i32_tl(t0, fp0);
6219: tcg_temp_free_i32(fp0);
6220: }
6221: gen_store_gpr(t0, rt);
1.1.1.5 root 6222: opn = "mfc1";
6223: break;
6224: case OPC_MTC1:
1.1.1.7 root 6225: gen_load_gpr(t0, rt);
6226: {
6227: TCGv_i32 fp0 = tcg_temp_new_i32();
6228:
6229: tcg_gen_trunc_tl_i32(fp0, t0);
6230: gen_store_fpr32(fp0, fs);
6231: tcg_temp_free_i32(fp0);
6232: }
1.1.1.5 root 6233: opn = "mtc1";
6234: break;
6235: case OPC_CFC1:
1.1.1.7 root 6236: gen_helper_1i(cfc1, t0, fs);
6237: gen_store_gpr(t0, rt);
1.1.1.5 root 6238: opn = "cfc1";
6239: break;
6240: case OPC_CTC1:
1.1.1.7 root 6241: gen_load_gpr(t0, rt);
6242: gen_helper_1i(ctc1, t0, fs);
1.1.1.5 root 6243: opn = "ctc1";
6244: break;
1.1.1.8 root 6245: #if defined(TARGET_MIPS64)
1.1.1.5 root 6246: case OPC_DMFC1:
1.1.1.8 root 6247: gen_load_fpr64(ctx, t0, fs);
1.1.1.7 root 6248: gen_store_gpr(t0, rt);
1.1.1.6 root 6249: opn = "dmfc1";
6250: break;
1.1.1.5 root 6251: case OPC_DMTC1:
1.1.1.7 root 6252: gen_load_gpr(t0, rt);
1.1.1.8 root 6253: gen_store_fpr64(ctx, t0, fs);
1.1.1.6 root 6254: opn = "dmtc1";
6255: break;
1.1.1.8 root 6256: #endif
1.1.1.6 root 6257: case OPC_MFHC1:
1.1.1.7 root 6258: {
6259: TCGv_i32 fp0 = tcg_temp_new_i32();
6260:
6261: gen_load_fpr32h(fp0, fs);
6262: tcg_gen_ext_i32_tl(t0, fp0);
6263: tcg_temp_free_i32(fp0);
6264: }
6265: gen_store_gpr(t0, rt);
1.1.1.6 root 6266: opn = "mfhc1";
6267: break;
6268: case OPC_MTHC1:
1.1.1.7 root 6269: gen_load_gpr(t0, rt);
6270: {
6271: TCGv_i32 fp0 = tcg_temp_new_i32();
6272:
6273: tcg_gen_trunc_tl_i32(fp0, t0);
6274: gen_store_fpr32h(fp0, fs);
6275: tcg_temp_free_i32(fp0);
6276: }
1.1.1.6 root 6277: opn = "mthc1";
6278: break;
1.1.1.5 root 6279: default:
1.1.1.6 root 6280: MIPS_INVAL(opn);
6281: generate_exception (ctx, EXCP_RI);
1.1.1.7 root 6282: goto out;
1.1.1.4 root 6283: }
6284: MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
1.1.1.7 root 6285:
6286: out:
6287: tcg_temp_free(t0);
1.1.1.4 root 6288: }
6289:
1.1.1.6 root 6290: static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6291: {
1.1.1.8 root 6292: int l1;
1.1.1.7 root 6293: TCGCond cond;
1.1.1.8 root 6294: TCGv_i32 t0;
6295:
6296: if (rd == 0) {
6297: /* Treat as NOP. */
6298: return;
6299: }
1.1.1.7 root 6300:
6301: if (tf)
6302: cond = TCG_COND_EQ;
6303: else
6304: cond = TCG_COND_NE;
6305:
1.1.1.8 root 6306: l1 = gen_new_label();
6307: t0 = tcg_temp_new_i32();
6308: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6309: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6310: tcg_temp_free_i32(t0);
6311: if (rs == 0) {
6312: tcg_gen_movi_tl(cpu_gpr[rd], 0);
6313: } else {
6314: tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6315: }
1.1.1.7 root 6316: gen_set_label(l1);
6317: }
6318:
6319: static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6320: {
6321: int cond;
1.1.1.8 root 6322: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 6323: int l1 = gen_new_label();
6324:
6325: if (tf)
6326: cond = TCG_COND_EQ;
6327: else
6328: cond = TCG_COND_NE;
6329:
1.1.1.8 root 6330: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6331: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6332: gen_load_fpr32(t0, fs);
6333: gen_store_fpr32(t0, fd);
1.1.1.7 root 6334: gen_set_label(l1);
1.1.1.8 root 6335: tcg_temp_free_i32(t0);
1.1.1.7 root 6336: }
6337:
6338: static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6339: {
6340: int cond;
1.1.1.8 root 6341: TCGv_i32 t0 = tcg_temp_new_i32();
6342: TCGv_i64 fp0;
1.1.1.7 root 6343: int l1 = gen_new_label();
6344:
6345: if (tf)
6346: cond = TCG_COND_EQ;
6347: else
6348: cond = TCG_COND_NE;
6349:
1.1.1.8 root 6350: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6351: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6352: tcg_temp_free_i32(t0);
6353: fp0 = tcg_temp_new_i64();
1.1.1.7 root 6354: gen_load_fpr64(ctx, fp0, fs);
6355: gen_store_fpr64(ctx, fp0, fd);
6356: tcg_temp_free_i64(fp0);
1.1.1.8 root 6357: gen_set_label(l1);
1.1.1.7 root 6358: }
6359:
6360: static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6361: {
6362: int cond;
1.1.1.8 root 6363: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.7 root 6364: int l1 = gen_new_label();
6365: int l2 = gen_new_label();
1.1.1.4 root 6366:
1.1.1.7 root 6367: if (tf)
6368: cond = TCG_COND_EQ;
1.1.1.6 root 6369: else
1.1.1.7 root 6370: cond = TCG_COND_NE;
6371:
1.1.1.8 root 6372: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6373: tcg_gen_brcondi_i32(cond, t0, 0, l1);
6374: gen_load_fpr32(t0, fs);
6375: gen_store_fpr32(t0, fd);
1.1.1.7 root 6376: gen_set_label(l1);
6377:
1.1.1.8 root 6378: tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
6379: tcg_gen_brcondi_i32(cond, t0, 0, l2);
6380: gen_load_fpr32h(t0, fs);
6381: gen_store_fpr32h(t0, fd);
6382: tcg_temp_free_i32(t0);
1.1.1.7 root 6383: gen_set_label(l2);
1.1.1.6 root 6384: }
6385:
1.1.1.4 root 6386:
1.1.1.12! root 6387: static void gen_farith (DisasContext *ctx, enum fopcode op1,
1.1.1.6 root 6388: int ft, int fs, int fd, int cc)
1.1.1.4 root 6389: {
1.1.1.6 root 6390: const char *opn = "farith";
1.1.1.4 root 6391: const char *condnames[] = {
6392: "c.f",
6393: "c.un",
6394: "c.eq",
6395: "c.ueq",
6396: "c.olt",
6397: "c.ult",
6398: "c.ole",
6399: "c.ule",
6400: "c.sf",
6401: "c.ngle",
6402: "c.seq",
6403: "c.ngl",
6404: "c.lt",
6405: "c.nge",
6406: "c.le",
6407: "c.ngt",
6408: };
1.1.1.6 root 6409: const char *condnames_abs[] = {
6410: "cabs.f",
6411: "cabs.un",
6412: "cabs.eq",
6413: "cabs.ueq",
6414: "cabs.olt",
6415: "cabs.ult",
6416: "cabs.ole",
6417: "cabs.ule",
6418: "cabs.sf",
6419: "cabs.ngle",
6420: "cabs.seq",
6421: "cabs.ngl",
6422: "cabs.lt",
6423: "cabs.nge",
6424: "cabs.le",
6425: "cabs.ngt",
6426: };
6427: enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
1.1.1.5 root 6428: uint32_t func = ctx->opcode & 0x3f;
6429:
1.1.1.12! root 6430: switch (op1) {
! 6431: case OPC_ADD_S:
1.1.1.7 root 6432: {
6433: TCGv_i32 fp0 = tcg_temp_new_i32();
6434: TCGv_i32 fp1 = tcg_temp_new_i32();
6435:
6436: gen_load_fpr32(fp0, fs);
6437: gen_load_fpr32(fp1, ft);
6438: gen_helper_float_add_s(fp0, fp0, fp1);
6439: tcg_temp_free_i32(fp1);
6440: gen_store_fpr32(fp0, fd);
6441: tcg_temp_free_i32(fp0);
6442: }
1.1.1.6 root 6443: opn = "add.s";
6444: optype = BINOP;
6445: break;
1.1.1.12! root 6446: case OPC_SUB_S:
1.1.1.7 root 6447: {
6448: TCGv_i32 fp0 = tcg_temp_new_i32();
6449: TCGv_i32 fp1 = tcg_temp_new_i32();
6450:
6451: gen_load_fpr32(fp0, fs);
6452: gen_load_fpr32(fp1, ft);
6453: gen_helper_float_sub_s(fp0, fp0, fp1);
6454: tcg_temp_free_i32(fp1);
6455: gen_store_fpr32(fp0, fd);
6456: tcg_temp_free_i32(fp0);
6457: }
1.1.1.6 root 6458: opn = "sub.s";
6459: optype = BINOP;
6460: break;
1.1.1.12! root 6461: case OPC_MUL_S:
1.1.1.7 root 6462: {
6463: TCGv_i32 fp0 = tcg_temp_new_i32();
6464: TCGv_i32 fp1 = tcg_temp_new_i32();
6465:
6466: gen_load_fpr32(fp0, fs);
6467: gen_load_fpr32(fp1, ft);
6468: gen_helper_float_mul_s(fp0, fp0, fp1);
6469: tcg_temp_free_i32(fp1);
6470: gen_store_fpr32(fp0, fd);
6471: tcg_temp_free_i32(fp0);
6472: }
1.1.1.6 root 6473: opn = "mul.s";
6474: optype = BINOP;
6475: break;
1.1.1.12! root 6476: case OPC_DIV_S:
1.1.1.7 root 6477: {
6478: TCGv_i32 fp0 = tcg_temp_new_i32();
6479: TCGv_i32 fp1 = tcg_temp_new_i32();
6480:
6481: gen_load_fpr32(fp0, fs);
6482: gen_load_fpr32(fp1, ft);
6483: gen_helper_float_div_s(fp0, fp0, fp1);
6484: tcg_temp_free_i32(fp1);
6485: gen_store_fpr32(fp0, fd);
6486: tcg_temp_free_i32(fp0);
6487: }
1.1.1.6 root 6488: opn = "div.s";
6489: optype = BINOP;
6490: break;
1.1.1.12! root 6491: case OPC_SQRT_S:
1.1.1.7 root 6492: {
6493: TCGv_i32 fp0 = tcg_temp_new_i32();
6494:
6495: gen_load_fpr32(fp0, fs);
6496: gen_helper_float_sqrt_s(fp0, fp0);
6497: gen_store_fpr32(fp0, fd);
6498: tcg_temp_free_i32(fp0);
6499: }
1.1.1.6 root 6500: opn = "sqrt.s";
6501: break;
1.1.1.12! root 6502: case OPC_ABS_S:
1.1.1.7 root 6503: {
6504: TCGv_i32 fp0 = tcg_temp_new_i32();
6505:
6506: gen_load_fpr32(fp0, fs);
6507: gen_helper_float_abs_s(fp0, fp0);
6508: gen_store_fpr32(fp0, fd);
6509: tcg_temp_free_i32(fp0);
6510: }
1.1.1.6 root 6511: opn = "abs.s";
6512: break;
1.1.1.12! root 6513: case OPC_MOV_S:
1.1.1.7 root 6514: {
6515: TCGv_i32 fp0 = tcg_temp_new_i32();
6516:
6517: gen_load_fpr32(fp0, fs);
6518: gen_store_fpr32(fp0, fd);
6519: tcg_temp_free_i32(fp0);
6520: }
1.1.1.6 root 6521: opn = "mov.s";
6522: break;
1.1.1.12! root 6523: case OPC_NEG_S:
1.1.1.7 root 6524: {
6525: TCGv_i32 fp0 = tcg_temp_new_i32();
6526:
6527: gen_load_fpr32(fp0, fs);
6528: gen_helper_float_chs_s(fp0, fp0);
6529: gen_store_fpr32(fp0, fd);
6530: tcg_temp_free_i32(fp0);
6531: }
1.1.1.6 root 6532: opn = "neg.s";
6533: break;
1.1.1.12! root 6534: case OPC_ROUND_L_S:
1.1.1.6 root 6535: check_cp1_64bitmode(ctx);
1.1.1.7 root 6536: {
6537: TCGv_i32 fp32 = tcg_temp_new_i32();
6538: TCGv_i64 fp64 = tcg_temp_new_i64();
6539:
6540: gen_load_fpr32(fp32, fs);
6541: gen_helper_float_roundl_s(fp64, fp32);
6542: tcg_temp_free_i32(fp32);
6543: gen_store_fpr64(ctx, fp64, fd);
6544: tcg_temp_free_i64(fp64);
6545: }
1.1.1.6 root 6546: opn = "round.l.s";
6547: break;
1.1.1.12! root 6548: case OPC_TRUNC_L_S:
1.1.1.6 root 6549: check_cp1_64bitmode(ctx);
1.1.1.7 root 6550: {
6551: TCGv_i32 fp32 = tcg_temp_new_i32();
6552: TCGv_i64 fp64 = tcg_temp_new_i64();
6553:
6554: gen_load_fpr32(fp32, fs);
6555: gen_helper_float_truncl_s(fp64, fp32);
6556: tcg_temp_free_i32(fp32);
6557: gen_store_fpr64(ctx, fp64, fd);
6558: tcg_temp_free_i64(fp64);
6559: }
1.1.1.6 root 6560: opn = "trunc.l.s";
6561: break;
1.1.1.12! root 6562: case OPC_CEIL_L_S:
1.1.1.6 root 6563: check_cp1_64bitmode(ctx);
1.1.1.7 root 6564: {
6565: TCGv_i32 fp32 = tcg_temp_new_i32();
6566: TCGv_i64 fp64 = tcg_temp_new_i64();
6567:
6568: gen_load_fpr32(fp32, fs);
6569: gen_helper_float_ceill_s(fp64, fp32);
6570: tcg_temp_free_i32(fp32);
6571: gen_store_fpr64(ctx, fp64, fd);
6572: tcg_temp_free_i64(fp64);
6573: }
1.1.1.6 root 6574: opn = "ceil.l.s";
6575: break;
1.1.1.12! root 6576: case OPC_FLOOR_L_S:
1.1.1.6 root 6577: check_cp1_64bitmode(ctx);
1.1.1.7 root 6578: {
6579: TCGv_i32 fp32 = tcg_temp_new_i32();
6580: TCGv_i64 fp64 = tcg_temp_new_i64();
6581:
6582: gen_load_fpr32(fp32, fs);
6583: gen_helper_float_floorl_s(fp64, fp32);
6584: tcg_temp_free_i32(fp32);
6585: gen_store_fpr64(ctx, fp64, fd);
6586: tcg_temp_free_i64(fp64);
6587: }
1.1.1.6 root 6588: opn = "floor.l.s";
6589: break;
1.1.1.12! root 6590: case OPC_ROUND_W_S:
1.1.1.7 root 6591: {
6592: TCGv_i32 fp0 = tcg_temp_new_i32();
6593:
6594: gen_load_fpr32(fp0, fs);
6595: gen_helper_float_roundw_s(fp0, fp0);
6596: gen_store_fpr32(fp0, fd);
6597: tcg_temp_free_i32(fp0);
6598: }
1.1.1.6 root 6599: opn = "round.w.s";
6600: break;
1.1.1.12! root 6601: case OPC_TRUNC_W_S:
1.1.1.7 root 6602: {
6603: TCGv_i32 fp0 = tcg_temp_new_i32();
6604:
6605: gen_load_fpr32(fp0, fs);
6606: gen_helper_float_truncw_s(fp0, fp0);
6607: gen_store_fpr32(fp0, fd);
6608: tcg_temp_free_i32(fp0);
6609: }
1.1.1.6 root 6610: opn = "trunc.w.s";
6611: break;
1.1.1.12! root 6612: case OPC_CEIL_W_S:
1.1.1.7 root 6613: {
6614: TCGv_i32 fp0 = tcg_temp_new_i32();
6615:
6616: gen_load_fpr32(fp0, fs);
6617: gen_helper_float_ceilw_s(fp0, fp0);
6618: gen_store_fpr32(fp0, fd);
6619: tcg_temp_free_i32(fp0);
6620: }
1.1.1.6 root 6621: opn = "ceil.w.s";
6622: break;
1.1.1.12! root 6623: case OPC_FLOOR_W_S:
1.1.1.7 root 6624: {
6625: TCGv_i32 fp0 = tcg_temp_new_i32();
6626:
6627: gen_load_fpr32(fp0, fs);
6628: gen_helper_float_floorw_s(fp0, fp0);
6629: gen_store_fpr32(fp0, fd);
6630: tcg_temp_free_i32(fp0);
6631: }
1.1.1.6 root 6632: opn = "floor.w.s";
6633: break;
1.1.1.12! root 6634: case OPC_MOVCF_S:
1.1.1.7 root 6635: gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 6636: opn = "movcf.s";
6637: break;
1.1.1.12! root 6638: case OPC_MOVZ_S:
1.1.1.7 root 6639: {
6640: int l1 = gen_new_label();
1.1.1.8 root 6641: TCGv_i32 fp0;
1.1.1.7 root 6642:
1.1.1.8 root 6643: if (ft != 0) {
6644: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6645: }
6646: fp0 = tcg_temp_new_i32();
1.1.1.7 root 6647: gen_load_fpr32(fp0, fs);
6648: gen_store_fpr32(fp0, fd);
6649: tcg_temp_free_i32(fp0);
6650: gen_set_label(l1);
6651: }
1.1.1.6 root 6652: opn = "movz.s";
6653: break;
1.1.1.12! root 6654: case OPC_MOVN_S:
1.1.1.7 root 6655: {
6656: int l1 = gen_new_label();
1.1.1.8 root 6657: TCGv_i32 fp0;
1.1.1.7 root 6658:
1.1.1.8 root 6659: if (ft != 0) {
6660: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6661: fp0 = tcg_temp_new_i32();
6662: gen_load_fpr32(fp0, fs);
6663: gen_store_fpr32(fp0, fd);
6664: tcg_temp_free_i32(fp0);
6665: gen_set_label(l1);
6666: }
1.1.1.7 root 6667: }
1.1.1.6 root 6668: opn = "movn.s";
6669: break;
1.1.1.12! root 6670: case OPC_RECIP_S:
1.1.1.6 root 6671: check_cop1x(ctx);
1.1.1.7 root 6672: {
6673: TCGv_i32 fp0 = tcg_temp_new_i32();
6674:
6675: gen_load_fpr32(fp0, fs);
6676: gen_helper_float_recip_s(fp0, fp0);
6677: gen_store_fpr32(fp0, fd);
6678: tcg_temp_free_i32(fp0);
6679: }
1.1.1.6 root 6680: opn = "recip.s";
6681: break;
1.1.1.12! root 6682: case OPC_RSQRT_S:
1.1.1.6 root 6683: check_cop1x(ctx);
1.1.1.7 root 6684: {
6685: TCGv_i32 fp0 = tcg_temp_new_i32();
6686:
6687: gen_load_fpr32(fp0, fs);
6688: gen_helper_float_rsqrt_s(fp0, fp0);
6689: gen_store_fpr32(fp0, fd);
6690: tcg_temp_free_i32(fp0);
6691: }
1.1.1.6 root 6692: opn = "rsqrt.s";
6693: break;
1.1.1.12! root 6694: case OPC_RECIP2_S:
1.1.1.6 root 6695: check_cp1_64bitmode(ctx);
1.1.1.7 root 6696: {
6697: TCGv_i32 fp0 = tcg_temp_new_i32();
6698: TCGv_i32 fp1 = tcg_temp_new_i32();
6699:
6700: gen_load_fpr32(fp0, fs);
6701: gen_load_fpr32(fp1, fd);
6702: gen_helper_float_recip2_s(fp0, fp0, fp1);
6703: tcg_temp_free_i32(fp1);
6704: gen_store_fpr32(fp0, fd);
6705: tcg_temp_free_i32(fp0);
6706: }
1.1.1.6 root 6707: opn = "recip2.s";
6708: break;
1.1.1.12! root 6709: case OPC_RECIP1_S:
1.1.1.6 root 6710: check_cp1_64bitmode(ctx);
1.1.1.7 root 6711: {
6712: TCGv_i32 fp0 = tcg_temp_new_i32();
6713:
6714: gen_load_fpr32(fp0, fs);
6715: gen_helper_float_recip1_s(fp0, fp0);
6716: gen_store_fpr32(fp0, fd);
6717: tcg_temp_free_i32(fp0);
6718: }
1.1.1.6 root 6719: opn = "recip1.s";
6720: break;
1.1.1.12! root 6721: case OPC_RSQRT1_S:
1.1.1.6 root 6722: check_cp1_64bitmode(ctx);
1.1.1.7 root 6723: {
6724: TCGv_i32 fp0 = tcg_temp_new_i32();
6725:
6726: gen_load_fpr32(fp0, fs);
6727: gen_helper_float_rsqrt1_s(fp0, fp0);
6728: gen_store_fpr32(fp0, fd);
6729: tcg_temp_free_i32(fp0);
6730: }
1.1.1.6 root 6731: opn = "rsqrt1.s";
6732: break;
1.1.1.12! root 6733: case OPC_RSQRT2_S:
1.1.1.6 root 6734: check_cp1_64bitmode(ctx);
1.1.1.7 root 6735: {
6736: TCGv_i32 fp0 = tcg_temp_new_i32();
6737: TCGv_i32 fp1 = tcg_temp_new_i32();
6738:
6739: gen_load_fpr32(fp0, fs);
6740: gen_load_fpr32(fp1, ft);
6741: gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6742: tcg_temp_free_i32(fp1);
6743: gen_store_fpr32(fp0, fd);
6744: tcg_temp_free_i32(fp0);
6745: }
1.1.1.6 root 6746: opn = "rsqrt2.s";
6747: break;
1.1.1.12! root 6748: case OPC_CVT_D_S:
1.1.1.6 root 6749: check_cp1_registers(ctx, fd);
1.1.1.7 root 6750: {
6751: TCGv_i32 fp32 = tcg_temp_new_i32();
6752: TCGv_i64 fp64 = tcg_temp_new_i64();
6753:
6754: gen_load_fpr32(fp32, fs);
6755: gen_helper_float_cvtd_s(fp64, fp32);
6756: tcg_temp_free_i32(fp32);
6757: gen_store_fpr64(ctx, fp64, fd);
6758: tcg_temp_free_i64(fp64);
6759: }
1.1.1.6 root 6760: opn = "cvt.d.s";
6761: break;
1.1.1.12! root 6762: case OPC_CVT_W_S:
1.1.1.7 root 6763: {
6764: TCGv_i32 fp0 = tcg_temp_new_i32();
6765:
6766: gen_load_fpr32(fp0, fs);
6767: gen_helper_float_cvtw_s(fp0, fp0);
6768: gen_store_fpr32(fp0, fd);
6769: tcg_temp_free_i32(fp0);
6770: }
1.1.1.6 root 6771: opn = "cvt.w.s";
6772: break;
1.1.1.12! root 6773: case OPC_CVT_L_S:
1.1.1.6 root 6774: check_cp1_64bitmode(ctx);
1.1.1.7 root 6775: {
6776: TCGv_i32 fp32 = tcg_temp_new_i32();
6777: TCGv_i64 fp64 = tcg_temp_new_i64();
6778:
6779: gen_load_fpr32(fp32, fs);
6780: gen_helper_float_cvtl_s(fp64, fp32);
6781: tcg_temp_free_i32(fp32);
6782: gen_store_fpr64(ctx, fp64, fd);
6783: tcg_temp_free_i64(fp64);
6784: }
1.1.1.6 root 6785: opn = "cvt.l.s";
6786: break;
1.1.1.12! root 6787: case OPC_CVT_PS_S:
1.1.1.6 root 6788: check_cp1_64bitmode(ctx);
1.1.1.7 root 6789: {
6790: TCGv_i64 fp64 = tcg_temp_new_i64();
6791: TCGv_i32 fp32_0 = tcg_temp_new_i32();
6792: TCGv_i32 fp32_1 = tcg_temp_new_i32();
6793:
6794: gen_load_fpr32(fp32_0, fs);
6795: gen_load_fpr32(fp32_1, ft);
6796: tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6797: tcg_temp_free_i32(fp32_1);
6798: tcg_temp_free_i32(fp32_0);
6799: gen_store_fpr64(ctx, fp64, fd);
6800: tcg_temp_free_i64(fp64);
6801: }
1.1.1.6 root 6802: opn = "cvt.ps.s";
6803: break;
1.1.1.12! root 6804: case OPC_CMP_F_S:
! 6805: case OPC_CMP_UN_S:
! 6806: case OPC_CMP_EQ_S:
! 6807: case OPC_CMP_UEQ_S:
! 6808: case OPC_CMP_OLT_S:
! 6809: case OPC_CMP_ULT_S:
! 6810: case OPC_CMP_OLE_S:
! 6811: case OPC_CMP_ULE_S:
! 6812: case OPC_CMP_SF_S:
! 6813: case OPC_CMP_NGLE_S:
! 6814: case OPC_CMP_SEQ_S:
! 6815: case OPC_CMP_NGL_S:
! 6816: case OPC_CMP_LT_S:
! 6817: case OPC_CMP_NGE_S:
! 6818: case OPC_CMP_LE_S:
! 6819: case OPC_CMP_NGT_S:
! 6820: if (ctx->opcode & (1 << 6)) {
! 6821: gen_cmpabs_s(ctx, func-48, ft, fs, cc);
! 6822: opn = condnames_abs[func-48];
! 6823: } else {
! 6824: gen_cmp_s(ctx, func-48, ft, fs, cc);
! 6825: opn = condnames[func-48];
1.1.1.6 root 6826: }
6827: break;
1.1.1.12! root 6828: case OPC_ADD_D:
1.1.1.6 root 6829: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6830: {
6831: TCGv_i64 fp0 = tcg_temp_new_i64();
6832: TCGv_i64 fp1 = tcg_temp_new_i64();
6833:
6834: gen_load_fpr64(ctx, fp0, fs);
6835: gen_load_fpr64(ctx, fp1, ft);
6836: gen_helper_float_add_d(fp0, fp0, fp1);
6837: tcg_temp_free_i64(fp1);
6838: gen_store_fpr64(ctx, fp0, fd);
6839: tcg_temp_free_i64(fp0);
6840: }
1.1.1.4 root 6841: opn = "add.d";
1.1.1.6 root 6842: optype = BINOP;
1.1.1.4 root 6843: break;
1.1.1.12! root 6844: case OPC_SUB_D:
1.1.1.6 root 6845: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6846: {
6847: TCGv_i64 fp0 = tcg_temp_new_i64();
6848: TCGv_i64 fp1 = tcg_temp_new_i64();
6849:
6850: gen_load_fpr64(ctx, fp0, fs);
6851: gen_load_fpr64(ctx, fp1, ft);
6852: gen_helper_float_sub_d(fp0, fp0, fp1);
6853: tcg_temp_free_i64(fp1);
6854: gen_store_fpr64(ctx, fp0, fd);
6855: tcg_temp_free_i64(fp0);
6856: }
1.1.1.4 root 6857: opn = "sub.d";
1.1.1.6 root 6858: optype = BINOP;
1.1.1.4 root 6859: break;
1.1.1.12! root 6860: case OPC_MUL_D:
1.1.1.6 root 6861: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6862: {
6863: TCGv_i64 fp0 = tcg_temp_new_i64();
6864: TCGv_i64 fp1 = tcg_temp_new_i64();
6865:
6866: gen_load_fpr64(ctx, fp0, fs);
6867: gen_load_fpr64(ctx, fp1, ft);
6868: gen_helper_float_mul_d(fp0, fp0, fp1);
6869: tcg_temp_free_i64(fp1);
6870: gen_store_fpr64(ctx, fp0, fd);
6871: tcg_temp_free_i64(fp0);
6872: }
1.1.1.4 root 6873: opn = "mul.d";
1.1.1.6 root 6874: optype = BINOP;
1.1.1.4 root 6875: break;
1.1.1.12! root 6876: case OPC_DIV_D:
1.1.1.6 root 6877: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 root 6878: {
6879: TCGv_i64 fp0 = tcg_temp_new_i64();
6880: TCGv_i64 fp1 = tcg_temp_new_i64();
6881:
6882: gen_load_fpr64(ctx, fp0, fs);
6883: gen_load_fpr64(ctx, fp1, ft);
6884: gen_helper_float_div_d(fp0, fp0, fp1);
6885: tcg_temp_free_i64(fp1);
6886: gen_store_fpr64(ctx, fp0, fd);
6887: tcg_temp_free_i64(fp0);
6888: }
1.1.1.4 root 6889: opn = "div.d";
1.1.1.6 root 6890: optype = BINOP;
1.1.1.4 root 6891: break;
1.1.1.12! root 6892: case OPC_SQRT_D:
1.1.1.6 root 6893: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6894: {
6895: TCGv_i64 fp0 = tcg_temp_new_i64();
6896:
6897: gen_load_fpr64(ctx, fp0, fs);
6898: gen_helper_float_sqrt_d(fp0, fp0);
6899: gen_store_fpr64(ctx, fp0, fd);
6900: tcg_temp_free_i64(fp0);
6901: }
1.1.1.4 root 6902: opn = "sqrt.d";
6903: break;
1.1.1.12! root 6904: case OPC_ABS_D:
1.1.1.6 root 6905: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6906: {
6907: TCGv_i64 fp0 = tcg_temp_new_i64();
6908:
6909: gen_load_fpr64(ctx, fp0, fs);
6910: gen_helper_float_abs_d(fp0, fp0);
6911: gen_store_fpr64(ctx, fp0, fd);
6912: tcg_temp_free_i64(fp0);
6913: }
1.1.1.4 root 6914: opn = "abs.d";
6915: break;
1.1.1.12! root 6916: case OPC_MOV_D:
1.1.1.6 root 6917: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6918: {
6919: TCGv_i64 fp0 = tcg_temp_new_i64();
6920:
6921: gen_load_fpr64(ctx, fp0, fs);
6922: gen_store_fpr64(ctx, fp0, fd);
6923: tcg_temp_free_i64(fp0);
6924: }
1.1.1.4 root 6925: opn = "mov.d";
6926: break;
1.1.1.12! root 6927: case OPC_NEG_D:
1.1.1.6 root 6928: check_cp1_registers(ctx, fs | fd);
1.1.1.7 root 6929: {
6930: TCGv_i64 fp0 = tcg_temp_new_i64();
6931:
6932: gen_load_fpr64(ctx, fp0, fs);
6933: gen_helper_float_chs_d(fp0, fp0);
6934: gen_store_fpr64(ctx, fp0, fd);
6935: tcg_temp_free_i64(fp0);
6936: }
1.1.1.4 root 6937: opn = "neg.d";
6938: break;
1.1.1.12! root 6939: case OPC_ROUND_L_D:
1.1.1.6 root 6940: check_cp1_64bitmode(ctx);
1.1.1.7 root 6941: {
6942: TCGv_i64 fp0 = tcg_temp_new_i64();
6943:
6944: gen_load_fpr64(ctx, fp0, fs);
6945: gen_helper_float_roundl_d(fp0, fp0);
6946: gen_store_fpr64(ctx, fp0, fd);
6947: tcg_temp_free_i64(fp0);
6948: }
1.1.1.6 root 6949: opn = "round.l.d";
6950: break;
1.1.1.12! root 6951: case OPC_TRUNC_L_D:
1.1.1.6 root 6952: check_cp1_64bitmode(ctx);
1.1.1.7 root 6953: {
6954: TCGv_i64 fp0 = tcg_temp_new_i64();
6955:
6956: gen_load_fpr64(ctx, fp0, fs);
6957: gen_helper_float_truncl_d(fp0, fp0);
6958: gen_store_fpr64(ctx, fp0, fd);
6959: tcg_temp_free_i64(fp0);
6960: }
1.1.1.6 root 6961: opn = "trunc.l.d";
6962: break;
1.1.1.12! root 6963: case OPC_CEIL_L_D:
1.1.1.6 root 6964: check_cp1_64bitmode(ctx);
1.1.1.7 root 6965: {
6966: TCGv_i64 fp0 = tcg_temp_new_i64();
6967:
6968: gen_load_fpr64(ctx, fp0, fs);
6969: gen_helper_float_ceill_d(fp0, fp0);
6970: gen_store_fpr64(ctx, fp0, fd);
6971: tcg_temp_free_i64(fp0);
6972: }
1.1.1.6 root 6973: opn = "ceil.l.d";
6974: break;
1.1.1.12! root 6975: case OPC_FLOOR_L_D:
1.1.1.6 root 6976: check_cp1_64bitmode(ctx);
1.1.1.7 root 6977: {
6978: TCGv_i64 fp0 = tcg_temp_new_i64();
6979:
6980: gen_load_fpr64(ctx, fp0, fs);
6981: gen_helper_float_floorl_d(fp0, fp0);
6982: gen_store_fpr64(ctx, fp0, fd);
6983: tcg_temp_free_i64(fp0);
6984: }
1.1.1.6 root 6985: opn = "floor.l.d";
6986: break;
1.1.1.12! root 6987: case OPC_ROUND_W_D:
1.1.1.6 root 6988: check_cp1_registers(ctx, fs);
1.1.1.7 root 6989: {
6990: TCGv_i32 fp32 = tcg_temp_new_i32();
6991: TCGv_i64 fp64 = tcg_temp_new_i64();
6992:
6993: gen_load_fpr64(ctx, fp64, fs);
6994: gen_helper_float_roundw_d(fp32, fp64);
6995: tcg_temp_free_i64(fp64);
6996: gen_store_fpr32(fp32, fd);
6997: tcg_temp_free_i32(fp32);
6998: }
1.1.1.4 root 6999: opn = "round.w.d";
7000: break;
1.1.1.12! root 7001: case OPC_TRUNC_W_D:
1.1.1.6 root 7002: check_cp1_registers(ctx, fs);
1.1.1.7 root 7003: {
7004: TCGv_i32 fp32 = tcg_temp_new_i32();
7005: TCGv_i64 fp64 = tcg_temp_new_i64();
7006:
7007: gen_load_fpr64(ctx, fp64, fs);
7008: gen_helper_float_truncw_d(fp32, fp64);
7009: tcg_temp_free_i64(fp64);
7010: gen_store_fpr32(fp32, fd);
7011: tcg_temp_free_i32(fp32);
7012: }
1.1.1.4 root 7013: opn = "trunc.w.d";
7014: break;
1.1.1.12! root 7015: case OPC_CEIL_W_D:
1.1.1.6 root 7016: check_cp1_registers(ctx, fs);
1.1.1.7 root 7017: {
7018: TCGv_i32 fp32 = tcg_temp_new_i32();
7019: TCGv_i64 fp64 = tcg_temp_new_i64();
7020:
7021: gen_load_fpr64(ctx, fp64, fs);
7022: gen_helper_float_ceilw_d(fp32, fp64);
7023: tcg_temp_free_i64(fp64);
7024: gen_store_fpr32(fp32, fd);
7025: tcg_temp_free_i32(fp32);
7026: }
1.1.1.4 root 7027: opn = "ceil.w.d";
7028: break;
1.1.1.12! root 7029: case OPC_FLOOR_W_D:
1.1.1.6 root 7030: check_cp1_registers(ctx, fs);
1.1.1.7 root 7031: {
7032: TCGv_i32 fp32 = tcg_temp_new_i32();
7033: TCGv_i64 fp64 = tcg_temp_new_i64();
7034:
7035: gen_load_fpr64(ctx, fp64, fs);
7036: gen_helper_float_floorw_d(fp32, fp64);
7037: tcg_temp_free_i64(fp64);
7038: gen_store_fpr32(fp32, fd);
7039: tcg_temp_free_i32(fp32);
7040: }
1.1.1.5 root 7041: opn = "floor.w.d";
7042: break;
1.1.1.12! root 7043: case OPC_MOVCF_D:
1.1.1.7 root 7044: gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 7045: opn = "movcf.d";
1.1.1.4 root 7046: break;
1.1.1.12! root 7047: case OPC_MOVZ_D:
1.1.1.7 root 7048: {
7049: int l1 = gen_new_label();
1.1.1.8 root 7050: TCGv_i64 fp0;
1.1.1.7 root 7051:
1.1.1.8 root 7052: if (ft != 0) {
7053: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7054: }
7055: fp0 = tcg_temp_new_i64();
1.1.1.7 root 7056: gen_load_fpr64(ctx, fp0, fs);
7057: gen_store_fpr64(ctx, fp0, fd);
7058: tcg_temp_free_i64(fp0);
7059: gen_set_label(l1);
7060: }
1.1.1.6 root 7061: opn = "movz.d";
7062: break;
1.1.1.12! root 7063: case OPC_MOVN_D:
1.1.1.7 root 7064: {
7065: int l1 = gen_new_label();
1.1.1.8 root 7066: TCGv_i64 fp0;
1.1.1.7 root 7067:
1.1.1.8 root 7068: if (ft != 0) {
7069: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7070: fp0 = tcg_temp_new_i64();
7071: gen_load_fpr64(ctx, fp0, fs);
7072: gen_store_fpr64(ctx, fp0, fd);
7073: tcg_temp_free_i64(fp0);
7074: gen_set_label(l1);
7075: }
1.1.1.7 root 7076: }
1.1.1.6 root 7077: opn = "movn.d";
7078: break;
1.1.1.12! root 7079: case OPC_RECIP_D:
1.1.1.6 root 7080: check_cp1_64bitmode(ctx);
1.1.1.7 root 7081: {
7082: TCGv_i64 fp0 = tcg_temp_new_i64();
7083:
7084: gen_load_fpr64(ctx, fp0, fs);
7085: gen_helper_float_recip_d(fp0, fp0);
7086: gen_store_fpr64(ctx, fp0, fd);
7087: tcg_temp_free_i64(fp0);
7088: }
1.1.1.6 root 7089: opn = "recip.d";
7090: break;
1.1.1.12! root 7091: case OPC_RSQRT_D:
1.1.1.6 root 7092: check_cp1_64bitmode(ctx);
1.1.1.7 root 7093: {
7094: TCGv_i64 fp0 = tcg_temp_new_i64();
7095:
7096: gen_load_fpr64(ctx, fp0, fs);
7097: gen_helper_float_rsqrt_d(fp0, fp0);
7098: gen_store_fpr64(ctx, fp0, fd);
7099: tcg_temp_free_i64(fp0);
7100: }
1.1.1.6 root 7101: opn = "rsqrt.d";
7102: break;
1.1.1.12! root 7103: case OPC_RECIP2_D:
1.1.1.6 root 7104: check_cp1_64bitmode(ctx);
1.1.1.7 root 7105: {
7106: TCGv_i64 fp0 = tcg_temp_new_i64();
7107: TCGv_i64 fp1 = tcg_temp_new_i64();
7108:
7109: gen_load_fpr64(ctx, fp0, fs);
7110: gen_load_fpr64(ctx, fp1, ft);
7111: gen_helper_float_recip2_d(fp0, fp0, fp1);
7112: tcg_temp_free_i64(fp1);
7113: gen_store_fpr64(ctx, fp0, fd);
7114: tcg_temp_free_i64(fp0);
7115: }
1.1.1.6 root 7116: opn = "recip2.d";
7117: break;
1.1.1.12! root 7118: case OPC_RECIP1_D:
1.1.1.6 root 7119: check_cp1_64bitmode(ctx);
1.1.1.7 root 7120: {
7121: TCGv_i64 fp0 = tcg_temp_new_i64();
7122:
7123: gen_load_fpr64(ctx, fp0, fs);
7124: gen_helper_float_recip1_d(fp0, fp0);
7125: gen_store_fpr64(ctx, fp0, fd);
7126: tcg_temp_free_i64(fp0);
7127: }
1.1.1.6 root 7128: opn = "recip1.d";
7129: break;
1.1.1.12! root 7130: case OPC_RSQRT1_D:
1.1.1.6 root 7131: check_cp1_64bitmode(ctx);
1.1.1.7 root 7132: {
7133: TCGv_i64 fp0 = tcg_temp_new_i64();
7134:
7135: gen_load_fpr64(ctx, fp0, fs);
7136: gen_helper_float_rsqrt1_d(fp0, fp0);
7137: gen_store_fpr64(ctx, fp0, fd);
7138: tcg_temp_free_i64(fp0);
7139: }
1.1.1.6 root 7140: opn = "rsqrt1.d";
7141: break;
1.1.1.12! root 7142: case OPC_RSQRT2_D:
1.1.1.6 root 7143: check_cp1_64bitmode(ctx);
1.1.1.7 root 7144: {
7145: TCGv_i64 fp0 = tcg_temp_new_i64();
7146: TCGv_i64 fp1 = tcg_temp_new_i64();
7147:
7148: gen_load_fpr64(ctx, fp0, fs);
7149: gen_load_fpr64(ctx, fp1, ft);
7150: gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
7151: tcg_temp_free_i64(fp1);
7152: gen_store_fpr64(ctx, fp0, fd);
7153: tcg_temp_free_i64(fp0);
7154: }
1.1.1.6 root 7155: opn = "rsqrt2.d";
1.1.1.4 root 7156: break;
1.1.1.12! root 7157: case OPC_CMP_F_D:
! 7158: case OPC_CMP_UN_D:
! 7159: case OPC_CMP_EQ_D:
! 7160: case OPC_CMP_UEQ_D:
! 7161: case OPC_CMP_OLT_D:
! 7162: case OPC_CMP_ULT_D:
! 7163: case OPC_CMP_OLE_D:
! 7164: case OPC_CMP_ULE_D:
! 7165: case OPC_CMP_SF_D:
! 7166: case OPC_CMP_NGLE_D:
! 7167: case OPC_CMP_SEQ_D:
! 7168: case OPC_CMP_NGL_D:
! 7169: case OPC_CMP_LT_D:
! 7170: case OPC_CMP_NGE_D:
! 7171: case OPC_CMP_LE_D:
! 7172: case OPC_CMP_NGT_D:
! 7173: if (ctx->opcode & (1 << 6)) {
! 7174: gen_cmpabs_d(ctx, func-48, ft, fs, cc);
! 7175: opn = condnames_abs[func-48];
! 7176: } else {
! 7177: gen_cmp_d(ctx, func-48, ft, fs, cc);
! 7178: opn = condnames[func-48];
1.1.1.6 root 7179: }
7180: break;
1.1.1.12! root 7181: case OPC_CVT_S_D:
1.1.1.6 root 7182: check_cp1_registers(ctx, fs);
1.1.1.7 root 7183: {
7184: TCGv_i32 fp32 = tcg_temp_new_i32();
7185: TCGv_i64 fp64 = tcg_temp_new_i64();
7186:
7187: gen_load_fpr64(ctx, fp64, fs);
7188: gen_helper_float_cvts_d(fp32, fp64);
7189: tcg_temp_free_i64(fp64);
7190: gen_store_fpr32(fp32, fd);
7191: tcg_temp_free_i32(fp32);
7192: }
1.1.1.6 root 7193: opn = "cvt.s.d";
7194: break;
1.1.1.12! root 7195: case OPC_CVT_W_D:
1.1.1.6 root 7196: check_cp1_registers(ctx, fs);
1.1.1.7 root 7197: {
7198: TCGv_i32 fp32 = tcg_temp_new_i32();
7199: TCGv_i64 fp64 = tcg_temp_new_i64();
7200:
7201: gen_load_fpr64(ctx, fp64, fs);
7202: gen_helper_float_cvtw_d(fp32, fp64);
7203: tcg_temp_free_i64(fp64);
7204: gen_store_fpr32(fp32, fd);
7205: tcg_temp_free_i32(fp32);
7206: }
1.1.1.6 root 7207: opn = "cvt.w.d";
7208: break;
1.1.1.12! root 7209: case OPC_CVT_L_D:
1.1.1.6 root 7210: check_cp1_64bitmode(ctx);
1.1.1.7 root 7211: {
7212: TCGv_i64 fp0 = tcg_temp_new_i64();
7213:
7214: gen_load_fpr64(ctx, fp0, fs);
7215: gen_helper_float_cvtl_d(fp0, fp0);
7216: gen_store_fpr64(ctx, fp0, fd);
7217: tcg_temp_free_i64(fp0);
7218: }
1.1.1.6 root 7219: opn = "cvt.l.d";
7220: break;
1.1.1.12! root 7221: case OPC_CVT_S_W:
1.1.1.7 root 7222: {
7223: TCGv_i32 fp0 = tcg_temp_new_i32();
7224:
7225: gen_load_fpr32(fp0, fs);
7226: gen_helper_float_cvts_w(fp0, fp0);
7227: gen_store_fpr32(fp0, fd);
7228: tcg_temp_free_i32(fp0);
7229: }
1.1.1.6 root 7230: opn = "cvt.s.w";
7231: break;
1.1.1.12! root 7232: case OPC_CVT_D_W:
1.1.1.6 root 7233: check_cp1_registers(ctx, fd);
1.1.1.7 root 7234: {
7235: TCGv_i32 fp32 = tcg_temp_new_i32();
7236: TCGv_i64 fp64 = tcg_temp_new_i64();
7237:
7238: gen_load_fpr32(fp32, fs);
7239: gen_helper_float_cvtd_w(fp64, fp32);
7240: tcg_temp_free_i32(fp32);
7241: gen_store_fpr64(ctx, fp64, fd);
7242: tcg_temp_free_i64(fp64);
7243: }
1.1.1.6 root 7244: opn = "cvt.d.w";
7245: break;
1.1.1.12! root 7246: case OPC_CVT_S_L:
1.1.1.6 root 7247: check_cp1_64bitmode(ctx);
1.1.1.7 root 7248: {
7249: TCGv_i32 fp32 = tcg_temp_new_i32();
7250: TCGv_i64 fp64 = tcg_temp_new_i64();
7251:
7252: gen_load_fpr64(ctx, fp64, fs);
7253: gen_helper_float_cvts_l(fp32, fp64);
7254: tcg_temp_free_i64(fp64);
7255: gen_store_fpr32(fp32, fd);
7256: tcg_temp_free_i32(fp32);
7257: }
1.1.1.6 root 7258: opn = "cvt.s.l";
7259: break;
1.1.1.12! root 7260: case OPC_CVT_D_L:
1.1.1.6 root 7261: check_cp1_64bitmode(ctx);
1.1.1.7 root 7262: {
7263: TCGv_i64 fp0 = tcg_temp_new_i64();
7264:
7265: gen_load_fpr64(ctx, fp0, fs);
7266: gen_helper_float_cvtd_l(fp0, fp0);
7267: gen_store_fpr64(ctx, fp0, fd);
7268: tcg_temp_free_i64(fp0);
7269: }
1.1.1.6 root 7270: opn = "cvt.d.l";
7271: break;
1.1.1.12! root 7272: case OPC_CVT_PS_PW:
1.1.1.6 root 7273: check_cp1_64bitmode(ctx);
1.1.1.7 root 7274: {
7275: TCGv_i64 fp0 = tcg_temp_new_i64();
7276:
7277: gen_load_fpr64(ctx, fp0, fs);
7278: gen_helper_float_cvtps_pw(fp0, fp0);
7279: gen_store_fpr64(ctx, fp0, fd);
7280: tcg_temp_free_i64(fp0);
7281: }
1.1.1.6 root 7282: opn = "cvt.ps.pw";
7283: break;
1.1.1.12! root 7284: case OPC_ADD_PS:
1.1.1.6 root 7285: check_cp1_64bitmode(ctx);
1.1.1.7 root 7286: {
7287: TCGv_i64 fp0 = tcg_temp_new_i64();
7288: TCGv_i64 fp1 = tcg_temp_new_i64();
7289:
7290: gen_load_fpr64(ctx, fp0, fs);
7291: gen_load_fpr64(ctx, fp1, ft);
7292: gen_helper_float_add_ps(fp0, fp0, fp1);
7293: tcg_temp_free_i64(fp1);
7294: gen_store_fpr64(ctx, fp0, fd);
7295: tcg_temp_free_i64(fp0);
7296: }
1.1.1.6 root 7297: opn = "add.ps";
7298: break;
1.1.1.12! root 7299: case OPC_SUB_PS:
1.1.1.6 root 7300: check_cp1_64bitmode(ctx);
1.1.1.7 root 7301: {
7302: TCGv_i64 fp0 = tcg_temp_new_i64();
7303: TCGv_i64 fp1 = tcg_temp_new_i64();
7304:
7305: gen_load_fpr64(ctx, fp0, fs);
7306: gen_load_fpr64(ctx, fp1, ft);
7307: gen_helper_float_sub_ps(fp0, fp0, fp1);
7308: tcg_temp_free_i64(fp1);
7309: gen_store_fpr64(ctx, fp0, fd);
7310: tcg_temp_free_i64(fp0);
7311: }
1.1.1.6 root 7312: opn = "sub.ps";
7313: break;
1.1.1.12! root 7314: case OPC_MUL_PS:
1.1.1.6 root 7315: check_cp1_64bitmode(ctx);
1.1.1.7 root 7316: {
7317: TCGv_i64 fp0 = tcg_temp_new_i64();
7318: TCGv_i64 fp1 = tcg_temp_new_i64();
7319:
7320: gen_load_fpr64(ctx, fp0, fs);
7321: gen_load_fpr64(ctx, fp1, ft);
7322: gen_helper_float_mul_ps(fp0, fp0, fp1);
7323: tcg_temp_free_i64(fp1);
7324: gen_store_fpr64(ctx, fp0, fd);
7325: tcg_temp_free_i64(fp0);
7326: }
1.1.1.6 root 7327: opn = "mul.ps";
7328: break;
1.1.1.12! root 7329: case OPC_ABS_PS:
1.1.1.6 root 7330: check_cp1_64bitmode(ctx);
1.1.1.7 root 7331: {
7332: TCGv_i64 fp0 = tcg_temp_new_i64();
7333:
7334: gen_load_fpr64(ctx, fp0, fs);
7335: gen_helper_float_abs_ps(fp0, fp0);
7336: gen_store_fpr64(ctx, fp0, fd);
7337: tcg_temp_free_i64(fp0);
7338: }
1.1.1.6 root 7339: opn = "abs.ps";
7340: break;
1.1.1.12! root 7341: case OPC_MOV_PS:
1.1.1.6 root 7342: check_cp1_64bitmode(ctx);
1.1.1.7 root 7343: {
7344: TCGv_i64 fp0 = tcg_temp_new_i64();
7345:
7346: gen_load_fpr64(ctx, fp0, fs);
7347: gen_store_fpr64(ctx, fp0, fd);
7348: tcg_temp_free_i64(fp0);
7349: }
1.1.1.6 root 7350: opn = "mov.ps";
7351: break;
1.1.1.12! root 7352: case OPC_NEG_PS:
1.1.1.6 root 7353: check_cp1_64bitmode(ctx);
1.1.1.7 root 7354: {
7355: TCGv_i64 fp0 = tcg_temp_new_i64();
7356:
7357: gen_load_fpr64(ctx, fp0, fs);
7358: gen_helper_float_chs_ps(fp0, fp0);
7359: gen_store_fpr64(ctx, fp0, fd);
7360: tcg_temp_free_i64(fp0);
7361: }
1.1.1.6 root 7362: opn = "neg.ps";
7363: break;
1.1.1.12! root 7364: case OPC_MOVCF_PS:
1.1.1.6 root 7365: check_cp1_64bitmode(ctx);
1.1.1.7 root 7366: gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 7367: opn = "movcf.ps";
7368: break;
1.1.1.12! root 7369: case OPC_MOVZ_PS:
1.1.1.6 root 7370: check_cp1_64bitmode(ctx);
1.1.1.7 root 7371: {
7372: int l1 = gen_new_label();
1.1.1.8 root 7373: TCGv_i64 fp0;
1.1.1.7 root 7374:
1.1.1.8 root 7375: if (ft != 0)
7376: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7377: fp0 = tcg_temp_new_i64();
7378: gen_load_fpr64(ctx, fp0, fs);
7379: gen_store_fpr64(ctx, fp0, fd);
7380: tcg_temp_free_i64(fp0);
1.1.1.7 root 7381: gen_set_label(l1);
7382: }
1.1.1.6 root 7383: opn = "movz.ps";
7384: break;
1.1.1.12! root 7385: case OPC_MOVN_PS:
1.1.1.6 root 7386: check_cp1_64bitmode(ctx);
1.1.1.7 root 7387: {
7388: int l1 = gen_new_label();
1.1.1.8 root 7389: TCGv_i64 fp0;
1.1.1.7 root 7390:
1.1.1.8 root 7391: if (ft != 0) {
7392: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7393: fp0 = tcg_temp_new_i64();
7394: gen_load_fpr64(ctx, fp0, fs);
7395: gen_store_fpr64(ctx, fp0, fd);
7396: tcg_temp_free_i64(fp0);
7397: gen_set_label(l1);
7398: }
1.1.1.7 root 7399: }
1.1.1.6 root 7400: opn = "movn.ps";
7401: break;
1.1.1.12! root 7402: case OPC_ADDR_PS:
1.1.1.6 root 7403: check_cp1_64bitmode(ctx);
1.1.1.7 root 7404: {
7405: TCGv_i64 fp0 = tcg_temp_new_i64();
7406: TCGv_i64 fp1 = tcg_temp_new_i64();
7407:
7408: gen_load_fpr64(ctx, fp0, ft);
7409: gen_load_fpr64(ctx, fp1, fs);
7410: gen_helper_float_addr_ps(fp0, fp0, fp1);
7411: tcg_temp_free_i64(fp1);
7412: gen_store_fpr64(ctx, fp0, fd);
7413: tcg_temp_free_i64(fp0);
7414: }
1.1.1.6 root 7415: opn = "addr.ps";
7416: break;
1.1.1.12! root 7417: case OPC_MULR_PS:
1.1.1.6 root 7418: check_cp1_64bitmode(ctx);
1.1.1.7 root 7419: {
7420: TCGv_i64 fp0 = tcg_temp_new_i64();
7421: TCGv_i64 fp1 = tcg_temp_new_i64();
7422:
7423: gen_load_fpr64(ctx, fp0, ft);
7424: gen_load_fpr64(ctx, fp1, fs);
7425: gen_helper_float_mulr_ps(fp0, fp0, fp1);
7426: tcg_temp_free_i64(fp1);
7427: gen_store_fpr64(ctx, fp0, fd);
7428: tcg_temp_free_i64(fp0);
7429: }
1.1.1.6 root 7430: opn = "mulr.ps";
7431: break;
1.1.1.12! root 7432: case OPC_RECIP2_PS:
1.1.1.6 root 7433: check_cp1_64bitmode(ctx);
1.1.1.7 root 7434: {
7435: TCGv_i64 fp0 = tcg_temp_new_i64();
7436: TCGv_i64 fp1 = tcg_temp_new_i64();
7437:
7438: gen_load_fpr64(ctx, fp0, fs);
7439: gen_load_fpr64(ctx, fp1, fd);
7440: gen_helper_float_recip2_ps(fp0, fp0, fp1);
7441: tcg_temp_free_i64(fp1);
7442: gen_store_fpr64(ctx, fp0, fd);
7443: tcg_temp_free_i64(fp0);
7444: }
1.1.1.6 root 7445: opn = "recip2.ps";
7446: break;
1.1.1.12! root 7447: case OPC_RECIP1_PS:
1.1.1.6 root 7448: check_cp1_64bitmode(ctx);
1.1.1.7 root 7449: {
7450: TCGv_i64 fp0 = tcg_temp_new_i64();
7451:
7452: gen_load_fpr64(ctx, fp0, fs);
7453: gen_helper_float_recip1_ps(fp0, fp0);
7454: gen_store_fpr64(ctx, fp0, fd);
7455: tcg_temp_free_i64(fp0);
7456: }
1.1.1.6 root 7457: opn = "recip1.ps";
7458: break;
1.1.1.12! root 7459: case OPC_RSQRT1_PS:
1.1.1.6 root 7460: check_cp1_64bitmode(ctx);
1.1.1.7 root 7461: {
7462: TCGv_i64 fp0 = tcg_temp_new_i64();
7463:
7464: gen_load_fpr64(ctx, fp0, fs);
7465: gen_helper_float_rsqrt1_ps(fp0, fp0);
7466: gen_store_fpr64(ctx, fp0, fd);
7467: tcg_temp_free_i64(fp0);
7468: }
1.1.1.6 root 7469: opn = "rsqrt1.ps";
7470: break;
1.1.1.12! root 7471: case OPC_RSQRT2_PS:
1.1.1.6 root 7472: check_cp1_64bitmode(ctx);
1.1.1.7 root 7473: {
7474: TCGv_i64 fp0 = tcg_temp_new_i64();
7475: TCGv_i64 fp1 = tcg_temp_new_i64();
7476:
7477: gen_load_fpr64(ctx, fp0, fs);
7478: gen_load_fpr64(ctx, fp1, ft);
7479: gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7480: tcg_temp_free_i64(fp1);
7481: gen_store_fpr64(ctx, fp0, fd);
7482: tcg_temp_free_i64(fp0);
7483: }
1.1.1.6 root 7484: opn = "rsqrt2.ps";
7485: break;
1.1.1.12! root 7486: case OPC_CVT_S_PU:
1.1.1.6 root 7487: check_cp1_64bitmode(ctx);
1.1.1.7 root 7488: {
7489: TCGv_i32 fp0 = tcg_temp_new_i32();
7490:
7491: gen_load_fpr32h(fp0, fs);
7492: gen_helper_float_cvts_pu(fp0, fp0);
7493: gen_store_fpr32(fp0, fd);
7494: tcg_temp_free_i32(fp0);
7495: }
1.1.1.6 root 7496: opn = "cvt.s.pu";
7497: break;
1.1.1.12! root 7498: case OPC_CVT_PW_PS:
1.1.1.6 root 7499: check_cp1_64bitmode(ctx);
1.1.1.7 root 7500: {
7501: TCGv_i64 fp0 = tcg_temp_new_i64();
7502:
7503: gen_load_fpr64(ctx, fp0, fs);
7504: gen_helper_float_cvtpw_ps(fp0, fp0);
7505: gen_store_fpr64(ctx, fp0, fd);
7506: tcg_temp_free_i64(fp0);
7507: }
1.1.1.6 root 7508: opn = "cvt.pw.ps";
1.1.1.4 root 7509: break;
1.1.1.12! root 7510: case OPC_CVT_S_PL:
1.1.1.6 root 7511: check_cp1_64bitmode(ctx);
1.1.1.7 root 7512: {
7513: TCGv_i32 fp0 = tcg_temp_new_i32();
7514:
7515: gen_load_fpr32(fp0, fs);
7516: gen_helper_float_cvts_pl(fp0, fp0);
7517: gen_store_fpr32(fp0, fd);
7518: tcg_temp_free_i32(fp0);
7519: }
1.1.1.6 root 7520: opn = "cvt.s.pl";
1.1.1.4 root 7521: break;
1.1.1.12! root 7522: case OPC_PLL_PS:
1.1.1.6 root 7523: check_cp1_64bitmode(ctx);
1.1.1.7 root 7524: {
7525: TCGv_i32 fp0 = tcg_temp_new_i32();
7526: TCGv_i32 fp1 = tcg_temp_new_i32();
7527:
7528: gen_load_fpr32(fp0, fs);
7529: gen_load_fpr32(fp1, ft);
7530: gen_store_fpr32h(fp0, fd);
7531: gen_store_fpr32(fp1, fd);
7532: tcg_temp_free_i32(fp0);
7533: tcg_temp_free_i32(fp1);
7534: }
1.1.1.6 root 7535: opn = "pll.ps";
1.1.1.4 root 7536: break;
1.1.1.12! root 7537: case OPC_PLU_PS:
1.1.1.6 root 7538: check_cp1_64bitmode(ctx);
1.1.1.7 root 7539: {
7540: TCGv_i32 fp0 = tcg_temp_new_i32();
7541: TCGv_i32 fp1 = tcg_temp_new_i32();
7542:
7543: gen_load_fpr32(fp0, fs);
7544: gen_load_fpr32h(fp1, ft);
7545: gen_store_fpr32(fp1, fd);
7546: gen_store_fpr32h(fp0, fd);
7547: tcg_temp_free_i32(fp0);
7548: tcg_temp_free_i32(fp1);
7549: }
1.1.1.6 root 7550: opn = "plu.ps";
7551: break;
1.1.1.12! root 7552: case OPC_PUL_PS:
1.1.1.6 root 7553: check_cp1_64bitmode(ctx);
1.1.1.7 root 7554: {
7555: TCGv_i32 fp0 = tcg_temp_new_i32();
7556: TCGv_i32 fp1 = tcg_temp_new_i32();
7557:
7558: gen_load_fpr32h(fp0, fs);
7559: gen_load_fpr32(fp1, ft);
7560: gen_store_fpr32(fp1, fd);
7561: gen_store_fpr32h(fp0, fd);
7562: tcg_temp_free_i32(fp0);
7563: tcg_temp_free_i32(fp1);
7564: }
1.1.1.6 root 7565: opn = "pul.ps";
1.1.1.4 root 7566: break;
1.1.1.12! root 7567: case OPC_PUU_PS:
1.1.1.6 root 7568: check_cp1_64bitmode(ctx);
1.1.1.7 root 7569: {
7570: TCGv_i32 fp0 = tcg_temp_new_i32();
7571: TCGv_i32 fp1 = tcg_temp_new_i32();
7572:
7573: gen_load_fpr32h(fp0, fs);
7574: gen_load_fpr32h(fp1, ft);
7575: gen_store_fpr32(fp1, fd);
7576: gen_store_fpr32h(fp0, fd);
7577: tcg_temp_free_i32(fp0);
7578: tcg_temp_free_i32(fp1);
7579: }
1.1.1.6 root 7580: opn = "puu.ps";
7581: break;
1.1.1.12! root 7582: case OPC_CMP_F_PS:
! 7583: case OPC_CMP_UN_PS:
! 7584: case OPC_CMP_EQ_PS:
! 7585: case OPC_CMP_UEQ_PS:
! 7586: case OPC_CMP_OLT_PS:
! 7587: case OPC_CMP_ULT_PS:
! 7588: case OPC_CMP_OLE_PS:
! 7589: case OPC_CMP_ULE_PS:
! 7590: case OPC_CMP_SF_PS:
! 7591: case OPC_CMP_NGLE_PS:
! 7592: case OPC_CMP_SEQ_PS:
! 7593: case OPC_CMP_NGL_PS:
! 7594: case OPC_CMP_LT_PS:
! 7595: case OPC_CMP_NGE_PS:
! 7596: case OPC_CMP_LE_PS:
! 7597: case OPC_CMP_NGT_PS:
! 7598: if (ctx->opcode & (1 << 6)) {
! 7599: gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
! 7600: opn = condnames_abs[func-48];
! 7601: } else {
! 7602: gen_cmp_ps(ctx, func-48, ft, fs, cc);
! 7603: opn = condnames[func-48];
1.1.1.6 root 7604: }
1.1.1.4 root 7605: break;
1.1.1.6 root 7606: default:
7607: MIPS_INVAL(opn);
7608: generate_exception (ctx, EXCP_RI);
7609: return;
7610: }
7611: switch (optype) {
7612: case BINOP:
7613: MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7614: break;
7615: case CMPOP:
7616: MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7617: break;
7618: default:
7619: MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7620: break;
7621: }
7622: }
7623:
7624: /* Coprocessor 3 (FPU) */
7625: static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7626: int fd, int fs, int base, int index)
7627: {
7628: const char *opn = "extended float load/store";
7629: int store = 0;
1.1.1.8 root 7630: TCGv t0 = tcg_temp_new();
1.1.1.6 root 7631:
7632: if (base == 0) {
1.1.1.7 root 7633: gen_load_gpr(t0, index);
1.1.1.6 root 7634: } else if (index == 0) {
1.1.1.7 root 7635: gen_load_gpr(t0, base);
1.1.1.6 root 7636: } else {
1.1.1.7 root 7637: gen_load_gpr(t0, index);
1.1.1.9 root 7638: gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
1.1.1.6 root 7639: }
7640: /* Don't do NOP if destination is zero: we must perform the actual
7641: memory access. */
1.1.1.8 root 7642: save_cpu_state(ctx, 0);
1.1.1.6 root 7643: switch (opc) {
7644: case OPC_LWXC1:
7645: check_cop1x(ctx);
1.1.1.7 root 7646: {
7647: TCGv_i32 fp0 = tcg_temp_new_i32();
7648:
1.1.1.8 root 7649: tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7650: tcg_gen_trunc_tl_i32(fp0, t0);
1.1.1.7 root 7651: gen_store_fpr32(fp0, fd);
7652: tcg_temp_free_i32(fp0);
7653: }
1.1.1.6 root 7654: opn = "lwxc1";
7655: break;
7656: case OPC_LDXC1:
7657: check_cop1x(ctx);
7658: check_cp1_registers(ctx, fd);
1.1.1.7 root 7659: {
7660: TCGv_i64 fp0 = tcg_temp_new_i64();
7661:
7662: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7663: gen_store_fpr64(ctx, fp0, fd);
7664: tcg_temp_free_i64(fp0);
7665: }
1.1.1.6 root 7666: opn = "ldxc1";
7667: break;
7668: case OPC_LUXC1:
7669: check_cp1_64bitmode(ctx);
1.1.1.7 root 7670: tcg_gen_andi_tl(t0, t0, ~0x7);
7671: {
7672: TCGv_i64 fp0 = tcg_temp_new_i64();
7673:
7674: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7675: gen_store_fpr64(ctx, fp0, fd);
7676: tcg_temp_free_i64(fp0);
7677: }
1.1.1.6 root 7678: opn = "luxc1";
7679: break;
7680: case OPC_SWXC1:
7681: check_cop1x(ctx);
1.1.1.7 root 7682: {
7683: TCGv_i32 fp0 = tcg_temp_new_i32();
1.1.1.8 root 7684: TCGv t1 = tcg_temp_new();
1.1.1.7 root 7685:
7686: gen_load_fpr32(fp0, fs);
7687: tcg_gen_extu_i32_tl(t1, fp0);
7688: tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7689: tcg_temp_free_i32(fp0);
1.1.1.8 root 7690: tcg_temp_free(t1);
1.1.1.7 root 7691: }
1.1.1.6 root 7692: opn = "swxc1";
7693: store = 1;
1.1.1.4 root 7694: break;
1.1.1.6 root 7695: case OPC_SDXC1:
7696: check_cop1x(ctx);
7697: check_cp1_registers(ctx, fs);
1.1.1.7 root 7698: {
7699: TCGv_i64 fp0 = tcg_temp_new_i64();
7700:
7701: gen_load_fpr64(ctx, fp0, fs);
7702: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7703: tcg_temp_free_i64(fp0);
7704: }
1.1.1.6 root 7705: opn = "sdxc1";
7706: store = 1;
7707: break;
7708: case OPC_SUXC1:
7709: check_cp1_64bitmode(ctx);
1.1.1.7 root 7710: tcg_gen_andi_tl(t0, t0, ~0x7);
7711: {
7712: TCGv_i64 fp0 = tcg_temp_new_i64();
7713:
7714: gen_load_fpr64(ctx, fp0, fs);
7715: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7716: tcg_temp_free_i64(fp0);
7717: }
1.1.1.6 root 7718: opn = "suxc1";
7719: store = 1;
7720: break;
7721: }
1.1.1.7 root 7722: tcg_temp_free(t0);
1.1.1.6 root 7723: MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7724: regnames[index], regnames[base]);
7725: }
7726:
7727: static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7728: int fd, int fr, int fs, int ft)
7729: {
7730: const char *opn = "flt3_arith";
7731:
7732: switch (opc) {
7733: case OPC_ALNV_PS:
7734: check_cp1_64bitmode(ctx);
1.1.1.7 root 7735: {
7736: TCGv t0 = tcg_temp_local_new();
1.1.1.8 root 7737: TCGv_i32 fp = tcg_temp_new_i32();
7738: TCGv_i32 fph = tcg_temp_new_i32();
1.1.1.7 root 7739: int l1 = gen_new_label();
7740: int l2 = gen_new_label();
7741:
7742: gen_load_gpr(t0, fr);
7743: tcg_gen_andi_tl(t0, t0, 0x7);
7744:
7745: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
1.1.1.8 root 7746: gen_load_fpr32(fp, fs);
7747: gen_load_fpr32h(fph, fs);
7748: gen_store_fpr32(fp, fd);
7749: gen_store_fpr32h(fph, fd);
1.1.1.7 root 7750: tcg_gen_br(l2);
7751: gen_set_label(l1);
7752: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7753: tcg_temp_free(t0);
7754: #ifdef TARGET_WORDS_BIGENDIAN
1.1.1.8 root 7755: gen_load_fpr32(fp, fs);
7756: gen_load_fpr32h(fph, ft);
7757: gen_store_fpr32h(fp, fd);
7758: gen_store_fpr32(fph, fd);
1.1.1.7 root 7759: #else
1.1.1.8 root 7760: gen_load_fpr32h(fph, fs);
7761: gen_load_fpr32(fp, ft);
7762: gen_store_fpr32(fph, fd);
7763: gen_store_fpr32h(fp, fd);
1.1.1.7 root 7764: #endif
7765: gen_set_label(l2);
1.1.1.8 root 7766: tcg_temp_free_i32(fp);
7767: tcg_temp_free_i32(fph);
1.1.1.7 root 7768: }
1.1.1.6 root 7769: opn = "alnv.ps";
7770: break;
7771: case OPC_MADD_S:
7772: check_cop1x(ctx);
1.1.1.7 root 7773: {
7774: TCGv_i32 fp0 = tcg_temp_new_i32();
7775: TCGv_i32 fp1 = tcg_temp_new_i32();
7776: TCGv_i32 fp2 = tcg_temp_new_i32();
7777:
7778: gen_load_fpr32(fp0, fs);
7779: gen_load_fpr32(fp1, ft);
7780: gen_load_fpr32(fp2, fr);
7781: gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7782: tcg_temp_free_i32(fp0);
7783: tcg_temp_free_i32(fp1);
7784: gen_store_fpr32(fp2, fd);
7785: tcg_temp_free_i32(fp2);
7786: }
1.1.1.6 root 7787: opn = "madd.s";
1.1.1.4 root 7788: break;
1.1.1.6 root 7789: case OPC_MADD_D:
7790: check_cop1x(ctx);
7791: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7792: {
7793: TCGv_i64 fp0 = tcg_temp_new_i64();
7794: TCGv_i64 fp1 = tcg_temp_new_i64();
7795: TCGv_i64 fp2 = tcg_temp_new_i64();
7796:
7797: gen_load_fpr64(ctx, fp0, fs);
7798: gen_load_fpr64(ctx, fp1, ft);
7799: gen_load_fpr64(ctx, fp2, fr);
7800: gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7801: tcg_temp_free_i64(fp0);
7802: tcg_temp_free_i64(fp1);
7803: gen_store_fpr64(ctx, fp2, fd);
7804: tcg_temp_free_i64(fp2);
7805: }
1.1.1.6 root 7806: opn = "madd.d";
7807: break;
7808: case OPC_MADD_PS:
7809: check_cp1_64bitmode(ctx);
1.1.1.7 root 7810: {
7811: TCGv_i64 fp0 = tcg_temp_new_i64();
7812: TCGv_i64 fp1 = tcg_temp_new_i64();
7813: TCGv_i64 fp2 = tcg_temp_new_i64();
7814:
7815: gen_load_fpr64(ctx, fp0, fs);
7816: gen_load_fpr64(ctx, fp1, ft);
7817: gen_load_fpr64(ctx, fp2, fr);
7818: gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7819: tcg_temp_free_i64(fp0);
7820: tcg_temp_free_i64(fp1);
7821: gen_store_fpr64(ctx, fp2, fd);
7822: tcg_temp_free_i64(fp2);
7823: }
1.1.1.6 root 7824: opn = "madd.ps";
1.1.1.4 root 7825: break;
1.1.1.6 root 7826: case OPC_MSUB_S:
7827: check_cop1x(ctx);
1.1.1.7 root 7828: {
7829: TCGv_i32 fp0 = tcg_temp_new_i32();
7830: TCGv_i32 fp1 = tcg_temp_new_i32();
7831: TCGv_i32 fp2 = tcg_temp_new_i32();
7832:
7833: gen_load_fpr32(fp0, fs);
7834: gen_load_fpr32(fp1, ft);
7835: gen_load_fpr32(fp2, fr);
7836: gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7837: tcg_temp_free_i32(fp0);
7838: tcg_temp_free_i32(fp1);
7839: gen_store_fpr32(fp2, fd);
7840: tcg_temp_free_i32(fp2);
7841: }
1.1.1.6 root 7842: opn = "msub.s";
1.1.1.4 root 7843: break;
1.1.1.6 root 7844: case OPC_MSUB_D:
7845: check_cop1x(ctx);
7846: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7847: {
7848: TCGv_i64 fp0 = tcg_temp_new_i64();
7849: TCGv_i64 fp1 = tcg_temp_new_i64();
7850: TCGv_i64 fp2 = tcg_temp_new_i64();
7851:
7852: gen_load_fpr64(ctx, fp0, fs);
7853: gen_load_fpr64(ctx, fp1, ft);
7854: gen_load_fpr64(ctx, fp2, fr);
7855: gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7856: tcg_temp_free_i64(fp0);
7857: tcg_temp_free_i64(fp1);
7858: gen_store_fpr64(ctx, fp2, fd);
7859: tcg_temp_free_i64(fp2);
7860: }
1.1.1.6 root 7861: opn = "msub.d";
7862: break;
7863: case OPC_MSUB_PS:
7864: check_cp1_64bitmode(ctx);
1.1.1.7 root 7865: {
7866: TCGv_i64 fp0 = tcg_temp_new_i64();
7867: TCGv_i64 fp1 = tcg_temp_new_i64();
7868: TCGv_i64 fp2 = tcg_temp_new_i64();
7869:
7870: gen_load_fpr64(ctx, fp0, fs);
7871: gen_load_fpr64(ctx, fp1, ft);
7872: gen_load_fpr64(ctx, fp2, fr);
7873: gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7874: tcg_temp_free_i64(fp0);
7875: tcg_temp_free_i64(fp1);
7876: gen_store_fpr64(ctx, fp2, fd);
7877: tcg_temp_free_i64(fp2);
7878: }
1.1.1.6 root 7879: opn = "msub.ps";
1.1.1.4 root 7880: break;
1.1.1.6 root 7881: case OPC_NMADD_S:
7882: check_cop1x(ctx);
1.1.1.7 root 7883: {
7884: TCGv_i32 fp0 = tcg_temp_new_i32();
7885: TCGv_i32 fp1 = tcg_temp_new_i32();
7886: TCGv_i32 fp2 = tcg_temp_new_i32();
7887:
7888: gen_load_fpr32(fp0, fs);
7889: gen_load_fpr32(fp1, ft);
7890: gen_load_fpr32(fp2, fr);
7891: gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7892: tcg_temp_free_i32(fp0);
7893: tcg_temp_free_i32(fp1);
7894: gen_store_fpr32(fp2, fd);
7895: tcg_temp_free_i32(fp2);
7896: }
1.1.1.6 root 7897: opn = "nmadd.s";
1.1.1.4 root 7898: break;
1.1.1.6 root 7899: case OPC_NMADD_D:
7900: check_cop1x(ctx);
7901: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7902: {
7903: TCGv_i64 fp0 = tcg_temp_new_i64();
7904: TCGv_i64 fp1 = tcg_temp_new_i64();
7905: TCGv_i64 fp2 = tcg_temp_new_i64();
7906:
7907: gen_load_fpr64(ctx, fp0, fs);
7908: gen_load_fpr64(ctx, fp1, ft);
7909: gen_load_fpr64(ctx, fp2, fr);
7910: gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7911: tcg_temp_free_i64(fp0);
7912: tcg_temp_free_i64(fp1);
7913: gen_store_fpr64(ctx, fp2, fd);
7914: tcg_temp_free_i64(fp2);
7915: }
1.1.1.6 root 7916: opn = "nmadd.d";
1.1.1.5 root 7917: break;
1.1.1.6 root 7918: case OPC_NMADD_PS:
7919: check_cp1_64bitmode(ctx);
1.1.1.7 root 7920: {
7921: TCGv_i64 fp0 = tcg_temp_new_i64();
7922: TCGv_i64 fp1 = tcg_temp_new_i64();
7923: TCGv_i64 fp2 = tcg_temp_new_i64();
7924:
7925: gen_load_fpr64(ctx, fp0, fs);
7926: gen_load_fpr64(ctx, fp1, ft);
7927: gen_load_fpr64(ctx, fp2, fr);
7928: gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7929: tcg_temp_free_i64(fp0);
7930: tcg_temp_free_i64(fp1);
7931: gen_store_fpr64(ctx, fp2, fd);
7932: tcg_temp_free_i64(fp2);
7933: }
1.1.1.6 root 7934: opn = "nmadd.ps";
1.1.1.4 root 7935: break;
1.1.1.6 root 7936: case OPC_NMSUB_S:
7937: check_cop1x(ctx);
1.1.1.7 root 7938: {
7939: TCGv_i32 fp0 = tcg_temp_new_i32();
7940: TCGv_i32 fp1 = tcg_temp_new_i32();
7941: TCGv_i32 fp2 = tcg_temp_new_i32();
7942:
7943: gen_load_fpr32(fp0, fs);
7944: gen_load_fpr32(fp1, ft);
7945: gen_load_fpr32(fp2, fr);
7946: gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7947: tcg_temp_free_i32(fp0);
7948: tcg_temp_free_i32(fp1);
7949: gen_store_fpr32(fp2, fd);
7950: tcg_temp_free_i32(fp2);
7951: }
1.1.1.6 root 7952: opn = "nmsub.s";
1.1.1.4 root 7953: break;
1.1.1.6 root 7954: case OPC_NMSUB_D:
7955: check_cop1x(ctx);
7956: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 root 7957: {
7958: TCGv_i64 fp0 = tcg_temp_new_i64();
7959: TCGv_i64 fp1 = tcg_temp_new_i64();
7960: TCGv_i64 fp2 = tcg_temp_new_i64();
7961:
7962: gen_load_fpr64(ctx, fp0, fs);
7963: gen_load_fpr64(ctx, fp1, ft);
7964: gen_load_fpr64(ctx, fp2, fr);
7965: gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7966: tcg_temp_free_i64(fp0);
7967: tcg_temp_free_i64(fp1);
7968: gen_store_fpr64(ctx, fp2, fd);
7969: tcg_temp_free_i64(fp2);
7970: }
1.1.1.6 root 7971: opn = "nmsub.d";
1.1.1.4 root 7972: break;
1.1.1.6 root 7973: case OPC_NMSUB_PS:
7974: check_cp1_64bitmode(ctx);
1.1.1.7 root 7975: {
7976: TCGv_i64 fp0 = tcg_temp_new_i64();
7977: TCGv_i64 fp1 = tcg_temp_new_i64();
7978: TCGv_i64 fp2 = tcg_temp_new_i64();
7979:
7980: gen_load_fpr64(ctx, fp0, fs);
7981: gen_load_fpr64(ctx, fp1, ft);
7982: gen_load_fpr64(ctx, fp2, fr);
7983: gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7984: tcg_temp_free_i64(fp0);
7985: tcg_temp_free_i64(fp1);
7986: gen_store_fpr64(ctx, fp2, fd);
7987: tcg_temp_free_i64(fp2);
7988: }
1.1.1.6 root 7989: opn = "nmsub.ps";
1.1.1.4 root 7990: break;
1.1.1.6 root 7991: default:
7992: MIPS_INVAL(opn);
7993: generate_exception (ctx, EXCP_RI);
1.1.1.4 root 7994: return;
7995: }
1.1.1.6 root 7996: MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7997: fregnames[fs], fregnames[ft]);
1.1 root 7998: }
7999:
1.1.1.12! root 8000: static void
! 8001: gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
! 8002: {
! 8003: TCGv t0;
1.1 root 8004:
1.1.1.12! root 8005: check_insn(env, ctx, ISA_MIPS32R2);
! 8006: t0 = tcg_temp_new();
1.1 root 8007:
1.1.1.12! root 8008: switch (rd) {
! 8009: case 0:
! 8010: save_cpu_state(ctx, 1);
! 8011: gen_helper_rdhwr_cpunum(t0);
! 8012: gen_store_gpr(t0, rt);
! 8013: break;
! 8014: case 1:
! 8015: save_cpu_state(ctx, 1);
! 8016: gen_helper_rdhwr_synci_step(t0);
! 8017: gen_store_gpr(t0, rt);
! 8018: break;
! 8019: case 2:
! 8020: save_cpu_state(ctx, 1);
! 8021: gen_helper_rdhwr_cc(t0);
! 8022: gen_store_gpr(t0, rt);
! 8023: break;
! 8024: case 3:
! 8025: save_cpu_state(ctx, 1);
! 8026: gen_helper_rdhwr_ccres(t0);
! 8027: gen_store_gpr(t0, rt);
! 8028: break;
! 8029: case 29:
! 8030: #if defined(CONFIG_USER_ONLY)
! 8031: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
! 8032: gen_store_gpr(t0, rt);
! 8033: break;
! 8034: #else
! 8035: /* XXX: Some CPUs implement this in hardware.
! 8036: Not supported yet. */
1.1 root 8037: #endif
1.1.1.12! root 8038: default: /* Invalid */
! 8039: MIPS_INVAL("rdhwr");
! 8040: generate_exception(ctx, EXCP_RI);
! 8041: break;
1.1.1.4 root 8042: }
1.1.1.12! root 8043: tcg_temp_free(t0);
! 8044: }
1.1.1.4 root 8045:
1.1.1.12! root 8046: static void handle_delay_slot (CPUState *env, DisasContext *ctx,
! 8047: int insn_bytes)
! 8048: {
! 8049: if (ctx->hflags & MIPS_HFLAG_BMASK) {
! 8050: int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
! 8051: /* Branches completion */
! 8052: ctx->hflags &= ~MIPS_HFLAG_BMASK;
! 8053: ctx->bstate = BS_BRANCH;
! 8054: save_cpu_state(ctx, 0);
! 8055: /* FIXME: Need to clear can_do_io. */
! 8056: switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
! 8057: case MIPS_HFLAG_B:
! 8058: /* unconditional branch */
! 8059: MIPS_DEBUG("unconditional branch");
! 8060: if (proc_hflags & MIPS_HFLAG_BX) {
! 8061: tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
! 8062: }
! 8063: gen_goto_tb(ctx, 0, ctx->btarget);
! 8064: break;
! 8065: case MIPS_HFLAG_BL:
! 8066: /* blikely taken case */
! 8067: MIPS_DEBUG("blikely branch taken");
! 8068: gen_goto_tb(ctx, 0, ctx->btarget);
! 8069: break;
! 8070: case MIPS_HFLAG_BC:
! 8071: /* Conditional branch */
! 8072: MIPS_DEBUG("conditional branch");
! 8073: {
! 8074: int l1 = gen_new_label();
1.1.1.7 root 8075:
1.1.1.12! root 8076: tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
! 8077: gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
! 8078: gen_set_label(l1);
! 8079: gen_goto_tb(ctx, 0, ctx->btarget);
! 8080: }
! 8081: break;
! 8082: case MIPS_HFLAG_BR:
! 8083: /* unconditional branch to register */
! 8084: MIPS_DEBUG("branch to register");
! 8085: if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
! 8086: TCGv t0 = tcg_temp_new();
! 8087: TCGv_i32 t1 = tcg_temp_new_i32();
! 8088:
! 8089: tcg_gen_andi_tl(t0, btarget, 0x1);
! 8090: tcg_gen_trunc_tl_i32(t1, t0);
! 8091: tcg_temp_free(t0);
! 8092: tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
! 8093: tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
! 8094: tcg_gen_or_i32(hflags, hflags, t1);
! 8095: tcg_temp_free_i32(t1);
! 8096:
! 8097: tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
! 8098: } else {
! 8099: tcg_gen_mov_tl(cpu_PC, btarget);
! 8100: }
! 8101: if (ctx->singlestep_enabled) {
! 8102: save_cpu_state(ctx, 0);
! 8103: gen_helper_0i(raise_exception, EXCP_DEBUG);
! 8104: }
! 8105: tcg_gen_exit_tb(0);
! 8106: break;
! 8107: default:
! 8108: MIPS_DEBUG("unknown branch");
! 8109: break;
! 8110: }
! 8111: }
! 8112: }
! 8113:
! 8114: /* ISA extensions (ASEs) */
! 8115: /* MIPS16 extension to MIPS32 */
! 8116:
! 8117: /* MIPS16 major opcodes */
! 8118: enum {
! 8119: M16_OPC_ADDIUSP = 0x00,
! 8120: M16_OPC_ADDIUPC = 0x01,
! 8121: M16_OPC_B = 0x02,
! 8122: M16_OPC_JAL = 0x03,
! 8123: M16_OPC_BEQZ = 0x04,
! 8124: M16_OPC_BNEQZ = 0x05,
! 8125: M16_OPC_SHIFT = 0x06,
! 8126: M16_OPC_LD = 0x07,
! 8127: M16_OPC_RRIA = 0x08,
! 8128: M16_OPC_ADDIU8 = 0x09,
! 8129: M16_OPC_SLTI = 0x0a,
! 8130: M16_OPC_SLTIU = 0x0b,
! 8131: M16_OPC_I8 = 0x0c,
! 8132: M16_OPC_LI = 0x0d,
! 8133: M16_OPC_CMPI = 0x0e,
! 8134: M16_OPC_SD = 0x0f,
! 8135: M16_OPC_LB = 0x10,
! 8136: M16_OPC_LH = 0x11,
! 8137: M16_OPC_LWSP = 0x12,
! 8138: M16_OPC_LW = 0x13,
! 8139: M16_OPC_LBU = 0x14,
! 8140: M16_OPC_LHU = 0x15,
! 8141: M16_OPC_LWPC = 0x16,
! 8142: M16_OPC_LWU = 0x17,
! 8143: M16_OPC_SB = 0x18,
! 8144: M16_OPC_SH = 0x19,
! 8145: M16_OPC_SWSP = 0x1a,
! 8146: M16_OPC_SW = 0x1b,
! 8147: M16_OPC_RRR = 0x1c,
! 8148: M16_OPC_RR = 0x1d,
! 8149: M16_OPC_EXTEND = 0x1e,
! 8150: M16_OPC_I64 = 0x1f
! 8151: };
! 8152:
! 8153: /* I8 funct field */
! 8154: enum {
! 8155: I8_BTEQZ = 0x0,
! 8156: I8_BTNEZ = 0x1,
! 8157: I8_SWRASP = 0x2,
! 8158: I8_ADJSP = 0x3,
! 8159: I8_SVRS = 0x4,
! 8160: I8_MOV32R = 0x5,
! 8161: I8_MOVR32 = 0x7
! 8162: };
! 8163:
! 8164: /* RRR f field */
! 8165: enum {
! 8166: RRR_DADDU = 0x0,
! 8167: RRR_ADDU = 0x1,
! 8168: RRR_DSUBU = 0x2,
! 8169: RRR_SUBU = 0x3
! 8170: };
! 8171:
! 8172: /* RR funct field */
! 8173: enum {
! 8174: RR_JR = 0x00,
! 8175: RR_SDBBP = 0x01,
! 8176: RR_SLT = 0x02,
! 8177: RR_SLTU = 0x03,
! 8178: RR_SLLV = 0x04,
! 8179: RR_BREAK = 0x05,
! 8180: RR_SRLV = 0x06,
! 8181: RR_SRAV = 0x07,
! 8182: RR_DSRL = 0x08,
! 8183: RR_CMP = 0x0a,
! 8184: RR_NEG = 0x0b,
! 8185: RR_AND = 0x0c,
! 8186: RR_OR = 0x0d,
! 8187: RR_XOR = 0x0e,
! 8188: RR_NOT = 0x0f,
! 8189: RR_MFHI = 0x10,
! 8190: RR_CNVT = 0x11,
! 8191: RR_MFLO = 0x12,
! 8192: RR_DSRA = 0x13,
! 8193: RR_DSLLV = 0x14,
! 8194: RR_DSRLV = 0x16,
! 8195: RR_DSRAV = 0x17,
! 8196: RR_MULT = 0x18,
! 8197: RR_MULTU = 0x19,
! 8198: RR_DIV = 0x1a,
! 8199: RR_DIVU = 0x1b,
! 8200: RR_DMULT = 0x1c,
! 8201: RR_DMULTU = 0x1d,
! 8202: RR_DDIV = 0x1e,
! 8203: RR_DDIVU = 0x1f
! 8204: };
! 8205:
! 8206: /* I64 funct field */
! 8207: enum {
! 8208: I64_LDSP = 0x0,
! 8209: I64_SDSP = 0x1,
! 8210: I64_SDRASP = 0x2,
! 8211: I64_DADJSP = 0x3,
! 8212: I64_LDPC = 0x4,
! 8213: I64_DADDIU5 = 0x5,
! 8214: I64_DADDIUPC = 0x6,
! 8215: I64_DADDIUSP = 0x7
! 8216: };
! 8217:
! 8218: /* RR ry field for CNVT */
! 8219: enum {
! 8220: RR_RY_CNVT_ZEB = 0x0,
! 8221: RR_RY_CNVT_ZEH = 0x1,
! 8222: RR_RY_CNVT_ZEW = 0x2,
! 8223: RR_RY_CNVT_SEB = 0x4,
! 8224: RR_RY_CNVT_SEH = 0x5,
! 8225: RR_RY_CNVT_SEW = 0x6,
! 8226: };
! 8227:
! 8228: static int xlat (int r)
! 8229: {
! 8230: static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
! 8231:
! 8232: return map[r];
! 8233: }
! 8234:
! 8235: static void gen_mips16_save (DisasContext *ctx,
! 8236: int xsregs, int aregs,
! 8237: int do_ra, int do_s0, int do_s1,
! 8238: int framesize)
! 8239: {
! 8240: TCGv t0 = tcg_temp_new();
! 8241: TCGv t1 = tcg_temp_new();
! 8242: int args, astatic;
! 8243:
! 8244: switch (aregs) {
! 8245: case 0:
! 8246: case 1:
! 8247: case 2:
! 8248: case 3:
! 8249: case 11:
! 8250: args = 0;
! 8251: break;
! 8252: case 4:
! 8253: case 5:
! 8254: case 6:
! 8255: case 7:
! 8256: args = 1;
! 8257: break;
! 8258: case 8:
! 8259: case 9:
! 8260: case 10:
! 8261: args = 2;
! 8262: break;
! 8263: case 12:
! 8264: case 13:
! 8265: args = 3;
! 8266: break;
! 8267: case 14:
! 8268: args = 4;
! 8269: break;
! 8270: default:
! 8271: generate_exception(ctx, EXCP_RI);
! 8272: return;
! 8273: }
! 8274:
! 8275: switch (args) {
! 8276: case 4:
! 8277: gen_base_offset_addr(ctx, t0, 29, 12);
! 8278: gen_load_gpr(t1, 7);
! 8279: op_st_sw(t1, t0, ctx);
! 8280: /* Fall through */
! 8281: case 3:
! 8282: gen_base_offset_addr(ctx, t0, 29, 8);
! 8283: gen_load_gpr(t1, 6);
! 8284: op_st_sw(t1, t0, ctx);
! 8285: /* Fall through */
! 8286: case 2:
! 8287: gen_base_offset_addr(ctx, t0, 29, 4);
! 8288: gen_load_gpr(t1, 5);
! 8289: op_st_sw(t1, t0, ctx);
! 8290: /* Fall through */
! 8291: case 1:
! 8292: gen_base_offset_addr(ctx, t0, 29, 0);
! 8293: gen_load_gpr(t1, 4);
! 8294: op_st_sw(t1, t0, ctx);
! 8295: }
! 8296:
! 8297: gen_load_gpr(t0, 29);
! 8298:
! 8299: #define DECR_AND_STORE(reg) do { \
! 8300: tcg_gen_subi_tl(t0, t0, 4); \
! 8301: gen_load_gpr(t1, reg); \
! 8302: op_st_sw(t1, t0, ctx); \
! 8303: } while (0)
! 8304:
! 8305: if (do_ra) {
! 8306: DECR_AND_STORE(31);
! 8307: }
! 8308:
! 8309: switch (xsregs) {
! 8310: case 7:
! 8311: DECR_AND_STORE(30);
! 8312: /* Fall through */
! 8313: case 6:
! 8314: DECR_AND_STORE(23);
! 8315: /* Fall through */
! 8316: case 5:
! 8317: DECR_AND_STORE(22);
! 8318: /* Fall through */
! 8319: case 4:
! 8320: DECR_AND_STORE(21);
! 8321: /* Fall through */
! 8322: case 3:
! 8323: DECR_AND_STORE(20);
! 8324: /* Fall through */
! 8325: case 2:
! 8326: DECR_AND_STORE(19);
! 8327: /* Fall through */
! 8328: case 1:
! 8329: DECR_AND_STORE(18);
! 8330: }
! 8331:
! 8332: if (do_s1) {
! 8333: DECR_AND_STORE(17);
! 8334: }
! 8335: if (do_s0) {
! 8336: DECR_AND_STORE(16);
! 8337: }
! 8338:
! 8339: switch (aregs) {
! 8340: case 0:
! 8341: case 4:
! 8342: case 8:
! 8343: case 12:
! 8344: case 14:
! 8345: astatic = 0;
! 8346: break;
! 8347: case 1:
! 8348: case 5:
! 8349: case 9:
! 8350: case 13:
! 8351: astatic = 1;
! 8352: break;
! 8353: case 2:
! 8354: case 6:
! 8355: case 10:
! 8356: astatic = 2;
! 8357: break;
! 8358: case 3:
! 8359: case 7:
! 8360: astatic = 3;
! 8361: break;
! 8362: case 11:
! 8363: astatic = 4;
! 8364: break;
! 8365: default:
! 8366: generate_exception(ctx, EXCP_RI);
! 8367: return;
! 8368: }
! 8369:
! 8370: if (astatic > 0) {
! 8371: DECR_AND_STORE(7);
! 8372: if (astatic > 1) {
! 8373: DECR_AND_STORE(6);
! 8374: if (astatic > 2) {
! 8375: DECR_AND_STORE(5);
! 8376: if (astatic > 3) {
! 8377: DECR_AND_STORE(4);
! 8378: }
! 8379: }
! 8380: }
! 8381: }
! 8382: #undef DECR_AND_STORE
! 8383:
! 8384: tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
! 8385: tcg_temp_free(t0);
! 8386: tcg_temp_free(t1);
! 8387: }
! 8388:
! 8389: static void gen_mips16_restore (DisasContext *ctx,
! 8390: int xsregs, int aregs,
! 8391: int do_ra, int do_s0, int do_s1,
! 8392: int framesize)
! 8393: {
! 8394: int astatic;
! 8395: TCGv t0 = tcg_temp_new();
! 8396: TCGv t1 = tcg_temp_new();
! 8397:
! 8398: tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
! 8399:
! 8400: #define DECR_AND_LOAD(reg) do { \
! 8401: tcg_gen_subi_tl(t0, t0, 4); \
! 8402: op_ld_lw(t1, t0, ctx); \
! 8403: gen_store_gpr(t1, reg); \
! 8404: } while (0)
! 8405:
! 8406: if (do_ra) {
! 8407: DECR_AND_LOAD(31);
! 8408: }
! 8409:
! 8410: switch (xsregs) {
! 8411: case 7:
! 8412: DECR_AND_LOAD(30);
! 8413: /* Fall through */
! 8414: case 6:
! 8415: DECR_AND_LOAD(23);
! 8416: /* Fall through */
! 8417: case 5:
! 8418: DECR_AND_LOAD(22);
! 8419: /* Fall through */
! 8420: case 4:
! 8421: DECR_AND_LOAD(21);
! 8422: /* Fall through */
! 8423: case 3:
! 8424: DECR_AND_LOAD(20);
! 8425: /* Fall through */
! 8426: case 2:
! 8427: DECR_AND_LOAD(19);
! 8428: /* Fall through */
! 8429: case 1:
! 8430: DECR_AND_LOAD(18);
! 8431: }
! 8432:
! 8433: if (do_s1) {
! 8434: DECR_AND_LOAD(17);
! 8435: }
! 8436: if (do_s0) {
! 8437: DECR_AND_LOAD(16);
! 8438: }
! 8439:
! 8440: switch (aregs) {
! 8441: case 0:
! 8442: case 4:
! 8443: case 8:
! 8444: case 12:
! 8445: case 14:
! 8446: astatic = 0;
! 8447: break;
! 8448: case 1:
! 8449: case 5:
! 8450: case 9:
! 8451: case 13:
! 8452: astatic = 1;
! 8453: break;
! 8454: case 2:
! 8455: case 6:
! 8456: case 10:
! 8457: astatic = 2;
! 8458: break;
! 8459: case 3:
! 8460: case 7:
! 8461: astatic = 3;
! 8462: break;
! 8463: case 11:
! 8464: astatic = 4;
! 8465: break;
! 8466: default:
! 8467: generate_exception(ctx, EXCP_RI);
! 8468: return;
! 8469: }
! 8470:
! 8471: if (astatic > 0) {
! 8472: DECR_AND_LOAD(7);
! 8473: if (astatic > 1) {
! 8474: DECR_AND_LOAD(6);
! 8475: if (astatic > 2) {
! 8476: DECR_AND_LOAD(5);
! 8477: if (astatic > 3) {
! 8478: DECR_AND_LOAD(4);
! 8479: }
! 8480: }
! 8481: }
! 8482: }
! 8483: #undef DECR_AND_LOAD
! 8484:
! 8485: tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
! 8486: tcg_temp_free(t0);
! 8487: tcg_temp_free(t1);
! 8488: }
! 8489:
! 8490: static void gen_addiupc (DisasContext *ctx, int rx, int imm,
! 8491: int is_64_bit, int extended)
! 8492: {
! 8493: TCGv t0;
! 8494:
! 8495: if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
! 8496: generate_exception(ctx, EXCP_RI);
! 8497: return;
! 8498: }
! 8499:
! 8500: t0 = tcg_temp_new();
! 8501:
! 8502: tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
! 8503: tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
! 8504: if (!is_64_bit) {
! 8505: tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
! 8506: }
! 8507:
! 8508: tcg_temp_free(t0);
! 8509: }
! 8510:
! 8511: #if defined(TARGET_MIPS64)
! 8512: static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
! 8513: int ry, int funct, int16_t offset,
! 8514: int extended)
! 8515: {
! 8516: switch (funct) {
! 8517: case I64_LDSP:
! 8518: check_mips_64(ctx);
! 8519: offset = extended ? offset : offset << 3;
! 8520: gen_ld(env, ctx, OPC_LD, ry, 29, offset);
! 8521: break;
! 8522: case I64_SDSP:
! 8523: check_mips_64(ctx);
! 8524: offset = extended ? offset : offset << 3;
! 8525: gen_st(ctx, OPC_SD, ry, 29, offset);
! 8526: break;
! 8527: case I64_SDRASP:
! 8528: check_mips_64(ctx);
! 8529: offset = extended ? offset : (ctx->opcode & 0xff) << 3;
! 8530: gen_st(ctx, OPC_SD, 31, 29, offset);
! 8531: break;
! 8532: case I64_DADJSP:
! 8533: check_mips_64(ctx);
! 8534: offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
! 8535: gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
! 8536: break;
! 8537: case I64_LDPC:
! 8538: if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
! 8539: generate_exception(ctx, EXCP_RI);
! 8540: } else {
! 8541: offset = extended ? offset : offset << 3;
! 8542: gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
! 8543: }
! 8544: break;
! 8545: case I64_DADDIU5:
! 8546: check_mips_64(ctx);
! 8547: offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
! 8548: gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
! 8549: break;
! 8550: case I64_DADDIUPC:
! 8551: check_mips_64(ctx);
! 8552: offset = extended ? offset : offset << 2;
! 8553: gen_addiupc(ctx, ry, offset, 1, extended);
! 8554: break;
! 8555: case I64_DADDIUSP:
! 8556: check_mips_64(ctx);
! 8557: offset = extended ? offset : offset << 2;
! 8558: gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
! 8559: break;
! 8560: }
! 8561: }
! 8562: #endif
! 8563:
! 8564: static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
! 8565: int *is_branch)
! 8566: {
! 8567: int extend = lduw_code(ctx->pc + 2);
! 8568: int op, rx, ry, funct, sa;
! 8569: int16_t imm, offset;
! 8570:
! 8571: ctx->opcode = (ctx->opcode << 16) | extend;
! 8572: op = (ctx->opcode >> 11) & 0x1f;
! 8573: sa = (ctx->opcode >> 22) & 0x1f;
! 8574: funct = (ctx->opcode >> 8) & 0x7;
! 8575: rx = xlat((ctx->opcode >> 8) & 0x7);
! 8576: ry = xlat((ctx->opcode >> 5) & 0x7);
! 8577: offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
! 8578: | ((ctx->opcode >> 21) & 0x3f) << 5
! 8579: | (ctx->opcode & 0x1f));
! 8580:
! 8581: /* The extended opcodes cleverly reuse the opcodes from their 16-bit
! 8582: counterparts. */
! 8583: switch (op) {
! 8584: case M16_OPC_ADDIUSP:
! 8585: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
! 8586: break;
! 8587: case M16_OPC_ADDIUPC:
! 8588: gen_addiupc(ctx, rx, imm, 0, 1);
! 8589: break;
! 8590: case M16_OPC_B:
! 8591: gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
! 8592: /* No delay slot, so just process as a normal instruction */
! 8593: break;
! 8594: case M16_OPC_BEQZ:
! 8595: gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
! 8596: /* No delay slot, so just process as a normal instruction */
! 8597: break;
! 8598: case M16_OPC_BNEQZ:
! 8599: gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
! 8600: /* No delay slot, so just process as a normal instruction */
! 8601: break;
! 8602: case M16_OPC_SHIFT:
! 8603: switch (ctx->opcode & 0x3) {
! 8604: case 0x0:
! 8605: gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
! 8606: break;
! 8607: case 0x1:
! 8608: #if defined(TARGET_MIPS64)
! 8609: check_mips_64(ctx);
! 8610: gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
! 8611: #else
! 8612: generate_exception(ctx, EXCP_RI);
! 8613: #endif
! 8614: break;
! 8615: case 0x2:
! 8616: gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
! 8617: break;
! 8618: case 0x3:
! 8619: gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
! 8620: break;
! 8621: }
! 8622: break;
! 8623: #if defined(TARGET_MIPS64)
! 8624: case M16_OPC_LD:
! 8625: check_mips_64(ctx);
! 8626: gen_ld(env, ctx, OPC_LD, ry, rx, offset);
! 8627: break;
! 8628: #endif
! 8629: case M16_OPC_RRIA:
! 8630: imm = ctx->opcode & 0xf;
! 8631: imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
! 8632: imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
! 8633: imm = (int16_t) (imm << 1) >> 1;
! 8634: if ((ctx->opcode >> 4) & 0x1) {
! 8635: #if defined(TARGET_MIPS64)
! 8636: check_mips_64(ctx);
! 8637: gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
! 8638: #else
! 8639: generate_exception(ctx, EXCP_RI);
! 8640: #endif
! 8641: } else {
! 8642: gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
! 8643: }
! 8644: break;
! 8645: case M16_OPC_ADDIU8:
! 8646: gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
! 8647: break;
! 8648: case M16_OPC_SLTI:
! 8649: gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
! 8650: break;
! 8651: case M16_OPC_SLTIU:
! 8652: gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
! 8653: break;
! 8654: case M16_OPC_I8:
! 8655: switch (funct) {
! 8656: case I8_BTEQZ:
! 8657: gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
! 8658: break;
! 8659: case I8_BTNEZ:
! 8660: gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
! 8661: break;
! 8662: case I8_SWRASP:
! 8663: gen_st(ctx, OPC_SW, 31, 29, imm);
! 8664: break;
! 8665: case I8_ADJSP:
! 8666: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
! 8667: break;
! 8668: case I8_SVRS:
! 8669: {
! 8670: int xsregs = (ctx->opcode >> 24) & 0x7;
! 8671: int aregs = (ctx->opcode >> 16) & 0xf;
! 8672: int do_ra = (ctx->opcode >> 6) & 0x1;
! 8673: int do_s0 = (ctx->opcode >> 5) & 0x1;
! 8674: int do_s1 = (ctx->opcode >> 4) & 0x1;
! 8675: int framesize = (((ctx->opcode >> 20) & 0xf) << 4
! 8676: | (ctx->opcode & 0xf)) << 3;
! 8677:
! 8678: if (ctx->opcode & (1 << 7)) {
! 8679: gen_mips16_save(ctx, xsregs, aregs,
! 8680: do_ra, do_s0, do_s1,
! 8681: framesize);
! 8682: } else {
! 8683: gen_mips16_restore(ctx, xsregs, aregs,
! 8684: do_ra, do_s0, do_s1,
! 8685: framesize);
! 8686: }
! 8687: }
! 8688: break;
! 8689: default:
! 8690: generate_exception(ctx, EXCP_RI);
! 8691: break;
! 8692: }
! 8693: break;
! 8694: case M16_OPC_LI:
! 8695: tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
! 8696: break;
! 8697: case M16_OPC_CMPI:
! 8698: tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
! 8699: break;
! 8700: #if defined(TARGET_MIPS64)
! 8701: case M16_OPC_SD:
! 8702: gen_st(ctx, OPC_SD, ry, rx, offset);
! 8703: break;
! 8704: #endif
! 8705: case M16_OPC_LB:
! 8706: gen_ld(env, ctx, OPC_LB, ry, rx, offset);
! 8707: break;
! 8708: case M16_OPC_LH:
! 8709: gen_ld(env, ctx, OPC_LH, ry, rx, offset);
! 8710: break;
! 8711: case M16_OPC_LWSP:
! 8712: gen_ld(env, ctx, OPC_LW, rx, 29, offset);
! 8713: break;
! 8714: case M16_OPC_LW:
! 8715: gen_ld(env, ctx, OPC_LW, ry, rx, offset);
! 8716: break;
! 8717: case M16_OPC_LBU:
! 8718: gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
! 8719: break;
! 8720: case M16_OPC_LHU:
! 8721: gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
! 8722: break;
! 8723: case M16_OPC_LWPC:
! 8724: gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
! 8725: break;
! 8726: #if defined(TARGET_MIPS64)
! 8727: case M16_OPC_LWU:
! 8728: gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
! 8729: break;
! 8730: #endif
! 8731: case M16_OPC_SB:
! 8732: gen_st(ctx, OPC_SB, ry, rx, offset);
! 8733: break;
! 8734: case M16_OPC_SH:
! 8735: gen_st(ctx, OPC_SH, ry, rx, offset);
! 8736: break;
! 8737: case M16_OPC_SWSP:
! 8738: gen_st(ctx, OPC_SW, rx, 29, offset);
! 8739: break;
! 8740: case M16_OPC_SW:
! 8741: gen_st(ctx, OPC_SW, ry, rx, offset);
! 8742: break;
! 8743: #if defined(TARGET_MIPS64)
! 8744: case M16_OPC_I64:
! 8745: decode_i64_mips16(env, ctx, ry, funct, offset, 1);
! 8746: break;
! 8747: #endif
! 8748: default:
! 8749: generate_exception(ctx, EXCP_RI);
! 8750: break;
! 8751: }
! 8752:
! 8753: return 4;
! 8754: }
! 8755:
! 8756: static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
! 8757: int *is_branch)
! 8758: {
! 8759: int rx, ry;
! 8760: int sa;
! 8761: int op, cnvt_op, op1, offset;
! 8762: int funct;
! 8763: int n_bytes;
! 8764:
! 8765: op = (ctx->opcode >> 11) & 0x1f;
! 8766: sa = (ctx->opcode >> 2) & 0x7;
! 8767: sa = sa == 0 ? 8 : sa;
! 8768: rx = xlat((ctx->opcode >> 8) & 0x7);
! 8769: cnvt_op = (ctx->opcode >> 5) & 0x7;
! 8770: ry = xlat((ctx->opcode >> 5) & 0x7);
! 8771: op1 = offset = ctx->opcode & 0x1f;
! 8772:
! 8773: n_bytes = 2;
! 8774:
! 8775: switch (op) {
! 8776: case M16_OPC_ADDIUSP:
! 8777: {
! 8778: int16_t imm = ((uint8_t) ctx->opcode) << 2;
! 8779:
! 8780: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
! 8781: }
! 8782: break;
! 8783: case M16_OPC_ADDIUPC:
! 8784: gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
! 8785: break;
! 8786: case M16_OPC_B:
! 8787: offset = (ctx->opcode & 0x7ff) << 1;
! 8788: offset = (int16_t)(offset << 4) >> 4;
! 8789: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
! 8790: /* No delay slot, so just process as a normal instruction */
! 8791: break;
! 8792: case M16_OPC_JAL:
! 8793: offset = lduw_code(ctx->pc + 2);
! 8794: offset = (((ctx->opcode & 0x1f) << 21)
! 8795: | ((ctx->opcode >> 5) & 0x1f) << 16
! 8796: | offset) << 2;
! 8797: op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
! 8798: gen_compute_branch(ctx, op, 4, rx, ry, offset);
! 8799: n_bytes = 4;
! 8800: *is_branch = 1;
! 8801: break;
! 8802: case M16_OPC_BEQZ:
! 8803: gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
! 8804: /* No delay slot, so just process as a normal instruction */
! 8805: break;
! 8806: case M16_OPC_BNEQZ:
! 8807: gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
! 8808: /* No delay slot, so just process as a normal instruction */
! 8809: break;
! 8810: case M16_OPC_SHIFT:
! 8811: switch (ctx->opcode & 0x3) {
! 8812: case 0x0:
! 8813: gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
! 8814: break;
! 8815: case 0x1:
! 8816: #if defined(TARGET_MIPS64)
! 8817: check_mips_64(ctx);
! 8818: gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
! 8819: #else
! 8820: generate_exception(ctx, EXCP_RI);
! 8821: #endif
! 8822: break;
! 8823: case 0x2:
! 8824: gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
! 8825: break;
! 8826: case 0x3:
! 8827: gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
! 8828: break;
! 8829: }
! 8830: break;
! 8831: #if defined(TARGET_MIPS64)
! 8832: case M16_OPC_LD:
! 8833: check_mips_64(ctx);
! 8834: gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
! 8835: break;
! 8836: #endif
! 8837: case M16_OPC_RRIA:
! 8838: {
! 8839: int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
! 8840:
! 8841: if ((ctx->opcode >> 4) & 1) {
! 8842: #if defined(TARGET_MIPS64)
! 8843: check_mips_64(ctx);
! 8844: gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
! 8845: #else
! 8846: generate_exception(ctx, EXCP_RI);
! 8847: #endif
! 8848: } else {
! 8849: gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
! 8850: }
! 8851: }
! 8852: break;
! 8853: case M16_OPC_ADDIU8:
! 8854: {
! 8855: int16_t imm = (int8_t) ctx->opcode;
! 8856:
! 8857: gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
! 8858: }
! 8859: break;
! 8860: case M16_OPC_SLTI:
! 8861: {
! 8862: int16_t imm = (uint8_t) ctx->opcode;
! 8863:
! 8864: gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
! 8865: }
! 8866: break;
! 8867: case M16_OPC_SLTIU:
! 8868: {
! 8869: int16_t imm = (uint8_t) ctx->opcode;
! 8870:
! 8871: gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
! 8872: }
! 8873: break;
! 8874: case M16_OPC_I8:
! 8875: {
! 8876: int reg32;
! 8877:
! 8878: funct = (ctx->opcode >> 8) & 0x7;
! 8879: switch (funct) {
! 8880: case I8_BTEQZ:
! 8881: gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
! 8882: ((int8_t)ctx->opcode) << 1);
! 8883: break;
! 8884: case I8_BTNEZ:
! 8885: gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
! 8886: ((int8_t)ctx->opcode) << 1);
! 8887: break;
! 8888: case I8_SWRASP:
! 8889: gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
! 8890: break;
! 8891: case I8_ADJSP:
! 8892: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
! 8893: ((int8_t)ctx->opcode) << 3);
! 8894: break;
! 8895: case I8_SVRS:
! 8896: {
! 8897: int do_ra = ctx->opcode & (1 << 6);
! 8898: int do_s0 = ctx->opcode & (1 << 5);
! 8899: int do_s1 = ctx->opcode & (1 << 4);
! 8900: int framesize = ctx->opcode & 0xf;
! 8901:
! 8902: if (framesize == 0) {
! 8903: framesize = 128;
! 8904: } else {
! 8905: framesize = framesize << 3;
! 8906: }
! 8907:
! 8908: if (ctx->opcode & (1 << 7)) {
! 8909: gen_mips16_save(ctx, 0, 0,
! 8910: do_ra, do_s0, do_s1, framesize);
! 8911: } else {
! 8912: gen_mips16_restore(ctx, 0, 0,
! 8913: do_ra, do_s0, do_s1, framesize);
! 8914: }
! 8915: }
! 8916: break;
! 8917: case I8_MOV32R:
! 8918: {
! 8919: int rz = xlat(ctx->opcode & 0x7);
! 8920:
! 8921: reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
! 8922: ((ctx->opcode >> 5) & 0x7);
! 8923: gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
! 8924: }
! 8925: break;
! 8926: case I8_MOVR32:
! 8927: reg32 = ctx->opcode & 0x1f;
! 8928: gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
! 8929: break;
! 8930: default:
! 8931: generate_exception(ctx, EXCP_RI);
! 8932: break;
! 8933: }
! 8934: }
! 8935: break;
! 8936: case M16_OPC_LI:
! 8937: {
! 8938: int16_t imm = (uint8_t) ctx->opcode;
! 8939:
! 8940: gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
! 8941: }
! 8942: break;
! 8943: case M16_OPC_CMPI:
! 8944: {
! 8945: int16_t imm = (uint8_t) ctx->opcode;
! 8946:
! 8947: gen_logic_imm(env, OPC_XORI, 24, rx, imm);
! 8948: }
! 8949: break;
! 8950: #if defined(TARGET_MIPS64)
! 8951: case M16_OPC_SD:
! 8952: check_mips_64(ctx);
! 8953: gen_st(ctx, OPC_SD, ry, rx, offset << 3);
! 8954: break;
! 8955: #endif
! 8956: case M16_OPC_LB:
! 8957: gen_ld(env, ctx, OPC_LB, ry, rx, offset);
! 8958: break;
! 8959: case M16_OPC_LH:
! 8960: gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
! 8961: break;
! 8962: case M16_OPC_LWSP:
! 8963: gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
! 8964: break;
! 8965: case M16_OPC_LW:
! 8966: gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
! 8967: break;
! 8968: case M16_OPC_LBU:
! 8969: gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
! 8970: break;
! 8971: case M16_OPC_LHU:
! 8972: gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
! 8973: break;
! 8974: case M16_OPC_LWPC:
! 8975: gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
! 8976: break;
! 8977: #if defined (TARGET_MIPS64)
! 8978: case M16_OPC_LWU:
! 8979: check_mips_64(ctx);
! 8980: gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
! 8981: break;
! 8982: #endif
! 8983: case M16_OPC_SB:
! 8984: gen_st(ctx, OPC_SB, ry, rx, offset);
! 8985: break;
! 8986: case M16_OPC_SH:
! 8987: gen_st(ctx, OPC_SH, ry, rx, offset << 1);
! 8988: break;
! 8989: case M16_OPC_SWSP:
! 8990: gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
! 8991: break;
! 8992: case M16_OPC_SW:
! 8993: gen_st(ctx, OPC_SW, ry, rx, offset << 2);
! 8994: break;
! 8995: case M16_OPC_RRR:
! 8996: {
! 8997: int rz = xlat((ctx->opcode >> 2) & 0x7);
! 8998: int mips32_op;
! 8999:
! 9000: switch (ctx->opcode & 0x3) {
! 9001: case RRR_ADDU:
! 9002: mips32_op = OPC_ADDU;
! 9003: break;
! 9004: case RRR_SUBU:
! 9005: mips32_op = OPC_SUBU;
! 9006: break;
! 9007: #if defined(TARGET_MIPS64)
! 9008: case RRR_DADDU:
! 9009: mips32_op = OPC_DADDU;
! 9010: check_mips_64(ctx);
! 9011: break;
! 9012: case RRR_DSUBU:
! 9013: mips32_op = OPC_DSUBU;
! 9014: check_mips_64(ctx);
! 9015: break;
! 9016: #endif
! 9017: default:
! 9018: generate_exception(ctx, EXCP_RI);
! 9019: goto done;
! 9020: }
! 9021:
! 9022: gen_arith(env, ctx, mips32_op, rz, rx, ry);
! 9023: done:
! 9024: ;
! 9025: }
! 9026: break;
! 9027: case M16_OPC_RR:
! 9028: switch (op1) {
! 9029: case RR_JR:
! 9030: {
! 9031: int nd = (ctx->opcode >> 7) & 0x1;
! 9032: int link = (ctx->opcode >> 6) & 0x1;
! 9033: int ra = (ctx->opcode >> 5) & 0x1;
! 9034:
! 9035: if (link) {
! 9036: op = nd ? OPC_JALRC : OPC_JALRS;
! 9037: } else {
! 9038: op = OPC_JR;
! 9039: }
! 9040:
! 9041: gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
! 9042: if (!nd) {
! 9043: *is_branch = 1;
! 9044: }
! 9045: }
! 9046: break;
! 9047: case RR_SDBBP:
! 9048: /* XXX: not clear which exception should be raised
! 9049: * when in debug mode...
! 9050: */
! 9051: check_insn(env, ctx, ISA_MIPS32);
! 9052: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
! 9053: generate_exception(ctx, EXCP_DBp);
! 9054: } else {
! 9055: generate_exception(ctx, EXCP_DBp);
! 9056: }
! 9057: break;
! 9058: case RR_SLT:
! 9059: gen_slt(env, OPC_SLT, 24, rx, ry);
! 9060: break;
! 9061: case RR_SLTU:
! 9062: gen_slt(env, OPC_SLTU, 24, rx, ry);
! 9063: break;
! 9064: case RR_BREAK:
! 9065: generate_exception(ctx, EXCP_BREAK);
! 9066: break;
! 9067: case RR_SLLV:
! 9068: gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
! 9069: break;
! 9070: case RR_SRLV:
! 9071: gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
! 9072: break;
! 9073: case RR_SRAV:
! 9074: gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
! 9075: break;
! 9076: #if defined (TARGET_MIPS64)
! 9077: case RR_DSRL:
! 9078: check_mips_64(ctx);
! 9079: gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
! 9080: break;
! 9081: #endif
! 9082: case RR_CMP:
! 9083: gen_logic(env, OPC_XOR, 24, rx, ry);
! 9084: break;
! 9085: case RR_NEG:
! 9086: gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
! 9087: break;
! 9088: case RR_AND:
! 9089: gen_logic(env, OPC_AND, rx, rx, ry);
! 9090: break;
! 9091: case RR_OR:
! 9092: gen_logic(env, OPC_OR, rx, rx, ry);
! 9093: break;
! 9094: case RR_XOR:
! 9095: gen_logic(env, OPC_XOR, rx, rx, ry);
! 9096: break;
! 9097: case RR_NOT:
! 9098: gen_logic(env, OPC_NOR, rx, ry, 0);
! 9099: break;
! 9100: case RR_MFHI:
! 9101: gen_HILO(ctx, OPC_MFHI, rx);
! 9102: break;
! 9103: case RR_CNVT:
! 9104: switch (cnvt_op) {
! 9105: case RR_RY_CNVT_ZEB:
! 9106: tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
! 9107: break;
! 9108: case RR_RY_CNVT_ZEH:
! 9109: tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
! 9110: break;
! 9111: case RR_RY_CNVT_SEB:
! 9112: tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
! 9113: break;
! 9114: case RR_RY_CNVT_SEH:
! 9115: tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
! 9116: break;
! 9117: #if defined (TARGET_MIPS64)
! 9118: case RR_RY_CNVT_ZEW:
! 9119: check_mips_64(ctx);
! 9120: tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
! 9121: break;
! 9122: case RR_RY_CNVT_SEW:
! 9123: check_mips_64(ctx);
! 9124: tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
! 9125: break;
! 9126: #endif
! 9127: default:
! 9128: generate_exception(ctx, EXCP_RI);
! 9129: break;
! 9130: }
! 9131: break;
! 9132: case RR_MFLO:
! 9133: gen_HILO(ctx, OPC_MFLO, rx);
! 9134: break;
! 9135: #if defined (TARGET_MIPS64)
! 9136: case RR_DSRA:
! 9137: check_mips_64(ctx);
! 9138: gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
! 9139: break;
! 9140: case RR_DSLLV:
! 9141: check_mips_64(ctx);
! 9142: gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
! 9143: break;
! 9144: case RR_DSRLV:
! 9145: check_mips_64(ctx);
! 9146: gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
! 9147: break;
! 9148: case RR_DSRAV:
! 9149: check_mips_64(ctx);
! 9150: gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
! 9151: break;
! 9152: #endif
! 9153: case RR_MULT:
! 9154: gen_muldiv(ctx, OPC_MULT, rx, ry);
! 9155: break;
! 9156: case RR_MULTU:
! 9157: gen_muldiv(ctx, OPC_MULTU, rx, ry);
! 9158: break;
! 9159: case RR_DIV:
! 9160: gen_muldiv(ctx, OPC_DIV, rx, ry);
! 9161: break;
! 9162: case RR_DIVU:
! 9163: gen_muldiv(ctx, OPC_DIVU, rx, ry);
! 9164: break;
! 9165: #if defined (TARGET_MIPS64)
! 9166: case RR_DMULT:
! 9167: check_mips_64(ctx);
! 9168: gen_muldiv(ctx, OPC_DMULT, rx, ry);
! 9169: break;
! 9170: case RR_DMULTU:
! 9171: check_mips_64(ctx);
! 9172: gen_muldiv(ctx, OPC_DMULTU, rx, ry);
! 9173: break;
! 9174: case RR_DDIV:
! 9175: check_mips_64(ctx);
! 9176: gen_muldiv(ctx, OPC_DDIV, rx, ry);
! 9177: break;
! 9178: case RR_DDIVU:
! 9179: check_mips_64(ctx);
! 9180: gen_muldiv(ctx, OPC_DDIVU, rx, ry);
! 9181: break;
! 9182: #endif
! 9183: default:
! 9184: generate_exception(ctx, EXCP_RI);
! 9185: break;
! 9186: }
! 9187: break;
! 9188: case M16_OPC_EXTEND:
! 9189: decode_extended_mips16_opc(env, ctx, is_branch);
! 9190: n_bytes = 4;
! 9191: break;
! 9192: #if defined(TARGET_MIPS64)
! 9193: case M16_OPC_I64:
! 9194: funct = (ctx->opcode >> 8) & 0x7;
! 9195: decode_i64_mips16(env, ctx, ry, funct, offset, 0);
! 9196: break;
! 9197: #endif
! 9198: default:
! 9199: generate_exception(ctx, EXCP_RI);
! 9200: break;
! 9201: }
! 9202:
! 9203: return n_bytes;
! 9204: }
! 9205:
! 9206: /* microMIPS extension to MIPS32 */
! 9207:
! 9208: /* microMIPS32 major opcodes */
! 9209:
! 9210: enum {
! 9211: POOL32A = 0x00,
! 9212: POOL16A = 0x01,
! 9213: LBU16 = 0x02,
! 9214: MOVE16 = 0x03,
! 9215: ADDI32 = 0x04,
! 9216: LBU32 = 0x05,
! 9217: SB32 = 0x06,
! 9218: LB32 = 0x07,
! 9219:
! 9220: POOL32B = 0x08,
! 9221: POOL16B = 0x09,
! 9222: LHU16 = 0x0a,
! 9223: ANDI16 = 0x0b,
! 9224: ADDIU32 = 0x0c,
! 9225: LHU32 = 0x0d,
! 9226: SH32 = 0x0e,
! 9227: LH32 = 0x0f,
! 9228:
! 9229: POOL32I = 0x10,
! 9230: POOL16C = 0x11,
! 9231: LWSP16 = 0x12,
! 9232: POOL16D = 0x13,
! 9233: ORI32 = 0x14,
! 9234: POOL32F = 0x15,
! 9235: POOL32S = 0x16,
! 9236: DADDIU32 = 0x17,
! 9237:
! 9238: POOL32C = 0x18,
! 9239: LWGP16 = 0x19,
! 9240: LW16 = 0x1a,
! 9241: POOL16E = 0x1b,
! 9242: XORI32 = 0x1c,
! 9243: JALS32 = 0x1d,
! 9244: ADDIUPC = 0x1e,
! 9245: POOL48A = 0x1f,
! 9246:
! 9247: /* 0x20 is reserved */
! 9248: RES_20 = 0x20,
! 9249: POOL16F = 0x21,
! 9250: SB16 = 0x22,
! 9251: BEQZ16 = 0x23,
! 9252: SLTI32 = 0x24,
! 9253: BEQ32 = 0x25,
! 9254: SWC132 = 0x26,
! 9255: LWC132 = 0x27,
! 9256:
! 9257: /* 0x28 and 0x29 are reserved */
! 9258: RES_28 = 0x28,
! 9259: RES_29 = 0x29,
! 9260: SH16 = 0x2a,
! 9261: BNEZ16 = 0x2b,
! 9262: SLTIU32 = 0x2c,
! 9263: BNE32 = 0x2d,
! 9264: SDC132 = 0x2e,
! 9265: LDC132 = 0x2f,
! 9266:
! 9267: /* 0x30 and 0x31 are reserved */
! 9268: RES_30 = 0x30,
! 9269: RES_31 = 0x31,
! 9270: SWSP16 = 0x32,
! 9271: B16 = 0x33,
! 9272: ANDI32 = 0x34,
! 9273: J32 = 0x35,
! 9274: SD32 = 0x36,
! 9275: LD32 = 0x37,
! 9276:
! 9277: /* 0x38 and 0x39 are reserved */
! 9278: RES_38 = 0x38,
! 9279: RES_39 = 0x39,
! 9280: SW16 = 0x3a,
! 9281: LI16 = 0x3b,
! 9282: JALX32 = 0x3c,
! 9283: JAL32 = 0x3d,
! 9284: SW32 = 0x3e,
! 9285: LW32 = 0x3f
! 9286: };
! 9287:
! 9288: /* POOL32A encoding of minor opcode field */
! 9289:
! 9290: enum {
! 9291: /* These opcodes are distinguished only by bits 9..6; those bits are
! 9292: * what are recorded below. */
! 9293: SLL32 = 0x0,
! 9294: SRL32 = 0x1,
! 9295: SRA = 0x2,
! 9296: ROTR = 0x3,
! 9297:
! 9298: SLLV = 0x0,
! 9299: SRLV = 0x1,
! 9300: SRAV = 0x2,
! 9301: ROTRV = 0x3,
! 9302: ADD = 0x4,
! 9303: ADDU32 = 0x5,
! 9304: SUB = 0x6,
! 9305: SUBU32 = 0x7,
! 9306: MUL = 0x8,
! 9307: AND = 0x9,
! 9308: OR32 = 0xa,
! 9309: NOR = 0xb,
! 9310: XOR32 = 0xc,
! 9311: SLT = 0xd,
! 9312: SLTU = 0xe,
! 9313:
! 9314: MOVN = 0x0,
! 9315: MOVZ = 0x1,
! 9316: LWXS = 0x4,
! 9317:
! 9318: /* The following can be distinguished by their lower 6 bits. */
! 9319: INS = 0x0c,
! 9320: EXT = 0x2c,
! 9321: POOL32AXF = 0x3c
! 9322: };
! 9323:
! 9324: /* POOL32AXF encoding of minor opcode field extension */
! 9325:
! 9326: enum {
! 9327: /* bits 11..6 */
! 9328: TEQ = 0x00,
! 9329: TGE = 0x08,
! 9330: TGEU = 0x10,
! 9331: TLT = 0x20,
! 9332: TLTU = 0x28,
! 9333: TNE = 0x30,
! 9334:
! 9335: MFC0 = 0x03,
! 9336: MTC0 = 0x0b,
! 9337:
! 9338: /* bits 13..12 for 0x01 */
! 9339: MFHI_ACC = 0x0,
! 9340: MFLO_ACC = 0x1,
! 9341: MTHI_ACC = 0x2,
! 9342: MTLO_ACC = 0x3,
! 9343:
! 9344: /* bits 13..12 for 0x2a */
! 9345: MADD_ACC = 0x0,
! 9346: MADDU_ACC = 0x1,
! 9347: MSUB_ACC = 0x2,
! 9348: MSUBU_ACC = 0x3,
! 9349:
! 9350: /* bits 13..12 for 0x32 */
! 9351: MULT_ACC = 0x0,
! 9352: MULTU_ACC = 0x0,
! 9353:
! 9354: /* bits 15..12 for 0x2c */
! 9355: SEB = 0x2,
! 9356: SEH = 0x3,
! 9357: CLO = 0x4,
! 9358: CLZ = 0x5,
! 9359: RDHWR = 0x6,
! 9360: WSBH = 0x7,
! 9361: MULT = 0x8,
! 9362: MULTU = 0x9,
! 9363: DIV = 0xa,
! 9364: DIVU = 0xb,
! 9365: MADD = 0xc,
! 9366: MADDU = 0xd,
! 9367: MSUB = 0xe,
! 9368: MSUBU = 0xf,
! 9369:
! 9370: /* bits 15..12 for 0x34 */
! 9371: MFC2 = 0x4,
! 9372: MTC2 = 0x5,
! 9373: MFHC2 = 0x8,
! 9374: MTHC2 = 0x9,
! 9375: CFC2 = 0xc,
! 9376: CTC2 = 0xd,
! 9377:
! 9378: /* bits 15..12 for 0x3c */
! 9379: JALR = 0x0,
! 9380: JR = 0x0, /* alias */
! 9381: JALR_HB = 0x1,
! 9382: JALRS = 0x4,
! 9383: JALRS_HB = 0x5,
! 9384:
! 9385: /* bits 15..12 for 0x05 */
! 9386: RDPGPR = 0xe,
! 9387: WRPGPR = 0xf,
! 9388:
! 9389: /* bits 15..12 for 0x0d */
! 9390: TLBP = 0x0,
! 9391: TLBR = 0x1,
! 9392: TLBWI = 0x2,
! 9393: TLBWR = 0x3,
! 9394: WAIT = 0x9,
! 9395: IRET = 0xd,
! 9396: DERET = 0xe,
! 9397: ERET = 0xf,
! 9398:
! 9399: /* bits 15..12 for 0x15 */
! 9400: DMT = 0x0,
! 9401: DVPE = 0x1,
! 9402: EMT = 0x2,
! 9403: EVPE = 0x3,
! 9404:
! 9405: /* bits 15..12 for 0x1d */
! 9406: DI = 0x4,
! 9407: EI = 0x5,
! 9408:
! 9409: /* bits 15..12 for 0x2d */
! 9410: SYNC = 0x6,
! 9411: SYSCALL = 0x8,
! 9412: SDBBP = 0xd,
! 9413:
! 9414: /* bits 15..12 for 0x35 */
! 9415: MFHI32 = 0x0,
! 9416: MFLO32 = 0x1,
! 9417: MTHI32 = 0x2,
! 9418: MTLO32 = 0x3,
! 9419: };
! 9420:
! 9421: /* POOL32B encoding of minor opcode field (bits 15..12) */
! 9422:
! 9423: enum {
! 9424: LWC2 = 0x0,
! 9425: LWP = 0x1,
! 9426: LDP = 0x4,
! 9427: LWM32 = 0x5,
! 9428: CACHE = 0x6,
! 9429: LDM = 0x7,
! 9430: SWC2 = 0x8,
! 9431: SWP = 0x9,
! 9432: SDP = 0xc,
! 9433: SWM32 = 0xd,
! 9434: SDM = 0xf
! 9435: };
! 9436:
! 9437: /* POOL32C encoding of minor opcode field (bits 15..12) */
! 9438:
! 9439: enum {
! 9440: LWL = 0x0,
! 9441: SWL = 0x8,
! 9442: LWR = 0x1,
! 9443: SWR = 0x9,
! 9444: PREF = 0x2,
! 9445: /* 0xa is reserved */
! 9446: LL = 0x3,
! 9447: SC = 0xb,
! 9448: LDL = 0x4,
! 9449: SDL = 0xc,
! 9450: LDR = 0x5,
! 9451: SDR = 0xd,
! 9452: /* 0x6 is reserved */
! 9453: LWU = 0xe,
! 9454: LLD = 0x7,
! 9455: SCD = 0xf
! 9456: };
! 9457:
! 9458: /* POOL32F encoding of minor opcode field (bits 5..0) */
! 9459:
! 9460: enum {
! 9461: /* These are the bit 7..6 values */
! 9462: ADD_FMT = 0x0,
! 9463: MOVN_FMT = 0x0,
! 9464:
! 9465: SUB_FMT = 0x1,
! 9466: MOVZ_FMT = 0x1,
! 9467:
! 9468: MUL_FMT = 0x2,
! 9469:
! 9470: DIV_FMT = 0x3,
! 9471:
! 9472: /* These are the bit 8..6 values */
! 9473: RSQRT2_FMT = 0x0,
! 9474: MOVF_FMT = 0x0,
! 9475:
! 9476: LWXC1 = 0x1,
! 9477: MOVT_FMT = 0x1,
! 9478:
! 9479: PLL_PS = 0x2,
! 9480: SWXC1 = 0x2,
! 9481:
! 9482: PLU_PS = 0x3,
! 9483: LDXC1 = 0x3,
! 9484:
! 9485: PUL_PS = 0x4,
! 9486: SDXC1 = 0x4,
! 9487: RECIP2_FMT = 0x4,
! 9488:
! 9489: PUU_PS = 0x5,
! 9490: LUXC1 = 0x5,
! 9491:
! 9492: CVT_PS_S = 0x6,
! 9493: SUXC1 = 0x6,
! 9494: ADDR_PS = 0x6,
! 9495: PREFX = 0x6,
! 9496:
! 9497: MULR_PS = 0x7,
! 9498:
! 9499: MADD_S = 0x01,
! 9500: MADD_D = 0x09,
! 9501: MADD_PS = 0x11,
! 9502: ALNV_PS = 0x19,
! 9503: MSUB_S = 0x21,
! 9504: MSUB_D = 0x29,
! 9505: MSUB_PS = 0x31,
! 9506:
! 9507: NMADD_S = 0x02,
! 9508: NMADD_D = 0x0a,
! 9509: NMADD_PS = 0x12,
! 9510: NMSUB_S = 0x22,
! 9511: NMSUB_D = 0x2a,
! 9512: NMSUB_PS = 0x32,
! 9513:
! 9514: POOL32FXF = 0x3b,
! 9515:
! 9516: CABS_COND_FMT = 0x1c, /* MIPS3D */
! 9517: C_COND_FMT = 0x3c
! 9518: };
! 9519:
! 9520: /* POOL32Fxf encoding of minor opcode extension field */
! 9521:
! 9522: enum {
! 9523: CVT_L = 0x04,
! 9524: RSQRT_FMT = 0x08,
! 9525: FLOOR_L = 0x0c,
! 9526: CVT_PW_PS = 0x1c,
! 9527: CVT_W = 0x24,
! 9528: SQRT_FMT = 0x28,
! 9529: FLOOR_W = 0x2c,
! 9530: CVT_PS_PW = 0x3c,
! 9531: CFC1 = 0x40,
! 9532: RECIP_FMT = 0x48,
! 9533: CEIL_L = 0x4c,
! 9534: CTC1 = 0x60,
! 9535: CEIL_W = 0x6c,
! 9536: MFC1 = 0x80,
! 9537: CVT_S_PL = 0x84,
! 9538: TRUNC_L = 0x8c,
! 9539: MTC1 = 0xa0,
! 9540: CVT_S_PU = 0xa4,
! 9541: TRUNC_W = 0xac,
! 9542: MFHC1 = 0xc0,
! 9543: ROUND_L = 0xcc,
! 9544: MTHC1 = 0xe0,
! 9545: ROUND_W = 0xec,
! 9546:
! 9547: MOV_FMT = 0x01,
! 9548: MOVF = 0x05,
! 9549: ABS_FMT = 0x0d,
! 9550: RSQRT1_FMT = 0x1d,
! 9551: MOVT = 0x25,
! 9552: NEG_FMT = 0x2d,
! 9553: CVT_D = 0x4d,
! 9554: RECIP1_FMT = 0x5d,
! 9555: CVT_S = 0x6d
! 9556: };
! 9557:
! 9558: /* POOL32I encoding of minor opcode field (bits 25..21) */
! 9559:
! 9560: enum {
! 9561: BLTZ = 0x00,
! 9562: BLTZAL = 0x01,
! 9563: BGEZ = 0x02,
! 9564: BGEZAL = 0x03,
! 9565: BLEZ = 0x04,
! 9566: BNEZC = 0x05,
! 9567: BGTZ = 0x06,
! 9568: BEQZC = 0x07,
! 9569: TLTI = 0x08,
! 9570: TGEI = 0x09,
! 9571: TLTIU = 0x0a,
! 9572: TGEIU = 0x0b,
! 9573: TNEI = 0x0c,
! 9574: LUI = 0x0d,
! 9575: TEQI = 0x0e,
! 9576: SYNCI = 0x10,
! 9577: BLTZALS = 0x11,
! 9578: BGEZALS = 0x13,
! 9579: BC2F = 0x14,
! 9580: BC2T = 0x15,
! 9581: BPOSGE64 = 0x1a,
! 9582: BPOSGE32 = 0x1b,
! 9583: /* These overlap and are distinguished by bit16 of the instruction */
! 9584: BC1F = 0x1c,
! 9585: BC1T = 0x1d,
! 9586: BC1ANY2F = 0x1c,
! 9587: BC1ANY2T = 0x1d,
! 9588: BC1ANY4F = 0x1e,
! 9589: BC1ANY4T = 0x1f
! 9590: };
! 9591:
! 9592: /* POOL16A encoding of minor opcode field */
! 9593:
! 9594: enum {
! 9595: ADDU16 = 0x0,
! 9596: SUBU16 = 0x1
! 9597: };
! 9598:
! 9599: /* POOL16B encoding of minor opcode field */
! 9600:
! 9601: enum {
! 9602: SLL16 = 0x0,
! 9603: SRL16 = 0x1
! 9604: };
! 9605:
! 9606: /* POOL16C encoding of minor opcode field */
! 9607:
! 9608: enum {
! 9609: NOT16 = 0x00,
! 9610: XOR16 = 0x04,
! 9611: AND16 = 0x08,
! 9612: OR16 = 0x0c,
! 9613: LWM16 = 0x10,
! 9614: SWM16 = 0x14,
! 9615: JR16 = 0x18,
! 9616: JRC16 = 0x1a,
! 9617: JALR16 = 0x1c,
! 9618: JALR16S = 0x1e,
! 9619: MFHI16 = 0x20,
! 9620: MFLO16 = 0x24,
! 9621: BREAK16 = 0x28,
! 9622: SDBBP16 = 0x2c,
! 9623: JRADDIUSP = 0x30
! 9624: };
! 9625:
! 9626: /* POOL16D encoding of minor opcode field */
! 9627:
! 9628: enum {
! 9629: ADDIUS5 = 0x0,
! 9630: ADDIUSP = 0x1
! 9631: };
! 9632:
! 9633: /* POOL16E encoding of minor opcode field */
! 9634:
! 9635: enum {
! 9636: ADDIUR2 = 0x0,
! 9637: ADDIUR1SP = 0x1
! 9638: };
! 9639:
! 9640: static int mmreg (int r)
! 9641: {
! 9642: static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
! 9643:
! 9644: return map[r];
! 9645: }
! 9646:
! 9647: /* Used for 16-bit store instructions. */
! 9648: static int mmreg2 (int r)
! 9649: {
! 9650: static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
! 9651:
! 9652: return map[r];
! 9653: }
! 9654:
! 9655: #define uMIPS_RD(op) ((op >> 7) & 0x7)
! 9656: #define uMIPS_RS(op) ((op >> 4) & 0x7)
! 9657: #define uMIPS_RS2(op) uMIPS_RS(op)
! 9658: #define uMIPS_RS1(op) ((op >> 1) & 0x7)
! 9659: #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
! 9660: #define uMIPS_RS5(op) (op & 0x1f)
! 9661:
! 9662: /* Signed immediate */
! 9663: #define SIMM(op, start, width) \
! 9664: ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
! 9665: << (32-width)) \
! 9666: >> (32-width))
! 9667: /* Zero-extended immediate */
! 9668: #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
! 9669:
! 9670: static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
! 9671: {
! 9672: int rd = mmreg(uMIPS_RD(ctx->opcode));
! 9673:
! 9674: gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
! 9675: }
! 9676:
! 9677: static void gen_addiur2 (CPUState *env, DisasContext *ctx)
! 9678: {
! 9679: static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
! 9680: int rd = mmreg(uMIPS_RD(ctx->opcode));
! 9681: int rs = mmreg(uMIPS_RS(ctx->opcode));
! 9682:
! 9683: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
! 9684: }
! 9685:
! 9686: static void gen_addiusp (CPUState *env, DisasContext *ctx)
! 9687: {
! 9688: int encoded = ZIMM(ctx->opcode, 1, 9);
! 9689: int decoded;
! 9690:
! 9691: if (encoded <= 1) {
! 9692: decoded = 256 + encoded;
! 9693: } else if (encoded <= 255) {
! 9694: decoded = encoded;
! 9695: } else if (encoded <= 509) {
! 9696: decoded = encoded - 512;
! 9697: } else {
! 9698: decoded = encoded - 768;
! 9699: }
! 9700:
! 9701: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
! 9702: }
! 9703:
! 9704: static void gen_addius5 (CPUState *env, DisasContext *ctx)
! 9705: {
! 9706: int imm = SIMM(ctx->opcode, 1, 4);
! 9707: int rd = (ctx->opcode >> 5) & 0x1f;
! 9708:
! 9709: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
! 9710: }
! 9711:
! 9712: static void gen_andi16 (CPUState *env, DisasContext *ctx)
! 9713: {
! 9714: static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
! 9715: 31, 32, 63, 64, 255, 32768, 65535 };
! 9716: int rd = mmreg(uMIPS_RD(ctx->opcode));
! 9717: int rs = mmreg(uMIPS_RS(ctx->opcode));
! 9718: int encoded = ZIMM(ctx->opcode, 0, 4);
! 9719:
! 9720: gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
! 9721: }
! 9722:
! 9723: static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
! 9724: int base, int16_t offset)
! 9725: {
! 9726: TCGv t0, t1;
! 9727: TCGv_i32 t2;
! 9728:
! 9729: if (ctx->hflags & MIPS_HFLAG_BMASK) {
! 9730: generate_exception(ctx, EXCP_RI);
! 9731: return;
! 9732: }
! 9733:
! 9734: t0 = tcg_temp_new();
! 9735:
! 9736: gen_base_offset_addr(ctx, t0, base, offset);
! 9737:
! 9738: t1 = tcg_const_tl(reglist);
! 9739: t2 = tcg_const_i32(ctx->mem_idx);
! 9740:
! 9741: save_cpu_state(ctx, 1);
! 9742: switch (opc) {
! 9743: case LWM32:
! 9744: gen_helper_lwm(t0, t1, t2);
! 9745: break;
! 9746: case SWM32:
! 9747: gen_helper_swm(t0, t1, t2);
! 9748: break;
! 9749: #ifdef TARGET_MIPS64
! 9750: case LDM:
! 9751: gen_helper_ldm(t0, t1, t2);
! 9752: break;
! 9753: case SDM:
! 9754: gen_helper_sdm(t0, t1, t2);
! 9755: break;
! 9756: #endif
! 9757: }
! 9758: MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
! 9759: tcg_temp_free(t0);
! 9760: tcg_temp_free(t1);
! 9761: tcg_temp_free_i32(t2);
! 9762: }
! 9763:
! 9764:
! 9765: static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
! 9766: {
! 9767: int rd = mmreg((ctx->opcode >> 3) & 0x7);
! 9768: int rs = mmreg(ctx->opcode & 0x7);
! 9769: int opc;
! 9770:
! 9771: switch (((ctx->opcode) >> 4) & 0x3f) {
! 9772: case NOT16 + 0:
! 9773: case NOT16 + 1:
! 9774: case NOT16 + 2:
! 9775: case NOT16 + 3:
! 9776: gen_logic(env, OPC_NOR, rd, rs, 0);
! 9777: break;
! 9778: case XOR16 + 0:
! 9779: case XOR16 + 1:
! 9780: case XOR16 + 2:
! 9781: case XOR16 + 3:
! 9782: gen_logic(env, OPC_XOR, rd, rd, rs);
! 9783: break;
! 9784: case AND16 + 0:
! 9785: case AND16 + 1:
! 9786: case AND16 + 2:
! 9787: case AND16 + 3:
! 9788: gen_logic(env, OPC_AND, rd, rd, rs);
! 9789: break;
! 9790: case OR16 + 0:
! 9791: case OR16 + 1:
! 9792: case OR16 + 2:
! 9793: case OR16 + 3:
! 9794: gen_logic(env, OPC_OR, rd, rd, rs);
! 9795: break;
! 9796: case LWM16 + 0:
! 9797: case LWM16 + 1:
! 9798: case LWM16 + 2:
! 9799: case LWM16 + 3:
! 9800: {
! 9801: static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
! 9802: int offset = ZIMM(ctx->opcode, 0, 4);
! 9803:
! 9804: gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
! 9805: 29, offset << 2);
! 9806: }
! 9807: break;
! 9808: case SWM16 + 0:
! 9809: case SWM16 + 1:
! 9810: case SWM16 + 2:
! 9811: case SWM16 + 3:
! 9812: {
! 9813: static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
! 9814: int offset = ZIMM(ctx->opcode, 0, 4);
! 9815:
! 9816: gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
! 9817: 29, offset << 2);
! 9818: }
! 9819: break;
! 9820: case JR16 + 0:
! 9821: case JR16 + 1:
! 9822: {
! 9823: int reg = ctx->opcode & 0x1f;
! 9824:
! 9825: gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
! 9826: }
! 9827: *is_branch = 1;
! 9828: break;
! 9829: case JRC16 + 0:
! 9830: case JRC16 + 1:
! 9831: {
! 9832: int reg = ctx->opcode & 0x1f;
! 9833:
! 9834: gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
! 9835: /* Let normal delay slot handling in our caller take us
! 9836: to the branch target. */
! 9837: }
! 9838: break;
! 9839: case JALR16 + 0:
! 9840: case JALR16 + 1:
! 9841: opc = OPC_JALR;
! 9842: goto do_jalr;
! 9843: case JALR16S + 0:
! 9844: case JALR16S + 1:
! 9845: opc = OPC_JALRS;
! 9846: do_jalr:
! 9847: {
! 9848: int reg = ctx->opcode & 0x1f;
! 9849:
! 9850: gen_compute_branch(ctx, opc, 2, reg, 31, 0);
! 9851: }
! 9852: *is_branch = 1;
! 9853: break;
! 9854: case MFHI16 + 0:
! 9855: case MFHI16 + 1:
! 9856: gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
! 9857: break;
! 9858: case MFLO16 + 0:
! 9859: case MFLO16 + 1:
! 9860: gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
! 9861: break;
! 9862: case BREAK16:
! 9863: generate_exception(ctx, EXCP_BREAK);
! 9864: break;
! 9865: case SDBBP16:
! 9866: /* XXX: not clear which exception should be raised
! 9867: * when in debug mode...
! 9868: */
! 9869: check_insn(env, ctx, ISA_MIPS32);
! 9870: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
! 9871: generate_exception(ctx, EXCP_DBp);
! 9872: } else {
! 9873: generate_exception(ctx, EXCP_DBp);
! 9874: }
! 9875: break;
! 9876: case JRADDIUSP + 0:
! 9877: case JRADDIUSP + 1:
! 9878: {
! 9879: int imm = ZIMM(ctx->opcode, 0, 5);
! 9880:
! 9881: gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
! 9882: gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
! 9883: /* Let normal delay slot handling in our caller take us
! 9884: to the branch target. */
! 9885: }
! 9886: break;
! 9887: default:
! 9888: generate_exception(ctx, EXCP_RI);
! 9889: break;
! 9890: }
! 9891: }
! 9892:
! 9893: static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
! 9894: {
! 9895: TCGv t0 = tcg_temp_new();
! 9896: TCGv t1 = tcg_temp_new();
! 9897:
! 9898: gen_load_gpr(t0, base);
! 9899:
! 9900: if (index != 0) {
! 9901: gen_load_gpr(t1, index);
! 9902: tcg_gen_shli_tl(t1, t1, 2);
! 9903: gen_op_addr_add(ctx, t0, t1, t0);
! 9904: }
! 9905:
! 9906: save_cpu_state(ctx, 0);
! 9907: op_ld_lw(t1, t0, ctx);
! 9908: gen_store_gpr(t1, rd);
! 9909:
! 9910: tcg_temp_free(t0);
! 9911: tcg_temp_free(t1);
! 9912: }
! 9913:
! 9914: static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
! 9915: int base, int16_t offset)
! 9916: {
! 9917: const char *opn = "ldst_pair";
! 9918: TCGv t0, t1;
! 9919:
! 9920: if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
! 9921: generate_exception(ctx, EXCP_RI);
! 9922: return;
! 9923: }
! 9924:
! 9925: t0 = tcg_temp_new();
! 9926: t1 = tcg_temp_new();
! 9927:
! 9928: gen_base_offset_addr(ctx, t0, base, offset);
! 9929:
! 9930: switch (opc) {
! 9931: case LWP:
! 9932: save_cpu_state(ctx, 0);
! 9933: op_ld_lw(t1, t0, ctx);
! 9934: gen_store_gpr(t1, rd);
! 9935: tcg_gen_movi_tl(t1, 4);
! 9936: gen_op_addr_add(ctx, t0, t0, t1);
! 9937: op_ld_lw(t1, t0, ctx);
! 9938: gen_store_gpr(t1, rd+1);
! 9939: opn = "lwp";
! 9940: break;
! 9941: case SWP:
! 9942: save_cpu_state(ctx, 1);
! 9943: gen_load_gpr(t1, rd);
! 9944: op_st_sw(t1, t0, ctx);
! 9945: tcg_gen_movi_tl(t1, 4);
! 9946: gen_op_addr_add(ctx, t0, t0, t1);
! 9947: gen_load_gpr(t1, rd+1);
! 9948: op_st_sw(t1, t0, ctx);
! 9949: opn = "swp";
! 9950: break;
! 9951: #ifdef TARGET_MIPS64
! 9952: case LDP:
! 9953: save_cpu_state(ctx, 0);
! 9954: op_ld_ld(t1, t0, ctx);
! 9955: gen_store_gpr(t1, rd);
! 9956: tcg_gen_movi_tl(t1, 8);
! 9957: gen_op_addr_add(ctx, t0, t0, t1);
! 9958: op_ld_ld(t1, t0, ctx);
! 9959: gen_store_gpr(t1, rd+1);
! 9960: opn = "ldp";
! 9961: break;
! 9962: case SDP:
! 9963: save_cpu_state(ctx, 1);
! 9964: gen_load_gpr(t1, rd);
! 9965: op_st_sd(t1, t0, ctx);
! 9966: tcg_gen_movi_tl(t1, 8);
! 9967: gen_op_addr_add(ctx, t0, t0, t1);
! 9968: gen_load_gpr(t1, rd+1);
! 9969: op_st_sd(t1, t0, ctx);
! 9970: opn = "sdp";
! 9971: break;
! 9972: #endif
! 9973: }
! 9974: MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
! 9975: tcg_temp_free(t0);
! 9976: tcg_temp_free(t1);
! 9977: }
! 9978:
! 9979: static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
! 9980: int *is_branch)
! 9981: {
! 9982: int extension = (ctx->opcode >> 6) & 0x3f;
! 9983: int minor = (ctx->opcode >> 12) & 0xf;
! 9984: uint32_t mips32_op;
! 9985:
! 9986: switch (extension) {
! 9987: case TEQ:
! 9988: mips32_op = OPC_TEQ;
! 9989: goto do_trap;
! 9990: case TGE:
! 9991: mips32_op = OPC_TGE;
! 9992: goto do_trap;
! 9993: case TGEU:
! 9994: mips32_op = OPC_TGEU;
! 9995: goto do_trap;
! 9996: case TLT:
! 9997: mips32_op = OPC_TLT;
! 9998: goto do_trap;
! 9999: case TLTU:
! 10000: mips32_op = OPC_TLTU;
! 10001: goto do_trap;
! 10002: case TNE:
! 10003: mips32_op = OPC_TNE;
! 10004: do_trap:
! 10005: gen_trap(ctx, mips32_op, rs, rt, -1);
! 10006: break;
! 10007: #ifndef CONFIG_USER_ONLY
! 10008: case MFC0:
! 10009: case MFC0 + 32:
! 10010: if (rt == 0) {
! 10011: /* Treat as NOP. */
! 10012: break;
! 10013: }
! 10014: gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
! 10015: break;
! 10016: case MTC0:
! 10017: case MTC0 + 32:
! 10018: {
! 10019: TCGv t0 = tcg_temp_new();
! 10020:
! 10021: gen_load_gpr(t0, rt);
! 10022: gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
! 10023: tcg_temp_free(t0);
! 10024: }
! 10025: break;
! 10026: #endif
! 10027: case 0x2c:
! 10028: switch (minor) {
! 10029: case SEB:
! 10030: gen_bshfl(ctx, OPC_SEB, rs, rt);
! 10031: break;
! 10032: case SEH:
! 10033: gen_bshfl(ctx, OPC_SEH, rs, rt);
! 10034: break;
! 10035: case CLO:
! 10036: mips32_op = OPC_CLO;
! 10037: goto do_cl;
! 10038: case CLZ:
! 10039: mips32_op = OPC_CLZ;
! 10040: do_cl:
! 10041: check_insn(env, ctx, ISA_MIPS32);
! 10042: gen_cl(ctx, mips32_op, rt, rs);
! 10043: break;
! 10044: case RDHWR:
! 10045: gen_rdhwr(env, ctx, rt, rs);
! 10046: break;
! 10047: case WSBH:
! 10048: gen_bshfl(ctx, OPC_WSBH, rs, rt);
! 10049: break;
! 10050: case MULT:
! 10051: mips32_op = OPC_MULT;
! 10052: goto do_muldiv;
! 10053: case MULTU:
! 10054: mips32_op = OPC_MULTU;
! 10055: goto do_muldiv;
! 10056: case DIV:
! 10057: mips32_op = OPC_DIV;
! 10058: goto do_muldiv;
! 10059: case DIVU:
! 10060: mips32_op = OPC_DIVU;
! 10061: goto do_muldiv;
! 10062: case MADD:
! 10063: mips32_op = OPC_MADD;
! 10064: goto do_muldiv;
! 10065: case MADDU:
! 10066: mips32_op = OPC_MADDU;
! 10067: goto do_muldiv;
! 10068: case MSUB:
! 10069: mips32_op = OPC_MSUB;
! 10070: goto do_muldiv;
! 10071: case MSUBU:
! 10072: mips32_op = OPC_MSUBU;
! 10073: do_muldiv:
! 10074: check_insn(env, ctx, ISA_MIPS32);
! 10075: gen_muldiv(ctx, mips32_op, rs, rt);
! 10076: break;
! 10077: default:
! 10078: goto pool32axf_invalid;
! 10079: }
! 10080: break;
! 10081: case 0x34:
! 10082: switch (minor) {
! 10083: case MFC2:
! 10084: case MTC2:
! 10085: case MFHC2:
! 10086: case MTHC2:
! 10087: case CFC2:
! 10088: case CTC2:
! 10089: generate_exception_err(ctx, EXCP_CpU, 2);
! 10090: break;
! 10091: default:
! 10092: goto pool32axf_invalid;
! 10093: }
! 10094: break;
! 10095: case 0x3c:
! 10096: switch (minor) {
! 10097: case JALR:
! 10098: case JALR_HB:
! 10099: gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
! 10100: *is_branch = 1;
! 10101: break;
! 10102: case JALRS:
! 10103: case JALRS_HB:
! 10104: gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
! 10105: *is_branch = 1;
! 10106: break;
! 10107: default:
! 10108: goto pool32axf_invalid;
! 10109: }
! 10110: break;
! 10111: case 0x05:
! 10112: switch (minor) {
! 10113: case RDPGPR:
! 10114: check_insn(env, ctx, ISA_MIPS32R2);
! 10115: gen_load_srsgpr(rt, rs);
! 10116: break;
! 10117: case WRPGPR:
! 10118: check_insn(env, ctx, ISA_MIPS32R2);
! 10119: gen_store_srsgpr(rt, rs);
! 10120: break;
! 10121: default:
! 10122: goto pool32axf_invalid;
! 10123: }
! 10124: break;
! 10125: #ifndef CONFIG_USER_ONLY
! 10126: case 0x0d:
! 10127: switch (minor) {
! 10128: case TLBP:
! 10129: mips32_op = OPC_TLBP;
! 10130: goto do_cp0;
! 10131: case TLBR:
! 10132: mips32_op = OPC_TLBR;
! 10133: goto do_cp0;
! 10134: case TLBWI:
! 10135: mips32_op = OPC_TLBWI;
! 10136: goto do_cp0;
! 10137: case TLBWR:
! 10138: mips32_op = OPC_TLBWR;
! 10139: goto do_cp0;
! 10140: case WAIT:
! 10141: mips32_op = OPC_WAIT;
! 10142: goto do_cp0;
! 10143: case DERET:
! 10144: mips32_op = OPC_DERET;
! 10145: goto do_cp0;
! 10146: case ERET:
! 10147: mips32_op = OPC_ERET;
! 10148: do_cp0:
! 10149: gen_cp0(env, ctx, mips32_op, rt, rs);
! 10150: break;
! 10151: default:
! 10152: goto pool32axf_invalid;
! 10153: }
! 10154: break;
! 10155: case 0x1d:
! 10156: switch (minor) {
! 10157: case DI:
! 10158: {
! 10159: TCGv t0 = tcg_temp_new();
! 10160:
! 10161: save_cpu_state(ctx, 1);
! 10162: gen_helper_di(t0);
! 10163: gen_store_gpr(t0, rs);
! 10164: /* Stop translation as we may have switched the execution mode */
! 10165: ctx->bstate = BS_STOP;
! 10166: tcg_temp_free(t0);
! 10167: }
! 10168: break;
! 10169: case EI:
! 10170: {
! 10171: TCGv t0 = tcg_temp_new();
! 10172:
! 10173: save_cpu_state(ctx, 1);
! 10174: gen_helper_ei(t0);
! 10175: gen_store_gpr(t0, rs);
! 10176: /* Stop translation as we may have switched the execution mode */
! 10177: ctx->bstate = BS_STOP;
! 10178: tcg_temp_free(t0);
! 10179: }
! 10180: break;
! 10181: default:
! 10182: goto pool32axf_invalid;
! 10183: }
! 10184: break;
! 10185: #endif
! 10186: case 0x2d:
! 10187: switch (minor) {
! 10188: case SYNC:
! 10189: /* NOP */
! 10190: break;
! 10191: case SYSCALL:
! 10192: generate_exception(ctx, EXCP_SYSCALL);
! 10193: ctx->bstate = BS_STOP;
! 10194: break;
! 10195: case SDBBP:
! 10196: check_insn(env, ctx, ISA_MIPS32);
! 10197: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
! 10198: generate_exception(ctx, EXCP_DBp);
! 10199: } else {
! 10200: generate_exception(ctx, EXCP_DBp);
! 10201: }
! 10202: break;
! 10203: default:
! 10204: goto pool32axf_invalid;
! 10205: }
! 10206: break;
! 10207: case 0x35:
! 10208: switch (minor) {
! 10209: case MFHI32:
! 10210: gen_HILO(ctx, OPC_MFHI, rs);
! 10211: break;
! 10212: case MFLO32:
! 10213: gen_HILO(ctx, OPC_MFLO, rs);
! 10214: break;
! 10215: case MTHI32:
! 10216: gen_HILO(ctx, OPC_MTHI, rs);
! 10217: break;
! 10218: case MTLO32:
! 10219: gen_HILO(ctx, OPC_MTLO, rs);
! 10220: break;
! 10221: default:
! 10222: goto pool32axf_invalid;
! 10223: }
! 10224: break;
! 10225: default:
! 10226: pool32axf_invalid:
! 10227: MIPS_INVAL("pool32axf");
! 10228: generate_exception(ctx, EXCP_RI);
! 10229: break;
! 10230: }
! 10231: }
! 10232:
! 10233: /* Values for microMIPS fmt field. Variable-width, depending on which
! 10234: formats the instruction supports. */
! 10235:
! 10236: enum {
! 10237: FMT_SD_S = 0,
! 10238: FMT_SD_D = 1,
! 10239:
! 10240: FMT_SDPS_S = 0,
! 10241: FMT_SDPS_D = 1,
! 10242: FMT_SDPS_PS = 2,
! 10243:
! 10244: FMT_SWL_S = 0,
! 10245: FMT_SWL_W = 1,
! 10246: FMT_SWL_L = 2,
! 10247:
! 10248: FMT_DWL_D = 0,
! 10249: FMT_DWL_W = 1,
! 10250: FMT_DWL_L = 2
! 10251: };
! 10252:
! 10253: static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
! 10254: {
! 10255: int extension = (ctx->opcode >> 6) & 0x3ff;
! 10256: uint32_t mips32_op;
! 10257:
! 10258: #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
! 10259: #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
! 10260: #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
! 10261:
! 10262: switch (extension) {
! 10263: case FLOAT_1BIT_FMT(CFC1, 0):
! 10264: mips32_op = OPC_CFC1;
! 10265: goto do_cp1;
! 10266: case FLOAT_1BIT_FMT(CTC1, 0):
! 10267: mips32_op = OPC_CTC1;
! 10268: goto do_cp1;
! 10269: case FLOAT_1BIT_FMT(MFC1, 0):
! 10270: mips32_op = OPC_MFC1;
! 10271: goto do_cp1;
! 10272: case FLOAT_1BIT_FMT(MTC1, 0):
! 10273: mips32_op = OPC_MTC1;
! 10274: goto do_cp1;
! 10275: case FLOAT_1BIT_FMT(MFHC1, 0):
! 10276: mips32_op = OPC_MFHC1;
! 10277: goto do_cp1;
! 10278: case FLOAT_1BIT_FMT(MTHC1, 0):
! 10279: mips32_op = OPC_MTHC1;
! 10280: do_cp1:
! 10281: gen_cp1(ctx, mips32_op, rt, rs);
! 10282: break;
! 10283:
! 10284: /* Reciprocal square root */
! 10285: case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
! 10286: mips32_op = OPC_RSQRT_S;
! 10287: goto do_unaryfp;
! 10288: case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
! 10289: mips32_op = OPC_RSQRT_D;
! 10290: goto do_unaryfp;
! 10291:
! 10292: /* Square root */
! 10293: case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
! 10294: mips32_op = OPC_SQRT_S;
! 10295: goto do_unaryfp;
! 10296: case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
! 10297: mips32_op = OPC_SQRT_D;
! 10298: goto do_unaryfp;
! 10299:
! 10300: /* Reciprocal */
! 10301: case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
! 10302: mips32_op = OPC_RECIP_S;
! 10303: goto do_unaryfp;
! 10304: case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
! 10305: mips32_op = OPC_RECIP_D;
! 10306: goto do_unaryfp;
! 10307:
! 10308: /* Floor */
! 10309: case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
! 10310: mips32_op = OPC_FLOOR_L_S;
! 10311: goto do_unaryfp;
! 10312: case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
! 10313: mips32_op = OPC_FLOOR_L_D;
! 10314: goto do_unaryfp;
! 10315: case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
! 10316: mips32_op = OPC_FLOOR_W_S;
! 10317: goto do_unaryfp;
! 10318: case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
! 10319: mips32_op = OPC_FLOOR_W_D;
! 10320: goto do_unaryfp;
! 10321:
! 10322: /* Ceiling */
! 10323: case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
! 10324: mips32_op = OPC_CEIL_L_S;
! 10325: goto do_unaryfp;
! 10326: case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
! 10327: mips32_op = OPC_CEIL_L_D;
! 10328: goto do_unaryfp;
! 10329: case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
! 10330: mips32_op = OPC_CEIL_W_S;
! 10331: goto do_unaryfp;
! 10332: case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
! 10333: mips32_op = OPC_CEIL_W_D;
! 10334: goto do_unaryfp;
! 10335:
! 10336: /* Truncation */
! 10337: case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
! 10338: mips32_op = OPC_TRUNC_L_S;
! 10339: goto do_unaryfp;
! 10340: case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
! 10341: mips32_op = OPC_TRUNC_L_D;
! 10342: goto do_unaryfp;
! 10343: case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
! 10344: mips32_op = OPC_TRUNC_W_S;
! 10345: goto do_unaryfp;
! 10346: case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
! 10347: mips32_op = OPC_TRUNC_W_D;
! 10348: goto do_unaryfp;
! 10349:
! 10350: /* Round */
! 10351: case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
! 10352: mips32_op = OPC_ROUND_L_S;
! 10353: goto do_unaryfp;
! 10354: case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
! 10355: mips32_op = OPC_ROUND_L_D;
! 10356: goto do_unaryfp;
! 10357: case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
! 10358: mips32_op = OPC_ROUND_W_S;
! 10359: goto do_unaryfp;
! 10360: case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
! 10361: mips32_op = OPC_ROUND_W_D;
! 10362: goto do_unaryfp;
! 10363:
! 10364: /* Integer to floating-point conversion */
! 10365: case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
! 10366: mips32_op = OPC_CVT_L_S;
! 10367: goto do_unaryfp;
! 10368: case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
! 10369: mips32_op = OPC_CVT_L_D;
! 10370: goto do_unaryfp;
! 10371: case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
! 10372: mips32_op = OPC_CVT_W_S;
! 10373: goto do_unaryfp;
! 10374: case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
! 10375: mips32_op = OPC_CVT_W_D;
! 10376: goto do_unaryfp;
! 10377:
! 10378: /* Paired-foo conversions */
! 10379: case FLOAT_1BIT_FMT(CVT_S_PL, 0):
! 10380: mips32_op = OPC_CVT_S_PL;
! 10381: goto do_unaryfp;
! 10382: case FLOAT_1BIT_FMT(CVT_S_PU, 0):
! 10383: mips32_op = OPC_CVT_S_PU;
! 10384: goto do_unaryfp;
! 10385: case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
! 10386: mips32_op = OPC_CVT_PW_PS;
! 10387: goto do_unaryfp;
! 10388: case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
! 10389: mips32_op = OPC_CVT_PS_PW;
! 10390: goto do_unaryfp;
! 10391:
! 10392: /* Floating-point moves */
! 10393: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
! 10394: mips32_op = OPC_MOV_S;
! 10395: goto do_unaryfp;
! 10396: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
! 10397: mips32_op = OPC_MOV_D;
! 10398: goto do_unaryfp;
! 10399: case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
! 10400: mips32_op = OPC_MOV_PS;
! 10401: goto do_unaryfp;
! 10402:
! 10403: /* Absolute value */
! 10404: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
! 10405: mips32_op = OPC_ABS_S;
! 10406: goto do_unaryfp;
! 10407: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
! 10408: mips32_op = OPC_ABS_D;
! 10409: goto do_unaryfp;
! 10410: case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
! 10411: mips32_op = OPC_ABS_PS;
! 10412: goto do_unaryfp;
! 10413:
! 10414: /* Negation */
! 10415: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
! 10416: mips32_op = OPC_NEG_S;
! 10417: goto do_unaryfp;
! 10418: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
! 10419: mips32_op = OPC_NEG_D;
! 10420: goto do_unaryfp;
! 10421: case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
! 10422: mips32_op = OPC_NEG_PS;
! 10423: goto do_unaryfp;
! 10424:
! 10425: /* Reciprocal square root step */
! 10426: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
! 10427: mips32_op = OPC_RSQRT1_S;
! 10428: goto do_unaryfp;
! 10429: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
! 10430: mips32_op = OPC_RSQRT1_D;
! 10431: goto do_unaryfp;
! 10432: case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
! 10433: mips32_op = OPC_RSQRT1_PS;
! 10434: goto do_unaryfp;
! 10435:
! 10436: /* Reciprocal step */
! 10437: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
! 10438: mips32_op = OPC_RECIP1_S;
! 10439: goto do_unaryfp;
! 10440: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
! 10441: mips32_op = OPC_RECIP1_S;
! 10442: goto do_unaryfp;
! 10443: case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
! 10444: mips32_op = OPC_RECIP1_PS;
! 10445: goto do_unaryfp;
! 10446:
! 10447: /* Conversions from double */
! 10448: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
! 10449: mips32_op = OPC_CVT_D_S;
! 10450: goto do_unaryfp;
! 10451: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
! 10452: mips32_op = OPC_CVT_D_W;
! 10453: goto do_unaryfp;
! 10454: case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
! 10455: mips32_op = OPC_CVT_D_L;
! 10456: goto do_unaryfp;
! 10457:
! 10458: /* Conversions from single */
! 10459: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
! 10460: mips32_op = OPC_CVT_S_D;
! 10461: goto do_unaryfp;
! 10462: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
! 10463: mips32_op = OPC_CVT_S_W;
! 10464: goto do_unaryfp;
! 10465: case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
! 10466: mips32_op = OPC_CVT_S_L;
! 10467: do_unaryfp:
! 10468: gen_farith(ctx, mips32_op, -1, rs, rt, 0);
! 10469: break;
! 10470:
! 10471: /* Conditional moves on floating-point codes */
! 10472: case COND_FLOAT_MOV(MOVT, 0):
! 10473: case COND_FLOAT_MOV(MOVT, 1):
! 10474: case COND_FLOAT_MOV(MOVT, 2):
! 10475: case COND_FLOAT_MOV(MOVT, 3):
! 10476: case COND_FLOAT_MOV(MOVT, 4):
! 10477: case COND_FLOAT_MOV(MOVT, 5):
! 10478: case COND_FLOAT_MOV(MOVT, 6):
! 10479: case COND_FLOAT_MOV(MOVT, 7):
! 10480: gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
! 10481: break;
! 10482: case COND_FLOAT_MOV(MOVF, 0):
! 10483: case COND_FLOAT_MOV(MOVF, 1):
! 10484: case COND_FLOAT_MOV(MOVF, 2):
! 10485: case COND_FLOAT_MOV(MOVF, 3):
! 10486: case COND_FLOAT_MOV(MOVF, 4):
! 10487: case COND_FLOAT_MOV(MOVF, 5):
! 10488: case COND_FLOAT_MOV(MOVF, 6):
! 10489: case COND_FLOAT_MOV(MOVF, 7):
! 10490: gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
! 10491: break;
! 10492: default:
! 10493: MIPS_INVAL("pool32fxf");
! 10494: generate_exception(ctx, EXCP_RI);
! 10495: break;
! 10496: }
! 10497: }
! 10498:
! 10499: static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
! 10500: uint16_t insn_hw1, int *is_branch)
! 10501: {
! 10502: int32_t offset;
! 10503: uint16_t insn;
! 10504: int rt, rs, rd, rr;
! 10505: int16_t imm;
! 10506: uint32_t op, minor, mips32_op;
! 10507: uint32_t cond, fmt, cc;
! 10508:
! 10509: insn = lduw_code(ctx->pc + 2);
! 10510: ctx->opcode = (ctx->opcode << 16) | insn;
! 10511:
! 10512: rt = (ctx->opcode >> 21) & 0x1f;
! 10513: rs = (ctx->opcode >> 16) & 0x1f;
! 10514: rd = (ctx->opcode >> 11) & 0x1f;
! 10515: rr = (ctx->opcode >> 6) & 0x1f;
! 10516: imm = (int16_t) ctx->opcode;
! 10517:
! 10518: op = (ctx->opcode >> 26) & 0x3f;
! 10519: switch (op) {
! 10520: case POOL32A:
! 10521: minor = ctx->opcode & 0x3f;
! 10522: switch (minor) {
! 10523: case 0x00:
! 10524: minor = (ctx->opcode >> 6) & 0xf;
! 10525: switch (minor) {
! 10526: case SLL32:
! 10527: mips32_op = OPC_SLL;
! 10528: goto do_shifti;
! 10529: case SRA:
! 10530: mips32_op = OPC_SRA;
! 10531: goto do_shifti;
! 10532: case SRL32:
! 10533: mips32_op = OPC_SRL;
! 10534: goto do_shifti;
! 10535: case ROTR:
! 10536: mips32_op = OPC_ROTR;
! 10537: do_shifti:
! 10538: gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
! 10539: break;
! 10540: default:
! 10541: goto pool32a_invalid;
! 10542: }
! 10543: break;
! 10544: case 0x10:
! 10545: minor = (ctx->opcode >> 6) & 0xf;
! 10546: switch (minor) {
! 10547: /* Arithmetic */
! 10548: case ADD:
! 10549: mips32_op = OPC_ADD;
! 10550: goto do_arith;
! 10551: case ADDU32:
! 10552: mips32_op = OPC_ADDU;
! 10553: goto do_arith;
! 10554: case SUB:
! 10555: mips32_op = OPC_SUB;
! 10556: goto do_arith;
! 10557: case SUBU32:
! 10558: mips32_op = OPC_SUBU;
! 10559: goto do_arith;
! 10560: case MUL:
! 10561: mips32_op = OPC_MUL;
! 10562: do_arith:
! 10563: gen_arith(env, ctx, mips32_op, rd, rs, rt);
! 10564: break;
! 10565: /* Shifts */
! 10566: case SLLV:
! 10567: mips32_op = OPC_SLLV;
! 10568: goto do_shift;
! 10569: case SRLV:
! 10570: mips32_op = OPC_SRLV;
! 10571: goto do_shift;
! 10572: case SRAV:
! 10573: mips32_op = OPC_SRAV;
! 10574: goto do_shift;
! 10575: case ROTRV:
! 10576: mips32_op = OPC_ROTRV;
! 10577: do_shift:
! 10578: gen_shift(env, ctx, mips32_op, rd, rs, rt);
! 10579: break;
! 10580: /* Logical operations */
! 10581: case AND:
! 10582: mips32_op = OPC_AND;
! 10583: goto do_logic;
! 10584: case OR32:
! 10585: mips32_op = OPC_OR;
! 10586: goto do_logic;
! 10587: case NOR:
! 10588: mips32_op = OPC_NOR;
! 10589: goto do_logic;
! 10590: case XOR32:
! 10591: mips32_op = OPC_XOR;
! 10592: do_logic:
! 10593: gen_logic(env, mips32_op, rd, rs, rt);
! 10594: break;
! 10595: /* Set less than */
! 10596: case SLT:
! 10597: mips32_op = OPC_SLT;
! 10598: goto do_slt;
! 10599: case SLTU:
! 10600: mips32_op = OPC_SLTU;
! 10601: do_slt:
! 10602: gen_slt(env, mips32_op, rd, rs, rt);
! 10603: break;
! 10604: default:
! 10605: goto pool32a_invalid;
! 10606: }
! 10607: break;
! 10608: case 0x18:
! 10609: minor = (ctx->opcode >> 6) & 0xf;
! 10610: switch (minor) {
! 10611: /* Conditional moves */
! 10612: case MOVN:
! 10613: mips32_op = OPC_MOVN;
! 10614: goto do_cmov;
! 10615: case MOVZ:
! 10616: mips32_op = OPC_MOVZ;
! 10617: do_cmov:
! 10618: gen_cond_move(env, mips32_op, rd, rs, rt);
! 10619: break;
! 10620: case LWXS:
! 10621: gen_ldxs(ctx, rs, rt, rd);
! 10622: break;
! 10623: default:
! 10624: goto pool32a_invalid;
! 10625: }
! 10626: break;
! 10627: case INS:
! 10628: gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
! 10629: return;
! 10630: case EXT:
! 10631: gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
! 10632: return;
! 10633: case POOL32AXF:
! 10634: gen_pool32axf(env, ctx, rt, rs, is_branch);
! 10635: break;
! 10636: case 0x07:
! 10637: generate_exception(ctx, EXCP_BREAK);
! 10638: break;
! 10639: default:
! 10640: pool32a_invalid:
! 10641: MIPS_INVAL("pool32a");
! 10642: generate_exception(ctx, EXCP_RI);
! 10643: break;
! 10644: }
! 10645: break;
! 10646: case POOL32B:
! 10647: minor = (ctx->opcode >> 12) & 0xf;
! 10648: switch (minor) {
! 10649: case CACHE:
! 10650: /* Treat as no-op. */
! 10651: break;
! 10652: case LWC2:
! 10653: case SWC2:
! 10654: /* COP2: Not implemented. */
! 10655: generate_exception_err(ctx, EXCP_CpU, 2);
! 10656: break;
! 10657: case LWP:
! 10658: case SWP:
! 10659: #ifdef TARGET_MIPS64
! 10660: case LDP:
! 10661: case SDP:
! 10662: #endif
! 10663: gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
! 10664: break;
! 10665: case LWM32:
! 10666: case SWM32:
! 10667: #ifdef TARGET_MIPS64
! 10668: case LDM:
! 10669: case SDM:
! 10670: #endif
! 10671: gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
! 10672: break;
! 10673: default:
! 10674: MIPS_INVAL("pool32b");
! 10675: generate_exception(ctx, EXCP_RI);
! 10676: break;
! 10677: }
! 10678: break;
! 10679: case POOL32F:
! 10680: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
! 10681: minor = ctx->opcode & 0x3f;
! 10682: check_cp1_enabled(ctx);
! 10683: switch (minor) {
! 10684: case ALNV_PS:
! 10685: mips32_op = OPC_ALNV_PS;
! 10686: goto do_madd;
! 10687: case MADD_S:
! 10688: mips32_op = OPC_MADD_S;
! 10689: goto do_madd;
! 10690: case MADD_D:
! 10691: mips32_op = OPC_MADD_D;
! 10692: goto do_madd;
! 10693: case MADD_PS:
! 10694: mips32_op = OPC_MADD_PS;
! 10695: goto do_madd;
! 10696: case MSUB_S:
! 10697: mips32_op = OPC_MSUB_S;
! 10698: goto do_madd;
! 10699: case MSUB_D:
! 10700: mips32_op = OPC_MSUB_D;
! 10701: goto do_madd;
! 10702: case MSUB_PS:
! 10703: mips32_op = OPC_MSUB_PS;
! 10704: goto do_madd;
! 10705: case NMADD_S:
! 10706: mips32_op = OPC_NMADD_S;
! 10707: goto do_madd;
! 10708: case NMADD_D:
! 10709: mips32_op = OPC_NMADD_D;
! 10710: goto do_madd;
! 10711: case NMADD_PS:
! 10712: mips32_op = OPC_NMADD_PS;
! 10713: goto do_madd;
! 10714: case NMSUB_S:
! 10715: mips32_op = OPC_NMSUB_S;
! 10716: goto do_madd;
! 10717: case NMSUB_D:
! 10718: mips32_op = OPC_NMSUB_D;
! 10719: goto do_madd;
! 10720: case NMSUB_PS:
! 10721: mips32_op = OPC_NMSUB_PS;
! 10722: do_madd:
! 10723: gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
! 10724: break;
! 10725: case CABS_COND_FMT:
! 10726: cond = (ctx->opcode >> 6) & 0xf;
! 10727: cc = (ctx->opcode >> 13) & 0x7;
! 10728: fmt = (ctx->opcode >> 10) & 0x3;
! 10729: switch (fmt) {
! 10730: case 0x0:
! 10731: gen_cmpabs_s(ctx, cond, rt, rs, cc);
! 10732: break;
! 10733: case 0x1:
! 10734: gen_cmpabs_d(ctx, cond, rt, rs, cc);
! 10735: break;
! 10736: case 0x2:
! 10737: gen_cmpabs_ps(ctx, cond, rt, rs, cc);
! 10738: break;
! 10739: default:
! 10740: goto pool32f_invalid;
! 10741: }
! 10742: break;
! 10743: case C_COND_FMT:
! 10744: cond = (ctx->opcode >> 6) & 0xf;
! 10745: cc = (ctx->opcode >> 13) & 0x7;
! 10746: fmt = (ctx->opcode >> 10) & 0x3;
! 10747: switch (fmt) {
! 10748: case 0x0:
! 10749: gen_cmp_s(ctx, cond, rt, rs, cc);
! 10750: break;
! 10751: case 0x1:
! 10752: gen_cmp_d(ctx, cond, rt, rs, cc);
! 10753: break;
! 10754: case 0x2:
! 10755: gen_cmp_ps(ctx, cond, rt, rs, cc);
! 10756: break;
! 10757: default:
! 10758: goto pool32f_invalid;
! 10759: }
! 10760: break;
! 10761: case POOL32FXF:
! 10762: gen_pool32fxf(env, ctx, rt, rs);
! 10763: break;
! 10764: case 0x00:
! 10765: /* PLL foo */
! 10766: switch ((ctx->opcode >> 6) & 0x7) {
! 10767: case PLL_PS:
! 10768: mips32_op = OPC_PLL_PS;
! 10769: goto do_ps;
! 10770: case PLU_PS:
! 10771: mips32_op = OPC_PLU_PS;
! 10772: goto do_ps;
! 10773: case PUL_PS:
! 10774: mips32_op = OPC_PUL_PS;
! 10775: goto do_ps;
! 10776: case PUU_PS:
! 10777: mips32_op = OPC_PUU_PS;
! 10778: goto do_ps;
! 10779: case CVT_PS_S:
! 10780: mips32_op = OPC_CVT_PS_S;
! 10781: do_ps:
! 10782: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
! 10783: break;
! 10784: default:
! 10785: goto pool32f_invalid;
! 10786: }
! 10787: break;
! 10788: case 0x08:
! 10789: /* [LS][WDU]XC1 */
! 10790: switch ((ctx->opcode >> 6) & 0x7) {
! 10791: case LWXC1:
! 10792: mips32_op = OPC_LWXC1;
! 10793: goto do_ldst_cp1;
! 10794: case SWXC1:
! 10795: mips32_op = OPC_SWXC1;
! 10796: goto do_ldst_cp1;
! 10797: case LDXC1:
! 10798: mips32_op = OPC_LDXC1;
! 10799: goto do_ldst_cp1;
! 10800: case SDXC1:
! 10801: mips32_op = OPC_SDXC1;
! 10802: goto do_ldst_cp1;
! 10803: case LUXC1:
! 10804: mips32_op = OPC_LUXC1;
! 10805: goto do_ldst_cp1;
! 10806: case SUXC1:
! 10807: mips32_op = OPC_SUXC1;
! 10808: do_ldst_cp1:
! 10809: gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
! 10810: break;
! 10811: default:
! 10812: goto pool32f_invalid;
! 10813: }
! 10814: break;
! 10815: case 0x18:
! 10816: /* 3D insns */
! 10817: fmt = (ctx->opcode >> 9) & 0x3;
! 10818: switch ((ctx->opcode >> 6) & 0x7) {
! 10819: case RSQRT2_FMT:
! 10820: switch (fmt) {
! 10821: case FMT_SDPS_S:
! 10822: mips32_op = OPC_RSQRT2_S;
! 10823: goto do_3d;
! 10824: case FMT_SDPS_D:
! 10825: mips32_op = OPC_RSQRT2_D;
! 10826: goto do_3d;
! 10827: case FMT_SDPS_PS:
! 10828: mips32_op = OPC_RSQRT2_PS;
! 10829: goto do_3d;
! 10830: default:
! 10831: goto pool32f_invalid;
! 10832: }
! 10833: break;
! 10834: case RECIP2_FMT:
! 10835: switch (fmt) {
! 10836: case FMT_SDPS_S:
! 10837: mips32_op = OPC_RECIP2_S;
! 10838: goto do_3d;
! 10839: case FMT_SDPS_D:
! 10840: mips32_op = OPC_RECIP2_D;
! 10841: goto do_3d;
! 10842: case FMT_SDPS_PS:
! 10843: mips32_op = OPC_RECIP2_PS;
! 10844: goto do_3d;
! 10845: default:
! 10846: goto pool32f_invalid;
! 10847: }
! 10848: break;
! 10849: case ADDR_PS:
! 10850: mips32_op = OPC_ADDR_PS;
! 10851: goto do_3d;
! 10852: case MULR_PS:
! 10853: mips32_op = OPC_MULR_PS;
! 10854: do_3d:
! 10855: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
! 10856: break;
! 10857: default:
! 10858: goto pool32f_invalid;
! 10859: }
! 10860: break;
! 10861: case 0x20:
! 10862: /* MOV[FT].fmt and PREFX */
! 10863: cc = (ctx->opcode >> 13) & 0x7;
! 10864: fmt = (ctx->opcode >> 9) & 0x3;
! 10865: switch ((ctx->opcode >> 6) & 0x7) {
! 10866: case MOVF_FMT:
! 10867: switch (fmt) {
! 10868: case FMT_SDPS_S:
! 10869: gen_movcf_s(rs, rt, cc, 0);
! 10870: break;
! 10871: case FMT_SDPS_D:
! 10872: gen_movcf_d(ctx, rs, rt, cc, 0);
! 10873: break;
! 10874: case FMT_SDPS_PS:
! 10875: gen_movcf_ps(rs, rt, cc, 0);
! 10876: break;
! 10877: default:
! 10878: goto pool32f_invalid;
! 10879: }
! 10880: break;
! 10881: case MOVT_FMT:
! 10882: switch (fmt) {
! 10883: case FMT_SDPS_S:
! 10884: gen_movcf_s(rs, rt, cc, 1);
! 10885: break;
! 10886: case FMT_SDPS_D:
! 10887: gen_movcf_d(ctx, rs, rt, cc, 1);
! 10888: break;
! 10889: case FMT_SDPS_PS:
! 10890: gen_movcf_ps(rs, rt, cc, 1);
! 10891: break;
! 10892: default:
! 10893: goto pool32f_invalid;
! 10894: }
! 10895: break;
! 10896: case PREFX:
! 10897: break;
! 10898: default:
! 10899: goto pool32f_invalid;
! 10900: }
! 10901: break;
! 10902: #define FINSN_3ARG_SDPS(prfx) \
! 10903: switch ((ctx->opcode >> 8) & 0x3) { \
! 10904: case FMT_SDPS_S: \
! 10905: mips32_op = OPC_##prfx##_S; \
! 10906: goto do_fpop; \
! 10907: case FMT_SDPS_D: \
! 10908: mips32_op = OPC_##prfx##_D; \
! 10909: goto do_fpop; \
! 10910: case FMT_SDPS_PS: \
! 10911: mips32_op = OPC_##prfx##_PS; \
! 10912: goto do_fpop; \
! 10913: default: \
! 10914: goto pool32f_invalid; \
! 10915: }
! 10916: case 0x30:
! 10917: /* regular FP ops */
! 10918: switch ((ctx->opcode >> 6) & 0x3) {
! 10919: case ADD_FMT:
! 10920: FINSN_3ARG_SDPS(ADD);
! 10921: break;
! 10922: case SUB_FMT:
! 10923: FINSN_3ARG_SDPS(SUB);
! 10924: break;
! 10925: case MUL_FMT:
! 10926: FINSN_3ARG_SDPS(MUL);
! 10927: break;
! 10928: case DIV_FMT:
! 10929: fmt = (ctx->opcode >> 8) & 0x3;
! 10930: if (fmt == 1) {
! 10931: mips32_op = OPC_DIV_D;
! 10932: } else if (fmt == 0) {
! 10933: mips32_op = OPC_DIV_S;
! 10934: } else {
! 10935: goto pool32f_invalid;
! 10936: }
! 10937: goto do_fpop;
! 10938: default:
! 10939: goto pool32f_invalid;
! 10940: }
! 10941: break;
! 10942: case 0x38:
! 10943: /* cmovs */
! 10944: switch ((ctx->opcode >> 6) & 0x3) {
! 10945: case MOVN_FMT:
! 10946: FINSN_3ARG_SDPS(MOVN);
! 10947: break;
! 10948: case MOVZ_FMT:
! 10949: FINSN_3ARG_SDPS(MOVZ);
! 10950: break;
! 10951: default:
! 10952: goto pool32f_invalid;
! 10953: }
! 10954: break;
! 10955: do_fpop:
! 10956: gen_farith(ctx, mips32_op, rt, rs, rd, 0);
! 10957: break;
! 10958: default:
! 10959: pool32f_invalid:
! 10960: MIPS_INVAL("pool32f");
! 10961: generate_exception(ctx, EXCP_RI);
! 10962: break;
! 10963: }
! 10964: } else {
! 10965: generate_exception_err(ctx, EXCP_CpU, 1);
! 10966: }
! 10967: break;
! 10968: case POOL32I:
! 10969: minor = (ctx->opcode >> 21) & 0x1f;
! 10970: switch (minor) {
! 10971: case BLTZ:
! 10972: mips32_op = OPC_BLTZ;
! 10973: goto do_branch;
! 10974: case BLTZAL:
! 10975: mips32_op = OPC_BLTZAL;
! 10976: goto do_branch;
! 10977: case BLTZALS:
! 10978: mips32_op = OPC_BLTZALS;
! 10979: goto do_branch;
! 10980: case BGEZ:
! 10981: mips32_op = OPC_BGEZ;
! 10982: goto do_branch;
! 10983: case BGEZAL:
! 10984: mips32_op = OPC_BGEZAL;
! 10985: goto do_branch;
! 10986: case BGEZALS:
! 10987: mips32_op = OPC_BGEZALS;
! 10988: goto do_branch;
! 10989: case BLEZ:
! 10990: mips32_op = OPC_BLEZ;
! 10991: goto do_branch;
! 10992: case BGTZ:
! 10993: mips32_op = OPC_BGTZ;
! 10994: do_branch:
! 10995: gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
! 10996: *is_branch = 1;
! 10997: break;
! 10998:
! 10999: /* Traps */
! 11000: case TLTI:
! 11001: mips32_op = OPC_TLTI;
! 11002: goto do_trapi;
! 11003: case TGEI:
! 11004: mips32_op = OPC_TGEI;
! 11005: goto do_trapi;
! 11006: case TLTIU:
! 11007: mips32_op = OPC_TLTIU;
! 11008: goto do_trapi;
! 11009: case TGEIU:
! 11010: mips32_op = OPC_TGEIU;
! 11011: goto do_trapi;
! 11012: case TNEI:
! 11013: mips32_op = OPC_TNEI;
! 11014: goto do_trapi;
! 11015: case TEQI:
! 11016: mips32_op = OPC_TEQI;
! 11017: do_trapi:
! 11018: gen_trap(ctx, mips32_op, rs, -1, imm);
! 11019: break;
! 11020:
! 11021: case BNEZC:
! 11022: case BEQZC:
! 11023: gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
! 11024: 4, rs, 0, imm << 1);
! 11025: /* Compact branches don't have a delay slot, so just let
! 11026: the normal delay slot handling take us to the branch
! 11027: target. */
! 11028: break;
! 11029: case LUI:
! 11030: gen_logic_imm(env, OPC_LUI, rs, -1, imm);
! 11031: break;
! 11032: case SYNCI:
! 11033: break;
! 11034: case BC2F:
! 11035: case BC2T:
! 11036: /* COP2: Not implemented. */
! 11037: generate_exception_err(ctx, EXCP_CpU, 2);
! 11038: break;
! 11039: case BC1F:
! 11040: mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
! 11041: goto do_cp1branch;
! 11042: case BC1T:
! 11043: mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
! 11044: goto do_cp1branch;
! 11045: case BC1ANY4F:
! 11046: mips32_op = OPC_BC1FANY4;
! 11047: goto do_cp1mips3d;
! 11048: case BC1ANY4T:
! 11049: mips32_op = OPC_BC1TANY4;
! 11050: do_cp1mips3d:
! 11051: check_cop1x(ctx);
! 11052: check_insn(env, ctx, ASE_MIPS3D);
! 11053: /* Fall through */
! 11054: do_cp1branch:
! 11055: gen_compute_branch1(env, ctx, mips32_op,
! 11056: (ctx->opcode >> 18) & 0x7, imm << 1);
! 11057: *is_branch = 1;
! 11058: break;
! 11059: case BPOSGE64:
! 11060: case BPOSGE32:
! 11061: /* MIPS DSP: not implemented */
! 11062: /* Fall through */
! 11063: default:
! 11064: MIPS_INVAL("pool32i");
! 11065: generate_exception(ctx, EXCP_RI);
! 11066: break;
! 11067: }
! 11068: break;
! 11069: case POOL32C:
! 11070: minor = (ctx->opcode >> 12) & 0xf;
! 11071: switch (minor) {
! 11072: case LWL:
! 11073: mips32_op = OPC_LWL;
! 11074: goto do_ld_lr;
! 11075: case SWL:
! 11076: mips32_op = OPC_SWL;
! 11077: goto do_st_lr;
! 11078: case LWR:
! 11079: mips32_op = OPC_LWR;
! 11080: goto do_ld_lr;
! 11081: case SWR:
! 11082: mips32_op = OPC_SWR;
! 11083: goto do_st_lr;
! 11084: #if defined(TARGET_MIPS64)
! 11085: case LDL:
! 11086: mips32_op = OPC_LDL;
! 11087: goto do_ld_lr;
! 11088: case SDL:
! 11089: mips32_op = OPC_SDL;
! 11090: goto do_st_lr;
! 11091: case LDR:
! 11092: mips32_op = OPC_LDR;
! 11093: goto do_ld_lr;
! 11094: case SDR:
! 11095: mips32_op = OPC_SDR;
! 11096: goto do_st_lr;
! 11097: case LWU:
! 11098: mips32_op = OPC_LWU;
! 11099: goto do_ld_lr;
! 11100: case LLD:
! 11101: mips32_op = OPC_LLD;
! 11102: goto do_ld_lr;
! 11103: #endif
! 11104: case LL:
! 11105: mips32_op = OPC_LL;
! 11106: goto do_ld_lr;
! 11107: do_ld_lr:
! 11108: gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
! 11109: break;
! 11110: do_st_lr:
! 11111: gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
! 11112: break;
! 11113: case SC:
! 11114: gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
! 11115: break;
! 11116: #if defined(TARGET_MIPS64)
! 11117: case SCD:
! 11118: gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
! 11119: break;
! 11120: #endif
! 11121: case PREF:
! 11122: /* Treat as no-op */
! 11123: break;
! 11124: default:
! 11125: MIPS_INVAL("pool32c");
! 11126: generate_exception(ctx, EXCP_RI);
! 11127: break;
! 11128: }
! 11129: break;
! 11130: case ADDI32:
! 11131: mips32_op = OPC_ADDI;
! 11132: goto do_addi;
! 11133: case ADDIU32:
! 11134: mips32_op = OPC_ADDIU;
! 11135: do_addi:
! 11136: gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
! 11137: break;
! 11138:
! 11139: /* Logical operations */
! 11140: case ORI32:
! 11141: mips32_op = OPC_ORI;
! 11142: goto do_logici;
! 11143: case XORI32:
! 11144: mips32_op = OPC_XORI;
! 11145: goto do_logici;
! 11146: case ANDI32:
! 11147: mips32_op = OPC_ANDI;
! 11148: do_logici:
! 11149: gen_logic_imm(env, mips32_op, rt, rs, imm);
! 11150: break;
! 11151:
! 11152: /* Set less than immediate */
! 11153: case SLTI32:
! 11154: mips32_op = OPC_SLTI;
! 11155: goto do_slti;
! 11156: case SLTIU32:
! 11157: mips32_op = OPC_SLTIU;
! 11158: do_slti:
! 11159: gen_slt_imm(env, mips32_op, rt, rs, imm);
! 11160: break;
! 11161: case JALX32:
! 11162: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
! 11163: gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
! 11164: *is_branch = 1;
! 11165: break;
! 11166: case JALS32:
! 11167: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
! 11168: gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
! 11169: *is_branch = 1;
! 11170: break;
! 11171: case BEQ32:
! 11172: gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
! 11173: *is_branch = 1;
! 11174: break;
! 11175: case BNE32:
! 11176: gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
! 11177: *is_branch = 1;
! 11178: break;
! 11179: case J32:
! 11180: gen_compute_branch(ctx, OPC_J, 4, rt, rs,
! 11181: (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
! 11182: *is_branch = 1;
! 11183: break;
! 11184: case JAL32:
! 11185: gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
! 11186: (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
! 11187: *is_branch = 1;
! 11188: break;
! 11189: /* Floating point (COP1) */
! 11190: case LWC132:
! 11191: mips32_op = OPC_LWC1;
! 11192: goto do_cop1;
! 11193: case LDC132:
! 11194: mips32_op = OPC_LDC1;
! 11195: goto do_cop1;
! 11196: case SWC132:
! 11197: mips32_op = OPC_SWC1;
! 11198: goto do_cop1;
! 11199: case SDC132:
! 11200: mips32_op = OPC_SDC1;
! 11201: do_cop1:
! 11202: gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
! 11203: break;
! 11204: case ADDIUPC:
! 11205: {
! 11206: int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
! 11207: int offset = SIMM(ctx->opcode, 0, 23) << 2;
! 11208:
! 11209: gen_addiupc(ctx, reg, offset, 0, 0);
! 11210: }
! 11211: break;
! 11212: /* Loads and stores */
! 11213: case LB32:
! 11214: mips32_op = OPC_LB;
! 11215: goto do_ld;
! 11216: case LBU32:
! 11217: mips32_op = OPC_LBU;
! 11218: goto do_ld;
! 11219: case LH32:
! 11220: mips32_op = OPC_LH;
! 11221: goto do_ld;
! 11222: case LHU32:
! 11223: mips32_op = OPC_LHU;
! 11224: goto do_ld;
! 11225: case LW32:
! 11226: mips32_op = OPC_LW;
! 11227: goto do_ld;
! 11228: #ifdef TARGET_MIPS64
! 11229: case LD32:
! 11230: mips32_op = OPC_LD;
! 11231: goto do_ld;
! 11232: case SD32:
! 11233: mips32_op = OPC_SD;
! 11234: goto do_st;
! 11235: #endif
! 11236: case SB32:
! 11237: mips32_op = OPC_SB;
! 11238: goto do_st;
! 11239: case SH32:
! 11240: mips32_op = OPC_SH;
! 11241: goto do_st;
! 11242: case SW32:
! 11243: mips32_op = OPC_SW;
! 11244: goto do_st;
! 11245: do_ld:
! 11246: gen_ld(env, ctx, mips32_op, rt, rs, imm);
! 11247: break;
! 11248: do_st:
! 11249: gen_st(ctx, mips32_op, rt, rs, imm);
! 11250: break;
! 11251: default:
! 11252: generate_exception(ctx, EXCP_RI);
! 11253: break;
! 11254: }
! 11255: }
! 11256:
! 11257: static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
! 11258: {
! 11259: uint32_t op;
! 11260:
! 11261: /* make sure instructions are on a halfword boundary */
! 11262: if (ctx->pc & 0x1) {
! 11263: env->CP0_BadVAddr = ctx->pc;
! 11264: generate_exception(ctx, EXCP_AdEL);
! 11265: ctx->bstate = BS_STOP;
! 11266: return 2;
! 11267: }
! 11268:
! 11269: op = (ctx->opcode >> 10) & 0x3f;
! 11270: /* Enforce properly-sized instructions in a delay slot */
! 11271: if (ctx->hflags & MIPS_HFLAG_BMASK) {
! 11272: int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
! 11273:
! 11274: switch (op) {
! 11275: case POOL32A:
! 11276: case POOL32B:
! 11277: case POOL32I:
! 11278: case POOL32C:
! 11279: case ADDI32:
! 11280: case ADDIU32:
! 11281: case ORI32:
! 11282: case XORI32:
! 11283: case SLTI32:
! 11284: case SLTIU32:
! 11285: case ANDI32:
! 11286: case JALX32:
! 11287: case LBU32:
! 11288: case LHU32:
! 11289: case POOL32F:
! 11290: case JALS32:
! 11291: case BEQ32:
! 11292: case BNE32:
! 11293: case J32:
! 11294: case JAL32:
! 11295: case SB32:
! 11296: case SH32:
! 11297: case POOL32S:
! 11298: case ADDIUPC:
! 11299: case SWC132:
! 11300: case SDC132:
! 11301: case SD32:
! 11302: case SW32:
! 11303: case LB32:
! 11304: case LH32:
! 11305: case DADDIU32:
! 11306: case POOL48A: /* ??? */
! 11307: case LWC132:
! 11308: case LDC132:
! 11309: case LD32:
! 11310: case LW32:
! 11311: if (bits & MIPS_HFLAG_BDS16) {
! 11312: generate_exception(ctx, EXCP_RI);
! 11313: /* Just stop translation; the user is confused. */
! 11314: ctx->bstate = BS_STOP;
! 11315: return 2;
! 11316: }
! 11317: break;
! 11318: case POOL16A:
! 11319: case POOL16B:
! 11320: case POOL16C:
! 11321: case LWGP16:
! 11322: case POOL16F:
! 11323: case LBU16:
! 11324: case LHU16:
! 11325: case LWSP16:
! 11326: case LW16:
! 11327: case SB16:
! 11328: case SH16:
! 11329: case SWSP16:
! 11330: case SW16:
! 11331: case MOVE16:
! 11332: case ANDI16:
! 11333: case POOL16D:
! 11334: case POOL16E:
! 11335: case BEQZ16:
! 11336: case BNEZ16:
! 11337: case B16:
! 11338: case LI16:
! 11339: if (bits & MIPS_HFLAG_BDS32) {
! 11340: generate_exception(ctx, EXCP_RI);
! 11341: /* Just stop translation; the user is confused. */
! 11342: ctx->bstate = BS_STOP;
! 11343: return 2;
! 11344: }
! 11345: break;
! 11346: default:
! 11347: break;
! 11348: }
! 11349: }
! 11350: switch (op) {
! 11351: case POOL16A:
! 11352: {
! 11353: int rd = mmreg(uMIPS_RD(ctx->opcode));
! 11354: int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
! 11355: int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
! 11356: uint32_t opc = 0;
! 11357:
! 11358: switch (ctx->opcode & 0x1) {
! 11359: case ADDU16:
! 11360: opc = OPC_ADDU;
! 11361: break;
! 11362: case SUBU16:
! 11363: opc = OPC_SUBU;
! 11364: break;
! 11365: }
! 11366:
! 11367: gen_arith(env, ctx, opc, rd, rs1, rs2);
! 11368: }
! 11369: break;
! 11370: case POOL16B:
! 11371: {
! 11372: int rd = mmreg(uMIPS_RD(ctx->opcode));
! 11373: int rs = mmreg(uMIPS_RS(ctx->opcode));
! 11374: int amount = (ctx->opcode >> 1) & 0x7;
! 11375: uint32_t opc = 0;
! 11376: amount = amount == 0 ? 8 : amount;
! 11377:
! 11378: switch (ctx->opcode & 0x1) {
! 11379: case SLL16:
! 11380: opc = OPC_SLL;
! 11381: break;
! 11382: case SRL16:
! 11383: opc = OPC_SRL;
! 11384: break;
! 11385: }
! 11386:
! 11387: gen_shift_imm(env, ctx, opc, rd, rs, amount);
! 11388: }
! 11389: break;
! 11390: case POOL16C:
! 11391: gen_pool16c_insn(env, ctx, is_branch);
! 11392: break;
! 11393: case LWGP16:
! 11394: {
! 11395: int rd = mmreg(uMIPS_RD(ctx->opcode));
! 11396: int rb = 28; /* GP */
! 11397: int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
! 11398:
! 11399: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
! 11400: }
! 11401: break;
! 11402: case POOL16F:
! 11403: if (ctx->opcode & 1) {
! 11404: generate_exception(ctx, EXCP_RI);
! 11405: } else {
! 11406: /* MOVEP */
! 11407: int enc_dest = uMIPS_RD(ctx->opcode);
! 11408: int enc_rt = uMIPS_RS2(ctx->opcode);
! 11409: int enc_rs = uMIPS_RS1(ctx->opcode);
! 11410: int rd, rs, re, rt;
! 11411: static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
! 11412: static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
! 11413: static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
! 11414:
! 11415: rd = rd_enc[enc_dest];
! 11416: re = re_enc[enc_dest];
! 11417: rs = rs_rt_enc[enc_rs];
! 11418: rt = rs_rt_enc[enc_rt];
! 11419:
! 11420: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
! 11421: gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
! 11422: }
! 11423: break;
! 11424: case LBU16:
! 11425: {
! 11426: int rd = mmreg(uMIPS_RD(ctx->opcode));
! 11427: int rb = mmreg(uMIPS_RS(ctx->opcode));
! 11428: int16_t offset = ZIMM(ctx->opcode, 0, 4);
! 11429: offset = (offset == 0xf ? -1 : offset);
! 11430:
! 11431: gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
! 11432: }
! 11433: break;
! 11434: case LHU16:
! 11435: {
! 11436: int rd = mmreg(uMIPS_RD(ctx->opcode));
! 11437: int rb = mmreg(uMIPS_RS(ctx->opcode));
! 11438: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
! 11439:
! 11440: gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
! 11441: }
! 11442: break;
! 11443: case LWSP16:
! 11444: {
! 11445: int rd = (ctx->opcode >> 5) & 0x1f;
! 11446: int rb = 29; /* SP */
! 11447: int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
! 11448:
! 11449: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
! 11450: }
! 11451: break;
! 11452: case LW16:
! 11453: {
! 11454: int rd = mmreg(uMIPS_RD(ctx->opcode));
! 11455: int rb = mmreg(uMIPS_RS(ctx->opcode));
! 11456: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
! 11457:
! 11458: gen_ld(env, ctx, OPC_LW, rd, rb, offset);
! 11459: }
! 11460: break;
! 11461: case SB16:
! 11462: {
! 11463: int rd = mmreg2(uMIPS_RD(ctx->opcode));
! 11464: int rb = mmreg(uMIPS_RS(ctx->opcode));
! 11465: int16_t offset = ZIMM(ctx->opcode, 0, 4);
! 11466:
! 11467: gen_st(ctx, OPC_SB, rd, rb, offset);
! 11468: }
! 11469: break;
! 11470: case SH16:
! 11471: {
! 11472: int rd = mmreg2(uMIPS_RD(ctx->opcode));
! 11473: int rb = mmreg(uMIPS_RS(ctx->opcode));
! 11474: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
! 11475:
! 11476: gen_st(ctx, OPC_SH, rd, rb, offset);
! 11477: }
! 11478: break;
! 11479: case SWSP16:
! 11480: {
! 11481: int rd = (ctx->opcode >> 5) & 0x1f;
! 11482: int rb = 29; /* SP */
! 11483: int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
! 11484:
! 11485: gen_st(ctx, OPC_SW, rd, rb, offset);
! 11486: }
! 11487: break;
! 11488: case SW16:
! 11489: {
! 11490: int rd = mmreg2(uMIPS_RD(ctx->opcode));
! 11491: int rb = mmreg(uMIPS_RS(ctx->opcode));
! 11492: int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
! 11493:
! 11494: gen_st(ctx, OPC_SW, rd, rb, offset);
! 11495: }
! 11496: break;
! 11497: case MOVE16:
! 11498: {
! 11499: int rd = uMIPS_RD5(ctx->opcode);
! 11500: int rs = uMIPS_RS5(ctx->opcode);
! 11501:
! 11502: gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
! 11503: }
! 11504: break;
! 11505: case ANDI16:
! 11506: gen_andi16(env, ctx);
! 11507: break;
! 11508: case POOL16D:
! 11509: switch (ctx->opcode & 0x1) {
! 11510: case ADDIUS5:
! 11511: gen_addius5(env, ctx);
! 11512: break;
! 11513: case ADDIUSP:
! 11514: gen_addiusp(env, ctx);
! 11515: break;
! 11516: }
! 11517: break;
! 11518: case POOL16E:
! 11519: switch (ctx->opcode & 0x1) {
! 11520: case ADDIUR2:
! 11521: gen_addiur2(env, ctx);
! 11522: break;
! 11523: case ADDIUR1SP:
! 11524: gen_addiur1sp(env, ctx);
! 11525: break;
! 11526: }
! 11527: break;
! 11528: case B16:
! 11529: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
! 11530: SIMM(ctx->opcode, 0, 10) << 1);
! 11531: *is_branch = 1;
! 11532: break;
! 11533: case BNEZ16:
! 11534: case BEQZ16:
! 11535: gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
! 11536: mmreg(uMIPS_RD(ctx->opcode)),
! 11537: 0, SIMM(ctx->opcode, 0, 7) << 1);
! 11538: *is_branch = 1;
! 11539: break;
! 11540: case LI16:
! 11541: {
! 11542: int reg = mmreg(uMIPS_RD(ctx->opcode));
! 11543: int imm = ZIMM(ctx->opcode, 0, 7);
! 11544:
! 11545: imm = (imm == 0x7f ? -1 : imm);
! 11546: tcg_gen_movi_tl(cpu_gpr[reg], imm);
! 11547: }
! 11548: break;
! 11549: case RES_20:
! 11550: case RES_28:
! 11551: case RES_29:
! 11552: case RES_30:
! 11553: case RES_31:
! 11554: case RES_38:
! 11555: case RES_39:
! 11556: generate_exception(ctx, EXCP_RI);
! 11557: break;
! 11558: default:
! 11559: decode_micromips32_opc (env, ctx, op, is_branch);
! 11560: return 4;
! 11561: }
! 11562:
! 11563: return 2;
! 11564: }
! 11565:
! 11566: /* SmartMIPS extension to MIPS32 */
! 11567:
! 11568: #if defined(TARGET_MIPS64)
! 11569:
! 11570: /* MDMX extension to MIPS64 */
! 11571:
! 11572: #endif
! 11573:
! 11574: static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
! 11575: {
! 11576: int32_t offset;
! 11577: int rs, rt, rd, sa;
! 11578: uint32_t op, op1, op2;
! 11579: int16_t imm;
! 11580:
! 11581: /* make sure instructions are on a word boundary */
! 11582: if (ctx->pc & 0x3) {
! 11583: env->CP0_BadVAddr = ctx->pc;
! 11584: generate_exception(ctx, EXCP_AdEL);
! 11585: return;
! 11586: }
! 11587:
! 11588: /* Handle blikely not taken case */
! 11589: if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
! 11590: int l1 = gen_new_label();
! 11591:
! 11592: MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
1.1.1.8 root 11593: tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11594: tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
1.1.1.6 root 11595: gen_goto_tb(ctx, 1, ctx->pc + 4);
11596: gen_set_label(l1);
1.1 root 11597: }
1.1.1.9 root 11598:
11599: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11600: tcg_gen_debug_insn_start(ctx->pc);
11601:
1.1.1.5 root 11602: op = MASK_OP_MAJOR(ctx->opcode);
11603: rs = (ctx->opcode >> 21) & 0x1f;
11604: rt = (ctx->opcode >> 16) & 0x1f;
11605: rd = (ctx->opcode >> 11) & 0x1f;
11606: sa = (ctx->opcode >> 6) & 0x1f;
1.1 root 11607: imm = (int16_t)ctx->opcode;
11608: switch (op) {
1.1.1.5 root 11609: case OPC_SPECIAL:
11610: op1 = MASK_SPECIAL(ctx->opcode);
1.1 root 11611: switch (op1) {
1.1.1.8 root 11612: case OPC_SLL: /* Shift with immediate */
11613: case OPC_SRA:
11614: gen_shift_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 11615: break;
1.1.1.12! root 11616: case OPC_SRL:
! 11617: switch ((ctx->opcode >> 21) & 0x1f) {
! 11618: case 1:
! 11619: /* rotr is decoded as srl on non-R2 CPUs */
! 11620: if (env->insn_flags & ISA_MIPS32R2) {
! 11621: op1 = OPC_ROTR;
! 11622: }
! 11623: /* Fallthrough */
! 11624: case 0:
! 11625: gen_shift_imm(env, ctx, op1, rd, rt, sa);
! 11626: break;
! 11627: default:
! 11628: generate_exception(ctx, EXCP_RI);
! 11629: break;
! 11630: }
! 11631: break;
1.1.1.8 root 11632: case OPC_MOVN: /* Conditional move */
11633: case OPC_MOVZ:
1.1.1.12! root 11634: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
! 11635: INSN_LOONGSON2E | INSN_LOONGSON2F);
1.1.1.8 root 11636: gen_cond_move(env, op1, rd, rs, rt);
11637: break;
11638: case OPC_ADD ... OPC_SUBU:
1.1.1.6 root 11639: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 11640: break;
1.1.1.8 root 11641: case OPC_SLLV: /* Shifts */
11642: case OPC_SRAV:
11643: gen_shift(env, ctx, op1, rd, rs, rt);
11644: break;
1.1.1.12! root 11645: case OPC_SRLV:
! 11646: switch ((ctx->opcode >> 6) & 0x1f) {
! 11647: case 1:
! 11648: /* rotrv is decoded as srlv on non-R2 CPUs */
! 11649: if (env->insn_flags & ISA_MIPS32R2) {
! 11650: op1 = OPC_ROTRV;
! 11651: }
! 11652: /* Fallthrough */
! 11653: case 0:
! 11654: gen_shift(env, ctx, op1, rd, rs, rt);
! 11655: break;
! 11656: default:
! 11657: generate_exception(ctx, EXCP_RI);
! 11658: break;
! 11659: }
! 11660: break;
1.1.1.8 root 11661: case OPC_SLT: /* Set on less than */
11662: case OPC_SLTU:
11663: gen_slt(env, op1, rd, rs, rt);
11664: break;
11665: case OPC_AND: /* Logic*/
11666: case OPC_OR:
11667: case OPC_NOR:
11668: case OPC_XOR:
11669: gen_logic(env, op1, rd, rs, rt);
11670: break;
1.1.1.5 root 11671: case OPC_MULT ... OPC_DIVU:
1.1.1.6 root 11672: if (sa) {
11673: check_insn(env, ctx, INSN_VR54XX);
11674: op1 = MASK_MUL_VR54XX(ctx->opcode);
11675: gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11676: } else
11677: gen_muldiv(ctx, op1, rs, rt);
1.1 root 11678: break;
1.1.1.5 root 11679: case OPC_JR ... OPC_JALR:
1.1.1.12! root 11680: gen_compute_branch(ctx, op1, 4, rs, rd, sa);
! 11681: *is_branch = 1;
! 11682: break;
1.1.1.5 root 11683: case OPC_TGE ... OPC_TEQ: /* Traps */
11684: case OPC_TNE:
11685: gen_trap(ctx, op1, rs, rt, -1);
11686: break;
11687: case OPC_MFHI: /* Move from HI/LO */
11688: case OPC_MFLO:
11689: gen_HILO(ctx, op1, rd);
1.1 root 11690: break;
1.1.1.5 root 11691: case OPC_MTHI:
11692: case OPC_MTLO: /* Move to HI/LO */
11693: gen_HILO(ctx, op1, rs);
11694: break;
1.1.1.6 root 11695: case OPC_PMON: /* Pmon entry point, also R4010 selsl */
11696: #ifdef MIPS_STRICT_STANDARD
11697: MIPS_INVAL("PMON / selsl");
11698: generate_exception(ctx, EXCP_RI);
11699: #else
1.1.1.7 root 11700: gen_helper_0i(pmon, sa);
1.1.1.6 root 11701: #endif
1.1.1.5 root 11702: break;
11703: case OPC_SYSCALL:
1.1 root 11704: generate_exception(ctx, EXCP_SYSCALL);
1.1.1.8 root 11705: ctx->bstate = BS_STOP;
1.1 root 11706: break;
1.1.1.5 root 11707: case OPC_BREAK:
1.1 root 11708: generate_exception(ctx, EXCP_BREAK);
11709: break;
1.1.1.6 root 11710: case OPC_SPIM:
11711: #ifdef MIPS_STRICT_STANDARD
11712: MIPS_INVAL("SPIM");
11713: generate_exception(ctx, EXCP_RI);
11714: #else
1.1.1.5 root 11715: /* Implemented as RI exception for now. */
11716: MIPS_INVAL("spim (unofficial)");
11717: generate_exception(ctx, EXCP_RI);
1.1.1.6 root 11718: #endif
1.1 root 11719: break;
1.1.1.5 root 11720: case OPC_SYNC:
1.1.1.6 root 11721: /* Treat as NOP. */
1.1 root 11722: break;
1.1.1.2 root 11723:
1.1.1.5 root 11724: case OPC_MOVCI:
1.1.1.6 root 11725: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
11726: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11727: check_cp1_enabled(ctx);
11728: gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11729: (ctx->opcode >> 16) & 1);
11730: } else {
11731: generate_exception_err(ctx, EXCP_CpU, 1);
11732: }
1.1.1.2 root 11733: break;
11734:
1.1.1.6 root 11735: #if defined(TARGET_MIPS64)
1.1.1.5 root 11736: /* MIPS64 specific opcodes */
11737: case OPC_DSLL:
1.1.1.8 root 11738: case OPC_DSRA:
1.1.1.5 root 11739: case OPC_DSLL32:
1.1.1.8 root 11740: case OPC_DSRA32:
1.1.1.6 root 11741: check_insn(env, ctx, ISA_MIPS3);
11742: check_mips_64(ctx);
1.1.1.8 root 11743: gen_shift_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 11744: break;
1.1.1.12! root 11745: case OPC_DSRL:
! 11746: switch ((ctx->opcode >> 21) & 0x1f) {
! 11747: case 1:
! 11748: /* drotr is decoded as dsrl on non-R2 CPUs */
! 11749: if (env->insn_flags & ISA_MIPS32R2) {
! 11750: op1 = OPC_DROTR;
! 11751: }
! 11752: /* Fallthrough */
! 11753: case 0:
! 11754: check_insn(env, ctx, ISA_MIPS3);
! 11755: check_mips_64(ctx);
! 11756: gen_shift_imm(env, ctx, op1, rd, rt, sa);
! 11757: break;
! 11758: default:
! 11759: generate_exception(ctx, EXCP_RI);
! 11760: break;
! 11761: }
! 11762: break;
! 11763: case OPC_DSRL32:
! 11764: switch ((ctx->opcode >> 21) & 0x1f) {
! 11765: case 1:
! 11766: /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
! 11767: if (env->insn_flags & ISA_MIPS32R2) {
! 11768: op1 = OPC_DROTR32;
! 11769: }
! 11770: /* Fallthrough */
! 11771: case 0:
! 11772: check_insn(env, ctx, ISA_MIPS3);
! 11773: check_mips_64(ctx);
! 11774: gen_shift_imm(env, ctx, op1, rd, rt, sa);
! 11775: break;
! 11776: default:
! 11777: generate_exception(ctx, EXCP_RI);
! 11778: break;
! 11779: }
! 11780: break;
1.1.1.5 root 11781: case OPC_DADD ... OPC_DSUBU:
1.1.1.6 root 11782: check_insn(env, ctx, ISA_MIPS3);
11783: check_mips_64(ctx);
11784: gen_arith(env, ctx, op1, rd, rs, rt);
1.1.1.5 root 11785: break;
1.1.1.8 root 11786: case OPC_DSLLV:
11787: case OPC_DSRAV:
11788: check_insn(env, ctx, ISA_MIPS3);
11789: check_mips_64(ctx);
11790: gen_shift(env, ctx, op1, rd, rs, rt);
11791: break;
1.1.1.12! root 11792: case OPC_DSRLV:
! 11793: switch ((ctx->opcode >> 6) & 0x1f) {
! 11794: case 1:
! 11795: /* drotrv is decoded as dsrlv on non-R2 CPUs */
! 11796: if (env->insn_flags & ISA_MIPS32R2) {
! 11797: op1 = OPC_DROTRV;
! 11798: }
! 11799: /* Fallthrough */
! 11800: case 0:
! 11801: check_insn(env, ctx, ISA_MIPS3);
! 11802: check_mips_64(ctx);
! 11803: gen_shift(env, ctx, op1, rd, rs, rt);
! 11804: break;
! 11805: default:
! 11806: generate_exception(ctx, EXCP_RI);
! 11807: break;
! 11808: }
! 11809: break;
1.1.1.5 root 11810: case OPC_DMULT ... OPC_DDIVU:
1.1.1.6 root 11811: check_insn(env, ctx, ISA_MIPS3);
11812: check_mips_64(ctx);
1.1.1.5 root 11813: gen_muldiv(ctx, op1, rs, rt);
11814: break;
1.1 root 11815: #endif
11816: default: /* Invalid */
11817: MIPS_INVAL("special");
11818: generate_exception(ctx, EXCP_RI);
11819: break;
11820: }
11821: break;
1.1.1.5 root 11822: case OPC_SPECIAL2:
11823: op1 = MASK_SPECIAL2(ctx->opcode);
1.1 root 11824: switch (op1) {
1.1.1.5 root 11825: case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11826: case OPC_MSUB ... OPC_MSUBU:
1.1.1.6 root 11827: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 11828: gen_muldiv(ctx, op1, rs, rt);
1.1 root 11829: break;
1.1.1.5 root 11830: case OPC_MUL:
1.1.1.6 root 11831: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 11832: break;
1.1.1.8 root 11833: case OPC_CLO:
11834: case OPC_CLZ:
1.1.1.6 root 11835: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 11836: gen_cl(ctx, op1, rd, rs);
1.1 root 11837: break;
1.1.1.5 root 11838: case OPC_SDBBP:
1.1 root 11839: /* XXX: not clear which exception should be raised
11840: * when in debug mode...
11841: */
1.1.1.6 root 11842: check_insn(env, ctx, ISA_MIPS32);
1.1 root 11843: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11844: generate_exception(ctx, EXCP_DBp);
11845: } else {
11846: generate_exception(ctx, EXCP_DBp);
11847: }
1.1.1.6 root 11848: /* Treat as NOP. */
1.1 root 11849: break;
1.1.1.12! root 11850: case OPC_DIV_G_2F:
! 11851: case OPC_DIVU_G_2F:
! 11852: case OPC_MULT_G_2F:
! 11853: case OPC_MULTU_G_2F:
! 11854: case OPC_MOD_G_2F:
! 11855: case OPC_MODU_G_2F:
! 11856: check_insn(env, ctx, INSN_LOONGSON2F);
! 11857: gen_loongson_integer(ctx, op1, rd, rs, rt);
! 11858: break;
1.1.1.6 root 11859: #if defined(TARGET_MIPS64)
1.1.1.8 root 11860: case OPC_DCLO:
11861: case OPC_DCLZ:
1.1.1.6 root 11862: check_insn(env, ctx, ISA_MIPS64);
11863: check_mips_64(ctx);
1.1.1.5 root 11864: gen_cl(ctx, op1, rd, rs);
11865: break;
1.1.1.12! root 11866: case OPC_DMULT_G_2F:
! 11867: case OPC_DMULTU_G_2F:
! 11868: case OPC_DDIV_G_2F:
! 11869: case OPC_DDIVU_G_2F:
! 11870: case OPC_DMOD_G_2F:
! 11871: case OPC_DMODU_G_2F:
! 11872: check_insn(env, ctx, INSN_LOONGSON2F);
! 11873: gen_loongson_integer(ctx, op1, rd, rs, rt);
! 11874: break;
1.1.1.5 root 11875: #endif
1.1 root 11876: default: /* Invalid */
11877: MIPS_INVAL("special2");
11878: generate_exception(ctx, EXCP_RI);
11879: break;
11880: }
11881: break;
1.1.1.5 root 11882: case OPC_SPECIAL3:
1.1.1.7 root 11883: op1 = MASK_SPECIAL3(ctx->opcode);
11884: switch (op1) {
11885: case OPC_EXT:
11886: case OPC_INS:
11887: check_insn(env, ctx, ISA_MIPS32R2);
11888: gen_bitops(ctx, op1, rt, rs, sa, rd);
11889: break;
11890: case OPC_BSHFL:
11891: check_insn(env, ctx, ISA_MIPS32R2);
11892: op2 = MASK_BSHFL(ctx->opcode);
11893: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 11894: break;
11895: case OPC_RDHWR:
1.1.1.12! root 11896: gen_rdhwr(env, ctx, rt, rd);
1.1.1.6 root 11897: break;
11898: case OPC_FORK:
11899: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 11900: {
1.1.1.8 root 11901: TCGv t0 = tcg_temp_new();
11902: TCGv t1 = tcg_temp_new();
1.1.1.7 root 11903:
11904: gen_load_gpr(t0, rt);
11905: gen_load_gpr(t1, rs);
11906: gen_helper_fork(t0, t1);
11907: tcg_temp_free(t0);
11908: tcg_temp_free(t1);
11909: }
1.1.1.6 root 11910: break;
11911: case OPC_YIELD:
11912: check_insn(env, ctx, ASE_MT);
1.1.1.7 root 11913: {
1.1.1.8 root 11914: TCGv t0 = tcg_temp_new();
1.1.1.7 root 11915:
1.1.1.8 root 11916: save_cpu_state(ctx, 1);
1.1.1.7 root 11917: gen_load_gpr(t0, rs);
11918: gen_helper_yield(t0, t0);
11919: gen_store_gpr(t0, rd);
11920: tcg_temp_free(t0);
11921: }
1.1.1.6 root 11922: break;
1.1.1.12! root 11923: case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
! 11924: case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
! 11925: case OPC_MOD_G_2E ... OPC_MODU_G_2E:
! 11926: check_insn(env, ctx, INSN_LOONGSON2E);
! 11927: gen_loongson_integer(ctx, op1, rd, rs, rt);
! 11928: break;
1.1.1.6 root 11929: #if defined(TARGET_MIPS64)
11930: case OPC_DEXTM ... OPC_DEXT:
11931: case OPC_DINSM ... OPC_DINS:
11932: check_insn(env, ctx, ISA_MIPS64R2);
11933: check_mips_64(ctx);
1.1.1.5 root 11934: gen_bitops(ctx, op1, rt, rs, sa, rd);
11935: break;
1.1.1.6 root 11936: case OPC_DBSHFL:
11937: check_insn(env, ctx, ISA_MIPS64R2);
11938: check_mips_64(ctx);
11939: op2 = MASK_DBSHFL(ctx->opcode);
1.1.1.7 root 11940: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 11941: break;
1.1.1.12! root 11942: case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
! 11943: case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
! 11944: case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
! 11945: check_insn(env, ctx, INSN_LOONGSON2E);
! 11946: gen_loongson_integer(ctx, op1, rd, rs, rt);
! 11947: break;
1.1.1.5 root 11948: #endif
11949: default: /* Invalid */
11950: MIPS_INVAL("special3");
11951: generate_exception(ctx, EXCP_RI);
11952: break;
11953: }
11954: break;
11955: case OPC_REGIMM:
11956: op1 = MASK_REGIMM(ctx->opcode);
1.1 root 11957: switch (op1) {
1.1.1.5 root 11958: case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
11959: case OPC_BLTZAL ... OPC_BGEZALL:
1.1.1.12! root 11960: gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
! 11961: *is_branch = 1;
! 11962: break;
1.1.1.5 root 11963: case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
11964: case OPC_TNEI:
11965: gen_trap(ctx, op1, rs, -1, imm);
11966: break;
11967: case OPC_SYNCI:
1.1.1.6 root 11968: check_insn(env, ctx, ISA_MIPS32R2);
11969: /* Treat as NOP. */
1.1 root 11970: break;
11971: default: /* Invalid */
1.1.1.6 root 11972: MIPS_INVAL("regimm");
1.1 root 11973: generate_exception(ctx, EXCP_RI);
11974: break;
11975: }
11976: break;
1.1.1.5 root 11977: case OPC_CP0:
1.1.1.6 root 11978: check_cp0_enabled(ctx);
1.1.1.5 root 11979: op1 = MASK_CP0(ctx->opcode);
1.1 root 11980: switch (op1) {
1.1.1.5 root 11981: case OPC_MFC0:
11982: case OPC_MTC0:
1.1.1.6 root 11983: case OPC_MFTR:
11984: case OPC_MTTR:
11985: #if defined(TARGET_MIPS64)
1.1.1.5 root 11986: case OPC_DMFC0:
11987: case OPC_DMTC0:
11988: #endif
1.1.1.7 root 11989: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 11990: gen_cp0(env, ctx, op1, rt, rd);
1.1.1.7 root 11991: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 11992: break;
11993: case OPC_C0_FIRST ... OPC_C0_LAST:
1.1.1.7 root 11994: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 11995: gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
1.1.1.7 root 11996: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 11997: break;
11998: case OPC_MFMC0:
1.1.1.7 root 11999: #ifndef CONFIG_USER_ONLY
12000: {
1.1.1.8 root 12001: TCGv t0 = tcg_temp_new();
1.1.1.7 root 12002:
12003: op2 = MASK_MFMC0(ctx->opcode);
12004: switch (op2) {
12005: case OPC_DMT:
12006: check_insn(env, ctx, ASE_MT);
12007: gen_helper_dmt(t0, t0);
1.1.1.8 root 12008: gen_store_gpr(t0, rt);
1.1.1.7 root 12009: break;
12010: case OPC_EMT:
12011: check_insn(env, ctx, ASE_MT);
12012: gen_helper_emt(t0, t0);
1.1.1.8 root 12013: gen_store_gpr(t0, rt);
1.1.1.7 root 12014: break;
12015: case OPC_DVPE:
12016: check_insn(env, ctx, ASE_MT);
12017: gen_helper_dvpe(t0, t0);
1.1.1.8 root 12018: gen_store_gpr(t0, rt);
1.1.1.7 root 12019: break;
12020: case OPC_EVPE:
12021: check_insn(env, ctx, ASE_MT);
12022: gen_helper_evpe(t0, t0);
1.1.1.8 root 12023: gen_store_gpr(t0, rt);
1.1.1.7 root 12024: break;
12025: case OPC_DI:
12026: check_insn(env, ctx, ISA_MIPS32R2);
12027: save_cpu_state(ctx, 1);
12028: gen_helper_di(t0);
1.1.1.8 root 12029: gen_store_gpr(t0, rt);
1.1.1.7 root 12030: /* Stop translation as we may have switched the execution mode */
12031: ctx->bstate = BS_STOP;
12032: break;
12033: case OPC_EI:
12034: check_insn(env, ctx, ISA_MIPS32R2);
12035: save_cpu_state(ctx, 1);
12036: gen_helper_ei(t0);
1.1.1.8 root 12037: gen_store_gpr(t0, rt);
1.1.1.7 root 12038: /* Stop translation as we may have switched the execution mode */
12039: ctx->bstate = BS_STOP;
12040: break;
12041: default: /* Invalid */
12042: MIPS_INVAL("mfmc0");
12043: generate_exception(ctx, EXCP_RI);
12044: break;
12045: }
12046: tcg_temp_free(t0);
1.1.1.5 root 12047: }
1.1.1.7 root 12048: #endif /* !CONFIG_USER_ONLY */
1.1 root 12049: break;
1.1.1.5 root 12050: case OPC_RDPGPR:
1.1.1.6 root 12051: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 root 12052: gen_load_srsgpr(rt, rd);
1.1.1.6 root 12053: break;
1.1.1.5 root 12054: case OPC_WRPGPR:
1.1.1.6 root 12055: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 root 12056: gen_store_srsgpr(rt, rd);
1.1.1.6 root 12057: break;
1.1 root 12058: default:
1.1.1.6 root 12059: MIPS_INVAL("cp0");
1.1.1.5 root 12060: generate_exception(ctx, EXCP_RI);
1.1 root 12061: break;
12062: }
12063: break;
1.1.1.8 root 12064: case OPC_ADDI: /* Arithmetic with immediate opcode */
12065: case OPC_ADDIU:
1.1.1.6 root 12066: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 12067: break;
1.1.1.8 root 12068: case OPC_SLTI: /* Set on less than with immediate opcode */
12069: case OPC_SLTIU:
12070: gen_slt_imm(env, op, rt, rs, imm);
12071: break;
12072: case OPC_ANDI: /* Arithmetic with immediate opcode */
12073: case OPC_LUI:
12074: case OPC_ORI:
12075: case OPC_XORI:
12076: gen_logic_imm(env, op, rt, rs, imm);
12077: break;
1.1.1.5 root 12078: case OPC_J ... OPC_JAL: /* Jump */
12079: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
1.1.1.12! root 12080: gen_compute_branch(ctx, op, 4, rs, rt, offset);
! 12081: *is_branch = 1;
! 12082: break;
1.1.1.5 root 12083: case OPC_BEQ ... OPC_BGTZ: /* Branch */
12084: case OPC_BEQL ... OPC_BGTZL:
1.1.1.12! root 12085: gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
! 12086: *is_branch = 1;
! 12087: break;
1.1.1.5 root 12088: case OPC_LB ... OPC_LWR: /* Load and stores */
1.1.1.12! root 12089: case OPC_LL:
! 12090: gen_ld(env, ctx, op, rt, rs, imm);
! 12091: break;
1.1.1.5 root 12092: case OPC_SB ... OPC_SW:
12093: case OPC_SWR:
1.1.1.12! root 12094: gen_st(ctx, op, rt, rs, imm);
1.1.1.5 root 12095: break;
1.1.1.8 root 12096: case OPC_SC:
12097: gen_st_cond(ctx, op, rt, rs, imm);
12098: break;
1.1.1.5 root 12099: case OPC_CACHE:
1.1.1.6 root 12100: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
12101: /* Treat as NOP. */
12102: break;
1.1.1.5 root 12103: case OPC_PREF:
1.1.1.6 root 12104: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
12105: /* Treat as NOP. */
1.1 root 12106: break;
1.1.1.2 root 12107:
1.1.1.6 root 12108: /* Floating point (COP1). */
1.1.1.5 root 12109: case OPC_LWC1:
12110: case OPC_LDC1:
12111: case OPC_SWC1:
12112: case OPC_SDC1:
1.1.1.12! root 12113: gen_cop1_ldst(env, ctx, op, rt, rs, imm);
1.1.1.4 root 12114: break;
12115:
1.1.1.5 root 12116: case OPC_CP1:
1.1.1.6 root 12117: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12118: check_cp1_enabled(ctx);
12119: op1 = MASK_CP1(ctx->opcode);
12120: switch (op1) {
12121: case OPC_MFHC1:
12122: case OPC_MTHC1:
12123: check_insn(env, ctx, ISA_MIPS32R2);
12124: case OPC_MFC1:
12125: case OPC_CFC1:
12126: case OPC_MTC1:
12127: case OPC_CTC1:
12128: gen_cp1(ctx, op1, rt, rd);
12129: break;
12130: #if defined(TARGET_MIPS64)
12131: case OPC_DMFC1:
12132: case OPC_DMTC1:
12133: check_insn(env, ctx, ISA_MIPS3);
12134: gen_cp1(ctx, op1, rt, rd);
12135: break;
1.1.1.5 root 12136: #endif
1.1.1.6 root 12137: case OPC_BC1ANY2:
12138: case OPC_BC1ANY4:
12139: check_cop1x(ctx);
12140: check_insn(env, ctx, ASE_MIPS3D);
12141: /* fall through */
12142: case OPC_BC1:
12143: gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
12144: (rt >> 2) & 0x7, imm << 2);
1.1.1.12! root 12145: *is_branch = 1;
! 12146: break;
1.1.1.6 root 12147: case OPC_S_FMT:
12148: case OPC_D_FMT:
12149: case OPC_W_FMT:
12150: case OPC_L_FMT:
12151: case OPC_PS_FMT:
1.1.1.12! root 12152: gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
1.1.1.6 root 12153: (imm >> 8) & 0x7);
12154: break;
12155: default:
12156: MIPS_INVAL("cp1");
12157: generate_exception (ctx, EXCP_RI);
12158: break;
12159: }
12160: } else {
12161: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.4 root 12162: }
1.1.1.2 root 12163: break;
12164:
12165: /* COP2. */
1.1.1.5 root 12166: case OPC_LWC2:
12167: case OPC_LDC2:
12168: case OPC_SWC2:
12169: case OPC_SDC2:
12170: case OPC_CP2:
12171: /* COP2: Not implemented. */
1.1.1.2 root 12172: generate_exception_err(ctx, EXCP_CpU, 2);
12173: break;
12174:
1.1.1.5 root 12175: case OPC_CP3:
1.1.1.6 root 12176: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12177: check_cp1_enabled(ctx);
12178: op1 = MASK_CP3(ctx->opcode);
12179: switch (op1) {
12180: case OPC_LWXC1:
12181: case OPC_LDXC1:
12182: case OPC_LUXC1:
12183: case OPC_SWXC1:
12184: case OPC_SDXC1:
12185: case OPC_SUXC1:
12186: gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
12187: break;
12188: case OPC_PREFX:
12189: /* Treat as NOP. */
12190: break;
12191: case OPC_ALNV_PS:
12192: case OPC_MADD_S:
12193: case OPC_MADD_D:
12194: case OPC_MADD_PS:
12195: case OPC_MSUB_S:
12196: case OPC_MSUB_D:
12197: case OPC_MSUB_PS:
12198: case OPC_NMADD_S:
12199: case OPC_NMADD_D:
12200: case OPC_NMADD_PS:
12201: case OPC_NMSUB_S:
12202: case OPC_NMSUB_D:
12203: case OPC_NMSUB_PS:
12204: gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12205: break;
12206: default:
12207: MIPS_INVAL("cp3");
12208: generate_exception (ctx, EXCP_RI);
12209: break;
12210: }
12211: } else {
12212: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.5 root 12213: }
1.1.1.2 root 12214: break;
12215:
1.1.1.6 root 12216: #if defined(TARGET_MIPS64)
1.1.1.5 root 12217: /* MIPS64 opcodes */
12218: case OPC_LWU:
12219: case OPC_LDL ... OPC_LDR:
12220: case OPC_LLD:
12221: case OPC_LD:
1.1.1.12! root 12222: check_insn(env, ctx, ISA_MIPS3);
! 12223: check_mips_64(ctx);
! 12224: gen_ld(env, ctx, op, rt, rs, imm);
! 12225: break;
! 12226: case OPC_SDL ... OPC_SDR:
1.1.1.5 root 12227: case OPC_SD:
1.1.1.6 root 12228: check_insn(env, ctx, ISA_MIPS3);
12229: check_mips_64(ctx);
1.1.1.12! root 12230: gen_st(ctx, op, rt, rs, imm);
1.1.1.5 root 12231: break;
1.1.1.8 root 12232: case OPC_SCD:
12233: check_insn(env, ctx, ISA_MIPS3);
12234: check_mips_64(ctx);
12235: gen_st_cond(ctx, op, rt, rs, imm);
12236: break;
12237: case OPC_DADDI:
12238: case OPC_DADDIU:
1.1.1.6 root 12239: check_insn(env, ctx, ISA_MIPS3);
12240: check_mips_64(ctx);
12241: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 12242: break;
12243: #endif
12244: case OPC_JALX:
1.1.1.12! root 12245: check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
! 12246: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
! 12247: gen_compute_branch(ctx, op, 4, rs, rt, offset);
! 12248: *is_branch = 1;
! 12249: break;
1.1.1.5 root 12250: case OPC_MDMX:
1.1.1.6 root 12251: check_insn(env, ctx, ASE_MDMX);
1.1.1.5 root 12252: /* MDMX: Not implemented. */
1.1 root 12253: default: /* Invalid */
1.1.1.6 root 12254: MIPS_INVAL("major opcode");
1.1 root 12255: generate_exception(ctx, EXCP_RI);
12256: break;
12257: }
12258: }
12259:
1.1.1.7 root 12260: static inline void
1.1.1.6 root 12261: gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
12262: int search_pc)
1.1 root 12263: {
1.1.1.6 root 12264: DisasContext ctx;
1.1 root 12265: target_ulong pc_start;
12266: uint16_t *gen_opc_end;
1.1.1.7 root 12267: CPUBreakpoint *bp;
1.1 root 12268: int j, lj = -1;
1.1.1.7 root 12269: int num_insns;
12270: int max_insns;
1.1.1.12! root 12271: int insn_bytes;
! 12272: int is_branch;
1.1 root 12273:
1.1.1.7 root 12274: if (search_pc)
12275: qemu_log("search pc %d\n", search_pc);
1.1.1.2 root 12276:
1.1 root 12277: pc_start = tb->pc;
1.1.1.9 root 12278: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1.1 root 12279: ctx.pc = pc_start;
1.1.1.2 root 12280: ctx.saved_pc = -1;
1.1.1.9 root 12281: ctx.singlestep_enabled = env->singlestep_enabled;
1.1 root 12282: ctx.tb = tb;
12283: ctx.bstate = BS_NONE;
1.1.1.2 root 12284: /* Restore delay slot state from the tb context. */
1.1.1.6 root 12285: ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
12286: restore_cpu_state(env, &ctx);
1.1.1.7 root 12287: #ifdef CONFIG_USER_ONLY
12288: ctx.mem_idx = MIPS_HFLAG_UM;
1.1 root 12289: #else
1.1.1.7 root 12290: ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
1.1 root 12291: #endif
1.1.1.7 root 12292: num_insns = 0;
12293: max_insns = tb->cflags & CF_COUNT_MASK;
12294: if (max_insns == 0)
12295: max_insns = CF_COUNT_MASK;
12296: LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
12297: gen_icount_start();
12298: while (ctx.bstate == BS_NONE) {
1.1.1.9 root 12299: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12300: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1.1.7 root 12301: if (bp->pc == ctx.pc) {
1.1.1.6 root 12302: save_cpu_state(&ctx, 1);
1.1.1.2 root 12303: ctx.bstate = BS_BRANCH;
1.1.1.7 root 12304: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 12305: /* Include the breakpoint location or the tb won't
12306: * be flushed when it must be. */
12307: ctx.pc += 4;
1.1.1.2 root 12308: goto done_generating;
12309: }
12310: }
12311: }
12312:
1.1 root 12313: if (search_pc) {
12314: j = gen_opc_ptr - gen_opc_buf;
12315: if (lj < j) {
12316: lj++;
12317: while (lj < j)
12318: gen_opc_instr_start[lj++] = 0;
12319: }
1.1.1.2 root 12320: gen_opc_pc[lj] = ctx.pc;
12321: gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12322: gen_opc_instr_start[lj] = 1;
1.1.1.7 root 12323: gen_opc_icount[lj] = num_insns;
1.1 root 12324: }
1.1.1.7 root 12325: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12326: gen_io_start();
1.1.1.12! root 12327:
! 12328: is_branch = 0;
! 12329: if (!(ctx.hflags & MIPS_HFLAG_M16)) {
! 12330: ctx.opcode = ldl_code(ctx.pc);
! 12331: insn_bytes = 4;
! 12332: decode_opc(env, &ctx, &is_branch);
! 12333: } else if (env->insn_flags & ASE_MICROMIPS) {
! 12334: ctx.opcode = lduw_code(ctx.pc);
! 12335: insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
! 12336: } else if (env->insn_flags & ASE_MIPS16) {
! 12337: ctx.opcode = lduw_code(ctx.pc);
! 12338: insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
! 12339: } else {
! 12340: generate_exception(&ctx, EXCP_RI);
! 12341: ctx.bstate = BS_STOP;
! 12342: break;
! 12343: }
! 12344: if (!is_branch) {
! 12345: handle_delay_slot(env, &ctx, insn_bytes);
! 12346: }
! 12347: ctx.pc += insn_bytes;
! 12348:
1.1.1.7 root 12349: num_insns++;
1.1.1.2 root 12350:
1.1.1.9 root 12351: /* Execute a branch and its delay slot as a single instruction.
12352: This is what GDB expects and is consistent with what the
12353: hardware does (e.g. if a delay slot instruction faults, the
12354: reported PC is the PC of the branch). */
12355: if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
1.1.1.2 root 12356: break;
12357:
1.1 root 12358: if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12359: break;
1.1.1.2 root 12360:
1.1.1.7 root 12361: if (gen_opc_ptr >= gen_opc_end)
12362: break;
12363:
12364: if (num_insns >= max_insns)
12365: break;
1.1.1.8 root 12366:
12367: if (singlestep)
12368: break;
1.1 root 12369: }
1.1.1.7 root 12370: if (tb->cflags & CF_LAST_IO)
12371: gen_io_end();
1.1.1.9 root 12372: if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
1.1.1.6 root 12373: save_cpu_state(&ctx, ctx.bstate == BS_NONE);
1.1.1.7 root 12374: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 12375: } else {
1.1.1.7 root 12376: switch (ctx.bstate) {
1.1.1.6 root 12377: case BS_STOP:
12378: gen_goto_tb(&ctx, 0, ctx.pc);
12379: break;
12380: case BS_NONE:
12381: save_cpu_state(&ctx, 0);
12382: gen_goto_tb(&ctx, 0, ctx.pc);
12383: break;
12384: case BS_EXCP:
1.1.1.7 root 12385: tcg_gen_exit_tb(0);
1.1.1.6 root 12386: break;
12387: case BS_BRANCH:
12388: default:
12389: break;
1.1.1.7 root 12390: }
1.1 root 12391: }
1.1.1.2 root 12392: done_generating:
1.1.1.7 root 12393: gen_icount_end(tb, num_insns);
1.1 root 12394: *gen_opc_ptr = INDEX_op_end;
12395: if (search_pc) {
12396: j = gen_opc_ptr - gen_opc_buf;
12397: lj++;
12398: while (lj <= j)
12399: gen_opc_instr_start[lj++] = 0;
12400: } else {
12401: tb->size = ctx.pc - pc_start;
1.1.1.7 root 12402: tb->icount = num_insns;
1.1 root 12403: }
12404: #ifdef DEBUG_DISAS
1.1.1.7 root 12405: LOG_DISAS("\n");
12406: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
12407: qemu_log("IN: %s\n", lookup_symbol(pc_start));
12408: log_target_disas(pc_start, ctx.pc - pc_start, 0);
12409: qemu_log("\n");
1.1 root 12410: }
12411: #endif
12412: }
12413:
1.1.1.7 root 12414: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1.1 root 12415: {
1.1.1.7 root 12416: gen_intermediate_code_internal(env, tb, 0);
1.1 root 12417: }
12418:
1.1.1.7 root 12419: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1.1 root 12420: {
1.1.1.7 root 12421: gen_intermediate_code_internal(env, tb, 1);
1.1 root 12422: }
12423:
1.1.1.7 root 12424: static void fpu_dump_state(CPUState *env, FILE *f,
12425: int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
12426: int flags)
1.1.1.4 root 12427: {
12428: int i;
1.1.1.6 root 12429: int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
1.1.1.4 root 12430:
1.1.1.12! root 12431: #define printfpr(fp) \
! 12432: do { \
! 12433: if (is_fpu64) \
! 12434: fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
! 12435: " fd:%13g fs:%13g psu: %13g\n", \
! 12436: (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
! 12437: (double)(fp)->fd, \
! 12438: (double)(fp)->fs[FP_ENDIAN_IDX], \
! 12439: (double)(fp)->fs[!FP_ENDIAN_IDX]); \
! 12440: else { \
! 12441: fpr_t tmp; \
! 12442: tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
! 12443: tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
! 12444: fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
! 12445: " fd:%13g fs:%13g psu:%13g\n", \
! 12446: tmp.w[FP_ENDIAN_IDX], tmp.d, \
! 12447: (double)tmp.fd, \
! 12448: (double)tmp.fs[FP_ENDIAN_IDX], \
! 12449: (double)tmp.fs[!FP_ENDIAN_IDX]); \
! 12450: } \
1.1.1.4 root 12451: } while(0)
12452:
1.1.1.6 root 12453:
12454: fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
1.1.1.7 root 12455: env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
12456: get_float_exception_flags(&env->active_fpu.fp_status));
1.1.1.6 root 12457: for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12458: fpu_fprintf(f, "%3s: ", fregnames[i]);
1.1.1.7 root 12459: printfpr(&env->active_fpu.fpr[i]);
1.1.1.4 root 12460: }
12461:
12462: #undef printfpr
12463: }
12464:
1.1.1.6 root 12465: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 12466: /* Debug help: The architecture requires 32bit code to maintain proper
1.1.1.7 root 12467: sign-extended values on 64bit machines. */
1.1.1.5 root 12468:
12469: #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12470:
1.1.1.7 root 12471: static void
12472: cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
12473: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
12474: int flags)
1.1.1.5 root 12475: {
12476: int i;
12477:
1.1.1.7 root 12478: if (!SIGN_EXT_P(env->active_tc.PC))
12479: cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12480: if (!SIGN_EXT_P(env->active_tc.HI[0]))
12481: cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12482: if (!SIGN_EXT_P(env->active_tc.LO[0]))
12483: cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
1.1.1.5 root 12484: if (!SIGN_EXT_P(env->btarget))
1.1.1.6 root 12485: cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
1.1.1.5 root 12486:
12487: for (i = 0; i < 32; i++) {
1.1.1.7 root 12488: if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12489: cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
1.1.1.5 root 12490: }
12491:
12492: if (!SIGN_EXT_P(env->CP0_EPC))
1.1.1.6 root 12493: cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
1.1.1.9 root 12494: if (!SIGN_EXT_P(env->lladdr))
12495: cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
1.1.1.5 root 12496: }
12497: #endif
12498:
1.1.1.6 root 12499: void cpu_dump_state (CPUState *env, FILE *f,
1.1 root 12500: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
12501: int flags)
12502: {
12503: int i;
1.1.1.6 root 12504:
1.1.1.12! root 12505: cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
! 12506: " LO=0x" TARGET_FMT_lx " ds %04x "
! 12507: TARGET_FMT_lx " " TARGET_FMT_ld "\n",
1.1.1.7 root 12508: env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12509: env->hflags, env->btarget, env->bcond);
1.1 root 12510: for (i = 0; i < 32; i++) {
12511: if ((i & 3) == 0)
12512: cpu_fprintf(f, "GPR%02d:", i);
1.1.1.7 root 12513: cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
1.1 root 12514: if ((i & 3) == 3)
12515: cpu_fprintf(f, "\n");
12516: }
12517:
1.1.1.6 root 12518: cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
12519: env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
12520: cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
1.1.1.9 root 12521: env->CP0_Config0, env->CP0_Config1, env->lladdr);
1.1.1.6 root 12522: if (env->hflags & MIPS_HFLAG_FPU)
1.1.1.5 root 12523: fpu_dump_state(env, f, cpu_fprintf, flags);
1.1.1.6 root 12524: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 12525: cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
1.1.1.4 root 12526: #endif
1.1 root 12527: }
12528:
1.1.1.7 root 12529: static void mips_tcg_init(void)
12530: {
12531: int i;
12532: static int inited;
12533:
12534: /* Initialize various static tables. */
12535: if (inited)
12536: return;
12537:
12538: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1.1.1.8 root 12539: TCGV_UNUSED(cpu_gpr[0]);
12540: for (i = 1; i < 32; i++)
1.1.1.7 root 12541: cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
12542: offsetof(CPUState, active_tc.gpr[i]),
12543: regnames[i]);
12544: cpu_PC = tcg_global_mem_new(TCG_AREG0,
12545: offsetof(CPUState, active_tc.PC), "PC");
12546: for (i = 0; i < MIPS_DSP_ACC; i++) {
12547: cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
12548: offsetof(CPUState, active_tc.HI[i]),
12549: regnames_HI[i]);
12550: cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
12551: offsetof(CPUState, active_tc.LO[i]),
12552: regnames_LO[i]);
12553: cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
12554: offsetof(CPUState, active_tc.ACX[i]),
12555: regnames_ACX[i]);
12556: }
12557: cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
12558: offsetof(CPUState, active_tc.DSPControl),
12559: "DSPControl");
1.1.1.8 root 12560: bcond = tcg_global_mem_new(TCG_AREG0,
12561: offsetof(CPUState, bcond), "bcond");
1.1.1.7 root 12562: btarget = tcg_global_mem_new(TCG_AREG0,
12563: offsetof(CPUState, btarget), "btarget");
1.1.1.8 root 12564: hflags = tcg_global_mem_new_i32(TCG_AREG0,
12565: offsetof(CPUState, hflags), "hflags");
12566:
1.1.1.7 root 12567: fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
12568: offsetof(CPUState, active_fpu.fcr0),
12569: "fcr0");
12570: fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
12571: offsetof(CPUState, active_fpu.fcr31),
12572: "fcr31");
12573:
12574: /* register helpers */
12575: #define GEN_HELPER 2
12576: #include "helper.h"
12577:
12578: inited = 1;
12579: }
12580:
1.1.1.6 root 12581: #include "translate_init.c"
12582:
12583: CPUMIPSState *cpu_mips_init (const char *cpu_model)
1.1 root 12584: {
12585: CPUMIPSState *env;
1.1.1.6 root 12586: const mips_def_t *def;
1.1 root 12587:
1.1.1.6 root 12588: def = cpu_mips_find_by_name(cpu_model);
12589: if (!def)
12590: return NULL;
1.1 root 12591: env = qemu_mallocz(sizeof(CPUMIPSState));
1.1.1.6 root 12592: env->cpu_model = def;
1.1.1.9 root 12593: env->cpu_model_str = cpu_model;
1.1.1.6 root 12594:
1.1.1.2 root 12595: cpu_exec_init(env);
1.1.1.9 root 12596: #ifndef CONFIG_USER_ONLY
12597: mmu_init(env, def);
12598: #endif
12599: fpu_init(env, def);
12600: mvp_init(env, def);
1.1.1.7 root 12601: mips_tcg_init();
1.1.1.5 root 12602: cpu_reset(env);
1.1.1.8 root 12603: qemu_init_vcpu(env);
1.1.1.5 root 12604: return env;
12605: }
12606:
12607: void cpu_reset (CPUMIPSState *env)
12608: {
1.1.1.7 root 12609: if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12610: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12611: log_cpu_state(env, 0);
12612: }
12613:
1.1.1.5 root 12614: memset(env, 0, offsetof(CPUMIPSState, breakpoints));
1.1 root 12615: tlb_flush(env, 1);
1.1.1.5 root 12616:
1.1.1.9 root 12617: /* Reset registers to their default values */
12618: env->CP0_PRid = env->cpu_model->CP0_PRid;
12619: env->CP0_Config0 = env->cpu_model->CP0_Config0;
12620: #ifdef TARGET_WORDS_BIGENDIAN
12621: env->CP0_Config0 |= (1 << CP0C0_BE);
12622: #endif
12623: env->CP0_Config1 = env->cpu_model->CP0_Config1;
12624: env->CP0_Config2 = env->cpu_model->CP0_Config2;
12625: env->CP0_Config3 = env->cpu_model->CP0_Config3;
12626: env->CP0_Config6 = env->cpu_model->CP0_Config6;
12627: env->CP0_Config7 = env->cpu_model->CP0_Config7;
12628: env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12629: << env->cpu_model->CP0_LLAddr_shift;
12630: env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
12631: env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12632: env->CCRes = env->cpu_model->CCRes;
12633: env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12634: env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12635: env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12636: env->current_tc = 0;
12637: env->SEGBITS = env->cpu_model->SEGBITS;
12638: env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12639: #if defined(TARGET_MIPS64)
12640: if (env->cpu_model->insn_flags & ISA_MIPS3) {
12641: env->SEGMask |= 3ULL << 62;
12642: }
12643: #endif
12644: env->PABITS = env->cpu_model->PABITS;
12645: env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12646: env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12647: env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12648: env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12649: env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12650: env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12651: env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12652: env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12653: env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12654: env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12655: env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
12656: env->insn_flags = env->cpu_model->insn_flags;
12657:
1.1.1.7 root 12658: #if defined(CONFIG_USER_ONLY)
12659: env->hflags = MIPS_HFLAG_UM;
1.1.1.8 root 12660: /* Enable access to the SYNCI_Step register. */
12661: env->CP0_HWREna |= (1 << 1);
1.1.1.9 root 12662: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12663: env->hflags |= MIPS_HFLAG_FPU;
12664: }
12665: #ifdef TARGET_MIPS64
12666: if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
12667: env->hflags |= MIPS_HFLAG_F64;
12668: }
12669: #endif
1.1.1.7 root 12670: #else
1.1.1.5 root 12671: if (env->hflags & MIPS_HFLAG_BMASK) {
12672: /* If the exception was raised from a delay slot,
1.1.1.7 root 12673: come back to the jump. */
12674: env->CP0_ErrorEPC = env->active_tc.PC - 4;
1.1.1.5 root 12675: } else {
1.1.1.7 root 12676: env->CP0_ErrorEPC = env->active_tc.PC;
1.1.1.5 root 12677: }
1.1.1.7 root 12678: env->active_tc.PC = (int32_t)0xBFC00000;
1.1.1.9 root 12679: env->CP0_Random = env->tlb->nb_tlb - 1;
12680: env->tlb->tlb_in_use = env->tlb->nb_tlb;
1.1 root 12681: env->CP0_Wired = 0;
1.1.1.5 root 12682: /* SMP not implemented */
12683: env->CP0_EBase = 0x80000000;
12684: env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
1.1.1.6 root 12685: /* vectored interrupts not implemented, timer on int 7,
12686: no performance counters. */
12687: env->CP0_IntCtl = 0xe0000000;
12688: {
12689: int i;
12690:
12691: for (i = 0; i < 7; i++) {
12692: env->CP0_WatchLo[i] = 0;
12693: env->CP0_WatchHi[i] = 0x80000000;
12694: }
12695: env->CP0_WatchLo[7] = 0;
12696: env->CP0_WatchHi[7] = 0;
12697: }
1.1 root 12698: /* Count register increments in debug mode, EJTAG version 1 */
12699: env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
1.1.1.6 root 12700: env->hflags = MIPS_HFLAG_CP0;
1.1.1.2 root 12701: #endif
1.1.1.9 root 12702: #if defined(TARGET_MIPS64)
12703: if (env->cpu_model->insn_flags & ISA_MIPS3) {
12704: env->hflags |= MIPS_HFLAG_64;
12705: }
12706: #endif
1.1.1.7 root 12707: env->exception_index = EXCP_NONE;
1.1 root 12708: }
1.1.1.7 root 12709:
12710: void gen_pc_load(CPUState *env, TranslationBlock *tb,
12711: unsigned long searched_pc, int pc_pos, void *puc)
12712: {
12713: env->active_tc.PC = gen_opc_pc[pc_pos];
12714: env->hflags &= ~MIPS_HFLAG_BMASK;
12715: env->hflags |= gen_opc_hflags[pc_pos];
12716: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.