mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 10:19:47 -04:00
recompiler: IRQ-redirect guard must CONSUME the benign same-site resume
The first guard shape (6ead85c) surfaced redirects but left cpu->pc
nonzero when the exception epilogue benignly resumed at the site's own
PC (the offline mode-1 restore path publishes cpu->pc = real_epc and
never zeroes it). At a goto-type check site the stale pc then survived
into the NEXT check site, where it read as a foreign redirect and
spuriously unwound the frame mid-function — measured live on WipEout 3:
the top-level PC=0 exit moved earlier (frame ~639, exit ra=0) instead
of dying at the original site. The trampoline's own return-boundary
helper already consumes the same-site publish (pc==stop -> pc=0); the
guard now does the same: surface a foreign resume, consume a same-site
one, fall through untouched only when pc==0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -157,7 +157,7 @@ std::string CodeGenerator::emit_interrupt_check(uint32_t resume_pc,
|
||||
return std::string("#ifdef PSX_ENABLE_BLOCK_CYCLES\n") + indent +
|
||||
"psx_cyc_bb_defer_flush();\n#endif\n" + indent +
|
||||
fmt::format("psx_check_interrupts_at(cpu, 0x{:08X}u);\n", resume_pc) + indent +
|
||||
fmt::format("if (cpu->pc != 0u && ((cpu->pc ^ 0x{:08X}u) & 0x1FFFFFFFu)) return; /* IRQ redirect */\n",
|
||||
fmt::format("if (cpu->pc != 0u) {{ if ((cpu->pc ^ 0x{:08X}u) & 0x1FFFFFFFu) return; cpu->pc = 0u; }} /* IRQ redirect / consume same-site resume */\n",
|
||||
resume_pc);
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ std::string CodeGenerator::emit_interrupt_check_expr(const std::string& resume_p
|
||||
return std::string("#ifdef PSX_ENABLE_BLOCK_CYCLES\n") + indent +
|
||||
"psx_cyc_bb_defer_flush();\n#endif\n" + indent +
|
||||
fmt::format("psx_check_interrupts_at(cpu, {});\n", resume_pc_expr) + indent +
|
||||
fmt::format("if (cpu->pc != 0u && ((cpu->pc ^ ({})) & 0x1FFFFFFFu)) return; /* IRQ redirect */\n",
|
||||
fmt::format("if (cpu->pc != 0u) {{ if ((cpu->pc ^ ({})) & 0x1FFFFFFFu) return; cpu->pc = 0u; }} /* IRQ redirect / consume same-site resume */\n",
|
||||
resume_pc_expr);
|
||||
}
|
||||
|
||||
|
||||
@@ -181,14 +181,14 @@ bool FullFunctionEmitter::emit_function(
|
||||
return std::string("#ifdef PSX_ENABLE_BLOCK_CYCLES\n") + indent +
|
||||
"psx_cyc_bb_defer_flush();\n#endif\n" + indent +
|
||||
fmt::format("psx_check_interrupts_at(cpu, 0x{:08X}u);\n", rt) + indent +
|
||||
fmt::format("if (cpu->pc != 0u && ((cpu->pc ^ 0x{:08X}u) & 0x1FFFFFFFu)) return; /* IRQ redirect */\n", rt);
|
||||
fmt::format("if (cpu->pc != 0u) {{ if ((cpu->pc ^ 0x{:08X}u) & 0x1FFFFFFFu) return; cpu->pc = 0u; }} /* IRQ redirect / consume same-site resume */\n", rt);
|
||||
};
|
||||
auto emit_irq_check_expr = [](const std::string& resume_pc_expr,
|
||||
const std::string& indent = " ") {
|
||||
return std::string("#ifdef PSX_ENABLE_BLOCK_CYCLES\n") + indent +
|
||||
"psx_cyc_bb_defer_flush();\n#endif\n" + indent +
|
||||
fmt::format("psx_check_interrupts_at(cpu, {});\n", resume_pc_expr) + indent +
|
||||
fmt::format("if (cpu->pc != 0u && ((cpu->pc ^ ({})) & 0x1FFFFFFFu)) return; /* IRQ redirect */\n",
|
||||
fmt::format("if (cpu->pc != 0u) {{ if ((cpu->pc ^ ({})) & 0x1FFFFFFFu) return; cpu->pc = 0u; }} /* IRQ redirect / consume same-site resume */\n",
|
||||
resume_pc_expr);
|
||||
};
|
||||
auto emit_cosim_instr = [](uint32_t pc, const std::string& indent = " ") {
|
||||
@@ -1210,7 +1210,7 @@ bool FullFunctionEmitter::emit_function(
|
||||
" * back here as a registered continuation target. */\n"
|
||||
" if (cpu->read_word(0x{:08X}u) != 0u) {{\n"
|
||||
" psx_check_interrupts_at(cpu, 0x{:08X}u);\n"
|
||||
" if (cpu->pc != 0u && ((cpu->pc ^ 0x{:08X}u) & 0x1FFFFFFFu)) return; /* IRQ redirect */\n"
|
||||
" if (cpu->pc != 0u) {{ if ((cpu->pc ^ 0x{:08X}u) & 0x1FFFFFFFu) return; cpu->pc = 0u; }} /* IRQ redirect / consume */\n"
|
||||
" cpu->pc = 0x{:08X}u; return;\n"
|
||||
" }}\n",
|
||||
addr, ram_pc, ram_pc + 0x10u, ram_pc, ram_pc, ram_pc, ram_pc);
|
||||
|
||||
Reference in New Issue
Block a user