RSP: Move IsBranch into RSPInstruction

This commit is contained in:
zilmar 2025-03-28 12:43:38 +10:30
parent 0c0a46c1e0
commit 1a83c9b120
5 changed files with 206 additions and 201 deletions

View File

@ -7,6 +7,7 @@
#include <Project64-rsp-core/cpu/RSPCpu.h>
#include <Project64-rsp-core/cpu/RSPInstruction.h>
#include <Project64-rsp-core/cpu/RSPOpcode.h>
#include <Project64-rsp-core/cpu/RspLog.h>
#include <Project64-rsp-core/cpu/RspMemory.h>
#include <Project64-rsp-core/cpu/RspTypes.h>
@ -244,107 +245,6 @@ bool IsRegisterConstant(uint32_t Reg, uint32_t * Constant)
}
}
/*
IsOpcodeBranch
Output:
True: Opcode is a branch
False: Opcode is not a branch
Input: PC
*/
bool IsOpcodeBranch(uint32_t PC, RSPOpcode RspOp)
{
PC = PC; // Unused
switch (RspOp.op)
{
case RSP_REGIMM:
switch (RspOp.rt)
{
case RSP_REGIMM_BLTZ:
case RSP_REGIMM_BGEZ:
case RSP_REGIMM_BLTZAL:
case RSP_REGIMM_BGEZAL:
return true;
default:
//CompilerWarning(stdstr_f(stdstr_f("Unknown opcode in IsOpcodeBranch\n%s",RSPOpcodeName(RspOp.Hex,PC)).c_str());
break;
}
break;
case RSP_SPECIAL:
switch (RspOp.funct)
{
case RSP_SPECIAL_SLL:
case RSP_SPECIAL_SRL:
case RSP_SPECIAL_SRA:
case RSP_SPECIAL_SLLV:
case RSP_SPECIAL_SRLV:
case RSP_SPECIAL_SRAV:
case RSP_SPECIAL_ADD:
case RSP_SPECIAL_ADDU:
case RSP_SPECIAL_SUB:
case RSP_SPECIAL_SUBU:
case RSP_SPECIAL_AND:
case RSP_SPECIAL_OR:
case RSP_SPECIAL_XOR:
case RSP_SPECIAL_NOR:
case RSP_SPECIAL_SLT:
case RSP_SPECIAL_SLTU:
case RSP_SPECIAL_BREAK:
break;
case RSP_SPECIAL_JALR:
case RSP_SPECIAL_JR:
return true;
default:
//CompilerWarning(stdstr_f("Unknown opcode in IsOpcodeBranch\n%s",RSPOpcodeName(RspOp.Hex,PC)).c_str());
break;
}
break;
case RSP_J:
case RSP_JAL:
case RSP_BEQ:
case RSP_BNE:
case RSP_BLEZ:
case RSP_BGTZ:
return true;
case RSP_ADDI:
case RSP_ADDIU:
case RSP_SLTI:
case RSP_SLTIU:
case RSP_ANDI:
case RSP_ORI:
case RSP_XORI:
case RSP_LUI:
case RSP_CP0:
case RSP_CP2:
break;
case RSP_LB:
case RSP_LH:
case RSP_LW:
case RSP_LBU:
case RSP_LHU:
case RSP_SB:
case RSP_SH:
case RSP_SW:
break;
case RSP_LC2:
case RSP_SC2:
break;
default:
//CompilerWarning(stdstr_f("Unknown opcode in IsOpcodeBranch\n%s",RSPOpcodeName(RspOp.Hex,PC)).c_str());
break;
}
return false;
}
/*
GetInstructionInfo
Output: None in regard to return value
@ -396,30 +296,30 @@ typedef struct
#pragma warning(pop)
void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
void GetInstructionInfo(uint32_t PC, const RSPOpcode & RspOp, OPCODE_INFO * info)
{
switch (RspOp->op)
switch (RspOp.op)
{
case RSP_REGIMM:
switch (RspOp->rt)
switch (RspOp.rt)
{
case RSP_REGIMM_BLTZ:
case RSP_REGIMM_BLTZAL:
case RSP_REGIMM_BGEZ:
case RSP_REGIMM_BGEZAL:
info->flags = InvalidOpcode;
info->SourceReg0 = RspOp->rs;
info->SourceReg0 = RspOp.rs;
info->SourceReg1 = UNUSED_OPERAND;
break;
default:
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp->Value).NameAndParam().c_str()).c_str());
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp.Value).NameAndParam().c_str()).c_str());
info->flags = InvalidOpcode;
break;
}
break;
case RSP_SPECIAL:
switch (RspOp->funct)
switch (RspOp.funct)
{
case RSP_SPECIAL_BREAK:
info->DestReg = UNUSED_OPERAND;
@ -431,8 +331,8 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_SPECIAL_SLL:
case RSP_SPECIAL_SRL:
case RSP_SPECIAL_SRA:
info->DestReg = RspOp->rd;
info->SourceReg0 = RspOp->rt;
info->DestReg = RspOp.rd;
info->SourceReg0 = RspOp.rt;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction;
break;
@ -449,9 +349,9 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_SPECIAL_NOR:
case RSP_SPECIAL_SLT:
case RSP_SPECIAL_SLTU:
info->DestReg = RspOp->rd;
info->SourceReg0 = RspOp->rs;
info->SourceReg1 = RspOp->rt;
info->DestReg = RspOp.rd;
info->SourceReg0 = RspOp.rs;
info->SourceReg1 = RspOp.rt;
info->flags = GPR_Instruction;
break;
@ -462,7 +362,7 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
break;
default:
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp->Value).NameAndParam().c_str()).c_str());
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp.Value).NameAndParam().c_str()).c_str());
info->flags = InvalidOpcode;
break;
}
@ -476,13 +376,13 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_BEQ:
case RSP_BNE:
info->flags = InvalidOpcode;
info->SourceReg0 = RspOp->rt;
info->SourceReg1 = RspOp->rs;
info->SourceReg0 = RspOp.rt;
info->SourceReg1 = RspOp.rs;
break;
case RSP_BLEZ:
case RSP_BGTZ:
info->flags = InvalidOpcode;
info->SourceReg0 = RspOp->rs;
info->SourceReg0 = RspOp.rs;
info->SourceReg1 = UNUSED_OPERAND;
break;
@ -493,27 +393,27 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_ANDI:
case RSP_ORI:
case RSP_XORI:
info->DestReg = RspOp->rt;
info->SourceReg0 = RspOp->rs;
info->DestReg = RspOp.rt;
info->SourceReg0 = RspOp.rs;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction;
break;
case RSP_LUI:
info->DestReg = RspOp->rt;
info->DestReg = RspOp.rt;
info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction;
break;
case RSP_CP0:
switch (RspOp->rs)
switch (RspOp.rs)
{
case RSP_COP0_MF:
info->DestReg = RspOp->rt;
info->DestReg = RspOp.rt;
info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = UNUSED_OPERAND;
if (RspOp->rd == 0x4 || RspOp->rd == 0x7)
if (RspOp.rd == 0x4 || RspOp.rd == 0x7)
{
info->flags = InvalidOpcode | COPO_MF_Instruction;
}
@ -524,7 +424,7 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
break;
case RSP_COP0_MT:
info->StoredReg = RspOp->rt;
info->StoredReg = RspOp.rt;
info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction | Store_Operation;
@ -533,9 +433,9 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
break;
case RSP_CP2:
if ((RspOp->rs & 0x10) != 0)
if ((RspOp.rs & 0x10) != 0)
{
switch (RspOp->funct)
switch (RspOp.funct)
{
case RSP_VECTOR_VNOP:
info->DestReg = UNUSED_OPERAND;
@ -557,9 +457,9 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_VECTOR_VNAND:
case RSP_VECTOR_VNOR:
case RSP_VECTOR_VNXOR:
info->DestReg = RspOp->sa;
info->SourceReg0 = RspOp->rd;
info->SourceReg1 = RspOp->rt;
info->DestReg = RspOp.sa;
info->SourceReg0 = RspOp.rd;
info->SourceReg1 = RspOp.rt;
info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation;
break;
case RSP_VECTOR_VMACF:
@ -568,9 +468,9 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_VECTOR_VMADM:
case RSP_VECTOR_VMADN:
case RSP_VECTOR_VMADH:
info->DestReg = RspOp->sa;
info->SourceReg0 = RspOp->rd;
info->SourceReg1 = RspOp->rt;
info->DestReg = RspOp.sa;
info->SourceReg0 = RspOp.rd;
info->SourceReg1 = RspOp.rt;
info->flags = VEC_Instruction | VEC_Accumulate | Accum_Operation;
break;
case RSP_VECTOR_VADD:
@ -584,9 +484,9 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_VECTOR_VEQ:
case RSP_VECTOR_VGE:
case RSP_VECTOR_VNE:
info->DestReg = RspOp->sa;
info->SourceReg0 = RspOp->rd;
info->SourceReg1 = RspOp->rt;
info->DestReg = RspOp.sa;
info->SourceReg0 = RspOp.rd;
info->SourceReg1 = RspOp.rt;
info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation | Flag_Instruction;
break;
@ -596,45 +496,45 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_VECTOR_VRCPH:
case RSP_VECTOR_VRSQL:
case RSP_VECTOR_VRSQH:
info->DestReg = RspOp->sa;
info->SourceReg0 = RspOp->rt;
info->DestReg = RspOp.sa;
info->SourceReg0 = RspOp.rt;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation; // Assume reset?
break;
case RSP_VECTOR_VMRG:
info->DestReg = RspOp->sa;
info->SourceReg0 = RspOp->rt;
info->SourceReg1 = RspOp->rd;
info->DestReg = RspOp.sa;
info->SourceReg0 = RspOp.rt;
info->SourceReg1 = RspOp.rd;
info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation | Flag_Instruction; // Assume reset?
break;
case RSP_VECTOR_VSAW:
// info->flags = InvalidOpcode;
info->DestReg = RspOp->sa;
info->DestReg = RspOp.sa;
info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = VEC_Instruction | Accum_Operation | VEC_Accumulate;
break;
default:
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp->Value).NameAndParam().c_str()).c_str());
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp.Value).NameAndParam().c_str()).c_str());
info->flags = InvalidOpcode;
break;
}
}
else
{
switch (RspOp->rs)
switch (RspOp.rs)
{
case RSP_COP2_CT:
info->StoredReg = RspOp->rt;
info->StoredReg = RspOp.rt;
info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction | Store_Operation | Flag_Instruction;
break;
case RSP_COP2_CF:
info->DestReg = RspOp->rt;
info->DestReg = RspOp.rt;
info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction | Load_Operation | Flag_Instruction;
@ -642,19 +542,19 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
// RD is always the vector register, RT is always GPR
case RSP_COP2_MT:
info->DestReg = RspOp->rd;
info->SourceReg0 = RspOp->rt;
info->DestReg = RspOp.rd;
info->SourceReg0 = RspOp.rt;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = VEC_Instruction | GPR_Instruction | Load_Operation;
break;
case RSP_COP2_MF:
info->DestReg = RspOp->rt;
info->SourceReg0 = RspOp->rd;
info->DestReg = RspOp.rt;
info->SourceReg0 = RspOp.rd;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = VEC_Instruction | GPR_Instruction | Store_Operation;
break;
default:
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp->Value).NameAndParam().c_str()).c_str());
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp.Value).NameAndParam().c_str()).c_str());
info->flags = InvalidOpcode;
break;
}
@ -665,21 +565,21 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_LW:
case RSP_LBU:
case RSP_LHU:
info->DestReg = RspOp->rt;
info->IndexReg = RspOp->base;
info->DestReg = RspOp.rt;
info->IndexReg = RspOp.base;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = Load_Operation | GPR_Instruction;
break;
case RSP_SB:
case RSP_SH:
case RSP_SW:
info->StoredReg = RspOp->rt;
info->IndexReg = RspOp->base;
info->StoredReg = RspOp.rt;
info->IndexReg = RspOp.base;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = Store_Operation | GPR_Instruction;
break;
case RSP_LC2:
switch (RspOp->rd)
switch (RspOp.rd)
{
case RSP_LSC2_BV:
case RSP_LSC2_SV:
@ -689,8 +589,8 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_LSC2_LV:
case RSP_LSC2_UV:
case RSP_LSC2_PV:
info->DestReg = RspOp->rt;
info->IndexReg = RspOp->base;
info->DestReg = RspOp.rt;
info->IndexReg = RspOp.base;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = Load_Operation | VEC_Instruction;
break;
@ -699,13 +599,13 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
info->flags = InvalidOpcode;
break;
default:
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp->Value).NameAndParam().c_str()).c_str());
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp.Value).NameAndParam().c_str()).c_str());
info->flags = InvalidOpcode;
break;
}
break;
case RSP_SC2:
switch (RspOp->rd)
switch (RspOp.rd)
{
case RSP_LSC2_BV:
case RSP_LSC2_SV:
@ -718,8 +618,8 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_LSC2_HV:
case RSP_LSC2_FV:
case RSP_LSC2_WV:
info->DestReg = RspOp->rt;
info->IndexReg = RspOp->base;
info->DestReg = RspOp.rt;
info->IndexReg = RspOp.base;
info->SourceReg1 = UNUSED_OPERAND;
info->flags = Store_Operation | VEC_Instruction;
break;
@ -727,13 +627,13 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
info->flags = InvalidOpcode;
break;
default:
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp->Value).NameAndParam().c_str()).c_str());
CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s", RSPInstruction(PC, RspOp.Value).NameAndParam().c_str()).c_str());
info->flags = InvalidOpcode;
break;
}
break;
default:
/* CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC)).c_str());
/* CompilerWarning(stdstr_f("Unknown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp.Hex,PC)).c_str());
*/
info->flags = InvalidOpcode;
break;
@ -764,8 +664,8 @@ bool DelaySlotAffectBranch(uint32_t PC)
memset(&infoDelay, 0, sizeof(infoDelay));
memset(&infoBranch, 0, sizeof(infoBranch));
GetInstructionInfo(PC, &BranchOp, &infoBranch);
GetInstructionInfo(DelayPC, &DelayOp, &infoDelay);
GetInstructionInfo(PC, BranchOp, &infoBranch);
GetInstructionInfo(DelayPC, DelayOp, &infoDelay);
if ((infoDelay.flags & COPO_MF_Instruction) == COPO_MF_Instruction)
{
@ -798,17 +698,19 @@ Input: Top, not the current operation, the one above
Bottom: The current opcode for re-ordering bubble style
*/
bool CompareInstructions(uint32_t PC, RSPOpcode * Top, RSPOpcode * Bottom)
bool CompareInstructions(uint32_t PC, const RSPInstruction & Top, RSPOpcode * Bottom)
{
OPCODE_INFO info0, info1;
uint32_t InstructionType;
GetInstructionInfo(PC - 4, Top, &info0);
GetInstructionInfo(PC, Bottom, &info1);
RSPOpcode TopOpcode;
TopOpcode.Value = Top.Value();
GetInstructionInfo(PC - 4, TopOpcode, &info0);
GetInstructionInfo(PC, *Bottom, &info1);
#ifdef COMPARE_INSTRUCTIONS_VERBOSE
CPU_Message("Comparing %s (%X)", RSPOpcodeName(Top->Hex, PC - 4), PC - 4);
CPU_Message("to %s (%X)", RSPOpcodeName(Bottom->Hex, PC), PC);
CPU_Message("Comparing %s (%X)", Top.NameAndParam().c_str(), Top.Address());
CPU_Message("to %s (%X)", RSPInstruction(PC, Bottom->Value).NameAndParam().c_str(), PC);
#endif
// Usually branches and such

View File

@ -435,11 +435,10 @@ void CRSPRecompiler::ReOrderInstructions(uint32_t StartPC, uint32_t EndPC)
{
uint32_t InstructionCount = EndPC - StartPC;
uint32_t Count, ReorderedOps, CurrentPC;
RSPOpcode PreviousOp, CurrentOp, RspOp;
RSPInstruction PreviousOp(StartPC, *(uint32_t *)(m_IMEM + (StartPC & 0xFFC)));
RSPOpcode CurrentOp, RspOp;
PreviousOp.Value = *(uint32_t *)(m_IMEM + (StartPC & 0xFFC));
if (IsOpcodeBranch(StartPC, PreviousOp))
if (PreviousOp.IsBranch())
{
// The sub block ends here anyway
return;
@ -472,7 +471,7 @@ void CRSPRecompiler::ReOrderInstructions(uint32_t StartPC, uint32_t EndPC)
for (Count = 0; Count < InstructionCount; Count += 4)
{
CurrentPC = StartPC;
PreviousOp.Value = *(uint32_t *)(m_IMEM + (CurrentPC & 0xFFC));
PreviousOp = RSPInstruction(CurrentPC, *(uint32_t *)(m_IMEM + (CurrentPC & 0xFFC)));
ReorderedOps = 0;
for (;;)
@ -484,11 +483,11 @@ void CRSPRecompiler::ReOrderInstructions(uint32_t StartPC, uint32_t EndPC)
}
CurrentOp.Value = *(uint32_t *)(m_IMEM + CurrentPC);
if (CompareInstructions(CurrentPC, &PreviousOp, &CurrentOp))
if (CompareInstructions(CurrentPC, PreviousOp, &CurrentOp))
{
// Move current opcode up
*(uint32_t *)(m_IMEM + CurrentPC - 4) = CurrentOp.Value;
*(uint32_t *)(m_IMEM + CurrentPC) = PreviousOp.Value;
*(uint32_t *)(m_IMEM + CurrentPC) = PreviousOp.Value();
ReorderedOps++;
@ -496,7 +495,7 @@ void CRSPRecompiler::ReOrderInstructions(uint32_t StartPC, uint32_t EndPC)
CPU_Message("Swapped %X and %X", CurrentPC - 4, CurrentPC);
#endif
}
PreviousOp.Value = *(uint32_t *)(m_IMEM + (CurrentPC & 0xFFC));
PreviousOp = RSPInstruction(CurrentPC, *(uint32_t *)(m_IMEM + (CurrentPC & 0xFFC)));
if (IsOpcodeNop(CurrentPC) && IsOpcodeNop(CurrentPC + 4) && IsOpcodeNop(CurrentPC + 8))
{
@ -734,7 +733,7 @@ void CRSPRecompiler::BuildBranchLabels(void)
{
RspOp.Value = *(uint32_t *)(RSPInfo.IMEM + i);
if (IsOpcodeBranch(i, RspOp))
if (RSPInstruction(i, RspOp.Value).IsBranch())
{
if (RspCode.LabelCount >= (sizeof(RspCode.BranchLabels) / sizeof(RspCode.BranchLabels[0])) - 1)
{

View File

@ -11,6 +11,7 @@
class CRSPSystem;
class RSPRegisterHandlerPlugin;
class RSPInstruction;
class CRSPRecompiler
{
@ -74,8 +75,7 @@ extern bool ChangedPC;
#define EntireAccum (Low16BitAccum | Middle16BitAccum | High16BitAccum)
bool DelaySlotAffectBranch(uint32_t PC);
bool CompareInstructions(uint32_t PC, RSPOpcode * Top, RSPOpcode * Bottom);
bool IsOpcodeBranch(uint32_t PC, RSPOpcode RspOp);
bool CompareInstructions(uint32_t PC, const RSPInstruction & Top, RSPOpcode * Bottom);
bool IsOpcodeNop(uint32_t PC);
bool IsRegisterConstant(uint32_t Reg, uint32_t * Constant);

View File

@ -7,27 +7,30 @@ class RSPInstruction
{
public:
RSPInstruction(uint32_t Address, uint32_t Instruction);
RSPInstruction & operator=(const RSPInstruction &);
const char * Name();
const char * Param();
std::string NameAndParam();
uint32_t Address() const;
bool IsBranch() const;
const char * Name() const;
const char * Param() const;
std::string NameAndParam() const;
uint32_t Value() const;
private:
RSPInstruction(void);
RSPInstruction(const RSPInstruction &);
RSPInstruction & operator=(const RSPInstruction &);
void DecodeName(void);
void DecodeSpecialName(void);
void DecodeRegImmName(void);
void DecodeCop0Name(void);
void DecodeCop2Name(void);
void DecodeLSC2Name(const char LoadStoreIdent);
void DecodeName(void) const;
void DecodeSpecialName(void) const;
void DecodeRegImmName(void) const;
void DecodeCop0Name(void) const;
void DecodeCop2Name(void) const;
void DecodeLSC2Name(const char LoadStoreIdent) const;
static const char * ElementSpecifier(uint32_t Element);
uint32_t m_Address;
RSPOpcode m_Instruction;
char m_Name[40];
char m_Param[200];
mutable char m_Name[40];
mutable char m_Param[200];
};

View File

@ -1,6 +1,7 @@
#include "RSPInstruction.h"
#include "RSPRegisters.h"
#include <Common/StdString.h>
#include <Settings/Settings.h>
RSPInstruction::RSPInstruction(uint32_t Address, uint32_t Instruction) :
m_Address(Address)
@ -10,7 +11,102 @@ RSPInstruction::RSPInstruction(uint32_t Address, uint32_t Instruction) :
m_Instruction.Value = Instruction;
}
const char * RSPInstruction::Name()
RSPInstruction & RSPInstruction::operator=(const RSPInstruction & e)
{
m_Address = e.m_Address;
m_Instruction.Value = e.m_Instruction.Value;
memcpy(m_Name, e.m_Name, sizeof(m_Name));
memcpy(m_Param, e.m_Param, sizeof(m_Param));
return *this;
}
uint32_t RSPInstruction::Address() const
{
return m_Address;
}
bool RSPInstruction::IsBranch() const
{
switch (m_Instruction.op)
{
case RSP_REGIMM:
switch (m_Instruction.rt)
{
case RSP_REGIMM_BLTZ:
case RSP_REGIMM_BGEZ:
case RSP_REGIMM_BLTZAL:
case RSP_REGIMM_BGEZAL:
return true;
default:
#ifdef _DEBUG
g_Notify->BreakPoint(__FILE__, __LINE__);
#endif
break;
}
break;
case RSP_SPECIAL:
switch (m_Instruction.funct)
{
case RSP_SPECIAL_SLL:
case RSP_SPECIAL_SRL:
case RSP_SPECIAL_SRA:
case RSP_SPECIAL_SLLV:
case RSP_SPECIAL_SRLV:
case RSP_SPECIAL_SRAV:
case RSP_SPECIAL_ADD:
case RSP_SPECIAL_ADDU:
case RSP_SPECIAL_SUB:
case RSP_SPECIAL_SUBU:
case RSP_SPECIAL_AND:
case RSP_SPECIAL_OR:
case RSP_SPECIAL_XOR:
case RSP_SPECIAL_NOR:
case RSP_SPECIAL_SLT:
case RSP_SPECIAL_SLTU:
case RSP_SPECIAL_BREAK:
break;
case RSP_SPECIAL_JALR:
case RSP_SPECIAL_JR:
return true;
default:
break;
}
break;
case RSP_J:
case RSP_JAL:
case RSP_BEQ:
case RSP_BNE:
case RSP_BLEZ:
case RSP_BGTZ:
return true;
case RSP_ADDI:
case RSP_ADDIU:
case RSP_SLTI:
case RSP_SLTIU:
case RSP_ANDI:
case RSP_ORI:
case RSP_XORI:
case RSP_LUI:
case RSP_CP0:
case RSP_CP2:
case RSP_LB:
case RSP_LH:
case RSP_LW:
case RSP_LBU:
case RSP_LHU:
case RSP_SB:
case RSP_SH:
case RSP_SW:
case RSP_LC2:
case RSP_SC2:
break;
default:
break;
}
return false;
}
const char * RSPInstruction::Name() const
{
if (m_Name[0] == '\0')
{
@ -19,7 +115,7 @@ const char * RSPInstruction::Name()
return m_Name;
}
const char * RSPInstruction::Param()
const char * RSPInstruction::Param() const
{
if (m_Param[0] == '\0')
{
@ -28,12 +124,17 @@ const char * RSPInstruction::Param()
return m_Param;
}
std::string RSPInstruction::NameAndParam()
std::string RSPInstruction::NameAndParam() const
{
return stdstr_f("%s %s", Name(), Param());
}
void RSPInstruction::DecodeName(void)
uint32_t RSPInstruction::Value() const
{
return m_Instruction.Value;
}
void RSPInstruction::DecodeName(void) const
{
switch (m_Instruction.op)
{
@ -174,7 +275,7 @@ void RSPInstruction::DecodeName(void)
}
}
void RSPInstruction::DecodeSpecialName(void)
void RSPInstruction::DecodeSpecialName(void) const
{
switch (m_Instruction.funct)
{
@ -266,7 +367,7 @@ void RSPInstruction::DecodeSpecialName(void)
}
}
void RSPInstruction::DecodeRegImmName(void)
void RSPInstruction::DecodeRegImmName(void) const
{
switch (m_Instruction.rt)
{
@ -308,7 +409,7 @@ void RSPInstruction::DecodeRegImmName(void)
}
}
void RSPInstruction::DecodeCop0Name(void)
void RSPInstruction::DecodeCop0Name(void) const
{
switch (m_Instruction.rs)
{
@ -326,7 +427,7 @@ void RSPInstruction::DecodeCop0Name(void)
}
}
void RSPInstruction::DecodeCop2Name(void)
void RSPInstruction::DecodeCop2Name(void) const
{
if ((m_Instruction.rs & 0x10) == 0)
{
@ -620,7 +721,7 @@ void RSPInstruction::DecodeCop2Name(void)
}
}
void RSPInstruction::DecodeLSC2Name(const char LoadStoreIdent)
void RSPInstruction::DecodeLSC2Name(const char LoadStoreIdent) const
{
switch (m_Instruction.rd)
{