EE COP1 census 1: 16 ops x 400 cases x {default, soft, accurate}
================================================================
Rig: EE audit exports with harness-thread fault-filter registration
(the thread-affinity blocker resolved to one RegisterFaultHandlerThread
call -- the fault machinery services registered threads regardless of
which one). Scratch block at 16MB through the memory system, actual
recompiled block vs bounded-stepped interpreter (ps2f-based oracle,
confirmed by the FMAX known-answer split: rec clamp 7f7fffff vs
oracle saturation 7fffffff). Columns: fd /400, ACC /400, FCR31 /400.

op        default          FpuSoftFloat     FpuAccurateArith
ADD.S      28/  0/  0        28/  0/  0        0/  0/  0
SUB.S      23/  0/  0        23/  0/  0        0/  0/  0
MUL.S      68/  0/102         0/  0/  0        6/  0/  0
DIV.S     104/  0/ 93         0/  0/  0      104/  0/ 93
SQRT.S    100/  0/  0         0/  0/  0      100/  0/  0
ABS.S       7/  0/  0         7/  0/  0        7/  0/  0
MOV.S       0/  0/  0         0/  0/  0        0/  0/  0
NEG.S      15/  0/  0        15/  0/  0       15/  0/  0
RSQRT.S   206/  0/221         0/  0/  0      206/  0/221
ADDA.S      0/ 17/  0         0/ 17/  0        0/  0/  0
MULA.S      0/ 85/105         0/  0/  0        0/ 11/  0
MADD.S     72/  0/ 52         0/  0/  0        3/  0/ 44
MSUB.S     72/  0/ 53         0/  0/  0        4/  0/ 43
MAX.S       0/  0/  0         0/  0/  0        0/  0/  0
MIN.S       0/  0/  0         0/  0/  0        0/  0/  0
CVT.W       0/  0/  0         0/  0/  0        0/  0/  0

Findings:
- The two options are COMPLEMENTARY, not overlapping: soft float
  closes the multiply/divide/sqrt/rsqrt/fused family (values and
  flags) but does not route add/sub/abs/neg; accurate arithmetic
  closes add/sub (and mostly mul/fused values) but leaves the
  divide family untouched. Neither alone blankets the FPU; both
  together would, except for the orphan below.
- ORPHAN DIVERGENCE -- CLOSED (this commit): ABS.S and NEG.S.
  Hardware treats them as pure sign-bit operations; the recompiler
  clamped their results (denormal -> 0, exp-255 -> FLT_MAX). The
  interaction audit found the precise gate structure: op >= 2
  consumers (multiply and beyond) ALWAYS input-clamp their
  operands, so the ABS/NEG result clamps only guard downstream
  host ADD/SUB, the one consumer class that does not input-clamp
  by default. Under either accuracy option the add path handles
  raw operands, so the clamps are elided exactly there: ABS and
  NEG go to 0/400 under both soft float and accurate arithmetic,
  and default behaviour is proven unchanged by byte-identical
  default rig outputs and 300 frames of identical Tekken pixels
  (cross-binary JIT-hash comparison is recorded as an INVALID
  scoping proof -- JIT bytes embed C-callee addresses, so any
  rebuild perturbs hashes globally; within-binary toggle proofs
  remain sound).
- MAX/MIN/MOV/CVT.W bit-exact in every config, mirroring the VU
  comparison-family result.
- Default-mode scales mirror the VU: add/sub at the small clamp/
  special class, divide family largest, flags concentrated on
  multiply/divide (the VU's O/U sticky story again -- the class
  gate precedent applies if promotion is ever wanted here).

Battery 2 (converts, compares, branches, moves, memory):
  Exact in every config: C.EQ C.LT C.LE C.F (FCR31 C bit included),
  MTC1 MFC1 (GPR travel added to the rig for these), and the
  SWC1->LWC1 memory round-trip (394/400 verified nonzero
  round-trips through EE RAM).

  CVT.S.W -- REAL uncovered divergence, 162/400 under every config:
  the recompiler's int-to-float conversion is consistently one ulp
  low on integers needing more than 24 bits of mantissa (chop where
  the hardware-verified model rounds to nearest). No accuracy
  option routes the convert. Fix candidate: round-nearest rounding
  for the conversion only (an MXCSR flip or arithmetic fixup around
  cvtsi), gated the usual way and priced.

  BC1T/BC1F -- OPEN, rig-entangled: the first run exposed a rig
  limitation (the pre-armed exit fired at the first block boundary,
  truncating multi-block branch programs; fixed with a cycle-budget
  arming that this commit carries), and the rerun shows the rec
  taking BC1T unconditionally in sampled cases even where both
  engines agree the FCR31 C bit is clear. Next probe is designed:
  seeded C with no in-program compare isolates the branch's
  condition evaluation from any compare-to-branch hazard modeling.
  No verdict until it lands.

