diff options
Diffstat (limited to 'libc')
43 files changed, 1315 insertions, 494 deletions
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index d7a659a8c..44685e6b8 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -1892,7 +1892,7 @@ int getnameinfo(const struct sockaddr *sa, socklen_t hostlen, char *serv, socklen_t servlen, - unsigned flags) + int flags) { int serrno = errno; bool ok = 0; @@ -2699,7 +2699,7 @@ int gethostent_r(struct hostent *result_buf, char *buf, size_t buflen, hostp = __open_etc_hosts(); if (hostp == NULL) { *result = NULL; - ret = TRY_AGAIN; + *h_errnop = ret = TRY_AGAIN; goto DONE; } } diff --git a/libc/misc/auxvt/getauxval.c b/libc/misc/auxvt/getauxval.c index 2bdffaf2c..7610b7e5c 100755 --- a/libc/misc/auxvt/getauxval.c +++ b/libc/misc/auxvt/getauxval.c @@ -17,32 +17,28 @@ * <http://www.gnu.org/licenses/>. */ -#include "errno.h" -#include "ldso.h" -#include "sys/auxv.h" +#include <errno.h> +#include <ldso.h> +#include <sys/auxv.h> - -/* - * - * aarch64 gcc 11 uses __getauxval() in init_have_lse_atomics() - * - */ unsigned long int __getauxval (unsigned long int __type) { - if ( __type >= AUX_MAX_AT_ID ){ + // Requested value part of cached subset of auxiliary vector? + if (__type < AUX_MAX_AT_ID) { + if (_dl_auxvt[__type].a_type == __type) + return _dl_auxvt[__type].a_un.a_val; + __set_errno (ENOENT); return 0; } - if ( _dl_auxvt[__type].a_type == __type){ - return _dl_auxvt[__type].a_un.a_val; - } + // Otherwise we have to iterate the auxiliary vector. + for (ElfW(auxv_t) *entry = _dl_auxv_start; entry->a_type != AT_NULL; entry++) + if (entry->a_type == __type) + return entry->a_un.a_val; __set_errno (ENOENT); return 0; } -unsigned long int getauxval (unsigned long int __type){ - return __getauxval( __type ); -} - +weak_alias(__getauxval, getauxval) diff --git a/libc/misc/elf/dl-support.c b/libc/misc/elf/dl-support.c index 87cd1bb72..09cbefc18 100644 --- a/libc/misc/elf/dl-support.c +++ b/libc/misc/elf/dl-support.c @@ -12,6 +12,7 @@ */ #include <link.h> +#include <ldso.h> #include <elf.h> #if defined(USE_TLS) && USE_TLS #include <assert.h> @@ -31,17 +32,29 @@ ElfW(Phdr) *_dl_phdr; size_t _dl_phnum; size_t _dl_pagesize; +ElfW(auxv_t) _dl_auxvt[AUX_MAX_AT_ID]; +ElfW(auxv_t) *_dl_auxv_start; + void internal_function _dl_aux_init (ElfW(auxv_t) *av); void internal_function _dl_aux_init (ElfW(auxv_t) *av) { + _dl_auxv_start = av; + + memset(_dl_auxvt, 0x00, sizeof(_dl_auxvt)); + for (; av->a_type != AT_NULL; av++) + { + if (av->a_type < AUX_MAX_AT_ID) + _dl_auxvt[av->a_type] = *av; + } + /* Get the program headers base address from the aux vect */ - _dl_phdr = (ElfW(Phdr) *) av[AT_PHDR].a_un.a_val; + _dl_phdr = (ElfW(Phdr) *) _dl_auxvt[AT_PHDR].a_un.a_val; /* Get the number of program headers from the aux vect */ - _dl_phnum = (size_t) av[AT_PHNUM].a_un.a_val; + _dl_phnum = (size_t) _dl_auxvt[AT_PHNUM].a_un.a_val; /* Get the pagesize from the aux vect */ - _dl_pagesize = (av[AT_PAGESZ].a_un.a_val) ? (size_t) av[AT_PAGESZ].a_un.a_val : PAGE_SIZE; + _dl_pagesize = (_dl_auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) _dl_auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE; } #if defined(USE_TLS) && USE_TLS diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index 64a9c8214..60695b6ed 100644 --- a/libc/misc/internals/__uClibc_main.c +++ b/libc/misc/internals/__uClibc_main.c @@ -43,7 +43,7 @@ /* Are we in a secure process environment or are we dealing * with setuid stuff? If we are dynamically linked, then we * already have _dl_secure, otherwise we need to re-examine - * auxvt[] below. + * _dl_auxvt[] below. */ int _pe_secure = 0; libc_hidden_data_def(_pe_secure) @@ -84,6 +84,8 @@ static void fdpic_init_array_jump(void *addr) #ifndef SHARED void *__libc_stack_end = NULL; +#include "dl-auxvt.h" + # ifdef __UCLIBC_HAS_SSP__ # include <dl-osinfo.h> static uintptr_t stack_chk_guard; @@ -373,7 +375,6 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, { #ifndef SHARED unsigned long *aux_dat; - ElfW(auxv_t) auxvt[AT_EGID + 1]; #endif #ifdef __UCLIBC_HAS_THREADS_NATIVE__ @@ -399,23 +400,14 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, #ifndef SHARED /* Pull stuff from the ELF header when possible */ - memset(auxvt, 0x00, sizeof(auxvt)); aux_dat = (unsigned long*)__environ; while (*aux_dat) { aux_dat++; } aux_dat++; - while (*aux_dat) { - ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat; - if (auxv_entry->a_type <= AT_EGID) { - memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t))); - } - aux_dat += 2; - } /* Get the program headers (_dl_phdr) from the aux vector It will be used into __libc_setup_tls. */ - - _dl_aux_init (auxvt); + _dl_aux_init ((ElfW(auxv_t) *)aux_dat); #endif /* We need to initialize uClibc. If we are dynamically linked this @@ -431,10 +423,10 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, #ifndef SHARED /* Prevent starting SUID binaries where the stdin. stdout, and * stderr file descriptors are not already opened. */ - if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && __check_suid()) || - (auxvt[AT_UID].a_un.a_val != (size_t)-1 && - (auxvt[AT_UID].a_un.a_val != auxvt[AT_EUID].a_un.a_val || - auxvt[AT_GID].a_un.a_val != auxvt[AT_EGID].a_un.a_val))) + if ((_dl_auxvt[AT_UID].a_un.a_val == (size_t)-1 && __check_suid()) || + (_dl_auxvt[AT_UID].a_un.a_val != (size_t)-1 && + (_dl_auxvt[AT_UID].a_un.a_val != _dl_auxvt[AT_EUID].a_un.a_val || + _dl_auxvt[AT_GID].a_un.a_val != _dl_auxvt[AT_EGID].a_un.a_val))) #else if (_dl_secure) #endif diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c index cb2c4df87..3bbdef18e 100644 --- a/libc/misc/internals/reloc_static_pie.c +++ b/libc/misc/internals/reloc_static_pie.c @@ -107,6 +107,8 @@ reloc_static_pie(ElfW(Addr) load_addr) PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym); } } +#else + (void)rel_size; #endif } _dl_load_base = load_addr; diff --git a/libc/stdio/_scanf.c b/libc/stdio/_scanf.c index 3f3000d6f..cb72d14ac 100644 --- a/libc/stdio/_scanf.c +++ b/libc/stdio/_scanf.c @@ -1715,7 +1715,7 @@ int attribute_hidden __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) #define MAX_DIGITS 65 /* Allow one leading 0. */ unsigned char buf[MAX_DIGITS+2+ 100]; unsigned char usflag, base; - unsigned char nonzero = 0; + unsigned char nonzero __attribute__((unused)) = 0; unsigned char seendigit = 0; #ifndef __UCLIBC_HAS_FLOATS__ diff --git a/libc/stdlib/stdlib.c b/libc/stdlib/stdlib.c index f5936630c..c45dd53a5 100644 --- a/libc/stdlib/stdlib.c +++ b/libc/stdlib/stdlib.c @@ -822,6 +822,7 @@ libc_hidden_def(_stdlib_mb_cur_max) #endif +#if defined(L_mblen) || defined(L_mbtowc) || defined(L_wctomb) #ifdef __UCLIBC_HAS_LOCALE__ /* * The following function return 1 if the encoding is stateful, 0 if stateless. @@ -844,6 +845,7 @@ static __always_inline int is_stateful(unsigned char encoding) #else #define is_stateful(encoding) 0 #endif +#endif /**********************************************************************/ #ifdef L_mblen diff --git a/libc/string/generic/strnlen.c b/libc/string/generic/strnlen.c index 4d4cde84f..82d4122ec 100644 --- a/libc/string/generic/strnlen.c +++ b/libc/string/generic/strnlen.c @@ -29,15 +29,17 @@ '\0' terminator is found in that many characters, return MAXLEN. */ size_t strnlen (const char *str, size_t maxlen) { - const char *char_ptr, *end_ptr = str + maxlen; + const char *char_ptr, *end_ptr; const unsigned long int *longword_ptr; unsigned long int longword, himagic, lomagic; if (maxlen == 0) return 0; - if (__builtin_expect (end_ptr < str, 0)) + if (__builtin_expect ((uintptr_t)str + maxlen < (uintptr_t)str, 0)) end_ptr = (const char *) ~0UL; + else + end_ptr = str + maxlen; /* Handle the first few characters by reading one character at a time. Do this until CHAR_PTR is aligned on a longword boundary. */ diff --git a/libc/string/x86_64/strcat.S b/libc/string/x86_64/strcat.S index 55e09e5f1..209e19062 100644 --- a/libc/string/x86_64/strcat.S +++ b/libc/string/x86_64/strcat.S @@ -106,7 +106,7 @@ ENTRY (BP_SYM (strcat)) /* Align, it is a jump target. */ /* Next 3 insns are 8 bytes total, make sure we decode them in one go */ - .p2align 3,,8 + .p2align 3,,7 3: subq $8,%rax /* correct pointer increment. */ diff --git a/libc/string/x86_64/strcspn.S b/libc/string/x86_64/strcspn.S index 7a06c8867..5ef565db7 100644 --- a/libc/string/x86_64/strcspn.S +++ b/libc/string/x86_64/strcspn.S @@ -94,7 +94,7 @@ L(1): leaq -4(%rdx), %rax /* prepare loop */ /* but it will also align entire function to 16 bytes, */ /* potentially creating largish padding at link time. */ /* We are aligning to 8 bytes instead: */ - .p2align 3,,8 + .p2align 3,,7 L(3): addq $4, %rax /* adjust pointer for full loop round */ diff --git a/libc/string/x86_64/strlen.S b/libc/string/x86_64/strlen.S index 9e84326c2..2fe2f58b2 100644 --- a/libc/string/x86_64/strlen.S +++ b/libc/string/x86_64/strlen.S @@ -102,7 +102,7 @@ ENTRY (strlen) /* Align, it is a jump target. */ /* Next 3 insns are 8 bytes total, make sure we decode them in one go */ - .p2align 3,,8 + .p2align 3,,7 3: subq $8,%rax /* correct pointer increment. */ diff --git a/libc/string/x86_64/strspn.S b/libc/string/x86_64/strspn.S index 366377649..8dc42656b 100644 --- a/libc/string/x86_64/strspn.S +++ b/libc/string/x86_64/strspn.S @@ -89,7 +89,7 @@ L(1): leaq -4(%rdx), %rax /* prepare loop */ /* but it will also align entire function to 16 bytes, */ /* potentially creating largish padding at link time. */ /* We are aligning to 8 bytes instead: */ - .p2align 3,,8 + .p2align 3,,7 L(3): addq $4, %rax /* adjust pointer for full loop round */ diff --git a/libc/sysdeps/linux/aarch64/bits/fenv.h b/libc/sysdeps/linux/aarch64/bits/fenv.h new file mode 100644 index 000000000..4febd2177 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/fenv.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2004-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 + +/* Define bits representing exceptions in the FPSR status word. */ +enum + { + FE_INVALID = +#define FE_INVALID 1 + FE_INVALID, + FE_DIVBYZERO = +#define FE_DIVBYZERO 2 + FE_DIVBYZERO, + FE_OVERFLOW = +#define FE_OVERFLOW 4 + FE_OVERFLOW, + FE_UNDERFLOW = +#define FE_UNDERFLOW 8 + FE_UNDERFLOW, + FE_INEXACT = +#define FE_INEXACT 16 + FE_INEXACT, + }; + +/* Amount to shift by to convert an exception bit in FPSR to a an + exception bit mask in FPCR. */ +#define FE_EXCEPT_SHIFT 8 + +/* All supported exceptions. */ +#define FE_ALL_EXCEPT \ + (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) + +/* Define bits representing rounding modes in the FPCR Rmode field. */ +#define FE_TONEAREST 0x000000 +#define FE_UPWARD 0x400000 +#define FE_DOWNWARD 0x800000 +#define FE_TOWARDZERO 0xc00000 + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + +/* Type representing floating-point environment. */ +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 *) -1l) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exceptions are masked. */ +# define FE_NOMASK_ENV ((const fenv_t *) -2) +#endif + +/* 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/aarch64/crt1.S b/libc/sysdeps/linux/aarch64/crt1.S index e9f946894..965d3265d 100644 --- a/libc/sysdeps/linux/aarch64/crt1.S +++ b/libc/sysdeps/linux/aarch64/crt1.S @@ -52,8 +52,8 @@ _start: /* Save off the atexit pointer */ mov x19, x0 - /* Calculate load address... idk how this works, but it does */ - adrp x0, _start + /* "Calculate" load address. The link address of __ehdr_start is 0. */ + adrp x0, __ehdr_start /* Do relocations */ bl reloc_static_pie diff --git a/libc/sysdeps/linux/aarch64/fpu_control.h b/libc/sysdeps/linux/aarch64/fpu_control.h new file mode 100644 index 000000000..c3e7f6629 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/fpu_control.h @@ -0,0 +1,102 @@ +/* Copyright (C) 1996-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 _AARCH64_FPU_CONTROL_H +#define _AARCH64_FPU_CONTROL_H + +#include <features.h> + +/* Macros for accessing the FPCR and FPSR. */ + +#if __GNUC_PREREQ (6,0) +# define _FPU_GETCW(fpcr) (fpcr = __builtin_aarch64_get_fpcr ()) +# define _FPU_SETCW(fpcr) __builtin_aarch64_set_fpcr (fpcr) +# define _FPU_GETFPSR(fpsr) (fpsr = __builtin_aarch64_get_fpsr ()) +# define _FPU_SETFPSR(fpsr) __builtin_aarch64_set_fpsr (fpsr) +#else +# define _FPU_GETCW(fpcr) \ + ({ \ + __uint64_t __fpcr; \ + __asm__ __volatile__ ("mrs %0, fpcr" : "=r" (__fpcr)); \ + fpcr = __fpcr; \ + }) + +# define _FPU_SETCW(fpcr) \ + ({ \ + __uint64_t __fpcr = fpcr; \ + __asm__ __volatile__ ("msr fpcr, %0" : : "r" (__fpcr)); \ + }) + +# define _FPU_GETFPSR(fpsr) \ + ({ \ + __uint64_t __fpsr; \ + __asm__ __volatile__ ("mrs %0, fpsr" : "=r" (__fpsr)); \ + fpsr = __fpsr; \ + }) + +# define _FPU_SETFPSR(fpsr) \ + ({ \ + __uint64_t __fpsr = fpsr; \ + __asm__ __volatile__ ("msr fpsr, %0" : : "r" (__fpsr)); \ + }) +#endif + +/* Reserved bits should be preserved when modifying register + contents. These two masks indicate which bits in each of FPCR and + FPSR should not be changed. */ + +#define _FPU_RESERVED 0xfe0fe0f8 +#define _FPU_FPSR_RESERVED 0x0fffffe0 + +#define _FPU_DEFAULT 0x00000000 +#define _FPU_FPSR_DEFAULT 0x00000000 + +/* Layout of FPCR and FPSR: + + | | | | | | | | + 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 + s s s s s s s s s s s + c c c c c c c c c c c c + N Z C V Q A D F R R S S S L L L I U U I U O D I I U U I U O D I + C H N Z M M T T B E E E D N N X F F Z O D N N X F F Z O + P O O R R Z N N N E K K E E E E E C K K C C C C C + D D I I P + E E D D + E E + */ + +#define _FPU_FPCR_RM_MASK 0xc00000 + +#define _FPU_FPCR_MASK_IXE 0x1000 +#define _FPU_FPCR_MASK_UFE 0x0800 +#define _FPU_FPCR_MASK_OFE 0x0400 +#define _FPU_FPCR_MASK_DZE 0x0200 +#define _FPU_FPCR_MASK_IOE 0x0100 + +#define _FPU_FPCR_IEEE \ + (_FPU_DEFAULT | _FPU_FPCR_MASK_IXE \ + | _FPU_FPCR_MASK_UFE | _FPU_FPCR_MASK_OFE \ + | _FPU_FPCR_MASK_DZE | _FPU_FPCR_MASK_IOE) + +#define _FPU_FPSR_IEEE 0 + +typedef unsigned int fpu_control_t; +typedef unsigned int fpu_fpsr_t; + +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; + +#endif 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/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 */ diff --git a/libc/sysdeps/linux/arm/bits/fenv.h b/libc/sysdeps/linux/arm/bits/fenv.h index 106bf36c2..ab60b9e70 100644 --- a/libc/sysdeps/linux/arm/bits/fenv.h +++ b/libc/sysdeps/linux/arm/bits/fenv.h @@ -1,5 +1,4 @@ -/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. - This file is part of the GNU C Library. +/* Copyright (C) 2004-2025 Free Software Foundation, Inc. The GNU C |