mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-04-27 07:35:43 -04: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_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;
|
||||||
@ -314,4 +330,4 @@ void CodeCache::InterpretUncachedBlock()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace CPU
|
} // namespace CPU
|
||||||
|
@ -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…
x
Reference in New Issue
Block a user