1/* Wrapper around clone system call.  C-SKY ABIV2 version.
2   Copyright (C) 2018-2021 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4
5   The GNU C Library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   The GNU C Library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with the GNU C Library.  If not, see
17   <https://www.gnu.org/licenses/>.  */
18
19/* clone() is even more special than fork() as it mucks with stacks
20   and invokes a function in the right context after its all over.  */
21
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, struct user_desc *tls, pid_t *ctid) */
28
29        .text
30ENTRY (__clone)
31	/* Sanity check arguments.  */
32	cmpnei	a0, 0		/* No NULL function pointers.  */
33	bf	__error_arg
34	cmpnei	a1, 0		/* No NULL stack pointers.  */
35	bf	__error_arg
36
37	subi	a1, 8
38	stw	a0, (a1, 0)	/* Insert the function into the new stack.  */
39	stw	a3, (a1, 4)	/* Insert the args into the new stack.  */
40
41	mov	t1, r7		/* Save r7.  */
42	mov	t2, r4		/* Save r4.  */
43
44	/* The syscall expects the args to be in different slots.  */
45	mov	a0, a2
46	ldw	a2, (sp, 0)
47	ldw	a3, (sp, 8)
48	ldw	r4, (sp, 4)
49	lrw	r7, __NR_clone
50	trap	0
51
52	mov	r7, t1		/* Restore r7.  */
53	mov	r4, t2		/* Restore r4.  */
54	btsti	a0, 31		/* Check if return is less than zero.  */
55	bt	__do_syscall_error
56	cmpnei	a0, 0
57	bf	__thread_start
58	rts
59
60__error_arg:
61	lrw	a0, -EINVAL
62
63__do_syscall_error:
64#ifdef __PIC__
65	subi	sp, 8
66	stw	gb, (sp, 0)
67	stw	r15, (sp, 4)
68	grs	gb, .Lgetpc
69.Lgetpc:
70	lrw	t0, .Lgetpc@GOTPC
71	addu	gb, gb, t0
72	lrw	t0, __syscall_error@PLT
73	ldr.w	t0, (gb, t0 << 0)
74	jsr	t0
75	ldw	gb, (sp, 0)
76	ldw	r15, (sp, 4)
77	addi	sp, 8
78#else
79	jmpi	__syscall_error
80#endif /* __PIC__ */
81	rts
82PSEUDO_END (__clone)
83
84ENTRY (__thread_start)
85	.cfi_label .Ldummy
86	cfi_undefined (lr)
87	ldw	a0, (sp, 4)	/* Restore args from new sp.  */
88	ldw	a1, (sp, 0)	/* Restore function from new sp.  */
89	addi	sp, 8
90	jsr	a1
91
92	/* exit */
93	lrw	r7, __NR_exit
94	trap	0
95END (__thread_start)
96
97libc_hidden_def (__clone)
98weak_alias (__clone, clone)
99