diff options
Diffstat (limited to 'libm')
213 files changed, 8976 insertions, 48 deletions
| diff --git a/libm/aarch64/Makefile.arch b/libm/aarch64/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/aarch64/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/aarch64/fclrexcpt.c b/libm/aarch64/fclrexcpt.c new file mode 100644 index 000000000..3dbd9a8bb --- /dev/null +++ b/libm/aarch64/fclrexcpt.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ +  fpu_fpsr_t fpsr; +  fpu_fpsr_t fpsr_new; + +  excepts &= FE_ALL_EXCEPT; + +  _FPU_GETFPSR (fpsr); +  fpsr_new = fpsr & ~excepts; + +  if (fpsr != fpsr_new) +    _FPU_SETFPSR (fpsr_new); + +  return 0; +} diff --git a/libm/aarch64/fedisblxcpt.c b/libm/aarch64/fedisblxcpt.c new file mode 100644 index 000000000..a36873690 --- /dev/null +++ b/libm/aarch64/fedisblxcpt.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2001-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fedisableexcept (int excepts) +{ +  fpu_control_t fpcr; +  fpu_control_t fpcr_new; + +  _FPU_GETCW (fpcr); +  excepts &= FE_ALL_EXCEPT; +  fpcr_new = fpcr & ~(excepts << FE_EXCEPT_SHIFT); + +  if (fpcr != fpcr_new) +    _FPU_SETCW (fpcr_new); + +  return (fpcr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT; +} diff --git a/libm/aarch64/feenablxcpt.c b/libm/aarch64/feenablxcpt.c new file mode 100644 index 000000000..b5aa3bdc6 --- /dev/null +++ b/libm/aarch64/feenablxcpt.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2001-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feenableexcept (int excepts) +{ +  fpu_control_t fpcr; +  fpu_control_t fpcr_new; +  fpu_control_t updated_fpcr; + +  _FPU_GETCW (fpcr); +  excepts &= FE_ALL_EXCEPT; +  fpcr_new = fpcr | (excepts << FE_EXCEPT_SHIFT); + +  if (fpcr != fpcr_new) +    { +      _FPU_SETCW (fpcr_new); + +      /* Trapping exceptions are optional in AArch64; the relevant enable +	 bits in FPCR are RES0 hence the absence of support can be detected +	 by reading back the FPCR and comparing with the required value.  */ +      _FPU_GETCW (updated_fpcr); + +      if (fpcr_new & ~updated_fpcr) +	return -1; +    } + +  return (fpcr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT; +} diff --git a/libm/aarch64/fegetenv.c b/libm/aarch64/fegetenv.c new file mode 100644 index 000000000..a85575eb8 --- /dev/null +++ b/libm/aarch64/fegetenv.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetenv (fenv_t *envp) +{ +  fpu_control_t fpcr; +  fpu_fpsr_t fpsr; +  _FPU_GETCW (fpcr); +  _FPU_GETFPSR (fpsr); +  envp->__fpcr = fpcr; +  envp->__fpsr = fpsr; +  return 0; +} diff --git a/libm/aarch64/fegetexcept.c b/libm/aarch64/fegetexcept.c new file mode 100644 index 000000000..a9eac299c --- /dev/null +++ b/libm/aarch64/fegetexcept.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2001-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetexcept (void) +{ +  fpu_control_t fpcr; +  _FPU_GETCW (fpcr); +  return (fpcr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT; +} diff --git a/libm/aarch64/fegetmode.c b/libm/aarch64/fegetmode.c new file mode 100644 index 000000000..8393e6d05 --- /dev/null +++ b/libm/aarch64/fegetmode.c @@ -0,0 +1,26 @@ +/* Store current floating-point control modes.  AArch64 version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ +  _FPU_GETCW (*modep); +  return 0; +} diff --git a/libm/aarch64/fegetround.c b/libm/aarch64/fegetround.c new file mode 100644 index 000000000..1f34c6918 --- /dev/null +++ b/libm/aarch64/fegetround.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +/* Return the floating-point rounding mode.  */ + +static inline int +get_rounding_mode (void) +{ +  fpu_control_t fpcr; + +  _FPU_GETCW (fpcr); +  return fpcr & _FPU_FPCR_RM_MASK; +} + +int +fegetround (void) +{ +  return get_rounding_mode (); +} diff --git a/libm/aarch64/feholdexcpt.c b/libm/aarch64/feholdexcpt.c new file mode 100644 index 000000000..09c8cd38b --- /dev/null +++ b/libm/aarch64/feholdexcpt.c @@ -0,0 +1,25 @@ +/* Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feholdexcept (fenv_t *envp) +{ +  libc_feholdexcept_aarch64 (envp); +  return 0; +} diff --git a/libm/aarch64/fenv_private.h b/libm/aarch64/fenv_private.h new file mode 100644 index 000000000..5afb790ea --- /dev/null +++ b/libm/aarch64/fenv_private.h @@ -0,0 +1,300 @@ +/* Private floating point rounding and exceptions handling.  AArch64 version. +   Copyright (C) 2014-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#ifndef AARCH64_FENV_PRIVATE_H +#define AARCH64_FENV_PRIVATE_H 1 + +#include <fenv.h> +#include <fpu_control.h> + +static __always_inline void +libc_feholdexcept_aarch64 (fenv_t *envp) +{ +  fpu_control_t fpcr; +  fpu_control_t new_fpcr; +  fpu_fpsr_t fpsr; +  fpu_fpsr_t new_fpsr; + +  _FPU_GETCW (fpcr); +  _FPU_GETFPSR (fpsr); +  envp->__fpcr = fpcr; +  envp->__fpsr = fpsr; + +  /* Clear exception flags and set all exceptions to non-stop.  */ +  new_fpcr = fpcr & ~(FE_ALL_EXCEPT << FE_EXCEPT_SHIFT); +  new_fpsr = fpsr & ~FE_ALL_EXCEPT; + +  if (unlikely (new_fpcr != fpcr)) +    _FPU_SETCW (new_fpcr); + +  if (new_fpsr != fpsr) +    _FPU_SETFPSR (new_fpsr); +} + +#define libc_feholdexcept  libc_feholdexcept_aarch64 +#define libc_feholdexceptf libc_feholdexcept_aarch64 +#define libc_feholdexceptl libc_feholdexcept_aarch64 + +static __always_inline void +libc_fesetround_aarch64 (int round) +{ +  fpu_control_t fpcr; + +  _FPU_GETCW (fpcr); + +  /* Check whether rounding modes are different.  */ +  round = (fpcr ^ round) & _FPU_FPCR_RM_MASK; + +  /* Set new rounding mode if different.  */ +  if (unlikely (round != 0)) +    _FPU_SETCW (fpcr ^ round); +} + +#define libc_fesetround  libc_fesetround_aarch64 +#define libc_fesetroundf libc_fesetround_aarch64 +#define libc_fesetroundl libc_fesetround_aarch64 + +static __always_inline void +libc_feholdexcept_setround_aarch64 (fenv_t *envp, int round) +{ +  fpu_control_t fpcr; +  fpu_control_t new_fpcr; +  fpu_fpsr_t fpsr; +  fpu_fpsr_t new_fpsr; + +  _FPU_GETCW (fpcr); +  _FPU_GETFPSR (fpsr); +  envp->__fpcr = fpcr; +  envp->__fpsr = fpsr; + +  /* Clear exception flags, set all exceptions to non-stop, +     and set new rounding mode.  */ +  new_fpcr = fpcr & ~((FE_ALL_EXCEPT << FE_EXCEPT_SHIFT) | _FPU_FPCR_RM_MASK); +  new_fpcr |= round; +  new_fpsr = fpsr & ~FE_ALL_EXCEPT; + +  if (unlikely (new_fpcr != fpcr)) +    _FPU_SETCW (new_fpcr); + +  if (new_fpsr != fpsr) +    _FPU_SETFPSR (new_fpsr); +} + +#define libc_feholdexcept_setround  libc_feholdexcept_setround_aarch64 +#define libc_feholdexcept_setroundf libc_feholdexcept_setround_aarch64 +#define libc_feholdexcept_setroundl libc_feholdexcept_setround_aarch64 + +static __always_inline int +libc_fetestexcept_aarch64 (int ex) +{ +  fpu_fpsr_t fpsr; + +  _FPU_GETFPSR (fpsr); +  return fpsr & ex & FE_ALL_EXCEPT; +} + +#define libc_fetestexcept  libc_fetestexcept_aarch64 +#define libc_fetestexceptf libc_fetestexcept_aarch64 +#define libc_fetestexceptl libc_fetestexcept_aarch64 + +static __always_inline void +libc_fesetenv_aarch64 (const fenv_t *envp) +{ +  fpu_control_t fpcr; +  fpu_control_t new_fpcr; + +  _FPU_GETCW (fpcr); +  new_fpcr = envp->__fpcr; + +  if (unlikely (fpcr != new_fpcr)) +    _FPU_SETCW (new_fpcr); + +  _FPU_SETFPSR (envp->__fpsr); +} + +#define libc_fesetenv  libc_fesetenv_aarch64 +#define libc_fesetenvf libc_fesetenv_aarch64 +#define libc_fesetenvl libc_fesetenv_aarch64 +#define libc_feresetround_noex  libc_fesetenv_aarch64 +#define libc_feresetround_noexf libc_fesetenv_aarch64 +#define libc_feresetround_noexl libc_fesetenv_aarch64 + +static __always_inline int +libc_feupdateenv_test_aarch64 (const fenv_t *envp, int ex) +{ +  fpu_control_t fpcr; +  fpu_control_t new_fpcr; +  fpu_fpsr_t fpsr; +  fpu_fpsr_t new_fpsr; +  int excepts; + +  _FPU_GETCW (fpcr); +  _FPU_GETFPSR (fpsr); + +  /* Merge current exception flags with the saved fenv.  */ +  excepts = fpsr & FE_ALL_EXCEPT; +  new_fpcr = envp->__fpcr; +  new_fpsr = envp->__fpsr | excepts; + +  if (unlikely (fpcr != new_fpcr)) +    _FPU_SETCW (new_fpcr); + +  if (fpsr != new_fpsr) +    _FPU_SETFPSR (new_fpsr); + +  /* Raise the exceptions if enabled in the new FP state.  */ +  if (unlikely (excepts & (new_fpcr >> FE_EXCEPT_SHIFT))) +    feraiseexcept (excepts); + +  return excepts & ex; +} + +#define libc_feupdateenv_test  libc_feupdateenv_test_aarch64 +#define libc_feupdateenv_testf libc_feupdateenv_test_aarch64 +#define libc_feupdateenv_testl libc_feupdateenv_test_aarch64 + +static __always_inline void +libc_feupdateenv_aarch64 (const fenv_t *envp) +{ +  libc_feupdateenv_test_aarch64 (envp, 0); +} + +#define libc_feupdateenv  libc_feupdateenv_aarch64 +#define libc_feupdateenvf libc_feupdateenv_aarch64 +#define libc_feupdateenvl libc_feupdateenv_aarch64 + +static __always_inline void +libc_feholdsetround_aarch64 (fenv_t *envp, int round) +{ +  fpu_control_t fpcr; +  fpu_fpsr_t fpsr; + +  _FPU_GETCW (fpcr); +  _FPU_GETFPSR (fpsr); +  envp->__fpcr = fpcr; +  envp->__fpsr = fpsr; + +  /* Check whether rounding modes are different.  */ +  round = (fpcr ^ round) & _FPU_FPCR_RM_MASK; + +  /* Set new rounding mode if different.  */ +  if (unlikely (round != 0)) +    _FPU_SETCW (fpcr ^ round); +} + +#define libc_feholdsetround  libc_feholdsetround_aarch64 +#define libc_feholdsetroundf libc_feholdsetround_aarch64 +#define libc_feholdsetroundl libc_feholdsetround_aarch64 + +static __always_inline void +libc_feresetround_aarch64 (fenv_t *envp) +{ +  fpu_control_t fpcr; +  int round; + +  _FPU_GETCW (fpcr); + +  /* Check whether rounding modes are different.  */ +  round = (envp->__fpcr ^ fpcr) & _FPU_FPCR_RM_MASK; + +  /* Restore the rounding mode if it was changed.  */ +  if (unlikely (round != 0)) +    _FPU_SETCW (fpcr ^ round); +} + +#define libc_feresetround  libc_feresetround_aarch64 +#define libc_feresetroundf libc_feresetround_aarch64 +#define libc_feresetroundl libc_feresetround_aarch64 + +/* We have support for rounding mode context.  */ +#define HAVE_RM_CTX 1 + +static __always_inline void +libc_feholdsetround_aarch64_ctx (struct rm_ctx *ctx, int r) +{ +  fpu_control_t fpcr; +  int round; + +  _FPU_GETCW (fpcr); +  ctx->env.__fpcr = fpcr; + +  /* Check whether rounding modes are different.  */ +  round = (fpcr ^ r) & _FPU_FPCR_RM_MASK; +  ctx->updated_status = round != 0; + +  /* Set the rounding mode if changed.  */ +  if (unlikely (round != 0)) +    _FPU_SETCW (fpcr ^ round); +} + +#define libc_feholdsetround_ctx		libc_feholdsetround_aarch64_ctx +#define libc_feholdsetroundf_ctx	libc_feholdsetround_aarch64_ctx +#define libc_feholdsetroundl_ctx	libc_feholdsetround_aarch64_ctx + +static __always_inline void +libc_feresetround_aarch64_ctx (struct rm_ctx *ctx) +{ +  /* Restore the rounding mode if updated.  */ +  if (unlikely (ctx->updated_status)) +    _FPU_SETCW (ctx->env.__fpcr); +} + +#define libc_feresetround_ctx		libc_feresetround_aarch64_ctx +#define libc_feresetroundf_ctx		libc_feresetround_aarch64_ctx +#define libc_feresetroundl_ctx		libc_feresetround_aarch64_ctx + +static __always_inline void +libc_feholdsetround_noex_aarch64_ctx (struct rm_ctx *ctx, int r) +{ +  fpu_control_t fpcr; +  fpu_fpsr_t fpsr; +  int round; + +  _FPU_GETCW (fpcr); +  _FPU_GETFPSR (fpsr); +  ctx->env.__fpcr = fpcr; +  ctx->env.__fpsr = fpsr; + +  /* Check whether rounding modes are different.  */ +  round = (fpcr ^ r) & _FPU_FPCR_RM_MASK; +  ctx->updated_status = round != 0; + +  /* Set the rounding mode if changed.  */ +  if (unlikely (round != 0)) +    _FPU_SETCW (fpcr ^ round); +} + +#define libc_feholdsetround_noex_ctx	libc_feholdsetround_noex_aarch64_ctx +#define libc_feholdsetround_noexf_ctx	libc_feholdsetround_noex_aarch64_ctx +#define libc_feholdsetround_noexl_ctx	libc_feholdsetround_noex_aarch64_ctx + +static __always_inline void +libc_feresetround_noex_aarch64_ctx (struct rm_ctx *ctx) +{ +  /* Restore the rounding mode if updated.  */ +  if (unlikely (ctx->updated_status)) +    _FPU_SETCW (ctx->env.__fpcr); + +  /* Write new FPSR to restore exception flags.  */ +  _FPU_SETFPSR (ctx->env.__fpsr); +} + +#define libc_feresetround_noex_ctx	libc_feresetround_noex_aarch64_ctx +#define libc_feresetround_noexf_ctx	libc_feresetround_noex_aarch64_ctx +#define libc_feresetround_noexl_ctx	libc_feresetround_noex_aarch64_ctx + +#endif diff --git a/libm/aarch64/fesetenv.c b/libm/aarch64/fesetenv.c new file mode 100644 index 000000000..eb7a08da0 --- /dev/null +++ b/libm/aarch64/fesetenv.c @@ -0,0 +1,73 @@ +/* Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetenv (const fenv_t *envp) +{ +  fpu_control_t fpcr; +  fpu_control_t fpcr_new; +  fpu_control_t updated_fpcr; +  fpu_fpsr_t fpsr; +  fpu_fpsr_t fpsr_new; + +  _FPU_GETCW (fpcr); + +  if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV)) +    { +      /* The new FPCR/FPSR are valid, so don't merge the reserved flags.  */ +      fpcr_new = envp->__fpcr; + +      if (fpcr != fpcr_new) +	_FPU_SETCW (fpcr_new); + +      _FPU_SETFPSR (envp->__fpsr); +      return 0; +    } + +  _FPU_GETFPSR (fpsr); +  fpcr_new = fpcr & _FPU_RESERVED; +  fpsr_new = fpsr & _FPU_FPSR_RESERVED; + +  if (envp == FE_DFL_ENV) +    { +      fpcr_new |= _FPU_DEFAULT; +      fpsr_new |= _FPU_FPSR_DEFAULT; +    } +  else +    { +      fpcr_new |= _FPU_FPCR_IEEE; +      fpsr_new |= _FPU_FPSR_IEEE; +    } + +  _FPU_SETFPSR (fpsr_new); + +  if (fpcr != fpcr_new) +    { +      _FPU_SETCW (fpcr_new); + +      /* Trapping exceptions are optional in AArch64; the relevant enable +	 bits in FPCR are RES0 hence the absence of support can be detected +	 by reading back the FPCR and comparing with the required value.  */ +      _FPU_GETCW (updated_fpcr); + +      return fpcr_new & ~updated_fpcr; +    } + +  return 0; +} diff --git a/libm/aarch64/fesetexcept.c b/libm/aarch64/fesetexcept.c new file mode 100644 index 000000000..14a0b4232 --- /dev/null +++ b/libm/aarch64/fesetexcept.c @@ -0,0 +1,33 @@ +/* Set given exception flags.  AArch64 version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexcept (int excepts) +{ +  fpu_fpsr_t fpsr; +  fpu_fpsr_t fpsr_new; + +  _FPU_GETFPSR (fpsr); +  fpsr_new = fpsr | (excepts & FE_ALL_EXCEPT); +  if (fpsr != fpsr_new) +    _FPU_SETFPSR (fpsr_new); + +  return 0; +} diff --git a/libm/aarch64/fesetmode.c b/libm/aarch64/fesetmode.c new file mode 100644 index 000000000..34e7c9316 --- /dev/null +++ b/libm/aarch64/fesetmode.c @@ -0,0 +1,33 @@ +/* Install given floating-point control modes.  AArch64 version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetmode (const femode_t *modep) +{ +  fpu_control_t fpcr, fpcr_new; +  _FPU_GETCW (fpcr); +  if (modep == FE_DFL_MODE) +    fpcr_new = (fpcr & _FPU_RESERVED) | _FPU_DEFAULT; +  else +    fpcr_new = *modep; +  if (fpcr != fpcr_new) +    _FPU_SETCW (fpcr_new); +  return 0; +} diff --git a/libm/aarch64/fesetround.c b/libm/aarch64/fesetround.c new file mode 100644 index 000000000..63a558258 --- /dev/null +++ b/libm/aarch64/fesetround.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" +#include <fpu_control.h> + +int +fesetround (int round) +{ +  if (round & ~_FPU_FPCR_RM_MASK) +    return 1; + +  libc_fesetround_aarch64 (round); +  return 0; +} diff --git a/libm/aarch64/feupdateenv.c b/libm/aarch64/feupdateenv.c new file mode 100644 index 000000000..2b4e62ecc --- /dev/null +++ b/libm/aarch64/feupdateenv.c @@ -0,0 +1,84 @@ +/* Copyright (C) 2009-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feupdateenv (const fenv_t *envp) +{ +  fpu_control_t fpcr; +  fpu_control_t fpcr_new; +  fpu_control_t updated_fpcr; +  fpu_fpsr_t fpsr; +  fpu_fpsr_t fpsr_new; +  int excepts; + +  _FPU_GETCW (fpcr); +  _FPU_GETFPSR (fpsr); +  excepts = fpsr & FE_ALL_EXCEPT; + +  if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV)) +    { +      fpcr_new = envp->__fpcr; +      fpsr_new = envp->__fpsr | excepts; + +      if (fpcr != fpcr_new) +        _FPU_SETCW (fpcr_new); + +      if (fpsr != fpsr_new) +        _FPU_SETFPSR (fpsr_new); + +      if (excepts & (fpcr_new >> FE_EXCEPT_SHIFT)) +        return feraiseexcept (excepts); + +      return 0; +    } + +  fpcr_new = fpcr & _FPU_RESERVED; +  fpsr_new = fpsr & (_FPU_FPSR_RESERVED | FE_ALL_EXCEPT); + +  if (envp == FE_DFL_ENV) +    { +      fpcr_new |= _FPU_DEFAULT; +      fpsr_new |= _FPU_FPSR_DEFAULT; +    } +  else +    { +      fpcr_new |= _FPU_FPCR_IEEE; +      fpsr_new |= _FPU_FPSR_IEEE; +    } + +  _FPU_SETFPSR (fpsr_new); + +  if (fpcr != fpcr_new) +    { +      _FPU_SETCW (fpcr_new); + +      /* Trapping exceptions are optional in AArch64; the relevant enable +	 bits in FPCR are RES0 hence the absence of support can be detected +	 by reading back the FPCR and comparing with the required value.  */ +      _FPU_GETCW (updated_fpcr); + +      if (fpcr_new & ~updated_fpcr) +        return 1; +    } + +  if (excepts & (fpcr_new >> FE_EXCEPT_SHIFT)) +    return feraiseexcept (excepts); + +  return 0; +} diff --git a/libm/aarch64/fgetexcptflg.c b/libm/aarch64/fgetexcptflg.c new file mode 100644 index 000000000..2c8920989 --- /dev/null +++ b/libm/aarch64/fgetexcptflg.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2001-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ +  *flagp = libc_fetestexcept_aarch64 (excepts); +  return 0; +} diff --git a/libm/aarch64/fraiseexcpt.c b/libm/aarch64/fraiseexcpt.c new file mode 100644 index 000000000..6a016d046 --- /dev/null +++ b/libm/aarch64/fraiseexcpt.c @@ -0,0 +1,89 @@ +/* Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include <float.h> +#include <stdint.h> + +int +feraiseexcept (int excepts) +{ +  uint64_t fpsr; +  const float fp_zero = 0.0; +  const float fp_one = 1.0; +  const float fp_max = FLT_MAX; +  const float fp_min = FLT_MIN; +  const float fp_1e32 = 1.0e32f; +  const float fp_two = 2.0; +  const float fp_three = 3.0; + +  /* Raise exceptions represented by EXCEPTS.  But we must raise only +     one signal at a time.  It is important that if the OVERFLOW or +     UNDERFLOW exception and the inexact exception are given at the +     same time, the OVERFLOW or UNDERFLOW exception precedes the +     INEXACT exception. + +     After each exception we read from the FPSR, to force the +     exception to be raised immediately.  */ + +  if (FE_INVALID & excepts) +    __asm__ __volatile__ ( +			  "ldr	s0, %1\n\t" +			  "fdiv	s0, s0, s0\n\t" +			  "mrs	%0, fpsr" : "=r" (fpsr) +			  : "m" (fp_zero) +			  : "d0"); + +  if (FE_DIVBYZERO & excepts) +    __asm__ __volatile__ ( +			  "ldr	s0, %1\n\t" +			  "ldr	s1, %2\n\t" +			  "fdiv	s0, s0, s1\n\t" +			  "mrs	%0, fpsr" : "=r" (fpsr) +			  : "m" (fp_one), "m" (fp_zero) +			  : "d0", "d1"); + +  if (FE_OVERFLOW & excepts) +    /* There's no way to raise overflow without also raising inexact.  */ +    __asm__ __volatile__ ( +			  "ldr	s0, %1\n\t" +			  "ldr	s1, %2\n\t" +			  "fadd s0, s0, s1\n\t" +			  "mrs	%0, fpsr" : "=r" (fpsr) +			  : "m" (fp_max), "m" (fp_1e32) +			  : "d0", "d1"); + +  if (FE_UNDERFLOW & excepts) +    __asm__ __volatile__ ( +			  "ldr	s0, %1\n\t" +			  "ldr	s1, %2\n\t" +			  "fdiv s0, s0, s1\n\t" +			  "mrs	%0, fpsr" : "=r" (fpsr) +			  : "m" (fp_min), "m" (fp_three) +			  : "d0", "d1"); + +  if (FE_INEXACT & excepts) +    __asm__ __volatile__ ( +			  "ldr	s0, %1\n\t" +			  "ldr	s1, %2\n\t" +			  "fdiv s0, s0, s1\n\t" +			  "mrs	%0, fpsr" : "=r" (fpsr) +			  : "m" (fp_two), "m" (fp_three) +			  : "d0", "d1"); + +  return 0; +} diff --git a/libm/aarch64/fsetexcptflg.c b/libm/aarch64/fsetexcptflg.c new file mode 100644 index 000000000..a78623d14 --- /dev/null +++ b/libm/aarch64/fsetexcptflg.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ +  fpu_fpsr_t fpsr; +  fpu_fpsr_t fpsr_new; + +  /* Get the current environment.  */ +  _FPU_GETFPSR (fpsr); +  excepts &= FE_ALL_EXCEPT; + +  /* Set the desired exception mask.  */ +  fpsr_new = fpsr & ~excepts; +  fpsr_new |= *flagp & excepts; + +  /* Save state back to the FPU.  */ +  if (fpsr != fpsr_new) +    _FPU_SETFPSR (fpsr_new); + +  return 0; +} diff --git a/libm/aarch64/ftestexcept.c b/libm/aarch64/ftestexcept.c new file mode 100644 index 000000000..eecb93406 --- /dev/null +++ b/libm/aarch64/ftestexcept.c @@ -0,0 +1,24 @@ +/* Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fetestexcept (int excepts) +{ +  return libc_fetestexcept_aarch64 (excepts); +} diff --git a/libm/arc/Makefile.arch b/libm/arc/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/arc/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/arc/fclrexcpt.c b/libm/arc/fclrexcpt.c new file mode 100644 index 000000000..76631657d --- /dev/null +++ b/libm/arc/fclrexcpt.c @@ -0,0 +1,34 @@ +/* Clear given exceptions in current floating-point environment. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ +  unsigned int fpsr; + +  _FPU_GETS (fpsr); + +  /* Clear the relevant bits, FWE is preserved.  */ +  fpsr &= ~excepts; + +  _FPU_SETS (fpsr); + +  return 0; +} diff --git a/libm/arc/fegetenv.c b/libm/arc/fegetenv.c new file mode 100644 index 000000000..ad332c3e5 --- /dev/null +++ b/libm/arc/fegetenv.c @@ -0,0 +1,33 @@ +/* Store current floating-point environment. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetenv (fenv_t *envp) +{ +  unsigned int fpcr; +  unsigned int fpsr; + +  _FPU_GETCW (fpcr); +  _FPU_GETS (fpsr); +  envp->__fpcr = fpcr; +  envp->__fpsr = fpsr; + +  return 0; +} diff --git a/libm/arc/fegetmode.c b/libm/arc/fegetmode.c new file mode 100644 index 000000000..e6aebbc87 --- /dev/null +++ b/libm/arc/fegetmode.c @@ -0,0 +1,30 @@ +/* Store current floating-point control modes. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ +  unsigned int fpcr; + +  _FPU_GETCW (fpcr); +  *modep = fpcr; + +  return 0; +} diff --git a/libm/arc/fegetround.c b/libm/arc/fegetround.c new file mode 100644 index 000000000..4dc476a7c --- /dev/null +++ b/libm/arc/fegetround.c @@ -0,0 +1,28 @@ +/* Return current rounding direction. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetround (void) +{ +  unsigned int fpcr; +  _FPU_GETCW (fpcr); + +  return (fpcr >> __FPU_RND_SHIFT) & __FPU_RND_MASK; +} diff --git a/libm/arc/feholdexcpt.c b/libm/arc/feholdexcpt.c new file mode 100644 index 000000000..8febc7508 --- /dev/null +++ b/libm/arc/feholdexcpt.c @@ -0,0 +1,39 @@ +/* Store current floating-point environment and clear exceptions. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feholdexcept (fenv_t *envp) +{ +  unsigned int fpcr; +  unsigned int fpsr; + +  _FPU_GETCW (fpcr); +  _FPU_GETS (fpsr); + +  envp->__fpcr = fpcr; +  envp->__fpsr = fpsr; + +  fpsr &= ~FE_ALL_EXCEPT; + +  _FPU_SETCW (fpcr); +  _FPU_SETS (fpsr); + +  return 0; +} diff --git a/libm/arc/fenv_private.h b/libm/arc/fenv_private.h new file mode 100644 index 000000000..5f74c5e13 --- /dev/null +++ b/libm/arc/fenv_private.h @@ -0,0 +1,326 @@ +/* Optimized inline fenv.h functions for libm.  Generic version. +   Copyright (C) 2011-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#ifndef _FENV_PRIVATE_H +#define _FENV_PRIVATE_H 1 + +#include <fenv.h> +#include "get-rounding-mode.h" + +/* The standards only specify one variant of the fenv.h interfaces. +   But at least for some architectures we can be more efficient if we +   know what operations are going to be performed.  Therefore we +   define additional interfaces.  By default they refer to the normal +   interfaces.  */ + +static __always_inline void +default_libc_feholdexcept (fenv_t *e) +{ +  (void) feholdexcept (e); +} + +#ifndef libc_feholdexcept +# define libc_feholdexcept  default_libc_feholdexcept +#endif +#ifndef libc_feholdexceptf +# define libc_feholdexceptf default_libc_feholdexcept +#endif +#ifndef libc_feholdexceptl +# define libc_feholdexceptl default_libc_feholdexcept +#endif + +static __always_inline void +default_libc_fesetround (int r) +{ +  (void) fesetround (r); +} + +#ifndef libc_fesetround +# define libc_fesetround  default_libc_fesetround +#endif +#ifndef libc_fesetroundf +# define libc_fesetroundf default_libc_fesetround +#endif +#ifndef libc_fesetroundl +# define libc_fesetroundl default_libc_fesetround +#endif + +static __always_inline void +default_libc_feholdexcept_setround (fenv_t *e, int r) +{ +  feholdexcept (e); +  fesetround (r); +} + +#ifndef libc_feholdexcept_setround +# define libc_feholdexcept_setround  default_libc_feholdexcept_setround +#endif +#ifndef libc_feholdexcept_setroundf +# define libc_feholdexcept_setroundf default_libc_feholdexcept_setround +#endif +#ifndef libc_feholdexcept_setroundl +# define libc_feholdexcept_setroundl default_libc_feholdexcept_setround +#endif + +#ifndef libc_feholdsetround_53bit +# define libc_feholdsetround_53bit libc_feholdsetround +#endif + +#ifndef libc_fetestexcept +# define libc_fetestexcept  fetestexcept +#endif +#ifndef libc_fetestexceptf +# define libc_fetestexceptf fetestexcept +#endif +#ifndef libc_fetestexceptl +# define libc_fetestexceptl fetestexcept +#endif + +static __always_inline void +default_libc_fesetenv (fenv_t *e) +{ +  (void) fesetenv (e); +} + +#ifndef libc_fesetenv +# define libc_fesetenv  default_libc_fesetenv +#endif +#ifndef libc_fesetenvf +# define libc_fesetenvf default_libc_fesetenv +#endif +#ifndef libc_fesetenvl +# define libc_fesetenvl default_libc_fesetenv +#endif + +static __always_inline void +default_libc_feupdateenv (fenv_t *e) +{ +  (void) feupdateenv (e); +} + +#ifndef libc_feupdateenv +# define libc_feupdateenv  default_libc_feupdateenv +#endif +#ifndef libc_feupdateenvf +# define libc_feupdateenvf default_libc_feupdateenv +#endif +#ifndef libc_feupdateenvl +# define libc_feupdateenvl default_libc_feupdateenv +#endif + +#ifndef libc_feresetround_53bit +# define libc_feresetround_53bit libc_feresetround +#endif + +static __always_inline int +default_libc_feupdateenv_test (fenv_t *e, int ex) +{ +  int ret = fetestexcept (ex); +  feupdateenv (e); +  return ret; +} + +#ifndef libc_feupdateenv_test +# define libc_feupdateenv_test  default_libc_feupdateenv_test +#endif +#ifndef libc_feupdateenv_testf +# define libc_feupdateenv_testf default_libc_feupdateenv_test +#endif +#ifndef libc_feupdateenv_testl +# define libc_feupdateenv_testl default_libc_feupdateenv_test +#endif + +/* Save and set the rounding mode.  The use of fenv_t to store the old mode +   allows a target-specific version of this function to avoid converting the +   rounding mode from the fpu format.  By default we have no choice but to +   manipulate the entire env.  */ + +#ifndef libc_feholdsetround +# define libc_feholdsetround  libc_feholdexcept_setround +#endif +#ifndef libc_feholdsetroundf +# define libc_feholdsetroundf libc_feholdexcept_setroundf +#endif +#ifndef libc_feholdsetroundl +# define libc_feholdsetroundl libc_feholdexcept_setroundl +#endif + +/* ... and the reverse.  */ + +#ifndef libc_feresetround +# define libc_feresetround  libc_feupdateenv +#endif +#ifndef libc_feresetroundf +# define libc_feresetroundf libc_feupdateenvf +#endif +#ifndef libc_feresetroundl +# define libc_feresetroundl libc_feupdateenvl +#endif + +/* ... and a version that also discards exceptions.  */ + +#ifndef libc_feresetround_noex +# define libc_feresetround_noex  libc_fesetenv +#endif +#ifndef libc_feresetround_noexf +# define libc_feresetround_noexf libc_fesetenvf +#endif +#ifndef libc_feresetround_noexl +# define libc_feresetround_noexl libc_fesetenvl +#endif + +#ifndef HAVE_RM_CTX +# define HAVE_RM_CTX 0 +#endif + + +/* Default implementation using standard fenv functions. +   Avoid unnecessary rounding mode changes by first checking the +   current rounding mode.  Note the use of unlikely is +   important for performance.  */ + +static __always_inline void +default_libc_feholdsetround_ctx (struct rm_ctx *ctx, int round) +{ +  ctx->updated_status = false; + +  /* Update rounding mode only if different.  */ +  if (unlikely (round != get_rounding_mode ())) +    { +      ctx->updated_status = true; +      fegetenv (&ctx->env); +      fesetround (round); +    } +} + +static __always_inline void +default_libc_feresetround_ctx (struct rm_ctx *ctx) +{ +  /* Restore the rounding mode if updated.  */ +  if (unlikely (ctx->updated_status)) +    feupdateenv (&ctx->env); +} + +static __always_inline void +default_libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round) +{ +  /* Save exception flags and rounding mode, and disable exception +     traps.  */ +  feholdexcept (&ctx->env); + +  /* Update rounding mode only if different.  */ +  if (unlikely (round != get_rounding_mode ())) +    fesetround (round); +} + +static __always_inline void +default_libc_feresetround_noex_ctx (struct rm_ctx *ctx) +{ +  /* Restore exception flags and rounding mode.  */ +  fesetenv (&ctx->env); +} + +#if HAVE_RM_CTX +/* Set/Restore Rounding Modes only when necessary.  If defined, these functions +   set/restore floating point state only if the state needed within the lexical +   block is different from the current state.  This saves a lot of time when +   the floating point unit is much slower than the fixed point units.  */ + +# ifndef libc_feholdsetround_noex_ctx +#   define libc_feholdsetround_noex_ctx  libc_feholdsetround_ctx +# endif +# ifndef libc_feholdsetround_noexf_ctx +#   define libc_feholdsetround_noexf_ctx libc_feholdsetroundf_ctx +# endif +# ifndef libc_feholdsetround_noexl_ctx +#   define libc_feholdsetround_noexl_ctx libc_feholdsetroundl_ctx +# endif + +# ifndef libc_feresetround_noex_ctx +#   define libc_feresetround_noex_ctx  libc_fesetenv_ctx +# endif +# ifndef libc_feresetround_noexf_ctx +#   define libc_feresetround_noexf_ctx libc_fesetenvf_ctx +# endif +# ifndef libc_feresetround_noexl_ctx +#   define libc_feresetround_noexl_ctx libc_fesetenvl_ctx +# endif + +#else + +# define libc_feholdsetround_ctx      default_libc_feholdsetround_ctx +# define libc_feresetround_ctx        default_libc_feresetround_ctx +# define libc_feholdsetround_noex_ctx default_libc_feholdsetround_noex_ctx +# define libc_feresetround_noex_ctx   default_libc_feresetround_noex_ctx + +# define libc_feholdsetroundf_ctx libc_feholdsetround_ctx +# define libc_feholdsetroundl_ctx libc_feholdsetround_ctx +# define libc_feresetroundf_ctx   libc_feresetround_ctx +# define libc_feresetroundl_ctx   libc_feresetround_ctx + +# define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ctx +# define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ctx +# define libc_feresetround_noexf_ctx   libc_feresetround_noex_ctx +# define libc_feresetround_noexl_ctx   libc_feresetround_noex_ctx + +#endif + +#ifndef libc_feholdsetround_53bit_ctx +#  define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx +#endif +#ifndef libc_feresetround_53bit_ctx +#  define libc_feresetround_53bit_ctx libc_feresetround_ctx +#endif + +#define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \ +  struct rm_ctx ctx __attribute__((cleanup (CLEANUPFUNC ## _ctx))); \ +  ROUNDFUNC ## _ctx (&ctx, (RM)) + +/* Set the rounding mode within a lexical block.  Restore the rounding mode to +   the value at the start of the block.  The exception mode must be preserved. +   Exceptions raised within the block must be set in the exception flags. +   Non-stop mode may be enabled inside the block.  */ + +#define SET_RESTORE_ROUND(RM) \ +  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround) +#define SET_RESTORE_ROUNDF(RM) \ +  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetroundf) +#define SET_RESTORE_ROUNDL(RM) \ +  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetroundl) + +/* Set the rounding mode within a lexical block.  Restore the rounding mode to +   the value at the start of the block.  The exception mode must be preserved. +   Exceptions raised within the block must be discarded, and exception flags +   are restored to the value at the start of the block. +   Non-stop mode must be enabled inside the block.  */ + +#define SET_RESTORE_ROUND_NOEX(RM) \ +  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noex, \ +			     libc_feresetround_noex) +#define SET_RESTORE_ROUND_NOEXF(RM) \ +  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexf, \ +			     libc_feresetround_noexf) +#define SET_RESTORE_ROUND_NOEXL(RM) \ +  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexl, \ +			     libc_feresetround_noexl) + +/* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits.  */ +#define SET_RESTORE_ROUND_53BIT(RM) \ +  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_53bit,	      \ +			     libc_feresetround_53bit) + +#endif /* fenv_private.h.  */ diff --git a/libm/arc/fesetenv.c b/libm/arc/fesetenv.c new file mode 100644 index 000000000..59ec3b722 --- /dev/null +++ b/libm/arc/fesetenv.c @@ -0,0 +1,44 @@ +/* Install given floating-point environment (does not raise exceptions). +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fpu_control.h" + +int +fesetenv (const fenv_t *envp) +{ +  unsigned int fpcr; +  unsigned int fpsr; + +  if (envp == FE_DFL_ENV) +    { +      fpcr = _FPU_DEFAULT; +      fpsr = _FPU_FPSR_DEFAULT; +    } +  else +    { +      /* No need to mask out reserved bits as they are IoW.  */ +      fpcr = envp->__fpcr; +      fpsr = envp->__fpsr; +    } + +  _FPU_SETCW (fpcr); +  _FPU_SETS (fpsr); + +  /* Success.  */ +  return 0; +} diff --git a/libm/arc/fesetexcept.c b/libm/arc/fesetexcept.c new file mode 100644 index 000000000..3756a2e09 --- /dev/null +++ b/libm/arc/fesetexcept.c @@ -0,0 +1,31 @@ +/* Set given exception flags. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fpu_control.h" + +int +fesetexcept (int excepts) +{ +  unsigned int fpsr; + +  _FPU_GETS (fpsr); +  fpsr |= excepts; +  _FPU_SETS (fpsr); + +  return 0; +} diff --git a/libm/arc/fesetmode.c b/libm/arc/fesetmode.c new file mode 100644 index 000000000..1fc2bdf12 --- /dev/null +++ b/libm/arc/fesetmode.c @@ -0,0 +1,39 @@ +/* Install given floating-point control modes. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fpu_control.h" + +int +fesetmode (const femode_t *modep) +{ +  unsigned int fpcr; + +  if (modep == FE_DFL_MODE) +    { +      fpcr = _FPU_DEFAULT; +    } +  else +    { +      /* No need to mask out reserved bits as they are IoW.  */ +      fpcr = *modep; +    } + +  _FPU_SETCW (fpcr); + +  return 0; +} diff --git a/libm/arc/fesetround.c b/libm/arc/fesetround.c new file mode 100644 index 000000000..e156e9cf5 --- /dev/null +++ b/libm/arc/fesetround.c @@ -0,0 +1,36 @@ +/* Set current rounding direction. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetround (int round) +{ +  unsigned int fpcr; + +  _FPU_GETCW (fpcr); + +  if (((fpcr >> __FPU_RND_SHIFT) & __FPU_RND_MASK) != round) +    { +      fpcr &= ~(__FPU_RND_MASK << __FPU_RND_SHIFT); +      fpcr |= (round & __FPU_RND_MASK) << __FPU_RND_SHIFT; +      _FPU_SETCW (fpcr); +    } + +  return 0; +} diff --git a/libm/arc/feupdateenv.c b/libm/arc/feupdateenv.c new file mode 100644 index 000000000..6a59b2bfe --- /dev/null +++ b/libm/arc/feupdateenv.c @@ -0,0 +1,47 @@ +/* Install given floating-point environment and raise exceptions, +   without clearing currently raised exceptions. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fpu_control.h" + +int +feupdateenv (const fenv_t *envp) +{ +  unsigned int fpcr; +  unsigned int fpsr; + +  _FPU_GETS (fpsr); + +  if (envp == FE_DFL_ENV) +    { +      fpcr = _FPU_DEFAULT; +    } +  else +    { +      fpcr = envp->__fpcr; + +      /* currently raised exceptions need to be preserved.  */ +      fpsr |= envp->__fpsr; +    } + +  _FPU_SETCW (fpcr); +  _FPU_SETS (fpsr); + +  /* Success.  */ +  return 0; +} diff --git a/libm/arc/fgetexcptflg.c b/libm/arc/fgetexcptflg.c new file mode 100644 index 000000000..03f97f99f --- /dev/null +++ b/libm/arc/fgetexcptflg.c @@ -0,0 +1,30 @@ +/* Store current representation for exceptions, ARC version. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ +  unsigned int fpsr; + +  _FPU_GETS (fpsr); +  *flagp = fpsr & excepts; + +  return 0; +} diff --git a/libm/arc/fraiseexcpt.c b/libm/arc/fraiseexcpt.c new file mode 100644 index 000000000..2ff5e0269 --- /dev/null +++ b/libm/arc/fraiseexcpt.c @@ -0,0 +1,35 @@ +/* Raise given exceptions. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include <float.h> +#include <math.h> + +int +feraiseexcept (int excepts) +{ +  unsigned int fpsr; + +  /* currently raised exceptions are not cleared.  */ +  _FPU_GETS (fpsr); +  fpsr |= excepts; + +  _FPU_SETS (fpsr); + +  return 0; +} diff --git a/libm/arc/fsetexcptflg.c b/libm/arc/fsetexcptflg.c new file mode 100644 index 000000000..97ff20fff --- /dev/null +++ b/libm/arc/fsetexcptflg.c @@ -0,0 +1,37 @@ +/* Set floating-point environment exception handling, ARC version. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ +  unsigned int fpsr; + +  _FPU_GETS (fpsr); + +  /* Clear the bits first.  */ +  fpsr &= ~excepts; + +  /* Now set those bits, copying them over from @flagp.  */ +  fpsr |= *flagp & excepts; + +  _FPU_SETS (fpsr); + +  return 0; +} diff --git a/libm/arc/ftestexcept.c b/libm/arc/ftestexcept.c new file mode 100644 index 000000000..ccc557e5e --- /dev/null +++ b/libm/arc/ftestexcept.c @@ -0,0 +1,31 @@ +/* Test exception in current environment. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "fenv_private.h" +#include <stdio.h> + +int +fetestexcept (int excepts) +{ +  unsigned int fpsr; + +  _FPU_GETS (fpsr); + +  return fpsr & excepts; +} diff --git a/libm/arc/get-rounding-mode.h b/libm/arc/get-rounding-mode.h new file mode 100644 index 000000000..d1bf3475d --- /dev/null +++ b/libm/arc/get-rounding-mode.h @@ -0,0 +1,37 @@ +/* Determine floating-point rounding mode within libc.  ARC version. +   Copyright (C) 2020-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#ifndef _ARC_GET_ROUNDING_MODE_H +#define _ARC_GET_ROUNDING_MODE_H	1 + +#include <fenv.h> +#include <fpu_control.h> + +static inline int +get_rounding_mode (void) +{ +#if defined(__ARC_FPU_SP__) ||  defined(__ARC_FPU_DP__) +  unsigned int fpcr; +  _FPU_GETCW (fpcr); + +  return (fpcr >> __FPU_RND_SHIFT) & __FPU_RND_MASK; +#else +  return FE_TONEAREST; +#endif +} + +#endif /* get-rounding-mode.h */ diff --git a/libm/arm/Makefile.arch b/libm/arm/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/arm/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/arm/arm-features.h b/libm/arm/arm-features.h new file mode 100644 index 000000000..8f9fd7362 --- /dev/null +++ b/libm/arm/arm-features.h @@ -0,0 +1,58 @@ +/* Macros to test for CPU features on ARM.  Generic ARM version. +   Copyright (C) 2012-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#ifndef _ARM_ARM_FEATURES_H +#define _ARM_ARM_FEATURES_H 1 + +/* An OS-specific arm-features.h file should define ARM_HAVE_VFP to +   an appropriate expression for testing at runtime whether the VFP +   hardware is present.  We'll then redefine it to a constant if we +   know at compile time that we can assume VFP.  */ + +#ifndef __SOFTFP__ +/* The compiler is generating VFP instructions, so we're already +   assuming the hardware exists.  */ +# undef ARM_HAVE_VFP +# define ARM_HAVE_VFP	1 +#endif + +/* An OS-specific arm-features.h file may define ARM_ASSUME_NO_IWMMXT +   to indicate at compile time that iWMMXt hardware is never present +   at runtime (or that we never care about its state) and so need not +   be checked for.  */ + +/* A more-specific arm-features.h file may define ARM_ALWAYS_BX to indicate +   that instructions using pc as a destination register must never be used, +   so a "bx" (or "blx") instruction is always required.  */ + +/* The log2 of the minimum alignment required for an address that +   is the target of a computed branch (i.e. a "bx" instruction). +   A more-specific arm-features.h file may define this to set a more +   stringent requirement. + +   Using this only makes sense for code in ARM mode (where instructions +   always have a fixed size of four bytes), or for Thumb-mode code that is +   specifically aligning all the related branch targets to match (since +   Thumb instructions might be either two or four bytes).  */ +#ifndef ARM_BX_ALIGN_LOG2 +# define ARM_BX_ALIGN_LOG2	2 +#endif + +/* An OS-specific arm-features.h file may define ARM_NO_INDEX_REGISTER to +   indicate that the two-register addressing modes must never be used.  */ + +#endif  /* arm-features.h */ diff --git a/libm/arm/fclrexcpt.c b/libm/arm/fclrexcpt.c new file mode 100644 index 000000000..81de94271 --- /dev/null +++ b/libm/arm/fclrexcpt.c @@ -0,0 +1,41 @@ +/* Clear given exceptions in current floating-point environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "arm-features.h" + + +int +feclearexcept (int excepts) +{ +  fpu_control_t fpscr, new_fpscr; + +  /* Fail if a VFP unit isn't present unless nothing needs to be done.  */ +  if (!ARM_HAVE_VFP) +    return (excepts != 0); + +  _FPU_GETCW (fpscr); +  excepts &= FE_ALL_EXCEPT; +  new_fpscr = fpscr & ~excepts; + +  /* Write new exception flags if changed.  */ +  if (new_fpscr != fpscr) +    _FPU_SETCW (new_fpscr); + +  return 0; +} diff --git a/libm/arm/fedisblxcpt.c b/libm/arm/fedisblxcpt.c new file mode 100644 index 000000000..c507e80b4 --- /dev/null +++ b/libm/arm/fedisblxcpt.c @@ -0,0 +1,41 @@ +/* Disable floating-point exceptions. +   Copyright (C) 2001-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "arm-features.h" + + +int +fedisableexcept (int excepts) +{ +  fpu_control_t fpscr, new_fpscr; + +  /* Fail if a VFP unit isn't present.  */ +  if (!ARM_HAVE_VFP) +    return -1; + +  _FPU_GETCW (fpscr); +  excepts &= FE_ALL_EXCEPT; +  new_fpscr = fpscr & ~(excepts << FE_EXCEPT_SHIFT); + +  /* Write new exceptions if changed.  */ +  if (new_fpscr != fpscr) +    _FPU_SETCW (new_fpscr); + +  return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT; +} diff --git a/libm/arm/feenablxcpt.c b/libm/arm/feenablxcpt.c new file mode 100644 index 000000000..41e8eb912 --- /dev/null +++ b/libm/arm/feenablxcpt.c @@ -0,0 +1,49 @@ +/* Enable floating-point exceptions. +   Copyright (C) 2001-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "arm-features.h" + + +int +feenableexcept (int excepts) +{ +  fpu_control_t fpscr, new_fpscr, updated_fpscr; + +  /* Fail if a VFP unit isn't present.  */ +  if (!ARM_HAVE_VFP) +    return -1; + +  _FPU_GETCW (fpscr); +  excepts &= FE_ALL_EXCEPT; +  new_fpscr = fpscr | (excepts << FE_EXCEPT_SHIFT); + +  if (new_fpscr != fpscr) +    { +      _FPU_SETCW (new_fpscr); + +      /* Not all VFP architectures support trapping exceptions, so +	 test whether the relevant bits were set and fail if not.  */ +      _FPU_GETCW (updated_fpscr); + +      if (new_fpscr & ~updated_fpscr) +	return -1; +    } + +  return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT; +} diff --git a/libm/arm/fegetenv.c b/libm/arm/fegetenv.c new file mode 100644 index 000000000..a9f63f5c9 --- /dev/null +++ b/libm/arm/fegetenv.c @@ -0,0 +1,35 @@ +/* Store current floating-point environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "arm-features.h" + + +int +fegetenv (fenv_t *envp) +{ +  fpu_control_t fpscr; + +  /* Fail if a VFP unit isn't present.  */ +  if (!ARM_HAVE_VFP) +    return 1; + +  _FPU_GETCW (fpscr); +  envp->__cw = fpscr; +  return 0; +} diff --git a/libm/arm/fegetexcept.c b/libm/arm/fegetexcept.c new file mode 100644 index 000000000..5dd8e144b --- /dev/null +++ b/libm/arm/fegetexcept.c @@ -0,0 +1,35 @@ +/* Get floating-point exceptions. +   Copyright (C) 2001-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "arm-features.h" + + +int +fegetexcept (void) +{ +  fpu_control_t fpscr; + +  /* Return with all exceptions disabled if a VFP unit isn't present.  */ +  if (!ARM_HAVE_VFP) +    return 0; + +  _FPU_GETCW (fpscr); + +  return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT; +} diff --git a/libm/arm/fegetmode.c b/libm/arm/fegetmode.c new file mode 100644 index 000000000..bf2597353 --- /dev/null +++ b/libm/arm/fegetmode.c @@ -0,0 +1,28 @@ +/* Store current floating-point control modes.  ARM version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "arm-features.h" + +int +fegetmode (femode_t *modep) +{ +  if (ARM_HAVE_VFP) +    _FPU_GETCW (*modep); +  return 0; +} diff --git a/libm/arm/fegetround.c b/libm/arm/fegetround.c new file mode 100644 index 000000000..2f9320491 --- /dev/null +++ b/libm/arm/fegetround.c @@ -0,0 +1,42 @@ +/* Return current rounding direction. +   Copyright (C) 2004-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include "arm-features.h" +#include <fenv.h> +#include <fpu_control.h> + +/* Return the floating-point rounding mode.  */ + +static inline int +get_rounding_mode (void) +{ +  fpu_control_t fpscr; + +  /* FE_TONEAREST is the only supported rounding mode +     if a VFP unit isn't present.  */ +  if (!ARM_HAVE_VFP) +    return FE_TONEAREST; + +  _FPU_GETCW (fpscr); +  return fpscr & _FPU_MASK_RM; +} + +int +fegetround (void) +{ +  return get_rounding_mode (); +} diff --git a/libm/arm/feholdexcpt.c b/libm/arm/feholdexcpt.c new file mode 100644 index 000000000..3608931db --- /dev/null +++ b/libm/arm/feholdexcpt.c @@ -0,0 +1,31 @@ +/* Store current floating-point environment and clear exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include "fenv_private.h" +#include "arm-features.h" + + +int +feholdexcept (fenv_t *envp) +{ +  /* Fail if a VFP unit isn't present.  */ +  if (!ARM_HAVE_VFP) +    return 1; + +  libc_feholdexcept_vfp (envp); +  return 0; +} diff --git a/libm/arm/fenv_private.h b/libm/arm/fenv_private.h new file mode 100644 index 000000000..566bf443c --- /dev/null +++ b/libm/arm/fenv_private.h @@ -0,0 +1,248 @@ +/* Private floating point rounding and exceptions handling.  ARM VFP version. +   Copyright (C) 2014-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#ifndef ARM_FENV_PRIVATE_H +#define ARM_FENV_PRIVATE_H 1 + +#include <fenv.h> +#include <fpu_control.h> + +static __always_inline void +libc_feholdexcept_vfp (fenv_t *envp) +{ +  fpu_control_t fpscr; + +  _FPU_GETCW (fpscr); +  envp->__cw = fpscr; + +  /* Clear exception flags and set all exceptions to non-stop.  */ +  fpscr &= ~_FPU_MASK_EXCEPT; +  _FPU_SETCW (fpscr); +} + +static __always_inline void +libc_fesetround_vfp (int round) +{ +  fpu_control_t fpscr; + +  _FPU_GETCW (fpscr); + +  /* Set new rounding mode if different.  */ +  if (unlikely ((fpscr & _FPU_MASK_RM) != round)) +    _FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round); +} + +static __always_inline void +libc_feholdexcept_setround_vfp (fenv_t *envp, int round) +{ +  fpu_control_t fpscr; + +  _FPU_GETCW (fpscr); +  envp->__cw = fpscr; + +  /* Clear exception flags, set all exceptions to non-stop, +     and set new rounding mode.  */ +  fpscr &= ~(_FPU_MASK_EXCEPT | _FPU_MASK_RM); +  _FPU_SETCW (fpscr | round); +} + +static __always_inline void +libc_feholdsetround_vfp (fenv_t *envp, int round) +{ +  fpu_control_t fpscr; + +  _FPU_GETCW (fpscr); +  envp->__cw = fpscr; + +  /* Set new rounding mode if different.  */ +  if (unlikely ((fpscr & _FPU_MASK_RM) != round)) +    _FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round); +} + +static __always_inline void +libc_feresetround_vfp (fenv_t *envp) +{ +  fpu_control_t fpscr, round; + +  _FPU_GETCW (fpscr); + +  /* Check whether rounding modes are different.  */ +  round = (envp->__cw ^ fpscr) & _FPU_MASK_RM; + +  /* Restore the rounding mode if it was changed.  */ +  if (unlikely (round != 0)) +    _FPU_SETCW (fpscr ^ round); +} + +static __always_inline int +libc_fetestexcept_vfp (int ex) +{ +  fpu_control_t fpscr; + +  _FPU_GETCW (fpscr); +  return fpscr & ex & FE_ALL_EXCEPT; +} + +static __always_inline void +libc_fesetenv_vfp (const fenv_t *envp) +{ +  fpu_control_t fpscr, new_fpscr; + +  _FPU_GETCW (fpscr); +  new_fpscr = envp->__cw; + +  /* Write new FPSCR if different (ignoring NZCV flags).  */ +  if (unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0)) +    _FPU_SETCW (new_fpscr); +} + +static __always_inline int +libc_feupdateenv_test_vfp (const fenv_t *envp, int ex) +{ +  fpu_control_t fpscr, new_fpscr; +  int excepts; + +  _FPU_GETCW (fpscr); + +  /* Merge current exception flags with the saved fenv.  */ +  excepts = fpscr & FE_ALL_EXCEPT; +  new_fpscr = envp->__cw | excepts; + +  /* Write new FPSCR if different (ignoring NZCV flags).  */ +  if (unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0)) +    _FPU_SETCW (new_fpscr); + +  /* Raise the exceptions if enabled in the new FP state.  */ +  if (unlikely (excepts & (new_fpscr >> FE_EXCEPT_SHIFT))) +    feraiseexcept (excepts); + +  return excepts & ex; +} + +static __always_inline void +libc_feupdateenv_vfp (const fenv_t *envp) +{ +  libc_feupdateenv_test_vfp (envp, 0); +} + +static __always_inline void +libc_feholdsetround_vfp_ctx (struct rm_ctx *ctx, int r) +{ +  fpu_control_t fpscr, round; + +  _FPU_GETCW (fpscr); +  ctx->updated_status = false; +  ctx->env.__cw = fpscr; + +  /* Check whether rounding modes are different.  */ +  round = (fpscr ^ r) & _FPU_MASK_RM; + +  /* Set the rounding mode if changed.  */ +  if (unlikely (round != 0)) +    { +      ctx->updated_status = true; +      _FPU_SETCW (fpscr ^ round); +    } +} + +static __always_inline void +libc_feresetround_vfp_ctx (struct rm_ctx *ctx) +{ +  /* Restore the rounding mode if updated.  */ +  if (unlikely (ctx->updated_status)) +    { +      fpu_control_t fpscr; + +      _FPU_GETCW (fpscr); +      fpscr = (fpscr & ~_FPU_MASK_RM) | (ctx->env.__cw & _FPU_MASK_RM); +      _FPU_SETCW (fpscr); +    } +} + +static __always_inline void +libc_fesetenv_vfp_ctx (struct rm_ctx *ctx) +{ +  fpu_control_t fpscr, new_fpscr; + +  _FPU_GETCW (fpscr); +  new_fpscr = ctx->env.__cw; + +  /* Write new FPSCR if different (ignoring NZCV flags).  */ +  if (unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0)) +    _FPU_SETCW (new_fpscr); +} + +#ifndef __SOFTFP__ + +# define libc_feholdexcept  libc_feholdexcept_vfp +# define libc_feholdexceptf libc_feholdexcept_vfp +# define libc_feholdexceptl libc_feholdexcept_vfp + +# define libc_fesetround  libc_fesetround_vfp +# define libc_fesetroundf libc_fesetround_vfp +# define libc_fesetroundl libc_fesetround_vfp + +# define libc_feresetround  libc_feresetround_vfp +# define libc_feresetroundf libc_feresetround_vfp +# define libc_feresetroundl libc_feresetround_vfp + +# define libc_feresetround_noex  libc_fesetenv_vfp +# define libc_feresetround_noexf libc_fesetenv_vfp +# define libc_feresetround_noexl libc_fesetenv_vfp + +# define libc_feholdexcept_setround  libc_feholdexcept_setround_vfp +# define libc_feholdexcept_setroundf libc_feholdexcept_setround_vfp +# define libc_feholdexcept_setroundl libc_feholdexcept_setround_vfp + +# define libc_feholdsetround  libc_feholdsetround_vfp +# define libc_feholdsetroundf libc_feholdsetround_vfp +# define libc_feholdsetroundl libc_feholdsetround_vfp + +# define libc_fetestexcept  libc_fetestexcept_vfp +# define libc_fetestexceptf libc_fetestexcept_vfp +# define libc_fetestexceptl libc_fetestexcept_vfp + +# define libc_fesetenv  libc_fesetenv_vfp +# define libc_fesetenvf libc_fesetenv_vfp +# define libc_fesetenvl libc_fesetenv_vfp + +# define libc_feupdateenv  libc_feupdateenv_vfp +# define libc_feupdateenvf libc_feupdateenv_vfp +# define libc_feupdateenvl libc_feupdateenv_vfp + +# define libc_feupdateenv_test  libc_feupdateenv_test_vfp +# define libc_feupdateenv_testf libc_feupdateenv_test_vfp +# define libc_feupdateenv_testl libc_feupdateenv_test_vfp + +/* We have support for rounding mode context.  */ +#define HAVE_RM_CTX 1 + +# define libc_feholdsetround_ctx	libc_feholdsetround_vfp_ctx +# define libc_feresetround_ctx		libc_feresetround_vfp_ctx +# define libc_feresetround_noex_ctx	libc_fesetenv_vfp_ctx + +# define libc_feholdsetroundf_ctx	libc_feholdsetround_vfp_ctx +# define libc_feresetroundf_ctx		libc_feresetround_vfp_ctx +# define libc_feresetround_noexf_ctx	libc_fesetenv_vfp_ctx + +# define libc_feholdsetroundl_ctx	libc_feholdsetround_vfp_ctx +# define libc_feresetroundl_ctx		libc_feresetround_vfp_ctx +# define libc_feresetround_noexl_ctx	libc_fesetenv_vfp_ctx + +#endif + +#endif /* ARM_FENV_PRIVATE_H */ diff --git a/libm/arm/fesetenv.c b/libm/arm/fesetenv.c new file mode 100644 index 000000000..4675dbe88 --- /dev/null +++ b/libm/arm/fesetenv.c @@ -0,0 +1,62 @@ +/* Install given floating-point environment. +   Copyright (C) 2004-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "arm-features.h" + + +int +fesetenv (const fenv_t *envp) +{ +  fpu_control_t fpscr, new_fpscr, updated_fpscr; + +  /* Fail if a VFP unit isn't present.  */ +  if (!ARM_HAVE_VFP) +    return 1; + +  _FPU_GETCW (fpscr); + +  if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV)) +    { +      /* The new FPSCR is valid, so don't merge the reserved flags.  */ +      new_fpscr = envp->__cw; + +      /* Write new FPSCR if different (ignoring NZCV flags).  */ +      if (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0) +	_FPU_SETCW (new_fpscr); + +      return 0; +    } + +  /* Preserve the reserved FPSCR flags.  */ +  new_fpscr = fpscr & _FPU_RESERVED; +  new_fpscr |= (envp == FE_DFL_ENV) ? _FPU_DEFAULT : _FPU_IEEE; + +  if (((new_fpscr ^ fpscr) & ~_FPU_MASK_NZCV) != 0) +    { +      _FPU_SETCW (new_fpscr); + +      /* Not all VFP architectures support trapping exceptions, so +	 test whether the relevant bits were set and fail if not.  */ +      _FPU_GETCW (updated_fpscr); + +      return new_fpscr & ~updated_fpscr; +    } + +  return 0; +} diff --git a/libm/arm/fesetexcept.c b/libm/arm/fesetexcept.c new file mode 100644 index 000000000..03338c783 --- /dev/null +++ b/libm/arm/fesetexcept.c @@ -0,0 +1,37 @@ +/* Set given exception flags.  ARM version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "arm-features.h" + +int +fesetexcept (int excepts) +{ +  fpu_control_t fpscr, new_fpscr; + +  /* Fail if a VFP unit isn't present unless nothing needs to be done.  */ +  if (!ARM_HAVE_VFP) +    return (excepts != 0); + +  _FPU_GETCW (fpscr); +  new_fpscr = fpscr | (excepts & FE_ALL_EXCEPT); +  if (new_fpscr != fpscr) +    _FPU_SETCW (new_fpscr); + +  return 0; +} diff --git a/libm/arm/fesetmode.c b/libm/arm/fesetmode.c new file mode 100644 index 000000000..7919022b0 --- /dev/null +++ b/libm/arm/fesetmode.c @@ -0,0 +1,44 @@ +/* Install given floating-point control modes.  ARM version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "arm-features.h" + +/* NZCV flags, QC bit, IDC bit and bits for IEEE exception status.  */ +#define FPU_STATUS_BITS 0xf800009f + +int +fesetmode (const femode_t *modep) +{ +  fpu_control_t fpscr, new_fpscr; + +  if (!ARM_HAVE_VFP) +    /* Nothing to do.  */ +    return 0; + +  _FPU_GETCW (fpscr); +  if (modep == FE_DFL_MODE) +    new_fpscr = (fpscr & (_FPU_RESERVED | FPU_STATUS_BITS)) | _FPU_DEFAULT; +  else +    new_fpscr = (fpscr & FPU_STATUS_BITS) | (*modep & ~FPU_STATUS_BITS); + +  if (((new_fpscr ^ fpscr) & ~_FPU_MASK_NZCV) != 0) +    _FPU_SETCW (new_fpscr); + +  return 0; +} diff --git a/libm/arm/fesetround.c b/libm/arm/fesetround.c new file mode 100644 index 000000000..1cb6b366c --- /dev/null +++ b/libm/arm/fesetround.c @@ -0,0 +1,35 @@ +/* Set current rounding direction. +   Copyright (C) 2004-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include "fenv_private.h" +#include "arm-features.h" + + +int +fesetround (int round) +{ +  /* FE_TONEAREST is the only supported rounding mode +     if a VFP unit isn't present.  */ +  if (!ARM_HAVE_VFP) +    return (round == FE_TONEAREST) ? 0 : 1; + +  if (round & ~_FPU_MASK_RM) +    return 1; + +  libc_fesetround_vfp (round); +  return 0; +} diff --git a/libm/arm/feupdateenv.c b/libm/arm/feupdateenv.c new file mode 100644 index 000000000..a246b865b --- /dev/null +++ b/libm/arm/feupdateenv.c @@ -0,0 +1,73 @@ +/* Install given floating-point environment and raise exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "arm-features.h" + + +int +feupdateenv (const fenv_t *envp) +{ +  fpu_control_t fpscr, new_fpscr, updated_fpscr; +  int excepts; + +  /* Fail if a VFP unit isn't present.  */ +  if (!ARM_HAVE_VFP) +    return 1; + +  _FPU_GETCW (fpscr); +  excepts = fpscr & FE_ALL_EXCEPT; + +  if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV)) +    { +      /* Merge current exception flags with the saved fenv.  */ +      new_fpscr = envp->__cw | excepts; + +      /* Write new FPSCR if different (ignoring NZCV flags).  */ +      if (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0) +	_FPU_SETCW (new_fpscr); + +      /* Raise the exceptions if enabled in the new FP state.  */ +      if (excepts & (new_fpscr >> FE_EXCEPT_SHIFT)) +	return feraiseexcept (excepts); + +      return 0; +    } + +  /* Preserve the reserved FPSCR flags.  */ +  new_fpscr = fpscr & (_FPU_RESERVED | FE_ALL_EXCEPT); +  new_fpscr |= (envp == FE_DFL_ENV) ? _FPU_DEFAULT : _FPU_IEEE; + +  if (((new_fpscr ^ fpscr) & ~_FPU_MASK_NZCV) != 0) +    { +      _FPU_SETCW (new_fpscr); + +      /* Not all VFP architectures support trapping exceptions, so +	 test whether the relevant bits were set and fail if not.  */ +      _FPU_GETCW (updated_fpscr); + +      if (new_fpscr & ~updated_fpscr) +	return 1; +    } + +  /* Raise the exceptions if enabled in the new FP state.  */ +  if (excepts & (new_fpscr >> FE_EXCEPT_SHIFT)) +    return feraiseexcept (excepts); + +  return 0; +} diff --git a/libm/arm/fgetexcptflg.c b/libm/arm/fgetexcptflg.c new file mode 100644 index 000000000..2ef835fd4 --- /dev/null +++ b/libm/arm/fgetexcptflg.c @@ -0,0 +1,31 @@ +/* Store current representation for exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include "fenv_private.h" +#include "arm-features.h" + + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ +  /* Fail if a VFP unit isn't present.  */ +  if (!ARM_HAVE_VFP) +    return 1; + +  *flagp = libc_fetestexcept_vfp (excepts); +  return 0; +} diff --git a/libm/arm/fraiseexcpt.c b/libm/arm/fraiseexcpt.c new file mode 100644 index 000000000..91a5d6308 --- /dev/null +++ b/libm/arm/fraiseexcpt.c @@ -0,0 +1,103 @@ +/* Raise given exceptions. +   Copyright (C) 2004-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fpu_control.h> +#include <fenv.h> +#include <float.h> +#include "arm-features.h" + + +int +feraiseexcept (int excepts) +{ +  /* Fail if a VFP unit isn't present unless nothing needs to be done.  */ +  if (!ARM_HAVE_VFP) +    return (excepts != 0); +  else +    { +      fpu_control_t fpscr; +      const float fp_zero = 0.0, fp_one = 1.0, fp_max = FLT_MAX, +                  fp_min = FLT_MIN, fp_1e32 = 1.0e32f, fp_two = 2.0, +		  fp_three = 3.0; + +      /* Raise exceptions represented by EXPECTS.  But we must raise only +	 one signal at a time.  It is important that if the overflow/underflow +	 exception and the inexact exception are given at the same time, +	 the overflow/underflow exception follows the inexact exception.  After +	 each exception we read from the fpscr, to force the exception to be +	 raised immediately.  */ + +      /* There are additional complications because this file may be compiled +         without VFP support enabled, and we also can't assume that the +	 assembler has VFP instructions enabled. To get around this we use the +	 generic coprocessor mnemonics and avoid asking GCC to put float values +	 in VFP registers.  */ + +      /* First: invalid exception.  */ +      if (FE_INVALID & excepts) +	__asm__ __volatile__ ( +	  "ldc p10, cr0, %1\n\t"                        /* flds s0, %1  */ +	  "cdp p10, 8, cr0, cr0, cr0, 0\n\t"            /* fdivs s0, s0, s0  */ +	  "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr)  /* fmrx %0, fpscr  */ +			                : "m" (fp_zero) +					: "s0"); + +      /* Next: division by zero.  */ +      if (FE_DIVBYZERO & excepts) +	__asm__ __volatile__ ( +	  "ldc p10, cr0, %1\n\t"                        /* flds s0, %1  */ +	  "ldcl p10, cr0, %2\n\t"                       /* flds s1, %2  */ +	  "cdp p10, 8, cr0, cr0, cr0, 1\n\t"            /* fdivs s0, s0, s1  */ +	  "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr)  /* fmrx %0, fpscr  */ +			                : "m" (fp_one), "m" (fp_zero) +					: "s0", "s1"); + +      /* Next: overflow.  */ +      if (FE_OVERFLOW & excepts) +	/* There's no way to raise overflow without also raising inexact.  */ +	__asm__ __volatile__ ( +	  "ldc p10, cr0, %1\n\t"                        /* flds s0, %1  */ +	  "ldcl p10, cr0, %2\n\t"                       /* flds s1, %2  */ +	  "cdp p10, 3, cr0, cr0, cr0, 1\n\t"            /* fadds s0, s0, s1  */ +	  "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr)  /* fmrx %0, fpscr  */ +			                : "m" (fp_max), "m" (fp_1e32) +					: "s0", "s1"); + +      /* Next: underflow.  */ +      if (FE_UNDERFLOW & excepts) +	__asm__ __volatile__ ( +	  "ldc p10, cr0, %1\n\t"                        /* flds s0, %1  */ +	  "ldcl p10, cr0, %2\n\t"                       /* flds s1, %2  */ +	  "cdp p10, 8, cr0, cr0, cr0, 1\n\t"            /* fdivs s0, s0, s1  */ +	  "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr)  /* fmrx %0, fpscr  */ +			                : "m" (fp_min), "m" (fp_three) +					: "s0", "s1"); + +      /* Last: inexact.  */ +      if (FE_INEXACT & excepts) +	__asm__ __volatile__ ( +	  "ldc p10, cr0, %1\n\t"                        /* flds s0, %1  */ +	  "ldcl p10, cr0, %2\n\t"                       /* flds s1, %2  */ +	  "cdp p10, 8, cr0, cr0, cr0, 1\n\t"            /* fdivs s0, s0, s1  */ +	  "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr)  /* fmrx %0, fpscr  */ +			                : "m" (fp_two), "m" (fp_three) +					: "s0", "s1"); + +      /* Success.  */ +      return 0; +    } +} diff --git a/libm/arm/fsetexcptflg.c b/libm/arm/fsetexcptflg.c new file mode 100644 index 000000000..343b33af9 --- /dev/null +++ b/libm/arm/fsetexcptflg.c @@ -0,0 +1,44 @@ +/* Set floating-point environment exception handling. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> +#include "arm-features.h" + + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ +  fpu_control_t fpscr, new_fpscr; + +  /* Fail if a VFP unit isn't present unless nothing needs to be done.  */ +  if (!ARM_HAVE_VFP) +    return (excepts != 0); + +  _FPU_GETCW (fpscr); +  excepts &= FE_ALL_EXCEPT; + +  /* Set the desired exception mask.  */ +  new_fpscr = fpscr & ~excepts; +  new_fpscr |= *flagp & excepts; + +  /* Write new exception flags if changed.  */ +  if (new_fpscr != fpscr) +    _FPU_SETCW (new_fpscr); + +  return 0; +} diff --git a/libm/arm/ftestexcept.c b/libm/arm/ftestexcept.c new file mode 100644 index 000000000..8b836d97d --- /dev/null +++ b/libm/arm/ftestexcept.c @@ -0,0 +1,30 @@ +/* Test exception in current environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include "fenv_private.h" +#include "arm-features.h" + + +int +fetestexcept (int excepts) +{ +  /* Return no exception flags if a VFP unit isn't present.  */ +  if (!ARM_HAVE_VFP) +    return 0; + +  return libc_fetestexcept_vfp (excepts); +} diff --git a/libm/cexp.c b/libm/cexp.c index 87512b7c5..a08d12d4e 100644 --- a/libm/cexp.c +++ b/libm/cexp.c @@ -38,10 +38,10 @@ libm_hidden_proto(cexpf)  __complex__ float cexpf(__complex__ float z)  {  	__complex__ float ret; -	double r_exponent = exp(__real__ z); +	double r_exponent = exp((double)__real__ z); -	__real__ ret = r_exponent * cosf(__imag__ z); -	__imag__ ret = r_exponent * sinf(__imag__ z); +	__real__ ret = r_exponent * (double) cosf(__imag__ z); +	__imag__ ret = r_exponent * (double) sinf(__imag__ z);  	return ret;  } 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/e_exp.c b/libm/e_exp.c index ffa556120..f694f67d1 100644 --- a/libm/e_exp.c +++ b/libm/e_exp.c @@ -126,7 +126,7 @@ double __ieee754_exp(double x)	/* default IEEE double exp */  	    if(hx < 0x3FF0A2B2) {	/* and |x| < 1.5 ln2 */  		hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;  	    } else { -		k  = invln2*x+halF[xsb]; +		k  = (int32_t)(invln2*x+halF[xsb]);  		t  = k;  		hi = x - t*ln2HI[0];	/* t*ln2HI is exact here */  		lo = t*ln2LO[0]; diff --git a/libm/float_wrappers.c b/libm/float_wrappers.c index 948f6bc14..35887dde2 100644 --- a/libm/float_wrappers.c +++ b/libm/float_wrappers.c @@ -230,7 +230,7 @@ long_WRAPPER1(lround)  float modff (float x, float *iptr)  {  	double y, result; -	result = modf( x, &y ); +	result = modf( (double)x, &y );  	*iptr = (float)y;  	return (float) result;  } diff --git a/libm/m68k/Makefile.arch b/libm/m68k/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/m68k/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/m68k/fclrexcpt.c b/libm/m68k/fclrexcpt.c new file mode 100644 index 000000000..904ba5a19 --- /dev/null +++ b/libm/m68k/fclrexcpt.c @@ -0,0 +1,39 @@ +/* Clear given exceptions in current floating-point environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +feclearexcept (int excepts) +{ +  fexcept_t fpsr; + +  /* Mask out unsupported bits/exceptions.  */ +  excepts &= FE_ALL_EXCEPT; + +  /* Fetch the fpu status register.  */ +  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); + +  /* Clear the relevant bits.  */ +  fpsr &= ~excepts; + +  /* Put the new data in effect.  */ +  __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr)); + +  /* Success.  */ +  return 0; +} diff --git a/libm/m68k/fedisblxcpt.c b/libm/m68k/fedisblxcpt.c new file mode 100644 index 000000000..c2c593e38 --- /dev/null +++ b/libm/m68k/fedisblxcpt.c @@ -0,0 +1,36 @@ +/* Disable floating-point exceptions. +   Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +fedisableexcept (int excepts) +{ +  unsigned int old_exc, new_exc; + +  /* Get the current control register contents.  */ +  __asm__ ("fmove%.l %!,%0" : "=dm" (new_exc)); + +  old_exc = (new_exc >> 6) & FE_ALL_EXCEPT; + +  excepts &= FE_ALL_EXCEPT; + +  new_exc &= ~(excepts << 6); +  __asm__ ("fmove%.l %0,%!" : : "dm" (new_exc)); + +  return old_exc; +} diff --git a/libm/m68k/feenablxcpt.c b/libm/m68k/feenablxcpt.c new file mode 100644 index 000000000..9c01dc28b --- /dev/null +++ b/libm/m68k/feenablxcpt.c @@ -0,0 +1,36 @@ +/* Enable floating-point exceptions. +   Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +feenableexcept (int excepts) +{ +  unsigned int new_exc, old_exc; + +  /* Get the current control register contents.  */ +  __asm__ ("fmove%.l %!,%0" : "=dm" (new_exc)); + +  old_exc = (new_exc >> 6) & FE_ALL_EXCEPT; + +  excepts &= FE_ALL_EXCEPT; + +  new_exc |= excepts << 6; +  __asm__ ("fmove%.l %0,%!" : : "dm" (new_exc)); + +  return old_exc; +} diff --git a/libm/m68k/fegetenv.c b/libm/m68k/fegetenv.c new file mode 100644 index 000000000..2cd0a7c88 --- /dev/null +++ b/libm/m68k/fegetenv.c @@ -0,0 +1,33 @@ +/* Store current floating-point environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +fegetenv (fenv_t *envp) +{ +#ifdef __mcoldfire__ +  __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (envp->__control_register)); +  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (envp->__status_register)); +  __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (envp->__instruction_address)); +#else +  __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*envp)); +#endif + +  /* Success.  */ +  return 0; +} diff --git a/libm/m68k/fegetexcept.c b/libm/m68k/fegetexcept.c new file mode 100644 index 000000000..1be3f8bf5 --- /dev/null +++ b/libm/m68k/fegetexcept.c @@ -0,0 +1,29 @@ +/* Get enabled floating-point exceptions. +   Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +fegetexcept (void) +{ +  unsigned int exc; + +  /* Get the current control register contents.  */ +  __asm__ ("fmove%.l %!,%0" : "=dm" (exc)); + +  return (exc >> 6) & FE_ALL_EXCEPT; +} diff --git a/libm/m68k/fegetmode.c b/libm/m68k/fegetmode.c new file mode 100644 index 000000000..19f49922a --- /dev/null +++ b/libm/m68k/fegetmode.c @@ -0,0 +1,26 @@ +/* Store current floating-point control modes.  M68K version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ +  _FPU_GETCW (*modep); +  return 0; +} diff --git a/libm/m68k/fegetround.c b/libm/m68k/fegetround.c new file mode 100644 index 000000000..02f6c4c41 --- /dev/null +++ b/libm/m68k/fegetround.c @@ -0,0 +1,28 @@ +/* Return current rounding direction. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +fegetround (void) +{ +  int fpcr; + +  __asm__ ("fmove%.l %!,%0" : "=dm" (fpcr)); + +  return fpcr & FE_UPWARD; +} diff --git a/libm/m68k/feholdexcpt.c b/libm/m68k/feholdexcpt.c new file mode 100644 index 000000000..c0891969a --- /dev/null +++ b/libm/m68k/feholdexcpt.c @@ -0,0 +1,42 @@ +/* Store current floating-point environment and clear exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +feholdexcept (fenv_t *envp) +{ +  fexcept_t fpcr, fpsr; + +  /* Store the environment.  */ +#ifdef __mcoldfire__ +  __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (envp->__control_register)); +  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (envp->__status_register)); +  __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (envp->__instruction_address)); +#else +  __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*envp)); +#endif + +  /* Now clear all exceptions.  */ +  fpsr = envp->__status_register & ~FE_ALL_EXCEPT; +  __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr)); +  /* And set all exceptions to non-stop.  */ +  fpcr = envp->__control_register & ~(FE_ALL_EXCEPT << 6); +  __asm__ __volatile__ ("fmove%.l %0,%!" : : "dm" (fpcr)); + +  return 0; +} diff --git a/libm/m68k/fesetenv.c b/libm/m68k/fesetenv.c new file mode 100644 index 000000000..873eb9abe --- /dev/null +++ b/libm/m68k/fesetenv.c @@ -0,0 +1,63 @@ +/* Install given floating-point environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +fesetenv (const fenv_t *envp) +{ +  fenv_t temp; + +  /* Install the environment specified by ENVP.  But there are a few +     values which we do not want to come from the saved environment. +     Therefore, we get the current environment and replace the values +     we want to use from the environment specified by the parameter.  */ +#ifdef __mcoldfire__ +  __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (temp.__control_register)); +  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (temp.__status_register)); +  __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (temp.__instruction_address)); +#else +  __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*&temp)); +#endif + +  temp.__status_register &= ~FE_ALL_EXCEPT; +  temp.__control_register &= ~((FE_ALL_EXCEPT << 6) | FE_UPWARD); +  if (envp == FE_DFL_ENV) +    ; +  else if (envp == FE_NOMASK_ENV) +    temp.__control_register |= FE_ALL_EXCEPT << 6; +  else +    { +      temp.__control_register |= (envp->__control_register +				  & ((FE_ALL_EXCEPT << 6) | FE_UPWARD)); +      temp.__status_register |= envp->__status_register & FE_ALL_EXCEPT; +    } + +#ifdef __mcoldfire__ +  __asm__ __volatile__ ("fmove%.l %0,%/fpiar" +			:: "dm" (temp.__instruction_address)); +  __asm__ __volatile__ ("fmove%.l %0,%/fpcr" +			:: "dm" (temp.__control_register)); +  __asm__ __volatile__ ("fmove%.l %0,%/fpsr" +			:: "dm" (temp.__status_register)); +#else +  __asm__ __volatile__ ("fmovem%.l %0,%/fpcr/%/fpsr/%/fpiar" : : "m" (*&temp)); +#endif + +  /* Success.  */ +  return 0; +} diff --git a/libm/m68k/fesetexcept.c b/libm/m68k/fesetexcept.c new file mode 100644 index 000000000..6ae4a55ea --- /dev/null +++ b/libm/m68k/fesetexcept.c @@ -0,0 +1,30 @@ +/* Set given exception flags.  M68K version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +fesetexcept (int excepts) +{ +  fexcept_t fpsr; + +  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); +  fpsr |= excepts & FE_ALL_EXCEPT; +  __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr)); + +  return 0; +} diff --git a/libm/m68k/fesetmode.c b/libm/m68k/fesetmode.c new file mode 100644 index 000000000..a7e93d616 --- /dev/null +++ b/libm/m68k/fesetmode.c @@ -0,0 +1,31 @@ +/* Install given floating-point control modes.  M68K version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetmode (const femode_t *modep) +{ +  femode_t mode; +  if (modep == FE_DFL_MODE) +    mode = _FPU_DEFAULT; +  else +    mode = *modep; +  _FPU_SETCW (mode); +  return 0; +} diff --git a/libm/m68k/fesetround.c b/libm/m68k/fesetround.c new file mode 100644 index 000000000..a8abc4e6e --- /dev/null +++ b/libm/m68k/fesetround.c @@ -0,0 +1,35 @@ +/* Set current rounding direction. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +fesetround (int round) +{ +  fexcept_t fpcr; + +  if (round & ~FE_UPWARD) +    /* ROUND is no valid rounding mode.  */ +    return 1; + +  __asm__ ("fmove%.l %!,%0" : "=dm" (fpcr)); +  fpcr &= ~FE_UPWARD; +  fpcr |= round; +  __asm__ __volatile__ ("fmove%.l %0,%!" : : "dm" (fpcr)); + +  return 0; +} diff --git a/libm/m68k/feupdateenv.c b/libm/m68k/feupdateenv.c new file mode 100644 index 000000000..29dcc712e --- /dev/null +++ b/libm/m68k/feupdateenv.c @@ -0,0 +1,39 @@ +/* Install given floating-point environment and raise exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +feupdateenv (const fenv_t *envp) +{ +  fexcept_t fpsr; + +  /* Save current exceptions.  */ +  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); +  fpsr &= FE_ALL_EXCEPT; + +  /* Install new environment.  */ +  fesetenv (envp); + +  /* Raise the saved exception.  Incidentally for us the implementation +     defined format of the values in objects of type fexcept_t is the +     same as the ones specified using the FE_* constants.  */ +  feraiseexcept ((int) fpsr); + +  /* Success.  */ +  return 0; +} diff --git a/libm/m68k/fgetexcptflg.c b/libm/m68k/fgetexcptflg.c new file mode 100644 index 000000000..7a564555b --- /dev/null +++ b/libm/m68k/fgetexcptflg.c @@ -0,0 +1,32 @@ +/* Store current representation for exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ +  fexcept_t fpsr; + +  /* Get the current exceptions.  */ +  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); + +  *flagp = fpsr & excepts & FE_ALL_EXCEPT; + +  /* Success.  */ +  return 0; +} diff --git a/libm/m68k/fraiseexcpt.c b/libm/m68k/fraiseexcpt.c new file mode 100644 index 000000000..4599c08f7 --- /dev/null +++ b/libm/m68k/fraiseexcpt.c @@ -0,0 +1,106 @@ +/* Raise given exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <float.h> +#include <math.h> + +int +feraiseexcept (int excepts) +{ +#if defined(__mcffpu__) + +  /* The Coldfire FPU allows an exception to be raised by asserting +     the associated EXC bit and then executing an arbitrary arithmetic +     instruction.  fmove.l is classified as an arithmetic instruction +     and suffices for this purpose. + +     We therefore raise an exception by setting both the EXC and AEXC +     bit associated with the exception (the former being 6 bits to the +     left of the latter) and then loading the longword at (%sp) into an +     FP register.  */ + +  inline void +  raise_one_exception (int mask) +  { +    if (excepts & mask) +      { +	int fpsr; +	double unused; + +	__asm__ volatile ("fmove%.l %/fpsr,%0" : "=d" (fpsr)); +	fpsr |= (mask << 6) | mask; +	__asm__ volatile ("fmove%.l %0,%/fpsr" :: "d" (fpsr)); +	__asm__ volatile ("fmove%.l (%%sp),%0" : "=f" (unused)); +      } +  } + +  raise_one_exception (FE_INVALID); +  raise_one_exception (FE_DIVBYZERO); +  raise_one_exception (FE_OVERFLOW); +  raise_one_exception (FE_UNDERFLOW); +  raise_one_exception (FE_INEXACT); + +#else +  /* Raise exceptions represented by EXCEPTS.  But we must raise only one +     signal at a time.  It is important that if the overflow/underflow +     exception and the divide by zero exception are given at the same +     time, the overflow/underflow exception follows the divide by zero +     exception.  */ + +  /* First: invalid exception.  */ +  if (excepts & FE_INVALID) +    { +      /* One example of an invalid operation is 0 * Infinity.  */ +      double d = HUGE_VAL; +      __asm__ __volatile__ ("fmul%.s %#0r0,%0; fnop" : "=f" (d) : "0" (d)); +    } + +  /* Next: division by zero.  */ +  if (excepts & FE_DIVBYZERO) +    { +      double d = 1.0; +      __asm__ __volatile__ ("fdiv%.s %#0r0,%0; fnop" : "=f" (d) : "0" (d)); +    } + +  /* Next: overflow.  */ +  if (excepts & FE_OVERFLOW) +    { +      long double d = LDBL_MAX; + +      __asm__ __volatile__ ("fmul%.x %0,%0; fnop" : "=f" (d) : "0" (d)); +    } + +  /* Next: underflow.  */ +  if (excepts & FE_UNDERFLOW) +    { +      long double d = -LDBL_MAX; + +      __asm__ __volatile__ ("fetox%.x %0; fnop" : "=f" (d) : "0" (d)); +    } + +  /* Last: inexact.  */ +  if (excepts & FE_INEXACT) +    { +      long double d = 1.0; +      __asm__ __volatile__ ("fdiv%.s %#0r3,%0; fnop" : "=f" (d) : "0" (d)); +    } + +#endif +  /* Success.  */ +  return 0; +} diff --git a/libm/m68k/fsetexcptflg.c b/libm/m68k/fsetexcptflg.c new file mode 100644 index 000000000..18fc1811f --- /dev/null +++ b/libm/m68k/fsetexcptflg.c @@ -0,0 +1,38 @@ +/* Set floating-point environment exception handling. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <math.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ +  fexcept_t fpsr; + +  /* Get the current status register.  */ +  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); + +  /* Install the new exception bits in the Accrued Exception Byte.  */ +  fpsr &= ~(excepts & FE_ALL_EXCEPT); +  fpsr |= *flagp & excepts & FE_ALL_EXCEPT; + +  /* Store the new status register.  */ +  __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr)); + +  /* Success.  */ +  return 0; +} diff --git a/libm/m68k/ftestexcept.c b/libm/m68k/ftestexcept.c new file mode 100644 index 000000000..1ece1a48d --- /dev/null +++ b/libm/m68k/ftestexcept.c @@ -0,0 +1,29 @@ +/* Test exception in current environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> + +int +fetestexcept (int excepts) +{ +  fexcept_t fpsr; + +  /* Get current exceptions.  */ +  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr)); + +  return fpsr & excepts & FE_ALL_EXCEPT; +} diff --git a/libm/mips/Makefile.arch b/libm/mips/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/mips/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/mips/fclrexcpt.c b/libm/mips/fclrexcpt.c new file mode 100644 index 000000000..04d48d712 --- /dev/null +++ b/libm/mips/fclrexcpt.c @@ -0,0 +1,44 @@ +/* Clear given exceptions in current floating-point environment. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_libc.h" +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ +  int cw; + +  /* Mask out unsupported bits/exceptions.  */ +  excepts &= FE_ALL_EXCEPT; + +  /* Read the complete control word.  */ +  _FPU_GETCW (cw); + +  /* Clear exception flag bits and cause bits. If the cause bit is not +     cleared, the next CTC instruction (just below) will re-generate the +     exception.  */ + +  cw &= ~(excepts | (excepts << CAUSE_SHIFT)); + +  /* Put the new data in effect.  */ +  _FPU_SETCW (cw); + +  /* Success.  */ +  return 0; +} diff --git a/libm/mips/fedisblxcpt.c b/libm/mips/fedisblxcpt.c new file mode 100644 index 000000000..85cd6c518 --- /dev/null +++ b/libm/mips/fedisblxcpt.c @@ -0,0 +1,38 @@ +/* Disable floating-point exceptions. +   Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_libc.h" +#include <fpu_control.h> + +int +fedisableexcept (int excepts) +{ +  unsigned int new_exc, old_exc; + +  /* Get the current control word.  */ +  _FPU_GETCW (new_exc); + +  old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT; + +  excepts &= FE_ALL_EXCEPT; + +  new_exc &= ~(excepts << ENABLE_SHIFT); +  _FPU_SETCW (new_exc); + +  return old_exc; +} diff --git a/libm/mips/feenablxcpt.c b/libm/mips/feenablxcpt.c new file mode 100644 index 000000000..9d919a8ba --- /dev/null +++ b/libm/mips/feenablxcpt.c @@ -0,0 +1,38 @@ +/* Enable floating-point exceptions. +   Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_libc.h" +#include <fpu_control.h> + +int +feenableexcept (int excepts) +{ +  unsigned int new_exc, old_exc; + +  /* Get the current control word.  */ +  _FPU_GETCW (new_exc); + +  old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT; + +  excepts &= FE_ALL_EXCEPT; + +  new_exc |= excepts << ENABLE_SHIFT; +  _FPU_SETCW (new_exc); + +  return old_exc; +} diff --git a/libm/mips/fegetenv.c b/libm/mips/fegetenv.c new file mode 100644 index 000000000..94f3444ac --- /dev/null +++ b/libm/mips/fegetenv.c @@ -0,0 +1,28 @@ +/* Store current floating-point environment. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetenv (fenv_t *envp) +{ +  _FPU_GETCW (*envp); + +  /* Success.  */ +  return 0; +} diff --git a/libm/mips/fegetexcept.c b/libm/mips/fegetexcept.c new file mode 100644 index 000000000..4c7c89fa6 --- /dev/null +++ b/libm/mips/fegetexcept.c @@ -0,0 +1,31 @@ +/* Get enabled floating-point exceptions. +   Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_libc.h" +#include <fpu_control.h> + +int +fegetexcept (void) +{ +  unsigned int exc; + +  /* Get the current control word.  */ +  _FPU_GETCW (exc); + +  return (exc & ENABLE_MASK) >> ENABLE_SHIFT; +} diff --git a/libm/mips/fegetmode.c b/libm/mips/fegetmode.c new file mode 100644 index 000000000..136b8d3fb --- /dev/null +++ b/libm/mips/fegetmode.c @@ -0,0 +1,26 @@ +/* Store current floating-point control modes.  MIPS version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ +  _FPU_GETCW (*modep); +  return 0; +} diff --git a/libm/mips/fegetround.c b/libm/mips/fegetround.c new file mode 100644 index 000000000..4d8f3744d --- /dev/null +++ b/libm/mips/fegetround.c @@ -0,0 +1,30 @@ +/* Return current rounding direction. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetround (void) +{ +  int cw; + +  /* Get control word.  */ +  _FPU_GETCW (cw); + +  return cw & _FPU_RC_MASK; +} diff --git a/libm/mips/feholdexcpt.c b/libm/mips/feholdexcpt.c new file mode 100644 index 000000000..b1e35ae5a --- /dev/null +++ b/libm/mips/feholdexcpt.c @@ -0,0 +1,35 @@ +/* Store current floating-point environment and clear exceptions. +   Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feholdexcept (fenv_t *envp) +{ +  fpu_control_t cw; + +  /* Save the current state.  */ +  _FPU_GETCW (cw); +  envp->__fp_control_register = cw; + +  /* Clear all exception enable bits and flags.  */ +  cw &= ~(_FPU_MASK_V|_FPU_MASK_Z|_FPU_MASK_O|_FPU_MASK_U|_FPU_MASK_I|FE_ALL_EXCEPT); +  _FPU_SETCW (cw); + +  return 0; +} diff --git a/libm/mips/fenv_libc.h b/libm/mips/fenv_libc.h new file mode 100644 index 000000000..642a7b127 --- /dev/null +++ b/libm/mips/fenv_libc.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#ifndef _FENV_LIBC_H +#define _FENV_LIBC_H    1 + +/* Mask for enabling exceptions and for the CAUSE bits.  */ +#define ENABLE_MASK	0x00F80U +#define CAUSE_MASK	0x1F000U + +/* Shift for FE_* flags to get up to the ENABLE bits and the CAUSE bits.  */ +#define	ENABLE_SHIFT	5 +#define	CAUSE_SHIFT	10 + + +#endif /* _FENV_LIBC_H */ diff --git a/libm/mips/fenv_private.h b/libm/mips/fenv_private.h new file mode 100644 index 000000000..bc9be3b62 --- /dev/null +++ b/libm/mips/fenv_private.h @@ -0,0 +1,238 @@ +/* Internal math stuff.  MIPS version. +   Copyright (C) 2013-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#ifndef MIPS_FENV_PRIVATE_H +#define MIPS_FENV_PRIVATE_H 1 + +/* Inline functions to speed up the math library implementation.  The +   default versions of these routines are in generic/fenv_private.h +   and call fesetround, feholdexcept, etc.  These routines use inlined +   code instead.  */ + +#include <fenv.h> +#include "fenv_libc.h" +#include <fpu_control.h> + +#define _FPU_MASK_ALL (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O \ +		       |_FPU_MASK_U | _FPU_MASK_I | FE_ALL_EXCEPT) + +static __always_inline void +libc_feholdexcept_mips (fenv_t *envp) +{ +  fpu_control_t cw; + +  /* Save the current state.  */ +  _FPU_GETCW (cw); +  envp->__fp_control_register = cw; + +  /* Clear all exception enable bits and flags.  */ +  cw &= ~(_FPU_MASK_ALL); +  _FPU_SETCW (cw); +} +#define libc_feholdexcept libc_feholdexcept_mips +#define libc_feholdexceptf libc_feholdexcept_mips +#define libc_feholdexceptl libc_feholdexcept_mips + +static __always_inline void +libc_fesetround_mips (int round) +{ +  fpu_control_t cw; + +  /* Get current state.  */ +  _FPU_GETCW (cw); + +  /* Set rounding bits.  */ +  cw &= ~_FPU_RC_MASK; +  cw |= round; + +  /* Set new state.  */ +  _FPU_SETCW (cw); +} +#define libc_fesetround libc_fesetround_mips +#define libc_fesetroundf libc_fesetround_mips +#define libc_fesetroundl libc_fesetround_mips + +static __always_inline void +libc_feholdexcept_setround_mips (fenv_t *envp, int round) +{ +  fpu_control_t cw; + +  /* Save the current state.  */ +  _FPU_GETCW (cw); +  envp->__fp_control_register = cw; + +  /* Clear all exception enable bits and flags.  */ +  cw &= ~(_FPU_MASK_ALL); + +  /* Set rounding bits.  */ +  cw &= ~_FPU_RC_MASK; +  cw |= round; + +  /* Set new state.  */ +  _FPU_SETCW (cw); +} +#define libc_feholdexcept_setround libc_feholdexcept_setround_mips +#define libc_feholdexcept_setroundf libc_feholdexcept_setround_mips +#define libc_feholdexcept_setroundl libc_feholdexcept_setround_mips + +#define libc_feholdsetround libc_feholdexcept_setround_mips +#define libc_feholdsetroundf libc_feholdexcept_setround_mips +#define libc_feholdsetroundl libc_feholdexcept_setround_mips + +static __always_inline void +libc_fesetenv_mips (fenv_t *envp) +{ +  fpu_control_t cw __attribute__ ((unused)); + +  /* Read current state to flush fpu pipeline.  */ +  _FPU_GETCW (cw); + +  _FPU_SETCW (envp->__fp_control_register); +} +#define libc_fesetenv libc_fesetenv_mips +#define libc_fesetenvf libc_fesetenv_mips +#define libc_fesetenvl libc_fesetenv_mips + +static __always_inline int +libc_feupdateenv_test_mips (fenv_t *envp, int excepts) +{ +  /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */ +  int cw, temp; + +  /* Get current control word.  */ +  _FPU_GETCW (cw); + +  /* Set flag bits (which are accumulative), and *also* set the +     cause bits.  The setting of the cause bits is what actually causes +     the hardware to generate the exception, if the corresponding enable +     bit is set as well.  */ +  temp = cw & FE_ALL_EXCEPT; +  temp |= envp->__fp_control_register | (temp << CAUSE_SHIFT); + +  /* Set new state.  */ +  _FPU_SETCW (temp); + +  return cw & excepts & FE_ALL_EXCEPT; +} +#define libc_feupdateenv_test libc_feupdateenv_test_mips +#define libc_feupdateenv_testf libc_feupdateenv_test_mips +#define libc_feupdateenv_testl libc_feupdateenv_test_mips + +static __always_inline void +libc_feupdateenv_mips (fenv_t *envp) +{ +  libc_feupdateenv_test_mips (envp, 0); +} +#define libc_feupdateenv libc_feupdateenv_mips +#define libc_feupdateenvf libc_feupdateenv_mips +#define libc_feupdateenvl libc_feupdateenv_mips + +#define libc_feresetround libc_feupdateenv_mips +#define libc_feresetroundf libc_feupdateenv_mips +#define libc_feresetroundl libc_feupdateenv_mips + +static __always_inline int +libc_fetestexcept_mips (int excepts) +{ +  int cw; + +  /* Get current control word.  */ +  _FPU_GETCW (cw); + +  return cw & excepts & FE_ALL_EXCEPT; +} +#define libc_fetestexcept libc_fetestexcept_mips +#define libc_fetestexceptf libc_fetestexcept_mips +#define libc_fetestexceptl libc_fetestexcept_mips + +/*  Enable support for rounding mode context.  */ +#define HAVE_RM_CTX 1 + +static __always_inline void +libc_feholdexcept_setround_mips_ctx (struct rm_ctx *ctx, int round) +{ +  fpu_control_t old, new; + +  /* Save the current state.  */ +  _FPU_GETCW (old); +  ctx->env.__fp_control_register = old; + +  /* Clear all exception enable bits and flags.  */ +  new = old & ~(_FPU_MASK_ALL); + +  /* Set rounding bits.  */ +  new = (new & ~_FPU_RC_MASK) | round; + +  if (__glibc_unlikely (new != old)) +    { +      _FPU_SETCW (new); +      ctx->updated_status = true; +    } +  else +    ctx->updated_status = false; +} +#define libc_feholdexcept_setround_ctx   libc_feholdexcept_setround_mips_ctx +#define libc_feholdexcept_setroundf_ctx  libc_feholdexcept_setround_mips_ctx +#define libc_feholdexcept_setroundl_ctx  libc_feholdexcept_setround_mips_ctx + +static __always_inline void +libc_fesetenv_mips_ctx (struct rm_ctx *ctx) +{ +  libc_fesetenv_mips (&ctx->env); +} +#define libc_fesetenv_ctx                libc_fesetenv_mips_ctx +#define libc_fesetenvf_ctx               libc_fesetenv_mips_ctx +#define libc_fesetenvl_ctx               libc_fesetenv_mips_ctx + +static __always_inline void +libc_feupdateenv_mips_ctx (struct rm_ctx *ctx) +{ +  if (__glibc_unlikely (ctx->updated_status)) +    libc_feupdateenv_test_mips (&ctx->env, 0); +} +#define libc_feupdateenv_ctx             libc_feupdateenv_mips_ctx +#define libc_feupdateenvf_ctx            libc_feupdateenv_mips_ctx +#define libc_feupdateenvl_ctx            libc_feupdateenv_mips_ctx +#define libc_feresetround_ctx            libc_feupdateenv_mips_ctx +#define libc_feresetroundf_ctx           libc_feupdateenv_mips_ctx +#define libc_feresetroundl_ctx           libc_feupdateenv_mips_ctx + +static __always_inline void +libc_feholdsetround_mips_ctx (struct rm_ctx *ctx, int round) +{ +  fpu_control_t old, new; + +  /* Save the current state.  */ +  _FPU_GETCW (old); +  ctx->env.__fp_control_register = old; + +  /* Set rounding bits.  */ +  new = (old & ~_FPU_RC_MASK) | round; + +  if (__glibc_unlikely (new != old)) +    { +      _FPU_SETCW (new); +      ctx->updated_status = true; +    } +  else +    ctx->updated_status = false; +} +#define libc_feholdsetround_ctx          libc_feholdsetround_mips_ctx +#define libc_feholdsetroundf_ctx         libc_feholdsetround_mips_ctx +#define libc_feholdsetroundl_ctx         libc_feholdsetround_mips_ctx + +#endif diff --git a/libm/mips/fesetenv.c b/libm/mips/fesetenv.c new file mode 100644 index 000000000..03b5b91a6 --- /dev/null +++ b/libm/mips/fesetenv.c @@ -0,0 +1,38 @@ +/* Install given floating-point environment. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetenv (const fenv_t *envp) +{ +  fpu_control_t cw; + +  /* Read first current state to flush fpu pipeline.  */ +  _FPU_GETCW (cw); + +  if (envp == FE_DFL_ENV) +    _FPU_SETCW (_FPU_DEFAULT); +  else if (envp == FE_NOMASK_ENV) +    _FPU_SETCW (_FPU_IEEE); +  else +    _FPU_SETCW (envp->__fp_control_register); + +  /* Success.  */ +  return 0; +} diff --git a/libm/mips/fesetexcept.c b/libm/mips/fesetexcept.c new file mode 100644 index 000000000..1c9a0de3b --- /dev/null +++ b/libm/mips/fesetexcept.c @@ -0,0 +1,31 @@ +/* Set given exception flags.  MIPS version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexcept (int excepts) +{ +  fpu_control_t temp; + +  _FPU_GETCW (temp); +  temp |= excepts & FE_ALL_EXCEPT; +  _FPU_SETCW (temp); + +  return 0; +} diff --git a/libm/mips/fesetmode.c b/libm/mips/fesetmode.c new file mode 100644 index 000000000..cb4ffdc06 --- /dev/null +++ b/libm/mips/fesetmode.c @@ -0,0 +1,37 @@ +/* Install given floating-point control modes.  MIPS version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +#define FCSR_STATUS 0xfe83f07c + +int +fesetmode (const femode_t *modep) +{ +  fpu_control_t cw; + +  _FPU_GETCW (cw); +  cw &= FCSR_STATUS; +  if (modep == FE_DFL_MODE) +    cw |= _FPU_DEFAULT; +  else +    cw |= *modep & ~FCSR_STATUS; +  _FPU_SETCW (cw); + +  return 0; +} diff --git a/libm/mips/fesetround.c b/libm/mips/fesetround.c new file mode 100644 index 000000000..532092710 --- /dev/null +++ b/libm/mips/fesetround.c @@ -0,0 +1,40 @@ +/* Set current rounding direction. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetround (int round) +{ +  fpu_control_t cw; + +  if ((round & ~_FPU_RC_MASK) != 0) +    /* ROUND is no valid rounding mode.  */ +    return 1; + +  /* Get current state.  */ +  _FPU_GETCW (cw); + +  /* Set rounding bits.  */ +  cw &= ~_FPU_RC_MASK; +  cw |= round; +  /* Set new state.  */ +  _FPU_SETCW (cw); + +  return 0; +} diff --git a/libm/mips/feupdateenv.c b/libm/mips/feupdateenv.c new file mode 100644 index 000000000..d90604db3 --- /dev/null +++ b/libm/mips/feupdateenv.c @@ -0,0 +1,40 @@ +/* Install given floating-point environment and raise exceptions. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feupdateenv (const fenv_t *envp) +{ +  int temp; + +  /* Save current exceptions.  */ +  _FPU_GETCW (temp); +  temp &= FE_ALL_EXCEPT; + +  /* Install new environment.  */ +  fesetenv (envp); + +  /* Raise the saved exception.  Incidentally for us the implementation +     defined format of the values in objects of type fexcept_t is the +     same as the ones specified using the FE_* constants.  */ +  feraiseexcept (temp); + +  /* Success.  */ +  return 0; +} diff --git a/libm/mips/fgetexcptflg.c b/libm/mips/fgetexcptflg.c new file mode 100644 index 000000000..b03eca55e --- /dev/null +++ b/libm/mips/fgetexcptflg.c @@ -0,0 +1,37 @@ +/* Store current representation for exceptions. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ +  fpu_control_t temp; + +  /* Get the current exceptions.  */ +  _FPU_GETCW (temp); + +  /* We only save the relevant bits here. In particular, care has to be +     taken with the CAUSE bits, as an inadvertent restore later on could +     generate unexpected exceptions.  */ + +  *flagp = temp & excepts & FE_ALL_EXCEPT; + +  /* Success.  */ +  return 0; +} diff --git a/libm/mips/fraiseexcpt.c b/libm/mips/fraiseexcpt.c new file mode 100644 index 000000000..6327b1104 --- /dev/null +++ b/libm/mips/fraiseexcpt.c @@ -0,0 +1,42 @@ +/* Raise given exceptions. +   Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_libc.h" +#include <fpu_control.h> + +int +feraiseexcept (int excepts) +{ +  fpu_control_t cw; + +  /* Get current state.  */ +  _FPU_GETCW (cw); + +  /* Set flag bits (which are accumulative), and *also* set the +     cause bits. The setting of the cause bits is what actually causes +     the hardware to generate the exception, if the corresponding enable +     bit is set as well.  */ + +  excepts &= FE_ALL_EXCEPT; +  cw |= excepts | (excepts << CAUSE_SHIFT); + +  /* Set new state.  */ +  _FPU_SETCW (cw); + +  return 0; +} diff --git a/libm/mips/fsetexcptflg.c b/libm/mips/fsetexcptflg.c new file mode 100644 index 000000000..d98a300e2 --- /dev/null +++ b/libm/mips/fsetexcptflg.c @@ -0,0 +1,40 @@ +/* Set floating-point environment exception handling. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ +  fpu_control_t temp; + +  /* Get the current exceptions.  */ +  _FPU_GETCW (temp); + +  /* Make sure the flags we want restored are legal.  */ +  excepts &= FE_ALL_EXCEPT; + +  /* Now clear the bits called for, and copy them in from flagp. Note that +     we ignore all non-flag bits from *flagp, so they don't matter.  */ +  temp = (temp & ~excepts) | (*flagp & excepts); + +  _FPU_SETCW (temp); + +  /* Success.  */ +  return 0; +} diff --git a/libm/mips/ftestexcept.c b/libm/mips/ftestexcept.c new file mode 100644 index 000000000..8fdca7560 --- /dev/null +++ b/libm/mips/ftestexcept.c @@ -0,0 +1,30 @@ +/* Test exception in current environment. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fetestexcept (int excepts) +{ +  int cw; + +  /* Get current control word.  */ +  _FPU_GETCW (cw); + +  return cw & excepts & FE_ALL_EXCEPT; +} diff --git a/libm/nan.c b/libm/nan.c index 454734b6f..9c2cd6e90 100644 --- a/libm/nan.c +++ b/libm/nan.c @@ -28,7 +28,7 @@ double nan (const char *tagp)  		sprintf (buf, "NAN(%s)", tagp);  		return strtod (buf, NULL);  	} -	return NAN; +	return (double)NAN;  }  libm_hidden_def(nan) @@ -53,7 +53,7 @@ long double nanl (const char *tagp)  		sprintf (buf, "NAN(%s)", tagp);  		return strtold (buf, NULL);  	} -	return NAN; +	return (long double)NAN;  }  libm_hidden_def(nanl)  #endif 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/s_expm1.c b/libm/s_expm1.c index 8e51ae748..85defefa4 100644 --- a/libm/s_expm1.c +++ b/libm/s_expm1.c @@ -159,7 +159,7 @@ double expm1(double x)  		else  		    {hi = x + ln2_hi; lo = -ln2_lo;  k = -1;}  	    } else { -		k  = invln2*x+((xsb==0)?0.5:-0.5); +		k  = (int32_t)(invln2*x+((xsb==0)?0.5:-0.5));  		t  = k;  		hi = x - t*ln2_hi;	/* t*ln2_hi is exact here */  		lo = t*ln2_lo; diff --git a/libm/s_lrint.c b/libm/s_lrint.c index 09800d8de..2a8db9fbe 100644 --- a/libm/s_lrint.c +++ b/libm/s_lrint.c @@ -49,19 +49,13 @@ lrint (double x)    if (_j0 < 20)      { -      if (_j0 < -1) -	return 0; -      else -	{ -	  w = two52[sx] + x; -	  t = w - two52[sx]; -	  EXTRACT_WORDS (i0, i1, t); -	  _j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; -	  i0 &= 0xfffff; -	  i0 |= 0x100000; - -	  result = i0 >> (20 - _j0); -	} +      w = two52[sx] + x; +      t = w - two52[sx]; +      EXTRACT_WORDS (i0, i1, t); +      _j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; +      i0 &= 0xfffff; +      i0 |= 0x100000; +      result = (_j0 < 0 ? 0 : i0 >> (20 - _j0));      }    else if (_j0 < (int32_t) (8 * sizeof (long int)) - 1)      { diff --git a/libm/s_nextafter.c b/libm/s_nextafter.c index 73a8ab2be..7eb4ec46e 100644 --- a/libm/s_nextafter.c +++ b/libm/s_nextafter.c @@ -18,6 +18,7 @@  #include "math.h"  #include "math_private.h" +#include <float.h>  double nextafter(double x, double y)  { @@ -68,5 +69,13 @@ double nextafter(double x, double y)  	return x;  }  libm_hidden_def(nextafter) +#if LDBL_MANT_DIG == DBL_MANT_DIG  strong_alias_untyped(nextafter, nexttoward)  libm_hidden_def(nexttoward) +#else +double nexttoward(double x, long double y) +{ +       return nextafter(x, y); +} +libm_hidden_def(nexttoward) +#endif diff --git a/libm/sh/sh4/Makefile.arch b/libm/sh/sh4/Makefile.arch index e38e99c15..69996edda 100644 --- a/libm/sh/sh4/Makefile.arch +++ b/libm/sh/sh4/Makefile.arch @@ -8,7 +8,7 @@  ifeq ($(UCLIBC_HAS_FENV),y)  libm_ARCH_CSRC:=$(wildcard $(libm_SUBARCH_DIR)/*.c) -libm_ARCH_COBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.c,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_SRC)) +libm_ARCH_COBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.c,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_CSRC))  libm_ARCH_SSRC:=$(wildcard $(libm_SUBARCH_DIR)/*.S)  libm_ARCH_SOBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.S,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_SSRC))  endif diff --git a/libm/sh/sh4/fclrexcpt.c b/libm/sh/sh4/fclrexcpt.c new file mode 100644 index 000000000..286b4f36a --- /dev/null +++ b/libm/sh/sh4/fclrexcpt.c @@ -0,0 +1,39 @@ +/* Clear given exceptions in current floating-point environment. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ +  fpu_control_t cw; + +  /* Mask out unsupported bits/exceptions.  */ +  excepts &= FE_ALL_EXCEPT; + +  /* Read the complete control word.  */ +  _FPU_GETCW (cw); + +  /* Clear exception bits.  */ +  cw &= ~excepts; + +  /* Put the new data in effect.  */ +  _FPU_SETCW (cw); + +  return 0; +} diff --git a/libm/sh/sh4/fedisblxcpt.c b/libm/sh/sh4/fedisblxcpt.c new file mode 100644 index 000000000..69f9ff2c4 --- /dev/null +++ b/libm/sh/sh4/fedisblxcpt.c @@ -0,0 +1,37 @@ +/* Disable floating-point exceptions. +   Copyright (C) 2012-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fedisableexcept (int excepts) +{ +  fpu_control_t temp, old_exc; + +  /* Get the current control register contents.  */ +  _FPU_GETCW (temp); + +  old_exc = (temp >> 5) & FE_ALL_EXCEPT; + +  excepts &= FE_ALL_EXCEPT; + +  temp &= ~(excepts << 5); +  _FPU_SETCW (temp); + +  return old_exc; +} diff --git a/libm/sh/sh4/feenablxcpt.c b/libm/sh/sh4/feenablxcpt.c new file mode 100644 index 000000000..bf2b01f0b --- /dev/null +++ b/libm/sh/sh4/feenablxcpt.c @@ -0,0 +1,36 @@ +/* Enable floating-point exceptions. +   Copyright (C) 2012-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feenableexcept (int excepts) +{ +  fpu_control_t temp, old_flag; + +  /* Get current exceptions.  */ +  _FPU_GETCW (temp); + +  old_flag = (temp >> 5) & FE_ALL_EXCEPT; +  excepts &= FE_ALL_EXCEPT; + +  temp |= excepts << 5; +  _FPU_SETCW (temp); + +  return old_flag; +} diff --git a/libm/sh/sh4/fegetenv.c b/libm/sh/sh4/fegetenv.c new file mode 100644 index 000000000..d76964f8b --- /dev/null +++ b/libm/sh/sh4/fegetenv.c @@ -0,0 +1,30 @@ +/* Store current floating-point environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetenv (fenv_t *envp) +{ +  fpu_control_t temp; +  _FPU_GETCW (temp); + +  envp->__fpscr = temp; + +  return 0; +} diff --git a/libm/sh/sh4/fegetexcept.c b/libm/sh/sh4/fegetexcept.c new file mode 100644 index 000000000..85f783520 --- /dev/null +++ b/libm/sh/sh4/fegetexcept.c @@ -0,0 +1,30 @@ +/* Get enabled floating-point exceptions. +   Copyright (C) 2012-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetexcept (void) +{ +  fpu_control_t temp; + +  /* Get current exceptions.  */ +  _FPU_GETCW (temp); + +  return (temp >> 5) & FE_ALL_EXCEPT; +} diff --git a/libm/sh/sh4/fegetmode.c b/libm/sh/sh4/fegetmode.c new file mode 100644 index 000000000..16deb5183 --- /dev/null +++ b/libm/sh/sh4/fegetmode.c @@ -0,0 +1,26 @@ +/* Store current floating-point control modes.  SH4 version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ +  _FPU_GETCW (*modep); +  return 0; +} diff --git a/libm/sh/sh4/fegetround.c b/libm/sh/sh4/fegetround.c new file mode 100644 index 000000000..b7c26eb6f --- /dev/null +++ b/libm/sh/sh4/fegetround.c @@ -0,0 +1,30 @@ +/* Return current rounding direction. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetround (void) +{ +  fpu_control_t cw; + +  /* Get control word.  */ +  _FPU_GETCW (cw); + +  return cw & 0x1; +} diff --git a/libm/sh/sh4/feholdexcpt.c b/libm/sh/sh4/feholdexcpt.c index 70b51e8dd..fc462b403 100644 --- a/libm/sh/sh4/feholdexcpt.c +++ b/libm/sh/sh4/feholdexcpt.c @@ -1,13 +1,19 @@ -/* - * - * Copyright (c) 2007  STMicroelectronics Ltd - * Filippo Arcidiacono (filippo.arcidiacono@st.com) - * - * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. - * - * Taken from glibc 2.6 - * - */ +/* Store current floating-point environment and clear exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */  #include <fenv.h>  #include <fpu_control.h> @@ -15,15 +21,20 @@  int  feholdexcept (fenv_t *envp)  { -  unsigned long int temp; +  fpu_control_t temp;    /* Store the environment.  */    _FPU_GETCW (temp);    envp->__fpscr = temp; -  /* Now set all exceptions to non-stop.  */ +  /* Clear the status flags.  */    temp &= ~FE_ALL_EXCEPT; + +  /* Now set all exceptions to non-stop.  */ +  temp &= ~(FE_ALL_EXCEPT << 5); +    _FPU_SETCW (temp); -  return 1; +  /* Success.  */ +  return 0;  } diff --git a/libm/sh/sh4/fesetenv.c b/libm/sh/sh4/fesetenv.c index c5cfc1d51..6a9a68090 100644 --- a/libm/sh/sh4/fesetenv.c +++ b/libm/sh/sh4/fesetenv.c @@ -1,13 +1,19 @@ -/* - * - * Copyright (c) 2007  STMicroelectronics Ltd - * Filippo Arcidiacono (filippo.arcidiacono@st.com) - * - * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. - * - * Taken from glibc 2.6 - * - */ +/* Install given floating-point environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */  #include <fenv.h>  #include <fpu_control.h> @@ -19,7 +25,7 @@ fesetenv (const fenv_t *envp)        _FPU_SETCW (_FPU_DEFAULT);    else      { -      unsigned long int temp = envp->__fpscr; +      fpu_control_t temp = envp->__fpscr;        _FPU_SETCW (temp);      }    return 0; diff --git a/libm/sh/sh4/fesetexcept.c b/libm/sh/sh4/fesetexcept.c new file mode 100644 index 000000000..eceb0bb4f --- /dev/null +++ b/libm/sh/sh4/fesetexcept.c @@ -0,0 +1,31 @@ +/* Set given exception flags.  SH4 version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexcept (int excepts) +{ +  fpu_control_t temp; + +  _FPU_GETCW (temp); +  temp |= (excepts & FE_ALL_EXCEPT); +  _FPU_SETCW (temp); + +  return 0; +} diff --git a/libm/sh/sh4/fesetmode.c b/libm/sh/sh4/fesetmode.c new file mode 100644 index 000000000..073da0984 --- /dev/null +++ b/libm/sh/sh4/fesetmode.c @@ -0,0 +1,37 @@ +/* Install given floating-point control modes.  SH4 version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +#define FPU_STATUS 0x3f07c + +int +fesetmode (const femode_t *modep) +{ +  fpu_control_t fpscr; + +  _FPU_GETCW (fpscr); +  fpscr &= FPU_STATUS; +  if (modep == FE_DFL_MODE) +    fpscr |= _FPU_DEFAULT; +  else +    fpscr |= *modep & ~FPU_STATUS; +  _FPU_SETCW (fpscr); + +  return 0; +} diff --git a/libm/sh/sh4/fesetround.c b/libm/sh/sh4/fesetround.c new file mode 100644 index 000000000..144eca86f --- /dev/null +++ b/libm/sh/sh4/fesetround.c @@ -0,0 +1,40 @@ +/* Set current rounding direction. +   Copyright (C) 1998-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetround (int round) +{ +  fpu_control_t cw; + +  if ((round & ~0x1) != 0) +    /* ROUND is no valid rounding mode.  */ +    return 1; + +  /* Get current state.  */ +  _FPU_GETCW (cw); + +  /* Set rounding bits.  */ +  cw &= ~0x1; +  cw |= round; +  /* Set new state.  */ +  _FPU_SETCW (cw); + +  return 0; +} diff --git a/libm/sh/sh4/feupdateenv.c b/libm/sh/sh4/feupdateenv.c new file mode 100644 index 000000000..cb7e95259 --- /dev/null +++ b/libm/sh/sh4/feupdateenv.c @@ -0,0 +1,36 @@ +/* Install given floating-point environment and raise exceptions. +   Copyright (C) 2012-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +feupdateenv (const fenv_t *envp) +{ +  fpu_control_t temp; + +  _FPU_GETCW (temp); +  temp = (temp & FE_ALL_EXCEPT); + +  /* Raise the saved exception. Incidentally for us the implementation +    defined format of the values in objects of type fexcept_t is the +    same as the ones specified using the FE_* constants. */ +  fesetenv (envp); +  feraiseexcept ((int) temp); + +  return 0; +} diff --git a/libm/sh/sh4/fgetexcptflg.c b/libm/sh/sh4/fgetexcptflg.c new file mode 100644 index 000000000..308b5ad44 --- /dev/null +++ b/libm/sh/sh4/fgetexcptflg.c @@ -0,0 +1,37 @@ +/* Store current representation for exceptions. +   Copyright (C) 2013-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library.  If not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ +  fpu_control_t temp; + +  /* Get the current exceptions.  */ +  _FPU_GETCW (temp); + +  /* We only save the relevant bits here. In particular, care has to be +     taken with the CAUSE bits, as an inadvertent restore later on could +     generate unexpected exceptions.  */ + +  *flagp = temp & excepts & FE_ALL_EXCEPT; + +  /* Success.  */ +  return 0; +} diff --git a/libm/sh/sh4/fraiseexcpt.c b/libm/sh/sh4/fraiseexcpt.c new file mode 100644 index 000000000..1ed495b7a --- /dev/null +++ b/libm/sh/sh4/fraiseexcpt.c @@ -0,0 +1,70 @@ +/* Raise given exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <float.h> +#include <fpu_control.h> +#include <math.h> + +int +feraiseexcept (int excepts) +{ +  if (excepts == 0) +    return 0; + +  /* Raise exceptions represented by EXPECTS.  */ + +  if (excepts & FE_INEXACT) +  { +    double d = 1.0, x = 3.0; +    __asm__ __volatile__ ("fdiv %1, %0" : "+d" (d) : "d" (x)); +  } + +  if (excepts & FE_UNDERFLOW) +  { +    long double d = LDBL_MIN, x = 10; +    __asm__ __volatile__ ("fdiv %1, %0" : "+d" (d) : "d" (x)); +  } + +  if (excepts & FE_OVERFLOW) +  { +    long double d = LDBL_MAX; +    __asm__ __volatile__ ("fmul %0, %0" : "+d" (d) : "d" (d)); +  } + +  if (excepts & FE_DIVBYZERO) +  { +    double d = 1.0, x = 0.0; +    __asm__ __volatile__ ("fdiv %1, %0" : "+d" (d) : "d" (x)); +  } + +  if (excepts & FE_INVALID) +  { +    double d = HUGE_VAL, x = 0.0; +    __asm__ __volatile__ ("fmul %1, %0" : "+d" (d) : "d" (x)); +  } + +  { +    /* Restore flag fields.  */ +    fpu_control_t cw; +    _FPU_GETCW (cw); +    cw |= (excepts & FE_ALL_EXCEPT); +    _FPU_SETCW (cw); +  } + +  return 0; +} diff --git a/libm/sh/sh4/fsetexcptflg.c b/libm/sh/sh4/fsetexcptflg.c new file mode 100644 index 000000000..8fcb94973 --- /dev/null +++ b/libm/sh/sh4/fsetexcptflg.c @@ -0,0 +1,38 @@ +/* Set floating-point environment exception handling. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <math.h> +#include <fpu_control.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ +  fpu_control_t temp; + +  /* Get the current environment.  */ +  _FPU_GETCW (temp); + +  /* Set the desired exception mask.  */ +  temp &= ~(excepts & FE_ALL_EXCEPT); +  temp |= (*flagp & excepts & FE_ALL_EXCEPT); + +  /* Save state back to the FPU.  */ +  _FPU_SETCW (temp); + +  return 0; +} diff --git a/libm/sh/sh4/ftestexcept.c b/libm/sh/sh4/ftestexcept.c new file mode 100644 index 000000000..edc523426 --- /dev/null +++ b/libm/sh/sh4/ftestexcept.c @@ -0,0 +1,30 @@ +/* Test exception in current environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fetestexcept (int excepts) +{ +  fpu_control_t temp; + +  /* Get current exceptions.  */ +  _FPU_GETCW (temp); + +  return temp & excepts & FE_ALL_EXCEPT; +} diff --git a/libm/sparc/Makefile.arch b/libm/sparc/Makefile.arch new file mode 100644 index 000000000..bd38690be --- /dev/null +++ b/libm/sparc/Makefile.arch @@ -0,0 +1,16 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/sparc/fclrexcpt.c b/libm/sparc/fclrexcpt.c new file mode 100644 index 000000000..ae344658d --- /dev/null +++ b/libm/sparc/fclrexcpt.c @@ -0,0 +1,34 @@ +/* Clear given exceptions in current floating-point environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feclearexcept (int excepts) +{ +  fenv_t tmp; + +  __fenv_stfsr (tmp); + +  tmp &= ~(excepts & FE_ALL_EXCEPT); + +  __fenv_ldfsr (tmp); + +  /* Success.  */ +  return 0; +} diff --git a/libm/sparc/fedisblxcpt.c b/libm/sparc/fedisblxcpt.c new file mode 100644 index 000000000..9bc546f2d --- /dev/null +++ b/libm/sparc/fedisblxcpt.c @@ -0,0 +1,34 @@ +/* Disable floating-point exceptions. +   Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fedisableexcept (int excepts) +{ +  fenv_t new_exc, old_exc; + +  __fenv_stfsr (new_exc); + +  old_exc = (new_exc >> 18) & FE_ALL_EXCEPT; +  new_exc &= ~(((fenv_t)excepts & FE_ALL_EXCEPT) << 18); + +  __fenv_ldfsr (new_exc); + +  return old_exc; +} diff --git a/libm/sparc/feenablxcpt.c b/libm/sparc/feenablxcpt.c new file mode 100644 index 000000000..ab88e7e42 --- /dev/null +++ b/libm/sparc/feenablxcpt.c @@ -0,0 +1,34 @@ +/* Enable floating-point exceptions. +   Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feenableexcept (int excepts) +{ +  fenv_t new_exc, old_exc; + +  __fenv_stfsr (new_exc); + +  old_exc = (new_exc >> 18) & FE_ALL_EXCEPT; +  new_exc |= (((fenv_t)excepts & FE_ALL_EXCEPT) << 18); + +  __fenv_ldfsr (new_exc); + +  return old_exc; +} diff --git a/libm/sparc/fegetenv.c b/libm/sparc/fegetenv.c new file mode 100644 index 000000000..883012932 --- /dev/null +++ b/libm/sparc/fegetenv.c @@ -0,0 +1,28 @@ +/* Store current floating-point environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetenv (fenv_t *envp) +{ +  __fenv_stfsr (*envp); + +  /* Success.  */ +  return 0; +} diff --git a/libm/sparc/fegetexcept.c b/libm/sparc/fegetexcept.c new file mode 100644 index 000000000..53dfdab8c --- /dev/null +++ b/libm/sparc/fegetexcept.c @@ -0,0 +1,28 @@ +/* Get enabled floating-point exceptions. +   Copyright (C) 2000-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetexcept (void) +{ +  fenv_t exc; +  __fenv_stfsr (exc); + +  return (exc >> 18) & FE_ALL_EXCEPT; +} diff --git a/libm/sparc/fegetmode.c b/libm/sparc/fegetmode.c new file mode 100644 index 000000000..0bb9ba111 --- /dev/null +++ b/libm/sparc/fegetmode.c @@ -0,0 +1,26 @@ +/* Store current floating-point control modes.  SPARC version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetmode (femode_t *modep) +{ +  __fenv_stfsr (*modep); +  return 0; +} diff --git a/libm/sparc/fegetround.c b/libm/sparc/fegetround.c new file mode 100644 index 000000000..bb53a735e --- /dev/null +++ b/libm/sparc/fegetround.c @@ -0,0 +1,29 @@ +/* Return current rounding direction. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetround (void) +{ +  fenv_t tmp; + +  __fenv_stfsr (tmp); + +  return tmp & __FE_ROUND_MASK; +} diff --git a/libm/sparc/feholdexcpt.c b/libm/sparc/feholdexcpt.c new file mode 100644 index 000000000..7d712198b --- /dev/null +++ b/libm/sparc/feholdexcpt.c @@ -0,0 +1,34 @@ +/* Store current floating-point environment and clear exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feholdexcept (fenv_t *envp) +{ +  fenv_t tmp; + +  __fenv_stfsr (*envp); + +  /* Set all exceptions to non-stop and clear all exceptions.  */ +  tmp = *envp & ~((0x1f << 23) | FE_ALL_EXCEPT); + +  __fenv_ldfsr (tmp); + +  return 0; +} diff --git a/libm/sparc/fenv_private.h b/libm/sparc/fenv_private.h new file mode 100644 index 000000000..b888d8442 --- /dev/null +++ b/libm/sparc/fenv_private.h @@ -0,0 +1,187 @@ +#ifndef SPARC_FENV_PRIVATE_H +#define SPARC_FENV_PRIVATE_H 1 + +#include <fenv.h> +#include <fpu_control.h> + +/* For internal use only: access the fp state register.  */ +#define __fenv_stfsr(X)   _FPU_GETCW (X) +#define __fenv_ldfsr(X)   _FPU_SETCW (X) + +static __always_inline void +libc_feholdexcept (fenv_t *e) +{ +  fenv_t etmp; +  __fenv_stfsr(etmp); +  *(e) = etmp; +  etmp = etmp & ~((0x1f << 23) | FE_ALL_EXCEPT); +  __fenv_ldfsr(etmp); +} + +static __always_inline void +libc_fesetround (int r) +{ +  fenv_t etmp; +  __fenv_stfsr(etmp); +  etmp = (etmp & ~__FE_ROUND_MASK) | (r); +  __fenv_ldfsr(etmp); +} + +static __always_inline void +libc_feholdexcept_setround (fenv_t *e, int r) +{ +  fenv_t etmp; +  __fenv_stfsr(etmp); +  *(e) = etmp; +  etmp = etmp & ~((0x1f << 23) | FE_ALL_EXCEPT); +  etmp = (etmp & ~__FE_ROUND_MASK) | (r); +  __fenv_ldfsr(etmp); +} + +static __always_inline int +libc_fetestexcept (int e) +{ +  fenv_t etmp; +  __fenv_stfsr(etmp); +  return etmp & (e) & FE_ALL_EXCEPT; +} + +static __always_inline void +libc_fesetenv (fenv_t *e) +{ +  __fenv_ldfsr(*e); +} + +static __always_inline int +libc_feupdateenv_test (fenv_t *e, int ex) +{ +  fenv_t etmp; + +  __fenv_stfsr(etmp); +  etmp &= FE_ALL_EXCEPT; + +  __fenv_ldfsr(*e); + +  feraiseexcept (etmp); + +  return etmp & ex; +} + +static __always_inline void +libc_feupdateenv (fenv_t *e) +{ +  libc_feupdateenv_test (e, 0); +} + +static __always_inline void +libc_feholdsetround (fenv_t *e, int r) +{ +  fenv_t etmp; +  __fenv_stfsr(etmp); +  *(e) = etmp; +  etmp = (etmp & ~__FE_ROUND_MASK) | (r); +  __fenv_ldfsr(etmp); +} + +static __always_inline void +libc_feresetround (fenv_t *e) +{ +  fenv_t etmp; +  __fenv_stfsr(etmp); +  etmp = (etmp & ~__FE_ROUND_MASK) | (*e & __FE_ROUND_MASK); +  __fenv_ldfsr(etmp); +} + +#define libc_feholdexceptf		libc_feholdexcept +#define libc_fesetroundf		libc_fesetround +#define libc_feholdexcept_setroundf	libc_feholdexcept_setround +#define libc_fetestexceptf		libc_fetestexcept +#define libc_fesetenvf			libc_fesetenv +#define libc_feupdateenv_testf		libc_feupdateenv_test +#define libc_feupdateenvf		libc_feupdateenv +#define libc_feholdsetroundf		libc_feholdsetround +#define libc_feresetroundf		libc_feresetround +#define libc_feholdexcept		libc_feholdexcept +#define libc_fesetround			libc_fesetround +#define libc_feholdexcept_setround	libc_feholdexcept_setround +#define libc_fetestexcept		libc_fetestexcept +#define libc_fesetenv			libc_fesetenv +#define libc_feupdateenv_test		libc_feupdateenv_test +#define libc_feupdateenv		libc_feupdateenv +#define libc_feholdsetround		libc_feholdsetround +#define libc_feresetround		libc_feresetround +#define libc_feholdexceptl		libc_feholdexcept +#define libc_fesetroundl		libc_fesetround +#define libc_feholdexcept_setroundl	libc_feholdexcept_setround +#define libc_fetestexceptl		libc_fetestexcept +#define libc_fesetenvl			libc_fesetenv +#define libc_feupdateenv_testl		libc_feupdateenv_test +#define libc_feupdateenvl		libc_feupdateenv +#define libc_feholdsetroundl		libc_feholdsetround +#define libc_feresetroundl		libc_feresetround + +/* We have support for rounding mode context.  */ +#define HAVE_RM_CTX 1 + +static __always_inline void +libc_feholdexcept_setround_sparc_ctx (struct rm_ctx *ctx, int round) +{ +  fenv_t new; + +  __fenv_stfsr(ctx->env); +  new = ctx->env & ~((0x1f << 23) | FE_ALL_EXCEPT); +  new = (new & ~__FE_ROUND_MASK) | round; +  if (unlikely (new != ctx->env)) +    { +      __fenv_ldfsr(new); +      ctx->updated_status = true; +    } +  else +    ctx->updated_status = false; +} + +static __always_inline void +libc_fesetenv_sparc_ctx (struct rm_ctx *ctx) +{ +  libc_fesetenv(&ctx->env); +} + +static __always_inline void +libc_feupdateenv_sparc_ctx (struct rm_ctx *ctx) +{ +  if (unlikely (ctx->updated_status)) +    libc_feupdateenv_test (&ctx->env, 0); +} + +static __always_inline void +libc_feholdsetround_sparc_ctx (struct rm_ctx *ctx, int round) +{ +  fenv_t new; + +  __fenv_stfsr(ctx->env); +  new = (ctx->env & ~__FE_ROUND_MASK) | round; +  if (unlikely (new != ctx->env)) +    { +      __fenv_ldfsr(new); +      ctx->updated_status = true; +    } +  else +    ctx->updated_status = false; +} +#define libc_feholdexcept_setround_ctx   libc_feholdexcept_setround_sparc_ctx +#define libc_feholdexcept_setroundf_ctx  libc_feholdexcept_setround_sparc_ctx +#define libc_feholdexcept_setroundl_ctx  libc_feholdexcept_setround_sparc_ctx +#define libc_fesetenv_ctx                libc_fesetenv_sparc_ctx +#define libc_fesetenvf_ctx               libc_fesetenv_sparc_ctx +#define libc_fesetenvl_ctx               libc_fesetenv_sparc_ctx +#define libc_feupdateenv_ctx             libc_feupdateenv_sparc_ctx +#define libc_feupdateenvf_ctx            libc_feupdateenv_sparc_ctx +#define libc_feupdateenvl_ctx            libc_feupdateenv_sparc_ctx +#define libc_feresetround_ctx            libc_feupdateenv_sparc_ctx +#define libc_feresetroundf_ctx           libc_feupdateenv_sparc_ctx +#define libc_feresetroundl_ctx           libc_feupdateenv_sparc_ctx +#define libc_feholdsetround_ctx          libc_feholdsetround_sparc_ctx +#define libc_feholdsetroundf_ctx         libc_feholdsetround_sparc_ctx +#define libc_feholdsetroundl_ctx         libc_feholdsetround_sparc_ctx + +#endif /* SPARC_FENV_PRIVATE_H */ diff --git a/libm/sparc/fesetenv.c b/libm/sparc/fesetenv.c new file mode 100644 index 000000000..d6f3dc5f5 --- /dev/null +++ b/libm/sparc/fesetenv.c @@ -0,0 +1,45 @@ +/* Install given floating-point environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetenv (const fenv_t *envp) +{ +  fenv_t dummy; + +  /* Put these constants in memory explicitly, so as to cope with a +     -fPIC bug as of gcc 970624.  Making them automatic is quicker +     than loading up the pic register in this instance.  */ + +  if (envp == FE_DFL_ENV) +    { +      dummy = 0; +      envp = &dummy; +    } +  else if (envp == FE_NOMASK_ENV) +    { +      dummy = 0x1f << 23; +      envp = &dummy; +    } + +  __fenv_ldfsr (*envp); + +  /* Success.  */ +  return 0; +} diff --git a/libm/sparc/fesetexcept.c b/libm/sparc/fesetexcept.c new file mode 100644 index 000000000..02210b691 --- /dev/null +++ b/libm/sparc/fesetexcept.c @@ -0,0 +1,31 @@ +/* Set given exception flags.  SPARC version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetexcept (int excepts) +{ +  fenv_t tmp; + +  __fenv_stfsr (tmp); +  tmp |= excepts & FE_ALL_EXCEPT; +  __fenv_ldfsr (tmp); + +  return 0; +} diff --git a/libm/sparc/fesetmode.c b/libm/sparc/fesetmode.c new file mode 100644 index 000000000..e72b3d9df --- /dev/null +++ b/libm/sparc/fesetmode.c @@ -0,0 +1,38 @@ +/* Install given floating-point control modes.  SPARC version. +   Copyright (C) 2016-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" +#include <fpu_control.h> + +#define FPU_CONTROL_BITS 0xcfc00000UL + +int +fesetmode (const femode_t *modep) +{ +  femode_t fsr; + +  __fenv_stfsr (fsr); +  fsr &= ~FPU_CONTROL_BITS; +  if (modep == FE_DFL_MODE) +    fsr |= _FPU_DEFAULT; +  else +    fsr |= *modep & FPU_CONTROL_BITS; +  __fenv_ldfsr (fsr); + +  return 0; +} diff --git a/libm/sparc/fesetround.c b/libm/sparc/fesetround.c new file mode 100644 index 000000000..ba3a4e50f --- /dev/null +++ b/libm/sparc/fesetround.c @@ -0,0 +1,36 @@ +/* Set current rounding direction. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fesetround (int round) +{ +  fenv_t tmp; + +  if ((round & ~__FE_ROUND_MASK) != 0) +    /* ROUND is no valid rounding mode.  */ +    return 1; + +  __fenv_stfsr (tmp); +  tmp &= ~__FE_ROUND_MASK; +  tmp |= round; +  __fenv_ldfsr (tmp); + +  return 0; +} diff --git a/libm/sparc/feupdateenv.c b/libm/sparc/feupdateenv.c new file mode 100644 index 000000000..272536cf3 --- /dev/null +++ b/libm/sparc/feupdateenv.c @@ -0,0 +1,40 @@ +/* Install given floating-point environment and raise exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +feupdateenv (const fenv_t *envp) +{ +  fexcept_t tmp; + +  /* Save current exceptions.  */ +  __fenv_stfsr (tmp); +  tmp &= FE_ALL_EXCEPT; + +  /* Install new environment.  */ +  fesetenv (envp); + +  /* Raise the saved exception.  Incidentally for us the implementation +     defined format of the values in objects of type fexcept_t is the +     same as the ones specified using the FE_* constants.  */ +  feraiseexcept ((int) tmp); + +  /* Success.  */ +  return 0; +} diff --git a/libm/sparc/fgetexcptflg.c b/libm/sparc/fgetexcptflg.c new file mode 100644 index 000000000..d8568906e --- /dev/null +++ b/libm/sparc/fgetexcptflg.c @@ -0,0 +1,33 @@ +/* Store current representation for exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ +  fexcept_t tmp; + +  /* Get the current exceptions.  */ +  __fenv_stfsr (tmp); + +  *flagp = tmp & excepts & FE_ALL_EXCEPT; + +  /* Success.  */ +  return 0; +} diff --git a/libm/sparc/fpu_control.h b/libm/sparc/fpu_control.h new file mode 100644 index 000000000..542f9fb1b --- /dev/null +++ b/libm/sparc/fpu_control.h @@ -0,0 +1,75 @@ +/* FPU control word bits.  SPARC version. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H	1 + + +#include <features.h> +#include <bits/wordsize.h> + +/* masking of interrupts */ +#define _FPU_MASK_IM  0x08000000 +#define _FPU_MASK_OM  0x04000000 +#define _FPU_MASK_UM  0x02000000 +#define _FPU_MASK_ZM  0x01000000 +#define _FPU_MASK_PM  0x00800000 + +/* precision control */ +#define _FPU_EXTENDED 0x00000000     /* RECOMMENDED */ +#define _FPU_DOUBLE   0x20000000 +#define _FPU_80BIT    0x30000000 +#define _FPU_SINGLE   0x10000000     /* DO NOT USE */ + +/* rounding control / Sparc */ +#define _FPU_RC_DOWN    0xc0000000 +#define _FPU_RC_UP      0x80000000 +#define _FPU_RC_ZERO    0x40000000 +#define _FPU_RC_NEAREST 0x0        /* RECOMMENDED */ + +#define _FPU_RESERVED   0x303e0000  /* Reserved bits in cw */ + + +/* Now two recommended cw */ + +/* Linux and IEEE default: +     - extended precision +     - rounding to nearest +     - no exceptions  */ +#define _FPU_DEFAULT  0x0 +#define _FPU_IEEE     0x0 + +/* Type of the control word.  */ +typedef unsigned long int fpu_control_t; + +#if __WORDSIZE == 64 +# define _FPU_GETCW(cw) __asm__ __volatile__ ("stx %%fsr,%0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ __volatile__ ("ldx %0,%%fsr" : : "m" (*&cw)) +#else +# ifdef __leon__ +   /* Prevent stfsr from being placed directly after other fp instruction.  */ +#  define _FPU_GETCW(cw) __asm__ __volatile__ ("nop; st %%fsr,%0" : "=m" (*&cw)) +# else +#  define _FPU_GETCW(cw) __asm__ __volatile__ ("st %%fsr,%0" : "=m" (*&cw)) +# endif +# define _FPU_SETCW(cw) __asm__ __volatile__ ("ld %0,%%fsr" : : "m" (*&cw)) +#endif + +/* Default control word set at startup.  */ +extern fpu_control_t __fpu_control; + +#endif	/* fpu_control.h */ diff --git a/libm/sparc/fraiseexcpt.c b/libm/sparc/fraiseexcpt.c new file mode 100644 index 000000000..72e151fe6 --- /dev/null +++ b/libm/sparc/fraiseexcpt.c @@ -0,0 +1,81 @@ +/* Raise given exceptions. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include <float.h> +#include <math.h> +#include "math-barriers.h" + +int +feraiseexcept (int excepts) +{ +  static const struct { +    double zero, one, max, min, pi; +  } c = { +    0.0, 1.0, DBL_MAX, DBL_MIN, M_PI +  }; +  double d; + +  /* Raise exceptions represented by EXPECTS.  But we must raise only +     one signal at a time.  It is important the if the overflow/underflow +     exception and the inexact exception are given at the same time, +     the overflow/underflow exception follows the inexact exception.  */ + +  /* First: invalid exception.  */ +  if ((FE_INVALID & excepts) != 0) +    { +      /* One example of an invalid operation is 0/0.  */ +      __asm__ ("" : "=e" (d) : "0" (c.zero)); +      d /= c.zero; +      math_force_eval (d); +    } + +  /* Next: division by zero.  */ +  if ((FE_DIVBYZERO & excepts) != 0) +    { +      __asm__ ("" : "=e" (d) : "0" (c.one)); +      d /= c.zero; +      math_force_eval (d); +    } + +  /* Next: overflow.  */ +  if ((FE_OVERFLOW & excepts) != 0) +    { +      __asm__ ("" : "=e" (d) : "0" (c.max)); +      d *= d; +      math_force_eval (d); +    } + +  /* Next: underflow.  */ +  if ((FE_UNDERFLOW & excepts) != 0) +    { +      __asm__ ("" : "=e" (d) : "0" (c.min)); +      d *= d; +      math_force_eval (d); +    } + +  /* Last: inexact.  */ +  if ((FE_INEXACT & excepts) != 0) +    { +      __asm__ ("" : "=e" (d) : "0" (c.one)); +      d /= c.pi; +      math_force_eval (d); +    } + +  /* Success.  */ +  return 0; +} diff --git a/libm/sparc/fsetexcptflg.c b/libm/sparc/fsetexcptflg.c new file mode 100644 index 000000000..4b3b6ae68 --- /dev/null +++ b/libm/sparc/fsetexcptflg.c @@ -0,0 +1,36 @@ +/* Set floating-point environment exception handling. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" +#include <math.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ +  fenv_t tmp; + +  __fenv_stfsr (tmp); + +  tmp &= ~(excepts & FE_ALL_EXCEPT); +  tmp |= *flagp & excepts & FE_ALL_EXCEPT; + +  __fenv_ldfsr (tmp); + +  /* Success.  */ +  return 0; +} diff --git a/libm/sparc/ftestexcept.c b/libm/sparc/ftestexcept.c new file mode 100644 index 000000000..1fe87bb36 --- /dev/null +++ b/libm/sparc/ftestexcept.c @@ -0,0 +1,29 @@ +/* Test exception in current environment. +   Copyright (C) 1997-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#include <fenv.h> +#include "fenv_private.h" + +int +fetestexcept (int excepts) +{ +  fenv_t tmp; + +  __fenv_stfsr (tmp); + +  return tmp & excepts & FE_ALL_EXCEPT; +} diff --git a/libm/sparc/math-barriers.h b/libm/sparc/math-barriers.h new file mode 100644 index 000000000..4b02ff47b --- /dev/null +++ b/libm/sparc/math-barriers.h @@ -0,0 +1,36 @@ +/* Control when floating-point expressions are evaluated.  Generic version. +   Copyright (C) 2007-2025 Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <https://www.gnu.org/licenses/>.  */ + +#ifndef _MATH_BARRIERS_H +#define _MATH_BARRIERS_H	1 + +/* math_opt_barrier evaluates and returns its floating-point argument +   and ensures that the evaluation of any expression using the result +   of math_opt_barrier is not moved before the call.  math_force_eval +   ensures that its floating-point argument is evaluated for its side +   effects even if its value is apparently unused, and that the +   evaluation of its argument is not moved after the call.  Both these +   macros are used to ensure the correct ordering of floating-point +   expression evaluations with respect to accesses to the +   floating-point environment.  */ + +#define math_opt_barrier(x)					\ +  ({ __typeof (x) __x = (x); __asm ("" : "+m" (__x)); __x; }) +#define math_force_eval(x)						\ +  ({ __typeof (x) __x = (x); __asm __volatile__ ("" : : "m" (__x)); }) + +#endif /* math-barriers.h */ diff --git a/libm/w_cabs.c b/libm/w_cabs.c index b2592484c..546b6affa 100644 --- a/libm/w_cabs.c +++ b/libm/w_cabs.c @@ -17,7 +17,7 @@ libm_hidden_def(cabs)  libm_hidden_proto(cabsf)  float cabsf(float _Complex z)  { -	return (float) hypot(__real__ z, __imag__ z); +	return (float) hypot((double)__real__ z, (double)__imag__ z);  }  libm_hidden_def(cabsf) diff --git a/libm/w_j0f.c b/libm/w_j0f.c index 89821bc98..496e098cd 100644 --- a/libm/w_j0f.c +++ b/libm/w_j0f.c @@ -63,6 +63,6 @@ y0f (float x)  	return __kernel_standard_f (x, x, 135);      }  # endif /* __UCLIBC_HAS_FENV__ */ -  return (float) __ieee754_y0f ((double) x); +  return (float) __ieee754_y0 ((double) x);  }  #endif /* __DO_XSI_MATH__ */ | 
