1/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
2   This file is part of the GNU C Library.
3   Contributed by Richard Henderson <rth@tamu.edu>, 1996.
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   <http://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 <features.h>
23#define _ERRNO_H	1
24#include <bits/errno.h>
25#include <sys/syscall.h>
26#include <sys/regdef.h>
27
28/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */
29
30.text
31.globl  clone;
32.align 3;
33.ent  clone , 0;
34
35clone:
36	.frame $30 , 0, $26
37	.prologue 0
38
39	/* Sanity check arguments.  */
40	ldiq	v0,EINVAL
41	beq	a0,$error		/* no NULL function pointers */
42	beq	a1,$error		/* no NULL stack pointers */
43
44	/* Save the fn ptr and arg on the new stack.  */
45	subq	a1,16,a1
46	stq	a0,0(a1)
47	stq	a3,8(a1)
48
49	/* Do the system call */
50	mov	a2,a0
51	ldiq	v0,__NR_clone
52	call_pal 131
53
54	bne	a3,$error
55	beq	v0,thread_start
56
57	/* Successful return from the parent */
58	ret
59
60	/* Something bad happened -- no child created */
61$error:
62	br	gp,1f
631:	ldgp	gp,0(gp)
64	jmp	zero,__syscall_error
65
66.end clone
67
68/* Load up the arguments to the function.  Put this block of code in
69   its own function so that we can terminate the stack trace with our
70   debug info.  */
71
72	.ent thread_start
73thread_start:
74	.frame fp,0,zero,0
75	mov	zero,fp
76	.prologue 0
77
78	/* Load up the arguments.  */
79	ldq	pv,0($30)
80	ldq	a0,8($30)
81	addq	$30,16,$30
82
83	/* Call the user's function */
84	jsr	ra,(pv)
85	ldgp	gp,0(ra)
86
87	/* Call _exit rather than doing it inline for breakpoint purposes */
88	mov	v0,a0
89	jsr	ra,HIDDEN_JUMPTARGET(_exit)
90
91	/* Die horribly.  */
92	halt
93
94	.end thread_start
95