jak-project/decompiler/Disasm/OpcodeInfo.cpp

547 lines
22 KiB
C++
Raw Normal View History

/*!
* @file OpcodeInfo.cpp
* Decoding info for each opcode.
*/
2020-08-22 23:30:17 -04:00
#include "OpcodeInfo.h"
#include "common/util/Assert.h"
2020-08-22 23:30:17 -04:00
namespace decompiler {
2020-08-22 23:30:17 -04:00
OpcodeInfo gOpcodeInfo[(uint32_t)InstructionKind::EE_OP_MAX];
namespace {
bool opcodes_initialized = false;
}
2020-08-22 23:30:17 -04:00
typedef InstructionKind IK;
typedef FieldType FT;
typedef DecodeType DT;
static OpcodeInfo& def(IK k, const char* name) {
gOpcodeInfo[(uint32_t)k].defined = true;
gOpcodeInfo[(uint32_t)k].name = name;
return gOpcodeInfo[(uint32_t)k];
}
static OpcodeInfo& def_branch(IK k, const char* name) {
auto& result = def(k, name);
result.is_branch = true;
result.has_delay_slot = true;
return result;
}
static OpcodeInfo& def_branch_likely(IK k, const char* name) {
auto& result = def(k, name);
result.is_branch = true;
result.is_branch_likely = true;
result.has_delay_slot = true;
return result;
}
static OpcodeInfo& def_store(IK k, const char* name) {
auto& result = def(k, name);
result.is_store = true;
return result;
}
static OpcodeInfo& def_load(IK k, const char* name) {
auto& result = def(k, name);
result.is_load = true;
return result;
}
static OpcodeInfo& drt_srs_ssimm16(OpcodeInfo& info) {
return info.dst_gpr(FT::RT).src_gpr(FT::RS).src(FT::SIMM16, DT::IMM);
}
static OpcodeInfo& srt_ssimm16_srs(OpcodeInfo& info) {
return info.src_gpr(FT::RT).src(FT::SIMM16, DT::IMM).src_gpr(FT::RS);
}
static OpcodeInfo& drt_ssimm16_srs(OpcodeInfo& info) {
return info.dst_gpr(FT::RT).src(FT::SIMM16, DT::IMM).src_gpr(FT::RS);
}
static OpcodeInfo& drd_srs_srt(OpcodeInfo& info) {
return info.dst_gpr(FT::RD).src_gpr(FT::RS).src_gpr(FT::RT);
}
static OpcodeInfo& drd_srt_srs(OpcodeInfo& info) {
return info.dst_gpr(FT::RD).src_gpr(FT::RT).src_gpr(FT::RS);
}
static OpcodeInfo& drd_srt_ssa(OpcodeInfo& info) {
return info.dst_gpr(FT::RD).src_gpr(FT::RT).src(FT::SA, DT::IMM);
}
static OpcodeInfo& srs_srt_bt(OpcodeInfo& info) {
return info.src_gpr(FT::RS).src_gpr(FT::RT).src(FT::SIMM16, DT::BRANCH_TARGET);
}
static OpcodeInfo& srs_bt(OpcodeInfo& info) {
return info.src_gpr(FT::RS).src(FT::SIMM16, DT::BRANCH_TARGET);
}
static OpcodeInfo& bt(OpcodeInfo& info) {
return info.src(FT::SIMM16, DT::BRANCH_TARGET);
}
static OpcodeInfo& dfd_sfs_sft(OpcodeInfo& info) {
return info.dst_fpr(FT::FD).src_fpr(FT::FS).src_fpr(FT::FT);
}
static OpcodeInfo& sfs_sft(OpcodeInfo& info) {
return info.src_fpr(FT::FS).src_fpr(FT::FT);
}
static OpcodeInfo& dfd_sfs(OpcodeInfo& info) {
return info.dst_fpr(FT::FD).src_fpr(FT::FS);
}
static OpcodeInfo& dfd_sft(OpcodeInfo& info) {
return info.dst_fpr(FT::FD).src_fpr(FT::FT);
}
2020-08-22 23:30:17 -04:00
static OpcodeInfo& drd(OpcodeInfo& info) {
return info.dst_gpr(FT::RD);
}
static OpcodeInfo& cd_dvft_svfs(OpcodeInfo& info) {
return info.src(FT::DEST, DT::DEST).dst_vf(FT::FT).src_vf(FT::FS);
}
static OpcodeInfo& cd_dvfd_svfs_svft(OpcodeInfo& info) {
return info.src(FT::DEST, DT::DEST).dst_vf(FT::FD).src_vf(FT::FS).src_vf(FT::FT);
}
static OpcodeInfo& cb_cd_dvfd_svfs_svft(OpcodeInfo& info) {
return info.src(FT::BC, DT::BC)
.src(FT::DEST, DT::DEST)
.dst_vf(FT::FD)
.src_vf(FT::FS)
.src_vf(FT::FT);
}
static OpcodeInfo& cb_cd_dacc_svfs_svft(OpcodeInfo& info) {
return info.src(FT::BC, DT::BC)
.src(FT::DEST, DT::DEST)
.dst(FT::ZERO, DT::VU_ACC)
.src_vf(FT::FS)
.src_vf(FT::FT);
}
static OpcodeInfo& cd_dvfd_svfs_sq(OpcodeInfo& info) {
return info.src(FT::DEST, DT::DEST).dst_vf(FT::FD).src_vf(FT::FS).src(FT::ZERO, DT::VU_Q);
}
static OpcodeInfo& cd_dacc_svfs_svft(OpcodeInfo& info) {
return info.src(FT::DEST, DT::DEST).dst(FT::ZERO, DT::VU_ACC).src_vf(FT::FS).src_vf(FT::FT);
}
void init_opcode_info() {
if (opcodes_initialized) {
return;
}
2020-08-22 23:30:17 -04:00
gOpcodeInfo[0].name = ";; ??????";
// RT, RS, SIMM
drt_srs_ssimm16(def(IK::DADDIU, "daddiu")); // Doubleword Add Immediate Unsigned
drt_srs_ssimm16(def(IK::ADDIU, "addiu")); // Add Immediate Unsigned Word
drt_srs_ssimm16(def(IK::SLTI, "slti")); // Set on Less Than Immediate
drt_srs_ssimm16(def(IK::SLTIU, "sltiu")); // Set on Less Than Immediate Unsigned
// stores in srt_ssimm16_srs
srt_ssimm16_srs(def_store(IK::SB, "sb")); // Store Byte
srt_ssimm16_srs(def_store(IK::SH, "sh")); // Store Halfword
srt_ssimm16_srs(def_store(IK::SW, "sw")); // Store Word
srt_ssimm16_srs(def_store(IK::SD, "sd")); // Store Doubleword
srt_ssimm16_srs(def_store(IK::SQ, "sq")); // Store Quadword
// loads in dsrt_ssimm16_srs
drt_ssimm16_srs(def_load(IK::LB, "lb")); // Load Byte
drt_ssimm16_srs(def_load(IK::LBU, "lbu")); // Load Byte Unsigned
drt_ssimm16_srs(def_load(IK::LH, "lh")); // Load Halfword
drt_ssimm16_srs(def_load(IK::LHU, "lhu")); // Load Halfword Unsigned
drt_ssimm16_srs(def_load(IK::LW, "lw")); // Load Word
drt_ssimm16_srs(def_load(IK::LWU, "lwu")); // Load Word Unsigned
drt_ssimm16_srs(def_load(IK::LD, "ld")); // Load Doubleword
drt_ssimm16_srs(def_load(IK::LQ, "lq")); // Load Quadword
drt_ssimm16_srs(def_load(IK::LDR, "ldr")); // Load Doubleword Left
drt_ssimm16_srs(def_load(IK::LDL, "ldl")); // Load Doubleword Right
drt_ssimm16_srs(def_load(IK::LWL, "lwl")); // Load Word Left
drt_ssimm16_srs(def_load(IK::LWR, "lwr")); // Load Word Right
// drd_srs_srt
drd_srs_srt(def(IK::DADDU, "daddu")); // Doubleword Add Unsigned
drd_srs_srt(def(IK::SUBU, "subu")); // Subtract Unsigned Word
drd_srs_srt(def(IK::ADDU, "addu")); // Add Unsigned Word
drd_srs_srt(def(IK::DSUBU, "dsubu")); // Doubleword Subtract Unsigned
drd_srs_srt(def(IK::MULT3, "mult3")); // Multiply Word
drd_srs_srt(def(IK::MULTU3, "multu3")); // Multiply Unsigned Word
drd_srs_srt(def(IK::AND, "and")); // And
drd_srs_srt(def(IK::OR, "or")); // Or
drd_srs_srt(def(IK::NOR, "nor")); // Not Or
drd_srs_srt(def(IK::XOR, "xor")); // Exclusive Or
drd_srs_srt(def(IK::MOVN, "movn")); // Move Conditional on Not Zero
drd_srs_srt(def(IK::MOVZ, "movz")); // Move Conditional on Zero
drd_srs_srt(def(IK::SLT, "slt")); // Set on Less Than
drd_srs_srt(def(IK::SLTU, "sltu")); // Set on Less Than Unsigned
// fixed shifts
drd_srt_ssa(def(IK::SLL, "sll")); // Shift Left Logical
drd_srt_ssa(def(IK::SRA, "sra")); // Shift Right Arithmetic
drd_srt_ssa(def(IK::SRL, "srl")); // Shift Right Logical
drd_srt_ssa(def(IK::DSLL, "dsll")); // Doubleword Shift Left Logical
drd_srt_ssa(def(IK::DSLL32, "dsll32")); // Doubleword Shift Left Logical Plus 32
drd_srt_ssa(def(IK::DSRA, "dsra")); // Doubleword Shift Right Arithmetic
drd_srt_ssa(def(IK::DSRA32, "dsra32")); // Doubleword Shift Right Arithmetic Plus 32
drd_srt_ssa(def(IK::DSRL, "dsrl")); // Doubleword Shift Right Logical
drd_srt_ssa(def(IK::DSRL32, "dsrl32")); // Doubleword Shift Right Logical Plus 32
// variable shifts
drd_srt_srs(def(IK::DSRAV, "dsrav")); // Doubleword Shift Right Arithmetic Variable
drd_srt_srs(def(IK::SLLV, "sllv")); // Shift Word Left Logical Variable
drd_srt_srs(def(IK::DSLLV, "dsllv")); // Doubleword Shift Left Logical Variable
drd_srt_srs(def(IK::DSRLV, "dsrlv")); // Doubleword Shift Right Logical Variable
// branch (two registers)
srs_srt_bt(def_branch(IK::BEQ, "beq")); // Branch on Equal
srs_srt_bt(def_branch(IK::BNE, "bne")); // Branch on Not Equal
srs_srt_bt(def_branch_likely(IK::BEQL, "beql")); // Branch on Equal Likely
srs_srt_bt(def_branch_likely(IK::BNEL, "bnel")); // Branch on Not Equal Likely
// branch (one register)
srs_bt(def_branch(IK::BLTZ, "bltz")); // Branch on Less Than Zero
srs_bt(def_branch(IK::BGEZ, "bgez")); // Branch on Greater Than or Equal to Zero
srs_bt(def_branch(IK::BLEZ, "blez")); // Branch on Less Than or Equal to Zero
srs_bt(def_branch(IK::BGTZ, "bgtz")); // Branch on Greater Than Zero
srs_bt(def_branch(IK::BGEZAL, "bgezal")); // Branch on Greater Than or Equal to Zero and Link
srs_bt(def_branch_likely(IK::BLTZL, "bltzl")); // Branch on Less Than Zero Likely
srs_bt(def_branch_likely(IK::BGTZL, "bgtzl")); // Branch on Greater Than Zero Likely
srs_bt(def_branch_likely(IK::BGEZL, "bgezl")); // Branch on Greater Than or Equal to Zero Likely
// weird ones
def(IK::DIV, "div").src_gpr(FT::RS).src_gpr(FT::RT); // Divide Word
def(IK::DIVU, "divu").src_gpr(FT::RS).src_gpr(FT::RT); // Divide Unsigned Word
def(IK::ORI, "ori").dst_gpr(FT::RT).src_gpr(FT::RS).src(FT::ZIMM16, DT::IMM); // Or Immediate
def(IK::XORI, "xori")
.dst_gpr(FT::RT)
.src_gpr(FT::RS)
.src(FT::ZIMM16, DT::IMM); // Exclusive Or Immediate
def(IK::ANDI, "andi").dst_gpr(FT::RT).src_gpr(FT::RS).src(FT::ZIMM16, DT::IMM); // And Immediate
def(IK::LUI, "lui").dst_gpr(FT::RT).src(FT::SIMM16, DT::IMM); // Load Upper Immediate
def(IK::JALR, "jalr").dst_gpr(FT::RD).src_gpr(FT::RS).has_delay_slot =
true; // Jump and Link Register
def(IK::JR, "jr").src_gpr(FT::RS).has_delay_slot = true; // Jump Register
def_load(IK::LWC1, "lwc1")
.dst_fpr(FT::FT)
.src(FT::SIMM16, DT::IMM)
.src_gpr(FT::RS); // Load Word to Floating Point
def_store(IK::SWC1, "swc1")
.src_fpr(FT::FT)
.src(FT::SIMM16, DT::IMM)
.src_gpr(FT::RS); // Store Word from Floating Point
// weird moves
def(IK::MFC1, "mfc1").dst_gpr(FT::RT).src_fpr(FT::FS); // Move Word from Floating Point
def(IK::MTC1, "mtc1").dst_fpr(FT::FS).src_gpr(FT::RT); // Move Word to Floating Point
2020-08-22 23:30:17 -04:00
def(IK::MTC0, "mtc0")
.src_gpr(FT::RT)
.dst(FT::RD, DT::COP0); // Move to System Control Coprocessor
def(IK::MFC0, "mfc0")
.dst_gpr(FT::RT)
.src(FT::RD, DT::COP0); // Move from System Control Coprocessor
def(IK::MTDAB, "mtdab").src_gpr(FT::RT); // Move to Data Address Breakpoint Register
def(IK::MTDABM, "mtdabm").src_gpr(FT::RT); // Move to Data Address Breakpoint Mask Register
drd(def(IK::MFHI, "mfhi")); // Move from HI Register
drd(def(IK::MFLO, "mflo")); // Move from LO Register
def(IK::MTLO1, "mtlo1").src_gpr(FT::RS); // Move to LO1 Register
drd(def(IK::MFLO1, "mflo1")); // Move from LO1 Register
drd(def(IK::PMFHL_UW, "pmfhl.uw").gpr128()); // Parallel Move From HI/LO Register
drd(def(IK::PMFHL_LW, "pmfhl.lw").gpr128());
drd(def(IK::PMFHL_LH, "pmfhl.lh").gpr128());
2020-08-22 23:30:17 -04:00
def(IK::MFPC, "mfpc").dst_gpr(FT::RT).src(FT::PCR, DT::PCR); // Move from Performance Counter
def(IK::MTPC, "mtpc").src_gpr(FT::RT).dst(FT::PCR, DT::PCR); // Move to Performance Counter
// other weirds
def(IK::SYSCALL, "syscall").src(FT::SYSCALL, DT::IMM); // System Call
def(IK::CACHE_DXWBIN, "cache dxwbin")
.src_gpr(FT::RS)
.src(FT::SIMM16, DT::IMM); // Cache Operation (Index Writeback Invalidate)
def(IK::PREF, "pref").src_gpr(FT::RT).src(FT::SIMM16, DT::IMM).src_gpr(FT::RS); // Prefetch
// plains
def(IK::SYNCP, "sync.p"); // Synchronize Shared Memory (Pipeline)
def(IK::SYNCL, "sync.l"); // Synchronize Shared Memory (Load)
def(IK::ERET, "eret"); // Exception Return
def(IK::EI, "ei"); // Enable Interrupt
def(IK::MTSAB, "mtsab")
.src_gpr(FT::RS)
.src(FT::ZIMM16, DT::IMM); // Move Byte Count to Shift Amount Register
drd_srs_srt(def(IK::QFSRV, "qfsrv")).gpr128(); // Quadword Funnel Shift Right Variable
2020-08-22 23:30:17 -04:00
drd_srs_srt(def(IK::PPACB, "ppacb").gpr128()); // Parallel Pack to Byte
drd_srs_srt(def(IK::PPACH, "ppach").gpr128()); // Parallel Pack to Halfword
drd_srs_srt(def(IK::PPACW, "ppacw").gpr128()); // Parallel Pack to Word
drd_srs_srt(def(IK::PADDB, "paddb").gpr128()); // Parallel Add Byte
drd_srs_srt(def(IK::PADDH, "paddh").gpr128()); // Parallel Add Halfword
drd_srs_srt(def(IK::PADDW, "paddw").gpr128()); // Parallel Add Word
drd_srs_srt(def(IK::PSUBH, "psubh").gpr128()); // Parallel Subtract Halfword
drd_srs_srt(def(IK::PSUBW, "psubw").gpr128()); // Parallel Subtract Word
drd_srs_srt(def(IK::PMINH, "pminh").gpr128()); // Parallel Minimize Halfword
drd_srs_srt(def(IK::PMINW, "pminw").gpr128()); // Parallel Minimize Word
drd_srs_srt(def(IK::PMAXH, "pmaxh").gpr128()); // Parallel Maximize Halfword
drd_srs_srt(def(IK::PMAXW, "pmaxw").gpr128()); // Parallel Maximize Word
drd_srs_srt(def(IK::PEXTLB, "pextlb").gpr128()); // Parallel Extend Lower from Byte
drd_srs_srt(def(IK::PEXTLH, "pextlh").gpr128()); // Parallel Extend Lower from Halfword
drd_srs_srt(def(IK::PEXTLW, "pextlw").gpr128()); // Parallel Extend Lower from Word
drd_srs_srt(def(IK::PCGTW, "pcgtw").gpr128()); // Parallel Compare for Greater Than Word
drd_srs_srt(def(IK::PCGTB, "pcgtb").gpr128()); // Parallel Compare for Greater Than Byte
drd_srs_srt(def(IK::PCEQB, "pceqb").gpr128()); // Parallel Compare for Equal Byte
drd_srs_srt(def(IK::PCEQW, "pceqw").gpr128()); // Parallel Compare for Equal Word
drd_srs_srt(def(IK::PEXTUB, "pextub").gpr128()); // Parallel Extend Upper from Byte
drd_srs_srt(def(IK::PEXTUH, "pextuh").gpr128()); // Parallel Extend Upper from Halfword
drd_srs_srt(def(IK::PEXTUW, "pextuw").gpr128()); // Parallel Extend Upper from Word
drd_srs_srt(def(IK::PCPYUD, "pcpyud").gpr128()); // Parallel Copy Upper Doubleword
drd_srs_srt(def(IK::PCPYLD, "pcpyld").gpr128()); // Parallel Copy Lower Doubleword
drd_srs_srt(def(IK::PMADDH, "pmaddh").gpr128()); // Parallel Multiply-Add Halfword
drd_srs_srt(def(IK::PMULTH, "pmulth").gpr128()); // Parallel Multiply Halfword
drd_srs_srt(def(IK::PINTEH, "pinteh").gpr128()); // Parallel Interleave Even Halfword
drd_srs_srt(def(IK::PAND, "pand").gpr128()); // Parallel And
drd_srs_srt(def(IK::POR, "por").gpr128()); // Parallel Or
drd_srs_srt(def(IK::PNOR, "pnor").gpr128()); // Parallel Not Or
drd_srs_srt(def(IK::PXOR, "pxor").gpr128()); // Parallel Exclusive Or
def(IK::PEXEW, "pexew").gpr128().dst_gpr(FT::RD).src_gpr(FT::RT); // Parallel Exchange Even Word
def(IK::PEXCW, "pexcw")
.gpr128()
.dst_gpr(FT::RD)
.src_gpr(FT::RT); // Parallel Exchange Center Word
drd_srt_ssa(def(IK::PSLLW, "psllw").gpr128()); // Parallel Shift Left Logical Word
drd_srt_ssa(def(IK::PSLLH, "psllh").gpr128()); // Parallel Shift Left Logical Halfword
drd_srt_ssa(def(IK::PSRAW, "psraw").gpr128()); // Parallel Shift Right Arithmetic Word
drd_srt_ssa(def(IK::PSRAH, "psrah").gpr128()); // Parallel Shift Right Arithmetic Halfword
drd_srt_ssa(def(IK::PSRLH, "psrlh").gpr128()); // Parallel Shift Right Logical Halfword
def(IK::PLZCW, "plzcw")
.dst_gpr(FT::RD)
.src_gpr(FT::RS)
.gpr128(); // Parallel Leading Zero Count Word
def(IK::PABSW, "pabsw").dst_gpr(FT::RD).src_gpr(FT::RT).gpr128(); // Parallel Absolute Word
def(IK::PROT3W, "prot3w").dst_gpr(FT::RD).src_gpr(FT::RT).gpr128(); // Parallel Rotate 3 Word
def(IK::PCPYH, "pcpyh").dst_gpr(FT::RD).src_gpr(FT::RT).gpr128(); // Parallel Copy Halfword
2020-08-22 23:30:17 -04:00
// COP1
// branch (no registers)
bt(def_branch(IK::BC1F, "bc1f")); // Branch on FP False
bt(def_branch(IK::BC1T, "bc1t")); // Branch on FP True
bt(def_branch_likely(IK::BC1FL, "bc1fl")); // Branch on FP False Likely
bt(def_branch_likely(IK::BC1TL, "bc1tl")); // Branch on FP True Likely
dfd_sfs_sft(def(IK::ADDS, "add.s")); // Floating Point Add
dfd_sfs_sft(def(IK::SUBS, "sub.s")); // Floating Point Subtract
dfd_sfs_sft(def(IK::MULS, "mul.s")); // Floating Point Multiply
dfd_sfs_sft(def(IK::DIVS, "div.s")); // Floating Point Divide
dfd_sfs_sft(def(IK::MINS, "min.s")); // Floating Point Minimum
dfd_sfs_sft(def(IK::MAXS, "max.s")); // Floating Point Maximum
dfd_sfs_sft(def(IK::MADDS, "madd.s")); // Floating Point Multiply-Add
dfd_sfs_sft(def(IK::MSUBS, "msub.s")); // Floating Point Multiply and Subtract
dfd_sfs_sft(def(IK::RSQRTS, "rsqrt.s")); // Floating Point Reciporcal Square Root
dfd_sfs(def(IK::ABSS, "abs.s")); // Floating Point Absolute Value
dfd_sfs(def(IK::NEGS, "neg.s")); // Floating Point Negate
dfd_sfs(def(IK::CVTSW, "cvt.s.w")); // Fixed-point Convert to Single Floating Point
dfd_sfs(def(IK::CVTWS, "cvt.w.s")); // Floating Point Convert to Word Fixed-point
dfd_sfs(def(IK::MOVS, "mov.s")); // Floating Point Move
dfd_sft(def(IK::SQRTS, "sqrt.s")); // Floating Point Square Root
2020-08-22 23:30:17 -04:00
sfs_sft(def(IK::CLTS, "c.lt.s")); // Floating Point Compare
sfs_sft(def(IK::CLES, "c.le.s")); // Floating Point Compare
sfs_sft(def(IK::CEQS, "c.eq.s")); // Floating Point Compare
sfs_sft(def(IK::MULAS, "mula.s")); // Floating Point Multiply to Accumulator
sfs_sft(def(IK::MADDAS, "madda.s")); // Floating Point Multiply-Add to Accumulator
sfs_sft(def(IK::ADDAS, "adda.s")); // Floating Point Add to Accumulator
sfs_sft(def(IK::MSUBAS, "msuba.s")); // Floating Point Multiply and Subtract from Accumulator
// COP2 weirds
def_store(IK::SQC2, "sqc2")
.src(FT::FT, DT::VF)
.src(FT::SIMM16, DT::IMM)
.src_gpr(FT::RS); // Store Quadword from COP2
def_load(IK::LQC2, "lqc2")
.dst(FT::FT, DT::VF)
.src(FT::SIMM16, DT::IMM)
.src_gpr(FT::RS); // Load Quadword to COP2
// COP2
// NOTE: if adding more here, update AtomicOp.cpp AsmOp::update_register_info()
2020-08-22 23:30:17 -04:00
cd_dvft_svfs(def(IK::VMOVE, "vmove")); // Transfer between Floating-Point Registers
cd_dvft_svfs(def(IK::VFTOI0, "vftoi0")); // Conversion to Fixed Point
cd_dvft_svfs(def(IK::VFTOI4, "vftoi4")); // Conversion to Fixed Point
cd_dvft_svfs(def(IK::VFTOI12, "vftoi12")); // Conversion to Fixed Point
cd_dvft_svfs(def(IK::VFTOI15, "vftoi15")); // Conversion to Fixed Point
2020-08-22 23:30:17 -04:00
cd_dvft_svfs(def(IK::VITOF0, "vitof0")); // Conversion to Floating Point Number
cd_dvft_svfs(def(IK::VITOF12, "vitof12")); // Conversion to Floating Point Number
cd_dvft_svfs(def(IK::VITOF15, "vitof15")); // Conversion to Floating Point Number
cd_dvft_svfs(def(IK::VABS, "vabs")); // Absolute Value
cd_dvfd_svfs_svft(def(IK::VADD, "vadd"));
cd_dvfd_svfs_svft(def(IK::VSUB, "vsub"));
cd_dvfd_svfs_svft(def(IK::VMUL, "vmul"));
cd_dvfd_svfs_svft(def(IK::VMINI, "vmini"));
cd_dvfd_svfs_svft(def(IK::VMAX, "vmax"));
cd_dvfd_svfs_svft(def(IK::VOPMSUB, "vopmsub"));
cd_dvfd_svfs_svft(def(IK::VMADD, "vmadd"));
cd_dvfd_svfs_svft(def(IK::VMSUB, "vmsub"));
cb_cd_dvfd_svfs_svft(def(IK::VSUB_BC, "vsub"));
cb_cd_dvfd_svfs_svft(def(IK::VADD_BC, "vadd"));
cb_cd_dvfd_svfs_svft(def(IK::VMADD_BC, "vmadd"));
cb_cd_dvfd_svfs_svft(def(IK::VMSUB_BC, "vmsub"));
cb_cd_dvfd_svfs_svft(def(IK::VMUL_BC, "vmul"));
cb_cd_dvfd_svfs_svft(def(IK::VMINI_BC, "vmini"));
cb_cd_dvfd_svfs_svft(def(IK::VMAX_BC, "vmax"));
cb_cd_dacc_svfs_svft(def(IK::VADDA_BC, "vadda"));
cb_cd_dacc_svfs_svft(def(IK::VMADDA_BC, "vmadda"));
cb_cd_dacc_svfs_svft(def(IK::VMULA_BC, "vmula"));
cb_cd_dacc_svfs_svft(def(IK::VMSUBA_BC, "vmsuba"));
cd_dvfd_svfs_sq(def(IK::VADDQ, "vaddq"));
cd_dvfd_svfs_sq(def(IK::VSUBQ, "vsubq"));
cd_dvfd_svfs_sq(def(IK::VMULQ, "vmulq"));
cd_dvfd_svfs_sq(def(IK::VMSUBQ, "vmsubq"));
cd_dacc_svfs_svft(def(IK::VMULA, "vmula"));
cd_dacc_svfs_svft(def(IK::VADDA, "vadda"));
cd_dacc_svfs_svft(def(IK::VMADDA, "vmadda"));
cd_dacc_svfs_svft(def(IK::VMSUBA, "vmsuba"));
2020-08-22 23:30:17 -04:00
cd_dacc_svfs_svft(def(IK::VOPMULA, "vopmula"));
// weird
def(IK::VDIV, "vdiv")
.dst(FT::ZERO, DT::VU_Q)
.src_vf(FT::FS)
2021-02-13 12:05:50 -05:00
.src(FT::FS_F, DT::VF_F)
2020-08-22 23:30:17 -04:00
.src_vf(FT::FT)
2021-02-13 12:05:50 -05:00
.src(FT::FT_F, DT::VF_F);
2020-08-22 23:30:17 -04:00
def(IK::VRSQRT, "vrsqrt")
.dst(FT::ZERO, DT::VU_Q)
.src_vf(FT::FS)
2021-02-13 12:05:50 -05:00
.src(FT::FS_F, DT::VF_F)
2020-08-22 23:30:17 -04:00
.src_vf(FT::FT)
2021-02-13 12:05:50 -05:00
.src(FT::FT_F, DT::VF_F);
2020-08-22 23:30:17 -04:00
def(IK::VCLIP, "vclip").src(FT::DEST, DT::DEST).src_vf(FT::FS).src_vf(FT::FT);
def(IK::VMULAQ, "vmulaq")
.src(FT::DEST, DT::DEST)
.dst(FT::ZERO, DT::VU_ACC)
.src_vf(FT::FS)
.src(FT::ZERO, DT::VU_Q);
def(IK::VRGET, "vrget").src(FT::DEST, DT::DEST).dst_vf(FT::FT);
def(IK::VMR32, "vmr32").src(FT::DEST, DT::DEST).src_vf(FT::FT).dst_vf(FT::FS);
2020-08-22 23:30:17 -04:00
// integer
def(IK::VMTIR, "vmtir").dst(FT::RT, DT::VI).src_vf(FT::FS).src(FT::BC, DT::BC);
def(IK::VIAND, "viand").dst_vi(FT::FD).src_vi(FT::FS).src_vi(FT::FT);
def(IK::VLQI, "vlqi").src(FT::DEST, DT::DEST).dst_vf(FT::FT).src_vi(FT::FS); // todo inc
def(IK::VSQI, "vsqi").src(FT::DEST, DT::DEST).src_vf(FT::FS).src_vi(FT::FT); // todo inc
def(IK::VIADDI, "viaddi").dst_vi(FT::FT).src_vi(FT::FS).src(FT::IMM5, DT::IMM);
def(IK::QMFC2, "qmfc2").src(FT::IL, DT::IL).dst_gpr(FT::RT).src_vf(FT::FS);
def(IK::QMTC2, "qmtc2").src(FT::IL, DT::IL).dst_vf(FT::FS).src_gpr(FT::RT);
2021-02-13 12:05:50 -05:00
def(IK::VSQRT, "vsqrt").dst(FT::ZERO, DT::VU_Q).src_vf(FT::FT).src(FT::FT_F, DT::VF_F);
2020-08-22 23:30:17 -04:00
def(IK::VRXOR, "vrxor").src(FT::BC, DT::BC).src_vf(FT::FS);
def(IK::VRNEXT, "vrnext").src(FT::DEST, DT::DEST).dst_vf(FT::FT);
def(IK::CTC2, "ctc2").src(FT::IL, DT::IL).src_gpr(FT::RT).dst(FT::RD, DT::VI);
def(IK::CFC2, "cfc2").src(FT::IL, DT::IL).dst_gpr(FT::RT).src(FT::RD, DT::VI);
def(IK::VCALLMS, "vcallms").src(FT::IMM15, DT::VCALLMS_TARGET);
def(IK::VNOP, "vnop");
def(IK::VWAITQ, "vwaitq");
uint32_t valid_count = 0, total_count = 0;
for (auto& info : gOpcodeInfo) {
if (info.defined) {
valid_count++;
}
total_count++;
}
// for the UNKNOWN op which shouldn't be valid.
total_count--;
ASSERT(total_count == valid_count);
opcodes_initialized = true;
2020-08-22 23:30:17 -04:00
}
void OpcodeInfo::step(DecodeStep& s) {
ASSERT(step_count < MAX_DECODE_STEPS);
2020-08-22 23:30:17 -04:00
steps[step_count] = s;
step_count++;
defined = true;
}
OpcodeInfo& OpcodeInfo::src(FieldType field, DecodeType decode) {
DecodeStep new_step;
new_step.is_src = true;
new_step.field = field;
new_step.decode = decode;
step(new_step);
return *this;
}
OpcodeInfo& OpcodeInfo::src_gpr(FieldType field) {
return src(field, DT::GPR);
}
OpcodeInfo& OpcodeInfo::src_fpr(FieldType field) {
return src(field, DT::FPR);
}
OpcodeInfo& OpcodeInfo::src_vf(FieldType field) {
return src(field, DT::VF);
}
OpcodeInfo& OpcodeInfo::src_vi(FieldType field) {
return src(field, DT::VI);
}
OpcodeInfo& OpcodeInfo::dst(FieldType field, DecodeType decode) {
DecodeStep new_step;
new_step.is_src = false;
new_step.field = field;
new_step.decode = decode;
step(new_step);
return *this;
}
OpcodeInfo& OpcodeInfo::dst_gpr(FieldType field) {
return dst(field, DT::GPR);
}
OpcodeInfo& OpcodeInfo::dst_fpr(FieldType field) {
return dst(field, DT::FPR);
}
OpcodeInfo& OpcodeInfo::dst_vf(FieldType field) {
return dst(field, DT::VF);
}
OpcodeInfo& OpcodeInfo::dst_vi(FieldType field) {
return dst(field, DT::VI);
}
OpcodeInfo& OpcodeInfo::gpr128() {
gpr_128 = true;
return *this;
}
} // namespace decompiler