Browse Source

nds32: add NPTL/TLS, *context function, libm changes and code cleanup

This commit includes following features.
1. Support NPTL/TLS
2. Add libm function which is used to handle FP rounding and excpetions
   (ex: fclrexcpt,fedisblxcpti,feenablxcpt... )
3. Add *context function for operating user context
   (ex: setcontext,getcontext,makecontext... )
4. Change the return flow from signal handler
5. Cleanup of old code

The testsuite only has 2 errors, tst-cpuclock1 and tst-cputimer1,
which are related to timing accuracy. (math and locale tests are disabled)

Signed-off-by: Vincent Ren-Wei Chen <vincentc@andestech.com>
Vincent Ren-Wei Chen 7 years ago
parent
commit
6af3332a4c
91 changed files with 4023 additions and 996 deletions
  1. 0 1
      extra/Configs/Config.in
  2. 1 0
      extra/Configs/Config.nds32
  3. 167 0
      extra/Configs/defconfigs/nds32/defconfig
  4. 3 0
      include/elf.h
  5. 6 88
      ldso/ldso/nds32/dl-startup.h
  6. 3 2
      ldso/ldso/nds32/dl-sysdep.h
  7. 100 0
      ldso/ldso/nds32/dl-tlsdesc.S
  8. 64 30
      ldso/ldso/nds32/elfinterp.c
  9. 0 24
      ldso/ldso/nds32/resolve.S
  10. 0 1
      ldso/libdl/Makefile.in
  11. 21 1
      libc/string/nds32/memcpy.S
  12. 1 1
      libc/string/nds32/memset.S
  13. 1 1
      libc/sysdeps/linux/common/posix_fadvise.c
  14. 1 1
      libc/sysdeps/linux/common/posix_fadvise64.c
  15. 1 1
      libc/sysdeps/linux/common/sync_file_range.c
  16. 1 5
      libc/sysdeps/linux/nds32/Makefile
  17. 4 2
      libc/sysdeps/linux/nds32/Makefile.arch
  18. 1 1
      libc/sysdeps/linux/nds32/__longjmp.S
  19. 110 0
      libc/sysdeps/linux/nds32/bits/atomic.h
  20. 5 1
      libc/sysdeps/linux/nds32/bits/fcntl.h
  21. 79 0
      libc/sysdeps/linux/nds32/bits/fenv.h
  22. 1 0
      libc/sysdeps/linux/nds32/bits/mman.h
  23. 12 6
      libc/sysdeps/linux/nds32/bits/setjmp.h
  24. 0 59
      libc/sysdeps/linux/nds32/bits/sigcontext.h
  25. 35 0
      libc/sysdeps/linux/nds32/bits/sigcontextinfo.h
  26. 277 77
      libc/sysdeps/linux/nds32/bits/syscalls.h
  27. 1 1
      libc/sysdeps/linux/nds32/bits/uClibc_arch_features.h
  28. 2 3
      libc/sysdeps/linux/nds32/bsd-_setjmp.S
  29. 2 2
      libc/sysdeps/linux/nds32/bsd-setjmp.S
  30. 144 56
      libc/sysdeps/linux/nds32/clone.S
  31. 0 7
      libc/sysdeps/linux/nds32/crt1.S
  32. 0 24
      libc/sysdeps/linux/nds32/crti.S
  33. 77 0
      libc/sysdeps/linux/nds32/fpu_control.h
  34. 106 0
      libc/sysdeps/linux/nds32/getcontext.S
  35. 17 1
      libc/sysdeps/linux/nds32/jmpbuf-unwind.h
  36. 77 0
      libc/sysdeps/linux/nds32/makecontext.c
  37. 0 101
      libc/sysdeps/linux/nds32/mmap.S
  38. 28 0
      libc/sysdeps/linux/nds32/mremap.c
  39. 23 0
      libc/sysdeps/linux/nds32/prctl.c
  40. 85 0
      libc/sysdeps/linux/nds32/setcontext.S
  41. 1 1
      libc/sysdeps/linux/nds32/setjmp.S
  42. 0 40
      libc/sysdeps/linux/nds32/sigaction.c
  43. 0 42
      libc/sysdeps/linux/nds32/sigrestorer.S
  44. 38 0
      libc/sysdeps/linux/nds32/swapcontext.c
  45. 26 91
      libc/sysdeps/linux/nds32/sys/ucontext.h
  46. 0 60
      libc/sysdeps/linux/nds32/syscall.S
  47. 28 0
      libc/sysdeps/linux/nds32/syscall.c
  48. 19 20
      libc/sysdeps/linux/nds32/sysdep.S
  49. 107 214
      libc/sysdeps/linux/nds32/sysdep.h
  50. 27 0
      libc/sysdeps/linux/nds32/ucontext_i.sym
  51. 85 29
      libc/sysdeps/linux/nds32/vfork.S
  52. 16 0
      libm/nds32/Makefile.arch
  53. 34 0
      libm/nds32/e_sqrt.c
  54. 52 0
      libm/nds32/fclrexcpt.c
  55. 49 0
      libm/nds32/fedisblxcpt.c
  56. 50 0
      libm/nds32/feenablxcpt.c
  57. 40 0
      libm/nds32/fegetenv.c
  58. 41 0
      libm/nds32/fegetexcept.c
  59. 40 0
      libm/nds32/fegetround.c
  60. 51 0
      libm/nds32/feholdexcpt.c
  61. 33 0
      libm/nds32/fenv_libc.h
  62. 51 0
      libm/nds32/fesetenv.c
  63. 42 0
      libm/nds32/fesetround.c
  64. 48 0
      libm/nds32/feupdateenv.c
  65. 44 0
      libm/nds32/fgetexcptflg.c
  66. 104 0
      libm/nds32/fraiseexcpt.c
  67. 48 0
      libm/nds32/fsetexcptflg.c
  68. 40 0
      libm/nds32/ftestexcept.c
  69. 1 1
      libpthread/linuxthreads/sysdeps/nds32/pspinlock.c
  70. 1 1
      libpthread/linuxthreads/sysdeps/nds32/pt-machine.h
  71. 16 0
      libpthread/nptl/sysdeps/nds32/Makefile.arch
  72. 59 0
      libpthread/nptl/sysdeps/nds32/dl-tls.h
  73. 1 0
      libpthread/nptl/sysdeps/nds32/libc-dl-tlsdesc.S
  74. 65 0
      libpthread/nptl/sysdeps/nds32/pthread_spin_lock.c
  75. 26 0
      libpthread/nptl/sysdeps/nds32/pthread_spin_trylock.c
  76. 39 0
      libpthread/nptl/sysdeps/nds32/pthreaddef.h
  77. 12 0
      libpthread/nptl/sysdeps/nds32/tcb-offsets.sym
  78. 178 0
      libpthread/nptl/sysdeps/nds32/tls.h
  79. 17 0
      libpthread/nptl/sysdeps/nds32/tlsdesc.sym
  80. 9 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile
  81. 12 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile.arch
  82. 177 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/pthreadtypes.h
  83. 38 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/semaphore.h
  84. 4 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/clone.S
  85. 22 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/createthread.c
  86. 27 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/fork.c
  87. 323 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/lowlevellock.h
  88. 18 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pt-raise.c
  89. 92 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pthread_once.c
  90. 273 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h
  91. 43 0
      libpthread/nptl/sysdeps/unix/sysv/linux/nds32/vfork.S

+ 0 - 1
extra/Configs/Config.in

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

+ 1 - 0
extra/Configs/Config.nds32

@@ -13,6 +13,7 @@ config FORCE_OPTIONS_FOR_ARCH
 	select ARCH_ANY_ENDIAN
 	select ARCH_HAS_DEPRECATED_SYSCALLS
 	select ARCH_HAS_MMU
+	select ARCH_HAS_UCONTEXT
 
 choice
 	prompt "MMU Page Size"

+ 167 - 0
extra/Configs/defconfigs/nds32/defconfig

@@ -0,0 +1,167 @@
+TARGET_nds32=y
+#
+# Using ELF file format
+#
+ARCH_HAS_DEPRECATED_SYSCALLS=y
+ARCH_ANY_ENDIAN=y
+ARCH_LITTLE_ENDIAN=y
+# ARCH_WANTS_BIG_ENDIAN is not set
+ARCH_WANTS_LITTLE_ENDIAN=y
+ARCH_HAS_MMU=y
+ARCH_USE_MMU=y
+UCLIBC_HAS_FLOATS=y
+UCLIBC_HAS_FPU=y
+DO_C99_MATH=y
+DO_XSI_MATH=y
+UCLIBC_HAS_FENV=y
+KERNEL_HEADERS=""
+HAVE_DOT_CONFIG=y
+
+#
+# General Library Settings
+#
+DOPIC=y
+ARCH_HAS_UCONTEXT=y
+HAVE_SHARED=y
+# FORCE_SHAREABLE_TEXT_SEGMENTS is not set
+LDSO_LDD_SUPPORT=y
+LDSO_CACHE_SUPPORT=y
+# LDSO_PRELOAD_ENV_SUPPORT is not set
+# LDSO_PRELOAD_FILE_SUPPORT is not set
+LDSO_BASE_FILENAME="ld.so"
+# LDSO_STANDALONE_SUPPORT is not set
+# LDSO_PRELINK_SUPPORT is not set
+UCLIBC_STATIC_LDCONFIG=y
+LDSO_RUNPATH=y
+LDSO_RUNPATH_OF_EXECUTABLE=y
+LDSO_SAFE_RUNPATH=y
+LDSO_SEARCH_INTERP_PATH=y
+LDSO_LD_LIBRARY_PATH=y
+LDSO_NO_CLEANUP=y
+UCLIBC_CTOR_DTOR=y
+LDSO_GNU_HASH_SUPPORT=y
+# HAS_NO_THREADS is not set
+# UCLIBC_HAS_LINUXTHREADS is not set
+UCLIBC_HAS_THREADS_NATIVE=y
+UCLIBC_HAS_THREADS=y
+UCLIBC_HAS_TLS=y
+PTHREADS_DEBUG_SUPPORT=y
+UCLIBC_HAS_SYSLOG=y
+UCLIBC_HAS_LFS=y
+# MALLOC is not set
+# MALLOC_SIMPLE is not set
+MALLOC_STANDARD=y
+MALLOC_GLIBC_COMPAT=y
+# UCLIBC_HAS_OBSTACK is not set
+UCLIBC_DYNAMIC_ATEXIT=y
+COMPAT_ATEXIT=y
+UCLIBC_HAS_UTMPX=y
+UCLIBC_HAS_UTMP=y
+UCLIBC_SUSV2_LEGACY=y
+UCLIBC_SUSV3_LEGACY=y
+UCLIBC_HAS_CONTEXT_FUNCS=y
+UCLIBC_SUSV3_LEGACY_MACROS=y
+UCLIBC_SUSV4_LEGACY=y
+# UCLIBC_STRICT_HEADERS is not set
+# UCLIBC_HAS_STUBS is not set
+UCLIBC_HAS_SHADOW=y
+UCLIBC_HAS_PROGRAM_INVOCATION_NAME=y
+UCLIBC_HAS___PROGNAME=y
+UCLIBC_HAS_PTY=y
+ASSUME_DEVPTS=y
+UNIX98PTY_ONLY=y
+UCLIBC_HAS_GETPT=y
+UCLIBC_HAS_LIBUTIL=y
+UCLIBC_HAS_TM_EXTENSIONS=y
+UCLIBC_HAS_TZ_CACHING=y
+UCLIBC_HAS_TZ_FILE=y
+UCLIBC_HAS_TZ_FILE_READ_MANY=y
+UCLIBC_TZ_FILE_PATH="/etc/TZ"
+UCLIBC_FALLBACK_TO_ETC_LOCALTIME=y
+
+#
+# Advanced Library Settings
+#
+UCLIBC_PWD_BUFFER_SIZE=256
+UCLIBC_GRP_BUFFER_SIZE=256
+
+#
+# Support various families of functions
+#
+UCLIBC_LINUX_MODULE_26=y
+# UCLIBC_LINUX_MODULE_24 is not set
+UCLIBC_LINUX_SPECIFIC=y
+UCLIBC_HAS_GNU_ERROR=y
+UCLIBC_BSD_SPECIFIC=y
+UCLIBC_HAS_BSD_ERR=y
+UCLIBC_HAS_OBSOLETE_BSD_SIGNAL=y
+# UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL is not set
+# UCLIBC_NTP_LEGACY is not set
+UCLIBC_SV4_DEPRECATED=y
+UCLIBC_HAS_REALTIME=y
+UCLIBC_HAS_ADVANCED_REALTIME=y
+UCLIBC_HAS_EPOLL=y
+UCLIBC_HAS_XATTR=y
+UCLIBC_HAS_PROFILING=y
+UCLIBC_HAS_CRYPT_IMPL=y
+UCLIBC_HAS_SHA256_CRYPT_IMPL=y
+# UCLIBC_HAS_SHA512_CRYPT_IMPL is not set
+UCLIBC_HAS_CRYPT=y
+UCLIBC_HAS_NETWORK_SUPPORT=y
+UCLIBC_HAS_SOCKET=y
+UCLIBC_HAS_IPV4=y
+UCLIBC_HAS_IPV6=y
+UCLIBC_HAS_RPC=y
+UCLIBC_HAS_FULL_RPC=y
+# UCLIBC_HAS_REENTRANT_RPC is not set
+UCLIBC_USE_NETLINK=y
+UCLIBC_SUPPORT_AI_ADDRCONFIG=y
+UCLIBC_HAS_BSD_RES_CLOSE=y
+UCLIBC_HAS_COMPAT_RES_STATE=y
+# UCLIBC_HAS_EXTRA_COMPAT_RES_STATE is not set
+UCLIBC_HAS_RESOLVER_SUPPORT=y
+UCLIBC_HAS_LIBRESOLV_STUB=y
+UCLIBC_HAS_LIBNSL_STUB=y
+
+UCLIBC_HAS_STRING_GENERIC_OPT=y
+UCLIBC_HAS_STRING_ARCH_OPT=y
+UCLIBC_HAS_STDIO_FUTEXES=y
+UCLIBC_HAS_CTYPE_TABLES=y
+UCLIBC_HAS_CTYPE_SIGNED=y
+# UCLIBC_HAS_CTYPE_UNSAFE is not set
+UCLIBC_HAS_CTYPE_CHECKED=y
+# UCLIBC_HAS_CTYPE_ENFORCED is not set
+UCLIBC_HAS_WCHAR=y
+# UCLIBC_HAS_LOCALE is not set
+UCLIBC_HAS_HEXADECIMAL_FLOATS=y
+UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y
+UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9
+UCLIBC_HAS_STDIO_BUFSIZ_4096=y
+UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y
+UCLIBC_HAS_STDIO_GETC_MACRO=y
+UCLIBC_HAS_STDIO_PUTC_MACRO=y
+UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y
+UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE=y
+UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y
+UCLIBC_HAS_PRINTF_M_SPEC=y
+UCLIBC_HAS_ERRNO_MESSAGES=y
+UCLIBC_HAS_SIGNUM_MESSAGES=y
+UCLIBC_HAS_GNU_GETOPT=y
+UCLIBC_HAS_GETOPT_LONG=y
+UCLIBC_HAS_GNU_GETSUBOPT=y
+UCLIBC_HAS_ARGP=y
+
+UCLIBC_HAS_REGEX=y
+# UCLIBC_HAS_REGEX_OLD is not set
+UCLIBC_HAS_FNMATCH=y
+# UCLIBC_HAS_FNMATCH_OLD is not set
+UCLIBC_HAS_WORDEXP=y
+UCLIBC_HAS_NFTW=y
+UCLIBC_HAS_FTW=y
+UCLIBC_HAS_FTS=y
+UCLIBC_HAS_GLOB=y
+UCLIBC_HAS_GNU_GLOB=y
+
+CROSS_COMPILER_PREFIX=""
+UCLIBC_EXTRA_CFLAGS=""
+# DOSTRIP is not set

+ 3 - 0
include/elf.h

@@ -2985,6 +2985,9 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_NDS32_PLTREL_LO12			65
 #define R_NDS32_PLT_GOTREL_HI20			66
 #define R_NDS32_PLT_GOTREL_LO12			67
+#define R_NDS32_TLS_TPOFF                       102
+#define R_NDS32_TLS_DESC                        119
+
 
 /* Processor specific section indices.  These sections do not actually
    exist.  Symbols with a st_shndx field corresponding to one of these

+ 6 - 88
ldso/ldso/nds32/dl-startup.h

@@ -6,68 +6,7 @@
 /* Need bootstrap relocations */
 #define ARCH_NEEDS_BOOTSTRAP_RELOCS
 
-#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
-# define STACK_PUSH
-# define STACK_POP
-#else
-# define STACK_PUSH     "addi   $sp,    $sp,    -24"
-# define STACK_POP      "addi   $sp,    $sp,    24"
-#endif
 
-
-#ifdef __NDS32_N1213_43U1H__
-__asm__("\
-	.text\n\
-	.globl 	_start\n\
-	.globl  _dl_start\n\
-	.globl 	_dl_start_user\n\
-    .type	_start,#function\n\
-    .type	_dl_start,#function\n\
-	.type 	_dl_start_user,#function\n\
-	.align	4\n\
-	.pic\n\
-1:\n\
-	ret\n\
-_start:\n\
-	! we are PIC code, so get global offset table\n\
-	jal	1b\n\
-	sethi	$gp, HI20(_GLOBAL_OFFSET_TABLE_)\n\
-	ori		$gp, $gp, LO12(_GLOBAL_OFFSET_TABLE_+4)\n\
-	add		$gp, $lp, $gp\n\
-\n\
-	! at start time, all the args are on the stack\n\
-	addi	$r0,	$sp,	0\n\
-    ! adjust stack\n\
-    !addi    $sp,    $sp,    -24\n\
-	"STACK_PUSH"\n\
-	bal	_dl_start@PLT\n\
-	! save user entry point in r6\n\
-	addi	$r6,	$r0,	0\n\
-    ! adjust sp and reload registers\n\
-    !addi    $sp,    $sp,    24\n\
-	"STACK_POP"\n\
-\n\
-_dl_start_user:\n\
-\n\
-	! See if we were run as a command with the executable file\n\
-	! name as an extra leading argument.\n\
-	! skip these arguments\n\
-	l.w		$r2,	_dl_skip_args@GOTOFF	! args to skip\n\
-	lwi		$r0,	[$sp+0]					! original argc\n\
-	slli	$r1,	$r2,	2				! offset for new sp\n\
-	add		$sp,	$sp,	$r1				! adjust sp to skip args\n\
-	sub		$r0,	$r0,	$r2				! set new argc\n\
-	swi		$r0,	[$sp+0]					! save new argc\n\
-\n\
-	! load address of _dl_fini finalizer function\n\
-	la		$r5, _dl_fini@GOTOFF\n\
-	! jump to the user_s entry point\n\
-	addi	$r15,	$r6,	0\n\
-	jr		$r15\n\
-	.size   _dl_start_user, . - _dl_start_user\n\
-	.previous\n\
-");
-#else
 __asm__("\
 	.text\n\
 	.globl 	_start\n\
@@ -89,13 +28,11 @@ _start:\n\
 	addi	$r0,	$sp,	0\n\
     ! adjust stack\n\
     !addi    $sp,    $sp,    -24\n\
-	"STACK_PUSH"\n\
 	bal	_dl_start@PLT\n\
 	! save user entry point in r6\n\
 	addi	$r6,	$r0,	0\n\
     ! adjust sp and reload registers\n\
     !addi    $sp,    $sp,    24\n\
-	"STACK_POP"\n\
 \n\
 _dl_start_user:\n\
 	! See if we were run as a command with the executable file\n\
@@ -115,31 +52,12 @@ _dl_start_user:\n\
 	.size   _dl_start_user, . - _dl_start_user\n\
 	.previous\n\
 ");
-#endif
 
-#define COPY_UNALIGNED_WORD(swp, twp, align) \
-  { \
-    void *__s = (swp), *__t = (twp); \
-    unsigned char *__s1 = __s, *__t1 = __t; \
-    unsigned short *__s2 = __s, *__t2 = __t; \
-    unsigned long *__s4 = __s, *__t4 = __t; \
-    switch ((align)) \
-    { \
-    case 0: \
-      *__t4 = *__s4; \
-      break; \
-    case 2: \
-      *__t2++ = *__s2++; \
-      *__t2 = *__s2; \
-      break; \
-    default: \
-      *__t1++ = *__s1++; \
-      *__t1++ = *__s1++; \
-      *__t1++ = *__s1++; \
-      *__t1 = *__s1; \
-      break; \
-    } \
-  }
+#define COPY_UNALIGNED_WORD(swp, twp) \
+{ \
+        __typeof (swp) __tmp = __builtin_nds32_unaligned_load_w ((unsigned int*)&swp); \
+        __builtin_nds32_unaligned_store_w ((unsigned int *)twp, __tmp); \
+}
 
 /* Get a pointer to the argv array.  On many platforms this can be just
  * the address if the first argument, on other platforms we need to
@@ -162,7 +80,7 @@ void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
 			break;
 		case R_NDS32_32_RELA:
 			value = symbol_addr + rpnt->r_addend;
-			COPY_UNALIGNED_WORD (&value, reloc_addr, (int) reloc_addr & 3);
+			COPY_UNALIGNED_WORD (value, reloc_addr);
 			break;
 #undef COPY_UNALIGNED_WORD
 		case R_NDS32_RELATIVE:

+ 3 - 2
ldso/ldso/nds32/dl-sysdep.h

@@ -57,7 +57,8 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
    ELF_RTYPE_CLASS_NOCOPY 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_NDS32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)	\
+  ((((type) == R_NDS32_JMP_SLOT || (type) == R_NDS32_TLS_TPOFF \
+      || (type) == R_NDS32_TLS_DESC) * ELF_RTYPE_CLASS_PLT)	\
    | (((type) == R_NDS32_COPY) * ELF_RTYPE_CLASS_COPY))
 
 /* Return the link-time address of _DYNAMIC.  Conveniently, this is the
@@ -81,7 +82,7 @@ elf_machine_load_address (void)
      via the GOT to make sure the compiler initialized %ebx in time.  */
 
 	Elf32_Addr addr;
