phase9: merge B 2 — 394 regions / 385 distinct bodies
B: 32 new this cycle. Load-bearing insight: frame slots never read back are the callee's 9th/10th stack arguments (0x80057748 was 68-vs-80 until the 10-arg call). Branchless conditional lever (ternary-zero differs from if/else — sltu+negu+and). negu evidence set grows (3rd row) for finding 26's toolchain direction. Sibling 0x8005789C (11th stack arg) recorded with the start-from-10-args note. Gate MATCH whole-binary SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
This commit is contained in:
@@ -111,6 +111,7 @@
|
||||
0x80031F78 0x80031FC4 src/func_80031F78.c
|
||||
0x800321EC 0x800321F8 src/func_800321EC.c
|
||||
0x80034A80 0x80034ABC src/func_80034A80.c
|
||||
0x800354F8 0x80035548 src/func_800354F8.c
|
||||
0x80036308 0x80036328 src/func_80036308.c
|
||||
0x80036328 0x8003636C src/func_80036328.c
|
||||
0x8003636C 0x80036378 src/func_8003636C.c
|
||||
@@ -150,6 +151,7 @@
|
||||
0x8005182C 0x80051864 src/func_8005182C.c
|
||||
0x80052C98 0x80052CAC src/func_80052C98.c
|
||||
0x80057524 0x80057564 src/func_80057524.c
|
||||
0x80057748 0x80057798 src/func_80057748.c
|
||||
0x8005784C 0x8005789C src/func_8005784C.c
|
||||
0x800579A0 0x800579F0 src/func_800579A0.c
|
||||
0x80057AE0 0x80057B30 src/func_80057AE0.c
|
||||
|
||||
|
@@ -0,0 +1,59 @@
|
||||
/* func_800354F8 — 0x800354F8..0x80035548 (80 bytes).
|
||||
*
|
||||
* Original words:
|
||||
* 27BDFFE8 addiu sp,sp,-24
|
||||
* AFB00010 sw s0,16(sp)
|
||||
* AFBF0014 sw ra,20(sp)
|
||||
* 0C00CEB7 jal 0x80033ADC
|
||||
* 00808021 _move s0,a0 (delay slot) keep the argument
|
||||
* 0C00D18E jal 0x80034638
|
||||
* 02002021 _move a0,s0 (delay slot)
|
||||
* 0C00D2A0 jal 0x80034A80
|
||||
* 02002021 _move a0,s0 (delay slot)
|
||||
* 0C00C7AF jal 0x80031EBC
|
||||
* 02002021 _move a0,s0 (delay slot)
|
||||
* 0C00D2AF jal 0x80034ABC
|
||||
* 02002021 _move a0,s0 (delay slot)
|
||||
* 0C00D394 jal 0x80034E50
|
||||
* 02002021 _move a0,s0 (delay slot)
|
||||
* 8FBF0014 lw ra,20(sp)
|
||||
* 8FB00010 lw s0,16(sp)
|
||||
* 27BD0018 addiu sp,sp,24
|
||||
* 03E00008 jr ra
|
||||
* 00000000 nop
|
||||
*
|
||||
* Six calls in sequence, all with the routine's single argument, none returning a value.
|
||||
*
|
||||
* The first call receives the argument directly (`move s0,a0` is in its delay slot because
|
||||
* `s0` is the *save*, not the setup), and every later call is set up by `move a0,s0` in its
|
||||
* own delay slot — so all six call sites share one saved register and the frame exists only
|
||||
* for that. Six identical `move`-into-delay-slot patterns is the signature of a flat call
|
||||
* sequence rather than a loop, and the order below is the order they appear.
|
||||
*
|
||||
* One of the callees, `0x80034A80`, is already registered in this project as a
|
||||
* compiler-artefact row (a 112-byte frame receiving a 16-byte struct copy that is then
|
||||
* discarded), which is independent corroboration that this address is a real routine start
|
||||
* and that this row calls what it appears to call.
|
||||
*
|
||||
* LIMITS: the callees are named for their addresses and nothing establishes their
|
||||
* signatures beyond the single register set at each site; all six are written as taking one
|
||||
* `int` because that is all the original passes. Whether any of them returns a value is
|
||||
* invisible here, since no result is used.
|
||||
*/
|
||||
|
||||
void func_80033ADC(int a0);
|
||||
void func_80034638(int a0);
|
||||
void func_80034A80(int a0);
|
||||
void func_80031EBC(int a0);
|
||||
void func_80034ABC(int a0);
|
||||
void func_80034E50(int a0);
|
||||
|
||||
void func_800354F8(int a0)
|
||||
{
|
||||
func_80033ADC(a0);
|
||||
func_80034638(a0);
|
||||
func_80034A80(a0);
|
||||
func_80031EBC(a0);
|
||||
func_80034ABC(a0);
|
||||
func_80034E50(a0);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/* func_80057748 — 0x80057748..0x80057798 (80 bytes).
|
||||
*
|
||||
* Original words:
|
||||
* 27BDFFD0 addiu sp,sp,-48
|
||||
* 30A700FF andi a3,a1,0xff narrow the second argument
|
||||
* 30C600FF andi a2,a2,0xff narrow the third
|
||||
* AFA70020 sw a3,32(sp) local[8] = narrowed a1
|
||||
* 0007382B sltu a3,zero,a3 a3 = (narrowed a1 != 0)
|
||||
* 00073823 negu a3,a3 a3 = 0 or -1
|
||||
* 24050001 li a1,1
|
||||
* AFA60024 sw a2,36(sp) local[9] = narrowed a2
|
||||
* 2406FFFF li a2,-1
|
||||
* 00873824 and a3,a0,a3 a3 = a0 & that mask
|
||||
* AFBF0028 sw ra,40(sp)
|
||||
* AFA00010 sw zero,16(sp) local[0] = 0
|
||||
* AFA00014 sw zero,20(sp) local[1] = 0
|
||||
* AFA00018 sw zero,24(sp) local[2] = 0
|
||||
* 0C015D99 jal 0x80057664
|
||||
* AFA0001C _sw zero,28(sp) (delay slot) local[3] = 0
|
||||
* 8FBF0028 lw ra,40(sp)
|
||||
* 27BD0030 addiu sp,sp,48
|
||||
* 03E00008 jr ra
|
||||
* 00000000 nop
|
||||
*
|
||||
* **The zero-or-minus-one mask is the interesting construction, and it is the
|
||||
* branchless conditional.** `sltu a3,zero,a3` sets `a3` to 1 iff the narrowed argument is
|
||||
* non-zero, and the following `negu a3,a3` turns that into 0 or **-1** — so `and a3,a0,a3`
|
||||
* either keeps `a0` or clears it with **no branch at all**. That is exactly what a
|
||||
* conditional expression `(narrowed ? a0 : 0)` compiles to when cc1 avoids a branch, and it
|
||||
* is why the same argument is written as a ternary here rather than an `if`.
|
||||
*
|
||||
* `negu`, not the trapping `sub`, is again positive evidence for this toolchain (finding
|
||||
* 26's direction), and it appears twice in this family.
|
||||
*
|
||||
* The frame is 48 bytes and the call's outgoing register arguments are `a0`, 1, -1 and the
|
||||
* masked value, while the four words at 16-28(sp) are zeroed — which is the outgoing stack
|
||||
* argument area, so the callee takes **eight** arguments and the last four are all zero.
|
||||
* The two narrowed values land at 32 and 36(sp), i.e. beyond the outgoing area, so they are
|
||||
* frame locals that this routine writes and never reads.
|
||||
*
|
||||
* LIMITS: the mask 0xff, the constants 1 and -1, and the frame layout are read from the
|
||||
* bytes. That the narrowed values are never read back follows from their frame offsets being
|
||||
* past the argument area; nothing establishes why they are stored. Whether the callee's last
|
||||
* four arguments are genuinely meant to be zero or are a partially filled structure cannot
|
||||
* be told from this body, and the eight-argument signature is inferred purely from the four
|
||||
* zeroed stack words.
|
||||
*/
|
||||
|
||||
void func_80057664(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
|
||||
int a8, int a9);
|
||||
|
||||
void func_80057748(int a0, int a1, int a2)
|
||||
{
|
||||
int narrowed1 = a1 & 0xff;
|
||||
int narrowed2 = a2 & 0xff;
|
||||
|
||||
func_80057664(a0, 1, -1, narrowed1 ? a0 : 0, 0, 0, 0, 0, narrowed1, narrowed2);
|
||||
}
|
||||
Reference in New Issue
Block a user