docs(phase-32): T4b hand pass — row (c) func_80039308 PLATEAU at 4 (§501-O phantom-slot census for a leaf; ledger row); 🛑 CHECKPOINT refreshed for the pause: (a) PROVED · (b) BANKED commit:4001 · (c) PLATEAU 4 · (d) NEXT (sibling search first), then T4b close and T5

- (c): cnt's slot is spill_stack_slot[23] (evicted from $s7), so the phantom @0x8 must be an initial-loop no-traffic slot; every producer refuted on dump facts (leaf: no save area; LO spilled after GR and products alternate to GR_REGS — C3 measured; no unallocated single-block equiv pseudo; expand-time locals precede; 13 lh single-use, no lb). Rows 49/50 = two move_movables hoists in body order.
- row (d) read only (rtu DIFF 13 re-verified); brief + step 0 (§501-N banked-sibling search on its symbol set) in the checkpoint
- no src/ change in this commit; fleet R22 owed at the T4b close (last check-all 218/218 before the (b) bank)
This commit is contained in:
Drew T
2026-09-06 12:31:08 -06:00
parent 3e90db193f
commit e7679b51ff
6 changed files with 578 additions and 141 deletions
+41
View File
@@ -0,0 +1,41 @@
# main:func_80039308 (src/800_c.c, 518 ins) — T4b HAND PASS, S84 (2026-09-06) — PLATEAU at 4 (verdict, not a bank)
Current best draft: `.run/P32/t5x/fable/func_80039308.c` — rtu DIFF 4 in the real TU (rows 49/50 preheader swap, rows 412/415
`lhu/sh $t0` vs `$s7`). Fable's Y4 (`.run/P32/t5x/work/func_80039308/v_Y4.c`, direct `*(s16 *)(p + 6) = arg1`) is REGISTER-EXACT on
412/415 (`lhu $s7,X($sp)` / `sh $s7`) and is the natural spelling; its residual is the frame: target `[arg1 spill @0x0][8 bytes, no
traffic @0x8][cnt @0x10]` (frame 0x40), Y2 gives `[arg1 @0][cnt @8]` (0x38), Y4's dead `u16 sav[4]` lands at 0x0 and pushes arg1 to 0x8.
## The phantom slot — producer census (§501-M applied; every row read from the dumps)
The draft's `.greg`: `Spilling reg 23. Register 95 now on stack.` then `Spilling reg 65.` — `cnt` (95) is global-allocated to `$s7`,
`order_regs_for_reload` picks `$s7` as the GR spill register (the least-used register in a function that uses every GPR), `spill_hard_reg`
evicts 95 (its retry fails: it conflicts with 50 allocnos and `$v0/$v1/$a0/$a1/$s2`), `alter_reg(95, 23)` → `spill_stack_slot[23]` = cnt's
slot, allocated AFTER the initial `alter_reg` loop. So the target's `[arg1 @0][X @8][cnt @0x10]` needs X allocated between the initial
loop's arg1 slot and the `$s7` eviction — i.e. an INITIAL-LOOP slot (any regno > 73) with no traffic, or a main-loop slot before the
first spill (reload1.c:879). Refuted on this function:
| producer | why not here |
|---|---|
| caller-save area (caller-save.c:249) | leaf function, 0 calls → every `reg_n_calls_crossed` = 0 → `caller_save_needed` never set |
| `spill_stack_slot[65]` (a LO-evicted product whose retry fails) | GR_REGS is spilled before LO_REG (draft trace), so it would land AFTER cnt's slot; and a product's alternate class is `GR_REGS` (C3: two overlapping products → `mflo $a1`/`$v1`, both allocated) |
| reload1.c:879 (invalid REG_EQUIV address) | needs an UNALLOCATED single-block pseudo with a MEM equivalence through a spilled pseudo; local-alloc allocates every single-block pseudo here (the `k2 = sav[0]` temp gets `$t0` — `$t0` is free at idx 444 because s18 dies at 443) |
| expand-time local (`u16 sav[4]`, `pad[2]`) | precedes every reload slot: Y1/Y3/Y4 measured arg1 at 0x10/0x8 |
| global's local-alloc kick-out (global.c:1100–1160) leaving an unallocated local | its traffic would be visible unless def/use are adjacent through `$s7`; the only adjacent `$s7` pairs are the six `mflo $s7` products, which are LO-class global allocnos (not local qtys) — and C3 shows products never fail |
| combine ghost (newi2pat split → `ST_REGS or none`) | needs a signed narrow load whose narrow value is still live: all 13 `lh` in the target are single-use (`bne`, `mult`, `sll`, `addiu`, `slti` consumers), `pan`'s four uses sit in four blocks (a HImode `pan` would leave real `sll/sra` in the arms — the target has none), no `lb`; `b4`'s `lbu` folds to the `addu $v1,$s4,$zero` copy via `nonzero_bits` (2-insn merge, refs zeroed) |
`tools/ghost_census.py` on the draft, Y2, Y4 and C3: no ghosts. **Verdict: the phantom slot's producer is not identified; the Y4 form is
the natural one and the whole 412/415 residual is this slot's offset.**
## Rows 49/50 (`addiu $s3,$zero,2` before `sll $s2,$s5,8`)
Read from `.loop`: both are `move_movables` hoists in the target — the `2` (first used in the innermost loop's `*t1 == 2` compare) precedes
`vbase = b2 * 0x100` because movables are spliced in body order, so the original computed `vol = b2 * 0x100` IN THE BODY (hoisted), not in
the preheader. Fable's X2 (unpinned vbase in the body) measured 515 ins / 495: the `$18` pin is load-bearing for the callee-saved bank once
vbase is a hoisted movable; the steering of a hoisted invariant to `$s2` without a pin (§501-E launders) is the open lever.
## Measured this session
| variant | change | result |
|---|---|---|
| c0 (draft) | — | 4; frame 0x40 = sav[8] 16 + cnt 8; no ghosts; `Spilling reg 23` evicts 95 |
| cY4 / cY2 | Fable's direct-arg1 forms | frame 0x40 (`sav[4]` at 0x0) / 0x38; unallocated at reload entry = {73, 95}; no ghosts |
| c3_twoprod | Y2 + `pa = v*A; pb = v*B;` before both shifts | 434 ins, frame 0x38, products in `$a1`/`$v1` (alternate class wins), no slot |
Next levers (not tried): a movable-invariant `vol = b2 * 0x100` in the body with §501-E launders to hold `$s2`; for the slot, a
register-only 3-insn chain that combine folds into one insn with a live head (path (b), §501-M) — no such chain exists in this
function's target shape (every `and/sll/addu` triple is already at its folded form).
+392
View File
@@ -0,0 +1,392 @@
/* func_80039308 (main, src/800_c.c, 518 ins) -- NEAR, closeness 17 (518 ins, exact length).
*
* P32/T3 pass: 34 -> 17, starting from the S79 body (.run/S79w/opus/func_80039308.c).
* Every number below was measured with tools/match_one.py against
* asm/nonmatchings/800_c/func_80039308.s; the final body was re-checked with
* tools/rtu_match.py in the real TU (same 17, no declaration conflicts).
*
* WHAT MOVED IT (each byte-witnessed, in the order it was found):
*
* 1. `s16 b4;` + `n = b4;` (was `s32 b4; n = b4 & 0xFF;`) 34 -> 33
* The target's `addu $v1,$s4,$zero` at idx 39 is a WIDENING COPY, not a mask. A short
* whose only def is an `lbu` needs no extension instruction, but gcc-2.7.2 still emits
* the (set (reg n) (reg b4)) move and cannot coalesce it (b4 stays live, n is killed by
* `sll $v1,$v1,9`). Measured INERT for this instruction: `b4 & 0xFF`, `(u8)b4`,
* `(s32)(u8)b4` (all `andi`); `n = b4` with b4 an s32 or a u8, `n = *s0`, `n = s0[0]`,
* `n = (u8)*s0` (all folded away -> 517 ins). The s16 declaration is the whole trick.
*
* 2. SPLIT THE PAN SUM OFF ITS -0x40. `pan1 = s0[4] + t9[3]; pan1 -= 0x40;` instead of
* one expression ties the sum's destination to the SECOND load's register, which is what
* the target does (`addu $v0,$a1,$v0`). 33 -> 32.
*
* 3. THE FIRST PAN LOAD MUST LAND IN $a1 -- REUSE A DEAD LOCAL TO PUT IT THERE.
* `bb = s0[4]; pan1 = bb + t9[3]; ...`, where `bb` is the depth-2 loop's own (dead) temp,
* shares $a1 with `cc`, exactly as the target does. 32 -> 30. A fresh temp, `cc`, `x`
* and `res` were each measured: 47, 32, 35, 36. THE VARIABLE'S IDENTITY IS THE LEVER --
* which dead local you reuse decides the hard register.
*
* 4. MERGE THE arm-1 `sav[0]` TEMP WITH THE else-arm COMPARE LOCAL (`k2`). 30 -> 26
* Sweeping 22 candidates for that temp: only `k2` pays, and it pays in the OTHER arm --
* the merge makes k2 a cross-arm global pseudo, so the else head comes out
* `addu $t1,$t6,$v0` / `addu $t0,$s5,$zero` (was $t0 / $s2) and idx 440/441/443/452 all
* close. Splitting it back out (with or without a dummy `k2 = b2` def in arm 1) is 21.
*
* 5. PIN THE DEAD-RESET CONSTANT LOCAL: `register s32 two __asm__("$2")`. 26 -> 22
* `two` is the S349 dead-reset local holding the 2 stored to D_800762B0[j]. Pinned to
* $v0 it forces the D_800762B0 pointer load up into the A2B98 sequence and fixes the
* `sb $v0,0($v1)` operands. Swept $2..$8: $2 is the unique optimum (26,26,53,60,58,56).
*
* 6. A SECOND MASK TEMP AND AN ADDRESS LOCAL, BOTH PINNED TO $4. 22 -> 21
* mp = &mm[j]; mv = ~*mp; D_800C7D20 &= mv; mv2 = *mp; D_800A2B98 |= mv2;
* with `register s32 *mp __asm__("$4")` AND `register s32 mv2 __asm__("$4")`. Two
* variables on ONE hard register is the point: the target's address register dies INTO
* the second loaded value (`lw $a0,0x0($a0)`), and only the shared pin reproduces
* `lui $v0,%hi(D_80073140) / sll $a0,$a2,2 / addu $a0,$a0,$v0 / lw $v0,0x0($a0)`.
* mv2 swept $2..$7: 21,43,17,18,31,25 -- $4 unique. The mp pin alone is inert.
*
* 7. NAME THE BYTE OFFSET IN A DEAD LOCAL AND COMPUTE t9 FIRST. 21 -> 17
* v = n * 0x10;
* t9 = *(u8 **)((u8 *)arg0 + 0x1E0) + n * 0x200;
* cnt = *(*(u8 **)((u8 *)arg0 + 0x1DC) + v);
* Naming the offset takes the MULT out of the MEM address, so the address PLUS keeps its
* source operand order (base first) instead of being canonicalised to (mult, base); the
* t9-before-cnt order then lets both `sll`s issue before the `addu`. The whole head
* block (idx 38/40/41/42) closes. 25 candidate locals were swept for that offset temp:
* `v`, `pan` and `mv2` all give 17 (identical diff sets), `x` 20, `xoff` 21, most 22+.
*
* MEASURED INERT ON THIS BODY (do not re-try):
* - THE HEAD, before item 7: textual operand swap, `(n << 4)`, `*(u32 *)` casts,
* `tbl = base; cnt = tbl[n*0x10]`, `tbl = base; tbl += n*0x10; cnt = *tbl` (this one DOES
* fix the RTL operand order but flips $v0/$a0), pinning a named base pointer to $2 or $4,
* pinning t9 to $25 (514 ins), pinning an offset local to $4 (85). 27-46 each.
* - idx 390/391, the missing `addu $a2,$a0,$zero`: `p = r;` before the guard, a fresh
* `p2 = r;`, `p = &D_800C6DD0[idx1*0x60];` recomputed, `p = r + 0`. cse propagates `r`
* into all eleven post-guard stores ($a0) AND flips p/q from $a2/$a3 to $a3/$a2: 57-70.
* The copy needs a pseudo cse will not canonicalise away; no C spelling found.
* - idx 49/50 (`sll $s2,$s5,8` vs `addiu $s3,$zero,2`, a 2-insn preheader swap): swapping
* the u26/vbase statements (35), `vbase = u26 * 0x100` (17, conserved), hoisting the 2
* into a named local (520 ins) or a $19-pinned one (520 ins), unpinning vbase (59),
* moving vbase into the loop (515 / 262).
* - idx 412/415 (`lhu $t0` vs `lhu $s7`): pinning k2 to $21/$22/$23 explodes to 501-504 at
* 521 ins (a callee-saved pin forces extra copies); $8/$9/$10 are 22/26/26.
* - THE MASK BLOCK'S LAST 11 (idx 484-490, 494-497) IS ONE ALIAS FACT. The second
* `D_80073140[j]` load cannot be scheduled above the `D_800C7D20` store from C. Writing
* it as a struct member (`((VMask *)mp)->w`, or typing mp as `VMask *`) DOES hoist it --
* gcc-2.7.2's true_dependence returns 0 when MEM_IN_STRUCT_P differs and the OTHER ref's
* address does not vary -- but it costs the item-6 allocation: net 20-24, never better.
* Putting both loads adjacent lets cse merge them (516/517 ins). Mixed spellings (array
* `D_80073140[j]` for one side, `*mp` for the other) either merge or do not hoist. Also
* swept: mm pinned $2..$5 (the pin IS honoured and conserved at 22), mv pinned $2/$3/$5/$6,
* reordering the two read-modify-writes, naming the `~`, both operand orders, moving
* `two = 2` and the D_800762B4 store, a named D_800762B0 pointer, a 4th dead reset, and
* zero-byte `__asm__ ("" :: "r"(...))` sliders on mm/mv. All 17 or worse.
* - permuter_ils --klass REGALLOC, 2 cycles x 150s @ -j3, seeded with the 22-point body:
* best 22, no improvement. These residuals are cross-block allocation + sched2 order,
* outside the permuter's reach.
*
* RESIDUAL (17, exact length, same instruction multiset in every cluster):
* idx 49,50 2 preheader: the hoisted `2` vs the vbase `sll`, adjacent swap
* idx 390,391 2 the un-spellable `addu $a2,$a0,$zero` (reorg duplicates the target insn)
* idx 412,415 2 the sav[0] temp on $t0 where the target reuses $s7
* idx 484-490 7 the second mask load stuck below the D_800C7D20 store (alias)
* idx 494-497 4 the D_800762B0 `addu` scheduled after the A2B98 store instead of before
*
* Relocation audit (SYS law 1c): the 16 D_ symbols named here are exactly the 16 %hi/%lo
* operands of this .s -- verified by grepping both. The function is a leaf (0 jal), so
* there is no S263 call-arity axis. Declarations are copied from src/800_c.c and
* rtu_match.py confirms the TU accepts them.
*/
typedef struct { u32 w; } VMask;
extern u8 *D_800762B0;
extern u8 D_800762B3[];
extern u8 D_800762B4[];
extern s32 D_80073140[][1]; /* [][1] spelling: load-bearing for func_800391D4 (S79 lever; §500-I) */
extern u16 D_8006AB30[];
extern u16 D_8006ABD8[];
extern u16 D_8006ACD8[];
extern s16 D_8006AF08[];
extern s32 D_800A2B98;
extern s32 D_800A2BA0;
extern u8 D_800A4F19;
extern u8 D_800C6DD0[];
extern u8 D_800C6DD4[];
extern u8 D_800C6DDD[];
extern s32 D_800C7D20;
extern s32 D_800C7D2C;
void func_80039308(u8 **arg0, s16 arg1) {
u8 *src;
u8 *s0;
u8 *t9;
u8 *a3;
u8 *t1;
u8 *a1p;
u8 *a0p;
u8 *p;
u8 *q;
u8 *r;
u8 *tb;
s32 b2;
s32 b3;
s16 b4;
s32 bb;
u8 t3;
u8 t5;
s16 t7;
s16 cc;
s32 i;
s32 cnt;
s32 a2;
s32 t0;
s32 v1;
s32 res;
s32 idx1;
u8 *cb;
s32 *mm;
register s32 *mp __asm__("$4");
register s32 mv2 __asm__("$4");
register s32 two __asm__("$2");
s32 tmp;
s32 pan;
s32 pan1;
s32 x;
s32 s17;
s32 s18;
s32 v;
s32 u26;
s32 n;
register s32 vbase __asm__("$18");
s32 off;
u32 t2;
u32 vol;
u32 vv;
u32 prod;
s32 k2;
u8 *tbl;
s32 tmp2;
s32 coff;
s32 xoff;
s32 mv;
s32 j;
s32 ax;
s32 ax2;
u8 *pb;
s32 c7;
s32 pa, pb;
src = *arg0;
*arg0 = src + 1;
b2 = src[0];
*arg0 = src + 2;
b3 = src[1];
if (b3 != 0) {
if ((((u8 *)arg0 + arg1)[0x1BA] & 1) == 0) {
s0 = (u8 *)arg0 + (arg1 * 26 + 26);
i = 0;
b4 = *s0;
n = b4;
v = n * 0x10;
t9 = *(u8 **)((u8 *)arg0 + 0x1E0) + n * 0x200;
cnt = *(*(u8 **)((u8 *)arg0 + 0x1DC) + v);
if (cnt != 0) {
u26 = b2;
vbase = b2 * 0x100;
do {
if (u26 >= t9[6] && u26 <= t9[7]) {
t2 = 0x100;
t3 = 0;
t5 = 0;
t7 = -1;
t0 = 0;
a3 = D_800C6DDD;
a2 = 1;
t1 = D_800762B0;
do {
if (a3[0x4E] != 0) {
bb = a3[0];
if ((u8)bb < (t2 & 0xFF)) {
t3 = a2;
t2 = bb & 0xFF;
} else if ((u8)bb == (t2 & 0xFF)) {
if (D_800762B3[a2] == 0 && *t1 == 2) {
t3 = a2;
}
}
} else {
t5 = 1;
t7 = t0;
break;
}
a2++;
t1++;
t0++;
a3 += 0x60;
} while (t0 < 0x10);
if (t5 == 0) {
if (*t9 >= t2) {
t7 = t3 - 1;
} else {
a1p = D_800762B0;
a0p = D_800762B4;
v1 = 0;
while (v1 < 0x10) {
if (*a1p == 2 && *a0p == 0) {
res = v1;
goto found;
}
v1++;
a1p++;
a0p++;
}
res = -1;
found:
t7 = res;
}
}
if (t7 >= 0) {
p = &D_800C6DD0[t7 * 0x60];
q = p + 0x10;
p[0xD] = *t9;
if (p[0x5C] != 0 && *(s16 *)(p + 8) == b4 && p[0xC] == i &&
*(s16 *)(*(u32 *)(p + 0x50) + 0x1EC) == *(s16 *)((u8 *)arg0 + 0x1EC)) {
*(s32 *)(p + 0x14) = 0x13;
} else {
tmp = *(s16 *)(t9 + 0x16) - 1;
tbl = *(u8 **)((u8 *)arg0 + 0x1DC) + (tmp >> 1) * 0x10;
if (tmp & 1) {
x = *(s16 *)(tbl + 0xE) << 3;
} else {
x = *(s16 *)(tbl + 0xC) << 3;
}
*(s32 *)(q + 0x1C) = x;
*(u16 *)(q + 0x3A) = *(u16 *)(t9 + 0x10);
*(u16 *)(q + 0x3C) = *(u16 *)(t9 + 0x12);
*(s32 *)(q + 4) = 0x6009F;
}
v = b3 * s0[1];
v >>= 7;
v = v * t9[2];
v >>= 7;
v = D_8006ACD8[v];
v = v * *(s16 *)((u8 *)arg0 + 0x1F2);
v >>= 7;
if (D_800A4F19 != 0) {
bb = s0[4];
pan1 = bb + t9[3]; pan1 -= 0x40;
cc = pan1;
if (pan1 < 0) {
cc = 0;
} else if (pan1 >= 0x80) {
cc = 0x7F;
}
if (cc > 0) {
pa = v * D_8006AF08[0x80 - cc];
pb = v * D_8006AF08[cc];
s17 = pa * 4 >> 16;
s18 = pb * 4 >> 16;
} else {
s17 = (s16)v;
s18 = v * D_8006AF08[cc] * 4 >> 16;
}
} else {
s17 = s18 = v * 0x2D41 >> 14;
}
*(s16 *)(q + 8) = (u32)((s16)s17 * *(s16 *)((u8 *)arg0 + 0x10)) >> 14;
*(s16 *)(q + 0xA) = (u32)((s16)s18 * *(s16 *)((u8 *)arg0 + 0x10)) >> 14;
pan = *(s16 *)(s0 + 2);
vol = vbase;
if (pan >= 0x41) {
vol = vbase + (u32)((pan - 0x40) * t9[0xD] * 4);
} else if (pan < 0x40) {
vol = vbase - (u32)((0x40 - pan) * t9[0xC] * 4);
}
tmp2 = t9[4] * 0x100 - t9[5];
*(s32 *)(p + 0x54) = tmp2;
tmp2 -= 0x3C00;
vol -= (u32)tmp2;
p[0x58] = t9[0xC];
p[0x59] = t9[0xD];
vv = (u16)vol;
if (vv >= 0x5301) {
*(s16 *)(q + 0x14) = 0x3FFF;
} else {
prod = D_8006AB30[vv >> 8];
prod *= D_8006ABD8[(vv & 0xFE) / 2];
*(s16 *)(q + 0x14) = prod >> 15;
}
p[0x5D] = 1;
D_800A2B98 &= ~((VMask *)q)->w;
D_800C7D20 |= ((VMask *)q)->w;
D_800762B4[t7] = 1;
if (t9[1] & 4) {
D_800A2BA0 &= ~((VMask *)q)->w;
D_800C7D2C |= ((VMask *)q)->w;
} else {
D_800C7D2C &= ~((VMask *)q)->w;
D_800A2BA0 |= ((VMask *)q)->w;
}
idx1 = t7;
r = &D_800C6DD0[idx1 * 0x60];
p = r;
if (r[0x5A] != 0) {
coff = *(s16 *)&r[6] * 26;
*(u8 *)(*(u32 *)&r[0x50] + coff + idx1 + 0x23) = 0;
r[0x5A] = 0;
}
r = 0;
*(s0 + idx1 + 9) = 1;
*(s16 *)(p + 4) = b2;
*(s16 *)(p + 8) = b4;
p[0xC] = i;
p[0x5C] = 1;
*(s16 *)(p + 0) = s17;
*(s16 *)(p + 2) = s18;
*(u32 *)(p + 0x50) = (u32)arg0;
p[0x5B] = 1;
*(s16 *)(p + 6) = arg1;
if (*((u8 *)arg0 + 0x1F4) != 0) {
p[0x5A] = 2;
} else {
p[0x5A] = 1;
}
}
}
i++;
t9 += 0x20;
} while (i < cnt);
}
}
} else {
j = 0;
tb = (u8 *)arg0 + arg1 * 26;
k2 = b2;
off = 0;
do {
if ((tb + j)[0x23] != 0 && *(s16 *)&D_800C6DD4[off] == k2) {
idx1 = (s16)j;
xoff = idx1 * 0x60;
cb = D_800C6DD0;
r = cb + xoff;
if (r[0x5A] != 0) {
coff = *(s16 *)&r[6] * 26;
*(u8 *)(*(u32 *)&r[0x50] + coff + idx1 + 0x23) = 0;
r[0x5A] = 0;
}
mm = (s32 *)D_80073140;
D_800C7D20 &= ~mm[j];
D_800A2B98 |= mm[j];
pb = D_800762B0 + j;
two = 2;
*pb = two;
D_800762B4[j] = 0;
}
cb = 0;
mm = 0;
two = 0;
j++;
off += 0x60;
} while (j < 0x10);
}
}
+1
View File
@@ -4,3 +4,4 @@
{"ts": "2026-09-05 23:33:21", "addr": "0x800cf408", "name": "func_800CF408", "reach": null, "klass": "SCHED+REGALLOC", "nins": 178, "status": "near", "closeness": 3, "where_stuck": "S83 Fable: 49 -> 3, zero pins (the \u00a7501-H shape + a dead arg1 kill against cse re-association + the P_TAG OT write + a named mhi born before block 1). Residual idx 10-12 = \u00a7501-H verbatim (the unboosted tag load blocks one cycle behind the tpage sw; the empty cycle eats the highest-LUID floater ori $s5,0x96) COUPLED to the $t2/$t3 qty_compare contest (2389 vs 2400): every cure of one re-opens the other. NEXT: fill the OT-chain lhu gap with an UNBOOSTED `p & m24` as the target does (needs a 2-set a3 that combine does not re-merge \u2014 combine.c:2309 decrements reg_n_sets on the merge \u2014 e.g. a second set through a different width/mode or a volatile-qualified temp), or move the contest margin by one ref elsewhere (an extra ob use in a block that does not touch the tag load)", "best_draft": ".run/P32/t5x/fable/func_800CF408.c", "binary": "md_MAIN_007", "source": "P32-T4b S83 Fable agent (499k tokens, 21 min, 135-variant sweep); report .run/P32/t5x/reports/func_800CF408.md", "residual": null, "passes_tried": null}
{"ts": "2026-09-05 12:06:54", "addr": "0x80032a74", "name": "func_80032A74", "reach": null, "klass": "WALL-CANDIDATE", "nins": 422, "status": "near", "closeness": 1, "where_stuck": "WALL candidate CONFIRMED in the real TU (S83): 422/422, sole residual idx 244 `lh v0,0x18(s1)` vs target `lhu` \u2014 extendhisi2 is a force_not_mem EXPAND (the orphan frame slot is minted only at an lh; \u00a7172 producer 3 caller-save area, reload1.c:1445), so lhu loses the 8 frame bytes; ~200 byte-probes + 100-variant retyping sweep (S79) + permuter_ils 8x150s null (S80). Citation current (\u00a7172, reload1.c:1445). Draft synced to the TU (typedefs stripped via cdecl.strip_provided_typedefs; D_80064D44/D_8006A970/func_8003F144/func_800316F8 spelled as the TU)", "best_draft": ".run/P32/t4/drafts/func_80032A74_tuclean.c", "binary": "main", "source": "P32-T4 S83 re-probe (R40): the S79w Opus draft was a CC1 FAIL in src/800_b_2.c only for PLUMBING (7 typedefs the TU provides via 800_shared.h + 4 decl spellings); stripped/synced copy re-run in the REAL TU: DIFF 1 (idx 244 lh vs lhu) \u2014 the recorded residual, confirmed in TU context", "residual": null, "passes_tried": null}
{"ts": "2026-09-06 11:41:02", "addr": "0x80032a74", "name": "func_80032A74", "reach": null, "klass": "WALL-PROVED", "nins": 422, "status": "near", "closeness": 1, "where_stuck": "T4b HAND PASS S84 (2026-09-06, Fable Max): PROVED at 1 by producer census. Residual = ONE reload-time slot at sp+0x48 (the u16 lhu draft is 422/422 with DIFF 22 = frame rows only; the s16 lh draft is DIFF 1 at idx 244 with the frame exact). The four post-parameter slot producers (reload1.c:658 ghost alter_reg / caller-save.c:249 area / reload1.c:879 invalid-equiv address / reload1.c:3499 spill_stack_slot) each refuted on the bytes: the site loads lhu and the function has no lb and no double load (combine newi2pat ghosts re-derive a narrow load); no register-only insn shares a block with a call (no sched.c:4962 staleness, so no save area without sw/lw); no unallocated single-block equiv pseudo; $t0 holds no pseudo (else $t1 would be the spill reg) and LO mult results retry into GR_REGS. NEW mechanism measured: optimize_reg_copy_2 ghosts (tmp = x; tmp op= c; x = tmp) are minted AFTER regclass -> GR_REGS, allocated, vars=0 (P14). 18 isolated reproducers, 0 draft variants; cookbook \u00a7501-M; notes .run/P32/t4c/func_80032A74/NOTES.md", "best_draft": ".run/P32/t4/drafts/func_80032A74_tuclean.c", "binary": "main", "source": null, "residual": null, "passes_tried": null}
{"ts": "2026-09-06 12:27:56", "addr": "0x80039308", "name": "func_80039308", "reach": null, "klass": "FRAME+SCHED", "nins": 518, "status": "near", "closeness": 4, "where_stuck": "T4b HAND PASS S84 (2026-09-06): PLATEAU at 4. Rows 412/415: Fable Y4 (direct *(s16*)(p+6)=arg1) is register-exact (lhu/sh $s7 = the spilled HImode parameter reloaded through the spill register) and natural; the residual is the frame: target [arg1 @0][8-byte no-traffic slot @8][cnt @0x10]. Producer census (\u00a7501-M/\u00a7501-O): cnt slot = spill_stack_slot[23] (cnt evicted from $s7, retry fails), so the phantom is an INITIAL-LOOP slot with no traffic \u2014 caller-save area dead (leaf), LO eviction lands after cnt (GR spilled first; products alternate to GR_REGS, C3), no unallocated single-block equiv pseudo ($t0 free at the k2 site), expand-time locals precede (Y1/Y3/Y4), all 13 lh single-use + no lb (no combine ghost). Rows 49/50: both preheader insns are move_movables hoists in body order (vol = b2*0x100 in the body); X2 measured 495 \u2014 a hoisted vbase needs \u00a7501-E steering to $s2 without the pin. Notes .run/P32/t4c/func_80039308/NOTES.md", "best_draft": ".run/P32/t5x/fable/func_80039308.c", "binary": "main", "source": null, "residual": null, "passes_tried": null}
+1 -1
View File
@@ -7,6 +7,6 @@
| # | addr | reach | class | nins | status | closeness | where it stuck | best draft |
|--:|------|------:|-------|-----:|--------|----------:|----------------|------------|
| 1 | func_80032A74 | None | WALL-PROVED | 422 | near | 1 | T4b HAND PASS S84 (2026-09-06, Fable Max): PROVED at 1 by producer census. Residual = ONE reload-time slot at sp+0x48 (the u16 lhu draft is 422/422 with DIFF 22 = frame rows only; the s16 lh draft is DIFF 1 at idx 244 with the frame exact). The four post-parameter slot producers (reload1.c:658 ghost alter_reg / caller-save.c:249 area / reload1.c:879 invalid-equiv address / reload1.c:3499 spill_stack_slot) each refuted on the bytes: the site loads lhu and the function has no lb and no double load (combine newi2pat ghosts re-derive a narrow load); no register-only insn shares a block with a call (no sched.c:4962 staleness, so no save area without sw/lw); no unallocated single-block equiv pseudo; $t0 holds no pseudo (else $t1 would be the spill reg) and LO mult results retry into GR_REGS. NEW mechanism measured: optimize_reg_copy_2 ghosts (tmp = x; tmp op= c; x = tmp) are minted AFTER regclass -> GR_REGS, allocated, vars=0 (P14). 18 isolated reproducers, 0 draft variants; cookbook §501-M; notes .run/P32/t4c/func_80032A74/NOTES.md | `.run/P32/t4/drafts/func_80032A74_tuclean.c` |
| 2 | func_80039308 | None | FRAME+SCHED | 518 | near | 4 | S83 Fable: 17 -> 4 in the real TU. Closed the 11-row alias block (natural spelling; tail via a pointer so the li follows the addu in RTL) and rows 390/391 (p = r + a dead reset). Residual 4 = two causes: rows 49/50 the hoisted constant 2 vs the pinned vbase preheader order (move_movables splices after source preheader code); rows 412/415 a PHANTOM 8-byte frame slot with no traffic at sp+8 between the arg1 HImode spill (sp+0) and cnt (sp+0x10) — `lhu $s7` is reload's spill register; storing arg1 directly reproduces sh $a1/lhu $s7 but not the slot (frame 0x38 vs 0x40). NEXT: induce the phantom slot — a hard-reg spill_stack_slot (reload1.c spill_hard_reg on LO or $s7 during retry_global_alloc), cf. §501-E (pins forbid regs at retry) and the func_80032A74 ghost-pseudo finding (a stranded combine temp -> alter_reg 8-byte slot in regno order) | `.run/P32/t5x/fable/func_80039308.c` |
| 2 | func_80039308 | None | FRAME+SCHED | 518 | near | 4 | T4b HAND PASS S84 (2026-09-06): PLATEAU at 4. Rows 412/415: Fable Y4 (direct *(s16*)(p+6)=arg1) is register-exact (lhu/sh $s7 = the spilled HImode parameter reloaded through the spill register) and natural; the residual is the frame: target [arg1 @0][8-byte no-traffic slot @8][cnt @0x10]. Producer census (§501-M/§501-O): cnt slot = spill_stack_slot[23] (cnt evicted from $s7, retry fails), so the phantom is an INITIAL-LOOP slot with no traffic — caller-save area dead (leaf), LO eviction lands after cnt (GR spilled first; products alternate to GR_REGS, C3), no unallocated single-block equiv pseudo ($t0 free at the k2 site), expand-time locals precede (Y1/Y3/Y4), all 13 lh single-use + no lb (no combine ghost). Rows 49/50: both preheader insns are move_movables hoists in body order (vol = b2*0x100 in the body); X2 measured 495 — a hoisted vbase needs §501-E steering to $s2 without the pin. Notes .run/P32/t4c/func_80039308/NOTES.md | `.run/P32/t5x/fable/func_80039308.c` |
| 3 | func_80185810 | None | SCHED | 489 | near | 13 | S83 Fable: 35 -> 13 at exact length; 3 of 4 windows closed (P_TAG bitfield OT link + integer add for the addu operand order; sched1 flush_pending_lists at the 33rd memory op explains the load order -> HI temps; hard-reg destinations are not birthing-boosted -> pins uu $4 / mode $5 / ot16 $6 give the LUID order; shf pin $3). Residual ONE cause idx 363-380: `cl &= 0xFFFF` is an unboosted 2nd set — the fence after p[7]/= is needed (else its two reads float to the block head, 43/51) yet it blocks sched2 fillers crossing into the tpage/code window. NEXT: a spelling in which cl is single-set (its high half cleared at birth: cl = *(u16*)... or the shift form) so no fence is needed, or the two cl reads consume a fresh single-set copy that combine cannot fold (nonzero_bits defeats a plain andi copy; try a subreg/HI-mode temp) | `.run/P32/t5x/fable/func_80185810.c` |
| 4 | func_80062144 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | |
+22
View File
@@ -37454,3 +37454,25 @@ position and flips the m24/colour `$t1/$t0` order. **Law:** when a same-family s
constants BEFORE touching a dial on the draft; the residual class name (§501-H) is the family's signature, not a lever list. The
target's `vars= 8` here is a combine-minted ghost (§501-M species, `ghost_census.py`: `ST_REGS or none` → SLOT) reproduced by the
port for free. Notes and every variant: `.run/P32/t4c/func_800CF408/`.
**§501-O — A PHANTOM SLOT BETWEEN A PARAMETER'S SPILL AND AN EVICTED PSEUDO'S SLOT: the census for a LEAF, and what it leaves
open (P32 T4b hand pass, S84 2026-09-06; `main:func_80039308` 518 ins, PLATEAU at 4).** Target frame `[s16 arg1 spill @0x0][8 bytes,
no traffic @0x8][cnt @0x10]`; the natural spelling (`*(s16 *)(p + 6) = arg1`, Fable's Y4) is register-exact — the HImode parameter
pseudo is spilled by global (`sh $a1,0($sp)` at entry, the head promotions keep reading `$a1` because reload's `find_equiv_reg` still
finds the value there, and the late use reloads `lhu $s7` = the spill register) — and lands `[arg1 @0][cnt @8]`. Read from `.greg`:
`cnt` is global-allocated to `$s7`, `order_regs_for_reload` picks `$s7` as the GR spill register (the least-used GPR in a function that
uses all 24), `spill_hard_reg` evicts it (its retry fails), and `alter_reg(cnt, 23)` mints `spill_stack_slot[23]` AFTER the initial
`alter_reg` loop. So the phantom must be an INITIAL-LOOP slot (any regno above the parameter's) with no traffic, or a main-loop slot
before the first spill. Refuted here, each on a dump fact: caller-save area (leaf: every `reg_n_calls_crossed` is 0); a LO-evicted
product's `spill_stack_slot[65]` (GR_REGS is spilled before LO_REG, so it would follow cnt's slot — and a product's alternate class is
`GR_REGS`: two overlapping products allocate to `$a1`/`$v1`, C3); reload1.c:879 (needs an unallocated single-block equivalence pseudo;
local-alloc allocates every short temp — `$t0` is free at the `k2` site because s18 dies one insn earlier); expand-time locals (they
precede every reload slot: Y1/Y3/Y4 measured the parameter at 0x10/0x8); global's local-alloc kick-out (its victim's traffic shows
unless def/use are adjacent through `$s7`, and the only such pairs are the six LO-class `mflo $s7` products); a combine ghost (all
thirteen `lh` are single-use — `bne/mult/sll/addiu/slti` consumers —, no `lb`, and a HImode `pan` would leave real `sll/sra` in the
arms the target does not have). **What this row teaches:** (1) `tools/ghost_census.py` + the `.greg` "Spilling reg N / now on stack"
lines give the slot ORDER for free — read them before any frame probe; (2) the six `mflo $s7 / op $s7` pairs are byte-identical whether
the product is LO-homed with an input reload or slot-homed with a deleted output reload (§501-M's inheritance species), so a phantom
whose traffic-free pseudo is a product cannot be excluded by the bytes alone — only by allocation (alternate class `GR_REGS` always
saves a product); (3) rows 49/50 are two `move_movables` hoists in BODY order — the original computed `vol = b2 * 0x100` in the loop;
steering the hoisted invariant into `$s2` without the `$18` pin (X2 = 495) is the open lever (§501-E launders).
+121 -140
View File
@@ -99,7 +99,7 @@ Scale estimate: 3–5 sessions.
`func_80011380` → `.run/m3/opus/func_80011380.c`; `func_801834A4` → `.run/S71_gate14/ov_SC03_105*/`),
`exclude_audit --write`, `backlog.py render`; a T3 idiom naming a wall's mechanism re-opens that row
(bounded: one attempt, permuter first). Wall table into this file; cookbook §496+; decision log; accelerators.
- [~] **T4b — crack and bank the final 15 (ADDED 2026-09-05 by Drew's directive; supersedes the kill gate: "anything that isn't the original hand-written asm or the PsyQ libs needs to be cracked and banked before we finish")** — **FIRST PASS COMPLETE 2026-09-05 (S83): 11 of 15 BANKED byte-identical, 4 carried to the NEXT session's HAND pass (Drew: no second agent round; hand-crack the remaining ones).** Hand pass first (22 spellings, 0 banks, every blocker refined to a mechanism in `.run/P32/t4b/<fn>/NOTES.md`), then one Fable agent per row (permission, not requirement — Drew), resumed 3-at-a-time through three usage-limit outages. Banked (each: coordinator `rtu_match` in the CURRENT real TU → `gate_main` / `bank.sh` byte-identical → one commit; pins dropped by `exclude_audit --write`; mechanism in cookbook §501–§501-L): `main:func_800391D4` `commit:3956` · `main:func_80039DEC` `commit:3959` · `md_MAIN_009:func_800CD674` `commit:3964` · `ov_SC06_022:func_8017DF28` `commit:3966` · `main:func_80020DA4` `commit:3969` · `ov_SC03_105:func_801834A4` `commit:3972` · `md_MAIN_003:func_800CF3E8` `commit:3976` · `md_MAIN_009:func_800CD92C` `commit:3979` · `ov_SC07_002:func_8017DC80` `commit:3983` · `main:func_80011380` `commit:3990` (the §474 "PROVED" wall) · `md_MAIN_007:func_800CF6D0` `commit:3992`. Ten of the eleven were T4 "walls" or long-standing NEARs. **HAND PASS S84 (2026-09-06, Fable Max, no agents): row (a) `main:func_80032A74` → PROVED at 1 (§501-M producer census: the 0x48 slot can only be a combine-minted ghost, which needs an `lh`/`lb`; the pin stays with its final verdict; ledger + `tools/ghost_census.py` + `cc1_dumps.sh` repair; row (b) `md_MAIN_007:func_800CF408` → **BANKED byte-identical `commit:4001`** (the banked sibling func_800CD92C's spelling ported with a u32 array alias of the OT symbol, §501-N; zero pins/asm); rows (c)(d) next).** Carried (4, all exact length, in `docs/backlog.md` with next levers): `main:func_80032A74` 1 (the last pin; ghost pseudo — near-proved) · `md_MAIN_007:func_800CF408` 3 · `main:func_80039308` 4 · `ov_SC03_105:func_80185810` 13. Close: fleet R22 **218 passed / 0 failed, exits 0/0/0** (23:33–23:36 MDT, `.run/P32/t4b/r22_full.log`); `make report`: instr 13,486,890 / 13,488,497 = 100.0% · distinct 5,814,982 / 5,816,589 = 100.0% (90,982 / 90,984 unique) · fn-count 363,210 / 363,214 = 100.00% · **INCLUDE_ASM 4**; main REAL 787 · LINKED 1,256 · VERBATIM 3 · stubs 2 · 2,089 / 2,091 = 99.90% · `143dbb89…`; census `.run/P32/frontier_t4b_close.json` 4 stubs / 1,607 ins; decision-log P32 S83 T4b (R31); accelerators (10)–(11); tools-health OK (`.run/P32/t4b/tools_health.log`).
- [~] **T4b — crack and bank the final 15 (ADDED 2026-09-05 by Drew's directive; supersedes the kill gate: "anything that isn't the original hand-written asm or the PsyQ libs needs to be cracked and banked before we finish")** — **FIRST PASS COMPLETE 2026-09-05 (S83): 11 of 15 BANKED byte-identical, 4 carried to the NEXT session's HAND pass (Drew: no second agent round; hand-crack the remaining ones).** Hand pass first (22 spellings, 0 banks, every blocker refined to a mechanism in `.run/P32/t4b/<fn>/NOTES.md`), then one Fable agent per row (permission, not requirement — Drew), resumed 3-at-a-time through three usage-limit outages. Banked (each: coordinator `rtu_match` in the CURRENT real TU → `gate_main` / `bank.sh` byte-identical → one commit; pins dropped by `exclude_audit --write`; mechanism in cookbook §501–§501-L): `main:func_800391D4` `commit:3956` · `main:func_80039DEC` `commit:3959` · `md_MAIN_009:func_800CD674` `commit:3964` · `ov_SC06_022:func_8017DF28` `commit:3966` · `main:func_80020DA4` `commit:3969` · `ov_SC03_105:func_801834A4` `commit:3972` · `md_MAIN_003:func_800CF3E8` `commit:3976` · `md_MAIN_009:func_800CD92C` `commit:3979` · `ov_SC07_002:func_8017DC80` `commit:3983` · `main:func_80011380` `commit:3990` (the §474 "PROVED" wall) · `md_MAIN_007:func_800CF6D0` `commit:3992`. Ten of the eleven were T4 "walls" or long-standing NEARs. **HAND PASS S84 (2026-09-06, Fable Max, no agents): row (a) `main:func_80032A74` → PROVED at 1 (§501-M producer census: the 0x48 slot can only be a combine-minted ghost, which needs an `lh`/`lb`; the pin stays with its final verdict; ledger + `tools/ghost_census.py` + `cc1_dumps.sh` repair; row (b) `md_MAIN_007:func_800CF408` → **BANKED byte-identical `commit:4001`** (the banked sibling func_800CD92C's spelling ported with a u32 array alias of the OT symbol, §501-N; zero pins/asm); row (c) `main:func_80039308` → PLATEAU at 4 (S84 verdict, §501-O: the phantom slot's producer census refutes every route; Y4 is register-exact); row (d) NEXT).** Carried (4, all exact length, in `docs/backlog.md` with next levers): `main:func_80032A74` 1 (the last pin; ghost pseudo — near-proved) · `md_MAIN_007:func_800CF408` 3 · `main:func_80039308` 4 · `ov_SC03_105:func_80185810` 13. Close: fleet R22 **218 passed / 0 failed, exits 0/0/0** (23:33–23:36 MDT, `.run/P32/t4b/r22_full.log`); `make report`: instr 13,486,890 / 13,488,497 = 100.0% · distinct 5,814,982 / 5,816,589 = 100.0% (90,982 / 90,984 unique) · fn-count 363,210 / 363,214 = 100.00% · **INCLUDE_ASM 4**; main REAL 787 · LINKED 1,256 · VERBATIM 3 · stubs 2 · 2,089 / 2,091 = 99.90% · `143dbb89…`; census `.run/P32/frontier_t4b_close.json` 4 stubs / 1,607 ins; decision-log P32 S83 T4b (R31); accelerators (10)–(11); tools-health OK (`.run/P32/t4b/tools_health.log`).
- [ ] **T5 — PhaseEnd** (Max, Tier 1 — prompt R27): P7 checkbox walk; milestone demo (R22 fleet N/N, tools-health,
`verbatim_check --strict`, final census, wall ledger, parked-5 dispositions via `make audit-disc`,
`make report` all three metrics + main `143dbb89…` with/without SDK dirs, corrected denominators); **WAIT
@@ -135,6 +135,7 @@ cookbook before the next drafting step (R16/R30) · no `Co-Authored-By` trailer
needed for T0–T2b; if T2d needs it: `tools/ghidra_mcp_start.sh` → pause → Drew runs `/mcp` (R29) → G2 ping.
## Log
- 2026-09-06 (S84, continued) — **T4b hand pass, row (c) `main:func_80039308` → PLATEAU at 4 (verdict).** Producer census for the target's phantom slot `[arg1 @0][8 @8][cnt @0x10]` (§501-O): cnt's slot is `spill_stack_slot[23]` (cnt evicted from `$s7`, `.greg` "Register 95 now on stack"), so the phantom is an initial-loop slot with no traffic; every producer refuted on dump facts (leaf → no save area; LO spilled after GR; products alternate to GR_REGS — C3 measured `mflo $a1/$v1`; no unallocated single-block equiv pseudo; expand-time locals precede; all 13 `lh` single-use, no `lb`). Rows 49/50 = two `move_movables` hoists in body order (open: steer the hoisted `b2 * 0x100` into `$s2` without the pin). Ledger row updated (closeness 4, FRAME+SCHED), NOTES `.run/P32/t4c/func_80039308/NOTES.md`, probe `c3_twoprod.c`. **Row (d) `ov_SC03_105:func_80185810` (13) read (report + rtu DIFF 13 re-verified) — NOT started; per §501-N its step 0 is a banked-sibling search on its symbol set (`D_800A5E60`, `D_801BC9B4/BC`, `D_801BA6B0`, `D_800AF630`, `D_800A6610`).** Session paused here at Drew's request (87% context).
- 2026-09-06 (S84, continued) — **T4b hand pass, row (b) `md_MAIN_007:func_800CF408` BANKED byte-identical (`commit:4001`: bank.sh — rtu MATCH 178/178 in the real TU, splice, `make build BINARY=md_MAIN_007 -j8` rc 0, sha `2ff702b6…` == `config/check.md_MAIN_007.sha`).** The Fable draft's 3-row prologue-weave residual (§501-L) was a shape symptom: the same-family banked sibling `md_MAIN_009:func_800CD92C` (§501-H) had matched with the plain libgpu addPrim shape; porting it with this function's constants matched first try (`b0d_sibport_alias.c`). The TU declares `extern u8 D_800AA60C[]`, which kills the sibling's `u32` ARRAY_REF (the form whose address `memory_address → force_reg` lets cse bind the OT base into `$t2`; every `u8` respelling emits the `$at` macro form ×8) — solved with the fleet's asm-label alias `extern u32 wD_800AA60C[] __asm__("D_800AA60C");` (1,438 banked files carry the pattern; a declaration, not an asm body). Measured and refuted on the way: the sibling's lever-7 trailing volatile asm 2-set dial (flips `$t1/$t0`), the struct-view and P_TAG-on-`u8` forms. Post-bank: `twin_rescan` 3 open / 0 newly free; `verbatim_check --strict` 5==5; backlog rendered 4 open (the row pruned). Harvest: cookbook **§501-N**, accelerators (13), NOTES `.run/P32/t4c/func_800CF408/NOTES.md` (7 variants). bank.sh's `Claude-Session` trailer now comes from `$CLAUDE_SESSION` (was S83's id hard-coded). NEXT = row (c) `main:func_80039308` (4).
- 2026-09-06 (S84, session 72d8b4b1, Max, Fable 5.1) — **T4b hand pass, row (a) `main:func_80032A74` CLOSED: PROVED at 1 (verdict, not a bank).** Preflight: tree clean, `verbatim_check --strict` 5==5, `make check-all` 218 passed / 0 failed rc 0 (`.run/P32/t4c/check_all_preflight.log`). Re-verified in the real TU (`rtu_match … --tu src/800_b_2.c --asm-subdir asm/nonmatchings/800_b_2`): the `s16 u18` draft DIFF 1 (idx 244 `lh` vs `lhu`, frame exact); the `u16 u18` TU-clean variant DIFF 22 = the 22 frame rows only (422/422 code). The residual is ONE reload-time slot at sp+0x48. Instead of a spelling sweep, enumerated every post-parameter stack-slot producer from the 2.7.2 source (reload1.c:658 ghost `alter_reg` · caller-save.c:249 area · reload1.c:879 invalid-equiv address · reload1.c:3499 `spill_stack_slot`) and refuted each on the bytes/dumps: combine's `newi2pat` ghosts re-derive a narrow load (`lh`/`lb`) and the site is `lhu` with no `lb`/double load; a save area without `sw/lw` needs sched.c:4962 staleness and no register-only insn shares a block with any of the 7 calls; unallocated single-block equiv pseudos cannot exist; `$t0` holds no pseudo (`order_regs_for_reload`) and LO mult results retry into `GR_REGS`. Found and measured a NEW ghost producer — `local-alloc.c optimize_reg_copy_2` on `tmp = x; tmp op= c; x = tmp;` (P13 refs 5, P14 refs 1) — which cannot slot because it is minted after regclass (class `GR_REGS`, no conflicts → allocated, vars=0). 18 isolated reproducers, 0 draft variants. Deliverables: cookbook **§501-M**, `tools/ghost_census.py` (new) + `tools/cc1_dumps.sh` (repaired: frame line + census, the under-counting `(use)` grep gone) + SETUP rows (R21), accelerators (12), backlog row (WALL-PROVED) + `tools/backlog.py` tie-break repair (kept the EARLIEST record at equal closeness — the S84 row never rendered), `config/wave_exclude.txt` annotated (`exclude_audit --assert-fresh` 1/1), notes `.run/P32/t4c/func_80032A74/NOTES.md`. NEXT = row (b) `md_MAIN_007:func_800CF408` (3).
- 2026-09-05 13:05–23:40 MDT (S83, continued) — **T4b first pass COMPLETE: 11 of 15 banked, 4 carried.** Fifteen Fable agents launched from `.run/P32/t5x/` (BRIEF + packs + the hand-pass NOTES); three usage-limit outages killed every run (resumed each time via SendMessage with context intact; "write deliverables early" saved one crack from a dead run); from the second outage on, resumed 3 at a time (Drew). Verdicts: 11 MATCH (each re-verified by the coordinator in the CURRENT real TU and banked byte-identical — main rows via `gate_main` slates, overlays/modules via `SPLIT=… DRAFT_DIR=.run/P32/t5x/fable bank.sh`), 4 NEAR at exact length (1 / 3 / 4 / 13) with pass-attributed residuals and next levers ledgered. Every crack came from READING a pass dump against the 2.7.2 source; cookbook §501–§501-L (12 new laws: cascades, cross-jump-after-alloc, dying-input vs birthing boost, hard-reg sets count, pins forbid retry regs, CSE-quantity split, three-passes-three-dials, constants as floaters, manufactured orphans, a proved tree wall is not an RTL wall, sched2's /s exemption, coupled dials); decision-log P32 S83 T4b; accelerators (10)–(11). Instrument defects: bank.sh (empty fn list → built the unchanged tree, exit 0; `_jr_` TU split; draft dir) hardened, and two premature "banked" ledger messages corrected in the next commit (memory: write the message from the tool's output). Pins 7 → 1. Fleet R22 218/218 at the close; `make report` fleet 100.0/100.0/100.00, 4 stubs. **Drew: no second agent round; hand-crack the remaining four next session.** NEXT = the hand pass on the four (see the 🛑 block), then T5.
@@ -151,150 +152,131 @@ cookbook before the next drafting step (R16/R30) · no `Co-Authored-By` trailer
- 2026-09-05 — **T1a DONE — `resident:func_800D128C` BANKED (243 ins, byte-identical 8e17e02f, R22 213/213).** The stored S71 closeness-0 draft was byte-correct all along; the whole task was three instrument defects the resident (the fleet's one `common.h`-only, `--pre`-sandwich binary) exposed in overlay-only assumptions: (1) `jr_isolate_all` dropped a file-local typedef whose name engine_types.h also defines (§496 — fixed: provided types derived from the TU's own includes); (2) `jtbl_carve` regenerated `JTBL_INTERLEAVE` without the `--pre hdr.rodata.o` clause → extract refused → the gate linked a stale script and booked the byte-correct draft as DIFF; `harvest_verify` ignored that extract's rc (§498 — both fixed, R49/R61); (3) `interleave_check` read a `--pre` line as n=0 (false DRIFT; fixed). R38 then found two more stored MATCH bodies for T1b/T1c (see their rows). Effort stayed Max.
- 2026-09-05 — **T0 DONE.** Baseline reads all green (`.run/P32/t0_baseline.log`): `verbatim_check --strict` 5 bodies == 5 rows; `exclude_audit --assert-fresh` 8 entries, 8 WALL, 0 stale; `frontier_classify` → 21 rows = the S80 census exactly; `make tools-health` OK (sigs fresh, corpus(+resident), cdecl, audit-binaries 213/213, report lint+dedup, cookbook-index, split_indicator 213 OK); `make check-all` 213 passed / 0 failed, rc 0. Harness task list #1–#11 built (R28). NEXT = T1a.
## 🛑 SESSION CHECKPOINT — T4b HAND PASS IN PROGRESS: row (a) PROVED at 1, row (b) BANKED, rows (c)(d) NEXT, then T5 (2026-09-06 ~13:30 MDT; written by session 72d8b4b1 "S84"; SUPERSEDES the 2026-09-05 23:45 block)
## 🛑 SESSION CHECKPOINT — T4b HAND PASS: (a) PROVED at 1 · (b) BANKED · (c) PLATEAU at 4 · (d) NEXT, then T4b close and T5 (2026-09-06 ~15:00 MDT; written by session 72d8b4b1 "S84" at Drew's pause request; SUPERSEDES the two earlier S84 blocks and the 2026-09-05 23:45 block)
### 0. How to use this block
You are a FRESH SESSION that has read `PROJECT_CONTEXT.md`, `phase-ends/DIGEST.md`, `PhaseEnd_Phase29/30/31.md` and this file, and
nothing else (CLAUDE.md protocol, R64 candidate). Replay this block verbatim into your chat, state phase / done / NEXT / effort,
list the rules from the digest, then WAIT for Drew. **NEXT is the HAND pass on rows (c) → (d) — Drew (2026-09-05 23:2x MDT):
"we will hand crack the remaining ones next session instead of using agents."** Non-obvious root-cause work: recommend
**effort: Max** (R7/R27 — prompt and wait for the `/effort`). No Agent tool, no Workflow. After the two (banked or honestly
ledgered), T5 = the PhaseEnd (Tier 1, Max, WAIT for gate 2).
list the rules from the digest, then WAIT for Drew. **NEXT is the HAND pass on row (d) `ov_SC03_105:func_80185810` (13) — Drew
(2026-09-05): "we will hand crack the remaining ones next session instead of using agents."** Non-obvious root-cause work: recommend
**effort: Max** (R7/R27 — prompt and wait for the `/effort`). No Agent tool, no Workflow. After (d) (banked or honestly ledgered):
the T4b close (§4 step 2), then T5 = the PhaseEnd (Tier 1, Max, WAIT for gate 2).
### 1. Where we are
**Phase 32 — the last 21 + the parked 5 (short, kill-gated) — extended by Drew's T4b directive: every function that is not original
hand-asm or a PsyQ object must be cracked and banked before the phase closes.** Gate 1 approved 2026-09-05; R44–R63 ratified then;
R64 candidate. Tasks: **T0 ✓ T1a ✓ T1b ✓ T1c ✓ T2a–c ✓ (T2d not needed) T3 ✓ T4 ✓ T4b first pass ✓ (11 of 15 banked)** ·
**T4b hand pass IN PROGRESS: row (a) `main:func_80032A74` CLOSED as PROVED at 1 (S84, a verdict); row (b)
`md_MAIN_007:func_800CF408` BANKED byte-identical `commit:4001` (S84 — md_MAIN_007 is now 100% C); rows (c)(d) open** · **T5 pending.** Harness tasks #1–#13 (#13 = T4b in_progress).
Fleet **218 binaries**. **S84 `src/` change: ONE bank (`src/md_MAIN_007/md_MAIN_007.c`, `commit:4001`, sha byte-identical by `make build`); no `config/` (except the `wave_exclude.txt` annotation) or carve-state change; a fleet R22 is still owed at the T4b close.** Last fleet R22:
`make clean && make extract-all && make check-all` → 217+main extracted, **218 passed / 0 failed, exits 0/0/0 at 2026-09-05 23:36 MDT**
(`.run/P32/t4b/r22_full.log`); S84 preflight `make check-all` → **218 passed / 0 failed, EXIT=0** (`.run/P32/t4c/check_all_preflight.log`).
`make report` (S83 close, still current): **instr 13,486,890 / 13,488,497 = 100.0% · distinct 5,814,982 / 5,816,589 = 100.0% (90,982 /
90,984 unique fns) · fn-count 363,210 / 363,214 = 100.00% · INCLUDE_ASM 4**; main REAL 787 · LINKED 1,256 · VERBATIM 3 · stubs 2 ·
byte-identical 2,089 / 2,091 = 99.90% · sha `143dbb89…`. `verbatim_check --strict` 5 == 5 (S84). `config/wave_exclude.txt`: **1 entry**
(`main:func_80032A74`, now carrying its S84 PROVED verdict), `exclude_audit --assert-fresh` 1/1 OK (S84). Census
`.run/P32/frontier_t4b_close.json`: **4 stubs / 1,607 ins** at the S83 close — now **3 stubs / 1,429 ins** open after (b) (regenerate at the T4b close). `make tools-health` → OK at the S83 close (`.run/P32/t4b/tools_health.log`);
`cookbook_index.py --check` OK (S84). Non-ghidra tree clean at HEAD after the S84 commit; the `ghidra/` churn is R23 restart-noise —
never stage it. Claude commits, Drew pushes (R6; ~100 unpushed). 100% C: resident, md_SC03_053/054/056, md_MAIN_003, md_MAIN_009,
**T4b hand pass (S84): (a) `main:func_80032A74` PROVED at 1 (verdict) · (b) `md_MAIN_007:func_800CF408` BANKED byte-identical
`commit:4001` (md_MAIN_007 is now 100% C) · (c) `main:func_80039308` PLATEAU at 4 (verdict) · (d) `ov_SC03_105:func_80185810` 13,
NOT started** · **T5 pending.** Harness tasks #1–#13 (#13 = T4b in_progress).
Fleet **218 binaries**. **S84 `src/` change: ONE bank (`src/md_MAIN_007/md_MAIN_007.c`, `commit:4001`, sha byte-identical by `make build
BINARY=md_MAIN_007 -j8` rc 0); no `config/` (except the `wave_exclude.txt` annotation) or carve-state change; a fleet R22 is still owed
at the T4b close.** Last fleet R22: `make clean && make extract-all && make check-all` → 217+main extracted, **218 passed / 0 failed,
exits 0/0/0 at 2026-09-05 23:36 MDT** (`.run/P32/t4b/r22_full.log`); S84 preflight `make check-all` → **218 passed / 0 failed, EXIT=0**
(`.run/P32/t4c/check_all_preflight.log`, before the bank). `make report` (S83 close, still current for the fleet numbers): **instr
13,486,890 / 13,488,497 = 100.0% · distinct 5,814,982 / 5,816,589 = 100.0% (90,982 / 90,984 unique fns) · fn-count 363,210 / 363,214 =
100.00% · INCLUDE_ASM 4** → now **3 stubs / 1,429 ins** open after (b) (regenerate at the T4b close: `frontier_classify --json
.run/P32/frontier_t4b_final.json`). Main: REAL 787 · LINKED 1,256 · VERBATIM 3 · stubs 2 · byte-identical 2,089 / 2,091 = 99.90% · sha
`143dbb89…`. `verbatim_check --strict` 5 == 5 (S84, after the bank). `config/wave_exclude.txt`: **1 entry** (`main:func_80032A74`, with
its S84 PROVED verdict), `exclude_audit --assert-fresh` 1/1 OK. `docs/backlog.md`: **4 open** (`func_80032A74` WALL-PROVED 1 ·
`func_80039308` FRAME+SCHED 4 · `func_80185810` SCHED 13 · `func_80062144` legacy failed row). `make tools-health` → OK at the S83 close;
`cookbook_index.py --check` OK (S84). Non-ghidra tree clean at HEAD after the S84 commits; the `ghidra/` churn is R23 restart-noise —
never stage it. Claude commits, Drew pushes (R6; ~105 unpushed). 100% C: resident, md_MAIN_007, md_MAIN_009, md_MAIN_003, md_SC03_053/054/056,
ov_SC06_022, ov_SC07_002.
### 2. What S84 did (session 72d8b4b1, 2026-09-06, Max, Fable 5.1, no agents)
Row (a) (verdict) and row (b) (BANKED). **Row (b):** the banked sibling `func_800CD92C`'s spelling ported with this row's constants =
MATCH first try; the TU's `u8` declaration of the OT symbol needed the fleet's asm-label alias `extern u32 wD_800AA60C[]
__asm__("D_800AA60C");` (§501-N, accelerators (13)); bank.sh (`.run/P32/t3s3/bank.sh`) did the rtu → splice → build → sha → commit chain.
**Row (a):** Re-verified both best drafts in the real TU; then, instead of a spelling sweep, read every post-parameter stack-slot
producer out of `tools/reference/gcc-2.7.2` and refuted each on the bytes/dumps — the producer census is cookbook **§501-M** and
`.run/P32/t4c/func_80032A74/NOTES.md`. Found a NEW ghost producer (`local-alloc.c optimize_reg_copy_2`) and measured why it cannot
slot (post-regclass → allocatable). Tooling: **`tools/ghost_census.py`** (new; ghosts with stale refs and their class), **`tools/cc1_dumps.sh`
repaired** (prints the `.frame` line + ins count + spill lines + the census; its `(use)` grep under-counted), **`tools/backlog.py`
tie-break repaired** (kept the EARLIEST record at equal closeness — the S84 PROVED row never rendered), SETUP rows (R21), accelerators
(12), backlog row `WALL-PROVED`, the pin annotated. 18 isolated reproducers (`.run/P32/t4c/func_80032A74/p1..p18.c`), 0 draft
variants. **Verdict for (a): PROVED at 1** — the honest final disposition the plan allows for this row (P9; nothing redefined).
### 2. What S84 did (session 72d8b4b1, 2026-09-06, Max, Fable 5.1, no agents; commits `commit:4000` `commit:4001` `commit:4002` + the close commit)
* **(a) PROVED at 1** by a PRODUCER CENSUS from the compiler source instead of a spelling sweep (cookbook **§501-M**, accelerators (12)):
the 0x48 slot can only be a combine-minted ghost (`newi2pat` split, combine.c:1887/1963 → reload1.c:658), which re-derives a signed
narrow load; the site is `lhu`, no `lb`, no double load. Caller-save area / reload1.c:879 / `spill_stack_slot` refuted on the bytes.
Found and measured a NEW ghost producer (`local-alloc.c optimize_reg_copy_2`, P13/P14) that cannot slot (post-regclass → allocated).
* **(b) BANKED** by porting the banked sibling `md_MAIN_009:func_800CD92C`'s spelling with this row's constants (cookbook **§501-N**,
accelerators (13)) — the TU's `extern u8 D_800AA60C[]` needed the fleet's asm-label alias `extern u32 wD_800AA60C[]
__asm__("D_800AA60C");` (1,438 banked files carry the pattern; a declaration, not an asm body). MATCH first try; `bank.sh` chain.
* **(c) PLATEAU at 4** with the phantom-slot producer census for a leaf (cookbook **§501-O**) and the 49/50 mechanism (two
`move_movables` hoists in body order).
* **Tools:** `tools/ghost_census.py` (new: ghosts in a `.lreg` dump with class → SLOT / allocatable); `tools/cc1_dumps.sh` repaired
(frame line + ins + spill lines + census; the under-counting `(use)` grep is gone); `tools/backlog.py` tie-break repaired (kept the
EARLIEST record at equal closeness → a re-verdict never rendered); `.run/P32/t3s3/bank.sh` session trailer from `$CLAUDE_SESSION`;
SETUP rows (R21) for all three; `.run/P32/t4c/dump.sh` (private dump + census under `.run/P32/t4c/dumps_<tag>/`).
### 3. THE REMAINING ROWS — the hand-crack briefs (all at EXACT length, all rtu-clean; (c)(d) unchanged from the 23:45 block)
Verify any draft with `rtu_match` in the REAL TU (main: `--tu src/<sub>.c --asm-subdir asm/nonmatchings/<sub>`; overlays/modules:
`--split <tu-basename> --source <binary>`); bank via `gate_main` (main) or `SPLIT=<tu-basename> DRAFT_DIR=<dir> .run/P32/t3s3/bank.sh
<binary> <tu> <asmdir> <arm> "<title>" <fn>` (it refuses on red). RTL dumps: `tools/cc1_dumps.sh <self-contained draft> <tag>` →
`.run/c294/dumps_<tag>/<tag>.i.{rtl,jump,cse,loop,flow,combine,sched,lreg,greg}` + the `.frame`/ins/spill/ghost summary (the draft
must carry its own typedefs/externs; add `-O0` by editing the script's cc1 line for boot). Each row's Fable report
(`.run/P32/t5x/reports/<fn>.md`) carries the dump citations and the measured-inert list — READ IT FIRST, do not repeat its sweeps.
**Do the producer census BEFORE any spelling probe (§501-M, accelerators (12)): name the pass and the dump line that owns the residual — and
BEFORE that, `grep -l` for a banked same-family sibling and port its spelling with the row's constants (§501-N, accelerators (13)).**
### 3. ROW (d) — the brief for the next session (all facts re-verified S84 unless marked S83)
**`ov_SC03_105:func_80185810` — 489 ins, closeness 13, exact length, every register allocation matches.** TU
`src/ov_SC03_105/ov_SC03_105_jr_80181C84.c`, sub `ov_SC03_105_jr_80181C84`, asm `asm/ov_SC03_105/nonmatchings/ov_SC03_105_jr_80181C84/`.
Draft `.run/P32/t5x/fable/func_80185810.c` (= Fable work `v7.c`) — **rtu DIFF 13 in the real TU (S84):** rows 363–380, the tpage/code
RMW window: mine `sh v1,22(s0); lbu v1,7(s0); srl; or; sb; andi a3,0xffff; li v1,2; subu; … sll a2,14; … sllv a0; lui/addiu v1 (D_800A6610);
addu s1,a2,v1` vs target `srl; sll $a2,14; sh; lbu; andi $a3,0xFFFF; or; sb; li; subu; lui/addiu $v0; addu $s1,$a2,$v0; sllv` — i.e. the
target interleaves `sll $a2,14`, `andi $a3,0xFFFF`, `li/subu` INTO the tpage/code window and puts `la D_800A6610`/`addu $s1` before the
`sllv`. Report `.run/P32/t5x/reports/func_80185810.md` (READ IT FIRST); harness `.run/P32/t5x/work/func_80185810/` (`dump.sh`, `exp/run.py`
named-edit A/B, `exp/sweep.py` = the 3,360-variant region-2 sweep — do NOT repeat, `exp/rtlsum.py`). Three windows were closed by Fable
with pins (`register u32 uu __asm__("$4"), mode ("$5"), ot16 ("$6")`, `shf ("$3")`) and HI temps (`t20/t22` with `tp = D_801BA6B0` loaded
between the loads and the stores — sched1's `flush_pending_lists` at the 33rd memory op) and the libgpu `P_TAG` bitfield OT link.
**The residual's ONE cause (S83, read from the dumps):** `cl &= 0xFFFF` is an unboosted 2nd set whose anti-dependences hold the w-chain's
two `cl` reads; the zero-byte `__asm__ volatile("")` fence after `p[7] |= …` is needed (without it the reads float to the block head and
take `$a0/$a1`: 43/51) yet it forbids sched2's fillers from crossing into the tpage/code window. A fresh single-set `clx` is boosted but
combine folds the `andi` via `nonzero_bits(cl)` into any same-block consumer (59); 2-set `clx` unboosted (49/39/42); an arm-duplicated store
does not cross-jump (490 ins); a launder asm is a real move for block_alloc. **Next levers, in order:** (0) **§501-N first — search for a
BANKED sibling with this shape and PORT its spelling before touching any dial:** `grep -ln 'D_800A5E60' src/*.c src/*/*.c` (the prim-buffer
cursor also used by (b)'s family), `grep -ln 'D_801BC9B4\|D_801BA6B0\|D_800A6610' src/ov_SC03_*/*.c`, and the §501-I banked exemplar
`ov_SC07_002:func_8017DC80` (DR_TPAGE shared-scratch idiom) + `src/800.c:3826` (the same idiom banked in main); compare their tpage/code
window spelling (`tp = 1; q[3] = tp; … tp = tpage; *(u32 *)(q+4) = tp;`) with the draft's `cl` chain. (1) If no sibling: make `cl`
single-set with its high half cleared at birth (`cl = *(u16 *)…` or a shift form) so no fence is needed, or give the two reads a fresh copy
combine cannot fold (a HImode/subreg temp defeats `nonzero_bits`) — §501-L's "different-mode temp" — and read the `-dS` trace at the
window (T-14/T-20 in `dumps_NOFENCE`) before each probe; ≤ ~10 probes, then the verdict. Pins are dials to be removed at the end if a
sibling shows the natural form (§501-E: a pin forbids its register to every retried allocno).
**(a) `main:func_80032A74` — CLOSED: PROVED at 1 (S84).** Best drafts: `.run/P32/t4/drafts/func_80032A74_tuclean.c` (`s16 u18`, rtu
DIFF 1 = idx 244 `lh` vs `lhu`, frame exact) and `.run/P32/t4c/func_80032A74/lhu_tuclean.c` (`u16 u18`, 422/422 code, DIFF 22 = the
frame rows: vars 56 vs 64). Proof: the residual is one reload-time slot at sp+0x48; its only zero-code producer is a combine-minted
ghost (`newi2pat` split, combine.c:1887/1963 → reload1.c:658), which re-derives a narrow signed load; the site is `lhu`, the function
has no `lb` and no double load, all nine `lh` are single-use. Caller-save area (caller-save.c:249) needs sched.c:4962 staleness and no
register-only insn shares a block with any call; reload1.c:879 needs an unallocated single-block equiv pseudo; `spill_stack_slot`
needs a pseudo in `$t0` (impossible: `lw $t0` param reloads) or a failed LO retry (mult results have alternate `GR_REGS`).
`optimize_reg_copy_2` ghosts are post-regclass and allocatable (P14 vars=0). Do NOT reopen without a new producer.
**(b) `md_MAIN_007:func_800CF408` — CLOSED: BANKED byte-identical `commit:4001` (S84).** Draft `.run/P32/t4c/bank/func_800CF408.c` = the sibling
port (`b0d_sibport_alias.c`); notes `.run/P32/t4c/func_800CF408/NOTES.md`. The brief below is kept for the record only.
**(b, superseded) `md_MAIN_007:func_800CF408` — 178 ins, closeness 3, zero pins.** TU `src/md_MAIN_007/md_MAIN_007.c`, sub `md_MAIN_007`, asm
`asm/md_MAIN_007/nonmatchings/md_MAIN_007/`. Draft `.run/P32/t5x/fable/func_800CF408.c`; report `.run/P32/t5x/reports/func_800CF408.md`;
probes/dumps `.run/P32/t5x/work/func_800CF408/`. **Residual idx 10–12** (`ori $s5,0x96` below `sw $s0` / `li $s0,5`): §501-H's floater
mechanism — the unboosted tag load lingers up block 1's store stream, is `blocking` one cycle behind the tpage `sw` at T-139, and the
empty cycle consumes the highest-LUID floater — COUPLED to the `$t2/$t3` `qty_compare` contest (ob vs 0xFF000000: 2389 vs 2400, one
ref apart): mhi's `li` UID above the index `sll` cures the floater but moves mhi's birth one slot later and flips the contest (18);
`ob` after the index fixes the contest but opens a bubble in the OT-chain `lhu` gap that eats the same floater (13). The target fills
that gap with `and $a3,$v0,$t1` = an UNBOOSTED `p & m24`; a 2-set `a3` is re-merged by combine (`reg_n_sets--`, combine.c:2309 → 36),
an asm launder there is a sched2 delay-slot phantom nop (179 ins). **Next lever (§501-L):** a filler for that gap that combine cannot
re-merge and that changes neither count — a different-mode temp (`u16`/HImode view of `p & m24`), a `volatile` temp, or moving the
contest margin by one `ob` reference in a block that does not touch the tag load. 135-variant sweep floor 3 (×24) — do not repeat.
**(c) `main:func_80039308` — 518 ins, closeness 4.** TU `src/800_c.c` (which now spells `extern s32 D_80073140[][1]`), sub `800_c`,
asm `asm/nonmatchings/800_c/`. Draft `.run/P32/t5x/fable/func_80039308.c`; report `.run/P32/t5x/reports/func_80039308.md`. **Residual =
two causes:** rows 49/50 — the hoisted constant `2` vs the pinned `vbase` preheader order (move_movables splices after source
preheader code; unpinning/moving vbase → 515/495; a named `cst2` → 520/286); rows 412/415 — `lhu $s7` is reload's SPILL REGISTER:
storing `arg1` directly spills the HImode parameter and reproduces `sh $a1 / lhu $s7` exactly, but the target frame is [arg1 spill
@0][8-byte slot with NO traffic @8][cnt @0x10] and the phantom slot could not be induced (frame 0x38 vs 0x40). **Next lever:** run the
§501-M producer census on THIS frame first — the phantom slot sits BETWEEN the arg1 spill (regno-lowest) and `cnt`, i.e. it is an
`alter_reg` slot of a pseudo numbered between them (or a `spill_stack_slot`): read the `.greg` "Spilling reg N" / "now on stack" lines
and the `.lreg` headers (`tools/ghost_census.py`) before any spelling; the S83 hypotheses (a hard-reg `spill_stack_slot` on LO or `$s7`
during `retry_global_alloc`, or a ghost as in (a)) are now testable with the census; cf. §501-E. Corrected law from this row: at an
equal-priority load/store tie sched2 issues the STORE via `potential_hazard`, not LUID (sched.c:2616–2680).
**(d) `ov_SC03_105:func_80185810` — 489 ins, closeness 13.** TU `src/ov_SC03_105/ov_SC03_105_jr_80181C84.c`, sub
`ov_SC03_105_jr_80181C84`, asm `asm/ov_SC03_105/nonmatchings/ov_SC03_105_jr_80181C84/`. Draft `.run/P32/t5x/fable/func_80185810.c`;
report `.run/P32/t5x/reports/func_80185810.md`; harness `.run/P32/t5x/work/func_80185810/`. Three of four windows closed (P_TAG
bitfield OT link + integer add `(otz<<2)+(u32)ob` for the addu operand order; sched1 `flush_pending_lists` at the 33rd memory op
explains the load order → HI temps t20/t22 with tp loaded between loads and stores; pins uu `$4` / mode `$5` / ot16 `$6` — a hard-reg
destination is NOT birthing-boosted, so the LUID tie-break gives the load order; shf pinned `$3`). **Residual ONE cause, idx
363–380:** `cl &= 0xFFFF` is an unboosted 2nd set whose anti-deps hold the w-chain's two `cl` reads — the zero-byte fence after
`p[7] |=` is needed (without it the reads float to the block head and take `$a0/$a1`: 43/51) yet it forbids sched2's fillers (`sll $a2`,
`andi $a3`, `li/subu`) from crossing into the tpage/code window. A fresh single-set `clx` is boosted but combine folds the `andi` via
`nonzero_bits(cl)` into any same-block consumer (59); 2-set `clx` unboosted (49/39/42); an arm-duplicated store does not cross-jump
(490 ins); a launder asm is a real move for block_alloc. **Next lever:** make `cl` single-set with its high half cleared at birth
(`cl = *(u16 *)…` or a shift form) so no fence is needed, or give the two reads a fresh copy combine cannot fold (a HImode/subreg
temp defeats `nonzero_bits`). 3,360-variant region-2 sweep best 14 — do not repeat.
**(a) `main:func_80032A74` — CLOSED: PROVED at 1 (S84).** Best drafts `.run/P32/t4/drafts/func_80032A74_tuclean.c` (`s16 u18`, DIFF 1) and
`.run/P32/t4c/func_80032A74/lhu_tuclean.c` (`u16 u18`, 422/422 code, DIFF 22 frame rows). Proof in `.run/P32/t4c/func_80032A74/NOTES.md`
+ §501-M. Do NOT reopen without a new producer.
**(b) `md_MAIN_007:func_800CF408` — CLOSED: BANKED `commit:4001` (S84).** `.run/P32/t4c/bank/func_800CF408.c` = `func_800CF408/b0d_sibport_alias.c`.
**(c) `main:func_80039308` — CLOSED for this phase: PLATEAU at 4 (S84).** Best draft `.run/P32/t5x/fable/func_80039308.c` (4);
register-exact spill form `.run/P32/t5x/work/func_80039308/v_Y4.c` (8: the frame). Census + open levers in
`.run/P32/t4c/func_80039308/NOTES.md` and §501-O: the phantom slot `[arg1 @0][8 @8][cnt @0x10]` has no identified producer (initial-loop
slot with no traffic; every route refuted); rows 49/50 = hoisted-invariant order (`vol = b2 * 0x100` in the body, needs `$s2` steering
without the `$18` pin). Reopen only with a new idea for the slot — the row is honestly ledgered (R41 cost: ~3 h S84 + Fable 655k tokens S83).
### 4. NEXT — in order
0. **Preflight:** `git status --short | grep -v ghidra/` (empty) · `verbatim_check --strict` (5 == 5) · `make check-all` → 218/218 (R56 baseline). Prompt `/effort max` (R27) and WAIT.
1. **The hand pass on (c) → (d), one row at a time:** FIRST `grep -l` the family's banked bodies (for (c): the main `800_c.c` neighbours;
for (d): the `ov_SC03_105`/`jr_80181C84` OT/DR_TPAGE shapes and §501-I) and port a sibling's spelling if one exists; then read the report, reproduce the residual with `rtu_match`, dump the RTL
(`cc1_dumps.sh`), run the producer census where the residual is a frame/slot (§501-M), attribute the residual to a PASS and a dump
line before the first probe (§501, accelerators (11)/(12)), then the row's next lever; ≤ ~10 draft probes per row before writing the
verdict. A MATCH → bank + commit + `backlog.py render` + cookbook §501-N…; a plateau → `backlog.py log` (closeness, class, best draft,
cost) — write "banked" only from the tool's printed success line; a PROVED verdict names the pass and the refuted producers (P9).
0. **Preflight:** `git status --short | grep -v ghidra/` (empty) · `verbatim_check --strict` (5 == 5) · `make check-all` → 218/218 (R56
baseline; the last one was BEFORE the (b) bank — run it). Prompt `/effort max` (R27) and WAIT.
1. **Row (d)** per §3 (sibling search → port → else the `cl` lever; rtu_match with `--split ov_SC03_105_jr_80181C84 --source ov_SC03_105`;
bank via `SPLIT=ov_SC03_105_jr_80181C84 DRAFT_DIR=<dir> .run/P32/t3s3/bank.sh ov_SC03_105 src/ov_SC03_105/ov_SC03_105_jr_80181C84.c
asm/ov_SC03_105/nonmatchings/ov_SC03_105_jr_80181C84 hand "<title>" func_80185810`; a plateau → `backlog.py log` with closeness, class,
best draft, cost — write "banked" only from the tool's printed success line).
2. **T4b close:** `make clean && make extract-all && make check-all` (quote 218/218) · `make report` + `make report BINARY=main` ·
`frontier_classify --json .run/P32/frontier_t4b_final.json` · refresh this block · commit · harness #13 done.
`frontier_classify --json .run/P32/frontier_t4b_final.json` · `make tools-health` · `twin_rescan` · refresh this block · commit · harness #13 done.
3. **T5 (Max, Tier 1 — prompt R27; WAIT for gate 2):** P7 walk (T0–T4b) → milestone demo (R22 218/218 · tools-health · verbatim 5==5 ·
the final census · the wall ledger — ONE pin, PROVED · `make audit-disc` UNCLAIMED 0 of 220 · `make report` ×3 metrics + main
`143dbb89…` WITH and WITHOUT the SDK object dirs · denominators) → WAIT → `PhaseEnd_Phase32.md` (Build Log · Deviations incl.
the T4b directive and the remainder stated plainly · Commit Message · Rules Added — R64 to RATIFY + the S83/S84 candidates
below · Changelog v1.30.0 → v1.31.0 · Roadmap delta: P33 = verify + public flip · Plain-English Recap · believed/failed/sooner ·
🛑) → DIGEST.md §2/§3 (step 3b) → `git mv phase-ends/CURRENT_PHASE.md phase-ends/logs/Phase32.md` (R19) → R23 → leave both
uncommitted for Drew (R6) → "PhaseEnd file created. Commit the file and start a new Claude Code session for the next phase." →
HARD STOP (P8). **Rule candidates for the PhaseEnd table:** (i) a wall verdict must be PASS-attributed with a dump line
(R40 → "exonerate the instrument, then name the pass"); (ii) write "banked" only from the tool's printed success line; (iii) agents
write deliverables early (a dead run's draft banked); (iv) a helper must refuse an empty work list (R43 restated); **(v) S84: a
residual gets a PRODUCER CENSUS from the compiler source before a spelling sweep, and "PROVED" means every producer refuted on the
bytes (accelerators (12)); (vi) S84: a ledger's tie-break is part of the instrument — a re-verdict that cannot surface is a silent
skip (backlog.py kept the earliest record at equal closeness; R43/R61 family).**
the final census · the wall ledger — ONE pin, PROVED, plus the two ledgered plateaus (c)(d?) stated plainly · `make audit-disc` UNCLAIMED
0 of 220 · `make report` ×3 metrics + main `143dbb89…` WITH and WITHOUT the SDK object dirs · denominators) → WAIT → `PhaseEnd_Phase32.md`
(Build Log · Deviations incl. the T4b directive and the remainder · Commit Message · Rules Added — R64 to RATIFY + the candidates below ·
Changelog v1.30.0 → v1.31.0 · Roadmap delta: P33 = verify + public flip · Plain-English Recap · believed/failed/sooner · 🛑) → DIGEST.md
§2/§3 (step 3b) → `git mv phase-ends/CURRENT_PHASE.md phase-ends/logs/Phase32.md` (R19) → R23 → leave both uncommitted for Drew (R6) →
"PhaseEnd file created. Commit the file and start a new Claude Code session for the next phase." → HARD STOP (P8).
**Rule candidates for the PhaseEnd table:** (i) a wall verdict must be PASS-attributed with a dump line (R40 → "exonerate the
instrument, then name the pass"); (ii) write "banked" only from the tool's printed success line; (iii) agents write deliverables early;
(iv) a helper must refuse an empty work list (R43 restated); **(v) S84: a residual gets a PRODUCER CENSUS from the compiler source before
a spelling sweep, and "PROVED" means every producer refuted on the bytes (accelerators (12)); (vi) S84: a ledger's tie-break is part of
the instrument (backlog.py kept the earliest record at equal closeness — a re-verdict that cannot surface is a silent skip); (vii) S84:
when a same-family sibling is banked, port its SPELLING before touching a dial on the draft (§501-N, accelerators (13)).**
### 5. Files, tools, exact invocations, gotchas
- **`.run/P32/t4c/`** (S84, tracked: `dump.sh` (private dump + census, writes `dumps_<tag>/` under t4c), `check_all_preflight.log`,
`func_80032A74/{NOTES.md,lhu_tuclean.c,p1..p18.c}`; ignored: `dumps_*/`, `rtu/`). **`.run/P32/t5x/`** (tracked: BRIEF.md, targets.json,
`fable/func_*.c` (15), `reports/*.md` (15), `verdicts.jsonl`; untracked: packs/, work/, rtu/). **`.run/P32/t4b/`** (tracked:
`<fn>/NOTES.md|HYPOTHESIS.md`, `<fn>/*.c`, `*.log`). **`.run/P32/t3s3/`**: `bank.sh` (env `SPLIT=`, `DRAFT_DIR=`), `splice.py`, logs.
**`.run/c294/dumps_*`**: `cc1_dumps.sh` output (regenerable).
- **`tools/ghost_census.py <tag>.i.lreg`** — headers with no occurrence in the post-sched stream: `ST_REGS or none` ⇒ an 8-byte slot
(combine-minted); `GR_REGS …` ⇒ allocatable, no slot. `tools/cc1_dumps.sh` runs it and prints `vars=` (the arbiter).
- **Gotchas that bit in S84:** `rtu_match` on a MAIN function needs `--asm-subdir asm/nonmatchings/<sub>` (its default is the overlay
layout: "No such file … asm/ov_SC01_077/nonmatchings/…") · `.run/P32/t4b/func_80032A74/lhu.c` carries the TU-provided typedefs
(`Rec14`, `Slot54` …) and FAILS cc1 in the real TU — use the `*_tuclean.c` drafts (`cdecl.strip_provided_typedefs`) · a mechanism probe
must keep the temp's LAST mention after the variable's (cse `make_regs_eqv` canonicalizes the shorter-lived reg away) and sched can
sink a protecting store below a copy · `backlog.py` ties are now latest-wins (repaired) · the cookbook index does not index the bold
`§501-x` sub-entries (only `## §` headings) — `--check` stays green after appending one.
- **Gotchas from S83 (still live):** `gate_main --assert-baseline --allow-dirty` RESTORES the working tree's TUs before building (use an
in-tree `make extract BINARY=main && make build BINARY=main` for an uncommitted TU edit) · `make extract BINARY=main` rewrites main's
`asm/` — never while something reads those `.s` files · a bank helper called with no function name built the unchanged tree and
exited 0 (fixed, R43) · backticks inside a double-quoted `--where` argument are command substitution (use single quotes) ·
`.run/P32/**` allowlists are per-subdir — an ignored path silently breaks a `git add … &&` chain · an agent's masked_diff probe in
`src/` is build input (Makefile guard `commit:3949`).
- **`.run/P32/t4c/`** (S84, tracked: `dump.sh`, `check_all_preflight.log`, `func_80032A74/{NOTES.md,lhu_tuclean.c,p1..p18.c}`,
`func_800CF408/{NOTES.md,b0..b3*.c}` (b0d = the banked body), `func_80039308/{NOTES.md,c3_twoprod.c}`; ignored: `dumps_*/`, `rtu/`, `bank/`).
**`.run/P32/t5x/`** (Fable drafts/reports/work), **`.run/P32/t4b/`** (S83 hand-pass notes), **`.run/P32/t3s3/`**: `bank.sh` (env `SPLIT=`,
`DRAFT_DIR=`, `CLAUDE_SESSION=`), `splice.py`, bank logs. **`.run/c294/dumps_*`**: `tools/cc1_dumps.sh` output (regenerable).
- **Instruments:** `tools/cc1_dumps.sh <self-contained draft> <tag>` (`.frame` line, ins, `Spilling reg`/`now on stack`, ghost census) ·
`tools/ghost_census.py <tag>.i.lreg` (`ST_REGS or none` ⇒ an 8-byte slot; `GR_REGS` ⇒ allocatable) · `.run/P32/t4c/dump.sh` (same,
private dir) · `tools/rtu_match.py` (main: `--tu src/<sub>.c --asm-subdir asm/nonmatchings/<sub>`; overlays/modules: `--split <tu-basename>
--source <binary>`).
- **Gotchas that bit in S84:** `rtu_match` on a MAIN function needs `--asm-subdir` (its default is the overlay layout) · the T4b `lhu.c`
draft of (a) carries TU-provided typedefs and CC1-FAILs in the real TU — use `*_tuclean.c` · a TU may declare a symbol with another
type (`extern u8 D_800AA60C[]` in md_MAIN_007) — the alias `extern u32 wSYM[] __asm__("SYM");` is the fleet's spelling, a plain
redeclaration CC1-FAILs · the sibling's lever-7 trailing `__asm__ volatile("" : "=r"(x))` 2-set dial is NOT portable (a volatile asm
makes hard regs live at its position: m24/colour `$t1/$t0` swap) · a mechanism probe must keep the temp's LAST mention after the
variable's (cse `make_regs_eqv` canonicalizes the shorter-lived reg away) · `grep "\$t2\b"` in double quotes anchors on `$` — use
`'[$]t2[^0-9]'` · `backlog.py` ties are latest-wins now · the cookbook index does not index bold `§501-x` sub-entries.
- **Gotchas from S83 (still live):** `gate_main --assert-baseline --allow-dirty` RESTORES the working tree's TUs before building · `make
extract BINARY=main` rewrites main's `asm/` — never while something reads those `.s` files · backticks inside a double-quoted `--where`
are command substitution (use single quotes) · `.run/P32/**` allowlists are per-subdir · an agent's masked_diff probe in `src/` is build
input (Makefile guard `commit:3949`).
### 6. Environment
Fleet 218; shas: main `143dbb89f34491258bbc27810d0a12ec8b43a8dd` · md_MAIN_007 `2ff702b605ab5cfc18474c464c4c07e5f8ffd48c` · ov_SC03_105
@@ -305,18 +287,17 @@ Drew pushes.
### 7. Standing reminders
Every bank commits before the next command that can touch `src/` (R42) · count banks from the SOURCE and quote the fleet's green count
at every close (R58) · verify a build from its exit code (R53) · a masked/permuter score is not a closeness until its diff is read
(R63) · an `__asm__` body that reproduces instructions is a verbatim, not a bank (R62; zero-byte fences/launders are dials) · re-verify in
the CURRENT TU before splicing (§500-F) · attribute a residual to a PASS before sweeping levers (§501, accelerators (11)) · census the
PRODUCERS of a frame residual before any spelling (§501-M, accelerators (12)) · write "banked" only from the tool's printed success
line · rules check every 4 tasks (P6) · harvest into the cookbook before the next drafting step (R16/R30) · no `Co-Authored-By` (R5) ·
never stage `ghidra/` (R23).
(R63) · an `__asm__` body that reproduces instructions is a verbatim, not a bank (R62; zero-byte fences/launders are dials; asm-label
DECLARATIONS are the fleet's alias spelling) · re-verify in the CURRENT TU before splicing (§500-F) · port a banked sibling before dialing
(§501-N) · attribute a residual to a PASS before sweeping levers (§501, accelerators (11)) · census the PRODUCERS of a frame residual
before any spelling (§501-M/O, accelerators (12)) · write "banked" only from the tool's printed success line · rules check every 4 tasks
(P6) · harvest into the cookbook before the next drafting step (R16/R30) · no `Co-Authored-By` (R5) · never stage `ghidra/` (R23).
**Plain-English recap (R18).** This session banked the second leftover function outright: instead of tuning the previous draft further, it
copied the wording of an already-finished cousin function from the same family, adjusted the numbers, and it matched on the first
try (the only snag was a type declaration in the file, solved the way 1,400 other files already do). It also took the first of the four leftover functions — the one that was a single instruction
away — and, instead of trying more rewordings, listed every way the 1995 compiler can leave an unused slot in a function's stack
frame and struck each off against the bytes. The only way that could produce this slot at zero cost needs a signed 16-bit load, and
the original uses an unsigned one, so the function is now recorded as proved-unreachable by re-spelling, with the compiler pass named.
Along the way a genuinely new compiler quirk was found and measured (a temporary copied in and out of a variable leaves a ghost
register behind), a small measuring tool was written, an old one repaired, and a ledger bug fixed that had been hiding updated
verdicts. Three functions remain, each with its cause written down; nothing in the game's rebuilt code changed.
**Plain-English recap (R18).** Four functions were left; this session settled three of them by hand. One is now proved unreachable by
rewording (we listed every way the 1995 compiler can leave an unused stack slot and struck each off against the bytes), one was matched
outright and banked by copying the wording of an already-finished cousin function and adjusting its numbers (the game's md_MAIN_007
module is now 100% C), and one was measured to its floor with the same census and left honestly recorded with its open levers. Along
the way a new compiler quirk was found and measured, a measuring tool was written and an old one repaired, and a ledger bug that hid
updated verdicts was fixed. One function remains, thirteen instructions from done, with its cause written down and a cheap first move
(look for a finished cousin) queued for the next session; nothing else in the game's rebuilt code changed, and the last fleet-wide
rebuild check was green.