Blame sysdeps/riscv/rvf/math_private.h

Packit 6c4009
/* Private floating point rounding and exceptions handling.  RISC-V version.
Packit 6c4009
   Copyright (C) 2014-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#ifndef RISCV_MATH_PRIVATE_H
Packit 6c4009
#define RISCV_MATH_PRIVATE_H 1
Packit 6c4009
Packit 6c4009
#include <fenv.h>
Packit 6c4009
#include <fpu_control.h>
Packit 6c4009
#include <get-rounding-mode.h>
Packit 6c4009
Packit 6c4009
static __always_inline int
Packit 6c4009
riscv_getround (void)
Packit 6c4009
{
Packit 6c4009
  return get_rounding_mode ();
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static __always_inline void
Packit 6c4009
riscv_setround (int rm)
Packit 6c4009
{
Packit 6c4009
  asm volatile ("fsrm %z0" : : "rJ" (rm));
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static __always_inline int
Packit 6c4009
riscv_getflags (void)
Packit 6c4009
{
Packit 6c4009
  int flags;
Packit 6c4009
  asm volatile ("frflags %0" : "=r" (flags));
Packit 6c4009
  return flags;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static __always_inline void
Packit 6c4009
riscv_setflags (int flags)
Packit 6c4009
{
Packit 6c4009
  asm volatile ("fsflags %z0" : : "rJ" (flags));
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static __always_inline void
Packit 6c4009
libc_feholdexcept_riscv (fenv_t *envp)
Packit 6c4009
{
Packit 6c4009
  asm volatile ("csrrc %0, fcsr, %1" : "=r" (*envp) : "i" (FE_ALL_EXCEPT));
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define libc_feholdexcept  libc_feholdexcept_riscv
Packit 6c4009
#define libc_feholdexceptf libc_feholdexcept_riscv
Packit 6c4009
#define libc_feholdexceptl libc_feholdexcept_riscv
Packit 6c4009
Packit 6c4009
static __always_inline void
Packit 6c4009
libc_fesetround_riscv (int round)
Packit 6c4009
{
Packit 6c4009
  riscv_setround (round);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define libc_fesetround  libc_fesetround_riscv
Packit 6c4009
#define libc_fesetroundf libc_fesetround_riscv
Packit 6c4009
#define libc_fesetroundl libc_fesetround_riscv
Packit 6c4009
Packit 6c4009
static __always_inline void
Packit 6c4009
libc_feholdexcept_setround_riscv (fenv_t *envp, int round)
Packit 6c4009
{
Packit 6c4009
  libc_fesetround_riscv (round);
Packit 6c4009
  libc_feholdexcept_riscv (envp);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define libc_feholdexcept_setround  libc_feholdexcept_setround_riscv
Packit 6c4009
#define libc_feholdexcept_setroundf libc_feholdexcept_setround_riscv
Packit 6c4009
#define libc_feholdexcept_setroundl libc_feholdexcept_setround_riscv
Packit 6c4009
Packit 6c4009
static __always_inline int
Packit 6c4009
libc_fetestexcept_riscv (int ex)
Packit 6c4009
{
Packit 6c4009
  return riscv_getflags () & ex;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define libc_fetestexcept  libc_fetestexcept_riscv
Packit 6c4009
#define libc_fetestexceptf libc_fetestexcept_riscv
Packit 6c4009
#define libc_fetestexceptl libc_fetestexcept_riscv
Packit 6c4009
Packit 6c4009
static __always_inline void
Packit 6c4009
libc_fesetenv_riscv (const fenv_t *envp)
Packit 6c4009
{
Packit 6c4009
  long int env = (long int) envp - (long int) FE_DFL_ENV;
Packit 6c4009
  if (env != 0)
Packit 6c4009
    env = *envp;
Packit 6c4009
Packit 6c4009
  _FPU_SETCW (env);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define libc_fesetenv  libc_fesetenv_riscv
Packit 6c4009
#define libc_fesetenvf libc_fesetenv_riscv
Packit 6c4009
#define libc_fesetenvl libc_fesetenv_riscv
Packit 6c4009
#define libc_feresetround_noex  libc_fesetenv_riscv
Packit 6c4009
#define libc_feresetround_noexf libc_fesetenv_riscv
Packit 6c4009
#define libc_feresetround_noexl libc_fesetenv_riscv
Packit 6c4009
Packit 6c4009
static __always_inline int
Packit 6c4009
libc_feupdateenv_test_riscv (const fenv_t *envp, int ex)
Packit 6c4009
{
Packit 6c4009
  fenv_t env = *envp;
Packit 6c4009
  int flags = riscv_getflags ();
Packit 6c4009
  asm volatile ("csrw fcsr, %z0" : : "rJ" (env | flags));
Packit 6c4009
  return flags & ex;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define libc_feupdateenv_test  libc_feupdateenv_test_riscv
Packit 6c4009
#define libc_feupdateenv_testf libc_feupdateenv_test_riscv
Packit 6c4009
#define libc_feupdateenv_testl libc_feupdateenv_test_riscv
Packit 6c4009
Packit 6c4009
static __always_inline void
Packit 6c4009
libc_feupdateenv_riscv (const fenv_t *envp)
Packit 6c4009
{
Packit 6c4009
  _FPU_SETCW (*envp | riscv_getflags ());
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define libc_feupdateenv  libc_feupdateenv_riscv
Packit 6c4009
#define libc_feupdateenvf libc_feupdateenv_riscv
Packit 6c4009
#define libc_feupdateenvl libc_feupdateenv_riscv
Packit 6c4009
Packit 6c4009
static __always_inline void
Packit 6c4009
libc_feholdsetround_riscv (fenv_t *envp, int round)
Packit 6c4009
{
Packit 6c4009
  /* Note this implementation makes an improperly-formatted fenv_t and
Packit 6c4009
     so should only be used in conjunction with libc_feresetround.  */
Packit 6c4009
  int old_round;
Packit 6c4009
  asm volatile ("csrrw %0, frm, %z1" : "=r" (old_round) : "rJ" (round));
Packit 6c4009
  *envp = old_round;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define libc_feholdsetround  libc_feholdsetround_riscv
Packit 6c4009
#define libc_feholdsetroundf libc_feholdsetround_riscv
Packit 6c4009
#define libc_feholdsetroundl libc_feholdsetround_riscv
Packit 6c4009
Packit 6c4009
static __always_inline void
Packit 6c4009
libc_feresetround_riscv (fenv_t *envp)
Packit 6c4009
{
Packit 6c4009
  /* Note this implementation takes an improperly-formatted fenv_t and
Packit 6c4009
     so should only be used in conjunction with libc_feholdsetround.  */
Packit 6c4009
  riscv_setround (*envp);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define libc_feresetround  libc_feresetround_riscv
Packit 6c4009
#define libc_feresetroundf libc_feresetround_riscv
Packit 6c4009
#define libc_feresetroundl libc_feresetround_riscv
Packit 6c4009
Packit 6c4009
#include_next <math_private.h>
Packit 6c4009
Packit 6c4009
#endif