Browse Source

nios2: sync support with glibc

Only static linking is supported for now.
More debugging and analyzing for ld.so, TLS and NPTL
is required. But at least you can bootup a static
root fileystem in Qemu.
Waldemar Brodkorb 8 years ago
parent
commit
b8fcdddcbb
53 changed files with 2337 additions and 952 deletions
  1. 0 1
      extra/Configs/Config.in
  2. 0 2
      extra/Configs/Config.nios2
  3. 50 47
      include/elf.h
  4. 18 0
      ldso/ldso/nios2/dl-debug.h
  5. 12 0
      ldso/ldso/nios2/dl-inlines.h
  6. 34 0
      ldso/ldso/nios2/dl-startup.h
  7. 1 0
      ldso/ldso/nios2/dl-syscalls.h
  8. 74 0
      ldso/ldso/nios2/dl-sysdep.h
  9. 297 0
      ldso/ldso/nios2/elfinterp.c
  10. 73 0
      ldso/ldso/nios2/resolve.S
  11. 2 9
      libc/sysdeps/linux/nios2/Makefile.arch
  12. 31 40
      libc/sysdeps/linux/nios2/__longjmp.S
  13. 18 0
      libc/sysdeps/linux/nios2/__syscall_error.c
  14. 3 3
      libc/sysdeps/linux/nios2/bits/fcntl.h
  15. 0 50
      libc/sysdeps/linux/nios2/bits/kernel_stat.h
  16. 4 2
      libc/sysdeps/linux/nios2/bits/kernel_types.h
  17. 6 24
      libc/sysdeps/linux/nios2/bits/setjmp.h
  18. 0 167
      libc/sysdeps/linux/nios2/bits/stat.h
  19. 82 91
      libc/sysdeps/linux/nios2/bits/syscalls.h
  20. 0 44
      libc/sysdeps/linux/nios2/bsd-_setjmp.S
  21. 0 51
      libc/sysdeps/linux/nios2/bsd-setjmp.S
  22. 88 64
      libc/sysdeps/linux/nios2/clone.S
  23. 0 50
      libc/sysdeps/linux/nios2/clone.c
  24. 93 54
      libc/sysdeps/linux/nios2/crt1.S
  25. 0 98
      libc/sysdeps/linux/nios2/fpu_control.h
  26. 10 6
      libc/sysdeps/linux/nios2/jmpbuf-offsets.h
  27. 33 6
      libc/sysdeps/linux/nios2/jmpbuf-unwind.h
  28. 54 47
      libc/sysdeps/linux/nios2/setjmp.S
  29. 0 47
      libc/sysdeps/linux/nios2/syscall.c
  30. 34 0
      libc/sysdeps/linux/nios2/sysdep.h
  31. 52 48
      libc/sysdeps/linux/nios2/vfork.S
  32. 1 1
      libpthread/nptl/pthread_create.c
  33. 4 0
      libpthread/nptl/sysdeps/nios2/Makefile.arch
  34. 48 0
      libpthread/nptl/sysdeps/nios2/dl-tls.h
  35. 32 0
      libpthread/nptl/sysdeps/nios2/libc-tls.c
  36. 66 0
      libpthread/nptl/sysdeps/nios2/pthread_spin_lock.c
  37. 27 0
      libpthread/nptl/sysdeps/nios2/pthread_spin_trylock.c
  38. 36 0
      libpthread/nptl/sysdeps/nios2/pthreaddef.h
  39. 14 0
      libpthread/nptl/sysdeps/nios2/tcb-offsets.sym
  40. 178 0
      libpthread/nptl/sysdeps/nios2/tls.h
  41. 9 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/Makefile
  42. 9 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/Makefile.arch
  43. 189 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/bits/pthreadtypes.h
  44. 32 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/bits/semaphore.h
  45. 3 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/clone.S
  46. 22 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/createthread.c
  47. 30 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/fork.c
  48. 281 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/lowlevellock.h
  49. 5 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/pt-gettimeofday.c
  50. 99 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/pthread_once.c
  51. 140 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/sysdep-cancel.h
  52. 38 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nios2/vfork.S
  53. 5 0
      utils/ldd.c

+ 0 - 1
extra/Configs/Config.in

@@ -522,7 +522,6 @@ config UCLIBC_HAS_THREADS_NATIVE
 		   !TARGET_ia64 && \
 		   !TARGET_m68k && \
 		   !TARGET_nds32 && \
-		   !TARGET_nios2 && \
 		   !TARGET_or1k && \
 		   ARCH_USE_MMU
 	help

+ 0 - 2
extra/Configs/Config.nios2

@@ -11,6 +11,4 @@ config FORCE_OPTIONS_FOR_ARCH
 	bool
 	default y
 	select ARCH_LITTLE_ENDIAN
-	select ARCH_HAS_NO_MMU
 	select ARCH_HAS_NO_LDSO
-	select HAVE_NO_PIC

+ 50 - 47
include/elf.h

@@ -3081,53 +3081,56 @@ typedef Elf32_Addr Elf32_Conflict;
 /* Andes ELF Version 1.3 and after */
 #define E_NDS32_ELF_VER_1_3			0x1
 
-/* NIOS relocations. */
-#define R_NIOS_NONE				0
-#define R_NIOS_32				1	/* A 32 bit absolute relocation.*/
-#define R_NIOS_LO16_LO5			2	/* A LO-16 5 bit absolute relocation.  */
-#define R_NIOS_LO16_HI11		3	/* A LO-16 top 11 bit absolute relocation.  */
-#define R_NIOS_HI16_LO5			4	/* A HI-16 5 bit absolute relocation.  */
-#define R_NIOS_HI16_HI11		5	/* A HI-16 top 11 bit absolute relocation.  */
-#define R_NIOS_PCREL6			6	/* A 6 bit relative relocation.  */
-#define R_NIOS_PCREL8			7	/* An 8 bit relative relocation.  */
-#define R_NIOS_PCREL11			8	/* An 11 bit relative relocation.  */
-#define R_NIOS_16				9	/* A 16 bit absolute relocation.  */
-#define R_NIOS_H_LO5			10	/* Low 5-bits of absolute relocation in halfwords.  */
-#define R_NIOS_H_HI11			11	/* Top 11 bits of 16-bit absolute relocation in halfwords.  */
-#define R_NIOS_H_XLO5			12	/* Low 5 bits of top 16-bits of 32-bit absolute relocation in halfwords.  */
-#define R_NIOS_H_XHI11			13	/* Top 11 bits of top 16-bits of 32-bit absolute relocation in halfwords.  */
-#define R_NIOS_H_16				14	/* Half-word @h value */
-#define R_NIOS_H_32				15	/* Word @h value */
-#define R_NIOS_GNU_VTINHERIT	200	/* GNU extension to record C++ vtable hierarchy */
-#define R_NIOS_GNU_VTENTRY		201	/* GNU extension to record C++ vtable member usage */
-/* Keep this the last entry.  */
-#define R_NIOS_NUM				202
-
-/* NIOS II relocations */
-#define R_NIOS2_NONE			0
-#define R_NIOS2_S16				1
-#define R_NIOS2_U16				2
-#define R_NIOS2_PCREL16			3
-#define R_NIOS2_CALL26			4
-#define R_NIOS2_IMM5			5
-#define R_NIOS2_CACHE_OPX		6
-#define R_NIOS2_IMM6			7
-#define R_NIOS2_IMM8			8
-#define R_NIOS2_HI16			9
-#define R_NIOS2_LO16			10
-#define R_NIOS2_HIADJ16		11
-#define R_NIOS2_BFD_RELOC_32	12
-#define R_NIOS2_BFD_RELOC_16	13
-#define R_NIOS2_BFD_RELOC_8	14
-#define R_NIOS2_GPREL			15
-#define R_NIOS2_GNU_VTINHERIT	16
-#define R_NIOS2_GNU_VTENTRY	17
-#define R_NIOS2_UJMP			18
-#define R_NIOS2_CJMP			19
-#define R_NIOS2_CALLR			20
-#define R_NIOS2_ALIGN			21
-/* Keep this the last entry.  */
-#define R_NIOS2_NUM				22
+/* Legal values for d_tag (dynamic entry type).  */
+#define DT_NIOS2_GP             0x70000002 /* Address of _gp.  */
+
+/* Nios II relocations.  */
+#define R_NIOS2_NONE		0	/* No reloc.  */
+#define R_NIOS2_S16		1	/* Direct signed 16 bit.  */
+#define R_NIOS2_U16		2	/* Direct unsigned 16 bit.  */
+#define R_NIOS2_PCREL16		3	/* PC relative 16 bit.  */
+#define R_NIOS2_CALL26		4	/* Direct call.  */
+#define R_NIOS2_IMM5		5	/* 5 bit constant expression.  */
+#define R_NIOS2_CACHE_OPX	6	/* 5 bit expression, shift 22.  */
+#define R_NIOS2_IMM6		7	/* 6 bit constant expression.  */
+#define R_NIOS2_IMM8		8	/* 8 bit constant expression.  */
+#define R_NIOS2_HI16		9	/* High 16 bit.  */
+#define R_NIOS2_LO16		10	/* Low 16 bit.  */
+#define R_NIOS2_HIADJ16		11	/* High 16 bit, adjusted.  */
+#define R_NIOS2_BFD_RELOC_32	12	/* 32 bit symbol value + addend.  */
+#define R_NIOS2_BFD_RELOC_16	13	/* 16 bit symbol value + addend.  */
+#define R_NIOS2_BFD_RELOC_8	14	/* 8 bit symbol value + addend.  */
+#define R_NIOS2_GPREL		15	/* 16 bit GP pointer offset.  */
+#define R_NIOS2_GNU_VTINHERIT	16	/* GNU C++ vtable hierarchy.  */
+#define R_NIOS2_GNU_VTENTRY	17	/* GNU C++ vtable member usage.  */
+#define R_NIOS2_UJMP		18	/* Unconditional branch.  */
+#define R_NIOS2_CJMP		19	/* Conditional branch.  */
+#define R_NIOS2_CALLR		20	/* Indirect call through register.  */
+#define R_NIOS2_ALIGN		21	/* Alignment requirement for linker relaxation.  */
+#define R_NIOS2_GOT16		22	/* 16 bit GOT entry.  */
+#define R_NIOS2_CALL16		23	/* 16 bit GOT entry for function.  */
+#define R_NIOS2_GOTOFF_LO	24	/* %lo of offset to GOT pointer.  */
+#define R_NIOS2_GOTOFF_HA	25	/* %hiadj of offset to GOT pointer.  */
+#define R_NIOS2_PCREL_LO	26	/* %lo of PC relative offset.  */
+#define R_NIOS2_PCREL_HA	27	/* %hiadj of PC relative offset.  */
+#define R_NIOS2_TLS_GD16	28	/* 16 bit GOT offset for TLS GD.  */
+#define R_NIOS2_TLS_LDM16	29	/* 16 bit GOT offset for TLS LDM.  */
+#define R_NIOS2_TLS_LDO16	30	/* 16 bit module relative offset.  */
+#define R_NIOS2_TLS_IE16	31	/* 16 bit GOT offset for TLS IE.  */
+#define R_NIOS2_TLS_LE16	32	/* 16 bit LE TP-relative offset.  */
+#define R_NIOS2_TLS_DTPMOD	33	/* Module number.  */
+#define R_NIOS2_TLS_DTPREL	34	/* Module-relative offset.  */
+#define R_NIOS2_TLS_TPREL	35	/* TP-relative offset.  */
+#define R_NIOS2_COPY		36	/* Copy symbol at runtime.  */
+#define R_NIOS2_GLOB_DAT	37	/* Create GOT entry.  */
+#define R_NIOS2_JUMP_SLOT	38	/* Create PLT entry.  */
+#define R_NIOS2_RELATIVE	39	/* Adjust by program base.  */
+#define R_NIOS2_GOTOFF		40	/* 16 bit offset to GOT pointer.  */
+#define R_NIOS2_CALL26_NOAT	41	/* Direct call in .noat section.  */
+#define R_NIOS2_GOT_LO		42	/* %lo() of GOT entry.  */
+#define R_NIOS2_GOT_HA		43	/* %hiadj() of GOT entry.  */
+#define R_NIOS2_CALL_LO		44	/* %lo() of function GOT entry.  */
+#define R_NIOS2_CALL_HA		45	/* %hiadj() of function GOT entry.  */
 
 /* Xtensa-specific declarations */
 

