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