OSDN Git Service

Remove HAVE_ELF
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / sh / clone.S
1 /* Copyright (C) 1999, 2000 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 #define _ERRNO_H        1
25 #include <bits/errno.h>
26
27
28 #ifdef __HAVE_SHARED__ 
29 #define PLTJMP(_x)      _x##@PLT
30 #else
31 #define PLTJMP(_x)      _x
32 #endif
33
34
35 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
36
37         .text
38
39 .text
40 .align 4
41 .type   clone,@function
42 .globl  clone;
43 clone:
44         /* sanity check arguments.  */
45         tst     r4, r4
46         bt      0f
47         tst     r5, r5
48         bf/s    1f
49          mov    #+__NR_clone, r3
50 0:              
51         bra __syscall_error
52          mov    #-EINVAL, r4
53
54 1:
55         /* insert the args onto the new stack */
56         mov.l   r7, @-r5
57         /* save the function pointer as the 0th element */
58         mov.l   r4, @-r5
59         
60         /* do the system call */
61         mov     r6, r4
62         trapa   #0x12
63         mov     r0, r1
64 #ifdef __sh2__
65 // 12 arithmetic shifts for the crappy sh2, because shad doesn't exist! 
66         shar    r1
67         shar    r1
68         shar    r1
69         shar    r1
70         shar    r1
71         shar    r1
72         shar    r1
73         shar    r1
74         shar    r1
75         shar    r1
76         shar    r1
77         shar    r1
78 #else           
79         mov     #-12, r2
80         shad    r2, r1
81 #endif
82         not     r1, r1                  // r1=0 means r0 = -1 to -4095
83         tst     r1, r1                  // i.e. error in linux
84         bf/s    2f
85          tst    r0, r0
86         bra __syscall_error
87          mov    r0, r4
88
89 2:
90         bt      3f
91         rts
92          nop
93 3:
94         /* thread starts */
95         mov.l   @r15, r1
96         jsr     @r1
97          mov.l  @(4,r15), r4
98
99         /* we are done, passing the return value through r0  */
100         mov.l   .L1, r1
101 #ifdef __HAVE_SHARED__ 
102         mov.l   r12, @-r15
103         sts.l   pr, @-r15
104         mov     r0, r4
105         mova    .LG, r0  /* .LG from syscall_error.S */
106         mov.l   .LG, r12
107         add     r0, r12
108         mova    .L1, 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 .L1:
121         .long   PLTJMP( HIDDEN_JUMPTARGET(_exit))
122 .size clone,.-clone;
123
124 #include "syscall_error.S"