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