Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / unix / sysv / linux / arm / clone.S
blob44286a5cd0b7196259038d2881bf164170841022
1 /* Copyright (C) 1996-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Pat Beirne <patb@corelcomputer.com>
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, see
17    <http://www.gnu.org/licenses/>.  */
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>
26 #define CLONE_VM      0x00000100
27 #define CLONE_THREAD  0x00010000
29 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
30              pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
32         .text
33 ENTRY(__clone)
34         @ sanity check args
35         cmp     r0, #0
36         ite     ne
37         cmpne   r1, #0
38         moveq   r0, #-EINVAL
39         beq     PLTJMP(syscall_error)
41         @ insert the args onto the new stack
42         str     r3, [r1, #-4]!
43         str     r0, [r1, #-4]!
45         @ do the system call
46         @ get flags
47         mov     r0, r2
48 #ifdef RESET_PID
49         mov     ip, r2
50 #endif
51         @ new sp is already in r1
52         push    {r4, r7}
53         cfi_adjust_cfa_offset (8)
54         cfi_rel_offset (r4, 0)
55         cfi_rel_offset (r7, 4)
56         ldr     r2, [sp, #8]
57         ldr     r3, [sp, #12]
58         ldr     r4, [sp, #16]
59         ldr     r7, =SYS_ify(clone)
60         swi     0x0
61         cfi_endproc
62         cmp     r0, #0
63         beq     1f
64         pop     {r4, r7}
65         blt     PLTJMP(C_SYMBOL_NAME(__syscall_error))
66         RETINSTR(, lr)
68         cfi_startproc
69 PSEUDO_END (__clone)
72         .fnstart
73         .cantunwind
74 #ifdef RESET_PID
75         tst     ip, #CLONE_THREAD
76         bne     3f
77         GET_TLS (lr)
78         mov     r1, r0
79         tst     ip, #CLONE_VM
80         ldr     r7, =SYS_ify(getpid)
81         ite     ne
82         movne   r0, #-1
83         swieq   0x0
84         NEGOFF_ADJ_BASE (r1, TID_OFFSET)
85         str     r0, NEGOFF_OFF1 (r1, TID_OFFSET)
86         str     r0, NEGOFF_OFF2 (r1, PID_OFFSET, TID_OFFSET)
88 #endif
89         @ pick the function arg and call address off the stack and execute
90         ldr     r0, [sp, #4]
91 #if defined(__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)
92         ldr     ip, [sp], #8
93         mov     lr, pc
94         bx      ip
95 #else
96         ldr     lr, [sp], #8
97         blx     lr
98 #endif
100         @ and we are done, passing the return value through r0
101         b       PLTJMP(HIDDEN_JUMPTARGET(_exit))
103         .fnend
105 weak_alias (__clone, clone)