+ 18 - 0
ldso/ldso/nios2/dl-debug.h

@@ -0,0 +1,18 @@
+/* nios2 shared library loader suppport */
+
+static const char * const _dl_reltypes_tab[] =
+	{
+		"R_NIOS2_NONE",
+		"R_NIOS2_BFD_RELOC_32",
+		"R_NIOS2_BFD_RELOC_16",
+		"R_NIOS2_BFD_RELOC_8",
+		"R_NIOS2_GNU_VTINHERIT",
+		"R_NIOS2_GNU_VTENTRY",
+		"R_NIOS2_GOT16",
+		"R_NIOS2_CALL16",
+		"R_NIOS2_JUMP_SLOT",
+		"R_NIOS2_GLOB_DAT",
+		"R_NIOS2_RELATIVE",
+		"R_NIOS2_GOTOFF",
+		"R_NIOS2_COPY",
+	};

+ 12 - 0
ldso/ldso/nios2/dl-inlines.h

@@ -0,0 +1,12 @@
+
+unsigned int
+internal_function
+_dl_nios2_get_gp_value (struct link_map *main_map)
+{ 
+  ElfW(Dyn) *dyn = main_map->l_ld;
+  for (dyn = main_map->l_ld; dyn->d_tag != DT_NULL; ++dyn)
+    if (dyn->d_tag == DT_NIOS2_GP)
+      return (unsigned int)(dyn->d_un.d_ptr);
+  return 0;
+}
+

+ 34 - 0
ldso/ldso/nios2/dl-startup.h

@@ -0,0 +1,34 @@
+__asm__ ("\
+	.text\n\
+	.globl _start\n\
+	.type _start, %function\n\
+_start:\n\
+        mov r4, sp\n\
+        br _dl_start\n\
+	mov r16, r4\n\
+        jmp r16\n\
+");
+
+/*
+ * Get a pointer to the argv array.  On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#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)
+{
+	switch (ELF_R_TYPE(rpnt->r_info)) {
+		case R_NIOS2_RELATIVE:
+			*reloc_addr = load_addr + rpnt->r_addend;
+			break;
+		default:
+			_dl_exit(1);
+			break;
+	}
+}

+ 1 - 0
ldso/ldso/nios2/dl-syscalls.h

@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */

+ 74 - 0
ldso/ldso/nios2/dl-sysdep.h

