mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 06:15:38 +00:00
Bus: Fix failed safe instruction reads raising guest exceptions
This commit is contained in:
parent
28c88cd69f
commit
028a5c60d7
|
@ -1015,8 +1015,8 @@ ALWAYS_INLINE static TickCount DoDMAAccess(u32 offset, u32& value)
|
||||||
|
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
|
|
||||||
template<bool add_ticks, bool icache_read = false, u32 word_count = 1>
|
template<bool add_ticks, bool icache_read = false, u32 word_count = 1, bool raise_exceptions>
|
||||||
ALWAYS_INLINE_RELEASE void DoInstructionRead(PhysicalMemoryAddress address, void* data)
|
ALWAYS_INLINE_RELEASE bool DoInstructionRead(PhysicalMemoryAddress address, void* data)
|
||||||
{
|
{
|
||||||
using namespace Bus;
|
using namespace Bus;
|
||||||
|
|
||||||
|
@ -1027,17 +1027,24 @@ ALWAYS_INLINE_RELEASE void DoInstructionRead(PhysicalMemoryAddress address, void
|
||||||
std::memcpy(data, &g_ram[address & RAM_MASK], sizeof(u32) * word_count);
|
std::memcpy(data, &g_ram[address & RAM_MASK], sizeof(u32) * word_count);
|
||||||
if constexpr (add_ticks)
|
if constexpr (add_ticks)
|
||||||
g_state.pending_ticks += (icache_read ? 1 : RAM_READ_TICKS) * word_count;
|
g_state.pending_ticks += (icache_read ? 1 : RAM_READ_TICKS) * word_count;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else if (address >= BIOS_BASE && address < (BIOS_BASE + BIOS_SIZE))
|
else if (address >= BIOS_BASE && address < (BIOS_BASE + BIOS_SIZE))
|
||||||
{
|
{
|
||||||
std::memcpy(data, &g_bios[(address - BIOS_BASE) & BIOS_MASK], sizeof(u32) * word_count);
|
std::memcpy(data, &g_bios[(address - BIOS_BASE) & BIOS_MASK], sizeof(u32) * word_count);
|
||||||
if constexpr (add_ticks)
|
if constexpr (add_ticks)
|
||||||
g_state.pending_ticks += m_bios_access_time[static_cast<u32>(MemoryAccessSize::Word)] * word_count;
|
g_state.pending_ticks += m_bios_access_time[static_cast<u32>(MemoryAccessSize::Word)] * word_count;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CPU::RaiseException(address, Cop0Registers::CAUSE::MakeValueForException(Exception::IBE, false, false, 0));
|
if (raise_exceptions)
|
||||||
|
CPU::RaiseException(address, Cop0Registers::CAUSE::MakeValueForException(Exception::IBE, false, false, 0));
|
||||||
|
|
||||||
std::memset(data, 0, sizeof(u32) * word_count);
|
std::memset(data, 0, sizeof(u32) * word_count);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1115,20 +1122,20 @@ u32 FillICache(VirtualMemoryAddress address)
|
||||||
switch ((address >> 2) & 0x03u)
|
switch ((address >> 2) & 0x03u)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
DoInstructionRead<true, true, 4>(address & ~(ICACHE_LINE_SIZE - 1u), line_data);
|
DoInstructionRead<true, true, 4, false>(address & ~(ICACHE_LINE_SIZE - 1u), line_data);
|
||||||
line_tag = GetICacheTagForAddress(address);
|
line_tag = GetICacheTagForAddress(address);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
DoInstructionRead<true, true, 3>(address & (~(ICACHE_LINE_SIZE - 1u) | 0x4), line_data + 0x4);
|
DoInstructionRead<true, true, 3, false>(address & (~(ICACHE_LINE_SIZE - 1u) | 0x4), line_data + 0x4);
|
||||||
line_tag = GetICacheTagForAddress(address) | 0x1;
|
line_tag = GetICacheTagForAddress(address) | 0x1;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
DoInstructionRead<true, true, 2>(address & (~(ICACHE_LINE_SIZE - 1u) | 0x8), line_data + 0x8);
|
DoInstructionRead<true, true, 2, false>(address & (~(ICACHE_LINE_SIZE - 1u) | 0x8), line_data + 0x8);
|
||||||
line_tag = GetICacheTagForAddress(address) | 0x3;
|
line_tag = GetICacheTagForAddress(address) | 0x3;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
default:
|
default:
|
||||||
DoInstructionRead<true, true, 1>(address & (~(ICACHE_LINE_SIZE - 1u) | 0xC), line_data + 0xC);
|
DoInstructionRead<true, true, 1, false>(address & (~(ICACHE_LINE_SIZE - 1u) | 0xC), line_data + 0xC);
|
||||||
line_tag = GetICacheTagForAddress(address) | 0x7;
|
line_tag = GetICacheTagForAddress(address) | 0x7;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1402,7 +1409,7 @@ bool FetchInstruction()
|
||||||
case 0x04: // KSEG0 - physical memory cached
|
case 0x04: // KSEG0 - physical memory cached
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
DoInstructionRead<true, false, 1>(address, &g_state.next_instruction.bits);
|
DoInstructionRead<true, false, 1, false>(address, &g_state.next_instruction.bits);
|
||||||
#else
|
#else
|
||||||
if (CompareICacheTag(address))
|
if (CompareICacheTag(address))
|
||||||
g_state.next_instruction.bits = ReadICache(address);
|
g_state.next_instruction.bits = ReadICache(address);
|
||||||
|
@ -1414,7 +1421,8 @@ bool FetchInstruction()
|
||||||
|
|
||||||
case 0x05: // KSEG1 - physical memory uncached
|
case 0x05: // KSEG1 - physical memory uncached
|
||||||
{
|
{
|
||||||
DoInstructionRead<true, false, 1>(address, &g_state.next_instruction.bits);
|
if (!DoInstructionRead<true, false, 1, true>(address, &g_state.next_instruction.bits))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1443,8 +1451,7 @@ bool SafeReadInstruction(VirtualMemoryAddress addr, u32* value)
|
||||||
case 0x04: // KSEG0 - physical memory cached
|
case 0x04: // KSEG0 - physical memory cached
|
||||||
case 0x05: // KSEG1 - physical memory uncached
|
case 0x05: // KSEG1 - physical memory uncached
|
||||||
{
|
{
|
||||||
DoInstructionRead<false, false, 1>(addr, value);
|
return DoInstructionRead<false, false, 1, false>(addr, value);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x01: // KUSEG 512M-1024M
|
case 0x01: // KUSEG 512M-1024M
|
||||||
|
|
Loading…
Reference in a new issue