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

1.1       root        1: /*
                      2:  *  MIPS32 emulation for qemu: main translation routines.
                      3:  * 
                      4:  *  Copyright (c) 2004-2005 Jocelyn Mayer
1.1.1.4 ! root        5:  *  Copyright (c) 2006 Marius Groeger (FPU operations)
1.1       root        6:  *
                      7:  * This library is free software; you can redistribute it and/or
                      8:  * modify it under the terms of the GNU Lesser General Public
                      9:  * License as published by the Free Software Foundation; either
                     10:  * version 2 of the License, or (at your option) any later version.
                     11:  *
                     12:  * This library is distributed in the hope that it will be useful,
                     13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15:  * Lesser General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU Lesser General Public
                     18:  * License along with this library; if not, write to the Free Software
                     19:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     20:  */
                     21: 
                     22: #include <stdarg.h>
                     23: #include <stdlib.h>
                     24: #include <stdio.h>
                     25: #include <string.h>
                     26: #include <inttypes.h>
                     27: 
                     28: #include "cpu.h"
                     29: #include "exec-all.h"
                     30: #include "disas.h"
                     31: 
1.1.1.2   root       32: //#define MIPS_DEBUG_DISAS
1.1       root       33: //#define MIPS_SINGLE_STEP
                     34: 
1.1.1.2   root       35: #ifdef USE_DIRECT_JUMP
                     36: #define TBPARAM(x)
                     37: #else
                     38: #define TBPARAM(x) (long)(x)
                     39: #endif
                     40: 
1.1       root       41: enum {
                     42: #define DEF(s, n, copy_size) INDEX_op_ ## s,
                     43: #include "opc.h"
                     44: #undef DEF
                     45:     NB_OPS,
                     46: };
                     47: 
                     48: static uint16_t *gen_opc_ptr;
                     49: static uint32_t *gen_opparam_ptr;
                     50: 
                     51: #include "gen-op.h"
                     52: 
                     53: /* MIPS opcodes */
                     54: #define EXT_SPECIAL  0x100
                     55: #define EXT_SPECIAL2 0x200
                     56: #define EXT_REGIMM   0x300
                     57: #define EXT_CP0      0x400
                     58: #define EXT_CP1      0x500
                     59: #define EXT_CP2      0x600
                     60: #define EXT_CP3      0x700
                     61: 
                     62: enum {
                     63:     /* indirect opcode tables */
                     64:     OPC_SPECIAL  = 0x00,
                     65:     OPC_BREGIMM  = 0x01,
                     66:     OPC_CP0      = 0x10,
                     67:     OPC_CP1      = 0x11,
                     68:     OPC_CP2      = 0x12,
                     69:     OPC_CP3      = 0x13,
                     70:     OPC_SPECIAL2 = 0x1C,
                     71:     /* arithmetic with immediate */
                     72:     OPC_ADDI     = 0x08,
                     73:     OPC_ADDIU    = 0x09,
                     74:     OPC_SLTI     = 0x0A,
                     75:     OPC_SLTIU    = 0x0B,
                     76:     OPC_ANDI     = 0x0C,
                     77:     OPC_ORI      = 0x0D,
                     78:     OPC_XORI     = 0x0E,
                     79:     OPC_LUI      = 0x0F,
                     80:     /* Jump and branches */
                     81:     OPC_J        = 0x02,
                     82:     OPC_JAL      = 0x03,
                     83:     OPC_BEQ      = 0x04,  /* Unconditional if rs = rt = 0 (B) */
                     84:     OPC_BEQL     = 0x14,
                     85:     OPC_BNE      = 0x05,
                     86:     OPC_BNEL     = 0x15,
                     87:     OPC_BLEZ     = 0x06,
                     88:     OPC_BLEZL    = 0x16,
                     89:     OPC_BGTZ     = 0x07,
                     90:     OPC_BGTZL    = 0x17,
                     91:     OPC_JALX     = 0x1D,  /* MIPS 16 only */
                     92:     /* Load and stores */
                     93:     OPC_LB       = 0x20,
                     94:     OPC_LH       = 0x21,
                     95:     OPC_LWL      = 0x22,
                     96:     OPC_LW       = 0x23,
                     97:     OPC_LBU      = 0x24,
                     98:     OPC_LHU      = 0x25,
                     99:     OPC_LWR      = 0x26,
1.1.1.4 ! root      100:     OPC_LWU      = 0x27,
1.1       root      101:     OPC_SB       = 0x28,
                    102:     OPC_SH       = 0x29,
                    103:     OPC_SWL      = 0x2A,
                    104:     OPC_SW       = 0x2B,
                    105:     OPC_SWR      = 0x2E,
                    106:     OPC_LL       = 0x30,
                    107:     OPC_SC       = 0x38,
                    108:     /* Floating point load/store */
                    109:     OPC_LWC1     = 0x31,
                    110:     OPC_LWC2     = 0x32,
                    111:     OPC_LDC1     = 0x35,
                    112:     OPC_LDC2     = 0x36,
                    113:     OPC_SWC1     = 0x39,
                    114:     OPC_SWC2     = 0x3A,
                    115:     OPC_SDC1     = 0x3D,
                    116:     OPC_SDC2     = 0x3E,
                    117:     /* Cache and prefetch */
                    118:     OPC_CACHE    = 0x2F,
                    119:     OPC_PREF     = 0x33,
                    120: };
                    121: 
                    122: /* MIPS special opcodes */
                    123: enum {
                    124:     /* Shifts */
                    125:     OPC_SLL      = 0x00 | EXT_SPECIAL,
                    126:     /* NOP is SLL r0, r0, 0   */
                    127:     /* SSNOP is SLL r0, r0, 1 */
                    128:     OPC_SRL      = 0x02 | EXT_SPECIAL,
                    129:     OPC_SRA      = 0x03 | EXT_SPECIAL,
                    130:     OPC_SLLV     = 0x04 | EXT_SPECIAL,
                    131:     OPC_SRLV     = 0x06 | EXT_SPECIAL,
                    132:     OPC_SRAV     = 0x07 | EXT_SPECIAL,
                    133:     /* Multiplication / division */
                    134:     OPC_MULT     = 0x18 | EXT_SPECIAL,
                    135:     OPC_MULTU    = 0x19 | EXT_SPECIAL,
                    136:     OPC_DIV      = 0x1A | EXT_SPECIAL,
                    137:     OPC_DIVU     = 0x1B | EXT_SPECIAL,
                    138:     /* 2 registers arithmetic / logic */
                    139:     OPC_ADD      = 0x20 | EXT_SPECIAL,
                    140:     OPC_ADDU     = 0x21 | EXT_SPECIAL,
                    141:     OPC_SUB      = 0x22 | EXT_SPECIAL,
                    142:     OPC_SUBU     = 0x23 | EXT_SPECIAL,
                    143:     OPC_AND      = 0x24 | EXT_SPECIAL,
                    144:     OPC_OR       = 0x25 | EXT_SPECIAL,
                    145:     OPC_XOR      = 0x26 | EXT_SPECIAL,
                    146:     OPC_NOR      = 0x27 | EXT_SPECIAL,
                    147:     OPC_SLT      = 0x2A | EXT_SPECIAL,
                    148:     OPC_SLTU     = 0x2B | EXT_SPECIAL,
                    149:     /* Jumps */
                    150:     OPC_JR       = 0x08 | EXT_SPECIAL,
                    151:     OPC_JALR     = 0x09 | EXT_SPECIAL,
                    152:     /* Traps */
                    153:     OPC_TGE      = 0x30 | EXT_SPECIAL,
                    154:     OPC_TGEU     = 0x31 | EXT_SPECIAL,
                    155:     OPC_TLT      = 0x32 | EXT_SPECIAL,
                    156:     OPC_TLTU     = 0x33 | EXT_SPECIAL,
                    157:     OPC_TEQ      = 0x34 | EXT_SPECIAL,
                    158:     OPC_TNE      = 0x36 | EXT_SPECIAL,
                    159:     /* HI / LO registers load & stores */
                    160:     OPC_MFHI     = 0x10 | EXT_SPECIAL,
                    161:     OPC_MTHI     = 0x11 | EXT_SPECIAL,
                    162:     OPC_MFLO     = 0x12 | EXT_SPECIAL,
                    163:     OPC_MTLO     = 0x13 | EXT_SPECIAL,
                    164:     /* Conditional moves */
                    165:     OPC_MOVZ     = 0x0A | EXT_SPECIAL,
                    166:     OPC_MOVN     = 0x0B | EXT_SPECIAL,
                    167: 
                    168:     OPC_MOVCI    = 0x01 | EXT_SPECIAL,
                    169: 
                    170:     /* Special */
                    171:     OPC_PMON     = 0x05 | EXT_SPECIAL,
                    172:     OPC_SYSCALL  = 0x0C | EXT_SPECIAL,
                    173:     OPC_BREAK    = 0x0D | EXT_SPECIAL,
                    174:     OPC_SYNC     = 0x0F | EXT_SPECIAL,
                    175: };
                    176: 
                    177: enum {
                    178:     /* Mutiply & xxx operations */
                    179:     OPC_MADD     = 0x00 | EXT_SPECIAL2,
                    180:     OPC_MADDU    = 0x01 | EXT_SPECIAL2,
                    181:     OPC_MUL      = 0x02 | EXT_SPECIAL2,
                    182:     OPC_MSUB     = 0x04 | EXT_SPECIAL2,
                    183:     OPC_MSUBU    = 0x05 | EXT_SPECIAL2,
                    184:     /* Misc */
                    185:     OPC_CLZ      = 0x20 | EXT_SPECIAL2,
                    186:     OPC_CLO      = 0x21 | EXT_SPECIAL2,
                    187:     /* Special */
                    188:     OPC_SDBBP    = 0x3F | EXT_SPECIAL2,
                    189: };
                    190: 
                    191: /* Branch REGIMM */
                    192: enum {
                    193:     OPC_BLTZ     = 0x00 | EXT_REGIMM,
                    194:     OPC_BLTZL    = 0x02 | EXT_REGIMM,
                    195:     OPC_BGEZ     = 0x01 | EXT_REGIMM,
                    196:     OPC_BGEZL    = 0x03 | EXT_REGIMM,
                    197:     OPC_BLTZAL   = 0x10 | EXT_REGIMM,
                    198:     OPC_BLTZALL  = 0x12 | EXT_REGIMM,
                    199:     OPC_BGEZAL   = 0x11 | EXT_REGIMM,
                    200:     OPC_BGEZALL  = 0x13 | EXT_REGIMM,
                    201:     OPC_TGEI     = 0x08 | EXT_REGIMM,
                    202:     OPC_TGEIU    = 0x09 | EXT_REGIMM,
                    203:     OPC_TLTI     = 0x0A | EXT_REGIMM,
                    204:     OPC_TLTIU    = 0x0B | EXT_REGIMM,
                    205:     OPC_TEQI     = 0x0C | EXT_REGIMM,
                    206:     OPC_TNEI     = 0x0E | EXT_REGIMM,
                    207: };
                    208: 
                    209: enum {
                    210:     /* Coprocessor 0 (MMU) */
                    211:     OPC_MFC0     = 0x00 | EXT_CP0,
                    212:     OPC_MTC0     = 0x04 | EXT_CP0,
                    213:     OPC_TLBR     = 0x01 | EXT_CP0,
                    214:     OPC_TLBWI    = 0x02 | EXT_CP0,
                    215:     OPC_TLBWR    = 0x06 | EXT_CP0,
                    216:     OPC_TLBP     = 0x08 | EXT_CP0,
                    217:     OPC_ERET     = 0x18 | EXT_CP0,
                    218:     OPC_DERET    = 0x1F | EXT_CP0,
                    219:     OPC_WAIT     = 0x20 | EXT_CP0,
                    220: };
                    221: 
1.1.1.4 ! root      222: #ifdef MIPS_USES_FPU
        !           223: enum {
        !           224:     /* Coprocessor 1 (FPU) */
        !           225:     OPC_MFC1     = 0x00 | EXT_CP1,
        !           226:     OPC_MTC1     = 0x04 | EXT_CP1,
        !           227:     OPC_CFC1     = 0x02 | EXT_CP1,
        !           228:     OPC_CTC1     = 0x06 | EXT_CP1,
        !           229: };
        !           230: #endif
        !           231: 
1.1       root      232: const unsigned char *regnames[] =
                    233:     { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
                    234:       "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
                    235:       "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
                    236:       "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
                    237: 
                    238: /* Warning: no function for r0 register (hard wired to zero) */
                    239: #define GEN32(func, NAME) \
                    240: static GenOpFunc *NAME ## _table [32] = {                                     \
                    241: NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \
                    242: NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \
                    243: NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \
                    244: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
                    245: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
                    246: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
                    247: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
                    248: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
                    249: };                                                                            \
                    250: static inline void func(int n)                                                \
                    251: {                                                                             \
                    252:     NAME ## _table[n]();                                                      \
                    253: }
                    254: 
                    255: /* General purpose registers moves */
                    256: GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
                    257: GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
                    258: GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
                    259: 
                    260: GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
                    261: GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
                    262: 
