Browse Source

microblaze: add NPTL/TLS support from GNU libc

Not perfect, but a starting point.
Some tests of the test suite are failing.
Waldemar Brodkorb 7 years ago
parent
commit
191739597c
33 changed files with 1394 additions and 100 deletions
  1. 0 1
      extra/Configs/Config.in
  2. 31 24
      include/elf.h
  3. 8 0
      ldso/ldso/microblaze/dl-debug.h
  4. 0 3
      ldso/ldso/microblaze/dl-startup.h
  5. 14 14
      ldso/ldso/microblaze/dl-sysdep.h
  6. 12 10
      ldso/ldso/microblaze/elfinterp.c
  7. 1 1
      libc/sysdeps/linux/microblaze/Makefile.arch
  8. 18 0
      libc/sysdeps/linux/microblaze/__syscall_error.c
  9. 1 2
      libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h
  10. 8 9
      libc/sysdeps/linux/microblaze/clone.S
  11. 0 6
      libc/sysdeps/linux/microblaze/jmpbuf-offsets.h
  12. 25 0
      libc/sysdeps/linux/microblaze/jmpbuf-unwind.h
  13. 81 2
      libc/sysdeps/linux/microblaze/sysdep.h
  14. 30 28
      libc/sysdeps/linux/microblaze/vfork.S
  15. 4 0
      libpthread/nptl/sysdeps/microblaze/Makefile.arch
  16. 26 0
      libpthread/nptl/sysdeps/microblaze/dl-tls.h
  17. 36 0
      libpthread/nptl/sysdeps/microblaze/libc-tls.c
  18. 62 0
      libpthread/nptl/sysdeps/microblaze/pthread_spin_lock.c
  19. 27 0
      libpthread/nptl/sysdeps/microblaze/pthread_spin_trylock.c
  20. 40 0
      libpthread/nptl/sysdeps/microblaze/pthreaddef.h
  21. 11 0
      libpthread/nptl/sysdeps/microblaze/tcb-offsets.sym
  22. 159 0
      libpthread/nptl/sysdeps/microblaze/tls.h
  23. 13 0
      libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/Makefile
  24. 8 0
      libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/Makefile.arch
  25. 181 0
      libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/bits/pthreadtypes.h
  26. 32 0
      libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/bits/semaphore.h
  27. 4 0
      libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/clone.S
  28. 22 0
      libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/createthread.c
  29. 29 0
      libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/fork.c
  30. 278 0
      libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/lowlevellock.h
  31. 89 0
      libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/pthread_once.c
  32. 139 0
      libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/sysdep-cancel.h
  33. 5 0
      libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/vfork.S

+ 0 - 1
extra/Configs/Config.in

@@ -521,7 +521,6 @@ config UCLIBC_HAS_THREADS_NATIVE
 		   !TARGET_hppa && \
 		   !TARGET_ia64 && \
 		   !TARGET_m68k && \
-		   !TARGET_microblaze && \
 		   !TARGET_nds32 && \
 		   !TARGET_nios2 && \
 		   !TARGET_or1k && \

+ 31 - 24
include/elf.h

@@ -3234,30 +3234,37 @@ typedef Elf32_Addr Elf32_Conflict;
 
 #define DT_C6000_NUM    4
 
-/* microblaze specific relocs */
-#define R_MICROBLAZE_NONE 0
-#define R_MICROBLAZE_32 1
-#define R_MICROBLAZE_32_PCREL 2
-#define R_MICROBLAZE_64_PCREL 3
-#define R_MICROBLAZE_32_PCREL_LO 4
-#define R_MICROBLAZE_64 5
-#define R_MICROBLAZE_32_LO 6
-#define R_MICROBLAZE_SRO32 7
-#define R_MICROBLAZE_SRW32 8
-#define R_MICROBLAZE_64_NONE 9
-#define R_MICROBLAZE_32_SYM_OP_SYM 10
-#define R_MICROBLAZE_GNU_VTINHERIT 11
-#define R_MICROBLAZE_GNU_VTENTRY 12
-#define R_MICROBLAZE_GOTPC_64 13  /* PC-relative GOT offset */
-#define R_MICROBLAZE_GOT_64 14  /* GOT entry offset */
-#define R_MICROBLAZE_PLT_64 15  /* PLT offset (PC-relative  */
-#define R_MICROBLAZE_REL 16  /* adjust by program base */
-#define R_MICROBLAZE_JUMP_SLOT 17  /* create PLT entry */
-#define R_MICROBLAZE_GLOB_DAT 18  /* create GOT entry */
-#define R_MICROBLAZE_GOTOFF_64 19  /* offset relative to GOT */
-#define R_MICROBLAZE_GOTOFF_32 20  /* offset relative to GOT */
-#define R_MICROBLAZE_COPY 21  /* runtime copy */
-#define R_MICROBLAZE_NUM 22
+/* MicroBlaze relocations */
+#define R_MICROBLAZE_NONE		0	/* No reloc. */
+#define R_MICROBLAZE_32 		1	/* Direct 32 bit. */
+#define R_MICROBLAZE_32_PCREL		2	/* PC relative 32 bit. */
+#define R_MICROBLAZE_64_PCREL		3	/* PC relative 64 bit. */
+#define R_MICROBLAZE_32_PCREL_LO	4	/* Low 16 bits of PCREL32. */
+#define R_MICROBLAZE_64 		5	/* Direct 64 bit. */
+#define R_MICROBLAZE_32_LO		6	/* Low 16 bit. */
+#define R_MICROBLAZE_SRO32		7	/* Read-only small data area. */
+#define R_MICROBLAZE_SRW32		8	/* Read-write small data area. */
+#define R_MICROBLAZE_64_NONE		9	/* No reloc. */
+#define R_MICROBLAZE_32_SYM_OP_SYM	10	/* Symbol Op Symbol relocation. */
+#define R_MICROBLAZE_GNU_VTINHERIT	11	/* GNU C++ vtable hierarchy. */
+#define R_MICROBLAZE_GNU_VTENTRY	12	/* GNU C++ vtable member usage. */
+#define R_MICROBLAZE_GOTPC_64		13	/* PC-relative GOT offset.  */
+#define R_MICROBLAZE_GOT_64		14	/* GOT entry offset.  */
+#define R_MICROBLAZE_PLT_64		15	/* PLT offset (PC-relative).  */
+#define R_MICROBLAZE_REL		16	/* Adjust by program base.  */
+#define R_MICROBLAZE_JUMP_SLOT		17	/* Create PLT entry.  */
+#define R_MICROBLAZE_GLOB_DAT		18	/* Create GOT entry.  */
+#define R_MICROBLAZE_GOTOFF_64		19	/* 64 bit offset to GOT. */
+#define R_MICROBLAZE_GOTOFF_32		20	/* 32 bit offset to GOT. */
+#define R_MICROBLAZE_COPY		21	/* Runtime copy.  */
+#define R_MICROBLAZE_TLS		22	/* TLS Reloc. */
+#define R_MICROBLAZE_TLSGD		23	/* TLS General Dynamic. */
+#define R_MICROBLAZE_TLSLD		24	/* TLS Local Dynamic. */
+#define R_MICROBLAZE_TLSDTPMOD32	25	/* TLS Module ID. */
+#define R_MICROBLAZE_TLSDTPREL32	26	/* TLS Offset Within TLS Block. */
+#define R_MICROBLAZE_TLSDTPREL64	27	/* TLS Offset Within TLS Block. */
+#define R_MICROBLAZE_TLSGOTTPREL32	28	/* TLS Offset From Thread Pointer. */
+#define R_MICROBLAZE_TLSTPREL32 	29	/* TLS Offset From Thread Pointer. */
 
 /* Meta relocations */
 #define R_METAG_HIADDR16                 0

