diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/sparc64/clone.S')
-rw-r--r-- | sysdeps/unix/sysv/linux/sparc64/clone.S | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/sparc64/clone.S b/sysdeps/unix/sysv/linux/sparc64/clone.S new file mode 100644 index 0000000000..fe38bf4ab7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc64/clone.S @@ -0,0 +1,89 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@tamu.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. 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/errno.h> +#include <asm/unistd.h> + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .text + .align 4 + .globl __libc_clone + .type __libc_clone,@function + .weak clone + __clone = __libc_clone + clone = __libc_clone + +__libc_clone: + save %sp,-160,%sp + + /* sanity check arguments */ + brz,pn %i0, 99f + mov %i0, %l0 /* save fn */ + brz,pn %i1, 99f + mov %i3, %l3 /* save arg */ + + /* Do the system call */ + mov %i1, %o1 + mov %i2, %o0 + set __NR_clone, %g1 + ta 0x11 + bcs,pn %xcc, 99f + nop + brnz %o0, __thread_start + mov %o0, %i0 + ret + restore +99: +#ifdef PIC + rd %pc, %g1 + sethi %hi(_GLOBAL_OFFSET_TABLE_-(99b-.)), %l7 + or %l7, %lo(_GLOBAL_OFFSET_TABLE_-(99b-.)), %l7 + add %l7, %g1, %l7 + set EINVAL, %i0 + sethi %hi(errno), %g2 + or %g2, %lo(errno), %g2 + st %i0, [%l7+%g2] +#else + sethi %hi(errno), %g2 + add %g2, %g4, %g2 + set EINVAL, %i0 + st %i0, [%g2+%lo(errno)] +#endif +#ifdef _LIBC_REENTRANT + call __errno_location + nop + st %i0, [%o0] +#endif + mov -1,%i0 + ret + restore + .size __libc_clone,.-__libc_clone + + .type __thread_start,@function +__thread_start: + mov %g0, %fp /* terminate backtrace */ + sub %sp, 6*8, %sp /* provide arg storage */ + call %l0 + mov %l3,%o0 + call _exit,0 + nop + .size __thread_start,.-__thread_start |