Start to look at x64 recompiler

This commit is contained in:
zilmar 2023-04-04 17:44:42 +09:30
parent fe35d950f3
commit 2c40d47a34
18 changed files with 382 additions and 327 deletions

View File

@ -53,6 +53,7 @@ add_library(Project64-core STATIC
N64System/Recompiler/JumpInfo.cpp
N64System/Recompiler/LoopAnalysis.cpp
N64System/Recompiler/Recompiler.cpp
N64System/Recompiler/RecompilerOps.cpp
N64System/Recompiler/RecompilerMemory.cpp
N64System/Recompiler/RegBase.cpp
N64System/Recompiler/Aarch64/Aarch64ops.cpp

View File

@ -246,7 +246,6 @@ protected:
static Func Jump_CoP1_L[64];
static void GenerateAddressErrorException(uint64_t VAddr, bool FromRead);
static void GenerateFloatingPointException(void);
static void GenerateOverflowException(void);
static void GenerateTLBReadException(uint64_t VAddr, const char * function);
static void GenerateTLBWriteException(uint64_t VAddr, const char * function);

View File

@ -1482,29 +1482,25 @@ void CN64System::SyncCPU(CN64System * const SecondCPU)
if (bFastSP() && m_Recomp)
{
#if defined(__aarch64__) || defined(__amd64__) || defined(_M_X64)
g_Notify->BreakPoint(__FILE__, __LINE__);
#else
uint32_t StackPointer = (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF);
uint32_t TargetStackPos = 0;
uint8_t * TargetStackPos = nullptr;
if (StackPointer < m_MMU_VM.RdramSize())
{
TargetStackPos = (uint32_t)(m_MMU_VM.Rdram() + StackPointer);
TargetStackPos = m_MMU_VM.Rdram() + StackPointer;
}
else if (StackPointer > 0x04000000 && StackPointer < 0x04001000)
{
TargetStackPos = (uint32_t)(m_MMU_VM.Dmem() + StackPointer - 0x04000000);
TargetStackPos = m_MMU_VM.Dmem() + StackPointer - 0x04000000;
}
else if (StackPointer > 0x04001000 && StackPointer < 0x04002000)
{
TargetStackPos = (uint32_t)(m_MMU_VM.Imem() + StackPointer - 0x04001000);
TargetStackPos = m_MMU_VM.Imem() + StackPointer - 0x04001000;
}
if (m_Recomp->MemoryStackPos() != TargetStackPos)
{
ErrorFound = true;
}
#endif
}
if (m_SystemTimer != SecondCPU->m_SystemTimer)
@ -1679,29 +1675,25 @@ void CN64System::DumpSyncErrors(CN64System * SecondCPU)
}
if (bFastSP() && m_Recomp)
{
#if defined(__aarch64__) || defined(__amd64__) || defined(_M_X64)
g_Notify->BreakPoint(__FILE__, __LINE__);
#else
uint32_t StackPointer = (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF);
uint32_t TargetStackPos = 0;
uint8_t * TargetStackPos = nullptr;
if (StackPointer < m_MMU_VM.RdramSize())
{
TargetStackPos = (uint32_t)(m_MMU_VM.Rdram() + StackPointer);
TargetStackPos = m_MMU_VM.Rdram() + StackPointer;
}
else if (StackPointer > 0x04000000 && StackPointer < 0x04001000)
{
TargetStackPos = (uint32_t)(m_MMU_VM.Dmem() + StackPointer - 0x04000000);
TargetStackPos = m_MMU_VM.Dmem() + StackPointer - 0x04000000;
}
else if (StackPointer > 0x04001000 && StackPointer < 0x04002000)
{
TargetStackPos = (uint32_t)(m_MMU_VM.Imem() + StackPointer - 0x04001000);
TargetStackPos = m_MMU_VM.Imem() + StackPointer - 0x04001000;
}
if (m_Recomp->MemoryStackPos() != TargetStackPos)
{
Error.LogF("MemoryStack = %X should be: %X\r\n", m_Recomp->MemoryStackPos(), (uint32_t)(m_MMU_VM.Rdram() + (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF)));
Error.LogF("MemoryStack = %p should be: %p\r\n", m_Recomp->MemoryStackPos(), (uint32_t)(m_MMU_VM.Rdram() + (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF)));
}
#endif
}
uint32_t *Rdram = (uint32_t *)m_MMU_VM.Rdram(), *Rdram2 = (uint32_t *)SecondCPU->m_MMU_VM.Rdram();

View File

