* [PATCH 0/2] OpenRISC glibc hard float support
@ 2024-03-29 7:40 Stafford Horne
2024-03-29 7:40 ` [PATCH 1/2] or1k: Add " Stafford Horne
2024-03-29 7:40 ` [PATCH 2/2] build-many-glibcs.py: Add openrisc hard float glibc variant Stafford Horne
0 siblings, 2 replies; 8+ messages in thread
From: Stafford Horne @ 2024-03-29 7:40 UTC (permalink / raw)
To: GLIBC patches; +Cc: Linux OpenRISC, Stafford Horne
This series adds hardware floating point support to the OpenRIS glibc port.
I will keep this cover letter short and point to patch 1/2. It contains details
about the change and testing results.
Stafford Horne (2):
or1k: Add hard float support
build-many-glibcs.py: Add openrisc hard float glibc variant
scripts/build-many-glibcs.py | 5 +-
sysdeps/or1k/fpu/fclrexcpt.c | 44 +
sysdeps/or1k/fpu/fegetenv.c | 32 +
sysdeps/or1k/fpu/fegetmode.c | 29 +
sysdeps/or1k/fpu/fegetround.c | 29 +
sysdeps/or1k/fpu/feholdexcpt.c | 33 +
sysdeps/or1k/fpu/fenv_private.h | 199 +++
sysdeps/or1k/fpu/fesetenv.c | 32 +
sysdeps/or1k/fpu/fesetexcept.c | 35 +
sysdeps/or1k/fpu/fesetmode.c | 39 +
sysdeps/or1k/fpu/fesetround.c | 39 +
sysdeps/or1k/fpu/feupdateenv.c | 33 +
sysdeps/or1k/fpu/fgetexcptflg.c | 29 +
.../or1k/fpu/fix-fp-int-convert-overflow.h | 38 +
sysdeps/or1k/fpu/fraiseexcpt.c | 67 +
sysdeps/or1k/fpu/fsetexcptflg.c | 43 +
sysdeps/or1k/fpu/ftestexcept.c | 27 +
sysdeps/or1k/fpu/get-rounding-mode.h | 38 +
sysdeps/or1k/fpu/libm-test-ulps | 1115 +++++++++++++++++
sysdeps/or1k/fpu/libm-test-ulps-name | 1 +
sysdeps/or1k/fpu_control.h | 61 +
sysdeps/or1k/libm-test-ulps-name | 1 -
sysdeps/or1k/math-tests-snan-payload.h | 26 +
sysdeps/or1k/math-tests-trap.h | 27 +
sysdeps/or1k/{ => nofpu}/libm-test-ulps | 0
sysdeps/or1k/nofpu/libm-test-ulps-name | 1 +
sysdeps/or1k/sfp-machine.h | 18 +-
sysdeps/unix/sysv/linux/or1k/getcontext.S | 6 +
sysdeps/unix/sysv/linux/or1k/setcontext.S | 6 +
sysdeps/unix/sysv/linux/or1k/swapcontext.S | 12 +
sysdeps/unix/sysv/linux/or1k/sys/ucontext.h | 1 +
sysdeps/unix/sysv/linux/or1k/ucontext_i.sym | 3 +
32 files changed, 2065 insertions(+), 4 deletions(-)
create mode 100644 sysdeps/or1k/fpu/fclrexcpt.c
create mode 100644 sysdeps/or1k/fpu/fegetenv.c
create mode 100644 sysdeps/or1k/fpu/fegetmode.c
create mode 100644 sysdeps/or1k/fpu/fegetround.c
create mode 100644 sysdeps/or1k/fpu/feholdexcpt.c
create mode 100644 sysdeps/or1k/fpu/fenv_private.h
create mode 100644 sysdeps/or1k/fpu/fesetenv.c
create mode 100644 sysdeps/or1k/fpu/fesetexcept.c
create mode 100644 sysdeps/or1k/fpu/fesetmode.c
create mode 100644 sysdeps/or1k/fpu/fesetround.c
create mode 100644 sysdeps/or1k/fpu/feupdateenv.c
create mode 100644 sysdeps/or1k/fpu/fgetexcptflg.c
create mode 100644 sysdeps/or1k/fpu/fix-fp-int-convert-overflow.h
create mode 100644 sysdeps/or1k/fpu/fraiseexcpt.c
create mode 100644 sysdeps/or1k/fpu/fsetexcptflg.c
create mode 100644 sysdeps/or1k/fpu/ftestexcept.c
create mode 100644 sysdeps/or1k/fpu/get-rounding-mode.h
create mode 100644 sysdeps/or1k/fpu/libm-test-ulps
create mode 100644 sysdeps/or1k/fpu/libm-test-ulps-name
create mode 100644 sysdeps/or1k/fpu_control.h
delete mode 100644 sysdeps/or1k/libm-test-ulps-name
create mode 100644 sysdeps/or1k/math-tests-snan-payload.h
create mode 100644 sysdeps/or1k/math-tests-trap.h
rename sysdeps/or1k/{ => nofpu}/libm-test-ulps (100%)
create mode 100644 sysdeps/or1k/nofpu/libm-test-ulps-name
--
2.44.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] or1k: Add hard float support
2024-03-29 7:40 [PATCH 0/2] OpenRISC glibc hard float support Stafford Horne
@ 2024-03-29 7:40 ` Stafford Horne
2024-04-16 14:04 ` Adhemerval Zanella Netto
2024-03-29 7:40 ` [PATCH 2/2] build-many-glibcs.py: Add openrisc hard float glibc variant Stafford Horne
1 sibling, 1 reply; 8+ messages in thread
From: Stafford Horne @ 2024-03-29 7:40 UTC (permalink / raw)
To: GLIBC patches; +Cc: Linux OpenRISC, Stafford Horne
This patch adds hardware floating point support to OpenRISC. Hardware
floating point toolchain builds are enabled by passing the machine
specific argument -mhard-float to gcc via CFLAGS. With this enabled GCC
generates floating point instructions for single-precision operations
and exports __or1k_hard_float__.
There are 2 main parts to this patch.
- Implement fenv functions to update the FPCSR flags keeping it in sync
with sfp (software floating point).
- Update machine context functions to store and restore the FPCSR
state.
*On mcontext_t ABI*
This patch adds __fpcsr to mcontext_t. This is an ABI change, but also
an ABI fix. The linux kernel has always defined padding in mcontext_t
that was was missing from the glibc ABI. This unused space is has now
been re-purposed for storing the FPCSR. This patch brings OpenRISC
glibc in line with the Linux kernel and other libc implementation
(musl).
*Hard float ABI*
The calling conventions and types do not change with OpenRISC hard-float
so glibc hard-float builds continue to use dynamic linker
/lib/ld-linux-or1k.so.1.
*Testing*
I have tested this patch both with hard-float and soft-float builds and
the test results look fine to me. Results are as follows:
Hard Float
# failures
FAIL: elf/tst-sprof-basic (Not checked, seen in other ports too)
FAIL: gmon/tst-gmon-pie (GCC PIE bug)
FAIL: gmon/tst-gmon-pie-gprof (GCC PIE bug)
FAIL: nptl/tst-cond24 (timeouts)
FAIL: nptl/tst-mutex10 (timeouts)
# summary
5 FAIL
4279 PASS
83 UNSUPPORTED
16 XFAIL
2 XPASS
# versions
Toolchain: or1k-smhfpu-linux-gnu
Compiler: gcc version 14.0.1 20240324 (experimental) [master r14-9649-gbb04a11418f] (GCC)
Binutils: GNU assembler version 2.42.0 (or1k-smhfpu-linux-gnu) using BFD version (GNU Binutils) 2.42.0.20240324
Linux: Linux buildroot 6.8.0-rc5-00003-g9158c6253560-dirty #78 SMP Fri Mar 22 16:56:54 GMT 2024 openrisc GNU/Linux
Soft Float
# failures
FAIL: elf/tst-sprof-basic
FAIL: gmon/tst-gmon-pie
FAIL: gmon/tst-gmon-pie-gprof
FAIL: iconvdata/iconv-test (timeout, passed when run manually)
FAIL: nptl/tst-mutex10
# summary
5 FAIL
4281 PASS
81 UNSUPPORTED
16 XFAIL
2 XPASS
# versions
Toolchain: or1k-smh-linux-gnu
Compiler: gcc version 14.0.1 20240324 (experimental) [master r14-9649-gbb04a11418f] (GCC)
Binutils: GNU assembler version 2.42.0 (or1k-smh-linux-gnu) using BFD version (GNU Binutils) 2.42.0.20240324
Linux: Linux buildroot 6.8.0-rc5-00003-g9158c6253560-dirty #78 SMP Fri Mar 22 16:56:54 GMT 2024 openrisc GNU/Linux
Documentation: https://raw.githubusercontent.com/openrisc/doc/master/openrisc-arch-1.4-rev0.pdf
---
sysdeps/or1k/fpu/fclrexcpt.c | 44 +
sysdeps/or1k/fpu/fegetenv.c | 32 +
sysdeps/or1k/fpu/fegetmode.c | 29 +
sysdeps/or1k/fpu/fegetround.c | 29 +
sysdeps/or1k/fpu/feholdexcpt.c | 33 +
sysdeps/or1k/fpu/fenv_private.h | 199 +++
sysdeps/or1k/fpu/fesetenv.c | 32 +
sysdeps/or1k/fpu/fesetexcept.c | 35 +
sysdeps/or1k/fpu/fesetmode.c | 39 +
sysdeps/or1k/fpu/fesetround.c | 39 +
sysdeps/or1k/fpu/feupdateenv.c | 33 +
sysdeps/or1k/fpu/fgetexcptflg.c | 29 +
.../or1k/fpu/fix-fp-int-convert-overflow.h | 38 +
sysdeps/or1k/fpu/fraiseexcpt.c | 67 +
sysdeps/or1k/fpu/fsetexcptflg.c | 43 +
sysdeps/or1k/fpu/ftestexcept.c | 27 +
sysdeps/or1k/fpu/get-rounding-mode.h | 38 +
sysdeps/or1k/fpu/libm-test-ulps | 1115 +++++++++++++++++
sysdeps/or1k/fpu/libm-test-ulps-name | 1 +
sysdeps/or1k/fpu_control.h | 61 +
sysdeps/or1k/libm-test-ulps-name | 1 -
sysdeps/or1k/math-tests-snan-payload.h | 26 +
sysdeps/or1k/math-tests-trap.h | 27 +
sysdeps/or1k/{ => nofpu}/libm-test-ulps | 0
sysdeps/or1k/nofpu/libm-test-ulps-name | 1 +
sysdeps/or1k/sfp-machine.h | 18 +-
sysdeps/unix/sysv/linux/or1k/getcontext.S | 6 +
sysdeps/unix/sysv/linux/or1k/setcontext.S | 6 +
sysdeps/unix/sysv/linux/or1k/swapcontext.S | 12 +
sysdeps/unix/sysv/linux/or1k/sys/ucontext.h | 1 +
sysdeps/unix/sysv/linux/or1k/ucontext_i.sym | 3 +
31 files changed, 2062 insertions(+), 2 deletions(-)
create mode 100644 sysdeps/or1k/fpu/fclrexcpt.c
create mode 100644 sysdeps/or1k/fpu/fegetenv.c
create mode 100644 sysdeps/or1k/fpu/fegetmode.c
create mode 100644 sysdeps/or1k/fpu/fegetround.c
create mode 100644 sysdeps/or1k/fpu/feholdexcpt.c
create mode 100644 sysdeps/or1k/fpu/fenv_private.h
create mode 100644 sysdeps/or1k/fpu/fesetenv.c
create mode 100644 sysdeps/or1k/fpu/fesetexcept.c
create mode 100644 sysdeps/or1k/fpu/fesetmode.c
create mode 100644 sysdeps/or1k/fpu/fesetround.c
create mode 100644 sysdeps/or1k/fpu/feupdateenv.c
create mode 100644 sysdeps/or1k/fpu/fgetexcptflg.c
create mode 100644 sysdeps/or1k/fpu/fix-fp-int-convert-overflow.h
create mode 100644 sysdeps/or1k/fpu/fraiseexcpt.c
create mode 100644 sysdeps/or1k/fpu/fsetexcptflg.c
create mode 100644 sysdeps/or1k/fpu/ftestexcept.c
create mode 100644 sysdeps/or1k/fpu/get-rounding-mode.h
create mode 100644 sysdeps/or1k/fpu/libm-test-ulps
create mode 100644 sysdeps/or1k/fpu/libm-test-ulps-name
create mode 100644 sysdeps/or1k/fpu_control.h
delete mode 100644 sysdeps/or1k/libm-test-ulps-name
create mode 100644 sysdeps/or1k/math-tests-snan-payload.h
create mode 100644 sysdeps/or1k/math-tests-trap.h
rename sysdeps/or1k/{ => nofpu}/libm-test-ulps (100%)
create mode 100644 sysdeps/or1k/nofpu/libm-test-ulps-name
diff --git a/sysdeps/or1k/fpu/fclrexcpt.c b/sysdeps/or1k/fpu/fclrexcpt.c
new file mode 100644
index 0000000000..44224f9c24
--- /dev/null
+++ b/sysdeps/or1k/fpu/fclrexcpt.c
@@ -0,0 +1,44 @@
+/* Clear given exceptions in current floating-point environment.
+ OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#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;
+}
+libm_hidden_def (feclearexcept)
diff --git a/sysdeps/or1k/fpu/fegetenv.c b/sysdeps/or1k/fpu/fegetenv.c
new file mode 100644
index 0000000000..70c75aa0bf
--- /dev/null
+++ b/sysdeps/or1k/fpu/fegetenv.c
@@ -0,0 +1,32 @@
+/* Store current floating-point environment.
+ Copyright (C) 2024 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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+__fegetenv (fenv_t *envp)
+{
+ _FPU_GETCW (*envp);
+
+ /* Success. */
+ return 0;
+}
+libm_hidden_def (__fegetenv)
+weak_alias (__fegetenv, fegetenv)
+libm_hidden_weak (fegetenv)
diff --git a/sysdeps/or1k/fpu/fegetmode.c b/sysdeps/or1k/fpu/fegetmode.c
new file mode 100644
index 0000000000..7fffd2e0b5
--- /dev/null
+++ b/sysdeps/or1k/fpu/fegetmode.c
@@ -0,0 +1,29 @@
+/* Store current floating-point control modes. OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetmode (femode_t *modep)
+{
+ _FPU_GETCW (*modep);
+
+ /* Success. */
+ return 0;
+}
diff --git a/sysdeps/or1k/fpu/fegetround.c b/sysdeps/or1k/fpu/fegetround.c
new file mode 100644
index 0000000000..7e993b980a
--- /dev/null
+++ b/sysdeps/or1k/fpu/fegetround.c
@@ -0,0 +1,29 @@
+/* Return current rounding direction. OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#include <fenv.h>
+#include <get-rounding-mode.h>
+
+int
+__fegetround (void)
+{
+ return get_rounding_mode ();
+}
+libm_hidden_def (__fegetround)
+weak_alias (__fegetround, fegetround)
+libm_hidden_weak (fegetround)
diff --git a/sysdeps/or1k/fpu/feholdexcpt.c b/sysdeps/or1k/fpu/feholdexcpt.c
new file mode 100644
index 0000000000..0036e41ba2
--- /dev/null
+++ b/sysdeps/or1k/fpu/feholdexcpt.c
@@ -0,0 +1,33 @@
+/* Store current floating-point environment and clear exceptions.
+ OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#include <fenv.h>
+#include <fenv_private.h>
+
+int
+__feholdexcept (fenv_t *envp)
+{
+ libc_feholdexcept_or1k (envp);
+
+ /* Success. */
+ return 0;
+}
+libm_hidden_def (__feholdexcept)
+weak_alias (__feholdexcept, feholdexcept)
+libm_hidden_weak (feholdexcept)
diff --git a/sysdeps/or1k/fpu/fenv_private.h b/sysdeps/or1k/fpu/fenv_private.h
new file mode 100644
index 0000000000..4f401e7a5a
--- /dev/null
+++ b/sysdeps/or1k/fpu/fenv_private.h
@@ -0,0 +1,199 @@
+/* Private floating point rounding and exceptions handling. OpenRISC version.
+ Copyright (C) 2024 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 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 (__glibc_unlikely (cw != cw_new))
+ _FPU_SETCW (cw_new);
+
+ /* Raise the exceptions if enabled in the new FP state. */
+ if (__glibc_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 (__glibc_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 (__glibc_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
+
+#include_next <fenv_private.h>
+
+#endif
diff --git a/sysdeps/or1k/fpu/fesetenv.c b/sysdeps/or1k/fpu/fesetenv.c
new file mode 100644
index 0000000000..742ca719e0
--- /dev/null
+++ b/sysdeps/or1k/fpu/fesetenv.c
@@ -0,0 +1,32 @@
+/* Install given floating-point environment. OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#include <fenv.h>
+#include <fenv_private.h>
+
+int
+__fesetenv (const fenv_t *envp)
+{
+ libc_fesetenv_or1k (envp);
+
+ /* Success. */
+ return 0;
+}
+libm_hidden_def (__fesetenv)
+weak_alias (__fesetenv, fesetenv)
+libm_hidden_weak (fesetenv)
diff --git a/sysdeps/or1k/fpu/fesetexcept.c b/sysdeps/or1k/fpu/fesetexcept.c
new file mode 100644
index 0000000000..43734eac18
--- /dev/null
+++ b/sysdeps/or1k/fpu/fesetexcept.c
@@ -0,0 +1,35 @@
+/* Set given exception flags. OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#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/sysdeps/or1k/fpu/fesetmode.c b/sysdeps/or1k/fpu/fesetmode.c
new file mode 100644
index 0000000000..d4556927ce
--- /dev/null
+++ b/sysdeps/or1k/fpu/fesetmode.c
@@ -0,0 +1,39 @@
+/* Install given floating-point control modes. OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#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/sysdeps/or1k/fpu/fesetround.c b/sysdeps/or1k/fpu/fesetround.c
new file mode 100644
index 0000000000..c2ada98f1b
--- /dev/null
+++ b/sysdeps/or1k/fpu/fesetround.c
@@ -0,0 +1,39 @@
+/* Set current rounding direction. OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#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. */
+ }
+}
+libm_hidden_def (__fesetround)
+weak_alias (__fesetround, fesetround)
+libm_hidden_weak (fesetround)
diff --git a/sysdeps/or1k/fpu/feupdateenv.c b/sysdeps/or1k/fpu/feupdateenv.c
new file mode 100644
index 0000000000..3355bf6596
--- /dev/null
+++ b/sysdeps/or1k/fpu/feupdateenv.c
@@ -0,0 +1,33 @@
+/* Install given floating-point environment and raise exceptions.
+ OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#include <fenv.h>
+#include <fenv_private.h>
+
+int
+__feupdateenv (const fenv_t *envp)
+{
+ libc_feupdateenv_or1k (envp);
+
+ /* Success. */
+ return 0;
+}
+libm_hidden_def (__feupdateenv)
+weak_alias (__feupdateenv, feupdateenv)
+libm_hidden_weak (feupdateenv)
diff --git a/sysdeps/or1k/fpu/fgetexcptflg.c b/sysdeps/or1k/fpu/fgetexcptflg.c
new file mode 100644
index 0000000000..a954f6a2f1
--- /dev/null
+++ b/sysdeps/or1k/fpu/fgetexcptflg.c
@@ -0,0 +1,29 @@
+/* Store current state of exceptions. OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#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/sysdeps/or1k/fpu/fix-fp-int-convert-overflow.h b/sysdeps/or1k/fpu/fix-fp-int-convert-overflow.h
new file mode 100644
index 0000000000..78104289c0
--- /dev/null
+++ b/sysdeps/or1k/fpu/fix-fp-int-convert-overflow.h
@@ -0,0 +1,38 @@
+/* Fix for conversion of floating point to integer overflow. OpenRISC version.
+ Copyright (C) 2024 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 FIX_FP_INT_CONVERT_OVERFLOW_H
+#define FIX_FP_INT_CONVERT_OVERFLOW_H 1
+
+/* The generic libgcc2.c conversions from floating point to long long
+ may not raise the correct exceptions on overflow (and may raise
+ spurious "inexact" exceptions even in non-overflow cases, see
+ <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59412>). */
+#define FIX_FLT_LONG_CONVERT_OVERFLOW 0
+#define FIX_FLT_LLONG_CONVERT_OVERFLOW 1
+
+#define FIX_DBL_LONG_CONVERT_OVERFLOW 0
+#define FIX_DBL_LLONG_CONVERT_OVERFLOW 1
+
+#define FIX_LDBL_LONG_CONVERT_OVERFLOW 0
+#define FIX_LDBL_LLONG_CONVERT_OVERFLOW 0
+
+#define FIX_FLT128_LONG_CONVERT_OVERFLOW 0
+#define FIX_FLT128_LLONG_CONVERT_OVERFLOW 0
+
+#endif /* fix-fp-int-convert-overflow.h */
diff --git a/sysdeps/or1k/fpu/fraiseexcpt.c b/sysdeps/or1k/fpu/fraiseexcpt.c
new file mode 100644
index 0000000000..bbacfd50bc
--- /dev/null
+++ b/sysdeps/or1k/fpu/fraiseexcpt.c
@@ -0,0 +1,67 @@
+/* Raise given exceptions. OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#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;
+}
+libm_hidden_def (__feraiseexcept)
+weak_alias (__feraiseexcept, feraiseexcept)
+libm_hidden_weak (feraiseexcept)
diff --git a/sysdeps/or1k/fpu/fsetexcptflg.c b/sysdeps/or1k/fpu/fsetexcptflg.c
new file mode 100644
index 0000000000..c327e4c5d1
--- /dev/null
+++ b/sysdeps/or1k/fpu/fsetexcptflg.c
@@ -0,0 +1,43 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 2024 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/>. */
+
+#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/sysdeps/or1k/fpu/ftestexcept.c b/sysdeps/or1k/fpu/ftestexcept.c
new file mode 100644
index 0000000000..59f06afa22
--- /dev/null
+++ b/sysdeps/or1k/fpu/ftestexcept.c
@@ -0,0 +1,27 @@
+/* Test exception in current environment. OpenRISC version.
+ Copyright (C) 2024 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/>. */
+
+#include <fenv.h>
+#include <fenv_private.h>
+
+int
+fetestexcept (int excepts)
+{
+ return libc_fetestexcept_or1k (excepts);
+}
+libm_hidden_def (fetestexcept)
diff --git a/sysdeps/or1k/fpu/get-rounding-mode.h b/sysdeps/or1k/fpu/get-rounding-mode.h
new file mode 100644
index 0000000000..a66d553be8
--- /dev/null
+++ b/sysdeps/or1k/fpu/get-rounding-mode.h
@@ -0,0 +1,38 @@
+/* Determine floating-point rounding mode within libc. OpenRISC version.
+
+ Copyright (C) 2024 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 _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/sysdeps/or1k/fpu/libm-test-ulps b/sysdeps/or1k/fpu/libm-test-ulps
new file mode 100644
index 0000000000..948ec01cdc
--- /dev/null
+++ b/sysdeps/or1k/fpu/libm-test-ulps
@@ -0,0 +1,1115 @@
+# Begin of automatic generation
+
+# Maximal error of functions:
+Function: "acos":
+double: 1
+float: 1
+
+Function: "acos_downward":
+double: 1
+float: 1
+
+Function: "acos_towardzero":
+double: 1
+float: 1
+
+Function: "acos_upward":
+double: 1
+float: 1
+
+Function: "acosh":
+double: 2
+float: 2
+
+Function: "acosh_downward":
+double: 2
+float: 2
+
+Function: "acosh_towardzero":
+double: 2
+float: 2
+
+Function: "acosh_upward":
+double: 2
+float: 2
+
+Function: "asin":
+double: 1
+float: 1
+
+Function: "asin_downward":
+double: 1
+float: 1
+
+Function: "asin_towardzero":
+double: 1
+float: 1
+
+Function: "asin_upward":
+double: 2
+float: 1
+
+Function: "asinh":
+double: 2
+float: 2
+
+Function: "asinh_downward":
+double: 3
+float: 3
+
+Function: "asinh_towardzero":
+double: 2
+float: 2
+
+Function: "asinh_upward":
+double: 3
+float: 3
+
+Function: "atan":
+double: 1
+float: 1
+
+Function: "atan2":
+float: 2
+
+Function: "atan2_downward":
+double: 5
+float: 2
+
+Function: "atan2_towardzero":
+double: 5
+float: 2
+
+Function: "atan2_upward":
+double: 8
+float: 2
+
+Function: "atan_downward":
+double: 1
+float: 2
+
+Function: "atan_towardzero":
+double: 1
+float: 1
+
+Function: "atan_upward":
+double: 1
+float: 2
+
+Function: "atanh":
+double: 2
+float: 2
+
+Function: "atanh_downward":
+double: 3
+float: 3
+
+Function: "atanh_towardzero":
+double: 2
+float: 2
+
+Function: "atanh_upward":
+double: 3
+float: 3
+
+Function: "cabs":
+double: 1
+
+Function: "cabs_downward":
+double: 1
+
+Function: "cabs_towardzero":
+double: 1
+
+Function: "cabs_upward":
+double: 1
+
+Function: Real part of "cacos":
+double: 1
+float: 2
+
+Function: Imaginary part of "cacos":
+double: 2
+float: 2
+
+Function: Real part of "cacos_downward":
+double: 3
+float: 2
+
+Function: Imaginary part of "cacos_downward":
+double: 5
+float: 3
+
+Function: Real part of "cacos_towardzero":
+double: 3
+float: 2
+
+Function: Imaginary part of "cacos_towardzero":
+double: 4
+float: 2
+
+Function: Real part of "cacos_upward":
+double: 2
+float: 2
+
+Function: Imaginary part of "cacos_upward":
+double: 5
+float: 7
+
+Function: Real part of "cacosh":
+double: 2
+float: 2
+
+Function: Imaginary part of "cacosh":
+double: 1
+float: 2
+
+Function: Real part of "cacosh_downward":
+double: 4
+float: 2
+
+Function: Imaginary part of "cacosh_downward":
+double: 3
+float: 3
+
+Function: Real part of "cacosh_towardzero":
+double: 4
+float: 2
+
+Function: Imaginary part of "cacosh_towardzero":
+double: 3
+float: 2
+
+Function: Real part of "cacosh_upward":
+double: 4
+float: 3
+
+Function: Imaginary part of "cacosh_upward":
+double: 3
+float: 2
+
+Function: "carg":
+float: 1
+
+Function: "carg_downward":
+double: 5
+float: 2
+
+Function: "carg_towardzero":
+double: 5
+float: 2
+
+Function: "carg_upward":
+double: 8
+float: 2
+
+Function: Real part of "casin":
+double: 1
+float: 1
+
+Function: Imaginary part of "casin":
+double: 2
+float: 2
+
+Function: Real part of "casin_downward":
+double: 3
+float: 2
+
+Function: Imaginary part of "casin_downward":
+double: 5
+float: 3
+
+Function: Real part of "casin_towardzero":
+double: 3
+float: 1
+
+Function: Imaginary part of "casin_towardzero":
+double: 4
+float: 2
+
+Function: Real part of "casin_upward":
+double: 3
+float: 2
+
+Function: Imaginary part of "casin_upward":
+double: 5
+float: 7
+
+Function: Real part of "casinh":
+double: 2
+float: 2
+
+Function: Imaginary part of "casinh":
+double: 1
+float: 1
+
+Function: Real part of "casinh_downward":
+double: 5
+float: 3
+
+Function: Imaginary part of "casinh_downward":
+double: 3
+float: 2
+
+Function: Real part of "casinh_towardzero":
+double: 4
+float: 2
+
+Function: Imaginary part of "casinh_towardzero":
+double: 3
+float: 1
+
+Function: Real part of "casinh_upward":
+double: 5
+float: 7
+
+Function: Imaginary part of "casinh_upward":
+double: 3
+float: 2
+
+Function: Real part of "catan":
+double: 1
+float: 1
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+
+Function: Real part of "catan_downward":
+double: 1
+float: 2
+
+Function: Imaginary part of "catan_downward":
+double: 2
+float: 2
+
+Function: Real part of "catan_towardzero":
+double: 1
+float: 2
+
+Function: Imaginary part of "catan_towardzero":
+double: 2
+float: 2
+
+Function: Real part of "catan_upward":
+double: 2
+float: 1
+
+Function: Imaginary part of "catan_upward":
+double: 2
+float: 2
+
+Function: Real part of "catanh":
+double: 1
+float: 1
+
+Function: Imaginary part of "catanh":
+double: 1
+float: 1
+
+Function: Real part of "catanh_downward":
+double: 2
+float: 2
+
+Function: Imaginary part of "catanh_downward":
+double: 1
+float: 2
+
+Function: Real part of "catanh_towardzero":
+double: 2
+float: 2
+
+Function: Imaginary part of "catanh_towardzero":
+double: 1
+float: 2
+
+Function: Real part of "catanh_upward":
+double: 4
+float: 4
+
+Function: Imaginary part of "catanh_upward":
+double: 2
+float: 1
+
+Function: "cbrt":
+double: 4
+float: 1
+
+Function: "cbrt_downward":
+double: 4
+float: 1
+
+Function: "cbrt_towardzero":
+double: 3
+float: 1
+
+Function: "cbrt_upward":
+double: 5
+float: 1
+
+Function: Real part of "ccos":
+double: 1
+float: 1
+
+Function: Imaginary part of "ccos":
+double: 1
+float: 1
+
+Function: Real part of "ccos_downward":
+double: 3
+float: 1
+
+Function: Imaginary part of "ccos_downward":
+double: 3
+float: 3
+
+Function: Real part of "ccos_towardzero":
+double: 3
+float: 2
+
+Function: Imaginary part of "ccos_towardzero":
+double: 3
+float: 3
+
+Function: Real part of "ccos_upward":
+double: 1
+float: 2
+
+Function: Imaginary part of "ccos_upward":
+double: 2
+float: 2
+
+Function: Real part of "ccosh":
+double: 2
+float: 1
+
+Function: Imaginary part of "ccosh":
+double: 1
+float: 1
+
+Function: Real part of "ccosh_downward":
+double: 3
+float: 2
+
+Function: Imaginary part of "ccosh_downward":
+double: 3
+float: 3
+
+Function: Real part of "ccosh_towardzero":
+double: 3
+float: 3
+
+Function: Imaginary part of "ccosh_towardzero":
+double: 3
+float: 3
+
+Function: Real part of "ccosh_upward":
+double: 1
+float: 2
+
+Function: Imaginary part of "ccosh_upward":
+double: 2
+float: 2
+
+Function: Real part of "cexp":
+double: 2
+float: 1
+
+Function: Imaginary part of "cexp":
+double: 1
+float: 2
+
+Function: Real part of "cexp_downward":
+double: 4
+float: 2
+
+Function: Imaginary part of "cexp_downward":
+double: 3
+float: 3
+
+Function: Real part of "cexp_towardzero":
+double: 4
+float: 2
+
+Function: Imaginary part of "cexp_towardzero":
+double: 3
+float: 3
+
+Function: Real part of "cexp_upward":
+double: 2
+float: 2
+
+Function: Imaginary part of "cexp_upward":
+double: 3
+float: 2
+
+Function: Real part of "clog":
+double: 3
+float: 3
+
+Function: Imaginary part of "clog":
+double: 1
+float: 1
+
+Function: Real part of "clog10":
+double: 3
+float: 4
+
+Function: Imaginary part of "clog10":
+double: 2
+float: 2
+
+Function: Real part of "clog10_downward":
+double: 7
+float: 5
+
+Function: Imaginary part of "clog10_downward":
+double: 8
+float: 4
+
+Function: Real part of "clog10_towardzero":
+double: 5
+float: 5
+
+Function: Imaginary part of "clog10_towardzero":
+double: 8
+float: 4
+
+Function: Real part of "clog10_upward":
+double: 6
+float: 5
+
+Function: Imaginary part of "clog10_upward":
+double: 5
+float: 4
+
+Function: Real part of "clog_downward":
+double: 4
+float: 3
+
+Function: Imaginary part of "clog_downward":
+double: 5
+float: 2
+
+Function: Real part of "clog_towardzero":
+double: 8
+float: 4
+
+Function: Imaginary part of "clog_towardzero":
+double: 5
+float: 3
+
+Function: Real part of "clog_upward":
+double: 8
+float: 3
+
+Function: Imaginary part of "clog_upward":
+double: 8
+float: 2
+
+Function: "cos":
+double: 1
+float: 1
+
+Function: "cos_downward":
+double: 1
+float: 1
+
+Function: "cos_towardzero":
+double: 4
+float: 1
+
+Function: "cos_upward":
+double: 4
+float: 1
+
+Function: "cosh":
+double: 2
+float: 2
+
+Function: "cosh_downward":
+double: 3
+float: 1
+
+Function: "cosh_towardzero":
+double: 3
+float: 1
+
+Function: "cosh_upward":
+double: 2
+float: 2
+
+Function: Real part of "cpow":
+double: 2
+float: 5
+
+Function: Imaginary part of "cpow":
+float: 2
+
+Function: Real part of "cpow_downward":
+double: 5
+float: 8
+
+Function: Imaginary part of "cpow_downward":
+double: 2
+float: 2
+
+Function: Real part of "cpow_towardzero":
+double: 5
+float: 8
+
+Function: Imaginary part of "cpow_towardzero":
+double: 2
+float: 2
+
+Function: Real part of "cpow_upward":
+double: 4
+float: 1
+
+Function: Imaginary part of "cpow_upward":
+double: 2
+float: 2
+
+Function: Real part of "csin":
+double: 1
+float: 1
+
+Function: Real part of "csin_downward":
+double: 3
+float: 3
+
+Function: Imaginary part of "csin_downward":
+double: 3
+float: 1
+
+Function: Real part of "csin_towardzero":
+double: 3
+float: 3
+
+Function: Imaginary part of "csin_towardzero":
+double: 3
+float: 1
+
+Function: Real part of "csin_upward":
+double: 2
+float: 2
+
+Function: Imaginary part of "csin_upward":
+double: 1
+float: 2
+
+Function: Real part of "csinh":
+float: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+
+Function: Real part of "csinh_downward":
+double: 3
+float: 1
+
+Function: Imaginary part of "csinh_downward":
+double: 3
+float: 3
+
+Function: Real part of "csinh_towardzero":
+double: 3
+float: 2
+
+Function: Imaginary part of "csinh_towardzero":
+double: 3
+float: 3
+
+Function: Real part of "csinh_upward":
+double: 1
+float: 2
+
+Function: Imaginary part of "csinh_upward":
+double: 2
+float: 2
+
+Function: Real part of "csqrt":
+double: 2
+float: 2
+
+Function: Imaginary part of "csqrt":
+double: 2
+float: 2
+
+Function: Real part of "csqrt_downward":
+double: 5
+float: 4
+
+Function: Imaginary part of "csqrt_downward":
+double: 4
+float: 3
+
+Function: Real part of "csqrt_towardzero":
+double: 4
+float: 3
+
+Function: Imaginary part of "csqrt_towardzero":
+double: 4
+float: 3
+
+Function: Real part of "csqrt_upward":
+double: 5
+float: 4
+
+Function: Imaginary part of "csqrt_upward":
+double: 3
+float: 3
+
+Function: Real part of "ctan":
+double: 1
+float: 1
+
+Function: Imaginary part of "ctan":
+double: 2
+float: 2
+
+Function: Real part of "ctan_downward":
+double: 6
+float: 5
+
+Function: Imaginary part of "ctan_downward":
+double: 3
+float: 2
+
+Function: Real part of "ctan_towardzero":
+double: 5
+float: 3
+
+Function: Imaginary part of "ctan_towardzero":
+double: 3
+float: 2
+
+Function: Real part of "ctan_upward":
+double: 2
+float: 4
+
+Function: Imaginary part of "ctan_upward":
+double: 2
+float: 1
+
+Function: Real part of "ctanh":
+double: 2
+float: 2
+
+Function: Imaginary part of "ctanh":
+double: 2
+float: 2
+
+Function: Real part of "ctanh_downward":
+double: 3
+float: 2
+
+Function: Imaginary part of "ctanh_downward":
+double: 6
+float: 5
+
+Function: Real part of "ctanh_towardzero":
+double: 3
+float: 2
+
+Function: Imaginary part of "ctanh_towardzero":
+double: 5
+float: 3
+
+Function: Real part of "ctanh_upward":
+double: 2
+float: 2
+
+Function: Imaginary part of "ctanh_upward":
+double: 2
+float: 3
+
+Function: "erf":
+double: 1
+float: 1
+
+Function: "erf_downward":
+double: 1
+float: 1
+
+Function: "erf_towardzero":
+double: 1
+float: 1
+
+Function: "erf_upward":
+double: 1
+float: 1
+
+Function: "erfc":
+double: 5
+float: 3
+
+Function: "erfc_downward":
+double: 5
+float: 6
+
+Function: "erfc_towardzero":
+double: 3
+float: 4
+
+Function: "erfc_upward":
+double: 5
+float: 6
+
+Function: "exp":
+double: 1
+float: 1
+
+Function: "exp10":
+double: 2
+float: 1
+
+Function: "exp10_downward":
+double: 3
+float: 1
+
+Function: "exp10_towardzero":
+double: 3
+float: 1
+
+Function: "exp10_upward":
+double: 2
+float: 1
+
+Function: "exp2":
+double: 1
+
+Function: "exp2_downward":
+double: 1
+
+Function: "exp2_towardzero":
+double: 1
+
+Function: "exp2_upward":
+double: 1
+float: 1
+
+Function: "exp_downward":
+double: 1
+float: 1
+
+Function: "exp_towardzero":
+double: 1
+float: 1
+
+Function: "exp_upward":
+double: 1
+float: 1
+
+Function: "expm1":
+double: 1
+float: 1
+
+Function: "expm1_downward":
+double: 1
+float: 1
+
+Function: "expm1_towardzero":
+double: 1
+float: 2
+
+Function: "expm1_upward":
+double: 1
+float: 1
+
+Function: "gamma":
+double: 4
+float: 7
+
+Function: "gamma_downward":
+double: 7
+float: 7
+
+Function: "gamma_towardzero":
+double: 7
+float: 7
+
+Function: "gamma_upward":
+double: 5
+float: 6
+
+Function: "hypot":
+double: 1
+float: 1
+
+Function: "hypot_downward":
+double: 1
+
+Function: "hypot_towardzero":
+double: 1
+
+Function: "hypot_upward":
+double: 1
+
+Function: "j0":
+double: 2
+float: 9
+
+Function: "j0_downward":
+double: 5
+float: 9
+
+Function: "j0_towardzero":
+double: 6
+float: 9
+
+Function: "j0_upward":
+double: 9
+float: 9
+
+Function: "j1":
+double: 4
+float: 9
+
+Function: "j1_downward":
+double: 5
+float: 8
+
+Function: "j1_towardzero":
+double: 4
+float: 8
+
+Function: "j1_upward":
+double: 9
+float: 9
+
+Function: "jn":
+double: 4
+float: 4
+
+Function: "jn_downward":
+double: 7
+float: 9
+
+Function: "jn_towardzero":
+double: 7
+float: 9
+
+Function: "jn_upward":
+double: 7
+float: 9
+
+Function: "lgamma":
+double: 4
+float: 7
+
+Function: "lgamma_downward":
+double: 7
+float: 7
+
+Function: "lgamma_towardzero":
+double: 7
+float: 7
+
+Function: "lgamma_upward":
+double: 5
+float: 6
+
+Function: "log10":
+double: 2
+float: 2
+
+Function: "log10_downward":
+double: 2
+float: 3
+
+Function: "log10_towardzero":
+double: 2
+float: 1
+
+Function: "log10_upward":
+double: 2
+float: 2
+
+Function: "log1p":
+double: 1
+float: 1
+
+Function: "log1p_downward":
+double: 2
+float: 2
+
+Function: "log1p_towardzero":
+double: 2
+float: 2
+
+Function: "log1p_upward":
+double: 2
+float: 2
+
+Function: "log2":
+float: 1
+
+Function: "log2_downward":
+double: 1
+
+Function: "log2_towardzero":
+double: 1
+
+Function: "log2_upward":
+double: 1
+
+Function: "pow":
+double: 1
+
+Function: "pow_downward":
+double: 1
+float: 1
+
+Function: "pow_towardzero":
+double: 1
+float: 1
+
+Function: "pow_upward":
+double: 1
+float: 1
+
+Function: "sin":
+double: 1
+float: 1
+
+Function: "sin_downward":
+double: 4
+float: 1
+
+Function: "sin_towardzero":
+double: 3
+float: 1
+
+Function: "sin_upward":
+double: 7
+float: 1
+
+Function: "sincos":
+double: 1
+
+Function: "sincos_downward":
+double: 1
+float: 1
+
+Function: "sincos_towardzero":
+double: 4
+float: 1
+
+Function: "sincos_upward":
+double: 1
+float: 1
+
+Function: "sinh":
+double: 2
+float: 2
+
+Function: "sinh_downward":
+double: 3
+float: 3
+
+Function: "sinh_towardzero":
+double: 3
+float: 2
+
+Function: "sinh_upward":
+double: 3
+float: 3
+
+Function: "tan":
+float: 1
+
+Function: "tan_downward":
+double: 1
+float: 2
+
+Function: "tan_towardzero":
+double: 1
+float: 1
+
+Function: "tan_upward":
+double: 1
+float: 1
+
+Function: "tanh":
+double: 2
+float: 2
+
+Function: "tanh_downward":
+double: 3
+float: 3
+
+Function: "tanh_towardzero":
+double: 2
+float: 2
+
+Function: "tanh_upward":
+double: 3
+float: 3
+
+Function: "tgamma":
+double: 9
+float: 8
+
+Function: "tgamma_downward":
+double: 9
+float: 9
+
+Function: "tgamma_towardzero":
+double: 9
+float: 8
+
+Function: "tgamma_upward":
+double: 9
+float: 8
+
+Function: "y0":
+double: 3
+float: 9
+
+Function: "y0_downward":
+double: 3
+float: 9
+
+Function: "y0_towardzero":
+double: 4
+float: 9
+
+Function: "y0_upward":
+double: 3
+float: 9
+
+Function: "y1":
+double: 3
+float: 9
+
+Function: "y1_downward":
+double: 6
+float: 9
+
+Function: "y1_towardzero":
+double: 3
+float: 9
+
+Function: "y1_upward":
+double: 7
+float: 9
+
+Function: "yn":
+double: 3
+float: 3
+
+Function: "yn_downward":
+double: 6
+float: 8
+
+Function: "yn_towardzero":
+double: 8
+float: 8
+
+Function: "yn_upward":
+double: 8
+float: 8
+
+# end of automatic generation
diff --git a/sysdeps/or1k/fpu/libm-test-ulps-name b/sysdeps/or1k/fpu/libm-test-ulps-name
new file mode 100644
index 0000000000..7f72f7a873
--- /dev/null
+++ b/sysdeps/or1k/fpu/libm-test-ulps-name
@@ -0,0 +1 @@
+OpenRISC hard-float
diff --git a/sysdeps/or1k/fpu_control.h b/sysdeps/or1k/fpu_control.h
new file mode 100644
index 0000000000..4ac03db7a9
--- /dev/null
+++ b/sysdeps/or1k/fpu_control.h
@@ -0,0 +1,61 @@
+/* FPU control word bits. OpenRISC version.
+ Copyright (C) 2024 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 _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:
+
+ +-----------+----------------------------+-----+----+
+ | 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 |
+ +-----------+----------------------------+-----+----+
+
+ */
+
+# 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/sysdeps/or1k/libm-test-ulps-name b/sysdeps/or1k/libm-test-ulps-name
deleted file mode 100644
index 0af6591fd9..0000000000
--- a/sysdeps/or1k/libm-test-ulps-name
+++ /dev/null
@@ -1 +0,0 @@
-OpenRISC
diff --git a/sysdeps/or1k/math-tests-snan-payload.h b/sysdeps/or1k/math-tests-snan-payload.h
new file mode 100644
index 0000000000..62467a371c
--- /dev/null
+++ b/sysdeps/or1k/math-tests-snan-payload.h
@@ -0,0 +1,26 @@
+/* Configuration for math tests: sNaN payloads. OpenRISC version.
+ Copyright (C) 2024 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 OR1K_MATH_TESTS_SNAN_PAYLOAD_H
+#define OR1K_MATH_TESTS_SNAN_PAYLOAD_H 1
+
+/* OpenRISC floating-point instructions do not preserve NaN
+ payloads. */
+#define SNAN_TESTS_PRESERVE_PAYLOAD 0
+
+#endif /* math-tests-snan-payload.h */
diff --git a/sysdeps/or1k/math-tests-trap.h b/sysdeps/or1k/math-tests-trap.h
new file mode 100644
index 0000000000..a95b42d66d
--- /dev/null
+++ b/sysdeps/or1k/math-tests-trap.h
@@ -0,0 +1,27 @@
+/* Configuration for math tests: support for enabling exception traps.
+ OpenRISC version.
+ Copyright (C) 2024 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 OR1K_MATH_TESTS_TRAP_H
+#define OR1K_MATH_TESTS_TRAP_H 1
+
+#include <fenv.h>
+
+#define EXCEPTION_ENABLE_SUPPORTED(EXCEPT) ((EXCEPT) == 0)
+
+#endif /* math-tests-trap.h */
diff --git a/sysdeps/or1k/libm-test-ulps b/sysdeps/or1k/nofpu/libm-test-ulps
similarity index 100%
rename from sysdeps/or1k/libm-test-ulps
rename to sysdeps/or1k/nofpu/libm-test-ulps
diff --git a/sysdeps/or1k/nofpu/libm-test-ulps-name b/sysdeps/or1k/nofpu/libm-test-ulps-name
new file mode 100644
index 0000000000..76c66a0e53
--- /dev/null
+++ b/sysdeps/or1k/nofpu/libm-test-ulps-name
@@ -0,0 +1 @@
+OpenRISC soft-float
diff --git a/sysdeps/or1k/sfp-machine.h b/sysdeps/or1k/sfp-machine.h
index d17fd37730..e58e683969 100644
--- a/sysdeps/or1k/sfp-machine.h
+++ b/sysdeps/or1k/sfp-machine.h
@@ -36,7 +36,6 @@
#define _FP_MUL_MEAT_DW_Q(R,X,Y) \
_FP_MUL_MEAT_DW_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
-
#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y)
#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
@@ -90,4 +89,21 @@
#define FP_ROUNDMODE (_fpcsr & FP_RND_MASK)
+#ifdef __or1k_hard_float__
+#define FP_INIT_ROUNDMODE \
+do { \
+ __asm__ volatile ("l.mfspr %0,r0,20" : "=r" (_fpcsr)); \
+} while (0)
+
+#define FP_HANDLE_EXCEPTIONS \
+do { \
+ if (__builtin_expect (_fex, 0)) \
+ { \
+ _fpcsr &= ~FP_EX_ALL; \
+ _fpcsr |= _fex; \
+ __asm__ volatile ("l.mtspr r0,%0,20" : : "r" (_fpcsr)); \
+ } \
+} while (0)
+#endif /* __or1k_hard_float__ */
+
#define _FP_TININESS_AFTER_ROUNDING 0
diff --git a/sysdeps/unix/sysv/linux/or1k/getcontext.S b/sysdeps/unix/sysv/linux/or1k/getcontext.S
index a25b377bda..397b9e4c60 100644
--- a/sysdeps/unix/sysv/linux/or1k/getcontext.S
+++ b/sysdeps/unix/sysv/linux/or1k/getcontext.S
@@ -46,6 +46,12 @@ ENTRY(__getcontext)
l.sw (UCONTEXT_MCONTEXT + 28*4)(r3), r28
l.sw (UCONTEXT_MCONTEXT + 30*4)(r3), r30
+#ifdef __or1k_hard_float__
+ /* Store the floating point state. */
+ l.mfspr r4, r0, 20
+ l.sw (MCONTEXT_FPCSR)(r3), r4
+#endif /* __or1k_hard_float__ */
+
/* Get signal mask. */
/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
l.ori r6, r0, _NSIG8
diff --git a/sysdeps/unix/sysv/linux/or1k/setcontext.S b/sysdeps/unix/sysv/linux/or1k/setcontext.S
index d28a0ac0aa..4bf258b6f1 100644
--- a/sysdeps/unix/sysv/linux/or1k/setcontext.S
+++ b/sysdeps/unix/sysv/linux/or1k/setcontext.S
@@ -40,6 +40,12 @@ ENTRY(__setcontext)
l.bf 1f
l.nop
+#ifdef __or1k_hard_float__
+ /* Restore the floating point state. */
+ l.lwz r28, (MCONTEXT_FPCSR)(r30)
+ l.mtspr r0, r28, 20
+#endif /* __or1k_hard_float__ */
+
/* Restore argument registers, for the makecontext case. */
l.lwz r3, (UCONTEXT_MCONTEXT + 3*4)(r30)
l.lwz r4, (UCONTEXT_MCONTEXT + 4*4)(r30)
diff --git a/sysdeps/unix/sysv/linux/or1k/swapcontext.S b/sysdeps/unix/sysv/linux/or1k/swapcontext.S
index d09651a5b2..dfc788812c 100644
--- a/sysdeps/unix/sysv/linux/or1k/swapcontext.S
+++ b/sysdeps/unix/sysv/linux/or1k/swapcontext.S
@@ -45,6 +45,12 @@ ENTRY(__swapcontext)
l.sw (UCONTEXT_MCONTEXT + 28*4)(r3), r28
l.sw (UCONTEXT_MCONTEXT + 30*4)(r3), r30
+#ifdef __or1k_hard_float__
+ /* Store the floating point state. */
+ l.mfspr r6, r0, 20
+ l.sw (MCONTEXT_FPCSR)(r3), r6
+#endif /* __or1k_hard_float__ */
+
/* Store ucp to non-argument syscall preserved register. */
l.ori r30, r4, 0
@@ -82,6 +88,12 @@ ENTRY(__swapcontext)
l.bf 1f
l.nop
+#ifdef __or1k_hard_float__
+ /* Restore the floating point state. */
+ l.lwz r28, (MCONTEXT_FPCSR)(r30)
+ l.mtspr r0, r28, 20
+#endif /* __or1k_hard_float__ */
+
/* Restore argument registers, for the makecontext case. */
l.lwz r3, (UCONTEXT_MCONTEXT + 3*4)(r30)
l.lwz r4, (UCONTEXT_MCONTEXT + 4*4)(r30)
diff --git a/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h b/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h
index b17e919154..1b428592ee 100644
--- a/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h
+++ b/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h
@@ -38,6 +38,7 @@ typedef struct
unsigned long int __gprs[__NGREG];
unsigned long int __pc;
unsigned long int __sr;
+ unsigned long int __fpcsr;
} mcontext_t;
/* Userlevel context. */
diff --git a/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym b/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym
index a8d4db080f..45cd72527d 100644
--- a/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym
+++ b/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym
@@ -13,6 +13,7 @@ _NSIG8 (_NSIG / 8)
-- Offsets of the fields in the ucontext_t structure.
#define ucontext(member) offsetof (ucontext_t, member)
#define stack(member) ucontext (uc_stack.member)
+#define mcontext(member) ucontext (uc_mcontext.member)
UCONTEXT_LINK ucontext (uc_link)
UCONTEXT_STACK ucontext (uc_stack)
@@ -23,4 +24,6 @@ STACK_SP stack (ss_sp)
STACK_SIZE stack (ss_size)
STACK_FLAGS stack (ss_flags)
+MCONTEXT_FPCSR mcontext (__fpcsr)
+
UCONTEXT_SIZE sizeof (ucontext_t)
--
2.44.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] build-many-glibcs.py: Add openrisc hard float glibc variant
2024-03-29 7:40 [PATCH 0/2] OpenRISC glibc hard float support Stafford Horne
2024-03-29 7:40 ` [PATCH 1/2] or1k: Add " Stafford Horne
@ 2024-03-29 7:40 ` Stafford Horne
1 sibling, 0 replies; 8+ messages in thread
From: Stafford Horne @ 2024-03-29 7:40 UTC (permalink / raw)
To: GLIBC patches; +Cc: Linux OpenRISC, Stafford Horne
This adds the OpenRISC hard float glibc variant to the build many
script. We update the compiler for glibc to support hard-float
multilibs to allow us to use a single generic compiler for all glibc
variants, this requires updating the compiler name.
Tested and all builds are passing.
---
scripts/build-many-glibcs.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/scripts/build-many-glibcs.py b/scripts/build-many-glibcs.py
index ecc743e672..b3d4617f62 100755
--- a/scripts/build-many-glibcs.py
+++ b/scripts/build-many-glibcs.py
@@ -361,8 +361,9 @@ class Context(object):
os_name='linux-gnu')
self.add_config(arch='or1k',
os_name='linux-gnu',
- variant='soft',
- gcc_cfg=['--with-multilib-list=mcmov'])
+ gcc_cfg=['--with-multilib-list=mcmov,mhard-float'],
+ glibcs=[{'variant': 'soft'},
+ {'variant': 'hard', 'ccopts': '-mhard-float'}])
self.add_config(arch='powerpc',
os_name='linux-gnu',
gcc_cfg=['--disable-multilib', '--enable-secureplt'],
--
2.44.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] or1k: Add hard float support
2024-03-29 7:40 ` [PATCH 1/2] or1k: Add " Stafford Horne
@ 2024-04-16 14:04 ` Adhemerval Zanella Netto
2024-04-16 14:53 ` Richard Henderson
0 siblings, 1 reply; 8+ messages in thread
From: Adhemerval Zanella Netto @ 2024-04-16 14:04 UTC (permalink / raw)
To: Stafford Horne, GLIBC patches; +Cc: Linux OpenRISC
On 29/03/24 04:40, Stafford Horne wrote:
> This patch adds hardware floating point support to OpenRISC. Hardware
> floating point toolchain builds are enabled by passing the machine
> specific argument -mhard-float to gcc via CFLAGS. With this enabled GCC
> generates floating point instructions for single-precision operations
> and exports __or1k_hard_float__.
>
> There are 2 main parts to this patch.
>
> - Implement fenv functions to update the FPCSR flags keeping it in sync
> with sfp (software floating point).
> - Update machine context functions to store and restore the FPCSR
> state.
>
> *On mcontext_t ABI*
>
> This patch adds __fpcsr to mcontext_t. This is an ABI change, but also
> an ABI fix. The linux kernel has always defined padding in mcontext_t
> that was was missing from the glibc ABI. This unused space is has now
> been re-purposed for storing the FPCSR. This patch brings OpenRISC
> glibc in line with the Linux kernel and other libc implementation
> (musl).
>
> *Hard float ABI*
>
> The calling conventions and types do not change with OpenRISC hard-float
> so glibc hard-float builds continue to use dynamic linker
> /lib/ld-linux-or1k.so.1.
>
> *Testing*
>
> I have tested this patch both with hard-float and soft-float builds and
> the test results look fine to me. Results are as follows:
>
> Hard Float
>
> # failures
> FAIL: elf/tst-sprof-basic (Not checked, seen in other ports too)
> FAIL: gmon/tst-gmon-pie (GCC PIE bug)
> FAIL: gmon/tst-gmon-pie-gprof (GCC PIE bug)
> FAIL: nptl/tst-cond24 (timeouts)
> FAIL: nptl/tst-mutex10 (timeouts)
>
> # summary
> 5 FAIL
> 4279 PASS
> 83 UNSUPPORTED
> 16 XFAIL
> 2 XPASS
>
> # versions
> Toolchain: or1k-smhfpu-linux-gnu
> Compiler: gcc version 14.0.1 20240324 (experimental) [master r14-9649-gbb04a11418f] (GCC)
> Binutils: GNU assembler version 2.42.0 (or1k-smhfpu-linux-gnu) using BFD version (GNU Binutils) 2.42.0.20240324
> Linux: Linux buildroot 6.8.0-rc5-00003-g9158c6253560-dirty #78 SMP Fri Mar 22 16:56:54 GMT 2024 openrisc GNU/Linux
>
> Soft Float
>
> # failures
> FAIL: elf/tst-sprof-basic
> FAIL: gmon/tst-gmon-pie
> FAIL: gmon/tst-gmon-pie-gprof
> FAIL: iconvdata/iconv-test (timeout, passed when run manually)
> FAIL: nptl/tst-mutex10
>
> # summary
> 5 FAIL
> 4281 PASS
> 81 UNSUPPORTED
> 16 XFAIL
> 2 XPASS
>
> # versions
> Toolchain: or1k-smh-linux-gnu
> Compiler: gcc version 14.0.1 20240324 (experimental) [master r14-9649-gbb04a11418f] (GCC)
> Binutils: GNU assembler version 2.42.0 (or1k-smh-linux-gnu) using BFD version (GNU Binutils) 2.42.0.20240324
> Linux: Linux buildroot 6.8.0-rc5-00003-g9158c6253560-dirty #78 SMP Fri Mar 22 16:56:54 GMT 2024 openrisc GNU/Linux
>
> Documentation: https://raw.githubusercontent.com/openrisc/doc/master/openrisc-arch-1.4-rev0.pdf
If I understond correctly the OpenRISC hard-float ABIs uses the same
parameter passing ABI from soft-fp, similar of what ARM does with
-mfloat-abi=softfp. So the the shared objects built with/without
-mhard-float should be interoperable, assuming hardware has hard-fp
support.
However it does solve the potential problem a binary built with softfp
loading a hardfp built shared object, or even trying to link with a
static object with different ABI (and assuming a hardware without
hard-fp support).. It means that loader and ldconfig won't recognize
shared objects with different floating-point objects if they are installed
on the same system.
I don't think we have a strong policy regarding this, and historical
there were ABI variants that followed this (like powerpc soft and hard),
but most ABIs that support soft/hard floating-point usually advertise it
through ElfXX_Ehdr::e_flags.
For instance, with arm:
$ cat << EOF > lib.c
float foo_float (float x, float y)
{
return x + y;
}
double foo_double (double x, double y)
{
return x + y;
}
EOF
$ arm-glibc-linux-gnueabi-gcc -shared -o lib.so lib.c
$ readelf -h lib.so | grep Flags
Flags: 0x5000200, Version5 EABI, soft-float ABI
$ arm-glibc-linux-gnueabihf-gcc -shared -o lib.so lib.c
$ readelf -h lib.so | grep Flags
Flags: 0x5000400, Version5 EABI, hard-float ABI
This is similar for RISC-V rv64imac-lp64 vs rv64imafdc-lp64d, where the
former also defined a soft-float ABI (Flags 0x1) while the latter a
a hard-float (Flags: 0x5).
With a different ABI, it prevents possible issues with mcontext_t change
and related functions (for instance, when a hard-float binary runs on
a soft-fp built libc.so and start to see that the fpcsr is not save/restore).
And it seems that OpenRISCV also support a double-precision (-mdouble-float),
but I think it does not really require a distinction between single and
double (as RISC-V does and it would require a different ABI for support
it [1]).
[1] https://sourceware.org/bugzilla/show_bug.cgi?id=30963
> ---
> sysdeps/or1k/fpu/fclrexcpt.c | 44 +
> sysdeps/or1k/fpu/fegetenv.c | 32 +
> sysdeps/or1k/fpu/fegetmode.c | 29 +
> sysdeps/or1k/fpu/fegetround.c | 29 +
> sysdeps/or1k/fpu/feholdexcpt.c | 33 +
> sysdeps/or1k/fpu/fenv_private.h | 199 +++
> sysdeps/or1k/fpu/fesetenv.c | 32 +
> sysdeps/or1k/fpu/fesetexcept.c | 35 +
> sysdeps/or1k/fpu/fesetmode.c | 39 +
> sysdeps/or1k/fpu/fesetround.c | 39 +
> sysdeps/or1k/fpu/feupdateenv.c | 33 +
> sysdeps/or1k/fpu/fgetexcptflg.c | 29 +
> .../or1k/fpu/fix-fp-int-convert-overflow.h | 38 +
> sysdeps/or1k/fpu/fraiseexcpt.c | 67 +
> sysdeps/or1k/fpu/fsetexcptflg.c | 43 +
> sysdeps/or1k/fpu/ftestexcept.c | 27 +
> sysdeps/or1k/fpu/get-rounding-mode.h | 38 +
> sysdeps/or1k/fpu/libm-test-ulps | 1115 +++++++++++++++++
> sysdeps/or1k/fpu/libm-test-ulps-name | 1 +
> sysdeps/or1k/fpu_control.h | 61 +
> sysdeps/or1k/libm-test-ulps-name | 1 -
> sysdeps/or1k/math-tests-snan-payload.h | 26 +
> sysdeps/or1k/math-tests-trap.h | 27 +
> sysdeps/or1k/{ => nofpu}/libm-test-ulps | 0
> sysdeps/or1k/nofpu/libm-test-ulps-name | 1 +
> sysdeps/or1k/sfp-machine.h | 18 +-
> sysdeps/unix/sysv/linux/or1k/getcontext.S | 6 +
> sysdeps/unix/sysv/linux/or1k/setcontext.S | 6 +
> sysdeps/unix/sysv/linux/or1k/swapcontext.S | 12 +
> sysdeps/unix/sysv/linux/or1k/sys/ucontext.h | 1 +
> sysdeps/unix/sysv/linux/or1k/ucontext_i.sym | 3 +
> 31 files changed, 2062 insertions(+), 2 deletions(-)
> create mode 100644 sysdeps/or1k/fpu/fclrexcpt.c
> create mode 100644 sysdeps/or1k/fpu/fegetenv.c
> create mode 100644 sysdeps/or1k/fpu/fegetmode.c
> create mode 100644 sysdeps/or1k/fpu/fegetround.c
> create mode 100644 sysdeps/or1k/fpu/feholdexcpt.c
> create mode 100644 sysdeps/or1k/fpu/fenv_private.h
> create mode 100644 sysdeps/or1k/fpu/fesetenv.c
> create mode 100644 sysdeps/or1k/fpu/fesetexcept.c
> create mode 100644 sysdeps/or1k/fpu/fesetmode.c
> create mode 100644 sysdeps/or1k/fpu/fesetround.c
> create mode 100644 sysdeps/or1k/fpu/feupdateenv.c
> create mode 100644 sysdeps/or1k/fpu/fgetexcptflg.c
> create mode 100644 sysdeps/or1k/fpu/fix-fp-int-convert-overflow.h
> create mode 100644 sysdeps/or1k/fpu/fraiseexcpt.c
> create mode 100644 sysdeps/or1k/fpu/fsetexcptflg.c
> create mode 100644 sysdeps/or1k/fpu/ftestexcept.c
> create mode 100644 sysdeps/or1k/fpu/get-rounding-mode.h
> create mode 100644 sysdeps/or1k/fpu/libm-test-ulps
> create mode 100644 sysdeps/or1k/fpu/libm-test-ulps-name
> create mode 100644 sysdeps/or1k/fpu_control.h
> delete mode 100644 sysdeps/or1k/libm-test-ulps-name
> create mode 100644 sysdeps/or1k/math-tests-snan-payload.h
> create mode 100644 sysdeps/or1k/math-tests-trap.h
> rename sysdeps/or1k/{ => nofpu}/libm-test-ulps (100%)
> create mode 100644 sysdeps/or1k/nofpu/libm-test-ulps-name
>
> diff --git a/sysdeps/or1k/fpu/fclrexcpt.c b/sysdeps/or1k/fpu/fclrexcpt.c
> new file mode 100644
> index 0000000000..44224f9c24
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fclrexcpt.c
> @@ -0,0 +1,44 @@
> +/* Clear given exceptions in current floating-point environment.
> + OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#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;
> +}
> +libm_hidden_def (feclearexcept)
> diff --git a/sysdeps/or1k/fpu/fegetenv.c b/sysdeps/or1k/fpu/fegetenv.c
> new file mode 100644
> index 0000000000..70c75aa0bf
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fegetenv.c
> @@ -0,0 +1,32 @@
> +/* Store current floating-point environment.
> + Copyright (C) 2024 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/>. */
> +
> +#include <fenv.h>
> +#include <fpu_control.h>
> +
> +int
> +__fegetenv (fenv_t *envp)
> +{
> + _FPU_GETCW (*envp);
> +
> + /* Success. */
> + return 0;
> +}
> +libm_hidden_def (__fegetenv)
> +weak_alias (__fegetenv, fegetenv)
> +libm_hidden_weak (fegetenv)
> diff --git a/sysdeps/or1k/fpu/fegetmode.c b/sysdeps/or1k/fpu/fegetmode.c
> new file mode 100644
> index 0000000000..7fffd2e0b5
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fegetmode.c
> @@ -0,0 +1,29 @@
> +/* Store current floating-point control modes. OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#include <fenv.h>
> +#include <fpu_control.h>
> +
> +int
> +fegetmode (femode_t *modep)
> +{
> + _FPU_GETCW (*modep);
> +
> + /* Success. */
> + return 0;
> +}
> diff --git a/sysdeps/or1k/fpu/fegetround.c b/sysdeps/or1k/fpu/fegetround.c
> new file mode 100644
> index 0000000000..7e993b980a
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fegetround.c
> @@ -0,0 +1,29 @@
> +/* Return current rounding direction. OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#include <fenv.h>
> +#include <get-rounding-mode.h>
> +
> +int
> +__fegetround (void)
> +{
> + return get_rounding_mode ();
> +}
> +libm_hidden_def (__fegetround)
> +weak_alias (__fegetround, fegetround)
> +libm_hidden_weak (fegetround)
> diff --git a/sysdeps/or1k/fpu/feholdexcpt.c b/sysdeps/or1k/fpu/feholdexcpt.c
> new file mode 100644
> index 0000000000..0036e41ba2
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/feholdexcpt.c
> @@ -0,0 +1,33 @@
> +/* Store current floating-point environment and clear exceptions.
> + OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#include <fenv.h>
> +#include <fenv_private.h>
> +
> +int
> +__feholdexcept (fenv_t *envp)
> +{
> + libc_feholdexcept_or1k (envp);
> +
> + /* Success. */
> + return 0;
> +}
> +libm_hidden_def (__feholdexcept)
> +weak_alias (__feholdexcept, feholdexcept)
> +libm_hidden_weak (feholdexcept)
> diff --git a/sysdeps/or1k/fpu/fenv_private.h b/sysdeps/or1k/fpu/fenv_private.h
> new file mode 100644
> index 0000000000..4f401e7a5a
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fenv_private.h
> @@ -0,0 +1,199 @@
> +/* Private floating point rounding and exceptions handling. OpenRISC version.
> + Copyright (C) 2024 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 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 (__glibc_unlikely (cw != cw_new))
> + _FPU_SETCW (cw_new);
> +
> + /* Raise the exceptions if enabled in the new FP state. */
> + if (__glibc_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 (__glibc_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 (__glibc_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
> +
> +#include_next <fenv_private.h>
> +
> +#endif
> diff --git a/sysdeps/or1k/fpu/fesetenv.c b/sysdeps/or1k/fpu/fesetenv.c
> new file mode 100644
> index 0000000000..742ca719e0
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fesetenv.c
> @@ -0,0 +1,32 @@
> +/* Install given floating-point environment. OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#include <fenv.h>
> +#include <fenv_private.h>
> +
> +int
> +__fesetenv (const fenv_t *envp)
> +{
> + libc_fesetenv_or1k (envp);
> +
> + /* Success. */
> + return 0;
> +}
> +libm_hidden_def (__fesetenv)
> +weak_alias (__fesetenv, fesetenv)
> +libm_hidden_weak (fesetenv)
> diff --git a/sysdeps/or1k/fpu/fesetexcept.c b/sysdeps/or1k/fpu/fesetexcept.c
> new file mode 100644
> index 0000000000..43734eac18
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fesetexcept.c
> @@ -0,0 +1,35 @@
> +/* Set given exception flags. OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#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/sysdeps/or1k/fpu/fesetmode.c b/sysdeps/or1k/fpu/fesetmode.c
> new file mode 100644
> index 0000000000..d4556927ce
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fesetmode.c
> @@ -0,0 +1,39 @@
> +/* Install given floating-point control modes. OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#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/sysdeps/or1k/fpu/fesetround.c b/sysdeps/or1k/fpu/fesetround.c
> new file mode 100644
> index 0000000000..c2ada98f1b
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fesetround.c
> @@ -0,0 +1,39 @@
> +/* Set current rounding direction. OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#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. */
> + }
> +}
> +libm_hidden_def (__fesetround)
> +weak_alias (__fesetround, fesetround)
> +libm_hidden_weak (fesetround)
> diff --git a/sysdeps/or1k/fpu/feupdateenv.c b/sysdeps/or1k/fpu/feupdateenv.c
> new file mode 100644
> index 0000000000..3355bf6596
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/feupdateenv.c
> @@ -0,0 +1,33 @@
> +/* Install given floating-point environment and raise exceptions.
> + OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#include <fenv.h>
> +#include <fenv_private.h>
> +
> +int
> +__feupdateenv (const fenv_t *envp)
> +{
> + libc_feupdateenv_or1k (envp);
> +
> + /* Success. */
> + return 0;
> +}
> +libm_hidden_def (__feupdateenv)
> +weak_alias (__feupdateenv, feupdateenv)
> +libm_hidden_weak (feupdateenv)
> diff --git a/sysdeps/or1k/fpu/fgetexcptflg.c b/sysdeps/or1k/fpu/fgetexcptflg.c
> new file mode 100644
> index 0000000000..a954f6a2f1
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fgetexcptflg.c
> @@ -0,0 +1,29 @@
> +/* Store current state of exceptions. OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#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/sysdeps/or1k/fpu/fix-fp-int-convert-overflow.h b/sysdeps/or1k/fpu/fix-fp-int-convert-overflow.h
> new file mode 100644
> index 0000000000..78104289c0
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fix-fp-int-convert-overflow.h
> @@ -0,0 +1,38 @@
> +/* Fix for conversion of floating point to integer overflow. OpenRISC version.
> + Copyright (C) 2024 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 FIX_FP_INT_CONVERT_OVERFLOW_H
> +#define FIX_FP_INT_CONVERT_OVERFLOW_H 1
> +
> +/* The generic libgcc2.c conversions from floating point to long long
> + may not raise the correct exceptions on overflow (and may raise
> + spurious "inexact" exceptions even in non-overflow cases, see
> + <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59412>). */
> +#define FIX_FLT_LONG_CONVERT_OVERFLOW 0
> +#define FIX_FLT_LLONG_CONVERT_OVERFLOW 1
> +
> +#define FIX_DBL_LONG_CONVERT_OVERFLOW 0
> +#define FIX_DBL_LLONG_CONVERT_OVERFLOW 1
> +
> +#define FIX_LDBL_LONG_CONVERT_OVERFLOW 0
> +#define FIX_LDBL_LLONG_CONVERT_OVERFLOW 0
> +
> +#define FIX_FLT128_LONG_CONVERT_OVERFLOW 0
> +#define FIX_FLT128_LLONG_CONVERT_OVERFLOW 0
> +
> +#endif /* fix-fp-int-convert-overflow.h */
> diff --git a/sysdeps/or1k/fpu/fraiseexcpt.c b/sysdeps/or1k/fpu/fraiseexcpt.c
> new file mode 100644
> index 0000000000..bbacfd50bc
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fraiseexcpt.c
> @@ -0,0 +1,67 @@
> +/* Raise given exceptions. OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#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;
> +}
> +libm_hidden_def (__feraiseexcept)
> +weak_alias (__feraiseexcept, feraiseexcept)
> +libm_hidden_weak (feraiseexcept)
> diff --git a/sysdeps/or1k/fpu/fsetexcptflg.c b/sysdeps/or1k/fpu/fsetexcptflg.c
> new file mode 100644
> index 0000000000..c327e4c5d1
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/fsetexcptflg.c
> @@ -0,0 +1,43 @@
> +/* Set floating-point environment exception handling.
> + Copyright (C) 2024 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/>. */
> +
> +#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/sysdeps/or1k/fpu/ftestexcept.c b/sysdeps/or1k/fpu/ftestexcept.c
> new file mode 100644
> index 0000000000..59f06afa22
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/ftestexcept.c
> @@ -0,0 +1,27 @@
> +/* Test exception in current environment. OpenRISC version.
> + Copyright (C) 2024 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/>. */
> +
> +#include <fenv.h>
> +#include <fenv_private.h>
> +
> +int
> +fetestexcept (int excepts)
> +{
> + return libc_fetestexcept_or1k (excepts);
> +}
> +libm_hidden_def (fetestexcept)
> diff --git a/sysdeps/or1k/fpu/get-rounding-mode.h b/sysdeps/or1k/fpu/get-rounding-mode.h
> new file mode 100644
> index 0000000000..a66d553be8
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/get-rounding-mode.h
> @@ -0,0 +1,38 @@
> +/* Determine floating-point rounding mode within libc. OpenRISC version.
> +
> + Copyright (C) 2024 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 _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/sysdeps/or1k/fpu/libm-test-ulps b/sysdeps/or1k/fpu/libm-test-ulps
> new file mode 100644
> index 0000000000..948ec01cdc
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/libm-test-ulps
> @@ -0,0 +1,1115 @@
> +# Begin of automatic generation
> +
> +# Maximal error of functions:
> +Function: "acos":
> +double: 1
> +float: 1
> +
> +Function: "acos_downward":
> +double: 1
> +float: 1
> +
> +Function: "acos_towardzero":
> +double: 1
> +float: 1
> +
> +Function: "acos_upward":
> +double: 1
> +float: 1
> +
> +Function: "acosh":
> +double: 2
> +float: 2
> +
> +Function: "acosh_downward":
> +double: 2
> +float: 2
> +
> +Function: "acosh_towardzero":
> +double: 2
> +float: 2
> +
> +Function: "acosh_upward":
> +double: 2
> +float: 2
> +
> +Function: "asin":
> +double: 1
> +float: 1
> +
> +Function: "asin_downward":
> +double: 1
> +float: 1
> +
> +Function: "asin_towardzero":
> +double: 1
> +float: 1
> +
> +Function: "asin_upward":
> +double: 2
> +float: 1
> +
> +Function: "asinh":
> +double: 2
> +float: 2
> +
> +Function: "asinh_downward":
> +double: 3
> +float: 3
> +
> +Function: "asinh_towardzero":
> +double: 2
> +float: 2
> +
> +Function: "asinh_upward":
> +double: 3
> +float: 3
> +
> +Function: "atan":
> +double: 1
> +float: 1
> +
> +Function: "atan2":
> +float: 2
> +
> +Function: "atan2_downward":
> +double: 5
> +float: 2
> +
> +Function: "atan2_towardzero":
> +double: 5
> +float: 2
> +
> +Function: "atan2_upward":
> +double: 8
> +float: 2
> +
> +Function: "atan_downward":
> +double: 1
> +float: 2
> +
> +Function: "atan_towardzero":
> +double: 1
> +float: 1
> +
> +Function: "atan_upward":
> +double: 1
> +float: 2
> +
> +Function: "atanh":
> +double: 2
> +float: 2
> +
> +Function: "atanh_downward":
> +double: 3
> +float: 3
> +
> +Function: "atanh_towardzero":
> +double: 2
> +float: 2
> +
> +Function: "atanh_upward":
> +double: 3
> +float: 3
> +
> +Function: "cabs":
> +double: 1
> +
> +Function: "cabs_downward":
> +double: 1
> +
> +Function: "cabs_towardzero":
> +double: 1
> +
> +Function: "cabs_upward":
> +double: 1
> +
> +Function: Real part of "cacos":
> +double: 1
> +float: 2
> +
> +Function: Imaginary part of "cacos":
> +double: 2
> +float: 2
> +
> +Function: Real part of "cacos_downward":
> +double: 3
> +float: 2
> +
> +Function: Imaginary part of "cacos_downward":
> +double: 5
> +float: 3
> +
> +Function: Real part of "cacos_towardzero":
> +double: 3
> +float: 2
> +
> +Function: Imaginary part of "cacos_towardzero":
> +double: 4
> +float: 2
> +
> +Function: Real part of "cacos_upward":
> +double: 2
> +float: 2
> +
> +Function: Imaginary part of "cacos_upward":
> +double: 5
> +float: 7
> +
> +Function: Real part of "cacosh":
> +double: 2
> +float: 2
> +
> +Function: Imaginary part of "cacosh":
> +double: 1
> +float: 2
> +
> +Function: Real part of "cacosh_downward":
> +double: 4
> +float: 2
> +
> +Function: Imaginary part of "cacosh_downward":
> +double: 3
> +float: 3
> +
> +Function: Real part of "cacosh_towardzero":
> +double: 4
> +float: 2
> +
> +Function: Imaginary part of "cacosh_towardzero":
> +double: 3
> +float: 2
> +
> +Function: Real part of "cacosh_upward":
> +double: 4
> +float: 3
> +
> +Function: Imaginary part of "cacosh_upward":
> +double: 3
> +float: 2
> +
> +Function: "carg":
> +float: 1
> +
> +Function: "carg_downward":
> +double: 5
> +float: 2
> +
> +Function: "carg_towardzero":
> +double: 5
> +float: 2
> +
> +Function: "carg_upward":
> +double: 8
> +float: 2
> +
> +Function: Real part of "casin":
> +double: 1
> +float: 1
> +
> +Function: Imaginary part of "casin":
> +double: 2
> +float: 2
> +
> +Function: Real part of "casin_downward":
> +double: 3
> +float: 2
> +
> +Function: Imaginary part of "casin_downward":
> +double: 5
> +float: 3
> +
> +Function: Real part of "casin_towardzero":
> +double: 3
> +float: 1
> +
> +Function: Imaginary part of "casin_towardzero":
> +double: 4
> +float: 2
> +
> +Function: Real part of "casin_upward":
> +double: 3
> +float: 2
> +
> +Function: Imaginary part of "casin_upward":
> +double: 5
> +float: 7
> +
> +Function: Real part of "casinh":
> +double: 2
> +float: 2
> +
> +Function: Imaginary part of "casinh":
> +double: 1
> +float: 1
> +
> +Function: Real part of "casinh_downward":
> +double: 5
> +float: 3
> +
> +Function: Imaginary part of "casinh_downward":
> +double: 3
> +float: 2
> +
> +Function: Real part of "casinh_towardzero":
> +double: 4
> +float: 2
> +
> +Function: Imaginary part of "casinh_towardzero":
> +double: 3
> +float: 1
> +
> +Function: Real part of "casinh_upward":
> +double: 5
> +float: 7
> +
> +Function: Imaginary part of "casinh_upward":
> +double: 3
> +float: 2
> +
> +Function: Real part of "catan":
> +double: 1
> +float: 1
> +
> +Function: Imaginary part of "catan":
> +double: 1
> +float: 1
> +
> +Function: Real part of "catan_downward":
> +double: 1
> +float: 2
> +
> +Function: Imaginary part of "catan_downward":
> +double: 2
> +float: 2
> +
> +Function: Real part of "catan_towardzero":
> +double: 1
> +float: 2
> +
> +Function: Imaginary part of "catan_towardzero":
> +double: 2
> +float: 2
> +
> +Function: Real part of "catan_upward":
> +double: 2
> +float: 1
> +
> +Function: Imaginary part of "catan_upward":
> +double: 2
> +float: 2
> +
> +Function: Real part of "catanh":
> +double: 1
> +float: 1
> +
> +Function: Imaginary part of "catanh":
> +double: 1
> +float: 1
> +
> +Function: Real part of "catanh_downward":
> +double: 2
> +float: 2
> +
> +Function: Imaginary part of "catanh_downward":
> +double: 1
> +float: 2
> +
> +Function: Real part of "catanh_towardzero":
> +double: 2
> +float: 2
> +
> +Function: Imaginary part of "catanh_towardzero":
> +double: 1
> +float: 2
> +
> +Function: Real part of "catanh_upward":
> +double: 4
> +float: 4
> +
> +Function: Imaginary part of "catanh_upward":
> +double: 2
> +float: 1
> +
> +Function: "cbrt":
> +double: 4
> +float: 1
> +
> +Function: "cbrt_downward":
> +double: 4
> +float: 1
> +
> +Function: "cbrt_towardzero":
> +double: 3
> +float: 1
> +
> +Function: "cbrt_upward":
> +double: 5
> +float: 1
> +
> +Function: Real part of "ccos":
> +double: 1
> +float: 1
> +
> +Function: Imaginary part of "ccos":
> +double: 1
> +float: 1
> +
> +Function: Real part of "ccos_downward":
> +double: 3
> +float: 1
> +
> +Function: Imaginary part of "ccos_downward":
> +double: 3
> +float: 3
> +
> +Function: Real part of "ccos_towardzero":
> +double: 3
> +float: 2
> +
> +Function: Imaginary part of "ccos_towardzero":
> +double: 3
> +float: 3
> +
> +Function: Real part of "ccos_upward":
> +double: 1
> +float: 2
> +
> +Function: Imaginary part of "ccos_upward":
> +double: 2
> +float: 2
> +
> +Function: Real part of "ccosh":
> +double: 2
> +float: 1
> +
> +Function: Imaginary part of "ccosh":
> +double: 1
> +float: 1
> +
> +Function: Real part of "ccosh_downward":
> +double: 3
> +float: 2
> +
> +Function: Imaginary part of "ccosh_downward":
> +double: 3
> +float: 3
> +
> +Function: Real part of "ccosh_towardzero":
> +double: 3
> +float: 3
> +
> +Function: Imaginary part of "ccosh_towardzero":
> +double: 3
> +float: 3
> +
> +Function: Real part of "ccosh_upward":
> +double: 1
> +float: 2
> +
> +Function: Imaginary part of "ccosh_upward":
> +double: 2
> +float: 2
> +
> +Function: Real part of "cexp":
> +double: 2
> +float: 1
> +
> +Function: Imaginary part of "cexp":
> +double: 1
> +float: 2
> +
> +Function: Real part of "cexp_downward":
> +double: 4
> +float: 2
> +
> +Function: Imaginary part of "cexp_downward":
> +double: 3
> +float: 3
> +
> +Function: Real part of "cexp_towardzero":
> +double: 4
> +float: 2
> +
> +Function: Imaginary part of "cexp_towardzero":
> +double: 3
> +float: 3
> +
> +Function: Real part of "cexp_upward":
> +double: 2
> +float: 2
> +
> +Function: Imaginary part of "cexp_upward":
> +double: 3
> +float: 2
> +
> +Function: Real part of "clog":
> +double: 3
> +float: 3
> +
> +Function: Imaginary part of "clog":
> +double: 1
> +float: 1
> +
> +Function: Real part of "clog10":
> +double: 3
> +float: 4
> +
> +Function: Imaginary part of "clog10":
> +double: 2
> +float: 2
> +
> +Function: Real part of "clog10_downward":
> +double: 7
> +float: 5
> +
> +Function: Imaginary part of "clog10_downward":
> +double: 8
> +float: 4
> +
> +Function: Real part of "clog10_towardzero":
> +double: 5
> +float: 5
> +
> +Function: Imaginary part of "clog10_towardzero":
> +double: 8
> +float: 4
> +
> +Function: Real part of "clog10_upward":
> +double: 6
> +float: 5
> +
> +Function: Imaginary part of "clog10_upward":
> +double: 5
> +float: 4
> +
> +Function: Real part of "clog_downward":
> +double: 4
> +float: 3
> +
> +Function: Imaginary part of "clog_downward":
> +double: 5
> +float: 2
> +
> +Function: Real part of "clog_towardzero":
> +double: 8
> +float: 4
> +
> +Function: Imaginary part of "clog_towardzero":
> +double: 5
> +float: 3
> +
> +Function: Real part of "clog_upward":
> +double: 8
> +float: 3
> +
> +Function: Imaginary part of "clog_upward":
> +double: 8
> +float: 2
> +
> +Function: "cos":
> +double: 1
> +float: 1
> +
> +Function: "cos_downward":
> +double: 1
> +float: 1
> +
> +Function: "cos_towardzero":
> +double: 4
> +float: 1
> +
> +Function: "cos_upward":
> +double: 4
> +float: 1
> +
> +Function: "cosh":
> +double: 2
> +float: 2
> +
> +Function: "cosh_downward":
> +double: 3
> +float: 1
> +
> +Function: "cosh_towardzero":
> +double: 3
> +float: 1
> +
> +Function: "cosh_upward":
> +double: 2
> +float: 2
> +
> +Function: Real part of "cpow":
> +double: 2
> +float: 5
> +
> +Function: Imaginary part of "cpow":
> +float: 2
> +
> +Function: Real part of "cpow_downward":
> +double: 5
> +float: 8
> +
> +Function: Imaginary part of "cpow_downward":
> +double: 2
> +float: 2
> +
> +Function: Real part of "cpow_towardzero":
> +double: 5
> +float: 8
> +
> +Function: Imaginary part of "cpow_towardzero":
> +double: 2
> +float: 2
> +
> +Function: Real part of "cpow_upward":
> +double: 4
> +float: 1
> +
> +Function: Imaginary part of "cpow_upward":
> +double: 2
> +float: 2
> +
> +Function: Real part of "csin":
> +double: 1
> +float: 1
> +
> +Function: Real part of "csin_downward":
> +double: 3
> +float: 3
> +
> +Function: Imaginary part of "csin_downward":
> +double: 3
> +float: 1
> +
> +Function: Real part of "csin_towardzero":
> +double: 3
> +float: 3
> +
> +Function: Imaginary part of "csin_towardzero":
> +double: 3
> +float: 1
> +
> +Function: Real part of "csin_upward":
> +double: 2
> +float: 2
> +
> +Function: Imaginary part of "csin_upward":
> +double: 1
> +float: 2
> +
> +Function: Real part of "csinh":
> +float: 1
> +
> +Function: Imaginary part of "csinh":
> +double: 1
> +float: 1
> +
> +Function: Real part of "csinh_downward":
> +double: 3
> +float: 1
> +
> +Function: Imaginary part of "csinh_downward":
> +double: 3
> +float: 3
> +
> +Function: Real part of "csinh_towardzero":
> +double: 3
> +float: 2
> +
> +Function: Imaginary part of "csinh_towardzero":
> +double: 3
> +float: 3
> +
> +Function: Real part of "csinh_upward":
> +double: 1
> +float: 2
> +
> +Function: Imaginary part of "csinh_upward":
> +double: 2
> +float: 2
> +
> +Function: Real part of "csqrt":
> +double: 2
> +float: 2
> +
> +Function: Imaginary part of "csqrt":
> +double: 2
> +float: 2
> +
> +Function: Real part of "csqrt_downward":
> +double: 5
> +float: 4
> +
> +Function: Imaginary part of "csqrt_downward":
> +double: 4
> +float: 3
> +
> +Function: Real part of "csqrt_towardzero":
> +double: 4
> +float: 3
> +
> +Function: Imaginary part of "csqrt_towardzero":
> +double: 4
> +float: 3
> +
> +Function: Real part of "csqrt_upward":
> +double: 5
> +float: 4
> +
> +Function: Imaginary part of "csqrt_upward":
> +double: 3
> +float: 3
> +
> +Function: Real part of "ctan":
> +double: 1
> +float: 1
> +
> +Function: Imaginary part of "ctan":
> +double: 2
> +float: 2
> +
> +Function: Real part of "ctan_downward":
> +double: 6
> +float: 5
> +
> +Function: Imaginary part of "ctan_downward":
> +double: 3
> +float: 2
> +
> +Function: Real part of "ctan_towardzero":
> +double: 5
> +float: 3
> +
> +Function: Imaginary part of "ctan_towardzero":
> +double: 3
> +float: 2
> +
> +Function: Real part of "ctan_upward":
> +double: 2
> +float: 4
> +
> +Function: Imaginary part of "ctan_upward":
> +double: 2
> +float: 1
> +
> +Function: Real part of "ctanh":
> +double: 2
> +float: 2
> +
> +Function: Imaginary part of "ctanh":
> +double: 2
> +float: 2
> +
> +Function: Real part of "ctanh_downward":
> +double: 3
> +float: 2
> +
> +Function: Imaginary part of "ctanh_downward":
> +double: 6
> +float: 5
> +
> +Function: Real part of "ctanh_towardzero":
> +double: 3
> +float: 2
> +
> +Function: Imaginary part of "ctanh_towardzero":
> +double: 5
> +float: 3
> +
> +Function: Real part of "ctanh_upward":
> +double: 2
> +float: 2
> +
> +Function: Imaginary part of "ctanh_upward":
> +double: 2
> +float: 3
> +
> +Function: "erf":
> +double: 1
> +float: 1
> +
> +Function: "erf_downward":
> +double: 1
> +float: 1
> +
> +Function: "erf_towardzero":
> +double: 1
> +float: 1
> +
> +Function: "erf_upward":
> +double: 1
> +float: 1
> +
> +Function: "erfc":
> +double: 5
> +float: 3
> +
> +Function: "erfc_downward":
> +double: 5
> +float: 6
> +
> +Function: "erfc_towardzero":
> +double: 3
> +float: 4
> +
> +Function: "erfc_upward":
> +double: 5
> +float: 6
> +
> +Function: "exp":
> +double: 1
> +float: 1
> +
> +Function: "exp10":
> +double: 2
> +float: 1
> +
> +Function: "exp10_downward":
> +double: 3
> +float: 1
> +
> +Function: "exp10_towardzero":
> +double: 3
> +float: 1
> +
> +Function: "exp10_upward":
> +double: 2
> +float: 1
> +
> +Function: "exp2":
> +double: 1
> +
> +Function: "exp2_downward":
> +double: 1
> +
> +Function: "exp2_towardzero":
> +double: 1
> +
> +Function: "exp2_upward":
> +double: 1
> +float: 1
> +
> +Function: "exp_downward":
> +double: 1
> +float: 1
> +
> +Function: "exp_towardzero":
> +double: 1
> +float: 1
> +
> +Function: "exp_upward":
> +double: 1
> +float: 1
> +
> +Function: "expm1":
> +double: 1
> +float: 1
> +
> +Function: "expm1_downward":
> +double: 1
> +float: 1
> +
> +Function: "expm1_towardzero":
> +double: 1
> +float: 2
> +
> +Function: "expm1_upward":
> +double: 1
> +float: 1
> +
> +Function: "gamma":
> +double: 4
> +float: 7
> +
> +Function: "gamma_downward":
> +double: 7
> +float: 7
> +
> +Function: "gamma_towardzero":
> +double: 7
> +float: 7
> +
> +Function: "gamma_upward":
> +double: 5
> +float: 6
> +
> +Function: "hypot":
> +double: 1
> +float: 1
> +
> +Function: "hypot_downward":
> +double: 1
> +
> +Function: "hypot_towardzero":
> +double: 1
> +
> +Function: "hypot_upward":
> +double: 1
> +
> +Function: "j0":
> +double: 2
> +float: 9
> +
> +Function: "j0_downward":
> +double: 5
> +float: 9
> +
> +Function: "j0_towardzero":
> +double: 6
> +float: 9
> +
> +Function: "j0_upward":
> +double: 9
> +float: 9
> +
> +Function: "j1":
> +double: 4
> +float: 9
> +
> +Function: "j1_downward":
> +double: 5
> +float: 8
> +
> +Function: "j1_towardzero":
> +double: 4
> +float: 8
> +
> +Function: "j1_upward":
> +double: 9
> +float: 9
> +
> +Function: "jn":
> +double: 4
> +float: 4
> +
> +Function: "jn_downward":
> +double: 7
> +float: 9
> +
> +Function: "jn_towardzero":
> +double: 7
> +float: 9
> +
> +Function: "jn_upward":
> +double: 7
> +float: 9
> +
> +Function: "lgamma":
> +double: 4
> +float: 7
> +
> +Function: "lgamma_downward":
> +double: 7
> +float: 7
> +
> +Function: "lgamma_towardzero":
> +double: 7
> +float: 7
> +
> +Function: "lgamma_upward":
> +double: 5
> +float: 6
> +
> +Function: "log10":
> +double: 2
> +float: 2
> +
> +Function: "log10_downward":
> +double: 2
> +float: 3
> +
> +Function: "log10_towardzero":
> +double: 2
> +float: 1
> +
> +Function: "log10_upward":
> +double: 2
> +float: 2
> +
> +Function: "log1p":
> +double: 1
> +float: 1
> +
> +Function: "log1p_downward":
> +double: 2
> +float: 2
> +
> +Function: "log1p_towardzero":
> +double: 2
> +float: 2
> +
> +Function: "log1p_upward":
> +double: 2
> +float: 2
> +
> +Function: "log2":
> +float: 1
> +
> +Function: "log2_downward":
> +double: 1
> +
> +Function: "log2_towardzero":
> +double: 1
> +
> +Function: "log2_upward":
> +double: 1
> +
> +Function: "pow":
> +double: 1
> +
> +Function: "pow_downward":
> +double: 1
> +float: 1
> +
> +Function: "pow_towardzero":
> +double: 1
> +float: 1
> +
> +Function: "pow_upward":
> +double: 1
> +float: 1
> +
> +Function: "sin":
> +double: 1
> +float: 1
> +
> +Function: "sin_downward":
> +double: 4
> +float: 1
> +
> +Function: "sin_towardzero":
> +double: 3
> +float: 1
> +
> +Function: "sin_upward":
> +double: 7
> +float: 1
> +
> +Function: "sincos":
> +double: 1
> +
> +Function: "sincos_downward":
> +double: 1
> +float: 1
> +
> +Function: "sincos_towardzero":
> +double: 4
> +float: 1
> +
> +Function: "sincos_upward":
> +double: 1
> +float: 1
> +
> +Function: "sinh":
> +double: 2
> +float: 2
> +
> +Function: "sinh_downward":
> +double: 3
> +float: 3
> +
> +Function: "sinh_towardzero":
> +double: 3
> +float: 2
> +
> +Function: "sinh_upward":
> +double: 3
> +float: 3
> +
> +Function: "tan":
> +float: 1
> +
> +Function: "tan_downward":
> +double: 1
> +float: 2
> +
> +Function: "tan_towardzero":
> +double: 1
> +float: 1
> +
> +Function: "tan_upward":
> +double: 1
> +float: 1
> +
> +Function: "tanh":
> +double: 2
> +float: 2
> +
> +Function: "tanh_downward":
> +double: 3
> +float: 3
> +
> +Function: "tanh_towardzero":
> +double: 2
> +float: 2
> +
> +Function: "tanh_upward":
> +double: 3
> +float: 3
> +
> +Function: "tgamma":
> +double: 9
> +float: 8
> +
> +Function: "tgamma_downward":
> +double: 9
> +float: 9
> +
> +Function: "tgamma_towardzero":
> +double: 9
> +float: 8
> +
> +Function: "tgamma_upward":
> +double: 9
> +float: 8
> +
> +Function: "y0":
> +double: 3
> +float: 9
> +
> +Function: "y0_downward":
> +double: 3
> +float: 9
> +
> +Function: "y0_towardzero":
> +double: 4
> +float: 9
> +
> +Function: "y0_upward":
> +double: 3
> +float: 9
> +
> +Function: "y1":
> +double: 3
> +float: 9
> +
> +Function: "y1_downward":
> +double: 6
> +float: 9
> +
> +Function: "y1_towardzero":
> +double: 3
> +float: 9
> +
> +Function: "y1_upward":
> +double: 7
> +float: 9
> +
> +Function: "yn":
> +double: 3
> +float: 3
> +
> +Function: "yn_downward":
> +double: 6
> +float: 8
> +
> +Function: "yn_towardzero":
> +double: 8
> +float: 8
> +
> +Function: "yn_upward":
> +double: 8
> +float: 8
> +
> +# end of automatic generation
> diff --git a/sysdeps/or1k/fpu/libm-test-ulps-name b/sysdeps/or1k/fpu/libm-test-ulps-name
> new file mode 100644
> index 0000000000..7f72f7a873
> --- /dev/null
> +++ b/sysdeps/or1k/fpu/libm-test-ulps-name
> @@ -0,0 +1 @@
> +OpenRISC hard-float
> diff --git a/sysdeps/or1k/fpu_control.h b/sysdeps/or1k/fpu_control.h
> new file mode 100644
> index 0000000000..4ac03db7a9
> --- /dev/null
> +++ b/sysdeps/or1k/fpu_control.h
> @@ -0,0 +1,61 @@
> +/* FPU control word bits. OpenRISC version.
> + Copyright (C) 2024 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 _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:
> +
> + +-----------+----------------------------+-----+----+
> + | 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 |
> + +-----------+----------------------------+-----+----+
> +
> + */
> +
> +# 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/sysdeps/or1k/libm-test-ulps-name b/sysdeps/or1k/libm-test-ulps-name
> deleted file mode 100644
> index 0af6591fd9..0000000000
> --- a/sysdeps/or1k/libm-test-ulps-name
> +++ /dev/null
> @@ -1 +0,0 @@
> -OpenRISC
> diff --git a/sysdeps/or1k/math-tests-snan-payload.h b/sysdeps/or1k/math-tests-snan-payload.h
> new file mode 100644
> index 0000000000..62467a371c
> --- /dev/null
> +++ b/sysdeps/or1k/math-tests-snan-payload.h
> @@ -0,0 +1,26 @@
> +/* Configuration for math tests: sNaN payloads. OpenRISC version.
> + Copyright (C) 2024 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 OR1K_MATH_TESTS_SNAN_PAYLOAD_H
> +#define OR1K_MATH_TESTS_SNAN_PAYLOAD_H 1
> +
> +/* OpenRISC floating-point instructions do not preserve NaN
> + payloads. */
> +#define SNAN_TESTS_PRESERVE_PAYLOAD 0
> +
> +#endif /* math-tests-snan-payload.h */
> diff --git a/sysdeps/or1k/math-tests-trap.h b/sysdeps/or1k/math-tests-trap.h
> new file mode 100644
> index 0000000000..a95b42d66d
> --- /dev/null
> +++ b/sysdeps/or1k/math-tests-trap.h
> @@ -0,0 +1,27 @@
> +/* Configuration for math tests: support for enabling exception traps.
> + OpenRISC version.
> + Copyright (C) 2024 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 OR1K_MATH_TESTS_TRAP_H
> +#define OR1K_MATH_TESTS_TRAP_H 1
> +
> +#include <fenv.h>
> +
> +#define EXCEPTION_ENABLE_SUPPORTED(EXCEPT) ((EXCEPT) == 0)
> +
> +#endif /* math-tests-trap.h */
> diff --git a/sysdeps/or1k/libm-test-ulps b/sysdeps/or1k/nofpu/libm-test-ulps
> similarity index 100%
> rename from sysdeps/or1k/libm-test-ulps
> rename to sysdeps/or1k/nofpu/libm-test-ulps
> diff --git a/sysdeps/or1k/nofpu/libm-test-ulps-name b/sysdeps/or1k/nofpu/libm-test-ulps-name
> new file mode 100644
> index 0000000000..76c66a0e53
> --- /dev/null
> +++ b/sysdeps/or1k/nofpu/libm-test-ulps-name
> @@ -0,0 +1 @@
> +OpenRISC soft-float
> diff --git a/sysdeps/or1k/sfp-machine.h b/sysdeps/or1k/sfp-machine.h
> index d17fd37730..e58e683969 100644
> --- a/sysdeps/or1k/sfp-machine.h
> +++ b/sysdeps/or1k/sfp-machine.h
> @@ -36,7 +36,6 @@
> #define _FP_MUL_MEAT_DW_Q(R,X,Y) \
> _FP_MUL_MEAT_DW_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
>
> -
> #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y)
> #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
> #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
> @@ -90,4 +89,21 @@
>
> #define FP_ROUNDMODE (_fpcsr & FP_RND_MASK)
>
> +#ifdef __or1k_hard_float__
> +#define FP_INIT_ROUNDMODE \
> +do { \
> + __asm__ volatile ("l.mfspr %0,r0,20" : "=r" (_fpcsr)); \
> +} while (0)
> +
> +#define FP_HANDLE_EXCEPTIONS \
> +do { \
> + if (__builtin_expect (_fex, 0)) \
> + { \
> + _fpcsr &= ~FP_EX_ALL; \
> + _fpcsr |= _fex; \
> + __asm__ volatile ("l.mtspr r0,%0,20" : : "r" (_fpcsr)); \
> + } \
> +} while (0)
> +#endif /* __or1k_hard_float__ */
> +
> #define _FP_TININESS_AFTER_ROUNDING 0
> diff --git a/sysdeps/unix/sysv/linux/or1k/getcontext.S b/sysdeps/unix/sysv/linux/or1k/getcontext.S
> index a25b377bda..397b9e4c60 100644
> --- a/sysdeps/unix/sysv/linux/or1k/getcontext.S
> +++ b/sysdeps/unix/sysv/linux/or1k/getcontext.S
> @@ -46,6 +46,12 @@ ENTRY(__getcontext)
> l.sw (UCONTEXT_MCONTEXT + 28*4)(r3), r28
> l.sw (UCONTEXT_MCONTEXT + 30*4)(r3), r30
>
> +#ifdef __or1k_hard_float__
> + /* Store the floating point state. */
> + l.mfspr r4, r0, 20
> + l.sw (MCONTEXT_FPCSR)(r3), r4
> +#endif /* __or1k_hard_float__ */
> +
> /* Get signal mask. */
> /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
> l.ori r6, r0, _NSIG8
> diff --git a/sysdeps/unix/sysv/linux/or1k/setcontext.S b/sysdeps/unix/sysv/linux/or1k/setcontext.S
> index d28a0ac0aa..4bf258b6f1 100644
> --- a/sysdeps/unix/sysv/linux/or1k/setcontext.S
> +++ b/sysdeps/unix/sysv/linux/or1k/setcontext.S
> @@ -40,6 +40,12 @@ ENTRY(__setcontext)
> l.bf 1f
> l.nop
>
> +#ifdef __or1k_hard_float__
> + /* Restore the floating point state. */
> + l.lwz r28, (MCONTEXT_FPCSR)(r30)
> + l.mtspr r0, r28, 20
> +#endif /* __or1k_hard_float__ */
> +
> /* Restore argument registers, for the makecontext case. */
> l.lwz r3, (UCONTEXT_MCONTEXT + 3*4)(r30)
> l.lwz r4, (UCONTEXT_MCONTEXT + 4*4)(r30)
> diff --git a/sysdeps/unix/sysv/linux/or1k/swapcontext.S b/sysdeps/unix/sysv/linux/or1k/swapcontext.S
> index d09651a5b2..dfc788812c 100644
> --- a/sysdeps/unix/sysv/linux/or1k/swapcontext.S
> +++ b/sysdeps/unix/sysv/linux/or1k/swapcontext.S
> @@ -45,6 +45,12 @@ ENTRY(__swapcontext)
> l.sw (UCONTEXT_MCONTEXT + 28*4)(r3), r28
> l.sw (UCONTEXT_MCONTEXT + 30*4)(r3), r30
>
> +#ifdef __or1k_hard_float__
> + /* Store the floating point state. */
> + l.mfspr r6, r0, 20
> + l.sw (MCONTEXT_FPCSR)(r3), r6
> +#endif /* __or1k_hard_float__ */
> +
> /* Store ucp to non-argument syscall preserved register. */
> l.ori r30, r4, 0
>
> @@ -82,6 +88,12 @@ ENTRY(__swapcontext)
> l.bf 1f
> l.nop
>
> +#ifdef __or1k_hard_float__
> + /* Restore the floating point state. */
> + l.lwz r28, (MCONTEXT_FPCSR)(r30)
> + l.mtspr r0, r28, 20
> +#endif /* __or1k_hard_float__ */
> +
> /* Restore argument registers, for the makecontext case. */
> l.lwz r3, (UCONTEXT_MCONTEXT + 3*4)(r30)
> l.lwz r4, (UCONTEXT_MCONTEXT + 4*4)(r30)
> diff --git a/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h b/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h
> index b17e919154..1b428592ee 100644
> --- a/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h
> +++ b/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h
> @@ -38,6 +38,7 @@ typedef struct
> unsigned long int __gprs[__NGREG];
> unsigned long int __pc;
> unsigned long int __sr;
> + unsigned long int __fpcsr;
> } mcontext_t;
>
> /* Userlevel context. */
> diff --git a/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym b/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym
> index a8d4db080f..45cd72527d 100644
> --- a/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym
> +++ b/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym
> @@ -13,6 +13,7 @@ _NSIG8 (_NSIG / 8)
> -- Offsets of the fields in the ucontext_t structure.
> #define ucontext(member) offsetof (ucontext_t, member)
> #define stack(member) ucontext (uc_stack.member)
> +#define mcontext(member) ucontext (uc_mcontext.member)
>
> UCONTEXT_LINK ucontext (uc_link)
> UCONTEXT_STACK ucontext (uc_stack)
> @@ -23,4 +24,6 @@ STACK_SP stack (ss_sp)
> STACK_SIZE stack (ss_size)
> STACK_FLAGS stack (ss_flags)
>
> +MCONTEXT_FPCSR mcontext (__fpcsr)
> +
> UCONTEXT_SIZE sizeof (ucontext_t)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] or1k: Add hard float support
2024-04-16 14:04 ` Adhemerval Zanella Netto
@ 2024-04-16 14:53 ` Richard Henderson
2024-04-16 16:20 ` Adhemerval Zanella Netto
0 siblings, 1 reply; 8+ messages in thread
From: Richard Henderson @ 2024-04-16 14:53 UTC (permalink / raw)
To: Adhemerval Zanella Netto, Stafford Horne, GLIBC patches; +Cc: Linux OpenRISC
On 4/16/24 07:04, Adhemerval Zanella Netto wrote:
> If I understond correctly the OpenRISC hard-float ABIs uses the same
> parameter passing ABI from soft-fp, similar of what ARM does with
> -mfloat-abi=softfp. So the the shared objects built with/without
> -mhard-float should be interoperable, assuming hardware has hard-fp
> support.
>
> However it does solve the potential problem a binary built with softfp
> loading a hardfp built shared object, or even trying to link with a
> static object with different ABI (and assuming a hardware without
> hard-fp support).. It means that loader and ldconfig won't recognize
> shared objects with different floating-point objects if they are installed
> on the same system.
>
> I don't think we have a strong policy regarding this, and historical
> there were ABI variants that followed this (like powerpc soft and hard),
> but most ABIs that support soft/hard floating-point usually advertise it
> through ElfXX_Ehdr::e_flags.
>
> For instance, with arm:
>
> $ cat << EOF > lib.c
> float foo_float (float x, float y)
> {
> return x + y;
> }
>
> double foo_double (double x, double y)
> {
> return x + y;
> }
> EOF
> $ arm-glibc-linux-gnueabi-gcc -shared -o lib.so lib.c
> $ readelf -h lib.so | grep Flags
> Flags: 0x5000200, Version5 EABI, soft-float ABI
> $ arm-glibc-linux-gnueabihf-gcc -shared -o lib.so lib.c
> $ readelf -h lib.so | grep Flags
> Flags: 0x5000400, Version5 EABI, hard-float ABI
The typical reason for wanting an e_flags bit is because those architectures want the
parameter passing to change when floating-point registers are available.
But for OpenRISC there is no separate floating-point register set. All floating-point
operations use the same general-purpose registers as for all integer operations. So there
is no point in a new parameter passing ABI.
r~
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] or1k: Add hard float support
2024-04-16 14:53 ` Richard Henderson
@ 2024-04-16 16:20 ` Adhemerval Zanella Netto
2024-04-16 19:56 ` Richard Henderson
0 siblings, 1 reply; 8+ messages in thread
From: Adhemerval Zanella Netto @ 2024-04-16 16:20 UTC (permalink / raw)
To: Richard Henderson, Stafford Horne, GLIBC patches; +Cc: Linux OpenRISC
On 16/04/24 11:53, Richard Henderson wrote:
> On 4/16/24 07:04, Adhemerval Zanella Netto wrote:
>> If I understond correctly the OpenRISC hard-float ABIs uses the same
>> parameter passing ABI from soft-fp, similar of what ARM does with
>> -mfloat-abi=softfp. So the the shared objects built with/without
>> -mhard-float should be interoperable, assuming hardware has hard-fp
>> support.
>>
>> However it does solve the potential problem a binary built with softfp
>> loading a hardfp built shared object, or even trying to link with a
>> static object with different ABI (and assuming a hardware without
>> hard-fp support).. It means that loader and ldconfig won't recognize
>> shared objects with different floating-point objects if they are installed
>> on the same system.
>>
>> I don't think we have a strong policy regarding this, and historical
>> there were ABI variants that followed this (like powerpc soft and hard),
>> but most ABIs that support soft/hard floating-point usually advertise it
>> through ElfXX_Ehdr::e_flags.
>>
>> For instance, with arm:
>>
>> $ cat << EOF > lib.c
>> float foo_float (float x, float y)
>> {
>> return x + y;
>> }
>>
>> double foo_double (double x, double y)
>> {
>> return x + y;
>> }
>> EOF
>> $ arm-glibc-linux-gnueabi-gcc -shared -o lib.so lib.c
>> $ readelf -h lib.so | grep Flags
>> Flags: 0x5000200, Version5 EABI, soft-float ABI
>> $ arm-glibc-linux-gnueabihf-gcc -shared -o lib.so lib.c
>> $ readelf -h lib.so | grep Flags
>> Flags: 0x5000400, Version5 EABI, hard-float ABI
>
> The typical reason for wanting an e_flags bit is because those architectures want the parameter passing to change when floating-point registers are available.
>
> But for OpenRISC there is no separate floating-point register set. All floating-point operations use the same general-purpose registers as for all integer operations. So there is no point in a new parameter passing ABI.
Right, it was not clear from patch without dig into the ABI documen
itself. So the only thing I am not sure is the mcontext_t change.
Other ABIs added a symbol version to proper handle it, so maybe
OpenRISC would need something similar.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] or1k: Add hard float support
2024-04-16 16:20 ` Adhemerval Zanella Netto
@ 2024-04-16 19:56 ` Richard Henderson
2024-04-16 20:37 ` Stafford Horne
0 siblings, 1 reply; 8+ messages in thread
From: Richard Henderson @ 2024-04-16 19:56 UTC (permalink / raw)
To: Adhemerval Zanella Netto, Stafford Horne, GLIBC patches; +Cc: Linux OpenRISC
On 4/16/24 09:20, Adhemerval Zanella Netto wrote:
> Right, it was not clear from patch without dig into the ABI documen
> itself. So the only thing I am not sure is the mcontext_t change.
> Other ABIs added a symbol version to proper handle it, so maybe
> OpenRISC would need something similar.
Yes, I think some compat symbols are needed for getcontext et al, since the size of
ucontext_t changes.
I think softfloat glibc should populate the same field (with zero, since neither
exceptions nor rounding are supported).
r~
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] or1k: Add hard float support
2024-04-16 19:56 ` Richard Henderson
@ 2024-04-16 20:37 ` Stafford Horne
0 siblings, 0 replies; 8+ messages in thread
From: Stafford Horne @ 2024-04-16 20:37 UTC (permalink / raw)
To: Richard Henderson; +Cc: Adhemerval Zanella Netto, GLIBC patches, Linux OpenRISC
On Tue, Apr 16, 2024 at 12:56:11PM -0700, Richard Henderson wrote:
> On 4/16/24 09:20, Adhemerval Zanella Netto wrote:
> > Right, it was not clear from patch without dig into the ABI documen
> > itself. So the only thing I am not sure is the mcontext_t change.
> > Other ABIs added a symbol version to proper handle it, so maybe
> > OpenRISC would need something similar.
>
> Yes, I think some compat symbols are needed for getcontext et al, since the
> size of ucontext_t changes.
Just to re-iterate, the size of ucontext_t provided by the kernel never changed.
But the change of ucontext_t in glibc changing causes issues.
With the glibc ucontext_t size change there will be a problem with running
old compiled applications on new versions of glibc if this hard-float series is
added as is. I will see if we can add some versioning to ensure binaries will
not break when running on new glibc versions after this series.
> I think softfloat glibc should populate the same field (with zero, since
> neither exceptions nor rounding are supported).
Let me double check this is the case.
-Stafford
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2024-04-16 20:37 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-29 7:40 [PATCH 0/2] OpenRISC glibc hard float support Stafford Horne
2024-03-29 7:40 ` [PATCH 1/2] or1k: Add " Stafford Horne
2024-04-16 14:04 ` Adhemerval Zanella Netto
2024-04-16 14:53 ` Richard Henderson
2024-04-16 16:20 ` Adhemerval Zanella Netto
2024-04-16 19:56 ` Richard Henderson
2024-04-16 20:37 ` Stafford Horne
2024-03-29 7:40 ` [PATCH 2/2] build-many-glibcs.py: Add openrisc hard float glibc variant Stafford Horne
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).