blob: 44b5fccaa573191d19ebf7fedf28cb9ef814b23f [file] [log] [blame]
/*
* 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)
* Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
* Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP 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, see <http://www.gnu.org/licenses/>.
*/
#include "cpu.h"
#include "disas/disas.h"
#include "tcg-op.h"
#include "exec/cpu_ldst.h"
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
#include "sysemu/kvm.h"
#include "trace-tcg.h"
#define MIPS_DEBUG_DISAS 0
//#define MIPS_DEBUG_SIGN_EXTENSIONS
/* 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),
/* logic with immediate */
OPC_ANDI = (0x0C << 26),
OPC_ORI = (0x0D << 26),
OPC_XORI = (0x0E << 26),
OPC_LUI = (0x0F << 26),
/* arithmetic with immediate */
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),
OPC_DAUI = (0x1D << 26),
/* 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_LWPC = OPC_LW | 0x5,
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_LDPC = OPC_LD | 0x5,
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),
/* Compact Branches */
OPC_BLEZALC = (0x06 << 26),
OPC_BGEZALC = (0x06 << 26),
OPC_BGEUC = (0x06 << 26),
OPC_BGTZALC = (0x07 << 26),
OPC_BLTZALC = (0x07 << 26),
OPC_BLTUC = (0x07 << 26),
OPC_BOVC = (0x08 << 26),
OPC_BEQZALC = (0x08 << 26),
OPC_BEQC = (0x08 << 26),
OPC_BLEZC = (0x16 << 26),
OPC_BGEZC = (0x16 << 26),
OPC_BGEC = (0x16 << 26),
OPC_BGTZC = (0x17 << 26),
OPC_BLTZC = (0x17 << 26),
OPC_BLTC = (0x17 << 26),
OPC_BNVC = (0x18 << 26),
OPC_BNEZALC = (0x18 << 26),
OPC_BNEC = (0x18 << 26),
OPC_BC = (0x32 << 26),
OPC_BEQZC = (0x36 << 26),
OPC_JIC = (0x36 << 26),
OPC_BALC = (0x3A << 26),
OPC_BNEZC = (0x3E << 26),
OPC_JIALC = (0x3E << 26),
/* MDMX ASE specific */
OPC_MDMX = (0x1E << 26),
/* MSA ASE, same as MDMX */
OPC_MSA = OPC_MDMX,
/* Cache and prefetch */
OPC_CACHE = (0x2F << 26),
OPC_PREF = (0x33 << 26),
/* PC-relative address computation / loads */
OPC_PCREL = (0x3B << 26),
};
/* PC-relative address computation / loads */
#define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
#define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
enum {
/* Instructions determined by bits 19 and 20 */
OPC_ADDIUPC = OPC_PCREL | (0 << 19),
R6_OPC_LWPC = OPC_PCREL | (1 << 19),
OPC_LWUPC = OPC_PCREL | (2 << 19),
/* Instructions determined by bits 16 ... 20 */
OPC_AUIPC = OPC_PCREL | (0x1e << 16),
OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
/* Other */
R6_OPC_LDPC = OPC_PCREL | (6 << 18),
};
/* 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_ROTR = OPC_SRL | (1 << 21),
OPC_SRA = 0x03 | OPC_SPECIAL,
OPC_SLLV = 0x04 | OPC_SPECIAL,
OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
OPC_ROTRV = OPC_SRLV | (1 << 6),
OPC_SRAV = 0x07 | OPC_SPECIAL,
OPC_DSLLV = 0x14 | OPC_SPECIAL,
OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
OPC_DROTRV = OPC_DSRLV | (1 << 6),
OPC_DSRAV = 0x17 | OPC_SPECIAL,
OPC_DSLL = 0x38 | OPC_SPECIAL,
OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
OPC_DROTR = OPC_DSRL | (1 << 21),
OPC_DSRA = 0x3B | OPC_SPECIAL,
OPC_DSLL32 = 0x3C | OPC_SPECIAL,
OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
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_SELEQZ = 0x35 | OPC_SPECIAL,
OPC_SELNEZ = 0x37 | OPC_SPECIAL,
OPC_MOVCI = 0x01 | OPC_SPECIAL,
/* Special */
OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
OPC_SYSCALL = 0x0C | OPC_SPECIAL,
OPC_BREAK = 0x0D | OPC_SPECIAL,
OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
OPC_SYNC = 0x0F | OPC_SPECIAL,
OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
};
/* R6 Multiply and Divide instructions have the same Opcode
and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
#define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
enum {
R6_OPC_MUL = OPC_MULT | (2 << 6),
R6_OPC_MUH = OPC_MULT | (3 << 6),
R6_OPC_MULU = OPC_MULTU | (2 << 6),
R6_OPC_MUHU = OPC_MULTU | (3 << 6),
R6_OPC_DIV = OPC_DIV | (2 << 6),
R6_OPC_MOD = OPC_DIV | (3 << 6),
R6_OPC_DIVU = OPC_DIVU | (2 << 6),
R6_OPC_MODU = OPC_DIVU | (3 << 6),
R6_OPC_DMUL = OPC_DMULT | (2 << 6),
R6_OPC_DMUH = OPC_DMULT | (3 << 6),
R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
R6_OPC_DDIV = OPC_DDIV | (2 << 6),
R6_OPC_DMOD = OPC_DDIV | (3 << 6),
R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
R6_OPC_CLO = 0x11 | OPC_SPECIAL,
R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
OPC_LSA = 0x05 | OPC_SPECIAL,
OPC_DLSA = 0x15 | 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,
OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
OPC_DATI = (0x1e << 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,
/* Loongson 2F */
OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
OPC_DMODU_G_2F = 0x1f | 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,
/* Loongson 2E */
OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
/* MIPS DSP Load */
OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
/* MIPS DSP Arithmetic */
OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
/* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
/* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
/* MIPS DSP GPR-Based Shift Sub-class */
OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
/* MIPS DSP Multiply Sub-class insns */
/* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
/* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
/* DSP Bit/Manipulation Sub-class */
OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
/* MIPS DSP Append Sub-class */
OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
/* MIPS DSP Accumulator and DSPControl Access Sub-class */
OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
/* R6 */
R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
R6_OPC_LL = 0x36 | OPC_SPECIAL3,
R6_OPC_SC = 0x26 | OPC_SPECIAL3,
R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
R6_OPC_SCD = 0x27 | 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,
OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
};
/* 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,
OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
};
/* MIPS DSP REGIMM opcodes */
enum {
OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
};
#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
/* MIPS DSP Load */
enum {
OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
};
#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Arithmetic Sub-class */
OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
/* MIPS DSP Multiply Sub-class insns */
OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
};
#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Arithmetic Sub-class */
OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
/* MIPS DSP Multiply Sub-class insns */
OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
};
#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Arithmetic Sub-class */
OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
/* DSP Bit/Manipulation Sub-class */
OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
};
#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Arithmetic Sub-class */
OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
/* DSP Compare-Pick Sub-class */
OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
};
#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP GPR-Based Shift Sub-class */
OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
};
#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Multiply Sub-class insns */
OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
};
#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* DSP Bit/Manipulation Sub-class */
OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
};
#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Append Sub-class */
OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
};
#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Accumulator and DSPControl Access Sub-class */
OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
};
#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Arithmetic Sub-class */
OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
/* DSP Bit/Manipulation Sub-class */
OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
};
#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Multiply Sub-class insns */
OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
/* MIPS DSP Arithmetic Sub-class */
OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
};
#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* DSP Compare-Pick Sub-class */
OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
/* MIPS DSP Arithmetic Sub-class */
OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
};
#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* DSP Append Sub-class */
OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
};
#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Accumulator and DSPControl Access Sub-class */
OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
};
#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* DSP Bit/Manipulation Sub-class */
OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
};
#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Multiply Sub-class insns */
OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
};
#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP GPR-Based Shift Sub-class */
OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
};
/* 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_TLBINV = 0x03 | OPC_C0,
OPC_TLBINVF = 0x04 | 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))
/* Values for the fmt field in FP instructions */
enum {
/* 0 - 15 are reserved */
FMT_S = 16, /* single fp */
FMT_D = 17, /* double fp */
FMT_E = 18, /* extended fp */
FMT_Q = 19, /* quad fp */
FMT_W = 20, /* 32-bit fixed */
FMT_L = 21, /* 64-bit fixed */
FMT_PS = 22, /* paired single fp */
/* 23 - 31 are reserved */
};
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_BZ_V = (0x0B << 21) | OPC_CP1,
OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
OPC_BZ_B = (0x18 << 21) | OPC_CP1,
OPC_BZ_H = (0x19 << 21) | OPC_CP1,
OPC_BZ_W = (0x1A << 21) | OPC_CP1,
OPC_BZ_D = (0x1B << 21) | OPC_CP1,
OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
};
#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,
OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
};
#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
enum {
OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
OPC_PMOVMSKB = (29 << 21) | (0x0F) | 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,
OPC_NMSUB_S = 0x38 | OPC_CP3,
OPC_NMSUB_D = 0x39 | OPC_CP3,
OPC_NMSUB_PS= 0x3E | OPC_CP3,
};
/* MSA Opcodes */
#define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
enum {
OPC_MSA_I8_00 = 0x00 | OPC_MSA,
OPC_MSA_I8_01 = 0x01 | OPC_MSA,
OPC_MSA_I8_02 = 0x02 | OPC_MSA,
OPC_MSA_I5_06 = 0x06 | OPC_MSA,
OPC_MSA_I5_07 = 0x07 | OPC_MSA,
OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
OPC_MSA_3R_0D = 0x0D | OPC_MSA,
OPC_MSA_3R_0E = 0x0E | OPC_MSA,
OPC_MSA_3R_0F = 0x0F | OPC_MSA,
OPC_MSA_3R_10 = 0x10 | OPC_MSA,
OPC_MSA_3R_11 = 0x11 | OPC_MSA,
OPC_MSA_3R_12 = 0x12 | OPC_MSA,
OPC_MSA_3R_13 = 0x13 | OPC_MSA,
OPC_MSA_3R_14 = 0x14 | OPC_MSA,
OPC_MSA_3R_15 = 0x15 | OPC_MSA,
OPC_MSA_ELM = 0x19 | OPC_MSA,
OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
OPC_MSA_VEC = 0x1E | OPC_MSA,
/* MI10 instruction */
OPC_LD_B = (0x20) | OPC_MSA,
OPC_LD_H = (0x21) | OPC_MSA,
OPC_LD_W = (0x22) | OPC_MSA,
OPC_LD_D = (0x23) | OPC_MSA,
OPC_ST_B = (0x24) | OPC_MSA,
OPC_ST_H = (0x25) | OPC_MSA,
OPC_ST_W = (0x26) | OPC_MSA,
OPC_ST_D = (0x27) | OPC_MSA,
};
enum {
/* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
/* I8 instruction */
OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
/* VEC/2R/2RF instruction */
OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
/* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
/* 2RF instruction df(bit 16) = _w, _d */
OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
/* 3R instruction df(bits 22..21) = _b, _h, _w, d */
OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
/* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
/* 3RF instruction _df(bit 21) = _w, _d */
OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
/* BIT instruction df(bits 22..16) = _B _H _W _D */
OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
};
#if !defined(CONFIG_USER_ONLY)
// #define DEBUG_INTERPRETER 1
#if defined(DEBUG_INTERPRETER)
#define DEBUG_DISSAS(opc) do { \
int i; \
fprintf(stderr, "%s:%d\t%s pc %u op 0x%x rs %d rt %d rd %d sa %d imm 0x%x\n", \
__func__, __LINE__, opc, CPU.pc, op, rs, rt, rd, sa, (uint32_t)imm);\
for (i = 0; i < 32; i++) { \
fprintf(stderr, "$%d = 0x" TARGET_FMT_lx " ", i, CPU.gpr_reg[i]); \
if ((i % 4) == 3) fprintf(stderr, "\n"); \
} \
fprintf(stderr, "\n"); \
} while (0)
#else
#define DEBUG_DISSAS(opc)
#endif
#define DEBUG_ERROR(msg) do { \
fprintf(stderr, "%s:%d\t%s pc %u op 0x%x rs %d rt %d rd %d sa %d imm 0x%x\n", \
__func__, __LINE__, msg, CPU.pc, op, rs, rt, rd, sa, (uint32_t)imm);\
exit(1); \
} while(0)
CPUInterpreterContext CPU;
static inline hwaddr translate_address(CPUMIPSState *env, target_ulong address) {
#define USEG_LIMIT 0x7FFFFFFFUL
#define KSEG0_BASE 0x80000000UL
#define KSEG1_BASE 0xA0000000UL
#define KSEG2_BASE 0xC0000000UL
#define KSEG3_BASE 0xE0000000UL
#define KVM_KSEG0_BASE 0x40000000UL
#define KVM_KSEG2_BASE 0x60000000UL
if (address <= USEG_LIMIT) {
/* useg */
if (env->CP0_Status & (1 << CP0St_ERL)) {
return address & 0xFFFFFFFF;
} else {
return address;
}
#if defined(TARGET_MIPS64)
} else if (address < 0x4000000000000000ULL) {
return address;
} else if (address < 0x8000000000000000ULL) {
return address;
} else if (address < 0xC000000000000000ULL) {
/* xkphys */
if ((address & 0x07FFFFFFFFFFFFFFULL) <= env->PAMask) {
return address & env->PAMask;
} else {
return address;
}
} else if (address < 0xFFFFFFFF80000000ULL) {
/* xkseg */
return address;
#endif
} else if (address < (int32_t)KSEG1_BASE) {
/* kseg0 */
return address - (int32_t)KSEG0_BASE;
} else if (address < (int32_t)KSEG2_BASE) {
/* kseg1 */
return address - (int32_t)KSEG1_BASE;
} else
return address;
}
int tlb_exception_interpreter(CPUMIPSState *env, uint32_t *code, uint32_t size)
{
uint32_t opcode;
uint32_t op, op1;
int16_t imm;
int rs, rt, rd, sa;
int i;
MIPSCPU *cpu = mips_env_get_cpu(env);
CPUState *cs = CPU(cpu);
CPU.branch_addr = 0;
CPU.CP0_EntryLo0 = env->CP0_EntryLo0;
CPU.CP0_EntryLo1 = env->CP0_EntryLo1;
CPU.CP0_BadVAddr = env->CP0_BadVAddr;
CPU.CP0_EntryHi = env->CP0_EntryHi;
CPU.CP0_Context = env->CP0_Context;
CPU.CP0_XContext = env->CP0_XContext;
CPU.CP0_PageMask = env->CP0_PageMask;
CPU.CP0_PageGrain = env->CP0_PageGrain;
CPU.CP0_PageGrain_rw_bitmask = env->CP0_PageGrain_rw_bitmask;
CPU.CP0_Index = env->CP0_Index;
for (i = 0; i < MIPS_KSCRATCH_NUM; i++) {
CPU.CP0_KScratch[i] = env->CP0_KScratch[i];
}
while (1) {
op = MASK_OP_MAJOR(code[CPU.pc]);
rs = (code[CPU.pc] >> 21) & 0x1f;
rt = (code[CPU.pc] >> 16) & 0x1f;
rd = (code[CPU.pc] >> 11) & 0x1f;
sa = (code[CPU.pc] >> 6) & 0x1f;
imm = (int16_t)code[CPU.pc];
opcode = code[CPU.pc];
CPU.pc++;
switch (op) {
case OPC_SPECIAL:
op1 = MASK_SPECIAL(opcode);
switch (op1) {
case OPC_JR:
case OPC_JALR:
DEBUG_DISSAS("Jump");
return -2;
case OPC_SLL:
CPU.gpr_reg[rt] = (int32_t)(CPU.gpr_reg[rt] << sa);
DEBUG_DISSAS("sll");
break;
case OPC_SRA:
CPU.gpr_reg[rt] = (int32_t)((int32_t)CPU.gpr_reg[rt] >> sa);
DEBUG_DISSAS("sra");
break;
case OPC_SRL:
switch ((opcode >> 21) & 0x1f) {
case 1:
{
uint32_t mask = ~(-1 << sa);
CPU.gpr_reg[rd] = (int32_t)((((uint32_t)CPU.gpr_reg[rt] & mask) << (32 - sa)) |
(((uint32_t)CPU.gpr_reg[rt]) >> sa));
DEBUG_DISSAS("ror");
break;
}
case 0:
CPU.gpr_reg[rt] = (int32_t)((uint32_t)CPU.gpr_reg[rt] >> sa);
DEBUG_DISSAS("srl");
break;
default:
DEBUG_ERROR("srl Unknown");
break;
}
break;
case OPC_ROTR:
{
target_ulong mask = ~(-1 << sa);
CPU.gpr_reg[rd] = (int32_t)(((CPU.gpr_reg[rt] & mask) << (32 - sa)) |
(((target_ulong)CPU.gpr_reg[rt]) >> sa));
DEBUG_DISSAS("rotr");
break;
}
case OPC_ADDU:
CPU.gpr_reg[rd] = (int32_t)(CPU.gpr_reg[rs] + CPU.gpr_reg[rt]);
DEBUG_DISSAS("addu");
break;
case OPC_SUBU:
CPU.gpr_reg[rd] = (int32_t)(CPU.gpr_reg[rs] - CPU.gpr_reg[rt]);
DEBUG_DISSAS("subu");
break;
case OPC_AND: /* Logic*/
CPU.gpr_reg[rd] = CPU.gpr_reg[rs] & CPU.gpr_reg[rt];
DEBUG_DISSAS("and");
break;
case OPC_OR:
CPU.gpr_reg[rd] = CPU.gpr_reg[rs] | CPU.gpr_reg[rt];
DEBUG_DISSAS("or");
break;
case OPC_XOR:
CPU.gpr_reg[rd] = CPU.gpr_reg[rs] ^ CPU.gpr_reg[rt];
DEBUG_DISSAS("xor");
break;
#if defined(TARGET_MIPS64)
/* MIPS64 specific opcodes */
case OPC_DSLL:
CPU.gpr_reg[rd] = CPU.gpr_reg[rt] << sa;
DEBUG_DISSAS("dsll");
break;
case OPC_DSRA:
CPU.gpr_reg[rd] = CPU.gpr_reg[rt] >> sa;
DEBUG_DISSAS("dsra");
break;
case OPC_DSLL32:
CPU.gpr_reg[rd] = CPU.gpr_reg[rt] << (sa + 32);
DEBUG_DISSAS("dsll32");
break;
case OPC_DSRA32:
CPU.gpr_reg[rd] = CPU.gpr_reg[rt] >> (sa + 32);
DEBUG_DISSAS("dsra32");
break;
case OPC_DSRL:
switch ((opcode >> 21) & 0x1f) {
case 1:
{
target_ulong mask = ~(-1 << sa);
CPU.gpr_reg[rd] = (((target_ulong)CPU.gpr_reg[rt] & mask) << (64 - sa)) |
(((target_ulong)CPU.gpr_reg[rt]) >> sa);
DEBUG_DISSAS("dror");
break;
}
case 0:
CPU.gpr_reg[rt] = ((target_ulong)CPU.gpr_reg[rt] >> sa);
DEBUG_DISSAS("dsrl");
break;
default:
DEBUG_DISSAS("dsrl Unknown");
break;
}
break;
case OPC_DROTR:
{
target_ulong mask = ~(-1 << sa);
CPU.gpr_reg[rd] = (((target_ulong)CPU.gpr_reg[rt] & mask) << (64 - sa)) |
(((target_ulong)CPU.gpr_reg[rt]) >> sa);
DEBUG_DISSAS("drotr");
break;
}
case OPC_DROTR32:
{
target_ulong mask = ~(-1 << (sa + 32));
CPU.gpr_reg[rd] = (((target_ulong)CPU.gpr_reg[rt] & mask) << (32 - sa)) |
(((target_ulong)CPU.gpr_reg[rt]) >> (sa + 32));
DEBUG_DISSAS("drotr32");
break;
}
case OPC_DSRL32:
CPU.gpr_reg[rd] = ((target_ulong)CPU.gpr_reg[rt]) >> (sa + 32);
DEBUG_DISSAS("dsrl32");
break;
case OPC_DADDU:
CPU.gpr_reg[rd] = CPU.gpr_reg[rs] + CPU.gpr_reg[rt];
DEBUG_DISSAS("daddu");
break;
case OPC_DSUBU:
CPU.gpr_reg[rd] = CPU.gpr_reg[rs] - CPU.gpr_reg[rt];
DEBUG_DISSAS("dsubu");
break;
#endif
default:
DEBUG_ERROR("Unknown");
break;
}
break;
case OPC_SPECIAL3:
{
target_ulong mask;
op1 = MASK_SPECIAL3(opcode);
switch (op1) {
case OPC_EXT:
mask = (~(-1 << (rd + 1))) << sa;
CPU.gpr_reg[rt] = (int32_t)(((target_ulong)(CPU.gpr_reg[rs] & mask)) >> sa);
DEBUG_DISSAS("ext");
break;
case OPC_INS:
mask = ~(-1 << (rd - sa + 1));
CPU.gpr_reg[rt] = (int32_t)((CPU.gpr_reg[rt] & ~(mask << sa)) |
((CPU.gpr_reg[rs] & mask) << sa));
DEBUG_DISSAS("ins");
break;
#if defined(TARGET_MIPS64)
case OPC_DEXT:
mask = (~(-1 << (rd + 1))) << sa;
CPU.gpr_reg[rt] = ((target_ulong)(CPU.gpr_reg[rs] & mask)) >> sa |
(CPU.gpr_reg[rt] & ~((target_ulong)mask >> sa));
DEBUG_DISSAS("dext");
break;
case OPC_DINSM:
mask = ~(-1 << ((rd + 32) - sa + 1));
CPU.gpr_reg[rt] = (CPU.gpr_reg[rt] & ~(mask << sa)) |
((CPU.gpr_reg[rs] & mask) << sa);
DEBUG_DISSAS("dinsm");
break;
case OPC_DINS:
mask = ~(-1 << (rd - sa + 1));
CPU.gpr_reg[rt] = (CPU.gpr_reg[rt] & ~(mask << sa)) |
((CPU.gpr_reg[rs] & mask) << sa);
DEBUG_DISSAS("dins");
break;
#endif
default:
DEBUG_ERROR("Unknown");
break;
}
break;
}
case OPC_REGIMM:
op1 = MASK_REGIMM(opcode);
switch (op1) {
case OPC_BLTZL: /* REGIMM branches */
if (CPU.gpr_reg[rs] < 0) {
CPU.branch_addr = CPU.pc + (int32_t)imm;
DEBUG_DISSAS("bltzl");
continue;
} else {
CPU.pc++;
}
DEBUG_DISSAS("bltzl");
break;
case OPC_BGEZL:
if (CPU.gpr_reg[rs] >= 0) {
CPU.branch_addr = CPU.pc + (int32_t)imm;
DEBUG_DISSAS("bgezl");
continue;
} else {
CPU.pc++;
}
DEBUG_DISSAS("bgezl");
break;
case OPC_BLTZ:
if (CPU.gpr_reg[rs] < 0) {
CPU.branch_addr = CPU.pc + (int32_t)imm;
DEBUG_DISSAS("bltz");
continue;
}
DEBUG_DISSAS("bltz");
break;
case OPC_BGEZ:
if (CPU.gpr_reg[rs] >= 0) {
CPU.branch_addr = CPU.pc + (int32_t)imm;
DEBUG_DISSAS("bgez");
continue;
}
DEBUG_DISSAS("bgez");
break;
default: /* Invalid */
DEBUG_ERROR("Unknown");
break;
}
break;
case OPC_CP0:
op1 = MASK_CP0(opcode);
switch (op1) {
case OPC_MFC0:
switch (rd) {
case 4:
switch (opcode & 0x7) {
case 0:
// Context
CPU.gpr_reg[rt] = (int32_t)CPU.CP0_Context;
DEBUG_DISSAS("mfc0 Context");
break;
default:
DEBUG_DISSAS("mfc0 reg 4: Unknown select");
break;
}
break;
case 5:
switch (opcode & 0x7) {
case 0:
CPU.gpr_reg[rt] = CPU.CP0_PageMask;
DEBUG_DISSAS("mfc0 PageMask");
break;
case 1:
CPU.gpr_reg[rt] = CPU.CP0_PageGrain;
DEBUG_DISSAS("mfc0 PageGrain");
break;
default:
DEBUG_ERROR("mfc0 reg 5 Unknown select");
}
break;
case 8:
switch (opcode & 0x7) {
case 0:
// BadVAddr
CPU.gpr_reg[rt] = CPU.CP0_BadVAddr;
DEBUG_DISSAS("mfc0 BadVAddr");
break;
default:
DEBUG_ERROR("mfc0 reg 8 Unknown select");
break;
}
break;
case 13:
switch (opcode & 0x7) {
case 0:
CPU.gpr_reg[rt] = CPU.CP0_Cause;
DEBUG_DISSAS("mfc0 CP0_Cause");
break;
default:
DEBUG_ERROR("mfc0 Unknown select");
break;
}
break;
#if defined(TARGET_MIPS64)
case 20:
switch (opcode & 0x7) {
case 0:
// XContext
CPU.gpr_reg[rt] = CPU.CP0_XContext;
DEBUG_DISSAS("mfc0 XContext");
break;
default:
DEBUG_DISSAS("mfc0 reg 20: Unknown select");
break;
}
break;
#endif
case 31:
switch(opcode & 0x7) {
case 2 ... 7:
CPU.gpr_reg[rt] = (int32_t)CPU.CP0_KScratch[(opcode & 0x7) - 2];
DEBUG_DISSAS("mfc0 KScratch");
break;
default:
DEBUG_ERROR("mfc0 Unknown sel");
}
break;
default:
DEBUG_ERROR("mfc0 Unknown");
break;
}
break;
case OPC_MTC0:
switch (rd) {
case 2:
switch (opcode & 0x7) {
case 0:
{
// EntryLo0
target_ulong rxi = CPU.gpr_reg[rt] & (CPU.CP0_PageGrain & (3u << CP0PG_XIE));
CPU.CP0_EntryLo0 = (CPU.gpr_reg[rt] & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI));
DEBUG_DISSAS("mtc0 EntryLo0");
break;
}
default:
DEBUG_ERROR("mtc0 reg 2 Unknown select");
break;
}
break;
case 3:
switch (opcode & 0x7) {
case 0:
{
// EntryLo1
target_ulong rxi = CPU.gpr_reg[rt] & (CPU.CP0_PageGrain & (3u << CP0PG_XIE));
CPU.CP0_EntryLo1 = (CPU.gpr_reg[rt] & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI));
DEBUG_DISSAS("mtc0 EntryLo1");
break;
}
default:
DEBUG_ERROR("mtc0 reg 3 Unknown select");
break;
}
break;
case 5:
switch (opcode & 0x7) {
case 0:
{
uint64_t mask = CPU.gpr_reg[rt] >> (TARGET_PAGE_BITS + 1);
if (!(env->insn_flags & ISA_MIPS32R6) || (CPU.gpr_reg[rt] == ~0) ||
(mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
CPU.CP0_PageMask = CPU.gpr_reg[rt] & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
}
DEBUG_DISSAS("mtc0 PageMask");
break;
}
case 1:
CPU.CP0_PageGrain = (CPU.gpr_reg[rt] & CPU.CP0_PageGrain_rw_bitmask) |
(CPU.CP0_PageGrain & ~CPU.CP0_PageGrain_rw_bitmask);
DEBUG_DISSAS("mtc0 PageGrain");
break;
default:
DEBUG_ERROR("mtc0 reg 5 Unknown select");
}
break;
case 31:
switch(opcode & 0x7) {
case 2 ... 7:
CPU.CP0_KScratch[(opcode & 0x7) - 2] = CPU.gpr_reg[rt];
DEBUG_DISSAS("mtc0 KScratch");
break;
default:
DEBUG_ERROR("mtc0 Unknown sel");
}
break;
default:
DEBUG_ERROR("mtc0 Unknown");
break;
}
break;
#if defined(TARGET_MIPS64)
case OPC_DMFC0:
switch (rd) {
case 4:
switch (opcode & 0x7) {
case 0:
// Context
CPU.gpr_reg[rt] = CPU.CP0_Context;
DEBUG_DISSAS("dmfc0 Context");
break;
default:
DEBUG_DISSAS("dmfc0 reg 4: Unknown select");
break;
}
break;
case 5:
switch (opcode & 0x7) {
case 0:
CPU.gpr_reg[rt] = CPU.CP0_PageMask;
DEBUG_DISSAS("mfc0 PageMask");
break;
case 1:
CPU.gpr_reg[rt] = CPU.CP0_PageGrain;
DEBUG_DISSAS("mfc0 PageGrain");
break;
default:
DEBUG_ERROR("mfc0 reg 5 Unknown select");
}
break;
case 8:
switch (opcode & 0x7) {
case 0:
// BadVAddr
CPU.gpr_reg[rt] = CPU.CP0_BadVAddr;
DEBUG_DISSAS("dmfc0 BadVAddr");
break;
default:
DEBUG_DISSAS("dmfc0 reg 8: Unknown select");
break;
}
break;
case 20:
switch (opcode & 0x7) {
case 0:
// XContext
CPU.gpr_reg[rt] = CPU.CP0_XContext;
DEBUG_DISSAS("dmfc0 XContext");
break;
default:
DEBUG_DISSAS("dmfc0 reg 20: Unknown select");
break;
}
break;
case 31:
switch(opcode & 0x7) {
case 2 ... 7:
CPU.gpr_reg[rt] = CPU.CP0_KScratch[(opcode & 0x7) - 2];
DEBUG_DISSAS("dmfc0 KScratch");
break;
default:
DEBUG_ERROR("dmfc0 Unknown sel");
}
break;
default:
DEBUG_ERROR("dmfc0 Unknown");
break;
}
break;
case OPC_DMTC0:
switch (rd) {
case 2:
switch (opcode & 0x7) {
case 0:
{
// EntryLo0
target_ulong rxi = CPU.gpr_reg[rt] & ((CPU.CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
CPU.CP0_EntryLo0 = (CPU.gpr_reg[rt] & 0x3FFFFFFF) | rxi;
DEBUG_DISSAS("dmtc0 EntryLo0");
break;
}
default:
DEBUG_ERROR("dmtc0 Unknown sel");
break;
}
break;
case 3:
switch (opcode & 0x7) {
case 0:
{
// EntryLo1
target_ulong rxi = CPU.gpr_reg[rt] & ((CPU.CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
CPU.CP0_EntryLo1 = (CPU.gpr_reg[rt] & 0x3FFFFFFF) | rxi;
DEBUG_DISSAS("dmtc0 EntryLo1");
break;
}
default:
DEBUG_ERROR("dmtc0 Unknown select");
break;
}
break;
case 5:
switch (opcode & 0x7) {
case 0:
{
uint64_t mask = CPU.gpr_reg[rt] >> (TARGET_PAGE_BITS + 1);
if (!(env->insn_flags & ISA_MIPS32R6) || (CPU.gpr_reg[rt] == ~0) ||
(mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
CPU.CP0_PageMask = CPU.gpr_reg[rt] & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
}
DEBUG_DISSAS("mtc0 PageMask");
break;
}
case 1:
CPU.CP0_PageGrain = (CPU.gpr_reg[rt] & CPU.CP0_PageGrain_rw_bitmask) |
(CPU.CP0_PageGrain & ~CPU.CP0_PageGrain_rw_bitmask);
DEBUG_DISSAS("mtc0 PageGrain");
break;
default:
DEBUG_ERROR("mtc0 reg 5 Unknown select");
}
break;
case 31:
switch(opcode & 0x7) {
case 2 ... 7:
CPU.CP0_KScratch[(opcode & 0x7) - 2] = CPU.gpr_reg[rt];
DEBUG_DISSAS("dmtc0 KScratch");
break;
default:
DEBUG_ERROR("dmtc0 Unknown sel");
}
break;
default:
DEBUG_ERROR("dmtc0 Unknown");
break;
}
break;
#endif
case OPC_C0_FIRST ... OPC_C0_LAST:
switch (MASK_C0(opcode)) {
case OPC_ERET:
// Exception return
DEBUG_DISSAS("eret");
return 0;
case OPC_TLBWR:
if (likely(CPU.do_tlbwr)) {
env->CP0_EntryLo0 = CPU.CP0_EntryLo0;
env->CP0_EntryLo1 = CPU.CP0_EntryLo1;
r4k_helper_tlbwr(env);
}
DEBUG_DISSAS("tlbwr");
break;
case OPC_TLBWI:
env->CP0_EntryLo0 = CPU.CP0_EntryLo0;
env->CP0_EntryLo1 = CPU.CP0_EntryLo1;
r4k_helper_tlbwi(env);
DEBUG_DISSAS("tlbwi");
break;
case OPC_TLBP:
r4k_helper_tlbp(env);
CPU.CP0_Index = env->CP0_Index;
DEBUG_DISSAS("tlbp");
break;
default:
DEBUG_ERROR("opc_c0 Unknown");
break;
}
break;
default:
DEBUG_ERROR("Unknown");
break;
}
break;
case OPC_ADDIU:
CPU.gpr_reg[rt] = CPU.gpr_reg[rs] + imm;
DEBUG_DISSAS("addiu");
break;
case OPC_ANDI: /* Arithmetic with immediate opcode */
CPU.gpr_reg[rt] = CPU.gpr_reg[rs] & (uint32_t)imm;
DEBUG_DISSAS("andi");
break;
case OPC_LUI: /* OPC_AUI */
CPU.gpr_reg[rt] = ((int32_t)imm) << 16;
DEBUG_DISSAS("lui");
break;
case OPC_ORI:
CPU.gpr_reg[rt] = CPU.gpr_reg[rs] | ((uint32_t)imm);
DEBUG_DISSAS("ori");
break;
case OPC_XORI:
CPU.gpr_reg[rt] = CPU.gpr_reg[rs] ^ ((uint32_t)imm);
DEBUG_DISSAS("xori");
break;
case OPC_J:
case OPC_JAL: /* Jump */
case OPC_JALX:
DEBUG_DISSAS("Jump");
return -1;
/* Branch */
case OPC_BEQ:
if (CPU.gpr_reg[rs] == CPU.gpr_reg[rt]) {
CPU.branch_addr = CPU.pc + (int32_t)imm;
DEBUG_DISSAS("beq");
continue;
}
DEBUG_DISSAS("beq");
break;
case OPC_BEQL:
if (CPU.gpr_reg[rs] == CPU.gpr_reg[rt]) {
CPU.branch_addr = CPU.pc + (int32_t)imm;
DEBUG_DISSAS("beql");
continue;
} else {
CPU.pc++;
}
DEBUG_DISSAS("beql");
break;
case OPC_BNE:
if (CPU.gpr_reg[rs] != CPU.gpr_reg[rt]) {
CPU.branch_addr = CPU.pc + (int32_t)imm;
DEBUG_DISSAS("bne");
continue;
}
DEBUG_DISSAS("bne");
break;
case OPC_LW:
{
CPU.gpr_reg[rt] = (int32_t)ldl_phys(cs->as, translate_address(env, CPU.gpr_reg[rs] + imm));
DEBUG_DISSAS("lw");
break;
}
case OPC_SW:
stl_phys(cs->as, translate_address(env, CPU.gpr_reg[rs] + imm), CPU.gpr_reg[rt]);
DEBUG_DISSAS("sw");
break;
#if defined(TARGET_MIPS64)
/* MIPS64 opcodes */
case OPC_LD:
CPU.gpr_reg[rt] = ldq_phys(cs->as, translate_address(env, CPU.gpr_reg[rs] + imm));
DEBUG_DISSAS("ld");
break;
case OPC_SD:
stq_phys(cs->as, translate_address(env, CPU.gpr_reg[rs] + imm), CPU.gpr_reg[rt]);
DEBUG_DISSAS("sd");
break;
case OPC_DADDIU:
CPU.gpr_reg[rt] = CPU.gpr_reg[rs] + imm;
DEBUG_DISSAS("daddiu");
break;
#endif
default: /* Invalid */
DEBUG_ERROR("Unknown");
break;
}
if (CPU.branch_addr) {
CPU.pc = CPU.branch_addr;
CPU.branch_addr = 0;
}
if (CPU.pc >= size) {
DEBUG_ERROR("Code buffer Index out of bounds");
return -3;
}
} //end of while
}
#endif
/* global register indices */
static TCGv_ptr cpu_env;
static TCGv cpu_gpr[32], cpu_PC;
static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
static TCGv cpu_dspctrl, btarget, bcond;
static TCGv_i32 hflags;
static TCGv_i32 fpu_fcr0, fpu_fcr31;
static TCGv_i64 fpu_f64[32];
static TCGv_i64 msa_wr_d[64];
static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
#include "exec/gen-icount.h"
#define gen_helper_0e0i(name, arg) do { \
TCGv_i32 helper_tmp = tcg_const_i32(arg); \
gen_helper_##name(cpu_env, helper_tmp); \
tcg_temp_free_i32(helper_tmp); \
} while(0)
#define gen_helper_0e1i(name, arg1, arg2) do { \
TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
gen_helper_##name(cpu_env, arg1, helper_tmp); \
tcg_temp_free_i32(helper_tmp); \
} while(0)
#define gen_helper_1e0i(name, ret, arg1) do { \
TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
gen_helper_##name(ret, cpu_env, helper_tmp); \
tcg_temp_free_i32(helper_tmp); \
} while(0)
#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
tcg_temp_free_i32(helper_tmp); \
} while(0)
#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
tcg_temp_free_i32(helper_tmp); \
} while(0)
#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
tcg_temp_free_i32(helper_tmp); \
} while(0)
#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
tcg_temp_free_i32(helper_tmp); \
} while(0)
typedef struct DisasContext {
struct TranslationBlock *tb;
target_ulong pc, saved_pc;
uint32_t opcode;
int singlestep_enabled;
int insn_flags;
int32_t CP0_Config1;
/* Routine used to access memory */
int mem_idx;
TCGMemOp default_tcg_memop_mask;
uint32_t hflags, saved_hflags;
int bstate;
target_ulong btarget;
bool ulri;
int kscrexist;
bool rxi;
int ie;
bool bi;
bool bp;
} DisasContext;
enum {
BS_NONE = 0, /* We go out of the TB without reaching a branch or an
* exception condition */
BS_STOP = 1, /* We want to stop translation for any reason */
BS_BRANCH = 2, /* We reached a branch condition */
BS_EXCP = 3, /* We reached an exception condition */
};
static const char * const 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",
};
static const char * const regnames_HI[] = {
"HI0", "HI1", "HI2", "HI3",
};
static const char * const regnames_LO[] = {
"LO0", "LO1", "LO2", "LO3",
};
static const char * const 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",
};
static const char * const msaregnames[] = {
"w0.d0", "w0.d1", "w1.d0", "w1.d1",
"w2.d0", "w2.d1", "w3.d0", "w3.d1",
"w4.d0", "w4.d1", "w5.d0", "w5.d1",
"w6.d0", "w6.d1", "w7.d0", "w7.d1",
"w8.d0", "w8.d1", "w9.d0", "w9.d1",
"w10.d0", "w10.d1", "w11.d0", "w11.d1",
"w12.d0", "w12.d1", "w13.d0", "w13.d1",
"w14.d0", "w14.d1", "w15.d0", "w15.d1",
"w16.d0", "w16.d1", "w17.d0", "w17.d1",
"w18.d0", "w18.d1", "w19.d0", "w19.d1",
"w20.d0", "w20.d1", "w21.d0", "w21.d1",
"w22.d0", "w22.d1", "w23.d0", "w23.d1",
"w24.d0", "w24.d1", "w25.d0", "w25.d1",
"w26.d0", "w26.d1", "w27.d0", "w27.d1",
"w28.d0", "w28.d1", "w29.d0", "w29.d1",
"w30.d0", "w30.d1", "w31.d0", "w31.d1",
};
#define MIPS_DEBUG(fmt, ...) \
do { \
if (MIPS_DEBUG_DISAS) { \
qemu_log_mask(CPU_LOG_TB_IN_ASM, \
TARGET_FMT_lx ": %08x " fmt "\n", \
ctx->pc, ctx->opcode , ## __VA_ARGS__); \
} \
} while (0)
#define LOG_DISAS(...) \
do { \
if (MIPS_DEBUG_DISAS) { \
qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
} \
} while (0)
#define MIPS_INVAL(op) \
MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
/* General purpose registers moves. */
static inline void gen_load_gpr (TCGv t, int reg)
{
if (reg == 0)
tcg_gen_movi_tl(t, 0);
else
tcg_gen_mov_tl(t, cpu_gpr[reg]);
}
static inline void gen_store_gpr (TCGv t, int reg)
{
if (reg != 0)
tcg_gen_mov_tl(cpu_gpr[reg], t);
}
/* Moves to/from shadow registers. */
static inline void gen_load_srsgpr (int from, int to)
{
TCGv t0 = tcg_temp_new();
if (from == 0)
tcg_gen_movi_tl(t0, 0);
else {
TCGv_i32 t2 = tcg_temp_new_i32();
TCGv_ptr addr = tcg_temp_new_ptr();
tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
tcg_gen_andi_i32(t2, t2, 0xf);
tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
tcg_gen_ext_i32_ptr(addr, t2);
tcg_gen_add_ptr(addr, cpu_env, addr);
tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
tcg_temp_free_ptr(addr);
tcg_temp_free_i32(t2);
}
gen_store_gpr(t0, to);
tcg_temp_free(t0);
}
static inline void gen_store_srsgpr (int from, int to)
{
if (to != 0) {
TCGv t0 = tcg_temp_new();
TCGv_i32 t2 = tcg_temp_new_i32();
TCGv_ptr addr = tcg_temp_new_ptr();
gen_load_gpr(t0, from);
tcg_gen_ld_i32(