RSP: Add RspCodeBlock and update RSPInstruction
This commit is contained in:
parent
08f293eafe
commit
825f786c58
|
@ -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" />
|
||||
|
|
|
@ -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>
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue