Counting the daylight after mflo
You've seen nops trail an mflo since the warm-up divide. Time to make the pattern precise, because at this game's settings it follows a rule you can count on: IDO keeps two instruction slots between an mflo (or mfhi) and the jr ra. Real work can occupy those slots; whatever real work doesn't fill, nops do.
Here's mixed(a, b, c), which returns a * b + c:
multu a0, a1 # HI:LO = a * b
mflo t6 # fetch the low 32 bits — the product
addu v0, t6, a2 # + c … one slot of the window, filled
nop # the other slot — nothing left to put there
jr ra
nop
Two things to absorb:
multu, not mult. For a 32-bit result the low word is identical either way, so IDO uses the unsigned form even for s32 math. Expect it.
- Count from
mflo to jr: the addu is one slot, the nop is the second. Compare the pure a * b you met earlier — mflo v0 straight into two nops, because nothing needed doing. Same rule, different fill.
Why the window exists: the multiply unit is slow, and this compiler pads conservatively rather than proving the pipeline safe. The padding is emitted for you — you can't write a nop in C, and you never need to. What you can do is stop being surprised: see mflo, glance down two lines, and expect either work or padding before the return.
The target has the same skeleton with one real instruction in the window. Its operand order is the whole puzzle.
Your task
Write func_80183c10 to reproduce the target assembly.