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/RSPCpu.h>
#include <Project64-rsp-core/cpu/RSPInstruction.h> #include <Project64-rsp-core/cpu/RSPInstruction.h>
#include <Project64-rsp-core/cpu/RSPOpcode.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/RspMemory.h>
#include <Project64-rsp-core/cpu/RspTypes.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 GetInstructionInfo
Output: None in regard to return value Output: None in regard to return value
@ -396,30 +296,30 @@ typedef struct
#pragma warning(pop) #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: case RSP_REGIMM:
switch (RspOp->rt) switch (RspOp.rt)
{ {
case RSP_REGIMM_BLTZ: case RSP_REGIMM_BLTZ:
case RSP_REGIMM_BLTZAL: case RSP_REGIMM_BLTZAL:
case RSP_REGIMM_BGEZ: case RSP_REGIMM_BGEZ:
case RSP_REGIMM_BGEZAL: case RSP_REGIMM_BGEZAL:
info->flags = InvalidOpcode; info->flags = InvalidOpcode;
info->SourceReg0 = RspOp->rs; info->SourceReg0 = RspOp.rs;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
break; break;
default: 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; info->flags = InvalidOpcode;
break; break;
} }
break; break;
case RSP_SPECIAL: case RSP_SPECIAL:
switch (RspOp->funct) switch (RspOp.funct)
{ {
case RSP_SPECIAL_BREAK: case RSP_SPECIAL_BREAK:
info->DestReg = UNUSED_OPERAND; 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_SLL:
case RSP_SPECIAL_SRL: case RSP_SPECIAL_SRL:
case RSP_SPECIAL_SRA: case RSP_SPECIAL_SRA:
info->DestReg = RspOp->rd; info->DestReg = RspOp.rd;
info->SourceReg0 = RspOp->rt; info->SourceReg0 = RspOp.rt;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction; info->flags = GPR_Instruction;
break; break;
@ -449,9 +349,9 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_SPECIAL_NOR: case RSP_SPECIAL_NOR:
case RSP_SPECIAL_SLT: case RSP_SPECIAL_SLT:
case RSP_SPECIAL_SLTU: case RSP_SPECIAL_SLTU:
info->DestReg = RspOp->rd; info->DestReg = RspOp.rd;
info->SourceReg0 = RspOp->rs; info->SourceReg0 = RspOp.rs;
info->SourceReg1 = RspOp->rt; info->SourceReg1 = RspOp.rt;
info->flags = GPR_Instruction; info->flags = GPR_Instruction;
break; break;
@ -462,7 +362,7 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
break; break;
default: 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; info->flags = InvalidOpcode;
break; break;
} }
@ -476,13 +376,13 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_BEQ: case RSP_BEQ:
case RSP_BNE: case RSP_BNE:
info->flags = InvalidOpcode; info->flags = InvalidOpcode;
info->SourceReg0 = RspOp->rt; info->SourceReg0 = RspOp.rt;
info->SourceReg1 = RspOp->rs; info->SourceReg1 = RspOp.rs;
break; break;
case RSP_BLEZ: case RSP_BLEZ:
case RSP_BGTZ: case RSP_BGTZ:
info->flags = InvalidOpcode; info->flags = InvalidOpcode;
info->SourceReg0 = RspOp->rs; info->SourceReg0 = RspOp.rs;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
break; break;
@ -493,27 +393,27 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_ANDI: case RSP_ANDI:
case RSP_ORI: case RSP_ORI:
case RSP_XORI: case RSP_XORI:
info->DestReg = RspOp->rt; info->DestReg = RspOp.rt;
info->SourceReg0 = RspOp->rs; info->SourceReg0 = RspOp.rs;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction; info->flags = GPR_Instruction;
break; break;
case RSP_LUI: case RSP_LUI:
info->DestReg = RspOp->rt; info->DestReg = RspOp.rt;
info->SourceReg0 = UNUSED_OPERAND; info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction; info->flags = GPR_Instruction;
break; break;
case RSP_CP0: case RSP_CP0:
switch (RspOp->rs) switch (RspOp.rs)
{ {
case RSP_COP0_MF: case RSP_COP0_MF:
info->DestReg = RspOp->rt; info->DestReg = RspOp.rt;
info->SourceReg0 = UNUSED_OPERAND; info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = 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; info->flags = InvalidOpcode | COPO_MF_Instruction;
} }
@ -524,7 +424,7 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
break; break;
case RSP_COP0_MT: case RSP_COP0_MT:
info->StoredReg = RspOp->rt; info->StoredReg = RspOp.rt;
info->SourceReg0 = UNUSED_OPERAND; info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction | Store_Operation; info->flags = GPR_Instruction | Store_Operation;
@ -533,9 +433,9 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
break; break;
case RSP_CP2: case RSP_CP2:
if ((RspOp->rs & 0x10) != 0) if ((RspOp.rs & 0x10) != 0)
{ {
switch (RspOp->funct) switch (RspOp.funct)
{ {
case RSP_VECTOR_VNOP: case RSP_VECTOR_VNOP:
info->DestReg = UNUSED_OPERAND; 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_VNAND:
case RSP_VECTOR_VNOR: case RSP_VECTOR_VNOR:
case RSP_VECTOR_VNXOR: case RSP_VECTOR_VNXOR:
info->DestReg = RspOp->sa; info->DestReg = RspOp.sa;
info->SourceReg0 = RspOp->rd; info->SourceReg0 = RspOp.rd;
info->SourceReg1 = RspOp->rt; info->SourceReg1 = RspOp.rt;
info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation; info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation;
break; break;
case RSP_VECTOR_VMACF: 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_VMADM:
case RSP_VECTOR_VMADN: case RSP_VECTOR_VMADN:
case RSP_VECTOR_VMADH: case RSP_VECTOR_VMADH:
info->DestReg = RspOp->sa; info->DestReg = RspOp.sa;
info->SourceReg0 = RspOp->rd; info->SourceReg0 = RspOp.rd;
info->SourceReg1 = RspOp->rt; info->SourceReg1 = RspOp.rt;
info->flags = VEC_Instruction | VEC_Accumulate | Accum_Operation; info->flags = VEC_Instruction | VEC_Accumulate | Accum_Operation;
break; break;
case RSP_VECTOR_VADD: 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_VEQ:
case RSP_VECTOR_VGE: case RSP_VECTOR_VGE:
case RSP_VECTOR_VNE: case RSP_VECTOR_VNE:
info->DestReg = RspOp->sa; info->DestReg = RspOp.sa;
info->SourceReg0 = RspOp->rd; info->SourceReg0 = RspOp.rd;
info->SourceReg1 = RspOp->rt; info->SourceReg1 = RspOp.rt;
info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation | Flag_Instruction; info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation | Flag_Instruction;
break; break;
@ -596,45 +496,45 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_VECTOR_VRCPH: case RSP_VECTOR_VRCPH:
case RSP_VECTOR_VRSQL: case RSP_VECTOR_VRSQL:
case RSP_VECTOR_VRSQH: case RSP_VECTOR_VRSQH:
info->DestReg = RspOp->sa; info->DestReg = RspOp.sa;
info->SourceReg0 = RspOp->rt; info->SourceReg0 = RspOp.rt;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation; // Assume reset? info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation; // Assume reset?
break; break;
case RSP_VECTOR_VMRG: case RSP_VECTOR_VMRG:
info->DestReg = RspOp->sa; info->DestReg = RspOp.sa;
info->SourceReg0 = RspOp->rt; info->SourceReg0 = RspOp.rt;
info->SourceReg1 = RspOp->rd; info->SourceReg1 = RspOp.rd;
info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation | Flag_Instruction; // Assume reset? info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation | Flag_Instruction; // Assume reset?
break; break;
case RSP_VECTOR_VSAW: case RSP_VECTOR_VSAW:
// info->flags = InvalidOpcode; // info->flags = InvalidOpcode;
info->DestReg = RspOp->sa; info->DestReg = RspOp.sa;
info->SourceReg0 = UNUSED_OPERAND; info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = VEC_Instruction | Accum_Operation | VEC_Accumulate; info->flags = VEC_Instruction | Accum_Operation | VEC_Accumulate;
break; break;
default: 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; info->flags = InvalidOpcode;
break; break;
} }
} }
else else
{ {
switch (RspOp->rs) switch (RspOp.rs)
{ {
case RSP_COP2_CT: case RSP_COP2_CT:
info->StoredReg = RspOp->rt; info->StoredReg = RspOp.rt;
info->SourceReg0 = UNUSED_OPERAND; info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction | Store_Operation | Flag_Instruction; info->flags = GPR_Instruction | Store_Operation | Flag_Instruction;
break; break;
case RSP_COP2_CF: case RSP_COP2_CF:
info->DestReg = RspOp->rt; info->DestReg = RspOp.rt;
info->SourceReg0 = UNUSED_OPERAND; info->SourceReg0 = UNUSED_OPERAND;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = GPR_Instruction | Load_Operation | Flag_Instruction; 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 // RD is always the vector register, RT is always GPR
case RSP_COP2_MT: case RSP_COP2_MT:
info->DestReg = RspOp->rd; info->DestReg = RspOp.rd;
info->SourceReg0 = RspOp->rt; info->SourceReg0 = RspOp.rt;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = VEC_Instruction | GPR_Instruction | Load_Operation; info->flags = VEC_Instruction | GPR_Instruction | Load_Operation;
break; break;
case RSP_COP2_MF: case RSP_COP2_MF:
info->DestReg = RspOp->rt; info->DestReg = RspOp.rt;
info->SourceReg0 = RspOp->rd; info->SourceReg0 = RspOp.rd;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = VEC_Instruction | GPR_Instruction | Store_Operation; info->flags = VEC_Instruction | GPR_Instruction | Store_Operation;
break; break;
default: 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; info->flags = InvalidOpcode;
break; break;
} }
@ -665,21 +565,21 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
case RSP_LW: case RSP_LW:
case RSP_LBU: case RSP_LBU:
case RSP_LHU: case RSP_LHU:
info->DestReg = RspOp->rt; info->DestReg = RspOp.rt;
info->IndexReg = RspOp->base; info->IndexReg = RspOp.base;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = Load_Operation | GPR_Instruction; info->flags = Load_Operation | GPR_Instruction;
break; break;
case RSP_SB: case RSP_SB:
case RSP_SH: case RSP_SH:
case RSP_SW: case RSP_SW:
info->StoredReg = RspOp->rt; info->StoredReg = RspOp.rt;
info->IndexReg = RspOp->base; info->IndexReg = RspOp.base;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = Store_Operation | GPR_Instruction; info->flags = Store_Operation | GPR_Instruction;
break; break;
case RSP_LC2: case RSP_LC2:
switch (RspOp->rd) switch (RspOp.rd)
{ {
case RSP_LSC2_BV: case RSP_LSC2_BV:
case RSP_LSC2_SV: 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_LV:
case RSP_LSC2_UV: case RSP_LSC2_UV:
case RSP_LSC2_PV: case RSP_LSC2_PV:
info->DestReg = RspOp->rt; info->DestReg = RspOp.rt;
info->IndexReg = RspOp->base; info->IndexReg = RspOp.base;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = Load_Operation | VEC_Instruction; info->flags = Load_Operation | VEC_Instruction;
break; break;
@ -699,13 +599,13 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
info->flags = InvalidOpcode; info->flags = InvalidOpcode;
break; break;
default: 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; info->flags = InvalidOpcode;
break; break;
} }
break; break;
case RSP_SC2: case RSP_SC2:
switch (RspOp->rd) switch (RspOp.rd)
{ {
case RSP_LSC2_BV: case RSP_LSC2_BV:
case RSP_LSC2_SV: 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_HV:
case RSP_LSC2_FV: case RSP_LSC2_FV:
case RSP_LSC2_WV: case RSP_LSC2_WV:
info->DestReg = RspOp->rt; info->DestReg = RspOp.rt;
info->IndexReg = RspOp->base; info->IndexReg = RspOp.base;
info->SourceReg1 = UNUSED_OPERAND; info->SourceReg1 = UNUSED_OPERAND;
info->flags = Store_Operation | VEC_Instruction; info->flags = Store_Operation | VEC_Instruction;
break; break;
@ -727,13 +627,13 @@ void GetInstructionInfo(uint32_t PC, RSPOpcode * RspOp, OPCODE_INFO * info)
info->flags = InvalidOpcode; info->flags = InvalidOpcode;
break; break;
default: 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; info->flags = InvalidOpcode;
break; break;
} }
break; break;
default: 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; info->flags = InvalidOpcode;
break; break;
@ -764,8 +664,8 @@ bool DelaySlotAffectBranch(uint32_t PC)
memset(&infoDelay, 0, sizeof(infoDelay)); memset(&infoDelay, 0, sizeof(infoDelay));
memset(&infoBranch, 0, sizeof(infoBranch)); memset(&infoBranch, 0, sizeof(infoBranch));
GetInstructionInfo(PC, &BranchOp, &infoBranch); GetInstructionInfo(PC, BranchOp, &infoBranch);
GetInstructionInfo(DelayPC, &DelayOp, &infoDelay); GetInstructionInfo(DelayPC, DelayOp, &infoDelay);
if ((infoDelay.flags & COPO_MF_Instruction) == COPO_MF_Instruction) 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 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; OPCODE_INFO info0, info1;
uint32_t InstructionType; uint32_t InstructionType;
GetInstructionInfo(PC - 4, Top, &info0); RSPOpcode TopOpcode;
GetInstructionInfo(PC, Bottom, &info1); TopOpcode.Value = Top.Value();
GetInstructionInfo(PC - 4, TopOpcode, &info0);
GetInstructionInfo(PC, *Bottom, &info1);
#ifdef COMPARE_INSTRUCTIONS_VERBOSE #ifdef COMPARE_INSTRUCTIONS_VERBOSE
CPU_Message("Comparing %s (%X)", RSPOpcodeName(Top->Hex, PC - 4), PC - 4); CPU_Message("Comparing %s (%X)", Top.NameAndParam().c_str(), Top.Address());
CPU_Message("to %s (%X)", RSPOpcodeName(Bottom->Hex, PC), PC); CPU_Message("to %s (%X)", RSPInstruction(PC, Bottom->Value).NameAndParam().c_str(), PC);
#endif #endif
// Usually branches and such // 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 InstructionCount = EndPC - StartPC;
uint32_t Count, ReorderedOps, CurrentPC; 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 (PreviousOp.IsBranch())
if (IsOpcodeBranch(StartPC, PreviousOp))
{ {
// The sub block ends here anyway // The sub block ends here anyway
return; return;
@ -472,7 +471,7 @@ void CRSPRecompiler::ReOrderInstructions(uint32_t StartPC, uint32_t EndPC)
for (Count = 0; Count < InstructionCount; Count += 4) for (Count = 0; Count < InstructionCount; Count += 4)
{ {
CurrentPC = StartPC; CurrentPC = StartPC;
PreviousOp.Value = *(uint32_t *)(m_IMEM + (CurrentPC & 0xFFC)); PreviousOp = RSPInstruction(CurrentPC, *(uint32_t *)(m_IMEM + (CurrentPC & 0xFFC)));
ReorderedOps = 0; ReorderedOps = 0;
for (;;) for (;;)
@ -484,11 +483,11 @@ void CRSPRecompiler::ReOrderInstructions(uint32_t StartPC, uint32_t EndPC)
} }
CurrentOp.Value = *(uint32_t *)(m_IMEM + CurrentPC); CurrentOp.Value = *(uint32_t *)(m_IMEM + CurrentPC);
if (CompareInstructions(CurrentPC, &PreviousOp, &CurrentOp)) if (CompareInstructions(CurrentPC, PreviousOp, &CurrentOp))
{ {
// Move current opcode up // Move current opcode up
*(uint32_t *)(m_IMEM + CurrentPC - 4) = CurrentOp.Value; *(uint32_t *)(m_IMEM + CurrentPC - 4) = CurrentOp.Value;
*(uint32_t *)(m_IMEM + CurrentPC) = PreviousOp.Value; *(uint32_t *)(m_IMEM + CurrentPC) = PreviousOp.Value();
ReorderedOps++; ReorderedOps++;
@ -496,7 +495,7 @@ void CRSPRecompiler::ReOrderInstructions(uint32_t StartPC, uint32_t EndPC)
CPU_Message("Swapped %X and %X", CurrentPC - 4, CurrentPC); CPU_Message("Swapped %X and %X", CurrentPC - 4, CurrentPC);
#endif #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)) if (IsOpcodeNop(CurrentPC) && IsOpcodeNop(CurrentPC + 4) && IsOpcodeNop(CurrentPC + 8))
{ {
@ -734,7 +733,7 @@ void CRSPRecompiler::BuildBranchLabels(void)
{ {
RspOp.Value = *(uint32_t *)(RSPInfo.IMEM + i); 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) if (RspCode.LabelCount >= (sizeof(RspCode.BranchLabels) / sizeof(RspCode.BranchLabels[0])) - 1)
{ {

View File

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

View File

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

View File

@ -1,6 +1,7 @@
#include "RSPInstruction.h" #include "RSPInstruction.h"
#include "RSPRegisters.h" #include "RSPRegisters.h"
#include <Common/StdString.h> #include <Common/StdString.h>
#include <Settings/Settings.h>
RSPInstruction::RSPInstruction(uint32_t Address, uint32_t Instruction) : RSPInstruction::RSPInstruction(uint32_t Address, uint32_t Instruction) :
m_Address(Address) m_Address(Address)
@ -10,7 +11,102 @@ RSPInstruction::RSPInstruction(uint32_t Address, uint32_t Instruction) :
m_Instruction.Value = 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') if (m_Name[0] == '\0')
{ {
@ -19,7 +115,7 @@ const char * RSPInstruction::Name()
return m_Name; return m_Name;
} }
const char * RSPInstruction::Param() const char * RSPInstruction::Param() const
{ {
if (m_Param[0] == '\0') if (m_Param[0] == '\0')
{ {
@ -28,12 +124,17 @@ const char * RSPInstruction::Param()
return m_Param; return m_Param;
} }
std::string RSPInstruction::NameAndParam() std::string RSPInstruction::NameAndParam() const
{ {
return stdstr_f("%s %s", Name(), Param()); 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) 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) 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) 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) 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) 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) switch (m_Instruction.rd)
{ {