Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc64 / setcontext.S
blobe47a57a0d6dca07804545cb2669aeb1e695fc518
1 /* Switch to context.
2    Copyright (C) 2002-2015 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <rtld-global-offsets.h>
21 #include <shlib-compat.h>
23 #define __ASSEMBLY__
24 #include <asm/ptrace.h>
25 #include "ucontext_i.h"
26 #include <asm/errno.h>
28         .section        ".toc","aw"
29 .LC__dl_hwcap:
30 #ifdef SHARED
31         .tc _rtld_global_ro[TC],_rtld_global_ro
32 #else
33         .tc _dl_hwcap[TC],_dl_hwcap
34 #endif
35         .section ".text"
37 #if SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4)
38 ENTRY(__novec_setcontext)
39         CALL_MCOUNT 1
40   mflr  r0
41   std   r31,-8(1)
42   cfi_offset(r31,-8)
43   std   r0,FRAME_LR_SAVE(r1)
44   cfi_offset (lr, FRAME_LR_SAVE)
45   stdu  r1,-128(r1)
46   cfi_adjust_cfa_offset (128)
47   mr    r31,r3
50  * If this ucontext refers to the point where we were interrupted
51  * by a signal, we have to use the rt_sigreturn system call to
52  * return to the context so we get both LR and CTR restored.
53  *
54  * Otherwise, the context we are restoring is either just after
55  * a procedure call (getcontext/swapcontext) or at the beginning
56  * of a procedure call (makecontext), so we don't need to restore
57  * msr and ctr.  We don't restore r13 since it will be used as
58  * the TLS pointer.  */
59   ld      r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
60   cmpdi r0,0
61   bne     L(nv_do_sigret)
63   li    r5,0
64   addi  r4,r3,UCONTEXT_SIGMASK
65   li    r3,SIG_SETMASK
66   bl    JUMPTARGET(__sigprocmask)
67   nop
68   cmpdi r3,0
69   bne   L(nv_error_exit)
71 # ifdef SHARED
72 /* Load _rtld-global._dl_hwcap.  */
73   ld    r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
74 # else
75   ld    r5,0(r5) /* Load extern _dl_hwcap.  */
76 # endif
78   lfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
79   lfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
80   lfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
82 # ifdef _ARCH_PWR6
83   /* Use the extended four-operand version of the mtfsf insn.  */
84   mtfsf  0xff,fp0,1,0
85 # else
86   .machine push
87   .machine "power6"
88   /* Availability of DFP indicates a 64-bit FPSCR.  */
89   andi.  r6,r5,PPC_FEATURE_HAS_DFP
90   beq    5f
91   /* Use the extended four-operand version of the mtfsf insn.  */
92   mtfsf  0xff,fp0,1,0
93   b      6f
94   /* Continue to operate on the FPSCR as if it were 32-bits.  */
96   mtfsf  0xff,fp0
98   .machine pop
99 # endif /* _ARCH_PWR6 */
100   lfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
101   lfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
102   lfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
103   lfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
104   lfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
105   lfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
106   lfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
107   lfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
108   lfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
109   lfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
110   lfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
111   lfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
112   lfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
113   lfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
114   lfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
115   lfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
116   lfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
117   lfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
118   lfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
119   lfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
120   lfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
121   lfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
122   lfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
123   lfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
124   lfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
125   lfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
126   lfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
127   lfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
128   lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
129   lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
131   /* End FDE now, because the unwind info would be wrong while
132      we're reloading registers to switch to the new context.  */
133   cfi_endproc
135   ld   r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
136   ld   r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
137   mtlr r0
138   ld   r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
139   ld   r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
140   ld   r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
141   mtxer r0
142   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
143   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
144   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
145   mtcr r0
146   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
147   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
148   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
149   ld   r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
150   ld   r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
151   ld   r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
152   ld   r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
153   /* Don't reload the thread ID or TLS pointer (r13).  */
154   ld   r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
155   ld   r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
156   ld   r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
157   ld   r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
158   ld   r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
159   ld   r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
160   ld   r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
161   ld   r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
162   ld   r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
163   ld   r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
164   ld   r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
165   ld   r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
166   ld   r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
167   ld   r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
168   ld   r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
169   ld   r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
170   ld   r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
172   /* Now we branch to the "Next Instruction Pointer" from the saved
173      context.  With the powerpc64 instruction set there is no good way to
174      do this (from user state) without clobbering either the LR or CTR.
175      The makecontext and swapcontext functions depend on the callers
176      LR being preserved so we use the CTR.  */
177   ld   r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
178   mtctr r0
179   ld   r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
180   ld   r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
181   bctr
183   /* Re-establish FDE for the rest of the actual setcontext routine.  */
184   cfi_startproc
185   cfi_offset (lr, FRAME_LR_SAVE)
186   cfi_adjust_cfa_offset (128)
188 L(nv_error_exit):
189   ld   r0,128+FRAME_LR_SAVE(r1)
190   addi r1,r1,128
191   mtlr r0
192         ld   r31,-8(r1)
193   blr
195   /* At this point we assume that the ucontext was created by a
196      rt_signal and we should use rt_sigreturn to restore the original
197      state.  As of the 2.4.21 kernel the ucontext is the first thing
198      (offset 0) in the rt_signal frame and rt_sigreturn expects the
199      ucontext address in R1.  Normally the rt-signal trampoline handles
200      this by popping dummy frame before the rt_signal syscall.  In our
201      case the stack may not be in its original (signal handler return with
202      R1 pointing at the dummy frame) state.  We do have the ucontext
203      address in R3, so simply copy R3 to R1 before the syscall.  */
204 L(nv_do_sigret):
205   mr   r1,r3,
206   li   r0,SYS_ify(rt_sigreturn)
207   sc
208   /* No return.  */
210 PSEUDO_END(__novec_setcontext)
212 compat_symbol (libc, __novec_setcontext, setcontext, GLIBC_2_3)
214 #endif
216         .section ".text"
217         .machine        "altivec"
218 ENTRY(__setcontext)
219         CALL_MCOUNT 1
220   mflr  r0
221   std   r31,-8(1)
222   cfi_offset(r31,-8)
223   std   r0,FRAME_LR_SAVE(r1)
224   cfi_offset (lr, FRAME_LR_SAVE)
225   stdu  r1,-128(r1)
226   cfi_adjust_cfa_offset (128)
227   mr    r31,r3
230  * If this ucontext refers to the point where we were interrupted
231  * by a signal, we have to use the rt_sigreturn system call to
232  * return to the context so we get both LR and CTR restored.
234  * Otherwise, the context we are restoring is either just after
235  * a procedure call (getcontext/swapcontext) or at the beginning
236  * of a procedure call (makecontext), so we don't need to restore
237  * msr and ctr.  We don't restore r13 since it will be used as
238  * the TLS pointer.  */
239   ld      r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
240   cmpdi r0,0
241   bne     L(do_sigret)
243   li    r5,0
244   addi  r4,r3,UCONTEXT_SIGMASK
245   li    r3,SIG_SETMASK
246   bl    JUMPTARGET(__sigprocmask)
247   nop
248   cmpdi r3,0
249   bne   L(error_exit)
251   ld    r5,.LC__dl_hwcap@toc(r2)
252   ld    r10,(SIGCONTEXT_V_REGS_PTR)(r31)
253 # ifdef SHARED
254 /* Load _rtld-global._dl_hwcap.  */
255   ld    r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
256 # else
257   ld    r5,0(r5) /* Load extern _dl_hwcap.  */
258 # endif
259   andis.  r6,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
260   beq   L(has_no_vec)
262   cmpdi r10,0
263   beq   L(has_no_vec)
264   lwz   r0,(33*16)(r10)
266   li    r9,(16*32)
267   mtspr VRSAVE,r0
268   cmpwi r0,0
269   beq   L(has_no_vec)
271   lvx   v19,r9,r10
272   la    r9,(16)(r10)
274   lvx   v0,0,r10
275   lvx   v1,0,r9
276   addi  r10,r10,32
277   addi  r9,r9,32
279   mtvscr  v19
280   lvx   v2,0,r10
281   lvx   v3,0,r9
282   addi  r10,r10,32
283   addi  r9,r9,32
285   lvx   v4,0,r10
286   lvx   v5,0,r9
287   addi  r10,r10,32
288   addi  r9,r9,32
290   lvx   v6,0,r10
291   lvx   v7,0,r9
292   addi  r10,r10,32
293   addi  r9,r9,32
295   lvx   v8,0,r10
296   lvx   v9,0,r9
297   addi  r10,r10,32
298   addi  r9,r9,32
300   lvx   v10,0,r10
301   lvx   v11,0,r9
302   addi  r10,r10,32
303   addi  r9,r9,32
305   lvx   v12,0,r10
306   lvx   v13,0,r9
307   addi  r10,r10,32
308   addi  r9,r9,32
310   lvx   v14,0,r10
311   lvx   v15,0,r9
312   addi  r10,r10,32
313   addi  r9,r9,32
315   lvx   v16,0,r10
316   lvx   v17,0,r9
317   addi  r10,r10,32
318   addi  r9,r9,32
320   lvx   v18,0,r10
321   lvx   v19,0,r9
322   addi  r10,r10,32
323   addi  r9,r9,32
325   lvx   v20,0,r10
326   lvx   v21,0,r9
327   addi  r10,r10,32
328   addi  r9,r9,32
330   lvx   v22,0,r10
331   lvx   v23,0,r9
332   addi  r10,r10,32
333   addi  r9,r9,32
335   lvx   v24,0,r10
336   lvx   v25,0,r9
337   addi  r10,r10,32
338   addi  r9,r9,32
340   lvx   v26,0,r10
341   lvx   v27,0,r9
342   addi  r10,r10,32
343   addi  r9,r9,32
345   lvx   v28,0,r10
346   lvx   v29,0,r9
347   addi  r10,r10,32
348   addi  r9,r9,32
350   lvx   v30,0,r10
351   lvx   v31,0,r9
352   addi  r10,r10,32
353   addi  r9,r9,32
355   lvx   v10,0,r10
356   lvx   v11,0,r9
357   addi  r10,r10,32
358   addi  r9,r9,32
360 L(has_no_vec):
361   lfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
362   lfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
363   lfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
365 # ifdef _ARCH_PWR6
366   /* Use the extended four-operand version of the mtfsf insn.  */
367   mtfsf  0xff,fp0,1,0
368 # else
369   .machine push
370   .machine "power6"
371   /* Availability of DFP indicates a 64-bit FPSCR.  */
372   andi.  r6,r5,PPC_FEATURE_HAS_DFP
373   beq    7f
374   /* Use the extended four-operand version of the mtfsf insn.  */
375   mtfsf  0xff,fp0,1,0
376   b      8f
377   /* Continue to operate on the FPSCR as if it were 32-bits.  */
379   mtfsf  0xff,fp0
381   .machine pop
382 # endif /* _ARCH_PWR6 */
383   lfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
384   lfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
385   lfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
386   lfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
387   lfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
388   lfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
389   lfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
390   lfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
391   lfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
392   lfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
393   lfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
394   lfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
395   lfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
396   lfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
397   lfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
398   lfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
399   lfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
400   lfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
401   lfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
402   lfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
403   lfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
404   lfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
405   lfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
406   lfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
407   lfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
408   lfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
409   lfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
410   lfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
411   lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
412   lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
414   /* End FDE now, because the unwind info would be wrong while
415      we're reloading registers to switch to the new context.  */
416   cfi_endproc
418   ld   r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
419   ld   r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
420   mtlr r0
421   ld   r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
422   ld   r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
423   ld   r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
424   mtxer r0
425   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
426   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
427   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
428   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
429   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
430   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
431   ld   r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
432   mtcr r0
433   ld   r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
434   ld   r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
435   ld   r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
436   /* Don't reload the thread ID or TLS pointer (r13).  */
437   ld   r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
438   ld   r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
439   ld   r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
440   ld   r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
441   ld   r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
442   ld   r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
443   ld   r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
444   ld   r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
445   ld   r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
446   ld   r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
447   ld   r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
448   ld   r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
449   ld   r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
450   ld   r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
451   ld   r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
452   ld   r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
453   ld   r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
455   /* Now we branch to the "Next Instruction Pointer" from the saved
456      context.  With the powerpc64 instruction set there is no good way to
457      do this (from user state) without clobbering either the LR or CTR.
458      The makecontext and swapcontext functions depend on the callers
459      LR being preserved so we use the CTR.  */
460   ld   r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
461   mtctr r0
462   ld   r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
463   ld   r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
464   bctr
466   /* Re-establish FDE for the rest of the actual setcontext routine.  */
467   cfi_startproc
468   cfi_offset (lr, FRAME_LR_SAVE)
469   cfi_adjust_cfa_offset (128)
471 L(error_exit):
472   ld   r0,128+FRAME_LR_SAVE(r1)
473   addi r1,r1,128
474   mtlr r0
475         ld   r31,-8(r1)
476   blr
478   /* At this point we assume that the ucontext was created by a
479      rt_signal and we should use rt_sigreturn to restore the original
480      state.  As of the 2.4.21 kernel the ucontext is the first thing
481      (offset 0) in the rt_signal frame and rt_sigreturn expects the
482      ucontext address in R1.  Normally the rt-signal trampoline handles
483      this by popping dummy frame before the rt_signal syscall.  In our
484      case the stack may not be in its original (signal handler return with
485      R1 pointing at the dummy frame) state.  We do have the ucontext
486      address in R3, so simply copy R3 to R1 before the syscall.  */
487 L(do_sigret):
488   mr   r1,r3,
489   li   r0,SYS_ify(rt_sigreturn)
490   sc
491   /* No return.  */
493 PSEUDO_END(__setcontext)
495 versioned_symbol (libc, __setcontext, setcontext, GLIBC_2_3_4)