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