This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "uClibc-ng - small C library for embedded systems".
The branch, master has been updated
via 6af3332a4cbd1ffbc81f74759ef7c5e1a87d2e10 (commit)
from 82af21a60bc6e53dd92c1c140f20179d2ae4ad40 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 6af3332a4cbd1ffbc81f74759ef7c5e1a87d2e10
Author: Vincent Ren-Wei Chen <vincentc(a)andestech.com>
Date: Tue Jan 17 07:31:24 2017 +0100
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(a)andestech.com>
-----------------------------------------------------------------------
Summary of changes:
extra/Configs/Config.in | 1 -
extra/Configs/Config.nds32 | 1 +
extra/Configs/defconfigs/nds32/defconfig | 167 ++++++++++
include/elf.h | 3 +
ldso/ldso/nds32/dl-startup.h | 94 +-----
ldso/ldso/nds32/dl-sysdep.h | 5 +-
ldso/ldso/nds32/dl-tlsdesc.S | 100 ++++++
ldso/ldso/nds32/elfinterp.c | 94 ++++--
ldso/ldso/nds32/resolve.S | 24 --
ldso/libdl/Makefile.in | 1 -
libc/string/nds32/memcpy.S | 22 +-
libc/string/nds32/memset.S | 2 +-
libc/sysdeps/linux/common/posix_fadvise.c | 2 +-
libc/sysdeps/linux/common/posix_fadvise64.c | 2 +-
libc/sysdeps/linux/common/sync_file_range.c | 2 +-
libc/sysdeps/linux/nds32/Makefile | 6 +-
libc/sysdeps/linux/nds32/Makefile.arch | 6 +-
libc/sysdeps/linux/nds32/__longjmp.S | 2 +-
libc/sysdeps/linux/nds32/bits/atomic.h | 110 +++++++
libc/sysdeps/linux/nds32/bits/fcntl.h | 6 +-
libc/sysdeps/linux/nds32/bits/fenv.h | 79 +++++
libc/sysdeps/linux/nds32/bits/mman.h | 1 +
libc/sysdeps/linux/nds32/bits/setjmp.h | 18 +-
libc/sysdeps/linux/nds32/bits/sigcontext.h | 59 ----
libc/sysdeps/linux/nds32/bits/sigcontextinfo.h | 35 ++
libc/sysdeps/linux/nds32/bits/syscalls.h | 354 ++++++++++++++++-----
.../linux/nds32/bits/uClibc_arch_features.h | 2 +-
libc/sysdeps/linux/nds32/bsd-_setjmp.S | 5 +-
libc/sysdeps/linux/nds32/bsd-setjmp.S | 4 +-
libc/sysdeps/linux/nds32/clone.S | 200 ++++++++----
libc/sysdeps/linux/nds32/crt1.S | 7 -
libc/sysdeps/linux/nds32/crti.S | 24 --
libc/sysdeps/linux/nds32/fpu_control.h | 77 +++++
libc/sysdeps/linux/nds32/getcontext.S | 106 ++++++
libc/sysdeps/linux/nds32/jmpbuf-unwind.h | 18 +-
libc/sysdeps/linux/nds32/makecontext.c | 77 +++++
libc/sysdeps/linux/nds32/mmap.S | 101 ------
libc/sysdeps/linux/nds32/mremap.c | 28 ++
libc/sysdeps/linux/nds32/prctl.c | 23 ++
libc/sysdeps/linux/nds32/setcontext.S | 85 +++++
libc/sysdeps/linux/nds32/setjmp.S | 2 +-
libc/sysdeps/linux/nds32/sigaction.c | 40 ---
libc/sysdeps/linux/nds32/sigrestorer.S | 42 ---
libc/sysdeps/linux/nds32/swapcontext.c | 38 +++
libc/sysdeps/linux/nds32/sys/ucontext.h | 117 ++-----
libc/sysdeps/linux/nds32/syscall.S | 60 ----
libc/sysdeps/linux/nds32/syscall.c | 28 ++
libc/sysdeps/linux/nds32/sysdep.S | 39 ++-
libc/sysdeps/linux/nds32/sysdep.h | 321 +++++++------------
libc/sysdeps/linux/nds32/ucontext_i.sym | 27 ++
libc/sysdeps/linux/nds32/vfork.S | 114 +++++--
libm/nds32/Makefile.arch | 16 +
libm/nds32/e_sqrt.c | 34 ++
libm/nds32/fclrexcpt.c | 52 +++
libm/nds32/fedisblxcpt.c | 49 +++
libm/nds32/feenablxcpt.c | 50 +++
libm/nds32/fegetenv.c | 40 +++
libm/nds32/fegetexcept.c | 41 +++
libm/nds32/fegetround.c | 40 +++
libm/nds32/feholdexcpt.c | 51 +++
libm/nds32/fenv_libc.h | 33 ++
libm/nds32/fesetenv.c | 51 +++
libm/nds32/fesetround.c | 42 +++
libm/nds32/feupdateenv.c | 48 +++
libm/nds32/fgetexcptflg.c | 44 +++
libm/nds32/fraiseexcpt.c | 104 ++++++
libm/nds32/fsetexcptflg.c | 48 +++
libm/nds32/ftestexcept.c | 40 +++
libpthread/linuxthreads/sysdeps/nds32/pspinlock.c | 2 +-
libpthread/linuxthreads/sysdeps/nds32/pt-machine.h | 2 +-
libpthread/nptl/sysdeps/nds32/Makefile.arch | 16 +
libpthread/nptl/sysdeps/nds32/dl-tls.h | 59 ++++
libpthread/nptl/sysdeps/nds32/libc-dl-tlsdesc.S | 1 +
libpthread/nptl/sysdeps/nds32/pthread_spin_lock.c | 65 ++++
.../nptl/sysdeps/nds32/pthread_spin_trylock.c | 26 ++
libpthread/nptl/sysdeps/nds32/pthreaddef.h | 39 +++
libpthread/nptl/sysdeps/nds32/tcb-offsets.sym | 12 +
libpthread/nptl/sysdeps/nds32/tls.h | 178 +++++++++++
libpthread/nptl/sysdeps/nds32/tlsdesc.sym | 17 +
.../nptl/sysdeps/unix/sysv/linux/nds32/Makefile | 9 +
.../sysdeps/unix/sysv/linux/nds32/Makefile.arch | 12 +
.../unix/sysv/linux/nds32/bits/pthreadtypes.h | 177 +++++++++++
.../sysdeps/unix/sysv/linux/nds32/bits/semaphore.h | 38 +++
.../nptl/sysdeps/unix/sysv/linux/nds32/clone.S | 4 +
.../sysdeps/unix/sysv/linux/nds32/createthread.c | 22 ++
.../nptl/sysdeps/unix/sysv/linux/nds32/fork.c | 27 ++
.../sysdeps/unix/sysv/linux/nds32/lowlevellock.h | 323 +++++++++++++++++++
.../nptl/sysdeps/unix/sysv/linux/nds32/pt-raise.c | 18 ++
.../sysdeps/unix/sysv/linux/nds32/pthread_once.c | 92 ++++++
.../sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h | 273 ++++++++++++++++
.../nptl/sysdeps/unix/sysv/linux/nds32/vfork.S | 43 +++
91 files changed, 4023 insertions(+), 996 deletions(-)
create mode 100644 extra/Configs/defconfigs/nds32/defconfig
create mode 100644 ldso/ldso/nds32/dl-tlsdesc.S
create mode 100644 libc/sysdeps/linux/nds32/bits/atomic.h
create mode 100644 libc/sysdeps/linux/nds32/bits/fenv.h
delete mode 100644 libc/sysdeps/linux/nds32/bits/sigcontext.h
create mode 100644 libc/sysdeps/linux/nds32/bits/sigcontextinfo.h
create mode 100644 libc/sysdeps/linux/nds32/fpu_control.h
create mode 100644 libc/sysdeps/linux/nds32/getcontext.S
create mode 100644 libc/sysdeps/linux/nds32/makecontext.c
delete mode 100644 libc/sysdeps/linux/nds32/mmap.S
create mode 100644 libc/sysdeps/linux/nds32/mremap.c
create mode 100644 libc/sysdeps/linux/nds32/prctl.c
create mode 100644 libc/sysdeps/linux/nds32/setcontext.S
delete mode 100644 libc/sysdeps/linux/nds32/sigaction.c
delete mode 100644 libc/sysdeps/linux/nds32/sigrestorer.S
create mode 100644 libc/sysdeps/linux/nds32/swapcontext.c
delete mode 100644 libc/sysdeps/linux/nds32/syscall.S
create mode 100644 libc/sysdeps/linux/nds32/syscall.c
create mode 100644 libc/sysdeps/linux/nds32/ucontext_i.sym
create mode 100644 libm/nds32/Makefile.arch
create mode 100644 libm/nds32/e_sqrt.c
create mode 100644 libm/nds32/fclrexcpt.c
create mode 100644 libm/nds32/fedisblxcpt.c
create mode 100644 libm/nds32/feenablxcpt.c
create mode 100644 libm/nds32/fegetenv.c
create mode 100644 libm/nds32/fegetexcept.c
create mode 100644 libm/nds32/fegetround.c
create mode 100644 libm/nds32/feholdexcpt.c
create mode 100644 libm/nds32/fenv_libc.h
create mode 100644 libm/nds32/fesetenv.c
create mode 100644 libm/nds32/fesetround.c
create mode 100644 libm/nds32/feupdateenv.c
create mode 100644 libm/nds32/fgetexcptflg.c
create mode 100644 libm/nds32/fraiseexcpt.c
create mode 100644 libm/nds32/fsetexcptflg.c
create mode 100644 libm/nds32/ftestexcept.c
create mode 100644 libpthread/nptl/sysdeps/nds32/Makefile.arch
create mode 100644 libpthread/nptl/sysdeps/nds32/dl-tls.h
create mode 100644 libpthread/nptl/sysdeps/nds32/libc-dl-tlsdesc.S
create mode 100644 libpthread/nptl/sysdeps/nds32/pthread_spin_lock.c
create mode 100644 libpthread/nptl/sysdeps/nds32/pthread_spin_trylock.c
create mode 100644 libpthread/nptl/sysdeps/nds32/pthreaddef.h
create mode 100644 libpthread/nptl/sysdeps/nds32/tcb-offsets.sym
create mode 100644 libpthread/nptl/sysdeps/nds32/tls.h
create mode 100644 libpthread/nptl/sysdeps/nds32/tlsdesc.sym
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile.arch
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/pthreadtypes.h
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/semaphore.h
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/clone.S
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/createthread.c
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/fork.c
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/lowlevellock.h
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pt-raise.c
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pthread_once.c
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h
create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/vfork.S
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index f312e7a..a9d62f5 100644
--- a/extra/Configs/Config.in
+++ b/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
diff --git a/extra/Configs/Config.nds32 b/extra/Configs/Config.nds32
index a742499..2ed6a32 100644
--- a/extra/Configs/Config.nds32
+++ b/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"
diff --git a/extra/Configs/defconfigs/nds32/defconfig
b/extra/Configs/defconfigs/nds32/defconfig
new file mode 100644
index 0000000..d870ad7
--- /dev/null
+++ b/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
diff --git a/include/elf.h b/include/elf.h
index e0937b7..0f188e7 100644
--- a/include/elf.h
+++ b/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
diff --git a/ldso/ldso/nds32/dl-startup.h b/ldso/ldso/nds32/dl-startup.h
index f700531..56892a2 100644
--- a/ldso/ldso/nds32/dl-startup.h
+++ b/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:
diff --git a/ldso/ldso/nds32/dl-sysdep.h b/ldso/ldso/nds32/dl-sysdep.h
index c4a32ca..5ff2aa9 100644
--- a/ldso/ldso/nds32/dl-sysdep.h
+++ b/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();
}
diff --git a/ldso/ldso/nds32/dl-tlsdesc.S b/ldso/ldso/nds32/dl-tlsdesc.S
new file mode 100644
index 0000000..a7ea1f2
--- /dev/null
+++ b/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__
diff --git a/ldso/ldso/nds32/elfinterp.c b/ldso/ldso/nds32/elfinterp.c
index 6a091f8..9f67141 100644
--- a/ldso/ldso/nds32/elfinterp.c
+++ b/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
diff --git a/ldso/ldso/nds32/resolve.S b/ldso/ldso/nds32/resolve.S
index 8c53850..e88d9ad 100644
--- a/ldso/ldso/nds32/resolve.S
+++ b/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
diff --git a/ldso/libdl/Makefile.in b/ldso/libdl/Makefile.in
index 24e00fa..3fd8a6c 100644
--- a/ldso/libdl/Makefile.in
+++ b/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)
diff --git a/libc/string/nds32/memcpy.S b/libc/string/nds32/memcpy.S
index 4f285b5..4da2c83 100644
--- a/libc/string/nds32/memcpy.S
+++ b/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
diff --git a/libc/string/nds32/memset.S b/libc/string/nds32/memset.S
index edd15a4..ba208f6 100644
--- a/libc/string/nds32/memset.S
+++ b/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.
*/
diff --git a/libc/sysdeps/linux/common/posix_fadvise.c
b/libc/sysdeps/linux/common/posix_fadvise.c
index c4ebeaa..82a25d0 100644
--- a/libc/sysdeps/linux/common/posix_fadvise.c
+++ b/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) */
diff --git a/libc/sysdeps/linux/common/posix_fadvise64.c
b/libc/sysdeps/linux/common/posix_fadvise64.c
index eb722ec..b9a9d93 100644
--- a/libc/sysdeps/linux/common/posix_fadvise64.c
+++ b/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) */
diff --git a/libc/sysdeps/linux/common/sync_file_range.c
b/libc/sysdeps/linux/common/sync_file_range.c
index ed03d2f..faeae3c 100644
--- a/libc/sysdeps/linux/common/sync_file_range.c
+++ b/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 */
diff --git a/libc/sysdeps/linux/nds32/Makefile b/libc/sysdeps/linux/nds32/Makefile
index 633c91f..86a32a6 100644
--- a/libc/sysdeps/linux/nds32/Makefile
+++ b/libc/sysdeps/linux/nds32/Makefile
@@ -1,9 +1,5 @@
-# Makefile for uClibc
-#
-# Copyright (C) 2000-2005 Erik Andersen <andersen(a)uclibc.org>
-#
+# Makefile for uClibc-ng
# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
-#
top_srcdir=../../../../
top_builddir=../../../../
diff --git a/libc/sysdeps/linux/nds32/Makefile.arch
b/libc/sysdeps/linux/nds32/Makefile.arch
index 8691875..d5cdddb 100644
--- a/libc/sysdeps/linux/nds32/Makefile.arch
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/__longjmp.S b/libc/sysdeps/linux/nds32/__longjmp.S
index fbea6f6..16c4dad 100644
--- a/libc/sysdeps/linux/nds32/__longjmp.S
+++ b/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.
*/
diff --git a/libc/sysdeps/linux/nds32/bits/atomic.h
b/libc/sysdeps/linux/nds32/bits/atomic.h
new file mode 100644
index 0000000..f93fa7a
--- /dev/null
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/bits/fcntl.h
b/libc/sysdeps/linux/nds32/bits/fcntl.h
index d21c4e0..a936023 100644
--- a/libc/sysdeps/linux/nds32/bits/fcntl.h
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/bits/fenv.h b/libc/sysdeps/linux/nds32/bits/fenv.h
new file mode 100644
index 0000000..010d870
--- /dev/null
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/bits/mman.h b/libc/sysdeps/linux/nds32/bits/mman.h
index 13f3e60..ac242e0 100644
--- a/libc/sysdeps/linux/nds32/bits/mman.h
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/bits/setjmp.h
b/libc/sysdeps/linux/nds32/bits/setjmp.h
index 92d8900..e287c24 100644
--- a/libc/sysdeps/linux/nds32/bits/setjmp.h
+++ b/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 */
diff --git a/libc/sysdeps/linux/nds32/bits/sigcontext.h
b/libc/sysdeps/linux/nds32/bits/sigcontext.h
deleted file mode 100644
index e91f6a9..0000000
--- a/libc/sysdeps/linux/nds32/bits/sigcontext.h
+++ /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/nds32/bits/sigcontextinfo.h
b/libc/sysdeps/linux/nds32/bits/sigcontextinfo.h
new file mode 100644
index 0000000..f3237bd
--- /dev/null
+++ b/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(a)gnu.org>rg>, 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))
+
diff --git a/libc/sysdeps/linux/nds32/bits/syscalls.h
b/libc/sysdeps/linux/nds32/bits/syscalls.h
index f69ad4c..215ce34 100644
--- a/libc/sysdeps/linux/nds32/bits/syscalls.h
+++ b/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 */
diff --git a/libc/sysdeps/linux/nds32/bits/uClibc_arch_features.h
b/libc/sysdeps/linux/nds32/bits/uClibc_arch_features.h
index 12e4af9..5c4f634 100644
--- a/libc/sysdeps/linux/nds32/bits/uClibc_arch_features.h
+++ b/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__
diff --git a/libc/sysdeps/linux/nds32/bsd-_setjmp.S
b/libc/sysdeps/linux/nds32/bsd-_setjmp.S
index a7ab1c7..745f109 100644
--- a/libc/sysdeps/linux/nds32/bsd-_setjmp.S
+++ b/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)
diff --git a/libc/sysdeps/linux/nds32/bsd-setjmp.S
b/libc/sysdeps/linux/nds32/bsd-setjmp.S
index b00e62d..e1f7c83 100644
--- a/libc/sysdeps/linux/nds32/bsd-setjmp.S
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/clone.S b/libc/sysdeps/linux/nds32/clone.S
index 5dba178..1ed77fb 100644
--- a/libc/sysdeps/linux/nds32/clone.S
+++ b/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(a)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)
diff --git a/libc/sysdeps/linux/nds32/crt1.S b/libc/sysdeps/linux/nds32/crt1.S
index 5454401..c30f433 100644
--- a/libc/sysdeps/linux/nds32/crt1.S
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/crti.S b/libc/sysdeps/linux/nds32/crti.S
index 92e5e71..61d01b6 100644
--- a/libc/sysdeps/linux/nds32/crti.S
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/fpu_control.h
b/libc/sysdeps/linux/nds32/fpu_control.h
new file mode 100644
index 0000000..8ad43f6
--- /dev/null
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/getcontext.S
b/libc/sysdeps/linux/nds32/getcontext.S
new file mode 100644
index 0000000..7bc1ca2
--- /dev/null
+++ b/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(a)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)
+
diff --git a/libc/sysdeps/linux/nds32/jmpbuf-unwind.h
b/libc/sysdeps/linux/nds32/jmpbuf-unwind.h
index 14a3029..8499e99 100644
--- a/libc/sysdeps/linux/nds32/jmpbuf-unwind.h
+++ b/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))
diff --git a/libc/sysdeps/linux/nds32/makecontext.c
b/libc/sysdeps/linux/nds32/makecontext.c
new file mode 100644
index 0000000..d8f38aa
--- /dev/null
+++ b/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(a)tilera.com>om>, 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)
diff --git a/libc/sysdeps/linux/nds32/mmap.S b/libc/sysdeps/linux/nds32/mmap.S
deleted file mode 100644
index 351d1c5..0000000
--- a/libc/sysdeps/linux/nds32/mmap.S
+++ /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/nds32/mremap.c b/libc/sysdeps/linux/nds32/mremap.c
new file mode 100644
index 0000000..9b2d835
--- /dev/null
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/prctl.c b/libc/sysdeps/linux/nds32/prctl.c
new file mode 100644
index 0000000..b20f4ca
--- /dev/null
+++ b/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);
+}
diff --git a/libc/sysdeps/linux/nds32/setcontext.S
b/libc/sysdeps/linux/nds32/setcontext.S
new file mode 100644
index 0000000..f926532
--- /dev/null
+++ b/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)
+
diff --git a/libc/sysdeps/linux/nds32/setjmp.S b/libc/sysdeps/linux/nds32/setjmp.S
index 8cb9adb..262d749 100644
--- a/libc/sysdeps/linux/nds32/setjmp.S
+++ b/libc/sysdeps/linux/nds32/setjmp.S
@@ -106,4 +106,4 @@ ENTRY(__sigsetjmp)
#endif
END(__sigsetjmp)
-hidden_def(__sigsetjmp)
+libc_hidden_def(__sigsetjmp)
diff --git a/libc/sysdeps/linux/nds32/sigaction.c b/libc/sysdeps/linux/nds32/sigaction.c
deleted file mode 100644
index 1a24c49..0000000
--- a/libc/sysdeps/linux/nds32/sigaction.c
+++ /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/nds32/sigrestorer.S
b/libc/sysdeps/linux/nds32/sigrestorer.S
deleted file mode 100644
index bf61886..0000000
--- a/libc/sysdeps/linux/nds32/sigrestorer.S
+++ /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/nds32/swapcontext.c
b/libc/sysdeps/linux/nds32/swapcontext.c
new file mode 100644
index 0000000..310923f
--- /dev/null
+++ b/libc/sysdeps/linux/nds32/swapcontext.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 2001-2013 Free Software Foundation, Inc.
+ Contributed by David Mosberger-Tang <davidm(a)hpl.hp.com>om>.
+
+ 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)
diff --git a/libc/sysdeps/linux/nds32/sys/ucontext.h
b/libc/sysdeps/linux/nds32/sys/ucontext.h
index 4dca27f..0d7422a 100644
--- a/libc/sysdeps/linux/nds32/sys/ucontext.h
+++ b/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 */
diff --git a/libc/sysdeps/linux/nds32/syscall.S b/libc/sysdeps/linux/nds32/syscall.S
deleted file mode 100644
index 032c643..0000000
--- a/libc/sysdeps/linux/nds32/syscall.S
+++ /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/nds32/syscall.c b/libc/sysdeps/linux/nds32/syscall.c
new file mode 100644
index 0000000..2c949ef
--- /dev/null
+++ b/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;
+}
diff --git a/libc/sysdeps/linux/nds32/sysdep.S b/libc/sysdeps/linux/nds32/sysdep.S
index 4e86a26..0ab325f 100644
--- a/libc/sysdeps/linux/nds32/sysdep.S
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/sysdep.h b/libc/sysdeps/linux/nds32/sysdep.h
index 7472a99..3407978 100644
--- a/libc/sysdeps/linux/nds32/sysdep.h
+++ b/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
diff --git a/libc/sysdeps/linux/nds32/ucontext_i.sym
b/libc/sysdeps/linux/nds32/ucontext_i.sym
new file mode 100644
index 0000000..1a5f2e5
--- /dev/null
+++ b/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)
diff --git a/libc/sysdeps/linux/nds32/vfork.S b/libc/sysdeps/linux/nds32/vfork.S
index c955359..ac3fa30 100644
--- a/libc/sysdeps/linux/nds32/vfork.S
+++ b/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)
diff --git a/libm/nds32/Makefile.arch b/libm/nds32/Makefile.arch
new file mode 100644
index 0000000..bd38690
--- /dev/null
+++ b/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)
diff --git a/libm/nds32/e_sqrt.c b/libm/nds32/e_sqrt.c
new file mode 100644
index 0000000..c737e10
--- /dev/null
+++ b/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
diff --git a/libm/nds32/fclrexcpt.c b/libm/nds32/fclrexcpt.c
new file mode 100644
index 0000000..938f15a
--- /dev/null
+++ b/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
+}
diff --git a/libm/nds32/fedisblxcpt.c b/libm/nds32/fedisblxcpt.c
new file mode 100644
index 0000000..bbb6d54
--- /dev/null
+++ b/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(a)gnu.org>rg>, 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
+}
diff --git a/libm/nds32/feenablxcpt.c b/libm/nds32/feenablxcpt.c
new file mode 100644
index 0000000..14aef98
--- /dev/null
+++ b/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(a)gnu.org>rg>, 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
+}
diff --git a/libm/nds32/fegetenv.c b/libm/nds32/fegetenv.c
new file mode 100644
index 0000000..782cf79
--- /dev/null
+++ b/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
+}
diff --git a/libm/nds32/fegetexcept.c b/libm/nds32/fegetexcept.c
new file mode 100644
index 0000000..1ffe361
--- /dev/null
+++ b/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(a)gnu.org>rg>, 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
+}
diff --git a/libm/nds32/fegetround.c b/libm/nds32/fegetround.c
new file mode 100644
index 0000000..e4e70ea
--- /dev/null
+++ b/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
+}
diff --git a/libm/nds32/feholdexcpt.c b/libm/nds32/feholdexcpt.c
new file mode 100644
index 0000000..4ea3679
--- /dev/null
+++ b/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
+}
+
diff --git a/libm/nds32/fenv_libc.h b/libm/nds32/fenv_libc.h
new file mode 100644
index 0000000..a76f131
--- /dev/null
+++ b/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(a)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 */
diff --git a/libm/nds32/fesetenv.c b/libm/nds32/fesetenv.c
new file mode 100644
index 0000000..4682d3c
--- /dev/null
+++ b/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
+}
diff --git a/libm/nds32/fesetround.c b/libm/nds32/fesetround.c
new file mode 100644
index 0000000..012a5bf
--- /dev/null
+++ b/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
+}
diff --git a/libm/nds32/feupdateenv.c b/libm/nds32/feupdateenv.c
new file mode 100644
index 0000000..d58c900
--- /dev/null
+++ b/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(a)cygnus.com>om>, 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
+}
diff --git a/libm/nds32/fgetexcptflg.c b/libm/nds32/fgetexcptflg.c
new file mode 100644
index 0000000..e446c42
--- /dev/null
+++ b/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(a)cygnus.com>om>, 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
+}
diff --git a/libm/nds32/fraiseexcpt.c b/libm/nds32/fraiseexcpt.c
new file mode 100644
index 0000000..d194211
--- /dev/null
+++ b/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);
+}
diff --git a/libm/nds32/fsetexcptflg.c b/libm/nds32/fsetexcptflg.c
new file mode 100644
index 0000000..7da943b
--- /dev/null
+++ b/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
+}
diff --git a/libm/nds32/ftestexcept.c b/libm/nds32/ftestexcept.c
new file mode 100644
index 0000000..8257b6f
--- /dev/null
+++ b/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
+}
diff --git a/libpthread/linuxthreads/sysdeps/nds32/pspinlock.c
b/libpthread/linuxthreads/sysdeps/nds32/pspinlock.c
index f8adf07..770a55a 100644
--- a/libpthread/linuxthreads/sysdeps/nds32/pspinlock.c
+++ b/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.
*/
diff --git a/libpthread/linuxthreads/sysdeps/nds32/pt-machine.h
b/libpthread/linuxthreads/sysdeps/nds32/pt-machine.h
index 5bbb9e8..631c284 100644
--- a/libpthread/linuxthreads/sysdeps/nds32/pt-machine.h
+++ b/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.
*/
diff --git a/libpthread/nptl/sysdeps/nds32/Makefile.arch
b/libpthread/nptl/sysdeps/nds32/Makefile.arch
new file mode 100644
index 0000000..7eb852a
--- /dev/null
+++ b/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
diff --git a/libpthread/nptl/sysdeps/nds32/dl-tls.h
b/libpthread/nptl/sysdeps/nds32/dl-tls.h
new file mode 100644
index 0000000..3b11e7f
--- /dev/null
+++ b/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
diff --git a/libpthread/nptl/sysdeps/nds32/libc-dl-tlsdesc.S
b/libpthread/nptl/sysdeps/nds32/libc-dl-tlsdesc.S
new file mode 100644
index 0000000..5892a8b
--- /dev/null
+++ b/libpthread/nptl/sysdeps/nds32/libc-dl-tlsdesc.S
@@ -0,0 +1 @@
+#include <ldso/ldso/nds32/dl-tlsdesc.S>
diff --git a/libpthread/nptl/sysdeps/nds32/pthread_spin_lock.c
b/libpthread/nptl/sysdeps/nds32/pthread_spin_lock.c
new file mode 100644
index 0000000..cec3acb
--- /dev/null
+++ b/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;
+}
diff --git a/libpthread/nptl/sysdeps/nds32/pthread_spin_trylock.c
b/libpthread/nptl/sysdeps/nds32/pthread_spin_trylock.c
new file mode 100644
index 0000000..4e9aa64
--- /dev/null
+++ b/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;
+}
diff --git a/libpthread/nptl/sysdeps/nds32/pthreaddef.h
b/libpthread/nptl/sysdeps/nds32/pthreaddef.h
new file mode 100644
index 0000000..c9d3f77
--- /dev/null
+++ b/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))
+
+
diff --git a/libpthread/nptl/sysdeps/nds32/tcb-offsets.sym
b/libpthread/nptl/sysdeps/nds32/tcb-offsets.sym
new file mode 100644
index 0000000..3b9e101
--- /dev/null
+++ b/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)
+
diff --git a/libpthread/nptl/sysdeps/nds32/tls.h b/libpthread/nptl/sysdeps/nds32/tls.h
new file mode 100644
index 0000000..e2a3862
--- /dev/null
+++ b/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 */
+
+
diff --git a/libpthread/nptl/sysdeps/nds32/tlsdesc.sym
b/libpthread/nptl/sysdeps/nds32/tlsdesc.sym
new file mode 100644
index 0000000..4fa3ada
--- /dev/null
+++ b/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)
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile
new file mode 100644
index 0000000..2caba11
--- /dev/null
+++ b/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
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile.arch
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile.arch
new file mode 100644
index 0000000..3b8935c
--- /dev/null
+++ b/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)
+
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/pthreadtypes.h
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/pthreadtypes.h
new file mode 100644
index 0000000..695a61f
--- /dev/null
+++ b/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 */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/semaphore.h
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/semaphore.h
new file mode 100644
index 0000000..8ee7742
--- /dev/null
+++ b/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(a)redhat.com>om>, 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;
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/clone.S
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/clone.S
new file mode 100644
index 0000000..94b39fc
--- /dev/null
+++ b/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>
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/createthread.c
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/createthread.c
new file mode 100644
index 0000000..486bc24
--- /dev/null
+++ b/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>
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/fork.c
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/fork.c
new file mode 100644
index 0000000..beb6cb0
--- /dev/null
+++ b/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(a)nexus.co.uk>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"
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/lowlevellock.h
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/lowlevellock.h
new file mode 100644
index 0000000..32b0044
--- /dev/null
+++ b/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 */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pt-raise.c
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pt-raise.c
new file mode 100644
index 0000000..6c0d4b5
--- /dev/null
+++ b/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(a)redhat.com>om>, 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>
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pthread_once.c
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pthread_once.c
new file mode 100644
index 0000000..ce68ce6
--- /dev/null
+++ b/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(a)redhat.com>om>, 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)
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h
new file mode 100644
index 0000000..a0f4de5
--- /dev/null
+++ b/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
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/vfork.S
b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/vfork.S
new file mode 100644
index 0000000..f11f76a
--- /dev/null
+++ b/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>
hooks/post-receive
--
uClibc-ng - small C library for embedded systems