Cleanup old obsolete PPC_REL16 checks
[glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / getcontext-common.S
blob27285ed4a53fabcafd7c161e4a90cf5de64deca1
1 /* Save current context, powerpc32 common.
2    Copyright (C) 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston MA
18    02110-1301 USA.  */
20 /* This is the common implementation of getcontext for powerpc32.
21    It not complete in itself should be included in to a framework that 
22    defines:
23      __CONTEXT_FUNC_NAME
24    and if appropriate:
25      __CONTEXT_ENABLE_FPRS
26      __CONTEXT_ENABLE_VRS
27    Any archecture that implements the Vector unit is assumed to also 
28    implement the floating unit.  */
30 /* Stack frame offsets.  */
31 #define _FRAME_BACKCHAIN        0
32 #define _FRAME_LR_SAVE          4
33 #define _FRAME_PARM_SAVE1       8
34 #define _FRAME_PARM_SAVE2       12
35 #define _FRAME_PARM_SAVE3       16
36 #define _FRAME_PARM_SAVE4       20
38 #ifdef __CONTEXT_ENABLE_VRS
39         .machine        "altivec"
40 #endif
41 ENTRY(__CONTEXT_FUNC_NAME)
42         stwu    r1,-16(r1)
43         cfi_adjust_cfa_offset (16)
44 /* Insure that the _UC_REGS start on a quadword boundary.  */
45         stw     r3,_FRAME_PARM_SAVE1(r1)
46         addi    r3,r3,_UC_REG_SPACE+12
47         clrrwi  r3,r3,4
49 /* Save the general purpose registers */
50         stw     r0,_UC_GREGS+(PT_R0*4)(r3)
51         mflr    r0
52         stw     r2,_UC_GREGS+(PT_R2*4)(r3)
53         stw     r4,_UC_GREGS+(PT_R4*4)(r3)
54 /* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers
55    return address.  */
56         stw     r0,_UC_GREGS+(PT_LNK*4)(r3)
57         stw     r0,_UC_GREGS+(PT_NIP*4)(r3)
58         stw     r0,_FRAME_LR_SAVE+16(r1)
59         cfi_offset (lr, _FRAME_LR_SAVE)
60         stw     r5,_UC_GREGS+(PT_R5*4)(r3)
61         stw     r6,_UC_GREGS+(PT_R6*4)(r3)
62         stw     r7,_UC_GREGS+(PT_R7*4)(r3)
63         stw     r8,_UC_GREGS+(PT_R8*4)(r3)
64         stw     r9,_UC_GREGS+(PT_R9*4)(r3)
65         stw     r10,_UC_GREGS+(PT_R10*4)(r3)
66         stw     r11,_UC_GREGS+(PT_R11*4)(r3)
67         stw     r12,_UC_GREGS+(PT_R12*4)(r3)
68         stw     r13,_UC_GREGS+(PT_R13*4)(r3)
69         stw     r14,_UC_GREGS+(PT_R14*4)(r3)
70         stw     r15,_UC_GREGS+(PT_R15*4)(r3)
71         stw     r16,_UC_GREGS+(PT_R16*4)(r3)
72         stw     r17,_UC_GREGS+(PT_R17*4)(r3)
73         stw     r18,_UC_GREGS+(PT_R18*4)(r3)
74         stw     r19,_UC_GREGS+(PT_R19*4)(r3)
75         stw     r20,_UC_GREGS+(PT_R20*4)(r3)
76         stw     r21,_UC_GREGS+(PT_R21*4)(r3)
77         stw     r22,_UC_GREGS+(PT_R22*4)(r3)
78         stw     r23,_UC_GREGS+(PT_R23*4)(r3)
79         stw     r24,_UC_GREGS+(PT_R24*4)(r3)
80         stw     r25,_UC_GREGS+(PT_R25*4)(r3)
81         stw     r26,_UC_GREGS+(PT_R26*4)(r3)
82         stw     r27,_UC_GREGS+(PT_R27*4)(r3)
83         stw     r28,_UC_GREGS+(PT_R28*4)(r3)
84         stw     r29,_UC_GREGS+(PT_R29*4)(r3)
85         stw     r30,_UC_GREGS+(PT_R30*4)(r3)
86         stw     r31,_UC_GREGS+(PT_R31*4)(r3)
87 /* Save the value of R1.  We had to push the stack before we
88    had the address of uc_reg_space.  So compute the address of
89    the callers stack pointer and save it as R1.  */
90         addi    r8,r1,16
91         li      r0,0
92 /* Save the count, exception and condition registers.  */
93         mfctr   r11
94         mfxer   r10
95         mfcr    r9
96         stw     r8,_UC_GREGS+(PT_R1*4)(r3)
97         stw     r11,_UC_GREGS+(PT_CTR*4)(r3)
98         stw     r10,_UC_GREGS+(PT_XER*4)(r3)
99         stw     r9,_UC_GREGS+(PT_CCR*4)(r3)
100 /* Set the return value of getcontext to "success".  R3 is the only
101    register whose value is not preserved in the saved context.  */
102         stw     r0,_UC_GREGS+(PT_R3*4)(r3)
104 /* Zero fill fields that can't be set in user state. */
105         stw     r0,_UC_GREGS+(PT_MSR*4)(r3)
106         stw     r0,_UC_GREGS+(PT_MQ*4)(r3)
108 #ifdef __CONTEXT_ENABLE_FPRS
109 /* Save the floating-point registers */
110         stfd    fp0,_UC_FREGS+(0*8)(r3)
111         stfd    fp1,_UC_FREGS+(1*8)(r3)
112         stfd    fp2,_UC_FREGS+(2*8)(r3)
113         stfd    fp3,_UC_FREGS+(3*8)(r3)
114         stfd    fp4,_UC_FREGS+(4*8)(r3)
115         stfd    fp5,_UC_FREGS+(5*8)(r3)
116         stfd    fp6,_UC_FREGS+(6*8)(r3)
117         stfd    fp7,_UC_FREGS+(7*8)(r3)
118         stfd    fp8,_UC_FREGS+(8*8)(r3)
119         stfd    fp9,_UC_FREGS+(9*8)(r3)
120         stfd    fp10,_UC_FREGS+(10*8)(r3)
121         stfd    fp11,_UC_FREGS+(11*8)(r3)
122         stfd    fp12,_UC_FREGS+(12*8)(r3)
123         stfd    fp13,_UC_FREGS+(13*8)(r3)
124         stfd    fp14,_UC_FREGS+(14*8)(r3)
125         stfd    fp15,_UC_FREGS+(15*8)(r3)
126         stfd    fp16,_UC_FREGS+(16*8)(r3)
127         stfd    fp17,_UC_FREGS+(17*8)(r3)
128         stfd    fp18,_UC_FREGS+(18*8)(r3)
129         stfd    fp19,_UC_FREGS+(19*8)(r3)
130         stfd    fp20,_UC_FREGS+(20*8)(r3)
131         stfd    fp21,_UC_FREGS+(21*8)(r3)
132         stfd    fp22,_UC_FREGS+(22*8)(r3)
133         stfd    fp23,_UC_FREGS+(23*8)(r3)
134         stfd    fp24,_UC_FREGS+(24*8)(r3)
135         stfd    fp25,_UC_FREGS+(25*8)(r3)
136         stfd    fp26,_UC_FREGS+(26*8)(r3)
137         stfd    fp27,_UC_FREGS+(27*8)(r3)
138         stfd    fp28,_UC_FREGS+(28*8)(r3)
139         stfd    fp29,_UC_FREGS+(29*8)(r3)
140         mffs    fp0
141         stfd    fp30,_UC_FREGS+(30*8)(r3)
142         stfd    fp31,_UC_FREGS+(31*8)(r3)
143         stfd    fp0,_UC_FREGS+(32*8)(r3)
145 # ifdef __CONTEXT_ENABLE_VRS
146 #  ifdef PIC
147         mflr    r8
148         bcl     20,31,1f
149 1:      mflr    r7
150         addis   r7,r7,_GLOBAL_OFFSET_TABLE_-1b@ha
151         addi    r7,r7,_GLOBAL_OFFSET_TABLE_-1b@l
152 #   ifdef SHARED
153         lwz     r7,_rtld_global_ro@got(r7)
154         mtlr    r8
155         lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r7)
156 #   else
157         lwz     r7,_dl_hwcap@got(r7)
158         mtlr    r8
159         lwz     r7,4(r7)
160 #   endif
161 #  else
162         lis     r7,(_dl_hwcap+4)@ha
163         lwz     r7,(_dl_hwcap+4)@l(r7)
164 #  endif
165         andis.  r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
167         la      r10,(_UC_VREGS)(r3)
168         la      r9,(_UC_VREGS+16)(r3)
169         
170         beq     2f      /* L(no_vec) */
171 /* address of the combined VSCR/VSAVE quadword.  */     
172         la      r8,(_UC_VREGS+512)(r3)
174 /* Save the vector registers */
175         stvx  v0,0,r10
176         stvx  v1,0,r9
177         addi  r10,r10,32
178         addi  r9,r9,32
179 /* We need to get the Vector Status and Control Register early to avoid
180    store order problems later with the VSAVE register that shares the
181    same quadword.  */
182         mfvscr  v0
184         stvx  v2,0,r10
185         stvx  v3,0,r9
186         addi  r10,r10,32
187         addi  r9,r9,32
189         stvx    v0,0,r8
190         
191         stvx  v4,0,r10
192         stvx  v5,0,r9
193         addi  r10,r10,32
194         addi  r9,r9,32
196         stvx  v6,0,r10
197         stvx  v7,0,r9
198         addi  r10,r10,32
199         addi  r9,r9,32
201         stvx  v8,0,r10
202         stvx  v9,0,r9
203         addi  r10,r10,32
204         addi  r9,r9,32
206         stvx  v10,0,r10
207         stvx  v11,0,r9
208         addi  r10,r10,32
209         addi  r9,r9,32
211         stvx  v12,0,r10
212         stvx  v13,0,r9
213         addi  r10,r10,32
214         addi  r9,r9,32
216         stvx  v14,0,r10
217         stvx  v15,0,r9
218         addi  r10,r10,32
219         addi  r9,r9,32
221         stvx  v16,0,r10
222         stvx  v17,0,r9
223         addi  r10,r10,32
224         addi  r9,r9,32
226         stvx  v18,0,r10
227         stvx  v19,0,r9
228         addi  r10,r10,32
229         addi  r9,r9,32
231         stvx  v20,0,r10
232         stvx  v21,0,r9
233         addi  r10,r10,32
234         addi  r9,r9,32
236         stvx  v22,0,r10
237         stvx  v23,0,r9
238         addi  r10,r10,32
239         addi  r9,r9,32
241         stvx  v24,0,r10
242         stvx  v25,0,r9
243         addi  r10,r10,32
244         addi  r9,r9,32
246         stvx  v26,0,r10
247         stvx  v27,0,r9
248         addi  r10,r10,32
249         addi  r9,r9,32
251         stvx  v28,0,r10
252         stvx  v29,0,r9
253         addi  r10,r10,32
254         addi  r9,r9,32
256         mfspr   r0,VRSAVE
257         stvx  v30,0,r10
258         stvx  v31,0,r9
260         stw     r0,0(r8)
262 2: /* L(no_vec): */
263 # endif
264 #endif
265 /* We need to set up parms and call sigprocmask which will clobber
266    volatile registers. So before the call we need to retrieve the
267    original ucontext ptr (parm1) from stack and store the UC_REGS_PTR
268    (current R3).  */
269         lwz     r12,_FRAME_PARM_SAVE1(r1)
270         li      r4,0
271         stw     r3,_UC_REGS_PTR(r12)
272         addi    r5,r12,_UC_SIGMASK
273         li      r3,SIG_BLOCK
274         bl      __sigprocmask@local
276         lwz     r0,_FRAME_LR_SAVE+16(r1)
277         addi    r1,r1,16
278         mtlr    r0
279         blr
280 END(__CONTEXT_FUNC_NAME)