Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / sh / clone.S
blob62a597e0deef21ac1f3dd955376e28b862a16f3a
1 /* Copyright (C) 1999-2015 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, see
16    <http://www.gnu.org/licenses/>.  */
18 /* clone() is even more special than fork() as it mucks with stacks
19    and invokes a function in the right context after its all over.  */
21 #include <sysdep.h>
22 #define _ERRNO_H        1
23 #include <bits/errno.h>
24 #include <tcb-offsets.h>
26 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
27              pid_t *ptid, void *tls, pid_t *ctid); */
29         .text
30 ENTRY(__clone)
31         /* sanity check arguments.  */
32         tst     r4, r4
33         bt/s    0f
34          tst    r5, r5
35         bf      1f
37         bra     .Lsyscall_error
38          mov    #-EINVAL,r0
40         /* insert the args onto the new stack */
41         mov.l   r7, @-r5
42         /* save the function pointer as the 0th element */
43         mov.l   r4, @-r5
45         /* do the system call */
46         mov     r6, r4
47         mov.l   @r15, r6
48         mov.l   @(8,r15), r7
49         mov.l   @(4,r15), r0
50         mov     #+SYS_ify(clone), r3
51         trapa   #0x15
52         mov     r0, r1
53         mov     #-12, r2
54         shad    r2, r1
55         not     r1, r1                  // r1=0 means r0 = -1 to -4095
56         tst     r1, r1                  // i.e. error in linux
57         bf      .Lclone_end
58 .Lsyscall_error:
59         SYSCALL_ERROR_HANDLER
60 .Lclone_end:
61         tst     r0, r0
62         bt      2f
63 .Lpseudo_end:
64         rts
65          nop
67         /* terminate the stack frame */
68         mov     #0, r14
69         mov     r4, r0
70         shlr16  r0
71         tst     #1, r0                  // CLONE_THREAD = (1 << 16)
72         bf/s    4f
73          mov    r4, r0
74         /* new pid */
75         shlr8   r0
76         tst     #1, r0                  // CLONE_VM = (1 << 8)
77         bf/s    3f
78          mov    #-1, r0
79         mov     #+SYS_ify(getpid), r3
80         trapa   #0x15
82         stc     gbr, r1
83         mov.w   .Lpidoff, r2
84         add     r1, r2
85         mov.l   r0, @r2
86         mov.w   .Ltidoff, r2
87         add     r1, r2
88         mov.l   r0, @r2
90         /* thread starts */
91         mov.l   @r15, r1
92         jsr     @r1
93          mov.l  @(4,r15), r4
95         /* we are done, passing the return value through r0  */
96         mov.l   .L3, r1
97 #ifdef SHARED
98         mov.l   r12, @-r15
99         sts.l   pr, @-r15
100         mov     r0, r4
101         mova    .LG, r0
102         mov.l   .LG, r12
103         add     r0, r12
104         mova    .L3, r0
105         add     r0, r1
106         jsr     @r1
107          nop
108         lds.l   @r15+, pr
109         rts
110          mov.l  @r15+, r12
111 #else
112         jmp     @r1
113          mov    r0, r4
114 #endif
115         .align  2
116 .LG:
117         .long   _GLOBAL_OFFSET_TABLE_
118 .L3:
119         .long   PLTJMP(C_SYMBOL_NAME(_exit))
120 .Lpidoff:
121         .word   PID - TLS_PRE_TCB_SIZE
122 .Ltidoff:
123         .word   TID - TLS_PRE_TCB_SIZE
124 PSEUDO_END (__clone)
126 weak_alias (__clone, clone)