(root)/
glibc-2.38/
sysdeps/
csky/
fpu/
fenv_private.h
       1  /* Private floating point rounding and exceptions handling.  C-SKY version.
       2     Copyright (C) 2018-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 CSKY_FENV_PRIVATE_H
      20  #define CSKY_FENV_PRIVATE_H 1
      21  
      22  #include <fenv.h>
      23  #include <fpu_control.h>
      24  #include <fenv_libc.h>
      25  
      26  static __always_inline void
      27  libc_feholdexcept_vfp (fenv_t *envp)
      28  {
      29    fpu_control_t fpsr, fpcr;
      30  
      31    _FPU_GETCW (fpcr);
      32    envp->__fpcr = fpcr;
      33  
      34    _FPU_GETFPSR (fpsr);
      35    envp->__fpsr = fpsr;
      36  
      37    /* Now set all exceptions to non-stop.  */
      38    fpcr &= ~FE_ALL_EXCEPT;
      39  
      40    /* And clear all exception flags.  */
      41    fpsr &= ~(FE_ALL_EXCEPT << CAUSE_SHIFT);
      42  
      43    _FPU_SETFPSR (fpsr);
      44  
      45    _FPU_SETCW (fpcr);
      46  }
      47  
      48  static __always_inline void
      49  libc_fesetround_vfp (int round)
      50  {
      51    fpu_control_t fpcr;
      52  
      53    _FPU_GETCW (fpcr);
      54  
      55    /* Set new rounding mode if different.  */
      56    if (__glibc_unlikely ((fpcr & FE_DOWNWARD) != round))
      57      _FPU_SETCW ((fpcr & ~FE_DOWNWARD) | round);
      58  }
      59  
      60  static __always_inline void
      61  libc_feholdexcept_setround_vfp (fenv_t *envp, int round)
      62  {
      63    fpu_control_t fpsr, fpcr;
      64  
      65    _FPU_GETCW (fpcr);
      66    envp->__fpcr = fpcr;
      67  
      68    _FPU_GETFPSR (fpsr);
      69    envp->__fpsr = fpsr;
      70  
      71    /* Clear exception flags, set all exceptions to non-stop,
      72       and set new rounding mode.  */
      73    fpsr &= ~(FE_ALL_EXCEPT << CAUSE_SHIFT);
      74    _FPU_SETFPSR (fpsr);
      75  
      76    fpcr &= ~(FE_ALL_EXCEPT | FE_DOWNWARD);
      77    _FPU_SETCW (fpcr | round);
      78  }
      79  
      80  static __always_inline void
      81  libc_feholdsetround_vfp (fenv_t *envp, int round)
      82  {
      83    fpu_control_t fpcr;
      84  
      85    _FPU_GETCW (fpcr);
      86    envp->__fpcr = fpcr;
      87  
      88    /* Set new rounding mode if different.  */
      89    if (__glibc_unlikely ((fpcr & FE_DOWNWARD) != round))
      90      _FPU_SETCW ((fpcr & ~FE_DOWNWARD) | round);
      91  }
      92  
      93  static __always_inline void
      94  libc_feresetround_vfp (fenv_t *envp)
      95  {
      96    fpu_control_t fpcr, round;
      97  
      98    _FPU_GETCW (fpcr);
      99  
     100    /* Check whether rounding modes are different.  */
     101    round = (envp->__fpcr ^ fpcr) & FE_DOWNWARD;
     102  
     103    /* Restore the rounding mode if it was changed.  */
     104    if (__glibc_unlikely (round != 0))
     105      _FPU_SETCW (fpcr ^ round);
     106  }
     107  
     108  static __always_inline int
     109  libc_fetestexcept_vfp (int ex)
     110  {
     111    fpu_control_t fpsr;
     112  
     113    _FPU_GETFPSR (fpsr);
     114    fpsr = fpsr >> CAUSE_SHIFT;
     115    return fpsr & ex & FE_ALL_EXCEPT;
     116  }
     117  
     118  static __always_inline void
     119  libc_fesetenv_vfp (const fenv_t *envp)
     120  {
     121    fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr;
     122  
     123    _FPU_GETCW (fpcr);
     124    _FPU_GETFPSR (fpsr);
     125  
     126    new_fpcr = envp->__fpcr;
     127    new_fpsr = envp->__fpsr;
     128  
     129    if (__glibc_unlikely (fpsr ^ new_fpsr) != 0)
     130      _FPU_SETFPSR (new_fpsr);
     131  
     132    if (__glibc_unlikely (fpcr ^ new_fpcr) != 0)
     133      _FPU_SETCW (new_fpcr);
     134  }
     135  
     136  static __always_inline int
     137  libc_feupdateenv_test_vfp (const fenv_t *envp, int ex)
     138  {
     139    fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr, excepts;
     140  
     141    _FPU_GETCW (fpcr);
     142    _FPU_GETFPSR (fpsr);
     143  
     144    /* Merge current exception flags with the saved fenv.  */
     145    excepts = (fpsr >> CAUSE_SHIFT) & FE_ALL_EXCEPT;
     146    new_fpcr = envp->__fpcr;
     147    new_fpsr = envp->__fpsr | (excepts << CAUSE_SHIFT);
     148  
     149    /* Write FCR and FESR if different.  */
     150    if (__glibc_unlikely (fpsr ^ new_fpsr) != 0)
     151      _FPU_SETFPSR (new_fpsr);
     152  
     153    if (__glibc_unlikely (fpcr ^ new_fpcr) != 0)
     154      _FPU_SETCW (new_fpcr);
     155  
     156    /* Raise the exceptions if enabled in the new FP state.  */
     157    if (__glibc_unlikely (excepts & new_fpcr))
     158      __feraiseexcept (excepts);
     159  
     160    return excepts & ex;
     161  }
     162  
     163  static __always_inline void
     164  libc_feupdateenv_vfp (const fenv_t *envp)
     165  {
     166    libc_feupdateenv_test_vfp (envp, 0);
     167  }
     168  
     169  static __always_inline void
     170  libc_feholdsetround_vfp_ctx (struct rm_ctx *ctx, int r)
     171  {
     172    fpu_control_t fpcr, fpsr, round;
     173  
     174    _FPU_GETCW (fpcr);
     175    _FPU_GETFPSR (fpsr);
     176    ctx->updated_status = false;
     177    ctx->env.__fpcr = fpcr;
     178    ctx->env.__fpsr = fpsr;
     179  
     180    /* Check whether rounding modes are different.  */
     181    round = (fpcr ^ r) & FE_DOWNWARD;
     182  
     183    /* Set the rounding mode if changed.  */
     184    if (__glibc_unlikely (round != 0))
     185      {
     186        ctx->updated_status = true;
     187        _FPU_SETCW (fpcr ^ round);
     188      }
     189  }
     190  
     191  static __always_inline void
     192  libc_feresetround_vfp_ctx (struct rm_ctx *ctx)
     193  {
     194    /* Restore the rounding mode if updated.  */
     195    if (__glibc_unlikely (ctx->updated_status))
     196      {
     197        fpu_control_t fpcr;
     198  
     199        _FPU_GETCW (fpcr);
     200        fpcr = (fpcr & ~FE_DOWNWARD) | (ctx->env.__fpcr & FE_DOWNWARD);
     201        _FPU_SETCW (fpcr);
     202      }
     203  }
     204  
     205  static __always_inline void
     206  libc_fesetenv_vfp_ctx (struct rm_ctx *ctx)
     207  {
     208    fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr;
     209  
     210    _FPU_GETCW (fpcr);
     211    _FPU_GETFPSR (fpsr);
     212  
     213    new_fpcr = ctx->env.__fpcr;
     214    new_fpsr = ctx->env.__fpsr;
     215  
     216    if (__glibc_unlikely (fpsr ^ new_fpsr) != 0)
     217      _FPU_SETFPSR (new_fpsr);
     218  
     219    if (__glibc_unlikely (fpcr ^ new_fpcr) != 0)
     220      _FPU_SETCW (new_fpcr);
     221  }
     222  
     223  #define libc_feholdexcept  libc_feholdexcept_vfp
     224  #define libc_feholdexceptf libc_feholdexcept_vfp
     225  #define libc_feholdexceptl libc_feholdexcept_vfp
     226  
     227  #define libc_fesetround  libc_fesetround_vfp
     228  #define libc_fesetroundf libc_fesetround_vfp
     229  #define libc_fesetroundl libc_fesetround_vfp
     230  
     231  #define libc_feresetround  libc_feresetround_vfp
     232  #define libc_feresetroundf libc_feresetround_vfp
     233  #define libc_feresetroundl libc_feresetround_vfp
     234  
     235  #define libc_feresetround_noex  libc_fesetenv_vfp
     236  #define libc_feresetround_noexf libc_fesetenv_vfp
     237  #define libc_feresetround_noexl libc_fesetenv_vfp
     238  
     239  #define libc_feholdexcept_setround  libc_feholdexcept_setround_vfp
     240  #define libc_feholdexcept_setroundf libc_feholdexcept_setround_vfp
     241  #define libc_feholdexcept_setroundl libc_feholdexcept_setround_vfp
     242  
     243  #define libc_feholdsetround  libc_feholdsetround_vfp
     244  #define libc_feholdsetroundf libc_feholdsetround_vfp
     245  #define libc_feholdsetroundl libc_feholdsetround_vfp
     246  
     247  #define libc_fetestexcept  libc_fetestexcept_vfp
     248  #define libc_fetestexceptf libc_fetestexcept_vfp
     249  #define libc_fetestexceptl libc_fetestexcept_vfp
     250  
     251  #define libc_fesetenv  libc_fesetenv_vfp
     252  #define libc_fesetenvf libc_fesetenv_vfp
     253  #define libc_fesetenvl libc_fesetenv_vfp
     254  
     255  #define libc_feupdateenv  libc_feupdateenv_vfp
     256  #define libc_feupdateenvf libc_feupdateenv_vfp
     257  #define libc_feupdateenvl libc_feupdateenv_vfp
     258  
     259  #define libc_feupdateenv_test  libc_feupdateenv_test_vfp
     260  #define libc_feupdateenv_testf libc_feupdateenv_test_vfp
     261  #define libc_feupdateenv_testl libc_feupdateenv_test_vfp
     262  
     263  /* We have support for rounding mode context.  */
     264  #define HAVE_RM_CTX 1
     265  
     266  #define libc_feholdsetround_ctx		libc_feholdsetround_vfp_ctx
     267  #define libc_feresetround_ctx		libc_feresetround_vfp_ctx
     268  #define libc_feresetround_noex_ctx	libc_fesetenv_vfp_ctx
     269  
     270  #define libc_feholdsetroundf_ctx	libc_feholdsetround_vfp_ctx
     271  #define libc_feresetroundf_ctx		libc_feresetround_vfp_ctx
     272  #define libc_feresetround_noexf_ctx	libc_fesetenv_vfp_ctx
     273  
     274  #define libc_feholdsetroundl_ctx	libc_feholdsetround_vfp_ctx
     275  #define libc_feresetroundl_ctx		libc_feresetround_vfp_ctx
     276  #define libc_feresetround_noexl_ctx	libc_fesetenv_vfp_ctx
     277  
     278  #include_next <fenv_private.h>
     279  
     280  #endif /* CSKY_FENV_PRIVATE_H */