phase9: merge B 0x800AA01C — 400 regions / 391 distinct bodies (400-region milestone crossed)

B: 38 new this cycle. 0x800AA01C three-way mode switch (if/else-if/else
chain — arms are exact complements: set bit 3/clear 6 vs set 6/clear 3 vs
clear both). Contrast finding: the move a0,v0 after the lookup decides
whether the flush gets the looked-up object or the original a0 — one
instruction, re-verified per family row (0x800AAC44 negative recorded).
Gate MATCH whole-binary SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9.
This commit is contained in:
Christopher Williams
2026-09-24 02:46:02 -04:00
parent 4405bb7e68
commit 861aab3cd5
2 changed files with 75 additions and 0 deletions
+1
View File
@@ -271,6 +271,7 @@
0x800A9D58 0x800A9D90 src/func_800A9D58.c
0x800A9F7C 0x800A9FD4 src/func_800A9F7C.c
0x800A9FD4 0x800AA01C src/func_800A9FD4.c
0x800AA01C 0x800AA0A0 src/func_800AA01C.c
0x800AA2B4 0x800AA2F8 src/func_800AA2B4.c
0x800AA56C 0x800AA59C src/func_800AA56C.c
0x800AC818 0x800AC85C src/func_800AC818.c
1 # Code-region registry: one C region per matched function.
271 0x800A9D58
272 0x800A9F7C
273 0x800A9FD4
274 0x800AA01C
275 0x800AA2B4
276 0x800AA56C
277 0x800AC818
+74
View File
@@ -0,0 +1,74 @@
/* func_800AA01C — 0x800AA01C..0x800AA0A0 (132 bytes).
*
* Original words:
* 27BDFFE8 addiu sp,sp,-24
* AFB00010 sw s0,16(sp)
* AFBF0014 sw ra,20(sp)
* 0C02A0B4 jal 0x800A82D0 the shared lookup
* 00A08021 _move s0,a1 (delay slot) keep the mode
* 00402021 move a0,v0 the looked-up object becomes the working pointer
* 10800015 beqz a0,0x800AA08C
* 00000000 _nop (delay slot)
* 16000006 bnez s0,0x800AA058 <- mode != 0
* 00000000 _nop
* 90820014 lbu v0,20(a0)
* 34420008 ori v0,v0,0x8
* 0802A821 j 0x800AA084
* 304200BF _andi v0,v0,0xBF (delay slot) clear bit 6
* 24020001 li v0,1 <- 0x800AA058, mode == 1 test
* 16020006 bne s0,v0,0x800AA078
* 00000000 _nop (delay slot)
* 90820014 lbu v0,20(a0) <- mode 1 arm
* 34420040 ori v0,v0,0x40 set bit 6
* 0802A821 j 0x800AA084
* 304200F7 _andi v0,v0,0xF7 (delay slot) clear bit 3
* 90820014 lbu v0,20(a0) <- 0x800AA078, the default arm
* 304200B7 andi v0,v0,0xB7 clear bits 6 and 3
* 0C02A0C4 jal 0x800A8310 <- 0x800AA084
* A0820014 _sb v0,20(a0) (delay slot) write the byte back
* 8FBF0014 lw ra,20(sp) <- 0x800AA08C
* 8FB00010 lw s0,16(sp)
* 27BD0018 addiu sp,sp,24
* 03E00008 jr ra
* 00000000 nop
*
* A three-way mode switch that edits two bits of a byte field in a looked-up object, then
* flushes. All three arms converge on one store and one flush, so this is a `switch`-like
* shape with a single tail rather than three returns.
*
* The masks are read-modify-write pairs, and the pairing is what identifies each arm:
* - mode 0 → `| 0x8` then `& ~0x40` — **sets** bit 3, **clears** bit 6;
* - mode 1 → `| 0x40` then `& ~0x8` — **sets** bit 6, **clears** bit 3;
* - anything else → `& 0xB7` — clears both.
* So the field encodes a two-state selection with a third "neither" case, and the two
* non-default arms are exact complements of each other. That is a strong structural signal the
* source was an `if`/`else if`/`else` chain rather than a switch with distinct bodies.
*
* The object pointer is moved into `a0` immediately after the lookup, so the flush receives
* the **looked-up object** — the opposite of the sibling row `0x800AAC44`, where the flush
* receives the routine's original `a0`. Two rows in one family that differ in exactly that
* respect, which is why the `move a0,v0` is worth checking on every row rather than assumed.
*
* LIMITS: the field offset 0x14 and the masks 0x08/0x40/0xB7 are read from the bytes. The
* comparison `bnez s0` then `li v0,1` / `bne s0,v0` shows the mode is compared against 0 and
* then 1, so the parameter is an index; its type is not otherwise constrained. The lookup is
* already registered in this project, corroborating the target.
*/
int func_800A82D0(int a0);
void func_800A8310(int p);
void func_800AA01C(int a0, int mode)
{
char *p = (char *)func_800A82D0(a0);
if (p != 0) {
if (mode == 0)
p[0x14] = (p[0x14] | 0x08) & ~0x40;
else if (mode == 1)
p[0x14] = (p[0x14] | 0x40) & ~0x08;
else
p[0x14] = p[0x14] & ~0x48;
func_800A8310((int)p);
}
}