1.1.1.4 ! root      263: #ifdef MIPS_USES_FPU
        !           264: const unsigned char *fregnames[] =
        !           265:     { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
        !           266:       "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
        !           267:       "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
        !           268:       "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
        !           269: 
        !           270: # define SFGEN32(func, NAME) \
        !           271: static GenOpFunc *NAME ## _table [32] = {                                     \
        !           272: NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,                                \
        !           273: NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,                                \
        !           274: NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,                               \
        !           275: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
        !           276: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
        !           277: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
        !           278: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
        !           279: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
        !           280: };                                                                            \
        !           281: static inline void func(int n)                                                \
        !           282: {                                                                             \
        !           283:     NAME ## _table[n]();                                                      \
        !           284: }
        !           285: 
        !           286: # define DFGEN32(func, NAME) \
        !           287: static GenOpFunc *NAME ## _table [32] = {                                     \
        !           288: NAME ## 0,  0, NAME ## 2,  0,                                                 \
        !           289: NAME ## 4,  0, NAME ## 6,  0,                                                 \
        !           290: NAME ## 8,  0, NAME ## 10, 0,                                                 \
        !           291: NAME ## 12, 0, NAME ## 14, 0,                                                 \
        !           292: NAME ## 16, 0, NAME ## 18, 0,                                                 \
        !           293: NAME ## 20, 0, NAME ## 22, 0,                                                 \
        !           294: NAME ## 24, 0, NAME ## 26, 0,                                                 \
        !           295: NAME ## 28, 0, NAME ## 30, 0,                                                 \
        !           296: };                                                                            \
        !           297: static inline void func(int n)                                                \
        !           298: {                                                                             \
        !           299:     NAME ## _table[n]();                                                      \
        !           300: }
        !           301: 
        !           302: SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
        !           303: SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
        !           304: 
        !           305: SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
        !           306: SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
        !           307: 
        !           308: SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
        !           309: SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
        !           310: 
        !           311: DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
        !           312: DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
        !           313: 
        !           314: DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
        !           315: DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
        !           316: 
        !           317: DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
        !           318: DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
        !           319: 
        !           320: #define FOP_CONDS(fmt) \
        !           321: static GenOpFunc * cond_ ## fmt ## _table[16] = {                       \
        !           322:     gen_op_cmp_ ## fmt ## _f,                                           \
        !           323:     gen_op_cmp_ ## fmt ## _un,                                          \
        !           324:     gen_op_cmp_ ## fmt ## _eq,                                          \
        !           325:     gen_op_cmp_ ## fmt ## _ueq,                                         \
        !           326:     gen_op_cmp_ ## fmt ## _olt,                                         \
        !           327:     gen_op_cmp_ ## fmt ## _ult,                                         \
        !           328:     gen_op_cmp_ ## fmt ## _ole,                                         \
        !           329:     gen_op_cmp_ ## fmt ## _ule,                                         \
        !           330:     gen_op_cmp_ ## fmt ## _sf,                                          \
        !           331:     gen_op_cmp_ ## fmt ## _ngle,                                        \
        !           332:     gen_op_cmp_ ## fmt ## _seq,                                         \
        !           333:     gen_op_cmp_ ## fmt ## _ngl,                                         \
        !           334:     gen_op_cmp_ ## fmt ## _lt,                                          \
        !           335:     gen_op_cmp_ ## fmt ## _nge,                                         \
        !           336:     gen_op_cmp_ ## fmt ## _le,                                          \
        !           337:     gen_op_cmp_ ## fmt ## _ngt,                                         \
        !           338: };                                                                      \
        !           339: static inline void gen_cmp_ ## fmt(int n)                               \
        !           340: {                                                                       \
        !           341:     cond_ ## fmt ## _table[n]();                                        \
        !           342: }
        !           343: 
        !           344: FOP_CONDS(d)
        !           345: FOP_CONDS(s)
        !           346: 
        !           347: #endif
        !           348: 
1.1       root      349: typedef struct DisasContext {
                    350:     struct TranslationBlock *tb;
                    351:     target_ulong pc, saved_pc;
                    352:     uint32_t opcode;
                    353:     /* Routine used to access memory */
                    354:     int mem_idx;
                    355:     uint32_t hflags, saved_hflags;
                    356:     uint32_t CP0_Status;
                    357:     int bstate;
                    358:     target_ulong btarget;
                    359: } DisasContext;
                    360: 
                    361: enum {
                    362:     BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
                    363:                       * exception condition
                    364:                       */
                    365:     BS_STOP     = 1, /* We want to stop translation for any reason */
                    366:     BS_BRANCH   = 2, /* We reached a branch condition     */
                    367:     BS_EXCP     = 3, /* We reached an exception condition */
                    368: };
                    369: 
                    370: #if defined MIPS_DEBUG_DISAS
                    371: #define MIPS_DEBUG(fmt, args...)                                              \
                    372: do {                                                                          \
                    373:     if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
                    374:         fprintf(logfile, "%08x: %08x " fmt "\n",                              \
                    375:                 ctx->pc, ctx->opcode , ##args);                               \
                    376:     }                                                                         \
                    377: } while (0)
                    378: #else
                    379: #define MIPS_DEBUG(fmt, args...) do { } while(0)
                    380: #endif
                    381: 
                    382: #define MIPS_INVAL(op)                                                        \
                    383: do {                                                                          \
                    384:     MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
                    385:                ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
                    386: } while (0)
                    387: 
                    388: #define GEN_LOAD_REG_TN(Tn, Rn)                                               \
                    389: do {                                                                          \
                    390:     if (Rn == 0) {                                                            \
                    391:         glue(gen_op_reset_, Tn)();                                            \
                    392:     } else {                                                                  \
                    393:         glue(gen_op_load_gpr_, Tn)(Rn);                                       \
                    394:     }                                                                         \
                    395: } while (0)
                    396: 
                    397: #define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
                    398: do {                                                                          \
                    399:     if (Imm == 0) {                                                           \
                    400:         glue(gen_op_reset_, Tn)();                                            \
                    401:     } else {                                                                  \
                    402:         glue(gen_op_set_, Tn)(Imm);                                           \
                    403:     }                                                                         \
                    404: } while (0)
                    405: 
                    406: #define GEN_STORE_TN_REG(Rn, Tn)                                              \
                    407: do {                                                                          \
                    408:     if (Rn != 0) {                                                            \
                    409:         glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \
                    410:     }                                                                         \
                    411: } while (0)
                    412: 
1.1.1.4 ! root      413: #ifdef MIPS_USES_FPU
        !           414: 
        !           415: # define GEN_LOAD_FREG_FTN(FTn, Fn)                                           \
        !           416: do {                                                                          \
        !           417:     glue(gen_op_load_fpr_, FTn)(Fn);                                          \
        !           418: } while (0)
        !           419: 
        !           420: #define GEN_STORE_FTN_FREG(Fn, FTn)                                           \
        !           421: do {                                                                          \
        !           422:     glue(gen_op_store_fpr_, FTn)(Fn);                                         \
        !           423: } while (0)
        !           424: 
        !           425: #endif
        !           426: 
1.1       root      427: static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
                    428: {
                    429: #if defined MIPS_DEBUG_DISAS
                    430:     if (loglevel & CPU_LOG_TB_IN_ASM) {
                    431:             fprintf(logfile, "hflags %08x saved %08x\n",
                    432:                     ctx->hflags, ctx->saved_hflags);
                    433:     }
                    434: #endif
                    435:     if (do_save_pc && ctx->pc != ctx->saved_pc) {
                    436:         gen_op_save_pc(ctx->pc);
                    437:         ctx->saved_pc = ctx->pc;
                    438:     }
                    439:     if (ctx->hflags != ctx->saved_hflags) {
                    440:         gen_op_save_state(ctx->hflags);
                    441:         ctx->saved_hflags = ctx->hflags;
                    442:         if (ctx->hflags & MIPS_HFLAG_BR) {
                    443:             gen_op_save_breg_target();
                    444:         } else if (ctx->hflags & MIPS_HFLAG_B) {
                    445:             gen_op_save_btarget(ctx->btarget);
                    446:         } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
                    447:             gen_op_save_bcond();
                    448:             gen_op_save_btarget(ctx->btarget);
                    449:         }
                    450:     }
                    451: }
                    452: 
1.1.1.2   root      453: static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
1.1       root      454: {
                    455: #if defined MIPS_DEBUG_DISAS
                    456:     if (loglevel & CPU_LOG_TB_IN_ASM)
                    457:             fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
                    458: #endif
                    459:     save_cpu_state(ctx, 1);
1.1.1.2   root      460:     if (err == 0)
                    461:         gen_op_raise_exception(excp);
                    462:     else
                    463:         gen_op_raise_exception_err(excp, err);
1.1       root      464:     ctx->bstate = BS_EXCP;
                    465: }
                    466: 
1.1.1.2   root      467: static inline void generate_exception (DisasContext *ctx, int excp)
                    468: {
                    469:     generate_exception_err (ctx, excp, 0);
                    470: }
                    471: 
1.1       root      472: #if defined(CONFIG_USER_ONLY)
                    473: #define op_ldst(name)        gen_op_##name##_raw()
                    474: #define OP_LD_TABLE(width)
                    475: #define OP_ST_TABLE(width)
                    476: #else
                    477: #define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
                    478: #define OP_LD_TABLE(width)                                                    \
                    479: static GenOpFunc *gen_op_l##width[] = {                                       \
                    480:     &gen_op_l##width##_user,                                                  \
                    481:     &gen_op_l##width##_kernel,                                                \
                    482: }
                    483: #define OP_ST_TABLE(width)                                                    \
                    484: static GenOpFunc *gen_op_s##width[] = {                                       \
                    485:     &gen_op_s##width##_user,                                                  \
                    486:     &gen_op_s##width##_kernel,                                                \
                    487: }
                    488: #endif
                    489: 
                    490: #ifdef TARGET_MIPS64
                    491: OP_LD_TABLE(d);
                    492: OP_LD_TABLE(dl);
                    493: OP_LD_TABLE(dr);
                    494: OP_ST_TABLE(d);
                    495: OP_ST_TABLE(dl);
                    496: OP_ST_TABLE(dr);
                    497: #endif
                    498: OP_LD_TABLE(w);
1.1.1.4 ! root      499: OP_LD_TABLE(wu);
1.1       root      500: OP_LD_TABLE(wl);
                    501: OP_LD_TABLE(wr);
                    502: OP_ST_TABLE(w);
                    503: OP_ST_TABLE(wl);
                    504: OP_ST_TABLE(wr);
                    505: OP_LD_TABLE(h);
                    506: OP_LD_TABLE(hu);
                    507: OP_ST_TABLE(h);
                    508: OP_LD_TABLE(b);
                    509: OP_LD_TABLE(bu);
                    510: OP_ST_TABLE(b);
                    511: OP_LD_TABLE(l);
                    512: OP_ST_TABLE(c);
1.1.1.4 ! root      513: #ifdef MIPS_USES_FPU
        !           514: OP_LD_TABLE(wc1);
        !           515: OP_ST_TABLE(wc1);
        !           516: OP_LD_TABLE(dc1);
        !           517: OP_ST_TABLE(dc1);
        !           518: #endif
