RSP: Create CRSPRecompiler

This commit is contained in:
zilmar 2024-08-08 09:39:45 +09:30
parent f7ab608976
commit 762d1b1566
7 changed files with 112 additions and 89 deletions

View File

@ -26,7 +26,6 @@ uint32_t CompilePC, JumpTableSize, BlockID = 0;
uint32_t dwBuffer = MainBuffer;
bool ChangedPC;
RSP_BLOCK CurrentBlock;
RSP_CODE RspCode;
RSP_COMPILER Compiler;
@ -41,6 +40,11 @@ p_Recompfunc RSP_Recomp_Vector[64];
p_Recompfunc RSP_Recomp_Lc2[32];
p_Recompfunc RSP_Recomp_Sc2[32];
CRSPRecompiler::CRSPRecompiler(CRSPSystem & System) :
m_System(System)
{
}
void BuildRecompilerCPU(void)
{
RSP_Recomp_Opcode[0] = &CRSPRecompilerOps::SPECIAL;
@ -506,7 +510,7 @@ void ReOrderInstructions(uint32_t StartPC, uint32_t EndPC)
CPU_Message("");
}
void ReOrderSubBlock(RSP_BLOCK * Block)
void CRSPRecompiler::ReOrderSubBlock(RSP_BLOCK * Block)
{
uint32_t end = 0x0ffc;
uint32_t count;
@ -641,7 +645,7 @@ Description:
Resolves all the collected branches, x86 style
*/
void LinkBranches(RSP_BLOCK * Block)
void CRSPRecompiler::LinkBranches(RSP_BLOCK * Block)
{
uint32_t OrigPrgCount = *PrgCount;
uint32_t Count, Target;
@ -649,15 +653,15 @@ void LinkBranches(RSP_BLOCK * Block)
uint8_t * X86Code;
RSP_BLOCK Save;
if (!CurrentBlock.ResolveCount)
if (!m_CurrentBlock.ResolveCount)
{
return;
}
CPU_Message("***** Linking branches (%i) *****", CurrentBlock.ResolveCount);
CPU_Message("***** Linking branches (%i) *****", m_CurrentBlock.ResolveCount);
for (Count = 0; Count < CurrentBlock.ResolveCount; Count++)
for (Count = 0; Count < m_CurrentBlock.ResolveCount; Count++)
{
Target = CurrentBlock.BranchesToResolve[Count].TargetPC;
Target = m_CurrentBlock.BranchesToResolve[Count].TargetPC;
X86Code = (uint8_t *)*(JumpTable + (Target >> 2));
if (!X86Code)
@ -677,7 +681,7 @@ void LinkBranches(RSP_BLOCK * Block)
X86Code = (uint8_t *)*(JumpTable + (Target >> 2));
}
JumpWord = CurrentBlock.BranchesToResolve[Count].X86JumpLoc;
JumpWord = m_CurrentBlock.BranchesToResolve[Count].X86JumpLoc;
x86_SetBranch32b(JumpWord, (uint32_t *)X86Code);
CPU_Message("Linked RSP branch from x86: %08X, to RSP: %X / x86: %08X",
@ -786,18 +790,18 @@ void CompilerLinkBlocks(void)
x86_SetBranch32b(RecompPos - 4, KnownCode);
}
void CompilerRSPBlock(void)
void CRSPRecompiler::CompilerRSPBlock(void)
{
CRSPRecompilerOps RecompilerOps(RSPSystem);
CRSPRecompilerOps RecompilerOps(RSPSystem, *this);
uint8_t * IMEM_SAVE = (uint8_t *)malloc(0x1000);
const size_t X86BaseAddress = (size_t)RecompPos;
NextInstruction = RSPPIPELINE_NORMAL;
CompilePC = *PrgCount;
memset(&CurrentBlock, 0, sizeof(CurrentBlock));
CurrentBlock.StartPC = CompilePC;
CurrentBlock.CurrPC = CompilePC;
memset(&m_CurrentBlock, 0, sizeof(m_CurrentBlock));
m_CurrentBlock.StartPC = CompilePC;
m_CurrentBlock.CurrPC = CompilePC;
// Align the block to a boundary
if (X86BaseAddress & 7)
@ -815,13 +819,13 @@ void CompilerRSPBlock(void)
CPU_Message("====== Block %d ======", BlockID++);
CPU_Message("x86 code at: %X", RecompPos);
CPU_Message("Jump table: %X", Table);
CPU_Message("Start of block: %X", CurrentBlock.StartPC);
CPU_Message("Start of block: %X", m_CurrentBlock.StartPC);
CPU_Message("====== Recompiled code ======");
if (Compiler.bReOrdering)
{
memcpy(IMEM_SAVE, RSPInfo.IMEM, 0x1000);
ReOrderSubBlock(&CurrentBlock);
ReOrderSubBlock(&m_CurrentBlock);
}
// This is for the block about to be compiled
@ -843,8 +847,8 @@ void CompilerRSPBlock(void)
*(JumpTable + (CompilePC >> 2)) = RecompPos;
// Reorder from here to next label or branch
CurrentBlock.CurrPC = CompilePC;
ReOrderSubBlock(&CurrentBlock);
m_CurrentBlock.CurrPC = CompilePC;
ReOrderSubBlock(&m_CurrentBlock);
}
else if (NextInstruction != RSPPIPELINE_DELAY_SLOT_DONE)
{
@ -918,9 +922,9 @@ void CompilerRSPBlock(void)
CPU_Message("***** Continuing static SubBlock (jump table entry added for PC: %04X at X86: %08X) *****", CompilePC, RecompPos);
*(JumpTable + (CompilePC >> 2)) = RecompPos;
CurrentBlock.CurrPC = CompilePC;
m_CurrentBlock.CurrPC = CompilePC;
// Reorder from after delay to next label or branch
ReOrderSubBlock(&CurrentBlock);
ReOrderSubBlock(&m_CurrentBlock);
}
else
{
@ -955,7 +959,7 @@ void CompilerRSPBlock(void)
free(IMEM_SAVE);
}
uint32_t RunRecompilerCPU(uint32_t Cycles)
uint32_t CRSPRecompiler::RunCPU(uint32_t Cycles)
{
#ifndef EXCEPTION_EXECUTE_HANDLER
#define EXCEPTION_EXECUTE_HANDLER 1
@ -1005,7 +1009,7 @@ uint32_t RunRecompilerCPU(uint32_t Cycles)
// to fill in still either from this block, or jumps
// that go out of it, let's rock
LinkBranches(&CurrentBlock);
LinkBranches(&m_CurrentBlock);
if (Profiling && !IndvidualBlock)
{
StopTimer();
@ -1046,3 +1050,28 @@ uint32_t RunRecompilerCPU(uint32_t Cycles)
}
return Cycles;
}
void CRSPRecompiler::Branch_AddRef(uint32_t Target, uint32_t * X86Loc)
{
if (m_CurrentBlock.ResolveCount >= 150)
{
CompilerWarning("Out of branch reference space");
}
else
{
uint8_t * KnownCode = (uint8_t *)(*(JumpTable + (Target >> 2)));
if (KnownCode == NULL)
{
uint32_t i = m_CurrentBlock.ResolveCount;
m_CurrentBlock.BranchesToResolve[i].TargetPC = Target;
m_CurrentBlock.BranchesToResolve[i].X86JumpLoc = X86Loc;
m_CurrentBlock.ResolveCount += 1;
}
else
{
CPU_Message(" (static jump to %X)", KnownCode);
x86_SetBranch32b((uint32_t *)X86Loc, (uint32_t *)KnownCode);
}
}
}

View File

@ -5,6 +5,44 @@
#include <Project64-rsp-core/cpu/RspTypes.h>
#include <Settings/Settings.h>
class CRSPSystem;
class CRSPRecompiler
{
friend class CRSPRecompilerOps;
typedef struct
{
uint32_t StartPC, CurrPC; // Block start
struct
{
uint32_t TargetPC; // Target for this unknown branch
uint32_t * X86JumpLoc; // Our x86 uint32_t to fill
} BranchesToResolve[200]; // Branches inside or outside block
uint32_t ResolveCount; // Branches with NULL jump table
} RSP_BLOCK;
public:
CRSPRecompiler(CRSPSystem & System);
uint32_t RunCPU(uint32_t Cycles);
void Branch_AddRef(uint32_t Target, uint32_t * X86Loc);
private:
CRSPRecompiler();
CRSPRecompiler(const CRSPRecompiler &);
CRSPRecompiler & operator=(const CRSPRecompiler &);
void CompilerRSPBlock(void);
void LinkBranches(RSP_BLOCK * Block);
void ReOrderSubBlock(RSP_BLOCK * Block);
CRSPSystem & m_System;
RSP_BLOCK m_CurrentBlock;
};
extern uint32_t CompilePC, NextInstruction, JumpTableSize;
extern bool ChangedPC;
@ -28,33 +66,13 @@ bool IsOpcodeNop(uint32_t PC);
bool IsNextInstructionMmx(uint32_t PC);
bool IsRegisterConstant(uint32_t Reg, uint32_t * Constant);
void RSP_Element2Mmx(int MmxReg);
void RSP_MultiElement2Mmx(int MmxReg1, int MmxReg2);
#define MainBuffer 0
#define SecondaryBuffer 1
uint32_t RunRecompilerCPU(uint32_t Cycles);
void BuildRecompilerCPU(void);
void CompilerRSPBlock(void);
void CompilerToggleBuffer(void);
typedef struct
{
uint32_t StartPC, CurrPC; // Block start
struct
{
uint32_t TargetPC; // Target for this unknown branch
uint32_t * X86JumpLoc; // Our x86 uint32_t to fill
} BranchesToResolve[200]; // Branches inside or outside block
uint32_t ResolveCount; // Branches with NULL jump table
} RSP_BLOCK;
extern RSP_BLOCK CurrentBlock;
typedef struct
{
bool bIsRegConst[32]; // bool toggle for constant

View File

@ -98,31 +98,6 @@ extern p_Recompfunc RSP_Recomp_Vector[64];
extern p_Recompfunc RSP_Recomp_Lc2[32];
extern p_Recompfunc RSP_Recomp_Sc2[32];
void Branch_AddRef(uint32_t Target, uint32_t * X86Loc)
{
if (CurrentBlock.ResolveCount >= 150)
{
CompilerWarning("Out of branch reference space");
}
else
{
uint8_t * KnownCode = (uint8_t *)(*(JumpTable + (Target >> 2)));
if (KnownCode == NULL)
{
uint32_t i = CurrentBlock.ResolveCount;
CurrentBlock.BranchesToResolve[i].TargetPC = Target;
CurrentBlock.BranchesToResolve[i].X86JumpLoc = X86Loc;
CurrentBlock.ResolveCount += 1;
}
else
{
CPU_Message(" (static jump to %X)", KnownCode);
x86_SetBranch32b((uint32_t *)X86Loc, (uint32_t *)KnownCode);
}
}
}
void CRSPRecompilerOps::Cheat_r4300iOpcode(RSPOp::Func FunctAddress, const char * FunctName)
{
CPU_Message(" %X %s", CompilePC, RSPInstruction(CompilePC, RSPOpC.Value).NameAndParam().c_str());
@ -183,8 +158,9 @@ void CompileBranchExit(uint32_t TargetPC, uint32_t ContinuePC)
Ret();
}
CRSPRecompilerOps::CRSPRecompilerOps(CRSPSystem & System) :
CRSPRecompilerOps::CRSPRecompilerOps(CRSPSystem & System, CRSPRecompiler & Recompiler) :
m_System(System),
m_Recompiler(Recompiler),
m_Reg(System.m_Reg),
m_GPR(System.m_Reg.m_GPR),
m_ACCUM(System.m_Reg.m_ACCUM),
@ -215,7 +191,7 @@ void CRSPRecompilerOps::J(void)
else if (NextInstruction == RSPPIPELINE_DELAY_SLOT_DONE)
{
JmpLabel32("BranchToJump", 0);
Branch_AddRef((RSPOpC.target << 2) & 0xFFC, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef((RSPOpC.target << 2) & 0xFFC, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
}
else if (NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
@ -253,7 +229,7 @@ void CRSPRecompilerOps::JAL(void)
Pop(x86_EAX);
}
JmpLabel32("BranchToJump", 0);
Branch_AddRef((RSPOpC.target << 2) & 0xFFC, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef((RSPOpC.target << 2) & 0xFFC, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
}
else if (NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
@ -311,7 +287,7 @@ void CRSPRecompilerOps::BEQ(void)
if (RSPOpC.rs == 0 && RSPOpC.rt == 0)
{
JmpLabel32("BranchToJump", 0);
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
return;
}
@ -338,7 +314,7 @@ void CRSPRecompilerOps::BEQ(void)
CompConstToVariable(true, &BranchCompare, "BranchCompare");
JeLabel32("BranchEqual", 0);
}
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
}
else if (NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
@ -422,7 +398,7 @@ void CRSPRecompilerOps::BNE(void)
CompConstToVariable(true, &BranchCompare, "BranchCompare");
JeLabel32("BranchNotEqual", 0);
}
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
}
else if (NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
@ -466,7 +442,7 @@ void CRSPRecompilerOps::BLEZ(void)
if (RSPOpC.rs == 0)
{
JmpLabel32("BranchToJump", 0);
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
return;
}
@ -482,7 +458,7 @@ void CRSPRecompilerOps::BLEZ(void)
JeLabel32("BranchLessEqual", 0);
}
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
}
else if (NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
@ -539,7 +515,7 @@ void CRSPRecompilerOps::BGTZ(void)
CompConstToVariable(true, &BranchCompare, "BranchCompare");
JeLabel32("BranchGreater", 0);
}
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
}
else if (NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
@ -2002,7 +1978,7 @@ void CRSPRecompilerOps::RegImm_BLTZ(void)
CompConstToVariable(true, &BranchCompare, "BranchCompare");
JeLabel32("BranchLess", 0);
}
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
}
else if (NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
@ -2046,7 +2022,7 @@ void CRSPRecompilerOps::RegImm_BGEZ(void)
if (RSPOpC.rs == 0)
{
JmpLabel32("BranchToJump", 0);
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
return;
}
@ -2061,7 +2037,7 @@ void CRSPRecompilerOps::RegImm_BGEZ(void)
CompConstToVariable(true, &BranchCompare, "BranchCompare");
JeLabel32("BranchGreaterEqual", 0);
}
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
}
else if (NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
@ -2105,7 +2081,7 @@ void CRSPRecompilerOps::RegImm_BLTZAL(void)
// Take a look at the branch compare variable
CompConstToVariable(true, &BranchCompare, "BranchCompare");
JeLabel32("BranchLessEqual", 0);
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
}
else if (NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
@ -2151,7 +2127,7 @@ void CRSPRecompilerOps::RegImm_BGEZAL(void)
if (RSPOpC.rs == 0)
{
JmpLabel32("BranchToJump", 0);
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
return;
}
@ -2167,7 +2143,7 @@ void CRSPRecompilerOps::RegImm_BGEZAL(void)
CompConstToVariable(true, &BranchCompare, "BranchCompare");
JeLabel32("BranchGreaterEqual", 0);
}
Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
}
else if (NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)

