(root)/
glibc-2.38/
sysdeps/
arm/
fenv_private.h
       1  /* Private floating point rounding and exceptions handling.  ARM VFP version.
       2     Copyright (C) 2014-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library.  If not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef ARM_FENV_PRIVATE_H
      20  #define ARM_FENV_PRIVATE_H 1
      21  
      22  #include <fenv.h>
      23  #include <fpu_control.h>
      24  
      25  static __always_inline void
      26  libc_feholdexcept_vfp (fenv_t *envp)
      27  {
      28    fpu_control_t fpscr;
      29  
      30    _FPU_GETCW (fpscr);
      31    envp->__cw = fpscr;
      32  
      33    /* Clear exception flags and set all exceptions to non-stop.  */
      34    fpscr &= ~_FPU_MASK_EXCEPT;
      35    _FPU_SETCW (fpscr);
      36  }
      37  
      38  static __always_inline void
      39  libc_fesetround_vfp (int round)
      40  {
      41    fpu_control_t fpscr;
      42  
      43    _FPU_GETCW (fpscr);
      44  
      45    /* Set new rounding mode if different.  */
      46    if (__glibc_unlikely ((fpscr & _FPU_MASK_RM) != round))
      47      _FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round);
      48  }
      49  
      50  static __always_inline void
      51  libc_feholdexcept_setround_vfp (fenv_t *envp, int round)
      52  {
      53    fpu_control_t fpscr;
      54  
      55    _FPU_GETCW (fpscr);
      56    envp->__cw = fpscr;
      57  
      58    /* Clear exception flags, set all exceptions to non-stop,
      59       and set new rounding mode.  */
      60    fpscr &= ~(_FPU_MASK_EXCEPT | _FPU_MASK_RM);
      61    _FPU_SETCW (fpscr | round);
      62  }
      63  
      64  static __always_inline void
      65  libc_feholdsetround_vfp (fenv_t *envp, int round)
      66  {
      67    fpu_control_t fpscr;
      68  
      69    _FPU_GETCW (fpscr);
      70    envp->__cw = fpscr;
      71  
      72    /* Set new rounding mode if different.  */
      73    if (__glibc_unlikely ((fpscr & _FPU_MASK_RM) != round))
      74      _FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round);
      75  }
      76  
      77  static __always_inline void
      78  libc_feresetround_vfp (fenv_t *envp)
      79  {
      80    fpu_control_t fpscr, round;
      81  
      82    _FPU_GETCW (fpscr);
      83  
      84    /* Check whether rounding modes are different.  */
      85    round = (envp->__cw ^ fpscr) & _FPU_MASK_RM;
      86  
      87    /* Restore the rounding mode if it was changed.  */
      88    if (__glibc_unlikely (round != 0))
      89      _FPU_SETCW (fpscr ^ round);
      90  }
      91  
      92  static __always_inline int
      93  libc_fetestexcept_vfp (int ex)
      94  {
      95    fpu_control_t fpscr;
      96  
      97    _FPU_GETCW (fpscr);
      98    return fpscr & ex & FE_ALL_EXCEPT;
      99  }
     100  
     101  static __always_inline void
     102  libc_fesetenv_vfp (const fenv_t *envp)
     103  {
     104    fpu_control_t fpscr, new_fpscr;
     105  
     106    _FPU_GETCW (fpscr);
     107    new_fpscr = envp->__cw;
     108  
     109    /* Write new FPSCR if different (ignoring NZCV flags).  */
     110    if (__glibc_unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0))
     111      _FPU_SETCW (new_fpscr);
     112  }
     113  
     114  static __always_inline int
     115  libc_feupdateenv_test_vfp (const fenv_t *envp, int ex)
     116  {
     117    fpu_control_t fpscr, new_fpscr;
     118    int excepts;
     119  
     120    _FPU_GETCW (fpscr);
     121  
     122    /* Merge current exception flags with the saved fenv.  */
     123    excepts = fpscr & FE_ALL_EXCEPT;
     124    new_fpscr = envp->__cw | excepts;
     125  
     126    /* Write new FPSCR if different (ignoring NZCV flags).  */
     127    if (__glibc_unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0))
     128      _FPU_SETCW (new_fpscr);
     129  
     130    /* Raise the exceptions if enabled in the new FP state.  */
     131    if (__glibc_unlikely (excepts & (new_fpscr >> FE_EXCEPT_SHIFT)))
     132      __feraiseexcept (excepts);
     133  
     134    return excepts & ex;
     135  }
     136  
     137  static __always_inline void
     138  libc_feupdateenv_vfp (const fenv_t *envp)
     139  {
     140    libc_feupdateenv_test_vfp (envp, 0);
     141  }
     142  
     143  static __always_inline void
     144  libc_feholdsetround_vfp_ctx (struct rm_ctx *ctx, int r)
     145  {
     146    fpu_control_t fpscr, round;
     147  
     148    _FPU_GETCW (fpscr);
     149    ctx->updated_status = false;
     150    ctx->env.__cw = fpscr;
     151  
     152    /* Check whether rounding modes are different.  */
     153    round = (fpscr ^ r) & _FPU_MASK_RM;
     154  
     155    /* Set the rounding mode if changed.  */
     156    if (__glibc_unlikely (round != 0))
     157      {
     158        ctx->updated_status = true;
     159        _FPU_SETCW (fpscr ^ round);
     160      }
     161  }
     162  
     163  static __always_inline void
     164  libc_feresetround_vfp_ctx (struct rm_ctx *ctx)
     165  {
     166    /* Restore the rounding mode if updated.  */
     167    if (__glibc_unlikely (ctx->updated_status))
     168      {
     169        fpu_control_t fpscr;
     170  
     171        _FPU_GETCW (fpscr);
     172        fpscr = (fpscr & ~_FPU_MASK_RM) | (ctx->env.__cw & _FPU_MASK_RM);
     173        _FPU_SETCW (fpscr);
     174      }
     175  }
     176  
     177  static __always_inline void
     178  libc_fesetenv_vfp_ctx (struct rm_ctx *ctx)
     179  {
     180    fpu_control_t fpscr, new_fpscr;
     181  
     182    _FPU_GETCW (fpscr);
     183    new_fpscr = ctx->env.__cw;
     184  
     185    /* Write new FPSCR if different (ignoring NZCV flags).  */
     186    if (__glibc_unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0))
     187      _FPU_SETCW (new_fpscr);
     188  }
     189  
     190  #ifndef __SOFTFP__
     191  
     192  # define libc_feholdexcept  libc_feholdexcept_vfp
     193  # define libc_feholdexceptf libc_feholdexcept_vfp
     194  # define libc_feholdexceptl libc_feholdexcept_vfp
     195  
     196  # define libc_fesetround  libc_fesetround_vfp
     197  # define libc_fesetroundf libc_fesetround_vfp
     198  # define libc_fesetroundl libc_fesetround_vfp
     199  
     200  # define libc_feresetround  libc_feresetround_vfp
     201  # define libc_feresetroundf libc_feresetround_vfp
     202  # define libc_feresetroundl libc_feresetround_vfp
     203  
     204  # define libc_feresetround_noex  libc_fesetenv_vfp
     205  # define libc_feresetround_noexf libc_fesetenv_vfp
     206  # define libc_feresetround_noexl libc_fesetenv_vfp
     207  
     208  # define libc_feholdexcept_setround  libc_feholdexcept_setround_vfp
     209  # define libc_feholdexcept_setroundf libc_feholdexcept_setround_vfp
     210  # define libc_feholdexcept_setroundl libc_feholdexcept_setround_vfp
     211  
     212  # define libc_feholdsetround  libc_feholdsetround_vfp
     213  # define libc_feholdsetroundf libc_feholdsetround_vfp
     214  # define libc_feholdsetroundl libc_feholdsetround_vfp
     215  
     216  # define libc_fetestexcept  libc_fetestexcept_vfp
     217  # define libc_fetestexceptf libc_fetestexcept_vfp
     218  # define libc_fetestexceptl libc_fetestexcept_vfp
     219  
     220  # define libc_fesetenv  libc_fesetenv_vfp
     221  # define libc_fesetenvf libc_fesetenv_vfp
     222  # define libc_fesetenvl libc_fesetenv_vfp
     223  
     224  # define libc_feupdateenv  libc_feupdateenv_vfp
     225  # define libc_feupdateenvf libc_feupdateenv_vfp
     226  # define libc_feupdateenvl libc_feupdateenv_vfp
     227  
     228  # define libc_feupdateenv_test  libc_feupdateenv_test_vfp
     229  # define libc_feupdateenv_testf libc_feupdateenv_test_vfp
     230  # define libc_feupdateenv_testl libc_feupdateenv_test_vfp
     231  
     232  /* We have support for rounding mode context.  */
     233  #define HAVE_RM_CTX 1
     234  
     235  # define libc_feholdsetround_ctx	libc_feholdsetround_vfp_ctx
     236  # define libc_feresetround_ctx		libc_feresetround_vfp_ctx
     237  # define libc_feresetround_noex_ctx	libc_fesetenv_vfp_ctx
     238  
     239  # define libc_feholdsetroundf_ctx	libc_feholdsetround_vfp_ctx
     240  # define libc_feresetroundf_ctx		libc_feresetround_vfp_ctx
     241  # define libc_feresetround_noexf_ctx	libc_fesetenv_vfp_ctx
     242  
     243  # define libc_feholdsetroundl_ctx	libc_feholdsetround_vfp_ctx
     244  # define libc_feresetroundl_ctx		libc_feresetround_vfp_ctx
     245  # define libc_feresetround_noexl_ctx	libc_fesetenv_vfp_ctx
     246  
     247  #endif
     248  
     249  #include_next <fenv_private.h>
     250  
     251  #endif /* ARM_FENV_PRIVATE_H */