1/* Copyright (C) 2001, 2005 Free Software Foundation, Inc.
2
3   The GNU C Library is free software; you can redistribute it and/or
4   modify it under the terms of the GNU Library General Public License as
5   published by the Free Software Foundation; either version 2 of the
6   License, or (at your option) any later version.
7
8   The GNU C Library is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   Library General Public License for more details.
12
13   You should have received a copy of the GNU Library General Public
14   License along with the GNU C Library; see the file COPYING.LIB.  If not,
15   see <http://www.gnu.org/licenses/>.  */
16
17/* clone is even more special than fork as it mucks with stacks
18   and invokes a function in the right context after its all over.  */
19
20#include <features.h>
21#include <sysdep.h>
22#define _ERRNO_H	1
23#include <bits/errno.h>
24#define __ASSEMBLY__
25
26/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
27                    a2                    a3               a4        a5
28             pid_t *ptid, struct user_desc *tls, pid_t *ctid)
29                   a6               a7              16(sp)
30*/
31
32        .text
33ENTRY (__clone)
34
35	/* Sanity check arguments.  */
36	beqz	a2, .Leinval	/* no NULL function pointers */
37	beqz	a3, .Leinval	/* no NULL stack pointers */
38
39	/* a2 and a3 are candidates for destruction by system-call return
40	   parameters.  We don't need the stack pointer after the system
41	   call.  We trust that the kernel will preserve a6, a7 and a9. */
42
43	mov	a9, a5			/* save function argument */
44	mov	a5, a7
45	mov	a7, a2			/* save function pointer */
46	mov	a8, a6			/* use a8 as a temp */
47	mov	a6, a4
48	mov	a4, a8
49	l32i	a8, a1, FRAMESIZE	/* child_tid */
50	movi	a2, SYS_ify(clone)
51
52	/* syscall(NR_clone,clone_flags, usp, parent_tid, child_tls, child_tid)
53                     a2         a6        a3        a4        a5         a8
54         */
55
56	syscall
57	bltz	a2, SYSCALL_ERROR_LABEL
58	beqz	a2, .Lthread_start
59
60	/* fall through for parent */
61
62.Lpseudo_end:
63	abi_ret
64
65.Leinval:
66	movi	a2, -EINVAL
67	j	SYSCALL_ERROR_LABEL
68
69.Lthread_start:
70
71	/* start child thread */
72	movi	a0, 0			/* terminate the stack frame */
73
74#if defined(__XTENSA_WINDOWED_ABI__)
75	mov	a6, a9			/* load up the 'arg' parameter */
76	callx4	a7			/* call the user's function */
77
78	/* Call _exit.  Note that any return parameter from the user's
79	   function in a6 is seen as inputs to _exit. */
80	movi	a2, JUMPTARGET(_exit)
81	callx4	a2
82#elif defined(__XTENSA_CALL0_ABI__)
83	mov	a2, a9			/* load up the 'arg' parameter */
84#ifdef __FDPIC__
85	mov	a12, a11
86	l32i	a11, a7, 4
87	l32i	a7, a7, 0
88#endif
89	callx0	a7			/* call the user's function */
90
91	/* Call _exit.  Note that any return parameter from the user's
92	   function in a2 is seen as inputs to _exit.  */
93	movi	a0, JUMPTARGET(_exit)
94	FDPIC_LOAD_JUMPTARGET(a0, a12, a0)
95	callx0	a0
96#else
97#error Unsupported Xtensa ABI
98#endif
99
100PSEUDO_END (__clone)
101weak_alias (__clone, clone)
102