@@ -0,0 +1,74 @@
+/* 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;				\
+} while(0)
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+
+#define MAGIC1 EM_ALTERA_NIOS2
+#undef  MAGIC2
+/* Used for error messages */
+#define ELF_TARGET "nios2"
+
+struct elf_resolve;
+unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.
+   ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type)				\
+  ((((type) == R_NIOS2_JUMP_SLOT				\
+     || (type) == R_NIOS2_TLS_DTPMOD				\
+     || (type) == R_NIOS2_TLS_DTPREL				\
+     || (type) == R_NIOS2_TLS_TPREL) * ELF_RTYPE_CLASS_PLT)	\
+   | (((type) == R_NIOS2_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
+   first element of the GOT.  */
+static inline Elf32_Addr
+elf_machine_dynamic (void)
+{
+  Elf32_Addr *dynamic;
+  int tmp;
+  __asm__ ("nextpc\t%0\n\t"
+       "1: movhi\t%1, %%hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)\n\t"
+       "addi\t%1, %1, %%lo(_GLOBAL_OFFSET_TABLE_ - 1b)\n\t"
+       "add\t%0, %0, %1\n"
+       : "=r" (dynamic), "=r" (tmp));
+  return *dynamic;
+}
+
+/* Return the run-time load address of the shared object.  */
+static inline Elf32_Addr
+elf_machine_load_address (void)
+{
+  Elf32_Addr result;
+  int tmp;
+  __asm__ ("nextpc\t%0\n\t"
+       "1: movhi\t%1, %%hiadj(1b)\n\t"
+       "addi\t%1, %1, %%lo(1b)\n\t"
+       "sub\t%0, %0, %1\n"
+       : "=r" (result), "=r" (tmp));
+  return result;
+}
+
+static __always_inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+		      Elf32_Word relative_count)
+{
+	Elf32_Rel * rpnt = (void *) rel_addr;
+	do {
+		Elf32_Addr *const reloc_addr = (void *) (load_off + (rpnt)->r_offset);
+
+		*reloc_addr += load_off;
+	} while (--relative_count);
+}
+

+ 297 - 0
ldso/ldso/nios2/elfinterp.c

@@ -0,0 +1,297 @@
+/* nios2 ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ *                              David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2004 Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ldso.h"
+
+/* Program to load an ELF binary on a linux system, and run it.
+   References to symbols in sharable libraries can be resolved by either
+   an ELF sharable library or a linux style of shared library. */
+
+extern int _dl_linux_resolve(void);
+
+unsigned long
+_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+	ELF_RELOC *this_reloc;
+	char *strtab;
+	ElfW(Sym) *symtab;
+	int symtab_index;
+	char *rel_addr;
+	char *new_addr;
+	char **got_addr;
+	ElfW(Addr) instr_addr;
+	char *symname;
+
+	rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+	this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry);
+	symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+	symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+	strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+	symname = strtab + symtab[symtab_index].st_name;
+
+	/* Address of the jump instruction to fix up. */
+	instr_addr = (this_reloc->r_offset + tpnt->loadaddr);
+	got_addr = (char **)instr_addr;
+
+	/* Get the address of the GOT entry. */
+	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+	if (unlikely(!new_addr)) {
+		_dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
+		_dl_exit(1);
+	}
+
+#if defined (__SUPPORT_LD_DEBUG__)
+	if (_dl_debug_bindings) {
+		_dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+		if (_dl_debug_detail)
+			_dl_dprintf(_dl_debug_file,
+			            "\tpatched: %x ==> %x @ %x\n",
+			            *got_addr, new_addr, got_addr);
+	}
+	if (!_dl_debug_nofixups)
+#endif
+		*got_addr = new_addr;
+
+	return (unsigned long)new_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+	  unsigned long rel_addr, unsigned long rel_size,
+	  int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+			   ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+	unsigned int i;
+	char *strtab;
+	ElfW(Sym) *symtab;
+	ELF_RELOC *rpnt;
+	int symtab_index;
+
+	/* Parse the relocation information. */
+	rpnt = (ELF_RELOC *)rel_addr;
+	rel_size /= sizeof(ELF_RELOC);
+
+	symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+	strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+	for (i = 0; i < rel_size; i++, rpnt++) {
+		int res;
+
+		symtab_index = ELF_R_SYM(rpnt->r_info);
+
+		debug_sym(symtab, strtab, symtab_index);
+		debug_reloc(symtab, strtab, rpnt);
+
+		res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
+
+		if (res == 0)
+			continue;
+
+		_dl_dprintf(2, "\n%s: ", _dl_progname);
+
+		if (symtab_index)
+			_dl_dprintf(2, "symbol '%s': ",
+				    strtab + symtab[symtab_index].st_name);
+
+		if (unlikely(res < 0)) {
+			int reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+			_dl_dprintf(2, "can't handle reloc type "
+#if defined (__SUPPORT_LD_DEBUG__)
+				    "%s\n", _dl_reltypes(reloc_type));
+#else
+				    "%x\n", reloc_type);
+#endif
+			_dl_exit(-res);
+		} else if (unlikely(res > 0)) {
+			_dl_dprintf(2, "can't resolve symbol\n");
+			return res;
+		}
+	}
+
+	return 0;
+}
+
+static int
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+	     ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+	int reloc_type;
+	int symtab_index;
+	char *symname;
+#if defined USE_TLS && USE_TLS
+	struct elf_resolve *tls_tpnt = NULL;
+#endif
+	struct symbol_ref sym_ref;
+	ElfW(Addr) *reloc_addr;
+	ElfW(Addr) symbol_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+	ElfW(Addr) old_val;
+#endif
+
+	reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+	reloc_type = ELF_R_TYPE(rpnt->r_info);
+	symtab_index = ELF_R_SYM(rpnt->r_info);
+	sym_ref.sym = &symtab[symtab_index];
+	sym_ref.tpnt = NULL;
+	symbol_addr = 0;
+	symname = strtab + sym_ref.sym->st_name;
+
+	if (symtab_index) {
+		symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
+				elf_machine_type_class(reloc_type), &sym_ref);
+		/*
+		 * We want to allow undefined references to weak symbols - this
+		 * might have been intentional.  We should not be linking local
+		 * symbols here, so all bases should be covered.
+		 */
+		if (unlikely(!symbol_addr && (ELF_ST_TYPE(sym_ref.sym->st_info) != STT_TLS)
+					&& (ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) {
+			/* This may be non-fatal if called from dlopen. */
+			return 1;
+		}
+#if defined USE_TLS && USE_TLS
+		tls_tpnt = sym_ref.tpnt;
+#endif
+	} else {
+		/* Relocs against STN_UNDEF are usually treated as using a
+		 * symbol value of zero, and using the module containing the
+		 * reloc itself. */
+		symbol_addr = sym_ref.sym->st_value;
+#if defined USE_TLS && USE_TLS
+		tls_tpnt = tpnt;
+#endif
+	}
+
+
+#if defined (__SUPPORT_LD_DEBUG__)
+	if (reloc_addr) {
+		old_val = *reloc_addr;
+	} else {
+		old_val = 0;
+	}
+#endif
+
+	switch (reloc_type) {
+		case R_NIOS2_NONE:
+			break;
+
+		case R_NIOS2_BFD_RELOC_32:
+		case R_NIOS2_GLOB_DAT:
+		case R_NIOS2_JUMP_SLOT:
+			*reloc_addr = symbol_addr + rpnt->r_addend;
+			break;
+
+		case R_NIOS2_RELATIVE:
+			*reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
+			break;
+
+		case R_NIOS2_COPY:
+			if (symbol_addr) {
+#if defined (__SUPPORT_LD_DEBUG__)
+				if (_dl_debug_move)
+					_dl_dprintf(_dl_debug_file,
+						    "\t%s move %d bytes from %x to %x\n",
+						    symname, sym_ref.sym->st_size,
+						    symbol_addr, reloc_addr);
+#endif
+
+				_dl_memcpy((char *)reloc_addr,
+					   (char *)symbol_addr,
+					   sym_ref.sym->st_size);
+			}
+			break;
+
+		default:
+			return -1;	/* Calls _dl_exit(1). */
+	}
+
+#if defined (__SUPPORT_LD_DEBUG__)
+	if (_dl_debug_reloc && _dl_debug_detail)
+		_dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
+			    old_val, *reloc_addr, reloc_addr);
+#endif
+
+	return 0;
+}
+
+static int
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+		  ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+	int reloc_type;
+	ElfW(Addr) *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+	ElfW(Addr) old_val;
+#endif
+
+	(void)scope;
+	(void)strtab;
+
+	reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset);
+	reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+	old_val = *reloc_addr;
+#endif
+
+	switch (reloc_type) {
+		case R_NIOS2_NONE:
+			break;
+		case R_NIOS2_JUMP_SLOT:
+			*reloc_addr += (unsigned long)tpnt->loadaddr;
+			break;
+		default:
+			_dl_exit(1);
+	}
+
+#if defined (__SUPPORT_LD_DEBUG__)
+	if (_dl_debug_reloc && _dl_debug_detail)
+		_dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n",
+			    old_val, *reloc_addr, reloc_addr);
+#endif
+
+	return 0;
+}
+
+void
+_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+	unsigned long rel_addr, unsigned long rel_size)
+{
+	(void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information(struct dyn_elf *rpnt,
+	struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
+{
+	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}

+ 73 - 0
ldso/ldso/nios2/resolve.S

@@ -0,0 +1,73 @@
+/* PLT trampolines.  Nios II version.
+   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/>.  */
+
+/* This code is used in dl-runtime.c to call the `fixup' function
+   and then redirect to the address it returns. */
+
+	.text
+	.align 4
+	.globl _dl_linux_resolver
+	.globl _dl_linux_resolve
+	.type  _dl_linux_resolve,@function
+
+_dl_linux_resolve:
+/* The runtime resolver receives the original function arguments in r4
+   through r7, the shared library identifier from GOT[1]? in r14, and the
+   relocation index times four in r15. It updates the corresponding PLT GOT
+   entry so that the PLT entry will transfer control directly to the target
+   in the future, and then transfers control to the target. */
+	/* Save arguments and return address.  */
+	subi sp, sp, 28
+	stw r22, 24(sp)
+	stw r8, 20(sp)  /* save r8, because this might be a call to mcount */
+	stw r7, 16(sp)
+	stw r6, 12(sp)
+	stw r5, 8(sp)
+	stw r4, 4(sp)
+	stw ra, 0(sp)
+
+	/* Get pointer to linker struct.  */
+	mov r4, r14
+
+	/* Get the relocation offset.  We're given a multiple of 4 and
+	   need a multiple of 12, so multiply by 3. */
+	slli r5, r15, 1
+	add r5, r5, r15
+
+	/* Call the fixup routine.  */
+	nextpc r22
+1:	movhi r2, %hiadj(_gp_got - 1b)
+	addi r2, r2, %lo(_gp_got - 1b)
+	add r22, r22, r2
+	ldw r2, %call(_dl_linux_resolver)(r22)
+	callr r2
+
+	/* Restore the arguments and return address.  */
+	ldw ra, 0(sp)
+	ldw r4, 4(sp)
+	ldw r5, 8(sp)
+	ldw r6, 12(sp)
+	ldw r7, 16(sp)
+	ldw r8, 20(sp)
+	ldw r22, 24(sp)
+	addi sp, sp, 28
+
+	/* Jump to the newly found address.  */
+	jmp r2
+
+    .size _dl_linux_resolve, . - _dl_linux_resolve

+ 2 - 9
libc/sysdeps/linux/nios2/Makefile.arch

@@ -1,12 +1,5 @@
 # Makefile for uClibc
-#
-# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
-#
 # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
-#
 
-CSRC-y := brk.c syscall.c
-
-SSRC-y := \
-	__longjmp.S bsd-_setjmp.S bsd-setjmp.S setjmp.S \
-	vfork.S clone.S
+CSRC-y := __syscall_error.c
+SSRC-y := __longjmp.S setjmp.S vfork.S clone.S

+ 31 - 40
libc/sysdeps/linux/nios2/__longjmp.S

@@ -1,48 +1,39 @@
-/*
- * libc/sysdeps/linux/nios2/__longjmp.S
- *
- *  Copyright (C) 2004,05,06  Microtronix Datacom Ltd
- *
- * 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 Wentao Xu <wentao@microtronix.com>
- * 
- */
+/* longjmp for Nios II.
+   Copyright (C) 2015-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
 
-#include <features.h>
-#include <jmpbuf-offsets.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 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/>.  */
 
-.globl __longjmp
-.type  __longjmp,@function
-.balign 4
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
 
-__longjmp:
-    /* return value is in r5*/
+ENTRY (__longjmp)
     mov     r2,  r5
-  
-    /* jmp_buf in r4, restore regs.  */
-    ldw     r16, (JB_REGS+ 0)(r4)
-    ldw     r17, (JB_REGS+ 4)(r4)
-    ldw     r18, (JB_REGS+ 8)(r4)
-    ldw     r19, (JB_REGS+12)(r4)
-    ldw     r20, (JB_REGS+16)(r4)
-    ldw     r21, (JB_REGS+20)(r4)
-    ldw     r22, (JB_REGS+24)(r4)
-    ldw     r23, (JB_REGS+28)(r4)
-    
-    ldw     ra, JB_PC(r4)
-    ldw     fp, JB_FP(r4)
-    ldw     gp, JB_GP(r4)
-    ldw     sp, JB_SP(r4)
-    
-#ifdef __UCLIBC_HAS_FPU__
-    RESTORE_FPU r4 JB_FPREGS
-#endif
 
-  /* return to saved RA */    
+    ldw	    r16, (JB_R16*4)(r4)
+    ldw	    r17, (JB_R17*4)(r4)
+    ldw	    r18, (JB_R18*4)(r4)
+    ldw	    r19, (JB_R19*4)(r4)
+    ldw	    r20, (JB_R20*4)(r4)
+    ldw     r21, (JB_R21*4)(r4)
+    ldw	    r22, (JB_R22*4)(r4)
+    ldw	    fp,  (JB_FP*4)(r4)
+    ldw	    ra,  (JB_RA*4)(r4)
+    ldw	    sp,  (JB_SP*4)(r4)
+  
     ret
 
-.size __longjmp,.-__longjmp
+END (__longjmp)
 libc_hidden_def(__longjmp)

+ 18 - 0
libc/sysdeps/linux/nios2/__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;
+}

+ 3 - 3
libc/sysdeps/linux/nios2/bits/fcntl.h

@@ -44,9 +44,9 @@
 #define O_ASYNC		 020000
 
 #ifdef __USE_GNU
-# define O_DIRECTORY	 040000	/* Must be a directory.	 */
-# define O_NOFOLLOW	0100000	/* Do not follow links.	 */
-# define O_DIRECT	0200000	/* Direct disk access.	*/
+# define O_DIRECTORY	0200000 /* Must be a directory.	 */
+# define O_NOFOLLOW	0400000	/* Do not follow links.	 */
+# define O_DIRECT	 040000	/* Direct disk access.	*/
 # define O_NOATIME     01000000 /* Do not set atime.  */
 # define O_CLOEXEC     02000000 /* set close_on_exec */
 # define O_PATH       010000000 /* Resolve pathname but do not open file.  */

+ 0 - 50
libc/sysdeps/linux/nios2/bits/kernel_stat.h

@@ -1,50 +0,0 @@
-#ifndef _BITS_STAT_STRUCT_H
-#define _BITS_STAT_STRUCT_H
-
-/* This file provides whatever this particular arch's kernel thinks
- * struct kernel_stat should look like...  It turns out each arch has a
- * different opinion on the subject... */
-
-struct kernel_stat {
-	unsigned short st_dev;
-	unsigned short __pad1;
-	unsigned long st_ino;
-	unsigned short st_mode;
-	unsigned short st_nlink;
-	unsigned short st_uid;
-	unsigned short st_gid;
-	unsigned short st_rdev;
-	unsigned short __pad2;
-	unsigned long  st_size;
-	unsigned long  st_blksize;
-	unsigned long  st_blocks;
-	struct timespec st_atim;
-	struct timespec st_mtim;
-	struct timespec st_ctim;
-	unsigned long  __unused4;
-	unsigned long  __unused5;
-};
-
-struct kernel_stat64 {
-	unsigned short	st_dev;
-	unsigned char	__pad0[10];
-#define _HAVE_STAT64___ST_INO
-	unsigned long	__st_ino;
-	unsigned int	st_mode;
-	unsigned int	st_nlink;
-	unsigned long	st_uid;
-	unsigned long	st_gid;
-	unsigned short	st_rdev;
-	unsigned char	__pad3[10];
-	long long	st_size;
-	unsigned long	st_blksize;
-	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
-	unsigned long	__pad4;		/* future possible st_blocks high bits */
-	struct timespec	st_atim;
-	struct timespec	st_mtim;
-	struct timespec	st_ctim;
-	unsigned long long	st_ino;
-};
-
-#endif	/*  _BITS_STAT_STRUCT_H */
-

+ 4 - 2
libc/sysdeps/linux/nios2/bits/kernel_types.h

@@ -10,10 +10,10 @@
 typedef unsigned long	__kernel_dev_t;
 typedef unsigned long	__kernel_ino_t;
 typedef unsigned short	__kernel_mode_t;
-typedef unsigned short	__kernel_nlink_t;
+typedef unsigned long	__kernel_nlink_t;
 typedef long		__kernel_off_t;
 typedef int		__kernel_pid_t;
-typedef unsigned short	__kernel_ipc_pid_t;
+typedef int		__kernel_ipc_pid_t;
 typedef unsigned int	__kernel_uid_t;
 typedef unsigned int	__kernel_gid_t;
 typedef unsigned int	__kernel_size_t;
@@ -22,6 +22,8 @@ typedef int		__kernel_ptrdiff_t;
 typedef long		__kernel_time_t;
 typedef long		__kernel_suseconds_t;
 typedef long		__kernel_clock_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
 typedef unsigned short	__kernel_uid16_t;

+ 6 - 24
libc/sysdeps/linux/nios2/bits/setjmp.h

@@ -1,5 +1,5 @@
-/* Define the machine-dependent type `jmp_buf'.  Nios2 version.
-   Copyright (C) 1992,93,95,97,2000 Free Software Foundation, Inc.
+/* Define the machine-dependent type `jmp_buf'.  Nios II version.
+   Copyright (C) 1992-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
@@ -13,7 +13,7 @@
    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
+   License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
 #ifndef _BITS_SETJMP_H
@@ -23,27 +23,9 @@
 # error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
 #endif
 
-typedef struct
-{
-    /* Callee-saved registers r16 through r23.  */
-    unsigned long __regs[8];
+/* Saves r16-r22 (callee-saved, including GOT pointer), fp (frame pointer),
+   ra (return address), and sp (stack pointer).  */
 
-    /* Program counter.  */
-    unsigned long __pc;
-
-    /* Stack pointer.  */
-    unsigned long __sp;
-
-    /* The frame pointer.  */
-    unsigned long __fp;
-
-    /* The global pointer.  */
-    unsigned long __gp;
-
-	/* floating point regs, if any */
-#ifdef __UCLIBC_HAS_FPU__
-    unsigned long __fpregs[64];
-#endif
-} __jmp_buf[1];
+typedef int __jmp_buf[10];
 
 #endif	/* bits/setjmp.h */

+ 0 - 167
libc/sysdeps/linux/nios2/bits/stat.h

@@ -1,167 +0,0 @@
-/* Copyright (C) 1992,95,96,97,98,99,2000,2001 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 _SYS_STAT_H
-# error "Never include <bits/stat.h> directly; use <sys/stat.h> instead."
-#endif
-
-/* Versions of the `struct stat' data structure.  */
-#define _STAT_VER_LINUX_OLD	1
-#define _STAT_VER_KERNEL	1
-#define _STAT_VER_SVR4		2
-#define _STAT_VER_LINUX		3
-#define _STAT_VER		_STAT_VER_LINUX	/* The one defined below.  */
-
-/* Versions of the `xmknod' interface.  */
-#define _MKNOD_VER_LINUX	1
-#define _MKNOD_VER_SVR4		2
-#define _MKNOD_VER		_MKNOD_VER_LINUX /* The bits defined below.  */
-
-
-struct stat
-  {
-    __dev_t st_dev;			/* Device.  */
-    unsigned short int __pad1;
-#ifndef __USE_FILE_OFFSET64
-    __ino_t st_ino;			/* File serial number.	*/
-#else
-    __ino_t __st_ino;			/* 32bit file serial number.	*/
-#endif
-    __mode_t st_mode;			/* File mode.  */
-    __nlink_t st_nlink;			/* Link count.  */
-    __uid_t st_uid;			/* User ID of the file's owner.	*/
-    __gid_t st_gid;			/* Group ID of the file's group.*/
-    __dev_t st_rdev;			/* Device number, if device.  */
-    unsigned short int __pad2;
-#ifndef __USE_FILE_OFFSET64
-    __off_t st_size;			/* Size of file, in bytes.  */
-#else
-    __off64_t st_size;			/* Size of file, in bytes.  */
-#endif
-    __blksize_t st_blksize;		/* Optimal block size for I/O.  */
-
-#ifndef __USE_FILE_OFFSET64
-    __blkcnt_t st_blocks;		/* Number 512-byte blocks allocated. */
-#else
-    __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */
-#endif
-#ifdef __USE_MISC
-    /* Nanosecond resolution timestamps are stored in a format
-       equivalent to 'struct timespec'.  This is the type used
-       whenever possible but the Unix namespace rules do not allow the
-       identifier 'timespec' to appear in the <sys/stat.h> header.
-       Therefore we have to handle the use of this header in strictly
-       standard-compliant sources special.  */
-    struct timespec st_atim;		/* Time of last access.  */
-    struct timespec st_mtim;		/* Time of last modification.  */
-    struct timespec st_ctim;		/* Time of last status change.  */
-# define st_atime st_atim.tv_sec	/* Backward compatibility.  */
-# define st_mtime st_mtim.tv_sec
-# define st_ctime st_ctim.tv_sec
-#else
-    __time_t st_atime;			/* Time of last access.  */
-    unsigned long int st_atimensec;	/* Nscecs of last access.  */
-    __time_t st_mtime;			/* Time of last modification.  */
-    unsigned long int st_mtimensec;	/* Nsecs of last modification.  */
-    __time_t st_ctime;			/* Time of last status change.  */
-    unsigned long int st_ctimensec;	/* Nsecs of last status change.  */
-#endif
-#ifndef __USE_FILE_OFFSET64
-    unsigned long int __unused4;
-    unsigned long int __unused5;
-#else
-    __ino64_t st_ino;			/* File serial number.	*/
-#endif
-  };
-
-#ifdef __USE_LARGEFILE64
-struct stat64
-  {
-    __dev_t st_dev;			/* Device.  */
-    unsigned int __pad1;
-
-    __ino_t __st_ino;			/* 32bit file serial number.	*/
-    __mode_t st_mode;			/* File mode.  */
-    __nlink_t st_nlink;			/* Link count.  */
-    __uid_t st_uid;			/* User ID of the file's owner.	*/
-    __gid_t st_gid;			/* Group ID of the file's group.*/
-    __dev_t st_rdev;			/* Device number, if device.  */
-    unsigned int __pad2;
-    __off64_t st_size;			/* Size of file, in bytes.  */
-    __blksize_t st_blksize;		/* Optimal block size for I/O.  */
-
-    __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */
-#ifdef __USE_MISC
-    /* Nanosecond resolution timestamps are stored in a format
-       equivalent to 'struct timespec'.  This is the type used
-       whenever possible but the Unix namespace rules do not allow the
-       identifier 'timespec' to appear in the <sys/stat.h> header.
-       Therefore we have to handle the use of this header in strictly
-       standard-compliant sources special.  */
-    struct timespec st_atim;		/* Time of last access.  */
-    struct timespec st_mtim;		/* Time of last modification.  */
-    struct timespec st_ctim;		/* Time of last status change.  */
-#else
-    __time_t st_atime;			/* Time of last access.  */
-    unsigned long int st_atimensec;	/* Nscecs of last access.  */
-    __time_t st_mtime;			/* Time of last modification.  */
-    unsigned long int st_mtimensec;	/* Nsecs of last modification.  */
-    __time_t st_ctime;			/* Time of last status change.  */
-    unsigned long int st_ctimensec;	/* Nsecs of last status change.  */
-#endif
-    __ino64_t st_ino;			/* File serial number.		*/
-  };
-#endif
-
-/* Tell code we have these members.  */
-#define	_STATBUF_ST_BLKSIZE
-#define _STATBUF_ST_RDEV
-/* Nanosecond resolution time values are supported.  */
-#define _STATBUF_ST_NSEC
-
-/* Encoding of the file mode.  */
-
-#define	__S_IFMT	0170000	/* These bits determine file type.  */
-
-/* File types.  */
-#define	__S_IFDIR	0040000	/* Directory.  */
-#define	__S_IFCHR	0020000	/* Character device.  */
-#define	__S_IFBLK	0060000	/* Block device.  */
-#define	__S_IFREG	0100000	/* Regular file.  */
-#define	__S_IFIFO	0010000	/* FIFO.  */
-#define	__S_IFLNK	0120000	/* Symbolic link.  */
-#define	__S_IFSOCK	0140000	/* Socket.  */
-
-/* POSIX.1b objects.  Note that these macros always evaluate to zero.  But
-   they do it by enforcing the correct use of the macros.  */
-#define __S_TYPEISMQ(buf)  ((buf)->st_mode - (buf)->st_mode)
-#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode)
-#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode)
-
-/* Protection bits.  */
-
-#define	__S_ISUID	04000	/* Set user ID on execution.  */
-#define	__S_ISGID	02000	/* Set group ID on execution.  */
-#define	__S_ISVTX	01000	/* Save swapped text after use (sticky).  */
-#define	__S_IREAD	0400	/* Read by owner.  */
-#define	__S_IWRITE	0200	/* Write by owner.  */
-#define	__S_IEXEC	0100	/* Execute by owner.  */
-
-#ifdef __USE_ATFILE
-# define UTIME_NOW	((1l << 30) - 1l)
-# define UTIME_OMIT	((1l << 30) - 2l)
-#endif

+ 82 - 91
libc/sysdeps/linux/nios2/bits/syscalls.h

@@ -4,106 +4,97 @@
 # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
 #endif
 
-#define TRAP_ID_SYSCALL	0
+#ifdef __ASSEMBLER__
 
-#ifndef __ASSEMBLER__
+#undef DO_CALL
+#define DO_CALL(syscall_name, args) \
+    DOARGS_##args                   \
+    movi r2, SYS_ify(syscall_name);  \
+    trap;
 
-#include <errno.h>
-
-#define __syscall_return(type, res)					\
-	do {								\
-		if (unlikely(INTERNAL_SYSCALL_ERROR_P(res, ))) {	\
-			__set_errno(INTERNAL_SYSCALL_ERRNO(res, ));	\
-			res = (unsigned long) -1;			\
-		}							\
-		return (type) (res);					\
-	} while (0)
+#define DOARGS_0 /* nothing */
+#define DOARGS_1 /* nothing */
+#define DOARGS_2 /* nothing */
+#define DOARGS_3 /* nothing */
+#define DOARGS_4 /* nothing */
+#define DOARGS_5 ldw r8, 0(sp);
+#define DOARGS_6 ldw r9, 4(sp); ldw r8, 0(sp);
 
-#define INTERNAL_SYSCALL_NCS(name, err, nr, args...)			\
-(__extension__ \
-	({								\
-		long __res;						\
-		__asm__ __volatile__ (					\
-			"movi    r2,    %2\n\t"   /* TRAP_ID_SYSCALL */ \
-			"movi    r3,    %1\n\t"   /* __NR_##name     */	\
-			ASM_ARGS_##nr					\
-			"trap\n\t"					\
-			"mov     %0,    r2\n\t"   /* syscall return  */	\
-			:   "=r" (__res)          /* %0              */	\
-			:   "i" (name)            /* %1              */	\
-			  , "i" (TRAP_ID_SYSCALL) /* %2              */	\
-			  MAP_ARGS_##nr (args)    /* %3-%8           */	\
-			:   "r2"					\
-			  , "r3"					\
-			  CLOB_ARGS_##nr          /* Clobbered       */ \
-		);							\
-		__res;							\
-	}) \
-)
+#else
 
-#define INTERNAL_SYSCALL_ERROR_P(val, err)	\
-	((unsigned long)(val) >= (unsigned long)(-125))
-
-#define ASM_ARGS_0
-#define MAP_ARGS_0()
-#define CLOB_ARGS_0
-
-#define ASM_ARGS_1		\
-	"mov     r4,    %3\n\t"
-#define MAP_ARGS_1(a)		\
-	, "r" ((long) a)
-#define CLOB_ARGS_1		\
-	, "r4"
+#include <errno.h>
 
-#define ASM_ARGS_2		\
-	ASM_ARGS_1		\
-	"mov     r5,    %4\n\t"
-#define MAP_ARGS_2(a, b)	\
-	MAP_ARGS_1(a)		\
-	, "r" ((long) b)
-#define CLOB_ARGS_2		\
-	CLOB_ARGS_1		\
-	, "r5"
+#undef INTERNAL_SYSCALL_DECL
+#define INTERNAL_SYSCALL_DECL(err) unsigned int err __attribute__((unused))
 
-#define ASM_ARGS_3		\
-	ASM_ARGS_2		\
-	"mov     r6,    %5\n\t"
-#define MAP_ARGS_3(a, b, c)	\
-	MAP_ARGS_2(a, b)	\
-	, "r" ((long) c)
-#define CLOB_ARGS_3		\
-	CLOB_ARGS_2		\
-	, "r6"
+#undef INTERNAL_SYSCALL_ERROR_P
+#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (unsigned int) (err))
 
-#define ASM_ARGS_4		\
-	ASM_ARGS_3		\
-	"mov     r7,    %6\n\t"
-#define MAP_ARGS_4(a, b, c, d)	\
-	MAP_ARGS_3(a, b, c)	\
-	, "r" ((long) d)
-#define CLOB_ARGS_4		\
-	CLOB_ARGS_3		\
-	, "r7"
+#undef INTERNAL_SYSCALL_ERRNO
+#define INTERNAL_SYSCALL_ERRNO(val, err)   ((void) (err), val)
 
-#define ASM_ARGS_5		\
-	ASM_ARGS_4		\
-	"mov     r8,    %7\n\t"
-#define MAP_ARGS_5(a, b, c, d, e)	\
-	MAP_ARGS_4(a, b, c, d)		\
-	, "r" ((long) e)
-#define CLOB_ARGS_5		\
-	CLOB_ARGS_4		\
-	, "r8"
+#undef INTERNAL_SYSCALL_NCS
+#define INTERNAL_SYSCALL_NCS(name, err, nr, args...)            \
+  ({ unsigned int _sys_result;                                  \
+     {                                                          \
+       LOAD_ARGS_##nr (args)					\
+       LOAD_REGS_##nr						\
+       register int _r2 __asm__ ("r2") = (int)(name);           \
+       register int _sys_err __asm__ ("r7");                        \
+       __asm__ volatile ("trap"                                 \
+                     : "+r" (_r2), "=r" (_sys_err)              \
+                     : ASM_ARGS_##nr				\
+                     : "memory");                               \
+       _sys_result = _r2;                                       \
+       err = _sys_err;						\
+     }                                                          \
+     (int) _sys_result; })
 
-#define ASM_ARGS_6		\
-	ASM_ARGS_5		\
-	"mov     r9,    %8\n\t"
-#define MAP_ARGS_6(a, b, c, d, e, f)	\
-	MAP_ARGS_5(a, b, c, d, e)	\
-	, "r" ((long) f)
-#define CLOB_ARGS_6		\
-	CLOB_ARGS_5		\
-	, "r9"
+#define LOAD_ARGS_0()
+#define LOAD_REGS_0
+#define ASM_ARGS_0
+#define LOAD_ARGS_1(a1)				\
+  LOAD_ARGS_0 ()				\
+  int __arg1 = (int) (a1);
+#define LOAD_REGS_1				\
+  register int _r4 __asm__ ("r4") = __arg1;	\
+  LOAD_REGS_0
+#define ASM_ARGS_1                  "r" (_r4)
+#define LOAD_ARGS_2(a1, a2)			\
+  LOAD_ARGS_1 (a1)				\
+  int __arg2 = (int) (a2);
+#define LOAD_REGS_2				\
+  register int _r5 __asm__ ("r5") = __arg2;	\
+  LOAD_REGS_1
+#define ASM_ARGS_2      ASM_ARGS_1, "r" (_r5)
+#define LOAD_ARGS_3(a1, a2, a3)			\
+  LOAD_ARGS_2 (a1, a2)				\
+  int __arg3 = (int) (a3);
+#define LOAD_REGS_3				\
+  register int _r6 __asm__ ("r6") = __arg3;	\
+  LOAD_REGS_2
+#define ASM_ARGS_3      ASM_ARGS_2, "r" (_r6)
+#define LOAD_ARGS_4(a1, a2, a3, a4)		\
+  LOAD_ARGS_3 (a1, a2, a3)			\
+  int __arg4 = (int) (a4);
+#define LOAD_REGS_4				\
+  register int _r7 __asm__ ("r7") = __arg4;	\
+  LOAD_REGS_3
+#define ASM_ARGS_4      ASM_ARGS_3, "r" (_r7)
+#define LOAD_ARGS_5(a1, a2, a3, a4, a5)		\
+  LOAD_ARGS_4 (a1, a2, a3, a4)			\
+  int __arg5 = (int) (a5);
+#define LOAD_REGS_5				\
+  register int _r8 __asm__ ("r8") = __arg5;	\
+  LOAD_REGS_4
+#define ASM_ARGS_5      ASM_ARGS_4, "r" (_r8)
+#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)	\
+  LOAD_ARGS_5 (a1, a2, a3, a4, a5)		\
+  int __arg6 = (int) (a6);
+#define LOAD_REGS_6			    \
+  register int _r9 __asm__ ("r9") = __arg6;     \
+  LOAD_REGS_5
+#define ASM_ARGS_6      ASM_ARGS_5, "r" (_r9)
 
 #endif /* __ASSEMBLER__ */
 #endif /* _BITS_SYSCALLS_H */

+ 0 - 44
libc/sysdeps/linux/nios2/bsd-_setjmp.S

@@ -1,44 +0,0 @@
-/*
- * libc/sysdeps/linux/nios2/bsd-_setjmp.S
- *
- *  Copyright (C) 2004,05,06  Microtronix Datacom Ltd
- *
- * 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 Wentao Xu <wentao@microtronix.com>
- * 
- */
-
-#include <features.h>
-#include <jmpbuf-offsets.h>
-
-   .globl _setjmp
-   .type  _setjmp,@function
-   .balign 4
-
-_setjmp:
-    stw     r16, (JB_REGS+ 0)(r4)
-    stw     r17, (JB_REGS+ 4)(r4)
-    stw     r18, (JB_REGS+ 8)(r4)
-    stw     r19, (JB_REGS+12)(r4)
-    stw     r20, (JB_REGS+16)(r4)
-    stw     r21, (JB_REGS+20)(r4)
-    stw     r22, (JB_REGS+24)(r4)
-    stw     r23, (JB_REGS+28)(r4)
-    
-    stw     ra, JB_PC(r4)
-    stw     sp, JB_SP(r4)
-    stw     fp, JB_FP(r4)
-    stw     gp, JB_GP(r4)
-    
-#ifdef __UCLIBC_HAS_FPU__
-    SAVE_FPU r4 JB_FPREGS
-#endif
-    stw     r0, JB_SIZE(r4) /* signal mask is not saved */
-    mov     r2, zero
-    ret
-
-
-

+ 0 - 51
libc/sysdeps/linux/nios2/bsd-setjmp.S

@@ -1,51 +0,0 @@
-/*
- * libc/sysdeps/linux/nios2/bsd-setjmp.S
- *
- *  Copyright (C) 2004,05,06  Microtronix Datacom Ltd
- *
- * 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 Wentao Xu <wentao@microtronix.com>
- * 
- */
-
-
-#include <features.h>
-#include <jmpbuf-offsets.h>
-
-   .globl setjmp
-   .type  setjmp,@function
-   .balign 4
-
-setjmp:
-    stw     r16, (JB_REGS+ 0)(r4)
-    stw     r17, (JB_REGS+ 4)(r4)
-    stw     r18, (JB_REGS+ 8)(r4)
-    stw     r19, (JB_REGS+12)(r4)
-    stw     r20, (JB_REGS+16)(r4)
-    stw     r21, (JB_REGS+20)(r4)
-    stw     r22, (JB_REGS+24)(r4)
-    stw     r23, (JB_REGS+28)(r4)
-    
-    stw     ra, JB_PC(r4)
-    stw     sp, JB_SP(r4)
-    stw     fp, JB_FP(r4)
-    stw     gp, JB_GP(r4)
-    
-#ifdef __UCLIBC_HAS_FPU__
-    SAVE_FPU r4 JB_FPREGS
-#endif
-
-    movui r5, 1
-#ifdef __PIC__
-    /* just pray 16 bit offset is enough */
-    br __sigjmp_save
-#else
-    movhi r8, %hi(__sigjmp_save)
-    ori r8, r8, %lo(__sigjmp_save)    
-    jmp r8
-#endif
-
-

+ 88 - 64
libc/sysdeps/linux/nios2/clone.S

@@ -1,70 +1,94 @@
-/*
- * libc/sysdeps/linux/nios2/clone.S -- `clone' syscall for linux/nios2
- *
- *  Copyright (C) 2004  Microtronix Datacom Ltd
- *
- * 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 Wentao Xu <wentao@microtronix.com>
- */
-
-#define _ERRNO_H
+/* clone() implementation for Nios II.
+   Copyright (C) 2008-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andrew Jenner <andrew@codesourcery.com>, 2008.
+
+   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>
-#include <sys/syscall.h>
-
-#ifdef __NR_clone
-/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
-
-.text
-.global clone
-.type   clone,%function
-.align 4
-clone:
-	addi    sp,sp,-8
-	mov     r8,r4
-	stw     ra,4(sp)
-	stw     r16,0(sp)
-
-	mov     r4,r6
-	movi    r2,-EINVAL
-	
-	/* sanity check */
-	beq     r8,zero,CLONE_ERROR_LABEL
-	beq     r5,zero,CLONE_ERROR_LABEL
-	
-	/* system call */
-	movi    r2,TRAP_ID_SYSCALL
-	movi    r3,__NR_clone
-	trap
-	
-	/* child call the function */
-	mov     r4,r7
-	bne     r2,zero,CLONE_ERROR_LABEL
-	callr   r8
-	
-	/* exit if it returns */
-	mov     r4,r2
-	movi    r3,__NR_exit
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <tcb-offsets.h>
+#endif
+
+#define CLONE_VM      0x00000100
+
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+	     void *parent_tidptr, void *tls, void *child_tidptr) */
+
+	.text
+ENTRY(__clone)
+	/* Sanity check arguments.  */
+	movi	r2, EINVAL
+
+	subi	r5, r5, 8	/* Reserve argument save space.  */
+	stw	r4, 4(r5)	/* Save function pointer.  */
+	stw	r7, 0(r5)	/* Save argument pointer.  */
+
+	/* Load arguments.  */
+	mov	r4, r6
+	ldw	r6, 0(sp)
+	ldw	r7, 8(sp)
+	ldw	r8, 4(sp)
+
+	/* Do the system call.  */
+	movi	r2, SYS_ify (clone)
+
 	trap
