Add missing export of fallocate64 on 32-bit platforms.
[glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / swapcontext-common.S
blob89b1a6195414e531c95d5e372d61eae1fbd85465
1 /* Save current context and jump to a new context.
2    Copyright (C) 2005, 2006, 2008, 2009 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)
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)
147 # ifdef PIC
148         mflr    r8
149 #  ifdef HAVE_ASM_PPC_REL16
150         bcl     20,31,1f
151 1:      mflr    r7
152         addis   r7,r7,_GLOBAL_OFFSET_TABLE_-1b@ha
153         addi    r7,r7,_GLOBAL_OFFSET_TABLE_-1b@l
154 #  else
155         bl      _GLOBAL_OFFSET_TABLE_@local-4
156         mflr    r7
157 #  endif
158 #  ifdef SHARED
159         lwz     r7,_rtld_global_ro@got(r7)
160         mtlr    r8
161         lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r7)
162 #  else
163         lwz     r7,_dl_hwcap@got(r7)
164         mtlr    r8
165         lwz     r7,4(r7)
166 #  endif
167 # else
168         lis     r7,(_dl_hwcap+4)@ha
169         lwz     r7,(_dl_hwcap+4)@l(r7)
170 # endif
172 # ifdef __CONTEXT_ENABLE_VRS
173         andis.  r6,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
175         la      r10,(_UC_VREGS)(r3)
176         la      r9,(_UC_VREGS+16)(r3)
178 /*      beq     L(no_vec)*/
179         beq     2f
180 /* address of the combined VSCR/VSAVE quadword.  */
181         la      r8,(_UC_VREGS+512)(r3)
183 /* Save the vector registers */
184         stvx  v0,0,r10
185         stvx  v1,0,r9
186         addi  r10,r10,32
187         addi  r9,r9,32
188 /* We need to get the Vector Status and Control Register early to avoid
189    store order problems later with the VSAVE register that shares the
190    same quadword.  */
191         mfvscr  v0
193         stvx  v2,0,r10
194         stvx  v3,0,r9
195         addi  r10,r10,32
196         addi  r9,r9,32
198         stvx    v0,0,r8
200         stvx  v4,0,r10
201         stvx  v5,0,r9
202         addi  r10,r10,32
203         addi  r9,r9,32
205         stvx  v6,0,r10
206         stvx  v7,0,r9
207         addi  r10,r10,32
208         addi  r9,r9,32
210         stvx  v8,0,r10
211         stvx  v9,0,r9
212         addi  r10,r10,32
213         addi  r9,r9,32
215         stvx  v10,0,r10
216         stvx  v11,0,r9
217         addi  r10,r10,32
218         addi  r9,r9,32
220         stvx  v12,0,r10
221         stvx  v13,0,r9
222         addi  r10,r10,32
223         addi  r9,r9,32
225         stvx  v14,0,r10
226         stvx  v15,0,r9
227         addi  r10,r10,32
228         addi  r9,r9,32
230         stvx  v16,0,r10
231         stvx  v17,0,r9
232         addi  r10,r10,32
233         addi  r9,r9,32
235         stvx  v18,0,r10
236         stvx  v19,0,r9
237         addi  r10,r10,32
238         addi  r9,r9,32
240         stvx  v20,0,r10
241         stvx  v21,0,r9
242         addi  r10,r10,32
243         addi  r9,r9,32
245         stvx  v22,0,r10
246         stvx  v23,0,r9
247         addi  r10,r10,32
248         addi  r9,r9,32
250         stvx  v24,0,r10
251         stvx  v25,0,r9
252         addi  r10,r10,32
253         addi  r9,r9,32
255         stvx  v26,0,r10
256         stvx  v27,0,r9
257         addi  r10,r10,32
258         addi  r9,r9,32
260         stvx  v28,0,r10
261         stvx  v29,0,r9
262         addi  r10,r10,32
263         addi  r9,r9,32
265         mfvscr  v0
266         stvx  v30,0,r10
267         stvx  v31,0,r9
268         stw     r0,0(r8)
270 2: /*L(no_vec):*/
271 # endif /* __CONTEXT_ENABLE_VRS */
272 #endif /* __CONTEXT_ENABLE_FPRS */
274 /* Restore ucontext (parm1) from stack.  */
275         lwz     r12,_FRAME_PARM_SAVE1(r1)
276         li      r4,0
277         stw     r3,_UC_REGS_PTR(r12)
278         addi    r5,r12,_UC_SIGMASK
279         li      r3,SIG_SETMASK
280         bl      __sigprocmask@local
281         cmpwi   r3,0
282         bne     3f      /* L(error_exit) */
284         /*
285          * If the new ucontext refers to the point where we were interrupted
286          * by a signal, we have to use the rt_sigreturn system call to
287          * return to the context so we get both LR and CTR restored.
288          *
289          * Otherwise, the context we are restoring is either just after
290          * a procedure call (getcontext/swapcontext) or at the beginning
291          * of a procedure call (makecontext), so we don't need to restore
292          * r0, xer, ctr.  We don't restore r2 since it will be used as
293          * the TLS pointer.
294          */
295         lwz     r4,_FRAME_PARM_SAVE2(r1)
296         lwz     r31,_UC_REGS_PTR(r4)
297         lwz     r0,_UC_GREGS+(PT_MSR*4)(r31)
298         cmpwi   r0,0
299         bne     4f      /* L(do_sigret) */
301 #ifdef __CONTEXT_ENABLE_FPRS
302 # ifdef __CONTEXT_ENABLE_VRS
304 #  ifdef PIC
305         mflr    r8
306 #   ifdef HAVE_ASM_PPC_REL16
307         bcl     20,31,5f
308 5:      mflr    r7
309         addis   r7,r7,_GLOBAL_OFFSET_TABLE_-5b@ha
310         addi    r7,r7,_GLOBAL_OFFSET_TABLE_-5b@l
311 #   else
312         bl      _GLOBAL_OFFSET_TABLE_@local-4
313         mflr    r7
314 #   endif
315         mtlr    r8
316 #   ifdef SHARED
317         lwz     r7,_rtld_global_ro@got(r7)
318         lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r7)
319 #   else
320         lwz     r7,_dl_hwcap@got(r7)
321         lwz     r7,4(r7)
322 #   endif
323 #  else
324         lis     r7,(_dl_hwcap+4)@ha
325         lwz     r7,(_dl_hwcap+4)@l(r7)
326 #  endif
327         andis.  r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
328         la      r10,(_UC_VREGS)(r31)
329         beq     6f      /* L(has_no_vec) */
331         lwz   r0,(32*16)(r10)
332         li    r9,(32*16)
333         cmpwi r0,0
334         mtspr VRSAVE,r0
335         beq     6f      /* L(has_no_vec) */
337         lvx   v19,r9,r10
338         la    r9,(16)(r10)
340         lvx   v0,0,r10
341         lvx   v1,0,r9
342         addi  r10,r10,32
343         addi  r9,r9,32
345         mtvscr  v19
346         lvx   v2,0,r10
347         lvx   v3,0,r9
348         addi  r10,r10,32
349         addi  r9,r9,32
351         lvx   v4,0,r10
352         lvx   v5,0,r9
353         addi  r10,r10,32
354         addi  r9,r9,32
356         lvx   v6,0,r10
357         lvx   v7,0,r9
358         addi  r10,r10,32
359         addi  r9,r9,32
361         lvx   v8,0,r10
362         lvx   v9,0,r9
363         addi  r10,r10,32
364         addi  r9,r9,32
366         lvx   v10,0,r10
367         lvx   v11,0,r9
368         addi  r10,r10,32
369         addi  r9,r9,32
371         lvx   v12,0,r10
372         lvx   v13,0,r9
373         addi  r10,r10,32
374         addi  r9,r9,32
376         lvx   v14,0,r10
377         lvx   v15,0,r9
378         addi  r10,r10,32
379         addi  r9,r9,32
381         lvx   v16,0,r10
382         lvx   v17,0,r9
383         addi  r10,r10,32
384         addi  r9,r9,32
386         lvx   v18,0,r10
387         lvx   v19,0,r9
388         addi  r10,r10,32
389         addi  r9,r9,32
391         lvx   v20,0,r10
392         lvx   v21,0,r9
393         addi  r10,r10,32
394         addi  r9,r9,32
396         lvx   v22,0,r10
397         lvx   v23,0,r9
398         addi  r10,r10,32
399         addi  r9,r9,32
401         lvx   v24,0,r10
402         lvx   v25,0,r9
403         addi  r10,r10,32
404         addi  r9,r9,32
406         lvx   v26,0,r10
407         lvx   v27,0,r9
408         addi  r10,r10,32
409         addi  r9,r9,32
411         lvx   v28,0,r10
412         lvx   v29,0,r9
413         addi  r10,r10,32
414         addi  r9,r9,32
416         lvx   v30,0,r10
417         lvx   v31,0,r9
418         addi  r10,r10,32
419         addi  r9,r9,32
421         lvx   v10,0,r10
422         lvx   v11,0,r9
424 6: /* L(has_no_vec): */
425 # endif /* __CONTEXT_ENABLE_VRS */
426         /* Restore the floating-point registers */
427         lfd     fp31,_UC_FREGS+(32*8)(r31)
428         lfd     fp0,_UC_FREGS+(0*8)(r31)
429 # ifdef _ARCH_PWR6
430         /* Use the extended four-operand version of the mtfsf insn.  */
431         mtfsf   0xff,fp31,1,0
432 # else
433         .machine push
434         .machine "power6"
435         /* Availability of DFP indicates a 64-bit FPSCR.  */
436         andi.   r6,r7,PPC_FEATURE_HAS_DFP
437         beq     7f
438         /* Use the extended four-operand version of the mtfsf insn.  */
439         mtfsf   0xff,fp31,1,0
440         b       8f
441         /* Continue to operate on the FPSCR as if it were 32-bits.  */
442 7:      mtfsf   0xff,fp31
443 8:      .machine pop
444 #endif /* _ARCH_PWR6 */
445         lfd     fp1,_UC_FREGS+(1*8)(r31)
446         lfd     fp2,_UC_FREGS+(2*8)(r31)
447         lfd     fp3,_UC_FREGS+(3*8)(r31)
448         lfd     fp4,_UC_FREGS+(4*8)(r31)
449         lfd     fp5,_UC_FREGS+(5*8)(r31)
450         lfd     fp6,_UC_FREGS+(6*8)(r31)
451         lfd     fp7,_UC_FREGS+(7*8)(r31)
452         lfd     fp8,_UC_FREGS+(8*8)(r31)
453         lfd     fp9,_UC_FREGS+(9*8)(r31)
454         lfd     fp10,_UC_FREGS+(10*8)(r31)
455         lfd     fp11,_UC_FREGS+(11*8)(r31)
456         lfd     fp12,_UC_FREGS+(12*8)(r31)
457         lfd     fp13,_UC_FREGS+(13*8)(r31)
458         lfd     fp14,_UC_FREGS+(14*8)(r31)
459         lfd     fp15,_UC_FREGS+(15*8)(r31)
460         lfd     fp16,_UC_FREGS+(16*8)(r31)
461         lfd     fp17,_UC_FREGS+(17*8)(r31)
462         lfd     fp18,_UC_FREGS+(18*8)(r31)
463         lfd     fp19,_UC_FREGS+(19*8)(r31)
464         lfd     fp20,_UC_FREGS+(20*8)(r31)
465         lfd     fp21,_UC_FREGS+(21*8)(r31)
466         lfd     fp22,_UC_FREGS+(22*8)(r31)
467         lfd     fp23,_UC_FREGS+(23*8)(r31)
468         lfd     fp24,_UC_FREGS+(24*8)(r31)
469         lfd     fp25,_UC_FREGS+(25*8)(r31)
470         lfd     fp26,_UC_FREGS+(26*8)(r31)
471         lfd     fp27,_UC_FREGS+(27*8)(r31)
472         lfd     fp28,_UC_FREGS+(28*8)(r31)
473         lfd     fp29,_UC_FREGS+(29*8)(r31)
474         lfd     fp30,_UC_FREGS+(30*8)(r31)
475         lfd     fp31,_UC_FREGS+(31*8)(r31)
476 #endif /* __CONTEXT_ENABLE_FPRS */
478         /* Restore LR and CCR, and set CTR to the NIP value */
479         lwz     r3,_UC_GREGS+(PT_LNK*4)(r31)
480         lwz     r4,_UC_GREGS+(PT_NIP*4)(r31)
481         lwz     r5,_UC_GREGS+(PT_CCR*4)(r31)
482         mtlr    r3
483         mtctr   r4
484         mtcr    r5
486         /* Restore the general registers */
487         lwz     r3,_UC_GREGS+(PT_R3*4)(r31)
488         lwz     r4,_UC_GREGS+(PT_R4*4)(r31)
489         lwz     r5,_UC_GREGS+(PT_R5*4)(r31)
490         lwz     r6,_UC_GREGS+(PT_R6*4)(r31)
491         lwz     r7,_UC_GREGS+(PT_R7*4)(r31)
492         lwz     r8,_UC_GREGS+(PT_R8*4)(r31)
493         lwz     r9,_UC_GREGS+(PT_R9*4)(r31)
494         lwz     r10,_UC_GREGS+(PT_R10*4)(r31)
495         lwz     r11,_UC_GREGS+(PT_R11*4)(r31)
496         lwz     r12,_UC_GREGS+(PT_R12*4)(r31)
497         lwz     r13,_UC_GREGS+(PT_R13*4)(r31)
498         lwz     r14,_UC_GREGS+(PT_R14*4)(r31)
499         lwz     r15,_UC_GREGS+(PT_R15*4)(r31)
500         lwz     r16,_UC_GREGS+(PT_R16*4)(r31)
501         lwz     r17,_UC_GREGS+(PT_R17*4)(r31)
502         lwz     r18,_UC_GREGS+(PT_R18*4)(r31)
503         lwz     r19,_UC_GREGS+(PT_R19*4)(r31)
504         lwz     r20,_UC_GREGS+(PT_R20*4)(r31)
505         lwz     r21,_UC_GREGS+(PT_R21*4)(r31)
506         lwz     r22,_UC_GREGS+(PT_R22*4)(r31)
507         lwz     r23,_UC_GREGS+(PT_R23*4)(r31)
508         lwz     r24,_UC_GREGS+(PT_R24*4)(r31)
509         lwz     r25,_UC_GREGS+(PT_R25*4)(r31)
510         lwz     r26,_UC_GREGS+(PT_R26*4)(r31)
511         lwz     r27,_UC_GREGS+(PT_R27*4)(r31)
512         lwz     r28,_UC_GREGS+(PT_R28*4)(r31)
513         lwz     r29,_UC_GREGS+(PT_R29*4)(r31)
514         lwz     r30,_UC_GREGS+(PT_R30*4)(r31)
515         lwz     r1,_UC_GREGS+(PT_R1*4)(r31)
516         lwz     r31,_UC_GREGS+(PT_R31*4)(r31)
518         bctr
520 3:/*L(error_exit):*/
521         lwz     r0,_FRAME_LR_SAVE+16(r1)
522         addi    r1,r1,16
523         mtlr    r0
524         blr
526 4:/*L(do_sigret):*/
527         addi    r1,r4,-0xd0
528         li      r0,SYS_ify(rt_sigreturn)
529         sc
530         /* NOTREACHED */
532 END(__CONTEXT_FUNC_NAME)