mirror of
https://github.com/ran-j/PS2Recomp.git
synced 2026-09-26 08:51:05 -04:00
feat: better decode and code gen (remove some old instruction)
This commit is contained in:
@@ -28,48 +28,66 @@ namespace ps2recomp
|
||||
std::string translateVUInstruction(const Instruction &inst);
|
||||
std::string translateFPUInstruction(const Instruction &inst);
|
||||
std::string translateCOP0Instruction(const Instruction &inst);
|
||||
std::string translateRegimmInstruction(const Instruction &inst);
|
||||
std::string translateSpecialInstruction(const Instruction &inst);
|
||||
|
||||
// MMI instruction translations
|
||||
// MMI Translation functions
|
||||
std::string translateMMI0Instruction(const Instruction &inst);
|
||||
std::string translateMMI1Instruction(const Instruction &inst);
|
||||
std::string translateMMI2Instruction(const Instruction &inst);
|
||||
std::string translateMMI3Instruction(const Instruction &inst);
|
||||
std::string translatePMFHLInstruction(const Instruction &inst);
|
||||
std::string translatePMTHLInstruction(const Instruction &inst);
|
||||
|
||||
// Instruction Helpers
|
||||
std::string translateQFSRV(const Instruction &inst);
|
||||
std::string translatePCPYLD(const Instruction &inst);
|
||||
std::string translatePCPYUD(const Instruction &inst);
|
||||
std::string translatePMADDW(const Instruction &inst);
|
||||
std::string translatePDIVW(const Instruction &inst);
|
||||
std::string translatePCPYLD(const Instruction &inst);
|
||||
std::string translatePMADDH(const Instruction &inst);
|
||||
std::string translatePHMADH(const Instruction &inst);
|
||||
std::string translatePMULTH(const Instruction &inst);
|
||||
std::string translatePDIVW(const Instruction &inst);
|
||||
std::string translatePDIVBW(const Instruction &inst);
|
||||
std::string translatePEXEH(const Instruction &inst);
|
||||
std::string translatePREVH(const Instruction &inst);
|
||||
std::string translatePMULTH(const Instruction &inst);
|
||||
std::string translatePDIVBW(const Instruction &inst);
|
||||
std::string translatePEXEW(const Instruction &inst);
|
||||
std::string translatePROT3W(const Instruction &inst);
|
||||
std::string translatePMULTUW(const Instruction &inst);
|
||||
std::string translatePDIVUW(const Instruction &inst);
|
||||
std::string translatePCPYUD(const Instruction &inst);
|
||||
std::string translatePEXCH(const Instruction &inst);
|
||||
std::string translatePCPYH(const Instruction &inst);
|
||||
std::string translatePEXCW(const Instruction &inst);
|
||||
std::string translatePMTHI(const Instruction &inst);
|
||||
std::string translatePMTLO(const Instruction &inst);
|
||||
|
||||
// SPECIAL instructions
|
||||
std::string translateSYNC(const Instruction &inst);
|
||||
std::string translateEI(const Instruction &inst);
|
||||
std::string translateDI(const Instruction &inst);
|
||||
std::string translateDSLL(const Instruction &inst);
|
||||
std::string translateDSRL(const Instruction &inst);
|
||||
std::string translateDSRA(const Instruction &inst);
|
||||
std::string translateDSLLV(const Instruction &inst);
|
||||
std::string translateDSRLV(const Instruction &inst);
|
||||
std::string translateDSRAV(const Instruction &inst);
|
||||
std::string translateDSLL32(const Instruction &inst);
|
||||
std::string translateDSRL32(const Instruction &inst);
|
||||
std::string translateDSRA32(const Instruction &inst);
|
||||
std::string translateDADD(const Instruction &inst);
|
||||
std::string translateDADDU(const Instruction &inst);
|
||||
std::string translateDSUB(const Instruction &inst);
|
||||
std::string translateDSUBU(const Instruction &inst);
|
||||
// VU instruction translations
|
||||
std::string translateVU_VADD_Field(const Instruction &inst);
|
||||
std::string translateVU_VSUB_Field(const Instruction &inst);
|
||||
std::string translateVU_VMUL_Field(const Instruction &inst);
|
||||
std::string translateVU_VADD(const Instruction &inst);
|
||||
std::string translateVU_VSUB(const Instruction &inst);
|
||||
std::string translateVU_VMUL(const Instruction &inst);
|
||||
std::string translateVU_VDIV(const Instruction &inst);
|
||||
std::string translateVU_VSQRT(const Instruction &inst);
|
||||
std::string translateVU_VRSQRT(const Instruction &inst);
|
||||
std::string translateVU_VMTIR(const Instruction &inst);
|
||||
std::string translateVU_VMFIR(const Instruction &inst);
|
||||
std::string translateVU_VILWR(const Instruction &inst);
|
||||
std::string translateVU_VISWR(const Instruction &inst);
|
||||
std::string translateVU_VIADD(const Instruction &inst);
|
||||
std::string translateVU_VISUB(const Instruction &inst);
|
||||
std::string translateVU_VIADDI(const Instruction &inst);
|
||||
std::string translateVU_VIAND(const Instruction &inst);
|
||||
std::string translateVU_VIOR(const Instruction &inst);
|
||||
std::string translateVU_VCALLMS(const Instruction &inst);
|
||||
std::string translateVU_VCALLMSR(const Instruction &inst);
|
||||
std::string translateVU_VRNEXT(const Instruction &inst);
|
||||
std::string translateVU_VRGET(const Instruction &inst);
|
||||
std::string translateVU_VRINIT(const Instruction &inst);
|
||||
std::string translateVU_VRXOR(const Instruction &inst);
|
||||
|
||||
//
|
||||
std::string generateJumpTableSwitch(const Instruction &inst, uint32_t tableAddress,
|
||||
const std::vector<JumpTableEntry> &entries);
|
||||
|
||||
|
||||
@@ -8,183 +8,221 @@ namespace ps2recomp
|
||||
// Basic MIPS opcodes (shared with R4300i)
|
||||
enum MipsOpcodes
|
||||
{
|
||||
OPCODE_SPECIAL = 0x00,
|
||||
OPCODE_REGIMM = 0x01,
|
||||
OPCODE_J = 0x02,
|
||||
OPCODE_JAL = 0x03,
|
||||
OPCODE_BEQ = 0x04,
|
||||
OPCODE_BNE = 0x05,
|
||||
OPCODE_BLEZ = 0x06,
|
||||
OPCODE_BGTZ = 0x07,
|
||||
OPCODE_ADDI = 0x08,
|
||||
OPCODE_ADDIU = 0x09,
|
||||
OPCODE_SLTI = 0x0A,
|
||||
OPCODE_SLTIU = 0x0B,
|
||||
OPCODE_ANDI = 0x0C,
|
||||
OPCODE_ORI = 0x0D,
|
||||
OPCODE_XORI = 0x0E,
|
||||
OPCODE_LUI = 0x0F,
|
||||
OPCODE_COP0 = 0x10,
|
||||
OPCODE_COP1 = 0x11,
|
||||
OPCODE_COP2 = 0x12, // VU0 macro instructions
|
||||
OPCODE_SPECIAL = 0x00, // Special instructions group (see SpecialFunctions)
|
||||
OPCODE_REGIMM = 0x01, // RegImm instructions group (see RegimmFunctions)
|
||||
OPCODE_J = 0x02, // Jump
|
||||
OPCODE_JAL = 0x03, // Jump and Link
|
||||
OPCODE_BEQ = 0x04, // Branch on Equal
|
||||
OPCODE_BNE = 0x05, // Branch on Not Equal
|
||||
OPCODE_BLEZ = 0x06, // Branch on Less Than or Equal to Zero
|
||||
OPCODE_BGTZ = 0x07, // Branch on Greater Than Zero
|
||||
|
||||
OPCODE_ADDI = 0x08, // Add Immediate Word
|
||||
OPCODE_ADDIU = 0x09, // Add Immediate Unsigned Word
|
||||
OPCODE_SLTI = 0x0A, // Set on Less Than Immediate
|
||||
OPCODE_SLTIU = 0x0B, // Set on Less Than Immediate Unsigned
|
||||
OPCODE_ANDI = 0x0C, // AND Immediate
|
||||
OPCODE_ORI = 0x0D, // OR Immediate
|
||||
OPCODE_XORI = 0x0E, // XOR Immediate
|
||||
OPCODE_LUI = 0x0F, // Load Upper Immediate
|
||||
|
||||
OPCODE_COP0 = 0x10, // Coprocessor 0 instructions (see Cop0Format)
|
||||
OPCODE_COP1 = 0x11, // Coprocessor 1 (FPU) instructions (see Cop1Format)
|
||||
OPCODE_COP2 = 0x12, // Coprocessor 2 (VU0 Macro) instructions (see Cop2Format)
|
||||
OPCODE_COP3 = 0x13, // Unused on PS2
|
||||
OPCODE_BEQL = 0x14,
|
||||
OPCODE_BNEL = 0x15,
|
||||
OPCODE_BLEZL = 0x16,
|
||||
OPCODE_BGTZL = 0x17,
|
||||
OPCODE_DADDI = 0x18,
|
||||
OPCODE_DADDIU = 0x19,
|
||||
OPCODE_LDL = 0x1A,
|
||||
OPCODE_LDR = 0x1B,
|
||||
OPCODE_MMI = 0x1C, // PS2 specific multimedia instructions
|
||||
OPCODE_LQ = 0x1E, // PS2 specific 128-bit load
|
||||
OPCODE_SQ = 0x1F, // PS2 specific 128-bit store
|
||||
OPCODE_LB = 0x20,
|
||||
OPCODE_LH = 0x21,
|
||||
OPCODE_LWL = 0x22,
|
||||
OPCODE_LW = 0x23,
|
||||
OPCODE_LBU = 0x24,
|
||||
OPCODE_LHU = 0x25,
|
||||
OPCODE_LWR = 0x26,
|
||||
OPCODE_LWU = 0x27,
|
||||
OPCODE_SB = 0x28,
|
||||
OPCODE_SH = 0x29,
|
||||
OPCODE_SWL = 0x2A,
|
||||
OPCODE_SW = 0x2B,
|
||||
OPCODE_SDL = 0x2C,
|
||||
OPCODE_SDR = 0x2D,
|
||||
OPCODE_SWR = 0x2E,
|
||||
OPCODE_CACHE = 0x2F,
|
||||
OPCODE_LL = 0x30,
|
||||
OPCODE_LWC1 = 0x31,
|
||||
OPCODE_LWC2 = 0x32,
|
||||
OPCODE_PREF = 0x33,
|
||||
OPCODE_LLD = 0x34,
|
||||
OPCODE_LDC1 = 0x35,
|
||||
OPCODE_LDC2 = 0x36,
|
||||
OPCODE_LD = 0x37,
|
||||
OPCODE_SC = 0x38,
|
||||
OPCODE_SWC1 = 0x39,
|
||||
OPCODE_SWC2 = 0x3A,
|
||||
OPCODE_SCD = 0x3C,
|
||||
OPCODE_SDC1 = 0x3D,
|
||||
OPCODE_SDC2 = 0x3E,
|
||||
OPCODE_SD = 0x3F,
|
||||
OPCODE_LQC2 = 0x36,
|
||||
OPCODE_SQC2 = 0x3E
|
||||
|
||||
OPCODE_BEQL = 0x14, // Branch on Equal Likely
|
||||
OPCODE_BNEL = 0x15, // Branch on Not Equal Likely
|
||||
OPCODE_BLEZL = 0x16, // Branch on Less Than or Equal to Zero Likely
|
||||
OPCODE_BGTZL = 0x17, // Branch on Greater Than Zero Likely
|
||||
|
||||
OPCODE_DADDI = 0x18, // Doubleword Add Immediate
|
||||
OPCODE_DADDIU = 0x19, // Doubleword Add Immediate Unsigned
|
||||
OPCODE_LDL = 0x1A, // Load Doubleword Left
|
||||
OPCODE_LDR = 0x1B, // Load Doubleword Right
|
||||
OPCODE_MMI = 0x1C, // PS2 specific MMI instructions group (see MMIFunctions)
|
||||
|
||||
OPCODE_LQ = 0x1E, // PS2 specific 128-bit load
|
||||
OPCODE_SQ = 0x1F, // PS2 specific 128-bit store
|
||||
|
||||
OPCODE_LB = 0x20, // Load Byte
|
||||
OPCODE_LH = 0x21, // Load Halfword
|
||||
OPCODE_LWL = 0x22, // Load Word Left
|
||||
OPCODE_LW = 0x23, // Load Word
|
||||
OPCODE_LBU = 0x24, // Load Byte Unsigned
|
||||
OPCODE_LHU = 0x25, // Load Halfword Unsigned
|
||||
OPCODE_LWR = 0x26, // Load Word Right
|
||||
OPCODE_LWU = 0x27, // Load Word Unsigned
|
||||
|
||||
OPCODE_SB = 0x28, // Store Byte
|
||||
OPCODE_SH = 0x29, // Store Halfword
|
||||
OPCODE_SWL = 0x2A, // Store Word Left
|
||||
OPCODE_SW = 0x2B, // Store Word
|
||||
OPCODE_SDL = 0x2C, // Store Doubleword Left
|
||||
OPCODE_SDR = 0x2D, // Store Doubleword Right
|
||||
OPCODE_SWR = 0x2E, // Store Word Right
|
||||
OPCODE_CACHE = 0x2F, // Cache Operation
|
||||
|
||||
OPCODE_LL = 0x30, // LL - Load Linked Word, maybe omitted/unused
|
||||
OPCODE_LWC1 = 0x31, // Load Word to Coprocessor 1 (FPU)
|
||||
OPCODE_LWC2 = 0x32, // Load Word to Coprocessor 2, maybe omitted/unused
|
||||
OPCODE_PREF = 0x33, // Prefetch
|
||||
OPCODE_LLD = 0x34, // Load Linked Doubleword, maybe omitted/unused
|
||||
OPCODE_LDC1 = 0x35, // Load Doubleword to Coprocessor 1, FPU is single-precision
|
||||
OPCODE_LDC2 = 0x36, // Load Quadword to Coprocessor 2 (VU0) - Overrides standard MIPS LDC2
|
||||
OPCODE_LD = 0x37, // Load Doubleword
|
||||
|
||||
OPCODE_SC = 0x38, // Store Conditional Word, maybe omitted/unused?
|
||||
OPCODE_SWC1 = 0x39, // Store Word from Coprocessor 1 (FPU)
|
||||
OPCODE_SWC2 = 0x3A, // SWC2 - Store Word from Coprocessor 2, maybe omitted/unused
|
||||
OPCODE_SCD = 0x3C, // SCD - Store Conditional Doubleword, maybe omitted/unused?
|
||||
OPCODE_SDC1 = 0x3D, // SDC1 - Store Doubleword from Coprocessor 1, FPU is single-precision
|
||||
OPCODE_SDC2 = 0x3E, // PS2 specific Store Quadword from Coprocessor 2 (VU0) - Overrides standard MIPS SDC2
|
||||
OPCODE_SD = 0x3F, // Store Doubleword
|
||||
|
||||
//OPCODE_LQC2 = 0x36,
|
||||
//OPCODE_SQC2 = 0x3E
|
||||
};
|
||||
|
||||
// SPECIAL function codes
|
||||
// SPECIAL Function (bits 5-0) for OPCODE_SPECIAL
|
||||
enum SpecialFunctions
|
||||
{
|
||||
SPECIAL_SLL = 0x00,
|
||||
SPECIAL_SRL = 0x02,
|
||||
SPECIAL_SRA = 0x03,
|
||||
SPECIAL_SLLV = 0x04,
|
||||
SPECIAL_SRLV = 0x06,
|
||||
SPECIAL_SRAV = 0x07,
|
||||
SPECIAL_JR = 0x08,
|
||||
SPECIAL_JALR = 0x09,
|
||||
SPECIAL_MOVZ = 0x0A,
|
||||
SPECIAL_MOVN = 0x0B,
|
||||
SPECIAL_SYSCALL = 0x0C,
|
||||
SPECIAL_BREAK = 0x0D,
|
||||
SPECIAL_SYNC = 0x0F,
|
||||
SPECIAL_MFHI = 0x10,
|
||||
SPECIAL_MTHI = 0x11,
|
||||
SPECIAL_MFLO = 0x12,
|
||||
SPECIAL_MTLO = 0x13,
|
||||
SPECIAL_DSLLV = 0x14,
|
||||
SPECIAL_DSRLV = 0x16,
|
||||
SPECIAL_DSRAV = 0x17,
|
||||
SPECIAL_MULT = 0x18,
|
||||
SPECIAL_MULTU = 0x19,
|
||||
SPECIAL_DIV = 0x1A,
|
||||
SPECIAL_DIVU = 0x1B,
|
||||
SPECIAL_ADD = 0x20,
|
||||
SPECIAL_ADDU = 0x21,
|
||||
SPECIAL_SUB = 0x22,
|
||||
SPECIAL_SUBU = 0x23,
|
||||
SPECIAL_AND = 0x24,
|
||||
SPECIAL_OR = 0x25,
|
||||
SPECIAL_XOR = 0x26,
|
||||
SPECIAL_NOR = 0x27,
|
||||
SPECIAL_MFSA = 0x28,
|
||||
SPECIAL_MTSA = 0x29,
|
||||
SPECIAL_SLT = 0x2A,
|
||||
SPECIAL_SLTU = 0x2B,
|
||||
SPECIAL_DADD = 0x2C,
|
||||
SPECIAL_DADDU = 0x2D,
|
||||
SPECIAL_DSUB = 0x2E,
|
||||
SPECIAL_DSUBU = 0x2F,
|
||||
SPECIAL_TGE = 0x30,
|
||||
SPECIAL_TGEU = 0x31,
|
||||
SPECIAL_TLT = 0x32,
|
||||
SPECIAL_TLTU = 0x33,
|
||||
SPECIAL_TEQ = 0x34,
|
||||
SPECIAL_TNE = 0x36,
|
||||
SPECIAL_DSLL = 0x38,
|
||||
SPECIAL_DSRL = 0x3A,
|
||||
SPECIAL_DSRA = 0x3B,
|
||||
SPECIAL_DSLL32 = 0x3C,
|
||||
SPECIAL_DSRL32 = 0x3E,
|
||||
SPECIAL_DSRA32 = 0x3F
|
||||
SPECIAL_SLL = 0x00, // Shift Word Left Logical
|
||||
|
||||
SPECIAL_SRL = 0x02, // Shift Word Right Logical
|
||||
SPECIAL_SRA = 0x03, // Shift Word Right Arithmetic
|
||||
SPECIAL_SLLV = 0x04, // Shift Word Left Logical Variable
|
||||
|
||||
SPECIAL_SRLV = 0x06, // Shift Word Right Logical Variable
|
||||
SPECIAL_SRAV = 0x07, // Shift Word Right Arithmetic Variable
|
||||
|
||||
SPECIAL_JR = 0x08, // Jump Register
|
||||
SPECIAL_JALR = 0x09, // Jump and Link Register
|
||||
SPECIAL_MOVZ = 0x0A, // Move Conditional on Zero
|
||||
SPECIAL_MOVN = 0x0B, // Move Conditional on Not Zero
|
||||
SPECIAL_SYSCALL = 0x0C, // System Call
|
||||
SPECIAL_BREAK = 0x0D, // Breakpoint
|
||||
|
||||
SPECIAL_SYNC = 0x0F, // Synchronize Shared Memory
|
||||
|
||||
SPECIAL_MFHI = 0x10, // Move From HI Register
|
||||
SPECIAL_MTHI = 0x11, // Move To HI Register
|
||||
SPECIAL_MFLO = 0x12, // Move From LO Register
|
||||
SPECIAL_MTLO = 0x13, // Move To LO Register
|
||||
SPECIAL_DSLLV = 0x14, // Doubleword Shift Left Logical Variable
|
||||
|
||||
SPECIAL_DSRLV = 0x16, // Doubleword Shift Right Logical Variable
|
||||
SPECIAL_DSRAV = 0x17, // Doubleword Shift Right Arithmetic Variable
|
||||
|
||||
SPECIAL_MULT = 0x18, // Multiply Word
|
||||
SPECIAL_MULTU = 0x19, // Multiply Unsigned Word
|
||||
SPECIAL_DIV = 0x1A, // Divide Word
|
||||
SPECIAL_DIVU = 0x1B, // Divide Unsigned Word
|
||||
|
||||
SPECIAL_ADD = 0x20, // Add Word
|
||||
SPECIAL_ADDU = 0x21, // Add Unsigned Word
|
||||
SPECIAL_SUB = 0x22, // Subtract Word
|
||||
SPECIAL_SUBU = 0x23, // Subtract Unsigned Word
|
||||
SPECIAL_AND = 0x24, // AND
|
||||
SPECIAL_OR = 0x25, // OR
|
||||
SPECIAL_XOR = 0x26, // XOR
|
||||
SPECIAL_NOR = 0x27, // NOR
|
||||
|
||||
SPECIAL_MFSA = 0x28, // Move From SA Register (PS2 specific)
|
||||
SPECIAL_MTSA = 0x29, // Move To SA Register (PS2 specific)
|
||||
SPECIAL_SLT = 0x2A, // Set on Less Than
|
||||
SPECIAL_SLTU = 0x2B, // Set on Less Than Unsigned
|
||||
SPECIAL_DADD = 0x2C, // Doubleword Add
|
||||
SPECIAL_DADDU = 0x2D, // Doubleword Add Unsigned
|
||||
SPECIAL_DSUB = 0x2E, // Doubleword Subtract
|
||||
SPECIAL_DSUBU = 0x2F, // Doubleword Subtract Unsigned
|
||||
|
||||
SPECIAL_TGE = 0x30, // Trap if Greater or Equal
|
||||
SPECIAL_TGEU = 0x31, // Trap if Greater or Equal Unsigned
|
||||
SPECIAL_TLT = 0x32, // Trap if Less Than
|
||||
SPECIAL_TLTU = 0x33, // Trap if Less Than Unsigned
|
||||
SPECIAL_TEQ = 0x34, // Trap if Equal
|
||||
|
||||
SPECIAL_TNE = 0x36, // Trap if Not Equal
|
||||
|
||||
SPECIAL_DSLL = 0x38, // Doubleword Shift Left Logical
|
||||
|
||||
SPECIAL_DSRL = 0x3A, // Doubleword Shift Right Logical
|
||||
SPECIAL_DSRA = 0x3B, // Doubleword Shift Right Arithmetic
|
||||
SPECIAL_DSLL32 = 0x3C, // Doubleword Shift Left Logical +32
|
||||
|
||||
SPECIAL_DSRL32 = 0x3E, // Doubleword Shift Right Logical +32
|
||||
SPECIAL_DSRA32 = 0x3F, // Doubleword Shift Right Arithmetic +32
|
||||
};
|
||||
|
||||
// REGIMM function codes
|
||||
// REGIMM RT Field (bits 20-16) for OPCODE_REGIMM
|
||||
enum RegimmFunctions
|
||||
{
|
||||
REGIMM_BLTZ = 0x00,
|
||||
REGIMM_BGEZ = 0x01,
|
||||
REGIMM_BLTZL = 0x02,
|
||||
REGIMM_BGEZL = 0x03,
|
||||
REGIMM_TGEI = 0x08,
|
||||
REGIMM_TGEIU = 0x09,
|
||||
REGIMM_TLTI = 0x0A,
|
||||
REGIMM_TLTIU = 0x0B,
|
||||
REGIMM_TEQI = 0x0C,
|
||||
REGIMM_TNEI = 0x0E,
|
||||
REGIMM_BLTZAL = 0x10,
|
||||
REGIMM_BGEZAL = 0x11,
|
||||
REGIMM_BLTZALL = 0x12,
|
||||
REGIMM_BGEZALL = 0x13,
|
||||
REGIMM_MTSAB = 0x18,
|
||||
REGIMM_MTSAH = 0x19
|
||||
REGIMM_BLTZ = 0x00, // Branch on Less Than Zero
|
||||
REGIMM_BGEZ = 0x01, // Branch on Greater Than or Equal to Zero
|
||||
REGIMM_BLTZL = 0x02, // Branch on Less Than Zero Likely
|
||||
REGIMM_BGEZL = 0x03, // Branch on Greater Than or Equal to Zero Likely
|
||||
|
||||
REGIMM_TGEI = 0x08, // Trap if Greater or Equal Immediate
|
||||
REGIMM_TGEIU = 0x09, // Trap if Greater or Equal Immediate Unsigned
|
||||
REGIMM_TLTI = 0x0A, // Trap if Less Than Immediate
|
||||
REGIMM_TLTIU = 0x0B, // Trap if Less Than Immediate Unsigned
|
||||
REGIMM_TEQI = 0x0C, // Trap if Equal Immediate
|
||||
|
||||
REGIMM_TNEI = 0x0E, // Trap if Not Equal Immediate
|
||||
|
||||
REGIMM_BLTZAL = 0x10, // Branch on Less Than Zero and Link
|
||||
REGIMM_BGEZAL = 0x11, // Branch on Greater Than or Equal to Zero and Link
|
||||
REGIMM_BLTZALL = 0x12, // Branch on Less Than Zero and Link Likely
|
||||
REGIMM_BGEZALL = 0x13, // Branch on Greater Than or Equal to Zero and Link Likely
|
||||
|
||||
REGIMM_MTSAB = 0x18, // Move To SA Register Byte (PS2 specific)
|
||||
REGIMM_MTSAH = 0x19, // Move To SA Register Halfword (PS2 specific)
|
||||
};
|
||||
|
||||
// PS2-specific MMI function codes
|
||||
// MMI Function Field (bits 5-0) for OPCODE_MMI (0x1C)
|
||||
enum MMIFunctions
|
||||
{
|
||||
MMI_MADD = 0x00,
|
||||
MMI_MADDU = 0x01,
|
||||
MMI_PLZCW = 0x04,
|
||||
MMI_MMI0 = 0x08,
|
||||
MMI_MMI2 = 0x09,
|
||||
MMI_MFHI1 = 0x10,
|
||||
MMI_MTHI1 = 0x11,
|
||||
MMI_MFLO1 = 0x12,
|
||||
MMI_MTLO1 = 0x13,
|
||||
MMI_MULT1 = 0x18,
|
||||
MMI_MULTU1 = 0x19,
|
||||
MMI_DIV1 = 0x1A,
|
||||
MMI_DIVU1 = 0x1B,
|
||||
MMI_MADD1 = 0x20,
|
||||
MMI_MADDU1 = 0x21,
|
||||
MMI_MMI1 = 0x28,
|
||||
MMI_MMI3 = 0x29,
|
||||
MMI_PMFHL = 0x30,
|
||||
MMI_PMTHL = 0x31,
|
||||
MMI_PSLLH = 0x34,
|
||||
MMI_PSRLH = 0x36,
|
||||
MMI_PSRAH = 0x37,
|
||||
MMI_PSLLW = 0x3C,
|
||||
MMI_PSRLW = 0x3E,
|
||||
MMI_PSRAW = 0x3F,
|
||||
MMI_MSUB = 0x02,
|
||||
MMI_MSUBU = 0x03
|
||||
MMI_MADD = 0x00, // Multiply Add Word (to LO/HI)
|
||||
MMI_MADDU = 0x01, // Multiply Add Unsigned Word (to LO/HI)
|
||||
MMI_MSUB = 0x02, // Multiply Subtract Word (Not listed in provided doc table, but valid MMI)
|
||||
MMI_MSUBU = 0x03, // Multiply Subtract Unsigned Word (Not listed in provided doc table, but valid MMI)
|
||||
MMI_PLZCW = 0x04, // Parallel Leading Zero/One Count Word
|
||||
|
||||
MMI_MMI0 = 0x08, // Group MMI0 instructions (see MMI0Functions)
|
||||
MMI_MMI2 = 0x09, // Group MMI2 instructions (see MMI2Functions)
|
||||
|
||||
MMI_MFHI1 = 0x10, // Move From HI1 Register
|
||||
MMI_MTHI1 = 0x11, // Move To HI1 Register
|
||||
MMI_MFLO1 = 0x12, // Move From LO1 Register
|
||||
MMI_MTLO1 = 0x13, // Move To LO1 Register
|
||||
|
||||
MMI_MULT1 = 0x18, // Multiply Word to LO1/HI1
|
||||
MMI_MULTU1 = 0x19, // Multiply Unsigned Word to LO1/HI1
|
||||
MMI_DIV1 = 0x1A, // Divide Word using LO1/HI1
|
||||
MMI_DIVU1 = 0x1B, // Divide Unsigned Word using LO1/HI1
|
||||
|
||||
MMI_MADD1 = 0x20, // Multiply Add Word to LO1/HI1
|
||||
MMI_MADDU1 = 0x21, // Multiply Add Unsigned Word to LO1/HI1
|
||||
|
||||
MMI_MMI1 = 0x28, // Group MMI1 instructions (see MMI1Functions)
|
||||
MMI_MMI3 = 0x29, // Group MMI3 instructions (see MMI3Functions)
|
||||
|
||||
MMI_PMFHL = 0x30, // Parallel Move From HI/LO Register (see PMFHLFunctions for 'sa' field)
|
||||
MMI_PMTHL = 0x31, // Parallel Move To HI/LO Register (see PMFHLFunctions for 'sa' field)
|
||||
|
||||
MMI_PSLLH = 0x34, // Parallel Shift Left Logical Halfword
|
||||
|
||||
MMI_PSRLH = 0x36, // Parallel Shift Right Logical Halfword
|
||||
MMI_PSRAH = 0x37, // Parallel Shift Right Arithmetic Halfword
|
||||
|
||||
MMI_PSLLW = 0x3C, // Parallel Shift Left Logical Word
|
||||
|
||||
MMI_PSRLW = 0x3E, // Parallel Shift Right Logical Word
|
||||
MMI_PSRAW = 0x3F // Parallel Shift Right Arithmetic Word
|
||||
};
|
||||
|
||||
// PS2-specific MMI0 function codes
|
||||
// PS2-specific MMI0 Sub-Function Field (bits 0-5 within MMI_MMI0 group)
|
||||
enum MMI0Functions
|
||||
{
|
||||
MMI0_PADDW = 0x00,
|
||||
@@ -214,7 +252,7 @@ namespace ps2recomp
|
||||
MMI0_PPAC5 = 0x1F
|
||||
};
|
||||
|
||||
// PS2-specific MMI1 function codes
|
||||
// PS2-specific MMI1 Sub-Function Field (bits 0-5 within MMI_MMI1 group)
|
||||
enum MMI1Functions
|
||||
{
|
||||
MMI1_PABSW = 0x01,
|
||||
@@ -237,7 +275,7 @@ namespace ps2recomp
|
||||
MMI1_QFSRV = 0x1B
|
||||
};
|
||||
|
||||
// PS2-specific MMI2 function codes
|
||||
// PS2-specific MMI2 Sub-Function Field (bits 0-5 within MMI_MMI2 group)
|
||||
enum MMI2Functions
|
||||
{
|
||||
MMI2_PMADDW = 0x00,
|
||||
@@ -248,14 +286,12 @@ namespace ps2recomp
|
||||
MMI2_PMFLO = 0x09,
|
||||
MMI2_PINTH = 0x0A,
|
||||
MMI2_PMULTW = 0x0C,
|
||||
MMI2_PDIVW = 0x0D,
|
||||
MMI2_PDIVW = 0x0D,
|
||||
MMI2_PCPYLD = 0x0E,
|
||||
MMI2_PAND = 0x12,
|
||||
MMI2_PXOR = 0x13,
|
||||
MMI2_PMADDH = 0x14,
|
||||
MMI2_PHMADH = 0x15,
|
||||
MMI2_PAND_ = 0x16,
|
||||
MMI2_PXOR_ = 0x17,
|
||||
MMI2_PMSUBH = 0x18,
|
||||
MMI2_PHMSBH = 0x19,
|
||||
MMI2_PEXEH = 0x1A,
|
||||
@@ -266,11 +302,13 @@ namespace ps2recomp
|
||||
MMI2_PROT3W = 0x1F
|
||||
};
|
||||
|
||||
// PS2-specific MMI3 function codes
|
||||
// PS2-specific MMI3 Sub-Function Field (bits 0-5 within MMI_MMI3 group)
|
||||
enum MMI3Functions
|
||||
{
|
||||
MMI3_PMADDUW = 0x00,
|
||||
MMI3_PSRAVW = 0x03,
|
||||
MMI3_PMTHI = 0x08, // Move To HI register
|
||||
MMI3_PMTLO = 0x09, // Move To LO register
|
||||
MMI3_PINTEH = 0x0A,
|
||||
MMI3_PMULTUW = 0x0C,
|
||||
MMI3_PDIVUW = 0x0D,
|
||||
@@ -279,195 +317,382 @@ namespace ps2recomp
|
||||
MMI3_PNOR = 0x13,
|
||||
MMI3_PEXCH = 0x1A,
|
||||
MMI3_PCPYH = 0x1B,
|
||||
MMI3_PEXCW = 0x1E,
|
||||
MMI3_PMTHI = 0x08, // Move To HI register
|
||||
MMI3_PMTLO = 0x09 // Move To LO register
|
||||
MMI3_PEXCW = 0x1E
|
||||
};
|
||||
|
||||
// COP0 (rs field)
|
||||
// PMFHL/PMTHL Sub-Function Field ('sa' field, bits 10-6)
|
||||
enum PMFHLFunctions
|
||||
{
|
||||
PMFHL_LW = 0x00, // Load Word / Lower Word
|
||||
PMFHL_UW = 0x01, // Upper Word
|
||||
PMFHL_SLW = 0x02, // Signed Lower Word
|
||||
PMFHL_LH = 0x03, // Load Halfword / Lower Halfword
|
||||
PMFHL_SH = 0x04 // Store Halfword / Signed Upper Halfword? (Doc name varies)
|
||||
};
|
||||
|
||||
// COP0 Format Field ('fmt' or 'rs' field, bits 25-21) for OPCODE_COP0
|
||||
enum COP0Format
|
||||
{
|
||||
COP0_MF = 0x00, // Move From COP0
|
||||
COP0_MT = 0x04, // Move To COP0
|
||||
COP0_CO = 0x10 // COP0 operation
|
||||
COP0_MF = 0x00, // Move From COP0 - MFC0 (fmt=00000)
|
||||
COP0_MT = 0x04, // Move To COP0 - MTC0 (fmt=00100)
|
||||
COP0_BC = 0x08, // BC0 group (fmt=01000) (see Cop0BranchCondition)
|
||||
COP0_CO = 0x10 // COP0 Operation group (fmt=10000) (see Cop0CoFunctions)
|
||||
};
|
||||
|
||||
// COP0 CO (COProcessor) function codes
|
||||
// COP0 CO Function Field (bits 5-0) for COP0_CO Format
|
||||
enum Cop0CoFunctions
|
||||
{
|
||||
COP0_CO_TLBR = 0x01, // TLB Read
|
||||
COP0_CO_TLBWI = 0x02, // TLB Write Indexed
|
||||
|
||||
COP0_CO_TLBWR = 0x06, // TLB Write Random
|
||||
COP0_CO_TLBP = 0x08, // TLB Probe
|
||||
COP0_CO_ERET = 0x18, // Return from Exception
|
||||
COP0_CO_EI = 0x38, // Enable Interrupts
|
||||
COP0_CO_DI = 0x39 // Disable Interrupts
|
||||
|
||||
COP0_CO_TLBP = 0x08, // TLB Probe
|
||||
|
||||
COP0_CO_ERET = 0x18, // Return from Exception
|
||||
|
||||
COP0_CO_EI = 0x38, // Enable Interrupts
|
||||
COP0_CO_DI = 0x39 // Disable Interrupts
|
||||
};
|
||||
|
||||
// COP0 BC Condition Field ('fmt' or 'rt' field, bits 20-16) for COP0_BC Format
|
||||
enum Cop0BranchCondition
|
||||
{
|
||||
COP0_BC_BCF = 0x00, // Branch on Condition False
|
||||
COP0_BC_BCT = 0x01, // Branch on Condition True
|
||||
COP0_BC_BCFL = 0x02, // Branch on Condition False Likely
|
||||
COP0_BC_BCTL = 0x03, // Branch on Condition True Likely
|
||||
};
|
||||
|
||||
// COP0 Register Numbers (used with MFC0/MTC0)
|
||||
enum COP0Reg
|
||||
{
|
||||
COP0_REG_INDEX = 0, // Index into TLB array
|
||||
COP0_REG_RANDOM = 1, // Randomly generated index into TLB array
|
||||
COP0_REG_ENTRYLO0 = 2, // Low half of TLB entry for even-numbered virtual pages
|
||||
COP0_REG_ENTRYLO1 = 3, // Low half of TLB entry for odd-numbered virtual pages
|
||||
COP0_REG_CONTEXT = 4, // TLB miss handler pointer
|
||||
COP0_REG_PAGEMASK = 5, // TLB page size mask
|
||||
COP0_REG_WIRED = 6, // Controls which TLB entries are affected by random replacement
|
||||
COP0_REG_BADVADDR = 8, // Virtual address of most recent address-related exception
|
||||
COP0_REG_COUNT = 9, // Timer count
|
||||
COP0_REG_ENTRYHI = 10, // High half of TLB entry
|
||||
COP0_REG_COMPARE = 11, // Timer compare value
|
||||
COP0_REG_STATUS = 12, // Processor status and control
|
||||
COP0_REG_CAUSE = 13, // Cause of last exception
|
||||
COP0_REG_EPC = 14, // Exception program counter
|
||||
COP0_REG_PRID = 15, // Processor identification and revision
|
||||
COP0_REG_CONFIG = 16, // Configuration register
|
||||
COP0_REG_INDEX = 0, // Index into TLB array
|
||||
COP0_REG_RANDOM = 1, // Randomly generated index into TLB array
|
||||
COP0_REG_ENTRYLO0 = 2, // Low half of TLB entry for even-numbered virtual pages
|
||||
COP0_REG_ENTRYLO1 = 3, // Low half of TLB entry for odd-numbered virtual pages
|
||||
COP0_REG_CONTEXT = 4, // Context
|
||||
COP0_REG_PAGEMASK = 5, // TLB page size mask
|
||||
COP0_REG_WIRED = 6, // Controls which TLB entries are affected by random replacement
|
||||
|
||||
COP0_REG_BADVADDR = 8, // Virtual address of most recent address-related exception
|
||||
COP0_REG_COUNT = 9, // Timer count
|
||||
COP0_REG_ENTRYHI = 10, // High half of TLB entry
|
||||
COP0_REG_COMPARE = 11, // Timer compare value
|
||||
COP0_REG_STATUS = 12, // Processor status and control
|
||||
COP0_REG_CAUSE = 13, // Cause of last exception
|
||||
COP0_REG_EPC = 14, // Exception program counter
|
||||
COP0_REG_PRID = 15, // Processor identification and revision
|
||||
COP0_REG_CONFIG = 16, // Configuration register
|
||||
|
||||
COP0_REG_BADPADDR = 23, // Bad physical address
|
||||
COP0_REG_DEBUG = 24, // Debug register
|
||||
COP0_REG_PERF = 25, // Performance counter
|
||||
COP0_REG_TAGLO = 28, // Low bits of cache tag
|
||||
COP0_REG_TAGHI = 29, // High bits of cache tag
|
||||
COP0_REG_ERROREPC = 30 // Error exception program counter
|
||||
|
||||
COP0_REG_TAGLO = 28, // Cache TagLo (I-Cache & D-Cache)
|
||||
COP0_REG_TAGHI = 29, // High bits of cache tag ( Cache TagHi )
|
||||
COP0_REG_ERROREPC = 30 // Error exception program counter
|
||||
};
|
||||
|
||||
// COP1 (FPU) function codes
|
||||
// COP1 (FPU) Format Field ('fmt' or 'rs' field, bits 25-21) for OPCODE_COP1
|
||||
enum Cop1Format
|
||||
{
|
||||
COP1_MF = 0x00, // Move From FPU Register
|
||||
COP1_CF = 0x02, // Move From FPU Control Register
|
||||
COP1_MT = 0x04, // Move To FPU Register
|
||||
COP1_CT = 0x06, // Move To FPU Control Register
|
||||
COP1_BC = 0x08, // Branch on FPU Condition
|
||||
COP1_S = 0x10, // Single Precision Operation
|
||||
COP1_W = 0x14, // Word (integer) Operation
|
||||
COP1_BC_BCF = 0x00,
|
||||
COP1_BC_BCT = 0x01,
|
||||
COP1_L = 0x15, // Long (64-bit integer) Operation
|
||||
COP1_D = 0x11, // Double Precision Operation (unused on PS2 FPU?)
|
||||
COP1_BC = 0x08, // Branch on FPU Condition (see Cop1BranchCondition)
|
||||
|
||||
COP1_D = 0x11, // Standard MIPS Double format; EE FPU is single-precision, (unused on PS2 FPU?)
|
||||
COP1_L = 0x15, // Long (64-bit integer) Operation (unused on PS2 FPU?)
|
||||
|
||||
COP1_S = 0x10, // Single Precision Operation (see Cop1FunctionsS)
|
||||
COP1_W = 0x14 // Word (integer) Operation (see Cop1FunctionsW)
|
||||
};
|
||||
|
||||
enum Cop1Functions
|
||||
// COP1 Function Field (bits 5-0) for COP1_S Format (Single-Precision)
|
||||
enum Cop1FunctionsS
|
||||
{
|
||||
COP1_FUNC_ADD = 0x00,
|
||||
COP1_FUNC_SUB = 0x01,
|
||||
COP1_FUNC_MUL = 0x02,
|
||||
COP1_FUNC_DIV = 0x03,
|
||||
COP1_FUNC_SQRT = 0x04,
|
||||
COP1_FUNC_ABS = 0x05,
|
||||
COP1_FUNC_MOV = 0x06,
|
||||
COP1_FUNC_NEG = 0x07,
|
||||
COP1_FUNC_ROUND_L = 0x08,
|
||||
COP1_FUNC_TRUNC_L = 0x09,
|
||||
COP1_FUNC_CEIL_L = 0x0A,
|
||||
COP1_FUNC_FLOOR_L = 0x0B,
|
||||
COP1_FUNC_ROUND_W = 0x0C,
|
||||
COP1_FUNC_TRUNC_W = 0x0D,
|
||||
COP1_FUNC_CEIL_W = 0x0E,
|
||||
COP1_FUNC_FLOOR_W = 0x0F,
|
||||
COP1_FUNC_CVT_S = 0x20, // Convert to Single
|
||||
COP1_FUNC_CVT_D = 0x21, // Convert to Double
|
||||
COP1_FUNC_CVT_W = 0x24, // Convert to Word
|
||||
COP1_FUNC_CVT_L = 0x25, // Convert to Long
|
||||
// Comparisons (lowest 5 bits matter for condition, C bit set in FCR31)
|
||||
COP1_FUNC_C_F = 0x30, // False
|
||||
COP1_FUNC_C_UN = 0x31, // Unordered
|
||||
COP1_FUNC_C_EQ = 0x32, // Equal
|
||||
COP1_FUNC_C_UEQ = 0x33, // Unordered or Equal
|
||||
COP1_FUNC_C_OLT = 0x34, // Ordered Less Than
|
||||
COP1_FUNC_C_ULT = 0x35, // Unordered or Less Than
|
||||
COP1_FUNC_C_OLE = 0x36, // Ordered Less Than or Equal
|
||||
COP1_FUNC_C_ULE = 0x37, // Unordered or Less Than or Equal
|
||||
COP1_FUNC_C_SF = 0x38, // Signaling False
|
||||
COP1_FUNC_C_NGLE = 0x39, // Not Greater or Less or Equal (Unordered)
|
||||
COP1_FUNC_C_SEQ = 0x3A, // Signaling Equal
|
||||
COP1_FUNC_C_NGL = 0x3B, // Not Greater or Less (Unordered or Equal)
|
||||
COP1_FUNC_C_LT = 0x3C, // Signaling Less Than
|
||||
COP1_FUNC_C_NGE = 0x3D, // Not Greater or Equal (Unordered or Less Than)
|
||||
COP1_FUNC_C_LE = 0x3E, // Signaling Less Than or Equal
|
||||
COP1_FUNC_C_NGT = 0x3F, // Not Greater Than (Unordered or Less Than or Equal)
|
||||
COP1_S_ADD = 0x00, // ADD.S
|
||||
COP1_S_SUB = 0x01, // SUB.S
|
||||
COP1_S_MUL = 0x02, // MUL.S
|
||||
COP1_S_DIV = 0x03, // DIV.S
|
||||
COP1_S_SQRT = 0x04, // SQRT.S
|
||||
COP1_S_ABS = 0x05, // ABS.S
|
||||
COP1_S_MOV = 0x06, // MOV.S
|
||||
COP1_S_NEG = 0x07, // NEG.S
|
||||
|
||||
COP1_S_ROUND_L = 0x08, // ROUND.L.S - Requires 64-bit int dest, likely unused
|
||||
COP1_S_TRUNC_L = 0x09, // TRUNC.L.S - Requires 64-bit int dest, likely unused
|
||||
COP1_S_CEIL_L = 0x0A, // CEIL.L.S - Requires 64-bit int dest, likely unused
|
||||
COP1_S_FLOOR_L = 0x0B, // FLOOR.L.S - Requires 64-bit int dest, likely unused
|
||||
COP1_S_ROUND_W = 0x0C, // ROUND.W.S
|
||||
COP1_S_TRUNC_W = 0x0D, // TRUNC.W.S
|
||||
COP1_S_CEIL_W = 0x0E, // CEIL.W.S
|
||||
COP1_S_FLOOR_W = 0x0F, // FLOOR.W.S
|
||||
|
||||
// --- Additional Arithmetic/Functions (from FPU.S table) ---
|
||||
COP1_S_RSQRT = 0x16, // RSQRT.S (Reciprocal Square Root)
|
||||
COP1_S_ADDA = 0x18, // ADDA.S (Add Accumulator)
|
||||
COP1_S_SUBA = 0x19, // SUBA.S (Subtract Accumulator)
|
||||
COP1_S_MULA = 0x1A, // MULA.S (Multiply Accumulator)
|
||||
COP1_S_MADD = 0x1C, // MADD.S (Multiply Add)
|
||||
COP1_S_MSUB = 0x1D, // MSUB.S (Multiply Subtract)
|
||||
COP1_S_MADDA = 0x1E, // MADDA.S (Multiply Add Accumulator)
|
||||
COP1_S_MSUBA = 0x1F, // MSUBA.S (Multiply Subtract Accumulator)
|
||||
|
||||
// --- Conversions (from FPU.S table) ---
|
||||
COP1_S_CVT_D = 0x21, // CVT.D.S - Requires double-precision FPU
|
||||
COP1_S_CVT_W = 0x24, // CVT.W.S (Convert to Word)
|
||||
COP1_S_CVT_L = 0x25, // CVT.L.S - Requires 64-bit int dest, likely unused
|
||||
|
||||
// --- Min/Max (from FPU.S table) ---
|
||||
COP1_S_MAX = 0x28, // MAX.S
|
||||
COP1_S_MIN = 0x29, // MIN.S
|
||||
|
||||
COP1_S_C_F = 0x30, // C.F.S (False)
|
||||
COP1_S_C_UN = 0x31, // C.UN.S (Unordered)
|
||||
COP1_S_C_EQ = 0x32, // C.EQ.S (Equal)
|
||||
COP1_S_C_UEQ = 0x33, // C.UEQ.S (Unordered or Equal)
|
||||
COP1_S_C_OLT = 0x34, // C.OLT.S (Ordered Less Than)
|
||||
COP1_S_C_ULT = 0x35, // C.ULT.S (Unordered or Less Than)
|
||||
COP1_S_C_OLE = 0x36, // C.OLE.S (Ordered Less Than or Equal)
|
||||
COP1_S_C_ULE = 0x37, // C.ULE.S (Unordered or Less Than or Equal)
|
||||
COP1_S_C_SF = 0x38, // C.SF.S (Signaling False)
|
||||
COP1_S_C_NGLE = 0x39, // C.NGLE.S (Not Greater or Less or Equal - Unordered)
|
||||
COP1_S_C_SEQ = 0x3A, // C.SEQ.S (Signaling Equal)
|
||||
COP1_S_C_NGL = 0x3B, // C.NGL.S (Not Greater or Less - Unordered or Equal)
|
||||
COP1_S_C_LT = 0x3C, // C.LT.S (Signaling Less Than)
|
||||
COP1_S_C_NGE = 0x3D, // C.NGE.S (Not Greater or Equal - Unordered or Less Than)
|
||||
COP1_S_C_LE = 0x3E, // C.LE.S (Signaling Less Than or Equal)
|
||||
COP1_S_C_NGT = 0x3F, // C.NGT.S (Not Greater Than - Unordered or Less Than or Equal)
|
||||
};
|
||||
|
||||
// COP2 (VU0 macro) function codes
|
||||
enum Cop2Functions
|
||||
// COP1 Function Field (bits 5-0) for COP1_W Format (Word/Integer source)
|
||||
enum Cop1FunctionsW
|
||||
{
|
||||
COP2_QMFC2 = 0x00, // Move From Coprocessor 2 (128-bit)
|
||||
COP2_CFC2 = 0x02, // Move Control From Coprocessor 2
|
||||
COP2_QMTC2 = 0x04, // Move To Coprocessor 2 (128-bit)
|
||||
COP2_CTC2 = 0x06, // Move Control To Coprocessor 2
|
||||
COP2_BC2 = 0x08, // Branch On Coprocessor 2 Condition
|
||||
COP2_CO = 0x10, // COProcessor instructions (VU0 macro)
|
||||
COP2_BCF = 0x00, // Branch on VU0 false
|
||||
COP2_BCT = 0x01, // Branch on VU0 true
|
||||
COP2_BCFL = 0x02, // Branch on VU0 false likely
|
||||
COP2_BCTL = 0x03, // Branch on VU0 true likely
|
||||
COP2_BCEF = 0x4, // Branch on VU0 equal flag false (new)
|
||||
COP2_BCET = 0x5, // Branch on VU0 equal flag true (new)
|
||||
COP2_BCEFL = 0x6, // Branch on VU0 equal flag false likely (new)
|
||||
COP2_BCETL = 0x7, // Branch on VU0 equal flag true likely (new)
|
||||
COP2_MFC2 = 0x02,
|
||||
COP2_MTC2 = 0x0A,
|
||||
COP2_BC2F = 0x11, // Branch on VU0 condition false
|
||||
COP2_VU0OPS = 0x12, // VU0 Special Operations
|
||||
COP2_MTVUCF = 0x13, // Move To VU0 control/flag register
|
||||
COP2_CTCVU = 0x18, // Control To VU0 with specific functionality
|
||||
COP2_VMTIR = 0x1C, // Move To VU0 I Register
|
||||
COP2_VCLIP = 0x1E, // VU0 Clipping operation
|
||||
COP2_VLDQ = 0x1F // VU0 Load/Store Quad with Decrement
|
||||
COP1_W_CVT_S = 0x20, // CVT.S.W (Convert Word Integer to Single Float)
|
||||
// 0x21 --- (Standard MIPS: CVT.D.W - requires double-precision)
|
||||
// 0x24 --- (Standard MIPS: CVT.W.W - Nop?)
|
||||
// 0x25 --- (Standard MIPS: CVT.L.W - requires 64-bit int dest)
|
||||
};
|
||||
|
||||
// VU0 macro instruction function codes (subset - there are many more)
|
||||
enum VU0MacroFunctions
|
||||
// COP1 BC Condition Field ('fmt' or 'rt' field, bits 20-16) for COP1_BC Format
|
||||
enum Cop1BranchCondition
|
||||
{
|
||||
VU0_VADD = 0x00,
|
||||
VU0_VSUB = 0x01,
|
||||
VU0_VMUL = 0x02,
|
||||
VU0_VDIV = 0x03,
|
||||
VU0_VSQRT = 0x04,
|
||||
VU0_VRSQRT = 0x05,
|
||||
VU0_VMULQ = 0x06,
|
||||
VU0_VIADD = 0x10,
|
||||
VU0_VISUB = 0x11,
|
||||
VU0_VIADDI = 0x12,
|
||||
VU0_VIAND = 0x13,
|
||||
VU0_VIOR = 0x14,
|
||||
VU0_VILWR = 0x15,
|
||||
VU0_VISWR = 0x16,
|
||||
VU0_VCALLMS = 0x20,
|
||||
VU0_VCALLMSR = 0x21,
|
||||
VU0_VRGET = 0x3F, // Get VU0 R register
|
||||
VU0_VSUB_XYZ = 0x38 // Subtract with component selection
|
||||
COP1_BC_BCF = 0x00, // Branch on FPU Condition False (BC1F)
|
||||
COP1_BC_BCT = 0x01, // Branch on FPU Condition True (BC1T)
|
||||
COP1_BC_BCFL = 0x02, // Branch on FPU Condition False Likely (BC1FL)
|
||||
COP1_BC_BCTL = 0x03, // Branch on FPU Condition True Likely (BC1TL)
|
||||
};
|
||||
|
||||
enum VU0SpecialFormats
|
||||
// COP2 (VU0 Macro) Format Field ('fmt' or 'rs' field, bits 25-21) for OPCODE_COP2
|
||||
enum Cop2Format
|
||||
{
|
||||
VU0_BC2F = 0x11, // Branch on VU0 condition false
|
||||
VU0_MTVUCF = 0x13, // Move To VU0 control/flag register
|
||||
VU0_CTCVU = 0x18, // Control To VU0 with specific functionality
|
||||
VU0_VMTIR = 0x1C, // Move To VU0 I Register
|
||||
VU0_VCLIP = 0x1E, // VU0 Clipping operation
|
||||
VU0_VLDQ = 0x1F // VU0 Load/Store Quad with Decrement
|
||||
// Note: Standard MIPS MFC2/MTC2 use fmt 0x00/0x04, EE uses QMFC2/QMTC2
|
||||
COP2_QMFC2 = 0x01, // QMFC2 (fmt=00001) - Load Quadword From Coprocessor 2
|
||||
COP2_CFC2 = 0x02, // CFC2 (fmt=00010) - Load Control Word From Coprocessor 2
|
||||
COP2_QMTC2 = 0x05, // QMTC2 (fmt=00101) - Store Quadword To Coprocessor 2
|
||||
COP2_CTC2 = 0x06, // CTC2 (fmt=00110) - Store Control Word To Coprocessor 2
|
||||
COP2_BC = 0x08, // BC2 group (fmt=01000) (see Cop2BranchCondition)
|
||||
COP2_CO = 0x10, // VU0 Macro Operation group (fmt=1xxxx)
|
||||
};
|
||||
|
||||
// COP2 BC Condition Field ('fmt' or 'rt' field, bits 20-16) for COP2_BC Format
|
||||
enum Cop2BranchCondition
|
||||
{
|
||||
COP2_BC_BCF = 0x00, // Branch on VU0 Condition False (BC2F)
|
||||
COP2_BC_BCT = 0x01, // Branch on VU0 Condition True (BC2T)
|
||||
COP2_BC_BCFL = 0x02, // Branch on VU0 Condition False Likely (BC2FL)
|
||||
COP2_BC_BCTL = 0x03, // Branch on VU0 Condition True Likely (BC2TL)
|
||||
};
|
||||
|
||||
// VU0 Macro Function Field (bits 5-0) for COP2_CO Format (Special1 Table)
|
||||
enum VU0MacroSpecial1Functions : uint8_t
|
||||
{
|
||||
VU0_S1_VADDx = 0x00,
|
||||
VU0_S1_VADDy = 0x01,
|
||||
VU0_S1_VADDz = 0x02,
|
||||
VU0_S1_VADDw = 0x03,
|
||||
VU0_S1_VSUBx = 0x04,
|
||||
VU0_S1_VSUBy = 0x05,
|
||||
VU0_S1_VSUBz = 0x06,
|
||||
VU0_S1_VSUBw = 0x07,
|
||||
VU0_S1_VMADDx = 0x08,
|
||||
VU0_S1_VMADDy = 0x09,
|
||||
VU0_S1_VMADDz = 0x0A,
|
||||
VU0_S1_VMADDw = 0x0B,
|
||||
VU0_S1_VMSUBx = 0x0C,
|
||||
VU0_S1_VMSUBy = 0x0D,
|
||||
VU0_S1_VMSUBz = 0x0E,
|
||||
VU0_S1_VMSUBw = 0x0F,
|
||||
VU0_S1_VMAXx = 0x10,
|
||||
VU0_S1_VMAXy = 0x11,
|
||||
VU0_S1_VMAXz = 0x12,
|
||||
VU0_S1_VMAXw = 0x13,
|
||||
VU0_S1_VMINIx = 0x14,
|
||||
VU0_S1_VMINIy = 0x15,
|
||||
VU0_S1_VMINIz = 0x16,
|
||||
VU0_S1_VMINIw = 0x17,
|
||||
VU0_S1_VMULx = 0x18,
|
||||
VU0_S1_VMULy = 0x19,
|
||||
VU0_S1_VMULz = 0x1A,
|
||||
VU0_S1_VMULw = 0x1B,
|
||||
VU0_S1_VMULq = 0x1C,
|
||||
VU0_S1_VMAXi = 0x1D,
|
||||
VU0_S1_VMULi = 0x1E,
|
||||
VU0_S1_VMINIi = 0x1F,
|
||||
VU0_S1_VADDq = 0x20,
|
||||
VU0_S1_VMADDq = 0x21,
|
||||
VU0_S1_VADDi = 0x22,
|
||||
VU0_S1_VMADDi = 0x23,
|
||||
VU0_S1_VSUBq = 0x24,
|
||||
VU0_S1_VMSUBq = 0x25,
|
||||
VU0_S1_VSUBi = 0x26,
|
||||
VU0_S1_VMSUBi = 0x27,
|
||||
VU0_S1_VADD = 0x28,
|
||||
VU0_S1_VMADD = 0x29,
|
||||
VU0_S1_VMUL = 0x2A,
|
||||
VU0_S1_VMAX = 0x2B,
|
||||
VU0_S1_VSUB = 0x2C,
|
||||
VU0_S1_VMSUB = 0x2D,
|
||||
VU0_S1_VOPMSUB = 0x2E,
|
||||
VU0_S1_VMINI = 0x2F,
|
||||
VU0_S1_VIADD = 0x30,
|
||||
VU0_S1_VISUB = 0x31,
|
||||
VU0_S1_VIADDI = 0x32,
|
||||
VU0_S1_VIAND = 0x34,
|
||||
VU0_S1_VIOR = 0x35,
|
||||
VU0_S1_VCALLMS = 0x38,
|
||||
VU0_S1_VCALLMSR = 0x39,
|
||||
};
|
||||
|
||||
// VU0 Macro Function Field (bits 5-0) for COP2_CO Format (Special2 Table)
|
||||
enum VU0MacroSpecial2Functions : uint8_t
|
||||
{
|
||||
VU0_S2_VADDAx = 0x00,
|
||||
VU0_S2_VADDAy = 0x01,
|
||||
VU0_S2_VADDAz = 0x02,
|
||||
VU0_S2_VADDAw = 0x03,
|
||||
VU0_S2_VSUBAx = 0x04,
|
||||
VU0_S2_VSUBAy = 0x05,
|
||||
VU0_S2_VSUBAz = 0x06,
|
||||
VU0_S2_VSUBAw = 0x07,
|
||||
VU0_S2_VMADDAx = 0x08,
|
||||
VU0_S2_VMADDAy = 0x09,
|
||||
VU0_S2_VMADDAz = 0x0A,
|
||||
VU0_S2_VMADDAw = 0x0B,
|
||||
VU0_S2_VMSUBAx = 0x0C,
|
||||
VU0_S2_VMSUBAy = 0x0D,
|
||||
VU0_S2_VMSUBAz = 0x0E,
|
||||
VU0_S2_VMSUBAw = 0x0F,
|
||||
VU0_S2_VITOF0 = 0x10,
|
||||
VU0_S2_VITOF4 = 0x11,
|
||||
VU0_S2_VITOF12 = 0x12,
|
||||
VU0_S2_VITOF15 = 0x13,
|
||||
VU0_S2_VFTOI0 = 0x14,
|
||||
VU0_S2_VFTOI4 = 0x15,
|
||||
VU0_S2_VFTOI12 = 0x16,
|
||||
VU0_S2_VFTOI15 = 0x17,
|
||||
VU0_S2_VMULAx = 0x18,
|
||||
VU0_S2_VMULAy = 0x19,
|
||||
VU0_S2_VMULAz = 0x1A,
|
||||
VU0_S2_VMULAw = 0x1B,
|
||||
VU0_S2_VMULAq = 0x1C,
|
||||
VU0_S2_VABS = 0x1D,
|
||||
VU0_S2_VMULAi = 0x1E,
|
||||
VU0_S2_VCLIPw = 0x1F,
|
||||
VU0_S2_VADDAq = 0x20,
|
||||
VU0_S2_VMADDAq = 0x21,
|
||||
VU0_S2_VADDAi = 0x22,
|
||||
VU0_S2_VMADDAi = 0x23,
|
||||
VU0_S2_VSUBAq = 0x24,
|
||||
VU0_S2_VMSUBAq = 0x25,
|
||||
VU0_S2_VSUBAi = 0x26,
|
||||
VU0_S2_VMSUBAi = 0x27,
|
||||
VU0_S2_VADDA = 0x28,
|
||||
VU0_S2_VMADDA = 0x29,
|
||||
VU0_S2_VMULA = 0x2A,
|
||||
VU0_S2_VSUBA = 0x2C,
|
||||
VU0_S2_VMSUBA = 0x2D,
|
||||
VU0_S2_VOPMULA = 0x2E,
|
||||
VU0_S2_VNOP = 0x2F,
|
||||
VU0_S2_VMOVE = 0x30,
|
||||
VU0_S2_VMR32 = 0x31,
|
||||
VU0_S2_VLQI = 0x34,
|
||||
VU0_S2_VSQI = 0x35,
|
||||
VU0_S2_VLQD = 0x36,
|
||||
VU0_S2_VSQD = 0x37,
|
||||
VU0_S2_VDIV = 0x38,
|
||||
VU0_S2_VSQRT = 0x39,
|
||||
VU0_S2_VRSQRT = 0x3A,
|
||||
VU0_S2_VWAITQ = 0x3B,
|
||||
VU0_S2_VMTIR = 0x3C,
|
||||
VU0_S2_VMFIR = 0x3D,
|
||||
VU0_S2_VILWR = 0x3E,
|
||||
VU0_S2_VISWR = 0x3F,
|
||||
VU0_S2_VRNEXT = 0x40,
|
||||
VU0_S2_VRGET = 0x41,
|
||||
VU0_S2_VRINIT = 0x42,
|
||||
VU0_S2_VRXOR = 0x43
|
||||
};
|
||||
|
||||
// // VU0 macro instruction function codes (subset - there are many more)
|
||||
// enum VU0MacroFunctions
|
||||
// {
|
||||
// VU0_VADD = 0x00,
|
||||
// VU0_VSUB = 0x01,
|
||||
// VU0_VMUL = 0x02,
|
||||
// VU0_VDIV = 0x03,
|
||||
// VU0_VSQRT = 0x04,
|
||||
// VU0_VRSQRT = 0x05,
|
||||
// VU0_VMULQ = 0x06,
|
||||
// VU0_VIADD = 0x10,
|
||||
// VU0_VISUB = 0x11,
|
||||
// VU0_VIADDI = 0x12,
|
||||
// VU0_VIAND = 0x13,
|
||||
// VU0_VIOR = 0x14,
|
||||
// VU0_VILWR = 0x15,
|
||||
// VU0_VISWR = 0x16,
|
||||
// VU0_VCALLMS = 0x20,
|
||||
// VU0_VCALLMSR = 0x21,
|
||||
// VU0_VRGET = 0x3F, // Get VU0 R register
|
||||
// VU0_VSUB_XYZ = 0x38 // Subtract with component selection
|
||||
// };
|
||||
|
||||
// enum VU0SpecialFormats
|
||||
// {
|
||||
// VU0_BC2F = 0x11, // Branch on VU0 condition false
|
||||
// VU0_MTVUCF = 0x13, // Move To VU0 control/flag register
|
||||
// VU0_CTCVU = 0x18, // Control To VU0 with specific functionality
|
||||
// VU0_VMTIR = 0x1C, // Move To VU0 I Register
|
||||
// VU0_VCLIP = 0x1E, // VU0 Clipping operation
|
||||
// VU0_VLDQ = 0x1F // VU0 Load/Store Quad with Decrement
|
||||
// };
|
||||
|
||||
// VU0 Control Register Numbers (used with CFC2/CTC2)
|
||||
enum VU0ControlRegisters
|
||||
{
|
||||
VU0_CR_STATUS = 0, // Status/Control register
|
||||
VU0_CR_MAC = 1, // MAC flags register
|
||||
VU0_CR_CLIP = 5, // Clipping flags register
|
||||
VU0_CR_CLIP = 5, // Clipping flags register //TODO maybe this is a 2 instead of 5
|
||||
VU0_CR_R = 3, // R register (Random number)
|
||||
VU0_CR_I = 4, // I register (Immediate)
|
||||
VU0_CR_CMSAR0 = 13, // VU0 microprogram start address register
|
||||
VU0_CR_FBRST = 18 // VIF/VU0/VU1 reset register
|
||||
};
|
||||
|
||||
enum VU0OPSFunctions
|
||||
{
|
||||
VU0OPS_QMFC2_NI = 0x00, // Non-incrementing QMFC2
|
||||
VU0OPS_QMFC2_I = 0x01, // Incrementing QMFC2
|
||||
VU0OPS_QMTC2_NI = 0x02, // Non-incrementing QMTC2
|
||||
VU0OPS_QMTC2_I = 0x03, // Incrementing QMTC2
|
||||
VU0OPS_VMFIR = 0x04, // Move From Integer Register
|
||||
VU0OPS_VXITOP = 0x08, // Execute Interrupt on VU0
|
||||
VU0OPS_VWAITQ = 0x3B, // Wait for Q register operations to complete
|
||||
VU0OPS_VMFHL = 0x1C, // Move from High / Low(similar to PMFHL)
|
||||
VU0OPS_VMTIR = 0x3C // Move to VU0 I Register with function code
|
||||
VU0OPS_QMFC2_NI = 0x00, // Non-incrementing QMFC2
|
||||
VU0OPS_QMFC2_I = 0x01, // Incrementing QMFC2
|
||||
VU0OPS_QMTC2_NI = 0x02, // Non-incrementing QMTC2
|
||||
VU0OPS_QMTC2_I = 0x03, // Incrementing QMTC2
|
||||
VU0OPS_VMFIR = 0x04, // Move From Integer Register
|
||||
VU0OPS_VXITOP = 0x08, // Execute Interrupt on VU0
|
||||
VU0OPS_VWAITQ = 0x3B, // Wait for Q register operations to complete
|
||||
VU0OPS_VMFHL = 0x1C, // Move from High / Low(similar to PMFHL)
|
||||
VU0OPS_VMTIR = 0x3C // Move to VU0 I Register with function code
|
||||
};
|
||||
|
||||
enum VU0OPSFunctionsExtra
|
||||
@@ -494,16 +719,6 @@ namespace ps2recomp
|
||||
VU0_FMT_LQSQ_COP0 = 0x1B // Load/store quad VU0 format
|
||||
};
|
||||
|
||||
// PMFHL functions (sa field)
|
||||
enum PMFHLFunctions
|
||||
{
|
||||
PMFHL_LW = 0x00,
|
||||
PMFHL_UW = 0x01,
|
||||
PMFHL_SLW = 0x02,
|
||||
PMFHL_LH = 0x03,
|
||||
PMFHL_SH = 0x04
|
||||
};
|
||||
|
||||
// Instruction decoding helper macros
|
||||
#define OPCODE(inst) ((inst >> 26) & 0x3F)
|
||||
#define RS(inst) ((inst >> 21) & 0x1F)
|
||||
@@ -512,8 +727,31 @@ namespace ps2recomp
|
||||
#define SA(inst) ((inst >> 6) & 0x1F)
|
||||
#define FUNCTION(inst) ((inst) & 0x3F)
|
||||
#define IMMEDIATE(inst) ((inst) & 0xFFFF)
|
||||
#define SIMMEDIATE(inst) ((int16_t)((inst) & 0xFFFF))
|
||||
#define SIMMEDIATE(inst) ((int32_t)(int16_t)((inst) & 0xFFFF))
|
||||
#define TARGET(inst) ((inst) & 0x3FFFFFF)
|
||||
#define COP_FUNCT(inst) ((uint8_t)((inst) & 0x3F)) // Function field for COPz CO instructions
|
||||
#define FPU_FMT(inst) ((uint8_t)(((inst) >> 21) & 0x1F)) // Format field for FPU instructions
|
||||
#define FT(inst) RT(inst) // Target FPU register
|
||||
#define FS(inst) RD(inst) // Source FPU register
|
||||
#define FD(inst) SA(inst) // Destination FPU register
|
||||
#define VU_I(inst) ((inst >> 25) & 0x1) // VU Upper I bit
|
||||
#define VU_E(inst) ((inst >> 24) & 0x1) // VU Upper E bit
|
||||
#define VU_M(inst) ((inst >> 23) & 0x1) // VU Upper M bit (VU0 only)
|
||||
#define VU_D(inst) ((inst >> 22) & 0x1) // VU Upper D bit
|
||||
#define VU_T(inst) ((inst >> 21) & 0x1) // VU Upper T bit
|
||||
#define VU_DEST(inst) ((uint8_t)(((inst) >> 16) & 0xF)) // VU Destination mask
|
||||
#define VU_FSF(inst) ((uint8_t)(((inst) >> 10) & 0x3)) // VU Source Field F
|
||||
#define VU_FTF(inst) ((uint8_t)(((inst) >> 8) & 0x3)) // VU Target Field F
|
||||
#define VU_FD(inst) ((uint8_t)(((inst) >> 11) & 0x1F)) // VU Destination Vector Register
|
||||
#define VU_FS(inst) ((uint8_t)(((inst) >> 6) & 0x1F)) // VU Source Vector Register
|
||||
#define VU_FT(inst) ((uint8_t)((inst) & 0x1F)) // VU Target Vector Register
|
||||
#define VU_IS(inst) RT(inst) // VU Source Integer Register
|
||||
#define VU_IT(inst) RD(inst) // VU Target Integer Register
|
||||
#define VU_ID(inst) SA(inst) // VU Destination Integer Register
|
||||
#define VU_IMM5(inst) ((uint8_t)((inst >> 6) & 0x1F)) // VU 5-bit immediate
|
||||
#define VU_IMM11(inst) ((uint16_t)((inst) & 0x7FF)) // VU 11-bit immediate
|
||||
#define VU_SIMM11(inst) ((int16_t)(((inst & 0x7FF) ^ 0x400) - 0x400)) // VU 11-bit signed immediate
|
||||
#define VU_IMM15(inst) ((uint16_t)((inst) & 0x7FFF)) // VU 15-bit immediate
|
||||
|
||||
} // namespace ps2recomp
|
||||
|
||||
|
||||
@@ -15,14 +15,15 @@ namespace ps2recomp
|
||||
{
|
||||
uint32_t address;
|
||||
uint32_t opcode;
|
||||
uint32_t rs; // Source register
|
||||
uint32_t rt; // Target register
|
||||
uint32_t rd; // Destination register
|
||||
uint32_t sa; // Shift amount
|
||||
uint32_t function; // Function code for R-type instructions
|
||||
uint32_t immediate; // Immediate value for I-type instructions
|
||||
uint32_t target; // Jump target for J-type instructions
|
||||
uint32_t raw; // Raw instruction value
|
||||
uint32_t rs; // Source register
|
||||
uint32_t rt; // Target register
|
||||
uint32_t rd; // Destination register
|
||||
uint32_t sa; // Shift amount
|
||||
uint32_t function; // Function code for R-type instructions
|
||||
uint32_t immediate; // Immediate value for I-type instructions
|
||||
uint32_t simmediate; // Sign-extended immediate value (extended to 32 bits)
|
||||
uint32_t target; // Jump target for J-type instructions
|
||||
uint32_t raw; // Raw instruction value
|
||||
|
||||
// Instruction type flags
|
||||
bool isMMI; // Is MMI instruction (PS2 specific)
|
||||
@@ -49,6 +50,8 @@ namespace ps2recomp
|
||||
bool usesPReg; // Uses P register
|
||||
bool modifiesMAC; // Modifies MAC flags
|
||||
uint8_t vectorField; // xyzw field mask
|
||||
uint8_t fsf; // Field select for FS reg (bits 10-11)
|
||||
uint8_t ftf; // Source Field select for FT reg (bits 8-9)
|
||||
} vectorInfo;
|
||||
|
||||
struct
|
||||
@@ -56,9 +59,21 @@ namespace ps2recomp
|
||||
bool modifiesGPR; // Modifies general purpose register
|
||||
bool modifiesFPR; // Modifies floating point register
|
||||
bool modifiesVFR; // Modifies vector float register
|
||||
bool modifiesVIR; // Modifies vector integer register
|
||||
bool modifiesVIC; // Modifies vector integer control register
|
||||
bool modifiesMemory; // Modifies memory
|
||||
bool modifiesControl; // Modifies control register
|
||||
} modificationInfo;
|
||||
|
||||
Instruction() : address(0), opcode(0), rs(0), rt(0), rd(0), sa(0), function(0),
|
||||
immediate(0), simmediate(0), target(0), raw(0),
|
||||
isMMI(false), isVU(false), isBranch(false), isJump(false), isCall(false),
|
||||
isReturn(false), hasDelaySlot(false), isMultimedia(false), isStore(false), isLoad(false),
|
||||
mmiType(0), mmiFunction(0), pmfhlVariation(0), vuFunction(0)
|
||||
{
|
||||
vectorInfo = {};
|
||||
modificationInfo = {};
|
||||
}
|
||||
};
|
||||
|
||||
// Function information
|
||||
|
||||
+1235
-1834
File diff suppressed because it is too large
Load Diff
+326
-371
@@ -25,6 +25,7 @@ namespace ps2recomp
|
||||
inst.sa = SA(rawInstruction);
|
||||
inst.function = FUNCTION(rawInstruction);
|
||||
inst.immediate = IMMEDIATE(rawInstruction);
|
||||
inst.simmediate = SIMMEDIATE(rawInstruction);
|
||||
inst.target = TARGET(rawInstruction);
|
||||
|
||||
inst.isMMI = false;
|
||||
@@ -53,6 +54,8 @@ namespace ps2recomp
|
||||
inst.modificationInfo.modifiesGPR = false;
|
||||
inst.modificationInfo.modifiesFPR = false;
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
inst.modificationInfo.modifiesVIR = false;
|
||||
inst.modificationInfo.modifiesVIC = false;
|
||||
inst.modificationInfo.modifiesMemory = false;
|
||||
inst.modificationInfo.modifiesControl = false;
|
||||
|
||||
@@ -68,18 +71,10 @@ namespace ps2recomp
|
||||
|
||||
case OPCODE_J:
|
||||
decodeJType(inst);
|
||||
inst.isJump = true;
|
||||
inst.hasDelaySlot = true;
|
||||
inst.modificationInfo.modifiesControl = true; // PC
|
||||
break;
|
||||
|
||||
case OPCODE_JAL:
|
||||
decodeJType(inst);
|
||||
inst.isJump = true;
|
||||
inst.isCall = true;
|
||||
inst.hasDelaySlot = true;
|
||||
inst.modificationInfo.modifiesGPR = true; // $ra (r[31])
|
||||
inst.modificationInfo.modifiesControl = true; // PC
|
||||
break;
|
||||
|
||||
case OPCODE_BEQ:
|
||||
@@ -96,6 +91,103 @@ namespace ps2recomp
|
||||
inst.modificationInfo.modifiesControl = true; // PC potentially
|
||||
break;
|
||||
|
||||
case OPCODE_DADDI:
|
||||
case OPCODE_DADDIU:
|
||||
decodeIType(inst);
|
||||
if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
break;
|
||||
|
||||
case OPCODE_MMI:
|
||||
decodeMMI(inst);
|
||||
break;
|
||||
|
||||
case OPCODE_LQ:
|
||||
decodeIType(inst);
|
||||
inst.isLoad = true;
|
||||
inst.isMultimedia = true; // 128-bit load
|
||||
break;
|
||||
|
||||
case OPCODE_SQ:
|
||||
decodeIType(inst);
|
||||
inst.isStore = true;
|
||||
inst.isMultimedia = true; // 128-bit store
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
break;
|
||||
|
||||
case OPCODE_LB:
|
||||
case OPCODE_LH:
|
||||
case OPCODE_LW:
|
||||
case OPCODE_LBU:
|
||||
case OPCODE_LHU:
|
||||
case OPCODE_LWU:
|
||||
case OPCODE_LD:
|
||||
inst.isLoad = true;
|
||||
if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
break;
|
||||
|
||||
case OPCODE_LWL:
|
||||
case OPCODE_LWR:
|
||||
case OPCODE_LDL:
|
||||
case OPCODE_LDR:
|
||||
inst.isLoad = true;
|
||||
if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
break;
|
||||
|
||||
case OPCODE_LWC1:
|
||||
inst.isLoad = true;
|
||||
inst.modificationInfo.modifiesFPR = true;
|
||||
break;
|
||||
|
||||
case OPCODE_LDC1: // Not present/used on EE FPU
|
||||
case OPCODE_LWC2: // Maybe unused
|
||||
case OPCODE_LDC2: // VU Load
|
||||
inst.isLoad = true;
|
||||
inst.isVU = true;
|
||||
inst.modificationInfo.modifiesVFR = true;
|
||||
break;
|
||||
|
||||
case OPCODE_SB:
|
||||
case OPCODE_SH:
|
||||
case OPCODE_SW:
|
||||
case OPCODE_SD:
|
||||
inst.isStore = true;
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
break;
|
||||
|
||||
case OPCODE_SWL:
|
||||
case OPCODE_SWR:
|
||||
case OPCODE_SDL:
|
||||
case OPCODE_SDR:
|
||||
inst.isStore = true;
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
break;
|
||||
|
||||
case OPCODE_SWC1:
|
||||
inst.isStore = true;
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
break;
|
||||
|
||||
case OPCODE_SDC1: // Not present/used on EE FPU
|
||||
case OPCODE_SWC2: // Potentially unused
|
||||
case OPCODE_SDC2:
|
||||
inst.isStore = true;
|
||||
inst.isVU = true;
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
break;
|
||||
|
||||
case OPCODE_SC:
|
||||
case OPCODE_SCD:
|
||||
inst.isStore = true;
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true; // Writes success/fail to rt
|
||||
inst.modificationInfo.modifiesControl = true; // Reads/Clears LLBit
|
||||
break;
|
||||
|
||||
case OPCODE_ADDI:
|
||||
case OPCODE_ADDIU:
|
||||
case OPCODE_SLTI:
|
||||
@@ -109,144 +201,25 @@ namespace ps2recomp
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
break;
|
||||
|
||||
case OPCODE_DADDI:
|
||||
case OPCODE_DADDIU:
|
||||
decodeIType(inst);
|
||||
if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
break;
|
||||
|
||||
case OPCODE_MMI:
|
||||
decodeMMI(inst);
|
||||
inst.isMMI = true;
|
||||
inst.isMultimedia = true;
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
break;
|
||||
|
||||
case OPCODE_LQ:
|
||||
decodeIType(inst);
|
||||
inst.isLoad = true;
|
||||
inst.isMultimedia = true; // 128-bit load
|
||||
if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
break;
|
||||
|
||||
case OPCODE_SQ:
|
||||
decodeIType(inst);
|
||||
inst.isStore = true;
|
||||
inst.isMultimedia = true; // 128-bit store
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
break;
|
||||
|
||||
case OPCODE_LB:
|
||||
case OPCODE_LH:
|
||||
case OPCODE_LWL:
|
||||
case OPCODE_LW:
|
||||
case OPCODE_LBU:
|
||||
case OPCODE_LHU:
|
||||
case OPCODE_LWR:
|
||||
case OPCODE_LWU:
|
||||
case OPCODE_LD:
|
||||
case OPCODE_LDL:
|
||||
case OPCODE_LDR:
|
||||
case OPCODE_LL:
|
||||
case OPCODE_LWC1:
|
||||
case OPCODE_LDC1:
|
||||
case OPCODE_LWC2:
|
||||
case OPCODE_LDC2: // VU Load
|
||||
decodeIType(inst);
|
||||
inst.isLoad = true;
|
||||
if (inst.opcode == OPCODE_LWC1 || inst.opcode == OPCODE_LDC1)
|
||||
inst.modificationInfo.modifiesFPR = true;
|
||||
else if (inst.opcode == OPCODE_LQC2)
|
||||
inst.modificationInfo.modifiesVFR = true;
|
||||
else if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true; // Standard GPR loads
|
||||
break;
|
||||
|
||||
case OPCODE_SB:
|
||||
case OPCODE_SH:
|
||||
case OPCODE_SWL:
|
||||
case OPCODE_SW:
|
||||
case OPCODE_SWR:
|
||||
case OPCODE_SD:
|
||||
case OPCODE_SDL:
|
||||
case OPCODE_SDR:
|
||||
case OPCODE_SC:
|
||||
case OPCODE_SWC1:
|
||||
case OPCODE_SDC1:
|
||||
case OPCODE_SWC2:
|
||||
case OPCODE_SDC2:
|
||||
case OPCODE_SCD: // VU Store
|
||||
decodeIType(inst);
|
||||
inst.isStore = true;
|
||||
if (inst.opcode == OPCODE_SC || inst.opcode == OPCODE_SCD)
|
||||
{
|
||||
if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPCODE_CACHE:
|
||||
decodeIType(inst);
|
||||
inst.modificationInfo.modifiesControl = true; // Cache state
|
||||
break;
|
||||
|
||||
case OPCODE_PREF:
|
||||
decodeIType(inst);
|
||||
break;
|
||||
|
||||
case OPCODE_COP0:
|
||||
decodeCOP0(inst);
|
||||
inst.modificationInfo.modifiesControl = true;
|
||||
if (inst.rs == COP0_MF && inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
break;
|
||||
|
||||
case OPCODE_COP1:
|
||||
decodeCOP1(inst);
|
||||
// Can modify FPRs, FCRs, GPRs (MFC1/CFC1), or PC (BC1)
|
||||
if (inst.isBranch)
|
||||
inst.modificationInfo.modifiesControl = true; // PC
|
||||
if (inst.rs == COP1_MF || inst.rs == COP1_CF)
|
||||
{
|
||||
// MFC1, CFC1
|
||||
if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
}
|
||||
else if (inst.rs == COP1_S || inst.rs == COP1_W || inst.rs == COP1_L)
|
||||
{
|
||||
inst.modificationInfo.modifiesFPR = true;
|
||||
}
|
||||
if (inst.rs == COP1_CT || inst.function >= COP1_FUNC_C_F)
|
||||
{ // CTC1 or Compare
|
||||
inst.modificationInfo.modifiesControl = true; // FCR31
|
||||
}
|
||||
break;
|
||||
|
||||
case OPCODE_COP2:
|
||||
decodeCOP2(inst);
|
||||
inst.isVU = true;
|
||||
inst.isMultimedia = true;
|
||||
// Can modify VFRs, VU Flags, GPRs (QMFC2/CFC2), PC (BC2), memory (VISWR)
|
||||
if (inst.isBranch)
|
||||
inst.modificationInfo.modifiesControl = true; // PC
|
||||
if (inst.rs == COP2_QMFC2 || inst.rs == COP2_CFC2)
|
||||
{
|
||||
// QMFC2, CFC2
|
||||
if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
}
|
||||
else if (inst.rs == COP2_QMTC2 || inst.rs == COP2_CTC2)
|
||||
{
|
||||
// Modifies VU state based on GPR
|
||||
}
|
||||
else
|
||||
{
|
||||
inst.modificationInfo.modifiesVFR = true; // Default assumption
|
||||
inst.modificationInfo.modifiesControl = true; // Flags, Q, P, I etc.
|
||||
}
|
||||
if (inst.isStore)
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -255,6 +228,13 @@ namespace ps2recomp
|
||||
break;
|
||||
}
|
||||
|
||||
// Generic multimedia flag if MMI or VU
|
||||
if (inst.isMMI || inst.isVU)
|
||||
{
|
||||
inst.isMultimedia = true;
|
||||
inst.vectorInfo.isVector = inst.isVU; // Only VU ops are truly vector
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
@@ -277,9 +257,12 @@ namespace ps2recomp
|
||||
void R5900Decoder::decodeJType(Instruction &inst) const
|
||||
{
|
||||
// J-type instructions already have all fields set correctly
|
||||
inst.isJump = true;
|
||||
inst.hasDelaySlot = true;
|
||||
inst.modificationInfo.modifiesControl = true; // PC
|
||||
if (inst.opcode == OPCODE_JAL)
|
||||
{
|
||||
inst.isCall = true;
|
||||
inst.modificationInfo.modifiesGPR = true; // $ra (r[31])
|
||||
}
|
||||
}
|
||||
@@ -420,13 +403,8 @@ namespace ps2recomp
|
||||
|
||||
case SPECIAL_SYNC:
|
||||
inst.modificationInfo.modifiesGPR = false;
|
||||
// Potentially modifies memory/cache visibility
|
||||
inst.modificationInfo.modifiesControl = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Other R-type instructions
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,82 +471,69 @@ namespace ps2recomp
|
||||
// The function field is actually determined by the lowest 6 bits (as in R-type)
|
||||
uint32_t mmiFunction = inst.function;
|
||||
|
||||
// Categorize the MMI instruction type based on the rs field
|
||||
uint32_t rs = inst.rs;
|
||||
|
||||
if (mmiFunction == MMI_MMI0)
|
||||
{
|
||||
decodeMMI0(inst);
|
||||
return;
|
||||
}
|
||||
if (mmiFunction == MMI_MMI1)
|
||||
{
|
||||
decodeMMI1(inst);
|
||||
return;
|
||||
}
|
||||
if (mmiFunction == MMI_MMI2)
|
||||
{
|
||||
decodeMMI2(inst);
|
||||
return;
|
||||
}
|
||||
if (mmiFunction == MMI_MMI3)
|
||||
{
|
||||
decodeMMI3(inst);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mmiFunction)
|
||||
{
|
||||
// Thouse comments has the same value
|
||||
case MMI_MADD:
|
||||
case MMI_MADDU:
|
||||
case MMI_MSUB:
|
||||
case MMI_MSUBU:
|
||||
case MMI_MADD1:
|
||||
case MMI_MADDU1:
|
||||
// Multiply-add operations
|
||||
inst.modificationInfo.modifiesControl = true; // Modifies HI/LO or HI1/LO1
|
||||
break;
|
||||
|
||||
case MMI_PLZCW:
|
||||
// Count leading zeros/ones
|
||||
break;
|
||||
|
||||
case MMI_MFHI1:
|
||||
case MMI_MFLO1:
|
||||
// Modifies rd GPR (already set)
|
||||
break;
|
||||
|
||||
case MMI_MTHI1:
|
||||
case MMI_MTLO1:
|
||||
// Secondary HI/LO register operations
|
||||
inst.modificationInfo.modifiesGPR = false;
|
||||
inst.modificationInfo.modifiesControl = true;
|
||||
break;
|
||||
|
||||
case MMI_MULT1:
|
||||
case MMI_MULTU1:
|
||||
case MMI_DIV1:
|
||||
case MMI_DIVU1:
|
||||
// Secondary multiply/divide operations
|
||||
break;
|
||||
|
||||
case MMI_MMI0:
|
||||
// First set of multimedia instructions
|
||||
decodeMMI0(inst);
|
||||
break;
|
||||
|
||||
case MMI_MMI1:
|
||||
// Second set of multimedia instructions
|
||||
decodeMMI1(inst);
|
||||
break;
|
||||
|
||||
case MMI_MMI2:
|
||||
// Third set of multimedia instructions
|
||||
decodeMMI2(inst);
|
||||
break;
|
||||
|
||||
case MMI_MMI3:
|
||||
// Fourth set of multimedia instructions
|
||||
decodeMMI3(inst);
|
||||
break;
|
||||
|
||||
case MMI_PMFHL:
|
||||
// PMFHL variations based on sa field
|
||||
decodePMFHL(inst);
|
||||
break;
|
||||
|
||||
case MMI_PMTHL:
|
||||
// PMTHL operations
|
||||
inst.modificationInfo.modifiesGPR = false;
|
||||
// case MMI2_PMADDW:
|
||||
case MMI2_PMSUBW:
|
||||
case MMI2_PMULTW:
|
||||
case MMI2_PDIVW:
|
||||
case MMI2_PDIVBW:
|
||||
case MMI2_PMADDH:
|
||||
case MMI2_PHMADH:
|
||||
// case MMI2_PMSUBH:
|
||||
// case MMI2_PHMSBH:
|
||||
case MMI2_PMULTH:
|
||||
// case MMI3_PMADDUW:
|
||||
// case MMI3_PMULTUW:
|
||||
// case MMI3_PDIVUW:
|
||||
inst.modificationInfo.modifiesGPR = false; // Writes to HI/LO or HI1/LO1
|
||||
inst.modificationInfo.modifiesControl = true;
|
||||
break;
|
||||
|
||||
case MMI_PSLLH:
|
||||
case MMI_PSRLH:
|
||||
case MMI_PSRAH:
|
||||
case MMI_PSLLW:
|
||||
case MMI_PSRLW:
|
||||
case MMI_PSRAW:
|
||||
// SIMD shift operations
|
||||
case MMI_MTHI1:
|
||||
case MMI_MTLO1:
|
||||
case MMI_PMTHL:
|
||||
case MMI3_PMTHI:
|
||||
case MMI3_PMTLO:
|
||||
inst.modificationInfo.modifiesGPR = false; // Writes to HI/LO or HI1/LO1
|
||||
inst.modificationInfo.modifiesControl = true;
|
||||
break;
|
||||
case MMI_PMFHL:
|
||||
decodePMFHL(inst);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown or unsupported MMI function
|
||||
std::cerr << "Unknown MMI function: " << std::hex << mmiFunction << std::endl;
|
||||
@@ -812,207 +777,197 @@ namespace ps2recomp
|
||||
void R5900Decoder::decodeCOP0(Instruction &inst) const
|
||||
{
|
||||
// COP0 (System Control) instructions
|
||||
uint32_t rs = inst.rs; // Actually the cop0 format field
|
||||
|
||||
if (rs == COP0_MF)
|
||||
uint8_t format = inst.rs;
|
||||
inst.modificationInfo.modifiesControl = true; // Assume COP0 always modifies some control state
|
||||
if (format == COP0_MF && inst.rt != 0)
|
||||
{
|
||||
// Move From COP0 register
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
}
|
||||
else if (rs == COP0_MT)
|
||||
else if (format == COP0_CO && inst.function == COP0_CO_ERET)
|
||||
{
|
||||
// Move To COP0 register
|
||||
}
|
||||
else if (rs == COP0_CO)
|
||||
inst.isReturn = true;
|
||||
inst.hasDelaySlot = false;
|
||||
} // ERET is special
|
||||
else if (format == COP0_BC)
|
||||
{
|
||||
// COProcessor operations
|
||||
uint32_t function = inst.function;
|
||||
|
||||
if (function == COP0_CO_ERET)
|
||||
{
|
||||
inst.isReturn = true;
|
||||
inst.hasDelaySlot = true;
|
||||
}
|
||||
else if (function == COP0_CO_TLBR ||
|
||||
function == COP0_CO_TLBWI ||
|
||||
function == COP0_CO_TLBWR ||
|
||||
function == COP0_CO_TLBP)
|
||||
{
|
||||
// TLB operations
|
||||
}
|
||||
else if (function == COP0_CO_EI || function == COP0_CO_DI)
|
||||
{
|
||||
// Enable/Disable Interrupts
|
||||
}
|
||||
inst.isBranch = true;
|
||||
inst.hasDelaySlot = true;
|
||||
}
|
||||
}
|
||||
|
||||
void R5900Decoder::decodeCOP1(Instruction &inst) const
|
||||
{
|
||||
// COP1 (FPU) instructions
|
||||
uint32_t rs = inst.rs; // The FPU format field
|
||||
|
||||
if (rs == COP1_MF)
|
||||
uint8_t format = inst.rs;
|
||||
if (format == COP1_MF || format == COP1_CF)
|
||||
{
|
||||
// Move From FPU register
|
||||
if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
}
|
||||
else if (rs == COP1_CF)
|
||||
else if (format == COP1_BC)
|
||||
{
|
||||
// Move From FPU Control register
|
||||
inst.isBranch = true;
|
||||
inst.hasDelaySlot = true;
|
||||
inst.modificationInfo.modifiesControl = true;
|
||||
}
|
||||
else if (rs == COP1_MT)
|
||||
else if (format == COP1_S || format == COP1_W || format == COP1_L)
|
||||
{
|
||||
// Move To FPU register
|
||||
inst.modificationInfo.modifiesFPR = true;
|
||||
}
|
||||
else if (rs == COP1_CT)
|
||||
if (format == COP1_CT || (format == COP1_S && inst.function >= COP1_S_C_F))
|
||||
{
|
||||
// Move To FPU Control register
|
||||
}
|
||||
else if (rs == COP1_BC)
|
||||
{
|
||||
// FPU Branch on Condition
|
||||
uint32_t rt = inst.rt; // The condition code
|
||||
if (rt == COP1_BC_BCF || rt == COP1_BC_BCT)
|
||||
{
|
||||
inst.isBranch = true;
|
||||
inst.hasDelaySlot = true;
|
||||
}
|
||||
}
|
||||
else if (rs == COP1_S || rs == COP1_W)
|
||||
{
|
||||
// FPU operations (single precision or word)
|
||||
uint32_t function = inst.function;
|
||||
// Decode specific FPU operation based on function field
|
||||
}
|
||||
inst.modificationInfo.modifiesControl = true;
|
||||
} // FCR31
|
||||
}
|
||||
|
||||
void R5900Decoder::decodeCOP2(Instruction &inst) const
|
||||
{
|
||||
uint8_t format = inst.rs;
|
||||
inst.isVU = true;
|
||||
inst.isMultimedia = true;
|
||||
|
||||
uint32_t rs = inst.rs; // The format field
|
||||
|
||||
switch (rs)
|
||||
switch (format)
|
||||
{
|
||||
case COP2_QMFC2: // Move From COP2 (128-bit)
|
||||
case COP2_CFC2: // Move Control From COP2
|
||||
case COP2_QMTC2: // Move To COP2 (128-bit)
|
||||
case COP2_CTC2: // Move Control To COP2
|
||||
// Register transfer operations
|
||||
case COP2_QMFC2:
|
||||
case COP2_CFC2:
|
||||
if (inst.rt != 0)
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
break;
|
||||
|
||||
case COP2_BC2: // Branch on COP2 condition
|
||||
{
|
||||
uint32_t rt = inst.rt; // The condition code
|
||||
|
||||
if (rt == COP2_BCF || rt == COP2_BCT ||
|
||||
rt == COP2_BCFL || rt == COP2_BCTL ||
|
||||
rt == COP2_BCEF || rt == COP2_BCET ||
|
||||
rt == COP2_BCEFL || rt == COP2_BCETL)
|
||||
{
|
||||
inst.isBranch = true;
|
||||
inst.hasDelaySlot = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case COP2_CO: // VU0 vector operations
|
||||
{
|
||||
uint32_t function = inst.function;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case VU0_VADD:
|
||||
case VU0_VSUB:
|
||||
case VU0_VMUL:
|
||||
// Basic vector math operations
|
||||
break;
|
||||
|
||||
case VU0_VDIV:
|
||||
case VU0_VSQRT:
|
||||
case VU0_VRSQRT:
|
||||
// Division and square root operations
|
||||
break;
|
||||
|
||||
case VU0_VMULQ:
|
||||
// Multiply by Q register
|
||||
break;
|
||||
|
||||
case VU0_VIADD:
|
||||
case VU0_VISUB:
|
||||
case VU0_VIADDI:
|
||||
// Integer operations
|
||||
break;
|
||||
|
||||
case VU0_VIAND:
|
||||
case VU0_VIOR:
|
||||
// Logical operations
|
||||
break;
|
||||
|
||||
case VU0_VILWR:
|
||||
case VU0_VISWR:
|
||||
// Load/Store operations
|
||||
inst.isLoad = (function == VU0_VILWR);
|
||||
inst.isStore = (function == VU0_VISWR);
|
||||
break;
|
||||
|
||||
case VU0_VCALLMS:
|
||||
case VU0_VCALLMSR:
|
||||
// VU0 microprogram calls
|
||||
inst.isCall = true;
|
||||
break;
|
||||
|
||||
case VU0_VRGET:
|
||||
// Get random number from R register
|
||||
break;
|
||||
|
||||
default:
|
||||
// Other VU0 operations
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case COP2_CTCVU: // Control Transfer to VU0
|
||||
case COP2_MTVUCF: // Move To VU Control/Flag register
|
||||
case COP2_VMTIR: // Move To VU0 I Register
|
||||
// Special register operations
|
||||
case COP2_QMTC2:
|
||||
inst.modificationInfo.modifiesVFR = true;
|
||||
break; // Modifies VU state
|
||||
case COP2_CTC2:
|
||||
inst.modificationInfo.modifiesControl = true;
|
||||
break; // Modifies VU control state
|
||||
case COP2_BC:
|
||||
inst.isBranch = true;
|
||||
inst.hasDelaySlot = true;
|
||||
inst.modificationInfo.modifiesControl = true;
|
||||
break;
|
||||
case COP2_CO: // VU Macro instructions (format >= 0x10)
|
||||
case COP2_CO + 1:
|
||||
case COP2_CO + 2:
|
||||
case COP2_CO + 3:
|
||||
case COP2_CO + 4:
|
||||
case COP2_CO + 5:
|
||||
case COP2_CO + 6:
|
||||
case COP2_CO + 7:
|
||||
case COP2_CO + 8:
|
||||
case COP2_CO + 9:
|
||||
case COP2_CO + 10:
|
||||
case COP2_CO + 11:
|
||||
case COP2_CO + 12:
|
||||
case COP2_CO + 13:
|
||||
case COP2_CO + 14:
|
||||
case COP2_CO + 15:
|
||||
{ // Refine based on specific VU function
|
||||
uint8_t vu_func = inst.function;
|
||||
|
||||
case COP2_VU0OPS: // Additional VU0 operations
|
||||
{
|
||||
uint32_t function = inst.function;
|
||||
|
||||
switch (function)
|
||||
if (vu_func == VU0_S2_VDIV || vu_func == VU0_S2_VSQRT || vu_func == VU0_S2_VRSQRT)
|
||||
{
|
||||
case VU0OPS_QMFC2_NI: // Non-incrementing QMFC2
|
||||
case VU0OPS_QMFC2_I: // Incrementing QMFC2
|
||||
case VU0OPS_QMTC2_NI: // Non-incrementing QMTC2
|
||||
case VU0OPS_QMTC2_I: // Incrementing QMTC2
|
||||
// Extended register transfer operations
|
||||
break;
|
||||
|
||||
case VU0OPS_VMFIR: // Move From Integer Register
|
||||
// Move operations
|
||||
break;
|
||||
|
||||
case VU0OPS_VXITOP: // Execute Interrupt on VU0
|
||||
break;
|
||||
|
||||
case VU0OPS_VWAITQ: // Wait for Q register operations
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown VU0OPS
|
||||
break;
|
||||
inst.vectorInfo.fsf = (inst.raw >> 10) & 0x3; // Extract bits 10-11
|
||||
inst.vectorInfo.ftf = (inst.raw >> 8) & 0x3; // Extract bits 8-9
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown COP2 format
|
||||
inst.vectorInfo.vectorField = (inst.raw >> 21) & 0xF;
|
||||
|
||||
inst.modificationInfo.modifiesVFR = true; // Default: Modifies Vector Float Reg
|
||||
inst.modificationInfo.modifiesControl = true; // Default: Modifies Flags/Special Regs (Q, P, I, MAC, Clip...)
|
||||
|
||||
if (vu_func >= 0x3C) // Special2 Table
|
||||
{
|
||||
switch (vu_func)
|
||||
{
|
||||
case VU0_S2_VDIV:
|
||||
case VU0_S2_VSQRT:
|
||||
case VU0_S2_VRSQRT:
|
||||
inst.vectorInfo.usesQReg = true;
|
||||
break;
|
||||
case VU0_S2_VMTIR:
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
inst.modificationInfo.modifiesVIC = true;
|
||||
break;
|
||||
case VU0_S2_VMFIR:
|
||||
inst.modificationInfo.modifiesVIR = false;
|
||||
break; // Reads VI, writes VF
|
||||
case VU0_S2_VILWR:
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
inst.modificationInfo.modifiesVIR = true;
|
||||
inst.isLoad = true;
|
||||
break;
|
||||
case VU0_S2_VISWR:
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
inst.modificationInfo.modifiesVIR = false;
|
||||
inst.isStore = true;
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
break;
|
||||
|
||||
case VU0_S2_VRINIT:
|
||||
case VU0_S2_VRXOR:
|
||||
inst.modificationInfo.modifiesVFR = false; /* Modifies R */
|
||||
break; // Modifies R
|
||||
case VU0_S2_VRGET:
|
||||
inst.modificationInfo.modifiesControl = false; /* Reads R, writes VF */
|
||||
break;
|
||||
case VU0_S2_VRNEXT:
|
||||
inst.modificationInfo.modifiesControl = true; /* Modifies R */
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
break; // Writes R
|
||||
case VU0_S2_VABS:
|
||||
case VU0_S2_VMOVE:
|
||||
case VU0_S2_VMR32:
|
||||
inst.modificationInfo.modifiesControl = false;
|
||||
break; // Only VF
|
||||
case VU0_S2_VNOP:
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
inst.modificationInfo.modifiesControl = false;
|
||||
break;
|
||||
case VU0_S2_VCLIPw:
|
||||
inst.modificationInfo.modifiesVFR = false; /* Modifies Clip flags */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // Special1 Table
|
||||
{
|
||||
if (vu_func >= VU0_S1_VIADD && vu_func <= VU0_S1_VIOR)
|
||||
{
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
inst.modificationInfo.modifiesVIR = true;
|
||||
} // Integer ops
|
||||
if (vu_func == VU0_S1_VIADDI)
|
||||
{
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
inst.modificationInfo.modifiesVIR = true;
|
||||
}
|
||||
if (vu_func == VU0_S2_VMFIR)
|
||||
{
|
||||
inst.modificationInfo.modifiesVIR = false;
|
||||
} // Only reads VIR
|
||||
if (vu_func == VU0_S2_VMTIR)
|
||||
{
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
inst.modificationInfo.modifiesVIC = true;
|
||||
} // Modifies I reg
|
||||
if (vu_func == VU0_S2_VILWR)
|
||||
{
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
inst.modificationInfo.modifiesVIR = true;
|
||||
inst.isLoad = true;
|
||||
}
|
||||
if (vu_func == VU0_S2_VISWR)
|
||||
{
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
inst.modificationInfo.modifiesVIR = false;
|
||||
inst.isStore = true;
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
}
|
||||
if (vu_func == VU0_S2_VDIV || vu_func == VU0_S2_VSQRT || vu_func == VU0_S2_VRSQRT)
|
||||
{
|
||||
inst.vectorInfo.usesQReg = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R5900Decoder::decodePMFHL(Instruction &inst) const
|
||||
@@ -1094,8 +1049,7 @@ namespace ps2recomp
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculate branch target: PC + 4 + (sign-extended immediate << 2)
|
||||
int32_t offset = static_cast<int16_t>(inst.immediate) << 2;
|
||||
int32_t offset = inst.simmediate << 2;
|
||||
return inst.address + 4 + offset;
|
||||
}
|
||||
|
||||
@@ -1106,6 +1060,13 @@ namespace ps2recomp
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (inst.opcode == OPCODE_SPECIAL &&
|
||||
(inst.function == SPECIAL_JR || inst.function == SPECIAL_JALR))
|
||||
{
|
||||
// JR/JALR: target is in the rs register (can't be determined statically)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (inst.opcode == OPCODE_J || inst.opcode == OPCODE_JAL)
|
||||
{
|
||||
// J/JAL: target is in the lower 26 bits, shifted left by 2
|
||||
@@ -1113,12 +1074,6 @@ namespace ps2recomp
|
||||
uint32_t pc_upper = (inst.address + 4) & 0xF0000000;
|
||||
return pc_upper | (inst.target << 2);
|
||||
}
|
||||
else if (inst.opcode == OPCODE_SPECIAL &&
|
||||
(inst.function == SPECIAL_JR || inst.function == SPECIAL_JALR))
|
||||
{
|
||||
// JR/JALR: target is in the rs register (can't be determined statically)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <iostream>
|
||||
|
||||
constexpr uint32_t PS2_RAM_SIZE = 32 * 1024 * 1024; // 32MB
|
||||
constexpr uint32_t PS2_RAM_MASK = PS2_RAM_SIZE - 1; // Mask for 32MB alignment
|
||||
constexpr uint32_t PS2_RAM_MASK = 0x1FFFFFF; // Mask for 32MB alignment
|
||||
constexpr uint32_t PS2_RAM_BASE = 0x00000000; // Physical base of RDRAM
|
||||
constexpr uint32_t PS2_SCRATCHPAD_BASE = 0x70000000;
|
||||
constexpr uint32_t PS2_SCRATCHPAD_SIZE = 16 * 1024; // 16KB
|
||||
|
||||
Reference in New Issue
Block a user