CPU/Recompiler: Implement LUT-based fastmem
This commit is contained in:
@ -98,7 +98,7 @@ static void UnlinkBlock(CodeBlock* block);
|
||||
static void ClearState();
|
||||
|
||||
static BlockMap s_blocks;
|
||||
static std::array<std::vector<CodeBlock*>, CPU_CODE_CACHE_PAGE_COUNT> m_ram_block_map;
|
||||
static std::array<std::vector<CodeBlock*>, Bus::RAM_CODE_PAGE_COUNT> m_ram_block_map;
|
||||
|
||||
#ifdef WITH_RECOMPILER
|
||||
static HostCodeMap s_host_code_map;
|
||||
@ -106,11 +106,14 @@ static HostCodeMap s_host_code_map;
|
||||
static void AddBlockToHostCodeMap(CodeBlock* block);
|
||||
static void RemoveBlockFromHostCodeMap(CodeBlock* block);
|
||||
|
||||
#ifdef WITH_FASTMEM
|
||||
static bool InitializeFastmem();
|
||||
static void ShutdownFastmem();
|
||||
static Common::PageFaultHandler::HandlerResult PageFaultHandler(void* exception_pc, void* fault_address, bool is_write);
|
||||
#endif // WITH_FASTMEM
|
||||
static Common::PageFaultHandler::HandlerResult LUTPageFaultHandler(void* exception_pc, void* fault_address,
|
||||
bool is_write);
|
||||
#ifdef WITH_MMAP_FASTMEM
|
||||
static Common::PageFaultHandler::HandlerResult MMapPageFaultHandler(void* exception_pc, void* fault_address,
|
||||
bool is_write);
|
||||
#endif
|
||||
#endif // WITH_RECOMPILER
|
||||
|
||||
void Initialize()
|
||||
@ -130,10 +133,8 @@ void Initialize()
|
||||
Panic("Failed to initialize code space");
|
||||
}
|
||||
|
||||
#ifdef WITH_FASTMEM
|
||||
if (g_settings.IsUsingFastmem() && !InitializeFastmem())
|
||||
Panic("Failed to initialize fastmem");
|
||||
#endif
|
||||
|
||||
ResetFastMap();
|
||||
CompileDispatcher();
|
||||
@ -161,10 +162,8 @@ void ClearState()
|
||||
void Shutdown()
|
||||
{
|
||||
ClearState();
|
||||
#ifdef WITH_FASTMEM
|
||||
ShutdownFastmem();
|
||||
#endif
|
||||
#ifdef WITH_RECOMPILER
|
||||
ShutdownFastmem();
|
||||
s_code_buffer.Destroy();
|
||||
#endif
|
||||
}
|
||||
@ -339,10 +338,7 @@ void Reinitialize()
|
||||
|
||||
#ifdef WITH_RECOMPILER
|
||||
|
||||
#ifdef WITH_FASTMEM
|
||||
ShutdownFastmem();
|
||||
#endif
|
||||
|
||||
s_code_buffer.Destroy();
|
||||
|
||||
if (g_settings.IsUsingRecompiler())
|
||||
@ -358,10 +354,8 @@ void Reinitialize()
|
||||
Panic("Failed to initialize code space");
|
||||
}
|
||||
|
||||
#ifdef WITH_FASTMEM
|
||||
if (g_settings.IsUsingFastmem() && !InitializeFastmem())
|
||||
Panic("Failed to initialize fastmem");
|
||||
#endif
|
||||
|
||||
ResetFastMap();
|
||||
CompileDispatcher();
|
||||
@ -620,7 +614,7 @@ void FastCompileBlockFunction()
|
||||
|
||||
void InvalidateBlocksWithPageIndex(u32 page_index)
|
||||
{
|
||||
DebugAssert(page_index < CPU_CODE_CACHE_PAGE_COUNT);
|
||||
DebugAssert(page_index < Bus::RAM_CODE_PAGE_COUNT);
|
||||
auto& blocks = m_ram_block_map[page_index];
|
||||
for (CodeBlock* block : blocks)
|
||||
{
|
||||
@ -737,27 +731,37 @@ void RemoveBlockFromHostCodeMap(CodeBlock* block)
|
||||
s_host_code_map.erase(hc_iter);
|
||||
}
|
||||
|
||||
#ifdef WITH_FASTMEM
|
||||
|
||||
bool InitializeFastmem()
|
||||
{
|
||||
if (!Common::PageFaultHandler::InstallHandler(&s_host_code_map, PageFaultHandler))
|
||||
const CPUFastmemMode mode = g_settings.cpu_fastmem_mode;
|
||||
Assert(mode != CPUFastmemMode::Disabled);
|
||||
|
||||
#ifdef WITH_MMAP_FASTMEM
|
||||
const auto handler = (mode == CPUFastmemMode::MMap) ? MMapPageFaultHandler : LUTPageFaultHandler;
|
||||
#else
|
||||
const auto handler = LUTPageFaultHandler;
|
||||
Assert(mode != CPUFastmemMode::MMap);
|
||||
#endif
|
||||
|
||||
if (!Common::PageFaultHandler::InstallHandler(&s_host_code_map, handler))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to install page fault handler");
|
||||
return false;
|
||||
}
|
||||
|
||||
Bus::UpdateFastmemViews(true, g_state.cop0_regs.sr.Isc);
|
||||
Bus::UpdateFastmemViews(mode, g_state.cop0_regs.sr.Isc);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShutdownFastmem()
|
||||
{
|
||||
Common::PageFaultHandler::RemoveHandler(&s_host_code_map);
|
||||
Bus::UpdateFastmemViews(false, false);
|
||||
Bus::UpdateFastmemViews(CPUFastmemMode::Disabled, false);
|
||||
}
|
||||
|
||||
Common::PageFaultHandler::HandlerResult PageFaultHandler(void* exception_pc, void* fault_address, bool is_write)
|
||||
#ifdef WITH_MMAP_FASTMEM
|
||||
|
||||
Common::PageFaultHandler::HandlerResult MMapPageFaultHandler(void* exception_pc, void* fault_address, bool is_write)
|
||||
{
|
||||
if (static_cast<u8*>(fault_address) < g_state.fastmem_base ||
|
||||
(static_cast<u8*>(fault_address) - g_state.fastmem_base) >= Bus::FASTMEM_REGION_SIZE)
|
||||
@ -827,7 +831,46 @@ Common::PageFaultHandler::HandlerResult PageFaultHandler(void* exception_pc, voi
|
||||
return Common::PageFaultHandler::HandlerResult::ExecuteNextHandler;
|
||||
}
|
||||
|
||||
#endif // WITH_FASTMEM
|
||||
#endif
|
||||
|
||||
Common::PageFaultHandler::HandlerResult LUTPageFaultHandler(void* exception_pc, void* fault_address, bool is_write)
|
||||
{
|
||||
// use upper_bound to find the next block after the pc
|
||||
HostCodeMap::iterator upper_iter =
|
||||
s_host_code_map.upper_bound(reinterpret_cast<CodeBlock::HostCodePointer>(exception_pc));
|
||||
if (upper_iter == s_host_code_map.begin())
|
||||
return Common::PageFaultHandler::HandlerResult::ExecuteNextHandler;
|
||||
|
||||
// then decrement it by one to (hopefully) get the block we want
|
||||
upper_iter--;
|
||||
|
||||
// find the loadstore info in the code block
|
||||
CodeBlock* block = upper_iter->second;
|
||||
for (auto bpi_iter = block->loadstore_backpatch_info.begin(); bpi_iter != block->loadstore_backpatch_info.end();
|
||||
++bpi_iter)
|
||||
{
|
||||
Recompiler::LoadStoreBackpatchInfo& lbi = *bpi_iter;
|
||||
if (lbi.host_pc == exception_pc)
|
||||
{
|
||||
// found it, do fixup
|
||||
if (Recompiler::CodeGenerator::BackpatchLoadStore(lbi))
|
||||
{
|
||||
// remove the backpatch entry since we won't be coming back to this one
|
||||
block->loadstore_backpatch_info.erase(bpi_iter);
|
||||
return Common::PageFaultHandler::HandlerResult::ContinueExecution;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log_ErrorPrintf("Failed to backpatch %p in block 0x%08X", exception_pc, block->GetPC());
|
||||
return Common::PageFaultHandler::HandlerResult::ExecuteNextHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we didn't find the pc in our list..
|
||||
Log_ErrorPrintf("Loadstore PC not found for %p in block 0x%08X", exception_pc, block->GetPC());
|
||||
return Common::PageFaultHandler::HandlerResult::ExecuteNextHandler;
|
||||
}
|
||||
|
||||
#endif // WITH_RECOMPILER
|
||||
|
||||
|
||||
Reference in New Issue
Block a user