1 /* Save current context.
2 Copyright (C) 2002, 2004 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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
21 #include <rtld-global-offsets.h>
22 #include <shlib-compat.h>
25 #include <asm/ptrace.h>
26 #include "ucontext_i.h"
31 /* Insure that the _UC_REGS start on a quadword boundary. */
32 stw r3,_FRAME_PARM_SAVE1(r1)
33 addi r3,r3,_UC_REG_SPACE+12
36 /* Save the general purpose registers */
37 stw r0,_UC_GREGS+(PT_R0*4)(r3)
39 stw r2,_UC_GREGS+(PT_R2*4)(r3)
40 stw r4,_UC_GREGS+(PT_R4*4)(r3)
41 /* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers
43 stw r0,_UC_GREGS+(PT_LNK*4)(r3)
44 stw r0,_UC_GREGS+(PT_NIP*4)(r3)
45 stw r0,_FRAME_LR_SAVE+16(r1)
46 stw r5,_UC_GREGS+(PT_R5*4)(r3)
47 stw r6,_UC_GREGS+(PT_R6*4)(r3)
48 stw r7,_UC_GREGS+(PT_R7*4)(r3)
49 stw r8,_UC_GREGS+(PT_R8*4)(r3)
50 stw r9,_UC_GREGS+(PT_R9*4)(r3)
51 stw r10,_UC_GREGS+(PT_R10*4)(r3)
52 stw r11,_UC_GREGS+(PT_R11*4)(r3)
53 stw r12,_UC_GREGS+(PT_R12*4)(r3)
54 stw r13,_UC_GREGS+(PT_R13*4)(r3)
55 stw r14,_UC_GREGS+(PT_R14*4)(r3)
56 stw r15,_UC_GREGS+(PT_R15*4)(r3)
57 stw r16,_UC_GREGS+(PT_R16*4)(r3)
58 stw r17,_UC_GREGS+(PT_R17*4)(r3)
59 stw r18,_UC_GREGS+(PT_R18*4)(r3)
60 stw r19,_UC_GREGS+(PT_R19*4)(r3)
61 stw r20,_UC_GREGS+(PT_R20*4)(r3)
62 stw r21,_UC_GREGS+(PT_R21*4)(r3)
63 stw r22,_UC_GREGS+(PT_R22*4)(r3)
64 stw r23,_UC_GREGS+(PT_R23*4)(r3)
65 stw r24,_UC_GREGS+(PT_R24*4)(r3)
66 stw r25,_UC_GREGS+(PT_R25*4)(r3)
67 stw r26,_UC_GREGS+(PT_R26*4)(r3)
68 stw r27,_UC_GREGS+(PT_R27*4)(r3)
69 stw r28,_UC_GREGS+(PT_R28*4)(r3)
70 stw r29,_UC_GREGS+(PT_R29*4)(r3)
71 stw r30,_UC_GREGS+(PT_R30*4)(r3)
72 stw r31,_UC_GREGS+(PT_R31*4)(r3)
73 /* Save the value of R1. We had to push the stack before we
74 had the address of uc_reg_space. So compute the address of
75 the callers stack pointer and save it as R1. */
78 /* Save the count, exception and condition registers. */
82 stw r8,_UC_GREGS+(PT_R1*4)(r3)
83 stw r11,_UC_GREGS+(PT_CTR*4)(r3)
84 stw r10,_UC_GREGS+(PT_XER*4)(r3)
85 stw r9,_UC_GREGS+(PT_CCR*4)(r3)
86 /* Set the return value of getcontext to "success". R3 is the only
87 register whose value is not preserved in the saved context. */
88 stw r0,_UC_GREGS+(PT_R3*4)(r3)
90 /* Zero fill fields that can't be set in user state. */
91 stw r0,_UC_GREGS+(PT_MSR*4)(r3)
92 stw r0,_UC_GREGS+(PT_MQ*4)(r3)
94 /* Save the floating-point registers */
95 stfd fp0,_UC_FREGS+(0*8)(r3)
96 stfd fp1,_UC_FREGS+(1*8)(r3)
97 stfd fp2,_UC_FREGS+(2*8)(r3)
98 stfd fp3,_UC_FREGS+(3*8)(r3)
99 stfd fp4,_UC_FREGS+(4*8)(r3)
100 stfd fp5,_UC_FREGS+(5*8)(r3)
101 stfd fp6,_UC_FREGS+(6*8)(r3)
102 stfd fp7,_UC_FREGS+(7*8)(r3)
103 stfd fp8,_UC_FREGS+(8*8)(r3)
104 stfd fp9,_UC_FREGS+(9*8)(r3)
105 stfd fp10,_UC_FREGS+(10*8)(r3)
106 stfd fp11,_UC_FREGS+(11*8)(r3)
107 stfd fp12,_UC_FREGS+(12*8)(r3)
108 stfd fp13,_UC_FREGS+(13*8)(r3)
109 stfd fp14,_UC_FREGS+(14*8)(r3)
110 stfd fp15,_UC_FREGS+(15*8)(r3)
111 stfd fp16,_UC_FREGS+(16*8)(r3)
112 stfd fp17,_UC_FREGS+(17*8)(r3)
113 stfd fp18,_UC_FREGS+(18*8)(r3)
114 stfd fp19,_UC_FREGS+(19*8)(r3)
115 stfd fp20,_UC_FREGS+(20*8)(r3)
116 stfd fp21,_UC_FREGS+(21*8)(r3)
117 stfd fp22,_UC_FREGS+(22*8)(r3)
118 stfd fp23,_UC_FREGS+(23*8)(r3)
119 stfd fp24,_UC_FREGS+(24*8)(r3)
120 stfd fp25,_UC_FREGS+(25*8)(r3)
121 stfd fp26,_UC_FREGS+(26*8)(r3)
122 stfd fp27,_UC_FREGS+(27*8)(r3)
123 stfd fp28,_UC_FREGS+(28*8)(r3)
124 stfd fp29,_UC_FREGS+(29*8)(r3)
126 stfd fp30,_UC_FREGS+(30*8)(r3)
127 stfd fp31,_UC_FREGS+(31*8)(r3)
128 stfd fp0,_UC_FREGS+(32*8)(r3)
132 bl _GLOBAL_OFFSET_TABLE_@local-4
135 lwz r7,_rtld_global_ro@got(r7)
137 lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r7)
139 lwz r7,_dl_hwcap@got(r7)
145 lwz r7,_dl_hwcap@l(r7)
147 andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
149 la r10,(_UC_VREGS)(r3)
150 la r9,(_UC_VREGS+16)(r3)
153 /* address of the combined VSCR/VSAVE quadword. */
154 la r8,(_UC_VREGS+512)(r3)
156 /* Save the vector registers */
161 /* We need to get the Vector Status and Control Register early to avoid
162 store order problems later with the VSAVE register that shares the
245 /* We need to set up parms and call sigprocmask which will clobber
246 volatile registers. So before the call we need to retrieve the
247 original ucontext ptr (parm1) from stack and store the UC_REGS_PTR
249 lwz r12,_FRAME_PARM_SAVE1(r1)
251 stw r3,_UC_REGS_PTR(r12)
252 addi r5,r12,_UC_SIGMASK
254 bl JUMPTARGET(__sigprocmask)
256 lwz r0,_FRAME_LR_SAVE+16(r1)
262 versioned_symbol (libc, __getcontext, getcontext, GLIBC_2_3_4)
264 #if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
267 ENTRY(__novec_getcontext)
269 * Since we are not attempting to save the altivec registers,
270 * there is no need to get the register storage space
271 * aligned on a 16-byte boundary.
273 addi r3,r3,_UC_REG_SPACE
274 stw r3,_UC_REGS_PTR - _UC_REG_SPACE(r3)
275 stw r0,_UC_GREGS+(PT_R0*4)(r3)
276 stw r1,_UC_GREGS+(PT_R1*4)(r3)
280 stw r0,_UC_GREGS+(PT_LNK*4)(r3)
281 stw r0,_UC_GREGS+(PT_NIP*4)(r3)
282 stw r2,_UC_GREGS+(PT_R2*4)(r3)
283 stw r4,_UC_GREGS+(PT_R4*4)(r3)
284 stw r5,_UC_GREGS+(PT_R5*4)(r3)
285 stw r6,_UC_GREGS+(PT_R6*4)(r3)
286 stw r7,_UC_GREGS+(PT_R7*4)(r3)
287 stw r8,_UC_GREGS+(PT_R8*4)(r3)
288 stw r9,_UC_GREGS+(PT_R9*4)(r3)
289 stw r10,_UC_GREGS+(PT_R10*4)(r3)
290 stw r11,_UC_GREGS+(PT_R11*4)(r3)
291 stw r12,_UC_GREGS+(PT_R12*4)(r3)
292 stw r13,_UC_GREGS+(PT_R13*4)(r3)
293 stw r14,_UC_GREGS+(PT_R14*4)(r3)
294 stw r15,_UC_GREGS+(PT_R15*4)(r3)
295 stw r16,_UC_GREGS+(PT_R16*4)(r3)
296 stw r17,_UC_GREGS+(PT_R17*4)(r3)
297 stw r18,_UC_GREGS+(PT_R18*4)(r3)
298 stw r19,_UC_GREGS+(PT_R19*4)(r3)
299 stw r20,_UC_GREGS+(PT_R20*4)(r3)
300 stw r21,_UC_GREGS+(PT_R21*4)(r3)
301 stw r22,_UC_GREGS+(PT_R22*4)(r3)
302 stw r23,_UC_GREGS+(PT_R23*4)(r3)
303 stw r24,_UC_GREGS+(PT_R24*4)(r3)
304 stw r25,_UC_GREGS+(PT_R25*4)(r3)
305 stw r26,_UC_GREGS+(PT_R26*4)(r3)
306 stw r27,_UC_GREGS+(PT_R27*4)(r3)
307 stw r28,_UC_GREGS+(PT_R28*4)(r3)
308 stw r29,_UC_GREGS+(PT_R29*4)(r3)
309 stw r30,_UC_GREGS+(PT_R30*4)(r3)
310 stw r31,_UC_GREGS+(PT_R31*4)(r3)
312 stw r0,_UC_GREGS+(PT_CTR*4)(r3)
314 stw r0,_UC_GREGS+(PT_XER*4)(r3)
316 stw r0,_UC_GREGS+(PT_CCR*4)(r3)
318 /* Set the return value of getcontext to "success". R3 is the only
319 register whose value is not preserved in the saved context. */
321 stw r0,_UC_GREGS+(PT_R3*4)(r3)
323 /* Zero fill fields that can't be set in user state. */
324 stw r0,_UC_GREGS+(PT_MSR*4)(r3)
325 stw r0,_UC_GREGS+(PT_MQ*4)(r3)
327 /* Save the floating-point registers */
328 stfd fp0,_UC_FREGS+(0*8)(r3)
329 stfd fp1,_UC_FREGS+(1*8)(r3)
330 stfd fp2,_UC_FREGS+(2*8)(r3)
331 stfd fp3,_UC_FREGS+(3*8)(r3)
332 stfd fp4,_UC_FREGS+(4*8)(r3)
333 stfd fp5,_UC_FREGS+(5*8)(r3)
334 stfd fp6,_UC_FREGS+(6*8)(r3)
335 stfd fp7,_UC_FREGS+(7*8)(r3)
336 stfd fp8,_UC_FREGS+(8*8)(r3)
337 stfd fp9,_UC_FREGS+(9*8)(r3)
338 stfd fp10,_UC_FREGS+(10*8)(r3)
339 stfd fp11,_UC_FREGS+(11*8)(r3)
340 stfd fp12,_UC_FREGS+(12*8)(r3)
341 stfd fp13,_UC_FREGS+(13*8)(r3)
342 stfd fp14,_UC_FREGS+(14*8)(r3)
343 stfd fp15,_UC_FREGS+(15*8)(r3)
344 stfd fp16,_UC_FREGS+(16*8)(r3)
345 stfd fp17,_UC_FREGS+(17*8)(r3)
346 stfd fp18,_UC_FREGS+(18*8)(r3)
347 stfd fp19,_UC_FREGS+(19*8)(r3)
348 stfd fp20,_UC_FREGS+(20*8)(r3)
349 stfd fp21,_UC_FREGS+(21*8)(r3)
350 stfd fp22,_UC_FREGS+(22*8)(r3)
351 stfd fp23,_UC_FREGS+(23*8)(r3)
352 stfd fp24,_UC_FREGS+(24*8)(r3)
353 stfd fp25,_UC_FREGS+(25*8)(r3)
354 stfd fp26,_UC_FREGS+(26*8)(r3)
355 stfd fp27,_UC_FREGS+(27*8)(r3)
356 stfd fp28,_UC_FREGS+(28*8)(r3)
357 stfd fp29,_UC_FREGS+(29*8)(r3)
359 stfd fp30,_UC_FREGS+(30*8)(r3)
360 stfd fp31,_UC_FREGS+(31*8)(r3)
361 stfd fp0,_UC_FREGS+(32*8)(r3)
363 addi r5,r3,_UC_SIGMASK - _UC_REG_SPACE
366 bl JUMPTARGET(__sigprocmask)
372 END(__novec_getcontext)
375 compat_symbol (libc, __novec_getcontext, getcontext, GLIBC_2_3_3)
379 #if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3)
382 #include <bits/errno.h>
385 ENTRY (__getcontext_stub)
387 b JUMPTARGET(__syscall_error)
388 END (__getcontext_stub)
391 compat_symbol (libc, __getcontext_stub, getcontext, GLIBC_2_1)