]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/ia64/clone2.S
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / ia64 / clone2.S
CommitLineData
a334319f 1/* Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
41bdb6e2 2 This file is part of the GNU C Library.
101c92fc
UD
3
4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
101c92fc
UD
8
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
41bdb6e2 12 Lesser General Public License for more details.
101c92fc 13
41bdb6e2
AJ
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. */
101c92fc
UD
18
19
20#include <sysdep.h>
21#include <asm/errno.h>
22
23
24/* int __clone2(int (*fn) (void *arg), void *child_stack_base, */
625f22fc 25/* size_t child_stack_size, int flags, void *arg, */
b33e6163 26/* pid_t *parent_tid, void *tls, pid_t *child_tid) */
101c92fc 27
c776b3d7
UD
28#define CHILD p8
29#define PARENT p9
30
101c92fc 31ENTRY(__clone2)
c776b3d7 32 .prologue
484cc801 33 alloc r2=ar.pfs,8,1,6,0
4c48dc93 34 cmp.eq p6,p0=0,in0
101c92fc 35 mov r8=EINVAL
4c48dc93
UD
36 mov out0=in3 /* Flags are first syscall argument. */
37 mov out1=in1 /* Stack address. */
a334319f 38(p6) br.cond.spnt.many __syscall_error
c776b3d7 39 ;;
4c48dc93 40 mov out2=in2 /* Stack size. */
b5ec5617
UD
41 mov out3=in5 /* Parent TID Pointer */
42 mov out4=in7 /* Child TID Pointer */
b33e6163 43 mov out5=in6 /* TLS pointer */
c776b3d7
UD
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
101c92fc 62 cmp.eq p6,p0=-1,r10
c776b3d7
UD
63 cmp.eq CHILD,PARENT=0,r8 /* Are we the child? */
64(p6) br.cond.spnt.many __syscall_error
101c92fc 65 ;;
484cc801 66(CHILD) mov loc0=gp
101c92fc
UD
67(PARENT) ret
68 ;;
484cc801
UD
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
851: ld8 out1=[in0],8 /* Retrieve code pointer. */
86 mov out0=in4 /* Pass proper argument to fn */
87 ;;
c776b3d7 88 ld8 gp=[in0] /* Load function gp. */
4c48dc93 89 mov b6=out1
c776b3d7 90 br.call.dptk.many rp=b6 /* Call fn(arg) in the child */
101c92fc 91 ;;
4c48dc93 92 mov out0=r8 /* Argument to _exit */
484cc801 93 mov gp=loc0
ab8dc78f
UD
94 .globl HIDDEN_JUMPTARGET(_exit)
95 br.call.dpnt.many rp=HIDDEN_JUMPTARGET(_exit)
96 /* call _exit with result from fn. */
101c92fc 97 ret /* Not reached. */
101c92fc
UD
98PSEUDO_END(__clone2)
99
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. */