OSDN Git Service

423a6c2f1b1f20acdc2eb36d3b070cedd72627c3
[uclinux-h8/uClinux-dist.git] / uClibc / libc / sysdeps / linux / sh / clone.S
1 /* Copyright (C) 1999, 2000, 2003, 2004, 2007 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
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.
8
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.
13
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.  */
18
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.  */
21
22 #include <features.h>
23 #include <asm/unistd.h>
24 #include <sysdep.h>
25 #define _ERRNO_H        1
26 #include <bits/errno.h>
27 #ifdef RESET_PID
28 #include <tcb-offsets.h>
29 #endif
30 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
31              pid_t *ptid, void *tls, pid_t *ctid); */
32
33         .text
34 ENTRY(__clone)
35         /* sanity check arguments.  */
36         tst     r4, r4
37         bt/s    0f
38          tst    r5, r5
39         bf      1f
40 0:
41         bra     .Lsyscall_error
42          mov    #-EINVAL,r0
43 1:
44         /* insert the args onto the new stack */
45         mov.l   r7, @-r5
46         /* save the function pointer as the 0th element */
47         mov.l   r4, @-r5
48
49         /* do the system call */
50         mov     r6, r4
51         mov.l   @r15, r6
52         mov.l   @(8,r15), r7
53         mov.l   @(4,r15), r0
54         mov     #+SYS_ify(clone), r3
55         trapa   #0x15
56         mov     r0, r1
57         mov     #-12, r2
58         shad    r2, r1
59         not     r1, r1                  // r1=0 means r0 = -1 to -4095
60         tst     r1, r1                  // i.e. error in linux
61         bf      .Lclone_end
62 .Lsyscall_error:
63         SYSCALL_ERROR_HANDLER
64 .Lclone_end:
65         tst     r0, r0
66         bt      2f
67 .Lpseudo_end:
68         rts
69          nop
70 2:
71         /* terminate the stack frame */
72         mov     #0, r14
73 #ifdef RESET_PID
74         mov     r4, r0
75         shlr16  r0
76         tst     #1, r0                  // CLONE_THREAD = (1 << 16)
77         bf/s    4f
78          mov    r4, r0
79         /* new pid */
80         shlr8   r0
81         tst     #1, r0                  // CLONE_VM = (1 << 8)
82         bf/s    3f
83          mov    #-1, r0
84         mov     #+SYS_ify(getpid), r3
85         trapa   #0x15
86 3:
87         stc     gbr, r1
88         mov.w   .Lpidoff, r2
89         add     r1, r2
90         mov.l   r0, @r2
91         mov.w   .Ltidoff, r2
92         add     r1, r2
93         mov.l   r0, @r2
94 4:
95 #endif
96         /* thread starts */
97         mov.l   @r15, r1
98         jsr     @r1
99          mov.l  @(4,r15), r4
100
101         /* we are done, passing the return value through r0  */
102         mov.l   .L3, r1
103 #ifdef SHARED
104         mov.l   r12, @-r15
105         sts.l   pr, @-r15
106         mov     r0, r4
107         mova    .LG, r0
108         mov.l   .LG, r12
109         add     r0, r12
110         mova    .L3, r0
111         add     r0, r1
112         jsr     @r1
113          nop
114         lds.l   @r15+, pr
115         rts
116          mov.l  @r15+, r12
117 #else
118         jmp     @r1
119          mov    r0, r4
120 #endif
121         .align  2
122 .LG:
123         .long   _GLOBAL_OFFSET_TABLE_
124 .L3:
125         .long   PLTJMP(C_SYMBOL_NAME(_exit))
126 #ifdef RESET_PID
127 .Lpidoff:
128         .word   PID - TLS_PRE_TCB_SIZE
129 .Ltidoff:
130         .word   TID - TLS_PRE_TCB_SIZE
131 #endif
132 PSEUDO_END (__clone)
133
134 weak_alias (__clone, clone)