RSP: Add RspCodeBlock and update RSPInstruction

This commit is contained in:
zilmar 2025-06-12 21:22:54 +09:30
parent 08f293eafe
commit 825f786c58
7 changed files with 262 additions and 1 deletions

View File

@ -66,6 +66,7 @@
<ClCompile Include="Hle\musyx.cpp" />
<ClCompile Include="Recompiler\Mmx.cpp" />
<ClCompile Include="Recompiler\RspAssembler.cpp" />
<ClCompile Include="Recompiler\RspCodeBlock.cpp" />
<ClCompile Include="Recompiler\RspProfiling.cpp" />
<ClCompile Include="Recompiler\RspRecompilerAnalysis.cpp" />
<ClCompile Include="Recompiler\RspRecompilerCPU-x64.cpp" />
@ -101,6 +102,7 @@
<ClInclude Include="Hle\ucodes.h" />
<ClInclude Include="Recompiler\asmjit.h" />
<ClInclude Include="Recompiler\RspAssembler.h" />
<ClInclude Include="Recompiler\RspCodeBlock.h" />
<ClInclude Include="Recompiler\RspProfiling.h" />
<ClInclude Include="Recompiler\RspRecompilerCPU-x64.h" />
<ClInclude Include="Recompiler\RspRecompilerCPU-x86.h" />

View File

@ -147,6 +147,9 @@
<ClCompile Include="Recompiler\RspAssembler.cpp">
<Filter>Source Files\Recompiler</Filter>
</ClCompile>
<ClCompile Include="Recompiler\RspCodeBlock.cpp">
<Filter>Source Files\Recompiler</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="cpu\RSPInstruction.h">
@ -242,5 +245,8 @@
<ClInclude Include="Recompiler\RspRecompilerCPU-x64.h">
<Filter>Header Files\Recompiler</Filter>
</ClInclude>
<ClInclude Include="Recompiler\RspCodeBlock.h">
<Filter>Header Files\Recompiler</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,86 @@
#include "RspCodeBlock.h"
#include <Common/StdString.h>
#include <Project64-rsp-core/cpu/RspSystem.h>
RspCodeBlock::RspCodeBlock(CRSPSystem & System, uint32_t StartAddress, RspCodeType type) :
m_System(System),
m_StartAddress(StartAddress),
m_CodeType(type),
m_Valid(true)
{
Analyze();
}
bool RspCodeBlock::Valid() const
{
return m_Valid;
}
void RspCodeBlock::Analyze(void)
{
uint32_t Address = m_StartAddress;
uint8_t * IMEM = m_System.m_IMEM;
enum EndHleTaskOp
{
J_0x1118 = 0x09000446
};
bool FoundEnd = false;
for (;;)
{
RSPInstruction Instruction(Address, *(uint32_t *)(IMEM + (Address & 0xFFF)));
if (Instruction.IsConditionalBranch())
{
uint32_t target = Instruction.ConditionalBranchTarget();
if (std::find(m_BranchTargets.begin(), m_BranchTargets.end(), target) == m_BranchTargets.end())
{
m_BranchTargets.insert(target);
}
}
else if (Instruction.IsStaticCall())
{
uint32_t target = Instruction.StaticCallTarget();
if (std::find(m_FunctionCalls.begin(), m_FunctionCalls.end(), target) == m_FunctionCalls.end())
{
m_FunctionCalls.insert(target);
}
}
m_Instructions.push_back(Instruction);
if (FoundEnd)
{
break;
}
if ((m_CodeType == RspCodeType_SUBROUTINE && Instruction.IsJumpReturn()) ||
(m_CodeType == RspCodeType_TASK && Instruction.Value() == J_0x1118))
{
bool JumpBeyond = false;
for (Addresses::iterator itr = m_BranchTargets.begin(); itr != m_BranchTargets.end(); itr++)
{
if (*itr > Address)
{
JumpBeyond = true;
break;
}
}
FoundEnd = !JumpBeyond;
}
Address += 4;
if (Address == 0x2000)
{
m_Valid = false;
return;
}
}
for (Addresses::iterator itr = m_FunctionCalls.begin(); itr != m_FunctionCalls.end(); itr++)
{
RspCodeBlockPtr FunctionCall = std::make_unique<RspCodeBlock>(m_System, *itr, RspCodeType_SUBROUTINE);
if (!FunctionCall->Valid())
{
m_Valid = false;
return;
}
m_FunctionBlocks.push_back(std::move(FunctionCall));
}
}

