(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / getcontext.S
blob4c75354a5f12d029b4736e959e796dd884ae5e1a
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
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <rtld-global-offsets.h>
22 #include <shlib-compat.h>
24 #define __ASSEMBLY__
25 #include <asm/ptrace.h>
26 #include "ucontext_i.h"
28         .machine        "altivec"
29 ENTRY(__getcontext)
30         stwu    r1,-16(r1)
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
34         clrrwi  r3,r3,4
36 /* Save the general purpose registers */
37         stw     r0,_UC_GREGS+(PT_R0*4)(r3)
38         mflr    r0
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
42    return address.  */
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.  */
76         addi    r8,r1,16
77         li      r0,0
78 /* Save the count, exception and condition registers.  */
79         mfctr   r11
80         mfxer   r10
81         mfcr    r9
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)
125         mffs    fp0
126         stfd    fp30,_UC_FREGS+(30*8)(r3)
127         stfd    fp31,_UC_FREGS+(31*8)(r3)
128         stfd    fp0,_UC_FREGS+(32*8)(r3)
130 #ifdef PIC
131         mflr    r8
132         bl      _GLOBAL_OFFSET_TABLE_@local-4
133         mflr    r7
134 # ifdef SHARED
135         lwz     r7,_rtld_global_ro@got(r7)
136         mtlr    r8
137         lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r7)
138 # else
139         lwz     r7,_dl_hwcap@got(r7)
140         mtlr    r8
141         lwz     r7,0(r7)
142 # endif
143 #else
144         lis     r7,_dl_hwcap@ha
145         lwz     r7,_dl_hwcap@l(r7)
146 #endif
147         andis.  r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
149         la      r10,(_UC_VREGS)(r3)
150         la      r9,(_UC_VREGS+16)(r3)
151         
152         beq     L(no_vec)
153 /* address of the combined VSCR/VSAVE quadword.  */     
154         la      r8,(_UC_VREGS+512)(r3)
156 /* Save the vector registers */
157         stvx  v0,0,r10
158         stvx  v1,0,r9
159         addi  r10,r10,32
160         addi  r9,r9,32
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
163    same quadword.  */
164         mfvscr  v0
166         stvx  v2,0,r10
167         stvx  v3,0,r9
168         addi  r10,r10,32
169         addi  r9,r9,32
171         stvx    v0,0,r8
172         
173         stvx  v4,0,r10
174         stvx  v5,0,r9
175         addi  r10,r10,32
176         addi  r9,r9,32
178         stvx  v6,0,r10
179         stvx  v7,0,r9
180         addi  r10,r10,32
181         addi  r9,r9,32
183         stvx  v8,0,r10
184         stvx  v9,0,r9
185         addi  r10,r10,32
186         addi  r9,r9,32
188         stvx  v10,0,r10
189         stvx  v11,0,r9
190         addi  r10,r10,32
191         addi  r9,r9,32
193         stvx  v12,0,r10
194         stvx  v13,0,r9
195         addi  r10,r10,32
196         addi  r9,r9,32
198         stvx  v14,0,r10
199         stvx  v15,0,r9
200         addi  r10,r10,32
201         addi  r9,r9,32
203         stvx  v16,0,r10
204         stvx  v17,0,r9
205         addi  r10,r10,32
206         addi  r9,r9,32
208         stvx  v18,0,r10
209         stvx  v19,0,r9
210         addi  r10,r10,32
211         addi  r9,r9,32
213         stvx  v20,0,r10
214         stvx  v21,0,r9
215         addi  r10,r10,32
216         addi  r9,r9,32
218         stvx  v22,0,r10
219         stvx  v23,0,r9
220         addi  r10,r10,32
221         addi  r9,r9,32
223         stvx  v24,0,r10
224         stvx  v25,0,r9
225         addi  r10,r10,32
226         addi  r9,r9,32
228         stvx  v26,0,r10
229         stvx  v27,0,r9
230         addi  r10,r10,32
231         addi  r9,r9,32
233         stvx  v28,0,r10
234         stvx  v29,0,r9
235         addi  r10,r10,32
236         addi  r9,r9,32
238         mfspr   r0,VRSAVE
239         stvx  v30,0,r10
240         stvx  v31,0,r9
242         stw     r0,0(r8)
244 L(no_vec):
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
248    (current R3).  */
249         lwz     r12,_FRAME_PARM_SAVE1(r1)
250         li      r4,0
251         stw     r3,_UC_REGS_PTR(r12)
252         addi    r5,r12,_UC_SIGMASK
253         li      r3,SIG_BLOCK
254         bl      JUMPTARGET(__sigprocmask)
256         lwz     r0,_FRAME_LR_SAVE+16(r1)
257         addi    r1,r1,16
258         mtlr    r0
259         blr
260 END(__getcontext)
262 versioned_symbol (libc, __getcontext, getcontext, GLIBC_2_3_4)
264 #if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
266         compat_text_section
267 ENTRY(__novec_getcontext)
268         /*
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.
272          */
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)
277         mflr    r0
278         stwu    r1,-16(r1)
279         stw     r0,20(r1)
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)
311         mfctr   r0
312         stw     r0,_UC_GREGS+(PT_CTR*4)(r3)
313         mfxer   r0
314         stw     r0,_UC_GREGS+(PT_XER*4)(r3)
315         mfcr    r0
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.  */
320         li      r0,0
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)
358         mffs    fp0
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
364         li      r4,0
365         li      r3,SIG_BLOCK
366         bl      JUMPTARGET(__sigprocmask)
368         lwz     r0,20(r1)
369         addi    r1,r1,16
370         mtlr    r0
371         blr
372 END(__novec_getcontext)
373         .previous
375 compat_symbol (libc, __novec_getcontext, getcontext, GLIBC_2_3_3)
377 #endif
379 #if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3)
381 #define _ERRNO_H        1
382 #include <bits/errno.h>
384         compat_text_section
385 ENTRY (__getcontext_stub)
386         li      r3,ENOSYS
387         b       JUMPTARGET(__syscall_error)
388 END (__getcontext_stub)
389         .previous
391 compat_symbol (libc, __getcontext_stub, getcontext, GLIBC_2_1)
393 #endif