-	__asm__ ("la	%0, _dl_start@GOTOFF\n" : "=r" (addr) );
+	__asm__ ("la	%0, _DYNAMIC@GOTOFF\n" : "=r" (addr) );
 	return addr - elf_machine_dynamic();
 }
 

+ 100 - 0
ldso/ldso/nds32/dl-tlsdesc.S

@@ -0,0 +1,100 @@
+/* Thread-local storage handling in the ELF dynamic linker.  NDS32 version.
+   Copyright (C) 2006-2013 Free Software Foundation, Inc.
+
+   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>
+#if defined __UCLIBC_HAS_TLS__
+#include <tls.h>
+#include "tlsdesc.h"
+
+	.text
+	.hidden _dl_tlsdesc_return
+	.global	_dl_tlsdesc_return
+	.type	_dl_tlsdesc_return,#function
+	cfi_startproc
+	.align 2
+_dl_tlsdesc_return:
+	lwi	$r0,	[$r0	+ 4]
+	add	$r0,	$r0,	$r25
+	ret
+	cfi_endproc
+	.size   _dl_tlsdesc_return, .-_dl_tlsdesc_return
+
+#ifdef SHARED
+	.hidden _dl_tlsdesc_dynamic
+	.global	_dl_tlsdesc_dynamic
+	.type	_dl_tlsdesc_dynamic,#function
+	cfi_startproc
+	.pic
+/*
+	The assembly code that follows is a rendition of the following
+	C code, hand-optimized a little bit.
+
+ptrdiff_t
+_dl_tlsdesc_dynamic(struct tlsdesc *tdp)
+{
+       struct tlsdesc_dynamic_arg *td = tdp->argument.pointer;
+       dtv_t *dtv = (dtv_t *)THREAD_DTV();
+       if (__builtin_expect (td->gen_count <= dtv[0].counter
+                             && dtv[td->tlsinfo.ti_module].pointer.val
+                                != TLS_DTV_UNALLOCATED,
+                             1))
+               return dtv[td->tlsinfo.ti_module].pointer.val +
+                       td->tlsinfo.ti_offset - __builtin_thread_pointer();
+
+       return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer();
+}
+*/
+	.align 2
+
+_dl_tlsdesc_dynamic:
+	lwi	$r0,	[$r0	+ 4]
+	lwi	$r1,	[$r0 +	#TLSDESC_GEN_COUNT]  	/* $r0=td $r1=td->gen_count*/
+	lwi	$r2,	[$r25 +	#DTV_OFFSET]	    	/* $r2=&dtv[0]*/
+	lwi	$r3,	[$r2]
+	sub	$r1,	$r1,	$r3
+	bgtz	$r1,	2f
+	lwi	$r3,	[$r0 +	#TLSDESC_MODID]	    	/* r3=module id */
+	slli	$r3,	$r3,	#3			/* r3=module offset=module id*8(byte) */
+	lw	$r3,	[$r2 +	$r3]		   	/* r3=&dtc[module ID]=&dtv[0]+ module offset*/
+	movi	$r1,	#-1
+	beq	$r3,	$r1,	2f
+	lwi	$r1,	[$r0 +	#TLSDESC_MODOFF]
+	add	$r0,	$r3,	$r1
+1:
+	ret
+2:
+	smw.adm $sp,[$sp],$sp,#0x6
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(gp, 0)
+	cfi_rel_offset(lp, 4)
+	mfusr 	$r15, $PC;
+	sethi 	$gp,  hi20(_GLOBAL_OFFSET_TABLE_ + 4);
+	ori   	$gp,  $gp,  lo12(_GLOBAL_OFFSET_TABLE_ + 8);
+	add   	$gp,  $r15, $gp;
+	sethi 	$r15, hi20(__tls_get_addr@PLT);
+	ori	$r15, $r15, lo12(__tls_get_addr@PLT);
+	add	$r15, $r15, $gp
+	jral 	$r15
+	lmw.bim $sp,[$sp],$sp,#0x6
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(gp)
+	cfi_restore(lp)
+	j	1b
+	cfi_endproc
+	.size   _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
+#endif
+#endif // __UCLIBC_HAS_TLS__

+ 64 - 30
ldso/ldso/nds32/elfinterp.c

@@ -44,6 +44,11 @@
 
 #include "ldso.h"
 
+#if defined(USE_TLS) && USE_TLS
+#include "dl-tls.h"
+#include "tlsdeschtab.h"
+#endif
+
 extern int _dl_linux_resolve(void);
 
 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
@@ -95,7 +100,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 		{
 			_dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
 			if (_dl_debug_detail) _dl_dprintf(_dl_debug_file,
-					"\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
+					"\tpatch %x ==> %x @ %x", (unsigned int)*got_addr, (unsigned int)new_addr, (unsigned int)got_addr);
 		}
 	}
 	if (!_dl_debug_nofixups) {
@@ -168,6 +173,9 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
 	int reloc_type;
 	int symtab_index;
 	char *symname = NULL;
+#if defined USE_TLS && USE_TLS
+	struct elf_resolve *tls_tpnt = NULL;
+#endif
 	unsigned long *reloc_addr;
 	unsigned long symbol_addr;
 	int goof = 0;
@@ -190,40 +198,40 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
 		 * have been intentional.  We should not be linking local symbols
 		 * here, so all bases should be covered.
 		 */
-		if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) {
+		if (!symbol_addr
+		    && (ELF32_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
+		    && (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
 			_dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
-				     _dl_progname, strtab + symtab[symtab_index].st_name);
+				     _dl_progname, symname);
 			_dl_exit (1);
 		}
+		if (_dl_trace_prelink) {
+			_dl_debug_lookup(symname, tpnt, &symtab[symtab_index],
+				&sym_ref, elf_machine_type_class(reloc_type));
+		}
+#if defined USE_TLS && USE_TLS
+		tls_tpnt = sym_ref.tpnt;
+#endif
 	}
 
-#define COPY_UNALIGNED_WORD(swp, twp, align) \
-  { \
-    void *__s = (swp), *__t = (twp); \
-    unsigned char *__s1 = __s, *__t1 = __t; \
-    unsigned short *__s2 = __s, *__t2 = __t; \
-    unsigned long *__s4 = __s, *__t4 = __t; \
-    switch ((align)) \
-    { \
-    case 0: \
-      *__t4 = *__s4; \
-      break; \
-    case 2: \
-      *__t2++ = *__s2++; \
-      *__t2 = *__s2; \
-      break; \
-    default: \
-      *__t1++ = *__s1++; \
-      *__t1++ = *__s1++; \
-      *__t1++ = *__s1++; \
-      *__t1 = *__s1; \
-      break; \
-    } \
-  }
+#if defined USE_TLS && USE_TLS
+	/* In case of a TLS reloc, tls_tpnt NULL means we have an 'anonymous'
+	   symbol.  This is the case for a static tls variable, so the lookup
+	   module is just that one is referencing the tls variable. */
+	if (!tls_tpnt)
+		tls_tpnt = tpnt;
+#endif
 
+#define COPY_UNALIGNED_WORD(swp, twp) \
+{ \
+	__typeof (swp) __tmp = __builtin_nds32_unaligned_load_w ((unsigned int*)&swp); \
+	__builtin_nds32_unaligned_store_w ((unsigned int *)twp, __tmp); \
+}
 #if defined (__SUPPORT_LD_DEBUG__)
 	{
-		unsigned long old_val = *reloc_addr;
+		unsigned long old_val = 0;
+		if(reloc_type != R_NDS32_NONE)
+			old_val = *reloc_addr;
 #endif
 		symbol_addr += rpnt->r_addend ;
 		switch (reloc_type) {
@@ -235,7 +243,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
 				*reloc_addr = symbol_addr;
 				break;
 			case R_NDS32_32_RELA:
-				COPY_UNALIGNED_WORD (&symbol_addr, reloc_addr,(int) reloc_addr & 3);
+				COPY_UNALIGNED_WORD (symbol_addr, reloc_addr);
 				break;
 #undef COPY_UNALIGNED_WORD
 			case R_NDS32_RELATIVE:
@@ -245,12 +253,38 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
 				_dl_memcpy((void *) reloc_addr,
 					   (void *) symbol_addr, symtab[symtab_index].st_size);
 				break;
+#if defined USE_TLS && USE_TLS
+			case R_NDS32_TLS_TPOFF:
+				CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
+				*reloc_addr = (symbol_addr + tls_tpnt->l_tls_offset);
+				break;
+			case R_NDS32_TLS_DESC:
+				{
+					struct tlsdesc volatile *td = 
+							(struct tlsdesc volatile *)reloc_addr;
+#ifndef SHARED
+					CHECK_STATIC_TLS((struct link_map *) tls_tpnt);
+#else
+					if (!TRY_STATIC_TLS ((struct link_map *) tls_tpnt))
+					{
+					        td->argument.pointer = _dl_make_tlsdesc_dynamic((struct link_map *) tls_tpnt, symbol_addr);
+					        td->entry = _dl_tlsdesc_dynamic;
+					}
+					else
+#endif
+					{
+					        td->argument.value = symbol_addr + tls_tpnt->l_tls_offset;
+					        td->entry = _dl_tlsdesc_return;
+					}
+				}
+				break;
+#endif
 			default:
 				return -1; /*call _dl_exit(1) */
 		}
 #if defined (__SUPPORT_LD_DEBUG__)
 		if (_dl_debug_reloc && _dl_debug_detail)
-			_dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+			_dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", (unsigned int)old_val, (unsigned int)*reloc_addr, (unsigned int)reloc_addr);
 	}
 
 #endif
@@ -283,7 +317,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
 		}
 #if defined (__SUPPORT_LD_DEBUG__)
 		if (_dl_debug_reloc && _dl_debug_detail)
-			_dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+			_dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", (unsigned int)old_val, (unsigned int)*reloc_addr, (unsigned int)reloc_addr);
 	}
 
 #endif

+ 0 - 24
ldso/ldso/nds32/resolve.S

@@ -3,14 +3,6 @@
  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  */
 
-#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
-# define STACK_PUSH
-# define STACK_POP
-#else
-# define STACK_PUSH     addi   $sp,    $sp,    -24
-# define STACK_POP      addi   $sp,    $sp,    24
-#endif
-
  .text
  .align 4      ! 16 byte boundary
  .globl _dl_linux_resolve
@@ -28,22 +20,11 @@ _dl_linux_resolve:
 	smw.adm	$r0,	[$sp],	$r5,	6
 
 	! init gp
-#ifdef __NDS32_N1213_43U1H__
-	sethi	$gp,	HI20(_GLOBAL_OFFSET_TABLE_+4)
-	ori	$gp,	$gp,	LO12(_GLOBAL_OFFSET_TABLE_+8)
-	add	$gp,	$ta,	$gp
-#else
 	mfusr	$ta,	$PC
 	sethi	$gp,	HI20(_GLOBAL_OFFSET_TABLE_+4)
 	ori	$gp,	$gp,	LO12(_GLOBAL_OFFSET_TABLE_+8)
 	add	$gp,	$ta,	$gp
-#endif
 
-	! #ifdef __NDS32_ABI_1__
-	! adjust stack
-	!addi	$sp,	$sp,	-24
-	STACK_PUSH
-	! #endif
 
 	! set arguments
 	addi	$r0,	$r17,	0
@@ -61,11 +42,6 @@ _dl_linux_resolve:
 	! save the return
 	addi	$ta,	$r0,	0
 
-	! #ifdef __NDS32_ABI_1__
-	! adjust sp
-	!addi	$sp,	$sp,	24
-	STACK_POP
-	! #endif
 
 	! reload registers
 	lmw.bim	$r0,	[$sp],	$r5,	6

+ 0 - 1
ldso/libdl/Makefile.in

@@ -33,7 +33,6 @@ libdl_SRC := $(libdl_DIR)/libdl.c
 libdl_OBJ := $(patsubst $(libdl_DIR)/%.c,$(libdl_OUT)/%.o,$(libdl_SRC))
 
 resolve := $(top_builddir)ldso/ldso/$(TARGET_ARCH)/resolve.o
-
 libdl-a-y := $(libdl_OBJ) $(resolve)
 ifeq ($(DOPIC),y)
 libdl-a-y := $(libdl-a-y:.o=.os)

+ 21 - 1
libc/string/nds32/memcpy.S

@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Andes Technology, Inc.
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  */
 
@@ -54,12 +54,32 @@ ENTRY(memcpy)
 	srli	$r3, $r2, #5
 	beqz	$r3, .Lword_copy_entry
 	pushm	$r6, $r13
+        cfi_adjust_cfa_offset(32)
+        cfi_rel_offset(r6, 0)
+        cfi_rel_offset(r7, 4)
+        cfi_rel_offset(r8, 8)
+        cfi_rel_offset(r9, 12)
+        cfi_rel_offset(r10, 16)
+        cfi_rel_offset(r11, 20)
+        cfi_rel_offset(r12, 24)
+        cfi_rel_offset(r13, 28)
+
 .L3:
 	lmw.bim	$r6, [$r1], $r13
 	addi	$r3, $r3, #-1
 	smw.bim	$r6, [$r0], $r13
 	bnez	$r3, .L3
 	popm	$r6, $r13
+        cfi_adjust_cfa_offset(-32)
+        cfi_restore(r6)
+        cfi_restore(r7)
+        cfi_restore(r8)
+        cfi_restore(r9)
+        cfi_restore(r10)
+        cfi_restore(r11)
+        cfi_restore(r12)
+        cfi_restore(r13)
+
 
 .Lword_copy_entry:
 	andi	$r2, $r2, #31

+ 1 - 1
libc/string/nds32/memset.S

@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Andes Technology, Inc.
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  */
 

+ 1 - 1
libc/sysdeps/linux/common/posix_fadvise.c

@@ -41,7 +41,7 @@ int posix_fadvise(int fd, off_t offset, off_t len, int advice)
 #  if __WORDSIZE == 64
 	ret = INTERNAL_SYSCALL(fadvise64_64, err, 4, fd, offset, len, advice);
 #  else
-#   if defined (__arm__) || \
+#   if defined (__arm__) || defined (__nds32__) || \
       (defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) && (defined(__powerpc__) || defined(__xtensa__)))
 	/* arch with 64-bit data in even reg alignment #1: [powerpc/xtensa]
 	 * custom syscall handler (rearranges @advice to avoid register hole punch) */

+ 1 - 1
libc/sysdeps/linux/common/posix_fadvise64.c

@@ -25,7 +25,7 @@ int posix_fadvise64(int fd, off64_t offset, off64_t len, int advice)
 	int ret;
 	INTERNAL_SYSCALL_DECL (err);
 	/* ARM has always been funky. */
-#if defined (__arm__) || \
+#if defined (__arm__) || defined (__nds32__) || \
     (defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) && (defined(__powerpc__) || defined(__xtensa__)))
 	/* arch with 64-bit data in even reg alignment #1: [powerpc/xtensa]
 	 * custom syscall handler (rearranges @advice to avoid register hole punch) */

+ 1 - 1
libc/sysdeps/linux/common/sync_file_range.c

@@ -28,7 +28,7 @@ static int __NC(sync_file_range)(int fd, off64_t offset, off64_t nbytes, unsigne
 	return INLINE_SYSCALL(sync_file_range, 6, fd,
 			OFF64_HI_LO(offset), OFF64_HI_LO(nbytes), flags);
 #  elif (defined __mips__ && _MIPS_SIM == _ABIO32) || \
-	(defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) && !(defined(__powerpc__) || defined(__xtensa__)))
+	(defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) && !(defined(__powerpc__) || defined(__xtensa__) || defined(__nds32__)))
 	/* arch with 64-bit data in even reg alignment #2: [arcv2/others-in-future]
 	 * stock syscall handler in kernel (reg hole punched)
 	 * see libc/sysdeps/linux/common/posix_fadvise.c for more details */

+ 1 - 5
libc/sysdeps/linux/nds32/Makefile

@@ -1,9 +1,5 @@
-# Makefile for uClibc
-#
-# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
-#
+# Makefile for uClibc-ng
 # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
-#
 
 top_srcdir=../../../../
 top_builddir=../../../../

+ 4 - 2
libc/sysdeps/linux/nds32/Makefile.arch

@@ -1,5 +1,7 @@
 # Copyright (C) 2016 Andes Technology, Inc.
 # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
 
-CSRC-y := brk.c sigaction.c
-SSRC-y := setjmp.S __longjmp.S bsd-setjmp.S bsd-_setjmp.S clone.S mmap.S sigrestorer.S vfork.S sysdep.S syscall.S
+CSRC-y := brk.c prctl.c mremap.c syscall.c
+SSRC-y := setjmp.S __longjmp.S bsd-setjmp.S bsd-_setjmp.S clone.S vfork.S sysdep.S syscall.S
+CSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += makecontext.c swapcontext.c
+SSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += getcontext.S setcontext.S

+ 1 - 1
libc/sysdeps/linux/nds32/__longjmp.S

@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Andes Technology, Inc.
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  */
 

+ 110 - 0
libc/sysdeps/linux/nds32/bits/atomic.h

@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#ifndef _NDS32_BITS_ATOMIC_H
+#define _NDS32_BITS_ATOMIC_H
+
+#include <stdint.h>
+
+typedef int8_t atomic8_t;
+typedef uint8_t uatomic8_t;
+typedef int_fast8_t atomic_fast8_t;
+typedef uint_fast8_t uatomic_fast8_t;
+
+typedef int16_t atomic16_t;
+typedef uint16_t uatomic16_t;
+typedef int_fast16_t atomic_fast16_t;
+typedef uint_fast16_t uatomic_fast16_t;
+
+typedef int32_t atomic32_t;
+typedef uint32_t uatomic32_t;
+typedef int_fast32_t atomic_fast32_t;
+typedef uint_fast32_t uatomic_fast32_t;
+
+typedef int64_t atomic64_t;
+typedef uint64_t uatomic64_t;
+typedef int_fast64_t atomic_fast64_t;
+typedef uint_fast64_t uatomic_fast64_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+
+#ifndef atomic_full_barrier
+# define atomic_full_barrier() __asm__ ("dsb" ::: "memory")
+#endif
+
+#ifndef atomic_read_barrier
+# define atomic_read_barrier() atomic_full_barrier ()
+#endif
+
+#ifndef atomic_write_barrier
+# define atomic_write_barrier() atomic_full_barrier ()
+#endif
+
+#define atomic_exchange_acq(mem, newval)                    \
+  ({   unsigned long val, offset, temp;                     \
+                                                            \
+       __asm__ volatile (                                       \
+               "move   %2, %4\n\t"                          \
+               "move   %1, #0x0\n\t"                        \
+               "1:\n\t"                                     \
+               "llw    %0, [%3 + %1 << 0]\n\t"              \
+               "move   %2, %4\n\t"                          \
+               "scw    %2, [%3 + %1 << 0]\n\t"              \
+               "beqz   %2, 1b\n\t"                          \
+               : "=&r" (val), "=&r" (offset), "=&r" (temp)  \
+               : "r" (mem), "r" (newval)                    \
+               : "memory" );                                \
+       val; })
+
+#define atomic_compare_and_exchange_val_acq(mem, newval, oldval)  \
+  ({   unsigned long val, offset, temp;                     \
+                                                            \
+       __asm__ volatile (                                       \
+               "move   %1, #0x0\n\t"                        \
+               "move   %2, %4\n\t"                          \
+               "1:\n\t"                                     \
+               "llw    %0, [%3 + %1 << 0]\n\t"              \
+               "bne    %0, %5, 2f\n\t"                      \
+               "move   %2, %4\n\t"                          \
+               "scw    %2, [%3 + %1 << 0]\n\t"              \
+               "beqz   %2, 1b\n\t"                          \
+               "j      3f\n\t"                              \
+               "2:\n\t"                                     \
+               "move   %2, %0\n\t"                          \
+               "scw    %2, [%3 + %1 << 0]\n\t"              \
+               "3:\n\t"                                     \
+               : "=&r" (val), "=&r" (offset), "=&r" (temp)  \
+               : "r" (mem), "r" (newval), "r" (oldval)      \
+               : "memory" ); \
+       val; })
+
+#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
+  ({   unsigned long val, offset, temp;                     \
+                                                            \
+       __asm__ volatile (                                       \
+               "move   %1, #0x0\n\t"                        \
+               "move   %2, %4\n\t"                          \
+               "1:\n\t"                                     \
+               "llw    %0, [%3 + %1 << 0]\n\t"              \
+               "bne    %5, %0, 2f\n\t"                      \
+               "move   %2, %4\n\t"                          \
+               "scw    %2, [%3 + %1 << 0]\n\t"              \
+               "beqz   %2, 1b\n\t"                          \
+               "addi   %0, %1, #0\n\t"                      \
+               "j      3f\n\t"                              \
+               "2:\n\t"                                     \
+               "scw    %0, [%3 + %1 << 0]\n\t"              \
+               "addi   %0, %1, #0x1\n\t"                    \
+               "3:\n\t"                                     \
+               : "=&r" (val), "=&r" (offset), "=&r" (temp)  \
+               : "r" (mem), "r" (newval), "r" (oldval)      \
+               : "memory" ); \
+       val; })
+
+#endif

