Files
BFM-decomp/cookbook/C0367.md
T

1.2 KiB
Raw Blame History

§327 — A RANGE TEST MUST BE HImode: WITH s32 + A (u16) CAST GCC PROVES THE MASK REDUNDANT AND DROPS THE andi (P31 S67; byte-proven ov_SC02_039/func_8017EC34, 154 ins)

s32 q + (u16)q lets fold-const derive q = 0x7F ± (s16 x >> 1) and conclude the mask cannot change the value, so the andi never emits — a REAL −1 length drift that reads like a schedule difference and sends you hunting the scheduler. Declare u16 q and test q >= 0x2F && q < 0x80. Three more levers from the same function, all reusable:

  • §194-H in-place AND. v1 &= 0x2000; inside if (v1 != 0) — only the IN-PLACE form reuses the hard reg, which is what lets dbr speculate it into the guard's delay slot.
  • §3-T2 chain order. Put the LONG chain (p->0xA += D_8019B5E6[i]) BEFORE the short store (p->0x34 = s1+1); sched1 re-swaps the two shs itself, and the leading lh forces the genuine nop delay slot (may_trap_p on a MEM blocks dbr) while freeing $a0 for the table value.
  • Build the 2nd argument INLINE in the call with a (u16) cast. As a preceding statement (u16 code = ...; & 0xFFFF) its sll/ori/or chain outranks move $a0,$s1 in sched priority and steals the beqz delay slot.