CPU/CodeCache: Fast path for self-linking blocks

pull/22/head
Connor McLaughlin 5 years ago
parent 09de3819eb
commit 9e3bb62216

@ -5,8 +5,6 @@
#include "cpu_recompiler_code_generator.h" #include "cpu_recompiler_code_generator.h"
#include "cpu_recompiler_thunks.h" #include "cpu_recompiler_thunks.h"
#include "system.h" #include "system.h"
#include <thread>
#include <chrono>
Log_SetChannel(CPU::CodeCache); Log_SetChannel(CPU::CodeCache);
namespace CPU { namespace CPU {
@ -31,15 +29,18 @@ void CodeCache::Initialize(System* system, Core* core, Bus* bus)
void CodeCache::Execute() void CodeCache::Execute()
{ {
CodeBlockKey next_block_key = GetNextBlockKey();
while (m_core->m_downcount >= 0) while (m_core->m_downcount >= 0)
{ {
if (m_core->HasPendingInterrupt()) if (m_core->HasPendingInterrupt())
{ {
// TODO: Fill in m_next_instruction... // TODO: Fill in m_next_instruction...
m_core->DispatchInterrupt(); m_core->DispatchInterrupt();
next_block_key = GetNextBlockKey();
} }
m_current_block = GetNextBlock(); m_current_block = LookupBlock(next_block_key);
if (!m_current_block) if (!m_current_block)
{ {
Log_WarningPrintf("Falling back to uncached interpreter at 0x%08X", m_core->GetRegs().pc); Log_WarningPrintf("Falling back to uncached interpreter at 0x%08X", m_core->GetRegs().pc);
@ -47,18 +48,29 @@ void CodeCache::Execute()
continue; continue;
} }
reexecute_block:
if (USE_RECOMPILER) if (USE_RECOMPILER)
m_current_block->host_code(m_core); m_current_block->host_code(m_core);
else else
InterpretCachedBlock(*m_current_block); InterpretCachedBlock(*m_current_block);
next_block_key = GetNextBlockKey();
if (m_current_block_flushed) if (m_current_block_flushed)
{ {
m_current_block_flushed = false; m_current_block_flushed = false;
delete m_current_block; delete m_current_block;
m_current_block = nullptr;
continue;
} }
m_current_block = nullptr; // Loop to same block?
next_block_key = GetNextBlockKey();
if (next_block_key.bits == m_current_block->key.bits)
{
// we can jump straight to it if there's no pending interrupts
if (m_core->m_downcount >= 0 && !m_core->HasPendingInterrupt())
goto reexecute_block;
}
} }
} }
@ -72,14 +84,18 @@ void CodeCache::Reset()
m_code_buffer->Reset(); m_code_buffer->Reset();
} }
const CPU::CodeBlock* CodeCache::GetNextBlock() CodeBlockKey CodeCache::GetNextBlockKey() const
{ {
const u32 address = m_bus->UnmirrorAddress(m_core->m_regs.pc & UINT32_C(0x1FFFFFFF)); const u32 address = m_bus->UnmirrorAddress(m_core->m_regs.pc & UINT32_C(0x1FFFFFFF));
CodeBlockKey key = {}; CodeBlockKey key = {};
key.SetPC(address); key.SetPC(address);
key.user_mode = m_core->InUserMode(); key.user_mode = m_core->InUserMode();
return key;
}
const CPU::CodeBlock* CodeCache::LookupBlock(CodeBlockKey key)
{
BlockMap::iterator iter = m_blocks.find(key.bits); BlockMap::iterator iter = m_blocks.find(key.bits);
if (iter != m_blocks.end()) if (iter != m_blocks.end())
return iter->second; return iter->second;
@ -89,7 +105,7 @@ const CPU::CodeBlock* CodeCache::GetNextBlock()
if (CompileBlock(block)) if (CompileBlock(block))
{ {
// insert into the page map // insert into the page map
if (m_bus->IsRAMAddress(address)) if (m_bus->IsRAMAddress(key.GetPC()))
{ {
const u32 start_page = block->GetStartPageIndex(); const u32 start_page = block->GetStartPageIndex();
const u32 end_page = block->GetEndPageIndex(); const u32 end_page = block->GetEndPageIndex();
@ -102,7 +118,7 @@ const CPU::CodeBlock* CodeCache::GetNextBlock()
} }
else else
{ {
Log_ErrorPrintf("Failed to compile block at PC=0x%08X", address); Log_ErrorPrintf("Failed to compile block at PC=0x%08X", key.GetPC());
} }
iter = m_blocks.emplace(key.bits, block).first; iter = m_blocks.emplace(key.bits, block).first;

@ -34,7 +34,8 @@ public:
private: private:
using BlockMap = std::unordered_map<u32, CodeBlock*>; using BlockMap = std::unordered_map<u32, CodeBlock*>;
const CodeBlock* GetNextBlock(); CodeBlockKey GetNextBlockKey() const;
const CodeBlock* LookupBlock(CodeBlockKey key);
bool CompileBlock(CodeBlock* block); bool CompileBlock(CodeBlock* block);
void FlushBlock(CodeBlock* block); void FlushBlock(CodeBlock* block);
void InterpretCachedBlock(const CodeBlock& block); void InterpretCachedBlock(const CodeBlock& block);

Loading…
Cancel
Save