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