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