Rsp: Start to work on x64 compiling tasks

This commit is contained in:
zilmar 2025-04-11 15:33:04 +09:30
parent df883161c0
commit 14f033bce4
14 changed files with 416 additions and 28 deletions

View File

@ -45,6 +45,9 @@
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\3rdParty\asmjit\asmjit.vcxproj">
<Project>{a72c9f08-ebb4-443d-9982-da21ae8b367d}</Project>
</ProjectReference>
<ProjectReference Include="..\..\3rdParty\zlib\zlib.vcxproj">
<Project>{731bd205-2826-4631-b7af-117658e88dbc}</Project>
</ProjectReference>

View File

@ -41,7 +41,59 @@ bool CHleTask::IsHleTask(void)
return false;
}
void CHleTask::ExecuteTask_1a13a51a(TASK_INFO & TaskInfo)
#if defined(__amd64__) || defined(_M_X64)
void CHleTask::SetupCommandList(const TASK_INFO & TaskInfo)
{
uint32_t JumpTableLength = 0x7E, JumpTablePos = 0x10;
if ((HLETaskType)(TaskInfo.Type) == HLETaskType::Audio)
{
if (*((uint32_t *)&m_DMEM[0]) == 0x00000001 && *((uint32_t *)&m_DMEM[0x30]) == 0xf0000f00)
{
JumpTableLength = 0x10;
JumpTablePos = 0x10;
}
}
uint32_t JumpTableCRC = crc32(0L, m_IMEM + JumpTablePos, JumpTableLength << 1);
TaskFunctionMap::iterator itr = m_FunctionMap.find(JumpTableCRC);
if (itr != m_FunctionMap.end())
{
m_TaskFunctions = &itr->second;
return;
}
if (m_FunctionMap.size() > 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
m_TaskFunctions = nullptr;
TaskFunctions JumpFunctions;
for (uint32_t i = 0, n = JumpTableLength; i < n; i++)
{
uint16_t FuncAddress = *((uint16_t *)(m_DMEM + (((i << 1) + JumpTablePos) ^ 2)));
if (FuncAddress != 0x1118)
{
m_Recompiler.CompileHLETask(FuncAddress);
void * FuncPtr = *(JumpTable + ((FuncAddress & 0xFFF) >> 2));
JumpFunctions.emplace_back(TaskFunctionAddress(FuncAddress, FuncPtr));
}
else
{
JumpFunctions.emplace_back(TaskFunctionAddress(FuncAddress, nullptr));
}
}
m_FunctionMap[JumpTableCRC] = JumpFunctions;
itr = m_FunctionMap.find(JumpTableCRC);
if (itr == m_FunctionMap.end())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
return;
}
m_TaskFunctions = &itr->second;
}
void CHleTask::ExecuteTask_1a13a51a(const TASK_INFO & TaskInfo)
{
*((uint32_t *)(m_DMEM + 0x320)) = 0;
GPR_T8 = 0x360;
@ -92,16 +144,13 @@ void CHleTask::ExecuteTask_1a13a51a(TASK_INFO & TaskInfo)
{
RSPSystem.SyncSystem()->ExecuteOps(0x10000, 0x118);
}
#if defined(_M_IX86) && defined(_MSC_VER)
void * Block = FunctionAddress.second;
_asm {
pushad
call Block
popad
typedef void (*FuncPtr)();
FuncPtr func = (FuncPtr)(*(JumpTable + ((*m_SP_PC_REG & 0xFFF) >> 2)));
if (func == nullptr)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
#else
g_Notify->BreakPoint(__FILE__, __LINE__);
#endif
func();
if (SyncCPU)
{
RSPSystem.BasicSyncCheck();
@ -147,6 +196,41 @@ void CHleTask::ExecuteTask_1a13a51a(TASK_INFO & TaskInfo)
}
}
void CHleTask::SetupTask(const TASK_INFO & TaskInfo)
{
if (TaskInfo.Flags != 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (*m_SP_DMA_FULL_REG != 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
m_RSPRegisterHandler->WriteReg(RSPRegister_MEM_ADDR, 0);
m_RSPRegisterHandler->WriteReg(RSPRegister_DRAM_ADDR, TaskInfo.UcodeData);
m_RSPRegisterHandler->WriteReg(RSPRegister_RD_LEN, TaskInfo.UcodeDataSize);
if (*m_SP_DMA_BUSY_REG != 0 || (*m_SP_STATUS_REG & 0x80) != 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
m_RSPRegisterHandler->WriteReg(RSPRegister_MEM_ADDR, 0x1080);
m_RSPRegisterHandler->WriteReg(RSPRegister_DRAM_ADDR, TaskInfo.Ucode);
m_RSPRegisterHandler->WriteReg(RSPRegister_RD_LEN, 0x0F7F);
if (*m_SP_DMA_BUSY_REG != 0 || (*m_SP_STATUS_REG & 0x80) != 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
*m_SP_SEMAPHORE_REG = 0;
if (SyncCPU)
{
*m_SP_PC_REG = 0x80;
RSPSystem.SyncSystem()->ExecuteOps(200, 0x080);
RSPSystem.BasicSyncCheck();
}
SetupCommandList(TaskInfo);
}
#endif
bool CHleTask::ProcessHleTask(void)
{
TASK_INFO & TaskInfo = *((TASK_INFO *)(m_DMEM + 0xFC0));
@ -185,3 +269,29 @@ bool CHleTask::ProcessHleTask(void)
}
return false;
}
bool CHleTask::HleTaskRecompiler(void)
{
const TASK_INFO & TaskInfo = *((TASK_INFO *)(m_DMEM + 0xFC0));
if (SyncCPU)
{
RSPSystem.SetupSyncCPU();
}
SetupTask(TaskInfo);
uint32_t UcodeSize = TaskInfo.UcodeSize;
if (UcodeSize < 0x4 || TaskInfo.UcodeSize > 0x0F80)
{
UcodeSize = 0x0F80;
}
m_UcodeCRC = crc32(0L, m_IMEM + 0x80, UcodeSize);
if (m_UcodeCRC == 0x1a13a51a)
{
ExecuteTask_1a13a51a(TaskInfo);
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
return true;
}

View File

@ -49,13 +49,16 @@ public:
bool IsHleTask(void);
bool ProcessHleTask(void);
bool HleTaskRecompiler(void);
private:
CHleTask(void);
CHleTask(const CHleTask & copy);
CHleTask & operator=(const CHleTask & rhs);
void ExecuteTask_1a13a51a(TASK_INFO & TaskInfo);
void SetupCommandList(const TASK_INFO & TaskInfo);
void ExecuteTask_1a13a51a(const TASK_INFO & TaskInfo);
void SetupTask(const TASK_INFO & TaskInfo);
void (*&CheckInterrupts)(void);
void (*&ProcessDList)(void);

View File

@ -37,6 +37,7 @@
</PreBuildEvent>
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<AdditionalIncludeDirectories>$(SolutionDir)Source\3rdParty\asmjit\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
@ -64,8 +65,10 @@
<ClCompile Include="Hle\mp3.cpp" />
<ClCompile Include="Hle\musyx.cpp" />
<ClCompile Include="Recompiler\Mmx.cpp" />
<ClCompile Include="Recompiler\RspAssembler.cpp" />
<ClCompile Include="Recompiler\RspProfiling.cpp" />
<ClCompile Include="Recompiler\RspRecompilerAnalysis.cpp" />
<ClCompile Include="Recompiler\RspRecompilerCPU-x64.cpp" />
<ClCompile Include="Recompiler\RspRecompilerCPU-x86.cpp" />
<ClCompile Include="Recompiler\RspRecompilerOps-x86.cpp" />
<ClCompile Include="Recompiler\RspRecompilerSections.cpp" />
@ -96,7 +99,10 @@
<ClInclude Include="Hle\HleTask.h" />
<ClInclude Include="Hle\mem.h" />
<ClInclude Include="Hle\ucodes.h" />
<ClInclude Include="Recompiler\asmjit.h" />
<ClInclude Include="Recompiler\RspAssembler.h" />
<ClInclude Include="Recompiler\RspProfiling.h" />
<ClInclude Include="Recompiler\RspRecompilerCPU-x64.h" />
<ClInclude Include="Recompiler\RspRecompilerCPU-x86.h" />
<ClInclude Include="Recompiler\RspRecompilerOps-x86.h" />
<ClInclude Include="Recompiler\X86.h" />

View File

@ -66,9 +66,6 @@
<ClCompile Include="Recompiler\RspRecompilerAnalysis.cpp">
<Filter>Source Files\Recompiler</Filter>
</ClCompile>
<ClCompile Include="Recompiler\RspRecompilerCPU.cpp">
<Filter>Source Files\Recompiler</Filter>
</ClCompile>
<ClCompile Include="Recompiler\RspRecompilerSections.cpp">
<Filter>Source Files\Recompiler</Filter>
</ClCompile>
@ -141,6 +138,15 @@
<ClCompile Include="Recompiler\RspRecompilerOps-x86.cpp">
<Filter>Source Files\Recompiler</Filter>
</ClCompile>
<ClCompile Include="Recompiler\RspRecompilerCPU-x86.cpp">
<Filter>Source Files\Recompiler</Filter>
</ClCompile>
<ClCompile Include="Recompiler\RspRecompilerCPU-x64.cpp">
<Filter>Source Files\Recompiler</Filter>
</ClCompile>
<ClCompile Include="Recompiler\RspAssembler.cpp">
<Filter>Source Files\Recompiler</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="cpu\RSPInstruction.h">
@ -173,9 +179,6 @@
<ClInclude Include="Settings\RspSettings.h">
<Filter>Header Files\Settings</Filter>
</ClInclude>
<ClInclude Include="Recompiler\RspRecompilerCPU.h">
<Filter>Header Files\Recompiler</Filter>
</ClInclude>
<ClInclude Include="cpu\RspMemory.h">
<Filter>Header Files\cpu</Filter>
</ClInclude>
@ -227,5 +230,17 @@
<ClInclude Include="Recompiler\RspRecompilerOps-x86.h">
<Filter>Header Files\Recompiler</Filter>
</ClInclude>
<ClInclude Include="Recompiler\RspRecompilerCPU-x86.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Recompiler\asmjit.h">
<Filter>Header Files\Recompiler</Filter>
</ClInclude>
<ClInclude Include="Recompiler\RspAssembler.h">
<Filter>Header Files\Recompiler</Filter>
</ClInclude>
<ClInclude Include="Recompiler\RspRecompilerCPU-x64.h">
<Filter>Header Files\Recompiler</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,37 @@
#if defined(__amd64__) || defined(_M_X64)
#include "RspAssembler.h"
#include <Common/StdString.h>
#include <Project64-rsp-core/Settings/RspSettings.h>
#include <Settings/Settings.h>
RspAssembler::RspAssembler(asmjit::CodeHolder * CodeHolder, std::string & CodeLog) :
asmjit::x86::Assembler(CodeHolder),
m_CodeLog(CodeLog)
{
setLogger(nullptr);
setErrorHandler(this);
addFlags(asmjit::FormatFlags::kHexOffsets);
addFlags(asmjit::FormatFlags::kHexImms);
addFlags(asmjit::FormatFlags::kExplainImms);
}
void RspAssembler::handleError(asmjit::Error /*err*/, const char * /*message*/, asmjit::BaseEmitter * /*origin*/)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
asmjit::Error RspAssembler::_log(const char * data, size_t size) noexcept
{
stdstr AsmjitLog(std::string(data, size));
AsmjitLog.Trim("\n");
m_CodeLog.append(stdstr_f(" %s\n", AsmjitLog.c_str()));
return asmjit::kErrorOk;
}
void RspAssembler::Reset(void)
{
setLogger(LogAsmCode ? this : nullptr);
}
#endif

View File

@ -0,0 +1,26 @@
#pragma once
#if defined(__amd64__) || defined(_M_X64)
#include <Project64-rsp-core/Recompiler/asmjit.h>
class RspAssembler :
public asmjit::x86::Assembler,
public asmjit::ErrorHandler,
public asmjit::Logger
{
public:
RspAssembler(asmjit::CodeHolder * CodeHolder, std::string & CodeLog);
void Reset(void);
private:
RspAssembler();
RspAssembler(const RspAssembler &);
RspAssembler & operator=(const RspAssembler &);
void handleError(asmjit::Error err, const char * message, asmjit::BaseEmitter * origin);
asmjit::Error _log(const char * data, size_t size) noexcept;
std::string & m_CodeLog;
};
#endif

View File

@ -0,0 +1,119 @@
#if defined(__amd64__) || defined(_M_X64)
#include "RspRecompilerCPU-x64.h"
#include <Common/Log.h>
#include <Project64-rsp-core/Recompiler/RspAssembler.h>
#include <Project64-rsp-core/Settings/RspSettings.h>
#include <Project64-rsp-core/cpu/RspMemory.h>
#include <Project64-rsp-core/cpu/RspSystem.h>
#include <Settings/Settings.h>
#define AddressOf(Addr) CRSPRecompiler::GetAddressOf(5, (Addr))
extern CLog * CPULog;
CRSPRecompiler::CRSPRecompiler(CRSPSystem & System) :
m_System(System),
m_BlockID(0),
m_Assembler(nullptr)
{
m_Environment = asmjit::Environment::host();
m_CodeHolder.init(m_Environment);
m_CodeHolder.setErrorHandler(this);
m_CodeHolder.setLogger(nullptr);
m_Assembler = new RspAssembler(&m_CodeHolder, m_CodeLog);
}
CRSPRecompiler::~CRSPRecompiler()
{
if (m_Assembler != nullptr)
{
delete m_Assembler;
m_Assembler = nullptr;
}
}
void CRSPRecompiler::Reset()
{
m_Assembler->Reset();
}
void CRSPRecompiler::CompileHLETask(uint32_t Address)
{
Log("====== Block %d ======", m_BlockID++);
Log("asm code at: %016llX", (uint64_t)RecompPos);
Log("Jump table: %X", Table);
Log("Start of block: %X", Address);
Log("====== Recompiled code ======");
*(JumpTable + ((Address & 0xFFF) >> 2)) = RecompPos;
m_Assembler->push(asmjit::x86::rbp);
m_Assembler->mov(asmjit::x86::rbp, asmjit::x86::rsp);
m_Assembler->sub(asmjit::x86::rsp, 0x30);
m_Assembler->mov(asmjit::x86::rcx, asmjit::imm((uintptr_t)&m_System));
m_Assembler->mov(asmjit::x86::edx, asmjit::imm(0x10000));
m_Assembler->mov(asmjit::x86::r8d, asmjit::imm(0x118));
m_Assembler->mov(asmjit::x86::rax, asmjit::imm(AddressOf(&CRSPSystem::ExecuteOps)));
m_Assembler->call(asmjit::x86::rax);
m_Assembler->add(asmjit::x86::rsp, 0x30);
m_Assembler->pop(asmjit::x86::rbp);
m_Assembler->ret();
m_Assembler->finalize();
m_CodeHolder.relocateToBase((uint64_t)RecompPos);
size_t codeSize = m_CodeHolder.codeSize();
m_CodeHolder.copyFlattenedData(RecompPos, codeSize);
RecompPos += codeSize;
if (LogAsmCode && !m_CodeLog.empty() && CPULog != nullptr)
{
CPULog->Log(m_CodeLog.c_str());
CPULog->Log("\r\n");
CPULog->Flush();
m_CodeLog.clear();
}
#endif
}
void CRSPRecompiler::Log(_Printf_format_string_ const char * Text, ...)
{
if (!LogAsmCode)
{
return;
}
va_list args;
va_start(args, Text);
#pragma warning(push)
#pragma warning(disable : 4996)
size_t nlen = _vscprintf(Text, args) + 1;
char * buffer = (char *)alloca(nlen * sizeof(char));
buffer[nlen - 1] = 0;
if (buffer != nullptr)
{
vsprintf(buffer, Text, args);
m_CodeLog += buffer;
m_CodeLog += "\n";
}
#pragma warning(pop)
va_end(args);
}
void CRSPRecompiler::handleError(asmjit::Error /*err*/, const char * /*message*/, asmjit::BaseEmitter * /*origin*/)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
uintptr_t CRSPRecompiler::GetAddressOf(int value, ...)
{
void * Address;
va_list ap;
va_start(ap, value);
Address = va_arg(ap, void *);
va_end(ap);
return (uintptr_t)Address;
}

View File

@ -0,0 +1,37 @@
#if defined(__amd64__) || defined(_M_X64)
#pragma once
#include "asmjit.h"
class CRSPSystem;
class RspAssembler;
class CRSPRecompiler :
public asmjit::ErrorHandler
{
public:
CRSPRecompiler(CRSPSystem & System);
~CRSPRecompiler();
void Reset();
void CompileHLETask(uint32_t Address);
void Log(_Printf_format_string_ const char * Text, ...);
private:
CRSPRecompiler();
CRSPRecompiler(const CRSPRecompiler &);
CRSPRecompiler & operator=(const CRSPRecompiler &);
void handleError(asmjit::Error err, const char * message, asmjit::BaseEmitter * origin);
static uintptr_t GetAddressOf(int32_t value, ...);
CRSPSystem & m_System;
std::string m_CodeLog;
uint32_t m_BlockID;
asmjit::Environment m_Environment;
asmjit::CodeHolder m_CodeHolder;
RspAssembler * m_Assembler;
};
#endif

View File

@ -0,0 +1,15 @@
#pragma once
#define ASMJIT_STATIC
#ifdef new
#pragma push_macro("new")
#undef new
#include <asmjit\asmjit.h>
#pragma pop_macro("new")
#else
#include <asmjit\asmjit.h>
#endif
#include <asmjit\a64.h>
#include <asmjit\arm.h>
#include <asmjit\arm\a64assembler.h>

View File

@ -95,6 +95,25 @@ be greater than the number of cycles that the RSP should have performed.
uint32_t DoRspCycles(uint32_t Cycles)
{
#if defined(__amd64__) || defined(_M_X64)
if (CRSPSettings::CPUMethod() == RSPCpuMethod::RecompilerTasks)
{
if (!RSPSystem.IsHleTask() || !RSPSystem.HleTaskRecompiler())
{
if (g_RSPDebugger != nullptr)
{
g_RSPDebugger->RspCyclesStart();
RSPSystem.ExecuteOps((uint32_t)-1, (uint32_t)-1);
g_RSPDebugger->RspCyclesStop();
}
else
{
RSPSystem.ExecuteOps((uint32_t)-1, (uint32_t)-1);
}
}
return Cycles;
}
#endif
if (CRSPSettings::CPUMethod() == RSPCpuMethod::HighLevelEmulation && RSPSystem.ProcessHleTask())
{
return Cycles;
@ -110,17 +129,13 @@ uint32_t DoRspCycles(uint32_t Cycles)
{
RSPSystem.RunRecompiler();
}
#endif
#if defined(__amd64__) || defined(_M_X64)
if (CRSPSettings::CPUMethod() == RSPCpuMethod::RecompilerTasks)
{
RSPSystem.ExecuteOps((uint32_t)-1, (uint32_t)-1);
}
#endif
else
{
#endif
RSPSystem.ExecuteOps((uint32_t)-1, (uint32_t)-1);
#if defined(__i386__) || defined(_M_IX86)
}
#endif
if (g_RSPDebugger != nullptr)
{
g_RSPDebugger->RspCyclesStop();

View File

@ -13,9 +13,7 @@ CRSPSystem::CRSPSystem() :
CHleTask(*this),
m_SyncSystem(nullptr),
m_BaseSystem(nullptr),
#if defined(__i386__) || defined(_M_IX86)
m_Recompiler(*this),
#endif
m_RSPRegisterHandler(nullptr),
m_Op(*this),
m_NextInstruction(RSPPIPELINE_NORMAL),
@ -133,6 +131,7 @@ void CRSPSystem::Reset(RSP_INFO & Info)
{
m_SyncSystem->Reset(Info);
}
m_Recompiler.Reset();
}
void CRSPSystem::RomClosed(void)

View File

@ -1,6 +1,7 @@
#pragma once
#include <Project64-rsp-core/Hle/HleTask.h>
#include <Project64-rsp-core/RSPInfo.h>
#include <Project64-rsp-core/Recompiler/RspRecompilerCPU-x64.h>
#include <Project64-rsp-core/Recompiler/RspRecompilerCPU-x86.h>
#include <Project64-rsp-core/cpu/RSPInterpreterOps.h>
#include <Project64-rsp-core/cpu/RSPRegisters.h>
@ -53,9 +54,7 @@ private:
CRSPSystem * m_SyncSystem;
CRSPSystem * m_BaseSystem;
#if defined(__i386__) || defined(_M_IX86)
CRSPRecompiler m_Recompiler;
#endif
RSPRegisterHandlerPlugin * m_RSPRegisterHandler;
CRSPRegisters m_Reg;
RSPOp m_Op;

View File

@ -39,6 +39,7 @@
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<AdditionalIncludeDirectories>$(SolutionDir)Source\3rdParty\asmjit\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
@ -57,6 +58,9 @@
<ClInclude Include="Rsp.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\3rdParty\asmjit\asmjit.vcxproj">
<Project>{a72c9f08-ebb4-443d-9982-da21ae8b367d}</Project>
</ProjectReference>
<ProjectReference Include="..\3rdParty\zlib\zlib.vcxproj">
<Project>{731bd205-2826-4631-b7af-117658e88dbc}</Project>
</ProjectReference>