diff options
Diffstat (limited to 'libm/arm')
| -rw-r--r-- | libm/arm/Makefile.arch | 16 | ||||
| -rw-r--r-- | libm/arm/arm-features.h | 58 | ||||
| -rw-r--r-- | libm/arm/fclrexcpt.c | 41 | ||||
| -rw-r--r-- | libm/arm/fedisblxcpt.c | 41 | ||||
| -rw-r--r-- | libm/arm/feenablxcpt.c | 49 | ||||
| -rw-r--r-- | libm/arm/fegetenv.c | 35 | ||||
| -rw-r--r-- | libm/arm/fegetexcept.c | 35 | ||||
| -rw-r--r-- | libm/arm/fegetmode.c | 28 | ||||
| -rw-r--r-- | libm/arm/fegetround.c | 42 | ||||
| -rw-r--r-- | libm/arm/feholdexcpt.c | 31 | ||||
| -rw-r--r-- | libm/arm/fenv_private.h | 248 | ||||
| -rw-r--r-- | libm/arm/fesetenv.c | 62 | ||||
| -rw-r--r-- | libm/arm/fesetexcept.c | 37 | ||||
| -rw-r--r-- | libm/arm/fesetmode.c | 44 | ||||
| -rw-r--r-- | libm/arm/fesetround.c | 35 | ||||
| -rw-r--r-- | libm/arm/feupdateenv.c | 73 | ||||
| -rw-r--r-- | libm/arm/fgetexcptflg.c | 31 | ||||
| -rw-r--r-- | libm/arm/fraiseexcpt.c | 103 | ||||
| -rw-r--r-- | libm/arm/fsetexcptflg.c | 44 | ||||
| -rw-r--r-- | libm/arm/ftestexcept.c | 30 | 
20 files changed, 1083 insertions, 0 deletions
| 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); +} | 
