]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S
Update.
[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 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 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
33 std r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
34 std r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
35 mflr r0
36 std r31,-8(1)
37 std r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
38 std r0,FRAME_LR_SAVE(r1)
39 std r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
40 std r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
41 stdu r1,-128(r1)
42 std r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r3)
43 std r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r3)
44 std r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r3)
45 std r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r3)
46 std r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r3)
47 std r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r3)
48 std r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r3)
49 std r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
50 std r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
51 std r13,(SIGCONTEXT_GP_REGS+(PT_R13*8))(r3)
52 std r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r3)
53 std r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r3)
54 std r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r3)
55 std r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r3)
56 std r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r3)
57 std r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r3)
58 std r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r3)
59 std r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r3)
60 std r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r3)
61 std r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r3)
62 std r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r3)
63 std r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r3)
64 std r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r3)
65 std r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r3)
66 std r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r3)
67 std r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
68 std r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r3)
69 std r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r3)
70 mfctr r0
71 std r0,(SIGCONTEXT_GP_REGS+(PT_CTR*8))(r3)
72 mfxer r0
73 std r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r3)
74 mfcr r0
75 std r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r3)
76
77 /* Set the return value of swapcontext to "success". R3 is the only
78 register whose value is not preserved in the saved context. */
79 li r0,0
80 std r0,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r3)
81
82 /* Zero fill fields that can't be set in user state or are unused. */
83 std r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r3)
84 std r0,(SIGCONTEXT_GP_REGS+(34*8))(r3)
85 std r0,(SIGCONTEXT_GP_REGS+(PT_SOFTE*8))(r3)
86 std r0,(SIGCONTEXT_GP_REGS+(40*8))(r3)
87 std r0,(SIGCONTEXT_GP_REGS+(41*8))(r3)
88 std r0,(SIGCONTEXT_GP_REGS+(42*8))(r3)
89 std r0,(SIGCONTEXT_GP_REGS+(PT_RESULT*8))(r3)
90
91 /* Set the PT_REGS pointer to the address of sigcontext gp_regs
92 field. Struct pt_regs and elf_gregset_t are the same thing.
93 We kept the regs field for backwards compatibility with
94 libraries built before we extended sigcontext. */
95 addi r0,r3,SIGCONTEXT_GP_REGS
96 std r0,SIGCONTEXT_PT_REGS(r3)
97
98 stfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r3)
99 stfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r3)
100 stfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r3)
101 stfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r3)
102 stfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r3)
103 stfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r3)
104 stfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r3)
105 stfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r3)
106 stfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r3)
107 stfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r3)
108 stfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r3)
109 stfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r3)
110 stfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r3)
111 stfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r3)
112 stfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r3)
113 stfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r3)
114 stfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r3)
115 stfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r3)
116 stfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r3)
117 stfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r3)
118 stfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r3)
119 stfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r3)
120 stfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r3)
121 stfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r3)
122 stfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r3)
123 stfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r3)
124 stfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r3)
125 stfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r3)
126 stfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r3)
127 stfd fp29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
128 mffs fp0
129 stfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r3)
130 stfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r3)
131 stfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r3)
132
133 mr r31,r4
134 addi r5,r3,UCONTEXT_SIGMASK
135 addi r4,r4,UCONTEXT_SIGMASK
136 li r3,SIG_SETMASK
137 bl JUMPTARGET(sigprocmask)
138 nop
139 cmpdi r3,0
140 bne L(nv_error_exit)
141
142 /*
143 * If this new ucontext refers to the point where we were interrupted
144 * by a signal, we have to use the rt_sigreturn system call to
145 * return to the context so we get both LR and CTR restored.
146 *
147 * Otherwise, the context we are restoring is either just after
148 * a procedure call (getcontext/swapcontext) or at the beginning
149 * of a procedure call (makecontext), so we don't need to restore
150 * msr and ctr. We don't restore r13 since it will be used as
151 * the TLS pointer. */
152 lwz r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
153 cmpdi r0,0
154 bne L(nv_do_sigret)
155
156 lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
157 lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
158 lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
159 mtfsf 0xff,fp0
160 lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
161 lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
162 lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
163 lfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
164 lfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
165 lfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
166 lfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
167 lfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
168 lfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
169 lfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
170 lfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
171 lfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
172 lfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
173 lfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
174 lfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
175 lfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
176 lfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
177 lfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
178 lfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
179 lfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
180 lfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
181 lfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
182 lfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
183 lfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
184 lfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
185 lfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
186 lfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
187 lfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
188 lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
189 lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
190
191 ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
192 ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
193 mtlr r0
194 ld r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
195 ld r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
196 ld r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
197 mtxer r0
198 ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
199 ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
200 ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
201 mfcr r0
202 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
203 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
204 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
205 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
206 ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
207 ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
208 ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
209 /* Don't reload the thread ID or TLS pointer (r13). */
210 ld r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
211 ld r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
212 ld r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
213 ld r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
214 ld r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
215 ld r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
216 ld r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
217 ld r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
218 ld r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
219 ld r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
220 ld r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
221 ld r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
222 ld r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
223 ld r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
224 ld r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
225 ld r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
226 ld r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
227
228 /* Now we branch to the "Next Instruction Pointer" from the saved
229 context. With the powerpc64 instruction set there is no good way to
230 do this (from user state) without clobbering either the LR or CTR.
231 The makecontext and swapcontext functions depend on the callers
232 LR being preserved so we use the CTR. */
233 ld r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
234 mtctr r0
235 ld r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
236 ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
237 bctr
238
239 L(nv_error_exit):
240 ld r0,128+FRAME_LR_SAVE(r1)
241 addi r1,r1,128
242 mtlr r0
243 ld r31,-8(r1)
244 blr
245
246 /* At this point we assume that the ucontext was created by a
247 rt_signal and we should use rt_sigreturn to restore the original
248 state. As of the 2.4.21 kernel the ucontext is the first thing
249 (offset 0) in the rt_signal frame and rt_sigreturn expects the
250 ucontext address in R1. Normally the rt-signal trampoline handles
251 this by popping dummy frame before the rt_signal syscall. In our
252 case the stack may not be in its original (signal handler return with
253 R1 pointing at the dummy frame) state. We do have the ucontext
254 address in R3, so simply copy R3 to R1 before the syscall. */
255 L(nv_do_sigret):
256 mr r1,r3,
257 li r0,SYS_ify(rt_sigreturn)
258 sc
259 /* No return. */
260 #else
261 /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
262 mflr r0
263 std r0,FRAME_LR_SAVE(r1)
264 stdu r1,-128(r1)
265 li r3,ENOSYS
266 bl JUMPTARGET(__syscall_error)
267 nop
268 li r3,-1
269 ld r0,128+FRAME_LR_SAVE(r1)
270 addi r1,r1,128
271 mtlr r0
272 blr
273 #endif
274
275 PSEUDO_END(__novec_swapcontext)
276
277 compat_symbol (libc, __novec_swapcontext, swapcontext, GLIBC_2_3)
278
279 #endif
280
281 .section ".toc","aw"
282 .LC__dl_hwcap:
283 #ifdef SHARED
284 .tc _rtld_global_ro[TC],_rtld_global_ro
285 #else
286 .tc _dl_hwcap[TC],_dl_hwcap
287 #endif
288 .section ".text"
289
290 ENTRY(__swapcontext)
291 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
292 std r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
293 std r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
294 mflr r0
295 std r31,-8(1)
296 std r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
297 std r0,FRAME_LR_SAVE(r1)
298 std r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
299 std r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
300 stdu r1,-128(r1)
301 std r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r3)
302 std r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r3)
303 std r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r3)
304 std r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r3)
305 std r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r3)
306 std r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r3)
307 std r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r3)
308 std r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
309 std r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
310 std r13,(SIGCONTEXT_GP_REGS+(PT_R13*8))(r3)
311 std r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r3)
312 std r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r3)
313 std r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r3)
314 std r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r3)
315 std r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r3)
316 std r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r3)
317 std r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r3)
318 std r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r3)
319 std r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r3)
320 std r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r3)
321 std r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r3)
322 std r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r3)
323 std r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r3)
324 std r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r3)
325 std r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r3)
326 std r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
327 std r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r3)
328 std r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r3)
329 mfctr r0
330 std r0,(SIGCONTEXT_GP_REGS+(PT_CTR*8))(r3)
331 mfxer r0
332 std r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r3)
333 mfcr r0
334 std r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r3)
335
336 /* Set the return value of swapcontext to "success". R3 is the only
337 register whose value is not preserved in the saved context. */
338 li r0,0
339 std r0,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r3)
340
341 /* Zero fill fields that can't be set in user state or are unused. */
342 std r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r3)
343 std r0,(SIGCONTEXT_GP_REGS+(34*8))(r3)
344 std r0,(SIGCONTEXT_GP_REGS+(PT_SOFTE*8))(r3)
345 std r0,(SIGCONTEXT_GP_REGS+(40*8))(r3)
346 std r0,(SIGCONTEXT_GP_REGS+(41*8))(r3)
347 std r0,(SIGCONTEXT_GP_REGS+(42*8))(r3)
348 std r0,(SIGCONTEXT_GP_REGS+(PT_RESULT*8))(r3)
349
350 /* Set the PT_REGS pointer to the address of sigcontext gp_regs
351 field. Struct pt_regs and elf_gregset_t are the same thing.
352 We kept the regs field for backwards compatibility with
353 libraries built before we extended sigcontext. */
354 addi r0,r3,SIGCONTEXT_GP_REGS
355 std r0,SIGCONTEXT_PT_REGS(r3)
356
357 stfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r3)
358 stfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r3)
359 stfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r3)
360 stfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r3)
361 stfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r3)
362 stfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r3)
363 stfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r3)
364 stfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r3)
365 stfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r3)
366 stfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r3)
367 stfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r3)
368 stfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r3)
369 stfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r3)
370 stfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r3)
371 stfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r3)
372 stfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r3)
373 stfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r3)
374 stfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r3)
375 stfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r3)
376 stfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r3)
377 stfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r3)
378 stfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r3)
379 stfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r3)
380 stfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r3)
381 stfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r3)
382 stfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r3)
383 stfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r3)
384 stfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r3)
385 stfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r3)
386 stfd fp29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
387 mffs fp0
388 stfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r3)
389 stfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r3)
390 stfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r3)
391
392 ld r8,.LC__dl_hwcap@toc(r2)
393 li r10,0
394 #ifdef SHARED
395 /* Load _rtld-global._dl_hwcap. */
396 ld r8,RTLD_GLOBAL_DL_HWCAP_OFFSET(r8)
397 #else
398 ld r8,0(r8) /* Load extern _dl_hwcap. */
399 #endif
400 andis. r8,r8,(PPC_FEATURE_HAS_ALTIVEC >> 16)
401 beq L(has_no_vec)
402
403 la r10,(SIGCONTEXT_V_RESERVE+8)(r3)
404 la r9,(SIGCONTEXT_V_RESERVE+24)(r3)
405 clrrdi r10,r10,4
406 clrrdi r9,r9,4
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 v11,0,r9
455 addi r19,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 stvx v10,0,r10
489 stvx v11,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(9)
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 r10,(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 lwz 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_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 v11,0,r9
599 addi r19,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 mfcr r0
685 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
686 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
687 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
688 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
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)