summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/sysdeps/linux/microblaze/Makefile.arch4
-rw-r--r--libc/sysdeps/linux/microblaze/clone.S78
-rw-r--r--libc/sysdeps/linux/microblaze/clone.c47
-rw-r--r--libc/sysdeps/linux/microblaze/vfork.S17
4 files changed, 86 insertions, 60 deletions
diff --git a/libc/sysdeps/linux/microblaze/Makefile.arch b/libc/sysdeps/linux/microblaze/Makefile.arch
index 6f1e9fb3d..e23515ed0 100644
--- a/libc/sysdeps/linux/microblaze/Makefile.arch
+++ b/libc/sysdeps/linux/microblaze/Makefile.arch
@@ -5,5 +5,5 @@
#
# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
-CSRC-y := clone.c
-SSRC-y := setjmp.S __longjmp.S vfork.S
+CSRC-y :=
+SSRC-y := setjmp.S __longjmp.S vfork.S clone.S
diff --git a/libc/sysdeps/linux/microblaze/clone.S b/libc/sysdeps/linux/microblaze/clone.S
new file mode 100644
index 000000000..46d4fe6b4
--- /dev/null
+++ b/libc/sysdeps/linux/microblaze/clone.S
@@ -0,0 +1,78 @@
+/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ 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, 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 <sysdep.h>
+#define _ERRNO_H 1
+#include <bits/errno.h>
+
+/* int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+ pid_t *ptid, struct user_desc *tls, pid_t *ctid);
+
+ INCOMING: r5 (fn), r6 (child_stack), r7 (flags), r8 (arg), r9 (ptid)
+ r10 (tls), 28 (r1) ctid
+
+ OUTGOING:
+
+ linux: arch/microblaze/entry.S: sys_clone expects
+ r5 (flags) r6 (child stack) r7 (stack_size) r8 (ptid)r9 (ctid)
+ r10 (tls)
+*/
+
+ .text
+ENTRY (__clone)
+ addik r3,r0,-EINVAL
+ beqi r5,1f ; // Invalid func
+ beqi r6,1f ; // Invalid stack
+ addik r6,r6,-8
+ swi r5,r6,0 ; // Push fn onto child's stack
+ swi r8,r6,4 ; // Push arg for child
+ addk r5,r0,r7 ; // flags for clone() syscall
+ addk r7,r0,r0
+ addk r8,r0,r9 ; // parent tid ptr
+ lwi r9,r1,28 ; // child tid ptr
+ addik r12,r0,SYS_ify(clone)
+ brki r14,8
+ addk r0,r0,r0
+ addik r4,r0,-4095
+ cmpu r4,r4,r3
+ bgei r4,1f
+ beqi r3,L(thread_start)
+ rtsd r15,8
+ nop
+
+L(thread_start):
+ lwi r12,r1,0 ; // fn
+ lwi r5,r1,4 ; // arg
+ brald r15,r12
+ nop
+ addk r5,r0,r3
+ addik r12,r0,SYS_ify(exit)
+ brki r14,8
+ nop
+
+1: rsubk r3,r3,r0
+ rtsd r15,8
+ addik r3,r0,-1 /* delay slot. */
+
+END(__clone)
+
+libc_hidden_def (__clone)
+weak_alias (__clone,clone)
diff --git a/libc/sysdeps/linux/microblaze/clone.c b/libc/sysdeps/linux/microblaze/clone.c
deleted file mode 100644
index d92100865..000000000
--- a/libc/sysdeps/linux/microblaze/clone.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2004 Atmel Corporation
- *
- * This file is subject to the terms and conditions of the GNU Lesser General
- * Public License. See the file "COPYING.LIB" in the main directory of this
- * archive for more details.
- */
-#include <sched.h>
-#include <errno.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, ...)
-{
- int rval = -EINVAL;
- if (fn && child_stack)
- rval = INTERNAL_SYSCALL(clone, 0, 2, flags, child_stack);
-
- if (rval == 0)
- {
- int exitCode = fn(arg);
- rval = INTERNAL_SYSCALL(exit, 0, 1, exitCode);
- }
-
- return rval;
-}
-
-#ifdef __NR_clone2
-int
-__clone2(int (*fn)(void *arg), void *child_stack, size_t stack_size,
- int flags, void *arg, ...)
-{
- int rval = -EINVAL;
- if (fn && child_stack)
- {
- rval = INTERNAL_SYSCALL(clone2, 0, 3, flags, child_stack, stack_size);
- }
-
- if (rval == 0)
- {
- int exitCode = fn(arg);
- rval = INTERNAL_SYSCALL(exit, 0, 1, exitCode);
- }
-
- return rval;
-}
-#endif
diff --git a/libc/sysdeps/linux/microblaze/vfork.S b/libc/sysdeps/linux/microblaze/vfork.S
index cd6012889..cadd1167d 100644
--- a/libc/sysdeps/linux/microblaze/vfork.S
+++ b/libc/sysdeps/linux/microblaze/vfork.S
@@ -29,19 +29,14 @@ __vfork:
addi r4, r3, 125 /* minimum err value */
blti r4, 1f /* is r3 < -125? */
bri 2f /* normal return */
-1: sub r3, r3, r0 /* r3 = -r3 */
-#ifdef __PIC__
- mfs r3,rpc
- addik r3,r3,_GLOBAL_OFFSET_TABLE_+8
- lwi r3,r3,C_SYMBOL_NAME(errno)@GOT
- sw r3, r0, r3
-#else
- swi r3, r0, C_SYMBOL_NAME(errno);
-#endif
- /* state restore etc */
+
+1: rsubk r3,r3,r0
+ rtsd r15,8
+ addik r3,r0,-1 /* delay slot. */
+
2: rtsd r15, 8 /* error return */
nop
.size __vfork, .-__vfork
-weak_alias(__vfork,vfork)
+weak_alias(__vfork, vfork)
libc_hidden_def(vfork)