xref: /minix3/lib/libc/arch/arm/sys/__clone.S (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc/* $NetBSD: __clone.S,v 1.9 2013/11/30 20:20:42 joerg Exp $ */
22fe8fb19SBen Gras
32fe8fb19SBen Gras/*
42fe8fb19SBen Gras * Copyright (c) 2001 Christopher Gilbert
52fe8fb19SBen Gras * All rights reserved.
62fe8fb19SBen Gras *
72fe8fb19SBen Gras * 1. Redistributions of source code must retain the above copyright
82fe8fb19SBen Gras *    notice, this list of conditions and the following disclaimer.
92fe8fb19SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
102fe8fb19SBen Gras *    notice, this list of conditions and the following disclaimer in the
112fe8fb19SBen Gras *    documentation and/or other materials provided with the distribution.
122fe8fb19SBen Gras * 3. The name of the company nor the name of the author may be used to
132fe8fb19SBen Gras *    endorse or promote products derived from this software without specific
142fe8fb19SBen Gras *    prior written permission.
152fe8fb19SBen Gras *
162fe8fb19SBen Gras * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
172fe8fb19SBen Gras * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
182fe8fb19SBen Gras * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
192fe8fb19SBen Gras * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
202fe8fb19SBen Gras * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
212fe8fb19SBen Gras * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
222fe8fb19SBen Gras * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
232fe8fb19SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
242fe8fb19SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
252fe8fb19SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
262fe8fb19SBen Gras * SUCH DAMAGE.
272fe8fb19SBen Gras */
282fe8fb19SBen Gras
292fe8fb19SBen Gras#include "SYS.h"
30*84d9c625SLionel Sambuc#include <sys/errno.h>
312fe8fb19SBen Gras
322fe8fb19SBen Gras#ifdef WEAK_ALIAS
332fe8fb19SBen GrasWEAK_ALIAS(clone, __clone)
342fe8fb19SBen Gras#endif
352fe8fb19SBen Gras
362fe8fb19SBen Gras/*
372fe8fb19SBen Gras * int __clone(int (*fn)(void *), void *stack, int flags, void *arg);
382fe8fb19SBen Gras */
392fe8fb19SBen GrasENTRY(__clone)
402fe8fb19SBen Gras
412fe8fb19SBen Gras	/* test stack and function are not null */
42*84d9c625SLionel Sambuc#if defined(__thumb__) && defined(_ARM_ARCH_T2)
43*84d9c625SLionel Sambuc	cbz	r0, .Leinval
44*84d9c625SLionel Sambuc	cbz	r1, .Leinval
45*84d9c625SLionel Sambuc#elif !defined(__thumb__)
46*84d9c625SLionel Sambuc	cmp	r0, #0x00
47*84d9c625SLionel Sambuc	cmpne	r1, #0x00
482fe8fb19SBen Gras	beq	.Leinval
49*84d9c625SLionel Sambuc#else
50*84d9c625SLionel Sambuc	cmp	r0, #0x00
51*84d9c625SLionel Sambuc	beq	.Leinval
52*84d9c625SLionel Sambuc	cmp	r1, #0x00
53*84d9c625SLionel Sambuc	beq	.Leinval
54*84d9c625SLionel Sambuc#endif
552fe8fb19SBen Gras
562fe8fb19SBen Gras	/* place the func and its arg onto the child's stack */
57*84d9c625SLionel Sambuc#if !defined(__thumb__) || defined(_ARM_ARCH_T2)
582fe8fb19SBen Gras	stmfd	r1!, {r0, r3}
59*84d9c625SLionel Sambuc#else
60*84d9c625SLionel Sambuc	subs	r1, r1, #8
61*84d9c625SLionel Sambuc	stmia	r1!, {r0, r3}
62*84d9c625SLionel Sambuc#endif
632fe8fb19SBen Gras
642fe8fb19SBen Gras	/* syscall expects (flags, stack) */
652fe8fb19SBen Gras	mov	r0, r2
662fe8fb19SBen Gras
672fe8fb19SBen Gras	SYSTRAP(__clone)
68*84d9c625SLionel Sambuc#if !defined(__thumb__) || defined(_ARM_ARCH_T2)
69*84d9c625SLionel Sambuc	_INVOKE_CERROR()
70*84d9c625SLionel Sambuc#else
71*84d9c625SLionel Sambuc	bcs	.Lcerror
72*84d9c625SLionel Sambuc#endif
732fe8fb19SBen Gras
742fe8fb19SBen Gras	/*
752fe8fb19SBen Gras	 * r1 and r0 are the same as from fork:
762fe8fb19SBen Gras	 * r1 == 0 in parent process, r1 == 1 in child process.
772fe8fb19SBen Gras	 * r0 == pid of child in parent, r0 == pid of parent in child.
782fe8fb19SBen Gras	 */
792fe8fb19SBen Gras	/* if this is the parent then just return the pid */
80*84d9c625SLionel Sambuc#if defined(__thumb__)
81*84d9c625SLionel Sambuc#if defined(_ARM_ARCH_T2)
82*84d9c625SLionel Sambuc	cbz	r1, 1f
83*84d9c625SLionel Sambuc#else
84*84d9c625SLionel Sambuc	cmp	r1, #0x00
85*84d9c625SLionel Sambuc	bne	1f
86*84d9c625SLionel Sambuc#endif
87*84d9c625SLionel Sambuc	RET
88*84d9c625SLionel Sambuc1:
89*84d9c625SLionel Sambuc#else
90*84d9c625SLionel Sambuc	cmp	r1, #0x00
912fe8fb19SBen Gras	RETc(eq)
92*84d9c625SLionel Sambuc#endif
93*84d9c625SLionel Sambuc
942fe8fb19SBen Gras	/*
952fe8fb19SBen Gras	 * This is the child
962fe8fb19SBen Gras	 * load the function and arg off the stack
972fe8fb19SBen Gras	 */
98*84d9c625SLionel Sambuc	pop	{r1, r2}
992fe8fb19SBen Gras
1002fe8fb19SBen Gras	/* place arg in r0 */
1012fe8fb19SBen Gras	mov	r0, r2
1022fe8fb19SBen Gras
1032fe8fb19SBen Gras	/* call the function */
104*84d9c625SLionel Sambuc#ifdef _ARM_ARCH_5T
105*84d9c625SLionel Sambuc	blx	r1
1062fe8fb19SBen Gras#else
107*84d9c625SLionel Sambuc	/* setup return address */
108*84d9c625SLionel Sambuc	mov	lr, pc
109*84d9c625SLionel Sambuc	RETr(r1)
1102fe8fb19SBen Gras#endif
1112fe8fb19SBen Gras	/* call _exit with the returned value */
112*84d9c625SLionel Sambuc	bl	PLT_SYM(_C_LABEL(_exit))
1132fe8fb19SBen Gras
1142fe8fb19SBen Gras	/* NOTREACHED */
1152fe8fb19SBen Gras
1162fe8fb19SBen Gras	/* error handler if func or stack is NULL */
117*84d9c625SLionel Sambuc	.align	0
1182fe8fb19SBen Gras.Leinval:
119*84d9c625SLionel Sambuc	movs	r0, #EINVAL
120*84d9c625SLionel Sambuc#if !defined(__thumb__) || defined(_ARM_ARCH_T2)
121*84d9c625SLionel Sambuc	b	CERROR
122*84d9c625SLionel Sambuc#else
123*84d9c625SLionel Sambuc.Lcerror:
124*84d9c625SLionel Sambuc	push	{lr}
125*84d9c625SLionel Sambuc	bl	CERROR
126*84d9c625SLionel Sambuc	pop	{pc}
127*84d9c625SLionel Sambuc#endif
128*84d9c625SLionel SambucEND(__clone)
129