use super::mips_register_info::*;
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum MipsOpcode {
ADD = 0,
ADDU,
SUB,
SUBU,
AND,
OR,
XOR,
NOR,
SLT,
SLTU,
SLL,
SRL,
SRA,
SLLV,
SRLV,
SRAV,
MULT,
MULTU,
DIV,
DIVU,
MFHI,
MFLO,
MTHI,
MTLO,
JR,
JALR,
ADDI,
ADDIU,
ANDI,
ORI,
XORI,
SLTI,
SLTIU,
LW,
LH,
LHU,
LB,
LBU,
SW,
SH,
SB,
LUI,
BEQ,
BNE,
BLEZ,
BGTZ,
BLTZ,
BGEZ,
J,
JAL,
ADD_S,
SUB_S,
MUL_S,
DIV_S,
MOV_S,
NEG_S,
ABS_S,
SQRT_S,
CVT_S_W,
CVT_W_S,
C_EQ_S,
C_LT_S,
C_LE_S,
ADD_D,
SUB_D,
MUL_D,
DIV_D,
MOV_D,
NEG_D,
ABS_D,
SQRT_D,
CVT_D_W,
CVT_W_D,
CVT_S_D,
CVT_D_S,
C_EQ_D,
C_LT_D,
C_LE_D,
LWC1, SWC1, LDC1, SDC1,
DADD,
DADDU,
DSUB,
DSUBU,
DADDIU,
DSLL,
DSRL,
DSRA,
DSLLV,
DSRLV,
DSRAV,
DMULT,
DMULTU,
DDIV,
DDIVU,
LD,
SD,
LDL,
LDR,
SDL,
SDR,
NOP,
MOVE,
LI,
LA,
B,
BGE,
BLT,
BGT,
BLE,
BEQZ,
BNEZ,
NEG,
NOT,
ABS,
SYSCALL,
BREAK,
SYNC,
MFC0,
MTC0,
ERET,
WAIT,
DADDI,
DMUL,
DMULU,
LWU,
LL,
SC,
LLD,
SCD,
ADDV_B,
ADDV_H,
ADDV_W,
ADDV_D,
SUBV_B,
SUBV_H,
SUBV_W,
SUBV_D,
MULV_B,
MULV_H,
MULV_W,
MULV_D,
ANDV,
ORV,
XORV,
NORV,
LD_B,
LD_H,
LD_W,
LD_D,
ST_B,
ST_H,
ST_W,
ST_D,
CEQ_B,
CEQ_H,
CEQ_W,
CEQ_D,
CLE_S_B,
CLE_S_H,
CLE_S_W,
CLE_S_D,
CLT_S_B,
CLT_S_H,
CLT_S_W,
CLT_S_D,
FADD_W,
FADD_D,
FSUB_W,
FSUB_D,
FMUL_W,
FMUL_D,
FDIV_W,
FDIV_D,
FMAX_W,
FMAX_D,
FMIN_W,
FMIN_D,
FCEQ_W,
FCEQ_D,
FCLT_W,
FCLT_D,
FCLE_W,
FCLE_D,
BNZ_V,
BZ_V,
INSERT_B,
INSERT_H,
INSERT_W,
INSERT_D,
SLDI_B,
SLDI_H,
SLDI_W,
SLDI_D,
ILVEV_B,
ILVEV_H,
ILVEV_W,
ILVEV_D,
ILVOD_B,
ILVOD_H,
ILVOD_W,
ILVOD_D,
ILVL_B,
ILVL_H,
ILVL_W,
ILVL_D,
ILVR_B,
ILVR_H,
ILVR_W,
ILVR_D,
PCKEV_B,
PCKEV_H,
PCKEV_W,
PCKEV_D,
PCKOD_B,
PCKOD_H,
PCKOD_W,
PCKOD_D,
SHF_B,
SHF_H,
SHF_W,
VSHF_B,
VSHF_H,
VSHF_W,
VSHF_D,
ADDQ_PH,
ADDQ_S_PH,
ADDQ_S_W,
ADDU_QB,
ADDU_S_QB,
ADDWC,
CMPGU_EQ_QB,
CMPGU_LT_QB,
CMPGU_LE_QB,
CMPU_EQ_QB,
CMPU_LT_QB,
CMPU_LE_QB,
DPA_W_PH,
DPAQX_S_W_PH,
DPAQX_SA_W_PH,
DPAU_H_QBL,
DPAU_H_QBR,
DPS_W_PH,
DPSQX_S_W_PH,
DPSQX_SA_W_PH,
DPSU_H_QBL,
DPSU_H_QBR,
EXTR_W,
EXTR_R_W,
EXTR_RS_W,
EXTR_S_H,
INSV,
MADD,
MADDU,
MSUB,
MTHLIP,
MUL_PH,
MUL_S_PH,
MULQ_RS_W,
MULQ_S_PH,
MULQ_S_W,
PACKRL_PH,
PICK_QB,
PICK_PH,
PRECEQ_W_PHL,
PRECEQ_W_PHR,
PRECEQU_PH_QBL,
PRECEQU_PH_QBR,
PRECEU_PH_QBL,
PRECEU_PH_QBR,
PRECRQ_QB_PH,
PRECRQ_PH_W,
PRECRQ_RS_PH_W,
REPL_QB,
REPL_PH,
SHLL_QB,
SHLL_PH,
SHRA_R_PH,
SHRA_R_W,
SHRL_QB,
SUBQ_PH,
SUBQ_S_PH,
SUBQ_S_W,
SUBU_QB,
SUBU_S_QB,
DMT,
EMT,
DVPE,
EVPE,
YIELD_MT,
MFTR,
MTTR,
UMM_ADD,
UMM_ADDU,
UMM_SUB,
UMM_SUBU,
UMM_AND,
UMM_OR,
UMM_XOR,
UMM_NOR,
UMM_SLL,
UMM_SRL,
UMM_SRA,
UMM_LW,
UMM_SW,
UMM_BEQ,
UMM_BNE,
UMM_J,
UMM_JAL,
UMM_DADD,
UMM_DADDU,
UMM_DSUB,
UMM_DSUBU,
UMM_LD,
UMM_SD,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MipsOperandType {
RegDef,
RegUse1,
RegUse2,
RegBase,
RegStore,
VReg,
MemImm,
FpReg,
Imm16,
UImm16,
Simm5,
Imm8,
Shamt,
BranchOffset,
JumpTarget,
Label,
CopReg,
}
#[derive(Debug, Clone)]
pub struct MipsInstrDesc {
pub opcode: MipsOpcode,
pub mnemonic: String,
pub is_terminator: bool,
pub is_branch: bool,
pub is_call: bool,
pub is_return: bool,
pub may_load: bool,
pub may_store: bool,
pub has_side_effects: bool,
pub is_compare: bool,
pub is_commutative: bool,
pub is_cond_branch: bool,
pub operand_types: Vec<MipsOperandType>,
pub mc_opcode: u32,
}
pub struct MipsInstrInfo {
pub desc_map: HashMap<MipsOpcode, MipsInstrDesc>,
}
impl MipsInstrInfo {
pub fn new() -> Self {
let mut info = MipsInstrInfo {
desc_map: HashMap::new(),
};
info.register_all();
info
}
pub fn get_desc(&self, opcode: MipsOpcode) -> Option<&MipsInstrDesc> {
self.desc_map.get(&opcode)
}
pub fn get_mnemonic(&self, opcode: MipsOpcode) -> String {
self.desc_map
.get(&opcode)
.map(|d| d.mnemonic.clone())
.unwrap_or_else(|| "INVALID".into())
}
fn add(
&mut self,
opcode: MipsOpcode,
mnemonic: &str,
is_terminator: bool,
is_branch: bool,
is_call: bool,
is_return: bool,
may_load: bool,
may_store: bool,
has_side_effects: bool,
is_compare: bool,
is_commutative: bool,
is_cond_branch: bool,
operand_types: Vec<MipsOperandType>,
mc_opcode: u32,
) {
self.desc_map.insert(
opcode,
MipsInstrDesc {
opcode,
mnemonic: mnemonic.to_string(),
is_terminator,
is_branch,
is_call,
is_return,
may_load,
may_store,
has_side_effects,
is_compare,
is_commutative,
is_cond_branch,
operand_types,
mc_opcode,
},
);
}
fn register_all(&mut self) {
use MipsOperandType::*;
let r_alu = vec![RegDef, RegUse1, RegUse2];
self.add(
MipsOpcode::ADD,
"add",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r_alu.clone(),
0x20,
);
self.add(
MipsOpcode::ADDU,
"addu",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r_alu.clone(),
0x21,
);
self.add(
MipsOpcode::SUB,
"sub",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_alu.clone(),
0x22,
);
self.add(
MipsOpcode::SUBU,
"subu",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_alu.clone(),
0x23,
);
self.add(
MipsOpcode::AND,
"and",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r_alu.clone(),
0x24,
);
self.add(
MipsOpcode::OR,
"or",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r_alu.clone(),
0x25,
);
self.add(
MipsOpcode::XOR,
"xor",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r_alu.clone(),
0x26,
);
self.add(
MipsOpcode::NOR,
"nor",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r_alu.clone(),
0x27,
);
self.add(
MipsOpcode::SLT,
"slt",
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
r_alu.clone(),
0x2A,
);
self.add(
MipsOpcode::SLTU,
"sltu",
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
r_alu.clone(),
0x2B,
);
let r_shift = vec![RegDef, RegUse1, Shamt];
self.add(
MipsOpcode::SLL,
"sll",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_shift.clone(),
0x00,
);
self.add(
MipsOpcode::SRL,
"srl",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_shift.clone(),
0x02,
);
self.add(
MipsOpcode::SRA,
"sra",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_shift.clone(),
0x03,
);
let r_shiftv = vec![RegDef, RegUse1, RegUse2];
self.add(
MipsOpcode::SLLV,
"sllv",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_shiftv.clone(),
0x04,
);
self.add(
MipsOpcode::SRLV,
"srlv",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_shiftv.clone(),
0x06,
);
self.add(
MipsOpcode::SRAV,
"srav",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_shiftv.clone(),
0x07,
);
let r_md = vec![RegUse1, RegUse2];
self.add(
MipsOpcode::MULT,
"mult",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r_md.clone(),
0x18,
);
self.add(
MipsOpcode::MULTU,
"multu",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r_md.clone(),
0x19,
);
self.add(
MipsOpcode::DIV,
"div",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_md.clone(),
0x1A,
);
self.add(
MipsOpcode::DIVU,
"divu",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_md.clone(),
0x1B,
);
let r_mf = vec![RegDef];
self.add(
MipsOpcode::MFHI,
"mfhi",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_mf.clone(),
0x10,
);
self.add(
MipsOpcode::MFLO,
"mflo",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_mf.clone(),
0x12,
);
let r_mt = vec![RegUse1];
self.add(
MipsOpcode::MTHI,
"mthi",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_mt.clone(),
0x11,
);
self.add(
MipsOpcode::MTLO,
"mtlo",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r_mt.clone(),
0x13,
);
let r_jr = vec![RegUse1];
self.add(
MipsOpcode::JR,
"jr",
true,
true,
false,
true,
false,
false,
false,
false,
false,
false,
r_jr.clone(),
0x08,
);
let r_jalr = vec![RegDef, RegUse1];
self.add(
MipsOpcode::JALR,
"jalr",
true,
true,
true,
false,
false,
false,
false,
false,
false,
false,
r_jalr.clone(),
0x09,
);
let i_imm = vec![RegDef, RegUse1, Imm16];
self.add(
MipsOpcode::ADDI,
"addi",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
i_imm.clone(),
0x08,
);
self.add(
MipsOpcode::ADDIU,
"addiu",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
i_imm.clone(),
0x09,
);
self.add(
MipsOpcode::ANDI,
"andi",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
i_imm.clone(),
0x0C,
);
self.add(
MipsOpcode::ORI,
"ori",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
i_imm.clone(),
0x0D,
);
self.add(
MipsOpcode::XORI,
"xori",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
i_imm.clone(),
0x0E,
);
self.add(
MipsOpcode::SLTI,
"slti",
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
i_imm.clone(),
0x0A,
);
self.add(
MipsOpcode::SLTIU,
"sltiu",
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
i_imm.clone(),
0x0B,
);
let i_lui = vec![RegDef, Imm16];
self.add(
MipsOpcode::LUI,
"lui",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
i_lui.clone(),
0x0F,
);
let i_load = vec![RegDef, RegBase, Imm16];
self.add(
MipsOpcode::LW,
"lw",
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
i_load.clone(),
0x23,
);
self.add(
MipsOpcode::LH,
"lh",
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
i_load.clone(),
0x21,
);
self.add(
MipsOpcode::LHU,
"lhu",
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
i_load.clone(),
0x25,
);
self.add(
MipsOpcode::LB,
"lb",
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
i_load.clone(),
0x20,
);
self.add(
MipsOpcode::LBU,
"lbu",
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
i_load.clone(),
0x24,
);
let i_lwc1 = vec![FpReg, RegBase, Imm16];
self.add(
MipsOpcode::LWC1,
"lwc1",
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
i_lwc1.clone(),
0x31,
);
let i_ldc1 = vec![FpReg, RegBase, Imm16];
self.add(
MipsOpcode::LDC1,
"ldc1",
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
i_ldc1.clone(),
0x35,
);
let i_store = vec![RegStore, RegBase, Imm16];
self.add(
MipsOpcode::SW,
"sw",
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
i_store.clone(),
0x2B,
);
self.add(
MipsOpcode::SH,
"sh",
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
i_store.clone(),
0x29,
);
self.add(
MipsOpcode::SB,
"sb",
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
i_store.clone(),
0x28,
);
let i_swc1 = vec![FpReg, RegBase, Imm16];
self.add(
MipsOpcode::SWC1,
"swc1",
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
i_swc1.clone(),
0x39,
);
let i_sdc1 = vec![FpReg, RegBase, Imm16];
self.add(
MipsOpcode::SDC1,
"sdc1",
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
i_sdc1.clone(),
0x3D,
);
let i_branch = vec![RegUse1, RegUse2, BranchOffset];
self.add(
MipsOpcode::BEQ,
"beq",
true,
true,
false,
false,
false,
false,
false,
false,
true,
true,
i_branch.clone(),
0x04,
);
self.add(
MipsOpcode::BNE,
"bne",
true,
true,
false,
false,
false,
false,
false,
false,
true,
true,
i_branch.clone(),
0x05,
);
let i_brz = vec![RegUse1, BranchOffset];
self.add(
MipsOpcode::BLEZ,
"blez",
true,
true,
false,
false,
false,
false,
false,
false,
false,
true,
i_brz.clone(),
0x06,
);
self.add(
MipsOpcode::BGTZ,
"bgtz",
true,
true,
false,
false,
false,
false,
false,
false,
false,
true,
i_brz.clone(),
0x07,
);
self.add(
MipsOpcode::BLTZ,
"bltz",
true,
true,
false,
false,
false,
false,
false,
false,
false,
true,
i_brz.clone(),
0x00,
);
self.add(
MipsOpcode::BGEZ,
"bgez",
true,
true,
false,
false,
false,
false,
false,
false,
false,
true,
i_brz.clone(),
0x01,
);
let j_target = vec![JumpTarget];
self.add(
MipsOpcode::J,
"j",
true,
true,
false,
false,
false,
false,
false,
false,
false,
false,
j_target.clone(),
0x02,
);
self.add(
MipsOpcode::JAL,
"jal",
true,
true,
true,
false,
false,
false,
false,
false,
false,
false,
j_target.clone(),
0x03,
);
let f_alu = vec![FpReg, FpReg, FpReg];
self.add(
MipsOpcode::ADD_S,
"add.s",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
f_alu.clone(),
0x10,
);
self.add(
MipsOpcode::SUB_S,
"sub.s",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_alu.clone(),
0x10,
);
self.add(
MipsOpcode::MUL_S,
"mul.s",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
f_alu.clone(),
0x10,
);
self.add(
MipsOpcode::DIV_S,
"div.s",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_alu.clone(),
0x10,
);
let f_mov = vec![FpReg, FpReg];
self.add(
MipsOpcode::MOV_S,
"mov.s",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_mov.clone(),
0x10,
);
let f_unary = vec![FpReg, FpReg];
self.add(
MipsOpcode::NEG_S,
"neg.s",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_unary.clone(),
0x10,
);
self.add(
MipsOpcode::ABS_S,
"abs.s",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_unary.clone(),
0x10,
);
self.add(
MipsOpcode::SQRT_S,
"sqrt.s",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_unary.clone(),
0x10,
);
let f_cvt = vec![FpReg, FpReg];
self.add(
MipsOpcode::CVT_S_W,
"cvt.s.w",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_cvt.clone(),
0x10,
);
self.add(
MipsOpcode::CVT_W_S,
"cvt.w.s",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_cvt.clone(),
0x10,
);
let f_cmp = vec![FpReg, FpReg];
self.add(
MipsOpcode::C_EQ_S,
"c.eq.s",
false,
false,
false,
false,
false,
false,
false,
true,
true,
false,
f_cmp.clone(),
0x10,
);
self.add(
MipsOpcode::C_LT_S,
"c.lt.s",
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
f_cmp.clone(),
0x10,
);
self.add(
MipsOpcode::C_LE_S,
"c.le.s",
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
f_cmp.clone(),
0x10,
);
self.add(
MipsOpcode::ADD_D,
"add.d",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
f_alu.clone(),
0x11,
);
self.add(
MipsOpcode::SUB_D,
"sub.d",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_alu.clone(),
0x11,
);
self.add(
MipsOpcode::MUL_D,
"mul.d",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
f_alu.clone(),
0x11,
);
self.add(
MipsOpcode::DIV_D,
"div.d",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_alu.clone(),
0x11,
);
self.add(
MipsOpcode::MOV_D,
"mov.d",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_mov.clone(),
0x11,
);
self.add(
MipsOpcode::NEG_D,
"neg.d",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_unary.clone(),
0x11,
);
self.add(
MipsOpcode::ABS_D,
"abs.d",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_unary.clone(),
0x11,
);
self.add(
MipsOpcode::SQRT_D,
"sqrt.d",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_unary.clone(),
0x11,
);
self.add(
MipsOpcode::CVT_D_W,
"cvt.d.w",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_cvt.clone(),
0x11,
);
self.add(
MipsOpcode::CVT_W_D,
"cvt.w.d",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_cvt.clone(),
0x11,
);
self.add(
MipsOpcode::CVT_S_D,
"cvt.s.d",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_cvt.clone(),
0x11,
);
self.add(
MipsOpcode::CVT_D_S,
"cvt.d.s",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
f_cvt.clone(),
0x11,
);
self.add(
MipsOpcode::C_EQ_D,
"c.eq.d",
false,
false,
false,
false,
false,
false,
false,
true,
true,
false,
f_cmp.clone(),
0x11,
);
self.add(
MipsOpcode::C_LT_D,
"c.lt.d",
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
f_cmp.clone(),
0x11,
);
self.add(
MipsOpcode::C_LE_D,
"c.le.d",
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
f_cmp.clone(),
0x11,
);
let r64_alu = vec![RegDef, RegUse1, RegUse2];
self.add(
MipsOpcode::DADD,
"dadd",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r64_alu.clone(),
0x2C,
);
self.add(
MipsOpcode::DADDU,
"daddu",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r64_alu.clone(),
0x2D,
);
self.add(
MipsOpcode::DSUB,
"dsub",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r64_alu.clone(),
0x2E,
);
self.add(
MipsOpcode::DSUBU,
"dsubu",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r64_alu.clone(),
0x2F,
);
let i64_imm = vec![RegDef, RegUse1, Imm16];
self.add(
MipsOpcode::DADDIU,
"daddiu",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
i64_imm.clone(),
0x19,
);
let r64_shift = vec![RegDef, RegUse1, Shamt];
self.add(
MipsOpcode::DSLL,
"dsll",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r64_shift.clone(),
0x38,
);
self.add(
MipsOpcode::DSRL,
"dsrl",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r64_shift.clone(),
0x3A,
);
self.add(
MipsOpcode::DSRA,
"dsra",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r64_shift.clone(),
0x3B,
);
let r64_shiftv = vec![RegDef, RegUse1, RegUse2];
self.add(
MipsOpcode::DSLLV,
"dsllv",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r64_shiftv.clone(),
0x14,
);
self.add(
MipsOpcode::DSRLV,
"dsrlv",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r64_shiftv.clone(),
0x16,
);
self.add(
MipsOpcode::DSRAV,
"dsrav",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r64_shiftv.clone(),
0x17,
);
let r64_md = vec![RegUse1, RegUse2];
self.add(
MipsOpcode::DMULT,
"dmult",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r64_md.clone(),
0x1C,
);
self.add(
MipsOpcode::DMULTU,
"dmultu",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
r64_md.clone(),
0x1D,
);
self.add(
MipsOpcode::DDIV,
"ddiv",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r64_md.clone(),
0x1E,
);
self.add(
MipsOpcode::DDIVU,
"ddivu",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
r64_md.clone(),
0x1F,
);
let i64_load = vec![RegDef, RegBase, Imm16];
self.add(
MipsOpcode::LD,
"ld",
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
i64_load.clone(),
0x37,
);
self.add(
MipsOpcode::LDL,
"ldl",
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
i64_load.clone(),
0x1A,
);
self.add(
MipsOpcode::LDR,
"ldr",
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
i64_load.clone(),
0x1B,
);
let i64_store = vec![RegStore, RegBase, Imm16];
self.add(
MipsOpcode::SD,
"sd",
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
i64_store.clone(),
0x3F,
);
self.add(
MipsOpcode::SDL,
"sdl",
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
i64_store.clone(),
0x2C,
);
self.add(
MipsOpcode::SDR,
"sdr",
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
i64_store.clone(),
0x2D,
);
self.add(
MipsOpcode::NOP,
"nop",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![],
0x00,
);
self.add(
MipsOpcode::MOVE,
"move",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, RegUse1],
0x21,
);
self.add(
MipsOpcode::LI,
"li",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, Imm16],
0x09,
);
self.add(
MipsOpcode::LA,
"la",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, Imm16],
0x09,
);
self.add(
MipsOpcode::B,
"b",
true,
true,
false,
false,
false,
false,
false,
false,
false,
false,
vec![BranchOffset],
0x04,
);
self.add(
MipsOpcode::BGE,
"bge",
true,
true,
false,
false,
false,
false,
false,
false,
true,
true,
vec![RegUse1, RegUse2, BranchOffset],
0x00,
);
self.add(
MipsOpcode::BLT,
"blt",
true,
true,
false,
false,
false,
false,
false,
false,
false,
true,
vec![RegUse1, RegUse2, BranchOffset],
0x00,
);
self.add(
MipsOpcode::BGT,
"bgt",
true,
true,
false,
false,
false,
false,
false,
false,
false,
true,
vec![RegUse1, RegUse2, BranchOffset],
0x00,
);
self.add(
MipsOpcode::BLE,
"ble",
true,
true,
false,
false,
false,
false,
false,
false,
false,
true,
vec![RegUse1, RegUse2, BranchOffset],
0x00,
);
self.add(
MipsOpcode::BEQZ,
"beqz",
true,
true,
false,
false,
false,
false,
false,
false,
false,
true,
vec![RegUse1, BranchOffset],
0x04,
);
self.add(
MipsOpcode::BNEZ,
"bnez",
true,
true,
false,
false,
false,
false,
false,
false,
false,
true,
vec![RegUse1, BranchOffset],
0x05,
);
self.add(
MipsOpcode::NEG,
"neg",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, RegUse1],
0x22,
);
self.add(
MipsOpcode::NOT,
"not",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, RegUse1],
0x27,
);
self.add(
MipsOpcode::ABS,
"abs",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, RegUse1],
0x00,
);
self.add(
MipsOpcode::SYSCALL,
"syscall",
true,
false,
false,
false,
false,
false,
true,
false,
false,
false,
vec![],
0x0C,
);
self.add(
MipsOpcode::BREAK,
"break",
true,
false,
false,
false,
false,
false,
true,
false,
false,
false,
vec![],
0x0D,
);
self.add(
MipsOpcode::SYNC,
"sync",
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
vec![],
0x0F,
);
self.add(
MipsOpcode::MFC0,
"mfc0",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, CopReg],
0x10,
);
self.add(
MipsOpcode::MTC0,
"mtc0",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegUse1, CopReg],
0x10,
);
self.add(
MipsOpcode::ERET,
"eret",
true,
false,
false,
true,
false,
false,
true,
false,
false,
false,
vec![],
0x18,
);
self.add(
MipsOpcode::WAIT,
"wait",
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
vec![],
0x20,
);
self.add(
MipsOpcode::DADDI,
"daddi",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, RegUse1, Imm16],
0x18,
);
self.add(
MipsOpcode::DMUL,
"dmul",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, RegUse1, RegUse2],
0x1C,
);
self.add(
MipsOpcode::DMULU,
"dmulu",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, RegUse1, RegUse2],
0x1D,
);
self.add(
MipsOpcode::LWU,
"lwu",
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
vec![RegDef, MemImm],
0x27,
);
self.add(
MipsOpcode::LL,
"ll",
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
vec![RegDef, MemImm],
0x30,
);
self.add(
MipsOpcode::SC,
"sc",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
vec![RegDef, MemImm],
0x38,
);
self.add(
MipsOpcode::LLD,
"lld",
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
vec![RegDef, MemImm],
0x34,
);
self.add(
MipsOpcode::SCD,
"scd",
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
vec![RegDef, MemImm],
0x3C,
);
let msa_int_3r: Vec<(&str, MipsOpcode)> = vec![
("addv.b", MipsOpcode::ADDV_B),
("addv.h", MipsOpcode::ADDV_H),
("addv.w", MipsOpcode::ADDV_W),
("addv.d", MipsOpcode::ADDV_D),
("subv.b", MipsOpcode::SUBV_B),
("subv.h", MipsOpcode::SUBV_H),
("subv.w", MipsOpcode::SUBV_W),
("subv.d", MipsOpcode::SUBV_D),
("mulv.b", MipsOpcode::MULV_B),
("mulv.h", MipsOpcode::MULV_H),
("mulv.w", MipsOpcode::MULV_W),
("mulv.d", MipsOpcode::MULV_D),
("and.v", MipsOpcode::ANDV),
("or.v", MipsOpcode::ORV),
("xor.v", MipsOpcode::XORV),
("nor.v", MipsOpcode::NORV),
];
for (mn, op) in msa_int_3r {
self.add(
op,
mn,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
vec![VReg, VReg, VReg],
0x1E,
);
}
let msa_ldst: Vec<(&str, MipsOpcode, bool)> = vec![
("ld.b", MipsOpcode::LD_B, true),
("ld.h", MipsOpcode::LD_H, true),
("ld.w", MipsOpcode::LD_W, true),
("ld.d", MipsOpcode::LD_D, true),
("st.b", MipsOpcode::ST_B, false),
("st.h", MipsOpcode::ST_H, false),
("st.w", MipsOpcode::ST_W, false),
("st.d", MipsOpcode::ST_D, false),
];
for (mn, op, is_load) in msa_ldst {
self.add(
op,
mn,
false,
false,
false,
false,
false,
false,
false,
is_load,
!is_load,
false,
vec![VReg, MemImm],
0x1F,
);
}
let msa_compare: Vec<(&str, MipsOpcode)> = vec![
("ceq.b", MipsOpcode::CEQ_B),
("ceq.h", MipsOpcode::CEQ_H),
("ceq.w", MipsOpcode::CEQ_W),
("ceq.d", MipsOpcode::CEQ_D),
("cle.s.b", MipsOpcode::CLE_S_B),
("cle.s.h", MipsOpcode::CLE_S_H),
("cle.s.w", MipsOpcode::CLE_S_W),
("cle.s.d", MipsOpcode::CLE_S_D),
("clt.s.b", MipsOpcode::CLT_S_B),
("clt.s.h", MipsOpcode::CLT_S_H),
("clt.s.w", MipsOpcode::CLT_S_W),
("clt.s.d", MipsOpcode::CLT_S_D),
];
for (mn, op) in msa_compare {
self.add(
op,
mn,
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
vec![VReg, VReg, VReg],
0x1E,
);
}
let msa_fp: Vec<(&str, MipsOpcode)> = vec![
("fadd.w", MipsOpcode::FADD_W),
("fadd.d", MipsOpcode::FADD_D),
("fsub.w", MipsOpcode::FSUB_W),
("fsub.d", MipsOpcode::FSUB_D),
("fmul.w", MipsOpcode::FMUL_W),
("fmul.d", MipsOpcode::FMUL_D),
("fdiv.w", MipsOpcode::FDIV_W),
("fdiv.d", MipsOpcode::FDIV_D),
("fmax.w", MipsOpcode::FMAX_W),
("fmax.d", MipsOpcode::FMAX_D),
("fmin.w", MipsOpcode::FMIN_W),
("fmin.d", MipsOpcode::FMIN_D),
("fceq.w", MipsOpcode::FCEQ_W),
("fceq.d", MipsOpcode::FCEQ_D),
("fclt.w", MipsOpcode::FCLT_W),
("fclt.d", MipsOpcode::FCLT_D),
("fcle.w", MipsOpcode::FCLE_W),
("fcle.d", MipsOpcode::FCLE_D),
];
for (mn, op) in msa_fp {
self.add(
op,
mn,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![VReg, VReg, VReg],
0x1E,
);
}
self.add(
MipsOpcode::BNZ_V,
"bnz.v",
true,
true,
false,
false,
false,
false,
false,
false,
false,
false,
vec![VReg, Label],
0x1E,
);
self.add(
MipsOpcode::BZ_V,
"bz.v",
true,
true,
false,
false,
false,
false,
false,
false,
false,
false,
vec![VReg, Label],
0x1E,
);
let msa_permute: Vec<(&str, MipsOpcode)> = vec![
("insert.b", MipsOpcode::INSERT_B),
("insert.h", MipsOpcode::INSERT_H),
("insert.w", MipsOpcode::INSERT_W),
("insert.d", MipsOpcode::INSERT_D),
("sldi.b", MipsOpcode::SLDI_B),
("sldi.h", MipsOpcode::SLDI_H),
("sldi.w", MipsOpcode::SLDI_W),
("sldi.d", MipsOpcode::SLDI_D),
("ilvev.b", MipsOpcode::ILVEV_B),
("ilvev.h", MipsOpcode::ILVEV_H),
("ilvev.w", MipsOpcode::ILVEV_W),
("ilvev.d", MipsOpcode::ILVEV_D),
("ilvod.b", MipsOpcode::ILVOD_B),
("ilvod.h", MipsOpcode::ILVOD_H),
("ilvod.w", MipsOpcode::ILVOD_W),
("ilvod.d", MipsOpcode::ILVOD_D),
("ilvl.b", MipsOpcode::ILVL_B),
("ilvl.h", MipsOpcode::ILVL_H),
("ilvl.w", MipsOpcode::ILVL_W),
("ilvl.d", MipsOpcode::ILVL_D),
("ilvr.b", MipsOpcode::ILVR_B),
("ilvr.h", MipsOpcode::ILVR_H),
("ilvr.w", MipsOpcode::ILVR_W),
("ilvr.d", MipsOpcode::ILVR_D),
("pckev.b", MipsOpcode::PCKEV_B),
("pckev.h", MipsOpcode::PCKEV_H),
("pckev.w", MipsOpcode::PCKEV_W),
("pckev.d", MipsOpcode::PCKEV_D),
("pckod.b", MipsOpcode::PCKOD_B),
("pckod.h", MipsOpcode::PCKOD_H),
("pckod.w", MipsOpcode::PCKOD_W),
("pckod.d", MipsOpcode::PCKOD_D),
("shf.b", MipsOpcode::SHF_B),
("shf.h", MipsOpcode::SHF_H),
("shf.w", MipsOpcode::SHF_W),
("vshf.b", MipsOpcode::VSHF_B),
("vshf.h", MipsOpcode::VSHF_H),
("vshf.w", MipsOpcode::VSHF_W),
("vshf.d", MipsOpcode::VSHF_D),
];
for (mn, op) in msa_permute {
self.add(
op,
mn,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![VReg, VReg, VReg],
0x1E,
);
}
let dsp_ops: Vec<(&str, MipsOpcode)> = vec![
("addq.ph", MipsOpcode::ADDQ_PH),
("addq_s.ph", MipsOpcode::ADDQ_S_PH),
("addq_s.w", MipsOpcode::ADDQ_S_W),
("addu.qb", MipsOpcode::ADDU_QB),
("addu_s.qb", MipsOpcode::ADDU_S_QB),
("addwc", MipsOpcode::ADDWC),
("cmpgu.eq.qb", MipsOpcode::CMPGU_EQ_QB),
("cmpgu.lt.qb", MipsOpcode::CMPGU_LT_QB),
("cmpgu.le.qb", MipsOpcode::CMPGU_LE_QB),
("cmpu.eq.qb", MipsOpcode::CMPU_EQ_QB),
("cmpu.lt.qb", MipsOpcode::CMPU_LT_QB),
("cmpu.le.qb", MipsOpcode::CMPU_LE_QB),
("dpa.w.ph", MipsOpcode::DPA_W_PH),
("dpaqx_s.w.ph", MipsOpcode::DPAQX_S_W_PH),
("dpaqx_sa.w.ph", MipsOpcode::DPAQX_SA_W_PH),
("dpau.h.qbl", MipsOpcode::DPAU_H_QBL),
("dpau.h.qbr", MipsOpcode::DPAU_H_QBR),
("dps.w.ph", MipsOpcode::DPS_W_PH),
("dpsqx_s.w.ph", MipsOpcode::DPSQX_S_W_PH),
("dpsqx_sa.w.ph", MipsOpcode::DPSQX_SA_W_PH),
("dpsu.h.qbl", MipsOpcode::DPSU_H_QBL),
("dpsu.h.qbr", MipsOpcode::DPSU_H_QBR),
("extr.w", MipsOpcode::EXTR_W),
("extr_r.w", MipsOpcode::EXTR_R_W),
("extr_rs.w", MipsOpcode::EXTR_RS_W),
("extr_s.h", MipsOpcode::EXTR_S_H),
("insv", MipsOpcode::INSV),
("madd", MipsOpcode::MADD),
("maddu", MipsOpcode::MADDU),
("msub", MipsOpcode::MSUB),
("mthlip", MipsOpcode::MTHLIP),
("mul.ph", MipsOpcode::MUL_PH),
("mul_s.ph", MipsOpcode::MUL_S_PH),
("mulq_rs.w", MipsOpcode::MULQ_RS_W),
("mulq_s.ph", MipsOpcode::MULQ_S_PH),
("mulq_s.w", MipsOpcode::MULQ_S_W),
("packrl.ph", MipsOpcode::PACKRL_PH),
("pick.qb", MipsOpcode::PICK_QB),
("pick.ph", MipsOpcode::PICK_PH),
("preceq.w.phl", MipsOpcode::PRECEQ_W_PHL),
("preceq.w.phr", MipsOpcode::PRECEQ_W_PHR),
("precequ.ph.qbl", MipsOpcode::PRECEQU_PH_QBL),
("precequ.ph.qbr", MipsOpcode::PRECEQU_PH_QBR),
("preceu.ph.qbl", MipsOpcode::PRECEU_PH_QBL),
("preceu.ph.qbr", MipsOpcode::PRECEU_PH_QBR),
("precrq.qb.ph", MipsOpcode::PRECRQ_QB_PH),
("precrq.ph.w", MipsOpcode::PRECRQ_PH_W),
("precrq_rs.ph.w", MipsOpcode::PRECRQ_RS_PH_W),
("repl.qb", MipsOpcode::REPL_QB),
("repl.ph", MipsOpcode::REPL_PH),
("shll.qb", MipsOpcode::SHLL_QB),
("shll.ph", MipsOpcode::SHLL_PH),
("shra_r.ph", MipsOpcode::SHRA_R_PH),
("shra_r.w", MipsOpcode::SHRA_R_W),
("shrl.qb", MipsOpcode::SHRL_QB),
("subq.ph", MipsOpcode::SUBQ_PH),
("subq_s.ph", MipsOpcode::SUBQ_S_PH),
("subq_s.w", MipsOpcode::SUBQ_S_W),
("subu.qb", MipsOpcode::SUBU_QB),
("subu_s.qb", MipsOpcode::SUBU_S_QB),
];
for (mn, op) in dsp_ops {
self.add(
op,
mn,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, RegUse1, RegUse2],
0x1C,
);
}
for (mn, op) in &[
("dmt", MipsOpcode::DMT),
("emt", MipsOpcode::EMT),
("dvpe", MipsOpcode::DVPE),
("evpe", MipsOpcode::EVPE),
("yield", MipsOpcode::YIELD_MT),
] {
self.add(
*op,
mn,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
vec![],
0x1C,
);
}
self.add(
MipsOpcode::MFTR,
"mftr",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, RegUse1, Imm8],
0x1C,
);
self.add(
MipsOpcode::MTTR,
"mttr",
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegUse1, RegUse2, Imm8],
0x1C,
);
let umm_ops: Vec<(&str, MipsOpcode)> = vec![
("add", MipsOpcode::UMM_ADD),
("addu", MipsOpcode::UMM_ADDU),
("sub", MipsOpcode::UMM_SUB),
("subu", MipsOpcode::UMM_SUBU),
("and", MipsOpcode::UMM_AND),
("or", MipsOpcode::UMM_OR),
("xor", MipsOpcode::UMM_XOR),
("nor", MipsOpcode::UMM_NOR),
("sll", MipsOpcode::UMM_SLL),
("srl", MipsOpcode::UMM_SRL),
("sra", MipsOpcode::UMM_SRA),
("lw", MipsOpcode::UMM_LW),
("sw", MipsOpcode::UMM_SW),
("beq", MipsOpcode::UMM_BEQ),
("bne", MipsOpcode::UMM_BNE),
("j", MipsOpcode::UMM_J),
("jal", MipsOpcode::UMM_JAL),
("dadd", MipsOpcode::UMM_DADD),
("daddu", MipsOpcode::UMM_DADDU),
("dsub", MipsOpcode::UMM_DSUB),
("dsubu", MipsOpcode::UMM_DSUBU),
("ld", MipsOpcode::UMM_LD),
("sd", MipsOpcode::UMM_SD),
];
for (mn, op) in umm_ops {
self.add(
op,
mn,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
vec![RegDef, RegUse1, RegUse2],
0x1C,
);
}
}
pub fn is_terminator(&self, opcode: MipsOpcode) -> bool {
self.desc_map
.get(&opcode)
.map(|d| d.is_terminator)
.unwrap_or(false)
}
pub fn is_branch(&self, opcode: MipsOpcode) -> bool {
self.desc_map
.get(&opcode)
.map(|d| d.is_branch)
.unwrap_or(false)
}
pub fn is_call(&self, opcode: MipsOpcode) -> bool {
self.desc_map
.get(&opcode)
.map(|d| d.is_call)
.unwrap_or(false)
}
pub fn is_return(&self, opcode: MipsOpcode) -> bool {
self.desc_map
.get(&opcode)
.map(|d| d.is_return)
.unwrap_or(false)
}
pub fn may_load(&self, opcode: MipsOpcode) -> bool {
self.desc_map
.get(&opcode)
.map(|d| d.may_load)
.unwrap_or(false)
}
pub fn may_store(&self, opcode: MipsOpcode) -> bool {
self.desc_map
.get(&opcode)
.map(|d| d.may_store)
.unwrap_or(false)
}
pub fn get_r_type_alu_opcodes() -> Vec<MipsOpcode> {
vec![
MipsOpcode::ADD,
MipsOpcode::ADDU,
MipsOpcode::SUB,
MipsOpcode::SUBU,
MipsOpcode::AND,
MipsOpcode::OR,
MipsOpcode::XOR,
MipsOpcode::NOR,
MipsOpcode::SLT,
MipsOpcode::SLTU,
]
}
pub fn get_load_opcodes() -> Vec<MipsOpcode> {
vec![
MipsOpcode::LW,
MipsOpcode::LH,
MipsOpcode::LHU,
MipsOpcode::LB,
MipsOpcode::LBU,
MipsOpcode::LWC1,
MipsOpcode::LDC1,
MipsOpcode::LD,
]
}
pub fn get_store_opcodes() -> Vec<MipsOpcode> {
vec![
MipsOpcode::SW,
MipsOpcode::SH,
MipsOpcode::SB,
MipsOpcode::SWC1,
MipsOpcode::SDC1,
MipsOpcode::SD,
]
}
pub fn get_branch_opcodes() -> Vec<MipsOpcode> {
vec![
MipsOpcode::BEQ,
MipsOpcode::BNE,
MipsOpcode::BLEZ,
MipsOpcode::BGTZ,
MipsOpcode::BLTZ,
MipsOpcode::BGEZ,
MipsOpcode::BEQZ,
MipsOpcode::BNEZ,
MipsOpcode::B,
]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_all_opcodes_registered() {
let info = MipsInstrInfo::new();
assert!(info.get_desc(MipsOpcode::ADD).is_some());
assert!(info.get_desc(MipsOpcode::LW).is_some());
assert!(info.get_desc(MipsOpcode::SW).is_some());
assert!(info.get_desc(MipsOpcode::BEQ).is_some());
assert!(info.get_desc(MipsOpcode::J).is_some());
assert!(info.get_desc(MipsOpcode::JAL).is_some());
assert!(info.get_desc(MipsOpcode::JR).is_some());
assert!(info.get_desc(MipsOpcode::NOP).is_some());
assert!(info.get_desc(MipsOpcode::LD).is_some());
assert!(info.get_desc(MipsOpcode::ADD_S).is_some());
assert!(info.get_desc(MipsOpcode::ADD_D).is_some());
}
#[test]
fn test_mnemonics() {
let info = MipsInstrInfo::new();
assert_eq!(info.get_mnemonic(MipsOpcode::ADD), "add");
assert_eq!(info.get_mnemonic(MipsOpcode::ADDIU), "addiu");
assert_eq!(info.get_mnemonic(MipsOpcode::LW), "lw");
assert_eq!(info.get_mnemonic(MipsOpcode::SW), "sw");
assert_eq!(info.get_mnemonic(MipsOpcode::BEQ), "beq");
assert_eq!(info.get_mnemonic(MipsOpcode::J), "j");
assert_eq!(info.get_mnemonic(MipsOpcode::JAL), "jal");
assert_eq!(info.get_mnemonic(MipsOpcode::JR), "jr");
assert_eq!(info.get_mnemonic(MipsOpcode::NOP), "nop");
assert_eq!(info.get_mnemonic(MipsOpcode::LI), "li");
}
#[test]
fn test_terminators() {
let info = MipsInstrInfo::new();
assert!(info.is_terminator(MipsOpcode::JR));
assert!(info.is_terminator(MipsOpcode::J));
assert!(info.is_terminator(MipsOpcode::BEQ));
assert!(!info.is_terminator(MipsOpcode::ADD));
assert!(!info.is_terminator(MipsOpcode::LW));
}
#[test]
fn test_branches() {
let info = MipsInstrInfo::new();
assert!(info.is_branch(MipsOpcode::BEQ));
assert!(info.is_branch(MipsOpcode::BNE));
assert!(info.is_branch(MipsOpcode::J));
assert!(!info.is_branch(MipsOpcode::ADD));
}
#[test]
fn test_calls() {
let info = MipsInstrInfo::new();
assert!(info.is_call(MipsOpcode::JAL));
assert!(info.is_call(MipsOpcode::JALR));
assert!(!info.is_call(MipsOpcode::J));
}
#[test]
fn test_returns() {
let info = MipsInstrInfo::new();
assert!(info.is_return(MipsOpcode::JR));
assert!(!info.is_return(MipsOpcode::JAL));
}
#[test]
fn test_load_store() {
let info = MipsInstrInfo::new();
assert!(info.may_load(MipsOpcode::LW));
assert!(info.may_load(MipsOpcode::LB));
assert!(info.may_load(MipsOpcode::LD));
assert!(!info.may_load(MipsOpcode::SW));
assert!(info.may_store(MipsOpcode::SW));
assert!(info.may_store(MipsOpcode::SD));
}
#[test]
fn test_compare_opcodes() {
let info = MipsInstrInfo::new();
let desc_add = info.get_desc(MipsOpcode::ADD).unwrap();
assert!(desc_add.is_commutative);
assert!(!desc_add.is_compare);
let desc_slt = info.get_desc(MipsOpcode::SLT).unwrap();
assert!(desc_slt.is_compare);
assert!(!desc_slt.is_commutative);
}
#[test]
fn test_fpu_mnemonics() {
let info = MipsInstrInfo::new();
assert_eq!(info.get_mnemonic(MipsOpcode::ADD_S), "add.s");
assert_eq!(info.get_mnemonic(MipsOpcode::SUB_D), "sub.d");
assert_eq!(info.get_mnemonic(MipsOpcode::C_EQ_S), "c.eq.s");
assert_eq!(info.get_mnemonic(MipsOpcode::CVT_D_S), "cvt.d.s");
}
#[test]
fn test_r_type_alu_list() {
let alu = MipsInstrInfo::get_r_type_alu_opcodes();
assert!(alu.contains(&MipsOpcode::ADD));
assert!(alu.contains(&MipsOpcode::AND));
assert!(alu.contains(&MipsOpcode::OR));
assert_eq!(alu.len(), 10);
}
#[test]
fn test_load_list() {
let loads = MipsInstrInfo::get_load_opcodes();
assert!(loads.contains(&MipsOpcode::LW));
assert!(loads.contains(&MipsOpcode::LD));
}
#[test]
fn test_store_list() {
let stores = MipsInstrInfo::get_store_opcodes();
assert!(stores.contains(&MipsOpcode::SW));
assert!(stores.contains(&MipsOpcode::SD));
}
#[test]
fn test_branch_list() {
let branches = MipsInstrInfo::get_branch_opcodes();
assert!(branches.contains(&MipsOpcode::BEQ));
assert!(branches.contains(&MipsOpcode::B));
}
#[test]
fn test_pseudo_instructions() {
let info = MipsInstrInfo::new();
assert!(info.get_desc(MipsOpcode::NOP).is_some());
assert!(info.get_desc(MipsOpcode::MOVE).is_some());
assert!(info.get_desc(MipsOpcode::LI).is_some());
assert!(info.get_desc(MipsOpcode::B).is_some());
assert!(info.get_desc(MipsOpcode::BGE).is_some());
assert!(info.get_desc(MipsOpcode::BLT).is_some());
assert!(info.get_desc(MipsOpcode::BGT).is_some());
assert!(info.get_desc(MipsOpcode::BLE).is_some());
}
#[test]
fn test_mips64_instructions() {
let info = MipsInstrInfo::new();
assert_eq!(info.get_mnemonic(MipsOpcode::DADD), "dadd");
assert_eq!(info.get_mnemonic(MipsOpcode::DSUB), "dsub");
assert_eq!(info.get_mnemonic(MipsOpcode::LD), "ld");
assert_eq!(info.get_mnemonic(MipsOpcode::SD), "sd");
assert!(info.may_load(MipsOpcode::LD));
assert!(info.may_store(MipsOpcode::SD));
}
#[test]
fn test_system_instructions() {
let info = MipsInstrInfo::new();
let syscall_desc = info.get_desc(MipsOpcode::SYSCALL).unwrap();
assert!(syscall_desc.has_side_effects);
assert!(syscall_desc.is_terminator);
let break_desc = info.get_desc(MipsOpcode::BREAK).unwrap();
assert!(break_desc.has_side_effects);
}
#[test]
fn test_opcode_discriminant_unique() {
let ops = [
MipsOpcode::ADD as u32,
MipsOpcode::ADDU as u32,
MipsOpcode::SUB as u32,
MipsOpcode::LW as u32,
MipsOpcode::SW as u32,
MipsOpcode::BEQ as u32,
MipsOpcode::J as u32,
MipsOpcode::NOP as u32,
];
let mut seen = std::collections::HashSet::new();
for &o in &ops {
assert!(seen.insert(o), "Duplicate MipsOpcode discriminant: {}", o);
}
}
}