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