3 Commits

Author SHA1 Message Date
Matthew Stanley ec9e8c327a Refresh COP0 provenance and session mouse reset fixture coverage 2026-10-06 19:25:54 -07:00
Matthew Stanley 22883ef052 Use upstream batched texture windows and inactive interpreter hook seams 2026-10-03 23:51:13 -07:00
Alexandros Mandravillis bdbba2a52f interp: read cop0 before the instruction's own cycle charge
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.
2026-09-30 22:18:36 +03:00