-	
-CLONE_ERROR_LABEL: 
-	movi    r3,-4096
-	sub     r16,zero,r2
-	bgeu    r3,r2,CLONE_OK
-	
-	/* store errno */
-	call    __errno_location
-	stw     r16,0(r2)
-	movi    r2,-1
-
-CLONE_OK:
-	ldw     ra,4(sp)
-	ldw     r16,0(sp)
-	addi    sp,sp,8
+
+	/* See if we're on the newly created thread.  */
+	beq	r2, zero, thread_start
+	/* Successful return from the parent */
 	ret
 
-.size clone,.-clone
+thread_start:
+	/* We expect the argument registers to be preserved across system
+	   calls and across task cloning, so flags should be in r4 here.  */
+	andi	r2, r4, CLONE_VM
+	bne	r2, zero, 2f
+        DO_CALL (getpid, 0)
+#ifdef RESET_PID
+	stw	r2, PID_OFFSET(r23)
+	stw	r2, TID_OFFSET(r23)
+#endif
+2:
+	ldw	r5, 4(sp)	/* Function pointer.  */
+	ldw	r4, 0(sp)	/* Argument pointer.  */
+	addi	sp, sp, 8
+
+        /* Call the user's function.  */
+	callr	r5
 
+	/* _exit with the result.  */
+	mov	r4, r2
+#ifdef __PIC__
+	nextpc	r22
+1:	movhi	r8, %hiadj(_gp_got - 1b)
+	addi	r8, r8, %lo(_gp_got - 1b)
+	add	r22, r22, r8
+	ldw	r8, %call(HIDDEN_JUMPTARGET(_exit))(r22)
+	jmp	r8
+#else
+	jmpi	_exit
 #endif
