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