From 6af3332a4cbd1ffbc81f74759ef7c5e1a87d2e10 Mon Sep 17 00:00:00 2001 From: Vincent Ren-Wei Chen Date: Tue, 17 Jan 2017 07:31:24 +0100 Subject: nds32: add NPTL/TLS, *context function, libm changes and code cleanup This commit includes following features. 1. Support NPTL/TLS 2. Add libm function which is used to handle FP rounding and excpetions (ex: fclrexcpt,fedisblxcpti,feenablxcpt... ) 3. Add *context function for operating user context (ex: setcontext,getcontext,makecontext... ) 4. Change the return flow from signal handler 5. Cleanup of old code The testsuite only has 2 errors, tst-cpuclock1 and tst-cputimer1, which are related to timing accuracy. (math and locale tests are disabled) Signed-off-by: Vincent Ren-Wei Chen --- .../sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h | 273 +++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h') diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h new file mode 100644 index 000000000..a0f4de5c8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2016-2017 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Copyright (C) 2003-2013 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + + + +#define PUSHARGS_0 +#define PUSHARGS_1 smw.adm $r0, [$sp], $r0, #0; \ + cfi_adjust_cfa_offset(4); \ + cfi_rel_offset(r0,0); \ + addi $sp, $sp, -4; \ + cfi_adjust_cfa_offset(4); +#define PUSHARGS_2 smw.adm $r0, [$sp], $r1, #0; \ + cfi_adjust_cfa_offset(8); \ + cfi_rel_offset(r1, 4); \ + cfi_rel_offset(r0, 0); +#define PUSHARGS_3 smw.adm $r0, [$sp], $r2, #0; \ + cfi_adjust_cfa_offset(12); \ + cfi_rel_offset(r2, 8); \ + cfi_rel_offset(r1, 4); \ + cfi_rel_offset(r0, 0); \ + addi $sp, $sp, -4; \ + cfi_adjust_cfa_offset(4); +#define PUSHARGS_4 smw.adm $r0, [$sp], $r3, #0; \ + cfi_adjust_cfa_offset(16); \ + cfi_rel_offset(r3, 12); \ + cfi_rel_offset(r2, 8); \ + cfi_rel_offset(r1, 4); \ + cfi_rel_offset(r0, 0); +#define PUSHARGS_5 smw.adm $r0, [$sp], $r4, #0; \ + cfi_adjust_cfa_offset(20); \ + cfi_rel_offset(r4, 16); \ + cfi_rel_offset(r3, 12); \ + cfi_rel_offset(r2, 8); \ + cfi_rel_offset(r1, 4); \ + cfi_rel_offset(r0, 0); \ + addi $sp, $sp, -4; \ + cfi_adjust_cfa_offset(4); +#define PUSHARGS_6 smw.adm $r0, [$sp], $r5, #0; \ + cfi_adjust_cfa_offset(24); \ + cfi_rel_offset(r5, 20); \ + cfi_rel_offset(r4, 16); \ + cfi_rel_offset(r3, 12); \ + cfi_rel_offset(r2, 8); \ + cfi_rel_offset(r1, 4); \ + cfi_rel_offset(r0, 0); + +#define POPARGS2_0 +#define POPARGS2_1 addi $sp, $sp, 4; \ + cfi_adjust_cfa_offset(-4); \ + lmw.bim $r0, [$sp], $r0, #0; \ + cfi_adjust_cfa_offset(-4); \ + cfi_restore(r0); +#define POPARGS2_2 lmw.bim $r0, [$sp], $r1, #0; \ + cfi_adjust_cfa_offset(-8); \ + cfi_restore(r0); \ + cfi_restore(r1); +#define POPARGS2_3 addi $sp, $sp, 4; \ + cfi_adjust_cfa_offset(-4); \ + lmw.bim $r0, [$sp], $r2, #0; \ + cfi_adjust_cfa_offset(-12); \ + cfi_restore(r0); \ + cfi_restore(r1); \ + cfi_restore(r2); +#define POPARGS2_4 lmw.bim $r0, [$sp], $r3, #0; \ + cfi_adjust_cfa_offset(-16); \ + cfi_restore(r0); \ + cfi_restore(r1); \ + cfi_restore(r2); \ + cfi_restore(r3); +#define POPARGS2_5 addi $sp, $sp, 4; \ + cfi_adjust_cfa_offset(-4); \ + lmw.bim $r0, [$sp], $r4, #0; \ + cfi_adjust_cfa_offset(-20); \ + cfi_restore(r0); \ + cfi_restore(r1); \ + cfi_restore(r2); \ + cfi_restore(r3); \ + cfi_restore(r4); +#define POPARGS2_6 lmw.bim $r0, [$sp], $r5, #0; \ + cfi_adjust_cfa_offset(-24); \ + cfi_restore(r0); \ + cfi_restore(r1); \ + cfi_restore(r2); \ + cfi_restore(r3); \ + cfi_restore(r4); \ + cfi_restore(r5); + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +/* NOTE: We do mark syscalls with unwind annotations, for the benefit of + cancellation; but they're really only accurate at the point of the + syscall. The ARM unwind directives are not rich enough without adding + a custom personality function. */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .align 2; \ + ENTRY (__##syscall_name##_nocancel); \ + __do_syscall(syscall_name); \ + PSEUDO_RET; \ + ret; \ + END (__##syscall_name##_nocancel); \ + ENTRY (name); \ + smw.adm $r6,[$sp],$r6,0x2; \ + cfi_adjust_cfa_offset(8); \ + cfi_offset(r6,-8); \ + cfi_offset(lp,-4); \ + SINGLE_THREAD_P ($r15); \ + bgtz $r15, .Lpseudo_cancel; \ + __do_syscall(syscall_name); \ + j 50f; \ + .Lpseudo_cancel: \ + PUSHARGS_##args; /* save syscall args etc. around CENABLE. */ \ + CENABLE ($r5); \ + mov55 $r6, $r0; /* put mask in safe place. */ \ + POPARGS2_##args; \ + __do_syscall(syscall_name); /* do the call. */ \ + push $r0; \ + cfi_adjust_cfa_offset(4); \ + cfi_rel_offset(r0, 0); \ + addi $sp, $sp, -4; \ + cfi_adjust_cfa_offset(4); \ + mov55 $r0, $r6; /* save syscall return value. */\ + CDISABLE($r5); \ + addi $sp, $sp, 4; \ + cfi_adjust_cfa_offset(-4); \ + pop $r0; /* retrieve return value. */ \ + cfi_adjust_cfa_offset(-4); \ + cfi_restore(r0); \ +50: \ + lmw.bim $r6,[$sp],$r6, 0x2; \ + cfi_adjust_cfa_offset(-8); \ + cfi_restore(lp); \ + cfi_restore(r6); \ + PSEUDO_RET; +# ifndef __ASSEMBLER__ +//# if defined IS_IN_libpthread || !defined NOT_IN_libc +//extern int __local_multiple_threads attribute_hidden; +//# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +//# else +/* There is no __local_multiple_threads for librt */ +# define SINGLE_THREAD_P __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +//# endif +# else +# define SINGLE_THREAD_P(reg) \ + addi reg, $r25, MULTIPLE_THREADS_OFFSET; \ + lw reg, [reg]; +# define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P(x) +# endif + + +# ifdef IS_IN_libpthread +# define CENABLE(reg) jmp(reg, __pthread_enable_asynccancel) +# define CDISABLE(reg) jmp(reg, __pthread_disable_asynccancel) +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE(reg) jmp(reg, __libc_enable_asynccancel) +# define CDISABLE(reg) jmp(reg, __libc_disable_asynccancel) +# define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_librt +# define CENABLE(reg) jmp(reg, __librt_enable_asynccancel) +# define CDISABLE(reg) jmp(reg, __librt_disable_asynccancel) +# else +# error Unsupported library +# endif + +#elif !defined __ASSEMBLER__ + +/* For rtld, et cetera. */ +# define SINGLE_THREAD_P 1 +# define NO_CANCELLATION 1 + +#endif + + + + + + + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif + + + +#ifdef PIC +#define PSEUDO_RET \ + .pic \ + .align 2; \ + bgez $r0, 1f; \ + sltsi $r1, $r0, -4096; \ + bgtz $r1, 1f; \ + PIC_jmp_err \ + nop; \ + 1: +#else /* PIC*/ +#define PSEUDO_RET \ + .align 2; \ + bgez $r0, 1f; \ + sltsi $r1, $r0, -4096; \ + bgtz $r1, 1f; \ + j SYSCALL_ERROR; \ + 1: +#endif + +#ifdef PIC +#define jmp(reg, symble) PIC_jmpr(reg, symble) +/* reg: available register */ +#define PIC_jmp_err \ + smw.adm $sp,[$sp],$sp,#0x6; \ + mfusr $r15, $PC; \ + sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_ + 4); \ + ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_ + 8); \ + add $gp, $r15, $gp; \ + sethi $r15, hi20(SYSCALL_ERROR@PLT); \ + ori $r15, $r15, lo12(SYSCALL_ERROR@PLT); \ + add $r15, $r15, $gp; \ + jral $r15; \ + lmw.bim $sp,[$sp],$sp,#0x6; \ + ret; + +#define PIC_jmp(reg, symble) \ + mfusr $r15, $PC; \ + sethi reg, hi20(_GLOBAL_OFFSET_TABLE_ + 4); \ + ori reg, reg, lo12(_GLOBAL_OFFSET_TABLE_ + 8); \ + add reg, $r15, reg; \ + sethi $r15, hi20(symble@PLT); \ + ori $r15, $r15, lo12(symble@PLT); \ + add $r15, $r15, reg; \ + jr $r15; + + +#define PIC_jmpr(reg, symble) \ + mfusr $r15, $PC; \ + sethi reg, hi20(_GLOBAL_OFFSET_TABLE_ + 4); \ + ori reg, reg, lo12(_GLOBAL_OFFSET_TABLE_ + 8); \ + add reg, $r15, reg; \ + sethi $r15, hi20(symble@PLT); \ + ori $r15, $r15, lo12(symble@PLT); \ + add $r15, $r15, reg; \ + jral $r15; + +#else +#define jmp(reg, symble) jal symble +#endif -- cgit v1.2.3