1/* Copyright (C) 1996-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 <tls.h>
25
26/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
27	     void *parent_tidptr, void *tls, void *child_tidptr) */
28
29        .text
30ENTRY (__clone)
31
32	/* Sanity check arguments.  */
33	movel	#-EINVAL, %d0
34	movel	4(%sp), %a0		/* no NULL function pointers */
35	tstl	%a0
36	jeq	SYSCALL_ERROR_LABEL
37	movel	8(%sp), %a1		/* no NULL stack pointers */
38	tstl	%a1
39	jeq	SYSCALL_ERROR_LABEL
40
41	/* Allocate space and copy the argument onto the new stack.  */
42	movel	16(%sp), -(%a1)
43
44	/* Do the system call */
45	movel	12+0(%sp), %d1		/* get flags */
46	movel	%d3, -(%a1)             /* save %d3 and get parent_tidptr */
47	movel	%d3, -(%sp)
48	cfi_adjust_cfa_offset (4)
49	cfi_rel_offset (%d3, 0)
50	movel	20+4(%sp), %d3
51	movel	%d4, -(%a1)		/* save %d4 and get child_tidptr */
52	movel	%d4, -(%sp)
53	cfi_adjust_cfa_offset (4)
54	cfi_rel_offset (%d4, 0)
55	movel	28+8(%sp), %d4
56	movel	%d5, -(%a1)             /* save %d5 and get tls */
57	movel	%d5, -(%sp)
58	cfi_adjust_cfa_offset (4)
59	cfi_rel_offset (%d5, 0)
60	movel	24+12(%sp), %d5
61	/* save %d2 and get stack pointer */
62#ifdef __mcoldfire__
63	movel	%d2, -(%a1)
64	movel	%d2, -(%sp)
65	cfi_adjust_cfa_offset (4)
66	cfi_rel_offset (%d2, 0)
67	movel	%a1, %d2
68#else
69	exg	%d2, %a1		/* save %d2 and get stack pointer */
70	cfi_register (%d2, %a1)
71#endif
72	movel	#SYS_ify (clone), %d0
73
74	/* End FDE now, because in the child the unwind info will be
75	   wrong.  */
76	cfi_endproc
77
78	trap	#0
79#ifdef __mcoldfire__
80	movel	(%sp)+, %d2
81#else
82	exg	%d2, %a1		/* restore %d2 */
83#endif
84	movel	(%sp)+, %d5             /* restore %d5, %d4 and %d3 */
85	movel	(%sp)+, %d4
86	movel	(%sp)+, %d3
87
88	tstl	%d0
89	jmi	SYSCALL_ERROR_LABEL
90	jeq	1f
91
92	rts
93
941:
95	cfi_startproc
96	cfi_undefined (pc)	/* Mark end of stack */
97	subl	%fp, %fp	/* terminate the stack frame */
98	jsr	(%a0)
99	movel	%d0, %d1
100	movel	#SYS_ify (exit), %d0
101	trap	#0
102	cfi_endproc
103
104	cfi_startproc
105PSEUDO_END (__clone)
106
107libc_hidden_def (__clone)
108weak_alias (__clone, clone)
109