mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
bdbba2a52f
With cycle charging on, the dirty-RAM interpreter charges an instruction's fetch and base cycle before its body runs. When that charge reaches a device deadline, the device event runs first. If it raises an interrupt, CAUSE.IP2 is set before MFC0/CFC0 read CAUSE, so the read sees an IRQ that belongs to the next instruction boundary. Compiled code batches its charges to the boundary and never shows this. Seen in the kernel's syscall handler: `mfc0 a1,Cause` ran interpreted, a CD IRQ fell due on its own cycle, and the handler saved CAUSE 0x420 instead of 0x20. The IRQ itself was taken at the right boundary; only the value saved inside the instruction was wrong. MFC0 and CFC0 now return COP0 as it stood when the instruction began. interp_cop0_read_sample links the production decoder (cycle charging on) into a fixture at -O0 and -O2, with a device service that raises IP2 on the read's own cycle. It reads 0x420 before this change and 0x20 after. Controls cover no event and an IRQ raised before the instruction. fixture_link.py stubs every other runtime seam with abort(), so an unexpected call fails the test.
10 lines
368 B
C
10 lines
368 B
C
/* Production dirty-RAM interpreter decoder, built with per-instruction cycle
|
|
* charging on, for test_interp_cop0_read_sample.c. */
|
|
#define PSX_ENABLE_BLOCK_CYCLES 1
|
|
#define PSX_NO_DEBUG_TOOLS 1
|
|
#include "../src/dirty_ram_interp.c"
|
|
|
|
int interp_test_step(CPUState *cpu, uint32_t pc, uint32_t insn, uint32_t *next) {
|
|
return exec_one_fetched(cpu, pc, insn, next);
|
|
}
|