Annotation of qemu/target-mips/translate.c, revision 1.1.1.5

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.