Files
BFM-decomp/cookbook/C0262.md
T

1.7 KiB
Raw Blame History

§241 — THE FOLDED SIGN-EXTEND-AND-SCALE: sll 16 ; sra (16 − log2 scale) (P31 S58b)

A sll $x,16 followed by sra $x,N with N < 16 is not a division and not a plain extension: it is a sign-extension of a halfword fused with a left shift of 16 − N.

pair meaning scale
sll 16 ; sra 16 plain (s16)x ×1
sll 16 ; sra 14 ((s16)x) * 4 ×4 — indexes a 4-byte table
sll 17 ; sra 14 (s16)(x*2) * 4 doubled index, 8-byte elements
sll 16 ; sra 17 ((s16)x) >> 1 signed halve (N > 16)

BYTE-VERIFIED. asm/ov_SC07_007/.../func_80180EC8.s lines 11–16: sll $v0,$v0,16 ; sra $v0,$v0,14 feeding an lw off a %lo base — i.e. a 4-byte-element table indexed by a sign-extended halfword. The first draft used explicit *4 scaling and produced sra 12.

THE C SPELLINGS.

  • ×4 fold: write the index unscaled and sign-extended — ((v << 16) >> 16) — and let gcc fold the scale into the sra amount (func_80180EC8).
  • doubled index into 8-byte rows: (s16)(m * 2) used as the subscript gives sll 17 ; sra 14 exactly, with the second element as base+4 off the shared lui/addiu (func_801AE734, md_SC07_004).
  • signed halve: ((s16)u16_global) >> 1 gives lhu ; sll 16 ; sra 17 (func_8017F30C, ov_SC06_022; func_801800D0, ov_SC03_029; func_801AC3C8's accumulator, where the temp must be s16 not s32 or you get a bare sra 17 with no leading sll).

THE DISCRIMINATOR vs §167-03's HImode-division reading: ask what consumes the result. If it feeds an lw/lhu address, it is a scaled index (this section). If it feeds an addu/subu sum or a compare, it is a divide (§167-03/§167-25).