+
+END(__clone)
+libc_hidden_def (__clone)
+weak_alias (__clone, clone)

+ 0 - 50
libc/sysdeps/linux/nios2/clone.c

@@ -1,50 +0,0 @@
-/*
- * libc/sysdeps/linux/nios2/clone.c -- `clone' syscall for linux/nios2
- * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- *
- *
- *  Copyright (C) 2004,05  Microtronix Datacom Ltd
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *
- * Written by Miles Bader <miles@gnu.org>
- * Nios2 port by Wentao Xu
- */
-
-#include <errno.h>
-#include <sched.h>
-#include <sys/syscall.h>
-
-int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg, ...)
-{
-  register unsigned long rval __asm__ ("r2") = -EINVAL;
-
-  if (fn && child_stack) {
-      register unsigned long syscall __asm__ ("r3");
-      register unsigned long arg0 __asm__ ("r4");
-      register unsigned long arg1 __asm__ ("r5");
-
-      /* Clone this thread.  */
-      rval = TRAP_ID_SYSCALL;
-      syscall = __NR_clone;
-      arg0 = flags;
-      arg1 = (unsigned long)child_stack;
-      __asm__ __volatile__ ("trap "
-         : "=r" (rval), "=r" (syscall)
-         : "0" (rval),"1" (syscall), "r" (arg0), "r" (arg1)
-         );
-
-      if (rval == 0) {
-         /* In child thread, call fn and exit.  */
-         arg0 = (*fn) (arg);
-         syscall = __NR_exit;
-         __asm__ __volatile__ ("trap "
-          : "=r" (rval), "=r" (syscall)
-          : "1" (syscall), "r" (arg0));
-      }
-   }
-
-  __syscall_return (int, rval);
-}

