Use .machine push; .machine "power6" and .machine pop around mtfsf
[glibc/history.git] / sysdeps / unix / sysv / linux / powerpc / powerpc64 / setcontext.S
blob24413e00bcbff89d091413cbe55c0167d2fc4d47
1 /* Switch to context.
2    Copyright (C) 2002, 2004, 2005, 2006, 2008, 2009
3    Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA
19    02110-1301 USA.  */
21 #include <sysdep.h>
22 #include <rtld-global-offsets.h>
23 #include <shlib-compat.h>
24 #include <kernel-features.h>
26 #define __ASSEMBLY__
27 #include <asm/ptrace.h>
28 #include "ucontext_i.h"
29 #include <asm/errno.h>
31         .section        ".toc","aw"
32 .LC__dl_hwcap:
33 #ifdef SHARED
34         .tc _rtld_global_ro[TC],_rtld_global_ro
35 #else
36         .tc _dl_hwcap[TC],_dl_hwcap
37 #endif
38         .section ".text"
40 #if SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4)
41 ENTRY(__novec_setcontext)
42         CALL_MCOUNT 1
43 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
44   mflr  r0
45   std   r31,-8(1)
46   cfi_offset(r31,-8)
47   std   r0,FRAME_LR_SAVE(r1)
48   cfi_offset (lr, FRAME_LR_SAVE)
49   stdu  r1,-128(r1)
50   cfi_adjust_cfa_offset (128)
51   mr    r31,r3
54  * If this ucontext refers to the point where we were interrupted
55  * by a signal, we have to use the rt_sigreturn system call to
56  * return to the context so we get both LR and CTR restored.
57  *
58  * Otherwise, the context we are restoring is either just after
59  * a procedure call (getcontext/swapcontext) or at the beginning
60  * of a procedure call (makecontext), so we don't need to restore
61  * msr and ctr.  We don't restore r13 since it will be used as
62  * the TLS pointer.  */
63   ld      r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
64   cmpdi r0,0
65   bne     L(nv_do_sigret)
67   li    r5,0
68   addi  r4,r3,UCONTEXT_SIGMASK
69   li    r3,SIG_SETMASK
70   bl    JUMPTARGET(__sigprocmask)
71   nop
72   cmpdi r3,0
73   bne   L(nv_error_exit)
75 # ifdef SHARED
76 /* Load _rtld-global._dl_hwcap.  */
77   ld    r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
78 # else
79   ld    r5,0(r5) /* Load extern _dl_hwcap.  */
80 # endif
82   lfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
83   lfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
84   lfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
86 # ifdef _ARCH_PWR6
87   /* Use the extended four-operand version of the mtfsf insn.  */
88   mtfsf  0xff,fp0,1,0
89 # else
90   .machine push
91   .machine "power6"
92   /* Availability of DFP indicates a 64-bit FPSCR.  */
93   andi.  r6,r5,PPC_FEATURE_HAS_DFP
94   beq    5f
95   /* Use the extended four-operand version of the mtfsf insn.  */
96   mtfsf  0xff,fp0,1,0
97   b      6f
98   /* Continue to operate on the FPSCR as if it were 32-bits.  */
100   mtfsf  0xff,fp0
102   .machine pop
103 # endif /* _ARCH_PWR6 */
104   lfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
105   lfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
106   lfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
107   lfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
108   lfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
109   lfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
110   lfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
111   lfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
112   lfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
113   lfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
114   lfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
115   lfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
116   lfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
117   lfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
118   lfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
119   lfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
120   lfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
121   lfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
122   lfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
123   lfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
124   lfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
125   lfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
126   lfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
127   lfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
128   lfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
129   lfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
130   lfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
131   lfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
132   lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
133   lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
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 L(nv_error_exit):
184   ld   r0,128+FRAME_LR_SAVE(r1)
185   addi r1,r1,128
186   mtlr r0
187         ld   r31,-8(r1)
188   blr
190   /* At this point we assume that the ucontext was created by a
191      rt_signal and we should use rt_sigreturn to restore the original
192      state.  As of the 2.4.21 kernel the ucontext is the first thing
193      (offset 0) in the rt_signal frame and rt_sigreturn expects the
194      ucontext address in R1.  Normally the rt-signal trampoline handles
195      this by popping dummy frame before the rt_signal syscall.  In our
196      case the stack may not be in its original (signal handler return with
197      R1 pointing at the dummy frame) state.  We do have the ucontext
198      address in R3, so simply copy R3 to R1 before the syscall.  */
199 L(nv_do_sigret):
200   mr   r1,r3,
201   li   r0,SYS_ify(rt_sigreturn)
202   sc
203   /* No return.  */
204 #else
205   /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub.  */
206   mflr r0
207   std  r0,FRAME_LR_SAVE(r1)
208   cfi_offset(lr,FRAME_LR_SAVE)
209   stdu r1,-128(r1)
210   cfi_adjust_cfa_offset(128)
211   li   r3,ENOSYS
212   bl   JUMPTARGET(__syscall_error)
213   nop
214   li   r3,-1
215   ld   r0,128+FRAME_LR_SAVE(r1)
216   addi r1,r1,128
217   mtlr r0
218   blr
219 #endif
221 PSEUDO_END(__novec_setcontext)
223 compat_symbol (libc, __novec_setcontext, setcontext, GLIBC_2_3)
225 #endif
227         .section ".text"
228         .machine        "altivec"
229 ENTRY(__setcontext)
230         CALL_MCOUNT 1
231 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
232   mflr  r0
233   std   r31,-8(1)
234   cfi_offset(r31,-8)
235   std   r0,FRAME_LR_SAVE(r1)
236   cfi_offset (lr, FRAME_LR_SAVE)
237   stdu  r1,-128(r1)
238   cfi_adjust_cfa_offset (128)
239   mr    r31,r3
242  * If this ucontext refers to the point where we were interrupted
243  * by a signal, we have to use the rt_sigreturn system call to
244  * return to the context so we get both LR and CTR restored.
246  * Otherwise, the context we are restoring is either just after
247  * a procedure call (getcontext/swapcontext) or at the beginning
248  * of a procedure call (makecontext), so we don't need to restore
249  * msr and ctr.  We don't restore r13 since it will be used as
250  * the TLS pointer.  */
251   ld      r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
252   cmpdi r0,0
253   bne     L(do_sigret)
255   li    r5,0
256   addi  r4,r3,UCONTEXT_SIGMASK
257   li    r3,SIG_SETMASK
258   bl    JUMPTARGET(__sigprocmask)
259   nop
260   cmpdi r3,0
261   bne   L(error_exit)
263   ld    r5,.LC__dl_hwcap@toc(r2)
264   ld    r10,(SIGCONTEXT_V_REGS_PTR)(r31)
265 # ifdef SHARED
266 /* Load _rtld-global._dl_hwcap.  */
267   ld    r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
268 # else
269   ld    r5,0(r5) /* Load extern _dl_hwcap.  */
270 # endif
271   andis.  r6,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
272   beq   L(has_no_vec)
274   cmpdi r10,0
275   beq   L(has_no_vec)
276   lwz   r0,(33*16)(r10)
278   li    r9,(16*32)
279   mtspr VRSAVE,r0
280   cmpwi r0,0
281   beq   L(has_no_vec)
283   lvx   v19,r9,r10
284   la    r9,(16)(r10)
286   lvx   v0,0,r10
287   lvx   v1,0,r9
288   addi  r10,r10,32
289   addi  r9,r9,32
291   mtvscr  v19
292   lvx   v2,0,r10
293   lvx   v3,0,r9
294   addi  r10,r10,32
295   addi  r9,r9,32
297   lvx   v4,0,r10
298   lvx   v5,0,r9
299   addi  r10,r10,32
300   addi  r9,r9,32
302   lvx   v6,0,r10
303   lvx   v7,0,r9
304   addi  r10,r10,32
305   addi  r9,r9,32
307   lvx   v8,0,r10
308   lvx   v9,0,r9
309   addi  r10,r10,32
310   addi  r9,r9,32
312   lvx   v10,0,r10
313   lvx   v11,0,r9
314   addi  r10,r10,32
315   addi  r9,r9,32
317   lvx   v12,0,r10
318   lvx   v13,0,r9
319   addi  r10,r10,32
320   addi  r9,r9,32
322   lvx   v14,0,r10
323   lvx   v15,0,r9
324   addi  r10,r10,32
325   addi  r9,r9,32
327   lvx   v16,0,r10
328   lvx   v17,0,r9
329   addi  r10,r10,32
330   addi  r9,r9,32
332   lvx   v18,0,r10
333   lvx   v19,0,r9
334   addi  r10,r10,32
335   addi  r9,r9,32
337   lvx   v20,0,r10
338   lvx   v21,0,r9
339   addi  r10,r10,32
340   addi  r9,r9,32
342   lvx   v22,0,r10
343   lvx   v23,0,r9
344   addi  r10,r10,32
345   addi  r9,r9,32
347   lvx   v24,0,r10
348   lvx   v25,0,r9
349   addi  r10,r10,32
350   addi  r9,r9,32
352   lvx   v26,0,r10
353   lvx   v27,0,r9
354   addi  r10,r10,32
355   addi  r9,r9,32
357   lvx   v28,0,r10
358   lvx   v29,0,r9
359   addi  r10,r10,32
360   addi  r9,r9,32
362   lvx   v30,0,r10
363   lvx   v31,0,r9
364   addi  r10,r10,32
365   addi  r9,r9,32
367   lvx   v10,0,r10
368   lvx   v11,0,r9
369   addi  r10,r10,32
370   addi  r9,r9,32
372 L(has_no_vec):
373   lfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
374   lfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
375   lfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
377 # ifdef _ARCH_PWR6
378   /* Use the extended four-operand version of the mtfsf insn.  */
379   mtfsf  0xff,fp0,1,0
380 # else
381   .machine push
382   .machine "power6"
383   /* Availability of DFP indicates a 64-bit FPSCR.  */
384   andi.  r6,r5,PPC_FEATURE_HAS_DFP
385   beq    7f
386   /* Use the extended four-operand version of the mtfsf insn.  */
387   mtfsf  0xff,fp0,1,0
388   b      8f
389   /* Continue to operate on the FPSCR as if it were 32-bits.  */
391   mtfsf  0xff,fp0
393   .machine pop
394 # endif /* _ARCH_PWR6 */
395   lfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
396   lfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
397   lfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
398   lfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
399   lfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
400   lfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
401   lfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
402   lfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
403   lfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
404   lfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
405   lfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
406   lfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
407   lfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
408   lfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
409   lfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
410   lfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
411   lfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
412   lfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
413   lfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
414   lfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
415   lfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
416   lfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
417   lfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
418   lfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
419   lfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
420   lfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
421   lfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
422   lfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
423   lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
424   lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
426   ld   r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
427   ld   r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
428   mtlr r0
429   ld   r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
430   ld   r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
431   ld   r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
432   mtxer r0
433   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
434   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
435   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
436   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
437   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
438   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
439   ld   r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
440   mtcr r0
441   ld   r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
442   ld   r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
443   ld   r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
444   /* Don't reload the thread ID or TLS pointer (r13).  */
445   ld   r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
446   ld   r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
447   ld   r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
448   ld   r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
449   ld   r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
450   ld   r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
451   ld   r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
452   ld   r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
453   ld   r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
454   ld   r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
455   ld   r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
456   ld   r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
457   ld   r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
458   ld   r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
459   ld   r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
460   ld   r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
461   ld   r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
463   /* Now we branch to the "Next Instruction Pointer" from the saved
464      context.  With the powerpc64 instruction set there is no good way to
465      do this (from user state) without clobbering either the LR or CTR.
466      The makecontext and swapcontext functions depend on the callers
467      LR being preserved so we use the CTR.  */
468   ld   r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
469   mtctr r0
470   ld   r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
471   ld   r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
472   bctr
474 L(error_exit):
475   ld   r0,128+FRAME_LR_SAVE(r1)
476   addi r1,r1,128
477   mtlr r0
478         ld   r31,-8(r1)
479   blr
481   /* At this point we assume that the ucontext was created by a
482      rt_signal and we should use rt_sigreturn to restore the original
483      state.  As of the 2.4.21 kernel the ucontext is the first thing
484      (offset 0) in the rt_signal frame and rt_sigreturn expects the
485      ucontext address in R1.  Normally the rt-signal trampoline handles
486      this by popping dummy frame before the rt_signal syscall.  In our
487      case the stack may not be in its original (signal handler return with
488      R1 pointing at the dummy frame) state.  We do have the ucontext
489      address in R3, so simply copy R3 to R1 before the syscall.  */
490 L(do_sigret):
491   mr   r1,r3,
492   li   r0,SYS_ify(rt_sigreturn)
493   sc
494   /* No return.  */
495 #else
496   /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub.  */
497   mflr r0
498   std  r0,FRAME_LR_SAVE(r1)
499   cfi_offset (lr, FRAME_LR_SAVE)
500   stdu r1,-128(r1)
501   cfi_adjust_cfa_offset (128)
502   li   r3,ENOSYS
503   bl   JUMPTARGET(__syscall_error)
504   nop
505   li   r3,-1
506   ld   r0,128+FRAME_LR_SAVE(r1)
507   addi r1,r1,128
508   mtlr r0
509   blr
510 #endif
512 PSEUDO_END(__setcontext)
514 versioned_symbol (libc, __setcontext, setcontext, GLIBC_2_3_4)