What it costs to call another function
Call another function and your function's shape changes. The culprit is bl: it overwrites the link register lr with the resume address — but lr already held the return address handed to us, and losing it strands us from our own caller. So the first job is to stash it somewhere that survives the call: a stack frame.
Here's frame_ex(s32 x) { return process(x) - 5; }:
stwu r1,-16(r1) # PROLOGUE: push a 16-byte frame (r1 is the stack pointer)
mflr r0 # r0 = our return address (the link register)
stw r0,20(r1) # save it into the caller's frame, above our own
bl process # call process(x) — trashes lr, but we saved it
lwz r0,20(r1) # EPILOGUE: reload our return address
subi r3,r3,5 # adjust the return value
mtlr r0 # restore lr
addi r1,r1,16 # pop the frame
blr # return
Every non-leaf function wears the same prologue and epilogue. stwu r1, -N(r1) opens the frame and chains it back to the caller's. mflr and stw hide the return address on the way in; lwz, mtlr, and addi r1 unwind it on the way out. None of it is the point of the function, so skim past it to the real work in the middle.
Where does the frame land? After stwu r1, -16(r1), r1 sits 16 bytes lower, and slots lay out:
20(r1) LR save slot (in the caller's frame) <- our return address goes here
16(r1) caller's back-chain word
12(r1) saved-register slot (used in later lessons)
8(r1) parameter area
4(r1) our own LR save slot (unused — leaf callees fill it)
0(r1) back-chain: points at the old r1 (= r1 + 16)
The return address at 20(r1) isn't ours — it lives in the caller's frame, 16 + 4 bytes above the stack pointer we just dropped.
func_8026ffa4 reuses this prologue and epilogue verbatim, so ignore them. The only instruction doing real work is the one between the bl and the lwz.
Your task
Write func_8026ffa4, which calls compute(x) and returns a value derived from the result. compute is declared for you. Expect a full prologue and epilogue around the bl.