(root)/
glibc-2.38/
sysdeps/
riscv/
rvf/
fenv_private.h
       1  /* Private floating point rounding and exceptions handling.  RISC-V 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 RISCV_FENV_PRIVATE_H
      20  #define RISCV_FENV_PRIVATE_H 1
      21  
      22  #include <fenv.h>
      23  #include <fpu_control.h>
      24  #include <get-rounding-mode.h>
      25  
      26  static __always_inline int
      27  riscv_getround (void)
      28  {
      29    return get_rounding_mode ();
      30  }
      31  
      32  static __always_inline void
      33  riscv_setround (int rm)
      34  {
      35    asm volatile ("fsrm %z0" : : "rJ" (rm));
      36  }
      37  
      38  static __always_inline int
      39  riscv_getflags (void)
      40  {
      41    int flags;
      42    asm volatile ("frflags %0" : "=r" (flags));
      43    return flags;
      44  }
      45  
      46  static __always_inline void
      47  riscv_setflags (int flags)
      48  {
      49    asm volatile ("fsflags %z0" : : "rJ" (flags));
      50  }
      51  
      52  static __always_inline void
      53  libc_feholdexcept_riscv (fenv_t *envp)
      54  {
      55    asm volatile ("csrrc %0, fcsr, %1" : "=r" (*envp) : "i" (FE_ALL_EXCEPT));
      56  }
      57  
      58  #define libc_feholdexcept  libc_feholdexcept_riscv
      59  #define libc_feholdexceptf libc_feholdexcept_riscv
      60  #define libc_feholdexceptl libc_feholdexcept_riscv
      61  
      62  static __always_inline void
      63  libc_fesetround_riscv (int round)
      64  {
      65    riscv_setround (round);
      66  }
      67  
      68  #define libc_fesetround  libc_fesetround_riscv
      69  #define libc_fesetroundf libc_fesetround_riscv
      70  #define libc_fesetroundl libc_fesetround_riscv
      71  
      72  static __always_inline void
      73  libc_feholdexcept_setround_riscv (fenv_t *envp, int round)
      74  {
      75    libc_feholdexcept_riscv (envp);
      76    libc_fesetround_riscv (round);
      77  }
      78  
      79  #define libc_feholdexcept_setround  libc_feholdexcept_setround_riscv
      80  #define libc_feholdexcept_setroundf libc_feholdexcept_setround_riscv
      81  #define libc_feholdexcept_setroundl libc_feholdexcept_setround_riscv
      82  
      83  static __always_inline int
      84  libc_fetestexcept_riscv (int ex)
      85  {
      86    return riscv_getflags () & ex;
      87  }
      88  
      89  #define libc_fetestexcept  libc_fetestexcept_riscv
      90  #define libc_fetestexceptf libc_fetestexcept_riscv
      91  #define libc_fetestexceptl libc_fetestexcept_riscv
      92  
      93  static __always_inline void
      94  libc_fesetenv_riscv (const fenv_t *envp)
      95  {
      96    long int env = (long int) envp - (long int) FE_DFL_ENV;
      97    if (env != 0)
      98      env = *envp;
      99  
     100    _FPU_SETCW (env);
     101  }
     102  
     103  #define libc_fesetenv  libc_fesetenv_riscv
     104  #define libc_fesetenvf libc_fesetenv_riscv
     105  #define libc_fesetenvl libc_fesetenv_riscv
     106  #define libc_feresetround_noex  libc_fesetenv_riscv
     107  #define libc_feresetround_noexf libc_fesetenv_riscv
     108  #define libc_feresetround_noexl libc_fesetenv_riscv
     109  
     110  static __always_inline int
     111  libc_feupdateenv_test_riscv (const fenv_t *envp, int ex)
     112  {
     113    fenv_t env = *envp;
     114    int flags = riscv_getflags ();
     115    asm volatile ("csrw fcsr, %z0" : : "rJ" (env | flags));
     116    return flags & ex;
     117  }
     118  
     119  #define libc_feupdateenv_test  libc_feupdateenv_test_riscv
     120  #define libc_feupdateenv_testf libc_feupdateenv_test_riscv
     121  #define libc_feupdateenv_testl libc_feupdateenv_test_riscv
     122  
     123  static __always_inline void
     124  libc_feupdateenv_riscv (const fenv_t *envp)
     125  {
     126    _FPU_SETCW (*envp | riscv_getflags ());
     127  }
     128  
     129  #define libc_feupdateenv  libc_feupdateenv_riscv
     130  #define libc_feupdateenvf libc_feupdateenv_riscv
     131  #define libc_feupdateenvl libc_feupdateenv_riscv
     132  
     133  static __always_inline void
     134  libc_feholdsetround_riscv (fenv_t *envp, int round)
     135  {
     136    /* Note this implementation makes an improperly-formatted fenv_t and
     137       so should only be used in conjunction with libc_feresetround.  */
     138    int old_round;
     139    asm volatile ("csrrw %0, frm, %z1" : "=r" (old_round) : "rJ" (round));
     140    *envp = old_round;
     141  }
     142  
     143  #define libc_feholdsetround  libc_feholdsetround_riscv
     144  #define libc_feholdsetroundf libc_feholdsetround_riscv
     145  #define libc_feholdsetroundl libc_feholdsetround_riscv
     146  
     147  static __always_inline void
     148  libc_feresetround_riscv (fenv_t *envp)
     149  {
     150    /* Note this implementation takes an improperly-formatted fenv_t and
     151       so should only be used in conjunction with libc_feholdsetround.  */
     152    riscv_setround (*envp);
     153  }
     154  
     155  #define libc_feresetround  libc_feresetround_riscv
     156  #define libc_feresetroundf libc_feresetround_riscv
     157  #define libc_feresetroundl libc_feresetround_riscv
     158  
     159  #include_next <fenv_private.h>
     160  
     161  #endif