]>
Commit | Line | Data |
---|---|---|
aebcf54c | 1 | /* Jump to a new context. |
a334319f | 2 | Copyright (C) 2002, 2004 Free Software Foundation, Inc. |
aebcf54c UD |
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 | |
a334319f UD |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
18 | 02111-1307 USA. */ | |
aebcf54c UD |
19 | |
20 | #include <sysdep.h> | |
5ef6ae4b | 21 | #include <rtld-global-offsets.h> |
54ee14b3 | 22 | #include <shlib-compat.h> |
aebcf54c UD |
23 | |
24 | #define __ASSEMBLY__ | |
25 | #include <asm/ptrace.h> | |
26 | #include "ucontext_i.h" | |
27 | ||
a334319f UD |
28 | .machine "altivec" |
29 | ENTRY(__setcontext) | |
30 | mflr r0 | |
31 | stwu r1,-16(r1) | |
32 | stw r0,20(r1) | |
33 | stw r31,12(r1) | |
34 | lwz r31,_UC_REGS_PTR(r3) | |
35 | ||
36 | /* | |
37 | * If this ucontext refers to the point where we were interrupted | |
38 | * by a signal, we have to use the rt_sigreturn system call to | |
39 | * return to the context so we get both LR and CTR restored. | |
40 | * | |
41 | * Otherwise, the context we are restoring is either just after | |
42 | * a procedure call (getcontext/swapcontext) or at the beginning | |
43 | * of a procedure call (makecontext), so we don't need to restore | |
44 | * r0, xer, ctr. We don't restore r2 since it will be used as | |
45 | * the TLS pointer. | |
46 | */ | |
47 | lwz r0,_UC_GREGS+(PT_MSR*4)(r31) | |
48 | cmpwi r0,0 | |
49 | bne L(do_sigret) | |
50 | ||
51 | /* Restore the signal mask */ | |
52 | li r5,0 | |
53 | addi r4,r3,_UC_SIGMASK | |
54 | li r3,SIG_SETMASK | |
55 | bl JUMPTARGET(__sigprocmask) | |
56 | cmpwi r3,0 | |
57 | bne L(error_exit) | |
58 | ||
59 | #ifdef PIC | |
60 | mflr r8 | |
61 | bl _GLOBAL_OFFSET_TABLE_@local-4 | |
62 | mflr r7 | |
63 | # ifdef SHARED | |
64 | lwz r7,_rtld_global_ro@got(r7) | |
65 | mtlr r8 | |
66 | lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r7) | |
67 | # else | |
68 | lwz r7,_dl_hwcap@got(r7) | |
69 | mtlr r8 | |
70 | lwz r7,0(r7) | |
71 | # endif | |
5ef6ae4b | 72 | #else |
a334319f UD |
73 | lis r7,_dl_hwcap@ha |
74 | lwz r7,_dl_hwcap@l(r7) | |
5ef6ae4b | 75 | #endif |
a334319f UD |
76 | andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16) |
77 | la r10,(_UC_VREGS)(r31) | |
78 | beq L(has_no_vec) | |
79 | ||
80 | lwz r0,(32*16)(r10) | |
81 | li r9,(32*16) | |
82 | cmpwi r0,0 | |
83 | mtspr VRSAVE,r0 | |
84 | beq L(has_no_vec) | |
85 | ||
86 | lvx v19,r9,r10 | |
87 | la r9,(16)(r10) | |
88 | ||
89 | lvx v0,0,r10 | |
90 | lvx v1,0,r9 | |
91 | addi r10,r10,32 | |
92 | addi r9,r9,32 | |
93 | ||
94 | mtvscr v19 | |
95 | lvx v2,0,r10 | |
96 | lvx v3,0,r9 | |
97 | addi r10,r10,32 | |
98 | addi r9,r9,32 | |
99 | ||
100 | lvx v4,0,r10 | |
101 | lvx v5,0,r9 | |
102 | addi r10,r10,32 | |
103 | addi r9,r9,32 | |
104 | ||
105 | lvx v6,0,r10 | |
106 | lvx v7,0,r9 | |
107 | addi r10,r10,32 | |
108 | addi r9,r9,32 | |
109 | ||
110 | lvx v8,0,r10 | |
111 | lvx v9,0,r9 | |
112 | addi r10,r10,32 | |
113 | addi r9,r9,32 | |
114 | ||
115 | lvx v10,0,r10 | |
116 | lvx v11,0,r9 | |
117 | addi r10,r10,32 | |
118 | addi r9,r9,32 | |
119 | ||
120 | lvx v12,0,r10 | |
121 | lvx v13,0,r9 | |
122 | addi r10,r10,32 | |
123 | addi r9,r9,32 | |
124 | ||
125 | lvx v14,0,r10 | |
126 | lvx v15,0,r9 | |
127 | addi r10,r10,32 | |
128 | addi r9,r9,32 | |
129 | ||
130 | lvx v16,0,r10 | |
131 | lvx v17,0,r9 | |
132 | addi r10,r10,32 | |
133 | addi r9,r9,32 | |
134 | ||
135 | lvx v18,0,r10 | |
136 | lvx v19,0,r9 | |
137 | addi r10,r10,32 | |
138 | addi r9,r9,32 | |
139 | ||
140 | lvx v20,0,r10 | |
141 | lvx v21,0,r9 | |
142 | addi r10,r10,32 | |
143 | addi r9,r9,32 | |
144 | ||
145 | lvx v22,0,r10 | |
146 | lvx v23,0,r9 | |
147 | addi r10,r10,32 | |
148 | addi r9,r9,32 | |
149 | ||
150 | lvx v24,0,r10 | |
151 | lvx v25,0,r9 | |
152 | addi r10,r10,32 | |
153 | addi r9,r9,32 | |
154 | ||
155 | lvx v26,0,r10 | |
156 | lvx v27,0,r9 | |
157 | addi r10,r10,32 | |
158 | addi r9,r9,32 | |
159 | ||
160 | lvx v28,0,r10 | |
161 | lvx v29,0,r9 | |
162 | addi r10,r10,32 | |
163 | addi r9,r9,32 | |
164 | ||
165 | lvx v30,0,r10 | |
166 | lvx v31,0,r9 | |
167 | addi r10,r10,32 | |
168 | addi r9,r9,32 | |
169 | ||
170 | lvx v10,0,r10 | |
171 | lvx v11,0,r9 | |
172 | ||
173 | L(has_no_vec): | |
174 | /* Restore the floating-point registers */ | |
175 | lfd fp31,_UC_FREGS+(32*8)(r31) | |
176 | lfd fp0,_UC_FREGS+(0*8)(r31) | |
177 | mtfsf 0xff,fp31 | |
178 | lfd fp1,_UC_FREGS+(1*8)(r31) | |
179 | lfd fp2,_UC_FREGS+(2*8)(r31) | |
180 | lfd fp3,_UC_FREGS+(3*8)(r31) | |
181 | lfd fp4,_UC_FREGS+(4*8)(r31) | |
182 | lfd fp5,_UC_FREGS+(5*8)(r31) | |
183 | lfd fp6,_UC_FREGS+(6*8)(r31) | |
184 | lfd fp7,_UC_FREGS+(7*8)(r31) | |
185 | lfd fp8,_UC_FREGS+(8*8)(r31) | |
186 | lfd fp9,_UC_FREGS+(9*8)(r31) | |
187 | lfd fp10,_UC_FREGS+(10*8)(r31) | |
188 | lfd fp11,_UC_FREGS+(11*8)(r31) | |
189 | lfd fp12,_UC_FREGS+(12*8)(r31) | |
190 | lfd fp13,_UC_FREGS+(13*8)(r31) | |
191 | lfd fp14,_UC_FREGS+(14*8)(r31) | |
192 | lfd fp15,_UC_FREGS+(15*8)(r31) | |
193 | lfd fp16,_UC_FREGS+(16*8)(r31) | |
194 | lfd fp17,_UC_FREGS+(17*8)(r31) | |
195 | lfd fp18,_UC_FREGS+(18*8)(r31) | |
196 | lfd fp19,_UC_FREGS+(19*8)(r31) | |
197 | lfd fp20,_UC_FREGS+(20*8)(r31) | |
198 | lfd fp21,_UC_FREGS+(21*8)(r31) | |
199 | lfd fp22,_UC_FREGS+(22*8)(r31) | |
200 | lfd fp23,_UC_FREGS+(23*8)(r31) | |
201 | lfd fp24,_UC_FREGS+(24*8)(r31) | |
202 | lfd fp25,_UC_FREGS+(25*8)(r31) | |
203 | lfd fp26,_UC_FREGS+(26*8)(r31) | |
204 | lfd fp27,_UC_FREGS+(27*8)(r31) | |
205 | lfd fp28,_UC_FREGS+(28*8)(r31) | |
206 | lfd fp29,_UC_FREGS+(29*8)(r31) | |
207 | lfd fp30,_UC_FREGS+(30*8)(r31) | |
208 | lfd fp31,_UC_FREGS+(31*8)(r31) | |
209 | ||
210 | /* Restore LR and CCR, and set CTR to the NIP value */ | |
211 | lwz r3,_UC_GREGS+(PT_LNK*4)(r31) | |
212 | lwz r4,_UC_GREGS+(PT_NIP*4)(r31) | |
213 | lwz r5,_UC_GREGS+(PT_CCR*4)(r31) | |
214 | mtlr r3 | |
215 | mtctr r4 | |
216 | mtcr r5 | |
217 | ||
218 | /* Restore the general registers */ | |
219 | lwz r1,_UC_GREGS+(PT_R1*4)(r31) | |
220 | lwz r3,_UC_GREGS+(PT_R3*4)(r31) | |
221 | lwz r4,_UC_GREGS+(PT_R4*4)(r31) | |
222 | lwz r5,_UC_GREGS+(PT_R5*4)(r31) | |
223 | lwz r6,_UC_GREGS+(PT_R6*4)(r31) | |
224 | lwz r7,_UC_GREGS+(PT_R7*4)(r31) | |
225 | lwz r8,_UC_GREGS+(PT_R8*4)(r31) | |
226 | lwz r9,_UC_GREGS+(PT_R9*4)(r31) | |
227 | lwz r10,_UC_GREGS+(PT_R10*4)(r31) | |
228 | lwz r11,_UC_GREGS+(PT_R11*4)(r31) | |
229 | lwz r12,_UC_GREGS+(PT_R12*4)(r31) | |
230 | lwz r13,_UC_GREGS+(PT_R13*4)(r31) | |
231 | lwz r14,_UC_GREGS+(PT_R14*4)(r31) | |
232 | lwz r15,_UC_GREGS+(PT_R15*4)(r31) | |
233 | lwz r16,_UC_GREGS+(PT_R16*4)(r31) | |
234 | lwz r17,_UC_GREGS+(PT_R17*4)(r31) | |
235 | lwz r18,_UC_GREGS+(PT_R18*4)(r31) | |
236 | lwz r19,_UC_GREGS+(PT_R19*4)(r31) | |
237 | lwz r20,_UC_GREGS+(PT_R20*4)(r31) | |
238 | lwz r21,_UC_GREGS+(PT_R21*4)(r31) | |
239 | lwz r22,_UC_GREGS+(PT_R22*4)(r31) | |
240 | lwz r23,_UC_GREGS+(PT_R23*4)(r31) | |
241 | lwz r24,_UC_GREGS+(PT_R24*4)(r31) | |
242 | lwz r25,_UC_GREGS+(PT_R25*4)(r31) | |
243 | lwz r26,_UC_GREGS+(PT_R26*4)(r31) | |
244 | lwz r27,_UC_GREGS+(PT_R27*4)(r31) | |
245 | lwz r28,_UC_GREGS+(PT_R28*4)(r31) | |
246 | lwz r29,_UC_GREGS+(PT_R29*4)(r31) | |
247 | lwz r30,_UC_GREGS+(PT_R30*4)(r31) | |
248 | lwz r31,_UC_GREGS+(PT_R31*4)(r31) | |
249 | ||
250 | bctr | |
251 | ||
252 | L(error_exit): | |
253 | lwz r31,12(r1) | |
254 | lwz r0,20(r1) | |
255 | addi r1,r1,16 | |
256 | mtlr r0 | |
257 | blr | |
258 | ||
259 | L(do_sigret): | |
260 | addi r1,r3,-0xd0 | |
261 | li r0,SYS_ify(rt_sigreturn) | |
262 | sc | |
263 | /* NOTREACHED */ | |
264 | ||
265 | END (__setcontext) | |
aebcf54c | 266 | |
5ef6ae4b UD |
267 | versioned_symbol (libc, __setcontext, setcontext, GLIBC_2_3_4) |
268 | ||
269 | #if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4) | |
270 | ||
d3a4a571 | 271 | compat_text_section |
a334319f UD |
272 | ENTRY(__novec_setcontext) |
273 | mflr r0 | |
274 | stwu r1,-16(r1) | |
275 | stw r0,20(r1) | |
276 | stw r31,12(r1) | |
277 | lwz r31,_UC_REGS_PTR(r3) | |
278 | ||
279 | /* | |
280 | * If this ucontext refers to the point where we were interrupted | |
281 | * by a signal, we have to use the rt_sigreturn system call to | |
282 | * return to the context so we get both LR and CTR restored. | |
283 | * | |
284 | * Otherwise, the context we are restoring is either just after | |
285 | * a procedure call (getcontext/swapcontext) or at the beginning | |
286 | * of a procedure call (makecontext), so we don't need to restore | |
287 | * r0, xer, ctr. We don't restore r2 since it will be used as | |
288 | * the TLS pointer. | |
289 | */ | |
290 | lwz r0,_UC_GREGS+(PT_MSR*4)(r31) | |
291 | cmpwi r0,0 | |
292 | bne L(novec_do_sigret) | |
293 | ||
294 | /* Restore the signal mask */ | |
295 | li r5,0 | |
296 | addi r4,r3,_UC_SIGMASK | |
297 | li r3,SIG_SETMASK | |
298 | bl JUMPTARGET(__sigprocmask) | |
299 | cmpwi r3,0 | |
300 | bne L(novec_error_exit) | |
301 | ||
302 | /* Restore the floating-point registers */ | |
303 | lfd fp31,_UC_FREGS+(32*8)(r31) | |
304 | lfd fp0,_UC_FREGS+(0*8)(r31) | |
305 | mtfsf 0xff,fp31 | |
306 | lfd fp1,_UC_FREGS+(1*8)(r31) | |
307 | lfd fp2,_UC_FREGS+(2*8)(r31) | |
308 | lfd fp3,_UC_FREGS+(3*8)(r31) | |
309 | lfd fp4,_UC_FREGS+(4*8)(r31) | |
310 | lfd fp5,_UC_FREGS+(5*8)(r31) | |
311 | lfd fp6,_UC_FREGS+(6*8)(r31) | |
312 | lfd fp7,_UC_FREGS+(7*8)(r31) | |
313 | lfd fp8,_UC_FREGS+(8*8)(r31) | |
314 | lfd fp9,_UC_FREGS+(9*8)(r31) | |
315 | lfd fp10,_UC_FREGS+(10*8)(r31) | |
316 | lfd fp11,_UC_FREGS+(11*8)(r31) | |
317 | lfd fp12,_UC_FREGS+(12*8)(r31) | |
318 | lfd fp13,_UC_FREGS+(13*8)(r31) | |
319 | lfd fp14,_UC_FREGS+(14*8)(r31) | |
320 | lfd fp15,_UC_FREGS+(15*8)(r31) | |
321 | lfd fp16,_UC_FREGS+(16*8)(r31) | |
322 | lfd fp17,_UC_FREGS+(17*8)(r31) | |
323 | lfd fp18,_UC_FREGS+(18*8)(r31) | |
324 | lfd fp19,_UC_FREGS+(19*8)(r31) | |
325 | lfd fp20,_UC_FREGS+(20*8)(r31) | |
326 | lfd fp21,_UC_FREGS+(21*8)(r31) | |
327 | lfd fp22,_UC_FREGS+(22*8)(r31) | |
328 | lfd fp23,_UC_FREGS+(23*8)(r31) | |
329 | lfd fp24,_UC_FREGS+(24*8)(r31) | |
330 | lfd fp25,_UC_FREGS+(25*8)(r31) | |
331 | lfd fp26,_UC_FREGS+(26*8)(r31) | |
332 | lfd fp27,_UC_FREGS+(27*8)(r31) | |
333 | lfd fp28,_UC_FREGS+(28*8)(r31) | |
334 | lfd fp29,_UC_FREGS+(29*8)(r31) | |
335 | lfd fp30,_UC_FREGS+(30*8)(r31) | |
336 | lfd fp31,_UC_FREGS+(31*8)(r31) | |
337 | ||
338 | /* Restore LR and CCR, and set CTR to the NIP value */ | |
339 | lwz r3,_UC_GREGS+(PT_LNK*4)(r31) | |
340 | lwz r4,_UC_GREGS+(PT_NIP*4)(r31) | |
341 | lwz r5,_UC_GREGS+(PT_CCR*4)(r31) | |
342 | mtlr r3 | |
343 | mtctr r4 | |
344 | mtcr r5 | |
345 | ||
346 | /* Restore the general registers */ | |
347 | lwz r1,_UC_GREGS+(PT_R1*4)(r31) | |
348 | lwz r3,_UC_GREGS+(PT_R3*4)(r31) | |
349 | lwz r4,_UC_GREGS+(PT_R4*4)(r31) | |
350 | lwz r5,_UC_GREGS+(PT_R5*4)(r31) | |
351 | lwz r6,_UC_GREGS+(PT_R6*4)(r31) | |
352 | lwz r7,_UC_GREGS+(PT_R7*4)(r31) | |
353 | lwz r8,_UC_GREGS+(PT_R8*4)(r31) | |
354 | lwz r9,_UC_GREGS+(PT_R9*4)(r31) | |
355 | lwz r10,_UC_GREGS+(PT_R10*4)(r31) | |
356 | lwz r11,_UC_GREGS+(PT_R11*4)(r31) | |
357 | lwz r12,_UC_GREGS+(PT_R12*4)(r31) | |
358 | lwz r13,_UC_GREGS+(PT_R13*4)(r31) | |
359 | lwz r14,_UC_GREGS+(PT_R14*4)(r31) | |
360 | lwz r15,_UC_GREGS+(PT_R15*4)(r31) | |
361 | lwz r16,_UC_GREGS+(PT_R16*4)(r31) | |
362 | lwz r17,_UC_GREGS+(PT_R17*4)(r31) | |
363 | lwz r18,_UC_GREGS+(PT_R18*4)(r31) | |
364 | lwz r19,_UC_GREGS+(PT_R19*4)(r31) | |
365 | lwz r20,_UC_GREGS+(PT_R20*4)(r31) | |
366 | lwz r21,_UC_GREGS+(PT_R21*4)(r31) | |
367 | lwz r22,_UC_GREGS+(PT_R22*4)(r31) | |
368 | lwz r23,_UC_GREGS+(PT_R23*4)(r31) | |
369 | lwz r24,_UC_GREGS+(PT_R24*4)(r31) | |
370 | lwz r25,_UC_GREGS+(PT_R25*4)(r31) | |
371 | lwz r26,_UC_GREGS+(PT_R26*4)(r31) | |
372 | lwz r27,_UC_GREGS+(PT_R27*4)(r31) | |
373 | lwz r28,_UC_GREGS+(PT_R28*4)(r31) | |
374 | lwz r29,_UC_GREGS+(PT_R29*4)(r31) | |
375 | lwz r30,_UC_GREGS+(PT_R30*4)(r31) | |
376 | lwz r31,_UC_GREGS+(PT_R31*4)(r31) | |
377 | ||
378 | bctr | |
379 | ||
380 | L(novec_error_exit): | |
381 | lwz r31,12(r1) | |
382 | lwz r0,20(r1) | |
383 | addi r1,r1,16 | |
384 | mtlr r0 | |
385 | blr | |
ef690add | 386 | |
a334319f UD |
387 | L(novec_do_sigret): |
388 | addi r1,r3,-0xd0 | |
389 | li r0,SYS_ify(rt_sigreturn) | |
390 | sc | |
391 | /* NOTREACHED */ | |
5ef6ae4b | 392 | |
a334319f | 393 | END (__novec_setcontext) |
d3a4a571 | 394 | .previous |
5ef6ae4b UD |
395 | |
396 | compat_symbol (libc, __novec_setcontext, setcontext, GLIBC_2_3_3) | |
397 | ||
398 | #endif | |
54ee14b3 | 399 | |
f89d6892 | 400 | #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_3) |
54ee14b3 | 401 | |
a334319f UD |
402 | #define _ERRNO_H 1 |
403 | #include <bits/errno.h> | |
54ee14b3 | 404 | |
d3a4a571 | 405 | compat_text_section |
54ee14b3 UD |
406 | ENTRY (__setcontext_stub) |
407 | li r3,ENOSYS | |
a334319f | 408 | b JUMPTARGET(__syscall_error) |
d3a4a571 UD |
409 | END (__setcontext_stub) |
410 | .previous | |
54ee14b3 | 411 | |
f89d6892 | 412 | compat_symbol (libc, __setcontext_stub, setcontext, GLIBC_2_0) |
54ee14b3 UD |
413 | |
414 | #endif |