The handwritten assembly is located where commented and with less indentation levels(lines 40-80).
The idea is to have a reliable push where the stack pointer $r1
remains unchanged.
On this proposal, the $r10
is used as the pointer to the top of the stack and it'll be initialized by having the same address as the stack pointer $r1
:
mr 10, 1
Push will be accomplished with 1 instructions:
stdu @push_element_register, -16(10)
Pop will be accomplished with 2 instructions:
ld @pop_element_register, 0(10)
addi 10, 10, 16
When branching out of the function (aka when the stack pointer changes), a fake call stack is built in order to save the pushed elements from being overwritten by the new call stack:
mflr 0
std 0, 16(1) # save LR
stdu 1, -32(10) # create 32 bytes additionally for the stack and backchain
mr 1, 10
bl @target
When that branch returns, the fake call stack restores the stack pointer $r1
and the pointer to the top of the stack $r10
:
addi 10, 1, 32 # restore top of the stack address
ld 1, 0(1) # backchain
ld 0, 16(1) # restore LR
mtlr 0
vret and vcall will be changed in order to be consistent with push/pop? i.e., will r10 be saved in stack before a (v)call?will r10 be copied to r1 before a call (in order to not overwrite the stack)?