1/* Save current context and install the given one.
2   Copyright (C) 2002-2021 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, see
17   <https://www.gnu.org/licenses/>.  */
18
19#include <sysdep.h>
20#include <rtld-global-offsets.h>
21#include <shlib-compat.h>
22
23#define __ASSEMBLY__
24#include <asm/ptrace.h>
25#include "ucontext_i.h"
26#include <asm/errno.h>
27
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
35
36#if SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4)
37	.section	".text"
38ENTRY(__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)
86
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)
91
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)
100
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)
107
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)
142
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)
151
152  ld	r8,.LC__dl_hwcap@toc(r2)
153# ifdef SHARED
154/* Load _rtld-global._dl_hwcap.  */
155  ld    r8,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r8)
156# else
157  ld    r8,0(r8) /* Load extern _dl_hwcap.  */
158# endif
159
160  lfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
161  lfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
162  lfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
163
164# ifdef _ARCH_PWR6
165  /* Use the extended four-operand version of the mtfsf insn.  */
166  .machine push
167  .machine "power6"
168
169  mtfsf  0xff,fp0,1,0
170
171  .machine pop
172# else
173  /* Availability of DFP indicates a 64-bit FPSCR.  */
174  andi.  r6,r8,PPC_FEATURE_HAS_DFP
175  beq    5f
176
177  .machine push
178  .machine "power6"
179
180  mtfsf  0xff,fp0,1,0
181
182  .machine pop
183
184  b      6f
185  /* Continue to operate on the FPSCR as if it were 32-bits.  */
1865:
187  mtfsf  0xff,fp0
1886:
189#endif /* _ARCH_PWR6 */
190
191  lfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
192  lfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
193  lfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
194  lfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
195  lfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
196  lfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
197  lfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
198  lfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
199  lfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
200  lfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
201  lfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
202  lfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
203  lfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
204  lfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
205  lfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
206  lfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
207  lfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
208  lfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
209  lfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
210  lfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
211  lfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
212  lfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
213  lfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
214  lfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
215  lfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
216  lfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
217  lfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
218  lfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
219  lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
220  lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
221
222  ld   r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
223  ld   r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
224  mtlr r0
225  ld   r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
226  ld   r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
227  ld   r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
228  mtxer r0
229  ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
230  ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
231  ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
232  mtcr r0
233  ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
234  ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
235  ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
236  ld   r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
237  ld   r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
238  ld   r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
239  ld   r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
240  /* Don't reload the thread ID or TLS pointer (r13).  */
241  ld   r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
242  ld   r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
243  ld   r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
244  ld   r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
245  ld   r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
246  ld   r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
247  ld   r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
248  ld   r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
249  ld   r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
250  ld   r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
251  ld   r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
252  ld   r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
253  ld   r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
254  ld   r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
255  ld   r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
256  ld   r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
257  ld   r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
258
259  /* Now we branch to the "Next Instruction Pointer" from the saved
260     context.  With the powerpc64 instruction set there is no good way to
261     do this (from user state) without clobbering either the LR or CTR.
262     The makecontext and swapcontext functions depend on the callers
263     LR being preserved so we use the CTR.  */
264  ld   r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
265  mtctr r0
266  ld   r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
267  ld   r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
268  bctr
269
270L(nv_error_exit):
271  ld    r0,128+FRAME_LR_SAVE(r1)
272  addi  r1,r1,128
273  mtlr  r0
274  ld    r31,-8(r1)
275  blr
276
277PSEUDO_END(__novec_swapcontext)
278
279compat_symbol (libc, __novec_swapcontext, swapcontext, GLIBC_2_3)
280
281#endif
282
283	.section ".text"
284	.machine	"altivec"
285ENTRY(__swapcontext)
286	CALL_MCOUNT 2
287  std  r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
288  std  r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
289  mflr  r0
290  std   r31,-8(1)
291  cfi_offset(r31,-8)
292  std  r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
293  std  r0,FRAME_LR_SAVE(r1)
294  cfi_offset (lr, FRAME_LR_SAVE)
295  std  r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
296  std  r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
297  stdu  r1,-128(r1)
298  cfi_adjust_cfa_offset(128)
299  std  r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r3)
300  std  r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r3)
301  std  r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r3)
302  std  r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r3)
303  std  r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r3)
304  std  r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r3)
305  std  r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r3)
306  std  r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
307  std  r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
308  std  r13,(SIGCONTEXT_GP_REGS+(PT_R13*8))(r3)
309  std  r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r3)
310  std  r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r3)
311  std  r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r3)
312  std  r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r3)
313  std  r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r3)
314  std  r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r3)
315  std  r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r3)
316  std  r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r3)
317  std  r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r3)
318  std  r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r3)
319  std  r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r3)
320  std  r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r3)
321  std  r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r3)
322  std  r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r3)
323  std  r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r3)
324  std  r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
325  std  r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r3)
326  std  r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r3)
327  mfctr  r0
328  std  r0,(SIGCONTEXT_GP_REGS+(PT_CTR*8))(r3)
329  mfxer  r0
330  std  r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r3)
331  mfcr  r0
332  std  r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r3)
333
334  /* Set the return value of swapcontext to "success".  R3 is the only
335     register whose value is not preserved in the saved context.  */
336  li   r0,0
337  std  r0,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r3)
338
339  /* Zero fill fields that can't be set in user state or are unused.  */
340  std  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r3)
341  std  r0,(SIGCONTEXT_GP_REGS+(34*8))(r3)
342  std  r0,(SIGCONTEXT_GP_REGS+(PT_SOFTE*8))(r3)
343  std  r0,(SIGCONTEXT_GP_REGS+(40*8))(r3)
344  std  r0,(SIGCONTEXT_GP_REGS+(41*8))(r3)
345  std  r0,(SIGCONTEXT_GP_REGS+(42*8))(r3)
346  std  r0,(SIGCONTEXT_GP_REGS+(PT_RESULT*8))(r3)
347
348  /* Set the PT_REGS pointer to the address of sigcontext gp_regs
349     field.  Struct pt_regs and elf_gregset_t are the same thing.
350     We kept the regs field for backwards compatibility with
351     libraries built before we extended sigcontext.  */
352  addi r0,r3,SIGCONTEXT_GP_REGS
353  std  r0,SIGCONTEXT_PT_REGS(r3)
354
355  stfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r3)
356  stfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r3)
357  stfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r3)
358  stfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r3)
359  stfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r3)
360  stfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r3)
361  stfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r3)
362  stfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r3)
363  stfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r3)
364  stfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r3)
365  stfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r3)
366  stfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r3)
367  stfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r3)
368  stfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r3)
369  stfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r3)
370  stfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r3)
371  stfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r3)
372  stfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r3)
373  stfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r3)
374  stfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r3)
375  stfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r3)
376  stfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r3)
377  stfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r3)
378  stfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r3)
379  stfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r3)
380  stfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r3)
381  stfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r3)
382  stfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r3)
383  stfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r3)
384  stfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r3)
385  mffs  fp0
386  stfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r3)
387  stfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r3)
388  stfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r3)
389
390  ld    r8,.LC__dl_hwcap@toc(r2)
391#ifdef SHARED
392/* Load _rtld-global._dl_hwcap.  */
393  ld    r8,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r8)
394#else
395  ld    r8,0(r8) /* Load extern _dl_hwcap.  */
396#endif
397  la    r10,(SIGCONTEXT_V_RESERVE+8)(r3)
398  la    r9,(SIGCONTEXT_V_RESERVE+24)(r3)
399
400  andis.  r6,r8,(PPC_FEATURE_HAS_ALTIVEC >> 16)
401
402  clrrdi  r10,r10,4
403  beq   L(has_no_vec)
404
405  clrrdi  r9,r9,4
406  mr    r8,r10	/* Capture *v_regs value in r5.  */
407
408  stvx  v0,0,r10
409  stvx  v1,0,r9
410  addi  r10,r10,32
411  addi  r9,r9,32
412
413  stvx  v2,0,r10
414  stvx  v3,0,r9
415  addi  r10,r10,32
416  addi  r9,r9,32
417
418  stvx  v4,0,r10
419  stvx  v5,0,r9
420  addi  r10,r10,32
421  addi  r9,r9,32
422
423  stvx  v6,0,r10
424  stvx  v7,0,r9
425  addi  r10,r10,32
426  addi  r9,r9,32
427
428  stvx  v8,0,r10
429  stvx  v9,0,r9
430  addi  r10,r10,32
431  addi  r9,r9,32
432
433  stvx  v10,0,r10
434  stvx  v11,0,r9
435  addi  r10,r10,32
436  addi  r9,r9,32
437
438  stvx  v12,0,r10
439  stvx  v13,0,r9
440  addi  r10,r10,32
441  addi  r9,r9,32
442
443  stvx  v14,0,r10
444  stvx  v15,0,r9
445  addi  r10,r10,32
446  addi  r9,r9,32
447
448  stvx  v16,0,r10
449  stvx  v17,0,r9
450  addi  r10,r10,32
451  addi  r9,r9,32
452
453  stvx  v18,0,r10
454  stvx  v19,0,r9
455  addi  r10,r10,32
456  addi  r9,r9,32
457
458  stvx  v20,0,r10
459  stvx  v21,0,r9
460  addi  r10,r10,32
461  addi  r9,r9,32
462
463  stvx  v22,0,r10
464  stvx  v23,0,r9
465  addi  r10,r10,32
466  addi  r9,r9,32
467
468  stvx  v24,0,r10
469  stvx  v25,0,r9
470  addi  r10,r10,32
471  addi  r9,r9,32
472
473  stvx  v26,0,r10
474  stvx  v27,0,r9
475  addi  r10,r10,32
476  addi  r9,r9,32
477
478  stvx  v28,0,r10
479  stvx  v29,0,r9
480  addi  r10,r10,32
481  addi  r9,r9,32
482
483  stvx  v30,0,r10
484  stvx  v31,0,r9
485  addi  r10,r10,32
486  addi  r9,r9,32
487
488  mfvscr  v0
489  mfspr r0,VRSAVE
490  stvx  v0,0,r10
491  stw   r0,0(r9)
492
493L(has_no_vec):
494/*
495   Store either a NULL or a quadword aligned pointer to the Vector register
496   array into *v_regs.
497*/
498  std   r8,(SIGCONTEXT_V_REGS_PTR)(r3)
499
500  mr    r31,r4
501  addi  r5,r3,UCONTEXT_SIGMASK
502  addi  r4,r4,UCONTEXT_SIGMASK
503  li    r3,SIG_SETMASK
504  bl    JUMPTARGET(__sigprocmask)
505  nop
506  cmpdi  r3,0
507  bne   L(error_exit)
508
509  ld    r8,.LC__dl_hwcap@toc(r2)
510  ld    r10,(SIGCONTEXT_V_REGS_PTR)(r31)
511# ifdef SHARED
512/* Load _rtld-global._dl_hwcap.  */
513  ld    r8,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r8)
514# else
515  ld    r8,0(r8) /* Load extern _dl_hwcap.  */
516# endif
517  andis.  r6,r8,(PPC_FEATURE_HAS_ALTIVEC >> 16)
518  beq   L(has_no_vec2)
519
520  cmpdi r10,0
521  beq   L(has_no_vec2)
522  lwz   r0,(33*16)(r10)
523
524  li    r9,(16*32)
525  mtspr VRSAVE,r0
526  cmpwi r0,0
527  beq   L(has_no_vec2)
528
529  lvx   v19,r9,r10
530  la    r9,(16)(r10)
531
532  lvx   v0,0,r10
533  lvx   v1,0,r9
534  addi  r10,r10,32
535  addi  r9,r9,32
536
537  mtvscr  v19
538  lvx   v2,0,r10
539  lvx   v3,0,r9
540  addi  r10,r10,32
541  addi  r9,r9,32
542
543  lvx   v4,0,r10
544  lvx   v5,0,r9
545  addi  r10,r10,32
546  addi  r9,r9,32
547
548  lvx   v6,0,r10
549  lvx   v7,0,r9
550  addi  r10,r10,32
551  addi  r9,r9,32
552
553  lvx   v8,0,r10
554  lvx   v9,0,r9
555  addi  r10,r10,32
556  addi  r9,r9,32
557
558  lvx   v10,0,r10
559  lvx   v11,0,r9
560  addi  r10,r10,32
561  addi  r9,r9,32
562
563  lvx   v12,0,r10
564  lvx   v13,0,r9
565  addi  r10,r10,32
566  addi  r9,r9,32
567
568  lvx   v14,0,r10
569  lvx   v15,0,r9
570  addi  r10,r10,32
571  addi  r9,r9,32
572
573  lvx   v16,0,r10
574  lvx   v17,0,r9
575  addi  r10,r10,32
576  addi  r9,r9,32
577
578  lvx   v18,0,r10
579  lvx   v19,0,r9
580  addi  r10,r10,32
581  addi  r9,r9,32
582
583  lvx   v20,0,r10
584  lvx   v21,0,r9
585  addi  r10,r10,32
586  addi  r9,r9,32
587
588  lvx   v22,0,r10
589  lvx   v23,0,r9
590  addi  r10,r10,32
591  addi  r9,r9,32
592
593  lvx   v24,0,r10
594  lvx   v25,0,r9
595  addi  r10,r10,32
596  addi  r9,r9,32
597
598  lvx   v26,0,r10
599  lvx   v27,0,r9
600  addi  r10,r10,32
601  addi  r9,r9,32
602
603  lvx   v28,0,r10
604  lvx   v29,0,r9
605  addi  r10,r10,32
606  addi  r9,r9,32
607
608  lvx   v30,0,r10
609  lvx   v31,0,r9
610  addi  r10,r10,32
611  addi  r9,r9,32
612
613  lvx   v10,0,r10
614  lvx   v11,0,r9
615  addi  r10,r10,32
616  addi  r9,r9,32
617
618L(has_no_vec2):
619
620  lfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
621  lfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
622  lfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
623
624# ifdef _ARCH_PWR6
625  /* Use the extended four-operand version of the mtfsf insn.  */
626  .machine push
627  .machine "power6"
628
629  mtfsf  0xff,fp0,1,0
630
631  .machine pop
632# else
633  /* Availability of DFP indicates a 64-bit FPSCR.  */
634  andi.  r6,r8,PPC_FEATURE_HAS_DFP
635  beq    7f
636
637  .machine push
638  .machine "power6"
639
640  mtfsf  0xff,fp0,1,0
641
642  .machine pop
643
644  b      8f
645  /* Continue to operate on the FPSCR as if it were 32-bits.  */
6467:
647  mtfsf  0xff,fp0
6488:
649#endif /* _ARCH_PWR6 */
650
651  lfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
652  lfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
653  lfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
654  lfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
655  lfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
656  lfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
657  lfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
658  lfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
659  lfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
660  lfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
661  lfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
662  lfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
663  lfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
664  lfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
665  lfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
666  lfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
667  lfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
668  lfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
669  lfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
670  lfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
671  lfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
672  lfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
673  lfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
674  lfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
675  lfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
676  lfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
677  lfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
678  lfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
679  lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
680  lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
681
682  ld   r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
683  ld   r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
684  mtlr r0
685  ld   r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
686  ld   r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
687  ld   r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
688  mtxer r0
689  ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
690  ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
691  ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
692  ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
693  ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
694  ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
695  ld   r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
696  mtcr r0
697  ld   r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
698  ld   r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
699  ld   r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
700  /* Don't reload the thread ID or TLS pointer (r13).  */
701  ld   r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
702  ld   r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
703  ld   r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
704  ld   r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
705  ld   r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
706  ld   r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
707  ld   r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
708  ld   r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
709  ld   r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
710  ld   r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
711  ld   r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
712  ld   r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
713  ld   r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
714  ld   r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
715  ld   r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
716  ld   r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
717  ld   r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
718
719  /* Now we branch to the "Next Instruction Pointer" from the saved
720     context.  With the powerpc64 instruction set there is no good way to
721     do this (from user state) without clobbering either the LR or CTR.
722     The makecontext and swapcontext functions depend on the callers
723     LR being preserved so we use the CTR.  */
724  ld   r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
725  mtctr r0
726  ld   r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
727  ld   r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
728  bctr
729
730L(error_exit):
731  ld    r0,128+FRAME_LR_SAVE(r1)
732  addi  r1,r1,128
733  mtlr  r0
734  ld    r31,-8(r1)
735  blr
736
737PSEUDO_END(__swapcontext)
738
739versioned_symbol (libc, __swapcontext, swapcontext, GLIBC_2_3_4)
740