(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / unix / sysv / linux / mips / clone.S
blob043f5921cbddf7886aeb342acaadb99cd2084c85
1 /* Copyright (C) 1996, 1997, 2000, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ralf Baechle <ralf@linux-mips.org>, 1996.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 /* clone() is even more special than fork() as it mucks with stacks
21    and invokes a function in the right context after its all over.  */
23 #include <sys/asm.h>
24 #include <sysdep.h>
25 #define _ERRNO_H        1
26 #include <bits/errno.h>
28 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */
30         .text
31 LOCALSZ= 1
32 FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
33 GPOFF= FRAMESZ-(1*SZREG)
34 NESTED(__clone,4*SZREG,sp)
35 #ifdef __PIC__
36         SETUP_GP
37 #endif
38         PTR_SUBU sp, FRAMESZ
39         SETUP_GP64 (GPOFF, __clone)
40 #ifdef __PIC__
41         SAVE_GP (GPOFF)
42 #endif
43 #ifdef PROF
44         .set            noat
45         move            $1,ra
46         jal             _mcount
47         .set            at
48 #endif
51         /* Sanity check arguments.  */
52         li              v0,EINVAL
53         beqz            a0,L(error)     /* No NULL function pointers.  */
54         beqz            a1,L(error)     /* No NULL stack pointers.  */
56         PTR_SUBU        a1,32           /* Reserve argument save space.  */
57         PTR_S           a0,0(a1)        /* Save function pointer.  */
58         PTR_S           a3,PTRSIZE(a1)  /* Save argument pointer.  */
61         /* Do the system call */
62         move            a0,a2
63         li              v0,__NR_clone
64         syscall
66         bnez            a3,L(error)
67         beqz            v0,L(thread_start)
69         /* Successful return from the parent */
70         RESTORE_GP64
71         PTR_ADDU        sp, FRAMESZ
72         ret
74         /* Something bad happened -- no child created */
75 L(error):
76 #ifdef __PIC__
77         PTR_LA          t9,__syscall_error
78         RESTORE_GP64
79         PTR_ADDU        sp, FRAMESZ
80         jr              t9
81 #else
82         RESTORE_GP64
83         PTR_ADDU        sp, FRAMESZ
84         j               __syscall_error
85 #endif
86         END(__clone)
88 /* Load up the arguments to the function.  Put this block of code in
89    its own function so that we can terminate the stack trace with our
90    debug info.  */
92 ENTRY(__thread_start)
93 L(thread_start):
94         /* cp is already loaded.  */
95         SAVE_GP (GPOFF)
96         /* The stackframe has been created on entry of clone().  */
97         /* Restore the arg for user's function.  */
98         PTR_L           t9,0(sp)        /* Function pointer.  */
99         PTR_L           a0,PTRSIZE(sp)  /* Argument pointer.  */
101         /* Call the user's function.  */
102         jal             t9
104         /* Call _exit rather than doing it inline for breakpoint purposes.  */
105         move            a0,v0
106 #ifdef __PIC__
107         PTR_LA          t9,_exit
108         jalr            t9
109 #else
110         jal             _exit
111 #endif
112         END(__thread_start)
114 weak_alias(__clone, clone)