diff options
Diffstat (limited to 'libm/aarch64')
| -rw-r--r-- | libm/aarch64/Makefile.arch | 16 | ||||
| -rw-r--r-- | libm/aarch64/fclrexcpt.c | 35 | ||||
| -rw-r--r-- | libm/aarch64/fedisblxcpt.c | 34 | ||||
| -rw-r--r-- | libm/aarch64/feenablxcpt.c | 45 | ||||
| -rw-r--r-- | libm/aarch64/fegetenv.c | 30 | ||||
| -rw-r--r-- | libm/aarch64/fegetexcept.c | 26 | ||||
| -rw-r--r-- | libm/aarch64/fegetmode.c | 26 | ||||
| -rw-r--r-- | libm/aarch64/fegetround.c | 35 | ||||
| -rw-r--r-- | libm/aarch64/feholdexcpt.c | 25 | ||||
| -rw-r--r-- | libm/aarch64/fenv_private.h | 300 | ||||
| -rw-r--r-- | libm/aarch64/fesetenv.c | 73 | ||||
| -rw-r--r-- | libm/aarch64/fesetexcept.c | 33 | ||||
| -rw-r--r-- | libm/aarch64/fesetmode.c | 33 | ||||
| -rw-r--r-- | libm/aarch64/fesetround.c | 29 | ||||
| -rw-r--r-- | libm/aarch64/feupdateenv.c | 84 | ||||
| -rw-r--r-- | libm/aarch64/fgetexcptflg.c | 25 | ||||
| -rw-r--r-- | libm/aarch64/fraiseexcpt.c | 89 | ||||
| -rw-r--r-- | libm/aarch64/fsetexcptflg.c | 39 | ||||
| -rw-r--r-- | libm/aarch64/ftestexcept.c | 24 | 
19 files changed, 1001 insertions, 0 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); +} | 
