2.9
[glibc/nacl-glibc.git] / sysdeps / unix / sysv / linux / sh / clone.S
blobf892c475dded0758847b2f29bccecb8fcf9d3b45
1 /* Copyright (C) 1999, 2000, 2003, 2004, 2007 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
19 /* clone() is even more special than fork() as it mucks with stacks
20    and invokes a function in the right context after its all over.  */
22 #include <sysdep.h>
23 #define _ERRNO_H        1
24 #include <bits/errno.h>
25 #ifdef RESET_PID
26 #include <tcb-offsets.h>
27 #endif
28 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
29              pid_t *ptid, void *tls, pid_t *ctid); */
31         .text
32 ENTRY(__clone)
33         /* sanity check arguments.  */
34         tst     r4, r4
35         bt/s    0f
36          tst    r5, r5
37         bf      1f
39         bra     .Lsyscall_error
40          mov    #-EINVAL,r0
42         /* insert the args onto the new stack */
43         mov.l   r7, @-r5
44         /* save the function pointer as the 0th element */
45         mov.l   r4, @-r5
47         /* do the system call */
48         mov     r6, r4
49         mov.l   @r15, r6
50         mov.l   @(8,r15), r7
51         mov.l   @(4,r15), r0
52         mov     #+SYS_ify(clone), r3
53         trapa   #0x15
54         mov     r0, r1
55         mov     #-12, r2
56         shad    r2, r1
57         not     r1, r1                  // r1=0 means r0 = -1 to -4095
58         tst     r1, r1                  // i.e. error in linux
59         bf      .Lclone_end
60 .Lsyscall_error:        
61         SYSCALL_ERROR_HANDLER
62 .Lclone_end:
63         tst     r0, r0
64         bt      2f
65 .Lpseudo_end:
66         rts
67          nop
69         /* terminate the stack frame */
70         mov     #0, r14
71 #ifdef RESET_PID
72         mov     r4, r0
73         shlr16  r0
74         tst     #1, r0                  // CLONE_THREAD = (1 << 16)
75         bf/s    4f
76          mov    r4, r0
77         /* new pid */
78         shlr8   r0
79         tst     #1, r0                  // CLONE_VM = (1 << 8)
80         bf/s    3f
81          mov    #-1, r0
82         mov     #+SYS_ify(getpid), r3
83         trapa   #0x15
85         stc     gbr, r1
86         mov.w   .Lpidoff, r2
87         add     r1, r2
88         mov.l   r0, @r2 
89         mov.w   .Ltidoff, r2
90         add     r1, r2
91         mov.l   r0, @r2 
93 #endif
94         /* thread starts */
95         mov.l   @r15, r1
96         jsr     @r1
97          mov.l  @(4,r15), r4
99         /* we are done, passing the return value through r0  */
100         mov.l   .L3, r1
101 #ifdef SHARED
102         mov.l   r12, @-r15
103         sts.l   pr, @-r15
104         mov     r0, r4
105         mova    .LG, r0
106         mov.l   .LG, r12
107         add     r0, r12
108         mova    .L3, r0
109         add     r0, r1
110         jsr     @r1
111          nop
112         lds.l   @r15+, pr
113         rts
114          mov.l  @r15+, r12
115 #else
116         jmp     @r1
117          mov    r0, r4
118 #endif
119         .align  2
120 .LG:
121         .long   _GLOBAL_OFFSET_TABLE_
122 .L3:
123         .long   PLTJMP(C_SYMBOL_NAME(_exit))
124 #ifdef RESET_PID
125 .Lpidoff:
126         .word   PID - TLS_PRE_TCB_SIZE
127 .Ltidoff:
128         .word   TID - TLS_PRE_TCB_SIZE
129 #endif
130 PSEUDO_END (__clone)
132 weak_alias (__clone, clone)