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