+ 8 - 0
ldso/ldso/microblaze/dl-debug.h

@@ -51,4 +51,12 @@ static const char * const _dl_reltypes_tab[] =
 		"R_MICROBLAZE_GOTOFF_64",
 		"R_MICROBLAZE_GOTOFF_32",
 		"R_MICROBLAZE_COPY",
+		"R_MICROBLAZE_TLS",
+		"R_MICROBLAZE_TLSGD",
+		"R_MICROBLAZE_TLSLD",
+		"R_MICROBLAZE_TLSDTPMOD32",
+		"R_MICROBLAZE_TLSDTPREL32",
+		"R_MICROBLAZE_TLSDTPREL64",
+		"R_MICROBLAZE_TLSGOTTPREL32",
+		"R_MICROBLAZE_TLSTPREL32",
 	};

+ 0 - 3
ldso/ldso/microblaze/dl-startup.h

@@ -78,9 +78,6 @@ _dl_start_user:\n\
  */
 #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1)
 
-/* The ld.so library requires relocations */
-#define ARCH_NEEDS_BOOTSTRAP_RELOCS
-
 static __always_inline
 void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
 	unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab)

+ 14 - 14
ldso/ldso/microblaze/dl-sysdep.h

@@ -1,5 +1,3 @@
-/* elf reloc code for the microblaze platform, based on glibc 2.3.6, dl-machine.h */
-
 /*
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -15,37 +13,41 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* Use reloca */
 #define ELF_USES_RELOCA
 
 #include <elf.h>
 
-
 /* Initialise the GOT */