1.1       root      519: 
                    520: /* Load and store */
                    521: static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt,
                    522:                       int base, int16_t offset)
                    523: {
                    524:     const unsigned char *opn = "unk";
                    525: 
                    526:     if (base == 0) {
                    527:         GEN_LOAD_IMM_TN(T0, offset);
                    528:     } else if (offset == 0) {
                    529:         gen_op_load_gpr_T0(base);
                    530:     } else {
                    531:         gen_op_load_gpr_T0(base);
                    532:         gen_op_set_T1(offset);
                    533:         gen_op_add();
                    534:     }
                    535:     /* Don't do NOP if destination is zero: we must perform the actual
                    536:      * memory access
                    537:      */
                    538:     switch (opc) {
                    539: #if defined(TARGET_MIPS64)
                    540:     case OPC_LD:
                    541: #if defined (MIPS_HAS_UNALIGNED_LS)
                    542:     case OPC_ULD:
                    543: #endif
                    544:         op_ldst(ld);
                    545:         GEN_STORE_TN_REG(rt, T0);
                    546:         opn = "ld";
                    547:         break;
                    548:     case OPC_SD:
                    549: #if defined (MIPS_HAS_UNALIGNED_LS)
                    550:     case OPC_USD:
                    551: #endif
                    552:         GEN_LOAD_REG_TN(T1, rt);
                    553:         op_ldst(sd);
                    554:         opn = "sd";
                    555:         break;
                    556:     case OPC_LDL:
                    557:         op_ldst(ldl);
                    558:         GEN_STORE_TN_REG(rt, T0);
                    559:         opn = "ldl";
                    560:         break;
                    561:     case OPC_SDL:
                    562:         GEN_LOAD_REG_TN(T1, rt);
                    563:         op_ldst(sdl);
                    564:         opn = "sdl";
                    565:         break;
                    566:     case OPC_LDR:
                    567:         op_ldst(ldr);
                    568:         GEN_STORE_TN_REG(rt, T0);
                    569:         opn = "ldr";
                    570:         break;
                    571:     case OPC_SDR:
                    572:         GEN_LOAD_REG_TN(T1, rt);
                    573:         op_ldst(sdr);
                    574:         opn = "sdr";
                    575:         break;
                    576: #endif
                    577:     case OPC_LW:
                    578: #if defined (MIPS_HAS_UNALIGNED_LS)
                    579:     case OPC_ULW:
                    580: #endif
                    581:         op_ldst(lw);
                    582:         GEN_STORE_TN_REG(rt, T0);
                    583:         opn = "lw";
                    584:         break;
1.1.1.4 ! root      585:     case OPC_LWU:
        !           586:         op_ldst(lwu);
        !           587:         GEN_STORE_TN_REG(rt, T0);
        !           588:         opn = "lwu";
        !           589:         break;
1.1       root      590:     case OPC_SW:
                    591: #if defined (MIPS_HAS_UNALIGNED_LS)
                    592:     case OPC_USW:
                    593: #endif
                    594:         GEN_LOAD_REG_TN(T1, rt);
                    595:         op_ldst(sw);
                    596:         opn = "sw";
                    597:         break;
                    598:     case OPC_LH:
                    599: #if defined (MIPS_HAS_UNALIGNED_LS)
                    600:     case OPC_ULH:
                    601: #endif
                    602:         op_ldst(lh);
                    603:         GEN_STORE_TN_REG(rt, T0);
                    604:         opn = "lh";
                    605:         break;
                    606:     case OPC_SH:
                    607: #if defined (MIPS_HAS_UNALIGNED_LS)
                    608:     case OPC_USH:
                    609: #endif
                    610:         GEN_LOAD_REG_TN(T1, rt);
                    611:         op_ldst(sh);
                    612:         opn = "sh";
                    613:         break;
                    614:     case OPC_LHU:
                    615: #if defined (MIPS_HAS_UNALIGNED_LS)
                    616:     case OPC_ULHU:
                    617: #endif
                    618:         op_ldst(lhu);
                    619:         GEN_STORE_TN_REG(rt, T0);
                    620:         opn = "lhu";
                    621:         break;
                    622:     case OPC_LB:
                    623:         op_ldst(lb);
                    624:         GEN_STORE_TN_REG(rt, T0);
                    625:         opn = "lb";
                    626:         break;
                    627:     case OPC_SB:
                    628:         GEN_LOAD_REG_TN(T1, rt);
                    629:         op_ldst(sb);
                    630:         opn = "sb";
                    631:         break;
                    632:     case OPC_LBU:
                    633:         op_ldst(lbu);
                    634:         GEN_STORE_TN_REG(rt, T0);
                    635:         opn = "lbu";
                    636:         break;
                    637:     case OPC_LWL:
                    638:        GEN_LOAD_REG_TN(T1, rt);
                    639:         op_ldst(lwl);
                    640:         GEN_STORE_TN_REG(rt, T0);
                    641:         opn = "lwl";
                    642:         break;
                    643:     case OPC_SWL:
                    644:         GEN_LOAD_REG_TN(T1, rt);
                    645:         op_ldst(swl);
                    646:         opn = "swr";
                    647:         break;
                    648:     case OPC_LWR:
                    649:        GEN_LOAD_REG_TN(T1, rt);
                    650:         op_ldst(lwr);
                    651:         GEN_STORE_TN_REG(rt, T0);
                    652:         opn = "lwr";
                    653:         break;
                    654:     case OPC_SWR:
                    655:         GEN_LOAD_REG_TN(T1, rt);
                    656:         op_ldst(swr);
                    657:         opn = "swr";
                    658:         break;
                    659:     case OPC_LL:
                    660:         op_ldst(ll);
                    661:         GEN_STORE_TN_REG(rt, T0);
                    662:         opn = "ll";
                    663:         break;
                    664:     case OPC_SC:
                    665:         GEN_LOAD_REG_TN(T1, rt);
                    666:         op_ldst(sc);
                    667:         GEN_STORE_TN_REG(rt, T0);
                    668:         opn = "sc";
                    669:         break;
                    670:     default:
                    671:         MIPS_INVAL("load/store");
                    672:         generate_exception(ctx, EXCP_RI);
                    673:         return;
                    674:     }
                    675:     MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
                    676: }
                    677: 
1.1.1.4 ! root      678: #ifdef MIPS_USES_FPU
        !           679: 
        !           680: /* Load and store */
        !           681: static void gen_flt_ldst (DisasContext *ctx, uint16_t opc, int ft,
        !           682:                       int base, int16_t offset)
        !           683: {
        !           684:     const unsigned char *opn = "unk";
        !           685: 
        !           686:     if (base == 0) {
        !           687:         GEN_LOAD_IMM_TN(T0, offset);
        !           688:     } else if (offset == 0) {
        !           689:         gen_op_load_gpr_T0(base);
        !           690:     } else {
        !           691:         gen_op_load_gpr_T0(base);
        !           692:         gen_op_set_T1(offset);
        !           693:         gen_op_add();
        !           694:     }
        !           695:     /* Don't do NOP if destination is zero: we must perform the actual
        !           696:      * memory access
        !           697:      */
        !           698:     switch (opc) {
        !           699:     case OPC_LWC1:
        !           700:         op_ldst(lwc1);
        !           701:         GEN_STORE_FTN_FREG(ft, WT0);
        !           702:         opn = "lwc1";
        !           703:         break;
        !           704:     case OPC_SWC1:
        !           705:         GEN_LOAD_FREG_FTN(WT0, ft);
        !           706:         op_ldst(swc1);
        !           707:         opn = "swc1";
        !           708:         break;
        !           709:     case OPC_LDC1:
        !           710:         op_ldst(ldc1);
        !           711:         GEN_STORE_FTN_FREG(ft, DT0);
        !           712:         opn = "ldc1";
        !           713:         break;
        !           714:     case OPC_SDC1:
        !           715:         GEN_LOAD_FREG_FTN(DT0, ft);
        !           716:         op_ldst(sdc1);
        !           717:         opn = "sdc1";
        !           718:         break;
        !           719:     default:
        !           720:         MIPS_INVAL("float load/store");
        !           721:         generate_exception(ctx, EXCP_CpU);
        !           722:         return;
        !           723:     }
        !           724:     MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
        !           725: }
        !           726: #endif
        !           727: 
1.1       root      728: /* Arithmetic with immediate operand */
                    729: static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt,
                    730:                            int rs, int16_t imm)
                    731: {
                    732:     uint32_t uimm;
                    733:     const unsigned char *opn = "unk";
                    734: 
                    735:     if (rt == 0 && opc != OPC_ADDI) {
                    736:         /* if no destination, treat it as a NOP 
                    737:          * For addi, we must generate the overflow exception when needed.
                    738:          */
                    739:         MIPS_DEBUG("NOP");
                    740:         return;
                    741:     }
                    742:     if (opc == OPC_ADDI || opc == OPC_ADDIU ||
                    743:         opc == OPC_SLTI || opc == OPC_SLTIU)
                    744:         uimm = (int32_t)imm; /* Sign extent to 32 bits */
                    745:     else
                    746:         uimm = (uint16_t)imm;
                    747:     if (opc != OPC_LUI) {
                    748:         GEN_LOAD_REG_TN(T0, rs);
                    749:         GEN_LOAD_IMM_TN(T1, uimm);
                    750:     } else {
                    751:         uimm = uimm << 16;
                    752:         GEN_LOAD_IMM_TN(T0, uimm);
                    753:     }
                    754:     switch (opc) {
                    755:     case OPC_ADDI:
                    756:         save_cpu_state(ctx, 1);
                    757:         gen_op_addo();
                    758:         opn = "addi";
                    759:         break;
                    760:     case OPC_ADDIU:
                    761:         gen_op_add();
                    762:         opn = "addiu";
                    763:         break;
                    764:     case OPC_SLTI:
                    765:         gen_op_lt();
                    766:         opn = "slti";
                    767:         break;
                    768:     case OPC_SLTIU:
                    769:         gen_op_ltu();
                    770:         opn = "sltiu";
                    771:         break;
                    772:     case OPC_ANDI:
                    773:         gen_op_and();
                    774:         opn = "andi";
                    775:         break;
                    776:     case OPC_ORI:
                    777:         gen_op_or();
                    778:         opn = "ori";
                    779:         break;
                    780:     case OPC_XORI:
                    781:         gen_op_xor();
                    782:         opn = "xori";
                    783:         break;
                    784:     case OPC_LUI:
                    785:         opn = "lui";
                    786:         break;
                    787:     case OPC_SLL:
                    788:         gen_op_sll();
                    789:         opn = "sll";
                    790:         break;
                    791:     case OPC_SRA:
                    792:         gen_op_sra();
                    793:         opn = "sra";
                    794:         break;
                    795:     case OPC_SRL:
                    796:         gen_op_srl();
                    797:         opn = "srl";
                    798:         break;
                    799:     default:
                    800:         MIPS_INVAL("imm arith");
                    801:         generate_exception(ctx, EXCP_RI);
                    802:         return;
                    803:     }
                    804:     GEN_STORE_TN_REG(rt, T0);
                    805:     MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);
                    806: }
                    807: 
                    808: /* Arithmetic */
                    809: static void gen_arith (DisasContext *ctx, uint16_t opc,
                    810:                        int rd, int rs, int rt)
                    811: {
                    812:     const unsigned char *opn = "unk";
                    813: 
                    814:     if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB) {
                    815:         /* if no destination, treat it as a NOP 
                    816:          * For add & sub, we must generate the overflow exception when needed.
                    817:          */
                    818:         MIPS_DEBUG("NOP");
                    819:         return;
                    820:     }
                    821:     GEN_LOAD_REG_TN(T0, rs);
                    822:     GEN_LOAD_REG_TN(T1, rt);
                    823:     switch (opc) {
                    824:     case OPC_ADD:
                    825:         save_cpu_state(ctx, 1);
                    826:         gen_op_addo();
                    827:         opn = "add";
                    828:         break;
                    829:     case OPC_ADDU:
                    830:         gen_op_add();
                    831:         opn = "addu";
                    832:         break;
                    833:     case OPC_SUB:
                    834:         save_cpu_state(ctx, 1);
                    835:         gen_op_subo();
                    836:         opn = "sub";
                    837:         break;
                    838:     case OPC_SUBU:
                    839:         gen_op_sub();
                    840:         opn = "subu";
                    841:         break;
                    842:     case OPC_SLT:
                    843:         gen_op_lt();
                    844:         opn = "slt";
                    845:         break;
                    846:     case OPC_SLTU:
                    847:         gen_op_ltu();
                    848:         opn = "sltu";
                    849:         break;
                    850:     case OPC_AND:
                    851:         gen_op_and();
                    852:         opn = "and";
                    853:         break;
                    854:     case OPC_NOR:
                    855:         gen_op_nor();
                    856:         opn = "nor";
                    857:         break;
                    858:     case OPC_OR:
                    859:         gen_op_or();
                    860:         opn = "or";
                    861:         break;
                    862:     case OPC_XOR:
                    863:         gen_op_xor();
                    864:         opn = "xor";
                    865:         break;
                    866:     case OPC_MUL:
                    867:         gen_op_mul();
                    868:         opn = "mul";
                    869:         break;
                    870:     case OPC_MOVN:
                    871:         gen_op_movn(rd);
                    872:         opn = "movn";
                    873:         goto print;
                    874:     case OPC_MOVZ:
                    875:         gen_op_movz(rd);
                    876:         opn = "movz";
                    877:         goto print;
                    878:     case OPC_SLLV:
                    879:         gen_op_sllv();
                    880:         opn = "sllv";
                    881:         break;
                    882:     case OPC_SRAV:
                    883:         gen_op_srav();
                    884:         opn = "srav";
                    885:         break;
                    886:     case OPC_SRLV:
                    887:         gen_op_srlv();
                    888:         opn = "srlv";
                    889:         break;
                    890:     default:
                    891:         MIPS_INVAL("arith");
                    892:         generate_exception(ctx, EXCP_RI);
                    893:         return;
                    894:     }
                    895:     GEN_STORE_TN_REG(rd, T0);
                    896:  print:
                    897:     MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
                    898: }
                    899: 
                    900: /* Arithmetic on HI/LO registers */
                    901: static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg)
                    902: {
                    903:     const unsigned char *opn = "unk";
                    904: 
                    905:     if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
                    906:         /* Treat as a NOP */
                    907:         MIPS_DEBUG("NOP");
                    908:         return;
                    909:     }
                    910:     switch (opc) {
                    911:     case OPC_MFHI:
                    912:         gen_op_load_HI();
                    913:         GEN_STORE_TN_REG(reg, T0);
                    914:         opn = "mfhi";
                    915:         break;
                    916:     case OPC_MFLO:
                    917:         gen_op_load_LO();
                    918:         GEN_STORE_TN_REG(reg, T0);
                    919:         opn = "mflo";
                    920:         break;
                    921:     case OPC_MTHI:
                    922:         GEN_LOAD_REG_TN(T0, reg);
                    923:         gen_op_store_HI();
                    924:         opn = "mthi";
                    925:         break;
                    926:     case OPC_MTLO:
                    927:         GEN_LOAD_REG_TN(T0, reg);
                    928:         gen_op_store_LO();
                    929:         opn = "mtlo";
                    930:         break;
                    931:     default:
                    932:         MIPS_INVAL("HILO");
                    933:         generate_exception(ctx, EXCP_RI);
                    934:         return;
                    935:     }
                    936:     MIPS_DEBUG("%s %s", opn, regnames[reg]);
                    937: }
                    938: 
                    939: static void gen_muldiv (DisasContext *ctx, uint16_t opc,
                    940:                         int rs, int rt)
                    941: {
                    942:     const unsigned char *opn = "unk";
                    943: 
                    944:     GEN_LOAD_REG_TN(T0, rs);
                    945:     GEN_LOAD_REG_TN(T1, rt);
                    946:     switch (opc) {
                    947:     case OPC_DIV:
                    948:         gen_op_div();
                    949:         opn = "div";
                    950:         break;
                    951:     case OPC_DIVU:
                    952:         gen_op_divu();
                    953:         opn = "divu";
                    954:         break;
                    955:     case OPC_MULT:
                    956:         gen_op_mult();
                    957:         opn = "mult";
                    958:         break;
                    959:     case OPC_MULTU:
                    960:         gen_op_multu();
                    961:         opn = "multu";
                    962:         break;
                    963:     case OPC_MADD:
                    964:         gen_op_madd();
                    965:         opn = "madd";
                    966:         break;
                    967:     case OPC_MADDU:
                    968:         gen_op_maddu();
                    969:         opn = "maddu";
                    970:         break;
                    971:     case OPC_MSUB:
                    972:         gen_op_msub();
                    973:         opn = "msub";
                    974:         break;
                    975:     case OPC_MSUBU:
                    976:         gen_op_msubu();
                    977:         opn = "msubu";
                    978:         break;
                    979:     default:
                    980:         MIPS_INVAL("mul/div");
                    981:         generate_exception(ctx, EXCP_RI);
                    982:         return;
                    983:     }
                    984:     MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
                    985: }
                    986: 
                    987: static void gen_cl (DisasContext *ctx, uint16_t opc,
                    988:                     int rd, int rs)
                    989: {
                    990:     const unsigned char *opn = "unk";
                    991:     if (rd == 0) {
                    992:         /* Treat as a NOP */
                    993:         MIPS_DEBUG("NOP");
                    994:         return;
                    995:     }
                    996:     GEN_LOAD_REG_TN(T0, rs);
                    997:     switch (opc) {
                    998:     case OPC_CLO:
                    999:         /* CLO */
                   1000:         gen_op_clo();
                   1001:         opn = "clo";
                   1002:         break;
                   1003:     case OPC_CLZ:
                   1004:         /* CLZ */
                   1005:         gen_op_clz();
                   1006:         opn = "clz";
                   1007:         break;
                   1008:     default:
                   1009:         MIPS_INVAL("CLx");
                   1010:         generate_exception(ctx, EXCP_RI);
                   1011:         return;
                   1012:     }
                   1013:     gen_op_store_T0_gpr(rd);
                   1014:     MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
                   1015: }
                   1016: 
                   1017: /* Traps */
                   1018: static void gen_trap (DisasContext *ctx, uint16_t opc,
                   1019:                       int rs, int rt, int16_t imm)
                   1020: {
                   1021:     int cond;
                   1022: 
                   1023:     cond = 0;
                   1024:     /* Load needed operands */
                   1025:     switch (opc) {
                   1026:     case OPC_TEQ:
                   1027:     case OPC_TGE:
                   1028:     case OPC_TGEU:
                   1029:     case OPC_TLT:
                   1030:     case OPC_TLTU:
                   1031:     case OPC_TNE:
                   1032:         /* Compare two registers */
                   1033:         if (rs != rt) {
                   1034:             GEN_LOAD_REG_TN(T0, rs);
                   1035:             GEN_LOAD_REG_TN(T1, rt);
                   1036:             cond = 1;
                   1037:         }
                   1038:     case OPC_TEQI:
                   1039:     case OPC_TGEI:
                   1040:     case OPC_TGEIU:
                   1041:     case OPC_TLTI:
                   1042:     case OPC_TLTIU:
                   1043:     case OPC_TNEI:
                   1044:         /* Compare register to immediate */
                   1045:         if (rs != 0 || imm != 0) {
                   1046:             GEN_LOAD_REG_TN(T0, rs);
                   1047:             GEN_LOAD_IMM_TN(T1, (int32_t)imm);
                   1048:             cond = 1;
                   1049:         }
                   1050:         break;
                   1051:     }
                   1052:     if (cond == 0) {
                   1053:         switch (opc) {
                   1054:         case OPC_TEQ:   /* rs == rs */
                   1055:         case OPC_TEQI:  /* r0 == 0  */
                   1056:         case OPC_TGE:   /* rs >= rs */
                   1057:         case OPC_TGEI:  /* r0 >= 0  */
                   1058:         case OPC_TGEU:  /* rs >= rs unsigned */
                   1059:         case OPC_TGEIU: /* r0 >= 0  unsigned */
                   1060:             /* Always trap */
                   1061:             gen_op_set_T0(1);
                   1062:             break;
                   1063:         case OPC_TLT:   /* rs < rs           */
                   1064:         case OPC_TLTI:  /* r0 < 0            */
                   1065:         case OPC_TLTU:  /* rs < rs unsigned  */
                   1066:         case OPC_TLTIU: /* r0 < 0  unsigned  */
                   1067:         case OPC_TNE:   /* rs != rs          */
                   1068:         case OPC_TNEI:  /* r0 != 0           */
                   1069:             /* Never trap: treat as NOP */
                   1070:             return;
                   1071:         default:
                   1072:             MIPS_INVAL("TRAP");
                   1073:             generate_exception(ctx, EXCP_RI);
                   1074:             return;
                   1075:         }
                   1076:     } else {
                   1077:         switch (opc) {
                   1078:         case OPC_TEQ:
                   1079:         case OPC_TEQI:
                   1080:             gen_op_eq();
                   1081:             break;
                   1082:         case OPC_TGE:
                   1083:         case OPC_TGEI:
                   1084:             gen_op_ge();
                   1085:             break;
                   1086:         case OPC_TGEU:
                   1087:         case OPC_TGEIU:
                   1088:             gen_op_geu();
                   1089:             break;
                   1090:         case OPC_TLT:
                   1091:         case OPC_TLTI:
                   1092:             gen_op_lt();
                   1093:             break;
                   1094:         case OPC_TLTU:
                   1095:         case OPC_TLTIU:
                   1096:             gen_op_ltu();
                   1097:             break;
                   1098:         case OPC_TNE:
                   1099:         case OPC_TNEI:
                   1100:             gen_op_ne();
                   1101:             break;
                   1102:         default:
                   1103:             MIPS_INVAL("TRAP");
                   1104:             generate_exception(ctx, EXCP_RI);
                   1105:             return;
                   1106:         }
                   1107:     }
                   1108:     save_cpu_state(ctx, 1);
                   1109:     gen_op_trap();
                   1110:     ctx->bstate = BS_STOP;
                   1111: }
                   1112: 
