Interpreter: Return 0 on all types of bad memory reads - probably best for IgnoreBadMemoryAccess

But ideally I want to get rid of this at some point.
This commit is contained in:
Henrik Rydgård committed 2026-08-28 14:32:42 +02:00
1 parent 991d43a713
commit 3a1162475b
2 files changed
+25 -16

No files matched your search

+17 -8
View File
@@ -116,7 +116,7 @@ static u8 ReadMMIO_U8(MIPSState *mips, u32 addr) {
static u16 ReadMMIO_U16(MIPSState *mips, u32 addr) {
if (!Memory::IsKernelCodeAddress(mips->pc)) {
Core_MemoryException(addr, 2, mips->pc, MemoryExceptionType::READ_WORD, "Kernel mode only");
return (u8)UNKNOWN_MMIO_POISON;
return (u16)UNKNOWN_MMIO_POISON;
}
WARN_LOG(Log::CPU, "Unhandled MMIO Read16 at %08x", addr);
return (u16)UNKNOWN_MMIO_POISON;
@@ -125,7 +125,7 @@ static u16 ReadMMIO_U16(MIPSState *mips, u32 addr) {
static u32 ReadMMIO_U32(MIPSState *mips, u32 addr) {
if (!Memory::IsKernelCodeAddress(mips->pc)) {
Core_MemoryException(addr, 4, mips->pc, MemoryExceptionType::READ_WORD, "Kernel mode only");
return (u8)UNKNOWN_MMIO_POISON;
return UNKNOWN_MMIO_POISON;
}
if (GpioMMIO::IsGpioAddress(addr)) {
return GpioMMIO::Read32(addr);
@@ -434,6 +434,8 @@ namespace MIPSInt {
} else {
Memory::WriteUnchecked_U32(R(rt), addr);
}
// Report success even if the store got dropped - reporting failure just makes
// the usual retry loop spin on the same bad address forever.
if (rt != 0) {
R(rt) = 1;
}
@@ -481,6 +483,11 @@ namespace MIPSInt {
PC += 4;
}
// On a bad access that's set to be ignored (the default), we mirror what
// Memory::ReadOrException_*/WriteOrException_* do, which is also what the JIT's slow
// path calls: loads produce zero, stores are dropped, and PC advances either way.
// Returning without advancing PC instead would just re-execute the same instruction forever.
// When the access is set to break, Core_MemoryException has already stopped the core.
void Int_ITypeMem(MIPSState *mips, MIPSOpcode op) {
int imm = (signed short)(op&0xFFFF);
int rt = _RT;
@@ -601,12 +608,13 @@ namespace MIPSInt {
case 34: //lwl
{
// Not checking for alignment here - the actual read will be aligned.
if (!Memory::IsValidAddress(addr)) {
u32 mem = 0;
if (Memory::IsValidAddress(addr)) {
mem = Memory::ReadUnchecked_U32(addr & 0xfffffffc);
} else {
Core_MemoryException(addr, 4, PC, MemoryExceptionType::READ_WORD, "lwl");
break;
}
u32 shift = (addr & 3) * 8;
u32 mem = Memory::ReadUnchecked_U32(addr & 0xfffffffc);
u32 result = ( u32(R(rt)) & (0x00ffffff >> shift) ) | ( mem << (24 - shift) );
R(rt) = result;
}
@@ -615,12 +623,13 @@ namespace MIPSInt {
case 38: //lwr
{
// Not checking for alignment here - the actual read will be aligned.
if (!Memory::IsValidAddress(addr)) {
u32 mem = 0;
if (Memory::IsValidAddress(addr)) {
mem = Memory::ReadUnchecked_U32(addr & 0xfffffffc);
} else {
Core_MemoryException(addr, 4, PC, MemoryExceptionType::READ_WORD, "lwr");
break;
}
u32 shift = (addr & 3) * 8;
u32 mem = Memory::ReadUnchecked_U32(addr & 0xfffffffc);
u32 regval = R(rt);
u32 result = ( regval & (0xffffff00 << (24 - shift)) ) | ( mem >> shift );
R(rt) = result;
+8 -8
View File
@@ -216,23 +216,22 @@ namespace MIPSInt
float d[4];
ReadVector(mips, d, V_Quad, vt);
int offset = (addr >> 2) & 3;
const bool valid = Memory::IsValid4AlignedAddress(addr);
if ((op & 2) == 0) {
if (!Memory::IsValid4AlignedAddress(addr)) {
if (!valid) {
Core_MemoryException(addr, 16, PC, MemoryExceptionType::READ_WORD, "lvl.q");
break;
}
// It's an LVL
for (int i = 0; i < offset + 1; i++) {
d[3 - i] = Memory::ReadUnchecked_Float(addr - 4 * i);
d[3 - i] = valid ? Memory::ReadUnchecked_Float(addr - 4 * i) : 0.0f;
}
} else {
if (!Memory::IsValid4AlignedAddress(addr)) {
if (!valid) {
Core_MemoryException(addr, 16, PC, MemoryExceptionType::READ_WORD, "lvr.q");
break;
}
// It's an LVR
for (int i = 0; i < (3 - offset) + 1; i++) {
d[i] = Memory::ReadUnchecked_Float(addr + 4 * i);
d[i] = valid ? Memory::ReadUnchecked_Float(addr + 4 * i) : 0.0f;
}
}
WriteVector(mips, d, V_Quad, vt);
@@ -244,13 +243,14 @@ namespace MIPSInt
// rejected - we don't try to carry it out anyway, same as every other path here.
if ((addr & 0xF) || !Memory::IsValid4AlignedAddress(addr)) {
Core_MemoryException(addr, 16, PC, MemoryExceptionType::READ_WORD, "lv.q");
const float zero[4]{};
WriteVector(mips, zero, V_Quad, vt);
break;
}
#ifndef COMMON_BIG_ENDIAN
cf = reinterpret_cast<const float *>(Memory::GetPointerUnchecked(addr));
if (cf)
WriteVector(mips, cf, V_Quad, vt);
WriteVector(mips, cf, V_Quad, vt);
#else
float lvqd[4];