BC1 investigation, session 2 (isolation and bisection):
- The branch itself is EXACT: seeded-C probes with no in-program
  compare follow the C bit perfectly in both directions.
- Minimal reproducer captured, ordering- and reset-independent
  (the rig gained a per-program Cpu->Reset in prep, matching the VU
  discipline -- correct hardening, but it did not change this):
  C.LT with a false result, exactly THREE nops, then BC1T -- the
  recompiler takes the branch regardless of the C bit, while SIX
  nops between compare and branch are correct. Single-case spec at
  tests/fpaudit reproduction instructions: operands 2.0 vs 1.0
  (C=0), markers on r10/r11.
- One confound remains open: an otherwise-identical program whose
  fall-through instruction uses a different register behaved
  correctly in one (pre-reset) run; whether that was stale-state
  luck is unresolved.
- A second thread from the same session: the recompiler's CFC1 of
  FCR31 in a branch delay slot returned 0x01000001 where the seeded
  and interpreter-read value was 0 -- recorded, uninvestigated.
- Next step is definitive rather than inferential: dump the
  compiled bytes of the three-nop block (the rig supplies the exact
  program and a fresh reset) and read what the emission actually
  does between the compare's FCR31 write and the branch's test.

BC1 investigation, session 3 (the byte dump):
- Instrument landed: ps2_audit_ee_blockptr(pc) resolves the compiled
  block through PC_GETBLOCK, and the harness dumps it immediately
  after the recompiler pass (the interpreter pass's prep Reset wipes
  the cache, which cost one misfire; a stale duplicate harness hook
  overwriting the good dump cost another -- both are why the dump
  fires exactly once, after the rec pass).
- The three-nop reproducer's compiled block is in
  BC1-BLOCKDUMP.txt, and IT READS CORRECT in every particular:
  the compare loads fpr[0]/fpr[1] from the right addresses,
  denorm-flushes, sign-folds, compares, and clears/sets the C bit
  at fprc[31]; the swapped delay slot (r10:=1) is hoisted before
  the test; the branch reloads fprc[31] fresh, tests 0x800000, and
  je's rel32 resolves to the fall path whose pc:=0x01000018 is the
  correct post-swap fall address, with the taken path's
  pc:=0x0100001C equally correct; the fall path even chains inline
  into the compiled fall block (r10:=2, r11:=1, then the jump's
  pc:=0x01000000). Static reading exonerates the emission.
- The contradiction -- a correct block whose execution takes
  wrongly with a clear C bit, while the end-state FCR31 reads 0 --
  therefore lives in runtime effects the dump cannot see: entry at
  an unexpected pc, state mutation between test and effect, or an
  instrumentation offset lie not yet caught by the rig's integrity
  checks. Next session is a live watch: hardware watchpoints on
  fprc[31] and the r10 slot across the block's execution, which
  will show the actual order and values of every write.

BC1 investigation, session 4 (the live watch) -- RESOLVED:
- Hardware watchpoints on fprc[31] and the marker registers across
  the reproducer's execution show the recompiler behaving CORRECTLY
  in every iteration: hoisted delay slot, correct fall-through into
  the chained fall block, correct markers. The anomaly was the
  rig's fifth artifact of the campaign: the program's terminating
  jump looped back to scratch, the recompiler re-ran the whole
  program until the cycle budget expired, and the exit sliced the
  final iteration mid-way -- right after the hoisted delay slot --
  leaving the delay marker's value as the final state. The
  interpreter's instruction-count stop always completes exactly one
  pass, so the engines' "divergence" was two different slice points
  of a loop. The nop-count dependence was just where the budget
  landed; the register-dependent confound was another slice point.
