phase11: merge 35 + 5-way re-partition — 556 bodies / 565 regions
Worker D's 0x80025ADC (136 B). Partitions re-interleaved 5 ways because workers B and C are both at ~94% context and effectively exhausted, leaving 2 active workers against 45 remaining bodies. A fifth worker restores capacity.
This commit is contained in:
+793
-794
File diff suppressed because it is too large
Load Diff
@@ -81,6 +81,7 @@
|
||||
0x800230E4 0x8002311C src/func_800230E4.c
|
||||
0x80024C14 0x80024C34 src/func_80024C14.c
|
||||
0x80025070 0x800250AC src/func_80025070.c
|
||||
0x80025ADC 0x80025B64 src/func_80025ADC.c
|
||||
0x80026180 0x800261C0 src/func_80026180.c
|
||||
0x80026258 0x80026264 src/func_80026258.c
|
||||
0x80026264 0x80026274 src/func_80026264.c
|
||||
|
||||
|
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* func_80012918 — 72 bytes at 0x80012918..0x80012960
|
||||
*
|
||||
* Hypothesis, not a claim about meaning: releases a sub-object if one is attached —
|
||||
* calling a helper with the parent plus an offset and the sub-object, then clearing the
|
||||
* slot. A one-branch body; matched on the FIRST spelling as the third member of a family
|
||||
* whose other members are already matched (src/func_8001289C.c has the identical shape).
|
||||
*
|
||||
* Original words:
|
||||
* 27BDFFE8 addiu sp,sp,-24
|
||||
* AFB00010 sw s0,16(sp)
|
||||
* 00A08021 move s0,a1 ; s0 = a1
|
||||
* 1200000B beqz s0,0x80012948 ; if (a1 == 0) skip everything
|
||||
* AFBF0014 sw ra,20(sp) ; (delay)
|
||||
* 8E050028 lw a1,40(s0) ; a1 = a1[10]
|
||||
* 00000000 nop
|
||||
* 10A00004 beqz a1,0x8001294C ; if (a1[10] == 0) skip the call
|
||||
* 00001021 move v0,zero ; (delay) v0 = 0
|
||||
* 0C009958 jal 0x80026560 ; func_80026560(a0 + 0x90, a1[10])
|
||||
* 24840090 addiu a0,a0,144 ; (delay)
|
||||
* AE000028 sw zero,40(s0) ; a1[10] = 0
|
||||
* 00001021 move v0,zero ; 0x8001294C: v0 = 0
|
||||
* 8FBF0014 lw ra,20(sp) ; 0x80012948:
|
||||
* 8FB00010 lw s0,16(sp)
|
||||
* 27BD0018 addiu sp,sp,24
|
||||
* 03E00008 jr ra
|
||||
* 00000000 nop
|
||||
*
|
||||
* **FAMILY MATCH.** `src/func_8001289C.c` (72 bytes, the same histogram and size) is
|
||||
* `if (a1 != 0 && *a1 != 0) { func_80026560(a0 + 0x94, *a1); *a1 = 0; } return v0;`
|
||||
* and this row is that with a different field offset and a different parent offset. The
|
||||
* two byte-required details are both inherited from the sibling:
|
||||
*
|
||||
* 1. **The guard is the `&&` chain** `a1 != 0 && a1[10] != 0` — cc1 emits `beqz s0` for the
|
||||
* first term and `beqz a1` for the second, with the `move v0,zero` in the second
|
||||
* branch's delay slot.
|
||||
* 2. **`v0` is a real local initialised to 0 and returned**, not a `return 0;` — the
|
||||
* original has `move v0,zero` in a branch delay slot AND at the join, which is what an
|
||||
* initialised-and-returned local produces.
|
||||
*
|
||||
* The field is at byte offset 40 (int index 10) and the parent offset is 0x90, whereas the
|
||||
* sibling uses 0 and 0x94 — the same body with different constants, which is exactly what
|
||||
* the family score of 1.000 predicted.
|
||||
*
|
||||
* LIMITS: the function name, the callee, both offsets and the "release the sub-object"
|
||||
* reading are hypotheses taken from the instruction shape; only the bytes are evidence.
|
||||
* func_80026560 is declared here rather than registered.
|
||||
*/
|
||||
|
||||
extern void func_80026560(int a0, int a1);
|
||||
|
||||
int func_80012918(int a0, int *a1)
|
||||
{
|
||||
int v0 = 0;
|
||||
|
||||
if (a1 != 0 && a1[10] != 0) {
|
||||
func_80026560(a0 + 0x90, a1[10]);
|
||||
a1[10] = 0;
|
||||
}
|
||||
|
||||
return v0;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* func_800259A0 — 60 bytes at 0x800259A0..0x800259DC
|
||||
*
|
||||
* Hypothesis, not a claim about meaning: forwards to a helper, substituting a word from a
|
||||
* sub-object when one is present and zero when it is not, and passing the original second
|
||||
* argument through as the third. A leaf-sized body with one branch — it matched on the
|
||||
* FIRST spelling, and it is the third member of a family whose other members are already
|
||||
* matched (src/func_80025070.c has the identical shape).
|
||||
*
|
||||
* Original words:
|
||||
* 27BDFFE8 addiu sp,sp,-24
|
||||
* AFBF0010 sw ra,16(sp)
|
||||
* 8C820020 lw v0,32(a0) ; obj2 = *(int **)((char *)a0 + 0x20)
|
||||
* 00000000 nop
|
||||
* 14400004 bnez v0,0x800259C0 ; if (obj2 != 0) -> the else arm
|
||||
* 00A03021 move a2,a1 ; (delay) the ORIGINAL a1 becomes the 3rd argument
|
||||
* 08009671 j 0x800259C4
|
||||
* 00002821 move a1,zero ; (delay) then-argument: 0
|
||||
* 8C410020 lw a1,32(v0) ; 0x800259C0: else-argument: obj2[8]
|
||||
* 0C009635 jal 0x800258D4 ; 0x800259C4: func_800258D4(a0, a1, a2)
|
||||
* 00000000 nop
|
||||
* 8FBF0010 lw ra,16(sp)
|
||||
* 27BD0018 addiu sp,sp,24
|
||||
* 03E00008 jr ra
|
||||
* 00000000 nop
|
||||
*
|
||||
* **FAMILY MATCH: THE SOURCE SHAPE IS THE SIBLING'S, VERBATIM.** `src/func_80025070.c`
|
||||
* (60 bytes, the same opcode histogram and the same size) is
|
||||
* `if (obj2 == 0) func_800250AC((int)a0, 0, a1); else func_800250AC((int)a0, *(int *)((char *)obj2 + 0x20), a1);`
|
||||
* and this row is that with a different callee. **Writing the `if` as `obj2 == 0` with the
|
||||
* zero arm FIRST is byte-required**: cc1 emits `bnez v0,<else>` with the zero case as the
|
||||
* fall-through path, and the original's `j 0x800259C4 / move a1,zero` in the delay is
|
||||
* exactly that layout. Note the THIRD argument is the *original* `a1`, captured in the
|
||||
* branch delay slot before `a1` is overwritten — so the source must pass `a1` (not a copy
|
||||
* made after the branch) as the third argument.
|
||||
*
|
||||
* The family was found by `./tools/sf3_family` (opcode-histogram cosine × size ratio against
|
||||
* already-matched regions). This row scored 1.000 against `0x80025070` — identical histogram,
|
||||
* identical size — and that is what made it a one-attempt row.
|
||||
*
|
||||
* LIMITS: the function name, the callee, the sub-object offset (0x20) and the meaning of the
|
||||
* forwarded word are hypotheses taken from the instruction shape; only the bytes are
|
||||
* evidence. func_800258D4 is not registered and is referenced by its address-named spelling.
|
||||
*/
|
||||
|
||||
void func_800258D4(int, int, int);
|
||||
|
||||
int func_800259A0(int *a0, int a1)
|
||||
{
|
||||
int *obj2 = *(int **)((char *)a0 + 0x20);
|
||||
|
||||
if (obj2 == 0)
|
||||
func_800258D4((int)a0, 0, a1);
|
||||
else
|
||||
func_800258D4((int)a0, *(int *)((char *)obj2 + 0x20), a1);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* func_8006B2D4 — 84 bytes at 0x8006B2D4..0x8006B328
|
||||
*
|
||||
* Hypothesis, not a claim about meaning: walks a singly-linked list from a global head and
|
||||
* calls a teardown routine on every node that has a flag set. Matched on the FIRST spelling
|
||||
* as the third member of a family whose sibling is already matched (src/func_8006ADB0.c has
|
||||
* the identical shape and differs only in the callee).
|
||||
*
|
||||
* Original words:
|
||||
* 8F820550 lw a0,1360(gp) ; node = D_80121E88 (hoisted above the frame)
|
||||
* 27BDFFE8 addiu sp,sp,-24
|
||||
* AFBF0014 sw ra,20(sp)
|
||||
* 10800009 beqz a0,0x8006B314 ; while (node != 0)
|
||||
* AFB00010 sw s0,16(sp) ; (delay)
|
||||
* 8C82000C lw v0,12(a0) ; 0x8006B2E8: mid = node[3]
|
||||
* 00000000 nop
|
||||
* 8C410160 lw v1,352(v0) ; flag = *(int *)(mid + 352)
|
||||
* 8C50018C lw s0,396(v0) ; next = *(int *)(mid + 396)
|
||||
* 10600004 beqz v1,0x8006B308 ; if (flag != 0) func_800C022C(node)
|
||||
* 00000000 nop
|
||||
* 0C03008B jal 0x800C022C
|
||||
* 00000000 nop
|
||||
* 02002021 move a0,s0 ; 0x8006B308: node = next
|
||||
* 1480FFF7 bnez a0,0x8006B2E8 ; more -> loop
|
||||
* 00000000 nop
|
||||
* 8FBF0014 lw ra,20(sp) ; (END)
|
||||
* 8FB00010 lw s0,16(sp)
|
||||
* 27BD0018 addiu sp,sp,24
|
||||
* 03E00008 jr ra
|
||||
* 00000000 nop
|
||||
*
|
||||
* **FAMILY MATCH.** `src/func_8006ADB0.c` (84 bytes, identical histogram and size) is the
|
||||
* same walk with `func_800BFF20` as the callee. Two details are inherited from it and are
|
||||
* byte-required:
|
||||
*
|
||||
* 1. **`next` is read BEFORE the call** (`lw s0,396(v0)` precedes the `jal`) — the loop
|
||||
* pointer therefore does not survive the call and the next pointer lives in a
|
||||
* callee-saved register. Reading the next pointer after the call changes the bytes.
|
||||
* 2. **The head is hoisted above the frame setup** (`lw a0,1360(gp)` is the first
|
||||
* instruction), which is what a `while (node != 0)` over a global produces.
|
||||
*
|
||||
* This row calls `func_800C022C`, a 464-byte row I classified as a near-miss earlier in the
|
||||
* session — the same sub-object layout (`mid + 352`, `mid + 396`) appears in both, which is
|
||||
* further evidence that the family spans both directions of the call graph.
|
||||
*
|
||||
* LIMITS: the function name, the callee, the global head, the node offsets (3, 352, 396) and
|
||||
* the whole "walk and tear down" reading are hypotheses taken from the instruction shape;
|
||||
* only the bytes are evidence. Both symbols are referenced by their address-named spellings.
|
||||
*/
|
||||
|
||||
extern int D_80121E88;
|
||||
extern void func_800C022C(int *node);
|
||||
|
||||
void func_8006B2D4(void)
|
||||
{
|
||||
int *node = (int *)D_80121E88;
|
||||
|
||||
while (node != 0) {
|
||||
int *mid = *(int **)((char *)node + 12);
|
||||
int *flag = *(int **)((char *)mid + 352);
|
||||
int *next = *(int **)((char *)mid + 396);
|
||||
|
||||
if (flag != 0)
|
||||
func_800C022C(node);
|
||||
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user