diff options
Diffstat (limited to 'libc/sysdeps/linux/frv/clone.S')
-rw-r--r-- | libc/sysdeps/linux/frv/clone.S | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/frv/clone.S b/libc/sysdeps/linux/frv/clone.S new file mode 100644 index 000000000..2e3c6b742 --- /dev/null +++ b/libc/sysdeps/linux/frv/clone.S @@ -0,0 +1,83 @@ +/* Copyright (C) 2003 Free Software Foudnation, Inc. + This file is part of the GNU C Library. + Contributed by Alexandre Oliva <aoliva@redhat.com>, 2003. + + 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> +#define _ERRNO_H 1 +#include <bits/errno.h> + + .text + .globl __clone + .type __clone,@function +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */ +__clone: + /* Sanity check arguments. */ + cmp.p gr8, gr0, icc0 + cmp gr9, gr0, icc1 + mov.p gr8, gr4 + beq icc0, #0, .Lerror + mov.p gr11, gr5 + beq icc1, #0, .Lerror + + mov.p gr10, gr8 + setlos #__NR_clone, gr7 + tra gr0,gr0 + + cmp gr8, gr0, icc0 + bgtlr icc0, #1 + beq icc0, #0, .Lthread_start + +.Lsys_error: + sethi.p #gotofffuncdeschi(__syscall_error), gr14 + setlo #gotofffuncdesclo(__syscall_error), gr14 + ldd @(gr14, gr15), gr14 + jmpl @(gr14, gr0) + +.Lerror: + setlos.p #-EINVAL, gr7 + bra .Lsys_error + +############################################################################### +# +# come here as the new thread [GR4 is fn, GR5 is arg] +# +############################################################################### +.Lthread_start: + /* Save the PIC register. */ + mov gr15, gr17 + + /* Call the user's function. */ + ldd.p @(gr4, gr0), gr14 + mov gr5, gr8 + calll @(gr14, gr0) + + /* Call _exit, rather simply inlining the syscall, such that + breakpoints work.*/ + + mov.p gr17, gr15 + call _exit + + /* Should never get here. */ + jmpl @(gr0, gr0) + .size __clone,.-__clone + +.weak clone + clone = __clone |