diff --git a/Core/MIPS/IR/IRCompBranch.cpp b/Core/MIPS/IR/IRCompBranch.cpp index a2beeba266..8077107d19 100644 --- a/Core/MIPS/IR/IRCompBranch.cpp +++ b/Core/MIPS/IR/IRCompBranch.cpp @@ -411,9 +411,13 @@ void IRFrontend::Comp_JumpReg(MIPSOpcode op) { if (andLink && rs == rd) delaySlotIsNice = false; + // The CPUs ignore the target's low two bits (tests/cpu/jump/unaligned). Sony's ME firmware keeps + // flags there in its command table, and calls the entries as they are, and the PS1 emulator returns + // through such an address. int destReg; if (IsSyscall(delaySlotOp)) { - ir.Write(IROp::SetPC, 0, rs); + ir.Write(IROp::AndConst, IRTEMP_LHS, rs, 0, ~3U); + ir.Write(IROp::SetPC, 0, IRTEMP_LHS); if (andLink) ir.WriteSetConstant(rd, GetCompilerPC() + 8); CompileDelaySlot(); @@ -422,19 +426,17 @@ void IRFrontend::Comp_JumpReg(MIPSOpcode op) { // Account for the delay slot itself in total bytes. js.compilerPC += 4; return; // Syscall (delay slot) wrote exit code. - } else if (delaySlotIsNice && !IsMediaEngine()) { + } else if (delaySlotIsNice) { if (andLink) ir.WriteSetConstant(rd, GetCompilerPC() + 8); CompileDelaySlot(); - destReg = rs; // Safe because FlushAll doesn't change any regs + // Safe because the delay slot doesn't change rs. + ir.Write(IROp::AndConst, IRTEMP_LHS, rs, 0, ~3U); + destReg = IRTEMP_LHS; FlushAll(); } else { - // Bad delay slot. The Media Engine ignores the target's low two bits: Sony's ME firmware keeps - // flags there in its command table, and calls the entries as they are. - if (IsMediaEngine()) - ir.Write(IROp::AndConst, IRTEMP_LHS, rs, 0, ~3U); - else - ir.Write(IROp::Mov, IRTEMP_LHS, rs); + // Bad delay slot. + ir.Write(IROp::AndConst, IRTEMP_LHS, rs, 0, ~3U); destReg = IRTEMP_LHS; if (andLink) ir.WriteSetConstant(rd, GetCompilerPC() + 8); diff --git a/Core/MIPS/Interpreter.cpp b/Core/MIPS/Interpreter.cpp index 9b8fe9b630..3dae884035 100644 --- a/Core/MIPS/Interpreter.cpp +++ b/Core/MIPS/Interpreter.cpp @@ -334,10 +334,9 @@ namespace MIPSInt { int rs = _RS; int rd = _RD; - u32 addr = R(rs); - // The Media Engine ignores the target's low two bits: Sony's ME firmware keeps flags there. - if (mips->IsMediaEngine()) - addr &= ~3; + // The CPUs ignore the target's low two bits (tests/cpu/jump/unaligned). Sony's ME firmware keeps + // flags there, and the PS1 emulator returns through such an address. + u32 addr = R(rs) & ~3; switch (op & 0x3f) { case 8: //jr if (!mips->inDelaySlot) diff --git a/pspautotests b/pspautotests index 51fc2c4d87..713b8ccc4f 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 51fc2c4d87fc09df9e87a62e1755ae4816cda13a +Subproject commit 713b8ccc4f2830c54ce3c20bbafc085f3506e810 diff --git a/test.py b/test.py index fe430cad47..628ee7abc5 100755 --- a/test.py +++ b/test.py @@ -93,6 +93,7 @@ tests_good = [ "cpu/cpu_alu/cpu_div", "cpu/cpu_alu/shift_encodings", "cpu/cpu_alu/allegrex_encodings", + "cpu/jump/unaligned", "cpu/vfpu/callout", "cpu/vfpu/colors", "cpu/vfpu/convert",