|
|
|
@@ -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;
|
|
|
|
|
}
|