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