@ -13,7 +13,7 @@
extern "C" void __clear_cache_android(uint8_t * begin, uint8_t * end);
#endif
CCodeBlock::CCodeBlock(CMipsMemoryVM & MMU, uint32_t VAddrEnter) :
CCodeBlock::CCodeBlock(CMipsMemoryVM & MMU, CRegisters & Reg, uint32_t VAddrEnter) :
m_MMU(MMU),
m_VAddrEnter(VAddrEnter),
m_VAddrFirst(VAddrEnter),
@ -34,7 +34,9 @@ CCodeBlock::CCodeBlock(CMipsMemoryVM & MMU, uint32_t VAddrEnter) :
}
#endif
#if defined(__i386__) || defined(_M_IX86)
m_RecompilerOps = new CX86RecompilerOps(MMU, *this);
m_RecompilerOps = new CX86RecompilerOps(MMU, Reg, *this);
#elif defined(__amd64__) || defined(_M_X64)
m_RecompilerOps = new CX64RecompilerOps(MMU, Reg, *this);
#elif defined(__arm__) || defined(_M_ARM)
m_RecompilerOps = new CArmRecompilerOps(MMU, *this);
#else

View File

@ -13,7 +13,7 @@ class CCodeBlock :
public asmjit::ErrorHandler
{
public:
CCodeBlock(CMipsMemoryVM & MMU, uint32_t VAddrEnter);
CCodeBlock(CMipsMemoryVM & MMU, CRegisters & Reg, uint32_t VAddrEnter);
~CCodeBlock();
bool Compile();

View File

@ -357,7 +357,6 @@ bool CCodeSection::ParentContinue()
bool CCodeSection::GenerateNativeCode(uint32_t Test)
{
#if defined(__i386__) || defined(_M_IX86)
if (m_EnterLabel.isValid())
{
if (m_Test == Test)
@ -785,10 +784,6 @@ bool CCodeSection::GenerateNativeCode(uint32_t Test)
m_RecompilerOps->SetNextStepType(PIPELINE_STAGE_END_BLOCK);
}
} while (m_RecompilerOps->GetNextStepType() != PIPELINE_STAGE_END_BLOCK);
#else
Test = Test;
g_Notify->BreakPoint(__FILE__, __LINE__);
#endif
return true;
}

View File

@ -374,7 +374,7 @@ CCompiledFunc * CRecompiler::CompileCode()
CheckRecompMem();
WriteTrace(TraceRecompiler, TraceDebug, "Compile Block-Start: Program Counter: %X pAddr: %X", PROGRAM_COUNTER, pAddr);
CCodeBlock CodeBlock(m_MMU, PROGRAM_COUNTER);
CCodeBlock CodeBlock(m_MMU, m_Registers, PROGRAM_COUNTER);
if (!CodeBlock.Compile())
{
return nullptr;

View File

@ -0,0 +1,15 @@
#include "stdafx.h"
#include "RecompilerOps.h"
CRecompilerOpsBase::CRecompilerOpsBase(CMipsMemoryVM & MMU, CRegisters & Reg, CCodeBlock & CodeBlock) :
m_Reg(Reg),
m_MMU(MMU),
m_CodeBlock(CodeBlock),
m_Section(nullptr)
{
}
CRecompilerOpsBase::~CRecompilerOpsBase()
{
}

View File

@ -1,4 +1,6 @@
#pragma once
#include <Project64-core\N64System\Mips\R4300iOpcode.h>
#include <Project64-core\Settings\DebugSettings.h>
enum RecompilerBranchType
{
@ -35,6 +37,29 @@ enum RecompilerTrapCompare
RecompilerTrapCompare_TLTIU,
};
class CCodeBlock;
class CCodeSection;
class CMipsMemoryVM;
class CRegisters;
class CRecompilerOpsBase :
protected CDebugSettings
{
protected:
CRecompilerOpsBase(CMipsMemoryVM & MMU, CRegisters & Reg, CCodeBlock & CodeBlock);
~CRecompilerOpsBase();
CMipsMemoryVM & m_MMU;
CRegisters & m_Reg;
CCodeBlock & m_CodeBlock;
R4300iOpcode m_Opcode;
CCodeSection * m_Section;
private:
CRecompilerOpsBase(const CRecompilerOpsBase &);
CRecompilerOpsBase & operator=(const CRecompilerOpsBase &);
};
#if defined(__i386__) || defined(_M_IX86)
#include <Project64-core/N64System/Recompiler/x86/x86RecompilerOps.h>

View File

@ -1,9 +1,12 @@
#include "stdafx.h"
#if defined(__amd64__) || defined(_M_X64)
#include <Project64-core/N64System/Recompiler/x64-86/x64RecompilerOps.h>
#include <Project64-core\N64System\Recompiler\CodeBlock.h>
#include <Project64-core\N64System\Recompiler\CodeSection.h>
#include <Project64-core\N64System\Recompiler\x64-86\x64RecompilerOps.h>
CX64RecompilerOps::CX64RecompilerOps(CMipsMemoryVM & /*MMU*/, CCodeBlock & CodeBlock) :
CX64RecompilerOps::CX64RecompilerOps(CMipsMemoryVM & MMU, CRegisters & Reg, CCodeBlock & CodeBlock) :
CRecompilerOpsBase(MMU, Reg, CodeBlock),
m_Assembler(CodeBlock),
m_RegWorkingSet(CodeBlock, m_Assembler)
{
@ -795,12 +798,10 @@ void CX64RecompilerOps::UnknownOpcode()
void CX64RecompilerOps::EnterCodeBlock()
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CX64RecompilerOps::CompileExitCode()
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CX64RecompilerOps::CompileInPermLoop(CRegInfo & /*RegSet*/, uint32_t /*ProgramCounter*/)
@ -813,14 +814,14 @@ void CX64RecompilerOps::SyncRegState(const CRegInfo & /*SyncTo*/)
g_Notify->BreakPoint(__FILE__, __LINE__);
}
CRegInfo & CX64RecompilerOps::GetRegWorkingSet(void)
CX64RegInfo & CX64RecompilerOps::GetRegWorkingSet(void)
{
return m_RegWorkingSet;
}
void CX64RecompilerOps::SetRegWorkingSet(const CRegInfo & /*RegInfo*/)
void CX64RecompilerOps::SetRegWorkingSet(const CX64RegInfo & RegInfo)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
m_RegWorkingSet = RegInfo;
}
bool CX64RecompilerOps::InheritParentInfo()

