|
|
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 root 7: *
8: * This library is free software; you can redistribute it and/or
9: * modify it under the terms of the GNU Lesser General Public
10: * License as published by the Free Software Foundation; either
11: * version 2 of the License, or (at your option) any later version.
12: *
13: * This library is distributed in the hope that it will be useful,
14: * but WITHOUT ANY WARRANTY; without even the implied warranty of
15: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16: * Lesser General Public License for more details.
17: *
18: * You should have received a copy of the GNU Lesser General Public
19: * License along with this library; if not, write to the Free Software
1.1.1.7 ! root 20: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
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: //#define MIPS_SINGLE_STEP
42:
1.1.1.5 root 43: /* MIPS major opcodes */
44: #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
1.1 root 45:
46: enum {
47: /* indirect opcode tables */
1.1.1.5 root 48: OPC_SPECIAL = (0x00 << 26),
49: OPC_REGIMM = (0x01 << 26),
50: OPC_CP0 = (0x10 << 26),
51: OPC_CP1 = (0x11 << 26),
52: OPC_CP2 = (0x12 << 26),
53: OPC_CP3 = (0x13 << 26),
54: OPC_SPECIAL2 = (0x1C << 26),
55: OPC_SPECIAL3 = (0x1F << 26),
1.1 root 56: /* arithmetic with immediate */
1.1.1.5 root 57: OPC_ADDI = (0x08 << 26),
58: OPC_ADDIU = (0x09 << 26),
59: OPC_SLTI = (0x0A << 26),
60: OPC_SLTIU = (0x0B << 26),
61: OPC_ANDI = (0x0C << 26),
62: OPC_ORI = (0x0D << 26),
63: OPC_XORI = (0x0E << 26),
64: OPC_LUI = (0x0F << 26),
65: OPC_DADDI = (0x18 << 26),
66: OPC_DADDIU = (0x19 << 26),
1.1 root 67: /* Jump and branches */
1.1.1.5 root 68: OPC_J = (0x02 << 26),
69: OPC_JAL = (0x03 << 26),
70: OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
71: OPC_BEQL = (0x14 << 26),
72: OPC_BNE = (0x05 << 26),
73: OPC_BNEL = (0x15 << 26),
74: OPC_BLEZ = (0x06 << 26),
75: OPC_BLEZL = (0x16 << 26),
76: OPC_BGTZ = (0x07 << 26),
77: OPC_BGTZL = (0x17 << 26),
78: OPC_JALX = (0x1D << 26), /* MIPS 16 only */
1.1 root 79: /* Load and stores */
1.1.1.5 root 80: OPC_LDL = (0x1A << 26),
81: OPC_LDR = (0x1B << 26),
82: OPC_LB = (0x20 << 26),
83: OPC_LH = (0x21 << 26),
84: OPC_LWL = (0x22 << 26),
85: OPC_LW = (0x23 << 26),
86: OPC_LBU = (0x24 << 26),
87: OPC_LHU = (0x25 << 26),
88: OPC_LWR = (0x26 << 26),
89: OPC_LWU = (0x27 << 26),
90: OPC_SB = (0x28 << 26),
91: OPC_SH = (0x29 << 26),
92: OPC_SWL = (0x2A << 26),
93: OPC_SW = (0x2B << 26),
94: OPC_SDL = (0x2C << 26),
95: OPC_SDR = (0x2D << 26),
96: OPC_SWR = (0x2E << 26),
97: OPC_LL = (0x30 << 26),
98: OPC_LLD = (0x34 << 26),
99: OPC_LD = (0x37 << 26),
100: OPC_SC = (0x38 << 26),
101: OPC_SCD = (0x3C << 26),
102: OPC_SD = (0x3F << 26),
1.1 root 103: /* Floating point load/store */
1.1.1.5 root 104: OPC_LWC1 = (0x31 << 26),
105: OPC_LWC2 = (0x32 << 26),
106: OPC_LDC1 = (0x35 << 26),
107: OPC_LDC2 = (0x36 << 26),
108: OPC_SWC1 = (0x39 << 26),
109: OPC_SWC2 = (0x3A << 26),
110: OPC_SDC1 = (0x3D << 26),
111: OPC_SDC2 = (0x3E << 26),
112: /* MDMX ASE specific */
113: OPC_MDMX = (0x1E << 26),
1.1 root 114: /* Cache and prefetch */
1.1.1.5 root 115: OPC_CACHE = (0x2F << 26),
116: OPC_PREF = (0x33 << 26),
117: /* Reserved major opcode */
118: OPC_MAJOR3B_RESERVED = (0x3B << 26),
1.1 root 119: };
120:
121: /* MIPS special opcodes */
1.1.1.5 root 122: #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
123:
1.1 root 124: enum {
125: /* Shifts */
1.1.1.5 root 126: OPC_SLL = 0x00 | OPC_SPECIAL,
1.1 root 127: /* NOP is SLL r0, r0, 0 */
128: /* SSNOP is SLL r0, r0, 1 */
1.1.1.5 root 129: /* EHB is SLL r0, r0, 3 */
130: OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
131: OPC_SRA = 0x03 | OPC_SPECIAL,
132: OPC_SLLV = 0x04 | OPC_SPECIAL,
1.1.1.6 root 133: OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
1.1.1.5 root 134: OPC_SRAV = 0x07 | OPC_SPECIAL,
135: OPC_DSLLV = 0x14 | OPC_SPECIAL,
136: OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
137: OPC_DSRAV = 0x17 | OPC_SPECIAL,
138: OPC_DSLL = 0x38 | OPC_SPECIAL,
139: OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
140: OPC_DSRA = 0x3B | OPC_SPECIAL,
141: OPC_DSLL32 = 0x3C | OPC_SPECIAL,
142: OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
143: OPC_DSRA32 = 0x3F | OPC_SPECIAL,
1.1 root 144: /* Multiplication / division */
1.1.1.5 root 145: OPC_MULT = 0x18 | OPC_SPECIAL,
146: OPC_MULTU = 0x19 | OPC_SPECIAL,
147: OPC_DIV = 0x1A | OPC_SPECIAL,
148: OPC_DIVU = 0x1B | OPC_SPECIAL,
149: OPC_DMULT = 0x1C | OPC_SPECIAL,
150: OPC_DMULTU = 0x1D | OPC_SPECIAL,
151: OPC_DDIV = 0x1E | OPC_SPECIAL,
152: OPC_DDIVU = 0x1F | OPC_SPECIAL,
1.1 root 153: /* 2 registers arithmetic / logic */
1.1.1.5 root 154: OPC_ADD = 0x20 | OPC_SPECIAL,
155: OPC_ADDU = 0x21 | OPC_SPECIAL,
156: OPC_SUB = 0x22 | OPC_SPECIAL,
157: OPC_SUBU = 0x23 | OPC_SPECIAL,
158: OPC_AND = 0x24 | OPC_SPECIAL,
159: OPC_OR = 0x25 | OPC_SPECIAL,
160: OPC_XOR = 0x26 | OPC_SPECIAL,
161: OPC_NOR = 0x27 | OPC_SPECIAL,
162: OPC_SLT = 0x2A | OPC_SPECIAL,
163: OPC_SLTU = 0x2B | OPC_SPECIAL,
164: OPC_DADD = 0x2C | OPC_SPECIAL,
165: OPC_DADDU = 0x2D | OPC_SPECIAL,
166: OPC_DSUB = 0x2E | OPC_SPECIAL,
167: OPC_DSUBU = 0x2F | OPC_SPECIAL,
1.1 root 168: /* Jumps */
1.1.1.5 root 169: OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
170: OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
1.1 root 171: /* Traps */
1.1.1.5 root 172: OPC_TGE = 0x30 | OPC_SPECIAL,
173: OPC_TGEU = 0x31 | OPC_SPECIAL,
174: OPC_TLT = 0x32 | OPC_SPECIAL,
175: OPC_TLTU = 0x33 | OPC_SPECIAL,
176: OPC_TEQ = 0x34 | OPC_SPECIAL,
177: OPC_TNE = 0x36 | OPC_SPECIAL,
1.1 root 178: /* HI / LO registers load & stores */
1.1.1.5 root 179: OPC_MFHI = 0x10 | OPC_SPECIAL,
180: OPC_MTHI = 0x11 | OPC_SPECIAL,
181: OPC_MFLO = 0x12 | OPC_SPECIAL,
182: OPC_MTLO = 0x13 | OPC_SPECIAL,
1.1 root 183: /* Conditional moves */
1.1.1.5 root 184: OPC_MOVZ = 0x0A | OPC_SPECIAL,
185: OPC_MOVN = 0x0B | OPC_SPECIAL,
1.1 root 186:
1.1.1.5 root 187: OPC_MOVCI = 0x01 | OPC_SPECIAL,
1.1 root 188:
189: /* Special */
1.1.1.5 root 190: OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */
191: OPC_SYSCALL = 0x0C | OPC_SPECIAL,
192: OPC_BREAK = 0x0D | OPC_SPECIAL,
193: OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */
194: OPC_SYNC = 0x0F | OPC_SPECIAL,
195:
196: OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
197: OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
198: OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
199: OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
200: OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
201: OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
202: OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
203: };
204:
1.1.1.6 root 205: /* Multiplication variants of the vr54xx. */
206: #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
207:
208: enum {
209: OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
210: OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
211: OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
212: OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
213: OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
214: OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
215: OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
216: OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
217: OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
218: OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
219: OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
220: OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
221: OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
222: OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
223: };
224:
1.1.1.5 root 225: /* REGIMM (rt field) opcodes */
226: #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
227:
228: enum {
229: OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
230: OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
231: OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
232: OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
233: OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
234: OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
235: OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
236: OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
237: OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
238: OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
239: OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
240: OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
241: OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
242: OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
243: OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
1.1 root 244: };
245:
1.1.1.5 root 246: /* Special2 opcodes */
247: #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
248:
1.1 root 249: enum {
1.1.1.5 root 250: /* Multiply & xxx operations */
251: OPC_MADD = 0x00 | OPC_SPECIAL2,
252: OPC_MADDU = 0x01 | OPC_SPECIAL2,
253: OPC_MUL = 0x02 | OPC_SPECIAL2,
254: OPC_MSUB = 0x04 | OPC_SPECIAL2,
255: OPC_MSUBU = 0x05 | OPC_SPECIAL2,
1.1 root 256: /* Misc */
1.1.1.5 root 257: OPC_CLZ = 0x20 | OPC_SPECIAL2,
258: OPC_CLO = 0x21 | OPC_SPECIAL2,
259: OPC_DCLZ = 0x24 | OPC_SPECIAL2,
260: OPC_DCLO = 0x25 | OPC_SPECIAL2,
1.1 root 261: /* Special */
1.1.1.5 root 262: OPC_SDBBP = 0x3F | OPC_SPECIAL2,
263: };
264:
265: /* Special3 opcodes */
266: #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
267:
268: enum {
269: OPC_EXT = 0x00 | OPC_SPECIAL3,
270: OPC_DEXTM = 0x01 | OPC_SPECIAL3,
271: OPC_DEXTU = 0x02 | OPC_SPECIAL3,
272: OPC_DEXT = 0x03 | OPC_SPECIAL3,
273: OPC_INS = 0x04 | OPC_SPECIAL3,
274: OPC_DINSM = 0x05 | OPC_SPECIAL3,
275: OPC_DINSU = 0x06 | OPC_SPECIAL3,
276: OPC_DINS = 0x07 | OPC_SPECIAL3,
1.1.1.6 root 277: OPC_FORK = 0x08 | OPC_SPECIAL3,
278: OPC_YIELD = 0x09 | OPC_SPECIAL3,
1.1.1.5 root 279: OPC_BSHFL = 0x20 | OPC_SPECIAL3,
280: OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
281: OPC_RDHWR = 0x3B | OPC_SPECIAL3,
1.1 root 282: };
283:
1.1.1.5 root 284: /* BSHFL opcodes */
285: #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
286:
1.1 root 287: enum {
1.1.1.5 root 288: OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
289: OPC_SEB = (0x10 << 6) | OPC_BSHFL,
290: OPC_SEH = (0x18 << 6) | OPC_BSHFL,
1.1 root 291: };
292:
1.1.1.5 root 293: /* DBSHFL opcodes */
294: #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
295:
1.1 root 296: enum {
1.1.1.5 root 297: OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
298: OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
1.1 root 299: };
300:
1.1.1.5 root 301: /* Coprocessor 0 (rs field) */
302: #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
303:
1.1.1.4 root 304: enum {
1.1.1.5 root 305: OPC_MFC0 = (0x00 << 21) | OPC_CP0,
306: OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
307: OPC_MTC0 = (0x04 << 21) | OPC_CP0,
308: OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
1.1.1.6 root 309: OPC_MFTR = (0x08 << 21) | OPC_CP0,
1.1.1.5 root 310: OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
311: OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
1.1.1.6 root 312: OPC_MTTR = (0x0C << 21) | OPC_CP0,
1.1.1.5 root 313: OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
314: OPC_C0 = (0x10 << 21) | OPC_CP0,
315: OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
316: OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
1.1.1.4 root 317: };
1.1.1.5 root 318:
319: /* MFMC0 opcodes */
1.1.1.6 root 320: #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
1.1.1.5 root 321:
322: enum {
1.1.1.6 root 323: OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
324: OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
325: OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
326: OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
1.1.1.5 root 327: OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
328: OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
329: };
330:
331: /* Coprocessor 0 (with rs == C0) */
332: #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
333:
334: enum {
335: OPC_TLBR = 0x01 | OPC_C0,
336: OPC_TLBWI = 0x02 | OPC_C0,
337: OPC_TLBWR = 0x06 | OPC_C0,
338: OPC_TLBP = 0x08 | OPC_C0,
339: OPC_RFE = 0x10 | OPC_C0,
340: OPC_ERET = 0x18 | OPC_C0,
341: OPC_DERET = 0x1F | OPC_C0,
342: OPC_WAIT = 0x20 | OPC_C0,
343: };
344:
345: /* Coprocessor 1 (rs field) */
346: #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
347:
348: enum {
349: OPC_MFC1 = (0x00 << 21) | OPC_CP1,
350: OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
351: OPC_CFC1 = (0x02 << 21) | OPC_CP1,
1.1.1.6 root 352: OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
1.1.1.5 root 353: OPC_MTC1 = (0x04 << 21) | OPC_CP1,
354: OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
355: OPC_CTC1 = (0x06 << 21) | OPC_CP1,
1.1.1.6 root 356: OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
1.1.1.5 root 357: OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
1.1.1.6 root 358: OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
359: OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
1.1.1.5 root 360: OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
361: OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
362: OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
363: OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
364: OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
365: OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
1.1.1.6 root 366: OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
1.1.1.5 root 367: };
368:
1.1.1.6 root 369: #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
370: #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
371:
1.1.1.5 root 372: enum {
373: OPC_BC1F = (0x00 << 16) | OPC_BC1,
374: OPC_BC1T = (0x01 << 16) | OPC_BC1,
375: OPC_BC1FL = (0x02 << 16) | OPC_BC1,
376: OPC_BC1TL = (0x03 << 16) | OPC_BC1,
377: };
378:
1.1.1.6 root 379: enum {
380: OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
381: OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
382: };
383:
384: enum {
385: OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
386: OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
387: };
1.1.1.5 root 388:
389: #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1.1.1.6 root 390:
391: enum {
392: OPC_MFC2 = (0x00 << 21) | OPC_CP2,
393: OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
394: OPC_CFC2 = (0x02 << 21) | OPC_CP2,
395: OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
396: OPC_MTC2 = (0x04 << 21) | OPC_CP2,
397: OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
398: OPC_CTC2 = (0x06 << 21) | OPC_CP2,
399: OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
400: OPC_BC2 = (0x08 << 21) | OPC_CP2,
401: };
402:
403: #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
404:
405: enum {
406: OPC_LWXC1 = 0x00 | OPC_CP3,
407: OPC_LDXC1 = 0x01 | OPC_CP3,
408: OPC_LUXC1 = 0x05 | OPC_CP3,
409: OPC_SWXC1 = 0x08 | OPC_CP3,
410: OPC_SDXC1 = 0x09 | OPC_CP3,
411: OPC_SUXC1 = 0x0D | OPC_CP3,
412: OPC_PREFX = 0x0F | OPC_CP3,
413: OPC_ALNV_PS = 0x1E | OPC_CP3,
414: OPC_MADD_S = 0x20 | OPC_CP3,
415: OPC_MADD_D = 0x21 | OPC_CP3,
416: OPC_MADD_PS = 0x26 | OPC_CP3,
417: OPC_MSUB_S = 0x28 | OPC_CP3,
418: OPC_MSUB_D = 0x29 | OPC_CP3,
419: OPC_MSUB_PS = 0x2E | OPC_CP3,
420: OPC_NMADD_S = 0x30 | OPC_CP3,
421: OPC_NMADD_D = 0x31 | OPC_CP3,
422: OPC_NMADD_PS= 0x36 | OPC_CP3,
423: OPC_NMSUB_S = 0x38 | OPC_CP3,
424: OPC_NMSUB_D = 0x39 | OPC_CP3,
425: OPC_NMSUB_PS= 0x3E | OPC_CP3,
426: };
427:
1.1.1.7 ! root 428: /* global register indices */
! 429: static TCGv_ptr cpu_env;
! 430: static TCGv cpu_gpr[32], cpu_PC;
! 431: static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
! 432: static TCGv cpu_dspctrl, btarget;
! 433: static TCGv_i32 bcond;
! 434: static TCGv_i32 fpu_fpr32[32], fpu_fpr32h[32];
! 435: static TCGv_i64 fpu_fpr64[32];
! 436: static TCGv_i32 fpu_fcr0, fpu_fcr31;
! 437:
! 438: #include "gen-icount.h"
! 439:
! 440: #define gen_helper_0i(name, arg) do { \
! 441: TCGv_i32 helper_tmp = tcg_const_i32(arg); \
! 442: gen_helper_##name(helper_tmp); \
! 443: tcg_temp_free_i32(helper_tmp); \
! 444: } while(0)
1.1.1.4 root 445:
1.1.1.7 ! root 446: #define gen_helper_1i(name, arg1, arg2) do { \
! 447: TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
! 448: gen_helper_##name(arg1, helper_tmp); \
! 449: tcg_temp_free_i32(helper_tmp); \
! 450: } while(0)
1.1.1.4 root 451:
1.1.1.7 ! root 452: #define gen_helper_2i(name, arg1, arg2, arg3) do { \
! 453: TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
! 454: gen_helper_##name(arg1, arg2, helper_tmp); \
! 455: tcg_temp_free_i32(helper_tmp); \
! 456: } while(0)
1.1.1.4 root 457:
1.1.1.7 ! root 458: #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
! 459: TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
! 460: gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
! 461: tcg_temp_free_i32(helper_tmp); \
! 462: } while(0)
1.1.1.4 root 463:
1.1 root 464: typedef struct DisasContext {
465: struct TranslationBlock *tb;
466: target_ulong pc, saved_pc;
467: uint32_t opcode;
468: /* Routine used to access memory */
469: int mem_idx;
470: uint32_t hflags, saved_hflags;
471: int bstate;
472: target_ulong btarget;
473: } DisasContext;
474:
475: enum {
476: BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1.1.1.7 ! root 477: * exception condition */
1.1 root 478: BS_STOP = 1, /* We want to stop translation for any reason */
479: BS_BRANCH = 2, /* We reached a branch condition */
480: BS_EXCP = 3, /* We reached an exception condition */
481: };
482:
1.1.1.7 ! root 483: static const char *regnames[] =
! 484: { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
! 485: "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
! 486: "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
! 487: "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
! 488:
! 489: static const char *regnames_HI[] =
! 490: { "HI0", "HI1", "HI2", "HI3", };
! 491:
! 492: static const char *regnames_LO[] =
! 493: { "LO0", "LO1", "LO2", "LO3", };
! 494:
! 495: static const char *regnames_ACX[] =
! 496: { "ACX0", "ACX1", "ACX2", "ACX3", };
! 497:
! 498: static const char *fregnames[] =
! 499: { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
! 500: "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
! 501: "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
! 502: "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
! 503:
! 504: static const char *fregnames_64[] =
! 505: { "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7",
! 506: "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15",
! 507: "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23",
! 508: "F24", "F25", "F26", "F27", "F28", "F29", "F30", "F31", };
! 509:
! 510: static const char *fregnames_h[] =
! 511: { "h0", "h1", "h2", "h3", "h4", "h5", "h6", "h7",
! 512: "h8", "h9", "h10", "h11", "h12", "h13", "h14", "h15",
! 513: "h16", "h17", "h18", "h19", "h20", "h21", "h22", "h23",
! 514: "h24", "h25", "h26", "h27", "h28", "h29", "h30", "h31", };
! 515:
1.1.1.6 root 516: #ifdef MIPS_DEBUG_DISAS
1.1.1.7 ! root 517: #define MIPS_DEBUG(fmt, args...) \
! 518: qemu_log_mask(CPU_LOG_TB_IN_ASM, \
! 519: TARGET_FMT_lx ": %08x " fmt "\n", \
! 520: ctx->pc, ctx->opcode , ##args)
! 521: #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
1.1 root 522: #else
523: #define MIPS_DEBUG(fmt, args...) do { } while(0)
1.1.1.7 ! root 524: #define LOG_DISAS(...) do { } while (0)
1.1 root 525: #endif
526:
527: #define MIPS_INVAL(op) \
528: do { \
529: MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
530: ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
531: } while (0)
532:
1.1.1.7 ! root 533: /* General purpose registers moves. */
! 534: static inline void gen_load_gpr (TCGv t, int reg)
! 535: {
! 536: if (reg == 0)
! 537: tcg_gen_movi_tl(t, 0);
! 538: else
! 539: tcg_gen_mov_tl(t, cpu_gpr[reg]);
! 540: }
1.1.1.6 root 541:
1.1.1.7 ! root 542: static inline void gen_store_gpr (TCGv t, int reg)
! 543: {
! 544: if (reg != 0)
! 545: tcg_gen_mov_tl(cpu_gpr[reg], t);
! 546: }
1.1.1.6 root 547:
1.1.1.7 ! root 548: /* Moves to/from ACX register. */
! 549: static inline void gen_load_ACX (TCGv t, int reg)
! 550: {
! 551: tcg_gen_mov_tl(t, cpu_ACX[reg]);
! 552: }
1.1.1.6 root 553:
1.1.1.7 ! root 554: static inline void gen_store_ACX (TCGv t, int reg)
! 555: {
! 556: tcg_gen_mov_tl(cpu_ACX[reg], t);
! 557: }
1.1 root 558:
1.1.1.7 ! root 559: /* Moves to/from shadow registers. */
! 560: static inline void gen_load_srsgpr (int from, int to)
! 561: {
! 562: TCGv r_tmp1 = tcg_temp_new();
1.1.1.6 root 563:
1.1.1.7 ! root 564: if (from == 0)
! 565: tcg_gen_movi_tl(r_tmp1, 0);
! 566: else {
! 567: TCGv_i32 r_tmp2 = tcg_temp_new_i32();
! 568: TCGv_ptr addr = tcg_temp_new_ptr();
1.1.1.6 root 569:
1.1.1.7 ! root 570: tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
! 571: tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
! 572: tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
! 573: tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
! 574: tcg_gen_ext_i32_ptr(addr, r_tmp2);
! 575: tcg_gen_add_ptr(addr, cpu_env, addr);
1.1 root 576:
1.1.1.7 ! root 577: tcg_gen_ld_tl(r_tmp1, addr, sizeof(target_ulong) * from);
! 578: tcg_temp_free_ptr(addr);
! 579: tcg_temp_free_i32(r_tmp2);
! 580: }
! 581: gen_store_gpr(r_tmp1, to);
! 582: tcg_temp_free(r_tmp1);
! 583: }
1.1 root 584:
1.1.1.7 ! root 585: static inline void gen_store_srsgpr (int from, int to)
! 586: {
! 587: if (to != 0) {
! 588: TCGv r_tmp1 = tcg_temp_new();
! 589: TCGv_i32 r_tmp2 = tcg_temp_new_i32();
! 590: TCGv_ptr addr = tcg_temp_new_ptr();
1.1.1.4 root 591:
1.1.1.7 ! root 592: gen_load_gpr(r_tmp1, from);
! 593: tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
! 594: tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
! 595: tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
! 596: tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
! 597: tcg_gen_ext_i32_ptr(addr, r_tmp2);
! 598: tcg_gen_add_ptr(addr, cpu_env, addr);
1.1.1.4 root 599:
1.1.1.7 ! root 600: tcg_gen_st_tl(r_tmp1, addr, sizeof(target_ulong) * to);
! 601: tcg_temp_free_ptr(addr);
! 602: tcg_temp_free_i32(r_tmp2);
! 603: tcg_temp_free(r_tmp1);
1.1.1.6 root 604: }
605: }
606:
1.1.1.7 ! root 607: /* Floating point register moves. */
! 608: static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
1.1.1.6 root 609: {
1.1.1.7 ! root 610: tcg_gen_mov_i32(t, fpu_fpr32[reg]);
! 611: }
! 612:
! 613: static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
! 614: {
! 615: tcg_gen_mov_i32(fpu_fpr32[reg], t);
! 616: }
! 617:
! 618: static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
! 619: {
! 620: if (ctx->hflags & MIPS_HFLAG_F64)
! 621: tcg_gen_mov_i64(t, fpu_fpr64[reg]);
! 622: else {
! 623: tcg_gen_concat_i32_i64(t, fpu_fpr32[reg & ~1], fpu_fpr32[reg | 1]);
1.1.1.6 root 624: }
625: }
626:
1.1.1.7 ! root 627: static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
1.1 root 628: {
1.1.1.7 ! root 629: if (ctx->hflags & MIPS_HFLAG_F64)
! 630: tcg_gen_mov_i64(fpu_fpr64[reg], t);
! 631: else {
! 632: tcg_gen_trunc_i64_i32(fpu_fpr32[reg & ~1], t);
! 633: tcg_gen_shri_i64(t, t, 32);
! 634: tcg_gen_trunc_i64_i32(fpu_fpr32[reg | 1], t);
1.1 root 635: }
1.1.1.7 ! root 636: }
! 637:
! 638: static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
! 639: {
! 640: tcg_gen_mov_i32(t, fpu_fpr32h[reg]);
! 641: }
! 642:
! 643: static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
! 644: {
! 645: tcg_gen_mov_i32(fpu_fpr32h[reg], t);
! 646: }
! 647:
! 648: static inline void get_fp_cond (TCGv_i32 t)
! 649: {
! 650: TCGv_i32 r_tmp1 = tcg_temp_new_i32();
! 651: TCGv_i32 r_tmp2 = tcg_temp_new_i32();
! 652:
! 653: tcg_gen_shri_i32(r_tmp2, fpu_fcr31, 24);
! 654: tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xfe);
! 655: tcg_gen_shri_i32(r_tmp1, fpu_fcr31, 23);
! 656: tcg_gen_andi_i32(r_tmp1, r_tmp1, 0x1);
! 657: tcg_gen_or_i32(t, r_tmp1, r_tmp2);
! 658: tcg_temp_free_i32(r_tmp1);
! 659: tcg_temp_free_i32(r_tmp2);
! 660: }
! 661:
! 662: #define FOP_CONDS(type, fmt, bits) \
! 663: static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
! 664: TCGv_i##bits b, int cc) \
! 665: { \
! 666: switch (n) { \
! 667: case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
! 668: case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
! 669: case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
! 670: case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
! 671: case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
! 672: case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
! 673: case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
! 674: case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
! 675: case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
! 676: case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
! 677: case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
! 678: case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
! 679: case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
! 680: case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
! 681: case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
! 682: case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
! 683: default: abort(); \
! 684: } \
! 685: }
! 686:
! 687: FOP_CONDS(, d, 64)
! 688: FOP_CONDS(abs, d, 64)
! 689: FOP_CONDS(, s, 32)
! 690: FOP_CONDS(abs, s, 32)
! 691: FOP_CONDS(, ps, 64)
! 692: FOP_CONDS(abs, ps, 64)
! 693: #undef FOP_CONDS
! 694:
! 695: /* Tests */
! 696: #define OP_COND(name, cond) \
! 697: static inline void glue(gen_op_, name) (TCGv t0, TCGv t1) \
! 698: { \
! 699: int l1 = gen_new_label(); \
! 700: int l2 = gen_new_label(); \
! 701: \
! 702: tcg_gen_brcond_tl(cond, t0, t1, l1); \
! 703: tcg_gen_movi_tl(t0, 0); \
! 704: tcg_gen_br(l2); \
! 705: gen_set_label(l1); \
! 706: tcg_gen_movi_tl(t0, 1); \
! 707: gen_set_label(l2); \
! 708: }
! 709: OP_COND(eq, TCG_COND_EQ);
! 710: OP_COND(ne, TCG_COND_NE);
! 711: OP_COND(ge, TCG_COND_GE);
! 712: OP_COND(geu, TCG_COND_GEU);
! 713: OP_COND(lt, TCG_COND_LT);
! 714: OP_COND(ltu, TCG_COND_LTU);
! 715: #undef OP_COND
! 716:
! 717: #define OP_CONDI(name, cond) \
! 718: static inline void glue(gen_op_, name) (TCGv t, target_ulong val) \
! 719: { \
! 720: int l1 = gen_new_label(); \
! 721: int l2 = gen_new_label(); \
! 722: \
! 723: tcg_gen_brcondi_tl(cond, t, val, l1); \
! 724: tcg_gen_movi_tl(t, 0); \
! 725: tcg_gen_br(l2); \
! 726: gen_set_label(l1); \
! 727: tcg_gen_movi_tl(t, 1); \
! 728: gen_set_label(l2); \
! 729: }
! 730: OP_CONDI(lti, TCG_COND_LT);
! 731: OP_CONDI(ltiu, TCG_COND_LTU);
! 732: #undef OP_CONDI
! 733:
! 734: #define OP_CONDZ(name, cond) \
! 735: static inline void glue(gen_op_, name) (TCGv t) \
! 736: { \
! 737: int l1 = gen_new_label(); \
! 738: int l2 = gen_new_label(); \
! 739: \
! 740: tcg_gen_brcondi_tl(cond, t, 0, l1); \
! 741: tcg_gen_movi_tl(t, 0); \
! 742: tcg_gen_br(l2); \
! 743: gen_set_label(l1); \
! 744: tcg_gen_movi_tl(t, 1); \
! 745: gen_set_label(l2); \
! 746: }
! 747: OP_CONDZ(gez, TCG_COND_GE);
! 748: OP_CONDZ(gtz, TCG_COND_GT);
! 749: OP_CONDZ(lez, TCG_COND_LE);
! 750: OP_CONDZ(ltz, TCG_COND_LT);
! 751: #undef OP_CONDZ
! 752:
! 753: static inline void gen_save_pc(target_ulong pc)
! 754: {
! 755: tcg_gen_movi_tl(cpu_PC, pc);
! 756: }
! 757:
! 758: static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
! 759: {
! 760: LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1.1 root 761: if (do_save_pc && ctx->pc != ctx->saved_pc) {
1.1.1.6 root 762: gen_save_pc(ctx->pc);
1.1 root 763: ctx->saved_pc = ctx->pc;
764: }
765: if (ctx->hflags != ctx->saved_hflags) {
1.1.1.7 ! root 766: TCGv_i32 r_tmp = tcg_temp_new_i32();
! 767:
! 768: tcg_gen_movi_i32(r_tmp, ctx->hflags);
! 769: tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
! 770: tcg_temp_free_i32(r_tmp);
1.1 root 771: ctx->saved_hflags = ctx->hflags;
1.1.1.6 root 772: switch (ctx->hflags & MIPS_HFLAG_BMASK) {
773: case MIPS_HFLAG_BR:
774: break;
775: case MIPS_HFLAG_BC:
776: case MIPS_HFLAG_BL:
777: case MIPS_HFLAG_B:
1.1.1.7 ! root 778: tcg_gen_movi_tl(btarget, ctx->btarget);
1.1.1.6 root 779: break;
1.1 root 780: }
781: }
782: }
783:
1.1.1.7 ! root 784: static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
1.1.1.6 root 785: {
786: ctx->saved_hflags = ctx->hflags;
787: switch (ctx->hflags & MIPS_HFLAG_BMASK) {
788: case MIPS_HFLAG_BR:
789: break;
790: case MIPS_HFLAG_BC:
791: case MIPS_HFLAG_BL:
1.1.1.7 ! root 792: case MIPS_HFLAG_B:
1.1.1.6 root 793: ctx->btarget = env->btarget;
794: break;
795: }
796: }
797:
1.1.1.7 ! root 798: static inline void
! 799: generate_exception_err (DisasContext *ctx, int excp, int err)
1.1 root 800: {
1.1.1.7 ! root 801: TCGv_i32 texcp = tcg_const_i32(excp);
! 802: TCGv_i32 terr = tcg_const_i32(err);
1.1 root 803: save_cpu_state(ctx, 1);
1.1.1.7 ! root 804: gen_helper_raise_exception_err(texcp, terr);
! 805: tcg_temp_free_i32(terr);
! 806: tcg_temp_free_i32(texcp);
! 807: gen_helper_interrupt_restart();
! 808: tcg_gen_exit_tb(0);
! 809: }
! 810:
! 811: static inline void
! 812: generate_exception (DisasContext *ctx, int excp)
! 813: {
! 814: save_cpu_state(ctx, 1);
! 815: gen_helper_0i(raise_exception, excp);
! 816: gen_helper_interrupt_restart();
! 817: tcg_gen_exit_tb(0);
1.1 root 818: }
819:
1.1.1.7 ! root 820: /* Addresses computation */
! 821: static inline void gen_op_addr_add (DisasContext *ctx, TCGv t0, TCGv t1)
1.1.1.2 root 822: {
1.1.1.7 ! root 823: tcg_gen_add_tl(t0, t0, t1);
! 824:
! 825: #if defined(TARGET_MIPS64)
! 826: /* For compatibility with 32-bit code, data reference in user mode
! 827: with Status_UX = 0 should be casted to 32-bit and sign extended.
! 828: See the MIPS64 PRA manual, section 4.10. */
! 829: if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
! 830: !(ctx->hflags & MIPS_HFLAG_UX)) {
! 831: tcg_gen_ext32s_i64(t0, t0);
! 832: }
! 833: #endif
1.1.1.2 root 834: }
835:
1.1.1.7 ! root 836: static inline void check_cp0_enabled(DisasContext *ctx)
1.1.1.6 root 837: {
838: if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
839: generate_exception_err(ctx, EXCP_CpU, 1);
840: }
841:
1.1.1.7 ! root 842: static inline void check_cp1_enabled(DisasContext *ctx)
1.1.1.6 root 843: {
844: if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
845: generate_exception_err(ctx, EXCP_CpU, 1);
846: }
847:
848: /* Verify that the processor is running with COP1X instructions enabled.
849: This is associated with the nabla symbol in the MIPS32 and MIPS64
850: opcode tables. */
851:
1.1.1.7 ! root 852: static inline void check_cop1x(DisasContext *ctx)
1.1.1.6 root 853: {
854: if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
855: generate_exception(ctx, EXCP_RI);
856: }
857:
858: /* Verify that the processor is running with 64-bit floating-point
859: operations enabled. */
860:
1.1.1.7 ! root 861: static inline void check_cp1_64bitmode(DisasContext *ctx)
1.1.1.6 root 862: {
863: if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
864: generate_exception(ctx, EXCP_RI);
865: }
866:
867: /*
868: * Verify if floating point register is valid; an operation is not defined
869: * if bit 0 of any register specification is set and the FR bit in the
870: * Status register equals zero, since the register numbers specify an
871: * even-odd pair of adjacent coprocessor general registers. When the FR bit
872: * in the Status register equals one, both even and odd register numbers
873: * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
874: *
875: * Multiple 64 bit wide registers can be checked by calling
876: * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
877: */
1.1.1.7 ! root 878: static inline void check_cp1_registers(DisasContext *ctx, int regs)
1.1.1.6 root 879: {
880: if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
881: generate_exception(ctx, EXCP_RI);
882: }
883:
884: /* This code generates a "reserved instruction" exception if the
885: CPU does not support the instruction set corresponding to flags. */
1.1.1.7 ! root 886: static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
1.1.1.6 root 887: {
888: if (unlikely(!(env->insn_flags & flags)))
889: generate_exception(ctx, EXCP_RI);
890: }
891:
892: /* This code generates a "reserved instruction" exception if 64-bit
893: instructions are not enabled. */
1.1.1.7 ! root 894: static inline void check_mips_64(DisasContext *ctx)
1.1.1.6 root 895: {
896: if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
897: generate_exception(ctx, EXCP_RI);
898: }
899:
1.1.1.7 ! root 900: /* load/store instructions. */
! 901: #define OP_LD(insn,fname) \
! 902: static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx) \
! 903: { \
! 904: tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
! 905: }
! 906: OP_LD(lb,ld8s);
! 907: OP_LD(lbu,ld8u);
! 908: OP_LD(lh,ld16s);
! 909: OP_LD(lhu,ld16u);
! 910: OP_LD(lw,ld32s);
! 911: #if defined(TARGET_MIPS64)
! 912: OP_LD(lwu,ld32u);
! 913: OP_LD(ld,ld64);
! 914: #endif
! 915: #undef OP_LD
! 916:
! 917: #define OP_ST(insn,fname) \
! 918: static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
! 919: { \
! 920: tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
! 921: }
! 922: OP_ST(sb,st8);
! 923: OP_ST(sh,st16);
! 924: OP_ST(sw,st32);
! 925: #if defined(TARGET_MIPS64)
! 926: OP_ST(sd,st64);
! 927: #endif
! 928: #undef OP_ST
! 929:
! 930: #define OP_LD_ATOMIC(insn,fname) \
! 931: static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
! 932: { \
! 933: tcg_gen_mov_tl(t1, t0); \
! 934: tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
! 935: tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
1.1 root 936: }
1.1.1.7 ! root 937: OP_LD_ATOMIC(ll,ld32s);
! 938: #if defined(TARGET_MIPS64)
! 939: OP_LD_ATOMIC(lld,ld64);
1.1 root 940: #endif
1.1.1.7 ! root 941: #undef OP_LD_ATOMIC
1.1 root 942:
1.1.1.7 ! root 943: #define OP_ST_ATOMIC(insn,fname,almask) \
! 944: static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
! 945: { \
! 946: TCGv r_tmp = tcg_temp_local_new(); \
! 947: int l1 = gen_new_label(); \
! 948: int l2 = gen_new_label(); \
! 949: int l3 = gen_new_label(); \
! 950: \
! 951: tcg_gen_andi_tl(r_tmp, t0, almask); \
! 952: tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1); \
! 953: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
! 954: generate_exception(ctx, EXCP_AdES); \
! 955: gen_set_label(l1); \
! 956: tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
! 957: tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2); \
! 958: tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
! 959: tcg_gen_movi_tl(t0, 1); \
! 960: tcg_gen_br(l3); \
! 961: gen_set_label(l2); \
! 962: tcg_gen_movi_tl(t0, 0); \
! 963: gen_set_label(l3); \
! 964: tcg_temp_free(r_tmp); \
! 965: }
! 966: OP_ST_ATOMIC(sc,st32,0x3);
1.1.1.6 root 967: #if defined(TARGET_MIPS64)
1.1.1.7 ! root 968: OP_ST_ATOMIC(scd,st64,0x7);
1.1 root 969: #endif
1.1.1.7 ! root 970: #undef OP_ST_ATOMIC
1.1 root 971:
972: /* Load and store */
1.1.1.5 root 973: static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1.1 root 974: int base, int16_t offset)
975: {
1.1.1.6 root 976: const char *opn = "ldst";
1.1.1.7 ! root 977: TCGv t0 = tcg_temp_local_new();
! 978: TCGv t1 = tcg_temp_local_new();
1.1 root 979:
980: if (base == 0) {
1.1.1.7 ! root 981: tcg_gen_movi_tl(t0, offset);
1.1 root 982: } else if (offset == 0) {
1.1.1.7 ! root 983: gen_load_gpr(t0, base);
1.1 root 984: } else {
1.1.1.7 ! root 985: tcg_gen_movi_tl(t0, offset);
! 986: gen_op_addr_add(ctx, t0, cpu_gpr[base]);
1.1 root 987: }
988: /* Don't do NOP if destination is zero: we must perform the actual
1.1.1.6 root 989: memory access. */
1.1 root 990: switch (opc) {
1.1.1.6 root 991: #if defined(TARGET_MIPS64)
992: case OPC_LWU:
1.1.1.7 ! root 993: op_ldst_lwu(t0, ctx);
! 994: gen_store_gpr(t0, rt);
1.1.1.6 root 995: opn = "lwu";
996: break;
1.1 root 997: case OPC_LD:
1.1.1.7 ! root 998: op_ldst_ld(t0, ctx);
! 999: gen_store_gpr(t0, rt);
1.1 root 1000: opn = "ld";
1001: break;
1.1.1.5 root 1002: case OPC_LLD:
1.1.1.7 ! root 1003: op_ldst_lld(t0, t1, ctx);
! 1004: gen_store_gpr(t0, rt);
1.1.1.5 root 1005: opn = "lld";
1006: break;
1.1 root 1007: case OPC_SD:
1.1.1.7 ! root 1008: gen_load_gpr(t1, rt);
! 1009: op_ldst_sd(t0, t1, ctx);
1.1 root 1010: opn = "sd";
1011: break;
1.1.1.5 root 1012: case OPC_SCD:
1.1.1.6 root 1013: save_cpu_state(ctx, 1);
1.1.1.7 ! root 1014: gen_load_gpr(t1, rt);
! 1015: op_ldst_scd(t0, t1, ctx);
! 1016: gen_store_gpr(t0, rt);
1.1.1.5 root 1017: opn = "scd";
1018: break;
1.1 root 1019: case OPC_LDL:
1.1.1.7 ! root 1020: save_cpu_state(ctx, 1);
! 1021: gen_load_gpr(t1, rt);
! 1022: gen_helper_3i(ldl, t1, t0, t1, ctx->mem_idx);
! 1023: gen_store_gpr(t1, rt);
1.1 root 1024: opn = "ldl";
1025: break;
1026: case OPC_SDL:
1.1.1.7 ! root 1027: save_cpu_state(ctx, 1);
! 1028: gen_load_gpr(t1, rt);
! 1029: gen_helper_2i(sdl, t0, t1, ctx->mem_idx);
1.1 root 1030: opn = "sdl";
1031: break;
1032: case OPC_LDR:
1.1.1.7 ! root 1033: save_cpu_state(ctx, 1);
! 1034: gen_load_gpr(t1, rt);
! 1035: gen_helper_3i(ldr, t1, t0, t1, ctx->mem_idx);
! 1036: gen_store_gpr(t1, rt);
1.1 root 1037: opn = "ldr";
1038: break;
1039: case OPC_SDR:
1.1.1.7 ! root 1040: save_cpu_state(ctx, 1);
! 1041: gen_load_gpr(t1, rt);
! 1042: gen_helper_2i(sdr, t0, t1, ctx->mem_idx);
1.1 root 1043: opn = "sdr";
1044: break;
1045: #endif
1046: case OPC_LW:
1.1.1.7 ! root 1047: op_ldst_lw(t0, ctx);
! 1048: gen_store_gpr(t0, rt);
1.1 root 1049: opn = "lw";
1050: break;
1051: case OPC_SW:
1.1.1.7 ! root 1052: gen_load_gpr(t1, rt);
! 1053: op_ldst_sw(t0, t1, ctx);
1.1 root 1054: opn = "sw";
1055: break;
1056: case OPC_LH:
1.1.1.7 ! root 1057: op_ldst_lh(t0, ctx);
! 1058: gen_store_gpr(t0, rt);
1.1 root 1059: opn = "lh";
1060: break;
1061: case OPC_SH:
1.1.1.7 ! root 1062: gen_load_gpr(t1, rt);
! 1063: op_ldst_sh(t0, t1, ctx);
1.1 root 1064: opn = "sh";
1065: break;
1066: case OPC_LHU:
1.1.1.7 ! root 1067: op_ldst_lhu(t0, ctx);
! 1068: gen_store_gpr(t0, rt);
1.1 root 1069: opn = "lhu";
1070: break;
1071: case OPC_LB:
1.1.1.7 ! root 1072: op_ldst_lb(t0, ctx);
! 1073: gen_store_gpr(t0, rt);
1.1 root 1074: opn = "lb";
1075: break;
1076: case OPC_SB:
1.1.1.7 ! root 1077: gen_load_gpr(t1, rt);
! 1078: op_ldst_sb(t0, t1, ctx);
1.1 root 1079: opn = "sb";
1080: break;
1081: case OPC_LBU:
1.1.1.7 ! root 1082: op_ldst_lbu(t0, ctx);
! 1083: gen_store_gpr(t0, rt);
1.1 root 1084: opn = "lbu";
1085: break;
1086: case OPC_LWL:
1.1.1.7 ! root 1087: save_cpu_state(ctx, 1);
! 1088: gen_load_gpr(t1, rt);
! 1089: gen_helper_3i(lwl, t1, t0, t1, ctx->mem_idx);
! 1090: gen_store_gpr(t1, rt);
1.1 root 1091: opn = "lwl";
1092: break;
1093: case OPC_SWL:
1.1.1.7 ! root 1094: save_cpu_state(ctx, 1);
! 1095: gen_load_gpr(t1, rt);
! 1096: gen_helper_2i(swl, t0, t1, ctx->mem_idx);
1.1 root 1097: opn = "swr";
1098: break;
1099: case OPC_LWR:
1.1.1.7 ! root 1100: save_cpu_state(ctx, 1);
! 1101: gen_load_gpr(t1, rt);
! 1102: gen_helper_3i(lwr, t1, t0, t1, ctx->mem_idx);
! 1103: gen_store_gpr(t1, rt);
1.1 root 1104: opn = "lwr";
1105: break;
1106: case OPC_SWR:
1.1.1.7 ! root 1107: save_cpu_state(ctx, 1);
! 1108: gen_load_gpr(t1, rt);
! 1109: gen_helper_2i(swr, t0, t1, ctx->mem_idx);
1.1 root 1110: opn = "swr";
1111: break;
1112: case OPC_LL:
1.1.1.7 ! root 1113: op_ldst_ll(t0, t1, ctx);
! 1114: gen_store_gpr(t0, rt);
1.1 root 1115: opn = "ll";
1116: break;
1117: case OPC_SC:
1.1.1.6 root 1118: save_cpu_state(ctx, 1);
1.1.1.7 ! root 1119: gen_load_gpr(t1, rt);
! 1120: op_ldst_sc(t0, t1, ctx);
! 1121: gen_store_gpr(t0, rt);
1.1 root 1122: opn = "sc";
1123: break;
1124: default:
1.1.1.6 root 1125: MIPS_INVAL(opn);
1.1 root 1126: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 1127: goto out;
1.1 root 1128: }
1129: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1.1.1.7 ! root 1130: out:
! 1131: tcg_temp_free(t0);
! 1132: tcg_temp_free(t1);
1.1 root 1133: }
1134:
1.1.1.4 root 1135: /* Load and store */
1.1.1.5 root 1136: static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1.1.1.7 ! root 1137: int base, int16_t offset)
1.1.1.4 root 1138: {
1.1.1.6 root 1139: const char *opn = "flt_ldst";
1.1.1.7 ! root 1140: TCGv t0 = tcg_temp_local_new();
1.1.1.4 root 1141:
1142: if (base == 0) {
1.1.1.7 ! root 1143: tcg_gen_movi_tl(t0, offset);
1.1.1.4 root 1144: } else if (offset == 0) {
1.1.1.7 ! root 1145: gen_load_gpr(t0, base);
1.1.1.4 root 1146: } else {
1.1.1.7 ! root 1147: tcg_gen_movi_tl(t0, offset);
! 1148: gen_op_addr_add(ctx, t0, cpu_gpr[base]);
1.1.1.4 root 1149: }
1150: /* Don't do NOP if destination is zero: we must perform the actual
1.1.1.6 root 1151: memory access. */
1.1.1.4 root 1152: switch (opc) {
1153: case OPC_LWC1:
1.1.1.7 ! root 1154: {
! 1155: TCGv_i32 fp0 = tcg_temp_new_i32();
! 1156: TCGv t1 = tcg_temp_new();
! 1157:
! 1158: tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
! 1159: tcg_gen_trunc_tl_i32(fp0, t1);
! 1160: gen_store_fpr32(fp0, ft);
! 1161: tcg_temp_free(t1);
! 1162: tcg_temp_free_i32(fp0);
! 1163: }
1.1.1.4 root 1164: opn = "lwc1";
1165: break;
1166: case OPC_SWC1:
1.1.1.7 ! root 1167: {
! 1168: TCGv_i32 fp0 = tcg_temp_new_i32();
! 1169: TCGv t1 = tcg_temp_new();
! 1170:
! 1171: gen_load_fpr32(fp0, ft);
! 1172: tcg_gen_extu_i32_tl(t1, fp0);
! 1173: tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
! 1174: tcg_temp_free(t1);
! 1175: tcg_temp_free_i32(fp0);
! 1176: }
1.1.1.4 root 1177: opn = "swc1";
1178: break;
1179: case OPC_LDC1:
1.1.1.7 ! root 1180: {
! 1181: TCGv_i64 fp0 = tcg_temp_new_i64();
! 1182:
! 1183: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
! 1184: gen_store_fpr64(ctx, fp0, ft);
! 1185: tcg_temp_free_i64(fp0);
! 1186: }
1.1.1.4 root 1187: opn = "ldc1";
1188: break;
1189: case OPC_SDC1:
1.1.1.7 ! root 1190: {
! 1191: TCGv_i64 fp0 = tcg_temp_new_i64();
! 1192:
! 1193: gen_load_fpr64(ctx, fp0, ft);
! 1194: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
! 1195: tcg_temp_free_i64(fp0);
! 1196: }
1.1.1.4 root 1197: opn = "sdc1";
1198: break;
1199: default:
1.1.1.6 root 1200: MIPS_INVAL(opn);
1201: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 1202: goto out;
1.1.1.4 root 1203: }
1204: MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1.1.1.7 ! root 1205: out:
! 1206: tcg_temp_free(t0);
1.1.1.4 root 1207: }
1.1.1.5 root 1208:
1.1 root 1209: /* Arithmetic with immediate operand */
1.1.1.6 root 1210: static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1211: int rt, int rs, int16_t imm)
1.1 root 1212: {
1.1.1.6 root 1213: target_ulong uimm;
1214: const char *opn = "imm arith";
1.1.1.7 ! root 1215: TCGv t0 = tcg_temp_local_new();
1.1 root 1216:
1.1.1.5 root 1217: if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1.1.1.6 root 1218: /* If no destination, treat it as a NOP.
1219: For addi, we must generate the overflow exception when needed. */
1.1 root 1220: MIPS_DEBUG("NOP");
1.1.1.7 ! root 1221: goto out;
1.1 root 1222: }
1.1.1.6 root 1223: uimm = (uint16_t)imm;
1224: switch (opc) {
1225: case OPC_ADDI:
1226: case OPC_ADDIU:
1227: #if defined(TARGET_MIPS64)
1228: case OPC_DADDI:
1229: case OPC_DADDIU:
1230: #endif
1231: case OPC_SLTI:
1232: case OPC_SLTIU:
1233: uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1234: /* Fall through. */
1235: case OPC_ANDI:
1236: case OPC_ORI:
1237: case OPC_XORI:
1.1.1.7 ! root 1238: gen_load_gpr(t0, rs);
1.1.1.6 root 1239: break;
1240: case OPC_LUI:
1.1.1.7 ! root 1241: tcg_gen_movi_tl(t0, imm << 16);
1.1.1.6 root 1242: break;
1243: case OPC_SLL:
1244: case OPC_SRA:
1245: case OPC_SRL:
1246: #if defined(TARGET_MIPS64)
1247: case OPC_DSLL:
1248: case OPC_DSRA:
1249: case OPC_DSRL:
1250: case OPC_DSLL32:
1251: case OPC_DSRA32:
1252: case OPC_DSRL32:
1253: #endif
1254: uimm &= 0x1f;
1.1.1.7 ! root 1255: gen_load_gpr(t0, rs);
1.1.1.6 root 1256: break;
1.1 root 1257: }
1258: switch (opc) {
1259: case OPC_ADDI:
1.1.1.7 ! root 1260: {
! 1261: TCGv r_tmp1 = tcg_temp_new();
! 1262: TCGv r_tmp2 = tcg_temp_new();
! 1263: int l1 = gen_new_label();
! 1264:
! 1265: save_cpu_state(ctx, 1);
! 1266: tcg_gen_ext32s_tl(r_tmp1, t0);
! 1267: tcg_gen_addi_tl(t0, r_tmp1, uimm);
! 1268:
! 1269: tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
! 1270: tcg_gen_xori_tl(r_tmp2, t0, uimm);
! 1271: tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
! 1272: tcg_temp_free(r_tmp2);
! 1273: tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
! 1274: /* operands of same sign, result different sign */
! 1275: generate_exception(ctx, EXCP_OVERFLOW);
! 1276: gen_set_label(l1);
! 1277: tcg_temp_free(r_tmp1);
! 1278:
! 1279: tcg_gen_ext32s_tl(t0, t0);
! 1280: }
1.1 root 1281: opn = "addi";
1282: break;
1283: case OPC_ADDIU:
1.1.1.7 ! root 1284: tcg_gen_addi_tl(t0, t0, uimm);
! 1285: tcg_gen_ext32s_tl(t0, t0);
1.1 root 1286: opn = "addiu";
1287: break;
1.1.1.6 root 1288: #if defined(TARGET_MIPS64)
1.1.1.5 root 1289: case OPC_DADDI:
1.1.1.7 ! root 1290: {
! 1291: TCGv r_tmp1 = tcg_temp_new();
! 1292: TCGv r_tmp2 = tcg_temp_new();
! 1293: int l1 = gen_new_label();
! 1294:
! 1295: save_cpu_state(ctx, 1);
! 1296: tcg_gen_mov_tl(r_tmp1, t0);
! 1297: tcg_gen_addi_tl(t0, t0, uimm);
! 1298:
! 1299: tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
! 1300: tcg_gen_xori_tl(r_tmp2, t0, uimm);
! 1301: tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
! 1302: tcg_temp_free(r_tmp2);
! 1303: tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
! 1304: /* operands of same sign, result different sign */
! 1305: generate_exception(ctx, EXCP_OVERFLOW);
! 1306: gen_set_label(l1);
! 1307: tcg_temp_free(r_tmp1);
! 1308: }
1.1.1.5 root 1309: opn = "daddi";
1310: break;
1311: case OPC_DADDIU:
1.1.1.7 ! root 1312: tcg_gen_addi_tl(t0, t0, uimm);
1.1.1.5 root 1313: opn = "daddiu";
1314: break;
1315: #endif
1.1 root 1316: case OPC_SLTI:
1.1.1.7 ! root 1317: gen_op_lti(t0, uimm);
1.1 root 1318: opn = "slti";
1319: break;
1320: case OPC_SLTIU:
1.1.1.7 ! root 1321: gen_op_ltiu(t0, uimm);
1.1 root 1322: opn = "sltiu";
1323: break;
1324: case OPC_ANDI:
1.1.1.7 ! root 1325: tcg_gen_andi_tl(t0, t0, uimm);
1.1 root 1326: opn = "andi";
1327: break;
1328: case OPC_ORI:
1.1.1.7 ! root 1329: tcg_gen_ori_tl(t0, t0, uimm);
1.1 root 1330: opn = "ori";
1331: break;
1332: case OPC_XORI:
1.1.1.7 ! root 1333: tcg_gen_xori_tl(t0, t0, uimm);
1.1 root 1334: opn = "xori";
1335: break;
1336: case OPC_LUI:
1337: opn = "lui";
1338: break;
1339: case OPC_SLL:
1.1.1.7 ! root 1340: tcg_gen_shli_tl(t0, t0, uimm);
! 1341: tcg_gen_ext32s_tl(t0, t0);
1.1 root 1342: opn = "sll";
1343: break;
1344: case OPC_SRA:
1.1.1.7 ! root 1345: tcg_gen_ext32s_tl(t0, t0);
! 1346: tcg_gen_sari_tl(t0, t0, uimm);
1.1 root 1347: opn = "sra";
1348: break;
1349: case OPC_SRL:
1.1.1.6 root 1350: switch ((ctx->opcode >> 21) & 0x1f) {
1351: case 0:
1.1.1.7 ! root 1352: if (uimm != 0) {
! 1353: tcg_gen_ext32u_tl(t0, t0);
! 1354: tcg_gen_shri_tl(t0, t0, uimm);
! 1355: } else {
! 1356: tcg_gen_ext32s_tl(t0, t0);
! 1357: }
1.1.1.5 root 1358: opn = "srl";
1.1.1.6 root 1359: break;
1360: case 1:
1361: /* rotr is decoded as srl on non-R2 CPUs */
1362: if (env->insn_flags & ISA_MIPS32R2) {
1.1.1.7 ! root 1363: if (uimm != 0) {
! 1364: TCGv_i32 r_tmp1 = tcg_temp_new_i32();
! 1365:
! 1366: tcg_gen_trunc_tl_i32(r_tmp1, t0);
! 1367: tcg_gen_rotri_i32(r_tmp1, r_tmp1, uimm);
! 1368: tcg_gen_ext_i32_tl(t0, r_tmp1);
! 1369: tcg_temp_free_i32(r_tmp1);
! 1370: }
1.1.1.6 root 1371: opn = "rotr";
1372: } else {
1.1.1.7 ! root 1373: if (uimm != 0) {
! 1374: tcg_gen_ext32u_tl(t0, t0);
! 1375: tcg_gen_shri_tl(t0, t0, uimm);
! 1376: } else {
! 1377: tcg_gen_ext32s_tl(t0, t0);
! 1378: }
1.1.1.6 root 1379: opn = "srl";
1380: }
1381: break;
1382: default:
1383: MIPS_INVAL("invalid srl flag");
1384: generate_exception(ctx, EXCP_RI);
1385: break;
1386: }
1.1.1.5 root 1387: break;
1.1.1.6 root 1388: #if defined(TARGET_MIPS64)
1.1.1.5 root 1389: case OPC_DSLL:
1.1.1.7 ! root 1390: tcg_gen_shli_tl(t0, t0, uimm);
1.1.1.5 root 1391: opn = "dsll";
1392: break;
1393: case OPC_DSRA:
1.1.1.7 ! root 1394: tcg_gen_sari_tl(t0, t0, uimm);
1.1.1.5 root 1395: opn = "dsra";
1396: break;
1397: case OPC_DSRL:
1.1.1.6 root 1398: switch ((ctx->opcode >> 21) & 0x1f) {
1399: case 0:
1.1.1.7 ! root 1400: tcg_gen_shri_tl(t0, t0, uimm);
1.1.1.5 root 1401: opn = "dsrl";
1.1.1.6 root 1402: break;
1403: case 1:
1404: /* drotr is decoded as dsrl on non-R2 CPUs */
1405: if (env->insn_flags & ISA_MIPS32R2) {
1.1.1.7 ! root 1406: if (uimm != 0) {
! 1407: tcg_gen_rotri_tl(t0, t0, uimm);
! 1408: }
1.1.1.6 root 1409: opn = "drotr";
1410: } else {
1.1.1.7 ! root 1411: tcg_gen_shri_tl(t0, t0, uimm);
1.1.1.6 root 1412: opn = "dsrl";
1413: }
1414: break;
1415: default:
1416: MIPS_INVAL("invalid dsrl flag");
1417: generate_exception(ctx, EXCP_RI);
1418: break;
1419: }
1.1.1.5 root 1420: break;
1421: case OPC_DSLL32:
1.1.1.7 ! root 1422: tcg_gen_shli_tl(t0, t0, uimm + 32);
1.1.1.5 root 1423: opn = "dsll32";
1424: break;
1425: case OPC_DSRA32:
1.1.1.7 ! root 1426: tcg_gen_sari_tl(t0, t0, uimm + 32);
1.1.1.5 root 1427: opn = "dsra32";
1428: break;
1429: case OPC_DSRL32:
1.1.1.6 root 1430: switch ((ctx->opcode >> 21) & 0x1f) {
1431: case 0:
1.1.1.7 ! root 1432: tcg_gen_shri_tl(t0, t0, uimm + 32);
1.1.1.5 root 1433: opn = "dsrl32";
1.1.1.6 root 1434: break;
1435: case 1:
1436: /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1437: if (env->insn_flags & ISA_MIPS32R2) {
1.1.1.7 ! root 1438: tcg_gen_rotri_tl(t0, t0, uimm + 32);
1.1.1.6 root 1439: opn = "drotr32";
1440: } else {
1.1.1.7 ! root 1441: tcg_gen_shri_tl(t0, t0, uimm + 32);
1.1.1.6 root 1442: opn = "dsrl32";
1443: }
1444: break;
1445: default:
1446: MIPS_INVAL("invalid dsrl32 flag");
1447: generate_exception(ctx, EXCP_RI);
1448: break;
1449: }
1.1 root 1450: break;
1.1.1.5 root 1451: #endif
1.1 root 1452: default:
1.1.1.6 root 1453: MIPS_INVAL(opn);
1.1 root 1454: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 1455: goto out;
1.1 root 1456: }
1.1.1.7 ! root 1457: gen_store_gpr(t0, rt);
1.1.1.6 root 1458: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1.1.1.7 ! root 1459: out:
! 1460: tcg_temp_free(t0);
1.1 root 1461: }
1462:
1463: /* Arithmetic */
1.1.1.6 root 1464: static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1.1 root 1465: int rd, int rs, int rt)
1466: {
1.1.1.6 root 1467: const char *opn = "arith";
1.1.1.7 ! root 1468: TCGv t0 = tcg_temp_local_new();
! 1469: TCGv t1 = tcg_temp_local_new();
1.1 root 1470:
1.1.1.5 root 1471: if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1472: && opc != OPC_DADD && opc != OPC_DSUB) {
1.1.1.6 root 1473: /* If no destination, treat it as a NOP.
1474: For add & sub, we must generate the overflow exception when needed. */
1.1 root 1475: MIPS_DEBUG("NOP");
1.1.1.7 ! root 1476: goto out;
1.1 root 1477: }
1.1.1.7 ! root 1478: gen_load_gpr(t0, rs);
1.1.1.6 root 1479: /* Specialcase the conventional move operation. */
1480: if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1481: || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1.1.1.7 ! root 1482: gen_store_gpr(t0, rd);
! 1483: goto out;
1.1.1.6 root 1484: }
1.1.1.7 ! root 1485: gen_load_gpr(t1, rt);
1.1 root 1486: switch (opc) {
1487: case OPC_ADD:
1.1.1.7 ! root 1488: {
! 1489: TCGv r_tmp1 = tcg_temp_new();
! 1490: TCGv r_tmp2 = tcg_temp_new();
! 1491: int l1 = gen_new_label();
! 1492:
! 1493: save_cpu_state(ctx, 1);
! 1494: tcg_gen_ext32s_tl(r_tmp1, t0);
! 1495: tcg_gen_ext32s_tl(r_tmp2, t1);
! 1496: tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
! 1497:
! 1498: tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
! 1499: tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
! 1500: tcg_gen_xor_tl(r_tmp2, t0, t1);
! 1501: tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
! 1502: tcg_temp_free(r_tmp2);
! 1503: tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
! 1504: /* operands of same sign, result different sign */
! 1505: generate_exception(ctx, EXCP_OVERFLOW);
! 1506: gen_set_label(l1);
! 1507: tcg_temp_free(r_tmp1);
! 1508:
! 1509: tcg_gen_ext32s_tl(t0, t0);
! 1510: }
1.1 root 1511: opn = "add";
1512: break;
1513: case OPC_ADDU:
1.1.1.7 ! root 1514: tcg_gen_add_tl(t0, t0, t1);
! 1515: tcg_gen_ext32s_tl(t0, t0);
1.1 root 1516: opn = "addu";
1517: break;
1518: case OPC_SUB:
1.1.1.7 ! root 1519: {
! 1520: TCGv r_tmp1 = tcg_temp_new();
! 1521: TCGv r_tmp2 = tcg_temp_new();
! 1522: int l1 = gen_new_label();
! 1523:
! 1524: save_cpu_state(ctx, 1);
! 1525: tcg_gen_ext32s_tl(r_tmp1, t0);
! 1526: tcg_gen_ext32s_tl(r_tmp2, t1);
! 1527: tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
! 1528:
! 1529: tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
! 1530: tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
! 1531: tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
! 1532: tcg_temp_free(r_tmp2);
! 1533: tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
! 1534: /* operands of different sign, first operand and result different sign */
! 1535: generate_exception(ctx, EXCP_OVERFLOW);
! 1536: gen_set_label(l1);
! 1537: tcg_temp_free(r_tmp1);
! 1538:
! 1539: tcg_gen_ext32s_tl(t0, t0);
! 1540: }
1.1 root 1541: opn = "sub";
1542: break;
1543: case OPC_SUBU:
1.1.1.7 ! root 1544: tcg_gen_sub_tl(t0, t0, t1);
! 1545: tcg_gen_ext32s_tl(t0, t0);
1.1 root 1546: opn = "subu";
1547: break;
1.1.1.6 root 1548: #if defined(TARGET_MIPS64)
1.1.1.5 root 1549: case OPC_DADD:
1.1.1.7 ! root 1550: {
! 1551: TCGv r_tmp1 = tcg_temp_new();
! 1552: TCGv r_tmp2 = tcg_temp_new();
! 1553: int l1 = gen_new_label();
! 1554:
! 1555: save_cpu_state(ctx, 1);
! 1556: tcg_gen_mov_tl(r_tmp1, t0);
! 1557: tcg_gen_add_tl(t0, t0, t1);
! 1558:
! 1559: tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
! 1560: tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
! 1561: tcg_gen_xor_tl(r_tmp2, t0, t1);
! 1562: tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
! 1563: tcg_temp_free(r_tmp2);
! 1564: tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
! 1565: /* operands of same sign, result different sign */
! 1566: generate_exception(ctx, EXCP_OVERFLOW);
! 1567: gen_set_label(l1);
! 1568: tcg_temp_free(r_tmp1);
! 1569: }
1.1.1.5 root 1570: opn = "dadd";
1571: break;
1572: case OPC_DADDU:
1.1.1.7 ! root 1573: tcg_gen_add_tl(t0, t0, t1);
1.1.1.5 root 1574: opn = "daddu";
1575: break;
1576: case OPC_DSUB:
1.1.1.7 ! root 1577: {
! 1578: TCGv r_tmp1 = tcg_temp_new();
! 1579: TCGv r_tmp2 = tcg_temp_new();
! 1580: int l1 = gen_new_label();
! 1581:
! 1582: save_cpu_state(ctx, 1);
! 1583: tcg_gen_mov_tl(r_tmp1, t0);
! 1584: tcg_gen_sub_tl(t0, t0, t1);
! 1585:
! 1586: tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
! 1587: tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
! 1588: tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
! 1589: tcg_temp_free(r_tmp2);
! 1590: tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
! 1591: /* operands of different sign, first operand and result different sign */
! 1592: generate_exception(ctx, EXCP_OVERFLOW);
! 1593: gen_set_label(l1);
! 1594: tcg_temp_free(r_tmp1);
! 1595: }
1.1.1.5 root 1596: opn = "dsub";
1597: break;
1598: case OPC_DSUBU:
1.1.1.7 ! root 1599: tcg_gen_sub_tl(t0, t0, t1);
1.1.1.5 root 1600: opn = "dsubu";
1601: break;
1602: #endif
1.1 root 1603: case OPC_SLT:
1.1.1.7 ! root 1604: gen_op_lt(t0, t1);
1.1 root 1605: opn = "slt";
1606: break;
1607: case OPC_SLTU:
1.1.1.7 ! root 1608: gen_op_ltu(t0, t1);
1.1 root 1609: opn = "sltu";
1610: break;
1611: case OPC_AND:
1.1.1.7 ! root 1612: tcg_gen_and_tl(t0, t0, t1);
1.1 root 1613: opn = "and";
1614: break;
1615: case OPC_NOR:
1.1.1.7 ! root 1616: tcg_gen_or_tl(t0, t0, t1);
! 1617: tcg_gen_not_tl(t0, t0);
1.1 root 1618: opn = "nor";
1619: break;
1620: case OPC_OR:
1.1.1.7 ! root 1621: tcg_gen_or_tl(t0, t0, t1);
1.1 root 1622: opn = "or";
1623: break;
1624: case OPC_XOR:
1.1.1.7 ! root 1625: tcg_gen_xor_tl(t0, t0, t1);
1.1 root 1626: opn = "xor";
1627: break;
1628: case OPC_MUL:
1.1.1.7 ! root 1629: tcg_gen_mul_tl(t0, t0, t1);
! 1630: tcg_gen_ext32s_tl(t0, t0);
1.1 root 1631: opn = "mul";
1632: break;
1633: case OPC_MOVN:
1.1.1.7 ! root 1634: {
! 1635: int l1 = gen_new_label();
! 1636:
! 1637: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
! 1638: gen_store_gpr(t0, rd);
! 1639: gen_set_label(l1);
! 1640: }
1.1 root 1641: opn = "movn";
1642: goto print;
1643: case OPC_MOVZ:
1.1.1.7 ! root 1644: {
! 1645: int l1 = gen_new_label();
! 1646:
! 1647: tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
! 1648: gen_store_gpr(t0, rd);
! 1649: gen_set_label(l1);
! 1650: }
1.1 root 1651: opn = "movz";
1652: goto print;
1653: case OPC_SLLV:
1.1.1.7 ! root 1654: tcg_gen_andi_tl(t0, t0, 0x1f);
! 1655: tcg_gen_shl_tl(t0, t1, t0);
! 1656: tcg_gen_ext32s_tl(t0, t0);
1.1 root 1657: opn = "sllv";
1658: break;
1659: case OPC_SRAV:
1.1.1.7 ! root 1660: tcg_gen_ext32s_tl(t1, t1);
! 1661: tcg_gen_andi_tl(t0, t0, 0x1f);
! 1662: tcg_gen_sar_tl(t0, t1, t0);
1.1 root 1663: opn = "srav";
1664: break;
1665: case OPC_SRLV:
1.1.1.6 root 1666: switch ((ctx->opcode >> 6) & 0x1f) {
1667: case 0:
1.1.1.7 ! root 1668: tcg_gen_ext32u_tl(t1, t1);
! 1669: tcg_gen_andi_tl(t0, t0, 0x1f);
! 1670: tcg_gen_shr_tl(t0, t1, t0);
! 1671: tcg_gen_ext32s_tl(t0, t0);
1.1.1.5 root 1672: opn = "srlv";
1.1.1.6 root 1673: break;
1674: case 1:
1675: /* rotrv is decoded as srlv on non-R2 CPUs */
1676: if (env->insn_flags & ISA_MIPS32R2) {
1.1.1.7 ! root 1677: int l1 = gen_new_label();
! 1678: int l2 = gen_new_label();
! 1679:
! 1680: tcg_gen_andi_tl(t0, t0, 0x1f);
! 1681: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
! 1682: {
! 1683: TCGv_i32 r_tmp1 = tcg_temp_new_i32();
! 1684: TCGv_i32 r_tmp2 = tcg_temp_new_i32();
! 1685:
! 1686: tcg_gen_trunc_tl_i32(r_tmp1, t0);
! 1687: tcg_gen_trunc_tl_i32(r_tmp2, t1);
! 1688: tcg_gen_rotr_i32(r_tmp1, r_tmp1, r_tmp2);
! 1689: tcg_temp_free_i32(r_tmp1);
! 1690: tcg_temp_free_i32(r_tmp2);
! 1691: tcg_gen_br(l2);
! 1692: }
! 1693: gen_set_label(l1);
! 1694: tcg_gen_mov_tl(t0, t1);
! 1695: gen_set_label(l2);
1.1.1.6 root 1696: opn = "rotrv";
1697: } else {
1.1.1.7 ! root 1698: tcg_gen_ext32u_tl(t1, t1);
! 1699: tcg_gen_andi_tl(t0, t0, 0x1f);
! 1700: tcg_gen_shr_tl(t0, t1, t0);
! 1701: tcg_gen_ext32s_tl(t0, t0);
1.1.1.6 root 1702: opn = "srlv";
1703: }
1704: break;
1705: default:
1706: MIPS_INVAL("invalid srlv flag");
1707: generate_exception(ctx, EXCP_RI);
1708: break;
1709: }
1.1.1.5 root 1710: break;
1.1.1.6 root 1711: #if defined(TARGET_MIPS64)
1.1.1.5 root 1712: case OPC_DSLLV:
1.1.1.7 ! root 1713: tcg_gen_andi_tl(t0, t0, 0x3f);
! 1714: tcg_gen_shl_tl(t0, t1, t0);
1.1.1.5 root 1715: opn = "dsllv";
1716: break;
1717: case OPC_DSRAV:
1.1.1.7 ! root 1718: tcg_gen_andi_tl(t0, t0, 0x3f);
! 1719: tcg_gen_sar_tl(t0, t1, t0);
1.1.1.5 root 1720: opn = "dsrav";
1721: break;
1722: case OPC_DSRLV:
1.1.1.6 root 1723: switch ((ctx->opcode >> 6) & 0x1f) {
1724: case 0:
1.1.1.7 ! root 1725: tcg_gen_andi_tl(t0, t0, 0x3f);
! 1726: tcg_gen_shr_tl(t0, t1, t0);
1.1.1.5 root 1727: opn = "dsrlv";
1.1.1.6 root 1728: break;
1729: case 1:
1730: /* drotrv is decoded as dsrlv on non-R2 CPUs */
1731: if (env->insn_flags & ISA_MIPS32R2) {
1.1.1.7 ! root 1732: int l1 = gen_new_label();
! 1733: int l2 = gen_new_label();
! 1734:
! 1735: tcg_gen_andi_tl(t0, t0, 0x3f);
! 1736: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
! 1737: {
! 1738: tcg_gen_rotr_tl(t0, t1, t0);
! 1739: tcg_gen_br(l2);
! 1740: }
! 1741: gen_set_label(l1);
! 1742: tcg_gen_mov_tl(t0, t1);
! 1743: gen_set_label(l2);
1.1.1.6 root 1744: opn = "drotrv";
1745: } else {
1.1.1.7 ! root 1746: tcg_gen_andi_tl(t0, t0, 0x3f);
! 1747: tcg_gen_shr_tl(t0, t1, t0);
1.1.1.6 root 1748: opn = "dsrlv";
1749: }
1750: break;
1751: default:
1752: MIPS_INVAL("invalid dsrlv flag");
1753: generate_exception(ctx, EXCP_RI);
1754: break;
1755: }
1.1 root 1756: break;
1.1.1.5 root 1757: #endif
1.1 root 1758: default:
1.1.1.6 root 1759: MIPS_INVAL(opn);
1.1 root 1760: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 1761: goto out;
1.1 root 1762: }
1.1.1.7 ! root 1763: gen_store_gpr(t0, rd);
1.1 root 1764: print:
1765: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1.1.1.7 ! root 1766: out:
! 1767: tcg_temp_free(t0);
! 1768: tcg_temp_free(t1);
1.1 root 1769: }
1770:
1771: /* Arithmetic on HI/LO registers */
1.1.1.5 root 1772: static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1.1 root 1773: {
1.1.1.6 root 1774: const char *opn = "hilo";
1.1.1.7 ! root 1775: TCGv t0 = tcg_temp_local_new();
1.1 root 1776:
1777: if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1.1.1.6 root 1778: /* Treat as NOP. */
1.1 root 1779: MIPS_DEBUG("NOP");
1.1.1.7 ! root 1780: goto out;
1.1 root 1781: }
1782: switch (opc) {
1783: case OPC_MFHI:
1.1.1.7 ! root 1784: tcg_gen_mov_tl(t0, cpu_HI[0]);
! 1785: gen_store_gpr(t0, reg);
1.1 root 1786: opn = "mfhi";
1787: break;
1788: case OPC_MFLO:
1.1.1.7 ! root 1789: tcg_gen_mov_tl(t0, cpu_LO[0]);
! 1790: gen_store_gpr(t0, reg);
1.1 root 1791: opn = "mflo";
1792: break;
1793: case OPC_MTHI:
1.1.1.7 ! root 1794: gen_load_gpr(t0, reg);
! 1795: tcg_gen_mov_tl(cpu_HI[0], t0);
1.1 root 1796: opn = "mthi";
1797: break;
1798: case OPC_MTLO:
1.1.1.7 ! root 1799: gen_load_gpr(t0, reg);
! 1800: tcg_gen_mov_tl(cpu_LO[0], t0);
1.1 root 1801: opn = "mtlo";
1802: break;
1803: default:
1.1.1.6 root 1804: MIPS_INVAL(opn);
1.1 root 1805: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 1806: goto out;
1.1 root 1807: }
1808: MIPS_DEBUG("%s %s", opn, regnames[reg]);
1.1.1.7 ! root 1809: out:
! 1810: tcg_temp_free(t0);
1.1 root 1811: }
1812:
1.1.1.5 root 1813: static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1.1 root 1814: int rs, int rt)
1815: {
1.1.1.6 root 1816: const char *opn = "mul/div";
1.1.1.7 ! root 1817: TCGv t0 = tcg_temp_local_new();
! 1818: TCGv t1 = tcg_temp_local_new();
1.1 root 1819:
1.1.1.7 ! root 1820: gen_load_gpr(t0, rs);
! 1821: gen_load_gpr(t1, rt);
1.1 root 1822: switch (opc) {
1823: case OPC_DIV:
1.1.1.7 ! root 1824: {
! 1825: int l1 = gen_new_label();
! 1826:
! 1827: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
! 1828: {
! 1829: int l2 = gen_new_label();
! 1830: TCGv_i32 r_tmp1 = tcg_temp_local_new_i32();
! 1831: TCGv_i32 r_tmp2 = tcg_temp_local_new_i32();
! 1832: TCGv_i32 r_tmp3 = tcg_temp_local_new_i32();
! 1833:
! 1834: tcg_gen_trunc_tl_i32(r_tmp1, t0);
! 1835: tcg_gen_trunc_tl_i32(r_tmp2, t1);
! 1836: tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp1, -1 << 31, l2);
! 1837: tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp2, -1, l2);
! 1838: tcg_gen_ext32s_tl(cpu_LO[0], t0);
! 1839: tcg_gen_movi_tl(cpu_HI[0], 0);
! 1840: tcg_gen_br(l1);
! 1841: gen_set_label(l2);
! 1842: tcg_gen_div_i32(r_tmp3, r_tmp1, r_tmp2);
! 1843: tcg_gen_rem_i32(r_tmp2, r_tmp1, r_tmp2);
! 1844: tcg_gen_ext_i32_tl(cpu_LO[0], r_tmp3);
! 1845: tcg_gen_ext_i32_tl(cpu_HI[0], r_tmp2);
! 1846: tcg_temp_free_i32(r_tmp1);
! 1847: tcg_temp_free_i32(r_tmp2);
! 1848: tcg_temp_free_i32(r_tmp3);
! 1849: }
! 1850: gen_set_label(l1);
! 1851: }
1.1 root 1852: opn = "div";
1853: break;
1854: case OPC_DIVU:
1.1.1.7 ! root 1855: {
! 1856: int l1 = gen_new_label();
! 1857:
! 1858: tcg_gen_ext32s_tl(t1, t1);
! 1859: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
! 1860: {
! 1861: TCGv_i32 r_tmp1 = tcg_temp_new_i32();
! 1862: TCGv_i32 r_tmp2 = tcg_temp_new_i32();
! 1863: TCGv_i32 r_tmp3 = tcg_temp_new_i32();
! 1864:
! 1865: tcg_gen_trunc_tl_i32(r_tmp1, t0);
! 1866: tcg_gen_trunc_tl_i32(r_tmp2, t1);
! 1867: tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2);
! 1868: tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2);
! 1869: tcg_gen_ext_i32_tl(cpu_LO[0], r_tmp3);
! 1870: tcg_gen_ext_i32_tl(cpu_HI[0], r_tmp1);
! 1871: tcg_temp_free_i32(r_tmp1);
! 1872: tcg_temp_free_i32(r_tmp2);
! 1873: tcg_temp_free_i32(r_tmp3);
! 1874: }
! 1875: gen_set_label(l1);
! 1876: }
1.1 root 1877: opn = "divu";
1878: break;
1879: case OPC_MULT:
1.1.1.7 ! root 1880: {
! 1881: TCGv_i64 r_tmp1 = tcg_temp_new_i64();
! 1882: TCGv_i64 r_tmp2 = tcg_temp_new_i64();
! 1883:
! 1884: tcg_gen_ext_tl_i64(r_tmp1, t0);
! 1885: tcg_gen_ext_tl_i64(r_tmp2, t1);
! 1886: tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
! 1887: tcg_temp_free_i64(r_tmp2);
! 1888: tcg_gen_trunc_i64_tl(t0, r_tmp1);
! 1889: tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
! 1890: tcg_gen_trunc_i64_tl(t1, r_tmp1);
! 1891: tcg_temp_free_i64(r_tmp1);
! 1892: tcg_gen_ext32s_tl(cpu_LO[0], t0);
! 1893: tcg_gen_ext32s_tl(cpu_HI[0], t1);
! 1894: }
1.1 root 1895: opn = "mult";
1896: break;
1897: case OPC_MULTU:
1.1.1.7 ! root 1898: {
! 1899: TCGv_i64 r_tmp1 = tcg_temp_new_i64();
! 1900: TCGv_i64 r_tmp2 = tcg_temp_new_i64();
! 1901:
! 1902: tcg_gen_ext32u_tl(t0, t0);
! 1903: tcg_gen_ext32u_tl(t1, t1);
! 1904: tcg_gen_extu_tl_i64(r_tmp1, t0);
! 1905: tcg_gen_extu_tl_i64(r_tmp2, t1);
! 1906: tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
! 1907: tcg_temp_free_i64(r_tmp2);
! 1908: tcg_gen_trunc_i64_tl(t0, r_tmp1);
! 1909: tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
! 1910: tcg_gen_trunc_i64_tl(t1, r_tmp1);
! 1911: tcg_temp_free_i64(r_tmp1);
! 1912: tcg_gen_ext32s_tl(cpu_LO[0], t0);
! 1913: tcg_gen_ext32s_tl(cpu_HI[0], t1);
! 1914: }
1.1 root 1915: opn = "multu";
1916: break;
1.1.1.6 root 1917: #if defined(TARGET_MIPS64)
1.1.1.5 root 1918: case OPC_DDIV:
1.1.1.7 ! root 1919: {
! 1920: int l1 = gen_new_label();
! 1921:
! 1922: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
! 1923: {
! 1924: int l2 = gen_new_label();
! 1925:
! 1926: tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
! 1927: tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
! 1928: tcg_gen_mov_tl(cpu_LO[0], t0);
! 1929: tcg_gen_movi_tl(cpu_HI[0], 0);
! 1930: tcg_gen_br(l1);
! 1931: gen_set_label(l2);
! 1932: tcg_gen_div_i64(cpu_LO[0], t0, t1);
! 1933: tcg_gen_rem_i64(cpu_HI[0], t0, t1);
! 1934: }
! 1935: gen_set_label(l1);
! 1936: }
1.1.1.5 root 1937: opn = "ddiv";
1938: break;
1939: case OPC_DDIVU:
1.1.1.7 ! root 1940: {
! 1941: int l1 = gen_new_label();
! 1942:
! 1943: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
! 1944: tcg_gen_divu_i64(cpu_LO[0], t0, t1);
! 1945: tcg_gen_remu_i64(cpu_HI[0], t0, t1);
! 1946: gen_set_label(l1);
! 1947: }
1.1.1.5 root 1948: opn = "ddivu";
1949: break;
1950: case OPC_DMULT:
1.1.1.7 ! root 1951: gen_helper_dmult(t0, t1);
1.1.1.5 root 1952: opn = "dmult";
1953: break;
1954: case OPC_DMULTU:
1.1.1.7 ! root 1955: gen_helper_dmultu(t0, t1);
1.1.1.5 root 1956: opn = "dmultu";
1957: break;
1958: #endif
1.1 root 1959: case OPC_MADD:
1.1.1.7 ! root 1960: {
! 1961: TCGv_i64 r_tmp1 = tcg_temp_new_i64();
! 1962: TCGv_i64 r_tmp2 = tcg_temp_new_i64();
! 1963:
! 1964: tcg_gen_ext_tl_i64(r_tmp1, t0);
! 1965: tcg_gen_ext_tl_i64(r_tmp2, t1);
! 1966: tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
! 1967: tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
! 1968: tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
! 1969: tcg_temp_free_i64(r_tmp2);
! 1970: tcg_gen_trunc_i64_tl(t0, r_tmp1);
! 1971: tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
! 1972: tcg_gen_trunc_i64_tl(t1, r_tmp1);
! 1973: tcg_temp_free_i64(r_tmp1);
! 1974: tcg_gen_ext32s_tl(cpu_LO[0], t0);
! 1975: tcg_gen_ext32s_tl(cpu_LO[1], t1);
! 1976: }
1.1 root 1977: opn = "madd";
1978: break;
1979: case OPC_MADDU:
1.1.1.7 ! root 1980: {
! 1981: TCGv_i64 r_tmp1 = tcg_temp_new_i64();
! 1982: TCGv_i64 r_tmp2 = tcg_temp_new_i64();
! 1983:
! 1984: tcg_gen_ext32u_tl(t0, t0);
! 1985: tcg_gen_ext32u_tl(t1, t1);
! 1986: tcg_gen_extu_tl_i64(r_tmp1, t0);
! 1987: tcg_gen_extu_tl_i64(r_tmp2, t1);
! 1988: tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
! 1989: tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
! 1990: tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
! 1991: tcg_temp_free_i64(r_tmp2);
! 1992: tcg_gen_trunc_i64_tl(t0, r_tmp1);
! 1993: tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
! 1994: tcg_gen_trunc_i64_tl(t1, r_tmp1);
! 1995: tcg_temp_free_i64(r_tmp1);
! 1996: tcg_gen_ext32s_tl(cpu_LO[0], t0);
! 1997: tcg_gen_ext32s_tl(cpu_HI[0], t1);
! 1998: }
1.1 root 1999: opn = "maddu";
2000: break;
2001: case OPC_MSUB:
1.1.1.7 ! root 2002: {
! 2003: TCGv_i64 r_tmp1 = tcg_temp_new_i64();
! 2004: TCGv_i64 r_tmp2 = tcg_temp_new_i64();
! 2005:
! 2006: tcg_gen_ext_tl_i64(r_tmp1, t0);
! 2007: tcg_gen_ext_tl_i64(r_tmp2, t1);
! 2008: tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
! 2009: tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
! 2010: tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
! 2011: tcg_temp_free_i64(r_tmp2);
! 2012: tcg_gen_trunc_i64_tl(t0, r_tmp1);
! 2013: tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
! 2014: tcg_gen_trunc_i64_tl(t1, r_tmp1);
! 2015: tcg_temp_free_i64(r_tmp1);
! 2016: tcg_gen_ext32s_tl(cpu_LO[0], t0);
! 2017: tcg_gen_ext32s_tl(cpu_HI[0], t1);
! 2018: }
1.1 root 2019: opn = "msub";
2020: break;
2021: case OPC_MSUBU:
1.1.1.7 ! root 2022: {
! 2023: TCGv_i64 r_tmp1 = tcg_temp_new_i64();
! 2024: TCGv_i64 r_tmp2 = tcg_temp_new_i64();
! 2025:
! 2026: tcg_gen_ext32u_tl(t0, t0);
! 2027: tcg_gen_ext32u_tl(t1, t1);
! 2028: tcg_gen_extu_tl_i64(r_tmp1, t0);
! 2029: tcg_gen_extu_tl_i64(r_tmp2, t1);
! 2030: tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
! 2031: tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
! 2032: tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
! 2033: tcg_temp_free_i64(r_tmp2);
! 2034: tcg_gen_trunc_i64_tl(t0, r_tmp1);
! 2035: tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
! 2036: tcg_gen_trunc_i64_tl(t1, r_tmp1);
! 2037: tcg_temp_free_i64(r_tmp1);
! 2038: tcg_gen_ext32s_tl(cpu_LO[0], t0);
! 2039: tcg_gen_ext32s_tl(cpu_HI[0], t1);
! 2040: }
1.1 root 2041: opn = "msubu";
2042: break;
2043: default:
1.1.1.6 root 2044: MIPS_INVAL(opn);
1.1 root 2045: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 2046: goto out;
1.1 root 2047: }
2048: MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1.1.1.7 ! root 2049: out:
! 2050: tcg_temp_free(t0);
! 2051: tcg_temp_free(t1);
1.1 root 2052: }
2053:
1.1.1.6 root 2054: static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2055: int rd, int rs, int rt)
2056: {
2057: const char *opn = "mul vr54xx";
1.1.1.7 ! root 2058: TCGv t0 = tcg_temp_local_new();
! 2059: TCGv t1 = tcg_temp_local_new();
1.1.1.6 root 2060:
1.1.1.7 ! root 2061: gen_load_gpr(t0, rs);
! 2062: gen_load_gpr(t1, rt);
1.1.1.6 root 2063:
2064: switch (opc) {
2065: case OPC_VR54XX_MULS:
1.1.1.7 ! root 2066: gen_helper_muls(t0, t0, t1);
1.1.1.6 root 2067: opn = "muls";
1.1.1.7 ! root 2068: break;
1.1.1.6 root 2069: case OPC_VR54XX_MULSU:
1.1.1.7 ! root 2070: gen_helper_mulsu(t0, t0, t1);
1.1.1.6 root 2071: opn = "mulsu";
1.1.1.7 ! root 2072: break;
1.1.1.6 root 2073: case OPC_VR54XX_MACC:
1.1.1.7 ! root 2074: gen_helper_macc(t0, t0, t1);
1.1.1.6 root 2075: opn = "macc";
1.1.1.7 ! root 2076: break;
1.1.1.6 root 2077: case OPC_VR54XX_MACCU:
1.1.1.7 ! root 2078: gen_helper_maccu(t0, t0, t1);
1.1.1.6 root 2079: opn = "maccu";
1.1.1.7 ! root 2080: break;
1.1.1.6 root 2081: case OPC_VR54XX_MSAC:
1.1.1.7 ! root 2082: gen_helper_msac(t0, t0, t1);
1.1.1.6 root 2083: opn = "msac";
1.1.1.7 ! root 2084: break;
1.1.1.6 root 2085: case OPC_VR54XX_MSACU:
1.1.1.7 ! root 2086: gen_helper_msacu(t0, t0, t1);
1.1.1.6 root 2087: opn = "msacu";
1.1.1.7 ! root 2088: break;
1.1.1.6 root 2089: case OPC_VR54XX_MULHI:
1.1.1.7 ! root 2090: gen_helper_mulhi(t0, t0, t1);
1.1.1.6 root 2091: opn = "mulhi";
1.1.1.7 ! root 2092: break;
1.1.1.6 root 2093: case OPC_VR54XX_MULHIU:
1.1.1.7 ! root 2094: gen_helper_mulhiu(t0, t0, t1);
1.1.1.6 root 2095: opn = "mulhiu";
1.1.1.7 ! root 2096: break;
1.1.1.6 root 2097: case OPC_VR54XX_MULSHI:
1.1.1.7 ! root 2098: gen_helper_mulshi(t0, t0, t1);
1.1.1.6 root 2099: opn = "mulshi";
1.1.1.7 ! root 2100: break;
1.1.1.6 root 2101: case OPC_VR54XX_MULSHIU:
1.1.1.7 ! root 2102: gen_helper_mulshiu(t0, t0, t1);
1.1.1.6 root 2103: opn = "mulshiu";
1.1.1.7 ! root 2104: break;
1.1.1.6 root 2105: case OPC_VR54XX_MACCHI:
1.1.1.7 ! root 2106: gen_helper_macchi(t0, t0, t1);
1.1.1.6 root 2107: opn = "macchi";
1.1.1.7 ! root 2108: break;
1.1.1.6 root 2109: case OPC_VR54XX_MACCHIU:
1.1.1.7 ! root 2110: gen_helper_macchiu(t0, t0, t1);
1.1.1.6 root 2111: opn = "macchiu";
1.1.1.7 ! root 2112: break;
1.1.1.6 root 2113: case OPC_VR54XX_MSACHI:
1.1.1.7 ! root 2114: gen_helper_msachi(t0, t0, t1);
1.1.1.6 root 2115: opn = "msachi";
1.1.1.7 ! root 2116: break;
1.1.1.6 root 2117: case OPC_VR54XX_MSACHIU:
1.1.1.7 ! root 2118: gen_helper_msachiu(t0, t0, t1);
1.1.1.6 root 2119: opn = "msachiu";
1.1.1.7 ! root 2120: break;
1.1.1.6 root 2121: default:
2122: MIPS_INVAL("mul vr54xx");
2123: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 2124: goto out;
1.1.1.6 root 2125: }
1.1.1.7 ! root 2126: gen_store_gpr(t0, rd);
1.1.1.6 root 2127: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1.1.1.7 ! root 2128:
! 2129: out:
! 2130: tcg_temp_free(t0);
! 2131: tcg_temp_free(t1);
1.1.1.6 root 2132: }
2133:
1.1.1.5 root 2134: static void gen_cl (DisasContext *ctx, uint32_t opc,
1.1 root 2135: int rd, int rs)
2136: {
1.1.1.6 root 2137: const char *opn = "CLx";
1.1.1.7 ! root 2138: TCGv t0 = tcg_temp_local_new();
! 2139:
1.1 root 2140: if (rd == 0) {
1.1.1.6 root 2141: /* Treat as NOP. */
1.1 root 2142: MIPS_DEBUG("NOP");
1.1.1.7 ! root 2143: goto out;
1.1 root 2144: }
1.1.1.7 ! root 2145: gen_load_gpr(t0, rs);
1.1 root 2146: switch (opc) {
2147: case OPC_CLO:
1.1.1.7 ! root 2148: gen_helper_clo(t0, t0);
1.1 root 2149: opn = "clo";
2150: break;
2151: case OPC_CLZ:
1.1.1.7 ! root 2152: gen_helper_clz(t0, t0);
1.1 root 2153: opn = "clz";
2154: break;
1.1.1.6 root 2155: #if defined(TARGET_MIPS64)
1.1.1.5 root 2156: case OPC_DCLO:
1.1.1.7 ! root 2157: gen_helper_dclo(t0, t0);
1.1.1.5 root 2158: opn = "dclo";
2159: break;
2160: case OPC_DCLZ:
1.1.1.7 ! root 2161: gen_helper_dclz(t0, t0);
1.1.1.5 root 2162: opn = "dclz";
2163: break;
2164: #endif
1.1 root 2165: default:
1.1.1.6 root 2166: MIPS_INVAL(opn);
1.1 root 2167: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 2168: goto out;
1.1 root 2169: }
1.1.1.7 ! root 2170: gen_store_gpr(t0, rd);
1.1 root 2171: MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1.1.1.7 ! root 2172:
! 2173: out:
! 2174: tcg_temp_free(t0);
1.1 root 2175: }
2176:
2177: /* Traps */
1.1.1.5 root 2178: static void gen_trap (DisasContext *ctx, uint32_t opc,
1.1 root 2179: int rs, int rt, int16_t imm)
2180: {
2181: int cond;
1.1.1.7 ! root 2182: TCGv t0 = tcg_temp_local_new();
! 2183: TCGv t1 = tcg_temp_local_new();
1.1 root 2184:
2185: cond = 0;
2186: /* Load needed operands */
2187: switch (opc) {
2188: case OPC_TEQ:
2189: case OPC_TGE:
2190: case OPC_TGEU:
2191: case OPC_TLT:
2192: case OPC_TLTU:
2193: case OPC_TNE:
2194: /* Compare two registers */
2195: if (rs != rt) {
1.1.1.7 ! root 2196: gen_load_gpr(t0, rs);
! 2197: gen_load_gpr(t1, rt);
1.1 root 2198: cond = 1;
2199: }
1.1.1.5 root 2200: break;
1.1 root 2201: case OPC_TEQI:
2202: case OPC_TGEI:
2203: case OPC_TGEIU:
2204: case OPC_TLTI:
2205: case OPC_TLTIU:
2206: case OPC_TNEI:
2207: /* Compare register to immediate */
2208: if (rs != 0 || imm != 0) {
1.1.1.7 ! root 2209: gen_load_gpr(t0, rs);
! 2210: tcg_gen_movi_tl(t1, (int32_t)imm);
1.1 root 2211: cond = 1;
2212: }
2213: break;
2214: }
2215: if (cond == 0) {
2216: switch (opc) {
2217: case OPC_TEQ: /* rs == rs */
2218: case OPC_TEQI: /* r0 == 0 */
2219: case OPC_TGE: /* rs >= rs */
2220: case OPC_TGEI: /* r0 >= 0 */
2221: case OPC_TGEU: /* rs >= rs unsigned */
2222: case OPC_TGEIU: /* r0 >= 0 unsigned */
2223: /* Always trap */
1.1.1.7 ! root 2224: tcg_gen_movi_tl(t0, 1);
1.1 root 2225: break;
2226: case OPC_TLT: /* rs < rs */
2227: case OPC_TLTI: /* r0 < 0 */
2228: case OPC_TLTU: /* rs < rs unsigned */
2229: case OPC_TLTIU: /* r0 < 0 unsigned */
2230: case OPC_TNE: /* rs != rs */
2231: case OPC_TNEI: /* r0 != 0 */
1.1.1.6 root 2232: /* Never trap: treat as NOP. */
1.1.1.7 ! root 2233: goto out;
1.1 root 2234: default:
1.1.1.6 root 2235: MIPS_INVAL("trap");
1.1 root 2236: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 2237: goto out;
1.1 root 2238: }
2239: } else {
2240: switch (opc) {
2241: case OPC_TEQ:
2242: case OPC_TEQI:
1.1.1.7 ! root 2243: gen_op_eq(t0, t1);
1.1 root 2244: break;
2245: case OPC_TGE:
2246: case OPC_TGEI:
1.1.1.7 ! root 2247: gen_op_ge(t0, t1);
1.1 root 2248: break;
2249: case OPC_TGEU:
2250: case OPC_TGEIU:
1.1.1.7 ! root 2251: gen_op_geu(t0, t1);
1.1 root 2252: break;
2253: case OPC_TLT:
2254: case OPC_TLTI:
1.1.1.7 ! root 2255: gen_op_lt(t0, t1);
1.1 root 2256: break;
2257: case OPC_TLTU:
2258: case OPC_TLTIU:
1.1.1.7 ! root 2259: gen_op_ltu(t0, t1);
1.1 root 2260: break;
2261: case OPC_TNE:
2262: case OPC_TNEI:
1.1.1.7 ! root 2263: gen_op_ne(t0, t1);
1.1 root 2264: break;
2265: default:
1.1.1.6 root 2266: MIPS_INVAL("trap");
1.1 root 2267: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 2268: goto out;
1.1 root 2269: }
2270: }
2271: save_cpu_state(ctx, 1);
1.1.1.7 ! root 2272: {
! 2273: int l1 = gen_new_label();
! 2274:
! 2275: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
! 2276: gen_helper_0i(raise_exception, EXCP_TRAP);
! 2277: gen_set_label(l1);
! 2278: }
1.1 root 2279: ctx->bstate = BS_STOP;
1.1.1.7 ! root 2280: out:
! 2281: tcg_temp_free(t0);
! 2282: tcg_temp_free(t1);
1.1 root 2283: }
2284:
1.1.1.7 ! root 2285: static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1.1.1.2 root 2286: {
2287: TranslationBlock *tb;
2288: tb = ctx->tb;
2289: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1.1.1.7 ! root 2290: tcg_gen_goto_tb(n);
1.1.1.6 root 2291: gen_save_pc(dest);
1.1.1.7 ! root 2292: tcg_gen_exit_tb((long)tb + n);
1.1.1.2 root 2293: } else {
1.1.1.6 root 2294: gen_save_pc(dest);
1.1.1.7 ! root 2295: tcg_gen_exit_tb(0);
1.1.1.2 root 2296: }
2297: }
2298:
1.1 root 2299: /* Branches (before delay slot) */
1.1.1.5 root 2300: static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1.1 root 2301: int rs, int rt, int32_t offset)
2302: {
1.1.1.7 ! root 2303: target_ulong btgt = -1;
1.1.1.6 root 2304: int blink = 0;
1.1.1.7 ! root 2305: int bcond_compute = 0;
! 2306: TCGv t0 = tcg_temp_local_new();
! 2307: TCGv t1 = tcg_temp_local_new();
1.1 root 2308:
1.1.1.6 root 2309: if (ctx->hflags & MIPS_HFLAG_BMASK) {
2310: #ifdef MIPS_DEBUG_DISAS
1.1.1.7 ! root 2311: LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
1.1.1.6 root 2312: #endif
2313: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 2314: goto out;
1.1.1.6 root 2315: }
2316:
2317: /* Load needed operands */
2318: switch (opc) {
2319: case OPC_BEQ:
2320: case OPC_BEQL:
2321: case OPC_BNE:
2322: case OPC_BNEL:
1.1 root 2323: /* Compare two registers */
2324: if (rs != rt) {
1.1.1.7 ! root 2325: gen_load_gpr(t0, rs);
! 2326: gen_load_gpr(t1, rt);
! 2327: bcond_compute = 1;
1.1 root 2328: }
1.1.1.7 ! root 2329: btgt = ctx->pc + 4 + offset;
1.1 root 2330: break;
2331: case OPC_BGEZ:
2332: case OPC_BGEZAL:
2333: case OPC_BGEZALL:
2334: case OPC_BGEZL:
2335: case OPC_BGTZ:
2336: case OPC_BGTZL:
2337: case OPC_BLEZ:
2338: case OPC_BLEZL:
2339: case OPC_BLTZ:
2340: case OPC_BLTZAL:
2341: case OPC_BLTZALL:
2342: case OPC_BLTZL:
2343: /* Compare to zero */
2344: if (rs != 0) {
1.1.1.7 ! root 2345: gen_load_gpr(t0, rs);
! 2346: bcond_compute = 1;
1.1 root 2347: }
1.1.1.7 ! root 2348: btgt = ctx->pc + 4 + offset;
1.1 root 2349: break;
2350: case OPC_J:
2351: case OPC_JAL:
2352: /* Jump to immediate */
1.1.1.7 ! root 2353: btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
1.1 root 2354: break;
2355: case OPC_JR:
2356: case OPC_JALR:
2357: /* Jump to register */
1.1.1.5 root 2358: if (offset != 0 && offset != 16) {
2359: /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1.1.1.6 root 2360: others are reserved. */
2361: MIPS_INVAL("jump hint");
1.1 root 2362: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 2363: goto out;
1.1 root 2364: }
1.1.1.7 ! root 2365: gen_load_gpr(btarget, rs);
1.1 root 2366: break;
2367: default:
2368: MIPS_INVAL("branch/jump");
2369: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 2370: goto out;
1.1 root 2371: }
1.1.1.7 ! root 2372: if (bcond_compute == 0) {
1.1 root 2373: /* No condition to be computed */
2374: switch (opc) {
2375: case OPC_BEQ: /* rx == rx */
2376: case OPC_BEQL: /* rx == rx likely */
2377: case OPC_BGEZ: /* 0 >= 0 */
2378: case OPC_BGEZL: /* 0 >= 0 likely */
2379: case OPC_BLEZ: /* 0 <= 0 */
2380: case OPC_BLEZL: /* 0 <= 0 likely */
2381: /* Always take */
1.1.1.2 root 2382: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 2383: MIPS_DEBUG("balways");
2384: break;
2385: case OPC_BGEZAL: /* 0 >= 0 */
2386: case OPC_BGEZALL: /* 0 >= 0 likely */
2387: /* Always take and link */
2388: blink = 31;
1.1.1.2 root 2389: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 2390: MIPS_DEBUG("balways and link");
2391: break;
2392: case OPC_BNE: /* rx != rx */
2393: case OPC_BGTZ: /* 0 > 0 */
2394: case OPC_BLTZ: /* 0 < 0 */
1.1.1.6 root 2395: /* Treat as NOP. */
1.1 root 2396: MIPS_DEBUG("bnever (NOP)");
1.1.1.7 ! root 2397: goto out;
1.1.1.2 root 2398: case OPC_BLTZAL: /* 0 < 0 */
1.1.1.7 ! root 2399: tcg_gen_movi_tl(t0, ctx->pc + 8);
! 2400: gen_store_gpr(t0, 31);
1.1.1.6 root 2401: MIPS_DEBUG("bnever and link");
1.1.1.7 ! root 2402: goto out;
1.1.1.2 root 2403: case OPC_BLTZALL: /* 0 < 0 likely */
1.1.1.7 ! root 2404: tcg_gen_movi_tl(t0, ctx->pc + 8);
! 2405: gen_store_gpr(t0, 31);
1.1.1.6 root 2406: /* Skip the instruction in the delay slot */
2407: MIPS_DEBUG("bnever, link and skip");
2408: ctx->pc += 4;
1.1.1.7 ! root 2409: goto out;
1.1 root 2410: case OPC_BNEL: /* rx != rx likely */
2411: case OPC_BGTZL: /* 0 > 0 likely */
2412: case OPC_BLTZL: /* 0 < 0 likely */
2413: /* Skip the instruction in the delay slot */
2414: MIPS_DEBUG("bnever and skip");
1.1.1.6 root 2415: ctx->pc += 4;
1.1.1.7 ! root 2416: goto out;
1.1 root 2417: case OPC_J:
1.1.1.2 root 2418: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.7 ! root 2419: MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
1.1 root 2420: break;
2421: case OPC_JAL:
2422: blink = 31;
1.1.1.2 root 2423: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.7 ! root 2424: MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
1.1 root 2425: break;
2426: case OPC_JR:
1.1.1.2 root 2427: ctx->hflags |= MIPS_HFLAG_BR;
1.1 root 2428: MIPS_DEBUG("jr %s", regnames[rs]);
2429: break;
2430: case OPC_JALR:
2431: blink = rt;
1.1.1.2 root 2432: ctx->hflags |= MIPS_HFLAG_BR;
1.1 root 2433: MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2434: break;
2435: default:
2436: MIPS_INVAL("branch/jump");
2437: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 2438: goto out;
1.1 root 2439: }
2440: } else {
2441: switch (opc) {
2442: case OPC_BEQ:
1.1.1.7 ! root 2443: gen_op_eq(t0, t1);
1.1.1.6 root 2444: MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
1.1.1.7 ! root 2445: regnames[rs], regnames[rt], btgt);
1.1 root 2446: goto not_likely;
2447: case OPC_BEQL:
1.1.1.7 ! root 2448: gen_op_eq(t0, t1);
1.1.1.6 root 2449: MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
1.1.1.7 ! root 2450: regnames[rs], regnames[rt], btgt);
1.1 root 2451: goto likely;
2452: case OPC_BNE:
1.1.1.7 ! root 2453: gen_op_ne(t0, t1);
1.1.1.6 root 2454: MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
1.1.1.7 ! root 2455: regnames[rs], regnames[rt], btgt);
1.1 root 2456: goto not_likely;
2457: case OPC_BNEL:
1.1.1.7 ! root 2458: gen_op_ne(t0, t1);
1.1.1.6 root 2459: MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
1.1.1.7 ! root 2460: regnames[rs], regnames[rt], btgt);
1.1 root 2461: goto likely;
2462: case OPC_BGEZ:
1.1.1.7 ! root 2463: gen_op_gez(t0);
! 2464: MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2465: goto not_likely;
2466: case OPC_BGEZL:
1.1.1.7 ! root 2467: gen_op_gez(t0);
! 2468: MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2469: goto likely;
2470: case OPC_BGEZAL:
1.1.1.7 ! root 2471: gen_op_gez(t0);
! 2472: MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2473: blink = 31;
2474: goto not_likely;
2475: case OPC_BGEZALL:
1.1.1.7 ! root 2476: gen_op_gez(t0);
1.1 root 2477: blink = 31;
1.1.1.7 ! root 2478: MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2479: goto likely;
2480: case OPC_BGTZ:
1.1.1.7 ! root 2481: gen_op_gtz(t0);
! 2482: MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2483: goto not_likely;
2484: case OPC_BGTZL:
1.1.1.7 ! root 2485: gen_op_gtz(t0);
! 2486: MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2487: goto likely;
2488: case OPC_BLEZ:
1.1.1.7 ! root 2489: gen_op_lez(t0);
! 2490: MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2491: goto not_likely;
2492: case OPC_BLEZL:
1.1.1.7 ! root 2493: gen_op_lez(t0);
! 2494: MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2495: goto likely;
2496: case OPC_BLTZ:
1.1.1.7 ! root 2497: gen_op_ltz(t0);
! 2498: MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2499: goto not_likely;
2500: case OPC_BLTZL:
1.1.1.7 ! root 2501: gen_op_ltz(t0);
! 2502: MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2503: goto likely;
2504: case OPC_BLTZAL:
1.1.1.7 ! root 2505: gen_op_ltz(t0);
1.1 root 2506: blink = 31;
1.1.1.7 ! root 2507: MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2508: not_likely:
1.1.1.2 root 2509: ctx->hflags |= MIPS_HFLAG_BC;
1.1.1.7 ! root 2510: tcg_gen_trunc_tl_i32(bcond, t0);
1.1 root 2511: break;
2512: case OPC_BLTZALL:
1.1.1.7 ! root 2513: gen_op_ltz(t0);
1.1 root 2514: blink = 31;
1.1.1.7 ! root 2515: MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
1.1 root 2516: likely:
1.1.1.2 root 2517: ctx->hflags |= MIPS_HFLAG_BL;
1.1.1.7 ! root 2518: tcg_gen_trunc_tl_i32(bcond, t0);
1.1 root 2519: break;
1.1.1.6 root 2520: default:
2521: MIPS_INVAL("conditional branch/jump");
2522: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 2523: goto out;
1.1 root 2524: }
2525: }
1.1.1.6 root 2526: MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
1.1.1.7 ! root 2527: blink, ctx->hflags, btgt);
1.1.1.6 root 2528:
1.1.1.7 ! root 2529: ctx->btarget = btgt;
1.1 root 2530: if (blink > 0) {
1.1.1.7 ! root 2531: tcg_gen_movi_tl(t0, ctx->pc + 8);
! 2532: gen_store_gpr(t0, blink);
1.1 root 2533: }
1.1.1.7 ! root 2534:
! 2535: out:
! 2536: tcg_temp_free(t0);
! 2537: tcg_temp_free(t1);
1.1 root 2538: }
2539:
1.1.1.5 root 2540: /* special3 bitfield operations */
2541: static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1.1.1.7 ! root 2542: int rs, int lsb, int msb)
1.1 root 2543: {
1.1.1.7 ! root 2544: TCGv t0 = tcg_temp_new();
! 2545: TCGv t1 = tcg_temp_new();
! 2546: target_ulong mask;
! 2547:
! 2548: gen_load_gpr(t1, rs);
1.1.1.5 root 2549: switch (opc) {
2550: case OPC_EXT:
2551: if (lsb + msb > 31)
2552: goto fail;
1.1.1.7 ! root 2553: tcg_gen_shri_tl(t0, t1, lsb);
! 2554: if (msb != 31) {
! 2555: tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
! 2556: } else {
! 2557: tcg_gen_ext32s_tl(t0, t0);
! 2558: }
1.1.1.5 root 2559: break;
1.1.1.6 root 2560: #if defined(TARGET_MIPS64)
1.1.1.5 root 2561: case OPC_DEXTM:
1.1.1.7 ! root 2562: tcg_gen_shri_tl(t0, t1, lsb);
! 2563: if (msb != 31) {
! 2564: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
! 2565: }
1.1.1.5 root 2566: break;
2567: case OPC_DEXTU:
1.1.1.7 ! root 2568: tcg_gen_shri_tl(t0, t1, lsb + 32);
! 2569: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
1.1.1.5 root 2570: break;
2571: case OPC_DEXT:
1.1.1.7 ! root 2572: tcg_gen_shri_tl(t0, t1, lsb);
! 2573: tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
1.1.1.5 root 2574: break;
1.1.1.6 root 2575: #endif
1.1.1.5 root 2576: case OPC_INS:
2577: if (lsb > msb)
2578: goto fail;
1.1.1.7 ! root 2579: mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
! 2580: gen_load_gpr(t0, rt);
! 2581: tcg_gen_andi_tl(t0, t0, ~mask);
! 2582: tcg_gen_shli_tl(t1, t1, lsb);
! 2583: tcg_gen_andi_tl(t1, t1, mask);
! 2584: tcg_gen_or_tl(t0, t0, t1);
! 2585: tcg_gen_ext32s_tl(t0, t0);
1.1.1.5 root 2586: break;
1.1.1.6 root 2587: #if defined(TARGET_MIPS64)
1.1.1.5 root 2588: case OPC_DINSM:
2589: if (lsb > msb)
2590: goto fail;
1.1.1.7 ! root 2591: mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
! 2592: gen_load_gpr(t0, rt);
! 2593: tcg_gen_andi_tl(t0, t0, ~mask);
! 2594: tcg_gen_shli_tl(t1, t1, lsb);
! 2595: tcg_gen_andi_tl(t1, t1, mask);
! 2596: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 2597: break;
2598: case OPC_DINSU:
2599: if (lsb > msb)
2600: goto fail;
1.1.1.7 ! root 2601: mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
! 2602: gen_load_gpr(t0, rt);
! 2603: tcg_gen_andi_tl(t0, t0, ~mask);
! 2604: tcg_gen_shli_tl(t1, t1, lsb + 32);
! 2605: tcg_gen_andi_tl(t1, t1, mask);
! 2606: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 2607: break;
2608: case OPC_DINS:
2609: if (lsb > msb)
2610: goto fail;
1.1.1.7 ! root 2611: gen_load_gpr(t0, rt);
! 2612: mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
! 2613: gen_load_gpr(t0, rt);
! 2614: tcg_gen_andi_tl(t0, t0, ~mask);
! 2615: tcg_gen_shli_tl(t1, t1, lsb);
! 2616: tcg_gen_andi_tl(t1, t1, mask);
! 2617: tcg_gen_or_tl(t0, t0, t1);
1.1.1.5 root 2618: break;
1.1.1.6 root 2619: #endif
1.1.1.5 root 2620: default:
2621: fail:
2622: MIPS_INVAL("bitops");
2623: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 2624: tcg_temp_free(t0);
! 2625: tcg_temp_free(t1);
1.1 root 2626: return;
2627: }
1.1.1.7 ! root 2628: gen_store_gpr(t0, rt);
! 2629: tcg_temp_free(t0);
! 2630: tcg_temp_free(t1);
! 2631: }
! 2632:
! 2633: static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
! 2634: {
! 2635: TCGv t0 = tcg_temp_new();
! 2636: TCGv t1 = tcg_temp_new();
! 2637:
! 2638: gen_load_gpr(t1, rt);
! 2639: switch (op2) {
! 2640: case OPC_WSBH:
! 2641: tcg_gen_shri_tl(t0, t1, 8);
! 2642: tcg_gen_andi_tl(t0, t0, 0x00FF00FF);
! 2643: tcg_gen_shli_tl(t1, t1, 8);
! 2644: tcg_gen_andi_tl(t1, t1, ~0x00FF00FF);
! 2645: tcg_gen_or_tl(t0, t0, t1);
! 2646: tcg_gen_ext32s_tl(t0, t0);
! 2647: break;
! 2648: case OPC_SEB:
! 2649: tcg_gen_ext8s_tl(t0, t1);
! 2650: break;
! 2651: case OPC_SEH:
! 2652: tcg_gen_ext16s_tl(t0, t1);
! 2653: break;
! 2654: #if defined(TARGET_MIPS64)
! 2655: case OPC_DSBH:
! 2656: gen_load_gpr(t1, rt);
! 2657: tcg_gen_shri_tl(t0, t1, 8);
! 2658: tcg_gen_andi_tl(t0, t0, 0x00FF00FF00FF00FFULL);
! 2659: tcg_gen_shli_tl(t1, t1, 8);
! 2660: tcg_gen_andi_tl(t1, t1, ~0x00FF00FF00FF00FFULL);
! 2661: tcg_gen_or_tl(t0, t0, t1);
! 2662: break;
! 2663: case OPC_DSHD:
! 2664: gen_load_gpr(t1, rt);
! 2665: tcg_gen_shri_tl(t0, t1, 16);
! 2666: tcg_gen_andi_tl(t0, t0, 0x0000FFFF0000FFFFULL);
! 2667: tcg_gen_shli_tl(t1, t1, 16);
! 2668: tcg_gen_andi_tl(t1, t1, ~0x0000FFFF0000FFFFULL);
! 2669: tcg_gen_or_tl(t1, t0, t1);
! 2670: tcg_gen_shri_tl(t0, t1, 32);
! 2671: tcg_gen_shli_tl(t1, t1, 32);
! 2672: tcg_gen_or_tl(t0, t0, t1);
! 2673: break;
! 2674: #endif
! 2675: default:
! 2676: MIPS_INVAL("bsfhl");
! 2677: generate_exception(ctx, EXCP_RI);
! 2678: tcg_temp_free(t0);
! 2679: tcg_temp_free(t1);
! 2680: return;
! 2681: }
! 2682: gen_store_gpr(t0, rd);
! 2683: tcg_temp_free(t0);
! 2684: tcg_temp_free(t1);
1.1.1.5 root 2685: }
1.1.1.4 root 2686:
1.1.1.7 ! root 2687: #ifndef CONFIG_USER_ONLY
1.1.1.5 root 2688: /* CP0 (MMU and control) */
1.1.1.7 ! root 2689: static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
! 2690: {
! 2691: TCGv_i32 r_tmp = tcg_temp_new_i32();
! 2692:
! 2693: tcg_gen_ld_i32(r_tmp, cpu_env, off);
! 2694: tcg_gen_ext_i32_tl(t, r_tmp);
! 2695: tcg_temp_free_i32(r_tmp);
! 2696: }
! 2697:
! 2698: static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
! 2699: {
! 2700: tcg_gen_ld_tl(t, cpu_env, off);
! 2701: tcg_gen_ext32s_tl(t, t);
! 2702: }
! 2703:
! 2704: static inline void gen_mtc0_store32 (TCGv t, target_ulong off)
! 2705: {
! 2706: TCGv_i32 r_tmp = tcg_temp_new_i32();
! 2707:
! 2708: tcg_gen_trunc_tl_i32(r_tmp, t);
! 2709: tcg_gen_st_i32(r_tmp, cpu_env, off);
! 2710: tcg_temp_free_i32(r_tmp);
! 2711: }
! 2712:
! 2713: static inline void gen_mtc0_store64 (TCGv t, target_ulong off)
! 2714: {
! 2715: tcg_gen_ext32s_tl(t, t);
! 2716: tcg_gen_st_tl(t, cpu_env, off);
! 2717: }
! 2718:
! 2719: static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
1.1.1.5 root 2720: {
2721: const char *rn = "invalid";
2722:
1.1.1.6 root 2723: if (sel != 0)
2724: check_insn(env, ctx, ISA_MIPS32);
2725:
1.1.1.5 root 2726: switch (reg) {
2727: case 0:
2728: switch (sel) {
2729: case 0:
1.1.1.7 ! root 2730: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
1.1.1.5 root 2731: rn = "Index";
2732: break;
2733: case 1:
1.1.1.6 root 2734: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2735: gen_helper_mfc0_mvpcontrol(t0);
1.1.1.5 root 2736: rn = "MVPControl";
1.1.1.6 root 2737: break;
1.1.1.5 root 2738: case 2:
1.1.1.6 root 2739: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2740: gen_helper_mfc0_mvpconf0(t0);
1.1.1.5 root 2741: rn = "MVPConf0";
1.1.1.6 root 2742: break;
1.1.1.5 root 2743: case 3:
1.1.1.6 root 2744: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2745: gen_helper_mfc0_mvpconf1(t0);
1.1.1.5 root 2746: rn = "MVPConf1";
1.1.1.6 root 2747: break;
1.1.1.5 root 2748: default:
2749: goto die;
1.1 root 2750: }
2751: break;
1.1.1.5 root 2752: case 1:
2753: switch (sel) {
2754: case 0:
1.1.1.7 ! root 2755: gen_helper_mfc0_random(t0);
1.1.1.5 root 2756: rn = "Random";
1.1.1.6 root 2757: break;
1.1.1.5 root 2758: case 1:
1.1.1.6 root 2759: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2760: gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
1.1.1.5 root 2761: rn = "VPEControl";
1.1.1.6 root 2762: break;
1.1.1.5 root 2763: case 2:
1.1.1.6 root 2764: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2765: gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
1.1.1.5 root 2766: rn = "VPEConf0";
1.1.1.6 root 2767: break;
1.1.1.5 root 2768: case 3:
1.1.1.6 root 2769: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2770: gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
1.1.1.5 root 2771: rn = "VPEConf1";
1.1.1.6 root 2772: break;
1.1.1.5 root 2773: case 4:
1.1.1.6 root 2774: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2775: gen_mfc0_load64(t0, offsetof(CPUState, CP0_YQMask));
1.1.1.5 root 2776: rn = "YQMask";
1.1.1.6 root 2777: break;
1.1.1.5 root 2778: case 5:
1.1.1.6 root 2779: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2780: gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 2781: rn = "VPESchedule";
1.1.1.6 root 2782: break;
1.1.1.5 root 2783: case 6:
1.1.1.6 root 2784: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2785: gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 2786: rn = "VPEScheFBack";
1.1.1.6 root 2787: break;
1.1.1.5 root 2788: case 7:
1.1.1.6 root 2789: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2790: gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
1.1.1.5 root 2791: rn = "VPEOpt";
1.1.1.6 root 2792: break;
1.1.1.5 root 2793: default:
2794: goto die;
2795: }
1.1 root 2796: break;
1.1.1.5 root 2797: case 2:
2798: switch (sel) {
2799: case 0:
1.1.1.7 ! root 2800: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
! 2801: tcg_gen_ext32s_tl(t0, t0);
1.1.1.6 root 2802: rn = "EntryLo0";
2803: break;
2804: case 1:
2805: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2806: gen_helper_mfc0_tcstatus(t0);
1.1.1.6 root 2807: rn = "TCStatus";
2808: break;
2809: case 2:
2810: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2811: gen_helper_mfc0_tcbind(t0);
1.1.1.6 root 2812: rn = "TCBind";
2813: break;
1.1.1.5 root 2814: case 3:
1.1.1.6 root 2815: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2816: gen_helper_mfc0_tcrestart(t0);
1.1.1.6 root 2817: rn = "TCRestart";
2818: break;
1.1.1.5 root 2819: case 4:
1.1.1.6 root 2820: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2821: gen_helper_mfc0_tchalt(t0);
1.1.1.6 root 2822: rn = "TCHalt";
2823: break;
1.1.1.5 root 2824: case 5:
1.1.1.6 root 2825: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2826: gen_helper_mfc0_tccontext(t0);
1.1.1.6 root 2827: rn = "TCContext";
2828: break;
1.1.1.5 root 2829: case 6:
1.1.1.6 root 2830: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2831: gen_helper_mfc0_tcschedule(t0);
1.1.1.6 root 2832: rn = "TCSchedule";
2833: break;
1.1.1.5 root 2834: case 7:
1.1.1.6 root 2835: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 2836: gen_helper_mfc0_tcschefback(t0);
1.1.1.6 root 2837: rn = "TCScheFBack";
2838: break;
1.1.1.5 root 2839: default:
2840: goto die;
2841: }
1.1 root 2842: break;
1.1.1.5 root 2843: case 3:
2844: switch (sel) {
2845: case 0:
1.1.1.7 ! root 2846: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
! 2847: tcg_gen_ext32s_tl(t0, t0);
1.1.1.6 root 2848: rn = "EntryLo1";
2849: break;
1.1.1.5 root 2850: default:
2851: goto die;
1.1.1.6 root 2852: }
1.1 root 2853: break;
1.1.1.5 root 2854: case 4:
2855: switch (sel) {
2856: case 0:
1.1.1.7 ! root 2857: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
! 2858: tcg_gen_ext32s_tl(t0, t0);
1.1.1.6 root 2859: rn = "Context";
2860: break;
2861: case 1:
1.1.1.7 ! root 2862: // gen_helper_mfc0_contextconfig(t0); /* SmartMIPS ASE */
1.1.1.6 root 2863: rn = "ContextConfig";
2864: // break;
1.1.1.5 root 2865: default:
2866: goto die;
1.1.1.6 root 2867: }
1.1 root 2868: break;
1.1.1.5 root 2869: case 5:
2870: switch (sel) {
2871: case 0:
1.1.1.7 ! root 2872: gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
1.1.1.6 root 2873: rn = "PageMask";
2874: break;
2875: case 1:
2876: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 2877: gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
1.1.1.6 root 2878: rn = "PageGrain";
2879: break;
1.1.1.5 root 2880: default:
2881: goto die;
1.1.1.6 root 2882: }
1.1 root 2883: break;
1.1.1.5 root 2884: case 6:
2885: switch (sel) {
2886: case 0:
1.1.1.7 ! root 2887: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
1.1.1.6 root 2888: rn = "Wired";
2889: break;
2890: case 1:
2891: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 2892: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
1.1.1.6 root 2893: rn = "SRSConf0";
2894: break;
2895: case 2:
2896: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 2897: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
1.1.1.6 root 2898: rn = "SRSConf1";
2899: break;
1.1.1.5 root 2900: case 3:
1.1.1.6 root 2901: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 2902: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
1.1.1.6 root 2903: rn = "SRSConf2";
2904: break;
1.1.1.5 root 2905: case 4:
1.1.1.6 root 2906: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 2907: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
1.1.1.6 root 2908: rn = "SRSConf3";
2909: break;
1.1.1.5 root 2910: case 5:
1.1.1.6 root 2911: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 2912: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
1.1.1.6 root 2913: rn = "SRSConf4";
2914: break;
1.1.1.5 root 2915: default:
2916: goto die;
1.1.1.6 root 2917: }
1.1 root 2918: break;
1.1.1.5 root 2919: case 7:
2920: switch (sel) {
2921: case 0:
1.1.1.6 root 2922: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 2923: gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
1.1.1.6 root 2924: rn = "HWREna";
2925: break;
1.1.1.5 root 2926: default:
2927: goto die;
1.1.1.6 root 2928: }
1.1 root 2929: break;
1.1.1.5 root 2930: case 8:
2931: switch (sel) {
2932: case 0:
1.1.1.7 ! root 2933: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
! 2934: tcg_gen_ext32s_tl(t0, t0);
! 2935: rn = "BadVAddr";
1.1.1.6 root 2936: break;
1.1.1.5 root 2937: default:
2938: goto die;
2939: }
1.1.1.2 root 2940: break;
1.1.1.5 root 2941: case 9:
2942: switch (sel) {
2943: case 0:
1.1.1.7 ! root 2944: /* Mark as an IO operation because we read the time. */
! 2945: if (use_icount)
! 2946: gen_io_start();
! 2947: gen_helper_mfc0_count(t0);
! 2948: if (use_icount) {
! 2949: gen_io_end();
! 2950: ctx->bstate = BS_STOP;
! 2951: }
1.1.1.6 root 2952: rn = "Count";
2953: break;
2954: /* 6,7 are implementation dependent */
1.1.1.5 root 2955: default:
2956: goto die;
1.1.1.6 root 2957: }
1.1.1.5 root 2958: break;
2959: case 10:
2960: switch (sel) {
2961: case 0:
1.1.1.7 ! root 2962: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
! 2963: tcg_gen_ext32s_tl(t0, t0);
1.1.1.6 root 2964: rn = "EntryHi";
2965: break;
1.1.1.5 root 2966: default:
2967: goto die;
1.1.1.6 root 2968: }
1.1.1.5 root 2969: break;
2970: case 11:
2971: switch (sel) {
2972: case 0:
1.1.1.7 ! root 2973: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
1.1.1.6 root 2974: rn = "Compare";
2975: break;
2976: /* 6,7 are implementation dependent */
1.1.1.5 root 2977: default:
2978: goto die;
1.1.1.6 root 2979: }
1.1.1.5 root 2980: break;
2981: case 12:
2982: switch (sel) {
2983: case 0:
1.1.1.7 ! root 2984: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
1.1.1.6 root 2985: rn = "Status";
2986: break;
2987: case 1:
2988: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 2989: gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
1.1.1.6 root 2990: rn = "IntCtl";
2991: break;
2992: case 2:
2993: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 2994: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
1.1.1.6 root 2995: rn = "SRSCtl";
2996: break;
1.1.1.5 root 2997: case 3:
1.1.1.6 root 2998: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 2999: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 3000: rn = "SRSMap";
3001: break;
1.1.1.5 root 3002: default:
3003: goto die;
3004: }
3005: break;
3006: case 13:
3007: switch (sel) {
3008: case 0:
1.1.1.7 ! root 3009: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
1.1.1.6 root 3010: rn = "Cause";
3011: break;
1.1.1.5 root 3012: default:
3013: goto die;
3014: }
3015: break;
3016: case 14:
3017: switch (sel) {
3018: case 0:
1.1.1.7 ! root 3019: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
! 3020: tcg_gen_ext32s_tl(t0, t0);
1.1.1.6 root 3021: rn = "EPC";
3022: break;
1.1.1.5 root 3023: default:
3024: goto die;
1.1.1.6 root 3025: }
1.1.1.5 root 3026: break;
3027: case 15:
3028: switch (sel) {
3029: case 0:
1.1.1.7 ! root 3030: gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
1.1.1.6 root 3031: rn = "PRid";
3032: break;
3033: case 1:
3034: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3035: gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
1.1.1.6 root 3036: rn = "EBase";
3037: break;
1.1.1.5 root 3038: default:
3039: goto die;
3040: }
3041: break;
3042: case 16:
3043: switch (sel) {
3044: case 0:
1.1.1.7 ! root 3045: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
1.1.1.5 root 3046: rn = "Config";
3047: break;
3048: case 1:
1.1.1.7 ! root 3049: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
1.1.1.5 root 3050: rn = "Config1";
3051: break;
3052: case 2:
1.1.1.7 ! root 3053: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
1.1.1.5 root 3054: rn = "Config2";
3055: break;
3056: case 3:
1.1.1.7 ! root 3057: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
1.1.1.5 root 3058: rn = "Config3";
3059: break;
1.1.1.6 root 3060: /* 4,5 are reserved */
3061: /* 6,7 are implementation dependent */
3062: case 6:
1.1.1.7 ! root 3063: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
1.1.1.6 root 3064: rn = "Config6";
3065: break;
3066: case 7:
1.1.1.7 ! root 3067: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
1.1.1.6 root 3068: rn = "Config7";
3069: break;
1.1.1.5 root 3070: default:
3071: goto die;
1.1 root 3072: }
1.1.1.4 root 3073: break;
1.1.1.5 root 3074: case 17:
3075: switch (sel) {
3076: case 0:
1.1.1.7 ! root 3077: gen_helper_mfc0_lladdr(t0);
1.1.1.6 root 3078: rn = "LLAddr";
3079: break;
1.1.1.5 root 3080: default:
3081: goto die;
3082: }
1.1.1.4 root 3083: break;
1.1.1.5 root 3084: case 18:
3085: switch (sel) {
1.1.1.6 root 3086: case 0 ... 7:
1.1.1.7 ! root 3087: gen_helper_1i(mfc0_watchlo, t0, sel);
1.1.1.6 root 3088: rn = "WatchLo";
3089: break;
1.1.1.5 root 3090: default:
3091: goto die;
3092: }
1.1.1.4 root 3093: break;
1.1.1.5 root 3094: case 19:
3095: switch (sel) {
1.1.1.6 root 3096: case 0 ...7:
1.1.1.7 ! root 3097: gen_helper_1i(mfc0_watchhi, t0, sel);
1.1.1.6 root 3098: rn = "WatchHi";
3099: break;
1.1.1.5 root 3100: default:
3101: goto die;
3102: }
1.1.1.4 root 3103: break;
1.1.1.5 root 3104: case 20:
3105: switch (sel) {
3106: case 0:
1.1.1.6 root 3107: #if defined(TARGET_MIPS64)
3108: check_insn(env, ctx, ISA_MIPS3);
1.1.1.7 ! root 3109: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
! 3110: tcg_gen_ext32s_tl(t0, t0);
1.1.1.6 root 3111: rn = "XContext";
3112: break;
3113: #endif
1.1.1.5 root 3114: default:
3115: goto die;
1.1.1.4 root 3116: }
3117: break;
1.1.1.5 root 3118: case 21:
3119: /* Officially reserved, but sel 0 is used for R1x000 framemask */
3120: switch (sel) {
3121: case 0:
1.1.1.7 ! root 3122: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
1.1.1.6 root 3123: rn = "Framemask";
3124: break;
1.1.1.5 root 3125: default:
3126: goto die;
1.1.1.4 root 3127: }
3128: break;
1.1.1.5 root 3129: case 22:
1.1.1.7 ! root 3130: tcg_gen_movi_tl(t0, 0); /* unimplemented */
1.1.1.6 root 3131: rn = "'Diagnostic"; /* implementation dependent */
3132: break;
1.1.1.5 root 3133: case 23:
3134: switch (sel) {
3135: case 0:
1.1.1.7 ! root 3136: gen_helper_mfc0_debug(t0); /* EJTAG support */
1.1.1.6 root 3137: rn = "Debug";
3138: break;
3139: case 1:
1.1.1.7 ! root 3140: // gen_helper_mfc0_tracecontrol(t0); /* PDtrace support */
1.1.1.6 root 3141: rn = "TraceControl";
3142: // break;
3143: case 2:
1.1.1.7 ! root 3144: // gen_helper_mfc0_tracecontrol2(t0); /* PDtrace support */
1.1.1.6 root 3145: rn = "TraceControl2";
3146: // break;
1.1.1.5 root 3147: case 3:
1.1.1.7 ! root 3148: // gen_helper_mfc0_usertracedata(t0); /* PDtrace support */
1.1.1.6 root 3149: rn = "UserTraceData";
3150: // break;
1.1.1.5 root 3151: case 4:
1.1.1.7 ! root 3152: // gen_helper_mfc0_tracebpc(t0); /* PDtrace support */
1.1.1.6 root 3153: rn = "TraceBPC";
3154: // break;
1.1.1.5 root 3155: default:
3156: goto die;
1.1.1.4 root 3157: }
1.1.1.5 root 3158: break;
3159: case 24:
3160: switch (sel) {
3161: case 0:
1.1.1.7 ! root 3162: /* EJTAG support */
! 3163: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
! 3164: tcg_gen_ext32s_tl(t0, t0);
1.1.1.6 root 3165: rn = "DEPC";
3166: break;
1.1.1.5 root 3167: default:
3168: goto die;
3169: }
3170: break;
3171: case 25:
3172: switch (sel) {
3173: case 0:
1.1.1.7 ! root 3174: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
1.1.1.6 root 3175: rn = "Performance0";
1.1.1.5 root 3176: break;
3177: case 1:
1.1.1.7 ! root 3178: // gen_helper_mfc0_performance1(t0);
1.1.1.6 root 3179: rn = "Performance1";
3180: // break;
1.1.1.5 root 3181: case 2:
1.1.1.7 ! root 3182: // gen_helper_mfc0_performance2(t0);
1.1.1.6 root 3183: rn = "Performance2";
3184: // break;
1.1.1.5 root 3185: case 3:
1.1.1.7 ! root 3186: // gen_helper_mfc0_performance3(t0);
1.1.1.6 root 3187: rn = "Performance3";
3188: // break;
1.1.1.5 root 3189: case 4:
1.1.1.7 ! root 3190: // gen_helper_mfc0_performance4(t0);
1.1.1.6 root 3191: rn = "Performance4";
3192: // break;
1.1.1.5 root 3193: case 5:
1.1.1.7 ! root 3194: // gen_helper_mfc0_performance5(t0);
1.1.1.6 root 3195: rn = "Performance5";
3196: // break;
1.1.1.5 root 3197: case 6:
1.1.1.7 ! root 3198: // gen_helper_mfc0_performance6(t0);
1.1.1.6 root 3199: rn = "Performance6";
3200: // break;
1.1.1.5 root 3201: case 7:
1.1.1.7 ! root 3202: // gen_helper_mfc0_performance7(t0);
1.1.1.6 root 3203: rn = "Performance7";
3204: // break;
1.1.1.5 root 3205: default:
3206: goto die;
3207: }
3208: break;
3209: case 26:
1.1.1.7 ! root 3210: tcg_gen_movi_tl(t0, 0); /* unimplemented */
! 3211: rn = "ECC";
! 3212: break;
1.1.1.5 root 3213: case 27:
3214: switch (sel) {
3215: case 0 ... 3:
1.1.1.7 ! root 3216: tcg_gen_movi_tl(t0, 0); /* unimplemented */
1.1.1.6 root 3217: rn = "CacheErr";
3218: break;
1.1.1.5 root 3219: default:
3220: goto die;
3221: }
3222: break;
3223: case 28:
3224: switch (sel) {
3225: case 0:
3226: case 2:
3227: case 4:
3228: case 6:
1.1.1.7 ! root 3229: gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
1.1.1.5 root 3230: rn = "TagLo";
3231: break;
3232: case 1:
3233: case 3:
3234: case 5:
3235: case 7:
1.1.1.7 ! root 3236: gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
1.1.1.5 root 3237: rn = "DataLo";
3238: break;
3239: default:
3240: goto die;
3241: }
3242: break;
3243: case 29:
3244: switch (sel) {
3245: case 0:
3246: case 2:
3247: case 4:
3248: case 6:
1.1.1.7 ! root 3249: gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
1.1.1.5 root 3250: rn = "TagHi";
3251: break;
3252: case 1:
3253: case 3:
3254: case 5:
3255: case 7:
1.1.1.7 ! root 3256: gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
1.1.1.5 root 3257: rn = "DataHi";
3258: break;
3259: default:
3260: goto die;
3261: }
3262: break;
3263: case 30:
3264: switch (sel) {
3265: case 0:
1.1.1.7 ! root 3266: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
! 3267: tcg_gen_ext32s_tl(t0, t0);
1.1.1.6 root 3268: rn = "ErrorEPC";
3269: break;
1.1.1.5 root 3270: default:
3271: goto die;
3272: }
3273: break;
3274: case 31:
3275: switch (sel) {
3276: case 0:
1.1.1.7 ! root 3277: /* EJTAG support */
! 3278: gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 3279: rn = "DESAVE";
3280: break;
1.1.1.5 root 3281: default:
3282: goto die;
3283: }
3284: break;
3285: default:
3286: goto die;
3287: }
1.1.1.7 ! root 3288: LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 3289: return;
3290:
3291: die:
1.1.1.7 ! root 3292: LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 3293: generate_exception(ctx, EXCP_RI);
3294: }
3295:
1.1.1.7 ! root 3296: static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
1.1.1.5 root 3297: {
3298: const char *rn = "invalid";
3299:
1.1.1.6 root 3300: if (sel != 0)
3301: check_insn(env, ctx, ISA_MIPS32);
3302:
1.1.1.7 ! root 3303: if (use_icount)
! 3304: gen_io_start();
! 3305:
1.1.1.5 root 3306: switch (reg) {
3307: case 0:
3308: switch (sel) {
3309: case 0:
1.1.1.7 ! root 3310: gen_helper_mtc0_index(t0);
1.1.1.5 root 3311: rn = "Index";
3312: break;
3313: case 1:
1.1.1.6 root 3314: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3315: gen_helper_mtc0_mvpcontrol(t0);
1.1.1.5 root 3316: rn = "MVPControl";
1.1.1.6 root 3317: break;
1.1.1.5 root 3318: case 2:
1.1.1.6 root 3319: check_insn(env, ctx, ASE_MT);
3320: /* ignored */
1.1.1.5 root 3321: rn = "MVPConf0";
1.1.1.6 root 3322: break;
1.1.1.5 root 3323: case 3:
1.1.1.6 root 3324: check_insn(env, ctx, ASE_MT);
3325: /* ignored */
1.1.1.5 root 3326: rn = "MVPConf1";
1.1.1.6 root 3327: break;
1.1.1.5 root 3328: default:
3329: goto die;
3330: }
3331: break;
3332: case 1:
3333: switch (sel) {
3334: case 0:
1.1.1.6 root 3335: /* ignored */
1.1.1.5 root 3336: rn = "Random";
1.1.1.6 root 3337: break;
1.1.1.5 root 3338: case 1:
1.1.1.6 root 3339: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3340: gen_helper_mtc0_vpecontrol(t0);
1.1.1.5 root 3341: rn = "VPEControl";
1.1.1.6 root 3342: break;
1.1.1.5 root 3343: case 2:
1.1.1.6 root 3344: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3345: gen_helper_mtc0_vpeconf0(t0);
1.1.1.5 root 3346: rn = "VPEConf0";
1.1.1.6 root 3347: break;
1.1.1.5 root 3348: case 3:
1.1.1.6 root 3349: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3350: gen_helper_mtc0_vpeconf1(t0);
1.1.1.5 root 3351: rn = "VPEConf1";
1.1.1.6 root 3352: break;
1.1.1.5 root 3353: case 4:
1.1.1.6 root 3354: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3355: gen_helper_mtc0_yqmask(t0);
1.1.1.5 root 3356: rn = "YQMask";
1.1.1.6 root 3357: break;
1.1.1.5 root 3358: case 5:
1.1.1.6 root 3359: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3360: gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 3361: rn = "VPESchedule";
1.1.1.6 root 3362: break;
1.1.1.5 root 3363: case 6:
1.1.1.6 root 3364: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3365: gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 3366: rn = "VPEScheFBack";
1.1.1.6 root 3367: break;
1.1.1.5 root 3368: case 7:
1.1.1.6 root 3369: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3370: gen_helper_mtc0_vpeopt(t0);
1.1.1.5 root 3371: rn = "VPEOpt";
1.1.1.6 root 3372: break;
1.1.1.5 root 3373: default:
3374: goto die;
3375: }
3376: break;
3377: case 2:
3378: switch (sel) {
3379: case 0:
1.1.1.7 ! root 3380: gen_helper_mtc0_entrylo0(t0);
1.1.1.6 root 3381: rn = "EntryLo0";
3382: break;
3383: case 1:
3384: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3385: gen_helper_mtc0_tcstatus(t0);
1.1.1.6 root 3386: rn = "TCStatus";
3387: break;
3388: case 2:
3389: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3390: gen_helper_mtc0_tcbind(t0);
1.1.1.6 root 3391: rn = "TCBind";
3392: break;
1.1.1.5 root 3393: case 3:
1.1.1.6 root 3394: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3395: gen_helper_mtc0_tcrestart(t0);
1.1.1.6 root 3396: rn = "TCRestart";
3397: break;
1.1.1.5 root 3398: case 4:
1.1.1.6 root 3399: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3400: gen_helper_mtc0_tchalt(t0);
1.1.1.6 root 3401: rn = "TCHalt";
3402: break;
1.1.1.5 root 3403: case 5:
1.1.1.6 root 3404: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3405: gen_helper_mtc0_tccontext(t0);
1.1.1.6 root 3406: rn = "TCContext";
3407: break;
1.1.1.5 root 3408: case 6:
1.1.1.6 root 3409: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3410: gen_helper_mtc0_tcschedule(t0);
1.1.1.6 root 3411: rn = "TCSchedule";
3412: break;
1.1.1.5 root 3413: case 7:
1.1.1.6 root 3414: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3415: gen_helper_mtc0_tcschefback(t0);
1.1.1.6 root 3416: rn = "TCScheFBack";
3417: break;
1.1.1.5 root 3418: default:
3419: goto die;
3420: }
3421: break;
3422: case 3:
3423: switch (sel) {
3424: case 0:
1.1.1.7 ! root 3425: gen_helper_mtc0_entrylo1(t0);
1.1.1.6 root 3426: rn = "EntryLo1";
3427: break;
1.1.1.5 root 3428: default:
3429: goto die;
1.1.1.6 root 3430: }
1.1.1.5 root 3431: break;
3432: case 4:
3433: switch (sel) {
3434: case 0:
1.1.1.7 ! root 3435: gen_helper_mtc0_context(t0);
1.1.1.6 root 3436: rn = "Context";
3437: break;
3438: case 1:
1.1.1.7 ! root 3439: // gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
1.1.1.6 root 3440: rn = "ContextConfig";
3441: // break;
1.1.1.5 root 3442: default:
3443: goto die;
1.1.1.6 root 3444: }
1.1.1.5 root 3445: break;
3446: case 5:
3447: switch (sel) {
3448: case 0:
1.1.1.7 ! root 3449: gen_helper_mtc0_pagemask(t0);
1.1.1.6 root 3450: rn = "PageMask";
3451: break;
3452: case 1:
3453: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3454: gen_helper_mtc0_pagegrain(t0);
1.1.1.6 root 3455: rn = "PageGrain";
3456: break;
1.1.1.5 root 3457: default:
3458: goto die;
1.1.1.6 root 3459: }
1.1.1.5 root 3460: break;
3461: case 6:
3462: switch (sel) {
3463: case 0:
1.1.1.7 ! root 3464: gen_helper_mtc0_wired(t0);
1.1.1.6 root 3465: rn = "Wired";
3466: break;
3467: case 1:
3468: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3469: gen_helper_mtc0_srsconf0(t0);
1.1.1.6 root 3470: rn = "SRSConf0";
3471: break;
3472: case 2:
3473: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3474: gen_helper_mtc0_srsconf1(t0);
1.1.1.6 root 3475: rn = "SRSConf1";
3476: break;
1.1.1.5 root 3477: case 3:
1.1.1.6 root 3478: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3479: gen_helper_mtc0_srsconf2(t0);
1.1.1.6 root 3480: rn = "SRSConf2";
3481: break;
1.1.1.5 root 3482: case 4:
1.1.1.6 root 3483: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3484: gen_helper_mtc0_srsconf3(t0);
1.1.1.6 root 3485: rn = "SRSConf3";
3486: break;
1.1.1.5 root 3487: case 5:
1.1.1.6 root 3488: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3489: gen_helper_mtc0_srsconf4(t0);
1.1.1.6 root 3490: rn = "SRSConf4";
3491: break;
1.1.1.5 root 3492: default:
3493: goto die;
1.1.1.6 root 3494: }
1.1.1.5 root 3495: break;
3496: case 7:
3497: switch (sel) {
3498: case 0:
1.1.1.6 root 3499: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3500: gen_helper_mtc0_hwrena(t0);
1.1.1.6 root 3501: rn = "HWREna";
3502: break;
1.1.1.5 root 3503: default:
3504: goto die;
1.1.1.6 root 3505: }
1.1.1.5 root 3506: break;
3507: case 8:
3508: /* ignored */
1.1.1.7 ! root 3509: rn = "BadVAddr";
1.1.1.5 root 3510: break;
3511: case 9:
3512: switch (sel) {
3513: case 0:
1.1.1.7 ! root 3514: gen_helper_mtc0_count(t0);
1.1.1.6 root 3515: rn = "Count";
3516: break;
3517: /* 6,7 are implementation dependent */
1.1.1.5 root 3518: default:
3519: goto die;
1.1.1.6 root 3520: }
3521: /* Stop translation as we may have switched the execution mode */
3522: ctx->bstate = BS_STOP;
1.1.1.5 root 3523: break;
3524: case 10:
3525: switch (sel) {
3526: case 0:
1.1.1.7 ! root 3527: gen_helper_mtc0_entryhi(t0);
1.1.1.6 root 3528: rn = "EntryHi";
3529: break;
1.1.1.5 root 3530: default:
3531: goto die;
1.1.1.6 root 3532: }
1.1.1.5 root 3533: break;
3534: case 11:
3535: switch (sel) {
3536: case 0:
1.1.1.7 ! root 3537: gen_helper_mtc0_compare(t0);
1.1.1.6 root 3538: rn = "Compare";
3539: break;
3540: /* 6,7 are implementation dependent */
1.1.1.5 root 3541: default:
3542: goto die;
1.1.1.6 root 3543: }
3544: /* Stop translation as we may have switched the execution mode */
3545: ctx->bstate = BS_STOP;
1.1.1.5 root 3546: break;
3547: case 12:
3548: switch (sel) {
3549: case 0:
1.1.1.7 ! root 3550: gen_helper_mtc0_status(t0);
1.1.1.6 root 3551: /* BS_STOP isn't good enough here, hflags may have changed. */
3552: gen_save_pc(ctx->pc + 4);
3553: ctx->bstate = BS_EXCP;
3554: rn = "Status";
3555: break;
3556: case 1:
3557: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3558: gen_helper_mtc0_intctl(t0);
1.1.1.6 root 3559: /* Stop translation as we may have switched the execution mode */
3560: ctx->bstate = BS_STOP;
3561: rn = "IntCtl";
3562: break;
3563: case 2:
3564: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3565: gen_helper_mtc0_srsctl(t0);
1.1.1.6 root 3566: /* Stop translation as we may have switched the execution mode */
3567: ctx->bstate = BS_STOP;
3568: rn = "SRSCtl";
3569: break;
1.1.1.5 root 3570: case 3:
1.1.1.6 root 3571: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3572: gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 3573: /* Stop translation as we may have switched the execution mode */
3574: ctx->bstate = BS_STOP;
3575: rn = "SRSMap";
3576: break;
1.1.1.5 root 3577: default:
3578: goto die;
1.1.1.6 root 3579: }
1.1.1.5 root 3580: break;
3581: case 13:
3582: switch (sel) {
3583: case 0:
1.1.1.7 ! root 3584: gen_helper_mtc0_cause(t0);
1.1.1.6 root 3585: rn = "Cause";
3586: break;
1.1.1.5 root 3587: default:
3588: goto die;
1.1.1.6 root 3589: }
3590: /* Stop translation as we may have switched the execution mode */
3591: ctx->bstate = BS_STOP;
1.1.1.5 root 3592: break;
3593: case 14:
3594: switch (sel) {
3595: case 0:
1.1.1.7 ! root 3596: gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 3597: rn = "EPC";
3598: break;
1.1.1.5 root 3599: default:
3600: goto die;
1.1.1.6 root 3601: }
1.1.1.5 root 3602: break;
3603: case 15:
3604: switch (sel) {
3605: case 0:
1.1.1.6 root 3606: /* ignored */
3607: rn = "PRid";
3608: break;
3609: case 1:
3610: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 3611: gen_helper_mtc0_ebase(t0);
1.1.1.6 root 3612: rn = "EBase";
3613: break;
1.1.1.5 root 3614: default:
3615: goto die;
1.1.1.6 root 3616: }
1.1.1.5 root 3617: break;
3618: case 16:
3619: switch (sel) {
3620: case 0:
1.1.1.7 ! root 3621: gen_helper_mtc0_config0(t0);
1.1.1.5 root 3622: rn = "Config";
1.1.1.6 root 3623: /* Stop translation as we may have switched the execution mode */
3624: ctx->bstate = BS_STOP;
1.1.1.5 root 3625: break;
3626: case 1:
1.1.1.6 root 3627: /* ignored, read only */
1.1.1.5 root 3628: rn = "Config1";
3629: break;
3630: case 2:
1.1.1.7 ! root 3631: gen_helper_mtc0_config2(t0);
1.1.1.5 root 3632: rn = "Config2";
1.1.1.6 root 3633: /* Stop translation as we may have switched the execution mode */
3634: ctx->bstate = BS_STOP;
1.1.1.5 root 3635: break;
3636: case 3:
1.1.1.6 root 3637: /* ignored, read only */
1.1.1.5 root 3638: rn = "Config3";
3639: break;
1.1.1.6 root 3640: /* 4,5 are reserved */
3641: /* 6,7 are implementation dependent */
3642: case 6:
3643: /* ignored */
3644: rn = "Config6";
3645: break;
3646: case 7:
3647: /* ignored */
3648: rn = "Config7";
3649: break;
1.1.1.5 root 3650: default:
3651: rn = "Invalid config selector";
3652: goto die;
3653: }
3654: break;
3655: case 17:
3656: switch (sel) {
3657: case 0:
1.1.1.6 root 3658: /* ignored */
3659: rn = "LLAddr";
3660: break;
1.1.1.5 root 3661: default:
3662: goto die;
3663: }
3664: break;
3665: case 18:
3666: switch (sel) {
1.1.1.6 root 3667: case 0 ... 7:
1.1.1.7 ! root 3668: gen_helper_1i(mtc0_watchlo, t0, sel);
1.1.1.6 root 3669: rn = "WatchLo";
3670: break;
1.1.1.5 root 3671: default:
3672: goto die;
3673: }
3674: break;
3675: case 19:
3676: switch (sel) {
1.1.1.6 root 3677: case 0 ... 7:
1.1.1.7 ! root 3678: gen_helper_1i(mtc0_watchhi, t0, sel);
1.1.1.6 root 3679: rn = "WatchHi";
3680: break;
1.1.1.5 root 3681: default:
3682: goto die;
3683: }
3684: break;
3685: case 20:
3686: switch (sel) {
3687: case 0:
1.1.1.6 root 3688: #if defined(TARGET_MIPS64)
3689: check_insn(env, ctx, ISA_MIPS3);
1.1.1.7 ! root 3690: gen_helper_mtc0_xcontext(t0);
1.1.1.6 root 3691: rn = "XContext";
3692: break;
3693: #endif
1.1.1.5 root 3694: default:
3695: goto die;
3696: }
3697: break;
3698: case 21:
3699: /* Officially reserved, but sel 0 is used for R1x000 framemask */
3700: switch (sel) {
3701: case 0:
1.1.1.7 ! root 3702: gen_helper_mtc0_framemask(t0);
1.1.1.6 root 3703: rn = "Framemask";
3704: break;
1.1.1.5 root 3705: default:
3706: goto die;
3707: }
3708: break;
3709: case 22:
3710: /* ignored */
3711: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 root 3712: break;
1.1.1.5 root 3713: case 23:
3714: switch (sel) {
3715: case 0:
1.1.1.7 ! root 3716: gen_helper_mtc0_debug(t0); /* EJTAG support */
1.1.1.6 root 3717: /* BS_STOP isn't good enough here, hflags may have changed. */
3718: gen_save_pc(ctx->pc + 4);
3719: ctx->bstate = BS_EXCP;
3720: rn = "Debug";
3721: break;
3722: case 1:
1.1.1.7 ! root 3723: // gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
1.1.1.6 root 3724: rn = "TraceControl";
3725: /* Stop translation as we may have switched the execution mode */
3726: ctx->bstate = BS_STOP;
3727: // break;
3728: case 2:
1.1.1.7 ! root 3729: // gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
1.1.1.6 root 3730: rn = "TraceControl2";
3731: /* Stop translation as we may have switched the execution mode */
3732: ctx->bstate = BS_STOP;
3733: // break;
3734: case 3:
3735: /* Stop translation as we may have switched the execution mode */
3736: ctx->bstate = BS_STOP;
1.1.1.7 ! root 3737: // gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
1.1.1.6 root 3738: rn = "UserTraceData";
3739: /* Stop translation as we may have switched the execution mode */
3740: ctx->bstate = BS_STOP;
3741: // break;
1.1.1.5 root 3742: case 4:
1.1.1.7 ! root 3743: // gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
1.1.1.6 root 3744: /* Stop translation as we may have switched the execution mode */
3745: ctx->bstate = BS_STOP;
3746: rn = "TraceBPC";
3747: // break;
1.1.1.5 root 3748: default:
3749: goto die;
3750: }
3751: break;
3752: case 24:
3753: switch (sel) {
3754: case 0:
1.1.1.7 ! root 3755: /* EJTAG support */
! 3756: gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 3757: rn = "DEPC";
3758: break;
1.1.1.5 root 3759: default:
3760: goto die;
3761: }
3762: break;
3763: case 25:
3764: switch (sel) {
3765: case 0:
1.1.1.7 ! root 3766: gen_helper_mtc0_performance0(t0);
1.1.1.6 root 3767: rn = "Performance0";
3768: break;
3769: case 1:
1.1.1.7 ! root 3770: // gen_helper_mtc0_performance1(t0);
1.1.1.6 root 3771: rn = "Performance1";
3772: // break;
3773: case 2:
1.1.1.7 ! root 3774: // gen_helper_mtc0_performance2(t0);
1.1.1.6 root 3775: rn = "Performance2";
3776: // break;
3777: case 3:
1.1.1.7 ! root 3778: // gen_helper_mtc0_performance3(t0);
1.1.1.6 root 3779: rn = "Performance3";
3780: // break;
1.1.1.5 root 3781: case 4:
1.1.1.7 ! root 3782: // gen_helper_mtc0_performance4(t0);
1.1.1.6 root 3783: rn = "Performance4";
3784: // break;
1.1.1.5 root 3785: case 5:
1.1.1.7 ! root 3786: // gen_helper_mtc0_performance5(t0);
1.1.1.6 root 3787: rn = "Performance5";
3788: // break;
1.1.1.5 root 3789: case 6:
1.1.1.7 ! root 3790: // gen_helper_mtc0_performance6(t0);
1.1.1.6 root 3791: rn = "Performance6";
3792: // break;
1.1.1.5 root 3793: case 7:
1.1.1.7 ! root 3794: // gen_helper_mtc0_performance7(t0);
1.1.1.6 root 3795: rn = "Performance7";
3796: // break;
1.1.1.5 root 3797: default:
3798: goto die;
3799: }
3800: break;
3801: case 26:
1.1.1.6 root 3802: /* ignored */
1.1.1.5 root 3803: rn = "ECC";
1.1.1.6 root 3804: break;
1.1.1.5 root 3805: case 27:
3806: switch (sel) {
3807: case 0 ... 3:
1.1.1.6 root 3808: /* ignored */
3809: rn = "CacheErr";
3810: break;
1.1.1.5 root 3811: default:
3812: goto die;
3813: }
3814: break;
3815: case 28:
3816: switch (sel) {
3817: case 0:
3818: case 2:
3819: case 4:
3820: case 6:
1.1.1.7 ! root 3821: gen_helper_mtc0_taglo(t0);
1.1.1.5 root 3822: rn = "TagLo";
3823: break;
3824: case 1:
3825: case 3:
3826: case 5:
3827: case 7:
1.1.1.7 ! root 3828: gen_helper_mtc0_datalo(t0);
1.1.1.5 root 3829: rn = "DataLo";
3830: break;
3831: default:
3832: goto die;
3833: }
3834: break;
3835: case 29:
3836: switch (sel) {
3837: case 0:
3838: case 2:
3839: case 4:
3840: case 6:
1.1.1.7 ! root 3841: gen_helper_mtc0_taghi(t0);
1.1.1.5 root 3842: rn = "TagHi";
3843: break;
3844: case 1:
3845: case 3:
3846: case 5:
3847: case 7:
1.1.1.7 ! root 3848: gen_helper_mtc0_datahi(t0);
1.1.1.5 root 3849: rn = "DataHi";
3850: break;
3851: default:
3852: rn = "invalid sel";
3853: goto die;
3854: }
3855: break;
3856: case 30:
3857: switch (sel) {
3858: case 0:
1.1.1.7 ! root 3859: gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 3860: rn = "ErrorEPC";
3861: break;
1.1.1.5 root 3862: default:
3863: goto die;
3864: }
3865: break;
3866: case 31:
3867: switch (sel) {
3868: case 0:
1.1.1.7 ! root 3869: /* EJTAG support */
! 3870: gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 3871: rn = "DESAVE";
3872: break;
1.1.1.5 root 3873: default:
3874: goto die;
3875: }
1.1.1.6 root 3876: /* Stop translation as we may have switched the execution mode */
3877: ctx->bstate = BS_STOP;
1.1.1.5 root 3878: break;
3879: default:
3880: goto die;
3881: }
1.1.1.7 ! root 3882: LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
! 3883: /* For simplicity assume that all writes can cause interrupts. */
! 3884: if (use_icount) {
! 3885: gen_io_end();
! 3886: ctx->bstate = BS_STOP;
1.1.1.5 root 3887: }
3888: return;
3889:
3890: die:
1.1.1.7 ! root 3891: LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 3892: generate_exception(ctx, EXCP_RI);
3893: }
3894:
1.1.1.6 root 3895: #if defined(TARGET_MIPS64)
1.1.1.7 ! root 3896: static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
1.1.1.5 root 3897: {
3898: const char *rn = "invalid";
3899:
1.1.1.6 root 3900: if (sel != 0)
3901: check_insn(env, ctx, ISA_MIPS64);
3902:
1.1.1.5 root 3903: switch (reg) {
3904: case 0:
3905: switch (sel) {
3906: case 0:
1.1.1.7 ! root 3907: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
1.1.1.5 root 3908: rn = "Index";
3909: break;
3910: case 1:
1.1.1.6 root 3911: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3912: gen_helper_mfc0_mvpcontrol(t0);
1.1.1.5 root 3913: rn = "MVPControl";
1.1.1.6 root 3914: break;
1.1.1.5 root 3915: case 2:
1.1.1.6 root 3916: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3917: gen_helper_mfc0_mvpconf0(t0);
1.1.1.5 root 3918: rn = "MVPConf0";
1.1.1.6 root 3919: break;
1.1.1.5 root 3920: case 3:
1.1.1.6 root 3921: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3922: gen_helper_mfc0_mvpconf1(t0);
1.1.1.5 root 3923: rn = "MVPConf1";
1.1.1.6 root 3924: break;
1.1.1.5 root 3925: default:
3926: goto die;
3927: }
3928: break;
3929: case 1:
3930: switch (sel) {
3931: case 0:
1.1.1.7 ! root 3932: gen_helper_mfc0_random(t0);
1.1.1.5 root 3933: rn = "Random";
1.1.1.6 root 3934: break;
1.1.1.5 root 3935: case 1:
1.1.1.6 root 3936: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3937: gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
1.1.1.5 root 3938: rn = "VPEControl";
1.1.1.6 root 3939: break;
1.1.1.5 root 3940: case 2:
1.1.1.6 root 3941: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3942: gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
1.1.1.5 root 3943: rn = "VPEConf0";
1.1.1.6 root 3944: break;
1.1.1.5 root 3945: case 3:
1.1.1.6 root 3946: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3947: gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
1.1.1.5 root 3948: rn = "VPEConf1";
1.1.1.6 root 3949: break;
1.1.1.5 root 3950: case 4:
1.1.1.6 root 3951: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3952: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask));
1.1.1.5 root 3953: rn = "YQMask";
1.1.1.6 root 3954: break;
1.1.1.5 root 3955: case 5:
1.1.1.6 root 3956: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3957: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 3958: rn = "VPESchedule";
1.1.1.6 root 3959: break;
1.1.1.5 root 3960: case 6:
1.1.1.6 root 3961: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3962: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 3963: rn = "VPEScheFBack";
1.1.1.6 root 3964: break;
1.1.1.5 root 3965: case 7:
1.1.1.6 root 3966: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3967: gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
1.1.1.5 root 3968: rn = "VPEOpt";
1.1.1.6 root 3969: break;
1.1.1.5 root 3970: default:
3971: goto die;
3972: }
3973: break;
3974: case 2:
3975: switch (sel) {
3976: case 0:
1.1.1.7 ! root 3977: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
1.1.1.6 root 3978: rn = "EntryLo0";
3979: break;
3980: case 1:
3981: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3982: gen_helper_mfc0_tcstatus(t0);
1.1.1.6 root 3983: rn = "TCStatus";
3984: break;
3985: case 2:
3986: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3987: gen_helper_mfc0_tcbind(t0);
1.1.1.6 root 3988: rn = "TCBind";
3989: break;
1.1.1.5 root 3990: case 3:
1.1.1.6 root 3991: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3992: gen_helper_dmfc0_tcrestart(t0);
1.1.1.6 root 3993: rn = "TCRestart";
3994: break;
1.1.1.5 root 3995: case 4:
1.1.1.6 root 3996: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 3997: gen_helper_dmfc0_tchalt(t0);
1.1.1.6 root 3998: rn = "TCHalt";
3999: break;
1.1.1.5 root 4000: case 5:
1.1.1.6 root 4001: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4002: gen_helper_dmfc0_tccontext(t0);
1.1.1.6 root 4003: rn = "TCContext";
4004: break;
1.1.1.5 root 4005: case 6:
1.1.1.6 root 4006: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4007: gen_helper_dmfc0_tcschedule(t0);
1.1.1.6 root 4008: rn = "TCSchedule";
4009: break;
1.1.1.5 root 4010: case 7:
1.1.1.6 root 4011: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4012: gen_helper_dmfc0_tcschefback(t0);
1.1.1.6 root 4013: rn = "TCScheFBack";
4014: break;
1.1.1.5 root 4015: default:
4016: goto die;
4017: }
4018: break;
4019: case 3:
4020: switch (sel) {
4021: case 0:
1.1.1.7 ! root 4022: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
1.1.1.6 root 4023: rn = "EntryLo1";
4024: break;
1.1.1.5 root 4025: default:
4026: goto die;
1.1.1.6 root 4027: }
1.1.1.5 root 4028: break;
4029: case 4:
4030: switch (sel) {
4031: case 0:
1.1.1.7 ! root 4032: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
1.1.1.6 root 4033: rn = "Context";
4034: break;
4035: case 1:
1.1.1.7 ! root 4036: // gen_helper_dmfc0_contextconfig(t0); /* SmartMIPS ASE */
1.1.1.6 root 4037: rn = "ContextConfig";
4038: // break;
1.1.1.5 root 4039: default:
4040: goto die;
1.1.1.6 root 4041: }
1.1.1.5 root 4042: break;
4043: case 5:
4044: switch (sel) {
4045: case 0:
1.1.1.7 ! root 4046: gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
1.1.1.6 root 4047: rn = "PageMask";
4048: break;
4049: case 1:
4050: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4051: gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
1.1.1.6 root 4052: rn = "PageGrain";
4053: break;
1.1.1.5 root 4054: default:
4055: goto die;
1.1.1.6 root 4056: }
1.1.1.5 root 4057: break;
4058: case 6:
4059: switch (sel) {
4060: case 0:
1.1.1.7 ! root 4061: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
1.1.1.6 root 4062: rn = "Wired";
4063: break;
4064: case 1:
4065: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4066: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
1.1.1.6 root 4067: rn = "SRSConf0";
4068: break;
4069: case 2:
4070: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4071: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
1.1.1.6 root 4072: rn = "SRSConf1";
4073: break;
1.1.1.5 root 4074: case 3:
1.1.1.6 root 4075: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4076: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
1.1.1.6 root 4077: rn = "SRSConf2";
4078: break;
1.1.1.5 root 4079: case 4:
1.1.1.6 root 4080: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4081: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
1.1.1.6 root 4082: rn = "SRSConf3";
4083: break;
1.1.1.5 root 4084: case 5:
1.1.1.6 root 4085: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4086: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
1.1.1.6 root 4087: rn = "SRSConf4";
4088: break;
1.1.1.5 root 4089: default:
4090: goto die;
1.1.1.6 root 4091: }
1.1.1.5 root 4092: break;
4093: case 7:
4094: switch (sel) {
4095: case 0:
1.1.1.6 root 4096: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4097: gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
1.1.1.6 root 4098: rn = "HWREna";
4099: break;
1.1.1.5 root 4100: default:
4101: goto die;
1.1.1.6 root 4102: }
1.1.1.5 root 4103: break;
4104: case 8:
4105: switch (sel) {
4106: case 0:
1.1.1.7 ! root 4107: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
! 4108: rn = "BadVAddr";
1.1.1.6 root 4109: break;
1.1.1.5 root 4110: default:
4111: goto die;
1.1.1.6 root 4112: }
1.1.1.5 root 4113: break;
4114: case 9:
4115: switch (sel) {
4116: case 0:
1.1.1.7 ! root 4117: /* Mark as an IO operation because we read the time. */
! 4118: if (use_icount)
! 4119: gen_io_start();
! 4120: gen_helper_mfc0_count(t0);
! 4121: if (use_icount) {
! 4122: gen_io_end();
! 4123: ctx->bstate = BS_STOP;
! 4124: }
1.1.1.6 root 4125: rn = "Count";
4126: break;
4127: /* 6,7 are implementation dependent */
1.1.1.5 root 4128: default:
4129: goto die;
1.1.1.6 root 4130: }
1.1.1.5 root 4131: break;
4132: case 10:
4133: switch (sel) {
4134: case 0:
1.1.1.7 ! root 4135: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
1.1.1.6 root 4136: rn = "EntryHi";
4137: break;
1.1.1.5 root 4138: default:
4139: goto die;
1.1.1.6 root 4140: }
1.1.1.5 root 4141: break;
4142: case 11:
4143: switch (sel) {
4144: case 0:
1.1.1.7 ! root 4145: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
1.1.1.6 root 4146: rn = "Compare";
4147: break;
4148: /* 6,7 are implementation dependent */
1.1.1.5 root 4149: default:
4150: goto die;
1.1.1.6 root 4151: }
1.1.1.5 root 4152: break;
4153: case 12:
4154: switch (sel) {
4155: case 0:
1.1.1.7 ! root 4156: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
1.1.1.6 root 4157: rn = "Status";
4158: break;
4159: case 1:
4160: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4161: gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
1.1.1.6 root 4162: rn = "IntCtl";
4163: break;
4164: case 2:
4165: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4166: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
1.1.1.6 root 4167: rn = "SRSCtl";
4168: break;
1.1.1.5 root 4169: case 3:
1.1.1.6 root 4170: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4171: gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 4172: rn = "SRSMap";
4173: break;
1.1.1.5 root 4174: default:
4175: goto die;
1.1.1.6 root 4176: }
1.1.1.5 root 4177: break;
4178: case 13:
4179: switch (sel) {
4180: case 0:
1.1.1.7 ! root 4181: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
1.1.1.6 root 4182: rn = "Cause";
4183: break;
1.1.1.5 root 4184: default:
4185: goto die;
1.1.1.6 root 4186: }
1.1.1.5 root 4187: break;
4188: case 14:
4189: switch (sel) {
4190: case 0:
1.1.1.7 ! root 4191: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 4192: rn = "EPC";
4193: break;
1.1.1.5 root 4194: default:
4195: goto die;
1.1.1.6 root 4196: }
1.1.1.5 root 4197: break;
4198: case 15:
4199: switch (sel) {
4200: case 0:
1.1.1.7 ! root 4201: gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
1.1.1.6 root 4202: rn = "PRid";
4203: break;
4204: case 1:
4205: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4206: gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
1.1.1.6 root 4207: rn = "EBase";
4208: break;
1.1.1.5 root 4209: default:
4210: goto die;
1.1.1.6 root 4211: }
1.1.1.5 root 4212: break;
4213: case 16:
4214: switch (sel) {
4215: case 0:
1.1.1.7 ! root 4216: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
1.1.1.5 root 4217: rn = "Config";
4218: break;
4219: case 1:
1.1.1.7 ! root 4220: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
1.1.1.5 root 4221: rn = "Config1";
4222: break;
4223: case 2:
1.1.1.7 ! root 4224: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
1.1.1.5 root 4225: rn = "Config2";
4226: break;
4227: case 3:
1.1.1.7 ! root 4228: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
1.1.1.5 root 4229: rn = "Config3";
4230: break;
4231: /* 6,7 are implementation dependent */
1.1.1.7 ! root 4232: case 6:
! 4233: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
! 4234: rn = "Config6";
! 4235: break;
! 4236: case 7:
! 4237: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
! 4238: rn = "Config7";
! 4239: break;
1.1.1.5 root 4240: default:
4241: goto die;
4242: }
4243: break;
4244: case 17:
4245: switch (sel) {
4246: case 0:
1.1.1.7 ! root 4247: gen_helper_dmfc0_lladdr(t0);
1.1.1.6 root 4248: rn = "LLAddr";
4249: break;
1.1.1.5 root 4250: default:
4251: goto die;
4252: }
4253: break;
4254: case 18:
4255: switch (sel) {
1.1.1.6 root 4256: case 0 ... 7:
1.1.1.7 ! root 4257: gen_helper_1i(dmfc0_watchlo, t0, sel);
1.1.1.6 root 4258: rn = "WatchLo";
4259: break;
1.1.1.5 root 4260: default:
4261: goto die;
4262: }
4263: break;
4264: case 19:
4265: switch (sel) {
1.1.1.6 root 4266: case 0 ... 7:
1.1.1.7 ! root 4267: gen_helper_1i(mfc0_watchhi, t0, sel);
1.1.1.6 root 4268: rn = "WatchHi";
4269: break;
1.1.1.5 root 4270: default:
4271: goto die;
4272: }
4273: break;
4274: case 20:
4275: switch (sel) {
4276: case 0:
1.1.1.6 root 4277: check_insn(env, ctx, ISA_MIPS3);
1.1.1.7 ! root 4278: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
1.1.1.6 root 4279: rn = "XContext";
4280: break;
1.1.1.5 root 4281: default:
4282: goto die;
4283: }
4284: break;
4285: case 21:
4286: /* Officially reserved, but sel 0 is used for R1x000 framemask */
4287: switch (sel) {
4288: case 0:
1.1.1.7 ! root 4289: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
1.1.1.6 root 4290: rn = "Framemask";
4291: break;
1.1.1.5 root 4292: default:
4293: goto die;
4294: }
4295: break;
4296: case 22:
1.1.1.7 ! root 4297: tcg_gen_movi_tl(t0, 0); /* unimplemented */
1.1.1.6 root 4298: rn = "'Diagnostic"; /* implementation dependent */
4299: break;
1.1.1.5 root 4300: case 23:
4301: switch (sel) {
4302: case 0:
1.1.1.7 ! root 4303: gen_helper_mfc0_debug(t0); /* EJTAG support */
1.1.1.6 root 4304: rn = "Debug";
4305: break;
4306: case 1:
1.1.1.7 ! root 4307: // gen_helper_dmfc0_tracecontrol(t0); /* PDtrace support */
1.1.1.6 root 4308: rn = "TraceControl";
4309: // break;
4310: case 2:
1.1.1.7 ! root 4311: // gen_helper_dmfc0_tracecontrol2(t0); /* PDtrace support */
1.1.1.6 root 4312: rn = "TraceControl2";
4313: // break;
1.1.1.5 root 4314: case 3:
1.1.1.7 ! root 4315: // gen_helper_dmfc0_usertracedata(t0); /* PDtrace support */
1.1.1.6 root 4316: rn = "UserTraceData";
4317: // break;
1.1.1.5 root 4318: case 4:
1.1.1.7 ! root 4319: // gen_helper_dmfc0_tracebpc(t0); /* PDtrace support */
1.1.1.6 root 4320: rn = "TraceBPC";
4321: // break;
1.1.1.5 root 4322: default:
4323: goto die;
4324: }
4325: break;
4326: case 24:
4327: switch (sel) {
4328: case 0:
1.1.1.7 ! root 4329: /* EJTAG support */
! 4330: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 4331: rn = "DEPC";
4332: break;
1.1.1.5 root 4333: default:
4334: goto die;
4335: }
4336: break;
4337: case 25:
4338: switch (sel) {
4339: case 0:
1.1.1.7 ! root 4340: gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
1.1.1.6 root 4341: rn = "Performance0";
1.1.1.5 root 4342: break;
4343: case 1:
1.1.1.7 ! root 4344: // gen_helper_dmfc0_performance1(t0);
1.1.1.6 root 4345: rn = "Performance1";
4346: // break;
1.1.1.5 root 4347: case 2:
1.1.1.7 ! root 4348: // gen_helper_dmfc0_performance2(t0);
1.1.1.6 root 4349: rn = "Performance2";
4350: // break;
1.1.1.5 root 4351: case 3:
1.1.1.7 ! root 4352: // gen_helper_dmfc0_performance3(t0);
1.1.1.6 root 4353: rn = "Performance3";
4354: // break;
1.1.1.5 root 4355: case 4:
1.1.1.7 ! root 4356: // gen_helper_dmfc0_performance4(t0);
1.1.1.6 root 4357: rn = "Performance4";
4358: // break;
1.1.1.5 root 4359: case 5:
1.1.1.7 ! root 4360: // gen_helper_dmfc0_performance5(t0);
1.1.1.6 root 4361: rn = "Performance5";
4362: // break;
1.1.1.5 root 4363: case 6:
1.1.1.7 ! root 4364: // gen_helper_dmfc0_performance6(t0);
1.1.1.6 root 4365: rn = "Performance6";
4366: // break;
1.1.1.5 root 4367: case 7:
1.1.1.7 ! root 4368: // gen_helper_dmfc0_performance7(t0);
1.1.1.6 root 4369: rn = "Performance7";
4370: // break;
1.1.1.5 root 4371: default:
4372: goto die;
4373: }
4374: break;
4375: case 26:
1.1.1.7 ! root 4376: tcg_gen_movi_tl(t0, 0); /* unimplemented */
! 4377: rn = "ECC";
! 4378: break;
1.1.1.5 root 4379: case 27:
4380: switch (sel) {
4381: /* ignored */
4382: case 0 ... 3:
1.1.1.7 ! root 4383: tcg_gen_movi_tl(t0, 0); /* unimplemented */
1.1.1.6 root 4384: rn = "CacheErr";
4385: break;
1.1.1.5 root 4386: default:
4387: goto die;
4388: }
4389: break;
4390: case 28:
4391: switch (sel) {
4392: case 0:
4393: case 2:
4394: case 4:
4395: case 6:
1.1.1.7 ! root 4396: gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
1.1.1.5 root 4397: rn = "TagLo";
4398: break;
4399: case 1:
4400: case 3:
4401: case 5:
4402: case 7:
1.1.1.7 ! root 4403: gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
1.1.1.5 root 4404: rn = "DataLo";
4405: break;
4406: default:
4407: goto die;
4408: }
4409: break;
4410: case 29:
4411: switch (sel) {
4412: case 0:
4413: case 2:
4414: case 4:
4415: case 6:
1.1.1.7 ! root 4416: gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
1.1.1.5 root 4417: rn = "TagHi";
4418: break;
4419: case 1:
4420: case 3:
4421: case 5:
4422: case 7:
1.1.1.7 ! root 4423: gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
1.1.1.5 root 4424: rn = "DataHi";
4425: break;
4426: default:
4427: goto die;
4428: }
4429: break;
4430: case 30:
4431: switch (sel) {
4432: case 0:
1.1.1.7 ! root 4433: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 4434: rn = "ErrorEPC";
4435: break;
1.1.1.5 root 4436: default:
4437: goto die;
4438: }
4439: break;
4440: case 31:
4441: switch (sel) {
4442: case 0:
1.1.1.7 ! root 4443: /* EJTAG support */
! 4444: gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 4445: rn = "DESAVE";
4446: break;
1.1.1.5 root 4447: default:
4448: goto die;
4449: }
4450: break;
4451: default:
1.1.1.6 root 4452: goto die;
1.1.1.5 root 4453: }
1.1.1.7 ! root 4454: LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4455: return;
4456:
4457: die:
1.1.1.7 ! root 4458: LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 4459: generate_exception(ctx, EXCP_RI);
4460: }
4461:
1.1.1.7 ! root 4462: static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
1.1.1.5 root 4463: {
4464: const char *rn = "invalid";
4465:
1.1.1.6 root 4466: if (sel != 0)
4467: check_insn(env, ctx, ISA_MIPS64);
4468:
1.1.1.7 ! root 4469: if (use_icount)
! 4470: gen_io_start();
! 4471:
1.1.1.5 root 4472: switch (reg) {
4473: case 0:
4474: switch (sel) {
4475: case 0:
1.1.1.7 ! root 4476: gen_helper_mtc0_index(t0);
1.1.1.5 root 4477: rn = "Index";
4478: break;
4479: case 1:
1.1.1.6 root 4480: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4481: gen_helper_mtc0_mvpcontrol(t0);
1.1.1.5 root 4482: rn = "MVPControl";
1.1.1.6 root 4483: break;
1.1.1.5 root 4484: case 2:
1.1.1.6 root 4485: check_insn(env, ctx, ASE_MT);
4486: /* ignored */
1.1.1.5 root 4487: rn = "MVPConf0";
1.1.1.6 root 4488: break;
1.1.1.5 root 4489: case 3:
1.1.1.6 root 4490: check_insn(env, ctx, ASE_MT);
4491: /* ignored */
1.1.1.5 root 4492: rn = "MVPConf1";
1.1.1.6 root 4493: break;
1.1.1.5 root 4494: default:
4495: goto die;
4496: }
4497: break;
4498: case 1:
4499: switch (sel) {
4500: case 0:
1.1.1.6 root 4501: /* ignored */
1.1.1.5 root 4502: rn = "Random";
1.1.1.6 root 4503: break;
1.1.1.5 root 4504: case 1:
1.1.1.6 root 4505: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4506: gen_helper_mtc0_vpecontrol(t0);
1.1.1.5 root 4507: rn = "VPEControl";
1.1.1.6 root 4508: break;
1.1.1.5 root 4509: case 2:
1.1.1.6 root 4510: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4511: gen_helper_mtc0_vpeconf0(t0);
1.1.1.5 root 4512: rn = "VPEConf0";
1.1.1.6 root 4513: break;
1.1.1.5 root 4514: case 3:
1.1.1.6 root 4515: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4516: gen_helper_mtc0_vpeconf1(t0);
1.1.1.5 root 4517: rn = "VPEConf1";
1.1.1.6 root 4518: break;
1.1.1.5 root 4519: case 4:
1.1.1.6 root 4520: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4521: gen_helper_mtc0_yqmask(t0);
1.1.1.5 root 4522: rn = "YQMask";
1.1.1.6 root 4523: break;
1.1.1.5 root 4524: case 5:
1.1.1.6 root 4525: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4526: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
1.1.1.5 root 4527: rn = "VPESchedule";
1.1.1.6 root 4528: break;
1.1.1.5 root 4529: case 6:
1.1.1.6 root 4530: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4531: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
1.1.1.5 root 4532: rn = "VPEScheFBack";
1.1.1.6 root 4533: break;
1.1.1.5 root 4534: case 7:
1.1.1.6 root 4535: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4536: gen_helper_mtc0_vpeopt(t0);
1.1.1.5 root 4537: rn = "VPEOpt";
1.1.1.6 root 4538: break;
1.1.1.5 root 4539: default:
4540: goto die;
4541: }
4542: break;
4543: case 2:
4544: switch (sel) {
4545: case 0:
1.1.1.7 ! root 4546: gen_helper_mtc0_entrylo0(t0);
1.1.1.6 root 4547: rn = "EntryLo0";
4548: break;
4549: case 1:
4550: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4551: gen_helper_mtc0_tcstatus(t0);
1.1.1.6 root 4552: rn = "TCStatus";
4553: break;
4554: case 2:
4555: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4556: gen_helper_mtc0_tcbind(t0);
1.1.1.6 root 4557: rn = "TCBind";
4558: break;
1.1.1.5 root 4559: case 3:
1.1.1.6 root 4560: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4561: gen_helper_mtc0_tcrestart(t0);
1.1.1.6 root 4562: rn = "TCRestart";
4563: break;
1.1.1.5 root 4564: case 4:
1.1.1.6 root 4565: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4566: gen_helper_mtc0_tchalt(t0);
1.1.1.6 root 4567: rn = "TCHalt";
4568: break;
1.1.1.5 root 4569: case 5:
1.1.1.6 root 4570: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4571: gen_helper_mtc0_tccontext(t0);
1.1.1.6 root 4572: rn = "TCContext";
4573: break;
1.1.1.5 root 4574: case 6:
1.1.1.6 root 4575: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4576: gen_helper_mtc0_tcschedule(t0);
1.1.1.6 root 4577: rn = "TCSchedule";
4578: break;
1.1.1.5 root 4579: case 7:
1.1.1.6 root 4580: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 4581: gen_helper_mtc0_tcschefback(t0);
1.1.1.6 root 4582: rn = "TCScheFBack";
4583: break;
1.1.1.5 root 4584: default:
4585: goto die;
4586: }
4587: break;
4588: case 3:
4589: switch (sel) {
4590: case 0:
1.1.1.7 ! root 4591: gen_helper_mtc0_entrylo1(t0);
1.1.1.6 root 4592: rn = "EntryLo1";
4593: break;
1.1.1.5 root 4594: default:
4595: goto die;
1.1.1.6 root 4596: }
1.1.1.5 root 4597: break;
4598: case 4:
4599: switch (sel) {
4600: case 0:
1.1.1.7 ! root 4601: gen_helper_mtc0_context(t0);
1.1.1.6 root 4602: rn = "Context";
4603: break;
4604: case 1:
1.1.1.7 ! root 4605: // gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
1.1.1.6 root 4606: rn = "ContextConfig";
4607: // break;
1.1.1.5 root 4608: default:
4609: goto die;
1.1.1.6 root 4610: }
1.1.1.5 root 4611: break;
4612: case 5:
4613: switch (sel) {
4614: case 0:
1.1.1.7 ! root 4615: gen_helper_mtc0_pagemask(t0);
1.1.1.6 root 4616: rn = "PageMask";
4617: break;
4618: case 1:
4619: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4620: gen_helper_mtc0_pagegrain(t0);
1.1.1.6 root 4621: rn = "PageGrain";
4622: break;
1.1.1.5 root 4623: default:
4624: goto die;
1.1.1.6 root 4625: }
1.1.1.5 root 4626: break;
4627: case 6:
4628: switch (sel) {
4629: case 0:
1.1.1.7 ! root 4630: gen_helper_mtc0_wired(t0);
1.1.1.6 root 4631: rn = "Wired";
4632: break;
4633: case 1:
4634: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4635: gen_helper_mtc0_srsconf0(t0);
1.1.1.6 root 4636: rn = "SRSConf0";
4637: break;
4638: case 2:
4639: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4640: gen_helper_mtc0_srsconf1(t0);
1.1.1.6 root 4641: rn = "SRSConf1";
4642: break;
1.1.1.5 root 4643: case 3:
1.1.1.6 root 4644: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4645: gen_helper_mtc0_srsconf2(t0);
1.1.1.6 root 4646: rn = "SRSConf2";
4647: break;
1.1.1.5 root 4648: case 4:
1.1.1.6 root 4649: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4650: gen_helper_mtc0_srsconf3(t0);
1.1.1.6 root 4651: rn = "SRSConf3";
4652: break;
1.1.1.5 root 4653: case 5:
1.1.1.6 root 4654: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4655: gen_helper_mtc0_srsconf4(t0);
1.1.1.6 root 4656: rn = "SRSConf4";
4657: break;
1.1.1.5 root 4658: default:
4659: goto die;
1.1.1.6 root 4660: }
1.1.1.5 root 4661: break;
4662: case 7:
4663: switch (sel) {
4664: case 0:
1.1.1.6 root 4665: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4666: gen_helper_mtc0_hwrena(t0);
1.1.1.6 root 4667: rn = "HWREna";
4668: break;
1.1.1.5 root 4669: default:
4670: goto die;
1.1.1.6 root 4671: }
1.1.1.5 root 4672: break;
4673: case 8:
4674: /* ignored */
1.1.1.7 ! root 4675: rn = "BadVAddr";
1.1.1.5 root 4676: break;
4677: case 9:
4678: switch (sel) {
4679: case 0:
1.1.1.7 ! root 4680: gen_helper_mtc0_count(t0);
1.1.1.6 root 4681: rn = "Count";
4682: break;
4683: /* 6,7 are implementation dependent */
1.1.1.5 root 4684: default:
4685: goto die;
1.1.1.6 root 4686: }
4687: /* Stop translation as we may have switched the execution mode */
4688: ctx->bstate = BS_STOP;
1.1.1.5 root 4689: break;
4690: case 10:
4691: switch (sel) {
4692: case 0:
1.1.1.7 ! root 4693: gen_helper_mtc0_entryhi(t0);
1.1.1.6 root 4694: rn = "EntryHi";
4695: break;
1.1.1.5 root 4696: default:
4697: goto die;
1.1.1.6 root 4698: }
1.1.1.5 root 4699: break;
4700: case 11:
4701: switch (sel) {
4702: case 0:
1.1.1.7 ! root 4703: gen_helper_mtc0_compare(t0);
1.1.1.6 root 4704: rn = "Compare";
4705: break;
4706: /* 6,7 are implementation dependent */
1.1.1.5 root 4707: default:
4708: goto die;
1.1.1.6 root 4709: }
4710: /* Stop translation as we may have switched the execution mode */
4711: ctx->bstate = BS_STOP;
1.1.1.5 root 4712: break;
4713: case 12:
4714: switch (sel) {
4715: case 0:
1.1.1.7 ! root 4716: gen_helper_mtc0_status(t0);
1.1.1.6 root 4717: /* BS_STOP isn't good enough here, hflags may have changed. */
4718: gen_save_pc(ctx->pc + 4);
4719: ctx->bstate = BS_EXCP;
4720: rn = "Status";
4721: break;
4722: case 1:
4723: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4724: gen_helper_mtc0_intctl(t0);
1.1.1.6 root 4725: /* Stop translation as we may have switched the execution mode */
4726: ctx->bstate = BS_STOP;
4727: rn = "IntCtl";
4728: break;
4729: case 2:
4730: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4731: gen_helper_mtc0_srsctl(t0);
1.1.1.6 root 4732: /* Stop translation as we may have switched the execution mode */
4733: ctx->bstate = BS_STOP;
4734: rn = "SRSCtl";
4735: break;
1.1.1.5 root 4736: case 3:
1.1.1.6 root 4737: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4738: gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
1.1.1.6 root 4739: /* Stop translation as we may have switched the execution mode */
4740: ctx->bstate = BS_STOP;
4741: rn = "SRSMap";
4742: break;
1.1.1.5 root 4743: default:
4744: goto die;
1.1.1.6 root 4745: }
1.1.1.5 root 4746: break;
4747: case 13:
4748: switch (sel) {
4749: case 0:
1.1.1.7 ! root 4750: gen_helper_mtc0_cause(t0);
1.1.1.6 root 4751: rn = "Cause";
4752: break;
1.1.1.5 root 4753: default:
4754: goto die;
1.1.1.6 root 4755: }
4756: /* Stop translation as we may have switched the execution mode */
4757: ctx->bstate = BS_STOP;
1.1.1.5 root 4758: break;
4759: case 14:
4760: switch (sel) {
4761: case 0:
1.1.1.7 ! root 4762: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
1.1.1.6 root 4763: rn = "EPC";
4764: break;
1.1.1.5 root 4765: default:
4766: goto die;
1.1.1.6 root 4767: }
1.1.1.5 root 4768: break;
4769: case 15:
4770: switch (sel) {
4771: case 0:
1.1.1.6 root 4772: /* ignored */
4773: rn = "PRid";
4774: break;
4775: case 1:
4776: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 4777: gen_helper_mtc0_ebase(t0);
1.1.1.6 root 4778: rn = "EBase";
4779: break;
1.1.1.5 root 4780: default:
4781: goto die;
1.1.1.6 root 4782: }
1.1.1.5 root 4783: break;
4784: case 16:
4785: switch (sel) {
4786: case 0:
1.1.1.7 ! root 4787: gen_helper_mtc0_config0(t0);
1.1.1.5 root 4788: rn = "Config";
1.1.1.6 root 4789: /* Stop translation as we may have switched the execution mode */
4790: ctx->bstate = BS_STOP;
1.1.1.5 root 4791: break;
4792: case 1:
1.1.1.6 root 4793: /* ignored */
1.1.1.5 root 4794: rn = "Config1";
4795: break;
4796: case 2:
1.1.1.7 ! root 4797: gen_helper_mtc0_config2(t0);
1.1.1.5 root 4798: rn = "Config2";
1.1.1.6 root 4799: /* Stop translation as we may have switched the execution mode */
4800: ctx->bstate = BS_STOP;
1.1.1.5 root 4801: break;
4802: case 3:
1.1.1.6 root 4803: /* ignored */
1.1.1.5 root 4804: rn = "Config3";
4805: break;
4806: /* 6,7 are implementation dependent */
4807: default:
4808: rn = "Invalid config selector";
4809: goto die;
4810: }
4811: break;
4812: case 17:
4813: switch (sel) {
4814: case 0:
1.1.1.6 root 4815: /* ignored */
4816: rn = "LLAddr";
4817: break;
1.1.1.5 root 4818: default:
4819: goto die;
4820: }
4821: break;
4822: case 18:
4823: switch (sel) {
1.1.1.6 root 4824: case 0 ... 7:
1.1.1.7 ! root 4825: gen_helper_1i(mtc0_watchlo, t0, sel);
1.1.1.6 root 4826: rn = "WatchLo";
4827: break;
1.1.1.5 root 4828: default:
4829: goto die;
4830: }
4831: break;
4832: case 19:
4833: switch (sel) {
1.1.1.6 root 4834: case 0 ... 7:
1.1.1.7 ! root 4835: gen_helper_1i(mtc0_watchhi, t0, sel);
1.1.1.6 root 4836: rn = "WatchHi";
4837: break;
1.1.1.5 root 4838: default:
4839: goto die;
4840: }
4841: break;
4842: case 20:
4843: switch (sel) {
4844: case 0:
1.1.1.6 root 4845: check_insn(env, ctx, ISA_MIPS3);
1.1.1.7 ! root 4846: gen_helper_mtc0_xcontext(t0);
1.1.1.6 root 4847: rn = "XContext";
4848: break;
1.1.1.5 root 4849: default:
4850: goto die;
4851: }
4852: break;
4853: case 21:
4854: /* Officially reserved, but sel 0 is used for R1x000 framemask */
4855: switch (sel) {
4856: case 0:
1.1.1.7 ! root 4857: gen_helper_mtc0_framemask(t0);
1.1.1.6 root 4858: rn = "Framemask";
4859: break;
1.1.1.5 root 4860: default:
4861: goto die;
4862: }
4863: break;
4864: case 22:
4865: /* ignored */
4866: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 root 4867: break;
1.1.1.5 root 4868: case 23:
4869: switch (sel) {
4870: case 0:
1.1.1.7 ! root 4871: gen_helper_mtc0_debug(t0); /* EJTAG support */
1.1.1.6 root 4872: /* BS_STOP isn't good enough here, hflags may have changed. */
4873: gen_save_pc(ctx->pc + 4);
4874: ctx->bstate = BS_EXCP;
4875: rn = "Debug";
4876: break;
4877: case 1:
1.1.1.7 ! root 4878: // gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
1.1.1.6 root 4879: /* Stop translation as we may have switched the execution mode */
4880: ctx->bstate = BS_STOP;
4881: rn = "TraceControl";
4882: // break;
4883: case 2:
1.1.1.7 ! root 4884: // gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
1.1.1.6 root 4885: /* Stop translation as we may have switched the execution mode */
4886: ctx->bstate = BS_STOP;
4887: rn = "TraceControl2";
4888: // break;
4889: case 3:
1.1.1.7 ! root 4890: // gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
1.1.1.6 root 4891: /* Stop translation as we may have switched the execution mode */
4892: ctx->bstate = BS_STOP;
4893: rn = "UserTraceData";
4894: // break;
1.1.1.5 root 4895: case 4:
1.1.1.7 ! root 4896: // gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
1.1.1.6 root 4897: /* Stop translation as we may have switched the execution mode */
4898: ctx->bstate = BS_STOP;
4899: rn = "TraceBPC";
4900: // break;
1.1.1.5 root 4901: default:
4902: goto die;
4903: }
4904: break;
4905: case 24:
4906: switch (sel) {
4907: case 0:
1.1.1.7 ! root 4908: /* EJTAG support */
! 4909: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
1.1.1.6 root 4910: rn = "DEPC";
4911: break;
1.1.1.5 root 4912: default:
4913: goto die;
4914: }
4915: break;
4916: case 25:
4917: switch (sel) {
4918: case 0:
1.1.1.7 ! root 4919: gen_helper_mtc0_performance0(t0);
1.1.1.6 root 4920: rn = "Performance0";
4921: break;
4922: case 1:
1.1.1.7 ! root 4923: // gen_helper_mtc0_performance1(t0);
1.1.1.6 root 4924: rn = "Performance1";
4925: // break;
4926: case 2:
1.1.1.7 ! root 4927: // gen_helper_mtc0_performance2(t0);
1.1.1.6 root 4928: rn = "Performance2";
4929: // break;
1.1.1.5 root 4930: case 3:
1.1.1.7 ! root 4931: // gen_helper_mtc0_performance3(t0);
1.1.1.6 root 4932: rn = "Performance3";
4933: // break;
1.1.1.5 root 4934: case 4:
1.1.1.7 ! root 4935: // gen_helper_mtc0_performance4(t0);
1.1.1.6 root 4936: rn = "Performance4";
4937: // break;
1.1.1.5 root 4938: case 5:
1.1.1.7 ! root 4939: // gen_helper_mtc0_performance5(t0);
1.1.1.6 root 4940: rn = "Performance5";
4941: // break;
1.1.1.5 root 4942: case 6:
1.1.1.7 ! root 4943: // gen_helper_mtc0_performance6(t0);
1.1.1.6 root 4944: rn = "Performance6";
4945: // break;
1.1.1.5 root 4946: case 7:
1.1.1.7 ! root 4947: // gen_helper_mtc0_performance7(t0);
1.1.1.6 root 4948: rn = "Performance7";
4949: // break;
1.1.1.5 root 4950: default:
4951: goto die;
4952: }
1.1.1.6 root 4953: break;
1.1.1.5 root 4954: case 26:
1.1.1.6 root 4955: /* ignored */
1.1.1.5 root 4956: rn = "ECC";
1.1.1.6 root 4957: break;
1.1.1.5 root 4958: case 27:
4959: switch (sel) {
4960: case 0 ... 3:
1.1.1.6 root 4961: /* ignored */
4962: rn = "CacheErr";
4963: break;
1.1.1.5 root 4964: default:
4965: goto die;
4966: }
1.1.1.6 root 4967: break;
1.1.1.5 root 4968: case 28:
4969: switch (sel) {
4970: case 0:
4971: case 2:
4972: case 4:
4973: case 6:
1.1.1.7 ! root 4974: gen_helper_mtc0_taglo(t0);
1.1.1.5 root 4975: rn = "TagLo";
4976: break;
4977: case 1:
4978: case 3:
4979: case 5:
4980: case 7:
1.1.1.7 ! root 4981: gen_helper_mtc0_datalo(t0);
1.1.1.5 root 4982: rn = "DataLo";
4983: break;
4984: default:
4985: goto die;
4986: }
4987: break;
4988: case 29:
4989: switch (sel) {
4990: case 0:
4991: case 2:
4992: case 4:
4993: case 6:
1.1.1.7 ! root 4994: gen_helper_mtc0_taghi(t0);
1.1.1.5 root 4995: rn = "TagHi";
4996: break;
4997: case 1:
4998: case 3:
4999: case 5:
5000: case 7:
1.1.1.7 ! root 5001: gen_helper_mtc0_datahi(t0);
1.1.1.5 root 5002: rn = "DataHi";
5003: break;
5004: default:
5005: rn = "invalid sel";
5006: goto die;
5007: }
1.1.1.6 root 5008: break;
1.1.1.5 root 5009: case 30:
5010: switch (sel) {
5011: case 0:
1.1.1.7 ! root 5012: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
1.1.1.6 root 5013: rn = "ErrorEPC";
5014: break;
1.1.1.5 root 5015: default:
5016: goto die;
5017: }
5018: break;
5019: case 31:
5020: switch (sel) {
5021: case 0:
1.1.1.7 ! root 5022: /* EJTAG support */
! 5023: gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
1.1.1.6 root 5024: rn = "DESAVE";
5025: break;
1.1.1.5 root 5026: default:
5027: goto die;
5028: }
1.1.1.6 root 5029: /* Stop translation as we may have switched the execution mode */
5030: ctx->bstate = BS_STOP;
1.1.1.5 root 5031: break;
5032: default:
1.1.1.6 root 5033: goto die;
1.1.1.5 root 5034: }
1.1.1.7 ! root 5035: LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
! 5036: /* For simplicity assume that all writes can cause interrupts. */
! 5037: if (use_icount) {
! 5038: gen_io_end();
! 5039: ctx->bstate = BS_STOP;
1.1.1.5 root 5040: }
5041: return;
5042:
5043: die:
1.1.1.7 ! root 5044: LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
1.1.1.5 root 5045: generate_exception(ctx, EXCP_RI);
5046: }
1.1.1.6 root 5047: #endif /* TARGET_MIPS64 */
1.1.1.5 root 5048:
1.1.1.7 ! root 5049: static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
1.1.1.6 root 5050: int u, int sel, int h)
1.1.1.5 root 5051: {
1.1.1.6 root 5052: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.7 ! root 5053: TCGv t0 = tcg_temp_local_new();
1.1.1.5 root 5054:
1.1.1.6 root 5055: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
1.1.1.7 ! root 5056: ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
! 5057: (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
! 5058: tcg_gen_movi_tl(t0, -1);
1.1.1.6 root 5059: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5060: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1.1.1.7 ! root 5061: tcg_gen_movi_tl(t0, -1);
1.1.1.6 root 5062: else if (u == 0) {
5063: switch (rt) {
5064: case 2:
5065: switch (sel) {
5066: case 1:
1.1.1.7 ! root 5067: gen_helper_mftc0_tcstatus(t0);
1.1.1.6 root 5068: break;
5069: case 2:
1.1.1.7 ! root 5070: gen_helper_mftc0_tcbind(t0);
1.1.1.6 root 5071: break;
5072: case 3:
1.1.1.7 ! root 5073: gen_helper_mftc0_tcrestart(t0);
1.1.1.6 root 5074: break;
5075: case 4:
1.1.1.7 ! root 5076: gen_helper_mftc0_tchalt(t0);
1.1.1.6 root 5077: break;
5078: case 5:
1.1.1.7 ! root 5079: gen_helper_mftc0_tccontext(t0);
1.1.1.6 root 5080: break;
5081: case 6:
1.1.1.7 ! root 5082: gen_helper_mftc0_tcschedule(t0);
1.1.1.6 root 5083: break;
5084: case 7:
1.1.1.7 ! root 5085: gen_helper_mftc0_tcschefback(t0);
1.1.1.6 root 5086: break;
5087: default:
1.1.1.7 ! root 5088: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5089: break;
5090: }
5091: break;
5092: case 10:
5093: switch (sel) {
5094: case 0:
1.1.1.7 ! root 5095: gen_helper_mftc0_entryhi(t0);
1.1.1.6 root 5096: break;
5097: default:
1.1.1.7 ! root 5098: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5099: break;
5100: }
5101: case 12:
5102: switch (sel) {
5103: case 0:
1.1.1.7 ! root 5104: gen_helper_mftc0_status(t0);
1.1.1.6 root 5105: break;
5106: default:
1.1.1.7 ! root 5107: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5108: break;
5109: }
5110: case 23:
5111: switch (sel) {
5112: case 0:
1.1.1.7 ! root 5113: gen_helper_mftc0_debug(t0);
1.1.1.6 root 5114: break;
5115: default:
1.1.1.7 ! root 5116: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5117: break;
5118: }
5119: break;
5120: default:
1.1.1.7 ! root 5121: gen_mfc0(env, ctx, t0, rt, sel);
1.1.1.6 root 5122: }
5123: } else switch (sel) {
5124: /* GPR registers. */
5125: case 0:
1.1.1.7 ! root 5126: gen_helper_1i(mftgpr, t0, rt);
1.1.1.6 root 5127: break;
5128: /* Auxiliary CPU registers */
5129: case 1:
5130: switch (rt) {
5131: case 0:
1.1.1.7 ! root 5132: gen_helper_1i(mftlo, t0, 0);
1.1.1.6 root 5133: break;
5134: case 1:
1.1.1.7 ! root 5135: gen_helper_1i(mfthi, t0, 0);
1.1.1.6 root 5136: break;
5137: case 2:
1.1.1.7 ! root 5138: gen_helper_1i(mftacx, t0, 0);
1.1.1.6 root 5139: break;
5140: case 4:
1.1.1.7 ! root 5141: gen_helper_1i(mftlo, t0, 1);
1.1.1.6 root 5142: break;
5143: case 5:
1.1.1.7 ! root 5144: gen_helper_1i(mfthi, t0, 1);
1.1.1.6 root 5145: break;
5146: case 6:
1.1.1.7 ! root 5147: gen_helper_1i(mftacx, t0, 1);
1.1.1.6 root 5148: break;
5149: case 8:
1.1.1.7 ! root 5150: gen_helper_1i(mftlo, t0, 2);
1.1.1.6 root 5151: break;
5152: case 9:
1.1.1.7 ! root 5153: gen_helper_1i(mfthi, t0, 2);
1.1.1.6 root 5154: break;
5155: case 10:
1.1.1.7 ! root 5156: gen_helper_1i(mftacx, t0, 2);
1.1.1.6 root 5157: break;
5158: case 12:
1.1.1.7 ! root 5159: gen_helper_1i(mftlo, t0, 3);
1.1.1.6 root 5160: break;
5161: case 13:
1.1.1.7 ! root 5162: gen_helper_1i(mfthi, t0, 3);
1.1.1.6 root 5163: break;
5164: case 14:
1.1.1.7 ! root 5165: gen_helper_1i(mftacx, t0, 3);
1.1.1.6 root 5166: break;
5167: case 16:
1.1.1.7 ! root 5168: gen_helper_mftdsp(t0);
1.1.1.6 root 5169: break;
5170: default:
5171: goto die;
5172: }
5173: break;
5174: /* Floating point (COP1). */
5175: case 2:
5176: /* XXX: For now we support only a single FPU context. */
5177: if (h == 0) {
1.1.1.7 ! root 5178: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5179:
! 5180: gen_load_fpr32(fp0, rt);
! 5181: tcg_gen_ext_i32_tl(t0, fp0);
! 5182: tcg_temp_free_i32(fp0);
1.1.1.6 root 5183: } else {
1.1.1.7 ! root 5184: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5185:
! 5186: gen_load_fpr32h(fp0, rt);
! 5187: tcg_gen_ext_i32_tl(t0, fp0);
! 5188: tcg_temp_free_i32(fp0);
1.1.1.6 root 5189: }
5190: break;
5191: case 3:
5192: /* XXX: For now we support only a single FPU context. */
1.1.1.7 ! root 5193: gen_helper_1i(cfc1, t0, rt);
1.1.1.6 root 5194: break;
5195: /* COP2: Not implemented. */
5196: case 4:
5197: case 5:
5198: /* fall through */
5199: default:
5200: goto die;
5201: }
1.1.1.7 ! root 5202: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
! 5203: gen_store_gpr(t0, rd);
! 5204: tcg_temp_free(t0);
1.1.1.6 root 5205: return;
5206:
5207: die:
1.1.1.7 ! root 5208: tcg_temp_free(t0);
! 5209: LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1.1.1.6 root 5210: generate_exception(ctx, EXCP_RI);
5211: }
5212:
1.1.1.7 ! root 5213: static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
1.1.1.6 root 5214: int u, int sel, int h)
5215: {
5216: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.7 ! root 5217: TCGv t0 = tcg_temp_local_new();
1.1.1.6 root 5218:
1.1.1.7 ! root 5219: gen_load_gpr(t0, rt);
1.1.1.6 root 5220: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
1.1.1.7 ! root 5221: ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
! 5222: (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1.1.1.6 root 5223: /* NOP */ ;
5224: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5225: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5226: /* NOP */ ;
5227: else if (u == 0) {
5228: switch (rd) {
5229: case 2:
5230: switch (sel) {
5231: case 1:
1.1.1.7 ! root 5232: gen_helper_mttc0_tcstatus(t0);
1.1.1.6 root 5233: break;
5234: case 2:
1.1.1.7 ! root 5235: gen_helper_mttc0_tcbind(t0);
1.1.1.6 root 5236: break;
5237: case 3:
1.1.1.7 ! root 5238: gen_helper_mttc0_tcrestart(t0);
1.1.1.6 root 5239: break;
5240: case 4:
1.1.1.7 ! root 5241: gen_helper_mttc0_tchalt(t0);
1.1.1.6 root 5242: break;
5243: case 5:
1.1.1.7 ! root 5244: gen_helper_mttc0_tccontext(t0);
1.1.1.6 root 5245: break;
5246: case 6:
1.1.1.7 ! root 5247: gen_helper_mttc0_tcschedule(t0);
1.1.1.6 root 5248: break;
5249: case 7:
1.1.1.7 ! root 5250: gen_helper_mttc0_tcschefback(t0);
1.1.1.6 root 5251: break;
5252: default:
1.1.1.7 ! root 5253: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5254: break;
5255: }
5256: break;
5257: case 10:
5258: switch (sel) {
5259: case 0:
1.1.1.7 ! root 5260: gen_helper_mttc0_entryhi(t0);
1.1.1.6 root 5261: break;
5262: default:
1.1.1.7 ! root 5263: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5264: break;
5265: }
5266: case 12:
5267: switch (sel) {
5268: case 0:
1.1.1.7 ! root 5269: gen_helper_mttc0_status(t0);
1.1.1.6 root 5270: break;
5271: default:
1.1.1.7 ! root 5272: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5273: break;
5274: }
5275: case 23:
5276: switch (sel) {
5277: case 0:
1.1.1.7 ! root 5278: gen_helper_mttc0_debug(t0);
1.1.1.6 root 5279: break;
5280: default:
1.1.1.7 ! root 5281: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5282: break;
5283: }
5284: break;
5285: default:
1.1.1.7 ! root 5286: gen_mtc0(env, ctx, t0, rd, sel);
1.1.1.6 root 5287: }
5288: } else switch (sel) {
5289: /* GPR registers. */
5290: case 0:
1.1.1.7 ! root 5291: gen_helper_1i(mttgpr, t0, rd);
1.1.1.6 root 5292: break;
5293: /* Auxiliary CPU registers */
5294: case 1:
5295: switch (rd) {
5296: case 0:
1.1.1.7 ! root 5297: gen_helper_1i(mttlo, t0, 0);
1.1.1.6 root 5298: break;
5299: case 1:
1.1.1.7 ! root 5300: gen_helper_1i(mtthi, t0, 0);
1.1.1.6 root 5301: break;
5302: case 2:
1.1.1.7 ! root 5303: gen_helper_1i(mttacx, t0, 0);
1.1.1.6 root 5304: break;
5305: case 4:
1.1.1.7 ! root 5306: gen_helper_1i(mttlo, t0, 1);
1.1.1.6 root 5307: break;
5308: case 5:
1.1.1.7 ! root 5309: gen_helper_1i(mtthi, t0, 1);
1.1.1.6 root 5310: break;
5311: case 6:
1.1.1.7 ! root 5312: gen_helper_1i(mttacx, t0, 1);
1.1.1.6 root 5313: break;
5314: case 8:
1.1.1.7 ! root 5315: gen_helper_1i(mttlo, t0, 2);
1.1.1.6 root 5316: break;
5317: case 9:
1.1.1.7 ! root 5318: gen_helper_1i(mtthi, t0, 2);
1.1.1.6 root 5319: break;
5320: case 10:
1.1.1.7 ! root 5321: gen_helper_1i(mttacx, t0, 2);
1.1.1.6 root 5322: break;
5323: case 12:
1.1.1.7 ! root 5324: gen_helper_1i(mttlo, t0, 3);
1.1.1.6 root 5325: break;
5326: case 13:
1.1.1.7 ! root 5327: gen_helper_1i(mtthi, t0, 3);
1.1.1.6 root 5328: break;
5329: case 14:
1.1.1.7 ! root 5330: gen_helper_1i(mttacx, t0, 3);
1.1.1.6 root 5331: break;
5332: case 16:
1.1.1.7 ! root 5333: gen_helper_mttdsp(t0);
1.1.1.6 root 5334: break;
5335: default:
5336: goto die;
5337: }
5338: break;
5339: /* Floating point (COP1). */
5340: case 2:
5341: /* XXX: For now we support only a single FPU context. */
5342: if (h == 0) {
1.1.1.7 ! root 5343: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5344:
! 5345: tcg_gen_trunc_tl_i32(fp0, t0);
! 5346: gen_store_fpr32(fp0, rd);
! 5347: tcg_temp_free_i32(fp0);
1.1.1.6 root 5348: } else {
1.1.1.7 ! root 5349: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5350:
! 5351: tcg_gen_trunc_tl_i32(fp0, t0);
! 5352: gen_store_fpr32h(fp0, rd);
! 5353: tcg_temp_free_i32(fp0);
1.1.1.6 root 5354: }
5355: break;
5356: case 3:
5357: /* XXX: For now we support only a single FPU context. */
1.1.1.7 ! root 5358: gen_helper_1i(ctc1, t0, rd);
1.1.1.6 root 5359: break;
5360: /* COP2: Not implemented. */
5361: case 4:
5362: case 5:
5363: /* fall through */
5364: default:
5365: goto die;
5366: }
1.1.1.7 ! root 5367: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
! 5368: tcg_temp_free(t0);
1.1.1.6 root 5369: return;
5370:
5371: die:
1.1.1.7 ! root 5372: tcg_temp_free(t0);
! 5373: LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1.1.1.6 root 5374: generate_exception(ctx, EXCP_RI);
5375: }
5376:
5377: static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5378: {
5379: const char *opn = "ldst";
1.1.1.5 root 5380:
5381: switch (opc) {
5382: case OPC_MFC0:
5383: if (rt == 0) {
1.1.1.6 root 5384: /* Treat as NOP. */
1.1.1.5 root 5385: return;
5386: }
1.1.1.7 ! root 5387: {
! 5388: TCGv t0 = tcg_temp_local_new();
! 5389:
! 5390: gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
! 5391: gen_store_gpr(t0, rt);
! 5392: tcg_temp_free(t0);
! 5393: }
1.1.1.5 root 5394: opn = "mfc0";
5395: break;
5396: case OPC_MTC0:
1.1.1.7 ! root 5397: {
! 5398: TCGv t0 = tcg_temp_local_new();
! 5399:
! 5400: gen_load_gpr(t0, rt);
! 5401: save_cpu_state(ctx, 1);
! 5402: gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
! 5403: tcg_temp_free(t0);
! 5404: }
1.1.1.5 root 5405: opn = "mtc0";
5406: break;
1.1.1.6 root 5407: #if defined(TARGET_MIPS64)
1.1.1.5 root 5408: case OPC_DMFC0:
1.1.1.6 root 5409: check_insn(env, ctx, ISA_MIPS3);
1.1.1.5 root 5410: if (rt == 0) {
1.1.1.6 root 5411: /* Treat as NOP. */
1.1.1.5 root 5412: return;
5413: }
1.1.1.7 ! root 5414: {
! 5415: TCGv t0 = tcg_temp_local_new();
! 5416:
! 5417: gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
! 5418: gen_store_gpr(t0, rt);
! 5419: tcg_temp_free(t0);
! 5420: }
1.1.1.5 root 5421: opn = "dmfc0";
5422: break;
5423: case OPC_DMTC0:
1.1.1.6 root 5424: check_insn(env, ctx, ISA_MIPS3);
1.1.1.7 ! root 5425: {
! 5426: TCGv t0 = tcg_temp_local_new();
! 5427:
! 5428: gen_load_gpr(t0, rt);
! 5429: save_cpu_state(ctx, 1);
! 5430: gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
! 5431: tcg_temp_free(t0);
! 5432: }
1.1.1.5 root 5433: opn = "dmtc0";
5434: break;
1.1.1.6 root 5435: #endif
5436: case OPC_MFTR:
5437: check_insn(env, ctx, ASE_MT);
5438: if (rd == 0) {
5439: /* Treat as NOP. */
5440: return;
5441: }
1.1.1.7 ! root 5442: gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5443: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5444: opn = "mftr";
5445: break;
5446: case OPC_MTTR:
5447: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 5448: gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
1.1.1.6 root 5449: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5450: opn = "mttr";
5451: break;
1.1.1.5 root 5452: case OPC_TLBWI:
5453: opn = "tlbwi";
1.1.1.6 root 5454: if (!env->tlb->do_tlbwi)
5455: goto die;
1.1.1.7 ! root 5456: gen_helper_tlbwi();
1.1.1.5 root 5457: break;
5458: case OPC_TLBWR:
5459: opn = "tlbwr";
1.1.1.6 root 5460: if (!env->tlb->do_tlbwr)
5461: goto die;
1.1.1.7 ! root 5462: gen_helper_tlbwr();
1.1.1.5 root 5463: break;
5464: case OPC_TLBP:
5465: opn = "tlbp";
1.1.1.6 root 5466: if (!env->tlb->do_tlbp)
5467: goto die;
1.1.1.7 ! root 5468: gen_helper_tlbp();
1.1.1.5 root 5469: break;
5470: case OPC_TLBR:
5471: opn = "tlbr";
1.1.1.6 root 5472: if (!env->tlb->do_tlbr)
5473: goto die;
1.1.1.7 ! root 5474: gen_helper_tlbr();
1.1.1.5 root 5475: break;
5476: case OPC_ERET:
5477: opn = "eret";
1.1.1.6 root 5478: check_insn(env, ctx, ISA_MIPS2);
5479: save_cpu_state(ctx, 1);
1.1.1.7 ! root 5480: gen_helper_eret();
1.1.1.5 root 5481: ctx->bstate = BS_EXCP;
5482: break;
5483: case OPC_DERET:
5484: opn = "deret";
1.1.1.6 root 5485: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 5486: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1.1.1.6 root 5487: MIPS_INVAL(opn);
1.1.1.5 root 5488: generate_exception(ctx, EXCP_RI);
5489: } else {
1.1.1.6 root 5490: save_cpu_state(ctx, 1);
1.1.1.7 ! root 5491: gen_helper_deret();
1.1.1.5 root 5492: ctx->bstate = BS_EXCP;
5493: }
5494: break;
5495: case OPC_WAIT:
5496: opn = "wait";
1.1.1.6 root 5497: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
1.1.1.5 root 5498: /* If we get an exception, we want to restart at next instruction */
5499: ctx->pc += 4;
5500: save_cpu_state(ctx, 1);
5501: ctx->pc -= 4;
1.1.1.7 ! root 5502: gen_helper_wait();
1.1.1.5 root 5503: ctx->bstate = BS_EXCP;
5504: break;
5505: default:
1.1.1.6 root 5506: die:
5507: MIPS_INVAL(opn);
1.1.1.5 root 5508: generate_exception(ctx, EXCP_RI);
5509: return;
5510: }
5511: MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5512: }
1.1.1.7 ! root 5513: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 5514:
5515: /* CP1 Branches (before delay slot) */
1.1.1.6 root 5516: static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5517: int32_t cc, int32_t offset)
1.1.1.5 root 5518: {
5519: target_ulong btarget;
1.1.1.6 root 5520: const char *opn = "cp1 cond branch";
1.1.1.7 ! root 5521: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.6 root 5522:
5523: if (cc != 0)
5524: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
1.1.1.5 root 5525:
5526: btarget = ctx->pc + 4 + offset;
5527:
5528: switch (op) {
5529: case OPC_BC1F:
1.1.1.7 ! root 5530: {
! 5531: int l1 = gen_new_label();
! 5532: int l2 = gen_new_label();
! 5533:
! 5534: get_fp_cond(t0);
! 5535: tcg_gen_andi_i32(t0, t0, 0x1 << cc);
! 5536: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
! 5537: tcg_gen_movi_i32(bcond, 0);
! 5538: tcg_gen_br(l2);
! 5539: gen_set_label(l1);
! 5540: tcg_gen_movi_i32(bcond, 1);
! 5541: gen_set_label(l2);
! 5542: }
1.1.1.6 root 5543: opn = "bc1f";
1.1.1.5 root 5544: goto not_likely;
5545: case OPC_BC1FL:
1.1.1.7 ! root 5546: {
! 5547: int l1 = gen_new_label();
! 5548: int l2 = gen_new_label();
! 5549:
! 5550: get_fp_cond(t0);
! 5551: tcg_gen_andi_i32(t0, t0, 0x1 << cc);
! 5552: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
! 5553: tcg_gen_movi_i32(bcond, 0);
! 5554: tcg_gen_br(l2);
! 5555: gen_set_label(l1);
! 5556: tcg_gen_movi_i32(bcond, 1);
! 5557: gen_set_label(l2);
! 5558: }
1.1.1.6 root 5559: opn = "bc1fl";
1.1.1.5 root 5560: goto likely;
5561: case OPC_BC1T:
1.1.1.7 ! root 5562: {
! 5563: int l1 = gen_new_label();
! 5564: int l2 = gen_new_label();
! 5565:
! 5566: get_fp_cond(t0);
! 5567: tcg_gen_andi_i32(t0, t0, 0x1 << cc);
! 5568: tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
! 5569: tcg_gen_movi_i32(bcond, 0);
! 5570: tcg_gen_br(l2);
! 5571: gen_set_label(l1);
! 5572: tcg_gen_movi_i32(bcond, 1);
! 5573: gen_set_label(l2);
! 5574: }
1.1.1.6 root 5575: opn = "bc1t";
5576: goto not_likely;
1.1.1.5 root 5577: case OPC_BC1TL:
1.1.1.7 ! root 5578: {
! 5579: int l1 = gen_new_label();
! 5580: int l2 = gen_new_label();
! 5581:
! 5582: get_fp_cond(t0);
! 5583: tcg_gen_andi_i32(t0, t0, 0x1 << cc);
! 5584: tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
! 5585: tcg_gen_movi_i32(bcond, 0);
! 5586: tcg_gen_br(l2);
! 5587: gen_set_label(l1);
! 5588: tcg_gen_movi_i32(bcond, 1);
! 5589: gen_set_label(l2);
! 5590: }
1.1.1.6 root 5591: opn = "bc1tl";
1.1.1.5 root 5592: likely:
5593: ctx->hflags |= MIPS_HFLAG_BL;
1.1.1.6 root 5594: break;
5595: case OPC_BC1FANY2:
1.1.1.7 ! root 5596: {
! 5597: int l1 = gen_new_label();
! 5598: int l2 = gen_new_label();
! 5599:
! 5600: get_fp_cond(t0);
! 5601: tcg_gen_andi_i32(t0, t0, 0x3 << cc);
! 5602: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
! 5603: tcg_gen_movi_i32(bcond, 0);
! 5604: tcg_gen_br(l2);
! 5605: gen_set_label(l1);
! 5606: tcg_gen_movi_i32(bcond, 1);
! 5607: gen_set_label(l2);
! 5608: }
1.1.1.6 root 5609: opn = "bc1any2f";
5610: goto not_likely;
5611: case OPC_BC1TANY2:
1.1.1.7 ! root 5612: {
! 5613: int l1 = gen_new_label();
! 5614: int l2 = gen_new_label();
! 5615:
! 5616: get_fp_cond(t0);
! 5617: tcg_gen_andi_i32(t0, t0, 0x3 << cc);
! 5618: tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
! 5619: tcg_gen_movi_i32(bcond, 0);
! 5620: tcg_gen_br(l2);
! 5621: gen_set_label(l1);
! 5622: tcg_gen_movi_i32(bcond, 1);
! 5623: gen_set_label(l2);
! 5624: }
1.1.1.6 root 5625: opn = "bc1any2t";
5626: goto not_likely;
5627: case OPC_BC1FANY4:
1.1.1.7 ! root 5628: {
! 5629: int l1 = gen_new_label();
! 5630: int l2 = gen_new_label();
! 5631:
! 5632: get_fp_cond(t0);
! 5633: tcg_gen_andi_i32(t0, t0, 0xf << cc);
! 5634: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
! 5635: tcg_gen_movi_i32(bcond, 0);
! 5636: tcg_gen_br(l2);
! 5637: gen_set_label(l1);
! 5638: tcg_gen_movi_i32(bcond, 1);
! 5639: gen_set_label(l2);
! 5640: }
1.1.1.6 root 5641: opn = "bc1any4f";
5642: goto not_likely;
5643: case OPC_BC1TANY4:
1.1.1.7 ! root 5644: {
! 5645: int l1 = gen_new_label();
! 5646: int l2 = gen_new_label();
! 5647:
! 5648: get_fp_cond(t0);
! 5649: tcg_gen_andi_i32(t0, t0, 0xf << cc);
! 5650: tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
! 5651: tcg_gen_movi_i32(bcond, 0);
! 5652: tcg_gen_br(l2);
! 5653: gen_set_label(l1);
! 5654: tcg_gen_movi_i32(bcond, 1);
! 5655: gen_set_label(l2);
! 5656: }
1.1.1.6 root 5657: opn = "bc1any4t";
5658: not_likely:
5659: ctx->hflags |= MIPS_HFLAG_BC;
1.1.1.5 root 5660: break;
1.1.1.6 root 5661: default:
5662: MIPS_INVAL(opn);
5663: generate_exception (ctx, EXCP_RI);
1.1.1.7 ! root 5664: goto out;
1.1.1.5 root 5665: }
1.1.1.6 root 5666: MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
1.1.1.5 root 5667: ctx->hflags, btarget);
5668: ctx->btarget = btarget;
1.1.1.7 ! root 5669:
! 5670: out:
! 5671: tcg_temp_free_i32(t0);
1.1.1.5 root 5672: }
5673:
5674: /* Coprocessor 1 (FPU) */
1.1.1.6 root 5675:
5676: #define FOP(func, fmt) (((fmt) << 21) | (func))
5677:
1.1.1.5 root 5678: static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5679: {
1.1.1.6 root 5680: const char *opn = "cp1 move";
1.1.1.7 ! root 5681: TCGv t0 = tcg_temp_local_new();
1.1.1.5 root 5682:
5683: switch (opc) {
5684: case OPC_MFC1:
1.1.1.7 ! root 5685: {
! 5686: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5687:
! 5688: gen_load_fpr32(fp0, fs);
! 5689: tcg_gen_ext_i32_tl(t0, fp0);
! 5690: tcg_temp_free_i32(fp0);
! 5691: }
! 5692: gen_store_gpr(t0, rt);
1.1.1.5 root 5693: opn = "mfc1";
5694: break;
5695: case OPC_MTC1:
1.1.1.7 ! root 5696: gen_load_gpr(t0, rt);
! 5697: {
! 5698: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5699:
! 5700: tcg_gen_trunc_tl_i32(fp0, t0);
! 5701: gen_store_fpr32(fp0, fs);
! 5702: tcg_temp_free_i32(fp0);
! 5703: }
1.1.1.5 root 5704: opn = "mtc1";
5705: break;
5706: case OPC_CFC1:
1.1.1.7 ! root 5707: gen_helper_1i(cfc1, t0, fs);
! 5708: gen_store_gpr(t0, rt);
1.1.1.5 root 5709: opn = "cfc1";
5710: break;
5711: case OPC_CTC1:
1.1.1.7 ! root 5712: gen_load_gpr(t0, rt);
! 5713: gen_helper_1i(ctc1, t0, fs);
1.1.1.5 root 5714: opn = "ctc1";
5715: break;
5716: case OPC_DMFC1:
1.1.1.7 ! root 5717: {
! 5718: TCGv_i64 fp0 = tcg_temp_new_i64();
! 5719:
! 5720: gen_load_fpr64(ctx, fp0, fs);
! 5721: tcg_gen_trunc_i64_tl(t0, fp0);
! 5722: tcg_temp_free_i64(fp0);
! 5723: }
! 5724: gen_store_gpr(t0, rt);
1.1.1.6 root 5725: opn = "dmfc1";
5726: break;
1.1.1.5 root 5727: case OPC_DMTC1:
1.1.1.7 ! root 5728: gen_load_gpr(t0, rt);
! 5729: {
! 5730: TCGv_i64 fp0 = tcg_temp_new_i64();
! 5731:
! 5732: tcg_gen_extu_tl_i64(fp0, t0);
! 5733: gen_store_fpr64(ctx, fp0, fs);
! 5734: tcg_temp_free_i64(fp0);
! 5735: }
1.1.1.6 root 5736: opn = "dmtc1";
5737: break;
5738: case OPC_MFHC1:
1.1.1.7 ! root 5739: {
! 5740: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5741:
! 5742: gen_load_fpr32h(fp0, fs);
! 5743: tcg_gen_ext_i32_tl(t0, fp0);
! 5744: tcg_temp_free_i32(fp0);
! 5745: }
! 5746: gen_store_gpr(t0, rt);
1.1.1.6 root 5747: opn = "mfhc1";
5748: break;
5749: case OPC_MTHC1:
1.1.1.7 ! root 5750: gen_load_gpr(t0, rt);
! 5751: {
! 5752: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5753:
! 5754: tcg_gen_trunc_tl_i32(fp0, t0);
! 5755: gen_store_fpr32h(fp0, fs);
! 5756: tcg_temp_free_i32(fp0);
! 5757: }
1.1.1.6 root 5758: opn = "mthc1";
5759: break;
1.1.1.5 root 5760: default:
1.1.1.6 root 5761: MIPS_INVAL(opn);
5762: generate_exception (ctx, EXCP_RI);
1.1.1.7 ! root 5763: goto out;
1.1.1.4 root 5764: }
5765: MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
1.1.1.7 ! root 5766:
! 5767: out:
! 5768: tcg_temp_free(t0);
1.1.1.4 root 5769: }
5770:
1.1.1.6 root 5771: static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5772: {
1.1.1.7 ! root 5773: int l1 = gen_new_label();
1.1.1.6 root 5774: uint32_t ccbit;
1.1.1.7 ! root 5775: TCGCond cond;
! 5776: TCGv t0 = tcg_temp_local_new();
! 5777: TCGv_i32 r_tmp = tcg_temp_new_i32();
! 5778:
! 5779: if (cc)
! 5780: ccbit = 1 << (24 + cc);
! 5781: else
! 5782: ccbit = 1 << 23;
! 5783: if (tf)
! 5784: cond = TCG_COND_EQ;
! 5785: else
! 5786: cond = TCG_COND_NE;
! 5787:
! 5788: gen_load_gpr(t0, rd);
! 5789: tcg_gen_andi_i32(r_tmp, fpu_fcr31, ccbit);
! 5790: tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
! 5791: tcg_temp_free_i32(r_tmp);
! 5792: gen_load_gpr(t0, rs);
! 5793: gen_set_label(l1);
! 5794: gen_store_gpr(t0, rd);
! 5795: tcg_temp_free(t0);
! 5796: }
! 5797:
! 5798: static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
! 5799: {
! 5800: uint32_t ccbit;
! 5801: int cond;
! 5802: TCGv_i32 r_tmp1 = tcg_temp_new_i32();
! 5803: TCGv_i32 fp0 = tcg_temp_local_new_i32();
! 5804: int l1 = gen_new_label();
! 5805:
! 5806: if (cc)
! 5807: ccbit = 1 << (24 + cc);
! 5808: else
! 5809: ccbit = 1 << 23;
! 5810:
! 5811: if (tf)
! 5812: cond = TCG_COND_EQ;
! 5813: else
! 5814: cond = TCG_COND_NE;
! 5815:
! 5816: gen_load_fpr32(fp0, fd);
! 5817: tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
! 5818: tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
! 5819: tcg_temp_free_i32(r_tmp1);
! 5820: gen_load_fpr32(fp0, fs);
! 5821: gen_set_label(l1);
! 5822: gen_store_fpr32(fp0, fd);
! 5823: tcg_temp_free_i32(fp0);
! 5824: }
! 5825:
! 5826: static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
! 5827: {
! 5828: uint32_t ccbit;
! 5829: int cond;
! 5830: TCGv_i32 r_tmp1 = tcg_temp_new_i32();
! 5831: TCGv_i64 fp0 = tcg_temp_local_new_i64();
! 5832: int l1 = gen_new_label();
! 5833:
! 5834: if (cc)
! 5835: ccbit = 1 << (24 + cc);
! 5836: else
! 5837: ccbit = 1 << 23;
! 5838:
! 5839: if (tf)
! 5840: cond = TCG_COND_EQ;
! 5841: else
! 5842: cond = TCG_COND_NE;
! 5843:
! 5844: gen_load_fpr64(ctx, fp0, fd);
! 5845: tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
! 5846: tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
! 5847: tcg_temp_free_i32(r_tmp1);
! 5848: gen_load_fpr64(ctx, fp0, fs);
! 5849: gen_set_label(l1);
! 5850: gen_store_fpr64(ctx, fp0, fd);
! 5851: tcg_temp_free_i64(fp0);
! 5852: }
! 5853:
! 5854: static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
! 5855: {
! 5856: uint32_t ccbit1, ccbit2;
! 5857: int cond;
! 5858: TCGv_i32 r_tmp1 = tcg_temp_new_i32();
! 5859: TCGv_i32 fp0 = tcg_temp_local_new_i32();
! 5860: int l1 = gen_new_label();
! 5861: int l2 = gen_new_label();
1.1.1.4 root 5862:
1.1.1.6 root 5863: if (cc) {
1.1.1.7 ! root 5864: ccbit1 = 1 << (24 + cc);
! 5865: ccbit2 = 1 << (25 + cc);
! 5866: } else {
! 5867: ccbit1 = 1 << 23;
! 5868: ccbit2 = 1 << 25;
! 5869: }
! 5870:
! 5871: if (tf)
! 5872: cond = TCG_COND_EQ;
1.1.1.6 root 5873: else
1.1.1.7 ! root 5874: cond = TCG_COND_NE;
! 5875:
! 5876: gen_load_fpr32(fp0, fd);
! 5877: tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit1);
! 5878: tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
! 5879: gen_load_fpr32(fp0, fs);
! 5880: gen_set_label(l1);
! 5881: gen_store_fpr32(fp0, fd);
! 5882:
! 5883: gen_load_fpr32h(fp0, fd);
! 5884: tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit2);
! 5885: tcg_gen_brcondi_i32(cond, r_tmp1, 0, l2);
! 5886: gen_load_fpr32h(fp0, fs);
! 5887: gen_set_label(l2);
! 5888: gen_store_fpr32h(fp0, fd);
! 5889:
! 5890: tcg_temp_free_i32(r_tmp1);
! 5891: tcg_temp_free_i32(fp0);
1.1.1.6 root 5892: }
5893:
1.1.1.4 root 5894:
1.1.1.6 root 5895: static void gen_farith (DisasContext *ctx, uint32_t op1,
5896: int ft, int fs, int fd, int cc)
1.1.1.4 root 5897: {
1.1.1.6 root 5898: const char *opn = "farith";
1.1.1.4 root 5899: const char *condnames[] = {
5900: "c.f",
5901: "c.un",
5902: "c.eq",
5903: "c.ueq",
5904: "c.olt",
5905: "c.ult",
5906: "c.ole",
5907: "c.ule",
5908: "c.sf",
5909: "c.ngle",
5910: "c.seq",
5911: "c.ngl",
5912: "c.lt",
5913: "c.nge",
5914: "c.le",
5915: "c.ngt",
5916: };
1.1.1.6 root 5917: const char *condnames_abs[] = {
5918: "cabs.f",
5919: "cabs.un",
5920: "cabs.eq",
5921: "cabs.ueq",
5922: "cabs.olt",
5923: "cabs.ult",
5924: "cabs.ole",
5925: "cabs.ule",
5926: "cabs.sf",
5927: "cabs.ngle",
5928: "cabs.seq",
5929: "cabs.ngl",
5930: "cabs.lt",
5931: "cabs.nge",
5932: "cabs.le",
5933: "cabs.ngt",
5934: };
5935: enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
1.1.1.5 root 5936: uint32_t func = ctx->opcode & 0x3f;
5937:
1.1.1.4 root 5938: switch (ctx->opcode & FOP(0x3f, 0x1f)) {
1.1.1.6 root 5939: case FOP(0, 16):
1.1.1.7 ! root 5940: {
! 5941: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5942: TCGv_i32 fp1 = tcg_temp_new_i32();
! 5943:
! 5944: gen_load_fpr32(fp0, fs);
! 5945: gen_load_fpr32(fp1, ft);
! 5946: gen_helper_float_add_s(fp0, fp0, fp1);
! 5947: tcg_temp_free_i32(fp1);
! 5948: gen_store_fpr32(fp0, fd);
! 5949: tcg_temp_free_i32(fp0);
! 5950: }
1.1.1.6 root 5951: opn = "add.s";
5952: optype = BINOP;
5953: break;
5954: case FOP(1, 16):
1.1.1.7 ! root 5955: {
! 5956: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5957: TCGv_i32 fp1 = tcg_temp_new_i32();
! 5958:
! 5959: gen_load_fpr32(fp0, fs);
! 5960: gen_load_fpr32(fp1, ft);
! 5961: gen_helper_float_sub_s(fp0, fp0, fp1);
! 5962: tcg_temp_free_i32(fp1);
! 5963: gen_store_fpr32(fp0, fd);
! 5964: tcg_temp_free_i32(fp0);
! 5965: }
1.1.1.6 root 5966: opn = "sub.s";
5967: optype = BINOP;
5968: break;
5969: case FOP(2, 16):
1.1.1.7 ! root 5970: {
! 5971: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5972: TCGv_i32 fp1 = tcg_temp_new_i32();
! 5973:
! 5974: gen_load_fpr32(fp0, fs);
! 5975: gen_load_fpr32(fp1, ft);
! 5976: gen_helper_float_mul_s(fp0, fp0, fp1);
! 5977: tcg_temp_free_i32(fp1);
! 5978: gen_store_fpr32(fp0, fd);
! 5979: tcg_temp_free_i32(fp0);
! 5980: }
1.1.1.6 root 5981: opn = "mul.s";
5982: optype = BINOP;
5983: break;
5984: case FOP(3, 16):
1.1.1.7 ! root 5985: {
! 5986: TCGv_i32 fp0 = tcg_temp_new_i32();
! 5987: TCGv_i32 fp1 = tcg_temp_new_i32();
! 5988:
! 5989: gen_load_fpr32(fp0, fs);
! 5990: gen_load_fpr32(fp1, ft);
! 5991: gen_helper_float_div_s(fp0, fp0, fp1);
! 5992: tcg_temp_free_i32(fp1);
! 5993: gen_store_fpr32(fp0, fd);
! 5994: tcg_temp_free_i32(fp0);
! 5995: }
1.1.1.6 root 5996: opn = "div.s";
5997: optype = BINOP;
5998: break;
5999: case FOP(4, 16):
1.1.1.7 ! root 6000: {
! 6001: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6002:
! 6003: gen_load_fpr32(fp0, fs);
! 6004: gen_helper_float_sqrt_s(fp0, fp0);
! 6005: gen_store_fpr32(fp0, fd);
! 6006: tcg_temp_free_i32(fp0);
! 6007: }
1.1.1.6 root 6008: opn = "sqrt.s";
6009: break;
6010: case FOP(5, 16):
1.1.1.7 ! root 6011: {
! 6012: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6013:
! 6014: gen_load_fpr32(fp0, fs);
! 6015: gen_helper_float_abs_s(fp0, fp0);
! 6016: gen_store_fpr32(fp0, fd);
! 6017: tcg_temp_free_i32(fp0);
! 6018: }
1.1.1.6 root 6019: opn = "abs.s";
6020: break;
6021: case FOP(6, 16):
1.1.1.7 ! root 6022: {
! 6023: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6024:
! 6025: gen_load_fpr32(fp0, fs);
! 6026: gen_store_fpr32(fp0, fd);
! 6027: tcg_temp_free_i32(fp0);
! 6028: }
1.1.1.6 root 6029: opn = "mov.s";
6030: break;
6031: case FOP(7, 16):
1.1.1.7 ! root 6032: {
! 6033: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6034:
! 6035: gen_load_fpr32(fp0, fs);
! 6036: gen_helper_float_chs_s(fp0, fp0);
! 6037: gen_store_fpr32(fp0, fd);
! 6038: tcg_temp_free_i32(fp0);
! 6039: }
1.1.1.6 root 6040: opn = "neg.s";
6041: break;
6042: case FOP(8, 16):
6043: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6044: {
! 6045: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6046: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6047:
! 6048: gen_load_fpr32(fp32, fs);
! 6049: gen_helper_float_roundl_s(fp64, fp32);
! 6050: tcg_temp_free_i32(fp32);
! 6051: gen_store_fpr64(ctx, fp64, fd);
! 6052: tcg_temp_free_i64(fp64);
! 6053: }
1.1.1.6 root 6054: opn = "round.l.s";
6055: break;
6056: case FOP(9, 16):
6057: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6058: {
! 6059: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6060: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6061:
! 6062: gen_load_fpr32(fp32, fs);
! 6063: gen_helper_float_truncl_s(fp64, fp32);
! 6064: tcg_temp_free_i32(fp32);
! 6065: gen_store_fpr64(ctx, fp64, fd);
! 6066: tcg_temp_free_i64(fp64);
! 6067: }
1.1.1.6 root 6068: opn = "trunc.l.s";
6069: break;
6070: case FOP(10, 16):
6071: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6072: {
! 6073: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6074: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6075:
! 6076: gen_load_fpr32(fp32, fs);
! 6077: gen_helper_float_ceill_s(fp64, fp32);
! 6078: tcg_temp_free_i32(fp32);
! 6079: gen_store_fpr64(ctx, fp64, fd);
! 6080: tcg_temp_free_i64(fp64);
! 6081: }
1.1.1.6 root 6082: opn = "ceil.l.s";
6083: break;
6084: case FOP(11, 16):
6085: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6086: {
! 6087: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6088: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6089:
! 6090: gen_load_fpr32(fp32, fs);
! 6091: gen_helper_float_floorl_s(fp64, fp32);
! 6092: tcg_temp_free_i32(fp32);
! 6093: gen_store_fpr64(ctx, fp64, fd);
! 6094: tcg_temp_free_i64(fp64);
! 6095: }
1.1.1.6 root 6096: opn = "floor.l.s";
6097: break;
6098: case FOP(12, 16):
1.1.1.7 ! root 6099: {
! 6100: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6101:
! 6102: gen_load_fpr32(fp0, fs);
! 6103: gen_helper_float_roundw_s(fp0, fp0);
! 6104: gen_store_fpr32(fp0, fd);
! 6105: tcg_temp_free_i32(fp0);
! 6106: }
1.1.1.6 root 6107: opn = "round.w.s";
6108: break;
6109: case FOP(13, 16):
1.1.1.7 ! root 6110: {
! 6111: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6112:
! 6113: gen_load_fpr32(fp0, fs);
! 6114: gen_helper_float_truncw_s(fp0, fp0);
! 6115: gen_store_fpr32(fp0, fd);
! 6116: tcg_temp_free_i32(fp0);
! 6117: }
1.1.1.6 root 6118: opn = "trunc.w.s";
6119: break;
6120: case FOP(14, 16):
1.1.1.7 ! root 6121: {
! 6122: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6123:
! 6124: gen_load_fpr32(fp0, fs);
! 6125: gen_helper_float_ceilw_s(fp0, fp0);
! 6126: gen_store_fpr32(fp0, fd);
! 6127: tcg_temp_free_i32(fp0);
! 6128: }
1.1.1.6 root 6129: opn = "ceil.w.s";
6130: break;
6131: case FOP(15, 16):
1.1.1.7 ! root 6132: {
! 6133: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6134:
! 6135: gen_load_fpr32(fp0, fs);
! 6136: gen_helper_float_floorw_s(fp0, fp0);
! 6137: gen_store_fpr32(fp0, fd);
! 6138: tcg_temp_free_i32(fp0);
! 6139: }
1.1.1.6 root 6140: opn = "floor.w.s";
6141: break;
6142: case FOP(17, 16):
1.1.1.7 ! root 6143: gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 6144: opn = "movcf.s";
6145: break;
6146: case FOP(18, 16):
1.1.1.7 ! root 6147: {
! 6148: int l1 = gen_new_label();
! 6149: TCGv t0 = tcg_temp_new();
! 6150: TCGv_i32 fp0 = tcg_temp_local_new_i32();
! 6151:
! 6152: gen_load_gpr(t0, ft);
! 6153: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
! 6154: gen_load_fpr32(fp0, fs);
! 6155: gen_store_fpr32(fp0, fd);
! 6156: tcg_temp_free_i32(fp0);
! 6157: gen_set_label(l1);
! 6158: tcg_temp_free(t0);
! 6159: }
1.1.1.6 root 6160: opn = "movz.s";
6161: break;
6162: case FOP(19, 16):
1.1.1.7 ! root 6163: {
! 6164: int l1 = gen_new_label();
! 6165: TCGv t0 = tcg_temp_new();
! 6166: TCGv_i32 fp0 = tcg_temp_local_new_i32();
! 6167:
! 6168: gen_load_gpr(t0, ft);
! 6169: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
! 6170: gen_load_fpr32(fp0, fs);
! 6171: gen_store_fpr32(fp0, fd);
! 6172: tcg_temp_free_i32(fp0);
! 6173: gen_set_label(l1);
! 6174: tcg_temp_free(t0);
! 6175: }
1.1.1.6 root 6176: opn = "movn.s";
6177: break;
6178: case FOP(21, 16):
6179: check_cop1x(ctx);
1.1.1.7 ! root 6180: {
! 6181: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6182:
! 6183: gen_load_fpr32(fp0, fs);
! 6184: gen_helper_float_recip_s(fp0, fp0);
! 6185: gen_store_fpr32(fp0, fd);
! 6186: tcg_temp_free_i32(fp0);
! 6187: }
1.1.1.6 root 6188: opn = "recip.s";
6189: break;
6190: case FOP(22, 16):
6191: check_cop1x(ctx);
1.1.1.7 ! root 6192: {
! 6193: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6194:
! 6195: gen_load_fpr32(fp0, fs);
! 6196: gen_helper_float_rsqrt_s(fp0, fp0);
! 6197: gen_store_fpr32(fp0, fd);
! 6198: tcg_temp_free_i32(fp0);
! 6199: }
1.1.1.6 root 6200: opn = "rsqrt.s";
6201: break;
6202: case FOP(28, 16):
6203: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6204: {
! 6205: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6206: TCGv_i32 fp1 = tcg_temp_new_i32();
! 6207:
! 6208: gen_load_fpr32(fp0, fs);
! 6209: gen_load_fpr32(fp1, fd);
! 6210: gen_helper_float_recip2_s(fp0, fp0, fp1);
! 6211: tcg_temp_free_i32(fp1);
! 6212: gen_store_fpr32(fp0, fd);
! 6213: tcg_temp_free_i32(fp0);
! 6214: }
1.1.1.6 root 6215: opn = "recip2.s";
6216: break;
6217: case FOP(29, 16):
6218: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6219: {
! 6220: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6221:
! 6222: gen_load_fpr32(fp0, fs);
! 6223: gen_helper_float_recip1_s(fp0, fp0);
! 6224: gen_store_fpr32(fp0, fd);
! 6225: tcg_temp_free_i32(fp0);
! 6226: }
1.1.1.6 root 6227: opn = "recip1.s";
6228: break;
6229: case FOP(30, 16):
6230: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6231: {
! 6232: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6233:
! 6234: gen_load_fpr32(fp0, fs);
! 6235: gen_helper_float_rsqrt1_s(fp0, fp0);
! 6236: gen_store_fpr32(fp0, fd);
! 6237: tcg_temp_free_i32(fp0);
! 6238: }
1.1.1.6 root 6239: opn = "rsqrt1.s";
6240: break;
6241: case FOP(31, 16):
6242: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6243: {
! 6244: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6245: TCGv_i32 fp1 = tcg_temp_new_i32();
! 6246:
! 6247: gen_load_fpr32(fp0, fs);
! 6248: gen_load_fpr32(fp1, ft);
! 6249: gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
! 6250: tcg_temp_free_i32(fp1);
! 6251: gen_store_fpr32(fp0, fd);
! 6252: tcg_temp_free_i32(fp0);
! 6253: }
1.1.1.6 root 6254: opn = "rsqrt2.s";
6255: break;
6256: case FOP(33, 16):
6257: check_cp1_registers(ctx, fd);
1.1.1.7 ! root 6258: {
! 6259: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6260: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6261:
! 6262: gen_load_fpr32(fp32, fs);
! 6263: gen_helper_float_cvtd_s(fp64, fp32);
! 6264: tcg_temp_free_i32(fp32);
! 6265: gen_store_fpr64(ctx, fp64, fd);
! 6266: tcg_temp_free_i64(fp64);
! 6267: }
1.1.1.6 root 6268: opn = "cvt.d.s";
6269: break;
6270: case FOP(36, 16):
1.1.1.7 ! root 6271: {
! 6272: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6273:
! 6274: gen_load_fpr32(fp0, fs);
! 6275: gen_helper_float_cvtw_s(fp0, fp0);
! 6276: gen_store_fpr32(fp0, fd);
! 6277: tcg_temp_free_i32(fp0);
! 6278: }
1.1.1.6 root 6279: opn = "cvt.w.s";
6280: break;
6281: case FOP(37, 16):
6282: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6283: {
! 6284: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6285: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6286:
! 6287: gen_load_fpr32(fp32, fs);
! 6288: gen_helper_float_cvtl_s(fp64, fp32);
! 6289: tcg_temp_free_i32(fp32);
! 6290: gen_store_fpr64(ctx, fp64, fd);
! 6291: tcg_temp_free_i64(fp64);
! 6292: }
1.1.1.6 root 6293: opn = "cvt.l.s";
6294: break;
6295: case FOP(38, 16):
6296: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6297: {
! 6298: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6299: TCGv_i32 fp32_0 = tcg_temp_new_i32();
! 6300: TCGv_i32 fp32_1 = tcg_temp_new_i32();
! 6301:
! 6302: gen_load_fpr32(fp32_0, fs);
! 6303: gen_load_fpr32(fp32_1, ft);
! 6304: tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
! 6305: tcg_temp_free_i32(fp32_1);
! 6306: tcg_temp_free_i32(fp32_0);
! 6307: gen_store_fpr64(ctx, fp64, fd);
! 6308: tcg_temp_free_i64(fp64);
! 6309: }
1.1.1.6 root 6310: opn = "cvt.ps.s";
6311: break;
6312: case FOP(48, 16):
6313: case FOP(49, 16):
6314: case FOP(50, 16):
6315: case FOP(51, 16):
6316: case FOP(52, 16):
6317: case FOP(53, 16):
6318: case FOP(54, 16):
6319: case FOP(55, 16):
6320: case FOP(56, 16):
6321: case FOP(57, 16):
6322: case FOP(58, 16):
6323: case FOP(59, 16):
6324: case FOP(60, 16):
6325: case FOP(61, 16):
6326: case FOP(62, 16):
6327: case FOP(63, 16):
1.1.1.7 ! root 6328: {
! 6329: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6330: TCGv_i32 fp1 = tcg_temp_new_i32();
! 6331:
! 6332: gen_load_fpr32(fp0, fs);
! 6333: gen_load_fpr32(fp1, ft);
! 6334: if (ctx->opcode & (1 << 6)) {
! 6335: check_cop1x(ctx);
! 6336: gen_cmpabs_s(func-48, fp0, fp1, cc);
! 6337: opn = condnames_abs[func-48];
! 6338: } else {
! 6339: gen_cmp_s(func-48, fp0, fp1, cc);
! 6340: opn = condnames[func-48];
! 6341: }
! 6342: tcg_temp_free_i32(fp0);
! 6343: tcg_temp_free_i32(fp1);
1.1.1.6 root 6344: }
6345: break;
1.1.1.4 root 6346: case FOP(0, 17):
1.1.1.6 root 6347: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 ! root 6348: {
! 6349: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6350: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6351:
! 6352: gen_load_fpr64(ctx, fp0, fs);
! 6353: gen_load_fpr64(ctx, fp1, ft);
! 6354: gen_helper_float_add_d(fp0, fp0, fp1);
! 6355: tcg_temp_free_i64(fp1);
! 6356: gen_store_fpr64(ctx, fp0, fd);
! 6357: tcg_temp_free_i64(fp0);
! 6358: }
1.1.1.4 root 6359: opn = "add.d";
1.1.1.6 root 6360: optype = BINOP;
1.1.1.4 root 6361: break;
6362: case FOP(1, 17):
1.1.1.6 root 6363: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 ! root 6364: {
! 6365: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6366: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6367:
! 6368: gen_load_fpr64(ctx, fp0, fs);
! 6369: gen_load_fpr64(ctx, fp1, ft);
! 6370: gen_helper_float_sub_d(fp0, fp0, fp1);
! 6371: tcg_temp_free_i64(fp1);
! 6372: gen_store_fpr64(ctx, fp0, fd);
! 6373: tcg_temp_free_i64(fp0);
! 6374: }
1.1.1.4 root 6375: opn = "sub.d";
1.1.1.6 root 6376: optype = BINOP;
1.1.1.4 root 6377: break;
6378: case FOP(2, 17):
1.1.1.6 root 6379: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 ! root 6380: {
! 6381: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6382: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6383:
! 6384: gen_load_fpr64(ctx, fp0, fs);
! 6385: gen_load_fpr64(ctx, fp1, ft);
! 6386: gen_helper_float_mul_d(fp0, fp0, fp1);
! 6387: tcg_temp_free_i64(fp1);
! 6388: gen_store_fpr64(ctx, fp0, fd);
! 6389: tcg_temp_free_i64(fp0);
! 6390: }
1.1.1.4 root 6391: opn = "mul.d";
1.1.1.6 root 6392: optype = BINOP;
1.1.1.4 root 6393: break;
6394: case FOP(3, 17):
1.1.1.6 root 6395: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.7 ! root 6396: {
! 6397: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6398: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6399:
! 6400: gen_load_fpr64(ctx, fp0, fs);
! 6401: gen_load_fpr64(ctx, fp1, ft);
! 6402: gen_helper_float_div_d(fp0, fp0, fp1);
! 6403: tcg_temp_free_i64(fp1);
! 6404: gen_store_fpr64(ctx, fp0, fd);
! 6405: tcg_temp_free_i64(fp0);
! 6406: }
1.1.1.4 root 6407: opn = "div.d";
1.1.1.6 root 6408: optype = BINOP;
1.1.1.4 root 6409: break;
6410: case FOP(4, 17):
1.1.1.6 root 6411: check_cp1_registers(ctx, fs | fd);
1.1.1.7 ! root 6412: {
! 6413: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6414:
! 6415: gen_load_fpr64(ctx, fp0, fs);
! 6416: gen_helper_float_sqrt_d(fp0, fp0);
! 6417: gen_store_fpr64(ctx, fp0, fd);
! 6418: tcg_temp_free_i64(fp0);
! 6419: }
1.1.1.4 root 6420: opn = "sqrt.d";
6421: break;
6422: case FOP(5, 17):
1.1.1.6 root 6423: check_cp1_registers(ctx, fs | fd);
1.1.1.7 ! root 6424: {
! 6425: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6426:
! 6427: gen_load_fpr64(ctx, fp0, fs);
! 6428: gen_helper_float_abs_d(fp0, fp0);
! 6429: gen_store_fpr64(ctx, fp0, fd);
! 6430: tcg_temp_free_i64(fp0);
! 6431: }
1.1.1.4 root 6432: opn = "abs.d";
6433: break;
6434: case FOP(6, 17):
1.1.1.6 root 6435: check_cp1_registers(ctx, fs | fd);
1.1.1.7 ! root 6436: {
! 6437: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6438:
! 6439: gen_load_fpr64(ctx, fp0, fs);
! 6440: gen_store_fpr64(ctx, fp0, fd);
! 6441: tcg_temp_free_i64(fp0);
! 6442: }
1.1.1.4 root 6443: opn = "mov.d";
6444: break;
6445: case FOP(7, 17):
1.1.1.6 root 6446: check_cp1_registers(ctx, fs | fd);
1.1.1.7 ! root 6447: {
! 6448: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6449:
! 6450: gen_load_fpr64(ctx, fp0, fs);
! 6451: gen_helper_float_chs_d(fp0, fp0);
! 6452: gen_store_fpr64(ctx, fp0, fd);
! 6453: tcg_temp_free_i64(fp0);
! 6454: }
1.1.1.4 root 6455: opn = "neg.d";
6456: break;
1.1.1.6 root 6457: case FOP(8, 17):
6458: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6459: {
! 6460: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6461:
! 6462: gen_load_fpr64(ctx, fp0, fs);
! 6463: gen_helper_float_roundl_d(fp0, fp0);
! 6464: gen_store_fpr64(ctx, fp0, fd);
! 6465: tcg_temp_free_i64(fp0);
! 6466: }
1.1.1.6 root 6467: opn = "round.l.d";
6468: break;
6469: case FOP(9, 17):
6470: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6471: {
! 6472: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6473:
! 6474: gen_load_fpr64(ctx, fp0, fs);
! 6475: gen_helper_float_truncl_d(fp0, fp0);
! 6476: gen_store_fpr64(ctx, fp0, fd);
! 6477: tcg_temp_free_i64(fp0);
! 6478: }
1.1.1.6 root 6479: opn = "trunc.l.d";
6480: break;
6481: case FOP(10, 17):
6482: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6483: {
! 6484: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6485:
! 6486: gen_load_fpr64(ctx, fp0, fs);
! 6487: gen_helper_float_ceill_d(fp0, fp0);
! 6488: gen_store_fpr64(ctx, fp0, fd);
! 6489: tcg_temp_free_i64(fp0);
! 6490: }
1.1.1.6 root 6491: opn = "ceil.l.d";
6492: break;
6493: case FOP(11, 17):
6494: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6495: {
! 6496: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6497:
! 6498: gen_load_fpr64(ctx, fp0, fs);
! 6499: gen_helper_float_floorl_d(fp0, fp0);
! 6500: gen_store_fpr64(ctx, fp0, fd);
! 6501: tcg_temp_free_i64(fp0);
! 6502: }
1.1.1.6 root 6503: opn = "floor.l.d";
6504: break;
1.1.1.4 root 6505: case FOP(12, 17):
1.1.1.6 root 6506: check_cp1_registers(ctx, fs);
1.1.1.7 ! root 6507: {
! 6508: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6509: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6510:
! 6511: gen_load_fpr64(ctx, fp64, fs);
! 6512: gen_helper_float_roundw_d(fp32, fp64);
! 6513: tcg_temp_free_i64(fp64);
! 6514: gen_store_fpr32(fp32, fd);
! 6515: tcg_temp_free_i32(fp32);
! 6516: }
1.1.1.4 root 6517: opn = "round.w.d";
6518: break;
6519: case FOP(13, 17):
1.1.1.6 root 6520: check_cp1_registers(ctx, fs);
1.1.1.7 ! root 6521: {
! 6522: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6523: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6524:
! 6525: gen_load_fpr64(ctx, fp64, fs);
! 6526: gen_helper_float_truncw_d(fp32, fp64);
! 6527: tcg_temp_free_i64(fp64);
! 6528: gen_store_fpr32(fp32, fd);
! 6529: tcg_temp_free_i32(fp32);
! 6530: }
1.1.1.4 root 6531: opn = "trunc.w.d";
6532: break;
6533: case FOP(14, 17):
1.1.1.6 root 6534: check_cp1_registers(ctx, fs);
1.1.1.7 ! root 6535: {
! 6536: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6537: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6538:
! 6539: gen_load_fpr64(ctx, fp64, fs);
! 6540: gen_helper_float_ceilw_d(fp32, fp64);
! 6541: tcg_temp_free_i64(fp64);
! 6542: gen_store_fpr32(fp32, fd);
! 6543: tcg_temp_free_i32(fp32);
! 6544: }
1.1.1.4 root 6545: opn = "ceil.w.d";
6546: break;
6547: case FOP(15, 17):
1.1.1.6 root 6548: check_cp1_registers(ctx, fs);
1.1.1.7 ! root 6549: {
! 6550: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6551: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6552:
! 6553: gen_load_fpr64(ctx, fp64, fs);
! 6554: gen_helper_float_floorw_d(fp32, fp64);
! 6555: tcg_temp_free_i64(fp64);
! 6556: gen_store_fpr32(fp32, fd);
! 6557: tcg_temp_free_i32(fp32);
! 6558: }
1.1.1.5 root 6559: opn = "floor.w.d";
6560: break;
1.1.1.6 root 6561: case FOP(17, 17):
1.1.1.7 ! root 6562: gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 6563: opn = "movcf.d";
1.1.1.4 root 6564: break;
1.1.1.6 root 6565: case FOP(18, 17):
1.1.1.7 ! root 6566: {
! 6567: int l1 = gen_new_label();
! 6568: TCGv t0 = tcg_temp_new();
! 6569: TCGv_i64 fp0 = tcg_temp_local_new_i64();
! 6570:
! 6571: gen_load_gpr(t0, ft);
! 6572: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
! 6573: gen_load_fpr64(ctx, fp0, fs);
! 6574: gen_store_fpr64(ctx, fp0, fd);
! 6575: tcg_temp_free_i64(fp0);
! 6576: gen_set_label(l1);
! 6577: tcg_temp_free(t0);
! 6578: }
1.1.1.6 root 6579: opn = "movz.d";
6580: break;
6581: case FOP(19, 17):
1.1.1.7 ! root 6582: {
! 6583: int l1 = gen_new_label();
! 6584: TCGv t0 = tcg_temp_new();
! 6585: TCGv_i64 fp0 = tcg_temp_local_new_i64();
! 6586:
! 6587: gen_load_gpr(t0, ft);
! 6588: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
! 6589: gen_load_fpr64(ctx, fp0, fs);
! 6590: gen_store_fpr64(ctx, fp0, fd);
! 6591: tcg_temp_free_i64(fp0);
! 6592: gen_set_label(l1);
! 6593: tcg_temp_free(t0);
! 6594: }
1.1.1.6 root 6595: opn = "movn.d";
6596: break;
6597: case FOP(21, 17):
6598: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6599: {
! 6600: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6601:
! 6602: gen_load_fpr64(ctx, fp0, fs);
! 6603: gen_helper_float_recip_d(fp0, fp0);
! 6604: gen_store_fpr64(ctx, fp0, fd);
! 6605: tcg_temp_free_i64(fp0);
! 6606: }
1.1.1.6 root 6607: opn = "recip.d";
6608: break;
6609: case FOP(22, 17):
6610: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6611: {
! 6612: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6613:
! 6614: gen_load_fpr64(ctx, fp0, fs);
! 6615: gen_helper_float_rsqrt_d(fp0, fp0);
! 6616: gen_store_fpr64(ctx, fp0, fd);
! 6617: tcg_temp_free_i64(fp0);
! 6618: }
1.1.1.6 root 6619: opn = "rsqrt.d";
6620: break;
6621: case FOP(28, 17):
6622: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6623: {
! 6624: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6625: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6626:
! 6627: gen_load_fpr64(ctx, fp0, fs);
! 6628: gen_load_fpr64(ctx, fp1, ft);
! 6629: gen_helper_float_recip2_d(fp0, fp0, fp1);
! 6630: tcg_temp_free_i64(fp1);
! 6631: gen_store_fpr64(ctx, fp0, fd);
! 6632: tcg_temp_free_i64(fp0);
! 6633: }
1.1.1.6 root 6634: opn = "recip2.d";
6635: break;
6636: case FOP(29, 17):
6637: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6638: {
! 6639: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6640:
! 6641: gen_load_fpr64(ctx, fp0, fs);
! 6642: gen_helper_float_recip1_d(fp0, fp0);
! 6643: gen_store_fpr64(ctx, fp0, fd);
! 6644: tcg_temp_free_i64(fp0);
! 6645: }
1.1.1.6 root 6646: opn = "recip1.d";
6647: break;
6648: case FOP(30, 17):
6649: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6650: {
! 6651: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6652:
! 6653: gen_load_fpr64(ctx, fp0, fs);
! 6654: gen_helper_float_rsqrt1_d(fp0, fp0);
! 6655: gen_store_fpr64(ctx, fp0, fd);
! 6656: tcg_temp_free_i64(fp0);
! 6657: }
1.1.1.6 root 6658: opn = "rsqrt1.d";
6659: break;
6660: case FOP(31, 17):
6661: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6662: {
! 6663: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6664: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6665:
! 6666: gen_load_fpr64(ctx, fp0, fs);
! 6667: gen_load_fpr64(ctx, fp1, ft);
! 6668: gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
! 6669: tcg_temp_free_i64(fp1);
! 6670: gen_store_fpr64(ctx, fp0, fd);
! 6671: tcg_temp_free_i64(fp0);
! 6672: }
1.1.1.6 root 6673: opn = "rsqrt2.d";
1.1.1.4 root 6674: break;
6675: case FOP(48, 17):
6676: case FOP(49, 17):
6677: case FOP(50, 17):
6678: case FOP(51, 17):
6679: case FOP(52, 17):
6680: case FOP(53, 17):
6681: case FOP(54, 17):
6682: case FOP(55, 17):
6683: case FOP(56, 17):
6684: case FOP(57, 17):
6685: case FOP(58, 17):
6686: case FOP(59, 17):
6687: case FOP(60, 17):
6688: case FOP(61, 17):
6689: case FOP(62, 17):
6690: case FOP(63, 17):
1.1.1.7 ! root 6691: {
! 6692: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6693: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6694:
! 6695: gen_load_fpr64(ctx, fp0, fs);
! 6696: gen_load_fpr64(ctx, fp1, ft);
! 6697: if (ctx->opcode & (1 << 6)) {
! 6698: check_cop1x(ctx);
! 6699: check_cp1_registers(ctx, fs | ft);
! 6700: gen_cmpabs_d(func-48, fp0, fp1, cc);
! 6701: opn = condnames_abs[func-48];
! 6702: } else {
! 6703: check_cp1_registers(ctx, fs | ft);
! 6704: gen_cmp_d(func-48, fp0, fp1, cc);
! 6705: opn = condnames[func-48];
! 6706: }
! 6707: tcg_temp_free_i64(fp0);
! 6708: tcg_temp_free_i64(fp1);
1.1.1.6 root 6709: }
6710: break;
6711: case FOP(32, 17):
6712: check_cp1_registers(ctx, fs);
1.1.1.7 ! root 6713: {
! 6714: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6715: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6716:
! 6717: gen_load_fpr64(ctx, fp64, fs);
! 6718: gen_helper_float_cvts_d(fp32, fp64);
! 6719: tcg_temp_free_i64(fp64);
! 6720: gen_store_fpr32(fp32, fd);
! 6721: tcg_temp_free_i32(fp32);
! 6722: }
1.1.1.6 root 6723: opn = "cvt.s.d";
6724: break;
6725: case FOP(36, 17):
6726: check_cp1_registers(ctx, fs);
1.1.1.7 ! root 6727: {
! 6728: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6729: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6730:
! 6731: gen_load_fpr64(ctx, fp64, fs);
! 6732: gen_helper_float_cvtw_d(fp32, fp64);
! 6733: tcg_temp_free_i64(fp64);
! 6734: gen_store_fpr32(fp32, fd);
! 6735: tcg_temp_free_i32(fp32);
! 6736: }
1.1.1.6 root 6737: opn = "cvt.w.d";
6738: break;
6739: case FOP(37, 17):
6740: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6741: {
! 6742: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6743:
! 6744: gen_load_fpr64(ctx, fp0, fs);
! 6745: gen_helper_float_cvtl_d(fp0, fp0);
! 6746: gen_store_fpr64(ctx, fp0, fd);
! 6747: tcg_temp_free_i64(fp0);
! 6748: }
1.1.1.6 root 6749: opn = "cvt.l.d";
6750: break;
6751: case FOP(32, 20):
1.1.1.7 ! root 6752: {
! 6753: TCGv_i32 fp0 = tcg_temp_new_i32();
! 6754:
! 6755: gen_load_fpr32(fp0, fs);
! 6756: gen_helper_float_cvts_w(fp0, fp0);
! 6757: gen_store_fpr32(fp0, fd);
! 6758: tcg_temp_free_i32(fp0);
! 6759: }
1.1.1.6 root 6760: opn = "cvt.s.w";
6761: break;
6762: case FOP(33, 20):
6763: check_cp1_registers(ctx, fd);
1.1.1.7 ! root 6764: {
! 6765: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6766: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6767:
! 6768: gen_load_fpr32(fp32, fs);
! 6769: gen_helper_float_cvtd_w(fp64, fp32);
! 6770: tcg_temp_free_i32(fp32);
! 6771: gen_store_fpr64(ctx, fp64, fd);
! 6772: tcg_temp_free_i64(fp64);
! 6773: }
1.1.1.6 root 6774: opn = "cvt.d.w";
6775: break;
6776: case FOP(32, 21):
6777: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6778: {
! 6779: TCGv_i32 fp32 = tcg_temp_new_i32();
! 6780: TCGv_i64 fp64 = tcg_temp_new_i64();
! 6781:
! 6782: gen_load_fpr64(ctx, fp64, fs);
! 6783: gen_helper_float_cvts_l(fp32, fp64);
! 6784: tcg_temp_free_i64(fp64);
! 6785: gen_store_fpr32(fp32, fd);
! 6786: tcg_temp_free_i32(fp32);
! 6787: }
1.1.1.6 root 6788: opn = "cvt.s.l";
6789: break;
6790: case FOP(33, 21):
6791: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6792: {
! 6793: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6794:
! 6795: gen_load_fpr64(ctx, fp0, fs);
! 6796: gen_helper_float_cvtd_l(fp0, fp0);
! 6797: gen_store_fpr64(ctx, fp0, fd);
! 6798: tcg_temp_free_i64(fp0);
! 6799: }
1.1.1.6 root 6800: opn = "cvt.d.l";
6801: break;
6802: case FOP(38, 20):
6803: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6804: {
! 6805: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6806:
! 6807: gen_load_fpr64(ctx, fp0, fs);
! 6808: gen_helper_float_cvtps_pw(fp0, fp0);
! 6809: gen_store_fpr64(ctx, fp0, fd);
! 6810: tcg_temp_free_i64(fp0);
! 6811: }
1.1.1.6 root 6812: opn = "cvt.ps.pw";
6813: break;
6814: case FOP(0, 22):
6815: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6816: {
! 6817: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6818: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6819:
! 6820: gen_load_fpr64(ctx, fp0, fs);
! 6821: gen_load_fpr64(ctx, fp1, ft);
! 6822: gen_helper_float_add_ps(fp0, fp0, fp1);
! 6823: tcg_temp_free_i64(fp1);
! 6824: gen_store_fpr64(ctx, fp0, fd);
! 6825: tcg_temp_free_i64(fp0);
! 6826: }
1.1.1.6 root 6827: opn = "add.ps";
6828: break;
6829: case FOP(1, 22):
6830: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6831: {
! 6832: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6833: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6834:
! 6835: gen_load_fpr64(ctx, fp0, fs);
! 6836: gen_load_fpr64(ctx, fp1, ft);
! 6837: gen_helper_float_sub_ps(fp0, fp0, fp1);
! 6838: tcg_temp_free_i64(fp1);
! 6839: gen_store_fpr64(ctx, fp0, fd);
! 6840: tcg_temp_free_i64(fp0);
! 6841: }
1.1.1.6 root 6842: opn = "sub.ps";
6843: break;
6844: case FOP(2, 22):
6845: check_cp1_64bitmode(ctx);
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_mul_ps(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.6 root 6857: opn = "mul.ps";
6858: break;
6859: case FOP(5, 22):
6860: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6861: {
! 6862: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6863:
! 6864: gen_load_fpr64(ctx, fp0, fs);
! 6865: gen_helper_float_abs_ps(fp0, fp0);
! 6866: gen_store_fpr64(ctx, fp0, fd);
! 6867: tcg_temp_free_i64(fp0);
! 6868: }
1.1.1.6 root 6869: opn = "abs.ps";
6870: break;
6871: case FOP(6, 22):
6872: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6873: {
! 6874: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6875:
! 6876: gen_load_fpr64(ctx, fp0, fs);
! 6877: gen_store_fpr64(ctx, fp0, fd);
! 6878: tcg_temp_free_i64(fp0);
! 6879: }
1.1.1.6 root 6880: opn = "mov.ps";
6881: break;
6882: case FOP(7, 22):
6883: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6884: {
! 6885: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6886:
! 6887: gen_load_fpr64(ctx, fp0, fs);
! 6888: gen_helper_float_chs_ps(fp0, fp0);
! 6889: gen_store_fpr64(ctx, fp0, fd);
! 6890: tcg_temp_free_i64(fp0);
! 6891: }
1.1.1.6 root 6892: opn = "neg.ps";
6893: break;
6894: case FOP(17, 22):
6895: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6896: gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.6 root 6897: opn = "movcf.ps";
6898: break;
6899: case FOP(18, 22):
6900: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6901: {
! 6902: int l1 = gen_new_label();
! 6903: TCGv t0 = tcg_temp_new();
! 6904: TCGv_i32 fp0 = tcg_temp_local_new_i32();
! 6905: TCGv_i32 fph0 = tcg_temp_local_new_i32();
! 6906:
! 6907: gen_load_gpr(t0, ft);
! 6908: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
! 6909: gen_load_fpr32(fp0, fs);
! 6910: gen_load_fpr32h(fph0, fs);
! 6911: gen_store_fpr32(fp0, fd);
! 6912: gen_store_fpr32h(fph0, fd);
! 6913: tcg_temp_free_i32(fp0);
! 6914: tcg_temp_free_i32(fph0);
! 6915: gen_set_label(l1);
! 6916: tcg_temp_free(t0);
! 6917: }
1.1.1.6 root 6918: opn = "movz.ps";
6919: break;
6920: case FOP(19, 22):
6921: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6922: {
! 6923: int l1 = gen_new_label();
! 6924: TCGv t0 = tcg_temp_new();
! 6925: TCGv_i32 fp0 = tcg_temp_local_new_i32();
! 6926: TCGv_i32 fph0 = tcg_temp_local_new_i32();
! 6927:
! 6928: gen_load_gpr(t0, ft);
! 6929: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
! 6930: gen_load_fpr32(fp0, fs);
! 6931: gen_load_fpr32h(fph0, fs);
! 6932: gen_store_fpr32(fp0, fd);
! 6933: gen_store_fpr32h(fph0, fd);
! 6934: tcg_temp_free_i32(fp0);
! 6935: tcg_temp_free_i32(fph0);
! 6936: gen_set_label(l1);
! 6937: tcg_temp_free(t0);
! 6938: }
1.1.1.6 root 6939: opn = "movn.ps";
6940: break;
6941: case FOP(24, 22):
6942: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6943: {
! 6944: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6945: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6946:
! 6947: gen_load_fpr64(ctx, fp0, ft);
! 6948: gen_load_fpr64(ctx, fp1, fs);
! 6949: gen_helper_float_addr_ps(fp0, fp0, fp1);
! 6950: tcg_temp_free_i64(fp1);
! 6951: gen_store_fpr64(ctx, fp0, fd);
! 6952: tcg_temp_free_i64(fp0);
! 6953: }
1.1.1.6 root 6954: opn = "addr.ps";
6955: break;
6956: case FOP(26, 22):
6957: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6958: {
! 6959: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6960: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6961:
! 6962: gen_load_fpr64(ctx, fp0, ft);
! 6963: gen_load_fpr64(ctx, fp1, fs);
! 6964: gen_helper_float_mulr_ps(fp0, fp0, fp1);
! 6965: tcg_temp_free_i64(fp1);
! 6966: gen_store_fpr64(ctx, fp0, fd);
! 6967: tcg_temp_free_i64(fp0);
! 6968: }
1.1.1.6 root 6969: opn = "mulr.ps";
6970: break;
6971: case FOP(28, 22):
6972: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6973: {
! 6974: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6975: TCGv_i64 fp1 = tcg_temp_new_i64();
! 6976:
! 6977: gen_load_fpr64(ctx, fp0, fs);
! 6978: gen_load_fpr64(ctx, fp1, fd);
! 6979: gen_helper_float_recip2_ps(fp0, fp0, fp1);
! 6980: tcg_temp_free_i64(fp1);
! 6981: gen_store_fpr64(ctx, fp0, fd);
! 6982: tcg_temp_free_i64(fp0);
! 6983: }
1.1.1.6 root 6984: opn = "recip2.ps";
6985: break;
6986: case FOP(29, 22):
6987: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 6988: {
! 6989: TCGv_i64 fp0 = tcg_temp_new_i64();
! 6990:
! 6991: gen_load_fpr64(ctx, fp0, fs);
! 6992: gen_helper_float_recip1_ps(fp0, fp0);
! 6993: gen_store_fpr64(ctx, fp0, fd);
! 6994: tcg_temp_free_i64(fp0);
! 6995: }
1.1.1.6 root 6996: opn = "recip1.ps";
6997: break;
6998: case FOP(30, 22):
6999: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7000: {
! 7001: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7002:
! 7003: gen_load_fpr64(ctx, fp0, fs);
! 7004: gen_helper_float_rsqrt1_ps(fp0, fp0);
! 7005: gen_store_fpr64(ctx, fp0, fd);
! 7006: tcg_temp_free_i64(fp0);
! 7007: }
1.1.1.6 root 7008: opn = "rsqrt1.ps";
7009: break;
7010: case FOP(31, 22):
7011: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7012: {
! 7013: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7014: TCGv_i64 fp1 = tcg_temp_new_i64();
! 7015:
! 7016: gen_load_fpr64(ctx, fp0, fs);
! 7017: gen_load_fpr64(ctx, fp1, ft);
! 7018: gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
! 7019: tcg_temp_free_i64(fp1);
! 7020: gen_store_fpr64(ctx, fp0, fd);
! 7021: tcg_temp_free_i64(fp0);
! 7022: }
1.1.1.6 root 7023: opn = "rsqrt2.ps";
7024: break;
7025: case FOP(32, 22):
7026: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7027: {
! 7028: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7029:
! 7030: gen_load_fpr32h(fp0, fs);
! 7031: gen_helper_float_cvts_pu(fp0, fp0);
! 7032: gen_store_fpr32(fp0, fd);
! 7033: tcg_temp_free_i32(fp0);
! 7034: }
1.1.1.6 root 7035: opn = "cvt.s.pu";
7036: break;
7037: case FOP(36, 22):
7038: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7039: {
! 7040: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7041:
! 7042: gen_load_fpr64(ctx, fp0, fs);
! 7043: gen_helper_float_cvtpw_ps(fp0, fp0);
! 7044: gen_store_fpr64(ctx, fp0, fd);
! 7045: tcg_temp_free_i64(fp0);
! 7046: }
1.1.1.6 root 7047: opn = "cvt.pw.ps";
1.1.1.4 root 7048: break;
1.1.1.6 root 7049: case FOP(40, 22):
7050: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7051: {
! 7052: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7053:
! 7054: gen_load_fpr32(fp0, fs);
! 7055: gen_helper_float_cvts_pl(fp0, fp0);
! 7056: gen_store_fpr32(fp0, fd);
! 7057: tcg_temp_free_i32(fp0);
! 7058: }
1.1.1.6 root 7059: opn = "cvt.s.pl";
1.1.1.4 root 7060: break;
1.1.1.6 root 7061: case FOP(44, 22):
7062: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7063: {
! 7064: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7065: TCGv_i32 fp1 = tcg_temp_new_i32();
! 7066:
! 7067: gen_load_fpr32(fp0, fs);
! 7068: gen_load_fpr32(fp1, ft);
! 7069: gen_store_fpr32h(fp0, fd);
! 7070: gen_store_fpr32(fp1, fd);
! 7071: tcg_temp_free_i32(fp0);
! 7072: tcg_temp_free_i32(fp1);
! 7073: }
1.1.1.6 root 7074: opn = "pll.ps";
1.1.1.4 root 7075: break;
1.1.1.6 root 7076: case FOP(45, 22):
7077: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7078: {
! 7079: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7080: TCGv_i32 fp1 = tcg_temp_new_i32();
! 7081:
! 7082: gen_load_fpr32(fp0, fs);
! 7083: gen_load_fpr32h(fp1, ft);
! 7084: gen_store_fpr32(fp1, fd);
! 7085: gen_store_fpr32h(fp0, fd);
! 7086: tcg_temp_free_i32(fp0);
! 7087: tcg_temp_free_i32(fp1);
! 7088: }
1.1.1.6 root 7089: opn = "plu.ps";
7090: break;
7091: case FOP(46, 22):
7092: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7093: {
! 7094: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7095: TCGv_i32 fp1 = tcg_temp_new_i32();
! 7096:
! 7097: gen_load_fpr32h(fp0, fs);
! 7098: gen_load_fpr32(fp1, ft);
! 7099: gen_store_fpr32(fp1, fd);
! 7100: gen_store_fpr32h(fp0, fd);
! 7101: tcg_temp_free_i32(fp0);
! 7102: tcg_temp_free_i32(fp1);
! 7103: }
1.1.1.6 root 7104: opn = "pul.ps";
1.1.1.4 root 7105: break;
1.1.1.6 root 7106: case FOP(47, 22):
7107: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7108: {
! 7109: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7110: TCGv_i32 fp1 = tcg_temp_new_i32();
! 7111:
! 7112: gen_load_fpr32h(fp0, fs);
! 7113: gen_load_fpr32h(fp1, ft);
! 7114: gen_store_fpr32(fp1, fd);
! 7115: gen_store_fpr32h(fp0, fd);
! 7116: tcg_temp_free_i32(fp0);
! 7117: tcg_temp_free_i32(fp1);
! 7118: }
1.1.1.6 root 7119: opn = "puu.ps";
7120: break;
7121: case FOP(48, 22):
7122: case FOP(49, 22):
7123: case FOP(50, 22):
7124: case FOP(51, 22):
7125: case FOP(52, 22):
7126: case FOP(53, 22):
7127: case FOP(54, 22):
7128: case FOP(55, 22):
7129: case FOP(56, 22):
7130: case FOP(57, 22):
7131: case FOP(58, 22):
7132: case FOP(59, 22):
7133: case FOP(60, 22):
7134: case FOP(61, 22):
7135: case FOP(62, 22):
7136: case FOP(63, 22):
7137: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7138: {
! 7139: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7140: TCGv_i64 fp1 = tcg_temp_new_i64();
! 7141:
! 7142: gen_load_fpr64(ctx, fp0, fs);
! 7143: gen_load_fpr64(ctx, fp1, ft);
! 7144: if (ctx->opcode & (1 << 6)) {
! 7145: gen_cmpabs_ps(func-48, fp0, fp1, cc);
! 7146: opn = condnames_abs[func-48];
! 7147: } else {
! 7148: gen_cmp_ps(func-48, fp0, fp1, cc);
! 7149: opn = condnames[func-48];
! 7150: }
! 7151: tcg_temp_free_i64(fp0);
! 7152: tcg_temp_free_i64(fp1);
1.1.1.6 root 7153: }
1.1.1.4 root 7154: break;
1.1.1.6 root 7155: default:
7156: MIPS_INVAL(opn);
7157: generate_exception (ctx, EXCP_RI);
7158: return;
7159: }
7160: switch (optype) {
7161: case BINOP:
7162: MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7163: break;
7164: case CMPOP:
7165: MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7166: break;
7167: default:
7168: MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7169: break;
7170: }
7171: }
7172:
7173: /* Coprocessor 3 (FPU) */
7174: static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7175: int fd, int fs, int base, int index)
7176: {
7177: const char *opn = "extended float load/store";
7178: int store = 0;
1.1.1.7 ! root 7179: TCGv t0 = tcg_temp_local_new();
! 7180: TCGv t1 = tcg_temp_local_new();
1.1.1.6 root 7181:
7182: if (base == 0) {
1.1.1.7 ! root 7183: gen_load_gpr(t0, index);
1.1.1.6 root 7184: } else if (index == 0) {
1.1.1.7 ! root 7185: gen_load_gpr(t0, base);
1.1.1.6 root 7186: } else {
1.1.1.7 ! root 7187: gen_load_gpr(t0, index);
! 7188: gen_op_addr_add(ctx, t0, cpu_gpr[base]);
1.1.1.6 root 7189: }
7190: /* Don't do NOP if destination is zero: we must perform the actual
7191: memory access. */
7192: switch (opc) {
7193: case OPC_LWXC1:
7194: check_cop1x(ctx);
1.1.1.7 ! root 7195: {
! 7196: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7197:
! 7198: tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
! 7199: tcg_gen_trunc_tl_i32(fp0, t1);
! 7200: gen_store_fpr32(fp0, fd);
! 7201: tcg_temp_free_i32(fp0);
! 7202: }
1.1.1.6 root 7203: opn = "lwxc1";
7204: break;
7205: case OPC_LDXC1:
7206: check_cop1x(ctx);
7207: check_cp1_registers(ctx, fd);
1.1.1.7 ! root 7208: {
! 7209: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7210:
! 7211: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
! 7212: gen_store_fpr64(ctx, fp0, fd);
! 7213: tcg_temp_free_i64(fp0);
! 7214: }
1.1.1.6 root 7215: opn = "ldxc1";
7216: break;
7217: case OPC_LUXC1:
7218: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7219: tcg_gen_andi_tl(t0, t0, ~0x7);
! 7220: {
! 7221: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7222:
! 7223: tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
! 7224: gen_store_fpr64(ctx, fp0, fd);
! 7225: tcg_temp_free_i64(fp0);
! 7226: }
1.1.1.6 root 7227: opn = "luxc1";
7228: break;
7229: case OPC_SWXC1:
7230: check_cop1x(ctx);
1.1.1.7 ! root 7231: {
! 7232: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7233:
! 7234: gen_load_fpr32(fp0, fs);
! 7235: tcg_gen_extu_i32_tl(t1, fp0);
! 7236: tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
! 7237: tcg_temp_free_i32(fp0);
! 7238: }
1.1.1.6 root 7239: opn = "swxc1";
7240: store = 1;
1.1.1.4 root 7241: break;
1.1.1.6 root 7242: case OPC_SDXC1:
7243: check_cop1x(ctx);
7244: check_cp1_registers(ctx, fs);
1.1.1.7 ! root 7245: {
! 7246: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7247:
! 7248: gen_load_fpr64(ctx, fp0, fs);
! 7249: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
! 7250: tcg_temp_free_i64(fp0);
! 7251: }
1.1.1.6 root 7252: opn = "sdxc1";
7253: store = 1;
7254: break;
7255: case OPC_SUXC1:
7256: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7257: tcg_gen_andi_tl(t0, t0, ~0x7);
! 7258: {
! 7259: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7260:
! 7261: gen_load_fpr64(ctx, fp0, fs);
! 7262: tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
! 7263: tcg_temp_free_i64(fp0);
! 7264: }
1.1.1.6 root 7265: opn = "suxc1";
7266: store = 1;
7267: break;
7268: default:
7269: MIPS_INVAL(opn);
7270: generate_exception(ctx, EXCP_RI);
1.1.1.7 ! root 7271: tcg_temp_free(t0);
! 7272: tcg_temp_free(t1);
1.1.1.6 root 7273: return;
7274: }
1.1.1.7 ! root 7275: tcg_temp_free(t0);
! 7276: tcg_temp_free(t1);
1.1.1.6 root 7277: MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7278: regnames[index], regnames[base]);
7279: }
7280:
7281: static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7282: int fd, int fr, int fs, int ft)
7283: {
7284: const char *opn = "flt3_arith";
7285:
7286: switch (opc) {
7287: case OPC_ALNV_PS:
7288: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7289: {
! 7290: TCGv t0 = tcg_temp_local_new();
! 7291: TCGv_i32 fp0 = tcg_temp_local_new_i32();
! 7292: TCGv_i32 fph0 = tcg_temp_local_new_i32();
! 7293: TCGv_i32 fp1 = tcg_temp_local_new_i32();
! 7294: TCGv_i32 fph1 = tcg_temp_local_new_i32();
! 7295: int l1 = gen_new_label();
! 7296: int l2 = gen_new_label();
! 7297:
! 7298: gen_load_gpr(t0, fr);
! 7299: tcg_gen_andi_tl(t0, t0, 0x7);
! 7300: gen_load_fpr32(fp0, fs);
! 7301: gen_load_fpr32h(fph0, fs);
! 7302: gen_load_fpr32(fp1, ft);
! 7303: gen_load_fpr32h(fph1, ft);
! 7304:
! 7305: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
! 7306: gen_store_fpr32(fp0, fd);
! 7307: gen_store_fpr32h(fph0, fd);
! 7308: tcg_gen_br(l2);
! 7309: gen_set_label(l1);
! 7310: tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
! 7311: tcg_temp_free(t0);
! 7312: #ifdef TARGET_WORDS_BIGENDIAN
! 7313: gen_store_fpr32(fph1, fd);
! 7314: gen_store_fpr32h(fp0, fd);
! 7315: #else
! 7316: gen_store_fpr32(fph0, fd);
! 7317: gen_store_fpr32h(fp1, fd);
! 7318: #endif
! 7319: gen_set_label(l2);
! 7320: tcg_temp_free_i32(fp0);
! 7321: tcg_temp_free_i32(fph0);
! 7322: tcg_temp_free_i32(fp1);
! 7323: tcg_temp_free_i32(fph1);
! 7324: }
1.1.1.6 root 7325: opn = "alnv.ps";
7326: break;
7327: case OPC_MADD_S:
7328: check_cop1x(ctx);
1.1.1.7 ! root 7329: {
! 7330: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7331: TCGv_i32 fp1 = tcg_temp_new_i32();
! 7332: TCGv_i32 fp2 = tcg_temp_new_i32();
! 7333:
! 7334: gen_load_fpr32(fp0, fs);
! 7335: gen_load_fpr32(fp1, ft);
! 7336: gen_load_fpr32(fp2, fr);
! 7337: gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
! 7338: tcg_temp_free_i32(fp0);
! 7339: tcg_temp_free_i32(fp1);
! 7340: gen_store_fpr32(fp2, fd);
! 7341: tcg_temp_free_i32(fp2);
! 7342: }
1.1.1.6 root 7343: opn = "madd.s";
1.1.1.4 root 7344: break;
1.1.1.6 root 7345: case OPC_MADD_D:
7346: check_cop1x(ctx);
7347: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 ! root 7348: {
! 7349: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7350: TCGv_i64 fp1 = tcg_temp_new_i64();
! 7351: TCGv_i64 fp2 = tcg_temp_new_i64();
! 7352:
! 7353: gen_load_fpr64(ctx, fp0, fs);
! 7354: gen_load_fpr64(ctx, fp1, ft);
! 7355: gen_load_fpr64(ctx, fp2, fr);
! 7356: gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
! 7357: tcg_temp_free_i64(fp0);
! 7358: tcg_temp_free_i64(fp1);
! 7359: gen_store_fpr64(ctx, fp2, fd);
! 7360: tcg_temp_free_i64(fp2);
! 7361: }
1.1.1.6 root 7362: opn = "madd.d";
7363: break;
7364: case OPC_MADD_PS:
7365: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7366: {
! 7367: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7368: TCGv_i64 fp1 = tcg_temp_new_i64();
! 7369: TCGv_i64 fp2 = tcg_temp_new_i64();
! 7370:
! 7371: gen_load_fpr64(ctx, fp0, fs);
! 7372: gen_load_fpr64(ctx, fp1, ft);
! 7373: gen_load_fpr64(ctx, fp2, fr);
! 7374: gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
! 7375: tcg_temp_free_i64(fp0);
! 7376: tcg_temp_free_i64(fp1);
! 7377: gen_store_fpr64(ctx, fp2, fd);
! 7378: tcg_temp_free_i64(fp2);
! 7379: }
1.1.1.6 root 7380: opn = "madd.ps";
1.1.1.4 root 7381: break;
1.1.1.6 root 7382: case OPC_MSUB_S:
7383: check_cop1x(ctx);
1.1.1.7 ! root 7384: {
! 7385: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7386: TCGv_i32 fp1 = tcg_temp_new_i32();
! 7387: TCGv_i32 fp2 = tcg_temp_new_i32();
! 7388:
! 7389: gen_load_fpr32(fp0, fs);
! 7390: gen_load_fpr32(fp1, ft);
! 7391: gen_load_fpr32(fp2, fr);
! 7392: gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
! 7393: tcg_temp_free_i32(fp0);
! 7394: tcg_temp_free_i32(fp1);
! 7395: gen_store_fpr32(fp2, fd);
! 7396: tcg_temp_free_i32(fp2);
! 7397: }
1.1.1.6 root 7398: opn = "msub.s";
1.1.1.4 root 7399: break;
1.1.1.6 root 7400: case OPC_MSUB_D:
7401: check_cop1x(ctx);
7402: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 ! root 7403: {
! 7404: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7405: TCGv_i64 fp1 = tcg_temp_new_i64();
! 7406: TCGv_i64 fp2 = tcg_temp_new_i64();
! 7407:
! 7408: gen_load_fpr64(ctx, fp0, fs);
! 7409: gen_load_fpr64(ctx, fp1, ft);
! 7410: gen_load_fpr64(ctx, fp2, fr);
! 7411: gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
! 7412: tcg_temp_free_i64(fp0);
! 7413: tcg_temp_free_i64(fp1);
! 7414: gen_store_fpr64(ctx, fp2, fd);
! 7415: tcg_temp_free_i64(fp2);
! 7416: }
1.1.1.6 root 7417: opn = "msub.d";
7418: break;
7419: case OPC_MSUB_PS:
7420: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7421: {
! 7422: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7423: TCGv_i64 fp1 = tcg_temp_new_i64();
! 7424: TCGv_i64 fp2 = tcg_temp_new_i64();
! 7425:
! 7426: gen_load_fpr64(ctx, fp0, fs);
! 7427: gen_load_fpr64(ctx, fp1, ft);
! 7428: gen_load_fpr64(ctx, fp2, fr);
! 7429: gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
! 7430: tcg_temp_free_i64(fp0);
! 7431: tcg_temp_free_i64(fp1);
! 7432: gen_store_fpr64(ctx, fp2, fd);
! 7433: tcg_temp_free_i64(fp2);
! 7434: }
1.1.1.6 root 7435: opn = "msub.ps";
1.1.1.4 root 7436: break;
1.1.1.6 root 7437: case OPC_NMADD_S:
7438: check_cop1x(ctx);
1.1.1.7 ! root 7439: {
! 7440: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7441: TCGv_i32 fp1 = tcg_temp_new_i32();
! 7442: TCGv_i32 fp2 = tcg_temp_new_i32();
! 7443:
! 7444: gen_load_fpr32(fp0, fs);
! 7445: gen_load_fpr32(fp1, ft);
! 7446: gen_load_fpr32(fp2, fr);
! 7447: gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
! 7448: tcg_temp_free_i32(fp0);
! 7449: tcg_temp_free_i32(fp1);
! 7450: gen_store_fpr32(fp2, fd);
! 7451: tcg_temp_free_i32(fp2);
! 7452: }
1.1.1.6 root 7453: opn = "nmadd.s";
1.1.1.4 root 7454: break;
1.1.1.6 root 7455: case OPC_NMADD_D:
7456: check_cop1x(ctx);
7457: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 ! root 7458: {
! 7459: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7460: TCGv_i64 fp1 = tcg_temp_new_i64();
! 7461: TCGv_i64 fp2 = tcg_temp_new_i64();
! 7462:
! 7463: gen_load_fpr64(ctx, fp0, fs);
! 7464: gen_load_fpr64(ctx, fp1, ft);
! 7465: gen_load_fpr64(ctx, fp2, fr);
! 7466: gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
! 7467: tcg_temp_free_i64(fp0);
! 7468: tcg_temp_free_i64(fp1);
! 7469: gen_store_fpr64(ctx, fp2, fd);
! 7470: tcg_temp_free_i64(fp2);
! 7471: }
1.1.1.6 root 7472: opn = "nmadd.d";
1.1.1.5 root 7473: break;
1.1.1.6 root 7474: case OPC_NMADD_PS:
7475: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7476: {
! 7477: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7478: TCGv_i64 fp1 = tcg_temp_new_i64();
! 7479: TCGv_i64 fp2 = tcg_temp_new_i64();
! 7480:
! 7481: gen_load_fpr64(ctx, fp0, fs);
! 7482: gen_load_fpr64(ctx, fp1, ft);
! 7483: gen_load_fpr64(ctx, fp2, fr);
! 7484: gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
! 7485: tcg_temp_free_i64(fp0);
! 7486: tcg_temp_free_i64(fp1);
! 7487: gen_store_fpr64(ctx, fp2, fd);
! 7488: tcg_temp_free_i64(fp2);
! 7489: }
1.1.1.6 root 7490: opn = "nmadd.ps";
1.1.1.4 root 7491: break;
1.1.1.6 root 7492: case OPC_NMSUB_S:
7493: check_cop1x(ctx);
1.1.1.7 ! root 7494: {
! 7495: TCGv_i32 fp0 = tcg_temp_new_i32();
! 7496: TCGv_i32 fp1 = tcg_temp_new_i32();
! 7497: TCGv_i32 fp2 = tcg_temp_new_i32();
! 7498:
! 7499: gen_load_fpr32(fp0, fs);
! 7500: gen_load_fpr32(fp1, ft);
! 7501: gen_load_fpr32(fp2, fr);
! 7502: gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
! 7503: tcg_temp_free_i32(fp0);
! 7504: tcg_temp_free_i32(fp1);
! 7505: gen_store_fpr32(fp2, fd);
! 7506: tcg_temp_free_i32(fp2);
! 7507: }
1.1.1.6 root 7508: opn = "nmsub.s";
1.1.1.4 root 7509: break;
1.1.1.6 root 7510: case OPC_NMSUB_D:
7511: check_cop1x(ctx);
7512: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.7 ! root 7513: {
! 7514: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7515: TCGv_i64 fp1 = tcg_temp_new_i64();
! 7516: TCGv_i64 fp2 = tcg_temp_new_i64();
! 7517:
! 7518: gen_load_fpr64(ctx, fp0, fs);
! 7519: gen_load_fpr64(ctx, fp1, ft);
! 7520: gen_load_fpr64(ctx, fp2, fr);
! 7521: gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
! 7522: tcg_temp_free_i64(fp0);
! 7523: tcg_temp_free_i64(fp1);
! 7524: gen_store_fpr64(ctx, fp2, fd);
! 7525: tcg_temp_free_i64(fp2);
! 7526: }
1.1.1.6 root 7527: opn = "nmsub.d";
1.1.1.4 root 7528: break;
1.1.1.6 root 7529: case OPC_NMSUB_PS:
7530: check_cp1_64bitmode(ctx);
1.1.1.7 ! root 7531: {
! 7532: TCGv_i64 fp0 = tcg_temp_new_i64();
! 7533: TCGv_i64 fp1 = tcg_temp_new_i64();
! 7534: TCGv_i64 fp2 = tcg_temp_new_i64();
! 7535:
! 7536: gen_load_fpr64(ctx, fp0, fs);
! 7537: gen_load_fpr64(ctx, fp1, ft);
! 7538: gen_load_fpr64(ctx, fp2, fr);
! 7539: gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
! 7540: tcg_temp_free_i64(fp0);
! 7541: tcg_temp_free_i64(fp1);
! 7542: gen_store_fpr64(ctx, fp2, fd);
! 7543: tcg_temp_free_i64(fp2);
! 7544: }
1.1.1.6 root 7545: opn = "nmsub.ps";
1.1.1.4 root 7546: break;
1.1.1.6 root 7547: default:
7548: MIPS_INVAL(opn);
7549: generate_exception (ctx, EXCP_RI);
1.1.1.4 root 7550: return;
7551: }
1.1.1.6 root 7552: MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7553: fregnames[fs], fregnames[ft]);
1.1 root 7554: }
7555:
1.1.1.5 root 7556: /* ISA extensions (ASEs) */
7557: /* MIPS16 extension to MIPS32 */
7558: /* SmartMIPS extension to MIPS32 */
7559:
1.1.1.6 root 7560: #if defined(TARGET_MIPS64)
1.1 root 7561:
7562: /* MDMX extension to MIPS64 */
7563:
7564: #endif
7565:
1.1.1.6 root 7566: static void decode_opc (CPUState *env, DisasContext *ctx)
1.1 root 7567: {
7568: int32_t offset;
7569: int rs, rt, rd, sa;
1.1.1.5 root 7570: uint32_t op, op1, op2;
1.1 root 7571: int16_t imm;
7572:
1.1.1.4 root 7573: /* make sure instructions are on a word boundary */
7574: if (ctx->pc & 0x3) {
1.1.1.6 root 7575: env->CP0_BadVAddr = ctx->pc;
1.1.1.4 root 7576: generate_exception(ctx, EXCP_AdEL);
7577: return;
7578: }
7579:
1.1.1.7 ! root 7580: /* Handle blikely not taken case */
1.1.1.2 root 7581: if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
1.1.1.7 ! root 7582: int l1 = gen_new_label();
! 7583:
1.1.1.6 root 7584: MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
1.1.1.7 ! root 7585: tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
! 7586: {
! 7587: TCGv_i32 r_tmp = tcg_temp_new_i32();
! 7588:
! 7589: tcg_gen_movi_i32(r_tmp, ctx->hflags & ~MIPS_HFLAG_BMASK);
! 7590: tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
! 7591: tcg_temp_free_i32(r_tmp);
! 7592: }
1.1.1.6 root 7593: gen_goto_tb(ctx, 1, ctx->pc + 4);
7594: gen_set_label(l1);
1.1 root 7595: }
1.1.1.5 root 7596: op = MASK_OP_MAJOR(ctx->opcode);
7597: rs = (ctx->opcode >> 21) & 0x1f;
7598: rt = (ctx->opcode >> 16) & 0x1f;
7599: rd = (ctx->opcode >> 11) & 0x1f;
7600: sa = (ctx->opcode >> 6) & 0x1f;
1.1 root 7601: imm = (int16_t)ctx->opcode;
7602: switch (op) {
1.1.1.5 root 7603: case OPC_SPECIAL:
7604: op1 = MASK_SPECIAL(ctx->opcode);
1.1 root 7605: switch (op1) {
1.1.1.5 root 7606: case OPC_SLL: /* Arithmetic with immediate */
7607: case OPC_SRL ... OPC_SRA:
1.1.1.6 root 7608: gen_arith_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 7609: break;
1.1.1.6 root 7610: case OPC_MOVZ ... OPC_MOVN:
7611: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
1.1.1.5 root 7612: case OPC_SLLV: /* Arithmetic */
7613: case OPC_SRLV ... OPC_SRAV:
7614: case OPC_ADD ... OPC_NOR:
7615: case OPC_SLT ... OPC_SLTU:
1.1.1.6 root 7616: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 7617: break;
1.1.1.5 root 7618: case OPC_MULT ... OPC_DIVU:
1.1.1.6 root 7619: if (sa) {
7620: check_insn(env, ctx, INSN_VR54XX);
7621: op1 = MASK_MUL_VR54XX(ctx->opcode);
7622: gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7623: } else
7624: gen_muldiv(ctx, op1, rs, rt);
1.1 root 7625: break;
1.1.1.5 root 7626: case OPC_JR ... OPC_JALR:
7627: gen_compute_branch(ctx, op1, rs, rd, sa);
1.1 root 7628: return;
1.1.1.5 root 7629: case OPC_TGE ... OPC_TEQ: /* Traps */
7630: case OPC_TNE:
7631: gen_trap(ctx, op1, rs, rt, -1);
7632: break;
7633: case OPC_MFHI: /* Move from HI/LO */
7634: case OPC_MFLO:
7635: gen_HILO(ctx, op1, rd);
1.1 root 7636: break;
1.1.1.5 root 7637: case OPC_MTHI:
7638: case OPC_MTLO: /* Move to HI/LO */
7639: gen_HILO(ctx, op1, rs);
7640: break;
1.1.1.6 root 7641: case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7642: #ifdef MIPS_STRICT_STANDARD
7643: MIPS_INVAL("PMON / selsl");
7644: generate_exception(ctx, EXCP_RI);
7645: #else
1.1.1.7 ! root 7646: gen_helper_0i(pmon, sa);
1.1.1.6 root 7647: #endif
1.1.1.5 root 7648: break;
7649: case OPC_SYSCALL:
1.1 root 7650: generate_exception(ctx, EXCP_SYSCALL);
7651: break;
1.1.1.5 root 7652: case OPC_BREAK:
1.1 root 7653: generate_exception(ctx, EXCP_BREAK);
7654: break;
1.1.1.6 root 7655: case OPC_SPIM:
7656: #ifdef MIPS_STRICT_STANDARD
7657: MIPS_INVAL("SPIM");
7658: generate_exception(ctx, EXCP_RI);
7659: #else
1.1.1.5 root 7660: /* Implemented as RI exception for now. */
7661: MIPS_INVAL("spim (unofficial)");
7662: generate_exception(ctx, EXCP_RI);
1.1.1.6 root 7663: #endif
1.1 root 7664: break;
1.1.1.5 root 7665: case OPC_SYNC:
1.1.1.6 root 7666: /* Treat as NOP. */
1.1 root 7667: break;
1.1.1.2 root 7668:
1.1.1.5 root 7669: case OPC_MOVCI:
1.1.1.6 root 7670: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7671: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7672: save_cpu_state(ctx, 1);
7673: check_cp1_enabled(ctx);
7674: gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7675: (ctx->opcode >> 16) & 1);
7676: } else {
7677: generate_exception_err(ctx, EXCP_CpU, 1);
7678: }
1.1.1.2 root 7679: break;
7680:
1.1.1.6 root 7681: #if defined(TARGET_MIPS64)
1.1.1.5 root 7682: /* MIPS64 specific opcodes */
7683: case OPC_DSLL:
7684: case OPC_DSRL ... OPC_DSRA:
7685: case OPC_DSLL32:
7686: case OPC_DSRL32 ... OPC_DSRA32:
1.1.1.6 root 7687: check_insn(env, ctx, ISA_MIPS3);
7688: check_mips_64(ctx);
7689: gen_arith_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 7690: break;
7691: case OPC_DSLLV:
7692: case OPC_DSRLV ... OPC_DSRAV:
7693: case OPC_DADD ... OPC_DSUBU:
1.1.1.6 root 7694: check_insn(env, ctx, ISA_MIPS3);
7695: check_mips_64(ctx);
7696: gen_arith(env, ctx, op1, rd, rs, rt);
1.1.1.5 root 7697: break;
7698: case OPC_DMULT ... OPC_DDIVU:
1.1.1.6 root 7699: check_insn(env, ctx, ISA_MIPS3);
7700: check_mips_64(ctx);
1.1.1.5 root 7701: gen_muldiv(ctx, op1, rs, rt);
7702: break;
1.1 root 7703: #endif
7704: default: /* Invalid */
7705: MIPS_INVAL("special");
7706: generate_exception(ctx, EXCP_RI);
7707: break;
7708: }
7709: break;
1.1.1.5 root 7710: case OPC_SPECIAL2:
7711: op1 = MASK_SPECIAL2(ctx->opcode);
1.1 root 7712: switch (op1) {
1.1.1.5 root 7713: case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7714: case OPC_MSUB ... OPC_MSUBU:
1.1.1.6 root 7715: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 7716: gen_muldiv(ctx, op1, rs, rt);
1.1 root 7717: break;
1.1.1.5 root 7718: case OPC_MUL:
1.1.1.6 root 7719: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 7720: break;
1.1.1.5 root 7721: case OPC_CLZ ... OPC_CLO:
1.1.1.6 root 7722: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 7723: gen_cl(ctx, op1, rd, rs);
1.1 root 7724: break;
1.1.1.5 root 7725: case OPC_SDBBP:
1.1 root 7726: /* XXX: not clear which exception should be raised
7727: * when in debug mode...
7728: */
1.1.1.6 root 7729: check_insn(env, ctx, ISA_MIPS32);
1.1 root 7730: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7731: generate_exception(ctx, EXCP_DBp);
7732: } else {
7733: generate_exception(ctx, EXCP_DBp);
7734: }
1.1.1.6 root 7735: /* Treat as NOP. */
1.1 root 7736: break;
1.1.1.6 root 7737: #if defined(TARGET_MIPS64)
1.1.1.5 root 7738: case OPC_DCLZ ... OPC_DCLO:
1.1.1.6 root 7739: check_insn(env, ctx, ISA_MIPS64);
7740: check_mips_64(ctx);
1.1.1.5 root 7741: gen_cl(ctx, op1, rd, rs);
7742: break;
7743: #endif
1.1 root 7744: default: /* Invalid */
7745: MIPS_INVAL("special2");
7746: generate_exception(ctx, EXCP_RI);
7747: break;
7748: }
7749: break;
1.1.1.5 root 7750: case OPC_SPECIAL3:
1.1.1.7 ! root 7751: op1 = MASK_SPECIAL3(ctx->opcode);
! 7752: switch (op1) {
! 7753: case OPC_EXT:
! 7754: case OPC_INS:
! 7755: check_insn(env, ctx, ISA_MIPS32R2);
! 7756: gen_bitops(ctx, op1, rt, rs, sa, rd);
! 7757: break;
! 7758: case OPC_BSHFL:
! 7759: check_insn(env, ctx, ISA_MIPS32R2);
! 7760: op2 = MASK_BSHFL(ctx->opcode);
! 7761: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 7762: break;
7763: case OPC_RDHWR:
7764: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 7765: {
! 7766: TCGv t0 = tcg_temp_local_new();
! 7767:
! 7768: switch (rd) {
! 7769: case 0:
! 7770: save_cpu_state(ctx, 1);
! 7771: gen_helper_rdhwr_cpunum(t0);
! 7772: break;
! 7773: case 1:
! 7774: save_cpu_state(ctx, 1);
! 7775: gen_helper_rdhwr_synci_step(t0);
! 7776: break;
! 7777: case 2:
! 7778: save_cpu_state(ctx, 1);
! 7779: gen_helper_rdhwr_cc(t0);
! 7780: break;
! 7781: case 3:
! 7782: save_cpu_state(ctx, 1);
! 7783: gen_helper_rdhwr_ccres(t0);
! 7784: break;
! 7785: case 29:
! 7786: #if defined(CONFIG_USER_ONLY)
! 7787: tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
! 7788: break;
! 7789: #else
! 7790: /* XXX: Some CPUs implement this in hardware.
! 7791: Not supported yet. */
1.1.1.6 root 7792: #endif
1.1.1.7 ! root 7793: default: /* Invalid */
! 7794: MIPS_INVAL("rdhwr");
! 7795: generate_exception(ctx, EXCP_RI);
! 7796: break;
! 7797: }
! 7798: gen_store_gpr(t0, rt);
! 7799: tcg_temp_free(t0);
1.1.1.6 root 7800: }
7801: break;
7802: case OPC_FORK:
7803: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 7804: {
! 7805: TCGv t0 = tcg_temp_local_new();
! 7806: TCGv t1 = tcg_temp_local_new();
! 7807:
! 7808: gen_load_gpr(t0, rt);
! 7809: gen_load_gpr(t1, rs);
! 7810: gen_helper_fork(t0, t1);
! 7811: tcg_temp_free(t0);
! 7812: tcg_temp_free(t1);
! 7813: }
1.1.1.6 root 7814: break;
7815: case OPC_YIELD:
7816: check_insn(env, ctx, ASE_MT);
1.1.1.7 ! root 7817: {
! 7818: TCGv t0 = tcg_temp_local_new();
! 7819:
! 7820: gen_load_gpr(t0, rs);
! 7821: gen_helper_yield(t0, t0);
! 7822: gen_store_gpr(t0, rd);
! 7823: tcg_temp_free(t0);
! 7824: }
1.1.1.6 root 7825: break;
7826: #if defined(TARGET_MIPS64)
7827: case OPC_DEXTM ... OPC_DEXT:
7828: case OPC_DINSM ... OPC_DINS:
7829: check_insn(env, ctx, ISA_MIPS64R2);
7830: check_mips_64(ctx);
1.1.1.5 root 7831: gen_bitops(ctx, op1, rt, rs, sa, rd);
7832: break;
1.1.1.6 root 7833: case OPC_DBSHFL:
7834: check_insn(env, ctx, ISA_MIPS64R2);
7835: check_mips_64(ctx);
7836: op2 = MASK_DBSHFL(ctx->opcode);
1.1.1.7 ! root 7837: gen_bshfl(ctx, op2, rt, rd);
1.1.1.6 root 7838: break;
1.1.1.5 root 7839: #endif
7840: default: /* Invalid */
7841: MIPS_INVAL("special3");
7842: generate_exception(ctx, EXCP_RI);
7843: break;
7844: }
7845: break;
7846: case OPC_REGIMM:
7847: op1 = MASK_REGIMM(ctx->opcode);
1.1 root 7848: switch (op1) {
1.1.1.5 root 7849: case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7850: case OPC_BLTZAL ... OPC_BGEZALL:
7851: gen_compute_branch(ctx, op1, rs, -1, imm << 2);
1.1 root 7852: return;
1.1.1.5 root 7853: case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7854: case OPC_TNEI:
7855: gen_trap(ctx, op1, rs, -1, imm);
7856: break;
7857: case OPC_SYNCI:
1.1.1.6 root 7858: check_insn(env, ctx, ISA_MIPS32R2);
7859: /* Treat as NOP. */
1.1 root 7860: break;
7861: default: /* Invalid */
1.1.1.6 root 7862: MIPS_INVAL("regimm");
1.1 root 7863: generate_exception(ctx, EXCP_RI);
7864: break;
7865: }
7866: break;
1.1.1.5 root 7867: case OPC_CP0:
1.1.1.6 root 7868: check_cp0_enabled(ctx);
1.1.1.5 root 7869: op1 = MASK_CP0(ctx->opcode);
1.1 root 7870: switch (op1) {
1.1.1.5 root 7871: case OPC_MFC0:
7872: case OPC_MTC0:
1.1.1.6 root 7873: case OPC_MFTR:
7874: case OPC_MTTR:
7875: #if defined(TARGET_MIPS64)
1.1.1.5 root 7876: case OPC_DMFC0:
7877: case OPC_DMTC0:
7878: #endif
1.1.1.7 ! root 7879: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 7880: gen_cp0(env, ctx, op1, rt, rd);
1.1.1.7 ! root 7881: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 7882: break;
7883: case OPC_C0_FIRST ... OPC_C0_LAST:
1.1.1.7 ! root 7884: #ifndef CONFIG_USER_ONLY
1.1.1.6 root 7885: gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
1.1.1.7 ! root 7886: #endif /* !CONFIG_USER_ONLY */
1.1.1.5 root 7887: break;
7888: case OPC_MFMC0:
1.1.1.7 ! root 7889: #ifndef CONFIG_USER_ONLY
! 7890: {
! 7891: TCGv t0 = tcg_temp_local_new();
! 7892:
! 7893: op2 = MASK_MFMC0(ctx->opcode);
! 7894: switch (op2) {
! 7895: case OPC_DMT:
! 7896: check_insn(env, ctx, ASE_MT);
! 7897: gen_helper_dmt(t0, t0);
! 7898: break;
! 7899: case OPC_EMT:
! 7900: check_insn(env, ctx, ASE_MT);
! 7901: gen_helper_emt(t0, t0);
! 7902: break;
! 7903: case OPC_DVPE:
! 7904: check_insn(env, ctx, ASE_MT);
! 7905: gen_helper_dvpe(t0, t0);
! 7906: break;
! 7907: case OPC_EVPE:
! 7908: check_insn(env, ctx, ASE_MT);
! 7909: gen_helper_evpe(t0, t0);
! 7910: break;
! 7911: case OPC_DI:
! 7912: check_insn(env, ctx, ISA_MIPS32R2);
! 7913: save_cpu_state(ctx, 1);
! 7914: gen_helper_di(t0);
! 7915: /* Stop translation as we may have switched the execution mode */
! 7916: ctx->bstate = BS_STOP;
! 7917: break;
! 7918: case OPC_EI:
! 7919: check_insn(env, ctx, ISA_MIPS32R2);
! 7920: save_cpu_state(ctx, 1);
! 7921: gen_helper_ei(t0);
! 7922: /* Stop translation as we may have switched the execution mode */
! 7923: ctx->bstate = BS_STOP;
! 7924: break;
! 7925: default: /* Invalid */
! 7926: MIPS_INVAL("mfmc0");
! 7927: generate_exception(ctx, EXCP_RI);
! 7928: break;
! 7929: }
! 7930: gen_store_gpr(t0, rt);
! 7931: tcg_temp_free(t0);
1.1.1.5 root 7932: }
1.1.1.7 ! root 7933: #endif /* !CONFIG_USER_ONLY */
1.1 root 7934: break;
1.1.1.5 root 7935: case OPC_RDPGPR:
1.1.1.6 root 7936: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 7937: gen_load_srsgpr(rt, rd);
1.1.1.6 root 7938: break;
1.1.1.5 root 7939: case OPC_WRPGPR:
1.1.1.6 root 7940: check_insn(env, ctx, ISA_MIPS32R2);
1.1.1.7 ! root 7941: gen_store_srsgpr(rt, rd);
1.1.1.6 root 7942: break;
1.1 root 7943: default:
1.1.1.6 root 7944: MIPS_INVAL("cp0");
1.1.1.5 root 7945: generate_exception(ctx, EXCP_RI);
1.1 root 7946: break;
7947: }
7948: break;
1.1.1.5 root 7949: case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
1.1.1.6 root 7950: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 7951: break;
7952: case OPC_J ... OPC_JAL: /* Jump */
7953: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7954: gen_compute_branch(ctx, op, rs, rt, offset);
7955: return;
7956: case OPC_BEQ ... OPC_BGTZ: /* Branch */
7957: case OPC_BEQL ... OPC_BGTZL:
7958: gen_compute_branch(ctx, op, rs, rt, imm << 2);
7959: return;
7960: case OPC_LB ... OPC_LWR: /* Load and stores */
7961: case OPC_SB ... OPC_SW:
7962: case OPC_SWR:
7963: case OPC_LL:
7964: case OPC_SC:
7965: gen_ldst(ctx, op, rt, rs, imm);
7966: break;
7967: case OPC_CACHE:
1.1.1.6 root 7968: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
7969: /* Treat as NOP. */
7970: break;
1.1.1.5 root 7971: case OPC_PREF:
1.1.1.6 root 7972: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7973: /* Treat as NOP. */
1.1 root 7974: break;
1.1.1.2 root 7975:
1.1.1.6 root 7976: /* Floating point (COP1). */
1.1.1.5 root 7977: case OPC_LWC1:
7978: case OPC_LDC1:
7979: case OPC_SWC1:
7980: case OPC_SDC1:
1.1.1.6 root 7981: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7982: save_cpu_state(ctx, 1);
7983: check_cp1_enabled(ctx);
7984: gen_flt_ldst(ctx, op, rt, rs, imm);
7985: } else {
7986: generate_exception_err(ctx, EXCP_CpU, 1);
7987: }
1.1.1.4 root 7988: break;
7989:
1.1.1.5 root 7990: case OPC_CP1:
1.1.1.6 root 7991: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7992: save_cpu_state(ctx, 1);
7993: check_cp1_enabled(ctx);
7994: op1 = MASK_CP1(ctx->opcode);
7995: switch (op1) {
7996: case OPC_MFHC1:
7997: case OPC_MTHC1:
7998: check_insn(env, ctx, ISA_MIPS32R2);
7999: case OPC_MFC1:
8000: case OPC_CFC1:
8001: case OPC_MTC1:
8002: case OPC_CTC1:
8003: gen_cp1(ctx, op1, rt, rd);
8004: break;
8005: #if defined(TARGET_MIPS64)
8006: case OPC_DMFC1:
8007: case OPC_DMTC1:
8008: check_insn(env, ctx, ISA_MIPS3);
8009: gen_cp1(ctx, op1, rt, rd);
8010: break;
1.1.1.5 root 8011: #endif
1.1.1.6 root 8012: case OPC_BC1ANY2:
8013: case OPC_BC1ANY4:
8014: check_cop1x(ctx);
8015: check_insn(env, ctx, ASE_MIPS3D);
8016: /* fall through */
8017: case OPC_BC1:
8018: gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8019: (rt >> 2) & 0x7, imm << 2);
8020: return;
8021: case OPC_S_FMT:
8022: case OPC_D_FMT:
8023: case OPC_W_FMT:
8024: case OPC_L_FMT:
8025: case OPC_PS_FMT:
8026: gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8027: (imm >> 8) & 0x7);
8028: break;
8029: default:
8030: MIPS_INVAL("cp1");
8031: generate_exception (ctx, EXCP_RI);
8032: break;
8033: }
8034: } else {
8035: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.4 root 8036: }
1.1.1.2 root 8037: break;
8038:
8039: /* COP2. */
1.1.1.5 root 8040: case OPC_LWC2:
8041: case OPC_LDC2:
8042: case OPC_SWC2:
8043: case OPC_SDC2:
8044: case OPC_CP2:
8045: /* COP2: Not implemented. */
1.1.1.2 root 8046: generate_exception_err(ctx, EXCP_CpU, 2);
8047: break;
8048:
1.1.1.5 root 8049: case OPC_CP3:
1.1.1.6 root 8050: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8051: save_cpu_state(ctx, 1);
8052: check_cp1_enabled(ctx);
8053: op1 = MASK_CP3(ctx->opcode);
8054: switch (op1) {
8055: case OPC_LWXC1:
8056: case OPC_LDXC1:
8057: case OPC_LUXC1:
8058: case OPC_SWXC1:
8059: case OPC_SDXC1:
8060: case OPC_SUXC1:
8061: gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8062: break;
8063: case OPC_PREFX:
8064: /* Treat as NOP. */
8065: break;
8066: case OPC_ALNV_PS:
8067: case OPC_MADD_S:
8068: case OPC_MADD_D:
8069: case OPC_MADD_PS:
8070: case OPC_MSUB_S:
8071: case OPC_MSUB_D:
8072: case OPC_MSUB_PS:
8073: case OPC_NMADD_S:
8074: case OPC_NMADD_D:
8075: case OPC_NMADD_PS:
8076: case OPC_NMSUB_S:
8077: case OPC_NMSUB_D:
8078: case OPC_NMSUB_PS:
8079: gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8080: break;
8081: default:
8082: MIPS_INVAL("cp3");
8083: generate_exception (ctx, EXCP_RI);
8084: break;
8085: }
8086: } else {
8087: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.5 root 8088: }
1.1.1.2 root 8089: break;
8090:
1.1.1.6 root 8091: #if defined(TARGET_MIPS64)
1.1.1.5 root 8092: /* MIPS64 opcodes */
8093: case OPC_LWU:
8094: case OPC_LDL ... OPC_LDR:
8095: case OPC_SDL ... OPC_SDR:
8096: case OPC_LLD:
8097: case OPC_LD:
8098: case OPC_SCD:
8099: case OPC_SD:
1.1.1.6 root 8100: check_insn(env, ctx, ISA_MIPS3);
8101: check_mips_64(ctx);
1.1.1.5 root 8102: gen_ldst(ctx, op, rt, rs, imm);
8103: break;
8104: case OPC_DADDI ... OPC_DADDIU:
1.1.1.6 root 8105: check_insn(env, ctx, ISA_MIPS3);
8106: check_mips_64(ctx);
8107: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 8108: break;
8109: #endif
8110: case OPC_JALX:
1.1.1.6 root 8111: check_insn(env, ctx, ASE_MIPS16);
1.1.1.5 root 8112: /* MIPS16: Not implemented. */
8113: case OPC_MDMX:
1.1.1.6 root 8114: check_insn(env, ctx, ASE_MDMX);
1.1.1.5 root 8115: /* MDMX: Not implemented. */
1.1 root 8116: default: /* Invalid */
1.1.1.6 root 8117: MIPS_INVAL("major opcode");
1.1 root 8118: generate_exception(ctx, EXCP_RI);
8119: break;
8120: }
1.1.1.2 root 8121: if (ctx->hflags & MIPS_HFLAG_BMASK) {
1.1.1.6 root 8122: int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
1.1 root 8123: /* Branches completion */
1.1.1.2 root 8124: ctx->hflags &= ~MIPS_HFLAG_BMASK;
1.1 root 8125: ctx->bstate = BS_BRANCH;
8126: save_cpu_state(ctx, 0);
1.1.1.7 ! root 8127: /* FIXME: Need to clear can_do_io. */
1.1.1.6 root 8128: switch (hflags) {
1.1 root 8129: case MIPS_HFLAG_B:
8130: /* unconditional branch */
8131: MIPS_DEBUG("unconditional branch");
1.1.1.2 root 8132: gen_goto_tb(ctx, 0, ctx->btarget);
1.1 root 8133: break;
8134: case MIPS_HFLAG_BL:
8135: /* blikely taken case */
8136: MIPS_DEBUG("blikely branch taken");
1.1.1.2 root 8137: gen_goto_tb(ctx, 0, ctx->btarget);
1.1 root 8138: break;
8139: case MIPS_HFLAG_BC:
8140: /* Conditional branch */
8141: MIPS_DEBUG("conditional branch");
1.1.1.2 root 8142: {
1.1.1.7 ! root 8143: int l1 = gen_new_label();
! 8144:
! 8145: tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
! 8146: gen_goto_tb(ctx, 1, ctx->pc + 4);
! 8147: gen_set_label(l1);
! 8148: gen_goto_tb(ctx, 0, ctx->btarget);
1.1.1.2 root 8149: }
1.1 root 8150: break;
8151: case MIPS_HFLAG_BR:
8152: /* unconditional branch to register */
8153: MIPS_DEBUG("branch to register");
1.1.1.7 ! root 8154: tcg_gen_mov_tl(cpu_PC, btarget);
! 8155: tcg_gen_exit_tb(0);
1.1 root 8156: break;
8157: default:
8158: MIPS_DEBUG("unknown branch");
8159: break;
8160: }
8161: }
8162: }
8163:
1.1.1.7 ! root 8164: static inline void
1.1.1.6 root 8165: gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8166: int search_pc)
1.1 root 8167: {
1.1.1.6 root 8168: DisasContext ctx;
1.1 root 8169: target_ulong pc_start;
8170: uint16_t *gen_opc_end;
1.1.1.7 ! root 8171: CPUBreakpoint *bp;
1.1 root 8172: int j, lj = -1;
1.1.1.7 ! root 8173: int num_insns;
! 8174: int max_insns;
1.1 root 8175:
1.1.1.7 ! root 8176: if (search_pc)
! 8177: qemu_log("search pc %d\n", search_pc);
1.1.1.2 root 8178:
1.1 root 8179: pc_start = tb->pc;
1.1.1.7 ! root 8180: /* Leave some spare opc slots for branch handling. */
! 8181: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
1.1 root 8182: ctx.pc = pc_start;
1.1.1.2 root 8183: ctx.saved_pc = -1;
1.1 root 8184: ctx.tb = tb;
8185: ctx.bstate = BS_NONE;
1.1.1.2 root 8186: /* Restore delay slot state from the tb context. */
1.1.1.6 root 8187: ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8188: restore_cpu_state(env, &ctx);
1.1.1.7 ! root 8189: #ifdef CONFIG_USER_ONLY
! 8190: ctx.mem_idx = MIPS_HFLAG_UM;
1.1 root 8191: #else
1.1.1.7 ! root 8192: ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
1.1 root 8193: #endif
1.1.1.7 ! root 8194: num_insns = 0;
! 8195: max_insns = tb->cflags & CF_COUNT_MASK;
! 8196: if (max_insns == 0)
! 8197: max_insns = CF_COUNT_MASK;
1.1 root 8198: #ifdef DEBUG_DISAS
1.1.1.7 ! root 8199: qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
! 8200: /* FIXME: This may print out stale hflags from env... */
! 8201: log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
! 8202: #endif
! 8203: LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
! 8204: gen_icount_start();
! 8205: while (ctx.bstate == BS_NONE) {
! 8206: if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
! 8207: TAILQ_FOREACH(bp, &env->breakpoints, entry) {
! 8208: if (bp->pc == ctx.pc) {
1.1.1.6 root 8209: save_cpu_state(&ctx, 1);
1.1.1.2 root 8210: ctx.bstate = BS_BRANCH;
1.1.1.7 ! root 8211: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 8212: /* Include the breakpoint location or the tb won't
8213: * be flushed when it must be. */
8214: ctx.pc += 4;
1.1.1.2 root 8215: goto done_generating;
8216: }
8217: }
8218: }
8219:
1.1 root 8220: if (search_pc) {
8221: j = gen_opc_ptr - gen_opc_buf;
8222: if (lj < j) {
8223: lj++;
8224: while (lj < j)
8225: gen_opc_instr_start[lj++] = 0;
8226: }
1.1.1.2 root 8227: gen_opc_pc[lj] = ctx.pc;
8228: gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8229: gen_opc_instr_start[lj] = 1;
1.1.1.7 ! root 8230: gen_opc_icount[lj] = num_insns;
1.1 root 8231: }
1.1.1.7 ! root 8232: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
! 8233: gen_io_start();
1.1 root 8234: ctx.opcode = ldl_code(ctx.pc);
1.1.1.6 root 8235: decode_opc(env, &ctx);
1.1 root 8236: ctx.pc += 4;
1.1.1.7 ! root 8237: num_insns++;
1.1.1.2 root 8238:
8239: if (env->singlestep_enabled)
8240: break;
8241:
1.1 root 8242: if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8243: break;
1.1.1.2 root 8244:
1.1.1.7 ! root 8245: if (gen_opc_ptr >= gen_opc_end)
! 8246: break;
! 8247:
! 8248: if (num_insns >= max_insns)
! 8249: break;
1.1 root 8250: #if defined (MIPS_SINGLE_STEP)
8251: break;
8252: #endif
8253: }
1.1.1.7 ! root 8254: if (tb->cflags & CF_LAST_IO)
! 8255: gen_io_end();
1.1.1.2 root 8256: if (env->singlestep_enabled) {
1.1.1.6 root 8257: save_cpu_state(&ctx, ctx.bstate == BS_NONE);
1.1.1.7 ! root 8258: gen_helper_0i(raise_exception, EXCP_DEBUG);
1.1.1.6 root 8259: } else {
1.1.1.7 ! root 8260: switch (ctx.bstate) {
1.1.1.6 root 8261: case BS_STOP:
1.1.1.7 ! root 8262: gen_helper_interrupt_restart();
1.1.1.6 root 8263: gen_goto_tb(&ctx, 0, ctx.pc);
8264: break;
8265: case BS_NONE:
8266: save_cpu_state(&ctx, 0);
8267: gen_goto_tb(&ctx, 0, ctx.pc);
8268: break;
8269: case BS_EXCP:
1.1.1.7 ! root 8270: gen_helper_interrupt_restart();
! 8271: tcg_gen_exit_tb(0);
1.1.1.6 root 8272: break;
8273: case BS_BRANCH:
8274: default:
8275: break;
1.1.1.7 ! root 8276: }
1.1 root 8277: }
1.1.1.2 root 8278: done_generating:
1.1.1.7 ! root 8279: gen_icount_end(tb, num_insns);
1.1 root 8280: *gen_opc_ptr = INDEX_op_end;
8281: if (search_pc) {
8282: j = gen_opc_ptr - gen_opc_buf;
8283: lj++;
8284: while (lj <= j)
8285: gen_opc_instr_start[lj++] = 0;
8286: } else {
8287: tb->size = ctx.pc - pc_start;
1.1.1.7 ! root 8288: tb->icount = num_insns;
1.1 root 8289: }
8290: #ifdef DEBUG_DISAS
1.1.1.7 ! root 8291: LOG_DISAS("\n");
! 8292: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
! 8293: qemu_log("IN: %s\n", lookup_symbol(pc_start));
! 8294: log_target_disas(pc_start, ctx.pc - pc_start, 0);
! 8295: qemu_log("\n");
1.1 root 8296: }
1.1.1.7 ! root 8297: qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
1.1 root 8298: #endif
8299: }
8300:
1.1.1.7 ! root 8301: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1.1 root 8302: {
1.1.1.7 ! root 8303: gen_intermediate_code_internal(env, tb, 0);
1.1 root 8304: }
8305:
1.1.1.7 ! root 8306: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1.1 root 8307: {
1.1.1.7 ! root 8308: gen_intermediate_code_internal(env, tb, 1);
1.1 root 8309: }
8310:
1.1.1.7 ! root 8311: static void fpu_dump_state(CPUState *env, FILE *f,
! 8312: int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
! 8313: int flags)
1.1.1.4 root 8314: {
8315: int i;
1.1.1.6 root 8316: int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
1.1.1.4 root 8317:
1.1.1.6 root 8318: #define printfpr(fp) \
8319: do { \
8320: if (is_fpu64) \
8321: fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8322: (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8323: (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8324: else { \
8325: fpr_t tmp; \
8326: tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8327: tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8328: fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8329: tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8330: tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8331: } \
1.1.1.4 root 8332: } while(0)
8333:
1.1.1.6 root 8334:
8335: 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 8336: env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
! 8337: get_float_exception_flags(&env->active_fpu.fp_status));
1.1.1.6 root 8338: for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8339: fpu_fprintf(f, "%3s: ", fregnames[i]);
1.1.1.7 ! root 8340: printfpr(&env->active_fpu.fpr[i]);
1.1.1.4 root 8341: }
8342:
8343: #undef printfpr
8344: }
8345:
1.1.1.6 root 8346: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 8347: /* Debug help: The architecture requires 32bit code to maintain proper
1.1.1.7 ! root 8348: sign-extended values on 64bit machines. */
1.1.1.5 root 8349:
8350: #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8351:
1.1.1.7 ! root 8352: static void
! 8353: cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
! 8354: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
! 8355: int flags)
1.1.1.5 root 8356: {
8357: int i;
8358:
1.1.1.7 ! root 8359: if (!SIGN_EXT_P(env->active_tc.PC))
! 8360: cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
! 8361: if (!SIGN_EXT_P(env->active_tc.HI[0]))
! 8362: cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
! 8363: if (!SIGN_EXT_P(env->active_tc.LO[0]))
! 8364: cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
1.1.1.5 root 8365: if (!SIGN_EXT_P(env->btarget))
1.1.1.6 root 8366: cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
1.1.1.5 root 8367:
8368: for (i = 0; i < 32; i++) {
1.1.1.7 ! root 8369: if (!SIGN_EXT_P(env->active_tc.gpr[i]))
! 8370: cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
1.1.1.5 root 8371: }
8372:
8373: if (!SIGN_EXT_P(env->CP0_EPC))
1.1.1.6 root 8374: cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
1.1.1.5 root 8375: if (!SIGN_EXT_P(env->CP0_LLAddr))
1.1.1.6 root 8376: cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
1.1.1.5 root 8377: }
8378: #endif
8379:
1.1.1.6 root 8380: void cpu_dump_state (CPUState *env, FILE *f,
1.1 root 8381: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8382: int flags)
8383: {
8384: int i;
1.1.1.6 root 8385:
8386: cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
1.1.1.7 ! root 8387: env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
! 8388: env->hflags, env->btarget, env->bcond);
1.1 root 8389: for (i = 0; i < 32; i++) {
8390: if ((i & 3) == 0)
8391: cpu_fprintf(f, "GPR%02d:", i);
1.1.1.7 ! root 8392: cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
1.1 root 8393: if ((i & 3) == 3)
8394: cpu_fprintf(f, "\n");
8395: }
8396:
1.1.1.6 root 8397: cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8398: env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8399: cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
1.1 root 8400: env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
1.1.1.6 root 8401: if (env->hflags & MIPS_HFLAG_FPU)
1.1.1.5 root 8402: fpu_dump_state(env, f, cpu_fprintf, flags);
1.1.1.6 root 8403: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 8404: cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
1.1.1.4 root 8405: #endif
1.1 root 8406: }
8407:
1.1.1.7 ! root 8408: static void mips_tcg_init(void)
! 8409: {
! 8410: int i;
! 8411: static int inited;
! 8412:
! 8413: /* Initialize various static tables. */
! 8414: if (inited)
! 8415: return;
! 8416:
! 8417: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
! 8418: for (i = 0; i < 32; i++)
! 8419: cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
! 8420: offsetof(CPUState, active_tc.gpr[i]),
! 8421: regnames[i]);
! 8422: cpu_PC = tcg_global_mem_new(TCG_AREG0,
! 8423: offsetof(CPUState, active_tc.PC), "PC");
! 8424: for (i = 0; i < MIPS_DSP_ACC; i++) {
! 8425: cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
! 8426: offsetof(CPUState, active_tc.HI[i]),
! 8427: regnames_HI[i]);
! 8428: cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
! 8429: offsetof(CPUState, active_tc.LO[i]),
! 8430: regnames_LO[i]);
! 8431: cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
! 8432: offsetof(CPUState, active_tc.ACX[i]),
! 8433: regnames_ACX[i]);
! 8434: }
! 8435: cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
! 8436: offsetof(CPUState, active_tc.DSPControl),
! 8437: "DSPControl");
! 8438: bcond = tcg_global_mem_new_i32(TCG_AREG0,
! 8439: offsetof(CPUState, bcond), "bcond");
! 8440: btarget = tcg_global_mem_new(TCG_AREG0,
! 8441: offsetof(CPUState, btarget), "btarget");
! 8442: for (i = 0; i < 32; i++)
! 8443: fpu_fpr32[i] = tcg_global_mem_new_i32(TCG_AREG0,
! 8444: offsetof(CPUState, active_fpu.fpr[i].w[FP_ENDIAN_IDX]),
! 8445: fregnames[i]);
! 8446: for (i = 0; i < 32; i++)
! 8447: fpu_fpr64[i] = tcg_global_mem_new_i64(TCG_AREG0,
! 8448: offsetof(CPUState, active_fpu.fpr[i]),
! 8449: fregnames_64[i]);
! 8450: for (i = 0; i < 32; i++)
! 8451: fpu_fpr32h[i] = tcg_global_mem_new_i32(TCG_AREG0,
! 8452: offsetof(CPUState, active_fpu.fpr[i].w[!FP_ENDIAN_IDX]),
! 8453: fregnames_h[i]);
! 8454: fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
! 8455: offsetof(CPUState, active_fpu.fcr0),
! 8456: "fcr0");
! 8457: fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
! 8458: offsetof(CPUState, active_fpu.fcr31),
! 8459: "fcr31");
! 8460:
! 8461: /* register helpers */
! 8462: #define GEN_HELPER 2
! 8463: #include "helper.h"
! 8464:
! 8465: inited = 1;
! 8466: }
! 8467:
1.1.1.6 root 8468: #include "translate_init.c"
8469:
8470: CPUMIPSState *cpu_mips_init (const char *cpu_model)
1.1 root 8471: {
8472: CPUMIPSState *env;
1.1.1.6 root 8473: const mips_def_t *def;
1.1 root 8474:
1.1.1.6 root 8475: def = cpu_mips_find_by_name(cpu_model);
8476: if (!def)
8477: return NULL;
1.1 root 8478: env = qemu_mallocz(sizeof(CPUMIPSState));
1.1.1.6 root 8479: env->cpu_model = def;
8480:
1.1.1.2 root 8481: cpu_exec_init(env);
1.1.1.6 root 8482: env->cpu_model_str = cpu_model;
1.1.1.7 ! root 8483: mips_tcg_init();
1.1.1.5 root 8484: cpu_reset(env);
8485: return env;
8486: }
8487:
8488: void cpu_reset (CPUMIPSState *env)
8489: {
1.1.1.7 ! root 8490: if (qemu_loglevel_mask(CPU_LOG_RESET)) {
! 8491: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
! 8492: log_cpu_state(env, 0);
! 8493: }
! 8494:
1.1.1.5 root 8495: memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8496:
1.1 root 8497: tlb_flush(env, 1);
1.1.1.5 root 8498:
1.1 root 8499: /* Minimal init */
1.1.1.7 ! root 8500: #if defined(CONFIG_USER_ONLY)
! 8501: env->hflags = MIPS_HFLAG_UM;
! 8502: #else
1.1.1.5 root 8503: if (env->hflags & MIPS_HFLAG_BMASK) {
8504: /* If the exception was raised from a delay slot,
1.1.1.7 ! root 8505: come back to the jump. */
! 8506: env->CP0_ErrorEPC = env->active_tc.PC - 4;
1.1.1.5 root 8507: } else {
1.1.1.7 ! root 8508: env->CP0_ErrorEPC = env->active_tc.PC;
1.1.1.5 root 8509: }
1.1.1.7 ! root 8510: env->active_tc.PC = (int32_t)0xBFC00000;
1.1 root 8511: env->CP0_Wired = 0;
1.1.1.5 root 8512: /* SMP not implemented */
8513: env->CP0_EBase = 0x80000000;
8514: env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
1.1.1.6 root 8515: /* vectored interrupts not implemented, timer on int 7,
8516: no performance counters. */
8517: env->CP0_IntCtl = 0xe0000000;
8518: {
8519: int i;
8520:
8521: for (i = 0; i < 7; i++) {
8522: env->CP0_WatchLo[i] = 0;
8523: env->CP0_WatchHi[i] = 0x80000000;
8524: }
8525: env->CP0_WatchLo[7] = 0;
8526: env->CP0_WatchHi[7] = 0;
8527: }
1.1 root 8528: /* Count register increments in debug mode, EJTAG version 1 */
8529: env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
1.1.1.6 root 8530: env->hflags = MIPS_HFLAG_CP0;
1.1.1.2 root 8531: #endif
1.1.1.7 ! root 8532: env->exception_index = EXCP_NONE;
1.1.1.6 root 8533: cpu_mips_register(env, env->cpu_model);
1.1 root 8534: }
1.1.1.7 ! root 8535:
! 8536: void gen_pc_load(CPUState *env, TranslationBlock *tb,
! 8537: unsigned long searched_pc, int pc_pos, void *puc)
! 8538: {
! 8539: env->active_tc.PC = gen_opc_pc[pc_pos];
! 8540: env->hflags &= ~MIPS_HFLAG_BMASK;
! 8541: env->hflags |= gen_opc_hflags[pc_pos];
! 8542: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.