summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/h8300/clone.S
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps/linux/h8300/clone.S')
-rw-r--r--libc/sysdeps/linux/h8300/clone.S78
1 files changed, 78 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/h8300/clone.S b/libc/sysdeps/linux/h8300/clone.S
new file mode 100644
index 000000000..7d100b6c4
--- /dev/null
+++ b/libc/sysdeps/linux/h8300/clone.S
@@ -0,0 +1,78 @@
+/* Adapted from glibc */
+/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. */
+
+/* clone is even more special than fork as it mucks with stacks
+ and invokes a function in the right context after its all over. */
+
+#define _ERRNO_H
+#include <bits/errno.h>
+#include <sys/syscall.h>
+
+/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
+
+#ifdef __H8300H__
+ .h8300h
+#endif
+#ifdef __H8300S__
+ .h8300s
+#endif
+
+.text
+.globl _clone
+.globl ___clone
+_clone:
+___clone:
+ /* Sanity check arguments. */
+ mov.l #-EINVAL,er3
+ mov.l er0,er0 /* no NULL function pointers */
+ beq __syscall_error
+ mov.l er1,er1 /* no NULL stack pointers */
+ beq __syscall_error
+
+ /* Allocate space and copy the argument onto the new stack. */
+ mov.l @(4:16,sp),er3
+ mov.l er3,@-er1
+
+ /* Do the system call */
+ mov.l er0,er3 /* er3 = child entry */
+ mov.l er1,er0
+ mov.l er2,er1 /* er1 = flags */
+ mov.l er0,er2 /* er2 = child sp */
+ mov.l #__NR_clone,r0
+ trapa #0
+ mov.l er0,er0
+ bmi __syscall_error
+ beq thread_start
+
+ rts
+
+__syscall_error:
+ neg.l er0
+ mov.l er0,@-sp
+#if !defined(__PIC__)
+ jsr @__errno_location
+#else
+ mov.l @(__errno_location@GOTOFF,er5),er1
+ jsr @er1
+#endif
+ mov.l @sp,er1
+ mov.l er1,@er0
+ sub.l er0,er0
+ dec.l #1,er0
+
+ rts
+
+thread_start:
+ mov.l @sp+,er0 /* restore args */
+ jsr @er3
+ mov.l er0,er1
+ mov.l #__NR_exit,er0
+ trapa #0
+
+#if defined(__HAVE_ELF__)
+ .weak clone
+ clone = __clone
+#else
+ .set clone,__clone
+#endif
+