localedata: dz_BT, bo_CN: convert to UTF-8
[glibc.git] / sysdeps / unix / sysv / linux / ia64 / clone2.S
blob688ea6cef25882d7fb4ee9aed2fc56b53b039d6c
1 /* Copyright (C) 2000-2024 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, see
16    <https://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <asm/errno.h>
23 /* int  __clone2(int (*fn) (void *arg), void *child_stack_base,         */
24 /*               size_t child_stack_size, int flags, void *arg,         */
25 /*               pid_t *parent_tid, void *tls, pid_t *child_tid)        */
27 #define CHILD   p8
28 #define PARENT  p9
30 ENTRY(__clone2)
31         .prologue
32         alloc r2=ar.pfs,8,1,6,0
33         cmp.eq p6,p0=0,in0
34         cmp.eq p7,p0=0,in1
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       /* no NULL function pointers */
39 (p7)    br.cond.spnt.many __syscall_error       /* no NULL stack pointers */
40         ;;
41         mov out2=in2            /* Stack size.                          */
42         mov out3=in5            /* Parent TID Pointer                   */
43         mov out4=in7            /* Child TID Pointer                    */
44         mov out5=in6            /* TLS pointer                          */
45         /*
46          * clone2() is special: the child cannot execute br.ret right
47          * after the system call returns, because it starts out
48          * executing on an empty stack.  Because of this, we can't use
49          * the new (lightweight) syscall convention here.  Instead, we
50          * just fall back on always using "break".
51          *
52          * Furthermore, since the child starts with an empty stack, we
53          * need to avoid unwinding past invalid memory.  To that end,
54          * we'll pretend now that __clone2() is the end of the
55          * call-chain.  This is wrong for the parent, but only until
56          * it returns from clone2() but it's better than the
57          * alternative.
58          */
59         mov r15=SYS_ify (clone2)
60         .save rp, r0
61         break __IA64_BREAK_SYSCALL
62         .body
63         cmp.eq p6,p0=-1,r10
64         cmp.eq CHILD,PARENT=0,r8 /* Are we the child?   */
65 (p6)    br.cond.spnt.many __syscall_error
66         ;;
67 (CHILD) mov loc0=gp
68 (PARENT) ret
69         ;;
70         ld8 out1=[in0],8        /* Retrieve code pointer.       */
71         mov out0=in4            /* Pass proper argument to fn */
72         ;;
73         ld8 gp=[in0]            /* Load function gp.            */
74         mov b6=out1
75         br.call.dptk.many rp=b6 /* Call fn(arg) in the child    */
76         ;;
77         mov out0=r8             /* Argument to exit             */
78         mov gp=loc0
79         mov r15=SYS_ify (exit)
80         .save rp, r0
81         break __IA64_BREAK_SYSCALL
82         ret                     /* Not reached.         */
83 PSEUDO_END(__clone2)
85 libc_hidden_def (__clone2)
87 /* For now we leave __clone undefined.  This is unlikely to be a        */
88 /* problem, since at least the i386 __clone in glibc always failed      */
89 /* with a 0 sp (even though the kernel explicitly handled it).          */
90 /* Thus all such calls needed to pass an explicit sp, and as a result,  */
91 /* would be unlikely to work on ia64.                                   */