|
|
1.1 root 1: /*
2: * MIPS32 emulation for qemu: main translation routines.
1.1.1.6 ! root 3: *
1.1 root 4: * Copyright (c) 2004-2005 Jocelyn Mayer
1.1.1.4 root 5: * Copyright (c) 2006 Marius Groeger (FPU operations)
1.1.1.5 root 6: * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
1.1 root 7: *
8: * This library is free software; you can redistribute it and/or
9: * modify it under the terms of the GNU Lesser General Public
10: * License as published by the Free Software Foundation; either
11: * version 2 of the License, or (at your option) any later version.
12: *
13: * This library is distributed in the hope that it will be useful,
14: * but WITHOUT ANY WARRANTY; without even the implied warranty of
15: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16: * Lesser General Public License for more details.
17: *
18: * You should have received a copy of the GNU Lesser General Public
19: * License along with this library; if not, write to the Free Software
20: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21: */
22:
23: #include <stdarg.h>
24: #include <stdlib.h>
25: #include <stdio.h>
26: #include <string.h>
27: #include <inttypes.h>
28:
29: #include "cpu.h"
30: #include "exec-all.h"
31: #include "disas.h"
32:
1.1.1.2 root 33: //#define MIPS_DEBUG_DISAS
1.1.1.5 root 34: //#define MIPS_DEBUG_SIGN_EXTENSIONS
1.1 root 35: //#define MIPS_SINGLE_STEP
36:
1.1.1.2 root 37: #ifdef USE_DIRECT_JUMP
38: #define TBPARAM(x)
39: #else
40: #define TBPARAM(x) (long)(x)
41: #endif
42:
1.1 root 43: enum {
44: #define DEF(s, n, copy_size) INDEX_op_ ## s,
45: #include "opc.h"
46: #undef DEF
47: NB_OPS,
48: };
49:
50: static uint16_t *gen_opc_ptr;
51: static uint32_t *gen_opparam_ptr;
52:
53: #include "gen-op.h"
54:
1.1.1.5 root 55: /* MIPS major opcodes */
56: #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
1.1 root 57:
58: enum {
59: /* indirect opcode tables */
1.1.1.5 root 60: OPC_SPECIAL = (0x00 << 26),
61: OPC_REGIMM = (0x01 << 26),
62: OPC_CP0 = (0x10 << 26),
63: OPC_CP1 = (0x11 << 26),
64: OPC_CP2 = (0x12 << 26),
65: OPC_CP3 = (0x13 << 26),
66: OPC_SPECIAL2 = (0x1C << 26),
67: OPC_SPECIAL3 = (0x1F << 26),
1.1 root 68: /* arithmetic with immediate */
1.1.1.5 root 69: OPC_ADDI = (0x08 << 26),
70: OPC_ADDIU = (0x09 << 26),
71: OPC_SLTI = (0x0A << 26),
72: OPC_SLTIU = (0x0B << 26),
73: OPC_ANDI = (0x0C << 26),
74: OPC_ORI = (0x0D << 26),
75: OPC_XORI = (0x0E << 26),
76: OPC_LUI = (0x0F << 26),
77: OPC_DADDI = (0x18 << 26),
78: OPC_DADDIU = (0x19 << 26),
1.1 root 79: /* Jump and branches */
1.1.1.5 root 80: OPC_J = (0x02 << 26),
81: OPC_JAL = (0x03 << 26),
82: OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
83: OPC_BEQL = (0x14 << 26),
84: OPC_BNE = (0x05 << 26),
85: OPC_BNEL = (0x15 << 26),
86: OPC_BLEZ = (0x06 << 26),
87: OPC_BLEZL = (0x16 << 26),
88: OPC_BGTZ = (0x07 << 26),
89: OPC_BGTZL = (0x17 << 26),
90: OPC_JALX = (0x1D << 26), /* MIPS 16 only */
1.1 root 91: /* Load and stores */
1.1.1.5 root 92: OPC_LDL = (0x1A << 26),
93: OPC_LDR = (0x1B << 26),
94: OPC_LB = (0x20 << 26),
95: OPC_LH = (0x21 << 26),
96: OPC_LWL = (0x22 << 26),
97: OPC_LW = (0x23 << 26),
98: OPC_LBU = (0x24 << 26),
99: OPC_LHU = (0x25 << 26),
100: OPC_LWR = (0x26 << 26),
101: OPC_LWU = (0x27 << 26),
102: OPC_SB = (0x28 << 26),
103: OPC_SH = (0x29 << 26),
104: OPC_SWL = (0x2A << 26),
105: OPC_SW = (0x2B << 26),
106: OPC_SDL = (0x2C << 26),
107: OPC_SDR = (0x2D << 26),
108: OPC_SWR = (0x2E << 26),
109: OPC_LL = (0x30 << 26),
110: OPC_LLD = (0x34 << 26),
111: OPC_LD = (0x37 << 26),
112: OPC_SC = (0x38 << 26),
113: OPC_SCD = (0x3C << 26),
114: OPC_SD = (0x3F << 26),
1.1 root 115: /* Floating point load/store */
1.1.1.5 root 116: OPC_LWC1 = (0x31 << 26),
117: OPC_LWC2 = (0x32 << 26),
118: OPC_LDC1 = (0x35 << 26),
119: OPC_LDC2 = (0x36 << 26),
120: OPC_SWC1 = (0x39 << 26),
121: OPC_SWC2 = (0x3A << 26),
122: OPC_SDC1 = (0x3D << 26),
123: OPC_SDC2 = (0x3E << 26),
124: /* MDMX ASE specific */
125: OPC_MDMX = (0x1E << 26),
1.1 root 126: /* Cache and prefetch */
1.1.1.5 root 127: OPC_CACHE = (0x2F << 26),
128: OPC_PREF = (0x33 << 26),
129: /* Reserved major opcode */
130: OPC_MAJOR3B_RESERVED = (0x3B << 26),
1.1 root 131: };
132:
133: /* MIPS special opcodes */
1.1.1.5 root 134: #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
135:
1.1 root 136: enum {
137: /* Shifts */
1.1.1.5 root 138: OPC_SLL = 0x00 | OPC_SPECIAL,
1.1 root 139: /* NOP is SLL r0, r0, 0 */
140: /* SSNOP is SLL r0, r0, 1 */
1.1.1.5 root 141: /* EHB is SLL r0, r0, 3 */
142: OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
143: OPC_SRA = 0x03 | OPC_SPECIAL,
144: OPC_SLLV = 0x04 | OPC_SPECIAL,
1.1.1.6 ! root 145: OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
1.1.1.5 root 146: OPC_SRAV = 0x07 | OPC_SPECIAL,
147: OPC_DSLLV = 0x14 | OPC_SPECIAL,
148: OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
149: OPC_DSRAV = 0x17 | OPC_SPECIAL,
150: OPC_DSLL = 0x38 | OPC_SPECIAL,
151: OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
152: OPC_DSRA = 0x3B | OPC_SPECIAL,
153: OPC_DSLL32 = 0x3C | OPC_SPECIAL,
154: OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
155: OPC_DSRA32 = 0x3F | OPC_SPECIAL,
1.1 root 156: /* Multiplication / division */
1.1.1.5 root 157: OPC_MULT = 0x18 | OPC_SPECIAL,
158: OPC_MULTU = 0x19 | OPC_SPECIAL,
159: OPC_DIV = 0x1A | OPC_SPECIAL,
160: OPC_DIVU = 0x1B | OPC_SPECIAL,
161: OPC_DMULT = 0x1C | OPC_SPECIAL,
162: OPC_DMULTU = 0x1D | OPC_SPECIAL,
163: OPC_DDIV = 0x1E | OPC_SPECIAL,
164: OPC_DDIVU = 0x1F | OPC_SPECIAL,
1.1 root 165: /* 2 registers arithmetic / logic */
1.1.1.5 root 166: OPC_ADD = 0x20 | OPC_SPECIAL,
167: OPC_ADDU = 0x21 | OPC_SPECIAL,
168: OPC_SUB = 0x22 | OPC_SPECIAL,
169: OPC_SUBU = 0x23 | OPC_SPECIAL,
170: OPC_AND = 0x24 | OPC_SPECIAL,
171: OPC_OR = 0x25 | OPC_SPECIAL,
172: OPC_XOR = 0x26 | OPC_SPECIAL,
173: OPC_NOR = 0x27 | OPC_SPECIAL,
174: OPC_SLT = 0x2A | OPC_SPECIAL,
175: OPC_SLTU = 0x2B | OPC_SPECIAL,
176: OPC_DADD = 0x2C | OPC_SPECIAL,
177: OPC_DADDU = 0x2D | OPC_SPECIAL,
178: OPC_DSUB = 0x2E | OPC_SPECIAL,
179: OPC_DSUBU = 0x2F | OPC_SPECIAL,
1.1 root 180: /* Jumps */
1.1.1.5 root 181: OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
182: OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
1.1 root 183: /* Traps */
1.1.1.5 root 184: OPC_TGE = 0x30 | OPC_SPECIAL,
185: OPC_TGEU = 0x31 | OPC_SPECIAL,
186: OPC_TLT = 0x32 | OPC_SPECIAL,
187: OPC_TLTU = 0x33 | OPC_SPECIAL,
188: OPC_TEQ = 0x34 | OPC_SPECIAL,
189: OPC_TNE = 0x36 | OPC_SPECIAL,
1.1 root 190: /* HI / LO registers load & stores */
1.1.1.5 root 191: OPC_MFHI = 0x10 | OPC_SPECIAL,
192: OPC_MTHI = 0x11 | OPC_SPECIAL,
193: OPC_MFLO = 0x12 | OPC_SPECIAL,
194: OPC_MTLO = 0x13 | OPC_SPECIAL,
1.1 root 195: /* Conditional moves */
1.1.1.5 root 196: OPC_MOVZ = 0x0A | OPC_SPECIAL,
197: OPC_MOVN = 0x0B | OPC_SPECIAL,
1.1 root 198:
1.1.1.5 root 199: OPC_MOVCI = 0x01 | OPC_SPECIAL,
1.1 root 200:
201: /* Special */
1.1.1.5 root 202: OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */
203: OPC_SYSCALL = 0x0C | OPC_SPECIAL,
204: OPC_BREAK = 0x0D | OPC_SPECIAL,
205: OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */
206: OPC_SYNC = 0x0F | OPC_SPECIAL,
207:
208: OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
209: OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
210: OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
211: OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
212: OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
213: OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
214: OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
215: };
216:
1.1.1.6 ! root 217: /* Multiplication variants of the vr54xx. */
! 218: #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
! 219:
! 220: enum {
! 221: OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
! 222: OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
! 223: OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
! 224: OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
! 225: OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
! 226: OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
! 227: OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
! 228: OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
! 229: OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
! 230: OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
! 231: OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
! 232: OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
! 233: OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
! 234: OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
! 235: };
! 236:
1.1.1.5 root 237: /* REGIMM (rt field) opcodes */
238: #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
239:
240: enum {
241: OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
242: OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
243: OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
244: OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
245: OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
246: OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
247: OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
248: OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
249: OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
250: OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
251: OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
252: OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
253: OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
254: OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
255: OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
1.1 root 256: };
257:
1.1.1.5 root 258: /* Special2 opcodes */
259: #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
260:
1.1 root 261: enum {
1.1.1.5 root 262: /* Multiply & xxx operations */
263: OPC_MADD = 0x00 | OPC_SPECIAL2,
264: OPC_MADDU = 0x01 | OPC_SPECIAL2,
265: OPC_MUL = 0x02 | OPC_SPECIAL2,
266: OPC_MSUB = 0x04 | OPC_SPECIAL2,
267: OPC_MSUBU = 0x05 | OPC_SPECIAL2,
1.1 root 268: /* Misc */
1.1.1.5 root 269: OPC_CLZ = 0x20 | OPC_SPECIAL2,
270: OPC_CLO = 0x21 | OPC_SPECIAL2,
271: OPC_DCLZ = 0x24 | OPC_SPECIAL2,
272: OPC_DCLO = 0x25 | OPC_SPECIAL2,
1.1 root 273: /* Special */
1.1.1.5 root 274: OPC_SDBBP = 0x3F | OPC_SPECIAL2,
275: };
276:
277: /* Special3 opcodes */
278: #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
279:
280: enum {
281: OPC_EXT = 0x00 | OPC_SPECIAL3,
282: OPC_DEXTM = 0x01 | OPC_SPECIAL3,
283: OPC_DEXTU = 0x02 | OPC_SPECIAL3,
284: OPC_DEXT = 0x03 | OPC_SPECIAL3,
285: OPC_INS = 0x04 | OPC_SPECIAL3,
286: OPC_DINSM = 0x05 | OPC_SPECIAL3,
287: OPC_DINSU = 0x06 | OPC_SPECIAL3,
288: OPC_DINS = 0x07 | OPC_SPECIAL3,
1.1.1.6 ! root 289: OPC_FORK = 0x08 | OPC_SPECIAL3,
! 290: OPC_YIELD = 0x09 | OPC_SPECIAL3,
1.1.1.5 root 291: OPC_BSHFL = 0x20 | OPC_SPECIAL3,
292: OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
293: OPC_RDHWR = 0x3B | OPC_SPECIAL3,
1.1 root 294: };
295:
1.1.1.5 root 296: /* BSHFL opcodes */
297: #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
298:
1.1 root 299: enum {
1.1.1.5 root 300: OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
301: OPC_SEB = (0x10 << 6) | OPC_BSHFL,
302: OPC_SEH = (0x18 << 6) | OPC_BSHFL,
1.1 root 303: };
304:
1.1.1.5 root 305: /* DBSHFL opcodes */
306: #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
307:
1.1 root 308: enum {
1.1.1.5 root 309: OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
310: OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
1.1 root 311: };
312:
1.1.1.5 root 313: /* Coprocessor 0 (rs field) */
314: #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
315:
1.1.1.4 root 316: enum {
1.1.1.5 root 317: OPC_MFC0 = (0x00 << 21) | OPC_CP0,
318: OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
319: OPC_MTC0 = (0x04 << 21) | OPC_CP0,
320: OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
1.1.1.6 ! root 321: OPC_MFTR = (0x08 << 21) | OPC_CP0,
1.1.1.5 root 322: OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
323: OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
1.1.1.6 ! root 324: OPC_MTTR = (0x0C << 21) | OPC_CP0,
1.1.1.5 root 325: OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
326: OPC_C0 = (0x10 << 21) | OPC_CP0,
327: OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
328: OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
1.1.1.4 root 329: };
1.1.1.5 root 330:
331: /* MFMC0 opcodes */
1.1.1.6 ! root 332: #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
1.1.1.5 root 333:
334: enum {
1.1.1.6 ! root 335: OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
! 336: OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
! 337: OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
! 338: OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
1.1.1.5 root 339: OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
340: OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
341: };
342:
343: /* Coprocessor 0 (with rs == C0) */
344: #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
345:
346: enum {
347: OPC_TLBR = 0x01 | OPC_C0,
348: OPC_TLBWI = 0x02 | OPC_C0,
349: OPC_TLBWR = 0x06 | OPC_C0,
350: OPC_TLBP = 0x08 | OPC_C0,
351: OPC_RFE = 0x10 | OPC_C0,
352: OPC_ERET = 0x18 | OPC_C0,
353: OPC_DERET = 0x1F | OPC_C0,
354: OPC_WAIT = 0x20 | OPC_C0,
355: };
356:
357: /* Coprocessor 1 (rs field) */
358: #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
359:
360: enum {
361: OPC_MFC1 = (0x00 << 21) | OPC_CP1,
362: OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
363: OPC_CFC1 = (0x02 << 21) | OPC_CP1,
1.1.1.6 ! root 364: OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
1.1.1.5 root 365: OPC_MTC1 = (0x04 << 21) | OPC_CP1,
366: OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
367: OPC_CTC1 = (0x06 << 21) | OPC_CP1,
1.1.1.6 ! root 368: OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
1.1.1.5 root 369: OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
1.1.1.6 ! root 370: OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
! 371: OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
1.1.1.5 root 372: OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
373: OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
374: OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
375: OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
376: OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
377: OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
1.1.1.6 ! root 378: OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
1.1.1.5 root 379: };
380:
1.1.1.6 ! root 381: #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
! 382: #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
! 383:
1.1.1.5 root 384: enum {
385: OPC_BC1F = (0x00 << 16) | OPC_BC1,
386: OPC_BC1T = (0x01 << 16) | OPC_BC1,
387: OPC_BC1FL = (0x02 << 16) | OPC_BC1,
388: OPC_BC1TL = (0x03 << 16) | OPC_BC1,
389: };
390:
1.1.1.6 ! root 391: enum {
! 392: OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
! 393: OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
! 394: };
! 395:
! 396: enum {
! 397: OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
! 398: OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
! 399: };
1.1.1.5 root 400:
401: #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1.1.1.6 ! root 402:
! 403: enum {
! 404: OPC_MFC2 = (0x00 << 21) | OPC_CP2,
! 405: OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
! 406: OPC_CFC2 = (0x02 << 21) | OPC_CP2,
! 407: OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
! 408: OPC_MTC2 = (0x04 << 21) | OPC_CP2,
! 409: OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
! 410: OPC_CTC2 = (0x06 << 21) | OPC_CP2,
! 411: OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
! 412: OPC_BC2 = (0x08 << 21) | OPC_CP2,
! 413: };
! 414:
! 415: #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
! 416:
! 417: enum {
! 418: OPC_LWXC1 = 0x00 | OPC_CP3,
! 419: OPC_LDXC1 = 0x01 | OPC_CP3,
! 420: OPC_LUXC1 = 0x05 | OPC_CP3,
! 421: OPC_SWXC1 = 0x08 | OPC_CP3,
! 422: OPC_SDXC1 = 0x09 | OPC_CP3,
! 423: OPC_SUXC1 = 0x0D | OPC_CP3,
! 424: OPC_PREFX = 0x0F | OPC_CP3,
! 425: OPC_ALNV_PS = 0x1E | OPC_CP3,
! 426: OPC_MADD_S = 0x20 | OPC_CP3,
! 427: OPC_MADD_D = 0x21 | OPC_CP3,
! 428: OPC_MADD_PS = 0x26 | OPC_CP3,
! 429: OPC_MSUB_S = 0x28 | OPC_CP3,
! 430: OPC_MSUB_D = 0x29 | OPC_CP3,
! 431: OPC_MSUB_PS = 0x2E | OPC_CP3,
! 432: OPC_NMADD_S = 0x30 | OPC_CP3,
! 433: OPC_NMADD_D = 0x31 | OPC_CP3,
! 434: OPC_NMADD_PS= 0x36 | OPC_CP3,
! 435: OPC_NMSUB_S = 0x38 | OPC_CP3,
! 436: OPC_NMSUB_D = 0x39 | OPC_CP3,
! 437: OPC_NMSUB_PS= 0x3E | OPC_CP3,
! 438: };
! 439:
1.1.1.4 root 440:
1.1 root 441: const unsigned char *regnames[] =
442: { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
443: "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
444: "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
445: "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
446:
447: /* Warning: no function for r0 register (hard wired to zero) */
1.1.1.6 ! root 448: #define GEN32(func, NAME) \
! 449: static GenOpFunc *NAME ## _table [32] = { \
! 450: NULL, NAME ## 1, NAME ## 2, NAME ## 3, \
! 451: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
! 452: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
! 453: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
! 454: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
! 455: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
! 456: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
! 457: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
! 458: }; \
! 459: static always_inline void func(int n) \
! 460: { \
! 461: NAME ## _table[n](); \
1.1 root 462: }
463:
464: /* General purpose registers moves */
465: GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
466: GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
467: GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
468:
469: GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
470: GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
471:
1.1.1.6 ! root 472: /* Moves to/from shadow registers */
! 473: GEN32(gen_op_load_srsgpr_T0, gen_op_load_srsgpr_T0_gpr);
! 474: GEN32(gen_op_store_T0_srsgpr, gen_op_store_T0_srsgpr_gpr);
1.1.1.5 root 475:
476: static const char *fregnames[] =
1.1.1.4 root 477: { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
478: "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
479: "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
480: "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
481:
1.1.1.6 ! root 482: #define FGEN32(func, NAME) \
! 483: static GenOpFunc *NAME ## _table [32] = { \
! 484: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
! 485: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
! 486: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
! 487: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
! 488: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
! 489: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
! 490: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
! 491: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
! 492: }; \
! 493: static always_inline void func(int n) \
! 494: { \
! 495: NAME ## _table[n](); \
! 496: }
! 497:
! 498: FGEN32(gen_op_load_fpr_WT0, gen_op_load_fpr_WT0_fpr);
! 499: FGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
! 500:
! 501: FGEN32(gen_op_load_fpr_WT1, gen_op_load_fpr_WT1_fpr);
! 502: FGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
! 503:
! 504: FGEN32(gen_op_load_fpr_WT2, gen_op_load_fpr_WT2_fpr);
! 505: FGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
! 506:
! 507: FGEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fpr);
! 508: FGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
! 509:
! 510: FGEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fpr);
! 511: FGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
! 512:
! 513: FGEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fpr);
! 514: FGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
! 515:
! 516: FGEN32(gen_op_load_fpr_WTH0, gen_op_load_fpr_WTH0_fpr);
! 517: FGEN32(gen_op_store_fpr_WTH0, gen_op_store_fpr_WTH0_fpr);
! 518:
! 519: FGEN32(gen_op_load_fpr_WTH1, gen_op_load_fpr_WTH1_fpr);
! 520: FGEN32(gen_op_store_fpr_WTH1, gen_op_store_fpr_WTH1_fpr);
! 521:
! 522: FGEN32(gen_op_load_fpr_WTH2, gen_op_load_fpr_WTH2_fpr);
! 523: FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr);
! 524:
! 525: #define FOP_CONDS(type, fmt) \
! 526: static GenOpFunc1 * gen_op_cmp ## type ## _ ## fmt ## _table[16] = { \
! 527: gen_op_cmp ## type ## _ ## fmt ## _f, \
! 528: gen_op_cmp ## type ## _ ## fmt ## _un, \
! 529: gen_op_cmp ## type ## _ ## fmt ## _eq, \
! 530: gen_op_cmp ## type ## _ ## fmt ## _ueq, \
! 531: gen_op_cmp ## type ## _ ## fmt ## _olt, \
! 532: gen_op_cmp ## type ## _ ## fmt ## _ult, \
! 533: gen_op_cmp ## type ## _ ## fmt ## _ole, \
! 534: gen_op_cmp ## type ## _ ## fmt ## _ule, \
! 535: gen_op_cmp ## type ## _ ## fmt ## _sf, \
! 536: gen_op_cmp ## type ## _ ## fmt ## _ngle, \
! 537: gen_op_cmp ## type ## _ ## fmt ## _seq, \
! 538: gen_op_cmp ## type ## _ ## fmt ## _ngl, \
! 539: gen_op_cmp ## type ## _ ## fmt ## _lt, \
! 540: gen_op_cmp ## type ## _ ## fmt ## _nge, \
! 541: gen_op_cmp ## type ## _ ## fmt ## _le, \
! 542: gen_op_cmp ## type ## _ ## fmt ## _ngt, \
1.1.1.4 root 543: }; \
1.1.1.6 ! root 544: static always_inline void gen_cmp ## type ## _ ## fmt(int n, long cc) \
1.1.1.4 root 545: { \
1.1.1.6 ! root 546: gen_op_cmp ## type ## _ ## fmt ## _table[n](cc); \
1.1.1.4 root 547: }
548:
1.1.1.6 ! root 549: FOP_CONDS(, d)
! 550: FOP_CONDS(abs, d)
! 551: FOP_CONDS(, s)
! 552: FOP_CONDS(abs, s)
! 553: FOP_CONDS(, ps)
! 554: FOP_CONDS(abs, ps)
1.1.1.4 root 555:
1.1 root 556: typedef struct DisasContext {
557: struct TranslationBlock *tb;
558: target_ulong pc, saved_pc;
559: uint32_t opcode;
1.1.1.6 ! root 560: uint32_t fp_status;
1.1 root 561: /* Routine used to access memory */
562: int mem_idx;
563: uint32_t hflags, saved_hflags;
564: int bstate;
565: target_ulong btarget;
1.1.1.6 ! root 566: void *last_T0_store;
! 567: int last_T0_gpr;
1.1 root 568: } DisasContext;
569:
570: enum {
571: BS_NONE = 0, /* We go out of the TB without reaching a branch or an
572: * exception condition
573: */
574: BS_STOP = 1, /* We want to stop translation for any reason */
575: BS_BRANCH = 2, /* We reached a branch condition */
576: BS_EXCP = 3, /* We reached an exception condition */
577: };
578:
1.1.1.6 ! root 579: #ifdef MIPS_DEBUG_DISAS
1.1 root 580: #define MIPS_DEBUG(fmt, args...) \
581: do { \
582: if (loglevel & CPU_LOG_TB_IN_ASM) { \
1.1.1.6 ! root 583: fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n", \
1.1 root 584: ctx->pc, ctx->opcode , ##args); \
585: } \
586: } while (0)
587: #else
588: #define MIPS_DEBUG(fmt, args...) do { } while(0)
589: #endif
590:
591: #define MIPS_INVAL(op) \
592: do { \
593: MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
594: ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
595: } while (0)
596:
1.1.1.6 ! root 597: #define GEN_LOAD_REG_T0(Rn) \
! 598: do { \
! 599: if (Rn == 0) { \
! 600: gen_op_reset_T0(); \
! 601: } else { \
! 602: if (ctx->glue(last_T0, _store) != gen_opc_ptr \
! 603: || ctx->glue(last_T0, _gpr) != Rn) { \
! 604: gen_op_load_gpr_T0(Rn); \
! 605: } \
! 606: } \
! 607: } while (0)
! 608:
! 609: #define GEN_LOAD_REG_T1(Rn) \
! 610: do { \
! 611: if (Rn == 0) { \
! 612: gen_op_reset_T1(); \
! 613: } else { \
! 614: gen_op_load_gpr_T1(Rn); \
! 615: } \
! 616: } while (0)
! 617:
! 618: #define GEN_LOAD_REG_T2(Rn) \
! 619: do { \
! 620: if (Rn == 0) { \
! 621: gen_op_reset_T2(); \
! 622: } else { \
! 623: gen_op_load_gpr_T2(Rn); \
! 624: } \
! 625: } while (0)
! 626:
! 627: #define GEN_LOAD_SRSREG_TN(Tn, Rn) \
1.1 root 628: do { \
629: if (Rn == 0) { \
630: glue(gen_op_reset_, Tn)(); \
631: } else { \
1.1.1.6 ! root 632: glue(gen_op_load_srsgpr_, Tn)(Rn); \
1.1 root 633: } \
634: } while (0)
635:
1.1.1.6 ! root 636: #if defined(TARGET_MIPS64)
! 637: #define GEN_LOAD_IMM_TN(Tn, Imm) \
! 638: do { \
! 639: if (Imm == 0) { \
! 640: glue(gen_op_reset_, Tn)(); \
! 641: } else if ((int32_t)Imm == Imm) { \
! 642: glue(gen_op_set_, Tn)(Imm); \
! 643: } else { \
! 644: glue(gen_op_set64_, Tn)(((uint64_t)Imm) >> 32, (uint32_t)Imm); \
! 645: } \
! 646: } while (0)
! 647: #else
1.1 root 648: #define GEN_LOAD_IMM_TN(Tn, Imm) \
649: do { \
650: if (Imm == 0) { \
651: glue(gen_op_reset_, Tn)(); \
652: } else { \
653: glue(gen_op_set_, Tn)(Imm); \
654: } \
655: } while (0)
1.1.1.6 ! root 656: #endif
! 657:
! 658: #define GEN_STORE_T0_REG(Rn) \
! 659: do { \
! 660: if (Rn != 0) { \
! 661: glue(gen_op_store_T0,_gpr)(Rn); \
! 662: ctx->glue(last_T0,_store) = gen_opc_ptr; \
! 663: ctx->glue(last_T0,_gpr) = Rn; \
! 664: } \
! 665: } while (0)
! 666:
! 667: #define GEN_STORE_T1_REG(Rn) \
! 668: do { \
! 669: if (Rn != 0) \
! 670: glue(gen_op_store_T1,_gpr)(Rn); \
! 671: } while (0)
1.1 root 672:
1.1.1.6 ! root 673: #define GEN_STORE_TN_SRSREG(Rn, Tn) \
1.1 root 674: do { \
675: if (Rn != 0) { \
1.1.1.6 ! root 676: glue(glue(gen_op_store_, Tn),_srsgpr)(Rn); \
1.1 root 677: } \
678: } while (0)
679:
1.1.1.5 root 680: #define GEN_LOAD_FREG_FTN(FTn, Fn) \
1.1.1.4 root 681: do { \
682: glue(gen_op_load_fpr_, FTn)(Fn); \
683: } while (0)
684:
685: #define GEN_STORE_FTN_FREG(Fn, FTn) \
686: do { \
687: glue(gen_op_store_fpr_, FTn)(Fn); \
688: } while (0)
689:
1.1.1.6 ! root 690: static always_inline void gen_save_pc(target_ulong pc)
! 691: {
! 692: #if defined(TARGET_MIPS64)
! 693: if (pc == (int32_t)pc) {
! 694: gen_op_save_pc(pc);
! 695: } else {
! 696: gen_op_save_pc64(pc >> 32, (uint32_t)pc);
! 697: }
! 698: #else
! 699: gen_op_save_pc(pc);
! 700: #endif
! 701: }
! 702:
! 703: static always_inline void gen_save_btarget(target_ulong btarget)
! 704: {
! 705: #if defined(TARGET_MIPS64)
! 706: if (btarget == (int32_t)btarget) {
! 707: gen_op_save_btarget(btarget);
! 708: } else {
! 709: gen_op_save_btarget64(btarget >> 32, (uint32_t)btarget);
! 710: }
! 711: #else
! 712: gen_op_save_btarget(btarget);
! 713: #endif
! 714: }
! 715:
! 716: static always_inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
1.1 root 717: {
718: #if defined MIPS_DEBUG_DISAS
719: if (loglevel & CPU_LOG_TB_IN_ASM) {
720: fprintf(logfile, "hflags %08x saved %08x\n",
721: ctx->hflags, ctx->saved_hflags);
722: }
723: #endif
724: if (do_save_pc && ctx->pc != ctx->saved_pc) {
1.1.1.6 ! root 725: gen_save_pc(ctx->pc);
1.1 root 726: ctx->saved_pc = ctx->pc;
727: }
728: if (ctx->hflags != ctx->saved_hflags) {
729: gen_op_save_state(ctx->hflags);
730: ctx->saved_hflags = ctx->hflags;
1.1.1.6 ! root 731: switch (ctx->hflags & MIPS_HFLAG_BMASK) {
! 732: case MIPS_HFLAG_BR:
1.1 root 733: gen_op_save_breg_target();
1.1.1.6 ! root 734: break;
! 735: case MIPS_HFLAG_BC:
1.1 root 736: gen_op_save_bcond();
1.1.1.6 ! root 737: /* fall through */
! 738: case MIPS_HFLAG_BL:
! 739: /* bcond was already saved by the BL insn */
! 740: /* fall through */
! 741: case MIPS_HFLAG_B:
! 742: gen_save_btarget(ctx->btarget);
! 743: break;
1.1 root 744: }
745: }
746: }
747:
1.1.1.6 ! root 748: static always_inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
! 749: {
! 750: ctx->saved_hflags = ctx->hflags;
! 751: switch (ctx->hflags & MIPS_HFLAG_BMASK) {
! 752: case MIPS_HFLAG_BR:
! 753: gen_op_restore_breg_target();
! 754: break;
! 755: case MIPS_HFLAG_B:
! 756: ctx->btarget = env->btarget;
! 757: break;
! 758: case MIPS_HFLAG_BC:
! 759: case MIPS_HFLAG_BL:
! 760: ctx->btarget = env->btarget;
! 761: gen_op_restore_bcond();
! 762: break;
! 763: }
! 764: }
! 765:
! 766: static always_inline void generate_exception_err (DisasContext *ctx, int excp, int err)
1.1 root 767: {
768: #if defined MIPS_DEBUG_DISAS
769: if (loglevel & CPU_LOG_TB_IN_ASM)
770: fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
771: #endif
772: save_cpu_state(ctx, 1);
1.1.1.2 root 773: if (err == 0)
774: gen_op_raise_exception(excp);
775: else
776: gen_op_raise_exception_err(excp, err);
1.1 root 777: ctx->bstate = BS_EXCP;
778: }
779:
1.1.1.6 ! root 780: static always_inline void generate_exception (DisasContext *ctx, int excp)
1.1.1.2 root 781: {
782: generate_exception_err (ctx, excp, 0);
783: }
784:
1.1.1.6 ! root 785: static always_inline void check_cp0_enabled(DisasContext *ctx)
! 786: {
! 787: if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
! 788: generate_exception_err(ctx, EXCP_CpU, 1);
! 789: }
! 790:
! 791: static always_inline void check_cp1_enabled(DisasContext *ctx)
! 792: {
! 793: if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
! 794: generate_exception_err(ctx, EXCP_CpU, 1);
! 795: }
! 796:
! 797: /* Verify that the processor is running with COP1X instructions enabled.
! 798: This is associated with the nabla symbol in the MIPS32 and MIPS64
! 799: opcode tables. */
! 800:
! 801: static always_inline void check_cop1x(DisasContext *ctx)
! 802: {
! 803: if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
! 804: generate_exception(ctx, EXCP_RI);
! 805: }
! 806:
! 807: /* Verify that the processor is running with 64-bit floating-point
! 808: operations enabled. */
! 809:
! 810: static always_inline void check_cp1_64bitmode(DisasContext *ctx)
! 811: {
! 812: if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
! 813: generate_exception(ctx, EXCP_RI);
! 814: }
! 815:
! 816: /*
! 817: * Verify if floating point register is valid; an operation is not defined
! 818: * if bit 0 of any register specification is set and the FR bit in the
! 819: * Status register equals zero, since the register numbers specify an
! 820: * even-odd pair of adjacent coprocessor general registers. When the FR bit
! 821: * in the Status register equals one, both even and odd register numbers
! 822: * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
! 823: *
! 824: * Multiple 64 bit wide registers can be checked by calling
! 825: * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
! 826: */
! 827: void check_cp1_registers(DisasContext *ctx, int regs)
! 828: {
! 829: if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
! 830: generate_exception(ctx, EXCP_RI);
! 831: }
! 832:
! 833: /* This code generates a "reserved instruction" exception if the
! 834: CPU does not support the instruction set corresponding to flags. */
! 835: static always_inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
! 836: {
! 837: if (unlikely(!(env->insn_flags & flags)))
! 838: generate_exception(ctx, EXCP_RI);
! 839: }
! 840:
! 841: /* This code generates a "reserved instruction" exception if 64-bit
! 842: instructions are not enabled. */
! 843: static always_inline void check_mips_64(DisasContext *ctx)
! 844: {
! 845: if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
! 846: generate_exception(ctx, EXCP_RI);
! 847: }
! 848:
1.1 root 849: #if defined(CONFIG_USER_ONLY)
850: #define op_ldst(name) gen_op_##name##_raw()
851: #define OP_LD_TABLE(width)
852: #define OP_ST_TABLE(width)
853: #else
854: #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
855: #define OP_LD_TABLE(width) \
856: static GenOpFunc *gen_op_l##width[] = { \
857: &gen_op_l##width##_kernel, \
1.1.1.6 ! root 858: &gen_op_l##width##_super, \
! 859: &gen_op_l##width##_user, \
1.1 root 860: }
861: #define OP_ST_TABLE(width) \
862: static GenOpFunc *gen_op_s##width[] = { \
863: &gen_op_s##width##_kernel, \
1.1.1.6 ! root 864: &gen_op_s##width##_super, \
! 865: &gen_op_s##width##_user, \
1.1 root 866: }
867: #endif
868:
1.1.1.6 ! root 869: #if defined(TARGET_MIPS64)
1.1 root 870: OP_LD_TABLE(d);
871: OP_LD_TABLE(dl);
872: OP_LD_TABLE(dr);
873: OP_ST_TABLE(d);
874: OP_ST_TABLE(dl);
875: OP_ST_TABLE(dr);
1.1.1.5 root 876: OP_LD_TABLE(ld);
877: OP_ST_TABLE(cd);
1.1.1.6 ! root 878: OP_LD_TABLE(wu);
1.1 root 879: #endif
880: OP_LD_TABLE(w);
881: OP_LD_TABLE(wl);
882: OP_LD_TABLE(wr);
883: OP_ST_TABLE(w);
884: OP_ST_TABLE(wl);
885: OP_ST_TABLE(wr);
886: OP_LD_TABLE(h);
887: OP_LD_TABLE(hu);
888: OP_ST_TABLE(h);
889: OP_LD_TABLE(b);
890: OP_LD_TABLE(bu);
891: OP_ST_TABLE(b);
892: OP_LD_TABLE(l);
893: OP_ST_TABLE(c);
1.1.1.4 root 894: OP_LD_TABLE(wc1);
895: OP_ST_TABLE(wc1);
896: OP_LD_TABLE(dc1);
897: OP_ST_TABLE(dc1);
1.1.1.6 ! root 898: OP_LD_TABLE(uxc1);
! 899: OP_ST_TABLE(uxc1);
1.1 root 900:
901: /* Load and store */
1.1.1.5 root 902: static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1.1 root 903: int base, int16_t offset)
904: {
1.1.1.6 ! root 905: const char *opn = "ldst";
1.1 root 906:
907: if (base == 0) {
908: GEN_LOAD_IMM_TN(T0, offset);
909: } else if (offset == 0) {
910: gen_op_load_gpr_T0(base);
911: } else {
912: gen_op_load_gpr_T0(base);
913: gen_op_set_T1(offset);
1.1.1.6 ! root 914: gen_op_addr_add();
1.1 root 915: }
916: /* Don't do NOP if destination is zero: we must perform the actual
1.1.1.6 ! root 917: memory access. */
1.1 root 918: switch (opc) {
1.1.1.6 ! root 919: #if defined(TARGET_MIPS64)
! 920: case OPC_LWU:
! 921: op_ldst(lwu);
! 922: GEN_STORE_T0_REG(rt);
! 923: opn = "lwu";
! 924: break;
1.1 root 925: case OPC_LD:
926: op_ldst(ld);
1.1.1.6 ! root 927: GEN_STORE_T0_REG(rt);
1.1 root 928: opn = "ld";
929: break;
1.1.1.5 root 930: case OPC_LLD:
931: op_ldst(lld);
1.1.1.6 ! root 932: GEN_STORE_T0_REG(rt);
1.1.1.5 root 933: opn = "lld";
934: break;
1.1 root 935: case OPC_SD:
1.1.1.6 ! root 936: GEN_LOAD_REG_T1(rt);
1.1 root 937: op_ldst(sd);
938: opn = "sd";
939: break;
1.1.1.5 root 940: case OPC_SCD:
1.1.1.6 ! root 941: save_cpu_state(ctx, 1);
! 942: GEN_LOAD_REG_T1(rt);
1.1.1.5 root 943: op_ldst(scd);
1.1.1.6 ! root 944: GEN_STORE_T0_REG(rt);
1.1.1.5 root 945: opn = "scd";
946: break;
1.1 root 947: case OPC_LDL:
1.1.1.6 ! root 948: GEN_LOAD_REG_T1(rt);
1.1 root 949: op_ldst(ldl);
1.1.1.6 ! root 950: GEN_STORE_T1_REG(rt);
1.1 root 951: opn = "ldl";
952: break;
953: case OPC_SDL:
1.1.1.6 ! root 954: GEN_LOAD_REG_T1(rt);
1.1 root 955: op_ldst(sdl);
956: opn = "sdl";
957: break;
958: case OPC_LDR:
1.1.1.6 ! root 959: GEN_LOAD_REG_T1(rt);
1.1 root 960: op_ldst(ldr);
1.1.1.6 ! root 961: GEN_STORE_T1_REG(rt);
1.1 root 962: opn = "ldr";
963: break;
964: case OPC_SDR:
1.1.1.6 ! root 965: GEN_LOAD_REG_T1(rt);
1.1 root 966: op_ldst(sdr);
967: opn = "sdr";
968: break;
969: #endif
970: case OPC_LW:
971: op_ldst(lw);
1.1.1.6 ! root 972: GEN_STORE_T0_REG(rt);
1.1 root 973: opn = "lw";
974: break;
975: case OPC_SW:
1.1.1.6 ! root 976: GEN_LOAD_REG_T1(rt);
1.1 root 977: op_ldst(sw);
978: opn = "sw";
979: break;
980: case OPC_LH:
981: op_ldst(lh);
1.1.1.6 ! root 982: GEN_STORE_T0_REG(rt);
1.1 root 983: opn = "lh";
984: break;
985: case OPC_SH:
1.1.1.6 ! root 986: GEN_LOAD_REG_T1(rt);
1.1 root 987: op_ldst(sh);
988: opn = "sh";
989: break;
990: case OPC_LHU:
991: op_ldst(lhu);
1.1.1.6 ! root 992: GEN_STORE_T0_REG(rt);
1.1 root 993: opn = "lhu";
994: break;
995: case OPC_LB:
996: op_ldst(lb);
1.1.1.6 ! root 997: GEN_STORE_T0_REG(rt);
1.1 root 998: opn = "lb";
999: break;
1000: case OPC_SB:
1.1.1.6 ! root 1001: GEN_LOAD_REG_T1(rt);
1.1 root 1002: op_ldst(sb);
1003: opn = "sb";
1004: break;
1005: case OPC_LBU:
1006: op_ldst(lbu);
1.1.1.6 ! root 1007: GEN_STORE_T0_REG(rt);
1.1 root 1008: opn = "lbu";
1009: break;
1010: case OPC_LWL:
1.1.1.6 ! root 1011: GEN_LOAD_REG_T1(rt);
1.1 root 1012: op_ldst(lwl);
1.1.1.6 ! root 1013: GEN_STORE_T1_REG(rt);
1.1 root 1014: opn = "lwl";
1015: break;
1016: case OPC_SWL:
1.1.1.6 ! root 1017: GEN_LOAD_REG_T1(rt);
1.1 root 1018: op_ldst(swl);
1019: opn = "swr";
1020: break;
1021: case OPC_LWR:
1.1.1.6 ! root 1022: GEN_LOAD_REG_T1(rt);
1.1 root 1023: op_ldst(lwr);
1.1.1.6 ! root 1024: GEN_STORE_T1_REG(rt);
1.1 root 1025: opn = "lwr";
1026: break;
1027: case OPC_SWR:
1.1.1.6 ! root 1028: GEN_LOAD_REG_T1(rt);
1.1 root 1029: op_ldst(swr);
1030: opn = "swr";
1031: break;
1032: case OPC_LL:
1033: op_ldst(ll);
1.1.1.6 ! root 1034: GEN_STORE_T0_REG(rt);
1.1 root 1035: opn = "ll";
1036: break;
1037: case OPC_SC:
1.1.1.6 ! root 1038: save_cpu_state(ctx, 1);
! 1039: GEN_LOAD_REG_T1(rt);
1.1 root 1040: op_ldst(sc);
1.1.1.6 ! root 1041: GEN_STORE_T0_REG(rt);
1.1 root 1042: opn = "sc";
1043: break;
1044: default:
1.1.1.6 ! root 1045: MIPS_INVAL(opn);
1.1 root 1046: generate_exception(ctx, EXCP_RI);
1047: return;
1048: }
1049: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1050: }
1051:
1.1.1.4 root 1052: /* Load and store */
1.1.1.5 root 1053: static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1.1.1.4 root 1054: int base, int16_t offset)
1055: {
1.1.1.6 ! root 1056: const char *opn = "flt_ldst";
1.1.1.4 root 1057:
1058: if (base == 0) {
1059: GEN_LOAD_IMM_TN(T0, offset);
1060: } else if (offset == 0) {
1061: gen_op_load_gpr_T0(base);
1062: } else {
1063: gen_op_load_gpr_T0(base);
1064: gen_op_set_T1(offset);
1.1.1.6 ! root 1065: gen_op_addr_add();
1.1.1.4 root 1066: }
1067: /* Don't do NOP if destination is zero: we must perform the actual
1.1.1.6 ! root 1068: memory access. */
1.1.1.4 root 1069: switch (opc) {
1070: case OPC_LWC1:
1071: op_ldst(lwc1);
1072: GEN_STORE_FTN_FREG(ft, WT0);
1073: opn = "lwc1";
1074: break;
1075: case OPC_SWC1:
1076: GEN_LOAD_FREG_FTN(WT0, ft);
1077: op_ldst(swc1);
1078: opn = "swc1";
1079: break;
1080: case OPC_LDC1:
1081: op_ldst(ldc1);
1082: GEN_STORE_FTN_FREG(ft, DT0);
1083: opn = "ldc1";
1084: break;
1085: case OPC_SDC1:
1086: GEN_LOAD_FREG_FTN(DT0, ft);
1087: op_ldst(sdc1);
1088: opn = "sdc1";
1089: break;
1090: default:
1.1.1.6 ! root 1091: MIPS_INVAL(opn);
! 1092: generate_exception(ctx, EXCP_RI);
1.1.1.4 root 1093: return;
1094: }
1095: MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1096: }
1.1.1.5 root 1097:
1.1 root 1098: /* Arithmetic with immediate operand */
1.1.1.6 ! root 1099: static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
! 1100: int rt, int rs, int16_t imm)
1.1 root 1101: {
1.1.1.6 ! root 1102: target_ulong uimm;
! 1103: const char *opn = "imm arith";
1.1 root 1104:
1.1.1.5 root 1105: if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1.1.1.6 ! root 1106: /* If no destination, treat it as a NOP.
! 1107: For addi, we must generate the overflow exception when needed. */
1.1 root 1108: MIPS_DEBUG("NOP");
1109: return;
1110: }
1.1.1.6 ! root 1111: uimm = (uint16_t)imm;
! 1112: switch (opc) {
! 1113: case OPC_ADDI:
! 1114: case OPC_ADDIU:
! 1115: #if defined(TARGET_MIPS64)
! 1116: case OPC_DADDI:
! 1117: case OPC_DADDIU:
! 1118: #endif
! 1119: case OPC_SLTI:
! 1120: case OPC_SLTIU:
! 1121: uimm = (target_long)imm; /* Sign extend to 32/64 bits */
! 1122: /* Fall through. */
! 1123: case OPC_ANDI:
! 1124: case OPC_ORI:
! 1125: case OPC_XORI:
! 1126: GEN_LOAD_REG_T0(rs);
1.1 root 1127: GEN_LOAD_IMM_TN(T1, uimm);
1.1.1.6 ! root 1128: break;
! 1129: case OPC_LUI:
! 1130: GEN_LOAD_IMM_TN(T0, imm << 16);
! 1131: break;
! 1132: case OPC_SLL:
! 1133: case OPC_SRA:
! 1134: case OPC_SRL:
! 1135: #if defined(TARGET_MIPS64)
! 1136: case OPC_DSLL:
! 1137: case OPC_DSRA:
! 1138: case OPC_DSRL:
! 1139: case OPC_DSLL32:
! 1140: case OPC_DSRA32:
! 1141: case OPC_DSRL32:
! 1142: #endif
! 1143: uimm &= 0x1f;
! 1144: GEN_LOAD_REG_T0(rs);
! 1145: GEN_LOAD_IMM_TN(T1, uimm);
! 1146: break;
1.1 root 1147: }
1148: switch (opc) {
1149: case OPC_ADDI:
1150: save_cpu_state(ctx, 1);
1151: gen_op_addo();
1152: opn = "addi";
1153: break;
1154: case OPC_ADDIU:
1155: gen_op_add();
1156: opn = "addiu";
1157: break;
1.1.1.6 ! root 1158: #if defined(TARGET_MIPS64)
1.1.1.5 root 1159: case OPC_DADDI:
1160: save_cpu_state(ctx, 1);
1161: gen_op_daddo();
1162: opn = "daddi";
1163: break;
1164: case OPC_DADDIU:
1165: gen_op_dadd();
1166: opn = "daddiu";
1167: break;
1168: #endif
1.1 root 1169: case OPC_SLTI:
1170: gen_op_lt();
1171: opn = "slti";
1172: break;
1173: case OPC_SLTIU:
1174: gen_op_ltu();
1175: opn = "sltiu";
1176: break;
1177: case OPC_ANDI:
1178: gen_op_and();
1179: opn = "andi";
1180: break;
1181: case OPC_ORI:
1182: gen_op_or();
1183: opn = "ori";
1184: break;
1185: case OPC_XORI:
1186: gen_op_xor();
1187: opn = "xori";
1188: break;
1189: case OPC_LUI:
1190: opn = "lui";
1191: break;
1192: case OPC_SLL:
1193: gen_op_sll();
1194: opn = "sll";
1195: break;
1196: case OPC_SRA:
1197: gen_op_sra();
1198: opn = "sra";
1199: break;
1200: case OPC_SRL:
1.1.1.6 ! root 1201: switch ((ctx->opcode >> 21) & 0x1f) {
! 1202: case 0:
1.1.1.5 root 1203: gen_op_srl();
1204: opn = "srl";
1.1.1.6 ! root 1205: break;
! 1206: case 1:
! 1207: /* rotr is decoded as srl on non-R2 CPUs */
! 1208: if (env->insn_flags & ISA_MIPS32R2) {
! 1209: gen_op_rotr();
! 1210: opn = "rotr";
! 1211: } else {
! 1212: gen_op_srl();
! 1213: opn = "srl";
! 1214: }
! 1215: break;
! 1216: default:
! 1217: MIPS_INVAL("invalid srl flag");
! 1218: generate_exception(ctx, EXCP_RI);
! 1219: break;
! 1220: }
1.1.1.5 root 1221: break;
1.1.1.6 ! root 1222: #if defined(TARGET_MIPS64)
1.1.1.5 root 1223: case OPC_DSLL:
1224: gen_op_dsll();
1225: opn = "dsll";
1226: break;
1227: case OPC_DSRA:
1228: gen_op_dsra();
1229: opn = "dsra";
1230: break;
1231: case OPC_DSRL:
1.1.1.6 ! root 1232: switch ((ctx->opcode >> 21) & 0x1f) {
! 1233: case 0:
1.1.1.5 root 1234: gen_op_dsrl();
1235: opn = "dsrl";
1.1.1.6 ! root 1236: break;
! 1237: case 1:
! 1238: /* drotr is decoded as dsrl on non-R2 CPUs */
! 1239: if (env->insn_flags & ISA_MIPS32R2) {
! 1240: gen_op_drotr();
! 1241: opn = "drotr";
! 1242: } else {
! 1243: gen_op_dsrl();
! 1244: opn = "dsrl";
! 1245: }
! 1246: break;
! 1247: default:
! 1248: MIPS_INVAL("invalid dsrl flag");
! 1249: generate_exception(ctx, EXCP_RI);
! 1250: break;
! 1251: }
1.1.1.5 root 1252: break;
1253: case OPC_DSLL32:
1254: gen_op_dsll32();
1255: opn = "dsll32";
1256: break;
1257: case OPC_DSRA32:
1258: gen_op_dsra32();
1259: opn = "dsra32";
1260: break;
1261: case OPC_DSRL32:
1.1.1.6 ! root 1262: switch ((ctx->opcode >> 21) & 0x1f) {
! 1263: case 0:
1.1.1.5 root 1264: gen_op_dsrl32();
1265: opn = "dsrl32";
1.1.1.6 ! root 1266: break;
! 1267: case 1:
! 1268: /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
! 1269: if (env->insn_flags & ISA_MIPS32R2) {
! 1270: gen_op_drotr32();
! 1271: opn = "drotr32";
! 1272: } else {
! 1273: gen_op_dsrl32();
! 1274: opn = "dsrl32";
! 1275: }
! 1276: break;
! 1277: default:
! 1278: MIPS_INVAL("invalid dsrl32 flag");
! 1279: generate_exception(ctx, EXCP_RI);
! 1280: break;
! 1281: }
1.1 root 1282: break;
1.1.1.5 root 1283: #endif
1.1 root 1284: default:
1.1.1.6 ! root 1285: MIPS_INVAL(opn);
1.1 root 1286: generate_exception(ctx, EXCP_RI);
1287: return;
1288: }
1.1.1.6 ! root 1289: GEN_STORE_T0_REG(rt);
! 1290: MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1.1 root 1291: }
1292:
1293: /* Arithmetic */
1.1.1.6 ! root 1294: static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1.1 root 1295: int rd, int rs, int rt)
1296: {
1.1.1.6 ! root 1297: const char *opn = "arith";
1.1 root 1298:
1.1.1.5 root 1299: if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1300: && opc != OPC_DADD && opc != OPC_DSUB) {
1.1.1.6 ! root 1301: /* If no destination, treat it as a NOP.
! 1302: For add & sub, we must generate the overflow exception when needed. */
1.1 root 1303: MIPS_DEBUG("NOP");
1304: return;
1305: }
1.1.1.6 ! root 1306: GEN_LOAD_REG_T0(rs);
! 1307: /* Specialcase the conventional move operation. */
! 1308: if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
! 1309: || opc == OPC_SUBU || opc == OPC_DSUBU)) {
! 1310: GEN_STORE_T0_REG(rd);
! 1311: return;
! 1312: }
! 1313: GEN_LOAD_REG_T1(rt);
1.1 root 1314: switch (opc) {
1315: case OPC_ADD:
1316: save_cpu_state(ctx, 1);
1317: gen_op_addo();
1318: opn = "add";
1319: break;
1320: case OPC_ADDU:
1321: gen_op_add();
1322: opn = "addu";
1323: break;
1324: case OPC_SUB:
1325: save_cpu_state(ctx, 1);
1326: gen_op_subo();
1327: opn = "sub";
1328: break;
1329: case OPC_SUBU:
1330: gen_op_sub();
1331: opn = "subu";
1332: break;
1.1.1.6 ! root 1333: #if defined(TARGET_MIPS64)
1.1.1.5 root 1334: case OPC_DADD:
1335: save_cpu_state(ctx, 1);
1336: gen_op_daddo();
1337: opn = "dadd";
1338: break;
1339: case OPC_DADDU:
1340: gen_op_dadd();
1341: opn = "daddu";
1342: break;
1343: case OPC_DSUB:
1344: save_cpu_state(ctx, 1);
1345: gen_op_dsubo();
1346: opn = "dsub";
1347: break;
1348: case OPC_DSUBU:
1349: gen_op_dsub();
1350: opn = "dsubu";
1351: break;
1352: #endif
1.1 root 1353: case OPC_SLT:
1354: gen_op_lt();
1355: opn = "slt";
1356: break;
1357: case OPC_SLTU:
1358: gen_op_ltu();
1359: opn = "sltu";
1360: break;
1361: case OPC_AND:
1362: gen_op_and();
1363: opn = "and";
1364: break;
1365: case OPC_NOR:
1366: gen_op_nor();
1367: opn = "nor";
1368: break;
1369: case OPC_OR:
1370: gen_op_or();
1371: opn = "or";
1372: break;
1373: case OPC_XOR:
1374: gen_op_xor();
1375: opn = "xor";
1376: break;
1377: case OPC_MUL:
1378: gen_op_mul();
1379: opn = "mul";
1380: break;
1381: case OPC_MOVN:
1382: gen_op_movn(rd);
1383: opn = "movn";
1384: goto print;
1385: case OPC_MOVZ:
1386: gen_op_movz(rd);
1387: opn = "movz";
1388: goto print;
1389: case OPC_SLLV:
1390: gen_op_sllv();
1391: opn = "sllv";
1392: break;
1393: case OPC_SRAV:
1394: gen_op_srav();
1395: opn = "srav";
1396: break;
1397: case OPC_SRLV:
1.1.1.6 ! root 1398: switch ((ctx->opcode >> 6) & 0x1f) {
! 1399: case 0:
1.1.1.5 root 1400: gen_op_srlv();
1401: opn = "srlv";
1.1.1.6 ! root 1402: break;
! 1403: case 1:
! 1404: /* rotrv is decoded as srlv on non-R2 CPUs */
! 1405: if (env->insn_flags & ISA_MIPS32R2) {
! 1406: gen_op_rotrv();
! 1407: opn = "rotrv";
! 1408: } else {
! 1409: gen_op_srlv();
! 1410: opn = "srlv";
! 1411: }
! 1412: break;
! 1413: default:
! 1414: MIPS_INVAL("invalid srlv flag");
! 1415: generate_exception(ctx, EXCP_RI);
! 1416: break;
! 1417: }
1.1.1.5 root 1418: break;
1.1.1.6 ! root 1419: #if defined(TARGET_MIPS64)
1.1.1.5 root 1420: case OPC_DSLLV:
1421: gen_op_dsllv();
1422: opn = "dsllv";
1423: break;
1424: case OPC_DSRAV:
1425: gen_op_dsrav();
1426: opn = "dsrav";
1427: break;
1428: case OPC_DSRLV:
1.1.1.6 ! root 1429: switch ((ctx->opcode >> 6) & 0x1f) {
! 1430: case 0:
1.1.1.5 root 1431: gen_op_dsrlv();
1432: opn = "dsrlv";
1.1.1.6 ! root 1433: break;
! 1434: case 1:
! 1435: /* drotrv is decoded as dsrlv on non-R2 CPUs */
! 1436: if (env->insn_flags & ISA_MIPS32R2) {
! 1437: gen_op_drotrv();
! 1438: opn = "drotrv";
! 1439: } else {
! 1440: gen_op_dsrlv();
! 1441: opn = "dsrlv";
! 1442: }
! 1443: break;
! 1444: default:
! 1445: MIPS_INVAL("invalid dsrlv flag");
! 1446: generate_exception(ctx, EXCP_RI);
! 1447: break;
! 1448: }
1.1 root 1449: break;
1.1.1.5 root 1450: #endif
1.1 root 1451: default:
1.1.1.6 ! root 1452: MIPS_INVAL(opn);
1.1 root 1453: generate_exception(ctx, EXCP_RI);
1454: return;
1455: }
1.1.1.6 ! root 1456: GEN_STORE_T0_REG(rd);
1.1 root 1457: print:
1458: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1459: }
1460:
1461: /* Arithmetic on HI/LO registers */
1.1.1.5 root 1462: static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1.1 root 1463: {
1.1.1.6 ! root 1464: const char *opn = "hilo";
1.1 root 1465:
1466: if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1.1.1.6 ! root 1467: /* Treat as NOP. */
1.1 root 1468: MIPS_DEBUG("NOP");
1469: return;
1470: }
1471: switch (opc) {
1472: case OPC_MFHI:
1.1.1.6 ! root 1473: gen_op_load_HI(0);
! 1474: GEN_STORE_T0_REG(reg);
1.1 root 1475: opn = "mfhi";
1476: break;
1477: case OPC_MFLO:
1.1.1.6 ! root 1478: gen_op_load_LO(0);
! 1479: GEN_STORE_T0_REG(reg);
1.1 root 1480: opn = "mflo";
1481: break;
1482: case OPC_MTHI:
1.1.1.6 ! root 1483: GEN_LOAD_REG_T0(reg);
! 1484: gen_op_store_HI(0);
1.1 root 1485: opn = "mthi";
1486: break;
1487: case OPC_MTLO:
1.1.1.6 ! root 1488: GEN_LOAD_REG_T0(reg);
! 1489: gen_op_store_LO(0);
1.1 root 1490: opn = "mtlo";
1491: break;
1492: default:
1.1.1.6 ! root 1493: MIPS_INVAL(opn);
1.1 root 1494: generate_exception(ctx, EXCP_RI);
1495: return;
1496: }
1497: MIPS_DEBUG("%s %s", opn, regnames[reg]);
1498: }
1499:
1.1.1.5 root 1500: static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1.1 root 1501: int rs, int rt)
1502: {
1.1.1.6 ! root 1503: const char *opn = "mul/div";
1.1 root 1504:
1.1.1.6 ! root 1505: GEN_LOAD_REG_T0(rs);
! 1506: GEN_LOAD_REG_T1(rt);
1.1 root 1507: switch (opc) {
1508: case OPC_DIV:
1509: gen_op_div();
1510: opn = "div";
1511: break;
1512: case OPC_DIVU:
1513: gen_op_divu();
1514: opn = "divu";
1515: break;
1516: case OPC_MULT:
1517: gen_op_mult();
1518: opn = "mult";
1519: break;
1520: case OPC_MULTU:
1521: gen_op_multu();
1522: opn = "multu";
1523: break;
1.1.1.6 ! root 1524: #if defined(TARGET_MIPS64)
1.1.1.5 root 1525: case OPC_DDIV:
1526: gen_op_ddiv();
1527: opn = "ddiv";
1528: break;
1529: case OPC_DDIVU:
1530: gen_op_ddivu();
1531: opn = "ddivu";
1532: break;
1533: case OPC_DMULT:
1534: gen_op_dmult();
1535: opn = "dmult";
1536: break;
1537: case OPC_DMULTU:
1538: gen_op_dmultu();
1539: opn = "dmultu";
1540: break;
1541: #endif
1.1 root 1542: case OPC_MADD:
1543: gen_op_madd();
1544: opn = "madd";
1545: break;
1546: case OPC_MADDU:
1547: gen_op_maddu();
1548: opn = "maddu";
1549: break;
1550: case OPC_MSUB:
1551: gen_op_msub();
1552: opn = "msub";
1553: break;
1554: case OPC_MSUBU:
1555: gen_op_msubu();
1556: opn = "msubu";
1557: break;
1558: default:
1.1.1.6 ! root 1559: MIPS_INVAL(opn);
1.1 root 1560: generate_exception(ctx, EXCP_RI);
1561: return;
1562: }
1563: MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1564: }
1565:
1.1.1.6 ! root 1566: static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
! 1567: int rd, int rs, int rt)
! 1568: {
! 1569: const char *opn = "mul vr54xx";
! 1570:
! 1571: GEN_LOAD_REG_T0(rs);
! 1572: GEN_LOAD_REG_T1(rt);
! 1573:
! 1574: switch (opc) {
! 1575: case OPC_VR54XX_MULS:
! 1576: gen_op_muls();
! 1577: opn = "muls";
! 1578: break;
! 1579: case OPC_VR54XX_MULSU:
! 1580: gen_op_mulsu();
! 1581: opn = "mulsu";
! 1582: break;
! 1583: case OPC_VR54XX_MACC:
! 1584: gen_op_macc();
! 1585: opn = "macc";
! 1586: break;
! 1587: case OPC_VR54XX_MACCU:
! 1588: gen_op_maccu();
! 1589: opn = "maccu";
! 1590: break;
! 1591: case OPC_VR54XX_MSAC:
! 1592: gen_op_msac();
! 1593: opn = "msac";
! 1594: break;
! 1595: case OPC_VR54XX_MSACU:
! 1596: gen_op_msacu();
! 1597: opn = "msacu";
! 1598: break;
! 1599: case OPC_VR54XX_MULHI:
! 1600: gen_op_mulhi();
! 1601: opn = "mulhi";
! 1602: break;
! 1603: case OPC_VR54XX_MULHIU:
! 1604: gen_op_mulhiu();
! 1605: opn = "mulhiu";
! 1606: break;
! 1607: case OPC_VR54XX_MULSHI:
! 1608: gen_op_mulshi();
! 1609: opn = "mulshi";
! 1610: break;
! 1611: case OPC_VR54XX_MULSHIU:
! 1612: gen_op_mulshiu();
! 1613: opn = "mulshiu";
! 1614: break;
! 1615: case OPC_VR54XX_MACCHI:
! 1616: gen_op_macchi();
! 1617: opn = "macchi";
! 1618: break;
! 1619: case OPC_VR54XX_MACCHIU:
! 1620: gen_op_macchiu();
! 1621: opn = "macchiu";
! 1622: break;
! 1623: case OPC_VR54XX_MSACHI:
! 1624: gen_op_msachi();
! 1625: opn = "msachi";
! 1626: break;
! 1627: case OPC_VR54XX_MSACHIU:
! 1628: gen_op_msachiu();
! 1629: opn = "msachiu";
! 1630: break;
! 1631: default:
! 1632: MIPS_INVAL("mul vr54xx");
! 1633: generate_exception(ctx, EXCP_RI);
! 1634: return;
! 1635: }
! 1636: GEN_STORE_T0_REG(rd);
! 1637: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
! 1638: }
! 1639:
1.1.1.5 root 1640: static void gen_cl (DisasContext *ctx, uint32_t opc,
1.1 root 1641: int rd, int rs)
1642: {
1.1.1.6 ! root 1643: const char *opn = "CLx";
1.1 root 1644: if (rd == 0) {
1.1.1.6 ! root 1645: /* Treat as NOP. */
1.1 root 1646: MIPS_DEBUG("NOP");
1647: return;
1648: }
1.1.1.6 ! root 1649: GEN_LOAD_REG_T0(rs);
1.1 root 1650: switch (opc) {
1651: case OPC_CLO:
1652: gen_op_clo();
1653: opn = "clo";
1654: break;
1655: case OPC_CLZ:
1656: gen_op_clz();
1657: opn = "clz";
1658: break;
1.1.1.6 ! root 1659: #if defined(TARGET_MIPS64)
1.1.1.5 root 1660: case OPC_DCLO:
1661: gen_op_dclo();
1662: opn = "dclo";
1663: break;
1664: case OPC_DCLZ:
1665: gen_op_dclz();
1666: opn = "dclz";
1667: break;
1668: #endif
1.1 root 1669: default:
1.1.1.6 ! root 1670: MIPS_INVAL(opn);
1.1 root 1671: generate_exception(ctx, EXCP_RI);
1672: return;
1673: }
1674: gen_op_store_T0_gpr(rd);
1675: MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1676: }
1677:
1678: /* Traps */
1.1.1.5 root 1679: static void gen_trap (DisasContext *ctx, uint32_t opc,
1.1 root 1680: int rs, int rt, int16_t imm)
1681: {
1682: int cond;
1683:
1684: cond = 0;
1685: /* Load needed operands */
1686: switch (opc) {
1687: case OPC_TEQ:
1688: case OPC_TGE:
1689: case OPC_TGEU:
1690: case OPC_TLT:
1691: case OPC_TLTU:
1692: case OPC_TNE:
1693: /* Compare two registers */
1694: if (rs != rt) {
1.1.1.6 ! root 1695: GEN_LOAD_REG_T0(rs);
! 1696: GEN_LOAD_REG_T1(rt);
1.1 root 1697: cond = 1;
1698: }
1.1.1.5 root 1699: break;
1.1 root 1700: case OPC_TEQI:
1701: case OPC_TGEI:
1702: case OPC_TGEIU:
1703: case OPC_TLTI:
1704: case OPC_TLTIU:
1705: case OPC_TNEI:
1706: /* Compare register to immediate */
1707: if (rs != 0 || imm != 0) {
1.1.1.6 ! root 1708: GEN_LOAD_REG_T0(rs);
1.1 root 1709: GEN_LOAD_IMM_TN(T1, (int32_t)imm);
1710: cond = 1;
1711: }
1712: break;
1713: }
1714: if (cond == 0) {
1715: switch (opc) {
1716: case OPC_TEQ: /* rs == rs */
1717: case OPC_TEQI: /* r0 == 0 */
1718: case OPC_TGE: /* rs >= rs */
1719: case OPC_TGEI: /* r0 >= 0 */
1720: case OPC_TGEU: /* rs >= rs unsigned */
1721: case OPC_TGEIU: /* r0 >= 0 unsigned */
1722: /* Always trap */
1723: gen_op_set_T0(1);
1724: break;
1725: case OPC_TLT: /* rs < rs */
1726: case OPC_TLTI: /* r0 < 0 */
1727: case OPC_TLTU: /* rs < rs unsigned */
1728: case OPC_TLTIU: /* r0 < 0 unsigned */
1729: case OPC_TNE: /* rs != rs */
1730: case OPC_TNEI: /* r0 != 0 */
1.1.1.6 ! root 1731: /* Never trap: treat as NOP. */
1.1 root 1732: return;
1733: default:
1.1.1.6 ! root 1734: MIPS_INVAL("trap");
1.1 root 1735: generate_exception(ctx, EXCP_RI);
1736: return;
1737: }
1738: } else {
1739: switch (opc) {
1740: case OPC_TEQ:
1741: case OPC_TEQI:
1742: gen_op_eq();
1743: break;
1744: case OPC_TGE:
1745: case OPC_TGEI:
1746: gen_op_ge();
1747: break;
1748: case OPC_TGEU:
1749: case OPC_TGEIU:
1750: gen_op_geu();
1751: break;
1752: case OPC_TLT:
1753: case OPC_TLTI:
1754: gen_op_lt();
1755: break;
1756: case OPC_TLTU:
1757: case OPC_TLTIU:
1758: gen_op_ltu();
1759: break;
1760: case OPC_TNE:
1761: case OPC_TNEI:
1762: gen_op_ne();
1763: break;
1764: default:
1.1.1.6 ! root 1765: MIPS_INVAL("trap");
1.1 root 1766: generate_exception(ctx, EXCP_RI);
1767: return;
1768: }
1769: }
1770: save_cpu_state(ctx, 1);
1771: gen_op_trap();
1772: ctx->bstate = BS_STOP;
1773: }
1774:
1.1.1.6 ! root 1775: static always_inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1.1.1.2 root 1776: {
1777: TranslationBlock *tb;
1778: tb = ctx->tb;
1779: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1780: if (n == 0)
1781: gen_op_goto_tb0(TBPARAM(tb));
1782: else
1783: gen_op_goto_tb1(TBPARAM(tb));
1.1.1.6 ! root 1784: gen_save_pc(dest);
1.1.1.2 root 1785: gen_op_set_T0((long)tb + n);
1786: } else {
1.1.1.6 ! root 1787: gen_save_pc(dest);
! 1788: gen_op_reset_T0();
1.1.1.2 root 1789: }
1.1.1.6 ! root 1790: gen_op_exit_tb();
1.1.1.2 root 1791: }
1792:
1.1 root 1793: /* Branches (before delay slot) */
1.1.1.5 root 1794: static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1.1 root 1795: int rs, int rt, int32_t offset)
1796: {
1.1.1.6 ! root 1797: target_ulong btarget = -1;
! 1798: int blink = 0;
! 1799: int bcond = 0;
1.1 root 1800:
1.1.1.6 ! root 1801: if (ctx->hflags & MIPS_HFLAG_BMASK) {
! 1802: #ifdef MIPS_DEBUG_DISAS
! 1803: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 1804: fprintf(logfile,
! 1805: "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
! 1806: ctx->pc);
! 1807: }
! 1808: #endif
! 1809: generate_exception(ctx, EXCP_RI);
! 1810: return;
! 1811: }
! 1812:
! 1813: /* Load needed operands */
! 1814: switch (opc) {
! 1815: case OPC_BEQ:
! 1816: case OPC_BEQL:
! 1817: case OPC_BNE:
! 1818: case OPC_BNEL:
1.1 root 1819: /* Compare two registers */
1820: if (rs != rt) {
1.1.1.6 ! root 1821: GEN_LOAD_REG_T0(rs);
! 1822: GEN_LOAD_REG_T1(rt);
1.1 root 1823: bcond = 1;
1824: }
1825: btarget = ctx->pc + 4 + offset;
1826: break;
1827: case OPC_BGEZ:
1828: case OPC_BGEZAL:
1829: case OPC_BGEZALL:
1830: case OPC_BGEZL:
1831: case OPC_BGTZ:
1832: case OPC_BGTZL:
1833: case OPC_BLEZ:
1834: case OPC_BLEZL:
1835: case OPC_BLTZ:
1836: case OPC_BLTZAL:
1837: case OPC_BLTZALL:
1838: case OPC_BLTZL:
1839: /* Compare to zero */
1840: if (rs != 0) {
1841: gen_op_load_gpr_T0(rs);
1842: bcond = 1;
1843: }
1844: btarget = ctx->pc + 4 + offset;
1845: break;
1846: case OPC_J:
1847: case OPC_JAL:
1848: /* Jump to immediate */
1.1.1.6 ! root 1849: btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
1.1 root 1850: break;
1851: case OPC_JR:
1852: case OPC_JALR:
1853: /* Jump to register */
1.1.1.5 root 1854: if (offset != 0 && offset != 16) {
1855: /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1.1.1.6 ! root 1856: others are reserved. */
! 1857: MIPS_INVAL("jump hint");
1.1 root 1858: generate_exception(ctx, EXCP_RI);
1859: return;
1860: }
1.1.1.6 ! root 1861: GEN_LOAD_REG_T2(rs);
1.1 root 1862: break;
1863: default:
1864: MIPS_INVAL("branch/jump");
1865: generate_exception(ctx, EXCP_RI);
1866: return;
1867: }
1868: if (bcond == 0) {
1869: /* No condition to be computed */
1870: switch (opc) {
1871: case OPC_BEQ: /* rx == rx */
1872: case OPC_BEQL: /* rx == rx likely */
1873: case OPC_BGEZ: /* 0 >= 0 */
1874: case OPC_BGEZL: /* 0 >= 0 likely */
1875: case OPC_BLEZ: /* 0 <= 0 */
1876: case OPC_BLEZL: /* 0 <= 0 likely */
1877: /* Always take */
1.1.1.2 root 1878: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 1879: MIPS_DEBUG("balways");
1880: break;
1881: case OPC_BGEZAL: /* 0 >= 0 */
1882: case OPC_BGEZALL: /* 0 >= 0 likely */
1883: /* Always take and link */
1884: blink = 31;
1.1.1.2 root 1885: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 1886: MIPS_DEBUG("balways and link");
1887: break;
1888: case OPC_BNE: /* rx != rx */
1889: case OPC_BGTZ: /* 0 > 0 */
1890: case OPC_BLTZ: /* 0 < 0 */
1.1.1.6 ! root 1891: /* Treat as NOP. */
1.1 root 1892: MIPS_DEBUG("bnever (NOP)");
1893: return;
1.1.1.2 root 1894: case OPC_BLTZAL: /* 0 < 0 */
1.1.1.6 ! root 1895: GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
1.1.1.2 root 1896: gen_op_store_T0_gpr(31);
1.1.1.6 ! root 1897: MIPS_DEBUG("bnever and link");
1.1.1.2 root 1898: return;
1899: case OPC_BLTZALL: /* 0 < 0 likely */
1.1.1.6 ! root 1900: GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
1.1.1.2 root 1901: gen_op_store_T0_gpr(31);
1.1.1.6 ! root 1902: /* Skip the instruction in the delay slot */
! 1903: MIPS_DEBUG("bnever, link and skip");
! 1904: ctx->pc += 4;
1.1.1.2 root 1905: return;
1.1 root 1906: case OPC_BNEL: /* rx != rx likely */
1907: case OPC_BGTZL: /* 0 > 0 likely */
1908: case OPC_BLTZL: /* 0 < 0 likely */
1909: /* Skip the instruction in the delay slot */
1910: MIPS_DEBUG("bnever and skip");
1.1.1.6 ! root 1911: ctx->pc += 4;
1.1 root 1912: return;
1913: case OPC_J:
1.1.1.2 root 1914: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.6 ! root 1915: MIPS_DEBUG("j " TARGET_FMT_lx, btarget);
1.1 root 1916: break;
1917: case OPC_JAL:
1918: blink = 31;
1.1.1.2 root 1919: ctx->hflags |= MIPS_HFLAG_B;
1.1.1.6 ! root 1920: MIPS_DEBUG("jal " TARGET_FMT_lx, btarget);
1.1 root 1921: break;
1922: case OPC_JR:
1.1.1.2 root 1923: ctx->hflags |= MIPS_HFLAG_BR;
1.1 root 1924: MIPS_DEBUG("jr %s", regnames[rs]);
1925: break;
1926: case OPC_JALR:
1927: blink = rt;
1.1.1.2 root 1928: ctx->hflags |= MIPS_HFLAG_BR;
1.1 root 1929: MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1930: break;
1931: default:
1932: MIPS_INVAL("branch/jump");
1933: generate_exception(ctx, EXCP_RI);
1934: return;
1935: }
1936: } else {
1937: switch (opc) {
1938: case OPC_BEQ:
1939: gen_op_eq();
1.1.1.6 ! root 1940: MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
1.1 root 1941: regnames[rs], regnames[rt], btarget);
1942: goto not_likely;
1943: case OPC_BEQL:
1944: gen_op_eq();
1.1.1.6 ! root 1945: MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
1.1 root 1946: regnames[rs], regnames[rt], btarget);
1947: goto likely;
1948: case OPC_BNE:
1949: gen_op_ne();
1.1.1.6 ! root 1950: MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
1.1 root 1951: regnames[rs], regnames[rt], btarget);
1952: goto not_likely;
1953: case OPC_BNEL:
1954: gen_op_ne();
1.1.1.6 ! root 1955: MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
1.1 root 1956: regnames[rs], regnames[rt], btarget);
1957: goto likely;
1958: case OPC_BGEZ:
1959: gen_op_gez();
1.1.1.6 ! root 1960: MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 1961: goto not_likely;
1962: case OPC_BGEZL:
1963: gen_op_gez();
1.1.1.6 ! root 1964: MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 1965: goto likely;
1966: case OPC_BGEZAL:
1967: gen_op_gez();
1.1.1.6 ! root 1968: MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 1969: blink = 31;
1970: goto not_likely;
1971: case OPC_BGEZALL:
1972: gen_op_gez();
1973: blink = 31;
1.1.1.6 ! root 1974: MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 1975: goto likely;
1976: case OPC_BGTZ:
1977: gen_op_gtz();
1.1.1.6 ! root 1978: MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 1979: goto not_likely;
1980: case OPC_BGTZL:
1981: gen_op_gtz();
1.1.1.6 ! root 1982: MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 1983: goto likely;
1984: case OPC_BLEZ:
1985: gen_op_lez();
1.1.1.6 ! root 1986: MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 1987: goto not_likely;
1988: case OPC_BLEZL:
1989: gen_op_lez();
1.1.1.6 ! root 1990: MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 1991: goto likely;
1992: case OPC_BLTZ:
1993: gen_op_ltz();
1.1.1.6 ! root 1994: MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 1995: goto not_likely;
1996: case OPC_BLTZL:
1997: gen_op_ltz();
1.1.1.6 ! root 1998: MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 1999: goto likely;
2000: case OPC_BLTZAL:
2001: gen_op_ltz();
2002: blink = 31;
1.1.1.6 ! root 2003: MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 2004: not_likely:
1.1.1.2 root 2005: ctx->hflags |= MIPS_HFLAG_BC;
1.1.1.6 ! root 2006: gen_op_set_bcond();
1.1 root 2007: break;
2008: case OPC_BLTZALL:
2009: gen_op_ltz();
2010: blink = 31;
1.1.1.6 ! root 2011: MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btarget);
1.1 root 2012: likely:
1.1.1.2 root 2013: ctx->hflags |= MIPS_HFLAG_BL;
1.1.1.6 ! root 2014: gen_op_set_bcond();
! 2015: gen_op_save_bcond();
1.1 root 2016: break;
1.1.1.6 ! root 2017: default:
! 2018: MIPS_INVAL("conditional branch/jump");
! 2019: generate_exception(ctx, EXCP_RI);
! 2020: return;
1.1 root 2021: }
2022: }
1.1.1.6 ! root 2023: MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
1.1 root 2024: blink, ctx->hflags, btarget);
1.1.1.6 ! root 2025:
1.1 root 2026: ctx->btarget = btarget;
2027: if (blink > 0) {
1.1.1.6 ! root 2028: GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
1.1 root 2029: gen_op_store_T0_gpr(blink);
2030: }
2031: }
2032:
1.1.1.5 root 2033: /* special3 bitfield operations */
2034: static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2035: int rs, int lsb, int msb)
1.1 root 2036: {
1.1.1.6 ! root 2037: GEN_LOAD_REG_T1(rs);
1.1.1.5 root 2038: switch (opc) {
2039: case OPC_EXT:
2040: if (lsb + msb > 31)
2041: goto fail;
2042: gen_op_ext(lsb, msb + 1);
2043: break;
1.1.1.6 ! root 2044: #if defined(TARGET_MIPS64)
1.1.1.5 root 2045: case OPC_DEXTM:
2046: if (lsb + msb > 63)
2047: goto fail;
1.1.1.6 ! root 2048: gen_op_dext(lsb, msb + 1 + 32);
1.1.1.5 root 2049: break;
2050: case OPC_DEXTU:
2051: if (lsb + msb > 63)
2052: goto fail;
1.1.1.6 ! root 2053: gen_op_dext(lsb + 32, msb + 1);
1.1.1.5 root 2054: break;
2055: case OPC_DEXT:
1.1.1.6 ! root 2056: if (lsb + msb > 63)
! 2057: goto fail;
! 2058: gen_op_dext(lsb, msb + 1);
1.1.1.5 root 2059: break;
1.1.1.6 ! root 2060: #endif
1.1.1.5 root 2061: case OPC_INS:
2062: if (lsb > msb)
2063: goto fail;
1.1.1.6 ! root 2064: GEN_LOAD_REG_T0(rt);
1.1.1.5 root 2065: gen_op_ins(lsb, msb - lsb + 1);
2066: break;
1.1.1.6 ! root 2067: #if defined(TARGET_MIPS64)
1.1.1.5 root 2068: case OPC_DINSM:
2069: if (lsb > msb)
2070: goto fail;
1.1.1.6 ! root 2071: GEN_LOAD_REG_T0(rt);
! 2072: gen_op_dins(lsb, msb - lsb + 1 + 32);
1.1.1.5 root 2073: break;
2074: case OPC_DINSU:
2075: if (lsb > msb)
2076: goto fail;
1.1.1.6 ! root 2077: GEN_LOAD_REG_T0(rt);
! 2078: gen_op_dins(lsb + 32, msb - lsb + 1);
1.1.1.5 root 2079: break;
2080: case OPC_DINS:
2081: if (lsb > msb)
2082: goto fail;
1.1.1.6 ! root 2083: GEN_LOAD_REG_T0(rt);
! 2084: gen_op_dins(lsb, msb - lsb + 1);
1.1.1.5 root 2085: break;
1.1.1.6 ! root 2086: #endif
1.1.1.5 root 2087: default:
2088: fail:
2089: MIPS_INVAL("bitops");
2090: generate_exception(ctx, EXCP_RI);
1.1 root 2091: return;
2092: }
1.1.1.6 ! root 2093: GEN_STORE_T0_REG(rt);
1.1.1.5 root 2094: }
1.1.1.4 root 2095:
1.1.1.5 root 2096: /* CP0 (MMU and control) */
1.1.1.6 ! root 2097: static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
1.1.1.5 root 2098: {
2099: const char *rn = "invalid";
2100:
1.1.1.6 ! root 2101: if (sel != 0)
! 2102: check_insn(env, ctx, ISA_MIPS32);
! 2103:
1.1.1.5 root 2104: switch (reg) {
2105: case 0:
2106: switch (sel) {
2107: case 0:
1.1.1.6 ! root 2108: gen_op_mfc0_index();
1.1.1.5 root 2109: rn = "Index";
2110: break;
2111: case 1:
1.1.1.6 ! root 2112: check_insn(env, ctx, ASE_MT);
! 2113: gen_op_mfc0_mvpcontrol();
1.1.1.5 root 2114: rn = "MVPControl";
1.1.1.6 ! root 2115: break;
1.1.1.5 root 2116: case 2:
1.1.1.6 ! root 2117: check_insn(env, ctx, ASE_MT);
! 2118: gen_op_mfc0_mvpconf0();
1.1.1.5 root 2119: rn = "MVPConf0";
1.1.1.6 ! root 2120: break;
1.1.1.5 root 2121: case 3:
1.1.1.6 ! root 2122: check_insn(env, ctx, ASE_MT);
! 2123: gen_op_mfc0_mvpconf1();
1.1.1.5 root 2124: rn = "MVPConf1";
1.1.1.6 ! root 2125: break;
1.1.1.5 root 2126: default:
2127: goto die;
1.1 root 2128: }
2129: break;
1.1.1.5 root 2130: case 1:
2131: switch (sel) {
2132: case 0:
2133: gen_op_mfc0_random();
2134: rn = "Random";
1.1.1.6 ! root 2135: break;
1.1.1.5 root 2136: case 1:
1.1.1.6 ! root 2137: check_insn(env, ctx, ASE_MT);
! 2138: gen_op_mfc0_vpecontrol();
1.1.1.5 root 2139: rn = "VPEControl";
1.1.1.6 ! root 2140: break;
1.1.1.5 root 2141: case 2:
1.1.1.6 ! root 2142: check_insn(env, ctx, ASE_MT);
! 2143: gen_op_mfc0_vpeconf0();
1.1.1.5 root 2144: rn = "VPEConf0";
1.1.1.6 ! root 2145: break;
1.1.1.5 root 2146: case 3:
1.1.1.6 ! root 2147: check_insn(env, ctx, ASE_MT);
! 2148: gen_op_mfc0_vpeconf1();
1.1.1.5 root 2149: rn = "VPEConf1";
1.1.1.6 ! root 2150: break;
1.1.1.5 root 2151: case 4:
1.1.1.6 ! root 2152: check_insn(env, ctx, ASE_MT);
! 2153: gen_op_mfc0_yqmask();
1.1.1.5 root 2154: rn = "YQMask";
1.1.1.6 ! root 2155: break;
1.1.1.5 root 2156: case 5:
1.1.1.6 ! root 2157: check_insn(env, ctx, ASE_MT);
! 2158: gen_op_mfc0_vpeschedule();
1.1.1.5 root 2159: rn = "VPESchedule";
1.1.1.6 ! root 2160: break;
1.1.1.5 root 2161: case 6:
1.1.1.6 ! root 2162: check_insn(env, ctx, ASE_MT);
! 2163: gen_op_mfc0_vpeschefback();
1.1.1.5 root 2164: rn = "VPEScheFBack";
1.1.1.6 ! root 2165: break;
1.1.1.5 root 2166: case 7:
1.1.1.6 ! root 2167: check_insn(env, ctx, ASE_MT);
! 2168: gen_op_mfc0_vpeopt();
1.1.1.5 root 2169: rn = "VPEOpt";
1.1.1.6 ! root 2170: break;
1.1.1.5 root 2171: default:
2172: goto die;
2173: }
1.1 root 2174: break;
1.1.1.5 root 2175: case 2:
2176: switch (sel) {
2177: case 0:
1.1.1.6 ! root 2178: gen_op_mfc0_entrylo0();
! 2179: rn = "EntryLo0";
! 2180: break;
! 2181: case 1:
! 2182: check_insn(env, ctx, ASE_MT);
! 2183: gen_op_mfc0_tcstatus();
! 2184: rn = "TCStatus";
! 2185: break;
! 2186: case 2:
! 2187: check_insn(env, ctx, ASE_MT);
! 2188: gen_op_mfc0_tcbind();
! 2189: rn = "TCBind";
! 2190: break;
1.1.1.5 root 2191: case 3:
1.1.1.6 ! root 2192: check_insn(env, ctx, ASE_MT);
! 2193: gen_op_mfc0_tcrestart();
! 2194: rn = "TCRestart";
! 2195: break;
1.1.1.5 root 2196: case 4:
1.1.1.6 ! root 2197: check_insn(env, ctx, ASE_MT);
! 2198: gen_op_mfc0_tchalt();
! 2199: rn = "TCHalt";
! 2200: break;
1.1.1.5 root 2201: case 5:
1.1.1.6 ! root 2202: check_insn(env, ctx, ASE_MT);
! 2203: gen_op_mfc0_tccontext();
! 2204: rn = "TCContext";
! 2205: break;
1.1.1.5 root 2206: case 6:
1.1.1.6 ! root 2207: check_insn(env, ctx, ASE_MT);
! 2208: gen_op_mfc0_tcschedule();
! 2209: rn = "TCSchedule";
! 2210: break;
1.1.1.5 root 2211: case 7:
1.1.1.6 ! root 2212: check_insn(env, ctx, ASE_MT);
! 2213: gen_op_mfc0_tcschefback();
! 2214: rn = "TCScheFBack";
! 2215: break;
1.1.1.5 root 2216: default:
2217: goto die;
2218: }
1.1 root 2219: break;
1.1.1.5 root 2220: case 3:
2221: switch (sel) {
2222: case 0:
1.1.1.6 ! root 2223: gen_op_mfc0_entrylo1();
! 2224: rn = "EntryLo1";
! 2225: break;
1.1.1.5 root 2226: default:
2227: goto die;
1.1.1.6 ! root 2228: }
1.1 root 2229: break;
1.1.1.5 root 2230: case 4:
2231: switch (sel) {
2232: case 0:
1.1.1.6 ! root 2233: gen_op_mfc0_context();
! 2234: rn = "Context";
! 2235: break;
! 2236: case 1:
! 2237: // gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
! 2238: rn = "ContextConfig";
! 2239: // break;
1.1.1.5 root 2240: default:
2241: goto die;
1.1.1.6 ! root 2242: }
1.1 root 2243: break;
1.1.1.5 root 2244: case 5:
2245: switch (sel) {
2246: case 0:
1.1.1.6 ! root 2247: gen_op_mfc0_pagemask();
! 2248: rn = "PageMask";
! 2249: break;
! 2250: case 1:
! 2251: check_insn(env, ctx, ISA_MIPS32R2);
! 2252: gen_op_mfc0_pagegrain();
! 2253: rn = "PageGrain";
! 2254: break;
1.1.1.5 root 2255: default:
2256: goto die;
1.1.1.6 ! root 2257: }
1.1 root 2258: break;
1.1.1.5 root 2259: case 6:
2260: switch (sel) {
2261: case 0:
1.1.1.6 ! root 2262: gen_op_mfc0_wired();
! 2263: rn = "Wired";
! 2264: break;
! 2265: case 1:
! 2266: check_insn(env, ctx, ISA_MIPS32R2);
! 2267: gen_op_mfc0_srsconf0();
! 2268: rn = "SRSConf0";
! 2269: break;
! 2270: case 2:
! 2271: check_insn(env, ctx, ISA_MIPS32R2);
! 2272: gen_op_mfc0_srsconf1();
! 2273: rn = "SRSConf1";
! 2274: break;
1.1.1.5 root 2275: case 3:
1.1.1.6 ! root 2276: check_insn(env, ctx, ISA_MIPS32R2);
! 2277: gen_op_mfc0_srsconf2();
! 2278: rn = "SRSConf2";
! 2279: break;
1.1.1.5 root 2280: case 4:
1.1.1.6 ! root 2281: check_insn(env, ctx, ISA_MIPS32R2);
! 2282: gen_op_mfc0_srsconf3();
! 2283: rn = "SRSConf3";
! 2284: break;
1.1.1.5 root 2285: case 5:
1.1.1.6 ! root 2286: check_insn(env, ctx, ISA_MIPS32R2);
! 2287: gen_op_mfc0_srsconf4();
! 2288: rn = "SRSConf4";
! 2289: break;
1.1.1.5 root 2290: default:
2291: goto die;
1.1.1.6 ! root 2292: }
1.1 root 2293: break;
1.1.1.5 root 2294: case 7:
2295: switch (sel) {
2296: case 0:
1.1.1.6 ! root 2297: check_insn(env, ctx, ISA_MIPS32R2);
! 2298: gen_op_mfc0_hwrena();
! 2299: rn = "HWREna";
! 2300: break;
1.1.1.5 root 2301: default:
2302: goto die;
1.1.1.6 ! root 2303: }
1.1 root 2304: break;
1.1.1.5 root 2305: case 8:
2306: switch (sel) {
2307: case 0:
1.1.1.6 ! root 2308: gen_op_mfc0_badvaddr();
! 2309: rn = "BadVaddr";
! 2310: break;
1.1.1.5 root 2311: default:
2312: goto die;
2313: }
1.1.1.2 root 2314: break;
1.1.1.5 root 2315: case 9:
2316: switch (sel) {
2317: case 0:
1.1.1.6 ! root 2318: gen_op_mfc0_count();
! 2319: rn = "Count";
! 2320: break;
! 2321: /* 6,7 are implementation dependent */
1.1.1.5 root 2322: default:
2323: goto die;
1.1.1.6 ! root 2324: }
1.1.1.5 root 2325: break;
2326: case 10:
2327: switch (sel) {
2328: case 0:
1.1.1.6 ! root 2329: gen_op_mfc0_entryhi();
! 2330: rn = "EntryHi";
! 2331: break;
1.1.1.5 root 2332: default:
2333: goto die;
1.1.1.6 ! root 2334: }
1.1.1.5 root 2335: break;
2336: case 11:
2337: switch (sel) {
2338: case 0:
1.1.1.6 ! root 2339: gen_op_mfc0_compare();
! 2340: rn = "Compare";
! 2341: break;
! 2342: /* 6,7 are implementation dependent */
1.1.1.5 root 2343: default:
2344: goto die;
1.1.1.6 ! root 2345: }
1.1.1.5 root 2346: break;
2347: case 12:
2348: switch (sel) {
2349: case 0:
1.1.1.6 ! root 2350: gen_op_mfc0_status();
! 2351: rn = "Status";
! 2352: break;
! 2353: case 1:
! 2354: check_insn(env, ctx, ISA_MIPS32R2);
! 2355: gen_op_mfc0_intctl();
! 2356: rn = "IntCtl";
! 2357: break;
! 2358: case 2:
! 2359: check_insn(env, ctx, ISA_MIPS32R2);
! 2360: gen_op_mfc0_srsctl();
! 2361: rn = "SRSCtl";
! 2362: break;
1.1.1.5 root 2363: case 3:
1.1.1.6 ! root 2364: check_insn(env, ctx, ISA_MIPS32R2);
! 2365: gen_op_mfc0_srsmap();
! 2366: rn = "SRSMap";
! 2367: break;
1.1.1.5 root 2368: default:
2369: goto die;
2370: }
2371: break;
2372: case 13:
2373: switch (sel) {
2374: case 0:
1.1.1.6 ! root 2375: gen_op_mfc0_cause();
! 2376: rn = "Cause";
! 2377: break;
1.1.1.5 root 2378: default:
2379: goto die;
2380: }
2381: break;
2382: case 14:
2383: switch (sel) {
2384: case 0:
1.1.1.6 ! root 2385: gen_op_mfc0_epc();
! 2386: rn = "EPC";
! 2387: break;
1.1.1.5 root 2388: default:
2389: goto die;
1.1.1.6 ! root 2390: }
1.1.1.5 root 2391: break;
2392: case 15:
2393: switch (sel) {
2394: case 0:
1.1.1.6 ! root 2395: gen_op_mfc0_prid();
! 2396: rn = "PRid";
! 2397: break;
! 2398: case 1:
! 2399: check_insn(env, ctx, ISA_MIPS32R2);
! 2400: gen_op_mfc0_ebase();
! 2401: rn = "EBase";
! 2402: break;
1.1.1.5 root 2403: default:
2404: goto die;
2405: }
2406: break;
2407: case 16:
2408: switch (sel) {
2409: case 0:
1.1.1.6 ! root 2410: gen_op_mfc0_config0();
1.1.1.5 root 2411: rn = "Config";
2412: break;
2413: case 1:
1.1.1.6 ! root 2414: gen_op_mfc0_config1();
1.1.1.5 root 2415: rn = "Config1";
2416: break;
2417: case 2:
1.1.1.6 ! root 2418: gen_op_mfc0_config2();
1.1.1.5 root 2419: rn = "Config2";
2420: break;
2421: case 3:
1.1.1.6 ! root 2422: gen_op_mfc0_config3();
1.1.1.5 root 2423: rn = "Config3";
2424: break;
1.1.1.6 ! root 2425: /* 4,5 are reserved */
! 2426: /* 6,7 are implementation dependent */
! 2427: case 6:
! 2428: gen_op_mfc0_config6();
! 2429: rn = "Config6";
! 2430: break;
! 2431: case 7:
! 2432: gen_op_mfc0_config7();
! 2433: rn = "Config7";
! 2434: break;
1.1.1.5 root 2435: default:
2436: goto die;
1.1 root 2437: }
1.1.1.4 root 2438: break;
1.1.1.5 root 2439: case 17:
2440: switch (sel) {
2441: case 0:
1.1.1.6 ! root 2442: gen_op_mfc0_lladdr();
! 2443: rn = "LLAddr";
! 2444: break;
1.1.1.5 root 2445: default:
2446: goto die;
2447: }
1.1.1.4 root 2448: break;
1.1.1.5 root 2449: case 18:
2450: switch (sel) {
1.1.1.6 ! root 2451: case 0 ... 7:
! 2452: gen_op_mfc0_watchlo(sel);
! 2453: rn = "WatchLo";
! 2454: break;
1.1.1.5 root 2455: default:
2456: goto die;
2457: }
1.1.1.4 root 2458: break;
1.1.1.5 root 2459: case 19:
2460: switch (sel) {
1.1.1.6 ! root 2461: case 0 ...7:
! 2462: gen_op_mfc0_watchhi(sel);
! 2463: rn = "WatchHi";
! 2464: break;
1.1.1.5 root 2465: default:
2466: goto die;
2467: }
1.1.1.4 root 2468: break;
1.1.1.5 root 2469: case 20:
2470: switch (sel) {
2471: case 0:
1.1.1.6 ! root 2472: #if defined(TARGET_MIPS64)
! 2473: check_insn(env, ctx, ISA_MIPS3);
! 2474: gen_op_mfc0_xcontext();
! 2475: rn = "XContext";
! 2476: break;
! 2477: #endif
1.1.1.5 root 2478: default:
2479: goto die;
1.1.1.4 root 2480: }
2481: break;
1.1.1.5 root 2482: case 21:
2483: /* Officially reserved, but sel 0 is used for R1x000 framemask */
2484: switch (sel) {
2485: case 0:
1.1.1.6 ! root 2486: gen_op_mfc0_framemask();
! 2487: rn = "Framemask";
! 2488: break;
1.1.1.5 root 2489: default:
2490: goto die;
1.1.1.4 root 2491: }
2492: break;
1.1.1.5 root 2493: case 22:
1.1.1.6 ! root 2494: /* ignored */
! 2495: rn = "'Diagnostic"; /* implementation dependent */
! 2496: break;
1.1.1.5 root 2497: case 23:
2498: switch (sel) {
2499: case 0:
1.1.1.6 ! root 2500: gen_op_mfc0_debug(); /* EJTAG support */
! 2501: rn = "Debug";
! 2502: break;
! 2503: case 1:
! 2504: // gen_op_mfc0_tracecontrol(); /* PDtrace support */
! 2505: rn = "TraceControl";
! 2506: // break;
! 2507: case 2:
! 2508: // gen_op_mfc0_tracecontrol2(); /* PDtrace support */
! 2509: rn = "TraceControl2";
! 2510: // break;
1.1.1.5 root 2511: case 3:
1.1.1.6 ! root 2512: // gen_op_mfc0_usertracedata(); /* PDtrace support */
! 2513: rn = "UserTraceData";
! 2514: // break;
1.1.1.5 root 2515: case 4:
1.1.1.6 ! root 2516: // gen_op_mfc0_debug(); /* PDtrace support */
! 2517: rn = "TraceBPC";
! 2518: // break;
1.1.1.5 root 2519: default:
2520: goto die;
1.1.1.4 root 2521: }
1.1.1.5 root 2522: break;
2523: case 24:
2524: switch (sel) {
2525: case 0:
1.1.1.6 ! root 2526: gen_op_mfc0_depc(); /* EJTAG support */
! 2527: rn = "DEPC";
! 2528: break;
1.1.1.5 root 2529: default:
2530: goto die;
2531: }
2532: break;
2533: case 25:
2534: switch (sel) {
2535: case 0:
1.1.1.6 ! root 2536: gen_op_mfc0_performance0();
! 2537: rn = "Performance0";
1.1.1.5 root 2538: break;
2539: case 1:
1.1.1.6 ! root 2540: // gen_op_mfc0_performance1();
! 2541: rn = "Performance1";
! 2542: // break;
1.1.1.5 root 2543: case 2:
1.1.1.6 ! root 2544: // gen_op_mfc0_performance2();
! 2545: rn = "Performance2";
! 2546: // break;
1.1.1.5 root 2547: case 3:
1.1.1.6 ! root 2548: // gen_op_mfc0_performance3();
! 2549: rn = "Performance3";
! 2550: // break;
1.1.1.5 root 2551: case 4:
1.1.1.6 ! root 2552: // gen_op_mfc0_performance4();
! 2553: rn = "Performance4";
! 2554: // break;
1.1.1.5 root 2555: case 5:
1.1.1.6 ! root 2556: // gen_op_mfc0_performance5();
! 2557: rn = "Performance5";
! 2558: // break;
1.1.1.5 root 2559: case 6:
1.1.1.6 ! root 2560: // gen_op_mfc0_performance6();
! 2561: rn = "Performance6";
! 2562: // break;
1.1.1.5 root 2563: case 7:
1.1.1.6 ! root 2564: // gen_op_mfc0_performance7();
! 2565: rn = "Performance7";
! 2566: // break;
1.1.1.5 root 2567: default:
2568: goto die;
2569: }
2570: break;
2571: case 26:
2572: rn = "ECC";
2573: break;
2574: case 27:
2575: switch (sel) {
2576: /* ignored */
2577: case 0 ... 3:
1.1.1.6 ! root 2578: rn = "CacheErr";
! 2579: break;
1.1.1.5 root 2580: default:
2581: goto die;
2582: }
2583: break;
2584: case 28:
2585: switch (sel) {
2586: case 0:
2587: case 2:
2588: case 4:
2589: case 6:
2590: gen_op_mfc0_taglo();
2591: rn = "TagLo";
2592: break;
2593: case 1:
2594: case 3:
2595: case 5:
2596: case 7:
2597: gen_op_mfc0_datalo();
2598: rn = "DataLo";
2599: break;
2600: default:
2601: goto die;
2602: }
2603: break;
2604: case 29:
2605: switch (sel) {
2606: case 0:
2607: case 2:
2608: case 4:
2609: case 6:
2610: gen_op_mfc0_taghi();
2611: rn = "TagHi";
2612: break;
2613: case 1:
2614: case 3:
2615: case 5:
2616: case 7:
2617: gen_op_mfc0_datahi();
2618: rn = "DataHi";
2619: break;
2620: default:
2621: goto die;
2622: }
2623: break;
2624: case 30:
2625: switch (sel) {
2626: case 0:
1.1.1.6 ! root 2627: gen_op_mfc0_errorepc();
! 2628: rn = "ErrorEPC";
! 2629: break;
1.1.1.5 root 2630: default:
2631: goto die;
2632: }
2633: break;
2634: case 31:
2635: switch (sel) {
2636: case 0:
1.1.1.6 ! root 2637: gen_op_mfc0_desave(); /* EJTAG support */
! 2638: rn = "DESAVE";
! 2639: break;
1.1.1.5 root 2640: default:
2641: goto die;
2642: }
2643: break;
2644: default:
2645: goto die;
2646: }
2647: #if defined MIPS_DEBUG_DISAS
2648: if (loglevel & CPU_LOG_TB_IN_ASM) {
2649: fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2650: rn, reg, sel);
2651: }
2652: #endif
2653: return;
2654:
2655: die:
2656: #if defined MIPS_DEBUG_DISAS
2657: if (loglevel & CPU_LOG_TB_IN_ASM) {
2658: fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2659: rn, reg, sel);
2660: }
2661: #endif
2662: generate_exception(ctx, EXCP_RI);
2663: }
2664:
1.1.1.6 ! root 2665: static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
1.1.1.5 root 2666: {
2667: const char *rn = "invalid";
2668:
1.1.1.6 ! root 2669: if (sel != 0)
! 2670: check_insn(env, ctx, ISA_MIPS32);
! 2671:
1.1.1.5 root 2672: switch (reg) {
2673: case 0:
2674: switch (sel) {
2675: case 0:
1.1.1.6 ! root 2676: gen_op_mtc0_index();
1.1.1.5 root 2677: rn = "Index";
2678: break;
2679: case 1:
1.1.1.6 ! root 2680: check_insn(env, ctx, ASE_MT);
! 2681: gen_op_mtc0_mvpcontrol();
1.1.1.5 root 2682: rn = "MVPControl";
1.1.1.6 ! root 2683: break;
1.1.1.5 root 2684: case 2:
1.1.1.6 ! root 2685: check_insn(env, ctx, ASE_MT);
! 2686: /* ignored */
1.1.1.5 root 2687: rn = "MVPConf0";
1.1.1.6 ! root 2688: break;
1.1.1.5 root 2689: case 3:
1.1.1.6 ! root 2690: check_insn(env, ctx, ASE_MT);
! 2691: /* ignored */
1.1.1.5 root 2692: rn = "MVPConf1";
1.1.1.6 ! root 2693: break;
1.1.1.5 root 2694: default:
2695: goto die;
2696: }
2697: break;
2698: case 1:
2699: switch (sel) {
2700: case 0:
1.1.1.6 ! root 2701: /* ignored */
1.1.1.5 root 2702: rn = "Random";
1.1.1.6 ! root 2703: break;
1.1.1.5 root 2704: case 1:
1.1.1.6 ! root 2705: check_insn(env, ctx, ASE_MT);
! 2706: gen_op_mtc0_vpecontrol();
1.1.1.5 root 2707: rn = "VPEControl";
1.1.1.6 ! root 2708: break;
1.1.1.5 root 2709: case 2:
1.1.1.6 ! root 2710: check_insn(env, ctx, ASE_MT);
! 2711: gen_op_mtc0_vpeconf0();
1.1.1.5 root 2712: rn = "VPEConf0";
1.1.1.6 ! root 2713: break;
1.1.1.5 root 2714: case 3:
1.1.1.6 ! root 2715: check_insn(env, ctx, ASE_MT);
! 2716: gen_op_mtc0_vpeconf1();
1.1.1.5 root 2717: rn = "VPEConf1";
1.1.1.6 ! root 2718: break;
1.1.1.5 root 2719: case 4:
1.1.1.6 ! root 2720: check_insn(env, ctx, ASE_MT);
! 2721: gen_op_mtc0_yqmask();
1.1.1.5 root 2722: rn = "YQMask";
1.1.1.6 ! root 2723: break;
1.1.1.5 root 2724: case 5:
1.1.1.6 ! root 2725: check_insn(env, ctx, ASE_MT);
! 2726: gen_op_mtc0_vpeschedule();
1.1.1.5 root 2727: rn = "VPESchedule";
1.1.1.6 ! root 2728: break;
1.1.1.5 root 2729: case 6:
1.1.1.6 ! root 2730: check_insn(env, ctx, ASE_MT);
! 2731: gen_op_mtc0_vpeschefback();
1.1.1.5 root 2732: rn = "VPEScheFBack";
1.1.1.6 ! root 2733: break;
1.1.1.5 root 2734: case 7:
1.1.1.6 ! root 2735: check_insn(env, ctx, ASE_MT);
! 2736: gen_op_mtc0_vpeopt();
1.1.1.5 root 2737: rn = "VPEOpt";
1.1.1.6 ! root 2738: break;
1.1.1.5 root 2739: default:
2740: goto die;
2741: }
2742: break;
2743: case 2:
2744: switch (sel) {
2745: case 0:
1.1.1.6 ! root 2746: gen_op_mtc0_entrylo0();
! 2747: rn = "EntryLo0";
! 2748: break;
! 2749: case 1:
! 2750: check_insn(env, ctx, ASE_MT);
! 2751: gen_op_mtc0_tcstatus();
! 2752: rn = "TCStatus";
! 2753: break;
! 2754: case 2:
! 2755: check_insn(env, ctx, ASE_MT);
! 2756: gen_op_mtc0_tcbind();
! 2757: rn = "TCBind";
! 2758: break;
1.1.1.5 root 2759: case 3:
1.1.1.6 ! root 2760: check_insn(env, ctx, ASE_MT);
! 2761: gen_op_mtc0_tcrestart();
! 2762: rn = "TCRestart";
! 2763: break;
1.1.1.5 root 2764: case 4:
1.1.1.6 ! root 2765: check_insn(env, ctx, ASE_MT);
! 2766: gen_op_mtc0_tchalt();
! 2767: rn = "TCHalt";
! 2768: break;
1.1.1.5 root 2769: case 5:
1.1.1.6 ! root 2770: check_insn(env, ctx, ASE_MT);
! 2771: gen_op_mtc0_tccontext();
! 2772: rn = "TCContext";
! 2773: break;
1.1.1.5 root 2774: case 6:
1.1.1.6 ! root 2775: check_insn(env, ctx, ASE_MT);
! 2776: gen_op_mtc0_tcschedule();
! 2777: rn = "TCSchedule";
! 2778: break;
1.1.1.5 root 2779: case 7:
1.1.1.6 ! root 2780: check_insn(env, ctx, ASE_MT);
! 2781: gen_op_mtc0_tcschefback();
! 2782: rn = "TCScheFBack";
! 2783: break;
1.1.1.5 root 2784: default:
2785: goto die;
2786: }
2787: break;
2788: case 3:
2789: switch (sel) {
2790: case 0:
1.1.1.6 ! root 2791: gen_op_mtc0_entrylo1();
! 2792: rn = "EntryLo1";
! 2793: break;
1.1.1.5 root 2794: default:
2795: goto die;
1.1.1.6 ! root 2796: }
1.1.1.5 root 2797: break;
2798: case 4:
2799: switch (sel) {
2800: case 0:
1.1.1.6 ! root 2801: gen_op_mtc0_context();
! 2802: rn = "Context";
! 2803: break;
! 2804: case 1:
! 2805: // gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
! 2806: rn = "ContextConfig";
! 2807: // break;
1.1.1.5 root 2808: default:
2809: goto die;
1.1.1.6 ! root 2810: }
1.1.1.5 root 2811: break;
2812: case 5:
2813: switch (sel) {
2814: case 0:
1.1.1.6 ! root 2815: gen_op_mtc0_pagemask();
! 2816: rn = "PageMask";
! 2817: break;
! 2818: case 1:
! 2819: check_insn(env, ctx, ISA_MIPS32R2);
! 2820: gen_op_mtc0_pagegrain();
! 2821: rn = "PageGrain";
! 2822: break;
1.1.1.5 root 2823: default:
2824: goto die;
1.1.1.6 ! root 2825: }
1.1.1.5 root 2826: break;
2827: case 6:
2828: switch (sel) {
2829: case 0:
1.1.1.6 ! root 2830: gen_op_mtc0_wired();
! 2831: rn = "Wired";
! 2832: break;
! 2833: case 1:
! 2834: check_insn(env, ctx, ISA_MIPS32R2);
! 2835: gen_op_mtc0_srsconf0();
! 2836: rn = "SRSConf0";
! 2837: break;
! 2838: case 2:
! 2839: check_insn(env, ctx, ISA_MIPS32R2);
! 2840: gen_op_mtc0_srsconf1();
! 2841: rn = "SRSConf1";
! 2842: break;
1.1.1.5 root 2843: case 3:
1.1.1.6 ! root 2844: check_insn(env, ctx, ISA_MIPS32R2);
! 2845: gen_op_mtc0_srsconf2();
! 2846: rn = "SRSConf2";
! 2847: break;
1.1.1.5 root 2848: case 4:
1.1.1.6 ! root 2849: check_insn(env, ctx, ISA_MIPS32R2);
! 2850: gen_op_mtc0_srsconf3();
! 2851: rn = "SRSConf3";
! 2852: break;
1.1.1.5 root 2853: case 5:
1.1.1.6 ! root 2854: check_insn(env, ctx, ISA_MIPS32R2);
! 2855: gen_op_mtc0_srsconf4();
! 2856: rn = "SRSConf4";
! 2857: break;
1.1.1.5 root 2858: default:
2859: goto die;
1.1.1.6 ! root 2860: }
1.1.1.5 root 2861: break;
2862: case 7:
2863: switch (sel) {
2864: case 0:
1.1.1.6 ! root 2865: check_insn(env, ctx, ISA_MIPS32R2);
! 2866: gen_op_mtc0_hwrena();
! 2867: rn = "HWREna";
! 2868: break;
1.1.1.5 root 2869: default:
2870: goto die;
1.1.1.6 ! root 2871: }
1.1.1.5 root 2872: break;
2873: case 8:
2874: /* ignored */
2875: rn = "BadVaddr";
2876: break;
2877: case 9:
2878: switch (sel) {
2879: case 0:
1.1.1.6 ! root 2880: gen_op_mtc0_count();
! 2881: rn = "Count";
! 2882: break;
! 2883: /* 6,7 are implementation dependent */
1.1.1.5 root 2884: default:
2885: goto die;
1.1.1.6 ! root 2886: }
! 2887: /* Stop translation as we may have switched the execution mode */
! 2888: ctx->bstate = BS_STOP;
1.1.1.5 root 2889: break;
2890: case 10:
2891: switch (sel) {
2892: case 0:
1.1.1.6 ! root 2893: gen_op_mtc0_entryhi();
! 2894: rn = "EntryHi";
! 2895: break;
1.1.1.5 root 2896: default:
2897: goto die;
1.1.1.6 ! root 2898: }
1.1.1.5 root 2899: break;
2900: case 11:
2901: switch (sel) {
2902: case 0:
1.1.1.6 ! root 2903: gen_op_mtc0_compare();
! 2904: rn = "Compare";
! 2905: break;
! 2906: /* 6,7 are implementation dependent */
1.1.1.5 root 2907: default:
2908: goto die;
1.1.1.6 ! root 2909: }
! 2910: /* Stop translation as we may have switched the execution mode */
! 2911: ctx->bstate = BS_STOP;
1.1.1.5 root 2912: break;
2913: case 12:
2914: switch (sel) {
2915: case 0:
1.1.1.6 ! root 2916: gen_op_mtc0_status();
! 2917: /* BS_STOP isn't good enough here, hflags may have changed. */
! 2918: gen_save_pc(ctx->pc + 4);
! 2919: ctx->bstate = BS_EXCP;
! 2920: rn = "Status";
! 2921: break;
! 2922: case 1:
! 2923: check_insn(env, ctx, ISA_MIPS32R2);
! 2924: gen_op_mtc0_intctl();
! 2925: /* Stop translation as we may have switched the execution mode */
! 2926: ctx->bstate = BS_STOP;
! 2927: rn = "IntCtl";
! 2928: break;
! 2929: case 2:
! 2930: check_insn(env, ctx, ISA_MIPS32R2);
! 2931: gen_op_mtc0_srsctl();
! 2932: /* Stop translation as we may have switched the execution mode */
! 2933: ctx->bstate = BS_STOP;
! 2934: rn = "SRSCtl";
! 2935: break;
1.1.1.5 root 2936: case 3:
1.1.1.6 ! root 2937: check_insn(env, ctx, ISA_MIPS32R2);
! 2938: gen_op_mtc0_srsmap();
! 2939: /* Stop translation as we may have switched the execution mode */
! 2940: ctx->bstate = BS_STOP;
! 2941: rn = "SRSMap";
! 2942: break;
1.1.1.5 root 2943: default:
2944: goto die;
1.1.1.6 ! root 2945: }
1.1.1.5 root 2946: break;
2947: case 13:
2948: switch (sel) {
2949: case 0:
1.1.1.6 ! root 2950: gen_op_mtc0_cause();
! 2951: rn = "Cause";
! 2952: break;
1.1.1.5 root 2953: default:
2954: goto die;
1.1.1.6 ! root 2955: }
! 2956: /* Stop translation as we may have switched the execution mode */
! 2957: ctx->bstate = BS_STOP;
1.1.1.5 root 2958: break;
2959: case 14:
2960: switch (sel) {
2961: case 0:
1.1.1.6 ! root 2962: gen_op_mtc0_epc();
! 2963: rn = "EPC";
! 2964: break;
1.1.1.5 root 2965: default:
2966: goto die;
1.1.1.6 ! root 2967: }
1.1.1.5 root 2968: break;
2969: case 15:
2970: switch (sel) {
2971: case 0:
1.1.1.6 ! root 2972: /* ignored */
! 2973: rn = "PRid";
! 2974: break;
! 2975: case 1:
! 2976: check_insn(env, ctx, ISA_MIPS32R2);
! 2977: gen_op_mtc0_ebase();
! 2978: rn = "EBase";
! 2979: break;
1.1.1.5 root 2980: default:
2981: goto die;
1.1.1.6 ! root 2982: }
1.1.1.5 root 2983: break;
2984: case 16:
2985: switch (sel) {
2986: case 0:
1.1.1.6 ! root 2987: gen_op_mtc0_config0();
1.1.1.5 root 2988: rn = "Config";
1.1.1.6 ! root 2989: /* Stop translation as we may have switched the execution mode */
! 2990: ctx->bstate = BS_STOP;
1.1.1.5 root 2991: break;
2992: case 1:
1.1.1.6 ! root 2993: /* ignored, read only */
1.1.1.5 root 2994: rn = "Config1";
2995: break;
2996: case 2:
1.1.1.6 ! root 2997: gen_op_mtc0_config2();
1.1.1.5 root 2998: rn = "Config2";
1.1.1.6 ! root 2999: /* Stop translation as we may have switched the execution mode */
! 3000: ctx->bstate = BS_STOP;
1.1.1.5 root 3001: break;
3002: case 3:
1.1.1.6 ! root 3003: /* ignored, read only */
1.1.1.5 root 3004: rn = "Config3";
3005: break;
1.1.1.6 ! root 3006: /* 4,5 are reserved */
! 3007: /* 6,7 are implementation dependent */
! 3008: case 6:
! 3009: /* ignored */
! 3010: rn = "Config6";
! 3011: break;
! 3012: case 7:
! 3013: /* ignored */
! 3014: rn = "Config7";
! 3015: break;
1.1.1.5 root 3016: default:
3017: rn = "Invalid config selector";
3018: goto die;
3019: }
3020: break;
3021: case 17:
3022: switch (sel) {
3023: case 0:
1.1.1.6 ! root 3024: /* ignored */
! 3025: rn = "LLAddr";
! 3026: break;
1.1.1.5 root 3027: default:
3028: goto die;
3029: }
3030: break;
3031: case 18:
3032: switch (sel) {
1.1.1.6 ! root 3033: case 0 ... 7:
! 3034: gen_op_mtc0_watchlo(sel);
! 3035: rn = "WatchLo";
! 3036: break;
1.1.1.5 root 3037: default:
3038: goto die;
3039: }
3040: break;
3041: case 19:
3042: switch (sel) {
1.1.1.6 ! root 3043: case 0 ... 7:
! 3044: gen_op_mtc0_watchhi(sel);
! 3045: rn = "WatchHi";
! 3046: break;
1.1.1.5 root 3047: default:
3048: goto die;
3049: }
3050: break;
3051: case 20:
3052: switch (sel) {
3053: case 0:
1.1.1.6 ! root 3054: #if defined(TARGET_MIPS64)
! 3055: check_insn(env, ctx, ISA_MIPS3);
! 3056: gen_op_mtc0_xcontext();
! 3057: rn = "XContext";
! 3058: break;
! 3059: #endif
1.1.1.5 root 3060: default:
3061: goto die;
3062: }
3063: break;
3064: case 21:
3065: /* Officially reserved, but sel 0 is used for R1x000 framemask */
3066: switch (sel) {
3067: case 0:
1.1.1.6 ! root 3068: gen_op_mtc0_framemask();
! 3069: rn = "Framemask";
! 3070: break;
1.1.1.5 root 3071: default:
3072: goto die;
3073: }
3074: break;
3075: case 22:
3076: /* ignored */
3077: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 ! root 3078: break;
1.1.1.5 root 3079: case 23:
3080: switch (sel) {
3081: case 0:
1.1.1.6 ! root 3082: gen_op_mtc0_debug(); /* EJTAG support */
! 3083: /* BS_STOP isn't good enough here, hflags may have changed. */
! 3084: gen_save_pc(ctx->pc + 4);
! 3085: ctx->bstate = BS_EXCP;
! 3086: rn = "Debug";
! 3087: break;
! 3088: case 1:
! 3089: // gen_op_mtc0_tracecontrol(); /* PDtrace support */
! 3090: rn = "TraceControl";
! 3091: /* Stop translation as we may have switched the execution mode */
! 3092: ctx->bstate = BS_STOP;
! 3093: // break;
! 3094: case 2:
! 3095: // gen_op_mtc0_tracecontrol2(); /* PDtrace support */
! 3096: rn = "TraceControl2";
! 3097: /* Stop translation as we may have switched the execution mode */
! 3098: ctx->bstate = BS_STOP;
! 3099: // break;
! 3100: case 3:
! 3101: /* Stop translation as we may have switched the execution mode */
! 3102: ctx->bstate = BS_STOP;
! 3103: // gen_op_mtc0_usertracedata(); /* PDtrace support */
! 3104: rn = "UserTraceData";
! 3105: /* Stop translation as we may have switched the execution mode */
! 3106: ctx->bstate = BS_STOP;
! 3107: // break;
1.1.1.5 root 3108: case 4:
1.1.1.6 ! root 3109: // gen_op_mtc0_debug(); /* PDtrace support */
! 3110: /* Stop translation as we may have switched the execution mode */
! 3111: ctx->bstate = BS_STOP;
! 3112: rn = "TraceBPC";
! 3113: // break;
1.1.1.5 root 3114: default:
3115: goto die;
3116: }
3117: break;
3118: case 24:
3119: switch (sel) {
3120: case 0:
1.1.1.6 ! root 3121: gen_op_mtc0_depc(); /* EJTAG support */
! 3122: rn = "DEPC";
! 3123: break;
1.1.1.5 root 3124: default:
3125: goto die;
3126: }
3127: break;
3128: case 25:
3129: switch (sel) {
3130: case 0:
1.1.1.6 ! root 3131: gen_op_mtc0_performance0();
! 3132: rn = "Performance0";
! 3133: break;
! 3134: case 1:
! 3135: // gen_op_mtc0_performance1();
! 3136: rn = "Performance1";
! 3137: // break;
! 3138: case 2:
! 3139: // gen_op_mtc0_performance2();
! 3140: rn = "Performance2";
! 3141: // break;
! 3142: case 3:
! 3143: // gen_op_mtc0_performance3();
! 3144: rn = "Performance3";
! 3145: // break;
1.1.1.5 root 3146: case 4:
1.1.1.6 ! root 3147: // gen_op_mtc0_performance4();
! 3148: rn = "Performance4";
! 3149: // break;
1.1.1.5 root 3150: case 5:
1.1.1.6 ! root 3151: // gen_op_mtc0_performance5();
! 3152: rn = "Performance5";
! 3153: // break;
1.1.1.5 root 3154: case 6:
1.1.1.6 ! root 3155: // gen_op_mtc0_performance6();
! 3156: rn = "Performance6";
! 3157: // break;
1.1.1.5 root 3158: case 7:
1.1.1.6 ! root 3159: // gen_op_mtc0_performance7();
! 3160: rn = "Performance7";
! 3161: // break;
1.1.1.5 root 3162: default:
3163: goto die;
3164: }
3165: break;
3166: case 26:
1.1.1.6 ! root 3167: /* ignored */
1.1.1.5 root 3168: rn = "ECC";
1.1.1.6 ! root 3169: break;
1.1.1.5 root 3170: case 27:
3171: switch (sel) {
3172: case 0 ... 3:
1.1.1.6 ! root 3173: /* ignored */
! 3174: rn = "CacheErr";
! 3175: break;
1.1.1.5 root 3176: default:
3177: goto die;
3178: }
3179: break;
3180: case 28:
3181: switch (sel) {
3182: case 0:
3183: case 2:
3184: case 4:
3185: case 6:
3186: gen_op_mtc0_taglo();
3187: rn = "TagLo";
3188: break;
3189: case 1:
3190: case 3:
3191: case 5:
3192: case 7:
1.1.1.6 ! root 3193: gen_op_mtc0_datalo();
1.1.1.5 root 3194: rn = "DataLo";
3195: break;
3196: default:
3197: goto die;
3198: }
3199: break;
3200: case 29:
3201: switch (sel) {
3202: case 0:
3203: case 2:
3204: case 4:
3205: case 6:
3206: gen_op_mtc0_taghi();
3207: rn = "TagHi";
3208: break;
3209: case 1:
3210: case 3:
3211: case 5:
3212: case 7:
1.1.1.6 ! root 3213: gen_op_mtc0_datahi();
1.1.1.5 root 3214: rn = "DataHi";
3215: break;
3216: default:
3217: rn = "invalid sel";
3218: goto die;
3219: }
3220: break;
3221: case 30:
3222: switch (sel) {
3223: case 0:
1.1.1.6 ! root 3224: gen_op_mtc0_errorepc();
! 3225: rn = "ErrorEPC";
! 3226: break;
1.1.1.5 root 3227: default:
3228: goto die;
3229: }
3230: break;
3231: case 31:
3232: switch (sel) {
3233: case 0:
1.1.1.6 ! root 3234: gen_op_mtc0_desave(); /* EJTAG support */
! 3235: rn = "DESAVE";
! 3236: break;
1.1.1.5 root 3237: default:
3238: goto die;
3239: }
1.1.1.6 ! root 3240: /* Stop translation as we may have switched the execution mode */
! 3241: ctx->bstate = BS_STOP;
1.1.1.5 root 3242: break;
3243: default:
3244: goto die;
3245: }
3246: #if defined MIPS_DEBUG_DISAS
3247: if (loglevel & CPU_LOG_TB_IN_ASM) {
3248: fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3249: rn, reg, sel);
3250: }
3251: #endif
3252: return;
3253:
3254: die:
3255: #if defined MIPS_DEBUG_DISAS
3256: if (loglevel & CPU_LOG_TB_IN_ASM) {
3257: fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3258: rn, reg, sel);
3259: }
3260: #endif
3261: generate_exception(ctx, EXCP_RI);
3262: }
3263:
1.1.1.6 ! root 3264: #if defined(TARGET_MIPS64)
! 3265: static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
1.1.1.5 root 3266: {
3267: const char *rn = "invalid";
3268:
1.1.1.6 ! root 3269: if (sel != 0)
! 3270: check_insn(env, ctx, ISA_MIPS64);
! 3271:
1.1.1.5 root 3272: switch (reg) {
3273: case 0:
3274: switch (sel) {
3275: case 0:
1.1.1.6 ! root 3276: gen_op_mfc0_index();
1.1.1.5 root 3277: rn = "Index";
3278: break;
3279: case 1:
1.1.1.6 ! root 3280: check_insn(env, ctx, ASE_MT);
! 3281: gen_op_mfc0_mvpcontrol();
1.1.1.5 root 3282: rn = "MVPControl";
1.1.1.6 ! root 3283: break;
1.1.1.5 root 3284: case 2:
1.1.1.6 ! root 3285: check_insn(env, ctx, ASE_MT);
! 3286: gen_op_mfc0_mvpconf0();
1.1.1.5 root 3287: rn = "MVPConf0";
1.1.1.6 ! root 3288: break;
1.1.1.5 root 3289: case 3:
1.1.1.6 ! root 3290: check_insn(env, ctx, ASE_MT);
! 3291: gen_op_mfc0_mvpconf1();
1.1.1.5 root 3292: rn = "MVPConf1";
1.1.1.6 ! root 3293: break;
1.1.1.5 root 3294: default:
3295: goto die;
3296: }
3297: break;
3298: case 1:
3299: switch (sel) {
3300: case 0:
3301: gen_op_mfc0_random();
3302: rn = "Random";
1.1.1.6 ! root 3303: break;
1.1.1.5 root 3304: case 1:
1.1.1.6 ! root 3305: check_insn(env, ctx, ASE_MT);
! 3306: gen_op_mfc0_vpecontrol();
1.1.1.5 root 3307: rn = "VPEControl";
1.1.1.6 ! root 3308: break;
1.1.1.5 root 3309: case 2:
1.1.1.6 ! root 3310: check_insn(env, ctx, ASE_MT);
! 3311: gen_op_mfc0_vpeconf0();
1.1.1.5 root 3312: rn = "VPEConf0";
1.1.1.6 ! root 3313: break;
1.1.1.5 root 3314: case 3:
1.1.1.6 ! root 3315: check_insn(env, ctx, ASE_MT);
! 3316: gen_op_mfc0_vpeconf1();
1.1.1.5 root 3317: rn = "VPEConf1";
1.1.1.6 ! root 3318: break;
1.1.1.5 root 3319: case 4:
1.1.1.6 ! root 3320: check_insn(env, ctx, ASE_MT);
! 3321: gen_op_dmfc0_yqmask();
1.1.1.5 root 3322: rn = "YQMask";
1.1.1.6 ! root 3323: break;
1.1.1.5 root 3324: case 5:
1.1.1.6 ! root 3325: check_insn(env, ctx, ASE_MT);
! 3326: gen_op_dmfc0_vpeschedule();
1.1.1.5 root 3327: rn = "VPESchedule";
1.1.1.6 ! root 3328: break;
1.1.1.5 root 3329: case 6:
1.1.1.6 ! root 3330: check_insn(env, ctx, ASE_MT);
! 3331: gen_op_dmfc0_vpeschefback();
1.1.1.5 root 3332: rn = "VPEScheFBack";
1.1.1.6 ! root 3333: break;
1.1.1.5 root 3334: case 7:
1.1.1.6 ! root 3335: check_insn(env, ctx, ASE_MT);
! 3336: gen_op_mfc0_vpeopt();
1.1.1.5 root 3337: rn = "VPEOpt";
1.1.1.6 ! root 3338: break;
1.1.1.5 root 3339: default:
3340: goto die;
3341: }
3342: break;
3343: case 2:
3344: switch (sel) {
3345: case 0:
1.1.1.6 ! root 3346: gen_op_dmfc0_entrylo0();
! 3347: rn = "EntryLo0";
! 3348: break;
! 3349: case 1:
! 3350: check_insn(env, ctx, ASE_MT);
! 3351: gen_op_mfc0_tcstatus();
! 3352: rn = "TCStatus";
! 3353: break;
! 3354: case 2:
! 3355: check_insn(env, ctx, ASE_MT);
! 3356: gen_op_mfc0_tcbind();
! 3357: rn = "TCBind";
! 3358: break;
1.1.1.5 root 3359: case 3:
1.1.1.6 ! root 3360: check_insn(env, ctx, ASE_MT);
! 3361: gen_op_dmfc0_tcrestart();
! 3362: rn = "TCRestart";
! 3363: break;
1.1.1.5 root 3364: case 4:
1.1.1.6 ! root 3365: check_insn(env, ctx, ASE_MT);
! 3366: gen_op_dmfc0_tchalt();
! 3367: rn = "TCHalt";
! 3368: break;
1.1.1.5 root 3369: case 5:
1.1.1.6 ! root 3370: check_insn(env, ctx, ASE_MT);
! 3371: gen_op_dmfc0_tccontext();
! 3372: rn = "TCContext";
! 3373: break;
1.1.1.5 root 3374: case 6:
1.1.1.6 ! root 3375: check_insn(env, ctx, ASE_MT);
! 3376: gen_op_dmfc0_tcschedule();
! 3377: rn = "TCSchedule";
! 3378: break;
1.1.1.5 root 3379: case 7:
1.1.1.6 ! root 3380: check_insn(env, ctx, ASE_MT);
! 3381: gen_op_dmfc0_tcschefback();
! 3382: rn = "TCScheFBack";
! 3383: break;
1.1.1.5 root 3384: default:
3385: goto die;
3386: }
3387: break;
3388: case 3:
3389: switch (sel) {
3390: case 0:
1.1.1.6 ! root 3391: gen_op_dmfc0_entrylo1();
! 3392: rn = "EntryLo1";
! 3393: break;
1.1.1.5 root 3394: default:
3395: goto die;
1.1.1.6 ! root 3396: }
1.1.1.5 root 3397: break;
3398: case 4:
3399: switch (sel) {
3400: case 0:
1.1.1.6 ! root 3401: gen_op_dmfc0_context();
! 3402: rn = "Context";
! 3403: break;
! 3404: case 1:
! 3405: // gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */
! 3406: rn = "ContextConfig";
! 3407: // break;
1.1.1.5 root 3408: default:
3409: goto die;
1.1.1.6 ! root 3410: }
1.1.1.5 root 3411: break;
3412: case 5:
3413: switch (sel) {
3414: case 0:
1.1.1.6 ! root 3415: gen_op_mfc0_pagemask();
! 3416: rn = "PageMask";
! 3417: break;
! 3418: case 1:
! 3419: check_insn(env, ctx, ISA_MIPS32R2);
! 3420: gen_op_mfc0_pagegrain();
! 3421: rn = "PageGrain";
! 3422: break;
1.1.1.5 root 3423: default:
3424: goto die;
1.1.1.6 ! root 3425: }
1.1.1.5 root 3426: break;
3427: case 6:
3428: switch (sel) {
3429: case 0:
1.1.1.6 ! root 3430: gen_op_mfc0_wired();
! 3431: rn = "Wired";
! 3432: break;
! 3433: case 1:
! 3434: check_insn(env, ctx, ISA_MIPS32R2);
! 3435: gen_op_mfc0_srsconf0();
! 3436: rn = "SRSConf0";
! 3437: break;
! 3438: case 2:
! 3439: check_insn(env, ctx, ISA_MIPS32R2);
! 3440: gen_op_mfc0_srsconf1();
! 3441: rn = "SRSConf1";
! 3442: break;
1.1.1.5 root 3443: case 3:
1.1.1.6 ! root 3444: check_insn(env, ctx, ISA_MIPS32R2);
! 3445: gen_op_mfc0_srsconf2();
! 3446: rn = "SRSConf2";
! 3447: break;
1.1.1.5 root 3448: case 4:
1.1.1.6 ! root 3449: check_insn(env, ctx, ISA_MIPS32R2);
! 3450: gen_op_mfc0_srsconf3();
! 3451: rn = "SRSConf3";
! 3452: break;
1.1.1.5 root 3453: case 5:
1.1.1.6 ! root 3454: check_insn(env, ctx, ISA_MIPS32R2);
! 3455: gen_op_mfc0_srsconf4();
! 3456: rn = "SRSConf4";
! 3457: break;
1.1.1.5 root 3458: default:
3459: goto die;
1.1.1.6 ! root 3460: }
1.1.1.5 root 3461: break;
3462: case 7:
3463: switch (sel) {
3464: case 0:
1.1.1.6 ! root 3465: check_insn(env, ctx, ISA_MIPS32R2);
! 3466: gen_op_mfc0_hwrena();
! 3467: rn = "HWREna";
! 3468: break;
1.1.1.5 root 3469: default:
3470: goto die;
1.1.1.6 ! root 3471: }
1.1.1.5 root 3472: break;
3473: case 8:
3474: switch (sel) {
3475: case 0:
1.1.1.6 ! root 3476: gen_op_dmfc0_badvaddr();
! 3477: rn = "BadVaddr";
! 3478: break;
1.1.1.5 root 3479: default:
3480: goto die;
1.1.1.6 ! root 3481: }
1.1.1.5 root 3482: break;
3483: case 9:
3484: switch (sel) {
3485: case 0:
1.1.1.6 ! root 3486: gen_op_mfc0_count();
! 3487: rn = "Count";
! 3488: break;
! 3489: /* 6,7 are implementation dependent */
1.1.1.5 root 3490: default:
3491: goto die;
1.1.1.6 ! root 3492: }
1.1.1.5 root 3493: break;
3494: case 10:
3495: switch (sel) {
3496: case 0:
1.1.1.6 ! root 3497: gen_op_dmfc0_entryhi();
! 3498: rn = "EntryHi";
! 3499: break;
1.1.1.5 root 3500: default:
3501: goto die;
1.1.1.6 ! root 3502: }
1.1.1.5 root 3503: break;
3504: case 11:
3505: switch (sel) {
3506: case 0:
1.1.1.6 ! root 3507: gen_op_mfc0_compare();
! 3508: rn = "Compare";
! 3509: break;
! 3510: /* 6,7 are implementation dependent */
1.1.1.5 root 3511: default:
3512: goto die;
1.1.1.6 ! root 3513: }
1.1.1.5 root 3514: break;
3515: case 12:
3516: switch (sel) {
3517: case 0:
1.1.1.6 ! root 3518: gen_op_mfc0_status();
! 3519: rn = "Status";
! 3520: break;
! 3521: case 1:
! 3522: check_insn(env, ctx, ISA_MIPS32R2);
! 3523: gen_op_mfc0_intctl();
! 3524: rn = "IntCtl";
! 3525: break;
! 3526: case 2:
! 3527: check_insn(env, ctx, ISA_MIPS32R2);
! 3528: gen_op_mfc0_srsctl();
! 3529: rn = "SRSCtl";
! 3530: break;
1.1.1.5 root 3531: case 3:
1.1.1.6 ! root 3532: check_insn(env, ctx, ISA_MIPS32R2);
! 3533: gen_op_mfc0_srsmap();
! 3534: rn = "SRSMap";
! 3535: break;
1.1.1.5 root 3536: default:
3537: goto die;
1.1.1.6 ! root 3538: }
1.1.1.5 root 3539: break;
3540: case 13:
3541: switch (sel) {
3542: case 0:
1.1.1.6 ! root 3543: gen_op_mfc0_cause();
! 3544: rn = "Cause";
! 3545: break;
1.1.1.5 root 3546: default:
3547: goto die;
1.1.1.6 ! root 3548: }
1.1.1.5 root 3549: break;
3550: case 14:
3551: switch (sel) {
3552: case 0:
1.1.1.6 ! root 3553: gen_op_dmfc0_epc();
! 3554: rn = "EPC";
! 3555: break;
1.1.1.5 root 3556: default:
3557: goto die;
1.1.1.6 ! root 3558: }
1.1.1.5 root 3559: break;
3560: case 15:
3561: switch (sel) {
3562: case 0:
1.1.1.6 ! root 3563: gen_op_mfc0_prid();
! 3564: rn = "PRid";
! 3565: break;
! 3566: case 1:
! 3567: check_insn(env, ctx, ISA_MIPS32R2);
! 3568: gen_op_mfc0_ebase();
! 3569: rn = "EBase";
! 3570: break;
1.1.1.5 root 3571: default:
3572: goto die;
1.1.1.6 ! root 3573: }
1.1.1.5 root 3574: break;
3575: case 16:
3576: switch (sel) {
3577: case 0:
1.1.1.6 ! root 3578: gen_op_mfc0_config0();
1.1.1.5 root 3579: rn = "Config";
3580: break;
3581: case 1:
1.1.1.6 ! root 3582: gen_op_mfc0_config1();
1.1.1.5 root 3583: rn = "Config1";
3584: break;
3585: case 2:
1.1.1.6 ! root 3586: gen_op_mfc0_config2();
1.1.1.5 root 3587: rn = "Config2";
3588: break;
3589: case 3:
1.1.1.6 ! root 3590: gen_op_mfc0_config3();
1.1.1.5 root 3591: rn = "Config3";
3592: break;
3593: /* 6,7 are implementation dependent */
3594: default:
3595: goto die;
3596: }
3597: break;
3598: case 17:
3599: switch (sel) {
3600: case 0:
1.1.1.6 ! root 3601: gen_op_dmfc0_lladdr();
! 3602: rn = "LLAddr";
! 3603: break;
1.1.1.5 root 3604: default:
3605: goto die;
3606: }
3607: break;
3608: case 18:
3609: switch (sel) {
1.1.1.6 ! root 3610: case 0 ... 7:
! 3611: gen_op_dmfc0_watchlo(sel);
! 3612: rn = "WatchLo";
! 3613: break;
1.1.1.5 root 3614: default:
3615: goto die;
3616: }
3617: break;
3618: case 19:
3619: switch (sel) {
1.1.1.6 ! root 3620: case 0 ... 7:
! 3621: gen_op_mfc0_watchhi(sel);
! 3622: rn = "WatchHi";
! 3623: break;
1.1.1.5 root 3624: default:
3625: goto die;
3626: }
3627: break;
3628: case 20:
3629: switch (sel) {
3630: case 0:
1.1.1.6 ! root 3631: check_insn(env, ctx, ISA_MIPS3);
! 3632: gen_op_dmfc0_xcontext();
! 3633: rn = "XContext";
! 3634: break;
1.1.1.5 root 3635: default:
3636: goto die;
3637: }
3638: break;
3639: case 21:
3640: /* Officially reserved, but sel 0 is used for R1x000 framemask */
3641: switch (sel) {
3642: case 0:
1.1.1.6 ! root 3643: gen_op_mfc0_framemask();
! 3644: rn = "Framemask";
! 3645: break;
1.1.1.5 root 3646: default:
3647: goto die;
3648: }
3649: break;
3650: case 22:
1.1.1.6 ! root 3651: /* ignored */
! 3652: rn = "'Diagnostic"; /* implementation dependent */
! 3653: break;
1.1.1.5 root 3654: case 23:
3655: switch (sel) {
3656: case 0:
1.1.1.6 ! root 3657: gen_op_mfc0_debug(); /* EJTAG support */
! 3658: rn = "Debug";
! 3659: break;
! 3660: case 1:
! 3661: // gen_op_dmfc0_tracecontrol(); /* PDtrace support */
! 3662: rn = "TraceControl";
! 3663: // break;
! 3664: case 2:
! 3665: // gen_op_dmfc0_tracecontrol2(); /* PDtrace support */
! 3666: rn = "TraceControl2";
! 3667: // break;
1.1.1.5 root 3668: case 3:
1.1.1.6 ! root 3669: // gen_op_dmfc0_usertracedata(); /* PDtrace support */
! 3670: rn = "UserTraceData";
! 3671: // break;
1.1.1.5 root 3672: case 4:
1.1.1.6 ! root 3673: // gen_op_dmfc0_debug(); /* PDtrace support */
! 3674: rn = "TraceBPC";
! 3675: // break;
1.1.1.5 root 3676: default:
3677: goto die;
3678: }
3679: break;
3680: case 24:
3681: switch (sel) {
3682: case 0:
1.1.1.6 ! root 3683: gen_op_dmfc0_depc(); /* EJTAG support */
! 3684: rn = "DEPC";
! 3685: break;
1.1.1.5 root 3686: default:
3687: goto die;
3688: }
3689: break;
3690: case 25:
3691: switch (sel) {
3692: case 0:
1.1.1.6 ! root 3693: gen_op_mfc0_performance0();
! 3694: rn = "Performance0";
1.1.1.5 root 3695: break;
3696: case 1:
1.1.1.6 ! root 3697: // gen_op_dmfc0_performance1();
! 3698: rn = "Performance1";
! 3699: // break;
1.1.1.5 root 3700: case 2:
1.1.1.6 ! root 3701: // gen_op_dmfc0_performance2();
! 3702: rn = "Performance2";
! 3703: // break;
1.1.1.5 root 3704: case 3:
1.1.1.6 ! root 3705: // gen_op_dmfc0_performance3();
! 3706: rn = "Performance3";
! 3707: // break;
1.1.1.5 root 3708: case 4:
1.1.1.6 ! root 3709: // gen_op_dmfc0_performance4();
! 3710: rn = "Performance4";
! 3711: // break;
1.1.1.5 root 3712: case 5:
1.1.1.6 ! root 3713: // gen_op_dmfc0_performance5();
! 3714: rn = "Performance5";
! 3715: // break;
1.1.1.5 root 3716: case 6:
1.1.1.6 ! root 3717: // gen_op_dmfc0_performance6();
! 3718: rn = "Performance6";
! 3719: // break;
1.1.1.5 root 3720: case 7:
1.1.1.6 ! root 3721: // gen_op_dmfc0_performance7();
! 3722: rn = "Performance7";
! 3723: // break;
1.1.1.5 root 3724: default:
3725: goto die;
3726: }
3727: break;
3728: case 26:
3729: rn = "ECC";
3730: break;
3731: case 27:
3732: switch (sel) {
3733: /* ignored */
3734: case 0 ... 3:
1.1.1.6 ! root 3735: rn = "CacheErr";
! 3736: break;
1.1.1.5 root 3737: default:
3738: goto die;
3739: }
3740: break;
3741: case 28:
3742: switch (sel) {
3743: case 0:
3744: case 2:
3745: case 4:
3746: case 6:
3747: gen_op_mfc0_taglo();
3748: rn = "TagLo";
3749: break;
3750: case 1:
3751: case 3:
3752: case 5:
3753: case 7:
3754: gen_op_mfc0_datalo();
3755: rn = "DataLo";
3756: break;
3757: default:
3758: goto die;
3759: }
3760: break;
3761: case 29:
3762: switch (sel) {
3763: case 0:
3764: case 2:
3765: case 4:
3766: case 6:
3767: gen_op_mfc0_taghi();
3768: rn = "TagHi";
3769: break;
3770: case 1:
3771: case 3:
3772: case 5:
3773: case 7:
3774: gen_op_mfc0_datahi();
3775: rn = "DataHi";
3776: break;
3777: default:
3778: goto die;
3779: }
3780: break;
3781: case 30:
3782: switch (sel) {
3783: case 0:
1.1.1.6 ! root 3784: gen_op_dmfc0_errorepc();
! 3785: rn = "ErrorEPC";
! 3786: break;
1.1.1.5 root 3787: default:
3788: goto die;
3789: }
3790: break;
3791: case 31:
3792: switch (sel) {
3793: case 0:
1.1.1.6 ! root 3794: gen_op_mfc0_desave(); /* EJTAG support */
! 3795: rn = "DESAVE";
! 3796: break;
1.1.1.5 root 3797: default:
3798: goto die;
3799: }
3800: break;
3801: default:
1.1.1.6 ! root 3802: goto die;
1.1.1.5 root 3803: }
3804: #if defined MIPS_DEBUG_DISAS
3805: if (loglevel & CPU_LOG_TB_IN_ASM) {
3806: fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3807: rn, reg, sel);
3808: }
3809: #endif
3810: return;
3811:
3812: die:
3813: #if defined MIPS_DEBUG_DISAS
3814: if (loglevel & CPU_LOG_TB_IN_ASM) {
3815: fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3816: rn, reg, sel);
3817: }
3818: #endif
3819: generate_exception(ctx, EXCP_RI);
3820: }
3821:
1.1.1.6 ! root 3822: static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
1.1.1.5 root 3823: {
3824: const char *rn = "invalid";
3825:
1.1.1.6 ! root 3826: if (sel != 0)
! 3827: check_insn(env, ctx, ISA_MIPS64);
! 3828:
1.1.1.5 root 3829: switch (reg) {
3830: case 0:
3831: switch (sel) {
3832: case 0:
3833: gen_op_mtc0_index();
3834: rn = "Index";
3835: break;
3836: case 1:
1.1.1.6 ! root 3837: check_insn(env, ctx, ASE_MT);
! 3838: gen_op_mtc0_mvpcontrol();
1.1.1.5 root 3839: rn = "MVPControl";
1.1.1.6 ! root 3840: break;
1.1.1.5 root 3841: case 2:
1.1.1.6 ! root 3842: check_insn(env, ctx, ASE_MT);
! 3843: /* ignored */
1.1.1.5 root 3844: rn = "MVPConf0";
1.1.1.6 ! root 3845: break;
1.1.1.5 root 3846: case 3:
1.1.1.6 ! root 3847: check_insn(env, ctx, ASE_MT);
! 3848: /* ignored */
1.1.1.5 root 3849: rn = "MVPConf1";
1.1.1.6 ! root 3850: break;
1.1.1.5 root 3851: default:
3852: goto die;
3853: }
3854: break;
3855: case 1:
3856: switch (sel) {
3857: case 0:
1.1.1.6 ! root 3858: /* ignored */
1.1.1.5 root 3859: rn = "Random";
1.1.1.6 ! root 3860: break;
1.1.1.5 root 3861: case 1:
1.1.1.6 ! root 3862: check_insn(env, ctx, ASE_MT);
! 3863: gen_op_mtc0_vpecontrol();
1.1.1.5 root 3864: rn = "VPEControl";
1.1.1.6 ! root 3865: break;
1.1.1.5 root 3866: case 2:
1.1.1.6 ! root 3867: check_insn(env, ctx, ASE_MT);
! 3868: gen_op_mtc0_vpeconf0();
1.1.1.5 root 3869: rn = "VPEConf0";
1.1.1.6 ! root 3870: break;
1.1.1.5 root 3871: case 3:
1.1.1.6 ! root 3872: check_insn(env, ctx, ASE_MT);
! 3873: gen_op_mtc0_vpeconf1();
1.1.1.5 root 3874: rn = "VPEConf1";
1.1.1.6 ! root 3875: break;
1.1.1.5 root 3876: case 4:
1.1.1.6 ! root 3877: check_insn(env, ctx, ASE_MT);
! 3878: gen_op_mtc0_yqmask();
1.1.1.5 root 3879: rn = "YQMask";
1.1.1.6 ! root 3880: break;
1.1.1.5 root 3881: case 5:
1.1.1.6 ! root 3882: check_insn(env, ctx, ASE_MT);
! 3883: gen_op_mtc0_vpeschedule();
1.1.1.5 root 3884: rn = "VPESchedule";
1.1.1.6 ! root 3885: break;
1.1.1.5 root 3886: case 6:
1.1.1.6 ! root 3887: check_insn(env, ctx, ASE_MT);
! 3888: gen_op_mtc0_vpeschefback();
1.1.1.5 root 3889: rn = "VPEScheFBack";
1.1.1.6 ! root 3890: break;
1.1.1.5 root 3891: case 7:
1.1.1.6 ! root 3892: check_insn(env, ctx, ASE_MT);
! 3893: gen_op_mtc0_vpeopt();
1.1.1.5 root 3894: rn = "VPEOpt";
1.1.1.6 ! root 3895: break;
1.1.1.5 root 3896: default:
3897: goto die;
3898: }
3899: break;
3900: case 2:
3901: switch (sel) {
3902: case 0:
1.1.1.6 ! root 3903: gen_op_mtc0_entrylo0();
! 3904: rn = "EntryLo0";
! 3905: break;
! 3906: case 1:
! 3907: check_insn(env, ctx, ASE_MT);
! 3908: gen_op_mtc0_tcstatus();
! 3909: rn = "TCStatus";
! 3910: break;
! 3911: case 2:
! 3912: check_insn(env, ctx, ASE_MT);
! 3913: gen_op_mtc0_tcbind();
! 3914: rn = "TCBind";
! 3915: break;
1.1.1.5 root 3916: case 3:
1.1.1.6 ! root 3917: check_insn(env, ctx, ASE_MT);
! 3918: gen_op_mtc0_tcrestart();
! 3919: rn = "TCRestart";
! 3920: break;
1.1.1.5 root 3921: case 4:
1.1.1.6 ! root 3922: check_insn(env, ctx, ASE_MT);
! 3923: gen_op_mtc0_tchalt();
! 3924: rn = "TCHalt";
! 3925: break;
1.1.1.5 root 3926: case 5:
1.1.1.6 ! root 3927: check_insn(env, ctx, ASE_MT);
! 3928: gen_op_mtc0_tccontext();
! 3929: rn = "TCContext";
! 3930: break;
1.1.1.5 root 3931: case 6:
1.1.1.6 ! root 3932: check_insn(env, ctx, ASE_MT);
! 3933: gen_op_mtc0_tcschedule();
! 3934: rn = "TCSchedule";
! 3935: break;
1.1.1.5 root 3936: case 7:
1.1.1.6 ! root 3937: check_insn(env, ctx, ASE_MT);
! 3938: gen_op_mtc0_tcschefback();
! 3939: rn = "TCScheFBack";
! 3940: break;
1.1.1.5 root 3941: default:
3942: goto die;
3943: }
3944: break;
3945: case 3:
3946: switch (sel) {
3947: case 0:
1.1.1.6 ! root 3948: gen_op_mtc0_entrylo1();
! 3949: rn = "EntryLo1";
! 3950: break;
1.1.1.5 root 3951: default:
3952: goto die;
1.1.1.6 ! root 3953: }
1.1.1.5 root 3954: break;
3955: case 4:
3956: switch (sel) {
3957: case 0:
1.1.1.6 ! root 3958: gen_op_mtc0_context();
! 3959: rn = "Context";
! 3960: break;
! 3961: case 1:
! 3962: // gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
! 3963: rn = "ContextConfig";
! 3964: // break;
1.1.1.5 root 3965: default:
3966: goto die;
1.1.1.6 ! root 3967: }
1.1.1.5 root 3968: break;
3969: case 5:
3970: switch (sel) {
3971: case 0:
1.1.1.6 ! root 3972: gen_op_mtc0_pagemask();
! 3973: rn = "PageMask";
! 3974: break;
! 3975: case 1:
! 3976: check_insn(env, ctx, ISA_MIPS32R2);
! 3977: gen_op_mtc0_pagegrain();
! 3978: rn = "PageGrain";
! 3979: break;
1.1.1.5 root 3980: default:
3981: goto die;
1.1.1.6 ! root 3982: }
1.1.1.5 root 3983: break;
3984: case 6:
3985: switch (sel) {
3986: case 0:
1.1.1.6 ! root 3987: gen_op_mtc0_wired();
! 3988: rn = "Wired";
! 3989: break;
! 3990: case 1:
! 3991: check_insn(env, ctx, ISA_MIPS32R2);
! 3992: gen_op_mtc0_srsconf0();
! 3993: rn = "SRSConf0";
! 3994: break;
! 3995: case 2:
! 3996: check_insn(env, ctx, ISA_MIPS32R2);
! 3997: gen_op_mtc0_srsconf1();
! 3998: rn = "SRSConf1";
! 3999: break;
1.1.1.5 root 4000: case 3:
1.1.1.6 ! root 4001: check_insn(env, ctx, ISA_MIPS32R2);
! 4002: gen_op_mtc0_srsconf2();
! 4003: rn = "SRSConf2";
! 4004: break;
1.1.1.5 root 4005: case 4:
1.1.1.6 ! root 4006: check_insn(env, ctx, ISA_MIPS32R2);
! 4007: gen_op_mtc0_srsconf3();
! 4008: rn = "SRSConf3";
! 4009: break;
1.1.1.5 root 4010: case 5:
1.1.1.6 ! root 4011: check_insn(env, ctx, ISA_MIPS32R2);
! 4012: gen_op_mtc0_srsconf4();
! 4013: rn = "SRSConf4";
! 4014: break;
1.1.1.5 root 4015: default:
4016: goto die;
1.1.1.6 ! root 4017: }
1.1.1.5 root 4018: break;
4019: case 7:
4020: switch (sel) {
4021: case 0:
1.1.1.6 ! root 4022: check_insn(env, ctx, ISA_MIPS32R2);
! 4023: gen_op_mtc0_hwrena();
! 4024: rn = "HWREna";
! 4025: break;
1.1.1.5 root 4026: default:
4027: goto die;
1.1.1.6 ! root 4028: }
1.1.1.5 root 4029: break;
4030: case 8:
4031: /* ignored */
4032: rn = "BadVaddr";
4033: break;
4034: case 9:
4035: switch (sel) {
4036: case 0:
1.1.1.6 ! root 4037: gen_op_mtc0_count();
! 4038: rn = "Count";
! 4039: break;
! 4040: /* 6,7 are implementation dependent */
1.1.1.5 root 4041: default:
4042: goto die;
1.1.1.6 ! root 4043: }
! 4044: /* Stop translation as we may have switched the execution mode */
! 4045: ctx->bstate = BS_STOP;
1.1.1.5 root 4046: break;
4047: case 10:
4048: switch (sel) {
4049: case 0:
1.1.1.6 ! root 4050: gen_op_mtc0_entryhi();
! 4051: rn = "EntryHi";
! 4052: break;
1.1.1.5 root 4053: default:
4054: goto die;
1.1.1.6 ! root 4055: }
1.1.1.5 root 4056: break;
4057: case 11:
4058: switch (sel) {
4059: case 0:
1.1.1.6 ! root 4060: gen_op_mtc0_compare();
! 4061: rn = "Compare";
! 4062: break;
! 4063: /* 6,7 are implementation dependent */
1.1.1.5 root 4064: default:
4065: goto die;
1.1.1.6 ! root 4066: }
! 4067: /* Stop translation as we may have switched the execution mode */
! 4068: ctx->bstate = BS_STOP;
1.1.1.5 root 4069: break;
4070: case 12:
4071: switch (sel) {
4072: case 0:
1.1.1.6 ! root 4073: gen_op_mtc0_status();
! 4074: /* BS_STOP isn't good enough here, hflags may have changed. */
! 4075: gen_save_pc(ctx->pc + 4);
! 4076: ctx->bstate = BS_EXCP;
! 4077: rn = "Status";
! 4078: break;
! 4079: case 1:
! 4080: check_insn(env, ctx, ISA_MIPS32R2);
! 4081: gen_op_mtc0_intctl();
! 4082: /* Stop translation as we may have switched the execution mode */
! 4083: ctx->bstate = BS_STOP;
! 4084: rn = "IntCtl";
! 4085: break;
! 4086: case 2:
! 4087: check_insn(env, ctx, ISA_MIPS32R2);
! 4088: gen_op_mtc0_srsctl();
! 4089: /* Stop translation as we may have switched the execution mode */
! 4090: ctx->bstate = BS_STOP;
! 4091: rn = "SRSCtl";
! 4092: break;
1.1.1.5 root 4093: case 3:
1.1.1.6 ! root 4094: check_insn(env, ctx, ISA_MIPS32R2);
! 4095: gen_op_mtc0_srsmap();
! 4096: /* Stop translation as we may have switched the execution mode */
! 4097: ctx->bstate = BS_STOP;
! 4098: rn = "SRSMap";
! 4099: break;
1.1.1.5 root 4100: default:
4101: goto die;
1.1.1.6 ! root 4102: }
1.1.1.5 root 4103: break;
4104: case 13:
4105: switch (sel) {
4106: case 0:
1.1.1.6 ! root 4107: gen_op_mtc0_cause();
! 4108: rn = "Cause";
! 4109: break;
1.1.1.5 root 4110: default:
4111: goto die;
1.1.1.6 ! root 4112: }
! 4113: /* Stop translation as we may have switched the execution mode */
! 4114: ctx->bstate = BS_STOP;
1.1.1.5 root 4115: break;
4116: case 14:
4117: switch (sel) {
4118: case 0:
1.1.1.6 ! root 4119: gen_op_mtc0_epc();
! 4120: rn = "EPC";
! 4121: break;
1.1.1.5 root 4122: default:
4123: goto die;
1.1.1.6 ! root 4124: }
1.1.1.5 root 4125: break;
4126: case 15:
4127: switch (sel) {
4128: case 0:
1.1.1.6 ! root 4129: /* ignored */
! 4130: rn = "PRid";
! 4131: break;
! 4132: case 1:
! 4133: check_insn(env, ctx, ISA_MIPS32R2);
! 4134: gen_op_mtc0_ebase();
! 4135: rn = "EBase";
! 4136: break;
1.1.1.5 root 4137: default:
4138: goto die;
1.1.1.6 ! root 4139: }
1.1.1.5 root 4140: break;
4141: case 16:
4142: switch (sel) {
4143: case 0:
4144: gen_op_mtc0_config0();
4145: rn = "Config";
1.1.1.6 ! root 4146: /* Stop translation as we may have switched the execution mode */
! 4147: ctx->bstate = BS_STOP;
1.1.1.5 root 4148: break;
4149: case 1:
1.1.1.6 ! root 4150: /* ignored */
1.1.1.5 root 4151: rn = "Config1";
4152: break;
4153: case 2:
4154: gen_op_mtc0_config2();
4155: rn = "Config2";
1.1.1.6 ! root 4156: /* Stop translation as we may have switched the execution mode */
! 4157: ctx->bstate = BS_STOP;
1.1.1.5 root 4158: break;
4159: case 3:
1.1.1.6 ! root 4160: /* ignored */
1.1.1.5 root 4161: rn = "Config3";
4162: break;
4163: /* 6,7 are implementation dependent */
4164: default:
4165: rn = "Invalid config selector";
4166: goto die;
4167: }
4168: break;
4169: case 17:
4170: switch (sel) {
4171: case 0:
1.1.1.6 ! root 4172: /* ignored */
! 4173: rn = "LLAddr";
! 4174: break;
1.1.1.5 root 4175: default:
4176: goto die;
4177: }
4178: break;
4179: case 18:
4180: switch (sel) {
1.1.1.6 ! root 4181: case 0 ... 7:
! 4182: gen_op_mtc0_watchlo(sel);
! 4183: rn = "WatchLo";
! 4184: break;
1.1.1.5 root 4185: default:
4186: goto die;
4187: }
4188: break;
4189: case 19:
4190: switch (sel) {
1.1.1.6 ! root 4191: case 0 ... 7:
! 4192: gen_op_mtc0_watchhi(sel);
! 4193: rn = "WatchHi";
! 4194: break;
1.1.1.5 root 4195: default:
4196: goto die;
4197: }
4198: break;
4199: case 20:
4200: switch (sel) {
4201: case 0:
1.1.1.6 ! root 4202: check_insn(env, ctx, ISA_MIPS3);
! 4203: gen_op_mtc0_xcontext();
! 4204: rn = "XContext";
! 4205: break;
1.1.1.5 root 4206: default:
4207: goto die;
4208: }
4209: break;
4210: case 21:
4211: /* Officially reserved, but sel 0 is used for R1x000 framemask */
4212: switch (sel) {
4213: case 0:
1.1.1.6 ! root 4214: gen_op_mtc0_framemask();
! 4215: rn = "Framemask";
! 4216: break;
1.1.1.5 root 4217: default:
4218: goto die;
4219: }
4220: break;
4221: case 22:
4222: /* ignored */
4223: rn = "Diagnostic"; /* implementation dependent */
1.1.1.6 ! root 4224: break;
1.1.1.5 root 4225: case 23:
4226: switch (sel) {
4227: case 0:
1.1.1.6 ! root 4228: gen_op_mtc0_debug(); /* EJTAG support */
! 4229: /* BS_STOP isn't good enough here, hflags may have changed. */
! 4230: gen_save_pc(ctx->pc + 4);
! 4231: ctx->bstate = BS_EXCP;
! 4232: rn = "Debug";
! 4233: break;
! 4234: case 1:
! 4235: // gen_op_mtc0_tracecontrol(); /* PDtrace support */
! 4236: /* Stop translation as we may have switched the execution mode */
! 4237: ctx->bstate = BS_STOP;
! 4238: rn = "TraceControl";
! 4239: // break;
! 4240: case 2:
! 4241: // gen_op_mtc0_tracecontrol2(); /* PDtrace support */
! 4242: /* Stop translation as we may have switched the execution mode */
! 4243: ctx->bstate = BS_STOP;
! 4244: rn = "TraceControl2";
! 4245: // break;
! 4246: case 3:
! 4247: // gen_op_mtc0_usertracedata(); /* PDtrace support */
! 4248: /* Stop translation as we may have switched the execution mode */
! 4249: ctx->bstate = BS_STOP;
! 4250: rn = "UserTraceData";
! 4251: // break;
1.1.1.5 root 4252: case 4:
1.1.1.6 ! root 4253: // gen_op_mtc0_debug(); /* PDtrace support */
! 4254: /* Stop translation as we may have switched the execution mode */
! 4255: ctx->bstate = BS_STOP;
! 4256: rn = "TraceBPC";
! 4257: // break;
1.1.1.5 root 4258: default:
4259: goto die;
4260: }
4261: break;
4262: case 24:
4263: switch (sel) {
4264: case 0:
1.1.1.6 ! root 4265: gen_op_mtc0_depc(); /* EJTAG support */
! 4266: rn = "DEPC";
! 4267: break;
1.1.1.5 root 4268: default:
4269: goto die;
4270: }
4271: break;
4272: case 25:
4273: switch (sel) {
4274: case 0:
1.1.1.6 ! root 4275: gen_op_mtc0_performance0();
! 4276: rn = "Performance0";
! 4277: break;
! 4278: case 1:
! 4279: // gen_op_mtc0_performance1();
! 4280: rn = "Performance1";
! 4281: // break;
! 4282: case 2:
! 4283: // gen_op_mtc0_performance2();
! 4284: rn = "Performance2";
! 4285: // break;
1.1.1.5 root 4286: case 3:
1.1.1.6 ! root 4287: // gen_op_mtc0_performance3();
! 4288: rn = "Performance3";
! 4289: // break;
1.1.1.5 root 4290: case 4:
1.1.1.6 ! root 4291: // gen_op_mtc0_performance4();
! 4292: rn = "Performance4";
! 4293: // break;
1.1.1.5 root 4294: case 5:
1.1.1.6 ! root 4295: // gen_op_mtc0_performance5();
! 4296: rn = "Performance5";
! 4297: // break;
1.1.1.5 root 4298: case 6:
1.1.1.6 ! root 4299: // gen_op_mtc0_performance6();
! 4300: rn = "Performance6";
! 4301: // break;
1.1.1.5 root 4302: case 7:
1.1.1.6 ! root 4303: // gen_op_mtc0_performance7();
! 4304: rn = "Performance7";
! 4305: // break;
1.1.1.5 root 4306: default:
4307: goto die;
4308: }
1.1.1.6 ! root 4309: break;
1.1.1.5 root 4310: case 26:
1.1.1.6 ! root 4311: /* ignored */
1.1.1.5 root 4312: rn = "ECC";
1.1.1.6 ! root 4313: break;
1.1.1.5 root 4314: case 27:
4315: switch (sel) {
4316: case 0 ... 3:
1.1.1.6 ! root 4317: /* ignored */
! 4318: rn = "CacheErr";
! 4319: break;
1.1.1.5 root 4320: default:
4321: goto die;
4322: }
1.1.1.6 ! root 4323: break;
1.1.1.5 root 4324: case 28:
4325: switch (sel) {
4326: case 0:
4327: case 2:
4328: case 4:
4329: case 6:
4330: gen_op_mtc0_taglo();
4331: rn = "TagLo";
4332: break;
4333: case 1:
4334: case 3:
4335: case 5:
4336: case 7:
1.1.1.6 ! root 4337: gen_op_mtc0_datalo();
1.1.1.5 root 4338: rn = "DataLo";
4339: break;
4340: default:
4341: goto die;
4342: }
4343: break;
4344: case 29:
4345: switch (sel) {
4346: case 0:
4347: case 2:
4348: case 4:
4349: case 6:
4350: gen_op_mtc0_taghi();
4351: rn = "TagHi";
4352: break;
4353: case 1:
4354: case 3:
4355: case 5:
4356: case 7:
1.1.1.6 ! root 4357: gen_op_mtc0_datahi();
1.1.1.5 root 4358: rn = "DataHi";
4359: break;
4360: default:
4361: rn = "invalid sel";
4362: goto die;
4363: }
1.1.1.6 ! root 4364: break;
1.1.1.5 root 4365: case 30:
4366: switch (sel) {
4367: case 0:
1.1.1.6 ! root 4368: gen_op_mtc0_errorepc();
! 4369: rn = "ErrorEPC";
! 4370: break;
1.1.1.5 root 4371: default:
4372: goto die;
4373: }
4374: break;
4375: case 31:
4376: switch (sel) {
4377: case 0:
1.1.1.6 ! root 4378: gen_op_mtc0_desave(); /* EJTAG support */
! 4379: rn = "DESAVE";
! 4380: break;
1.1.1.5 root 4381: default:
4382: goto die;
4383: }
1.1.1.6 ! root 4384: /* Stop translation as we may have switched the execution mode */
! 4385: ctx->bstate = BS_STOP;
1.1.1.5 root 4386: break;
4387: default:
1.1.1.6 ! root 4388: goto die;
1.1.1.5 root 4389: }
4390: #if defined MIPS_DEBUG_DISAS
4391: if (loglevel & CPU_LOG_TB_IN_ASM) {
4392: fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4393: rn, reg, sel);
4394: }
4395: #endif
4396: return;
4397:
4398: die:
4399: #if defined MIPS_DEBUG_DISAS
4400: if (loglevel & CPU_LOG_TB_IN_ASM) {
4401: fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4402: rn, reg, sel);
4403: }
4404: #endif
4405: generate_exception(ctx, EXCP_RI);
4406: }
1.1.1.6 ! root 4407: #endif /* TARGET_MIPS64 */
1.1.1.5 root 4408:
1.1.1.6 ! root 4409: static void gen_mftr(CPUState *env, DisasContext *ctx, int rt,
! 4410: int u, int sel, int h)
1.1.1.5 root 4411: {
1.1.1.6 ! root 4412: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.5 root 4413:
1.1.1.6 ! root 4414: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
! 4415: ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) !=
! 4416: (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE))))
! 4417: gen_op_set_T0(-1);
! 4418: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
! 4419: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
! 4420: gen_op_set_T0(-1);
! 4421: else if (u == 0) {
! 4422: switch (rt) {
! 4423: case 2:
! 4424: switch (sel) {
! 4425: case 1:
! 4426: gen_op_mftc0_tcstatus();
! 4427: break;
! 4428: case 2:
! 4429: gen_op_mftc0_tcbind();
! 4430: break;
! 4431: case 3:
! 4432: gen_op_mftc0_tcrestart();
! 4433: break;
! 4434: case 4:
! 4435: gen_op_mftc0_tchalt();
! 4436: break;
! 4437: case 5:
! 4438: gen_op_mftc0_tccontext();
! 4439: break;
! 4440: case 6:
! 4441: gen_op_mftc0_tcschedule();
! 4442: break;
! 4443: case 7:
! 4444: gen_op_mftc0_tcschefback();
! 4445: break;
! 4446: default:
! 4447: gen_mfc0(env, ctx, rt, sel);
! 4448: break;
! 4449: }
! 4450: break;
! 4451: case 10:
! 4452: switch (sel) {
! 4453: case 0:
! 4454: gen_op_mftc0_entryhi();
! 4455: break;
! 4456: default:
! 4457: gen_mfc0(env, ctx, rt, sel);
! 4458: break;
! 4459: }
! 4460: case 12:
! 4461: switch (sel) {
! 4462: case 0:
! 4463: gen_op_mftc0_status();
! 4464: break;
! 4465: default:
! 4466: gen_mfc0(env, ctx, rt, sel);
! 4467: break;
! 4468: }
! 4469: case 23:
! 4470: switch (sel) {
! 4471: case 0:
! 4472: gen_op_mftc0_debug();
! 4473: break;
! 4474: default:
! 4475: gen_mfc0(env, ctx, rt, sel);
! 4476: break;
! 4477: }
! 4478: break;
! 4479: default:
! 4480: gen_mfc0(env, ctx, rt, sel);
! 4481: }
! 4482: } else switch (sel) {
! 4483: /* GPR registers. */
! 4484: case 0:
! 4485: gen_op_mftgpr(rt);
! 4486: break;
! 4487: /* Auxiliary CPU registers */
! 4488: case 1:
! 4489: switch (rt) {
! 4490: case 0:
! 4491: gen_op_mftlo(0);
! 4492: break;
! 4493: case 1:
! 4494: gen_op_mfthi(0);
! 4495: break;
! 4496: case 2:
! 4497: gen_op_mftacx(0);
! 4498: break;
! 4499: case 4:
! 4500: gen_op_mftlo(1);
! 4501: break;
! 4502: case 5:
! 4503: gen_op_mfthi(1);
! 4504: break;
! 4505: case 6:
! 4506: gen_op_mftacx(1);
! 4507: break;
! 4508: case 8:
! 4509: gen_op_mftlo(2);
! 4510: break;
! 4511: case 9:
! 4512: gen_op_mfthi(2);
! 4513: break;
! 4514: case 10:
! 4515: gen_op_mftacx(2);
! 4516: break;
! 4517: case 12:
! 4518: gen_op_mftlo(3);
! 4519: break;
! 4520: case 13:
! 4521: gen_op_mfthi(3);
! 4522: break;
! 4523: case 14:
! 4524: gen_op_mftacx(3);
! 4525: break;
! 4526: case 16:
! 4527: gen_op_mftdsp();
! 4528: break;
! 4529: default:
! 4530: goto die;
! 4531: }
! 4532: break;
! 4533: /* Floating point (COP1). */
! 4534: case 2:
! 4535: /* XXX: For now we support only a single FPU context. */
! 4536: if (h == 0) {
! 4537: GEN_LOAD_FREG_FTN(WT0, rt);
! 4538: gen_op_mfc1();
! 4539: } else {
! 4540: GEN_LOAD_FREG_FTN(WTH0, rt);
! 4541: gen_op_mfhc1();
! 4542: }
! 4543: break;
! 4544: case 3:
! 4545: /* XXX: For now we support only a single FPU context. */
! 4546: gen_op_cfc1(rt);
! 4547: break;
! 4548: /* COP2: Not implemented. */
! 4549: case 4:
! 4550: case 5:
! 4551: /* fall through */
! 4552: default:
! 4553: goto die;
! 4554: }
! 4555: #if defined MIPS_DEBUG_DISAS
! 4556: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 4557: fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
! 4558: rt, u, sel, h);
! 4559: }
! 4560: #endif
! 4561: return;
! 4562:
! 4563: die:
! 4564: #if defined MIPS_DEBUG_DISAS
! 4565: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 4566: fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
! 4567: rt, u, sel, h);
! 4568: }
! 4569: #endif
! 4570: generate_exception(ctx, EXCP_RI);
! 4571: }
! 4572:
! 4573: static void gen_mttr(CPUState *env, DisasContext *ctx, int rd,
! 4574: int u, int sel, int h)
! 4575: {
! 4576: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 4577:
! 4578: if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
! 4579: ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) !=
! 4580: (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE))))
! 4581: /* NOP */ ;
! 4582: else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
! 4583: (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
! 4584: /* NOP */ ;
! 4585: else if (u == 0) {
! 4586: switch (rd) {
! 4587: case 2:
! 4588: switch (sel) {
! 4589: case 1:
! 4590: gen_op_mttc0_tcstatus();
! 4591: break;
! 4592: case 2:
! 4593: gen_op_mttc0_tcbind();
! 4594: break;
! 4595: case 3:
! 4596: gen_op_mttc0_tcrestart();
! 4597: break;
! 4598: case 4:
! 4599: gen_op_mttc0_tchalt();
! 4600: break;
! 4601: case 5:
! 4602: gen_op_mttc0_tccontext();
! 4603: break;
! 4604: case 6:
! 4605: gen_op_mttc0_tcschedule();
! 4606: break;
! 4607: case 7:
! 4608: gen_op_mttc0_tcschefback();
! 4609: break;
! 4610: default:
! 4611: gen_mtc0(env, ctx, rd, sel);
! 4612: break;
! 4613: }
! 4614: break;
! 4615: case 10:
! 4616: switch (sel) {
! 4617: case 0:
! 4618: gen_op_mttc0_entryhi();
! 4619: break;
! 4620: default:
! 4621: gen_mtc0(env, ctx, rd, sel);
! 4622: break;
! 4623: }
! 4624: case 12:
! 4625: switch (sel) {
! 4626: case 0:
! 4627: gen_op_mttc0_status();
! 4628: break;
! 4629: default:
! 4630: gen_mtc0(env, ctx, rd, sel);
! 4631: break;
! 4632: }
! 4633: case 23:
! 4634: switch (sel) {
! 4635: case 0:
! 4636: gen_op_mttc0_debug();
! 4637: break;
! 4638: default:
! 4639: gen_mtc0(env, ctx, rd, sel);
! 4640: break;
! 4641: }
! 4642: break;
! 4643: default:
! 4644: gen_mtc0(env, ctx, rd, sel);
! 4645: }
! 4646: } else switch (sel) {
! 4647: /* GPR registers. */
! 4648: case 0:
! 4649: gen_op_mttgpr(rd);
! 4650: break;
! 4651: /* Auxiliary CPU registers */
! 4652: case 1:
! 4653: switch (rd) {
! 4654: case 0:
! 4655: gen_op_mttlo(0);
! 4656: break;
! 4657: case 1:
! 4658: gen_op_mtthi(0);
! 4659: break;
! 4660: case 2:
! 4661: gen_op_mttacx(0);
! 4662: break;
! 4663: case 4:
! 4664: gen_op_mttlo(1);
! 4665: break;
! 4666: case 5:
! 4667: gen_op_mtthi(1);
! 4668: break;
! 4669: case 6:
! 4670: gen_op_mttacx(1);
! 4671: break;
! 4672: case 8:
! 4673: gen_op_mttlo(2);
! 4674: break;
! 4675: case 9:
! 4676: gen_op_mtthi(2);
! 4677: break;
! 4678: case 10:
! 4679: gen_op_mttacx(2);
! 4680: break;
! 4681: case 12:
! 4682: gen_op_mttlo(3);
! 4683: break;
! 4684: case 13:
! 4685: gen_op_mtthi(3);
! 4686: break;
! 4687: case 14:
! 4688: gen_op_mttacx(3);
! 4689: break;
! 4690: case 16:
! 4691: gen_op_mttdsp();
! 4692: break;
! 4693: default:
! 4694: goto die;
! 4695: }
! 4696: break;
! 4697: /* Floating point (COP1). */
! 4698: case 2:
! 4699: /* XXX: For now we support only a single FPU context. */
! 4700: if (h == 0) {
! 4701: gen_op_mtc1();
! 4702: GEN_STORE_FTN_FREG(rd, WT0);
! 4703: } else {
! 4704: gen_op_mthc1();
! 4705: GEN_STORE_FTN_FREG(rd, WTH0);
! 4706: }
! 4707: break;
! 4708: case 3:
! 4709: /* XXX: For now we support only a single FPU context. */
! 4710: gen_op_ctc1(rd);
! 4711: break;
! 4712: /* COP2: Not implemented. */
! 4713: case 4:
! 4714: case 5:
! 4715: /* fall through */
! 4716: default:
! 4717: goto die;
! 4718: }
! 4719: #if defined MIPS_DEBUG_DISAS
! 4720: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 4721: fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
! 4722: rd, u, sel, h);
1.1.1.5 root 4723: }
1.1.1.6 ! root 4724: #endif
! 4725: return;
! 4726:
! 4727: die:
! 4728: #if defined MIPS_DEBUG_DISAS
! 4729: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 4730: fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
! 4731: rd, u, sel, h);
! 4732: }
! 4733: #endif
! 4734: generate_exception(ctx, EXCP_RI);
! 4735: }
! 4736:
! 4737: static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
! 4738: {
! 4739: const char *opn = "ldst";
1.1.1.5 root 4740:
4741: switch (opc) {
4742: case OPC_MFC0:
4743: if (rt == 0) {
1.1.1.6 ! root 4744: /* Treat as NOP. */
1.1.1.5 root 4745: return;
4746: }
1.1.1.6 ! root 4747: gen_mfc0(env, ctx, rd, ctx->opcode & 0x7);
1.1.1.5 root 4748: gen_op_store_T0_gpr(rt);
4749: opn = "mfc0";
4750: break;
4751: case OPC_MTC0:
1.1.1.6 ! root 4752: GEN_LOAD_REG_T0(rt);
1.1.1.5 root 4753: save_cpu_state(ctx, 1);
1.1.1.6 ! root 4754: gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
1.1.1.5 root 4755: opn = "mtc0";
4756: break;
1.1.1.6 ! root 4757: #if defined(TARGET_MIPS64)
1.1.1.5 root 4758: case OPC_DMFC0:
1.1.1.6 ! root 4759: check_insn(env, ctx, ISA_MIPS3);
1.1.1.5 root 4760: if (rt == 0) {
1.1.1.6 ! root 4761: /* Treat as NOP. */
1.1.1.5 root 4762: return;
4763: }
1.1.1.6 ! root 4764: gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7);
1.1.1.5 root 4765: gen_op_store_T0_gpr(rt);
4766: opn = "dmfc0";
4767: break;
4768: case OPC_DMTC0:
1.1.1.6 ! root 4769: check_insn(env, ctx, ISA_MIPS3);
! 4770: GEN_LOAD_REG_T0(rt);
1.1.1.5 root 4771: save_cpu_state(ctx, 1);
1.1.1.6 ! root 4772: gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
1.1.1.5 root 4773: opn = "dmtc0";
4774: break;
1.1.1.6 ! root 4775: #endif
! 4776: case OPC_MFTR:
! 4777: check_insn(env, ctx, ASE_MT);
! 4778: if (rd == 0) {
! 4779: /* Treat as NOP. */
! 4780: return;
! 4781: }
! 4782: gen_mftr(env, ctx, rt, (ctx->opcode >> 5) & 1,
! 4783: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
! 4784: gen_op_store_T0_gpr(rd);
! 4785: opn = "mftr";
! 4786: break;
! 4787: case OPC_MTTR:
! 4788: check_insn(env, ctx, ASE_MT);
! 4789: GEN_LOAD_REG_T0(rt);
! 4790: gen_mttr(env, ctx, rd, (ctx->opcode >> 5) & 1,
! 4791: ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
! 4792: opn = "mttr";
! 4793: break;
1.1.1.5 root 4794: case OPC_TLBWI:
4795: opn = "tlbwi";
1.1.1.6 ! root 4796: if (!env->tlb->do_tlbwi)
! 4797: goto die;
! 4798: gen_op_tlbwi();
1.1.1.5 root 4799: break;
4800: case OPC_TLBWR:
4801: opn = "tlbwr";
1.1.1.6 ! root 4802: if (!env->tlb->do_tlbwr)
! 4803: goto die;
! 4804: gen_op_tlbwr();
1.1.1.5 root 4805: break;
4806: case OPC_TLBP:
4807: opn = "tlbp";
1.1.1.6 ! root 4808: if (!env->tlb->do_tlbp)
! 4809: goto die;
! 4810: gen_op_tlbp();
1.1.1.5 root 4811: break;
4812: case OPC_TLBR:
4813: opn = "tlbr";
1.1.1.6 ! root 4814: if (!env->tlb->do_tlbr)
! 4815: goto die;
! 4816: gen_op_tlbr();
1.1.1.5 root 4817: break;
4818: case OPC_ERET:
4819: opn = "eret";
1.1.1.6 ! root 4820: check_insn(env, ctx, ISA_MIPS2);
! 4821: save_cpu_state(ctx, 1);
1.1.1.5 root 4822: gen_op_eret();
4823: ctx->bstate = BS_EXCP;
4824: break;
4825: case OPC_DERET:
4826: opn = "deret";
1.1.1.6 ! root 4827: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 4828: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1.1.1.6 ! root 4829: MIPS_INVAL(opn);
1.1.1.5 root 4830: generate_exception(ctx, EXCP_RI);
4831: } else {
1.1.1.6 ! root 4832: save_cpu_state(ctx, 1);
1.1.1.5 root 4833: gen_op_deret();
4834: ctx->bstate = BS_EXCP;
4835: }
4836: break;
4837: case OPC_WAIT:
4838: opn = "wait";
1.1.1.6 ! root 4839: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
1.1.1.5 root 4840: /* If we get an exception, we want to restart at next instruction */
4841: ctx->pc += 4;
4842: save_cpu_state(ctx, 1);
4843: ctx->pc -= 4;
4844: gen_op_wait();
4845: ctx->bstate = BS_EXCP;
4846: break;
4847: default:
1.1.1.6 ! root 4848: die:
! 4849: MIPS_INVAL(opn);
1.1.1.5 root 4850: generate_exception(ctx, EXCP_RI);
4851: return;
4852: }
4853: MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
4854: }
4855:
4856: /* CP1 Branches (before delay slot) */
1.1.1.6 ! root 4857: static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
! 4858: int32_t cc, int32_t offset)
1.1.1.5 root 4859: {
4860: target_ulong btarget;
1.1.1.6 ! root 4861: const char *opn = "cp1 cond branch";
! 4862:
! 4863: if (cc != 0)
! 4864: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
1.1.1.5 root 4865:
4866: btarget = ctx->pc + 4 + offset;
4867:
4868: switch (op) {
4869: case OPC_BC1F:
1.1.1.6 ! root 4870: gen_op_bc1f(cc);
! 4871: opn = "bc1f";
1.1.1.5 root 4872: goto not_likely;
4873: case OPC_BC1FL:
1.1.1.6 ! root 4874: gen_op_bc1f(cc);
! 4875: opn = "bc1fl";
1.1.1.5 root 4876: goto likely;
4877: case OPC_BC1T:
1.1.1.6 ! root 4878: gen_op_bc1t(cc);
! 4879: opn = "bc1t";
! 4880: goto not_likely;
1.1.1.5 root 4881: case OPC_BC1TL:
1.1.1.6 ! root 4882: gen_op_bc1t(cc);
! 4883: opn = "bc1tl";
1.1.1.5 root 4884: likely:
4885: ctx->hflags |= MIPS_HFLAG_BL;
1.1.1.6 ! root 4886: gen_op_set_bcond();
! 4887: gen_op_save_bcond();
! 4888: break;
! 4889: case OPC_BC1FANY2:
! 4890: gen_op_bc1any2f(cc);
! 4891: opn = "bc1any2f";
! 4892: goto not_likely;
! 4893: case OPC_BC1TANY2:
! 4894: gen_op_bc1any2t(cc);
! 4895: opn = "bc1any2t";
! 4896: goto not_likely;
! 4897: case OPC_BC1FANY4:
! 4898: gen_op_bc1any4f(cc);
! 4899: opn = "bc1any4f";
! 4900: goto not_likely;
! 4901: case OPC_BC1TANY4:
! 4902: gen_op_bc1any4t(cc);
! 4903: opn = "bc1any4t";
! 4904: not_likely:
! 4905: ctx->hflags |= MIPS_HFLAG_BC;
! 4906: gen_op_set_bcond();
1.1.1.5 root 4907: break;
1.1.1.6 ! root 4908: default:
! 4909: MIPS_INVAL(opn);
! 4910: generate_exception (ctx, EXCP_RI);
1.1.1.5 root 4911: return;
4912: }
1.1.1.6 ! root 4913: MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
1.1.1.5 root 4914: ctx->hflags, btarget);
4915: ctx->btarget = btarget;
4916: }
4917:
4918: /* Coprocessor 1 (FPU) */
1.1.1.6 ! root 4919:
! 4920: #define FOP(func, fmt) (((fmt) << 21) | (func))
! 4921:
1.1.1.5 root 4922: static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4923: {
1.1.1.6 ! root 4924: const char *opn = "cp1 move";
1.1.1.5 root 4925:
4926: switch (opc) {
4927: case OPC_MFC1:
4928: GEN_LOAD_FREG_FTN(WT0, fs);
4929: gen_op_mfc1();
1.1.1.6 ! root 4930: GEN_STORE_T0_REG(rt);
1.1.1.5 root 4931: opn = "mfc1";
4932: break;
4933: case OPC_MTC1:
1.1.1.6 ! root 4934: GEN_LOAD_REG_T0(rt);
1.1.1.5 root 4935: gen_op_mtc1();
4936: GEN_STORE_FTN_FREG(fs, WT0);
4937: opn = "mtc1";
4938: break;
4939: case OPC_CFC1:
1.1.1.6 ! root 4940: gen_op_cfc1(fs);
! 4941: GEN_STORE_T0_REG(rt);
1.1.1.5 root 4942: opn = "cfc1";
4943: break;
4944: case OPC_CTC1:
1.1.1.6 ! root 4945: GEN_LOAD_REG_T0(rt);
! 4946: gen_op_ctc1(fs);
1.1.1.5 root 4947: opn = "ctc1";
4948: break;
4949: case OPC_DMFC1:
1.1.1.6 ! root 4950: GEN_LOAD_FREG_FTN(DT0, fs);
! 4951: gen_op_dmfc1();
! 4952: GEN_STORE_T0_REG(rt);
! 4953: opn = "dmfc1";
! 4954: break;
1.1.1.5 root 4955: case OPC_DMTC1:
1.1.1.6 ! root 4956: GEN_LOAD_REG_T0(rt);
! 4957: gen_op_dmtc1();
! 4958: GEN_STORE_FTN_FREG(fs, DT0);
! 4959: opn = "dmtc1";
! 4960: break;
! 4961: case OPC_MFHC1:
! 4962: GEN_LOAD_FREG_FTN(WTH0, fs);
! 4963: gen_op_mfhc1();
! 4964: GEN_STORE_T0_REG(rt);
! 4965: opn = "mfhc1";
! 4966: break;
! 4967: case OPC_MTHC1:
! 4968: GEN_LOAD_REG_T0(rt);
! 4969: gen_op_mthc1();
! 4970: GEN_STORE_FTN_FREG(fs, WTH0);
! 4971: opn = "mthc1";
! 4972: break;
1.1.1.5 root 4973: default:
1.1.1.6 ! root 4974: MIPS_INVAL(opn);
! 4975: generate_exception (ctx, EXCP_RI);
1.1.1.4 root 4976: return;
4977: }
4978: MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
4979: }
4980:
1.1.1.6 ! root 4981: static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
! 4982: {
! 4983: uint32_t ccbit;
1.1.1.4 root 4984:
1.1.1.6 ! root 4985: GEN_LOAD_REG_T0(rd);
! 4986: GEN_LOAD_REG_T1(rs);
! 4987: if (cc) {
! 4988: ccbit = 1 << (24 + cc);
! 4989: } else
! 4990: ccbit = 1 << 23;
! 4991: if (!tf)
! 4992: gen_op_movf(ccbit);
! 4993: else
! 4994: gen_op_movt(ccbit);
! 4995: GEN_STORE_T0_REG(rd);
! 4996: }
! 4997:
! 4998: #define GEN_MOVCF(fmt) \
! 4999: static void glue(gen_movcf_, fmt) (DisasContext *ctx, int cc, int tf) \
! 5000: { \
! 5001: uint32_t ccbit; \
! 5002: \
! 5003: if (cc) { \
! 5004: ccbit = 1 << (24 + cc); \
! 5005: } else \
! 5006: ccbit = 1 << 23; \
! 5007: if (!tf) \
! 5008: glue(gen_op_float_movf_, fmt)(ccbit); \
! 5009: else \
! 5010: glue(gen_op_float_movt_, fmt)(ccbit); \
! 5011: }
! 5012: GEN_MOVCF(d);
! 5013: GEN_MOVCF(s);
! 5014: GEN_MOVCF(ps);
! 5015: #undef GEN_MOVCF
1.1.1.4 root 5016:
1.1.1.6 ! root 5017: static void gen_farith (DisasContext *ctx, uint32_t op1,
! 5018: int ft, int fs, int fd, int cc)
1.1.1.4 root 5019: {
1.1.1.6 ! root 5020: const char *opn = "farith";
1.1.1.4 root 5021: const char *condnames[] = {
5022: "c.f",
5023: "c.un",
5024: "c.eq",
5025: "c.ueq",
5026: "c.olt",
5027: "c.ult",
5028: "c.ole",
5029: "c.ule",
5030: "c.sf",
5031: "c.ngle",
5032: "c.seq",
5033: "c.ngl",
5034: "c.lt",
5035: "c.nge",
5036: "c.le",
5037: "c.ngt",
5038: };
1.1.1.6 ! root 5039: const char *condnames_abs[] = {
! 5040: "cabs.f",
! 5041: "cabs.un",
! 5042: "cabs.eq",
! 5043: "cabs.ueq",
! 5044: "cabs.olt",
! 5045: "cabs.ult",
! 5046: "cabs.ole",
! 5047: "cabs.ule",
! 5048: "cabs.sf",
! 5049: "cabs.ngle",
! 5050: "cabs.seq",
! 5051: "cabs.ngl",
! 5052: "cabs.lt",
! 5053: "cabs.nge",
! 5054: "cabs.le",
! 5055: "cabs.ngt",
! 5056: };
! 5057: enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
1.1.1.5 root 5058: uint32_t func = ctx->opcode & 0x3f;
5059:
1.1.1.4 root 5060: switch (ctx->opcode & FOP(0x3f, 0x1f)) {
1.1.1.6 ! root 5061: case FOP(0, 16):
! 5062: GEN_LOAD_FREG_FTN(WT0, fs);
! 5063: GEN_LOAD_FREG_FTN(WT1, ft);
! 5064: gen_op_float_add_s();
! 5065: GEN_STORE_FTN_FREG(fd, WT2);
! 5066: opn = "add.s";
! 5067: optype = BINOP;
! 5068: break;
! 5069: case FOP(1, 16):
! 5070: GEN_LOAD_FREG_FTN(WT0, fs);
! 5071: GEN_LOAD_FREG_FTN(WT1, ft);
! 5072: gen_op_float_sub_s();
! 5073: GEN_STORE_FTN_FREG(fd, WT2);
! 5074: opn = "sub.s";
! 5075: optype = BINOP;
! 5076: break;
! 5077: case FOP(2, 16):
! 5078: GEN_LOAD_FREG_FTN(WT0, fs);
! 5079: GEN_LOAD_FREG_FTN(WT1, ft);
! 5080: gen_op_float_mul_s();
! 5081: GEN_STORE_FTN_FREG(fd, WT2);
! 5082: opn = "mul.s";
! 5083: optype = BINOP;
! 5084: break;
! 5085: case FOP(3, 16):
! 5086: GEN_LOAD_FREG_FTN(WT0, fs);
! 5087: GEN_LOAD_FREG_FTN(WT1, ft);
! 5088: gen_op_float_div_s();
! 5089: GEN_STORE_FTN_FREG(fd, WT2);
! 5090: opn = "div.s";
! 5091: optype = BINOP;
! 5092: break;
! 5093: case FOP(4, 16):
! 5094: GEN_LOAD_FREG_FTN(WT0, fs);
! 5095: gen_op_float_sqrt_s();
! 5096: GEN_STORE_FTN_FREG(fd, WT2);
! 5097: opn = "sqrt.s";
! 5098: break;
! 5099: case FOP(5, 16):
! 5100: GEN_LOAD_FREG_FTN(WT0, fs);
! 5101: gen_op_float_abs_s();
! 5102: GEN_STORE_FTN_FREG(fd, WT2);
! 5103: opn = "abs.s";
! 5104: break;
! 5105: case FOP(6, 16):
! 5106: GEN_LOAD_FREG_FTN(WT0, fs);
! 5107: gen_op_float_mov_s();
! 5108: GEN_STORE_FTN_FREG(fd, WT2);
! 5109: opn = "mov.s";
! 5110: break;
! 5111: case FOP(7, 16):
! 5112: GEN_LOAD_FREG_FTN(WT0, fs);
! 5113: gen_op_float_chs_s();
! 5114: GEN_STORE_FTN_FREG(fd, WT2);
! 5115: opn = "neg.s";
! 5116: break;
! 5117: case FOP(8, 16):
! 5118: check_cp1_64bitmode(ctx);
! 5119: GEN_LOAD_FREG_FTN(WT0, fs);
! 5120: gen_op_float_roundl_s();
! 5121: GEN_STORE_FTN_FREG(fd, DT2);
! 5122: opn = "round.l.s";
! 5123: break;
! 5124: case FOP(9, 16):
! 5125: check_cp1_64bitmode(ctx);
! 5126: GEN_LOAD_FREG_FTN(WT0, fs);
! 5127: gen_op_float_truncl_s();
! 5128: GEN_STORE_FTN_FREG(fd, DT2);
! 5129: opn = "trunc.l.s";
! 5130: break;
! 5131: case FOP(10, 16):
! 5132: check_cp1_64bitmode(ctx);
! 5133: GEN_LOAD_FREG_FTN(WT0, fs);
! 5134: gen_op_float_ceill_s();
! 5135: GEN_STORE_FTN_FREG(fd, DT2);
! 5136: opn = "ceil.l.s";
! 5137: break;
! 5138: case FOP(11, 16):
! 5139: check_cp1_64bitmode(ctx);
! 5140: GEN_LOAD_FREG_FTN(WT0, fs);
! 5141: gen_op_float_floorl_s();
! 5142: GEN_STORE_FTN_FREG(fd, DT2);
! 5143: opn = "floor.l.s";
! 5144: break;
! 5145: case FOP(12, 16):
! 5146: GEN_LOAD_FREG_FTN(WT0, fs);
! 5147: gen_op_float_roundw_s();
! 5148: GEN_STORE_FTN_FREG(fd, WT2);
! 5149: opn = "round.w.s";
! 5150: break;
! 5151: case FOP(13, 16):
! 5152: GEN_LOAD_FREG_FTN(WT0, fs);
! 5153: gen_op_float_truncw_s();
! 5154: GEN_STORE_FTN_FREG(fd, WT2);
! 5155: opn = "trunc.w.s";
! 5156: break;
! 5157: case FOP(14, 16):
! 5158: GEN_LOAD_FREG_FTN(WT0, fs);
! 5159: gen_op_float_ceilw_s();
! 5160: GEN_STORE_FTN_FREG(fd, WT2);
! 5161: opn = "ceil.w.s";
! 5162: break;
! 5163: case FOP(15, 16):
! 5164: GEN_LOAD_FREG_FTN(WT0, fs);
! 5165: gen_op_float_floorw_s();
! 5166: GEN_STORE_FTN_FREG(fd, WT2);
! 5167: opn = "floor.w.s";
! 5168: break;
! 5169: case FOP(17, 16):
! 5170: GEN_LOAD_REG_T0(ft);
! 5171: GEN_LOAD_FREG_FTN(WT0, fs);
! 5172: GEN_LOAD_FREG_FTN(WT2, fd);
! 5173: gen_movcf_s(ctx, (ft >> 2) & 0x7, ft & 0x1);
! 5174: GEN_STORE_FTN_FREG(fd, WT2);
! 5175: opn = "movcf.s";
! 5176: break;
! 5177: case FOP(18, 16):
! 5178: GEN_LOAD_REG_T0(ft);
! 5179: GEN_LOAD_FREG_FTN(WT0, fs);
! 5180: GEN_LOAD_FREG_FTN(WT2, fd);
! 5181: gen_op_float_movz_s();
! 5182: GEN_STORE_FTN_FREG(fd, WT2);
! 5183: opn = "movz.s";
! 5184: break;
! 5185: case FOP(19, 16):
! 5186: GEN_LOAD_REG_T0(ft);
! 5187: GEN_LOAD_FREG_FTN(WT0, fs);
! 5188: GEN_LOAD_FREG_FTN(WT2, fd);
! 5189: gen_op_float_movn_s();
! 5190: GEN_STORE_FTN_FREG(fd, WT2);
! 5191: opn = "movn.s";
! 5192: break;
! 5193: case FOP(21, 16):
! 5194: check_cop1x(ctx);
! 5195: GEN_LOAD_FREG_FTN(WT0, fs);
! 5196: gen_op_float_recip_s();
! 5197: GEN_STORE_FTN_FREG(fd, WT2);
! 5198: opn = "recip.s";
! 5199: break;
! 5200: case FOP(22, 16):
! 5201: check_cop1x(ctx);
! 5202: GEN_LOAD_FREG_FTN(WT0, fs);
! 5203: gen_op_float_rsqrt_s();
! 5204: GEN_STORE_FTN_FREG(fd, WT2);
! 5205: opn = "rsqrt.s";
! 5206: break;
! 5207: case FOP(28, 16):
! 5208: check_cp1_64bitmode(ctx);
! 5209: GEN_LOAD_FREG_FTN(WT0, fs);
! 5210: GEN_LOAD_FREG_FTN(WT2, fd);
! 5211: gen_op_float_recip2_s();
! 5212: GEN_STORE_FTN_FREG(fd, WT2);
! 5213: opn = "recip2.s";
! 5214: break;
! 5215: case FOP(29, 16):
! 5216: check_cp1_64bitmode(ctx);
! 5217: GEN_LOAD_FREG_FTN(WT0, fs);
! 5218: gen_op_float_recip1_s();
! 5219: GEN_STORE_FTN_FREG(fd, WT2);
! 5220: opn = "recip1.s";
! 5221: break;
! 5222: case FOP(30, 16):
! 5223: check_cp1_64bitmode(ctx);
! 5224: GEN_LOAD_FREG_FTN(WT0, fs);
! 5225: gen_op_float_rsqrt1_s();
! 5226: GEN_STORE_FTN_FREG(fd, WT2);
! 5227: opn = "rsqrt1.s";
! 5228: break;
! 5229: case FOP(31, 16):
! 5230: check_cp1_64bitmode(ctx);
! 5231: GEN_LOAD_FREG_FTN(WT0, fs);
! 5232: GEN_LOAD_FREG_FTN(WT2, ft);
! 5233: gen_op_float_rsqrt2_s();
! 5234: GEN_STORE_FTN_FREG(fd, WT2);
! 5235: opn = "rsqrt2.s";
! 5236: break;
! 5237: case FOP(33, 16):
! 5238: check_cp1_registers(ctx, fd);
! 5239: GEN_LOAD_FREG_FTN(WT0, fs);
! 5240: gen_op_float_cvtd_s();
! 5241: GEN_STORE_FTN_FREG(fd, DT2);
! 5242: opn = "cvt.d.s";
! 5243: break;
! 5244: case FOP(36, 16):
! 5245: GEN_LOAD_FREG_FTN(WT0, fs);
! 5246: gen_op_float_cvtw_s();
! 5247: GEN_STORE_FTN_FREG(fd, WT2);
! 5248: opn = "cvt.w.s";
! 5249: break;
! 5250: case FOP(37, 16):
! 5251: check_cp1_64bitmode(ctx);
! 5252: GEN_LOAD_FREG_FTN(WT0, fs);
! 5253: gen_op_float_cvtl_s();
! 5254: GEN_STORE_FTN_FREG(fd, DT2);
! 5255: opn = "cvt.l.s";
! 5256: break;
! 5257: case FOP(38, 16):
! 5258: check_cp1_64bitmode(ctx);
! 5259: GEN_LOAD_FREG_FTN(WT1, fs);
! 5260: GEN_LOAD_FREG_FTN(WT0, ft);
! 5261: gen_op_float_cvtps_s();
! 5262: GEN_STORE_FTN_FREG(fd, DT2);
! 5263: opn = "cvt.ps.s";
! 5264: break;
! 5265: case FOP(48, 16):
! 5266: case FOP(49, 16):
! 5267: case FOP(50, 16):
! 5268: case FOP(51, 16):
! 5269: case FOP(52, 16):
! 5270: case FOP(53, 16):
! 5271: case FOP(54, 16):
! 5272: case FOP(55, 16):
! 5273: case FOP(56, 16):
! 5274: case FOP(57, 16):
! 5275: case FOP(58, 16):
! 5276: case FOP(59, 16):
! 5277: case FOP(60, 16):
! 5278: case FOP(61, 16):
! 5279: case FOP(62, 16):
! 5280: case FOP(63, 16):
! 5281: GEN_LOAD_FREG_FTN(WT0, fs);
! 5282: GEN_LOAD_FREG_FTN(WT1, ft);
! 5283: if (ctx->opcode & (1 << 6)) {
! 5284: check_cop1x(ctx);
! 5285: gen_cmpabs_s(func-48, cc);
! 5286: opn = condnames_abs[func-48];
! 5287: } else {
! 5288: gen_cmp_s(func-48, cc);
! 5289: opn = condnames[func-48];
! 5290: }
! 5291: break;
1.1.1.4 root 5292: case FOP(0, 17):
1.1.1.6 ! root 5293: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.4 root 5294: GEN_LOAD_FREG_FTN(DT0, fs);
5295: GEN_LOAD_FREG_FTN(DT1, ft);
5296: gen_op_float_add_d();
5297: GEN_STORE_FTN_FREG(fd, DT2);
5298: opn = "add.d";
1.1.1.6 ! root 5299: optype = BINOP;
1.1.1.4 root 5300: break;
5301: case FOP(1, 17):
1.1.1.6 ! root 5302: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.4 root 5303: GEN_LOAD_FREG_FTN(DT0, fs);
5304: GEN_LOAD_FREG_FTN(DT1, ft);
5305: gen_op_float_sub_d();
5306: GEN_STORE_FTN_FREG(fd, DT2);
5307: opn = "sub.d";
1.1.1.6 ! root 5308: optype = BINOP;
1.1.1.4 root 5309: break;
5310: case FOP(2, 17):
1.1.1.6 ! root 5311: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.4 root 5312: GEN_LOAD_FREG_FTN(DT0, fs);
5313: GEN_LOAD_FREG_FTN(DT1, ft);
5314: gen_op_float_mul_d();
5315: GEN_STORE_FTN_FREG(fd, DT2);
5316: opn = "mul.d";
1.1.1.6 ! root 5317: optype = BINOP;
1.1.1.4 root 5318: break;
5319: case FOP(3, 17):
1.1.1.6 ! root 5320: check_cp1_registers(ctx, fs | ft | fd);
1.1.1.4 root 5321: GEN_LOAD_FREG_FTN(DT0, fs);
5322: GEN_LOAD_FREG_FTN(DT1, ft);
5323: gen_op_float_div_d();
5324: GEN_STORE_FTN_FREG(fd, DT2);
5325: opn = "div.d";
1.1.1.6 ! root 5326: optype = BINOP;
1.1.1.4 root 5327: break;
5328: case FOP(4, 17):
1.1.1.6 ! root 5329: check_cp1_registers(ctx, fs | fd);
1.1.1.4 root 5330: GEN_LOAD_FREG_FTN(DT0, fs);
5331: gen_op_float_sqrt_d();
5332: GEN_STORE_FTN_FREG(fd, DT2);
5333: opn = "sqrt.d";
5334: break;
5335: case FOP(5, 17):
1.1.1.6 ! root 5336: check_cp1_registers(ctx, fs | fd);
1.1.1.4 root 5337: GEN_LOAD_FREG_FTN(DT0, fs);
5338: gen_op_float_abs_d();
5339: GEN_STORE_FTN_FREG(fd, DT2);
5340: opn = "abs.d";
5341: break;
5342: case FOP(6, 17):
1.1.1.6 ! root 5343: check_cp1_registers(ctx, fs | fd);
1.1.1.4 root 5344: GEN_LOAD_FREG_FTN(DT0, fs);
5345: gen_op_float_mov_d();
5346: GEN_STORE_FTN_FREG(fd, DT2);
5347: opn = "mov.d";
5348: break;
5349: case FOP(7, 17):
1.1.1.6 ! root 5350: check_cp1_registers(ctx, fs | fd);
1.1.1.4 root 5351: GEN_LOAD_FREG_FTN(DT0, fs);
5352: gen_op_float_chs_d();
5353: GEN_STORE_FTN_FREG(fd, DT2);
5354: opn = "neg.d";
5355: break;
1.1.1.6 ! root 5356: case FOP(8, 17):
! 5357: check_cp1_64bitmode(ctx);
! 5358: GEN_LOAD_FREG_FTN(DT0, fs);
! 5359: gen_op_float_roundl_d();
! 5360: GEN_STORE_FTN_FREG(fd, DT2);
! 5361: opn = "round.l.d";
! 5362: break;
! 5363: case FOP(9, 17):
! 5364: check_cp1_64bitmode(ctx);
! 5365: GEN_LOAD_FREG_FTN(DT0, fs);
! 5366: gen_op_float_truncl_d();
! 5367: GEN_STORE_FTN_FREG(fd, DT2);
! 5368: opn = "trunc.l.d";
! 5369: break;
! 5370: case FOP(10, 17):
! 5371: check_cp1_64bitmode(ctx);
! 5372: GEN_LOAD_FREG_FTN(DT0, fs);
! 5373: gen_op_float_ceill_d();
! 5374: GEN_STORE_FTN_FREG(fd, DT2);
! 5375: opn = "ceil.l.d";
! 5376: break;
! 5377: case FOP(11, 17):
! 5378: check_cp1_64bitmode(ctx);
! 5379: GEN_LOAD_FREG_FTN(DT0, fs);
! 5380: gen_op_float_floorl_d();
! 5381: GEN_STORE_FTN_FREG(fd, DT2);
! 5382: opn = "floor.l.d";
! 5383: break;
1.1.1.4 root 5384: case FOP(12, 17):
1.1.1.6 ! root 5385: check_cp1_registers(ctx, fs);
1.1.1.4 root 5386: GEN_LOAD_FREG_FTN(DT0, fs);
5387: gen_op_float_roundw_d();
5388: GEN_STORE_FTN_FREG(fd, WT2);
5389: opn = "round.w.d";
5390: break;
5391: case FOP(13, 17):
1.1.1.6 ! root 5392: check_cp1_registers(ctx, fs);
1.1.1.4 root 5393: GEN_LOAD_FREG_FTN(DT0, fs);
5394: gen_op_float_truncw_d();
5395: GEN_STORE_FTN_FREG(fd, WT2);
5396: opn = "trunc.w.d";
5397: break;
5398: case FOP(14, 17):
1.1.1.6 ! root 5399: check_cp1_registers(ctx, fs);
1.1.1.4 root 5400: GEN_LOAD_FREG_FTN(DT0, fs);
5401: gen_op_float_ceilw_d();
5402: GEN_STORE_FTN_FREG(fd, WT2);
5403: opn = "ceil.w.d";
5404: break;
5405: case FOP(15, 17):
1.1.1.6 ! root 5406: check_cp1_registers(ctx, fs);
1.1.1.4 root 5407: GEN_LOAD_FREG_FTN(DT0, fs);
5408: gen_op_float_floorw_d();
5409: GEN_STORE_FTN_FREG(fd, WT2);
1.1.1.5 root 5410: opn = "floor.w.d";
5411: break;
1.1.1.6 ! root 5412: case FOP(17, 17):
! 5413: GEN_LOAD_REG_T0(ft);
! 5414: GEN_LOAD_FREG_FTN(DT0, fs);
! 5415: GEN_LOAD_FREG_FTN(DT2, fd);
! 5416: gen_movcf_d(ctx, (ft >> 2) & 0x7, ft & 0x1);
1.1.1.5 root 5417: GEN_STORE_FTN_FREG(fd, DT2);
1.1.1.6 ! root 5418: opn = "movcf.d";
1.1.1.4 root 5419: break;
1.1.1.6 ! root 5420: case FOP(18, 17):
! 5421: GEN_LOAD_REG_T0(ft);
! 5422: GEN_LOAD_FREG_FTN(DT0, fs);
! 5423: GEN_LOAD_FREG_FTN(DT2, fd);
! 5424: gen_op_float_movz_d();
1.1.1.4 root 5425: GEN_STORE_FTN_FREG(fd, DT2);
1.1.1.6 ! root 5426: opn = "movz.d";
! 5427: break;
! 5428: case FOP(19, 17):
! 5429: GEN_LOAD_REG_T0(ft);
! 5430: GEN_LOAD_FREG_FTN(DT0, fs);
! 5431: GEN_LOAD_FREG_FTN(DT2, fd);
! 5432: gen_op_float_movn_d();
! 5433: GEN_STORE_FTN_FREG(fd, DT2);
! 5434: opn = "movn.d";
! 5435: break;
! 5436: case FOP(21, 17):
! 5437: check_cp1_64bitmode(ctx);
! 5438: GEN_LOAD_FREG_FTN(DT0, fs);
! 5439: gen_op_float_recip_d();
! 5440: GEN_STORE_FTN_FREG(fd, DT2);
! 5441: opn = "recip.d";
! 5442: break;
! 5443: case FOP(22, 17):
! 5444: check_cp1_64bitmode(ctx);
! 5445: GEN_LOAD_FREG_FTN(DT0, fs);
! 5446: gen_op_float_rsqrt_d();
! 5447: GEN_STORE_FTN_FREG(fd, DT2);
! 5448: opn = "rsqrt.d";
! 5449: break;
! 5450: case FOP(28, 17):
! 5451: check_cp1_64bitmode(ctx);
! 5452: GEN_LOAD_FREG_FTN(DT0, fs);
! 5453: GEN_LOAD_FREG_FTN(DT2, ft);
! 5454: gen_op_float_recip2_d();
! 5455: GEN_STORE_FTN_FREG(fd, DT2);
! 5456: opn = "recip2.d";
! 5457: break;
! 5458: case FOP(29, 17):
! 5459: check_cp1_64bitmode(ctx);
! 5460: GEN_LOAD_FREG_FTN(DT0, fs);
! 5461: gen_op_float_recip1_d();
! 5462: GEN_STORE_FTN_FREG(fd, DT2);
! 5463: opn = "recip1.d";
! 5464: break;
! 5465: case FOP(30, 17):
! 5466: check_cp1_64bitmode(ctx);
! 5467: GEN_LOAD_FREG_FTN(DT0, fs);
! 5468: gen_op_float_rsqrt1_d();
! 5469: GEN_STORE_FTN_FREG(fd, DT2);
! 5470: opn = "rsqrt1.d";
! 5471: break;
! 5472: case FOP(31, 17):
! 5473: check_cp1_64bitmode(ctx);
! 5474: GEN_LOAD_FREG_FTN(DT0, fs);
! 5475: GEN_LOAD_FREG_FTN(DT2, ft);
! 5476: gen_op_float_rsqrt2_d();
! 5477: GEN_STORE_FTN_FREG(fd, DT2);
! 5478: opn = "rsqrt2.d";
1.1.1.4 root 5479: break;
5480: case FOP(48, 17):
5481: case FOP(49, 17):
5482: case FOP(50, 17):
5483: case FOP(51, 17):
5484: case FOP(52, 17):
5485: case FOP(53, 17):
5486: case FOP(54, 17):
5487: case FOP(55, 17):
5488: case FOP(56, 17):
5489: case FOP(57, 17):
5490: case FOP(58, 17):
5491: case FOP(59, 17):
5492: case FOP(60, 17):
5493: case FOP(61, 17):
5494: case FOP(62, 17):
5495: case FOP(63, 17):
5496: GEN_LOAD_FREG_FTN(DT0, fs);
5497: GEN_LOAD_FREG_FTN(DT1, ft);
1.1.1.6 ! root 5498: if (ctx->opcode & (1 << 6)) {
! 5499: check_cop1x(ctx);
! 5500: check_cp1_registers(ctx, fs | ft);
! 5501: gen_cmpabs_d(func-48, cc);
! 5502: opn = condnames_abs[func-48];
! 5503: } else {
! 5504: check_cp1_registers(ctx, fs | ft);
! 5505: gen_cmp_d(func-48, cc);
! 5506: opn = condnames[func-48];
! 5507: }
! 5508: break;
! 5509: case FOP(32, 17):
! 5510: check_cp1_registers(ctx, fs);
! 5511: GEN_LOAD_FREG_FTN(DT0, fs);
! 5512: gen_op_float_cvts_d();
! 5513: GEN_STORE_FTN_FREG(fd, WT2);
! 5514: opn = "cvt.s.d";
! 5515: break;
! 5516: case FOP(36, 17):
! 5517: check_cp1_registers(ctx, fs);
! 5518: GEN_LOAD_FREG_FTN(DT0, fs);
! 5519: gen_op_float_cvtw_d();
! 5520: GEN_STORE_FTN_FREG(fd, WT2);
! 5521: opn = "cvt.w.d";
! 5522: break;
! 5523: case FOP(37, 17):
! 5524: check_cp1_64bitmode(ctx);
! 5525: GEN_LOAD_FREG_FTN(DT0, fs);
! 5526: gen_op_float_cvtl_d();
! 5527: GEN_STORE_FTN_FREG(fd, DT2);
! 5528: opn = "cvt.l.d";
! 5529: break;
! 5530: case FOP(32, 20):
! 5531: GEN_LOAD_FREG_FTN(WT0, fs);
! 5532: gen_op_float_cvts_w();
! 5533: GEN_STORE_FTN_FREG(fd, WT2);
! 5534: opn = "cvt.s.w";
! 5535: break;
! 5536: case FOP(33, 20):
! 5537: check_cp1_registers(ctx, fd);
! 5538: GEN_LOAD_FREG_FTN(WT0, fs);
! 5539: gen_op_float_cvtd_w();
! 5540: GEN_STORE_FTN_FREG(fd, DT2);
! 5541: opn = "cvt.d.w";
! 5542: break;
! 5543: case FOP(32, 21):
! 5544: check_cp1_64bitmode(ctx);
! 5545: GEN_LOAD_FREG_FTN(DT0, fs);
! 5546: gen_op_float_cvts_l();
! 5547: GEN_STORE_FTN_FREG(fd, WT2);
! 5548: opn = "cvt.s.l";
! 5549: break;
! 5550: case FOP(33, 21):
! 5551: check_cp1_64bitmode(ctx);
! 5552: GEN_LOAD_FREG_FTN(DT0, fs);
! 5553: gen_op_float_cvtd_l();
! 5554: GEN_STORE_FTN_FREG(fd, DT2);
! 5555: opn = "cvt.d.l";
! 5556: break;
! 5557: case FOP(38, 20):
! 5558: check_cp1_64bitmode(ctx);
! 5559: GEN_LOAD_FREG_FTN(WT0, fs);
! 5560: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5561: gen_op_float_cvtps_pw();
! 5562: GEN_STORE_FTN_FREG(fd, WT2);
! 5563: GEN_STORE_FTN_FREG(fd, WTH2);
! 5564: opn = "cvt.ps.pw";
! 5565: break;
! 5566: case FOP(0, 22):
! 5567: check_cp1_64bitmode(ctx);
! 5568: GEN_LOAD_FREG_FTN(WT0, fs);
! 5569: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5570: GEN_LOAD_FREG_FTN(WT1, ft);
! 5571: GEN_LOAD_FREG_FTN(WTH1, ft);
! 5572: gen_op_float_add_ps();
! 5573: GEN_STORE_FTN_FREG(fd, WT2);
! 5574: GEN_STORE_FTN_FREG(fd, WTH2);
! 5575: opn = "add.ps";
! 5576: break;
! 5577: case FOP(1, 22):
! 5578: check_cp1_64bitmode(ctx);
! 5579: GEN_LOAD_FREG_FTN(WT0, fs);
! 5580: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5581: GEN_LOAD_FREG_FTN(WT1, ft);
! 5582: GEN_LOAD_FREG_FTN(WTH1, ft);
! 5583: gen_op_float_sub_ps();
! 5584: GEN_STORE_FTN_FREG(fd, WT2);
! 5585: GEN_STORE_FTN_FREG(fd, WTH2);
! 5586: opn = "sub.ps";
! 5587: break;
! 5588: case FOP(2, 22):
! 5589: check_cp1_64bitmode(ctx);
! 5590: GEN_LOAD_FREG_FTN(WT0, fs);
! 5591: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5592: GEN_LOAD_FREG_FTN(WT1, ft);
! 5593: GEN_LOAD_FREG_FTN(WTH1, ft);
! 5594: gen_op_float_mul_ps();
! 5595: GEN_STORE_FTN_FREG(fd, WT2);
! 5596: GEN_STORE_FTN_FREG(fd, WTH2);
! 5597: opn = "mul.ps";
! 5598: break;
! 5599: case FOP(5, 22):
! 5600: check_cp1_64bitmode(ctx);
! 5601: GEN_LOAD_FREG_FTN(WT0, fs);
! 5602: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5603: gen_op_float_abs_ps();
! 5604: GEN_STORE_FTN_FREG(fd, WT2);
! 5605: GEN_STORE_FTN_FREG(fd, WTH2);
! 5606: opn = "abs.ps";
! 5607: break;
! 5608: case FOP(6, 22):
! 5609: check_cp1_64bitmode(ctx);
! 5610: GEN_LOAD_FREG_FTN(WT0, fs);
! 5611: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5612: gen_op_float_mov_ps();
! 5613: GEN_STORE_FTN_FREG(fd, WT2);
! 5614: GEN_STORE_FTN_FREG(fd, WTH2);
! 5615: opn = "mov.ps";
! 5616: break;
! 5617: case FOP(7, 22):
! 5618: check_cp1_64bitmode(ctx);
! 5619: GEN_LOAD_FREG_FTN(WT0, fs);
! 5620: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5621: gen_op_float_chs_ps();
! 5622: GEN_STORE_FTN_FREG(fd, WT2);
! 5623: GEN_STORE_FTN_FREG(fd, WTH2);
! 5624: opn = "neg.ps";
! 5625: break;
! 5626: case FOP(17, 22):
! 5627: check_cp1_64bitmode(ctx);
! 5628: GEN_LOAD_REG_T0(ft);
! 5629: GEN_LOAD_FREG_FTN(WT0, fs);
! 5630: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5631: GEN_LOAD_FREG_FTN(WT2, fd);
! 5632: GEN_LOAD_FREG_FTN(WTH2, fd);
! 5633: gen_movcf_ps(ctx, (ft >> 2) & 0x7, ft & 0x1);
! 5634: GEN_STORE_FTN_FREG(fd, WT2);
! 5635: GEN_STORE_FTN_FREG(fd, WTH2);
! 5636: opn = "movcf.ps";
! 5637: break;
! 5638: case FOP(18, 22):
! 5639: check_cp1_64bitmode(ctx);
! 5640: GEN_LOAD_REG_T0(ft);
! 5641: GEN_LOAD_FREG_FTN(WT0, fs);
! 5642: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5643: GEN_LOAD_FREG_FTN(WT2, fd);
! 5644: GEN_LOAD_FREG_FTN(WTH2, fd);
! 5645: gen_op_float_movz_ps();
! 5646: GEN_STORE_FTN_FREG(fd, WT2);
! 5647: GEN_STORE_FTN_FREG(fd, WTH2);
! 5648: opn = "movz.ps";
! 5649: break;
! 5650: case FOP(19, 22):
! 5651: check_cp1_64bitmode(ctx);
! 5652: GEN_LOAD_REG_T0(ft);
! 5653: GEN_LOAD_FREG_FTN(WT0, fs);
! 5654: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5655: GEN_LOAD_FREG_FTN(WT2, fd);
! 5656: GEN_LOAD_FREG_FTN(WTH2, fd);
! 5657: gen_op_float_movn_ps();
! 5658: GEN_STORE_FTN_FREG(fd, WT2);
! 5659: GEN_STORE_FTN_FREG(fd, WTH2);
! 5660: opn = "movn.ps";
! 5661: break;
! 5662: case FOP(24, 22):
! 5663: check_cp1_64bitmode(ctx);
! 5664: GEN_LOAD_FREG_FTN(WT0, ft);
! 5665: GEN_LOAD_FREG_FTN(WTH0, ft);
! 5666: GEN_LOAD_FREG_FTN(WT1, fs);
! 5667: GEN_LOAD_FREG_FTN(WTH1, fs);
! 5668: gen_op_float_addr_ps();
! 5669: GEN_STORE_FTN_FREG(fd, WT2);
! 5670: GEN_STORE_FTN_FREG(fd, WTH2);
! 5671: opn = "addr.ps";
! 5672: break;
! 5673: case FOP(26, 22):
! 5674: check_cp1_64bitmode(ctx);
! 5675: GEN_LOAD_FREG_FTN(WT0, ft);
! 5676: GEN_LOAD_FREG_FTN(WTH0, ft);
! 5677: GEN_LOAD_FREG_FTN(WT1, fs);
! 5678: GEN_LOAD_FREG_FTN(WTH1, fs);
! 5679: gen_op_float_mulr_ps();
! 5680: GEN_STORE_FTN_FREG(fd, WT2);
! 5681: GEN_STORE_FTN_FREG(fd, WTH2);
! 5682: opn = "mulr.ps";
! 5683: break;
! 5684: case FOP(28, 22):
! 5685: check_cp1_64bitmode(ctx);
! 5686: GEN_LOAD_FREG_FTN(WT0, fs);
! 5687: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5688: GEN_LOAD_FREG_FTN(WT2, fd);
! 5689: GEN_LOAD_FREG_FTN(WTH2, fd);
! 5690: gen_op_float_recip2_ps();
! 5691: GEN_STORE_FTN_FREG(fd, WT2);
! 5692: GEN_STORE_FTN_FREG(fd, WTH2);
! 5693: opn = "recip2.ps";
! 5694: break;
! 5695: case FOP(29, 22):
! 5696: check_cp1_64bitmode(ctx);
! 5697: GEN_LOAD_FREG_FTN(WT0, fs);
! 5698: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5699: gen_op_float_recip1_ps();
! 5700: GEN_STORE_FTN_FREG(fd, WT2);
! 5701: GEN_STORE_FTN_FREG(fd, WTH2);
! 5702: opn = "recip1.ps";
! 5703: break;
! 5704: case FOP(30, 22):
! 5705: check_cp1_64bitmode(ctx);
! 5706: GEN_LOAD_FREG_FTN(WT0, fs);
! 5707: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5708: gen_op_float_rsqrt1_ps();
! 5709: GEN_STORE_FTN_FREG(fd, WT2);
! 5710: GEN_STORE_FTN_FREG(fd, WTH2);
! 5711: opn = "rsqrt1.ps";
! 5712: break;
! 5713: case FOP(31, 22):
! 5714: check_cp1_64bitmode(ctx);
! 5715: GEN_LOAD_FREG_FTN(WT0, fs);
! 5716: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5717: GEN_LOAD_FREG_FTN(WT2, ft);
! 5718: GEN_LOAD_FREG_FTN(WTH2, ft);
! 5719: gen_op_float_rsqrt2_ps();
! 5720: GEN_STORE_FTN_FREG(fd, WT2);
! 5721: GEN_STORE_FTN_FREG(fd, WTH2);
! 5722: opn = "rsqrt2.ps";
! 5723: break;
! 5724: case FOP(32, 22):
! 5725: check_cp1_64bitmode(ctx);
! 5726: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5727: gen_op_float_cvts_pu();
! 5728: GEN_STORE_FTN_FREG(fd, WT2);
! 5729: opn = "cvt.s.pu";
! 5730: break;
! 5731: case FOP(36, 22):
! 5732: check_cp1_64bitmode(ctx);
! 5733: GEN_LOAD_FREG_FTN(WT0, fs);
! 5734: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5735: gen_op_float_cvtpw_ps();
! 5736: GEN_STORE_FTN_FREG(fd, WT2);
! 5737: GEN_STORE_FTN_FREG(fd, WTH2);
! 5738: opn = "cvt.pw.ps";
1.1.1.4 root 5739: break;
1.1.1.6 ! root 5740: case FOP(40, 22):
! 5741: check_cp1_64bitmode(ctx);
1.1.1.4 root 5742: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 5743: gen_op_float_cvts_pl();
1.1.1.4 root 5744: GEN_STORE_FTN_FREG(fd, WT2);
1.1.1.6 ! root 5745: opn = "cvt.s.pl";
1.1.1.4 root 5746: break;
1.1.1.6 ! root 5747: case FOP(44, 22):
! 5748: check_cp1_64bitmode(ctx);
1.1.1.4 root 5749: GEN_LOAD_FREG_FTN(WT0, fs);
5750: GEN_LOAD_FREG_FTN(WT1, ft);
1.1.1.6 ! root 5751: gen_op_float_pll_ps();
! 5752: GEN_STORE_FTN_FREG(fd, DT2);
! 5753: opn = "pll.ps";
1.1.1.4 root 5754: break;
1.1.1.6 ! root 5755: case FOP(45, 22):
! 5756: check_cp1_64bitmode(ctx);
1.1.1.4 root 5757: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 5758: GEN_LOAD_FREG_FTN(WTH1, ft);
! 5759: gen_op_float_plu_ps();
! 5760: GEN_STORE_FTN_FREG(fd, DT2);
! 5761: opn = "plu.ps";
! 5762: break;
! 5763: case FOP(46, 22):
! 5764: check_cp1_64bitmode(ctx);
! 5765: GEN_LOAD_FREG_FTN(WTH0, fs);
1.1.1.4 root 5766: GEN_LOAD_FREG_FTN(WT1, ft);
1.1.1.6 ! root 5767: gen_op_float_pul_ps();
! 5768: GEN_STORE_FTN_FREG(fd, DT2);
! 5769: opn = "pul.ps";
1.1.1.4 root 5770: break;
1.1.1.6 ! root 5771: case FOP(47, 22):
! 5772: check_cp1_64bitmode(ctx);
! 5773: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5774: GEN_LOAD_FREG_FTN(WTH1, ft);
! 5775: gen_op_float_puu_ps();
! 5776: GEN_STORE_FTN_FREG(fd, DT2);
! 5777: opn = "puu.ps";
! 5778: break;
! 5779: case FOP(48, 22):
! 5780: case FOP(49, 22):
! 5781: case FOP(50, 22):
! 5782: case FOP(51, 22):
! 5783: case FOP(52, 22):
! 5784: case FOP(53, 22):
! 5785: case FOP(54, 22):
! 5786: case FOP(55, 22):
! 5787: case FOP(56, 22):
! 5788: case FOP(57, 22):
! 5789: case FOP(58, 22):
! 5790: case FOP(59, 22):
! 5791: case FOP(60, 22):
! 5792: case FOP(61, 22):
! 5793: case FOP(62, 22):
! 5794: case FOP(63, 22):
! 5795: check_cp1_64bitmode(ctx);
1.1.1.4 root 5796: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 5797: GEN_LOAD_FREG_FTN(WTH0, fs);
1.1.1.4 root 5798: GEN_LOAD_FREG_FTN(WT1, ft);
1.1.1.6 ! root 5799: GEN_LOAD_FREG_FTN(WTH1, ft);
! 5800: if (ctx->opcode & (1 << 6)) {
! 5801: gen_cmpabs_ps(func-48, cc);
! 5802: opn = condnames_abs[func-48];
! 5803: } else {
! 5804: gen_cmp_ps(func-48, cc);
! 5805: opn = condnames[func-48];
! 5806: }
1.1.1.4 root 5807: break;
1.1.1.6 ! root 5808: default:
! 5809: MIPS_INVAL(opn);
! 5810: generate_exception (ctx, EXCP_RI);
! 5811: return;
! 5812: }
! 5813: switch (optype) {
! 5814: case BINOP:
! 5815: MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
! 5816: break;
! 5817: case CMPOP:
! 5818: MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
! 5819: break;
! 5820: default:
! 5821: MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
! 5822: break;
! 5823: }
! 5824: }
! 5825:
! 5826: /* Coprocessor 3 (FPU) */
! 5827: static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
! 5828: int fd, int fs, int base, int index)
! 5829: {
! 5830: const char *opn = "extended float load/store";
! 5831: int store = 0;
! 5832:
! 5833: if (base == 0) {
! 5834: if (index == 0)
! 5835: gen_op_reset_T0();
! 5836: else
! 5837: GEN_LOAD_REG_T0(index);
! 5838: } else if (index == 0) {
! 5839: GEN_LOAD_REG_T0(base);
! 5840: } else {
! 5841: GEN_LOAD_REG_T0(base);
! 5842: GEN_LOAD_REG_T1(index);
! 5843: gen_op_addr_add();
! 5844: }
! 5845: /* Don't do NOP if destination is zero: we must perform the actual
! 5846: memory access. */
! 5847: switch (opc) {
! 5848: case OPC_LWXC1:
! 5849: check_cop1x(ctx);
! 5850: op_ldst(lwc1);
! 5851: GEN_STORE_FTN_FREG(fd, WT0);
! 5852: opn = "lwxc1";
! 5853: break;
! 5854: case OPC_LDXC1:
! 5855: check_cop1x(ctx);
! 5856: check_cp1_registers(ctx, fd);
! 5857: op_ldst(ldc1);
! 5858: GEN_STORE_FTN_FREG(fd, DT0);
! 5859: opn = "ldxc1";
! 5860: break;
! 5861: case OPC_LUXC1:
! 5862: check_cp1_64bitmode(ctx);
! 5863: op_ldst(luxc1);
! 5864: GEN_STORE_FTN_FREG(fd, DT0);
! 5865: opn = "luxc1";
! 5866: break;
! 5867: case OPC_SWXC1:
! 5868: check_cop1x(ctx);
1.1.1.4 root 5869: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 5870: op_ldst(swc1);
! 5871: opn = "swxc1";
! 5872: store = 1;
1.1.1.4 root 5873: break;
1.1.1.6 ! root 5874: case OPC_SDXC1:
! 5875: check_cop1x(ctx);
! 5876: check_cp1_registers(ctx, fs);
! 5877: GEN_LOAD_FREG_FTN(DT0, fs);
! 5878: op_ldst(sdc1);
! 5879: opn = "sdxc1";
! 5880: store = 1;
! 5881: break;
! 5882: case OPC_SUXC1:
! 5883: check_cp1_64bitmode(ctx);
! 5884: GEN_LOAD_FREG_FTN(DT0, fs);
! 5885: op_ldst(suxc1);
! 5886: opn = "suxc1";
! 5887: store = 1;
! 5888: break;
! 5889: default:
! 5890: MIPS_INVAL(opn);
! 5891: generate_exception(ctx, EXCP_RI);
! 5892: return;
! 5893: }
! 5894: MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
! 5895: regnames[index], regnames[base]);
! 5896: }
! 5897:
! 5898: static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
! 5899: int fd, int fr, int fs, int ft)
! 5900: {
! 5901: const char *opn = "flt3_arith";
! 5902:
! 5903: switch (opc) {
! 5904: case OPC_ALNV_PS:
! 5905: check_cp1_64bitmode(ctx);
! 5906: GEN_LOAD_REG_T0(fr);
! 5907: GEN_LOAD_FREG_FTN(DT0, fs);
! 5908: GEN_LOAD_FREG_FTN(DT1, ft);
! 5909: gen_op_float_alnv_ps();
! 5910: GEN_STORE_FTN_FREG(fd, DT2);
! 5911: opn = "alnv.ps";
! 5912: break;
! 5913: case OPC_MADD_S:
! 5914: check_cop1x(ctx);
1.1.1.4 root 5915: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 5916: GEN_LOAD_FREG_FTN(WT1, ft);
! 5917: GEN_LOAD_FREG_FTN(WT2, fr);
! 5918: gen_op_float_muladd_s();
1.1.1.4 root 5919: GEN_STORE_FTN_FREG(fd, WT2);
1.1.1.6 ! root 5920: opn = "madd.s";
1.1.1.4 root 5921: break;
1.1.1.6 ! root 5922: case OPC_MADD_D:
! 5923: check_cop1x(ctx);
! 5924: check_cp1_registers(ctx, fd | fs | ft | fr);
! 5925: GEN_LOAD_FREG_FTN(DT0, fs);
! 5926: GEN_LOAD_FREG_FTN(DT1, ft);
! 5927: GEN_LOAD_FREG_FTN(DT2, fr);
! 5928: gen_op_float_muladd_d();
! 5929: GEN_STORE_FTN_FREG(fd, DT2);
! 5930: opn = "madd.d";
! 5931: break;
! 5932: case OPC_MADD_PS:
! 5933: check_cp1_64bitmode(ctx);
1.1.1.4 root 5934: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 5935: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5936: GEN_LOAD_FREG_FTN(WT1, ft);
! 5937: GEN_LOAD_FREG_FTN(WTH1, ft);
! 5938: GEN_LOAD_FREG_FTN(WT2, fr);
! 5939: GEN_LOAD_FREG_FTN(WTH2, fr);
! 5940: gen_op_float_muladd_ps();
1.1.1.4 root 5941: GEN_STORE_FTN_FREG(fd, WT2);
1.1.1.6 ! root 5942: GEN_STORE_FTN_FREG(fd, WTH2);
! 5943: opn = "madd.ps";
1.1.1.4 root 5944: break;
1.1.1.6 ! root 5945: case OPC_MSUB_S:
! 5946: check_cop1x(ctx);
1.1.1.4 root 5947: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 5948: GEN_LOAD_FREG_FTN(WT1, ft);
! 5949: GEN_LOAD_FREG_FTN(WT2, fr);
! 5950: gen_op_float_mulsub_s();
1.1.1.4 root 5951: GEN_STORE_FTN_FREG(fd, WT2);
1.1.1.6 ! root 5952: opn = "msub.s";
1.1.1.4 root 5953: break;
1.1.1.6 ! root 5954: case OPC_MSUB_D:
! 5955: check_cop1x(ctx);
! 5956: check_cp1_registers(ctx, fd | fs | ft | fr);
! 5957: GEN_LOAD_FREG_FTN(DT0, fs);
! 5958: GEN_LOAD_FREG_FTN(DT1, ft);
! 5959: GEN_LOAD_FREG_FTN(DT2, fr);
! 5960: gen_op_float_mulsub_d();
! 5961: GEN_STORE_FTN_FREG(fd, DT2);
! 5962: opn = "msub.d";
! 5963: break;
! 5964: case OPC_MSUB_PS:
! 5965: check_cp1_64bitmode(ctx);
1.1.1.4 root 5966: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 5967: GEN_LOAD_FREG_FTN(WTH0, fs);
! 5968: GEN_LOAD_FREG_FTN(WT1, ft);
! 5969: GEN_LOAD_FREG_FTN(WTH1, ft);
! 5970: GEN_LOAD_FREG_FTN(WT2, fr);
! 5971: GEN_LOAD_FREG_FTN(WTH2, fr);
! 5972: gen_op_float_mulsub_ps();
1.1.1.4 root 5973: GEN_STORE_FTN_FREG(fd, WT2);
1.1.1.6 ! root 5974: GEN_STORE_FTN_FREG(fd, WTH2);
! 5975: opn = "msub.ps";
1.1.1.4 root 5976: break;
1.1.1.6 ! root 5977: case OPC_NMADD_S:
! 5978: check_cop1x(ctx);
1.1.1.4 root 5979: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 5980: GEN_LOAD_FREG_FTN(WT1, ft);
! 5981: GEN_LOAD_FREG_FTN(WT2, fr);
! 5982: gen_op_float_nmuladd_s();
1.1.1.4 root 5983: GEN_STORE_FTN_FREG(fd, WT2);
1.1.1.6 ! root 5984: opn = "nmadd.s";
1.1.1.4 root 5985: break;
1.1.1.6 ! root 5986: case OPC_NMADD_D:
! 5987: check_cop1x(ctx);
! 5988: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.5 root 5989: GEN_LOAD_FREG_FTN(DT0, fs);
1.1.1.6 ! root 5990: GEN_LOAD_FREG_FTN(DT1, ft);
! 5991: GEN_LOAD_FREG_FTN(DT2, fr);
! 5992: gen_op_float_nmuladd_d();
! 5993: GEN_STORE_FTN_FREG(fd, DT2);
! 5994: opn = "nmadd.d";
1.1.1.5 root 5995: break;
1.1.1.6 ! root 5996: case OPC_NMADD_PS:
! 5997: check_cp1_64bitmode(ctx);
1.1.1.4 root 5998: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 5999: GEN_LOAD_FREG_FTN(WTH0, fs);
! 6000: GEN_LOAD_FREG_FTN(WT1, ft);
! 6001: GEN_LOAD_FREG_FTN(WTH1, ft);
! 6002: GEN_LOAD_FREG_FTN(WT2, fr);
! 6003: GEN_LOAD_FREG_FTN(WTH2, fr);
! 6004: gen_op_float_nmuladd_ps();
1.1.1.4 root 6005: GEN_STORE_FTN_FREG(fd, WT2);
1.1.1.6 ! root 6006: GEN_STORE_FTN_FREG(fd, WTH2);
! 6007: opn = "nmadd.ps";
1.1.1.4 root 6008: break;
1.1.1.6 ! root 6009: case OPC_NMSUB_S:
! 6010: check_cop1x(ctx);
1.1.1.4 root 6011: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 6012: GEN_LOAD_FREG_FTN(WT1, ft);
! 6013: GEN_LOAD_FREG_FTN(WT2, fr);
! 6014: gen_op_float_nmulsub_s();
1.1.1.4 root 6015: GEN_STORE_FTN_FREG(fd, WT2);
1.1.1.6 ! root 6016: opn = "nmsub.s";
1.1.1.4 root 6017: break;
1.1.1.6 ! root 6018: case OPC_NMSUB_D:
! 6019: check_cop1x(ctx);
! 6020: check_cp1_registers(ctx, fd | fs | ft | fr);
1.1.1.5 root 6021: GEN_LOAD_FREG_FTN(DT0, fs);
1.1.1.6 ! root 6022: GEN_LOAD_FREG_FTN(DT1, ft);
! 6023: GEN_LOAD_FREG_FTN(DT2, fr);
! 6024: gen_op_float_nmulsub_d();
! 6025: GEN_STORE_FTN_FREG(fd, DT2);
! 6026: opn = "nmsub.d";
1.1.1.4 root 6027: break;
1.1.1.6 ! root 6028: case OPC_NMSUB_PS:
! 6029: check_cp1_64bitmode(ctx);
1.1.1.4 root 6030: GEN_LOAD_FREG_FTN(WT0, fs);
1.1.1.6 ! root 6031: GEN_LOAD_FREG_FTN(WTH0, fs);
1.1.1.4 root 6032: GEN_LOAD_FREG_FTN(WT1, ft);
1.1.1.6 ! root 6033: GEN_LOAD_FREG_FTN(WTH1, ft);
! 6034: GEN_LOAD_FREG_FTN(WT2, fr);
! 6035: GEN_LOAD_FREG_FTN(WTH2, fr);
! 6036: gen_op_float_nmulsub_ps();
! 6037: GEN_STORE_FTN_FREG(fd, WT2);
! 6038: GEN_STORE_FTN_FREG(fd, WTH2);
! 6039: opn = "nmsub.ps";
1.1.1.4 root 6040: break;
1.1.1.6 ! root 6041: default:
! 6042: MIPS_INVAL(opn);
! 6043: generate_exception (ctx, EXCP_RI);
1.1.1.4 root 6044: return;
6045: }
1.1.1.6 ! root 6046: MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
! 6047: fregnames[fs], fregnames[ft]);
1.1 root 6048: }
6049:
1.1.1.5 root 6050: /* ISA extensions (ASEs) */
6051: /* MIPS16 extension to MIPS32 */
6052: /* SmartMIPS extension to MIPS32 */
6053:
1.1.1.6 ! root 6054: #if defined(TARGET_MIPS64)
1.1 root 6055:
6056: /* MDMX extension to MIPS64 */
6057:
6058: #endif
6059:
1.1.1.6 ! root 6060: static void decode_opc (CPUState *env, DisasContext *ctx)
1.1 root 6061: {
6062: int32_t offset;
6063: int rs, rt, rd, sa;
1.1.1.5 root 6064: uint32_t op, op1, op2;
1.1 root 6065: int16_t imm;
6066:
1.1.1.4 root 6067: /* make sure instructions are on a word boundary */
6068: if (ctx->pc & 0x3) {
1.1.1.6 ! root 6069: env->CP0_BadVAddr = ctx->pc;
1.1.1.4 root 6070: generate_exception(ctx, EXCP_AdEL);
6071: return;
6072: }
6073:
1.1.1.2 root 6074: if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
1.1.1.6 ! root 6075: int l1;
1.1 root 6076: /* Handle blikely not taken case */
1.1.1.6 ! root 6077: MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
! 6078: l1 = gen_new_label();
! 6079: gen_op_jnz_T2(l1);
! 6080: gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
! 6081: gen_goto_tb(ctx, 1, ctx->pc + 4);
! 6082: gen_set_label(l1);
1.1 root 6083: }
1.1.1.5 root 6084: op = MASK_OP_MAJOR(ctx->opcode);
6085: rs = (ctx->opcode >> 21) & 0x1f;
6086: rt = (ctx->opcode >> 16) & 0x1f;
6087: rd = (ctx->opcode >> 11) & 0x1f;
6088: sa = (ctx->opcode >> 6) & 0x1f;
1.1 root 6089: imm = (int16_t)ctx->opcode;
6090: switch (op) {
1.1.1.5 root 6091: case OPC_SPECIAL:
6092: op1 = MASK_SPECIAL(ctx->opcode);
1.1 root 6093: switch (op1) {
1.1.1.5 root 6094: case OPC_SLL: /* Arithmetic with immediate */
6095: case OPC_SRL ... OPC_SRA:
1.1.1.6 ! root 6096: gen_arith_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 6097: break;
1.1.1.6 ! root 6098: case OPC_MOVZ ... OPC_MOVN:
! 6099: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
1.1.1.5 root 6100: case OPC_SLLV: /* Arithmetic */
6101: case OPC_SRLV ... OPC_SRAV:
6102: case OPC_ADD ... OPC_NOR:
6103: case OPC_SLT ... OPC_SLTU:
1.1.1.6 ! root 6104: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 6105: break;
1.1.1.5 root 6106: case OPC_MULT ... OPC_DIVU:
1.1.1.6 ! root 6107: if (sa) {
! 6108: check_insn(env, ctx, INSN_VR54XX);
! 6109: op1 = MASK_MUL_VR54XX(ctx->opcode);
! 6110: gen_mul_vr54xx(ctx, op1, rd, rs, rt);
! 6111: } else
! 6112: gen_muldiv(ctx, op1, rs, rt);
1.1 root 6113: break;
1.1.1.5 root 6114: case OPC_JR ... OPC_JALR:
6115: gen_compute_branch(ctx, op1, rs, rd, sa);
1.1 root 6116: return;
1.1.1.5 root 6117: case OPC_TGE ... OPC_TEQ: /* Traps */
6118: case OPC_TNE:
6119: gen_trap(ctx, op1, rs, rt, -1);
6120: break;
6121: case OPC_MFHI: /* Move from HI/LO */
6122: case OPC_MFLO:
6123: gen_HILO(ctx, op1, rd);
1.1 root 6124: break;
1.1.1.5 root 6125: case OPC_MTHI:
6126: case OPC_MTLO: /* Move to HI/LO */
6127: gen_HILO(ctx, op1, rs);
6128: break;
1.1.1.6 ! root 6129: case OPC_PMON: /* Pmon entry point, also R4010 selsl */
! 6130: #ifdef MIPS_STRICT_STANDARD
! 6131: MIPS_INVAL("PMON / selsl");
! 6132: generate_exception(ctx, EXCP_RI);
! 6133: #else
1.1.1.5 root 6134: gen_op_pmon(sa);
1.1.1.6 ! root 6135: #endif
1.1.1.5 root 6136: break;
6137: case OPC_SYSCALL:
1.1 root 6138: generate_exception(ctx, EXCP_SYSCALL);
6139: break;
1.1.1.5 root 6140: case OPC_BREAK:
1.1 root 6141: generate_exception(ctx, EXCP_BREAK);
6142: break;
1.1.1.6 ! root 6143: case OPC_SPIM:
! 6144: #ifdef MIPS_STRICT_STANDARD
! 6145: MIPS_INVAL("SPIM");
! 6146: generate_exception(ctx, EXCP_RI);
! 6147: #else
1.1.1.5 root 6148: /* Implemented as RI exception for now. */
6149: MIPS_INVAL("spim (unofficial)");
6150: generate_exception(ctx, EXCP_RI);
1.1.1.6 ! root 6151: #endif
1.1 root 6152: break;
1.1.1.5 root 6153: case OPC_SYNC:
1.1.1.6 ! root 6154: /* Treat as NOP. */
1.1 root 6155: break;
1.1.1.2 root 6156:
1.1.1.5 root 6157: case OPC_MOVCI:
1.1.1.6 ! root 6158: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
! 6159: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
! 6160: save_cpu_state(ctx, 1);
! 6161: check_cp1_enabled(ctx);
! 6162: gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
! 6163: (ctx->opcode >> 16) & 1);
! 6164: } else {
! 6165: generate_exception_err(ctx, EXCP_CpU, 1);
! 6166: }
1.1.1.2 root 6167: break;
6168:
1.1.1.6 ! root 6169: #if defined(TARGET_MIPS64)
1.1.1.5 root 6170: /* MIPS64 specific opcodes */
6171: case OPC_DSLL:
6172: case OPC_DSRL ... OPC_DSRA:
6173: case OPC_DSLL32:
6174: case OPC_DSRL32 ... OPC_DSRA32:
1.1.1.6 ! root 6175: check_insn(env, ctx, ISA_MIPS3);
! 6176: check_mips_64(ctx);
! 6177: gen_arith_imm(env, ctx, op1, rd, rt, sa);
1.1.1.5 root 6178: break;
6179: case OPC_DSLLV:
6180: case OPC_DSRLV ... OPC_DSRAV:
6181: case OPC_DADD ... OPC_DSUBU:
1.1.1.6 ! root 6182: check_insn(env, ctx, ISA_MIPS3);
! 6183: check_mips_64(ctx);
! 6184: gen_arith(env, ctx, op1, rd, rs, rt);
1.1.1.5 root 6185: break;
6186: case OPC_DMULT ... OPC_DDIVU:
1.1.1.6 ! root 6187: check_insn(env, ctx, ISA_MIPS3);
! 6188: check_mips_64(ctx);
1.1.1.5 root 6189: gen_muldiv(ctx, op1, rs, rt);
6190: break;
1.1 root 6191: #endif
6192: default: /* Invalid */
6193: MIPS_INVAL("special");
6194: generate_exception(ctx, EXCP_RI);
6195: break;
6196: }
6197: break;
1.1.1.5 root 6198: case OPC_SPECIAL2:
6199: op1 = MASK_SPECIAL2(ctx->opcode);
1.1 root 6200: switch (op1) {
1.1.1.5 root 6201: case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
6202: case OPC_MSUB ... OPC_MSUBU:
1.1.1.6 ! root 6203: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 6204: gen_muldiv(ctx, op1, rs, rt);
1.1 root 6205: break;
1.1.1.5 root 6206: case OPC_MUL:
1.1.1.6 ! root 6207: gen_arith(env, ctx, op1, rd, rs, rt);
1.1 root 6208: break;
1.1.1.5 root 6209: case OPC_CLZ ... OPC_CLO:
1.1.1.6 ! root 6210: check_insn(env, ctx, ISA_MIPS32);
1.1.1.5 root 6211: gen_cl(ctx, op1, rd, rs);
1.1 root 6212: break;
1.1.1.5 root 6213: case OPC_SDBBP:
1.1 root 6214: /* XXX: not clear which exception should be raised
6215: * when in debug mode...
6216: */
1.1.1.6 ! root 6217: check_insn(env, ctx, ISA_MIPS32);
1.1 root 6218: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
6219: generate_exception(ctx, EXCP_DBp);
6220: } else {
6221: generate_exception(ctx, EXCP_DBp);
6222: }
1.1.1.6 ! root 6223: /* Treat as NOP. */
1.1 root 6224: break;
1.1.1.6 ! root 6225: #if defined(TARGET_MIPS64)
1.1.1.5 root 6226: case OPC_DCLZ ... OPC_DCLO:
1.1.1.6 ! root 6227: check_insn(env, ctx, ISA_MIPS64);
! 6228: check_mips_64(ctx);
1.1.1.5 root 6229: gen_cl(ctx, op1, rd, rs);
6230: break;
6231: #endif
1.1 root 6232: default: /* Invalid */
6233: MIPS_INVAL("special2");
6234: generate_exception(ctx, EXCP_RI);
6235: break;
6236: }
6237: break;
1.1.1.5 root 6238: case OPC_SPECIAL3:
1.1.1.6 ! root 6239: op1 = MASK_SPECIAL3(ctx->opcode);
! 6240: switch (op1) {
! 6241: case OPC_EXT:
! 6242: case OPC_INS:
! 6243: check_insn(env, ctx, ISA_MIPS32R2);
! 6244: gen_bitops(ctx, op1, rt, rs, sa, rd);
! 6245: break;
! 6246: case OPC_BSHFL:
! 6247: check_insn(env, ctx, ISA_MIPS32R2);
! 6248: op2 = MASK_BSHFL(ctx->opcode);
! 6249: switch (op2) {
! 6250: case OPC_WSBH:
! 6251: GEN_LOAD_REG_T1(rt);
! 6252: gen_op_wsbh();
! 6253: break;
! 6254: case OPC_SEB:
! 6255: GEN_LOAD_REG_T1(rt);
! 6256: gen_op_seb();
! 6257: break;
! 6258: case OPC_SEH:
! 6259: GEN_LOAD_REG_T1(rt);
! 6260: gen_op_seh();
! 6261: break;
! 6262: default: /* Invalid */
! 6263: MIPS_INVAL("bshfl");
! 6264: generate_exception(ctx, EXCP_RI);
! 6265: break;
! 6266: }
! 6267: GEN_STORE_T0_REG(rd);
! 6268: break;
! 6269: case OPC_RDHWR:
! 6270: check_insn(env, ctx, ISA_MIPS32R2);
! 6271: switch (rd) {
! 6272: case 0:
! 6273: save_cpu_state(ctx, 1);
! 6274: gen_op_rdhwr_cpunum();
! 6275: break;
! 6276: case 1:
! 6277: save_cpu_state(ctx, 1);
! 6278: gen_op_rdhwr_synci_step();
! 6279: break;
! 6280: case 2:
! 6281: save_cpu_state(ctx, 1);
! 6282: gen_op_rdhwr_cc();
! 6283: break;
! 6284: case 3:
! 6285: save_cpu_state(ctx, 1);
! 6286: gen_op_rdhwr_ccres();
! 6287: break;
! 6288: case 29:
! 6289: #if defined (CONFIG_USER_ONLY)
! 6290: gen_op_tls_value();
! 6291: break;
! 6292: #endif
! 6293: default: /* Invalid */
! 6294: MIPS_INVAL("rdhwr");
! 6295: generate_exception(ctx, EXCP_RI);
! 6296: break;
! 6297: }
! 6298: GEN_STORE_T0_REG(rt);
! 6299: break;
! 6300: case OPC_FORK:
! 6301: check_insn(env, ctx, ASE_MT);
! 6302: GEN_LOAD_REG_T0(rt);
! 6303: GEN_LOAD_REG_T1(rs);
! 6304: gen_op_fork();
! 6305: break;
! 6306: case OPC_YIELD:
! 6307: check_insn(env, ctx, ASE_MT);
! 6308: GEN_LOAD_REG_T0(rs);
! 6309: gen_op_yield();
! 6310: GEN_STORE_T0_REG(rd);
! 6311: break;
! 6312: #if defined(TARGET_MIPS64)
! 6313: case OPC_DEXTM ... OPC_DEXT:
! 6314: case OPC_DINSM ... OPC_DINS:
! 6315: check_insn(env, ctx, ISA_MIPS64R2);
! 6316: check_mips_64(ctx);
1.1.1.5 root 6317: gen_bitops(ctx, op1, rt, rs, sa, rd);
6318: break;
1.1.1.6 ! root 6319: case OPC_DBSHFL:
! 6320: check_insn(env, ctx, ISA_MIPS64R2);
! 6321: check_mips_64(ctx);
! 6322: op2 = MASK_DBSHFL(ctx->opcode);
1.1.1.5 root 6323: switch (op2) {
1.1.1.6 ! root 6324: case OPC_DSBH:
! 6325: GEN_LOAD_REG_T1(rt);
! 6326: gen_op_dsbh();
1.1.1.5 root 6327: break;
1.1.1.6 ! root 6328: case OPC_DSHD:
! 6329: GEN_LOAD_REG_T1(rt);
! 6330: gen_op_dshd();
1.1.1.5 root 6331: break;
6332: default: /* Invalid */
6333: MIPS_INVAL("dbshfl");
6334: generate_exception(ctx, EXCP_RI);
6335: break;
1.1.1.6 ! root 6336: }
! 6337: GEN_STORE_T0_REG(rd);
! 6338: break;
1.1.1.5 root 6339: #endif
6340: default: /* Invalid */
6341: MIPS_INVAL("special3");
6342: generate_exception(ctx, EXCP_RI);
6343: break;
6344: }
6345: break;
6346: case OPC_REGIMM:
6347: op1 = MASK_REGIMM(ctx->opcode);
1.1 root 6348: switch (op1) {
1.1.1.5 root 6349: case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
6350: case OPC_BLTZAL ... OPC_BGEZALL:
6351: gen_compute_branch(ctx, op1, rs, -1, imm << 2);
1.1 root 6352: return;
1.1.1.5 root 6353: case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
6354: case OPC_TNEI:
6355: gen_trap(ctx, op1, rs, -1, imm);
6356: break;
6357: case OPC_SYNCI:
1.1.1.6 ! root 6358: check_insn(env, ctx, ISA_MIPS32R2);
! 6359: /* Treat as NOP. */
1.1 root 6360: break;
6361: default: /* Invalid */
1.1.1.6 ! root 6362: MIPS_INVAL("regimm");
1.1 root 6363: generate_exception(ctx, EXCP_RI);
6364: break;
6365: }
6366: break;
1.1.1.5 root 6367: case OPC_CP0:
1.1.1.6 ! root 6368: check_cp0_enabled(ctx);
1.1.1.5 root 6369: op1 = MASK_CP0(ctx->opcode);
1.1 root 6370: switch (op1) {
1.1.1.5 root 6371: case OPC_MFC0:
6372: case OPC_MTC0:
1.1.1.6 ! root 6373: case OPC_MFTR:
! 6374: case OPC_MTTR:
! 6375: #if defined(TARGET_MIPS64)
1.1.1.5 root 6376: case OPC_DMFC0:
6377: case OPC_DMTC0:
6378: #endif
1.1.1.6 ! root 6379: gen_cp0(env, ctx, op1, rt, rd);
1.1.1.5 root 6380: break;
6381: case OPC_C0_FIRST ... OPC_C0_LAST:
1.1.1.6 ! root 6382: gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
1.1.1.5 root 6383: break;
6384: case OPC_MFMC0:
6385: op2 = MASK_MFMC0(ctx->opcode);
6386: switch (op2) {
1.1.1.6 ! root 6387: case OPC_DMT:
! 6388: check_insn(env, ctx, ASE_MT);
! 6389: gen_op_dmt();
! 6390: break;
! 6391: case OPC_EMT:
! 6392: check_insn(env, ctx, ASE_MT);
! 6393: gen_op_emt();
! 6394: break;
! 6395: case OPC_DVPE:
! 6396: check_insn(env, ctx, ASE_MT);
! 6397: gen_op_dvpe();
! 6398: break;
! 6399: case OPC_EVPE:
! 6400: check_insn(env, ctx, ASE_MT);
! 6401: gen_op_evpe();
! 6402: break;
1.1.1.5 root 6403: case OPC_DI:
1.1.1.6 ! root 6404: check_insn(env, ctx, ISA_MIPS32R2);
! 6405: save_cpu_state(ctx, 1);
1.1.1.5 root 6406: gen_op_di();
6407: /* Stop translation as we may have switched the execution mode */
6408: ctx->bstate = BS_STOP;
6409: break;
6410: case OPC_EI:
1.1.1.6 ! root 6411: check_insn(env, ctx, ISA_MIPS32R2);
! 6412: save_cpu_state(ctx, 1);
1.1.1.5 root 6413: gen_op_ei();
6414: /* Stop translation as we may have switched the execution mode */
6415: ctx->bstate = BS_STOP;
6416: break;
6417: default: /* Invalid */
1.1.1.6 ! root 6418: MIPS_INVAL("mfmc0");
1.1.1.5 root 6419: generate_exception(ctx, EXCP_RI);
6420: break;
6421: }
1.1.1.6 ! root 6422: GEN_STORE_T0_REG(rt);
1.1 root 6423: break;
1.1.1.5 root 6424: case OPC_RDPGPR:
1.1.1.6 ! root 6425: check_insn(env, ctx, ISA_MIPS32R2);
! 6426: GEN_LOAD_SRSREG_TN(T0, rt);
! 6427: GEN_STORE_T0_REG(rd);
! 6428: break;
1.1.1.5 root 6429: case OPC_WRPGPR:
1.1.1.6 ! root 6430: check_insn(env, ctx, ISA_MIPS32R2);
! 6431: GEN_LOAD_REG_T0(rt);
! 6432: GEN_STORE_TN_SRSREG(rd, T0);
! 6433: break;
1.1 root 6434: default:
1.1.1.6 ! root 6435: MIPS_INVAL("cp0");
1.1.1.5 root 6436: generate_exception(ctx, EXCP_RI);
1.1 root 6437: break;
6438: }
6439: break;
1.1.1.5 root 6440: case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
1.1.1.6 ! root 6441: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 6442: break;
6443: case OPC_J ... OPC_JAL: /* Jump */
6444: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
6445: gen_compute_branch(ctx, op, rs, rt, offset);
6446: return;
6447: case OPC_BEQ ... OPC_BGTZ: /* Branch */
6448: case OPC_BEQL ... OPC_BGTZL:
6449: gen_compute_branch(ctx, op, rs, rt, imm << 2);
6450: return;
6451: case OPC_LB ... OPC_LWR: /* Load and stores */
6452: case OPC_SB ... OPC_SW:
6453: case OPC_SWR:
6454: case OPC_LL:
6455: case OPC_SC:
6456: gen_ldst(ctx, op, rt, rs, imm);
6457: break;
6458: case OPC_CACHE:
1.1.1.6 ! root 6459: check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
! 6460: /* Treat as NOP. */
! 6461: break;
1.1.1.5 root 6462: case OPC_PREF:
1.1.1.6 ! root 6463: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
! 6464: /* Treat as NOP. */
1.1 root 6465: break;
1.1.1.2 root 6466:
1.1.1.6 ! root 6467: /* Floating point (COP1). */
1.1.1.5 root 6468: case OPC_LWC1:
6469: case OPC_LDC1:
6470: case OPC_SWC1:
6471: case OPC_SDC1:
1.1.1.6 ! root 6472: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
! 6473: save_cpu_state(ctx, 1);
! 6474: check_cp1_enabled(ctx);
! 6475: gen_flt_ldst(ctx, op, rt, rs, imm);
! 6476: } else {
! 6477: generate_exception_err(ctx, EXCP_CpU, 1);
! 6478: }
1.1.1.4 root 6479: break;
6480:
1.1.1.5 root 6481: case OPC_CP1:
1.1.1.6 ! root 6482: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
! 6483: save_cpu_state(ctx, 1);
! 6484: check_cp1_enabled(ctx);
! 6485: op1 = MASK_CP1(ctx->opcode);
! 6486: switch (op1) {
! 6487: case OPC_MFHC1:
! 6488: case OPC_MTHC1:
! 6489: check_insn(env, ctx, ISA_MIPS32R2);
! 6490: case OPC_MFC1:
! 6491: case OPC_CFC1:
! 6492: case OPC_MTC1:
! 6493: case OPC_CTC1:
! 6494: gen_cp1(ctx, op1, rt, rd);
! 6495: break;
! 6496: #if defined(TARGET_MIPS64)
! 6497: case OPC_DMFC1:
! 6498: case OPC_DMTC1:
! 6499: check_insn(env, ctx, ISA_MIPS3);
! 6500: gen_cp1(ctx, op1, rt, rd);
! 6501: break;
1.1.1.5 root 6502: #endif
1.1.1.6 ! root 6503: case OPC_BC1ANY2:
! 6504: case OPC_BC1ANY4:
! 6505: check_cop1x(ctx);
! 6506: check_insn(env, ctx, ASE_MIPS3D);
! 6507: /* fall through */
! 6508: case OPC_BC1:
! 6509: gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
! 6510: (rt >> 2) & 0x7, imm << 2);
! 6511: return;
! 6512: case OPC_S_FMT:
! 6513: case OPC_D_FMT:
! 6514: case OPC_W_FMT:
! 6515: case OPC_L_FMT:
! 6516: case OPC_PS_FMT:
! 6517: gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
! 6518: (imm >> 8) & 0x7);
! 6519: break;
! 6520: default:
! 6521: MIPS_INVAL("cp1");
! 6522: generate_exception (ctx, EXCP_RI);
! 6523: break;
! 6524: }
! 6525: } else {
! 6526: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.4 root 6527: }
1.1.1.2 root 6528: break;
6529:
6530: /* COP2. */
1.1.1.5 root 6531: case OPC_LWC2:
6532: case OPC_LDC2:
6533: case OPC_SWC2:
6534: case OPC_SDC2:
6535: case OPC_CP2:
6536: /* COP2: Not implemented. */
1.1.1.2 root 6537: generate_exception_err(ctx, EXCP_CpU, 2);
6538: break;
6539:
1.1.1.5 root 6540: case OPC_CP3:
1.1.1.6 ! root 6541: if (env->CP0_Config1 & (1 << CP0C1_FP)) {
! 6542: save_cpu_state(ctx, 1);
! 6543: check_cp1_enabled(ctx);
! 6544: op1 = MASK_CP3(ctx->opcode);
! 6545: switch (op1) {
! 6546: case OPC_LWXC1:
! 6547: case OPC_LDXC1:
! 6548: case OPC_LUXC1:
! 6549: case OPC_SWXC1:
! 6550: case OPC_SDXC1:
! 6551: case OPC_SUXC1:
! 6552: gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
! 6553: break;
! 6554: case OPC_PREFX:
! 6555: /* Treat as NOP. */
! 6556: break;
! 6557: case OPC_ALNV_PS:
! 6558: case OPC_MADD_S:
! 6559: case OPC_MADD_D:
! 6560: case OPC_MADD_PS:
! 6561: case OPC_MSUB_S:
! 6562: case OPC_MSUB_D:
! 6563: case OPC_MSUB_PS:
! 6564: case OPC_NMADD_S:
! 6565: case OPC_NMADD_D:
! 6566: case OPC_NMADD_PS:
! 6567: case OPC_NMSUB_S:
! 6568: case OPC_NMSUB_D:
! 6569: case OPC_NMSUB_PS:
! 6570: gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
! 6571: break;
! 6572: default:
! 6573: MIPS_INVAL("cp3");
! 6574: generate_exception (ctx, EXCP_RI);
! 6575: break;
! 6576: }
! 6577: } else {
! 6578: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.5 root 6579: }
1.1.1.2 root 6580: break;
6581:
1.1.1.6 ! root 6582: #if defined(TARGET_MIPS64)
1.1.1.5 root 6583: /* MIPS64 opcodes */
6584: case OPC_LWU:
6585: case OPC_LDL ... OPC_LDR:
6586: case OPC_SDL ... OPC_SDR:
6587: case OPC_LLD:
6588: case OPC_LD:
6589: case OPC_SCD:
6590: case OPC_SD:
1.1.1.6 ! root 6591: check_insn(env, ctx, ISA_MIPS3);
! 6592: check_mips_64(ctx);
1.1.1.5 root 6593: gen_ldst(ctx, op, rt, rs, imm);
6594: break;
6595: case OPC_DADDI ... OPC_DADDIU:
1.1.1.6 ! root 6596: check_insn(env, ctx, ISA_MIPS3);
! 6597: check_mips_64(ctx);
! 6598: gen_arith_imm(env, ctx, op, rt, rs, imm);
1.1.1.5 root 6599: break;
6600: #endif
6601: case OPC_JALX:
1.1.1.6 ! root 6602: check_insn(env, ctx, ASE_MIPS16);
1.1.1.5 root 6603: /* MIPS16: Not implemented. */
6604: case OPC_MDMX:
1.1.1.6 ! root 6605: check_insn(env, ctx, ASE_MDMX);
1.1.1.5 root 6606: /* MDMX: Not implemented. */
1.1 root 6607: default: /* Invalid */
1.1.1.6 ! root 6608: MIPS_INVAL("major opcode");
1.1 root 6609: generate_exception(ctx, EXCP_RI);
6610: break;
6611: }
1.1.1.2 root 6612: if (ctx->hflags & MIPS_HFLAG_BMASK) {
1.1.1.6 ! root 6613: int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
1.1 root 6614: /* Branches completion */
1.1.1.2 root 6615: ctx->hflags &= ~MIPS_HFLAG_BMASK;
1.1 root 6616: ctx->bstate = BS_BRANCH;
6617: save_cpu_state(ctx, 0);
1.1.1.6 ! root 6618: switch (hflags) {
1.1 root 6619: case MIPS_HFLAG_B:
6620: /* unconditional branch */
6621: MIPS_DEBUG("unconditional branch");
1.1.1.2 root 6622: gen_goto_tb(ctx, 0, ctx->btarget);
1.1 root 6623: break;
6624: case MIPS_HFLAG_BL:
6625: /* blikely taken case */
6626: MIPS_DEBUG("blikely branch taken");
1.1.1.2 root 6627: gen_goto_tb(ctx, 0, ctx->btarget);
1.1 root 6628: break;
6629: case MIPS_HFLAG_BC:
6630: /* Conditional branch */
6631: MIPS_DEBUG("conditional branch");
1.1.1.2 root 6632: {
6633: int l1;
6634: l1 = gen_new_label();
6635: gen_op_jnz_T2(l1);
6636: gen_goto_tb(ctx, 1, ctx->pc + 4);
6637: gen_set_label(l1);
6638: gen_goto_tb(ctx, 0, ctx->btarget);
6639: }
1.1 root 6640: break;
6641: case MIPS_HFLAG_BR:
6642: /* unconditional branch to register */
6643: MIPS_DEBUG("branch to register");
6644: gen_op_breg();
1.1.1.6 ! root 6645: gen_op_reset_T0();
! 6646: gen_op_exit_tb();
1.1 root 6647: break;
6648: default:
6649: MIPS_DEBUG("unknown branch");
6650: break;
6651: }
6652: }
6653: }
6654:
1.1.1.6 ! root 6655: static always_inline int
! 6656: gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
! 6657: int search_pc)
1.1 root 6658: {
1.1.1.6 ! root 6659: DisasContext ctx;
1.1 root 6660: target_ulong pc_start;
6661: uint16_t *gen_opc_end;
6662: int j, lj = -1;
6663:
1.1.1.2 root 6664: if (search_pc && loglevel)
1.1.1.4 root 6665: fprintf (logfile, "search pc %d\n", search_pc);
1.1.1.2 root 6666:
1.1 root 6667: pc_start = tb->pc;
6668: gen_opc_ptr = gen_opc_buf;
6669: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6670: gen_opparam_ptr = gen_opparam_buf;
1.1.1.2 root 6671: nb_gen_labels = 0;
1.1 root 6672: ctx.pc = pc_start;
1.1.1.2 root 6673: ctx.saved_pc = -1;
1.1 root 6674: ctx.tb = tb;
6675: ctx.bstate = BS_NONE;
1.1.1.2 root 6676: /* Restore delay slot state from the tb context. */
1.1.1.6 ! root 6677: ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
! 6678: restore_cpu_state(env, &ctx);
1.1 root 6679: #if defined(CONFIG_USER_ONLY)
1.1.1.6 ! root 6680: ctx.mem_idx = MIPS_HFLAG_UM;
1.1 root 6681: #else
1.1.1.6 ! root 6682: ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
1.1 root 6683: #endif
6684: #ifdef DEBUG_DISAS
6685: if (loglevel & CPU_LOG_TB_CPU) {
6686: fprintf(logfile, "------------------------------------------------\n");
1.1.1.2 root 6687: /* FIXME: This may print out stale hflags from env... */
1.1 root 6688: cpu_dump_state(env, logfile, fprintf, 0);
6689: }
6690: #endif
1.1.1.6 ! root 6691: #ifdef MIPS_DEBUG_DISAS
1.1 root 6692: if (loglevel & CPU_LOG_TB_IN_ASM)
1.1.1.6 ! root 6693: fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
1.1.1.2 root 6694: tb, ctx.mem_idx, ctx.hflags);
1.1 root 6695: #endif
6696: while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1.1.1.2 root 6697: if (env->nb_breakpoints > 0) {
6698: for(j = 0; j < env->nb_breakpoints; j++) {
6699: if (env->breakpoints[j] == ctx.pc) {
1.1.1.6 ! root 6700: save_cpu_state(&ctx, 1);
1.1.1.2 root 6701: ctx.bstate = BS_BRANCH;
6702: gen_op_debug();
1.1.1.6 ! root 6703: /* Include the breakpoint location or the tb won't
! 6704: * be flushed when it must be. */
! 6705: ctx.pc += 4;
1.1.1.2 root 6706: goto done_generating;
6707: }
6708: }
6709: }
6710:
1.1 root 6711: if (search_pc) {
6712: j = gen_opc_ptr - gen_opc_buf;
6713: if (lj < j) {
6714: lj++;
6715: while (lj < j)
6716: gen_opc_instr_start[lj++] = 0;
6717: }
1.1.1.2 root 6718: gen_opc_pc[lj] = ctx.pc;
6719: gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
6720: gen_opc_instr_start[lj] = 1;
1.1 root 6721: }
6722: ctx.opcode = ldl_code(ctx.pc);
1.1.1.6 ! root 6723: decode_opc(env, &ctx);
1.1 root 6724: ctx.pc += 4;
1.1.1.2 root 6725:
6726: if (env->singlestep_enabled)
6727: break;
6728:
1.1 root 6729: if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
6730: break;
1.1.1.2 root 6731:
1.1 root 6732: #if defined (MIPS_SINGLE_STEP)
6733: break;
6734: #endif
6735: }
1.1.1.2 root 6736: if (env->singlestep_enabled) {
1.1.1.6 ! root 6737: save_cpu_state(&ctx, ctx.bstate == BS_NONE);
1.1.1.2 root 6738: gen_op_debug();
1.1.1.6 ! root 6739: } else {
! 6740: switch (ctx.bstate) {
! 6741: case BS_STOP:
! 6742: gen_op_interrupt_restart();
! 6743: gen_goto_tb(&ctx, 0, ctx.pc);
! 6744: break;
! 6745: case BS_NONE:
! 6746: save_cpu_state(&ctx, 0);
! 6747: gen_goto_tb(&ctx, 0, ctx.pc);
! 6748: break;
! 6749: case BS_EXCP:
! 6750: gen_op_interrupt_restart();
! 6751: gen_op_reset_T0();
! 6752: gen_op_exit_tb();
! 6753: break;
! 6754: case BS_BRANCH:
! 6755: default:
! 6756: break;
! 6757: }
1.1 root 6758: }
1.1.1.2 root 6759: done_generating:
1.1.1.6 ! root 6760: ctx.last_T0_store = NULL;
1.1 root 6761: *gen_opc_ptr = INDEX_op_end;
6762: if (search_pc) {
6763: j = gen_opc_ptr - gen_opc_buf;
6764: lj++;
6765: while (lj <= j)
6766: gen_opc_instr_start[lj++] = 0;
6767: } else {
6768: tb->size = ctx.pc - pc_start;
6769: }
6770: #ifdef DEBUG_DISAS
6771: #if defined MIPS_DEBUG_DISAS
6772: if (loglevel & CPU_LOG_TB_IN_ASM)
6773: fprintf(logfile, "\n");
6774: #endif
6775: if (loglevel & CPU_LOG_TB_IN_ASM) {
6776: fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
1.1.1.6 ! root 6777: target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1.1 root 6778: fprintf(logfile, "\n");
6779: }
6780: if (loglevel & CPU_LOG_TB_OP) {
6781: fprintf(logfile, "OP:\n");
6782: dump_ops(gen_opc_buf, gen_opparam_buf);
6783: fprintf(logfile, "\n");
6784: }
6785: if (loglevel & CPU_LOG_TB_CPU) {
6786: fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
6787: }
6788: #endif
1.1.1.6 ! root 6789:
1.1 root 6790: return 0;
6791: }
6792:
6793: int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6794: {
6795: return gen_intermediate_code_internal(env, tb, 0);
6796: }
6797:
6798: int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6799: {
6800: return gen_intermediate_code_internal(env, tb, 1);
6801: }
6802:
1.1.1.6 ! root 6803: void fpu_dump_state(CPUState *env, FILE *f,
1.1.1.4 root 6804: int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
6805: int flags)
6806: {
6807: int i;
1.1.1.6 ! root 6808: int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
1.1.1.4 root 6809:
1.1.1.6 ! root 6810: #define printfpr(fp) \
! 6811: do { \
! 6812: if (is_fpu64) \
! 6813: fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
! 6814: (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
! 6815: (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
! 6816: else { \
! 6817: fpr_t tmp; \
! 6818: tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
! 6819: tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
! 6820: fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
! 6821: tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
! 6822: tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
! 6823: } \
1.1.1.4 root 6824: } while(0)
6825:
1.1.1.6 ! root 6826:
! 6827: fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
! 6828: env->fpu->fcr0, env->fpu->fcr31, is_fpu64, env->fpu->fp_status,
! 6829: get_float_exception_flags(&env->fpu->fp_status));
! 6830: fpu_fprintf(f, "FT0: "); printfpr(&env->fpu->ft0);
! 6831: fpu_fprintf(f, "FT1: "); printfpr(&env->fpu->ft1);
! 6832: fpu_fprintf(f, "FT2: "); printfpr(&env->fpu->ft2);
! 6833: for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
! 6834: fpu_fprintf(f, "%3s: ", fregnames[i]);
! 6835: printfpr(&env->fpu->fpr[i]);
1.1.1.4 root 6836: }
6837:
6838: #undef printfpr
6839: }
6840:
1.1.1.5 root 6841: void dump_fpu (CPUState *env)
1.1.1.4 root 6842: {
1.1.1.6 ! root 6843: if (loglevel) {
! 6844: fprintf(logfile, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
! 6845: env->PC[env->current_tc], env->HI[0][env->current_tc], env->LO[0][env->current_tc], env->hflags, env->btarget, env->bcond);
1.1.1.4 root 6846: fpu_dump_state(env, logfile, fprintf, 0);
6847: }
6848: }
1.1.1.5 root 6849:
1.1.1.6 ! root 6850: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 6851: /* Debug help: The architecture requires 32bit code to maintain proper
6852: sign-extened values on 64bit machines. */
6853:
6854: #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
6855:
6856: void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
6857: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6858: int flags)
6859: {
6860: int i;
6861:
1.1.1.6 ! root 6862: if (!SIGN_EXT_P(env->PC[env->current_tc]))
! 6863: cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC[env->current_tc]);
! 6864: if (!SIGN_EXT_P(env->HI[0][env->current_tc]))
! 6865: cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI[0][env->current_tc]);
! 6866: if (!SIGN_EXT_P(env->LO[0][env->current_tc]))
! 6867: cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO[0][env->current_tc]);
1.1.1.5 root 6868: if (!SIGN_EXT_P(env->btarget))
1.1.1.6 ! root 6869: cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
1.1.1.5 root 6870:
6871: for (i = 0; i < 32; i++) {
1.1.1.6 ! root 6872: if (!SIGN_EXT_P(env->gpr[i][env->current_tc]))
! 6873: cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i][env->current_tc]);
1.1.1.5 root 6874: }
6875:
6876: if (!SIGN_EXT_P(env->CP0_EPC))
1.1.1.6 ! root 6877: cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
1.1.1.5 root 6878: if (!SIGN_EXT_P(env->CP0_LLAddr))
1.1.1.6 ! root 6879: cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
1.1.1.5 root 6880: }
6881: #endif
6882:
1.1.1.6 ! root 6883: void cpu_dump_state (CPUState *env, FILE *f,
1.1 root 6884: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6885: int flags)
6886: {
6887: int i;
1.1.1.6 ! root 6888:
! 6889: 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",
! 6890: env->PC[env->current_tc], env->HI[env->current_tc], env->LO[env->current_tc], env->hflags, env->btarget, env->bcond);
1.1 root 6891: for (i = 0; i < 32; i++) {
6892: if ((i & 3) == 0)
6893: cpu_fprintf(f, "GPR%02d:", i);
1.1.1.6 ! root 6894: cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i][env->current_tc]);
1.1 root 6895: if ((i & 3) == 3)
6896: cpu_fprintf(f, "\n");
6897: }
6898:
1.1.1.6 ! root 6899: cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
! 6900: env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
! 6901: cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
1.1 root 6902: env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
1.1.1.6 ! root 6903: if (env->hflags & MIPS_HFLAG_FPU)
1.1.1.5 root 6904: fpu_dump_state(env, f, cpu_fprintf, flags);
1.1.1.6 ! root 6905: #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
1.1.1.5 root 6906: cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
1.1.1.4 root 6907: #endif
1.1 root 6908: }
6909:
1.1.1.6 ! root 6910: #include "translate_init.c"
! 6911:
! 6912: CPUMIPSState *cpu_mips_init (const char *cpu_model)
1.1 root 6913: {
6914: CPUMIPSState *env;
1.1.1.6 ! root 6915: const mips_def_t *def;
1.1 root 6916:
1.1.1.6 ! root 6917: def = cpu_mips_find_by_name(cpu_model);
! 6918: if (!def)
! 6919: return NULL;
1.1 root 6920: env = qemu_mallocz(sizeof(CPUMIPSState));
6921: if (!env)
6922: return NULL;
1.1.1.6 ! root 6923: env->cpu_model = def;
! 6924:
1.1.1.2 root 6925: cpu_exec_init(env);
1.1.1.6 ! root 6926: env->cpu_model_str = cpu_model;
1.1.1.5 root 6927: cpu_reset(env);
6928: return env;
6929: }
6930:
6931: void cpu_reset (CPUMIPSState *env)
6932: {
6933: memset(env, 0, offsetof(CPUMIPSState, breakpoints));
6934:
1.1 root 6935: tlb_flush(env, 1);
1.1.1.5 root 6936:
1.1 root 6937: /* Minimal init */
1.1.1.5 root 6938: #if !defined(CONFIG_USER_ONLY)
6939: if (env->hflags & MIPS_HFLAG_BMASK) {
6940: /* If the exception was raised from a delay slot,
6941: * come back to the jump. */
1.1.1.6 ! root 6942: env->CP0_ErrorEPC = env->PC[env->current_tc] - 4;
1.1.1.5 root 6943: } else {
1.1.1.6 ! root 6944: env->CP0_ErrorEPC = env->PC[env->current_tc];
1.1.1.5 root 6945: }
1.1.1.6 ! root 6946: env->PC[env->current_tc] = (int32_t)0xBFC00000;
1.1 root 6947: env->CP0_Wired = 0;
1.1.1.5 root 6948: /* SMP not implemented */
6949: env->CP0_EBase = 0x80000000;
6950: env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
1.1.1.6 ! root 6951: /* vectored interrupts not implemented, timer on int 7,
! 6952: no performance counters. */
! 6953: env->CP0_IntCtl = 0xe0000000;
! 6954: {
! 6955: int i;
! 6956:
! 6957: for (i = 0; i < 7; i++) {
! 6958: env->CP0_WatchLo[i] = 0;
! 6959: env->CP0_WatchHi[i] = 0x80000000;
! 6960: }
! 6961: env->CP0_WatchLo[7] = 0;
! 6962: env->CP0_WatchHi[7] = 0;
! 6963: }
1.1 root 6964: /* Count register increments in debug mode, EJTAG version 1 */
6965: env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
1.1.1.5 root 6966: #endif
1.1 root 6967: env->exception_index = EXCP_NONE;
1.1.1.2 root 6968: #if defined(CONFIG_USER_ONLY)
1.1.1.6 ! root 6969: env->hflags = MIPS_HFLAG_UM;
1.1.1.5 root 6970: env->user_mode_only = 1;
1.1.1.6 ! root 6971: #else
! 6972: env->hflags = MIPS_HFLAG_CP0;
1.1.1.2 root 6973: #endif
1.1.1.6 ! root 6974: cpu_mips_register(env, env->cpu_model);
1.1 root 6975: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.