(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / unix / sysv / linux / ia64 / clone2.S
blob69c9e050442d0268b25a3c5af068a0b4b19576b7
1 /* Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <asm/errno.h>
24 /* int  __clone2(int (*fn) (void *arg), void *child_stack_base,         */
25 /*               size_t child_stack_size, int flags, void *arg,         */
26 /*               pid_t *parent_tid, void *tls, pid_t *child_tid)        */
28 #define CHILD   p8
29 #define PARENT  p9
31 ENTRY(__clone2)
32         .prologue
33         alloc r2=ar.pfs,8,1,6,0
34         cmp.eq p6,p0=0,in0
35         mov r8=EINVAL
36         mov out0=in3            /* Flags are first syscall argument.    */
37         mov out1=in1            /* Stack address.                       */
38 (p6)    br.cond.spnt.many __syscall_error
39         ;;
40         mov out2=in2            /* Stack size.                          */
41         mov out3=in5            /* Parent TID Pointer                   */
42         mov out4=in7            /* Child TID Pointer                    */
43         mov out5=in6            /* TLS pointer                          */
44         /*
45          * clone2() is special: the child cannot execute br.ret right
46          * after the system call returns, because it starts out
47          * executing on an empty stack.  Because of this, we can't use
48          * the new (lightweight) syscall convention here.  Instead, we
49          * just fall back on always using "break".
50          *
51          * Furthermore, since the child starts with an empty stack, we
52          * need to avoid unwinding past invalid memory.  To that end,
53          * we'll pretend now that __clone2() is the end of the
54          * call-chain.  This is wrong for the parent, but only until
55          * it returns from clone2() but it's better than the
56          * alternative.
57          */
58         mov r15=SYS_ify (clone2)
59         .save rp, r0
60         break __BREAK_SYSCALL
61         .body
62         cmp.eq p6,p0=-1,r10
63         cmp.eq CHILD,PARENT=0,r8 /* Are we the child?   */
64 (p6)    br.cond.spnt.many __syscall_error
65         ;;
66 (CHILD) mov loc0=gp
67 (PARENT) ret
68         ;;
69 #ifdef RESET_PID
70         tbit.nz p6,p0=in3,16    /* CLONE_THREAD */
71         tbit.z p7,p10=in3,8     /* CLONE_VM */
72 (p6)    br.cond.dptk 1f
73         ;;
74         mov r15=SYS_ify (getpid)
75 (p10)   addl r8=-1,r0
76 (p7)    break __BREAK_SYSCALL
77         ;;
78         add r9=PID,r13
79         add r10=TID,r13
80         ;;
81         st4 [r9]=r8
82         st4 [r10]=r8
83         ;;
84 #endif
85 1:      ld8 out1=[in0],8        /* Retrieve code pointer.       */
86         mov out0=in4            /* Pass proper argument to fn */
87         ;;
88         ld8 gp=[in0]            /* Load function gp.            */
89         mov b6=out1
90         br.call.dptk.many rp=b6 /* Call fn(arg) in the child    */
91         ;;
92         mov out0=r8             /* Argument to _exit            */
93         mov gp=loc0
94         .globl HIDDEN_JUMPTARGET(_exit)
95         br.call.dpnt.many rp=HIDDEN_JUMPTARGET(_exit)
96                                 /* call _exit with result from fn.      */
97         ret                     /* Not reached.         */
98 PSEUDO_END(__clone2)
100 /* For now we leave __clone undefined.  This is unlikely to be a        */
101 /* problem, since at least the i386 __clone in glibc always failed      */
102 /* with a 0 sp (eventhough the kernel explicitly handled it).           */
103 /* Thus all such calls needed to pass an explicit sp, and as a result,  */
104 /* would be unlikely to work on ia64.                                   */