1/* Copyright (C) 1999, 2000, 2003, 2004, 2007 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 Lesser General Public
5   License as published by the Free Software Foundation; either
6   version 2.1 of the 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   Lesser General Public License for more details.
12
13   You should have received a copy of the GNU Lesser General Public
14   License along with the GNU C Library; if not, see
15   <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 <asm/unistd.h>
22#include <sysdep.h>
23#define _ERRNO_H	1
24#include <bits/errno.h>
25
26/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
27	     pid_t *ptid, void *tls, pid_t *ctid); */
28
29	.text
30ENTRY(__clone)
31	/* sanity check arguments.  */
32	tst	r4, r4
33	bt/s	0f
34	 tst	r5, r5
35	bf	1f
360:
37	bra	.Lsyscall_error
38	 mov	#-EINVAL,r0
391:
40	/* insert the args onto the new stack */
41	mov.l	r7, @-r5
42	/* save the function pointer as the 0th element */
43	mov.l	r4, @-r5
44
45	/* do the system call */
46	mov	r6, r4
47	mov.l	@r15, r6
48	mov.l	@(8,r15), r7
49	mov.l	@(4,r15), r0
50	mov	#+SYS_ify(clone), r3
51	trapa	#0x15
52	mov     r0, r1
53#ifdef __sh2__
54/* 12 arithmetic shifts for the sh2, because shad doesn't exist! */
55        shar    r1
56        shar    r1
57        shar    r1
58        shar    r1
59        shar    r1
60        shar    r1
61        shar    r1
62        shar    r1
63        shar    r1
64        shar    r1
65        shar    r1
66        shar    r1
67#else
68	mov	#-12, r2
69	shad	r2, r1
70#endif
71	not	r1, r1			// r1=0 means r0 = -1 to -4095
72	tst	r1, r1			// i.e. error in linux
73	bf	.Lclone_end
74.Lsyscall_error:
75	SYSCALL_ERROR_HANDLER
76.Lclone_end:
77	tst	r0, r0
78	bt	2f
79.Lpseudo_end:
80	rts
81	 nop
822:
83	/* terminate the stack frame */
84	mov	#0, r14
85
86	/* thread starts */
87	mov.l	@r15, r1
88	jsr	@r1
89	 mov.l	@(4,r15), r4
90
91	/* we are done, passing the return value through r0  */
92	mov.l	.L3, r1
93#ifdef SHARED
94	mov.l	r12, @-r15
95	sts.l	pr, @-r15
96	mov	r0, r4
97	mova	.LG, r0
98	mov.l	.LG, r12
99	add	r0, r12
100	mova	.L3, r0
101	add	r0, r1
102	jsr	@r1
103	 nop
104	lds.l	@r15+, pr
105	rts
106	 mov.l	@r15+, r12
107#else
108	jmp	@r1
109	 mov	r0, r4
110#endif
111	.align	2
112.LG:
113	.long	_GLOBAL_OFFSET_TABLE_
114.L3:
115	.long	PLTJMP(C_SYMBOL_NAME(_exit))
116
117PSEUDO_END (__clone)
118weak_alias (__clone, clone)
119