Blame sysdeps/unix/sysv/linux/alpha/setfpucw.c

Packit 6c4009
/* Set FP exception mask and rounding mode.
Packit 6c4009
   Copyright (C) 1996-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
#include <fpu_control.h>
Packit 6c4009
#include <fenv_libc.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
#define convert_bit(M, F, T)		\
Packit 6c4009
    ((T) < (F)				\
Packit 6c4009
     ? ((M) / ((F) / (T))) & (T)	\
Packit 6c4009
     : ((M) & (F)) * ((T) / (F)))
Packit 6c4009
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
__setfpucw (fpu_control_t fpu_control)
Packit 6c4009
{
Packit 6c4009
  unsigned long fpcr, swcr, fc = (int)fpu_control;
Packit 6c4009
Packit 6c4009
  /* ??? If this was a real external interface we'd want to read the current
Packit 6c4009
     exception state with __ieee_get_fp_control.  But this is an internal
Packit 6c4009
     function only called at process startup, so there's no point in trying
Packit 6c4009
     to preserve exceptions that cannot have been raised yet.  Indeed, this
Packit 6c4009
     entire function is likely to be one big nop unless the user overrides
Packit 6c4009
     the default __fpu_control variable.  */
Packit 6c4009
Packit 6c4009
  /* Convert the rounding mode from fpu_control.h format.  */
Packit 6c4009
  const unsigned long conv_rnd
Packit 6c4009
    = (  (FE_TOWARDZERO << (_FPU_RC_ZERO >> 8))
Packit 6c4009
       | (FE_DOWNWARD << (_FPU_RC_DOWN >> 8))
Packit 6c4009
       | (FE_TONEAREST << (_FPU_RC_NEAREST >> 8))
Packit 6c4009
       | (FE_UPWARD << (_FPU_RC_UP >> 8)));
Packit 6c4009
Packit 6c4009
  fpcr = ((conv_rnd >> ((fc >> 8) & 3)) & 3) << FPCR_ROUND_SHIFT;
Packit 6c4009
Packit 6c4009
  /* Convert the exception mask from fpu_control.h format.  */
Packit 6c4009
  swcr  = convert_bit (~fc, _FPU_MASK_IM, FE_INVALID >> SWCR_ENABLE_SHIFT);
Packit 6c4009
  swcr |= convert_bit (~fc, _FPU_MASK_DM, FE_UNDERFLOW >> SWCR_ENABLE_SHIFT);
Packit 6c4009
  swcr |= convert_bit (~fc, _FPU_MASK_ZM, FE_DIVBYZERO >> SWCR_ENABLE_SHIFT);
Packit 6c4009
  swcr |= convert_bit (~fc, _FPU_MASK_OM, FE_OVERFLOW >> SWCR_ENABLE_SHIFT);
Packit 6c4009
  swcr |= convert_bit (~fc, _FPU_MASK_PM, FE_INEXACT >> SWCR_ENABLE_SHIFT);
Packit 6c4009
Packit 6c4009
  /* Install everything.  */
Packit 6c4009
  __fpu_control = fc;
Packit 6c4009
  asm volatile ("mt_fpcr %0" : : "f"(fpcr));
Packit 6c4009
  __ieee_set_fp_control(swcr);
Packit 6c4009
}