Updated to fedora-glibc-20050620T1530
[glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / getcontext.S
blob10211458d5e423ce176df6a6b1a602e6fe411b42
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 # ifdef HAVE_ASM_PPC_REL16
133         bcl     20,31,1f
134 1:      mflr    r7
135         addis   r7,r7,_GLOBAL_OFFSET_TABLE_-1b@ha
136         addi    r7,r7,_GLOBAL_OFFSET_TABLE_-1b@l
137 # else
138         bl      _GLOBAL_OFFSET_TABLE_@local-4
139         mflr    r7
140 # endif
141 # ifdef SHARED
142         lwz     r7,_rtld_global_ro@got(r7)
143         mtlr    r8
144         lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r7)
145 # else
146         lwz     r7,_dl_hwcap@got(r7)
147         mtlr    r8
148         lwz     r7,0(r7)
149 # endif
150 #else
151         lis     r7,_dl_hwcap@ha
152         lwz     r7,_dl_hwcap@l(r7)
153 #endif
154         andis.  r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
156         la      r10,(_UC_VREGS)(r3)
157         la      r9,(_UC_VREGS+16)(r3)
158         
159         beq     L(no_vec)
160 /* address of the combined VSCR/VSAVE quadword.  */     
161         la      r8,(_UC_VREGS+512)(r3)
163 /* Save the vector registers */
164         stvx  v0,0,r10
165         stvx  v1,0,r9
166         addi  r10,r10,32
167         addi  r9,r9,32
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
170    same quadword.  */
171         mfvscr  v0
173         stvx  v2,0,r10
174         stvx  v3,0,r9
175         addi  r10,r10,32
176         addi  r9,r9,32
178         stvx    v0,0,r8
179         
180         stvx  v4,0,r10
181         stvx  v5,0,r9
182         addi  r10,r10,32
183         addi  r9,r9,32
185         stvx  v6,0,r10
186         stvx  v7,0,r9
187         addi  r10,r10,32
188         addi  r9,r9,32
190         stvx  v8,0,r10
191         stvx  v9,0,r9
192         addi  r10,r10,32
193         addi  r9,r9,32
195         stvx  v10,0,r10
196         stvx  v11,0,r9
197         addi  r10,r10,32
198         addi  r9,r9,32
200         stvx  v12,0,r10
201         stvx  v13,0,r9
202         addi  r10,r10,32
203         addi  r9,r9,32
205         stvx  v14,0,r10
206         stvx  v15,0,r9
207         addi  r10,r10,32
208         addi  r9,r9,32
210         stvx  v16,0,r10
211         stvx  v17,0,r9
212         addi  r10,r10,32
213         addi  r9,r9,32
215         stvx  v18,0,r10
216         stvx  v19,0,r9
217         addi  r10,r10,32
218         addi  r9,r9,32
220         stvx  v20,0,r10
221         stvx  v21,0,r9
222         addi  r10,r10,32
223         addi  r9,r9,32
225         stvx  v22,0,r10
226         stvx  v23,0,r9
227         addi  r10,r10,32
228         addi  r9,r9,32
230         stvx  v24,0,r10
231         stvx  v25,0,r9
232         addi  r10,r10,32
233         addi  r9,r9,32
235         stvx  v26,0,r10
236         stvx  v27,0,r9
237         addi  r10,r10,32
238         addi  r9,r9,32
240         stvx  v28,0,r10
241         stvx  v29,0,r9
242         addi  r10,r10,32
243         addi  r9,r9,32
245         mfspr   r0,VRSAVE
246         stvx  v30,0,r10
247         stvx  v31,0,r9
249         stw     r0,0(r8)
251 L(no_vec):
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
255    (current R3).  */
256         lwz     r12,_FRAME_PARM_SAVE1(r1)
257         li      r4,0
258         stw     r3,_UC_REGS_PTR(r12)
259         addi    r5,r12,_UC_SIGMASK
260         li      r3,SIG_BLOCK
261         bl      __sigprocmask@local
263         lwz     r0,_FRAME_LR_SAVE+16(r1)
264         addi    r1,r1,16
265         mtlr    r0
266         blr
267 END(__getcontext)
269 versioned_symbol (libc, __getcontext, getcontext, GLIBC_2_3_4)
271 #if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
273         compat_text_section
274 ENTRY(__novec_getcontext)
275         /*
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.
279          */
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)
284         mflr    r0
285         stwu    r1,-16(r1)
286         stw     r0,20(r1)
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)
318         mfctr   r0
319         stw     r0,_UC_GREGS+(PT_CTR*4)(r3)
320         mfxer   r0
321         stw     r0,_UC_GREGS+(PT_XER*4)(r3)
322         mfcr    r0
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.  */
327         li      r0,0
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)
365         mffs    fp0
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
371         li      r4,0
372         li      r3,SIG_BLOCK
373         bl      __sigprocmask@local
375         lwz     r0,20(r1)
376         addi    r1,r1,16
377         mtlr    r0
378         blr
379 END(__novec_getcontext)
380         .previous
382 compat_symbol (libc, __novec_getcontext, getcontext, GLIBC_2_3_3)
384 #endif
386 #if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3)
388 #define _ERRNO_H        1
389 #include <bits/errno.h>
391         compat_text_section
392 ENTRY (__getcontext_stub)
393         li      r3,ENOSYS
394         b       __syscall_error@local
395 END (__getcontext_stub)
396         .previous
398 compat_symbol (libc, __getcontext_stub, getcontext, GLIBC_2_1)
400 #endif