Saving gprs and fprs
For a function that saves and restores n GPRs and m FPRs (n>2 and m>2), the saving can be done using individual store and load instructions or by calling system-provided routines.
For a function that saves and restores n GPRs and m FPRs
(n>2 and m>2), the saving can be done using individual
store and load instructions or by calling system-provided routines
as shown in the following example:
#The following example shows the prolog/epilog of a function #which save n GPRs and m FPRs:
mflr r0 #move LR into GPR 0
subi r12,r1,8*m #compute GPR save pointer
bla _savegpr1_<32-n> #branch and link to save GPRs
bla _savefpr_<32-m>
stwu r1,<-frame_size>(r1) #update SP and save caller's SP
...
<save CR if necessary>
...
... #body of function
...
<reload save CR if necessary>
...
<reload caller's SP into r1> #see note below on
subi r12,r1,8*m #compute CPR restore pointer
bla _restgpr1_<32-n> #restore GPRs
ba _restfpr_<32-m> #restore FPRs and return
Note: The calling function SP can be restored by either adding the frame_size value
to the current SP whenever the frame_size is known or by
reloading it from offset 0 from the current SP. The first approach
is more efficient, but not possible for functions that use the alloca subroutine to dynamically allocate
stack space.
The following example shows a GPR save routine when FPRs are saved:
_savegpr1_13 stw r13,-76(r12) #save r13
_savegpr1_14 stw r14,-72(r12) #save r14
_savegpr1_15 stw r15,-68(r12) #save r15
_savegpr1_16 stw r16,-64(r12) #save r16
_savegpr1_17 stw r17,-60(r12) #save r17
_savegpr1_18 stw r18,-56(r12) #save r18
_savegpr1_19 stw r19,-52(r12) #save r19
_savegpr1_20 stw r20,-48(r12) #save r20
_savegpr1_21 stw r21,-44(r12) #save r21
_savegpr1_22 stw r22,-40(r12) #save r22
_savegpr1_23 stw r23,-36(r12) #save r23
_savegpr1_24 stw r24,-32(r12) #save r24
_savegpr1_25 stw r25,-28(r12) #save r25
_savegpr1_26 stw r26,-24(r12) #save r26
_savegpr1_27 stw r27,-20(r12) #save r27
_savegpr1_28 stw r28,-16(r12) #save r28
_savegpr1_29 stw r29,-12(r12) #save r29
stw r30,-8(r12) #save r30
stw r31,-4(r12) #save r31
blr #return
The following example shows an FPR save routine:
_savefpr_14 stfd f14,-144(r1) #save f14
_savefpr_15 stfd f15,-136(r1) #save f15
_savefpr_16 stfd f16,-128(r1) #save f16
_savefpr_17 stfd f17,-120(r1) #save f17
_savefpr_18 stfd f18,-112(r1) #save f18
_savefpr_19 stfd f19,-104(r1) #save f19
_savefpr_20 stfd f20,-96(r1) #save f20
_savefpr_21 stfd f21,-88(r1) #save f21
_savefpr_22 stfd f22,-80(r1) #save f22
_savefpr_23 stfd f23,-72(r1) #save f23
_savefpr_24 stfd f24,-64(r1) #save f24
_savefpr_25 stfd f25,-56(r1) #save f25
_savefpr_26 stfd f26,-48(r1) #save f26
_savefpr_27 stfd f27,-40(r1) #save f27
_savefpr_28 stfd f28,-32(r1) #save f28
_savefpr_29 stfd f29,-24(r1) #save f29
stfd f30,-16(r1) #save f30
stfd f31,-8(r1) #save f31
stw r0 , 8(r1) #save LR in
#caller's frame
blr #return
The following example shows a GPR restore routine when FPRs are saved:
_restgpr1_13 lwz r13,-76(r12) #restore r13
_restgpr1_14 lwz r14,-72(r12) #restore r14
_restgpr1_15 lwz r15,-68(r12) #restore r15
_restgpr1_16 lwz r16,-64(r12) #restore r16
_restgpr1_17 lwz r17,-60(r12) #restore r17
_restgpr1_18 lwz r18,-56(r12) #restore r18
_restgpr1_19 lwz r19,-52(r12) #restore r19
_restgpr1_20 lwz r20,-48(r12) #restore r20
_restgpr1_21 lwz r21,-44(r12) #restore r21
_restgpr1_22 lwz r22,-40(r12) #restore r22
_restgpr1_23 lwz r23,-36(r12) #restore r23
_restgpr1_24 lwz r24,-32(r12) #restore r24
_restgpr1_25 lwz r25,-28(r12) #restore r25
_restgpr1_26 lwz r26,-24(r12) #restore r26
_restgpr1_27 lwz r27,-20(r12) #restore r27
_restgpr1_28 lwz r28,-16(r12) #restore r28
_restgpr1_29 lwz r29,-12(r12) #restore r29
lwz r30,-8(r12) #restore r30
lwz r31,-4(r12) #restore r31
blr #return
The following example shows an FPR restore routine:
_restfpr_14 lfd r14,-144(r1) #restore r14
_restfpr_15 lfd r15,-136(r1) #restore r15
_restfpr_16 lfd r16,-128(r1) #restore r16
_restfpr_17 lfd r17,-120(r1) #restore r17
_restfpr_18 lfd r18,-112(r1) #restore r18
_restfpr_19 lfd r19,-104(r1) #restore r19
_restfpr_20 lfd r20,-96(r1) #restore r20
_restfpr_21 lfd r21,-88(r1) #restore r21
_restfpr_22 lfd r22,-80(r1) #restore r22
_restfpr_23 lfd r23,-72(r1) #restore r23
_restfpr_24 lfd r24,-64(r1) #restore r24
_restfpr_25 lfd r25,-56(r1) #restore r25
_restfpr_26 lfd r26,-48(r1) #restore r26
_restfpr_27 lfd r27,-40(r1) #restore r27
_restfpr_28 lfd r28,-32(r1) #restore r28
_restfpr_29 lwz r0,8(r1) #get return
#address from
#frame
lfd r29,-24(r1) #restore r29
mtlr r0 #move return
#address to LR
lfd r30,-16(r1) #restore r30
lfd r31,-8(r1) #restore r31
blr #return