summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extra/Configs/Config.in.arch3
-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--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/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
61 files changed, 2504 insertions, 90 deletions
diff --git a/extra/Configs/Config.in.arch b/extra/Configs/Config.in.arch
index cacac7e5e..df6b795fa 100644
--- a/extra/Configs/Config.in.arch
+++ b/extra/Configs/Config.in.arch
@@ -165,6 +165,7 @@ config UCLIBC_HAS_FENV
depends on UCLIBC_HAS_FLOATS
depends on TARGET_i386 || \
TARGET_aarch64 || \
+ TARGET_arc || \
TARGET_arm || \
TARGET_m68k || \
TARGET_metag || \
@@ -174,6 +175,8 @@ config UCLIBC_HAS_FENV
(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/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/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
+#ifnde