]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext.S
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / swapcontext.S
1 /* Save current context and jump to a new context.
2 Copyright (C) 2002, 2004 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., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20 #include <sysdep.h>
21 #include <rtld-global-offsets.h>
22 #include <shlib-compat.h>
23
24 #define __ASSEMBLY__
25 #include <asm/ptrace.h>
26 #include "ucontext_i.h"
27
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
286 #else
287 lis r7,_dl_hwcap@ha
288 lwz r7,_dl_hwcap@l(r7)
289 #endif
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)
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
484 compat_text_section
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
687
688 L(novec_do_sigret):
689 addi r1,r4,-0xd0
690 li r0,SYS_ify(rt_sigreturn)
691 sc
692 /* NOTREACHED */
693
694 END(__novec_swapcontext)
695 .previous
696
697 compat_symbol (libc, __novec_swapcontext, swapcontext, GLIBC_2_3_3)
698
699 #endif
700
701 #if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3)
702
703 #define _ERRNO_H 1
704 #include <bits/errno.h>
705
706 compat_text_section
707 ENTRY (__swapcontext_stub)
708 li r3,ENOSYS
709 b JUMPTARGET(__syscall_error)
710 END (__swapcontext_stub)
711 .previous
712
713 compat_symbol (libc, __swapcontext_stub, swapcontext, GLIBC_2_1)
714
715 #endif