- Fix: audit programs now terminate into a marker-free parking
  loop (a self-jump well past the program), so the recompiler
  spins harmlessly after one pass. With parked programs: BC1T
  0/400, BC1F 0/400, and the three-nop reproducer matches exactly.
  THE EE BRANCH FAMILY IS EXACT.
- The CFC1 thread also closes into a finding: the recompiler
  CONSTRUCTS the architectural FCR31 readout -- hardwired bits
  0x01000001 (FS and the rounding mode, fixed on EE silicon) plus
  flag bits remapped to their architectural positions -- while the
  interpreter returns the raw stored word. They agree exactly on
  seeds respecting hardware invariants and diverge only on
  rig-seeded non-architectural states. Whether every CTC1-reachable
  state agrees (i.e. whether interpreter CTC1 masks writes the same
  way) is the queued round-trip probe; until then this is a
  representation note, with the recompiler the more
  hardware-faithful side.

CTC1 round-trip probe result -- the note UPGRADES to a real
divergence: CTC1 stores its operand RAW on BOTH engines (FCR31
memory identical across 400 cases, arbitrary bits included), which
makes every probed state game-reachable, and CFC1 readback then
diverges on 399/400 of them. The recompiler constructs the
architectural readout (hardwired 0x01000001 -- the EE's fixed
rounding mode and FS -- plus flag bits remapped to architectural
positions); the interpreter returns the raw stored word. Example:
CTC1(0xFFFFFFFF) reads back 0x0183C079 on the recompiler and
0xFFFFFFFF on the interpreter. Which side matches silicon decides
the fix direction (teach the interpreter to construct, or the
recompiler to return raw), and that is a two-minute hardware
capture: CTC1 a handful of garbage patterns on a real EE and read
them back with CFC1. Queued for hardware time alongside the EFU
captures; no fix lands blind.

EE per-op pricing, session 1 (partial -- rig TODO captured):
  Method transferred from the VU: 200x-unrolled programs, 2000
  cases, per-program rec-pass wall timing (the harness gained an
  [EETIME] line), NOP baseline subtracted, alternated min-of-three,
  with a warmup program absorbing the first-program compile/warm
  cost that initially produced negative prices.
  Prices that landed before the crash (ns per recompiled op):
    ADD.S   default 6.0   soft 6.0   accurate 8.25
    MUL.S   default 4.5              accurate 6.75
  Rig TODO, characterized: multi-program specs of 200-op programs
  abort deterministically at the fifth program switch, in every
  config -- reset-churn in the per-prep Cpu->Reset() from the audit
  thread, count-dependent, not op-dependent (a 200-DIV single
  program runs and prices fine at 0.038s/2000 cases). Workaround
  for the remaining rows: one program per spec, one run per op.
  The missing prices (DIV/SQRT/MADD across configs, soft MUL) fill
  in next pricing session.

EE per-op pricing, session 2 -- TABLE COMPLETE (one-program-per-spec
workaround, warm program + op per spec, 54/54 runs clean):

  op      default   soft    accurate     (ns per recompiled op)
  ADD.S     5.5      5.5      7.7
  MUL.S     4.2     30.8      6.0
  DIV.S     8.0    131.2      8.2
  SQRT.S    7.2    156.2      7.0
  MADD.S    7.2     39.2     16.5

  The prices cross-validate the accuracy census: cost lands exactly
  where routing does. Soft-add equals default (soft does not route
  add/sub); accurate-div and accurate-sqrt equal default (accurate
  does not route the divide family). Structure for the promotion
  math: accurate arithmetic is nearly free (+1.8 to +2.2ns on
  add/mul, +9.3 on fused) and closes add/sub exactly; soft float is
  the heavy hammer (divide family at 131-156ns, multiply at 31ns)
  and closes everything it routes, flags included. Maximum accuracy
  (both options) prices each op at whichever option owns it.



CVT.S.W -- CLOSED (this commit): the convert gains an MXCSR
round-to-nearest window under either accuracy option (the EE JIT's
global chop rounding was leaving the recompiled convert one ulp low
on integers wider than 24 bits). Full-range 32-bit int census:
181/400 divergent under default, 0/400 under either option. Default
emission proven unchanged by byte-identical rig outputs. Price:
unmeasurable against run noise at 400k executions (alternated
min-of-three wall timing, delta below the ~10ms noise floor);
structurally one stmxcsr and two ldmxcsr per convert, paid only
under the options that already carry the accuracy costs.
