diff options
Diffstat (limited to 'libc/sysdeps/linux')
-rw-r--r-- | libc/sysdeps/linux/sh/Makefile | 2 | ||||
-rw-r--r-- | libc/sysdeps/linux/sh/clone.S | 137 | ||||
-rw-r--r-- | libc/sysdeps/linux/sh/vfork.S | 1 |
3 files changed, 139 insertions, 1 deletions
diff --git a/libc/sysdeps/linux/sh/Makefile b/libc/sysdeps/linux/sh/Makefile index 1f7d76a70..2e37e8974 100644 --- a/libc/sysdeps/linux/sh/Makefile +++ b/libc/sysdeps/linux/sh/Makefile @@ -32,7 +32,7 @@ TARGET_MACHINE_TYPE=$(shell $(CC) -dumpmachine) CRT0=crt0.S CRT0_OBJ=$(patsubst %.S,%.o, $(CRT0)) -SSRC=setjmp.S bsd-setjmp.S bsd-_setjmp.S __longjmp.S vfork.S +SSRC=setjmp.S bsd-setjmp.S bsd-_setjmp.S __longjmp.S vfork.S clone.S SOBJS=$(patsubst %.S,%.o, $(SSRC)) CSRC=_mmap.c longjmp.c pipe.c __init_brk.c brk.c sbrk.c diff --git a/libc/sysdeps/linux/sh/clone.S b/libc/sysdeps/linux/sh/clone.S new file mode 100644 index 000000000..95ae6647c --- /dev/null +++ b/libc/sysdeps/linux/sh/clone.S @@ -0,0 +1,137 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include <asm/unistd.h> +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .text +.extern __syscall_error + +ENTRY(__clone) + /* sanity check arguments. */ + tst r4, r4 + bf/s 1f + tst r5, r5 + bf/s 1f + mov.l .L1, r1 +#ifdef SHARED + mov.l r12, @-r15 + sts.l pr, @-r15 + mov.l .LG, r12 + mova .LG, r0 + add r0, r12 + mova .L1, r0 + add r0, r1 + jsr @r1 + mov #-EINVAL, r4 + lds.l @r15+, pr + rts + mov.l @r15+, r12 +#else + jmp @r1 + mov #-EINVAL, r4 +#endif + .align 2 +.L1: + .long PLTJMP(C_SYMBOL_NAME(__syscall_error)) +1: + /* insert the args onto the new stack */ + mov.l r7, @-r5 + /* save the function pointer as the 0th element */ + mov.l r4, @-r5 + + /* do the system call */ + mov r6, r4 + mov #+__NR_clone, r3 + trapa #0x12 + mov r0, r1 + mov #-12, r2 + shad r2, r1 + not r1, r1 // r1=0 means r0 = -1 to -4095 + tst r1, r1 // i.e. error in linux + bf 2f + mov.l .L2, r1 +#ifdef SHARED + mov r0, r4 + mov.l r12, @-r15 + sts.l pr, @-r15 + mov.l .LG, r12 + mova .LG, r0 + add r0, r12 + mova .L2, r0 + add r0, r1 + jsr @r1 + nop + lds.l @r15+, pr + rts + mov.l @r15+, r12 +#else + jmp @r1 + mov r0, r4 +#endif + .align 2 +.L2: + .long PLTJMP(C_SYMBOL_NAME(__syscall_error)) + +2: + tst r0, r0 + bt 3f + rts + nop +3: + /* thread starts */ + mov.l @r15, r1 + jsr @r1 + mov.l @(4,r15), r4 + + /* we are done, passing the return value through r0 */ + mov.l .L3, r1 +#ifdef SHARED + mov.l r12, @-r15 + sts.l pr, @-r15 + mov r0, r4 + mova .LG, r0 + mov.l .LG, r12 + add r0, r12 + mova .L3, r0 + add r0, r1 + jsr @r1 + nop + lds.l @r15+, pr + rts + mov.l @r15+, r12 +#else + jmp @r1 + mov r0, r4 +#endif + .align 2 +.LG: + .long _GLOBAL_OFFSET_TABLE_ +.L3: + .long PLTJMP(C_SYMBOL_NAME(_exit)) + END(__clone) + +.globl clone; + clone = __clone diff --git a/libc/sysdeps/linux/sh/vfork.S b/libc/sysdeps/linux/sh/vfork.S index 6b20cc3bb..ef7b373aa 100644 --- a/libc/sysdeps/linux/sh/vfork.S +++ b/libc/sysdeps/linux/sh/vfork.S @@ -85,6 +85,7 @@ ENTRY (__vfork) .align 4 2: +.global __syscall_error __syscall_error: /* Store it in errno... */ mov.l .L4, r1 |