xref: /minix/lib/libc/arch/arm/sys/__clone.S (revision 84d9c625)
1/* $NetBSD: __clone.S,v 1.9 2013/11/30 20:20:42 joerg Exp $ */
2
3/*
4 * Copyright (c) 2001 Christopher Gilbert
5 * All rights reserved.
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 * 3. The name of the company nor the name of the author may be used to
13 *    endorse or promote products derived from this software without specific
14 *    prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include "SYS.h"
30#include <sys/errno.h>
31
32#ifdef WEAK_ALIAS
33WEAK_ALIAS(clone, __clone)
34#endif
35
36/*
37 * int __clone(int (*fn)(void *), void *stack, int flags, void *arg);
38 */
39ENTRY(__clone)
40
41	/* test stack and function are not null */
42#if defined(__thumb__) && defined(_ARM_ARCH_T2)
43	cbz	r0, .Leinval
44	cbz	r1, .Leinval
45#elif !defined(__thumb__)
46	cmp	r0, #0x00
47	cmpne	r1, #0x00
48	beq	.Leinval
49#else
50	cmp	r0, #0x00
51	beq	.Leinval
52	cmp	r1, #0x00
53	beq	.Leinval
54#endif
55
56	/* place the func and its arg onto the child's stack */
57#if !defined(__thumb__) || defined(_ARM_ARCH_T2)
58	stmfd	r1!, {r0, r3}
59#else
60	subs	r1, r1, #8
61	stmia	r1!, {r0, r3}
62#endif
63
64	/* syscall expects (flags, stack) */
65	mov	r0, r2
66
67	SYSTRAP(__clone)
68#if !defined(__thumb__) || defined(_ARM_ARCH_T2)
69	_INVOKE_CERROR()
70#else
71	bcs	.Lcerror
72#endif
73
74	/*
75	 * r1 and r0 are the same as from fork:
76	 * r1 == 0 in parent process, r1 == 1 in child process.
77	 * r0 == pid of child in parent, r0 == pid of parent in child.
78	 */
79	/* if this is the parent then just return the pid */
80#if defined(__thumb__)
81#if defined(_ARM_ARCH_T2)
82	cbz	r1, 1f
83#else
84	cmp	r1, #0x00
85	bne	1f
86#endif
87	RET
881:
89#else
90	cmp	r1, #0x00
91	RETc(eq)
92#endif
93
94	/*
95	 * This is the child
96	 * load the function and arg off the stack
97	 */
98	pop	{r1, r2}
99
100	/* place arg in r0 */
101	mov	r0, r2
102
103	/* call the function */
104#ifdef _ARM_ARCH_5T
105	blx	r1
106#else
107	/* setup return address */
108	mov	lr, pc
109	RETr(r1)
110#endif
111	/* call _exit with the returned value */
112	bl	PLT_SYM(_C_LABEL(_exit))
113
114	/* NOTREACHED */
115
116	/* error handler if func or stack is NULL */
117	.align	0
118.Leinval:
119	movs	r0, #EINVAL
120#if !defined(__thumb__) || defined(_ARM_ARCH_T2)
121	b	CERROR
122#else
123.Lcerror:
124	push	{lr}
125	bl	CERROR
126	pop	{pc}
127#endif
128END(__clone)
129