Run with --reg v0 it reported 'varies-within-frame' for a colour
computation that is provably correct. The probe arms a WINDOW of block
leaders rather than one instruction, so the six values it counted came
from six different PCs -- and they decode exactly right for source
(248,136,8) at $s6=80: 248*80>>7 = 155, 136*80>>7 = 85, 8*80>>7 = 5, and
the assembled word 939873691 = 0x3805559B carries precisely those bytes
under command 0x38. 136 and 8 are the source bytes mid-load.
The test is only meaningful for a value that should be fixed for the
whole frame -- the callee-saved fade scale it was written for. For a
scratch register, counting across PCs measures the program running.
Scratch registers now return not-applicable, and --per-pc breaks values
down by instruction so each can be read on its own.
The oracle's source table also came back byte-identical to psx-runtime's:
same 3 words, same counts.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
packet_writers named the guilty code. Six PCs write the additive quads'
colour words, all running the same idiom:
lbu ,64() ; mult , ; mflo ; sra ,,7 ; sb ...
$s6 is the fade level, one value per frame, so every vertex in a frame
must see the same $s6 and the 64 quads should carry a handful of
colours. psx-runtime carries ~153 where DuckStation carries 3. A $s6
that changes WITHIN a frame explains that exactly: same source colours,
same arithmetic, a different scale per vertex.
Unlike every other comparison here this needs no oracle and no phase
lock -- 'constant within a frame' is checkable against one emulator on
its own, which is why it is worth a tool of its own after so many runs
lost to synchronising two.
$s6 is callee-saved and stays live across the swc2/NCLIP at
0x800684C4..0x800684D8, which is where a recompiled routine could lose it.
Ruled out first, by reading the implementations: mult computes eagerly
into cpu->lo and mflo reads it (no deferred-evaluation hazard), sb and
lw both handle scratchpad byte-exactly, and the lwl/lwr/swl/swr tables
are correct for little-endian R3000A.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>