+ 5 - 1
libc/sysdeps/linux/nds32/bits/fcntl.h

@@ -1,7 +1,11 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
 /* O_*, F_*, FD_* bit values for Linux.
    Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2007
    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

+ 79 - 0
libc/sysdeps/linux/nds32/bits/fenv.h

@@ -0,0 +1,79 @@
+/* Copyright (C) 2004-2012 Free Software Foundation, Inc.
+
+   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 _FENV_H
+# error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
+#endif
+
+/* Define bits representing exceptions in the FPCSR status word.  */
+enum
+  {
+    FE_INVALID =
+#define FE_INVALID	0x4
+      FE_INVALID,
+    FE_DIVBYZERO =
+#define FE_DIVBYZERO	0x8
+      FE_DIVBYZERO,
+    FE_OVERFLOW =
+#define FE_OVERFLOW	0x10
+      FE_OVERFLOW,
+    FE_UNDERFLOW =
+#define FE_UNDERFLOW	0x20
+      FE_UNDERFLOW,
+    FE_INEXACT =
+#define FE_INEXACT	0x40
+      FE_INEXACT,
+  };
+
+
+/* All supported exceptions.  */
+#define FE_ALL_EXCEPT	\
+	(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
+
+/* Define bits representing rounding modes in the FPCSR RM field.  */
+enum
+  {
+    FE_TONEAREST =
+#define FE_TONEAREST    0x0
+      FE_TONEAREST,
+    FE_UPWARD =
+#define FE_UPWARD       0x1
+      FE_UPWARD,
+    FE_DOWNWARD =
+#define FE_DOWNWARD     0x2
+      FE_DOWNWARD,
+    FE_TOWARDZERO =
+#define FE_TOWARDZERO   0x3
+      FE_TOWARDZERO
+  };
+
+/* Type representing exception flags. */
+typedef unsigned int fexcept_t;
+
+/* Type representing floating-point environment.  */
+typedef struct
+  {
+    unsigned int __fpcsr;
+  }
+fenv_t;
+
+/* If the default argument is used we use this value.  */
+#define FE_DFL_ENV	((const fenv_t *) -1l)
+
+#ifdef __USE_GNU
+/* Floating-point environment where none of the exceptions are masked.  */
+# define FE_NOMASK_ENV  ((const fenv_t *) -2)
+#endif

+ 1 - 0
libc/sysdeps/linux/nds32/bits/mman.h

@@ -103,4 +103,5 @@
 /* Flags for `mremap'.  */
 #ifdef __USE_GNU
 # define MREMAP_MAYMOVE	1
+# define MREMAP_FIXED	2
 #endif

+ 12 - 6
libc/sysdeps/linux/nds32/bits/setjmp.h

@@ -24,19 +24,25 @@
 #ifndef _BITS_SETJMP_H
 #define _BITS_SETJMP_H  1
 
-#ifndef _SETJMP_H
+#if !defined _SETJMP_H && !defined _PTHREAD_H
 # error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
 #endif
 
 #ifndef _ASM
 typedef struct
   {
-    /* Callee-saved registers r6 - r14, r16 - r19 and r28 - r31.  */
-    int __regs[31];
+    /* Callee-saved registers: r6 - r14,
+ *      * fp, gp, lp, sp: r28 - r31.  */
+    int __regs[13];
+
+    /* Floating-Point Configuration Register.  */
+    int __fpcfg;
+
+    /* Callee-saved fp registers pointer.  */
+    int __fpregs[32];
+
+  } __jmp_buf[1] __attribute__((__aligned__ (8)));
 
-    /* Program counter.  */
-    void * __pc;
-  } __jmp_buf[1];
 #endif
 
 #endif  /* bits/setjmp.h */

+ 0 - 59
libc/sysdeps/linux/nds32/bits/sigcontext.h

@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2016 Andes Technology, Inc.
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-
-#ifndef _BITS_SIGCONTEXT_H
-#define _BITS_SIGCONTEXT_H 1
-
-#ifndef sigcontext_struct
-#define sigcontext_struct sigcontext
-
-struct sigcontext{
-        unsigned long trap_no;
-        unsigned long error_code;
-        unsigned long oldmask;
-        unsigned long nds32_r0;
-        unsigned long nds32_r1;
-        unsigned long nds32_r2;
-        unsigned long nds32_r3;
-        unsigned long nds32_r4;
-        unsigned long nds32_r5;
-        unsigned long nds32_r6;
-        unsigned long nds32_r7;
-        unsigned long nds32_r8;
-        unsigned long nds32_r9;
-        unsigned long nds32_r10;
-        unsigned long nds32_r11;
-        unsigned long nds32_r12;
-        unsigned long nds32_r13;
-        unsigned long nds32_r14;
-        unsigned long nds32_r15;
-        unsigned long nds32_r16;
-        unsigned long nds32_r17;
-        unsigned long nds32_r18;
-        unsigned long nds32_r19;
-	unsigned long nds32_r20;
-	unsigned long nds32_r21;
-	unsigned long nds32_r22;
-	unsigned long nds32_r23;
-	unsigned long nds32_r24;
-	unsigned long nds32_r25;
-        unsigned long nds32_fp;   //r28
-        unsigned long nds32_gp;   //r29
-        unsigned long nds32_lp;   //r30
-        unsigned long nds32_sp;   //r31
-        unsigned long nds32_d1lo;
-        unsigned long nds32_d1hi;
-        unsigned long nds32_d0lo;
-        unsigned long nds32_d0hi;
-        unsigned long nds32_ipsw;
-        unsigned long nds32_ipc;
-        unsigned long fault_address;
-};
-
-#define sc_pc  nds32_ipc /* For sysdeps/generic/profil-counter.h.  */
-
-#endif /* sigcontext_struct  */
-
-#endif /* _BITS_SIGCONTEXT_H  */

+ 35 - 0
libc/sysdeps/linux/nds32/bits/sigcontextinfo.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 1999-2013 Free Software Foundation, Inc.
+   Contributed by Philip Blundell <philb@gnu.org>, 1999.
+
+   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 <sys/ucontext.h>
+
+#define SIGCONTEXT siginfo_t *_si, struct ucontext *
+#define SIGCONTEXT_EXTRA_ARGS _si,
+
+#define GET_PC(ctx)	((void *) (ctx)->uc_mcontext.nds32_ipc)
+#define GET_FRAME(ctx)	ADVANCE_STACK_FRAME ((void *) ctx->uc_mcontext.nds32_fp)
+#define GET_STACK(ctx)	((void *) (ctx)->uc_mcontext.nds32_sp)
+
+
+#define CALL_SIGHANDLER(handler, signo, ctx) \
+  (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+

+ 277 - 77
libc/sysdeps/linux/nds32/bits/syscalls.h

@@ -3,6 +3,26 @@
  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  */
 
+/*
+ * For nds32 ISA, the syscall number(SWID) shall be determined at compile time.
+ * (ex: asm("syscall SWID"); )
+ * If the value of syscall number is determined at run time, we shall issue
+ * this syscall through sys_syscall.
+ * (ex:
+ *     asm("move $r0, SYSCALL_number"
+ *         "syscall 0x5071");
+ *     where 0x5071 is syscall number for sys_syscall
+ * )
+ *
+ * The following two macros are implemented according that syscall number
+ * is determined in compiler time or run time,
+ *
+ * 1. INTERNAL_SYSCALL_NCS: the syscall number is determined at run time
+ * 2. INTERNAL_SYSCALL: the syscall number is determined at compile time
+ *
+ */
+
+
 #ifndef _BITS_SYSCALLS_H
 #define _BITS_SYSCALLS_H
 #ifndef _SYSCALL_H
@@ -11,6 +31,14 @@
 
 #ifndef __ASSEMBLER__
 #include <errno.h>
+#include <common/sysdep.h>
+
+#define X(x) #x
+#define Y(x) X(x)
+#define        LIB_SYSCALL    __NR_syscall
+
+#define __issue_syscall(syscall_name)                   		\
+"       syscall  "  Y(syscall_name) ";	\n"
 
 #undef INTERNAL_SYSCALL_ERROR_P
 #define INTERNAL_SYSCALL_ERROR_P(val, err) ((unsigned int) (val) >= 0xfffff001u)
@@ -18,86 +46,258 @@
 #undef INTERNAL_SYSCALL_ERRNO
 #define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val))
 
-#define X(x) #x
-#define Y(x) X(x)
+#undef INLINE_SYSCALL
+#define INLINE_SYSCALL(name, nr, args...)                        	\
+  ({                                                             	\
+     INTERNAL_SYSCALL_DECL (err);                                	\
+     long result_var = INTERNAL_SYSCALL (name, err, nr, args);   	\
+     if (INTERNAL_SYSCALL_ERROR_P (result_var, err))             	\
+       {                                                         	\
+         __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); 	\
+			result_var = -1 ;			 	\
+       }                                                         	\
+     result_var;                                                 	\
+  })
+
+
+#undef INTERNAL_SYSCALL_DECL
+#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
+
 
