Merge pull request #22746 from hrydgard/cpu-jump-low-bits

CPU: jr and jalr ignore the target's low two bits on the main CPU too
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2026-10-23 14:59:31 +02:00
commit da92d72d81
4 files changed
+16 -14

No files matched your search

+11 -9
View File
@@ -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);
+3 -4
View File
@@ -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)
+1
View File
@@ -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",