-#define INIT_GOT(GOT_BASE,MODULE)							\
-do {														\
-	GOT_BASE[2] = (unsigned long) _dl_linux_resolve;		\
-	GOT_BASE[1] = (unsigned long) MODULE;					\
+#define INIT_GOT(GOT_BASE,MODULE)				\
+do {								\
+	GOT_BASE[1] = (unsigned long) MODULE;			\
+	GOT_BASE[2] = (unsigned long) _dl_linux_resolve;	\
 } while(0)
 
 /* Here we define the magic numbers that this dynamic loader should accept */
-
 #define MAGIC1 EM_MICROBLAZE
 #undef  MAGIC2
 /* Used for error messages */
 #define ELF_TARGET "microblaze"
 
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
 struct elf_resolve;
 unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
 
 #define elf_machine_type_class(type) \
-  (((type) == R_MICROBLAZE_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT \
+  (((type) == R_MICROBLAZE_JUMP_SLOT || \
+    (type) == R_MICROBLAZE_TLSDTPREL32 || \
+    (type) == R_MICROBLAZE_TLSDTPMOD32 || \
+    (type) == R_MICROBLAZE_TLSTPREL32) \
+    * ELF_RTYPE_CLASS_PLT \
    | ((type) == R_MICROBLAZE_COPY) * ELF_RTYPE_CLASS_COPY)
 
 /* Return the link-time address of _DYNAMIC.  Conveniently, this is the
    first element of the GOT.  This must be inlined in a function which
    uses global data.  */
-static inline Elf32_Addr
+static __always_inline Elf32_Addr __attribute__ ((unused))
 elf_machine_dynamic (void)
 {
   Elf32_Addr got_entry_0;
@@ -56,7 +58,6 @@ elf_machine_dynamic (void)
   return got_entry_0;
 }
 
-
 /* Return the run-time load address of the shared object.  */
 static inline Elf32_Addr
 elf_machine_load_address (void)
@@ -64,6 +65,7 @@ elf_machine_load_address (void)
   /* Compute the difference between the runtime address of _DYNAMIC as seen
      by a GOTOFF reference, and the link-time address found in the special
      unrelocated first GOT entry.  */
+
   Elf32_Addr dyn;
   __asm__ __volatile__ (
     "addik %0,r20,_DYNAMIC@GOTOFF"
@@ -72,8 +74,6 @@ elf_machine_load_address (void)
   return dyn - elf_machine_dynamic ();
 }
 
-
-
 static __always_inline void
 elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
 		      Elf32_Word relative_count)

+ 12 - 10
ldso/ldso/microblaze/elfinterp.c

@@ -214,16 +214,13 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
 		case R_MICROBLAZE_NONE:
 		case R_MICROBLAZE_64_NONE:
 			break;
-
 		case R_MICROBLAZE_64:
 			*reloc_addr = symbol_addr + rpnt->r_addend;
 			break;
-
 		case R_MICROBLAZE_32:
 		case R_MICROBLAZE_32_LO:
 			*reloc_addr = symbol_addr + rpnt->r_addend;
 			break;
-
 		case R_MICROBLAZE_32_PCREL:
 		case R_MICROBLAZE_32_PCREL_LO:
 		case R_MICROBLAZE_64_PCREL:
@@ -231,16 +228,25 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
 		case R_MICROBLAZE_SRW32:
 			*reloc_addr = symbol_addr + rpnt->r_addend;
 			break;
-
 		case R_MICROBLAZE_GLOB_DAT:
 		case R_MICROBLAZE_JUMP_SLOT:
 			*reloc_addr = symbol_addr + rpnt->r_addend;
 			break;
-/* Handled by elf_machine_relative */
 		case R_MICROBLAZE_REL:
 			*reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
 			break;
-
+#if defined USE_TLS && USE_TLS
+		case R_MICROBLAZE_TLSDTPMOD32:
+			*reloc_addr = tls_tpnt->l_tls_modid;
+			break;
+		case R_MICROBLAZE_TLSDTPREL32:
+			*reloc_addr = symbol_addr;
+			break;
+		case R_MICROBLAZE_TLSTPREL32:
+			CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
+			*reloc_addr = tls_tpnt->l_tls_offset + symbol_addr + rpnt->r_addend;
+			break;
+#endif
 		case R_MICROBLAZE_COPY:
 			if (symbol_addr) {
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -250,7 +256,6 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
 						    symname, sym_ref.sym->st_size,
 						    symbol_addr, reloc_addr);
 #endif
-
 				_dl_memcpy((char *)reloc_addr,
 					   (char *)symbol_addr,
 					   sym_ref.sym->st_size);
@@ -260,7 +265,6 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
 				_dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
 #endif
 			break;
-
 		default:
 			return -1;	/* Calls _dl_exit(1). */
 	}
@@ -279,14 +283,12 @@ _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
 		  ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
 {
 	int reloc_type;
-	int symtab_index;
 	ElfW(Addr) *reloc_addr;
 #if defined (__SUPPORT_LD_DEBUG__)
 	ElfW(Addr) old_val;
 #endif
 
 	(void)scope;
-	symtab_index = ELF_R_SYM(rpnt->r_info);
 	(void)strtab;
 
 	reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset);

+ 1 - 1
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 :=
+CSRC-y := __syscall_error.c
 SSRC-y := setjmp.S __longjmp.S vfork.S clone.S

+ 18 - 0
libc/sysdeps/linux/microblaze/__syscall_error.c

@@ -0,0 +1,18 @@
+/* Wrapper for setting errno.
+ *
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <errno.h>
+#include <features.h>
+
+/* This routine is jumped to by all the syscall handlers, to stash
+ * an error number into errno.  */
+int __syscall_error(int err_no) attribute_hidden;
+int __syscall_error(int err_no)
+{
+	__set_errno(-err_no);
+	return -1;
+}

+ 1 - 2
libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h

@@ -6,8 +6,7 @@
 #define _BITS_UCLIBC_ARCH_FEATURES_H
 
 /* instruction used when calling abort() to kill yourself */
-/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/
-#undef __UCLIBC_ABORT_INSTRUCTION__
+#define __UCLIBC_ABORT_INSTRUCTION__ "brki r0, -1"
 
 /* can your target use syscall6() for mmap ? */
 #define __UCLIBC_MMAP_HAS_6_ARGS__

+ 8 - 9
libc/sysdeps/linux/microblaze/clone.S

@@ -23,6 +23,10 @@
 #define _ERRNO_H	1
 #include <bits/errno.h>
 
+#if defined __UCLIBC_HAS_THREADS__ && !defined __UCLIBC_HAS_LINUXTHREADS__
+#include <sysdep-cancel.h>
+#endif
+
 /* int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg,
               pid_t *ptid, struct user_desc *tls, pid_t *ctid);
 
@@ -39,8 +43,8 @@
         .text
 ENTRY (__clone)
 	addik	r3,r0,-EINVAL
-	beqi	r5,1f	; // Invalid func
-	beqi	r6,1f	; // Invalid stack
+	beqi	r5,SYSCALL_ERROR_LABEL	; // Invalid func
+	beqi	r6,SYSCALL_ERROR_LABEL	; // Invalid stack
 	addik	r6,r6,-8
 	swi	r5,r6,0			; // Push fn onto child's stack
 	swi	r8,r6,4			; // Push arg for child
@@ -53,7 +57,7 @@ ENTRY (__clone)
 	addk	r0,r0,r0
 	addik	r4,r0,-4095
 	cmpu	r4,r4,r3
-	bgei	r4,1f
+	bgei	r4,SYSCALL_ERROR_LABEL
 	beqi	r3,L(thread_start)
 	rtsd	r15,8
 	nop
@@ -67,12 +71,7 @@ L(thread_start):
 	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)
+PSEUDO_END(__clone)
 
 libc_hidden_def (__clone)
 weak_alias (__clone,clone)

+ 0 - 6
libc/sysdeps/linux/microblaze/jmpbuf-offsets.h

@@ -1,6 +0,0 @@
-/*
- * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-#define JB_SIZE		(4 * 18)

+ 25 - 0
libc/sysdeps/linux/microblaze/jmpbuf-unwind.h

@@ -10,3 +10,28 @@
    containing a local variable at ADDRESS.  */
 #define _JMPBUF_UNWINDS(jmpbuf, address) \
   ((void *) (address) < (void *) (jmpbuf)[0].__sp)
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <stdint.h>
+#include <unwind.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+   containing a local variable at ADDRESS.  */
+#undef _JMPBUF_UNWINDS
+#define _JMPBUF_UNWINDS(jmpbuf, address)		\
+  ((void *) (address) < (void *) (jmpbuf)[0].__sp)
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+static inline uintptr_t __attribute__ ((unused))
+_jmpbuf_sp (__jmp_buf regs)
+{
+  void *sp = (void *) regs[0].__sp;
+  return (uintptr_t) sp;
+}
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+  ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+
+#endif

+ 81 - 2
libc/sysdeps/linux/microblaze/sysdep.h

@@ -1,9 +1,25 @@
+/* Copyright (C) 2000-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/>.  */
+
 #include <common/sysdep.h>
 
 #ifdef  __ASSEMBLER__
 
-/* Syntactic details of assembler.  */
-
 # define ALIGNARG(log2) log2
 # define ASM_SIZE_DIRECTIVE(name) .size name,.-name
 
@@ -22,4 +38,67 @@
 #  define L(name) $L##name
 # endif
 
+/* We don't want the label for the error handler to be visible in the symbol
+   table when we define it here.  */
+# ifdef __PIC__
+#  define SYSCALL_ERROR_LABEL 0f
+# else
+#  define SYSCALL_ERROR_LABEL __syscall_error
+# endif
+
+# define DO_CALL(syscall_name, args)                \
+    addik r12,r0,SYS_ify (syscall_name);            \
+    brki  r14,8;                                    \
+    addk  r0,r0,r0;
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)           \
+  .text;                                            \
+  ENTRY (name)                                      \
+    DO_CALL (syscall_name, args);                   \
+    addik r12,r0,-4095;                             \
+    cmpu  r12,r12,r3;                               \
+    bgei  r12,SYSCALL_ERROR_LABEL;
+
+# undef PSEUDO_END
+# define PSEUDO_END(name)                           \
+  SYSCALL_ERROR_HANDLER;                            \
+  END (name)
+
+#ifdef __PIC__
+# define SYSCALL_ERROR_LABEL_DCL 0
+# if defined _LIBC_REENTRANT
+#  define SYSCALL_ERROR_HANDLER                     \
+SYSCALL_ERROR_LABEL_DCL:                            \
+    addik r1,r1,-16;                                \
+    swi   r15,r1,0;                                 \
+    swi   r20,r1,8;                                 \
+    rsubk r3,r3,r0;                                 \
+    swi   r3,r1,12;                                 \
+    mfs   r20,rpc;                                  \
+    addik r20,r20,_GLOBAL_OFFSET_TABLE_+8;          \
+    brlid r15,__errno_location@PLT;                 \
+    nop;                                            \
+    lwi   r4,r1,12;                                 \
+    swi   r4,r3,0;                                  \
+    lwi   r20,r1,8;                                 \
+    lwi   r15,r1,0;                                 \
+    addik r1,r1,16;                                 \
+    rtsd  r15,8;                                    \
+    addik r3,r0,-1;
+# else /* !_LIBC_REENTRANT.  */
+#  define SYSCALL_ERROR_HANDLER                     \
+SYSCALL_ERROR_LABEL_DCL:                            \
+    mfs   r12,rpc;                                  \
+    addik r12,r12,_GLOBAL_OFFSET_TABLE_+8;          \
+    lwi   r12,r12,errno@GOT;                        \
+    rsubk r3,r3,r0;                                 \
+    swi   r3,r12,0;                                 \
+    rtsd  r15,8;                                    \
+    addik r3,r0,-1;
+# endif /* _LIBC_REENTRANT.  */
+#else
+#  define SYSCALL_ERROR_HANDLER  /* Nothing here; code in sysdep.S is used.  */
+#endif /* PIC.  */
+
 #endif

