Files
BFM-decomp/cookbook/C0239.md
T

2.1 KiB

§218 — A NARROW TYPE AT THE ABI BOUNDARY COSTS AN IN-PLACE sll/sra PAIR — on the RETURN as well as on the PARAMETER (P31 S58)

Extends §43, whose tell is stated in the negative ("absence of in-place sll/sra proves 32-bit params"). This is the cost direction, and it applies to the return type too, which §43 does not cover.

1. A NARROW RETURN TYPE IN THE PROTOTYPE COSTS A SIGN-EXTENSION AT EVERY CALL SITE. func_80183258 (ov_SC04_011, 23 ins): the TU's authoritative prototype is extern s16 func_80174774(void); (atlas tu=('s16',())). Calling it directly forces an sll v0,v0,0x10 / sra pair the target does not have — even though the result feeds only a zero-test. The atlas row is byte-true for the SYMBOL but must not be allowed to reach the call site uncast. Fix, which is the TU's own house style: a cast-at-call through an s32-returning function pointer, ((s32 (*)(void))func_80174774)().

2. A NARROW ARG CAST EMITS THE PAIR IN PLACE ON THE ARGUMENT REGISTER — AND PERTURBS HEAD ALLOCATION. func_8017EAC0 (ov_SC02_011, 16 ins) is the clean A/B: without the (s16)a1 narrowing of arg4 the head is the naive move $a3,$a1 shape, 15 ins; with it, the sll/sra pair displaces the allocator into routing $a0 through $v0, producing the target's odd addu $v0,$a0 / addu $a1,$v0 head — 16 ins, MATCH. func_8017C624 shows the same 2-insn pre-call form (§18484). So a strange-looking head copy chain is a tell for a narrowed argument, not a scheduling artefact.

3. WHEN THE TU'S DECLARATION IS THE NARROW ONE AND THE TARGET IS 32-BIT, USE §202's DEF-SIDE ALIAS. func_80185C6C (ov_SC06_029, 7 ins): the TU carries extern void *func_80185C6C(s16, s32); at four sites, but the target has no sll/sra on $a0 at all — both args are 32-bit. Adopting s16 costs a sign-extension from instruction #1, and a K&R (int,int)-promoted definition conflicts with the s16 prototype. The definition was banked as aF80185C6C __asm__("func_80185C6C") with the TU's declarations untouched and callers unaffected.