summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Rules.mak14
-rw-r--r--extra/Configs/Config.in.arch11
-rw-r--r--extra/scripts/unifdef.c12
-rw-r--r--include/fenv.h10
-rw-r--r--include/internal/time64_helpers.h5
-rw-r--r--include/libintl.h3
-rw-r--r--include/netdb.h2
-rw-r--r--include/pty.h6
-rw-r--r--include/spawn.h1
-rw-r--r--include/stdint.h8
-rw-r--r--include/stdlib.h4
-rw-r--r--include/sys/mount.h25
-rw-r--r--include/unistd.h9
-rw-r--r--ldso/include/dl-auxvt.h9
-rwxr-xr-xldso/include/ldso.h3
-rw-r--r--ldso/ldso/Makefile.in5
-rw-r--r--ldso/ldso/aarch64/dl-sysdep.h25
-rw-r--r--ldso/ldso/aarch64/elfinterp.c4
-rw-r--r--ldso/ldso/arm/dl-sysdep.h69
-rw-r--r--ldso/ldso/dl-elf.c2
-rw-r--r--ldso/ldso/dl-startup.c6
-rw-r--r--ldso/ldso/i386/dl-sysdep.h27
-rw-r--r--ldso/ldso/m68k/elfinterp.c4
-rw-r--r--ldso/ldso/riscv32/dl-sysdep.h22
-rw-r--r--ldso/ldso/x86_64/dl-sysdep.h45
-rw-r--r--libc/inet/resolv.c4
-rwxr-xr-xlibc/misc/auxvt/getauxval.c30
-rw-r--r--libc/misc/elf/dl-support.c19
-rw-r--r--libc/misc/internals/__uClibc_main.c24
-rw-r--r--libc/misc/internals/reloc_static_pie.c2
-rw-r--r--libc/misc/sysvipc/ipc.h9
-rw-r--r--libc/misc/sysvipc/msgq.c21
-rw-r--r--libc/misc/sysvipc/sem.c11
-rw-r--r--libc/misc/sysvipc/shm.c19
-rw-r--r--libc/stdio/_scanf.c2
-rw-r--r--libc/stdlib/malloc-standard/malloc.c10
-rw-r--r--libc/stdlib/stdlib.c2
-rw-r--r--libc/string/generic/strnlen.c6
-rw-r--r--libc/string/x86_64/strcat.S2
-rw-r--r--libc/string/x86_64/strcspn.S2
-rw-r--r--libc/string/x86_64/strlen.S2
-rw-r--r--libc/string/x86_64/strspn.S2
-rw-r--r--libc/sysdeps/linux/aarch64/bits/fenv.h78
-rw-r--r--libc/sysdeps/linux/aarch64/bits/shm.h87
-rw-r--r--libc/sysdeps/linux/aarch64/crt1.S4
-rw-r--r--libc/sysdeps/linux/aarch64/fpu_control.h102
-rw-r--r--libc/sysdeps/linux/arc/bits/fenv.h75
-rw-r--r--libc/sysdeps/linux/arc/fpu_control.h104
-rw-r--r--libc/sysdeps/linux/arm/bits/fenv.h107
-rw-r--r--libc/sysdeps/linux/arm/bits/shm.h6
-rw-r--r--libc/sysdeps/linux/arm/crt1.S15
-rw-r--r--libc/sysdeps/linux/arm/fpu_control.h192
-rw-r--r--libc/sysdeps/linux/common/Makefile.in1
-rw-r--r--libc/sysdeps/linux/common/bits/msq.h14
-rw-r--r--libc/sysdeps/linux/common/bits/nan.h4
-rw-r--r--libc/sysdeps/linux/common/bits/sem.h8
-rw-r--r--libc/sysdeps/linux/common/clock_adjtime.c2
-rw-r--r--libc/sysdeps/linux/common/getentropy.c46
-rw-r--r--libc/sysdeps/linux/common/getrandom.c3
-rw-r--r--libc/sysdeps/linux/common/sys/random.h18
-rw-r--r--libc/sysdeps/linux/common/utimes.c4
-rw-r--r--libc/sysdeps/linux/csky/bits/fenv.h123
-rw-r--r--libc/sysdeps/linux/csky/fpu_control.h147
-rw-r--r--libc/sysdeps/linux/kvx/bits/shm.h87
-rw-r--r--libc/sysdeps/linux/m68k/bits/fenv.h98
-rw-r--r--libc/sysdeps/linux/m68k/bits/shm.h108
-rw-r--r--libc/sysdeps/linux/m68k/bsd-_setjmp.S4
-rw-r--r--libc/sysdeps/linux/m68k/bsd-setjmp.S4
-rw-r--r--libc/sysdeps/linux/m68k/fpu_control.h77
-rw-r--r--libc/sysdeps/linux/m68k/setjmp.S4
-rw-r--r--libc/sysdeps/linux/mips/bits/fenv.h82
-rw-r--r--libc/sysdeps/linux/mips/bits/msq.h94
-rw-r--r--libc/sysdeps/linux/mips/bits/sem.h11
-rw-r--r--libc/sysdeps/linux/mips/bits/shm.h28
-rw-r--r--libc/sysdeps/linux/mips/bits/syscalls.h36
-rw-r--r--libc/sysdeps/linux/mips/fpu_control.h68
-rw-r--r--libc/sysdeps/linux/or1k/bits/fenv.h84
-rw-r--r--libc/sysdeps/linux/or1k/fpu_control.h88
-rw-r--r--libc/sysdeps/linux/riscv32/bits/fenv.h2
-rw-r--r--libc/sysdeps/linux/riscv32/bits/shm.h6
-rw-r--r--libc/sysdeps/linux/riscv64/bits/fenv.h2
-rw-r--r--libc/sysdeps/linux/riscv64/bits/shm.h7
-rw-r--r--libc/sysdeps/linux/sh/bits/fenv.h60
-rw-r--r--libc/sysdeps/linux/sh/fpu_control.h30
-rw-r--r--libc/sysdeps/linux/sparc/bits/fenv.h60
-rw-r--r--libc/sysdeps/linux/sparc/fpu_control.h24
-rw-r--r--libc/sysdeps/linux/x86_64/crt1.S6
-rw-r--r--libm/aarch64/Makefile.arch16
-rw-r--r--libm/aarch64/fclrexcpt.c35
-rw-r--r--libm/aarch64/fedisblxcpt.c34
-rw-r--r--libm/aarch64/feenablxcpt.c45
-rw-r--r--libm/aarch64/fegetenv.c30
-rw-r--r--libm/aarch64/fegetexcept.c26
-rw-r--r--libm/aarch64/fegetmode.c26
-rw-r--r--libm/aarch64/fegetround.c35
-rw-r--r--libm/aarch64/feholdexcpt.c25
-rw-r--r--libm/aarch64/fenv_private.h300
-rw-r--r--libm/aarch64/fesetenv.c73
-rw-r--r--libm/aarch64/fesetexcept.c33
-rw-r--r--libm/aarch64/fesetmode.c33
-rw-r--r--libm/aarch64/fesetround.c29
-rw-r--r--libm/aarch64/feupdateenv.c84
-rw-r--r--libm/aarch64/fgetexcptflg.c25
-rw-r--r--libm/aarch64/fraiseexcpt.c89
-rw-r--r--libm/aarch64/fsetexcptflg.c39
-rw-r--r--libm/aarch64/ftestexcept.c24
-rw-r--r--libm/arc/Makefile.arch16
-rw-r--r--libm/arc/fclrexcpt.c34
-rw-r--r--libm/arc/fegetenv.c33
-rw-r--r--libm/arc/fegetmode.c30
-rw-r--r--libm/arc/fegetround.c28
-rw-r--r--libm/arc/feholdexcpt.c39
-rw-r--r--libm/arc/fenv_private.h326
-rw-r--r--libm/arc/fesetenv.c44
-rw-r--r--libm/arc/fesetexcept.c31
-rw-r--r--libm/arc/fesetmode.c39
-rw-r--r--libm/arc/fesetround.c36
-rw-r--r--libm/arc/feupdateenv.c47
-rw-r--r--libm/arc/fgetexcptflg.c30
-rw-r--r--libm/arc/fraiseexcpt.c35
-rw-r--r--libm/arc/fsetexcptflg.c37
-rw-r--r--libm/arc/ftestexcept.c31
-rw-r--r--libm/arc/get-rounding-mode.h37
-rw-r--r--libm/arm/Makefile.arch16
-rw-r--r--libm/arm/arm-features.h58
-rw-r--r--libm/arm/fclrexcpt.c41
-rw-r--r--libm/arm/fedisblxcpt.c41
-rw-r--r--libm/arm/feenablxcpt.c49
-rw-r--r--libm/arm/fegetenv.c35
-rw-r--r--libm/arm/fegetexcept.c35
-rw-r--r--libm/arm/fegetmode.c28
-rw-r--r--libm/arm/fegetround.c42
-rw-r--r--libm/arm/feholdexcpt.c31
-rw-r--r--libm/arm/fenv_private.h248
-rw-r--r--libm/arm/fesetenv.c62
-rw-r--r--libm/arm/fesetexcept.c37
-rw-r--r--libm/arm/fesetmode.c44
-rw-r--r--libm/arm/fesetround.c35
-rw-r--r--libm/arm/feupdateenv.c73
-rw-r--r--libm/arm/fgetexcptflg.c31
-rw-r--r--libm/arm/fraiseexcpt.c103
-rw-r--r--libm/arm/fsetexcptflg.c44
-rw-r--r--libm/arm/ftestexcept.c30
-rw-r--r--libm/csky/Makefile.arch16
-rw-r--r--libm/csky/fclrexcpt.c40
-rw-r--r--libm/csky/fedisblxcpt.c40
-rw-r--r--libm/csky/feenablxcpt.c39
-rw-r--r--libm/csky/fegetenv.c33
-rw-r--r--libm/csky/fegetexcept.c31
-rw-r--r--libm/csky/fegetmode.c27
-rw-r--r--libm/csky/fegetround.c30
-rw-r--r--libm/csky/feholdexcpt.c30
-rw-r--r--libm/csky/fenv_libc.h29
-rw-r--r--libm/csky/fenv_private.h277
-rw-r--r--libm/csky/fesetenv.c55
-rw-r--r--libm/csky/fesetexcept.c32
-rw-r--r--libm/csky/fesetmode.c32
-rw-r--r--libm/csky/fesetround.c28
-rw-r--r--libm/csky/feupdateenv.c42
-rw-r--r--libm/csky/fgetexcptflg.c31
-rw-r--r--libm/csky/fraiseexcpt.c122
-rw-r--r--libm/csky/fsetexcptflg.c42
-rw-r--r--libm/csky/ftestexcept.c28
-rw-r--r--libm/m68k/Makefile.arch16
-rw-r--r--libm/m68k/fclrexcpt.c39
-rw-r--r--libm/m68k/fedisblxcpt.c36
-rw-r--r--libm/m68k/feenablxcpt.c36
-rw-r--r--libm/m68k/fegetenv.c33
-rw-r--r--libm/m68k/fegetexcept.c29
-rw-r--r--libm/m68k/fegetmode.c26
-rw-r--r--libm/m68k/fegetround.c28
-rw-r--r--libm/m68k/feholdexcpt.c42
-rw-r--r--libm/m68k/fesetenv.c63
-rw-r--r--libm/m68k/fesetexcept.c30
-rw-r--r--libm/m68k/fesetmode.c31
-rw-r--r--libm/m68k/fesetround.c35
-rw-r--r--libm/m68k/feupdateenv.c39
-rw-r--r--libm/m68k/fgetexcptflg.c32
-rw-r--r--libm/m68k/fraiseexcpt.c106
-rw-r--r--libm/m68k/fsetexcptflg.c38
-rw-r--r--libm/m68k/ftestexcept.c29
-rw-r--r--libm/mips/Makefile.arch16
-rw-r--r--libm/mips/fclrexcpt.c44
-rw-r--r--libm/mips/fedisblxcpt.c38
-rw-r--r--libm/mips/feenablxcpt.c38
-rw-r--r--libm/mips/fegetenv.c28
-rw-r--r--libm/mips/fegetexcept.c31
-rw-r--r--libm/mips/fegetmode.c26
-rw-r--r--libm/mips/fegetround.c30
-rw-r--r--libm/mips/feholdexcpt.c35
-rw-r--r--libm/mips/fenv_libc.h29
-rw-r--r--libm/mips/fenv_private.h238
-rw-r--r--libm/mips/fesetenv.c38
-rw-r--r--libm/mips/fesetexcept.c31
-rw-r--r--libm/mips/fesetmode.c37
-rw-r--r--libm/mips/fesetround.c40
-rw-r--r--libm/mips/feupdateenv.c40
-rw-r--r--libm/mips/fgetexcptflg.c37
-rw-r--r--libm/mips/fraiseexcpt.c42
-rw-r--r--libm/mips/fsetexcptflg.c40
-rw-r--r--libm/mips/ftestexcept.c30
-rw-r--r--libm/or1k/Makefile.arch16
-rw-r--r--libm/or1k/fclrexcpt.c42
-rw-r--r--libm/or1k/fegetenv.c28
-rw-r--r--libm/or1k/fegetmode.c28
-rw-r--r--libm/or1k/fegetround.c25
-rw-r--r--libm/or1k/feholdexcpt.c29
-rw-r--r--libm/or1k/fenv_private.h196
-rw-r--r--libm/or1k/fesetenv.c28
-rw-r--r--libm/or1k/fesetexcept.c34
-rw-r--r--libm/or1k/fesetmode.c38
-rw-r--r--libm/or1k/fesetround.c35
-rw-r--r--libm/or1k/feupdateenv.c29
-rw-r--r--libm/or1k/fgetexcptflg.c28
-rw-r--r--libm/or1k/fraiseexcpt.c63
-rw-r--r--libm/or1k/fsetexcptflg.c42
-rw-r--r--libm/or1k/ftestexcept.c25
-rw-r--r--libm/or1k/get-rounding-mode.h36
-rw-r--r--libm/riscv32/Makefile.arch16
-rw-r--r--libm/riscv32/fclrexcpt.c26
-rw-r--r--libm/riscv32/fegetenv.c28
-rw-r--r--libm/riscv32/fegetmode.c26
-rw-r--r--libm/riscv32/fegetround.c25
-rw-r--r--libm/riscv32/feholdexcpt.c26
-rw-r--r--libm/riscv32/fenv_private.h156
-rw-r--r--libm/riscv32/fesetenv.c26
-rw-r--r--libm/riscv32/fesetexcept.c25
-rw-r--r--libm/riscv32/fesetmode.c30
-rw-r--r--libm/riscv32/fesetround.c35
-rw-r--r--libm/riscv32/feupdateenv.c26
-rw-r--r--libm/riscv32/fgetexcptflg.c29
-rw-r--r--libm/riscv32/fraiseexcpt.c26
-rw-r--r--libm/riscv32/fsetexcptflg.c29
-rw-r--r--libm/riscv32/ftestexcept.c25
-rw-r--r--libm/riscv32/get-rounding-mode.h32
-rw-r--r--libm/riscv64/Makefile.arch16
-rw-r--r--libm/riscv64/fclrexcpt.c26
-rw-r--r--libm/riscv64/fegetenv.c28
-rw-r--r--libm/riscv64/fegetmode.c26
-rw-r--r--libm/riscv64/fegetround.c25
-rw-r--r--libm/riscv64/feholdexcpt.c26
-rw-r--r--libm/riscv64/fenv_private.h156
-rw-r--r--libm/riscv64/fesetenv.c26
-rw-r--r--libm/riscv64/fesetexcept.c25
-rw-r--r--libm/riscv64/fesetmode.c30
-rw-r--r--libm/riscv64/fesetround.c35
-rw-r--r--libm/riscv64/feupdateenv.c26
-rw-r--r--libm/riscv64/fgetexcptflg.c29
-rw-r--r--libm/riscv64/fraiseexcpt.c26
-rw-r--r--libm/riscv64/fsetexcptflg.c29
-rw-r--r--libm/riscv64/ftestexcept.c25
-rw-r--r--libm/riscv64/get-rounding-mode.h32
-rw-r--r--libm/sh/sh4/Makefile.arch2
-rw-r--r--libm/sh/sh4/fclrexcpt.c39
-rw-r--r--libm/sh/sh4/fedisblxcpt.c37
-rw-r--r--libm/sh/sh4/feenablxcpt.c36
-rw-r--r--libm/sh/sh4/fegetenv.c30
-rw-r--r--libm/sh/sh4/fegetexcept.c30
-rw-r--r--libm/sh/sh4/fegetmode.c26
-rw-r--r--libm/sh/sh4/fegetround.c30
-rw-r--r--libm/sh/sh4/feholdexcpt.c37
-rw-r--r--libm/sh/sh4/fesetenv.c28
-rw-r--r--libm/sh/sh4/fesetexcept.c31
-rw-r--r--libm/sh/sh4/fesetmode.c37
-rw-r--r--libm/sh/sh4/fesetround.c40
-rw-r--r--libm/sh/sh4/feupdateenv.c36
-rw-r--r--libm/sh/sh4/fgetexcptflg.c37
-rw-r--r--libm/sh/sh4/fraiseexcpt.c70
-rw-r--r--libm/sh/sh4/fsetexcptflg.c38
-rw-r--r--libm/sh/sh4/ftestexcept.c30
-rw-r--r--libm/sparc/Makefile.arch16
-rw-r--r--libm/sparc/fclrexcpt.c34
-rw-r--r--libm/sparc/fedisblxcpt.c34
-rw-r--r--libm/sparc/feenablxcpt.c34
-rw-r--r--libm/sparc/fegetenv.c28
-rw-r--r--libm/sparc/fegetexcept.c28
-rw-r--r--libm/sparc/fegetmode.c26
-rw-r--r--libm/sparc/fegetround.c29
-rw-r--r--libm/sparc/feholdexcpt.c34
-rw-r--r--libm/sparc/fenv_private.h187
-rw-r--r--libm/sparc/fesetenv.c45
-rw-r--r--libm/sparc/fesetexcept.c31
-rw-r--r--libm/sparc/fesetmode.c38
-rw-r--r--libm/sparc/fesetround.c36
-rw-r--r--libm/sparc/feupdateenv.c40
-rw-r--r--libm/sparc/fgetexcptflg.c33
-rw-r--r--libm/sparc/fpu_control.h75
-rw-r--r--libm/sparc/fraiseexcpt.c81
-rw-r--r--libm/sparc/fsetexcptflg.c36
-rw-r--r--libm/sparc/ftestexcept.c29
-rw-r--r--libm/sparc/math-barriers.h36
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/m68k/bits/pthreadtypes.h18
-rw-r--r--libutil/forkpty.c3
-rw-r--r--libutil/openpty.c80
294 files changed, 10941 insertions, 843 deletions
diff --git a/Rules.mak b/Rules.mak
index 0138a1c67..56e515ab7 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -1,7 +1,7 @@
# Rules.mak for uClibc-ng
#
# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
-# Copyright (C) 2015-2024 Waldemar Brodkorb <wbx@uclibc-ng.org>
+# Copyright (C) 2015-2025 Waldemar Brodkorb <wbx@uclibc-ng.org>
#
# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
#
@@ -128,7 +128,7 @@ export RUNTIME_PREFIX DEVEL_PREFIX KERNEL_HEADERS MULTILIB_DIR
# Now config hard core
MAJOR_VERSION := 1
MINOR_VERSION := 0
-SUBLEVEL := 50
+SUBLEVEL := 54
EXTRAVERSION :=
VERSION := $(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL)
ABI_VERSION := $(MAJOR_VERSION)
@@ -312,10 +312,6 @@ endif
endif
endif
-ifeq ($(TARGET_ARCH),aarch64)
-CPU_CFLAGS-y += -ftls-model=initial-exec
-endif
-
$(eval $(call check-gcc-var,-std=gnu99))
CPU_CFLAGS-y += $(CFLAG_-std=gnu99)
@@ -668,6 +664,12 @@ endif
ifeq ($(TARGET_ARCH),i386)
CFLAGS += -fno-omit-frame-pointer
endif
+ifeq ($(TARGET_ARCH),bfin)
+CFLAGS += -Wno-implicit-function-declaration
+endif
+ifeq ($(TARGET_ARCH),frv)
+CFLAGS += -Wno-implicit-function-declaration
+endif
ifneq ($(strip $(UCLIBC_EXTRA_LDFLAGS)),"")
LDFLAGS += $(call qstrip,$(UCLIBC_EXTRA_LDFLAGS))
endif
diff --git a/extra/Configs/Config.in.arch b/extra/Configs/Config.in.arch
index c13497893..24c0db157 100644
--- a/extra/Configs/Config.in.arch
+++ b/extra/Configs/Config.in.arch
@@ -164,9 +164,20 @@ config UCLIBC_HAS_FENV
bool "Enable C99 Floating-point environment"
depends on UCLIBC_HAS_FLOATS
depends on TARGET_i386 || \
+ TARGET_aarch64 || \
+ TARGET_arc || \
+ TARGET_arm || \
+ TARGET_csky || \
+ TARGET_m68k || \
TARGET_metag || \
+ TARGET_mips || \
TARGET_nds32 || \
+ TARGET_or1k || \
(TARGET_powerpc && CONFIG_E500) || \
+ TARGET_riscv32 || \
+ TARGET_riscv64 || \
+ (TARGET_sh && (CONFIG_SH4 || CONFIG_SH4A)) || \
+ TARGET_sparc || \
TARGET_x86_64
help
If you want the uClibc math library to contain the C99 floating
diff --git a/extra/scripts/unifdef.c b/extra/scripts/unifdef.c
index 0f059205f..cfe34377a 100644
--- a/extra/scripts/unifdef.c
+++ b/extra/scripts/unifdef.c
@@ -201,7 +201,7 @@ static int depth; /* current #if nesting */
static int delcount; /* count of deleted lines */
static unsigned blankcount; /* count of blank lines */
static unsigned blankmax; /* maximum recent blankcount */
-static bool constexpr; /* constant #if expression */
+static bool const_expr; /* constant #if expression */
static bool zerosyms; /* to format symdepth output */
static bool firstsym; /* ditto */
@@ -951,7 +951,7 @@ static long prec(const struct ops *ops)
/*
* Function for evaluating the innermost parts of expressions,
* viz. !expr (expr) number defined(symbol) symbol
- * We reset the constexpr flag in the last two cases.
+ * We reset the const_expr flag in the last two cases.
*/
static Linetype
eval_unary(const struct ops *ops, long *valp, const char **cpp)
@@ -1011,7 +1011,7 @@ eval_unary(const struct ops *ops, long *valp, const char **cpp)
*valp = (value[sym] != NULL);
lt = *valp ? LT_TRUE : LT_FALSE;
}
- constexpr = false;
+ const_expr = false;
} else if (!endsym(*cp)) {
debug("eval%d symbol", prec(ops));
sym = findsym(&cp);
@@ -1028,7 +1028,7 @@ eval_unary(const struct ops *ops, long *valp, const char **cpp)
lt = *valp ? LT_TRUE : LT_FALSE;
cp = skipargs(cp);
}
- constexpr = false;
+ const_expr = false;
} else {
debug("eval%d bad expr", prec(ops));
return (LT_ERROR);
@@ -1088,10 +1088,10 @@ ifeval(const char **cpp)
long val = 0;
debug("eval %s", *cpp);
- constexpr = killconsts ? false : true;
+ const_expr = killconsts ? false : true;
ret = eval_table(eval_ops, &val, cpp);
debug("eval = %d", val);
- return (constexpr ? LT_IF : ret == LT_ERROR ? LT_IF : ret);
+ return (const_expr ? LT_IF : ret == LT_ERROR ? LT_IF : ret);
}
/*
diff --git a/include/fenv.h b/include/fenv.h
index 9ba384756..4b532c573 100644
--- a/include/fenv.h
+++ b/include/fenv.h
@@ -23,6 +23,7 @@
#define _FENV_H 1
#include <features.h>
+#include <stdbool.h>
/* Get the architecture dependend definitions. The following definitions
are expected to be done:
@@ -130,6 +131,15 @@ extern int fedisableexcept (int __excepts) __THROW;
extern int fegetexcept (void) __THROW;
#endif
+/* Rounding mode context. This allows functions to set/restore rounding mode
+ only when the desired rounding mode is different from the current rounding
+ mode. */
+struct rm_ctx
+{
+ fenv_t env;
+ bool updated_status;
+};
+
__END_DECLS
#endif /* fenv.h */
diff --git a/include/internal/time64_helpers.h b/include/internal/time64_helpers.h
index 2284aacd9..e2ed0f3bb 100644
--- a/include/internal/time64_helpers.h
+++ b/include/internal/time64_helpers.h
@@ -1,10 +1,15 @@
#ifndef _TIME64_HELPERS_H
#define _TIME64_HELPERS_H
+#include <linux/version.h>
#include <bits/types.h>
#include <time.h>
#include <stddef.h>
+#if defined(__UCLIBC_USE_TIME64__) && __TARGET_ARCH_BITS__ == 32 && LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0)
+#error 64bit time on 32bit targets is not supported on Linux < 5.1.0
+#endif
+
struct __ts64_struct {
__S64_TYPE tv_sec;
__S64_TYPE tv_nsec;
diff --git a/include/libintl.h b/include/libintl.h
index b7123a963..6d8b9f342 100644
--- a/include/libintl.h
+++ b/include/libintl.h
@@ -50,9 +50,6 @@ char *bindtextdomain(const char *domainname, const char *dirname);
#endif
-#include <stdio.h>
-#define gettext_printf(args...) printf(args)
-
/* to supply LC_MESSAGES and other stuff GNU expects to be exported when
including libintl.h */
#include <locale.h>
diff --git a/include/netdb.h b/include/netdb.h
index a85797956..26c999e59 100644
--- a/include/netdb.h
+++ b/include/netdb.h
@@ -689,7 +689,7 @@ extern const char *gai_strerror (int __ecode) __THROW;
extern int getnameinfo (const struct sockaddr *__restrict __sa,
socklen_t __salen, char *__restrict __host,
socklen_t __hostlen, char *__restrict __serv,
- socklen_t __servlen, unsigned int __flags);
+ socklen_t __servlen, int __flags);
libc_hidden_proto(getnameinfo)
#endif /* POSIX */
diff --git a/include/pty.h b/include/pty.h
index f23a260ae..609ac2459 100644
--- a/include/pty.h
+++ b/include/pty.h
@@ -31,13 +31,15 @@ __BEGIN_DECLS
attributes according to TERMP and WINP and return handles for both
ends in AMASTER and ASLAVE. */
extern int openpty (int *__amaster, int *__aslave, char *__name,
- struct termios *__termp, struct winsize *__winp) __THROW;
+ const struct termios *__termp,
+ const struct winsize *__winp) __THROW;
libutil_hidden_proto(openpty)
/* Create child process and establish the slave pseudo terminal as the
child's controlling terminal. */
extern int forkpty (int *__amaster, char *__name,
- struct termios *__termp, struct winsize *__winp) __THROW;
+ const struct termios *__termp,
+ const struct winsize *__winp) __THROW;
__END_DECLS
diff --git a/include/spawn.h b/include/spawn.h
index 3de375b41..cf01639c1 100644
--- a/include/spawn.h
+++ b/include/spawn.h
@@ -103,6 +103,7 @@ int posix_spawnattr_init (posix_spawnattr_t *__attr)
static inline
int posix_spawnattr_destroy (posix_spawnattr_t *__attr)
{
+ (void)__attr;
return 0;
}
diff --git a/include/stdint.h b/include/stdint.h
index 749f73697..5fedfb574 100644
--- a/include/stdint.h
+++ b/include/stdint.h
@@ -144,11 +144,19 @@ typedef unsigned long long int uintmax_t;
# if __WORDSIZE == 64
+# ifndef __INT64_C
# define __INT64_C(c) c ## L
+# endif
+# ifndef __UINT64_C
# define __UINT64_C(c) c ## UL
+# endif
# else
+# ifndef __INT64_C
# define __INT64_C(c) c ## LL
+# endif
+# ifndef __UINT64_C
# define __UINT64_C(c) c ## ULL
+# endif
# endif
/* Limits of integral types. */
diff --git a/include/stdlib.h b/include/stdlib.h
index d4e0b75e7..448c5e336 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -986,9 +986,13 @@ extern int getpt (void);
extern int getloadavg (double __loadavg[], int __nelem)
__THROW __nonnull ((1));
+/* reallocarray() only provided by the malloc-standard implementation */
+#if defined(__MALLOC_STANDARD__)
extern void *reallocarray (void *__ptr, size_t __m, size_t __n);
#endif
+#endif
+
#ifdef _LIBC
extern int __drand48_iterate (unsigned short int xsubi[3], struct drand48_data *buffer) attribute_hidden;
diff --git a/include/sys/mount.h b/include/sys/mount.h
index c0e7b84f8..f9edbeba3 100644
--- a/include/sys/mount.h
+++ b/include/sys/mount.h
@@ -32,54 +32,79 @@
supported */
enum
{
+#undef MS_RDONLY
MS_RDONLY = 1, /* Mount read-only. */
#define MS_RDONLY MS_RDONLY
+#undef MS_NOSUID
MS_NOSUID = 2, /* Ignore suid and sgid bits. */
#define MS_NOSUID MS_NOSUID
+#undef MS_NODEV
MS_NODEV = 4, /* Disallow access to device special files. */
#define MS_NODEV MS_NODEV
+#undef MS_NOEXEC
MS_NOEXEC = 8, /* Disallow program execution. */
#define MS_NOEXEC MS_NOEXEC
+#undef MS_SYNCHRONOUS
MS_SYNCHRONOUS = 16, /* Writes are synced at once. */
#define MS_SYNCHRONOUS MS_SYNCHRONOUS
+#undef MS_REMOUNT
MS_REMOUNT = 32, /* Alter flags of a mounted FS. */
#define MS_REMOUNT MS_REMOUNT
+#undef MS_MANDLOCK
MS_MANDLOCK = 64, /* Allow mandatory locks on an FS. */
#define MS_MANDLOCK MS_MANDLOCK
+#undef MS_DIRSYNC
MS_DIRSYNC = 128, /* Directory modifications are synchronous. */
#define MS_DIRSYNC MS_DIRSYNC
+#undef MS_NOATIME
MS_NOATIME = 1024, /* Do not update access times. */
#define MS_NOATIME MS_NOATIME
+#undef MS_NODIRATIME
MS_NODIRATIME = 2048, /* Do not update directory access times. */
#define MS_NODIRATIME MS_NODIRATIME
+#undef MS_BIND
MS_BIND = 4096, /* Bind directory at different place. */
#define MS_BIND MS_BIND
+#undef MS_MOVE
MS_MOVE = 8192,
#define MS_MOVE MS_MOVE
+#undef MS_REC
MS_REC = 16384,
#define MS_REC MS_REC
+#undef MS_SILENT
MS_SILENT = 32768,
#define MS_SILENT MS_SILENT
+#undef MS_POSIXACL
MS_POSIXACL = 1 << 16, /* VFS does not apply the umask. */
#define MS_POSIXACL MS_POSIXACL
+#undef MS_UNBINDABLE
MS_UNBINDABLE = 1 << 17, /* Change to unbindable. */
#define MS_UNBINDABLE MS_UNBINDABLE
+#undef MS_PRIVATE
MS_PRIVATE = 1 << 18, /* Change to private. */
#define MS_PRIVATE MS_PRIVATE
+#undef MS_SLAVE
MS_SLAVE = 1 << 19, /* Change to slave. */
#define MS_SLAVE MS_SLAVE
+#undef MS_SHARED
MS_SHARED = 1 << 20, /* Change to shared. */
#define MS_SHARED MS_SHARED
+#undef MS_RELATIME
MS_RELATIME = 1 << 21, /* Update atime relative to mtime/ctime. */
#define MS_RELATIME MS_RELATIME
+#undef MS_KERNMOUNT
MS_KERNMOUNT = 1 << 22, /* This is a kern_mount call. */
#define MS_KERNMOUNT MS_KERNMOUNT
+#undef MS_I_VERSION
MS_I_VERSION = 1 << 23, /* Update inode I_version field. */
#define MS_I_VERSION MS_I_VERSION
+#undef MS_STRICTATIME
MS_STRICTATIME = 1 << 24, /* Always perform atime updates. */
#define MS_STRICTATIME MS_STRICTATIME
+#undef MS_ACTIVE
MS_ACTIVE = 1 << 30,
#define MS_ACTIVE MS_ACTIVE
+#undef MS_NOUSER
MS_NOUSER = 1 << 31
#define MS_NOUSER MS_NOUSER
};
diff --git a/include/unistd.h b/include/unistd.h
index d50e1e4d3..e45266f14 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -1250,6 +1250,15 @@ extern void swab (const void *__restrict __from, void *__restrict __to,
extern char *ctermid (char *__s) __THROW;
#endif
+/* OpenBSD-compatible access to random bytes.
+ May be a cancellation point here, unlike in glibc/musl. */
+#ifdef _DEFAULT_SOURCE
+# ifndef __getentropy_defined
+extern int getentropy(void *__buf, size_t __len) __nonnull ((1)) __wur;
+# define __getentropy_defined
+# endif
+#endif
+
__END_DECLS
diff --git a/ldso/include/dl-auxvt.h b/ldso/include/dl-auxvt.h
new file mode 100644
index 000000000..29eda6eb3
--- /dev/null
+++ b/ldso/include/dl-auxvt.h
@@ -0,0 +1,9 @@
+#ifndef _DL_AUXVT_H
+#define _DL_AUXVT_H
+
+#define AUX_MAX_AT_ID 40
+extern ElfW(auxv_t) _dl_auxvt[AUX_MAX_AT_ID]; /* Cache frequently accessed auxiliary vector entries */
+extern ElfW(auxv_t) *_dl_auxv_start; /* Start of the auxiliary vector */
+
+#endif /* _DL_AUXVT_H */
+
diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h
index a397cce61..061d8a536 100755
--- a/ldso/include/ldso.h
+++ b/ldso/include/ldso.h
@@ -191,8 +191,7 @@ extern void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE loa
#endif
-#define AUX_MAX_AT_ID 40
-extern ElfW(auxv_t) _dl_auxvt[AUX_MAX_AT_ID];
+#include <dl-auxvt.h>
void load_vdso(void *sys_info_ehdr, char **envp );
diff --git a/ldso/ldso/Makefile.in b/ldso/ldso/Makefile.in
index 6e8a0c388..0f8ed140d 100644
--- a/ldso/ldso/Makefile.in
+++ b/ldso/ldso/Makefile.in
@@ -19,6 +19,11 @@ ifeq ($(TARGET_ARCH),arm)
CFLAGS-rtld += -fno-unwind-tables -fno-asynchronous-unwind-tables
endif
+ifeq ($(TARGET_ARCH),bfin)
+# for gcc 10.5.0 and above we need to use -ffreestanding
+CFLAGS-rtld += -ffreestanding
+endif
+
CFLAGS-rtld += -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include -I$(top_srcdir)ldso/ldso
CFLAGS-rtld += -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\"
diff --git a/ldso/ldso/aarch64/dl-sysdep.h b/ldso/ldso/aarch64/dl-sysdep.h
index 6d9d2c1fb..3466920d9 100644
--- a/ldso/ldso/aarch64/dl-sysdep.h
+++ b/ldso/ldso/aarch64/dl-sysdep.h
@@ -54,28 +54,21 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
|| (type) == R_AARCH64_TLSDESC) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_AARCH64_COPY) * ELF_RTYPE_CLASS_COPY))
-/* Return the link-time address of _DYNAMIC. Conveniently, this is the
- first element of the GOT. */
-extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
-static __always_inline ElfW(Addr) __attribute__ ((unused))
-elf_machine_dynamic (void)
-{
- return _GLOBAL_OFFSET_TABLE_[0];
-}
-
/* Return the run-time load address of the shared object. */
static __always_inline ElfW(Addr) __attribute__ ((unused))
elf_machine_load_address (void)
{
- /* To figure out the load address we use the definition that for any symbol:
- dynamic_addr(symbol) = static_addr(symbol) + load_addr
-
- _DYNAMIC sysmbol is used here as its link-time address stored in
- the special unrelocated first GOT entry. */
+ extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
+ return (ElfW(Addr)) &__ehdr_start;
+}
- extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
- return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic ();
+/* Return the link-time address of _DYNAMIC. */
+static __always_inline ElfW(Addr) __attribute__ ((unused))
+elf_machine_dynamic (void)
+{
+ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
+ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
}
static __always_inline void
diff --git a/ldso/ldso/aarch64/elfinterp.c b/ldso/ldso/aarch64/elfinterp.c
index 9365569cc..d8530ecd1 100644
--- a/ldso/ldso/aarch64/elfinterp.c
+++ b/ldso/ldso/aarch64/elfinterp.c
@@ -227,13 +227,13 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
#else
if (!TRY_STATIC_TLS ((struct link_map *) tls_tpnt))
{
- td->arg = _dl_make_tlsdesc_dynamic((struct link_map *) tls_tpnt, symbol_addr);
+ td->arg = _dl_make_tlsdesc_dynamic((struct link_map *) tls_tpnt, symbol_addr + rpnt->r_addend);
td->entry = _dl_tlsdesc_dynamic;
}
else
#endif
{
- td->arg = (void*)(symbol_addr + tls_tpnt->l_tls_offset);
+ td->arg = (void*)(symbol_addr + tls_tpnt->l_tls_offset + rpnt->r_addend);
td->entry = _dl_tlsdesc_return;
}
}
diff --git a/ldso/ldso/arm/dl-sysdep.h b/ldso/ldso/arm/dl-sysdep.h
index 0f783e1c4..93e36b694 100644
--- a/ldso/ldso/arm/dl-sysdep.h
+++ b/ldso/ldso/arm/dl-sysdep.h
@@ -96,43 +96,6 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
| (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
#endif /* __FDPIC__ */
-/* Return the link-time address of _DYNAMIC. Conveniently, this is the
- first element of the GOT. We used to use the PIC register to do this
- without a constant pool reference, but GCC 4.2 will use a pseudo-register
- for the PIC base, so it may not be in r10. */
-static __always_inline Elf32_Addr __attribute__ ((unused))
-elf_machine_dynamic (void)
-{
- Elf32_Addr dynamic;
-#if !defined __thumb__
- __asm__ ("ldr %0, 2f\n"
- "1: ldr %0, [pc, %0]\n"
- "b 3f\n"
- "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n"
- "3:" : "=r" (dynamic));
-#else
- int tmp;
- __asm__ (".align 2\n"
- "bx pc\n"
- "nop\n"
- ".arm\n"
- "ldr %0, 2f\n"
- "1: ldr %0, [pc, %0]\n"
- "b 3f\n"
- "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n"
- "3:"
- ".align 2\n"
- "orr %1, pc, #1\n"
- "bx %1\n"
- ".force_thumb\n"
- : "=r" (dynamic), "=&r" (tmp));
-#endif
-
- return dynamic;
-}
-
-extern char __dl_start[] __asm__("_dl_start");
-
#ifdef __FDPIC__
/* We must force strings used early in the bootstrap into the data
segment. */
@@ -148,28 +111,16 @@ extern char __dl_start[] __asm__("_dl_start");
static __always_inline Elf32_Addr __attribute__ ((unused))
elf_machine_load_address (void)
{
-#if defined(__FDPIC__)
- return 0;
-#else
- Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
- Elf32_Addr pcrel_addr;
-#if defined __OPTIMIZE__ && !defined __thumb__
- __asm__ ("adr %0, _dl_start" : "=r" (pcrel_addr));
-#else
- /* A simple adr does not work in Thumb mode because the offset is
- negative, and for debug builds may be too large. */
- int tmp;
- __asm__ ("adr %1, 1f\n\t"
- "ldr %0, [%1]\n\t"
- "add %0, %0, %1\n\t"
- "b 2f\n\t"
- ".align 2\n\t"
- "1: .word _dl_start - 1b\n\t"
- "2:"
- : "=r" (pcrel_addr), "=r" (tmp));
-#endif
- return pcrel_addr - got_addr;
-#endif
+ extern const Elf32_Ehdr __ehdr_start attribute_hidden;
+ return (Elf32_Addr) &__ehdr_start;
+}
+
+/* Return the link-time address of _DYNAMIC. */
+static __always_inline Elf32_Addr __attribute__ ((unused))
+elf_machine_dynamic (void)
+{
+ extern Elf32_Dyn _DYNAMIC[] attribute_hidden;
+ return (Elf32_Addr) _DYNAMIC - elf_machine_load_address ();
}
static __always_inline void
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index 4f50d62b7..6656acb0f 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -1028,7 +1028,7 @@ int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int now_flag)
return goof;
}
-#if !defined(__FDPIC__) && !defined(__DSBT__)
+#if !defined(__FDPIC__) && !defined(__FRV_FDPIC__) && !defined(__DSBT__)
/* Process DT_RELR relative relocations */
DL_RELOCATE_RELR(tpnt);
#endif
diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c
index e7000bd87..ec6b72a39 100644
--- a/ldso/ldso/dl-startup.c
+++ b/ldso/ldso/dl-startup.c
@@ -100,6 +100,7 @@ extern ElfW(Addr) _begin[] attribute_hidden;
ElfW(auxv_t) _dl_auxvt[AUX_MAX_AT_ID];
+ElfW(auxv_t) *_dl_auxv_start;
#ifdef LDSO_NEED_DPNT
ElfW(Dyn) *_dl_saved_dpnt = 0;
@@ -131,6 +132,7 @@ DL_START(unsigned long args)
struct elf_resolve tpnt_tmp;
struct elf_resolve *tpnt = &tpnt_tmp;
ElfW(auxv_t) _dl_auxvt_tmp[AUX_MAX_AT_ID];
+ ElfW(auxv_t) *_dl_auxv_start_tmp;
ElfW(Dyn) *dpnt;
uint32_t *p32;
@@ -166,6 +168,7 @@ DL_START(unsigned long args)
/* The junk on the stack immediately following the environment is
* the Auxiliary Vector Table. Read out the elements of the auxvt,
* sort and store them in auxvt for later use. */
+ _dl_auxv_start_tmp = (ElfW(auxv_t) *)aux_dat;
while (*aux_dat) {
ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat;
@@ -264,7 +267,7 @@ DL_START(unsigned long args)
that once we are done, we have considerably more flexibility. */
SEND_EARLY_STDERR_DEBUG("About to do library loader relocations\n");
-#if !defined(__FDPIC__) && !defined(__DSBT__)
+#if !defined(__FDPIC__) && !defined(__FRV_FDPIC__) && !defined(__DSBT__)
/* Process DT_RELR relative relocations */
DL_RELOCATE_RELR(tpnt);
#endif
@@ -367,6 +370,7 @@ DL_START(unsigned long args)
* now the globals work. so copy the aux vector
*/
_dl_memcpy( _dl_auxvt, _dl_auxvt_tmp, sizeof( ElfW(auxv_t) ) * AUX_MAX_AT_ID );
+ _dl_auxv_start = _dl_auxv_start_tmp;
_dl_elf_main = (int (*)(int, char **, char **))
_dl_get_ready_to_run(tpnt, load_addr, envp, argv
diff --git a/ldso/ldso/i386/dl-sysdep.h b/ldso/ldso/i386/dl-sysdep.h
index b95328df4..8fc80a145 100644
--- a/ldso/ldso/i386/dl-sysdep.h
+++ b/ldso/ldso/i386/dl-sysdep.h
@@ -35,28 +35,21 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent
|| (type) == R_386_TLS_TPOFF) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY))
-/* Return the link-time address of _DYNAMIC. Conveniently, this is the
- first element of the GOT, a special entry that is never relocated. */
-extern const Elf32_Addr _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
-static __always_inline Elf32_Addr __attribute__ ((unused, const))
-elf_machine_dynamic (void)
-{
- /* This produces a GOTOFF reloc that resolves to zero at link time, so in
- fact just loads from the GOT register directly. By doing it without
- an asm we can let the compiler choose any register. */
- return _GLOBAL_OFFSET_TABLE_[0];
-}
-
-extern Elf32_Dyn bygotoff[] __asm__ ("_DYNAMIC") attribute_hidden;
/* Return the run-time load address of the shared object. */
static __always_inline Elf32_Addr attribute_unused
elf_machine_load_address (void)
{
- /* Compute the difference between the runtime address of _DYNAMIC as seen
- by a GOTOFF reference, and the link-time address found in the special
- unrelocated first GOT entry. */
- return (Elf32_Addr) &bygotoff - elf_machine_dynamic ();
+ extern const Elf32_Ehdr __ehdr_start attribute_hidden;
+ return (Elf32_Addr) &__ehdr_start;
+}
+
+/* Return the link-time address of _DYNAMIC. */
+static __always_inline Elf32_Addr __attribute__ ((unused, const))
+elf_machine_dynamic (void)
+{
+ extern Elf32_Dyn _DYNAMIC[] attribute_hidden;
+ return (Elf32_Addr) _DYNAMIC - elf_machine_load_address ();
}
static __always_inline void
diff --git a/ldso/ldso/m68k/elfinterp.c b/ldso/ldso/m68k/elfinterp.c
index 25ea23067..e7fa117da 100644
--- a/ldso/ldso/m68k/elfinterp.c
+++ b/ldso/ldso/m68k/elfinterp.c
@@ -193,7 +193,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
#endif
#if defined (__SUPPORT_LD_DEBUG__)
- old_val = *reloc_addr;
+ old_val = reloc_addr ? *reloc_addr : 0;
#endif
switch (reloc_type) {
@@ -292,7 +292,7 @@ _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
reloc_type = ELF_R_TYPE(rpnt->r_info);
#if defined (__SUPPORT_LD_DEBUG__)
- old_val = *reloc_addr;
+ old_val = reloc_addr ? *reloc_addr : 0;
#endif
switch (reloc_type) {
diff --git a/ldso/ldso/riscv32/dl-sysdep.h b/ldso/ldso/riscv32/dl-sysdep.h
index e0a59fddd..02296b148 100644
--- a/ldso/ldso/riscv32/dl-sysdep.h
+++ b/ldso/ldso/riscv32/dl-sysdep.h
@@ -59,22 +59,20 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
| (ELF_RTYPE_CLASS_COPY * ((type) == R_RISCV_COPY)))
-/* Return the link-time address of _DYNAMIC. */
-static inline ElfW(Addr)
-elf_machine_dynamic (void)
-{
- extern ElfW(Addr) _GLOBAL_OFFSET_TABLE_ __attribute__ ((visibility ("hidden")));
- return _GLOBAL_OFFSET_TABLE_;
-}
-
-
/* Return the run-time load address of the shared object. */
static __always_inline ElfW(Addr) __attribute__ ((unused))
elf_machine_load_address (void)
{
- ElfW(Addr) load_addr;
- __asm__ ("lla %0, _DYNAMIC" : "=r" (load_addr));
- return load_addr - elf_machine_dynamic ();
+ extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
+ return (ElfW(Addr)) &__ehdr_start;
+}
+
+/* Return the link-time address of _DYNAMIC. */
+static inline ElfW(Addr)
+elf_machine_dynamic (void)
+{
+ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
+ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
}
static __always_inline void
diff --git a/ldso/ldso/x86_64/dl-sysdep.h b/ldso/ldso/x86_64/dl-sysdep.h
index ccf9a8851..58447a951 100644
--- a/ldso/ldso/x86_64/dl-sysdep.h
+++ b/ldso/ldso/x86_64/dl-sysdep.h
@@ -52,48 +52,21 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent
* ELF_RTYPE_CLASS_PLT) \
| (((type) == R_X86_64_COPY) * ELF_RTYPE_CLASS_COPY))
-/* Return the link-time address of _DYNAMIC. Conveniently, this is the
- first element of the GOT. This must be inlined in a function which
- uses global data. */
-static __always_inline Elf64_Addr __attribute__ ((unused))
-elf_machine_dynamic (void)
-{
- Elf64_Addr addr;
-
- /* This works because we have our GOT address available in the small PIC
- model. */
- addr = (Elf64_Addr) &_DYNAMIC;
-
- return addr;
-}
-
/* Return the run-time load address of the shared object. */
static __always_inline Elf64_Addr __attribute__ ((unused))
elf_machine_load_address (void)
{
- register Elf64_Addr addr, tmp;
-
- /* The easy way is just the same as on x86:
- leaq _dl_start, %0
- leaq _dl_start(%%rip), %1
- subq %0, %1
- but this does not work with binutils since we then have
- a R_X86_64_32S relocation in a shared lib.
-
- Instead we store the address of _dl_start in the data section
- and compare it with the current value that we can get via
- an RIP relative addressing mode. */
-
- __asm__ ("movq 1f(%%rip), %1\n"
- "0:\tleaq _dl_start(%%rip), %0\n\t"
- "subq %1, %0\n\t"
- ".section\t.data\n"
- "1:\t.quad _dl_start\n\t"
- ".previous\n\t"
- : "=r" (addr), "=r" (tmp) : : "cc");
+ extern const Elf64_Ehdr __ehdr_start attribute_hidden;
+ return (Elf64_Addr) &__ehdr_start;
+}
- return addr;
+/* Return the link-time address of _DYNAMIC. */
+static __always_inline Elf64_Addr __attribute__ ((unused))
+elf_machine_dynamic (void)
+{
+ extern Elf64_Dyn _DYNAMIC[] attribute_hidden;
+ return (Elf64_Addr) _DYNAMIC - elf_machine_load_address ();
}
static __always_inline void
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/misc/sysvipc/ipc.h b/libc/misc/sysvipc/ipc.h
index b342dc1cf..58a690ee3 100644
--- a/libc/misc/sysvipc/ipc.h
+++ b/libc/misc/sysvipc/ipc.h
@@ -1,12 +1,19 @@
#ifndef IPC_H
#define IPC_H
#include <syscall.h>
+#include <bits/kernel-features.h>
#include <bits/wordsize.h>
#ifndef __ARCH_HAS_DEPRECATED_SYSCALLS__
# define __IPC_64 0x0
+#elif defined __mips__ || defined __m68k__
+# if __LINUX_KERNEL_VERSION < 0x050100
+# define __IPC_64 0x100
+# else
+# define __IPC_64 0x0
+# endif
#else
-# if __WORDSIZE == 32 || defined __alpha__ || defined __mips__
+# if __WORDSIZE == 32 || defined __alpha__
# define __IPC_64 0x100
# else
# define __IPC_64 0x0
diff --git a/libc/misc/sysvipc/msgq.c b/libc/misc/sysvipc/msgq.c
index 185cd268b..2d8bcae99 100644
--- a/libc/misc/sysvipc/msgq.c
+++ b/libc/misc/sysvipc/msgq.c
@@ -1,5 +1,6 @@
#include <errno.h>
#include <sys/msg.h>
+#include <stddef.h>
#include "ipc.h"
#ifdef __UCLIBC_HAS_THREADS_NATIVE__
#include "sysdep-cancel.h"
@@ -7,6 +8,12 @@
#define SINGLE_THREAD_P 1
#endif
+#if defined(__UCLIBC_USE_TIME64__)
+union msqun {
+ struct msqid_ds* buff;
+ void *__pad;
+};
+#endif
#ifdef L_msgctl
@@ -18,9 +25,19 @@ static __inline__ _syscall3(int, __libc_msgctl, int, msqid, int, cmd, struct msq
int msgctl(int msqid, int cmd, struct msqid_ds *buf)
{
#ifdef __NR_msgctl
- return __libc_msgctl(msqid, cmd | __IPC_64, buf);
+ int __ret = __libc_msgctl(msqid, cmd | __IPC_64, buf);
+#if (__WORDSIZE == 32) && defined(__UCLIBC_USE_TIME64__) && (defined(__mips) || defined(__riscv))
+ union msqun arg = {.buff = buf};
+ // When cmd is IPC_RMID, buf should be NULL.
+ if (arg.__pad != NULL) {
+ arg.buff->msg_stime = (__time_t)arg.buff->msg_stime_internal_1 | (__time_t)(arg.buff->msg_stime_internal_2) << 32;
+ arg.buff->msg_rtime = (__time_t)arg.buff->msg_rtime_internal_1 | (__time_t)(arg.buff->msg_rtime_internal_2) << 32;
+ arg.buff->msg_ctime = (__time_t)arg.buff->msg_ctime_internal_1 | (__time_t)(arg.buff->msg_ctime_internal_2) << 32;
+ }
+#endif
+ return __ret;
#else
- return __syscall_ipc(IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf, 0);
+ return __syscall_ipc(IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf, 0);
#endif
}
#endif
diff --git a/libc/misc/sysvipc/sem.c b/libc/misc/sysvipc/sem.c
index 07076eff7..66f86f53c 100644
--- a/libc/misc/sysvipc/sem.c
+++ b/libc/misc/sysvipc/sem.c
@@ -57,9 +57,14 @@ int semctl(int semid, int semnum, int cmd, ...)
va_end (ap);
#ifdef __NR_semctl
int __ret = __semctl(semid, semnum, cmd | __IPC_64, arg.__pad);
-#if defined(__UCLIBC_USE_TIME64__)
- arg.buf->sem_otime = (__time_t)arg.buf->__sem_otime_internal_1 | (__time_t)(arg.buf->__sem_otime_internal_2) << 32;
- arg.buf->sem_ctime = (__time_t)arg.buf->__sem_ctime_internal_1 | (__time_t)(arg.buf->__sem_ctime_internal_2) << 32;
+#if (__WORDSIZE == 32) && defined(__UCLIBC_USE_TIME64__)
+ // Only when cmd is IPC_STAT and IPC_SET, semun points to struct semid_ds.
+ // At this point, arg.__pad should not be NULL, but a check is added just
+ // to be safe.
+ if ((cmd & (IPC_STAT | IPC_SET)) && (arg.__pad != NULL)) {
+ arg.buf->sem_otime = (__time_t)arg.buf->__sem_otime_internal_1 | (__time_t)(arg.buf->__sem_otime_internal_2) << 32;
+ arg.buf->sem_ctime = (__time_t)arg.buf->__sem_ctime_internal_1 | (__time_t)(arg.buf->__sem_ctime_internal_2) << 32;
+ }
#endif
return __ret;
#else
diff --git a/libc/misc/sysvipc/shm.c b/libc/misc/sysvipc/shm.c
index cd46ff0dd..b3366b301 100644
--- a/libc/misc/sysvipc/shm.c
+++ b/libc/misc/sysvipc/shm.c
@@ -25,6 +25,13 @@
#include <syscall.h>
#include "ipc.h"
+#if defined(__UCLIBC_USE_TIME64__)
+union shmun {
+ struct shmid_ds* buff;
+ void *__pad;
+};
+#endif
+
#ifdef L_shmat
/* Attach the shared memory segment associated with SHMID to the data
segment of the calling process. SHMADDR and SHMFLG determine how
@@ -59,7 +66,17 @@ static __always_inline _syscall3(int, __syscall_shmctl, int, shmid, int, cmd, st
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
{
#ifdef __NR_shmctl
- return __syscall_shmctl(shmid, cmd | __IPC_64, buf);
+ int __ret = __syscall_shmctl(shmid, cmd | __IPC_64, buf);
+#if (__WORDSIZE == 32) && defined(__mips) && defined(__UCLIBC_USE_TIME64__)
+ union shmun arg = {.buff = buf};
+ // When cmd is IPC_RMID, buf should be NULL.
+ if (arg.__pad != NULL) {
+ arg.buff->shm_atime = (__time_t)arg.buff->shm_atime_internal_1 | (__time_t)(arg.buff->shm_atime_internal_2) << 32;
+ arg.buff->shm_dtime = (__time_t)arg.buff->shm_dtime_internal_1 | (__time_t)(arg.buff->shm_dtime_internal_2) << 32;
+ arg.buff->shm_ctime = (__time_t)arg.buff->shm_ctime_internal_1 | (__time_t)(arg.buff->shm_ctime_internal_2) << 32;
+ }
+#endif
+ return __ret;
#else
return __syscall_ipc(IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf, 0);
#endif
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/malloc-standard/malloc.c b/libc/stdlib/malloc-standard/malloc.c
index cecea87ec..e51bc6610 100644
--- a/libc/stdlib/malloc-standard/malloc.c
+++ b/libc/stdlib/malloc-standard/malloc.c
@@ -29,7 +29,7 @@ __UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
struct malloc_state __malloc_state; /* never directly referenced */
/* forward declaration */
-static int __malloc_largebin_index(unsigned int sz);
+static int __malloc_largebin_index(unsigned long sz);
#ifdef __UCLIBC_MALLOC_DEBUGGING__
@@ -755,10 +755,10 @@ static void* __malloc_alloc(size_t nb, mstate av)
Compute index for size. We expect this to be inlined when
compiled with optimization, else not, which works out well.
*/
-static int __malloc_largebin_index(unsigned int sz)
+static int __malloc_largebin_index(unsigned long sz)
{
- unsigned int x = sz >> SMALLBIN_WIDTH;
- unsigned int m; /* bit position of highest set bit of m */
+ unsigned long x = sz >> SMALLBIN_WIDTH;
+ unsigned long m; /* bit position of highest set bit of m */
if (x >= 0x10000) return NBINS-1;
@@ -776,7 +776,7 @@ static int __malloc_largebin_index(unsigned int sz)
S. Warren Jr's book "Hacker's Delight".
*/
- unsigned int n = ((x - 0x100) >> 16) & 8;
+ unsigned long n = ((x - 0x100) >> 16) & 8;
x <<= n;
m = ((x - 0x1000) >> 16) & 4;
n += m;
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/bits/shm.h b/libc/sysdeps/linux/aarch64/bits/shm.h
new file mode 100644
index 000000000..bfb603499
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bits/shm.h
@@ -0,0 +1,87 @@
+/*
+ * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB
+ * in this tarball.
+ */
+
+#ifndef _SYS_SHM_H
+# error "Never include <bits/shm.h> directly; use <sys/shm.h> instead."
+#endif
+
+#include <bits/types.h>
+
+/* Permission flag for shmget. */
+#define SHM_R 0400 /* or S_IRUGO from <linux/stat.h> */
+#define SHM_W 0200 /* or S_IWUGO from <linux/stat.h> */
+
+/* Flags for `shmat'. */
+#define SHM_RDONLY 010000 /* attach read-only else read-write */
+#define SHM_RND 020000 /* round attach address to SHMLBA */
+#define SHM_REMAP 040000 /* take-over region on attach */
+
+/* Commands for `shmctl'. */
+#define SHM_LOCK 11 /* lock segment (root only) */
+#define SHM_UNLOCK 12 /* unlock segment (root only) */
+
+__BEGIN_DECLS
+
+/* Segment low boundary address multiple. */
+#define SHMLBA (__getpagesize () << 2)
+extern int __getpagesize (void) __THROW __attribute__ ((__const__));
+
+
+/* Type to count number of attaches. */
+typedef unsigned long int shmatt_t;
+
+/* Data structure describing a set of semaphores. */
+struct shmid_ds
+ {
+ struct ipc_perm shm_perm; /* operation permission struct */
+ size_t shm_segsz; /* size of segment in bytes */
+ __time_t shm_atime; /* time of last shmat() */
+ __time_t shm_dtime; /* time of last shmdt() */
+ __time_t shm_ctime; /* time of last change by shmctl() */
+ __pid_t shm_cpid; /* pid of creator */
+ __pid_t shm_lpid; /* pid of last shmop */
+ shmatt_t shm_nattch; /* number of current attaches */
+ unsigned long int __uclibc_unused1;
+ unsigned long int __uclibc_unused2;
+ };
+
+#ifdef __USE_MISC
+
+/* ipcs ctl commands */
+# define SHM_STAT 13
+# define SHM_INFO 14
+
+/* shm_mode upper byte flags */
+# define SHM_DEST 01000 /* segment will be destroyed on last detach */
+# define SHM_LOCKED 02000 /* segment will not be swapped */
+# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */
+# define SHM_NORESERVE 010000 /* don't check for reservations */
+
+struct shminfo
+ {
+ unsigned long int shmmax;
+ unsigned long int shmmin;
+ unsigned long int shmmni;
+ unsigned long int shmseg;
+ unsigned long int shmall;
+ unsigned long int __uclibc_unused1;
+ unsigned long int __uclibc_unused2;
+ unsigned long int __uclibc_unused3;
+ unsigned long int __uclibc_unused4;
+ };
+
+struct shm_info
+ {
+ int used_ids;
+ unsigned long int shm_tot; /* total allocated shm */
+ unsigned long int shm_rss; /* total resident shm */
+ unsigned long int shm_swp; /* total swapped shm */
+ unsigned long int swap_attempts;
+ unsigned long int swap_successes;
+ };
+
+#endif /* __USE_MISC */
+
+__END_DECLS
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 Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -12,87 +11,77 @@
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/>. */
+ 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
-#ifdef __MAVERICK__
-
/* Define bits representing exceptions in the FPU status word. */
enum
{
- FE_INVALID = 1,
-#define FE_INVALID FE_INVALID
- FE_OVERFLOW = 4,
-#define FE_OVERFLOW FE_OVERFLOW
- FE_UNDERFLOW = 8,
-#define FE_UNDERFLOW FE_UNDERFLOW
- FE_INEXACT = 16,
-#define FE_INEXACT FE_INEXACT
+ 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 to a mask bit. */
-#define FE_EXCEPT_SHIFT 5
+#define FE_EXCEPT_SHIFT 8
/* All supported exceptions. */
-#define FE_ALL_EXCEPT \
- (FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
-
-/* IEEE rounding modes. */
-enum
- {
- FE_TONEAREST = 0,
-#define FE_TONEAREST FE_TONEAREST
- FE_TOWARDZERO = 0x400,
-#define FE_TOWARDZERO FE_TOWARDZERO
- FE_DOWNWARD = 0x800,
-#define FE_DOWNWARD FE_DOWNWARD
- FE_UPWARD = 0xc00,
-#define FE_UPWARD FE_UPWARD
- };
-
-#define FE_ROUND_MASK (FE_UPWARD)
-
-#else /* !__MAVERICK__ */
+#define FE_ALL_EXCEPT \
+ (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
-/* Define bits representing exceptions in the FPU status word. */
+/* VFP supports all of the four defined rounding modes. */
enum
{
- FE_INVALID = 1,
-#define FE_INVALID FE_INVALID
- FE_DIVBYZERO = 2,
-#define FE_DIVBYZERO FE_DIVBYZERO
- FE_OVERFLOW = 4,
-#define FE_OVERFLOW FE_OVERFLOW
- FE_UNDERFLOW = 8,
-#define FE_UNDERFLOW FE_UNDERFLOW
- };
-
-/* Amount to shift by to convert an exception to a mask bit. */
-#define FE_EXCEPT_SHIFT 16
-
-/* All supported exceptions. */
-#define FE_ALL_EXCEPT \
- (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW)
-
-/* The ARM FPU basically only supports round-to-nearest. Other rounding
- modes exist, but you have to encode them in the actual instruction. */
+ FE_TONEAREST =
#define FE_TONEAREST 0
-
-#endif /* __MAVERICK__ */
+ FE_TONEAREST,
+ FE_UPWARD =
+#define FE_UPWARD 0x400000
+ FE_UPWARD,
+ FE_DOWNWARD =
+#define FE_DOWNWARD 0x800000
+ FE_DOWNWARD,
+ FE_TOWARDZERO =
+#define FE_TOWARDZERO 0xc00000
+ FE_TOWARDZERO
+ };
/* Type representing exception flags. */
-typedef unsigned long int fexcept_t;
+typedef unsigned int fexcept_t;
/* Type representing floating-point environment. */
typedef struct
{
- unsigned long int __cw;
+ unsigned int __cw;
}
fenv_t;
/* If the default argument is used we use this value. */
-#define FE_DFL_ENV ((fenv_t *) -1l)
+#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/arm/bits/shm.h b/libc/sysdeps/linux/arm/bits/shm.h
index 86245faff..aa1a72e54 100644
--- a/libc/sysdeps/linux/arm/bits/shm.h
+++ b/libc/sysdeps/linux/arm/bits/shm.h
@@ -49,12 +49,18 @@ struct shmid_ds
{
struct ipc_perm shm_perm; /* operation permission struct */
size_t shm_segsz; /* size of segment in bytes */
+#if defined(__UCLIBC_USE_TIME64__)
+ __time_t shm_atime;
+ __time_t shm_dtime;
+ __time_t shm_ctime;
+#else
__time_t shm_atime; /* time of last shmat() */
unsigned long int __uclibc_unused1;
__time_t shm_dtime; /* time of last shmdt() */
unsigned long int __uclibc_unused2;
__time_t shm_ctime; /* time of last change by shmctl() */
unsigned long int __uclibc_unused3;
+#endif
__pid_t shm_cpid; /* pid of creator */
__pid_t shm_lpid; /* pid of last shmop */
shmatt_t shm_nattch; /* number of current attaches */
diff --git a/libc/sysdeps/linux/arm/crt1.S b/libc/sysdeps/linux/arm/crt1.S
index 799f11080..040ddfd27 100644
--- a/libc/sysdeps/linux/arm/crt1.S
+++ b/libc/sysdeps/linux/arm/crt1.S
@@ -248,13 +248,9 @@ _start:
#if defined(__ARCH_USE_MMU__) || defined(__UCLIBC_FORMAT_ELF__)
#ifdef L_rcrt1
/* We don't need to save a1 since no dynamic linker should have run */
- ldr a1, .L_GOT /* Get value at .L_GOT + 0 (offset to GOT)*/
- adr a2, .L_GOT /* Get address of .L_GOT */
- ldr a3, .L_GOT+16 /* Get value of _start(GOT) stored in .L_GOT */
- adr a4, _start /* Get address of _start after relocation (changes to pc - ~30 or so) */
- add a1, a1, a2 /* Calculate where the GOT is */
- ldr a2, [a1, a3] /* GOT + _start(GOT) = offset of _start from begin of file */
- sub a1, a4, a2 /* Current addr of _start - offset from beginning of file = load addr */
+ adr a1, .L__ehdr_start_off /* Get address of .L__ehdr_start_off */
+ ldr a2, .L__ehdr_start_off /* Offset from .L__ehdr_start_off to __ehdr_start */
+ add a1, a1, a2 /* Address of __ehdr_start = load addr */
bl reloc_static_pie
mov a1, #0 /* Clean up a1 so that a random address won't get called at the end of program */
@@ -325,9 +321,10 @@ _start:
.word _fini(GOT)
.word _init(GOT)
.word main(GOT)
-#ifdef L_rcrt1
- .word _start(GOT)
#endif
+#ifdef L_rcrt1
+.L__ehdr_start_off:
+ .word __ehdr_start - .L__ehdr_start_off
#endif
#endif
diff --git a/libc/sysdeps/linux/arm/fpu_control.h b/libc/sysdeps/linux/arm/fpu_control.h
index 1b9b09df6..05ac6a03c 100644
--- a/libc/sysdeps/linux/arm/fpu_control.h
+++ b/libc/sysdeps/linux/arm/fpu_control.h
@@ -1,6 +1,5 @@
-/* FPU control word definitions. ARM version.
- Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
+/* FPU control word definitions. ARM VFP version.
+ 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
@@ -13,13 +12,22 @@
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/>. */
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
#ifndef _FPU_CONTROL_H
#define _FPU_CONTROL_H
-#ifdef __VFP_FP__
+#if !(defined(_LIBC) && !defined(_LIBC_TEST)) && defined(__SOFTFP__)
+
+#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)
+extern fpu_control_t __fpu_control;
+
+#else
/* masking of interrupts */
#define _FPU_MASK_IM 0x00000100 /* invalid operation */
@@ -28,175 +36,39 @@
#define _FPU_MASK_UM 0x00000800 /* underflow */
#define _FPU_MASK_PM 0x00001000 /* inexact */
+#define _FPU_MASK_NZCV 0xf0000000 /* NZCV flags */
+#define _FPU_MASK_RM 0x00c00000 /* rounding mode */
+#define _FPU_MASK_EXCEPT 0x00001f1f /* all exception flags */
+
/* Some bits in the FPSCR are not yet defined. They must be preserved when
modifying the contents. */
-#define _FPU_RESERVED 0x0e08e0e0
+#define _FPU_RESERVED 0x00086060
#define _FPU_DEFAULT 0x00000000
-/* Default + exceptions enabled. */
+
+/* Default + exceptions enabled. */
#define _FPU_IEEE (_FPU_DEFAULT | 0x00001f00)
/* Type of the control word. */
typedef unsigned int fpu_control_t;
/* Macros for accessing the hardware control word. */
+#ifdef __SOFTFP__
/* This is fmrx %0, fpscr. */
-#define _FPU_GETCW(cw) \
+# define _FPU_GETCW(cw) \
__asm__ __volatile__ ("mrc p10, 7, %0, cr1, cr0, 0" : "=r" (cw))
/* This is fmxr fpscr, %0. */
-#define _FPU_SETCW(cw) \
+# define _FPU_SETCW(cw) \
__asm__ __volatile__ ("mcr p10, 7, %0, cr1, cr0, 0" : : "r" (cw))
+#else
+# define _FPU_GETCW(cw) \
+ __asm__ __volatile__ ("vmrs %0, fpscr" : "=r" (cw))
+# define _FPU_SETCW(cw) \
+ __asm__ __volatile__ ("vmsr fpscr, %0" : : "r" (cw))
+#endif
-#elif defined __MAVERICK__
-
-/* DSPSC register: (from EP9312 User's Guide)
- *
- * bits 31..29 - DAID
- * bits 28..26 - HVID
- * bits 25..24 - RSVD
- * bit 23 - ISAT
- * bit 22 - UI
- * bit 21 - INT
- * bit 20 - AEXC
- * bits 19..18 - SAT
- * bits 17..16 - FCC
- * bit 15 - V
- * bit 14 - FWDEN
- * bit 13 - Invalid
- * bit 12 - Denorm
- * bits 11..10 - RM
- * bits 9..5 - IXE, UFE, OFE, RSVD, IOE
- * bits 4..0 - IX, UF, OF, RSVD, IO
- */
-
-/* masking of interrupts */
-#define _FPU_MASK_IM (1 << 5) /* invalid operation */
-#define _FPU_MASK_ZM 0 /* divide by zero */
-#define _FPU_MASK_OM (1 << 7) /* overflow */
-#define _FPU_MASK_UM (1 << 8) /* underflow */
-#define _FPU_MASK_PM (1 << 9) /* inexact */
-#define _FPU_MASK_DM 0 /* denormalized operation */
-
-#define _FPU_RESERVED 0xfffff000 /* These bits are reserved. */
-
-#define _FPU_DEFAULT 0x00b00000 /* Default value. */
-#define _FPU_IEEE 0x00b003a0 /* Default + exceptions enabled. */
-
-/* Type of the control word. */
-typedef unsigned int fpu_control_t;
-
-/* Macros for accessing the hardware control word. */
-#define _FPU_GETCW(cw) ({ \
- register int __t1, __t2; \
- \
- __asm__ __volatile__ ( \
- "cfmvr64l %1, mvdx0\n\t" \
- "cfmvr64h %2, mvdx0\n\t" \
- "cfmv32sc mvdx0, dspsc\n\t" \
- "cfmvr64l %0, mvdx0\n\t" \
- "cfmv64lr mvdx0, %1\n\t" \
- "cfmv64hr mvdx0, %2" \
- : "=r" (cw), "=r" (__t1), "=r" (__t2) \
- ); \
-})
-
-#define _FPU_SETCW(cw) ({ \
- register int __t0, __t1, __t2; \
- \
- __asm__ __volatile__ ( \
- "cfmvr64l %1, mvdx0\n\t" \
- "cfmvr64h %2, mvdx0\n\t" \
- "cfmv64lr mvdx0, %0\n\t" \
- "cfmvsc32 dspsc, mvdx0\n\t" \
- "cfmv64lr mvdx0, %1\n\t" \
- "cfmv64hr mvdx0, %2" \
- : "=r" (__t0), "=r" (__t1), "=r" (__t2) \
- : "0" (cw) \
- ); \
-})
-
-#else /* !__MAVERICK__ */
-
-/* We have a slight terminology confusion here. On the ARM, the register
- * we're interested in is actually the FPU status word - the FPU control
- * word is something different (which is implementation-defined and only
- * accessible from supervisor mode.)
- *
- * The FPSR looks like this:
- *
- * 31-24 23-16 15-8 7-0
- * | system ID | trap enable | system control | exception flags |
- *
- * We ignore the system ID bits; for interest's sake they are:
- *
- * 0000 "old" FPE
- * 1000 FPPC hardware
- * 0001 FPE 400
- * 1001 FPA hardware
- *
- * The trap enable and exception flags are both structured like this:
- *
- * 7 - 5 4 3 2 1 0
- * | reserved | INX | UFL | OFL | DVZ | IVO |
- *
- * where a `1' bit in the enable byte means that the trap can occur, and
- * a `1' bit in the flags byte means the exception has occurred.
- *
- * The exceptions are:
- *
- * IVO - invalid operation
- * DVZ - divide by zero
- * OFL - overflow
- * UFL - underflow
- * INX - inexact (do not use; implementations differ)
- *
- * The system control byte looks like this:
- *
- * 7-5 4 3 2 1 0
- * | reserved | AC | EP | SO | NE | ND |
- *
- * where the bits mean
- *
- * ND - no denormalised numbers (force them all to zero)
- * NE - enable NaN exceptions
- * SO - synchronous operation
- * EP - use expanded packed-decimal format
- * AC - use alternate definition for C flag on compare operations
- */
-
-/* masking of interrupts */
-#define _FPU_MASK_IM 0x00010000 /* invalid operation */
-#define _FPU_MASK_ZM 0x00020000 /* divide by zero */
-#define _FPU_MASK_OM 0x00040000 /* overflow */
-#define _FPU_MASK_UM 0x00080000 /* underflow */
-#define _FPU_MASK_PM 0x00100000 /* inexact */
-#define _FPU_MASK_DM 0x00000000 /* denormalized operation */
-
-/* The system id bytes cannot be changed.
- Only the bottom 5 bits in the trap enable byte can be changed.
- Only the bottom 5 bits in the system control byte can be changed.
- Only the bottom 5 bits in the exception flags are used.
- The exception flags are set by the fpu, but can be zeroed by the user. */
-#define _FPU_RESERVED 0xffe0e0e0 /* These bits are reserved. */
-
-/* The fdlibm code requires strict IEEE double precision arithmetic,
- no interrupts for exceptions, rounding to nearest. Changing the
- rounding mode will break long double I/O. Turn on the AC bit,
- the compiler generates code that assumes it is on. */
-#define _FPU_DEFAULT 0x00001000 /* Default value. */
-#define _FPU_IEEE 0x001f1000 /* Default + exceptions enabled. */
-
-/* Type of the control word. */
-typedef unsigned int fpu_control_t;
-
-/* Macros for accessing the hardware control word. */
-#define _FPU_GETCW(cw) __asm__ ("rfs %0" : "=r" (cw))
-#define _FPU_SETCW(cw) __asm__ ("wfs %0" : : "r" (cw))
-
-#endif /* __MAVERICK__ */
-
-#if 0
/* Default control word set at startup. */
extern fpu_control_t __fpu_control;
-#endif
+
+#endif /* __SOFTFP__ */
#endif /* _FPU_CONTROL_H */
diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in
index e0b280c33..4a4317432 100644
--- a/libc/sysdeps/linux/common/Makefile.in
+++ b/libc/sysdeps/linux/common/Makefile.in
@@ -27,6 +27,7 @@ CSRC-$(UCLIBC_LINUX_SPECIFIC) += \
eventfd_write.c \
fanotify.c \
getrandom.c \
+ getentropy.c \
inotify.c \
ioperm.c \
iopl.c \
diff --git a/libc/sysdeps/linux/common/bits/msq.h b/libc/sysdeps/linux/common/bits/msq.h
index b594cfff2..0cb734263 100644
--- a/libc/sysdeps/linux/common/bits/msq.h
+++ b/libc/sysdeps/linux/common/bits/msq.h
@@ -37,17 +37,31 @@ typedef unsigned long int msglen_t;
struct msqid_ds
{
struct ipc_perm msg_perm; /* structure describing operation permission */
+#if (__WORDSIZE == 32 && defined(__riscv) && defined(__UCLIBC_USE_TIME64__))
+ unsigned long int msg_stime_internal_1;
+ unsigned long int msg_stime_internal_2;
+ unsigned long int msg_rtime_internal_1;
+ unsigned long int msg_rtime_internal_2;
+ unsigned long int msg_ctime_internal_1;
+ unsigned long int msg_ctime_internal_2;
+#else
__time_t msg_stime; /* time of last msgsnd command */
unsigned long int __uclibc_unused1;
__time_t msg_rtime; /* time of last msgrcv command */
unsigned long int __uclibc_unused2;
__time_t msg_ctime; /* time of last change */
unsigned long int __uclibc_unused3;
+#endif
unsigned long int __msg_cbytes; /* current number of bytes on queue */
msgqnum_t msg_qnum; /* number of messages currently on queue */
msglen_t msg_qbytes; /* max number of bytes allowed on queue */
__pid_t msg_lspid; /* pid of last msgsnd() */
__pid_t msg_lrpid; /* pid of last msgrcv() */
+#if (__WORDSIZE == 32 && defined(__riscv) && defined(__UCLIBC_USE_TIME64__))
+ __time_t msg_stime; /* time of last msgsnd command */
+ __time_t msg_rtime; /* time of last msgrcv command */
+ __time_t msg_ctime; /* time of last change */
+#endif
unsigned long int __uclibc_unused4;
unsigned long int __uclibc_unused5;
};
diff --git a/libc/sysdeps/linux/common/bits/nan.h b/libc/sysdeps/linux/common/bits/nan.h
index 00cb405f1..46cfb613f 100644
--- a/libc/sysdeps/linux/common/bits/nan.h
+++ b/libc/sysdeps/linux/common/bits/nan.h
@@ -25,7 +25,9 @@
#if __GNUC_PREREQ(3,3)
-# define NAN (__builtin_nanf (""))
+# ifndef NAN
+# define NAN (__builtin_nanf (""))
+# endif
#elif defined __GNUC__
diff --git a/libc/sysdeps/linux/common/bits/sem.h b/libc/sysdeps/linux/common/bits/sem.h
index 24a130981..d855494ee 100644
--- a/libc/sysdeps/linux/common/bits/sem.h
+++ b/libc/sysdeps/linux/common/bits/sem.h
@@ -45,8 +45,8 @@ struct semid_ds
#else
__time_t sem_otime; /* last semop() time */
#endif
-#if (__WORDSIZE == 32 && !defined(__ARC64_ARCH32__) && !defined(__arc__) && !defined(__arm__) && !defined(__or1k__) && !defined(__xtensa__)) || \
- ((defined(__ARC64_ARCH32__) || defined(__arc__) || defined(__arm__) || defined(__or1k__) || defined(__xtensa__)) && !defined(__UCLIBC_USE_TIME64__))
+#if (__WORDSIZE == 32 && !defined(__ARC64_ARCH32__) && !defined(__arc__) && !defined(__arm__) && !defined(__or1k__) && !defined(__xtensa__) && !defined(__riscv)) || \
+ ((defined(__ARC64_ARCH32__) || defined(__arc__) || defined(__arm__) || defined(__or1k__) || defined(__xtensa__) || defined(__riscv)) && !defined(__UCLIBC_USE_TIME64__))
unsigned long int __uclibc_unused1;
#endif
#if defined(__UCLIBC_USE_TIME64__)
@@ -55,8 +55,8 @@ struct semid_ds
#else
__time_t sem_ctime; /* last time changed by semctl() */
#endif
-#if (__WORDSIZE == 32 && !defined(__ARC64_ARCH32__) && !defined(__arc__) && !defined(__arm__) && !defined(__or1k__) && !defined(__xtensa__)) || \
- ((defined(__ARC64_ARCH32__) || defined(__arc__) || defined(__arm__) || defined(__or1k__) || defined(__xtensa__)) && !defined(__UCLIBC_USE_TIME64__))
+#if (__WORDSIZE == 32 && !defined(__ARC64_ARCH32__) && !defined(__arc__) && !defined(__arm__) && !defined(__or1k__) && !defined(__xtensa__) && !defined(__riscv)) || \
+ ((defined(__ARC64_ARCH32__) || defined(__arc__) || defined(__arm__) || defined(__or1k__) || defined(__xtensa__) || defined(__riscv)) && !defined(__UCLIBC_USE_TIME64__))
unsigned long int __uclibc_unused2;
#endif
unsigned long int sem_nsems; /* number of semaphores in set */
diff --git a/libc/sysdeps/linux/common/clock_adjtime.c b/libc/sysdeps/linux/common/clock_adjtime.c
index 53f64e9d5..ada256ccd 100644
--- a/libc/sysdeps/linux/common/clock_adjtime.c
+++ b/libc/sysdeps/linux/common/clock_adjtime.c
@@ -15,5 +15,5 @@ _syscall2_64(int, clock_adjtime, clockid_t, clock_id, struct timex*, ntx)
#elif defined(__NR_clock_adjtime)
_syscall2(int, clock_adjtime, clockid_t, clock_id, struct timex*, ntx)
#else
-#error "clock_adjtime syscall is not defined!"
+#warning "clock_adjtime syscall is not defined!"
#endif
diff --git a/libc/sysdeps/linux/common/getentropy.c b/libc/sysdeps/linux/common/getentropy.c
new file mode 100644
index 000000000..d255310b6
--- /dev/null
+++ b/libc/sysdeps/linux/common/getentropy.c
@@ -0,0 +1,46 @@
+/*
+ * getentropy() by wrapping getrandom(), for µClibc-ng
+ *
+ * © 2025 mirabilos Ⓕ CC0 or MirBSD or GNU LGPLv2
+ *
+ * Note: may be a thread cancellation point, unlike the
+ * implementations in glibc and musl libc. Should this
+ * ever become a concern, it will need patching.
+ */
+
+#define _DEFAULT_SOURCE
+#include <errno.h>
+#include <unistd.h>
+#include <sys/random.h>
+#include <sys/syscall.h>
+
+#ifdef __NR_getrandom
+int
+getentropy(void *__buf, size_t __len)
+{
+ ssize_t n;
+
+ if (__len > 256U) {
+ errno = EIO;
+ return (-1);
+ }
+
+ again:
+ if ((n = getrandom(__buf, __len, 0)) == -1)
+ switch (errno) {
+ case EAGAIN: /* should not happen but better safe than sorry */
+ case EINTR:
+ goto again;
+ default:
+ errno = EIO;
+ /* FALLTHROUGH */
+ case EFAULT:
+ case ENOSYS:
+ return (-1);
+ }
+ if ((size_t)n != __len)
+ /* also shouldn’t happen (safety net) */
+ goto again;
+ return (0);
+}
+#endif
diff --git a/libc/sysdeps/linux/common/getrandom.c b/libc/sysdeps/linux/common/getrandom.c
index bb9841463..1db1663b9 100644
--- a/libc/sysdeps/linux/common/getrandom.c
+++ b/libc/sysdeps/linux/common/getrandom.c
@@ -8,6 +8,7 @@
#include <sys/syscall.h>
#include <sys/random.h>
+
#ifdef __NR_getrandom
-_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
+_syscall3(ssize_t, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
#endif
diff --git a/libc/sysdeps/linux/common/sys/random.h b/libc/sysdeps/linux/common/sys/random.h
index 3d24e439b..c3d9cf575 100644
--- a/libc/sysdeps/linux/common/sys/random.h
+++ b/libc/sysdeps/linux/common/sys/random.h
@@ -4,11 +4,19 @@
#ifndef _SYS_RANDOM_H
#define _SYS_RANDOM_H 1
+
#include <features.h>
#include <stddef.h>
__BEGIN_DECLS
+#include <bits/types.h>
+
+#ifndef __ssize_t_defined
+typedef __ssize_t ssize_t;
+# define __ssize_t_defined
+#endif
+
#if defined __UCLIBC_LINUX_SPECIFIC__
# if 0 /*def __ASSUME_GETRANDOM_SYSCALL */
# include <linux/random.h>
@@ -26,9 +34,15 @@ __BEGIN_DECLS
# define GRND_RANDOM 0x0002
# define GRND_INSECURE 0x0004
# endif
-/* FIXME: aren't there a couple of __restrict and const missing ? */
-extern int getrandom(void *__buf, size_t count, unsigned int flags)
+extern ssize_t getrandom(void *__buf, size_t count, unsigned int flags)
__nonnull ((1)) __wur;
+
+/* OpenBSD-compatible access to random bytes.
+ May be a cancellation point here, unlike in glibc/musl. */
+# ifndef __getentropy_defined
+extern int getentropy(void *__buf, size_t __len) __nonnull ((1)) __wur;
+# define __getentropy_defined
+# endif
#endif
__END_DECLS
diff --git a/libc/sysdeps/linux/common/utimes.c b/libc/sysdeps/linux/common/utimes.c
index a28594dfd..c471a9b89 100644
--- a/libc/sysdeps/linux/common/utimes.c
+++ b/libc/sysdeps/linux/common/utimes.c
@@ -9,7 +9,7 @@
#include <sys/syscall.h>
#include <sys/time.h>
-#if (defined (__NR_utimensat) || defined(__NR_utimensat_time64)) && !defined __NR_utimes
+#if (defined (__NR_utimensat) || defined(__NR_utimensat_time64)) && (!defined __NR_utimes || defined(__UCLIBC_USE_TIME64__))
# include <fcntl.h>
# include <stddef.h>
int utimes(const char *file, const struct timeval tvp[2])
@@ -50,6 +50,6 @@ int utimes(const char *file, const struct timeval tvp[2])
}
#endif
-#if defined __NR_utimensat || defined __NR_utimensat_time64 || defined __NR_utimes || defined __NR_utime
+#if (((defined __NR_utimensat || defined __NR_utimensat_time64) && (!defined __NR_utimes || defined __UCLIBC_USE_TIME64__))) || defined __NR_utimes || defined __NR_utime
libc_hidden_def(utimes)
#endif
diff --git a/libc/sysdeps/linux/csky/bits/fenv.h b/libc/sysdeps/linux/csky/bits/fenv.h
index 3359e1f8e..1428f385a 100644
--- a/libc/sysdeps/linux/csky/bits/fenv.h
+++ b/libc/sysdeps/linux/csky/bits/fenv.h
@@ -1,65 +1,108 @@
-/*
- * Copyright (C) 2017 Hangzhou C-SKY Microsystems co.,ltd.
- *
- * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB
- * in this tarball.
- */
+/* Floating point environment. C-SKY version.
+ Copyright (C) 2018-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 the exception. We use the bit positions of
- the appropriate bits in the FPSR Accrued Exception Byte. */
+#ifdef __csky_hard_float__
+/* Define bits representing the exception. We use the bit positions
+ of the appropriate bits in the FPU control word. */
enum
{
- FE_INEXACT = 1 << 3,
-#define FE_INEXACT FE_INEXACT
- FE_DIVBYZERO = 1 << 4,
-#define FE_DIVBYZERO FE_DIVBYZERO
- FE_UNDERFLOW = 1 << 5,
-#define FE_UNDERFLOW FE_UNDERFLOW
- FE_OVERFLOW = 1 << 6,
-#define FE_OVERFLOW FE_OVERFLOW
- FE_INVALID = 1 << 7
-#define FE_INVALID FE_INVALID
+ 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,
+ __FE_DENORMAL = 0x20
};
#define FE_ALL_EXCEPT \
(FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
-/* The csky FPU supports all of the four defined rounding modes. We use
- the bit positions in the FPCR Mode Control Byte as the values for the
- appropriate macros. */
+/* The C-SKY FPU supports all of the four defined rounding modes. We
+ use again the bit positions in the FPU control word as the values
+ for the appropriate macros. */
+enum
+ {
+ FE_TONEAREST =
+#define FE_TONEAREST (0x0 << 24)
+ FE_TONEAREST,
+ FE_TOWARDZERO =
+#define FE_TOWARDZERO (0x1 << 24)
+ FE_TOWARDZERO,
+ FE_UPWARD =
+#define FE_UPWARD (0x2 << 24)
+ FE_UPWARD,
+ FE_DOWNWARD =
+#define FE_DOWNWARD (0x3 << 24)
+ FE_DOWNWARD,
+ __FE_ROUND_MASK = (0x3 << 24)
+ };
+
+#else
+
+/* In the soft-float case, only rounding to nearest is supported, with
+ no exceptions. */
+
enum
{
- FE_TONEAREST = 0,
-#define FE_TONEAREST FE_TONEAREST
- FE_TOWARDZERO = 1 << 4,
-#define FE_TOWARDZERO FE_TOWARDZERO
- FE_DOWNWARD = 2 << 4,
-#define FE_DOWNWARD FE_DOWNWARD
- FE_UPWARD = 3 << 4
-#define FE_UPWARD FE_UPWARD
+ __FE_UNDEFINED = -1,
+
+ FE_TONEAREST =
+# define FE_TONEAREST 0x0
+ FE_TONEAREST
};
+# define FE_ALL_EXCEPT 0
+
+#endif
+
/* Type representing exception flags. */
typedef unsigned int fexcept_t;
-/* Type representing floating-point environment. This structure
- corresponds to the layout of the block written by `fmovem'. */
+/* Type representing floating-point environment. */
typedef struct
- {
- unsigned int __control_register;
- unsigned int __status_register;
- unsigned int __instruction_address;
- }
-fenv_t;
+{
+ 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)
+#define FE_DFL_ENV ((const fenv_t *) -1)
-#ifdef __USE_GNU
+#if defined __USE_GNU && defined __csky_hard_float__
/* Floating-point environment where none of the exceptions are masked. */
-# define FE_NOMASK_ENV ((__const fenv_t *) -2)
+# 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/csky/fpu_control.h b/libc/sysdeps/linux/csky/fpu_control.h
new file mode 100644
index 000000000..a2d615554
--- /dev/null
+++ b/libc/sysdeps/linux/csky/fpu_control.h
@@ -0,0 +1,147 @@
+/* FPU control word bits. C-SKY version.
+ Copyright (C) 2018-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
+
+/* C-SKY FPU floating point control register bits.
+
+ 31-28 -> Reserved (read as 0, write with 0).
+ 27 -> 0: Flush denormalized results to zero.
+ 1: Flush denormalized results to signed minimal normal number.
+ 26 -> Reserved (read as 0, write with 0).
+ 25-24 -> Rounding control.
+ 23-6 -> Reserved (read as 0, write with 0).
+ 5 -> Enable exception for input denormalized exception.
+ 4 -> Enable exception for inexact exception.
+ 3 -> Enable exception for underflow exception.
+ 2 -> Enable exception for overflow exception.
+ 1 -> Enable exception for division by zero exception.
+ 0 -> Enable exception for invalid operation exception.
+
+ Rounding Control:
+ 00 - Rounding to nearest (RN).
+ 01 - Rounding toward zero (RZ).
+ 10 - Rounding (up) toward plus infinity (RP).
+ 11 - Rounding (down)toward minus infinity (RM).
+
+ C-SKY FPU floating point exception status register bits.
+
+ 15 -> Accumulate bit for any exception.
+ 14 -> Reserved (read as 0, write with 0).
+ 13 -> Cause bit for input denormalized exception.
+ 12 -> Cause bit for inexact exception.
+ 11 -> Cause bit for underflow exception.
+ 10 -> Cause bit for overflow exception.
+ 9 -> Cause bit for division by zero exception.
+ 8 -> Cause bit for invalid operation exception.
+ 7 -> Flag bit for any exception.
+ 6 -> Reserved (read as 0, write with 0).
+ 5 -> Flag exception for input denormalized exception.
+ 4 -> Flag exception for inexact exception.
+ 3 -> Flag exception for underflow exception.
+ 2 -> Flag exception for overflow exception.
+ 1 -> Flag exception for division by zero exception.
+ 0 -> Flag exception for invalid operation exception. */
+
+#include <features.h>
+
+#ifdef __csky_soft_float__
+
+# 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_GETFPSR(cw) (cw) = 0
+# define _FPU_SETFPSR(cw) (void) (cw)
+extern fpu_control_t __fpu_control;
+
+#else /* __csky_soft_float__ */
+
+/* Masking of interrupts. */
+# define _FPU_MASK_IDE (1 << 5) /* Input denormalized exception. */
+# define _FPU_MASK_IXE (1 << 4) /* Inexact exception. */
+# define _FPU_MASK_UFE (1 << 3) /* Underflow exception. */
+# define _FPU_MASK_OFE (1 << 2) /* Overflow exception. */
+# define _FPU_MASK_DZE (1 << 1) /* Division by zero exception. */
+# define _FPU_MASK_IOE (1 << 0) /* Invalid operation exception. */
+
+# define _FPU_MASK_FEA (1 << 15) /* Case for any exception. */
+# define _FPU_MASK_FEC (1 << 7) /* Flag for any exception. */
+
+/* Flush denormalized numbers to zero. */
+# define _FPU_FLUSH_TZ 0x8000000
+
+/* Rounding control. */
+# define _FPU_RC_NEAREST (0x0 << 24) /* RECOMMENDED. */
+# define _FPU_RC_ZERO (0x1 << 24)
+# define _FPU_RC_UP (0x2 << 24)
+# define _FPU_RC_DOWN (0x3 << 24)
+
+# define _FPU_RESERVED 0xf460ffc0 /* Reserved bits in cw. */
+# define _FPU_FPSR_RESERVED 0xffff4040
+
+/* The fdlibm code requires strict IEEE double precision arithmetic,
+ and no interrupts for exceptions, rounding to nearest. */
+
+# define _FPU_DEFAULT 0x00000000
+# define _FPU_FPSR_DEFAULT 0x00000000
+
+/* IEEE: same as above, but exceptions. */
+# define _FPU_FPCR_IEEE 0x0000001F
+# define _FPU_FPSR_IEEE 0x00000000
+
+/* Type of the control word. */
+typedef unsigned int fpu_control_t;
+
+/* Macros for accessing the hardware control word. */
+# if (__CSKY__ == 2)
+# define _FPU_GETCW(cw) __asm__ volatile ("mfcr %0, cr<1, 2>" : "=a" (cw))
+# define _FPU_SETCW(cw) __asm__ volatile ("mtcr %0, cr<1, 2>" : : "a" (cw))
+# define _FPU_GETFPSR(cw) __asm__ volatile ("mfcr %0, cr<2, 2>" : "=a" (cw))
+# define _FPU_SETFPSR(cw) __asm__ volatile ("mtcr %0, cr<2, 2>" : : "a" (cw))
+# else
+# define _FPU_GETCW(cw) __asm__ volatile ("1: cprcr %0, cpcr2 \n" \
+ " btsti %0, 31 \n" \
+ " bt 1b \n" \
+ " cprcr %0, cpcr1\n" : "=b" (cw))
+
+# define _FPU_SETCW(cw) __asm__ volatile ("1: cprcr r7, cpcr2 \n" \
+ " btsti r7, 31 \n" \
+ " bt 1b \n" \
+ " cpwcr %0, cpcr1 \n" \
+ : : "b" (cw) : "r7")
+
+# define _FPU_GETFPSR(cw) __asm__ volatile ("1: cprcr %0, cpcr2 \n" \
+ " btsti %0, 31 \n" \
+ " bt 1b \n" \
+ " cprcr %0, cpcr4\n" : "=b" (cw))
+
+# define _FPU_SETFPSR(cw) __asm__ volatile ("1: cprcr r7, cpcr2 \n" \
+ " btsti r7, 31 \n" \
+ " bt 1b \n" \
+ " cpwcr %0, cpcr4 \n" \
+ : : "b" (cw) : "r7")
+# endif /* __CSKY__ != 2 */
+
+/* Default control word set at startup. */
+extern fpu_control_t __fpu_control;
+
+#endif /* !__csky_soft_float__ */
+
+#endif /* fpu_control.h */
diff --git a/libc/sysdeps/linux/kvx/bits/shm.h b/libc/sysdeps/linux/kvx/bits/shm.h
new file mode 100644
index 000000000..bfb603499
--- /dev/null
+++ b/libc/sysdeps/linux/kvx/bits/shm.h
@@ -0,0 +1,87 @@
+/*
+ * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB
+ * in this tarball.
+ */
+
+#ifndef _SYS_SHM_H
+# error "Never include <bits/shm.h> directly; use <sys/shm.h> instead."
+#endif
+
+#include <bits/types.h>
+
+/* Permission flag for shmget. */
+#define SHM_R 0400 /* or S_IRUGO from <linux/stat.h> */
+#define SHM_W 0200 /* or S_IWUGO from <linux/stat.h> */
+
+/* Flags for `shmat'. */
+#define SHM_RDONLY 010000 /* attach read-only else read-write */
+#define SHM_RND 020000 /* round attach address to SHMLBA */
+#define SHM_REMAP 040000 /* take-over region on attach */
+
+/* Commands for `shmctl'. */
+#define SHM_LOCK 11 /* lock segment (root only) */
+#define SHM_UNLOCK 12 /* unlock segment (root only) */
+
+__BEGIN_DECLS
+
+/* Segment low boundary address multiple. */
+#define SHMLBA (__getpagesize () << 2)
+extern int __getpagesize (void) __THROW __attribute__ ((__const__));
+
+
+/* Type to count number of attaches. */
+typedef unsigned long int shmatt_t;
+
+/* Data structure describing a set of semaphores. */
+struct shmid_ds
+ {
+ struct ipc_perm shm_perm; /* operation permission struct */
+ size_t shm_segsz; /* size of segment in bytes */
+ __time_t shm_atime; /* time of last shmat() */
+ __time_t shm_dtime; /* time of last shmdt() */
+ __time_t shm_ctime; /* time of last change by shmctl() */
+ __pid_t shm_cpid; /* pid of creator */
+ __pid_t shm_lpid; /* pid of last shmop */
+ shmatt_t shm_nattch; /* number of current attaches */
+ unsigned long int __uclibc_unused1;
+ unsigned long int __uclibc_unused2;
+ };
+
+#ifdef __USE_MISC
+
+/* ipcs ctl commands */
+# define SHM_STAT 13
+# define SHM_INFO 14
+
+/* shm_mode upper byte flags */
+# define SHM_DEST 01000 /* segment will be destroyed on last detach */
+# define SHM_LOCKED 02000 /* segment will not be swapped */
+# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */
+# define SHM_NORESERVE 010000 /* don't check for reservations */
+
+struct shminfo
+ {
+ unsigned long int shmmax;
+ unsigned long int shmmin;
+ unsigned long int shmmni;
+ unsigned long int shmseg;
+ unsigned long int shmall;
+ unsigned long int __uclibc_unused1;
+ unsigned long int __uclibc_unused2;
+ unsigned long int __uclibc_unused3;
+ unsigned long int __uclibc_unused4;
+ };
+
+struct shm_info
+ {
+ int used_ids;
+ unsigned long int shm_tot; /* total allocated shm */
+ unsigned long int shm_rss; /* total resident shm */
+ unsigned long int shm_swp; /* total swapped shm */
+ unsigned long int swap_attempts;
+ unsigned long int swap_successes;
+ };
+
+#endif /* __USE_MISC */
+
+__END_DECLS
diff --git a/libc/sysdeps/linux/m68k/bits/fenv.h b/libc/sysdeps/linux/m68k/bits/fenv.h
index b07f0ab51..37c5fe829 100644
--- a/libc/sysdeps/linux/m68k/bits/fenv.h
+++ b/libc/sysdeps/linux/m68k/bits/fenv.h
@@ -1,5 +1,4 @@
-/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
+/* Copyright (C) 1997-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
@@ -12,31 +11,38 @@
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/>. */
+ 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
+#if defined __HAVE_68881__ || defined __HAVE_FPU__ || defined __mcffpu__
+
/* Define bits representing the exception. We use the bit positions of
the appropriate bits in the FPSR Accrued Exception Byte. */
enum
{
- FE_INEXACT = 1 << 3,
-#define FE_INEXACT FE_INEXACT
- FE_DIVBYZERO = 1 << 4,
-#define FE_DIVBYZERO FE_DIVBYZERO
- FE_UNDERFLOW = 1 << 5,
-#define FE_UNDERFLOW FE_UNDERFLOW
- FE_OVERFLOW = 1 << 6,
-#define FE_OVERFLOW FE_OVERFLOW
- FE_INVALID = 1 << 7
-#define FE_INVALID FE_INVALID
+ FE_INEXACT =
+# define FE_INEXACT (1 << 3)
+ FE_INEXACT,
+ FE_DIVBYZERO =
+# define FE_DIVBYZERO (1 << 4)
+ FE_DIVBYZERO,
+ FE_UNDERFLOW =
+# define FE_UNDERFLOW (1 << 5)
+ FE_UNDERFLOW,
+ FE_OVERFLOW =
+# define FE_OVERFLOW (1 << 6)
+ FE_OVERFLOW,
+ FE_INVALID =
+# define FE_INVALID (1 << 7)
+ FE_INVALID
};
-#define FE_ALL_EXCEPT \
+# define FE_ALL_EXCEPT \
(FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
/* The m68k FPU supports all of the four defined rounding modes. We use
@@ -44,21 +50,45 @@ enum
appropriate macros. */
enum
{
- FE_TONEAREST = 0,
-#define FE_TONEAREST FE_TONEAREST
- FE_TOWARDZERO = 1 << 4,
-#define FE_TOWARDZERO FE_TOWARDZERO
- FE_DOWNWARD = 2 << 4,
-#define FE_DOWNWARD FE_DOWNWARD
- FE_UPWARD = 3 << 4
-#define FE_UPWARD FE_UPWARD
+ FE_TONEAREST =
+# define FE_TONEAREST 0
+ FE_TONEAREST,
+ FE_TOWARDZERO =
+# define FE_TOWARDZERO (1 << 4)
+ FE_TOWARDZERO,
+ FE_DOWNWARD =
+# define FE_DOWNWARD (2 << 4)
+ FE_DOWNWARD,
+ FE_UPWARD =
+# define FE_UPWARD (3 << 4)
+ FE_UPWARD
};
+#else
+
+/* In the soft-float case, only rounding to nearest is supported, with
+ no exceptions. */
+
+# define FE_ALL_EXCEPT 0
+
+enum
+ {
+ __FE_UNDEFINED = -1,
+
+ FE_TONEAREST =
+# define FE_TONEAREST 0
+ FE_TONEAREST
+ };
+
+#endif
+
/* Type representing exception flags. */
typedef unsigned int fexcept_t;
+#if defined __HAVE_68881__ || defined __HAVE_FPU__ || defined __mcffpu__
+
/* Type representing floating-point environment. This structure
corresponds to the layout of the block written by `fmovem'. */
typedef struct
@@ -69,10 +99,30 @@ typedef struct
}
fenv_t;
+#else
+
+/* Keep ABI compatibility with the type used in the generic
+ bits/fenv.h, formerly used for no-FPU ColdFire. */
+typedef struct
+ {
+ fexcept_t __excepts;
+ }
+fenv_t;
+
+#endif
+
/* If the default argument is used we use this value. */
#define FE_DFL_ENV ((const fenv_t *) -1)
-#ifdef __USE_GNU
+#if defined __USE_GNU && (defined __HAVE_68881__ \
+ || defined __HAVE_FPU__ \
+ || defined __mcffpu__)
/* 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/m68k/bits/shm.h b/libc/sysdeps/linux/m68k/bits/shm.h
new file mode 100644
index 000000000..aa1a72e54
--- /dev/null
+++ b/libc/sysdeps/linux/m68k/bits/shm.h
@@ -0,0 +1,108 @@
+/* Copyright (C) 1995,1996,1997,2000,2002,2004 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_SHM_H
+# error "Never include <bits/shm.h> directly; use <sys/shm.h> instead."
+#endif
+
+#include <bits/types.h>
+
+/* Permission flag for shmget. */
+#define SHM_R 0400 /* or S_IRUGO from <linux/stat.h> */
+#define SHM_W 0200 /* or S_IWUGO from <linux/stat.h> */
+
+/* Flags for `shmat'. */
+#define SHM_RDONLY 010000 /* attach read-only else read-write */
+#define SHM_RND 020000 /* round attach address to SHMLBA */
+#define SHM_REMAP 040000 /* take-over region on attach */
+
+/* Commands for `shmctl'. */
+#define SHM_LOCK 11 /* lock segment (root only) */
+#define SHM_UNLOCK 12 /* unlock segment (root only) */
+
+__BEGIN_DECLS
+
+/* Segment low boundary address multiple. */
+#define SHMLBA (__getpagesize () << 2)
+extern int __getpagesize (void) __THROW __attribute__ ((__const__));
+
+
+/* Type to count number of attaches. */
+typedef unsigned long int shmatt_t;
+
+/* Data structure describing a set of semaphores. */
+struct shmid_ds
+ {
+ struct ipc_perm shm_perm; /* operation permission struct */
+ size_t shm_segsz; /* size of segment in bytes */
+#if defined(__UCLIBC_USE_TIME64__)
+ __time_t shm_atime;
+ __time_t shm_dtime;
+ __time_t shm_ctime;
+#else
+ __time_t shm_atime; /* time of last shmat() */
+ unsigned long int __uclibc_unused1;
+ __time_t shm_dtime; /* time of last shmdt() */
+ unsigned long int __uclibc_unused2;
+ __time_t shm_ctime; /* time of last change by shmctl() */
+ unsigned long int __uclibc_unused3;
+#endif
+ __pid_t shm_cpid; /* pid of creator */
+ __pid_t shm_lpid; /* pid of last shmop */
+ shmatt_t shm_nattch; /* number of current attaches */
+ unsigned long int __uclibc_unused4;
+ unsigned long int __uclibc_unused5;
+ };
+
+#ifdef __USE_MISC
+
+/* ipcs ctl commands */
+# define SHM_STAT 13
+# define SHM_INFO 14
+
+/* shm_mode upper byte flags */
+# define SHM_DEST 01000 /* segment will be destroyed on last detach */
+# define SHM_LOCKED 02000 /* segment will not be swapped */
+# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */
+# define SHM_NORESERVE 010000 /* don't check for reservations */
+
+struct shminfo
+ {
+ unsigned long int shmmax;
+ unsigned long int shmmin;
+ unsigned long int shmmni;
+ unsigned long int shmseg;
+ unsigned long int shmall;
+ unsigned long int __uclibc_unused1;
+ unsigned long int __uclibc_unused2;
+ unsigned long int __uclibc_unused3;
+ unsigned long int __uclibc_unused4;
+ };
+
+struct shm_info
+ {
+ int used_ids;
+ unsigned long int shm_tot; /* total allocated shm */
+ unsigned long int shm_rss; /* total resident shm */
+ unsigned long int shm_swp; /* total swapped shm */
+ unsigned long int swap_attempts;
+ unsigned long int swap_successes;
+ };
+
+#endif /* __USE_MISC */
+
+__END_DECLS
diff --git a/libc/sysdeps/linux/m68k/bsd-_setjmp.S b/libc/sysdeps/linux/m68k/bsd-_setjmp.S
index c963cccf5..eaabce8ed 100644
--- a/libc/sysdeps/linux/m68k/bsd-_setjmp.S
+++ b/libc/sysdeps/linux/m68k/bsd-_setjmp.S
@@ -13,7 +13,9 @@ _setjmp:
moveal %sp@(4), %a0
movel %sp@(0), %a0@(JB_PC)
moveml %d2-%d7/%a2-%a7, %a0@(JB_REGS)
-#if defined __HAVE_68881__ || defined __UCLIBC_HAS_FPU__
+#if defined(__mcffpu__) && defined(__UCLIBC_HAS_FPU__)
+ fmovemd %fp2-%fp7, %a0@(JB_FPREGS)
+#elif defined(__HAVE_68881__)
fmovemx %fp2-%fp7, %a0@(JB_FPREGS)
#endif
clrl %d0
diff --git a/libc/sysdeps/linux/m68k/bsd-setjmp.S b/libc/sysdeps/linux/m68k/bsd-setjmp.S
index 9daf27713..7d76d192b 100644
--- a/libc/sysdeps/linux/m68k/bsd-setjmp.S
+++ b/libc/sysdeps/linux/m68k/bsd-setjmp.S
@@ -14,7 +14,9 @@ setjmp:
moveal %sp@(4), %a0
movel %sp@(0), %a0@(JB_PC)
moveml %d2-%d7/%a2-%a7, %a0@(JB_REGS)
-#if defined __HAVE_68881__ || defined __UCLIBC_HAS_FPU__
+#if defined(__mcffpu__) && defined(__UCLIBC_HAS_FPU__)
+ fmovemd %fp2-%fp7, %a0@(JB_FPREGS)
+#elif defined(__HAVE_68881__)
fmovemx %fp2-%fp7, %a0@(JB_FPREGS)
#endif
clrl %d0
diff --git a/libc/sysdeps/linux/m68k/fpu_control.h b/libc/sysdeps/linux/m68k/fpu_control.h
index 35ad95e6d..c3a9c6326 100644
--- a/libc/sysdeps/linux/m68k/fpu_control.h
+++ b/libc/sysdeps/linux/m68k/fpu_control.h
@@ -1,6 +1,5 @@
/* 68k FPU control word definitions.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
+ 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
@@ -13,8 +12,8 @@
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/>. */
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
#ifndef _FPU_CONTROL_H
#define _FPU_CONTROL_H
@@ -29,9 +28,9 @@
* 12 -> enable trap for OVFL exception
* 11 -> enable trap for UNFL exception
* 10 -> enable trap for DZ exception
- * 9 -> enable trap for INEX2 exception
- * 8 -> enable trap for INEX1 exception
- * 7-6 -> Precision Control
+ * 9 -> enable trap for INEX2 exception (INEX on Coldfire)
+ * 8 -> enable trap for INEX1 exception (IDE on Coldfire)
+ * 7-6 -> Precision Control (only bit 6 is used on Coldfire)
* 5-4 -> Rounding Control
* 3-0 -> zero (read as 0, write as 0)
*
@@ -53,50 +52,66 @@
#include <features.h>
+#if defined (__mcoldfire__) && !defined (__mcffpu__)
+
+# define _FPU_RESERVED 0xffffffff
+# define _FPU_DEFAULT 0x00000000
+# define _FPU_GETCW(cw) ((cw) = 0)
+# define _FPU_SETCW(cw) ((void) (cw))
+
+#else
+
/* masking of interrupts */
-#define _FPU_MASK_BSUN 0x8000
-#define _FPU_MASK_SNAN 0x4000
-#define _FPU_MASK_OPERR 0x2000
-#define _FPU_MASK_OVFL 0x1000
-#define _FPU_MASK_UNFL 0x0800
-#define _FPU_MASK_DZ 0x0400
-#define _FPU_MASK_INEX1 0x0200
-#define _FPU_MASK_INEX2 0x0100
+# define _FPU_MASK_BSUN 0x8000
+# define _FPU_MASK_SNAN 0x4000
+# define _FPU_MASK_OPERR 0x2000
+# define _FPU_MASK_OVFL 0x1000
+# define _FPU_MASK_UNFL 0x0800
+# define _FPU_MASK_DZ 0x0400
+# define _FPU_MASK_INEX1 0x0200
+# define _FPU_MASK_INEX2 0x0100
/* precision control */
-#define _FPU_EXTENDED 0x00 /* RECOMMENDED */
-#define _FPU_DOUBLE 0x80
-#define _FPU_SINGLE 0x40 /* DO NOT USE */
+# ifdef __mcoldfire__
+# define _FPU_DOUBLE 0x00
+# else
+# define _FPU_EXTENDED 0x00 /* RECOMMENDED */
+# define _FPU_DOUBLE 0x80
+# endif
+# define _FPU_SINGLE 0x40 /* DO NOT USE */
/* rounding control */
-#define _FPU_RC_NEAREST 0x00 /* RECOMMENDED */
-#define _FPU_RC_ZERO 0x10
-#define _FPU_RC_DOWN 0x20
-#define _FPU_RC_UP 0x30
+# define _FPU_RC_NEAREST 0x00 /* RECOMMENDED */
+# define _FPU_RC_ZERO 0x10
+# define _FPU_RC_DOWN 0x20
+# define _FPU_RC_UP 0x30
-#define _FPU_RESERVED 0xFFFF000F /* Reserved bits in fpucr */
+# ifdef __mcoldfire__
+# define _FPU_RESERVED 0xFFFF800F
+# else
+# define _FPU_RESERVED 0xFFFF000F /* Reserved bits in fpucr */
+# endif
/* Now two recommended fpucr */
/* The fdlibm code requires no interrupts for exceptions. Don't
change the rounding mode, it would break long double I/O! */
-#define _FPU_DEFAULT 0x00000000
+# define _FPU_DEFAULT 0x00000000
/* IEEE: same as above, but exceptions. We must make it non-zero so
that __setfpucw works. This bit will be ignored. */
-#define _FPU_IEEE 0x00000001
+# define _FPU_IEEE 0x00000001
+
+/* Macros for accessing the hardware control word. */
+# define _FPU_GETCW(cw) __asm__ ("fmove%.l %!, %0" : "=dm" (cw))
+# define _FPU_SETCW(cw) __asm__ volatile ("fmove%.l %0, %!" : : "dm" (cw))
+#endif
/* Type of the control word. */
typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
-/* Macros for accessing the hardware control word. */
-#define _FPU_GETCW(cw) __asm__ ("fmove%.l %!, %0" : "=dm" (cw))
-#define _FPU_SETCW(cw) __asm__ __volatile__ ("fmove%.l %0, %!" : : "dm" (cw))
-
-#if 0
/* Default control word set at startup. */
extern fpu_control_t __fpu_control;
-#endif
#endif /* _M68K_FPU_CONTROL_H */
diff --git a/libc/sysdeps/linux/m68k/setjmp.S b/libc/sysdeps/linux/m68k/setjmp.S
index 5f05b8591..d10163ec6 100644
--- a/libc/sysdeps/linux/m68k/setjmp.S
+++ b/libc/sysdeps/linux/m68k/setjmp.S
@@ -14,7 +14,9 @@ __sigsetjmp:
moveal %sp@(4), %a0
movel %sp@(0), %a0@(JB_PC)
moveml %d2-%d7/%a2-%a7, %a0@(JB_REGS)
-#if defined __HAVE_68881__ || defined __UCLIBC_HAS_FPU__
+#if defined(__mcffpu__) && defined (__UCLIBC_HAS_FPU__)
+ fmovemd %fp2-%fp7, %a0@(JB_FPREGS)
+#elif defined(__HAVE_68881__)
fmovemx %fp2-%fp7, %a0@(JB_FPREGS)
#endif
clrl %d0
diff --git a/libc/sysdeps/linux/mips/bits/fenv.h b/libc/sysdeps/linux/mips/bits/fenv.h
index 944101f75..25ae4d9ca 100644
--- a/libc/sysdeps/linux/mips/bits/fenv.h
+++ b/libc/sysdeps/linux/mips/bits/fenv.h
@@ -1,5 +1,4 @@
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
+/* Copyright (C) 1998-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
@@ -12,31 +11,38 @@
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/>. */
+ 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
+#ifdef __mips_hard_float
+
/* Define bits representing the exception. We use the bit positions
of the appropriate bits in the FPU control word. */
enum
{
- FE_INEXACT = 0x04,
-#define FE_INEXACT FE_INEXACT
- FE_UNDERFLOW = 0x08,
-#define FE_UNDERFLOW FE_UNDERFLOW
- FE_OVERFLOW = 0x10,
-#define FE_OVERFLOW FE_OVERFLOW
- FE_DIVBYZERO = 0x20,
-#define FE_DIVBYZERO FE_DIVBYZERO
- FE_INVALID = 0x40,
-#define FE_INVALID FE_INVALID
+ FE_INEXACT =
+# define FE_INEXACT 0x04
+ FE_INEXACT,
+ FE_UNDERFLOW =
+# define FE_UNDERFLOW 0x08
+ FE_UNDERFLOW,
+ FE_OVERFLOW =
+# define FE_OVERFLOW 0x10
+ FE_OVERFLOW,
+ FE_DIVBYZERO =
+# define FE_DIVBYZERO 0x20
+ FE_DIVBYZERO,
+ FE_INVALID =
+# define FE_INVALID 0x40
+ FE_INVALID,
};
-#define FE_ALL_EXCEPT \
+# define FE_ALL_EXCEPT \
(FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
/* The MIPS FPU supports all of the four defined rounding modes. We
@@ -44,16 +50,38 @@ enum
for the appropriate macros. */
enum
{
- FE_TONEAREST = 0x0,
-#define FE_TONEAREST FE_TONEAREST
- FE_TOWARDZERO = 0x1,
-#define FE_TOWARDZERO FE_TOWARDZERO
- FE_UPWARD = 0x2,
-#define FE_UPWARD FE_UPWARD
- FE_DOWNWARD = 0x3
-#define FE_DOWNWARD FE_DOWNWARD
+ FE_TONEAREST =
+# define FE_TONEAREST 0x0
+ FE_TONEAREST,
+ FE_TOWARDZERO =
+# define FE_TOWARDZERO 0x1
+ FE_TOWARDZERO,
+ FE_UPWARD =
+# define FE_UPWARD 0x2
+ FE_UPWARD,
+ FE_DOWNWARD =
+# define FE_DOWNWARD 0x3
+ FE_DOWNWARD
};
+#else
+
+/* In the soft-float case, only rounding to nearest is supported, with
+ no exceptions. */
+
+enum
+ {
+ __FE_UNDEFINED = -1,
+
+ FE_TONEAREST =
+# define FE_TONEAREST 0x0
+ FE_TONEAREST
+ };
+
+# define FE_ALL_EXCEPT 0
+
+#endif
+
/* Type representing exception flags. */
typedef unsigned short int fexcept_t;
@@ -70,7 +98,13 @@ fenv_t;
/* If the default argument is used we use this value. */
#define FE_DFL_ENV ((const fenv_t *) -1)
-#ifdef __USE_GNU
+#if defined __USE_GNU && defined __mips_hard_float
/* Floating-point environment where none of the exception is 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/mips/bits/msq.h b/libc/sysdeps/linux/mips/bits/msq.h
index bcf1073e8..141b1ff9f 100644
--- a/libc/sysdeps/linux/mips/bits/msq.h
+++ b/libc/sysdeps/linux/mips/bits/msq.h
@@ -35,30 +35,58 @@ typedef unsigned long int msglen_t;
/* Structure of record for one message inside the kernel.
The type `struct msg' is opaque. */
+#if (__WORDSIZE == 32) && defined(__MIPSEL__)
struct msqid_ds
{
struct ipc_perm msg_perm; /* structure describing operation permission */
-#if (__WORDSIZE == 32) && !defined(__MIPSEL__)
- unsigned long __unused1;
-#endif
- __time_t msg_stime; /* time of last msgsnd command */
-#if (__WORDSIZE == 32) && defined(__MIPSEL__)
- unsigned long __unused1;
-#endif
-#if (__WORDSIZE == 32) && !defined(__MIPSEL__)
- unsigned long __unused2;
-#endif
- __time_t msg_rtime; /* time of last msgrcv command */
-#if (__WORDSIZE == 32) && defined(__MIPSEL__)
- unsigned long __unused2;
-#endif
-#if (__WORDSIZE == 32) && !defined(__MIPSEL__)
- unsigned long __unused3;
-#endif
- __time_t msg_ctime; /* time of last change */
-#if (__WORDSIZE == 32) && defined(__MIPSEL__)
- unsigned long __unused3;
-#endif
+# if defined(__UCLIBC_USE_TIME64__)
+ unsigned long msg_stime_internal_1; /* time of last msgsnd command */
+ unsigned long msg_stime_internal_2;
+ unsigned long msg_rtime_internal_1; /* time of last msgrcv command */
+ unsigned long msg_rtime_internal_2;
+ unsigned long msg_ctime_internal_1; /* time of last change */
+ unsigned long msg_ctime_internal_2;
+# else
+ __time_t msg_stime;
+ unsigned long int __uclibc_unused1;
+ __time_t msg_rtime;
+ unsigned long int __uclibc_unused2;
+ __time_t msg_ctime;
+ unsigned long int __uclibc_unused3;
+# endif
+ unsigned long int __msg_cbytes; /* current number of bytes on queue */
+ msgqnum_t msg_qnum; /* number of messages currently on queue */
+ msglen_t msg_qbytes; /* max number of bytes allowed on queue */
+ __pid_t msg_lspid; /* pid of last msgsnd() */
+ __pid_t msg_lrpid; /* pid of last msgrcv() */
+ unsigned long int __uclibc_unused4;
+ unsigned long int __uclibc_unused5;
+# if defined(__UCLIBC_USE_TIME64__)
+ __time_t msg_stime;
+ __time_t msg_rtime;
+ __time_t msg_ctime;
+# endif
+};
+
+#elif (__WORDSIZE == 32) && defined(__MIPSEB__)
+struct msqid_ds
+{
+ struct ipc_perm msg_perm; /* structure describing operation permission */
+# if defined(__UCLIBC_USE_TIME64__)
+ unsigned long msg_stime_internal_2; /* time of last msgsnd command */
+ unsigned long msg_stime_internal_1;
+ unsigned long msg_rtime_internal_2; /* time of last msgrcv command */
+ unsigned long msg_rtime_internal_1;
+ unsigned long msg_ctime_internal_2; /* time of last change */
+ unsigned long msg_ctime_internal_1;
+# else
+ unsigned long int __uclibc_unused1;
+ __time_t msg_stime;
+ unsigned long int __uclibc_unused2;
+ __time_t msg_rtime;
+ unsigned long int __uclibc_unused3;
+ __time_t msg_ctime;
+# endif
unsigned long int __msg_cbytes; /* current number of bytes on queue */
msgqnum_t msg_qnum; /* number of messages currently on queue */
msglen_t msg_qbytes; /* max number of bytes allowed on queue */
@@ -66,8 +94,32 @@ struct msqid_ds
__pid_t msg_lrpid; /* pid of last msgrcv() */
unsigned long int __uclibc_unused4;
unsigned long int __uclibc_unused5;
+# if defined(__UCLIBC_USE_TIME64__)
+ __time_t msg_stime;
+ __time_t msg_rtime;
+ __time_t msg_ctime;
+# endif
+};
+
+#else
+
+struct msqid_ds
+{
+ struct ipc_perm msg_perm; /* structure describing operation permission */
+ __time_t msg_stime; /* time of last msgsnd command */
+ __time_t msg_rtime; /* time of last msgrcv command */
+ __time_t msg_ctime; /* time of last change */
+ unsigned long int __msg_cbytes; /* current number of bytes on queue */
+ msgqnum_t msg_qnum; /* number of messages currently on queue */
+ msglen_t msg_qbytes; /* max number of bytes allowed on queue */
+ __pid_t msg_lspid; /* pid of last msgsnd() */
+ __pid_t msg_lrpid; /* pid of last msgrcv() */
+ unsigned long int __uclibc_unused4;
+ unsigned long int __uclibc_unused5;
};
+#endif
+
#ifdef __USE_MISC
# define msg_cbytes __msg_cbytes
diff --git a/libc/sysdeps/linux/mips/bits/sem.h b/libc/sysdeps/linux/mips/bits/sem.h
index 35eaa05c3..230d04868 100644
--- a/libc/sysdeps/linux/mips/bits/sem.h
+++ b/libc/sysdeps/linux/mips/bits/sem.h
@@ -38,22 +38,23 @@
struct semid_ds
{
struct ipc_perm sem_perm; /* operation permission struct */
-#if defined(__UCLIBC_USE_TIME64__)
+#if (__WORDSIZE == 32) && defined(__UCLIBC_USE_TIME64__)
unsigned long int __sem_otime_internal_1; /* last semop() time */
- unsigned long int __sem_otime_internal_2;
unsigned long int __sem_ctime_internal_1; /* last time changed by semctl() */
- unsigned long int __sem_ctime_internal_2;
#else
__time_t sem_otime; /* last semop() time */
__time_t sem_ctime; /* last time changed by semctl() */
#endif
unsigned long int sem_nsems; /* number of semaphores in set */
-#if defined(__UCLIBC_USE_TIME64__)
+#if (__WORDSIZE == 32) && defined(__UCLIBC_USE_TIME64__)
+ unsigned long int __sem_otime_internal_2;
+ unsigned long int __sem_ctime_internal_2;
__time_t sem_otime;
__time_t sem_ctime;
-#endif
+#else
unsigned long int __uclibc_unused1;
unsigned long int __uclibc_unused2;
+#endif
};
/* The user should define a union like the following to use it for arguments
diff --git a/libc/sysdeps/linux/mips/bits/shm.h b/libc/sysdeps/linux/mips/bits/shm.h
index bb87ba13d..1855a50b2 100644
--- a/libc/sysdeps/linux/mips/bits/shm.h
+++ b/libc/sysdeps/linux/mips/bits/shm.h
@@ -46,14 +46,32 @@ struct shmid_ds
{
struct ipc_perm shm_perm; /* operation permission struct */
size_t shm_segsz; /* size of segment in bytes */
- __time_t shm_atime; /* time of last shmat() */
- __time_t shm_dtime; /* time of last shmdt() */
- __time_t shm_ctime; /* time of last change by shmctl() */
+#if (__WORDSIZE == 32) && defined(__UCLIBC_USE_TIME64__)
+ unsigned long int shm_atime_internal_1; /* time of last shmat() */
+ unsigned long int shm_dtime_internal_1; /* time of last shmdt() */
+ unsigned long int shm_ctime_internal_1; /* time of last change by shmctl() */
+#else
+ __time_t shm_atime;
+ __time_t shm_dtime;
+ __time_t shm_ctime;
+#endif
__pid_t shm_cpid; /* pid of creator */
__pid_t shm_lpid; /* pid of last shmop */
shmatt_t shm_nattch; /* number of current attaches */
- unsigned long int __uclibc_unused1;
- unsigned long int __uclibc_unused2;
+#if (__WORDSIZE == 32) && defined(__UCLIBC_USE_TIME64__)
+ unsigned short int shm_atime_internal_2; /* time of last shmat() */
+ unsigned short int shm_dtime_internal_2; /* time of last shmdt() */
+ unsigned short int shm_ctime_internal_2; /* time of last change by shmctl() */
+ unsigned short int __uclibc_unused1;
+ __time_t shm_atime;
+ __time_t shm_dtime;
+ __time_t shm_ctime;
+#else
+ unsigned short int __uclibc_unused1;
+ unsigned short int __uclibc_unused2;
+ unsigned short int __uclibc_unused3;
+ unsigned short int __uclibc_unused4;
+#endif
};
#ifdef __USE_MISC
diff --git a/libc/sysdeps/linux/mips/bits/syscalls.h b/libc/sysdeps/linux/mips/bits/syscalls.h
index 13728ac55..64b42ffb1 100644
--- a/libc/sysdeps/linux/mips/bits/syscalls.h
+++ b/libc/sysdeps/linux/mips/bits/syscalls.h
@@ -184,7 +184,7 @@
({ \
long _sys_result; \
\
- FORCE_FRAME_POINTER; \
+ int* array = FORCE_FRAME_POINTER; \
{ \
register long __v0 __asm__("$2") ncs_init; \
register long __a0 __asm__("$4") = (long) arg1; \
@@ -193,15 +193,16 @@
register long __a3 __asm__("$7") = (long) arg4; \
__asm__ __volatile__ ( \
".set\tnoreorder\n\t" \
- "subu\t$29, 32\n\t" \
+ "subu\t$29, 32\n\t" \
"sw\t%6, 16($29)\n\t" \
cs_init \
"syscall\n\t" \
- "addiu\t$29, 32\n\t" \
- ".set\treorder" \
+ "addiu\t$29, 32\n\t" \
+ "addiu\t%7, %7, 0\n\t" \
+ ".set\treorder" \
: "=r" (__v0), "+r" (__a3) \
: input, "r" (__a0), "r" (__a1), "r" (__a2), \
- "r" ((long)arg5) \
+ "r" ((long)arg5), "r" (array) \
: __SYSCALL_CLOBBERS); \
err = __a3; \
_sys_result = __v0; \
@@ -213,7 +214,7 @@
({ \
long _sys_result; \
\
- FORCE_FRAME_POINTER; \
+ int* array = FORCE_FRAME_POINTER; \
{ \
register long __v0 __asm__("$2") ncs_init; \
register long __a0 __asm__("$4") = (long) arg1; \
@@ -221,17 +222,18 @@
register long __a2 __asm__("$6") = (long) arg3; \
register long __a3 __asm__("$7") = (long) arg4; \
__asm__ __volatile__ ( \
- ".set\tnoreorder\n\t" \
- "subu\t$29, 32\n\t" \
+ ".set\tnoreorder\n\t" \
+ "subu\t$29, 32\n\t" \
"sw\t%6, 16($29)\n\t" \
"sw\t%7, 20($29)\n\t" \
cs_init \
"syscall\n\t" \
- "addiu\t$29, 32\n\t" \
- ".set\treorder" \
+ "addiu\t$29, 32\n\t" \
+ "addiu\t%8, %8, 0\n\t" \
+ ".set\treorder" \
: "=r" (__v0), "+r" (__a3) \
: input, "r" (__a0), "r" (__a1), "r" (__a2), \
- "r" ((long)arg5), "r" ((long)arg6) \
+ "r" ((long)arg5), "r" ((long)arg6), "r" (array) \
: __SYSCALL_CLOBBERS); \
err = __a3; \
_sys_result = __v0; \
@@ -243,7 +245,7 @@
({ \
long _sys_result; \
\
- FORCE_FRAME_POINTER; \
+ int* array = FORCE_FRAME_POINTER; \
{ \
register long __v0 __asm__("$2") ncs_init; \
register long __a0 __asm__("$4") = (long) arg1; \
@@ -252,17 +254,19 @@
register long __a3 __asm__("$7") = (long) arg4; \
__asm__ __volatile__ ( \
".set\tnoreorder\n\t" \
- "subu\t$29, 32\n\t" \
+ "subu\t$29, 32\n\t" \
"sw\t%6, 16($29)\n\t" \
"sw\t%7, 20($29)\n\t" \
"sw\t%8, 24($29)\n\t" \
cs_init \
"syscall\n\t" \
- "addiu\t$29, 32\n\t" \
- ".set\treorder" \
+ "addiu\t$29, 32\n\t" \
+ "addiu\t%9, %9, 0\n\t" \
+ ".set\treorder" \
: "=r" (__v0), "+r" (__a3) \
: input, "r" (__a0), "r" (__a1), "r" (__a2), \
- "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7) \
+ "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7), \
+ "r" (array) \
: __SYSCALL_CLOBBERS); \
err = __a3; \
_sys_result = __v0; \
diff --git a/libc/sysdeps/linux/mips/fpu_control.h b/libc/sysdeps/linux/mips/fpu_control.h
index f855af506..6aa05e4cf 100644
--- a/libc/sysdeps/linux/mips/fpu_control.h
+++ b/libc/sysdeps/linux/mips/fpu_control.h
@@ -1,7 +1,5 @@
/* FPU control word bits. Mips version.
- Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Olaf Flebbe and Ralf Baechle.
+ 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
@@ -14,8 +12,8 @@
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/>. */
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
#ifndef _FPU_CONTROL_H
#define _FPU_CONTROL_H
@@ -28,7 +26,10 @@
* causing unimplemented operation exception. This bit is only
* available for MIPS III and newer.
* 23 -> Condition bit
- * 22-18 -> reserved (read as 0, write with 0)
+ * 22-21 -> reserved for architecture implementers
+ * 20 -> reserved (read as 0, write with 0)
+ * 19 -> IEEE 754-2008 non-arithmetic ABS.fmt and NEG.fmt enable
+ * 18 -> IEEE 754-2008 recommended NaN encoding enable
* 17 -> cause bit for unimplemented operation
* 16 -> cause bit for invalid exception
* 15 -> cause bit for division by zero exception
@@ -57,43 +58,74 @@
#include <features.h>
-/* masking of interrupts */
+#ifdef __mips_soft_float
+
+#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)
+extern fpu_control_t __fpu_control;
+
+#else /* __mips_soft_float */
+
+/* Masks for interrupts. */
#define _FPU_MASK_V 0x0800 /* Invalid operation */
#define _FPU_MASK_Z 0x0400 /* Division by zero */
#define _FPU_MASK_O 0x0200 /* Overflow */
#define _FPU_MASK_U 0x0100 /* Underflow */
#define _FPU_MASK_I 0x0080 /* Inexact operation */
-/* flush denormalized numbers to zero */
+/* Flush denormalized numbers to zero. */
#define _FPU_FLUSH_TZ 0x1000000
-/* rounding control */
+/* IEEE 754-2008 compliance control. */
+#define _FPU_ABS2008 0x80000
+#define _FPU_NAN2008 0x40000
+
+/* Rounding control. */
#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */
#define _FPU_RC_ZERO 0x1
#define _FPU_RC_UP 0x2
#define _FPU_RC_DOWN 0x3
+/* Mask for rounding control. */
+#define _FPU_RC_MASK 0x3
-#define _FPU_RESERVED 0xfe3c0000 /* Reserved bits in cw */
+#define _FPU_RESERVED 0xfe8c0000 /* Reserved bits in cw, incl ABS/NAN2008. */
/* The fdlibm code requires strict IEEE double precision arithmetic,
and no interrupts for exceptions, rounding to nearest. */
+#ifdef __mips_nan2008
+# define _FPU_DEFAULT 0x000C0000
+#else
+# define _FPU_DEFAULT 0x00000000
+#endif
-#define _FPU_DEFAULT 0x00000000
-
-/* IEEE: same as above, but exceptions */
-#define _FPU_IEEE 0x00000F80
+/* IEEE: same as above, but exceptions. */
+#ifdef __mips_nan2008
+# define _FPU_IEEE 0x000C0F80
+#else
+# define _FPU_IEEE 0x00000F80
+#endif
/* Type of the control word. */
typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
/* Macros for accessing the hardware control word. */
-#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw))
-#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw))
+extern fpu_control_t __mips_fpu_getcw (void) __THROW;
+extern void __mips_fpu_setcw (fpu_control_t) __THROW;
+#ifdef __mips16
+# define _FPU_GETCW(cw) do { (cw) = __mips_fpu_getcw (); } while (0)
+# define _FPU_SETCW(cw) __mips_fpu_setcw (cw)
+#else
+# define _FPU_GETCW(cw) __asm__ volatile ("cfc1 %0,$31" : "=r" (cw))
+# define _FPU_SETCW(cw) __asm__ volatile ("ctc1 %0,$31" : : "r" (cw))
+#endif
-#if 0
/* Default control word set at startup. */
extern fpu_control_t __fpu_control;
-#endif
+
+#endif /* __mips_soft_float */
#endif /* fpu_control.h */
diff --git a/libc/sysdeps/linux/or1k/bits/fenv.h b/libc/sysdeps/linux/or1k/bits/fenv.h
new file mode 100644
index 000000000..4701946ff
--- /dev/null
+++ b/libc/sysdeps/linux/or1k/bits/fenv.h
@@ -0,0 +1,84 @@
+/* Floating point environment, OpenRISC version.
+ Copyright (C) 2022-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
+
+#ifdef __or1k_hard_float__
+/* Define bits representing exceptions in the FPCSR status word. */
+enum
+ {
+ FE_OVERFLOW =
+#define FE_OVERFLOW (1 << 3)
+ FE_OVERFLOW,
+ FE_UNDERFLOW =
+#define FE_UNDERFLOW (1 << 4)
+ FE_UNDERFLOW,
+ FE_INEXACT =
+#define FE_INEXACT (1 << 8)
+ FE_INEXACT,
+ FE_INVALID =
+#define FE_INVALID (1 << 9)
+ FE_INVALID,
+ FE_DIVBYZERO =
+#define FE_DIVBYZERO (1 << 11)
+ FE_DIVBYZERO,
+ };
+
+/* 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 Rmode field. */
+#define FE_TONEAREST (0x0 << 1)
+#define FE_TOWARDZERO (0x1 << 1)
+#define FE_UPWARD (0x2 << 1)
+#define FE_DOWNWARD (0x3 << 1)
+
+#else
+
+/* In the soft-float case only rounding to nearest is supported, with
+ no exceptions. */
+
+enum
+ {
+ __FE_UNDEFINED = -1,
+
+ FE_TONEAREST =
+# define FE_TONEAREST 0x0
+ FE_TONEAREST
+ };
+
+# define FE_ALL_EXCEPT 0
+
+#endif /* __or1k_hard_float__ */
+
+/* Type representing exception flags. */
+typedef unsigned int fexcept_t;
+
+/* Type representing floating-point environment. */
+typedef unsigned int fenv_t;
+
+/* If the default argument is used we use this value. */
+#define FE_DFL_ENV ((const fenv_t *) -1l)
+
+/* 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/or1k/fpu_control.h b/libc/sysdeps/linux/or1k/fpu_control.h
new file mode 100644
index 000000000..9abde4f42
--- /dev/null
+++ b/libc/sysdeps/linux/or1k/fpu_control.h
@@ -0,0 +1,88 @@
+/* FPU control word bits. OpenRISC version.
+ Copyright (C) 2024-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
+
+#ifndef __or1k_hard_float__
+
+# define _FPU_RESERVED 0xffffffff
+# define _FPU_DEFAULT 0x00000000
+# define _FPU_GETCW(cw) (cw) = 0
+# define _FPU_SETCW(cw) (void) (cw)
+
+#else /* __or1k_hard_float__ */
+
+/* Layout of FPCSR:
+
+ The bits of the FPCSR are defined as follows, this should help
+ explain how the masks below have come to be.
+
+ +-----------+----------------------------+-----+----+
+ | 32 - 12 | 11 10 9 8 7 6 5 4 3 | 2-1 | 0 |
+ +-----------+----------------------------+-----+----+
+ | Reserved | DZ IN IV IX Z QN SN UN OV | RM | EE |
+ +-----------+----------------------------+-----+----+
+
+ Exception flags:
+
+ DZ - divide by zero flag.
+ IN - infinite flag.
+ IV - invalid flag.
+ IX - inexact flag.
+ Z - zero flag.
+ QN - qnan flag.
+ SN - snan flag.
+ UN - underflow flag.
+ OV - overflow flag.
+
+ Rounding modes:
+
+ The FPCSR bits 2-1 labeled above as RM specify the rounding mode.
+
+ 00 - round to nearest
+ 01 - round to zero
+ 10 - round to positive infinity
+ 11 - round to negative infinity
+
+ Enabling exceptions:
+
+ EE - set to enable FPU exceptions.
+
+ */
+
+# define _FPU_RESERVED 0xfffff000
+/* Default: rounding to nearest with exceptions disabled. */
+# define _FPU_DEFAULT 0
+/* IEEE: Same as above with exceptions enabled. */
+# define _FPU_IEEE (_FPU_DEFAULT | 1)
+
+# define _FPU_FPCSR_RM_MASK (0x3 << 1)
+
+/* Macros for accessing the hardware control word. */
+# define _FPU_GETCW(cw) __asm__ volatile ("l.mfspr %0,r0,20" : "=r" (cw))
+# define _FPU_SETCW(cw) __asm__ volatile ("l.mtspr r0,%0,20" : : "r" (cw))
+
+#endif /* __or1k_hard_float__ */
+
+/* Type of the control word. */
+typedef unsigned int fpu_control_t;
+
+/* Default control word set at startup. */
+extern fpu_control_t __fpu_control;
+
+#endif /* fpu_control.h */
diff --git a/libc/sysdeps/linux/riscv32/bits/fenv.h b/libc/sysdeps/linux/riscv32/bits/fenv.h
index a3f8031af..a6b828a76 100644
--- a/libc/sysdeps/linux/riscv32/bits/fenv.h
+++ b/libc/sysdeps/linux/riscv32/bits/fenv.h
@@ -64,10 +64,8 @@ typedef unsigned int fenv_t;
/* If the default argument is used we use this value. */
#define FE_DFL_ENV ((__const fenv_t *) -1)
-#if __GLIBC_USE (IEC_60559_BFP_EXT)
/* Type representing floating-point control modes. */
typedef unsigned int femode_t;
/* Default floating-point control modes. */
# define FE_DFL_MODE ((const femode_t *) -1L)
-#endif
diff --git a/libc/sysdeps/linux/riscv32/bits/shm.h b/libc/sysdeps/linux/riscv32/bits/shm.h
index 8a11c7050..9190c562b 100644
--- a/libc/sysdeps/linux/riscv32/bits/shm.h
+++ b/libc/sysdeps/linux/riscv32/bits/shm.h
@@ -37,12 +37,18 @@ struct shmid_ds
{
struct ipc_perm shm_perm; /* operation permission struct */
size_t shm_segsz; /* size of segment in bytes */
+#if defined(__UCLIBC_USE_TIME64__)
+ __time_t shm_atime;
+ __time_t shm_dtime;
+ __time_t shm_ctime;
+#else
__time_t shm_atime; /* time of last shmat() */
unsigned long int __uclibc_unused1;
__time_t shm_dtime; /* time of last shmdt() */
unsigned long int __uclibc_unused2;
__time_t shm_ctime; /* time of last change by shmctl() */
unsigned long int __uclibc_unused3;
+#endif
__pid_t shm_cpid; /* pid of creator */
__pid_t shm_lpid; /* pid of last shmop */
shmatt_t shm_nattch; /* number of current attaches */
diff --git a/libc/sysdeps/linux/riscv64/bits/fenv.h b/libc/sysdeps/linux/riscv64/bits/fenv.h
index a3f8031af..a6b828a76 100644
--- a/libc/sysdeps/linux/riscv64/bits/fenv.h
+++ b/libc/sysdeps/linux/riscv64/bits/fenv.h
@@ -64,10 +64,8 @@ typedef unsigned int fenv_t;
/* If the default argument is used we use this value. */
#define FE_DFL_ENV ((__const fenv_t *) -1)
-#if __GLIBC_USE (IEC_60559_BFP_EXT)
/* Type representing floating-point control modes. */
typedef unsigned int femode_t;
/* Default floating-point control modes. */
# define FE_DFL_MODE ((const femode_t *) -1L)
-#endif
diff --git a/libc/sysdeps/linux/riscv64/bits/shm.h b/libc/sysdeps/linux/riscv64/bits/shm.h
index 8a11c7050..bfb603499 100644
--- a/libc/sysdeps/linux/riscv64/bits/shm.h
+++ b/libc/sysdeps/linux/riscv64/bits/shm.h
@@ -38,16 +38,13 @@ struct shmid_ds
struct ipc_perm shm_perm; /* operation permission struct */
size_t shm_segsz; /* size of segment in bytes */
__time_t shm_atime; /* time of last shmat() */
- unsigned long int __uclibc_unused1;
__time_t shm_dtime; /* time of last shmdt() */
- unsigned long int __uclibc_unused2;
__time_t shm_ctime; /* time of last change by shmctl() */
- unsigned long int __uclibc_unused3;
__pid_t shm_cpid; /* pid of creator */
__pid_t shm_lpid; /* pid of last shmop */
shmatt_t shm_nattch; /* number of current attaches */
- unsigned long int __uclibc_unused4;
- unsigned long int __uclibc_unused5;
+ unsigned long int __uclibc_unused1;
+ unsigned long int __uclibc_unused2;
};
#ifdef __USE_MISC
diff --git a/libc/sysdeps/linux/sh/bits/fenv.h b/libc/sysdeps/linux/sh/bits/fenv.h
index 38c303ff2..349e7ddde 100644
--- a/libc/sysdeps/linux/sh/bits/fenv.h
+++ b/libc/sysdeps/linux/sh/bits/fenv.h
@@ -1,5 +1,4 @@
-/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
+/* Copyright (C) 1999-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
@@ -13,7 +12,7 @@
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/>. */
+ <https://www.gnu.org/licenses/>. */
#ifndef _FENV_H
# error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
@@ -24,34 +23,39 @@
of the appropriate bits in the FPU control word. */
enum
{
- FE_INEXACT = 0x04,
-#define FE_INEXACT FE_INEXACT
- FE_UNDERFLOW = 0x08,
-#define FE_UNDERFLOW FE_UNDERFLOW
- FE_OVERFLOW = 0x10,
-#define FE_OVERFLOW FE_OVERFLOW
- FE_DIVBYZERO = 0x20,
-#define FE_DIVBYZERO FE_DIVBYZERO
- FE_INVALID = 0x40,
-#define FE_INVALID FE_INVALID
+ FE_INEXACT =
+#define FE_INEXACT 0x04
+ FE_INEXACT,
+ FE_UNDERFLOW =
+#define FE_UNDERFLOW 0x08
+ FE_UNDERFLOW,
+ FE_OVERFLOW =
+#define FE_OVERFLOW 0x10
+ FE_OVERFLOW,
+ FE_DIVBYZERO =
+#define FE_DIVBYZERO 0x20
+ FE_DIVBYZERO,
+ FE_INVALID =
+#define FE_INVALID 0x40
+ FE_INVALID,
};
#define FE_ALL_EXCEPT \
(FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
-/* The SH FPU supports all of the four defined rounding modes. We
- use again the bit positions in the FPU control word as the values
- for the appropriate macros. */
+/* The SH FPU supports two of the four defined rounding modes: round to nearest
+ and round to zero. We use again the bit positions in the FPU control word
+ as the values for the appropriate macros. */
enum
{
- FE_TONEAREST = 0x0,
-#define FE_TONEAREST FE_TONEAREST
- FE_TOWARDZERO = 0x1,
-#define FE_TOWARDZERO FE_TOWARDZERO
- FE_UPWARD = 0x2,
-#define FE_UPWARD FE_UPWARD
- FE_DOWNWARD = 0x3
-#define FE_DOWNWARD FE_DOWNWARD
+ __FE_UNDEFINED = -1,
+
+ FE_TONEAREST =
+#define FE_TONEAREST 0x0
+ FE_TONEAREST,
+ FE_TOWARDZERO =
+#define FE_TOWARDZERO 0x1
+ FE_TOWARDZERO,
};
@@ -68,4 +72,10 @@ typedef struct
fenv_t;
/* If the default argument is used we use this value. */
-#define FE_DFL_ENV ((fenv_t *) -1)
+#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/sh/fpu_control.h b/libc/sysdeps/linux/sh/fpu_control.h
index 8143041fe..d5f401f91 100644
--- a/libc/sysdeps/linux/sh/fpu_control.h
+++ b/libc/sysdeps/linux/sh/fpu_control.h
@@ -1,6 +1,5 @@
/* FPU control word definitions. SH version.
- Copyright (C) 1999, 2000, 2009 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
+ Copyright (C) 1999-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
@@ -14,14 +13,23 @@
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/>. */
+ <https://www.gnu.org/licenses/>. */
#ifndef _FPU_CONTROL_H
#define _FPU_CONTROL_H
-#ifndef __SH4__
-#error This file is only correct for sh4
-#endif
+#if !defined(__SH_FPU_ANY__)
+
+#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)
+extern fpu_control_t __fpu_control;
+
+#else
+
+#include <features.h>
/* masking of interrupts */
#define _FPU_MASK_VM 0x0800 /* Invalid operation */
@@ -48,16 +56,20 @@ typedef unsigned int fpu_control_t;
#define _FPU_GETCW(cw) __asm__ ("sts fpscr,%0" : "=r" (cw))
#if defined __GNUC__
-/* GCC provides this function */
+__BEGIN_DECLS
+
+/* GCC provides this function. */
extern void __set_fpscr (unsigned long);
#define _FPU_SETCW(cw) __set_fpscr ((cw))
#else
#define _FPU_SETCW(cw) __asm__ ("lds %0,fpscr" : : "r" (cw))
#endif
-#if 0
/* Default control word set at startup. */
extern fpu_control_t __fpu_control;
-#endif
+
+__END_DECLS
+
+#endif /* __SH_FPU_ANY__ */
#endif /* _FPU_CONTROL_H */
diff --git a/libc/sysdeps/linux/sparc/bits/fenv.h b/libc/sysdeps/linux/sparc/bits/fenv.h
index 79ab8cefa..83b32cc51 100644
--- a/libc/sysdeps/linux/sparc/bits/fenv.h
+++ b/libc/sysdeps/linux/sparc/bits/fenv.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1997-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
@@ -12,26 +12,34 @@
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/>. */
+ <https://www.gnu.org/licenses/>. */
#ifndef _FENV_H
# error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
#endif
+#include <bits/wordsize.h>
+
+
/* Define bits representing the exception. We use the bit positions
of the appropriate accrued exception bits from the FSR. */
enum
{
- FE_INVALID = (1 << 9),
-#define FE_INVALID FE_INVALID
- FE_OVERFLOW = (1 << 8),
-#define FE_OVERFLOW FE_OVERFLOW
- FE_UNDERFLOW = (1 << 7),
-#define FE_UNDERFLOW FE_UNDERFLOW
- FE_DIVBYZERO = (1 << 6),
-#define FE_DIVBYZERO FE_DIVBYZERO
- FE_INEXACT = (1 << 5)
-#define FE_INEXACT FE_INEXACT
+ FE_INVALID =
+#define FE_INVALID (1 << 9)
+ FE_INVALID,
+ FE_OVERFLOW =
+#define FE_OVERFLOW (1 << 8)
+ FE_OVERFLOW,
+ FE_UNDERFLOW =
+#define FE_UNDERFLOW (1 << 7)
+ FE_UNDERFLOW,
+ FE_DIVBYZERO =
+#define FE_DIVBYZERO (1 << 6)
+ FE_DIVBYZERO,
+ FE_INEXACT =
+#define FE_INEXACT (1 << 5)
+ FE_INEXACT
};
#define FE_ALL_EXCEPT \
@@ -42,14 +50,18 @@ enum
for the appropriate macros. */
enum
{
- FE_TONEAREST = (0U << 30),
-#define FE_TONEAREST FE_TONEAREST
- FE_TOWARDZERO = (1U << 30),
-#define FE_TOWARDZERO FE_TOWARDZERO
- FE_UPWARD = (2U << 30),
-#define FE_UPWARD FE_UPWARD
- FE_DOWNWARD = (3U << 30)
-#define FE_DOWNWARD FE_DOWNWARD
+ FE_TONEAREST =
+#define FE_TONEAREST (0 << 30)
+ FE_TONEAREST,
+ FE_TOWARDZERO =
+#define FE_TOWARDZERO (1 << 30)
+ FE_TOWARDZERO,
+ FE_UPWARD =
+#define FE_UPWARD (-0x7fffffff - 1) /* (2 << 30) */
+ FE_UPWARD,
+ FE_DOWNWARD =
+#define FE_DOWNWARD (-0x40000000) /* (3 << 30) */
+ FE_DOWNWARD
};
#define __FE_ROUND_MASK (3U << 30)
@@ -70,6 +82,8 @@ typedef unsigned long int fenv_t;
# define FE_NOMASK_ENV ((const fenv_t *) -2)
#endif
-/* For internal use only: access the fp state register. */
-#define __fenv_stfsr(X) __asm__ ("st %%fsr,%0" : "=m" (X))
-#define __fenv_ldfsr(X) __asm__ __volatile__ ("ld %0,%%fsr" : : "m" (X))
+/* Type representing floating-point control modes. */
+typedef unsigned long int femode_t;
+
+/* Default floating-point control modes. */
+# define FE_DFL_MODE ((const femode_t *) -1L)
diff --git a/libc/sysdeps/linux/sparc/fpu_control.h b/libc/sysdeps/linux/sparc/fpu_control.h
index 57f1dbb67..542f9fb1b 100644
--- a/libc/sysdeps/linux/sparc/fpu_control.h
+++ b/libc/sysdeps/linux/sparc/fpu_control.h
@@ -1,6 +1,5 @@
/* FPU control word bits. SPARC version.
- Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
- Contributed by Miguel de Icaza
+ Copyright (C) 1997-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
@@ -14,13 +13,14 @@
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/>. */
+ <https://www.gnu.org/licenses/>. */
#ifndef _FPU_CONTROL_H
#define _FPU_CONTROL_H 1
#include <features.h>
+#include <bits/wordsize.h>
/* masking of interrupts */
#define _FPU_MASK_IM 0x08000000
@@ -41,7 +41,7 @@
#define _FPU_RC_ZERO 0x40000000
#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */
-#define _FPU_RESERVED 0x30300000 /* Reserved bits in cw */
+#define _FPU_RESERVED 0x303e0000 /* Reserved bits in cw */
/* Now two recommended cw */
@@ -56,12 +56,20 @@
/* Type of the control word. */
typedef unsigned long int fpu_control_t;
-#define _FPU_GETCW(cw) __asm__ ("st %%fsr,%0" : "=m" (*&cw))
-#define _FPU_SETCW(cw) __asm__ ("ld %0,%%fsr" : : "m" (*&cw))
+#if __WORDSIZE == 64
+# define _FPU_GETCW(cw) __asm__ __volatile__ ("stx %%fsr,%0" : "=m" (*&cw))
+# define _FPU_SETCW(cw) __asm__ __volatile__ ("ldx %0,%%fsr" : : "m" (*&cw))
+#else
+# ifdef __leon__
+ /* Prevent stfsr from being placed directly after other fp instruction. */
+# define _FPU_GETCW(cw) __asm__ __volatile__ ("nop; st %%fsr,%0" : "=m" (*&cw))
+# else
+# define _FPU_GETCW(cw) __asm__ __volatile__ ("st %%fsr,%0" : "=m" (*&cw))
+# endif
+# define _FPU_SETCW(cw) __asm__ __volatile__ ("ld %0,%%fsr" : : "m" (*&cw))
+#endif
-#if 0
/* Default control word set at startup. */
extern fpu_control_t __fpu_control;
-#endif
#endif /* fpu_control.h */
diff --git a/libc/sysdeps/linux/x86_64/crt1.S b/libc/sysdeps/linux/x86_64/crt1.S
index 701cbf2f6..151aeffeb 100644
--- a/libc/sysdeps/linux/x86_64/crt1.S
+++ b/libc/sysdeps/linux/x86_64/crt1.S
@@ -83,11 +83,7 @@ _start:
#ifdef L_rcrt1
pushq %rdi /* save rdi (but should be 0...) */
pushq %rdx /* store rdx (rtld_fini) */
- xorq %rcx, %rcx /* ensure rcx is 0 */
- addq _start@GOTPCREL(%rip), %rcx /* get offset of _start from beginning of file */
- movq _start@GOTPCREL(%rip), %rax /* get run time address of _start */
- subq %rcx, %rax /* calculate run time load offset */
- movq %rax, %rdi /* load offset -> param 1 */
+ lea __ehdr_start(%rip), %rdi /* "Calculate" load address... */
call reloc_static_pie /* relocate dynamic addrs */
xorq %rax, %rax /* cleanup */
popq %rdx
diff --git a/libm/aarch64/Makefile.arch b/libm/aarch64/Makefile.arch
new file mode 100644
index 000000000..bd38690be
--- /dev/null
+++ b/libm/aarch64/Makefile.arch
@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)
diff --git a/libm/aarch64/fclrexcpt.c b/libm/aarch64/fclrexcpt.c
new file mode 100644
index 000000000..3dbd9a8bb
--- /dev/null
+++ b/libm/aarch64/fclrexcpt.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feclearexcept (int excepts)
+{
+ fpu_fpsr_t fpsr;
+ fpu_fpsr_t fpsr_new;
+
+ excepts &= FE_ALL_EXCEPT;
+
+ _FPU_GETFPSR (fpsr);
+ fpsr_new = fpsr & ~excepts;
+
+ if (fpsr != fpsr_new)
+ _FPU_SETFPSR (fpsr_new);
+
+ return 0;
+}
diff --git a/libm/aarch64/fedisblxcpt.c b/libm/aarch64/fedisblxcpt.c
new file mode 100644
index 000000000..a36873690
--- /dev/null
+++ b/libm/aarch64/fedisblxcpt.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2001-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fedisableexcept (int excepts)
+{
+ fpu_control_t fpcr;
+ fpu_control_t fpcr_new;
+
+ _FPU_GETCW (fpcr);
+ excepts &= FE_ALL_EXCEPT;
+ fpcr_new = fpcr & ~(excepts << FE_EXCEPT_SHIFT);
+
+ if (fpcr != fpcr_new)
+ _FPU_SETCW (fpcr_new);
+
+ return (fpcr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
+}
diff --git a/libm/aarch64/feenablxcpt.c b/libm/aarch64/feenablxcpt.c
new file mode 100644
index 000000000..b5aa3bdc6
--- /dev/null
+++ b/libm/aarch64/feenablxcpt.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2001-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feenableexcept (int excepts)
+{
+ fpu_control_t fpcr;
+ fpu_control_t fpcr_new;
+ fpu_control_t updated_fpcr;
+
+ _FPU_GETCW (fpcr);
+ excepts &= FE_ALL_EXCEPT;
+ fpcr_new = fpcr | (excepts << FE_EXCEPT_SHIFT);
+
+ if (fpcr != fpcr_new)
+ {
+ _FPU_SETCW (fpcr_new);
+
+ /* Trapping exceptions are optional in AArch64; the relevant enable
+ bits in FPCR are RES0 hence the absence of support can be detected
+ by reading back the FPCR and comparing with the required value. */
+ _FPU_GETCW (updated_fpcr);
+
+ if (fpcr_new & ~updated_fpcr)
+ return -1;
+ }
+
+ return (fpcr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
+}
diff --git a/libm/aarch64/fegetenv.c b/libm/aarch64/fegetenv.c
new file mode 100644
index 000000000..a85575eb8
--- /dev/null
+++ b/libm/aarch64/fegetenv.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetenv (fenv_t *envp)
+{
+ fpu_control_t fpcr;
+ fpu_fpsr_t fpsr;
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+ envp->__fpcr = fpcr;
+ envp->__fpsr = fpsr;
+ return 0;
+}
diff --git a/libm/aarch64/fegetexcept.c b/libm/aarch64/fegetexcept.c
new file mode 100644
index 000000000..a9eac299c
--- /dev/null
+++ b/libm/aarch64/fegetexcept.c
@@ -0,0 +1,26 @@
+/* Copyright (C) 2001-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetexcept (void)
+{
+ fpu_control_t fpcr;
+ _FPU_GETCW (fpcr);
+ return (fpcr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
+}
diff --git a/libm/aarch64/fegetmode.c b/libm/aarch64/fegetmode.c
new file mode 100644
index 000000000..8393e6d05
--- /dev/null
+++ b/libm/aarch64/fegetmode.c
@@ -0,0 +1,26 @@
+/* Store current floating-point control modes. AArch64 version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetmode (femode_t *modep)
+{
+ _FPU_GETCW (*modep);
+ return 0;
+}
diff --git a/libm/aarch64/fegetround.c b/libm/aarch64/fegetround.c
new file mode 100644
index 000000000..1f34c6918
--- /dev/null
+++ b/libm/aarch64/fegetround.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+/* Return the floating-point rounding mode. */
+
+static inline int
+get_rounding_mode (void)
+{
+ fpu_control_t fpcr;
+
+ _FPU_GETCW (fpcr);
+ return fpcr & _FPU_FPCR_RM_MASK;
+}
+
+int
+fegetround (void)
+{
+ return get_rounding_mode ();
+}
diff --git a/libm/aarch64/feholdexcpt.c b/libm/aarch64/feholdexcpt.c
new file mode 100644
index 000000000..09c8cd38b
--- /dev/null
+++ b/libm/aarch64/feholdexcpt.c
@@ -0,0 +1,25 @@
+/* Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feholdexcept (fenv_t *envp)
+{
+ libc_feholdexcept_aarch64 (envp);
+ return 0;
+}
diff --git a/libm/aarch64/fenv_private.h b/libm/aarch64/fenv_private.h
new file mode 100644
index 000000000..5afb790ea
--- /dev/null
+++ b/libm/aarch64/fenv_private.h
@@ -0,0 +1,300 @@
+/* Private floating point rounding and exceptions handling. AArch64 version.
+ Copyright (C) 2014-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_FENV_PRIVATE_H
+#define AARCH64_FENV_PRIVATE_H 1
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+static __always_inline void
+libc_feholdexcept_aarch64 (fenv_t *envp)
+{
+ fpu_control_t fpcr;
+ fpu_control_t new_fpcr;
+ fpu_fpsr_t fpsr;
+ fpu_fpsr_t new_fpsr;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+ envp->__fpcr = fpcr;
+ envp->__fpsr = fpsr;
+
+ /* Clear exception flags and set all exceptions to non-stop. */
+ new_fpcr = fpcr & ~(FE_ALL_EXCEPT << FE_EXCEPT_SHIFT);
+ new_fpsr = fpsr & ~FE_ALL_EXCEPT;
+
+ if (unlikely (new_fpcr != fpcr))
+ _FPU_SETCW (new_fpcr);
+
+ if (new_fpsr != fpsr)
+ _FPU_SETFPSR (new_fpsr);
+}
+
+#define libc_feholdexcept libc_feholdexcept_aarch64
+#define libc_feholdexceptf libc_feholdexcept_aarch64
+#define libc_feholdexceptl libc_feholdexcept_aarch64
+
+static __always_inline void
+libc_fesetround_aarch64 (int round)
+{
+ fpu_control_t fpcr;
+
+ _FPU_GETCW (fpcr);
+
+ /* Check whether rounding modes are different. */
+ round = (fpcr ^ round) & _FPU_FPCR_RM_MASK;
+
+ /* Set new rounding mode if different. */
+ if (unlikely (round != 0))
+ _FPU_SETCW (fpcr ^ round);
+}
+
+#define libc_fesetround libc_fesetround_aarch64
+#define libc_fesetroundf libc_fesetround_aarch64
+#define libc_fesetroundl libc_fesetround_aarch64
+
+static __always_inline void
+libc_feholdexcept_setround_aarch64 (fenv_t *envp, int round)
+{
+ fpu_control_t fpcr;
+ fpu_control_t new_fpcr;
+ fpu_fpsr_t fpsr;
+ fpu_fpsr_t new_fpsr;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+ envp->__fpcr = fpcr;
+ envp->__fpsr = fpsr;
+
+ /* Clear exception flags, set all exceptions to non-stop,
+ and set new rounding mode. */
+ new_fpcr = fpcr & ~((FE_ALL_EXCEPT << FE_EXCEPT_SHIFT) | _FPU_FPCR_RM_MASK);
+ new_fpcr |= round;
+ new_fpsr = fpsr & ~FE_ALL_EXCEPT;
+
+ if (unlikely (new_fpcr != fpcr))
+ _FPU_SETCW (new_fpcr);
+
+ if (new_fpsr != fpsr)
+ _FPU_SETFPSR (new_fpsr);
+}
+
+#define libc_feholdexcept_setround libc_feholdexcept_setround_aarch64
+#define libc_feholdexcept_setroundf libc_feholdexcept_setround_aarch64
+#define libc_feholdexcept_setroundl libc_feholdexcept_setround_aarch64
+
+static __always_inline int
+libc_fetestexcept_aarch64 (int ex)
+{
+ fpu_fpsr_t fpsr;
+
+ _FPU_GETFPSR (fpsr);
+ return fpsr & ex & FE_ALL_EXCEPT;
+}
+
+#define libc_fetestexcept libc_fetestexcept_aarch64
+#define libc_fetestexceptf libc_fetestexcept_aarch64
+#define libc_fetestexceptl libc_fetestexcept_aarch64
+
+static __always_inline void
+libc_fesetenv_aarch64 (const fenv_t *envp)
+{
+ fpu_control_t fpcr;
+ fpu_control_t new_fpcr;
+
+ _FPU_GETCW (fpcr);
+ new_fpcr = envp->__fpcr;
+
+ if (unlikely (fpcr != new_fpcr))
+ _FPU_SETCW (new_fpcr);
+
+ _FPU_SETFPSR (envp->__fpsr);
+}
+
+#define libc_fesetenv libc_fesetenv_aarch64
+#define libc_fesetenvf libc_fesetenv_aarch64
+#define libc_fesetenvl libc_fesetenv_aarch64
+#define libc_feresetround_noex libc_fesetenv_aarch64
+#define libc_feresetround_noexf libc_fesetenv_aarch64
+#define libc_feresetround_noexl libc_fesetenv_aarch64
+
+static __always_inline int
+libc_feupdateenv_test_aarch64 (const fenv_t *envp, int ex)
+{
+ fpu_control_t fpcr;
+ fpu_control_t new_fpcr;
+ fpu_fpsr_t fpsr;
+ fpu_fpsr_t new_fpsr;
+ int excepts;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+
+ /* Merge current exception flags with the saved fenv. */
+ excepts = fpsr & FE_ALL_EXCEPT;
+ new_fpcr = envp->__fpcr;
+ new_fpsr = envp->__fpsr | excepts;
+
+ if (unlikely (fpcr != new_fpcr))
+ _FPU_SETCW (new_fpcr);
+
+ if (fpsr != new_fpsr)
+ _FPU_SETFPSR (new_fpsr);
+
+ /* Raise the exceptions if enabled in the new FP state. */
+ if (unlikely (excepts & (new_fpcr >> FE_EXCEPT_SHIFT)))
+ feraiseexcept (excepts);
+
+ return excepts & ex;
+}
+
+#define libc_feupdateenv_test libc_feupdateenv_test_aarch64
+#define libc_feupdateenv_testf libc_feupdateenv_test_aarch64
+#define libc_feupdateenv_testl libc_feupdateenv_test_aarch64
+
+static __always_inline void
+libc_feupdateenv_aarch64 (const fenv_t *envp)
+{
+ libc_feupdateenv_test_aarch64 (envp, 0);
+}
+
+#define libc_feupdateenv libc_feupdateenv_aarch64
+#define libc_feupdateenvf libc_feupdateenv_aarch64
+#define libc_feupdateenvl libc_feupdateenv_aarch64
+
+static __always_inline void
+libc_feholdsetround_aarch64 (fenv_t *envp, int round)
+{
+ fpu_control_t fpcr;
+ fpu_fpsr_t fpsr;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+ envp->__fpcr = fpcr;
+ envp->__fpsr = fpsr;
+
+ /* Check whether rounding modes are different. */
+ round = (fpcr ^ round) & _FPU_FPCR_RM_MASK;
+
+ /* Set new rounding mode if different. */
+ if (unlikely (round != 0))
+ _FPU_SETCW (fpcr ^ round);
+}
+
+#define libc_feholdsetround libc_feholdsetround_aarch64
+#define libc_feholdsetroundf libc_feholdsetround_aarch64
+#define libc_feholdsetroundl libc_feholdsetround_aarch64
+
+static __always_inline void
+libc_feresetround_aarch64 (fenv_t *envp)
+{
+ fpu_control_t fpcr;
+ int round;
+
+ _FPU_GETCW (fpcr);
+
+ /* Check whether rounding modes are different. */
+ round = (envp->__fpcr ^ fpcr) & _FPU_FPCR_RM_MASK;
+
+ /* Restore the rounding mode if it was changed. */
+ if (unlikely (round != 0))
+ _FPU_SETCW (fpcr ^ round);
+}
+
+#define libc_feresetround libc_feresetround_aarch64
+#define libc_feresetroundf libc_feresetround_aarch64
+#define libc_feresetroundl libc_feresetround_aarch64
+
+/* We have support for rounding mode context. */
+#define HAVE_RM_CTX 1
+
+static __always_inline void
+libc_feholdsetround_aarch64_ctx (struct rm_ctx *ctx, int r)
+{
+ fpu_control_t fpcr;
+ int round;
+
+ _FPU_GETCW (fpcr);
+ ctx->env.__fpcr = fpcr;
+
+ /* Check whether rounding modes are different. */
+ round = (fpcr ^ r) & _FPU_FPCR_RM_MASK;
+ ctx->updated_status = round != 0;
+
+ /* Set the rounding mode if changed. */
+ if (unlikely (round != 0))
+ _FPU_SETCW (fpcr ^ round);
+}
+
+#define libc_feholdsetround_ctx libc_feholdsetround_aarch64_ctx
+#define libc_feholdsetroundf_ctx libc_feholdsetround_aarch64_ctx
+#define libc_feholdsetroundl_ctx libc_feholdsetround_aarch64_ctx
+
+static __always_inline void
+libc_feresetround_aarch64_ctx (struct rm_ctx *ctx)
+{
+ /* Restore the rounding mode if updated. */
+ if (unlikely (ctx->updated_status))
+ _FPU_SETCW (ctx->env.__fpcr);
+}
+
+#define libc_feresetround_ctx libc_feresetround_aarch64_ctx
+#define libc_feresetroundf_ctx libc_feresetround_aarch64_ctx
+#define libc_feresetroundl_ctx libc_feresetround_aarch64_ctx
+
+static __always_inline void
+libc_feholdsetround_noex_aarch64_ctx (struct rm_ctx *ctx, int r)
+{
+ fpu_control_t fpcr;
+ fpu_fpsr_t fpsr;
+ int round;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+ ctx->env.__fpcr = fpcr;
+ ctx->env.__fpsr = fpsr;
+
+ /* Check whether rounding modes are different. */
+ round = (fpcr ^ r) & _FPU_FPCR_RM_MASK;
+ ctx->updated_status = round != 0;
+
+ /* Set the rounding mode if changed. */
+ if (unlikely (round != 0))
+ _FPU_SETCW (fpcr ^ round);
+}
+
+#define libc_feholdsetround_noex_ctx libc_feholdsetround_noex_aarch64_ctx
+#define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_aarch64_ctx
+#define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_aarch64_ctx
+
+static __always_inline void
+libc_feresetround_noex_aarch64_ctx (struct rm_ctx *ctx)
+{
+ /* Restore the rounding mode if updated. */
+ if (unlikely (ctx->updated_status))
+ _FPU_SETCW (ctx->env.__fpcr);
+
+ /* Write new FPSR to restore exception flags. */
+ _FPU_SETFPSR (ctx->env.__fpsr);
+}
+
+#define libc_feresetround_noex_ctx libc_feresetround_noex_aarch64_ctx
+#define libc_feresetround_noexf_ctx libc_feresetround_noex_aarch64_ctx
+#define libc_feresetround_noexl_ctx libc_feresetround_noex_aarch64_ctx
+
+#endif
diff --git a/libm/aarch64/fesetenv.c b/libm/aarch64/fesetenv.c
new file mode 100644
index 000000000..eb7a08da0
--- /dev/null
+++ b/libm/aarch64/fesetenv.c
@@ -0,0 +1,73 @@
+/* Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetenv (const fenv_t *envp)
+{
+ fpu_control_t fpcr;
+ fpu_control_t fpcr_new;
+ fpu_control_t updated_fpcr;
+ fpu_fpsr_t fpsr;
+ fpu_fpsr_t fpsr_new;
+
+ _FPU_GETCW (fpcr);
+
+ if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV))
+ {
+ /* The new FPCR/FPSR are valid, so don't merge the reserved flags. */
+ fpcr_new = envp->__fpcr;
+
+ if (fpcr != fpcr_new)
+ _FPU_SETCW (fpcr_new);
+
+ _FPU_SETFPSR (envp->__fpsr);
+ return 0;
+ }
+
+ _FPU_GETFPSR (fpsr);
+ fpcr_new = fpcr & _FPU_RESERVED;
+ fpsr_new = fpsr & _FPU_FPSR_RESERVED;
+
+ if (envp == FE_DFL_ENV)
+ {
+ fpcr_new |= _FPU_DEFAULT;
+ fpsr_new |= _FPU_FPSR_DEFAULT;
+ }
+ else
+ {
+ fpcr_new |= _FPU_FPCR_IEEE;
+ fpsr_new |= _FPU_FPSR_IEEE;
+ }
+
+ _FPU_SETFPSR (fpsr_new);
+
+ if (fpcr != fpcr_new)
+ {
+ _FPU_SETCW (fpcr_new);
+
+ /* Trapping exceptions are optional in AArch64; the relevant enable
+ bits in FPCR are RES0 hence the absence of support can be detected
+ by reading back the FPCR and comparing with the required value. */
+ _FPU_GETCW (updated_fpcr);
+
+ return fpcr_new & ~updated_fpcr;
+ }
+
+ return 0;
+}
diff --git a/libm/aarch64/fesetexcept.c b/libm/aarch64/fesetexcept.c
new file mode 100644
index 000000000..14a0b4232
--- /dev/null
+++ b/libm/aarch64/fesetexcept.c
@@ -0,0 +1,33 @@
+/* Set given exception flags. AArch64 version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexcept (int excepts)
+{
+ fpu_fpsr_t fpsr;
+ fpu_fpsr_t fpsr_new;
+
+ _FPU_GETFPSR (fpsr);
+ fpsr_new = fpsr | (excepts & FE_ALL_EXCEPT);
+ if (fpsr != fpsr_new)
+ _FPU_SETFPSR (fpsr_new);
+
+ return 0;
+}
diff --git a/libm/aarch64/fesetmode.c b/libm/aarch64/fesetmode.c
new file mode 100644
index 000000000..34e7c9316
--- /dev/null
+++ b/libm/aarch64/fesetmode.c
@@ -0,0 +1,33 @@
+/* Install given floating-point control modes. AArch64 version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetmode (const femode_t *modep)
+{
+ fpu_control_t fpcr, fpcr_new;
+ _FPU_GETCW (fpcr);
+ if (modep == FE_DFL_MODE)
+ fpcr_new = (fpcr & _FPU_RESERVED) | _FPU_DEFAULT;
+ else
+ fpcr_new = *modep;
+ if (fpcr != fpcr_new)
+ _FPU_SETCW (fpcr_new);
+ return 0;
+}
diff --git a/libm/aarch64/fesetround.c b/libm/aarch64/fesetround.c
new file mode 100644
index 000000000..63a558258
--- /dev/null
+++ b/libm/aarch64/fesetround.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+#include <fpu_control.h>
+
+int
+fesetround (int round)
+{
+ if (round & ~_FPU_FPCR_RM_MASK)
+ return 1;
+
+ libc_fesetround_aarch64 (round);
+ return 0;
+}
diff --git a/libm/aarch64/feupdateenv.c b/libm/aarch64/feupdateenv.c
new file mode 100644
index 000000000..2b4e62ecc
--- /dev/null
+++ b/libm/aarch64/feupdateenv.c
@@ -0,0 +1,84 @@
+/* Copyright (C) 2009-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feupdateenv (const fenv_t *envp)
+{
+ fpu_control_t fpcr;
+ fpu_control_t fpcr_new;
+ fpu_control_t updated_fpcr;
+ fpu_fpsr_t fpsr;
+ fpu_fpsr_t fpsr_new;
+ int excepts;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+ excepts = fpsr & FE_ALL_EXCEPT;
+
+ if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV))
+ {
+ fpcr_new = envp->__fpcr;
+ fpsr_new = envp->__fpsr | excepts;
+
+ if (fpcr != fpcr_new)
+ _FPU_SETCW (fpcr_new);
+
+ if (fpsr != fpsr_new)
+ _FPU_SETFPSR (fpsr_new);
+
+ if (excepts & (fpcr_new >> FE_EXCEPT_SHIFT))
+ return feraiseexcept (excepts);
+
+ return 0;
+ }
+
+ fpcr_new = fpcr & _FPU_RESERVED;
+ fpsr_new = fpsr & (_FPU_FPSR_RESERVED | FE_ALL_EXCEPT);
+
+ if (envp == FE_DFL_ENV)
+ {
+ fpcr_new |= _FPU_DEFAULT;
+ fpsr_new |= _FPU_FPSR_DEFAULT;
+ }
+ else
+ {
+ fpcr_new |= _FPU_FPCR_IEEE;
+ fpsr_new |= _FPU_FPSR_IEEE;
+ }
+
+ _FPU_SETFPSR (fpsr_new);
+
+ if (fpcr != fpcr_new)
+ {
+ _FPU_SETCW (fpcr_new);
+
+ /* Trapping exceptions are optional in AArch64; the relevant enable
+ bits in FPCR are RES0 hence the absence of support can be detected
+ by reading back the FPCR and comparing with the required value. */
+ _FPU_GETCW (updated_fpcr);
+
+ if (fpcr_new & ~updated_fpcr)
+ return 1;
+ }
+
+ if (excepts & (fpcr_new >> FE_EXCEPT_SHIFT))
+ return feraiseexcept (excepts);
+
+ return 0;
+}
diff --git a/libm/aarch64/fgetexcptflg.c b/libm/aarch64/fgetexcptflg.c
new file mode 100644
index 000000000..2c8920989
--- /dev/null
+++ b/libm/aarch64/fgetexcptflg.c
@@ -0,0 +1,25 @@
+/* Copyright (C) 2001-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ *flagp = libc_fetestexcept_aarch64 (excepts);
+ return 0;
+}
diff --git a/libm/aarch64/fraiseexcpt.c b/libm/aarch64/fraiseexcpt.c
new file mode 100644
index 000000000..6a016d046
--- /dev/null
+++ b/libm/aarch64/fraiseexcpt.c
@@ -0,0 +1,89 @@
+/* Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include <float.h>
+#include <stdint.h>
+
+int
+feraiseexcept (int excepts)
+{
+ uint64_t fpsr;
+ const float fp_zero = 0.0;
+ const float fp_one = 1.0;
+ const float fp_max = FLT_MAX;
+ const float fp_min = FLT_MIN;
+ const float fp_1e32 = 1.0e32f;
+ const float fp_two = 2.0;
+ const float fp_three = 3.0;
+
+ /* Raise exceptions represented by EXCEPTS. But we must raise only
+ one signal at a time. It is important that if the OVERFLOW or
+ UNDERFLOW exception and the inexact exception are given at the
+ same time, the OVERFLOW or UNDERFLOW exception precedes the
+ INEXACT exception.
+
+ After each exception we read from the FPSR, to force the
+ exception to be raised immediately. */
+
+ if (FE_INVALID & excepts)
+ __asm__ __volatile__ (
+ "ldr s0, %1\n\t"
+ "fdiv s0, s0, s0\n\t"
+ "mrs %0, fpsr" : "=r" (fpsr)
+ : "m" (fp_zero)
+ : "d0");
+
+ if (FE_DIVBYZERO & excepts)
+ __asm__ __volatile__ (
+ "ldr s0, %1\n\t"
+ "ldr s1, %2\n\t"
+ "fdiv s0, s0, s1\n\t"
+ "mrs %0, fpsr" : "=r" (fpsr)
+ : "m" (fp_one), "m" (fp_zero)
+ : "d0", "d1");
+
+ if (FE_OVERFLOW & excepts)
+ /* There's no way to raise overflow without also raising inexact. */
+ __asm__ __volatile__ (
+ "ldr s0, %1\n\t"
+ "ldr s1, %2\n\t"
+ "fadd s0, s0, s1\n\t"
+ "mrs %0, fpsr" : "=r" (fpsr)
+ : "m" (fp_max), "m" (fp_1e32)
+ : "d0", "d1");
+
+ if (FE_UNDERFLOW & excepts)
+ __asm__ __volatile__ (
+ "ldr s0, %1\n\t"
+ "ldr s1, %2\n\t"
+ "fdiv s0, s0, s1\n\t"
+ "mrs %0, fpsr" : "=r" (fpsr)
+ : "m" (fp_min), "m" (fp_three)
+ : "d0", "d1");
+
+ if (FE_INEXACT & excepts)
+ __asm__ __volatile__ (
+ "ldr s0, %1\n\t"
+ "ldr s1, %2\n\t"
+ "fdiv s0, s0, s1\n\t"
+ "mrs %0, fpsr" : "=r" (fpsr)
+ : "m" (fp_two), "m" (fp_three)
+ : "d0", "d1");
+
+ return 0;
+}
diff --git a/libm/aarch64/fsetexcptflg.c b/libm/aarch64/fsetexcptflg.c
new file mode 100644
index 000000000..a78623d14
--- /dev/null
+++ b/libm/aarch64/fsetexcptflg.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fpu_fpsr_t fpsr;
+ fpu_fpsr_t fpsr_new;
+
+ /* Get the current environment. */
+ _FPU_GETFPSR (fpsr);
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Set the desired exception mask. */
+ fpsr_new = fpsr & ~excepts;
+ fpsr_new |= *flagp & excepts;
+
+ /* Save state back to the FPU. */
+ if (fpsr != fpsr_new)
+ _FPU_SETFPSR (fpsr_new);
+
+ return 0;
+}
diff --git a/libm/aarch64/ftestexcept.c b/libm/aarch64/ftestexcept.c
new file mode 100644
index 000000000..eecb93406
--- /dev/null
+++ b/libm/aarch64/ftestexcept.c
@@ -0,0 +1,24 @@
+/* Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fetestexcept (int excepts)
+{
+ return libc_fetestexcept_aarch64 (excepts);
+}
diff --git a/libm/arc/Makefile.arch b/libm/arc/Makefile.arch
new file mode 100644
index 000000000..bd38690be
--- /dev/null
+++ b/libm/arc/Makefile.arch
@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)
diff --git a/libm/arc/fclrexcpt.c b/libm/arc/fclrexcpt.c
new file mode 100644
index 000000000..76631657d
--- /dev/null
+++ b/libm/arc/fclrexcpt.c
@@ -0,0 +1,34 @@
+/* Clear given exceptions in current floating-point environment.
+ 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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feclearexcept (int excepts)
+{
+ unsigned int fpsr;
+
+ _FPU_GETS (fpsr);
+
+ /* Clear the relevant bits, FWE is preserved. */
+ fpsr &= ~excepts;
+
+ _FPU_SETS (fpsr);
+
+ return 0;
+}
diff --git a/libm/arc/fegetenv.c b/libm/arc/fegetenv.c
new file mode 100644
index 000000000..ad332c3e5
--- /dev/null
+++ b/libm/arc/fegetenv.c
@@ -0,0 +1,33 @@
+/* Store current floating-point environment.
+ 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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetenv (fenv_t *envp)
+{
+ unsigned int fpcr;
+ unsigned int fpsr;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETS (fpsr);
+ envp->__fpcr = fpcr;
+ envp->__fpsr = fpsr;
+
+ return 0;
+}
diff --git a/libm/arc/fegetmode.c b/libm/arc/fegetmode.c
new file mode 100644
index 000000000..e6aebbc87
--- /dev/null
+++ b/libm/arc/fegetmode.c
@@ -0,0 +1,30 @@
+/* Store current floating-point control modes.
+ 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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetmode (femode_t *modep)
+{
+ unsigned int fpcr;
+
+ _FPU_GETCW (fpcr);
+ *modep = fpcr;
+
+ return 0;
+}
diff --git a/libm/arc/fegetround.c b/libm/arc/fegetround.c
new file mode 100644
index 000000000..4dc476a7c
--- /dev/null
+++ b/libm/arc/fegetround.c
@@ -0,0 +1,28 @@
+/* Return current rounding direction.
+ 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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetround (void)
+{
+ unsigned int fpcr;
+ _FPU_GETCW (fpcr);
+
+ return (fpcr >> __FPU_RND_SHIFT) & __FPU_RND_MASK;
+}
diff --git a/libm/arc/feholdexcpt.c b/libm/arc/feholdexcpt.c
new file mode 100644
index 000000000..8febc7508
--- /dev/null
+++ b/libm/arc/feholdexcpt.c
@@ -0,0 +1,39 @@
+/* Store current floating-point environment and clear exceptions.
+ 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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feholdexcept (fenv_t *envp)
+{
+ unsigned int fpcr;
+ unsigned int fpsr;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETS (fpsr);
+
+ envp->__fpcr = fpcr;
+ envp->__fpsr = fpsr;
+
+ fpsr &= ~FE_ALL_EXCEPT;
+
+ _FPU_SETCW (fpcr);
+ _FPU_SETS (fpsr);
+
+ return 0;
+}
diff --git a/libm/arc/fenv_private.h b/libm/arc/fenv_private.h
new file mode 100644
index 000000000..5f74c5e13
--- /dev/null
+++ b/libm/arc/fenv_private.h
@@ -0,0 +1,326 @@
+/* Optimized inline fenv.h functions for libm. Generic version.
+ Copyright (C) 2011-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_PRIVATE_H
+#define _FENV_PRIVATE_H 1
+
+#include <fenv.h>
+#include "get-rounding-mode.h"
+
+/* The standards only specify one variant of the fenv.h interfaces.
+ But at least for some architectures we can be more efficient if we
+ know what operations are going to be performed. Therefore we
+ define additional interfaces. By default they refer to the normal
+ interfaces. */
+
+static __always_inline void
+default_libc_feholdexcept (fenv_t *e)
+{
+ (void) feholdexcept (e);
+}
+
+#ifndef libc_feholdexcept
+# define libc_feholdexcept default_libc_feholdexcept
+#endif
+#ifndef libc_feholdexceptf
+# define libc_feholdexceptf default_libc_feholdexcept
+#endif
+#ifndef libc_feholdexceptl
+# define libc_feholdexceptl default_libc_feholdexcept
+#endif
+
+static __always_inline void
+default_libc_fesetround (int r)
+{
+ (void) fesetround (r);
+}
+
+#ifndef libc_fesetround
+# define libc_fesetround default_libc_fesetround
+#endif
+#ifndef libc_fesetroundf
+# define libc_fesetroundf default_libc_fesetround
+#endif
+#ifndef libc_fesetroundl
+# define libc_fesetroundl default_libc_fesetround
+#endif
+
+static __always_inline void
+default_libc_feholdexcept_setround (fenv_t *e, int r)
+{
+ feholdexcept (e);
+ fesetround (r);
+}
+
+#ifndef libc_feholdexcept_setround
+# define libc_feholdexcept_setround default_libc_feholdexcept_setround
+#endif
+#ifndef libc_feholdexcept_setroundf
+# define libc_feholdexcept_setroundf default_libc_feholdexcept_setround
+#endif
+#ifndef libc_feholdexcept_setroundl
+# define libc_feholdexcept_setroundl default_libc_feholdexcept_setround
+#endif
+
+#ifndef libc_feholdsetround_53bit
+# define libc_feholdsetround_53bit libc_feholdsetround
+#endif
+
+#ifndef libc_fetestexcept
+# define libc_fetestexcept fetestexcept
+#endif
+#ifndef libc_fetestexceptf
+# define libc_fetestexceptf fetestexcept
+#endif
+#ifndef libc_fetestexceptl
+# define libc_fetestexceptl fetestexcept
+#endif
+
+static __always_inline void
+default_libc_fesetenv (fenv_t *e)
+{
+ (void) fesetenv (e);
+}
+
+#ifndef libc_fesetenv
+# define libc_fesetenv default_libc_fesetenv
+#endif
+#ifndef libc_fesetenvf
+# define libc_fesetenvf default_libc_fesetenv
+#endif
+#ifndef libc_fesetenvl
+# define libc_fesetenvl default_libc_fesetenv
+#endif
+
+static __always_inline void
+default_libc_feupdateenv (fenv_t *e)
+{
+ (void) feupdateenv (e);
+}
+
+#ifndef libc_feupdateenv
+# define libc_feupdateenv default_libc_feupdateenv
+#endif
+#ifndef libc_feupdateenvf
+# define libc_feupdateenvf default_libc_feupdateenv
+#endif
+#ifndef libc_feupdateenvl
+# define libc_feupdateenvl default_libc_feupdateenv
+#endif
+
+#ifndef libc_feresetround_53bit
+# define libc_feresetround_53bit libc_feresetround
+#endif
+
+static __always_inline int
+default_libc_feupdateenv_test (fenv_t *e, int ex)
+{
+ int ret = fetestexcept (ex);
+ feupdateenv (e);
+ return ret;
+}
+
+#ifndef libc_feupdateenv_test
+# define libc_feupdateenv_test default_libc_feupdateenv_test
+#endif
+#ifndef libc_feupdateenv_testf
+# define libc_feupdateenv_testf default_libc_feupdateenv_test
+#endif
+#ifndef libc_feupdateenv_testl
+# define libc_feupdateenv_testl default_libc_feupdateenv_test
+#endif
+
+/* Save and set the rounding mode. The use of fenv_t to store the old mode
+ allows a target-specific version of this function to avoid converting the
+ rounding mode from the fpu format. By default we have no choice but to
+ manipulate the entire env. */
+
+#ifndef libc_feholdsetround
+# define libc_feholdsetround libc_feholdexcept_setround
+#endif
+#ifndef libc_feholdsetroundf
+# define libc_feholdsetroundf libc_feholdexcept_setroundf
+#endif
+#ifndef libc_feholdsetroundl
+# define libc_feholdsetroundl libc_feholdexcept_setroundl
+#endif
+
+/* ... and the reverse. */
+
+#ifndef libc_feresetround
+# define libc_feresetround libc_feupdateenv
+#endif
+#ifndef libc_feresetroundf
+# define libc_feresetroundf libc_feupdateenvf
+#endif
+#ifndef libc_feresetroundl
+# define libc_feresetroundl libc_feupdateenvl
+#endif
+
+/* ... and a version that also discards exceptions. */
+
+#ifndef libc_feresetround_noex
+# define libc_feresetround_noex libc_fesetenv
+#endif
+#ifndef libc_feresetround_noexf
+# define libc_feresetround_noexf libc_fesetenvf
+#endif
+#ifndef libc_feresetround_noexl
+# define libc_feresetround_noexl libc_fesetenvl
+#endif
+
+#ifndef HAVE_RM_CTX
+# define HAVE_RM_CTX 0
+#endif
+
+
+/* Default implementation using standard fenv functions.
+ Avoid unnecessary rounding mode changes by first checking the
+ current rounding mode. Note the use of unlikely is
+ important for performance. */
+
+static __always_inline void
+default_libc_feholdsetround_ctx (struct rm_ctx *ctx, int round)
+{
+ ctx->updated_status = false;
+
+ /* Update rounding mode only if different. */
+ if (unlikely (round != get_rounding_mode ()))
+ {
+ ctx->updated_status = true;
+ fegetenv (&ctx->env);
+ fesetround (round);
+ }
+}
+
+static __always_inline void
+default_libc_feresetround_ctx (struct rm_ctx *ctx)
+{
+ /* Restore the rounding mode if updated. */
+ if (unlikely (ctx->updated_status))
+ feupdateenv (&ctx->env);
+}
+
+static __always_inline void
+default_libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round)
+{
+ /* Save exception flags and rounding mode, and disable exception
+ traps. */
+ feholdexcept (&ctx->env);
+
+ /* Update rounding mode only if different. */
+ if (unlikely (round != get_rounding_mode ()))
+ fesetround (round);
+}
+
+static __always_inline void
+default_libc_feresetround_noex_ctx (struct rm_ctx *ctx)
+{
+ /* Restore exception flags and rounding mode. */
+ fesetenv (&ctx->env);
+}
+
+#if HAVE_RM_CTX
+/* Set/Restore Rounding Modes only when necessary. If defined, these functions
+ set/restore floating point state only if the state needed within the lexical
+ block is different from the current state. This saves a lot of time when
+ the floating point unit is much slower than the fixed point units. */
+
+# ifndef libc_feholdsetround_noex_ctx
+# define libc_feholdsetround_noex_ctx libc_feholdsetround_ctx
+# endif
+# ifndef libc_feholdsetround_noexf_ctx
+# define libc_feholdsetround_noexf_ctx libc_feholdsetroundf_ctx
+# endif
+# ifndef libc_feholdsetround_noexl_ctx
+# define libc_feholdsetround_noexl_ctx libc_feholdsetroundl_ctx
+# endif
+
+# ifndef libc_feresetround_noex_ctx
+# define libc_feresetround_noex_ctx libc_fesetenv_ctx
+# endif
+# ifndef libc_feresetround_noexf_ctx
+# define libc_feresetround_noexf_ctx libc_fesetenvf_ctx
+# endif
+# ifndef libc_feresetround_noexl_ctx
+# define libc_feresetround_noexl_ctx libc_fesetenvl_ctx
+# endif
+
+#else
+
+# define libc_feholdsetround_ctx default_libc_feholdsetround_ctx
+# define libc_feresetround_ctx default_libc_feresetround_ctx
+# define libc_feholdsetround_noex_ctx default_libc_feholdsetround_noex_ctx
+# define libc_feresetround_noex_ctx default_libc_feresetround_noex_ctx
+
+# define libc_feholdsetroundf_ctx libc_feholdsetround_ctx
+# define libc_feholdsetroundl_ctx libc_feholdsetround_ctx
+# define libc_feresetroundf_ctx libc_feresetround_ctx
+# define libc_feresetroundl_ctx libc_feresetround_ctx
+
+# define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ctx
+# define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ctx
+# define libc_feresetround_noexf_ctx libc_feresetround_noex_ctx
+# define libc_feresetround_noexl_ctx libc_feresetround_noex_ctx
+
+#endif
+
+#ifndef libc_feholdsetround_53bit_ctx
+# define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx
+#endif
+#ifndef libc_feresetround_53bit_ctx
+# define libc_feresetround_53bit_ctx libc_feresetround_ctx
+#endif
+
+#define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \
+ struct rm_ctx ctx __attribute__((cleanup (CLEANUPFUNC ## _ctx))); \
+ ROUNDFUNC ## _ctx (&ctx, (RM))
+
+/* Set the rounding mode within a lexical block. Restore the rounding mode to
+ the value at the start of the block. The exception mode must be preserved.
+ Exceptions raised within the block must be set in the exception flags.
+ Non-stop mode may be enabled inside the block. */
+
+#define SET_RESTORE_ROUND(RM) \
+ SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround)
+#define SET_RESTORE_ROUNDF(RM) \
+ SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetroundf)
+#define SET_RESTORE_ROUNDL(RM) \
+ SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetroundl)
+
+/* Set the rounding mode within a lexical block. Restore the rounding mode to
+ the value at the start of the block. The exception mode must be preserved.
+ Exceptions raised within the block must be discarded, and exception flags
+ are restored to the value at the start of the block.
+ Non-stop mode must be enabled inside the block. */
+
+#define SET_RESTORE_ROUND_NOEX(RM) \
+ SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noex, \
+ libc_feresetround_noex)
+#define SET_RESTORE_ROUND_NOEXF(RM) \
+ SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexf, \
+ libc_feresetround_noexf)
+#define SET_RESTORE_ROUND_NOEXL(RM) \
+ SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexl, \
+ libc_feresetround_noexl)
+
+/* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits. */
+#define SET_RESTORE_ROUND_53BIT(RM) \
+ SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_53bit, \
+ libc_feresetround_53bit)
+
+#endif /* fenv_private.h. */
diff --git a/libm/arc/fesetenv.c b/libm/arc/fesetenv.c
new file mode 100644
index 000000000..59ec3b722
--- /dev/null
+++ b/libm/arc/fesetenv.c
@@ -0,0 +1,44 @@
+/* Install given floating-point environment (does not raise exceptions).
+ 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/>. */
+
+#include <fenv.h>
+#include "fpu_control.h"
+
+int
+fesetenv (const fenv_t *envp)
+{
+ unsigned int fpcr;
+ unsigned int fpsr;
+
+ if (envp == FE_DFL_ENV)
+ {
+ fpcr = _FPU_DEFAULT;
+ fpsr = _FPU_FPSR_DEFAULT;
+ }
+ else
+ {
+ /* No need to mask out reserved bits as they are IoW. */
+ fpcr = envp->__fpcr;
+ fpsr = envp->__fpsr;
+ }
+
+ _FPU_SETCW (fpcr);
+ _FPU_SETS (fpsr);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/arc/fesetexcept.c b/libm/arc/fesetexcept.c
new file mode 100644
index 000000000..3756a2e09
--- /dev/null
+++ b/libm/arc/fesetexcept.c
@@ -0,0 +1,31 @@
+/* Set given exception flags.
+ 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/>. */
+
+#include <fenv.h>
+#include "fpu_control.h"
+
+int
+fesetexcept (int excepts)
+{
+ unsigned int fpsr;
+
+ _FPU_GETS (fpsr);
+ fpsr |= excepts;
+ _FPU_SETS (fpsr);
+
+ return 0;
+}
diff --git a/libm/arc/fesetmode.c b/libm/arc/fesetmode.c
new file mode 100644
index 000000000..1fc2bdf12
--- /dev/null
+++ b/libm/arc/fesetmode.c
@@ -0,0 +1,39 @@
+/* Install given floating-point control modes.
+ 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/>. */
+
+#include <fenv.h>
+#include "fpu_control.h"
+
+int
+fesetmode (const femode_t *modep)
+{
+ unsigned int fpcr;
+
+ if (modep == FE_DFL_MODE)
+ {
+ fpcr = _FPU_DEFAULT;
+ }
+ else
+ {
+ /* No need to mask out reserved bits as they are IoW. */
+ fpcr = *modep;
+ }
+
+ _FPU_SETCW (fpcr);
+
+ return 0;
+}
diff --git a/libm/arc/fesetround.c b/libm/arc/fesetround.c
new file mode 100644
index 000000000..e156e9cf5
--- /dev/null
+++ b/libm/arc/fesetround.c
@@ -0,0 +1,36 @@
+/* Set current rounding direction.
+ 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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fesetround (int round)
+{
+ unsigned int fpcr;
+
+ _FPU_GETCW (fpcr);
+
+ if (((fpcr >> __FPU_RND_SHIFT) & __FPU_RND_MASK) != round)
+ {
+ fpcr &= ~(__FPU_RND_MASK << __FPU_RND_SHIFT);
+ fpcr |= (round & __FPU_RND_MASK) << __FPU_RND_SHIFT;
+ _FPU_SETCW (fpcr);
+ }
+
+ return 0;
+}
diff --git a/libm/arc/feupdateenv.c b/libm/arc/feupdateenv.c
new file mode 100644
index 000000000..6a59b2bfe
--- /dev/null
+++ b/libm/arc/feupdateenv.c
@@ -0,0 +1,47 @@
+/* Install given floating-point environment and raise exceptions,
+ without clearing currently raised exceptions.
+ 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/>. */
+
+#include <fenv.h>
+#include "fpu_control.h"
+
+int
+feupdateenv (const fenv_t *envp)
+{
+ unsigned int fpcr;
+ unsigned int fpsr;
+
+ _FPU_GETS (fpsr);
+
+ if (envp == FE_DFL_ENV)
+ {
+ fpcr = _FPU_DEFAULT;
+ }
+ else
+ {
+ fpcr = envp->__fpcr;
+
+ /* currently raised exceptions need to be preserved. */
+ fpsr |= envp->__fpsr;
+ }
+
+ _FPU_SETCW (fpcr);
+ _FPU_SETS (fpsr);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/arc/fgetexcptflg.c b/libm/arc/fgetexcptflg.c
new file mode 100644
index 000000000..03f97f99f
--- /dev/null
+++ b/libm/arc/fgetexcptflg.c
@@ -0,0 +1,30 @@
+/* Store current representation for exceptions, 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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ unsigned int fpsr;
+
+ _FPU_GETS (fpsr);
+ *flagp = fpsr & excepts;
+
+ return 0;
+}
diff --git a/libm/arc/fraiseexcpt.c b/libm/arc/fraiseexcpt.c
new file mode 100644
index 000000000..2ff5e0269
--- /dev/null
+++ b/libm/arc/fraiseexcpt.c
@@ -0,0 +1,35 @@
+/* Raise given exceptions.
+ 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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include <float.h>
+#include <math.h>
+
+int
+feraiseexcept (int excepts)
+{
+ unsigned int fpsr;
+
+ /* currently raised exceptions are not cleared. */
+ _FPU_GETS (fpsr);
+ fpsr |= excepts;
+
+ _FPU_SETS (fpsr);
+
+ return 0;
+}
diff --git a/libm/arc/fsetexcptflg.c b/libm/arc/fsetexcptflg.c
new file mode 100644
index 000000000..97ff20fff
--- /dev/null
+++ b/libm/arc/fsetexcptflg.c
@@ -0,0 +1,37 @@
+/* Set floating-point environment exception handling, 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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ unsigned int fpsr;
+
+ _FPU_GETS (fpsr);
+
+ /* Clear the bits first. */
+ fpsr &= ~excepts;
+
+ /* Now set those bits, copying them over from @flagp. */
+ fpsr |= *flagp & excepts;
+
+ _FPU_SETS (fpsr);
+
+ return 0;
+}
diff --git a/libm/arc/ftestexcept.c b/libm/arc/ftestexcept.c
new file mode 100644
index 000000000..ccc557e5e
--- /dev/null
+++ b/libm/arc/ftestexcept.c
@@ -0,0 +1,31 @@
+/* Test exception in current environment.
+ 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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "fenv_private.h"
+#include <stdio.h>
+
+int
+fetestexcept (int excepts)
+{
+ unsigned int fpsr;
+
+ _FPU_GETS (fpsr);
+
+ return fpsr & excepts;
+}
diff --git a/libm/arc/get-rounding-mode.h b/libm/arc/get-rounding-mode.h
new file mode 100644
index 000000000..d1bf3475d
--- /dev/null
+++ b/libm/arc/get-rounding-mode.h
@@ -0,0 +1,37 @@
+/* Determine floating-point rounding mode within libc. 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 _ARC_GET_ROUNDING_MODE_H
+#define _ARC_GET_ROUNDING_MODE_H 1
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+static inline int
+get_rounding_mode (void)
+{
+#if defined(__ARC_FPU_SP__) || defined(__ARC_FPU_DP__)
+ unsigned int fpcr;
+ _FPU_GETCW (fpcr);
+
+ return (fpcr >> __FPU_RND_SHIFT) & __FPU_RND_MASK;
+#else
+ return FE_TONEAREST;
+#endif
+}
+
+#endif /* get-rounding-mode.h */
diff --git a/libm/arm/Makefile.arch b/libm/arm/Makefile.arch
new file mode 100644
index 000000000..bd38690be
--- /dev/null
+++ b/libm/arm/Makefile.arch
@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)
diff --git a/libm/arm/arm-features.h b/libm/arm/arm-features.h
new file mode 100644
index 000000000..8f9fd7362
--- /dev/null
+++ b/libm/arm/arm-features.h
@@ -0,0 +1,58 @@
+/* Macros to test for CPU features on ARM. Generic ARM version.
+ Copyright (C) 2012-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 _ARM_ARM_FEATURES_H
+#define _ARM_ARM_FEATURES_H 1
+
+/* An OS-specific arm-features.h file should define ARM_HAVE_VFP to
+ an appropriate expression for testing at runtime whether the VFP
+ hardware is present. We'll then redefine it to a constant if we
+ know at compile time that we can assume VFP. */
+
+#ifndef __SOFTFP__
+/* The compiler is generating VFP instructions, so we're already
+ assuming the hardware exists. */
+# undef ARM_HAVE_VFP
+# define ARM_HAVE_VFP 1
+#endif
+
+/* An OS-specific arm-features.h file may define ARM_ASSUME_NO_IWMMXT
+ to indicate at compile time that iWMMXt hardware is never present
+ at runtime (or that we never care about its state) and so need not
+ be checked for. */
+
+/* A more-specific arm-features.h file may define ARM_ALWAYS_BX to indicate
+ that instructions using pc as a destination register must never be used,
+ so a "bx" (or "blx") instruction is always required. */
+
+/* The log2 of the minimum alignment required for an address that
+ is the target of a computed branch (i.e. a "bx" instruction).
+ A more-specific arm-features.h file may define this to set a more
+ stringent requirement.
+
+ Using this only makes sense for code in ARM mode (where instructions
+ always have a fixed size of four bytes), or for Thumb-mode code that is
+ specifically aligning all the related branch targets to match (since
+ Thumb instructions might be either two or four bytes). */
+#ifndef ARM_BX_ALIGN_LOG2
+# define ARM_BX_ALIGN_LOG2 2
+#endif
+
+/* An OS-specific arm-features.h file may define ARM_NO_INDEX_REGISTER to
+ indicate that the two-register addressing modes must never be used. */
+
+#endif /* arm-features.h */
diff --git a/libm/arm/fclrexcpt.c b/libm/arm/fclrexcpt.c
new file mode 100644
index 000000000..81de94271
--- /dev/null
+++ b/libm/arm/fclrexcpt.c
@@ -0,0 +1,41 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "arm-features.h"
+
+
+int
+feclearexcept (int excepts)
+{
+ fpu_control_t fpscr, new_fpscr;
+
+ /* Fail if a VFP unit isn't present unless nothing needs to be done. */
+ if (!ARM_HAVE_VFP)
+ return (excepts != 0);
+
+ _FPU_GETCW (fpscr);
+ excepts &= FE_ALL_EXCEPT;
+ new_fpscr = fpscr & ~excepts;
+
+ /* Write new exception flags if changed. */
+ if (new_fpscr != fpscr)
+ _FPU_SETCW (new_fpscr);
+
+ return 0;
+}
diff --git a/libm/arm/fedisblxcpt.c b/libm/arm/fedisblxcpt.c
new file mode 100644
index 000000000..c507e80b4
--- /dev/null
+++ b/libm/arm/fedisblxcpt.c
@@ -0,0 +1,41 @@
+/* Disable floating-point exceptions.
+ Copyright (C) 2001-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "arm-features.h"
+
+
+int
+fedisableexcept (int excepts)
+{
+ fpu_control_t fpscr, new_fpscr;
+
+ /* Fail if a VFP unit isn't present. */
+ if (!ARM_HAVE_VFP)
+ return -1;
+
+ _FPU_GETCW (fpscr);
+ excepts &= FE_ALL_EXCEPT;
+ new_fpscr = fpscr & ~(excepts << FE_EXCEPT_SHIFT);
+
+ /* Write new exceptions if changed. */
+ if (new_fpscr != fpscr)
+ _FPU_SETCW (new_fpscr);
+
+ return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
+}
diff --git a/libm/arm/feenablxcpt.c b/libm/arm/feenablxcpt.c
new file mode 100644
index 000000000..41e8eb912
--- /dev/null
+++ b/libm/arm/feenablxcpt.c
@@ -0,0 +1,49 @@
+/* Enable floating-point exceptions.
+ Copyright (C) 2001-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "arm-features.h"
+
+
+int
+feenableexcept (int excepts)
+{
+ fpu_control_t fpscr, new_fpscr, updated_fpscr;
+
+ /* Fail if a VFP unit isn't present. */
+ if (!ARM_HAVE_VFP)
+ return -1;
+
+ _FPU_GETCW (fpscr);
+ excepts &= FE_ALL_EXCEPT;
+ new_fpscr = fpscr | (excepts << FE_EXCEPT_SHIFT);
+
+ if (new_fpscr != fpscr)
+ {
+ _FPU_SETCW (new_fpscr);
+
+ /* Not all VFP architectures support trapping exceptions, so
+ test whether the relevant bits were set and fail if not. */
+ _FPU_GETCW (updated_fpscr);
+
+ if (new_fpscr & ~updated_fpscr)
+ return -1;
+ }
+
+ return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
+}
diff --git a/libm/arm/fegetenv.c b/libm/arm/fegetenv.c
new file mode 100644
index 000000000..a9f63f5c9
--- /dev/null
+++ b/libm/arm/fegetenv.c
@@ -0,0 +1,35 @@
+/* Store current floating-point environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "arm-features.h"
+
+
+int
+fegetenv (fenv_t *envp)
+{
+ fpu_control_t fpscr;
+
+ /* Fail if a VFP unit isn't present. */
+ if (!ARM_HAVE_VFP)
+ return 1;
+
+ _FPU_GETCW (fpscr);
+ envp->__cw = fpscr;
+ return 0;
+}
diff --git a/libm/arm/fegetexcept.c b/libm/arm/fegetexcept.c
new file mode 100644
index 000000000..5dd8e144b
--- /dev/null
+++ b/libm/arm/fegetexcept.c
@@ -0,0 +1,35 @@
+/* Get floating-point exceptions.
+ Copyright (C) 2001-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "arm-features.h"
+
+
+int
+fegetexcept (void)
+{
+ fpu_control_t fpscr;
+
+ /* Return with all exceptions disabled if a VFP unit isn't present. */
+ if (!ARM_HAVE_VFP)
+ return 0;
+
+ _FPU_GETCW (fpscr);
+
+ return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
+}
diff --git a/libm/arm/fegetmode.c b/libm/arm/fegetmode.c
new file mode 100644
index 000000000..bf2597353
--- /dev/null
+++ b/libm/arm/fegetmode.c
@@ -0,0 +1,28 @@
+/* Store current floating-point control modes. ARM version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "arm-features.h"
+
+int
+fegetmode (femode_t *modep)
+{
+ if (ARM_HAVE_VFP)
+ _FPU_GETCW (*modep);
+ return 0;
+}
diff --git a/libm/arm/fegetround.c b/libm/arm/fegetround.c
new file mode 100644
index 000000000..2f9320491
--- /dev/null
+++ b/libm/arm/fegetround.c
@@ -0,0 +1,42 @@
+/* Return current rounding direction.
+ 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/>. */
+
+#include "arm-features.h"
+#include <fenv.h>
+#include <fpu_control.h>
+
+/* Return the floating-point rounding mode. */
+
+static inline int
+get_rounding_mode (void)
+{
+ fpu_control_t fpscr;
+
+ /* FE_TONEAREST is the only supported rounding mode
+ if a VFP unit isn't present. */
+ if (!ARM_HAVE_VFP)
+ return FE_TONEAREST;
+
+ _FPU_GETCW (fpscr);
+ return fpscr & _FPU_MASK_RM;
+}
+
+int
+fegetround (void)
+{
+ return get_rounding_mode ();
+}
diff --git a/libm/arm/feholdexcpt.c b/libm/arm/feholdexcpt.c
new file mode 100644
index 000000000..3608931db
--- /dev/null
+++ b/libm/arm/feholdexcpt.c
@@ -0,0 +1,31 @@
+/* Store current floating-point environment and clear exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include "fenv_private.h"
+#include "arm-features.h"
+
+
+int
+feholdexcept (fenv_t *envp)
+{
+ /* Fail if a VFP unit isn't present. */
+ if (!ARM_HAVE_VFP)
+ return 1;
+
+ libc_feholdexcept_vfp (envp);
+ return 0;
+}
diff --git a/libm/arm/fenv_private.h b/libm/arm/fenv_private.h
new file mode 100644
index 000000000..566bf443c
--- /dev/null
+++ b/libm/arm/fenv_private.h
@@ -0,0 +1,248 @@
+/* Private floating point rounding and exceptions handling. ARM VFP version.
+ Copyright (C) 2014-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 ARM_FENV_PRIVATE_H
+#define ARM_FENV_PRIVATE_H 1
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+static __always_inline void
+libc_feholdexcept_vfp (fenv_t *envp)
+{
+ fpu_control_t fpscr;
+
+ _FPU_GETCW (fpscr);
+ envp->__cw = fpscr;
+
+ /* Clear exception flags and set all exceptions to non-stop. */
+ fpscr &= ~_FPU_MASK_EXCEPT;
+ _FPU_SETCW (fpscr);
+}
+
+static __always_inline void
+libc_fesetround_vfp (int round)
+{
+ fpu_control_t fpscr;
+
+ _FPU_GETCW (fpscr);
+
+ /* Set new rounding mode if different. */
+ if (unlikely ((fpscr & _FPU_MASK_RM) != round))
+ _FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round);
+}
+
+static __always_inline void
+libc_feholdexcept_setround_vfp (fenv_t *envp, int round)
+{
+ fpu_control_t fpscr;
+
+ _FPU_GETCW (fpscr);
+ envp->__cw = fpscr;
+
+ /* Clear exception flags, set all exceptions to non-stop,
+ and set new rounding mode. */
+ fpscr &= ~(_FPU_MASK_EXCEPT | _FPU_MASK_RM);
+ _FPU_SETCW (fpscr | round);
+}
+
+static __always_inline void
+libc_feholdsetround_vfp (fenv_t *envp, int round)
+{
+ fpu_control_t fpscr;
+
+ _FPU_GETCW (fpscr);
+ envp->__cw = fpscr;
+
+ /* Set new rounding mode if different. */
+ if (unlikely ((fpscr & _FPU_MASK_RM) != round))
+ _FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round);
+}
+
+static __always_inline void
+libc_feresetround_vfp (fenv_t *envp)
+{
+ fpu_control_t fpscr, round;
+
+ _FPU_GETCW (fpscr);
+
+ /* Check whether rounding modes are different. */
+ round = (envp->__cw ^ fpscr) & _FPU_MASK_RM;
+
+ /* Restore the rounding mode if it was changed. */
+ if (unlikely (round != 0))
+ _FPU_SETCW (fpscr ^ round);
+}
+
+static __always_inline int
+libc_fetestexcept_vfp (int ex)
+{
+ fpu_control_t fpscr;
+
+ _FPU_GETCW (fpscr);
+ return fpscr & ex & FE_ALL_EXCEPT;
+}
+
+static __always_inline void
+libc_fesetenv_vfp (const fenv_t *envp)
+{
+ fpu_control_t fpscr, new_fpscr;
+
+ _FPU_GETCW (fpscr);
+ new_fpscr = envp->__cw;
+
+ /* Write new FPSCR if different (ignoring NZCV flags). */
+ if (unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0))
+ _FPU_SETCW (new_fpscr);
+}
+
+static __always_inline int
+libc_feupdateenv_test_vfp (const fenv_t *envp, int ex)
+{
+ fpu_control_t fpscr, new_fpscr;
+ int excepts;
+
+ _FPU_GETCW (fpscr);
+
+ /* Merge current exception flags with the saved fenv. */
+ excepts = fpscr & FE_ALL_EXCEPT;
+ new_fpscr = envp->__cw | excepts;
+
+ /* Write new FPSCR if different (ignoring NZCV flags). */
+ if (unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0))
+ _FPU_SETCW (new_fpscr);
+
+ /* Raise the exceptions if enabled in the new FP state. */
+ if (unlikely (excepts & (new_fpscr >> FE_EXCEPT_SHIFT)))
+ feraiseexcept (excepts);
+
+ return excepts & ex;
+}
+
+static __always_inline void
+libc_feupdateenv_vfp (const fenv_t *envp)
+{
+ libc_feupdateenv_test_vfp (envp, 0);
+}
+
+static __always_inline void
+libc_feholdsetround_vfp_ctx (struct rm_ctx *ctx, int r)
+{
+ fpu_control_t fpscr, round;
+
+ _FPU_GETCW (fpscr);
+ ctx->updated_status = false;
+ ctx->env.__cw = fpscr;
+
+ /* Check whether rounding modes are different. */
+ round = (fpscr ^ r) & _FPU_MASK_RM;
+
+ /* Set the rounding mode if changed. */
+ if (unlikely (round != 0))
+ {
+ ctx->updated_status = true;
+ _FPU_SETCW (fpscr ^ round);
+ }
+}
+
+static __always_inline void
+libc_feresetround_vfp_ctx (struct rm_ctx *ctx)
+{
+ /* Restore the rounding mode if updated. */
+ if (unlikely (ctx->updated_status))
+ {
+ fpu_control_t fpscr;
+
+ _FPU_GETCW (fpscr);
+ fpscr = (fpscr & ~_FPU_MASK_RM) | (ctx->env.__cw & _FPU_MASK_RM);
+ _FPU_SETCW (fpscr);
+ }
+}
+
+static __always_inline void
+libc_fesetenv_vfp_ctx (struct rm_ctx *ctx)
+{
+ fpu_control_t fpscr, new_fpscr;
+
+ _FPU_GETCW (fpscr);
+ new_fpscr = ctx->env.__cw;
+
+ /* Write new FPSCR if different (ignoring NZCV flags). */
+ if (unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0))
+ _FPU_SETCW (new_fpscr);
+}
+
+#ifndef __SOFTFP__
+
+# define libc_feholdexcept libc_feholdexcept_vfp
+# define libc_feholdexceptf libc_feholdexcept_vfp
+# define libc_feholdexceptl libc_feholdexcept_vfp
+
+# define libc_fesetround libc_fesetround_vfp
+# define libc_fesetroundf libc_fesetround_vfp
+# define libc_fesetroundl libc_fesetround_vfp
+
+# define libc_feresetround libc_feresetround_vfp
+# define libc_feresetroundf libc_feresetround_vfp
+# define libc_feresetroundl libc_feresetround_vfp
+
+# define libc_feresetround_noex libc_fesetenv_vfp
+# define libc_feresetround_noexf libc_fesetenv_vfp
+# define libc_feresetround_noexl libc_fesetenv_vfp
+
+# define libc_feholdexcept_setround libc_feholdexcept_setround_vfp
+# define libc_feholdexcept_setroundf libc_feholdexcept_setround_vfp
+# define libc_feholdexcept_setroundl libc_feholdexcept_setround_vfp
+
+# define libc_feholdsetround libc_feholdsetround_vfp
+# define libc_feholdsetroundf libc_feholdsetround_vfp
+# define libc_feholdsetroundl libc_feholdsetround_vfp
+
+# define libc_fetestexcept libc_fetestexcept_vfp
+# define libc_fetestexceptf libc_fetestexcept_vfp
+# define libc_fetestexceptl libc_fetestexcept_vfp
+
+# define libc_fesetenv libc_fesetenv_vfp
+# define libc_fesetenvf libc_fesetenv_vfp
+# define libc_fesetenvl libc_fesetenv_vfp
+
+# define libc_feupdateenv libc_feupdateenv_vfp
+# define libc_feupdateenvf libc_feupdateenv_vfp
+# define libc_feupdateenvl libc_feupdateenv_vfp
+
+# define libc_feupdateenv_test libc_feupdateenv_test_vfp
+# define libc_feupdateenv_testf libc_feupdateenv_test_vfp
+# define libc_feupdateenv_testl libc_feupdateenv_test_vfp
+
+/* We have support for rounding mode context. */
+#define HAVE_RM_CTX 1
+
+# define libc_feholdsetround_ctx libc_feholdsetround_vfp_ctx
+# define libc_feresetround_ctx libc_feresetround_vfp_ctx
+# define libc_feresetround_noex_ctx libc_fesetenv_vfp_ctx
+
+# define libc_feholdsetroundf_ctx libc_feholdsetround_vfp_ctx
+# define libc_feresetroundf_ctx libc_feresetround_vfp_ctx
+# define libc_feresetround_noexf_ctx libc_fesetenv_vfp_ctx
+
+# define libc_feholdsetroundl_ctx libc_feholdsetround_vfp_ctx
+# define libc_feresetroundl_ctx libc_feresetround_vfp_ctx
+# define libc_feresetround_noexl_ctx libc_fesetenv_vfp_ctx
+
+#endif
+
+#endif /* ARM_FENV_PRIVATE_H */
diff --git a/libm/arm/fesetenv.c b/libm/arm/fesetenv.c
new file mode 100644
index 000000000..4675dbe88
--- /dev/null
+++ b/libm/arm/fesetenv.c
@@ -0,0 +1,62 @@
+/* Install given floating-point environment.
+ 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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "arm-features.h"
+
+
+int
+fesetenv (const fenv_t *envp)
+{
+ fpu_control_t fpscr, new_fpscr, updated_fpscr;
+
+ /* Fail if a VFP unit isn't present. */
+ if (!ARM_HAVE_VFP)
+ return 1;
+
+ _FPU_GETCW (fpscr);
+
+ if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV))
+ {
+ /* The new FPSCR is valid, so don't merge the reserved flags. */
+ new_fpscr = envp->__cw;
+
+ /* Write new FPSCR if different (ignoring NZCV flags). */
+ if (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0)
+ _FPU_SETCW (new_fpscr);
+
+ return 0;
+ }
+
+ /* Preserve the reserved FPSCR flags. */
+ new_fpscr = fpscr & _FPU_RESERVED;
+ new_fpscr |= (envp == FE_DFL_ENV) ? _FPU_DEFAULT : _FPU_IEEE;
+
+ if (((new_fpscr ^ fpscr) & ~_FPU_MASK_NZCV) != 0)
+ {
+ _FPU_SETCW (new_fpscr);
+
+ /* Not all VFP architectures support trapping exceptions, so
+ test whether the relevant bits were set and fail if not. */
+ _FPU_GETCW (updated_fpscr);
+
+ return new_fpscr & ~updated_fpscr;
+ }
+
+ return 0;
+}
diff --git a/libm/arm/fesetexcept.c b/libm/arm/fesetexcept.c
new file mode 100644
index 000000000..03338c783
--- /dev/null
+++ b/libm/arm/fesetexcept.c
@@ -0,0 +1,37 @@
+/* Set given exception flags. ARM version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "arm-features.h"
+
+int
+fesetexcept (int excepts)
+{
+ fpu_control_t fpscr, new_fpscr;
+
+ /* Fail if a VFP unit isn't present unless nothing needs to be done. */
+ if (!ARM_HAVE_VFP)
+ return (excepts != 0);
+
+ _FPU_GETCW (fpscr);
+ new_fpscr = fpscr | (excepts & FE_ALL_EXCEPT);
+ if (new_fpscr != fpscr)
+ _FPU_SETCW (new_fpscr);
+
+ return 0;
+}
diff --git a/libm/arm/fesetmode.c b/libm/arm/fesetmode.c
new file mode 100644
index 000000000..7919022b0
--- /dev/null
+++ b/libm/arm/fesetmode.c
@@ -0,0 +1,44 @@
+/* Install given floating-point control modes. ARM version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "arm-features.h"
+
+/* NZCV flags, QC bit, IDC bit and bits for IEEE exception status. */
+#define FPU_STATUS_BITS 0xf800009f
+
+int
+fesetmode (const femode_t *modep)
+{
+ fpu_control_t fpscr, new_fpscr;
+
+ if (!ARM_HAVE_VFP)
+ /* Nothing to do. */
+ return 0;
+
+ _FPU_GETCW (fpscr);
+ if (modep == FE_DFL_MODE)
+ new_fpscr = (fpscr & (_FPU_RESERVED | FPU_STATUS_BITS)) | _FPU_DEFAULT;
+ else
+ new_fpscr = (fpscr & FPU_STATUS_BITS) | (*modep & ~FPU_STATUS_BITS);
+
+ if (((new_fpscr ^ fpscr) & ~_FPU_MASK_NZCV) != 0)
+ _FPU_SETCW (new_fpscr);
+
+ return 0;
+}
diff --git a/libm/arm/fesetround.c b/libm/arm/fesetround.c
new file mode 100644
index 000000000..1cb6b366c
--- /dev/null
+++ b/libm/arm/fesetround.c
@@ -0,0 +1,35 @@
+/* Set current rounding direction.
+ 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/>. */
+
+#include "fenv_private.h"
+#include "arm-features.h"
+
+
+int
+fesetround (int round)
+{
+ /* FE_TONEAREST is the only supported rounding mode
+ if a VFP unit isn't present. */
+ if (!ARM_HAVE_VFP)
+ return (round == FE_TONEAREST) ? 0 : 1;
+
+ if (round & ~_FPU_MASK_RM)
+ return 1;
+
+ libc_fesetround_vfp (round);
+ return 0;
+}
diff --git a/libm/arm/feupdateenv.c b/libm/arm/feupdateenv.c
new file mode 100644
index 000000000..a246b865b
--- /dev/null
+++ b/libm/arm/feupdateenv.c
@@ -0,0 +1,73 @@
+/* Install given floating-point environment and raise exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "arm-features.h"
+
+
+int
+feupdateenv (const fenv_t *envp)
+{
+ fpu_control_t fpscr, new_fpscr, updated_fpscr;
+ int excepts;
+
+ /* Fail if a VFP unit isn't present. */
+ if (!ARM_HAVE_VFP)
+ return 1;
+
+ _FPU_GETCW (fpscr);
+ excepts = fpscr & FE_ALL_EXCEPT;
+
+ if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV))
+ {
+ /* Merge current exception flags with the saved fenv. */
+ new_fpscr = envp->__cw | excepts;
+
+ /* Write new FPSCR if different (ignoring NZCV flags). */
+ if (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0)
+ _FPU_SETCW (new_fpscr);
+
+ /* Raise the exceptions if enabled in the new FP state. */
+ if (excepts & (new_fpscr >> FE_EXCEPT_SHIFT))
+ return feraiseexcept (excepts);
+
+ return 0;
+ }
+
+ /* Preserve the reserved FPSCR flags. */
+ new_fpscr = fpscr & (_FPU_RESERVED | FE_ALL_EXCEPT);
+ new_fpscr |= (envp == FE_DFL_ENV) ? _FPU_DEFAULT : _FPU_IEEE;
+
+ if (((new_fpscr ^ fpscr) & ~_FPU_MASK_NZCV) != 0)
+ {
+ _FPU_SETCW (new_fpscr);
+
+ /* Not all VFP architectures support trapping exceptions, so
+ test whether the relevant bits were set and fail if not. */
+ _FPU_GETCW (updated_fpscr);
+
+ if (new_fpscr & ~updated_fpscr)
+ return 1;
+ }
+
+ /* Raise the exceptions if enabled in the new FP state. */
+ if (excepts & (new_fpscr >> FE_EXCEPT_SHIFT))
+ return feraiseexcept (excepts);
+
+ return 0;
+}
diff --git a/libm/arm/fgetexcptflg.c b/libm/arm/fgetexcptflg.c
new file mode 100644
index 000000000..2ef835fd4
--- /dev/null
+++ b/libm/arm/fgetexcptflg.c
@@ -0,0 +1,31 @@
+/* Store current representation for exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include "fenv_private.h"
+#include "arm-features.h"
+
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ /* Fail if a VFP unit isn't present. */
+ if (!ARM_HAVE_VFP)
+ return 1;
+
+ *flagp = libc_fetestexcept_vfp (excepts);
+ return 0;
+}
diff --git a/libm/arm/fraiseexcpt.c b/libm/arm/fraiseexcpt.c
new file mode 100644
index 000000000..91a5d6308
--- /dev/null
+++ b/libm/arm/fraiseexcpt.c
@@ -0,0 +1,103 @@
+/* Raise given exceptions.
+ 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/>. */
+
+#include <fpu_control.h>
+#include <fenv.h>
+#include <float.h>
+#include "arm-features.h"
+
+
+int
+feraiseexcept (int excepts)
+{
+ /* Fail if a VFP unit isn't present unless nothing needs to be done. */
+ if (!ARM_HAVE_VFP)
+ return (excepts != 0);
+ else
+ {
+ fpu_control_t fpscr;
+ const float fp_zero = 0.0, fp_one = 1.0, fp_max = FLT_MAX,
+ fp_min = FLT_MIN, fp_1e32 = 1.0e32f, fp_two = 2.0,
+ fp_three = 3.0;
+
+ /* Raise exceptions represented by EXPECTS. But we must raise only
+ one signal at a time. It is important that if the overflow/underflow
+ exception and the inexact exception are given at the same time,
+ the overflow/underflow exception follows the inexact exception. After
+ each exception we read from the fpscr, to force the exception to be
+ raised immediately. */
+
+ /* There are additional complications because this file may be compiled
+ without VFP support enabled, and we also can't assume that the
+ assembler has VFP instructions enabled. To get around this we use the
+ generic coprocessor mnemonics and avoid asking GCC to put float values
+ in VFP registers. */
+
+ /* First: invalid exception. */
+ if (FE_INVALID & excepts)
+ __asm__ __volatile__ (
+ "ldc p10, cr0, %1\n\t" /* flds s0, %1 */
+ "cdp p10, 8, cr0, cr0, cr0, 0\n\t" /* fdivs s0, s0, s0 */
+ "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
+ : "m" (fp_zero)
+ : "s0");
+
+ /* Next: division by zero. */
+ if (FE_DIVBYZERO & excepts)
+ __asm__ __volatile__ (
+ "ldc p10, cr0, %1\n\t" /* flds s0, %1 */
+ "ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
+ "cdp p10, 8, cr0, cr0, cr0, 1\n\t" /* fdivs s0, s0, s1 */
+ "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
+ : "m" (fp_one), "m" (fp_zero)
+ : "s0", "s1");
+
+ /* Next: overflow. */
+ if (FE_OVERFLOW & excepts)
+ /* There's no way to raise overflow without also raising inexact. */
+ __asm__ __volatile__ (
+ "ldc p10, cr0, %1\n\t" /* flds s0, %1 */
+ "ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
+ "cdp p10, 3, cr0, cr0, cr0, 1\n\t" /* fadds s0, s0, s1 */
+ "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
+ : "m" (fp_max), "m" (fp_1e32)
+ : "s0", "s1");
+
+ /* Next: underflow. */
+ if (FE_UNDERFLOW & excepts)
+ __asm__ __volatile__ (
+ "ldc p10, cr0, %1\n\t" /* flds s0, %1 */
+ "ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
+ "cdp p10, 8, cr0, cr0, cr0, 1\n\t" /* fdivs s0, s0, s1 */
+ "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
+ : "m" (fp_min), "m" (fp_three)
+ : "s0", "s1");
+
+ /* Last: inexact. */
+ if (FE_INEXACT & excepts)
+ __asm__ __volatile__ (
+ "ldc p10, cr0, %1\n\t" /* flds s0, %1 */
+ "ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
+ "cdp p10, 8, cr0, cr0, cr0, 1\n\t" /* fdivs s0, s0, s1 */
+ "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
+ : "m" (fp_two), "m" (fp_three)
+ : "s0", "s1");
+
+ /* Success. */
+ return 0;
+ }
+}
diff --git a/libm/arm/fsetexcptflg.c b/libm/arm/fsetexcptflg.c
new file mode 100644
index 000000000..343b33af9
--- /dev/null
+++ b/libm/arm/fsetexcptflg.c
@@ -0,0 +1,44 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "arm-features.h"
+
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fpu_control_t fpscr, new_fpscr;
+
+ /* Fail if a VFP unit isn't present unless nothing needs to be done. */
+ if (!ARM_HAVE_VFP)
+ return (excepts != 0);
+
+ _FPU_GETCW (fpscr);
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Set the desired exception mask. */
+ new_fpscr = fpscr & ~excepts;
+ new_fpscr |= *flagp & excepts;
+
+ /* Write new exception flags if changed. */
+ if (new_fpscr != fpscr)
+ _FPU_SETCW (new_fpscr);
+
+ return 0;
+}
diff --git a/libm/arm/ftestexcept.c b/libm/arm/ftestexcept.c
new file mode 100644
index 000000000..8b836d97d
--- /dev/null
+++ b/libm/arm/ftestexcept.c
@@ -0,0 +1,30 @@
+/* Test exception in current environment.
+ Copyright (C) 1997-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/>. */
+
+#include "fenv_private.h"
+#include "arm-features.h"
+
+
+int
+fetestexcept (int excepts)
+{
+ /* Return no exception flags if a VFP unit isn't present. */
+ if (!ARM_HAVE_VFP)
+ return 0;
+
+ return libc_fetestexcept_vfp (excepts);
+}
diff --git a/libm/csky/Makefile.arch b/libm/csky/Makefile.arch
new file mode 100644
index 000000000..bd38690be
--- /dev/null
+++ b/libm/csky/Makefile.arch
@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)
diff --git a/libm/csky/fclrexcpt.c b/libm/csky/fclrexcpt.c
new file mode 100644
index 000000000..8f8acef16
--- /dev/null
+++ b/libm/csky/fclrexcpt.c
@@ -0,0 +1,40 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+feclearexcept (int excepts)
+{
+ int fpsr;
+
+ /* Mask out unsupported bits/exceptions. */
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Read the complete control word. */
+ _FPU_GETFPSR (fpsr);
+
+ /* Clear the relevant bits. */
+ fpsr &= ~(excepts | (excepts << CAUSE_SHIFT));
+
+ /* Put the new data in effect. */
+ _FPU_SETFPSR (fpsr);
+
+ return 0;
+}
diff --git a/libm/csky/fedisblxcpt.c b/libm/csky/fedisblxcpt.c
new file mode 100644
index 000000000..e518968ab
--- /dev/null
+++ b/libm/csky/fedisblxcpt.c
@@ -0,0 +1,40 @@
+/* Disable floating-point exceptions.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+fedisableexcept (int excepts)
+{
+ unsigned int new_exc, old_exc;
+
+ /* Get the current control word. */
+ _FPU_GETCW (new_exc);
+
+ old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT;
+
+ /* Get the except disable mask. */
+ excepts &= FE_ALL_EXCEPT;
+ new_exc &= ~(excepts << ENABLE_SHIFT);
+
+ /* Put the new data in effect. */
+ _FPU_SETCW (new_exc);
+
+ return old_exc;
+}
diff --git a/libm/csky/feenablxcpt.c b/libm/csky/feenablxcpt.c
new file mode 100644
index 000000000..90c495080
--- /dev/null
+++ b/libm/csky/feenablxcpt.c
@@ -0,0 +1,39 @@
+/* Enable floating-point exceptions.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+feenableexcept (int excepts)
+{
+ unsigned int new_exc, old_exc;
+
+ /* Get the current control word. */
+ _FPU_GETCW (new_exc);
+
+ old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT;
+
+ excepts &= FE_ALL_EXCEPT;
+
+ new_exc |= excepts << ENABLE_SHIFT;
+
+ _FPU_SETCW (new_exc);
+
+ return old_exc;
+}
diff --git a/libm/csky/fegetenv.c b/libm/csky/fegetenv.c
new file mode 100644
index 000000000..d98982fc1
--- /dev/null
+++ b/libm/csky/fegetenv.c
@@ -0,0 +1,33 @@
+/* Store current floating-point environment.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetenv (fenv_t *envp)
+{
+ unsigned int fpcr;
+ unsigned int fpsr;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+ envp->__fpcr = fpcr;
+ envp->__fpsr = fpsr;
+
+ return 0;
+}
diff --git a/libm/csky/fegetexcept.c b/libm/csky/fegetexcept.c
new file mode 100644
index 000000000..339f35923
--- /dev/null
+++ b/libm/csky/fegetexcept.c
@@ -0,0 +1,31 @@
+/* Get enabled floating-point exceptions.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+fegetexcept (void)
+{
+ unsigned int exc;
+
+ /* Get the current control word. */
+ _FPU_GETCW (exc);
+
+ return (exc & ENABLE_MASK) >> ENABLE_SHIFT;
+}
diff --git a/libm/csky/fegetmode.c b/libm/csky/fegetmode.c
new file mode 100644
index 000000000..09d8282dd
--- /dev/null
+++ b/libm/csky/fegetmode.c
@@ -0,0 +1,27 @@
+/* Store current floating-point control modes.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetmode (femode_t *modep)
+{
+ _FPU_GETCW (*modep);
+
+ return 0;
+}
diff --git a/libm/csky/fegetround.c b/libm/csky/fegetround.c
new file mode 100644
index 000000000..e68775af3
--- /dev/null
+++ b/libm/csky/fegetround.c
@@ -0,0 +1,30 @@
+/* Return current rounding direction.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetround (void)
+{
+ unsigned int cw;
+
+ /* Get control word. */
+ _FPU_GETCW (cw);
+
+ return cw & __FE_ROUND_MASK;
+}
diff --git a/libm/csky/feholdexcpt.c b/libm/csky/feholdexcpt.c
new file mode 100644
index 000000000..456af5eb1
--- /dev/null
+++ b/libm/csky/feholdexcpt.c
@@ -0,0 +1,30 @@
+/* Store current floating-point environment and clear exceptions.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "fenv_libc.h"
+#include "fenv_private.h"
+
+#include <stdio.h>
+
+int
+feholdexcept (fenv_t *envp)
+{
+ libc_feholdexcept_vfp (envp);
+ return 0;
+}
diff --git a/libm/csky/fenv_libc.h b/libm/csky/fenv_libc.h
new file mode 100644
index 000000000..44e89812d
--- /dev/null
+++ b/libm/csky/fenv_libc.h
@@ -0,0 +1,29 @@
+/* fpu registers environment. C-SKY version.
+ Copyright (C) 2018-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_LIBC_H
+#define _FENV_LIBC_H 1
+
+/* Mask for enabling exceptions and for the CAUSE bits. */
+#define ENABLE_MASK 0x0003FU
+#define CAUSE_MASK 0x3F000U
+
+/* Shift for FE_* flags to get up to the ENABLE bits and the CAUSE bits. */
+#define ENABLE_SHIFT 0
+#define CAUSE_SHIFT 8
+
+#endif /* fenv_libc.h */
diff --git a/libm/csky/fenv_private.h b/libm/csky/fenv_private.h
new file mode 100644
index 000000000..f0f48a88a
--- /dev/null
+++ b/libm/csky/fenv_private.h
@@ -0,0 +1,277 @@
+/* Private floating point rounding and exceptions handling. C-SKY version.
+ Copyright (C) 2018-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 CSKY_FENV_PRIVATE_H
+#define CSKY_FENV_PRIVATE_H 1
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "fenv_libc.h"
+
+static __always_inline void
+libc_feholdexcept_vfp (fenv_t *envp)
+{
+ fpu_control_t fpsr, fpcr;
+
+ _FPU_GETCW (fpcr);
+ envp->__fpcr = fpcr;
+
+ _FPU_GETFPSR (fpsr);
+ envp->__fpsr = fpsr;
+
+ /* Now set all exceptions to non-stop. */
+ fpcr &= ~FE_ALL_EXCEPT;
+
+ /* And clear all exception flags. */
+ fpsr &= ~(FE_ALL_EXCEPT << CAUSE_SHIFT);
+
+ _FPU_SETFPSR (fpsr);
+
+ _FPU_SETCW (fpcr);
+}
+
+static __always_inline void
+libc_fesetround_vfp (int round)
+{
+ fpu_control_t fpcr;
+
+ _FPU_GETCW (fpcr);
+
+ /* Set new rounding mode if different. */
+ if (unlikely ((fpcr & FE_DOWNWARD) != round))
+ _FPU_SETCW ((fpcr & ~FE_DOWNWARD) | round);
+}
+
+static __always_inline void
+libc_feholdexcept_setround_vfp (fenv_t *envp, int round)
+{
+ fpu_control_t fpsr, fpcr;
+
+ _FPU_GETCW (fpcr);
+ envp->__fpcr = fpcr;
+
+ _FPU_GETFPSR (fpsr);
+ envp->__fpsr = fpsr;
+
+ /* Clear exception flags, set all exceptions to non-stop,
+ and set new rounding mode. */
+ fpsr &= ~(FE_ALL_EXCEPT << CAUSE_SHIFT);
+ _FPU_SETFPSR (fpsr);
+
+ fpcr &= ~(FE_ALL_EXCEPT | FE_DOWNWARD);
+ _FPU_SETCW (fpcr | round);
+}
+
+static __always_inline void
+libc_feholdsetround_vfp (fenv_t *envp, int round)
+{
+ fpu_control_t fpcr;
+
+ _FPU_GETCW (fpcr);
+ envp->__fpcr = fpcr;
+
+ /* Set new rounding mode if different. */
+ if (unlikely ((fpcr & FE_DOWNWARD) != round))
+ _FPU_SETCW ((fpcr & ~FE_DOWNWARD) | round);
+}
+
+static __always_inline void
+libc_feresetround_vfp (fenv_t *envp)
+{
+ fpu_control_t fpcr, round;
+
+ _FPU_GETCW (fpcr);
+
+ /* Check whether rounding modes are different. */
+ round = (envp->__fpcr ^ fpcr) & FE_DOWNWARD;
+
+ /* Restore the rounding mode if it was changed. */
+ if (unlikely (round != 0))
+ _FPU_SETCW (fpcr ^ round);
+}
+
+static __always_inline int
+libc_fetestexcept_vfp (int ex)
+{
+ fpu_control_t fpsr;
+
+ _FPU_GETFPSR (fpsr);
+ fpsr = fpsr >> CAUSE_SHIFT;
+ return fpsr & ex & FE_ALL_EXCEPT;
+}
+
+static __always_inline void
+libc_fesetenv_vfp (const fenv_t *envp)
+{
+ fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+
+ new_fpcr = envp->__fpcr;
+ new_fpsr = envp->__fpsr;
+
+ if (unlikely (fpsr ^ new_fpsr) != 0)
+ _FPU_SETFPSR (new_fpsr);
+
+ if (unlikely (fpcr ^ new_fpcr) != 0)
+ _FPU_SETCW (new_fpcr);
+}
+
+static __always_inline int
+libc_feupdateenv_test_vfp (const fenv_t *envp, int ex)
+{
+ fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr, excepts;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+
+ /* Merge current exception flags with the saved fenv. */
+ excepts = (fpsr >> CAUSE_SHIFT) & FE_ALL_EXCEPT;
+ new_fpcr = envp->__fpcr;
+ new_fpsr = envp->__fpsr | (excepts << CAUSE_SHIFT);
+
+ /* Write FCR and FESR if different. */
+ if (unlikely (fpsr ^ new_fpsr) != 0)
+ _FPU_SETFPSR (new_fpsr);
+
+ if (unlikely (fpcr ^ new_fpcr) != 0)
+ _FPU_SETCW (new_fpcr);
+
+ /* Raise the exceptions if enabled in the new FP state. */
+ if (unlikely (excepts & new_fpcr))
+ feraiseexcept (excepts);
+
+ return excepts & ex;
+}
+
+static __always_inline void
+libc_feupdateenv_vfp (const fenv_t *envp)
+{
+ libc_feupdateenv_test_vfp (envp, 0);
+}
+
+static __always_inline void
+libc_feholdsetround_vfp_ctx (struct rm_ctx *ctx, int r)
+{
+ fpu_control_t fpcr, fpsr, round;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+ ctx->updated_status = false;
+ ctx->env.__fpcr = fpcr;
+ ctx->env.__fpsr = fpsr;
+
+ /* Check whether rounding modes are different. */
+ round = (fpcr ^ r) & FE_DOWNWARD;
+
+ /* Set the rounding mode if changed. */
+ if (unlikely (round != 0))
+ {
+ ctx->updated_status = true;
+ _FPU_SETCW (fpcr ^ round);
+ }
+}
+
+static __always_inline void
+libc_feresetround_vfp_ctx (struct rm_ctx *ctx)
+{
+ /* Restore the rounding mode if updated. */
+ if (unlikely (ctx->updated_status))
+ {
+ fpu_control_t fpcr;
+
+ _FPU_GETCW (fpcr);
+ fpcr = (fpcr & ~FE_DOWNWARD) | (ctx->env.__fpcr & FE_DOWNWARD);
+ _FPU_SETCW (fpcr);
+ }
+}
+
+static __always_inline void
+libc_fesetenv_vfp_ctx (struct rm_ctx *ctx)
+{
+ fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+
+ new_fpcr = ctx->env.__fpcr;
+ new_fpsr = ctx->env.__fpsr;
+
+ if (unlikely (fpsr ^ new_fpsr) != 0)
+ _FPU_SETFPSR (new_fpsr);
+
+ if (unlikely (fpcr ^ new_fpcr) != 0)
+ _FPU_SETCW (new_fpcr);
+}
+
+#define libc_feholdexcept libc_feholdexcept_vfp
+#define libc_feholdexceptf libc_feholdexcept_vfp
+#define libc_feholdexceptl libc_feholdexcept_vfp
+
+#define libc_fesetround libc_fesetround_vfp
+#define libc_fesetroundf libc_fesetround_vfp
+#define libc_fesetroundl libc_fesetround_vfp
+
+#define libc_feresetround libc_feresetround_vfp
+#define libc_feresetroundf libc_feresetround_vfp
+#define libc_feresetroundl libc_feresetround_vfp
+
+#define libc_feresetround_noex libc_fesetenv_vfp
+#define libc_feresetround_noexf libc_fesetenv_vfp
+#define libc_feresetround_noexl libc_fesetenv_vfp
+
+#define libc_feholdexcept_setround libc_feholdexcept_setround_vfp
+#define libc_feholdexcept_setroundf libc_feholdexcept_setround_vfp
+#define libc_feholdexcept_setroundl libc_feholdexcept_setround_vfp
+
+#define libc_feholdsetround libc_feholdsetround_vfp
+#define libc_feholdsetroundf libc_feholdsetround_vfp
+#define libc_feholdsetroundl libc_feholdsetround_vfp
+
+#define libc_fetestexcept libc_fetestexcept_vfp
+#define libc_fetestexceptf libc_fetestexcept_vfp
+#define libc_fetestexceptl libc_fetestexcept_vfp
+
+#define libc_fesetenv libc_fesetenv_vfp
+#define libc_fesetenvf libc_fesetenv_vfp
+#define libc_fesetenvl libc_fesetenv_vfp
+
+#define libc_feupdateenv libc_feupdateenv_vfp
+#define libc_feupdateenvf libc_feupdateenv_vfp
+#define libc_feupdateenvl libc_feupdateenv_vfp
+
+#define libc_feupdateenv_test libc_feupdateenv_test_vfp
+#define libc_feupdateenv_testf libc_feupdateenv_test_vfp
+#define libc_feupdateenv_testl libc_feupdateenv_test_vfp
+
+/* We have support for rounding mode context. */
+#define HAVE_RM_CTX 1
+
+#define libc_feholdsetround_ctx libc_feholdsetround_vfp_ctx
+#define libc_feresetround_ctx libc_feresetround_vfp_ctx
+#define libc_feresetround_noex_ctx libc_fesetenv_vfp_ctx
+
+#define libc_feholdsetroundf_ctx libc_feholdsetround_vfp_ctx
+#define libc_feresetroundf_ctx libc_feresetround_vfp_ctx
+#define libc_feresetround_noexf_ctx libc_fesetenv_vfp_ctx
+
+#define libc_feholdsetroundl_ctx libc_feholdsetround_vfp_ctx
+#define libc_feresetroundl_ctx libc_feresetround_vfp_ctx
+#define libc_feresetround_noexl_ctx libc_fesetenv_vfp_ctx
+
+#endif /* CSKY_FENV_PRIVATE_H */
diff --git a/libm/csky/fesetenv.c b/libm/csky/fesetenv.c
new file mode 100644
index 000000000..96b961598
--- /dev/null
+++ b/libm/csky/fesetenv.c
@@ -0,0 +1,55 @@
+/* Install given floating-point environment.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetenv (const fenv_t *envp)
+{
+ unsigned int fpcr;
+ unsigned int fpsr;
+
+ _FPU_GETCW (fpcr);
+ _FPU_GETFPSR (fpsr);
+
+ fpcr &= _FPU_RESERVED;
+ fpsr &= _FPU_FPSR_RESERVED;
+
+ if (envp == FE_DFL_ENV)
+ {
+ fpcr |= _FPU_DEFAULT;
+ fpsr |= _FPU_FPSR_DEFAULT;
+ }
+ else if (envp == FE_NOMASK_ENV)
+ {
+ fpcr |= _FPU_FPCR_IEEE;
+ fpsr |= _FPU_FPSR_IEEE;
+ }
+ else
+ {
+ fpcr |= envp->__fpcr & ~_FPU_RESERVED;
+ fpsr |= envp->__fpsr & ~_FPU_FPSR_RESERVED;
+ }
+
+ _FPU_SETFPSR (fpsr);
+
+ _FPU_SETCW (fpcr);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/csky/fesetexcept.c b/libm/csky/fesetexcept.c
new file mode 100644
index 000000000..940322197
--- /dev/null
+++ b/libm/csky/fesetexcept.c
@@ -0,0 +1,32 @@
+/* Set given exception flags.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "fenv_libc.h"
+
+int
+fesetexcept (int excepts)
+{
+ fpu_control_t fpsr, new_fpsr;
+ _FPU_GETFPSR (fpsr);
+ new_fpsr = fpsr | ((excepts & FE_ALL_EXCEPT) << CAUSE_SHIFT);
+ if (new_fpsr != fpsr)
+ _FPU_SETFPSR (new_fpsr);
+
+ return 0;
+}
diff --git a/libm/csky/fesetmode.c b/libm/csky/fesetmode.c
new file mode 100644
index 000000000..eddd2d401
--- /dev/null
+++ b/libm/csky/fesetmode.c
@@ -0,0 +1,32 @@
+/* Install given floating-point control modes.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetmode (const femode_t *modep)
+{
+ femode_t mode;
+ if (modep == FE_DFL_MODE)
+ mode = _FPU_DEFAULT;
+ else
+ mode = *modep;
+ _FPU_SETCW (mode);
+
+ return 0;
+}
diff --git a/libm/csky/fesetround.c b/libm/csky/fesetround.c
new file mode 100644
index 000000000..15a4b7c7e
--- /dev/null
+++ b/libm/csky/fesetround.c
@@ -0,0 +1,28 @@
+/* Set current rounding direction.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "fenv_private.h"
+
+#include <stdio.h>
+int
+fesetround (int round)
+{
+ libc_fesetround_vfp (round);
+ return 0;
+}
diff --git a/libm/csky/feupdateenv.c b/libm/csky/feupdateenv.c
new file mode 100644
index 000000000..91e627ad2
--- /dev/null
+++ b/libm/csky/feupdateenv.c
@@ -0,0 +1,42 @@
+/* Install given floating-point environment and raise exceptions.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "fenv_libc.h"
+#include "fenv_private.h"
+#include <stdio.h>
+
+int
+feupdateenv (const fenv_t *envp)
+{
+ int temp;
+
+ /* Save current exceptions. */
+ _FPU_GETFPSR (temp);
+ temp = (temp >> CAUSE_SHIFT) & FE_ALL_EXCEPT;
+ /* Install new environment. */
+ fesetenv (envp);
+
+ /* Raise the saved exception. Incidentally for us the implementation
+ defined format of the values in objects of type fexcept_t is the
+ same as the ones specified using the FE_* constants. */
+ feraiseexcept (temp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/csky/fgetexcptflg.c b/libm/csky/fgetexcptflg.c
new file mode 100644
index 000000000..c400a2c1f
--- /dev/null
+++ b/libm/csky/fgetexcptflg.c
@@ -0,0 +1,31 @@
+/* Store current representation for exceptions.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "fenv_libc.h"
+#include "fenv_private.h"
+#include <stdio.h>
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ *flagp = libc_fetestexcept_vfp (excepts);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/csky/fraiseexcpt.c b/libm/csky/fraiseexcpt.c
new file mode 100644
index 000000000..31cd32f2c
--- /dev/null
+++ b/libm/csky/fraiseexcpt.c
@@ -0,0 +1,122 @@
+/* Raise given exceptions.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+#include <float.h>
+#include <math.h>
+
+int
+feraiseexcept (int excepts)
+{
+ /* Raise exceptions represented by EXCEPTS. But we must raise only one
+ signal at a time. It is important that if the overflow/underflow
+ exception and the divide by zero exception are given at the same
+ time, the overflow/underflow exception follows the divide by zero
+ exception. */
+
+# ifndef __csky_fpuv1__
+ /* First: invalid exception. */
+ if (FE_INVALID & excepts)
+ {
+ /* One example of a invalid operation is 0 * Infinity. */
+ float x = HUGE_VALF, y = 0.0f;
+ __asm__ __volatile__ ("fmuls %0, %0, %1" : "+v" (x) : "v" (y));
+ }
+
+ /* Next: division by zero. */
+ if (FE_DIVBYZERO & excepts)
+ {
+ float x = 1.0f, y = 0.0f;
+ __asm__ __volatile__ ("fdivs %0, %0, %1" : "+v" (x) : "v" (y));
+ }
+
+ /* Next: overflow. */
+ if (FE_OVERFLOW & excepts)
+ {
+ float x = FLT_MAX;
+ __asm__ __volatile__ ("fmuls %0, %0, %0" : "+v" (x));
+ }
+ /* Next: underflow. */
+ if (FE_UNDERFLOW & excepts)
+ {
+ float x = -FLT_MIN;
+
+ __asm__ __volatile__ ("fmuls %0, %0, %0" : "+v" (x));
+ }
+
+ /* Last: inexact. */
+ if (FE_INEXACT & excepts)
+ {
+ float x = 1.0f, y = 3.0f;
+ __asm__ __volatile__ ("fdivs %0, %0, %1" : "+v" (x) : "v" (y));
+ }
+
+ if (__FE_DENORMAL & excepts)
+ {
+ double x = 4.9406564584124654e-324;
+ __asm__ __volatile__ ("fstod %0, %0" : "+v" (x));
+ }
+# else
+ int tmp = 0;
+ /* First: invalid exception. */
+ if (FE_INVALID & excepts)
+ {
+ /* One example of a invalid operation is 0 * Infinity. */
+ float x = HUGE_VALF, y = 0.0f;
+ __asm__ __volatile__ ("fmuls %0, %0, %2, %1"
+ : "+f" (x), "+r"(tmp) : "f" (y));
+ }
+
+ /* Next: division by zero. */
+ if (FE_DIVBYZERO & excepts)
+ {
+ float x = 1.0f, y = 0.0f;
+ __asm__ __volatile__ ("fdivs %0, %0, %2, %1"
+ : "+f" (x), "+r"(tmp) : "f" (y));
+ }
+
+ /* Next: overflow. */
+ if (FE_OVERFLOW & excepts)
+ {
+ float x = FLT_MAX, y = FLT_MAX;
+ __asm__ __volatile__ ("fmuls %0, %0, %2, %1"
+ : "+f" (x), "+r"(tmp) : "f" (y));
+ }
+
+ /* Next: underflow. */
+ if (FE_UNDERFLOW & excepts)
+ {
+ float x = -FLT_MIN, y = -FLT_MIN;
+
+ __asm__ __volatile__ ("fmuls %0, %0, %2, %1"
+ : "+f" (x), "+r"(tmp) : "f" (y));
+ }
+
+ /* Last: inexact. */
+ if (FE_INEXACT & excepts)
+ {
+ float x = 1.0f, y = 3.0f;
+ __asm__ __volatile__ ("fdivs %0, %0, %2, %1"
+ : "+f" (x), "+r"(tmp) : "f" (y));
+ }
+# endif /* __csky_fpuv2__ */
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/csky/fsetexcptflg.c b/libm/csky/fsetexcptflg.c
new file mode 100644
index 000000000..b6281d5c2
--- /dev/null
+++ b/libm/csky/fsetexcptflg.c
@@ -0,0 +1,42 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "fenv_libc.h"
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fpu_control_t temp;
+
+ /* Get the current exceptions. */
+ _FPU_GETFPSR (temp);
+
+ /* Make sure the flags we want restored are legal. */
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Now clear the bits called for, and copy them in from flagp. Note that
+ we ignore all non-flag bits from *flagp, so they don't matter. */
+ temp = ((temp >> CAUSE_SHIFT) & ~excepts) | (*flagp & excepts);
+ temp = temp << CAUSE_SHIFT;
+
+ _FPU_SETFPSR (temp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/csky/ftestexcept.c b/libm/csky/ftestexcept.c
new file mode 100644
index 000000000..6e3217eb1
--- /dev/null
+++ b/libm/csky/ftestexcept.c
@@ -0,0 +1,28 @@
+/* Test exception in current environment.
+ Copyright (C) 2018-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "fenv_libc.h"
+#include "fenv_private.h"
+#include <stdio.h>
+
+int
+fetestexcept (int excepts)
+{
+ return libc_fetestexcept_vfp (excepts);
+}
diff --git a/libm/m68k/Makefile.arch b/libm/m68k/Makefile.arch
new file mode 100644
index 000000000..bd38690be
--- /dev/null
+++ b/libm/m68k/Makefile.arch
@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)
diff --git a/libm/m68k/fclrexcpt.c b/libm/m68k/fclrexcpt.c
new file mode 100644
index 000000000..904ba5a19
--- /dev/null
+++ b/libm/m68k/fclrexcpt.c
@@ -0,0 +1,39 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+
+int
+feclearexcept (int excepts)
+{
+ fexcept_t fpsr;
+
+ /* Mask out unsupported bits/exceptions. */
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Fetch the fpu status register. */
+ __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+
+ /* Clear the relevant bits. */
+ fpsr &= ~excepts;
+
+ /* Put the new data in effect. */
+ __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr));
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/m68k/fedisblxcpt.c b/libm/m68k/fedisblxcpt.c
new file mode 100644
index 000000000..c2c593e38
--- /dev/null
+++ b/libm/m68k/fedisblxcpt.c
@@ -0,0 +1,36 @@
+/* Disable floating-point exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+
+int
+fedisableexcept (int excepts)
+{
+ unsigned int old_exc, new_exc;
+
+ /* Get the current control register contents. */
+ __asm__ ("fmove%.l %!,%0" : "=dm" (new_exc));
+
+ old_exc = (new_exc >> 6) & FE_ALL_EXCEPT;
+
+ excepts &= FE_ALL_EXCEPT;
+
+ new_exc &= ~(excepts << 6);
+ __asm__ ("fmove%.l %0,%!" : : "dm" (new_exc));
+
+ return old_exc;
+}
diff --git a/libm/m68k/feenablxcpt.c b/libm/m68k/feenablxcpt.c
new file mode 100644
index 000000000..9c01dc28b
--- /dev/null
+++ b/libm/m68k/feenablxcpt.c
@@ -0,0 +1,36 @@
+/* Enable floating-point exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+
+int
+feenableexcept (int excepts)
+{
+ unsigned int new_exc, old_exc;
+
+ /* Get the current control register contents. */
+ __asm__ ("fmove%.l %!,%0" : "=dm" (new_exc));
+
+ old_exc = (new_exc >> 6) & FE_ALL_EXCEPT;
+
+ excepts &= FE_ALL_EXCEPT;
+
+ new_exc |= excepts << 6;
+ __asm__ ("fmove%.l %0,%!" : : "dm" (new_exc));
+
+ return old_exc;
+}
diff --git a/libm/m68k/fegetenv.c b/libm/m68k/fegetenv.c
new file mode 100644
index 000000000..2cd0a7c88
--- /dev/null
+++ b/libm/m68k/fegetenv.c
@@ -0,0 +1,33 @@
+/* Store current floating-point environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+
+int
+fegetenv (fenv_t *envp)
+{
+#ifdef __mcoldfire__
+ __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (envp->__control_register));
+ __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (envp->__status_register));
+ __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (envp->__instruction_address));
+#else
+ __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*envp));
+#endif
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/m68k/fegetexcept.c b/libm/m68k/fegetexcept.c
new file mode 100644
index 000000000..1be3f8bf5
--- /dev/null
+++ b/libm/m68k/fegetexcept.c
@@ -0,0 +1,29 @@
+/* Get enabled floating-point exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+
+int
+fegetexcept (void)
+{
+ unsigned int exc;
+
+ /* Get the current control register contents. */
+ __asm__ ("fmove%.l %!,%0" : "=dm" (exc));
+
+ return (exc >> 6) & FE_ALL_EXCEPT;
+}
diff --git a/libm/m68k/fegetmode.c b/libm/m68k/fegetmode.c
new file mode 100644
index 000000000..19f49922a
--- /dev/null
+++ b/libm/m68k/fegetmode.c
@@ -0,0 +1,26 @@
+/* Store current floating-point control modes. M68K version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetmode (femode_t *modep)
+{
+ _FPU_GETCW (*modep);
+ return 0;
+}
diff --git a/libm/m68k/fegetround.c b/libm/m68k/fegetround.c
new file mode 100644
index 000000000..02f6c4c41
--- /dev/null
+++ b/libm/m68k/fegetround.c
@@ -0,0 +1,28 @@
+/* Return current rounding direction.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+
+int
+fegetround (void)
+{
+ int fpcr;
+
+ __asm__ ("fmove%.l %!,%0" : "=dm" (fpcr));
+
+ return fpcr & FE_UPWARD;
+}
diff --git a/libm/m68k/feholdexcpt.c b/libm/m68k/feholdexcpt.c
new file mode 100644
index 000000000..c0891969a
--- /dev/null
+++ b/libm/m68k/feholdexcpt.c
@@ -0,0 +1,42 @@
+/* Store current floating-point environment and clear exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+
+int
+feholdexcept (fenv_t *envp)
+{
+ fexcept_t fpcr, fpsr;
+
+ /* Store the environment. */
+#ifdef __mcoldfire__
+ __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (envp->__control_register));
+ __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (envp->__status_register));
+ __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (envp->__instruction_address));
+#else
+ __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*envp));
+#endif
+
+ /* Now clear all exceptions. */
+ fpsr = envp->__status_register & ~FE_ALL_EXCEPT;
+ __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr));
+ /* And set all exceptions to non-stop. */
+ fpcr = envp->__control_register & ~(FE_ALL_EXCEPT << 6);
+ __asm__ __volatile__ ("fmove%.l %0,%!" : : "dm" (fpcr));
+
+ return 0;
+}
diff --git a/libm/m68k/fesetenv.c b/libm/m68k/fesetenv.c
new file mode 100644
index 000000000..873eb9abe
--- /dev/null
+++ b/libm/m68k/fesetenv.c
@@ -0,0 +1,63 @@
+/* Install given floating-point environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+
+int
+fesetenv (const fenv_t *envp)
+{
+ fenv_t temp;
+
+ /* Install the environment specified by ENVP. But there are a few
+ values which we do not want to come from the saved environment.
+ Therefore, we get the current environment and replace the values
+ we want to use from the environment specified by the parameter. */
+#ifdef __mcoldfire__
+ __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (temp.__control_register));
+ __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (temp.__status_register));
+ __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (temp.__instruction_address));
+#else
+ __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*&temp));
+#endif
+
+ temp.__status_register &= ~FE_ALL_EXCEPT;
+ temp.__control_register &= ~((FE_ALL_EXCEPT << 6) | FE_UPWARD);
+ if (envp == FE_DFL_ENV)
+ ;
+ else if (envp == FE_NOMASK_ENV)
+ temp.__control_register |= FE_ALL_EXCEPT << 6;
+ else
+ {
+ temp.__control_register |= (envp->__control_register
+ & ((FE_ALL_EXCEPT << 6) | FE_UPWARD));
+ temp.__status_register |= envp->__status_register & FE_ALL_EXCEPT;
+ }
+
+#ifdef __mcoldfire__
+ __asm__ __volatile__ ("fmove%.l %0,%/fpiar"
+ :: "dm" (temp.__instruction_address));
+ __asm__ __volatile__ ("fmove%.l %0,%/fpcr"
+ :: "dm" (temp.__control_register));
+ __asm__ __volatile__ ("fmove%.l %0,%/fpsr"
+ :: "dm" (temp.__status_register));
+#else
+ __asm__ __volatile__ ("fmovem%.l %0,%/fpcr/%/fpsr/%/fpiar" : : "m" (*&temp));
+#endif
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/m68k/fesetexcept.c b/libm/m68k/fesetexcept.c
new file mode 100644
index 000000000..6ae4a55ea
--- /dev/null
+++ b/libm/m68k/fesetexcept.c
@@ -0,0 +1,30 @@
+/* Set given exception flags. M68K version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+
+int
+fesetexcept (int excepts)
+{
+ fexcept_t fpsr;
+
+ __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+ fpsr |= excepts & FE_ALL_EXCEPT;
+ __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr));
+
+ return 0;
+}
diff --git a/libm/m68k/fesetmode.c b/libm/m68k/fesetmode.c
new file mode 100644
index 000000000..a7e93d616
--- /dev/null
+++ b/libm/m68k/fesetmode.c
@@ -0,0 +1,31 @@
+/* Install given floating-point control modes. M68K version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetmode (const femode_t *modep)
+{
+ femode_t mode;
+ if (modep == FE_DFL_MODE)
+ mode = _FPU_DEFAULT;
+ else
+ mode = *modep;
+ _FPU_SETCW (mode);
+ return 0;
+}
diff --git a/libm/m68k/fesetround.c b/libm/m68k/fesetround.c
new file mode 100644
index 000000000..a8abc4e6e
--- /dev/null
+++ b/libm/m68k/fesetround.c
@@ -0,0 +1,35 @@
+/* Set current rounding direction.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+
+int
+fesetround (int round)
+{
+ fexcept_t fpcr;
+
+ if (round & ~FE_UPWARD)
+ /* ROUND is no valid rounding mode. */
+ return 1;
+
+ __asm__ ("fmove%.l %!,%0" : "=dm" (fpcr));
+ fpcr &= ~FE_UPWARD;
+ fpcr |= round;
+ __asm__ __volatile__ ("fmove%.l %0,%!" : : "dm" (fpcr));
+
+ return 0;
+}
diff --git a/libm/m68k/feupdateenv.c b/libm/m68k/feupdateenv.c
new file mode 100644
index 000000000..29dcc712e
--- /dev/null
+++ b/libm/m68k/feupdateenv.c
@@ -0,0 +1,39 @@
+/* Install given floating-point environment and raise exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+
+int
+feupdateenv (const fenv_t *envp)
+{
+ fexcept_t fpsr;
+
+ /* Save current exceptions. */
+ __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+ fpsr &= FE_ALL_EXCEPT;
+
+ /* Install new environment. */
+ fesetenv (envp);
+
+ /* Raise the saved exception. Incidentally for us the implementation
+ defined format of the values in objects of type fexcept_t is the
+ same as the ones specified using the FE_* constants. */
+ feraiseexcept ((int) fpsr);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/m68k/fgetexcptflg.c b/libm/m68k/fgetexcptflg.c
new file mode 100644
index 000000000..7a564555b
--- /dev/null
+++ b/libm/m68k/fgetexcptflg.c
@@ -0,0 +1,32 @@
+/* Store current representation for exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ fexcept_t fpsr;
+
+ /* Get the current exceptions. */
+ __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+
+ *flagp = fpsr & excepts & FE_ALL_EXCEPT;
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/m68k/fraiseexcpt.c b/libm/m68k/fraiseexcpt.c
new file mode 100644
index 000000000..4599c08f7
--- /dev/null
+++ b/libm/m68k/fraiseexcpt.c
@@ -0,0 +1,106 @@
+/* Raise given exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <float.h>
+#include <math.h>
+
+int
+feraiseexcept (int excepts)
+{
+#if defined(__mcffpu__)
+
+ /* The Coldfire FPU allows an exception to be raised by asserting
+ the associated EXC bit and then executing an arbitrary arithmetic
+ instruction. fmove.l is classified as an arithmetic instruction
+ and suffices for this purpose.
+
+ We therefore raise an exception by setting both the EXC and AEXC
+ bit associated with the exception (the former being 6 bits to the
+ left of the latter) and then loading the longword at (%sp) into an
+ FP register. */
+
+ inline void
+ raise_one_exception (int mask)
+ {
+ if (excepts & mask)
+ {
+ int fpsr;
+ double unused;
+
+ __asm__ volatile ("fmove%.l %/fpsr,%0" : "=d" (fpsr));
+ fpsr |= (mask << 6) | mask;
+ __asm__ volatile ("fmove%.l %0,%/fpsr" :: "d" (fpsr));
+ __asm__ volatile ("fmove%.l (%%sp),%0" : "=f" (unused));
+ }
+ }
+
+ raise_one_exception (FE_INVALID);
+ raise_one_exception (FE_DIVBYZERO);
+ raise_one_exception (FE_OVERFLOW);
+ raise_one_exception (FE_UNDERFLOW);
+ raise_one_exception (FE_INEXACT);
+
+#else
+ /* Raise exceptions represented by EXCEPTS. But we must raise only one
+ signal at a time. It is important that if the overflow/underflow
+ exception and the divide by zero exception are given at the same
+ time, the overflow/underflow exception follows the divide by zero
+ exception. */
+
+ /* First: invalid exception. */
+ if (excepts & FE_INVALID)
+ {
+ /* One example of an invalid operation is 0 * Infinity. */
+ double d = HUGE_VAL;
+ __asm__ __volatile__ ("fmul%.s %#0r0,%0; fnop" : "=f" (d) : "0" (d));
+ }
+
+ /* Next: division by zero. */
+ if (excepts & FE_DIVBYZERO)
+ {
+ double d = 1.0;
+ __asm__ __volatile__ ("fdiv%.s %#0r0,%0; fnop" : "=f" (d) : "0" (d));
+ }
+
+ /* Next: overflow. */
+ if (excepts & FE_OVERFLOW)
+ {
+ long double d = LDBL_MAX;
+
+ __asm__ __volatile__ ("fmul%.x %0,%0; fnop" : "=f" (d) : "0" (d));
+ }
+
+ /* Next: underflow. */
+ if (excepts & FE_UNDERFLOW)
+ {
+ long double d = -LDBL_MAX;
+
+ __asm__ __volatile__ ("fetox%.x %0; fnop" : "=f" (d) : "0" (d));
+ }
+
+ /* Last: inexact. */
+ if (excepts & FE_INEXACT)
+ {
+ long double d = 1.0;
+ __asm__ __volatile__ ("fdiv%.s %#0r3,%0; fnop" : "=f" (d) : "0" (d));
+ }
+
+#endif
+ /* Success. */
+ return 0;
+}
diff --git a/libm/m68k/fsetexcptflg.c b/libm/m68k/fsetexcptflg.c
new file mode 100644
index 000000000..18fc1811f
--- /dev/null
+++ b/libm/m68k/fsetexcptflg.c
@@ -0,0 +1,38 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <math.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fexcept_t fpsr;
+
+ /* Get the current status register. */
+ __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+
+ /* Install the new exception bits in the Accrued Exception Byte. */
+ fpsr &= ~(excepts & FE_ALL_EXCEPT);
+ fpsr |= *flagp & excepts & FE_ALL_EXCEPT;
+
+ /* Store the new status register. */
+ __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr));
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/m68k/ftestexcept.c b/libm/m68k/ftestexcept.c
new file mode 100644
index 000000000..1ece1a48d
--- /dev/null
+++ b/libm/m68k/ftestexcept.c
@@ -0,0 +1,29 @@
+/* Test exception in current environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+
+int
+fetestexcept (int excepts)
+{
+ fexcept_t fpsr;
+
+ /* Get current exceptions. */
+ __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+
+ return fpsr & excepts & FE_ALL_EXCEPT;
+}
diff --git a/libm/mips/Makefile.arch b/libm/mips/Makefile.arch
new file mode 100644
index 000000000..bd38690be
--- /dev/null
+++ b/libm/mips/Makefile.arch
@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)
diff --git a/libm/mips/fclrexcpt.c b/libm/mips/fclrexcpt.c
new file mode 100644
index 000000000..04d48d712
--- /dev/null
+++ b/libm/mips/fclrexcpt.c
@@ -0,0 +1,44 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+feclearexcept (int excepts)
+{
+ int cw;
+
+ /* Mask out unsupported bits/exceptions. */
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Read the complete control word. */
+ _FPU_GETCW (cw);
+
+ /* Clear exception flag bits and cause bits. If the cause bit is not
+ cleared, the next CTC instruction (just below) will re-generate the
+ exception. */
+
+ cw &= ~(excepts | (excepts << CAUSE_SHIFT));
+
+ /* Put the new data in effect. */
+ _FPU_SETCW (cw);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/mips/fedisblxcpt.c b/libm/mips/fedisblxcpt.c
new file mode 100644
index 000000000..85cd6c518
--- /dev/null
+++ b/libm/mips/fedisblxcpt.c
@@ -0,0 +1,38 @@
+/* Disable floating-point exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+fedisableexcept (int excepts)
+{
+ unsigned int new_exc, old_exc;
+
+ /* Get the current control word. */
+ _FPU_GETCW (new_exc);
+
+ old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT;
+
+ excepts &= FE_ALL_EXCEPT;
+
+ new_exc &= ~(excepts << ENABLE_SHIFT);
+ _FPU_SETCW (new_exc);
+
+ return old_exc;
+}
diff --git a/libm/mips/feenablxcpt.c b/libm/mips/feenablxcpt.c
new file mode 100644
index 000000000..9d919a8ba
--- /dev/null
+++ b/libm/mips/feenablxcpt.c
@@ -0,0 +1,38 @@
+/* Enable floating-point exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+feenableexcept (int excepts)
+{
+ unsigned int new_exc, old_exc;
+
+ /* Get the current control word. */
+ _FPU_GETCW (new_exc);
+
+ old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT;
+
+ excepts &= FE_ALL_EXCEPT;
+
+ new_exc |= excepts << ENABLE_SHIFT;
+ _FPU_SETCW (new_exc);
+
+ return old_exc;
+}
diff --git a/libm/mips/fegetenv.c b/libm/mips/fegetenv.c
new file mode 100644
index 000000000..94f3444ac
--- /dev/null
+++ b/libm/mips/fegetenv.c
@@ -0,0 +1,28 @@
+/* Store current floating-point environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetenv (fenv_t *envp)
+{
+ _FPU_GETCW (*envp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/mips/fegetexcept.c b/libm/mips/fegetexcept.c
new file mode 100644
index 000000000..4c7c89fa6
--- /dev/null
+++ b/libm/mips/fegetexcept.c
@@ -0,0 +1,31 @@
+/* Get enabled floating-point exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+fegetexcept (void)
+{
+ unsigned int exc;
+
+ /* Get the current control word. */
+ _FPU_GETCW (exc);
+
+ return (exc & ENABLE_MASK) >> ENABLE_SHIFT;
+}
diff --git a/libm/mips/fegetmode.c b/libm/mips/fegetmode.c
new file mode 100644
index 000000000..136b8d3fb
--- /dev/null
+++ b/libm/mips/fegetmode.c
@@ -0,0 +1,26 @@
+/* Store current floating-point control modes. MIPS version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetmode (femode_t *modep)
+{
+ _FPU_GETCW (*modep);
+ return 0;
+}
diff --git a/libm/mips/fegetround.c b/libm/mips/fegetround.c
new file mode 100644
index 000000000..4d8f3744d
--- /dev/null
+++ b/libm/mips/fegetround.c
@@ -0,0 +1,30 @@
+/* Return current rounding direction.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetround (void)
+{
+ int cw;
+
+ /* Get control word. */
+ _FPU_GETCW (cw);
+
+ return cw & _FPU_RC_MASK;
+}
diff --git a/libm/mips/feholdexcpt.c b/libm/mips/feholdexcpt.c
new file mode 100644
index 000000000..b1e35ae5a
--- /dev/null
+++ b/libm/mips/feholdexcpt.c
@@ -0,0 +1,35 @@
+/* Store current floating-point environment and clear exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feholdexcept (fenv_t *envp)
+{
+ fpu_control_t cw;
+
+ /* Save the current state. */
+ _FPU_GETCW (cw);
+ envp->__fp_control_register = cw;
+
+ /* Clear all exception enable bits and flags. */
+ cw &= ~(_FPU_MASK_V|_FPU_MASK_Z|_FPU_MASK_O|_FPU_MASK_U|_FPU_MASK_I|FE_ALL_EXCEPT);
+ _FPU_SETCW (cw);
+
+ return 0;
+}
diff --git a/libm/mips/fenv_libc.h b/libm/mips/fenv_libc.h
new file mode 100644
index 000000000..642a7b127
--- /dev/null
+++ b/libm/mips/fenv_libc.h
@@ -0,0 +1,29 @@
+/* Copyright (C) 2000-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_LIBC_H
+#define _FENV_LIBC_H 1
+
+/* Mask for enabling exceptions and for the CAUSE bits. */
+#define ENABLE_MASK 0x00F80U
+#define CAUSE_MASK 0x1F000U
+
+/* Shift for FE_* flags to get up to the ENABLE bits and the CAUSE bits. */
+#define ENABLE_SHIFT 5
+#define CAUSE_SHIFT 10
+
+
+#endif /* _FENV_LIBC_H */
diff --git a/libm/mips/fenv_private.h b/libm/mips/fenv_private.h
new file mode 100644
index 000000000..bc9be3b62
--- /dev/null
+++ b/libm/mips/fenv_private.h
@@ -0,0 +1,238 @@
+/* Internal math stuff. MIPS version.
+ Copyright (C) 2013-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 MIPS_FENV_PRIVATE_H
+#define MIPS_FENV_PRIVATE_H 1
+
+/* Inline functions to speed up the math library implementation. The
+ default versions of these routines are in generic/fenv_private.h
+ and call fesetround, feholdexcept, etc. These routines use inlined
+ code instead. */
+
+#include <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+#define _FPU_MASK_ALL (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O \
+ |_FPU_MASK_U | _FPU_MASK_I | FE_ALL_EXCEPT)
+
+static __always_inline void
+libc_feholdexcept_mips (fenv_t *envp)
+{
+ fpu_control_t cw;
+
+ /* Save the current state. */
+ _FPU_GETCW (cw);
+ envp->__fp_control_register = cw;
+
+ /* Clear all exception enable bits and flags. */
+ cw &= ~(_FPU_MASK_ALL);
+ _FPU_SETCW (cw);
+}
+#define libc_feholdexcept libc_feholdexcept_mips
+#define libc_feholdexceptf libc_feholdexcept_mips
+#define libc_feholdexceptl libc_feholdexcept_mips
+
+static __always_inline void
+libc_fesetround_mips (int round)
+{
+ fpu_control_t cw;
+
+ /* Get current state. */
+ _FPU_GETCW (cw);
+
+ /* Set rounding bits. */
+ cw &= ~_FPU_RC_MASK;
+ cw |= round;
+
+ /* Set new state. */
+ _FPU_SETCW (cw);
+}
+#define libc_fesetround libc_fesetround_mips
+#define libc_fesetroundf libc_fesetround_mips
+#define libc_fesetroundl libc_fesetround_mips
+
+static __always_inline void
+libc_feholdexcept_setround_mips (fenv_t *envp, int round)
+{
+ fpu_control_t cw;
+
+ /* Save the current state. */
+ _FPU_GETCW (cw);
+ envp->__fp_control_register = cw;
+
+ /* Clear all exception enable bits and flags. */
+ cw &= ~(_FPU_MASK_ALL);
+
+ /* Set rounding bits. */
+ cw &= ~_FPU_RC_MASK;
+ cw |= round;
+
+ /* Set new state. */
+ _FPU_SETCW (cw);
+}
+#define libc_feholdexcept_setround libc_feholdexcept_setround_mips
+#define libc_feholdexcept_setroundf libc_feholdexcept_setround_mips
+#define libc_feholdexcept_setroundl libc_feholdexcept_setround_mips
+
+#define libc_feholdsetround libc_feholdexcept_setround_mips
+#define libc_feholdsetroundf libc_feholdexcept_setround_mips
+#define libc_feholdsetroundl libc_feholdexcept_setround_mips
+
+static __always_inline void
+libc_fesetenv_mips (fenv_t *envp)
+{
+ fpu_control_t cw __attribute__ ((unused));
+
+ /* Read current state to flush fpu pipeline. */
+ _FPU_GETCW (cw);
+
+ _FPU_SETCW (envp->__fp_control_register);
+}
+#define libc_fesetenv libc_fesetenv_mips
+#define libc_fesetenvf libc_fesetenv_mips
+#define libc_fesetenvl libc_fesetenv_mips
+
+static __always_inline int
+libc_feupdateenv_test_mips (fenv_t *envp, int excepts)
+{
+ /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */
+ int cw, temp;
+
+ /* Get current control word. */
+ _FPU_GETCW (cw);
+
+ /* Set flag bits (which are accumulative), and *also* set the
+ cause bits. The setting of the cause bits is what actually causes
+ the hardware to generate the exception, if the corresponding enable
+ bit is set as well. */
+ temp = cw & FE_ALL_EXCEPT;
+ temp |= envp->__fp_control_register | (temp << CAUSE_SHIFT);
+
+ /* Set new state. */
+ _FPU_SETCW (temp);
+
+ return cw & excepts & FE_ALL_EXCEPT;
+}
+#define libc_feupdateenv_test libc_feupdateenv_test_mips
+#define libc_feupdateenv_testf libc_feupdateenv_test_mips
+#define libc_feupdateenv_testl libc_feupdateenv_test_mips
+
+static __always_inline void
+libc_feupdateenv_mips (fenv_t *envp)
+{
+ libc_feupdateenv_test_mips (envp, 0);
+}
+#define libc_feupdateenv libc_feupdateenv_mips
+#define libc_feupdateenvf libc_feupdateenv_mips
+#define libc_feupdateenvl libc_feupdateenv_mips
+
+#define libc_feresetround libc_feupdateenv_mips
+#define libc_feresetroundf libc_feupdateenv_mips
+#define libc_feresetroundl libc_feupdateenv_mips
+
+static __always_inline int
+libc_fetestexcept_mips (int excepts)
+{
+ int cw;
+
+ /* Get current control word. */
+ _FPU_GETCW (cw);
+
+ return cw & excepts & FE_ALL_EXCEPT;
+}
+#define libc_fetestexcept libc_fetestexcept_mips
+#define libc_fetestexceptf libc_fetestexcept_mips
+#define libc_fetestexceptl libc_fetestexcept_mips
+
+/* Enable support for rounding mode context. */
+#define HAVE_RM_CTX 1
+
+static __always_inline void
+libc_feholdexcept_setround_mips_ctx (struct rm_ctx *ctx, int round)
+{
+ fpu_control_t old, new;
+
+ /* Save the current state. */
+ _FPU_GETCW (old);
+ ctx->env.__fp_control_register = old;
+
+ /* Clear all exception enable bits and flags. */
+ new = old & ~(_FPU_MASK_ALL);
+
+ /* Set rounding bits. */
+ new = (new & ~_FPU_RC_MASK) | round;
+
+ if (__glibc_unlikely (new != old))
+ {
+ _FPU_SETCW (new);
+ ctx->updated_status = true;
+ }
+ else
+ ctx->updated_status = false;
+}
+#define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_mips_ctx
+#define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_mips_ctx
+#define libc_feholdexcept_setroundl_ctx libc_feholdexcept_setround_mips_ctx
+
+static __always_inline void
+libc_fesetenv_mips_ctx (struct rm_ctx *ctx)
+{
+ libc_fesetenv_mips (&ctx->env);
+}
+#define libc_fesetenv_ctx libc_fesetenv_mips_ctx
+#define libc_fesetenvf_ctx libc_fesetenv_mips_ctx
+#define libc_fesetenvl_ctx libc_fesetenv_mips_ctx
+
+static __always_inline void
+libc_feupdateenv_mips_ctx (struct rm_ctx *ctx)
+{
+ if (__glibc_unlikely (ctx->updated_status))
+ libc_feupdateenv_test_mips (&ctx->env, 0);
+}
+#define libc_feupdateenv_ctx libc_feupdateenv_mips_ctx
+#define libc_feupdateenvf_ctx libc_feupdateenv_mips_ctx
+#define libc_feupdateenvl_ctx libc_feupdateenv_mips_ctx
+#define libc_feresetround_ctx libc_feupdateenv_mips_ctx
+#define libc_feresetroundf_ctx libc_feupdateenv_mips_ctx
+#define libc_feresetroundl_ctx libc_feupdateenv_mips_ctx
+
+static __always_inline void
+libc_feholdsetround_mips_ctx (struct rm_ctx *ctx, int round)
+{
+ fpu_control_t old, new;
+
+ /* Save the current state. */
+ _FPU_GETCW (old);
+ ctx->env.__fp_control_register = old;
+
+ /* Set rounding bits. */
+ new = (old & ~_FPU_RC_MASK) | round;
+
+ if (__glibc_unlikely (new != old))
+ {
+ _FPU_SETCW (new);
+ ctx->updated_status = true;
+ }
+ else
+ ctx->updated_status = false;
+}
+#define libc_feholdsetround_ctx libc_feholdsetround_mips_ctx
+#define libc_feholdsetroundf_ctx libc_feholdsetround_mips_ctx
+#define libc_feholdsetroundl_ctx libc_feholdsetround_mips_ctx
+
+#endif
diff --git a/libm/mips/fesetenv.c b/libm/mips/fesetenv.c
new file mode 100644
index 000000000..03b5b91a6
--- /dev/null
+++ b/libm/mips/fesetenv.c
@@ -0,0 +1,38 @@
+/* Install given floating-point environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetenv (const fenv_t *envp)
+{
+ fpu_control_t cw;
+
+ /* Read first current state to flush fpu pipeline. */
+ _FPU_GETCW (cw);
+
+ if (envp == FE_DFL_ENV)
+ _FPU_SETCW (_FPU_DEFAULT);
+ else if (envp == FE_NOMASK_ENV)
+ _FPU_SETCW (_FPU_IEEE);
+ else
+ _FPU_SETCW (envp->__fp_control_register);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/mips/fesetexcept.c b/libm/mips/fesetexcept.c
new file mode 100644
index 000000000..1c9a0de3b
--- /dev/null
+++ b/libm/mips/fesetexcept.c
@@ -0,0 +1,31 @@
+/* Set given exception flags. MIPS version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexcept (int excepts)
+{
+ fpu_control_t temp;
+
+ _FPU_GETCW (temp);
+ temp |= excepts & FE_ALL_EXCEPT;
+ _FPU_SETCW (temp);
+
+ return 0;
+}
diff --git a/libm/mips/fesetmode.c b/libm/mips/fesetmode.c
new file mode 100644
index 000000000..cb4ffdc06
--- /dev/null
+++ b/libm/mips/fesetmode.c
@@ -0,0 +1,37 @@
+/* Install given floating-point control modes. MIPS version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+#define FCSR_STATUS 0xfe83f07c
+
+int
+fesetmode (const femode_t *modep)
+{
+ fpu_control_t cw;
+
+ _FPU_GETCW (cw);
+ cw &= FCSR_STATUS;
+ if (modep == FE_DFL_MODE)
+ cw |= _FPU_DEFAULT;
+ else
+ cw |= *modep & ~FCSR_STATUS;
+ _FPU_SETCW (cw);
+
+ return 0;
+}
diff --git a/libm/mips/fesetround.c b/libm/mips/fesetround.c
new file mode 100644
index 000000000..532092710
--- /dev/null
+++ b/libm/mips/fesetround.c
@@ -0,0 +1,40 @@
+/* Set current rounding direction.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetround (int round)
+{
+ fpu_control_t cw;
+
+ if ((round & ~_FPU_RC_MASK) != 0)
+ /* ROUND is no valid rounding mode. */
+ return 1;
+
+ /* Get current state. */
+ _FPU_GETCW (cw);
+
+ /* Set rounding bits. */
+ cw &= ~_FPU_RC_MASK;
+ cw |= round;
+ /* Set new state. */
+ _FPU_SETCW (cw);
+
+ return 0;
+}
diff --git a/libm/mips/feupdateenv.c b/libm/mips/feupdateenv.c
new file mode 100644
index 000000000..d90604db3
--- /dev/null
+++ b/libm/mips/feupdateenv.c
@@ -0,0 +1,40 @@
+/* Install given floating-point environment and raise exceptions.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feupdateenv (const fenv_t *envp)
+{
+ int temp;
+
+ /* Save current exceptions. */
+ _FPU_GETCW (temp);
+ temp &= FE_ALL_EXCEPT;
+
+ /* Install new environment. */
+ fesetenv (envp);
+
+ /* Raise the saved exception. Incidentally for us the implementation
+ defined format of the values in objects of type fexcept_t is the
+ same as the ones specified using the FE_* constants. */
+ feraiseexcept (temp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/mips/fgetexcptflg.c b/libm/mips/fgetexcptflg.c
new file mode 100644
index 000000000..b03eca55e
--- /dev/null
+++ b/libm/mips/fgetexcptflg.c
@@ -0,0 +1,37 @@
+/* Store current representation for exceptions.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ fpu_control_t temp;
+
+ /* Get the current exceptions. */
+ _FPU_GETCW (temp);
+
+ /* We only save the relevant bits here. In particular, care has to be
+ taken with the CAUSE bits, as an inadvertent restore later on could
+ generate unexpected exceptions. */
+
+ *flagp = temp & excepts & FE_ALL_EXCEPT;
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/mips/fraiseexcpt.c b/libm/mips/fraiseexcpt.c
new file mode 100644
index 000000000..6327b1104
--- /dev/null
+++ b/libm/mips/fraiseexcpt.c
@@ -0,0 +1,42 @@
+/* Raise given exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include "fenv_libc.h"
+#include <fpu_control.h>
+
+int
+feraiseexcept (int excepts)
+{
+ fpu_control_t cw;
+
+ /* Get current state. */
+ _FPU_GETCW (cw);
+
+ /* Set flag bits (which are accumulative), and *also* set the
+ cause bits. The setting of the cause bits is what actually causes
+ the hardware to generate the exception, if the corresponding enable
+ bit is set as well. */
+
+ excepts &= FE_ALL_EXCEPT;
+ cw |= excepts | (excepts << CAUSE_SHIFT);
+
+ /* Set new state. */
+ _FPU_SETCW (cw);
+
+ return 0;
+}
diff --git a/libm/mips/fsetexcptflg.c b/libm/mips/fsetexcptflg.c
new file mode 100644
index 000000000..d98a300e2
--- /dev/null
+++ b/libm/mips/fsetexcptflg.c
@@ -0,0 +1,40 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fpu_control_t temp;
+
+ /* Get the current exceptions. */
+ _FPU_GETCW (temp);
+
+ /* Make sure the flags we want restored are legal. */
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Now clear the bits called for, and copy them in from flagp. Note that
+ we ignore all non-flag bits from *flagp, so they don't matter. */
+ temp = (temp & ~excepts) | (*flagp & excepts);
+
+ _FPU_SETCW (temp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/mips/ftestexcept.c b/libm/mips/ftestexcept.c
new file mode 100644
index 000000000..8fdca7560
--- /dev/null
+++ b/libm/mips/ftestexcept.c
@@ -0,0 +1,30 @@
+/* Test exception in current environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fetestexcept (int excepts)
+{
+ int cw;
+
+ /* Get current control word. */
+ _FPU_GETCW (cw);
+
+ return cw & excepts & FE_ALL_EXCEPT;
+}
diff --git a/libm/or1k/Makefile.arch b/libm/or1k/Makefile.arch
new file mode 100644
index 000000000..bd38690be
--- /dev/null
+++ b/libm/or1k/Makefile.arch
@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)
diff --git a/libm/or1k/fclrexcpt.c b/libm/or1k/fclrexcpt.c
new file mode 100644
index 000000000..ecb327d72
--- /dev/null
+++ b/libm/or1k/fclrexcpt.c
@@ -0,0 +1,42 @@
+/* Clear given exceptions in current floating-point environment.
+ OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feclearexcept (int excepts)
+{
+ fpu_control_t cw;
+ fpu_control_t cw_new;
+
+ /* Mask out unsupported bits/exceptions. */
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Read the complete control word. */
+ _FPU_GETCW (cw);
+
+ cw_new = cw & ~excepts;
+
+ /* Put the new data in effect. */
+ if (cw != cw_new)
+ _FPU_SETCW (cw_new);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/or1k/fegetenv.c b/libm/or1k/fegetenv.c
new file mode 100644
index 000000000..7769d456f
--- /dev/null
+++ b/libm/or1k/fegetenv.c
@@ -0,0 +1,28 @@
+/* Store current floating-point environment.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetenv (fenv_t *envp)
+{
+ _FPU_GETCW (*envp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/or1k/fegetmode.c b/libm/or1k/fegetmode.c
new file mode 100644
index 000000000..40a789329
--- /dev/null
+++ b/libm/or1k/fegetmode.c
@@ -0,0 +1,28 @@
+/* Store current floating-point control modes. OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetmode (femode_t *modep)
+{
+ _FPU_GETCW (*modep);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/or1k/fegetround.c b/libm/or1k/fegetround.c
new file mode 100644
index 000000000..0965de2f9
--- /dev/null
+++ b/libm/or1k/fegetround.c
@@ -0,0 +1,25 @@
+/* Return current rounding direction. OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include "get-rounding-mode.h"
+
+int
+fegetround (void)
+{
+ return get_rounding_mode ();
+}
diff --git a/libm/or1k/feholdexcpt.c b/libm/or1k/feholdexcpt.c
new file mode 100644
index 000000000..cff06f3d0
--- /dev/null
+++ b/libm/or1k/feholdexcpt.c
@@ -0,0 +1,29 @@
+/* Store current floating-point environment and clear exceptions.
+ OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feholdexcept (fenv_t *envp)
+{
+ libc_feholdexcept_or1k (envp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/or1k/fenv_private.h b/libm/or1k/fenv_private.h
new file mode 100644
index 000000000..ede7d243a
--- /dev/null
+++ b/libm/or1k/fenv_private.h
@@ -0,0 +1,196 @@
+/* Private floating point rounding and exceptions handling. OpenRISC version.
+ Copyright (C) 2024-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 OR1K_FENV_PRIVATE_H
+#define OR1K_FENV_PRIVATE_H 1
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+static __always_inline void
+libc_feholdexcept_or1k (fenv_t *envp)
+{
+ fpu_control_t cw;
+ fpu_control_t cw_new;
+
+ /* Get and store the environment. */
+ _FPU_GETCW (cw);
+ *envp = cw;
+
+ /* Clear the exception status flags. */
+ cw_new = cw & ~FE_ALL_EXCEPT;
+
+ if (cw != cw_new)
+ _FPU_SETCW (cw_new);
+}
+
+#define libc_feholdexcept libc_feholdexcept_or1k
+#define libc_feholdexceptf libc_feholdexcept_or1k
+#define libc_feholdexceptl libc_feholdexcept_or1k
+
+static __always_inline void
+libc_fesetround_or1k (int round)
+{
+ fpu_control_t cw;
+ fpu_control_t cw_new;
+
+ _FPU_GETCW (cw);
+ cw_new = cw & ~_FPU_FPCSR_RM_MASK;
+ cw_new |= round;
+ if (cw != cw_new)
+ _FPU_SETCW (cw_new);
+}
+
+#define libc_fesetround libc_fesetround_or1k
+#define libc_fesetroundf libc_fesetround_or1k
+#define libc_fesetroundl libc_fesetround_or1k
+
+static __always_inline void
+libc_feholdexcept_setround_or1k (fenv_t *envp, int round)
+{
+ fpu_control_t cw;
+ fpu_control_t cw_new;
+
+ /* Get and store the environment. */
+ _FPU_GETCW (cw);
+ *envp = cw;
+
+ /* Clear the status flags and rounding mode. */
+ cw_new = cw & ~(FE_ALL_EXCEPT | _FPU_FPCSR_RM_MASK);
+
+ /* Set rounding mode. */
+ cw_new |= round;
+
+ if (cw != cw_new)
+ _FPU_SETCW (cw_new);
+}
+
+#define libc_feholdexcept_setround libc_feholdexcept_setround_or1k
+#define libc_feholdexcept_setroundf libc_feholdexcept_setround_or1k
+#define libc_feholdexcept_setroundl libc_feholdexcept_setround_or1k
+
+static __always_inline int
+libc_fetestexcept_or1k (int ex)
+{
+ fpu_control_t cw;
+
+ /* Get current control word. */
+ _FPU_GETCW (cw);
+
+ /* Check if any of the queried exception flags are set. */
+ return cw & ex & FE_ALL_EXCEPT;
+}
+
+#define libc_fetestexcept libc_fetestexcept_or1k
+#define libc_fetestexceptf libc_fetestexcept_or1k
+#define libc_fetestexceptl libc_fetestexcept_or1k
+
+static __always_inline void
+libc_fesetenv_or1k (const fenv_t *envp)
+{
+ if (envp == FE_DFL_ENV)
+ _FPU_SETCW (_FPU_DEFAULT);
+ else
+ _FPU_SETCW (*envp);
+}
+
+#define libc_fesetenv libc_fesetenv_or1k
+#define libc_fesetenvf libc_fesetenv_or1k
+#define libc_fesetenvl libc_fesetenv_or1k
+#define libc_feresetround_noex libc_fesetenv_or1k
+#define libc_feresetround_noexf libc_fesetenv_or1k
+#define libc_feresetround_noexl libc_fesetenv_or1k
+
+static __always_inline int
+libc_feupdateenv_test_or1k (const fenv_t *envp, int ex)
+{
+ fpu_control_t cw;
+ fpu_control_t cw_new;
+ int excepts;
+
+ /* Get current control word. */
+ _FPU_GETCW (cw);
+
+ /* Merge current exception flags with the passed fenv. */
+ excepts = cw & FE_ALL_EXCEPT;
+ cw_new = (envp == FE_DFL_ENV ? _FPU_DEFAULT : *envp) | excepts;
+
+ if (unlikely (cw != cw_new))
+ _FPU_SETCW (cw_new);
+
+ /* Raise the exceptions if enabled in the new FP state. */
+ if (unlikely (excepts))
+ feraiseexcept (excepts);
+
+ return excepts & ex;
+}
+
+#define libc_feupdateenv_test libc_feupdateenv_test_or1k
+#define libc_feupdateenv_testf libc_feupdateenv_test_or1k
+#define libc_feupdateenv_testl libc_feupdateenv_test_or1k
+
+static __always_inline void
+libc_feupdateenv_or1k (const fenv_t *envp)
+{
+ libc_feupdateenv_test_or1k (envp, 0);
+}
+
+#define libc_feupdateenv libc_feupdateenv_or1k
+#define libc_feupdateenvf libc_feupdateenv_or1k
+#define libc_feupdateenvl libc_feupdateenv_or1k
+
+static __always_inline void
+libc_feholdsetround_or1k (fenv_t *envp, int round)
+{
+ fpu_control_t cw;
+
+ _FPU_GETCW (cw);
+ *envp = cw;
+
+ /* Check whether rounding modes are different. */
+ round = (cw ^ round) & _FPU_FPCSR_RM_MASK;
+
+ /* Set new rounding mode if different. */
+ if (unlikely (round != 0))
+ _FPU_SETCW (cw ^ round);
+}
+
+#define libc_feholdsetround libc_feholdsetround_or1k
+#define libc_feholdsetroundf libc_feholdsetround_or1k
+#define libc_feholdsetroundl libc_feholdsetround_or1k
+
+static __always_inline void
+libc_feresetround_or1k (fenv_t *envp)
+{
+ fpu_control_t cw;
+ int round;
+
+ _FPU_GETCW (cw);
+
+ /* Check whether rounding modes are different. */
+ round = (*envp ^ cw) & _FPU_FPCSR_RM_MASK;
+
+ /* Restore the rounding mode if it was changed. */
+ if (unlikely (round != 0))
+ _FPU_SETCW (cw ^ round);
+}
+
+#define libc_feresetround libc_feresetround_or1k
+#define libc_feresetroundf libc_feresetround_or1k
+#define libc_feresetroundl libc_feresetround_or1k
+
+#endif
diff --git a/libm/or1k/fesetenv.c b/libm/or1k/fesetenv.c
new file mode 100644
index 000000000..a9c8448f4
--- /dev/null
+++ b/libm/or1k/fesetenv.c
@@ -0,0 +1,28 @@
+/* Install given floating-point environment. OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fesetenv (const fenv_t *envp)
+{
+ libc_fesetenv_or1k (envp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/or1k/fesetexcept.c b/libm/or1k/fesetexcept.c
new file mode 100644
index 000000000..abc5624c3
--- /dev/null
+++ b/libm/or1k/fesetexcept.c
@@ -0,0 +1,34 @@
+/* Set given exception flags. OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexcept (int excepts)
+{
+ fpu_control_t cw;
+ fpu_control_t cw_new;
+
+ _FPU_GETCW (cw);
+ cw_new = cw | (excepts & FE_ALL_EXCEPT);
+ if (cw != cw_new)
+ _FPU_SETCW (cw_new);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/or1k/fesetmode.c b/libm/or1k/fesetmode.c
new file mode 100644
index 000000000..74490621b
--- /dev/null
+++ b/libm/or1k/fesetmode.c
@@ -0,0 +1,38 @@
+/* Install given floating-point control modes. OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetmode (const femode_t *modep)
+{
+ fpu_control_t cw;
+ fpu_control_t cw_new;
+
+ _FPU_GETCW (cw);
+ cw_new = cw & ~_FPU_FPCSR_RM_MASK;
+ if (modep == FE_DFL_MODE)
+ cw_new |= (_FPU_DEFAULT & _FPU_FPCSR_RM_MASK);
+ else
+ cw_new |= (*modep & _FPU_FPCSR_RM_MASK);
+ if (cw != cw_new)
+ _FPU_SETCW (cw_new);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/or1k/fesetround.c b/libm/or1k/fesetround.c
new file mode 100644
index 000000000..37c2db4ab
--- /dev/null
+++ b/libm/or1k/fesetround.c
@@ -0,0 +1,35 @@
+/* Set current rounding direction. OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fesetround (int round)
+{
+ switch (round)
+ {
+ case FE_TONEAREST:
+ case FE_TOWARDZERO:
+ case FE_DOWNWARD:
+ case FE_UPWARD:
+ libc_fesetround_or1k (round);
+ return 0;
+ default:
+ return round; /* A nonzero value. */
+ }
+}
diff --git a/libm/or1k/feupdateenv.c b/libm/or1k/feupdateenv.c
new file mode 100644
index 000000000..b0f42744f
--- /dev/null
+++ b/libm/or1k/feupdateenv.c
@@ -0,0 +1,29 @@
+/* Install given floating-point environment and raise exceptions.
+ OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feupdateenv (const fenv_t *envp)
+{
+ libc_feupdateenv_or1k (envp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/or1k/fgetexcptflg.c b/libm/or1k/fgetexcptflg.c
new file mode 100644
index 000000000..2a725a4c7
--- /dev/null
+++ b/libm/or1k/fgetexcptflg.c
@@ -0,0 +1,28 @@
+/* Store current state of exceptions. OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ *flagp = libc_fetestexcept_or1k (excepts);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/or1k/fraiseexcpt.c b/libm/or1k/fraiseexcpt.c
new file mode 100644
index 000000000..31ceb830d
--- /dev/null
+++ b/libm/or1k/fraiseexcpt.c
@@ -0,0 +1,63 @@
+/* Raise given exceptions. OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include <float.h>
+#include <math.h>
+
+int
+feraiseexcept (int excepts)
+{
+ if (excepts == 0)
+ return 0;
+
+ /* Raise exceptions represented by EXPECTS. */
+
+ if (excepts & FE_INEXACT)
+ {
+ float d = 1.0, x = 3.0;
+ __asm__ volatile ("lf.div.s %0, %0, %1" : "+r" (d) : "r" (x));
+ }
+
+ if (excepts & FE_UNDERFLOW)
+ {
+ float d = FLT_MIN;
+ __asm__ volatile ("lf.mul.s %0, %0, %0" : "+r" (d));
+ }
+
+ if (excepts & FE_OVERFLOW)
+ {
+ float d = FLT_MAX;
+ __asm__ volatile ("lf.mul.s %0, %0, %0" : "+r" (d) : "r" (d));
+ }
+
+ if (excepts & FE_DIVBYZERO)
+ {
+ float d = 1.0, x = 0.0;
+ __asm__ volatile ("lf.div.s %0, %0, %1" : "+r" (d) : "r" (x));
+ }
+
+ if (excepts & FE_INVALID)
+ {
+ float d = HUGE_VAL, x = 0.0;
+ __asm__ volatile ("lf.mul.s %0, %1, %0" : "+r" (d) : "r" (x));
+ }
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/or1k/fsetexcptflg.c b/libm/or1k/fsetexcptflg.c
new file mode 100644
index 000000000..01c6e8635
--- /dev/null
+++ b/libm/or1k/fsetexcptflg.c
@@ -0,0 +1,42 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fpu_control_t cw;
+ fpu_control_t cw_new;
+
+ /* Get the current exceptions. */
+ _FPU_GETCW (cw);
+
+ /* Make sure the flags we want restored are legal. */
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Now set selected bits from flagp. Note that we ignore all non-flag
+ bits from *flagp, so they don't matter. */
+ cw_new = (cw & ~excepts) | (*flagp & excepts);
+
+ if (cw != cw_new)
+ _FPU_SETCW (cw_new);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/or1k/ftestexcept.c b/libm/or1k/ftestexcept.c
new file mode 100644
index 000000000..02ddf12c8
--- /dev/null
+++ b/libm/or1k/ftestexcept.c
@@ -0,0 +1,25 @@
+/* Test exception in current environment. OpenRISC version.
+ Copyright (C) 2024-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fetestexcept (int excepts)
+{
+ return libc_fetestexcept_or1k (excepts);
+}
diff --git a/libm/or1k/get-rounding-mode.h b/libm/or1k/get-rounding-mode.h
new file mode 100644
index 000000000..f65c4ecc0
--- /dev/null
+++ b/libm/or1k/get-rounding-mode.h
@@ -0,0 +1,36 @@
+/* Determine floating-point rounding mode within libc. OpenRISC version.
+
+ Copyright (C) 2024-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 _OR1K_GET_ROUNDING_MODE_H
+#define _OR1K_GET_ROUNDING_MODE_H 1
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+/* Return the floating-point rounding mode. */
+
+static inline int
+get_rounding_mode (void)
+{
+ fpu_control_t cw;
+
+ _FPU_GETCW (cw);
+ return cw & _FPU_FPCSR_RM_MASK;
+}
+
+#endif /* get-rounding-mode.h */
diff --git a/libm/riscv32/Makefile.arch b/libm/riscv32/Makefile.arch
new file mode 100644
index 000000000..bd38690be
--- /dev/null
+++ b/libm/riscv32/Makefile.arch
@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)
diff --git a/libm/riscv32/fclrexcpt.c b/libm/riscv32/fclrexcpt.c
new file mode 100644
index 000000000..849a910fc
--- /dev/null
+++ b/libm/riscv32/fclrexcpt.c
@@ -0,0 +1,26 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feclearexcept (int excepts)
+{
+ __asm__ volatile ("csrc fflags, %0" : : "r" (excepts));
+ return 0;
+}
diff --git a/libm/riscv32/fegetenv.c b/libm/riscv32/fegetenv.c
new file mode 100644
index 000000000..94f3444ac
--- /dev/null
+++ b/libm/riscv32/fegetenv.c
@@ -0,0 +1,28 @@
+/* Store current floating-point environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetenv (fenv_t *envp)
+{
+ _FPU_GETCW (*envp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/riscv32/fegetmode.c b/libm/riscv32/fegetmode.c
new file mode 100644
index 000000000..4b0ff270c
--- /dev/null
+++ b/libm/riscv32/fegetmode.c
@@ -0,0 +1,26 @@
+/* Store current floating-point control modes. RISC-V version.
+ Copyright (C) 2017-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetmode (femode_t *modep)
+{
+ _FPU_GETCW (*modep);
+ return 0;
+}
diff --git a/libm/riscv32/fegetround.c b/libm/riscv32/fegetround.c
new file mode 100644
index 000000000..abd13fc7f
--- /dev/null
+++ b/libm/riscv32/fegetround.c
@@ -0,0 +1,25 @@
+/* Return current rounding direction.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetround (void)
+{
+ return riscv_getround ();
+}
diff --git a/libm/riscv32/feholdexcpt.c b/libm/riscv32/feholdexcpt.c
new file mode 100644
index 000000000..5d95a08fe
--- /dev/null
+++ b/libm/riscv32/feholdexcpt.c
@@ -0,0 +1,26 @@
+/* Store current floating-point environment and clear exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feholdexcept (fenv_t *envp)
+{
+ libc_feholdexcept_riscv (envp);
+ return 0;
+}
diff --git a/libm/riscv32/fenv_private.h b/libm/riscv32/fenv_private.h
new file mode 100644
index 000000000..9eed4b614
--- /dev/null
+++ b/libm/riscv32/fenv_private.h
@@ -0,0 +1,156 @@
+/* Private floating point rounding and exceptions handling. RISC-V version.
+ Copyright (C) 2014-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 RISCV_FENV_PRIVATE_H
+#define RISCV_FENV_PRIVATE_H 1
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "get-rounding-mode.h"
+
+static __always_inline int
+riscv_getround (void)
+{
+ return get_rounding_mode ();
+}
+
+static __always_inline void
+riscv_setround (int rm)
+{
+ __asm__ volatile ("fsrm %z0" : : "rJ" (rm));
+}
+
+static __always_inline int
+riscv_getflags (void)
+{
+ int flags;
+ __asm__ volatile ("frflags %0" : "=r" (flags));
+ return flags;
+}
+
+static __always_inline void
+riscv_setflags (int flags)
+{
+ __asm__ volatile ("fsflags %z0" : : "rJ" (flags));
+}
+
+static __always_inline void
+libc_feholdexcept_riscv (fenv_t *envp)
+{
+ __asm__ volatile ("csrrc %0, fcsr, %1" : "=r" (*envp) : "i" (FE_ALL_EXCEPT));
+}
+
+#define libc_feholdexcept libc_feholdexcept_riscv
+#define libc_feholdexceptf libc_feholdexcept_riscv
+#define libc_feholdexceptl libc_feholdexcept_riscv
+
+static __always_inline void
+libc_fesetround_riscv (int round)
+{
+ riscv_setround (round);
+}
+
+#define libc_fesetround libc_fesetround_riscv
+#define libc_fesetroundf libc_fesetround_riscv
+#define libc_fesetroundl libc_fesetround_riscv
+
+static __always_inline void
+libc_feholdexcept_setround_riscv (fenv_t *envp, int round)
+{
+ libc_feholdexcept_riscv (envp);
+ libc_fesetround_riscv (round);
+}
+
+#define libc_feholdexcept_setround libc_feholdexcept_setround_riscv
+#define libc_feholdexcept_setroundf libc_feholdexcept_setround_riscv
+#define libc_feholdexcept_setroundl libc_feholdexcept_setround_riscv
+
+static __always_inline int
+libc_fetestexcept_riscv (int ex)
+{
+ return riscv_getflags () & ex;
+}
+
+#define libc_fetestexcept libc_fetestexcept_riscv
+#define libc_fetestexceptf libc_fetestexcept_riscv
+#define libc_fetestexceptl libc_fetestexcept_riscv
+
+static __always_inline void
+libc_fesetenv_riscv (const fenv_t *envp)
+{
+ long int env = (envp != FE_DFL_ENV ? *envp : 0);
+ _FPU_SETCW (env);
+}
+
+#define libc_fesetenv libc_fesetenv_riscv
+#define libc_fesetenvf libc_fesetenv_riscv
+#define libc_fesetenvl libc_fesetenv_riscv
+#define libc_feresetround_noex libc_fesetenv_riscv
+#define libc_feresetround_noexf libc_fesetenv_riscv
+#define libc_feresetround_noexl libc_fesetenv_riscv
+
+static __always_inline int
+libc_feupdateenv_test_riscv (const fenv_t *envp, int ex)
+{
+ fenv_t env = *envp;
+ int flags = riscv_getflags ();
+ __asm__ volatile ("csrw fcsr, %z0" : : "rJ" (env | flags));
+ return flags & ex;
+}
+
+#define libc_feupdateenv_test libc_feupdateenv_test_riscv
+#define libc_feupdateenv_testf libc_feupdateenv_test_riscv
+#define libc_feupdateenv_testl libc_feupdateenv_test_riscv
+
+static __always_inline void
+libc_feupdateenv_riscv (const fenv_t *envp)
+{
+ long int env = (envp != FE_DFL_ENV ? *envp : 0);
+ _FPU_SETCW (env | riscv_getflags ());
+}
+
+#define libc_feupdateenv libc_feupdateenv_riscv
+#define libc_feupdateenvf libc_feupdateenv_riscv
+#define libc_feupdateenvl libc_feupdateenv_riscv
+
+static __always_inline void
+libc_feholdsetround_riscv (fenv_t *envp, int round)
+{
+ /* Note this implementation makes an improperly-formatted fenv_t and
+ so should only be used in conjunction with libc_feresetround. */
+ int old_round;
+ __asm__ volatile ("csrrw %0, frm, %z1" : "=r" (old_round) : "rJ" (round));
+ *envp = old_round;
+}
+
+#define libc_feholdsetround libc_feholdsetround_riscv
+#define libc_feholdsetroundf libc_feholdsetround_riscv
+#define libc_feholdsetroundl libc_feholdsetround_riscv
+
+static __always_inline void
+libc_feresetround_riscv (fenv_t *envp)
+{
+ /* Note this implementation takes an improperly-formatted fenv_t and
+ so should only be used in conjunction with libc_feholdsetround. */
+ riscv_setround (*envp);
+}
+
+#define libc_feresetround libc_feresetround_riscv
+#define libc_feresetroundf libc_feresetround_riscv
+#define libc_feresetroundl libc_feresetround_riscv
+
+#endif
diff --git a/libm/riscv32/fesetenv.c b/libm/riscv32/fesetenv.c
new file mode 100644
index 000000000..8b7427c18
--- /dev/null
+++ b/libm/riscv32/fesetenv.c
@@ -0,0 +1,26 @@
+/* Install given floating-point environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fesetenv (const fenv_t *envp)
+{
+ libc_fesetenv_riscv (envp);
+ return 0;
+}
diff --git a/libm/riscv32/fesetexcept.c b/libm/riscv32/fesetexcept.c
new file mode 100644
index 000000000..9c931a1b7
--- /dev/null
+++ b/libm/riscv32/fesetexcept.c
@@ -0,0 +1,25 @@
+/* Set given exception flags. RISC-V version.
+ Copyright (C) 2017-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/>. */
+
+#include <fenv.h>
+
+int
+fesetexcept (int excepts)
+{
+ __asm__ volatile ("csrs fflags, %0" : : "r" (excepts));
+ return 0;
+}
diff --git a/libm/riscv32/fesetmode.c b/libm/riscv32/fesetmode.c
new file mode 100644
index 000000000..aaaf4480b
--- /dev/null
+++ b/libm/riscv32/fesetmode.c
@@ -0,0 +1,30 @@
+/* Install given floating-point control modes. RISC-V version.
+ Copyright (C) 2017-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetmode (const femode_t *modep)
+{
+ __asm__ volatile ("csrc fcsr, %0" : : "r" (~FE_ALL_EXCEPT));
+
+ if (modep != FE_DFL_MODE)
+ __asm__ volatile ("csrs fcsr, %0" : : "r" (*modep & ~FE_ALL_EXCEPT));
+
+ return 0;
+}
diff --git a/libm/riscv32/fesetround.c b/libm/riscv32/fesetround.c
new file mode 100644
index 000000000..a791751d1
--- /dev/null
+++ b/libm/riscv32/fesetround.c
@@ -0,0 +1,35 @@
+/* Set current rounding direction.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fesetround (int round)
+{
+ switch (round)
+ {
+ case FE_TONEAREST:
+ case FE_TOWARDZERO:
+ case FE_DOWNWARD:
+ case FE_UPWARD:
+ riscv_setround (round);
+ return 0;
+ default:
+ return round; /* A nonzero value. */
+ }
+}
diff --git a/libm/riscv32/feupdateenv.c b/libm/riscv32/feupdateenv.c
new file mode 100644
index 000000000..ea62bd1aa
--- /dev/null
+++ b/libm/riscv32/feupdateenv.c
@@ -0,0 +1,26 @@
+/* Install given floating-point environment and raise exceptions.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feupdateenv (const fenv_t *envp)
+{
+ libc_feupdateenv_riscv (envp);
+ return 0;
+}
diff --git a/libm/riscv32/fgetexcptflg.c b/libm/riscv32/fgetexcptflg.c
new file mode 100644
index 000000000..ecf513bed
--- /dev/null
+++ b/libm/riscv32/fgetexcptflg.c
@@ -0,0 +1,29 @@
+/* Store current representation for exceptions.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ /* Get the current exceptions. */
+ *flagp = riscv_getflags () & excepts;
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/riscv32/fraiseexcpt.c b/libm/riscv32/fraiseexcpt.c
new file mode 100644
index 000000000..f89f983d7
--- /dev/null
+++ b/libm/riscv32/fraiseexcpt.c
@@ -0,0 +1,26 @@
+/* Raise given exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feraiseexcept (int excepts)
+{
+ __asm__ volatile ("csrs fflags, %0" : : "r" (excepts));
+ return 0;
+}
diff --git a/libm/riscv32/fsetexcptflg.c b/libm/riscv32/fsetexcptflg.c
new file mode 100644
index 000000000..f295c18ab
--- /dev/null
+++ b/libm/riscv32/fsetexcptflg.c
@@ -0,0 +1,29 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fexcept_t flags = *flagp;
+ __asm__ volatile ("csrc fflags, %0" : : "r" (excepts));
+ __asm__ volatile ("csrs fflags, %0" : : "r" (flags & excepts));
+
+ return 0;
+}
diff --git a/libm/riscv32/ftestexcept.c b/libm/riscv32/ftestexcept.c
new file mode 100644
index 000000000..ed3a3e5e0
--- /dev/null
+++ b/libm/riscv32/ftestexcept.c
@@ -0,0 +1,25 @@
+/* Test exception in current environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fetestexcept (int excepts)
+{
+ return libc_fetestexcept_riscv (excepts);
+}
diff --git a/libm/riscv32/get-rounding-mode.h b/libm/riscv32/get-rounding-mode.h
new file mode 100644
index 000000000..7ab691ac8
--- /dev/null
+++ b/libm/riscv32/get-rounding-mode.h
@@ -0,0 +1,32 @@
+/* Determine floating-point rounding mode within libc. RISC-V version.
+ Copyright (C) 2015-2025 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _RISCV_GET_ROUNDING_MODE_H
+#define _RISCV_GET_ROUNDING_MODE_H
+
+/* Return the floating-point rounding mode. */
+
+static inline int
+get_rounding_mode (void)
+{
+ int rm;
+ __asm__ volatile ("frrm %0" : "=r" (rm));
+ return rm;
+}
+
+#endif /* get-rounding-mode.h */
diff --git a/libm/riscv64/Makefile.arch b/libm/riscv64/Makefile.arch
new file mode 100644
index 000000000..bd38690be
--- /dev/null
+++ b/libm/riscv64/Makefile.arch
@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)
diff --git a/libm/riscv64/fclrexcpt.c b/libm/riscv64/fclrexcpt.c
new file mode 100644
index 000000000..849a910fc
--- /dev/null
+++ b/libm/riscv64/fclrexcpt.c
@@ -0,0 +1,26 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feclearexcept (int excepts)
+{
+ __asm__ volatile ("csrc fflags, %0" : : "r" (excepts));
+ return 0;
+}
diff --git a/libm/riscv64/fegetenv.c b/libm/riscv64/fegetenv.c
new file mode 100644
index 000000000..94f3444ac
--- /dev/null
+++ b/libm/riscv64/fegetenv.c
@@ -0,0 +1,28 @@
+/* Store current floating-point environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetenv (fenv_t *envp)
+{
+ _FPU_GETCW (*envp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/riscv64/fegetmode.c b/libm/riscv64/fegetmode.c
new file mode 100644
index 000000000..4b0ff270c
--- /dev/null
+++ b/libm/riscv64/fegetmode.c
@@ -0,0 +1,26 @@
+/* Store current floating-point control modes. RISC-V version.
+ Copyright (C) 2017-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetmode (femode_t *modep)
+{
+ _FPU_GETCW (*modep);
+ return 0;
+}
diff --git a/libm/riscv64/fegetround.c b/libm/riscv64/fegetround.c
new file mode 100644
index 000000000..abd13fc7f
--- /dev/null
+++ b/libm/riscv64/fegetround.c
@@ -0,0 +1,25 @@
+/* Return current rounding direction.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetround (void)
+{
+ return riscv_getround ();
+}
diff --git a/libm/riscv64/feholdexcpt.c b/libm/riscv64/feholdexcpt.c
new file mode 100644
index 000000000..5d95a08fe
--- /dev/null
+++ b/libm/riscv64/feholdexcpt.c
@@ -0,0 +1,26 @@
+/* Store current floating-point environment and clear exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feholdexcept (fenv_t *envp)
+{
+ libc_feholdexcept_riscv (envp);
+ return 0;
+}
diff --git a/libm/riscv64/fenv_private.h b/libm/riscv64/fenv_private.h
new file mode 100644
index 000000000..9eed4b614
--- /dev/null
+++ b/libm/riscv64/fenv_private.h
@@ -0,0 +1,156 @@
+/* Private floating point rounding and exceptions handling. RISC-V version.
+ Copyright (C) 2014-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 RISCV_FENV_PRIVATE_H
+#define RISCV_FENV_PRIVATE_H 1
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "get-rounding-mode.h"
+
+static __always_inline int
+riscv_getround (void)
+{
+ return get_rounding_mode ();
+}
+
+static __always_inline void
+riscv_setround (int rm)
+{
+ __asm__ volatile ("fsrm %z0" : : "rJ" (rm));
+}
+
+static __always_inline int
+riscv_getflags (void)
+{
+ int flags;
+ __asm__ volatile ("frflags %0" : "=r" (flags));
+ return flags;
+}
+
+static __always_inline void
+riscv_setflags (int flags)
+{
+ __asm__ volatile ("fsflags %z0" : : "rJ" (flags));
+}
+
+static __always_inline void
+libc_feholdexcept_riscv (fenv_t *envp)
+{
+ __asm__ volatile ("csrrc %0, fcsr, %1" : "=r" (*envp) : "i" (FE_ALL_EXCEPT));
+}
+
+#define libc_feholdexcept libc_feholdexcept_riscv
+#define libc_feholdexceptf libc_feholdexcept_riscv
+#define libc_feholdexceptl libc_feholdexcept_riscv
+
+static __always_inline void
+libc_fesetround_riscv (int round)
+{
+ riscv_setround (round);
+}
+
+#define libc_fesetround libc_fesetround_riscv
+#define libc_fesetroundf libc_fesetround_riscv
+#define libc_fesetroundl libc_fesetround_riscv
+
+static __always_inline void
+libc_feholdexcept_setround_riscv (fenv_t *envp, int round)
+{
+ libc_feholdexcept_riscv (envp);
+ libc_fesetround_riscv (round);
+}
+
+#define libc_feholdexcept_setround libc_feholdexcept_setround_riscv
+#define libc_feholdexcept_setroundf libc_feholdexcept_setround_riscv
+#define libc_feholdexcept_setroundl libc_feholdexcept_setround_riscv
+
+static __always_inline int
+libc_fetestexcept_riscv (int ex)
+{
+ return riscv_getflags () & ex;
+}
+
+#define libc_fetestexcept libc_fetestexcept_riscv
+#define libc_fetestexceptf libc_fetestexcept_riscv
+#define libc_fetestexceptl libc_fetestexcept_riscv
+
+static __always_inline void
+libc_fesetenv_riscv (const fenv_t *envp)
+{
+ long int env = (envp != FE_DFL_ENV ? *envp : 0);
+ _FPU_SETCW (env);
+}
+
+#define libc_fesetenv libc_fesetenv_riscv
+#define libc_fesetenvf libc_fesetenv_riscv
+#define libc_fesetenvl libc_fesetenv_riscv
+#define libc_feresetround_noex libc_fesetenv_riscv
+#define libc_feresetround_noexf libc_fesetenv_riscv
+#define libc_feresetround_noexl libc_fesetenv_riscv
+
+static __always_inline int
+libc_feupdateenv_test_riscv (const fenv_t *envp, int ex)
+{
+ fenv_t env = *envp;
+ int flags = riscv_getflags ();
+ __asm__ volatile ("csrw fcsr, %z0" : : "rJ" (env | flags));
+ return flags & ex;
+}
+
+#define libc_feupdateenv_test libc_feupdateenv_test_riscv
+#define libc_feupdateenv_testf libc_feupdateenv_test_riscv
+#define libc_feupdateenv_testl libc_feupdateenv_test_riscv
+
+static __always_inline void
+libc_feupdateenv_riscv (const fenv_t *envp)
+{
+ long int env = (envp != FE_DFL_ENV ? *envp : 0);
+ _FPU_SETCW (env | riscv_getflags ());
+}
+
+#define libc_feupdateenv libc_feupdateenv_riscv
+#define libc_feupdateenvf libc_feupdateenv_riscv
+#define libc_feupdateenvl libc_feupdateenv_riscv
+
+static __always_inline void
+libc_feholdsetround_riscv (fenv_t *envp, int round)
+{
+ /* Note this implementation makes an improperly-formatted fenv_t and
+ so should only be used in conjunction with libc_feresetround. */
+ int old_round;
+ __asm__ volatile ("csrrw %0, frm, %z1" : "=r" (old_round) : "rJ" (round));
+ *envp = old_round;
+}
+
+#define libc_feholdsetround libc_feholdsetround_riscv
+#define libc_feholdsetroundf libc_feholdsetround_riscv
+#define libc_feholdsetroundl libc_feholdsetround_riscv
+
+static __always_inline void
+libc_feresetround_riscv (fenv_t *envp)
+{
+ /* Note this implementation takes an improperly-formatted fenv_t and
+ so should only be used in conjunction with libc_feholdsetround. */
+ riscv_setround (*envp);
+}
+
+#define libc_feresetround libc_feresetround_riscv
+#define libc_feresetroundf libc_feresetround_riscv
+#define libc_feresetroundl libc_feresetround_riscv
+
+#endif
diff --git a/libm/riscv64/fesetenv.c b/libm/riscv64/fesetenv.c
new file mode 100644
index 000000000..8b7427c18
--- /dev/null
+++ b/libm/riscv64/fesetenv.c
@@ -0,0 +1,26 @@
+/* Install given floating-point environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fesetenv (const fenv_t *envp)
+{
+ libc_fesetenv_riscv (envp);
+ return 0;
+}
diff --git a/libm/riscv64/fesetexcept.c b/libm/riscv64/fesetexcept.c
new file mode 100644
index 000000000..9c931a1b7
--- /dev/null
+++ b/libm/riscv64/fesetexcept.c
@@ -0,0 +1,25 @@
+/* Set given exception flags. RISC-V version.
+ Copyright (C) 2017-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/>. */
+
+#include <fenv.h>
+
+int
+fesetexcept (int excepts)
+{
+ __asm__ volatile ("csrs fflags, %0" : : "r" (excepts));
+ return 0;
+}
diff --git a/libm/riscv64/fesetmode.c b/libm/riscv64/fesetmode.c
new file mode 100644
index 000000000..aaaf4480b
--- /dev/null
+++ b/libm/riscv64/fesetmode.c
@@ -0,0 +1,30 @@
+/* Install given floating-point control modes. RISC-V version.
+ Copyright (C) 2017-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetmode (const femode_t *modep)
+{
+ __asm__ volatile ("csrc fcsr, %0" : : "r" (~FE_ALL_EXCEPT));
+
+ if (modep != FE_DFL_MODE)
+ __asm__ volatile ("csrs fcsr, %0" : : "r" (*modep & ~FE_ALL_EXCEPT));
+
+ return 0;
+}
diff --git a/libm/riscv64/fesetround.c b/libm/riscv64/fesetround.c
new file mode 100644
index 000000000..a791751d1
--- /dev/null
+++ b/libm/riscv64/fesetround.c
@@ -0,0 +1,35 @@
+/* Set current rounding direction.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fesetround (int round)
+{
+ switch (round)
+ {
+ case FE_TONEAREST:
+ case FE_TOWARDZERO:
+ case FE_DOWNWARD:
+ case FE_UPWARD:
+ riscv_setround (round);
+ return 0;
+ default:
+ return round; /* A nonzero value. */
+ }
+}
diff --git a/libm/riscv64/feupdateenv.c b/libm/riscv64/feupdateenv.c
new file mode 100644
index 000000000..ea62bd1aa
--- /dev/null
+++ b/libm/riscv64/feupdateenv.c
@@ -0,0 +1,26 @@
+/* Install given floating-point environment and raise exceptions.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feupdateenv (const fenv_t *envp)
+{
+ libc_feupdateenv_riscv (envp);
+ return 0;
+}
diff --git a/libm/riscv64/fgetexcptflg.c b/libm/riscv64/fgetexcptflg.c
new file mode 100644
index 000000000..ecf513bed
--- /dev/null
+++ b/libm/riscv64/fgetexcptflg.c
@@ -0,0 +1,29 @@
+/* Store current representation for exceptions.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ /* Get the current exceptions. */
+ *flagp = riscv_getflags () & excepts;
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/riscv64/fraiseexcpt.c b/libm/riscv64/fraiseexcpt.c
new file mode 100644
index 000000000..f89f983d7
--- /dev/null
+++ b/libm/riscv64/fraiseexcpt.c
@@ -0,0 +1,26 @@
+/* Raise given exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feraiseexcept (int excepts)
+{
+ __asm__ volatile ("csrs fflags, %0" : : "r" (excepts));
+ return 0;
+}
diff --git a/libm/riscv64/fsetexcptflg.c b/libm/riscv64/fsetexcptflg.c
new file mode 100644
index 000000000..f295c18ab
--- /dev/null
+++ b/libm/riscv64/fsetexcptflg.c
@@ -0,0 +1,29 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fexcept_t flags = *flagp;
+ __asm__ volatile ("csrc fflags, %0" : : "r" (excepts));
+ __asm__ volatile ("csrs fflags, %0" : : "r" (flags & excepts));
+
+ return 0;
+}
diff --git a/libm/riscv64/ftestexcept.c b/libm/riscv64/ftestexcept.c
new file mode 100644
index 000000000..ed3a3e5e0
--- /dev/null
+++ b/libm/riscv64/ftestexcept.c
@@ -0,0 +1,25 @@
+/* Test exception in current environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fetestexcept (int excepts)
+{
+ return libc_fetestexcept_riscv (excepts);
+}
diff --git a/libm/riscv64/get-rounding-mode.h b/libm/riscv64/get-rounding-mode.h
new file mode 100644
index 000000000..7ab691ac8
--- /dev/null
+++ b/libm/riscv64/get-rounding-mode.h
@@ -0,0 +1,32 @@
+/* Determine floating-point rounding mode within libc. RISC-V version.
+ Copyright (C) 2015-2025 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _RISCV_GET_ROUNDING_MODE_H
+#define _RISCV_GET_ROUNDING_MODE_H
+
+/* Return the floating-point rounding mode. */
+
+static inline int
+get_rounding_mode (void)
+{
+ int rm;
+ __asm__ volatile ("frrm %0" : "=r" (rm));
+ return rm;
+}
+
+#endif /* get-rounding-mode.h */
diff --git a/libm/sh/sh4/Makefile.arch b/libm/sh/sh4/Makefile.arch
index e38e99c15..69996edda 100644
--- a/libm/sh/sh4/Makefile.arch
+++ b/libm/sh/sh4/Makefile.arch
@@ -8,7 +8,7 @@
ifeq ($(UCLIBC_HAS_FENV),y)
libm_ARCH_CSRC:=$(wildcard $(libm_SUBARCH_DIR)/*.c)
-libm_ARCH_COBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.c,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_SRC))
+libm_ARCH_COBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.c,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_CSRC))
libm_ARCH_SSRC:=$(wildcard $(libm_SUBARCH_DIR)/*.S)
libm_ARCH_SOBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.S,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_SSRC))
endif
diff --git a/libm/sh/sh4/fclrexcpt.c b/libm/sh/sh4/fclrexcpt.c
new file mode 100644
index 000000000..286b4f36a
--- /dev/null
+++ b/libm/sh/sh4/fclrexcpt.c
@@ -0,0 +1,39 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feclearexcept (int excepts)
+{
+ fpu_control_t cw;
+
+ /* Mask out unsupported bits/exceptions. */
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Read the complete control word. */
+ _FPU_GETCW (cw);
+
+ /* Clear exception bits. */
+ cw &= ~excepts;
+
+ /* Put the new data in effect. */
+ _FPU_SETCW (cw);
+
+ return 0;
+}
diff --git a/libm/sh/sh4/fedisblxcpt.c b/libm/sh/sh4/fedisblxcpt.c
new file mode 100644
index 000000000..69f9ff2c4
--- /dev/null
+++ b/libm/sh/sh4/fedisblxcpt.c
@@ -0,0 +1,37 @@
+/* Disable floating-point exceptions.
+ Copyright (C) 2012-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fedisableexcept (int excepts)
+{
+ fpu_control_t temp, old_exc;
+
+ /* Get the current control register contents. */
+ _FPU_GETCW (temp);
+
+ old_exc = (temp >> 5) & FE_ALL_EXCEPT;
+
+ excepts &= FE_ALL_EXCEPT;
+
+ temp &= ~(excepts << 5);
+ _FPU_SETCW (temp);
+
+ return old_exc;
+}
diff --git a/libm/sh/sh4/feenablxcpt.c b/libm/sh/sh4/feenablxcpt.c
new file mode 100644
index 000000000..bf2b01f0b
--- /dev/null
+++ b/libm/sh/sh4/feenablxcpt.c
@@ -0,0 +1,36 @@
+/* Enable floating-point exceptions.
+ Copyright (C) 2012-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feenableexcept (int excepts)
+{
+ fpu_control_t temp, old_flag;
+
+ /* Get current exceptions. */
+ _FPU_GETCW (temp);
+
+ old_flag = (temp >> 5) & FE_ALL_EXCEPT;
+ excepts &= FE_ALL_EXCEPT;
+
+ temp |= excepts << 5;
+ _FPU_SETCW (temp);
+
+ return old_flag;
+}
diff --git a/libm/sh/sh4/fegetenv.c b/libm/sh/sh4/fegetenv.c
new file mode 100644
index 000000000..d76964f8b
--- /dev/null
+++ b/libm/sh/sh4/fegetenv.c
@@ -0,0 +1,30 @@
+/* Store current floating-point environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetenv (fenv_t *envp)
+{
+ fpu_control_t temp;
+ _FPU_GETCW (temp);
+
+ envp->__fpscr = temp;
+
+ return 0;
+}
diff --git a/libm/sh/sh4/fegetexcept.c b/libm/sh/sh4/fegetexcept.c
new file mode 100644
index 000000000..85f783520
--- /dev/null
+++ b/libm/sh/sh4/fegetexcept.c
@@ -0,0 +1,30 @@
+/* Get enabled floating-point exceptions.
+ Copyright (C) 2012-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetexcept (void)
+{
+ fpu_control_t temp;
+
+ /* Get current exceptions. */
+ _FPU_GETCW (temp);
+
+ return (temp >> 5) & FE_ALL_EXCEPT;
+}
diff --git a/libm/sh/sh4/fegetmode.c b/libm/sh/sh4/fegetmode.c
new file mode 100644
index 000000000..16deb5183
--- /dev/null
+++ b/libm/sh/sh4/fegetmode.c
@@ -0,0 +1,26 @@
+/* Store current floating-point control modes. SH4 version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetmode (femode_t *modep)
+{
+ _FPU_GETCW (*modep);
+ return 0;
+}
diff --git a/libm/sh/sh4/fegetround.c b/libm/sh/sh4/fegetround.c
new file mode 100644
index 000000000..b7c26eb6f
--- /dev/null
+++ b/libm/sh/sh4/fegetround.c
@@ -0,0 +1,30 @@
+/* Return current rounding direction.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetround (void)
+{
+ fpu_control_t cw;
+
+ /* Get control word. */
+ _FPU_GETCW (cw);
+
+ return cw & 0x1;
+}
diff --git a/libm/sh/sh4/feholdexcpt.c b/libm/sh/sh4/feholdexcpt.c
index 70b51e8dd..fc462b403 100644
--- a/libm/sh/sh4/feholdexcpt.c
+++ b/libm/sh/sh4/feholdexcpt.c
@@ -1,13 +1,19 @@
-/*
- *
- * Copyright (c) 2007 STMicroelectronics Ltd
- * Filippo Arcidiacono (filippo.arcidiacono@st.com)
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- *
- * Taken from glibc 2.6
- *
- */
+/* Store current floating-point environment and clear exceptions.
+ Copyright (C) 1997-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/>. */
#include <fenv.h>
#include <fpu_control.h>
@@ -15,15 +21,20 @@
int
feholdexcept (fenv_t *envp)
{
- unsigned long int temp;
+ fpu_control_t temp;
/* Store the environment. */
_FPU_GETCW (temp);
envp->__fpscr = temp;
- /* Now set all exceptions to non-stop. */
+ /* Clear the status flags. */
temp &= ~FE_ALL_EXCEPT;
+
+ /* Now set all exceptions to non-stop. */
+ temp &= ~(FE_ALL_EXCEPT << 5);
+
_FPU_SETCW (temp);
- return 1;
+ /* Success. */
+ return 0;
}
diff --git a/libm/sh/sh4/fesetenv.c b/libm/sh/sh4/fesetenv.c
index c5cfc1d51..6a9a68090 100644
--- a/libm/sh/sh4/fesetenv.c
+++ b/libm/sh/sh4/fesetenv.c
@@ -1,13 +1,19 @@
-/*
- *
- * Copyright (c) 2007 STMicroelectronics Ltd
- * Filippo Arcidiacono (filippo.arcidiacono@st.com)
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- *
- * Taken from glibc 2.6
- *
- */
+/* Install given floating-point environment.
+ Copyright (C) 1997-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/>. */
#include <fenv.h>
#include <fpu_control.h>
@@ -19,7 +25,7 @@ fesetenv (const fenv_t *envp)
_FPU_SETCW (_FPU_DEFAULT);
else
{
- unsigned long int temp = envp->__fpscr;
+ fpu_control_t temp = envp->__fpscr;
_FPU_SETCW (temp);
}
return 0;
diff --git a/libm/sh/sh4/fesetexcept.c b/libm/sh/sh4/fesetexcept.c
new file mode 100644
index 000000000..eceb0bb4f
--- /dev/null
+++ b/libm/sh/sh4/fesetexcept.c
@@ -0,0 +1,31 @@
+/* Set given exception flags. SH4 version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexcept (int excepts)
+{
+ fpu_control_t temp;
+
+ _FPU_GETCW (temp);
+ temp |= (excepts & FE_ALL_EXCEPT);
+ _FPU_SETCW (temp);
+
+ return 0;
+}
diff --git a/libm/sh/sh4/fesetmode.c b/libm/sh/sh4/fesetmode.c
new file mode 100644
index 000000000..073da0984
--- /dev/null
+++ b/libm/sh/sh4/fesetmode.c
@@ -0,0 +1,37 @@
+/* Install given floating-point control modes. SH4 version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+#define FPU_STATUS 0x3f07c
+
+int
+fesetmode (const femode_t *modep)
+{
+ fpu_control_t fpscr;
+
+ _FPU_GETCW (fpscr);
+ fpscr &= FPU_STATUS;
+ if (modep == FE_DFL_MODE)
+ fpscr |= _FPU_DEFAULT;
+ else
+ fpscr |= *modep & ~FPU_STATUS;
+ _FPU_SETCW (fpscr);
+
+ return 0;
+}
diff --git a/libm/sh/sh4/fesetround.c b/libm/sh/sh4/fesetround.c
new file mode 100644
index 000000000..144eca86f
--- /dev/null
+++ b/libm/sh/sh4/fesetround.c
@@ -0,0 +1,40 @@
+/* Set current rounding direction.
+ Copyright (C) 1998-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetround (int round)
+{
+ fpu_control_t cw;
+
+ if ((round & ~0x1) != 0)
+ /* ROUND is no valid rounding mode. */
+ return 1;
+
+ /* Get current state. */
+ _FPU_GETCW (cw);
+
+ /* Set rounding bits. */
+ cw &= ~0x1;
+ cw |= round;
+ /* Set new state. */
+ _FPU_SETCW (cw);
+
+ return 0;
+}
diff --git a/libm/sh/sh4/feupdateenv.c b/libm/sh/sh4/feupdateenv.c
new file mode 100644
index 000000000..cb7e95259
--- /dev/null
+++ b/libm/sh/sh4/feupdateenv.c
@@ -0,0 +1,36 @@
+/* Install given floating-point environment and raise exceptions.
+ Copyright (C) 2012-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feupdateenv (const fenv_t *envp)
+{
+ fpu_control_t temp;
+
+ _FPU_GETCW (temp);
+ temp = (temp & FE_ALL_EXCEPT);
+
+ /* Raise the saved exception. Incidentally for us the implementation
+ defined format of the values in objects of type fexcept_t is the
+ same as the ones specified using the FE_* constants. */
+ fesetenv (envp);
+ feraiseexcept ((int) temp);
+
+ return 0;
+}
diff --git a/libm/sh/sh4/fgetexcptflg.c b/libm/sh/sh4/fgetexcptflg.c
new file mode 100644
index 000000000..308b5ad44
--- /dev/null
+++ b/libm/sh/sh4/fgetexcptflg.c
@@ -0,0 +1,37 @@
+/* Store current representation for exceptions.
+ Copyright (C) 2013-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ fpu_control_t temp;
+
+ /* Get the current exceptions. */
+ _FPU_GETCW (temp);
+
+ /* We only save the relevant bits here. In particular, care has to be
+ taken with the CAUSE bits, as an inadvertent restore later on could
+ generate unexpected exceptions. */
+
+ *flagp = temp & excepts & FE_ALL_EXCEPT;
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/sh/sh4/fraiseexcpt.c b/libm/sh/sh4/fraiseexcpt.c
new file mode 100644
index 000000000..1ed495b7a
--- /dev/null
+++ b/libm/sh/sh4/fraiseexcpt.c
@@ -0,0 +1,70 @@
+/* Raise given exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <float.h>
+#include <fpu_control.h>
+#include <math.h>
+
+int
+feraiseexcept (int excepts)
+{
+ if (excepts == 0)
+ return 0;
+
+ /* Raise exceptions represented by EXPECTS. */
+
+ if (excepts & FE_INEXACT)
+ {
+ double d = 1.0, x = 3.0;
+ __asm__ __volatile__ ("fdiv %1, %0" : "+d" (d) : "d" (x));
+ }
+
+ if (excepts & FE_UNDERFLOW)
+ {
+ long double d = LDBL_MIN, x = 10;
+ __asm__ __volatile__ ("fdiv %1, %0" : "+d" (d) : "d" (x));
+ }
+
+ if (excepts & FE_OVERFLOW)
+ {
+ long double d = LDBL_MAX;
+ __asm__ __volatile__ ("fmul %0, %0" : "+d" (d) : "d" (d));
+ }
+
+ if (excepts & FE_DIVBYZERO)
+ {
+ double d = 1.0, x = 0.0;
+ __asm__ __volatile__ ("fdiv %1, %0" : "+d" (d) : "d" (x));
+ }
+
+ if (excepts & FE_INVALID)
+ {
+ double d = HUGE_VAL, x = 0.0;
+ __asm__ __volatile__ ("fmul %1, %0" : "+d" (d) : "d" (x));
+ }
+
+ {
+ /* Restore flag fields. */
+ fpu_control_t cw;
+ _FPU_GETCW (cw);
+ cw |= (excepts & FE_ALL_EXCEPT);
+ _FPU_SETCW (cw);
+ }
+
+ return 0;
+}
diff --git a/libm/sh/sh4/fsetexcptflg.c b/libm/sh/sh4/fsetexcptflg.c
new file mode 100644
index 000000000..8fcb94973
--- /dev/null
+++ b/libm/sh/sh4/fsetexcptflg.c
@@ -0,0 +1,38 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <math.h>
+#include <fpu_control.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fpu_control_t temp;
+
+ /* Get the current environment. */
+ _FPU_GETCW (temp);
+
+ /* Set the desired exception mask. */
+ temp &= ~(excepts & FE_ALL_EXCEPT);
+ temp |= (*flagp & excepts & FE_ALL_EXCEPT);
+
+ /* Save state back to the FPU. */
+ _FPU_SETCW (temp);
+
+ return 0;
+}
diff --git a/libm/sh/sh4/ftestexcept.c b/libm/sh/sh4/ftestexcept.c
new file mode 100644
index 000000000..edc523426
--- /dev/null
+++ b/libm/sh/sh4/ftestexcept.c
@@ -0,0 +1,30 @@
+/* Test exception in current environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fetestexcept (int excepts)
+{
+ fpu_control_t temp;
+
+ /* Get current exceptions. */
+ _FPU_GETCW (temp);
+
+ return temp & excepts & FE_ALL_EXCEPT;
+}
diff --git a/libm/sparc/Makefile.arch b/libm/sparc/Makefile.arch
new file mode 100644
index 000000000..bd38690be
--- /dev/null
+++ b/libm/sparc/Makefile.arch
@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)
diff --git a/libm/sparc/fclrexcpt.c b/libm/sparc/fclrexcpt.c
new file mode 100644
index 000000000..ae344658d
--- /dev/null
+++ b/libm/sparc/fclrexcpt.c
@@ -0,0 +1,34 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feclearexcept (int excepts)
+{
+ fenv_t tmp;
+
+ __fenv_stfsr (tmp);
+
+ tmp &= ~(excepts & FE_ALL_EXCEPT);
+
+ __fenv_ldfsr (tmp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/sparc/fedisblxcpt.c b/libm/sparc/fedisblxcpt.c
new file mode 100644
index 000000000..9bc546f2d
--- /dev/null
+++ b/libm/sparc/fedisblxcpt.c
@@ -0,0 +1,34 @@
+/* Disable floating-point exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fedisableexcept (int excepts)
+{
+ fenv_t new_exc, old_exc;
+
+ __fenv_stfsr (new_exc);
+
+ old_exc = (new_exc >> 18) & FE_ALL_EXCEPT;
+ new_exc &= ~(((fenv_t)excepts & FE_ALL_EXCEPT) << 18);
+
+ __fenv_ldfsr (new_exc);
+
+ return old_exc;
+}
diff --git a/libm/sparc/feenablxcpt.c b/libm/sparc/feenablxcpt.c
new file mode 100644
index 000000000..ab88e7e42
--- /dev/null
+++ b/libm/sparc/feenablxcpt.c
@@ -0,0 +1,34 @@
+/* Enable floating-point exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feenableexcept (int excepts)
+{
+ fenv_t new_exc, old_exc;
+
+ __fenv_stfsr (new_exc);
+
+ old_exc = (new_exc >> 18) & FE_ALL_EXCEPT;
+ new_exc |= (((fenv_t)excepts & FE_ALL_EXCEPT) << 18);
+
+ __fenv_ldfsr (new_exc);
+
+ return old_exc;
+}
diff --git a/libm/sparc/fegetenv.c b/libm/sparc/fegetenv.c
new file mode 100644
index 000000000..883012932
--- /dev/null
+++ b/libm/sparc/fegetenv.c
@@ -0,0 +1,28 @@
+/* Store current floating-point environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetenv (fenv_t *envp)
+{
+ __fenv_stfsr (*envp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/sparc/fegetexcept.c b/libm/sparc/fegetexcept.c
new file mode 100644
index 000000000..53dfdab8c
--- /dev/null
+++ b/libm/sparc/fegetexcept.c
@@ -0,0 +1,28 @@
+/* Get enabled floating-point exceptions.
+ Copyright (C) 2000-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetexcept (void)
+{
+ fenv_t exc;
+ __fenv_stfsr (exc);
+
+ return (exc >> 18) & FE_ALL_EXCEPT;
+}
diff --git a/libm/sparc/fegetmode.c b/libm/sparc/fegetmode.c
new file mode 100644
index 000000000..0bb9ba111
--- /dev/null
+++ b/libm/sparc/fegetmode.c
@@ -0,0 +1,26 @@
+/* Store current floating-point control modes. SPARC version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetmode (femode_t *modep)
+{
+ __fenv_stfsr (*modep);
+ return 0;
+}
diff --git a/libm/sparc/fegetround.c b/libm/sparc/fegetround.c
new file mode 100644
index 000000000..bb53a735e
--- /dev/null
+++ b/libm/sparc/fegetround.c
@@ -0,0 +1,29 @@
+/* Return current rounding direction.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetround (void)
+{
+ fenv_t tmp;
+
+ __fenv_stfsr (tmp);
+
+ return tmp & __FE_ROUND_MASK;
+}
diff --git a/libm/sparc/feholdexcpt.c b/libm/sparc/feholdexcpt.c
new file mode 100644
index 000000000..7d712198b
--- /dev/null
+++ b/libm/sparc/feholdexcpt.c
@@ -0,0 +1,34 @@
+/* Store current floating-point environment and clear exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feholdexcept (fenv_t *envp)
+{
+ fenv_t tmp;
+
+ __fenv_stfsr (*envp);
+
+ /* Set all exceptions to non-stop and clear all exceptions. */
+ tmp = *envp & ~((0x1f << 23) | FE_ALL_EXCEPT);
+
+ __fenv_ldfsr (tmp);
+
+ return 0;
+}
diff --git a/libm/sparc/fenv_private.h b/libm/sparc/fenv_private.h
new file mode 100644
index 000000000..b888d8442
--- /dev/null
+++ b/libm/sparc/fenv_private.h
@@ -0,0 +1,187 @@
+#ifndef SPARC_FENV_PRIVATE_H
+#define SPARC_FENV_PRIVATE_H 1
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+/* For internal use only: access the fp state register. */
+#define __fenv_stfsr(X) _FPU_GETCW (X)
+#define __fenv_ldfsr(X) _FPU_SETCW (X)
+
+static __always_inline void
+libc_feholdexcept (fenv_t *e)
+{
+ fenv_t etmp;
+ __fenv_stfsr(etmp);
+ *(e) = etmp;
+ etmp = etmp & ~((0x1f << 23) | FE_ALL_EXCEPT);
+ __fenv_ldfsr(etmp);
+}
+
+static __always_inline void
+libc_fesetround (int r)
+{
+ fenv_t etmp;
+ __fenv_stfsr(etmp);
+ etmp = (etmp & ~__FE_ROUND_MASK) | (r);
+ __fenv_ldfsr(etmp);
+}
+
+static __always_inline void
+libc_feholdexcept_setround (fenv_t *e, int r)
+{
+ fenv_t etmp;
+ __fenv_stfsr(etmp);
+ *(e) = etmp;
+ etmp = etmp & ~((0x1f << 23) | FE_ALL_EXCEPT);
+ etmp = (etmp & ~__FE_ROUND_MASK) | (r);
+ __fenv_ldfsr(etmp);
+}
+
+static __always_inline int
+libc_fetestexcept (int e)
+{
+ fenv_t etmp;
+ __fenv_stfsr(etmp);
+ return etmp & (e) & FE_ALL_EXCEPT;
+}
+
+static __always_inline void
+libc_fesetenv (fenv_t *e)
+{
+ __fenv_ldfsr(*e);
+}
+
+static __always_inline int
+libc_feupdateenv_test (fenv_t *e, int ex)
+{
+ fenv_t etmp;
+
+ __fenv_stfsr(etmp);
+ etmp &= FE_ALL_EXCEPT;
+
+ __fenv_ldfsr(*e);
+
+ feraiseexcept (etmp);
+
+ return etmp & ex;
+}
+
+static __always_inline void
+libc_feupdateenv (fenv_t *e)
+{
+ libc_feupdateenv_test (e, 0);
+}
+
+static __always_inline void
+libc_feholdsetround (fenv_t *e, int r)
+{
+ fenv_t etmp;
+ __fenv_stfsr(etmp);
+ *(e) = etmp;
+ etmp = (etmp & ~__FE_ROUND_MASK) | (r);
+ __fenv_ldfsr(etmp);
+}
+
+static __always_inline void
+libc_feresetround (fenv_t *e)
+{
+ fenv_t etmp;
+ __fenv_stfsr(etmp);
+ etmp = (etmp & ~__FE_ROUND_MASK) | (*e & __FE_ROUND_MASK);
+ __fenv_ldfsr(etmp);
+}
+
+#define libc_feholdexceptf libc_feholdexcept
+#define libc_fesetroundf libc_fesetround
+#define libc_feholdexcept_setroundf libc_feholdexcept_setround
+#define libc_fetestexceptf libc_fetestexcept
+#define libc_fesetenvf libc_fesetenv
+#define libc_feupdateenv_testf libc_feupdateenv_test
+#define libc_feupdateenvf libc_feupdateenv
+#define libc_feholdsetroundf libc_feholdsetround
+#define libc_feresetroundf libc_feresetround
+#define libc_feholdexcept libc_feholdexcept
+#define libc_fesetround libc_fesetround
+#define libc_feholdexcept_setround libc_feholdexcept_setround
+#define libc_fetestexcept libc_fetestexcept
+#define libc_fesetenv libc_fesetenv
+#define libc_feupdateenv_test libc_feupdateenv_test
+#define libc_feupdateenv libc_feupdateenv
+#define libc_feholdsetround libc_feholdsetround
+#define libc_feresetround libc_feresetround
+#define libc_feholdexceptl libc_feholdexcept
+#define libc_fesetroundl libc_fesetround
+#define libc_feholdexcept_setroundl libc_feholdexcept_setround
+#define libc_fetestexceptl libc_fetestexcept
+#define libc_fesetenvl libc_fesetenv
+#define libc_feupdateenv_testl libc_feupdateenv_test
+#define libc_feupdateenvl libc_feupdateenv
+#define libc_feholdsetroundl libc_feholdsetround
+#define libc_feresetroundl libc_feresetround
+
+/* We have support for rounding mode context. */
+#define HAVE_RM_CTX 1
+
+static __always_inline void
+libc_feholdexcept_setround_sparc_ctx (struct rm_ctx *ctx, int round)
+{
+ fenv_t new;
+
+ __fenv_stfsr(ctx->env);
+ new = ctx->env & ~((0x1f << 23) | FE_ALL_EXCEPT);
+ new = (new & ~__FE_ROUND_MASK) | round;
+ if (unlikely (new != ctx->env))
+ {
+ __fenv_ldfsr(new);
+ ctx->updated_status = true;
+ }
+ else
+ ctx->updated_status = false;
+}
+
+static __always_inline void
+libc_fesetenv_sparc_ctx (struct rm_ctx *ctx)
+{
+ libc_fesetenv(&ctx->env);
+}
+
+static __always_inline void
+libc_feupdateenv_sparc_ctx (struct rm_ctx *ctx)
+{
+ if (unlikely (ctx->updated_status))
+ libc_feupdateenv_test (&ctx->env, 0);
+}
+
+static __always_inline void
+libc_feholdsetround_sparc_ctx (struct rm_ctx *ctx, int round)
+{
+ fenv_t new;
+
+ __fenv_stfsr(ctx->env);
+ new = (ctx->env & ~__FE_ROUND_MASK) | round;
+ if (unlikely (new != ctx->env))
+ {
+ __fenv_ldfsr(new);
+ ctx->updated_status = true;
+ }
+ else
+ ctx->updated_status = false;
+}
+#define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_sparc_ctx
+#define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_sparc_ctx
+#define libc_feholdexcept_setroundl_ctx libc_feholdexcept_setround_sparc_ctx
+#define libc_fesetenv_ctx libc_fesetenv_sparc_ctx
+#define libc_fesetenvf_ctx libc_fesetenv_sparc_ctx
+#define libc_fesetenvl_ctx libc_fesetenv_sparc_ctx
+#define libc_feupdateenv_ctx libc_feupdateenv_sparc_ctx
+#define libc_feupdateenvf_ctx libc_feupdateenv_sparc_ctx
+#define libc_feupdateenvl_ctx libc_feupdateenv_sparc_ctx
+#define libc_feresetround_ctx libc_feupdateenv_sparc_ctx
+#define libc_feresetroundf_ctx libc_feupdateenv_sparc_ctx
+#define libc_feresetroundl_ctx libc_feupdateenv_sparc_ctx
+#define libc_feholdsetround_ctx libc_feholdsetround_sparc_ctx
+#define libc_feholdsetroundf_ctx libc_feholdsetround_sparc_ctx
+#define libc_feholdsetroundl_ctx libc_feholdsetround_sparc_ctx
+
+#endif /* SPARC_FENV_PRIVATE_H */
diff --git a/libm/sparc/fesetenv.c b/libm/sparc/fesetenv.c
new file mode 100644
index 000000000..d6f3dc5f5
--- /dev/null
+++ b/libm/sparc/fesetenv.c
@@ -0,0 +1,45 @@
+/* Install given floating-point environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fesetenv (const fenv_t *envp)
+{
+ fenv_t dummy;
+
+ /* Put these constants in memory explicitly, so as to cope with a
+ -fPIC bug as of gcc 970624. Making them automatic is quicker
+ than loading up the pic register in this instance. */
+
+ if (envp == FE_DFL_ENV)
+ {
+ dummy = 0;
+ envp = &dummy;
+ }
+ else if (envp == FE_NOMASK_ENV)
+ {
+ dummy = 0x1f << 23;
+ envp = &dummy;
+ }
+
+ __fenv_ldfsr (*envp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/sparc/fesetexcept.c b/libm/sparc/fesetexcept.c
new file mode 100644
index 000000000..02210b691
--- /dev/null
+++ b/libm/sparc/fesetexcept.c
@@ -0,0 +1,31 @@
+/* Set given exception flags. SPARC version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fesetexcept (int excepts)
+{
+ fenv_t tmp;
+
+ __fenv_stfsr (tmp);
+ tmp |= excepts & FE_ALL_EXCEPT;
+ __fenv_ldfsr (tmp);
+
+ return 0;
+}
diff --git a/libm/sparc/fesetmode.c b/libm/sparc/fesetmode.c
new file mode 100644
index 000000000..e72b3d9df
--- /dev/null
+++ b/libm/sparc/fesetmode.c
@@ -0,0 +1,38 @@
+/* Install given floating-point control modes. SPARC version.
+ Copyright (C) 2016-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+#include <fpu_control.h>
+
+#define FPU_CONTROL_BITS 0xcfc00000UL
+
+int
+fesetmode (const femode_t *modep)
+{
+ femode_t fsr;
+
+ __fenv_stfsr (fsr);
+ fsr &= ~FPU_CONTROL_BITS;
+ if (modep == FE_DFL_MODE)
+ fsr |= _FPU_DEFAULT;
+ else
+ fsr |= *modep & FPU_CONTROL_BITS;
+ __fenv_ldfsr (fsr);
+
+ return 0;
+}
diff --git a/libm/sparc/fesetround.c b/libm/sparc/fesetround.c
new file mode 100644
index 000000000..ba3a4e50f
--- /dev/null
+++ b/libm/sparc/fesetround.c
@@ -0,0 +1,36 @@
+/* Set current rounding direction.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fesetround (int round)
+{
+ fenv_t tmp;
+
+ if ((round & ~__FE_ROUND_MASK) != 0)
+ /* ROUND is no valid rounding mode. */
+ return 1;
+
+ __fenv_stfsr (tmp);
+ tmp &= ~__FE_ROUND_MASK;
+ tmp |= round;
+ __fenv_ldfsr (tmp);
+
+ return 0;
+}
diff --git a/libm/sparc/feupdateenv.c b/libm/sparc/feupdateenv.c
new file mode 100644
index 000000000..272536cf3
--- /dev/null
+++ b/libm/sparc/feupdateenv.c
@@ -0,0 +1,40 @@
+/* Install given floating-point environment and raise exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+feupdateenv (const fenv_t *envp)
+{
+ fexcept_t tmp;
+
+ /* Save current exceptions. */
+ __fenv_stfsr (tmp);
+ tmp &= FE_ALL_EXCEPT;
+
+ /* Install new environment. */
+ fesetenv (envp);
+
+ /* Raise the saved exception. Incidentally for us the implementation
+ defined format of the values in objects of type fexcept_t is the
+ same as the ones specified using the FE_* constants. */
+ feraiseexcept ((int) tmp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/sparc/fgetexcptflg.c b/libm/sparc/fgetexcptflg.c
new file mode 100644
index 000000000..d8568906e
--- /dev/null
+++ b/libm/sparc/fgetexcptflg.c
@@ -0,0 +1,33 @@
+/* Store current representation for exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ fexcept_t tmp;
+
+ /* Get the current exceptions. */
+ __fenv_stfsr (tmp);
+
+ *flagp = tmp & excepts & FE_ALL_EXCEPT;
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/sparc/fpu_control.h b/libm/sparc/fpu_control.h
new file mode 100644
index 000000000..542f9fb1b
--- /dev/null
+++ b/libm/sparc/fpu_control.h
@@ -0,0 +1,75 @@
+/* FPU control word bits. SPARC version.
+ Copyright (C) 1997-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 1
+
+
+#include <features.h>
+#include <bits/wordsize.h>
+
+/* masking of interrupts */
+#define _FPU_MASK_IM 0x08000000
+#define _FPU_MASK_OM 0x04000000
+#define _FPU_MASK_UM 0x02000000
+#define _FPU_MASK_ZM 0x01000000
+#define _FPU_MASK_PM 0x00800000
+
+/* precision control */
+#define _FPU_EXTENDED 0x00000000 /* RECOMMENDED */
+#define _FPU_DOUBLE 0x20000000
+#define _FPU_80BIT 0x30000000
+#define _FPU_SINGLE 0x10000000 /* DO NOT USE */
+
+/* rounding control / Sparc */
+#define _FPU_RC_DOWN 0xc0000000
+#define _FPU_RC_UP 0x80000000
+#define _FPU_RC_ZERO 0x40000000
+#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */
+
+#define _FPU_RESERVED 0x303e0000 /* Reserved bits in cw */
+
+
+/* Now two recommended cw */
+
+/* Linux and IEEE default:
+ - extended precision
+ - rounding to nearest
+ - no exceptions */
+#define _FPU_DEFAULT 0x0
+#define _FPU_IEEE 0x0
+
+/* Type of the control word. */
+typedef unsigned long int fpu_control_t;
+
+#if __WORDSIZE == 64
+# define _FPU_GETCW(cw) __asm__ __volatile__ ("stx %%fsr,%0" : "=m" (*&cw))
+# define _FPU_SETCW(cw) __asm__ __volatile__ ("ldx %0,%%fsr" : : "m" (*&cw))
+#else
+# ifdef __leon__
+ /* Prevent stfsr from being placed directly after other fp instruction. */
+# define _FPU_GETCW(cw) __asm__ __volatile__ ("nop; st %%fsr,%0" : "=m" (*&cw))
+# else
+# define _FPU_GETCW(cw) __asm__ __volatile__ ("st %%fsr,%0" : "=m" (*&cw))
+# endif
+# define _FPU_SETCW(cw) __asm__ __volatile__ ("ld %0,%%fsr" : : "m" (*&cw))
+#endif
+
+/* Default control word set at startup. */
+extern fpu_control_t __fpu_control;
+
+#endif /* fpu_control.h */
diff --git a/libm/sparc/fraiseexcpt.c b/libm/sparc/fraiseexcpt.c
new file mode 100644
index 000000000..72e151fe6
--- /dev/null
+++ b/libm/sparc/fraiseexcpt.c
@@ -0,0 +1,81 @@
+/* Raise given exceptions.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include <float.h>
+#include <math.h>
+#include "math-barriers.h"
+
+int
+feraiseexcept (int excepts)
+{
+ static const struct {
+ double zero, one, max, min, pi;
+ } c = {
+ 0.0, 1.0, DBL_MAX, DBL_MIN, M_PI
+ };
+ double d;
+
+ /* Raise exceptions represented by EXPECTS. But we must raise only
+ one signal at a time. It is important the if the overflow/underflow
+ exception and the inexact exception are given at the same time,
+ the overflow/underflow exception follows the inexact exception. */
+
+ /* First: invalid exception. */
+ if ((FE_INVALID & excepts) != 0)
+ {
+ /* One example of an invalid operation is 0/0. */
+ __asm__ ("" : "=e" (d) : "0" (c.zero));
+ d /= c.zero;
+ math_force_eval (d);
+ }
+
+ /* Next: division by zero. */
+ if ((FE_DIVBYZERO & excepts) != 0)
+ {
+ __asm__ ("" : "=e" (d) : "0" (c.one));
+ d /= c.zero;
+ math_force_eval (d);
+ }
+
+ /* Next: overflow. */
+ if ((FE_OVERFLOW & excepts) != 0)
+ {
+ __asm__ ("" : "=e" (d) : "0" (c.max));
+ d *= d;
+ math_force_eval (d);
+ }
+
+ /* Next: underflow. */
+ if ((FE_UNDERFLOW & excepts) != 0)
+ {
+ __asm__ ("" : "=e" (d) : "0" (c.min));
+ d *= d;
+ math_force_eval (d);
+ }
+
+ /* Last: inexact. */
+ if ((FE_INEXACT & excepts) != 0)
+ {
+ __asm__ ("" : "=e" (d) : "0" (c.one));
+ d /= c.pi;
+ math_force_eval (d);
+ }
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/sparc/fsetexcptflg.c b/libm/sparc/fsetexcptflg.c
new file mode 100644
index 000000000..4b3b6ae68
--- /dev/null
+++ b/libm/sparc/fsetexcptflg.c
@@ -0,0 +1,36 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+#include <math.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fenv_t tmp;
+
+ __fenv_stfsr (tmp);
+
+ tmp &= ~(excepts & FE_ALL_EXCEPT);
+ tmp |= *flagp & excepts & FE_ALL_EXCEPT;
+
+ __fenv_ldfsr (tmp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/libm/sparc/ftestexcept.c b/libm/sparc/ftestexcept.c
new file mode 100644
index 000000000..1fe87bb36
--- /dev/null
+++ b/libm/sparc/ftestexcept.c
@@ -0,0 +1,29 @@
+/* Test exception in current environment.
+ Copyright (C) 1997-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/>. */
+
+#include <fenv.h>
+#include "fenv_private.h"
+
+int
+fetestexcept (int excepts)
+{
+ fenv_t tmp;
+
+ __fenv_stfsr (tmp);
+
+ return tmp & excepts & FE_ALL_EXCEPT;
+}
diff --git a/libm/sparc/math-barriers.h b/libm/sparc/math-barriers.h
new file mode 100644
index 000000000..4b02ff47b
--- /dev/null
+++ b/libm/sparc/math-barriers.h
@@ -0,0 +1,36 @@
+/* Control when floating-point expressions are evaluated. Generic version.
+ Copyright (C) 2007-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 _MATH_BARRIERS_H
+#define _MATH_BARRIERS_H 1
+
+/* math_opt_barrier evaluates and returns its floating-point argument
+ and ensures that the evaluation of any expression using the result
+ of math_opt_barrier is not moved before the call. math_force_eval
+ ensures that its floating-point argument is evaluated for its side
+ effects even if its value is apparently unused, and that the
+ evaluation of its argument is not moved after the call. Both these
+ macros are used to ensure the correct ordering of floating-point
+ expression evaluations with respect to accesses to the
+ floating-point environment. */
+
+#define math_opt_barrier(x) \
+ ({ __typeof (x) __x = (x); __asm ("" : "+m" (__x)); __x; })
+#define math_force_eval(x) \
+ ({ __typeof (x) __x = (x); __asm __volatile__ ("" : : "m" (__x)); })
+
+#endif /* math-barriers.h */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/m68k/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/m68k/bits/pthreadtypes.h
index 2a90a0b90..d2f22caee 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/m68k/bits/pthreadtypes.h
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/m68k/bits/pthreadtypes.h
@@ -39,7 +39,7 @@ typedef unsigned long int pthread_t;
typedef union
{
char __size[__SIZEOF_PTHREAD_ATTR_T];
- long int __align;
+ long int __align __attribute__((__aligned__(4)));
} pthread_attr_t;
@@ -69,13 +69,13 @@ typedef union
};
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
- long int __align;
+ long int __align __attribute__((__aligned__(4)));
} pthread_mutex_t;
typedef union
{
char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
- long int __align;
+ long int __align __attribute__((__aligned__(4)));
} pthread_mutexattr_t;
@@ -95,13 +95,13 @@ typedef union
unsigned int __broadcast_seq;
} __data;
char __size[__SIZEOF_PTHREAD_COND_T];
- __extension__ long long int __align;
+ __extension__ long long int __align __attribute__((__aligned__(8)));
} pthread_cond_t;
typedef union
{
char __size[__SIZEOF_PTHREAD_CONDATTR_T];
- long int __align;
+ long int __align __attribute__((__aligned__(4)));
} pthread_condattr_t;
@@ -144,13 +144,13 @@ typedef union
int __writer;
} __data;
char __size[__SIZEOF_PTHREAD_RWLOCK_T];
- long int __align;
+ long int __align __attribute__((__aligned__(4)));
} pthread_rwlock_t;
typedef union
{
char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
- long int __align;
+ long int __align __attribute__((__aligned__(4)));
} pthread_rwlockattr_t;
#endif
@@ -165,13 +165,13 @@ typedef volatile int pthread_spinlock_t;
typedef union
{
char __size[__SIZEOF_PTHREAD_BARRIER_T];
- long int __align;
+ long int __align __attribute__((__aligned__(4)));
} pthread_barrier_t;
typedef union
{
char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
- int __align;
+ int __align __attribute__((__aligned__(4)));
} pthread_barrierattr_t;
#endif
diff --git a/libutil/forkpty.c b/libutil/forkpty.c
index 24643330c..7e42d1a33 100644
--- a/libutil/forkpty.c
+++ b/libutil/forkpty.c
@@ -23,7 +23,8 @@
#include <pty.h>
int
-forkpty (int *amaster, char *name, struct termios *termp, struct winsize *winp)
+forkpty (int *amaster, char *name, const struct termios *termp,
+ const struct winsize *winp)
{
int master, slave, pid;
diff --git a/libutil/openpty.c b/libutil/openpty.c
index 848dc8d38..74d86506b 100644
--- a/libutil/openpty.c
+++ b/libutil/openpty.c
@@ -26,82 +26,18 @@
#include <unistd.h>
#include <sys/types.h>
-/* BCS: the following function is, IMO, overkill */
-#if 0
-/* Return the result of ptsname_r in the buffer pointed to by PTS,
- which should be of length BUF_LEN. If it is too long to fit in
- this buffer, a sufficiently long buffer is allocated using malloc,
- and returned in PTS. 0 is returned upon success, -1 otherwise. */
-static int
-pts_name (int fd, char **pts, size_t buf_len)
-{
- int rv;
- char *buf = *pts;
-
- for (;;)
- {
- char *new_buf;
-
- if (buf_len)
- {
- rv = ptsname_r (fd, buf, buf_len);
-
- if (rv != 0 || memchr (buf, '\0', buf_len))
- /* We either got an error, or we succeeded and the
- returned name fit in the buffer. */
- break;
-
- /* Try again with a longer buffer. */
- buf_len += buf_len; /* Double it */
- }
- else
- /* No initial buffer; start out by mallocing one. */
- buf_len = 128; /* First time guess. */
-
- if (buf != *pts)
- /* We've already malloced another buffer at least once. */
- new_buf = realloc (buf, buf_len);
- else
- new_buf = malloc (buf_len);
- if (! new_buf)
- {
- rv = -1;
- __set_errno (ENOMEM);
- break;
- }
- buf = new_buf;
- }
-
- if (rv == 0)
- *pts = buf; /* Return buffer to the user. */
- else if (buf != *pts)
- free (buf); /* Free what we malloced when returning an error. */
-
- return rv;
-}
-#endif
-
/* Create pseudo tty master slave pair and set terminal attributes
according to TERMP and WINP. Return handles for both ends in
AMASTER and ASLAVE, and return the name of the slave end in NAME. */
int
-openpty (int *amaster, int *aslave, char *name, struct termios *termp,
- struct winsize *winp)
+openpty (int *amaster, int *aslave, char *name, const struct termios *termp,
+ const struct winsize *winp)
{
-#if 0
-#ifdef PATH_MAX
- char _buf[PATH_MAX];
-#else
- char _buf[512];
-#endif
- char *buf = _buf;
-#else
#ifdef PATH_MAX
char buf[PATH_MAX];
#else
char buf[512];
#endif
-#endif
int master, slave;
master = posix_openpt (O_RDWR);
@@ -114,20 +50,12 @@ openpty (int *amaster, int *aslave, char *name, struct termios *termp,
if (unlockpt (master))
goto fail;
-#if 0
- if (pts_name (master, &buf, sizeof (_buf)))
-#else
if (ptsname_r (master, buf, sizeof buf))
-#endif
goto fail;
slave = open (buf, O_RDWR | O_NOCTTY);
if (slave == -1)
{
-#if 0
- if (buf != _buf)
- free (buf);
-#endif
goto fail;
}
@@ -142,10 +70,6 @@ openpty (int *amaster, int *aslave, char *name, struct termios *termp,
if (name != NULL)
strcpy (name, buf);
-#if 0
- if (buf != _buf)
- free (buf);
-#endif
return 0;
fail: