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