OSDN Git Service

Replace FSF snail mail address with URLs
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / arm / clone.S
index 6672c7d..33b1041 100644 (file)
@@ -13,9 +13,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 /* clone() is even more special than fork() as it mucks with stacks
    and invokes a function in the right context after its all over.  */
 #include <features.h>
 #include <bits/errno.h>
 #include <sys/syscall.h>
+#include <bits/arm_asm.h>
 
-#ifdef __NR_clone
+#if defined(__NR_clone)
 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
 
 .text
-.global clone
-.type clone,%function
-.align 4
-clone:
+.global __clone
+.type __clone,%function
+.align 2
+#if defined(THUMB1_ONLY)
+.thumb_func
+__clone:
        @ sanity check args
        cmp     r0, #0
+       beq     __einval
+       cmp     r1, #0
+       beq     __einval
+
+       @ insert the args onto the new stack
+       sub     r1, r1, #8
+       str     r3, [r1, #4]
+       @ save the function pointer as the 0th element
+       str     r0, [r1]
+
+       @ do the system call
+       @ get flags
+       mov     r0, r2
+       @ new sp is already in r1
+       @ load remaining arguments off the stack
+       stmfd   sp!, {r4}
+       ldr     r2, [sp, #4]
+       ldr     r3, [sp, #8]
+       ldr     r4, [sp, #12]
+       DO_CALL (clone)
+       movs    a1, a1
+       blt     __error
+       ldmnefd sp!, {r4}
+       beq     1f
+       bx      lr
+1:
+
+       @ pick the function arg and call address off the stack and execute
+       ldr     r0, [sp, #4]
+       ldr     r1, [sp]
+       bl      2f      @ blx r1
+
+       @ and we are done, passing the return value through r0
+       bl      HIDDEN_JUMPTARGET(_exit)
+       @ Should never return
+       b       .
+
+2:
+       bx      r1
+
+__einval:
+       ldr     r0, =-EINVAL
+__error:
+       push    {r3, lr}
+       bl      __syscall_error
+       POP_RET
+.pool
+#else
+__clone:
+       @ sanity check args
+       cmp     r0, #0
+       IT(te, ne)
        cmpne   r1, #0
        moveq   r0, #-EINVAL
        beq     __error
@@ -49,10 +103,21 @@ clone:
        @ get flags
        mov     r0, r2
        @ new sp is already in r1
+       @ load remaining arguments off the stack
+       stmfd   sp!, {r4}
+       ldr     r2, [sp, #4]
+       ldr     r3, [sp, #8]
+       ldr     r4, [sp, #12]
        DO_CALL (clone)
        movs    a1, a1
        blt     __error
-       movne    pc, lr
+       ldmnefd sp!, {r4}
+       IT(t, ne)
+#if defined(__USE_BX__)
+       bxne    lr
+#else
+       movne   pc, lr
+#endif
 
        @ pick the function arg and call address off the stack and execute
        ldr     r0, [sp, #4]
@@ -64,7 +129,9 @@ clone:
 
 __error:
        b       __syscall_error
+#endif
 
-.size clone,.-clone
+.size __clone,.-__clone
+weak_alias(__clone, clone)
 
 #endif