+ 30 - 28
libc/sysdeps/linux/microblaze/vfork.S

@@ -1,42 +1,44 @@
-/*
- * libc/sysdeps/linux/microblaze/vfork.S -- `vfork' syscall for linux/microblaze
- *
- * Copyright (C) 2003  John Williams <jwilliams@itee.uq.edu.au>
- * Copyright (C) 2001  NEC Corporation
- * Copyright (C) 2001  Miles Bader <miles@gnu.org>
- *
- * 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.
- *
- * Written by Miles Bader <miles@gnu.org>
- * Microblaze port by John Williams
- */
-
-#include <sys/syscall.h>
+/* Copyright (C) 2005-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/>.  */
+
+#include <sysdep.h>
+#define _ERRNO_H	1
+#include <bits/errno.h>
 
 /* Clone the calling process, but without copying the whole address space.
    The calling process is suspended until the new process exits or is
    replaced by a call to `execve'.  Return -1 for errors, 0 to the new process,
    and the process ID of the new process to the old process.  */
 
-	.globl __vfork
-	.hidden __vfork
-	.align 4
-__vfork:
-	addi	r12, r0, SYS_vfork
-	brki	r14, 0x08;
-	addi	r4, r3, 125		/* minimum err value */
-	blti	r4, 1f			/* is r3 < -125? */
-	bri	2f			/* normal return */
+ENTRY(__vfork)
+
+	DO_CALL (vfork, 0)
+	addik	r12,r0,-4095
+	cmpu	r12,r12,r3
+	bgei	r12,1f
+	rtsd	r15,8
+	nop
 
 1:      rsubk   r3,r3,r0
         rtsd    r15,8
         addik   r3,r0,-1        /* delay slot.  */
 
-2:	rtsd	r15, 8			/* error return */
-	nop
-       .size   __vfork, .-__vfork
+END(__vfork)
 
 weak_alias(__vfork, vfork)
 libc_hidden_def(vfork)

+ 4 - 0
libpthread/nptl/sysdeps/microblaze/Makefile.arch

@@ -0,0 +1,4 @@
+# Makefile for uClibc NPTL
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+libc_arch_a_CSRC = libc-tls.c

+ 26 - 0
libpthread/nptl/sysdeps/microblaze/dl-tls.h

@@ -0,0 +1,26 @@
+/* Copyright (C) 2005-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/>.  */
+
+/* Type used for the representation of TLS information in the GOT.  */
+typedef struct
+{
+  unsigned long int ti_module;
+  unsigned long int ti_offset;
+} tls_index;
+
+extern void *__tls_get_addr (tls_index *ti);

+ 36 - 0
libpthread/nptl/sysdeps/microblaze/libc-tls.c

@@ -0,0 +1,36 @@
+/* Copyright (C) 2005-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/>.  */
+
+#include <sysdeps/generic/libc-tls.c>
+#include <dl-tls.h>
+
+/* On Microblaze, linker optimizations are not required, so __tls_get_addr
+   can be called even in statically linked binaries.  In this case module
+   must be always 1 and PT_TLS segment exist in the binary, otherwise it
+   would not link.  */
+
+#if defined(USE_TLS) && USE_TLS
+
+void *
+__tls_get_addr (tls_index *ti)
+{
+  dtv_t *dtv = THREAD_DTV ();
+  return (char *) dtv[1].pointer.val + ti->ti_offset;
+}
+
+#endif

+ 62 - 0
libpthread/nptl/sysdeps/microblaze/pthread_spin_lock.c

@@ -0,0 +1,62 @@
+/* pthread_spin_lock -- lock a spin lock.  Generic version.
+   Copyright (C) 2012-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/>.  */
+
+#include <atomic.h>
+#include "pthreadP.h"
+
+#define SPIN_LOCK_READS_BETWEEN_CMPXCHG 1000
+
+int
+pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  /* atomic_exchange usually takes less instructions than
+     atomic_compare_and_exchange.  On the other hand,
+     atomic_compare_and_exchange potentially generates less bus traffic
+     when the lock is locked.
+     We assume that the first try mostly will be successful, and we use
+     atomic_exchange.  For the subsequent tries we use
+     atomic_compare_and_exchange.  */
+  if (atomic_exchange_acq (lock, 1) == 0)
+    return 0;
+
+  do
+    {
+      /* The lock is contended and we need to wait.  Going straight back
+	 to cmpxchg is not a good idea on many targets as that will force
+	 expensive memory synchronizations among processors and penalize other
+	 running threads.
+	 On the other hand, we do want to update memory state on the local core
+	 once in a while to avoid spinning indefinitely until some event that
+	 will happen to update local memory as a side-effect.  */
+      if (SPIN_LOCK_READS_BETWEEN_CMPXCHG >= 0)
+	{
+	  int wait = SPIN_LOCK_READS_BETWEEN_CMPXCHG;
+
+	  while (*lock != 0 && wait > 0)
+	    --wait;
+	}
+      else
+	{
+	  while (*lock != 0)
+	    ;
+	}
+    }
+  while (atomic_compare_and_exchange_val_acq (lock, 1, 0) != 0);
+
+  return 0;
+}

+ 27 - 0
libpthread/nptl/sysdeps/microblaze/pthread_spin_trylock.c

@@ -0,0 +1,27 @@
+/* pthread_spin_trylock -- trylock a spin lock.  Generic version.
+   Copyright (C) 2012-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/>.  */
+
+#include <errno.h>
+#include <atomic.h>
+#include "pthreadP.h"
+
+int
+pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  return atomic_exchange_acq (lock, 1) ? EBUSY : 0;
+}

+ 40 - 0
libpthread/nptl/sysdeps/microblaze/pthreaddef.h

@@ -0,0 +1,40 @@
+/* Copyright (C) 2002-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/>.  */
+
+#include <stdlib.h>
+#include <string.h>
+
+/* Default stack size.  */
+#define ARCH_STACK_DEFAULT_SIZE  (2 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning.  */
+#define STACK_ALIGN         16
+
+/* Minimal stack size after allocating thread descriptor and guard size.  */
+#define MINIMAL_REST_STACK  2048
+
+/* Alignment requirement for TCB.  */
+#define TCB_ALIGNMENT       16
+
+/* Location of current stack frame.  */
+#define CURRENT_STACK_FRAME __builtin_frame_address (0)
+
+/* XXX Until we have a better place keep the definitions here.  */
+
+#define __exit_thread_inline(val) \
+INLINE_SYSCALL (exit, 1, (val))

+ 11 - 0
libpthread/nptl/sysdeps/microblaze/tcb-offsets.sym

@@ -0,0 +1,11 @@
+#include <sysdep.h>
+#include <tls.h>
+
+--
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+#define thread_offsetof(mem)	(long)(offsetof (struct pthread, mem) - sizeof (struct pthread))
+
+MULTIPLE_THREADS_OFFSET	thread_offsetof (header.multiple_threads)
+PID_OFFSET			thread_offsetof (pid)
+TID_OFFSET			thread_offsetof (tid)