1.1.1.2   root     1113: static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
                   1114: {
                   1115:     TranslationBlock *tb;
                   1116:     tb = ctx->tb;
                   1117:     if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
                   1118:         if (n == 0)
                   1119:             gen_op_goto_tb0(TBPARAM(tb));
                   1120:         else
                   1121:             gen_op_goto_tb1(TBPARAM(tb));
                   1122:         gen_op_save_pc(dest);
                   1123:         gen_op_set_T0((long)tb + n);
                   1124:         gen_op_exit_tb();
                   1125:     } else {
                   1126:         gen_op_save_pc(dest);
                   1127:         gen_op_set_T0(0);
                   1128:         gen_op_exit_tb();
                   1129:     }
                   1130: }
                   1131: 
1.1       root     1132: /* Branches (before delay slot) */
                   1133: static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
                   1134:                                 int rs, int rt, int32_t offset)
                   1135: {
                   1136:     target_ulong btarget;
                   1137:     int blink, bcond;
                   1138: 
                   1139:     btarget = -1;
                   1140:     blink = 0;
                   1141:     bcond = 0;
                   1142:     /* Load needed operands */
                   1143:     switch (opc) {
                   1144:     case OPC_BEQ:
                   1145:     case OPC_BEQL:
                   1146:     case OPC_BNE:
                   1147:     case OPC_BNEL:
                   1148:         /* Compare two registers */
                   1149:         if (rs != rt) {
                   1150:             GEN_LOAD_REG_TN(T0, rs);
                   1151:             GEN_LOAD_REG_TN(T1, rt);
                   1152:             bcond = 1;
                   1153:         }
                   1154:         btarget = ctx->pc + 4 + offset;
                   1155:         break;
                   1156:     case OPC_BGEZ:
                   1157:     case OPC_BGEZAL:
                   1158:     case OPC_BGEZALL:
                   1159:     case OPC_BGEZL:
                   1160:     case OPC_BGTZ:
                   1161:     case OPC_BGTZL:
                   1162:     case OPC_BLEZ:
                   1163:     case OPC_BLEZL:
                   1164:     case OPC_BLTZ:
                   1165:     case OPC_BLTZAL:
                   1166:     case OPC_BLTZALL:
                   1167:     case OPC_BLTZL:
                   1168:         /* Compare to zero */
                   1169:         if (rs != 0) {
                   1170:             gen_op_load_gpr_T0(rs);
                   1171:             bcond = 1;
                   1172:         }
                   1173:         btarget = ctx->pc + 4 + offset;
                   1174:         break;
                   1175:     case OPC_J:
                   1176:     case OPC_JAL:
                   1177:         /* Jump to immediate */
                   1178:         btarget = ((ctx->pc + 4) & 0xF0000000) | offset;
                   1179:         break;
                   1180:     case OPC_JR:
                   1181:     case OPC_JALR:
                   1182:         /* Jump to register */
                   1183:         if (offset != 0) {
                   1184:             /* Only hint = 0 is valid */
                   1185:             generate_exception(ctx, EXCP_RI);
                   1186:             return;
                   1187:         }
                   1188:         GEN_LOAD_REG_TN(T2, rs);
                   1189:         break;
                   1190:     default:
                   1191:         MIPS_INVAL("branch/jump");
                   1192:         generate_exception(ctx, EXCP_RI);
                   1193:         return;
                   1194:     }
                   1195:     if (bcond == 0) {
                   1196:         /* No condition to be computed */
                   1197:         switch (opc) {
                   1198:         case OPC_BEQ:     /* rx == rx        */
                   1199:         case OPC_BEQL:    /* rx == rx likely */
                   1200:         case OPC_BGEZ:    /* 0 >= 0          */
                   1201:         case OPC_BGEZL:   /* 0 >= 0 likely   */
                   1202:         case OPC_BLEZ:    /* 0 <= 0          */
                   1203:         case OPC_BLEZL:   /* 0 <= 0 likely   */
                   1204:             /* Always take */
1.1.1.2   root     1205:             ctx->hflags |= MIPS_HFLAG_B;
1.1       root     1206:             MIPS_DEBUG("balways");
                   1207:             break;
                   1208:         case OPC_BGEZAL:  /* 0 >= 0          */
                   1209:         case OPC_BGEZALL: /* 0 >= 0 likely   */
                   1210:             /* Always take and link */
                   1211:             blink = 31;
1.1.1.2   root     1212:             ctx->hflags |= MIPS_HFLAG_B;
1.1       root     1213:             MIPS_DEBUG("balways and link");
                   1214:             break;
                   1215:         case OPC_BNE:     /* rx != rx        */
                   1216:         case OPC_BGTZ:    /* 0 > 0           */
                   1217:         case OPC_BLTZ:    /* 0 < 0           */
                   1218:             /* Treated as NOP */
                   1219:             MIPS_DEBUG("bnever (NOP)");
                   1220:             return;
1.1.1.2   root     1221:         case OPC_BLTZAL:  /* 0 < 0           */
                   1222:             gen_op_set_T0(ctx->pc + 8);
                   1223:             gen_op_store_T0_gpr(31);
                   1224:             return;
                   1225:         case OPC_BLTZALL: /* 0 < 0 likely */
                   1226:             gen_op_set_T0(ctx->pc + 8);
                   1227:             gen_op_store_T0_gpr(31);
                   1228:             gen_goto_tb(ctx, 0, ctx->pc + 4);
                   1229:             return;
1.1       root     1230:         case OPC_BNEL:    /* rx != rx likely */
                   1231:         case OPC_BGTZL:   /* 0 > 0 likely */
                   1232:         case OPC_BLTZL:   /* 0 < 0 likely */
                   1233:             /* Skip the instruction in the delay slot */
                   1234:             MIPS_DEBUG("bnever and skip");
1.1.1.2   root     1235:             gen_goto_tb(ctx, 0, ctx->pc + 4);
1.1       root     1236:             return;
                   1237:         case OPC_J:
1.1.1.2   root     1238:             ctx->hflags |= MIPS_HFLAG_B;
1.1       root     1239:             MIPS_DEBUG("j %08x", btarget);
                   1240:             break;
                   1241:         case OPC_JAL:
                   1242:             blink = 31;
1.1.1.2   root     1243:             ctx->hflags |= MIPS_HFLAG_B;
1.1       root     1244:             MIPS_DEBUG("jal %08x", btarget);
                   1245:             break;
                   1246:         case OPC_JR:
1.1.1.2   root     1247:             ctx->hflags |= MIPS_HFLAG_BR;
1.1       root     1248:             MIPS_DEBUG("jr %s", regnames[rs]);
                   1249:             break;
                   1250:         case OPC_JALR:
                   1251:             blink = rt;
1.1.1.2   root     1252:             ctx->hflags |= MIPS_HFLAG_BR;
1.1       root     1253:             MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
                   1254:             break;
                   1255:         default:
                   1256:             MIPS_INVAL("branch/jump");
                   1257:             generate_exception(ctx, EXCP_RI);
                   1258:             return;
                   1259:         }
                   1260:     } else {
                   1261:         switch (opc) {
                   1262:         case OPC_BEQ:
                   1263:             gen_op_eq();
                   1264:             MIPS_DEBUG("beq %s, %s, %08x",
                   1265:                        regnames[rs], regnames[rt], btarget);
                   1266:             goto not_likely;
                   1267:         case OPC_BEQL:
                   1268:             gen_op_eq();
                   1269:             MIPS_DEBUG("beql %s, %s, %08x",
                   1270:                        regnames[rs], regnames[rt], btarget);
                   1271:             goto likely;
                   1272:         case OPC_BNE:
                   1273:             gen_op_ne();
                   1274:             MIPS_DEBUG("bne %s, %s, %08x",
                   1275:                        regnames[rs], regnames[rt], btarget);
                   1276:             goto not_likely;
                   1277:         case OPC_BNEL:
                   1278:             gen_op_ne();
                   1279:             MIPS_DEBUG("bnel %s, %s, %08x",
                   1280:                        regnames[rs], regnames[rt], btarget);
                   1281:             goto likely;
                   1282:         case OPC_BGEZ:
                   1283:             gen_op_gez();
                   1284:             MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
                   1285:             goto not_likely;
                   1286:         case OPC_BGEZL:
                   1287:             gen_op_gez();
                   1288:             MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
                   1289:             goto likely;
                   1290:         case OPC_BGEZAL:
                   1291:             gen_op_gez();
                   1292:             MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
                   1293:             blink = 31;
                   1294:             goto not_likely;
                   1295:         case OPC_BGEZALL:
                   1296:             gen_op_gez();
                   1297:             blink = 31;
                   1298:             MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
                   1299:             goto likely;
                   1300:         case OPC_BGTZ:
                   1301:             gen_op_gtz();
                   1302:             MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
                   1303:             goto not_likely;
                   1304:         case OPC_BGTZL:
                   1305:             gen_op_gtz();
                   1306:             MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
                   1307:             goto likely;
                   1308:         case OPC_BLEZ:
                   1309:             gen_op_lez();
                   1310:             MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
                   1311:             goto not_likely;
                   1312:         case OPC_BLEZL:
                   1313:             gen_op_lez();
                   1314:             MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
                   1315:             goto likely;
                   1316:         case OPC_BLTZ:
                   1317:             gen_op_ltz();
                   1318:             MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
                   1319:             goto not_likely;
                   1320:         case OPC_BLTZL:
                   1321:             gen_op_ltz();
                   1322:             MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
                   1323:             goto likely;
                   1324:         case OPC_BLTZAL:
                   1325:             gen_op_ltz();
                   1326:             blink = 31;
                   1327:             MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
                   1328:         not_likely:
1.1.1.2   root     1329:             ctx->hflags |= MIPS_HFLAG_BC;
1.1       root     1330:             break;
                   1331:         case OPC_BLTZALL:
                   1332:             gen_op_ltz();
                   1333:             blink = 31;
                   1334:             MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
                   1335:         likely:
1.1.1.2   root     1336:             ctx->hflags |= MIPS_HFLAG_BL;
1.1       root     1337:             break;
                   1338:         }
                   1339:         gen_op_set_bcond();
                   1340:     }
                   1341:     MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
                   1342:                blink, ctx->hflags, btarget);
                   1343:     ctx->btarget = btarget;
                   1344:     if (blink > 0) {
                   1345:         gen_op_set_T0(ctx->pc + 8);
                   1346:         gen_op_store_T0_gpr(blink);
                   1347:     }
                   1348:     return;
                   1349: }
                   1350: 
                   1351: /* CP0 (MMU and control) */
                   1352: static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
                   1353: {
                   1354:     const unsigned char *opn = "unk";
                   1355: 
                   1356:     if (!(ctx->CP0_Status & (1 << CP0St_CU0)) &&
1.1.1.3   root     1357:         (ctx->hflags & MIPS_HFLAG_UM) &&
1.1       root     1358:         !(ctx->hflags & MIPS_HFLAG_ERL) &&
                   1359:         !(ctx->hflags & MIPS_HFLAG_EXL)) {
                   1360:         if (loglevel & CPU_LOG_TB_IN_ASM) {
                   1361:             fprintf(logfile, "CP0 is not usable\n");
                   1362:         }
1.1.1.2   root     1363:         generate_exception_err (ctx, EXCP_CpU, 0);
1.1       root     1364:         return;
                   1365:     }
1.1.1.4 ! root     1366: 
1.1       root     1367:     switch (opc) {
                   1368:     case OPC_MFC0:
                   1369:         if (rt == 0) {
                   1370:             /* Treat as NOP */
                   1371:             return;
                   1372:         }
                   1373:         gen_op_mfc0(rd, ctx->opcode & 0x7);
                   1374:         gen_op_store_T0_gpr(rt);
                   1375:         opn = "mfc0";
                   1376:         break;
                   1377:     case OPC_MTC0:
                   1378:         /* If we get an exception, we want to restart at next instruction */
                   1379:         ctx->pc += 4;
                   1380:         save_cpu_state(ctx, 1);
                   1381:         ctx->pc -= 4;
                   1382:         GEN_LOAD_REG_TN(T0, rt);
                   1383:         gen_op_mtc0(rd, ctx->opcode & 0x7);
                   1384:         /* Stop translation as we may have switched the execution mode */
                   1385:         ctx->bstate = BS_STOP;
                   1386:         opn = "mtc0";
                   1387:         break;
                   1388: #if defined(MIPS_USES_R4K_TLB)
                   1389:     case OPC_TLBWI:
                   1390:         gen_op_tlbwi();
                   1391:         opn = "tlbwi";
                   1392:         break;
                   1393:     case OPC_TLBWR:
                   1394:         gen_op_tlbwr();
                   1395:         opn = "tlbwr";
                   1396:         break;
                   1397:     case OPC_TLBP:
                   1398:         gen_op_tlbp();
                   1399:         opn = "tlbp";
                   1400:         break;
                   1401:     case OPC_TLBR:
                   1402:         gen_op_tlbr();
                   1403:         opn = "tlbr";
                   1404:         break;
                   1405: #endif
                   1406:     case OPC_ERET:
                   1407:         opn = "eret";
                   1408:         save_cpu_state(ctx, 0);
                   1409:         gen_op_eret();
                   1410:         ctx->bstate = BS_EXCP;
                   1411:         break;
                   1412:     case OPC_DERET:
                   1413:         opn = "deret";
                   1414:         if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                   1415:             generate_exception(ctx, EXCP_RI);
                   1416:         } else {
                   1417:             save_cpu_state(ctx, 0);
                   1418:             gen_op_deret();
                   1419:             ctx->bstate = BS_EXCP;
                   1420:         }
                   1421:         break;
1.1.1.2   root     1422:     case OPC_WAIT:
                   1423:         opn = "wait";
                   1424:         /* If we get an exception, we want to restart at next instruction */
                   1425:         ctx->pc += 4;
                   1426:         save_cpu_state(ctx, 1);
                   1427:         ctx->pc -= 4;
                   1428:         gen_op_wait();
                   1429:         ctx->bstate = BS_EXCP;
                   1430:         break;
1.1       root     1431:     default:
                   1432:         if (loglevel & CPU_LOG_TB_IN_ASM) {
                   1433:             fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
                   1434:                     ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
                   1435:                     ((ctx->opcode >> 16) & 0x1F));
                   1436:         }
                   1437:         generate_exception(ctx, EXCP_RI);
                   1438:         return;
                   1439:     }
                   1440:     MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
                   1441: }
                   1442: 
