]>
Commit | Line | Data |
---|---|---|
aebcf54c | 1 | /* Save current context and 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(__swapcontext) | |
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 | stw r4,_FRAME_PARM_SAVE2(r1) /* new context pointer */ | |
35 | clrrwi r3,r3,4 | |
36 | ||
37 | /* Save the general purpose registers */ | |
38 | stw r0,_UC_GREGS+(PT_R0*4)(r3) | |
39 | mflr r0 | |
40 | stw r2,_UC_GREGS+(PT_R2*4)(r3) | |
41 | stw r4,_UC_GREGS+(PT_R4*4)(r3) | |
42 | /* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers | |
43 | return address. */ | |
44 | stw r0,_UC_GREGS+(PT_LNK*4)(r3) | |
45 | stw r0,_UC_GREGS+(PT_NIP*4)(r3) | |
46 | stw r0,_FRAME_LR_SAVE+16(r1) | |
47 | stw r5,_UC_GREGS+(PT_R5*4)(r3) | |
48 | stw r6,_UC_GREGS+(PT_R6*4)(r3) | |
49 | stw r7,_UC_GREGS+(PT_R7*4)(r3) | |
50 | stw r8,_UC_GREGS+(PT_R8*4)(r3) | |
51 | stw r9,_UC_GREGS+(PT_R9*4)(r3) | |
52 | stw r10,_UC_GREGS+(PT_R10*4)(r3) | |
53 | stw r11,_UC_GREGS+(PT_R11*4)(r3) | |
54 | stw r12,_UC_GREGS+(PT_R12*4)(r3) | |
55 | stw r13,_UC_GREGS+(PT_R13*4)(r3) | |
56 | stw r14,_UC_GREGS+(PT_R14*4)(r3) | |
57 | stw r15,_UC_GREGS+(PT_R15*4)(r3) | |
58 | stw r16,_UC_GREGS+(PT_R16*4)(r3) | |
59 | stw r17,_UC_GREGS+(PT_R17*4)(r3) | |
60 | stw r18,_UC_GREGS+(PT_R18*4)(r3) | |
61 | stw r19,_UC_GREGS+(PT_R19*4)(r3) | |
62 | stw r20,_UC_GREGS+(PT_R20*4)(r3) | |
63 | stw r21,_UC_GREGS+(PT_R21*4)(r3) | |
64 | stw r22,_UC_GREGS+(PT_R22*4)(r3) | |
65 | stw r23,_UC_GREGS+(PT_R23*4)(r3) | |
66 | stw r24,_UC_GREGS+(PT_R24*4)(r3) | |
67 | stw r25,_UC_GREGS+(PT_R25*4)(r3) | |
68 | stw r26,_UC_GREGS+(PT_R26*4)(r3) | |
69 | stw r27,_UC_GREGS+(PT_R27*4)(r3) | |
70 | stw r28,_UC_GREGS+(PT_R28*4)(r3) | |
71 | stw r29,_UC_GREGS+(PT_R29*4)(r3) | |
72 | stw r30,_UC_GREGS+(PT_R30*4)(r3) | |
73 | stw r31,_UC_GREGS+(PT_R31*4)(r3) | |
74 | ||
75 | /* Save the value of R1. We had to push the stack before we | |
76 | had the address of uc_reg_space. So compute the address of | |
77 | the callers stack pointer and save it as R1. */ | |
78 | addi r8,r1,16 | |
79 | li r0,0 | |
80 | /* Save the count, exception and condition registers. */ | |
81 | mfctr r11 | |
82 | mfxer r10 | |
83 | mfcr r9 | |
84 | stw r8,_UC_GREGS+(PT_R1*4)(r3) | |
85 | stw r11,_UC_GREGS+(PT_CTR*4)(r3) | |
86 | stw r10,_UC_GREGS+(PT_XER*4)(r3) | |
87 | stw r9,_UC_GREGS+(PT_CCR*4)(r3) | |
88 | /* Set the return value of getcontext to "success". R3 is the only | |
89 | register whose value is not preserved in the saved context. */ | |
90 | stw r0,_UC_GREGS+(PT_R3*4)(r3) | |
91 | ||
92 | /* Zero fill fields that can't be set in user state. */ | |
93 | stw r0,_UC_GREGS+(PT_MSR*4)(r3) | |
94 | stw r0,_UC_GREGS+(PT_MQ*4)(r3) | |
95 | ||
96 | /* Save the floating-point registers */ | |
97 | stfd fp0,_UC_FREGS+(0*8)(r3) | |
98 | stfd fp1,_UC_FREGS+(1*8)(r3) | |
99 | stfd fp2,_UC_FREGS+(2*8)(r3) | |
100 | stfd fp3,_UC_FREGS+(3*8)(r3) | |
101 | stfd fp4,_UC_FREGS+(4*8)(r3) | |
102 | stfd fp5,_UC_FREGS+(5*8)(r3) | |
103 | stfd fp6,_UC_FREGS+(6*8)(r3) | |
104 | stfd fp7,_UC_FREGS+(7*8)(r3) | |
105 | stfd fp8,_UC_FREGS+(8*8)(r3) | |
106 | stfd fp9,_UC_FREGS+(9*8)(r3) | |
107 | stfd fp10,_UC_FREGS+(10*8)(r3) | |
108 | stfd fp11,_UC_FREGS+(11*8)(r3) | |
109 | stfd fp12,_UC_FREGS+(12*8)(r3) | |
110 | stfd fp13,_UC_FREGS+(13*8)(r3) | |
111 | stfd fp14,_UC_FREGS+(14*8)(r3) | |
112 | stfd fp15,_UC_FREGS+(15*8)(r3) | |
113 | stfd fp16,_UC_FREGS+(16*8)(r3) | |
114 | stfd fp17,_UC_FREGS+(17*8)(r3) | |
115 | stfd fp18,_UC_FREGS+(18*8)(r3) | |
116 | stfd fp19,_UC_FREGS+(19*8)(r3) | |
117 | stfd fp20,_UC_FREGS+(20*8)(r3) | |
118 | stfd fp21,_UC_FREGS+(21*8)(r3) | |
119 | stfd fp22,_UC_FREGS+(22*8)(r3) | |
120 | stfd fp23,_UC_FREGS+(23*8)(r3) | |
121 | stfd fp24,_UC_FREGS+(24*8)(r3) | |
122 | stfd fp25,_UC_FREGS+(25*8)(r3) | |
123 | stfd fp26,_UC_FREGS+(26*8)(r3) | |
124 | stfd fp27,_UC_FREGS+(27*8)(r3) | |
125 | stfd fp28,_UC_FREGS+(28*8)(r3) | |
126 | stfd fp29,_UC_FREGS+(29*8)(r3) | |
127 | mffs fp0 | |
128 | stfd fp30,_UC_FREGS+(30*8)(r3) | |
129 | stfd fp31,_UC_FREGS+(31*8)(r3) | |
130 | stfd fp0,_UC_FREGS+(32*8)(r3) | |
131 | #ifdef PIC | |
132 | mflr r8 | |
133 | bl _GLOBAL_OFFSET_TABLE_@local-4 | |
134 | mflr r7 | |
135 | # ifdef SHARED | |
136 | lwz r7,_rtld_global_ro@got(r7) | |
137 | mtlr r8 | |
138 | lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r7) | |
139 | # else | |
140 | lwz r7,_dl_hwcap@got(r7) | |
141 | mtlr r8 | |
142 | lwz r7,0(r7) | |
143 | # endif | |
144 | #else | |
145 | lis r7,_dl_hwcap@ha | |
146 | lwz r7,_dl_hwcap@l(r7) | |
147 | #endif | |
148 | andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16) | |
149 | ||
150 | la r10,(_UC_VREGS)(r3) | |
151 | la r9,(_UC_VREGS+16)(r3) | |
152 | ||
153 | beq L(no_vec) | |
154 | /* address of the combined VSCR/VSAVE quadword. */ | |
155 | la r8,(_UC_VREGS+512)(r3) | |
156 | ||
157 | /* Save the vector registers */ | |
158 | stvx v0,0,r10 | |
159 | stvx v1,0,r9 | |
160 | addi r10,r10,32 | |
161 | addi r9,r9,32 | |
162 | /* We need to get the Vector Status and Control Register early to avoid | |
163 | store order problems later with the VSAVE register that shares the | |
164 | same quadword. */ | |
165 | mfvscr v0 | |
166 | ||
167 | stvx v2,0,r10 | |
168 | stvx v3,0,r9 | |
169 | addi r10,r10,32 | |
170 | addi r9,r9,32 | |
171 | ||
172 | stvx v0,0,r8 | |
173 | ||
174 | stvx v4,0,r10 | |
175 | stvx v5,0,r9 | |
176 | addi r10,r10,32 | |
177 | addi r9,r9,32 | |
178 | ||
179 | stvx v6,0,r10 | |
180 | stvx v7,0,r9 | |
181 | addi r10,r10,32 | |
182 | addi r9,r9,32 | |
183 | ||
184 | stvx v8,0,r10 | |
185 | stvx v9,0,r9 | |
186 | addi r10,r10,32 | |
187 | addi r9,r9,32 | |
188 | ||
189 | stvx v10,0,r10 | |
190 | stvx v11,0,r9 | |
191 | addi r10,r10,32 | |
192 | addi r9,r9,32 | |
193 | ||
194 | stvx v12,0,r10 | |
195 | stvx v13,0,r9 | |
196 | addi r10,r10,32 | |
197 | addi r9,r9,32 | |
198 | ||
199 | stvx v14,0,r10 | |
200 | stvx v15,0,r9 | |
201 | addi r10,r10,32 | |
202 | addi r9,r9,32 | |
203 | ||
204 | stvx v16,0,r10 | |
205 | stvx v17,0,r9 | |
206 | addi r10,r10,32 | |
207 | addi r9,r9,32 | |
208 | ||
209 | stvx v18,0,r10 | |
210 | stvx v19,0,r9 | |
211 | addi r10,r10,32 | |
212 | addi r9,r9,32 | |
213 | ||
214 | stvx v20,0,r10 | |
215 | stvx v21,0,r9 | |
216 | addi r10,r10,32 | |
217 | addi r9,r9,32 | |
218 | ||
219 | stvx v22,0,r10 | |
220 | stvx v23,0,r9 | |
221 | addi r10,r10,32 | |
222 | addi r9,r9,32 | |
223 | ||
224 | stvx v24,0,r10 | |
225 | stvx v25,0,r9 | |
226 | addi r10,r10,32 | |
227 | addi r9,r9,32 | |
228 | ||
229 | stvx v26,0,r10 | |
230 | stvx v27,0,r9 | |
231 | addi r10,r10,32 | |
232 | addi r9,r9,32 | |
233 | ||
234 | stvx v28,0,r10 | |
235 | stvx v29,0,r9 | |
236 | addi r10,r10,32 | |
237 | addi r9,r9,32 | |
238 | ||
239 | mfvscr v0 | |
240 | stvx v30,0,r10 | |
241 | stvx v31,0,r9 | |
242 | ||
243 | stw r0,0(r8) | |
244 | ||
245 | L(no_vec): | |
246 | /* Restore ucontext (parm1) from stack. */ | |
247 | lwz r12,_FRAME_PARM_SAVE1(r1) | |
248 | li r4,0 | |
249 | stw r3,_UC_REGS_PTR(r12) | |
250 | addi r5,r12,_UC_SIGMASK | |
251 | li r3,SIG_SETMASK | |
252 | bl JUMPTARGET(__sigprocmask) | |
253 | cmpwi r3,0 | |
254 | bne L(error_exit) | |
255 | ||
256 | /* | |
257 | * If the new ucontext refers to the point where we were interrupted | |
258 | * by a signal, we have to use the rt_sigreturn system call to | |
259 | * return to the context so we get both LR and CTR restored. | |
260 | * | |
261 | * Otherwise, the context we are restoring is either just after | |
262 | * a procedure call (getcontext/swapcontext) or at the beginning | |
263 | * of a procedure call (makecontext), so we don't need to restore | |
264 | * r0, xer, ctr. We don't restore r2 since it will be used as | |
265 | * the TLS pointer. | |
266 | */ | |
267 | lwz r4,_FRAME_PARM_SAVE2(r1) | |
268 | lwz r31,_UC_REGS_PTR(r4) | |
269 | lwz r0,_UC_GREGS+(PT_MSR*4)(r31) | |
270 | cmpwi r0,0 | |
271 | bne L(do_sigret) | |
272 | ||
273 | #ifdef PIC | |
274 | mflr r8 | |
275 | bl _GLOBAL_OFFSET_TABLE_@local-4 | |
276 | mflr r7 | |
277 | # ifdef SHARED | |
278 | lwz r7,_rtld_global_ro@got(r7) | |
279 | mtlr r8 | |
280 | lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r7) | |
281 | # else | |
282 | lwz r7,_dl_hwcap@got(r7) | |
283 | mtlr r8 | |
284 | lwz r7,0(r7) | |
285 | # endif | |
0ecb606c | 286 | #else |
a334319f UD |
287 | lis r7,_dl_hwcap@ha |
288 | lwz r7,_dl_hwcap@l(r7) | |
0ecb606c | 289 | #endif |
a334319f UD |
290 | andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16) |
291 | la r10,(_UC_VREGS)(r31) | |
292 | beq L(has_no_vec) | |
293 | ||
294 | lwz r0,(32*16)(r10) | |
295 | li r9,(32*16) | |
296 | cmpwi r0,0 | |
297 | mtspr VRSAVE,r0 | |
298 | beq L(has_no_vec) | |
299 | ||
300 | lvx v19,r9,r10 | |
301 | la r9,(16)(r10) | |
302 | ||
303 | lvx v0,0,r10 | |
304 | lvx v1,0,r9 | |
305 | addi r10,r10,32 | |
306 | addi r9,r9,32 | |
307 | ||
308 | mtvscr v19 | |
309 | lvx v2,0,r10 | |
310 | lvx v3,0,r9 | |
311 | addi r10,r10,32 | |
312 | addi r9,r9,32 | |
313 | ||
314 | lvx v4,0,r10 | |
315 | lvx v5,0,r9 | |
316 | addi r10,r10,32 | |
317 | addi r9,r9,32 | |
318 | ||
319 | lvx v6,0,r10 | |
320 | lvx v7,0,r9 | |
321 | addi r10,r10,32 | |
322 | addi r9,r9,32 | |
323 | ||
324 | lvx v8,0,r10 | |
325 | lvx v9,0,r9 | |
326 | addi r10,r10,32 | |
327 | addi r9,r9,32 | |
328 | ||
329 | lvx v10,0,r10 | |
330 | lvx v11,0,r9 | |
331 | addi r10,r10,32 | |
332 | addi r9,r9,32 | |
333 | ||
334 | lvx v12,0,r10 | |
335 | lvx v13,0,r9 | |
336 | addi r10,r10,32 | |
337 | addi r9,r9,32 | |
338 | ||
339 | lvx v14,0,r10 | |
340 | lvx v15,0,r9 | |
341 | addi r10,r10,32 | |
342 | addi r9,r9,32 | |
343 | ||
344 | lvx v16,0,r10 | |
345 | lvx v17,0,r9 | |
346 | addi r10,r10,32 | |
347 | addi r9,r9,32 | |
348 | ||
349 | lvx v18,0,r10 | |
350 | lvx v19,0,r9 | |
351 | addi r10,r10,32 | |
352 | addi r9,r9,32 | |
353 | ||
354 | lvx v20,0,r10 | |
355 | lvx v21,0,r9 | |
356 | addi r10,r10,32 | |
357 | addi r9,r9,32 | |
358 | ||
359 | lvx v22,0,r10 | |
360 | lvx v23,0,r9 | |
361 | addi r10,r10,32 | |
362 | addi r9,r9,32 | |
363 | ||
364 | lvx v24,0,r10 | |
365 | lvx v25,0,r9 | |
366 | addi r10,r10,32 | |
367 | addi r9,r9,32 | |
368 | ||
369 | lvx v26,0,r10 | |
370 | lvx v27,0,r9 | |
371 | addi r10,r10,32 | |
372 | addi r9,r9,32 | |
373 | ||
374 | lvx v28,0,r10 | |
375 | lvx v29,0,r9 | |
376 | addi r10,r10,32 | |
377 | addi r9,r9,32 | |
378 | ||
379 | lvx v30,0,r10 | |
380 | lvx v31,0,r9 | |
381 | addi r10,r10,32 | |
382 | addi r9,r9,32 | |
383 | ||
384 | lvx v10,0,r10 | |
385 | lvx v11,0,r9 | |
386 | ||
387 | L(has_no_vec): | |
388 | /* Restore the floating-point registers */ | |
389 | lfd fp31,_UC_FREGS+(32*8)(r31) | |
390 | lfd fp0,_UC_FREGS+(0*8)(r31) | |
391 | mtfsf 0xff,fp31 | |
392 | lfd fp1,_UC_FREGS+(1*8)(r31) | |
393 | lfd fp2,_UC_FREGS+(2*8)(r31) | |
394 | lfd fp3,_UC_FREGS+(3*8)(r31) | |
395 | lfd fp4,_UC_FREGS+(4*8)(r31) | |
396 | lfd fp5,_UC_FREGS+(5*8)(r31) | |
397 | lfd fp6,_UC_FREGS+(6*8)(r31) | |
398 | lfd fp7,_UC_FREGS+(7*8)(r31) | |
399 | lfd fp8,_UC_FREGS+(8*8)(r31) | |
400 | lfd fp9,_UC_FREGS+(9*8)(r31) | |
401 | lfd fp10,_UC_FREGS+(10*8)(r31) | |
402 | lfd fp11,_UC_FREGS+(11*8)(r31) | |
403 | lfd fp12,_UC_FREGS+(12*8)(r31) | |
404 | lfd fp13,_UC_FREGS+(13*8)(r31) | |
405 | lfd fp14,_UC_FREGS+(14*8)(r31) | |
406 | lfd fp15,_UC_FREGS+(15*8)(r31) | |
407 | lfd fp16,_UC_FREGS+(16*8)(r31) | |
408 | lfd fp17,_UC_FREGS+(17*8)(r31) | |
409 | lfd fp18,_UC_FREGS+(18*8)(r31) | |
410 | lfd fp19,_UC_FREGS+(19*8)(r31) | |
411 | lfd fp20,_UC_FREGS+(20*8)(r31) | |
412 | lfd fp21,_UC_FREGS+(21*8)(r31) | |
413 | lfd fp22,_UC_FREGS+(22*8)(r31) | |
414 | lfd fp23,_UC_FREGS+(23*8)(r31) | |
415 | lfd fp24,_UC_FREGS+(24*8)(r31) | |
416 | lfd fp25,_UC_FREGS+(25*8)(r31) | |
417 | lfd fp26,_UC_FREGS+(26*8)(r31) | |
418 | lfd fp27,_UC_FREGS+(27*8)(r31) | |
419 | lfd fp28,_UC_FREGS+(28*8)(r31) | |
420 | lfd fp29,_UC_FREGS+(29*8)(r31) | |
421 | lfd fp30,_UC_FREGS+(30*8)(r31) | |
422 | lfd fp31,_UC_FREGS+(31*8)(r31) | |
423 | ||
424 | /* Restore LR and CCR, and set CTR to the NIP value */ | |
425 | lwz r3,_UC_GREGS+(PT_LNK*4)(r31) | |
426 | lwz r4,_UC_GREGS+(PT_NIP*4)(r31) | |
427 | lwz r5,_UC_GREGS+(PT_CCR*4)(r31) | |
428 | mtlr r3 | |
429 | mtctr r4 | |
430 | mtcr r5 | |
431 | ||
432 | /* Restore the general registers */ | |
433 | lwz r1,_UC_GREGS+(PT_R1*4)(r31) | |
434 | lwz r3,_UC_GREGS+(PT_R3*4)(r31) | |
435 | lwz r4,_UC_GREGS+(PT_R4*4)(r31) | |
436 | lwz r5,_UC_GREGS+(PT_R5*4)(r31) | |
437 | lwz r6,_UC_GREGS+(PT_R6*4)(r31) | |
438 | lwz r7,_UC_GREGS+(PT_R7*4)(r31) | |
439 | lwz r8,_UC_GREGS+(PT_R8*4)(r31) | |
440 | lwz r9,_UC_GREGS+(PT_R9*4)(r31) | |
441 | lwz r10,_UC_GREGS+(PT_R10*4)(r31) | |
442 | lwz r11,_UC_GREGS+(PT_R11*4)(r31) | |
443 | lwz r12,_UC_GREGS+(PT_R12*4)(r31) | |
444 | lwz r13,_UC_GREGS+(PT_R13*4)(r31) | |
445 | lwz r14,_UC_GREGS+(PT_R14*4)(r31) | |
446 | lwz r15,_UC_GREGS+(PT_R15*4)(r31) | |
447 | lwz r16,_UC_GREGS+(PT_R16*4)(r31) | |
448 | lwz r17,_UC_GREGS+(PT_R17*4)(r31) | |
449 | lwz r18,_UC_GREGS+(PT_R18*4)(r31) | |
450 | lwz r19,_UC_GREGS+(PT_R19*4)(r31) | |
451 | lwz r20,_UC_GREGS+(PT_R20*4)(r31) | |
452 | lwz r21,_UC_GREGS+(PT_R21*4)(r31) | |
453 | lwz r22,_UC_GREGS+(PT_R22*4)(r31) | |
454 | lwz r23,_UC_GREGS+(PT_R23*4)(r31) | |
455 | lwz r24,_UC_GREGS+(PT_R24*4)(r31) | |
456 | lwz r25,_UC_GREGS+(PT_R25*4)(r31) | |
457 | lwz r26,_UC_GREGS+(PT_R26*4)(r31) | |
458 | lwz r27,_UC_GREGS+(PT_R27*4)(r31) | |
459 | lwz r28,_UC_GREGS+(PT_R28*4)(r31) | |
460 | lwz r29,_UC_GREGS+(PT_R29*4)(r31) | |
461 | lwz r30,_UC_GREGS+(PT_R30*4)(r31) | |
462 | lwz r31,_UC_GREGS+(PT_R31*4)(r31) | |
463 | ||
464 | bctr | |
465 | ||
466 | L(error_exit): | |
467 | lwz r0,_FRAME_LR_SAVE+16(r1) | |
468 | addi r1,r1,16 | |
469 | mtlr r0 | |
470 | blr | |
471 | ||
472 | L(do_sigret): | |
473 | addi r1,r4,-0xd0 | |
474 | li r0,SYS_ify(rt_sigreturn) | |
475 | sc | |
476 | /* NOTREACHED */ | |
477 | ||
478 | END(__swapcontext) | |
5ef6ae4b UD |
479 | |
480 | versioned_symbol (libc, __swapcontext, swapcontext, GLIBC_2_3_4) | |
481 | ||
482 | #if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4) | |
483 | ||
d3a4a571 | 484 | compat_text_section |
a334319f UD |
485 | ENTRY(__novec_swapcontext) |
486 | /* Save the current context */ | |
487 | addi r3,r3,_UC_REG_SPACE | |
488 | stw r3,_UC_REGS_PTR - _UC_REG_SPACE(r3) | |
489 | stw r0,_UC_GREGS+(PT_R0*4)(r3) | |
490 | stw r1,_UC_GREGS+(PT_R1*4)(r3) | |
491 | mflr r0 | |
492 | stwu r1,-16(r1) | |
493 | stw r0,20(r1) | |
494 | stw r31,12(r1) | |
495 | stw r31,_UC_GREGS+(PT_R31*4)(r3) | |
496 | mr r31,r4 /* new context pointer */ | |
497 | stw r0,_UC_GREGS+(PT_LNK*4)(r3) | |
498 | stw r0,_UC_GREGS+(PT_NIP*4)(r3) | |
499 | stw r2,_UC_GREGS+(PT_R2*4)(r3) | |
500 | stw r4,_UC_GREGS+(PT_R4*4)(r3) | |
501 | stw r5,_UC_GREGS+(PT_R5*4)(r3) | |
502 | stw r6,_UC_GREGS+(PT_R6*4)(r3) | |
503 | stw r7,_UC_GREGS+(PT_R7*4)(r3) | |
504 | stw r8,_UC_GREGS+(PT_R8*4)(r3) | |
505 | stw r9,_UC_GREGS+(PT_R9*4)(r3) | |
506 | stw r10,_UC_GREGS+(PT_R10*4)(r3) | |
507 | stw r11,_UC_GREGS+(PT_R11*4)(r3) | |
508 | stw r12,_UC_GREGS+(PT_R12*4)(r3) | |
509 | stw r13,_UC_GREGS+(PT_R13*4)(r3) | |
510 | stw r14,_UC_GREGS+(PT_R14*4)(r3) | |
511 | stw r15,_UC_GREGS+(PT_R15*4)(r3) | |
512 | stw r16,_UC_GREGS+(PT_R16*4)(r3) | |
513 | stw r17,_UC_GREGS+(PT_R17*4)(r3) | |
514 | stw r18,_UC_GREGS+(PT_R18*4)(r3) | |
515 | stw r19,_UC_GREGS+(PT_R19*4)(r3) | |
516 | stw r20,_UC_GREGS+(PT_R20*4)(r3) | |
517 | stw r21,_UC_GREGS+(PT_R21*4)(r3) | |
518 | stw r22,_UC_GREGS+(PT_R22*4)(r3) | |
519 | stw r23,_UC_GREGS+(PT_R23*4)(r3) | |
520 | stw r24,_UC_GREGS+(PT_R24*4)(r3) | |
521 | stw r25,_UC_GREGS+(PT_R25*4)(r3) | |
522 | stw r26,_UC_GREGS+(PT_R26*4)(r3) | |
523 | stw r27,_UC_GREGS+(PT_R27*4)(r3) | |
524 | stw r28,_UC_GREGS+(PT_R28*4)(r3) | |
525 | stw r29,_UC_GREGS+(PT_R29*4)(r3) | |
526 | stw r30,_UC_GREGS+(PT_R30*4)(r3) | |
527 | mfctr r0 | |
528 | stw r0,_UC_GREGS+(PT_CTR*4)(r3) | |
529 | mfxer r0 | |
530 | stw r0,_UC_GREGS+(PT_XER*4)(r3) | |
531 | mfcr r0 | |
532 | stw r0,_UC_GREGS+(PT_CCR*4)(r3) | |
533 | ||
534 | /* Set the return value of swapcontext to "success". R3 is the only | |
535 | register whose value is not preserved in the saved context. */ | |
536 | li r0,0 | |
537 | stw r0,_UC_GREGS+(PT_R3*4)(r3) | |
538 | ||
539 | /* Zero fill fields that can't be set in user state. */ | |
540 | stw r0,_UC_GREGS+(PT_MSR*4)(r3) | |
541 | stw r0,_UC_GREGS+(PT_MQ*4)(r3) | |
542 | ||
543 | /* Save the floating-point registers */ | |
544 | stfd fp0,_UC_FREGS+(0*8)(r3) | |
545 | stfd fp1,_UC_FREGS+(1*8)(r3) | |
546 | stfd fp2,_UC_FREGS+(2*8)(r3) | |
547 | stfd fp3,_UC_FREGS+(3*8)(r3) | |
548 | stfd fp4,_UC_FREGS+(4*8)(r3) | |
549 | stfd fp5,_UC_FREGS+(5*8)(r3) | |
550 | stfd fp6,_UC_FREGS+(6*8)(r3) | |
551 | stfd fp7,_UC_FREGS+(7*8)(r3) | |
552 | stfd fp8,_UC_FREGS+(8*8)(r3) | |
553 | stfd fp9,_UC_FREGS+(9*8)(r3) | |
554 | stfd fp10,_UC_FREGS+(10*8)(r3) | |
555 | stfd fp11,_UC_FREGS+(11*8)(r3) | |
556 | stfd fp12,_UC_FREGS+(12*8)(r3) | |
557 | stfd fp13,_UC_FREGS+(13*8)(r3) | |
558 | stfd fp14,_UC_FREGS+(14*8)(r3) | |
559 | stfd fp15,_UC_FREGS+(15*8)(r3) | |
560 | stfd fp16,_UC_FREGS+(16*8)(r3) | |
561 | stfd fp17,_UC_FREGS+(17*8)(r3) | |
562 | stfd fp18,_UC_FREGS+(18*8)(r3) | |
563 | stfd fp19,_UC_FREGS+(19*8)(r3) | |
564 | stfd fp20,_UC_FREGS+(20*8)(r3) | |
565 | stfd fp21,_UC_FREGS+(21*8)(r3) | |
566 | stfd fp22,_UC_FREGS+(22*8)(r3) | |
567 | stfd fp23,_UC_FREGS+(23*8)(r3) | |
568 | stfd fp24,_UC_FREGS+(24*8)(r3) | |
569 | stfd fp25,_UC_FREGS+(25*8)(r3) | |
570 | stfd fp26,_UC_FREGS+(26*8)(r3) | |
571 | stfd fp27,_UC_FREGS+(27*8)(r3) | |
572 | stfd fp28,_UC_FREGS+(28*8)(r3) | |
573 | stfd fp29,_UC_FREGS+(29*8)(r3) | |
574 | mffs fp0 | |
575 | stfd fp30,_UC_FREGS+(30*8)(r3) | |
576 | stfd fp31,_UC_FREGS+(31*8)(r3) | |
577 | stfd fp0,_UC_FREGS+(32*8)(r3) | |
578 | ||
579 | addi r5,r3,_UC_SIGMASK - _UC_REG_SPACE | |
580 | addi r4,r4,_UC_SIGMASK | |
581 | li r3,SIG_SETMASK | |
582 | bl JUMPTARGET(__sigprocmask) | |
583 | cmpwi r3,0 | |
584 | bne L(novec_error_exit) | |
585 | ||
586 | /* | |
587 | * If the new ucontext refers to the point where we were interrupted | |
588 | * by a signal, we have to use the rt_sigreturn system call to | |
589 | * return to the context so we get both LR and CTR restored. | |
590 | * | |
591 | * Otherwise, the context we are restoring is either just after | |
592 | * a procedure call (getcontext/swapcontext) or at the beginning | |
593 | * of a procedure call (makecontext), so we don't need to restore | |
594 | * r0, xer, ctr. We don't restore r2 since it will be used as | |
595 | * the TLS pointer. | |
596 | */ | |
597 | mr r4,r31 | |
598 | lwz r31,_UC_REGS_PTR(r31) | |
599 | lwz r0,_UC_GREGS+(PT_MSR*4)(r31) | |
600 | cmpwi r0,0 | |
601 | bne L(novec_do_sigret) | |
602 | ||
603 | /* Restore the floating-point registers */ | |
604 | lfd fp31,_UC_FREGS+(32*8)(r31) | |
605 | lfd fp0,_UC_FREGS+(0*8)(r31) | |
606 | mtfsf 0xff,fp31 | |
607 | lfd fp1,_UC_FREGS+(1*8)(r31) | |
608 | lfd fp2,_UC_FREGS+(2*8)(r31) | |
609 | lfd fp3,_UC_FREGS+(3*8)(r31) | |
610 | lfd fp4,_UC_FREGS+(4*8)(r31) | |
611 | lfd fp5,_UC_FREGS+(5*8)(r31) | |
612 | lfd fp6,_UC_FREGS+(6*8)(r31) | |
613 | lfd fp7,_UC_FREGS+(7*8)(r31) | |
614 | lfd fp8,_UC_FREGS+(8*8)(r31) | |
615 | lfd fp9,_UC_FREGS+(9*8)(r31) | |
616 | lfd fp10,_UC_FREGS+(10*8)(r31) | |
617 | lfd fp11,_UC_FREGS+(11*8)(r31) | |
618 | lfd fp12,_UC_FREGS+(12*8)(r31) | |
619 | lfd fp13,_UC_FREGS+(13*8)(r31) | |
620 | lfd fp14,_UC_FREGS+(14*8)(r31) | |
621 | lfd fp15,_UC_FREGS+(15*8)(r31) | |
622 | lfd fp16,_UC_FREGS+(16*8)(r31) | |
623 | lfd fp17,_UC_FREGS+(17*8)(r31) | |
624 | lfd fp18,_UC_FREGS+(18*8)(r31) | |
625 | lfd fp19,_UC_FREGS+(19*8)(r31) | |
626 | lfd fp20,_UC_FREGS+(20*8)(r31) | |
627 | lfd fp21,_UC_FREGS+(21*8)(r31) | |
628 | lfd fp22,_UC_FREGS+(22*8)(r31) | |
629 | lfd fp23,_UC_FREGS+(23*8)(r31) | |
630 | lfd fp24,_UC_FREGS+(24*8)(r31) | |
631 | lfd fp25,_UC_FREGS+(25*8)(r31) | |
632 | lfd fp26,_UC_FREGS+(26*8)(r31) | |
633 | lfd fp27,_UC_FREGS+(27*8)(r31) | |
634 | lfd fp28,_UC_FREGS+(28*8)(r31) | |
635 | lfd fp29,_UC_FREGS+(29*8)(r31) | |
636 | lfd fp30,_UC_FREGS+(30*8)(r31) | |
637 | lfd fp31,_UC_FREGS+(31*8)(r31) | |
638 | ||
639 | /* Restore LR and CCR, and set CTR to the NIP value */ | |
640 | lwz r3,_UC_GREGS+(PT_LNK*4)(r31) | |
641 | lwz r4,_UC_GREGS+(PT_NIP*4)(r31) | |
642 | lwz r5,_UC_GREGS+(PT_CCR*4)(r31) | |
643 | mtlr r3 | |
644 | mtctr r4 | |
645 | mtcr r5 | |
646 | ||
647 | /* Restore the general registers */ | |
648 | lwz r1,_UC_GREGS+(PT_R1*4)(r31) | |
649 | lwz r3,_UC_GREGS+(PT_R3*4)(r31) | |
650 | lwz r4,_UC_GREGS+(PT_R4*4)(r31) | |
651 | lwz r5,_UC_GREGS+(PT_R5*4)(r31) | |
652 | lwz r6,_UC_GREGS+(PT_R6*4)(r31) | |
653 | lwz r7,_UC_GREGS+(PT_R7*4)(r31) | |
654 | lwz r8,_UC_GREGS+(PT_R8*4)(r31) | |
655 | lwz r9,_UC_GREGS+(PT_R9*4)(r31) | |
656 | lwz r10,_UC_GREGS+(PT_R10*4)(r31) | |
657 | lwz r11,_UC_GREGS+(PT_R11*4)(r31) | |
658 | lwz r12,_UC_GREGS+(PT_R12*4)(r31) | |
659 | lwz r13,_UC_GREGS+(PT_R13*4)(r31) | |
660 | lwz r14,_UC_GREGS+(PT_R14*4)(r31) | |
661 | lwz r15,_UC_GREGS+(PT_R15*4)(r31) | |
662 | lwz r16,_UC_GREGS+(PT_R16*4)(r31) | |
663 | lwz r17,_UC_GREGS+(PT_R17*4)(r31) | |
664 | lwz r18,_UC_GREGS+(PT_R18*4)(r31) | |
665 | lwz r19,_UC_GREGS+(PT_R19*4)(r31) | |
666 | lwz r20,_UC_GREGS+(PT_R20*4)(r31) | |
667 | lwz r21,_UC_GREGS+(PT_R21*4)(r31) | |
668 | lwz r22,_UC_GREGS+(PT_R22*4)(r31) | |
669 | lwz r23,_UC_GREGS+(PT_R23*4)(r31) | |
670 | lwz r24,_UC_GREGS+(PT_R24*4)(r31) | |
671 | lwz r25,_UC_GREGS+(PT_R25*4)(r31) | |
672 | lwz r26,_UC_GREGS+(PT_R26*4)(r31) | |
673 | lwz r27,_UC_GREGS+(PT_R27*4)(r31) | |
674 | lwz r28,_UC_GREGS+(PT_R28*4)(r31) | |
675 | lwz r29,_UC_GREGS+(PT_R29*4)(r31) | |
676 | lwz r30,_UC_GREGS+(PT_R30*4)(r31) | |
677 | lwz r31,_UC_GREGS+(PT_R31*4)(r31) | |
678 | ||
679 | bctr | |
680 | ||
681 | L(novec_error_exit): | |
682 | lwz r31,12(r1) | |
683 | lwz r0,20(r1) | |
684 | addi r1,r1,16 | |
685 | mtlr r0 | |
686 | blr | |
aebcf54c | 687 | |
a334319f UD |
688 | L(novec_do_sigret): |
689 | addi r1,r4,-0xd0 | |
690 | li r0,SYS_ify(rt_sigreturn) | |
691 | sc | |
692 | /* NOTREACHED */ | |
aebcf54c | 693 | |
a334319f | 694 | END(__novec_swapcontext) |
d3a4a571 | 695 | .previous |
5ef6ae4b UD |
696 | |
697 | compat_symbol (libc, __novec_swapcontext, swapcontext, GLIBC_2_3_3) | |
aebcf54c | 698 | |
5ef6ae4b | 699 | #endif |
54ee14b3 UD |
700 | |
701 | #if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3) | |
702 | ||
a334319f UD |
703 | #define _ERRNO_H 1 |
704 | #include <bits/errno.h> | |
54ee14b3 | 705 | |
d3a4a571 | 706 | compat_text_section |
54ee14b3 UD |
707 | ENTRY (__swapcontext_stub) |
708 | li r3,ENOSYS | |
a334319f | 709 | b JUMPTARGET(__syscall_error) |
d3a4a571 UD |
710 | END (__swapcontext_stub) |
711 | .previous | |
54ee14b3 UD |
712 | |
713 | compat_symbol (libc, __swapcontext_stub, swapcontext, GLIBC_2_1) | |
714 | ||
715 | #endif |