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 # ifdef HAVE_ASM_PPC_REL16
135 addis r7,r7,_GLOBAL_OFFSET_TABLE_-1b@ha
136 addi r7,r7,_GLOBAL_OFFSET_TABLE_-1b@l
138 bl _GLOBAL_OFFSET_TABLE_@local-4
142 lwz r7,_rtld_global_ro@got(r7)
144 lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r7)
146 lwz r7,_dl_hwcap@got(r7)
152 lwz r7,_dl_hwcap@l(r7)
154 andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
156 la r10,(_UC_VREGS)(r3)
157 la r9,(_UC_VREGS+16)(r3)
160 /* address of the combined VSCR/VSAVE quadword. */
161 la r8,(_UC_VREGS+512)(r3)
163 /* Save the vector registers */
168 /* We need to get the Vector Status and Control Register early to avoid
169 store order problems later with the VSAVE register that shares the
252 /* We need to set up parms and call sigprocmask which will clobber
253 volatile registers. So before the call we need to retrieve the
254 original ucontext ptr (parm1) from stack and store the UC_REGS_PTR
256 lwz r12,_FRAME_PARM_SAVE1(r1)
258 stw r3,_UC_REGS_PTR(r12)
259 addi r5,r12,_UC_SIGMASK
261 bl __sigprocmask@local
263 lwz r0,_FRAME_LR_SAVE+16(r1)
269 versioned_symbol (libc, __getcontext, getcontext, GLIBC_2_3_4)
271 #if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
274 ENTRY(__novec_getcontext)
276 * Since we are not attempting to save the altivec registers,
277 * there is no need to get the register storage space
278 * aligned on a 16-byte boundary.
280 addi r3,r3,_UC_REG_SPACE
281 stw r3,_UC_REGS_PTR - _UC_REG_SPACE(r3)
282 stw r0,_UC_GREGS+(PT_R0*4)(r3)
283 stw r1,_UC_GREGS+(PT_R1*4)(r3)
287 stw r0,_UC_GREGS+(PT_LNK*4)(r3)
288 stw r0,_UC_GREGS+(PT_NIP*4)(r3)
289 stw r2,_UC_GREGS+(PT_R2*4)(r3)
290 stw r4,_UC_GREGS+(PT_R4*4)(r3)
291 stw r5,_UC_GREGS+(PT_R5*4)(r3)
292 stw r6,_UC_GREGS+(PT_R6*4)(r3)
293 stw r7,_UC_GREGS+(PT_R7*4)(r3)
294 stw r8,_UC_GREGS+(PT_R8*4)(r3)
295 stw r9,_UC_GREGS+(PT_R9*4)(r3)
296 stw r10,_UC_GREGS+(PT_R10*4)(r3)
297 stw r11,_UC_GREGS+(PT_R11*4)(r3)
298 stw r12,_UC_GREGS+(PT_R12*4)(r3)
299 stw r13,_UC_GREGS+(PT_R13*4)(r3)
300 stw r14,_UC_GREGS+(PT_R14*4)(r3)
301 stw r15,_UC_GREGS+(PT_R15*4)(r3)
302 stw r16,_UC_GREGS+(PT_R16*4)(r3)
303 stw r17,_UC_GREGS+(PT_R17*4)(r3)
304 stw r18,_UC_GREGS+(PT_R18*4)(r3)
305 stw r19,_UC_GREGS+(PT_R19*4)(r3)
306 stw r20,_UC_GREGS+(PT_R20*4)(r3)
307 stw r21,_UC_GREGS+(PT_R21*4)(r3)
308 stw r22,_UC_GREGS+(PT_R22*4)(r3)
309 stw r23,_UC_GREGS+(PT_R23*4)(r3)
310 stw r24,_UC_GREGS+(PT_R24*4)(r3)
311 stw r25,_UC_GREGS+(PT_R25*4)(r3)
312 stw r26,_UC_GREGS+(PT_R26*4)(r3)
313 stw r27,_UC_GREGS+(PT_R27*4)(r3)
314 stw r28,_UC_GREGS+(PT_R28*4)(r3)
315 stw r29,_UC_GREGS+(PT_R29*4)(r3)
316 stw r30,_UC_GREGS+(PT_R30*4)(r3)
317 stw r31,_UC_GREGS+(PT_R31*4)(r3)
319 stw r0,_UC_GREGS+(PT_CTR*4)(r3)
321 stw r0,_UC_GREGS+(PT_XER*4)(r3)
323 stw r0,_UC_GREGS+(PT_CCR*4)(r3)
325 /* Set the return value of getcontext to "success". R3 is the only
326 register whose value is not preserved in the saved context. */
328 stw r0,_UC_GREGS+(PT_R3*4)(r3)
330 /* Zero fill fields that can't be set in user state. */
331 stw r0,_UC_GREGS+(PT_MSR*4)(r3)
332 stw r0,_UC_GREGS+(PT_MQ*4)(r3)
334 /* Save the floating-point registers */
335 stfd fp0,_UC_FREGS+(0*8)(r3)
336 stfd fp1,_UC_FREGS+(1*8)(r3)
337 stfd fp2,_UC_FREGS+(2*8)(r3)
338 stfd fp3,_UC_FREGS+(3*8)(r3)
339 stfd fp4,_UC_FREGS+(4*8)(r3)
340 stfd fp5,_UC_FREGS+(5*8)(r3)
341 stfd fp6,_UC_FREGS+(6*8)(r3)
342 stfd fp7,_UC_FREGS+(7*8)(r3)
343 stfd fp8,_UC_FREGS+(8*8)(r3)
344 stfd fp9,_UC_FREGS+(9*8)(r3)
345 stfd fp10,_UC_FREGS+(10*8)(r3)
346 stfd fp11,_UC_FREGS+(11*8)(r3)
347 stfd fp12,_UC_FREGS+(12*8)(r3)
348 stfd fp13,_UC_FREGS+(13*8)(r3)
349 stfd fp14,_UC_FREGS+(14*8)(r3)
350 stfd fp15,_UC_FREGS+(15*8)(r3)
351 stfd fp16,_UC_FREGS+(16*8)(r3)
352 stfd fp17,_UC_FREGS+(17*8)(r3)
353 stfd fp18,_UC_FREGS+(18*8)(r3)
354 stfd fp19,_UC_FREGS+(19*8)(r3)
355 stfd fp20,_UC_FREGS+(20*8)(r3)
356 stfd fp21,_UC_FREGS+(21*8)(r3)
357 stfd fp22,_UC_FREGS+(22*8)(r3)
358 stfd fp23,_UC_FREGS+(23*8)(r3)
359 stfd fp24,_UC_FREGS+(24*8)(r3)
360 stfd fp25,_UC_FREGS+(25*8)(r3)
361 stfd fp26,_UC_FREGS+(26*8)(r3)
362 stfd fp27,_UC_FREGS+(27*8)(r3)
363 stfd fp28,_UC_FREGS+(28*8)(r3)
364 stfd fp29,_UC_FREGS+(29*8)(r3)
366 stfd fp30,_UC_FREGS+(30*8)(r3)
367 stfd fp31,_UC_FREGS+(31*8)(r3)
368 stfd fp0,_UC_FREGS+(32*8)(r3)
370 addi r5,r3,_UC_SIGMASK - _UC_REG_SPACE
373 bl __sigprocmask@local
379 END(__novec_getcontext)
382 compat_symbol (libc, __novec_getcontext, getcontext, GLIBC_2_3_3)
386 #if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3)
389 #include <bits/errno.h>
392 ENTRY (__getcontext_stub)
394 b __syscall_error@local
395 END (__getcontext_stub)
398 compat_symbol (libc, __getcontext_stub, getcontext, GLIBC_2_1)