1.1.1.4 ! root     1443: #ifdef MIPS_USES_FPU
        !          1444: /* CP1 Branches (before delay slot) */
        !          1445: static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond,
        !          1446:                                  int32_t offset)
        !          1447: {
        !          1448:     target_ulong btarget;
        !          1449: 
        !          1450:     btarget = ctx->pc + 4 + offset;
        !          1451: 
        !          1452:     switch (cond) {
        !          1453:     case 0x0000: /* bc1f */
        !          1454:         gen_op_bc1f();
        !          1455:         MIPS_DEBUG("bc1f %08x", btarget);
        !          1456:         goto not_likely;
        !          1457:     case 0x0002: /* bc1fl */
        !          1458:         gen_op_bc1f();
        !          1459:         MIPS_DEBUG("bc1fl %08x", btarget);
        !          1460:         goto likely;
        !          1461:     case 0x0001: /* bc1t */
        !          1462:         gen_op_bc1t();
        !          1463:         MIPS_DEBUG("bc1t %08x", btarget);
        !          1464:     not_likely:
        !          1465:         ctx->hflags |= MIPS_HFLAG_BC;
        !          1466:         break;
        !          1467:     case 0x0003: /* bc1tl */
        !          1468:         gen_op_bc1t();
        !          1469:         MIPS_DEBUG("bc1tl %08x", btarget);
        !          1470:     likely:
        !          1471:         ctx->hflags |= MIPS_HFLAG_BL;
        !          1472:         break;
        !          1473:     default:    
        !          1474:         MIPS_INVAL("cp1 branch/jump");
        !          1475:         generate_exception(ctx, EXCP_RI);
        !          1476:         return;
        !          1477:     }
        !          1478:     gen_op_set_bcond();
        !          1479: 
        !          1480:     MIPS_DEBUG("enter ds: cond %02x target %08x",
        !          1481:                ctx->hflags, btarget);
        !          1482:     ctx->btarget = btarget;
        !          1483: 
        !          1484:     return;
        !          1485: }
        !          1486: 
