2016-01-27 09:11:59 +00:00
|
|
|
#include "stdafx.h"
|
2022-10-10 00:22:17 +00:00
|
|
|
|
|
|
|
#include <Project64-core/ExceptionHandler.h>
|
|
|
|
#include <Project64-core/N64System/Interpreter/InterpreterCPU.h>
|
|
|
|
#include <Project64-core/N64System/N64System.h>
|
2021-04-14 05:34:15 +00:00
|
|
|
#include <Project64-core/N64System/Recompiler/Recompiler.h>
|
2016-01-27 09:11:59 +00:00
|
|
|
#include <Project64-core/N64System/SystemGlobals.h>
|
|
|
|
|
2017-04-27 22:14:55 +00:00
|
|
|
CRecompiler::CRecompiler(CMipsMemoryVM & MMU, CRegisters & Registers, bool & EndEmulation) :
|
|
|
|
m_MMU(MMU),
|
|
|
|
m_Registers(Registers),
|
|
|
|
m_EndEmulation(EndEmulation),
|
|
|
|
m_MemoryStack(0),
|
2022-08-08 10:52:51 +00:00
|
|
|
PROGRAM_COUNTER(Registers.m_PROGRAM_COUNTER),
|
|
|
|
m_LogFile(nullptr)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2016-09-26 11:10:11 +00:00
|
|
|
CFunctionMap::AllocateMemory();
|
2017-04-27 22:14:55 +00:00
|
|
|
ResetMemoryStackPos();
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CRecompiler::~CRecompiler()
|
|
|
|
{
|
|
|
|
ResetRecompCode(false);
|
2022-08-08 10:52:51 +00:00
|
|
|
StopLog();
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::Run()
|
|
|
|
{
|
2016-06-27 07:26:35 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "Start");
|
2022-08-08 10:52:51 +00:00
|
|
|
StartLog();
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
if (!CRecompMemory::AllocateMemory())
|
|
|
|
{
|
|
|
|
WriteTrace(TraceRecompiler, TraceError, "AllocateMemory failed");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!CFunctionMap::AllocateMemory())
|
|
|
|
{
|
|
|
|
WriteTrace(TraceRecompiler, TraceError, "AllocateMemory failed");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_EndEmulation = false;
|
|
|
|
|
|
|
|
__except_try()
|
|
|
|
{
|
|
|
|
if (g_System->LookUpMode() == FuncFind_VirtualLookup)
|
|
|
|
{
|
|
|
|
if (g_System->bSMM_ValidFunc())
|
|
|
|
{
|
|
|
|
RecompilerMain_VirtualTable_validate();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RecompilerMain_VirtualTable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (g_System->LookUpMode() == FuncFind_ChangeMemory)
|
|
|
|
{
|
|
|
|
RecompilerMain_ChangeMemory();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-01-10 07:16:01 +00:00
|
|
|
if (g_System->bSMM_ValidFunc())
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-01-10 07:16:01 +00:00
|
|
|
RecompilerMain_Lookup_validate();
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-01-10 07:16:01 +00:00
|
|
|
RecompilerMain_Lookup();
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-06-27 07:26:35 +00:00
|
|
|
__except_catch()
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
g_Notify->DisplayError(MSG_UNKNOWN_MEM_ACTION);
|
|
|
|
}
|
2016-06-27 07:26:35 +00:00
|
|
|
|
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "Done");
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::RecompilerMain_VirtualTable()
|
|
|
|
{
|
|
|
|
bool & Done = m_EndEmulation;
|
|
|
|
uint32_t & PC = PROGRAM_COUNTER;
|
|
|
|
|
|
|
|
while (!Done)
|
|
|
|
{
|
2017-04-27 22:14:55 +00:00
|
|
|
if (!m_MMU.ValidVaddr(PC))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
m_Registers.DoTLBReadMiss(false, PC);
|
2017-04-27 22:14:55 +00:00
|
|
|
if (!m_MMU.ValidVaddr(PC))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
g_Notify->DisplayError(stdstr_f("Failed to translate PC to a PAddr: %X\n\nEmulation stopped", PC).c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
PCCompiledFunc_TABLE & table = FunctionTable()[PC >> 0xC];
|
|
|
|
uint32_t TableEntry = (PC & 0xFFF) >> 2;
|
|
|
|
if (table)
|
|
|
|
{
|
|
|
|
CCompiledFunc * info = table[TableEntry];
|
2021-04-12 11:35:39 +00:00
|
|
|
if (info != nullptr)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
(info->Function())();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2016-08-07 06:48:33 +00:00
|
|
|
CCompiledFunc * info = CompileCode();
|
2021-04-12 11:35:39 +00:00
|
|
|
if (info == nullptr || m_EndEmulation)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-04-12 11:35:39 +00:00
|
|
|
if (table == nullptr)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
table = new PCCompiledFunc[(0x1000 >> 2)];
|
2021-04-12 11:35:39 +00:00
|
|
|
if (table == nullptr)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceError, "Failed to allocate PCCompiledFunc");
|
2016-01-27 09:11:59 +00:00
|
|
|
g_Notify->FatalError(MSG_MEM_ALLOC_ERROR);
|
|
|
|
}
|
2022-10-10 00:22:17 +00:00
|
|
|
memset(table, 0, sizeof(PCCompiledFunc) * (0x1000 >> 2));
|
2016-01-27 09:11:59 +00:00
|
|
|
if (g_System->bSMM_Protect())
|
|
|
|
{
|
|
|
|
WriteTrace(TraceRecompiler, TraceError, "Create Table (%X): Index = %d", table, PC >> 0xC);
|
2017-04-27 22:14:55 +00:00
|
|
|
m_MMU.ProtectMemory(PC & ~0xFFF, PC | 0xFFF);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
table[TableEntry] = info;
|
|
|
|
(info->Function())();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::RecompilerMain_VirtualTable_validate()
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::RecompilerMain_Lookup()
|
|
|
|
{
|
|
|
|
uint32_t PhysicalAddr;
|
|
|
|
|
|
|
|
while (!m_EndEmulation)
|
|
|
|
{
|
2022-05-01 22:06:50 +00:00
|
|
|
if (!m_MMU.VAddrToPAddr(PROGRAM_COUNTER, PhysicalAddr))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
m_Registers.DoTLBReadMiss(false, PROGRAM_COUNTER);
|
2022-05-01 22:06:50 +00:00
|
|
|
if (!m_MMU.VAddrToPAddr(PROGRAM_COUNTER, PhysicalAddr))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
g_Notify->DisplayError(stdstr_f("Failed to translate PC to a PAddr: %X\n\nEmulation stopped", PROGRAM_COUNTER).c_str());
|
|
|
|
m_EndEmulation = true;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (PhysicalAddr < g_System->RdramSize())
|
|
|
|
{
|
|
|
|
CCompiledFunc * info = JumpTable()[PhysicalAddr >> 2];
|
|
|
|
|
2021-04-12 11:35:39 +00:00
|
|
|
if (info == nullptr)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2016-08-07 06:48:33 +00:00
|
|
|
info = CompileCode();
|
2021-04-12 11:35:39 +00:00
|
|
|
if (info == nullptr || m_EndEmulation)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (g_System->bSMM_Protect())
|
|
|
|
{
|
2017-04-27 22:14:55 +00:00
|
|
|
m_MMU.ProtectMemory(PROGRAM_COUNTER & ~0xFFF, PROGRAM_COUNTER | 0xFFF);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
JumpTable()[PhysicalAddr >> 2] = info;
|
|
|
|
}
|
|
|
|
(info->Function())();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint32_t opsExecuted = 0;
|
|
|
|
|
2022-05-01 22:06:50 +00:00
|
|
|
while (m_MMU.VAddrToPAddr(PROGRAM_COUNTER, PhysicalAddr) && PhysicalAddr >= g_System->RdramSize())
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
CInterpreterCPU::ExecuteOps(g_System->CountPerOp());
|
|
|
|
opsExecuted += g_System->CountPerOp();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_SyncSystem)
|
|
|
|
{
|
|
|
|
g_System->UpdateSyncCPU(g_SyncSystem, opsExecuted);
|
|
|
|
g_System->SyncCPU(g_SyncSystem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-10 08:58:38 +00:00
|
|
|
void CRecompiler::RecompilerMain_Lookup_validate()
|
|
|
|
{
|
|
|
|
WriteTrace(TraceRecompiler, TraceInfo, "Start");
|
|
|
|
bool & Done = m_EndEmulation;
|
|
|
|
uint32_t & PC = PROGRAM_COUNTER;
|
|
|
|
|
|
|
|
uint32_t PhysicalAddr;
|
|
|
|
|
|
|
|
while (!Done)
|
|
|
|
{
|
2022-05-01 22:06:50 +00:00
|
|
|
if (!m_MMU.VAddrToPAddr(PC, PhysicalAddr))
|
2022-01-10 08:58:38 +00:00
|
|
|
{
|
|
|
|
m_Registers.DoTLBReadMiss(false, PC);
|
2022-05-01 22:06:50 +00:00
|
|
|
if (!m_MMU.VAddrToPAddr(PC, PhysicalAddr))
|
2022-01-10 08:58:38 +00:00
|
|
|
{
|
|
|
|
g_Notify->DisplayError(stdstr_f("Failed to translate PC to a PAddr: %X\n\nEmulation stopped", PC).c_str());
|
|
|
|
Done = true;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (PhysicalAddr < g_System->RdramSize())
|
|
|
|
{
|
|
|
|
CCompiledFunc * info = JumpTable()[PhysicalAddr >> 2];
|
|
|
|
|
|
|
|
if (info == nullptr)
|
|
|
|
{
|
|
|
|
info = CompileCode();
|
|
|
|
if (info == nullptr || m_EndEmulation)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (g_System->bSMM_Protect())
|
|
|
|
{
|
|
|
|
m_MMU.ProtectMemory(PC & ~0xFFF, PC | 0xFFF);
|
|
|
|
}
|
|
|
|
JumpTable()[PhysicalAddr >> 2] = info;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (*(info->MemLocation(0)) != info->MemContents(0) ||
|
|
|
|
*(info->MemLocation(1)) != info->MemContents(1))
|
|
|
|
{
|
|
|
|
if (PhysicalAddr > 0x1000)
|
|
|
|
{
|
|
|
|
ClearRecompCode_Phys((PhysicalAddr - 0x1000) & ~0xFFF, 0x3000, Remove_ValidateFunc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ClearRecompCode_Phys(0, 0x2000, Remove_ValidateFunc);
|
|
|
|
}
|
|
|
|
info = JumpTable()[PhysicalAddr >> 2];
|
|
|
|
if (info != nullptr)
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
info = nullptr;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bRecordExecutionTimes())
|
|
|
|
{
|
|
|
|
uint64_t PreNonCPUTime = g_System->m_CPU_Usage.NonCPUTime();
|
|
|
|
HighResTimeStamp StartTime, EndTime;
|
|
|
|
StartTime.SetToNow();
|
|
|
|
(info->Function())();
|
|
|
|
EndTime.SetToNow();
|
|
|
|
uint64_t PostNonCPUTime = g_System->m_CPU_Usage.NonCPUTime();
|
|
|
|
uint64_t TimeTaken = EndTime.GetMicroSeconds() - StartTime.GetMicroSeconds();
|
|
|
|
if (PostNonCPUTime >= PreNonCPUTime)
|
|
|
|
{
|
|
|
|
TimeTaken -= PostNonCPUTime - PreNonCPUTime;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TimeTaken -= PostNonCPUTime;
|
|
|
|
}
|
|
|
|
FUNCTION_PROFILE::iterator itr = m_BlockProfile.find(info->Function());
|
|
|
|
if (itr == m_BlockProfile.end())
|
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
FUNCTION_PROFILE_DATA data = {0};
|
2022-01-10 08:58:38 +00:00
|
|
|
data.Address = info->EnterPC();
|
|
|
|
std::pair<FUNCTION_PROFILE::iterator, bool> res = m_BlockProfile.insert(FUNCTION_PROFILE::value_type(info->Function(), data));
|
|
|
|
itr = res.first;
|
|
|
|
}
|
|
|
|
WriteTrace(TraceN64System, TraceNotice, "EndTime: %X StartTime: %X TimeTaken: %X", (uint32_t)(EndTime.GetMicroSeconds() & 0xFFFFFFFF), (uint32_t)(StartTime.GetMicroSeconds() & 0xFFFFFFFF), (uint32_t)TimeTaken);
|
|
|
|
itr->second.TimeTaken += TimeTaken;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
(info->Function())();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint32_t opsExecuted = 0;
|
|
|
|
|
2022-05-01 22:06:50 +00:00
|
|
|
while (m_MMU.VAddrToPAddr(PC, PhysicalAddr) && PhysicalAddr >= g_System->RdramSize())
|
2022-01-10 08:58:38 +00:00
|
|
|
{
|
|
|
|
CInterpreterCPU::ExecuteOps(g_System->CountPerOp());
|
|
|
|
opsExecuted += g_System->CountPerOp();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_SyncSystem)
|
|
|
|
{
|
|
|
|
g_System->UpdateSyncCPU(g_SyncSystem, opsExecuted);
|
|
|
|
g_System->SyncCPU(g_SyncSystem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "Done");
|
|
|
|
}
|
|
|
|
|
2016-01-27 09:11:59 +00:00
|
|
|
void CRecompiler::Reset()
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "Start");
|
2016-01-27 09:11:59 +00:00
|
|
|
ResetRecompCode(true);
|
|
|
|
ResetMemoryStackPos();
|
2016-09-26 11:10:11 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "Done");
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::ResetRecompCode(bool bAllocate)
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "Start");
|
2016-01-27 09:11:59 +00:00
|
|
|
CRecompMemory::Reset();
|
|
|
|
CFunctionMap::Reset(bAllocate);
|
|
|
|
|
|
|
|
for (CCompiledFuncList::iterator iter = m_Functions.begin(); iter != m_Functions.end(); iter++)
|
|
|
|
{
|
|
|
|
CCompiledFunc * Func = iter->second;
|
2021-04-12 11:35:39 +00:00
|
|
|
while (Func != nullptr)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
CCompiledFunc * CurrentFunc = Func;
|
|
|
|
Func = Func->Next();
|
|
|
|
|
|
|
|
delete CurrentFunc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_Functions.clear();
|
2016-09-26 11:10:11 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "Done");
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::RecompilerMain_ChangeMemory()
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
|
2016-08-07 06:48:33 +00:00
|
|
|
CCompiledFunc * CRecompiler::CompileCode()
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2016-08-07 06:48:33 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "Start (PC: %X)", PROGRAM_COUNTER);
|
|
|
|
|
2016-01-27 09:11:59 +00:00
|
|
|
uint32_t pAddr = 0;
|
2022-05-01 22:06:50 +00:00
|
|
|
if (!m_MMU.VAddrToPAddr(PROGRAM_COUNTER, pAddr))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
WriteTrace(TraceRecompiler, TraceError, "Failed to translate %X", PROGRAM_COUNTER);
|
2021-04-12 11:35:39 +00:00
|
|
|
return nullptr;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CCompiledFuncList::iterator iter = m_Functions.find(PROGRAM_COUNTER);
|
|
|
|
if (iter != m_Functions.end())
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceInfo, "Existing functions for address (Program Counter: %X pAddr: %X)", PROGRAM_COUNTER, pAddr);
|
2021-04-12 11:35:39 +00:00
|
|
|
for (CCompiledFunc * Func = iter->second; Func != nullptr; Func = Func->Next())
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
uint32_t PAddr;
|
2022-05-01 22:06:50 +00:00
|
|
|
if (m_MMU.VAddrToPAddr(Func->MinPC(), PAddr))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
MD5Digest Hash;
|
2017-04-27 22:14:55 +00:00
|
|
|
MD5(m_MMU.Rdram() + PAddr, (Func->MaxPC() - Func->MinPC()) + 4).get_digest(Hash);
|
2016-01-27 09:11:59 +00:00
|
|
|
if (memcmp(Hash.digest, Func->Hash().digest, sizeof(Hash.digest)) == 0)
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceInfo, "Using existing compiled code (Program Counter: %X pAddr: %X)", PROGRAM_COUNTER, pAddr);
|
2016-01-27 09:11:59 +00:00
|
|
|
return Func;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CheckRecompMem();
|
2016-08-07 06:48:33 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "Compile Block-Start: Program Counter: %X pAddr: %X", PROGRAM_COUNTER, pAddr);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-05-01 22:06:50 +00:00
|
|
|
CCodeBlock CodeBlock(m_MMU, PROGRAM_COUNTER, *g_RecompPos);
|
2016-01-27 09:11:59 +00:00
|
|
|
if (!CodeBlock.Compile())
|
|
|
|
{
|
2021-04-12 11:35:39 +00:00
|
|
|
return nullptr;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bShowRecompMemSize())
|
|
|
|
{
|
|
|
|
ShowMemUsed();
|
|
|
|
}
|
|
|
|
|
2022-08-08 10:52:51 +00:00
|
|
|
LogCodeBlock(CodeBlock);
|
|
|
|
|
2016-01-27 09:11:59 +00:00
|
|
|
CCompiledFunc * Func = new CCompiledFunc(CodeBlock);
|
2016-06-27 07:26:35 +00:00
|
|
|
std::pair<CCompiledFuncList::iterator, bool> ret = m_Functions.insert(CCompiledFuncList::value_type(Func->EnterPC(), Func));
|
2016-01-27 09:11:59 +00:00
|
|
|
if (ret.second == false)
|
|
|
|
{
|
|
|
|
Func->SetNext(ret.first->second->Next());
|
|
|
|
ret.first->second->SetNext(Func);
|
|
|
|
}
|
2016-08-07 06:48:33 +00:00
|
|
|
|
2022-08-29 08:27:17 +00:00
|
|
|
#if defined(__aarch64__) || defined(__amd64__) || defined(_M_X64)
|
2022-10-10 00:22:17 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2021-06-28 01:57:35 +00:00
|
|
|
#else
|
2016-08-07 06:48:33 +00:00
|
|
|
if (g_ModuleLogLevel[TraceRecompiler] >= TraceDebug)
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "Info->Function() = %X", Func->Function());
|
2016-08-07 06:48:33 +00:00
|
|
|
std::string dumpline;
|
|
|
|
uint32_t start_address = (uint32_t)(Func->Function()) & ~1;
|
2017-01-10 07:01:59 +00:00
|
|
|
for (uint8_t * ptr = (uint8_t *)start_address; ptr < CodeBlock.CompiledLocationEnd(); ptr++)
|
2016-08-07 06:48:33 +00:00
|
|
|
{
|
|
|
|
if (dumpline.empty())
|
|
|
|
{
|
|
|
|
dumpline += stdstr_f("%X: ", ptr);
|
|
|
|
}
|
|
|
|
dumpline += stdstr_f(" %02X", *ptr);
|
|
|
|
if ((((uint32_t)ptr - start_address) + 1) % 30 == 0)
|
|
|
|
{
|
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "%s", dumpline.c_str());
|
|
|
|
dumpline.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!dumpline.empty())
|
|
|
|
{
|
|
|
|
WriteTrace(TraceRecompiler, TraceDebug, "%s", dumpline.c_str());
|
|
|
|
}
|
|
|
|
}
|
2021-06-28 01:57:35 +00:00
|
|
|
#endif
|
2016-06-27 07:26:35 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceVerbose, "Done");
|
2016-01-27 09:11:59 +00:00
|
|
|
return Func;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::ClearRecompCode_Phys(uint32_t Address, int length, REMOVE_REASON Reason)
|
|
|
|
{
|
|
|
|
if (g_System->LookUpMode() == FuncFind_VirtualLookup)
|
|
|
|
{
|
|
|
|
ClearRecompCode_Virt(Address + 0x80000000, length, Reason);
|
|
|
|
ClearRecompCode_Virt(Address + 0xA0000000, length, Reason);
|
|
|
|
|
2022-01-10 07:16:01 +00:00
|
|
|
uint32_t VAddr, Index = 0;
|
|
|
|
while (g_TLB->PAddrToVAddr(Address, VAddr, Index))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-01-10 07:16:01 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceInfo, "ClearRecompCode Vaddr %X len: %d", VAddr, length);
|
|
|
|
ClearRecompCode_Virt(VAddr, length, Reason);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (g_System->LookUpMode() == FuncFind_PhysicalLookup)
|
|
|
|
{
|
|
|
|
if (Address < g_System->RdramSize())
|
|
|
|
{
|
|
|
|
int ClearLen = ((length + 3) & ~3);
|
|
|
|
if (Address + ClearLen > g_System->RdramSize())
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
ClearLen = g_System->RdramSize() - Address;
|
|
|
|
}
|
2021-05-18 11:51:36 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceInfo, "Resetting jump table, Addr: %X len: %d", Address, ClearLen);
|
2016-01-27 09:11:59 +00:00
|
|
|
memset((uint8_t *)JumpTable() + Address, 0, ClearLen);
|
|
|
|
if (g_System->bSMM_Protect())
|
|
|
|
{
|
2017-04-27 22:14:55 +00:00
|
|
|
m_MMU.UnProtectMemory(Address + 0x80000000, Address + 0x80000004);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceInfo, "Ignoring reset of jump table, Addr: %X len: %d", Address, ((length + 3) & ~3));
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::ClearRecompCode_Virt(uint32_t Address, int length, REMOVE_REASON Reason)
|
|
|
|
{
|
2016-09-26 11:10:11 +00:00
|
|
|
uint32_t AddressIndex, WriteStart;
|
|
|
|
int DataInBlock, DataToWrite, DataLeft;
|
|
|
|
|
2016-01-27 09:11:59 +00:00
|
|
|
switch (g_System->LookUpMode())
|
|
|
|
{
|
|
|
|
case FuncFind_VirtualLookup:
|
2016-09-26 11:10:11 +00:00
|
|
|
AddressIndex = Address >> 0xC;
|
|
|
|
WriteStart = (Address & 0xFFC);
|
|
|
|
length = ((length + 3) & ~0x3);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2016-09-26 11:10:11 +00:00
|
|
|
DataInBlock = 0x1000 - WriteStart;
|
|
|
|
DataToWrite = length < DataInBlock ? length : DataInBlock;
|
|
|
|
DataLeft = length - DataToWrite;
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2016-09-26 11:10:11 +00:00
|
|
|
{
|
2016-06-27 07:26:35 +00:00
|
|
|
PCCompiledFunc_TABLE & table = FunctionTable()[AddressIndex];
|
|
|
|
if (table)
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceError, "Delete table (%X): Index = %d", table, AddressIndex);
|
2016-06-27 07:26:35 +00:00
|
|
|
delete table;
|
2021-04-12 11:35:39 +00:00
|
|
|
table = nullptr;
|
2017-04-27 22:14:55 +00:00
|
|
|
m_MMU.UnProtectMemory(Address, Address + length);
|
2016-06-27 07:26:35 +00:00
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2016-06-27 07:26:35 +00:00
|
|
|
if (DataLeft > 0)
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2016-06-27 07:26:35 +00:00
|
|
|
break;
|
2016-01-27 09:11:59 +00:00
|
|
|
case FuncFind_PhysicalLookup:
|
2022-10-10 00:22:17 +00:00
|
|
|
{
|
|
|
|
uint32_t pAddr = 0;
|
|
|
|
if (m_MMU.VAddrToPAddr(Address, pAddr))
|
2016-11-18 19:49:24 +00:00
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
ClearRecompCode_Phys(pAddr, length, Reason);
|
2016-11-18 19:49:24 +00:00
|
|
|
}
|
2022-10-10 00:22:17 +00:00
|
|
|
}
|
|
|
|
break;
|
2016-01-27 09:11:59 +00:00
|
|
|
default:
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-08 10:52:51 +00:00
|
|
|
void CRecompiler::ResetLog()
|
|
|
|
{
|
|
|
|
StopLog();
|
|
|
|
StartLog();
|
|
|
|
}
|
|
|
|
|
2016-01-27 09:11:59 +00:00
|
|
|
void CRecompiler::ResetMemoryStackPos()
|
|
|
|
{
|
2022-08-29 08:27:17 +00:00
|
|
|
#if defined(__aarch64__) || defined(__amd64__) || defined(_M_X64)
|
2022-10-10 00:22:17 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2021-06-28 01:57:35 +00:00
|
|
|
#else
|
2016-01-27 09:11:59 +00:00
|
|
|
if (m_Registers.m_GPR[29].UW[0] == 0)
|
|
|
|
{
|
|
|
|
m_MemoryStack = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t pAddr = 0;
|
2022-05-01 22:06:50 +00:00
|
|
|
if (m_MMU.VAddrToPAddr(m_Registers.m_GPR[29].UW[0], pAddr))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-20 23:33:33 +00:00
|
|
|
if (pAddr < m_MMU.RdramSize())
|
|
|
|
{
|
|
|
|
m_MemoryStack = (uint32_t)(m_MMU.Rdram() + pAddr);
|
|
|
|
}
|
|
|
|
else if (pAddr > 0x04000000 && pAddr < 0x04001000)
|
|
|
|
{
|
|
|
|
m_MemoryStack = (uint32_t)(m_MMU.Dmem() + pAddr - 0x04000000);
|
|
|
|
}
|
|
|
|
else if (pAddr > 0x04001000 && pAddr < 0x04002000)
|
|
|
|
{
|
|
|
|
m_MemoryStack = (uint32_t)(m_MMU.Imem() + pAddr - 0x04001000);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WriteTrace(TraceRecompiler, TraceError, "Failed to translate SP address (%s)", m_Registers.m_GPR[29].UW[0]);
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
2021-06-28 01:57:35 +00:00
|
|
|
#endif
|
2016-10-02 21:46:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::DumpFunctionTimes()
|
|
|
|
{
|
2022-08-29 08:27:17 +00:00
|
|
|
#if defined(__aarch64__) || defined(__amd64__) || defined(_M_X64)
|
2022-10-10 00:22:17 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2021-06-28 01:57:35 +00:00
|
|
|
#else
|
2016-10-02 21:46:05 +00:00
|
|
|
CPath LogFileName(g_Settings->LoadStringVal(Directory_Log).c_str(), "FunctionTimes.csv");
|
|
|
|
|
|
|
|
CLog Log;
|
|
|
|
Log.Open(LogFileName);
|
|
|
|
|
|
|
|
for (FUNCTION_PROFILE::iterator itr = m_BlockProfile.begin(); itr != m_BlockProfile.end(); itr++)
|
|
|
|
{
|
|
|
|
Log.LogF("%X,0x%X,%d\r\n", (uint32_t)itr->first, itr->second.Address, (uint32_t)itr->second.TimeTaken);
|
|
|
|
}
|
2021-06-28 01:57:35 +00:00
|
|
|
#endif
|
2016-10-02 21:46:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::ResetFunctionTimes()
|
|
|
|
{
|
|
|
|
m_BlockProfile.clear();
|
2022-08-08 10:52:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::StartLog()
|
|
|
|
{
|
|
|
|
if (!bRecordRecompilerAsm())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
CPath LogFileName(g_Settings->LoadStringVal(Directory_Log).c_str(), "CPUoutput.log");
|
|
|
|
if (m_LogFile != nullptr)
|
|
|
|
{
|
|
|
|
StopLog();
|
|
|
|
}
|
|
|
|
m_LogFile = new CLog();
|
|
|
|
if (m_LogFile)
|
|
|
|
{
|
|
|
|
if (m_LogFile->Open(LogFileName))
|
|
|
|
{
|
|
|
|
m_LogFile->SetMaxFileSize(300 * CLog::MB);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
StopLog();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::StopLog(void)
|
|
|
|
{
|
|
|
|
if (m_LogFile != nullptr)
|
|
|
|
{
|
|
|
|
delete m_LogFile;
|
|
|
|
m_LogFile = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CRecompiler::LogCodeBlock(const CCodeBlock & CodeBlock)
|
|
|
|
{
|
|
|
|
if (!bRecordRecompilerAsm() || m_LogFile == nullptr || CodeBlock.CodeLog().empty())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_LogFile->Log(CodeBlock.CodeLog().c_str());
|
|
|
|
m_LogFile->Log("\r\n");
|
|
|
|
m_LogFile->Flush();
|
|
|
|
}
|