Updated to fedora-glibc-20090102T2110
[glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc64 / swapcontext.S
blobc42ccfbe44f4b63db2380e772ed93dfe11ff47c7
1 /* Save current context and install the given one.
2    Copyright (C) 2002, 2004, 2005, 2006, 2008 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, write to the Free
17    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA
18    02110-1301 USA.  */
20 #include <sysdep.h>
21 #include <rtld-global-offsets.h>
22 #include <shlib-compat.h>
23 #include <kernel-features.h>
25 #define __ASSEMBLY__
26 #include <asm/ptrace.h>
27 #include "ucontext_i.h"
28 #include <asm/errno.h>
30         .section        ".toc","aw"
31 .LC__dl_hwcap:
32 #ifdef SHARED
33         .tc _rtld_global_ro[TC],_rtld_global_ro
34 #else
35         .tc _dl_hwcap[TC],_dl_hwcap
36 #endif
38 #if SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4)
39         .section        ".text"
40 ENTRY(__novec_swapcontext)
41         CALL_MCOUNT 2
42 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
43   std  r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
44   std  r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
45   mflr  r0
46   std   r31,-8(1)
47   cfi_offset(r31,-8)
48   std  r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
49   std  r0,FRAME_LR_SAVE(r1)
50   cfi_offset (lr, FRAME_LR_SAVE)
51   std  r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
52   std  r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
53   stdu  r1,-128(r1)
54   cfi_adjust_cfa_offset (128)
55   std  r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r3)
56   std  r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r3)
57   std  r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r3)
58   std  r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r3)
59   std  r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r3)
60   std  r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r3)
61   std  r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r3)
62   std  r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
63   std  r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
64   std  r13,(SIGCONTEXT_GP_REGS+(PT_R13*8))(r3)
65   std  r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r3)
66   std  r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r3)
67   std  r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r3)
68   std  r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r3)
69   std  r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r3)
70   std  r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r3)
71   std  r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r3)
72   std  r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r3)
73   std  r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r3)
74   std  r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r3)
75   std  r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r3)
76   std  r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r3)
77   std  r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r3)
78   std  r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r3)
79   std  r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r3)
80   std  r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
81   std  r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r3)
82   std  r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r3)
83   mfctr  r0
84   std  r0,(SIGCONTEXT_GP_REGS+(PT_CTR*8))(r3)
85   mfxer  r0
86   std  r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r3)
87   mfcr  r0
88   std  r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r3)
90   /* Set the return value of swapcontext to "success".  R3 is the only
91      register whose value is not preserved in the saved context.  */
92   li   r0,0
93   std  r0,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r3)
95   /* Zero fill fields that can't be set in user state or are unused.  */
96   std  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r3)
97   std  r0,(SIGCONTEXT_GP_REGS+(34*8))(r3)
98   std  r0,(SIGCONTEXT_GP_REGS+(PT_SOFTE*8))(r3)
99   std  r0,(SIGCONTEXT_GP_REGS+(40*8))(r3)
100   std  r0,(SIGCONTEXT_GP_REGS+(41*8))(r3)
101   std  r0,(SIGCONTEXT_GP_REGS+(42*8))(r3)
102   std  r0,(SIGCONTEXT_GP_REGS+(PT_RESULT*8))(r3)
104   /* Set the PT_REGS pointer to the address of sigcontext gp_regs
105      field.  Struct pt_regs and elf_gregset_t are the same thing.
106      We kept the regs field for backwards compatibility with
107      libraries built before we extended sigcontext.  */
108   addi r0,r3,SIGCONTEXT_GP_REGS
109   std  r0,SIGCONTEXT_PT_REGS(r3)
111   stfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r3)
112   stfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r3)
113   stfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r3)
114   stfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r3)
115   stfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r3)
116   stfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r3)
117   stfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r3)
118   stfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r3)
119   stfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r3)
120   stfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r3)
121   stfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r3)
122   stfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r3)
123   stfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r3)
124   stfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r3)
125   stfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r3)
126   stfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r3)
127   stfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r3)
128   stfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r3)
129   stfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r3)
130   stfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r3)
131   stfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r3)
132   stfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r3)
133   stfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r3)
134   stfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r3)
135   stfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r3)
136   stfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r3)
137   stfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r3)
138   stfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r3)
139   stfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r3)
140   stfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r3)
141   mffs  fp0
142   stfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r3)
143   stfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r3)
144   stfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r3)
146   mr    r31,r4
147   addi  r5,r3,UCONTEXT_SIGMASK
148   addi  r4,r4,UCONTEXT_SIGMASK
149   li    r3,SIG_SETMASK
150   bl    JUMPTARGET(__sigprocmask)
151   nop
152   cmpdi  r3,0
153   bne   L(nv_error_exit)
156  * If this new ucontext refers to the point where we were interrupted
157  * by a signal, we have to use the rt_sigreturn system call to
158  * return to the context so we get both LR and CTR restored.
160  * Otherwise, the context we are restoring is either just after
161  * a procedure call (getcontext/swapcontext) or at the beginning
162  * of a procedure call (makecontext), so we don't need to restore
163  * msr and ctr.  We don't restore r13 since it will be used as
164  * the TLS pointer.  */
165   ld      r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
166   cmpdi r0,0
167   bne     L(nv_do_sigret)
169 # ifdef SHARED
170 /* Load _rtld-global._dl_hwcap.  */
171   ld    r8,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r8)
172 # else
173   ld    r8,0(r8) /* Load extern _dl_hwcap.  */
174 # endif
176   lfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
177   lfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
178   lfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
179 # ifdef _ARCH_PWR6
180   /* Use the extended four-operand version of the mtfsf insn.  */
181   mtfsf  0xff,fp0,1,0
182 # else
183   /* Availability of DFP indicates a 64-bit FPSCR.  */
184   andi.  r6,r8,PPC_FEATURE_HAS_DFP
185   beq    5f
186   /* Use the extended four-operand version of the mtfsf insn.  */
187   mtfsf  0xff,fp0,1,0
188   b      6f
189   /* Continue to operate on the FPSCR as if it were 32-bits.  */
191   mtfsf  0xff,fp0
193 #endif /* _ARCH_PWR6 */
194   lfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
195   lfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
196   lfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
197   lfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
198   lfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
199   lfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
200   lfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
201   lfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
202   lfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
203   lfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
204   lfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
205   lfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
206   lfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
207   lfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
208   lfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
209   lfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
210   lfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
211   lfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
212   lfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
213   lfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
214   lfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
215   lfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
216   lfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
217   lfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
218   lfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
219   lfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
220   lfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
221   lfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
222   lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
223   lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
225   ld   r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
226   ld   r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
227   mtlr r0
228   ld   r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
229   ld   r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
230   ld   r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
231   mtxer r0
232   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
233   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
234   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
235   mtcr r0
236   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
237   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
238   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
239   ld   r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
240   ld   r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
241   ld   r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
242   ld   r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
243   /* Don't reload the thread ID or TLS pointer (r13).  */
244   ld   r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
245   ld   r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
246   ld   r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
247   ld   r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
248   ld   r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
249   ld   r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
250   ld   r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
251   ld   r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
252   ld   r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
253   ld   r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
254   ld   r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
255   ld   r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
256   ld   r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
257   ld   r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
258   ld   r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
259   ld   r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
260   ld   r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
262   /* Now we branch to the "Next Instruction Pointer" from the saved
263      context.  With the powerpc64 instruction set there is no good way to
264      do this (from user state) without clobbering either the LR or CTR.
265      The makecontext and swapcontext functions depend on the callers
266      LR being preserved so we use the CTR.  */
267   ld   r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
268   mtctr r0
269   ld   r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
270   ld   r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
271   bctr
273 L(nv_error_exit):
274   ld    r0,128+FRAME_LR_SAVE(r1)
275   addi  r1,r1,128
276   mtlr  r0
277   ld    r31,-8(r1)
278   blr
280   /* At this point we assume that the ucontext was created by a
281      rt_signal and we should use rt_sigreturn to restore the original
282      state.  As of the 2.4.21 kernel the ucontext is the first thing
283      (offset 0) in the rt_signal frame and rt_sigreturn expects the
284      ucontext address in R1.  Normally the rt-signal trampoline handles
285      this by popping dummy frame before the rt_signal syscall.  In our
286      case the stack may not be in its original (signal handler return with
287      R1 pointing at the dummy frame) state.  We do have the ucontext
288      address in R3, so simply copy R3 to R1 before the syscall.  */
289 L(nv_do_sigret):
290   mr   r1,r3,
291   li   r0,SYS_ify(rt_sigreturn)
292   sc
293   /* No return.  */
294 #else
295   /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub.  */
296   mflr r0
297   std  r0,FRAME_LR_SAVE(r1)
298   cfi_offset(lr,FRAME_LR_SAVE)
299   stdu r1,-128(r1)
300   li   r3,ENOSYS
301   bl   JUMPTARGET(__syscall_error)
302   nop
303   li   r3,-1
304   ld   r0,128+FRAME_LR_SAVE(r1)
305   addi r1,r1,128
306   mtlr r0
307   blr
308 #endif
310 PSEUDO_END(__novec_swapcontext)
312 compat_symbol (libc, __novec_swapcontext, swapcontext, GLIBC_2_3)
314 #endif
316         .section ".text"
317         .machine        "altivec"
318 ENTRY(__swapcontext)
319         CALL_MCOUNT 2
320 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
321   std  r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
322   std  r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
323   mflr  r0
324   std   r31,-8(1)
325   cfi_offset(r31,-8)
326   std  r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
327   std  r0,FRAME_LR_SAVE(r1)
328   cfi_offset (lr, FRAME_LR_SAVE)
329   std  r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
330   std  r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
331   stdu  r1,-128(r1)
332   cfi_adjust_cfa_offset(128)
333   std  r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r3)
334   std  r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r3)
335   std  r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r3)
336   std  r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r3)
337   std  r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r3)
338   std  r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r3)
339   std  r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r3)
340   std  r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
341   std  r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
342   std  r13,(SIGCONTEXT_GP_REGS+(PT_R13*8))(r3)
343   std  r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r3)
344   std  r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r3)
345   std  r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r3)
346   std  r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r3)
347   std  r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r3)
348   std  r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r3)
349   std  r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r3)
350   std  r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r3)
351   std  r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r3)
352   std  r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r3)
353   std  r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r3)
354   std  r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r3)
355   std  r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r3)
356   std  r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r3)
357   std  r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r3)
358   std  r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
359   std  r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r3)
360   std  r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r3)
361   mfctr  r0
362   std  r0,(SIGCONTEXT_GP_REGS+(PT_CTR*8))(r3)
363   mfxer  r0
364   std  r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r3)
365   mfcr  r0
366   std  r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r3)
368   /* Set the return value of swapcontext to "success".  R3 is the only
369      register whose value is not preserved in the saved context.  */
370   li   r0,0
371   std  r0,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r3)
373   /* Zero fill fields that can't be set in user state or are unused.  */
374   std  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r3)
375   std  r0,(SIGCONTEXT_GP_REGS+(34*8))(r3)
376   std  r0,(SIGCONTEXT_GP_REGS+(PT_SOFTE*8))(r3)
377   std  r0,(SIGCONTEXT_GP_REGS+(40*8))(r3)
378   std  r0,(SIGCONTEXT_GP_REGS+(41*8))(r3)
379   std  r0,(SIGCONTEXT_GP_REGS+(42*8))(r3)
380   std  r0,(SIGCONTEXT_GP_REGS+(PT_RESULT*8))(r3)
382   /* Set the PT_REGS pointer to the address of sigcontext gp_regs
383      field.  Struct pt_regs and elf_gregset_t are the same thing.
384      We kept the regs field for backwards compatibility with
385      libraries built before we extended sigcontext.  */
386   addi r0,r3,SIGCONTEXT_GP_REGS
387   std  r0,SIGCONTEXT_PT_REGS(r3)
389   stfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r3)
390   stfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r3)
391   stfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r3)
392   stfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r3)
393   stfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r3)
394   stfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r3)
395   stfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r3)
396   stfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r3)
397   stfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r3)
398   stfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r3)
399   stfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r3)
400   stfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r3)
401   stfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r3)
402   stfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r3)
403   stfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r3)
404   stfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r3)
405   stfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r3)
406   stfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r3)
407   stfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r3)
408   stfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r3)
409   stfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r3)
410   stfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r3)
411   stfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r3)
412   stfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r3)
413   stfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r3)
414   stfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r3)
415   stfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r3)
416   stfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r3)
417   stfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r3)
418   stfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r3)
419   mffs  fp0
420   stfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r3)
421   stfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r3)
422   stfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r3)
424   ld    r8,.LC__dl_hwcap@toc(r2)
425 #ifdef SHARED
426 /* Load _rtld-global._dl_hwcap.  */
427   ld    r8,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r8)
428 #else
429   ld    r8,0(r8) /* Load extern _dl_hwcap.  */
430 #endif
431   la    r10,(SIGCONTEXT_V_RESERVE+8)(r3)
432   la    r9,(SIGCONTEXT_V_RESERVE+24)(r3)
434   andis.  r6,r8,(PPC_FEATURE_HAS_ALTIVEC >> 16)
436   clrrdi  r10,r10,4
437   beq   L(has_no_vec)
439   clrrdi  r9,r9,4
440   mr    r8,r10  /* Capture *v_regs value in r5.  */
442   stvx  v0,0,r10
443   stvx  v1,0,r9
444   addi  r10,r10,32
445   addi  r9,r9,32
447   stvx  v2,0,r10
448   stvx  v3,0,r9
449   addi  r10,r10,32
450   addi  r9,r9,32
452   stvx  v4,0,r10
453   stvx  v5,0,r9
454   addi  r10,r10,32
455   addi  r9,r9,32
457   stvx  v6,0,r10
458   stvx  v7,0,r9
459   addi  r10,r10,32
460   addi  r9,r9,32
462   stvx  v8,0,r10
463   stvx  v9,0,r9
464   addi  r10,r10,32
465   addi  r9,r9,32
467   stvx  v10,0,r10
468   stvx  v11,0,r9
469   addi  r10,r10,32
470   addi  r9,r9,32
472   stvx  v12,0,r10
473   stvx  v13,0,r9
474   addi  r10,r10,32
475   addi  r9,r9,32
477   stvx  v14,0,r10
478   stvx  v15,0,r9
479   addi  r10,r10,32
480   addi  r9,r9,32
482   stvx  v16,0,r10
483   stvx  v17,0,r9
484   addi  r10,r10,32
485   addi  r9,r9,32
487   stvx  v18,0,r10
488   stvx  v19,0,r9
489   addi  r10,r10,32
490   addi  r9,r9,32
492   stvx  v20,0,r10
493   stvx  v21,0,r9
494   addi  r10,r10,32
495   addi  r9,r9,32
497   stvx  v22,0,r10
498   stvx  v23,0,r9
499   addi  r10,r10,32
500   addi  r9,r9,32
502   stvx  v24,0,r10
503   stvx  v25,0,r9
504   addi  r10,r10,32
505   addi  r9,r9,32
507   stvx  v26,0,r10
508   stvx  v27,0,r9
509   addi  r10,r10,32
510   addi  r9,r9,32
512   stvx  v28,0,r10
513   stvx  v29,0,r9
514   addi  r10,r10,32
515   addi  r9,r9,32
517   stvx  v30,0,r10
518   stvx  v31,0,r9
519   addi  r10,r10,32
520   addi  r9,r9,32
522   mfvscr  v0
523   mfspr r0,VRSAVE
524   stvx  v0,0,r10
525   stw   r0,0(r9)
527 L(has_no_vec):
529    Store either a NULL or a quadword aligned pointer to the Vector register
530    array into *v_regs.
532   std   r8,(SIGCONTEXT_V_REGS_PTR)(r3)
534   mr    r31,r4
535   addi  r5,r3,UCONTEXT_SIGMASK
536   addi  r4,r4,UCONTEXT_SIGMASK
537   li    r3,SIG_SETMASK
538   bl    JUMPTARGET(__sigprocmask)
539   nop
540   cmpdi  r3,0
541   bne   L(error_exit)
544  * If this new ucontext refers to the point where we were interrupted
545  * by a signal, we have to use the rt_sigreturn system call to
546  * return to the context so we get both LR and CTR restored.
548  * Otherwise, the context we are restoring is either just after
549  * a procedure call (getcontext/swapcontext) or at the beginning
550  * of a procedure call (makecontext), so we don't need to restore
551  * msr and ctr.  We don't restore r13 since it will be used as
552  * the TLS pointer.  */
553   ld      r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
554   cmpdi r0,0
555   bne     L(do_sigret)
557   ld    r8,.LC__dl_hwcap@toc(r2)
558   ld    r10,(SIGCONTEXT_V_REGS_PTR)(r31)
559 # ifdef SHARED
560 /* Load _rtld-global._dl_hwcap.  */
561   ld    r8,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r8)
562 # else
563   ld    r8,0(r8) /* Load extern _dl_hwcap.  */
564 # endif
565   andis.  r6,r8,(PPC_FEATURE_HAS_ALTIVEC >> 16)
566   beq   L(has_no_vec2)
568   cmpdi r10,0
569   beq   L(has_no_vec2)
570   lwz   r0,(33*16)(r10)
572   li    r9,(16*32)
573   mtspr VRSAVE,r0
574   cmpwi r0,0
575   beq   L(has_no_vec2)
577   lvx   v19,r9,r10
578   la    r9,(16)(r10)
580   lvx   v0,0,r10
581   lvx   v1,0,r9
582   addi  r10,r10,32
583   addi  r9,r9,32
585   mtvscr  v19
586   lvx   v2,0,r10
587   lvx   v3,0,r9
588   addi  r10,r10,32
589   addi  r9,r9,32
591   lvx   v4,0,r10
592   lvx   v5,0,r9
593   addi  r10,r10,32
594   addi  r9,r9,32
596   lvx   v6,0,r10
597   lvx   v7,0,r9
598   addi  r10,r10,32
599   addi  r9,r9,32
601   lvx   v8,0,r10
602   lvx   v9,0,r9
603   addi  r10,r10,32
604   addi  r9,r9,32
606   lvx   v10,0,r10
607   lvx   v11,0,r9
608   addi  r10,r10,32
609   addi  r9,r9,32
611   lvx   v12,0,r10
612   lvx   v13,0,r9
613   addi  r10,r10,32
614   addi  r9,r9,32
616   lvx   v14,0,r10
617   lvx   v15,0,r9
618   addi  r10,r10,32
619   addi  r9,r9,32
621   lvx   v16,0,r10
622   lvx   v17,0,r9
623   addi  r10,r10,32
624   addi  r9,r9,32
626   lvx   v18,0,r10
627   lvx   v19,0,r9
628   addi  r10,r10,32
629   addi  r9,r9,32
631   lvx   v20,0,r10
632   lvx   v21,0,r9
633   addi  r10,r10,32
634   addi  r9,r9,32
636   lvx   v22,0,r10
637   lvx   v23,0,r9
638   addi  r10,r10,32
639   addi  r9,r9,32
641   lvx   v24,0,r10
642   lvx   v25,0,r9
643   addi  r10,r10,32
644   addi  r9,r9,32
646   lvx   v26,0,r10
647   lvx   v27,0,r9
648   addi  r10,r10,32
649   addi  r9,r9,32
651   lvx   v28,0,r10
652   lvx   v29,0,r9
653   addi  r10,r10,32
654   addi  r9,r9,32
656   lvx   v30,0,r10
657   lvx   v31,0,r9
658   addi  r10,r10,32
659   addi  r9,r9,32
661   lvx   v10,0,r10
662   lvx   v11,0,r9
663   addi  r10,r10,32
664   addi  r9,r9,32
666 L(has_no_vec2):
668   lfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
669   lfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
670   lfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
671 # ifdef _ARCH_PWR6
672   /* Use the extended four-operand version of the mtfsf insn.  */
673   mtfsf  0xff,fp0,1,0
674 # else
675   /* Availability of DFP indicates a 64-bit FPSCR.  */
676   andi.  r6,r8,PPC_FEATURE_HAS_DFP
677   beq    7f
678   /* Use the extended four-operand version of the mtfsf insn.  */
679   mtfsf  0xff,fp0,1,0
680   b      8f
681   /* Continue to operate on the FPSCR as if it were 32-bits.  */
683   mtfsf  0xff,fp0
685 #endif /* _ARCH_PWR6 */
686   lfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
687   lfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
688   lfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
689   lfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
690   lfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
691   lfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
692   lfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
693   lfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
694   lfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
695   lfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
696   lfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
697   lfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
698   lfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
699   lfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
700   lfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
701   lfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
702   lfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
703   lfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
704   lfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
705   lfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
706   lfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
707   lfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
708   lfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
709   lfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
710   lfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
711   lfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
712   lfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
713   lfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
714   lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
715   lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
717   ld   r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
718   ld   r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
719   mtlr r0
720   ld   r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
721   ld   r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
722   ld   r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
723   mtxer r0
724   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
725   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
726   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
727   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
728   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
729   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
730   ld   r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
731   mtcr r0
732   ld   r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
733   ld   r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
734   ld   r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
735   /* Don't reload the thread ID or TLS pointer (r13).  */
736   ld   r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
737   ld   r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
738   ld   r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
739   ld   r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
740   ld   r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
741   ld   r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
742   ld   r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
743   ld   r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
744   ld   r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
745   ld   r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
746   ld   r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
747   ld   r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
748   ld   r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
749   ld   r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
750   ld   r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
751   ld   r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
752   ld   r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
754   /* Now we branch to the "Next Instruction Pointer" from the saved
755      context.  With the powerpc64 instruction set there is no good way to
756      do this (from user state) without clobbering either the LR or CTR.
757      The makecontext and swapcontext functions depend on the callers
758      LR being preserved so we use the CTR.  */
759   ld   r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
760   mtctr r0
761   ld   r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
762   ld   r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
763   bctr
765 L(error_exit):
766   ld    r0,128+FRAME_LR_SAVE(r1)
767   addi  r1,r1,128
768   mtlr  r0
769   ld    r31,-8(r1)
770   blr
772   /* At this point we assume that the ucontext was created by a
773      rt_signal and we should use rt_sigreturn to restore the original
774      state.  As of the 2.4.21 kernel the ucontext is the first thing
775      (offset 0) in the rt_signal frame and rt_sigreturn expects the
776      ucontext address in R1.  Normally the rt-signal trampoline handles
777      this by popping dummy frame before the rt_signal syscall.  In our
778      case the stack may not be in its original (signal handler return with
779      R1 pointing at the dummy frame) state.  We do have the ucontext
780      address in R3, so simply copy R3 to R1 before the syscall.  */
781 L(do_sigret):
782   mr   r1,r3,
783   li   r0,SYS_ify(rt_sigreturn)
784   sc
785   /* No return.  */
786 #else
787   /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub.  */
788   mflr r0
789   std  r0,FRAME_LR_SAVE(r1)
790   cfi_offset (lr, FRAME_LR_SAVE)
791   stdu r1,-128(r1)
792   cfi_adjust_cfa_offset (128)
793   li   r3,ENOSYS
794   bl   JUMPTARGET(__syscall_error)
795   nop
796   li   r3,-1
797   ld   r0,128+FRAME_LR_SAVE(r1)
798   addi r1,r1,128
799   mtlr r0
800   blr
801 #endif
803 PSEUDO_END(__swapcontext)
805 versioned_symbol (libc, __swapcontext, swapcontext, GLIBC_2_3_4)