1.1       root     1487: /* Coprocessor 1 (FPU) */
1.1.1.4 ! root     1488: static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs)
        !          1489: {
        !          1490:     const unsigned char *opn = "unk";
        !          1491: 
        !          1492:     switch (opc) {
        !          1493:     case OPC_MFC1:
        !          1494:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1495:         gen_op_mfc1();
        !          1496:         GEN_STORE_TN_REG(rt, T0);
        !          1497:         opn = "mfc1";
        !          1498:         break;
        !          1499:     case OPC_MTC1:
        !          1500:         GEN_LOAD_REG_TN(T0, rt);
        !          1501:         gen_op_mtc1();
        !          1502:         GEN_STORE_FTN_FREG(fs, WT0);
        !          1503:         opn = "mtc1";
        !          1504:         break;
        !          1505:     case OPC_CFC1:
        !          1506:         if (fs != 0 && fs != 31) {
        !          1507:             MIPS_INVAL("cfc1 freg");
        !          1508:             generate_exception(ctx, EXCP_RI);
        !          1509:             return;
        !          1510:         }
        !          1511:         GEN_LOAD_IMM_TN(T1, fs);
        !          1512:         gen_op_cfc1();
        !          1513:         GEN_STORE_TN_REG(rt, T0);
        !          1514:         opn = "cfc1";
        !          1515:         break;
        !          1516:     case OPC_CTC1:
        !          1517:         if (fs != 0 && fs != 31) {
        !          1518:             MIPS_INVAL("ctc1 freg");
        !          1519:             generate_exception(ctx, EXCP_RI);
        !          1520:             return;
        !          1521:         }
        !          1522:         GEN_LOAD_IMM_TN(T1, fs);
        !          1523:         GEN_LOAD_REG_TN(T0, rt);
        !          1524:         gen_op_ctc1();
        !          1525:         opn = "ctc1";
        !          1526:         break;
        !          1527:     default:
        !          1528:         if (loglevel & CPU_LOG_TB_IN_ASM) {
        !          1529:             fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
        !          1530:                     ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
        !          1531:                     ((ctx->opcode >> 16) & 0x1F));
        !          1532:         }
        !          1533:         generate_exception(ctx, EXCP_RI);
        !          1534:         return;
        !          1535:     }
        !          1536:     MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
        !          1537: }
        !          1538: 
        !          1539: /* verify if floating point register is valid; an operation is not defined
        !          1540:  * if bit 0 of any register specification is set and the FR bit in the
        !          1541:  * Status register equals zero, since the register numbers specify an
        !          1542:  * even-odd pair of adjacent coprocessor general registers. When the FR bit
        !          1543:  * in the Status register equals one, both even and odd register numbers
        !          1544:  * are valid.
        !          1545:  * 
        !          1546:  * Multiple float registers can be checked by calling
        !          1547:  * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
        !          1548:  */
        !          1549: #define CHECK_FR(ctx, freg) do { \
        !          1550:         if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
        !          1551:             generate_exception(ctx, EXCP_RI); \
        !          1552:             return; \
        !          1553:         } \
        !          1554:     } while(0)
        !          1555: 
        !          1556: #define FOP(func, fmt) (((fmt) << 21) | (func))
        !          1557: 
        !          1558: static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int func)
        !          1559: {
        !          1560:     const unsigned char *opn = "unk";
        !          1561:     const char *condnames[] = {
        !          1562:             "c.f",
        !          1563:             "c.un",
        !          1564:             "c.eq",
        !          1565:             "c.ueq",
        !          1566:             "c.olt",
        !          1567:             "c.ult",
        !          1568:             "c.ole",
        !          1569:             "c.ule",
        !          1570:             "c.sf",
        !          1571:             "c.ngle",
        !          1572:             "c.seq",
        !          1573:             "c.ngl",
        !          1574:             "c.lt",
        !          1575:             "c.nge",
        !          1576:             "c.le",
        !          1577:             "c.ngt",
        !          1578:     };
        !          1579:     int binary = 0;
        !          1580:     
        !          1581:     switch (ctx->opcode & FOP(0x3f, 0x1f)) {
        !          1582:     case FOP(0, 17):
        !          1583:         CHECK_FR(ctx, fs | ft | fd);
        !          1584:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1585:         GEN_LOAD_FREG_FTN(DT1, ft);
        !          1586:         gen_op_float_add_d();
        !          1587:         GEN_STORE_FTN_FREG(fd, DT2);
        !          1588:         opn = "add.d";
        !          1589:         binary = 1;
        !          1590:         break;
        !          1591:     case FOP(1, 17):
        !          1592:         CHECK_FR(ctx, fs | ft | fd);
        !          1593:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1594:         GEN_LOAD_FREG_FTN(DT1, ft);
        !          1595:         gen_op_float_sub_d();
        !          1596:         GEN_STORE_FTN_FREG(fd, DT2);
        !          1597:         opn = "sub.d";
        !          1598:         binary = 1;
        !          1599:         break;
        !          1600:     case FOP(2, 17):
        !          1601:         CHECK_FR(ctx, fs | ft | fd);
        !          1602:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1603:         GEN_LOAD_FREG_FTN(DT1, ft);
        !          1604:         gen_op_float_mul_d();
        !          1605:         GEN_STORE_FTN_FREG(fd, DT2);
        !          1606:         opn = "mul.d";
        !          1607:         binary = 1;
        !          1608:         break;
        !          1609:     case FOP(3, 17):
        !          1610:         CHECK_FR(ctx, fs | ft | fd);
        !          1611:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1612:         GEN_LOAD_FREG_FTN(DT1, ft);
        !          1613:         gen_op_float_div_d();
        !          1614:         GEN_STORE_FTN_FREG(fd, DT2);
        !          1615:         opn = "div.d";
        !          1616:         binary = 1;
        !          1617:         break;
        !          1618:     case FOP(4, 17):
        !          1619:         CHECK_FR(ctx, fs | fd);
        !          1620:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1621:         gen_op_float_sqrt_d();
        !          1622:         GEN_STORE_FTN_FREG(fd, DT2);
        !          1623:         opn = "sqrt.d";
        !          1624:         break;
        !          1625:     case FOP(5, 17):
        !          1626:         CHECK_FR(ctx, fs | fd);
        !          1627:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1628:         gen_op_float_abs_d();
        !          1629:         GEN_STORE_FTN_FREG(fd, DT2);
        !          1630:         opn = "abs.d";
        !          1631:         break;
        !          1632:     case FOP(6, 17):
        !          1633:         CHECK_FR(ctx, fs | fd);
        !          1634:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1635:         gen_op_float_mov_d();
        !          1636:         GEN_STORE_FTN_FREG(fd, DT2);
        !          1637:         opn = "mov.d";
        !          1638:         break;
        !          1639:     case FOP(7, 17):
        !          1640:         CHECK_FR(ctx, fs | fd);
        !          1641:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1642:         gen_op_float_chs_d();
        !          1643:         GEN_STORE_FTN_FREG(fd, DT2);
        !          1644:         opn = "neg.d";
        !          1645:         break;
        !          1646:     /*  8 - round.l */
        !          1647:     /*  9 - trunc.l */
        !          1648:     /* 10 - ceil.l  */
        !          1649:     /* 11 - floor.l */
        !          1650:     case FOP(12, 17):
        !          1651:         CHECK_FR(ctx, fs | fd);
        !          1652:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1653:         gen_op_float_roundw_d();
        !          1654:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1655:         opn = "round.w.d";
        !          1656:         break;
        !          1657:     case FOP(13, 17):
        !          1658:         CHECK_FR(ctx, fs | fd);
        !          1659:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1660:         gen_op_float_truncw_d();
        !          1661:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1662:         opn = "trunc.w.d";
        !          1663:         break;
        !          1664:     case FOP(14, 17):
        !          1665:         CHECK_FR(ctx, fs | fd);
        !          1666:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1667:         gen_op_float_ceilw_d();
        !          1668:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1669:         opn = "ceil.w.d";
        !          1670:         break;
        !          1671:     case FOP(15, 17):
        !          1672:         CHECK_FR(ctx, fs | fd);
        !          1673:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1674:         gen_op_float_floorw_d();
        !          1675:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1676:         opn = "ceil.w.d";
        !          1677:         break;
        !          1678:     case FOP(33, 20): /* cvt.d.w */
        !          1679:         CHECK_FR(ctx, fs | fd);
        !          1680:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1681:         gen_op_float_cvtd_w();
        !          1682:         GEN_STORE_FTN_FREG(fd, DT2);
        !          1683:         opn = "cvt.d.w";
        !          1684:         break;
        !          1685:     case FOP(48, 17):
        !          1686:     case FOP(49, 17):
        !          1687:     case FOP(50, 17):
        !          1688:     case FOP(51, 17):
        !          1689:     case FOP(52, 17):
        !          1690:     case FOP(53, 17):
        !          1691:     case FOP(54, 17):
        !          1692:     case FOP(55, 17):
        !          1693:     case FOP(56, 17):
        !          1694:     case FOP(57, 17):
        !          1695:     case FOP(58, 17):
        !          1696:     case FOP(59, 17):
        !          1697:     case FOP(60, 17):
        !          1698:     case FOP(61, 17):
        !          1699:     case FOP(62, 17):
        !          1700:     case FOP(63, 17):
        !          1701:         CHECK_FR(ctx, fs | ft);
        !          1702:         GEN_LOAD_FREG_FTN(DT0, fs);
        !          1703:         GEN_LOAD_FREG_FTN(DT1, ft);
        !          1704:         gen_cmp_d(func-48);
        !          1705:         opn = condnames[func-48];
        !          1706:         break;
        !          1707:     case FOP(0, 16):
        !          1708:         CHECK_FR(ctx, fs | ft | fd);
        !          1709:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1710:         GEN_LOAD_FREG_FTN(WT1, ft);
        !          1711:         gen_op_float_add_s();
        !          1712:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1713:         opn = "add.s";
        !          1714:         binary = 1;
        !          1715:         break;
        !          1716:     case FOP(1, 16):
        !          1717:         CHECK_FR(ctx, fs | ft | fd);
        !          1718:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1719:         GEN_LOAD_FREG_FTN(WT1, ft);
        !          1720:         gen_op_float_sub_s();
        !          1721:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1722:         opn = "sub.s";
        !          1723:         binary = 1;
        !          1724:         break;
        !          1725:     case FOP(2, 16):
        !          1726:         CHECK_FR(ctx, fs | ft | fd);
        !          1727:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1728:         GEN_LOAD_FREG_FTN(WT1, ft);
        !          1729:         gen_op_float_mul_s();
        !          1730:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1731:         opn = "mul.s";
        !          1732:         binary = 1;
        !          1733:         break;
        !          1734:     case FOP(3, 16):
        !          1735:         CHECK_FR(ctx, fs | ft | fd);
        !          1736:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1737:         GEN_LOAD_FREG_FTN(WT1, ft);
        !          1738:         gen_op_float_div_s();
        !          1739:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1740:         opn = "div.s";
        !          1741:         binary = 1;
        !          1742:         break;
        !          1743:     case FOP(4, 16):
        !          1744:         CHECK_FR(ctx, fs | fd);
        !          1745:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1746:         gen_op_float_sqrt_s();
        !          1747:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1748:         opn = "sqrt.s";
        !          1749:         break;
        !          1750:     case FOP(5, 16):
        !          1751:         CHECK_FR(ctx, fs | fd);
        !          1752:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1753:         gen_op_float_abs_s();
        !          1754:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1755:         opn = "abs.s";
        !          1756:         break;
        !          1757:     case FOP(6, 16):
        !          1758:         CHECK_FR(ctx, fs | fd);
        !          1759:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1760:         gen_op_float_mov_s();
        !          1761:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1762:         opn = "mov.s";
        !          1763:         break;
        !          1764:     case FOP(7, 16):
        !          1765:         CHECK_FR(ctx, fs | fd);
        !          1766:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1767:         gen_op_float_chs_s();
        !          1768:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1769:         opn = "neg.s";
        !          1770:         break;
        !          1771:     case FOP(12, 16):
        !          1772:         CHECK_FR(ctx, fs | fd);
        !          1773:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1774:         gen_op_float_roundw_s();
        !          1775:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1776:         opn = "round.w.s";
        !          1777:         break;
        !          1778:     case FOP(13, 16):
        !          1779:         CHECK_FR(ctx, fs | fd);
        !          1780:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1781:         gen_op_float_truncw_s();
        !          1782:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1783:         opn = "trunc.w.s";
        !          1784:         break;
        !          1785:     case FOP(32, 20): /* cvt.s.w */
        !          1786:         CHECK_FR(ctx, fs | fd);
        !          1787:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1788:         gen_op_float_cvts_w();
        !          1789:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1790:         opn = "cvt.s.w";
        !          1791:         break;
        !          1792:     case FOP(36, 16): /* cvt.w.s */
        !          1793:         CHECK_FR(ctx, fs | fd);
        !          1794:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1795:         gen_op_float_cvtw_s();
        !          1796:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1797:         opn = "cvt.w.s";
        !          1798:         break;
        !          1799:     case FOP(36, 17): /* cvt.w.d */
        !          1800:         CHECK_FR(ctx, fs | fd);
        !          1801:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1802:         gen_op_float_cvtw_d();
        !          1803:         GEN_STORE_FTN_FREG(fd, WT2);
        !          1804:         opn = "cvt.w.d";
        !          1805:         break;
        !          1806:     case FOP(48, 16):
        !          1807:     case FOP(49, 16):
        !          1808:     case FOP(50, 16):
        !          1809:     case FOP(51, 16):
        !          1810:     case FOP(52, 16):
        !          1811:     case FOP(53, 16):
        !          1812:     case FOP(54, 16):
        !          1813:     case FOP(55, 16):
        !          1814:     case FOP(56, 16):
        !          1815:     case FOP(57, 16):
        !          1816:     case FOP(58, 16):
        !          1817:     case FOP(59, 16):
        !          1818:     case FOP(60, 16):
        !          1819:     case FOP(61, 16):
        !          1820:     case FOP(62, 16):
        !          1821:     case FOP(63, 16):
        !          1822:         CHECK_FR(ctx, fs | ft);
        !          1823:         GEN_LOAD_FREG_FTN(WT0, fs);
        !          1824:         GEN_LOAD_FREG_FTN(WT1, ft);
        !          1825:         gen_cmp_s(func-48);
        !          1826:         opn = condnames[func-48];
        !          1827:         break;
        !          1828:     default:    
        !          1829:         if (loglevel & CPU_LOG_TB_IN_ASM) {
        !          1830:             fprintf(logfile, "Invalid arith function: %08x %03x %03x %03x\n",
        !          1831:                     ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
        !          1832:                     ((ctx->opcode >> 16) & 0x1F));
        !          1833:         }
        !          1834:         generate_exception(ctx, EXCP_RI);
        !          1835:         return;
        !          1836:     }
        !          1837:     if (binary)
        !          1838:         MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
        !          1839:     else
        !          1840:         MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
        !          1841: }
        !          1842: #endif
1.1       root     1843: 
                   1844: /* ISA extensions */
                   1845: /* MIPS16 extension to MIPS32 */
                   1846: /* SmartMIPS extension to MIPS32 */
                   1847: 
                   1848: #ifdef TARGET_MIPS64
                   1849: static void gen_arith64 (DisasContext *ctx, uint16_t opc)
                   1850: {
                   1851:     if (func == 0x02 && rd == 0) {
                   1852:         /* NOP */
                   1853:         return;
                   1854:     }
                   1855:     if (rs == 0 || rt == 0) {
                   1856:         gen_op_reset_T0();
                   1857:         gen_op_save64();
                   1858:     } else {
                   1859:         gen_op_load_gpr_T0(rs);
                   1860:         gen_op_load_gpr_T1(rt);
                   1861:         gen_op_save64();
                   1862:         if (func & 0x01)
                   1863:             gen_op_mul64u();
                   1864:         else
                   1865:             gen_op_mul64s();
                   1866:     }
                   1867:     if (func & 0x02)
                   1868:         gen_op_add64();
                   1869:     else
                   1870:         gen_op_sub64();
                   1871: }
                   1872: 
                   1873: /* Coprocessor 3 (FPU) */
                   1874: 
                   1875: /* MDMX extension to MIPS64 */
                   1876: /* MIPS-3D extension to MIPS64 */
                   1877: 
                   1878: #endif
                   1879: 
