mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 14:25:37 +00:00
CPU/Recompiler: Don't use intepreter icache when falling back
Fixes broken rendering in TOCA 2. It has self-modifying code every frame, which gets falled back to the interpreter, and using the interpreter's icache, which resulted in stale code executing.
This commit is contained in:
parent
e24a2aa6ac
commit
1ed1d641a6
|
@ -410,7 +410,8 @@ void UpdateFastmemViews(CPUFastmemMode mode)
|
||||||
auto view = m_memory_arena.CreateReservedView(end_address_inclusive - start_address + 1, map_address);
|
auto view = m_memory_arena.CreateReservedView(end_address_inclusive - start_address + 1, map_address);
|
||||||
if (!view)
|
if (!view)
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Failed to map reserved region %p (size 0x%08X)", map_address, end_address_inclusive - start_address + 1);
|
Log_ErrorPrintf("Failed to map reserved region %p (size 0x%08X)", map_address,
|
||||||
|
end_address_inclusive - start_address + 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1664,9 +1665,7 @@ bool FetchInstruction()
|
||||||
{
|
{
|
||||||
DebugAssert(Common::IsAlignedPow2(g_state.regs.npc, 4));
|
DebugAssert(Common::IsAlignedPow2(g_state.regs.npc, 4));
|
||||||
|
|
||||||
using namespace Bus;
|
const PhysicalMemoryAddress address = g_state.regs.npc;
|
||||||
|
|
||||||
PhysicalMemoryAddress address = g_state.regs.npc;
|
|
||||||
switch (address >> 29)
|
switch (address >> 29)
|
||||||
{
|
{
|
||||||
case 0x00: // KUSEG 0M-512M
|
case 0x00: // KUSEG 0M-512M
|
||||||
|
@ -1710,6 +1709,43 @@ bool FetchInstruction()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FetchInstructionForInterpreterFallback()
|
||||||
|
{
|
||||||
|
DebugAssert(Common::IsAlignedPow2(g_state.regs.npc, 4));
|
||||||
|
|
||||||
|
const PhysicalMemoryAddress address = g_state.regs.npc;
|
||||||
|
switch (address >> 29)
|
||||||
|
{
|
||||||
|
case 0x00: // KUSEG 0M-512M
|
||||||
|
case 0x04: // KSEG0 - physical memory cached
|
||||||
|
case 0x05: // KSEG1 - physical memory uncached
|
||||||
|
{
|
||||||
|
// We don't use the icache when doing interpreter fallbacks, because it's probably stale.
|
||||||
|
if (!DoInstructionRead<false, false, 1, true>(address, &g_state.next_instruction.bits))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x01: // KUSEG 512M-1024M
|
||||||
|
case 0x02: // KUSEG 1024M-1536M
|
||||||
|
case 0x03: // KUSEG 1536M-2048M
|
||||||
|
case 0x06: // KSEG2
|
||||||
|
case 0x07: // KSEG2
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
CPU::RaiseException(Cop0Registers::CAUSE::MakeValueForException(Exception::IBE,
|
||||||
|
g_state.current_instruction_in_branch_delay_slot,
|
||||||
|
g_state.current_instruction_was_branch_taken, 0),
|
||||||
|
address);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_state.regs.pc = g_state.regs.npc;
|
||||||
|
g_state.regs.npc += sizeof(g_state.next_instruction.bits);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool SafeReadInstruction(VirtualMemoryAddress addr, u32* value)
|
bool SafeReadInstruction(VirtualMemoryAddress addr, u32* value)
|
||||||
{
|
{
|
||||||
switch (addr >> 29)
|
switch (addr >> 29)
|
||||||
|
|
|
@ -2009,7 +2009,7 @@ template<PGXPMode pgxp_mode>
|
||||||
void InterpretUncachedBlock()
|
void InterpretUncachedBlock()
|
||||||
{
|
{
|
||||||
g_state.regs.npc = g_state.regs.pc;
|
g_state.regs.npc = g_state.regs.pc;
|
||||||
if (!FetchInstruction())
|
if (!FetchInstructionForInterpreterFallback())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// At this point, pc contains the last address executed (in the previous block). The instruction has not been fetched
|
// At this point, pc contains the last address executed (in the previous block). The instruction has not been fetched
|
||||||
|
@ -2032,7 +2032,7 @@ void InterpretUncachedBlock()
|
||||||
const bool branch = IsBranchInstruction(g_state.current_instruction);
|
const bool branch = IsBranchInstruction(g_state.current_instruction);
|
||||||
if (!g_state.current_instruction_in_branch_delay_slot || branch)
|
if (!g_state.current_instruction_in_branch_delay_slot || branch)
|
||||||
{
|
{
|
||||||
if (!FetchInstruction())
|
if (!FetchInstructionForInterpreterFallback())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -100,6 +100,7 @@ ALWAYS_INLINE VirtualMemoryAddress PhysicalAddressToVirtual(PhysicalMemoryAddres
|
||||||
|
|
||||||
// defined in bus.cpp - memory access functions which return false if an exception was thrown.
|
// defined in bus.cpp - memory access functions which return false if an exception was thrown.
|
||||||
bool FetchInstruction();
|
bool FetchInstruction();
|
||||||
|
bool FetchInstructionForInterpreterFallback();
|
||||||
bool SafeReadInstruction(VirtualMemoryAddress addr, u32* value);
|
bool SafeReadInstruction(VirtualMemoryAddress addr, u32* value);
|
||||||
bool ReadMemoryByte(VirtualMemoryAddress addr, u8* value);
|
bool ReadMemoryByte(VirtualMemoryAddress addr, u8* value);
|
||||||
bool ReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value);
|
bool ReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value);
|
||||||
|
|
Loading…
Reference in a new issue