diff options
author | Vincent Ren-Wei Chen <vincentc@andestech.com> | 2017-01-17 07:31:24 +0100 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2017-01-22 10:06:29 +0100 |
commit | 6af3332a4cbd1ffbc81f74759ef7c5e1a87d2e10 (patch) | |
tree | 4deae5f23fd1e2664f21c09dfb57fda799dffd10 /libc | |
parent | 82af21a60bc6e53dd92c1c140f20179d2ae4ad40 (diff) |
nds32: add NPTL/TLS, *context function, libm changes and code cleanup
This commit includes following features.
1. Support NPTL/TLS
2. Add libm function which is used to handle FP rounding and excpetions
(ex: fclrexcpt,fedisblxcpti,feenablxcpt... )
3. Add *context function for operating user context
(ex: setcontext,getcontext,makecontext... )
4. Change the return flow from signal handler
5. Cleanup of old code
The testsuite only has 2 errors, tst-cpuclock1 and tst-cputimer1,
which are related to timing accuracy. (math and locale tests are disabled)
Signed-off-by: Vincent Ren-Wei Chen <vincentc@andestech.com>
Diffstat (limited to 'libc')
41 files changed, 1443 insertions, 848 deletions
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 <andersen@uclibc.org> -# +# Makefile for uClibc-ng # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. -# top_srcdir=../../../../ top_builddir=../../../../ 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 <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 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 + <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 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 <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 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 <philb@gnu.org>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <sys/ucontext.h> + +#define SIGCONTEXT siginfo_t *_si, struct ucontext * +#define SIGCONTEXT_EXTRA_ARGS _si, + +#define GET_PC(ctx) ((void *) (ctx)->uc_mcontext.nds32_ipc) +#define GET_FRAME(ctx) ADVANCE_STACK_FRAME ((void *) ctx->uc_mcontext.nds32_fp) +#define GET_STACK(ctx) ((void *) (ctx)->uc_mcontext.nds32_sp) + + +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) + 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 <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 12e4af9cd..5c4f634a0 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 a7ab1c731..745f109b4 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 b00e62da8..e1f7c83fc 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 5dba17896..1ed77fb2e 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@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 54544010f..c30f4334d 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 92e5e7175..61d01b63a 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 000000000..8ad43f623 --- /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 000000000..7bc1ca292 --- /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@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 14a302969..8499e99b4 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 000000000..d8f38aa15 --- /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@tilera.com>, 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdarg.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <ucontext.h> + +/* makecontext sets up a stack and the registers for the + user context. The stack looks like this: + + +-----------------------+ + | padding as required | + +-----------------------+ + sp -> | parameter 7-n | + +-----------------------+ + + The registers are set up like this: + $r0 .. $r5: parameter 1 to 6 + $r6 : uc_link + $sp : stack pointer. +*/ +void +__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) +{ + extern void __startcontext (void); + unsigned long int *sp; + unsigned long *regptr; + va_list ap; + int i; + + sp = (unsigned long int *) + ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + + /* Allocate stack arguments. */ + sp -= argc < 6 ? 0 : argc - 6; + + /* Keep the stack aligned. */ + sp = (unsigned long int *) (((uintptr_t) sp) & -8L); + + ucp->uc_mcontext.nds32_r6 = (uintptr_t) ucp->uc_link; + ucp->uc_mcontext.nds32_sp = (uintptr_t) sp; + ucp->uc_mcontext.nds32_ipc = (uintptr_t) func; + ucp->uc_mcontext.nds32_lp = (uintptr_t) &__startcontext; + + va_start (ap, argc); + regptr = &ucp->uc_mcontext.nds32_r0; + for (i = 0; i < argc; ++i) + if (i < 6) + *regptr++ = va_arg (ap, unsigned long int); + else + sp[i - 6] = va_arg (ap, unsigned long int); + + va_end (ap); + +} +weak_alias (__makecontext, makecontext) diff --git a/libc/sysdeps/linux/nds32/mmap.S b/libc/sysdeps/linux/nds32/mmap.S deleted file mode 100644 index 351d1c502..000000000 --- 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 000000000..9b2d83544 --- /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 000000000..b20f4ca79 --- /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 000000000..f9265328f --- /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 8cb9adbeb..262d74925 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 1a24c49b4..000000000 --- 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 bf6188656..000000000 --- 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 000000000..310923f0d --- /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@hpl.hp.com>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <ucontext.h> + +struct rv + { + long retval; + long first_return; + }; + +extern struct rv __getcontext (ucontext_t *__ucp); +extern int __setcontext (const ucontext_t *__ucp); + +int +__swapcontext (ucontext_t *oucp, const ucontext_t *ucp) +{ + struct rv rv = __getcontext (oucp); + if (rv.first_return) + __setcontext (ucp); + return 0; +} + +weak_alias (__swapcontext, swapcontext) diff --git a/libc/sysdeps/linux/nds32/sys/ucontext.h b/libc/sysdeps/linux/nds32/sys/ucontext.h index 4dca27fd5..0d7422aab 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 032c643fd..000000000 --- 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 000000000..2c949ef3a --- /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 4e86a26e0..0ab325f26 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 7472a99d4..340797858 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 000000000..1a5f2e5f3 --- /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 c955359fb..ac3fa30fd 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) |