phase9: merge C 3 — 361 regions / 352 distinct bodies
Worker C closed 0x80031F2C (a row the coordinator had recorded as a negative) via the F23 struct-assignment lever (second confirmation) — stale negative removed. Also 0x800129C8, 0x8009132C (F22: unsigned char local re-masks an already-zero-extended lbu — width-of-DESTINATION tell). C's link-error finding recorded: 'small-data section too large' on a region that built fine = a duplicate gp symbol (name mismatch), not a -G problem. New negative 0x80042E68 pairs with 0x80042DD4; named pointer lever untried. Gate MATCH whole-binary SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
This commit is contained in:
@@ -28,7 +28,6 @@
|
||||
0x800266A8 68 near-match byte-replication alloc (first sll register; fresh-context re-spelling 3B; named-locals regresses)
|
||||
0x8002D014 - near-match -
|
||||
0x8002D060 72 near-match -
|
||||
0x80031F2C 76 near-match cross-join/load-hoist (3 coordinator spellings: 92/92/68; original loads 4 words then stores, shared a3=a1 delay binding; finding-F6 family)
|
||||
0x80039308 - near-match -
|
||||
0x80042DD4 - near-match -
|
||||
0x80042E10 - near-match -
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
0x8001281C 0x80012834 src/func_8001281C.c
|
||||
0x8001289C 0x800128E4 src/func_8001289C.c
|
||||
0x800128E4 0x80012918 src/func_800128E4.c
|
||||
0x800129C8 0x80012A10 src/func_800129C8.c
|
||||
0x80012D8C 0x80012DBC src/func_80012D8C.c
|
||||
0x80012DBC 0x80012DE8 src/func_80012DBC.c
|
||||
0x80013C88 0x80013C90 src/func_80013C88.c
|
||||
@@ -100,6 +101,7 @@
|
||||
0x8002F404 0x8002F450 src/func_8002F404.c
|
||||
0x800301FC 0x8003022C src/func_800301FC.c
|
||||
0x80030358 0x80030390 src/func_80030358.c
|
||||
0x80031F2C 0x80031F78 src/func_80031F2C.c
|
||||
0x80031F78 0x80031FC4 src/func_80031F78.c
|
||||
0x800321EC 0x800321F8 src/func_800321EC.c
|
||||
0x80034A80 0x80034ABC src/func_80034A80.c
|
||||
@@ -209,6 +211,7 @@
|
||||
0x8009107C 0x800910B0 src/func_8009107C.c
|
||||
0x800912D4 0x800912FC src/func_800912D4.c
|
||||
0x800912FC 0x8009132C src/func_800912FC.c
|
||||
0x8009132C 0x80091370 src/func_8009132C.c
|
||||
0x80092068 0x80092088 src/func_80092068.c
|
||||
0x80092088 0x800920BC src/func_80092088.c
|
||||
0x800920BC 0x800920DC src/func_800920BC.c
|
||||
|
||||
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* func_800129C8 — 72 bytes at 0x800129C8..0x80012A10
|
||||
*
|
||||
* Calls a teardown routine with a fixed displacement from the first argument and
|
||||
* a value read through the second, then clears that value. Both null cases return
|
||||
* zero through the SAME epilogue, so the source uses guarded blocks rather than
|
||||
* early returns.
|
||||
*
|
||||
* The observed instructions are:
|
||||
* addiu sp,sp,-24
|
||||
* sw s0,16(sp)
|
||||
* move s0,a1 ; s0 = flag pointer
|
||||
* beqz s0,0x800129F8 ; if (flag == 0) goto return-zero
|
||||
* sw ra,20(sp) ; save ra (delay slot)
|
||||
* lw a1,0(s0) ; a1 = *flag
|
||||
* nop
|
||||
* beqz a1,0x800129FC ; if (*flag == 0) return 0
|
||||
* move v0,zero ; return value (delay slot)
|
||||
* jal 0x80026560
|
||||
* addiu a0,a0,152 ; first argument = p + 152 (delay slot)
|
||||
* sw zero,0(s0) ; *flag = 0
|
||||
* F8: move v0,zero ; return 0
|
||||
* FC: lw ra,20(sp)
|
||||
* lw s0,16(sp)
|
||||
* addiu sp,sp,24
|
||||
* jr ra
|
||||
* nop
|
||||
*
|
||||
* The second argument is kept in `s0` across the call, which is why the frame
|
||||
* saves both `ra` and `s0`. The value read through the pointer is passed as the
|
||||
* callee's second argument and the pointer is cleared afterwards.
|
||||
*
|
||||
* LIMITS: the displacement (152) and the parameter types are hypotheses read from
|
||||
* the instruction shape; what the pointer and the callee mean is unknown and is
|
||||
* not guessed here. Only the compiled bytes are evidence.
|
||||
*/
|
||||
|
||||
int func_800129C8(char *p, int *flag) {
|
||||
if (flag == 0)
|
||||
return 0;
|
||||
|
||||
if (*flag != 0) {
|
||||
func_80026560(p + 152, *flag);
|
||||
*flag = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* func_80031F2C — 76 bytes at 0x80031F2C..0x80031F78
|
||||
*
|
||||
* Copies either one word or four words out of a structure reached through the
|
||||
* first argument, depending on a flag word: the single-word case jumps over the
|
||||
* four-word case, and both converge on one epilogue.
|
||||
*
|
||||
* The observed instructions are:
|
||||
* lw a2,164(a0) ; q = p->ptr_a4
|
||||
* nop
|
||||
* lw v0,1300(a2) ; q->word_514 (the flag)
|
||||
* nop
|
||||
* bnez v0,0x80031F50 ; if (flag != 0) take the four-word arm
|
||||
* move a3,a1 ; out = a1 (delay slot)
|
||||
* lw v0,1308(a2) ; q->word_51c
|
||||
* j 0x80031F70
|
||||
* sw v0,0(a3) ; out[0] = v0 (delay slot)
|
||||
* 50: lw v0,1308(a2)
|
||||
* lw v1,1312(a2)
|
||||
* lw a0,1316(a2)
|
||||
* lw a1,1320(a2)
|
||||
* sw v0,0(a3) ; out[0..3] = four words
|
||||
* sw v1,4(a3)
|
||||
* sw a0,8(a3)
|
||||
* sw a1,12(a3)
|
||||
* 70: jr ra
|
||||
* nop
|
||||
*
|
||||
* Note the four-word arm re-reads the SAME first field that the one-word arm
|
||||
* reads (offset 0x51c), so the two arms differ only in how many words follow.
|
||||
*
|
||||
* LIMITS: the pointer offset (0xa4) and the five field offsets (0x514, 0x51c,
|
||||
* 0x520, 0x524, 0x528) are hypotheses read from the instruction shape; what the
|
||||
* structure holds is unknown and is not guessed here. Only the compiled bytes are
|
||||
* evidence.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int word_00;
|
||||
int word_04;
|
||||
int word_08;
|
||||
int word_0c;
|
||||
} func_80031F2C_block;
|
||||
|
||||
void func_80031F2C(char *p, int *out) {
|
||||
char *q = *(char **)(p + 164);
|
||||
|
||||
if (*(int *)(q + 1300) == 0)
|
||||
out[0] = *(int *)(q + 1308);
|
||||
else
|
||||
*(func_80031F2C_block *)out = *(func_80031F2C_block *)(q + 1308);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* func_8009132C — 68 bytes at 0x8009132C..0x80091370
|
||||
*
|
||||
* Reads a gp-relative mode byte, clears a gp-relative state word to -1, and when
|
||||
* the mode is exactly 1 makes a two-argument call before a final no-argument call.
|
||||
* The mode byte is read BEFORE the state word is cleared.
|
||||
*
|
||||
* The observed instructions are:
|
||||
* addiu sp,sp,-24
|
||||
* lbu v1,3388(gp) ; mode = D_80122674 <- UNSIGNED byte
|
||||
* li v0,-1
|
||||
* sw v0,1468(gp) ; D_80121EF4 = -1
|
||||
* li v0,1
|
||||
* bne v1,v0,0x80091358 ; if (mode != 1) skip the first call
|
||||
* sw ra,16(sp) ; save ra (delay slot)
|
||||
* lw a0,3368(gp) ; D_80122660
|
||||
* lw a1,3384(gp) ; D_80122670
|
||||
* jal 0x8008FCD8
|
||||
* nop
|
||||
* 58: jal 0x800912D4
|
||||
* nop
|
||||
* lw ra,16(sp)
|
||||
* addiu sp,sp,24
|
||||
* jr ra
|
||||
* nop
|
||||
*
|
||||
* Two source-shape requirements: the mode byte must be loaded before the state
|
||||
* store (reading it inline in the condition lets cc1 sink the load below the
|
||||
* store), and the local it is read into must be an `int`, not an `unsigned char`
|
||||
* — an `unsigned char` local makes cc1 re-mask the already-zero-extended `lbu`
|
||||
* result with `andi v0,v0,0xff`, costing 4 bytes.
|
||||
*
|
||||
* LIMITS: the four gp offsets (3388 = 0xD3C, 1468 = 0x5BC, 3368 = 0xD28,
|
||||
* 3384 = 0xD38) and the two callees are hypotheses read from the instruction
|
||||
* shape; the offsets are facts about this executable's gp layout (gp =
|
||||
* 0x80121938). What the mode and the state mean is unknown and is not guessed
|
||||
* here. The `lbu` shows the mode is an unsigned byte. Only the compiled bytes are
|
||||
* evidence.
|
||||
*/
|
||||
|
||||
extern unsigned char D_80122674;
|
||||
extern int D_80121EF4;
|
||||
extern int D_80122660;
|
||||
extern int D_80122670;
|
||||
|
||||
void func_8009132C(void) {
|
||||
int mode = D_80122674;
|
||||
|
||||
D_80121EF4 = -1;
|
||||
if (mode == 1)
|
||||
func_8008FCD8(D_80122660, D_80122670);
|
||||
func_800912D4();
|
||||
}
|
||||
Reference in New Issue
Block a user