+ 159 - 0
libpthread/nptl/sysdeps/microblaze/tls.h

@@ -0,0 +1,159 @@
+/* Copyright (C) 2005-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/>.  */
+
+#ifndef _TLS_H
+# define _TLS_H 1
+
+#ifndef __ASSEMBLER__
+
+# include <stdbool.h>
+# include <stddef.h>
+# include <stdint.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
+} dtv_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+/* We require TLS support in the tools.  */
+#define HAVE_TLS_SUPPORT		1
+#define HAVE___THREAD   		1
+#define HAVE_TLS_MODEL_ATTRIBUTE       	1
+
+/* Signal that TLS support is available.  */
+#define USE_TLS 1
+
+#ifndef __ASSEMBLER__
+
+/* Get system call information.  */
+# include <sysdep.h>
+
+/* The TP points to the start of the thread blocks.  */
+# define TLS_DTV_AT_TP  1
+
+/* Get the thread descriptor definition.  */
+# include <../../descr.h>
+
+typedef struct
+{
+  dtv_t *dtv;
+  void *private;
+} tcbhead_t;
+
+#define READ_THREAD_POINTER() \
+  ({ register void *__microblaze_thread_area __asm__ ("r21"); \
+     __microblaze_thread_area; })
+
+/* This is the size of the initial TCB.  */
+# define TLS_INIT_TCB_SIZE	sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB.  */
+# define TLS_INIT_TCB_ALIGN	16
+
+/* This is the size of the TCB.  */
+# define TLS_TCB_SIZE       	sizeof (tcbhead_t)
+
+/* This is the size we need before TCB.  */
+# define TLS_PRE_TCB_SIZE   	sizeof (struct pthread)
+
+/* Alignment requirements for the TCB.  */
+# define TLS_TCB_ALIGN      	16
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+# define INSTALL_DTV(tcbp, dtvp) \
+  (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1)
+
+/* Install new dtv for current thread.  */
+# define INSTALL_NEW_DTV(dtv) \
+  (THREAD_DTV() = (dtv))
+
+/* Return dtv of given thread descriptor.  */
+# define GET_DTV(tcbp) \
+  (((tcbhead_t *) (tcbp))->dtv)
+
+/* Code to initially initialize the thread pointer.
+   r21 is reserved for thread pointer.  */
+# define TLS_INIT_TP(tcbp, secondcall) \
+  ({ __asm__ __volatile__ ("or r21,r0,%0" : : "r" ((void *)tcbp)); NULL; })
+
+# define TLS_DEFINE_INIT_TP(tp, pd) void *tp = (pd) + 1
+
+/* Return the address of the dtv for the current thread.  */
+# define THREAD_DTV() \
+  (((tcbhead_t *) READ_THREAD_POINTER())->dtv)
+
+/* Return the thread descriptor for the current thread.  */
+# define THREAD_SELF \
+  (((struct pthread *) READ_THREAD_POINTER()) - 1)
+
+/* Magic for libthread_db to know how to do THREAD_SELF.  */
+# define DB_THREAD_SELF \
+  CONST_THREAD_AREA (32, sizeof (struct pthread))
+
+/* Read member of the thread descriptor directly.  */
+# define THREAD_GETMEM(descr, member) (descr->member)
+
+/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
+# define THREAD_GETMEM_NC(descr, member, idx) \
+  (descr->member[idx])
+
+/* Set member of the thread descriptor directly.  */
+# define THREAD_SETMEM(descr, member, value) \
+  (descr->member = (value))
+
+/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
+# define THREAD_SETMEM_NC(descr, member, idx, value) \
+  (descr->member[idx] = (value))
+
+/* Get and set the global scope generation counter in struct pthread.  */
+# define THREAD_GSCOPE_FLAG_UNUSED 0
+# define THREAD_GSCOPE_FLAG_USED   1
+# define THREAD_GSCOPE_FLAG_WAIT   2
+# define THREAD_GSCOPE_RESET_FLAG()                                         \
+  do                                                                        \
+    { int __res                                                             \
+      = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag,              \
+                             THREAD_GSCOPE_FLAG_UNUSED);                    \
+      if (__res == THREAD_GSCOPE_FLAG_WAIT)                                 \
+        lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE);  \
+    }                                                                       \
+  while (0)
+# define THREAD_GSCOPE_SET_FLAG()                                           \
+  do                                                                        \
+    {                                                                       \
+      THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED;            \
+      atomic_write_barrier ();                                              \
+    }                                                                       \
+  while (0)
+# define THREAD_GSCOPE_WAIT() \
+  GL (dl_wait_lookup_done) ()
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* tls.h.  */

+ 13 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/Makefile

@@ -0,0 +1,13 @@
+# Makefile for uClibc NPTL
+#
+# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org>
+#
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../../../../../
+top_builddir=../../../../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules

+ 8 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/Makefile.arch

@@ -0,0 +1,8 @@
+# Makefile for uClibc NPTL
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+libpthread_linux_arch_SSRC =
+libpthread_linux_arch_CSRC = pthread_once.c
+
+libc_linux_arch_CSRC = fork.c
+libc_linux_arch_SSRC = clone.S vfork.S

+ 181 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/bits/pthreadtypes.h