-#define __issue_syscall(syscall_name)                   \
-"       syscall  "  Y(syscall_name) ";                    \n"
-
-#define INTERNAL_SYSCALL_NCS(name, err, nr, args...)	\
-(__extension__ 						\
-({							\
-	register long __result __asm__("$r0");		\
-	register long _sys_num __asm__("$r8");		\
-							\
-	LOAD_ARGS_##nr (name, args)			\
-        _sys_num = (name);				\
-							\
-        __asm__ volatile (				\
-		__issue_syscall (name)                  \
-		: "=r" (__result)			\
-		: "r"(_sys_num) ASM_ARGS_##nr		\
-		: "$lp", "memory");			\
-	__result;					\
-}) \
-)
-
-/* Macros for setting up inline __asm__ input regs */
-#define ASM_ARGS_0
-#define ASM_ARGS_1	ASM_ARGS_0, "r" (__result)
-#define ASM_ARGS_2	ASM_ARGS_1, "r" (_arg2)
-#define ASM_ARGS_3	ASM_ARGS_2, "r" (_arg3)
-#define ASM_ARGS_4	ASM_ARGS_3, "r" (_arg4)
-#define ASM_ARGS_5	ASM_ARGS_4, "r" (_arg5)
-#define ASM_ARGS_6	ASM_ARGS_5, "r" (_arg6)
-#define ASM_ARGS_7	ASM_ARGS_6, "r" (_arg7)
-
-/* Macros for converting sys-call wrapper args into sys call args */
-#define LOAD_ARGS_0(name, arg)					\
-	_sys_num = (long) (name);				\
-
-#define LOAD_ARGS_1(name, arg1)					\
-	__result = (long) (arg1);					\
-	LOAD_ARGS_0 (name, arg1)
+#undef INTERNAL_SYSCALL
+#define INTERNAL_SYSCALL(name, err, nr, args...) internal_syscall##nr(__NR_##name, err, args)
 
 /*
- * Note that the use of _tmpX might look superflous, however it is needed
- * to ensure that register variables are not clobbered if arg happens to be
- * a function call itself. e.g. sched_setaffinity() calling getpid() for arg2
- *
- * Also this specific order of recursive calling is important to segregate
- * the tmp args evaluation (function call case described above) and assigment
- * of register variables
- */
-#define LOAD_ARGS_2(name, arg1, arg2)				\
-	long _tmp2 = (long) (arg2);				\
-	LOAD_ARGS_1 (name, arg1)				\
-	register long _arg2 __asm__ ("$r1") = _tmp2;
-
-#define LOAD_ARGS_3(name, arg1, arg2, arg3)			\
-	long _tmp3 = (long) (arg3);				\
-	LOAD_ARGS_2 (name, arg1, arg2)				\
-	register long _arg3 __asm__ ("$r2") = _tmp3;
-
-#define LOAD_ARGS_4(name, arg1, arg2, arg3, arg4)		\
-	long _tmp4 = (long) (arg4);				\
-	LOAD_ARGS_3 (name, arg1, arg2, arg3)			\
-	register long _arg4 __asm__ ("$r3") = _tmp4;
-
-#define LOAD_ARGS_5(name, arg1, arg2, arg3, arg4, arg5)		\
-	long _tmp5 = (long) (arg5);				\
-	LOAD_ARGS_4 (name, arg1, arg2, arg3, arg4)		\
-	register long _arg5 __asm__ ("$r4") = _tmp5;
-
-#define LOAD_ARGS_6(name,  arg1, arg2, arg3, arg4, arg5, arg6)	\
-	long _tmp6 = (long) (arg6);				\
-	LOAD_ARGS_5 (name, arg1, arg2, arg3, arg4, arg5)	\
-	register long _arg6 __asm__ ("$r5") = _tmp6;
-
-#define LOAD_ARGS_7(name, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
-	long _tmp7 = (long) (arg7);				\
-	LOAD_ARGS_6 (name, arg1, arg2, arg3, arg4, arg5, arg6)	\
-	register long _arg7 __asm__ ("$r6") = _tmp7;
+   The _NCS variant allows non-constant syscall numbers but it is not
+   possible to use more than four parameters.
+*/
+#undef INTERNAL_SYSCALL_NCS
+#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) internal_syscall_ncs##nr(name, err, args)
+
+
+#define internal_syscall0(name, err, dummy...)                   	\
+  ({                                                             	\
+       register long ___res  __asm__("$r0");               		\
+       __asm__ volatile (                                        	\
+       __issue_syscall (name)                                    	\
+       : "=r" (___res)         /* output operands  */             	\
+       :							 	\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 	\
+       ___res;							 	\
+  })
+
+#define internal_syscall1(name, err, arg1)                       	\
+  ({                                                             	\
+       register long ___res  __asm__("$r0");                         	\
+       register long __arg1 __asm__("$r0") = (long) (arg1);         	\
+       __asm__ volatile (                                        	\
+       __issue_syscall (name)                                    	\
+       : "=r" (___res)         /* output operands  */             	\
+       : "r" (__arg1)         /* input operands  */              	\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 	\
+        ___res;                                                   	\
+  })
+
+#define internal_syscall2(name, err, arg1, arg2)                 	\
+  ({                                                             	\
+       register long ___res  __asm__("$r0");                         	\
+       register long __arg1 __asm__("$r0") = (long) (arg1);         	\
+       register long __arg2 __asm__("$r1") = (long) (arg2);         	\
+       __asm__ volatile (                                        	\
+       __issue_syscall (name)                                    	\
+       : "=r" (___res)         /* output operands  */             	\
+       : "r" (__arg1)         /* input operands  */              	\
+       , "r" (__arg2)         /* input operands  */              	\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 	\
+        ___res;                                                   	\
+  })
+
+#define internal_syscall3(name, err, arg1, arg2, arg3)           	\
+  ({                                                             	\
+       register long ___res  __asm__("$r0");                         	\
+       register long __arg1 __asm__("$r0") = (long) (arg1);         	\
+       register long __arg2 __asm__("$r1") = (long) (arg2);         	\
+       register long __arg3 __asm__("$r2") = (long) (arg3);         	\
+       __asm__ volatile (                                        	\
+       __issue_syscall (name)                                    	\
+       : "=r" (___res)         /* output operands  */             	\
+       : "r" (__arg1)         /* input operands  */              	\
+       , "r" (__arg2)         /* input operands  */              	\
+       , "r" (__arg3)         /* input operands  */              	\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 	\
+        ___res;                                                   	\
+  })
+
+#define internal_syscall4(name, err, arg1, arg2, arg3, arg4)     	\
+  ({                                                             	\
+       register long ___res  __asm__("$r0");                         	\
+       register long __arg1 __asm__("$r0") = (long) (arg1);         	\
+       register long __arg2 __asm__("$r1") = (long) (arg2);         	\
+       register long __arg3 __asm__("$r2") = (long) (arg3);         	\
+       register long __arg4 __asm__("$r3") = (long) (arg4);         	\
+       __asm__ volatile (                                        	\
+       __issue_syscall (name)                                    	\
+       : "=r" (___res)         /* output operands  */             	\
+       : "r" (__arg1)         /* input operands  */              	\
+       , "r" (__arg2)         /* input operands  */              	\
+       , "r" (__arg3)         /* input operands  */              	\
+       , "r" (__arg4)         /* input operands  */              	\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 	\
+        ___res;                                                   	\
+  })
+
+#define internal_syscall5(name, err, arg1, arg2, arg3, arg4, arg5) 	\
+  ({                                                             	\
+       register long ___res  __asm__("$r0");                         	\
+       register long __arg1 __asm__("$r0") = (long) (arg1);         	\
+       register long __arg2 __asm__("$r1") = (long) (arg2);         	\
+       register long __arg3 __asm__("$r2") = (long) (arg3);         	\
+       register long __arg4 __asm__("$r3") = (long) (arg4);         	\
+       register long __arg5 __asm__("$r4") = (long) (arg5);         	\
+       __asm__ volatile (                                        	\
+       __issue_syscall (name)                                    	\
+       : "=r" (___res)         /* output operands  */             	\
+       : "r" (__arg1)         /* input operands  */              	\
+       , "r" (__arg2)         /* input operands  */              	\
+       , "r" (__arg3)         /* input operands  */              	\
+       , "r" (__arg4)         /* input operands  */              	\
+       , "r" (__arg5)         /* input operands  */              	\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 	\
+        ___res;                                                   	\
+  })
+
+#define internal_syscall6(name, err, arg1, arg2, arg3, arg4, arg5, arg6) 	\
+  ({                                                             		\
+       register long ___res  __asm__("$r0");                         		\
+       register long __arg1 __asm__("$r0") = (long) (arg1);         		\
+       register long __arg2 __asm__("$r1") = (long) (arg2);         		\
+       register long __arg3 __asm__("$r2") = (long) (arg3);         		\
+       register long __arg4 __asm__("$r3") = (long) (arg4);         		\
+       register long __arg5 __asm__("$r4") = (long) (arg5);         		\
+       register long __arg6 __asm__("$r5") = (long) (arg6);         		\
+       __asm__ volatile (                                        		\
+       __issue_syscall (name)                                    		\
+       : "=r" (___res)         /* output operands  */             		\
+       : "r" (__arg1)         /* input operands  */              		\
+       , "r" (__arg2)         /* input operands  */              		\
+       , "r" (__arg3)         /* input operands  */              		\
+       , "r" (__arg4)         /* input operands  */              		\
+       , "r" (__arg5)         /* input operands  */              		\
+       , "r" (__arg6)         /* input operands  */              		\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 		\
+        ___res;                                                   		\
+  })
+#define internal_syscall7(name, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7) 	\
+  ({                                                             		\
+       register long ___res  __asm__("$r0");                         		\
+       register long __arg1 __asm__("$r0") = (long) (arg1);         		\
+       register long __arg2 __asm__("$r1") = (long) (arg2);         		\
+       register long __arg3 __asm__("$r2") = (long) (arg3);         		\
+       register long __arg4 __asm__("$r3") = (long) (arg4);         		\
+       register long __arg5 __asm__("$r4") = (long) (arg5);         		\
+       register long __arg6 __asm__("$r5") = (long) (arg6);         		\
+       __asm__ volatile (                                        		\
+	"addi10.sp\t  #-4\n\t"							\
+	CFI_ADJUST_CFA_OFFSET(4)"\n\t"						\
+        "push\t %7\n\t"								\
+	CFI_ADJUST_CFA_OFFSET(4)"\n\t"						\
+       __issue_syscall (name)                                    		\
+	"addi10.sp\t  #4\n\t"							\
+	CFI_ADJUST_CFA_OFFSET(-4)"\n\t"						\
+        "pop\t %7\n\t"								\
+	CFI_ADJUST_CFA_OFFSET(-4)"\n\t"						\
+       : "=r" (___res)         /* output operands  */             		\
+       : "r" (__arg1)         /* input operands  */              		\
+       , "r" (__arg2)         /* input operands  */              		\
+       , "r" (__arg3)         /* input operands  */              		\
+       , "r" (__arg4)         /* input operands  */              		\
+       , "r" (__arg5)         /* input operands  */              		\
+       , "r" (__arg6)         /* input operands  */              		\
+       , "r" (arg7)         /* input operands  */              		\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 		\
+        ___res;                                                   		\
+  })
+
+#define internal_syscall_ncs0(name, err, dummy...)               	\
+  ({                                                             	\
+       register long __res  __asm__("$r0");                         	\
+       register long __no   __asm__("$r0") = (long) (name);         	\
+       __asm__ volatile (                                        	\
+       __issue_syscall (LIB_SYSCALL)                             	\
+       : "=r" (__res)         /* output operands  */             	\
+       : "r" (__no)           /* input operands  */              	\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 	\
+       __res;							 	\
+  })
+
+#define internal_syscall_ncs1(name, err, arg1)                   	\
+  ({                                                             	\
+       register long __res  __asm__("$r0");                         	\
+       register long __no   __asm__("$r0") = (long) (name);         	\
+       register long __arg1 __asm__("$r1") = (long) (arg1);         	\
+       __asm__ volatile (                                        	\
+       __issue_syscall (LIB_SYSCALL)                             	\
+       : "=r" (__res)         /* output operands  */             	\
+       : "r" (__arg1)         /* input operands  */              	\
+       , "r" (__no)           /* input operands  */              	\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 	\
+        __res;                                                   	\
+  })
+
+#define internal_syscall_ncs2(name, err, arg1, arg2)             	\
+  ({                                                             	\
+       register long __res  __asm__("$r0");                         	\
+       register long __no   __asm__("$r0") = (long) (name);         	\
+       register long __arg1 __asm__("$r1") = (long) (arg1);         	\
+       register long __arg2 __asm__("$r2") = (long) (arg2);         	\
+       __asm__ volatile (                                        	\
+       __issue_syscall (LIB_SYSCALL)                             	\
+       : "=r" (__res)         /* output operands  */             	\
+       : "r" (__arg1)         /* input operands  */              	\
+       , "r" (__arg2)         /* input operands  */              	\
+       , "r" (__no)           /* input operands  */              	\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 	\
+        __res;                                                   	\
+  })
+
+#define internal_syscall_ncs3(name, err, arg1, arg2, arg3)      	\
+  ({                                                            	\
+       register long __res  __asm__("$r0");                     	\
+       register long __no   __asm__("$r0") = (long) (name);     	\
+       register long __arg1 __asm__("$r1") = (long) (arg1);     	\
+       register long __arg2 __asm__("$r2") = (long) (arg2);     	\
+       register long __arg3 __asm__("$r3") = (long) (arg3);     	\
+       __asm__ volatile (                                       	\
+       __issue_syscall (LIB_SYSCALL)                            	\
+       : "=r" (__res)         /* output operands  */            	\
+       : "r" (__arg1)         /* input operands  */             	\
+       , "r" (__arg2)         /* input operands  */             	\
+       , "r" (__arg3)         /* input operands  */             	\
+       , "r" (__no)           /* input operands  */             	\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */	\
+        __res;                                                  	\
+  })
+
+#define internal_syscall_ncs4(name, err, arg1, arg2, arg3, arg4) 	\
+  ({                                                             	\
+       register long __res  __asm__("$r0");                      	\
+       register long __no   __asm__("$r0") = (long) (name);      	\
+       register long __arg1 __asm__("$r1") = (long) (arg1);      	\
+       register long __arg2 __asm__("$r2") = (long) (arg2);      	\
+       register long __arg3 __asm__("$r3") = (long) (arg3);      	\
+       register long __arg4 __asm__("$r4") = (long) (arg4);      	\
+       __asm__ volatile (                                        	\
+       __issue_syscall (LIB_SYSCALL)                             	\
+       : "=r" (__res)         /* output operands  */             	\
+       : "r" (__arg1)         /* input operands  */              	\
+       , "r" (__arg2)         /* input operands  */              	\
+       , "r" (__arg3)         /* input operands  */              	\
+       , "r" (__arg4)         /* input operands  */              	\
+       , "r" (__no)           /* input operands  */              	\
+       : __SYSCALL_CLOBBERS); /* list of clobbered registers  */ 	\
+        __res;                                                   	\
+  })
 
+#define __SYSCALL_CLOBBERS "$lp", "memory"
 #endif /* ! __ASSEMBLER__  */
 #endif /* _BITS_SYSCALLS_H */

+ 1 - 1
libc/sysdeps/linux/nds32/bits/uClibc_arch_features.h

@@ -11,7 +11,7 @@
 #define _BITS_UCLIBC_ARCH_FEATURES_H
 
 /* instruction used when calling abort() to kill yourself */
-#undef __UCLIBC_ABORT_INSTRUCTION__
+#define __UCLIBC_ABORT_INSTRUCTION__ "bal abort"
 
 /* does your target align 64bit values in register pairs ? (32bit arches only) */
 #define __UCLIBC_SYSCALL_ALIGN_64BIT__

+ 2 - 3
libc/sysdeps/linux/nds32/bsd-_setjmp.S

@@ -21,8 +21,8 @@ ENTRY(_setjmp)
 	add     $r2, $r15, $r2
 
 	! la    $r3, __sigsetjmp@PLT
-	sethi   $r3, hi20(__sigsetjmp@PLT)
-	ori     $r3, $r3, lo12(__sigsetjmp@PLT)
+	sethi   $r3, hi20(HIDDEN_JUMPTARGET(__sigsetjmp)@PLT)
+	ori     $r3, $r3, lo12(HIDDEN_JUMPTARGET(__sigsetjmp)@PLT)
 	add     $r3, $r3, $r2
 
 	jr      $r3
@@ -32,4 +32,3 @@ ENTRY(_setjmp)
 #endif
 
 END(_setjmp)
-libc_hidden_def(_setjmp)

+ 2 - 2
libc/sysdeps/linux/nds32/bsd-setjmp.S

@@ -21,8 +21,8 @@ ENTRY(setjmp)
 	add     $r2, $r15, $r2
 
 	! la    $r3, __sigsetjmp@PLT
-	sethi   $r3, hi20(__sigsetjmp@PLT)
-	ori     $r3, $r3, lo12(__sigsetjmp@PLT)
+	sethi   $r3, hi20(HIDDEN_JUMPTARGET(__sigsetjmp)@PLT)
+	ori     $r3, $r3, lo12(HIDDEN_JUMPTARGET(__sigsetjmp)@PLT)
 	add     $r3, $r3, $r2
 
 	jr      $r3

+ 144 - 56
libc/sysdeps/linux/nds32/clone.S

@@ -1,92 +1,180 @@
 /*
- * Copyright (C) 2016 Andes Technology, Inc.
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  */
 
+/* Copyright (C) 2010-2014 Free Software Foundation, Inc.
+   Contributed by Pat Beirne <patb@corelcomputer.com>
+
+   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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
 /* 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>
-#include <sys/syscall.h>
 #define _ERRNO_H	1
 #include <bits/errno.h>
 
-/*
-       int clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
-       _syscall2(int, clone, int, flags, void *, child_stack)
-*/
+#ifdef RESET_PID
+#include <tcb-offsets.h>
+#endif
+
+#define CLONE_VM      0x00000100
+#define CLONE_THREAD  0x00010000
+
+/* int clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
+   _syscall2(int, clone, int, flags, void *, child_stack)  */
 
 ENTRY(__clone)
+#ifdef __NDS32_ABI_2FP_PLUS__
+	lwi	$r4, [$sp]
+	lwi	$r5, [$sp+4]
+#endif
 #ifdef PIC
 	/* set GP register to parent only, cause child's $SP will be $r1. */
 	pushm	$fp, $gp
-#ifndef __NDS32_N1213_43U1H__
-	mfusr $r15, $PC
-#endif
-	sethi	$gp,	hi20(_GLOBAL_OFFSET_TABLE_+4)
-	ori	$gp,	$gp,	lo12(_GLOBAL_OFFSET_TABLE_+8)
-	add	$gp,	$gp,	$r15
-#endif
-        /* sanity check arguments.  */
-        beqz    $r0, 1f
-        bnez    $r1, 2f
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(fp, 0)
+	cfi_rel_offset(gp, 4)
+	mfusr	$r15, $pc
+	sethi	$gp, hi20(_GLOBAL_OFFSET_TABLE_+4)
+	ori	$gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_+8)
+	add	$gp, $gp, $r15
+#endif /* PIC  */
+
+	/* sanity check arguments.  */
+	beqz	$r0, 1f
+	bnez	$r1, 2f
 
 1:
-        movi    $r0, -EINVAL
+	movi	$r0, -EINVAL
+
 5:
 #ifdef PIC
-		  /* restore GP register, only in parent's stack */
-		  popm	$fp, $gp
-        la      $r15, C_SYMBOL_NAME(__syscall_error@PLT)
-        jr      $r15
-#else
-        b       C_SYMBOL_NAME(__syscall_error)
-#endif
+	/* restore GP register, only in parent's stack  */
+	la	$r15, C_SYMBOL_NAME(__syscall_error@PLT)
+	push	$lp
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset(lp, 0)
+	addi	$sp, $sp, -4
+	cfi_adjust_cfa_offset(4)
+	jral	$r15
+	addi	$sp, $sp, 4
+	cfi_adjust_cfa_offset(-4)
+	pop	$lp
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(lp)
+	popm	$fp, $gp
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(fp)
+	cfi_restore(gp)
+	ret
+#else /* ! PIC  */
+	la	$r15, C_SYMBOL_NAME(__syscall_error)
+	jr	$r15
+#endif /* ! PIC  */
 
 2:
-	/* Child's $SP will be $r1, push to child's stack only. */
+	/* Child's $sp will be $r1, make $sp 8-byte alignment */
+	bitci	$r1, $r1, 7
+	/* push to child's stack only.  */
 	addi	$r1, $r1, -4
-        swi.p   $r3, [$r1], -4  ! arg
-        swi     $r0, [$r1]  ! fn
+	swi.p	$r3, [$r1], -4			! arg
+	swi	$r0, [$r1]			! fn
+
+	/* do the system call  */
+	or	$r0, $r2, $r2			! move $r0, $r2
+
+	move    $r3, $r5
+	move    $r5, $r2                        ! Use $r5 to backup $r2
+						! The pt_regs is placed in $r5 in kerenl (sys_clone_wrapper)
+	move    $r2, $r4
 
-        /* do the system call */
-        or      $r0, $r2, $r2   ! move r0, r2
-        __do_syscall(clone)
-	!syscall (__NR_clone)
-        beqz    $r0, 4f
-        bltz    $r0, 5b
+#ifdef __NDS32_ABI_2FP_PLUS__
+# ifdef PIC
+       lwi     $r4, [$sp+#0x10]
+# else
+       lwi     $r4, [$sp+#0x8]
+# endif
+#else
+# ifdef PIC
+       lwi     $r4, [$sp+#0x8]
+# else
+       lwi     $r4, [$sp]
+# endif
+#endif
+
+	__do_syscall(clone)
+	beqz    $r0, 4f
+	bltz    $r0, 5b
 
-        ! parent
+
+10:
 #ifdef PIC
-	/* restore GP register, only in parent's stack */
+	/* restore GP register, only in parent's stack  */
 	popm	$fp, $gp
-#endif
-        ret
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(gp)
+	cfi_restore(fp)
+#endif /* PIC  */
+	ret
 
+#ifdef RESET_PID
 4:
-	/* Only in child's stack. */
-        pop     $r1  ! fn
-        pop     $r0  ! arg
-#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
+	cfi_undefined(lp)
+	movi	$r0, CLONE_THREAD		! Skip when CLONE_THREAD is set.
+	and	$r0, $r5, $r0
+	bnez	$r0, 8f
+	movi    $r0, CLONE_VM			! Value = -1 when CLONE_VM is set.
+	and	$r0, $r5, $r0
+	beqz	$r0, 6f
+	movi	$r0, -1
+	j	7f
+6:
+        __do_syscall(getpid) ! __do_syscall(gettid) ! __do_syscall(getpid)
+7:
+	swi     $r0, [$r25 + PID_OFFSET]
+        swi     $r0, [$r25 + TID_OFFSET]
+8:
 #else
-	addi	$sp, $sp, -24
-#endif
-	! use r15 in case _exit is PIC
-#ifdef __NDS32_N1213_43U1H__
-        or      $r15, $r1, $r1   ! move r15, r2
+4:
 #endif
-        bral    $r1
-#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
-#else
+	/* Only in child's stack.  */
+	pop	$r1				! fn
+	pop	$r0				! arg
+
+
+#if !defined(__NDS32_ABI_2__) && !defined(__NDS32_ABI_2FP_PLUS__)
+	addi	$sp, $sp, -24
+#endif /* !defined(__NDS32_ABI_2__) && !defined(__NDS32_ABI_2FP_PLUS__)  */
+
+	! use $r15 in case _exit is PIC
+	bral	$r1
+
+#if !defined(__NDS32_ABI_2__) && !defined(__NDS32_ABI_2FP_PLUS__)
 	addi	$sp, $sp, 24
-#endif
-	! use r15 in case _exit is PIC
+#endif /* !defined(__NDS32_ABI_2__) && !defined(__NDS32_ABI_2FP_PLUS__)  */
+
+	! use $r15 in case _exit is PIC
 #ifdef PIC
-        la      $r15, C_SYMBOL_NAME(_exit@PLT)
-        jr      $r15
-#else
-        b       C_SYMBOL_NAME(_exit)
-#endif
+	la	$r15, C_SYMBOL_NAME(_exit@PLT)
+#else /* ! PIC  */
+	la	$r15, C_SYMBOL_NAME(_exit)
+#endif /* ! PIC  */
+	jr	$r15
 
 
 PSEUDO_END (__clone)

+ 0 - 7
libc/sysdeps/linux/nds32/crt1.S

@@ -45,17 +45,10 @@ _start:
 
 #ifdef SHARED
 	/* set gp register */
-#ifdef __NDS32_N1213_43U1H__
-	jal	1b
-	sethi	$gp,	HI20(_GLOBAL_OFFSET_TABLE_)
-	ori	$gp,	$gp, LO12(_GLOBAL_OFFSET_TABLE_ + 4)
-	add	$gp,	$lp,	$gp
-#else
 	mfusr 	$r15, 	$PC
 	sethi	$gp,	HI20(_GLOBAL_OFFSET_TABLE_+4)
 	ori	$gp,	$gp, LO12(_GLOBAL_OFFSET_TABLE_ + 8)
 	add	$gp,	$r15,	$gp
-#endif
 
 	la		$r3,	_init@GOTOFF
 	la		$r4,	_fini@GOTOFF

+ 0 - 24
libc/sysdeps/linux/nds32/crti.S

@@ -11,8 +11,6 @@
 	.type	_init, @function
 _init:
 .LFB28:
-        ! Generate instructions for ABI: 1
-	! pretend args size: 0, auto vars size: 0, pushed regs size: 12, outgoing args size: 24
         ! Generate instructions for ABI: 2
 	! pretend args size: 0, auto vars size: 0, pushed regs size: 12, outgoing args size: 0
 	! frame pointer: $fp, needed: yes
@@ -22,22 +20,12 @@ _init:
 	smw.adm $sp,[$sp],$sp,#0x8
 	smw.adm $sp,[$sp],$sp,#0x6
 	.restore_16bit
-#ifdef __NDS32_N1213_43U1H__
-	sethi	$gp, hi20(_GLOBAL_OFFSET_TABLE_+8)
-	ori	$gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_+12)
-#else
 	sethi	$gp, hi20(_GLOBAL_OFFSET_TABLE_-8)
 	ori	$gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4)
 	mfusr	$ta, $pc
-#endif
 	add	$gp, $ta, $gp
-#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
         addi    $sp, $sp, -4
         addi    $fp, $sp, 8
-#else
-        addi    $sp, $sp, -28
-        addi    $fp, $sp, 32
-#endif
 	! end of prologue
 #APP
 	.align	2
@@ -48,8 +36,6 @@ _init:
 	.type	_fini, @function
 _fini:
 .LFB29:
-        ! Generate instructions for ABI: 1
-	! pretend args size: 0, auto vars size: 0, pushed regs size: 12, outgoing args size: 24
         ! Generate instructions for ABI: 2
 	! pretend args size: 0, auto vars size: 0, pushed regs size: 12, outgoing args size: 0
 	! frame pointer: $fp, needed: yes
@@ -59,22 +45,12 @@ _fini:
 	smw.adm $sp,[$sp],$sp,#0x8
 	smw.adm $sp,[$sp],$sp,#0x6
 	.restore_16bit
-#ifdef __NDS32_N1213_43U1H__
-	sethi	$gp, hi20(_GLOBAL_OFFSET_TABLE_+8)
-	ori	$gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_+12)
-#else
 	sethi	$gp, hi20(_GLOBAL_OFFSET_TABLE_-8)
 	ori	$gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4)
 	mfusr	$ta, $pc
-#endif
 	add	$gp, $ta, $gp
-#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
         addi    $sp, $sp, -4
         addi    $fp, $sp, 8
-#else
-        addi    $sp, $sp, -28
-        addi    $fp, $sp, 32
-#endif
 	! end of prologue
 #APP
 	.align  2

+ 77 - 0
libc/sysdeps/linux/nds32/fpu_control.h

@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#ifndef _FPU_CONTROL_H
+
+#ifdef  __NDS32_ABI_2FP_PLUS__
+/*
+ * Andes Floating-Point Control Status Register
+ * 31-20 -> Reserved
+ * 19	 -> RIT (RO)
+ * 18	 -> DNIT(RO)
+ * 17	 -> IEXT(RO)
+ * 16	 -> UDFT(RO)
+ * 15	 -> OVFT(RO)
+ * 14	 -> DBZT(RO)
+ * 13	 -> IVOT(RO)
+ * 12	 -> DNZ(RW),Denormalized flush-to-Zero mode.
+ * 11	 -> IEXE(RW),IEEE Ineaxct (IEX) exception trapping enable.
+ * 10	 -> UDFE(RW),IEEE Underflow (UDF) exception trapping enable.
+ * 9	 -> OVFE(RW),IEEE Overflow (OVF) exception trapping enable.
+ * 8	 -> DBZE(RW),IEEE Divide by Zero (DBZ) exception trapping enable.
+ * 7	 -> IVOE(RW),IEEE Invalid Operation (IVO) exception trapping enable.
+ * 6	 -> IEX(RW),IEEE Inexact (IEX) cumulative exception flag.
+ * 5	 -> UDF(RW),IEEE Underflow (UDF) cumulative exception flag.
+ * 4	 -> OVF(RW),IEEE Overflow (OVF) cumulative exception flag.
+ * 3	 -> DBZ(RW),IEEE Divide by Zero (DBZ) cumulative exception flag.
+ * 2	 -> IVO(RW),IEEE Invalid Operation (IVO) cumulative exception flag.
+ * 1-0	 -> Rounding modes.
+ *
+ * Rounding modes.
+ * 00 - rounding to nearest (RN)
+ * 01 - rounding (up) toward plus infinity (RP)
+ * 10 - rounding (down)toward minus infinity (RM)
+ * 11 - rounding toward zero (RZ)
+ *
+ */
+
+
+/* masking of interrupts */
+#define _FPU_MASK_IEX  	0x0800  /* Invalid operation */
+#define _FPU_MASK_UDF  	0x0400  /* Underflow         */
+#define _FPU_MASK_OVF  	0x0200  /* Overflow          */
+#define _FPU_MASK_DBZ  	0x0100  /* Division by zero  */
+#define _FPU_MASK_IVO 	0x0080  /* Invalid operation */
+
+/*Reserved and read-only bits*/
+#define _FPU_RESERVED	0xffffe000
+#define _FPU_DEFAULT    0x00000000
+
+/* Default + exceptions enabled. */
+#define _FPU_IEEE	(_FPU_DEFAULT | 0x00000f80)
+
+/* Type of the control word.  */
+typedef unsigned int fpu_control_t;
+
+/* Macros for accessing the hardware control word.  */
+/* This is fmrx %0, fpscr.  */
+#define _FPU_GETCW(cw) \
+  __asm__ __volatile__ ("fmfcsr\t %0\n\t" : "=r" (cw))
+/* This is fmxr fpscr, %0.  */
+#define _FPU_SETCW(cw) \
+  __asm__ __volatile__ ("fmtcsr\t %0\n\t": : "r" (cw))
+
+/* Default control word set at startup.  */
+extern fpu_control_t __fpu_control;
+#else
+#define _FPU_GETCW(cw) (cw) = 0
+#define _FPU_SETCW(cw) (void) (cw)
+#define _FPU_RESERVED 0xffffffff
+#define _FPU_DEFAULT  0x00000000
+typedef unsigned int fpu_control_t;
+extern fpu_control_t __fpu_control;
+
+#endif //__NDS32_ABI_2FP_PLUS__
+#endif //_FPU_CONTROL_H

+ 106 - 0
libc/sysdeps/linux/nds32/getcontext.S

@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 20[B01-2013 Free Software Foundation, Inc.
+   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
+
+   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 "ucontext_i.h"
+
+/*  __getcontext (const ucontext_t *ucp)
+
+  Saves the machine context in UCP such that when it is activated,
+  it appears as if __getcontext() returned again.
+
+  This implementation is intended to be used for *synchronous* context
+  switches only.  Therefore, it does not have to save anything
+  other than the PRESERVED state.  */
+
+ENTRY(__getcontext)
+        swi     $lp, [$r0 + UCONTEXT_PC]
+        addi    $r15, $r0, UCONTEXT_GREGS
+        xor     $r1, $r1, $r1
+	smw.bim	$r1, [$r15], $r1
+	smw.bim	$r1, [$r15], $r14
+        addi    $r15, $r15, 4
+	smw.bim	$r16, [$r15], $r25, #0xf
+	move    $r4, $r0
+
+	/* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask).  */
+	move    $r0, SIG_BLOCK
+	move	$r1, 0
+	addi	$r2, $r4, UCONTEXT_SIGMASK
+	move	$r3, _NSIG8
+	syscall SYS_ify(rt_sigprocmask)
+        bnez    $r0, 1f
+
+
+#ifdef __NDS32_ABI_2FP_PLUS__
+	addi	$r2, $r4, UCONTEXT_FDREGS
+/* Process for FPU registers.  */
+	fmfcfg	$r20	/* Keep $fpcfg in $r20.  */
+	slli	$r20, $r20, #28
+	srli	$r20, $r20, #30	/* Set $r20 as $fpcfg.freg.  */
+
+	/* Case switch for $r20 as $fpcfg.freg.  */
+	beqz	$r20, .LCFG0		/* Branch if $fpcfg.freg = 0b00.  */
+	xori	$r15, $r20, #0b10
+	beqz	$r15, .LCFG2		/* Branch if $fpcfg.freg = 0b10.  */
+	srli	$r20, $r20, #0b01
+	beqz	$r20, .LCFG1		/* Branch if $fpcfg.freg = 0b01.  */
+	/* Fall-through if $fpcfg.freg = 0b11.  */
+.LCFG3:
+	fsdi $fd31, [$r2 + 248]
+	fsdi $fd30, [$r2 + 240]
+	fsdi $fd29, [$r2 + 232]
+	fsdi $fd28, [$r2 + 224]
+	fsdi $fd27, [$r2 + 216]
+	fsdi $fd26, [$r2 + 208]
+	fsdi $fd25, [$r2 + 200]
+	fsdi $fd24, [$r2 + 192]
+.LCFG2:
+	fsdi $fd10, [$r2 + 80]
+	fsdi $fd9, [$r2 + 72]
+	fsdi $fd8, [$r2 + 64]
+.LCFG1:
+	fsdi $fd7, [$r2 + 56]
+	fsdi $fd6, [$r2 + 48]
+	fsdi $fd5, [$r2 + 40]
+	fsdi $fd4, [$r2 + 32]
+.LCFG0:
+	fsdi $fd3, [$r2 + 24]
+	/*save fpcsr*/
+	fmfcsr $r1
+	swi $r1, [$r2 + 0x100]
+#endif /* __NDS32_ABI_2FP_PLUS__ */
+
+	/* Set __getcontext return value to 0.  */
+        xor      $r0, $r0, $r0
+        /* Return first_return: 1 */
+        addi     $r1, $r0, 1
+        ret
+
+1:
+	move $r0, -1
+	ret
+END(__getcontext)
+
+weak_alias (__getcontext, getcontext)
+

+ 17 - 1
libc/sysdeps/linux/nds32/jmpbuf-unwind.h

@@ -5,8 +5,24 @@
 
 #include <setjmp.h>
 #include <jmpbuf-offsets.h>
+#include <stdint.h>
+#include <unwind.h>
+#include <sysdep.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)[0].__regs[__JMP_BUF_SP])
+  ((void *) (address) < &(jmpbuf)[0].__regs[__JMP_BUF_SP])
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+static inline uintptr_t __attribute__ ((unused))
+_jmpbuf_sp (__jmp_buf regs)
+{
+  uintptr_t sp = &(regs)[0].__regs[__JMP_BUF_SP];
+  return sp;
+}
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+  ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))

+ 77 - 0
libc/sysdeps/linux/nds32/makecontext.c

@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 2011-2013 Free Software Foundation, Inc.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <stdarg.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <ucontext.h>
+
+/* makecontext sets up a stack and the registers for the
+   user context.  The stack looks like this:
+
+               +-----------------------+
+	       | padding as required   |
+               +-----------------------+
+    sp ->      | parameter 7-n         |
+               +-----------------------+
+
+   The registers are set up like this:
+     $r0 .. $r5: parameter 1 to 6
+     $r6   : uc_link
+     $sp   : stack pointer.
+*/
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+  extern void __startcontext (void);
+  unsigned long int *sp;
+  unsigned long *regptr;
+  va_list ap;
+  int i;
+
+  sp = (unsigned long int *)
+    ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
+
+  /* Allocate stack arguments.  */
+  sp -= argc < 6 ? 0 : argc - 6;
+
+  /* Keep the stack aligned.  */
+  sp = (unsigned long int *) (((uintptr_t) sp) & -8L);
+
+  ucp->uc_mcontext.nds32_r6 = (uintptr_t) ucp->uc_link;
+  ucp->uc_mcontext.nds32_sp = (uintptr_t) sp;
+  ucp->uc_mcontext.nds32_ipc = (uintptr_t) func;
+  ucp->uc_mcontext.nds32_lp = (uintptr_t) &__startcontext;
+
+  va_start (ap, argc);
+  regptr = &ucp->uc_mcontext.nds32_r0;
+  for (i = 0; i < argc; ++i)
+    if (i < 6)
+      *regptr++ = va_arg (ap, unsigned long int);
+    else
+      sp[i - 6] = va_arg (ap, unsigned long int);
+
+  va_end (ap);
+
+}
+weak_alias (__makecontext, makecontext)

+ 0 - 101
libc/sysdeps/linux/nds32/mmap.S

@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2016 Andes Technology, Inc.
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-
-/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
-
-   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, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <sys/syscall.h>
-#include <sysdep.h>
-	.text
-
-.globl __mmap
-ENTRY (__mmap)
-
-#ifdef PIC
-.pic
-#endif
-
-   // reserve space for r0, r1
-#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
-#else
-   addi  $sp, $sp, -8
-#endif
-   // change to units  of the  system  page  size
-   srli $r5, $r5, 0xc
-
-   syscall SYS_ify(mmap2)
-#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
-#else
-   addi  $sp, $sp, 8
-#endif
-
-   /* r0 is < -4096 if there was an error.  */
-   bgez $r0, 1f
-   sltsi $r1,$r0,-4096
-   beqz $r1,2f
-
-1:
-   ret
-2:
-#ifdef PIC
-#ifdef __NDS32_N1213_43U1H__
-	! save lp
-	addi	$r2,	$lp,	0
-
-	! set r1 as gp
-	jal	1b
-	sethi	$r1,	hi20(_GLOBAL_OFFSET_TABLE_)
-	ori	$r1,	$r1,	lo12(_GLOBAL_OFFSET_TABLE_+4)
-	add	$r1,	$lp,	$r1
-
-	! restore lp
-	addi	$lp,	$r2,	0
-
-	! r15=SYSCALL_ERROR@PLT
-	sethi $r15, hi20(SYSCALL_ERROR@PLT)
-	ori	$r15,	$r15, lo12(SYSCALL_ERROR@PLT)
-	add	$r15, $r15, $r1
-
-	! jump to SYSCALL_ERROR
-	jr		$r15
-#else
-	! set r1 as gp
-	mfusr $r15, $PC
-	sethi	$r1,	hi20(_GLOBAL_OFFSET_TABLE_+4)
-	ori	$r1,	$r1,	lo12(_GLOBAL_OFFSET_TABLE_+8)
-	add	$r1,	$r1,	$r15
-
-	! r15=SYSCALL_ERROR@PLT
-	sethi $r15, hi20(SYSCALL_ERROR@PLT)
-	ori	$r15,	$r15, lo12(SYSCALL_ERROR@PLT)
-	add	$r15, $r15, $r1
-
-	! jump to SYSCALL_ERROR
-	jr		$r15
-#endif
-#else
-	j SYSCALL_ERROR
-#endif
-
-ret
-
-PSEUDO_END (__mmap)
-
-weak_alias (__mmap, mmap)
-libc_hidden_def(mmap)

+ 28 - 0
libc/sysdeps/linux/nds32/mremap.c

@@ -0,0 +1,28 @@
+/*
+ *  Copyright (C) 2017 Andes Technology, Inc.
+ *  Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <sysdep.h>
+
+#include <sys/mman.h>
+#include <sys/syscall.h>
+
+#ifdef __NR_mremap
+void *mremap (void *__addr, size_t __old_len, size_t __new_len,
+                     int __flags, ...);
+libc_hidden_proto(mremap)
+
+void *mremap (void *__addr, size_t __old_len, size_t __new_len, int __flags, ...)
+{
+        unsigned long arg1;
+        va_list arg;
+        va_start (arg, __flags);
+        arg1 = va_arg (arg, int);
+        va_end (arg);
+        return (void *)INLINE_SYSCALL(mremap,5,__addr,__old_len,__new_len,__flags,arg1);
+}
+libc_hidden_def (mremap)
+#endif

+ 23 - 0
libc/sysdeps/linux/nds32/prctl.c

@@ -0,0 +1,23 @@
+/*
+ *  Copyright (C) 2017 Andes Technology, Inc.
+ *  Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <sysdep.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+
+int prctl (int __option, ...)
+{
+	unsigned long arg1,arg2,arg3,arg4;
+	va_list arg;
+	va_start (arg, __option);
+	arg1 = va_arg (arg, unsigned long);
+	arg2 = va_arg (arg, unsigned long);
+	arg3 = va_arg (arg, unsigned long);
+	arg4 = va_arg (arg, unsigned long);
+	va_end (arg);
+	return INLINE_SYSCALL(prctl,5,__option,arg1,arg2,arg3,arg4);
+}

+ 85 - 0
libc/sysdeps/linux/nds32/setcontext.S

@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+
+ENTRY(__setcontext)
+        move    $r4, $r0
+
+#ifdef __NDS32_ABI_2FP_PLUS__
+	addi	$r0,  $r4, UCONTEXT_FDREGS
+
+	/* Case switch for $r20 as $fpcfg.freg.  */
+	beqz    $r20, .LCFG0         /* Branch if $fpcfg.freg = 0b00.  */
+	xori    $r15, $r20, #0b10
+	beqz    $r15, .LCFG2         /* Branch if $fpcfg.freg = 0b10.  */
+	srli    $r20, $r20, #0b01
+	beqz    $r20, .LCFG1         /* Branch if $fpcfg.freg = 0b01.  */
+	/* Fall-through if $fpcfg.freg = 0b11.  */
+.LCFG3:
+	fldi $fd31, [$r0 + 248]
+	fldi $fd30, [$r0 + 240]
+	fldi $fd29, [$r0 + 232]
+	fldi $fd28, [$r0 + 224]
+	fldi $fd27, [$r0 + 216]
+	fldi $fd26, [$r0 + 208]
+	fldi $fd25, [$r0 + 200]
+	fldi $fd24, [$r0 + 192]
+.LCFG2:
+	fldi $fd10, [$r0 + 80]
+	fldi $fd9, [$r0 + 72]
+	fldi $fd8, [$r0 + 64]
+.LCFG1:
+	fldi $fd7, [$r0 + 56]
+	fldi $fd6, [$r0 + 48]
+	fldi $fd5, [$r0 + 40]
+	fldi $fd4, [$r0 + 32]
+.LCFG0:
+	fldi $fd3, [$r0 + 24]
+	/*save fpcsr*/
+	lwi $r1, [$r0 + 0x100]
+	fmtcsr $r1
+#endif /* __NDS32_ABI_2FP_PLUS__ */
+
+	/* sigprocmask (SIG_BLOCK, &sc->sc_mask, NULL).  */
+	move    $r0, SIG_SETMASK
+	addi	$r1, $r4, UCONTEXT_SIGMASK
+	move	$r2, 0
+	move	$r3, _NSIG8
+	syscall SYS_ify(rt_sigprocmask)
+        bnez    $r0, 1f
+
+        move    $r0, $r4
+        addi    $r15, $r4, UCONTEXT_GREGS + 4
+	lmw.bim	$r1, [$r15], $r14
+        addi    $r15, $r15, 4
+	lmw.bim	$r16, [$r15], $r25, #0xf
+        lwi     $r15, [$r0 + UCONTEXT_PC]
+        push    $r1
+	cfi_adjust_cfa_offset (4)
+        move    $r1, $r0
+        lwi     $r0, [$r1 + UCONTEXT_GREGS]
+        pop     $r1
+	cfi_adjust_cfa_offset (-4)
+        jr      $r15
+1:
+	move $r0, -1
+	ret
+END(__setcontext)
+
+weak_alias (__setcontext, setcontext)
+libc_hidden_def(__setcontext)
+
+ENTRY (__startcontext)
+        move $r0, $r6
+	beqz $r0, 1f
+	jal HIDDEN_JUMPTARGET(__setcontext)
+1:	
+	move $r0, 0
+	j HIDDEN_JUMPTARGET(exit)
+END (__startcontext)
+

+ 1 - 1
libc/sysdeps/linux/nds32/setjmp.S

@@ -106,4 +106,4 @@ ENTRY(__sigsetjmp)
 #endif
 
 END(__sigsetjmp)
-hidden_def(__sigsetjmp)
+libc_hidden_def(__sigsetjmp)

+ 0 - 40
libc/sysdeps/linux/nds32/sigaction.c

@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2016 Andes Technology, Inc.
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-
-#include <errno.h>
-#include <signal.h>
-#include <sys/syscall.h>
-#include <string.h>
-#include <bits/kernel_sigaction.h>
-
-#define SA_RESTORER	0x04000000
-
-extern void __default_sa_restorer(void);
-
-int __libc_sigaction(int sig, const struct sigaction *act,
-					  struct sigaction *oact)
-{
-	struct sigaction kact;
-
-	if (act && !(act->sa_flags & SA_RESTORER)) {
-		memcpy(&kact, act, sizeof(kact));
-		kact.sa_restorer = __default_sa_restorer;
-		kact.sa_flags |= SA_RESTORER;
-		act = &kact;
-	}
-	/* NB: kernel (as of 2.6.25) will return EINVAL
-	 * if sizeof(act->sa_mask) does not match kernel's sizeof(sigset_t) */
-	return __syscall_rt_sigaction(sig, act, oact, sizeof(act->sa_mask));
-}
-
-#ifndef LIBC_SIGACTION
-# ifndef __UCLIBC_HAS_THREADS__
-strong_alias(__libc_sigaction,sigaction)
-libc_hidden_def(sigaction)
-# else
-weak_alias(__libc_sigaction,sigaction)
-libc_hidden_weak(sigaction)
-# endif
-#endif

+ 0 - 42
libc/sysdeps/linux/nds32/sigrestorer.S

@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2016 Andes Technology, Inc.
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-
-/* Copyright (C) 1999 Free Software Foundation, Inc.
-
-   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, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* If no SA_RESTORER function was specified by the application we use
-   one of these.  This avoids the need for the kernel to synthesise a return
-   instruction on the stack, which would involve expensive cache flushes. */
-
-ENTRY(__default_sa_restorer)
-	/* DO NOT SAVE r7 INTO STACK, THIS SYSCALL NEVER RETURN */
-	syscall	SYS_ify(sigreturn)
-END(__default_sa_restorer)
-
-#ifdef __NR_rt_sigreturn
-
-ENTRY(__default_rt_sa_restorer)
-	/* DO NOT SAVE r7 INTO STACK, THIS SYSCALL NEVER RETURN */
-	syscall	SYS_ify(rt_sigreturn)
-END(__default_rt_sa_restorer)
-
-#endif

+ 38 - 0
libc/sysdeps/linux/nds32/swapcontext.c

@@ -0,0 +1,38 @@
+/* Copyright (C) 2001-2013 Free Software Foundation, Inc.
+     Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
+
+   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 <ucontext.h>
+
+struct rv
+  {
+    long retval;
+    long first_return;
+  };
+
+extern struct rv __getcontext (ucontext_t *__ucp);
+extern int __setcontext (const ucontext_t *__ucp);
+
+int
+__swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
+{
+  struct rv rv = __getcontext (oucp);
+  if (rv.first_return)
+    __setcontext (ucp);
+  return 0;
+}
+
+weak_alias (__swapcontext, swapcontext)

+ 26 - 91
libc/sysdeps/linux/nds32/sys/ucontext.h

@@ -1,7 +1,20 @@
-/*
- * Copyright (C) 2016 Andes Technology, Inc.
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
+/* Copyright (C) 1998, 1999, 2001, 2006 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_UCONTEXT_H
 #define _SYS_UCONTEXT_H	1
@@ -10,103 +23,25 @@
 #include <signal.h>
 #include <sys/procfs.h>
 
-typedef int greg_t;
-
-/* Number of general registers.  */
-#define NGREG	32
-
-/* Container for all general registers.  */
-typedef elf_gregset_t gregset_t;
+/* We need the signal context definitions even if they are not used
+ *    included in <signal.h>.  */
+#include <bits/sigcontext.h>
 
-/* Number of each register is the `gregset_t' array.  */
-enum
-{
-  R0 = 0,
-#define R0	R0
-  R1 = 1,
-#define R1	R1
-  R2 = 2,
-#define R2	R2
-  R3 = 3,
-#define R3	R3
-  R4 = 4,
-#define R4	R4
-  R5 = 5,
-#define R5	R5
-  R6 = 6,
-#define R6	R6
-  R7 = 7,
-#define R7	R7
-  R8 = 8,
-#define R8	R8
-  R9 = 9,
-#define R9	R9
-  R10 = 10,
-#define R10	R10
-  R11 = 11,
-#define R11	R11
-  R12 = 12,
-#define R12	R12
-  R13 = 13,
-#define R13	R13
-  R14 = 14,
-#define R14	R14
-  R15 = 15,
-#define R15	R15
-  R16 = 16,
-#define R16     R16
-  R17 = 17,
-#define R17     R17
-  R18 = 18,
-#define R18     R18
-  R19 = 19,
-#define R19     R19
-  R20 = 20,
-#define R20     R20
-  R21 = 21,
-#define R21     R21
-  R22 = 22,
-#define R22     R22
-  R23 = 23,
-#define R23     R23
-  R24 = 24,
-#define R24     R24
-  R25 = 25,
-#define R25     R25
-  R26 = 26,
-#define R26     R26
-  R27 = 27,
-#define R27     R27
-  R28 = 28,
-#define R28     R28
-  R29 = 29,
-#define R29     R29
-  R30 = 30,
-#define R30     R30
-  R31 = 31
-#define R31     R31
 
-};
+/* Context to describe whole processor state.  This only describes
+   the core registers; coprocessor registers get saved elsewhere
+   (e.g. in uc_regspace, or somewhere unspecified on the stack
+   during non-RT signal handlers).  */
+typedef struct sigcontext mcontext_t;
 
-/* Structure to describe FPU registers.  */
-typedef elf_fpregset_t	fpregset_t;
-
-/* Context to describe whole processor state.  */
-typedef struct
-  {
-    gregset_t gregs;
-    fpregset_t fpregs;
-  } mcontext_t;
 
 /* Userlevel context.  */
 typedef struct ucontext
   {
     unsigned long int uc_flags;
     struct ucontext *uc_link;
-    __sigset_t uc_sigmask;
     stack_t uc_stack;
     mcontext_t uc_mcontext;
-    long int uc_filler[5];
+    __sigset_t uc_sigmask;
   } ucontext_t;
-
 #endif /* sys/ucontext.h */

+ 0 - 60
libc/sysdeps/linux/nds32/syscall.S

@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2016 Andes Technology, Inc.
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-
-#include <sys/syscall.h>
-#include <sysdep.h>
-
-	.text
-#ifdef PIC
-	.pic
-#endif
-	.align 2
-
-
-#ifdef PIC
-#ifdef __NDS32_N1213_43U1H__
-1:
-	ret
-99:
-	addi 	$r2, $lp, 0
-	jal 	1b
-	sethi 	$r1, hi20(_GLOBAL_OFFSET_TABLE_)
-	ori 	$r1, $r1, lo12(_GLOBAL_OFFSET_TABLE_+4)
-	add 	$r1, $lp, $r1
-	addi 	$lp, $r2, 0
-#else		/* !__NDS32_N1213_43U1H__ */
-99:
-	mfusr 	$r15, $PC
-	sethi 	$r1, hi20(_GLOBAL_OFFSET_TABLE_ + 4)
-	ori 	$r1, $r1, lo12(_GLOBAL_OFFSET_TABLE_ + 8)
-	add 	$r1, $r15, $r1
-#endif		/* end of __NDS32_N1213_43U1H__ */
-	sethi 	$r15, hi20(__syscall_error@PLT)
-	ori 	$r15, $r15, lo12(__syscall_error@PLT)
-	add 	$r15, $r15, $r1
-	jr 		$r15
-#else		/* !PIC	*/
-99:
-	j __syscall_error
-#endif		/* end of PIC */
-
-#ifdef PIC	
-	.pic 
-#endif
-
-	.align 2
-	.globl syscall
-	.func syscall
-	.type syscall, @function
-
-syscall:
-	syscall __NR_syscall
-	bgez $r0, 2f
-	sltsi $r1, $r0, -4096; 
-	beqz $r1, 99b; 
-2:
-	ret
-	.endfunc 
-	.size syscall, .-syscall

+ 28 - 0
libc/sysdeps/linux/nds32/syscall.c

@@ -0,0 +1,28 @@
+/*
+ *  Copyright (C) 2017 Andes Technology, Inc.
+ *  Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <sys/syscall.h>
+#include <sysdep.h>
+#include <unistd.h>
+long int syscall (long int __sysno, ...)
+{
+
+	int result;
+	unsigned long arg1,arg2,arg3,arg4,arg5,arg6;
+	va_list arg;
+	va_start (arg, __sysno);
+	arg1 = va_arg (arg, unsigned long);
+	arg2 = va_arg (arg, unsigned long);
+	arg3 = va_arg (arg, unsigned long);
+	arg4 = va_arg (arg, unsigned long);
+	arg5 = va_arg (arg, unsigned long);
+	arg6 = va_arg (arg, unsigned long);
+	va_end (arg);
+        __asm__ volatile ( "" ::: "memory" );
+	result = INLINE_SYSCALL(syscall,7,__sysno,arg1,arg2,arg3,arg4,arg5,arg6);
+	return result;
+}

+ 19 - 20
libc/sysdeps/linux/nds32/sysdep.S

@@ -26,15 +26,10 @@
 
 .text
 
-.globl C_SYMBOL_NAME(errno)
 .globl __syscall_error
 
 ENTRY (__syscall_error)
-#ifdef OLD_ABI
-	subri $r5, $r5, #0
-#else
 	subri $r0, $r0, #0
-#endif
 
 #define __syscall_error __syscall_error_1
 
@@ -48,56 +43,57 @@ syscall_error:
 #ifdef PIC
 	/* set GP register */
 	pushm	$gp, $lp
-#ifdef __NDS32_N1213_43U1H__
-	jal	2f
-	sethi	$gp,	hi20(_GLOBAL_OFFSET_TABLE_)
-	ori	$gp,	$gp,	lo12(_GLOBAL_OFFSET_TABLE_+4)
-	add	$gp,	$gp,	$lp
-#else
+        cfi_adjust_cfa_offset(8)
+        cfi_rel_offset(gp, 0)
+        cfi_rel_offset(lp, 4)
 	mfusr	$r15, $PC
 	sethi	$gp,	hi20(_GLOBAL_OFFSET_TABLE_+4)
 	ori	$gp,	$gp,	lo12(_GLOBAL_OFFSET_TABLE_+8)
 	add	$gp,	$gp,	$r15
 #endif
-#endif
 
 #if defined (EWOULDBLOCK_sys) && EWOULDBLOCK_sys != EAGAIN
 	/* We translate the system's EWOULDBLOCK error into EAGAIN.
 	   The GNU C library always defines EWOULDBLOCK==EAGAIN.
 	   EWOULDBLOCK_sys is the original number.  */
 	   push	$t0
+           cfi_adjust_cfa_offset(4)
 	   li	$t0, EWOULDBLOCK_sys
 	   bne	$r0, $t0, 1f
 	   pop	$t0
+	   cfi_adjust_cfa_offset(-4)
 	   li	$r0, EAGAIN
 1:
 #endif
 
 #ifdef _LIBC_REENTRANT
 	push	$lp
+        cfi_adjust_cfa_offset(4)
+        cfi_rel_offset(lp, 0)
 	push	$r0
-#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
-#else
-	addi	$sp,	$sp, -24
-#endif
+        cfi_adjust_cfa_offset(4)
+        cfi_rel_offset(r0, 0)
 
 #ifdef PIC
 	bal	C_SYMBOL_NAME(__errno_location@PLT)
 #else
 	bal	C_SYMBOL_NAME(__errno_location)
-#endif
-#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
-#else
-	addi	$sp,	$sp, 24
 #endif
 	pop	$r1
+        cfi_adjust_cfa_offset(-4)
+        cfi_restore(r1)
 
 	swi	$r1, [$r0]
 	li	$r0, -1
 	pop	$lp
+        cfi_adjust_cfa_offset(-4)
+        cfi_restore(lp)
 #ifdef PIC
 	/* restore GP register */
 	popm	$gp, $lp
+        cfi_adjust_cfa_offset(-8)
+        cfi_restore(lp)
+        cfi_restore(gp)
 #endif
 2:
 	ret
@@ -115,6 +111,9 @@ syscall_error:
 	
 	/* restore GP register */
 	popm	$gp, $lp
+        cfi_adjust_cfa_offset(-8)
+        cfi_restore(lp)
+        cfi_restore(gp)
 2:
 	ret
 

+ 107 - 214
libc/sysdeps/linux/nds32/sysdep.h

@@ -1,148 +1,96 @@
-//#include <sysdeps/generic/sysdep.h>
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#ifndef _LINUX_NDS32_SYSDEP_H
+#define _LINUX_NDS32_SYSDEP_H 1
+
+#include <common/sysdep.h>
+
 #ifdef	__ASSEMBLER__
 /* Define an entry point visible from C.  */
-#ifdef PIC
-#define ENTRY(name)                      \
+# ifdef PIC
+# define ENTRY(name)                      \
   .pic										\
   .align 2;                              \
   .globl C_SYMBOL_NAME(name);            \
   .func  C_SYMBOL_NAME(name);            \
   .type  C_SYMBOL_NAME(name), @function; \
-C_SYMBOL_NAME(name):
-#else
-#define ENTRY(name)                      \
+C_SYMBOL_NAME(name):			\
+	        cfi_startproc;
+
+# else
+# define ENTRY(name)                      \
   .align 2;                              \
   .globl C_SYMBOL_NAME(name);            \
   .func  C_SYMBOL_NAME(name);            \
   .type  C_SYMBOL_NAME(name), @function; \
-C_SYMBOL_NAME(name):
-#endif
+C_SYMBOL_NAME(name):			\
+	        cfi_startproc;
+# endif
 
 #undef END
 #define END(name) \
+  cfi_endproc;        \
   .endfunc;           \
   .size C_SYMBOL_NAME(name), .-C_SYMBOL_NAME(name)
 
 /* If compiled for profiling, call `mcount' at the start of each function.  */
-#ifdef HAVE_ELF
+# ifdef HAVE_ELF
 	#undef NO_UNDERSCORES
 	#define NO_UNDERSCORES
-#endif
+# endif
 
-#ifdef NO_UNDERSCORES
+# ifdef NO_UNDERSCORES
 	#define syscall_error __syscall_error
-#endif
+# endif
 
 #define SYS_ify(syscall_name)  (__NR_##syscall_name)
 
 #define __do_syscall(syscall_name)		\
   syscall	SYS_ify(syscall_name);
 
-#define SYSCALL_ERROR_HANDLER
-#define SYSCALL_ERROR __syscall_error
-
-
-#ifdef PIC
-#ifdef __NDS32_N1213_43U1H__
-#ifdef NDS_ABI_V0
-#define PSEUDO(name, syscall_name, args)	\
-  .pic;										\
-  .align 2;					\
-  1:	ret;	\
-  99:	addi	$r0,	$lp,	0;	\
-	jal	1b;	\
-	sethi	$r1,	hi20(_GLOBAL_OFFSET_TABLE_);	\
-	ori	$r1,	$r1,	lo12(_GLOBAL_OFFSET_TABLE_+4);	\
-	add	$r1,	$lp,	$r1;	\
-	addi	$lp,	$r0,	0;	\
-	sethi $r15, hi20(SYSCALL_ERROR@PLT);	\
-	ori	$r15,	$r15, lo12(SYSCALL_ERROR@PLT);	\
-	add	$r15, $r15, $r1;	\
-	jr		$r15;	\
-	nop;                                   	\
-	ENTRY(name);                          	\
-	__do_syscall(syscall_name);            	\
-	bgez $r5, 2f;				\
-	sltsi	$r0, $r5, -4096;		\
-	beqz	$r0, 99b;			\
-  2:
-#else
-#define PSEUDO(name, syscall_name, args)	\
-  .pic;										\
-  .align 2;					\
-  1:	ret;	\
-  99:	addi	$r2,	$lp,	0;	\
-	jal	1b;	\
-	sethi	$r1,	hi20(_GLOBAL_OFFSET_TABLE_);	\
-	ori	$r1,	$r1,	lo12(_GLOBAL_OFFSET_TABLE_+4);	\
-	add	$r1,	$lp,	$r1;	\
-	addi	$lp,	$r2,	0;	\
-	sethi $r15, hi20(SYSCALL_ERROR@PLT);	\
-	ori	$r15,	$r15, lo12(SYSCALL_ERROR@PLT);	\
-	add	$r15, $r15, $r1;	\
-	jr		$r15;	\
-	nop;                                   	\
-	ENTRY(name);                          	\
-	__do_syscall(syscall_name);            	\
-	bgez $r0, 2f;				\
-	sltsi	$r1, $r0, -4096;		\
-	beqz	$r1, 99b;			\
-  2:
-#endif
-#else
-#define PSEUDO(name, syscall_name, args)	\
-  .pic;										\
-  .align 2;					\
-  99:	mfusr $r15, $PC;	\
-	sethi	$r1,	hi20(_GLOBAL_OFFSET_TABLE_ + 4);	\
+# ifdef PIC
+# define PSEUDO(name, syscall_name, args)				\
+  .pic;									\
+  .align 2;								\
+  99:	mfusr $r15, $PC;						\
+	sethi	$r1,	hi20(_GLOBAL_OFFSET_TABLE_ + 4);		\
 	ori	$r1,	$r1,	lo12(_GLOBAL_OFFSET_TABLE_ + 8);	\
-	add	$r1,	$r15,	$r1;	\
-	sethi $r15, hi20(SYSCALL_ERROR@PLT);	\
-	ori	$r15,	$r15, lo12(SYSCALL_ERROR@PLT);	\
-	add	$r15, $r15, $r1;	\
-	jr		$r15;	\
-	nop;                                   	\
-	ENTRY(name);                          	\
-	__do_syscall(syscall_name);            	\
-	bgez $r0, 2f;				\
-	sltsi	$r1, $r0, -4096;		\
-	beqz	$r1, 99b;			\
+	add	$r1,	$r15,	$r1;					\
+	sethi $r15, hi20(SYSCALL_ERROR@PLT);				\
+	ori	$r15,	$r15, 	lo12(SYSCALL_ERROR@PLT);		\
+	add	$r15,	$r15, 	$r1;					\
+	jr	$r15;							\
+	nop;                                   				\
+	ENTRY(name);                          				\
+	__do_syscall(syscall_name);            				\
+	bgez $r0, 2f;							\
+	sltsi	$r1, 	$r0, 	-4096;					\
+	beqz	$r1, 	99b;						\
   2:
-#endif
-#else
-#ifdef OLD2_ABI
-#define PSEUDO(name, syscall_name, args)	\
-  .align 2;					\
-  99:	j SYSCALL_ERROR;                  	\
-	nop;                                   	\
-	ENTRY(name);                          	\
-	__do_syscall(syscall_name);            	\
-        bgez $r5, 2f;                           \
-        sltsi   $r0, $r5, -4096;                \
-        beqz    $r0, 99b;                       \
+# else
+# define PSEUDO(name, syscall_name, args)				\
+  .align 2;								\
+  99:	j SYSCALL_ERROR;                  				\
+	nop;                                   				\
+	ENTRY(name);                          				\
+	__do_syscall(syscall_name);            				\
+        bgez $r0, 2f;                           			\
+        sltsi   $r1, $r0, -4096;                			\
+        beqz    $r1, 99b;                       			\
   2:
-#else
-#define PSEUDO(name, syscall_name, args)	\
-  .align 2;					\
-  99:	j SYSCALL_ERROR;                  	\
-	nop;                                   	\
-	ENTRY(name);                          	\
-	__do_syscall(syscall_name);            	\
-        bgez $r0, 2f;                           \
-        sltsi   $r1, $r0, -4096;                \
-        beqz    $r1, 99b;                       \
-  2:
-#endif
-#endif
+# endif
 
 
-#define PSEUDO_NOERRNO(name, syscall_name, args) \
-  ENTRY(name);                                   \
+#define PSEUDO_NOERRNO(name, syscall_name, args) 			\
+  ENTRY(name);                                   			\
   __do_syscall(syscall_name);
 
 #undef PSEUDO_END
-#define PSEUDO_END(sym)				\
-	SYSCALL_ERROR_HANDLER			\
+#define PSEUDO_END(sym)							\
+	SYSCALL_ERROR_HANDLER						\
 	END(sym)
 
 #undef PSEUDO_END_ERRVAL
@@ -152,120 +100,65 @@ C_SYMBOL_NAME(name):
 
 #define ret_ERRVAL ret
 
-#define ret_NOERRNO ret	
+#define ret_NOERRNO ret
 #if defined NOT_IN_libc
 	#define SYSCALL_ERROR __local_syscall_error
 	#ifdef PIC
-		#ifdef __NDS32_N1213_43U1H__
-			#ifdef NDS_ABI_V0
-				#define SYSCALL_ERROR_HANDLER				\
-				__local_syscall_error:	pushm	$gp, $lp, $sp;				\
-					jal	1f;	\
-					sethi	$gp,	hi20(_GLOBAL_OFFSET_TABLE_);	\
-					ori	$gp,	$gp,	lo12(_GLOBAL_OFFSET_TABLE_+4);	\
-					add	$gp,	$gp,	$lp;	\
-					neg	$r5, $r5;	\
-					push	$r5;				\
-					addi	$sp,	$sp, -28; \
-					bal	C_SYMBOL_NAME(__errno_location@PLT);	\
-					addi	$sp,	$sp, 28; \
-					pop	$r1;			\
-					swi	$r1, [$r5];				\
-					li		$r5, -1;				\
-					popm	$gp, $lp, $sp;				\
-				1:	ret;
-			#else
-				#define SYSCALL_ERROR_HANDLER				\
-					__local_syscall_error:	pushm	$gp, $lp, $sp;				\
-						jal	1f;	\
-						sethi	$gp,	hi20(_GLOBAL_OFFSET_TABLE_);	\
-						ori	$gp,	$gp,	lo12(_GLOBAL_OFFSET_TABLE_+4);	\
-						add	$gp,	$gp,	$lp;	\
-						neg	$r0, $r0;	\
-						push	$r0;				\
-					#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP) \
-					        addi    $sp,    $sp, -4; \
-					#else \
-						addi	$sp,	$sp, -28; \
-					#endif \
-						bal	C_SYMBOL_NAME(__errno_location@PLT);	\
-					#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP) \
-					        addi    $sp,    $sp, 4; \
-					#else \
-						addi	$sp,	$sp, 28; \
-					#endif \
-						pop	$r1;			\
-						swi	$r1, [$r0];				\
-						li		$r0, -1;				\
-						popm	$gp, $lp, $sp;				\
-					1:	ret;
-			#endif
-		#else
-			#define SYSCALL_ERROR_HANDLER				\
-				__local_syscall_error:	pushm	$gp, $lp, $sp;				\
-					mfusr $r15, $PC;	\
-					sethi	$gp,	hi20(_GLOBAL_OFFSET_TABLE_+4);	\
-					ori	$gp,	$gp,	lo12(_GLOBAL_OFFSET_TABLE_+8);	\
-					add	$gp,	$gp,	$r15;	\
-					neg	$r0, $r0;	\
-					push	$r0;				\
-					#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP) \
-					        addi    $sp,    $sp, -4; \
-					#else \
-						addi	$sp,	$sp, -28; \
-					#endif \
-					bal	C_SYMBOL_NAME(__errno_location@PLT);	\
-					#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP) \
-					        addi    $sp,    $sp, 4; \
-					#else \
-						addi	$sp,	$sp, 28; \
-					#endif \
-					pop	$r1;			\
-					swi	$r1, [$r0];				\
-					li		$r0, -1;				\
-					popm	$gp, $lp, $sp;				\
-				1:	ret;
-		#endif
+		#define SYSCALL_ERROR_HANDLER						\
+			__local_syscall_error:						\
+				pushm	$gp, 	$lp;					\
+			        cfi_adjust_cfa_offset(8)				\
+			        cfi_rel_offset(gp, 0)					\
+			        cfi_rel_offset(lp, 4)					\
+				mfusr 	$r15, 	$PC;					\
+				sethi	$gp,	hi20(_GLOBAL_OFFSET_TABLE_+4);		\
+				ori	$gp,	$gp,	lo12(_GLOBAL_OFFSET_TABLE_+8);	\
+				add	$gp,	$gp,	$r15;				\
+				neg	$r0, 	$r0;					\
+				push	$r0;						\
+			        cfi_adjust_cfa_offset(4)				\
+			        cfi_rel_offset(r0, 0)					\
+				addi    $sp,    $sp, 	-4; 			\
+				bal	C_SYMBOL_NAME(__errno_location@PLT);		\
+				addi    $sp,    $sp, 	4; 			\
+				pop	$r1;						\
+			        cfi_adjust_cfa_offset(-4);                      	\
+			        cfi_restore(r1);                                	\
+				swi	$r1,	[$r0];					\
+				li	$r0,	-1;					\
+				popm	$gp,	$lp;					\
+			        cfi_adjust_cfa_offset(-8);                      	\
+			        cfi_restore(lp);                                	\
+			        cfi_restore(gp);  					\
+			1:	ret;
 	#else
-		#ifdef NDS_ABI_V0
-			#define SYSCALL_ERROR_HANDLER	\
-			__local_syscall_error:	push	$lp;				\
-				neg	$r5, $r5;	\
-				push	$r5;				\
-				addi	$sp,	$sp, -28; \
-				bal	C_SYMBOL_NAME(__errno_location);	\
-				addi	$sp,	$sp, 28; \
-				pop	$r1;			\
-				swi	$r1, [$r5];				\
-				li		$r5, -1;				\
-				pop	$lp;				\
+		#define SYSCALL_ERROR_HANDLER						\
+			__local_syscall_error:						\
+				push	$lp;						\
+			        cfi_adjust_cfa_offset(4)				\
+			        cfi_rel_offset(lp, 0)					\
+				neg	$r0,	$r0;					\
+				push	$r0;						\
+			        cfi_adjust_cfa_offset(4)				\
+			        cfi_rel_offset(r0, 0)					\
+				addi    $sp,    $sp, 	-4; 			\
+				bal	C_SYMBOL_NAME(__errno_location);		\
+				addi    $sp,    $sp, 	4; 			\
+				pop	$r1;						\
+			        cfi_adjust_cfa_offset(-4);                      	\
+			        cfi_restore(r1);                                	\
+				swi	$r1,	[$r0];					\
+				li	$r0,	-1;					\
+				pop	$lp;						\
+			        cfi_adjust_cfa_offset(-4);                      	\
+			        cfi_restore(lp);                                	\
 				ret;
-		#else
-			#define SYSCALL_ERROR_HANDLER	\
-			__local_syscall_error:	push	$lp;				\
-				neg	$r0, $r0;	\
-				push	$r0;				\
-				#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP) \
-				        addi    $sp,    $sp, -4; \
-				#else \
-					addi	$sp,	$sp, -28; \
-				#endif \
-				bal	C_SYMBOL_NAME(__errno_location);	\
-				#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP) \
-				        addi    $sp,    $sp, 4; \
-				#else \
-					addi	$sp,	$sp, 28; \
-				#endif \
-				pop	$r1;			\
-				swi	$r1, [$r0];				\
-				li		$r0, -1;				\
-				pop	$lp;				\
-				ret;
-		#endif
 	#endif
 
 #else
 	#define SYSCALL_ERROR_HANDLER
 	#define SYSCALL_ERROR __syscall_error
 #endif
+
 #endif	/* __ASSEMBLER__ */
+#endif //_LINUX_NDS32_SYSDEP_H

+ 27 - 0
libc/sysdeps/linux/nds32/ucontext_i.sym

@@ -0,0 +1,27 @@
+#include <stddef.h>
+#include <signal.h>
+#include <sys/ucontext.h>
+
+--
+
+SIG_BLOCK
+SIG_SETMASK
+_NSIG8          (_NSIG / 8)
+
+#define ucontext(member)	offsetof (ucontext_t, member)
+#define mcontext(member)	ucontext (uc_mcontext.member)
+#define mreg(reg)		mcontext (nds32_##reg)
+
+
+UCONTEXT_GREGS                  mcontext (nds32_r0)
+#ifdef __NDS32_ABI_2FP_PLUS__
+UCONTEXT_FDREGS                 mcontext (fpu.fd_regs)
+#endif
+UCONTEXT_PC                     mcontext (nds32_ipc)
+
+
+UCONTEXT_FLAGS                  ucontext (uc_flags)
+UCONTEXT_LINK                   ucontext (uc_link)
+UCONTEXT_STACK                  ucontext (uc_stack)
+UCONTEXT_MCONTEXT               ucontext (uc_mcontext)
+UCONTEXT_SIGMASK                ucontext (uc_sigmask)

+ 85 - 29
libc/sysdeps/linux/nds32/vfork.S

@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Andes Technology, Inc.
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  */
 
@@ -21,24 +21,36 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <sys/syscall.h>
 #include <sysdep.h>
-
 #define _ERRNO_H    1
+#include <bits/errno.h>
+
+#ifndef SAVE_PID
+#define SAVE_PID
+#endif
 
+#ifndef RESTORE_PID
+#define RESTORE_PID
+#endif
 /* Clone the calling process, but without copying the whole address space.
    The calling process is suspended until the new process exits or is
    replaced by a call to `execve'.  Return -1 for errors, 0 to the new process,
    and the process ID of the new process to the old process.  */
 
+
 ENTRY (__vfork)
 #ifdef PIC
 .pic
 #endif
 
 #ifdef __NR_vfork
-
+# ifdef SAVE_PID
+    SAVE_PID
+# endif
     syscall __NR_vfork
+# ifdef RESTORE_PID
+    RESTORE_PID
+# endif
     bltz $r0, 2f
 1:
     ret
@@ -46,42 +58,86 @@ ENTRY (__vfork)
     sltsi $r1, $r0, -4096
     bnez $r1, 1b;
 
+# ifdef __ASSUME_VFORK_SYSCALL
 #  ifdef PIC
-	#ifdef __NDS32_N1213_43U1H__
-		! save lp
-		addi	$r2,	$lp,	0
-
-		! set r1 as gp
-		jal	1b
-		sethi	$r1,	hi20(_GLOBAL_OFFSET_TABLE_)
-		ori	$r1,	$r1,	lo12(_GLOBAL_OFFSET_TABLE_+4)
-		add	$r1,	$lp,	$r1
-
-		! restore lp
-		addi	$lp,	$r2,	0
-	#else
-		! set r1 as gp
-		mfusr $r15, $PC
-		sethi	$r1,	hi20(_GLOBAL_OFFSET_TABLE_+4)
-		ori	$r1,	$r1,	lo12(_GLOBAL_OFFSET_TABLE_+8)
-		add	$r1,	$r1,	$r15
-	#endif
+	pushm	$gp,	$lp
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(gp, 0)
+	cfi_rel_offset(lp, 4)
+	mfusr 	$r15, 	$PC
+	sethi	$gp,	hi20(_GLOBAL_OFFSET_TABLE_+4)
+	ori	$gp,	$gp,	lo12(_GLOBAL_OFFSET_TABLE_+8)
+	add	$gp,	$gp,	$r15
 
 	! r15=C_SYMBOL_NAME(__syscall_error)@PLT
-	sethi $r15, hi20(C_SYMBOL_NAME(__syscall_error)@PLT)
+	sethi	$r15, 	hi20(C_SYMBOL_NAME(__syscall_error)@PLT)
 	ori	$r15,	$r15, lo12(C_SYMBOL_NAME(__syscall_error)@PLT)
-	add	$r15, $r15, $r1
+	add	$r15, 	$r15, 	$gp
 
 	! jump to SYSCALL_ERROR
-	jr		$r15
+	jral		$r15
+	popm	$gp,	$lp
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(lp)
+	cfi_restore(gp)
+	ret
 #  else
 	j C_SYMBOL_NAME(__syscall_error)
 #  endif
+# else
+    /* Check if vfork syscall is known at all. */
+	li $r1, -ENOSYS
+	beq	$r0, $r1, 1f
+
+# ifdef PIC
+3:
+	pushm	$gp,	$lp
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(gp, 0)
+	cfi_rel_offset(lp, 4)
+	mfusr	$r15,   $PC
+	sethi   $gp,    hi20(_GLOBAL_OFFSET_TABLE_+4)
+	ori     $gp,    $gp,    lo12(_GLOBAL_OFFSET_TABLE_+8)
+	add     $gp,    $gp,    $r15
+
+	! r15=C_SYMBOL_NAME(__syscall_error)@PLT
+	sethi	$r15,	hi20(C_SYMBOL_NAME(__syscall_error)@PLT)
+	ori     $r15,	$r15, lo12(C_SYMBOL_NAME(__syscall_error)@PLT)
+	add     $r15,	$r15, 	$gp
+
+	! jump to SYSCALL_ERROR
+	jral		$r15
+	popm	$gp,	$lp
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(lp)
+	cfi_restore(gp)
+	ret
+# else
+        j C_SYMBOL_NAME(__syscall_error)
+# endif
+1:
+# endif
+#endif
+
+#ifndef __ASSUME_VFORK_SYSCALL
+    /* If we don't have vfork, fork is close enough. */
+	syscall __NR_fork
+	bgez $r0, 1f
+	sltsi $r1, $r0, -4096
+	bnez	$r1, 1f
+
+# ifdef PIC
+        b       3b
+# else
+        j C_SYMBOL_NAME(__syscall_error)
+# endif
+1:
+    ret
 
-#else
-# error "__NR_vfork not available"
+#elif !defined __NR_vfork
+# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined"
 #endif
 
 PSEUDO_END (__vfork)
 weak_alias (__vfork, vfork)
-libc_hidden_def(vfork)
+libc_hidden_def (vfork)

+ 16 - 0
libm/nds32/Makefile.arch

@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)

+ 34 - 0
libm/nds32/e_sqrt.c

@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+
+   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/>.  */
+
+#if defined(__NDS32_ABI_2FP_PLUS__) && defined(__NDS32_EXT_FPU_DP__)
+
+double __ieee754_sqrt (double x)
+{
+  double z;
+  __asm__ ("fsqrtd %0,%1" : "=f" (z) : "f" (x));
+  return z;
+}
+strong_alias(__ieee754_sqrt, sqrt)
+libm_hidden_def(sqrt)
+#else
+#include <libm/e_sqrt.c>
+#endif

+ 52 - 0
libm/nds32/fclrexcpt.c

@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Clear given exceptions in current floating-point environment.
+   Copyright (C) 1997-2013 Free Software Foundation, Inc.
+
+   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 <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+
+int
+feclearexcept (int excepts)
+{
+#ifdef  __NDS32_ABI_2FP_PLUS__
+      unsigned long int temp;
+
+      /* Mask out unsupported bits/exceptions.  */
+      excepts &= FE_ALL_EXCEPT;
+
+      /* Get the current floating point status. */
+      _FPU_GETCW (temp);
+
+      /* Clear the relevant bits.  */
+      temp &= ~excepts;
+
+      /* Put the new data in effect.  */
+      _FPU_SETCW (temp);
+
+      /* Success.  */
+      return 0;
+#else
+      /* Unsupported, so fail unless nothing needs to be done.  */
+      return (excepts != 0);
+#endif
+}

+ 49 - 0
libm/nds32/fedisblxcpt.c

@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Disable floating-point exceptions.
+   Copyright (C) 2001-2013 Free Software Foundation, Inc.
+   Contributed by Philip Blundell <philb@gnu.org>, 2001.
+
+   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 <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+fedisableexcept (int excepts)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	unsigned long int new_exc, old_exc;
+
+	_FPU_GETCW(new_exc);
+
+	old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT;
+
+	excepts &= FE_ALL_EXCEPT;
+
+	new_exc &= ~(excepts << ENABLE_SHIFT);
+	new_exc &= ~_FPU_RESERVED;
+	_FPU_SETCW (new_exc);
+
+	return old_exc;
+#else
+	/* Unsupported, so return -1 for failure.  */
+	return -1;
+#endif
+}

+ 50 - 0
libm/nds32/feenablxcpt.c

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Enable floating-point exceptions.
+   Copyright (C) 2001-2013 Free Software Foundation, Inc.
+   Contributed by Philip Blundell <philb@gnu.org>, 2001.
+
+   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 <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+feenableexcept (int excepts)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	unsigned long int new_exc, old_exc;
+
+	_FPU_GETCW(new_exc);
+
+	old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT;
+
+	excepts &= FE_ALL_EXCEPT;
+
+	new_exc |= (excepts << ENABLE_SHIFT);
+	new_exc &= ~_FPU_RESERVED;
+
+	_FPU_SETCW(new_exc);
+
+	return old_exc;
+#else
+  /* Unsupported, so return -1 for failure.  */
+  return -1;
+#endif
+}

+ 40 - 0
libm/nds32/fegetenv.c

@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Store current floating-point environment.
+   Copyright (C) 1997-2013 Free Software Foundation, Inc.
+
+   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 <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetenv (fenv_t *envp)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+      unsigned long int temp;
+      _FPU_GETCW (temp);
+      envp->__fpcsr = temp;
+
+      /* Success.  */
+      return 0;
+#else
+  /* Unsupported, so fail.  */
+  return 1;
+#endif
+}

+ 41 - 0
libm/nds32/fegetexcept.c

@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Get floating-point exceptions.
+   Copyright (C) 2001-2013 Free Software Foundation, Inc.
+   Contributed by Philip Blundell <philb@gnu.org>, 2001
+
+   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 <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+fegetexcept (void)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	unsigned long temp;
+
+	_FPU_GETCW (temp);
+
+	return (temp & ENABLE_MASK) >> ENABLE_SHIFT;
+#else
+	/* Unsupported. Return all exceptions disabled.  */
+	return 0;
+#endif
+}

+ 40 - 0
libm/nds32/fegetround.c

@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Return current rounding direction.
+   Copyright (C) 2004-2013 Free Software Foundation, Inc.
+
+   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 <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetround (void)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	unsigned int temp;
+
+	/* Get the current environment.  */
+	_FPU_GETCW (temp);
+
+	return temp & 0x3;
+#else
+	/* The current soft-float implementation only handles TONEAREST.  */
+	return FE_TONEAREST;
+#endif
+}

+ 51 - 0
libm/nds32/feholdexcpt.c

@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Store current floating-point environment and clear exceptions.
+   Copyright (C) 1997-2013 Free Software Foundation, Inc.
+
+   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 <fenv.h>
+#include <fpu_control.h>
+#include "fenv_libc.h"
+
+int
+feholdexcept (fenv_t *envp)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	unsigned long int temp;
+
+	/* Store the environment.  */
+	_FPU_GETCW(temp);
+	envp->__fpcsr = temp;
+
+	/* Now set all exceptions to non-stop.  */
+	temp &= ~(FE_ALL_EXCEPT << ENABLE_SHIFT);
+
+	/* And clear all exception flags.  */
+	temp &= ~FE_ALL_EXCEPT;
+
+	_FPU_SETCW(temp);
+
+	return 0;
+#else
+	/* Unsupported, so fail.  */
+	return 1;
+#endif
+}
+

+ 33 - 0
libm/nds32/fenv_libc.h

@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 2000-2013 Free Software Foundation, Inc.
+   Contributed by Alexandre Oliva <aoliva@redhat.com>
+   based on the corresponding file in the mips port.
+
+   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 _FENV_LIBC_H
+#define _FENV_LIBC_H
+
+/* Mask for enabling exceptions and for the CAUSE bits.  */
+#define ENABLE_MASK	0x00F80U
+
+/* Shift for FE_* flags to get up to the ENABLE bits.  */
+#define	ENABLE_SHIFT	5
+
+#endif /* _FENV_LIBC_H */

+ 51 - 0
libm/nds32/fesetenv.c

@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Install given floating-point environment.
+   Copyright (C) 2004-2013 Free Software Foundation, Inc.
+
+   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 <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetenv (const fenv_t *envp)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	unsigned int temp;
+
+	_FPU_GETCW (temp);
+	temp &= _FPU_RESERVED;
+
+	if (envp == FE_DFL_ENV)
+	  temp |= _FPU_DEFAULT;
+	else if (envp == FE_NOMASK_ENV)
+	  temp |= _FPU_IEEE;
+	else
+	  temp |= envp->__fpcsr & ~_FPU_RESERVED;
+
+	_FPU_SETCW (temp);
+
+	/* Success.  */
+	return 0;
+#else
+
+	/* Unsupported, so fail.  */
+	return 1;
+#endif
+}

