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

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

unix.superglobalmegacorp.com

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