@@ -0,0 +1,181 @@
+/* Copyright (C) 2002-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/>.  */
+
+#ifndef _BITS_PTHREADTYPES_H
+# define _BITS_PTHREADTYPES_H	1
+
+# include <endian.h>
+
+# define __SIZEOF_PTHREAD_ATTR_T         36
+# define __SIZEOF_PTHREAD_MUTEX_T        24
+# define __SIZEOF_PTHREAD_MUTEXATTR_T     4
+# define __SIZEOF_PTHREAD_COND_T         48
+# define __SIZEOF_PTHREAD_COND_COMPAT_T  12
+# define __SIZEOF_PTHREAD_CONDATTR_T      4
+# define __SIZEOF_PTHREAD_RWLOCK_T       32
+# define __SIZEOF_PTHREAD_RWLOCKATTR_T    8
+# define __SIZEOF_PTHREAD_BARRIER_T      20
+# define __SIZEOF_PTHREAD_BARRIERATTR_T   4
+
+
+/* Thread identifiers.  The structure of the attribute type is not
+   exposed on purpose.  */
+typedef unsigned long int pthread_t;
+
+union pthread_attr_t
+{
+  char __size[__SIZEOF_PTHREAD_ATTR_T];
+  long int __align;
+};
+
+# ifndef __have_pthread_attr_t
+typedef union pthread_attr_t pthread_attr_t;
+#  define __have_pthread_attr_t	1
+# endif
+
+typedef struct __pthread_internal_slist
+{
+  struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+
+/* Data structures for mutex handling.  The structure of the attribute
+   type is not exposed on purpose.  */
+typedef union
+{
+  struct __pthread_mutex_s
+  {
+    int __lock;
+    unsigned int __count;
+    int __owner;
+    /* KIND must stay at this position in the structure to maintain
+       binary compatibility.  */
+    int __kind;
+    unsigned int __nusers;
+    __extension__ union
+    {
+      int __spins;
+      __pthread_slist_t __list;
+    };
+  } __data;
+  char __size[__SIZEOF_PTHREAD_MUTEX_T];
+  long int __align;
+} pthread_mutex_t;
+
+/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER.  */
+#define __PTHREAD_SPINS 0
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
+  int __align;
+} pthread_mutexattr_t;
+
+/* Data structure for conditional variable handling.  The structure of
+   the attribute type is not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __futex;
+    __extension__ unsigned long long int __total_seq;
+    __extension__ unsigned long long int __wakeup_seq;
+    __extension__ unsigned long long int __woken_seq;
+    void *__mutex;
+    unsigned int __nwaiters;
+    unsigned int __broadcast_seq;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_COND_T];
+  __extension__ long long int __align;
+} pthread_cond_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_CONDATTR_T];
+  int __align;
+} pthread_condattr_t;
+
+/* Keys for thread-specific data.  */
+typedef unsigned int pthread_key_t;
+
+/* Once-only execution.  */
+typedef int pthread_once_t;
+
+# if defined __USE_UNIX98 || defined __USE_XOPEN2K
+/* Data structure for read-write lock variable handling.  The
+   structure of the attribute type is not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __nr_readers;
+    unsigned int __readers_wakeup;
+    unsigned int __writer_wakeup;
+    unsigned int __nr_readers_queued;
+    unsigned int __nr_writers_queued;
+#  if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned char __pad1;
+    unsigned char __pad2;
+    unsigned char __shared;
+    /* FLAGS must stay at this position in the structure to maintain
+       binary compatibility.  */
+    unsigned char __flags;
+#  else
+    /* FLAGS must stay at this position in the structure to maintain
+       binary compatibility.  */
+    unsigned char __flags;
+    unsigned char __shared;
+    unsigned char __pad1;
+    unsigned char __pad2;
+#  endif
+    int __writer;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_RWLOCK_T];
+  long int __align;
+} pthread_rwlock_t;
+
+#define __PTHREAD_RWLOCK_ELISION_EXTRA 0
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
+  long int __align;
+} pthread_rwlockattr_t;
+# endif
+
+# ifdef __USE_XOPEN2K
+/* POSIX spinlock data type.  */
+typedef volatile int pthread_spinlock_t;
+
+/* POSIX barriers data type.  The structure of the type is
+   deliberately not exposed.  */
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_BARRIER_T];
+  long int __align;
+} pthread_barrier_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
+  int __align;
+} pthread_barrierattr_t;
+# endif
+
+#endif	/* bits/pthreadtypes.h.  */

+ 32 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/bits/semaphore.h

@@ -0,0 +1,32 @@
+/* Copyright (C) 2002-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/>.  */
+
+#ifndef _SEMAPHORE_H
+# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
+#endif
+
+#define __SIZEOF_SEM_T	16
+
+/* Value returned if `sem_open' failed.  */
+#define SEM_FAILED	((sem_t *) 0)
+
+typedef union
+{
+  char __size[__SIZEOF_SEM_T];
+  long int __align;
+} sem_t;

+ 4 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/clone.S

@@ -0,0 +1,4 @@
+#define RESET_PID
+#include <tls.h>
+#include <tcb-offsets.h>
+#include "../../../../../../../libc/sysdeps/linux/microblaze/clone.S"

+ 22 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/createthread.c

@@ -0,0 +1,22 @@
+/* Copyright (C) 2005 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/>.  */
+
+/* Value passed to 'clone' for initialization of the thread register.  */
+#define TLS_VALUE (pd + 1)
+
+/* Get the real implementation.	 */
+#include <sysdeps/pthread/createthread.c>

+ 29 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/fork.c

@@ -0,0 +1,29 @@
+/* Copyright (C) 2013 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/>.  */
+
+#include <sched.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <tls.h>
+
+
+#define ARCH_FORK() \
+  INLINE_SYSCALL (clone, 5,						      \
+		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \
+		  NULL, NULL, &THREAD_SELF->tid)
+
+#include "../fork.c"

+ 278 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/lowlevellock.h