+ 93 - 54
libc/sysdeps/linux/nios2/crt1.S

@@ -1,20 +1,40 @@
-/*
- * libc/sysdeps/linux/nios2/crt0.S -- entry point for linux/nios2
- *
- *  Copyright (C) 2004,05,06  Microtronix Datacom Ltd
- *
- * 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 Wentao Xu <wentao@microtronix.com>
- * Updated by Thomas Chou <thomas@wytron.com.tw> for crt1.S
- * 
- */
+/* Startup code for Nios II
+   Copyright (C) 1995-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.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file. (The GNU Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so. The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   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 <features.h>
 #include <asm/unistd.h>
-#define TRAP_ID_SYSCALL        0
 
     .global _start
     .type   _start,@function
@@ -27,45 +47,64 @@
     .type   main,@function
     .type   __uClibc_main,@function
     .text
-	.balign 4
+
 _start:
-    nop
-    br 0f
-0:
-    /* load gp */
-    movhi gp, %hiadj(_gp)
-    addi gp, gp, %lo(_gp)
-
-    /* load main, argc, argv from stack */
-    movhi r4, %hi(main)
-    ori  r4, r4, %lo(main)	/* main */
-    ldw r5, 0(sp)		/* argc */
-    ldw r6, 4(sp)		/* argv */
-
-    /* load the 4th arg */
-    movhi r7, %hi(_init)
-    ori  r7, r7, %lo(_init)
-
-    /* Allocate space on the stack for 6-7th arg, reuse 5th space */
-    addi sp,sp,-8
-    /* push 5-7th args on stack */
-    movhi r8, %hi(_fini)
-    ori  r8, r8, %lo(_fini)
-    stw  r8, 0(sp)
-
-    stw  r2, 4(sp)		/* rtld_fini */
-    stw  sp, 8(sp)		/* stack_end */
-
-    /* call uClibc_main, shouldn't return */
-#ifdef __PIC__
-    /* just pray 16 bit offset is enough */
-    br __uClibc_main
-#else
-    call __uClibc_main
-#endif
+	/* Set up the global pointer.  */
+	movhi	gp, %hiadj(_gp)
+	addi	gp, gp, %lo(_gp)
+
+	/* Save the stack pointer.  */
+	mov	r2, sp
+
+	/* Create room on the stack for the fini, rtld_fini and stack_end args
+	   to __uClibc_main. */
+	subi	sp, sp, 12
+
+	/* Push stack_end */
+	stw	r2, 8(sp)
+
+	/* Push rtld_fini */
+	stw	r4, 4(sp)
+
+	/* Set up the GOT pointer.  */
+	nextpc	r22
+1:	movhi	r2, %hiadj(_gp_got - 1b)
+	addi	r2, r2, %lo(_gp_got - 1b)
+	add	r22, r22, r2
+
+	/* r6 == argv */
+	addi	r6, sp, 16
+
+	/* r5 == argc */
+	ldw	r5, 12(sp)
+
+	/* r4 == main */
+	movhi	r4, %call_hiadj(main)
+	addi	r4, r4, %call_lo(main)
+	add	r4, r4, r22
+	ldw	r4, 0(r4)
+
+	/* fp == 0 */
+	mov	fp, zero
+
+	/* Let the libc call main and exit with its return code.  */
+	movhi	r2, %call_hiadj(__uClibc_main)
+	addi	r2, r2, %call_lo(__uClibc_main)
+	add	r2, r2, r22
+	ldw	r2, 0(r2)
+	callr	r2
+
+	/* should never get here....*/
+	movhi	r2, %call_hiadj(abort)
+	addi	r2, r2, %call_lo(abort)
+	add	r2, r2, r22
+	ldw	r2, 0(r2)
+	callr	r2
 
-    /* crash in the event of return */
-__exit:
-    movui r2, TRAP_ID_SYSCALL
-    movui r3, __NR_exit
-    trap
+/* Define a symbol for the first piece of initialized data.  */
+	.data
+	.globl __data_start
+__data_start:
+	.long 0
+	.weak data_start
+	data_start = __data_start

+ 0 - 98
libc/sysdeps/linux/nios2/fpu_control.h

@@ -1,98 +0,0 @@
-/* FPU control word bits.  Nios2 version.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000 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 _FPU_CONTROL_H
-#define _FPU_CONTROL_H
-
-/* MIPS FPU floating point control register bits.
- *
- * 31-25  -> floating point conditions code bits 7-1.  These bits are only
- *           available in MIPS IV.
- * 24     -> flush denormalized results to zero instead of
- *           causing unimplemented operation exception.  This bit is only
- *           available for MIPS III and newer.
- * 23     -> Condition bit
- * 22-18  -> reserved (read as 0, write with 0)
- * 17     -> cause bit for unimplemented operation
- * 16     -> cause bit for invalid exception
- * 15     -> cause bit for division by zero exception
- * 14     -> cause bit for overflow exception
- * 13     -> cause bit for underflow exception
- * 12     -> cause bit for inexact exception
- * 11     -> enable exception for invalid exception
- * 10     -> enable exception for division by zero exception
- *  9     -> enable exception for overflow exception
- *  8     -> enable exception for underflow exception
- *  7     -> enable exception for inexact exception
- *  6     -> flag invalid exception
- *  5     -> flag division by zero exception
- *  4     -> flag overflow exception
- *  3     -> flag underflow exception
- *  2     -> flag inexact exception
- *  1-0   -> rounding control
- *
- *
- * Rounding Control:
- * 00 - rounding to nearest (RN)
- * 01 - rounding toward zero (RZ)
- * 10 - rounding (up) toward plus infinity (RP)
- * 11 - rounding (down)toward minus infinity (RM)
- */
-
-#include <features.h>
-
-/* masking of interrupts */
-#define _FPU_MASK_V     0x0800  /* Invalid operation */
-#define _FPU_MASK_Z     0x0400  /* Division by zero  */
-#define _FPU_MASK_O     0x0200  /* Overflow          */
-#define _FPU_MASK_U     0x0100  /* Underflow         */
-#define _FPU_MASK_I     0x0080  /* Inexact operation */
-
-/* flush denormalized numbers to zero */
-#define _FPU_FLUSH_TZ   0x1000000
-
-/* rounding control */
-#define _FPU_RC_NEAREST 0x0     /* RECOMMENDED */
-#define _FPU_RC_ZERO    0x1
-#define _FPU_RC_UP      0x2
-#define _FPU_RC_DOWN    0x3
-
-#define _FPU_RESERVED 0xfe3c0000  /* Reserved bits in cw */
-
-
-/* The fdlibm code requires strict IEEE double precision arithmetic,
-   and no interrupts for exceptions, rounding to nearest.  */
-
-#define _FPU_DEFAULT  0x00000000
-
-/* IEEE:  same as above, but exceptions */
-#define _FPU_IEEE     0x00000F80
-
-/* Type of the control word.  */
-typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
-
-/* Macros for accessing the hardware control word.  */
-#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw))
-#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw))
-
-#if 0
-/* Default control word set at startup.  */
-extern fpu_control_t __fpu_control;
-#endif
-
-#endif	/* fpu_control.h */

+ 10 - 6
libc/sysdeps/linux/nios2/jmpbuf-offsets.h

@@ -6,12 +6,16 @@
 
 #include <features.h>
 
-#define JB_REGS		0
-#define JB_PC		32
-#define JB_SP		36
-#define JB_FP		40
-#define JB_GP		44
-#define JB_FPREGS 	48
+#define JB_R16 0
+#define JB_R17 1
+#define JB_R18 2
+#define JB_R19 3
+#define JB_R20 4
+#define JB_R21 5
+#define JB_R22 6
+#define JB_FP  7
+#define JB_RA  8
+#define JB_SP  9
 
 #ifdef __UCLIBC_HAS_FPU__
 # define JB_SIZE 304

+ 33 - 6
libc/sysdeps/linux/nios2/jmpbuf-unwind.h

@@ -1,12 +1,39 @@
-/*
- * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
+/* Examine __jmp_buf for unwinding frames.  Nios II version.
+   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 <setjmp.h>
+#include <jmpbuf-offsets.h>
 
 /* Test if longjmp to JMPBUF would unwind the frame
    containing a local variable at ADDRESS.  */
+
 #define _JMPBUF_UNWINDS(jmpbuf, address) \
-  ((void *) (address) < (void *) (jmpbuf)->__sp)
+  ((void *) (address) < (void *) (jmpbuf[JB_SP]))
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+
+#include <stdint.h>
+#include <unwind.h>
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj))
+
+#endif

+ 54 - 47
libc/sysdeps/linux/nios2/setjmp.S

@@ -1,49 +1,56 @@
-/*
- * libc/sysdeps/linux/nios2/setjmp.S
- *
- *  Copyright (C) 2004,05,06  Microtronix Datacom Ltd
- *
- * 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 Wentao Xu <wentao@microtronix.com>
- * 
- */
-
-#include <features.h>
+/* setjmp for Nios II.
+   Copyright (C) 1991-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 <jmpbuf-offsets.h>
 
-.globl __sigsetjmp
-.type  __sigsetjmp,@function
-.balign 4
-
-__sigsetjmp:
-    stw     r16, (JB_REGS+ 0)(r4)
-    stw     r17, (JB_REGS+ 4)(r4)
-    stw     r18, (JB_REGS+ 8)(r4)
-    stw     r19, (JB_REGS+12)(r4)
-    stw     r20, (JB_REGS+16)(r4)
-    stw     r21, (JB_REGS+20)(r4)
-    stw     r22, (JB_REGS+24)(r4)
-    stw     r23, (JB_REGS+28)(r4)
-    
-    stw     ra, JB_PC(r4)
-    stw     sp, JB_SP(r4)
-    stw     fp, JB_FP(r4)
-    stw     gp, JB_GP(r4)
-    
-#ifdef __UCLIBC_HAS_FPU__
-    SAVE_FPU r4 JB_FPREGS
-#endif
-
-#ifdef   __PIC__
-    /* just pray 16 bit offset is enough */
-    br __sigjmp_save
-#else
-    movhi r8, %hi(__sigjmp_save)
-    ori r8, r8, %lo(__sigjmp_save)    
-    jmp r8
-#endif
-
-.size __sigsetjmp,.-__sigsetjmp
+	.text
+ENTRY(setjmp)
+	movi	r5, 1
+	br	__sigsetjmp
+END(setjmp)
+libc_hidden_def(setjmp)
+
+ENTRY(_setjmp)
+	mov	r5, zero
+	br	__sigsetjmp
+END(_setjmp)
+libc_hidden_def(_setjmp)
+
+/* Save the current program position in ENV and return 0.  */
+ENTRY(__sigsetjmp)
+	stw	r16, (JB_R16*4)(r4)
+	stw	r17, (JB_R17*4)(r4)
+	stw	r18, (JB_R18*4)(r4)
+	stw	r19, (JB_R19*4)(r4)
+	stw	r20, (JB_R20*4)(r4)
+	stw	r21, (JB_R21*4)(r4)
+	stw	r22, (JB_R22*4)(r4)
+	stw	fp,  (JB_FP*4)(r4)
+	stw	ra,  (JB_RA*4)(r4)
+	stw	sp,  (JB_SP*4)(r4)
+	/* Save the signal mask if requested.  */
+        nextpc r2
+
+1:	movhi r3, %hiadj(__sigjmp_save - 1b)
+	addi r3, r3, %lo(__sigjmp_save - 1b)
+	add r2, r2, r3
+	jmp r2
+
+END(__sigsetjmp)
+libc_hidden_def(__sigsetjmp)

