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

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

unix.superglobalmegacorp.com

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