+ 42 - 0
libm/nds32/fesetround.c

@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Set current rounding direction.
+   Copyright (C) 2004-2013 Free Software Foundation, Inc.
+
+   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 <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetround (int round)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	fpu_control_t temp;
+	if ((round & ~0x3) != 0)
+	  /* ROUND is no valid rounding mode.  */
+		return 1;
+
+	_FPU_GETCW (temp);
+	temp = (temp & ~0x3) | round;
+	_FPU_SETCW (temp);
+	return 0;
+#else
+	return (round != FE_TONEAREST);
+#endif
+}

+ 48 - 0
libm/nds32/feupdateenv.c

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Install given floating-point environment and raise exceptions.
+   Copyright (C) 1997-2013 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <fenv.h>
+#include <fpu_control.h>
+
+int
+feupdateenv (const fenv_t *envp)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	unsigned int temp;
+
+	/* Get the current exception state.  */
+	_FPU_GETCW (temp);
+
+	/* Install new environment.  */
+	fesetenv (envp);
+
+	/* Raise the saved exceptions.  */
+	feraiseexcept (temp & FE_ALL_EXCEPT);
+
+	/* Success.  */
+	return 0;
+#else
+	/* Unsupported, so fail.  */
+	return 1;
+#endif
+}

+ 44 - 0
libm/nds32/fgetexcptflg.c