View File

@ -7,7 +7,7 @@ class CRSPRegisters;
class CRSPRecompilerOps
{
public:
CRSPRecompilerOps(CRSPSystem & System);
CRSPRecompilerOps(CRSPSystem & System, CRSPRecompiler & Recompiler);
void SPECIAL(void);
void REGIMM(void);
@ -203,6 +203,7 @@ private:
CRSPSystem & m_System;
CRSPRegisters & m_Reg;
CRSPRecompiler & m_Recompiler;
UWORD32 * m_GPR;
UDWORD * m_ACCUM;
UWORD32 * m_Flags;

View File

@ -3,6 +3,7 @@
#include <Project64-rsp-core/Hle/hle.h>
#include <Project64-rsp-core/RSPDebugger.h>
#include <Project64-rsp-core/RSPInfo.h>
#include <Project64-rsp-core/Recompiler/RspRecompilerCPU.h>
#include <Project64-rsp-core/Settings/RspSettings.h>
#include <Project64-rsp-core/cpu/RSPRegisters.h>
#include <Project64-rsp-core/cpu/RspSystem.h>
@ -112,9 +113,6 @@ be greater than the number of cycles that the RSP should have performed.
(this value is ignored if the RSP has been stopped)
*/
uint32_t RunInterpreterCPU(uint32_t Cycles);
uint32_t RunRecompilerCPU(uint32_t Cycles);
#define MI_INTR_SP 0x01 /* Bit 0: SP intr */
uint32_t DoRspCycles(uint32_t Cycles)
@ -183,7 +181,7 @@ uint32_t DoRspCycles(uint32_t Cycles)
switch (g_CPUCore)
{
case RecompilerCPU:
RunRecompilerCPU(Cycles);
CRSPRecompiler(RSPSystem).RunCPU(Cycles);
break;
case InterpreterCPU:
RSPSystem.RunInterpreterCPU(Cycles);

View File

@ -22,5 +22,3 @@ extern uint32_t RSP_JumpTo;
// Returns the new PC, based on whether the condition passes
unsigned int RSP_branch_if(int condition);
uint32_t RunInterpreterCPU(uint32_t Cycles);

View File

@ -6,11 +6,14 @@ class CRSPRegisters;
class RSPOp
{
friend class CRSPSystem;
friend class CRSPRecompilerOps;
public:
RSPOp(CRSPSystem & System);
~RSPOp();
public:
private:
RSPOp();
RSPOp(const RSPOp &);
RSPOp & operator=(const RSPOp &);