1.1.1.2   root     1880: static void gen_blikely(DisasContext *ctx)
                   1881: {
                   1882:     int l1;
                   1883:     l1 = gen_new_label();
                   1884:     gen_op_jnz_T2(l1);
                   1885:     gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
                   1886:     gen_goto_tb(ctx, 1, ctx->pc + 4);
                   1887:     gen_set_label(l1);
                   1888: }
                   1889: 
1.1       root     1890: static void decode_opc (DisasContext *ctx)
                   1891: {
                   1892:     int32_t offset;
                   1893:     int rs, rt, rd, sa;
                   1894:     uint16_t op, op1;
                   1895:     int16_t imm;
                   1896: 
1.1.1.4 ! root     1897:     /* make sure instructions are on a word boundary */
        !          1898:     if (ctx->pc & 0x3) {
        !          1899:         generate_exception(ctx, EXCP_AdEL);
        !          1900:         return;
        !          1901:     }
        !          1902: 
1.1.1.2   root     1903:     if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
1.1       root     1904:         /* Handle blikely not taken case */
                   1905:         MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
1.1.1.2   root     1906:         gen_blikely(ctx);
1.1       root     1907:     }
                   1908:     op = ctx->opcode >> 26;
                   1909:     rs = ((ctx->opcode >> 21) & 0x1F);
                   1910:     rt = ((ctx->opcode >> 16) & 0x1F);
                   1911:     rd = ((ctx->opcode >> 11) & 0x1F);
                   1912:     sa = ((ctx->opcode >> 6) & 0x1F);
                   1913:     imm = (int16_t)ctx->opcode;
                   1914:     switch (op) {
                   1915:     case 0x00:          /* Special opcode */
                   1916:         op1 = ctx->opcode & 0x3F;
                   1917:         switch (op1) {
                   1918:         case 0x00:          /* Arithmetic with immediate */
                   1919:         case 0x02 ... 0x03:
                   1920:             gen_arith_imm(ctx, op1 | EXT_SPECIAL, rd, rt, sa);
                   1921:             break;
                   1922:         case 0x04:          /* Arithmetic */
                   1923:         case 0x06 ... 0x07:
                   1924:         case 0x0A ... 0x0B:
                   1925:         case 0x20 ... 0x27:
                   1926:         case 0x2A ... 0x2B:
                   1927:             gen_arith(ctx, op1 | EXT_SPECIAL, rd, rs, rt);
                   1928:             break;
                   1929:         case 0x18 ... 0x1B: /* MULT / DIV */
                   1930:             gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt);
                   1931:             break;
                   1932:         case 0x08 ... 0x09: /* Jumps */
                   1933:             gen_compute_branch(ctx, op1 | EXT_SPECIAL, rs, rd, sa);
                   1934:             return;
                   1935:         case 0x30 ... 0x34: /* Traps */
                   1936:         case 0x36:
                   1937:             gen_trap(ctx, op1 | EXT_SPECIAL, rs, rt, -1);
                   1938:             break;
                   1939:         case 0x10:          /* Move from HI/LO */
                   1940:         case 0x12:
                   1941:             gen_HILO(ctx, op1 | EXT_SPECIAL, rd);
                   1942:             break;
                   1943:         case 0x11:
                   1944:         case 0x13:          /* Move to HI/LO */
                   1945:             gen_HILO(ctx, op1 | EXT_SPECIAL, rs);
                   1946:             break;
                   1947:         case 0x0C:          /* SYSCALL */
                   1948:             generate_exception(ctx, EXCP_SYSCALL);
                   1949:             break;
                   1950:         case 0x0D:          /* BREAK */
                   1951:             generate_exception(ctx, EXCP_BREAK);
                   1952:             break;
                   1953:         case 0x0F:          /* SYNC */
                   1954:             /* Treat as a noop */
                   1955:             break;
                   1956:         case 0x05:          /* Pmon entry point */
                   1957:             gen_op_pmon((ctx->opcode >> 6) & 0x1F);
                   1958:             break;
1.1.1.2   root     1959: 
1.1       root     1960:         case 0x01:          /* MOVCI */
1.1.1.2   root     1961: #if defined (MIPS_HAS_MOVCI)
                   1962:             /* XXX */
                   1963: #else
                   1964:             /* Not implemented */
                   1965:             generate_exception_err (ctx, EXCP_CpU, 1);
1.1       root     1966: #endif
1.1.1.2   root     1967:             break;
                   1968: 
1.1       root     1969: #if defined (TARGET_MIPS64)
                   1970:         case 0x14: /* MIPS64 specific opcodes */
                   1971:         case 0x16:
                   1972:         case 0x17:
                   1973:         case 0x1C ... 0x1F:
                   1974:         case 0x2C ... 0x2F:
                   1975:         case 0x37:
                   1976:         case 0x39 ... 0x3B:
                   1977:         case 0x3E ... 0x3F:
                   1978: #endif
                   1979:         default:            /* Invalid */
                   1980:             MIPS_INVAL("special");
                   1981:             generate_exception(ctx, EXCP_RI);
                   1982:             break;
                   1983:         }
                   1984:         break;
                   1985:     case 0x1C:          /* Special2 opcode */
                   1986:         op1 = ctx->opcode & 0x3F;
                   1987:         switch (op1) {
                   1988: #if defined (MIPS_USES_R4K_EXT)
                   1989:         /* Those instructions are not part of MIPS32 core */
                   1990:         case 0x00 ... 0x01: /* Multiply and add/sub */
                   1991:         case 0x04 ... 0x05:
                   1992:             gen_muldiv(ctx, op1 | EXT_SPECIAL2, rs, rt);
                   1993:             break;
                   1994:         case 0x02:          /* MUL */
                   1995:             gen_arith(ctx, op1 | EXT_SPECIAL2, rd, rs, rt);
                   1996:             break;
                   1997:         case 0x20 ... 0x21: /* CLO / CLZ */
                   1998:             gen_cl(ctx, op1 | EXT_SPECIAL2, rd, rs);
                   1999:             break;
                   2000: #endif
                   2001:         case 0x3F:          /* SDBBP */
                   2002:             /* XXX: not clear which exception should be raised
                   2003:              *      when in debug mode...
                   2004:              */
                   2005:             if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                   2006:                 generate_exception(ctx, EXCP_DBp);
                   2007:             } else {
                   2008:                 generate_exception(ctx, EXCP_DBp);
                   2009:             }
                   2010:             /* Treat as a noop */
                   2011:             break;
                   2012:         default:            /* Invalid */
                   2013:             MIPS_INVAL("special2");
                   2014:             generate_exception(ctx, EXCP_RI);
                   2015:             break;
                   2016:         }
                   2017:         break;
                   2018:     case 0x01:          /* B REGIMM opcode */
                   2019:         op1 = ((ctx->opcode >> 16) & 0x1F);
                   2020:         switch (op1) {
                   2021:         case 0x00 ... 0x03: /* REGIMM branches */
                   2022:         case 0x10 ... 0x13:
                   2023:             gen_compute_branch(ctx, op1 | EXT_REGIMM, rs, -1, imm << 2);
                   2024:             return;
                   2025:         case 0x08 ... 0x0C: /* Traps */
                   2026:         case 0x0E:
                   2027:             gen_trap(ctx, op1 | EXT_REGIMM, rs, -1, imm);
                   2028:             break;
                   2029:         default:            /* Invalid */
                   2030:             MIPS_INVAL("REGIMM");
                   2031:             generate_exception(ctx, EXCP_RI);
                   2032:             break;
                   2033:         }
                   2034:         break;
                   2035:     case 0x10:          /* CP0 opcode */
                   2036:         op1 = ((ctx->opcode >> 21) & 0x1F);
                   2037:         switch (op1) {
                   2038:         case 0x00:
                   2039:         case 0x04:
                   2040:             gen_cp0(ctx, op1 | EXT_CP0, rt, rd);
                   2041:             break;
                   2042:         default:
1.1.1.2   root     2043:             gen_cp0(ctx, (ctx->opcode & 0x3F) | EXT_CP0, rt, rd);
1.1       root     2044:             break;
                   2045:         }
                   2046:         break;
                   2047:     case 0x08 ... 0x0F: /* Arithmetic with immediate opcode */
                   2048:         gen_arith_imm(ctx, op, rt, rs, imm);
                   2049:         break;
                   2050:     case 0x02 ... 0x03: /* Jump */
                   2051:         offset = (int32_t)(ctx->opcode & 0x03FFFFFF) << 2;
                   2052:         gen_compute_branch(ctx, op, rs, rt, offset);
                   2053:         return;
                   2054:     case 0x04 ... 0x07: /* Branch */
                   2055:     case 0x14 ... 0x17:
                   2056:         gen_compute_branch(ctx, op, rs, rt, imm << 2);
                   2057:         return;
1.1.1.4 ! root     2058:     case 0x20 ... 0x2E: /* Load and stores */
1.1       root     2059:     case 0x30:
                   2060:     case 0x38:
                   2061:         gen_ldst(ctx, op, rt, rs, imm);
                   2062:         break;
                   2063:     case 0x2F:          /* Cache operation */
                   2064:         /* Treat as a noop */
                   2065:         break;
                   2066:     case 0x33:          /* Prefetch */
                   2067:         /* Treat as a noop */
                   2068:         break;
                   2069:     case 0x3F: /* HACK */
                   2070:         break;
1.1.1.2   root     2071: 
                   2072:     /* Floating point.  */
                   2073:     case 0x31: /* LWC1 */
                   2074:     case 0x35: /* LDC1 */
                   2075:     case 0x39: /* SWC1 */
                   2076:     case 0x3D: /* SDC1 */
1.1.1.4 ! root     2077: #if defined(MIPS_USES_FPU)
        !          2078:         gen_op_cp1_enabled();
        !          2079:         gen_flt_ldst(ctx, op, rt, rs, imm);
        !          2080: #else
        !          2081:         generate_exception_err(ctx, EXCP_CpU, 1);
        !          2082: #endif
        !          2083:         break;
        !          2084: 
1.1.1.2   root     2085:     case 0x11:          /* CP1 opcode */
1.1       root     2086: #if defined(MIPS_USES_FPU)
1.1.1.4 ! root     2087:         gen_op_cp1_enabled();
        !          2088:         op1 = ((ctx->opcode >> 21) & 0x1F);
        !          2089:         switch (op1) {
        !          2090:         case 0x00: /* mfc1 */
        !          2091:         case 0x02: /* cfc1 */
        !          2092:         case 0x04: /* mtc1 */
        !          2093:         case 0x06: /* ctc1 */
        !          2094:             gen_cp1(ctx, op1 | EXT_CP1, rt, rd);
        !          2095:             break;
        !          2096:         case 0x08: /* bc */
        !          2097:             gen_compute_branch1(ctx, rt, imm << 2);
        !          2098:             return;
        !          2099:         case 0x10: /* 16: fmt=single fp */
        !          2100:         case 0x11: /* 17: fmt=double fp */
        !          2101:         case 0x14: /* 20: fmt=32bit fixed */
        !          2102:         case 0x15: /* 21: fmt=64bit fixed */
        !          2103:             gen_farith(ctx, op1, rt, rd, sa, ctx->opcode & 0x3f);
        !          2104:             break;
        !          2105:         default:
        !          2106:             generate_exception_err(ctx, EXCP_RI, 1);
        !          2107:             break;
        !          2108:         }
        !          2109:         break;
1.1.1.2   root     2110: #else
                   2111:         generate_exception_err(ctx, EXCP_CpU, 1);
1.1       root     2112: #endif
1.1.1.2   root     2113:         break;
                   2114: 
                   2115:     /* COP2.  */
                   2116:     case 0x32: /* LWC2 */
                   2117:     case 0x36: /* LDC2 */
                   2118:     case 0x3A: /* SWC2 */
                   2119:     case 0x3E: /* SDC2 */
1.1       root     2120:     case 0x12:          /* CP2 opcode */
                   2121:         /* Not implemented */
1.1.1.2   root     2122:         generate_exception_err(ctx, EXCP_CpU, 2);
                   2123:         break;
                   2124: 
1.1       root     2125:     case 0x13:          /* CP3 opcode */
                   2126:         /* Not implemented */
1.1.1.2   root     2127:         generate_exception_err(ctx, EXCP_CpU, 3);
                   2128:         break;
                   2129: 
1.1       root     2130: #if defined (TARGET_MIPS64)
                   2131:     case 0x18 ... 0x1B:
                   2132:     case 0x27:
                   2133:     case 0x34:
                   2134:     case 0x37:
                   2135:         /* MIPS64 opcodes */
                   2136: #endif
                   2137: #if defined (MIPS_HAS_JALX)
                   2138:     case 0x1D:
                   2139:         /* JALX: not implemented */
                   2140: #endif
                   2141:     case 0x1E:
                   2142:         /* ASE specific */
                   2143:     default:            /* Invalid */
                   2144:         MIPS_INVAL("");
                   2145:         generate_exception(ctx, EXCP_RI);
                   2146:         break;
                   2147:     }
