1!    Copyright (C) 2013 Imagination Technologies Ltd.
2
3!    Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
4
5!    clone() is even more special than fork() as it mucks with stacks
6!    and invokes a function in the right context after its all over.
7
8#include <asm/errno.h>
9#include <asm/unistd.h>
10
11#define CLONE_VM      0x00000100
12#define CLONE_THREAD  0x00010000
13
14#ifdef __PIC__
15#define __CLONE_METAG_LOAD_TP ___metag_load_tp@PLT
16#else
17#define __CLONE_METAG_LOAD_TP ___metag_load_tp
18#endif
19
20/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
21			pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
22
23	.text
24	.global	__clone
25	.type	__clone,function
26__clone:
27	! sanity check args
28	MOV	D0Re0, #-EINVAL
29	CMP	D1Ar1, #0
30	BEQ	___error
31	CMP	D0Ar2, #0
32	BEQ     ___error
33
34	! save function pointer
35	MOV D0FrT, D1Ar1
36
37	! do the system call
38	MOV	D1Ar1, D1Ar3
39	MOV	D1Ar3, D1Ar5
40	MOV	D1Ar5, D0Ar6
41	MOV	D0Ar6, D0Ar4
42	GETD	D0Ar4, [A0StP+#-4]
43
44	! new sp is already in D0Ar2
45	MOV	D1Re0, #__NR_clone
46	SWITCH	#0x440001
47	CMP	D0Re0,#0
48	! Error on -1
49	BLT	___error
50	! If non-zero we are the parent
51	MOVNE	PC, D1RtP
52	! BRKPNT
53
54	! We are the child
55	! Rearrange the function arg and call address from registers
56	MOV	D0Ar2, D0FrT
57	MOV	D1Ar1, D0Ar6
58	MOV	D1RtP, PC
59	ADD	D1RtP, D1RtP, #8
60	MOV	PC, D0Ar2
61
62	! and we are done, passing the return value D0Re0 through D1Ar1
63	MOV	D1Ar1, D0Re0
64#ifdef __PIC__
65	B	_exit@PLT
66#else
67	B	_exit
68#endif
69
70___error:
71	MOV	D1Ar1, D0Re0
72#ifdef __PIC__
73	B	___syscall_error@PLT
74#else
75	B	___syscall_error
76#endif
77	.size	__clone, .-__clone
78
79.weak    _clone
80_clone    =   __clone
81