⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 translate.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  MIPS32 emulation for qemu: main translation routines. *  *  Copyright (c) 2004-2005 Jocelyn Mayer *  Copyright (c) 2006 Marius Groeger (FPU operations) *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <inttypes.h>#include "cpu.h"#include "exec-all.h"#include "disas.h"//#define MIPS_DEBUG_DISAS//#define MIPS_DEBUG_SIGN_EXTENSIONS//#define MIPS_SINGLE_STEP#ifdef USE_DIRECT_JUMP#define TBPARAM(x)#else#define TBPARAM(x) (long)(x)#endifenum {#define DEF(s, n, copy_size) INDEX_op_ ## s,#include "opc.h"#undef DEF    NB_OPS,};static uint16_t *gen_opc_ptr;static uint32_t *gen_opparam_ptr;#include "gen-op.h"/* MIPS major opcodes */#define MASK_OP_MAJOR(op)  (op & (0x3F << 26))enum {    /* indirect opcode tables */    OPC_SPECIAL  = (0x00 << 26),    OPC_REGIMM   = (0x01 << 26),    OPC_CP0      = (0x10 << 26),    OPC_CP1      = (0x11 << 26),    OPC_CP2      = (0x12 << 26),    OPC_CP3      = (0x13 << 26),    OPC_SPECIAL2 = (0x1C << 26),    OPC_SPECIAL3 = (0x1F << 26),    /* arithmetic with immediate */    OPC_ADDI     = (0x08 << 26),    OPC_ADDIU    = (0x09 << 26),    OPC_SLTI     = (0x0A << 26),    OPC_SLTIU    = (0x0B << 26),    OPC_ANDI     = (0x0C << 26),    OPC_ORI      = (0x0D << 26),    OPC_XORI     = (0x0E << 26),    OPC_LUI      = (0x0F << 26),    OPC_DADDI    = (0x18 << 26),    OPC_DADDIU   = (0x19 << 26),    /* Jump and branches */    OPC_J        = (0x02 << 26),    OPC_JAL      = (0x03 << 26),    OPC_BEQ      = (0x04 << 26),  /* Unconditional if rs = rt = 0 (B) */    OPC_BEQL     = (0x14 << 26),    OPC_BNE      = (0x05 << 26),    OPC_BNEL     = (0x15 << 26),    OPC_BLEZ     = (0x06 << 26),    OPC_BLEZL    = (0x16 << 26),    OPC_BGTZ     = (0x07 << 26),    OPC_BGTZL    = (0x17 << 26),    OPC_JALX     = (0x1D << 26),  /* MIPS 16 only */    /* Load and stores */    OPC_LDL      = (0x1A << 26),    OPC_LDR      = (0x1B << 26),    OPC_LB       = (0x20 << 26),    OPC_LH       = (0x21 << 26),    OPC_LWL      = (0x22 << 26),    OPC_LW       = (0x23 << 26),    OPC_LBU      = (0x24 << 26),    OPC_LHU      = (0x25 << 26),    OPC_LWR      = (0x26 << 26),    OPC_LWU      = (0x27 << 26),    OPC_SB       = (0x28 << 26),    OPC_SH       = (0x29 << 26),    OPC_SWL      = (0x2A << 26),    OPC_SW       = (0x2B << 26),    OPC_SDL      = (0x2C << 26),    OPC_SDR      = (0x2D << 26),    OPC_SWR      = (0x2E << 26),    OPC_LL       = (0x30 << 26),    OPC_LLD      = (0x34 << 26),    OPC_LD       = (0x37 << 26),    OPC_SC       = (0x38 << 26),    OPC_SCD      = (0x3C << 26),    OPC_SD       = (0x3F << 26),    /* Floating point load/store */    OPC_LWC1     = (0x31 << 26),    OPC_LWC2     = (0x32 << 26),    OPC_LDC1     = (0x35 << 26),    OPC_LDC2     = (0x36 << 26),    OPC_SWC1     = (0x39 << 26),    OPC_SWC2     = (0x3A << 26),    OPC_SDC1     = (0x3D << 26),    OPC_SDC2     = (0x3E << 26),    /* MDMX ASE specific */    OPC_MDMX     = (0x1E << 26),    /* Cache and prefetch */    OPC_CACHE    = (0x2F << 26),    OPC_PREF     = (0x33 << 26),    /* Reserved major opcode */    OPC_MAJOR3B_RESERVED = (0x3B << 26),};/* MIPS special opcodes */#define MASK_SPECIAL(op)   MASK_OP_MAJOR(op) | (op & 0x3F)enum {    /* Shifts */    OPC_SLL      = 0x00 | OPC_SPECIAL,    /* NOP is SLL r0, r0, 0   */    /* SSNOP is SLL r0, r0, 1 */    /* EHB is SLL r0, r0, 3 */    OPC_SRL      = 0x02 | OPC_SPECIAL, /* also ROTR */    OPC_SRA      = 0x03 | OPC_SPECIAL,    OPC_SLLV     = 0x04 | OPC_SPECIAL,    OPC_SRLV     = 0x06 | OPC_SPECIAL,    OPC_SRAV     = 0x07 | OPC_SPECIAL,    OPC_DSLLV    = 0x14 | OPC_SPECIAL,    OPC_DSRLV    = 0x16 | OPC_SPECIAL, /* also DROTRV */    OPC_DSRAV    = 0x17 | OPC_SPECIAL,    OPC_DSLL     = 0x38 | OPC_SPECIAL,    OPC_DSRL     = 0x3A | OPC_SPECIAL, /* also DROTR */    OPC_DSRA     = 0x3B | OPC_SPECIAL,    OPC_DSLL32   = 0x3C | OPC_SPECIAL,    OPC_DSRL32   = 0x3E | OPC_SPECIAL, /* also DROTR32 */    OPC_DSRA32   = 0x3F | OPC_SPECIAL,    /* Multiplication / division */    OPC_MULT     = 0x18 | OPC_SPECIAL,    OPC_MULTU    = 0x19 | OPC_SPECIAL,    OPC_DIV      = 0x1A | OPC_SPECIAL,    OPC_DIVU     = 0x1B | OPC_SPECIAL,    OPC_DMULT    = 0x1C | OPC_SPECIAL,    OPC_DMULTU   = 0x1D | OPC_SPECIAL,    OPC_DDIV     = 0x1E | OPC_SPECIAL,    OPC_DDIVU    = 0x1F | OPC_SPECIAL,    /* 2 registers arithmetic / logic */    OPC_ADD      = 0x20 | OPC_SPECIAL,    OPC_ADDU     = 0x21 | OPC_SPECIAL,    OPC_SUB      = 0x22 | OPC_SPECIAL,    OPC_SUBU     = 0x23 | OPC_SPECIAL,    OPC_AND      = 0x24 | OPC_SPECIAL,    OPC_OR       = 0x25 | OPC_SPECIAL,    OPC_XOR      = 0x26 | OPC_SPECIAL,    OPC_NOR      = 0x27 | OPC_SPECIAL,    OPC_SLT      = 0x2A | OPC_SPECIAL,    OPC_SLTU     = 0x2B | OPC_SPECIAL,    OPC_DADD     = 0x2C | OPC_SPECIAL,    OPC_DADDU    = 0x2D | OPC_SPECIAL,    OPC_DSUB     = 0x2E | OPC_SPECIAL,    OPC_DSUBU    = 0x2F | OPC_SPECIAL,    /* Jumps */    OPC_JR       = 0x08 | OPC_SPECIAL, /* Also JR.HB */    OPC_JALR     = 0x09 | OPC_SPECIAL, /* Also JALR.HB */    /* Traps */    OPC_TGE      = 0x30 | OPC_SPECIAL,    OPC_TGEU     = 0x31 | OPC_SPECIAL,    OPC_TLT      = 0x32 | OPC_SPECIAL,    OPC_TLTU     = 0x33 | OPC_SPECIAL,    OPC_TEQ      = 0x34 | OPC_SPECIAL,    OPC_TNE      = 0x36 | OPC_SPECIAL,    /* HI / LO registers load & stores */    OPC_MFHI     = 0x10 | OPC_SPECIAL,    OPC_MTHI     = 0x11 | OPC_SPECIAL,    OPC_MFLO     = 0x12 | OPC_SPECIAL,    OPC_MTLO     = 0x13 | OPC_SPECIAL,    /* Conditional moves */    OPC_MOVZ     = 0x0A | OPC_SPECIAL,    OPC_MOVN     = 0x0B | OPC_SPECIAL,    OPC_MOVCI    = 0x01 | OPC_SPECIAL,    /* Special */    OPC_PMON     = 0x05 | OPC_SPECIAL, /* inofficial */    OPC_SYSCALL  = 0x0C | OPC_SPECIAL,    OPC_BREAK    = 0x0D | OPC_SPECIAL,    OPC_SPIM     = 0x0E | OPC_SPECIAL, /* inofficial */    OPC_SYNC     = 0x0F | OPC_SPECIAL,    OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,    OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,    OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,    OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,    OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,    OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,    OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,};/* REGIMM (rt field) opcodes */#define MASK_REGIMM(op)    MASK_OP_MAJOR(op) | (op & (0x1F << 16))enum {    OPC_BLTZ     = (0x00 << 16) | OPC_REGIMM,    OPC_BLTZL    = (0x02 << 16) | OPC_REGIMM,    OPC_BGEZ     = (0x01 << 16) | OPC_REGIMM,    OPC_BGEZL    = (0x03 << 16) | OPC_REGIMM,    OPC_BLTZAL   = (0x10 << 16) | OPC_REGIMM,    OPC_BLTZALL  = (0x12 << 16) | OPC_REGIMM,    OPC_BGEZAL   = (0x11 << 16) | OPC_REGIMM,    OPC_BGEZALL  = (0x13 << 16) | OPC_REGIMM,    OPC_TGEI     = (0x08 << 16) | OPC_REGIMM,    OPC_TGEIU    = (0x09 << 16) | OPC_REGIMM,    OPC_TLTI     = (0x0A << 16) | OPC_REGIMM,    OPC_TLTIU    = (0x0B << 16) | OPC_REGIMM,    OPC_TEQI     = (0x0C << 16) | OPC_REGIMM,    OPC_TNEI     = (0x0E << 16) | OPC_REGIMM,    OPC_SYNCI    = (0x1F << 16) | OPC_REGIMM,};/* Special2 opcodes */#define MASK_SPECIAL2(op)  MASK_OP_MAJOR(op) | (op & 0x3F)enum {    /* Multiply & xxx operations */    OPC_MADD     = 0x00 | OPC_SPECIAL2,    OPC_MADDU    = 0x01 | OPC_SPECIAL2,    OPC_MUL      = 0x02 | OPC_SPECIAL2,    OPC_MSUB     = 0x04 | OPC_SPECIAL2,    OPC_MSUBU    = 0x05 | OPC_SPECIAL2,    /* Misc */    OPC_CLZ      = 0x20 | OPC_SPECIAL2,    OPC_CLO      = 0x21 | OPC_SPECIAL2,    OPC_DCLZ     = 0x24 | OPC_SPECIAL2,    OPC_DCLO     = 0x25 | OPC_SPECIAL2,    /* Special */    OPC_SDBBP    = 0x3F | OPC_SPECIAL2,};/* Special3 opcodes */#define MASK_SPECIAL3(op)  MASK_OP_MAJOR(op) | (op & 0x3F)enum {    OPC_EXT      = 0x00 | OPC_SPECIAL3,    OPC_DEXTM    = 0x01 | OPC_SPECIAL3,    OPC_DEXTU    = 0x02 | OPC_SPECIAL3,    OPC_DEXT     = 0x03 | OPC_SPECIAL3,    OPC_INS      = 0x04 | OPC_SPECIAL3,    OPC_DINSM    = 0x05 | OPC_SPECIAL3,    OPC_DINSU    = 0x06 | OPC_SPECIAL3,    OPC_DINS     = 0x07 | OPC_SPECIAL3,    OPC_BSHFL    = 0x20 | OPC_SPECIAL3,    OPC_DBSHFL   = 0x24 | OPC_SPECIAL3,    OPC_RDHWR    = 0x3B | OPC_SPECIAL3,};/* BSHFL opcodes */#define MASK_BSHFL(op)     MASK_SPECIAL3(op) | (op & (0x1F << 6))enum {    OPC_WSBH     = (0x02 << 6) | OPC_BSHFL,    OPC_SEB      = (0x10 << 6) | OPC_BSHFL,    OPC_SEH      = (0x18 << 6) | OPC_BSHFL,};/* DBSHFL opcodes */#define MASK_DBSHFL(op)    MASK_SPECIAL3(op) | (op & (0x1F << 6))enum {    OPC_DSBH     = (0x02 << 6) | OPC_DBSHFL,    OPC_DSHD     = (0x05 << 6) | OPC_DBSHFL,};/* Coprocessor 0 (rs field) */#define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))enum {    OPC_MFC0     = (0x00 << 21) | OPC_CP0,    OPC_DMFC0    = (0x01 << 21) | OPC_CP0,    OPC_MTC0     = (0x04 << 21) | OPC_CP0,    OPC_DMTC0    = (0x05 << 21) | OPC_CP0,    OPC_RDPGPR   = (0x0A << 21) | OPC_CP0,    OPC_MFMC0    = (0x0B << 21) | OPC_CP0,    OPC_WRPGPR   = (0x0E << 21) | OPC_CP0,    OPC_C0       = (0x10 << 21) | OPC_CP0,    OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,    OPC_C0_LAST  = (0x1F << 21) | OPC_CP0,};/* MFMC0 opcodes */#define MASK_MFMC0(op)     MASK_CP0(op) | (op & ((0x0C << 11) | (1 << 5)))enum {    OPC_DI       = (0 << 5) | (0x0C << 11) | OPC_MFMC0,    OPC_EI       = (1 << 5) | (0x0C << 11) | OPC_MFMC0,};/* Coprocessor 0 (with rs == C0) */#define MASK_C0(op)        MASK_CP0(op) | (op & 0x3F)enum {    OPC_TLBR     = 0x01 | OPC_C0,    OPC_TLBWI    = 0x02 | OPC_C0,    OPC_TLBWR    = 0x06 | OPC_C0,    OPC_TLBP     = 0x08 | OPC_C0,    OPC_RFE      = 0x10 | OPC_C0,    OPC_ERET     = 0x18 | OPC_C0,    OPC_DERET    = 0x1F | OPC_C0,    OPC_WAIT     = 0x20 | OPC_C0,};/* Coprocessor 1 (rs field) */#define MASK_CP1(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))enum {    OPC_MFC1     = (0x00 << 21) | OPC_CP1,    OPC_DMFC1    = (0x01 << 21) | OPC_CP1,    OPC_CFC1     = (0x02 << 21) | OPC_CP1,    OPC_MFHCI    = (0x03 << 21) | OPC_CP1,    OPC_MTC1     = (0x04 << 21) | OPC_CP1,    OPC_DMTC1    = (0x05 << 21) | OPC_CP1,    OPC_CTC1     = (0x06 << 21) | OPC_CP1,    OPC_MTHCI    = (0x07 << 21) | OPC_CP1,    OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */    OPC_S_FMT    = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */    OPC_D_FMT    = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */    OPC_E_FMT    = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */    OPC_Q_FMT    = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */    OPC_W_FMT    = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */    OPC_L_FMT    = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */};enum {    OPC_BC1F     = (0x00 << 16) | OPC_BC1,    OPC_BC1T     = (0x01 << 16) | OPC_BC1,    OPC_BC1FL    = (0x02 << 16) | OPC_BC1,    OPC_BC1TL    = (0x03 << 16) | OPC_BC1,};#define MASK_CP1_BCOND(op)      MASK_CP1(op) | (op & (0x3 << 16))#define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)#define MASK_CP2(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))#define MASK_CP3(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))const unsigned char *regnames[] =    { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",      "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",      "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };/* Warning: no function for r0 register (hard wired to zero) */#define GEN32(func, NAME) \static GenOpFunc *NAME ## _table [32] = {                                     \NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \};                                                                            \static inline void func(int n)                                                \{                                                                             \    NAME ## _table[n]();                                                      \}/* General purpose registers moves */GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);#ifdef MIPS_USES_FPUstatic const char *fregnames[] =    { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };# define SFGEN32(func, NAME) \static GenOpFunc *NAME ## _table [32] = {                                     \NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,                                \NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,                                \NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,                               \NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \};                                                                            \static inline void func(int n)                                                \{                                                                             \    NAME ## _table[n]();                                                      \}# define DFGEN32(func, NAME) \static GenOpFunc *NAME ## _table [32] = {                                     \NAME ## 0,  0, NAME ## 2,  0,                                                 \NAME ## 4,  0, NAME ## 6,  0,                                                 \NAME ## 8,  0, NAME ## 10, 0,                                                 \NAME ## 12, 0, NAME ## 14, 0,                                                 \NAME ## 16, 0, NAME ## 18, 0,                                                 \NAME ## 20, 0, NAME ## 22, 0,                                                 \NAME ## 24, 0, NAME ## 26, 0,                                                 \NAME ## 28, 0, NAME ## 30, 0,                                                 \};                                                                            \static inline void func(int n)                                                \{                                                                             \    NAME ## _table[n]();                                                      \}SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);#define FOP_CONDS(fmt) \static GenOpFunc * cond_ ## fmt ## _table[16] = {                       \    gen_op_cmp_ ## fmt ## _f,                                           \    gen_op_cmp_ ## fmt ## _un,                                          \    gen_op_cmp_ ## fmt ## _eq,                                          \    gen_op_cmp_ ## fmt ## _ueq,                                         \    gen_op_cmp_ ## fmt ## _olt,                                         \    gen_op_cmp_ ## fmt ## _ult,                                         \    gen_op_cmp_ ## fmt ## _ole,                                         \    gen_op_cmp_ ## fmt ## _ule,                                         \    gen_op_cmp_ ## fmt ## _sf,                                          \    gen_op_cmp_ ## fmt ## _ngle,                                        \    gen_op_cmp_ ## fmt ## _seq,                                         \    gen_op_cmp_ ## fmt ## _ngl,                                         \    gen_op_cmp_ ## fmt ## _lt,                                          \    gen_op_cmp_ ## fmt ## _nge,                                         \    gen_op_cmp_ ## fmt ## _le,                                          \

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -