summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/metag/clone.S
diff options
context:
space:
mode:
authorMarkos Chandras <markos.chandras@imgtec.com>2010-11-18 14:58:01 +0000
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2013-03-14 22:47:08 +0100
commitdaecc9a410a6f23d80daf8ce3afd280fea329e63 (patch)
tree8d603dd538809431cc01b9e656c827d1f0709052 /libc/sysdeps/linux/metag/clone.S
parent20221281b3d67880439cd1d16c151f4528d034fb (diff)
metag: Add NPTL support
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Diffstat (limited to 'libc/sysdeps/linux/metag/clone.S')
-rw-r--r--libc/sysdeps/linux/metag/clone.S50
1 files changed, 43 insertions, 7 deletions
diff --git a/libc/sysdeps/linux/metag/clone.S b/libc/sysdeps/linux/metag/clone.S
index 8fff56710..d9d836338 100644
--- a/libc/sysdeps/linux/metag/clone.S
+++ b/libc/sysdeps/linux/metag/clone.S
@@ -8,7 +8,17 @@
#include <asm/errno.h>
#include <asm/unistd.h>
-/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
+#define CLONE_VM 0x00000100
+#define CLONE_THREAD 0x00010000
+
+#ifdef __PIC__
+#define __CLONE_METAG_LOAD_TP ___metag_load_tp@PLT
+#else
+#define __CLONE_METAG_LOAD_TP ___metag_load_tp
+#endif
+
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+ pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
.text
.global __clone
@@ -25,8 +35,12 @@ __clone:
MOV D0FrT, D1Ar1
! do the system call
- ! get flags
MOV D1Ar1, D1Ar3
+ MOV D1Ar3, D1Ar5
+ MOV D1Ar5, D0Ar6
+ MOV D0Ar6, D0Ar4
+ GETD D0Ar4, [A0StP+#-4]
+
! new sp is already in D0Ar2
MOV D1Re0, #__NR_clone
SWITCH #0x440001
@@ -38,14 +52,36 @@ __clone:
! BRKPNT
! We are the child
- ! pick the function arg and call address off the stack and execute
- MOV D0Ar2, D0FrT
- MOV D1Ar1, D0Ar4
- MOV D1RtP, PC
+#ifdef RESET_PID
+ SETL [A0StP++], D0FrT, D1RtP
+ MOVT D0FrT, #HI(CLONE_THREAD)
+ ADD D0FrT, D0FrT, #LO(CLONE_THREAD)
+ ANDS D0FrT, D0FrT, D1Ar1
+ BNZ 3f
+ MOVT D0FrT, #HI(CLONE_VM)
+ ADD D0FrT, D0FrT, #LO(CLONE_VM)
+ ANDS D0FrT, D0FrT, D1Ar1
+ BZ 1f
+ MOV D1Ar1, #-1
+ BA 2f
+1: MOV D1Re0, #__NR_getpid
+ SWITCH #0x440001
+ MOV D1Ar1, D0Re0
+2: CALLR D1RtP, __CLONE_METAG_LOAD_TP
+ SUB D0Re0, D0Re0, #TLS_PRE_TCB_SIZE
+ SETD [D0Re0 + #PID], D1Ar1
+ SETD [D0Re0 + #TID], D1Ar1
+3: GETL D0FrT, D1RtP, [--A0StP]
+#endif
+ ! Rearrange the function arg and call address from registers
+ MOV D0Ar2, D0FrT
+ MOV D1Ar1, D0Ar6
+ MOV D1RtP, PC
ADD D1RtP, D1RtP, #8
MOV PC, D0Ar2
- ! and we are done, passing the return value through D0Re0
+ ! and we are done, passing the return value D0Re0 through D1Ar1
+ MOV D1Ar1, D0Re0
#ifdef __PIC__
B _exit@PLT
#else