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_thunks.h"
#include "system.h"
#include <thread>
#include <chrono>
Log_SetChannel(CPU::CodeCache);
namespace CPU {
@ -31,15 +29,18 @@ void CodeCache::Initialize(System* system, Core* core, Bus* bus)
void CodeCache::Execute()
{
CodeBlockKey next_block_key = GetNextBlockKey();
while (m_core->m_downcount >= 0)
{
if (m_core->HasPendingInterrupt())
{
// TODO: Fill in m_next_instruction...
m_core->DispatchInterrupt();
next_block_key = GetNextBlockKey();
}
m_current_block = GetNextBlock();
m_current_block = LookupBlock(next_block_key);
if (!m_current_block)
{
Log_WarningPrintf("Falling back to uncached interpreter at 0x%08X", m_core->GetRegs().pc);
@ -47,18 +48,29 @@ void CodeCache::Execute()
continue;
}
reexecute_block:
if (USE_RECOMPILER)
m_current_block->host_code(m_core);
else
InterpretCachedBlock(*m_current_block);
next_block_key = GetNextBlockKey();
if (m_current_block_flushed)
{
m_current_block_flushed = false;
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();
}
const CPU::CodeBlock* CodeCache::GetNextBlock()
CodeBlockKey CodeCache::GetNextBlockKey() const
{
const u32 address = m_bus->UnmirrorAddress(m_core->m_regs.pc & UINT32_C(0x1FFFFFFF));
CodeBlockKey key = {};
key.SetPC(address);
key.user_mode = m_core->InUserMode();
return key;
}
const CPU::CodeBlock* CodeCache::LookupBlock(CodeBlockKey key)
{
BlockMap::iterator iter = m_blocks.find(key.bits);
if (iter != m_blocks.end())
return iter->second;
@ -89,7 +105,7 @@ const CPU::CodeBlock* CodeCache::GetNextBlock()
if (CompileBlock(block))
{
// insert into the page map
if (m_bus->IsRAMAddress(address))
if (m_bus->IsRAMAddress(key.GetPC()))
{
const u32 start_page = block->GetStartPageIndex();
const u32 end_page = block->GetEndPageIndex();
@ -102,7 +118,7 @@ const CPU::CodeBlock* CodeCache::GetNextBlock()
}
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;

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

Loading…
Cancel
Save