Two lfs loads, only one is a global
Two pieces are already familiar. A float global reads as an lfs of a named symbol. Pool a float literal as an @N constant and it reads as an lfs too, just with a synthetic symbol. Once both land in one expression, you're staring at two lfs loads that are nearly twins, and the relocation name is the one thing that pries them apart. One came from a global you wrote. The other is a compiler-minted @N label for the constant.
With both values in FPRs, an fmuls does the multiply and an stfs sends the single-precision result back to the destination float global. The suffix still bites, just as the literal lesson flagged. Drop the f and a bare 0.5 is a double, lifting the expression to double precision and giving lfd/fmul/frsp. The f is the only reason you stay on lfs/fmuls/stfs.
Here's spin(), multiplying float global gAngle by 1.5f and stashing the result in gWobble:
lfs f1, @5@sda21(r2) # load the pooled literal 1.5f
lfs f0, gAngle@sda21(r2) # load the float global gAngle
fmuls f0, f1, f0 # gAngle * 1.5f
stfs f0, gWobble@sda21(r2) # gWobble = result
blr
Both loads come through r2, the .sdata2 base, but @5 is the constant and gAngle is the real global. Your target does the same multiply-then-store over a different float global and a different literal. The two reloc names and the literal's value are all there in the disassembly.
Your task
The globals are declared for you: gVelocity and gScaled (both f32). Write func_80246a2c (no arguments, no return) to reproduce the assembly above.