diff options
Diffstat (limited to 'libm')
145 files changed, 5978 insertions, 25 deletions
diff --git a/libm/arc/Makefile.arch b/libm/arc/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/arc/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/arc/fclrexcpt.c b/libm/arc/fclrexcpt.c new file mode 100644 index 000000000..76631657d --- /dev/null +++ b/libm/arc/fclrexcpt.c @@ -0,0 +1,34 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ + unsigned int fpsr; + + _FPU_GETS (fpsr); + + /* Clear the relevant bits, FWE is preserved. */ + fpsr &= ~excepts; + + _FPU_SETS (fpsr); + + return 0; +} diff --git a/libm/arc/fegetenv.c b/libm/arc/fegetenv.c new file mode 100644 index 000000000..ad332c3e5 --- /dev/null +++ b/libm/arc/fegetenv.c @@ -0,0 +1,33 @@ +/* Store current floating-point environment. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetenv (fenv_t *envp) +{ + unsigned int fpcr; + unsigned int fpsr; + + _FPU_GETCW (fpcr); + _FPU_GETS (fpsr); + envp->__fpcr = fpcr; + envp->__fpsr = fpsr; + + return 0; +} diff --git a/libm/arc/fegetmode.c b/libm/arc/fegetmode.c new file mode 100644 index 000000000..e6aebbc87 --- /dev/null +++ b/libm/arc/fegetmode.c @@ -0,0 +1,30 @@ +/* Store current floating-point control modes. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ + unsigned int fpcr; + + _FPU_GETCW (fpcr); + *modep = fpcr; + + return 0; +} diff --git a/libm/arc/fegetround.c b/libm/arc/fegetround.c new file mode 100644 index 000000000..4dc476a7c --- /dev/null +++ b/libm/arc/fegetround.c @@ -0,0 +1,28 @@ +/* Return current rounding direction. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetround (void) +{ + unsigned int fpcr; + _FPU_GETCW (fpcr); + + return (fpcr >> __FPU_RND_SHIFT) & __FPU_RND_MASK; +} diff --git a/libm/arc/feholdexcpt.c b/libm/arc/feholdexcpt.c new file mode 100644 index 000000000..8febc7508 --- /dev/null +++ b/libm/arc/feholdexcpt.c @@ -0,0 +1,39 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feholdexcept (fenv_t *envp) +{ + unsigned int fpcr; + unsigned int fpsr; + + _FPU_GETCW (fpcr); + _FPU_GETS (fpsr); + + envp->__fpcr = fpcr; + envp->__fpsr = fpsr; + + fpsr &= ~FE_ALL_EXCEPT; + + _FPU_SETCW (fpcr); + _FPU_SETS (fpsr); + + return 0; +} diff --git a/libm/arc/fenv_private.h b/libm/arc/fenv_private.h new file mode 100644 index 000000000..5f74c5e13 --- /dev/null +++ b/libm/arc/fenv_private.h @@ -0,0 +1,326 @@ +/* Optimized inline fenv.h functions for libm. Generic version. + Copyright (C) 2011-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _FENV_PRIVATE_H +#define _FENV_PRIVATE_H 1 + +#include <fenv.h> +#include "get-rounding-mode.h" + +/* The standards only specify one variant of the fenv.h interfaces. + But at least for some architectures we can be more efficient if we + know what operations are going to be performed. Therefore we + define additional interfaces. By default they refer to the normal + interfaces. */ + +static __always_inline void +default_libc_feholdexcept (fenv_t *e) +{ + (void) feholdexcept (e); +} + +#ifndef libc_feholdexcept +# define libc_feholdexcept default_libc_feholdexcept +#endif +#ifndef libc_feholdexceptf +# define libc_feholdexceptf default_libc_feholdexcept +#endif +#ifndef libc_feholdexceptl +# define libc_feholdexceptl default_libc_feholdexcept +#endif + +static __always_inline void +default_libc_fesetround (int r) +{ + (void) fesetround (r); +} + +#ifndef libc_fesetround +# define libc_fesetround default_libc_fesetround +#endif +#ifndef libc_fesetroundf +# define libc_fesetroundf default_libc_fesetround +#endif +#ifndef libc_fesetroundl +# define libc_fesetroundl default_libc_fesetround +#endif + +static __always_inline void +default_libc_feholdexcept_setround (fenv_t *e, int r) +{ + feholdexcept (e); + fesetround (r); +} + +#ifndef libc_feholdexcept_setround +# define libc_feholdexcept_setround default_libc_feholdexcept_setround +#endif +#ifndef libc_feholdexcept_setroundf +# define libc_feholdexcept_setroundf default_libc_feholdexcept_setround +#endif +#ifndef libc_feholdexcept_setroundl +# define libc_feholdexcept_setroundl default_libc_feholdexcept_setround +#endif + +#ifndef libc_feholdsetround_53bit +# define libc_feholdsetround_53bit libc_feholdsetround +#endif + +#ifndef libc_fetestexcept +# define libc_fetestexcept fetestexcept +#endif +#ifndef libc_fetestexceptf +# define libc_fetestexceptf fetestexcept +#endif +#ifndef libc_fetestexceptl +# define libc_fetestexceptl fetestexcept +#endif + +static __always_inline void +default_libc_fesetenv (fenv_t *e) +{ + (void) fesetenv (e); +} + +#ifndef libc_fesetenv +# define libc_fesetenv default_libc_fesetenv +#endif +#ifndef libc_fesetenvf +# define libc_fesetenvf default_libc_fesetenv +#endif +#ifndef libc_fesetenvl +# define libc_fesetenvl default_libc_fesetenv +#endif + +static __always_inline void +default_libc_feupdateenv (fenv_t *e) +{ + (void) feupdateenv (e); +} + +#ifndef libc_feupdateenv +# define libc_feupdateenv default_libc_feupdateenv +#endif +#ifndef libc_feupdateenvf +# define libc_feupdateenvf default_libc_feupdateenv +#endif +#ifndef libc_feupdateenvl +# define libc_feupdateenvl default_libc_feupdateenv +#endif + +#ifndef libc_feresetround_53bit +# define libc_feresetround_53bit libc_feresetround +#endif + +static __always_inline int +default_libc_feupdateenv_test (fenv_t *e, int ex) +{ + int ret = fetestexcept (ex); + feupdateenv (e); + return ret; +} + +#ifndef libc_feupdateenv_test +# define libc_feupdateenv_test default_libc_feupdateenv_test +#endif +#ifndef libc_feupdateenv_testf +# define libc_feupdateenv_testf default_libc_feupdateenv_test +#endif +#ifndef libc_feupdateenv_testl +# define libc_feupdateenv_testl default_libc_feupdateenv_test +#endif + +/* Save and set the rounding mode. The use of fenv_t to store the old mode + allows a target-specific version of this function to avoid converting the + rounding mode from the fpu format. By default we have no choice but to + manipulate the entire env. */ + +#ifndef libc_feholdsetround +# define libc_feholdsetround libc_feholdexcept_setround +#endif +#ifndef libc_feholdsetroundf +# define libc_feholdsetroundf libc_feholdexcept_setroundf +#endif +#ifndef libc_feholdsetroundl +# define libc_feholdsetroundl libc_feholdexcept_setroundl +#endif + +/* ... and the reverse. */ + +#ifndef libc_feresetround +# define libc_feresetround libc_feupdateenv +#endif +#ifndef libc_feresetroundf +# define libc_feresetroundf libc_feupdateenvf +#endif +#ifndef libc_feresetroundl +# define libc_feresetroundl libc_feupdateenvl +#endif + +/* ... and a version that also discards exceptions. */ + +#ifndef libc_feresetround_noex +# define libc_feresetround_noex libc_fesetenv +#endif +#ifndef libc_feresetround_noexf +# define libc_feresetround_noexf libc_fesetenvf +#endif +#ifndef libc_feresetround_noexl +# define libc_feresetround_noexl libc_fesetenvl +#endif + +#ifndef HAVE_RM_CTX +# define HAVE_RM_CTX 0 +#endif + + +/* Default implementation using standard fenv functions. + Avoid unnecessary rounding mode changes by first checking the + current rounding mode. Note the use of unlikely is + important for performance. */ + +static __always_inline void +default_libc_feholdsetround_ctx (struct rm_ctx *ctx, int round) +{ + ctx->updated_status = false; + + /* Update rounding mode only if different. */ + if (unlikely (round != get_rounding_mode ())) + { + ctx->updated_status = true; + fegetenv (&ctx->env); + fesetround (round); + } +} + +static __always_inline void +default_libc_feresetround_ctx (struct rm_ctx *ctx) +{ + /* Restore the rounding mode if updated. */ + if (unlikely (ctx->updated_status)) + feupdateenv (&ctx->env); +} + +static __always_inline void +default_libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round) +{ + /* Save exception flags and rounding mode, and disable exception + traps. */ + feholdexcept (&ctx->env); + + /* Update rounding mode only if different. */ + if (unlikely (round != get_rounding_mode ())) + fesetround (round); +} + +static __always_inline void +default_libc_feresetround_noex_ctx (struct rm_ctx *ctx) +{ + /* Restore exception flags and rounding mode. */ + fesetenv (&ctx->env); +} + +#if HAVE_RM_CTX +/* Set/Restore Rounding Modes only when necessary. If defined, these functions + set/restore floating point state only if the state needed within the lexical + block is different from the current state. This saves a lot of time when + the floating point unit is much slower than the fixed point units. */ + +# ifndef libc_feholdsetround_noex_ctx +# define libc_feholdsetround_noex_ctx libc_feholdsetround_ctx +# endif +# ifndef libc_feholdsetround_noexf_ctx +# define libc_feholdsetround_noexf_ctx libc_feholdsetroundf_ctx +# endif +# ifndef libc_feholdsetround_noexl_ctx +# define libc_feholdsetround_noexl_ctx libc_feholdsetroundl_ctx +# endif + +# ifndef libc_feresetround_noex_ctx +# define libc_feresetround_noex_ctx libc_fesetenv_ctx +# endif +# ifndef libc_feresetround_noexf_ctx +# define libc_feresetround_noexf_ctx libc_fesetenvf_ctx +# endif +# ifndef libc_feresetround_noexl_ctx +# define libc_feresetround_noexl_ctx libc_fesetenvl_ctx +# endif + +#else + +# define libc_feholdsetround_ctx default_libc_feholdsetround_ctx +# define libc_feresetround_ctx default_libc_feresetround_ctx +# define libc_feholdsetround_noex_ctx default_libc_feholdsetround_noex_ctx +# define libc_feresetround_noex_ctx default_libc_feresetround_noex_ctx + +# define libc_feholdsetroundf_ctx libc_feholdsetround_ctx +# define libc_feholdsetroundl_ctx libc_feholdsetround_ctx +# define libc_feresetroundf_ctx libc_feresetround_ctx +# define libc_feresetroundl_ctx libc_feresetround_ctx + +# define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ctx +# define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ctx +# define libc_feresetround_noexf_ctx libc_feresetround_noex_ctx +# define libc_feresetround_noexl_ctx libc_feresetround_noex_ctx + +#endif + +#ifndef libc_feholdsetround_53bit_ctx +# define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx +#endif +#ifndef libc_feresetround_53bit_ctx +# define libc_feresetround_53bit_ctx libc_feresetround_ctx +#endif + +#define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \ + struct rm_ctx ctx __attribute__((cleanup (CLEANUPFUNC ## _ctx))); \ + ROUNDFUNC ## _ctx (&ctx, (RM)) + +/* Set the rounding mode within a lexical block. Restore the rounding mode to + the value at the start of the block. The exception mode must be preserved. + Exceptions raised within the block must be set in the exception flags. + Non-stop mode may be enabled inside the block. */ + +#define SET_RESTORE_ROUND(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround) +#define SET_RESTORE_ROUNDF(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetroundf) +#define SET_RESTORE_ROUNDL(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetroundl) + +/* Set the rounding mode within a lexical block. Restore the rounding mode to + the value at the start of the block. The exception mode must be preserved. + Exceptions raised within the block must be discarded, and exception flags + are restored to the value at the start of the block. + Non-stop mode must be enabled inside the block. */ + +#define SET_RESTORE_ROUND_NOEX(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noex, \ + libc_feresetround_noex) +#define SET_RESTORE_ROUND_NOEXF(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexf, \ + libc_feresetround_noexf) +#define SET_RESTORE_ROUND_NOEXL(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexl, \ + libc_feresetround_noexl) + +/* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits. */ +#define SET_RESTORE_ROUND_53BIT(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_53bit, \ + libc_feresetround_53bit) + +#endif /* fenv_private.h. */ diff --git a/libm/arc/fesetenv.c b/libm/arc/fesetenv.c new file mode 100644 index 000000000..59ec3b722 --- /dev/null +++ b/libm/arc/fesetenv.c @@ -0,0 +1,44 @@ +/* Install given floating-point environment (does not raise exceptions). + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fpu_control.h" + +int +fesetenv (const fenv_t *envp) +{ + unsigned int fpcr; + unsigned int fpsr; + + if (envp == FE_DFL_ENV) + { + fpcr = _FPU_DEFAULT; + fpsr = _FPU_FPSR_DEFAULT; + } + else + { + /* No need to mask out reserved bits as they are IoW. */ + fpcr = envp->__fpcr; + fpsr = envp->__fpsr; + } + + _FPU_SETCW (fpcr); + _FPU_SETS (fpsr); + + /* Success. */ + return 0; +} diff --git a/libm/arc/fesetexcept.c b/libm/arc/fesetexcept.c new file mode 100644 index 000000000..3756a2e09 --- /dev/null +++ b/libm/arc/fesetexcept.c @@ -0,0 +1,31 @@ +/* Set given exception flags. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fpu_control.h" + +int +fesetexcept (int excepts) +{ + unsigned int fpsr; + + _FPU_GETS (fpsr); + fpsr |= excepts; + _FPU_SETS (fpsr); + + return 0; +} diff --git a/libm/arc/fesetmode.c b/libm/arc/fesetmode.c new file mode 100644 index 000000000..1fc2bdf12 --- /dev/null +++ b/libm/arc/fesetmode.c @@ -0,0 +1,39 @@ +/* Install given floating-point control modes. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fpu_control.h" + +int +fesetmode (const femode_t *modep) +{ + unsigned int fpcr; + + if (modep == FE_DFL_MODE) + { + fpcr = _FPU_DEFAULT; + } + else + { + /* No need to mask out reserved bits as they are IoW. */ + fpcr = *modep; + } + + _FPU_SETCW (fpcr); + + return 0; +} diff --git a/libm/arc/fesetround.c b/libm/arc/fesetround.c new file mode 100644 index 000000000..e156e9cf5 --- /dev/null +++ b/libm/arc/fesetround.c @@ -0,0 +1,36 @@ +/* Set current rounding direction. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetround (int round) +{ + unsigned int fpcr; + + _FPU_GETCW (fpcr); + + if (((fpcr >> __FPU_RND_SHIFT) & __FPU_RND_MASK) != round) + { + fpcr &= ~(__FPU_RND_MASK << __FPU_RND_SHIFT); + fpcr |= (round & __FPU_RND_MASK) << __FPU_RND_SHIFT; + _FPU_SETCW (fpcr); + } + + return 0; +} diff --git a/libm/arc/feupdateenv.c b/libm/arc/feupdateenv.c new file mode 100644 index 000000000..6a59b2bfe --- /dev/null +++ b/libm/arc/feupdateenv.c @@ -0,0 +1,47 @@ +/* Install given floating-point environment and raise exceptions, + without clearing currently raised exceptions. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fpu_control.h" + +int +feupdateenv (const fenv_t *envp) +{ + unsigned int fpcr; + unsigned int fpsr; + + _FPU_GETS (fpsr); + + if (envp == FE_DFL_ENV) + { + fpcr = _FPU_DEFAULT; + } + else + { + fpcr = envp->__fpcr; + + /* currently raised exceptions need to be preserved. */ + fpsr |= envp->__fpsr; + } + + _FPU_SETCW (fpcr); + _FPU_SETS (fpsr); + + /* Success. */ + return 0; +} diff --git a/libm/arc/fgetexcptflg.c b/libm/arc/fgetexcptflg.c new file mode 100644 index 000000000..03f97f99f --- /dev/null +++ b/libm/arc/fgetexcptflg.c @@ -0,0 +1,30 @@ +/* Store current representation for exceptions, ARC version. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + unsigned int fpsr; + + _FPU_GETS (fpsr); + *flagp = fpsr & excepts; + + return 0; +} diff --git a/libm/arc/fraiseexcpt.c b/libm/arc/fraiseexcpt.c new file mode 100644 index 000000000..2ff5e0269 --- /dev/null +++ b/libm/arc/fraiseexcpt.c @@ -0,0 +1,35 @@ +/* Raise given exceptions. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include <float.h> +#include <math.h> + +int +feraiseexcept (int excepts) +{ + unsigned int fpsr; + + /* currently raised exceptions are not cleared. */ + _FPU_GETS (fpsr); + fpsr |= excepts; + + _FPU_SETS (fpsr); + + return 0; +} diff --git a/libm/arc/fsetexcptflg.c b/libm/arc/fsetexcptflg.c new file mode 100644 index 000000000..97ff20fff --- /dev/null +++ b/libm/arc/fsetexcptflg.c @@ -0,0 +1,37 @@ +/* Set floating-point environment exception handling, ARC version. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + unsigned int fpsr; + + _FPU_GETS (fpsr); + + /* Clear the bits first. */ + fpsr &= ~excepts; + + /* Now set those bits, copying them over from @flagp. */ + fpsr |= *flagp & excepts; + + _FPU_SETS (fpsr); + + return 0; +} diff --git a/libm/arc/ftestexcept.c b/libm/arc/ftestexcept.c new file mode 100644 index 000000000..ccc557e5e --- /dev/null +++ b/libm/arc/ftestexcept.c @@ -0,0 +1,31 @@ +/* Test exception in current environment. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include "fenv_private.h" +#include <stdio.h> + +int +fetestexcept (int excepts) +{ + unsigned int fpsr; + + _FPU_GETS (fpsr); + + return fpsr & excepts; +} diff --git a/libm/arc/get-rounding-mode.h b/libm/arc/get-rounding-mode.h new file mode 100644 index 000000000..d1bf3475d --- /dev/null +++ b/libm/arc/get-rounding-mode.h @@ -0,0 +1,37 @@ +/* Determine floating-point rounding mode within libc. ARC version. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _ARC_GET_ROUNDING_MODE_H +#define _ARC_GET_ROUNDING_MODE_H 1 + +#include <fenv.h> +#include <fpu_control.h> + +static inline int +get_rounding_mode (void) +{ +#if defined(__ARC_FPU_SP__) || defined(__ARC_FPU_DP__) + unsigned int fpcr; + _FPU_GETCW (fpcr); + + return (fpcr >> __FPU_RND_SHIFT) & __FPU_RND_MASK; +#else + return FE_TONEAREST; +#endif +} + +#endif /* get-rounding-mode.h */ diff --git a/libm/csky/Makefile.arch b/libm/csky/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/csky/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/csky/fclrexcpt.c b/libm/csky/fclrexcpt.c new file mode 100644 index 000000000..8f8acef16 --- /dev/null +++ b/libm/csky/fclrexcpt.c @@ -0,0 +1,40 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_libc.h" +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ + int fpsr; + + /* Mask out unsupported bits/exceptions. */ + excepts &= FE_ALL_EXCEPT; + + /* Read the complete control word. */ + _FPU_GETFPSR (fpsr); + + /* Clear the relevant bits. */ + fpsr &= ~(excepts | (excepts << CAUSE_SHIFT)); + + /* Put the new data in effect. */ + _FPU_SETFPSR (fpsr); + + return 0; +} diff --git a/libm/csky/fedisblxcpt.c b/libm/csky/fedisblxcpt.c new file mode 100644 index 000000000..e518968ab --- /dev/null +++ b/libm/csky/fedisblxcpt.c @@ -0,0 +1,40 @@ +/* Disable floating-point exceptions. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_libc.h" +#include <fpu_control.h> + +int +fedisableexcept (int excepts) +{ + unsigned int new_exc, old_exc; + + /* Get the current control word. */ + _FPU_GETCW (new_exc); + + old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT; + + /* Get the except disable mask. */ + excepts &= FE_ALL_EXCEPT; + new_exc &= ~(excepts << ENABLE_SHIFT); + + /* Put the new data in effect. */ + _FPU_SETCW (new_exc); + + return old_exc; +} diff --git a/libm/csky/feenablxcpt.c b/libm/csky/feenablxcpt.c new file mode 100644 index 000000000..90c495080 --- /dev/null +++ b/libm/csky/feenablxcpt.c @@ -0,0 +1,39 @@ +/* Enable floating-point exceptions. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_libc.h" +#include <fpu_control.h> + +int +feenableexcept (int excepts) +{ + unsigned int new_exc, old_exc; + + /* Get the current control word. */ + _FPU_GETCW (new_exc); + + old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT; + + excepts &= FE_ALL_EXCEPT; + + new_exc |= excepts << ENABLE_SHIFT; + + _FPU_SETCW (new_exc); + + return old_exc; +} diff --git a/libm/csky/fegetenv.c b/libm/csky/fegetenv.c new file mode 100644 index 000000000..d98982fc1 --- /dev/null +++ b/libm/csky/fegetenv.c @@ -0,0 +1,33 @@ +/* Store current floating-point environment. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetenv (fenv_t *envp) +{ + unsigned int fpcr; + unsigned int fpsr; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); + envp->__fpcr = fpcr; + envp->__fpsr = fpsr; + + return 0; +} diff --git a/libm/csky/fegetexcept.c b/libm/csky/fegetexcept.c new file mode 100644 index 000000000..339f35923 --- /dev/null +++ b/libm/csky/fegetexcept.c @@ -0,0 +1,31 @@ +/* Get enabled floating-point exceptions. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_libc.h" +#include <fpu_control.h> + +int +fegetexcept (void) +{ + unsigned int exc; + + /* Get the current control word. */ + _FPU_GETCW (exc); + + return (exc & ENABLE_MASK) >> ENABLE_SHIFT; +} diff --git a/libm/csky/fegetmode.c b/libm/csky/fegetmode.c new file mode 100644 index 000000000..09d8282dd --- /dev/null +++ b/libm/csky/fegetmode.c @@ -0,0 +1,27 @@ +/* Store current floating-point control modes. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ + _FPU_GETCW (*modep); + + return 0; +} diff --git a/libm/csky/fegetround.c b/libm/csky/fegetround.c new file mode 100644 index 000000000..e68775af3 --- /dev/null +++ b/libm/csky/fegetround.c @@ -0,0 +1,30 @@ +/* Return current rounding direction. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetround (void) +{ + unsigned int cw; + + /* Get control word. */ + _FPU_GETCW (cw); + + return cw & __FE_ROUND_MASK; +} diff --git a/libm/csky/feholdexcpt.c b/libm/csky/feholdexcpt.c new file mode 100644 index 000000000..456af5eb1 --- /dev/null +++ b/libm/csky/feholdexcpt.c @@ -0,0 +1,30 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include "fenv_libc.h" +#include "fenv_private.h" + +#include <stdio.h> + +int +feholdexcept (fenv_t *envp) +{ + libc_feholdexcept_vfp (envp); + return 0; +} diff --git a/libm/csky/fenv_libc.h b/libm/csky/fenv_libc.h new file mode 100644 index 000000000..44e89812d --- /dev/null +++ b/libm/csky/fenv_libc.h @@ -0,0 +1,29 @@ +/* fpu registers environment. C-SKY version. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _FENV_LIBC_H +#define _FENV_LIBC_H 1 + +/* Mask for enabling exceptions and for the CAUSE bits. */ +#define ENABLE_MASK 0x0003FU +#define CAUSE_MASK 0x3F000U + +/* Shift for FE_* flags to get up to the ENABLE bits and the CAUSE bits. */ +#define ENABLE_SHIFT 0 +#define CAUSE_SHIFT 8 + +#endif /* fenv_libc.h */ diff --git a/libm/csky/fenv_private.h b/libm/csky/fenv_private.h new file mode 100644 index 000000000..f0f48a88a --- /dev/null +++ b/libm/csky/fenv_private.h @@ -0,0 +1,277 @@ +/* Private floating point rounding and exceptions handling. C-SKY version. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef CSKY_FENV_PRIVATE_H +#define CSKY_FENV_PRIVATE_H 1 + +#include <fenv.h> +#include <fpu_control.h> +#include "fenv_libc.h" + +static __always_inline void +libc_feholdexcept_vfp (fenv_t *envp) +{ + fpu_control_t fpsr, fpcr; + + _FPU_GETCW (fpcr); + envp->__fpcr = fpcr; + + _FPU_GETFPSR (fpsr); + envp->__fpsr = fpsr; + + /* Now set all exceptions to non-stop. */ + fpcr &= ~FE_ALL_EXCEPT; + + /* And clear all exception flags. */ + fpsr &= ~(FE_ALL_EXCEPT << CAUSE_SHIFT); + + _FPU_SETFPSR (fpsr); + + _FPU_SETCW (fpcr); +} + +static __always_inline void +libc_fesetround_vfp (int round) +{ + fpu_control_t fpcr; + + _FPU_GETCW (fpcr); + + /* Set new rounding mode if different. */ + if (unlikely ((fpcr & FE_DOWNWARD) != round)) + _FPU_SETCW ((fpcr & ~FE_DOWNWARD) | round); +} + +static __always_inline void +libc_feholdexcept_setround_vfp (fenv_t *envp, int round) +{ + fpu_control_t fpsr, fpcr; + + _FPU_GETCW (fpcr); + envp->__fpcr = fpcr; + + _FPU_GETFPSR (fpsr); + envp->__fpsr = fpsr; + + /* Clear exception flags, set all exceptions to non-stop, + and set new rounding mode. */ + fpsr &= ~(FE_ALL_EXCEPT << CAUSE_SHIFT); + _FPU_SETFPSR (fpsr); + + fpcr &= ~(FE_ALL_EXCEPT | FE_DOWNWARD); + _FPU_SETCW (fpcr | round); +} + +static __always_inline void +libc_feholdsetround_vfp (fenv_t *envp, int round) +{ + fpu_control_t fpcr; + + _FPU_GETCW (fpcr); + envp->__fpcr = fpcr; + + /* Set new rounding mode if different. */ + if (unlikely ((fpcr & FE_DOWNWARD) != round)) + _FPU_SETCW ((fpcr & ~FE_DOWNWARD) | round); +} + +static __always_inline void +libc_feresetround_vfp (fenv_t *envp) +{ + fpu_control_t fpcr, round; + + _FPU_GETCW (fpcr); + + /* Check whether rounding modes are different. */ + round = (envp->__fpcr ^ fpcr) & FE_DOWNWARD; + + /* Restore the rounding mode if it was changed. */ + if (unlikely (round != 0)) + _FPU_SETCW (fpcr ^ round); +} + +static __always_inline int +libc_fetestexcept_vfp (int ex) +{ + fpu_control_t fpsr; + + _FPU_GETFPSR (fpsr); + fpsr = fpsr >> CAUSE_SHIFT; + return fpsr & ex & FE_ALL_EXCEPT; +} + +static __always_inline void +libc_fesetenv_vfp (const fenv_t *envp) +{ + fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); + + new_fpcr = envp->__fpcr; + new_fpsr = envp->__fpsr; + + if (unlikely (fpsr ^ new_fpsr) != 0) + _FPU_SETFPSR (new_fpsr); + + if (unlikely (fpcr ^ new_fpcr) != 0) + _FPU_SETCW (new_fpcr); +} + +static __always_inline int +libc_feupdateenv_test_vfp (const fenv_t *envp, int ex) +{ + fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr, excepts; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); + + /* Merge current exception flags with the saved fenv. */ + excepts = (fpsr >> CAUSE_SHIFT) & FE_ALL_EXCEPT; + new_fpcr = envp->__fpcr; + new_fpsr = envp->__fpsr | (excepts << CAUSE_SHIFT); + + /* Write FCR and FESR if different. */ + if (unlikely (fpsr ^ new_fpsr) != 0) + _FPU_SETFPSR (new_fpsr); + + if (unlikely (fpcr ^ new_fpcr) != 0) + _FPU_SETCW (new_fpcr); + + /* Raise the exceptions if enabled in the new FP state. */ + if (unlikely (excepts & new_fpcr)) + feraiseexcept (excepts); + + return excepts & ex; +} + +static __always_inline void +libc_feupdateenv_vfp (const fenv_t *envp) +{ + libc_feupdateenv_test_vfp (envp, 0); +} + +static __always_inline void +libc_feholdsetround_vfp_ctx (struct rm_ctx *ctx, int r) +{ + fpu_control_t fpcr, fpsr, round; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); + ctx->updated_status = false; + ctx->env.__fpcr = fpcr; + ctx->env.__fpsr = fpsr; + + /* Check whether rounding modes are different. */ + round = (fpcr ^ r) & FE_DOWNWARD; + + /* Set the rounding mode if changed. */ + if (unlikely (round != 0)) + { + ctx->updated_status = true; + _FPU_SETCW (fpcr ^ round); + } +} + +static __always_inline void +libc_feresetround_vfp_ctx (struct rm_ctx *ctx) +{ + /* Restore the rounding mode if updated. */ + if (unlikely (ctx->updated_status)) + { + fpu_control_t fpcr; + + _FPU_GETCW (fpcr); + fpcr = (fpcr & ~FE_DOWNWARD) | (ctx->env.__fpcr & FE_DOWNWARD); + _FPU_SETCW (fpcr); + } +} + +static __always_inline void +libc_fesetenv_vfp_ctx (struct rm_ctx *ctx) +{ + fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); + + new_fpcr = ctx->env.__fpcr; + new_fpsr = ctx->env.__fpsr; + + if (unlikely (fpsr ^ new_fpsr) != 0) + _FPU_SETFPSR (new_fpsr); + + if (unlikely (fpcr ^ new_fpcr) != 0) + _FPU_SETCW (new_fpcr); +} + +#define libc_feholdexcept libc_feholdexcept_vfp +#define libc_feholdexceptf libc_feholdexcept_vfp +#define libc_feholdexceptl libc_feholdexcept_vfp + +#define libc_fesetround libc_fesetround_vfp +#define libc_fesetroundf libc_fesetround_vfp +#define libc_fesetroundl libc_fesetround_vfp + +#define libc_feresetround libc_feresetround_vfp +#define libc_feresetroundf libc_feresetround_vfp +#define libc_feresetroundl libc_feresetround_vfp + +#define libc_feresetround_noex libc_fesetenv_vfp +#define libc_feresetround_noexf libc_fesetenv_vfp +#define libc_feresetround_noexl libc_fesetenv_vfp + +#define libc_feholdexcept_setround libc_feholdexcept_setround_vfp +#define libc_feholdexcept_setroundf libc_feholdexcept_setround_vfp +#define libc_feholdexcept_setroundl libc_feholdexcept_setround_vfp + +#define libc_feholdsetround libc_feholdsetround_vfp +#define libc_feholdsetroundf libc_feholdsetround_vfp +#define libc_feholdsetroundl libc_feholdsetround_vfp + +#define libc_fetestexcept libc_fetestexcept_vfp +#define libc_fetestexceptf libc_fetestexcept_vfp +#define libc_fetestexceptl libc_fetestexcept_vfp + +#define libc_fesetenv libc_fesetenv_vfp +#define libc_fesetenvf libc_fesetenv_vfp +#define libc_fesetenvl libc_fesetenv_vfp + +#define libc_feupdateenv libc_feupdateenv_vfp +#define libc_feupdateenvf libc_feupdateenv_vfp +#define libc_feupdateenvl libc_feupdateenv_vfp + +#define libc_feupdateenv_test libc_feupdateenv_test_vfp +#define libc_feupdateenv_testf libc_feupdateenv_test_vfp +#define libc_feupdateenv_testl libc_feupdateenv_test_vfp + +/* We have support for rounding mode context. */ +#define HAVE_RM_CTX 1 + +#define libc_feholdsetround_ctx libc_feholdsetround_vfp_ctx +#define libc_feresetround_ctx libc_feresetround_vfp_ctx +#define libc_feresetround_noex_ctx libc_fesetenv_vfp_ctx + +#define libc_feholdsetroundf_ctx libc_feholdsetround_vfp_ctx +#define libc_feresetroundf_ctx libc_feresetround_vfp_ctx +#define libc_feresetround_noexf_ctx libc_fesetenv_vfp_ctx + +#define libc_feholdsetroundl_ctx libc_feholdsetround_vfp_ctx +#define libc_feresetroundl_ctx libc_feresetround_vfp_ctx +#define libc_feresetround_noexl_ctx libc_fesetenv_vfp_ctx + +#endif /* CSKY_FENV_PRIVATE_H */ diff --git a/libm/csky/fesetenv.c b/libm/csky/fesetenv.c new file mode 100644 index 000000000..96b961598 --- /dev/null +++ b/libm/csky/fesetenv.c @@ -0,0 +1,55 @@ +/* Install given floating-point environment. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetenv (const fenv_t *envp) +{ + unsigned int fpcr; + unsigned int fpsr; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); + + fpcr &= _FPU_RESERVED; + fpsr &= _FPU_FPSR_RESERVED; + + if (envp == FE_DFL_ENV) + { + fpcr |= _FPU_DEFAULT; + fpsr |= _FPU_FPSR_DEFAULT; + } + else if (envp == FE_NOMASK_ENV) + { + fpcr |= _FPU_FPCR_IEEE; + fpsr |= _FPU_FPSR_IEEE; + } + else + { + fpcr |= envp->__fpcr & ~_FPU_RESERVED; + fpsr |= envp->__fpsr & ~_FPU_FPSR_RESERVED; + } + + _FPU_SETFPSR (fpsr); + + _FPU_SETCW (fpcr); + + /* Success. */ + return 0; +} diff --git a/libm/csky/fesetexcept.c b/libm/csky/fesetexcept.c new file mode 100644 index 000000000..940322197 --- /dev/null +++ b/libm/csky/fesetexcept.c @@ -0,0 +1,32 @@ +/* Set given exception flags. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include "fenv_libc.h" + +int +fesetexcept (int excepts) +{ + fpu_control_t fpsr, new_fpsr; + _FPU_GETFPSR (fpsr); + new_fpsr = fpsr | ((excepts & FE_ALL_EXCEPT) << CAUSE_SHIFT); + if (new_fpsr != fpsr) + _FPU_SETFPSR (new_fpsr); + + return 0; +} diff --git a/libm/csky/fesetmode.c b/libm/csky/fesetmode.c new file mode 100644 index 000000000..eddd2d401 --- /dev/null +++ b/libm/csky/fesetmode.c @@ -0,0 +1,32 @@ +/* Install given floating-point control modes. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetmode (const femode_t *modep) +{ + femode_t mode; + if (modep == FE_DFL_MODE) + mode = _FPU_DEFAULT; + else + mode = *modep; + _FPU_SETCW (mode); + + return 0; +} diff --git a/libm/csky/fesetround.c b/libm/csky/fesetround.c new file mode 100644 index 000000000..15a4b7c7e --- /dev/null +++ b/libm/csky/fesetround.c @@ -0,0 +1,28 @@ +/* Set current rounding direction. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include "fenv_private.h" + +#include <stdio.h> +int +fesetround (int round) +{ + libc_fesetround_vfp (round); + return 0; +} diff --git a/libm/csky/feupdateenv.c b/libm/csky/feupdateenv.c new file mode 100644 index 000000000..91e627ad2 --- /dev/null +++ b/libm/csky/feupdateenv.c @@ -0,0 +1,42 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include "fenv_libc.h" +#include "fenv_private.h" +#include <stdio.h> + +int +feupdateenv (const fenv_t *envp) +{ + int temp; + + /* Save current exceptions. */ + _FPU_GETFPSR (temp); + temp = (temp >> CAUSE_SHIFT) & FE_ALL_EXCEPT; + /* Install new environment. */ + fesetenv (envp); + + /* Raise the saved exception. Incidentally for us the implementation + defined format of the values in objects of type fexcept_t is the + same as the ones specified using the FE_* constants. */ + feraiseexcept (temp); + + /* Success. */ + return 0; +} diff --git a/libm/csky/fgetexcptflg.c b/libm/csky/fgetexcptflg.c new file mode 100644 index 000000000..c400a2c1f --- /dev/null +++ b/libm/csky/fgetexcptflg.c @@ -0,0 +1,31 @@ +/* Store current representation for exceptions. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include "fenv_libc.h" +#include "fenv_private.h" +#include <stdio.h> + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + *flagp = libc_fetestexcept_vfp (excepts); + + /* Success. */ + return 0; +} diff --git a/libm/csky/fraiseexcpt.c b/libm/csky/fraiseexcpt.c new file mode 100644 index 000000000..31cd32f2c --- /dev/null +++ b/libm/csky/fraiseexcpt.c @@ -0,0 +1,122 @@ +/* Raise given exceptions. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_libc.h" +#include <fpu_control.h> +#include <float.h> +#include <math.h> + +int +feraiseexcept (int excepts) +{ + /* Raise exceptions represented by EXCEPTS. But we must raise only one + signal at a time. It is important that if the overflow/underflow + exception and the divide by zero exception are given at the same + time, the overflow/underflow exception follows the divide by zero + exception. */ + +# ifndef __csky_fpuv1__ + /* First: invalid exception. */ + if (FE_INVALID & excepts) + { + /* One example of a invalid operation is 0 * Infinity. */ + float x = HUGE_VALF, y = 0.0f; + __asm__ __volatile__ ("fmuls %0, %0, %1" : "+v" (x) : "v" (y)); + } + + /* Next: division by zero. */ + if (FE_DIVBYZERO & excepts) + { + float x = 1.0f, y = 0.0f; + __asm__ __volatile__ ("fdivs %0, %0, %1" : "+v" (x) : "v" (y)); + } + + /* Next: overflow. */ + if (FE_OVERFLOW & excepts) + { + float x = FLT_MAX; + __asm__ __volatile__ ("fmuls %0, %0, %0" : "+v" (x)); + } + /* Next: underflow. */ + if (FE_UNDERFLOW & excepts) + { + float x = -FLT_MIN; + + __asm__ __volatile__ ("fmuls %0, %0, %0" : "+v" (x)); + } + + /* Last: inexact. */ + if (FE_INEXACT & excepts) + { + float x = 1.0f, y = 3.0f; + __asm__ __volatile__ ("fdivs %0, %0, %1" : "+v" (x) : "v" (y)); + } + + if (__FE_DENORMAL & excepts) + { + double x = 4.9406564584124654e-324; + __asm__ __volatile__ ("fstod %0, %0" : "+v" (x)); + } +# else + int tmp = 0; + /* First: invalid exception. */ + if (FE_INVALID & excepts) + { + /* One example of a invalid operation is 0 * Infinity. */ + float x = HUGE_VALF, y = 0.0f; + __asm__ __volatile__ ("fmuls %0, %0, %2, %1" + : "+f" (x), "+r"(tmp) : "f" (y)); + } + + /* Next: division by zero. */ + if (FE_DIVBYZERO & excepts) + { + float x = 1.0f, y = 0.0f; + __asm__ __volatile__ ("fdivs %0, %0, %2, %1" + : "+f" (x), "+r"(tmp) : "f" (y)); + } + + /* Next: overflow. */ + if (FE_OVERFLOW & excepts) + { + float x = FLT_MAX, y = FLT_MAX; + __asm__ __volatile__ ("fmuls %0, %0, %2, %1" + : "+f" (x), "+r"(tmp) : "f" (y)); + } + + /* Next: underflow. */ + if (FE_UNDERFLOW & excepts) + { + float x = -FLT_MIN, y = -FLT_MIN; + + __asm__ __volatile__ ("fmuls %0, %0, %2, %1" + : "+f" (x), "+r"(tmp) : "f" (y)); + } + + /* Last: inexact. */ + if (FE_INEXACT & excepts) + { + float x = 1.0f, y = 3.0f; + __asm__ __volatile__ ("fdivs %0, %0, %2, %1" + : "+f" (x), "+r"(tmp) : "f" (y)); + } +# endif /* __csky_fpuv2__ */ + + /* Success. */ + return 0; +} diff --git a/libm/csky/fsetexcptflg.c b/libm/csky/fsetexcptflg.c new file mode 100644 index 000000000..b6281d5c2 --- /dev/null +++ b/libm/csky/fsetexcptflg.c @@ -0,0 +1,42 @@ +/* Set floating-point environment exception handling. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include "fenv_libc.h" + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fpu_control_t temp; + + /* Get the current exceptions. */ + _FPU_GETFPSR (temp); + + /* Make sure the flags we want restored are legal. */ + excepts &= FE_ALL_EXCEPT; + + /* Now clear the bits called for, and copy them in from flagp. Note that + we ignore all non-flag bits from *flagp, so they don't matter. */ + temp = ((temp >> CAUSE_SHIFT) & ~excepts) | (*flagp & excepts); + temp = temp << CAUSE_SHIFT; + + _FPU_SETFPSR (temp); + + /* Success. */ + return 0; +} diff --git a/libm/csky/ftestexcept.c b/libm/csky/ftestexcept.c new file mode 100644 index 000000000..6e3217eb1 --- /dev/null +++ b/libm/csky/ftestexcept.c @@ -0,0 +1,28 @@ +/* Test exception in current environment. + Copyright (C) 2018-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include "fenv_libc.h" +#include "fenv_private.h" +#include <stdio.h> + +int +fetestexcept (int excepts) +{ + return libc_fetestexcept_vfp (excepts); +} diff --git a/libm/m68k/Makefile.arch b/libm/m68k/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/m68k/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/m68k/fclrexcpt.c b/libm/m68k/fclrexcpt.c new file mode 100644 index 000000000..904ba5a19 --- /dev/null +++ b/libm/m68k/fclrexcpt.c @@ -0,0 +1,39 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +feclearexcept (int excepts) +{ + fexcept_t fpsr; + + /* Mask out unsupported bits/exceptions. */ + excepts &= FE_ALL_EXCEPT; + + /* Fetch the fpu status register. */ + __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); + + /* Clear the relevant bits. */ + fpsr &= ~excepts; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr)); + + /* Success. */ + return 0; +} diff --git a/libm/m68k/fedisblxcpt.c b/libm/m68k/fedisblxcpt.c new file mode 100644 index 000000000..c2c593e38 --- /dev/null +++ b/libm/m68k/fedisblxcpt.c @@ -0,0 +1,36 @@ +/* Disable floating-point exceptions. + Copyright (C) 2000-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fedisableexcept (int excepts) +{ + unsigned int old_exc, new_exc; + + /* Get the current control register contents. */ + __asm__ ("fmove%.l %!,%0" : "=dm" (new_exc)); + + old_exc = (new_exc >> 6) & FE_ALL_EXCEPT; + + excepts &= FE_ALL_EXCEPT; + + new_exc &= ~(excepts << 6); + __asm__ ("fmove%.l %0,%!" : : "dm" (new_exc)); + + return old_exc; +} diff --git a/libm/m68k/feenablxcpt.c b/libm/m68k/feenablxcpt.c new file mode 100644 index 000000000..9c01dc28b --- /dev/null +++ b/libm/m68k/feenablxcpt.c @@ -0,0 +1,36 @@ +/* Enable floating-point exceptions. + Copyright (C) 2000-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +feenableexcept (int excepts) +{ + unsigned int new_exc, old_exc; + + /* Get the current control register contents. */ + __asm__ ("fmove%.l %!,%0" : "=dm" (new_exc)); + + old_exc = (new_exc >> 6) & FE_ALL_EXCEPT; + + excepts &= FE_ALL_EXCEPT; + + new_exc |= excepts << 6; + __asm__ ("fmove%.l %0,%!" : : "dm" (new_exc)); + + return old_exc; +} diff --git a/libm/m68k/fegetenv.c b/libm/m68k/fegetenv.c new file mode 100644 index 000000000..2cd0a7c88 --- /dev/null +++ b/libm/m68k/fegetenv.c @@ -0,0 +1,33 @@ +/* Store current floating-point environment. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fegetenv (fenv_t *envp) +{ +#ifdef __mcoldfire__ + __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (envp->__control_register)); + __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (envp->__status_register)); + __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (envp->__instruction_address)); +#else + __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*envp)); +#endif + + /* Success. */ + return 0; +} diff --git a/libm/m68k/fegetexcept.c b/libm/m68k/fegetexcept.c new file mode 100644 index 000000000..1be3f8bf5 --- /dev/null +++ b/libm/m68k/fegetexcept.c @@ -0,0 +1,29 @@ +/* Get enabled floating-point exceptions. + Copyright (C) 2000-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fegetexcept (void) +{ + unsigned int exc; + + /* Get the current control register contents. */ + __asm__ ("fmove%.l %!,%0" : "=dm" (exc)); + + return (exc >> 6) & FE_ALL_EXCEPT; +} diff --git a/libm/m68k/fegetmode.c b/libm/m68k/fegetmode.c new file mode 100644 index 000000000..19f49922a --- /dev/null +++ b/libm/m68k/fegetmode.c @@ -0,0 +1,26 @@ +/* Store current floating-point control modes. M68K version. + Copyright (C) 2016-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ + _FPU_GETCW (*modep); + return 0; +} diff --git a/libm/m68k/fegetround.c b/libm/m68k/fegetround.c new file mode 100644 index 000000000..02f6c4c41 --- /dev/null +++ b/libm/m68k/fegetround.c @@ -0,0 +1,28 @@ +/* Return current rounding direction. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fegetround (void) +{ + int fpcr; + + __asm__ ("fmove%.l %!,%0" : "=dm" (fpcr)); + + return fpcr & FE_UPWARD; +} diff --git a/libm/m68k/feholdexcpt.c b/libm/m68k/feholdexcpt.c new file mode 100644 index 000000000..c0891969a --- /dev/null +++ b/libm/m68k/feholdexcpt.c @@ -0,0 +1,42 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +feholdexcept (fenv_t *envp) +{ + fexcept_t fpcr, fpsr; + + /* Store the environment. */ +#ifdef __mcoldfire__ + __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (envp->__control_register)); + __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (envp->__status_register)); + __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (envp->__instruction_address)); +#else + __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*envp)); +#endif + + /* Now clear all exceptions. */ + fpsr = envp->__status_register & ~FE_ALL_EXCEPT; + __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr)); + /* And set all exceptions to non-stop. */ + fpcr = envp->__control_register & ~(FE_ALL_EXCEPT << 6); + __asm__ __volatile__ ("fmove%.l %0,%!" : : "dm" (fpcr)); + + return 0; +} diff --git a/libm/m68k/fesetenv.c b/libm/m68k/fesetenv.c new file mode 100644 index 000000000..873eb9abe --- /dev/null +++ b/libm/m68k/fesetenv.c @@ -0,0 +1,63 @@ +/* Install given floating-point environment. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fesetenv (const fenv_t *envp) +{ + fenv_t temp; + + /* Install the environment specified by ENVP. But there are a few + values which we do not want to come from the saved environment. + Therefore, we get the current environment and replace the values + we want to use from the environment specified by the parameter. */ +#ifdef __mcoldfire__ + __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (temp.__control_register)); + __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (temp.__status_register)); + __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (temp.__instruction_address)); +#else + __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*&temp)); +#endif + + temp.__status_register &= ~FE_ALL_EXCEPT; + temp.__control_register &= ~((FE_ALL_EXCEPT << 6) | FE_UPWARD); + if (envp == FE_DFL_ENV) + ; + else if (envp == FE_NOMASK_ENV) + temp.__control_register |= FE_ALL_EXCEPT << 6; + else + { + temp.__control_register |= (envp->__control_register + & ((FE_ALL_EXCEPT << 6) | FE_UPWARD)); + temp.__status_register |= envp->__status_register & FE_ALL_EXCEPT; + } + +#ifdef __mcoldfire__ + __asm__ __volatile__ ("fmove%.l %0,%/fpiar" + :: "dm" (temp.__instruction_address)); + __asm__ __volatile__ ("fmove%.l %0,%/fpcr" + :: "dm" (temp.__control_register)); + __asm__ __volatile__ ("fmove%.l %0,%/fpsr" + :: "dm" (temp.__status_register)); +#else + __asm__ __volatile__ ("fmovem%.l %0,%/fpcr/%/fpsr/%/fpiar" : : "m" (*&temp)); +#endif + + /* Success. */ + return 0; +} diff --git a/libm/m68k/fesetexcept.c b/libm/m68k/fesetexcept.c new file mode 100644 index 000000000..6ae4a55ea --- /dev/null +++ b/libm/m68k/fesetexcept.c @@ -0,0 +1,30 @@ +/* Set given exception flags. M68K version. + Copyright (C) 2016-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fesetexcept (int excepts) +{ + fexcept_t fpsr; + + __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); + fpsr |= excepts & FE_ALL_EXCEPT; + __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr)); + + return 0; +} diff --git a/libm/m68k/fesetmode.c b/libm/m68k/fesetmode.c new file mode 100644 index 000000000..a7e93d616 --- /dev/null +++ b/libm/m68k/fesetmode.c @@ -0,0 +1,31 @@ +/* Install given floating-point control modes. M68K version. + Copyright (C) 2016-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetmode (const femode_t *modep) +{ + femode_t mode; + if (modep == FE_DFL_MODE) + mode = _FPU_DEFAULT; + else + mode = *modep; + _FPU_SETCW (mode); + return 0; +} diff --git a/libm/m68k/fesetround.c b/libm/m68k/fesetround.c new file mode 100644 index 000000000..a8abc4e6e --- /dev/null +++ b/libm/m68k/fesetround.c @@ -0,0 +1,35 @@ +/* Set current rounding direction. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fesetround (int round) +{ + fexcept_t fpcr; + + if (round & ~FE_UPWARD) + /* ROUND is no valid rounding mode. */ + return 1; + + __asm__ ("fmove%.l %!,%0" : "=dm" (fpcr)); + fpcr &= ~FE_UPWARD; + fpcr |= round; + __asm__ __volatile__ ("fmove%.l %0,%!" : : "dm" (fpcr)); + + return 0; +} diff --git a/libm/m68k/feupdateenv.c b/libm/m68k/feupdateenv.c new file mode 100644 index 000000000..29dcc712e --- /dev/null +++ b/libm/m68k/feupdateenv.c @@ -0,0 +1,39 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +feupdateenv (const fenv_t *envp) +{ + fexcept_t fpsr; + + /* Save current exceptions. */ + __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); + fpsr &= FE_ALL_EXCEPT; + + /* Install new environment. */ + fesetenv (envp); + + /* Raise the saved exception. Incidentally for us the implementation + defined format of the values in objects of type fexcept_t is the + same as the ones specified using the FE_* constants. */ + feraiseexcept ((int) fpsr); + + /* Success. */ + return 0; +} diff --git a/libm/m68k/fgetexcptflg.c b/libm/m68k/fgetexcptflg.c new file mode 100644 index 000000000..7a564555b --- /dev/null +++ b/libm/m68k/fgetexcptflg.c @@ -0,0 +1,32 @@ +/* Store current representation for exceptions. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + fexcept_t fpsr; + + /* Get the current exceptions. */ + __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); + + *flagp = fpsr & excepts & FE_ALL_EXCEPT; + + /* Success. */ + return 0; +} diff --git a/libm/m68k/fraiseexcpt.c b/libm/m68k/fraiseexcpt.c new file mode 100644 index 000000000..4599c08f7 --- /dev/null +++ b/libm/m68k/fraiseexcpt.c @@ -0,0 +1,106 @@ +/* Raise given exceptions. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <float.h> +#include <math.h> + +int +feraiseexcept (int excepts) +{ +#if defined(__mcffpu__) + + /* The Coldfire FPU allows an exception to be raised by asserting + the associated EXC bit and then executing an arbitrary arithmetic + instruction. fmove.l is classified as an arithmetic instruction + and suffices for this purpose. + + We therefore raise an exception by setting both the EXC and AEXC + bit associated with the exception (the former being 6 bits to the + left of the latter) and then loading the longword at (%sp) into an + FP register. */ + + inline void + raise_one_exception (int mask) + { + if (excepts & mask) + { + int fpsr; + double unused; + + __asm__ volatile ("fmove%.l %/fpsr,%0" : "=d" (fpsr)); + fpsr |= (mask << 6) | mask; + __asm__ volatile ("fmove%.l %0,%/fpsr" :: "d" (fpsr)); + __asm__ volatile ("fmove%.l (%%sp),%0" : "=f" (unused)); + } + } + + raise_one_exception (FE_INVALID); + raise_one_exception (FE_DIVBYZERO); + raise_one_exception (FE_OVERFLOW); + raise_one_exception (FE_UNDERFLOW); + raise_one_exception (FE_INEXACT); + +#else + /* Raise exceptions represented by EXCEPTS. But we must raise only one + signal at a time. It is important that if the overflow/underflow + exception and the divide by zero exception are given at the same + time, the overflow/underflow exception follows the divide by zero + exception. */ + + /* First: invalid exception. */ + if (excepts & FE_INVALID) + { + /* One example of an invalid operation is 0 * Infinity. */ + double d = HUGE_VAL; + __asm__ __volatile__ ("fmul%.s %#0r0,%0; fnop" : "=f" (d) : "0" (d)); + } + + /* Next: division by zero. */ + if (excepts & FE_DIVBYZERO) + { + double d = 1.0; + __asm__ __volatile__ ("fdiv%.s %#0r0,%0; fnop" : "=f" (d) : "0" (d)); + } + + /* Next: overflow. */ + if (excepts & FE_OVERFLOW) + { + long double d = LDBL_MAX; + + __asm__ __volatile__ ("fmul%.x %0,%0; fnop" : "=f" (d) : "0" (d)); + } + + /* Next: underflow. */ + if (excepts & FE_UNDERFLOW) + { + long double d = -LDBL_MAX; + + __asm__ __volatile__ ("fetox%.x %0; fnop" : "=f" (d) : "0" (d)); + } + + /* Last: inexact. */ + if (excepts & FE_INEXACT) + { + long double d = 1.0; + __asm__ __volatile__ ("fdiv%.s %#0r3,%0; fnop" : "=f" (d) : "0" (d)); + } + +#endif + /* Success. */ + return 0; +} diff --git a/libm/m68k/fsetexcptflg.c b/libm/m68k/fsetexcptflg.c new file mode 100644 index 000000000..18fc1811f --- /dev/null +++ b/libm/m68k/fsetexcptflg.c @@ -0,0 +1,38 @@ +/* Set floating-point environment exception handling. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <math.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fexcept_t fpsr; + + /* Get the current status register. */ + __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); + + /* Install the new exception bits in the Accrued Exception Byte. */ + fpsr &= ~(excepts & FE_ALL_EXCEPT); + fpsr |= *flagp & excepts & FE_ALL_EXCEPT; + + /* Store the new status register. */ + __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr)); + + /* Success. */ + return 0; +} diff --git a/libm/m68k/ftestexcept.c b/libm/m68k/ftestexcept.c new file mode 100644 index 000000000..1ece1a48d --- /dev/null +++ b/libm/m68k/ftestexcept.c @@ -0,0 +1,29 @@ +/* Test exception in current environment. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fetestexcept (int excepts) +{ + fexcept_t fpsr; + + /* Get current exceptions. */ + __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); + + return fpsr & excepts & FE_ALL_EXCEPT; +} diff --git a/libm/or1k/Makefile.arch b/libm/or1k/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/or1k/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/or1k/fclrexcpt.c b/libm/or1k/fclrexcpt.c new file mode 100644 index 000000000..ecb327d72 --- /dev/null +++ b/libm/or1k/fclrexcpt.c @@ -0,0 +1,42 @@ +/* Clear given exceptions in current floating-point environment. + OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ + fpu_control_t cw; + fpu_control_t cw_new; + + /* Mask out unsupported bits/exceptions. */ + excepts &= FE_ALL_EXCEPT; + + /* Read the complete control word. */ + _FPU_GETCW (cw); + + cw_new = cw & ~excepts; + + /* Put the new data in effect. */ + if (cw != cw_new) + _FPU_SETCW (cw_new); + + /* Success. */ + return 0; +} diff --git a/libm/or1k/fegetenv.c b/libm/or1k/fegetenv.c new file mode 100644 index 000000000..7769d456f --- /dev/null +++ b/libm/or1k/fegetenv.c @@ -0,0 +1,28 @@ +/* Store current floating-point environment. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetenv (fenv_t *envp) +{ + _FPU_GETCW (*envp); + + /* Success. */ + return 0; +} diff --git a/libm/or1k/fegetmode.c b/libm/or1k/fegetmode.c new file mode 100644 index 000000000..40a789329 --- /dev/null +++ b/libm/or1k/fegetmode.c @@ -0,0 +1,28 @@ +/* Store current floating-point control modes. OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ + _FPU_GETCW (*modep); + + /* Success. */ + return 0; +} diff --git a/libm/or1k/fegetround.c b/libm/or1k/fegetround.c new file mode 100644 index 000000000..0965de2f9 --- /dev/null +++ b/libm/or1k/fegetround.c @@ -0,0 +1,25 @@ +/* Return current rounding direction. OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "get-rounding-mode.h" + +int +fegetround (void) +{ + return get_rounding_mode (); +} diff --git a/libm/or1k/feholdexcpt.c b/libm/or1k/feholdexcpt.c new file mode 100644 index 000000000..cff06f3d0 --- /dev/null +++ b/libm/or1k/feholdexcpt.c @@ -0,0 +1,29 @@ +/* Store current floating-point environment and clear exceptions. + OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feholdexcept (fenv_t *envp) +{ + libc_feholdexcept_or1k (envp); + + /* Success. */ + return 0; +} diff --git a/libm/or1k/fenv_private.h b/libm/or1k/fenv_private.h new file mode 100644 index 000000000..ede7d243a --- /dev/null +++ b/libm/or1k/fenv_private.h @@ -0,0 +1,196 @@ +/* Private floating point rounding and exceptions handling. OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef OR1K_FENV_PRIVATE_H +#define OR1K_FENV_PRIVATE_H 1 + +#include <fenv.h> +#include <fpu_control.h> + +static __always_inline void +libc_feholdexcept_or1k (fenv_t *envp) +{ + fpu_control_t cw; + fpu_control_t cw_new; + + /* Get and store the environment. */ + _FPU_GETCW (cw); + *envp = cw; + + /* Clear the exception status flags. */ + cw_new = cw & ~FE_ALL_EXCEPT; + + if (cw != cw_new) + _FPU_SETCW (cw_new); +} + +#define libc_feholdexcept libc_feholdexcept_or1k +#define libc_feholdexceptf libc_feholdexcept_or1k +#define libc_feholdexceptl libc_feholdexcept_or1k + +static __always_inline void +libc_fesetround_or1k (int round) +{ + fpu_control_t cw; + fpu_control_t cw_new; + + _FPU_GETCW (cw); + cw_new = cw & ~_FPU_FPCSR_RM_MASK; + cw_new |= round; + if (cw != cw_new) + _FPU_SETCW (cw_new); +} + +#define libc_fesetround libc_fesetround_or1k +#define libc_fesetroundf libc_fesetround_or1k +#define libc_fesetroundl libc_fesetround_or1k + +static __always_inline void +libc_feholdexcept_setround_or1k (fenv_t *envp, int round) +{ + fpu_control_t cw; + fpu_control_t cw_new; + + /* Get and store the environment. */ + _FPU_GETCW (cw); + *envp = cw; + + /* Clear the status flags and rounding mode. */ + cw_new = cw & ~(FE_ALL_EXCEPT | _FPU_FPCSR_RM_MASK); + + /* Set rounding mode. */ + cw_new |= round; + + if (cw != cw_new) + _FPU_SETCW (cw_new); +} + +#define libc_feholdexcept_setround libc_feholdexcept_setround_or1k +#define libc_feholdexcept_setroundf libc_feholdexcept_setround_or1k +#define libc_feholdexcept_setroundl libc_feholdexcept_setround_or1k + +static __always_inline int +libc_fetestexcept_or1k (int ex) +{ + fpu_control_t cw; + + /* Get current control word. */ + _FPU_GETCW (cw); + + /* Check if any of the queried exception flags are set. */ + return cw & ex & FE_ALL_EXCEPT; +} + +#define libc_fetestexcept libc_fetestexcept_or1k +#define libc_fetestexceptf libc_fetestexcept_or1k +#define libc_fetestexceptl libc_fetestexcept_or1k + +static __always_inline void +libc_fesetenv_or1k (const fenv_t *envp) +{ + if (envp == FE_DFL_ENV) + _FPU_SETCW (_FPU_DEFAULT); + else + _FPU_SETCW (*envp); +} + +#define libc_fesetenv libc_fesetenv_or1k +#define libc_fesetenvf libc_fesetenv_or1k +#define libc_fesetenvl libc_fesetenv_or1k +#define libc_feresetround_noex libc_fesetenv_or1k +#define libc_feresetround_noexf libc_fesetenv_or1k +#define libc_feresetround_noexl libc_fesetenv_or1k + +static __always_inline int +libc_feupdateenv_test_or1k (const fenv_t *envp, int ex) +{ + fpu_control_t cw; + fpu_control_t cw_new; + int excepts; + + /* Get current control word. */ + _FPU_GETCW (cw); + + /* Merge current exception flags with the passed fenv. */ + excepts = cw & FE_ALL_EXCEPT; + cw_new = (envp == FE_DFL_ENV ? _FPU_DEFAULT : *envp) | excepts; + + if (unlikely (cw != cw_new)) + _FPU_SETCW (cw_new); + + /* Raise the exceptions if enabled in the new FP state. */ + if (unlikely (excepts)) + feraiseexcept (excepts); + + return excepts & ex; +} + +#define libc_feupdateenv_test libc_feupdateenv_test_or1k +#define libc_feupdateenv_testf libc_feupdateenv_test_or1k +#define libc_feupdateenv_testl libc_feupdateenv_test_or1k + +static __always_inline void +libc_feupdateenv_or1k (const fenv_t *envp) +{ + libc_feupdateenv_test_or1k (envp, 0); +} + +#define libc_feupdateenv libc_feupdateenv_or1k +#define libc_feupdateenvf libc_feupdateenv_or1k +#define libc_feupdateenvl libc_feupdateenv_or1k + +static __always_inline void +libc_feholdsetround_or1k (fenv_t *envp, int round) +{ + fpu_control_t cw; + + _FPU_GETCW (cw); + *envp = cw; + + /* Check whether rounding modes are different. */ + round = (cw ^ round) & _FPU_FPCSR_RM_MASK; + + /* Set new rounding mode if different. */ + if (unlikely (round != 0)) + _FPU_SETCW (cw ^ round); +} + +#define libc_feholdsetround libc_feholdsetround_or1k +#define libc_feholdsetroundf libc_feholdsetround_or1k +#define libc_feholdsetroundl libc_feholdsetround_or1k + +static __always_inline void +libc_feresetround_or1k (fenv_t *envp) +{ + fpu_control_t cw; + int round; + + _FPU_GETCW (cw); + + /* Check whether rounding modes are different. */ + round = (*envp ^ cw) & _FPU_FPCSR_RM_MASK; + + /* Restore the rounding mode if it was changed. */ + if (unlikely (round != 0)) + _FPU_SETCW (cw ^ round); +} + +#define libc_feresetround libc_feresetround_or1k +#define libc_feresetroundf libc_feresetround_or1k +#define libc_feresetroundl libc_feresetround_or1k + +#endif diff --git a/libm/or1k/fesetenv.c b/libm/or1k/fesetenv.c new file mode 100644 index 000000000..a9c8448f4 --- /dev/null +++ b/libm/or1k/fesetenv.c @@ -0,0 +1,28 @@ +/* Install given floating-point environment. OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetenv (const fenv_t *envp) +{ + libc_fesetenv_or1k (envp); + + /* Success. */ + return 0; +} diff --git a/libm/or1k/fesetexcept.c b/libm/or1k/fesetexcept.c new file mode 100644 index 000000000..abc5624c3 --- /dev/null +++ b/libm/or1k/fesetexcept.c @@ -0,0 +1,34 @@ +/* Set given exception flags. OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexcept (int excepts) +{ + fpu_control_t cw; + fpu_control_t cw_new; + + _FPU_GETCW (cw); + cw_new = cw | (excepts & FE_ALL_EXCEPT); + if (cw != cw_new) + _FPU_SETCW (cw_new); + + /* Success. */ + return 0; +} diff --git a/libm/or1k/fesetmode.c b/libm/or1k/fesetmode.c new file mode 100644 index 000000000..74490621b --- /dev/null +++ b/libm/or1k/fesetmode.c @@ -0,0 +1,38 @@ +/* Install given floating-point control modes. OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetmode (const femode_t *modep) +{ + fpu_control_t cw; + fpu_control_t cw_new; + + _FPU_GETCW (cw); + cw_new = cw & ~_FPU_FPCSR_RM_MASK; + if (modep == FE_DFL_MODE) + cw_new |= (_FPU_DEFAULT & _FPU_FPCSR_RM_MASK); + else + cw_new |= (*modep & _FPU_FPCSR_RM_MASK); + if (cw != cw_new) + _FPU_SETCW (cw_new); + + /* Success. */ + return 0; +} diff --git a/libm/or1k/fesetround.c b/libm/or1k/fesetround.c new file mode 100644 index 000000000..37c2db4ab --- /dev/null +++ b/libm/or1k/fesetround.c @@ -0,0 +1,35 @@ +/* Set current rounding direction. OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetround (int round) +{ + switch (round) + { + case FE_TONEAREST: + case FE_TOWARDZERO: + case FE_DOWNWARD: + case FE_UPWARD: + libc_fesetround_or1k (round); + return 0; + default: + return round; /* A nonzero value. */ + } +} diff --git a/libm/or1k/feupdateenv.c b/libm/or1k/feupdateenv.c new file mode 100644 index 000000000..b0f42744f --- /dev/null +++ b/libm/or1k/feupdateenv.c @@ -0,0 +1,29 @@ +/* Install given floating-point environment and raise exceptions. + OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feupdateenv (const fenv_t *envp) +{ + libc_feupdateenv_or1k (envp); + + /* Success. */ + return 0; +} diff --git a/libm/or1k/fgetexcptflg.c b/libm/or1k/fgetexcptflg.c new file mode 100644 index 000000000..2a725a4c7 --- /dev/null +++ b/libm/or1k/fgetexcptflg.c @@ -0,0 +1,28 @@ +/* Store current state of exceptions. OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + *flagp = libc_fetestexcept_or1k (excepts); + + /* Success. */ + return 0; +} diff --git a/libm/or1k/fraiseexcpt.c b/libm/or1k/fraiseexcpt.c new file mode 100644 index 000000000..31ceb830d --- /dev/null +++ b/libm/or1k/fraiseexcpt.c @@ -0,0 +1,63 @@ +/* Raise given exceptions. OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include <float.h> +#include <math.h> + +int +feraiseexcept (int excepts) +{ + if (excepts == 0) + return 0; + + /* Raise exceptions represented by EXPECTS. */ + + if (excepts & FE_INEXACT) + { + float d = 1.0, x = 3.0; + __asm__ volatile ("lf.div.s %0, %0, %1" : "+r" (d) : "r" (x)); + } + + if (excepts & FE_UNDERFLOW) + { + float d = FLT_MIN; + __asm__ volatile ("lf.mul.s %0, %0, %0" : "+r" (d)); + } + + if (excepts & FE_OVERFLOW) + { + float d = FLT_MAX; + __asm__ volatile ("lf.mul.s %0, %0, %0" : "+r" (d) : "r" (d)); + } + + if (excepts & FE_DIVBYZERO) + { + float d = 1.0, x = 0.0; + __asm__ volatile ("lf.div.s %0, %0, %1" : "+r" (d) : "r" (x)); + } + + if (excepts & FE_INVALID) + { + float d = HUGE_VAL, x = 0.0; + __asm__ volatile ("lf.mul.s %0, %1, %0" : "+r" (d) : "r" (x)); + } + + /* Success. */ + return 0; +} diff --git a/libm/or1k/fsetexcptflg.c b/libm/or1k/fsetexcptflg.c new file mode 100644 index 000000000..01c6e8635 --- /dev/null +++ b/libm/or1k/fsetexcptflg.c @@ -0,0 +1,42 @@ +/* Set floating-point environment exception handling. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fpu_control_t cw; + fpu_control_t cw_new; + + /* Get the current exceptions. */ + _FPU_GETCW (cw); + + /* Make sure the flags we want restored are legal. */ + excepts &= FE_ALL_EXCEPT; + + /* Now set selected bits from flagp. Note that we ignore all non-flag + bits from *flagp, so they don't matter. */ + cw_new = (cw & ~excepts) | (*flagp & excepts); + + if (cw != cw_new) + _FPU_SETCW (cw_new); + + /* Success. */ + return 0; +} diff --git a/libm/or1k/ftestexcept.c b/libm/or1k/ftestexcept.c new file mode 100644 index 000000000..02ddf12c8 --- /dev/null +++ b/libm/or1k/ftestexcept.c @@ -0,0 +1,25 @@ +/* Test exception in current environment. OpenRISC version. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fetestexcept (int excepts) +{ + return libc_fetestexcept_or1k (excepts); +} diff --git a/libm/or1k/get-rounding-mode.h b/libm/or1k/get-rounding-mode.h new file mode 100644 index 000000000..f65c4ecc0 --- /dev/null +++ b/libm/or1k/get-rounding-mode.h @@ -0,0 +1,36 @@ +/* Determine floating-point rounding mode within libc. OpenRISC version. + + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _OR1K_GET_ROUNDING_MODE_H +#define _OR1K_GET_ROUNDING_MODE_H 1 + +#include <fenv.h> +#include <fpu_control.h> + +/* Return the floating-point rounding mode. */ + +static inline int +get_rounding_mode (void) +{ + fpu_control_t cw; + + _FPU_GETCW (cw); + return cw & _FPU_FPCSR_RM_MASK; +} + +#endif /* get-rounding-mode.h */ diff --git a/libm/riscv32/Makefile.arch b/libm/riscv32/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/riscv32/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/riscv32/fclrexcpt.c b/libm/riscv32/fclrexcpt.c new file mode 100644 index 000000000..849a910fc --- /dev/null +++ b/libm/riscv32/fclrexcpt.c @@ -0,0 +1,26 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ + __asm__ volatile ("csrc fflags, %0" : : "r" (excepts)); + return 0; +} diff --git a/libm/riscv32/fegetenv.c b/libm/riscv32/fegetenv.c new file mode 100644 index 000000000..94f3444ac --- /dev/null +++ b/libm/riscv32/fegetenv.c @@ -0,0 +1,28 @@ +/* Store current floating-point environment. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetenv (fenv_t *envp) +{ + _FPU_GETCW (*envp); + + /* Success. */ + return 0; +} diff --git a/libm/riscv32/fegetmode.c b/libm/riscv32/fegetmode.c new file mode 100644 index 000000000..4b0ff270c --- /dev/null +++ b/libm/riscv32/fegetmode.c @@ -0,0 +1,26 @@ +/* Store current floating-point control modes. RISC-V version. + Copyright (C) 2017-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ + _FPU_GETCW (*modep); + return 0; +} diff --git a/libm/riscv32/fegetround.c b/libm/riscv32/fegetround.c new file mode 100644 index 000000000..abd13fc7f --- /dev/null +++ b/libm/riscv32/fegetround.c @@ -0,0 +1,25 @@ +/* Return current rounding direction. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetround (void) +{ + return riscv_getround (); +} diff --git a/libm/riscv32/feholdexcpt.c b/libm/riscv32/feholdexcpt.c new file mode 100644 index 000000000..5d95a08fe --- /dev/null +++ b/libm/riscv32/feholdexcpt.c @@ -0,0 +1,26 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 2000-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feholdexcept (fenv_t *envp) +{ + libc_feholdexcept_riscv (envp); + return 0; +} diff --git a/libm/riscv32/fenv_private.h b/libm/riscv32/fenv_private.h new file mode 100644 index 000000000..9eed4b614 --- /dev/null +++ b/libm/riscv32/fenv_private.h @@ -0,0 +1,156 @@ +/* Private floating point rounding and exceptions handling. RISC-V version. + Copyright (C) 2014-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef RISCV_FENV_PRIVATE_H +#define RISCV_FENV_PRIVATE_H 1 + +#include <fenv.h> +#include <fpu_control.h> +#include "get-rounding-mode.h" + +static __always_inline int +riscv_getround (void) +{ + return get_rounding_mode (); +} + +static __always_inline void +riscv_setround (int rm) +{ + __asm__ volatile ("fsrm %z0" : : "rJ" (rm)); +} + +static __always_inline int +riscv_getflags (void) +{ + int flags; + __asm__ volatile ("frflags %0" : "=r" (flags)); + return flags; +} + +static __always_inline void +riscv_setflags (int flags) +{ + __asm__ volatile ("fsflags %z0" : : "rJ" (flags)); +} + +static __always_inline void +libc_feholdexcept_riscv (fenv_t *envp) +{ + __asm__ volatile ("csrrc %0, fcsr, %1" : "=r" (*envp) : "i" (FE_ALL_EXCEPT)); +} + +#define libc_feholdexcept libc_feholdexcept_riscv +#define libc_feholdexceptf libc_feholdexcept_riscv +#define libc_feholdexceptl libc_feholdexcept_riscv + +static __always_inline void +libc_fesetround_riscv (int round) +{ + riscv_setround (round); +} + +#define libc_fesetround libc_fesetround_riscv +#define libc_fesetroundf libc_fesetround_riscv +#define libc_fesetroundl libc_fesetround_riscv + +static __always_inline void +libc_feholdexcept_setround_riscv (fenv_t *envp, int round) +{ + libc_feholdexcept_riscv (envp); + libc_fesetround_riscv (round); +} + +#define libc_feholdexcept_setround libc_feholdexcept_setround_riscv +#define libc_feholdexcept_setroundf libc_feholdexcept_setround_riscv +#define libc_feholdexcept_setroundl libc_feholdexcept_setround_riscv + +static __always_inline int +libc_fetestexcept_riscv (int ex) +{ + return riscv_getflags () & ex; +} + +#define libc_fetestexcept libc_fetestexcept_riscv +#define libc_fetestexceptf libc_fetestexcept_riscv +#define libc_fetestexceptl libc_fetestexcept_riscv + +static __always_inline void +libc_fesetenv_riscv (const fenv_t *envp) +{ + long int env = (envp != FE_DFL_ENV ? *envp : 0); + _FPU_SETCW (env); +} + +#define libc_fesetenv libc_fesetenv_riscv +#define libc_fesetenvf libc_fesetenv_riscv +#define libc_fesetenvl libc_fesetenv_riscv +#define libc_feresetround_noex libc_fesetenv_riscv +#define libc_feresetround_noexf libc_fesetenv_riscv +#define libc_feresetround_noexl libc_fesetenv_riscv + +static __always_inline int +libc_feupdateenv_test_riscv (const fenv_t *envp, int ex) +{ + fenv_t env = *envp; + int flags = riscv_getflags (); + __asm__ volatile ("csrw fcsr, %z0" : : "rJ" (env | flags)); + return flags & ex; +} + +#define libc_feupdateenv_test libc_feupdateenv_test_riscv +#define libc_feupdateenv_testf libc_feupdateenv_test_riscv +#define libc_feupdateenv_testl libc_feupdateenv_test_riscv + +static __always_inline void +libc_feupdateenv_riscv (const fenv_t *envp) +{ + long int env = (envp != FE_DFL_ENV ? *envp : 0); + _FPU_SETCW (env | riscv_getflags ()); +} + +#define libc_feupdateenv libc_feupdateenv_riscv +#define libc_feupdateenvf libc_feupdateenv_riscv +#define libc_feupdateenvl libc_feupdateenv_riscv + +static __always_inline void +libc_feholdsetround_riscv (fenv_t *envp, int round) +{ + /* Note this implementation makes an improperly-formatted fenv_t and + so should only be used in conjunction with libc_feresetround. */ + int old_round; + __asm__ volatile ("csrrw %0, frm, %z1" : "=r" (old_round) : "rJ" (round)); + *envp = old_round; +} + +#define libc_feholdsetround libc_feholdsetround_riscv +#define libc_feholdsetroundf libc_feholdsetround_riscv +#define libc_feholdsetroundl libc_feholdsetround_riscv + +static __always_inline void +libc_feresetround_riscv (fenv_t *envp) +{ + /* Note this implementation takes an improperly-formatted fenv_t and + so should only be used in conjunction with libc_feholdsetround. */ + riscv_setround (*envp); +} + +#define libc_feresetround libc_feresetround_riscv +#define libc_feresetroundf libc_feresetround_riscv +#define libc_feresetroundl libc_feresetround_riscv + +#endif diff --git a/libm/riscv32/fesetenv.c b/libm/riscv32/fesetenv.c new file mode 100644 index 000000000..8b7427c18 --- /dev/null +++ b/libm/riscv32/fesetenv.c @@ -0,0 +1,26 @@ +/* Install given floating-point environment. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetenv (const fenv_t *envp) +{ + libc_fesetenv_riscv (envp); + return 0; +} diff --git a/libm/riscv32/fesetexcept.c b/libm/riscv32/fesetexcept.c new file mode 100644 index 000000000..9c931a1b7 --- /dev/null +++ b/libm/riscv32/fesetexcept.c @@ -0,0 +1,25 @@ +/* Set given exception flags. RISC-V version. + Copyright (C) 2017-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fesetexcept (int excepts) +{ + __asm__ volatile ("csrs fflags, %0" : : "r" (excepts)); + return 0; +} diff --git a/libm/riscv32/fesetmode.c b/libm/riscv32/fesetmode.c new file mode 100644 index 000000000..aaaf4480b --- /dev/null +++ b/libm/riscv32/fesetmode.c @@ -0,0 +1,30 @@ +/* Install given floating-point control modes. RISC-V version. + Copyright (C) 2017-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetmode (const femode_t *modep) +{ + __asm__ volatile ("csrc fcsr, %0" : : "r" (~FE_ALL_EXCEPT)); + + if (modep != FE_DFL_MODE) + __asm__ volatile ("csrs fcsr, %0" : : "r" (*modep & ~FE_ALL_EXCEPT)); + + return 0; +} diff --git a/libm/riscv32/fesetround.c b/libm/riscv32/fesetround.c new file mode 100644 index 000000000..a791751d1 --- /dev/null +++ b/libm/riscv32/fesetround.c @@ -0,0 +1,35 @@ +/* Set current rounding direction. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetround (int round) +{ + switch (round) + { + case FE_TONEAREST: + case FE_TOWARDZERO: + case FE_DOWNWARD: + case FE_UPWARD: + riscv_setround (round); + return 0; + default: + return round; /* A nonzero value. */ + } +} diff --git a/libm/riscv32/feupdateenv.c b/libm/riscv32/feupdateenv.c new file mode 100644 index 000000000..ea62bd1aa --- /dev/null +++ b/libm/riscv32/feupdateenv.c @@ -0,0 +1,26 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feupdateenv (const fenv_t *envp) +{ + libc_feupdateenv_riscv (envp); + return 0; +} diff --git a/libm/riscv32/fgetexcptflg.c b/libm/riscv32/fgetexcptflg.c new file mode 100644 index 000000000..ecf513bed --- /dev/null +++ b/libm/riscv32/fgetexcptflg.c @@ -0,0 +1,29 @@ +/* Store current representation for exceptions. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + /* Get the current exceptions. */ + *flagp = riscv_getflags () & excepts; + + /* Success. */ + return 0; +} diff --git a/libm/riscv32/fraiseexcpt.c b/libm/riscv32/fraiseexcpt.c new file mode 100644 index 000000000..f89f983d7 --- /dev/null +++ b/libm/riscv32/fraiseexcpt.c @@ -0,0 +1,26 @@ +/* Raise given exceptions. + Copyright (C) 2000-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feraiseexcept (int excepts) +{ + __asm__ volatile ("csrs fflags, %0" : : "r" (excepts)); + return 0; +} diff --git a/libm/riscv32/fsetexcptflg.c b/libm/riscv32/fsetexcptflg.c new file mode 100644 index 000000000..f295c18ab --- /dev/null +++ b/libm/riscv32/fsetexcptflg.c @@ -0,0 +1,29 @@ +/* Set floating-point environment exception handling. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fexcept_t flags = *flagp; + __asm__ volatile ("csrc fflags, %0" : : "r" (excepts)); + __asm__ volatile ("csrs fflags, %0" : : "r" (flags & excepts)); + + return 0; +} diff --git a/libm/riscv32/ftestexcept.c b/libm/riscv32/ftestexcept.c new file mode 100644 index 000000000..ed3a3e5e0 --- /dev/null +++ b/libm/riscv32/ftestexcept.c @@ -0,0 +1,25 @@ +/* Test exception in current environment. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fetestexcept (int excepts) +{ + return libc_fetestexcept_riscv (excepts); +} diff --git a/libm/riscv32/get-rounding-mode.h b/libm/riscv32/get-rounding-mode.h new file mode 100644 index 000000000..7ab691ac8 --- /dev/null +++ b/libm/riscv32/get-rounding-mode.h @@ -0,0 +1,32 @@ +/* Determine floating-point rounding mode within libc. RISC-V version. + Copyright (C) 2015-2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _RISCV_GET_ROUNDING_MODE_H +#define _RISCV_GET_ROUNDING_MODE_H + +/* Return the floating-point rounding mode. */ + +static inline int +get_rounding_mode (void) +{ + int rm; + __asm__ volatile ("frrm %0" : "=r" (rm)); + return rm; +} + +#endif /* get-rounding-mode.h */ diff --git a/libm/riscv64/Makefile.arch b/libm/riscv64/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/riscv64/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/riscv64/fclrexcpt.c b/libm/riscv64/fclrexcpt.c new file mode 100644 index 000000000..849a910fc --- /dev/null +++ b/libm/riscv64/fclrexcpt.c @@ -0,0 +1,26 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ + __asm__ volatile ("csrc fflags, %0" : : "r" (excepts)); + return 0; +} diff --git a/libm/riscv64/fegetenv.c b/libm/riscv64/fegetenv.c new file mode 100644 index 000000000..94f3444ac --- /dev/null +++ b/libm/riscv64/fegetenv.c @@ -0,0 +1,28 @@ +/* Store current floating-point environment. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetenv (fenv_t *envp) +{ + _FPU_GETCW (*envp); + + /* Success. */ + return 0; +} diff --git a/libm/riscv64/fegetmode.c b/libm/riscv64/fegetmode.c new file mode 100644 index 000000000..4b0ff270c --- /dev/null +++ b/libm/riscv64/fegetmode.c @@ -0,0 +1,26 @@ +/* Store current floating-point control modes. RISC-V version. + Copyright (C) 2017-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ + _FPU_GETCW (*modep); + return 0; +} diff --git a/libm/riscv64/fegetround.c b/libm/riscv64/fegetround.c new file mode 100644 index 000000000..abd13fc7f --- /dev/null +++ b/libm/riscv64/fegetround.c @@ -0,0 +1,25 @@ +/* Return current rounding direction. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetround (void) +{ + return riscv_getround (); +} diff --git a/libm/riscv64/feholdexcpt.c b/libm/riscv64/feholdexcpt.c new file mode 100644 index 000000000..5d95a08fe --- /dev/null +++ b/libm/riscv64/feholdexcpt.c @@ -0,0 +1,26 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 2000-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feholdexcept (fenv_t *envp) +{ + libc_feholdexcept_riscv (envp); + return 0; +} diff --git a/libm/riscv64/fenv_private.h b/libm/riscv64/fenv_private.h new file mode 100644 index 000000000..9eed4b614 --- /dev/null +++ b/libm/riscv64/fenv_private.h @@ -0,0 +1,156 @@ +/* Private floating point rounding and exceptions handling. RISC-V version. + Copyright (C) 2014-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef RISCV_FENV_PRIVATE_H +#define RISCV_FENV_PRIVATE_H 1 + +#include <fenv.h> +#include <fpu_control.h> +#include "get-rounding-mode.h" + +static __always_inline int +riscv_getround (void) +{ + return get_rounding_mode (); +} + +static __always_inline void +riscv_setround (int rm) +{ + __asm__ volatile ("fsrm %z0" : : "rJ" (rm)); +} + +static __always_inline int +riscv_getflags (void) +{ + int flags; + __asm__ volatile ("frflags %0" : "=r" (flags)); + return flags; +} + +static __always_inline void +riscv_setflags (int flags) +{ + __asm__ volatile ("fsflags %z0" : : "rJ" (flags)); +} + +static __always_inline void +libc_feholdexcept_riscv (fenv_t *envp) +{ + __asm__ volatile ("csrrc %0, fcsr, %1" : "=r" (*envp) : "i" (FE_ALL_EXCEPT)); +} + +#define libc_feholdexcept libc_feholdexcept_riscv +#define libc_feholdexceptf libc_feholdexcept_riscv +#define libc_feholdexceptl libc_feholdexcept_riscv + +static __always_inline void +libc_fesetround_riscv (int round) +{ + riscv_setround (round); +} + +#define libc_fesetround libc_fesetround_riscv +#define libc_fesetroundf libc_fesetround_riscv +#define libc_fesetroundl libc_fesetround_riscv + +static __always_inline void +libc_feholdexcept_setround_riscv (fenv_t *envp, int round) +{ + libc_feholdexcept_riscv (envp); + libc_fesetround_riscv (round); +} + +#define libc_feholdexcept_setround libc_feholdexcept_setround_riscv +#define libc_feholdexcept_setroundf libc_feholdexcept_setround_riscv +#define libc_feholdexcept_setroundl libc_feholdexcept_setround_riscv + +static __always_inline int +libc_fetestexcept_riscv (int ex) +{ + return riscv_getflags () & ex; +} + +#define libc_fetestexcept libc_fetestexcept_riscv +#define libc_fetestexceptf libc_fetestexcept_riscv +#define libc_fetestexceptl libc_fetestexcept_riscv + +static __always_inline void +libc_fesetenv_riscv (const fenv_t *envp) +{ + long int env = (envp != FE_DFL_ENV ? *envp : 0); + _FPU_SETCW (env); +} + +#define libc_fesetenv libc_fesetenv_riscv +#define libc_fesetenvf libc_fesetenv_riscv +#define libc_fesetenvl libc_fesetenv_riscv +#define libc_feresetround_noex libc_fesetenv_riscv +#define libc_feresetround_noexf libc_fesetenv_riscv +#define libc_feresetround_noexl libc_fesetenv_riscv + +static __always_inline int +libc_feupdateenv_test_riscv (const fenv_t *envp, int ex) +{ + fenv_t env = *envp; + int flags = riscv_getflags (); + __asm__ volatile ("csrw fcsr, %z0" : : "rJ" (env | flags)); + return flags & ex; +} + +#define libc_feupdateenv_test libc_feupdateenv_test_riscv +#define libc_feupdateenv_testf libc_feupdateenv_test_riscv +#define libc_feupdateenv_testl libc_feupdateenv_test_riscv + +static __always_inline void +libc_feupdateenv_riscv (const fenv_t *envp) +{ + long int env = (envp != FE_DFL_ENV ? *envp : 0); + _FPU_SETCW (env | riscv_getflags ()); +} + +#define libc_feupdateenv libc_feupdateenv_riscv +#define libc_feupdateenvf libc_feupdateenv_riscv +#define libc_feupdateenvl libc_feupdateenv_riscv + +static __always_inline void +libc_feholdsetround_riscv (fenv_t *envp, int round) +{ + /* Note this implementation makes an improperly-formatted fenv_t and + so should only be used in conjunction with libc_feresetround. */ + int old_round; + __asm__ volatile ("csrrw %0, frm, %z1" : "=r" (old_round) : "rJ" (round)); + *envp = old_round; +} + +#define libc_feholdsetround libc_feholdsetround_riscv +#define libc_feholdsetroundf libc_feholdsetround_riscv +#define libc_feholdsetroundl libc_feholdsetround_riscv + +static __always_inline void +libc_feresetround_riscv (fenv_t *envp) +{ + /* Note this implementation takes an improperly-formatted fenv_t and + so should only be used in conjunction with libc_feholdsetround. */ + riscv_setround (*envp); +} + +#define libc_feresetround libc_feresetround_riscv +#define libc_feresetroundf libc_feresetround_riscv +#define libc_feresetroundl libc_feresetround_riscv + +#endif diff --git a/libm/riscv64/fesetenv.c b/libm/riscv64/fesetenv.c new file mode 100644 index 000000000..8b7427c18 --- /dev/null +++ b/libm/riscv64/fesetenv.c @@ -0,0 +1,26 @@ +/* Install given floating-point environment. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetenv (const fenv_t *envp) +{ + libc_fesetenv_riscv (envp); + return 0; +} diff --git a/libm/riscv64/fesetexcept.c b/libm/riscv64/fesetexcept.c new file mode 100644 index 000000000..9c931a1b7 --- /dev/null +++ b/libm/riscv64/fesetexcept.c @@ -0,0 +1,25 @@ +/* Set given exception flags. RISC-V version. + Copyright (C) 2017-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fesetexcept (int excepts) +{ + __asm__ volatile ("csrs fflags, %0" : : "r" (excepts)); + return 0; +} diff --git a/libm/riscv64/fesetmode.c b/libm/riscv64/fesetmode.c new file mode 100644 index 000000000..aaaf4480b --- /dev/null +++ b/libm/riscv64/fesetmode.c @@ -0,0 +1,30 @@ +/* Install given floating-point control modes. RISC-V version. + Copyright (C) 2017-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetmode (const femode_t *modep) +{ + __asm__ volatile ("csrc fcsr, %0" : : "r" (~FE_ALL_EXCEPT)); + + if (modep != FE_DFL_MODE) + __asm__ volatile ("csrs fcsr, %0" : : "r" (*modep & ~FE_ALL_EXCEPT)); + + return 0; +} diff --git a/libm/riscv64/fesetround.c b/libm/riscv64/fesetround.c new file mode 100644 index 000000000..a791751d1 --- /dev/null +++ b/libm/riscv64/fesetround.c @@ -0,0 +1,35 @@ +/* Set current rounding direction. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetround (int round) +{ + switch (round) + { + case FE_TONEAREST: + case FE_TOWARDZERO: + case FE_DOWNWARD: + case FE_UPWARD: + riscv_setround (round); + return 0; + default: + return round; /* A nonzero value. */ + } +} diff --git a/libm/riscv64/feupdateenv.c b/libm/riscv64/feupdateenv.c new file mode 100644 index 000000000..ea62bd1aa --- /dev/null +++ b/libm/riscv64/feupdateenv.c @@ -0,0 +1,26 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feupdateenv (const fenv_t *envp) +{ + libc_feupdateenv_riscv (envp); + return 0; +} diff --git a/libm/riscv64/fgetexcptflg.c b/libm/riscv64/fgetexcptflg.c new file mode 100644 index 000000000..ecf513bed --- /dev/null +++ b/libm/riscv64/fgetexcptflg.c @@ -0,0 +1,29 @@ +/* Store current representation for exceptions. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + /* Get the current exceptions. */ + *flagp = riscv_getflags () & excepts; + + /* Success. */ + return 0; +} diff --git a/libm/riscv64/fraiseexcpt.c b/libm/riscv64/fraiseexcpt.c new file mode 100644 index 000000000..f89f983d7 --- /dev/null +++ b/libm/riscv64/fraiseexcpt.c @@ -0,0 +1,26 @@ +/* Raise given exceptions. + Copyright (C) 2000-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feraiseexcept (int excepts) +{ + __asm__ volatile ("csrs fflags, %0" : : "r" (excepts)); + return 0; +} diff --git a/libm/riscv64/fsetexcptflg.c b/libm/riscv64/fsetexcptflg.c new file mode 100644 index 000000000..f295c18ab --- /dev/null +++ b/libm/riscv64/fsetexcptflg.c @@ -0,0 +1,29 @@ +/* Set floating-point environment exception handling. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fexcept_t flags = *flagp; + __asm__ volatile ("csrc fflags, %0" : : "r" (excepts)); + __asm__ volatile ("csrs fflags, %0" : : "r" (flags & excepts)); + + return 0; +} diff --git a/libm/riscv64/ftestexcept.c b/libm/riscv64/ftestexcept.c new file mode 100644 index 000000000..ed3a3e5e0 --- /dev/null +++ b/libm/riscv64/ftestexcept.c @@ -0,0 +1,25 @@ +/* Test exception in current environment. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fetestexcept (int excepts) +{ + return libc_fetestexcept_riscv (excepts); +} diff --git a/libm/riscv64/get-rounding-mode.h b/libm/riscv64/get-rounding-mode.h new file mode 100644 index 000000000..7ab691ac8 --- /dev/null +++ b/libm/riscv64/get-rounding-mode.h @@ -0,0 +1,32 @@ +/* Determine floating-point rounding mode within libc. RISC-V version. + Copyright (C) 2015-2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _RISCV_GET_ROUNDING_MODE_H +#define _RISCV_GET_ROUNDING_MODE_H + +/* Return the floating-point rounding mode. */ + +static inline int +get_rounding_mode (void) +{ + int rm; + __asm__ volatile ("frrm %0" : "=r" (rm)); + return rm; +} + +#endif /* get-rounding-mode.h */ diff --git a/libm/sh/sh4/Makefile.arch b/libm/sh/sh4/Makefile.arch index e38e99c15..69996edda 100644 --- a/libm/sh/sh4/Makefile.arch +++ b/libm/sh/sh4/Makefile.arch @@ -8,7 +8,7 @@ ifeq ($(UCLIBC_HAS_FENV),y) libm_ARCH_CSRC:=$(wildcard $(libm_SUBARCH_DIR)/*.c) -libm_ARCH_COBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.c,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_SRC)) +libm_ARCH_COBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.c,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_CSRC)) libm_ARCH_SSRC:=$(wildcard $(libm_SUBARCH_DIR)/*.S) libm_ARCH_SOBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.S,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_SSRC)) endif diff --git a/libm/sh/sh4/fclrexcpt.c b/libm/sh/sh4/fclrexcpt.c new file mode 100644 index 000000000..286b4f36a --- /dev/null +++ b/libm/sh/sh4/fclrexcpt.c @@ -0,0 +1,39 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ + fpu_control_t cw; + + /* Mask out unsupported bits/exceptions. */ + excepts &= FE_ALL_EXCEPT; + + /* Read the complete control word. */ + _FPU_GETCW (cw); + + /* Clear exception bits. */ + cw &= ~excepts; + + /* Put the new data in effect. */ + _FPU_SETCW (cw); + + return 0; +} diff --git a/libm/sh/sh4/fedisblxcpt.c b/libm/sh/sh4/fedisblxcpt.c new file mode 100644 index 000000000..69f9ff2c4 --- /dev/null +++ b/libm/sh/sh4/fedisblxcpt.c @@ -0,0 +1,37 @@ +/* Disable floating-point exceptions. + Copyright (C) 2012-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fedisableexcept (int excepts) +{ + fpu_control_t temp, old_exc; + + /* Get the current control register contents. */ + _FPU_GETCW (temp); + + old_exc = (temp >> 5) & FE_ALL_EXCEPT; + + excepts &= FE_ALL_EXCEPT; + + temp &= ~(excepts << 5); + _FPU_SETCW (temp); + + return old_exc; +} diff --git a/libm/sh/sh4/feenablxcpt.c b/libm/sh/sh4/feenablxcpt.c new file mode 100644 index 000000000..bf2b01f0b --- /dev/null +++ b/libm/sh/sh4/feenablxcpt.c @@ -0,0 +1,36 @@ +/* Enable floating-point exceptions. + Copyright (C) 2012-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feenableexcept (int excepts) +{ + fpu_control_t temp, old_flag; + + /* Get current exceptions. */ + _FPU_GETCW (temp); + + old_flag = (temp >> 5) & FE_ALL_EXCEPT; + excepts &= FE_ALL_EXCEPT; + + temp |= excepts << 5; + _FPU_SETCW (temp); + + return old_flag; +} diff --git a/libm/sh/sh4/fegetenv.c b/libm/sh/sh4/fegetenv.c new file mode 100644 index 000000000..d76964f8b --- /dev/null +++ b/libm/sh/sh4/fegetenv.c @@ -0,0 +1,30 @@ +/* Store current floating-point environment. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetenv (fenv_t *envp) +{ + fpu_control_t temp; + _FPU_GETCW (temp); + + envp->__fpscr = temp; + + return 0; +} diff --git a/libm/sh/sh4/fegetexcept.c b/libm/sh/sh4/fegetexcept.c new file mode 100644 index 000000000..85f783520 --- /dev/null +++ b/libm/sh/sh4/fegetexcept.c @@ -0,0 +1,30 @@ +/* Get enabled floating-point exceptions. + Copyright (C) 2012-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetexcept (void) +{ + fpu_control_t temp; + + /* Get current exceptions. */ + _FPU_GETCW (temp); + + return (temp >> 5) & FE_ALL_EXCEPT; +} diff --git a/libm/sh/sh4/fegetmode.c b/libm/sh/sh4/fegetmode.c new file mode 100644 index 000000000..16deb5183 --- /dev/null +++ b/libm/sh/sh4/fegetmode.c @@ -0,0 +1,26 @@ +/* Store current floating-point control modes. SH4 version. + Copyright (C) 2016-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ + _FPU_GETCW (*modep); + return 0; +} diff --git a/libm/sh/sh4/fegetround.c b/libm/sh/sh4/fegetround.c new file mode 100644 index 000000000..b7c26eb6f --- /dev/null +++ b/libm/sh/sh4/fegetround.c @@ -0,0 +1,30 @@ +/* Return current rounding direction. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetround (void) +{ + fpu_control_t cw; + + /* Get control word. */ + _FPU_GETCW (cw); + + return cw & 0x1; +} diff --git a/libm/sh/sh4/feholdexcpt.c b/libm/sh/sh4/feholdexcpt.c index 70b51e8dd..fc462b403 100644 --- a/libm/sh/sh4/feholdexcpt.c +++ b/libm/sh/sh4/feholdexcpt.c @@ -1,13 +1,19 @@ -/* - * - * Copyright (c) 2007 STMicroelectronics Ltd - * Filippo Arcidiacono (filippo.arcidiacono@st.com) - * - * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. - * - * Taken from glibc 2.6 - * - */ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ #include <fenv.h> #include <fpu_control.h> @@ -15,15 +21,20 @@ int feholdexcept (fenv_t *envp) { - unsigned long int temp; + fpu_control_t temp; /* Store the environment. */ _FPU_GETCW (temp); envp->__fpscr = temp; - /* Now set all exceptions to non-stop. */ + /* Clear the status flags. */ temp &= ~FE_ALL_EXCEPT; + + /* Now set all exceptions to non-stop. */ + temp &= ~(FE_ALL_EXCEPT << 5); + _FPU_SETCW (temp); - return 1; + /* Success. */ + return 0; } diff --git a/libm/sh/sh4/fesetenv.c b/libm/sh/sh4/fesetenv.c index c5cfc1d51..6a9a68090 100644 --- a/libm/sh/sh4/fesetenv.c +++ b/libm/sh/sh4/fesetenv.c @@ -1,13 +1,19 @@ -/* - * - * Copyright (c) 2007 STMicroelectronics Ltd - * Filippo Arcidiacono (filippo.arcidiacono@st.com) - * - * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. - * - * Taken from glibc 2.6 - * - */ +/* Install given floating-point environment. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ #include <fenv.h> #include <fpu_control.h> @@ -19,7 +25,7 @@ fesetenv (const fenv_t *envp) _FPU_SETCW (_FPU_DEFAULT); else { - unsigned long int temp = envp->__fpscr; + fpu_control_t temp = envp->__fpscr; _FPU_SETCW (temp); } return 0; diff --git a/libm/sh/sh4/fesetexcept.c b/libm/sh/sh4/fesetexcept.c new file mode 100644 index 000000000..eceb0bb4f --- /dev/null +++ b/libm/sh/sh4/fesetexcept.c @@ -0,0 +1,31 @@ +/* Set given exception flags. SH4 version. + Copyright (C) 2016-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexcept (int excepts) +{ + fpu_control_t temp; + + _FPU_GETCW (temp); + temp |= (excepts & FE_ALL_EXCEPT); + _FPU_SETCW (temp); + + return 0; +} diff --git a/libm/sh/sh4/fesetmode.c b/libm/sh/sh4/fesetmode.c new file mode 100644 index 000000000..073da0984 --- /dev/null +++ b/libm/sh/sh4/fesetmode.c @@ -0,0 +1,37 @@ +/* Install given floating-point control modes. SH4 version. + Copyright (C) 2016-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +#define FPU_STATUS 0x3f07c + +int +fesetmode (const femode_t *modep) +{ + fpu_control_t fpscr; + + _FPU_GETCW (fpscr); + fpscr &= FPU_STATUS; + if (modep == FE_DFL_MODE) + fpscr |= _FPU_DEFAULT; + else + fpscr |= *modep & ~FPU_STATUS; + _FPU_SETCW (fpscr); + + return 0; +} diff --git a/libm/sh/sh4/fesetround.c b/libm/sh/sh4/fesetround.c new file mode 100644 index 000000000..144eca86f --- /dev/null +++ b/libm/sh/sh4/fesetround.c @@ -0,0 +1,40 @@ +/* Set current rounding direction. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetround (int round) +{ + fpu_control_t cw; + + if ((round & ~0x1) != 0) + /* ROUND is no valid rounding mode. */ + return 1; + + /* Get current state. */ + _FPU_GETCW (cw); + + /* Set rounding bits. */ + cw &= ~0x1; + cw |= round; + /* Set new state. */ + _FPU_SETCW (cw); + + return 0; +} diff --git a/libm/sh/sh4/feupdateenv.c b/libm/sh/sh4/feupdateenv.c new file mode 100644 index 000000000..cb7e95259 --- /dev/null +++ b/libm/sh/sh4/feupdateenv.c @@ -0,0 +1,36 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 2012-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feupdateenv (const fenv_t *envp) +{ + fpu_control_t temp; + + _FPU_GETCW (temp); + temp = (temp & FE_ALL_EXCEPT); + + /* Raise the saved exception. Incidentally for us the implementation + defined format of the values in objects of type fexcept_t is the + same as the ones specified using the FE_* constants. */ + fesetenv (envp); + feraiseexcept ((int) temp); + + return 0; +} diff --git a/libm/sh/sh4/fgetexcptflg.c b/libm/sh/sh4/fgetexcptflg.c new file mode 100644 index 000000000..308b5ad44 --- /dev/null +++ b/libm/sh/sh4/fgetexcptflg.c @@ -0,0 +1,37 @@ +/* Store current representation for exceptions. + Copyright (C) 2013-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + fpu_control_t temp; + + /* Get the current exceptions. */ + _FPU_GETCW (temp); + + /* We only save the relevant bits here. In particular, care has to be + taken with the CAUSE bits, as an inadvertent restore later on could + generate unexpected exceptions. */ + + *flagp = temp & excepts & FE_ALL_EXCEPT; + + /* Success. */ + return 0; +} diff --git a/libm/sh/sh4/fraiseexcpt.c b/libm/sh/sh4/fraiseexcpt.c new file mode 100644 index 000000000..1ed495b7a --- /dev/null +++ b/libm/sh/sh4/fraiseexcpt.c @@ -0,0 +1,70 @@ +/* Raise given exceptions. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <float.h> +#include <fpu_control.h> +#include <math.h> + +int +feraiseexcept (int excepts) +{ + if (excepts == 0) + return 0; + + /* Raise exceptions represented by EXPECTS. */ + + if (excepts & FE_INEXACT) + { + double d = 1.0, x = 3.0; + __asm__ __volatile__ ("fdiv %1, %0" : "+d" (d) : "d" (x)); + } + + if (excepts & FE_UNDERFLOW) + { + long double d = LDBL_MIN, x = 10; + __asm__ __volatile__ ("fdiv %1, %0" : "+d" (d) : "d" (x)); + } + + if (excepts & FE_OVERFLOW) + { + long double d = LDBL_MAX; + __asm__ __volatile__ ("fmul %0, %0" : "+d" (d) : "d" (d)); + } + + if (excepts & FE_DIVBYZERO) + { + double d = 1.0, x = 0.0; + __asm__ __volatile__ ("fdiv %1, %0" : "+d" (d) : "d" (x)); + } + + if (excepts & FE_INVALID) + { + double d = HUGE_VAL, x = 0.0; + __asm__ __volatile__ ("fmul %1, %0" : "+d" (d) : "d" (x)); + } + + { + /* Restore flag fields. */ + fpu_control_t cw; + _FPU_GETCW (cw); + cw |= (excepts & FE_ALL_EXCEPT); + _FPU_SETCW (cw); + } + + return 0; +} diff --git a/libm/sh/sh4/fsetexcptflg.c b/libm/sh/sh4/fsetexcptflg.c new file mode 100644 index 000000000..8fcb94973 --- /dev/null +++ b/libm/sh/sh4/fsetexcptflg.c @@ -0,0 +1,38 @@ +/* Set floating-point environment exception handling. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <math.h> +#include <fpu_control.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fpu_control_t temp; + + /* Get the current environment. */ + _FPU_GETCW (temp); + + /* Set the desired exception mask. */ + temp &= ~(excepts & FE_ALL_EXCEPT); + temp |= (*flagp & excepts & FE_ALL_EXCEPT); + + /* Save state back to the FPU. */ + _FPU_SETCW (temp); + + return 0; +} diff --git a/libm/sh/sh4/ftestexcept.c b/libm/sh/sh4/ftestexcept.c new file mode 100644 index 000000000..edc523426 --- /dev/null +++ b/libm/sh/sh4/ftestexcept.c @@ -0,0 +1,30 @@ +/* Test exception in current environment. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fetestexcept (int excepts) +{ + fpu_control_t temp; + + /* Get current exceptions. */ + _FPU_GETCW (temp); + + return temp & excepts & FE_ALL_EXCEPT; +} diff --git a/libm/sparc/Makefile.arch b/libm/sparc/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/sparc/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/sparc/fclrexcpt.c b/libm/sparc/fclrexcpt.c new file mode 100644 index 000000000..ae344658d --- /dev/null +++ b/libm/sparc/fclrexcpt.c @@ -0,0 +1,34 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feclearexcept (int excepts) +{ + fenv_t tmp; + + __fenv_stfsr (tmp); + + tmp &= ~(excepts & FE_ALL_EXCEPT); + + __fenv_ldfsr (tmp); + + /* Success. */ + return 0; +} diff --git a/libm/sparc/fedisblxcpt.c b/libm/sparc/fedisblxcpt.c new file mode 100644 index 000000000..9bc546f2d --- /dev/null +++ b/libm/sparc/fedisblxcpt.c @@ -0,0 +1,34 @@ +/* Disable floating-point exceptions. + Copyright (C) 2000-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fedisableexcept (int excepts) +{ + fenv_t new_exc, old_exc; + + __fenv_stfsr (new_exc); + + old_exc = (new_exc >> 18) & FE_ALL_EXCEPT; + new_exc &= ~(((fenv_t)excepts & FE_ALL_EXCEPT) << 18); + + __fenv_ldfsr (new_exc); + + return old_exc; +} diff --git a/libm/sparc/feenablxcpt.c b/libm/sparc/feenablxcpt.c new file mode 100644 index 000000000..ab88e7e42 --- /dev/null +++ b/libm/sparc/feenablxcpt.c @@ -0,0 +1,34 @@ +/* Enable floating-point exceptions. + Copyright (C) 2000-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feenableexcept (int excepts) +{ + fenv_t new_exc, old_exc; + + __fenv_stfsr (new_exc); + + old_exc = (new_exc >> 18) & FE_ALL_EXCEPT; + new_exc |= (((fenv_t)excepts & FE_ALL_EXCEPT) << 18); + + __fenv_ldfsr (new_exc); + + return old_exc; +} diff --git a/libm/sparc/fegetenv.c b/libm/sparc/fegetenv.c new file mode 100644 index 000000000..883012932 --- /dev/null +++ b/libm/sparc/fegetenv.c @@ -0,0 +1,28 @@ +/* Store current floating-point environment. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetenv (fenv_t *envp) +{ + __fenv_stfsr (*envp); + + /* Success. */ + return 0; +} diff --git a/libm/sparc/fegetexcept.c b/libm/sparc/fegetexcept.c new file mode 100644 index 000000000..53dfdab8c --- /dev/null +++ b/libm/sparc/fegetexcept.c @@ -0,0 +1,28 @@ +/* Get enabled floating-point exceptions. + Copyright (C) 2000-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetexcept (void) +{ + fenv_t exc; + __fenv_stfsr (exc); + + return (exc >> 18) & FE_ALL_EXCEPT; +} diff --git a/libm/sparc/fegetmode.c b/libm/sparc/fegetmode.c new file mode 100644 index 000000000..0bb9ba111 --- /dev/null +++ b/libm/sparc/fegetmode.c @@ -0,0 +1,26 @@ +/* Store current floating-point control modes. SPARC version. + Copyright (C) 2016-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetmode (femode_t *modep) +{ + __fenv_stfsr (*modep); + return 0; +} diff --git a/libm/sparc/fegetround.c b/libm/sparc/fegetround.c new file mode 100644 index 000000000..bb53a735e --- /dev/null +++ b/libm/sparc/fegetround.c @@ -0,0 +1,29 @@ +/* Return current rounding direction. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetround (void) +{ + fenv_t tmp; + + __fenv_stfsr (tmp); + + return tmp & __FE_ROUND_MASK; +} diff --git a/libm/sparc/feholdexcpt.c b/libm/sparc/feholdexcpt.c new file mode 100644 index 000000000..7d712198b --- /dev/null +++ b/libm/sparc/feholdexcpt.c @@ -0,0 +1,34 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feholdexcept (fenv_t *envp) +{ + fenv_t tmp; + + __fenv_stfsr (*envp); + + /* Set all exceptions to non-stop and clear all exceptions. */ + tmp = *envp & ~((0x1f << 23) | FE_ALL_EXCEPT); + + __fenv_ldfsr (tmp); + + return 0; +} diff --git a/libm/sparc/fenv_private.h b/libm/sparc/fenv_private.h new file mode 100644 index 000000000..b888d8442 --- /dev/null +++ b/libm/sparc/fenv_private.h @@ -0,0 +1,187 @@ +#ifndef SPARC_FENV_PRIVATE_H +#define SPARC_FENV_PRIVATE_H 1 + +#include <fenv.h> +#include <fpu_control.h> + +/* For internal use only: access the fp state register. */ +#define __fenv_stfsr(X) _FPU_GETCW (X) +#define __fenv_ldfsr(X) _FPU_SETCW (X) + +static __always_inline void +libc_feholdexcept (fenv_t *e) +{ + fenv_t etmp; + __fenv_stfsr(etmp); + *(e) = etmp; + etmp = etmp & ~((0x1f << 23) | FE_ALL_EXCEPT); + __fenv_ldfsr(etmp); +} + +static __always_inline void +libc_fesetround (int r) +{ + fenv_t etmp; + __fenv_stfsr(etmp); + etmp = (etmp & ~__FE_ROUND_MASK) | (r); + __fenv_ldfsr(etmp); +} + +static __always_inline void +libc_feholdexcept_setround (fenv_t *e, int r) +{ + fenv_t etmp; + __fenv_stfsr(etmp); + *(e) = etmp; + etmp = etmp & ~((0x1f << 23) | FE_ALL_EXCEPT); + etmp = (etmp & ~__FE_ROUND_MASK) | (r); + __fenv_ldfsr(etmp); +} + +static __always_inline int +libc_fetestexcept (int e) +{ + fenv_t etmp; + __fenv_stfsr(etmp); + return etmp & (e) & FE_ALL_EXCEPT; +} + +static __always_inline void +libc_fesetenv (fenv_t *e) +{ + __fenv_ldfsr(*e); +} + +static __always_inline int +libc_feupdateenv_test (fenv_t *e, int ex) +{ + fenv_t etmp; + + __fenv_stfsr(etmp); + etmp &= FE_ALL_EXCEPT; + + __fenv_ldfsr(*e); + + feraiseexcept (etmp); + + return etmp & ex; +} + +static __always_inline void +libc_feupdateenv (fenv_t *e) +{ + libc_feupdateenv_test (e, 0); +} + +static __always_inline void +libc_feholdsetround (fenv_t *e, int r) +{ + fenv_t etmp; + __fenv_stfsr(etmp); + *(e) = etmp; + etmp = (etmp & ~__FE_ROUND_MASK) | (r); + __fenv_ldfsr(etmp); +} + +static __always_inline void +libc_feresetround (fenv_t *e) +{ + fenv_t etmp; + __fenv_stfsr(etmp); + etmp = (etmp & ~__FE_ROUND_MASK) | (*e & __FE_ROUND_MASK); + __fenv_ldfsr(etmp); +} + +#define libc_feholdexceptf libc_feholdexcept +#define libc_fesetroundf libc_fesetround +#define libc_feholdexcept_setroundf libc_feholdexcept_setround +#define libc_fetestexceptf libc_fetestexcept +#define libc_fesetenvf libc_fesetenv +#define libc_feupdateenv_testf libc_feupdateenv_test +#define libc_feupdateenvf libc_feupdateenv +#define libc_feholdsetroundf libc_feholdsetround +#define libc_feresetroundf libc_feresetround +#define libc_feholdexcept libc_feholdexcept +#define libc_fesetround libc_fesetround +#define libc_feholdexcept_setround libc_feholdexcept_setround +#define libc_fetestexcept libc_fetestexcept +#define libc_fesetenv libc_fesetenv +#define libc_feupdateenv_test libc_feupdateenv_test +#define libc_feupdateenv libc_feupdateenv +#define libc_feholdsetround libc_feholdsetround +#define libc_feresetround libc_feresetround +#define libc_feholdexceptl libc_feholdexcept +#define libc_fesetroundl libc_fesetround +#define libc_feholdexcept_setroundl libc_feholdexcept_setround +#define libc_fetestexceptl libc_fetestexcept +#define libc_fesetenvl libc_fesetenv +#define libc_feupdateenv_testl libc_feupdateenv_test +#define libc_feupdateenvl libc_feupdateenv +#define libc_feholdsetroundl libc_feholdsetround +#define libc_feresetroundl libc_feresetround + +/* We have support for rounding mode context. */ +#define HAVE_RM_CTX 1 + +static __always_inline void +libc_feholdexcept_setround_sparc_ctx (struct rm_ctx *ctx, int round) +{ + fenv_t new; + + __fenv_stfsr(ctx->env); + new = ctx->env & ~((0x1f << 23) | FE_ALL_EXCEPT); + new = (new & ~__FE_ROUND_MASK) | round; + if (unlikely (new != ctx->env)) + { + __fenv_ldfsr(new); + ctx->updated_status = true; + } + else + ctx->updated_status = false; +} + +static __always_inline void +libc_fesetenv_sparc_ctx (struct rm_ctx *ctx) +{ + libc_fesetenv(&ctx->env); +} + +static __always_inline void +libc_feupdateenv_sparc_ctx (struct rm_ctx *ctx) +{ + if (unlikely (ctx->updated_status)) + libc_feupdateenv_test (&ctx->env, 0); +} + +static __always_inline void +libc_feholdsetround_sparc_ctx (struct rm_ctx *ctx, int round) +{ + fenv_t new; + + __fenv_stfsr(ctx->env); + new = (ctx->env & ~__FE_ROUND_MASK) | round; + if (unlikely (new != ctx->env)) + { + __fenv_ldfsr(new); + ctx->updated_status = true; + } + else + ctx->updated_status = false; +} +#define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_sparc_ctx +#define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_sparc_ctx +#define libc_feholdexcept_setroundl_ctx libc_feholdexcept_setround_sparc_ctx +#define libc_fesetenv_ctx libc_fesetenv_sparc_ctx +#define libc_fesetenvf_ctx libc_fesetenv_sparc_ctx +#define libc_fesetenvl_ctx libc_fesetenv_sparc_ctx +#define libc_feupdateenv_ctx libc_feupdateenv_sparc_ctx +#define libc_feupdateenvf_ctx libc_feupdateenv_sparc_ctx +#define libc_feupdateenvl_ctx libc_feupdateenv_sparc_ctx +#define libc_feresetround_ctx libc_feupdateenv_sparc_ctx +#define libc_feresetroundf_ctx libc_feupdateenv_sparc_ctx +#define libc_feresetroundl_ctx libc_feupdateenv_sparc_ctx +#define libc_feholdsetround_ctx libc_feholdsetround_sparc_ctx +#define libc_feholdsetroundf_ctx libc_feholdsetround_sparc_ctx +#define libc_feholdsetroundl_ctx libc_feholdsetround_sparc_ctx + +#endif /* SPARC_FENV_PRIVATE_H */ diff --git a/libm/sparc/fesetenv.c b/libm/sparc/fesetenv.c new file mode 100644 index 000000000..d6f3dc5f5 --- /dev/null +++ b/libm/sparc/fesetenv.c @@ -0,0 +1,45 @@ +/* Install given floating-point environment. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetenv (const fenv_t *envp) +{ + fenv_t dummy; + + /* Put these constants in memory explicitly, so as to cope with a + -fPIC bug as of gcc 970624. Making them automatic is quicker + than loading up the pic register in this instance. */ + + if (envp == FE_DFL_ENV) + { + dummy = 0; + envp = &dummy; + } + else if (envp == FE_NOMASK_ENV) + { + dummy = 0x1f << 23; + envp = &dummy; + } + + __fenv_ldfsr (*envp); + + /* Success. */ + return 0; +} diff --git a/libm/sparc/fesetexcept.c b/libm/sparc/fesetexcept.c new file mode 100644 index 000000000..02210b691 --- /dev/null +++ b/libm/sparc/fesetexcept.c @@ -0,0 +1,31 @@ +/* Set given exception flags. SPARC version. + Copyright (C) 2016-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetexcept (int excepts) +{ + fenv_t tmp; + + __fenv_stfsr (tmp); + tmp |= excepts & FE_ALL_EXCEPT; + __fenv_ldfsr (tmp); + + return 0; +} diff --git a/libm/sparc/fesetmode.c b/libm/sparc/fesetmode.c new file mode 100644 index 000000000..e72b3d9df --- /dev/null +++ b/libm/sparc/fesetmode.c @@ -0,0 +1,38 @@ +/* Install given floating-point control modes. SPARC version. + Copyright (C) 2016-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" +#include <fpu_control.h> + +#define FPU_CONTROL_BITS 0xcfc00000UL + +int +fesetmode (const femode_t *modep) +{ + femode_t fsr; + + __fenv_stfsr (fsr); + fsr &= ~FPU_CONTROL_BITS; + if (modep == FE_DFL_MODE) + fsr |= _FPU_DEFAULT; + else + fsr |= *modep & FPU_CONTROL_BITS; + __fenv_ldfsr (fsr); + + return 0; +} diff --git a/libm/sparc/fesetround.c b/libm/sparc/fesetround.c new file mode 100644 index 000000000..ba3a4e50f --- /dev/null +++ b/libm/sparc/fesetround.c @@ -0,0 +1,36 @@ +/* Set current rounding direction. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetround (int round) +{ + fenv_t tmp; + + if ((round & ~__FE_ROUND_MASK) != 0) + /* ROUND is no valid rounding mode. */ + return 1; + + __fenv_stfsr (tmp); + tmp &= ~__FE_ROUND_MASK; + tmp |= round; + __fenv_ldfsr (tmp); + + return 0; +} diff --git a/libm/sparc/feupdateenv.c b/libm/sparc/feupdateenv.c new file mode 100644 index 000000000..272536cf3 --- /dev/null +++ b/libm/sparc/feupdateenv.c @@ -0,0 +1,40 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feupdateenv (const fenv_t *envp) +{ + fexcept_t tmp; + + /* Save current exceptions. */ + __fenv_stfsr (tmp); + tmp &= FE_ALL_EXCEPT; + + /* Install new environment. */ + fesetenv (envp); + + /* Raise the saved exception. Incidentally for us the implementation + defined format of the values in objects of type fexcept_t is the + same as the ones specified using the FE_* constants. */ + feraiseexcept ((int) tmp); + + /* Success. */ + return 0; +} diff --git a/libm/sparc/fgetexcptflg.c b/libm/sparc/fgetexcptflg.c new file mode 100644 index 000000000..d8568906e --- /dev/null +++ b/libm/sparc/fgetexcptflg.c @@ -0,0 +1,33 @@ +/* Store current representation for exceptions. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + fexcept_t tmp; + + /* Get the current exceptions. */ + __fenv_stfsr (tmp); + + *flagp = tmp & excepts & FE_ALL_EXCEPT; + + /* Success. */ + return 0; +} diff --git a/libm/sparc/fpu_control.h b/libm/sparc/fpu_control.h new file mode 100644 index 000000000..542f9fb1b --- /dev/null +++ b/libm/sparc/fpu_control.h @@ -0,0 +1,75 @@ +/* FPU control word bits. SPARC version. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H 1 + + +#include <features.h> +#include <bits/wordsize.h> + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x08000000 +#define _FPU_MASK_OM 0x04000000 +#define _FPU_MASK_UM 0x02000000 +#define _FPU_MASK_ZM 0x01000000 +#define _FPU_MASK_PM 0x00800000 + +/* precision control */ +#define _FPU_EXTENDED 0x00000000 /* RECOMMENDED */ +#define _FPU_DOUBLE 0x20000000 +#define _FPU_80BIT 0x30000000 +#define _FPU_SINGLE 0x10000000 /* DO NOT USE */ + +/* rounding control / Sparc */ +#define _FPU_RC_DOWN 0xc0000000 +#define _FPU_RC_UP 0x80000000 +#define _FPU_RC_ZERO 0x40000000 +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ + +#define _FPU_RESERVED 0x303e0000 /* Reserved bits in cw */ + + +/* Now two recommended cw */ + +/* Linux and IEEE default: + - extended precision + - rounding to nearest + - no exceptions */ +#define _FPU_DEFAULT 0x0 +#define _FPU_IEEE 0x0 + +/* Type of the control word. */ +typedef unsigned long int fpu_control_t; + +#if __WORDSIZE == 64 +# define _FPU_GETCW(cw) __asm__ __volatile__ ("stx %%fsr,%0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ __volatile__ ("ldx %0,%%fsr" : : "m" (*&cw)) +#else +# ifdef __leon__ + /* Prevent stfsr from being placed directly after other fp instruction. */ +# define _FPU_GETCW(cw) __asm__ __volatile__ ("nop; st %%fsr,%0" : "=m" (*&cw)) +# else +# define _FPU_GETCW(cw) __asm__ __volatile__ ("st %%fsr,%0" : "=m" (*&cw)) +# endif +# define _FPU_SETCW(cw) __asm__ __volatile__ ("ld %0,%%fsr" : : "m" (*&cw)) +#endif + +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; + +#endif /* fpu_control.h */ diff --git a/libm/sparc/fraiseexcpt.c b/libm/sparc/fraiseexcpt.c new file mode 100644 index 000000000..72e151fe6 --- /dev/null +++ b/libm/sparc/fraiseexcpt.c @@ -0,0 +1,81 @@ +/* Raise given exceptions. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <float.h> +#include <math.h> +#include "math-barriers.h" + +int +feraiseexcept (int excepts) +{ + static const struct { + double zero, one, max, min, pi; + } c = { + 0.0, 1.0, DBL_MAX, DBL_MIN, M_PI + }; + double d; + + /* Raise exceptions represented by EXPECTS. But we must raise only + one signal at a time. It is important the if the overflow/underflow + exception and the inexact exception are given at the same time, + the overflow/underflow exception follows the inexact exception. */ + + /* First: invalid exception. */ + if ((FE_INVALID & excepts) != 0) + { + /* One example of an invalid operation is 0/0. */ + __asm__ ("" : "=e" (d) : "0" (c.zero)); + d /= c.zero; + math_force_eval (d); + } + + /* Next: division by zero. */ + if ((FE_DIVBYZERO & excepts) != 0) + { + __asm__ ("" : "=e" (d) : "0" (c.one)); + d /= c.zero; + math_force_eval (d); + } + + /* Next: overflow. */ + if ((FE_OVERFLOW & excepts) != 0) + { + __asm__ ("" : "=e" (d) : "0" (c.max)); + d *= d; + math_force_eval (d); + } + + /* Next: underflow. */ + if ((FE_UNDERFLOW & excepts) != 0) + { + __asm__ ("" : "=e" (d) : "0" (c.min)); + d *= d; + math_force_eval (d); + } + + /* Last: inexact. */ + if ((FE_INEXACT & excepts) != 0) + { + __asm__ ("" : "=e" (d) : "0" (c.one)); + d /= c.pi; + math_force_eval (d); + } + + /* Success. */ + return 0; +} diff --git a/libm/sparc/fsetexcptflg.c b/libm/sparc/fsetexcptflg.c new file mode 100644 index 000000000..4b3b6ae68 --- /dev/null +++ b/libm/sparc/fsetexcptflg.c @@ -0,0 +1,36 @@ +/* Set floating-point environment exception handling. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" +#include <math.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fenv_t tmp; + + __fenv_stfsr (tmp); + + tmp &= ~(excepts & FE_ALL_EXCEPT); + tmp |= *flagp & excepts & FE_ALL_EXCEPT; + + __fenv_ldfsr (tmp); + + /* Success. */ + return 0; +} diff --git a/libm/sparc/ftestexcept.c b/libm/sparc/ftestexcept.c new file mode 100644 index 000000000..1fe87bb36 --- /dev/null +++ b/libm/sparc/ftestexcept.c @@ -0,0 +1,29 @@ +/* Test exception in current environment. + Copyright (C) 1997-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fetestexcept (int excepts) +{ + fenv_t tmp; + + __fenv_stfsr (tmp); + + return tmp & excepts & FE_ALL_EXCEPT; +} diff --git a/libm/sparc/math-barriers.h b/libm/sparc/math-barriers.h new file mode 100644 index 000000000..4b02ff47b --- /dev/null +++ b/libm/sparc/math-barriers.h @@ -0,0 +1,36 @@ +/* Control when floating-point expressions are evaluated. Generic version. + Copyright (C) 2007-2025 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _MATH_BARRIERS_H +#define _MATH_BARRIERS_H 1 + +/* math_opt_barrier evaluates and returns its floating-point argument + and ensures that the evaluation of any expression using the result + of math_opt_barrier is not moved before the call. math_force_eval + ensures that its floating-point argument is evaluated for its side + effects even if its value is apparently unused, and that the + evaluation of its argument is not moved after the call. Both these + macros are used to ensure the correct ordering of floating-point + expression evaluations with respect to accesses to the + floating-point environment. */ + +#define math_opt_barrier(x) \ + ({ __typeof (x) __x = (x); __asm ("" : "+m" (__x)); __x; }) +#define math_force_eval(x) \ + ({ __typeof (x) __x = (x); __asm __volatile__ ("" : : "m" (__x)); }) + +#endif /* math-barriers.h */ |