diff options
Diffstat (limited to 'libc/sysdeps/linux/m68k/clone.S')
-rw-r--r-- | libc/sysdeps/linux/m68k/clone.S | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/m68k/clone.S b/libc/sysdeps/linux/m68k/clone.S new file mode 100644 index 000000000..1f900685e --- /dev/null +++ b/libc/sysdeps/linux/m68k/clone.S @@ -0,0 +1,75 @@ +/* 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); */ + +.text +.align 4 +.type __clone,@function +.globl __clone; +__clone: + /* Sanity check arguments. */ + movel #-EINVAL, %d0 + movel 4(%sp), %d1 /* no NULL function pointers */ + movel %d1, %a0 + tstl %d1 + jeq syscall_error + movel 8(%sp), %d1 /* no NULL stack pointers */ + movel %d1, %a1 + tstl %d1 + jeq syscall_error + + /* Allocate space and copy the argument onto the new stack. */ + movel 16(%sp), -(%a1) + + /* Do the system call */ +#if 1 /* defined (CONFIG_COLDFIRE) */ + movel %d2, %d1 /* save %d2 and get stack pointer */ + movel %a1, %d2 + movel %d1, %a1 +#else + exg %d2, %a1 /* save %d2 and get stack pointer */ +#endif + movel 12(%sp), %d1 /* get flags */ + movel #__NR_clone, %d0 + trap #0 +#if 1 /* defined (CONFIG_COLDFIRE) */ + movel %d2, %d1 /* restore %d2 */ + movel %a1, %d2 + movel %d1, %a1 +#else + exg %d2, %a1 /* restore %d2 */ +#endif + + tstl %d0 + jmi syscall_error + jeq thread_start + + rts + +syscall_error: + negl %d0 + movel %d0, %sp@- + lea __errno_location-.-8, %a0 + jsr 0(%pc, %a0) + movel %d0, %a0 + movel %sp@+, %a0@ + moveq #-1, %d0 + + rts + +thread_start: + /*subl %fp, %fp*/ /* terminate the stack frame */ + jsr (%a0) + movel %d0, -(%sp) + movel #__NR_exit, %d0 + trap #0 + /*jsr exit*/ + |