2.9
[glibc/nacl-glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / swapcontext-common.S
blob0c7b945ed264b6ed761e9f4b08ca1889a61ecbc6
1 /* Save current context and jump to a new context.
2    Copyright (C) 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston MA
18    02110-1301 USA.  */
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.  */
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
38 #ifdef __CONTEXT_ENABLE_VRS
39         .machine        "altivec"
40 #endif
41 ENTRY(__CONTEXT_FUNC_NAME)
42         stwu    r1,-16(r1)
43         cfi_adjust_cfa_offset (16)
44 /* Insure that the _UC_REGS start on a quadword boundary.  */
45         stw     r3,_FRAME_PARM_SAVE1(r1)
46         addi    r3,r3,_UC_REG_SPACE+12
47         stw     r4,_FRAME_PARM_SAVE2(r1)        /* new context pointer */
48         clrrwi  r3,r3,4
50 /* Save the general purpose registers */
51         stw     r0,_UC_GREGS+(PT_R0*4)(r3)
52         mflr    r0
53         stw     r2,_UC_GREGS+(PT_R2*4)(r3)
54         stw     r4,_UC_GREGS+(PT_R4*4)(r3)                      
55 /* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers
56    return address.  */
57         stw     r0,_UC_GREGS+(PT_LNK*4)(r3)
58         stw     r0,_UC_GREGS+(PT_NIP*4)(r3)
59         stw     r0,_FRAME_LR_SAVE+16(r1)
60         cfi_offset (lr, _FRAME_LR_SAVE)
61         stw     r5,_UC_GREGS+(PT_R5*4)(r3)
62         stw     r6,_UC_GREGS+(PT_R6*4)(r3)
63         stw     r7,_UC_GREGS+(PT_R7*4)(r3)
64         stw     r8,_UC_GREGS+(PT_R8*4)(r3)
65         stw     r9,_UC_GREGS+(PT_R9*4)(r3)
66         stw     r10,_UC_GREGS+(PT_R10*4)(r3)
67         stw     r11,_UC_GREGS+(PT_R11*4)(r3)
68         stw     r12,_UC_GREGS+(PT_R12*4)(r3)
69         stw     r13,_UC_GREGS+(PT_R13*4)(r3)
70         stw     r14,_UC_GREGS+(PT_R14*4)(r3)
71         stw     r15,_UC_GREGS+(PT_R15*4)(r3)
72         stw     r16,_UC_GREGS+(PT_R16*4)(r3)
73         stw     r17,_UC_GREGS+(PT_R17*4)(r3)
74         stw     r18,_UC_GREGS+(PT_R18*4)(r3)
75         stw     r19,_UC_GREGS+(PT_R19*4)(r3)
76         stw     r20,_UC_GREGS+(PT_R20*4)(r3)
77         stw     r21,_UC_GREGS+(PT_R21*4)(r3)
78         stw     r22,_UC_GREGS+(PT_R22*4)(r3)
79         stw     r23,_UC_GREGS+(PT_R23*4)(r3)
80         stw     r24,_UC_GREGS+(PT_R24*4)(r3)
81         stw     r25,_UC_GREGS+(PT_R25*4)(r3)
82         stw     r26,_UC_GREGS+(PT_R26*4)(r3)
83         stw     r27,_UC_GREGS+(PT_R27*4)(r3)
84         stw     r28,_UC_GREGS+(PT_R28*4)(r3)
85         stw     r29,_UC_GREGS+(PT_R29*4)(r3)
86         stw     r30,_UC_GREGS+(PT_R30*4)(r3)
87         stw     r31,_UC_GREGS+(PT_R31*4)(r3)
88         
89 /* Save the value of R1.  We had to push the stack before we
90    had the address of uc_reg_space.  So compute the address of
91    the callers stack pointer and save it as R1.  */
92         addi    r8,r1,16
93         li      r0,0
94 /* Save the count, exception and condition registers.  */
95         mfctr   r11
96         mfxer   r10
97         mfcr    r9
98         stw     r8,_UC_GREGS+(PT_R1*4)(r3)
99         stw     r11,_UC_GREGS+(PT_CTR*4)(r3)
100         stw     r10,_UC_GREGS+(PT_XER*4)(r3)
101         stw     r9,_UC_GREGS+(PT_CCR*4)(r3)
102 /* Set the return value of getcontext to "success".  R3 is the only
103    register whose value is not preserved in the saved context.  */
104         stw     r0,_UC_GREGS+(PT_R3*4)(r3)
106         /* Zero fill fields that can't be set in user state. */
107         stw     r0,_UC_GREGS+(PT_MSR*4)(r3)
108         stw     r0,_UC_GREGS+(PT_MQ*4)(r3)
110 #ifdef __CONTEXT_ENABLE_FPRS
111         /* Save the floating-point registers */
112         stfd    fp0,_UC_FREGS+(0*8)(r3)
113         stfd    fp1,_UC_FREGS+(1*8)(r3)
114         stfd    fp2,_UC_FREGS+(2*8)(r3)
115         stfd    fp3,_UC_FREGS+(3*8)(r3)
116         stfd    fp4,_UC_FREGS+(4*8)(r3)
117         stfd    fp5,_UC_FREGS+(5*8)(r3)
118         stfd    fp6,_UC_FREGS+(6*8)(r3)
119         stfd    fp7,_UC_FREGS+(7*8)(r3)
120         stfd    fp8,_UC_FREGS+(8*8)(r3)
121         stfd    fp9,_UC_FREGS+(9*8)(r3)
122         stfd    fp10,_UC_FREGS+(10*8)(r3)
123         stfd    fp11,_UC_FREGS+(11*8)(r3)
124         stfd    fp12,_UC_FREGS+(12*8)(r3)
125         stfd    fp13,_UC_FREGS+(13*8)(r3)
126         stfd    fp14,_UC_FREGS+(14*8)(r3)
127         stfd    fp15,_UC_FREGS+(15*8)(r3)
128         stfd    fp16,_UC_FREGS+(16*8)(r3)
129         stfd    fp17,_UC_FREGS+(17*8)(r3)
130         stfd    fp18,_UC_FREGS+(18*8)(r3)
131         stfd    fp19,_UC_FREGS+(19*8)(r3)
132         stfd    fp20,_UC_FREGS+(20*8)(r3)
133         stfd    fp21,_UC_FREGS+(21*8)(r3)
134         stfd    fp22,_UC_FREGS+(22*8)(r3)
135         stfd    fp23,_UC_FREGS+(23*8)(r3)
136         stfd    fp24,_UC_FREGS+(24*8)(r3)
137         stfd    fp25,_UC_FREGS+(25*8)(r3)
138         stfd    fp26,_UC_FREGS+(26*8)(r3)
139         stfd    fp27,_UC_FREGS+(27*8)(r3)
140         stfd    fp28,_UC_FREGS+(28*8)(r3)
141         stfd    fp29,_UC_FREGS+(29*8)(r3)
142         mffs    fp0
143         stfd    fp30,_UC_FREGS+(30*8)(r3)
144         stfd    fp31,_UC_FREGS+(31*8)(r3)
145         stfd    fp0,_UC_FREGS+(32*8)(r3)
146         
147 # ifdef __CONTEXT_ENABLE_VRS
148 #  ifdef PIC
149         mflr    r8
150 #   ifdef HAVE_ASM_PPC_REL16
151         bcl     20,31,1f
152 1:      mflr    r7
153         addis   r7,r7,_GLOBAL_OFFSET_TABLE_-1b@ha
154         addi    r7,r7,_GLOBAL_OFFSET_TABLE_-1b@l
155 #   else
156         bl      _GLOBAL_OFFSET_TABLE_@local-4
157         mflr    r7
158 #   endif
159 #   ifdef SHARED
160         lwz     r7,_rtld_global_ro@got(r7)
161         mtlr    r8
162         lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r7)
163 #   else
164         lwz     r7,_dl_hwcap@got(r7)
165         mtlr    r8
166         lwz     r7,0(r7)
167 #   endif
168 #  else
169         lis     r7,_dl_hwcap@ha
170         lwz     r7,_dl_hwcap@l(r7)
171 #  endif
172         andis.  r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
174         la      r10,(_UC_VREGS)(r3)
175         la      r9,(_UC_VREGS+16)(r3)
176         
177 /*      beq     L(no_vec)*/
178         beq     2f
179 /* address of the combined VSCR/VSAVE quadword.  */     
180         la      r8,(_UC_VREGS+512)(r3)
182 /* Save the vector registers */
183         stvx  v0,0,r10
184         stvx  v1,0,r9
185         addi  r10,r10,32
186         addi  r9,r9,32
187 /* We need to get the Vector Status and Control Register early to avoid
188    store order problems later with the VSAVE register that shares the
189    same quadword.  */
190         mfvscr  v0
192         stvx  v2,0,r10
193         stvx  v3,0,r9
194         addi  r10,r10,32
195         addi  r9,r9,32
196         
197         stvx    v0,0,r8
199         stvx  v4,0,r10
200         stvx  v5,0,r9
201         addi  r10,r10,32
202         addi  r9,r9,32
204         stvx  v6,0,r10
205         stvx  v7,0,r9
206         addi  r10,r10,32
207         addi  r9,r9,32
209         stvx  v8,0,r10
210         stvx  v9,0,r9
211         addi  r10,r10,32
212         addi  r9,r9,32
214         stvx  v10,0,r10
215         stvx  v11,0,r9
216         addi  r10,r10,32
217         addi  r9,r9,32
219         stvx  v12,0,r10
220         stvx  v13,0,r9
221         addi  r10,r10,32
222         addi  r9,r9,32
224         stvx  v14,0,r10
225         stvx  v15,0,r9
226         addi  r10,r10,32
227         addi  r9,r9,32
229         stvx  v16,0,r10
230         stvx  v17,0,r9
231         addi  r10,r10,32
232         addi  r9,r9,32
234         stvx  v18,0,r10
235         stvx  v19,0,r9
236         addi  r10,r10,32
237         addi  r9,r9,32
239         stvx  v20,0,r10
240         stvx  v21,0,r9
241         addi  r10,r10,32
242         addi  r9,r9,32
244         stvx  v22,0,r10
245         stvx  v23,0,r9
246         addi  r10,r10,32
247         addi  r9,r9,32
249         stvx  v24,0,r10
250         stvx  v25,0,r9
251         addi  r10,r10,32
252         addi  r9,r9,32
254         stvx  v26,0,r10
255         stvx  v27,0,r9
256         addi  r10,r10,32
257         addi  r9,r9,32
259         stvx  v28,0,r10
260         stvx  v29,0,r9
261         addi  r10,r10,32
262         addi  r9,r9,32
264         mfvscr  v0
265         stvx  v30,0,r10
266         stvx  v31,0,r9
267         stw     r0,0(r8)
268         
269 2: /*L(no_vec):*/
270 # endif /* __CONTEXT_ENABLE_VRS */
271 #endif /* __CONTEXT_ENABLE_FPRS */
273 /* Restore ucontext (parm1) from stack.  */
274         lwz     r12,_FRAME_PARM_SAVE1(r1)
275         li      r4,0
276         stw     r3,_UC_REGS_PTR(r12)
277         addi    r5,r12,_UC_SIGMASK
278         li      r3,SIG_SETMASK
279         bl      __sigprocmask@local
280         cmpwi   r3,0
281         bne     3f      /* L(error_exit) */
283         /*
284          * If the new ucontext refers to the point where we were interrupted
285          * by a signal, we have to use the rt_sigreturn system call to
286          * return to the context so we get both LR and CTR restored.
287          *
288          * Otherwise, the context we are restoring is either just after
289          * a procedure call (getcontext/swapcontext) or at the beginning
290          * of a procedure call (makecontext), so we don't need to restore
291          * r0, xer, ctr.  We don't restore r2 since it will be used as
292          * the TLS pointer.
293          */
294         lwz     r4,_FRAME_PARM_SAVE2(r1)
295         lwz     r31,_UC_REGS_PTR(r4)
296         lwz     r0,_UC_GREGS+(PT_MSR*4)(r31)
297         cmpwi   r0,0
298         bne     4f      /* L(do_sigret) */
300 #ifdef __CONTEXT_ENABLE_FPRS
301 # ifdef __CONTEXT_ENABLE_VRS
303 #  ifdef PIC
304         mflr    r8
305 #   ifdef HAVE_ASM_PPC_REL16
306         bcl     20,31,5f
307 5:      mflr    r7
308         addis   r7,r7,_GLOBAL_OFFSET_TABLE_-1b@ha
309         addi    r7,r7,_GLOBAL_OFFSET_TABLE_-1b@l
310 #   else
311         bl      _GLOBAL_OFFSET_TABLE_@local-4
312         mflr    r7
313 #   endif
314         mtlr    r8
315 #   ifdef SHARED
316         lwz     r7,_rtld_global_ro@got(r7)
317         lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r7)
318 #   else
319         lwz     r7,_dl_hwcap@got(r7)
320         lwz     r7,0(r7)
321 #   endif
322 #  else
323         lis     r7,_dl_hwcap@ha
324         lwz     r7,_dl_hwcap@l(r7)
325 #  endif
326         andis.  r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
327         la      r10,(_UC_VREGS)(r31)
328         beq     6f      /* L(has_no_vec) */
330         lwz   r0,(32*16)(r10)
331         li    r9,(32*16)
332         cmpwi r0,0
333         mtspr VRSAVE,r0
334         beq     6f      /* L(has_no_vec) */
336         lvx   v19,r9,r10
337         la    r9,(16)(r10)
339         lvx   v0,0,r10
340         lvx   v1,0,r9
341         addi  r10,r10,32
342         addi  r9,r9,32
344         mtvscr  v19
345         lvx   v2,0,r10
346         lvx   v3,0,r9
347         addi  r10,r10,32
348         addi  r9,r9,32
350         lvx   v4,0,r10
351         lvx   v5,0,r9
352         addi  r10,r10,32
353         addi  r9,r9,32
355         lvx   v6,0,r10
356         lvx   v7,0,r9
357         addi  r10,r10,32
358         addi  r9,r9,32
360         lvx   v8,0,r10
361         lvx   v9,0,r9
362         addi  r10,r10,32
363         addi  r9,r9,32
365         lvx   v10,0,r10
366         lvx   v11,0,r9
367         addi  r10,r10,32
368         addi  r9,r9,32
370         lvx   v12,0,r10
371         lvx   v13,0,r9
372         addi  r10,r10,32
373         addi  r9,r9,32
375         lvx   v14,0,r10
376         lvx   v15,0,r9
377         addi  r10,r10,32
378         addi  r9,r9,32
380         lvx   v16,0,r10
381         lvx   v17,0,r9
382         addi  r10,r10,32
383         addi  r9,r9,32
385         lvx   v18,0,r10
386         lvx   v19,0,r9
387         addi  r10,r10,32
388         addi  r9,r9,32
390         lvx   v20,0,r10
391         lvx   v21,0,r9
392         addi  r10,r10,32
393         addi  r9,r9,32
395         lvx   v22,0,r10
396         lvx   v23,0,r9
397         addi  r10,r10,32
398         addi  r9,r9,32
400         lvx   v24,0,r10
401         lvx   v25,0,r9
402         addi  r10,r10,32
403         addi  r9,r9,32
405         lvx   v26,0,r10
406         lvx   v27,0,r9
407         addi  r10,r10,32
408         addi  r9,r9,32
410         lvx   v28,0,r10
411         lvx   v29,0,r9
412         addi  r10,r10,32
413         addi  r9,r9,32
415         lvx   v30,0,r10
416         lvx   v31,0,r9
417         addi  r10,r10,32
418         addi  r9,r9,32
420         lvx   v10,0,r10
421         lvx   v11,0,r9
423 6: /* L(has_no_vec): */
424 # endif /* __CONTEXT_ENABLE_VRS */
425         /* Restore the floating-point registers */
426         lfd     fp31,_UC_FREGS+(32*8)(r31)
427         lfd     fp0,_UC_FREGS+(0*8)(r31)
428         mtfsf   0xff,fp31
429         lfd     fp1,_UC_FREGS+(1*8)(r31)
430         lfd     fp2,_UC_FREGS+(2*8)(r31)
431         lfd     fp3,_UC_FREGS+(3*8)(r31)
432         lfd     fp4,_UC_FREGS+(4*8)(r31)
433         lfd     fp5,_UC_FREGS+(5*8)(r31)
434         lfd     fp6,_UC_FREGS+(6*8)(r31)
435         lfd     fp7,_UC_FREGS+(7*8)(r31)
436         lfd     fp8,_UC_FREGS+(8*8)(r31)
437         lfd     fp9,_UC_FREGS+(9*8)(r31)
438         lfd     fp10,_UC_FREGS+(10*8)(r31)
439         lfd     fp11,_UC_FREGS+(11*8)(r31)
440         lfd     fp12,_UC_FREGS+(12*8)(r31)
441         lfd     fp13,_UC_FREGS+(13*8)(r31)
442         lfd     fp14,_UC_FREGS+(14*8)(r31)
443         lfd     fp15,_UC_FREGS+(15*8)(r31)
444         lfd     fp16,_UC_FREGS+(16*8)(r31)
445         lfd     fp17,_UC_FREGS+(17*8)(r31)
446         lfd     fp18,_UC_FREGS+(18*8)(r31)
447         lfd     fp19,_UC_FREGS+(19*8)(r31)
448         lfd     fp20,_UC_FREGS+(20*8)(r31)
449         lfd     fp21,_UC_FREGS+(21*8)(r31)
450         lfd     fp22,_UC_FREGS+(22*8)(r31)
451         lfd     fp23,_UC_FREGS+(23*8)(r31)
452         lfd     fp24,_UC_FREGS+(24*8)(r31)
453         lfd     fp25,_UC_FREGS+(25*8)(r31)
454         lfd     fp26,_UC_FREGS+(26*8)(r31)
455         lfd     fp27,_UC_FREGS+(27*8)(r31)
456         lfd     fp28,_UC_FREGS+(28*8)(r31)
457         lfd     fp29,_UC_FREGS+(29*8)(r31)
458         lfd     fp30,_UC_FREGS+(30*8)(r31)
459         lfd     fp31,_UC_FREGS+(31*8)(r31)
460 #endif /* __CONTEXT_ENABLE_FPRS */
462         /* Restore LR and CCR, and set CTR to the NIP value */
463         lwz     r3,_UC_GREGS+(PT_LNK*4)(r31)
464         lwz     r4,_UC_GREGS+(PT_NIP*4)(r31)
465         lwz     r5,_UC_GREGS+(PT_CCR*4)(r31)
466         mtlr    r3
467         mtctr   r4
468         mtcr    r5
470         /* Restore the general registers */
471         lwz     r3,_UC_GREGS+(PT_R3*4)(r31)
472         lwz     r4,_UC_GREGS+(PT_R4*4)(r31)
473         lwz     r5,_UC_GREGS+(PT_R5*4)(r31)
474         lwz     r6,_UC_GREGS+(PT_R6*4)(r31)
475         lwz     r7,_UC_GREGS+(PT_R7*4)(r31)
476         lwz     r8,_UC_GREGS+(PT_R8*4)(r31)
477         lwz     r9,_UC_GREGS+(PT_R9*4)(r31)
478         lwz     r10,_UC_GREGS+(PT_R10*4)(r31)
479         lwz     r11,_UC_GREGS+(PT_R11*4)(r31)
480         lwz     r12,_UC_GREGS+(PT_R12*4)(r31)
481         lwz     r13,_UC_GREGS+(PT_R13*4)(r31)
482         lwz     r14,_UC_GREGS+(PT_R14*4)(r31)
483         lwz     r15,_UC_GREGS+(PT_R15*4)(r31)
484         lwz     r16,_UC_GREGS+(PT_R16*4)(r31)
485         lwz     r17,_UC_GREGS+(PT_R17*4)(r31)
486         lwz     r18,_UC_GREGS+(PT_R18*4)(r31)
487         lwz     r19,_UC_GREGS+(PT_R19*4)(r31)
488         lwz     r20,_UC_GREGS+(PT_R20*4)(r31)
489         lwz     r21,_UC_GREGS+(PT_R21*4)(r31)
490         lwz     r22,_UC_GREGS+(PT_R22*4)(r31)
491         lwz     r23,_UC_GREGS+(PT_R23*4)(r31)
492         lwz     r24,_UC_GREGS+(PT_R24*4)(r31)
493         lwz     r25,_UC_GREGS+(PT_R25*4)(r31)
494         lwz     r26,_UC_GREGS+(PT_R26*4)(r31)
495         lwz     r27,_UC_GREGS+(PT_R27*4)(r31)
496         lwz     r28,_UC_GREGS+(PT_R28*4)(r31)
497         lwz     r29,_UC_GREGS+(PT_R29*4)(r31)
498         lwz     r30,_UC_GREGS+(PT_R30*4)(r31)
499         lwz     r1,_UC_GREGS+(PT_R1*4)(r31)
500         lwz     r31,_UC_GREGS+(PT_R31*4)(r31)
502         bctr
503         
504 3:/*L(error_exit):*/
505         lwz     r0,_FRAME_LR_SAVE+16(r1)
506         addi    r1,r1,16
507         mtlr    r0
508         blr
509         
510 4:/*L(do_sigret):*/
511         addi    r1,r4,-0xd0
512         li      r0,SYS_ify(rt_sigreturn)
513         sc
514         /* NOTREACHED */
516 END(__CONTEXT_FUNC_NAME)