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