@@ -0,0 +1,278 @@
+/* Copyright (C) 2005, 2006, 2007, 2008, 2009 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; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LOWLEVELLOCK_H
+#define _LOWLEVELLOCK_H	1
+
+#include <time.h>
+#include <sys/param.h>
+#include <bits/pthreadtypes.h>
+#include <atomic.h>
+#include <sysdep.h>
+#include <bits/kernel-features.h>
+
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+#define FUTEX_REQUEUE		3
+#define FUTEX_CMP_REQUEUE	4
+#define FUTEX_WAKE_OP		5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1)
+#define FUTEX_LOCK_PI		6
+#define FUTEX_UNLOCK_PI		7
+#define FUTEX_TRYLOCK_PI	8
+#define FUTEX_WAIT_BITSET	9
+#define FUTEX_WAKE_BITSET	10
+#define FUTEX_PRIVATE_FLAG	128
+#define FUTEX_CLOCK_REALTIME	256
+
+#define FUTEX_BITSET_MATCH_ANY	0xffffffff
+
+/* Values for 'private' parameter of locking macros.  Yes, the
+   definition seems to be backwards.  But it is not.  The bit will be
+   reversed before passing to the system call.  */
+#define LLL_PRIVATE	0
+#define LLL_SHARED	FUTEX_PRIVATE_FLAG
+
+
+#if !defined NOT_IN_libc || defined IS_IN_rtld
+/* In libc.so or ld.so all futexes are private.  */
+# ifdef __ASSUME_PRIVATE_FUTEX
+#  define __lll_private_flag(fl, private) \
+  ((fl) | FUTEX_PRIVATE_FLAG)
+# else
+#  define __lll_private_flag(fl, private) \
+  ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
+# endif
+#else
+# ifdef __ASSUME_PRIVATE_FUTEX
+#  define __lll_private_flag(fl, private) \
+  (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
+# else
+#  define __lll_private_flag(fl, private) \
+  (__builtin_constant_p (private)					      \
+   ? ((private) == 0							      \
+      ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))	      \
+      : (fl))								      \
+   : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG)				      \
+	      & THREAD_GETMEM (THREAD_SELF, header.private_futex))))
+# endif
+#endif
+
+
+#define lll_futex_wait(futexp, val, private) \
+  lll_futex_timed_wait(futexp, val, NULL, private)
+
+#define lll_futex_timed_wait(futexp, val, timespec, private) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __sysret;							      \
+    __sysret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),		      \
+			      __lll_private_flag (FUTEX_WAIT, private),	      \
+			      (val), (timespec));			      \
+    __sysret;								      \
+  })
+
+#define lll_futex_wake(futexp, nr, private) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __sysret;							      \
+    __sysret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),		      \
+			      __lll_private_flag (FUTEX_WAKE, private),	      \
+			      (nr), 0);					      \
+    __sysret;								      \
+  })
+
+#define lll_robust_dead(futexv, private) \
+  do									      \
+    {									      \
+      int *__futexp = &(futexv);					      \
+      atomic_or (__futexp, FUTEX_OWNER_DIED);				      \
+      lll_futex_wake (__futexp, 1, private);				      \
+    }									      \
+  while (0)
+
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __sysret;							      \
+    __sysret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		      \
+			      __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
+			      (nr_wake), (nr_move), (mutex), (val));	      \
+    INTERNAL_SYSCALL_ERROR_P (__sysret, __err);				      \
+  })
+
+
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __sysret;							      \
+    __sysret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		      \
+			      __lll_private_flag (FUTEX_WAKE_OP, private),    \
+			      (nr_wake), (nr_wake2), (futexp2),		      \
+			      FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);		      \
+    INTERNAL_SYSCALL_ERROR_P (__sysret, __err);				      \
+  })
+
+
+#define lll_trylock(lock)	\
+  atomic_compare_and_exchange_val_acq(&(lock), 1, 0)
+
+#define lll_cond_trylock(lock)	\
+  atomic_compare_and_exchange_val_acq(&(lock), 2, 0)
+
+#define __lll_robust_trylock(futex, id) \
+  (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0)
+#define lll_robust_trylock(lock, id) \
+  __lll_robust_trylock (&(lock), id)
+
+extern void __lll_lock_wait_private (int *futex) attribute_hidden;
+extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
+extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
+
+#define __lll_lock(futex, private)					      \
+  ((void) ({								      \
+    int *__futex = (futex);						      \
+    if (unlikely(atomic_compare_and_exchange_val_acq (__futex, 1, 0)))        \
+      {									      \
+	if (__builtin_constant_p (private) && (private) == LLL_PRIVATE)	      \
+	  __lll_lock_wait_private (__futex);				      \
+	else								      \
+	  __lll_lock_wait (__futex, private);				      \
+      }									      \
+  }))
+#define lll_lock(futex, private) __lll_lock (&(futex), private)
+
+
+#define __lll_robust_lock(futex, id, private)				      \
+  ({									      \
+    int *__futex = (futex);						      \
+    int __val = 0;							      \
+									      \
+    if (unlikely(atomic_compare_and_exchange_bool_acq (__futex, id, 0)))      \
+      __val = __lll_robust_lock_wait (__futex, private);		      \
+    __val;								      \
+  })
+#define lll_robust_lock(futex, id, private) \
+  __lll_robust_lock (&(futex), id, private)
+
+
+#define __lll_cond_lock(futex, private)					      \
+  ((void) ({								      \
+    int *__futex = (futex);						      \
+    if (unlikely(atomic_exchange_acq (__futex, 2)))			      \
+      __lll_lock_wait (__futex, private);				      \
+  }))
+#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
+
+
+#define lll_robust_cond_lock(futex, id, private) \
+  __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
+
+
+extern int __lll_timedlock_wait (int *futex, const struct timespec *,
+				 int private) attribute_hidden;
+extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
+					int private) attribute_hidden;
+
+#define __lll_timedlock(futex, abstime, private)			      \
+  ({									      \
+     int *__futex = (futex);						      \
+     int __val = 0;							      \
+									      \
+     if (unlikely(atomic_exchange_acq (__futex, 1)))	                      \
+       __val = __lll_timedlock_wait (__futex, abstime, private);	      \
+     __val;								      \
+  })
+#define lll_timedlock(futex, abstime, private) \
+  __lll_timedlock (&(futex), abstime, private)
+
+
+#define __lll_robust_timedlock(futex, abstime, id, private)		      \
+  ({									      \
+    int *__futex = (futex);						      \
+    int __val = 0;							      \
+									      \
+    if (unlikely(atomic_compare_and_exchange_bool_acq (__futex, id, 0)))      \
+      __val = __lll_robust_timedlock_wait (__futex, abstime, private);	      \
+    __val;								      \
+  })
+#define lll_robust_timedlock(futex, abstime, id, private) \
+  __lll_robust_timedlock (&(futex), abstime, id, private)
+
+
+#define __lll_unlock(futex, private) \
+  (void)							\
+    ({ int *__futex = (futex);					\
+       int __oldval = atomic_exchange_rel (__futex, 0);		\
+       if (unlikely(__oldval > 1))			        \
+	 lll_futex_wake (__futex, 1, private);			\
+    })
+#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
+
+
+#define __lll_robust_unlock(futex, private) \
+  (void)							\
+    ({ int *__futex = (futex);					\
+       int __oldval = atomic_exchange_rel (__futex, 0);		\
+       if (unlikely(__oldval & FUTEX_WAITERS))	        	\
+	 lll_futex_wake (__futex, 1, private);			\
+    })
+#define lll_robust_unlock(futex, private) \
+  __lll_robust_unlock(&(futex), private)
+
+
+#define lll_islocked(futex) \
+  (futex != 0)
+
+
+/* Our internal lock implementation is identical to the binary-compatible
+   mutex implementation. */
+
+/* Initializers for lock.  */
+#define LLL_LOCK_INITIALIZER		(0)
+#define LLL_LOCK_INITIALIZER_LOCKED	(1)
+
+/* The states of a lock are:
+    0  -  untaken
+    1  -  taken by one user
+   >1  -  taken by more users */
+
+/* The kernel notifies a process which uses CLONE_CLEARTID via futex
+   wakeup when the clone terminates.  The memory location contains the
+   thread ID while the clone is running and is reset to zero
+   afterwards.	*/
+#define lll_wait_tid(tid) \
+  do {					\
+    __typeof (tid) __tid;		\
+    while ((__tid = (tid)) != 0)	\
+      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+  } while (0)
+
+extern int __lll_timedwait_tid (int *, const struct timespec *)
+     attribute_hidden;
+
+#define lll_timedwait_tid(tid, abstime) \
+  ({							\
+    int __res = 0;					\
+    if ((tid) != 0)					\
+      __res = __lll_timedwait_tid (&(tid), (abstime));	\
+    __res;						\
+  })
+
+#endif	/* lowlevellock.h */

+ 89 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/pthread_once.c

@@ -0,0 +1,89 @@
+/* Copyright (C) 2004-2013 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/>.  */
+
+#include "pthreadP.h"
+#include <lowlevellock.h>
+
+unsigned long int __fork_generation attribute_hidden;
+
+static void
+clear_once_control (void *arg)
+{
+  pthread_once_t *once_control = (pthread_once_t *) arg;
+
+  *once_control = 0;
+  lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
+}
+
+int
+__pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
+{
+  for (;;)
+    {
+      int oldval;
+      int newval;
+
+      /* Pseudo code:
+	 newval = __fork_generation | 1;
+	 oldval = *once_control;
+	 if ((oldval & 2) == 0)
+	   *once_control = newval;
+	 Do this atomically.
+      */
+      do
+	{
+	  newval = __fork_generation | 1;
+	  oldval = *once_control;
+	  if (oldval & 2)
+	    break;
+	} while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval);
+
+      /* Check if the initializer has already been done.  */
+      if ((oldval & 2) != 0)
+	return 0;
+
+      /* Check if another thread already runs the initializer.	*/
+      if ((oldval & 1) == 0)
+	break;
+
+      /* Check whether the initializer execution was interrupted by a fork.  */
+      if (oldval != newval)
+	break;
+
+      /* Same generation, some other thread was faster. Wait.  */
+      lll_futex_wait (once_control, oldval, LLL_PRIVATE);
+    }
+
+  /* This thread is the first here.  Do the initialization.
+     Register a cleanup handler so that in case the thread gets
+     interrupted the initialization can be restarted.  */
+  pthread_cleanup_push (clear_once_control, once_control);
+
+  init_routine ();
+
+  pthread_cleanup_pop (0);
+
+  /* Say that the initialisation is done.  */
+  *once_control = __fork_generation | 2;
+
+  /* Wake up all other threads.  */
+  lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
+
+  return 0;
+}
+weak_alias (__pthread_once, pthread_once)
+strong_alias (__pthread_once, __pthread_once_internal)