@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Store current representation for exceptions.
+   Copyright (C) 1997-2013 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	fpu_control_t temp;
+
+	/* Get the current exceptions.  */
+	_FPU_GETCW (temp);
+
+	*flagp = temp & excepts & FE_ALL_EXCEPT;
+
+	/* Success.  */
+	return 0;
+#else
+	/* Unsupported, so fail.  */
+	return 1;
+#endif
+}

+ 104 - 0
libm/nds32/fraiseexcpt.c

@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Raise given exceptions.
+   Copyright (C) 2004-2013 Free Software Foundation, Inc.
+
+   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 <fpu_control.h>
+#include <fenv.h>
+#include <float.h>
+#include "fenv_libc.h"
+
+int
+feraiseexcept (int excepts)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	float temp1 = 0.0, temp2 = 1.0;
+	if (FE_INVALID & excepts)
+	{
+		__asm__ volatile(
+			"fmtsr\t %0, $fs0\n\t"
+			"fdivs\t $fs0, $fs0, $fs0\n\t"
+			:
+			:"r"(temp1)
+			:"$fs0"
+			);
+	}
+	if (FE_DIVBYZERO & excepts)
+	{
+		__asm__ volatile(
+			"fmtsr\t %0, $fs0\n\t"
+			"fmtsr\t %1, $fs1\n\t"
+			"fdivs\t $fs0, $fs1, $fs0\n\t"
+			:
+			:"r"(temp1),"r"(temp2)
+			:"$fs0"
+			);
+	}
+	if (FE_OVERFLOW & excepts)
+	{
+	/* There's no way to raise overflow without also raising inexact.
+	*/
+		unsigned int fpcsr;
+		temp1 = FLT_MAX;
+		__asm__ volatile(
+			"fmfcsr\t %0\n\t"
+			"fmtsr\t %1, $fs0\n\t"
+			"fadds\t $fs0, $fs0, $fs0\n\t"
+			"ori\t %0,%0,0x10\n\t"
+			"fmtcsr\t %0\n\t"
+			:"=&r"(fpcsr)
+			:"r"(temp1)
+			:"$fs0"
+			);
+	}
+	if (FE_UNDERFLOW & excepts)
+	{
+	/* There's no way to raise overflow without also raising inexact.
+	*/
+		temp1 = FLT_MIN;
+		temp2 = 2.0;
+		__asm__ volatile(
+			"fmtsr\t %0, $fs0\n\t"
+			"fmtsr\t %1, $fs1\n\t"
+			"fdivs\t $fs1, $fs0, $fs1\n\t"
+			:
+			:"r"(temp1),"r"(temp2)
+			:"$fs0","$fs1"
+			);
+	}
+	if (FE_INEXACT & excepts)
+	{
+		temp1 = 3.0;
+		__asm__ volatile(
+			"fmtsr\t %0, $fs1\n\t"
+			"fmtsr\t %1, $fs0\n\t"
+			"fdivs\t $fs1, $fs0, $fs1\n\t"
+			:
+			:"r"(temp1),"r"(temp2)
+			:"$fs0","$fs1"
+			);
+	}
+
+	return 0;
+
+#endif
+	/* Unsupported, so fail unless nothing needs to be done.  */
+	return (excepts != 0);
+}

