phase9: merge B 3 — 404 regions / 395 distinct bodies

B: 42 new this cycle. Family rows restored the rate 3-for-3 first attempt
(selectors 6/17/15). Boundary note: 0x80057BE8 is in partition C (retired,
no race) — accepted under the standing verified-work-claimable policy. Key
finding: the family's argument map is NOT constant — stable positions
(narrowed a1 -> arg 9, 5th param -> arg 10) + per-row positions elsewhere
(no negu when there is no conditional selection — the discriminator
predicts it). Third selector-proving pair. Gate MATCH whole-binary SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9.
This commit is contained in:
Christopher Williams
2026-09-24 02:52:35 -04:00
parent 1f79de4a24
commit 2e9d88211c
4 changed files with 160 additions and 0 deletions
+3
View File
@@ -152,13 +152,16 @@
0x80052C98 0x80052CAC src/func_80052C98.c
0x80057524 0x80057564 src/func_80057524.c
0x80057748 0x80057798 src/func_80057748.c
0x80057798 0x800577E8 src/func_80057798.c
0x8005784C 0x8005789C src/func_8005784C.c
0x8005789C 0x800578EC src/func_8005789C.c
0x800579A0 0x800579F0 src/func_800579A0.c
0x800579F0 0x80057A40 src/func_800579F0.c
0x80057AE0 0x80057B30 src/func_80057AE0.c
0x80057B84 0x80057BE8 src/func_80057B84.c
0x80057BE8 0x80057C30 src/func_80057BE8.c
0x80057C30 0x80057C80 src/func_80057C30.c
0x80057C80 0x80057CD0 src/func_80057C80.c
0x80057DFC 0x80057E04 src/func_80057DFC.c
0x80058230 0x80058288 src/func_80058230.c
0x80058288 0x800582AC src/func_80058288.c
1 # Code-region registry: one C region per matched function.
152 0x80052C98
153 0x80057524
154 0x80057748
155 0x80057798
156 0x8005784C
157 0x8005789C
158 0x800579A0
159 0x800579F0
160 0x80057AE0
161 0x80057B84
162 0x80057BE8
163 0x80057C30
164 0x80057C80
165 0x80057DFC
166 0x80058230
167 0x80058288
+53
View File
@@ -0,0 +1,53 @@
/* func_80057798 — 0x80057798..0x800577E8 (80 bytes).
*
* Fifth member of the 0x80057xxx argument-block family, identical in shape to the already
* matched `0x80057748` with the selector 6.
*
* Original words:
* 27BDFFD0 addiu sp,sp,-48
* 30A700FF andi a3,a1,0xff
* 30C600FF andi a2,a2,0xff
* AFA70020 sw a3,32(sp) outgoing arg 9 = narrowed a1
* 0007382B sltu a3,zero,a3
* 00073823 negu a3,a3
* 24050006 li a1,6 the selector
* AFA60024 sw a2,36(sp) outgoing arg 10 = narrowed a2
* 2406FFFF li a2,-1
* 00873824 and a3,a0,a3
* AFBF0028 sw ra,40(sp)
* AFA00010 sw zero,16(sp) outgoing arg 5 = 0
* AFA00014 sw zero,20(sp) outgoing arg 6 = 0
* AFA00018 sw zero,24(sp) outgoing arg 7 = 0
* 0C015D99 jal 0x80057664
* AFA0001C _sw zero,28(sp) (delay slot) outgoing arg 8 = 0
* 8FBF0028 lw ra,40(sp)
* 27BD0030 addiu sp,sp,48
* 03E00008 jr ra
* 00000000 nop
*
* The frame is 48 bytes and the six words at 16–36(sp) are the **outgoing argument area**, so
* the callee takes ten arguments: four in registers, six on the stack. The two narrowed values
* land at 32 and 36(sp) — args 9 and 10 — which is the trap that cost an attempt earlier in this
* family and is now only a matter of reading the frame arithmetic.
*
* The conditional is **branchless**, which is this family's discriminator: `sltu` then `negu`
* builds a 0-or-−1 mask so `narrowed1 ? a0 : 0` costs no branch. Per the family's rule that means
* exactly **one** distinct value is being selected here (as against `0x80057B84`, which selects
* two and therefore needs a real `beqz`/`j`).
*
* LIMITS: the selector 6, the mask 0xff and the frame layout are read from the bytes. What the
* selector selects is not observable from this body; the evidence that it *is* a selector comes
* from the byte-identical siblings that differ only in this constant. The callee is named for its
* address.
*/
void func_80057664(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
int a8, int a9);
void func_80057798(int a0, int a1, int a2)
{
int narrowed1 = a1 & 0xff;
int narrowed2 = a2 & 0xff;
func_80057664(a0, 6, -1, narrowed1 ? a0 : 0, 0, 0, 0, 0, narrowed1, narrowed2);
}
+52
View File
@@ -0,0 +1,52 @@
/* func_80057BE8 — 0x80057BE8..0x80057C30 (72 bytes).
*
* Seventh member of the 0x80057xxx argument-block family, and the one whose argument **positions**
* differ rather than just the selector.
*
* Original words:
* 27BDFFD0 addiu sp,sp,-48
* 93A20040 lbu v0,64(sp) the FIFTH incoming parameter
* 30A500FF andi a1,a1,0xff
* AFA50020 sw a1,32(sp) outgoing arg 9 = narrowed a1
* 2405000F li a1,15 the selector
* AFA60018 sw a2,24(sp) outgoing arg 7 = a2
* 2406FFFF li a2,-1
* AFA7001C sw a3,28(sp) outgoing arg 8 = a3
* 00003821 move a3,zero outgoing arg 4 = 0
* AFBF0028 sw ra,40(sp)
* AFA00010 sw zero,16(sp) outgoing arg 5 = 0
* AFA00014 sw zero,20(sp) outgoing arg 6 = 0
* 0C015D99 jal 0x80057664
* AFA20024 _sw v0,36(sp) (delay slot) outgoing arg 10 = the fifth parameter
* 8FBF0028 lw ra,40(sp)
* 27BD0030 addiu sp,sp,48
* 03E00008 jr ra
* 00000000 nop
*
* **THE REGISTER ARGUMENTS ARE THE ONES THAT MOVED, NOT JUST THE SELECTOR.** In the other members
* outgoing args 4–8 are either a masked `a0` or zeros; here arg 4 is a plain **zero** (a
* `move a3,zero`, not the branchless mask), args 5 and 6 are zero, and args 7 and 8 carry the
* routine's **`a2` and `a3`** — so this row forwards its third and fourth parameters into the
* callee's seventh and eighth slots, which no other member does.
*
* Note also that there is **no `negu`** here: the mask machinery is absent because nothing is being
* conditionally selected — the only non-constant value placed in a register argument is zero. So
* the family's branchless-mask discriminator predicts this row's shape correctly: no conditional
* selection means no mask.
*
* The narrowed `a1` still goes to arg 9 and the fifth incoming parameter to arg 10, so those two
* positions are stable across the family while the register arguments are not — which is the
* reason each member's argument map has to be read rather than assumed.
*
* LIMITS: the selector 15, the mask 0xff, the displacements and the frame layout are read from the
* bytes. The fifth parameter is `unsigned char` by the single `lbu`. The callee is named for its
* address and nothing establishes what the selector means.
*/
void func_80057664(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
int a8, int a9);
void func_80057BE8(int a0, int a1, int a2, int a3, unsigned char a4)
{
func_80057664(a0, 15, -1, 0, 0, 0, a2, a3, a1 & 0xff, a4);
}
+52
View File
@@ -0,0 +1,52 @@
/* func_80057C80 — 0x80057C80..0x80057CD0 (80 bytes).
*
* Sixth member of the 0x80057xxx argument-block family, identical in shape to the already
* matched `0x80057748` with the selector 17.
*
* Original words:
* 27BDFFD0 addiu sp,sp,-48
* 30A700FF andi a3,a1,0xff
* 30C600FF andi a2,a2,0xff
* AFA70020 sw a3,32(sp) outgoing arg 9 = narrowed a1
* 0007382B sltu a3,zero,a3
* 00073823 negu a3,a3
* 24050011 li a1,17 the selector
* AFA60024 sw a2,36(sp) outgoing arg 10 = narrowed a2
* 2406FFFF li a2,-1
* 00873824 and a3,a0,a3
* AFBF0028 sw ra,40(sp)
* AFA00010 sw zero,16(sp) outgoing arg 5 = 0
* AFA00014 sw zero,20(sp) outgoing arg 6 = 0
* AFA00018 sw zero,24(sp) outgoing arg 7 = 0
* 0C015D99 jal 0x80057664
* AFA0001C _sw zero,28(sp) (delay slot) outgoing arg 8 = 0
* 8FBF0028 lw ra,40(sp)
* 27BD0030 addiu sp,sp,48
* 03E00008 jr ra
* 00000000 nop
*
* Byte-for-byte the same as `0x80057798` except `li a1,17` where that row has `li a1,6`. With the
* family now holding several such pairs — `0x8005789C`/`0x80057C30` differing only in 4 versus 16,
* and this row versus `0x80057798` differing only in 17 versus 6 — the selector reading is
* established well beyond a single observation: **the constant is the only thing that varies
* between structurally identical rows**, so it selects the callee's behaviour rather than carrying
* data.
*
* That is also why matching the family as a set is worth the effort: the argument map is derived
* once and each additional member costs only a constant change and a verification run.
*
* LIMITS: the selector 17, the mask 0xff and the frame layout are read from the bytes; what 17
* selects is not observable. The branchless mask shows exactly one distinct value is being
* selected, per the family's discriminator. The callee is named for its address.
*/
void func_80057664(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
int a8, int a9);
void func_80057C80(int a0, int a1, int a2)
{
int narrowed1 = a1 & 0xff;
int narrowed2 = a2 & 0xff;
func_80057664(a0, 17, -1, narrowed1 ? a0 : 0, 0, 0, 0, 0, narrowed1, narrowed2);
}