View File

@ -1,22 +1,19 @@
#pragma once
#if defined(__amd64__) || defined(_M_X64)
#include <Project64-core/N64System/Mips/R4300iOpcode.h>
#include <Project64-core/N64System/Recompiler/ExitInfo.h>
#include <Project64-core/N64System/Recompiler/RecompilerOps.h>
#include <Project64-core/N64System/Recompiler/RegInfo.h>
#include <Project64-core/N64System/Recompiler/x64-86/x64ops.h>
class CMipsMemoryVM;
class CCodeBlock;
class CCodeSection;
class CX64Ops;
struct CJumpInfo;
class CX64RecompilerOps
class CX64RecompilerOps :
public CRecompilerOpsBase
{
public:
CX64RecompilerOps(CMipsMemoryVM & MMU, CCodeBlock & CodeBlock);
CX64RecompilerOps(CMipsMemoryVM & MMU, CRegisters & Reg, CCodeBlock & CodeBlock);
~CX64RecompilerOps();
// Trap functions
@ -203,8 +200,8 @@ public:
void CompileExitCode();
void CompileInPermLoop(CRegInfo & RegSet, uint32_t ProgramCounter);
void SyncRegState(const CRegInfo & SyncTo);
CRegInfo & GetRegWorkingSet(void);
void SetRegWorkingSet(const CRegInfo & RegInfo);
CX64RegInfo & GetRegWorkingSet(void);
void SetRegWorkingSet(const CX64RegInfo & RegInfo);
bool InheritParentInfo();
void LinkJump(CJumpInfo & JumpInfo, uint32_t SectionID = -1, uint32_t FromSectionID = -1);
void JumpToSection(CCodeSection * Section);
@ -235,7 +232,6 @@ private:
CX64RegInfo m_RegWorkingSet;
CX64Ops m_Assembler;
R4300iOpcode m_Opcode;
};
typedef CX64RecompilerOps CRecompilerOps;

View File