+ 0 - 47
libc/sysdeps/linux/nios2/syscall.c

@@ -1,47 +0,0 @@
-/*
- * libc/sysdeps/linux/nios2/syscall.c -- generic syscall function for linux/nios2
- *
- * Copyright (C) 2004 Microtronix Datacom Ltd.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program 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 Library General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this program; see the file COPYING.LIB.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-#include <features.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/syscall.h>
-
-
-long syscall(long sysnum, long a, long b, long c, long d, long e, long f)
-{
-    register long _r2 __asm__("r2")=(long)TRAP_ID_SYSCALL;
-    register long _r3 __asm__("r3")=(long)sysnum;
-
-    register long _r4 __asm__("r4")=(long)(a);
-    register long _r5 __asm__("r5")=(long)(b);
-    register long _r6 __asm__("r6")=(long)(c);
-    register long _r7 __asm__("r7")=(long)(d);
-    register long _r8 __asm__("r8")=(long)(e);
-    register long _r9 __asm__("r9")=(long)(f);
-    __asm__ __volatile__(
-	    "trap "
-	    : "=r"(_r2), "=r"(_r3)
-	    : "0"(_r2), "1"(_r3),
-	      "r"(_r4), "r"(_r5), "r"(_r6), "r"(_r7), "r"(_r8), "r"(_r9)
-	    : "memory");
-
-  __syscall_return (long, _r2);
-}
-

+ 34 - 0
libc/sysdeps/linux/nios2/sysdep.h

@@ -0,0 +1,34 @@
+/* Assembler macros for Nios II.
+   Copyright (C) 2015-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__
+
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
+
+#define ENTRY(name)						 \
+  .globl C_SYMBOL_NAME(name);					 \
+  .type C_SYMBOL_NAME(name),%function;				 \
+  C_LABEL(name)
+
+#undef  END
+#define END(name)				\
+  ASM_SIZE_DIRECTIVE(name)
+
+#endif	/* __ASSEMBLER__ */

+ 52 - 48
libc/sysdeps/linux/nios2/vfork.S

@@ -1,50 +1,54 @@
-/*
- * libc/sysdeps/linux/nios2/vfork.S -- `vfork' syscall for linux/nios2
- *
- *  Copyright (C) 2004  Microtronix Datacom Ltd
- *
- * 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 Wentao Xu <wentao@microtronix.com>
- */
-
-#include <sys/syscall.h>
-
-#define __NR_vfork 1071
-
-.text
-.global	__vfork
-.hidden	__vfork
-.type	__vfork,%function
-.align 4
-__vfork:
-    movui   r2, TRAP_ID_SYSCALL
-    movui   r3, __NR_vfork
-    trap
-    movi    r8, -4096
-    bltu    r8, r2, fix_errno
-    ret
-fix_errno:
-    sub     r8, r0, r2
-    
-    addi    sp, sp, -8
-    stw     ra, 4(sp)
-    stw     r8, 0(sp)
-#ifndef __PIC__
-    call    __errno_location
-#else
-    
+/* vfork for Nios II Linux.
+   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>
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <tcb-offsets.h>
+#endif
+
+ENTRY(__vfork)
+
+#ifdef RESET_PID
+	ldw	r6, PID_OFFSET(r23)
+	sub	r7, zero, r6
+	bne	r7, zero, 2f
+	movhi	r7, %hi(0x80000000)
+2:
+	stw	r7, PID_OFFSET(r23)
 #endif
-    ldw     ra, 4(sp)
-    ldw     r8, 0(sp)
-    stw     r8, 0(r2)
-    
-    addi    r2, r0, -1
-    addi  sp, sp, 8
-    ret
-
-.size __vfork,.-__vfork
-weak_alias(__vfork,vfork)
+
+	movi	r4, 0x4111 /* (CLONE_VM | CLONE_VFORK | SIGCHLD) */
+	mov	r5, zero
+
+	/* Do the system call.  */
+    	movi 	r2, SYS_ify(clone)
+
+    	trap
+
+	beq	r2, zero, 1f
+#ifdef RESET_PID
+	stw	r6, PID_OFFSET(r23)
+#endif
+1:
+	ret
+
+END(__vfork)
+
+weak_alias(__vfork, vfork)
 libc_hidden_def(vfork)

+ 1 - 1
libpthread/nptl/pthread_create.c

@@ -454,7 +454,7 @@ __pthread_create_2_1 (
      performed in 'get_cached_stack'.  This way we avoid doing this if
      the stack freshly allocated with 'mmap'.  */
 
-#ifdef TLS_TCB_AT_TP
+#if TLS_TCB_AT_TP
   /* Reference to the TCB itself.  */
   pd->header.self = pd;
 

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

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

+ 48 - 0
libpthread/nptl/sysdeps/nios2/dl-tls.h

@@ -0,0 +1,48 @@
+/* Thread-local storage handling in the ELF dynamic linker.  Nios II 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/>.  */
+
+
+/* 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;
+
+/* The thread pointer points 0x7000 past the first static TLS block.  */
+#define TLS_TP_OFFSET		0x7000
+
+/* Dynamic thread vector pointers point 0x8000 past the start of each
+   TLS block.  */
+#define TLS_DTV_OFFSET		0x8000
+
+/* Compute the value for a GOTTPREL reloc.  */
+#define TLS_TPREL_VALUE(sym_map, sym) \
+  ((sym_map)->l_tls_offset + (sym)->st_value - TLS_TP_OFFSET)
+
+/* Compute the value for a DTPREL reloc.  */
+#define TLS_DTPREL_VALUE(sym) \
+  ((sym)->st_value - TLS_DTV_OFFSET)
+
+extern void *__tls_get_addr (tls_index *ti);
+
+# define GET_ADDR_OFFSET	(ti->ti_offset + TLS_DTV_OFFSET)
+# define __TLS_GET_ADDR(__ti)	(__tls_get_addr (__ti) - TLS_DTV_OFFSET)
+
+/* Value used for dtv entries for which the allocation is delayed.  */
+#define TLS_DTV_UNALLOCATED	((void *) -1l)

+ 32 - 0
libpthread/nptl/sysdeps/nios2/libc-tls.c

@@ -0,0 +1,32 @@
+/* Thread-local storage handling in the ELF dynamic linker.  Nios II version.
+   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 Nios II, 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.  */
+
+void *
+__tls_get_addr (tls_index *ti)
+{
+  dtv_t *dtv = THREAD_DTV ();
+  return (char *) dtv[1].pointer.val + GET_ADDR_OFFSET;
+}

+ 66 - 0
libpthread/nptl/sysdeps/nios2/pthread_spin_lock.c

@@ -0,0 +1,66 @@
+/* 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"
+
+/* A machine-specific version can define SPIN_LOCK_READS_BETWEEN_CMPXCHG
+  to the number of plain reads that it's optimal to spin on between uses
+  of atomic_compare_and_exchange_val_acq.  If spinning forever is optimal
+  then use -1.  If no plain reads here would ever be optimal, use 0.  */
+#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/nios2/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;
+}

+ 36 - 0
libpthread/nptl/sysdeps/nios2/pthreaddef.h

@@ -0,0 +1,36 @@
+/* pthread machine parameter definitions, Nios II version.
+   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/>.  */
+
+/* Default stack size.  */
+#define ARCH_STACK_DEFAULT_SIZE	(2 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning.  */
+#define STACK_ALIGN		4
+
+/* Minimal stack size after allocating thread descriptor and guard size.  */
+#define MINIMAL_REST_STACK	2048
+
+/* Alignment requirement for TCB.  */
+#define TCB_ALIGNMENT		4
+
+/* 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))

+ 14 - 0
libpthread/nptl/sysdeps/nios2/tcb-offsets.sym

@@ -0,0 +1,14 @@
+#include <sysdep.h>
+#include <tls.h>
+
+--
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+# undef __thread_self
+# define __thread_self          ((void *) 0)
+# define thread_offsetof(mem)   ((ptrdiff_t) THREAD_SELF + offsetof (struct pthread, mem))
+
+MULTIPLE_THREADS_OFFSET		thread_offsetof (header.multiple_threads)
+PID_OFFSET			thread_offsetof (pid)
+TID_OFFSET			thread_offsetof (tid)
+POINTER_GUARD			(offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))

+ 178 - 0
libpthread/nptl/sysdeps/nios2/tls.h

@@ -0,0 +1,178 @@
+/* Definition for thread-local data handling.  NPTL/Nios II 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/>.  */
+
+#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_TLS_MODEL_ATTRIBUTE        1
+#define HAVE___THREAD                   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;
+  uintptr_t pointer_guard;
+  unsigned spare[6];
+} tcbhead_t;
+
+register struct pthread *__thread_self __asm__("r23");
+
+#define READ_THREAD_POINTER() ((void *) __thread_self)
+
+/* This is the size of the initial TCB.  Because our TCB is before the thread
+   pointer, we don't need this.  */
+# define TLS_INIT_TCB_SIZE	0
+
+/* Alignment requirements for the initial TCB.  */
+# define TLS_INIT_TCB_ALIGN	__alignof__ (struct pthread)
+
+/* This is the size of the TCB.  Because our TCB is before the thread
+   pointer, we don't need this.  */
+# define TLS_TCB_SIZE		0
+
+/* Alignment requirements for the TCB.  */
+# define TLS_TCB_ALIGN		__alignof__ (struct pthread)
+
+/* This is the size we need before TCB - actually, it includes the TCB.  */
+# define TLS_PRE_TCB_SIZE \
+  (sizeof (struct pthread)						      \
+   + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
+
+/* The thread pointer (in hardware register r23) points to the end of
+   the TCB + 0x7000, as for PowerPC and MIPS.  */
+# define TLS_TCB_OFFSET 0x7000
+
+/* 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))[-1].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))[-1].dtv)
+
+/* Code to initially initialize the thread pointer.  */
+# define TLS_INIT_TP(tcbp, secondcall) \
+  (__thread_self = (struct pthread *) ((char *) tcbp + TLS_TCB_OFFSET), NULL)
+
+/* Value passed to 'clone' for initialization of the thread register.  */
+# define TLS_DEFINE_INIT_TP(tp, pd) \
+  void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE
+
+/* Return the address of the dtv for the current thread.  */
+# define THREAD_DTV() \
+  (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv)
+
+/* Return the thread descriptor for the current thread.  */
+# define THREAD_SELF \
+ ((struct pthread *) (READ_THREAD_POINTER ()			     \
+		      - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE))
+
+/* Magic for libthread_db to know how to do THREAD_SELF.  */
+# define DB_THREAD_SELF \
+  REGISTER (32, 32, 23 * 4, -TLS_PRE_TCB_SIZE - TLS_TCB_OFFSET)
+
+/* Access to data in the thread descriptor is easy.  */
+# define THREAD_GETMEM(descr, member) \
+  descr->member
+# define THREAD_GETMEM_NC(descr, member, idx) \
+  descr->member[idx]
+# define THREAD_SETMEM(descr, member, value) \
+  descr->member = (value)
+# define THREAD_SETMEM_NC(descr, member, idx, value) \
+  descr->member[idx] = (value)
+
+# define THREAD_GET_POINTER_GUARD()				\
+  (((tcbhead_t *) (READ_THREAD_POINTER ()			\
+		   - TLS_TCB_OFFSET))[-1].pointer_guard)
+# define THREAD_SET_POINTER_GUARD(value)	\
+  (THREAD_GET_POINTER_GUARD () = (value))
+# define THREAD_COPY_POINTER_GUARD(descr)				\
+  (((tcbhead_t *) ((void *) (descr)					\
+		   + TLS_PRE_TCB_SIZE))[-1].pointer_guard		\
+   = THREAD_GET_POINTER_GUARD())
+
+/* l_tls_offset == 0 is perfectly valid on Nios II, so we have to use some
+   different value to mean unset l_tls_offset.  */
+# define NO_TLS_OFFSET		-1
+
+/* 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 */

+ 9 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nios2/Makefile

@@ -0,0 +1,9 @@
+# Makefile for uClibc NPTL
+# Licensed under the LGPL v2.1, 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

+ 9 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nios2/Makefile.arch

@@ -0,0 +1,9 @@
+# Makefile for uClibc NPTL
+# Licensed under the LGPL v2.1, 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
+libc_linux_arch_SSRC-OMIT = waitpid.S

+ 189 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nios2/bits/pthreadtypes.h

@@ -0,0 +1,189 @@
+/* Machine-specific pthread type layouts.  Nios II 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/>.  */
+
+#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_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
+   deliberately not exposed.  */
+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 deliberately not exposed.  */
+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;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
+  long int __align;
+} pthread_mutexattr_t;
+
+/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER.  */
+#define __PTHREAD_SPINS 0
+
+
+/* Data structure for conditional variable handling.  The structure of
+   the attribute type is deliberately not exposed.  */
+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];
+  long 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 deliberately not exposed.  */
+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/nios2/bits/semaphore.h

