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