phase9: merge C 4 — 365 regions / 356 distinct bodies
4 tier-2 frames (0x8002864C, 0x80049298 with gp=-D_80121BFC, 0x801032D4, 0x800893E8). C's process-error owning (hardcoded ends instead of the worklist column) and the F24 finding (caller-saved reloaded pointer across a call means the store belongs before the call) recorded. Rare-epilogue census: 47 tier-2 rows carry the pattern at their final instructions — definitive class, broadcast to the workers. Gate MATCH whole-binary SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
This commit is contained in:
@@ -75,6 +75,7 @@
|
||||
0x80026F14 0x80026F3C src/func_80026F14.c
|
||||
0x800276B0 0x800276D4 src/func_800276B0.c
|
||||
0x800281A4 0x800281E4 src/func_800281A4.c
|
||||
0x8002864C 0x80028698 src/func_8002864C.c
|
||||
0x800290D0 0x800290F0 src/func_800290D0.c
|
||||
0x800290F0 0x80029118 src/func_800290F0.c
|
||||
0x8002A9D4 0x8002AA18 src/func_8002A9D4.c
|
||||
@@ -129,6 +130,7 @@
|
||||
0x800450C4 0x80045110 src/func_800450C4.c gp=-D_80121BFC
|
||||
0x80045388 0x800453C0 src/func_80045388.c
|
||||
0x800453C0 0x800453F8 src/func_800453C0.c
|
||||
0x80049298 0x800492E4 src/func_80049298.c gp=-D_80121BFC
|
||||
0x8004C060 0x8004C090 src/func_8004C060.c
|
||||
0x8004C090 0x8004C0AC src/func_8004C090.c
|
||||
0x8004C0AC 0x8004C0F0 src/func_8004C0AC.c
|
||||
@@ -188,6 +190,7 @@
|
||||
0x8008352C 0x8008355C src/func_8008352C.c
|
||||
0x80085B80 0x80085B90 src/func_80085B80.c
|
||||
0x80089314 0x80089338 src/func_80089314.c
|
||||
0x800893E8 0x80089434 src/func_800893E8.c
|
||||
0x80089C4C 0x80089C54 src/func_80042088.c
|
||||
0x80089C54 0x80089C64 src/func_80089C54.c
|
||||
0x80089C64 0x80089C74 src/func_80089C64.c
|
||||
@@ -329,6 +332,7 @@
|
||||
0x80102B30 0x80102B5C src/func_80102B30.c maspsx=off
|
||||
0x80102FA4 0x80102FD4 src/func_80102FA4.c
|
||||
0x80102FD4 0x80102FE0 src/func_80102FD4.c
|
||||
0x801032D4 0x80103320 src/func_801032D4.c
|
||||
0x80103A94 0x80103AA0 src/func_80103A94.c
|
||||
0x80103B54 0x80103B60 src/func_80103B54.c
|
||||
0x80103B60 0x80103B6C src/func_80103B60.c
|
||||
|
||||
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* func_8002864C — 76 bytes at 0x8002864C..0x800286A0
|
||||
*
|
||||
* Two-argument wrapper with a scratch buffer: fills a 16-byte local buffer, hands
|
||||
* it and the two caller arguments to a second routine, and returns 1. Both
|
||||
* caller arguments are kept in callee-saved registers across the first call.
|
||||
*
|
||||
* The observed instructions are:
|
||||
* addiu sp,sp,-48
|
||||
* sw s0,32(sp)
|
||||
* move s0,a1 ; s0 = first caller argument
|
||||
* sw s1,36(sp)
|
||||
* move s1,a2 ; s1 = second caller argument
|
||||
* sw ra,40(sp)
|
||||
* jal 0x80010B14
|
||||
* addiu a1,sp,16 ; second argument = the buffer (delay slot)
|
||||
* addiu a0,sp,16 ; first argument = the buffer
|
||||
* move a1,s0
|
||||
* jal 0x800283F4
|
||||
* move a2,s1 ; third argument (delay slot)
|
||||
* li v0,1 ; return 1
|
||||
* lw ra,40(sp)
|
||||
* lw s1,36(sp)
|
||||
* lw s0,32(sp)
|
||||
* addiu sp,sp,48
|
||||
* jr ra
|
||||
* nop
|
||||
*
|
||||
* The 48-byte frame holds a 16-byte buffer at sp+16 plus the two saved registers
|
||||
* and `ra`; the buffer is addressed as `sp + 16`, which is what a 16-byte local
|
||||
* array produces in this frame.
|
||||
*
|
||||
* LIMITS: the buffer size (16) and the two callees are hypotheses read from the
|
||||
* instruction shape; what the buffer and the callees mean is unknown and is not
|
||||
* guessed here. Only the compiled bytes are evidence.
|
||||
*/
|
||||
|
||||
int func_8002864C(char *a0, int a1, int a2) {
|
||||
int buf[4];
|
||||
|
||||
func_80010B14(a0, buf);
|
||||
func_800283F4(buf, a1, a2);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* func_80049298 — 76 bytes at 0x80049298..0x800492EC
|
||||
*
|
||||
* Indexes a 76-byte-stride record table, reads a signed 16-bit field out of it,
|
||||
* and makes two calls. The stride is `cc1`'s strength reduction of `* 76` into
|
||||
* `*5`, `*4`, `-self`, `*4`.
|
||||
*
|
||||
* The observed instructions are:
|
||||
* addiu sp,sp,-24
|
||||
* sll v0,a0,0x2 ; index * 4
|
||||
* addu v0,v0,a0 ; index * 5
|
||||
* sll v0,v0,0x2 ; index * 20
|
||||
* subu v0,v0,a0 ; index * 19
|
||||
* lui v1,0x8012
|
||||
* lw v1,7164(v1) ; v1 = D_80121BFC (the record table base)
|
||||
* sll v0,v0,0x2 ; index * 76
|
||||
* sw ra,16(sp)
|
||||
* addu v0,v0,v1 ; table + index*76 (index first)
|
||||
* lh a0,74(v0) ; *(short *)(record + 74) <- SIGNED 16-bit
|
||||
* jal 0x800909D8
|
||||
* move a1,zero ; second argument = 0 (delay slot)
|
||||
* jal 0x800ACA10
|
||||
* nop
|
||||
* lw ra,16(sp)
|
||||
* addiu sp,sp,24
|
||||
* jr ra
|
||||
* nop
|
||||
*
|
||||
* This is the sibling of the MATCHED func_800450C4: same table base, same stride,
|
||||
* same direct-expression `addu` order. **D_80121BFC is gp-marked in the tracked
|
||||
* registry but read ABSOLUTELY here**, so this region needs the per-region
|
||||
* `gp=-D_80121BFC` override (cookbook finding 16, the per-SITE rule).
|
||||
*
|
||||
* LIMITS: the table base (0x80121BFC), the stride (76), the field offset (74) and
|
||||
* the callees are hypotheses read from the instruction shape; what the records
|
||||
* hold is unknown and is not guessed here. Only the compiled bytes are evidence.
|
||||
*/
|
||||
|
||||
extern int D_80121BFC;
|
||||
|
||||
void func_80049298(int index) {
|
||||
char *record = (char *)(index * 76 + D_80121BFC);
|
||||
|
||||
func_800909D8(*(short *)(record + 74), 0);
|
||||
func_800ACA10();
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* func_800893E8 — 76 bytes at 0x800893E8..0x8008943C
|
||||
*
|
||||
* Extracts a signed 4-bit field out of a word reached through two pointer hops,
|
||||
* uses it to index a table of words and writes -1 there, then re-reads the first
|
||||
* hop and clears a field on it before a call.
|
||||
*
|
||||
* The observed instructions are:
|
||||
* addiu sp,sp,-24
|
||||
* sw ra,16(sp)
|
||||
* lw v0,28(a0) ; q = p->ptr_1c
|
||||
* nop
|
||||
* lw v0,12(v0) ; q->word_0c
|
||||
* li v1,-1
|
||||
* sll v0,v0,0x14 ; << 20
|
||||
* sra v0,v0,0x1c ; >> 28 <- ARITHMETIC, so a SIGNED 4-bit field
|
||||
* sll v0,v0,0x2 ; * 4
|
||||
* lui at,0x8014
|
||||
* addu at,at,v0 ; table + field*4
|
||||
* sw v1,-31648(at) ; D_80138460[field] = -1 (%lo as displacement)
|
||||
* lw v0,28(a0) ; RELOAD q = p->ptr_1c
|
||||
* jal 0x80089314
|
||||
* sw zero,8(v0) ; q->word_08 = 0 (delay slot)
|
||||
* lw ra,16(sp)
|
||||
* addiu sp,sp,24
|
||||
* jr ra
|
||||
* nop
|
||||
*
|
||||
* The `sll`/`sra` PAIR is the tell that the field is a signed bitfield: a plain
|
||||
* `(x >> 8) & 0xf` would emit `srl`/`andi`. The shift pair is therefore written
|
||||
* explicitly rather than as a mask. The pointer is loaded twice, so the C re-reads
|
||||
* it rather than caching it.
|
||||
*
|
||||
* LIMITS: the pointer offsets (0x1c, 0x0c, 0x08), the table base (0x80138460) and
|
||||
* the bitfield position (bits 8-11, signed) are hypotheses read from the
|
||||
* instruction shape; what the object and the table mean is unknown and is not
|
||||
* guessed here. Only the compiled bytes are evidence.
|
||||
*/
|
||||
|
||||
extern int D_80138460[];
|
||||
|
||||
void func_800893E8(char *p) {
|
||||
char *q = *(char **)(p + 28);
|
||||
int field = (*(int *)(q + 12) << 20) >> 28;
|
||||
|
||||
D_80138460[field] = -1;
|
||||
|
||||
q = *(char **)(p + 28);
|
||||
*(int *)(q + 8) = 0;
|
||||
func_80089314();
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* func_801032D4 — 76 bytes at 0x801032D4..0x80103328
|
||||
*
|
||||
* GTE state reset: one no-argument call, the far-colour triple zeroed, the
|
||||
* OFX/OFY pair zeroed, then two adjacent 16-bit globals cleared with absolute
|
||||
* stores.
|
||||
*
|
||||
* The observed instructions are:
|
||||
* addiu sp,sp,-24
|
||||
* sw ra,16(sp)
|
||||
* jal 0x801097A0
|
||||
* nop
|
||||
* move a0,zero
|
||||
* move a1,zero
|
||||
* jal 0x80103B6C ; gte_ldRFC / gte_ldGFC / gte_ldBFC
|
||||
* move a2,zero ; all three zero (delay slot)
|
||||
* move a0,zero
|
||||
* jal 0x80109778 ; gte_ldOFX / gte_ldOFY
|
||||
* move a1,zero ; both zero (delay slot)
|
||||
* lui at,0x8014
|
||||
* sh zero,11812(at) ; D_80142E24 = 0
|
||||
* lui at,0x8014
|
||||
* sh zero,11808(at) ; D_80142E20 = 0
|
||||
* lw ra,16(sp)
|
||||
* addiu sp,sp,24
|
||||
* jr ra
|
||||
* nop
|
||||
*
|
||||
* The two final stores are ABSOLUTE (through `$at`), not gp-relative, so the two
|
||||
* symbols must NOT be gp-marked: `lui 0x8014` plus 11812/11808 gives 0x80142E24
|
||||
* and 0x80142E20.
|
||||
*
|
||||
* LIMITS: the two global addresses and the three callees are hypotheses read from
|
||||
* the instruction shape; what the state means is unknown and is not guessed here.
|
||||
* Only the compiled bytes are evidence.
|
||||
*/
|
||||
|
||||
extern short D_80142E24;
|
||||
extern short D_80142E20;
|
||||
|
||||
void func_801032D4(void) {
|
||||
func_801097A0();
|
||||
func_80103B6C(0, 0, 0);
|
||||
func_80109778(0, 0);
|
||||
D_80142E24 = 0;
|
||||
D_80142E20 = 0;
|
||||
}
|
||||
Reference in New Issue
Block a user