?? translate.c
字號:
/* * 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, /* also ROTRV */ 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,};/* Multiplication variants of the vr54xx. */#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))enum { OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT, OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU, OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT, OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU, OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT, OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU, OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT, OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU, OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT, OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU, OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT, OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU, OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT, OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,};/* 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_FORK = 0x08 | OPC_SPECIAL3, OPC_YIELD = 0x09 | 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_MFTR = (0x08 << 21) | OPC_CP0, OPC_RDPGPR = (0x0A << 21) | OPC_CP0, OPC_MFMC0 = (0x0B << 21) | OPC_CP0, OPC_MTTR = (0x0C << 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 & 0xFFFF)enum { OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0, OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0, OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0, OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0, 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_MFHC1 = (0x03 << 21) | OPC_CP1, OPC_MTC1 = (0x04 << 21) | OPC_CP1, OPC_DMTC1 = (0x05 << 21) | OPC_CP1, OPC_CTC1 = (0x06 << 21) | OPC_CP1, OPC_MTHC1 = (0x07 << 21) | OPC_CP1, OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */ OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1, OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1, 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 */ OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */};#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))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,};enum { OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2, OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,};enum { OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4, OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,};#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))enum { OPC_MFC2 = (0x00 << 21) | OPC_CP2, OPC_DMFC2 = (0x01 << 21) | OPC_CP2, OPC_CFC2 = (0x02 << 21) | OPC_CP2, OPC_MFHC2 = (0x03 << 21) | OPC_CP2, OPC_MTC2 = (0x04 << 21) | OPC_CP2, OPC_DMTC2 = (0x05 << 21) | OPC_CP2, OPC_CTC2 = (0x06 << 21) | OPC_CP2, OPC_MTHC2 = (0x07 << 21) | OPC_CP2, OPC_BC2 = (0x08 << 21) | OPC_CP2,};#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)enum { OPC_LWXC1 = 0x00 | OPC_CP3, OPC_LDXC1 = 0x01 | OPC_CP3, OPC_LUXC1 = 0x05 | OPC_CP3, OPC_SWXC1 = 0x08 | OPC_CP3, OPC_SDXC1 = 0x09 | OPC_CP3, OPC_SUXC1 = 0x0D | OPC_CP3, OPC_PREFX = 0x0F | OPC_CP3, OPC_ALNV_PS = 0x1E | OPC_CP3, OPC_MADD_S = 0x20 | OPC_CP3, OPC_MADD_D = 0x21 | OPC_CP3, OPC_MADD_PS = 0x26 | OPC_CP3, OPC_MSUB_S = 0x28 | OPC_CP3, OPC_MSUB_D = 0x29 | OPC_CP3, OPC_MSUB_PS = 0x2E | OPC_CP3, OPC_NMADD_S = 0x30 | OPC_CP3, OPC_NMADD_D = 0x31 | OPC_CP3, OPC_NMADD_PS= 0x36 | OPC_CP3,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -