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