View File

@ -0,0 +1,42 @@
#pragma once
#include <Project64-rsp-core/cpu/RSPInstruction.h>
#include <memory>
#include <stdint.h>
#include <set>
#include <vector>
class CRSPSystem;
enum RspCodeType {
RspCodeType_TASK,
RspCodeType_SUBROUTINE,
};
class RspCodeBlock
{
typedef std::vector<RSPInstruction> RSPInstructions;
typedef std::set<uint32_t> Addresses;
typedef std::unique_ptr<RspCodeBlock> RspCodeBlockPtr;
typedef std::vector<RspCodeBlockPtr> RspCodeBlocks;
public:
RspCodeBlock(CRSPSystem & System, uint32_t StartAddress, RspCodeType type);
bool Valid() const;
private:
RspCodeBlock();
RspCodeBlock(const RspCodeBlock &);
RspCodeBlock & operator=(const RspCodeBlock &);
void Analyze();
RSPInstructions m_Instructions;
uint32_t m_StartAddress;
RspCodeType m_CodeType;
CRSPSystem & m_System;
Addresses m_BranchTargets;
Addresses m_FunctionCalls;
RspCodeBlocks m_FunctionBlocks;
bool m_Valid;
};

View File

@ -8,9 +8,16 @@ class RSPInstruction
public:
RSPInstruction(uint32_t Address, uint32_t Instruction);
RSPInstruction & operator=(const RSPInstruction &);
RSPInstruction(const RSPInstruction & e);
uint32_t Address() const;
uint32_t ConditionalBranchTarget() const;
uint32_t StaticCallTarget() const;
bool IsBranch() const;
bool IsJumpReturn() const;
bool IsRegisterJump() const;
bool IsStaticCall() const;
bool IsConditionalBranch() const;
bool IsNop() const;
const char * Name() const;
const char * Param() const;
@ -19,7 +26,6 @@ public:
private:
RSPInstruction(void);
RSPInstruction(const RSPInstruction &);
void DecodeName(void) const;
void DecodeSpecialName(void) const;

View File

@ -20,11 +20,52 @@ RSPInstruction & RSPInstruction::operator=(const RSPInstruction & e)
return *this;
}
RSPInstruction::RSPInstruction(const RSPInstruction & e) :
m_Address(e.m_Address)
{
m_Name[0] = '\0';
m_Param[0] = '\0';
m_Instruction.Value = e.m_Instruction.Value;
}
uint32_t RSPInstruction::Address() const
{
return m_Address;
}
uint32_t RSPInstruction::ConditionalBranchTarget() const
{
if (!IsConditionalBranch())
{
return 0;
}
return (m_Address + 4 + ((short)m_Instruction.offset << 2)) & 0x1FFC;
}
uint32_t RSPInstruction::StaticCallTarget() const
{
if (!IsStaticCall())
{
return 0;
}
return 0x1000 | (m_Instruction.target << 2) & 0xFFC;
}
bool RSPInstruction::IsJumpReturn() const
{
return IsRegisterJump() && m_Instruction.rs == 31;
}
bool RSPInstruction::IsRegisterJump() const
{
return m_Instruction.op == RSP_SPECIAL && (m_Instruction.funct == RSP_SPECIAL_JR || m_Instruction.funct == RSP_SPECIAL_JALR);
}
bool RSPInstruction::IsStaticCall() const
{
return m_Instruction.op == RSP_JAL;
}
bool RSPInstruction::IsBranch() const
{
switch (m_Instruction.op)
@ -106,6 +147,83 @@ bool RSPInstruction::IsBranch() const
return false;
}
bool RSPInstruction::IsConditionalBranch() 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:
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:
case RSP_SPECIAL_JALR:
case RSP_SPECIAL_JR:
default:
break;
}
break;
case RSP_J:
case RSP_JAL:
break;
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;
}
bool RSPInstruction::IsNop() const
{
return m_Instruction.op == RSP_SPECIAL && m_Instruction.funct == RSP_SPECIAL_SLL && m_Instruction.rd == 0;

View File

@ -17,6 +17,7 @@ class CRSPSystem :
friend class RSPOp;
friend class CRSPRecompilerOps;
friend class CRSPRecompiler;
friend class RspCodeBlock;
friend class CHleTask;
friend class RSPDebuggerUI;
friend class CRDPLog;