summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/nds32
diff options
context:
space:
mode:
authorVincent Ren-Wei Chen <vincentc@andestech.com>2017-01-17 07:31:24 +0100
committerWaldemar Brodkorb <wbx@openadk.org>2017-01-22 10:06:29 +0100
commit6af3332a4cbd1ffbc81f74759ef7c5e1a87d2e10 (patch)
tree4deae5f23fd1e2664f21c09dfb57fda799dffd10 /libc/sysdeps/linux/nds32
parent82af21a60bc6e53dd92c1c140f20179d2ae4ad40 (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/sysdeps/linux/nds32')
-rw-r--r--libc/sysdeps/linux/nds32/Makefile6
-rw-r--r--libc/sysdeps/linux/nds32/Makefile.arch6
-rw-r--r--libc/sysdeps/linux/nds32/__longjmp.S2
-rw-r--r--libc/sysdeps/linux/nds32/bits/atomic.h110
-rw-r--r--libc/sysdeps/linux/nds32/bits/fcntl.h6
-rw-r--r--libc/sysdeps/linux/nds32/bits/fenv.h79
-rw-r--r--libc/sysdeps/linux/nds32/bits/mman.h1
-rw-r--r--libc/sysdeps/linux/nds32/bits/setjmp.h18
-rw-r--r--libc/sysdeps/linux/nds32/bits/sigcontext.h59
-rw-r--r--libc/sysdeps/linux/nds32/bits/sigcontextinfo.h35
-rw-r--r--libc/sysdeps/linux/nds32/bits/syscalls.h354
-rw-r--r--libc/sysdeps/linux/nds32/bits/uClibc_arch_features.h2
-rw-r--r--libc/sysdeps/linux/nds32/bsd-_setjmp.S5
-rw-r--r--libc/sysdeps/linux/nds32/bsd-setjmp.S4
-rw-r--r--libc/sysdeps/linux/nds32/clone.S200
-rw-r--r--libc/sysdeps/linux/nds32/crt1.S7
-rw-r--r--libc/sysdeps/linux/nds32/crti.S24
-rw-r--r--libc/sysdeps/linux/nds32/fpu_control.h77
-rw-r--r--libc/sysdeps/linux/nds32/getcontext.S106
-rw-r--r--libc/sysdeps/linux/nds32/jmpbuf-unwind.h18
-rw-r--r--libc/sysdeps/linux/nds32/makecontext.c77
-rw-r--r--libc/sysdeps/linux/nds32/mmap.S101
-rw-r--r--libc/sysdeps/linux/nds32/mremap.c28
-rw-r--r--libc/sysdeps/linux/nds32/prctl.c23
-rw-r--r--libc/sysdeps/linux/nds32/setcontext.S85
-rw-r--r--libc/sysdeps/linux/nds32/setjmp.S2
-rw-r--r--libc/sysdeps/linux/nds32/sigaction.c40
-rw-r--r--libc/sysdeps/linux/nds32/sigrestorer.S42
-rw-r--r--libc/sysdeps/linux/nds32/swapcontext.c38
-rw-r--r--libc/sysdeps/linux/nds32/sys/ucontext.h117
-rw-r--r--libc/sysdeps/linux/nds32/syscall.S60
-rw-r--r--libc/sysdeps/linux/nds32/syscall.c28
-rw-r--r--libc/sysdeps/linux/nds32/sysdep.S39
-rw-r--r--libc/sysdeps/linux/nds32/sysdep.h321
-rw-r--r--libc/sysdeps/linux/nds32/ucontext_i.sym27
-rw-r--r--libc/sysdeps/linux/nds32/vfork.S114
36 files changed, 1418 insertions, 843 deletions
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)