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