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

1.1       root        1: /*
                      2:  *  MIPS32 emulation for qemu: main translation routines.
                      3:  * 
                      4:  *  Copyright (c) 2004-2005 Jocelyn Mayer
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, write to the Free Software
                     18:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     19:  */
                     20: 
                     21: #include <stdarg.h>
                     22: #include <stdlib.h>
                     23: #include <stdio.h>
                     24: #include <string.h>
                     25: #include <inttypes.h>
                     26: 
                     27: #include "cpu.h"
                     28: #include "exec-all.h"
                     29: #include "disas.h"
                     30: 
                     31: #define MIPS_DEBUG_DISAS
                     32: //#define MIPS_SINGLE_STEP
                     33: 
                     34: enum {
                     35: #define DEF(s, n, copy_size) INDEX_op_ ## s,
                     36: #include "opc.h"
                     37: #undef DEF
                     38:     NB_OPS,
                     39: };
                     40: 
                     41: static uint16_t *gen_opc_ptr;
                     42: static uint32_t *gen_opparam_ptr;
                     43: 
                     44: #include "gen-op.h"
                     45: 
                     46: /* MIPS opcodes */
                     47: #define EXT_SPECIAL  0x100
                     48: #define EXT_SPECIAL2 0x200
                     49: #define EXT_REGIMM   0x300
                     50: #define EXT_CP0      0x400
                     51: #define EXT_CP1      0x500
                     52: #define EXT_CP2      0x600
                     53: #define EXT_CP3      0x700
                     54: 
                     55: enum {
                     56:     /* indirect opcode tables */
                     57:     OPC_SPECIAL  = 0x00,
                     58:     OPC_BREGIMM  = 0x01,
                     59:     OPC_CP0      = 0x10,
                     60:     OPC_CP1      = 0x11,
                     61:     OPC_CP2      = 0x12,
                     62:     OPC_CP3      = 0x13,
                     63:     OPC_SPECIAL2 = 0x1C,
                     64:     /* arithmetic with immediate */
                     65:     OPC_ADDI     = 0x08,
                     66:     OPC_ADDIU    = 0x09,
                     67:     OPC_SLTI     = 0x0A,
                     68:     OPC_SLTIU    = 0x0B,
                     69:     OPC_ANDI     = 0x0C,
                     70:     OPC_ORI      = 0x0D,
                     71:     OPC_XORI     = 0x0E,
                     72:     OPC_LUI      = 0x0F,
                     73:     /* Jump and branches */
                     74:     OPC_J        = 0x02,
                     75:     OPC_JAL      = 0x03,
                     76:     OPC_BEQ      = 0x04,  /* Unconditional if rs = rt = 0 (B) */
                     77:     OPC_BEQL     = 0x14,
                     78:     OPC_BNE      = 0x05,
                     79:     OPC_BNEL     = 0x15,
                     80:     OPC_BLEZ     = 0x06,
                     81:     OPC_BLEZL    = 0x16,
                     82:     OPC_BGTZ     = 0x07,
                     83:     OPC_BGTZL    = 0x17,
                     84:     OPC_JALX     = 0x1D,  /* MIPS 16 only */
                     85:     /* Load and stores */
                     86:     OPC_LB       = 0x20,
                     87:     OPC_LH       = 0x21,
                     88:     OPC_LWL      = 0x22,
                     89:     OPC_LW       = 0x23,
                     90:     OPC_LBU      = 0x24,
                     91:     OPC_LHU      = 0x25,
                     92:     OPC_LWR      = 0x26,
                     93:     OPC_SB       = 0x28,
                     94:     OPC_SH       = 0x29,
                     95:     OPC_SWL      = 0x2A,
                     96:     OPC_SW       = 0x2B,
                     97:     OPC_SWR      = 0x2E,
                     98:     OPC_LL       = 0x30,
                     99:     OPC_SC       = 0x38,
                    100:     /* Floating point load/store */
                    101:     OPC_LWC1     = 0x31,
                    102:     OPC_LWC2     = 0x32,
                    103:     OPC_LDC1     = 0x35,
                    104:     OPC_LDC2     = 0x36,
                    105:     OPC_SWC1     = 0x39,
                    106:     OPC_SWC2     = 0x3A,
                    107:     OPC_SDC1     = 0x3D,
                    108:     OPC_SDC2     = 0x3E,
                    109:     /* Cache and prefetch */
                    110:     OPC_CACHE    = 0x2F,
                    111:     OPC_PREF     = 0x33,
                    112: };
                    113: 
                    114: /* MIPS special opcodes */
                    115: enum {
                    116:     /* Shifts */
                    117:     OPC_SLL      = 0x00 | EXT_SPECIAL,
                    118:     /* NOP is SLL r0, r0, 0   */
                    119:     /* SSNOP is SLL r0, r0, 1 */
                    120:     OPC_SRL      = 0x02 | EXT_SPECIAL,
                    121:     OPC_SRA      = 0x03 | EXT_SPECIAL,
                    122:     OPC_SLLV     = 0x04 | EXT_SPECIAL,
                    123:     OPC_SRLV     = 0x06 | EXT_SPECIAL,
                    124:     OPC_SRAV     = 0x07 | EXT_SPECIAL,
                    125:     /* Multiplication / division */
                    126:     OPC_MULT     = 0x18 | EXT_SPECIAL,
                    127:     OPC_MULTU    = 0x19 | EXT_SPECIAL,
                    128:     OPC_DIV      = 0x1A | EXT_SPECIAL,
                    129:     OPC_DIVU     = 0x1B | EXT_SPECIAL,
                    130:     /* 2 registers arithmetic / logic */
                    131:     OPC_ADD      = 0x20 | EXT_SPECIAL,
                    132:     OPC_ADDU     = 0x21 | EXT_SPECIAL,
                    133:     OPC_SUB      = 0x22 | EXT_SPECIAL,
                    134:     OPC_SUBU     = 0x23 | EXT_SPECIAL,
                    135:     OPC_AND      = 0x24 | EXT_SPECIAL,
                    136:     OPC_OR       = 0x25 | EXT_SPECIAL,
                    137:     OPC_XOR      = 0x26 | EXT_SPECIAL,
                    138:     OPC_NOR      = 0x27 | EXT_SPECIAL,
                    139:     OPC_SLT      = 0x2A | EXT_SPECIAL,
                    140:     OPC_SLTU     = 0x2B | EXT_SPECIAL,
                    141:     /* Jumps */
                    142:     OPC_JR       = 0x08 | EXT_SPECIAL,
                    143:     OPC_JALR     = 0x09 | EXT_SPECIAL,
                    144:     /* Traps */
                    145:     OPC_TGE      = 0x30 | EXT_SPECIAL,
                    146:     OPC_TGEU     = 0x31 | EXT_SPECIAL,
                    147:     OPC_TLT      = 0x32 | EXT_SPECIAL,
                    148:     OPC_TLTU     = 0x33 | EXT_SPECIAL,
                    149:     OPC_TEQ      = 0x34 | EXT_SPECIAL,
                    150:     OPC_TNE      = 0x36 | EXT_SPECIAL,
                    151:     /* HI / LO registers load & stores */
                    152:     OPC_MFHI     = 0x10 | EXT_SPECIAL,
                    153:     OPC_MTHI     = 0x11 | EXT_SPECIAL,
                    154:     OPC_MFLO     = 0x12 | EXT_SPECIAL,
                    155:     OPC_MTLO     = 0x13 | EXT_SPECIAL,
                    156:     /* Conditional moves */
                    157:     OPC_MOVZ     = 0x0A | EXT_SPECIAL,
                    158:     OPC_MOVN     = 0x0B | EXT_SPECIAL,
                    159: 
                    160:     OPC_MOVCI    = 0x01 | EXT_SPECIAL,
                    161: 
                    162:     /* Special */
                    163:     OPC_PMON     = 0x05 | EXT_SPECIAL,
                    164:     OPC_SYSCALL  = 0x0C | EXT_SPECIAL,
                    165:     OPC_BREAK    = 0x0D | EXT_SPECIAL,
                    166:     OPC_SYNC     = 0x0F | EXT_SPECIAL,
                    167: };
                    168: 
                    169: enum {
                    170:     /* Mutiply & xxx operations */
                    171:     OPC_MADD     = 0x00 | EXT_SPECIAL2,
                    172:     OPC_MADDU    = 0x01 | EXT_SPECIAL2,
                    173:     OPC_MUL      = 0x02 | EXT_SPECIAL2,
                    174:     OPC_MSUB     = 0x04 | EXT_SPECIAL2,
                    175:     OPC_MSUBU    = 0x05 | EXT_SPECIAL2,
                    176:     /* Misc */
                    177:     OPC_CLZ      = 0x20 | EXT_SPECIAL2,
                    178:     OPC_CLO      = 0x21 | EXT_SPECIAL2,
                    179:     /* Special */
                    180:     OPC_SDBBP    = 0x3F | EXT_SPECIAL2,
                    181: };
                    182: 
                    183: /* Branch REGIMM */
                    184: enum {
                    185:     OPC_BLTZ     = 0x00 | EXT_REGIMM,
                    186:     OPC_BLTZL    = 0x02 | EXT_REGIMM,
                    187:     OPC_BGEZ     = 0x01 | EXT_REGIMM,
                    188:     OPC_BGEZL    = 0x03 | EXT_REGIMM,
                    189:     OPC_BLTZAL   = 0x10 | EXT_REGIMM,
                    190:     OPC_BLTZALL  = 0x12 | EXT_REGIMM,
                    191:     OPC_BGEZAL   = 0x11 | EXT_REGIMM,
                    192:     OPC_BGEZALL  = 0x13 | EXT_REGIMM,
                    193:     OPC_TGEI     = 0x08 | EXT_REGIMM,
                    194:     OPC_TGEIU    = 0x09 | EXT_REGIMM,
                    195:     OPC_TLTI     = 0x0A | EXT_REGIMM,
                    196:     OPC_TLTIU    = 0x0B | EXT_REGIMM,
                    197:     OPC_TEQI     = 0x0C | EXT_REGIMM,
                    198:     OPC_TNEI     = 0x0E | EXT_REGIMM,
                    199: };
                    200: 
                    201: enum {
                    202:     /* Coprocessor 0 (MMU) */
                    203:     OPC_MFC0     = 0x00 | EXT_CP0,
                    204:     OPC_MTC0     = 0x04 | EXT_CP0,
                    205:     OPC_TLBR     = 0x01 | EXT_CP0,
                    206:     OPC_TLBWI    = 0x02 | EXT_CP0,
                    207:     OPC_TLBWR    = 0x06 | EXT_CP0,
                    208:     OPC_TLBP     = 0x08 | EXT_CP0,
                    209:     OPC_ERET     = 0x18 | EXT_CP0,
                    210:     OPC_DERET    = 0x1F | EXT_CP0,
                    211:     OPC_WAIT     = 0x20 | EXT_CP0,
                    212: };
                    213: 
                    214: const unsigned char *regnames[] =
                    215:     { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
                    216:       "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
                    217:       "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
                    218:       "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
                    219: 
                    220: /* Warning: no function for r0 register (hard wired to zero) */
                    221: #define GEN32(func, NAME) \
                    222: static GenOpFunc *NAME ## _table [32] = {                                     \
                    223: NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \
                    224: NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \
                    225: NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \
                    226: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
                    227: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
                    228: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
                    229: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
                    230: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
                    231: };                                                                            \
                    232: static inline void func(int n)                                                \
                    233: {                                                                             \
                    234:     NAME ## _table[n]();                                                      \
                    235: }
                    236: 
                    237: /* General purpose registers moves */
                    238: GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
                    239: GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
                    240: GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
                    241: 
                    242: GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
                    243: GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
                    244: 
                    245: typedef struct DisasContext {
                    246:     struct TranslationBlock *tb;
                    247:     target_ulong pc, saved_pc;
                    248:     uint32_t opcode;
                    249:     /* Routine used to access memory */
                    250:     int mem_idx;
                    251:     uint32_t hflags, saved_hflags;
                    252:     uint32_t CP0_Status;
                    253:     int bstate;
                    254:     target_ulong btarget;
                    255: } DisasContext;
                    256: 
                    257: enum {
                    258:     BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
                    259:                       * exception condition
                    260:                       */
                    261:     BS_STOP     = 1, /* We want to stop translation for any reason */
                    262:     BS_BRANCH   = 2, /* We reached a branch condition     */
                    263:     BS_EXCP     = 3, /* We reached an exception condition */
                    264: };
                    265: 
                    266: #if defined MIPS_DEBUG_DISAS
                    267: #define MIPS_DEBUG(fmt, args...)                                              \
                    268: do {                                                                          \
                    269:     if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
                    270:         fprintf(logfile, "%08x: %08x " fmt "\n",                              \
                    271:                 ctx->pc, ctx->opcode , ##args);                               \
                    272:     }                                                                         \
                    273: } while (0)
                    274: #else
                    275: #define MIPS_DEBUG(fmt, args...) do { } while(0)
                    276: #endif
                    277: 
                    278: #define MIPS_INVAL(op)                                                        \
                    279: do {                                                                          \
                    280:     MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
                    281:                ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
                    282: } while (0)
                    283: 
                    284: #define GEN_LOAD_REG_TN(Tn, Rn)                                               \
                    285: do {                                                                          \
                    286:     if (Rn == 0) {                                                            \
                    287:         glue(gen_op_reset_, Tn)();                                            \
                    288:     } else {                                                                  \
                    289:         glue(gen_op_load_gpr_, Tn)(Rn);                                       \
                    290:     }                                                                         \
                    291: } while (0)
                    292: 
                    293: #define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
                    294: do {                                                                          \
                    295:     if (Imm == 0) {                                                           \
                    296:         glue(gen_op_reset_, Tn)();                                            \
                    297:     } else {                                                                  \
                    298:         glue(gen_op_set_, Tn)(Imm);                                           \
                    299:     }                                                                         \
                    300: } while (0)
                    301: 
                    302: #define GEN_STORE_TN_REG(Rn, Tn)                                              \
                    303: do {                                                                          \
                    304:     if (Rn != 0) {                                                            \
                    305:         glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \
                    306:     }                                                                         \
                    307: } while (0)
                    308: 
                    309: static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
                    310: {
                    311: #if defined MIPS_DEBUG_DISAS
                    312:     if (loglevel & CPU_LOG_TB_IN_ASM) {
                    313:             fprintf(logfile, "hflags %08x saved %08x\n",
                    314:                     ctx->hflags, ctx->saved_hflags);
                    315:     }
                    316: #endif
                    317:     if (do_save_pc && ctx->pc != ctx->saved_pc) {
                    318:         gen_op_save_pc(ctx->pc);
                    319:         ctx->saved_pc = ctx->pc;
                    320:     }
                    321:     if (ctx->hflags != ctx->saved_hflags) {
                    322:         gen_op_save_state(ctx->hflags);
                    323:         ctx->saved_hflags = ctx->hflags;
                    324:         if (ctx->hflags & MIPS_HFLAG_BR) {
                    325:             gen_op_save_breg_target();
                    326:         } else if (ctx->hflags & MIPS_HFLAG_B) {
                    327:             gen_op_save_btarget(ctx->btarget);
                    328:         } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
                    329:             gen_op_save_bcond();
                    330:             gen_op_save_btarget(ctx->btarget);
                    331:         }
                    332:     }
                    333: }
                    334: 
                    335: static inline void generate_exception (DisasContext *ctx, int excp)
                    336: {
                    337: #if defined MIPS_DEBUG_DISAS
                    338:     if (loglevel & CPU_LOG_TB_IN_ASM)
                    339:             fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
                    340: #endif
                    341:     save_cpu_state(ctx, 1);
                    342:     gen_op_raise_exception(excp);
                    343:     ctx->bstate = BS_EXCP;
                    344: }
                    345: 
                    346: #if defined(CONFIG_USER_ONLY)
                    347: #define op_ldst(name)        gen_op_##name##_raw()
                    348: #define OP_LD_TABLE(width)
                    349: #define OP_ST_TABLE(width)
                    350: #else
                    351: #define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
                    352: #define OP_LD_TABLE(width)                                                    \
                    353: static GenOpFunc *gen_op_l##width[] = {                                       \
                    354:     &gen_op_l##width##_user,                                                  \
                    355:     &gen_op_l##width##_kernel,                                                \
                    356: }
                    357: #define OP_ST_TABLE(width)                                                    \
                    358: static GenOpFunc *gen_op_s##width[] = {                                       \
                    359:     &gen_op_s##width##_user,                                                  \
                    360:     &gen_op_s##width##_kernel,                                                \
                    361: }
                    362: #endif
                    363: 
                    364: #ifdef TARGET_MIPS64
                    365: OP_LD_TABLE(d);
                    366: OP_LD_TABLE(dl);
                    367: OP_LD_TABLE(dr);
                    368: OP_ST_TABLE(d);
                    369: OP_ST_TABLE(dl);
                    370: OP_ST_TABLE(dr);
                    371: #endif
                    372: OP_LD_TABLE(w);
                    373: OP_LD_TABLE(wl);
                    374: OP_LD_TABLE(wr);
                    375: OP_ST_TABLE(w);
                    376: OP_ST_TABLE(wl);
                    377: OP_ST_TABLE(wr);
                    378: OP_LD_TABLE(h);
                    379: OP_LD_TABLE(hu);
                    380: OP_ST_TABLE(h);
                    381: OP_LD_TABLE(b);
                    382: OP_LD_TABLE(bu);
                    383: OP_ST_TABLE(b);
                    384: OP_LD_TABLE(l);
                    385: OP_ST_TABLE(c);
                    386: 
                    387: /* Load and store */
                    388: static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt,
                    389:                       int base, int16_t offset)
                    390: {
                    391:     const unsigned char *opn = "unk";
                    392: 
                    393:     if (base == 0) {
                    394:         GEN_LOAD_IMM_TN(T0, offset);
                    395:     } else if (offset == 0) {
                    396:         gen_op_load_gpr_T0(base);
                    397:     } else {
                    398:         gen_op_load_gpr_T0(base);
                    399:         gen_op_set_T1(offset);
                    400:         gen_op_add();
                    401:     }
                    402:     /* Don't do NOP if destination is zero: we must perform the actual
                    403:      * memory access
                    404:      */
                    405:     switch (opc) {
                    406: #if defined(TARGET_MIPS64)
                    407:     case OPC_LD:
                    408: #if defined (MIPS_HAS_UNALIGNED_LS)
                    409:     case OPC_ULD:
                    410: #endif
                    411:         op_ldst(ld);
                    412:         GEN_STORE_TN_REG(rt, T0);
                    413:         opn = "ld";
                    414:         break;
                    415:     case OPC_SD:
                    416: #if defined (MIPS_HAS_UNALIGNED_LS)
                    417:     case OPC_USD:
                    418: #endif
                    419:         GEN_LOAD_REG_TN(T1, rt);
                    420:         op_ldst(sd);
                    421:         opn = "sd";
                    422:         break;
                    423:     case OPC_LDL:
                    424:         op_ldst(ldl);
                    425:         GEN_STORE_TN_REG(rt, T0);
                    426:         opn = "ldl";
                    427:         break;
                    428:     case OPC_SDL:
                    429:         GEN_LOAD_REG_TN(T1, rt);
                    430:         op_ldst(sdl);
                    431:         opn = "sdl";
                    432:         break;
                    433:     case OPC_LDR:
                    434:         op_ldst(ldr);
                    435:         GEN_STORE_TN_REG(rt, T0);
                    436:         opn = "ldr";
                    437:         break;
                    438:     case OPC_SDR:
                    439:         GEN_LOAD_REG_TN(T1, rt);
                    440:         op_ldst(sdr);
                    441:         opn = "sdr";
                    442:         break;
                    443: #endif
                    444:     case OPC_LW:
                    445: #if defined (MIPS_HAS_UNALIGNED_LS)
                    446:     case OPC_ULW:
                    447: #endif
                    448:         op_ldst(lw);
                    449:         GEN_STORE_TN_REG(rt, T0);
                    450:         opn = "lw";
                    451:         break;
                    452:     case OPC_SW:
                    453: #if defined (MIPS_HAS_UNALIGNED_LS)
                    454:     case OPC_USW:
                    455: #endif
                    456:         GEN_LOAD_REG_TN(T1, rt);
                    457:         op_ldst(sw);
                    458:         opn = "sw";
                    459:         break;
                    460:     case OPC_LH:
                    461: #if defined (MIPS_HAS_UNALIGNED_LS)
                    462:     case OPC_ULH:
                    463: #endif
                    464:         op_ldst(lh);
                    465:         GEN_STORE_TN_REG(rt, T0);
                    466:         opn = "lh";
                    467:         break;
                    468:     case OPC_SH:
                    469: #if defined (MIPS_HAS_UNALIGNED_LS)
                    470:     case OPC_USH:
                    471: #endif
                    472:         GEN_LOAD_REG_TN(T1, rt);
                    473:         op_ldst(sh);
                    474:         opn = "sh";
                    475:         break;
                    476:     case OPC_LHU:
                    477: #if defined (MIPS_HAS_UNALIGNED_LS)
                    478:     case OPC_ULHU:
                    479: #endif
                    480:         op_ldst(lhu);
                    481:         GEN_STORE_TN_REG(rt, T0);
                    482:         opn = "lhu";
                    483:         break;
                    484:     case OPC_LB:
                    485:         op_ldst(lb);
                    486:         GEN_STORE_TN_REG(rt, T0);
                    487:         opn = "lb";
                    488:         break;
                    489:     case OPC_SB:
                    490:         GEN_LOAD_REG_TN(T1, rt);
                    491:         op_ldst(sb);
                    492:         opn = "sb";
                    493:         break;
                    494:     case OPC_LBU:
                    495:         op_ldst(lbu);
                    496:         GEN_STORE_TN_REG(rt, T0);
                    497:         opn = "lbu";
                    498:         break;
                    499:     case OPC_LWL:
                    500:        GEN_LOAD_REG_TN(T1, rt);
                    501:         op_ldst(lwl);
                    502:         GEN_STORE_TN_REG(rt, T0);
                    503:         opn = "lwl";
                    504:         break;
                    505:     case OPC_SWL:
                    506:         GEN_LOAD_REG_TN(T1, rt);
                    507:         op_ldst(swl);
                    508:         opn = "swr";
                    509:         break;
                    510:     case OPC_LWR:
                    511:        GEN_LOAD_REG_TN(T1, rt);
                    512:         op_ldst(lwr);
                    513:         GEN_STORE_TN_REG(rt, T0);
                    514:         opn = "lwr";
                    515:         break;
                    516:     case OPC_SWR:
                    517:         GEN_LOAD_REG_TN(T1, rt);
                    518:         op_ldst(swr);
                    519:         opn = "swr";
                    520:         break;
                    521:     case OPC_LL:
                    522:         op_ldst(ll);
                    523:         GEN_STORE_TN_REG(rt, T0);
                    524:         opn = "ll";
                    525:         break;
                    526:     case OPC_SC:
                    527:         GEN_LOAD_REG_TN(T1, rt);
                    528:         op_ldst(sc);
                    529:         GEN_STORE_TN_REG(rt, T0);
                    530:         opn = "sc";
                    531:         break;
                    532:     default:
                    533:         MIPS_INVAL("load/store");
                    534:         generate_exception(ctx, EXCP_RI);
                    535:         return;
                    536:     }
                    537:     MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
                    538: }
                    539: 
                    540: /* Arithmetic with immediate operand */
                    541: static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt,
                    542:                            int rs, int16_t imm)
                    543: {
                    544:     uint32_t uimm;
                    545:     const unsigned char *opn = "unk";
                    546: 
                    547:     if (rt == 0 && opc != OPC_ADDI) {
                    548:         /* if no destination, treat it as a NOP 
                    549:          * For addi, we must generate the overflow exception when needed.
                    550:          */
                    551:         MIPS_DEBUG("NOP");
                    552:         return;
                    553:     }
                    554:     if (opc == OPC_ADDI || opc == OPC_ADDIU ||
                    555:         opc == OPC_SLTI || opc == OPC_SLTIU)
                    556:         uimm = (int32_t)imm; /* Sign extent to 32 bits */
                    557:     else
                    558:         uimm = (uint16_t)imm;
                    559:     if (opc != OPC_LUI) {
                    560:         GEN_LOAD_REG_TN(T0, rs);
                    561:         GEN_LOAD_IMM_TN(T1, uimm);
                    562:     } else {
                    563:         uimm = uimm << 16;
                    564:         GEN_LOAD_IMM_TN(T0, uimm);
                    565:     }
                    566:     switch (opc) {
                    567:     case OPC_ADDI:
                    568:         save_cpu_state(ctx, 1);
                    569:         gen_op_addo();
                    570:         opn = "addi";
                    571:         break;
                    572:     case OPC_ADDIU:
                    573:         gen_op_add();
                    574:         opn = "addiu";
                    575:         break;
                    576:     case OPC_SLTI:
                    577:         gen_op_lt();
                    578:         opn = "slti";
                    579:         break;
                    580:     case OPC_SLTIU:
                    581:         gen_op_ltu();
                    582:         opn = "sltiu";
                    583:         break;
                    584:     case OPC_ANDI:
                    585:         gen_op_and();
                    586:         opn = "andi";
                    587:         break;
                    588:     case OPC_ORI:
                    589:         gen_op_or();
                    590:         opn = "ori";
                    591:         break;
                    592:     case OPC_XORI:
                    593:         gen_op_xor();
                    594:         opn = "xori";
                    595:         break;
                    596:     case OPC_LUI:
                    597:         opn = "lui";
                    598:         break;
                    599:     case OPC_SLL:
                    600:         gen_op_sll();
                    601:         opn = "sll";
                    602:         break;
                    603:     case OPC_SRA:
                    604:         gen_op_sra();
                    605:         opn = "sra";
                    606:         break;
                    607:     case OPC_SRL:
                    608:         gen_op_srl();
                    609:         opn = "srl";
                    610:         break;
                    611:     default:
                    612:         MIPS_INVAL("imm arith");
                    613:         generate_exception(ctx, EXCP_RI);
                    614:         return;
                    615:     }
                    616:     GEN_STORE_TN_REG(rt, T0);
                    617:     MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);
                    618: }
                    619: 
                    620: /* Arithmetic */
                    621: static void gen_arith (DisasContext *ctx, uint16_t opc,
                    622:                        int rd, int rs, int rt)
                    623: {
                    624:     const unsigned char *opn = "unk";
                    625: 
                    626:     if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB) {
                    627:         /* if no destination, treat it as a NOP 
                    628:          * For add & sub, we must generate the overflow exception when needed.
                    629:          */
                    630:         MIPS_DEBUG("NOP");
                    631:         return;
                    632:     }
                    633:     GEN_LOAD_REG_TN(T0, rs);
                    634:     GEN_LOAD_REG_TN(T1, rt);
                    635:     switch (opc) {
                    636:     case OPC_ADD:
                    637:         save_cpu_state(ctx, 1);
                    638:         gen_op_addo();
                    639:         opn = "add";
                    640:         break;
                    641:     case OPC_ADDU:
                    642:         gen_op_add();
                    643:         opn = "addu";
                    644:         break;
                    645:     case OPC_SUB:
                    646:         save_cpu_state(ctx, 1);
                    647:         gen_op_subo();
                    648:         opn = "sub";
                    649:         break;
                    650:     case OPC_SUBU:
                    651:         gen_op_sub();
                    652:         opn = "subu";
                    653:         break;
                    654:     case OPC_SLT:
                    655:         gen_op_lt();
                    656:         opn = "slt";
                    657:         break;
                    658:     case OPC_SLTU:
                    659:         gen_op_ltu();
                    660:         opn = "sltu";
                    661:         break;
                    662:     case OPC_AND:
                    663:         gen_op_and();
                    664:         opn = "and";
                    665:         break;
                    666:     case OPC_NOR:
                    667:         gen_op_nor();
                    668:         opn = "nor";
                    669:         break;
                    670:     case OPC_OR:
                    671:         gen_op_or();
                    672:         opn = "or";
                    673:         break;
                    674:     case OPC_XOR:
                    675:         gen_op_xor();
                    676:         opn = "xor";
                    677:         break;
                    678:     case OPC_MUL:
                    679:         gen_op_mul();
                    680:         opn = "mul";
                    681:         break;
                    682:     case OPC_MOVN:
                    683:         gen_op_movn(rd);
                    684:         opn = "movn";
                    685:         goto print;
                    686:     case OPC_MOVZ:
                    687:         gen_op_movz(rd);
                    688:         opn = "movz";
                    689:         goto print;
                    690:     case OPC_SLLV:
                    691:         gen_op_sllv();
                    692:         opn = "sllv";
                    693:         break;
                    694:     case OPC_SRAV:
                    695:         gen_op_srav();
                    696:         opn = "srav";
                    697:         break;
                    698:     case OPC_SRLV:
                    699:         gen_op_srlv();
                    700:         opn = "srlv";
                    701:         break;
                    702:     default:
                    703:         MIPS_INVAL("arith");
                    704:         generate_exception(ctx, EXCP_RI);
                    705:         return;
                    706:     }
                    707:     GEN_STORE_TN_REG(rd, T0);
                    708:  print:
                    709:     MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
                    710: }
                    711: 
                    712: /* Arithmetic on HI/LO registers */
                    713: static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg)
                    714: {
                    715:     const unsigned char *opn = "unk";
                    716: 
                    717:     if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
                    718:         /* Treat as a NOP */
                    719:         MIPS_DEBUG("NOP");
                    720:         return;
                    721:     }
                    722:     switch (opc) {
                    723:     case OPC_MFHI:
                    724:         gen_op_load_HI();
                    725:         GEN_STORE_TN_REG(reg, T0);
                    726:         opn = "mfhi";
                    727:         break;
                    728:     case OPC_MFLO:
                    729:         gen_op_load_LO();
                    730:         GEN_STORE_TN_REG(reg, T0);
                    731:         opn = "mflo";
                    732:         break;
                    733:     case OPC_MTHI:
                    734:         GEN_LOAD_REG_TN(T0, reg);
                    735:         gen_op_store_HI();
                    736:         opn = "mthi";
                    737:         break;
                    738:     case OPC_MTLO:
                    739:         GEN_LOAD_REG_TN(T0, reg);
                    740:         gen_op_store_LO();
                    741:         opn = "mtlo";
                    742:         break;
                    743:     default:
                    744:         MIPS_INVAL("HILO");
                    745:         generate_exception(ctx, EXCP_RI);
                    746:         return;
                    747:     }
                    748:     MIPS_DEBUG("%s %s", opn, regnames[reg]);
                    749: }
                    750: 
                    751: static void gen_muldiv (DisasContext *ctx, uint16_t opc,
                    752:                         int rs, int rt)
                    753: {
                    754:     const unsigned char *opn = "unk";
                    755: 
                    756:     GEN_LOAD_REG_TN(T0, rs);
                    757:     GEN_LOAD_REG_TN(T1, rt);
                    758:     switch (opc) {
                    759:     case OPC_DIV:
                    760:         gen_op_div();
                    761:         opn = "div";
                    762:         break;
                    763:     case OPC_DIVU:
                    764:         gen_op_divu();
                    765:         opn = "divu";
                    766:         break;
                    767:     case OPC_MULT:
                    768:         gen_op_mult();
                    769:         opn = "mult";
                    770:         break;
                    771:     case OPC_MULTU:
                    772:         gen_op_multu();
                    773:         opn = "multu";
                    774:         break;
                    775:     case OPC_MADD:
                    776:         gen_op_madd();
                    777:         opn = "madd";
                    778:         break;
                    779:     case OPC_MADDU:
                    780:         gen_op_maddu();
                    781:         opn = "maddu";
                    782:         break;
                    783:     case OPC_MSUB:
                    784:         gen_op_msub();
                    785:         opn = "msub";
                    786:         break;
                    787:     case OPC_MSUBU:
                    788:         gen_op_msubu();
                    789:         opn = "msubu";
                    790:         break;
                    791:     default:
                    792:         MIPS_INVAL("mul/div");
                    793:         generate_exception(ctx, EXCP_RI);
                    794:         return;
                    795:     }
                    796:     MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
                    797: }
                    798: 
                    799: static void gen_cl (DisasContext *ctx, uint16_t opc,
                    800:                     int rd, int rs)
                    801: {
                    802:     const unsigned char *opn = "unk";
                    803:     if (rd == 0) {
                    804:         /* Treat as a NOP */
                    805:         MIPS_DEBUG("NOP");
                    806:         return;
                    807:     }
                    808:     GEN_LOAD_REG_TN(T0, rs);
                    809:     switch (opc) {
                    810:     case OPC_CLO:
                    811:         /* CLO */
                    812:         gen_op_clo();
                    813:         opn = "clo";
                    814:         break;
                    815:     case OPC_CLZ:
                    816:         /* CLZ */
                    817:         gen_op_clz();
                    818:         opn = "clz";
                    819:         break;
                    820:     default:
                    821:         MIPS_INVAL("CLx");
                    822:         generate_exception(ctx, EXCP_RI);
                    823:         return;
                    824:     }
                    825:     gen_op_store_T0_gpr(rd);
                    826:     MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
                    827: }
                    828: 
                    829: /* Traps */
                    830: static void gen_trap (DisasContext *ctx, uint16_t opc,
                    831:                       int rs, int rt, int16_t imm)
                    832: {
                    833:     int cond;
                    834: 
                    835:     cond = 0;
                    836:     /* Load needed operands */
                    837:     switch (opc) {
                    838:     case OPC_TEQ:
                    839:     case OPC_TGE:
                    840:     case OPC_TGEU:
                    841:     case OPC_TLT:
                    842:     case OPC_TLTU:
                    843:     case OPC_TNE:
                    844:         /* Compare two registers */
                    845:         if (rs != rt) {
                    846:             GEN_LOAD_REG_TN(T0, rs);
                    847:             GEN_LOAD_REG_TN(T1, rt);
                    848:             cond = 1;
                    849:         }
                    850:     case OPC_TEQI:
                    851:     case OPC_TGEI:
                    852:     case OPC_TGEIU:
                    853:     case OPC_TLTI:
                    854:     case OPC_TLTIU:
                    855:     case OPC_TNEI:
                    856:         /* Compare register to immediate */
                    857:         if (rs != 0 || imm != 0) {
                    858:             GEN_LOAD_REG_TN(T0, rs);
                    859:             GEN_LOAD_IMM_TN(T1, (int32_t)imm);
                    860:             cond = 1;
                    861:         }
                    862:         break;
                    863:     }
                    864:     if (cond == 0) {
                    865:         switch (opc) {
                    866:         case OPC_TEQ:   /* rs == rs */
                    867:         case OPC_TEQI:  /* r0 == 0  */
                    868:         case OPC_TGE:   /* rs >= rs */
                    869:         case OPC_TGEI:  /* r0 >= 0  */
                    870:         case OPC_TGEU:  /* rs >= rs unsigned */
                    871:         case OPC_TGEIU: /* r0 >= 0  unsigned */
                    872:             /* Always trap */
                    873:             gen_op_set_T0(1);
                    874:             break;
                    875:         case OPC_TLT:   /* rs < rs           */
                    876:         case OPC_TLTI:  /* r0 < 0            */
                    877:         case OPC_TLTU:  /* rs < rs unsigned  */
                    878:         case OPC_TLTIU: /* r0 < 0  unsigned  */
                    879:         case OPC_TNE:   /* rs != rs          */
                    880:         case OPC_TNEI:  /* r0 != 0           */
                    881:             /* Never trap: treat as NOP */
                    882:             return;
                    883:         default:
                    884:             MIPS_INVAL("TRAP");
                    885:             generate_exception(ctx, EXCP_RI);
                    886:             return;
                    887:         }
                    888:     } else {
                    889:         switch (opc) {
                    890:         case OPC_TEQ:
                    891:         case OPC_TEQI:
                    892:             gen_op_eq();
                    893:             break;
                    894:         case OPC_TGE:
                    895:         case OPC_TGEI:
                    896:             gen_op_ge();
                    897:             break;
                    898:         case OPC_TGEU:
                    899:         case OPC_TGEIU:
                    900:             gen_op_geu();
                    901:             break;
                    902:         case OPC_TLT:
                    903:         case OPC_TLTI:
                    904:             gen_op_lt();
                    905:             break;
                    906:         case OPC_TLTU:
                    907:         case OPC_TLTIU:
                    908:             gen_op_ltu();
                    909:             break;
                    910:         case OPC_TNE:
                    911:         case OPC_TNEI:
                    912:             gen_op_ne();
                    913:             break;
                    914:         default:
                    915:             MIPS_INVAL("TRAP");
                    916:             generate_exception(ctx, EXCP_RI);
                    917:             return;
                    918:         }
                    919:     }
                    920:     save_cpu_state(ctx, 1);
                    921:     gen_op_trap();
                    922:     ctx->bstate = BS_STOP;
                    923: }
                    924: 
                    925: /* Branches (before delay slot) */
                    926: static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
                    927:                                 int rs, int rt, int32_t offset)
                    928: {
                    929:     target_ulong btarget;
                    930:     int blink, bcond;
                    931: 
                    932:     btarget = -1;
                    933:     blink = 0;
                    934:     bcond = 0;
                    935:     /* Load needed operands */
                    936:     switch (opc) {
                    937:     case OPC_BEQ:
                    938:     case OPC_BEQL:
                    939:     case OPC_BNE:
                    940:     case OPC_BNEL:
                    941:         /* Compare two registers */
                    942:         if (rs != rt) {
                    943:             GEN_LOAD_REG_TN(T0, rs);
                    944:             GEN_LOAD_REG_TN(T1, rt);
                    945:             bcond = 1;
                    946:         }
                    947:         btarget = ctx->pc + 4 + offset;
                    948:         break;
                    949:     case OPC_BGEZ:
                    950:     case OPC_BGEZAL:
                    951:     case OPC_BGEZALL:
                    952:     case OPC_BGEZL:
                    953:     case OPC_BGTZ:
                    954:     case OPC_BGTZL:
                    955:     case OPC_BLEZ:
                    956:     case OPC_BLEZL:
                    957:     case OPC_BLTZ:
                    958:     case OPC_BLTZAL:
                    959:     case OPC_BLTZALL:
                    960:     case OPC_BLTZL:
                    961:         /* Compare to zero */
                    962:         if (rs != 0) {
                    963:             gen_op_load_gpr_T0(rs);
                    964:             bcond = 1;
                    965:         }
                    966:         btarget = ctx->pc + 4 + offset;
                    967:         break;
                    968:     case OPC_J:
                    969:     case OPC_JAL:
                    970:         /* Jump to immediate */
                    971:         btarget = ((ctx->pc + 4) & 0xF0000000) | offset;
                    972:         break;
                    973:     case OPC_JR:
                    974:     case OPC_JALR:
                    975:         /* Jump to register */
                    976:         if (offset != 0) {
                    977:             /* Only hint = 0 is valid */
                    978:             generate_exception(ctx, EXCP_RI);
                    979:             return;
                    980:         }
                    981:         GEN_LOAD_REG_TN(T2, rs);
                    982:         break;
                    983:     default:
                    984:         MIPS_INVAL("branch/jump");
                    985:         generate_exception(ctx, EXCP_RI);
                    986:         return;
                    987:     }
                    988:     if (bcond == 0) {
                    989:         /* No condition to be computed */
                    990:         switch (opc) {
                    991:         case OPC_BEQ:     /* rx == rx        */
                    992:         case OPC_BEQL:    /* rx == rx likely */
                    993:         case OPC_BGEZ:    /* 0 >= 0          */
                    994:         case OPC_BGEZL:   /* 0 >= 0 likely   */
                    995:         case OPC_BLEZ:    /* 0 <= 0          */
                    996:         case OPC_BLEZL:   /* 0 <= 0 likely   */
                    997:             /* Always take */
                    998:             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
                    999:             MIPS_DEBUG("balways");
                   1000:             break;
                   1001:         case OPC_BGEZAL:  /* 0 >= 0          */
                   1002:         case OPC_BGEZALL: /* 0 >= 0 likely   */
                   1003:             /* Always take and link */
                   1004:             blink = 31;
                   1005:             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
                   1006:             MIPS_DEBUG("balways and link");
                   1007:             break;
                   1008:         case OPC_BNE:     /* rx != rx        */
                   1009:         case OPC_BGTZ:    /* 0 > 0           */
                   1010:         case OPC_BLTZ:    /* 0 < 0           */
                   1011:         case OPC_BLTZAL:  /* 0 < 0           */
                   1012:             /* Treated as NOP */
                   1013:             MIPS_DEBUG("bnever (NOP)");
                   1014:             return;
                   1015:         case OPC_BNEL:    /* rx != rx likely */
                   1016:         case OPC_BGTZL:   /* 0 > 0 likely */
                   1017:         case OPC_BLTZALL: /* 0 < 0 likely */
                   1018:         case OPC_BLTZL:   /* 0 < 0 likely */
                   1019:             /* Skip the instruction in the delay slot */
                   1020:             MIPS_DEBUG("bnever and skip");
                   1021:             gen_op_branch((long)ctx->tb, ctx->pc + 4);
                   1022:             return;
                   1023:         case OPC_J:
                   1024:             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
                   1025:             MIPS_DEBUG("j %08x", btarget);
                   1026:             break;
                   1027:         case OPC_JAL:
                   1028:             blink = 31;
                   1029:             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
                   1030:             MIPS_DEBUG("jal %08x", btarget);
                   1031:             break;
                   1032:         case OPC_JR:
                   1033:             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
                   1034:             MIPS_DEBUG("jr %s", regnames[rs]);
                   1035:             break;
                   1036:         case OPC_JALR:
                   1037:             blink = rt;
                   1038:             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
                   1039:             MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
                   1040:             break;
                   1041:         default:
                   1042:             MIPS_INVAL("branch/jump");
                   1043:             generate_exception(ctx, EXCP_RI);
                   1044:             return;
                   1045:         }
                   1046:     } else {
                   1047:         switch (opc) {
                   1048:         case OPC_BEQ:
                   1049:             gen_op_eq();
                   1050:             MIPS_DEBUG("beq %s, %s, %08x",
                   1051:                        regnames[rs], regnames[rt], btarget);
                   1052:             goto not_likely;
                   1053:         case OPC_BEQL:
                   1054:             gen_op_eq();
                   1055:             MIPS_DEBUG("beql %s, %s, %08x",
                   1056:                        regnames[rs], regnames[rt], btarget);
                   1057:             goto likely;
                   1058:         case OPC_BNE:
                   1059:             gen_op_ne();
                   1060:             MIPS_DEBUG("bne %s, %s, %08x",
                   1061:                        regnames[rs], regnames[rt], btarget);
                   1062:             goto not_likely;
                   1063:         case OPC_BNEL:
                   1064:             gen_op_ne();
                   1065:             MIPS_DEBUG("bnel %s, %s, %08x",
                   1066:                        regnames[rs], regnames[rt], btarget);
                   1067:             goto likely;
                   1068:         case OPC_BGEZ:
                   1069:             gen_op_gez();
                   1070:             MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
                   1071:             goto not_likely;
                   1072:         case OPC_BGEZL:
                   1073:             gen_op_gez();
                   1074:             MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
                   1075:             goto likely;
                   1076:         case OPC_BGEZAL:
                   1077:             gen_op_gez();
                   1078:             MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
                   1079:             blink = 31;
                   1080:             goto not_likely;
                   1081:         case OPC_BGEZALL:
                   1082:             gen_op_gez();
                   1083:             blink = 31;
                   1084:             MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
                   1085:             goto likely;
                   1086:         case OPC_BGTZ:
                   1087:             gen_op_gtz();
                   1088:             MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
                   1089:             goto not_likely;
                   1090:         case OPC_BGTZL:
                   1091:             gen_op_gtz();
                   1092:             MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
                   1093:             goto likely;
                   1094:         case OPC_BLEZ:
                   1095:             gen_op_lez();
                   1096:             MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
                   1097:             goto not_likely;
                   1098:         case OPC_BLEZL:
                   1099:             gen_op_lez();
                   1100:             MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
                   1101:             goto likely;
                   1102:         case OPC_BLTZ:
                   1103:             gen_op_ltz();
                   1104:             MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
                   1105:             goto not_likely;
                   1106:         case OPC_BLTZL:
                   1107:             gen_op_ltz();
                   1108:             MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
                   1109:             goto likely;
                   1110:         case OPC_BLTZAL:
                   1111:             gen_op_ltz();
                   1112:             blink = 31;
                   1113:             MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
                   1114:         not_likely:
                   1115:             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BC;
                   1116:             break;
                   1117:         case OPC_BLTZALL:
                   1118:             gen_op_ltz();
                   1119:             blink = 31;
                   1120:             MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
                   1121:         likely:
                   1122:             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BL;
                   1123:             break;
                   1124:         }
                   1125:         gen_op_set_bcond();
                   1126:     }
                   1127:     MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
                   1128:                blink, ctx->hflags, btarget);
                   1129:     ctx->btarget = btarget;
                   1130:     if (blink > 0) {
                   1131:         gen_op_set_T0(ctx->pc + 8);
                   1132:         gen_op_store_T0_gpr(blink);
                   1133:     }
                   1134:     return;
                   1135: }
                   1136: 
                   1137: /* CP0 (MMU and control) */
                   1138: static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
                   1139: {
                   1140:     const unsigned char *opn = "unk";
                   1141: 
                   1142:     if (!(ctx->CP0_Status & (1 << CP0St_CU0)) &&
                   1143:         !(ctx->hflags & MIPS_HFLAG_UM) &&
                   1144:         !(ctx->hflags & MIPS_HFLAG_ERL) &&
                   1145:         !(ctx->hflags & MIPS_HFLAG_EXL)) {
                   1146:         if (loglevel & CPU_LOG_TB_IN_ASM) {
                   1147:             fprintf(logfile, "CP0 is not usable\n");
                   1148:         }
                   1149:         gen_op_raise_exception_err(EXCP_CpU, 0);
                   1150:         return;
                   1151:     }
                   1152:     switch (opc) {
                   1153:     case OPC_MFC0:
                   1154:         if (rt == 0) {
                   1155:             /* Treat as NOP */
                   1156:             return;
                   1157:         }
                   1158:         gen_op_mfc0(rd, ctx->opcode & 0x7);
                   1159:         gen_op_store_T0_gpr(rt);
                   1160:         opn = "mfc0";
                   1161:         break;
                   1162:     case OPC_MTC0:
                   1163:         /* If we get an exception, we want to restart at next instruction */
                   1164:         ctx->pc += 4;
                   1165:         save_cpu_state(ctx, 1);
                   1166:         ctx->pc -= 4;
                   1167:         GEN_LOAD_REG_TN(T0, rt);
                   1168:         gen_op_mtc0(rd, ctx->opcode & 0x7);
                   1169:         /* Stop translation as we may have switched the execution mode */
                   1170:         ctx->bstate = BS_STOP;
                   1171:         opn = "mtc0";
                   1172:         break;
                   1173: #if defined(MIPS_USES_R4K_TLB)
                   1174:     case OPC_TLBWI:
                   1175:         gen_op_tlbwi();
                   1176:         opn = "tlbwi";
                   1177:         break;
                   1178:     case OPC_TLBWR:
                   1179:         gen_op_tlbwr();
                   1180:         opn = "tlbwr";
                   1181:         break;
                   1182:     case OPC_TLBP:
                   1183:         gen_op_tlbp();
                   1184:         opn = "tlbp";
                   1185:         break;
                   1186:     case OPC_TLBR:
                   1187:         gen_op_tlbr();
                   1188:         opn = "tlbr";
                   1189:         break;
                   1190: #endif
                   1191:     case OPC_ERET:
                   1192:         opn = "eret";
                   1193:         save_cpu_state(ctx, 0);
                   1194:         gen_op_eret();
                   1195:         ctx->bstate = BS_EXCP;
                   1196:         break;
                   1197:     case OPC_DERET:
                   1198:         opn = "deret";
                   1199:         if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                   1200:             generate_exception(ctx, EXCP_RI);
                   1201:         } else {
                   1202:             save_cpu_state(ctx, 0);
                   1203:             gen_op_deret();
                   1204:             ctx->bstate = BS_EXCP;
                   1205:         }
                   1206:         break;
                   1207:     /* XXX: TODO: WAIT */
                   1208:     default:
                   1209:         if (loglevel & CPU_LOG_TB_IN_ASM) {
                   1210:             fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
                   1211:                     ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
                   1212:                     ((ctx->opcode >> 16) & 0x1F));
                   1213:         }
                   1214:         generate_exception(ctx, EXCP_RI);
                   1215:         return;
                   1216:     }
                   1217:     MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
                   1218: }
                   1219: 
                   1220: /* Coprocessor 1 (FPU) */
                   1221: 
                   1222: /* ISA extensions */
                   1223: /* MIPS16 extension to MIPS32 */
                   1224: /* SmartMIPS extension to MIPS32 */
                   1225: 
                   1226: #ifdef TARGET_MIPS64
                   1227: static void gen_arith64 (DisasContext *ctx, uint16_t opc)
                   1228: {
                   1229:     if (func == 0x02 && rd == 0) {
                   1230:         /* NOP */
                   1231:         return;
                   1232:     }
                   1233:     if (rs == 0 || rt == 0) {
                   1234:         gen_op_reset_T0();
                   1235:         gen_op_save64();
                   1236:     } else {
                   1237:         gen_op_load_gpr_T0(rs);
                   1238:         gen_op_load_gpr_T1(rt);
                   1239:         gen_op_save64();
                   1240:         if (func & 0x01)
                   1241:             gen_op_mul64u();
                   1242:         else
                   1243:             gen_op_mul64s();
                   1244:     }
                   1245:     if (func & 0x02)
                   1246:         gen_op_add64();
                   1247:     else
                   1248:         gen_op_sub64();
                   1249: }
                   1250: 
                   1251: /* Coprocessor 3 (FPU) */
                   1252: 
                   1253: /* MDMX extension to MIPS64 */
                   1254: /* MIPS-3D extension to MIPS64 */
                   1255: 
                   1256: #endif
                   1257: 
                   1258: static void decode_opc (DisasContext *ctx)
                   1259: {
                   1260:     int32_t offset;
                   1261:     int rs, rt, rd, sa;
                   1262:     uint16_t op, op1;
                   1263:     int16_t imm;
                   1264: 
                   1265:     if ((ctx->hflags & MIPS_HFLAG_DS) &&
                   1266:         (ctx->hflags & MIPS_HFLAG_BL)) {
                   1267:         /* Handle blikely not taken case */
                   1268:         MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
                   1269:         gen_op_blikely((long)ctx->tb, ctx->pc + 4,
                   1270:                        ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS));
                   1271:     }
                   1272:     op = ctx->opcode >> 26;
                   1273:     rs = ((ctx->opcode >> 21) & 0x1F);
                   1274:     rt = ((ctx->opcode >> 16) & 0x1F);
                   1275:     rd = ((ctx->opcode >> 11) & 0x1F);
                   1276:     sa = ((ctx->opcode >> 6) & 0x1F);
                   1277:     imm = (int16_t)ctx->opcode;
                   1278:     switch (op) {
                   1279:     case 0x00:          /* Special opcode */
                   1280:         op1 = ctx->opcode & 0x3F;
                   1281:         switch (op1) {
                   1282:         case 0x00:          /* Arithmetic with immediate */
                   1283:         case 0x02 ... 0x03:
                   1284:             gen_arith_imm(ctx, op1 | EXT_SPECIAL, rd, rt, sa);
                   1285:             break;
                   1286:         case 0x04:          /* Arithmetic */
                   1287:         case 0x06 ... 0x07:
                   1288:         case 0x0A ... 0x0B:
                   1289:         case 0x20 ... 0x27:
                   1290:         case 0x2A ... 0x2B:
                   1291:             gen_arith(ctx, op1 | EXT_SPECIAL, rd, rs, rt);
                   1292:             break;
                   1293:         case 0x18 ... 0x1B: /* MULT / DIV */
                   1294:             gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt);
                   1295:             break;
                   1296:         case 0x08 ... 0x09: /* Jumps */
                   1297:             gen_compute_branch(ctx, op1 | EXT_SPECIAL, rs, rd, sa);
                   1298:             return;
                   1299:         case 0x30 ... 0x34: /* Traps */
                   1300:         case 0x36:
                   1301:             gen_trap(ctx, op1 | EXT_SPECIAL, rs, rt, -1);
                   1302:             break;
                   1303:         case 0x10:          /* Move from HI/LO */
                   1304:         case 0x12:
                   1305:             gen_HILO(ctx, op1 | EXT_SPECIAL, rd);
                   1306:             break;
                   1307:         case 0x11:
                   1308:         case 0x13:          /* Move to HI/LO */
                   1309:             gen_HILO(ctx, op1 | EXT_SPECIAL, rs);
                   1310:             break;
                   1311:         case 0x0C:          /* SYSCALL */
                   1312:             generate_exception(ctx, EXCP_SYSCALL);
                   1313:             break;
                   1314:         case 0x0D:          /* BREAK */
                   1315:             generate_exception(ctx, EXCP_BREAK);
                   1316:             break;
                   1317:         case 0x0F:          /* SYNC */
                   1318:             /* Treat as a noop */
                   1319:             break;
                   1320:         case 0x05:          /* Pmon entry point */
                   1321:             gen_op_pmon((ctx->opcode >> 6) & 0x1F);
                   1322:             break;
                   1323: #if defined (MIPS_HAS_MOVCI)
                   1324:         case 0x01:          /* MOVCI */
                   1325: #endif
                   1326: #if defined (TARGET_MIPS64)
                   1327:         case 0x14: /* MIPS64 specific opcodes */
                   1328:         case 0x16:
                   1329:         case 0x17:
                   1330:         case 0x1C ... 0x1F:
                   1331:         case 0x2C ... 0x2F:
                   1332:         case 0x37:
                   1333:         case 0x39 ... 0x3B:
                   1334:         case 0x3E ... 0x3F:
                   1335: #endif
                   1336:         default:            /* Invalid */
                   1337:             MIPS_INVAL("special");
                   1338:             generate_exception(ctx, EXCP_RI);
                   1339:             break;
                   1340:         }
                   1341:         break;
                   1342:     case 0x1C:          /* Special2 opcode */
                   1343:         op1 = ctx->opcode & 0x3F;
                   1344:         switch (op1) {
                   1345: #if defined (MIPS_USES_R4K_EXT)
                   1346:         /* Those instructions are not part of MIPS32 core */
                   1347:         case 0x00 ... 0x01: /* Multiply and add/sub */
                   1348:         case 0x04 ... 0x05:
                   1349:             gen_muldiv(ctx, op1 | EXT_SPECIAL2, rs, rt);
                   1350:             break;
                   1351:         case 0x02:          /* MUL */
                   1352:             gen_arith(ctx, op1 | EXT_SPECIAL2, rd, rs, rt);
                   1353:             break;
                   1354:         case 0x20 ... 0x21: /* CLO / CLZ */
                   1355:             gen_cl(ctx, op1 | EXT_SPECIAL2, rd, rs);
                   1356:             break;
                   1357: #endif
                   1358:         case 0x3F:          /* SDBBP */
                   1359:             /* XXX: not clear which exception should be raised
                   1360:              *      when in debug mode...
                   1361:              */
                   1362:             if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                   1363:                 generate_exception(ctx, EXCP_DBp);
                   1364:             } else {
                   1365:                 generate_exception(ctx, EXCP_DBp);
                   1366:             }
                   1367:             /* Treat as a noop */
                   1368:             break;
                   1369:         default:            /* Invalid */
                   1370:             MIPS_INVAL("special2");
                   1371:             generate_exception(ctx, EXCP_RI);
                   1372:             break;
                   1373:         }
                   1374:         break;
                   1375:     case 0x01:          /* B REGIMM opcode */
                   1376:         op1 = ((ctx->opcode >> 16) & 0x1F);
                   1377:         switch (op1) {
                   1378:         case 0x00 ... 0x03: /* REGIMM branches */
                   1379:         case 0x10 ... 0x13:
                   1380:             gen_compute_branch(ctx, op1 | EXT_REGIMM, rs, -1, imm << 2);
                   1381:             return;
                   1382:         case 0x08 ... 0x0C: /* Traps */
                   1383:         case 0x0E:
                   1384:             gen_trap(ctx, op1 | EXT_REGIMM, rs, -1, imm);
                   1385:             break;
                   1386:         default:            /* Invalid */
                   1387:             MIPS_INVAL("REGIMM");
                   1388:             generate_exception(ctx, EXCP_RI);
                   1389:             break;
                   1390:         }
                   1391:         break;
                   1392:     case 0x10:          /* CP0 opcode */
                   1393:         op1 = ((ctx->opcode >> 21) & 0x1F);
                   1394:         switch (op1) {
                   1395:         case 0x00:
                   1396:         case 0x04:
                   1397:             gen_cp0(ctx, op1 | EXT_CP0, rt, rd);
                   1398:             break;
                   1399:         default:
                   1400:             gen_cp0(ctx, (ctx->opcode & 0x1F) | EXT_CP0, rt, rd);
                   1401:             break;
                   1402:         }
                   1403:         break;
                   1404:     case 0x08 ... 0x0F: /* Arithmetic with immediate opcode */
                   1405:         gen_arith_imm(ctx, op, rt, rs, imm);
                   1406:         break;
                   1407:     case 0x02 ... 0x03: /* Jump */
                   1408:         offset = (int32_t)(ctx->opcode & 0x03FFFFFF) << 2;
                   1409:         gen_compute_branch(ctx, op, rs, rt, offset);
                   1410:         return;
                   1411:     case 0x04 ... 0x07: /* Branch */
                   1412:     case 0x14 ... 0x17:
                   1413:         gen_compute_branch(ctx, op, rs, rt, imm << 2);
                   1414:         return;
                   1415:     case 0x20 ... 0x26: /* Load and stores */
                   1416:     case 0x28 ... 0x2E:
                   1417:     case 0x30:
                   1418:     case 0x38:
                   1419:         gen_ldst(ctx, op, rt, rs, imm);
                   1420:         break;
                   1421:     case 0x2F:          /* Cache operation */
                   1422:         /* Treat as a noop */
                   1423:         break;
                   1424:     case 0x33:          /* Prefetch */
                   1425:         /* Treat as a noop */
                   1426:         break;
                   1427:     case 0x3F: /* HACK */
                   1428:         break;
                   1429: #if defined(MIPS_USES_FPU)
                   1430:     case 0x31 ... 0x32: /* Floating point load/store */
                   1431:     case 0x35 ... 0x36:
                   1432:     case 0x3A ... 0x3B:
                   1433:     case 0x3D ... 0x3E:
                   1434:         /* Not implemented */
                   1435:         /* XXX: not correct */
                   1436: #endif
                   1437:     case 0x11:          /* CP1 opcode */
                   1438:         /* Not implemented */
                   1439:         /* XXX: not correct */
                   1440:     case 0x12:          /* CP2 opcode */
                   1441:         /* Not implemented */
                   1442:         /* XXX: not correct */
                   1443:     case 0x13:          /* CP3 opcode */
                   1444:         /* Not implemented */
                   1445:         /* XXX: not correct */
                   1446: #if defined (TARGET_MIPS64)
                   1447:     case 0x18 ... 0x1B:
                   1448:     case 0x27:
                   1449:     case 0x34:
                   1450:     case 0x37:
                   1451:         /* MIPS64 opcodes */
                   1452: #endif
                   1453: #if defined (MIPS_HAS_JALX)
                   1454:     case 0x1D:
                   1455:         /* JALX: not implemented */
                   1456: #endif
                   1457:     case 0x1E:
                   1458:         /* ASE specific */
                   1459: #if defined (MIPS_HAS_LSC)
                   1460:     case 0x31: /* LWC1 */
                   1461:     case 0x32: /* LWC2 */
                   1462:     case 0x35: /* SDC1 */
                   1463:     case 0x36: /* SDC2 */
                   1464: #endif
                   1465:     default:            /* Invalid */
                   1466:         MIPS_INVAL("");
                   1467:         generate_exception(ctx, EXCP_RI);
                   1468:         break;
                   1469:     }
                   1470:     if (ctx->hflags & MIPS_HFLAG_DS) {
                   1471:         int hflags = ctx->hflags;
                   1472:         /* Branches completion */
                   1473:         ctx->hflags &= ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS);
                   1474:         ctx->bstate = BS_BRANCH;
                   1475:         save_cpu_state(ctx, 0);
                   1476:         switch (hflags & MIPS_HFLAG_BMASK) {
                   1477:         case MIPS_HFLAG_B:
                   1478:             /* unconditional branch */
                   1479:             MIPS_DEBUG("unconditional branch");
                   1480:             gen_op_branch((long)ctx->tb, ctx->btarget);
                   1481:             break;
                   1482:         case MIPS_HFLAG_BL:
                   1483:             /* blikely taken case */
                   1484:             MIPS_DEBUG("blikely branch taken");
                   1485:             gen_op_branch((long)ctx->tb, ctx->btarget);
                   1486:             break;
                   1487:         case MIPS_HFLAG_BC:
                   1488:             /* Conditional branch */
                   1489:             MIPS_DEBUG("conditional branch");
                   1490:             gen_op_bcond((long)ctx->tb, ctx->btarget, ctx->pc + 4);
                   1491:             break;
                   1492:         case MIPS_HFLAG_BR:
                   1493:             /* unconditional branch to register */
                   1494:             MIPS_DEBUG("branch to register");
                   1495:             gen_op_breg();
                   1496:             break;
                   1497:         default:
                   1498:             MIPS_DEBUG("unknown branch");
                   1499:             break;
                   1500:         }
                   1501:     }
                   1502: }
                   1503: 
                   1504: int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
                   1505:                                     int search_pc)
                   1506: {
                   1507:     DisasContext ctx, *ctxp = &ctx;
                   1508:     target_ulong pc_start;
                   1509:     uint16_t *gen_opc_end;
                   1510:     int j, lj = -1;
                   1511: 
                   1512:     pc_start = tb->pc;
                   1513:     gen_opc_ptr = gen_opc_buf;
                   1514:     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
                   1515:     gen_opparam_ptr = gen_opparam_buf;
                   1516:     ctx.pc = pc_start;
                   1517:     ctx.tb = tb;
                   1518:     ctx.bstate = BS_NONE;
                   1519:     /* Restore delay slot state */
                   1520:     ctx.hflags = env->hflags;
                   1521:     ctx.saved_hflags = ctx.hflags;
                   1522:     if (ctx.hflags & MIPS_HFLAG_BR) {
                   1523:         gen_op_restore_breg_target();
                   1524:     } else if (ctx.hflags & MIPS_HFLAG_B) {
                   1525:         ctx.btarget = env->btarget;
                   1526:     } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
                   1527:         /* If we are in the delay slot of a conditional branch,
                   1528:          * restore the branch condition from env->bcond to T2
                   1529:          */
                   1530:         ctx.btarget = env->btarget;
                   1531:         gen_op_restore_bcond();
                   1532:     }
                   1533: #if defined(CONFIG_USER_ONLY)
                   1534:     ctx.mem_idx = 0;
                   1535: #else
                   1536:     ctx.mem_idx = (ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM ? 0 : 1;
                   1537: #endif
                   1538:     ctx.CP0_Status = env->CP0_Status;
                   1539: #ifdef DEBUG_DISAS
                   1540:     if (loglevel & CPU_LOG_TB_CPU) {
                   1541:         fprintf(logfile, "------------------------------------------------\n");
                   1542:         cpu_dump_state(env, logfile, fprintf, 0);
                   1543:     }
                   1544: #endif
                   1545: #if defined MIPS_DEBUG_DISAS
                   1546:     if (loglevel & CPU_LOG_TB_IN_ASM)
                   1547:         fprintf(logfile, "\ntb %p super %d cond %04x %04x\n",
                   1548:                 tb, ctx.mem_idx, ctx.hflags, env->hflags);
                   1549: #endif
                   1550:     while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
                   1551:         if (search_pc) {
                   1552:             j = gen_opc_ptr - gen_opc_buf;
                   1553:             save_cpu_state(ctxp, 1);
                   1554:             if (lj < j) {
                   1555:                 lj++;
                   1556:                 while (lj < j)
                   1557:                     gen_opc_instr_start[lj++] = 0;
                   1558:                 gen_opc_pc[lj] = ctx.pc;
                   1559:                 gen_opc_instr_start[lj] = 1;
                   1560:             }
                   1561:         }
                   1562:         ctx.opcode = ldl_code(ctx.pc);
                   1563:         decode_opc(&ctx);
                   1564:         ctx.pc += 4;
                   1565:         if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
                   1566:             break;
                   1567: #if defined (MIPS_SINGLE_STEP)
                   1568:         break;
                   1569: #endif
                   1570:     }
                   1571:     if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
                   1572:         save_cpu_state(ctxp, 0);
                   1573:         gen_op_branch((long)ctx.tb, ctx.pc);
                   1574:     }
                   1575:     gen_op_reset_T0();
                   1576:     /* Generate the return instruction */
                   1577:     gen_op_exit_tb();
                   1578:     *gen_opc_ptr = INDEX_op_end;
                   1579:     if (search_pc) {
                   1580:         j = gen_opc_ptr - gen_opc_buf;
                   1581:         lj++;
                   1582:         while (lj <= j)
                   1583:             gen_opc_instr_start[lj++] = 0;
                   1584:         tb->size = 0;
                   1585:     } else {
                   1586:         tb->size = ctx.pc - pc_start;
                   1587:     }
                   1588: #ifdef DEBUG_DISAS
                   1589: #if defined MIPS_DEBUG_DISAS
                   1590:     if (loglevel & CPU_LOG_TB_IN_ASM)
                   1591:         fprintf(logfile, "\n");
                   1592: #endif
                   1593:     if (loglevel & CPU_LOG_TB_IN_ASM) {
                   1594:         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
                   1595:        target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
                   1596:         fprintf(logfile, "\n");
                   1597:     }
                   1598:     if (loglevel & CPU_LOG_TB_OP) {
                   1599:         fprintf(logfile, "OP:\n");
                   1600:         dump_ops(gen_opc_buf, gen_opparam_buf);
                   1601:         fprintf(logfile, "\n");
                   1602:     }
                   1603:     if (loglevel & CPU_LOG_TB_CPU) {
                   1604:         fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
                   1605:     }
                   1606: #endif
                   1607:     
                   1608:     return 0;
                   1609: }
                   1610: 
                   1611: int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
                   1612: {
                   1613:     return gen_intermediate_code_internal(env, tb, 0);
                   1614: }
                   1615: 
                   1616: int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
                   1617: {
                   1618:     return gen_intermediate_code_internal(env, tb, 1);
                   1619: }
                   1620: 
                   1621: void cpu_dump_state (CPUState *env, FILE *f, 
                   1622:                      int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                   1623:                      int flags)
                   1624: {
                   1625:     uint32_t c0_status;
                   1626:     int i;
                   1627:     
                   1628:     cpu_fprintf(f, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
                   1629:                 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
                   1630:     for (i = 0; i < 32; i++) {
                   1631:         if ((i & 3) == 0)
                   1632:             cpu_fprintf(f, "GPR%02d:", i);
                   1633:         cpu_fprintf(f, " %s %08x", regnames[i], env->gpr[i]);
                   1634:         if ((i & 3) == 3)
                   1635:             cpu_fprintf(f, "\n");
                   1636:     }
                   1637: 
                   1638:     c0_status = env->CP0_Status;
                   1639:     if (env->hflags & MIPS_HFLAG_UM)
                   1640:         c0_status |= (1 << CP0St_UM);
                   1641:     if (env->hflags & MIPS_HFLAG_ERL)
                   1642:         c0_status |= (1 << CP0St_ERL);
                   1643:     if (env->hflags & MIPS_HFLAG_EXL)
                   1644:         c0_status |= (1 << CP0St_EXL);
                   1645: 
                   1646:     cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x%08x\n",
                   1647:                 c0_status, env->CP0_Cause, env->CP0_EPC);
                   1648:     cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n",
                   1649:                 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
                   1650: }
                   1651: 
                   1652: CPUMIPSState *cpu_mips_init (void)
                   1653: {
                   1654:     CPUMIPSState *env;
                   1655: 
                   1656:     cpu_exec_init();
                   1657:     env = qemu_mallocz(sizeof(CPUMIPSState));
                   1658:     if (!env)
                   1659:         return NULL;
                   1660:     tlb_flush(env, 1);
                   1661:     /* Minimal init */
                   1662:     env->PC = 0xBFC00000;
                   1663: #if defined (MIPS_USES_R4K_TLB)
                   1664:     env->CP0_random = MIPS_TLB_NB - 1;
                   1665: #endif
                   1666:     env->CP0_Wired = 0;
                   1667:     env->CP0_Config0 = MIPS_CONFIG0;
                   1668: #if defined (MIPS_CONFIG1)
                   1669:         env->CP0_Config1 = MIPS_CONFIG1;
                   1670: #endif
                   1671: #if defined (MIPS_CONFIG2)
                   1672:         env->CP0_Config2 = MIPS_CONFIG2;
                   1673: #endif
                   1674: #if defined (MIPS_CONFIG3)
                   1675:         env->CP0_Config3 = MIPS_CONFIG3;
                   1676: #endif
                   1677:     env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
                   1678:     env->CP0_WatchLo = 0;
                   1679:     env->hflags = MIPS_HFLAG_ERL;
                   1680:     /* Count register increments in debug mode, EJTAG version 1 */
                   1681:     env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
                   1682:     env->CP0_PRid = MIPS_CPU;
                   1683:     env->exception_index = EXCP_NONE;
                   1684: 
                   1685:     cpu_single_env = env;
                   1686: 
                   1687:     return env;
                   1688: }

unix.superglobalmegacorp.com

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