phase-36: T7 agent c42 — func_80186A8C and func_80182058 closed through cross-jump readings (10 bodies); related.txt requires evidence before calling a same-name body a variant (R22 218/218)

This commit is contained in:
Drew T
2026-09-10 18:17:41 -06:00
parent 2a4f28f835
commit 8bc06a2cb8
28 changed files with 9326 additions and 365 deletions
@@ -7,10 +7,6 @@ s32 func_80182058(void *a0)
u16 st;
if (func_8012BD14(*(s32 *)((s32)a0 + 0x64)) > 0x4000) {
/* LOAD-BEARING zero-byte cross-jump barrier (cookbook §5a).
* Without it gcc's find_cross_jump merges this `move v0,0; j epi`
* tail with the identical case-2 failure tail -> 58 ins instead of
* 60, and the case-2 `beq` then loses its delay-slot fill. */
return 0;
}
@@ -21,13 +17,13 @@ s32 func_80182058(void *a0)
*(s16 *)((s32)p + 0x2) = 8;
break;
case 2:
if (*(u16 *)((s32)p + 0x34) != 1) {
return 0;
if (*(u16 *)((s32)p + 0x34) == 1) {
goto hit;
}
goto hit;
goto fail;
case 4:
if (*(u16 *)((s32)p + 0x34) != 0) {
return 0;
goto fail;
}
hit:
D_801EEAF0 = st;
@@ -35,6 +31,9 @@ s32 func_80182058(void *a0)
*(s16 *)(*(s32 *)((s32)a0 + 0x64) + 0x2) = 10;
break;
default:
fail: /* the case-2/case-4 failures share this one `return 0`: a return
* falling out of a conditional (as the first one does) is what
* jump2's cross-jump would merge the early return into */
return 0;
}
@@ -0,0 +1,71 @@
# func_80182058 (ov_SC03_001_jr_8017AE2C.c) — T7 agent c42 — score 10 -> 0, the barrier gone
## (a) The residual in one sentence
COUNT 58 vs 60: the early `if (func_8012BD14(..) > 0x4000) return 0;` block (`j epi / move v0,zero`) is missing — mine
branches `beqz v0` into the case-2 failure's `v0 = 0; j epi` block instead, and that block, now a join, loses the
`move v0,zero` fill of the case-2 `beq` delay slot (a `nop` there). Every `j` offset after it shifts by 8.
## (b) The pass and the decision (read, then proven on `scratch/dumps_free`, `dumps_tree`, `dumps_w2` — `.greg` vs `.jump2`)
Post-reload cross-jumping (`toplev.c:3142` `jump_optimize (insns, 1, 1, 0)`; `jump.c:1969-2000` simple jumps tried
against every other jump to the same label, in chain order; `find_cross_jump` `jump.c:2371`, minimum 2).
Every `return 0` is `(set v0 0)` + `(jump epi)`. Before jump2 the lever-free body has FOUR such blocks: A (the early
return), B (case-2 failure), C (case-4 failure), D (the `default:`). A and C FALL OUT OF A CONDITIONAL JUMP whose label is
right after them. A is processed first; against B: `v0=0` matches (1 insn, minimum 2->1), then both streams reach a
JUMP_INSN (A's `if` jump 18 vs B's `beq` 54) that differ — and because jump 18's label follows A's own jump, the
jump-around-jump discount fires (`jump.c:2516-2519`, `prev_real_insn (JUMP_LABEL (i1)) == e1`): minimum 0, A is MERGED
INTO B (dumps_free `fn.jump2`: label 156 in front of B's insn 58, jump 18 retargeted there; C and D follow).
The target (= the tree's barrier body, dumps_tree) merges everything INTO A instead: the asm insn before A's `v0=0` makes
A's backward walk stop on an INSN-vs-JUMP code mismatch (`jump.c:2412`, no discount), so A finds no partner; D,
preceded by its own label, then merges into A through the label discount (`jump.c:2406-2410`), and B follows once it is
labelled. A survives in place, B becomes `beq hit / j A'` and reorg fills exactly as the target.
## (c) The move that closed it (10 -> 0, byte-proven)
Route the case-2 and case-4 failures to the `default:` block's `return 0` instead of returning in place:
case 2:
if (*(u16 *)((s32)p + 0x34) == 1) {
goto hit;
}
goto fail;
case 4:
if (*(u16 *)((s32)p + 0x34) != 0) {
goto fail;
}
hit: ...
break;
default:
fail:
return 0;
Now only TWO `v0=0; j epi` blocks reach jump2 (dumps_w2 `fn.greg`): A (after its conditional) and `fail` (after a
barrier + label). A vs fail: 1 match, then JUMP_INSN vs BARRIER (the stream-2 walk skips the label) -> code mismatch,
no discount, no merge. fail vs A: 1 match + its own label -> minimum 0 -> `fail` merged into A (dumps_w2 `fn.jump2`:
new `code_label 150` before A's insn 22, jumps 115/121/62/70 all retargeted to 150). The target's jump graph exactly.
No asm, no pin, no volatile, no invented term; the stale "LOAD-BEARING barrier" comment is dropped (refuted).
## (d) GENERATOR PROPOSAL
When a `__asm__ __volatile__("")` cross-jump barrier sits before an early `if (..) return K;` and several OTHER
`return K;` statements also fall out of conditionals (`if (..) return K;` inside switch cases / if-chains), rewrite those
others as `goto fail;` to ONE labelled `return K;` (the switch `default:` if it already returns K, else a new label after
the last statement): a labelled block can only be merged INTO the early return (label discount, `jump.c:2406`), never the
reverse, while fall-out-of-conditional returns carry the jump-around-jump discount (`jump.c:2518`) that lets the FIRST
return in insn order be merged away. Keep each branch's polarity: `if (ok) goto hit; goto fail;` (w1's
`if (!ok) goto fail; goto hit;` scores 2 — the `beq`/`bne` inverts).
## (e) What did NOT work (byte evidence)
* w1 (`if (x != 1) goto fail; goto hit;` in case 2): 2 — right jump graph, inverted case-2 branch (`bne ..,epi` + `j hit`).
* w4 (case 2 via `fail`, case 4 keeps `return 0;`): 11 — C is still a fall-out-of-conditional return; A merges into C.
* w6 (`fail:` as a trailing `return 0;` after the final return, default keeps its own): 11 — A merges again.
* w3 (switch restructured so failures `break` to a `return 0` after the switch, successes `goto done`): 12 — layout moves.
* The mechanical search (646 compiles, R7/R8/R10) has no move that re-targets a `return` to a shared label.
## (f) Where the method fell short
* The METHOD's cross-jump entries (c6/c10/c15) speak of merges the target keeps apart and of SHAPES made to differ; this
one is about merge DIRECTION: the same two blocks merge either way, and which survives is decided by which one owns
the discount (`jump.c:2406` label vs `:2518` jump-around-jump) and by insn order. Reading `.greg` (pre-jump2) against
`.jump2` for the surviving `code_label` settled it in one comparison — worth a METHOD line: "for a cross-jump
residual, find the SURVIVOR label in `.jump2` for both the tree body and yours".
* The TU/comment note ("LOAD-BEARING zero-byte cross-jump barrier (cookbook §5a)") was a claim; refuted on bytes.
Paths: body `.run/P36/agents/ov_SC03_001__func_80182058/body.c`; dumps `scratch/dumps_free/`, `scratch/dumps_tree/`,
`scratch/dumps_w2/`; variants `scratch/w1..w6.c`.
@@ -6,7 +6,7 @@ Same 230 instructions; at both `func_8012B178(a0, t - 0x4000)` sites the target
COUNT: 230 = 230, nothing missing — a pure ORDER residual of two insns, twice.
## (b) The passes and decisions (read, then proven on dumps `scratch/dumps_free`, `scratch/dumps_v1`)
* `calls.c:1879-1889` (gcc-2.7.2): MIPS has no `PUSH_ROUNDING`, so `PUSH_ARGS_REVERSED` is NOT defined (`calls.c:38-44`); the
* `calls.c:1860-1881` (gcc-2.7.2): MIPS has no `PUSH_ROUNDING`, so `PUSH_ARGS_REVERSED` is NOT defined (`calls.c:38-44`); the
hard-register loads are emitted in argument order, `$4 = a0` then `$5 = value` (dumps_free `fn.rtl` insns 163, 165).
* combine (`can_combine_p`, `combine.c:880-930`): the separate `av = t - 0x4000` insn (160) is folded into the `$5 = av`
arg-move (165), which sits AFTER `$4 = a0` — so the subtract becomes the last insn before the call (dumps_free `fn.combine`).
@@ -0,0 +1,74 @@
void func_80183E3C(s32 a0) {
extern u8 D_800AF648;
extern s32 D_801A73BC;
extern s32 D_8019989C;
extern s32 D_80199B70;
extern u16 D_80126B62;
/* sp+0x10 local block. Frame is 0x38 = 0x10 outgoing args + 0x20 vars +
* 8 saved regs ($s0,$ra), so the vars block is 12 bytes larger than the
* fields this function actually touches -> trailing `unused[3]`. */
struct {
s16 v[3]; /* sp+0x10 */
s16 pad0; /* sp+0x16 */
u16 sxy[2]; /* sp+0x18 */
s32 z; /* sp+0x1C */
s32 flag; /* sp+0x20 */
s32 unused[1]; /* sp+0x24 */
} L;
s16 x;
s32 y;
if (*(s32 *)(a0 + 0x94) == 0xD) {
L.v[0] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x48);
L.v[1] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4C);
L.v[2] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x50);
/* The target loads &D_800AF648 afresh (lui/addiu $a0) for EACH call. The
* second call names the object through a second declaration of the same
* symbol: its SYMBOL_REF string is a different pointer, so cse does not
* unify the two address pseudos into one callee-saved register. */
func_8004914C(&D_800AF648);
{
extern u8 D_800AF648_b __asm__("D_800AF648");
func_800491AC(&D_800AF648_b);
}
RotTransPers((s32)L.v, (s32)L.sxy, &L.z, &L.flag);
if (L.flag >= 0 && (u32)((L.sxy[0] + 0x9F) & 0xFFFF) < 0x13F
&& (u32)((L.sxy[1] + 0x77) & 0xFFFF) < 0xEF) {
s32 vol = (s16)L.sxy[0];
if (vol < 0) {
vol = -vol;
}
vol = ((0xA0 - vol) * 127) / 160;
func_8002D4C8(0x702, (vol | 0x1000) & 0xFFFF);
}
}
if (func_8012BCCC(a0) <= 0x24000) {
s16 c;
c = *(u16 *)(a0 + 0x102) + 1;
*(s16 *)(a0 + 0x102) = c;
if (c >= 0x78) {
if ((*(u16 *)(a0 + 0x100) & 0x2000) == 0) {
func_8012A828(a0, (s32)&D_801A73BC);
*(s16 *)(a0 + 0x2) = 10;
*(s16 *)(a0 + 0x102) = 0;
*(s32 *)(a0 + 0x58) = (s32)&D_8019989C | 0x40000000 | 0x20000000;
}
}
}
*(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) += func_8012B8E4(a0, 0x10);
*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) &= 0xFFF;
x = *(s16 *)(a0 + 0xA);
y = *(s16 *)&D_80126B62;
if (x <= y - 0x100) {
*(s16 *)(a0 + 0xA) = x + 0x8;
} else if (x >= y - 0x80) {
*(s16 *)(a0 + 0xA) = x - 0x8;
}
func_8012B1B4(a0, (s32)&D_80199B70);
func_8012CBCC(a0);
}
@@ -33,6 +33,7 @@ s16 y;
u32 c;
u16 bb;
u32 c0;
u32 w;
mk1 = 0xFFFFFF;
cc1 = 0x74808080;
@@ -50,10 +51,12 @@ s16 y;
yt = y;
c0 = yt + 1;
c0 <<= 16;
w = c0 | x1;
__asm__("" : "=r"(w) : "0"(w)); // !FAKE: launder w — sched1 launches a single-set p[2] value right before its store (birthing_insn_p, sched.c:2469) and sched2 ties the or/ori at equal priority and falls back to sched1's order (sched.c:2385); the asm's second set of w keeps it ahead of the cl chain, no plain spelling reorders them (S103 c19) (P36 S103 c46 minimum-lever)
c = v << 6;
c |= 0x4016;
cl = c << 16;
p[2] = c0 | x1;
p[2] = w;
p[3] = cl | 0x1800;
p += 5;
p[0] = (((u32)(p - 5)) & mk1) | ca;
@@ -35,7 +35,7 @@ void func_8017D000(void *a0) {
s32 t;
s16 *p;
void *w;
s16 *r;
if (cur != lo) {
if (lo < cur) {
@@ -72,7 +72,7 @@ void func_8017D000(void *a0) {
if (*(s16 *)((s32)a0 + 0xFC) == 0xB) {
s32 f = *(s32 *)((s32)a0 + 0x1C);
s32 v = -(f & 1) & 0xC0;
u8 v = -(f & 1) & 0xC0;
f = f + 1;
*(s32 *)((s32)a0 + 0x1C) = f;
D_801EED51 = v;
@@ -100,6 +100,7 @@ void func_8017D000(void *a0) {
u16 bs;
s32 x;
s16 y;
s16 *s;
t = (c - h) * 255 / h;
q = &D_801EED4D;
bs = (u16)D_801EED28;
@@ -107,7 +108,8 @@ void func_8017D000(void *a0) {
y = x - 4;
D_801EED55 = 0xFF;
*q = 0xFF;
*(s16 *)(q + 0xF) = x;
s = (s16 *)(q + 0xF);
*s = x;
D_801EED64 = bs + c;
D_801EED30 = x;
D_801EED6C = y;
@@ -115,14 +117,13 @@ void func_8017D000(void *a0) {
D_801EED74 = bs + c - 4;
D_801EED88 = -t;
D_801EED80 = -t;
func_800176F0(q + 0xF);
func_800176F0(s);
}
p = &D_801EEDA8;
D_801EED98 = *(u16 *)((s32)p - 0x18) + (u16)D_80193E88;
r = p - 0xC;
D_801EED98 = *(u16 *)r + (u16)D_80193E88;
*p = D_801EED98 - 4;
w = (void *)((s32)p - 0x80);
p = (s16 *)((s32)p - 0x18);
func_800176F0(w);
func_800176F0(p);
func_800176F0(p - 0x40);
func_800176F0(r);
}
@@ -0,0 +1,88 @@
# func_8017D000 (ov_SC04_011, TU ov_SC04_011_jr_8017AE2C.c) — T7 agent c44
**Result: score 0, lever-free.** No register pin, no asm, no added volatile, no do-while, no invented term, no dead
assignment. The fix is inside the function body only. Whole-object check on the `--try --keep` object: `objdump -drz` of the
ENTIRE `.o` (every function, relocations included) is identical to `.run/P36/delever/baseline/src/ov_SC04_011/
ov_SC04_011_jr_8017AE2C.o`, and `.text` compares equal with `cmp`. Candidates are in `scratch/` (`a1.c`, `b1.c`, `c1.c`,
`d1.c` = `body.c`, `e1.c`) with their `.dis`; the pass dumps are in `scratch/dumps_free/` and `scratch/dumps_d1/`.
No lever-free copy existed elsewhere: `git grep` finds no other definition that touches `D_801EEDA8`, and
`related.txt` listed no port candidate (the only `func_8017D000` in `src/shared/ov/` is an unrelated function with the same
overlay address).
## (a) The residual in one sentence
COUNT 296 vs 293. There were three independent defects. (1) In the `== 0xB` arm, `f` and `v` had swapped registers and
`f + 1; sw` was hoisted above `negu; andi 0xc0`. (2) In the else arm, `*(s16 *)(q + 0xF) = x` became an absolute
`lui at; sh v0,15(at)` (+1) where the target writes `sh v0,15(a2)`. As a result `addiu a0,a2,15` left the `jal` delay
slot (+1 `nop`). (3) In the tail, `*(u16 *)(p - 0x18)` became an absolute `lui v0; lhu v0,-24(v0)` (+1) where the target
reads `lhu v0,-24(s0)`.
## (b) The passes and the decisions (all three proven on bytes and in dumps)
### Defects 2 and 3: cse folds a base+offset MEM address into an absolute address. A register address is not folded.
* `find_best_addr` (cse.c:2621). An address that is not a bare REG is first run through `fold_rtx` and accepted by
`validate_change` with NO cost test (cse.c:2659-2662). `p` / `q` carry the constant equivalence `&SYM`, so
`(plus p -24)` folds to `(const (plus SYM -24))`, which is a valid MIPS address (the assembler's `lui at` macro). This is
why the tree needed the three launders.
* A BARE REG address skips that fold. For a REG, cse looks up the register's equivalence class and takes the member with
the lowest `ADDRESS_COST`, breaking ties by the higher `rtx_cost` (cse.c:2708-2735). `ADDRESS_COST(REG)=1`
(mips.h:2895), `(plus reg small_int)`=1, and `(const (plus sym k))`=2 (`mips_address_cost`, mips.c:1615-1653). So
for `s = q + 15; *s = x;` the class of `s` is {`s`, `(plus q 15)`, `(const D_801EED4D+15)`}. The tie at cost 1 goes to
`(plus q 15)` (the higher rtx_cost). The constant, at cost 2, is never chosen. Dump proof: `dumps_d1/d1.i.rtl` insn 433
is `(set (mem:HI (reg 240)) …)`, and `d1.i.cse` rewrites it as `(set (mem:HI (plus (reg 236) 15)) …)`. The tail
behaves the same way: insn 485 becomes `(mem:HI (plus (reg 86) -24))`.
* After that, the pointer temp's only other use is the call argument. The `(set s (plus q 15))` insn stays where the
source put it, just before the call (it is kept as a PLUS because `rtx_cost` of the CONST is higher). So reorg puts
`addiu a0,a2,15` back into the `jal` delay slot, and the tail's `r` ties to `p`'s `$s0` (`addiu s0,s0,-24` in the
first `jal`'s delay slot), as in the target.
### Defect 1: sched1's `birthing_insn_p` boost. The `u8` width removes it.
* With `s32 v`, the last insn of the chain (`v = t & 0xC0`) is a SET of a REG that is live after it and set only once.
`birthing_insn_p` (sched.c:2468-2499) returns 1 for it, and `adjust_priority` (sched.c:2539-2545) raises it to
`max_priority` when it becomes ready in the backward list scheduler. So the `v` chain is placed right before its first
`sb`, and `f + 1; sw` is scheduled above `negu/andi` (`dumps_free/free.i.lreg`: order 255 257 **262 265** 258 259 268).
* With `u8 v` (the width of every destination it is stored to), combine folds the truncating move into the `and`, and
that insn's destination becomes `(subreg:SI (reg:QI 191) 0)`. `birthing_insn_p` wants `GET_CODE (SET_DEST) == REG`,
so it gets no boost, and sched1 keeps source order: 255 259 262 269 272 275 278 (`dumps_d1/d1.i.sched`). Local-alloc
then gives `v` `$v0` and `f` `$v1`, as in the target. This is the same fact the tree's asm launder was forcing: an asm
output is not a plain birthing SET of the chain.
## (c) The source moves that closed it (three, independent; the scores are additive)
1. `s32 v = -(f & 1) & 0xC0;` → `u8 v = …` (the width of the ten `u8` stores). 33 → 17 (`a1.c`).
2. Else arm: `s16 *s = (s16 *)(q + 0xF); *s = x; … func_800176F0(s);` instead of `*(s16 *)(q + 0xF) = x; …
func_800176F0(q + 0xF);`. On top of 1: 17 → 2 (`c1.c`).
3. Tail: `r = p - 0xC; D_801EED98 = *(u16 *)r + (u16)D_80193E88; *p = D_801EED98 - 4; func_800176F0(p - 0x40);
func_800176F0(r);` instead of the reassigned `p` + `w`. On top of 1: 17 → 15 (`b1.c`). 1+2+3: **0** (`d1.c`).
Control: 2+3 without 1 = 16 (`e1.c`, MIXED), so move 1 is exactly defect 1.
## (d) GENERATOR PROPOSALS
* **COUNT +1 `lui at` / `lui vN` on an offset load/store where the target uses `k(reg)` of a pointer that holds `&SYM`:**
name the offset address as a pointer local (`T *s = (T *)(base + k); *s = …`), and if the target also passes
`base + k` to a call, pass `s` there. cse's `find_best_addr` keeps a register address as `(plus base k)` (cost tie,
cse.c:2715-2721) but folds a written-out `base + k` to an absolute address (cse.c:2659). This is the plain-C
replacement for the `__asm__("" : "=r"(p) : "0"(p))` launder whenever the pointer's other uses are call arguments.
* **ORDER + swapped `$v0/$v1` where the target computes a value's whole chain before an unrelated `x+1; sw`:** if the
value is only stored narrow (`sb`/`sh`), declare it with the store width (`u8`/`s16`). The subreg destination stops
sched1's birthing boost (sched.c:2468-2545). Test: `.lreg` shows the chain's last insn scheduled right before its first
use.
## (e) What did not work (byte evidence)
* `*(s32 *)(a0 + 0x1C) = f + 1;` with `f` not reassigned: 21 (`a2.c`). Worse, because the register swap stays.
* `b1.c` (tail only, on top of move 1): 15. That fixes the tail's `lui`; the else arm's absolute `sh` + `nop` remain.
* The mechanical search's best (15, a do-while + `R8 base tmp0`) never tried a pointer local on a MEM address. Its
`R12 width t` moves narrowed `t`, not `v`.
## (f) Where the method fell short
* METHOD_S103's launder list (c11: "write the read relative to a DERIVED pointer") describes the case where the pointer
is NOT known constant to cse. Here the pointer IS a known constant in the same block, and the answer is simpler:
make the address itself a REGISTER. `find_best_addr` never folds a REG, only non-REG addresses (cse.c:2659 vs
:2708-2735). This should be the FIRST launder move tried: it is one line and needs no pass-ordering conditions.
* COUNT-first worked: the three extras were one `lui at`, one `nop`, and one `lui v0`, each visible only in the whole
objdump (the hunk view split the `sh 15(a2)` across two hunks).
@@ -0,0 +1,47 @@
s32 func_80185578(s32 arg0, s32 arg1) {
extern u8 D_801BD0C4[];
extern s32 D_801BD2FC[];
extern u8 D_800D3918[];
extern void func_80187414(s32 a0, void *a1, void *a2, s32 a3);
extern void func_801873B0(s32 a0, void *a1, s32 a2, s32 a3, s32 a4, s32 a5);
extern void func_8001C924(s32 a0, void *a1);
u8 buf[8];
s16 y = arg1;
s32 res;
s16 state;
s32 flags;
state = *(u16 *)(arg0 + 0x70) & 0xF;
flags = *(u32 *)(arg0 + 0xE0);
if (flags & 4) {
return 0;
}
switch (state) {
case 0:
if (flags & 1) {
func_80187414(arg0, D_801BD0C4, buf, 0xC);
res = ((s32 (*)(s32, void *, s32, s32, s32, s32))func_801873B0)(arg0, buf, 0x27F, (s16)arg1, 0, 0);
*(s32 *)(arg0 + 0xD0) = res;
*(u32 *)(arg0 + 0xE0) &= ~1;
if (res != 0) {
*(u16 *)(arg0 + 0xEE) = *(u16 *)(res + 0x36);
}
}
/* fallthrough */
case 1:
case 2:
case 3:
func_80187414(arg0, D_800D3918, buf, 0xB);
res = ((s32 (*)(s32, void *, s32, s32, s32, s32))func_801873B0)(arg0, buf, 0x27F, (s16)(y | (state + 1)), 0, 0);
*(s32 *)(arg0 + 0xCC) = res;
*(u32 *)(arg0 + 0xE0) |= 4;
func_8001C924(*(s32 *)(arg0 + 0x20), (void *)D_801BD2FC[state]);
if (res != 0) {
*(u16 *)(arg0 + 0xEC) = *(u16 *)(res + 0x36);
}
break;
default:
return 1;
}
return 1;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,75 @@
# func_80185578 (ov_SC06_022, 6 copies): closed lever-free — it returns int, and `y` is an s16 (agent c43, S103)
**Result: score 0, and the whole object is byte-identical (`objdump -drz -s` diff empty), BUT THE CLOSE NEEDS A CHANGE
OUTSIDE THE BODY.** The function returns a value, so its three in-TU declarations have to say `s32` instead of
`void`:
- `src/ov_SC06_022/ov_SC06_022_jr_80184A28.c:2998` `extern void func_80185578(s32 a0, s32 a1);` → `extern s32 ...`
- `:3288` and `:3289` (the two "SIMULATION of real-TU context" rows right above the definition) → `extern s32 ...`
`PACK/body.c` is the definition (it gives `conflicting types` under `--body` while those rows still say void).
`PACK/body_tu.c` is the whole TU with the three rows retyped, and scores 0 via `--try` without `--body`. The other two
TUs that declare it (`ov_SC06_022_jr_80184304.c:2978`, `ov_SC06_022_jr_80182D08.c:3605`) are byte-identical either
way (whole-object diffs empty with the rows retyped: `scratch/decl_*.c`), so they can be retyped for consistency or
left alone. Their callers discard the result.
**Transfer: all 6 copies score 0, and each whole object is byte-identical**, with the same edit plus that TU's own
declarations retyped (`scratch/xfer.py`; 3-4 rows per TU). The copies are ov_SC06_018 func_801874E4, SC06_020
func_80181654, SC06_022 func_80185578, SC06_024 func_80187A50, SC06_032 func_80182288, SC06_033 func_80185F6C.
## (a) The residual (counted first: mine 90, target 94)
Two independent defects:
1. **A missing `move s3,s0`** (the `y = x` copy). The target keeps `x` in `$s0`, shared later with `res`, and `y` in
`$s3`. Lever-free, `y` and `x` became ONE pseudo (`move s2,a1`), and every register downstream shifts. The tree's
`addu y, x, $zero` asm faked that copy.
2. **Missing `$v0` writes**: `move v0,zero` on the `flags & 4` path and `li v0,1` on the other paths. The function
RETURNS 0 ("already set up", bit 2 of +0xE0) or 1. The tree declared it `void` and faked the return value with a
keepalive asm `"r"(rv)` after an `epi:` label.
## (b) The passes (proved on dumps: `scratch/dumps_r6/` vs `scratch/dumps_r6s/`)
1. The copy: with `s32 y`, `.rtl` insn 13 is `(set (reg:SI 74) (reg:SI 73))`, and cse1's `(set REG0 REG1)` case
(cse.c:7440-7474, gate :7455 wants a REG source) retargets the previous insn: `.cse` insn 6 becomes
`(set (reg 74) (reg:SI 5 a1))` and the copy disappears. With `s16 y`, the insn is
`(set (reg:HI 74) (subreg:HI (reg:SI 73) 0))`. Its source is a SUBREG, not a REG, so the gate fails and the copy
survives cse (`.cse` insn 13, `movhi_internal2`). It's a separate pseudo, so it gets `$s3` while `arg1` keeps
`$s0` and dies into the case-0 call. This is METHOD c4's width mechanism exactly: there's no PROMOTE_MODE, so the
s16 local is an HImode pseudo.
2. The return value: `return 0` / `return 1` on an `s32` function sets `$2` on every path, which a void function
can't do. No pass is involved; the bytes just prove the function has a return value.
What's proved on bytes: `r1` (s32 return, s32 y) = 16 [COUNT, 93 vs 94], which is the copy alone.
`r2`/`r3`/`r5`/`r6` (s32 return plus u16/s16 y, in several spellings) = 0. `r6s` (r6 with `s32 y`) = 16.
`r7` (no `y`, `arg1` used directly) = 16. history.txt's `y s32->u16` alone = 11, which is the width without the
return value.
## (c) The moves (a JOINT close; neither alone reaches 0)
- `void` → `s32`, with `return 0;` / `return 1;` in place of `rv = …; goto epi;` (plus the declarations above).
- `s16 y = arg1;` replaces `s32 x = arg1; s32 y; y = x;`, and case 0 passes `(s16)arg1`. `x` goes away entirely:
the parameter IS `x`.
## (d) GENERATOR PROPOSAL
Two rules. (1) **When a `void` function's tree body ends in a keepalive `__asm__ volatile("" : : "r"(v))` on a
0/1 (or constant) variable assigned before gotos to the end label, the function returns that value.** Retype the
definition and every in-TU `extern void` row to `s32`, turn `v = K; goto end;` into `return K;`, and score the
WHOLE TU (`--try` without `--body`). Callers that discard the result don't change bytes (checked in 2 TUs here).
Sizing grep: `grep -rn '__asm__ volatile("" : : "r"(rv))' src` = 6 (exactly this class). The wider
`grep -rn '__asm__ volatile("" : : "r"(' src | grep keepalive` = 19; not every one of those is a return value, so
check each target for `$v0` writes before the epilogue. (2) When a `y = x` copy of a parameter is
missing and `y` is only used under a `(s16)`/`(u16)` cast, declare `y` s16/u16 (R20) — AFTER rule 1, because a
missing return value adds COUNT noise that hides whether the width move worked (history's `y->u16` scored 11 and
the search stopped there).
## (e) Tried and did not work (bytes)
- Every body-only variant: the return value can't be produced in a void function without a lever. I didn't try a
`volatile` or asm.
- `r1`: s32 return with `s32 y` = 16. `r7`: drop `y` = 16. Both lose the copy (the cse.c:7455 swap).
## (f) Where the method fell short
- Counting first found it straight away: 4 missing = 1 copy + 3 `$v0` writes. But the brief's goal ("no change
outside the body") is unreachable for any function the decomp mis-declared as `void`, and the `--body` scorer
can't express the fix at all: it compiles `conflicting types`. The mechanical search (history.txt) ran 1,127
compiles on body-only moves that could never have reached 0.
- METHOD has no row for "keepalive asm = a missing return value". It should come FIRST in the COUNT branch: the
`$v0` writes are the cheapest instructions to account for, and one look at the target (`move v0,zero` in a `j`
delay slot, `li v0,1` before the epilogue) settles it.
- The tree's rows at `:3287-3289` ("SIMULATION of real-TU context") are two duplicate `extern void` declarations.
They are the lines that have to change, and the sibling TUs carry 3-4 such rows each.
+35 -35
View File
@@ -54,7 +54,7 @@
},
"kinds": {
"asm-body/direct": 13,
"barrier/direct": 1934,
"barrier/direct": 1929,
"barrier/via-macro": 2,
"gte-lever/direct": 362,
"gte-lever/via-macro": 100,
@@ -72,26 +72,26 @@
"binaries": 218,
"classes": {
"A": {
"bodies": 2334,
"distinct_bodies": 869,
"bodies": 2329,
"distinct_bodies": 868,
"file_scope": 0,
"in_bodies": 6910,
"in_bodies": 6900,
"kinds": {
"pin": 6910
"pin": 6900
},
"marked": 6910,
"sites": 6910,
"marked": 6900,
"sites": 6900,
"tus": 1416,
"unmarked": 0
},
"B": {
"bodies": 5024,
"distinct_bodies": 857,
"bodies": 5019,
"distinct_bodies": 856,
"file_scope": 13,
"in_bodies": 14623,
"in_bodies": 14618,
"kinds": {
"asm-body": 13,
"barrier": 1936,
"barrier": 1931,
"gte": 6858,
"gte-lever": 462,
"gte-unsigned": 3,
@@ -100,9 +100,9 @@
"launder": 1801,
"verbatim-body": 2682
},
"marked": 5359,
"sites": 14636,
"tus": 1599,
"marked": 5354,
"sites": 14631,
"tus": 1596,
"unmarked": 9277
},
"C": {
@@ -207,9 +207,9 @@
"coverage": {
"asm": {
"comment_dead": 6786,
"live": 22548,
"live": 22533,
"macro_block": 194,
"raw": 29528
"raw": 29513
},
"attribute": {
"comment_dead": 0,
@@ -225,9 +225,9 @@
},
"register": {
"comment_dead": 8565,
"live": 6960,
"live": 6950,
"macro_block": 18,
"raw": 15543
"raw": 15533
},
"volatile": {
"comment_dead": 2476,
@@ -237,7 +237,7 @@
}
},
"coverage_ok": true,
"elapsed_s": 29.7,
"elapsed_s": 31.0,
"generated": "2026-09-10",
"gte_levers": {
"direct": 362,
@@ -248,15 +248,15 @@
"via_macro": 100,
"what": "GTE ops whose clobbers exceed the canonical macro's (a scheduling steer): class-B levers INSIDE the headline number since T5 (2026-09-09), marked, 0 at the close"
},
"head": "321b540e7",
"head": "2a4f28f83",
"headers": 3181,
"levers_AB": {
"asm": 5093,
"bodies": 3060,
"distinct_bodies": 1160,
"marked": 12003,
"pins": 6910,
"sites": 12003,
"asm": 5088,
"bodies": 3050,
"distinct_bodies": 1158,
"marked": 11988,
"pins": 6900,
"sites": 11988,
"unmarked": 0,
"what": "register pins + asm statements excluding GTE ops: the classes the phase drives to 0"
},
@@ -412,7 +412,7 @@
"$29": 13,
"$3": 698,
"$4": 1045,
"$5": 969,
"$5": 959,
"$6": 212,
"$7": 175,
"$8": 170,
@@ -423,30 +423,30 @@
"v0": 2,
"v1": 3
},
"sites": 6910,
"sites": 6900,
"sp": 13,
"spelling": {
"__asm__": 6853,
"__asm__": 6843,
"asm": 57
},
"volatile_qualified": 3,
"zero": 106
},
"src_stamp": "7552158a131a0fab",
"src_stamp": "43d7810b6d23cc55",
"tus": 4121,
"unclassified": 0,
"union_AD": {
"bodies": 6586,
"bodies": 6576,
"by_kind": {
"main": 165,
"md": 133,
"ov": 6097,
"ov": 6087,
"resident": 10,
"shared": 181
},
"copies_in_multi": 5351,
"distinct_bodies": 1450,
"multi_copy_classes": 215
"copies_in_multi": 5341,
"distinct_bodies": 1448,
"multi_copy_classes": 213
},
"verbatim_excluded": {
"functions": 13,
+14 -14
View File
@@ -1,31 +1,31 @@
lever_census: 218 binaries · 4,121 TUs + 3,181 headers · coverage OK · unclassified 0 · verbatim excluded 13 fn / 14 sites (manifest 13)
coverage asm raw 29528 = live 22548 + macro-block 194 + comment/dead 6786
coverage register raw 15543 = live 6960 + macro-block 18 + comment/dead 8565
coverage asm raw 29513 = live 22533 + macro-block 194 + comment/dead 6786
coverage register raw 15533 = live 6950 + macro-block 18 + comment/dead 8565
coverage volatile raw 4448 = live 1890 + macro-block 82 + comment/dead 2476
coverage builtin raw 599 = live 445 + macro-block 0 + comment/dead 154
coverage attribute raw 76 = live 76 + macro-block 0 + comment/dead 0
class sites in-bodies file-scope bodies distinct TUs marked unmarked kinds
A pins 6910 6910 0 2334 869 1416 6910 0 {'pin': 6910}
B asm 14636 14623 13 5024 857 1599 5359 9277 {'launder': 1801, 'barrier': 1936, 'keepalive': 645, 'gte': 6858, 'gte-lever': 462, 'instruction': 236, 'asm-body': 13, 'gte-unsigned': 3, 'verbatim-body': 2682}
C volatile 1590 1438 152 496 95 610 14 1576 {'decl-body': 58, 'cast': 1378, 'decl-file': 152, 'param': 2}
A pins 6900 6900 0 2329 868 1416 6900 0 {'pin': 6900}
B asm 14631 14618 13 5019 856 1596 5354 9277 {'barrier': 1931, 'launder': 1801, 'keepalive': 645, 'gte': 6858, 'gte-lever': 462, 'gte-unsigned': 3, 'instruction': 236, 'asm-body': 13, 'verbatim-body': 2682}
C volatile 1590 1438 152 496 95 610 14 1576 {'decl-body': 58, 'decl-file': 152, 'cast': 1378, 'param': 2}
D register 50 50 0 47 47 6 0 50 {'register': 50}
E asm-label 7688 1265 6423 997 120 2084 0 7688 {'asm-label': 7688}
F builtin 445 445 0 428 28 302 0 445 {'builtin': 445}
G attribute 76 1 75 1 1 40 0 76 {'attribute': 76}
UNION A–D: 6,586 bodies · 1,450 distinct (addresses normalized) · 215 multi-copy classes holding 5,351 bodies · by kind {'ov': 6097, 'md': 133, 'shared': 181, 'main': 165, 'resident': 10}
THE PHASE'S NUMBER (pins + asm statements, GTE excluded): 12,003 sites in 3,060 bodies (1,160 distinct) · marked !FAKE 12,003 · UNMARKED 0
UNION A–D: 6,576 bodies · 1,448 distinct (addresses normalized) · 213 multi-copy classes holding 5,341 bodies · by kind {'main': 165, 'ov': 6087, 'resident': 10, 'shared': 181, 'md': 133}
THE PHASE'S NUMBER (pins + asm statements, GTE excluded): 11,988 sites in 3,050 bodies (1,158 distinct) · marked !FAKE 11,988 · UNMARKED 0
orphan !FAKE markers (no pin/asm site on the line nor below): 0
GTE levers (clobbers beyond the canonical macro's): 462 sites (100 via a variant macro, 362 direct) · marked 462 · UNMARKED 0 · unsigned GTE statements 3
per-TU asm macro definitions outside the GTE header: 314 {'gte': 150, 'instruction': 9, 'launder': 154, 'barrier': 1} (GTE variants 64)
pins: 6,910 · $0 106 · $sp 13 · with initializer 538 · volatile-qualified 3 · bare-name 15 · spellings {'__asm__': 6853, 'asm': 57}
per-TU asm macro definitions outside the GTE header: 314 {'gte': 150, 'launder': 154, 'instruction': 9, 'barrier': 1} (GTE variants 64)
pins: 6,900 · $0 106 · $sp 13 · with initializer 538 · volatile-qualified 3 · bare-name 15 · spellings {'__asm__': 6843, 'asm': 57}
whole-body asm routines in C shells, manifest PERMANENT (hand asm, NOT levers): 22 routines · 2,682 sites (2,660 private copies + 22 shared headers); asm-bodies NOT permanent (levers): 13 site(s) ['func_8001E378:DECOMPILE-NOW', 'func_80020F34:DECOMPILE-NOW', 'func_800249F0:DECOMPILE-NOW', 'func_80025CBC:DECOMPILE-NOW', 'func_80026514:UNCERTAIN', 'func_800268D0:UNCERTAIN', 'func_80027058:DECOMPILE-NOW', 'func_80027200:DECOMPILE-NOW', 'func_800CBA44:DECOMPILE-NOW', 'func_8017D810:DECOMPILE-NOW', 'func_8017E26C:UNCERTAIN', 'func_80184440:DECOMPILE-NOW', 'func_801A3BCC:DECOMPILE-NOW']
asm kinds: {'asm-body/direct': 13, 'barrier/direct': 1934, 'barrier/via-macro': 2, 'gte/direct': 200, 'gte/via-macro': 6658, 'gte-lever/direct': 362, 'gte-lever/via-macro': 100, 'gte-unsigned/direct': 3, 'instruction/direct': 214, 'instruction/via-macro': 22, 'keepalive/direct': 645, 'launder/direct': 1735, 'launder/via-macro': 66, 'verbatim-body/direct': 2682}
instruction mnemonics: {'la': 142, 'addu': 23, 'RTP_SND': 22, 'addiu': 22, '.section': 7, 'lui': 4, 'move': 4, 'lh': 3, 'and': 2, 'mult': 1, 'mfhi': 1, 'sll': 1, 'li': 1, 'lw': 1, 'nop': 1, 'srl': 1}
gte mnemonics: {'gte_ldv0': 757, 'gte_stlvnl': 593, 'gte_stsxy': 447, 'gte_rtps': 437, 'gte_stflg': 415, 'gte_rtpt': 352, 'gte_SetRotMatrix': 246, 'gte_stsxy3': 236, 'gte_rtv0tr': 228, 'gte_SetTransMatrix': 226, 'gte_ldv3c': 184, 'gte_ldv3': 177, 'gte_ldrgb': 164, 'gte_stsv': 161, 'lwc2': 159, 'gte_stsz4': 149, 'gte_stsz3': 147, 'gte_stszotz': 134, 'gte_ldIR0z': 134, 'gte_ldIRGB': 134, 'gte_dpcl': 134, 'gte_stORGB': 134, 'gte_stsxy3_f3': 111, 'gte_stclmv': 108, 'gte_nclip': 108, 'gte_stopz': 108, 'gte_stsxy3c': 108, 'gte_stsxy3_ft3': 79, 'gte_rtir': 75, 'gte_ldclmv': 72}
asm-bearing macro definitions: 314 (20 names, 3 with >1 text) kinds {'gte': 150, 'instruction': 9, 'launder': 154, 'barrier': 1}
asm kinds: {'asm-body/direct': 13, 'barrier/direct': 1929, 'barrier/via-macro': 2, 'gte/direct': 200, 'gte/via-macro': 6658, 'gte-lever/direct': 362, 'gte-lever/via-macro': 100, 'gte-unsigned/direct': 3, 'instruction/direct': 214, 'instruction/via-macro': 22, 'keepalive/direct': 645, 'launder/direct': 1735, 'launder/via-macro': 66, 'verbatim-body/direct': 2682}
instruction mnemonics: {'la': 142, 'addu': 23, 'addiu': 22, 'RTP_SND': 22, '.section': 7, 'lui': 4, 'move': 4, 'lh': 3, 'and': 2, 'mult': 1, 'mfhi': 1, 'sll': 1, 'li': 1, 'lw': 1, 'nop': 1, 'srl': 1}
gte mnemonics: {'gte_ldv0': 757, 'gte_stlvnl': 593, 'gte_stsxy': 447, 'gte_rtps': 437, 'gte_stflg': 415, 'gte_rtpt': 352, 'gte_SetRotMatrix': 246, 'gte_stsxy3': 236, 'gte_rtv0tr': 228, 'gte_SetTransMatrix': 226, 'gte_ldv3c': 184, 'gte_ldv3': 177, 'gte_ldrgb': 164, 'gte_stsv': 161, 'lwc2': 159, 'gte_stsz4': 149, 'gte_stsz3': 147, 'gte_stszotz': 134, 'gte_ldIR0z': 134, 'gte_ldIRGB': 134, 'gte_dpcl': 134, 'gte_stORGB': 134, 'gte_stsxy3_f3': 111, 'gte_nclip': 108, 'gte_stopz': 108, 'gte_stsxy3c': 108, 'gte_stclmv': 108, 'gte_stsxy3_ft3': 79, 'gte_rtir': 75, 'gte_ldclmv': 72}
asm-bearing macro definitions: 314 (20 names, 3 with >1 text) kinds {'gte': 150, 'launder': 154, 'instruction': 9, 'barrier': 1}
controls (R39):
src/800.c func_800226C0 pins got 14 expected 45 N-A
src/shared/ov/func_80178004.h pins got 8 expected 26 N-A
ov_SC03_006 func_80184034 bare-name pins got 0 expected 3 N-A
engine_prelude.h asm sites (a macro definition only) got 0 expected 0 OK
elapsed 29.7 s
elapsed 31.0 s
+177 -177
View File
@@ -1,7 +1,7 @@
{
"head": "321b540e7",
"head": "2a4f28f83",
"stamp": "15956e4a96c4",
"generated": "2026-09-10 18:08",
"generated": "2026-09-10 18:13",
"aliases": [
"main",
"ov_SC03_014",
@@ -21,206 +21,206 @@
"main": {
"objects": 85,
"identical": 85,
"seconds": 8.127000000000002,
"mean_s": 0.096
"seconds": 7.8809999999999985,
"mean_s": 0.093
},
"ov_SC03_014": {
"objects": 32,
"identical": 32,
"seconds": 5.461000000000001,
"mean_s": 0.171
"seconds": 5.423000000000001,
"mean_s": 0.169
},
"ov_SC03_015": {
"objects": 32,
"identical": 32,
"seconds": 5.338000000000001,
"mean_s": 0.167
"seconds": 5.321999999999999,
"mean_s": 0.166
},
"ov_SC04_011": {
"objects": 28,
"identical": 28,
"seconds": 4.664000000000001,
"mean_s": 0.167
"seconds": 4.66,
"mean_s": 0.166
}
},
"per_object_seconds": {
"build/src/800.o": 0.863,
"build/src/800_b.o": 0.119,
"build/src/800_b_2.o": 0.357,
"build/src/800_b_o0a.o": 0.083,
"build/src/800_c.o": 0.227,
"build/src/800b2.o": 0.085,
"build/src/apicard1.o": 0.076,
"build/src/apicard2.o": 0.082,
"build/src/apicard3.o": 0.078,
"build/src/apicard4.o": 0.079,
"build/src/apicard5.o": 0.117,
"build/src/apicard6.o": 0.094,
"build/src/apicard7.o": 0.108,
"build/src/boot.o": 0.115,
"build/src/gap.o": 0.088,
"build/src/800.o": 0.854,
"build/src/800_b.o": 0.083,
"build/src/800_b_2.o": 0.338,
"build/src/800_b_o0a.o": 0.077,
"build/src/800_c.o": 0.215,
"build/src/800b2.o": 0.113,
"build/src/apicard1.o": 0.077,
"build/src/apicard2.o": 0.074,
"build/src/apicard3.o": 0.081,
"build/src/apicard4.o": 0.068,
"build/src/apicard5.o": 0.104,
"build/src/apicard6.o": 0.085,
"build/src/apicard7.o": 0.082,
"build/src/boot.o": 0.13,
"build/src/gap.o": 0.067,
"build/src/libapi1.o": 0.085,
"build/src/libapi2.o": 0.069,
"build/src/libc2_1.o": 0.079,
"build/src/libc2_2.o": 0.074,
"build/src/libcd1.o": 0.082,
"build/src/libcd2.o": 0.069,
"build/src/libetc.o": 0.071,
"build/src/libgpu.o": 0.091,
"build/src/libgpu2.o": 0.088,
"build/src/libgs1.o": 0.078,
"build/src/libgs2.o": 0.073,
"build/src/libgs3.o": 0.069,
"build/src/libgs4.o": 0.079,
"build/src/libgs5.o": 0.079,
"build/src/libgs6.o": 0.097,
"build/src/libgs7.o": 0.074,
"build/src/libgs8.o": 0.085,
"build/src/libgte1.o": 0.079,
"build/src/libgte10.o": 0.078,
"build/src/libgte11.o": 0.078,
"build/src/libgte12.o": 0.076,
"build/src/libgte13.o": 0.078,
"build/src/libgte14.o": 0.073,
"build/src/libgte15.o": 0.076,
"build/src/libgte16.o": 0.078,
"build/src/libgte17.o": 0.079,
"build/src/libgte18.o": 0.083,
"build/src/libgte19.o": 0.078,
"build/src/libgte2.o": 0.077,
"build/src/libgte20.o": 0.075,
"build/src/libgte21.o": 0.074,
"build/src/libgte22.o": 0.076,
"build/src/libgte23.o": 0.071,
"build/src/libgte24.o": 0.081,
"build/src/libgte25.o": 0.078,
"build/src/libgte26.o": 0.083,
"build/src/libgte27.o": 0.075,
"build/src/libgte28.o": 0.079,
"build/src/libgte29.o": 0.078,
"build/src/libgte3.o": 0.077,
"build/src/libgte30.o": 0.081,
"build/src/libgte4.o": 0.078,
"build/src/libgte5.o": 0.074,
"build/src/libgte6.o": 0.089,
"build/src/libgte7.o": 0.086,
"build/src/libgte8.o": 0.079,
"build/src/libgte9.o": 0.084,
"build/src/libmcrd1.o": 0.091,
"build/src/libmcrd2.o": 0.087,
"build/src/libpad1.o": 0.078,
"build/src/libpad2.o": 0.092,
"build/src/sgap.o": 0.075,
"build/src/sgap_2.o": 0.076,
"build/src/sgap_3.o": 0.085,
"build/src/sgap_4.o": 0.086,
"build/src/sgap_5.o": 0.079,
"build/src/sgap_6.o": 0.077,
"build/src/sgap_8.o": 0.08,
"build/src/snd1.o": 0.085,
"build/src/libapi2.o": 0.074,
"build/src/libc2_1.o": 0.074,
"build/src/libc2_2.o": 0.07,
"build/src/libcd1.o": 0.083,
"build/src/libcd2.o": 0.074,
"build/src/libetc.o": 0.082,
"build/src/libgpu.o": 0.074,
"build/src/libgpu2.o": 0.084,
"build/src/libgs1.o": 0.073,
"build/src/libgs2.o": 0.076,
"build/src/libgs3.o": 0.064,
"build/src/libgs4.o": 0.066,
"build/src/libgs5.o": 0.073,
"build/src/libgs6.o": 0.092,
"build/src/libgs7.o": 0.078,
"build/src/libgs8.o": 0.069,
"build/src/libgte1.o": 0.08,
"build/src/libgte10.o": 0.076,
"build/src/libgte11.o": 0.081,
"build/src/libgte12.o": 0.079,
"build/src/libgte13.o": 0.079,
"build/src/libgte14.o": 0.078,
"build/src/libgte15.o": 0.074,
"build/src/libgte16.o": 0.074,
"build/src/libgte17.o": 0.082,
"build/src/libgte18.o": 0.076,
"build/src/libgte19.o": 0.07,
"build/src/libgte2.o": 0.071,
"build/src/libgte20.o": 0.077,
"build/src/libgte21.o": 0.072,
"build/src/libgte22.o": 0.075,
"build/src/libgte23.o": 0.075,
"build/src/libgte24.o": 0.077,
"build/src/libgte25.o": 0.082,
"build/src/libgte26.o": 0.073,
"build/src/libgte27.o": 0.079,
"build/src/libgte28.o": 0.077,
"build/src/libgte29.o": 0.079,
"build/src/libgte3.o": 0.084,
"build/src/libgte30.o": 0.09,
"build/src/libgte4.o": 0.073,
"build/src/libgte5.o": 0.082,
"build/src/libgte6.o": 0.073,
"build/src/libgte7.o": 0.078,
"build/src/libgte8.o": 0.073,
"build/src/libgte9.o": 0.082,
"build/src/libmcrd1.o": 0.089,
"build/src/libmcrd2.o": 0.076,
"build/src/libpad1.o": 0.084,
"build/src/libpad2.o": 0.09,
"build/src/sgap.o": 0.08,
"build/src/sgap_2.o": 0.07,
"build/src/sgap_3.o": 0.086,
"build/src/sgap_4.o": 0.082,
"build/src/sgap_5.o": 0.076,
"build/src/sgap_6.o": 0.075,
"build/src/sgap_8.o": 0.083,
"build/src/snd1.o": 0.081,
"build/src/snd10.o": 0.076,
"build/src/snd11.o": 0.075,
"build/src/snd12.o": 0.072,
"build/src/snd2.o": 0.083,
"build/src/snd3.o": 0.079,
"build/src/snd11.o": 0.072,
"build/src/snd12.o": 0.082,
"build/src/snd2.o": 0.085,
"build/src/snd3.o": 0.073,
"build/src/snd4.o": 0.076,
"build/src/snd5.o": 0.08,
"build/src/snd6.o": 0.087,
"build/src/snd7.o": 0.084,
"build/src/snd8.o": 0.074,
"build/src/snd9.o": 0.086,
"build/src/snd5.o": 0.074,
"build/src/snd6.o": 0.08,
"build/src/snd7.o": 0.077,
"build/src/snd8.o": 0.072,
"build/src/snd9.o": 0.082,
"build/src/ov_SC03_014/ov_SC03_014.o": 0.154,
"build/src/ov_SC03_014/ov_SC03_014_after.o": 0.592,
"build/src/ov_SC03_014/ov_SC03_014_jr_8012ACE0.o": 0.454,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135888.o": 0.076,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135A4C.o": 0.076,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135D20.o": 0.146,
"build/src/ov_SC03_014/ov_SC03_014_jr_801380E0.o": 0.189,
"build/src/ov_SC03_014/ov_SC03_014_jr_8013C98C.o": 0.139,
"build/src/ov_SC03_014/ov_SC03_014_jr_8013F350.o": 0.095,
"build/src/ov_SC03_014/ov_SC03_014_after.o": 0.594,
"build/src/ov_SC03_014/ov_SC03_014_jr_8012ACE0.o": 0.448,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135888.o": 0.072,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135A4C.o": 0.073,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135D20.o": 0.156,
"build/src/ov_SC03_014/ov_SC03_014_jr_801380E0.o": 0.175,
"build/src/ov_SC03_014/ov_SC03_014_jr_8013C98C.o": 0.135,
"build/src/ov_SC03_014/ov_SC03_014_jr_8013F350.o": 0.092,
"build/src/ov_SC03_014/ov_SC03_014_jr_8013FFD8.o": 0.086,
"build/src/ov_SC03_014/ov_SC03_014_jr_80140608.o": 0.225,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015444C.o": 0.091,
"build/src/ov_SC03_014/ov_SC03_014_jr_80154C24.o": 0.203,
"build/src/ov_SC03_014/ov_SC03_014_jr_801588CC.o": 0.114,
"build/src/ov_SC03_014/ov_SC03_014_jr_80140608.o": 0.207,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015444C.o": 0.088,
"build/src/ov_SC03_014/ov_SC03_014_jr_80154C24.o": 0.19,
"build/src/ov_SC03_014/ov_SC03_014_jr_801588CC.o": 0.123,
"build/src/ov_SC03_014/ov_SC03_014_jr_80159C84.o": 0.08,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015A3C8.o": 0.086,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015AE2C.o": 0.113,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015C32C.o": 0.549,
"build/src/ov_SC03_014/ov_SC03_014_jr_8016AB6C.o": 0.308,
"build/src/ov_SC03_014/ov_SC03_014_jr_80171B4C.o": 0.116,
"build/src/ov_SC03_014/ov_SC03_014_jr_801734BC.o": 0.229,
"build/src/ov_SC03_014/ov_SC03_014_jr_801789AC.o": 0.07,
"build/src/ov_SC03_014/ov_SC03_014_jr_80178D40.o": 0.126,
"build/src/ov_SC03_014/ov_SC03_014_jr_8017A4AC.o": 0.083,
"build/src/ov_SC03_014/ov_SC03_014_jr_8017AE2C.o": 0.196,
"build/src/ov_SC03_014/ov_SC03_014_jr_8017EB7C.o": 0.221,
"build/src/ov_SC03_014/ov_SC03_014_jr_80184440.o": 0.057,
"build/src/ov_SC03_014/ov_SC03_014_jr_801848E4.o": 0.306,
"build/src/ov_SC03_014/ov_SC03_014_o0b.o": 0.065,
"build/src/ov_SC03_014/ov_SC03_014_o0c.o": 0.069,
"build/src/ov_SC03_014/ov_SC03_014_o0d.o": 0.065,
"build/src/ov_SC03_014/ov_SC03_014_o0e.o": 0.082,
"build/src/ov_SC03_015/ov_SC03_015.o": 0.153,
"build/src/ov_SC03_015/ov_SC03_015_after.o": 0.6,
"build/src/ov_SC03_015/ov_SC03_015_jr_8012ACE0.o": 0.432,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015A3C8.o": 0.082,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015AE2C.o": 0.112,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015C32C.o": 0.546,
"build/src/ov_SC03_014/ov_SC03_014_jr_8016AB6C.o": 0.293,
"build/src/ov_SC03_014/ov_SC03_014_jr_80171B4C.o": 0.12,
"build/src/ov_SC03_014/ov_SC03_014_jr_801734BC.o": 0.24,
"build/src/ov_SC03_014/ov_SC03_014_jr_801789AC.o": 0.072,
"build/src/ov_SC03_014/ov_SC03_014_jr_80178D40.o": 0.119,
"build/src/ov_SC03_014/ov_SC03_014_jr_8017A4AC.o": 0.074,
"build/src/ov_SC03_014/ov_SC03_014_jr_8017AE2C.o": 0.193,
"build/src/ov_SC03_014/ov_SC03_014_jr_8017EB7C.o": 0.238,
"build/src/ov_SC03_014/ov_SC03_014_jr_80184440.o": 0.061,
"build/src/ov_SC03_014/ov_SC03_014_jr_801848E4.o": 0.32,
"build/src/ov_SC03_014/ov_SC03_014_o0b.o": 0.072,
"build/src/ov_SC03_014/ov_SC03_014_o0c.o": 0.07,
"build/src/ov_SC03_014/ov_SC03_014_o0d.o": 0.066,
"build/src/ov_SC03_014/ov_SC03_014_o0e.o": 0.072,
"build/src/ov_SC03_015/ov_SC03_015.o": 0.134,
"build/src/ov_SC03_015/ov_SC03_015_after.o": 0.575,
"build/src/ov_SC03_015/ov_SC03_015_jr_8012ACE0.o": 0.441,
"build/src/ov_SC03_015/ov_SC03_015_jr_80135888.o": 0.063,
"build/src/ov_SC03_015/ov_SC03_015_jr_80135A4C.o": 0.056,
"build/src/ov_SC03_015/ov_SC03_015_jr_80135D20.o": 0.135,
"build/src/ov_SC03_015/ov_SC03_015_jr_801380E0.o": 0.177,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013C98C.o": 0.122,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013F350.o": 0.089,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013FFD8.o": 0.072,
"build/src/ov_SC03_015/ov_SC03_015_jr_80140608.o": 0.204,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015444C.o": 0.087,
"build/src/ov_SC03_015/ov_SC03_015_jr_80135A4C.o": 0.061,
"build/src/ov_SC03_015/ov_SC03_015_jr_80135D20.o": 0.13,
"build/src/ov_SC03_015/ov_SC03_015_jr_801380E0.o": 0.182,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013C98C.o": 0.137,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013F350.o": 0.087,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013FFD8.o": 0.087,
"build/src/ov_SC03_015/ov_SC03_015_jr_80140608.o": 0.206,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015444C.o": 0.09,
"build/src/ov_SC03_015/ov_SC03_015_jr_80154C24.o": 0.193,
"build/src/ov_SC03_015/ov_SC03_015_jr_801588CC.o": 0.102,
"build/src/ov_SC03_015/ov_SC03_015_jr_80159C84.o": 0.076,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015A3C8.o": 0.077,
"build/src/ov_SC03_015/ov_SC03_015_jr_801588CC.o": 0.115,
"build/src/ov_SC03_015/ov_SC03_015_jr_80159C84.o": 0.082,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015A3C8.o": 0.087,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015AE2C.o": 0.109,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015C32C.o": 0.528,
"build/src/ov_SC03_015/ov_SC03_015_jr_8016AB6C.o": 0.319,
"build/src/ov_SC03_015/ov_SC03_015_jr_80171B4C.o": 0.121,
"build/src/ov_SC03_015/ov_SC03_015_jr_801734BC.o": 0.23,
"build/src/ov_SC03_015/ov_SC03_015_jr_801789AC.o": 0.069,
"build/src/ov_SC03_015/ov_SC03_015_jr_80178D40.o": 0.123,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017A4AC.o": 0.075,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017AE2C.o": 0.197,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017EB7C.o": 0.242,
"build/src/ov_SC03_015/ov_SC03_015_jr_80184440.o": 0.065,
"build/src/ov_SC03_015/ov_SC03_015_jr_801848E4.o": 0.322,
"build/src/ov_SC03_015/ov_SC03_015_o0b.o": 0.078,
"build/src/ov_SC03_015/ov_SC03_015_o0c.o": 0.067,
"build/src/ov_SC03_015/ov_SC03_015_o0d.o": 0.068,
"build/src/ov_SC03_015/ov_SC03_015_o0e.o": 0.087,
"build/src/ov_SC04_011/ov_SC04_011.o": 0.144,
"build/src/ov_SC04_011/ov_SC04_011_after.o": 0.487,
"build/src/ov_SC04_011/ov_SC04_011_jr_8012ACE0.o": 0.396,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135888.o": 0.065,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135A4C.o": 0.064,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135D20.o": 0.132,
"build/src/ov_SC04_011/ov_SC04_011_jr_801380E0.o": 0.173,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013C98C.o": 0.127,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013F350.o": 0.086,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013FFD8.o": 0.082,
"build/src/ov_SC04_011/ov_SC04_011_jr_80140608.o": 0.21,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015444C.o": 0.088,
"build/src/ov_SC04_011/ov_SC04_011_jr_80154C24.o": 0.203,
"build/src/ov_SC04_011/ov_SC04_011_jr_801588CC.o": 0.111,
"build/src/ov_SC04_011/ov_SC04_011_jr_80159C84.o": 0.075,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015A3C8.o": 0.077,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015AE2C.o": 0.112,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015C32C.o": 0.418,
"build/src/ov_SC04_011/ov_SC04_011_jr_8016AB6C.o": 0.261,
"build/src/ov_SC04_011/ov_SC04_011_jr_80171B4C.o": 0.122,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015C32C.o": 0.53,
"build/src/ov_SC03_015/ov_SC03_015_jr_8016AB6C.o": 0.31,
"build/src/ov_SC03_015/ov_SC03_015_jr_80171B4C.o": 0.117,
"build/src/ov_SC03_015/ov_SC03_015_jr_801734BC.o": 0.231,
"build/src/ov_SC03_015/ov_SC03_015_jr_801789AC.o": 0.07,
"build/src/ov_SC03_015/ov_SC03_015_jr_80178D40.o": 0.117,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017A4AC.o": 0.079,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017AE2C.o": 0.193,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017EB7C.o": 0.226,
"build/src/ov_SC03_015/ov_SC03_015_jr_80184440.o": 0.058,
"build/src/ov_SC03_015/ov_SC03_015_jr_801848E4.o": 0.32,
"build/src/ov_SC03_015/ov_SC03_015_o0b.o": 0.071,
"build/src/ov_SC03_015/ov_SC03_015_o0c.o": 0.068,
"build/src/ov_SC03_015/ov_SC03_015_o0d.o": 0.065,
"build/src/ov_SC03_015/ov_SC03_015_o0e.o": 0.088,
"build/src/ov_SC04_011/ov_SC04_011.o": 0.143,
"build/src/ov_SC04_011/ov_SC04_011_after.o": 0.488,
"build/src/ov_SC04_011/ov_SC04_011_jr_8012ACE0.o": 0.398,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135888.o": 0.064,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135A4C.o": 0.065,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135D20.o": 0.135,
"build/src/ov_SC04_011/ov_SC04_011_jr_801380E0.o": 0.168,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013C98C.o": 0.129,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013F350.o": 0.092,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013FFD8.o": 0.076,
"build/src/ov_SC04_011/ov_SC04_011_jr_80140608.o": 0.209,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015444C.o": 0.083,
"build/src/ov_SC04_011/ov_SC04_011_jr_80154C24.o": 0.195,
"build/src/ov_SC04_011/ov_SC04_011_jr_801588CC.o": 0.104,
"build/src/ov_SC04_011/ov_SC04_011_jr_80159C84.o": 0.074,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015A3C8.o": 0.079,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015AE2C.o": 0.106,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015C32C.o": 0.421,
"build/src/ov_SC04_011/ov_SC04_011_jr_8016AB6C.o": 0.255,
"build/src/ov_SC04_011/ov_SC04_011_jr_80171B4C.o": 0.109,
"build/src/ov_SC04_011/ov_SC04_011_jr_801734BC.o": 0.203,
"build/src/ov_SC04_011/ov_SC04_011_jr_801789AC.o": 0.07,
"build/src/ov_SC04_011/ov_SC04_011_jr_80178D40.o": 0.106,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017A4AC.o": 0.08,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017AE2C.o": 0.122,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017D494.o": 0.525,
"build/src/ov_SC04_011/ov_SC04_011_o0b.o": 0.06,
"build/src/ov_SC04_011/ov_SC04_011_o0c.o": 0.065
"build/src/ov_SC04_011/ov_SC04_011_jr_801789AC.o": 0.072,
"build/src/ov_SC04_011/ov_SC04_011_jr_80178D40.o": 0.118,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017A4AC.o": 0.083,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017AE2C.o": 0.126,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017D494.o": 0.528,
"build/src/ov_SC04_011/ov_SC04_011_o0b.o": 0.067,
"build/src/ov_SC04_011/ov_SC04_011_o0c.o": 0.07
},
"ok": true,
"seconds": 2.7
File diff suppressed because one or more lines are too long
@@ -100,12 +100,17 @@ def related_bodies(tu, fn, target_text, alias, top=6, max_lines=600):
for r in recs:
if r.get("form") == "def" and r.get("name") == fn:
body = txt[ls[r["line"] - 1]:ls[r["end"]]] if r["end"] < len(ls) else txt[ls[r["line"] - 1]:]
if "!FAKE" not in body and "__asm__ __volatile__" not in body:
# SAME NAME IS NOT SAME FUNCTION: overlays reuse addresses (S103, agent c43 — the func_80185578 listed
# here from ov_SC03_014 was a one-line different function). Evidence required: a shared callee/global
# and a comparable size.
n_t, n_b = target_text.count("\n") or 1, body.count("\n") or 1
shares = (set(SYM.findall(body)) - {fn}) & want
if "!FAKE" not in body and "__asm__ __volatile__" not in body and shares and 0.6 <= n_b / n_t <= 1.6:
same.append((rel, r["line"], body))
break
head = []
for rel, line, body in same:
head += [f"=== {fn} ALREADY LEVER-FREE in {rel}:{line} — a variant of your function: port it (R71) ===", body.rstrip(), ""]
head += [f"=== {fn} ALREADY LEVER-FREE in {rel}:{line} — same name, shares symbols and size: PROBABLY a variant; diff it before porting (R71) ===", body.rstrip(), ""]
seen, out = set(), head + [f"=== lever-free bodies in {alias} sharing a callee or global with {fn} "
f"({len(cands)} found; top {top} by shared symbols) — read them for the SHAPE ==="]
for _, n, name, rel, line, shared, body in cands:
+1
View File
@@ -47,3 +47,4 @@ date milestone head sites_AB pins asm bodies_AB distinct_AB marked unmarked gte_
2026-09-10 S103: c36 + c35 (four ov_SC07_006/ov_SC06_010 classes, 39 bodies); R19 reads cast arity dd5e44c24 12481 7186 5295 3260 1207 12481 0 462 314 1590 50 7680 445 76
2026-09-10 S103: extern-variant re-propagation (97), R19 cast regen (8 classes), c39 + c41 + c34 + c32 closes 7d5964b27 12033 6926 5107 3090 1164 12033 0 462 314 1590 50 7688 445 76
2026-09-10 S103: c38 + c40 (four tier classes, 30 bodies) 321b540e7 12003 6910 5093 3060 1160 12003 0 462 314 1590 50 7688 445 76
2026-09-10 S103: c42 func_80186A8C + func_80182058 (10 bodies) 2a4f28f83 11988 6900 5088 3050 1158 11988 0 462 314 1590 50 7688 445 76
1 date milestone head sites_AB pins asm bodies_AB distinct_AB marked unmarked gte_levers per_tu_asm_macros class_C class_D class_E class_F class_G
47 2026-09-10 S103: c36 + c35 (four ov_SC07_006/ov_SC06_010 classes, 39 bodies); R19 reads cast arity dd5e44c24 12481 7186 5295 3260 1207 12481 0 462 314 1590 50 7680 445 76
48 2026-09-10 S103: extern-variant re-propagation (97), R19 cast regen (8 classes), c39 + c41 + c34 + c32 closes 7d5964b27 12033 6926 5107 3090 1164 12033 0 462 314 1590 50 7688 445 76
49 2026-09-10 S103: c38 + c40 (four tier classes, 30 bodies) 321b540e7 12003 6910 5093 3060 1160 12003 0 462 314 1590 50 7688 445 76
50 2026-09-10 S103: c42 func_80186A8C + func_80182058 (10 bodies) 2a4f28f83 11988 6900 5088 3050 1158 11988 0 462 314 1590 50 7688 445 76
+4 -1
View File
@@ -93,6 +93,7 @@ counted, not marked). E, F and G belong to the canonical type layer and are the
| 2026-09-10 | S103: c36 + c35 (four ov_SC07_006/ov_SC06_010 classes, 39 bodies); R19 reads cast arity | 7186 | 5295 | **12481** | 3260 | 1207 | 462 | 314 | 1590 | 50 | 7680 | 445 | 76 | `dd5e44c24` |
| 2026-09-10 | S103: extern-variant re-propagation (97), R19 cast regen (8 classes), c39 + c41 + c34 + c32 closes | 6926 | 5107 | **12033** | 3090 | 1164 | 462 | 314 | 1590 | 50 | 7688 | 445 | 76 | `7d5964b27` |
| 2026-09-10 | S103: c38 + c40 (four tier classes, 30 bodies) | 6910 | 5093 | **12003** | 3060 | 1160 | 462 | 314 | 1590 | 50 | 7688 | 445 | 76 | `321b540e7` |
| 2026-09-10 | S103: c42 func_80186A8C + func_80182058 (10 bodies) | 6900 | 5088 | **11988** | 3050 | 1158 | 462 | 314 | 1590 | 50 | 7688 | 445 | 76 | `2a4f28f83` |
### The campaign — every batch, from the ledger (derived on every render)
@@ -264,7 +265,9 @@ counted, not marked). E, F and G belong to the canonical type layer and are the
| `c38p` | 2026-09-10 | E | 0 | 0 | 0 | 14 | 14 |
| `c40` | 2026-09-10 | E | 0 | 0 | 0 | 2 | 2 |
| `c40p` | 2026-09-10 | E | 0 | 0 | 0 | 12 | 12 |
| **total** | | | **17,119** | **20,778** | **283** | **22,417** | **9,676** |
| `c42` | 2026-09-10 | E | 0 | 0 | 0 | 3 | 2 |
| `c42p` | 2026-09-10 | E | 0 | 0 | 0 | 12 | 8 |
| **total** | | | **17,119** | **20,778** | **283** | **22,432** | **9,686** |
*Generated by `tools/lever_progress.py --render` from `.run/P36/census/lever_census.json` and `.run/P36/delever/ledger.jsonl`; the series lives in `docs/lever-progress.tsv` (R75: published numbers are generated, never typed).*
+10
View File
@@ -1694,6 +1694,16 @@ accumulate here as the phase produces them.**
merge; and a hand-rotated `if … do … while` written as a real `for` loop, whose `NOTE_INSN_LOOP_VTOP`
(`jump.c:2306`) makes reorg's `mostly_true_jump` predict taken (`reorg.c:1364-1372`) and fill the slot from the target.
Tools: `cc1_dumps_tu.sh` gains `-dd` (`.dbr`); METHOD notes `--keep`'s path is the LAST output line.
- **S103 — c42: `func_80186A8C` (ov_SC03_091, 8 → 0; 4/4) and `func_80182058` (ov_SC03_001, 10 → 0; 4/4) CLOSED —
both through jump2's cross-jump in ways METHOD did not yet list.** func_80186A8C: the `- 0x4000` folded into both arms
of the sign pick and `t` passed bare — `t` set in two blocks takes `$5` by copy preference, and cross-jump merges the two
identical arm tails into the target's single join instruction (argument registers load in order on MIPS,
`calls.c:1860-1881`); func_80182058: the case failures sent to one labelled `return 0` — cross-jump lowers its match
threshold for a block at a label (`jump.c:2406-2410`) or right after a conditional jump past it (`:2516-2519`), so which
block SURVIVES the merge is decided by where the labels are; the tree's "load-bearing zero-byte cross-jump barrier"
comment was refuted. METHOD note: for a cross-jump residual, find which label survives in `.jump2`, yours and the tree's.
- **S103 — the first MINIMUM-LEVER draw: c46 on `func_80177B5C`** (c19's plain body at 2; goal: 0 with the fewest marked
levers, ideally one, instead of 23 per copy × 132).
- **S103 — WHERE THE RESIDUE IS (measured at 12,003 sites): ~70% of the remaining lever weight sits in 9 classes of
≥100 copies, every one already read by an agent with a written reading** (approx. copies × sites/body:
func_8013D9B0 125×34 — c17 15 plain, the GTE-macro question; func_80177B5C 132×23 — c19 2, one `or` late;
+6 -14
View File
@@ -4283,15 +4283,11 @@ void func_8017F4DC(s32 a0) {
s32 t;
s32 r;
if (ang >= 0) {
t = -(ang << 4);
t = -(ang << 4) - 0x4000;
} else {
t = ang << 4;
}
{
register s32 av __asm__("$5"); // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B tus9)
av = t - 0x4000;
func_8012B178(a0, av);
t = (ang << 4) - 0x4000;
}
func_8012B178(a0, t);
r = ((s32 (*)(s32))func_8012CBA4)(a0);
if (r & 0x8000) {
*(u16 *)(a0 + 0x34) = 2;
@@ -4328,15 +4324,11 @@ void func_8017F4DC(s32 a0) {
*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) =
*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) + d;
if (ang >= 0) {
t = -(ang << 4);
t = -(ang << 4) - 0x4000;
} else {
t = ang << 4;
}
{
register s32 av __asm__("$5"); // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B tus9)
av = t - 0x4000;
func_8012B178(a0, av);
t = (ang << 4) - 0x4000;
}
func_8012B178(a0, t);
if ((((s32 (*)(s32))func_8012CBA4)(a0) & 0x2000) == 0) {
func_8012ADE4((u8 *)a0);
*(u16 *)(a0 + 0x34) = 2;
+14 -18
View File
@@ -7329,11 +7329,6 @@ s32 func_80182058(void *a0)
u16 st;
if (func_8012BD14(*(s32 *)((s32)a0 + 0x64)) > 0x4000) {
/* LOAD-BEARING zero-byte cross-jump barrier (cookbook §5a).
* Without it gcc's find_cross_jump merges this `move v0,0; j epi`
* tail with the identical case-2 failure tail -> 58 ins instead of
* 60, and the case-2 `beq` then loses its delay-slot fill. */
__asm__ __volatile__(""); // !FAKE: barrier — NEEDED DIFFERS (P36 rung B tus7)
return 0;
}
@@ -7344,13 +7339,13 @@ s32 func_80182058(void *a0)
*(s16 *)((s32)p + 0x2) = 8;
break;
case 2:
if (*(u16 *)((s32)p + 0x34) != 1) {
return 0;
if (*(u16 *)((s32)p + 0x34) == 1) {
goto hit;
}
goto hit;
goto fail;
case 4:
if (*(u16 *)((s32)p + 0x34) != 0) {
return 0;
goto fail;
}
hit:
D_801EEAF0 = st;
@@ -7358,6 +7353,9 @@ s32 func_80182058(void *a0)
*(s16 *)(*(s32 *)((s32)a0 + 0x64) + 0x2) = 10;
break;
default:
fail: /* the case-2/case-4 failures share this one `return 0`: a return
* falling out of a conditional (as the first one does) is what
* jump2's cross-jump would merge the early return into */
return 0;
}
@@ -8428,11 +8426,6 @@ s32 func_801834C0(void *a0)
u16 st;
if (func_8012BD14(*(s32 *)((s32)a0 + 0x64)) > 0x4000) {
/* LOAD-BEARING zero-byte cross-jump barrier (cookbook §5a).
* Without it gcc's find_cross_jump merges this `move v0,0; j epi`
* tail with the identical case-2 failure tail -> 58 ins instead of
* 60, and the case-2 `beq` then loses its delay-slot fill. */
__asm__ __volatile__(""); // !FAKE: barrier — NEEDED DIFFERS (P36 rung B tus7)
return 0;
}
@@ -8443,13 +8436,13 @@ s32 func_801834C0(void *a0)
*(s16 *)((s32)p + 0x2) = 8;
break;
case 2:
if (*(u16 *)((s32)p + 0x34) != 1) {
return 0;
if (*(u16 *)((s32)p + 0x34) == 1) {
goto hit;
}
goto hit;
goto fail;
case 4:
if (*(u16 *)((s32)p + 0x34) != 0) {
return 0;
goto fail;
}
hit:
D_801EEB00 = st;
@@ -8457,6 +8450,9 @@ s32 func_801834C0(void *a0)
*(s16 *)(*(s32 *)((s32)a0 + 0x64) + 0x2) = 10;
break;
default:
fail: /* the case-2/case-4 failures share this one `return 0`: a return
* falling out of a conditional (as the first one does) is what
* jump2's cross-jump would merge the early return into */
return 0;
}
+6 -14
View File
@@ -6876,15 +6876,11 @@ void func_80185BE4(s32 a0) {
s32 t;
s32 r;
if (ang >= 0) {
t = -(ang << 4);
t = -(ang << 4) - 0x4000;
} else {
t = ang << 4;
}
{
register s32 av __asm__("$5"); // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B tus9)
av = t - 0x4000;
func_8012B178(a0, av);
t = (ang << 4) - 0x4000;
}
func_8012B178(a0, t);
r = ((s32 (*)(s32))func_8012CBA4)(a0);
if (r & 0x8000) {
*(u16 *)(a0 + 0x34) = 2;
@@ -6921,15 +6917,11 @@ void func_80185BE4(s32 a0) {
*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) =
*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) + d;
if (ang >= 0) {
t = -(ang << 4);
t = -(ang << 4) - 0x4000;
} else {
t = ang << 4;
}
{
register s32 av __asm__("$5"); // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B tus9)
av = t - 0x4000;
func_8012B178(a0, av);
t = (ang << 4) - 0x4000;
}
func_8012B178(a0, t);
if ((((s32 (*)(s32))func_8012CBA4)(a0) & 0x2000) == 0) {
func_8012ADE4((u8 *)a0);
*(u16 *)(a0 + 0x34) = 2;
+6 -14
View File
@@ -5210,15 +5210,11 @@ void func_80186A8C(s32 a0) {
s32 t;
s32 r;
if (ang >= 0) {
t = -(ang << 4);
t = -(ang << 4) - 0x4000;
} else {
t = ang << 4;
}
{
register s32 av __asm__("$5"); // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B tus9)
av = t - 0x4000;
func_8012B178(a0, av);
t = (ang << 4) - 0x4000;
}
func_8012B178(a0, t);
r = ((s32 (*)(s32))func_8012CBA4)(a0);
if (r & 0x8000) {
*(u16 *)(a0 + 0x34) = 2;
@@ -5255,15 +5251,11 @@ void func_80186A8C(s32 a0) {
*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) =
*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) + d;
if (ang >= 0) {
t = -(ang << 4);
t = -(ang << 4) - 0x4000;
} else {
t = ang << 4;
}
{
register s32 av __asm__("$5"); // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B tus9)
av = t - 0x4000;
func_8012B178(a0, av);
t = (ang << 4) - 0x4000;
}
func_8012B178(a0, t);
if ((((s32 (*)(s32))func_8012CBA4)(a0) & 0x2000) == 0) {
func_8012ADE4((u8 *)a0);
*(u16 *)(a0 + 0x34) = 2;
+6 -14
View File
@@ -5093,15 +5093,11 @@ void func_80180864(s32 a0) {
s32 t;
s32 r;
if (ang >= 0) {
t = -(ang << 4);
t = -(ang << 4) - 0x4000;
} else {
t = ang << 4;
}
{
register s32 av __asm__("$5"); // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B tus9)
av = t - 0x4000;
func_8012B178(a0, av);
t = (ang << 4) - 0x4000;
}
func_8012B178(a0, t);
r = ((s32 (*)(s32))func_8012CBA4)(a0);
if (r & 0x8000) {
*(u16 *)(a0 + 0x34) = 2;
@@ -5138,15 +5134,11 @@ void func_80180864(s32 a0) {
*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) =
*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) + d;
if (ang >= 0) {
t = -(ang << 4);
t = -(ang << 4) - 0x4000;
} else {
t = ang << 4;
}
{
register s32 av __asm__("$5"); // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B tus9)
av = t - 0x4000;
func_8012B178(a0, av);
t = (ang << 4) - 0x4000;
}
func_8012B178(a0, t);
if ((((s32 (*)(s32))func_8012CBA4)(a0) & 0x2000) == 0) {
func_8012ADE4((u8 *)a0);
*(u16 *)(a0 + 0x34) = 2;
+6 -14
View File
@@ -4379,15 +4379,11 @@ void func_8018106C(s32 a0) {
s32 t;
s32 r;
if (ang >= 0) {
t = -(ang << 4);
t = -(ang << 4) - 0x4000;
} else {
t = ang << 4;
}
{
register s32 av __asm__("$5"); // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B tus9)
av = t - 0x4000;
func_8012B178(a0, av);
t = (ang << 4) - 0x4000;
}
func_8012B178(a0, t);
r = ((s32 (*)(s32))func_8012CBA4)(a0);
if (r & 0x8000) {
*(u16 *)(a0 + 0x34) = 2;
@@ -4424,15 +4420,11 @@ void func_8018106C(s32 a0) {
*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) =
*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) + d;
if (ang >= 0) {
t = -(ang << 4);
t = -(ang << 4) - 0x4000;
} else {
t = ang << 4;
}
{
register s32 av __asm__("$5"); // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B tus9)
av = t - 0x4000;
func_8012B178(a0, av);
t = (ang << 4) - 0x4000;
}
func_8012B178(a0, t);
if ((((s32 (*)(s32))func_8012CBA4)(a0) & 0x2000) == 0) {
func_8012ADE4((u8 *)a0);
*(u16 *)(a0 + 0x34) = 2;
+7 -9
View File
@@ -7371,11 +7371,6 @@ s32 func_801825BC(void *a0)
u16 st;
if (func_8012BD14(*(s32 *)((s32)a0 + 0x64)) > 0x4000) {
/* LOAD-BEARING zero-byte cross-jump barrier (cookbook §5a).
* Without it gcc's find_cross_jump merges this `move v0,0; j epi`
* tail with the identical case-2 failure tail -> 58 ins instead of
* 60, and the case-2 `beq` then loses its delay-slot fill. */
__asm__ __volatile__(""); // !FAKE: barrier — NEEDED DIFFERS (P36 rung B tus7)
return 0;
}
@@ -7386,13 +7381,13 @@ s32 func_801825BC(void *a0)
*(s16 *)((s32)p + 0x2) = 8;
break;
case 2:
if (*(u16 *)((s32)p + 0x34) != 1) {
return 0;
if (*(u16 *)((s32)p + 0x34) == 1) {
goto hit;
}
goto hit;
goto fail;
case 4:
if (*(u16 *)((s32)p + 0x34) != 0) {
return 0;
goto fail;
}
hit:
D_801E7020 = st;
@@ -7400,6 +7395,9 @@ s32 func_801825BC(void *a0)
*(s16 *)(*(s32 *)((s32)a0 + 0x64) + 0x2) = 10;
break;
default:
fail: /* the case-2/case-4 failures share this one `return 0`: a return
* falling out of a conditional (as the first one does) is what
* jump2's cross-jump would merge the early return into */
return 0;
}
+7 -9
View File
@@ -5411,11 +5411,6 @@ s32 func_8017FB10(void *a0)
u16 st;
if (func_8012BD14(*(s32 *)((s32)a0 + 0x64)) > 0x4000) {
/* LOAD-BEARING zero-byte cross-jump barrier (cookbook §5a).
* Without it gcc's find_cross_jump merges this `move v0,0; j epi`
* tail with the identical case-2 failure tail -> 58 ins instead of
* 60, and the case-2 `beq` then loses its delay-slot fill. */
__asm__ __volatile__(""); // !FAKE: barrier — NEEDED DIFFERS (P36 rung B tus7)
return 0;
}
@@ -5426,13 +5421,13 @@ s32 func_8017FB10(void *a0)
*(s16 *)((s32)p + 0x2) = 8;
break;
case 2:
if (*(u16 *)((s32)p + 0x34) != 1) {
return 0;
if (*(u16 *)((s32)p + 0x34) == 1) {
goto hit;
}
goto hit;
goto fail;
case 4:
if (*(u16 *)((s32)p + 0x34) != 0) {
return 0;
goto fail;
}
hit:
D_801ECE68 = st;
@@ -5440,6 +5435,9 @@ s32 func_8017FB10(void *a0)
*(s16 *)(*(s32 *)((s32)a0 + 0x64) + 0x2) = 10;
break;
default:
fail: /* the case-2/case-4 failures share this one `return 0`: a return
* falling out of a conditional (as the first one does) is what
* jump2's cross-jump would merge the early return into */
return 0;
}
+7 -9
View File
@@ -3289,11 +3289,6 @@ s32 func_80180FB4(void *a0)
u16 st;
if (func_8012BD14(*(s32 *)((s32)a0 + 0x64)) > 0x4000) {
/* LOAD-BEARING zero-byte cross-jump barrier (cookbook §5a).
* Without it gcc's find_cross_jump merges this `move v0,0; j epi`
* tail with the identical case-2 failure tail -> 58 ins instead of
* 60, and the case-2 `beq` then loses its delay-slot fill. */
__asm__ __volatile__(""); // !FAKE: barrier — NEEDED DIFFERS (P36 rung B tus9)
return 0;
}
@@ -3304,13 +3299,13 @@ s32 func_80180FB4(void *a0)
*(s16 *)((s32)p + 0x2) = 8;
break;
case 2:
if (*(u16 *)((s32)p + 0x34) != 1) {
return 0;
if (*(u16 *)((s32)p + 0x34) == 1) {
goto hit;
}
goto hit;
goto fail;
case 4:
if (*(u16 *)((s32)p + 0x34) != 0) {
return 0;
goto fail;
}
hit:
D_801ECE78 = st;
@@ -3318,6 +3313,9 @@ s32 func_80180FB4(void *a0)
*(s16 *)(*(s32 *)((s32)a0 + 0x64) + 0x2) = 10;
break;
default:
fail: /* the case-2/case-4 failures share this one `return 0`: a return
* falling out of a conditional (as the first one does) is what
* jump2's cross-jump would merge the early return into */
return 0;
}
+7 -2
View File
@@ -100,12 +100,17 @@ def related_bodies(tu, fn, target_text, alias, top=6, max_lines=600):
for r in recs:
if r.get("form") == "def" and r.get("name") == fn:
body = txt[ls[r["line"] - 1]:ls[r["end"]]] if r["end"] < len(ls) else txt[ls[r["line"] - 1]:]
if "!FAKE" not in body and "__asm__ __volatile__" not in body:
# SAME NAME IS NOT SAME FUNCTION: overlays reuse addresses (S103, agent c43 — the func_80185578 listed
# here from ov_SC03_014 was a one-line different function). Evidence required: a shared callee/global
# and a comparable size.
n_t, n_b = target_text.count("\n") or 1, body.count("\n") or 1
shares = (set(SYM.findall(body)) - {fn}) & want
if "!FAKE" not in body and "__asm__ __volatile__" not in body and shares and 0.6 <= n_b / n_t <= 1.6:
same.append((rel, r["line"], body))
break
head = []
for rel, line, body in same:
head += [f"=== {fn} ALREADY LEVER-FREE in {rel}:{line} — a variant of your function: port it (R71) ===", body.rstrip(), ""]
head += [f"=== {fn} ALREADY LEVER-FREE in {rel}:{line} — same name, shares symbols and size: PROBABLY a variant; diff it before porting (R71) ===", body.rstrip(), ""]
seen, out = set(), head + [f"=== lever-free bodies in {alias} sharing a callee or global with {fn} "
f"({len(cands)} found; top {top} by shared symbols) — read them for the SHAPE ==="]
for _, n, name, rel, line, shared, body in cands: