diff --git a/config/regions.tsv b/config/regions.tsv index 36efdaf..aa14aea 100644 --- a/config/regions.tsv +++ b/config/regions.tsv @@ -99,6 +99,7 @@ 0x80030358 0x80030390 src/func_80030358.c 0x80031F78 0x80031FC4 src/func_80031F78.c 0x800321EC 0x800321F8 src/func_800321EC.c +0x80034A80 0x80034ABC src/func_80034A80.c 0x80036308 0x80036328 src/func_80036308.c 0x8003636C 0x80036378 src/func_8003636C.c 0x80036378 0x80036380 src/func_80036378.c diff --git a/src/func_80034A80.c b/src/func_80034A80.c new file mode 100644 index 0000000..c1be3e0 --- /dev/null +++ b/src/func_80034A80.c @@ -0,0 +1,58 @@ +/* func_80034A80 — 0x80034A80..0x80034ABC (60 bytes). + * + * Original words: + * 27BDFF90 addiu sp,sp,-112 + * 3C058011 lui a1,0x8011 + * 24A5C114 addiu a1,a1,-16108 a1 = 0x8010C114 + * 8CA20000 lw v0,0(a1) + * 8CA30004 lw v1,4(a1) + * 8CA40008 lw a0,8(a1) + * AFA20010 sw v0,16(sp) + * AFA30014 sw v1,20(sp) + * AFA40018 sw a0,24(sp) + * 8CA2000C lw v0,12(a1) + * AFA2001C sw v0,28(sp) + * 27BD0070 addiu sp,sp,112 + * 03E00008 jr ra + * 00000000 nop + * + * A 112-byte frame that exists only to receive a 16-byte copy from a global, which + * is then discarded: nothing reads the frame, nothing is returned, and the frame is + * torn down immediately. Four words are loaded and four are stored, the fourth load + * scheduled after the first three stores. + * + * **This is a compiler artefact, like `0x8002E3A8`'s bare frame, but one step + * further on.** The frame is 80 bytes larger than the object copied into it, and + * the copy lands at offset 16 rather than 0 — so the source declared a local + * aggregate of 112 bytes and assigned a 16-byte struct into a member 16 bytes in, + * after which the local is dead. cc1 did not eliminate the stores (GCC 2.7.2 does + * not do dead-store elimination on aggregate members), so the whole sequence + * survives. + * + * `lui a1,0x8011` + `addiu a1,a1,-16108` is the macro expansion of a **symbol** + * address (cookbook finding 1; a literal would give `ori`, finding 5), so the + * source is the global at **0x8010C114** — `0x80110000 - 16108` is 0x8010C114, and + * note the displacement is negative, so the `lui` immediate is *not* the top half + * of the address (the sign-adjusted `%lo` trap). + * + * LIMITS: the frame size 112, the copy offset 16 and the four-word width are read + * from the displacements; the *declaration* that produces them is a reconstruction + * of compiler behaviour, not of a statement — the sizes are chosen to make the + * frame and offsets come out, and any 16-byte aggregate at offset 16 of a 112-byte + * frame would produce the same bytes. Since the copied data is never used, no + * observable property of this routine depends on what the type was. + */ + +typedef struct { + int w[4]; +} Blk16; + +extern Blk16 D_8010C114; + +void func_80034A80(void) +{ + char frame[112]; + Blk16 *slot = (Blk16 *)(frame + 16); + + *slot = D_8010C114; +}