phase9: merge B 2 + coordinator 1 — 351 regions / 342 distinct bodies
Worker B matched 0x800F6330 (correcting my stale negative: destination is 0x8011AA18 via the signed-displacement finding-4 trap) and 0x80090B7C (18th/19th first-attempt matches this cycle). Coordinator absorbed 0x80025070 (conditional dispatch wrapper). B's correction of its own void-vs-valued epilogue tell accepted (0x800FBDC0 counterexample; the shared-epilogue hypothesis stands untested — recorded as observation, not rule). Gate MATCH whole-binary SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
This commit is contained in:
@@ -60,6 +60,7 @@
|
||||
0x80022FCC 0x80022FFC src/func_80022FCC.c
|
||||
0x800230E4 0x8002311C src/func_800230E4.c
|
||||
0x80024C14 0x80024C34 src/func_80024C14.c
|
||||
0x80025070 0x800250AC src/func_80025070.c
|
||||
0x80026180 0x800261C0 src/func_80026180.c
|
||||
0x80026258 0x80026264 src/func_80026258.c
|
||||
0x80026264 0x80026274 src/func_80026264.c
|
||||
@@ -198,6 +199,7 @@
|
||||
0x800900A0 0x800900CC src/func_800900A0.c
|
||||
0x80090A44 0x80090A70 src/func_80090A44.c
|
||||
0x80090B64 0x80090B7C src/func_80090B64.c
|
||||
0x80090B7C 0x80090BB4 src/func_80090B7C.c
|
||||
0x80090C8C 0x80090CAC src/func_80090C8C.c
|
||||
0x8009107C 0x800910B0 src/func_8009107C.c
|
||||
0x800912D4 0x800912FC src/func_800912D4.c
|
||||
@@ -263,6 +265,7 @@
|
||||
0x800F5200 0x800F521C src/func_800F5200.c
|
||||
0x800F5AF8 0x800F5B40 src/func_800F5AF8.c
|
||||
0x800F5B40 0x800F5B70 src/func_800F5B40.c
|
||||
0x800F6330 0x800F6364 src/func_800F6330.c
|
||||
0x800F6570 0x800F6594 src/func_800F6570.c
|
||||
0x800F75D0 0x800F760C src/func_800F75D0.c
|
||||
0x800F7990 0x800F79C0 src/func_800F7990.c
|
||||
|
||||
|
@@ -0,0 +1,43 @@
|
||||
/* func_80025070 — 0x80025070..0x800250AC (60 bytes).
|
||||
*
|
||||
* Dispatches to func_800250AC with three arguments where the second is
|
||||
* selected by a null-conditional.
|
||||
*
|
||||
* Original words:
|
||||
* 0x27BDFFE8 addiu sp,sp,-24
|
||||
* 0xAFBF0010 sw ra,16(sp)
|
||||
* 0x8C820020 lw v0,32(a0) ; v0 = *(int *)(a0 + 0x20)
|
||||
* 0x00000000 nop
|
||||
* 0x14400003 bnez v0,else ; if (v0 != 0) else
|
||||
* 0x00A03021 move a2,a1 ; (delay) a2 = a1 (forward)
|
||||
* 0x08009425 j call
|
||||
* 0x00002821 move a1,zero ; (delay) a1 = 0
|
||||
* else:
|
||||
* 0x8C450020 lw a1,32(v0) ; a1 = *(int *)(v0 + 0x20)
|
||||
* call:
|
||||
* 0x0C00942B jal func_800250AC
|
||||
* 0x00000000 nop
|
||||
* 0x8FBF0010 lw ra,16(sp)
|
||||
* 0x27BD0018 addiu sp,sp,24
|
||||
* 0x03E00008 jr ra
|
||||
* 0x00000000 nop
|
||||
*
|
||||
* Dataflow: obj2 = *(a0+0x20); if (obj2 == 0) { a2 = a1; a1 = 0; }
|
||||
* else { a1 = *(obj2 + 0x20); } call with (a0, a1, a2). The a0 stays
|
||||
* forwarded unchanged. The j-with-delay structure selects the argument.
|
||||
*
|
||||
* LIMITS: the object layout and callee role are hypotheses. Only the
|
||||
* compiled bytes are evidence.
|
||||
*/
|
||||
|
||||
void func_800250AC(int, int, int);
|
||||
|
||||
int func_80025070(int *a0, int a1)
|
||||
{
|
||||
int *obj2 = *(int **)((char *)a0 + 0x20);
|
||||
|
||||
if (obj2 == 0)
|
||||
func_800250AC((int)a0, 0, a1);
|
||||
else
|
||||
func_800250AC((int)a0, *(int *)((char *)obj2 + 0x20), a1);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/* func_80090B7C — 0x80090B7C..0x80090BB4 (56 bytes).
|
||||
*
|
||||
* Original words:
|
||||
* 27BDFFE8 addiu sp,sp,-24
|
||||
* AFBF0010 sw ra,16(sp)
|
||||
* 00042400 sll a0,a0,0x10
|
||||
* 00051100 sll v0,a1,0x4
|
||||
* 00451023 subu v0,v0,a1 v0 = a1*15
|
||||
* 00021480 sll v0,v0,0x12 << 18
|
||||
* 00042403 sra a0,a0,0x10 a0 = (short)a0
|
||||
* 00022C03 sra a1,v0,0x10 >> 16
|
||||
* 0C03FE00 jal 0x800FF800
|
||||
* 24060003 _li a2,3 (delay slot) third argument = 3
|
||||
* 8FBF0010 lw ra,16(sp)
|
||||
* 27BD0018 addiu sp,sp,24
|
||||
* 03E00000 jr ra
|
||||
* 00000000 nop
|
||||
*
|
||||
* Narrows two values and forwards them with a constant third. The first is a
|
||||
* plain sign-extension; the second is the interesting one.
|
||||
*
|
||||
* `a1 << 4; - a1; << 18; >> 16` looks like two unrelated operations but is one:
|
||||
* `<< 18` is the fusion of a `<< 2` (from a multiply by 4) with a `<< 16` (from a
|
||||
* 16-bit sign-extension), so the whole sequence is
|
||||
* `((a1 * 15) << 2 << 16) >> 16` — that is, `(short)(a1 * 60)`. The `>> 16` is
|
||||
* what remains of the cast after cc1 folded the other shift into it, which is why
|
||||
* the emitted shift amount is 18 and not 2. Writing this as anything other than a
|
||||
* multiply-then-cast changes the shift amounts and will not match.
|
||||
*
|
||||
* LIMITS: the multipliers 15 and 4, and the fused shift amount 18, are read from
|
||||
* the instructions; that they express a single `* 60` is an arithmetic identity
|
||||
* rather than source evidence, but it is the only reading that yields a shift of
|
||||
* 18 in a 16-bit-narrowing context. The third argument's constant 3 is literal.
|
||||
* The callee is named for its address and its signature is inferred from the three
|
||||
* registers that are set.
|
||||
*/
|
||||
|
||||
void func_800FF800(short a, short b, int c);
|
||||
|
||||
void func_80090B7C(int a0, int a1)
|
||||
{
|
||||
func_800FF800((short)a0, (short)(a1 * 60), 3);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/* func_800F6330 — 0x800F6330..0x800F6364 (52 bytes).
|
||||
*
|
||||
* Original words:
|
||||
* 27BDFFE8 addiu sp,sp,-24
|
||||
* AFBF0010 sw ra,16(sp)
|
||||
* 0C03DD98 jal 0x800F7660
|
||||
* 2404FFFF _li a0,-0x1 (delay slot)
|
||||
* 244200F0 addiu v0,v0,240 result + 240
|
||||
* 3C018012 lui at,0x8012
|
||||
* AC22AA18 sw v0,-21992(at) D_8011AA18 = result + 240
|
||||
* 3C018012 lui at,0x8012
|
||||
* AC20AA1C sw zero,-21988(at) D_8011AA1C = 0
|
||||
* 8FBF0010 lw ra,16(sp)
|
||||
* 27BD0018 addiu sp,sp,24
|
||||
* 03E00008 jr ra
|
||||
* 00000000 nop
|
||||
*
|
||||
* Calls one routine with the sentinel -1, adds 240 to what it returns, publishes
|
||||
* the sum and clears the neighbouring global. Nothing is returned.
|
||||
*
|
||||
* `lui at,0x8012` + `sw v0,%lo(at)` is the assembler's expansion of a **symbol
|
||||
* store** through `$at` (cookbook finding 3: a store must not clobber its source
|
||||
* register, so the macro uses `$at`), so both destinations are symbols, not
|
||||
* computed addresses. The two `lui`s load the same high half for two adjacent
|
||||
* words, which is why the `lui` is re-emitted rather than shared — cc1 does not
|
||||
* hoist a macro-expanded constant across the store.
|
||||
*
|
||||
* LIMITS: the `-1` sentinel, the 240 offset and the two displacements are read
|
||||
* from the instructions. **The destination addresses are 0x8011AA18 and
|
||||
* 0x8011AA1C, not 0x8012AA18** — `lui at,0x8012` with a displacement the
|
||||
* disassembler prints as **-21992** is the sign-adjusted `%lo` split (cookbook
|
||||
* finding 4), so the effective address is 0x80120000 - 0x55E8. Naming the symbol
|
||||
* from the `lui` immediate alone puts it 64 KB away and produces a silently wrong
|
||||
* claim; that mistake was caught here only by recomputing the address. The two
|
||||
* globals are adjacent words (`0xAA1C` is `0xAA18` + 4). That the pair is a
|
||||
* counter and its reset is a guess from their adjacency and the zero store, not
|
||||
* evidence: nothing in the body reads either one.
|
||||
*/
|
||||
|
||||
extern int D_8011AA18;
|
||||
extern int D_8011AA1C;
|
||||
|
||||
int func_800F7660(int arg);
|
||||
|
||||
void func_800F6330(void)
|
||||
{
|
||||
D_8011AA18 = func_800F7660(-1) + 240;
|
||||
D_8011AA1C = 0;
|
||||
}
|
||||
Reference in New Issue
Block a user