@@ -0,0 +1,32 @@
+/* Machine-specific POSIX semaphore type layouts.  Nios II version.
+   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;

+ 3 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nios2/clone.S

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

+ 22 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nios2/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>

+ 30 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nios2/fork.c

@@ -0,0 +1,30 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Phil Blundell <pb@nexus.co.uk>, 2005
+
+   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,	\
+		  NULL, NULL, NULL, &THREAD_SELF->tid)
+
+#include "../fork.c"

+ 281 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nios2/lowlevellock.h

@@ -0,0 +1,281 @@
+/* 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; 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 __ret;							      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),		      \
+			      __lll_private_flag (FUTEX_WAIT, private),	      \
+			      (val), (timespec));			      \
+    __ret;								      \
+  })
+
+#define lll_futex_wake(futexp, nr, private) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),		      \
+			      __lll_private_flag (FUTEX_WAKE, private),	      \
+			      (nr), 0);					      \
+    __ret;								      \
+  })
+
+#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 __ret;							      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		      \
+			      __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
+			      (nr_wake), (nr_move), (mutex), (val));	      \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __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 __ret;							      \
+    __ret = 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 (__ret, __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 (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex,       \
+								1, 0), 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 (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
+								0), 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 (__builtin_expect (atomic_exchange_acq (__futex, 2), 0))		      \
+      __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 (__builtin_expect (atomic_exchange_acq (__futex, 1), 0))	      \
+       __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 (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
+								0), 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 (__builtin_expect (__oldval > 1, 0))			\
+	 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 (__builtin_expect (__oldval & FUTEX_WAITERS, 0))	\
+	 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 */

+ 5 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nios2/pt-gettimeofday.c

@@ -0,0 +1,5 @@
+#include <sys/syscall.h>
+#include <sys/time.h>
+
+int gettimeofday (struct timeval *, struct timezone *) attribute_hidden;
+_syscall2(int, gettimeofday, struct timeval *, tv, struct timezone *, tz)

+ 99 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nios2/pthread_once.c

@@ -0,0 +1,99 @@
+/* Copyright (C) 2004, 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/>.  */
+
+#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
+attribute_protected
+__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)
+
+#if defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__PIC__)
+/* When statically linked, if pthread_create is used, this file
+   will be brought in.  The exception handling code in GCC assumes
+   that if pthread_create is available, so are these.  */
+const void *include_pthread_getspecific attribute_hidden = pthread_getspecific;
+const void *include_pthread_setspecific attribute_hidden = pthread_setspecific;
+const void *include_pthread_key_create attribute_hidden = pthread_key_create;
+#endif

+ 140 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nios2/sysdep-cancel.h

@@ -0,0 +1,140 @@
+/* Assembler macros with cancellation support, Nios II version.
+   Copyright (C) 2003-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 PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+  .type __##syscall_name##_nocancel, @function;				      \
+  .globl __##syscall_name##_nocancel;					      \
+  __##syscall_name##_nocancel:						      \
+    cfi_startproc;                                                            \
+    DO_CALL (syscall_name, args);                                             \
+    ret;                                                                      \
+    cfi_endproc;                                                              \
+  .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \
+  ENTRY (name)								      \
+    SINGLE_THREAD_P(r2);						      \
+    bne r2, zero, pseudo_cancel;					      \
+    DO_CALL (syscall_name, args);					      \
+    ret;								      \
+  pseudo_cancel:							      \
+    SAVESTK_##args;                 /* save syscall args and adjust stack */  \
+    SAVEREG(ra, 0);                     /* save return address */             \
+    SAVEREG(r22, 4);                    /* save GOT pointer */                \
+    nextpc r22;                                                               \
+1:  movhi r2, %hiadj(_gp_got - 1b);					      \
+    addi r2, r2, %lo(_gp_got - 1b);					      \
+    add r22, r22, r2;                                                         \
+    CENABLE;                                                                  \
+    callr r3;                                                                 \
+    stw r2, 8(sp);                      /* save mask */                       \
+    LOADARGS_##args;                                                          \
+    movi r2, SYS_ify(syscall_name);                                           \
+    trap;                                                                     \
+    stw r2, 12(sp);                     /* save syscall result */             \
+    stw r7, 16(sp);                     /* save syscall error flag */         \
+    ldw r4, 8(sp);                      /* pass mask as argument 1 */         \
+    CDISABLE;                                                                 \
+    callr r3;                                                                 \
+    ldw r7, 16(sp);                     /* restore syscall error flag */      \
+    ldw r2, 12(sp);                     /* restore syscall result */          \
+    ldw ra, 0(sp);                      /* restore return address */          \
+    ldw r22, 4(sp);                     /* restore GOT pointer */             \
+    RESTORESTK_##args;                                                        \
+
+
+# undef PSEUDO_END
+# define PSEUDO_END(sym) \
+  END (sym)
+
+#define SAVEREG(REG, LOC) stw REG, LOC(sp); cfi_rel_offset (REG, LOC)
+#define SAVESTK(X) subi sp, sp, X; cfi_adjust_cfa_offset(X)
+#define SAVESTK_0 SAVESTK(20)
+#define SAVEARG_1 SAVEREG(r4, 20)
+#define SAVESTK_1 SAVESTK(24); SAVEARG_1
+#define SAVEARG_2 SAVEREG(r5, 24); SAVEARG_1
+#define SAVESTK_2 SAVESTK(28); SAVEARG_2
+#define SAVEARG_3 SAVEREG(r6, 28); SAVEARG_2
+#define SAVESTK_3 SAVESTK(32); SAVEARG_3
+#define SAVEARG_4 SAVEREG(r7, 32); SAVEARG_3
+#define SAVESTK_4 SAVESTK(36); SAVEARG_4
+#define SAVESTK_5 SAVESTK_4
+#define SAVESTK_6 SAVESTK_5
+
+#define LOADARGS_0
+#define LOADARGS_1 ldw r4, 20(sp)
+#define LOADARGS_2 LOADARGS_1; ldw r5, 24(sp)
+#define LOADARGS_3 LOADARGS_2; ldw r6, 28(sp)
+#define LOADARGS_4 LOADARGS_3; ldw r7, 32(sp)
+#define LOADARGS_5 LOADARGS_4; ldw r8, 36(sp)
+#define LOADARGS_6 LOADARGS_5; ldw r9, 40(sp)
+
+#define RESTORESTK(X) addi sp, sp, X; cfi_adjust_cfa_offset(-X)
+#define RESTORESTK_0 RESTORESTK(20)
+#define RESTORESTK_1 RESTORESTK(24)
+#define RESTORESTK_2 RESTORESTK(28)
+#define RESTORESTK_3 RESTORESTK(32)
+#define RESTORESTK_4 RESTORESTK(36)
+#define RESTORESTK_5 RESTORESTK(36)
+#define RESTORESTK_6 RESTORESTK(36)
+
+# endif
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	ldw r3, %call(__pthread_enable_asynccancel)(r22)
+#  define CDISABLE	ldw r3, %call(__pthread_disable_asynccancel)(r22)
+# elif defined IS_IN_librt
+#  define CENABLE	ldw r3, %call(__librt_enable_asynccancel)(r22)
+#  define CDISABLE	ldw r3, %call(__librt_disable_asynccancel)(r22)
+# elif !defined NOT_IN_libc
+#  define CENABLE	ldw r3, %call(__libc_enable_asynccancel)(r22)
+#  define CDISABLE	ldw r3, %call(__libc_disable_asynccancel)(r22)
+# else
+#  error Unsupported library
+# endif
+
+# ifndef __ASSEMBLER__
+#  define SINGLE_THREAD_P						\
+	__builtin_expect (THREAD_GETMEM (THREAD_SELF,			\
+					 header.multiple_threads)	\
+			  == 0, 1)
+# else
+#  define SINGLE_THREAD_P(reg)						\
+	ldw reg, MULTIPLE_THREADS_OFFSET(r23)
+# endif
+
+#elif !defined __ASSEMBLER__
+
+# define SINGLE_THREAD_P 1
+# define NO_CANCELLATION 1
+
+#endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif

+ 38 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nios2/vfork.S

@@ -0,0 +1,38 @@
+/* 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/>.  */
+
+#include <tcb-offsets.h>
+
+/* Save the PID value.  */
+#define SAVE_PID \
+	str	lr, [sp, #-4]!;		/* Save LR.  */			\
+	mov	r0, #0xffff0fff;	/* Point to the high page.  */	\
+	mov	lr, pc;			/* Save our return address.  */	\
+	sub	pc, r0, #31;		/* Jump to the TLS entry.  */	\
+	ldr	lr, [sp], #4;		/* Restore LR.  */		\
+	mov	r2, r0;			/* Save the TLS addr in r2.  */	\
+	ldr	r3, [r2, #PID_OFFSET];	/* Load the saved PID.  */	\
+	rsbs	r0, r3, #0;		/* Negate it.  */		\
+	moveq	r0, #0x80000000;	/* Use 0x80000000 if it was 0.  */ \
+	str	r0, [r2, #PID_OFFSET]	/* Store the temporary PID.  */
+
+/* Restore the old PID value in the parent.  */
+#define RESTORE_PID \
+	cmp	r0, #0;			/* If we are the parent... */	\
+	strne	r3, [r2, #PID_OFFSET]	/* ... restore the saved PID.  */
+
+#include "../../../../../../../libc/sysdeps/linux/nios2/vfork.S"

+ 5 - 0
utils/ldd.c

@@ -103,6 +103,11 @@
 #define ELFCLASSM	ELFCLASS32
 #endif
 
+#if defined(__nios2__)
+#define MATCH_MACHINE(x) (x == EM_NIOS32)
+#define ELFCLASSM	ELFCLASS32
+#endif
+
 #if defined(__powerpc__)
 #define MATCH_MACHINE(x) (x == EM_PPC)
 #define ELFCLASSM	ELFCLASS32