diff options
Diffstat (limited to 'libc/sysdeps/linux/arc')
-rw-r--r-- | libc/sysdeps/linux/arc/asm.h | 91 | ||||
-rw-r--r-- | libc/sysdeps/linux/arc/bits/atomic.h | 76 | ||||
-rwxr-xr-x | libc/sysdeps/linux/arc/bits/fcntl.h | 3 | ||||
-rw-r--r-- | libc/sysdeps/linux/arc/bits/fenv.h | 75 | ||||
-rw-r--r-- | libc/sysdeps/linux/arc/bits/syscalls.h | 4 | ||||
-rwxr-xr-x | libc/sysdeps/linux/arc/bits/uClibc_arch_features.h | 3 | ||||
-rw-r--r-- | libc/sysdeps/linux/arc/crt1.S | 4 | ||||
-rw-r--r-- | libc/sysdeps/linux/arc/fpu_control.h | 104 |
8 files changed, 352 insertions, 8 deletions
diff --git a/libc/sysdeps/linux/arc/asm.h b/libc/sysdeps/linux/arc/asm.h new file mode 100644 index 000000000..f83075ea1 --- /dev/null +++ b/libc/sysdeps/linux/arc/asm.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2022, Synopsys, Inc. (www.synopsys.com) + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +#ifndef _ARC_ASM_H +#define _ARC_ASM_H + +/* + * Some 16-bit instructions were excluded from the ARCv3 ISA + * the following macros are introduced to handle these changes in one place. + * This will allow not to change existing ARCv2 code and use 16-bit versions + * of instructions for ARCv2 and replace them with 32-bit vesrions for ARCv3 + */ + +#if defined (__ARC64_ARCH32__) + +.macro PUSHR reg + push \reg +.endm + +.macro PUSHR_S reg + push \reg +.endm + +.macro POPR reg + pop \reg +.endm + +.macro POPR_S reg + pop \reg +.endm + +.macro SUBR_S dst,src1,src2 + sub \dst, \src1, \src2 +.endm + +.macro ADDR_S dst,src1,src2 + add \dst, \src1, \src2 +.endm + +.macro ASRR_S dst,src1,src2 + asr \dst, \src1, \src2 +.endm + +.macro ASLR_S dst,src1,src2 + asl \dst, \src1, \src2 +.endm + +#elif defined (__ARC64_ARCH64__) + +# error ARCv3 64-bit is not supported by uClibc-ng + +#else /* ARCHS || ARC700 */ + +.macro PUSHR reg + push \reg +.endm + +.macro PUSHR_S reg + push_s \reg +.endm + +.macro POPR reg + pop \reg +.endm + +.macro POPR_S reg + pop_s \reg +.endm + +.macro SUBR_S dst,src1,src2 + sub_s \dst, \src1, \src2 +.endm + +.macro ADDR_S dst,src1,src2 + add_s \dst, \src1, \src2 +.endm + +.macro ASRR_S dst,src1,src2 + asr_s \dst, \src1, \src2 +.endm + +.macro ASLR_S dst,src1,src2 + asl_s \dst, \src1, \src2 +.endm + +#endif + +#endif /* _ARC_ASM_H */ diff --git a/libc/sysdeps/linux/arc/bits/atomic.h b/libc/sysdeps/linux/arc/bits/atomic.h index 587860964..610b3c7c7 100644 --- a/libc/sysdeps/linux/arc/bits/atomic.h +++ b/libc/sysdeps/linux/arc/bits/atomic.h @@ -26,8 +26,10 @@ void __arc_link_error (void); #ifdef __A7__ #define atomic_full_barrier() __asm__ __volatile__("": : :"memory") +#define ARC_BARRIER_INSTR "" #else #define atomic_full_barrier() __asm__ __volatile__("dmb 3": : :"memory") +#define ARC_BARRIER_INSTR "dmb 3" #endif /* Atomic compare and exchange. */ @@ -38,11 +40,12 @@ void __arc_link_error (void); #define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ ({ __arc_link_error (); oldval; }) -#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ ({ __arc_link_error (); oldval; }) #ifdef __CONFIG_ARC_HAS_ATOMICS__ +#ifdef __A7__ #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ ({ \ __typeof(oldval) prev; \ @@ -60,8 +63,55 @@ void __arc_link_error (void); \ prev; \ }) +#else /* !__A7__ */ +#define USE_ATOMIC_COMPILER_BUILTINS 1 -#else +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ \ + __typeof(*mem) __oldval = (oldval); \ + __atomic_compare_exchange_n(mem, (void *) &__oldval, newval, 0, \ + __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); \ + __oldval; \ + }) + +#define __arch_compare_and_exchange_val_8_rel(mem, newval, oldval) \ + ({ __arc_link_error (); oldval; }) + +#define __arch_compare_and_exchange_val_16_rel(mem, newval, oldval) \ + ({ __arc_link_error (); oldval; }) + +#define __arch_compare_and_exchange_val_64_rel(mem, newval, oldval) \ + ({ __arc_link_error (); oldval; }) + +#define __arch_compare_and_exchange_val_32_rel(mem, newval, oldval) \ + ({ \ + __typeof(*mem) __oldval = (oldval); \ + __atomic_compare_exchange_n(mem, (void *) &__oldval, newval, 0, \ + __ATOMIC_RELEASE, __ATOMIC_RELAXED); \ + __oldval; \ + }) + +/* Compare and exchange with "acquire" semantics, ie barrier after */ +#define atomic_compare_and_exchange_val_acq(mem, new, old) \ + __atomic_val_bysize(__arch_compare_and_exchange_val, acq, \ + mem, new, old) + +/* Compare and exchange with "release" semantics, ie barrier before */ +#define atomic_compare_and_exchange_val_rel(mem, new, old) \ + __atomic_val_bysize(__arch_compare_and_exchange_val, rel, \ + mem, new, old) + +/* Explicitly define here to use release semantics*/ +#define atomic_compare_and_exchange_bool_rel(mem, newval, oldval) \ + ({ \ + __typeof (oldval) __atg3_old = (oldval); \ + atomic_compare_and_exchange_val_rel (mem, newval, __atg3_old) \ + != __atg3_old; \ + }) + +#endif /* __A7__ */ + +#else /* !__CONFIG_ARC_HAS_ATOMICS__ */ #ifndef __NR_arc_usr_cmpxchg #error "__NR_arc_usr_cmpxchg missing: Please upgrade to kernel 4.9+ headers" @@ -101,6 +151,21 @@ void __arc_link_error (void); __typeof__(*(mem)) val = newval; \ \ __asm__ __volatile__( \ + "ex %0, [%1]\n" \ + ARC_BARRIER_INSTR \ + : "+r" (val) \ + : "r" (mem) \ + : "memory" ); \ + \ + val; \ + }) + +#define __arch_exchange_32_rel(mem, newval) \ + ({ \ + __typeof__(*(mem)) val = newval; \ + \ + __asm__ __volatile__( \ + ARC_BARRIER_INSTR"\n" \ "ex %0, [%1]" \ : "+r" (val) \ : "r" (mem) \ @@ -115,3 +180,10 @@ void __arc_link_error (void); abort(); \ __arch_exchange_32_acq(mem, newval); \ }) + +#define atomic_exchange_rel(mem, newval) \ + ({ \ + if (sizeof(*(mem)) != 4) \ + abort(); \ + __arch_exchange_32_rel(mem, newval); \ + }) diff --git a/libc/sysdeps/linux/arc/bits/fcntl.h b/libc/sysdeps/linux/arc/bits/fcntl.h index beb32e41e..b02849691 100755 --- a/libc/sysdeps/linux/arc/bits/fcntl.h +++ b/libc/sysdeps/linux/arc/bits/fcntl.h @@ -230,3 +230,6 @@ extern ssize_t tee (int __fdin, int __fdout, size_t __len, #endif __END_DECLS + +/* Include generic Linux declarations. */ +#include <bits/fcntl-linux.h> diff --git a/libc/sysdeps/linux/arc/bits/fenv.h b/libc/sysdeps/linux/arc/bits/fenv.h new file mode 100644 index 000000000..c5c76cb93 --- /dev/null +++ b/libc/sysdeps/linux/arc/bits/fenv.h @@ -0,0 +1,75 @@ +/* Floating point environment. ARC version. + Copyright (C) 2020-2025 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 + <https://www.gnu.org/licenses/>. */ + +#ifndef _FENV_H +# error "Never use <bits/fenv.h> directly; include <fenv.h> instead." +#endif + +enum + { + FE_INVALID = +# define FE_INVALID (0x01) + FE_INVALID, + FE_DIVBYZERO = +# define FE_DIVBYZERO (0x02) + FE_DIVBYZERO, + FE_OVERFLOW = +# define FE_OVERFLOW (0x04) + FE_OVERFLOW, + FE_UNDERFLOW = +# define FE_UNDERFLOW (0x08) + FE_UNDERFLOW, + FE_INEXACT = +# define FE_INEXACT (0x10) + FE_INEXACT + }; + +# define FE_ALL_EXCEPT \ + (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) + +enum + { + FE_TOWARDZERO = +# define FE_TOWARDZERO (0x0) + FE_TOWARDZERO, + FE_TONEAREST = +# define FE_TONEAREST (0x1) /* default */ + FE_TONEAREST, + FE_UPWARD = +# define FE_UPWARD (0x2) + FE_UPWARD, + FE_DOWNWARD = +# define FE_DOWNWARD (0x3) + FE_DOWNWARD + }; + +typedef unsigned int fexcept_t; + +typedef struct +{ + unsigned int __fpcr; + unsigned int __fpsr; +} fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((const fenv_t *) -1) + +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) diff --git a/libc/sysdeps/linux/arc/bits/syscalls.h b/libc/sysdeps/linux/arc/bits/syscalls.h index c858d788b..000b6b631 100644 --- a/libc/sysdeps/linux/arc/bits/syscalls.h +++ b/libc/sysdeps/linux/arc/bits/syscalls.h @@ -100,7 +100,7 @@ extern long __syscall_error (int); #ifdef __A7__ #define ARC_TRAP_INSN "trap0 \n\t" -#elif defined(__HS__) +#else #define ARC_TRAP_INSN "trap_s 0 \n\t" #endif @@ -182,7 +182,7 @@ extern long __syscall_error (int); #ifdef __A7__ #define ARC_TRAP_INSN trap0 -#elif defined(__HS__) +#else #define ARC_TRAP_INSN trap_s 0 #endif diff --git a/libc/sysdeps/linux/arc/bits/uClibc_arch_features.h b/libc/sysdeps/linux/arc/bits/uClibc_arch_features.h index 119bbb7e1..94e089d5d 100755 --- a/libc/sysdeps/linux/arc/bits/uClibc_arch_features.h +++ b/libc/sysdeps/linux/arc/bits/uClibc_arch_features.h @@ -17,9 +17,6 @@ /* can your target use syscall6() for mmap ? */ #undef __UCLIBC_MMAP_HAS_6_ARGS__ -/* does your target use statx */ -#undef __UCLIBC_HAVE_STATX__ - /* does your target have a broken create_module() ? */ #undef __UCLIBC_BROKEN_CREATE_MODULE__ diff --git a/libc/sysdeps/linux/arc/crt1.S b/libc/sysdeps/linux/arc/crt1.S index 70a06e058..ff36d252e 100644 --- a/libc/sysdeps/linux/arc/crt1.S +++ b/libc/sysdeps/linux/arc/crt1.S @@ -40,7 +40,9 @@ __start: ld_s r1, [sp] ; argc mov_s r5, r0 ; rltd_fini - add_s r2, sp, 4 ; argv + /* Use the universal 32-bit add instruction as 16-bit add_s was excluded from + ARCv3 ISA */ + add r2, sp, 4 ; argv #ifdef L_Scrt1 ld r0, [pcl, @main@gotpc] ld r3, [pcl, @_init@gotpc] diff --git a/libc/sysdeps/linux/arc/fpu_control.h b/libc/sysdeps/linux/arc/fpu_control.h new file mode 100644 index 000000000..e833de3aa --- /dev/null +++ b/libc/sysdeps/linux/arc/fpu_control.h @@ -0,0 +1,104 @@ +/* FPU control word bits. ARC version. + Copyright (C) 2020-2025 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 + <https://www.gnu.org/licenses/>. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +/* ARC FPU control register bits. + + [ 0] -> IVE: Enable invalid operation exception. + if 0, soft exception: status register IV flag set. + if 1, hardware exception trap (not supported in Linux yet). + [ 1] -> DZE: Enable division by zero exception. + if 0, soft exception: status register IV flag set. + if 1, hardware exception: (not supported in Linux yet). + [9:8] -> RM: Rounding Mode: + 00 - Rounding toward zero. + 01 - Rounding to nearest (default). + 10 - Rounding (up) toward plus infinity. + 11 - Rounding (down)toward minus infinity. + + ARC FPU status register bits. + + [ 0] -> IV: flag invalid operation. + [ 1] -> DZ: flag division by zero. + [ 2] -> OV: flag Overflow operation. + [ 3] -> UV: flag Underflow operation. + [ 4] -> IX: flag Inexact operation. + [31] -> FWE: Flag Write Enable. + If 1, above flags writable explicitly (clearing), + else IoW and only writable indirectly via bits [12:7]. */ + +#include <features.h> + +#if !defined(__ARC_FPU_SP__) && !defined(__ARC_FPU_DP__) + +# define _FPU_RESERVED 0xffffffff +# define _FPU_DEFAULT 0x00000000 +typedef unsigned int fpu_control_t; +# define _FPU_GETCW(cw) (cw) = 0 +# define _FPU_SETCW(cw) (void) (cw) +# define _FPU_GETS(cw) (cw) = 0 +# define _FPU_SETS(cw) (void) (cw) +extern fpu_control_t __fpu_control; + +#else + +#define _FPU_RESERVED 0 + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. + So only RM set to b'01. */ +# define _FPU_DEFAULT 0x00000100 + +/* Actually default needs to have FWE bit as 1 but that is already + ingrained into _FPU_SETS macro below. */ +#define _FPU_FPSR_DEFAULT 0x00000000 + +#define __FPU_RND_SHIFT 8 +#define __FPU_RND_MASK 0x3 + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +# define _FPU_GETCW(cw) __asm__ volatile ("lr %0, [0x300]" : "=r" (cw)) +# define _FPU_SETCW(cw) __asm__ volatile ("sr %0, [0x300]" : : "r" (cw)) + +/* Macros for accessing the hardware status word. + Writing to FPU_STATUS requires a "control" bit FWE to be able to set the + exception flags directly (as opposed to side-effects of FP instructions). + That is done in the macro here to keeps callers agnostic of this detail. + And given FWE is write-only and RAZ, no need to "clear" it in _FPU_GETS + macro. */ +# define _FPU_GETS(cw) \ + __asm__ volatile ("lr %0, [0x301] \r\n" \ + : "=r" (cw)) + +# define _FPU_SETS(cw) \ + do { \ + unsigned int __fwe = 0x80000000 | (cw); \ + __asm__ volatile ("sr %0, [0x301] \r\n" \ + : : "r" (__fwe)); \ + } while (0) + +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; + +#endif + +#endif /* fpu_control.h */ |