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