|
|
1.1 root 1: /*
2: * MIPS32 emulation for qemu: main translation routines.
3: *
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,
! 145: OPC_SRLV = 0x06 | OPC_SPECIAL,
! 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:
! 217: /* REGIMM (rt field) opcodes */
! 218: #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
! 219:
! 220: enum {
! 221: OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
! 222: OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
! 223: OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
! 224: OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
! 225: OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
! 226: OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
! 227: OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
! 228: OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
! 229: OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
! 230: OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
! 231: OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
! 232: OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
! 233: OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
! 234: OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
! 235: OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
1.1 root 236: };
237:
1.1.1.5 ! root 238: /* Special2 opcodes */
! 239: #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
! 240:
1.1 root 241: enum {
1.1.1.5 ! root 242: /* Multiply & xxx operations */
! 243: OPC_MADD = 0x00 | OPC_SPECIAL2,
! 244: OPC_MADDU = 0x01 | OPC_SPECIAL2,
! 245: OPC_MUL = 0x02 | OPC_SPECIAL2,
! 246: OPC_MSUB = 0x04 | OPC_SPECIAL2,
! 247: OPC_MSUBU = 0x05 | OPC_SPECIAL2,
1.1 root 248: /* Misc */
1.1.1.5 ! root 249: OPC_CLZ = 0x20 | OPC_SPECIAL2,
! 250: OPC_CLO = 0x21 | OPC_SPECIAL2,
! 251: OPC_DCLZ = 0x24 | OPC_SPECIAL2,
! 252: OPC_DCLO = 0x25 | OPC_SPECIAL2,
1.1 root 253: /* Special */
1.1.1.5 ! root 254: OPC_SDBBP = 0x3F | OPC_SPECIAL2,
! 255: };
! 256:
! 257: /* Special3 opcodes */
! 258: #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
! 259:
! 260: enum {
! 261: OPC_EXT = 0x00 | OPC_SPECIAL3,
! 262: OPC_DEXTM = 0x01 | OPC_SPECIAL3,
! 263: OPC_DEXTU = 0x02 | OPC_SPECIAL3,
! 264: OPC_DEXT = 0x03 | OPC_SPECIAL3,
! 265: OPC_INS = 0x04 | OPC_SPECIAL3,
! 266: OPC_DINSM = 0x05 | OPC_SPECIAL3,
! 267: OPC_DINSU = 0x06 | OPC_SPECIAL3,
! 268: OPC_DINS = 0x07 | OPC_SPECIAL3,
! 269: OPC_BSHFL = 0x20 | OPC_SPECIAL3,
! 270: OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
! 271: OPC_RDHWR = 0x3B | OPC_SPECIAL3,
1.1 root 272: };
273:
1.1.1.5 ! root 274: /* BSHFL opcodes */
! 275: #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
! 276:
1.1 root 277: enum {
1.1.1.5 ! root 278: OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
! 279: OPC_SEB = (0x10 << 6) | OPC_BSHFL,
! 280: OPC_SEH = (0x18 << 6) | OPC_BSHFL,
1.1 root 281: };
282:
1.1.1.5 ! root 283: /* DBSHFL opcodes */
! 284: #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
! 285:
1.1 root 286: enum {
1.1.1.5 ! root 287: OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
! 288: OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
1.1 root 289: };
290:
1.1.1.5 ! root 291: /* Coprocessor 0 (rs field) */
! 292: #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
! 293:
1.1.1.4 root 294: enum {
1.1.1.5 ! root 295: OPC_MFC0 = (0x00 << 21) | OPC_CP0,
! 296: OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
! 297: OPC_MTC0 = (0x04 << 21) | OPC_CP0,
! 298: OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
! 299: OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
! 300: OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
! 301: OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
! 302: OPC_C0 = (0x10 << 21) | OPC_CP0,
! 303: OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
! 304: OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
1.1.1.4 root 305: };
1.1.1.5 ! root 306:
! 307: /* MFMC0 opcodes */
! 308: #define MASK_MFMC0(op) MASK_CP0(op) | (op & ((0x0C << 11) | (1 << 5)))
! 309:
! 310: enum {
! 311: OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
! 312: OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
! 313: };
! 314:
! 315: /* Coprocessor 0 (with rs == C0) */
! 316: #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
! 317:
! 318: enum {
! 319: OPC_TLBR = 0x01 | OPC_C0,
! 320: OPC_TLBWI = 0x02 | OPC_C0,
! 321: OPC_TLBWR = 0x06 | OPC_C0,
! 322: OPC_TLBP = 0x08 | OPC_C0,
! 323: OPC_RFE = 0x10 | OPC_C0,
! 324: OPC_ERET = 0x18 | OPC_C0,
! 325: OPC_DERET = 0x1F | OPC_C0,
! 326: OPC_WAIT = 0x20 | OPC_C0,
! 327: };
! 328:
! 329: /* Coprocessor 1 (rs field) */
! 330: #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
! 331:
! 332: enum {
! 333: OPC_MFC1 = (0x00 << 21) | OPC_CP1,
! 334: OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
! 335: OPC_CFC1 = (0x02 << 21) | OPC_CP1,
! 336: OPC_MFHCI = (0x03 << 21) | OPC_CP1,
! 337: OPC_MTC1 = (0x04 << 21) | OPC_CP1,
! 338: OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
! 339: OPC_CTC1 = (0x06 << 21) | OPC_CP1,
! 340: OPC_MTHCI = (0x07 << 21) | OPC_CP1,
! 341: OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
! 342: OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
! 343: OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
! 344: OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
! 345: OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
! 346: OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
! 347: OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
! 348: };
! 349:
! 350: enum {
! 351: OPC_BC1F = (0x00 << 16) | OPC_BC1,
! 352: OPC_BC1T = (0x01 << 16) | OPC_BC1,
! 353: OPC_BC1FL = (0x02 << 16) | OPC_BC1,
! 354: OPC_BC1TL = (0x03 << 16) | OPC_BC1,
! 355: };
! 356:
! 357: #define MASK_CP1_BCOND(op) MASK_CP1(op) | (op & (0x3 << 16))
! 358: #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
! 359:
! 360: #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
! 361: #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1.1.1.4 root 362:
1.1 root 363: const unsigned char *regnames[] =
364: { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
365: "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
366: "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
367: "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
368:
369: /* Warning: no function for r0 register (hard wired to zero) */
370: #define GEN32(func, NAME) \
371: static GenOpFunc *NAME ## _table [32] = { \
372: NULL, NAME ## 1, NAME ## 2, NAME ## 3, \
373: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
374: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
375: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
376: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
377: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
378: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
379: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
380: }; \
381: static inline void func(int n) \
382: { \
383: NAME ## _table[n](); \
384: }
385:
386: /* General purpose registers moves */
387: GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
388: GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
389: GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
390:
391: GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
392: GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
393:
1.1.1.4 root 394: #ifdef MIPS_USES_FPU
1.1.1.5 ! root 395:
! 396: static const char *fregnames[] =
1.1.1.4 root 397: { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
398: "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
399: "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
400: "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
401:
402: # define SFGEN32(func, NAME) \
403: static GenOpFunc *NAME ## _table [32] = { \
404: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
405: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
406: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
407: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
408: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
409: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
410: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
411: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
412: }; \
413: static inline void func(int n) \
414: { \
415: NAME ## _table[n](); \
416: }
417:
418: # define DFGEN32(func, NAME) \
419: static GenOpFunc *NAME ## _table [32] = { \
420: NAME ## 0, 0, NAME ## 2, 0, \
421: NAME ## 4, 0, NAME ## 6, 0, \
422: NAME ## 8, 0, NAME ## 10, 0, \
423: NAME ## 12, 0, NAME ## 14, 0, \
424: NAME ## 16, 0, NAME ## 18, 0, \
425: NAME ## 20, 0, NAME ## 22, 0, \
426: NAME ## 24, 0, NAME ## 26, 0, \
427: NAME ## 28, 0, NAME ## 30, 0, \
428: }; \
429: static inline void func(int n) \
430: { \
431: NAME ## _table[n](); \
432: }
433:
434: SFGEN32(gen_op_load_fpr_WT0, gen_op_load_fpr_WT0_fpr);
435: SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
436:
437: SFGEN32(gen_op_load_fpr_WT1, gen_op_load_fpr_WT1_fpr);
438: SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
439:
440: SFGEN32(gen_op_load_fpr_WT2, gen_op_load_fpr_WT2_fpr);
441: SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
442:
443: DFGEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fpr);
444: DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
445:
446: DFGEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fpr);
447: DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
448:
449: DFGEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fpr);
450: DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
451:
452: #define FOP_CONDS(fmt) \
453: static GenOpFunc * cond_ ## fmt ## _table[16] = { \
454: gen_op_cmp_ ## fmt ## _f, \
455: gen_op_cmp_ ## fmt ## _un, \
456: gen_op_cmp_ ## fmt ## _eq, \
457: gen_op_cmp_ ## fmt ## _ueq, \
458: gen_op_cmp_ ## fmt ## _olt, \
459: gen_op_cmp_ ## fmt ## _ult, \
460: gen_op_cmp_ ## fmt ## _ole, \
461: gen_op_cmp_ ## fmt ## _ule, \
462: gen_op_cmp_ ## fmt ## _sf, \
463: gen_op_cmp_ ## fmt ## _ngle, \
464: gen_op_cmp_ ## fmt ## _seq, \
465: gen_op_cmp_ ## fmt ## _ngl, \
466: gen_op_cmp_ ## fmt ## _lt, \
467: gen_op_cmp_ ## fmt ## _nge, \
468: gen_op_cmp_ ## fmt ## _le, \
469: gen_op_cmp_ ## fmt ## _ngt, \
470: }; \
471: static inline void gen_cmp_ ## fmt(int n) \
472: { \
473: cond_ ## fmt ## _table[n](); \
474: }
475:
476: FOP_CONDS(d)
477: FOP_CONDS(s)
478:
1.1.1.5 ! root 479: #endif /* MIPS_USES_FPU */
1.1.1.4 root 480:
1.1 root 481: typedef struct DisasContext {
482: struct TranslationBlock *tb;
483: target_ulong pc, saved_pc;
484: uint32_t opcode;
485: /* Routine used to access memory */
486: int mem_idx;
487: uint32_t hflags, saved_hflags;
488: uint32_t CP0_Status;
489: int bstate;
490: target_ulong btarget;
491: } DisasContext;
492:
493: enum {
494: BS_NONE = 0, /* We go out of the TB without reaching a branch or an
495: * exception condition
496: */
497: BS_STOP = 1, /* We want to stop translation for any reason */
498: BS_BRANCH = 2, /* We reached a branch condition */
499: BS_EXCP = 3, /* We reached an exception condition */
500: };
501:
502: #if defined MIPS_DEBUG_DISAS
503: #define MIPS_DEBUG(fmt, args...) \
504: do { \
505: if (loglevel & CPU_LOG_TB_IN_ASM) { \
1.1.1.5 ! root 506: fprintf(logfile, TLSZ ": %08x " fmt "\n", \
1.1 root 507: ctx->pc, ctx->opcode , ##args); \
508: } \
509: } while (0)
510: #else
511: #define MIPS_DEBUG(fmt, args...) do { } while(0)
512: #endif
513:
514: #define MIPS_INVAL(op) \
515: do { \
516: MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
517: ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
518: } while (0)
519:
520: #define GEN_LOAD_REG_TN(Tn, Rn) \
521: do { \
522: if (Rn == 0) { \
523: glue(gen_op_reset_, Tn)(); \
524: } else { \
525: glue(gen_op_load_gpr_, Tn)(Rn); \
526: } \
527: } while (0)
528:
529: #define GEN_LOAD_IMM_TN(Tn, Imm) \
530: do { \
531: if (Imm == 0) { \
532: glue(gen_op_reset_, Tn)(); \
533: } else { \
534: glue(gen_op_set_, Tn)(Imm); \
535: } \
536: } while (0)
537:
538: #define GEN_STORE_TN_REG(Rn, Tn) \
539: do { \
540: if (Rn != 0) { \
541: glue(glue(gen_op_store_, Tn),_gpr)(Rn); \
542: } \
543: } while (0)
544:
1.1.1.5 ! root 545: #define GEN_LOAD_FREG_FTN(FTn, Fn) \
1.1.1.4 root 546: do { \
547: glue(gen_op_load_fpr_, FTn)(Fn); \
548: } while (0)
549:
550: #define GEN_STORE_FTN_FREG(Fn, FTn) \
551: do { \
552: glue(gen_op_store_fpr_, FTn)(Fn); \
553: } while (0)
554:
1.1 root 555: static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
556: {
557: #if defined MIPS_DEBUG_DISAS
558: if (loglevel & CPU_LOG_TB_IN_ASM) {
559: fprintf(logfile, "hflags %08x saved %08x\n",
560: ctx->hflags, ctx->saved_hflags);
561: }
562: #endif
563: if (do_save_pc && ctx->pc != ctx->saved_pc) {
564: gen_op_save_pc(ctx->pc);
565: ctx->saved_pc = ctx->pc;
566: }
567: if (ctx->hflags != ctx->saved_hflags) {
568: gen_op_save_state(ctx->hflags);
569: ctx->saved_hflags = ctx->hflags;
570: if (ctx->hflags & MIPS_HFLAG_BR) {
571: gen_op_save_breg_target();
572: } else if (ctx->hflags & MIPS_HFLAG_B) {
573: gen_op_save_btarget(ctx->btarget);
574: } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
575: gen_op_save_bcond();
576: gen_op_save_btarget(ctx->btarget);
577: }
578: }
579: }
580:
1.1.1.2 root 581: static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
1.1 root 582: {
583: #if defined MIPS_DEBUG_DISAS
584: if (loglevel & CPU_LOG_TB_IN_ASM)
585: fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
586: #endif
587: save_cpu_state(ctx, 1);
1.1.1.2 root 588: if (err == 0)
589: gen_op_raise_exception(excp);
590: else
591: gen_op_raise_exception_err(excp, err);
1.1 root 592: ctx->bstate = BS_EXCP;
593: }
594:
1.1.1.2 root 595: static inline void generate_exception (DisasContext *ctx, int excp)
596: {
597: generate_exception_err (ctx, excp, 0);
598: }
599:
1.1 root 600: #if defined(CONFIG_USER_ONLY)
601: #define op_ldst(name) gen_op_##name##_raw()
602: #define OP_LD_TABLE(width)
603: #define OP_ST_TABLE(width)
604: #else
605: #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
606: #define OP_LD_TABLE(width) \
607: static GenOpFunc *gen_op_l##width[] = { \
608: &gen_op_l##width##_user, \
609: &gen_op_l##width##_kernel, \
610: }
611: #define OP_ST_TABLE(width) \
612: static GenOpFunc *gen_op_s##width[] = { \
613: &gen_op_s##width##_user, \
614: &gen_op_s##width##_kernel, \
615: }
616: #endif
617:
1.1.1.5 ! root 618: #ifdef MIPS_HAS_MIPS64
1.1 root 619: OP_LD_TABLE(d);
620: OP_LD_TABLE(dl);
621: OP_LD_TABLE(dr);
622: OP_ST_TABLE(d);
623: OP_ST_TABLE(dl);
624: OP_ST_TABLE(dr);
1.1.1.5 ! root 625: OP_LD_TABLE(ld);
! 626: OP_ST_TABLE(cd);
1.1 root 627: #endif
628: OP_LD_TABLE(w);
1.1.1.4 root 629: OP_LD_TABLE(wu);
1.1 root 630: OP_LD_TABLE(wl);
631: OP_LD_TABLE(wr);
632: OP_ST_TABLE(w);
633: OP_ST_TABLE(wl);
634: OP_ST_TABLE(wr);
635: OP_LD_TABLE(h);
636: OP_LD_TABLE(hu);
637: OP_ST_TABLE(h);
638: OP_LD_TABLE(b);
639: OP_LD_TABLE(bu);
640: OP_ST_TABLE(b);
641: OP_LD_TABLE(l);
642: OP_ST_TABLE(c);
1.1.1.4 root 643: #ifdef MIPS_USES_FPU
644: OP_LD_TABLE(wc1);
645: OP_ST_TABLE(wc1);
646: OP_LD_TABLE(dc1);
647: OP_ST_TABLE(dc1);
648: #endif
1.1 root 649:
650: /* Load and store */
1.1.1.5 ! root 651: static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1.1 root 652: int base, int16_t offset)
653: {
1.1.1.5 ! root 654: const char *opn = "unk";
1.1 root 655:
656: if (base == 0) {
657: GEN_LOAD_IMM_TN(T0, offset);
658: } else if (offset == 0) {
659: gen_op_load_gpr_T0(base);
660: } else {
661: gen_op_load_gpr_T0(base);
662: gen_op_set_T1(offset);
663: gen_op_add();
664: }
665: /* Don't do NOP if destination is zero: we must perform the actual
666: * memory access
667: */
668: switch (opc) {
1.1.1.5 ! root 669: #ifdef MIPS_HAS_MIPS64
1.1 root 670: case OPC_LD:
671: op_ldst(ld);
672: GEN_STORE_TN_REG(rt, T0);
673: opn = "ld";
674: break;
1.1.1.5 ! root 675: case OPC_LLD:
! 676: op_ldst(lld);
! 677: GEN_STORE_TN_REG(rt, T0);
! 678: opn = "lld";
! 679: break;
1.1 root 680: case OPC_SD:
681: GEN_LOAD_REG_TN(T1, rt);
682: op_ldst(sd);
683: opn = "sd";
684: break;
1.1.1.5 ! root 685: case OPC_SCD:
! 686: GEN_LOAD_REG_TN(T1, rt);
! 687: op_ldst(scd);
! 688: opn = "scd";
! 689: break;
1.1 root 690: case OPC_LDL:
691: op_ldst(ldl);
692: GEN_STORE_TN_REG(rt, T0);
693: opn = "ldl";
694: break;
695: case OPC_SDL:
696: GEN_LOAD_REG_TN(T1, rt);
697: op_ldst(sdl);
698: opn = "sdl";
699: break;
700: case OPC_LDR:
701: op_ldst(ldr);
702: GEN_STORE_TN_REG(rt, T0);
703: opn = "ldr";
704: break;
705: case OPC_SDR:
706: GEN_LOAD_REG_TN(T1, rt);
707: op_ldst(sdr);
708: opn = "sdr";
709: break;
710: #endif
711: case OPC_LW:
712: op_ldst(lw);
713: GEN_STORE_TN_REG(rt, T0);
714: opn = "lw";
715: break;
1.1.1.4 root 716: case OPC_LWU:
717: op_ldst(lwu);
718: GEN_STORE_TN_REG(rt, T0);
719: opn = "lwu";
720: break;
1.1 root 721: case OPC_SW:
722: GEN_LOAD_REG_TN(T1, rt);
723: op_ldst(sw);
724: opn = "sw";
725: break;
726: case OPC_LH:
727: op_ldst(lh);
728: GEN_STORE_TN_REG(rt, T0);
729: opn = "lh";
730: break;
731: case OPC_SH:
732: GEN_LOAD_REG_TN(T1, rt);
733: op_ldst(sh);
734: opn = "sh";
735: break;
736: case OPC_LHU:
737: op_ldst(lhu);
738: GEN_STORE_TN_REG(rt, T0);
739: opn = "lhu";
740: break;
741: case OPC_LB:
742: op_ldst(lb);
743: GEN_STORE_TN_REG(rt, T0);
744: opn = "lb";
745: break;
746: case OPC_SB:
747: GEN_LOAD_REG_TN(T1, rt);
748: op_ldst(sb);
749: opn = "sb";
750: break;
751: case OPC_LBU:
752: op_ldst(lbu);
753: GEN_STORE_TN_REG(rt, T0);
754: opn = "lbu";
755: break;
756: case OPC_LWL:
757: GEN_LOAD_REG_TN(T1, rt);
758: op_ldst(lwl);
759: GEN_STORE_TN_REG(rt, T0);
760: opn = "lwl";
761: break;
762: case OPC_SWL:
763: GEN_LOAD_REG_TN(T1, rt);
764: op_ldst(swl);
765: opn = "swr";
766: break;
767: case OPC_LWR:
768: GEN_LOAD_REG_TN(T1, rt);
769: op_ldst(lwr);
770: GEN_STORE_TN_REG(rt, T0);
771: opn = "lwr";
772: break;
773: case OPC_SWR:
774: GEN_LOAD_REG_TN(T1, rt);
775: op_ldst(swr);
776: opn = "swr";
777: break;
778: case OPC_LL:
779: op_ldst(ll);
780: GEN_STORE_TN_REG(rt, T0);
781: opn = "ll";
782: break;
783: case OPC_SC:
784: GEN_LOAD_REG_TN(T1, rt);
785: op_ldst(sc);
786: GEN_STORE_TN_REG(rt, T0);
787: opn = "sc";
788: break;
789: default:
790: MIPS_INVAL("load/store");
791: generate_exception(ctx, EXCP_RI);
792: return;
793: }
794: MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
795: }
796:
1.1.1.4 root 797: #ifdef MIPS_USES_FPU
798:
799: /* Load and store */
1.1.1.5 ! root 800: static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1.1.1.4 root 801: int base, int16_t offset)
802: {
1.1.1.5 ! root 803: const char *opn = "unk";
1.1.1.4 root 804:
805: if (base == 0) {
806: GEN_LOAD_IMM_TN(T0, offset);
807: } else if (offset == 0) {
808: gen_op_load_gpr_T0(base);
809: } else {
810: gen_op_load_gpr_T0(base);
811: gen_op_set_T1(offset);
812: gen_op_add();
813: }
814: /* Don't do NOP if destination is zero: we must perform the actual
815: * memory access
816: */
817: switch (opc) {
818: case OPC_LWC1:
819: op_ldst(lwc1);
820: GEN_STORE_FTN_FREG(ft, WT0);
821: opn = "lwc1";
822: break;
823: case OPC_SWC1:
824: GEN_LOAD_FREG_FTN(WT0, ft);
825: op_ldst(swc1);
826: opn = "swc1";
827: break;
828: case OPC_LDC1:
829: op_ldst(ldc1);
830: GEN_STORE_FTN_FREG(ft, DT0);
831: opn = "ldc1";
832: break;
833: case OPC_SDC1:
834: GEN_LOAD_FREG_FTN(DT0, ft);
835: op_ldst(sdc1);
836: opn = "sdc1";
837: break;
838: default:
839: MIPS_INVAL("float load/store");
1.1.1.5 ! root 840: generate_exception_err(ctx, EXCP_CpU, 1);
1.1.1.4 root 841: return;
842: }
843: MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
844: }
1.1.1.5 ! root 845:
! 846: #endif /* MIPS_USES_FPU */
1.1.1.4 root 847:
1.1 root 848: /* Arithmetic with immediate operand */
1.1.1.5 ! root 849: static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
1.1 root 850: int rs, int16_t imm)
851: {
852: uint32_t uimm;
1.1.1.5 ! root 853: const char *opn = "unk";
1.1 root 854:
1.1.1.5 ! root 855: if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1.1 root 856: /* if no destination, treat it as a NOP
857: * For addi, we must generate the overflow exception when needed.
858: */
859: MIPS_DEBUG("NOP");
860: return;
861: }
862: if (opc == OPC_ADDI || opc == OPC_ADDIU ||
1.1.1.5 ! root 863: opc == OPC_DADDI || opc == OPC_DADDIU ||
1.1 root 864: opc == OPC_SLTI || opc == OPC_SLTIU)
1.1.1.5 ! root 865: uimm = (int32_t)imm; /* Sign extend to 32 bits */
1.1 root 866: else
867: uimm = (uint16_t)imm;
868: if (opc != OPC_LUI) {
869: GEN_LOAD_REG_TN(T0, rs);
870: GEN_LOAD_IMM_TN(T1, uimm);
871: } else {
872: uimm = uimm << 16;
873: GEN_LOAD_IMM_TN(T0, uimm);
874: }
875: switch (opc) {
876: case OPC_ADDI:
877: save_cpu_state(ctx, 1);
878: gen_op_addo();
879: opn = "addi";
880: break;
881: case OPC_ADDIU:
882: gen_op_add();
883: opn = "addiu";
884: break;
1.1.1.5 ! root 885: #ifdef MIPS_HAS_MIPS64
! 886: case OPC_DADDI:
! 887: save_cpu_state(ctx, 1);
! 888: gen_op_daddo();
! 889: opn = "daddi";
! 890: break;
! 891: case OPC_DADDIU:
! 892: gen_op_dadd();
! 893: opn = "daddiu";
! 894: break;
! 895: #endif
1.1 root 896: case OPC_SLTI:
897: gen_op_lt();
898: opn = "slti";
899: break;
900: case OPC_SLTIU:
901: gen_op_ltu();
902: opn = "sltiu";
903: break;
904: case OPC_ANDI:
905: gen_op_and();
906: opn = "andi";
907: break;
908: case OPC_ORI:
909: gen_op_or();
910: opn = "ori";
911: break;
912: case OPC_XORI:
913: gen_op_xor();
914: opn = "xori";
915: break;
916: case OPC_LUI:
917: opn = "lui";
918: break;
919: case OPC_SLL:
920: gen_op_sll();
921: opn = "sll";
922: break;
923: case OPC_SRA:
924: gen_op_sra();
925: opn = "sra";
926: break;
927: case OPC_SRL:
1.1.1.5 ! root 928: if ((ctx->opcode >> 21) & 1) {
! 929: gen_op_rotr();
! 930: opn = "rotr";
! 931: } else {
! 932: gen_op_srl();
! 933: opn = "srl";
! 934: }
! 935: break;
! 936: #ifdef MIPS_HAS_MIPS64
! 937: case OPC_DSLL:
! 938: gen_op_dsll();
! 939: opn = "dsll";
! 940: break;
! 941: case OPC_DSRA:
! 942: gen_op_dsra();
! 943: opn = "dsra";
! 944: break;
! 945: case OPC_DSRL:
! 946: if ((ctx->opcode >> 21) & 1) {
! 947: gen_op_drotr();
! 948: opn = "drotr";
! 949: } else {
! 950: gen_op_dsrl();
! 951: opn = "dsrl";
! 952: }
! 953: break;
! 954: case OPC_DSLL32:
! 955: gen_op_dsll32();
! 956: opn = "dsll32";
! 957: break;
! 958: case OPC_DSRA32:
! 959: gen_op_dsra32();
! 960: opn = "dsra32";
! 961: break;
! 962: case OPC_DSRL32:
! 963: if ((ctx->opcode >> 21) & 1) {
! 964: gen_op_drotr32();
! 965: opn = "drotr32";
! 966: } else {
! 967: gen_op_dsrl32();
! 968: opn = "dsrl32";
! 969: }
1.1 root 970: break;
1.1.1.5 ! root 971: #endif
1.1 root 972: default:
973: MIPS_INVAL("imm arith");
974: generate_exception(ctx, EXCP_RI);
975: return;
976: }
977: GEN_STORE_TN_REG(rt, T0);
978: MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);
979: }
980:
981: /* Arithmetic */
1.1.1.5 ! root 982: static void gen_arith (DisasContext *ctx, uint32_t opc,
1.1 root 983: int rd, int rs, int rt)
984: {
1.1.1.5 ! root 985: const char *opn = "unk";
1.1 root 986:
1.1.1.5 ! root 987: if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
! 988: && opc != OPC_DADD && opc != OPC_DSUB) {
1.1 root 989: /* if no destination, treat it as a NOP
990: * For add & sub, we must generate the overflow exception when needed.
991: */
992: MIPS_DEBUG("NOP");
993: return;
994: }
995: GEN_LOAD_REG_TN(T0, rs);
996: GEN_LOAD_REG_TN(T1, rt);
997: switch (opc) {
998: case OPC_ADD:
999: save_cpu_state(ctx, 1);
1000: gen_op_addo();
1001: opn = "add";
1002: break;
1003: case OPC_ADDU:
1004: gen_op_add();
1005: opn = "addu";
1006: break;
1007: case OPC_SUB:
1008: save_cpu_state(ctx, 1);
1009: gen_op_subo();
1010: opn = "sub";
1011: break;
1012: case OPC_SUBU:
1013: gen_op_sub();
1014: opn = "subu";
1015: break;
1.1.1.5 ! root 1016: #ifdef MIPS_HAS_MIPS64
! 1017: case OPC_DADD:
! 1018: save_cpu_state(ctx, 1);
! 1019: gen_op_daddo();
! 1020: opn = "dadd";
! 1021: break;
! 1022: case OPC_DADDU:
! 1023: gen_op_dadd();
! 1024: opn = "daddu";
! 1025: break;
! 1026: case OPC_DSUB:
! 1027: save_cpu_state(ctx, 1);
! 1028: gen_op_dsubo();
! 1029: opn = "dsub";
! 1030: break;
! 1031: case OPC_DSUBU:
! 1032: gen_op_dsub();
! 1033: opn = "dsubu";
! 1034: break;
! 1035: #endif
1.1 root 1036: case OPC_SLT:
1037: gen_op_lt();
1038: opn = "slt";
1039: break;
1040: case OPC_SLTU:
1041: gen_op_ltu();
1042: opn = "sltu";
1043: break;
1044: case OPC_AND:
1045: gen_op_and();
1046: opn = "and";
1047: break;
1048: case OPC_NOR:
1049: gen_op_nor();
1050: opn = "nor";
1051: break;
1052: case OPC_OR:
1053: gen_op_or();
1054: opn = "or";
1055: break;
1056: case OPC_XOR:
1057: gen_op_xor();
1058: opn = "xor";
1059: break;
1060: case OPC_MUL:
1061: gen_op_mul();
1062: opn = "mul";
1063: break;
1064: case OPC_MOVN:
1065: gen_op_movn(rd);
1066: opn = "movn";
1067: goto print;
1068: case OPC_MOVZ:
1069: gen_op_movz(rd);
1070: opn = "movz";
1071: goto print;
1072: case OPC_SLLV:
1073: gen_op_sllv();
1074: opn = "sllv";
1075: break;
1076: case OPC_SRAV:
1077: gen_op_srav();
1078: opn = "srav";
1079: break;
1080: case OPC_SRLV:
1.1.1.5 ! root 1081: if ((ctx->opcode >> 6) & 1) {
! 1082: gen_op_rotrv();
! 1083: opn = "rotrv";
! 1084: } else {
! 1085: gen_op_srlv();
! 1086: opn = "srlv";
! 1087: }
! 1088: break;
! 1089: #ifdef MIPS_HAS_MIPS64
! 1090: case OPC_DSLLV:
! 1091: gen_op_dsllv();
! 1092: opn = "dsllv";
! 1093: break;
! 1094: case OPC_DSRAV:
! 1095: gen_op_dsrav();
! 1096: opn = "dsrav";
! 1097: break;
! 1098: case OPC_DSRLV:
! 1099: if ((ctx->opcode >> 6) & 1) {
! 1100: gen_op_drotrv();
! 1101: opn = "drotrv";
! 1102: } else {
! 1103: gen_op_dsrlv();
! 1104: opn = "dsrlv";
! 1105: }
1.1 root 1106: break;
1.1.1.5 ! root 1107: #endif
1.1 root 1108: default:
1109: MIPS_INVAL("arith");
1110: generate_exception(ctx, EXCP_RI);
1111: return;
1112: }
1113: GEN_STORE_TN_REG(rd, T0);
1114: print:
1115: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1116: }
1117:
1118: /* Arithmetic on HI/LO registers */
1.1.1.5 ! root 1119: static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1.1 root 1120: {
1.1.1.5 ! root 1121: const char *opn = "unk";
1.1 root 1122:
1123: if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1124: /* Treat as a NOP */
1125: MIPS_DEBUG("NOP");
1126: return;
1127: }
1128: switch (opc) {
1129: case OPC_MFHI:
1130: gen_op_load_HI();
1131: GEN_STORE_TN_REG(reg, T0);
1132: opn = "mfhi";
1133: break;
1134: case OPC_MFLO:
1135: gen_op_load_LO();
1136: GEN_STORE_TN_REG(reg, T0);
1137: opn = "mflo";
1138: break;
1139: case OPC_MTHI:
1140: GEN_LOAD_REG_TN(T0, reg);
1141: gen_op_store_HI();
1142: opn = "mthi";
1143: break;
1144: case OPC_MTLO:
1145: GEN_LOAD_REG_TN(T0, reg);
1146: gen_op_store_LO();
1147: opn = "mtlo";
1148: break;
1149: default:
1150: MIPS_INVAL("HILO");
1151: generate_exception(ctx, EXCP_RI);
1152: return;
1153: }
1154: MIPS_DEBUG("%s %s", opn, regnames[reg]);
1155: }
1156:
1.1.1.5 ! root 1157: static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1.1 root 1158: int rs, int rt)
1159: {
1.1.1.5 ! root 1160: const char *opn = "unk";
1.1 root 1161:
1162: GEN_LOAD_REG_TN(T0, rs);
1163: GEN_LOAD_REG_TN(T1, rt);
1164: switch (opc) {
1165: case OPC_DIV:
1166: gen_op_div();
1167: opn = "div";
1168: break;
1169: case OPC_DIVU:
1170: gen_op_divu();
1171: opn = "divu";
1172: break;
1173: case OPC_MULT:
1174: gen_op_mult();
1175: opn = "mult";
1176: break;
1177: case OPC_MULTU:
1178: gen_op_multu();
1179: opn = "multu";
1180: break;
1.1.1.5 ! root 1181: #ifdef MIPS_HAS_MIPS64
! 1182: case OPC_DDIV:
! 1183: gen_op_ddiv();
! 1184: opn = "ddiv";
! 1185: break;
! 1186: case OPC_DDIVU:
! 1187: gen_op_ddivu();
! 1188: opn = "ddivu";
! 1189: break;
! 1190: case OPC_DMULT:
! 1191: gen_op_dmult();
! 1192: opn = "dmult";
! 1193: break;
! 1194: case OPC_DMULTU:
! 1195: gen_op_dmultu();
! 1196: opn = "dmultu";
! 1197: break;
! 1198: #endif
1.1 root 1199: case OPC_MADD:
1200: gen_op_madd();
1201: opn = "madd";
1202: break;
1203: case OPC_MADDU:
1204: gen_op_maddu();
1205: opn = "maddu";
1206: break;
1207: case OPC_MSUB:
1208: gen_op_msub();
1209: opn = "msub";
1210: break;
1211: case OPC_MSUBU:
1212: gen_op_msubu();
1213: opn = "msubu";
1214: break;
1215: default:
1216: MIPS_INVAL("mul/div");
1217: generate_exception(ctx, EXCP_RI);
1218: return;
1219: }
1220: MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1221: }
1222:
1.1.1.5 ! root 1223: static void gen_cl (DisasContext *ctx, uint32_t opc,
1.1 root 1224: int rd, int rs)
1225: {
1.1.1.5 ! root 1226: const char *opn = "unk";
1.1 root 1227: if (rd == 0) {
1228: /* Treat as a NOP */
1229: MIPS_DEBUG("NOP");
1230: return;
1231: }
1232: GEN_LOAD_REG_TN(T0, rs);
1233: switch (opc) {
1234: case OPC_CLO:
1235: gen_op_clo();
1236: opn = "clo";
1237: break;
1238: case OPC_CLZ:
1239: gen_op_clz();
1240: opn = "clz";
1241: break;
1.1.1.5 ! root 1242: #ifdef MIPS_HAS_MIPS64
! 1243: case OPC_DCLO:
! 1244: gen_op_dclo();
! 1245: opn = "dclo";
! 1246: break;
! 1247: case OPC_DCLZ:
! 1248: gen_op_dclz();
! 1249: opn = "dclz";
! 1250: break;
! 1251: #endif
1.1 root 1252: default:
1253: MIPS_INVAL("CLx");
1254: generate_exception(ctx, EXCP_RI);
1255: return;
1256: }
1257: gen_op_store_T0_gpr(rd);
1258: MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1259: }
1260:
1261: /* Traps */
1.1.1.5 ! root 1262: static void gen_trap (DisasContext *ctx, uint32_t opc,
1.1 root 1263: int rs, int rt, int16_t imm)
1264: {
1265: int cond;
1266:
1267: cond = 0;
1268: /* Load needed operands */
1269: switch (opc) {
1270: case OPC_TEQ:
1271: case OPC_TGE:
1272: case OPC_TGEU:
1273: case OPC_TLT:
1274: case OPC_TLTU:
1275: case OPC_TNE:
1276: /* Compare two registers */
1277: if (rs != rt) {
1278: GEN_LOAD_REG_TN(T0, rs);
1279: GEN_LOAD_REG_TN(T1, rt);
1280: cond = 1;
1281: }
1.1.1.5 ! root 1282: break;
1.1 root 1283: case OPC_TEQI:
1284: case OPC_TGEI:
1285: case OPC_TGEIU:
1286: case OPC_TLTI:
1287: case OPC_TLTIU:
1288: case OPC_TNEI:
1289: /* Compare register to immediate */
1290: if (rs != 0 || imm != 0) {
1291: GEN_LOAD_REG_TN(T0, rs);
1292: GEN_LOAD_IMM_TN(T1, (int32_t)imm);
1293: cond = 1;
1294: }
1295: break;
1296: }
1297: if (cond == 0) {
1298: switch (opc) {
1299: case OPC_TEQ: /* rs == rs */
1300: case OPC_TEQI: /* r0 == 0 */
1301: case OPC_TGE: /* rs >= rs */
1302: case OPC_TGEI: /* r0 >= 0 */
1303: case OPC_TGEU: /* rs >= rs unsigned */
1304: case OPC_TGEIU: /* r0 >= 0 unsigned */
1305: /* Always trap */
1306: gen_op_set_T0(1);
1307: break;
1308: case OPC_TLT: /* rs < rs */
1309: case OPC_TLTI: /* r0 < 0 */
1310: case OPC_TLTU: /* rs < rs unsigned */
1311: case OPC_TLTIU: /* r0 < 0 unsigned */
1312: case OPC_TNE: /* rs != rs */
1313: case OPC_TNEI: /* r0 != 0 */
1314: /* Never trap: treat as NOP */
1315: return;
1316: default:
1317: MIPS_INVAL("TRAP");
1318: generate_exception(ctx, EXCP_RI);
1319: return;
1320: }
1321: } else {
1322: switch (opc) {
1323: case OPC_TEQ:
1324: case OPC_TEQI:
1325: gen_op_eq();
1326: break;
1327: case OPC_TGE:
1328: case OPC_TGEI:
1329: gen_op_ge();
1330: break;
1331: case OPC_TGEU:
1332: case OPC_TGEIU:
1333: gen_op_geu();
1334: break;
1335: case OPC_TLT:
1336: case OPC_TLTI:
1337: gen_op_lt();
1338: break;
1339: case OPC_TLTU:
1340: case OPC_TLTIU:
1341: gen_op_ltu();
1342: break;
1343: case OPC_TNE:
1344: case OPC_TNEI:
1345: gen_op_ne();
1346: break;
1347: default:
1348: MIPS_INVAL("TRAP");
1349: generate_exception(ctx, EXCP_RI);
1350: return;
1351: }
1352: }
1353: save_cpu_state(ctx, 1);
1354: gen_op_trap();
1355: ctx->bstate = BS_STOP;
1356: }
1357:
1.1.1.2 root 1358: static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1359: {
1360: TranslationBlock *tb;
1361: tb = ctx->tb;
1362: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1363: if (n == 0)
1364: gen_op_goto_tb0(TBPARAM(tb));
1365: else
1366: gen_op_goto_tb1(TBPARAM(tb));
1367: gen_op_save_pc(dest);
1368: gen_op_set_T0((long)tb + n);
1369: gen_op_exit_tb();
1370: } else {
1371: gen_op_save_pc(dest);
1372: gen_op_set_T0(0);
1373: gen_op_exit_tb();
1374: }
1375: }
1376:
1.1 root 1377: /* Branches (before delay slot) */
1.1.1.5 ! root 1378: static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1.1 root 1379: int rs, int rt, int32_t offset)
1380: {
1381: target_ulong btarget;
1382: int blink, bcond;
1383:
1384: btarget = -1;
1385: blink = 0;
1386: bcond = 0;
1387: /* Load needed operands */
1388: switch (opc) {
1389: case OPC_BEQ:
1390: case OPC_BEQL:
1391: case OPC_BNE:
1392: case OPC_BNEL:
1393: /* Compare two registers */
1394: if (rs != rt) {
1395: GEN_LOAD_REG_TN(T0, rs);
1396: GEN_LOAD_REG_TN(T1, rt);
1397: bcond = 1;
1398: }
1399: btarget = ctx->pc + 4 + offset;
1400: break;
1401: case OPC_BGEZ:
1402: case OPC_BGEZAL:
1403: case OPC_BGEZALL:
1404: case OPC_BGEZL:
1405: case OPC_BGTZ:
1406: case OPC_BGTZL:
1407: case OPC_BLEZ:
1408: case OPC_BLEZL:
1409: case OPC_BLTZ:
1410: case OPC_BLTZAL:
1411: case OPC_BLTZALL:
1412: case OPC_BLTZL:
1413: /* Compare to zero */
1414: if (rs != 0) {
1415: gen_op_load_gpr_T0(rs);
1416: bcond = 1;
1417: }
1418: btarget = ctx->pc + 4 + offset;
1419: break;
1420: case OPC_J:
1421: case OPC_JAL:
1422: /* Jump to immediate */
1.1.1.5 ! root 1423: btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | offset;
1.1 root 1424: break;
1425: case OPC_JR:
1426: case OPC_JALR:
1427: /* Jump to register */
1.1.1.5 ! root 1428: if (offset != 0 && offset != 16) {
! 1429: /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
! 1430: others are reserved. */
1.1 root 1431: generate_exception(ctx, EXCP_RI);
1432: return;
1433: }
1434: GEN_LOAD_REG_TN(T2, rs);
1435: break;
1436: default:
1437: MIPS_INVAL("branch/jump");
1438: generate_exception(ctx, EXCP_RI);
1439: return;
1440: }
1441: if (bcond == 0) {
1442: /* No condition to be computed */
1443: switch (opc) {
1444: case OPC_BEQ: /* rx == rx */
1445: case OPC_BEQL: /* rx == rx likely */
1446: case OPC_BGEZ: /* 0 >= 0 */
1447: case OPC_BGEZL: /* 0 >= 0 likely */
1448: case OPC_BLEZ: /* 0 <= 0 */
1449: case OPC_BLEZL: /* 0 <= 0 likely */
1450: /* Always take */
1.1.1.2 root 1451: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 1452: MIPS_DEBUG("balways");
1453: break;
1454: case OPC_BGEZAL: /* 0 >= 0 */
1455: case OPC_BGEZALL: /* 0 >= 0 likely */
1456: /* Always take and link */
1457: blink = 31;
1.1.1.2 root 1458: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 1459: MIPS_DEBUG("balways and link");
1460: break;
1461: case OPC_BNE: /* rx != rx */
1462: case OPC_BGTZ: /* 0 > 0 */
1463: case OPC_BLTZ: /* 0 < 0 */
1464: /* Treated as NOP */
1465: MIPS_DEBUG("bnever (NOP)");
1466: return;
1.1.1.2 root 1467: case OPC_BLTZAL: /* 0 < 0 */
1468: gen_op_set_T0(ctx->pc + 8);
1469: gen_op_store_T0_gpr(31);
1470: return;
1471: case OPC_BLTZALL: /* 0 < 0 likely */
1472: gen_op_set_T0(ctx->pc + 8);
1473: gen_op_store_T0_gpr(31);
1474: gen_goto_tb(ctx, 0, ctx->pc + 4);
1475: return;
1.1 root 1476: case OPC_BNEL: /* rx != rx likely */
1477: case OPC_BGTZL: /* 0 > 0 likely */
1478: case OPC_BLTZL: /* 0 < 0 likely */
1479: /* Skip the instruction in the delay slot */
1480: MIPS_DEBUG("bnever and skip");
1.1.1.2 root 1481: gen_goto_tb(ctx, 0, ctx->pc + 4);
1.1 root 1482: return;
1483: case OPC_J:
1.1.1.2 root 1484: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 1485: MIPS_DEBUG("j %08x", btarget);
1486: break;
1487: case OPC_JAL:
1488: blink = 31;
1.1.1.2 root 1489: ctx->hflags |= MIPS_HFLAG_B;
1.1 root 1490: MIPS_DEBUG("jal %08x", btarget);
1491: break;
1492: case OPC_JR:
1.1.1.2 root 1493: ctx->hflags |= MIPS_HFLAG_BR;
1.1 root 1494: MIPS_DEBUG("jr %s", regnames[rs]);
1495: break;
1496: case OPC_JALR:
1497: blink = rt;
1.1.1.2 root 1498: ctx->hflags |= MIPS_HFLAG_BR;
1.1 root 1499: MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1500: break;
1501: default:
1502: MIPS_INVAL("branch/jump");
1503: generate_exception(ctx, EXCP_RI);
1504: return;
1505: }
1506: } else {
1507: switch (opc) {
1508: case OPC_BEQ:
1509: gen_op_eq();
1510: MIPS_DEBUG("beq %s, %s, %08x",
1511: regnames[rs], regnames[rt], btarget);
1512: goto not_likely;
1513: case OPC_BEQL:
1514: gen_op_eq();
1515: MIPS_DEBUG("beql %s, %s, %08x",
1516: regnames[rs], regnames[rt], btarget);
1517: goto likely;
1518: case OPC_BNE:
1519: gen_op_ne();
1520: MIPS_DEBUG("bne %s, %s, %08x",
1521: regnames[rs], regnames[rt], btarget);
1522: goto not_likely;
1523: case OPC_BNEL:
1524: gen_op_ne();
1525: MIPS_DEBUG("bnel %s, %s, %08x",
1526: regnames[rs], regnames[rt], btarget);
1527: goto likely;
1528: case OPC_BGEZ:
1529: gen_op_gez();
1530: MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
1531: goto not_likely;
1532: case OPC_BGEZL:
1533: gen_op_gez();
1534: MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
1535: goto likely;
1536: case OPC_BGEZAL:
1537: gen_op_gez();
1538: MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
1539: blink = 31;
1540: goto not_likely;
1541: case OPC_BGEZALL:
1542: gen_op_gez();
1543: blink = 31;
1544: MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
1545: goto likely;
1546: case OPC_BGTZ:
1547: gen_op_gtz();
1548: MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
1549: goto not_likely;
1550: case OPC_BGTZL:
1551: gen_op_gtz();
1552: MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
1553: goto likely;
1554: case OPC_BLEZ:
1555: gen_op_lez();
1556: MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
1557: goto not_likely;
1558: case OPC_BLEZL:
1559: gen_op_lez();
1560: MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
1561: goto likely;
1562: case OPC_BLTZ:
1563: gen_op_ltz();
1564: MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
1565: goto not_likely;
1566: case OPC_BLTZL:
1567: gen_op_ltz();
1568: MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
1569: goto likely;
1570: case OPC_BLTZAL:
1571: gen_op_ltz();
1572: blink = 31;
1573: MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1574: not_likely:
1.1.1.2 root 1575: ctx->hflags |= MIPS_HFLAG_BC;
1.1 root 1576: break;
1577: case OPC_BLTZALL:
1578: gen_op_ltz();
1579: blink = 31;
1580: MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1581: likely:
1.1.1.2 root 1582: ctx->hflags |= MIPS_HFLAG_BL;
1.1 root 1583: break;
1584: }
1585: gen_op_set_bcond();
1586: }
1587: MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1588: blink, ctx->hflags, btarget);
1589: ctx->btarget = btarget;
1590: if (blink > 0) {
1591: gen_op_set_T0(ctx->pc + 8);
1592: gen_op_store_T0_gpr(blink);
1593: }
1594: return;
1595: }
1596:
1.1.1.5 ! root 1597: /* special3 bitfield operations */
! 1598: static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
! 1599: int rs, int lsb, int msb)
1.1 root 1600: {
1.1.1.5 ! root 1601: GEN_LOAD_REG_TN(T1, rs);
! 1602: switch (opc) {
! 1603: case OPC_EXT:
! 1604: if (lsb + msb > 31)
! 1605: goto fail;
! 1606: gen_op_ext(lsb, msb + 1);
! 1607: break;
! 1608: case OPC_DEXTM:
! 1609: if (lsb + msb > 63)
! 1610: goto fail;
! 1611: gen_op_ext(lsb, msb + 1 + 32);
! 1612: break;
! 1613: case OPC_DEXTU:
! 1614: if (lsb + msb > 63)
! 1615: goto fail;
! 1616: gen_op_ext(lsb + 32, msb + 1);
! 1617: break;
! 1618: case OPC_DEXT:
! 1619: gen_op_ext(lsb, msb + 1);
! 1620: break;
! 1621: case OPC_INS:
! 1622: if (lsb > msb)
! 1623: goto fail;
! 1624: GEN_LOAD_REG_TN(T2, rt);
! 1625: gen_op_ins(lsb, msb - lsb + 1);
! 1626: break;
! 1627: case OPC_DINSM:
! 1628: if (lsb > msb)
! 1629: goto fail;
! 1630: GEN_LOAD_REG_TN(T2, rt);
! 1631: gen_op_ins(lsb, msb - lsb + 1 + 32);
! 1632: break;
! 1633: case OPC_DINSU:
! 1634: if (lsb > msb)
! 1635: goto fail;
! 1636: GEN_LOAD_REG_TN(T2, rt);
! 1637: gen_op_ins(lsb + 32, msb - lsb + 1);
! 1638: break;
! 1639: case OPC_DINS:
! 1640: if (lsb > msb)
! 1641: goto fail;
! 1642: GEN_LOAD_REG_TN(T2, rt);
! 1643: gen_op_ins(lsb, msb - lsb + 1);
! 1644: break;
! 1645: default:
! 1646: fail:
! 1647: MIPS_INVAL("bitops");
! 1648: generate_exception(ctx, EXCP_RI);
1.1 root 1649: return;
1650: }
1.1.1.5 ! root 1651: GEN_STORE_TN_REG(rt, T0);
! 1652: }
1.1.1.4 root 1653:
1.1.1.5 ! root 1654: /* CP0 (MMU and control) */
! 1655: static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
! 1656: {
! 1657: const char *rn = "invalid";
! 1658:
! 1659: switch (reg) {
! 1660: case 0:
! 1661: switch (sel) {
! 1662: case 0:
! 1663: gen_op_mfc0_index();
! 1664: rn = "Index";
! 1665: break;
! 1666: case 1:
! 1667: // gen_op_mfc0_mvpcontrol(); /* MT ASE */
! 1668: rn = "MVPControl";
! 1669: // break;
! 1670: case 2:
! 1671: // gen_op_mfc0_mvpconf0(); /* MT ASE */
! 1672: rn = "MVPConf0";
! 1673: // break;
! 1674: case 3:
! 1675: // gen_op_mfc0_mvpconf1(); /* MT ASE */
! 1676: rn = "MVPConf1";
! 1677: // break;
! 1678: default:
! 1679: goto die;
1.1 root 1680: }
1681: break;
1.1.1.5 ! root 1682: case 1:
! 1683: switch (sel) {
! 1684: case 0:
! 1685: gen_op_mfc0_random();
! 1686: rn = "Random";
! 1687: break;
! 1688: case 1:
! 1689: // gen_op_mfc0_vpecontrol(); /* MT ASE */
! 1690: rn = "VPEControl";
! 1691: // break;
! 1692: case 2:
! 1693: // gen_op_mfc0_vpeconf0(); /* MT ASE */
! 1694: rn = "VPEConf0";
! 1695: // break;
! 1696: case 3:
! 1697: // gen_op_mfc0_vpeconf1(); /* MT ASE */
! 1698: rn = "VPEConf1";
! 1699: // break;
! 1700: case 4:
! 1701: // gen_op_mfc0_YQMask(); /* MT ASE */
! 1702: rn = "YQMask";
! 1703: // break;
! 1704: case 5:
! 1705: // gen_op_mfc0_vpeschedule(); /* MT ASE */
! 1706: rn = "VPESchedule";
! 1707: // break;
! 1708: case 6:
! 1709: // gen_op_mfc0_vpeschefback(); /* MT ASE */
! 1710: rn = "VPEScheFBack";
! 1711: // break;
! 1712: case 7:
! 1713: // gen_op_mfc0_vpeopt(); /* MT ASE */
! 1714: rn = "VPEOpt";
! 1715: // break;
! 1716: default:
! 1717: goto die;
! 1718: }
1.1 root 1719: break;
1.1.1.5 ! root 1720: case 2:
! 1721: switch (sel) {
! 1722: case 0:
! 1723: gen_op_mfc0_entrylo0();
! 1724: rn = "EntryLo0";
! 1725: break;
! 1726: case 1:
! 1727: // gen_op_mfc0_tcstatus(); /* MT ASE */
! 1728: rn = "TCStatus";
! 1729: // break;
! 1730: case 2:
! 1731: // gen_op_mfc0_tcbind(); /* MT ASE */
! 1732: rn = "TCBind";
! 1733: // break;
! 1734: case 3:
! 1735: // gen_op_mfc0_tcrestart(); /* MT ASE */
! 1736: rn = "TCRestart";
! 1737: // break;
! 1738: case 4:
! 1739: // gen_op_mfc0_tchalt(); /* MT ASE */
! 1740: rn = "TCHalt";
! 1741: // break;
! 1742: case 5:
! 1743: // gen_op_mfc0_tccontext(); /* MT ASE */
! 1744: rn = "TCContext";
! 1745: // break;
! 1746: case 6:
! 1747: // gen_op_mfc0_tcschedule(); /* MT ASE */
! 1748: rn = "TCSchedule";
! 1749: // break;
! 1750: case 7:
! 1751: // gen_op_mfc0_tcschefback(); /* MT ASE */
! 1752: rn = "TCScheFBack";
! 1753: // break;
! 1754: default:
! 1755: goto die;
! 1756: }
1.1 root 1757: break;
1.1.1.5 ! root 1758: case 3:
! 1759: switch (sel) {
! 1760: case 0:
! 1761: gen_op_mfc0_entrylo1();
! 1762: rn = "EntryLo1";
! 1763: break;
! 1764: default:
! 1765: goto die;
! 1766: }
1.1 root 1767: break;
1.1.1.5 ! root 1768: case 4:
! 1769: switch (sel) {
! 1770: case 0:
! 1771: gen_op_mfc0_context();
! 1772: rn = "Context";
! 1773: break;
! 1774: case 1:
! 1775: // gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
! 1776: rn = "ContextConfig";
! 1777: // break;
! 1778: default:
! 1779: goto die;
! 1780: }
1.1 root 1781: break;
1.1.1.5 ! root 1782: case 5:
! 1783: switch (sel) {
! 1784: case 0:
! 1785: gen_op_mfc0_pagemask();
! 1786: rn = "PageMask";
! 1787: break;
! 1788: case 1:
! 1789: gen_op_mfc0_pagegrain();
! 1790: rn = "PageGrain";
! 1791: break;
! 1792: default:
! 1793: goto die;
! 1794: }
1.1 root 1795: break;
1.1.1.5 ! root 1796: case 6:
! 1797: switch (sel) {
! 1798: case 0:
! 1799: gen_op_mfc0_wired();
! 1800: rn = "Wired";
! 1801: break;
! 1802: case 1:
! 1803: // gen_op_mfc0_srsconf0(); /* shadow registers */
! 1804: rn = "SRSConf0";
! 1805: // break;
! 1806: case 2:
! 1807: // gen_op_mfc0_srsconf1(); /* shadow registers */
! 1808: rn = "SRSConf1";
! 1809: // break;
! 1810: case 3:
! 1811: // gen_op_mfc0_srsconf2(); /* shadow registers */
! 1812: rn = "SRSConf2";
! 1813: // break;
! 1814: case 4:
! 1815: // gen_op_mfc0_srsconf3(); /* shadow registers */
! 1816: rn = "SRSConf3";
! 1817: // break;
! 1818: case 5:
! 1819: // gen_op_mfc0_srsconf4(); /* shadow registers */
! 1820: rn = "SRSConf4";
! 1821: // break;
! 1822: default:
! 1823: goto die;
! 1824: }
1.1 root 1825: break;
1.1.1.5 ! root 1826: case 7:
! 1827: switch (sel) {
! 1828: case 0:
! 1829: gen_op_mfc0_hwrena();
! 1830: rn = "HWREna";
! 1831: break;
! 1832: default:
! 1833: goto die;
! 1834: }
1.1 root 1835: break;
1.1.1.5 ! root 1836: case 8:
! 1837: switch (sel) {
! 1838: case 0:
! 1839: gen_op_mfc0_badvaddr();
! 1840: rn = "BadVaddr";
! 1841: break;
! 1842: default:
! 1843: goto die;
! 1844: }
1.1.1.2 root 1845: break;
1.1.1.5 ! root 1846: case 9:
! 1847: switch (sel) {
! 1848: case 0:
! 1849: gen_op_mfc0_count();
! 1850: rn = "Count";
! 1851: break;
! 1852: /* 6,7 are implementation dependent */
! 1853: default:
! 1854: goto die;
! 1855: }
! 1856: break;
! 1857: case 10:
! 1858: switch (sel) {
! 1859: case 0:
! 1860: gen_op_mfc0_entryhi();
! 1861: rn = "EntryHi";
! 1862: break;
! 1863: default:
! 1864: goto die;
! 1865: }
! 1866: break;
! 1867: case 11:
! 1868: switch (sel) {
! 1869: case 0:
! 1870: gen_op_mfc0_compare();
! 1871: rn = "Compare";
! 1872: break;
! 1873: /* 6,7 are implementation dependent */
! 1874: default:
! 1875: goto die;
! 1876: }
! 1877: break;
! 1878: case 12:
! 1879: switch (sel) {
! 1880: case 0:
! 1881: gen_op_mfc0_status();
! 1882: rn = "Status";
! 1883: break;
! 1884: case 1:
! 1885: gen_op_mfc0_intctl();
! 1886: rn = "IntCtl";
! 1887: break;
! 1888: case 2:
! 1889: gen_op_mfc0_srsctl();
! 1890: rn = "SRSCtl";
! 1891: break;
! 1892: case 3:
! 1893: // gen_op_mfc0_srsmap(); /* shadow registers */
! 1894: rn = "SRSMap";
! 1895: // break;
! 1896: default:
! 1897: goto die;
! 1898: }
! 1899: break;
! 1900: case 13:
! 1901: switch (sel) {
! 1902: case 0:
! 1903: gen_op_mfc0_cause();
! 1904: rn = "Cause";
! 1905: break;
! 1906: default:
! 1907: goto die;
! 1908: }
! 1909: break;
! 1910: case 14:
! 1911: switch (sel) {
! 1912: case 0:
! 1913: gen_op_mfc0_epc();
! 1914: rn = "EPC";
! 1915: break;
! 1916: default:
! 1917: goto die;
! 1918: }
! 1919: break;
! 1920: case 15:
! 1921: switch (sel) {
! 1922: case 0:
! 1923: gen_op_mfc0_prid();
! 1924: rn = "PRid";
! 1925: break;
! 1926: case 1:
! 1927: gen_op_mfc0_ebase();
! 1928: rn = "EBase";
! 1929: break;
! 1930: default:
! 1931: goto die;
! 1932: }
! 1933: break;
! 1934: case 16:
! 1935: switch (sel) {
! 1936: case 0:
! 1937: gen_op_mfc0_config0();
! 1938: rn = "Config";
! 1939: break;
! 1940: case 1:
! 1941: gen_op_mfc0_config1();
! 1942: rn = "Config1";
! 1943: break;
! 1944: case 2:
! 1945: gen_op_mfc0_config2();
! 1946: rn = "Config2";
! 1947: break;
! 1948: case 3:
! 1949: gen_op_mfc0_config3();
! 1950: rn = "Config3";
! 1951: break;
! 1952: /* 6,7 are implementation dependent */
! 1953: default:
! 1954: goto die;
1.1 root 1955: }
1.1.1.4 root 1956: break;
1.1.1.5 ! root 1957: case 17:
! 1958: switch (sel) {
! 1959: case 0:
! 1960: gen_op_mfc0_lladdr();
! 1961: rn = "LLAddr";
! 1962: break;
! 1963: default:
! 1964: goto die;
! 1965: }
1.1.1.4 root 1966: break;
1.1.1.5 ! root 1967: case 18:
! 1968: switch (sel) {
! 1969: case 0:
! 1970: gen_op_mfc0_watchlo0();
! 1971: rn = "WatchLo";
! 1972: break;
! 1973: case 1:
! 1974: // gen_op_mfc0_watchlo1();
! 1975: rn = "WatchLo1";
! 1976: // break;
! 1977: case 2:
! 1978: // gen_op_mfc0_watchlo2();
! 1979: rn = "WatchLo2";
! 1980: // break;
! 1981: case 3:
! 1982: // gen_op_mfc0_watchlo3();
! 1983: rn = "WatchLo3";
! 1984: // break;
! 1985: case 4:
! 1986: // gen_op_mfc0_watchlo4();
! 1987: rn = "WatchLo4";
! 1988: // break;
! 1989: case 5:
! 1990: // gen_op_mfc0_watchlo5();
! 1991: rn = "WatchLo5";
! 1992: // break;
! 1993: case 6:
! 1994: // gen_op_mfc0_watchlo6();
! 1995: rn = "WatchLo6";
! 1996: // break;
! 1997: case 7:
! 1998: // gen_op_mfc0_watchlo7();
! 1999: rn = "WatchLo7";
! 2000: // break;
! 2001: default:
! 2002: goto die;
! 2003: }
1.1.1.4 root 2004: break;
1.1.1.5 ! root 2005: case 19:
! 2006: switch (sel) {
! 2007: case 0:
! 2008: gen_op_mfc0_watchhi0();
! 2009: rn = "WatchHi";
! 2010: break;
! 2011: case 1:
! 2012: // gen_op_mfc0_watchhi1();
! 2013: rn = "WatchHi1";
! 2014: // break;
! 2015: case 2:
! 2016: // gen_op_mfc0_watchhi2();
! 2017: rn = "WatchHi2";
! 2018: // break;
! 2019: case 3:
! 2020: // gen_op_mfc0_watchhi3();
! 2021: rn = "WatchHi3";
! 2022: // break;
! 2023: case 4:
! 2024: // gen_op_mfc0_watchhi4();
! 2025: rn = "WatchHi4";
! 2026: // break;
! 2027: case 5:
! 2028: // gen_op_mfc0_watchhi5();
! 2029: rn = "WatchHi5";
! 2030: // break;
! 2031: case 6:
! 2032: // gen_op_mfc0_watchhi6();
! 2033: rn = "WatchHi6";
! 2034: // break;
! 2035: case 7:
! 2036: // gen_op_mfc0_watchhi7();
! 2037: rn = "WatchHi7";
! 2038: // break;
! 2039: default:
! 2040: goto die;
! 2041: }
1.1.1.4 root 2042: break;
1.1.1.5 ! root 2043: case 20:
! 2044: switch (sel) {
! 2045: case 0:
! 2046: /* 64 bit MMU only */
! 2047: gen_op_mfc0_xcontext();
! 2048: rn = "XContext";
! 2049: break;
! 2050: default:
! 2051: goto die;
1.1.1.4 root 2052: }
2053: break;
1.1.1.5 ! root 2054: case 21:
! 2055: /* Officially reserved, but sel 0 is used for R1x000 framemask */
! 2056: switch (sel) {
! 2057: case 0:
! 2058: gen_op_mfc0_framemask();
! 2059: rn = "Framemask";
! 2060: break;
! 2061: default:
! 2062: goto die;
1.1.1.4 root 2063: }
2064: break;
1.1.1.5 ! root 2065: case 22:
! 2066: /* ignored */
! 2067: rn = "'Diagnostic"; /* implementation dependent */
! 2068: break;
! 2069: case 23:
! 2070: switch (sel) {
! 2071: case 0:
! 2072: gen_op_mfc0_debug(); /* EJTAG support */
! 2073: rn = "Debug";
! 2074: break;
! 2075: case 1:
! 2076: // gen_op_mfc0_tracecontrol(); /* PDtrace support */
! 2077: rn = "TraceControl";
! 2078: // break;
! 2079: case 2:
! 2080: // gen_op_mfc0_tracecontrol2(); /* PDtrace support */
! 2081: rn = "TraceControl2";
! 2082: // break;
! 2083: case 3:
! 2084: // gen_op_mfc0_usertracedata(); /* PDtrace support */
! 2085: rn = "UserTraceData";
! 2086: // break;
! 2087: case 4:
! 2088: // gen_op_mfc0_debug(); /* PDtrace support */
! 2089: rn = "TraceBPC";
! 2090: // break;
! 2091: default:
! 2092: goto die;
1.1.1.4 root 2093: }
1.1.1.5 ! root 2094: break;
! 2095: case 24:
! 2096: switch (sel) {
! 2097: case 0:
! 2098: gen_op_mfc0_depc(); /* EJTAG support */
! 2099: rn = "DEPC";
! 2100: break;
! 2101: default:
! 2102: goto die;
! 2103: }
! 2104: break;
! 2105: case 25:
! 2106: switch (sel) {
! 2107: case 0:
! 2108: gen_op_mfc0_performance0();
! 2109: rn = "Performance0";
! 2110: break;
! 2111: case 1:
! 2112: // gen_op_mfc0_performance1();
! 2113: rn = "Performance1";
! 2114: // break;
! 2115: case 2:
! 2116: // gen_op_mfc0_performance2();
! 2117: rn = "Performance2";
! 2118: // break;
! 2119: case 3:
! 2120: // gen_op_mfc0_performance3();
! 2121: rn = "Performance3";
! 2122: // break;
! 2123: case 4:
! 2124: // gen_op_mfc0_performance4();
! 2125: rn = "Performance4";
! 2126: // break;
! 2127: case 5:
! 2128: // gen_op_mfc0_performance5();
! 2129: rn = "Performance5";
! 2130: // break;
! 2131: case 6:
! 2132: // gen_op_mfc0_performance6();
! 2133: rn = "Performance6";
! 2134: // break;
! 2135: case 7:
! 2136: // gen_op_mfc0_performance7();
! 2137: rn = "Performance7";
! 2138: // break;
! 2139: default:
! 2140: goto die;
! 2141: }
! 2142: break;
! 2143: case 26:
! 2144: rn = "ECC";
! 2145: break;
! 2146: case 27:
! 2147: switch (sel) {
! 2148: /* ignored */
! 2149: case 0 ... 3:
! 2150: rn = "CacheErr";
! 2151: break;
! 2152: default:
! 2153: goto die;
! 2154: }
! 2155: break;
! 2156: case 28:
! 2157: switch (sel) {
! 2158: case 0:
! 2159: case 2:
! 2160: case 4:
! 2161: case 6:
! 2162: gen_op_mfc0_taglo();
! 2163: rn = "TagLo";
! 2164: break;
! 2165: case 1:
! 2166: case 3:
! 2167: case 5:
! 2168: case 7:
! 2169: gen_op_mfc0_datalo();
! 2170: rn = "DataLo";
! 2171: break;
! 2172: default:
! 2173: goto die;
! 2174: }
! 2175: break;
! 2176: case 29:
! 2177: switch (sel) {
! 2178: case 0:
! 2179: case 2:
! 2180: case 4:
! 2181: case 6:
! 2182: gen_op_mfc0_taghi();
! 2183: rn = "TagHi";
! 2184: break;
! 2185: case 1:
! 2186: case 3:
! 2187: case 5:
! 2188: case 7:
! 2189: gen_op_mfc0_datahi();
! 2190: rn = "DataHi";
! 2191: break;
! 2192: default:
! 2193: goto die;
! 2194: }
! 2195: break;
! 2196: case 30:
! 2197: switch (sel) {
! 2198: case 0:
! 2199: gen_op_mfc0_errorepc();
! 2200: rn = "ErrorEPC";
! 2201: break;
! 2202: default:
! 2203: goto die;
! 2204: }
! 2205: break;
! 2206: case 31:
! 2207: switch (sel) {
! 2208: case 0:
! 2209: gen_op_mfc0_desave(); /* EJTAG support */
! 2210: rn = "DESAVE";
! 2211: break;
! 2212: default:
! 2213: goto die;
! 2214: }
! 2215: break;
! 2216: default:
! 2217: goto die;
! 2218: }
! 2219: #if defined MIPS_DEBUG_DISAS
! 2220: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 2221: fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
! 2222: rn, reg, sel);
! 2223: }
! 2224: #endif
! 2225: return;
! 2226:
! 2227: die:
! 2228: #if defined MIPS_DEBUG_DISAS
! 2229: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 2230: fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
! 2231: rn, reg, sel);
! 2232: }
! 2233: #endif
! 2234: generate_exception(ctx, EXCP_RI);
! 2235: }
! 2236:
! 2237: static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
! 2238: {
! 2239: const char *rn = "invalid";
! 2240:
! 2241: switch (reg) {
! 2242: case 0:
! 2243: switch (sel) {
! 2244: case 0:
! 2245: gen_op_mtc0_index();
! 2246: rn = "Index";
! 2247: break;
! 2248: case 1:
! 2249: // gen_op_mtc0_mvpcontrol(); /* MT ASE */
! 2250: rn = "MVPControl";
! 2251: // break;
! 2252: case 2:
! 2253: // gen_op_mtc0_mvpconf0(); /* MT ASE */
! 2254: rn = "MVPConf0";
! 2255: // break;
! 2256: case 3:
! 2257: // gen_op_mtc0_mvpconf1(); /* MT ASE */
! 2258: rn = "MVPConf1";
! 2259: // break;
! 2260: default:
! 2261: goto die;
! 2262: }
! 2263: break;
! 2264: case 1:
! 2265: switch (sel) {
! 2266: case 0:
! 2267: /* ignored */
! 2268: rn = "Random";
! 2269: break;
! 2270: case 1:
! 2271: // gen_op_mtc0_vpecontrol(); /* MT ASE */
! 2272: rn = "VPEControl";
! 2273: // break;
! 2274: case 2:
! 2275: // gen_op_mtc0_vpeconf0(); /* MT ASE */
! 2276: rn = "VPEConf0";
! 2277: // break;
! 2278: case 3:
! 2279: // gen_op_mtc0_vpeconf1(); /* MT ASE */
! 2280: rn = "VPEConf1";
! 2281: // break;
! 2282: case 4:
! 2283: // gen_op_mtc0_YQMask(); /* MT ASE */
! 2284: rn = "YQMask";
! 2285: // break;
! 2286: case 5:
! 2287: // gen_op_mtc0_vpeschedule(); /* MT ASE */
! 2288: rn = "VPESchedule";
! 2289: // break;
! 2290: case 6:
! 2291: // gen_op_mtc0_vpeschefback(); /* MT ASE */
! 2292: rn = "VPEScheFBack";
! 2293: // break;
! 2294: case 7:
! 2295: // gen_op_mtc0_vpeopt(); /* MT ASE */
! 2296: rn = "VPEOpt";
! 2297: // break;
! 2298: default:
! 2299: goto die;
! 2300: }
! 2301: break;
! 2302: case 2:
! 2303: switch (sel) {
! 2304: case 0:
! 2305: gen_op_mtc0_entrylo0();
! 2306: rn = "EntryLo0";
! 2307: break;
! 2308: case 1:
! 2309: // gen_op_mtc0_tcstatus(); /* MT ASE */
! 2310: rn = "TCStatus";
! 2311: // break;
! 2312: case 2:
! 2313: // gen_op_mtc0_tcbind(); /* MT ASE */
! 2314: rn = "TCBind";
! 2315: // break;
! 2316: case 3:
! 2317: // gen_op_mtc0_tcrestart(); /* MT ASE */
! 2318: rn = "TCRestart";
! 2319: // break;
! 2320: case 4:
! 2321: // gen_op_mtc0_tchalt(); /* MT ASE */
! 2322: rn = "TCHalt";
! 2323: // break;
! 2324: case 5:
! 2325: // gen_op_mtc0_tccontext(); /* MT ASE */
! 2326: rn = "TCContext";
! 2327: // break;
! 2328: case 6:
! 2329: // gen_op_mtc0_tcschedule(); /* MT ASE */
! 2330: rn = "TCSchedule";
! 2331: // break;
! 2332: case 7:
! 2333: // gen_op_mtc0_tcschefback(); /* MT ASE */
! 2334: rn = "TCScheFBack";
! 2335: // break;
! 2336: default:
! 2337: goto die;
! 2338: }
! 2339: break;
! 2340: case 3:
! 2341: switch (sel) {
! 2342: case 0:
! 2343: gen_op_mtc0_entrylo1();
! 2344: rn = "EntryLo1";
! 2345: break;
! 2346: default:
! 2347: goto die;
! 2348: }
! 2349: break;
! 2350: case 4:
! 2351: switch (sel) {
! 2352: case 0:
! 2353: gen_op_mtc0_context();
! 2354: rn = "Context";
! 2355: break;
! 2356: case 1:
! 2357: // gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
! 2358: rn = "ContextConfig";
! 2359: // break;
! 2360: default:
! 2361: goto die;
! 2362: }
! 2363: break;
! 2364: case 5:
! 2365: switch (sel) {
! 2366: case 0:
! 2367: gen_op_mtc0_pagemask();
! 2368: rn = "PageMask";
! 2369: break;
! 2370: case 1:
! 2371: gen_op_mtc0_pagegrain();
! 2372: rn = "PageGrain";
! 2373: break;
! 2374: default:
! 2375: goto die;
! 2376: }
! 2377: break;
! 2378: case 6:
! 2379: switch (sel) {
! 2380: case 0:
! 2381: gen_op_mtc0_wired();
! 2382: rn = "Wired";
! 2383: break;
! 2384: case 1:
! 2385: // gen_op_mtc0_srsconf0(); /* shadow registers */
! 2386: rn = "SRSConf0";
! 2387: // break;
! 2388: case 2:
! 2389: // gen_op_mtc0_srsconf1(); /* shadow registers */
! 2390: rn = "SRSConf1";
! 2391: // break;
! 2392: case 3:
! 2393: // gen_op_mtc0_srsconf2(); /* shadow registers */
! 2394: rn = "SRSConf2";
! 2395: // break;
! 2396: case 4:
! 2397: // gen_op_mtc0_srsconf3(); /* shadow registers */
! 2398: rn = "SRSConf3";
! 2399: // break;
! 2400: case 5:
! 2401: // gen_op_mtc0_srsconf4(); /* shadow registers */
! 2402: rn = "SRSConf4";
! 2403: // break;
! 2404: default:
! 2405: goto die;
! 2406: }
! 2407: break;
! 2408: case 7:
! 2409: switch (sel) {
! 2410: case 0:
! 2411: gen_op_mtc0_hwrena();
! 2412: rn = "HWREna";
! 2413: break;
! 2414: default:
! 2415: goto die;
! 2416: }
! 2417: break;
! 2418: case 8:
! 2419: /* ignored */
! 2420: rn = "BadVaddr";
! 2421: break;
! 2422: case 9:
! 2423: switch (sel) {
! 2424: case 0:
! 2425: gen_op_mtc0_count();
! 2426: rn = "Count";
! 2427: break;
! 2428: /* 6,7 are implementation dependent */
! 2429: default:
! 2430: goto die;
! 2431: }
! 2432: /* Stop translation as we may have switched the execution mode */
! 2433: ctx->bstate = BS_STOP;
! 2434: break;
! 2435: case 10:
! 2436: switch (sel) {
! 2437: case 0:
! 2438: gen_op_mtc0_entryhi();
! 2439: rn = "EntryHi";
! 2440: break;
! 2441: default:
! 2442: goto die;
! 2443: }
! 2444: break;
! 2445: case 11:
! 2446: switch (sel) {
! 2447: case 0:
! 2448: gen_op_mtc0_compare();
! 2449: rn = "Compare";
! 2450: break;
! 2451: /* 6,7 are implementation dependent */
! 2452: default:
! 2453: goto die;
! 2454: }
! 2455: /* Stop translation as we may have switched the execution mode */
! 2456: ctx->bstate = BS_STOP;
! 2457: break;
! 2458: case 12:
! 2459: switch (sel) {
! 2460: case 0:
! 2461: gen_op_mtc0_status();
! 2462: rn = "Status";
! 2463: break;
! 2464: case 1:
! 2465: gen_op_mtc0_intctl();
! 2466: rn = "IntCtl";
! 2467: break;
! 2468: case 2:
! 2469: gen_op_mtc0_srsctl();
! 2470: rn = "SRSCtl";
! 2471: break;
! 2472: case 3:
! 2473: // gen_op_mtc0_srsmap(); /* shadow registers */
! 2474: rn = "SRSMap";
! 2475: // break;
! 2476: default:
! 2477: goto die;
! 2478: }
! 2479: /* Stop translation as we may have switched the execution mode */
! 2480: ctx->bstate = BS_STOP;
! 2481: break;
! 2482: case 13:
! 2483: switch (sel) {
! 2484: case 0:
! 2485: gen_op_mtc0_cause();
! 2486: rn = "Cause";
! 2487: break;
! 2488: default:
! 2489: goto die;
! 2490: }
! 2491: /* Stop translation as we may have switched the execution mode */
! 2492: ctx->bstate = BS_STOP;
! 2493: break;
! 2494: case 14:
! 2495: switch (sel) {
! 2496: case 0:
! 2497: gen_op_mtc0_epc();
! 2498: rn = "EPC";
! 2499: break;
! 2500: default:
! 2501: goto die;
! 2502: }
! 2503: break;
! 2504: case 15:
! 2505: switch (sel) {
! 2506: case 0:
! 2507: /* ignored */
! 2508: rn = "PRid";
! 2509: break;
! 2510: case 1:
! 2511: gen_op_mtc0_ebase();
! 2512: rn = "EBase";
! 2513: break;
! 2514: default:
! 2515: goto die;
! 2516: }
! 2517: break;
! 2518: case 16:
! 2519: switch (sel) {
! 2520: case 0:
! 2521: gen_op_mtc0_config0();
! 2522: rn = "Config";
! 2523: break;
! 2524: case 1:
! 2525: /* ignored */
! 2526: rn = "Config1";
! 2527: break;
! 2528: case 2:
! 2529: gen_op_mtc0_config2();
! 2530: rn = "Config2";
! 2531: break;
! 2532: case 3:
! 2533: /* ignored */
! 2534: rn = "Config3";
! 2535: break;
! 2536: /* 6,7 are implementation dependent */
! 2537: default:
! 2538: rn = "Invalid config selector";
! 2539: goto die;
! 2540: }
! 2541: /* Stop translation as we may have switched the execution mode */
! 2542: ctx->bstate = BS_STOP;
! 2543: break;
! 2544: case 17:
! 2545: switch (sel) {
! 2546: case 0:
! 2547: /* ignored */
! 2548: rn = "LLAddr";
! 2549: break;
! 2550: default:
! 2551: goto die;
! 2552: }
! 2553: break;
! 2554: case 18:
! 2555: switch (sel) {
! 2556: case 0:
! 2557: gen_op_mtc0_watchlo0();
! 2558: rn = "WatchLo";
! 2559: break;
! 2560: case 1:
! 2561: // gen_op_mtc0_watchlo1();
! 2562: rn = "WatchLo1";
! 2563: // break;
! 2564: case 2:
! 2565: // gen_op_mtc0_watchlo2();
! 2566: rn = "WatchLo2";
! 2567: // break;
! 2568: case 3:
! 2569: // gen_op_mtc0_watchlo3();
! 2570: rn = "WatchLo3";
! 2571: // break;
! 2572: case 4:
! 2573: // gen_op_mtc0_watchlo4();
! 2574: rn = "WatchLo4";
! 2575: // break;
! 2576: case 5:
! 2577: // gen_op_mtc0_watchlo5();
! 2578: rn = "WatchLo5";
! 2579: // break;
! 2580: case 6:
! 2581: // gen_op_mtc0_watchlo6();
! 2582: rn = "WatchLo6";
! 2583: // break;
! 2584: case 7:
! 2585: // gen_op_mtc0_watchlo7();
! 2586: rn = "WatchLo7";
! 2587: // break;
! 2588: default:
! 2589: goto die;
! 2590: }
! 2591: break;
! 2592: case 19:
! 2593: switch (sel) {
! 2594: case 0:
! 2595: gen_op_mtc0_watchhi0();
! 2596: rn = "WatchHi";
! 2597: break;
! 2598: case 1:
! 2599: // gen_op_mtc0_watchhi1();
! 2600: rn = "WatchHi1";
! 2601: // break;
! 2602: case 2:
! 2603: // gen_op_mtc0_watchhi2();
! 2604: rn = "WatchHi2";
! 2605: // break;
! 2606: case 3:
! 2607: // gen_op_mtc0_watchhi3();
! 2608: rn = "WatchHi3";
! 2609: // break;
! 2610: case 4:
! 2611: // gen_op_mtc0_watchhi4();
! 2612: rn = "WatchHi4";
! 2613: // break;
! 2614: case 5:
! 2615: // gen_op_mtc0_watchhi5();
! 2616: rn = "WatchHi5";
! 2617: // break;
! 2618: case 6:
! 2619: // gen_op_mtc0_watchhi6();
! 2620: rn = "WatchHi6";
! 2621: // break;
! 2622: case 7:
! 2623: // gen_op_mtc0_watchhi7();
! 2624: rn = "WatchHi7";
! 2625: // break;
! 2626: default:
! 2627: goto die;
! 2628: }
! 2629: break;
! 2630: case 20:
! 2631: switch (sel) {
! 2632: case 0:
! 2633: /* 64 bit MMU only */
! 2634: gen_op_mtc0_xcontext();
! 2635: rn = "XContext";
! 2636: break;
! 2637: default:
! 2638: goto die;
! 2639: }
! 2640: break;
! 2641: case 21:
! 2642: /* Officially reserved, but sel 0 is used for R1x000 framemask */
! 2643: switch (sel) {
! 2644: case 0:
! 2645: gen_op_mtc0_framemask();
! 2646: rn = "Framemask";
! 2647: break;
! 2648: default:
! 2649: goto die;
! 2650: }
! 2651: break;
! 2652: case 22:
! 2653: /* ignored */
! 2654: rn = "Diagnostic"; /* implementation dependent */
! 2655: break;
! 2656: case 23:
! 2657: switch (sel) {
! 2658: case 0:
! 2659: gen_op_mtc0_debug(); /* EJTAG support */
! 2660: rn = "Debug";
! 2661: break;
! 2662: case 1:
! 2663: // gen_op_mtc0_tracecontrol(); /* PDtrace support */
! 2664: rn = "TraceControl";
! 2665: // break;
! 2666: case 2:
! 2667: // gen_op_mtc0_tracecontrol2(); /* PDtrace support */
! 2668: rn = "TraceControl2";
! 2669: // break;
! 2670: case 3:
! 2671: // gen_op_mtc0_usertracedata(); /* PDtrace support */
! 2672: rn = "UserTraceData";
! 2673: // break;
! 2674: case 4:
! 2675: // gen_op_mtc0_debug(); /* PDtrace support */
! 2676: rn = "TraceBPC";
! 2677: // break;
! 2678: default:
! 2679: goto die;
! 2680: }
! 2681: /* Stop translation as we may have switched the execution mode */
! 2682: ctx->bstate = BS_STOP;
! 2683: break;
! 2684: case 24:
! 2685: switch (sel) {
! 2686: case 0:
! 2687: gen_op_mtc0_depc(); /* EJTAG support */
! 2688: rn = "DEPC";
! 2689: break;
! 2690: default:
! 2691: goto die;
! 2692: }
! 2693: break;
! 2694: case 25:
! 2695: switch (sel) {
! 2696: case 0:
! 2697: gen_op_mtc0_performance0();
! 2698: rn = "Performance0";
! 2699: break;
! 2700: case 1:
! 2701: // gen_op_mtc0_performance1();
! 2702: rn = "Performance1";
! 2703: // break;
! 2704: case 2:
! 2705: // gen_op_mtc0_performance2();
! 2706: rn = "Performance2";
! 2707: // break;
! 2708: case 3:
! 2709: // gen_op_mtc0_performance3();
! 2710: rn = "Performance3";
! 2711: // break;
! 2712: case 4:
! 2713: // gen_op_mtc0_performance4();
! 2714: rn = "Performance4";
! 2715: // break;
! 2716: case 5:
! 2717: // gen_op_mtc0_performance5();
! 2718: rn = "Performance5";
! 2719: // break;
! 2720: case 6:
! 2721: // gen_op_mtc0_performance6();
! 2722: rn = "Performance6";
! 2723: // break;
! 2724: case 7:
! 2725: // gen_op_mtc0_performance7();
! 2726: rn = "Performance7";
! 2727: // break;
! 2728: default:
! 2729: goto die;
! 2730: }
! 2731: break;
! 2732: case 26:
! 2733: /* ignored */
! 2734: rn = "ECC";
! 2735: break;
! 2736: case 27:
! 2737: switch (sel) {
! 2738: case 0 ... 3:
! 2739: /* ignored */
! 2740: rn = "CacheErr";
! 2741: break;
! 2742: default:
! 2743: goto die;
! 2744: }
! 2745: break;
! 2746: case 28:
! 2747: switch (sel) {
! 2748: case 0:
! 2749: case 2:
! 2750: case 4:
! 2751: case 6:
! 2752: gen_op_mtc0_taglo();
! 2753: rn = "TagLo";
! 2754: break;
! 2755: case 1:
! 2756: case 3:
! 2757: case 5:
! 2758: case 7:
! 2759: gen_op_mtc0_datalo();
! 2760: rn = "DataLo";
! 2761: break;
! 2762: default:
! 2763: goto die;
! 2764: }
! 2765: break;
! 2766: case 29:
! 2767: switch (sel) {
! 2768: case 0:
! 2769: case 2:
! 2770: case 4:
! 2771: case 6:
! 2772: gen_op_mtc0_taghi();
! 2773: rn = "TagHi";
! 2774: break;
! 2775: case 1:
! 2776: case 3:
! 2777: case 5:
! 2778: case 7:
! 2779: gen_op_mtc0_datahi();
! 2780: rn = "DataHi";
! 2781: break;
! 2782: default:
! 2783: rn = "invalid sel";
! 2784: goto die;
! 2785: }
! 2786: break;
! 2787: case 30:
! 2788: switch (sel) {
! 2789: case 0:
! 2790: gen_op_mtc0_errorepc();
! 2791: rn = "ErrorEPC";
! 2792: break;
! 2793: default:
! 2794: goto die;
! 2795: }
! 2796: break;
! 2797: case 31:
! 2798: switch (sel) {
! 2799: case 0:
! 2800: gen_op_mtc0_desave(); /* EJTAG support */
! 2801: rn = "DESAVE";
! 2802: break;
! 2803: default:
! 2804: goto die;
! 2805: }
! 2806: /* Stop translation as we may have switched the execution mode */
! 2807: ctx->bstate = BS_STOP;
! 2808: break;
! 2809: default:
! 2810: goto die;
! 2811: }
! 2812: #if defined MIPS_DEBUG_DISAS
! 2813: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 2814: fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
! 2815: rn, reg, sel);
! 2816: }
! 2817: #endif
! 2818: return;
! 2819:
! 2820: die:
! 2821: #if defined MIPS_DEBUG_DISAS
! 2822: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 2823: fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
! 2824: rn, reg, sel);
! 2825: }
! 2826: #endif
! 2827: generate_exception(ctx, EXCP_RI);
! 2828: }
! 2829:
! 2830: static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
! 2831: {
! 2832: const char *rn = "invalid";
! 2833:
! 2834: switch (reg) {
! 2835: case 0:
! 2836: switch (sel) {
! 2837: case 0:
! 2838: gen_op_mfc0_index();
! 2839: rn = "Index";
! 2840: break;
! 2841: case 1:
! 2842: // gen_op_dmfc0_mvpcontrol(); /* MT ASE */
! 2843: rn = "MVPControl";
! 2844: // break;
! 2845: case 2:
! 2846: // gen_op_dmfc0_mvpconf0(); /* MT ASE */
! 2847: rn = "MVPConf0";
! 2848: // break;
! 2849: case 3:
! 2850: // gen_op_dmfc0_mvpconf1(); /* MT ASE */
! 2851: rn = "MVPConf1";
! 2852: // break;
! 2853: default:
! 2854: goto die;
! 2855: }
! 2856: break;
! 2857: case 1:
! 2858: switch (sel) {
! 2859: case 0:
! 2860: gen_op_mfc0_random();
! 2861: rn = "Random";
! 2862: break;
! 2863: case 1:
! 2864: // gen_op_dmfc0_vpecontrol(); /* MT ASE */
! 2865: rn = "VPEControl";
! 2866: // break;
! 2867: case 2:
! 2868: // gen_op_dmfc0_vpeconf0(); /* MT ASE */
! 2869: rn = "VPEConf0";
! 2870: // break;
! 2871: case 3:
! 2872: // gen_op_dmfc0_vpeconf1(); /* MT ASE */
! 2873: rn = "VPEConf1";
! 2874: // break;
! 2875: case 4:
! 2876: // gen_op_dmfc0_YQMask(); /* MT ASE */
! 2877: rn = "YQMask";
! 2878: // break;
! 2879: case 5:
! 2880: // gen_op_dmfc0_vpeschedule(); /* MT ASE */
! 2881: rn = "VPESchedule";
! 2882: // break;
! 2883: case 6:
! 2884: // gen_op_dmfc0_vpeschefback(); /* MT ASE */
! 2885: rn = "VPEScheFBack";
! 2886: // break;
! 2887: case 7:
! 2888: // gen_op_dmfc0_vpeopt(); /* MT ASE */
! 2889: rn = "VPEOpt";
! 2890: // break;
! 2891: default:
! 2892: goto die;
! 2893: }
! 2894: break;
! 2895: case 2:
! 2896: switch (sel) {
! 2897: case 0:
! 2898: gen_op_dmfc0_entrylo0();
! 2899: rn = "EntryLo0";
! 2900: break;
! 2901: case 1:
! 2902: // gen_op_dmfc0_tcstatus(); /* MT ASE */
! 2903: rn = "TCStatus";
! 2904: // break;
! 2905: case 2:
! 2906: // gen_op_dmfc0_tcbind(); /* MT ASE */
! 2907: rn = "TCBind";
! 2908: // break;
! 2909: case 3:
! 2910: // gen_op_dmfc0_tcrestart(); /* MT ASE */
! 2911: rn = "TCRestart";
! 2912: // break;
! 2913: case 4:
! 2914: // gen_op_dmfc0_tchalt(); /* MT ASE */
! 2915: rn = "TCHalt";
! 2916: // break;
! 2917: case 5:
! 2918: // gen_op_dmfc0_tccontext(); /* MT ASE */
! 2919: rn = "TCContext";
! 2920: // break;
! 2921: case 6:
! 2922: // gen_op_dmfc0_tcschedule(); /* MT ASE */
! 2923: rn = "TCSchedule";
! 2924: // break;
! 2925: case 7:
! 2926: // gen_op_dmfc0_tcschefback(); /* MT ASE */
! 2927: rn = "TCScheFBack";
! 2928: // break;
! 2929: default:
! 2930: goto die;
! 2931: }
! 2932: break;
! 2933: case 3:
! 2934: switch (sel) {
! 2935: case 0:
! 2936: gen_op_dmfc0_entrylo1();
! 2937: rn = "EntryLo1";
! 2938: break;
! 2939: default:
! 2940: goto die;
! 2941: }
! 2942: break;
! 2943: case 4:
! 2944: switch (sel) {
! 2945: case 0:
! 2946: gen_op_dmfc0_context();
! 2947: rn = "Context";
! 2948: break;
! 2949: case 1:
! 2950: // gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */
! 2951: rn = "ContextConfig";
! 2952: // break;
! 2953: default:
! 2954: goto die;
! 2955: }
! 2956: break;
! 2957: case 5:
! 2958: switch (sel) {
! 2959: case 0:
! 2960: gen_op_mfc0_pagemask();
! 2961: rn = "PageMask";
! 2962: break;
! 2963: case 1:
! 2964: gen_op_mfc0_pagegrain();
! 2965: rn = "PageGrain";
! 2966: break;
! 2967: default:
! 2968: goto die;
! 2969: }
! 2970: break;
! 2971: case 6:
! 2972: switch (sel) {
! 2973: case 0:
! 2974: gen_op_mfc0_wired();
! 2975: rn = "Wired";
! 2976: break;
! 2977: case 1:
! 2978: // gen_op_dmfc0_srsconf0(); /* shadow registers */
! 2979: rn = "SRSConf0";
! 2980: // break;
! 2981: case 2:
! 2982: // gen_op_dmfc0_srsconf1(); /* shadow registers */
! 2983: rn = "SRSConf1";
! 2984: // break;
! 2985: case 3:
! 2986: // gen_op_dmfc0_srsconf2(); /* shadow registers */
! 2987: rn = "SRSConf2";
! 2988: // break;
! 2989: case 4:
! 2990: // gen_op_dmfc0_srsconf3(); /* shadow registers */
! 2991: rn = "SRSConf3";
! 2992: // break;
! 2993: case 5:
! 2994: // gen_op_dmfc0_srsconf4(); /* shadow registers */
! 2995: rn = "SRSConf4";
! 2996: // break;
! 2997: default:
! 2998: goto die;
! 2999: }
! 3000: break;
! 3001: case 7:
! 3002: switch (sel) {
! 3003: case 0:
! 3004: gen_op_mfc0_hwrena();
! 3005: rn = "HWREna";
! 3006: break;
! 3007: default:
! 3008: goto die;
! 3009: }
! 3010: break;
! 3011: case 8:
! 3012: switch (sel) {
! 3013: case 0:
! 3014: gen_op_dmfc0_badvaddr();
! 3015: rn = "BadVaddr";
! 3016: break;
! 3017: default:
! 3018: goto die;
! 3019: }
! 3020: break;
! 3021: case 9:
! 3022: switch (sel) {
! 3023: case 0:
! 3024: gen_op_mfc0_count();
! 3025: rn = "Count";
! 3026: break;
! 3027: /* 6,7 are implementation dependent */
! 3028: default:
! 3029: goto die;
! 3030: }
! 3031: break;
! 3032: case 10:
! 3033: switch (sel) {
! 3034: case 0:
! 3035: gen_op_dmfc0_entryhi();
! 3036: rn = "EntryHi";
! 3037: break;
! 3038: default:
! 3039: goto die;
! 3040: }
! 3041: break;
! 3042: case 11:
! 3043: switch (sel) {
! 3044: case 0:
! 3045: gen_op_mfc0_compare();
! 3046: rn = "Compare";
! 3047: break;
! 3048: /* 6,7 are implementation dependent */
! 3049: default:
! 3050: goto die;
! 3051: }
! 3052: break;
! 3053: case 12:
! 3054: switch (sel) {
! 3055: case 0:
! 3056: gen_op_mfc0_status();
! 3057: rn = "Status";
! 3058: break;
! 3059: case 1:
! 3060: gen_op_mfc0_intctl();
! 3061: rn = "IntCtl";
! 3062: break;
! 3063: case 2:
! 3064: gen_op_mfc0_srsctl();
! 3065: rn = "SRSCtl";
! 3066: break;
! 3067: case 3:
! 3068: gen_op_mfc0_srsmap(); /* shadow registers */
! 3069: rn = "SRSMap";
! 3070: break;
! 3071: default:
! 3072: goto die;
! 3073: }
! 3074: break;
! 3075: case 13:
! 3076: switch (sel) {
! 3077: case 0:
! 3078: gen_op_mfc0_cause();
! 3079: rn = "Cause";
! 3080: break;
! 3081: default:
! 3082: goto die;
! 3083: }
! 3084: break;
! 3085: case 14:
! 3086: switch (sel) {
! 3087: case 0:
! 3088: gen_op_dmfc0_epc();
! 3089: rn = "EPC";
! 3090: break;
! 3091: default:
! 3092: goto die;
! 3093: }
! 3094: break;
! 3095: case 15:
! 3096: switch (sel) {
! 3097: case 0:
! 3098: gen_op_mfc0_prid();
! 3099: rn = "PRid";
! 3100: break;
! 3101: case 1:
! 3102: gen_op_mfc0_ebase();
! 3103: rn = "EBase";
! 3104: break;
! 3105: default:
! 3106: goto die;
! 3107: }
! 3108: break;
! 3109: case 16:
! 3110: switch (sel) {
! 3111: case 0:
! 3112: gen_op_mfc0_config0();
! 3113: rn = "Config";
! 3114: break;
! 3115: case 1:
! 3116: gen_op_mfc0_config1();
! 3117: rn = "Config1";
! 3118: break;
! 3119: case 2:
! 3120: gen_op_mfc0_config2();
! 3121: rn = "Config2";
! 3122: break;
! 3123: case 3:
! 3124: gen_op_mfc0_config3();
! 3125: rn = "Config3";
! 3126: break;
! 3127: /* 6,7 are implementation dependent */
! 3128: default:
! 3129: goto die;
! 3130: }
! 3131: break;
! 3132: case 17:
! 3133: switch (sel) {
! 3134: case 0:
! 3135: gen_op_dmfc0_lladdr();
! 3136: rn = "LLAddr";
! 3137: break;
! 3138: default:
! 3139: goto die;
! 3140: }
! 3141: break;
! 3142: case 18:
! 3143: switch (sel) {
! 3144: case 0:
! 3145: gen_op_dmfc0_watchlo0();
! 3146: rn = "WatchLo";
! 3147: break;
! 3148: case 1:
! 3149: // gen_op_dmfc0_watchlo1();
! 3150: rn = "WatchLo1";
! 3151: // break;
! 3152: case 2:
! 3153: // gen_op_dmfc0_watchlo2();
! 3154: rn = "WatchLo2";
! 3155: // break;
! 3156: case 3:
! 3157: // gen_op_dmfc0_watchlo3();
! 3158: rn = "WatchLo3";
! 3159: // break;
! 3160: case 4:
! 3161: // gen_op_dmfc0_watchlo4();
! 3162: rn = "WatchLo4";
! 3163: // break;
! 3164: case 5:
! 3165: // gen_op_dmfc0_watchlo5();
! 3166: rn = "WatchLo5";
! 3167: // break;
! 3168: case 6:
! 3169: // gen_op_dmfc0_watchlo6();
! 3170: rn = "WatchLo6";
! 3171: // break;
! 3172: case 7:
! 3173: // gen_op_dmfc0_watchlo7();
! 3174: rn = "WatchLo7";
! 3175: // break;
! 3176: default:
! 3177: goto die;
! 3178: }
! 3179: break;
! 3180: case 19:
! 3181: switch (sel) {
! 3182: case 0:
! 3183: gen_op_mfc0_watchhi0();
! 3184: rn = "WatchHi";
! 3185: break;
! 3186: case 1:
! 3187: // gen_op_mfc0_watchhi1();
! 3188: rn = "WatchHi1";
! 3189: // break;
! 3190: case 2:
! 3191: // gen_op_mfc0_watchhi2();
! 3192: rn = "WatchHi2";
! 3193: // break;
! 3194: case 3:
! 3195: // gen_op_mfc0_watchhi3();
! 3196: rn = "WatchHi3";
! 3197: // break;
! 3198: case 4:
! 3199: // gen_op_mfc0_watchhi4();
! 3200: rn = "WatchHi4";
! 3201: // break;
! 3202: case 5:
! 3203: // gen_op_mfc0_watchhi5();
! 3204: rn = "WatchHi5";
! 3205: // break;
! 3206: case 6:
! 3207: // gen_op_mfc0_watchhi6();
! 3208: rn = "WatchHi6";
! 3209: // break;
! 3210: case 7:
! 3211: // gen_op_mfc0_watchhi7();
! 3212: rn = "WatchHi7";
! 3213: // break;
! 3214: default:
! 3215: goto die;
! 3216: }
! 3217: break;
! 3218: case 20:
! 3219: switch (sel) {
! 3220: case 0:
! 3221: /* 64 bit MMU only */
! 3222: gen_op_dmfc0_xcontext();
! 3223: rn = "XContext";
! 3224: break;
! 3225: default:
! 3226: goto die;
! 3227: }
! 3228: break;
! 3229: case 21:
! 3230: /* Officially reserved, but sel 0 is used for R1x000 framemask */
! 3231: switch (sel) {
! 3232: case 0:
! 3233: gen_op_mfc0_framemask();
! 3234: rn = "Framemask";
! 3235: break;
! 3236: default:
! 3237: goto die;
! 3238: }
! 3239: break;
! 3240: case 22:
! 3241: /* ignored */
! 3242: rn = "'Diagnostic"; /* implementation dependent */
! 3243: break;
! 3244: case 23:
! 3245: switch (sel) {
! 3246: case 0:
! 3247: gen_op_mfc0_debug(); /* EJTAG support */
! 3248: rn = "Debug";
! 3249: break;
! 3250: case 1:
! 3251: // gen_op_dmfc0_tracecontrol(); /* PDtrace support */
! 3252: rn = "TraceControl";
! 3253: // break;
! 3254: case 2:
! 3255: // gen_op_dmfc0_tracecontrol2(); /* PDtrace support */
! 3256: rn = "TraceControl2";
! 3257: // break;
! 3258: case 3:
! 3259: // gen_op_dmfc0_usertracedata(); /* PDtrace support */
! 3260: rn = "UserTraceData";
! 3261: // break;
! 3262: case 4:
! 3263: // gen_op_dmfc0_debug(); /* PDtrace support */
! 3264: rn = "TraceBPC";
! 3265: // break;
! 3266: default:
! 3267: goto die;
! 3268: }
! 3269: break;
! 3270: case 24:
! 3271: switch (sel) {
! 3272: case 0:
! 3273: gen_op_dmfc0_depc(); /* EJTAG support */
! 3274: rn = "DEPC";
! 3275: break;
! 3276: default:
! 3277: goto die;
! 3278: }
! 3279: break;
! 3280: case 25:
! 3281: switch (sel) {
! 3282: case 0:
! 3283: gen_op_mfc0_performance0();
! 3284: rn = "Performance0";
! 3285: break;
! 3286: case 1:
! 3287: // gen_op_dmfc0_performance1();
! 3288: rn = "Performance1";
! 3289: // break;
! 3290: case 2:
! 3291: // gen_op_dmfc0_performance2();
! 3292: rn = "Performance2";
! 3293: // break;
! 3294: case 3:
! 3295: // gen_op_dmfc0_performance3();
! 3296: rn = "Performance3";
! 3297: // break;
! 3298: case 4:
! 3299: // gen_op_dmfc0_performance4();
! 3300: rn = "Performance4";
! 3301: // break;
! 3302: case 5:
! 3303: // gen_op_dmfc0_performance5();
! 3304: rn = "Performance5";
! 3305: // break;
! 3306: case 6:
! 3307: // gen_op_dmfc0_performance6();
! 3308: rn = "Performance6";
! 3309: // break;
! 3310: case 7:
! 3311: // gen_op_dmfc0_performance7();
! 3312: rn = "Performance7";
! 3313: // break;
! 3314: default:
! 3315: goto die;
! 3316: }
! 3317: break;
! 3318: case 26:
! 3319: rn = "ECC";
! 3320: break;
! 3321: case 27:
! 3322: switch (sel) {
! 3323: /* ignored */
! 3324: case 0 ... 3:
! 3325: rn = "CacheErr";
! 3326: break;
! 3327: default:
! 3328: goto die;
! 3329: }
! 3330: break;
! 3331: case 28:
! 3332: switch (sel) {
! 3333: case 0:
! 3334: case 2:
! 3335: case 4:
! 3336: case 6:
! 3337: gen_op_mfc0_taglo();
! 3338: rn = "TagLo";
! 3339: break;
! 3340: case 1:
! 3341: case 3:
! 3342: case 5:
! 3343: case 7:
! 3344: gen_op_mfc0_datalo();
! 3345: rn = "DataLo";
! 3346: break;
! 3347: default:
! 3348: goto die;
! 3349: }
! 3350: break;
! 3351: case 29:
! 3352: switch (sel) {
! 3353: case 0:
! 3354: case 2:
! 3355: case 4:
! 3356: case 6:
! 3357: gen_op_mfc0_taghi();
! 3358: rn = "TagHi";
! 3359: break;
! 3360: case 1:
! 3361: case 3:
! 3362: case 5:
! 3363: case 7:
! 3364: gen_op_mfc0_datahi();
! 3365: rn = "DataHi";
! 3366: break;
! 3367: default:
! 3368: goto die;
! 3369: }
! 3370: break;
! 3371: case 30:
! 3372: switch (sel) {
! 3373: case 0:
! 3374: gen_op_dmfc0_errorepc();
! 3375: rn = "ErrorEPC";
! 3376: break;
! 3377: default:
! 3378: goto die;
! 3379: }
! 3380: break;
! 3381: case 31:
! 3382: switch (sel) {
! 3383: case 0:
! 3384: gen_op_mfc0_desave(); /* EJTAG support */
! 3385: rn = "DESAVE";
! 3386: break;
! 3387: default:
! 3388: goto die;
! 3389: }
! 3390: break;
! 3391: default:
! 3392: goto die;
! 3393: }
! 3394: #if defined MIPS_DEBUG_DISAS
! 3395: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 3396: fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
! 3397: rn, reg, sel);
! 3398: }
! 3399: #endif
! 3400: return;
! 3401:
! 3402: die:
! 3403: #if defined MIPS_DEBUG_DISAS
! 3404: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 3405: fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
! 3406: rn, reg, sel);
! 3407: }
! 3408: #endif
! 3409: generate_exception(ctx, EXCP_RI);
! 3410: }
! 3411:
! 3412: static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
! 3413: {
! 3414: const char *rn = "invalid";
! 3415:
! 3416: switch (reg) {
! 3417: case 0:
! 3418: switch (sel) {
! 3419: case 0:
! 3420: gen_op_mtc0_index();
! 3421: rn = "Index";
! 3422: break;
! 3423: case 1:
! 3424: // gen_op_dmtc0_mvpcontrol(); /* MT ASE */
! 3425: rn = "MVPControl";
! 3426: // break;
! 3427: case 2:
! 3428: // gen_op_dmtc0_mvpconf0(); /* MT ASE */
! 3429: rn = "MVPConf0";
! 3430: // break;
! 3431: case 3:
! 3432: // gen_op_dmtc0_mvpconf1(); /* MT ASE */
! 3433: rn = "MVPConf1";
! 3434: // break;
! 3435: default:
! 3436: goto die;
! 3437: }
! 3438: break;
! 3439: case 1:
! 3440: switch (sel) {
! 3441: case 0:
! 3442: /* ignored */
! 3443: rn = "Random";
! 3444: break;
! 3445: case 1:
! 3446: // gen_op_dmtc0_vpecontrol(); /* MT ASE */
! 3447: rn = "VPEControl";
! 3448: // break;
! 3449: case 2:
! 3450: // gen_op_dmtc0_vpeconf0(); /* MT ASE */
! 3451: rn = "VPEConf0";
! 3452: // break;
! 3453: case 3:
! 3454: // gen_op_dmtc0_vpeconf1(); /* MT ASE */
! 3455: rn = "VPEConf1";
! 3456: // break;
! 3457: case 4:
! 3458: // gen_op_dmtc0_YQMask(); /* MT ASE */
! 3459: rn = "YQMask";
! 3460: // break;
! 3461: case 5:
! 3462: // gen_op_dmtc0_vpeschedule(); /* MT ASE */
! 3463: rn = "VPESchedule";
! 3464: // break;
! 3465: case 6:
! 3466: // gen_op_dmtc0_vpeschefback(); /* MT ASE */
! 3467: rn = "VPEScheFBack";
! 3468: // break;
! 3469: case 7:
! 3470: // gen_op_dmtc0_vpeopt(); /* MT ASE */
! 3471: rn = "VPEOpt";
! 3472: // break;
! 3473: default:
! 3474: goto die;
! 3475: }
! 3476: break;
! 3477: case 2:
! 3478: switch (sel) {
! 3479: case 0:
! 3480: gen_op_dmtc0_entrylo0();
! 3481: rn = "EntryLo0";
! 3482: break;
! 3483: case 1:
! 3484: // gen_op_dmtc0_tcstatus(); /* MT ASE */
! 3485: rn = "TCStatus";
! 3486: // break;
! 3487: case 2:
! 3488: // gen_op_dmtc0_tcbind(); /* MT ASE */
! 3489: rn = "TCBind";
! 3490: // break;
! 3491: case 3:
! 3492: // gen_op_dmtc0_tcrestart(); /* MT ASE */
! 3493: rn = "TCRestart";
! 3494: // break;
! 3495: case 4:
! 3496: // gen_op_dmtc0_tchalt(); /* MT ASE */
! 3497: rn = "TCHalt";
! 3498: // break;
! 3499: case 5:
! 3500: // gen_op_dmtc0_tccontext(); /* MT ASE */
! 3501: rn = "TCContext";
! 3502: // break;
! 3503: case 6:
! 3504: // gen_op_dmtc0_tcschedule(); /* MT ASE */
! 3505: rn = "TCSchedule";
! 3506: // break;
! 3507: case 7:
! 3508: // gen_op_dmtc0_tcschefback(); /* MT ASE */
! 3509: rn = "TCScheFBack";
! 3510: // break;
! 3511: default:
! 3512: goto die;
! 3513: }
! 3514: break;
! 3515: case 3:
! 3516: switch (sel) {
! 3517: case 0:
! 3518: gen_op_dmtc0_entrylo1();
! 3519: rn = "EntryLo1";
! 3520: break;
! 3521: default:
! 3522: goto die;
! 3523: }
! 3524: break;
! 3525: case 4:
! 3526: switch (sel) {
! 3527: case 0:
! 3528: gen_op_dmtc0_context();
! 3529: rn = "Context";
! 3530: break;
! 3531: case 1:
! 3532: // gen_op_dmtc0_contextconfig(); /* SmartMIPS ASE */
! 3533: rn = "ContextConfig";
! 3534: // break;
! 3535: default:
! 3536: goto die;
! 3537: }
! 3538: break;
! 3539: case 5:
! 3540: switch (sel) {
! 3541: case 0:
! 3542: gen_op_mtc0_pagemask();
! 3543: rn = "PageMask";
! 3544: break;
! 3545: case 1:
! 3546: gen_op_mtc0_pagegrain();
! 3547: rn = "PageGrain";
! 3548: break;
! 3549: default:
! 3550: goto die;
! 3551: }
! 3552: break;
! 3553: case 6:
! 3554: switch (sel) {
! 3555: case 0:
! 3556: gen_op_mtc0_wired();
! 3557: rn = "Wired";
! 3558: break;
! 3559: case 1:
! 3560: // gen_op_dmtc0_srsconf0(); /* shadow registers */
! 3561: rn = "SRSConf0";
! 3562: // break;
! 3563: case 2:
! 3564: // gen_op_dmtc0_srsconf1(); /* shadow registers */
! 3565: rn = "SRSConf1";
! 3566: // break;
! 3567: case 3:
! 3568: // gen_op_dmtc0_srsconf2(); /* shadow registers */
! 3569: rn = "SRSConf2";
! 3570: // break;
! 3571: case 4:
! 3572: // gen_op_dmtc0_srsconf3(); /* shadow registers */
! 3573: rn = "SRSConf3";
! 3574: // break;
! 3575: case 5:
! 3576: // gen_op_dmtc0_srsconf4(); /* shadow registers */
! 3577: rn = "SRSConf4";
! 3578: // break;
! 3579: default:
! 3580: goto die;
! 3581: }
! 3582: break;
! 3583: case 7:
! 3584: switch (sel) {
! 3585: case 0:
! 3586: gen_op_mtc0_hwrena();
! 3587: rn = "HWREna";
! 3588: break;
! 3589: default:
! 3590: goto die;
! 3591: }
! 3592: break;
! 3593: case 8:
! 3594: /* ignored */
! 3595: rn = "BadVaddr";
! 3596: break;
! 3597: case 9:
! 3598: switch (sel) {
! 3599: case 0:
! 3600: gen_op_mtc0_count();
! 3601: rn = "Count";
! 3602: break;
! 3603: /* 6,7 are implementation dependent */
! 3604: default:
! 3605: goto die;
! 3606: }
! 3607: /* Stop translation as we may have switched the execution mode */
! 3608: ctx->bstate = BS_STOP;
! 3609: break;
! 3610: case 10:
! 3611: switch (sel) {
! 3612: case 0:
! 3613: gen_op_mtc0_entryhi();
! 3614: rn = "EntryHi";
! 3615: break;
! 3616: default:
! 3617: goto die;
! 3618: }
! 3619: break;
! 3620: case 11:
! 3621: switch (sel) {
! 3622: case 0:
! 3623: gen_op_mtc0_compare();
! 3624: rn = "Compare";
! 3625: break;
! 3626: /* 6,7 are implementation dependent */
! 3627: default:
! 3628: goto die;
! 3629: }
! 3630: /* Stop translation as we may have switched the execution mode */
! 3631: ctx->bstate = BS_STOP;
! 3632: break;
! 3633: case 12:
! 3634: switch (sel) {
! 3635: case 0:
! 3636: gen_op_mtc0_status();
! 3637: rn = "Status";
! 3638: break;
! 3639: case 1:
! 3640: gen_op_mtc0_intctl();
! 3641: rn = "IntCtl";
! 3642: break;
! 3643: case 2:
! 3644: gen_op_mtc0_srsctl();
! 3645: rn = "SRSCtl";
! 3646: break;
! 3647: case 3:
! 3648: gen_op_mtc0_srsmap(); /* shadow registers */
! 3649: rn = "SRSMap";
! 3650: break;
! 3651: default:
! 3652: goto die;
! 3653: }
! 3654: /* Stop translation as we may have switched the execution mode */
! 3655: ctx->bstate = BS_STOP;
! 3656: break;
! 3657: case 13:
! 3658: switch (sel) {
! 3659: case 0:
! 3660: gen_op_mtc0_cause();
! 3661: rn = "Cause";
! 3662: break;
! 3663: default:
! 3664: goto die;
! 3665: }
! 3666: /* Stop translation as we may have switched the execution mode */
! 3667: ctx->bstate = BS_STOP;
! 3668: break;
! 3669: case 14:
! 3670: switch (sel) {
! 3671: case 0:
! 3672: gen_op_dmtc0_epc();
! 3673: rn = "EPC";
! 3674: break;
! 3675: default:
! 3676: goto die;
! 3677: }
! 3678: break;
! 3679: case 15:
! 3680: switch (sel) {
! 3681: case 0:
! 3682: /* ignored */
! 3683: rn = "PRid";
! 3684: break;
! 3685: case 1:
! 3686: gen_op_mtc0_ebase();
! 3687: rn = "EBase";
! 3688: break;
! 3689: default:
! 3690: goto die;
! 3691: }
! 3692: break;
! 3693: case 16:
! 3694: switch (sel) {
! 3695: case 0:
! 3696: gen_op_mtc0_config0();
! 3697: rn = "Config";
! 3698: break;
! 3699: case 1:
! 3700: /* ignored */
! 3701: rn = "Config1";
! 3702: break;
! 3703: case 2:
! 3704: gen_op_mtc0_config2();
! 3705: rn = "Config2";
! 3706: break;
! 3707: case 3:
! 3708: /* ignored */
! 3709: rn = "Config3";
! 3710: break;
! 3711: /* 6,7 are implementation dependent */
! 3712: default:
! 3713: rn = "Invalid config selector";
! 3714: goto die;
! 3715: }
! 3716: /* Stop translation as we may have switched the execution mode */
! 3717: ctx->bstate = BS_STOP;
! 3718: break;
! 3719: case 17:
! 3720: switch (sel) {
! 3721: case 0:
! 3722: /* ignored */
! 3723: rn = "LLAddr";
! 3724: break;
! 3725: default:
! 3726: goto die;
! 3727: }
! 3728: break;
! 3729: case 18:
! 3730: switch (sel) {
! 3731: case 0:
! 3732: gen_op_dmtc0_watchlo0();
! 3733: rn = "WatchLo";
! 3734: break;
! 3735: case 1:
! 3736: // gen_op_dmtc0_watchlo1();
! 3737: rn = "WatchLo1";
! 3738: // break;
! 3739: case 2:
! 3740: // gen_op_dmtc0_watchlo2();
! 3741: rn = "WatchLo2";
! 3742: // break;
! 3743: case 3:
! 3744: // gen_op_dmtc0_watchlo3();
! 3745: rn = "WatchLo3";
! 3746: // break;
! 3747: case 4:
! 3748: // gen_op_dmtc0_watchlo4();
! 3749: rn = "WatchLo4";
! 3750: // break;
! 3751: case 5:
! 3752: // gen_op_dmtc0_watchlo5();
! 3753: rn = "WatchLo5";
! 3754: // break;
! 3755: case 6:
! 3756: // gen_op_dmtc0_watchlo6();
! 3757: rn = "WatchLo6";
! 3758: // break;
! 3759: case 7:
! 3760: // gen_op_dmtc0_watchlo7();
! 3761: rn = "WatchLo7";
! 3762: // break;
! 3763: default:
! 3764: goto die;
! 3765: }
! 3766: break;
! 3767: case 19:
! 3768: switch (sel) {
! 3769: case 0:
! 3770: gen_op_mtc0_watchhi0();
! 3771: rn = "WatchHi";
! 3772: break;
! 3773: case 1:
! 3774: // gen_op_dmtc0_watchhi1();
! 3775: rn = "WatchHi1";
! 3776: // break;
! 3777: case 2:
! 3778: // gen_op_dmtc0_watchhi2();
! 3779: rn = "WatchHi2";
! 3780: // break;
! 3781: case 3:
! 3782: // gen_op_dmtc0_watchhi3();
! 3783: rn = "WatchHi3";
! 3784: // break;
! 3785: case 4:
! 3786: // gen_op_dmtc0_watchhi4();
! 3787: rn = "WatchHi4";
! 3788: // break;
! 3789: case 5:
! 3790: // gen_op_dmtc0_watchhi5();
! 3791: rn = "WatchHi5";
! 3792: // break;
! 3793: case 6:
! 3794: // gen_op_dmtc0_watchhi6();
! 3795: rn = "WatchHi6";
! 3796: // break;
! 3797: case 7:
! 3798: // gen_op_dmtc0_watchhi7();
! 3799: rn = "WatchHi7";
! 3800: // break;
! 3801: default:
! 3802: goto die;
! 3803: }
! 3804: break;
! 3805: case 20:
! 3806: switch (sel) {
! 3807: case 0:
! 3808: /* 64 bit MMU only */
! 3809: gen_op_dmtc0_xcontext();
! 3810: rn = "XContext";
! 3811: break;
! 3812: default:
! 3813: goto die;
! 3814: }
! 3815: break;
! 3816: case 21:
! 3817: /* Officially reserved, but sel 0 is used for R1x000 framemask */
! 3818: switch (sel) {
! 3819: case 0:
! 3820: gen_op_mtc0_framemask();
! 3821: rn = "Framemask";
! 3822: break;
! 3823: default:
! 3824: goto die;
! 3825: }
! 3826: break;
! 3827: case 22:
! 3828: /* ignored */
! 3829: rn = "Diagnostic"; /* implementation dependent */
! 3830: break;
! 3831: case 23:
! 3832: switch (sel) {
! 3833: case 0:
! 3834: gen_op_mtc0_debug(); /* EJTAG support */
! 3835: rn = "Debug";
! 3836: break;
! 3837: case 1:
! 3838: // gen_op_dmtc0_tracecontrol(); /* PDtrace support */
! 3839: rn = "TraceControl";
! 3840: // break;
! 3841: case 2:
! 3842: // gen_op_dmtc0_tracecontrol2(); /* PDtrace support */
! 3843: rn = "TraceControl2";
! 3844: // break;
! 3845: case 3:
! 3846: // gen_op_dmtc0_usertracedata(); /* PDtrace support */
! 3847: rn = "UserTraceData";
! 3848: // break;
! 3849: case 4:
! 3850: // gen_op_dmtc0_debug(); /* PDtrace support */
! 3851: rn = "TraceBPC";
! 3852: // break;
! 3853: default:
! 3854: goto die;
! 3855: }
! 3856: /* Stop translation as we may have switched the execution mode */
! 3857: ctx->bstate = BS_STOP;
! 3858: break;
! 3859: case 24:
! 3860: switch (sel) {
! 3861: case 0:
! 3862: gen_op_dmtc0_depc(); /* EJTAG support */
! 3863: rn = "DEPC";
! 3864: break;
! 3865: default:
! 3866: goto die;
! 3867: }
! 3868: break;
! 3869: case 25:
! 3870: switch (sel) {
! 3871: case 0:
! 3872: gen_op_mtc0_performance0();
! 3873: rn = "Performance0";
! 3874: break;
! 3875: case 1:
! 3876: // gen_op_dmtc0_performance1();
! 3877: rn = "Performance1";
! 3878: // break;
! 3879: case 2:
! 3880: // gen_op_dmtc0_performance2();
! 3881: rn = "Performance2";
! 3882: // break;
! 3883: case 3:
! 3884: // gen_op_dmtc0_performance3();
! 3885: rn = "Performance3";
! 3886: // break;
! 3887: case 4:
! 3888: // gen_op_dmtc0_performance4();
! 3889: rn = "Performance4";
! 3890: // break;
! 3891: case 5:
! 3892: // gen_op_dmtc0_performance5();
! 3893: rn = "Performance5";
! 3894: // break;
! 3895: case 6:
! 3896: // gen_op_dmtc0_performance6();
! 3897: rn = "Performance6";
! 3898: // break;
! 3899: case 7:
! 3900: // gen_op_dmtc0_performance7();
! 3901: rn = "Performance7";
! 3902: // break;
! 3903: default:
! 3904: goto die;
! 3905: }
! 3906: break;
! 3907: case 26:
! 3908: /* ignored */
! 3909: rn = "ECC";
! 3910: break;
! 3911: case 27:
! 3912: switch (sel) {
! 3913: case 0 ... 3:
! 3914: /* ignored */
! 3915: rn = "CacheErr";
! 3916: break;
! 3917: default:
! 3918: goto die;
! 3919: }
! 3920: break;
! 3921: case 28:
! 3922: switch (sel) {
! 3923: case 0:
! 3924: case 2:
! 3925: case 4:
! 3926: case 6:
! 3927: gen_op_mtc0_taglo();
! 3928: rn = "TagLo";
! 3929: break;
! 3930: case 1:
! 3931: case 3:
! 3932: case 5:
! 3933: case 7:
! 3934: gen_op_mtc0_datalo();
! 3935: rn = "DataLo";
! 3936: break;
! 3937: default:
! 3938: goto die;
! 3939: }
! 3940: break;
! 3941: case 29:
! 3942: switch (sel) {
! 3943: case 0:
! 3944: case 2:
! 3945: case 4:
! 3946: case 6:
! 3947: gen_op_mtc0_taghi();
! 3948: rn = "TagHi";
! 3949: break;
! 3950: case 1:
! 3951: case 3:
! 3952: case 5:
! 3953: case 7:
! 3954: gen_op_mtc0_datahi();
! 3955: rn = "DataHi";
! 3956: break;
! 3957: default:
! 3958: rn = "invalid sel";
! 3959: goto die;
! 3960: }
! 3961: break;
! 3962: case 30:
! 3963: switch (sel) {
! 3964: case 0:
! 3965: gen_op_dmtc0_errorepc();
! 3966: rn = "ErrorEPC";
! 3967: break;
! 3968: default:
! 3969: goto die;
! 3970: }
! 3971: break;
! 3972: case 31:
! 3973: switch (sel) {
! 3974: case 0:
! 3975: gen_op_mtc0_desave(); /* EJTAG support */
! 3976: rn = "DESAVE";
! 3977: break;
! 3978: default:
! 3979: goto die;
! 3980: }
! 3981: /* Stop translation as we may have switched the execution mode */
! 3982: ctx->bstate = BS_STOP;
! 3983: break;
! 3984: default:
! 3985: goto die;
! 3986: }
! 3987: #if defined MIPS_DEBUG_DISAS
! 3988: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 3989: fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
! 3990: rn, reg, sel);
! 3991: }
! 3992: #endif
! 3993: return;
! 3994:
! 3995: die:
! 3996: #if defined MIPS_DEBUG_DISAS
! 3997: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 3998: fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
! 3999: rn, reg, sel);
! 4000: }
! 4001: #endif
! 4002: generate_exception(ctx, EXCP_RI);
! 4003: }
! 4004:
! 4005: static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
! 4006: {
! 4007: const char *opn = "unk";
! 4008:
! 4009: if ((!ctx->CP0_Status & (1 << CP0St_CU0) &&
! 4010: (ctx->hflags & MIPS_HFLAG_UM)) &&
! 4011: !(ctx->hflags & MIPS_HFLAG_ERL) &&
! 4012: !(ctx->hflags & MIPS_HFLAG_EXL)) {
! 4013: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 4014: fprintf(logfile, "CP0 is not usable\n");
! 4015: }
! 4016: generate_exception (ctx, EXCP_CpU);
! 4017: return;
! 4018: }
! 4019:
! 4020: switch (opc) {
! 4021: case OPC_MFC0:
! 4022: if (rt == 0) {
! 4023: /* Treat as NOP */
! 4024: return;
! 4025: }
! 4026: gen_mfc0(ctx, rd, ctx->opcode & 0x7);
! 4027: gen_op_store_T0_gpr(rt);
! 4028: opn = "mfc0";
! 4029: break;
! 4030: case OPC_MTC0:
! 4031: /* If we get an exception, we want to restart at next instruction */
! 4032: /* XXX: breaks for mtc in delay slot */
! 4033: ctx->pc += 4;
! 4034: save_cpu_state(ctx, 1);
! 4035: ctx->pc -= 4;
! 4036: GEN_LOAD_REG_TN(T0, rt);
! 4037: gen_mtc0(ctx, rd, ctx->opcode & 0x7);
! 4038: opn = "mtc0";
! 4039: break;
! 4040: case OPC_DMFC0:
! 4041: if (rt == 0) {
! 4042: /* Treat as NOP */
! 4043: return;
! 4044: }
! 4045: gen_dmfc0(ctx, rd, ctx->opcode & 0x7);
! 4046: gen_op_store_T0_gpr(rt);
! 4047: opn = "dmfc0";
! 4048: break;
! 4049: case OPC_DMTC0:
! 4050: /* If we get an exception, we want to restart at next instruction */
! 4051: /* XXX: breaks for dmtc in delay slot */
! 4052: ctx->pc += 4;
! 4053: save_cpu_state(ctx, 1);
! 4054: ctx->pc -= 4;
! 4055: GEN_LOAD_REG_TN(T0, rt);
! 4056: gen_dmtc0(ctx, rd, ctx->opcode & 0x7);
! 4057: opn = "dmtc0";
! 4058: break;
! 4059: #if defined(MIPS_USES_R4K_TLB)
! 4060: case OPC_TLBWI:
! 4061: gen_op_tlbwi();
! 4062: opn = "tlbwi";
! 4063: break;
! 4064: case OPC_TLBWR:
! 4065: gen_op_tlbwr();
! 4066: opn = "tlbwr";
! 4067: break;
! 4068: case OPC_TLBP:
! 4069: gen_op_tlbp();
! 4070: opn = "tlbp";
! 4071: break;
! 4072: case OPC_TLBR:
! 4073: gen_op_tlbr();
! 4074: opn = "tlbr";
! 4075: break;
! 4076: #endif
! 4077: case OPC_ERET:
! 4078: opn = "eret";
! 4079: save_cpu_state(ctx, 0);
! 4080: gen_op_eret();
! 4081: ctx->bstate = BS_EXCP;
! 4082: break;
! 4083: case OPC_DERET:
! 4084: opn = "deret";
! 4085: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
! 4086: generate_exception(ctx, EXCP_RI);
! 4087: } else {
! 4088: save_cpu_state(ctx, 0);
! 4089: gen_op_deret();
! 4090: ctx->bstate = BS_EXCP;
! 4091: }
! 4092: break;
! 4093: case OPC_WAIT:
! 4094: opn = "wait";
! 4095: /* If we get an exception, we want to restart at next instruction */
! 4096: ctx->pc += 4;
! 4097: save_cpu_state(ctx, 1);
! 4098: ctx->pc -= 4;
! 4099: gen_op_wait();
! 4100: ctx->bstate = BS_EXCP;
! 4101: break;
! 4102: default:
! 4103: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 4104: fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
! 4105: ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
! 4106: ((ctx->opcode >> 16) & 0x1F));
! 4107: }
! 4108: generate_exception(ctx, EXCP_RI);
! 4109: return;
! 4110: }
! 4111: MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
! 4112: }
! 4113:
! 4114: #ifdef MIPS_USES_FPU
! 4115:
! 4116: /* CP1 Branches (before delay slot) */
! 4117: static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
! 4118: int32_t offset)
! 4119: {
! 4120: target_ulong btarget;
! 4121:
! 4122: btarget = ctx->pc + 4 + offset;
! 4123:
! 4124: switch (op) {
! 4125: case OPC_BC1F:
! 4126: gen_op_bc1f();
! 4127: MIPS_DEBUG("bc1f " TLSZ, btarget);
! 4128: goto not_likely;
! 4129: case OPC_BC1FL:
! 4130: gen_op_bc1f();
! 4131: MIPS_DEBUG("bc1fl " TLSZ, btarget);
! 4132: goto likely;
! 4133: case OPC_BC1T:
! 4134: gen_op_bc1t();
! 4135: MIPS_DEBUG("bc1t " TLSZ, btarget);
! 4136: not_likely:
! 4137: ctx->hflags |= MIPS_HFLAG_BC;
! 4138: break;
! 4139: case OPC_BC1TL:
! 4140: gen_op_bc1t();
! 4141: MIPS_DEBUG("bc1tl " TLSZ, btarget);
! 4142: likely:
! 4143: ctx->hflags |= MIPS_HFLAG_BL;
! 4144: break;
! 4145: default:
! 4146: MIPS_INVAL("cp1 branch/jump");
! 4147: generate_exception_err (ctx, EXCP_RI, 1);
! 4148: return;
! 4149: }
! 4150: gen_op_set_bcond();
! 4151:
! 4152: MIPS_DEBUG("enter ds: cond %02x target " TLSZ,
! 4153: ctx->hflags, btarget);
! 4154: ctx->btarget = btarget;
! 4155:
! 4156: return;
! 4157: }
! 4158:
! 4159: /* Coprocessor 1 (FPU) */
! 4160: static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
! 4161: {
! 4162: const char *opn = "unk";
! 4163:
! 4164: switch (opc) {
! 4165: case OPC_MFC1:
! 4166: GEN_LOAD_FREG_FTN(WT0, fs);
! 4167: gen_op_mfc1();
! 4168: GEN_STORE_TN_REG(rt, T0);
! 4169: opn = "mfc1";
! 4170: break;
! 4171: case OPC_MTC1:
! 4172: GEN_LOAD_REG_TN(T0, rt);
! 4173: gen_op_mtc1();
! 4174: GEN_STORE_FTN_FREG(fs, WT0);
! 4175: opn = "mtc1";
! 4176: break;
! 4177: case OPC_CFC1:
! 4178: if (fs != 0 && fs != 31) {
! 4179: MIPS_INVAL("cfc1 freg");
! 4180: generate_exception_err (ctx, EXCP_RI, 1);
! 4181: return;
! 4182: }
! 4183: GEN_LOAD_IMM_TN(T1, fs);
! 4184: gen_op_cfc1();
! 4185: GEN_STORE_TN_REG(rt, T0);
! 4186: opn = "cfc1";
! 4187: break;
! 4188: case OPC_CTC1:
! 4189: if (fs != 0 && fs != 31) {
! 4190: MIPS_INVAL("ctc1 freg");
! 4191: generate_exception_err (ctx, EXCP_RI, 1);
! 4192: return;
! 4193: }
! 4194: GEN_LOAD_IMM_TN(T1, fs);
! 4195: GEN_LOAD_REG_TN(T0, rt);
! 4196: gen_op_ctc1();
! 4197: opn = "ctc1";
! 4198: break;
! 4199: case OPC_DMFC1:
! 4200: case OPC_DMTC1:
! 4201: /* Not implemented, fallthrough. */
! 4202: default:
! 4203: if (loglevel & CPU_LOG_TB_IN_ASM) {
! 4204: fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
! 4205: ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
! 4206: ((ctx->opcode >> 16) & 0x1F));
! 4207: }
! 4208: generate_exception_err (ctx, EXCP_RI, 1);
1.1.1.4 root 4209: return;
4210: }
4211: MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
4212: }
4213:
4214: /* verify if floating point register is valid; an operation is not defined
4215: * if bit 0 of any register specification is set and the FR bit in the
4216: * Status register equals zero, since the register numbers specify an
4217: * even-odd pair of adjacent coprocessor general registers. When the FR bit
4218: * in the Status register equals one, both even and odd register numbers
4219: * are valid.
4220: *
4221: * Multiple float registers can be checked by calling
4222: * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
4223: */
4224: #define CHECK_FR(ctx, freg) do { \
4225: if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
1.1.1.5 ! root 4226: generate_exception_err (ctx, EXCP_RI, 1); \
1.1.1.4 root 4227: return; \
4228: } \
4229: } while(0)
4230:
4231: #define FOP(func, fmt) (((fmt) << 21) | (func))
4232:
1.1.1.5 ! root 4233: static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
1.1.1.4 root 4234: {
1.1.1.5 ! root 4235: const char *opn = "unk";
1.1.1.4 root 4236: const char *condnames[] = {
4237: "c.f",
4238: "c.un",
4239: "c.eq",
4240: "c.ueq",
4241: "c.olt",
4242: "c.ult",
4243: "c.ole",
4244: "c.ule",
4245: "c.sf",
4246: "c.ngle",
4247: "c.seq",
4248: "c.ngl",
4249: "c.lt",
4250: "c.nge",
4251: "c.le",
4252: "c.ngt",
4253: };
4254: int binary = 0;
1.1.1.5 ! root 4255: uint32_t func = ctx->opcode & 0x3f;
! 4256:
1.1.1.4 root 4257: switch (ctx->opcode & FOP(0x3f, 0x1f)) {
4258: case FOP(0, 17):
4259: CHECK_FR(ctx, fs | ft | fd);
4260: GEN_LOAD_FREG_FTN(DT0, fs);
4261: GEN_LOAD_FREG_FTN(DT1, ft);
4262: gen_op_float_add_d();
4263: GEN_STORE_FTN_FREG(fd, DT2);
4264: opn = "add.d";
4265: binary = 1;
4266: break;
4267: case FOP(1, 17):
4268: CHECK_FR(ctx, fs | ft | fd);
4269: GEN_LOAD_FREG_FTN(DT0, fs);
4270: GEN_LOAD_FREG_FTN(DT1, ft);
4271: gen_op_float_sub_d();
4272: GEN_STORE_FTN_FREG(fd, DT2);
4273: opn = "sub.d";
4274: binary = 1;
4275: break;
4276: case FOP(2, 17):
4277: CHECK_FR(ctx, fs | ft | fd);
4278: GEN_LOAD_FREG_FTN(DT0, fs);
4279: GEN_LOAD_FREG_FTN(DT1, ft);
4280: gen_op_float_mul_d();
4281: GEN_STORE_FTN_FREG(fd, DT2);
4282: opn = "mul.d";
4283: binary = 1;
4284: break;
4285: case FOP(3, 17):
4286: CHECK_FR(ctx, fs | ft | fd);
4287: GEN_LOAD_FREG_FTN(DT0, fs);
4288: GEN_LOAD_FREG_FTN(DT1, ft);
4289: gen_op_float_div_d();
4290: GEN_STORE_FTN_FREG(fd, DT2);
4291: opn = "div.d";
4292: binary = 1;
4293: break;
4294: case FOP(4, 17):
4295: CHECK_FR(ctx, fs | fd);
4296: GEN_LOAD_FREG_FTN(DT0, fs);
4297: gen_op_float_sqrt_d();
4298: GEN_STORE_FTN_FREG(fd, DT2);
4299: opn = "sqrt.d";
4300: break;
4301: case FOP(5, 17):
4302: CHECK_FR(ctx, fs | fd);
4303: GEN_LOAD_FREG_FTN(DT0, fs);
4304: gen_op_float_abs_d();
4305: GEN_STORE_FTN_FREG(fd, DT2);
4306: opn = "abs.d";
4307: break;
4308: case FOP(6, 17):
4309: CHECK_FR(ctx, fs | fd);
4310: GEN_LOAD_FREG_FTN(DT0, fs);
4311: gen_op_float_mov_d();
4312: GEN_STORE_FTN_FREG(fd, DT2);
4313: opn = "mov.d";
4314: break;
4315: case FOP(7, 17):
4316: CHECK_FR(ctx, fs | fd);
4317: GEN_LOAD_FREG_FTN(DT0, fs);
4318: gen_op_float_chs_d();
4319: GEN_STORE_FTN_FREG(fd, DT2);
4320: opn = "neg.d";
4321: break;
4322: /* 8 - round.l */
4323: /* 9 - trunc.l */
4324: /* 10 - ceil.l */
4325: /* 11 - floor.l */
4326: case FOP(12, 17):
4327: CHECK_FR(ctx, fs | fd);
4328: GEN_LOAD_FREG_FTN(DT0, fs);
4329: gen_op_float_roundw_d();
4330: GEN_STORE_FTN_FREG(fd, WT2);
4331: opn = "round.w.d";
4332: break;
4333: case FOP(13, 17):
4334: CHECK_FR(ctx, fs | fd);
4335: GEN_LOAD_FREG_FTN(DT0, fs);
4336: gen_op_float_truncw_d();
4337: GEN_STORE_FTN_FREG(fd, WT2);
4338: opn = "trunc.w.d";
4339: break;
4340: case FOP(14, 17):
4341: CHECK_FR(ctx, fs | fd);
4342: GEN_LOAD_FREG_FTN(DT0, fs);
4343: gen_op_float_ceilw_d();
4344: GEN_STORE_FTN_FREG(fd, WT2);
4345: opn = "ceil.w.d";
4346: break;
4347: case FOP(15, 17):
4348: CHECK_FR(ctx, fs | fd);
4349: GEN_LOAD_FREG_FTN(DT0, fs);
4350: gen_op_float_floorw_d();
4351: GEN_STORE_FTN_FREG(fd, WT2);
1.1.1.5 ! root 4352: opn = "floor.w.d";
! 4353: break;
! 4354: case FOP(33, 16): /* cvt.d.s */
! 4355: CHECK_FR(ctx, fs | fd);
! 4356: GEN_LOAD_FREG_FTN(WT0, fs);
! 4357: gen_op_float_cvtd_s();
! 4358: GEN_STORE_FTN_FREG(fd, DT2);
! 4359: opn = "cvt.d.s";
1.1.1.4 root 4360: break;
4361: case FOP(33, 20): /* cvt.d.w */
4362: CHECK_FR(ctx, fs | fd);
4363: GEN_LOAD_FREG_FTN(WT0, fs);
4364: gen_op_float_cvtd_w();
4365: GEN_STORE_FTN_FREG(fd, DT2);
4366: opn = "cvt.d.w";
4367: break;
4368: case FOP(48, 17):
4369: case FOP(49, 17):
4370: case FOP(50, 17):
4371: case FOP(51, 17):
4372: case FOP(52, 17):
4373: case FOP(53, 17):
4374: case FOP(54, 17):
4375: case FOP(55, 17):
4376: case FOP(56, 17):
4377: case FOP(57, 17):
4378: case FOP(58, 17):
4379: case FOP(59, 17):
4380: case FOP(60, 17):
4381: case FOP(61, 17):
4382: case FOP(62, 17):
4383: case FOP(63, 17):
4384: CHECK_FR(ctx, fs | ft);
4385: GEN_LOAD_FREG_FTN(DT0, fs);
4386: GEN_LOAD_FREG_FTN(DT1, ft);
4387: gen_cmp_d(func-48);
4388: opn = condnames[func-48];
4389: break;
4390: case FOP(0, 16):
4391: CHECK_FR(ctx, fs | ft | fd);
4392: GEN_LOAD_FREG_FTN(WT0, fs);
4393: GEN_LOAD_FREG_FTN(WT1, ft);
4394: gen_op_float_add_s();
4395: GEN_STORE_FTN_FREG(fd, WT2);
4396: opn = "add.s";
4397: binary = 1;
4398: break;
4399: case FOP(1, 16):
4400: CHECK_FR(ctx, fs | ft | fd);
4401: GEN_LOAD_FREG_FTN(WT0, fs);
4402: GEN_LOAD_FREG_FTN(WT1, ft);
4403: gen_op_float_sub_s();
4404: GEN_STORE_FTN_FREG(fd, WT2);
4405: opn = "sub.s";
4406: binary = 1;
4407: break;
4408: case FOP(2, 16):
4409: CHECK_FR(ctx, fs | ft | fd);
4410: GEN_LOAD_FREG_FTN(WT0, fs);
4411: GEN_LOAD_FREG_FTN(WT1, ft);
4412: gen_op_float_mul_s();
4413: GEN_STORE_FTN_FREG(fd, WT2);
4414: opn = "mul.s";
4415: binary = 1;
4416: break;
4417: case FOP(3, 16):
4418: CHECK_FR(ctx, fs | ft | fd);
4419: GEN_LOAD_FREG_FTN(WT0, fs);
4420: GEN_LOAD_FREG_FTN(WT1, ft);
4421: gen_op_float_div_s();
4422: GEN_STORE_FTN_FREG(fd, WT2);
4423: opn = "div.s";
4424: binary = 1;
4425: break;
4426: case FOP(4, 16):
4427: CHECK_FR(ctx, fs | fd);
4428: GEN_LOAD_FREG_FTN(WT0, fs);
4429: gen_op_float_sqrt_s();
4430: GEN_STORE_FTN_FREG(fd, WT2);
4431: opn = "sqrt.s";
4432: break;
4433: case FOP(5, 16):
4434: CHECK_FR(ctx, fs | fd);
4435: GEN_LOAD_FREG_FTN(WT0, fs);
4436: gen_op_float_abs_s();
4437: GEN_STORE_FTN_FREG(fd, WT2);
4438: opn = "abs.s";
4439: break;
4440: case FOP(6, 16):
4441: CHECK_FR(ctx, fs | fd);
4442: GEN_LOAD_FREG_FTN(WT0, fs);
4443: gen_op_float_mov_s();
4444: GEN_STORE_FTN_FREG(fd, WT2);
4445: opn = "mov.s";
4446: break;
4447: case FOP(7, 16):
4448: CHECK_FR(ctx, fs | fd);
4449: GEN_LOAD_FREG_FTN(WT0, fs);
4450: gen_op_float_chs_s();
4451: GEN_STORE_FTN_FREG(fd, WT2);
4452: opn = "neg.s";
4453: break;
4454: case FOP(12, 16):
4455: CHECK_FR(ctx, fs | fd);
4456: GEN_LOAD_FREG_FTN(WT0, fs);
4457: gen_op_float_roundw_s();
4458: GEN_STORE_FTN_FREG(fd, WT2);
4459: opn = "round.w.s";
4460: break;
4461: case FOP(13, 16):
4462: CHECK_FR(ctx, fs | fd);
4463: GEN_LOAD_FREG_FTN(WT0, fs);
4464: gen_op_float_truncw_s();
4465: GEN_STORE_FTN_FREG(fd, WT2);
4466: opn = "trunc.w.s";
4467: break;
1.1.1.5 ! root 4468: case FOP(32, 17): /* cvt.s.d */
! 4469: CHECK_FR(ctx, fs | fd);
! 4470: GEN_LOAD_FREG_FTN(DT0, fs);
! 4471: gen_op_float_cvts_d();
! 4472: GEN_STORE_FTN_FREG(fd, WT2);
! 4473: opn = "cvt.s.d";
! 4474: break;
1.1.1.4 root 4475: case FOP(32, 20): /* cvt.s.w */
4476: CHECK_FR(ctx, fs | fd);
4477: GEN_LOAD_FREG_FTN(WT0, fs);
4478: gen_op_float_cvts_w();
4479: GEN_STORE_FTN_FREG(fd, WT2);
4480: opn = "cvt.s.w";
4481: break;
4482: case FOP(36, 16): /* cvt.w.s */
4483: CHECK_FR(ctx, fs | fd);
4484: GEN_LOAD_FREG_FTN(WT0, fs);
4485: gen_op_float_cvtw_s();
4486: GEN_STORE_FTN_FREG(fd, WT2);
4487: opn = "cvt.w.s";
4488: break;
4489: case FOP(36, 17): /* cvt.w.d */
4490: CHECK_FR(ctx, fs | fd);
1.1.1.5 ! root 4491: GEN_LOAD_FREG_FTN(DT0, fs);
1.1.1.4 root 4492: gen_op_float_cvtw_d();
4493: GEN_STORE_FTN_FREG(fd, WT2);
4494: opn = "cvt.w.d";
4495: break;
4496: case FOP(48, 16):
4497: case FOP(49, 16):
4498: case FOP(50, 16):
4499: case FOP(51, 16):
4500: case FOP(52, 16):
4501: case FOP(53, 16):
4502: case FOP(54, 16):
4503: case FOP(55, 16):
4504: case FOP(56, 16):
4505: case FOP(57, 16):
4506: case FOP(58, 16):
4507: case FOP(59, 16):
4508: case FOP(60, 16):
4509: case FOP(61, 16):
4510: case FOP(62, 16):
4511: case FOP(63, 16):
4512: CHECK_FR(ctx, fs | ft);
4513: GEN_LOAD_FREG_FTN(WT0, fs);
4514: GEN_LOAD_FREG_FTN(WT1, ft);
4515: gen_cmp_s(func-48);
4516: opn = condnames[func-48];
4517: break;
4518: default:
4519: if (loglevel & CPU_LOG_TB_IN_ASM) {
1.1.1.5 ! root 4520: fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
1.1.1.4 root 4521: ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4522: ((ctx->opcode >> 16) & 0x1F));
4523: }
1.1.1.5 ! root 4524: generate_exception_err (ctx, EXCP_RI, 1);
1.1.1.4 root 4525: return;
4526: }
4527: if (binary)
4528: MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
4529: else
4530: MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
4531: }
1.1 root 4532:
1.1.1.5 ! root 4533: static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
1.1 root 4534: {
1.1.1.5 ! root 4535: uint32_t ccbit;
! 4536:
! 4537: if (cc)
! 4538: ccbit = 1 << (24 + cc);
1.1 root 4539: else
1.1.1.5 ! root 4540: ccbit = 1 << 23;
! 4541: if (!tf)
! 4542: gen_op_movf(ccbit, rd, rs);
! 4543: else
! 4544: gen_op_movt(ccbit, rd, rs);
1.1 root 4545: }
4546:
1.1.1.5 ! root 4547: #endif /* MIPS_USES_FPU */
! 4548:
! 4549: /* ISA extensions (ASEs) */
! 4550: /* MIPS16 extension to MIPS32 */
! 4551: /* SmartMIPS extension to MIPS32 */
! 4552:
! 4553: #ifdef MIPS_HAS_MIPS64
1.1 root 4554: /* Coprocessor 3 (FPU) */
4555:
4556: /* MDMX extension to MIPS64 */
4557: /* MIPS-3D extension to MIPS64 */
4558:
4559: #endif
4560:
1.1.1.2 root 4561: static void gen_blikely(DisasContext *ctx)
4562: {
4563: int l1;
4564: l1 = gen_new_label();
4565: gen_op_jnz_T2(l1);
4566: gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
4567: gen_goto_tb(ctx, 1, ctx->pc + 4);
4568: gen_set_label(l1);
4569: }
4570:
1.1 root 4571: static void decode_opc (DisasContext *ctx)
4572: {
4573: int32_t offset;
4574: int rs, rt, rd, sa;
1.1.1.5 ! root 4575: uint32_t op, op1, op2;
1.1 root 4576: int16_t imm;
4577:
1.1.1.4 root 4578: /* make sure instructions are on a word boundary */
4579: if (ctx->pc & 0x3) {
4580: generate_exception(ctx, EXCP_AdEL);
4581: return;
4582: }
4583:
1.1.1.2 root 4584: if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
1.1 root 4585: /* Handle blikely not taken case */
1.1.1.5 ! root 4586: MIPS_DEBUG("blikely condition (" TLSZ ")", ctx->pc + 4);
1.1.1.2 root 4587: gen_blikely(ctx);
1.1 root 4588: }
1.1.1.5 ! root 4589: op = MASK_OP_MAJOR(ctx->opcode);
! 4590: rs = (ctx->opcode >> 21) & 0x1f;
! 4591: rt = (ctx->opcode >> 16) & 0x1f;
! 4592: rd = (ctx->opcode >> 11) & 0x1f;
! 4593: sa = (ctx->opcode >> 6) & 0x1f;
1.1 root 4594: imm = (int16_t)ctx->opcode;
4595: switch (op) {
1.1.1.5 ! root 4596: case OPC_SPECIAL:
! 4597: op1 = MASK_SPECIAL(ctx->opcode);
1.1 root 4598: switch (op1) {
1.1.1.5 ! root 4599: case OPC_SLL: /* Arithmetic with immediate */
! 4600: case OPC_SRL ... OPC_SRA:
! 4601: gen_arith_imm(ctx, op1, rd, rt, sa);
! 4602: break;
! 4603: case OPC_SLLV: /* Arithmetic */
! 4604: case OPC_SRLV ... OPC_SRAV:
! 4605: case OPC_MOVZ ... OPC_MOVN:
! 4606: case OPC_ADD ... OPC_NOR:
! 4607: case OPC_SLT ... OPC_SLTU:
! 4608: gen_arith(ctx, op1, rd, rs, rt);
1.1 root 4609: break;
1.1.1.5 ! root 4610: case OPC_MULT ... OPC_DIVU:
! 4611: gen_muldiv(ctx, op1, rs, rt);
1.1 root 4612: break;
1.1.1.5 ! root 4613: case OPC_JR ... OPC_JALR:
! 4614: gen_compute_branch(ctx, op1, rs, rd, sa);
1.1 root 4615: return;
1.1.1.5 ! root 4616: case OPC_TGE ... OPC_TEQ: /* Traps */
! 4617: case OPC_TNE:
! 4618: gen_trap(ctx, op1, rs, rt, -1);
! 4619: break;
! 4620: case OPC_MFHI: /* Move from HI/LO */
! 4621: case OPC_MFLO:
! 4622: gen_HILO(ctx, op1, rd);
1.1 root 4623: break;
1.1.1.5 ! root 4624: case OPC_MTHI:
! 4625: case OPC_MTLO: /* Move to HI/LO */
! 4626: gen_HILO(ctx, op1, rs);
! 4627: break;
! 4628: case OPC_PMON: /* Pmon entry point */
! 4629: gen_op_pmon(sa);
! 4630: break;
! 4631: case OPC_SYSCALL:
1.1 root 4632: generate_exception(ctx, EXCP_SYSCALL);
1.1.1.5 ! root 4633: ctx->bstate = BS_EXCP;
1.1 root 4634: break;
1.1.1.5 ! root 4635: case OPC_BREAK:
1.1 root 4636: generate_exception(ctx, EXCP_BREAK);
4637: break;
1.1.1.5 ! root 4638: case OPC_SPIM: /* SPIM ? */
! 4639: /* Implemented as RI exception for now. */
! 4640: MIPS_INVAL("spim (unofficial)");
! 4641: generate_exception(ctx, EXCP_RI);
1.1 root 4642: break;
1.1.1.5 ! root 4643: case OPC_SYNC:
! 4644: /* Treat as a noop. */
1.1 root 4645: break;
1.1.1.2 root 4646:
1.1.1.5 ! root 4647: #ifdef MIPS_USES_FPU
! 4648: case OPC_MOVCI:
! 4649: gen_op_cp1_enabled();
! 4650: gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
! 4651: (ctx->opcode >> 16) & 1);
1.1.1.2 root 4652: break;
1.1.1.5 ! root 4653: #endif
1.1.1.2 root 4654:
1.1.1.5 ! root 4655: #ifdef MIPS_HAS_MIPS64
! 4656: /* MIPS64 specific opcodes */
! 4657: case OPC_DSLL:
! 4658: case OPC_DSRL ... OPC_DSRA:
! 4659: case OPC_DSLL32:
! 4660: case OPC_DSRL32 ... OPC_DSRA32:
! 4661: gen_arith_imm(ctx, op1, rd, rt, sa);
! 4662: break;
! 4663: case OPC_DSLLV:
! 4664: case OPC_DSRLV ... OPC_DSRAV:
! 4665: case OPC_DADD ... OPC_DSUBU:
! 4666: gen_arith(ctx, op1, rd, rs, rt);
! 4667: break;
! 4668: case OPC_DMULT ... OPC_DDIVU:
! 4669: gen_muldiv(ctx, op1, rs, rt);
! 4670: break;
1.1 root 4671: #endif
4672: default: /* Invalid */
4673: MIPS_INVAL("special");
4674: generate_exception(ctx, EXCP_RI);
4675: break;
4676: }
4677: break;
1.1.1.5 ! root 4678: case OPC_SPECIAL2:
! 4679: op1 = MASK_SPECIAL2(ctx->opcode);
1.1 root 4680: switch (op1) {
1.1.1.5 ! root 4681: case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
! 4682: case OPC_MSUB ... OPC_MSUBU:
! 4683: gen_muldiv(ctx, op1, rs, rt);
1.1 root 4684: break;
1.1.1.5 ! root 4685: case OPC_MUL:
! 4686: gen_arith(ctx, op1, rd, rs, rt);
1.1 root 4687: break;
1.1.1.5 ! root 4688: case OPC_CLZ ... OPC_CLO:
! 4689: gen_cl(ctx, op1, rd, rs);
1.1 root 4690: break;
1.1.1.5 ! root 4691: case OPC_SDBBP:
1.1 root 4692: /* XXX: not clear which exception should be raised
4693: * when in debug mode...
4694: */
4695: if (!(ctx->hflags & MIPS_HFLAG_DM)) {
4696: generate_exception(ctx, EXCP_DBp);
4697: } else {
4698: generate_exception(ctx, EXCP_DBp);
4699: }
4700: /* Treat as a noop */
4701: break;
1.1.1.5 ! root 4702: #ifdef MIPS_HAS_MIPS64
! 4703: case OPC_DCLZ ... OPC_DCLO:
! 4704: gen_cl(ctx, op1, rd, rs);
! 4705: break;
! 4706: #endif
1.1 root 4707: default: /* Invalid */
4708: MIPS_INVAL("special2");
4709: generate_exception(ctx, EXCP_RI);
4710: break;
4711: }
4712: break;
1.1.1.5 ! root 4713: case OPC_SPECIAL3:
! 4714: op1 = MASK_SPECIAL3(ctx->opcode);
! 4715: switch (op1) {
! 4716: case OPC_EXT:
! 4717: case OPC_INS:
! 4718: gen_bitops(ctx, op1, rt, rs, sa, rd);
! 4719: break;
! 4720: case OPC_BSHFL:
! 4721: op2 = MASK_BSHFL(ctx->opcode);
! 4722: switch (op2) {
! 4723: case OPC_WSBH:
! 4724: GEN_LOAD_REG_TN(T1, rt);
! 4725: gen_op_wsbh();
! 4726: break;
! 4727: case OPC_SEB:
! 4728: GEN_LOAD_REG_TN(T1, rt);
! 4729: gen_op_seb();
! 4730: break;
! 4731: case OPC_SEH:
! 4732: GEN_LOAD_REG_TN(T1, rt);
! 4733: gen_op_seh();
! 4734: break;
! 4735: default: /* Invalid */
! 4736: MIPS_INVAL("bshfl");
! 4737: generate_exception(ctx, EXCP_RI);
! 4738: break;
! 4739: }
! 4740: GEN_STORE_TN_REG(rd, T0);
! 4741: break;
! 4742: case OPC_RDHWR:
! 4743: switch (rd) {
! 4744: case 0:
! 4745: gen_op_rdhwr_cpunum();
! 4746: break;
! 4747: case 1:
! 4748: gen_op_rdhwr_synci_step();
! 4749: break;
! 4750: case 2:
! 4751: gen_op_rdhwr_cc();
! 4752: break;
! 4753: case 3:
! 4754: gen_op_rdhwr_ccres();
! 4755: break;
! 4756: default: /* Invalid */
! 4757: MIPS_INVAL("rdhwr");
! 4758: generate_exception(ctx, EXCP_RI);
! 4759: break;
! 4760: }
! 4761: GEN_STORE_TN_REG(rt, T0);
! 4762: break;
! 4763: #ifdef MIPS_HAS_MIPS64
! 4764: case OPC_DEXTM ... OPC_DEXT:
! 4765: case OPC_DINSM ... OPC_DINS:
! 4766: gen_bitops(ctx, op1, rt, rs, sa, rd);
! 4767: break;
! 4768: case OPC_DBSHFL:
! 4769: op2 = MASK_DBSHFL(ctx->opcode);
! 4770: switch (op2) {
! 4771: case OPC_DSBH:
! 4772: GEN_LOAD_REG_TN(T1, rt);
! 4773: gen_op_dsbh();
! 4774: break;
! 4775: case OPC_DSHD:
! 4776: GEN_LOAD_REG_TN(T1, rt);
! 4777: gen_op_dshd();
! 4778: break;
! 4779: default: /* Invalid */
! 4780: MIPS_INVAL("dbshfl");
! 4781: generate_exception(ctx, EXCP_RI);
! 4782: break;
! 4783: }
! 4784: GEN_STORE_TN_REG(rd, T0);
! 4785: #endif
! 4786: default: /* Invalid */
! 4787: MIPS_INVAL("special3");
! 4788: generate_exception(ctx, EXCP_RI);
! 4789: break;
! 4790: }
! 4791: break;
! 4792: case OPC_REGIMM:
! 4793: op1 = MASK_REGIMM(ctx->opcode);
1.1 root 4794: switch (op1) {
1.1.1.5 ! root 4795: case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
! 4796: case OPC_BLTZAL ... OPC_BGEZALL:
! 4797: gen_compute_branch(ctx, op1, rs, -1, imm << 2);
1.1 root 4798: return;
1.1.1.5 ! root 4799: case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
! 4800: case OPC_TNEI:
! 4801: gen_trap(ctx, op1, rs, -1, imm);
! 4802: break;
! 4803: case OPC_SYNCI:
! 4804: /* treat as noop */
1.1 root 4805: break;
4806: default: /* Invalid */
4807: MIPS_INVAL("REGIMM");
4808: generate_exception(ctx, EXCP_RI);
4809: break;
4810: }
4811: break;
1.1.1.5 ! root 4812: case OPC_CP0:
! 4813: op1 = MASK_CP0(ctx->opcode);
1.1 root 4814: switch (op1) {
1.1.1.5 ! root 4815: case OPC_MFC0:
! 4816: case OPC_MTC0:
! 4817: #ifdef MIPS_HAS_MIPS64
! 4818: case OPC_DMFC0:
! 4819: case OPC_DMTC0:
! 4820: #endif
! 4821: gen_cp0(ctx, op1, rt, rd);
! 4822: break;
! 4823: case OPC_C0_FIRST ... OPC_C0_LAST:
! 4824: gen_cp0(ctx, MASK_C0(ctx->opcode), rt, rd);
! 4825: break;
! 4826: case OPC_MFMC0:
! 4827: op2 = MASK_MFMC0(ctx->opcode);
! 4828: switch (op2) {
! 4829: case OPC_DI:
! 4830: gen_op_di();
! 4831: /* Stop translation as we may have switched the execution mode */
! 4832: ctx->bstate = BS_STOP;
! 4833: break;
! 4834: case OPC_EI:
! 4835: gen_op_ei();
! 4836: /* Stop translation as we may have switched the execution mode */
! 4837: ctx->bstate = BS_STOP;
! 4838: break;
! 4839: default: /* Invalid */
! 4840: MIPS_INVAL("MFMC0");
! 4841: generate_exception(ctx, EXCP_RI);
! 4842: break;
! 4843: }
! 4844: GEN_STORE_TN_REG(rt, T0);
1.1 root 4845: break;
1.1.1.5 ! root 4846: /* Shadow registers (not implemented). */
! 4847: case OPC_RDPGPR:
! 4848: case OPC_WRPGPR:
1.1 root 4849: default:
1.1.1.5 ! root 4850: generate_exception(ctx, EXCP_RI);
1.1 root 4851: break;
4852: }
4853: break;
1.1.1.5 ! root 4854: case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
! 4855: gen_arith_imm(ctx, op, rt, rs, imm);
! 4856: break;
! 4857: case OPC_J ... OPC_JAL: /* Jump */
! 4858: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
! 4859: gen_compute_branch(ctx, op, rs, rt, offset);
! 4860: return;
! 4861: case OPC_BEQ ... OPC_BGTZ: /* Branch */
! 4862: case OPC_BEQL ... OPC_BGTZL:
! 4863: gen_compute_branch(ctx, op, rs, rt, imm << 2);
! 4864: return;
! 4865: case OPC_LB ... OPC_LWR: /* Load and stores */
! 4866: case OPC_SB ... OPC_SW:
! 4867: case OPC_SWR:
! 4868: case OPC_LL:
! 4869: case OPC_SC:
! 4870: gen_ldst(ctx, op, rt, rs, imm);
! 4871: break;
! 4872: case OPC_CACHE:
! 4873: /* Treat as a noop */
! 4874: break;
! 4875: case OPC_PREF:
1.1 root 4876: /* Treat as a noop */
4877: break;
1.1.1.2 root 4878:
4879: /* Floating point. */
1.1.1.5 ! root 4880: case OPC_LWC1:
! 4881: case OPC_LDC1:
! 4882: case OPC_SWC1:
! 4883: case OPC_SDC1:
1.1.1.4 root 4884: #if defined(MIPS_USES_FPU)
1.1.1.5 ! root 4885: save_cpu_state(ctx, 1);
1.1.1.4 root 4886: gen_op_cp1_enabled();
4887: gen_flt_ldst(ctx, op, rt, rs, imm);
4888: #else
4889: generate_exception_err(ctx, EXCP_CpU, 1);
4890: #endif
4891: break;
4892:
1.1.1.5 ! root 4893: case OPC_CP1:
1.1 root 4894: #if defined(MIPS_USES_FPU)
1.1.1.5 ! root 4895: save_cpu_state(ctx, 1);
1.1.1.4 root 4896: gen_op_cp1_enabled();
1.1.1.5 ! root 4897: op1 = MASK_CP1(ctx->opcode);
1.1.1.4 root 4898: switch (op1) {
1.1.1.5 ! root 4899: case OPC_MFC1:
! 4900: case OPC_CFC1:
! 4901: case OPC_MTC1:
! 4902: case OPC_CTC1:
! 4903: #ifdef MIPS_HAS_MIPS64
! 4904: case OPC_DMFC1:
! 4905: case OPC_DMTC1:
! 4906: #endif
! 4907: gen_cp1(ctx, op1, rt, rd);
1.1.1.4 root 4908: break;
1.1.1.5 ! root 4909: case OPC_BC1:
! 4910: gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
1.1.1.4 root 4911: return;
1.1.1.5 ! root 4912: case OPC_S_FMT:
! 4913: case OPC_D_FMT:
! 4914: case OPC_W_FMT:
! 4915: case OPC_L_FMT:
! 4916: gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
1.1.1.4 root 4917: break;
4918: default:
4919: generate_exception_err(ctx, EXCP_RI, 1);
4920: break;
4921: }
1.1.1.2 root 4922: #else
4923: generate_exception_err(ctx, EXCP_CpU, 1);
1.1 root 4924: #endif
1.1.1.2 root 4925: break;
4926:
4927: /* COP2. */
1.1.1.5 ! root 4928: case OPC_LWC2:
! 4929: case OPC_LDC2:
! 4930: case OPC_SWC2:
! 4931: case OPC_SDC2:
! 4932: case OPC_CP2:
! 4933: /* COP2: Not implemented. */
1.1.1.2 root 4934: generate_exception_err(ctx, EXCP_CpU, 2);
4935: break;
4936:
1.1.1.5 ! root 4937: #ifdef MIPS_USES_FPU
! 4938: case OPC_CP3:
! 4939: gen_op_cp1_enabled();
! 4940: op1 = MASK_CP3(ctx->opcode);
! 4941: switch (op1) {
1.1 root 4942: /* Not implemented */
1.1.1.5 ! root 4943: default:
! 4944: generate_exception_err(ctx, EXCP_RI, 1);
! 4945: break;
! 4946: }
1.1.1.2 root 4947: break;
1.1.1.5 ! root 4948: #endif
1.1.1.2 root 4949:
1.1.1.5 ! root 4950: #ifdef MIPS_HAS_MIPS64
! 4951: /* MIPS64 opcodes */
! 4952: case OPC_LWU:
! 4953: case OPC_LDL ... OPC_LDR:
! 4954: case OPC_SDL ... OPC_SDR:
! 4955: case OPC_LLD:
! 4956: case OPC_LD:
! 4957: case OPC_SCD:
! 4958: case OPC_SD:
! 4959: gen_ldst(ctx, op, rt, rs, imm);
! 4960: break;
! 4961: case OPC_DADDI ... OPC_DADDIU:
! 4962: gen_arith_imm(ctx, op, rt, rs, imm);
! 4963: break;
! 4964: #endif
! 4965: #ifdef MIPS_HAS_MIPS16
! 4966: case OPC_JALX:
! 4967: /* MIPS16: Not implemented. */
! 4968: #endif
! 4969: #ifdef MIPS_HAS_MDMX
! 4970: case OPC_MDMX:
! 4971: /* MDMX: Not implemented. */
1.1 root 4972: #endif
4973: default: /* Invalid */
4974: MIPS_INVAL("");
4975: generate_exception(ctx, EXCP_RI);
4976: break;
4977: }
1.1.1.2 root 4978: if (ctx->hflags & MIPS_HFLAG_BMASK) {
1.1 root 4979: int hflags = ctx->hflags;
4980: /* Branches completion */
1.1.1.2 root 4981: ctx->hflags &= ~MIPS_HFLAG_BMASK;
1.1 root 4982: ctx->bstate = BS_BRANCH;
4983: save_cpu_state(ctx, 0);
4984: switch (hflags & MIPS_HFLAG_BMASK) {
4985: case MIPS_HFLAG_B:
4986: /* unconditional branch */
4987: MIPS_DEBUG("unconditional branch");
1.1.1.2 root 4988: gen_goto_tb(ctx, 0, ctx->btarget);
1.1 root 4989: break;
4990: case MIPS_HFLAG_BL:
4991: /* blikely taken case */
4992: MIPS_DEBUG("blikely branch taken");
1.1.1.2 root 4993: gen_goto_tb(ctx, 0, ctx->btarget);
1.1 root 4994: break;
4995: case MIPS_HFLAG_BC:
4996: /* Conditional branch */
4997: MIPS_DEBUG("conditional branch");
1.1.1.2 root 4998: {
4999: int l1;
5000: l1 = gen_new_label();
5001: gen_op_jnz_T2(l1);
5002: gen_goto_tb(ctx, 1, ctx->pc + 4);
5003: gen_set_label(l1);
5004: gen_goto_tb(ctx, 0, ctx->btarget);
5005: }
1.1 root 5006: break;
5007: case MIPS_HFLAG_BR:
5008: /* unconditional branch to register */
5009: MIPS_DEBUG("branch to register");
5010: gen_op_breg();
5011: break;
5012: default:
5013: MIPS_DEBUG("unknown branch");
5014: break;
5015: }
5016: }
5017: }
5018:
5019: int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5020: int search_pc)
5021: {
5022: DisasContext ctx, *ctxp = &ctx;
5023: target_ulong pc_start;
5024: uint16_t *gen_opc_end;
5025: int j, lj = -1;
5026:
1.1.1.2 root 5027: if (search_pc && loglevel)
1.1.1.4 root 5028: fprintf (logfile, "search pc %d\n", search_pc);
1.1.1.2 root 5029:
1.1 root 5030: pc_start = tb->pc;
5031: gen_opc_ptr = gen_opc_buf;
5032: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
5033: gen_opparam_ptr = gen_opparam_buf;
1.1.1.2 root 5034: nb_gen_labels = 0;
1.1 root 5035: ctx.pc = pc_start;
1.1.1.2 root 5036: ctx.saved_pc = -1;
1.1 root 5037: ctx.tb = tb;
5038: ctx.bstate = BS_NONE;
1.1.1.2 root 5039: /* Restore delay slot state from the tb context. */
5040: ctx.hflags = tb->flags;
1.1 root 5041: ctx.saved_hflags = ctx.hflags;
5042: if (ctx.hflags & MIPS_HFLAG_BR) {
5043: gen_op_restore_breg_target();
5044: } else if (ctx.hflags & MIPS_HFLAG_B) {
5045: ctx.btarget = env->btarget;
5046: } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
5047: /* If we are in the delay slot of a conditional branch,
5048: * restore the branch condition from env->bcond to T2
5049: */
5050: ctx.btarget = env->btarget;
5051: gen_op_restore_bcond();
5052: }
5053: #if defined(CONFIG_USER_ONLY)
5054: ctx.mem_idx = 0;
5055: #else
1.1.1.4 root 5056: ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
1.1 root 5057: #endif
5058: ctx.CP0_Status = env->CP0_Status;
5059: #ifdef DEBUG_DISAS
5060: if (loglevel & CPU_LOG_TB_CPU) {
5061: fprintf(logfile, "------------------------------------------------\n");
1.1.1.2 root 5062: /* FIXME: This may print out stale hflags from env... */
1.1 root 5063: cpu_dump_state(env, logfile, fprintf, 0);
5064: }
5065: #endif
5066: #if defined MIPS_DEBUG_DISAS
5067: if (loglevel & CPU_LOG_TB_IN_ASM)
1.1.1.2 root 5068: fprintf(logfile, "\ntb %p super %d cond %04x\n",
5069: tb, ctx.mem_idx, ctx.hflags);
1.1 root 5070: #endif
5071: while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1.1.1.2 root 5072: if (env->nb_breakpoints > 0) {
5073: for(j = 0; j < env->nb_breakpoints; j++) {
5074: if (env->breakpoints[j] == ctx.pc) {
5075: save_cpu_state(ctxp, 1);
5076: ctx.bstate = BS_BRANCH;
5077: gen_op_debug();
5078: goto done_generating;
5079: }
5080: }
5081: }
5082:
1.1 root 5083: if (search_pc) {
5084: j = gen_opc_ptr - gen_opc_buf;
5085: if (lj < j) {
5086: lj++;
5087: while (lj < j)
5088: gen_opc_instr_start[lj++] = 0;
5089: }
1.1.1.2 root 5090: gen_opc_pc[lj] = ctx.pc;
5091: gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
5092: gen_opc_instr_start[lj] = 1;
1.1 root 5093: }
5094: ctx.opcode = ldl_code(ctx.pc);
5095: decode_opc(&ctx);
5096: ctx.pc += 4;
1.1.1.2 root 5097:
5098: if (env->singlestep_enabled)
5099: break;
5100:
1.1 root 5101: if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
5102: break;
1.1.1.2 root 5103:
1.1 root 5104: #if defined (MIPS_SINGLE_STEP)
5105: break;
5106: #endif
5107: }
1.1.1.2 root 5108: if (env->singlestep_enabled) {
5109: save_cpu_state(ctxp, ctx.bstate == BS_NONE);
5110: gen_op_debug();
5111: goto done_generating;
5112: }
5113: else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
1.1 root 5114: save_cpu_state(ctxp, 0);
1.1.1.2 root 5115: gen_goto_tb(&ctx, 0, ctx.pc);
1.1 root 5116: }
5117: gen_op_reset_T0();
5118: /* Generate the return instruction */
5119: gen_op_exit_tb();
1.1.1.2 root 5120: done_generating:
1.1 root 5121: *gen_opc_ptr = INDEX_op_end;
5122: if (search_pc) {
5123: j = gen_opc_ptr - gen_opc_buf;
5124: lj++;
5125: while (lj <= j)
5126: gen_opc_instr_start[lj++] = 0;
5127: tb->size = 0;
5128: } else {
5129: tb->size = ctx.pc - pc_start;
5130: }
5131: #ifdef DEBUG_DISAS
5132: #if defined MIPS_DEBUG_DISAS
5133: if (loglevel & CPU_LOG_TB_IN_ASM)
5134: fprintf(logfile, "\n");
5135: #endif
5136: if (loglevel & CPU_LOG_TB_IN_ASM) {
5137: fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
1.1.1.4 root 5138: target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1.1 root 5139: fprintf(logfile, "\n");
5140: }
5141: if (loglevel & CPU_LOG_TB_OP) {
5142: fprintf(logfile, "OP:\n");
5143: dump_ops(gen_opc_buf, gen_opparam_buf);
5144: fprintf(logfile, "\n");
5145: }
5146: if (loglevel & CPU_LOG_TB_CPU) {
5147: fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
5148: }
5149: #endif
5150:
5151: return 0;
5152: }
5153:
5154: int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
5155: {
5156: return gen_intermediate_code_internal(env, tb, 0);
5157: }
5158:
5159: int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
5160: {
5161: return gen_intermediate_code_internal(env, tb, 1);
5162: }
5163:
1.1.1.4 root 5164: #ifdef MIPS_USES_FPU
1.1.1.5 ! root 5165:
1.1.1.4 root 5166: void fpu_dump_state(CPUState *env, FILE *f,
5167: int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
5168: int flags)
5169: {
5170: int i;
5171:
5172: # define printfpr(fp) do { \
5173: fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
5174: (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
5175: } while(0)
5176:
5177: fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d\n",
5178: env->fcr0, env->fcr31,
1.1.1.5 ! root 5179: (env->CP0_Status & (1 << CP0St_FR)) != 0);
1.1.1.4 root 5180: fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
5181: fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
5182: fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
1.1.1.5 ! root 5183: for(i = 0; i < 32; i += 2) {
! 5184: fpu_fprintf(f, "%s: ", fregnames[i]);
1.1.1.4 root 5185: printfpr(FPR(env, i));
5186: }
5187:
5188: #undef printfpr
5189: }
5190:
1.1.1.5 ! root 5191: void dump_fpu (CPUState *env)
1.1.1.4 root 5192: {
5193: if (loglevel) {
1.1.1.5 ! root 5194: fprintf(logfile, "pc=0x" TLSZ " HI=0x" TLSZ " LO=0x" TLSZ " ds %04x " TLSZ " %d\n",
1.1.1.4 root 5195: env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5196: fpu_dump_state(env, logfile, fprintf, 0);
5197: }
5198: }
1.1.1.5 ! root 5199:
1.1.1.4 root 5200: #endif /* MIPS_USES_FPU */
5201:
1.1.1.5 ! root 5202: #if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
! 5203: /* Debug help: The architecture requires 32bit code to maintain proper
! 5204: sign-extened values on 64bit machines. */
! 5205:
! 5206: #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
! 5207:
! 5208: void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
! 5209: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
! 5210: int flags)
! 5211: {
! 5212: int i;
! 5213:
! 5214: if (!SIGN_EXT_P(env->PC))
! 5215: cpu_fprintf(f, "BROKEN: pc=0x" TLSZ "\n", env->PC);
! 5216: if (!SIGN_EXT_P(env->HI))
! 5217: cpu_fprintf(f, "BROKEN: HI=0x" TLSZ "\n", env->HI);
! 5218: if (!SIGN_EXT_P(env->LO))
! 5219: cpu_fprintf(f, "BROKEN: LO=0x" TLSZ "\n", env->LO);
! 5220: if (!SIGN_EXT_P(env->btarget))
! 5221: cpu_fprintf(f, "BROKEN: btarget=0x" TLSZ "\n", env->btarget);
! 5222:
! 5223: for (i = 0; i < 32; i++) {
! 5224: if (!SIGN_EXT_P(env->gpr[i]))
! 5225: cpu_fprintf(f, "BROKEN: %s=0x" TLSZ "\n", regnames[i], env->gpr[i]);
! 5226: }
! 5227:
! 5228: if (!SIGN_EXT_P(env->CP0_EPC))
! 5229: cpu_fprintf(f, "BROKEN: EPC=0x" TLSZ "\n", env->CP0_EPC);
! 5230: if (!SIGN_EXT_P(env->CP0_LLAddr))
! 5231: cpu_fprintf(f, "BROKEN: LLAddr=0x" TLSZ "\n", env->CP0_LLAddr);
! 5232: }
! 5233: #endif
! 5234:
1.1 root 5235: void cpu_dump_state (CPUState *env, FILE *f,
5236: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5237: int flags)
5238: {
5239: uint32_t c0_status;
5240: int i;
5241:
1.1.1.5 ! root 5242: cpu_fprintf(f, "pc=0x" TLSZ " HI=0x" TLSZ " LO=0x" TLSZ " ds %04x " TLSZ " %d\n",
1.1 root 5243: env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5244: for (i = 0; i < 32; i++) {
5245: if ((i & 3) == 0)
5246: cpu_fprintf(f, "GPR%02d:", i);
1.1.1.5 ! root 5247: cpu_fprintf(f, " %s " TLSZ, regnames[i], env->gpr[i]);
1.1 root 5248: if ((i & 3) == 3)
5249: cpu_fprintf(f, "\n");
5250: }
5251:
5252: c0_status = env->CP0_Status;
5253: if (env->hflags & MIPS_HFLAG_UM)
5254: c0_status |= (1 << CP0St_UM);
5255: if (env->hflags & MIPS_HFLAG_ERL)
5256: c0_status |= (1 << CP0St_ERL);
5257: if (env->hflags & MIPS_HFLAG_EXL)
5258: c0_status |= (1 << CP0St_EXL);
5259:
1.1.1.5 ! root 5260: cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TLSZ "\n",
1.1 root 5261: c0_status, env->CP0_Cause, env->CP0_EPC);
1.1.1.5 ! root 5262: cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TLSZ "\n",
1.1 root 5263: env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
1.1.1.4 root 5264: #ifdef MIPS_USES_FPU
1.1.1.5 ! root 5265: if (c0_status & (1 << CP0St_CU1))
! 5266: fpu_dump_state(env, f, cpu_fprintf, flags);
! 5267: #endif
! 5268: #if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
! 5269: cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
1.1.1.4 root 5270: #endif
1.1 root 5271: }
5272:
5273: CPUMIPSState *cpu_mips_init (void)
5274: {
5275: CPUMIPSState *env;
5276:
5277: env = qemu_mallocz(sizeof(CPUMIPSState));
5278: if (!env)
5279: return NULL;
1.1.1.2 root 5280: cpu_exec_init(env);
1.1.1.5 ! root 5281: cpu_reset(env);
! 5282: return env;
! 5283: }
! 5284:
! 5285: void cpu_reset (CPUMIPSState *env)
! 5286: {
! 5287: memset(env, 0, offsetof(CPUMIPSState, breakpoints));
! 5288:
1.1 root 5289: tlb_flush(env, 1);
1.1.1.5 ! root 5290:
1.1 root 5291: /* Minimal init */
1.1.1.5 ! root 5292: #if !defined(CONFIG_USER_ONLY)
! 5293: if (env->hflags & MIPS_HFLAG_BMASK) {
! 5294: /* If the exception was raised from a delay slot,
! 5295: * come back to the jump. */
! 5296: env->CP0_ErrorEPC = env->PC - 4;
! 5297: env->hflags &= ~MIPS_HFLAG_BMASK;
! 5298: } else {
! 5299: env->CP0_ErrorEPC = env->PC;
! 5300: }
! 5301: env->PC = (int32_t)0xBFC00000;
1.1 root 5302: #if defined (MIPS_USES_R4K_TLB)
1.1.1.5 ! root 5303: env->CP0_Random = MIPS_TLB_NB - 1;
! 5304: env->tlb_in_use = MIPS_TLB_NB;
1.1 root 5305: #endif
5306: env->CP0_Wired = 0;
1.1.1.5 ! root 5307: /* SMP not implemented */
! 5308: env->CP0_EBase = 0x80000000;
1.1 root 5309: env->CP0_Config0 = MIPS_CONFIG0;
1.1.1.5 ! root 5310: env->CP0_Config1 = MIPS_CONFIG1;
! 5311: env->CP0_Config2 = MIPS_CONFIG2;
! 5312: env->CP0_Config3 = MIPS_CONFIG3;
! 5313: env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
1.1 root 5314: env->CP0_WatchLo = 0;
5315: env->hflags = MIPS_HFLAG_ERL;
5316: /* Count register increments in debug mode, EJTAG version 1 */
5317: env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
5318: env->CP0_PRid = MIPS_CPU;
1.1.1.5 ! root 5319: #endif
1.1 root 5320: env->exception_index = EXCP_NONE;
1.1.1.2 root 5321: #if defined(CONFIG_USER_ONLY)
5322: env->hflags |= MIPS_HFLAG_UM;
1.1.1.5 ! root 5323: env->user_mode_only = 1;
1.1.1.2 root 5324: #endif
1.1.1.4 root 5325: #ifdef MIPS_USES_FPU
5326: env->fcr0 = MIPS_FCR0;
5327: #endif
1.1.1.5 ! root 5328: /* XXX some guesswork here, values are CPU specific */
! 5329: env->SYNCI_Step = 16;
! 5330: env->CCRes = 2;
1.1 root 5331: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.