]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
* sysdeps/powerpc/powerpc32/fpu/fprsave.S: Add cfi_offset for spilling
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / setcontext-common.S
1 /* Jump to a new context powerpc32 common.
2 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
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.
9
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.
14
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. */
19
20 /* This is the common implementation of setcontext 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. */
29
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
37
38 #ifdef __CONTEXT_ENABLE_VRS
39 .machine "altivec"
40 #endif
41 ENTRY(__CONTEXT_FUNC_NAME)
42 mflr r0
43 stwu r1,-16(r1)
44 cfi_adjust_cfa_offset (16)
45 stw r0,20(r1)
46 cfi_offset (lr, _FRAME_LR_SAVE)
47 stw r31,12(r1)
48 cfi_offset(r31,-4)
49 lwz r31,_UC_REGS_PTR(r3)
50
51 /*
52 * If this ucontext refers to the point where we were interrupted
53 * by a signal, we have to use the rt_sigreturn system call to
54 * return to the context so we get both LR and CTR restored.
55 *
56 * Otherwise, the context we are restoring is either just after
57 * a procedure call (getcontext/swapcontext) or at the beginning
58 * of a procedure call (makecontext), so we don't need to restore
59 * r0, xer, ctr. We don't restore r2 since it will be used as
60 * the TLS pointer.
61 */
62 lwz r0,_UC_GREGS+(PT_MSR*4)(r31)
63 cmpwi r0,0
64 bne 4f /* L(do_sigret) */
65
66 /* Restore the signal mask */
67 li r5,0
68 addi r4,r3,_UC_SIGMASK
69 li r3,SIG_SETMASK
70 bl __sigprocmask@local
71 cmpwi r3,0
72 bne 3f /* L(error_exit) */
73
74 #ifdef __CONTEXT_ENABLE_FPRS
75 # ifdef __CONTEXT_ENABLE_VRS
76 # ifdef PIC
77 mflr r8
78 # ifdef HAVE_ASM_PPC_REL16
79 bcl 20,31,1f
80 1: mflr r7
81 addis r7,r7,_GLOBAL_OFFSET_TABLE_-1b@ha
82 addi r7,r7,_GLOBAL_OFFSET_TABLE_-1b@l
83 # else
84 bl _GLOBAL_OFFSET_TABLE_@local-4
85 mflr r7
86 # endif
87 # ifdef SHARED
88 lwz r7,_rtld_global_ro@got(r7)
89 mtlr r8
90 lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r7)
91 # else
92 lwz r7,_dl_hwcap@got(r7)
93 mtlr r8
94 lwz r7,0(r7)
95 # endif
96 # else
97 lis r7,_dl_hwcap@ha
98 lwz r7,_dl_hwcap@l(r7)
99 # endif
100 andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
101 la r10,(_UC_VREGS)(r31)
102 beq 2f /* L(has_no_vec) */
103
104 lwz r0,(32*16)(r10)
105 li r9,(32*16)
106 cmpwi r0,0
107 mtspr VRSAVE,r0
108 beq 2f /* L(has_no_vec) */
109
110 lvx v19,r9,r10
111 la r9,(16)(r10)
112
113 lvx v0,0,r10
114 lvx v1,0,r9
115 addi r10,r10,32
116 addi r9,r9,32
117
118 mtvscr v19
119 lvx v2,0,r10
120 lvx v3,0,r9
121 addi r10,r10,32
122 addi r9,r9,32
123
124 lvx v4,0,r10
125 lvx v5,0,r9
126 addi r10,r10,32
127 addi r9,r9,32
128
129 lvx v6,0,r10
130 lvx v7,0,r9
131 addi r10,r10,32
132 addi r9,r9,32
133
134 lvx v8,0,r10
135 lvx v9,0,r9
136 addi r10,r10,32
137 addi r9,r9,32
138
139 lvx v10,0,r10
140 lvx v11,0,r9
141 addi r10,r10,32
142 addi r9,r9,32
143
144 lvx v12,0,r10
145 lvx v13,0,r9
146 addi r10,r10,32
147 addi r9,r9,32
148
149 lvx v14,0,r10
150 lvx v15,0,r9
151 addi r10,r10,32
152 addi r9,r9,32
153
154 lvx v16,0,r10
155 lvx v17,0,r9
156 addi r10,r10,32
157 addi r9,r9,32
158
159 lvx v18,0,r10
160 lvx v19,0,r9
161 addi r10,r10,32
162 addi r9,r9,32
163
164 lvx v20,0,r10
165 lvx v21,0,r9
166 addi r10,r10,32
167 addi r9,r9,32
168
169 lvx v22,0,r10
170 lvx v23,0,r9
171 addi r10,r10,32
172 addi r9,r9,32
173
174 lvx v24,0,r10
175 lvx v25,0,r9
176 addi r10,r10,32
177 addi r9,r9,32
178
179 lvx v26,0,r10
180 lvx v27,0,r9
181 addi r10,r10,32
182 addi r9,r9,32
183
184 lvx v28,0,r10
185 lvx v29,0,r9
186 addi r10,r10,32
187 addi r9,r9,32
188
189 lvx v30,0,r10
190 lvx v31,0,r9
191 addi r10,r10,32
192 addi r9,r9,32
193
194 lvx v10,0,r10
195 lvx v11,0,r9
196
197 2: /* L(has_no_vec): */
198 # endif /* __CONTEXT_ENABLE_VRS */
199 /* Restore the floating-point registers */
200 lfd fp31,_UC_FREGS+(32*8)(r31)
201 lfd fp0,_UC_FREGS+(0*8)(r31)
202 mtfsf 0xff,fp31
203 lfd fp1,_UC_FREGS+(1*8)(r31)
204 lfd fp2,_UC_FREGS+(2*8)(r31)
205 lfd fp3,_UC_FREGS+(3*8)(r31)
206 lfd fp4,_UC_FREGS+(4*8)(r31)
207 lfd fp5,_UC_FREGS+(5*8)(r31)
208 lfd fp6,_UC_FREGS+(6*8)(r31)
209 lfd fp7,_UC_FREGS+(7*8)(r31)
210 lfd fp8,_UC_FREGS+(8*8)(r31)
211 lfd fp9,_UC_FREGS+(9*8)(r31)
212 lfd fp10,_UC_FREGS+(10*8)(r31)
213 lfd fp11,_UC_FREGS+(11*8)(r31)
214 lfd fp12,_UC_FREGS+(12*8)(r31)
215 lfd fp13,_UC_FREGS+(13*8)(r31)
216 lfd fp14,_UC_FREGS+(14*8)(r31)
217 lfd fp15,_UC_FREGS+(15*8)(r31)
218 lfd fp16,_UC_FREGS+(16*8)(r31)
219 lfd fp17,_UC_FREGS+(17*8)(r31)
220 lfd fp18,_UC_FREGS+(18*8)(r31)
221 lfd fp19,_UC_FREGS+(19*8)(r31)
222 lfd fp20,_UC_FREGS+(20*8)(r31)
223 lfd fp21,_UC_FREGS+(21*8)(r31)
224 lfd fp22,_UC_FREGS+(22*8)(r31)
225 lfd fp23,_UC_FREGS+(23*8)(r31)
226 lfd fp24,_UC_FREGS+(24*8)(r31)
227 lfd fp25,_UC_FREGS+(25*8)(r31)
228 lfd fp26,_UC_FREGS+(26*8)(r31)
229 lfd fp27,_UC_FREGS+(27*8)(r31)
230 lfd fp28,_UC_FREGS+(28*8)(r31)
231 lfd fp29,_UC_FREGS+(29*8)(r31)
232 lfd fp30,_UC_FREGS+(30*8)(r31)
233 lfd fp31,_UC_FREGS+(31*8)(r31)
234 #endif /* __CONTEXT_ENABLE_FPRS */
235
236 /* Restore LR and CCR, and set CTR to the NIP value */
237 lwz r3,_UC_GREGS+(PT_LNK*4)(r31)
238 lwz r4,_UC_GREGS+(PT_NIP*4)(r31)
239 lwz r5,_UC_GREGS+(PT_CCR*4)(r31)
240 mtlr r3
241 mtctr r4
242 mtcr r5
243
244 /* Restore the general registers */
245 lwz r1,_UC_GREGS+(PT_R1*4)(r31)
246 lwz r3,_UC_GREGS+(PT_R3*4)(r31)
247 lwz r4,_UC_GREGS+(PT_R4*4)(r31)
248 lwz r5,_UC_GREGS+(PT_R5*4)(r31)
249 lwz r6,_UC_GREGS+(PT_R6*4)(r31)
250 lwz r7,_UC_GREGS+(PT_R7*4)(r31)
251 lwz r8,_UC_GREGS+(PT_R8*4)(r31)
252 lwz r9,_UC_GREGS+(PT_R9*4)(r31)
253 lwz r10,_UC_GREGS+(PT_R10*4)(r31)
254 lwz r11,_UC_GREGS+(PT_R11*4)(r31)
255 lwz r12,_UC_GREGS+(PT_R12*4)(r31)
256 lwz r13,_UC_GREGS+(PT_R13*4)(r31)
257 lwz r14,_UC_GREGS+(PT_R14*4)(r31)
258 lwz r15,_UC_GREGS+(PT_R15*4)(r31)
259 lwz r16,_UC_GREGS+(PT_R16*4)(r31)
260 lwz r17,_UC_GREGS+(PT_R17*4)(r31)
261 lwz r18,_UC_GREGS+(PT_R18*4)(r31)
262 lwz r19,_UC_GREGS+(PT_R19*4)(r31)
263 lwz r20,_UC_GREGS+(PT_R20*4)(r31)
264 lwz r21,_UC_GREGS+(PT_R21*4)(r31)
265 lwz r22,_UC_GREGS+(PT_R22*4)(r31)
266 lwz r23,_UC_GREGS+(PT_R23*4)(r31)
267 lwz r24,_UC_GREGS+(PT_R24*4)(r31)
268 lwz r25,_UC_GREGS+(PT_R25*4)(r31)
269 lwz r26,_UC_GREGS+(PT_R26*4)(r31)
270 lwz r27,_UC_GREGS+(PT_R27*4)(r31)
271 lwz r28,_UC_GREGS+(PT_R28*4)(r31)
272 lwz r29,_UC_GREGS+(PT_R29*4)(r31)
273 lwz r30,_UC_GREGS+(PT_R30*4)(r31)
274 lwz r31,_UC_GREGS+(PT_R31*4)(r31)
275
276 bctr
277
278 3: /* L(error_exit): */
279 lwz r31,12(r1)
280 lwz r0,20(r1)
281 addi r1,r1,16
282 mtlr r0
283 blr
284
285
286 4: /* L(do_sigret): */
287 addi r1,r3,-0xd0
288 li r0,SYS_ify(rt_sigreturn)
289 sc
290 /* NOTREACHED */
291
292 END (__CONTEXT_FUNC_NAME)
293