From 6af3332a4cbd1ffbc81f74759ef7c5e1a87d2e10 Mon Sep 17 00:00:00 2001 From: Vincent Ren-Wei Chen Date: Tue, 17 Jan 2017 07:31:24 +0100 Subject: 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 --- 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 f312e7a13..a9d62f50f 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 a74249947..2ed6a32b7 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 000000000..d870ad747 --- /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 e0937b732..0f188e792 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 f700531ca..56892a2ba 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 c4a32ca71..5ff2aa9ae 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 000000000..a7ea1f2d1 --- /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 + . */ + +#include +#if defined __UCLIBC_HAS_TLS__ +#include +#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 6a091f80a..9f671419c 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 8c53850d7..e88d9ad60 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 24e00faf0..3fd8a6cd1 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 4f285b5ee..4da2c83ea 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 edd15a410..ba208f6cf 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 c4ebeaa31..82a25d031 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 eb722ec20..b9a9d93ab 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 ed03d2f85..faeae3c61 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 633c91f3e..86a32a613 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 -# +# 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 8691875ee..d5cdddbfa 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 fbea6f6f4..16c4dad38 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 000000000..f93fa7a43 --- /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 + +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 d21c4e03c..a936023aa 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 000000000..010d870f5 --- /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 + . */ + +#ifndef _FENV_H +# error "Never use directly; include 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 13f3e60b3..ac242e065 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 92d89003a..e287c2481 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 directly; use 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 e91f6a9b0..000000000 --- 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 000000000..f3237bd57 --- /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 , 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 + . */ + +#include + +#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 f69ad4c41..215ce3467 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 +#include + +#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) \ + ({