2.3 KiB
§239 — TWO-STATEMENT INTEGER-SPACE MATERIALISATION REORDERS la vs sll; AND THE PLUS-TREE OPERAND ORDER (P31 S58b)
§164-01/§164-02 explain why parenthesisation and operand order are inert for &sym[i]. They are
not inert for the two constructs below, and both were found the hard way.
1. TO PUT THE BASE lui/addiu BEFORE THE INDEX sll, LEAVE POINTER SPACE. func_80186304
(ov_SC02_005, 72/72): every natural &D_xxx[i] / pointer-index spelling emits index-sll first,
then lui/addiu (cse qty_const swap, §164-02). The target emits base first. The fix is a
two-statement integer-space materialisation:
base = (s32)&sym; /* lui/addiu here */
p = (void **)(base + i * 8); /* sll, then addu */
That gets the expansion order right, but first-fit then assigned base→$a0/index→$v0; a
short-lived register s32 base __asm__("$2") (never live across a call, so §42e-safe) forced
base→$v0, index→$v1, and the card snapped to MATCH. This is the cheap hard-reg fix when only a
REGALLOC-PERM remains after the order is right.
2. FOR A REGISTER-HELD BASE, THE PLUS-TREE OPERAND ORDER IS THE DIAL. func_801A5C44
(md_SC07_003, 41/41): the target's addu $v1,$v1,$s1 ; lhu $v1,0x2($v1) appears only when the C
spells the shifted index term FIRST: ((idx << 2) + base + 2). Writing base + (idx << 2) emitted
addu $v1,$s1,$v1 on one arm and, worse, folded the +2 into the address so gcc reused $s1 itself
(addu $s1,$s1,$v1 ; lhu 2($s1)), clobbering a callee-saved register. §195-K's array-of-struct-vs-
address dichotomy covers global symbol bases; for a pointer local the dial is operand order.
3. AND FOR AN OT/TABLE POINTER, INTEGER FORM BEATS POINTER ARITHMETIC. func_80185910
(ov_SC02_000/ov_SC02_003, 140/140): (otz << 2) + (s32)tbl gives lw $v1,sp / sll $v1,2 / addu $v1,$v1,$s1; the tbl + otz pointer form misallocates. Same finding on func_80183478
(ov_SC06_029): folding the scale into a single initializer (idx = load * 8) makes cc1 expand the
index pseudo first, pinning it to $a0 and leaving $a2 for the counter.
BOUNDARY. None of this applies while the base is a plain global symbol reached by &sym[i] —
there §164-01/§164-02 still hold and the spelling is inert.