2.9
[glibc/nacl-glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / setcontext-common.S
blob40a7a24f1972da7ad697a0715364d3250bc9372c
1 /* Jump to a new context powerpc32 common.
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         mflr    r0
43         stwu    r1,-16(r1)
44         cfi_adjust_cfa_offset (16)
45         stw     r0,20(r1)
46         cfi_offset (lr, _FRAME_LR_SAVE)
47         stw     r31,12(r1)
48         cfi_offset(r31,-4)
49         lwz     r31,_UC_REGS_PTR(r3)
51         /*
52          * If this ucontext refers to the point where we were interrupted
53          * by a signal, we have to use the rt_sigreturn system call to
54          * return to the context so we get both LR and CTR restored.
55          *
56          * Otherwise, the context we are restoring is either just after
57          * a procedure call (getcontext/swapcontext) or at the beginning
58          * of a procedure call (makecontext), so we don't need to restore
59          * r0, xer, ctr.  We don't restore r2 since it will be used as
60          * the TLS pointer.
61          */
62         lwz     r0,_UC_GREGS+(PT_MSR*4)(r31)
63         cmpwi   r0,0
64         bne     4f      /* L(do_sigret) */
66         /* Restore the signal mask */
67         li      r5,0
68         addi    r4,r3,_UC_SIGMASK
69         li      r3,SIG_SETMASK
70         bl      __sigprocmask@local
71         cmpwi   r3,0
72         bne     3f      /* L(error_exit) */
74 #ifdef __CONTEXT_ENABLE_FPRS
75 # ifdef __CONTEXT_ENABLE_VRS
76 #  ifdef PIC
77         mflr    r8
78 #   ifdef HAVE_ASM_PPC_REL16
79         bcl     20,31,1f
80 1:      mflr    r7
81         addis   r7,r7,_GLOBAL_OFFSET_TABLE_-1b@ha
82         addi    r7,r7,_GLOBAL_OFFSET_TABLE_-1b@l
83 #   else
84         bl      _GLOBAL_OFFSET_TABLE_@local-4
85         mflr    r7
86 #   endif
87 #   ifdef SHARED
88         lwz     r7,_rtld_global_ro@got(r7)
89         mtlr    r8
90         lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r7)
91 #   else
92         lwz     r7,_dl_hwcap@got(r7)
93         mtlr    r8
94         lwz     r7,0(r7)
95 #   endif
96 #  else
97         lis     r7,_dl_hwcap@ha
98         lwz     r7,_dl_hwcap@l(r7)
99 #  endif
100         andis.  r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
101         la      r10,(_UC_VREGS)(r31)
102         beq     2f      /* L(has_no_vec) */
104         lwz   r0,(32*16)(r10)
105         li    r9,(32*16)
106         cmpwi r0,0
107         mtspr VRSAVE,r0
108         beq     2f      /* L(has_no_vec) */
110         lvx   v19,r9,r10
111         la    r9,(16)(r10)
113         lvx   v0,0,r10
114         lvx   v1,0,r9
115         addi  r10,r10,32
116         addi  r9,r9,32
118         mtvscr  v19
119         lvx   v2,0,r10
120         lvx   v3,0,r9
121         addi  r10,r10,32
122         addi  r9,r9,32
124         lvx   v4,0,r10
125         lvx   v5,0,r9
126         addi  r10,r10,32
127         addi  r9,r9,32
129         lvx   v6,0,r10
130         lvx   v7,0,r9
131         addi  r10,r10,32
132         addi  r9,r9,32
134         lvx   v8,0,r10
135         lvx   v9,0,r9
136         addi  r10,r10,32
137         addi  r9,r9,32
139         lvx   v10,0,r10
140         lvx   v11,0,r9
141         addi  r10,r10,32
142         addi  r9,r9,32
144         lvx   v12,0,r10
145         lvx   v13,0,r9
146         addi  r10,r10,32
147         addi  r9,r9,32
149         lvx   v14,0,r10
150         lvx   v15,0,r9
151         addi  r10,r10,32
152         addi  r9,r9,32
154         lvx   v16,0,r10
155         lvx   v17,0,r9
156         addi  r10,r10,32
157         addi  r9,r9,32
159         lvx   v18,0,r10
160         lvx   v19,0,r9
161         addi  r10,r10,32
162         addi  r9,r9,32
164         lvx   v20,0,r10
165         lvx   v21,0,r9
166         addi  r10,r10,32
167         addi  r9,r9,32
169         lvx   v22,0,r10
170         lvx   v23,0,r9
171         addi  r10,r10,32
172         addi  r9,r9,32
174         lvx   v24,0,r10
175         lvx   v25,0,r9
176         addi  r10,r10,32
177         addi  r9,r9,32
179         lvx   v26,0,r10
180         lvx   v27,0,r9
181         addi  r10,r10,32
182         addi  r9,r9,32
184         lvx   v28,0,r10
185         lvx   v29,0,r9
186         addi  r10,r10,32
187         addi  r9,r9,32
189         lvx   v30,0,r10
190         lvx   v31,0,r9
191         addi  r10,r10,32
192         addi  r9,r9,32
194         lvx   v10,0,r10
195         lvx   v11,0,r9
197 2: /* L(has_no_vec): */
198 # endif /* __CONTEXT_ENABLE_VRS */
199         /* Restore the floating-point registers */
200         lfd     fp31,_UC_FREGS+(32*8)(r31)
201         lfd     fp0,_UC_FREGS+(0*8)(r31)
202         mtfsf   0xff,fp31
203         lfd     fp1,_UC_FREGS+(1*8)(r31)
204         lfd     fp2,_UC_FREGS+(2*8)(r31)
205         lfd     fp3,_UC_FREGS+(3*8)(r31)
206         lfd     fp4,_UC_FREGS+(4*8)(r31)
207         lfd     fp5,_UC_FREGS+(5*8)(r31)
208         lfd     fp6,_UC_FREGS+(6*8)(r31)
209         lfd     fp7,_UC_FREGS+(7*8)(r31)
210         lfd     fp8,_UC_FREGS+(8*8)(r31)
211         lfd     fp9,_UC_FREGS+(9*8)(r31)
212         lfd     fp10,_UC_FREGS+(10*8)(r31)
213         lfd     fp11,_UC_FREGS+(11*8)(r31)
214         lfd     fp12,_UC_FREGS+(12*8)(r31)
215         lfd     fp13,_UC_FREGS+(13*8)(r31)
216         lfd     fp14,_UC_FREGS+(14*8)(r31)
217         lfd     fp15,_UC_FREGS+(15*8)(r31)
218         lfd     fp16,_UC_FREGS+(16*8)(r31)
219         lfd     fp17,_UC_FREGS+(17*8)(r31)
220         lfd     fp18,_UC_FREGS+(18*8)(r31)
221         lfd     fp19,_UC_FREGS+(19*8)(r31)
222         lfd     fp20,_UC_FREGS+(20*8)(r31)
223         lfd     fp21,_UC_FREGS+(21*8)(r31)
224         lfd     fp22,_UC_FREGS+(22*8)(r31)
225         lfd     fp23,_UC_FREGS+(23*8)(r31)
226         lfd     fp24,_UC_FREGS+(24*8)(r31)
227         lfd     fp25,_UC_FREGS+(25*8)(r31)
228         lfd     fp26,_UC_FREGS+(26*8)(r31)
229         lfd     fp27,_UC_FREGS+(27*8)(r31)
230         lfd     fp28,_UC_FREGS+(28*8)(r31)
231         lfd     fp29,_UC_FREGS+(29*8)(r31)
232         lfd     fp30,_UC_FREGS+(30*8)(r31)
233         lfd     fp31,_UC_FREGS+(31*8)(r31)
234 #endif /* __CONTEXT_ENABLE_FPRS */
236         /* Restore LR and CCR, and set CTR to the NIP value */
237         lwz     r3,_UC_GREGS+(PT_LNK*4)(r31)
238         lwz     r4,_UC_GREGS+(PT_NIP*4)(r31)
239         lwz     r5,_UC_GREGS+(PT_CCR*4)(r31)
240         mtlr    r3
241         mtctr   r4
242         mtcr    r5
244         /* Restore the general registers */
245         lwz     r1,_UC_GREGS+(PT_R1*4)(r31)
246         lwz     r3,_UC_GREGS+(PT_R3*4)(r31)
247         lwz     r4,_UC_GREGS+(PT_R4*4)(r31)
248         lwz     r5,_UC_GREGS+(PT_R5*4)(r31)
249         lwz     r6,_UC_GREGS+(PT_R6*4)(r31)
250         lwz     r7,_UC_GREGS+(PT_R7*4)(r31)
251         lwz     r8,_UC_GREGS+(PT_R8*4)(r31)
252         lwz     r9,_UC_GREGS+(PT_R9*4)(r31)
253         lwz     r10,_UC_GREGS+(PT_R10*4)(r31)
254         lwz     r11,_UC_GREGS+(PT_R11*4)(r31)
255         lwz     r12,_UC_GREGS+(PT_R12*4)(r31)
256         lwz     r13,_UC_GREGS+(PT_R13*4)(r31)
257         lwz     r14,_UC_GREGS+(PT_R14*4)(r31)
258         lwz     r15,_UC_GREGS+(PT_R15*4)(r31)
259         lwz     r16,_UC_GREGS+(PT_R16*4)(r31)
260         lwz     r17,_UC_GREGS+(PT_R17*4)(r31)
261         lwz     r18,_UC_GREGS+(PT_R18*4)(r31)
262         lwz     r19,_UC_GREGS+(PT_R19*4)(r31)
263         lwz     r20,_UC_GREGS+(PT_R20*4)(r31)
264         lwz     r21,_UC_GREGS+(PT_R21*4)(r31)
265         lwz     r22,_UC_GREGS+(PT_R22*4)(r31)
266         lwz     r23,_UC_GREGS+(PT_R23*4)(r31)
267         lwz     r24,_UC_GREGS+(PT_R24*4)(r31)
268         lwz     r25,_UC_GREGS+(PT_R25*4)(r31)
269         lwz     r26,_UC_GREGS+(PT_R26*4)(r31)
270         lwz     r27,_UC_GREGS+(PT_R27*4)(r31)
271         lwz     r28,_UC_GREGS+(PT_R28*4)(r31)
272         lwz     r29,_UC_GREGS+(PT_R29*4)(r31)
273         lwz     r30,_UC_GREGS+(PT_R30*4)(r31)
274         lwz     r31,_UC_GREGS+(PT_R31*4)(r31)
276         bctr
278 3: /* L(error_exit): */
279         lwz     r31,12(r1)
280         lwz     r0,20(r1)
281         addi    r1,r1,16
282         mtlr    r0
283         blr
286 4: /* L(do_sigret): */
287         addi    r1,r3,-0xd0
288         li      r0,SYS_ify(rt_sigreturn)
289         sc
290         /* NOTREACHED */
292 END (__CONTEXT_FUNC_NAME)