+ 139 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/sysdep-cancel.h

@@ -0,0 +1,139 @@
+/* Copyright (C) 2014-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/>.  */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <pthreadP.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+#ifdef __ASSEMBLER__
+
+#undef ret
+#define ret
+
+# if !IS_IN_librt || !defined(PIC)
+#  define AC_STACK_SIZE  16  /* space for r15, async_cancel arg and 2 temp words */
+#  define AC_SET_GOT /* empty */
+#  define AC_RESTORE_GOT /* empty */
+# else
+#  define AC_STACK_SIZE  20  /* extra 4 bytes for r20 */
+#  define AC_SET_GOT                                                 \
+    swi   r20, r1, AC_STACK_SIZE-4;                                  \
+    mfs   r20, rpc;                                                  \
+    addik r20, r20, _GLOBAL_OFFSET_TABLE_+8;
+#  define AC_RESTORE_GOT                                             \
+    lwi   r20, r1, AC_STACK_SIZE-4;
+# endif
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)                            \
+  .text;                                                             \
+  ENTRY (name)                                                       \
+    SINGLE_THREAD_P(r12);                                            \
+    bnei r12, L(pseudo_cancel);                                      \
+  .globl __##syscall_name##_nocancel;                                \
+  .type __##syscall_name##_nocancel,@function;                       \
+__##syscall_name##_nocancel:                                         \
+    DO_CALL (syscall_name, args);                                    \
+    addik r4, r0, -4095;                                             \
+    cmpu  r4, r4, r3;                                                \
+    rsubk   r3,r3,r0;						     \
+    rtsd    r15,8;						     \
+    addik   r3,r0,-1;						     \
+    rtsd  r15, 8;                                                    \
+    nop;                                                             \
+  .size __##syscall_name##_nocancel, .-__##syscall_name##_nocancel;  \
+L(pseudo_cancel):                                                    \
+    addik r1, r1, -AC_STACK_SIZE;                                    \
+    swi   r15, r1, 0;                                                \
+    AC_SET_GOT                                                       \
+    DOCARGS_##args                                                   \
+    CENABLE;                                                         \
+    swi   r3, r1, 8;                                                 \
+    UNDOCARGS_##args                                                 \
+    DO_CALL (syscall_name, args);                                    \
+    swi   r3, r1, 12;                                                \
+    lwi   r5, r1, 8;                                                 \
+    CDISABLE;                                                        \
+    lwi   r3, r1, 12;                                                \
+    lwi   r15, r1, 0;                                                \
+    AC_RESTORE_GOT                                                   \
+    addik r1, r1, AC_STACK_SIZE;                                     \
+    addik r4, r0, -4095;                                             \
+    cmpu  r4, r4, r3;                                                \
+    rsubk   r3,r3,r0;						     \
+    rtsd    r15,8;						     \
+    addik   r3,r0,-1;						     \
+    rtsd  r15, 8;                                                    \
+    nop;
+
+/*
+ * Macros to save/restore syscall arguments across CENABLE
+ * The arguments are saved into the caller's stack (original r1 + 4)
+ */
+
+# define DOCARGS_0
+# define DOCARGS_1  swi   r5, r1, AC_STACK_SIZE + 4;
+# define DOCARGS_2  swi   r6, r1, AC_STACK_SIZE + 8; DOCARGS_1
+# define DOCARGS_3  swi   r7, r1, AC_STACK_SIZE + 12; DOCARGS_2
+# define DOCARGS_4  swi   r8, r1, AC_STACK_SIZE + 16; DOCARGS_3
+# define DOCARGS_5  swi   r9, r1, AC_STACK_SIZE + 20; DOCARGS_4
+# define DOCARGS_6  swi   r10, r1, AC_STACK_SIZE + 24; DOCARGS_5
+
+# define UNDOCARGS_0
+# define UNDOCARGS_1  lwi   r5, r1, AC_STACK_SIZE + 4;
+# define UNDOCARGS_2  UNDOCARGS_1 lwi   r6, r1, AC_STACK_SIZE + 8;
+# define UNDOCARGS_3  UNDOCARGS_2 lwi   r7, r1, AC_STACK_SIZE + 12;
+# define UNDOCARGS_4  UNDOCARGS_3 lwi   r8, r1, AC_STACK_SIZE + 16;
+# define UNDOCARGS_5  UNDOCARGS_4 lwi   r9, r1, AC_STACK_SIZE + 20;
+# define UNDOCARGS_6  UNDOCARGS_5 lwi   r10, r1, AC_STACK_SIZE + 24;
+
+# ifdef PIC
+#  define PSEUDO_JMP(sym)  brlid r15, sym##@PLTPC; addk r0, r0, r0
+# else
+#  define PSEUDO_JMP(sym)  brlid r15, sym; addk r0, r0, r0
+# endif
+
+# if defined IS_IN_libpthread
+#  define CENABLE PSEUDO_JMP (__pthread_enable_asynccancel)
+#  define CDISABLE  PSEUDO_JMP (__pthread_disable_asynccancel)
+#  define __local_multiple_threads __pthread_multiple_threads
+# elif !defined NOT_IN_libc
+#  define CENABLE PSEUDO_JMP (__libc_enable_asynccancel)
+#  define CDISABLE  PSEUDO_JMP (__libc_disable_asynccancel)
+#  define __local_multiple_threads __libc_multiple_threads
+# elif defined IS_IN_librt
+#  define CENABLE PSEUDO_JMP (__librt_enable_asynccancel)
+#  define CDISABLE  PSEUDO_JMP (__librt_disable_asynccancel)
+# else
+#  error Unsupported library
+# endif
+
+#define SINGLE_THREAD_P(reg)                                         \
+     lwi reg, r0, MULTIPLE_THREADS_OFFSET(reg)
+
+#else /* !__ASSEMBLER__ */
+# define SINGLE_THREAD_P                                             \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,                      \
+                                   header.multiple_threads) == 0, 1)
+
+#endif /* __ASSEMBLER__ */
+
+#endif

+ 5 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/vfork.S

@@ -0,0 +1,5 @@
+#define SAVE_PID
+#define RESTORE_PID
+#include <tls.h>
+#include <tcb-offsets.h>
+#include <libc/sysdeps/linux/microblaze/vfork.S>