1/* Save current context and install the given one.
2 Copyright (C) 2002-2024 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

source code of glibc/sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S