+ 48 - 0
libm/nds32/fsetexcptflg.c

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Set floating-point environment exception handling.
+   Copyright (C) 1997-2013 Free Software Foundation, Inc.
+
+   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 <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	fexcept_t temp;
+
+	/* Get the current environment.  */
+	_FPU_GETCW (temp);
+
+	/* Set the desired exception mask.  */
+	temp &= ~(excepts & FE_ALL_EXCEPT);
+	temp |= (*flagp & excepts & FE_ALL_EXCEPT);
+
+	/* Save state back to the FPU.  */
+	_FPU_SETCW (temp);
+
+	/* Success.  */
+	return 0;
+#else
+	/* Unsupported, so fail unless nothing needs to be done.  */
+	return (excepts != 0);
+#endif
+}

+ 40 - 0
libm/nds32/ftestexcept.c

@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Test exception in current environment.
+   Copyright (C) 1997-2013 Free Software Foundation, Inc.
+
+   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 <fenv.h>
+#include <fpu_control.h>
+
+int
+fetestexcept (int excepts)
+{
+#ifdef __NDS32_ABI_2FP_PLUS__
+	fexcept_t temp;
+
+	/* Get current exceptions.  */
+	_FPU_GETCW(temp);
+
+	return temp & excepts & FE_ALL_EXCEPT;
+#else
+	/* Unsupported, return 0.  */
+	return 0;
+#endif
+}

+ 1 - 1
libpthread/linuxthreads/sysdeps/nds32/pspinlock.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Andes Technology, Inc.
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  */
 

+ 1 - 1
libpthread/linuxthreads/sysdeps/nds32/pt-machine.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Andes Technology, Inc.
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  */
 

+ 16 - 0
libpthread/nptl/sysdeps/nds32/Makefile.arch

@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng NPTL
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+ASFLAGS-dl-tlsdesc.S = -DNOT_IN_libc=1
+libc_arch_a_SSRC = libc-dl-tlsdesc.S
+
+CFLAGS-gen_tlsdesc.c = -S
+$(libpthread_arch_OUT)/gen_tlsdesc.c: $(libpthread_arch_DIR)/tlsdesc.sym | $(libpthread_arch_OUT)
+	$(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@
+$(libpthread_arch_OUT)/gen_tlsdesc.s: $(libpthread_arch_OUT)/gen_tlsdesc.c | headers
+	$(compile.c)
+libpthread-generated-y += $(libpthread_arch_OUT)/gen_tlsdesc.s
+$(libpthread_arch_OUT)/tlsdesc.h: $(libpthread_arch_OUT)/gen_tlsdesc.s
+	$(do_sed) $(PTHREAD_GENERATE_MANGLE) $< > $@
+	@if test ! -s $@ ; then rm -f $@ ; false ; fi
+pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(libpthread_arch_OUT)/tlsdesc.h

+ 59 - 0
libpthread/nptl/sysdeps/nds32/dl-tls.h

@@ -0,0 +1,59 @@
+/* Thread-local storage handling in the ELF dynamic linker.  NDS32 version.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+   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 _NDS32_DL_TLS_H
+#define _NDS32_DL_TLS_H 1
+
+
+/* Type used to represent a TLS descriptor.  */
+struct tlsdesc
+{
+  ptrdiff_t (*entry)(struct tlsdesc *);
+  union
+    {
+      void *pointer;
+      long value;
+    } argument;
+};
+
+/* 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;
+
+
+/* Type used as the argument in a TLS descriptor for a symbol that
+ *    needs dynamic TLS offsets.  */
+struct tlsdesc_dynamic_arg
+{
+  tls_index tlsinfo;
+  size_t gen_count;
+};
+
+
+extern void *__tls_get_addr (tls_index *ti);
+
+extern ptrdiff_t attribute_hidden
+  _dl_tlsdesc_return(struct tlsdesc_dynamic_arg *);
+
+extern void *_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset);
+extern ptrdiff_t attribute_hidden
+  _dl_tlsdesc_dynamic(struct tlsdesc *);
+
+#endif //_NDS32_DL_TLS_H

+ 1 - 0
libpthread/nptl/sysdeps/nds32/libc-dl-tlsdesc.S

@@ -0,0 +1 @@
+#include <ldso/ldso/nds32/dl-tlsdesc.S>

+ 65 - 0
libpthread/nptl/sysdeps/nds32/pthread_spin_lock.c

@@ -0,0 +1,65 @@
+/* pthread_spin_lock -- lock a spin lock.  Generic version.
+   Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+   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;
+}

+ 26 - 0
libpthread/nptl/sysdeps/nds32/pthread_spin_trylock.c

@@ -0,0 +1,26 @@
+/* pthread_spin_trylock -- trylock a spin lock.  Generic version.
+   Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+   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;
+}

+ 39 - 0
libpthread/nptl/sysdeps/nds32/pthreaddef.h

@@ -0,0 +1,39 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+   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.  SSE requires 16
+   bytes.  */
+#define STACK_ALIGN		16
+
+/* Minimal stack size after allocating thread descriptor and guard size.  */
+#define MINIMAL_REST_STACK	2048
+
+/* Alignment requirement for TCB.  */
+#define TCB_ALIGNMENT		16
+
+
+/* Location of current stack frame.  */
+#define CURRENT_STACK_FRAME	__builtin_frame_address (0)
+
+
+/* XXX Until we have a better place keep the definitions here.  */
+#define __exit_thread_inline(val) \
+  INLINE_SYSCALL (exit, 1, (val))
+
+

+ 12 - 0
libpthread/nptl/sysdeps/nds32/tcb-offsets.sym

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

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

