1/* Copyright (C) 1999-2022 Free Software Foundation, Inc.
2   This file is part of the GNU C Library.
3
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.
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
12   Lesser General Public License for more details.
13
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/>.  */
17
18/* clone() is even more special than fork() as it mucks with stacks
19   and invokes a function in the right context after its all over.  */
20
21#include <sysdep.h>
22#define _ERRNO_H	1
23#include <bits/errno.h>
24#include <tcb-offsets.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	mov	#-12, r2
54	shad	r2, r1
55	not	r1, r1			// r1=0 means r0 = -1 to -4095
56	tst	r1, r1			// i.e. error in linux
57	bf	.Lclone_end
58.Lsyscall_error:
59	SYSCALL_ERROR_HANDLER
60.Lclone_end:
61	tst	r0, r0
62	bt	2f
63.Lpseudo_end:
64	rts
65	 nop
662:
67	/* terminate the stack frame */
68	mov	#0, r14
69
70	/* thread starts */
71	mov.l	@r15, r1
72	jsr	@r1
73	 mov.l	@(4,r15), r4
74
75	/* we are done, passing the return value through r0  */
76	mov     r0, r4
77	mov	#+SYS_ify(exit), r3
78	trapa	#0x15
79	.align	2
80.LG:
81	.long	_GLOBAL_OFFSET_TABLE_
82.L3:
83	.long	PLTJMP(C_SYMBOL_NAME(_exit))
84PSEUDO_END (__clone)
85
86libc_hidden_def (__clone)
87weak_alias (__clone, clone)
88