(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / swapcontext.S
blobc4f0faddc38c050ed69ce14e4833e9dfd6bfd4e0
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.
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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <rtld-global-offsets.h>
22 #include <shlib-compat.h>
24 #define __ASSEMBLY__
25 #include <asm/ptrace.h>
26 #include "ucontext_i.h"
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
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)
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)
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)
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)
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
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
174         stvx  v4,0,r10
175         stvx  v5,0,r9
176         addi  r10,r10,32
177         addi  r9,r9,32
179         stvx  v6,0,r10
180         stvx  v7,0,r9
181         addi  r10,r10,32
182         addi  r9,r9,32
184         stvx  v8,0,r10
185         stvx  v9,0,r9
186         addi  r10,r10,32
187         addi  r9,r9,32
189         stvx  v10,0,r10
190         stvx  v11,0,r9
191         addi  r10,r10,32
192         addi  r9,r9,32
194         stvx  v12,0,r10
195         stvx  v13,0,r9
196         addi  r10,r10,32
197         addi  r9,r9,32
199         stvx  v14,0,r10
200         stvx  v15,0,r9
201         addi  r10,r10,32
202         addi  r9,r9,32
204         stvx  v16,0,r10
205         stvx  v17,0,r9
206         addi  r10,r10,32
207         addi  r9,r9,32
209         stvx  v18,0,r10
210         stvx  v19,0,r9
211         addi  r10,r10,32
212         addi  r9,r9,32
214         stvx  v20,0,r10
215         stvx  v21,0,r9
216         addi  r10,r10,32
217         addi  r9,r9,32
219         stvx  v22,0,r10
220         stvx  v23,0,r9
221         addi  r10,r10,32
222         addi  r9,r9,32
224         stvx  v24,0,r10
225         stvx  v25,0,r9
226         addi  r10,r10,32
227         addi  r9,r9,32
229         stvx  v26,0,r10
230         stvx  v27,0,r9
231         addi  r10,r10,32
232         addi  r9,r9,32
234         stvx  v28,0,r10
235         stvx  v29,0,r9
236         addi  r10,r10,32
237         addi  r9,r9,32
239         mfvscr  v0
240         stvx  v30,0,r10
241         stvx  v31,0,r9
243         stw     r0,0(r8)
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)
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)
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)
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)
300         lvx   v19,r9,r10
301         la    r9,(16)(r10)
303         lvx   v0,0,r10
304         lvx   v1,0,r9
305         addi  r10,r10,32
306         addi  r9,r9,32
308         mtvscr  v19
309         lvx   v2,0,r10
310         lvx   v3,0,r9
311         addi  r10,r10,32
312         addi  r9,r9,32
314         lvx   v4,0,r10
315         lvx   v5,0,r9
316         addi  r10,r10,32
317         addi  r9,r9,32
319         lvx   v6,0,r10
320         lvx   v7,0,r9
321         addi  r10,r10,32
322         addi  r9,r9,32
324         lvx   v8,0,r10
325         lvx   v9,0,r9
326         addi  r10,r10,32
327         addi  r9,r9,32
329         lvx   v10,0,r10
330         lvx   v11,0,r9
331         addi  r10,r10,32
332         addi  r9,r9,32
334         lvx   v12,0,r10
335         lvx   v13,0,r9
336         addi  r10,r10,32
337         addi  r9,r9,32
339         lvx   v14,0,r10
340         lvx   v15,0,r9
341         addi  r10,r10,32
342         addi  r9,r9,32
344         lvx   v16,0,r10
345         lvx   v17,0,r9
346         addi  r10,r10,32
347         addi  r9,r9,32
349         lvx   v18,0,r10
350         lvx   v19,0,r9
351         addi  r10,r10,32
352         addi  r9,r9,32
354         lvx   v20,0,r10
355         lvx   v21,0,r9
356         addi  r10,r10,32
357         addi  r9,r9,32
359         lvx   v22,0,r10
360         lvx   v23,0,r9
361         addi  r10,r10,32
362         addi  r9,r9,32
364         lvx   v24,0,r10
365         lvx   v25,0,r9
366         addi  r10,r10,32
367         addi  r9,r9,32
369         lvx   v26,0,r10
370         lvx   v27,0,r9
371         addi  r10,r10,32
372         addi  r9,r9,32
374         lvx   v28,0,r10
375         lvx   v29,0,r9
376         addi  r10,r10,32
377         addi  r9,r9,32
379         lvx   v30,0,r10
380         lvx   v31,0,r9
381         addi  r10,r10,32
382         addi  r9,r9,32
384         lvx   v10,0,r10
385         lvx   v11,0,r9
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)
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
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)
464         bctr
466 L(error_exit):
467         lwz     r0,_FRAME_LR_SAVE+16(r1)
468         addi    r1,r1,16
469         mtlr    r0
470         blr
472 L(do_sigret):
473         addi    r1,r4,-0xd0
474         li      r0,SYS_ify(rt_sigreturn)
475         sc
476         /* NOTREACHED */
478 END(__swapcontext)
480 versioned_symbol (libc, __swapcontext, swapcontext, GLIBC_2_3_4)
482 #if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
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)
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)
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)
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)
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)
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)
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)
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
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)
679         bctr
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
688 L(novec_do_sigret):
689         addi    r1,r4,-0xd0
690         li      r0,SYS_ify(rt_sigreturn)
691         sc
692         /* NOTREACHED */
694 END(__novec_swapcontext)
695         .previous
697 compat_symbol (libc, __novec_swapcontext, swapcontext, GLIBC_2_3_3)
699 #endif
701 #if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3)
703 #define _ERRNO_H        1
704 #include <bits/errno.h>
706         compat_text_section
707 ENTRY (__swapcontext_stub)
708         li      r3,ENOSYS
709         b       JUMPTARGET(__syscall_error)
710 END (__swapcontext_stub)
711         .previous
713 compat_symbol (libc, __swapcontext_stub, swapcontext, GLIBC_2_1)
715 #endif