phase12: track verified func_80042E10 source

This commit is contained in:
Christopher Williams
2026-09-25 10:12:36 -04:00
parent 3532ee80d9
commit d557e354a1
+75
View File
@@ -0,0 +1,75 @@
/*
* func_80042E10 — 88 bytes at 0x80042E10..0x80042E68
*
* PHASE 12 RESUME LANE C (autonomous matching). Row from the UN-ATTEMPTED band
* (negatives-d-unattempted.tsv) filtered through config/function_extents.tsv
* (size 88 grade exact term=jr_ra). NOT previously in the ledger.
*
* MATCH: candidate_bytes=88, differing_bytes=0, result=MATCH, exit 0 on the DEFAULT toolchain
* (tools/old-gcc/gcc-2.7.2-psx/cc1). No region overrides.
*
* Hypothesis, not a claim about meaning: `a2` is a BIT count; `n = a2 >> 5` is the word index at
* which the range ends. Walk words `n` down to `0` of two same-sized arrays and count how many
* satisfy `(x & y) == y`; report whether ALL `n + 1` of them do. Used with `n` = the last word the
* two bit maps share, this is a "is every remaining bit of x present in y" test.
*
* Original words (22):
* 00063143 sra a2,a2,0x5 n = a2 >> 5
* 00C03821 move a3,a2 i = n
* 00004021 move t0,zero count = 0
* 2409FFFF li t1,-1 ---- the end value lives in a REGISTER ----
* 00061080 sll v0,a2,0x2
* 00A22821 addu a1,v0,a1 a1 += n * 4
* 00A22021 addu a0,v0,a0 a0 += n * 4
* $L: 8C820000 lw v0,0(a0)
* 8CA30000 lw v1,0(a1)
* 00000000 nop
* 00431024 and v0,v0,v1
* 14430002 bne v0,v1,0x80042e48 if ((x & y) != y) skip the count
* 00000000 nop
* 25080001 addiu t0,t0,1 count++
* 24A5FFFC addiu a1,a1,-4
* 24E7FFFF addiu a3,a3,-1 i-- <-- INSIDE the loop body
* 14E9FFF6 bne a3,t1,0x80042e2c <-- tested AFTER the decrement, against t1
* 2484FFFC addiu a0,a0,-4 (delay slot)
* 24C20001 addiu v0,a2,1 n + 1
* 01021026 xor v0,t0,v0
* 03E00008 jr ra
* 2C420001 sltiu v0,v0,1 (count ^ (n + 1)) < 1 == count == n + 1
*
* THE LEVER: THE LOOP MUST BE A DO-WHILE WHOSE DECREMENT IS IN THE CONDITION, COUNTING DOWN TO -1.
* The natural `for (i = n; i >= 0; i--)` spelling is 88 bytes with 16 differing bytes: it emits
* `bltz a3,<exit>` and NEVER materialises -1, because gcc tests `i >= 0` with a register-immediate
* branch. Writing
* i = n; count = 0;
* do { ... body ...; i--; } while (i != -1);
* makes gcc hoist `li t1,-1` BEFORE the loop and test `bne a3,t1` after the decrement, which is
* the original's form byte-for-byte. (The `for (i = n; i != -1; i--)` spelling is NOT equivalent
* here: it is 96 bytes, because a for-loop's test is placed at the top.) **The `li <reg>,-1` +
* `bne` pair is therefore a fingerprint of a do-while countdown to -1, not of a `!= -1` condition
* written in any loop form** -- the same fingerprint appears in 0x800A86B4, where the natural `i >= 0`
* spelling also emits `bgez` and one induction variable instead of the original's two pointers.
* SECOND, SMALLER: the statement order matters -- `i = n;` must precede `count = 0;` for the
* prologue (`sra` / `move a3,a2` / `move t0,zero` / `li t1,-1`) to line up.
*
* LIMITS: `a2` is treated as a bit count (`>> 5`) because only that makes the `* 4` byte scaling
* consistent, and the two arrays are assumed to be bit maps of the same size; neither is
* independently evidenced. The `==` is compiled to `(a ^ b) < 1` (gcc's equality idiom for this
* shape), which is why the source's `count == n + 1` does not appear as a `beq`.
*/
int func_80042E10(int a0, int a1, int a2)
{
int n = a2 >> 5;
int count;
int i;
i = n;
count = 0;
do {
if ((*(int *)(a0 + i * 4) & *(int *)(a1 + i * 4)) == *(int *)(a1 + i * 4))
count++;
i--;
} while (i != -1);
return count == n + 1;
}