Files
BFM-decomp/cookbook/C0261.md
T

1.6 KiB
Raw Blame History

§240 — A + K + B: WRITE THE CONSTANT BETWEEN THE TWO RUNTIME TERMS (P31 S58b)

§164-16 says parentheses and operand order are inert for +/-. That is true of where the constant ends up; it is NOT true of which runtime term the addiu attaches to.

func_8018364C (ov_SC03_105, 17 oracle calls): the target emits addiu $a1,$a1,0x3000 before addu $a1,$a0,$a1. Every left-to-right spelling of i*0x200 + r%1024 + 0x3000 emitted addu then addiu. Measured:

source emission
A + B + K addu first, then addiu — wrong
A + K + B addiu on B, then addu with A — target
explicit temp statement correct order, but register-allocation drift ($a0/$a1 swap)
inline call in the final expression extra move

split_tree's rebuild attaches the constant to the term it was written next to.

THE COMPOUND-ASSIGNMENT COROLLARY. func_801824FC (ov_SC01_080, 14 oracle calls): in mem = mem - 0x20 + D*40 + (rand()&0x3F), every explicit-statement spelling — parenthesised, term- reordered, u32-barriered, temp-hoisted — canonicalised to mem + (D40 + rnd − 32). Only the compound mem -= 0x20; mem += … form put -0x20 on the memory operand as lw $a0 ; addiu $a0,-0x20 ahead of the D-term chain. (Cf. §219: += is not merely a style of RMW, it is an association dial.)

RELATED: ASSOCIATION CONTROL BY STATEMENT. func_80185EAC (ov_SC06_032): w = r + 0x200; as its own statement makes gcc reuse $s0 incrementally (addiu $s0,$s0,0x200 riding a jal rand delay slot); written inline it reassociated into an extra addiu $v0 and length-drifted.