CPU/NewRec: Add speculative constants

This commit is contained in:
Stenzek
2023-10-21 22:12:00 +10:00
parent b3cbe5a7ee
commit 6592cafadc
12 changed files with 858 additions and 225 deletions

View File

@ -66,6 +66,7 @@ static void FillBlockRegInfo(Block* block);
static void CopyRegInfo(InstructionInfo* dst, const InstructionInfo* src);
static void SetRegAccess(InstructionInfo* inst, Reg reg, bool write);
static void AddBlockToPageList(Block* block);
static void RemoveBlockFromPageList(Block* block);
static Common::PageFaultHandler::HandlerResult ExceptionHandler(void* exception_pc, void* fault_address, bool is_write);
@ -526,7 +527,7 @@ bool CPU::CodeCache::IsBlockCodeCurrent(const Block* block)
bool CPU::CodeCache::RevalidateBlock(Block* block)
{
DebugAssert(block->state != BlockState::Valid);
DebugAssert(AddressInRAM(block->pc));
DebugAssert(AddressInRAM(block->pc) || block->state == BlockState::NeedsRecompile);
if (block->state >= BlockState::NeedsRecompile)
return false;
@ -569,6 +570,39 @@ void CPU::CodeCache::AddBlockToPageList(Block* block)
}
}
void CPU::CodeCache::RemoveBlockFromPageList(Block* block)
{
DebugAssert(block->size > 0);
if (!AddressInRAM(block->pc) || block->protection != PageProtectionMode::WriteProtected)
return;
const u32 page_idx = block->StartPageIndex();
PageProtectionInfo& entry = s_page_protection[page_idx];
// unlink from list
Block* prev_block = nullptr;
Block* cur_block = entry.first_block_in_page;
while (cur_block)
{
if (cur_block != block)
{
prev_block = cur_block;
cur_block = cur_block->next_block_in_page;
continue;
}
if (prev_block)
prev_block->next_block_in_page = cur_block->next_block_in_page;
else
entry.first_block_in_page = cur_block->next_block_in_page;
if (!cur_block->next_block_in_page)
entry.last_block_in_page = prev_block;
cur_block->next_block_in_page = nullptr;
break;
}
}
void CPU::CodeCache::InvalidateBlocksWithPageIndex(u32 index)
{
DebugAssert(index < Bus::RAM_8MB_CODE_PAGE_COUNT);
@ -1480,13 +1514,14 @@ void CPU::CodeCache::AddLoadStoreInfo(void* code_address, u32 code_size, u32 gue
LoadstoreBackpatchInfo info;
info.thunk_address = thunk_address;
info.guest_pc = guest_pc;
info.guest_block = 0;
info.code_size = static_cast<u8>(code_size);
s_fastmem_backpatch_info.emplace(code_address, info);
}
void CPU::CodeCache::AddLoadStoreInfo(void* code_address, u32 code_size, u32 guest_pc, TickCount cycles,
u32 gpr_bitmask, u8 address_register, u8 data_register, MemoryAccessSize size,
bool is_signed, bool is_load)
void CPU::CodeCache::AddLoadStoreInfo(void* code_address, u32 code_size, u32 guest_pc, u32 guest_block,
TickCount cycles, u32 gpr_bitmask, u8 address_register, u8 data_register,
MemoryAccessSize size, bool is_signed, bool is_load)
{
DebugAssert(code_size < std::numeric_limits<u8>::max());
DebugAssert(cycles >= 0 && cycles < std::numeric_limits<u16>::max());
@ -1498,6 +1533,7 @@ void CPU::CodeCache::AddLoadStoreInfo(void* code_address, u32 code_size, u32 gue
LoadstoreBackpatchInfo info;
info.thunk_address = nullptr;
info.guest_pc = guest_pc;
info.guest_block = guest_block;
info.gpr_bitmask = gpr_bitmask;
info.cycles = static_cast<u16>(cycles);
info.address_register = address_register;
@ -1562,7 +1598,22 @@ Common::PageFaultHandler::HandlerResult CPU::CodeCache::HandleFastmemException(v
BackpatchLoadStore(exception_pc, info);
// TODO: queue block for recompilation later
// queue block for recompilation later
if (g_settings.cpu_execution_mode == CPUExecutionMode::NewRec)
{
Block* block = LookupBlock(info.guest_block);
if (block)
{
// This is a bit annoying, we have to remove it from the page list if it's a RAM block.
Log_DevFmt("Queuing block {:08X} for recompilation due to backpatch", block->pc);
RemoveBlockFromPageList(block);
InvalidateBlock(block, BlockState::NeedsRecompile);
// Need to reset the recompile count, otherwise it'll get trolled into an interpreter fallback.
block->compile_frame = System::GetFrameNumber();
block->compile_count = 1;
}
}
// and store the pc in the faulting list, so that we don't emit another fastmem loadstore
s_fastmem_faulting_pcs.insert(info.guest_pc);
@ -1570,6 +1621,11 @@ Common::PageFaultHandler::HandlerResult CPU::CodeCache::HandleFastmemException(v
return Common::PageFaultHandler::HandlerResult::ContinueExecution;
}
bool CPU::CodeCache::HasPreviouslyFaultedOnPC(u32 guest_pc)
{
return (s_fastmem_faulting_pcs.find(guest_pc) != s_fastmem_faulting_pcs.end());
}
void CPU::CodeCache::BackpatchLoadStore(void* host_pc, const LoadstoreBackpatchInfo& info)
{
s_code_buffer.WriteProtect(false);