]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/powerpc/powerpc64/getcontext.S
2.5-18.1
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc64 / getcontext.S
1 /* Save current context.
2 Copyright (C) 2002, 2004, 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 <asm/errno.h>
28 #include "ucontext_i.h"
29
30
31 #if SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4)
32 ENTRY(__novec_getcontext)
33 CALL_MCOUNT 1
34 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
35 std r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
36 std r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
37 mflr r0
38 std r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
39 std r0,FRAME_LR_SAVE(r1)
40 cfi_offset (lr, FRAME_LR_SAVE)
41 std r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
42 std r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
43 stdu r1,-128(r1)
44 cfi_adjust_cfa_offset (128)
45 std r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r3)
46 std r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r3)
47 std r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r3)
48 std r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r3)
49 std r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r3)
50 std r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r3)
51 std r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r3)
52 std r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
53 std r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
54 std r13,(SIGCONTEXT_GP_REGS+(PT_R13*8))(r3)
55 std r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r3)
56 std r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r3)
57 std r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r3)
58 std r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r3)
59 std r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r3)
60 std r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r3)
61 std r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r3)
62 std r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r3)
63 std r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r3)
64 std r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r3)
65 std r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r3)
66 std r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r3)
67 std r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r3)
68 std r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r3)
69 std r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r3)
70 std r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
71 std r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r3)
72 std r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r3)
73 mfctr r0
74 std r0,(SIGCONTEXT_GP_REGS+(PT_CTR*8))(r3)
75 mfxer r0
76 std r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r3)
77 mfcr r0
78 std r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r3)
79
80 /* Set the return value of swapcontext to "success". R3 is the only
81 register whose value is not preserved in the saved context. */
82 li r0,0
83 std r0,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r3)
84
85 /* Zero fill fields that can't be set in user state or are unused. */
86 std r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r3)
87 std r0,(SIGCONTEXT_GP_REGS+(34*8))(r3)
88 std r0,(SIGCONTEXT_GP_REGS+(PT_SOFTE*8))(r3)
89 std r0,(SIGCONTEXT_GP_REGS+(40*8))(r3)
90 std r0,(SIGCONTEXT_GP_REGS+(41*8))(r3)
91 std r0,(SIGCONTEXT_GP_REGS+(42*8))(r3)
92 std r0,(SIGCONTEXT_GP_REGS+(PT_RESULT*8))(r3)
93
94 /* Set the PT_REGS pointer to the address of sigcontext's gp_regs
95 field. Struct pt_regs and elf_gregset_t are the same thing.
96 We kept the regs field for backwards compatibility with
97 libraries built before we extended sigcontext. */
98 addi r0,r3,SIGCONTEXT_GP_REGS
99 std r0,SIGCONTEXT_PT_REGS(r3)
100
101 stfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r3)
102 stfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r3)
103 stfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r3)
104 stfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r3)
105 stfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r3)
106 stfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r3)
107 stfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r3)
108 stfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r3)
109 stfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r3)
110 stfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r3)
111 stfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r3)
112 stfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r3)
113 stfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r3)
114 stfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r3)
115 stfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r3)
116 stfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r3)
117 stfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r3)
118 stfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r3)
119 stfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r3)
120 stfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r3)
121 stfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r3)
122 stfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r3)
123 stfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r3)
124 stfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r3)
125 stfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r3)
126 stfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r3)
127 stfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r3)
128 stfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r3)
129 stfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r3)
130 stfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r3)
131 mffs fp0
132 stfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r3)
133 stfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r3)
134 stfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r3)
135
136 addi r5,r3,UCONTEXT_SIGMASK
137 li r4,0
138 li r3,SIG_BLOCK
139 bl JUMPTARGET(__sigprocmask)
140 nop
141 #else
142 /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
143 mflr r0
144 std r0,FRAME_LR_SAVE(r1)
145 cfi_offset (lr, FRAME_LR_SAVE)
146 stdu r1,-128(r1)
147 cfi_adjust_cfa_offset(128)
148 li r3,ENOSYS
149 bl JUMPTARGET(__syscall_error)
150 nop
151 li r3,-1
152 #endif
153
154 ld r0,128+FRAME_LR_SAVE(r1)
155 addi r1,r1,128
156 mtlr r0
157 blr
158 PSEUDO_END(__novec_getcontext)
159
160 compat_symbol (libc, __novec_getcontext, getcontext, GLIBC_2_3)
161
162 #endif
163
164 .section ".toc","aw"
165 .LC__dl_hwcap:
166 #ifdef SHARED
167 .tc _rtld_global_ro[TC],_rtld_global_ro
168 #else
169 .tc _dl_hwcap[TC],_dl_hwcap
170 #endif
171 .section ".text"
172
173 .machine "altivec"
174 ENTRY(__getcontext)
175 CALL_MCOUNT 1
176 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
177 std r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
178 std r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
179 mflr r0
180 std r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
181 std r0,FRAME_LR_SAVE(r1)
182 cfi_offset (lr, FRAME_LR_SAVE)
183 std r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
184 std r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
185 stdu r1,-128(r1)
186 cfi_adjust_cfa_offset (128)
187 std r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r3)
188 std r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r3)
189 std r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r3)
190 std r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r3)
191 std r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r3)
192 std r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r3)
193 std r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r3)
194 std r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
195 std r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
196 std r13,(SIGCONTEXT_GP_REGS+(PT_R13*8))(r3)
197 std r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r3)
198 std r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r3)
199 std r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r3)
200 std r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r3)
201 std r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r3)
202 std r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r3)
203 std r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r3)
204 std r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r3)
205 std r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r3)
206 std r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r3)
207 std r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r3)
208 std r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r3)
209 std r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r3)
210 std r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r3)
211 std r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r3)
212 std r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
213 std r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r3)
214 std r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r3)
215 mfctr r0
216 std r0,(SIGCONTEXT_GP_REGS+(PT_CTR*8))(r3)
217 mfxer r0
218 std r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r3)
219 mfcr r0
220 std r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r3)
221
222 /* Set the return value of swapcontext to "success". R3 is the only
223 register whose value is not preserved in the saved context. */
224 li r0,0
225 std r0,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r3)
226
227 /* Zero fill fields that can't be set in user state or are unused. */
228 std r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r3)
229 std r0,(SIGCONTEXT_GP_REGS+(34*8))(r3)
230 std r0,(SIGCONTEXT_GP_REGS+(PT_SOFTE*8))(r3)
231 std r0,(SIGCONTEXT_GP_REGS+(40*8))(r3)
232 std r0,(SIGCONTEXT_GP_REGS+(41*8))(r3)
233 std r0,(SIGCONTEXT_GP_REGS+(42*8))(r3)
234 std r0,(SIGCONTEXT_GP_REGS+(PT_RESULT*8))(r3)
235
236 /* Set the PT_REGS pointer to the address of sigcontext's gp_regs
237 field. Struct pt_regs and elf_gregset_t are the same thing.
238 We kept the regs field for backwards compatibility with
239 libraries built before we extended sigcontext. */
240 addi r0,r3,SIGCONTEXT_GP_REGS
241 std r0,SIGCONTEXT_PT_REGS(r3)
242
243 stfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r3)
244 stfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r3)
245 stfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r3)
246 stfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r3)
247 stfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r3)
248 stfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r3)
249 stfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r3)
250 stfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r3)
251 stfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r3)
252 stfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r3)
253 stfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r3)
254 stfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r3)
255 stfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r3)
256 stfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r3)
257 stfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r3)
258 stfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r3)
259 stfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r3)
260 stfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r3)
261 stfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r3)
262 stfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r3)
263 stfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r3)
264 stfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r3)
265 stfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r3)
266 stfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r3)
267 stfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r3)
268 stfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r3)
269 stfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r3)
270 stfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r3)
271 stfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r3)
272 stfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r3)
273 mffs fp0
274 stfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r3)
275 stfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r3)
276 stfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r3)
277
278 ld r5,.LC__dl_hwcap@toc(r2)
279 # ifdef SHARED
280 /* Load _rtld-global._dl_hwcap. */
281 ld r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
282 # else
283 ld r5,0(r5) /* Load extern _dl_hwcap. */
284 # endif
285 la r10,(SIGCONTEXT_V_RESERVE+8)(r3)
286 la r9,(SIGCONTEXT_V_RESERVE+24)(r3)
287
288 andis. r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
289
290 clrrdi r10,r10,4
291 beq L(has_no_vec)
292 clrrdi r9,r9,4
293 mr r5,r10 /* Capture *v_regs value in r5. */
294
295 stvx v0,0,r10
296 stvx v1,0,r9
297 addi r10,r10,32
298 addi r9,r9,32
299
300 stvx v2,0,r10
301 stvx v3,0,r9
302 addi r10,r10,32
303 addi r9,r9,32
304
305 stvx v4,0,r10
306 stvx v5,0,r9
307 addi r10,r10,32
308 addi r9,r9,32
309
310 stvx v6,0,r10
311 stvx v7,0,r9
312 addi r10,r10,32
313 addi r9,r9,32
314
315 stvx v8,0,r10
316 stvx v9,0,r9
317 addi r10,r10,32
318 addi r9,r9,32
319
320 stvx v10,0,r10
321 stvx v11,0,r9
322 addi r10,r10,32
323 addi r9,r9,32
324
325 stvx v12,0,r10
326 stvx v13,0,r9
327 addi r10,r10,32
328 addi r9,r9,32
329
330 stvx v14,0,r10
331 stvx v15,0,r9
332 addi r10,r10,32
333 addi r9,r9,32
334
335 stvx v16,0,r10
336 stvx v17,0,r9
337 addi r10,r10,32
338 addi r9,r9,32
339
340 stvx v18,0,r10
341 stvx v19,0,r9
342 addi r10,r10,32
343 addi r9,r9,32
344
345 stvx v20,0,r10
346 stvx v21,0,r9
347 addi r10,r10,32
348 addi r9,r9,32
349
350 stvx v22,0,r10
351 stvx v23,0,r9
352 addi r10,r10,32
353 addi r9,r9,32
354
355 stvx v24,0,r10
356 stvx v25,0,r9
357 addi r10,r10,32
358 addi r9,r9,32
359
360 stvx v26,0,r10
361 stvx v27,0,r9
362 addi r10,r10,32
363 addi r9,r9,32
364
365 stvx v28,0,r10
366 stvx v29,0,r9
367 addi r10,r10,32
368 addi r9,r9,32
369
370 stvx v30,0,r10
371 stvx v31,0,r9
372 addi r10,r10,32
373 addi r9,r9,32
374
375 mfvscr v0
376 mfspr r0,VRSAVE
377 stvx v0,0,r10
378 stw r0,0(9)
379
380 L(has_no_vec):
381 /*
382 Store either a NULL or a quadword aligned pointer to the Vector register
383 array into *v_regs.
384 */
385 std r5,(SIGCONTEXT_V_REGS_PTR)(r3)
386
387 addi r5,r3,UCONTEXT_SIGMASK
388 li r4,0
389 li r3,SIG_BLOCK
390 bl JUMPTARGET(__sigprocmask)
391 nop
392 #else
393 /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
394 mflr r0
395 std r0,FRAME_LR_SAVE(r1)
396 cfi_offset (lr, FRAME_LR_SAVE)
397 stdu r1,-128(r1)
398 cfi_adjust_cfa_offset (128)
399 li r3,ENOSYS
400 bl JUMPTARGET(__syscall_error)
401 nop
402 li r3,-1
403 #endif
404
405 ld r0,128+FRAME_LR_SAVE(r1)
406 addi r1,r1,128
407 mtlr r0
408 blr
409 PSEUDO_END(__getcontext)
410
411 versioned_symbol (libc, __getcontext, getcontext, GLIBC_2_3_4)