mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-03-06 14:27:44 +00:00
CPU/CodeCache: Fast path for self-linking blocks
This commit is contained in:
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;
|
||||
|
@ -314,4 +330,4 @@ void CodeCache::InterpretUncachedBlock()
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace CPU
|
||||
} // namespace CPU
|
||||
|
|
|
@ -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…
Reference in a new issue