@ -19,20 +19,28 @@ CX64RegInfo::~CX64RegInfo()
CX64RegInfo & CX64RegInfo::operator=(const CX64RegInfo & right)
{
CRegBase::operator=(right);
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef _DEBUG
if (*this != right)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
#endif
return *this;
}
bool CX64RegInfo::operator==(const CX64RegInfo & /*right*/) const
bool CX64RegInfo::operator==(const CX64RegInfo & Right) const
{
g_Notify->BreakPoint(__FILE__, __LINE__);
return false;
if (!CRegBase::operator==(Right))
{
return false;
}
return true;
}
bool CX64RegInfo::operator!=(const CX64RegInfo & /*right*/) const
bool CX64RegInfo::operator!=(const CX64RegInfo & Right) const
{
g_Notify->BreakPoint(__FILE__, __LINE__);
return false;
return !(Right == *this);
}
void CX64RegInfo::UnMap_GPR(uint32_t /*Reg*/, bool /*WriteBackValue*/)

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#if defined(__amd64__) || defined(_M_X64)
#include <Project64-core/N64System/Recompiler/CodeBlock.h>
#include <Project64-core/N64System/Recompiler/x64-86/x64ops.h>
CX64Ops::CX64Ops(CCodeBlock & CodeBlock) :
@ -8,4 +9,16 @@ CX64Ops::CX64Ops(CCodeBlock & CodeBlock) :
{
}
asmjit::Error CX64Ops::_log(const char * data, size_t size) noexcept
{
stdstr AsmjitLog(std::string(data, size));
AsmjitLog.Trim("\n");
for (SymbolMap::const_iterator itr = m_Symbols.begin(); itr != m_Symbols.end(); itr++)
{
AsmjitLog.Replace(itr->first, itr->second);
}
m_CodeBlock.Log(" %s", AsmjitLog.c_str());
return asmjit::kErrorOk;
}
#endif

View File

@ -1,9 +1,14 @@
#pragma once
#if defined(__amd64__) || defined(_M_X64)
#include <Project64-core/N64System/Recompiler/asmjit.h>
#include <map>
#include <string>
class CCodeBlock;
class CX64Ops
class CX64Ops :
public asmjit::x86::Assembler,
public asmjit::Logger
{
public:
CX64Ops(CCodeBlock & CodeBlock);
@ -13,6 +18,11 @@ private:
CX64Ops(const CX64Ops &);
CX64Ops & operator=(const CX64Ops &);
asmjit::Error _log(const char * data, size_t size) noexcept;
typedef std::map<std::string, std::string> SymbolMap;
SymbolMap m_Symbols;
CCodeBlock & m_CodeBlock;
};

View File

@ -2,7 +2,6 @@
#if defined(__i386__) || defined(_M_IX86)
#include <Project64-core/N64System/Interpreter/InterpreterOps.h>
#include <Project64-core/N64System/Mips/R4300iOpcode.h>
#include <Project64-core/N64System/Mips/Register.h>
#include <Project64-core/N64System/Recompiler/ExitInfo.h>
#include <Project64-core/N64System/Recompiler/JumpInfo.h>
@ -18,13 +17,14 @@ class CCodeBlock;
class CCodeSection;
class CX86RecompilerOps :
protected R4300iOp,
public CRecompilerOpsBase,
protected CN64SystemSettings,
protected CRecompilerSettings,
protected CLogSettings,
private CGameSettings
{
public:
CX86RecompilerOps(CMipsMemoryVM & MMU, CCodeBlock & CodeBlock);
CX86RecompilerOps(CMipsMemoryVM & MMU, CRegisters & Reg, CCodeBlock & CodeBlock);
~CX86RecompilerOps();
// Trap functions
@ -445,14 +445,10 @@ private:
void ResetMemoryStack();
EXIT_LIST m_ExitInfo;
CMipsMemoryVM & m_MMU;
CCodeBlock & m_CodeBlock;
CX86Ops m_Assembler;
PIPELINE_STAGE m_PipelineStage;
uint32_t m_CompilePC;
R4300iOpcode m_Opcode;
CX86RegInfo m_RegWorkingSet;
CCodeSection * m_Section;
CRegInfo m_RegBeforeDelay;
bool m_EffectDelaySlot;
static uint32_t m_TempValue32;

View File

@ -104,6 +104,7 @@
<ClCompile Include="N64System\Recompiler\LoopAnalysis.cpp" />
<ClCompile Include="N64System\Recompiler\Recompiler.cpp" />
<ClCompile Include="N64System\Recompiler\RecompilerMemory.cpp" />
<ClCompile Include="N64System\Recompiler\RecompilerOps.cpp" />
<ClCompile Include="N64System\Recompiler\RegBase.cpp" />
<ClCompile Include="N64System\Recompiler\x64-86\x64ops.cpp" />
<ClCompile Include="N64System\Recompiler\x64-86\x64RecompilerOps.cpp" />

View File

@ -435,6 +435,9 @@
<ClCompile Include="Settings\SettingType\SettingsType-RDB.cpp">
<Filter>Source Files\Settings\SettingType</Filter>
</ClCompile>
<ClCompile Include="N64System\Recompiler\RecompilerOps.cpp">
<Filter>Source Files\N64 System\Recompiler</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">