@@ -0,0 +1,178 @@
+/* Definition for thread-local data handling.  NPTL/NDS32 version.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+
+   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
+
+/* We use the multiple_threads field in the pthread struct */
+#define TLS_MULTIPLE_THREADS_IN_TCB	1
+
+/* Get the thread descriptor definition.  */
+# include <../../descr.h>
+
+/* The stack_guard is accessed directly by GCC -fstack-protector code,
+   so it is a part of public ABI.  The dtv and pointer_guard fields
+   are private.  */
+typedef struct
+{
+  dtv_t *dtv;
+  void *private;
+} tcbhead_t;
+
+/* This is the size of the initial TCB.  */
+# 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.  */
+# 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)))
+
+/* Return the thread descriptor (tp) for the current thread.  */
+register void *__thread_pointer __asm__ ("$r25");
+
+
+/* The thread pointer (in hardware register tp) points to the end of
+   the TCB.  The pthread_descr structure is immediately in front of the TCB.  */
+#ifndef TLS_TCB_OFFSET
+# define TLS_TCB_OFFSET	0
+#endif
+
+/* 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 (tp).  */
+# define TLS_INIT_TP(tcbp, secondcall) \
+    (__thread_pointer = (char *)(tcbp) + TLS_TCB_OFFSET, NULL)
+
+/* Return the address of the dtv for the current thread.  */
+# define THREAD_DTV() \
+    (((tcbhead_t *) (__thread_pointer - TLS_TCB_OFFSET))[-1].dtv)
+
+/* Return the thread descriptor for the current thread.  */
+# define THREAD_SELF \
+    ((struct pthread *) (__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, 152, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
+
+/* Read member of the thread descriptor directly.  */
+# define THREAD_GETMEM(descr, member) (descr->member)
+
+/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
+# define THREAD_GETMEM_NC(descr, member, idx) \
+    (descr->member[idx])
+
+/* Set member of the thread descriptor directly.  */
+# define THREAD_SETMEM(descr, member, value) \
+    (descr->member = (value))
+
+/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
+# define THREAD_SETMEM_NC(descr, member, idx, value) \
+    (descr->member[idx] = (value))
+
+
+/* l_tls_offset == 0 is perfectly valid on Tile, 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 */
+
+

+ 17 - 0
libpthread/nptl/sysdeps/nds32/tlsdesc.sym

@@ -0,0 +1,17 @@
+#include <stddef.h>
+#include <sysdep.h>
+#include <tls.h>
+#include <link.h>
+#include <dl-tls.h>
+
+--
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+#define dtv_offsetof(dtv) (long)(offsetof(tcbhead_t, dtv) - sizeof (tcbhead_t))
+DTV_OFFSET                      dtv_offsetof(dtv)
+
+TLSDESC_ARG			offsetof(struct tlsdesc, argument.pointer)
+
+TLSDESC_GEN_COUNT		offsetof(struct tlsdesc_dynamic_arg, gen_count)
+TLSDESC_MODID			offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module)
+TLSDESC_MODOFF			offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset)

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

@@ -0,0 +1,9 @@
+# Makefile for uClibc-ng NPTL
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+top_srcdir=../../../../../../../
+top_builddir=../../../../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules

+ 12 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile.arch

@@ -0,0 +1,12 @@
+# Makefile for uClibc-ng NPTL
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+libpthread_linux_arch_SSRC =
+libpthread_linux_arch_CSRC = pthread_once.c
+
+libc_linux_arch_CSRC = fork.c
+libc_linux_arch_SSRC = clone.S vfork.S
+libc_linux_arch_SSRC-OMIT = waitpid.S
+
+CFLAGS += $(SSP_ALL_CFLAGS)
+

+ 177 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/pthreadtypes.h

@@ -0,0 +1,177 @@
+/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
+
+   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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _BITS_PTHREADTYPES_H
+#define _BITS_PTHREADTYPES_H	1
+
+#define __SIZEOF_PTHREAD_ATTR_T 36
+#define __SIZEOF_PTHREAD_MUTEX_T 24
+#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+#define __SIZEOF_PTHREAD_COND_T 48
+#define __SIZEOF_PTHREAD_COND_COMPAT_T 12
+#define __SIZEOF_PTHREAD_CONDATTR_T 4
+#define __SIZEOF_PTHREAD_RWLOCK_T 32
+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+#define __SIZEOF_PTHREAD_BARRIER_T 20
+#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+
+
+/* Thread identifiers.  The structure of the attribute type is not
+   exposed on purpose.  */
+typedef unsigned long int pthread_t;
+
+union pthread_attr_t
+{
+  char __size[__SIZEOF_PTHREAD_ATTR_T];
+  long int __align;
+};
+#ifndef __have_pthread_attr_t
+typedef union pthread_attr_t pthread_attr_t;
+# define __have_pthread_attr_t  1
+#endif
+
+
+typedef struct __pthread_internal_slist
+{
+  struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+
+
+/* Data structures for mutex handling.  The structure of the attribute
+   type is not exposed on purpose.  */
+typedef union
+{
+  struct __pthread_mutex_s
+  {
+    int __lock;
+    unsigned int __count;
+    int __owner;
+    /* KIND must stay at this position in the structure to maintain
+       binary compatibility.  */
+    int __kind;
+    unsigned int __nusers;
+    __extension__ union
+    {
+      int __spins;
+      __pthread_slist_t __list;
+    };
+  } __data;
+  char __size[__SIZEOF_PTHREAD_MUTEX_T];
+  long int __align;
+} pthread_mutex_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
+  long int __align;
+} pthread_mutexattr_t;
+
+
+/* Data structure for conditional variable handling.  The structure of
+   the attribute type is not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __futex;
+    __extension__ unsigned long long int __total_seq;
+    __extension__ unsigned long long int __wakeup_seq;
+    __extension__ unsigned long long int __woken_seq;
+    void *__mutex;
+    unsigned int __nwaiters;
+    unsigned int __broadcast_seq;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_COND_T];
+  __extension__ long long int __align;
+} pthread_cond_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_CONDATTR_T];
+  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 not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __nr_readers;
+    unsigned int __readers_wakeup;
+    unsigned int __writer_wakeup;
+    unsigned int __nr_readers_queued;
+    unsigned int __nr_writers_queued;
+    /* 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;
+    int __writer;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_RWLOCK_T];
+  long int __align;
+} pthread_rwlock_t;
+
+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
+/* Extra attributes for the cleanup functions.  */
+/*
+ FIXME, check this after gcc uprgrade.
+ #define __cleanup_fct_attribute __attribute__ ((__regparm__ (1)))
+ warning: '__regparm__' attribute directive ignored
+*/
+
+#endif	/* bits/pthreadtypes.h */

+ 38 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/semaphore.h

@@ -0,0 +1,38 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#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)
+
+/* Maximum value the semaphore can have.  */
+#define SEM_VALUE_MAX   (2147483647)
+
+
+typedef union
+{
+  char __size[__SIZEOF_SEM_T];
+  long int __align;
+} sem_t;

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

@@ -0,0 +1,4 @@
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+# define RESET_PID
+# include <libc/sysdeps/linux/nds32/clone.S>

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

@@ -0,0 +1,22 @@
+/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
+
+   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 ((void *) (pd) \
+		   + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
+
+/* Get the real implementation.	 */
+#include <sysdeps/pthread/createthread.c>

+ 27 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nds32/fork.c

@@ -0,0 +1,27 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   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, 0,     \
+                 NULL, NULL, &THREAD_SELF->tid)
+
+#include "../fork.c"

+ 323 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nds32/lowlevellock.h

@@ -0,0 +1,323 @@
+/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
+
+   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_WAIT_REQUEUE_PI   11
+#define FUTEX_CMP_REQUEUE_PI    12
+#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_timed_wait_bitset(futexp, val, timespec, clockbit, private) \
+  ({									\
+    INTERNAL_SYSCALL_DECL (__err);					\
+    long int __ret;							\
+    int __op = FUTEX_WAIT_BITSET | clockbit;				\
+    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		\
+			      __lll_private_flag (__op, private),	\
+			      (val), (timespec), NULL /* Unused.  */,	\
+			      FUTEX_BITSET_MATCH_ANY);			\
+    __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);				      \
+  })
+
+/* Priority Inheritance support.  */
+#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \
+  lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private)
+
+#define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit,      \
+					mutex, private)			      \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    int __op = FUTEX_WAIT_REQUEUE_PI | clockbit;			      \
+									      \
+    INTERNAL_SYSCALL (futex, __err, 5, (futexp),			      \
+		      __lll_private_flag (__op, private),		      \
+		      (val), (timespec), mutex); 			      \
+  })
+
+#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv)  \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+									      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		      \
+			      __lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv),\
+			      (nr_wake), (nr_move), (mutex), (val));	      \
+    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);			\
+       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);			\
+       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_CHILD_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 */

+ 18 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pt-raise.c

@@ -0,0 +1,18 @@
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   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 <nptl/sysdeps/unix/sysv/linux/raise.c>

+ 92 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pthread_once.c

@@ -0,0 +1,92 @@
+/* Copyright (C) 2003-2013 Free Software Foundation, Inc.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "pthreadP.h"
+#include <lowlevellock.h>
+
+
+unsigned long int __fork_generation attribute_hidden;
+
+
+static void
+clear_once_control (void *arg)
+{
+  pthread_once_t *once_control = (pthread_once_t *) arg;
+
+  *once_control = 0;
+  lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
+}
+
+
+int
+__pthread_once (once_control, init_routine)
+     pthread_once_t *once_control;
+     void (*init_routine) (void);
+{
+  while (1)
+    {
+      int oldval, val, newval;
+
+      val = *once_control;
+      do
+	{
+	  /* Check if the initialized has already been done.  */
+	  if ((val & 2) != 0)
+	    return 0;
+
+	  oldval = val;
+	  newval = (oldval & 3) | __fork_generation | 1;
+	  val = atomic_compare_and_exchange_val_acq (once_control, newval,
+						     oldval);
+	}
+      while (__builtin_expect (val != oldval, 0));
+
+      /* Check if another thread already runs the initializer.	*/
+      if ((oldval & 1) != 0)
+	{
+	  /* Check whether the initializer execution was interrupted
+	     by a fork.	 */
+	  if (((oldval ^ newval) & -4) == 0)
+	    {
+	      /* Same generation, some other thread was faster. Wait.  */
+	      lll_futex_wait (once_control, newval, LLL_PRIVATE);
+	      continue;
+	    }
+	}
+
+      /* 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);
+
+
+      /* Add one to *once_control.  */
+      atomic_increment (once_control);
+
+      /* Wake up all other threads.  */
+      lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
+      break;
+    }
+
+  return 0;
+}
+weak_alias (__pthread_once, pthread_once)
+strong_alias (__pthread_once, __pthread_once_internal)

+ 273 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h

@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 2003-2013 Free Software Foundation, Inc.
+
+   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
+
+
+
+#define PUSHARGS_0
+#define PUSHARGS_1	smw.adm $r0, [$sp], $r0, #0;	\
+			cfi_adjust_cfa_offset(4);	\
+			cfi_rel_offset(r0,0);		\
+			addi	$sp, $sp, -4;		\
+			cfi_adjust_cfa_offset(4);
+#define PUSHARGS_2	smw.adm $r0, [$sp], $r1, #0;	\
+			cfi_adjust_cfa_offset(8);	\
+			cfi_rel_offset(r1, 4);		\
+			cfi_rel_offset(r0, 0);
+#define PUSHARGS_3	smw.adm $r0, [$sp], $r2, #0;	\
+			cfi_adjust_cfa_offset(12);	\
+			cfi_rel_offset(r2, 8);		\
+			cfi_rel_offset(r1, 4);		\
+			cfi_rel_offset(r0, 0);		\
+			addi	$sp, $sp, -4;		\
+			cfi_adjust_cfa_offset(4);
+#define PUSHARGS_4	smw.adm $r0, [$sp], $r3, #0;	\
+			cfi_adjust_cfa_offset(16);	\
+			cfi_rel_offset(r3, 12);		\
+			cfi_rel_offset(r2, 8);		\
+			cfi_rel_offset(r1, 4);		\
+			cfi_rel_offset(r0, 0);
+#define PUSHARGS_5	smw.adm $r0, [$sp], $r4, #0;	\
+			cfi_adjust_cfa_offset(20);	\
+			cfi_rel_offset(r4, 16);		\
+			cfi_rel_offset(r3, 12);		\
+			cfi_rel_offset(r2, 8);		\
+			cfi_rel_offset(r1, 4);		\
+			cfi_rel_offset(r0, 0);		\
+			addi	$sp, $sp, -4;		\
+			cfi_adjust_cfa_offset(4);
+#define PUSHARGS_6	smw.adm $r0, [$sp], $r5, #0;	\
+			cfi_adjust_cfa_offset(24);	\
+			cfi_rel_offset(r5, 20);		\
+			cfi_rel_offset(r4, 16);		\
+			cfi_rel_offset(r3, 12);		\
+			cfi_rel_offset(r2, 8);		\
+			cfi_rel_offset(r1, 4);		\
+			cfi_rel_offset(r0, 0);
+
+#define POPARGS2_0
+#define POPARGS2_1	addi	$sp, $sp, 4;		\
+			cfi_adjust_cfa_offset(-4);	\
+			lmw.bim $r0, [$sp], $r0, #0;	\
+			cfi_adjust_cfa_offset(-4);	\
+			cfi_restore(r0);
+#define POPARGS2_2	lmw.bim $r0, [$sp], $r1, #0;	\
+			cfi_adjust_cfa_offset(-8);	\
+			cfi_restore(r0);		\
+			cfi_restore(r1);
+#define POPARGS2_3	addi	$sp, $sp, 4;		\
+			cfi_adjust_cfa_offset(-4);	\
+			lmw.bim $r0, [$sp], $r2, #0;	\
+			cfi_adjust_cfa_offset(-12);	\
+			cfi_restore(r0);		\
+			cfi_restore(r1);		\
+			cfi_restore(r2);
+#define POPARGS2_4	lmw.bim $r0, [$sp], $r3, #0;	\
+			cfi_adjust_cfa_offset(-16);	\
+			cfi_restore(r0);		\
+			cfi_restore(r1);		\
+			cfi_restore(r2);		\
+			cfi_restore(r3);
+#define POPARGS2_5	addi	$sp, $sp, 4;		\
+			cfi_adjust_cfa_offset(-4);	\
+			lmw.bim $r0, [$sp], $r4, #0;	\
+			cfi_adjust_cfa_offset(-20);	\
+			cfi_restore(r0);		\
+			cfi_restore(r1);		\
+			cfi_restore(r2);		\
+			cfi_restore(r3);		\
+			cfi_restore(r4);
+#define POPARGS2_6	lmw.bim $r0, [$sp], $r5, #0;	\
+			cfi_adjust_cfa_offset(-24);	\
+			cfi_restore(r0);		\
+			cfi_restore(r1);		\
+			cfi_restore(r2);		\
+			cfi_restore(r3);		\
+			cfi_restore(r4);		\
+			cfi_restore(r5);
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+/* NOTE: We do mark syscalls with unwind annotations, for the benefit of
+   cancellation; but they're really only accurate at the point of the
+   syscall.  The ARM unwind directives are not rich enough without adding
+   a custom personality function.  */
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				\
+  .align 2;                                                             \
+  ENTRY (__##syscall_name##_nocancel);					\
+  __do_syscall(syscall_name);                                           \
+  PSEUDO_RET;                                                           \
+  ret;							                \
+  END (__##syscall_name##_nocancel);					\
+  ENTRY (name);								\
+  smw.adm $r6,[$sp],$r6,0x2;                                            \
+  cfi_adjust_cfa_offset(8); 						\
+  cfi_offset(r6,-8);						\
+  cfi_offset(lp,-4);						\
+  SINGLE_THREAD_P ($r15);                                               \
+  bgtz $r15, .Lpseudo_cancel;                                           \
+  __do_syscall(syscall_name);                                           \
+  j 50f;                                                                \
+  .Lpseudo_cancel:							\
+	PUSHARGS_##args;	/* save syscall args etc. around CENABLE.  */	\
+	CENABLE ($r5);							\
+	mov55 $r6, $r0;		/* put mask in safe place.  */    	\
+	POPARGS2_##args;                                                \
+	__do_syscall(syscall_name);		/* do the call.  */	\
+	push $r0;                                                       \
+	cfi_adjust_cfa_offset(4);					\
+	cfi_rel_offset(r0, 0);						\
+	addi $sp, $sp, -4;						\
+	cfi_adjust_cfa_offset(4);					\
+        mov55	$r0, $r6;		/* save syscall return value. */\
+	CDISABLE($r5);							\
+	addi $sp, $sp, 4;						\
+	cfi_adjust_cfa_offset(-4);					\
+        pop $r0;                          /* retrieve return value.  */	\
+	cfi_adjust_cfa_offset(-4);					\
+	cfi_restore(r0);						\
+50:									\
+  lmw.bim $r6,[$sp],$r6, 0x2;                                           \
+  cfi_adjust_cfa_offset(-8); 						\
+  cfi_restore(lp);							\
+  cfi_restore(r6);							\
+  PSEUDO_RET;
+# ifndef __ASSEMBLER__
+//#  if defined IS_IN_libpthread || !defined NOT_IN_libc
+//extern int __local_multiple_threads attribute_hidden;
+//#  define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+//#  else
+/*  There is no __local_multiple_threads for librt */
+#  define SINGLE_THREAD_P __builtin_expect (THREAD_GETMEM (THREAD_SELF,       \
+				           header.multiple_threads) == 0, 1)
+//#  endif
+# else
+#   define SINGLE_THREAD_P(reg)            \
+    addi reg, $r25, MULTIPLE_THREADS_OFFSET; \
+    lw   reg, [reg];
+#   define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P(x)
+# endif
+
+
+# ifdef IS_IN_libpthread
+#  define CENABLE(reg)	jmp(reg, __pthread_enable_asynccancel)
+#  define CDISABLE(reg) jmp(reg, __pthread_disable_asynccancel)
+#  define __local_multiple_threads __pthread_multiple_threads
+# elif !defined NOT_IN_libc
+#  define CENABLE(reg)	jmp(reg, __libc_enable_asynccancel)
+#  define CDISABLE(reg)	jmp(reg, __libc_disable_asynccancel)
+#  define __local_multiple_threads __libc_multiple_threads
+# elif defined IS_IN_librt
+#  define CENABLE(reg)	jmp(reg, __librt_enable_asynccancel)
+#  define CDISABLE(reg)	jmp(reg, __librt_disable_asynccancel)
+# else
+#  error Unsupported library
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* For rtld, et cetera.  */
+# 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
+
+
+
+#ifdef PIC
+#define PSEUDO_RET \
+	 .pic \
+   .align 2; \
+   bgez $r0, 1f; \
+   sltsi $r1, $r0, -4096;    \
+   bgtz  $r1, 1f;     \
+   PIC_jmp_err	\
+	 nop; \
+   1:
+#else  /* PIC*/
+#define PSEUDO_RET \
+   .align 2;         \
+   bgez  $r0, 1f; \
+   sltsi $r1, $r0, -4096; \
+   bgtz  $r1, 1f;     \
+   j SYSCALL_ERROR; \
+   1:
+#endif
+
+#ifdef PIC
+#define jmp(reg, symble) PIC_jmpr(reg, symble)
+/* reg: available register */
+#define PIC_jmp_err \
+   smw.adm $sp,[$sp],$sp,#0x6;  \
+   mfusr $r15, $PC;  \
+   sethi $gp,  hi20(_GLOBAL_OFFSET_TABLE_ + 4);  \
+   ori   $gp,  $gp,  lo12(_GLOBAL_OFFSET_TABLE_ + 8);  \
+   add   $gp,  $r15, $gp;  \
+   sethi $r15, hi20(SYSCALL_ERROR@PLT);  \
+   ori   $r15, $r15, lo12(SYSCALL_ERROR@PLT);  \
+   add   $r15, $r15, $gp;  \
+   jral  $r15; \
+   lmw.bim $sp,[$sp],$sp,#0x6; \
+   ret;
+
+#define PIC_jmp(reg, symble) \
+   mfusr $r15, $PC;  \
+   sethi reg,  hi20(_GLOBAL_OFFSET_TABLE_ + 4);  \
+   ori   reg,  reg,  lo12(_GLOBAL_OFFSET_TABLE_ + 8);  \
+   add   reg,  $r15, reg;  \
+   sethi $r15, hi20(symble@PLT);  \
+   ori   $r15, $r15, lo12(symble@PLT);  \
+   add   $r15, $r15, reg;  \
+   jr    $r15;
+
+
+#define PIC_jmpr(reg, symble) \
+   mfusr $r15, $PC;  \
+   sethi reg,  hi20(_GLOBAL_OFFSET_TABLE_ + 4);  \
+   ori   reg,  reg,  lo12(_GLOBAL_OFFSET_TABLE_ + 8);  \
+   add   reg,  $r15, reg;  \
+   sethi $r15, hi20(symble@PLT);  \
+   ori   $r15, $r15, lo12(symble@PLT);  \
+   add   $r15, $r15, reg;  \
+   jral  $r15;
+
+#else
+#define jmp(reg, symble) jal symble
+#endif

+ 43 - 0
libpthread/nptl/sysdeps/unix/sysv/linux/nds32/vfork.S

@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+
+   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 <tls.h>
+
+/* Save the PID value.  */
+#define SAVE_PID \
+	lwi  	$r1, [$r25 + PID_OFFSET];/* Get the thread pointer.  */	\
+	subri	$r1, $r1, 0x0;		 /* Negate it.  */		\
+	bnez	$r1, 1f;		 /* If it was zero... */		\
+	sethi	$r1, 0x80000;		 /* use 0x80000000 instead.  */	\
+1:	swi	$r1, [$r25 + PID_OFFSET];/* Store the temporary PID.  */
+
+/* Restore the old PID value in the parent.  */
+#define RESTORE_PID \
+	beqz	$r0, 1f;		/* If we are the parent... */	\
+	lwi  	$r1, [$r25 + PID_OFFSET];/* Get the thread pointer.  */	\
+	subri	$r1, $r1, 0x0;		/* Re-negate it.  */		\
+	sethi	$r2, 0x80000;		/* Load 0x80000000... */	\
+	bne	$r1, $r2, 2f;		/* ... compare against it... */	\
+	movi	$r1, 0;			/* ... use 0 instead.  */	\
+2:	swi	$r1, [$r25 + PID_OFFSET];/* Restore the PID.  */		\
+1:
+
+#include <../../../../../../../libc/sysdeps/linux/nds32/vfork.S>