1.1.1.2   root     2148:     if (ctx->hflags & MIPS_HFLAG_BMASK) {
1.1       root     2149:         int hflags = ctx->hflags;
                   2150:         /* Branches completion */
1.1.1.2   root     2151:         ctx->hflags &= ~MIPS_HFLAG_BMASK;
1.1       root     2152:         ctx->bstate = BS_BRANCH;
                   2153:         save_cpu_state(ctx, 0);
                   2154:         switch (hflags & MIPS_HFLAG_BMASK) {
                   2155:         case MIPS_HFLAG_B:
                   2156:             /* unconditional branch */
                   2157:             MIPS_DEBUG("unconditional branch");
1.1.1.2   root     2158:             gen_goto_tb(ctx, 0, ctx->btarget);
1.1       root     2159:             break;
                   2160:         case MIPS_HFLAG_BL:
                   2161:             /* blikely taken case */
                   2162:             MIPS_DEBUG("blikely branch taken");
1.1.1.2   root     2163:             gen_goto_tb(ctx, 0, ctx->btarget);
1.1       root     2164:             break;
                   2165:         case MIPS_HFLAG_BC:
                   2166:             /* Conditional branch */
                   2167:             MIPS_DEBUG("conditional branch");
1.1.1.2   root     2168:             {
                   2169:               int l1;
                   2170:               l1 = gen_new_label();
                   2171:               gen_op_jnz_T2(l1);
                   2172:               gen_goto_tb(ctx, 1, ctx->pc + 4);
                   2173:               gen_set_label(l1);
                   2174:               gen_goto_tb(ctx, 0, ctx->btarget);
                   2175:             }
1.1       root     2176:             break;
                   2177:         case MIPS_HFLAG_BR:
                   2178:             /* unconditional branch to register */
                   2179:             MIPS_DEBUG("branch to register");
                   2180:             gen_op_breg();
                   2181:             break;
                   2182:         default:
                   2183:             MIPS_DEBUG("unknown branch");
                   2184:             break;
                   2185:         }
                   2186:     }
                   2187: }
                   2188: 
                   2189: int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
                   2190:                                     int search_pc)
                   2191: {
                   2192:     DisasContext ctx, *ctxp = &ctx;
                   2193:     target_ulong pc_start;
                   2194:     uint16_t *gen_opc_end;
                   2195:     int j, lj = -1;
                   2196: 
1.1.1.2   root     2197:     if (search_pc && loglevel)
1.1.1.4 ! root     2198:         fprintf (logfile, "search pc %d\n", search_pc);
1.1.1.2   root     2199: 
1.1       root     2200:     pc_start = tb->pc;
                   2201:     gen_opc_ptr = gen_opc_buf;
                   2202:     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
                   2203:     gen_opparam_ptr = gen_opparam_buf;
1.1.1.2   root     2204:     nb_gen_labels = 0;
1.1       root     2205:     ctx.pc = pc_start;
1.1.1.2   root     2206:     ctx.saved_pc = -1;
1.1       root     2207:     ctx.tb = tb;
                   2208:     ctx.bstate = BS_NONE;
1.1.1.2   root     2209:     /* Restore delay slot state from the tb context.  */
                   2210:     ctx.hflags = tb->flags;
1.1       root     2211:     ctx.saved_hflags = ctx.hflags;
                   2212:     if (ctx.hflags & MIPS_HFLAG_BR) {
                   2213:         gen_op_restore_breg_target();
                   2214:     } else if (ctx.hflags & MIPS_HFLAG_B) {
                   2215:         ctx.btarget = env->btarget;
                   2216:     } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
                   2217:         /* If we are in the delay slot of a conditional branch,
                   2218:          * restore the branch condition from env->bcond to T2
                   2219:          */
                   2220:         ctx.btarget = env->btarget;
                   2221:         gen_op_restore_bcond();
                   2222:     }
                   2223: #if defined(CONFIG_USER_ONLY)
                   2224:     ctx.mem_idx = 0;
                   2225: #else
1.1.1.4 ! root     2226:     ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
1.1       root     2227: #endif
                   2228:     ctx.CP0_Status = env->CP0_Status;
                   2229: #ifdef DEBUG_DISAS
                   2230:     if (loglevel & CPU_LOG_TB_CPU) {
                   2231:         fprintf(logfile, "------------------------------------------------\n");
1.1.1.2   root     2232:         /* FIXME: This may print out stale hflags from env... */
1.1       root     2233:         cpu_dump_state(env, logfile, fprintf, 0);
                   2234:     }
                   2235: #endif
                   2236: #if defined MIPS_DEBUG_DISAS
                   2237:     if (loglevel & CPU_LOG_TB_IN_ASM)
1.1.1.2   root     2238:         fprintf(logfile, "\ntb %p super %d cond %04x\n",
                   2239:                 tb, ctx.mem_idx, ctx.hflags);
1.1       root     2240: #endif
                   2241:     while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1.1.1.2   root     2242:         if (env->nb_breakpoints > 0) {
                   2243:             for(j = 0; j < env->nb_breakpoints; j++) {
                   2244:                 if (env->breakpoints[j] == ctx.pc) {
                   2245:                     save_cpu_state(ctxp, 1);
                   2246:                     ctx.bstate = BS_BRANCH;
                   2247:                     gen_op_debug();
                   2248:                     goto done_generating;
                   2249:                 }
                   2250:             }
                   2251:         }
                   2252: 
1.1       root     2253:         if (search_pc) {
                   2254:             j = gen_opc_ptr - gen_opc_buf;
                   2255:             if (lj < j) {
                   2256:                 lj++;
                   2257:                 while (lj < j)
                   2258:                     gen_opc_instr_start[lj++] = 0;
                   2259:             }
1.1.1.2   root     2260:             gen_opc_pc[lj] = ctx.pc;
                   2261:             gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
                   2262:             gen_opc_instr_start[lj] = 1;
1.1       root     2263:         }
                   2264:         ctx.opcode = ldl_code(ctx.pc);
                   2265:         decode_opc(&ctx);
                   2266:         ctx.pc += 4;
1.1.1.2   root     2267: 
                   2268:         if (env->singlestep_enabled)
                   2269:             break;
                   2270: 
1.1       root     2271:         if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
                   2272:             break;
1.1.1.2   root     2273: 
1.1       root     2274: #if defined (MIPS_SINGLE_STEP)
                   2275:         break;
                   2276: #endif
                   2277:     }
1.1.1.2   root     2278:     if (env->singlestep_enabled) {
                   2279:         save_cpu_state(ctxp, ctx.bstate == BS_NONE);
                   2280:         gen_op_debug();
                   2281:         goto done_generating;
                   2282:     }
                   2283:     else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
1.1       root     2284:         save_cpu_state(ctxp, 0);
1.1.1.2   root     2285:         gen_goto_tb(&ctx, 0, ctx.pc);
1.1       root     2286:     }
                   2287:     gen_op_reset_T0();
                   2288:     /* Generate the return instruction */
                   2289:     gen_op_exit_tb();
1.1.1.2   root     2290: done_generating:
1.1       root     2291:     *gen_opc_ptr = INDEX_op_end;
                   2292:     if (search_pc) {
                   2293:         j = gen_opc_ptr - gen_opc_buf;
                   2294:         lj++;
                   2295:         while (lj <= j)
                   2296:             gen_opc_instr_start[lj++] = 0;
                   2297:         tb->size = 0;
                   2298:     } else {
                   2299:         tb->size = ctx.pc - pc_start;
                   2300:     }
                   2301: #ifdef DEBUG_DISAS
                   2302: #if defined MIPS_DEBUG_DISAS
                   2303:     if (loglevel & CPU_LOG_TB_IN_ASM)
                   2304:         fprintf(logfile, "\n");
                   2305: #endif
                   2306:     if (loglevel & CPU_LOG_TB_IN_ASM) {
                   2307:         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
1.1.1.4 ! root     2308:     target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1.1       root     2309:         fprintf(logfile, "\n");
                   2310:     }
                   2311:     if (loglevel & CPU_LOG_TB_OP) {
                   2312:         fprintf(logfile, "OP:\n");
                   2313:         dump_ops(gen_opc_buf, gen_opparam_buf);
                   2314:         fprintf(logfile, "\n");
                   2315:     }
                   2316:     if (loglevel & CPU_LOG_TB_CPU) {
                   2317:         fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
                   2318:     }
                   2319: #endif
                   2320:     
                   2321:     return 0;
                   2322: }
                   2323: 
                   2324: int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
                   2325: {
                   2326:     return gen_intermediate_code_internal(env, tb, 0);
                   2327: }
                   2328: 
                   2329: int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
                   2330: {
                   2331:     return gen_intermediate_code_internal(env, tb, 1);
                   2332: }
                   2333: 
1.1.1.4 ! root     2334: #ifdef MIPS_USES_FPU
        !          2335: void fpu_dump_state(CPUState *env, FILE *f, 
        !          2336:                     int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
        !          2337:                     int flags)
        !          2338: {
        !          2339:     int i;
        !          2340: 
        !          2341: #   define printfpr(fp) do { \
        !          2342:         fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
        !          2343:                 (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
        !          2344:     } while(0)
        !          2345: 
        !          2346:     fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
        !          2347:                 env->fcr0, env->fcr31,
        !          2348:                 (env->CP0_Status & (1<<CP0St_FR)) != 0);
        !          2349:     fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
        !          2350:     fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
        !          2351:     fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
        !          2352:     for(i=0; i < 32; i+=2) {
        !          2353:         fpu_fprintf(f, "f%02d: ", i);
        !          2354:         printfpr(FPR(env, i));
        !          2355:     }
        !          2356: 
        !          2357: #undef printfpr
        !          2358: }
        !          2359: 
        !          2360: void dump_fpu(CPUState *env)
        !          2361: {
        !          2362:     if (loglevel) { 
        !          2363:        fprintf(logfile, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
        !          2364:                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
        !          2365:        fpu_dump_state(env, logfile, fprintf, 0);
        !          2366:     }
        !          2367: }
        !          2368: #endif /* MIPS_USES_FPU */
        !          2369: 
1.1       root     2370: void cpu_dump_state (CPUState *env, FILE *f, 
                   2371:                      int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                   2372:                      int flags)
                   2373: {
                   2374:     uint32_t c0_status;
                   2375:     int i;
                   2376:     
                   2377:     cpu_fprintf(f, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
                   2378:                 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
                   2379:     for (i = 0; i < 32; i++) {
                   2380:         if ((i & 3) == 0)
                   2381:             cpu_fprintf(f, "GPR%02d:", i);
                   2382:         cpu_fprintf(f, " %s %08x", regnames[i], env->gpr[i]);
                   2383:         if ((i & 3) == 3)
                   2384:             cpu_fprintf(f, "\n");
                   2385:     }
                   2386: 
                   2387:     c0_status = env->CP0_Status;
                   2388:     if (env->hflags & MIPS_HFLAG_UM)
                   2389:         c0_status |= (1 << CP0St_UM);
                   2390:     if (env->hflags & MIPS_HFLAG_ERL)
                   2391:         c0_status |= (1 << CP0St_ERL);
                   2392:     if (env->hflags & MIPS_HFLAG_EXL)
                   2393:         c0_status |= (1 << CP0St_EXL);
                   2394: 
                   2395:     cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x%08x\n",
                   2396:                 c0_status, env->CP0_Cause, env->CP0_EPC);
                   2397:     cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n",
                   2398:                 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
1.1.1.4 ! root     2399: #ifdef MIPS_USES_FPU
        !          2400:     fpu_dump_state(env, f, cpu_fprintf, flags);
        !          2401: #endif
1.1       root     2402: }
                   2403: 
                   2404: CPUMIPSState *cpu_mips_init (void)
                   2405: {
                   2406:     CPUMIPSState *env;
                   2407: 
                   2408:     env = qemu_mallocz(sizeof(CPUMIPSState));
                   2409:     if (!env)
                   2410:         return NULL;
1.1.1.2   root     2411:     cpu_exec_init(env);
1.1       root     2412:     tlb_flush(env, 1);
                   2413:     /* Minimal init */
                   2414:     env->PC = 0xBFC00000;
                   2415: #if defined (MIPS_USES_R4K_TLB)
                   2416:     env->CP0_random = MIPS_TLB_NB - 1;
                   2417: #endif
                   2418:     env->CP0_Wired = 0;
                   2419:     env->CP0_Config0 = MIPS_CONFIG0;
                   2420: #if defined (MIPS_CONFIG1)
                   2421:         env->CP0_Config1 = MIPS_CONFIG1;
                   2422: #endif
                   2423: #if defined (MIPS_CONFIG2)
                   2424:         env->CP0_Config2 = MIPS_CONFIG2;
                   2425: #endif
                   2426: #if defined (MIPS_CONFIG3)
                   2427:         env->CP0_Config3 = MIPS_CONFIG3;
                   2428: #endif
                   2429:     env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
                   2430:     env->CP0_WatchLo = 0;
                   2431:     env->hflags = MIPS_HFLAG_ERL;
                   2432:     /* Count register increments in debug mode, EJTAG version 1 */
                   2433:     env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
                   2434:     env->CP0_PRid = MIPS_CPU;
                   2435:     env->exception_index = EXCP_NONE;
1.1.1.2   root     2436: #if defined(CONFIG_USER_ONLY)
                   2437:     env->hflags |= MIPS_HFLAG_UM;
                   2438: #endif
1.1.1.4 ! root     2439: #ifdef MIPS_USES_FPU
        !          2440:     env->fcr0 = MIPS_FCR0;     
        !          2441: #endif
1.1       root     2442:     return env;
                   2443: }

unix.superglobalmegacorp.com

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