Blame sysdeps/powerpc/fpu/fenv_libc.h

Packit Service 82fcde
/* Internal libc stuff for floating point environment routines.
Packit Service 82fcde
   Copyright (C) 1997-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#ifndef _FENV_LIBC_H
Packit Service 82fcde
#define _FENV_LIBC_H	1
Packit Service 82fcde
Packit Service 82fcde
#include <fenv.h>
Packit Service 82fcde
#include <ldsodefs.h>
Packit Service 82fcde
#include <sysdep.h>
Packit Service 82fcde
Packit Service 82fcde
extern const fenv_t *__fe_nomask_env_priv (void);
Packit Service 82fcde
Packit Service 82fcde
extern const fenv_t *__fe_mask_env (void) attribute_hidden;
Packit Service 82fcde
Packit Service 82fcde
/* The sticky bits in the FPSCR indicating exceptions have occurred.  */
Packit Service 82fcde
#define FPSCR_STICKY_BITS ((FE_ALL_EXCEPT | FE_ALL_INVALID) & ~FE_INVALID)
Packit Service 82fcde
Packit Service 82fcde
/* Equivalent to fegetenv, but returns a fenv_t instead of taking a
Packit Service 82fcde
   pointer.  */
Packit Service 82fcde
#define fegetenv_register() \
Packit Service 82fcde
        ({ fenv_t env; asm volatile ("mffs %0" : "=f" (env)); env; })
Packit Service 82fcde
Packit Service 54974d
/* Equivalent to fegetenv_register, but only returns bits for
Packit Service 8739ee
   status, exception enables, and mode.
Packit Service 8739ee
   Nicely, it turns out that the 'mffsl' instruction will decode to
Packit Service 8739ee
   'mffs' on architectures older than "power9" because the additional
Packit Service 8739ee
   bits set for 'mffsl' are "don't care" for 'mffs'.  'mffs' is a superset
Packit Service 8739ee
   of 'mffsl'.  */
Packit Service 8739ee
#define fegetenv_status()					\
Packit Service 54974d
  ({register double __fr;						\
Packit Service 54974d
    __asm__ __volatile__ (						\
Packit Service 54974d
      ".machine push; .machine \"power9\"; mffsl %0; .machine pop"	\
Packit Service 54974d
      : "=f" (__fr));							\
Packit Service 54974d
    __fr;								\
Packit Service 54974d
  })
Packit Service 54974d
Packit Service 82fcde
/* Equivalent to fesetenv, but takes a fenv_t instead of a pointer.  */
Packit Service 82fcde
#define fesetenv_register(env) \
Packit Service 82fcde
	do { \
Packit Service 82fcde
	  double d = (env); \
Packit Service 82fcde
	  if(GLRO(dl_hwcap) & PPC_FEATURE_HAS_DFP) \
Packit Service 82fcde
	    asm volatile (".machine push; " \
Packit Service 82fcde
			  ".machine \"power6\"; " \
Packit Service 82fcde
			  "mtfsf 0xff,%0,1,0; " \
Packit Service 82fcde
			  ".machine pop" : : "f" (d)); \
Packit Service 82fcde
	  else \
Packit Service 82fcde
	    asm volatile ("mtfsf 0xff,%0" : : "f" (d)); \
Packit Service 82fcde
	} while(0)
Packit Service 82fcde
Packit Service f7885b
/* Set the last 2 nibbles of the FPSCR, which contain the
Packit Service f7885b
   exception enables and the rounding mode.
Packit Service f7885b
   'fegetenv_status' retrieves these bits by reading the FPSCR.  */
Packit Service f7885b
#define fesetenv_mode(env) __builtin_mtfsf (0b00000011, (env));
Packit Service f7885b
Packit Service 82fcde
/* This very handy macro:
Packit Service 82fcde
   - Sets the rounding mode to 'round to nearest';
Packit Service 82fcde
   - Sets the processor into IEEE mode; and
Packit Service 82fcde
   - Prevents exceptions from being raised for inexact results.
Packit Service 82fcde
   These things happen to be exactly what you need for typical elementary
Packit Service 82fcde
   functions.  */
Packit Service 82fcde
#define relax_fenv_state() \
Packit Service 82fcde
	do { \
Packit Service 82fcde
	   if (GLRO(dl_hwcap) & PPC_FEATURE_HAS_DFP) \
Packit Service 70e79f
	     asm volatile (".machine push; .machine \"power6\"; " \
Packit Service 82fcde
		  "mtfsfi 7,0,1; .machine pop"); \
Packit Service 70e79f
	   asm volatile ("mtfsfi 7,0"); \
Packit Service 82fcde
	} while(0)
Packit Service 82fcde
Packit Service 82fcde
/* Set/clear a particular FPSCR bit (for instance,
Packit Service 82fcde
   reset_fpscr_bit(FPSCR_VE);
Packit Service 82fcde
   prevents INVALID exceptions from being raised).  */
Packit Service 82fcde
#define set_fpscr_bit(x) asm volatile ("mtfsb1 %0" : : "i"(x))
Packit Service 82fcde
#define reset_fpscr_bit(x) asm volatile ("mtfsb0 %0" : : "i"(x))
Packit Service 82fcde
Packit Service 82fcde
typedef union
Packit Service 82fcde
{
Packit Service 82fcde
  fenv_t fenv;
Packit Service 82fcde
  unsigned long long l;
Packit Service 82fcde
} fenv_union_t;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static inline int
Packit Service 82fcde
__fesetround_inline (int round)
Packit Service 82fcde
{
Packit Service 82fcde
  if ((unsigned int) round < 2)
Packit Service 82fcde
    {
Packit Service 82fcde
       asm volatile ("mtfsb0 30");
Packit Service 82fcde
       if ((unsigned int) round == 0)
Packit Service 82fcde
         asm volatile ("mtfsb0 31");
Packit Service 82fcde
       else
Packit Service 82fcde
         asm volatile ("mtfsb1 31");
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
       asm volatile ("mtfsb1 30");
Packit Service 82fcde
       if ((unsigned int) round == 2)
Packit Service 82fcde
         asm volatile ("mtfsb0 31");
Packit Service 82fcde
       else
Packit Service 82fcde
         asm volatile ("mtfsb1 31");
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 840927
/* Same as __fesetround_inline, however without runtime check to use DFP
Packit Service 840927
   mtfsfi syntax (as relax_fenv_state) or if round value is valid.  */
Packit Service 840927
static inline void
Packit Service 840927
__fesetround_inline_nocheck (const int round)
Packit Service 840927
{
Packit Service 840927
  asm volatile ("mtfsfi 7,%0" : : "i" (round));
Packit Service 840927
}
Packit Service 840927
Packit Service a343c1
#define FPSCR_MASK(bit) (1 << (31 - (bit)))
Packit Service a343c1
Packit Service 82fcde
/* Definitions of all the FPSCR bit numbers */
Packit Service 82fcde
enum {
Packit Service 82fcde
  FPSCR_FX = 0,    /* exception summary */
Packit Service a343c1
#define FPSCR_FX_MASK (FPSCR_MASK (FPSCR_FX))
Packit Service 82fcde
  FPSCR_FEX,       /* enabled exception summary */
Packit Service a343c1
#define FPSCR_FEX_MASK (FPSCR_MASK FPSCR_FEX))
Packit Service 82fcde
  FPSCR_VX,        /* invalid operation summary */
Packit Service a343c1
#define FPSCR_VX_MASK (FPSCR_MASK (FPSCR_VX))
Packit Service 82fcde
  FPSCR_OX,        /* overflow */
Packit Service a343c1
#define FPSCR_OX_MASK (FPSCR_MASK (FPSCR_OX))
Packit Service 82fcde
  FPSCR_UX,        /* underflow */
Packit Service a343c1
#define FPSCR_UX_MASK (FPSCR_MASK (FPSCR_UX))
Packit Service 82fcde
  FPSCR_ZX,        /* zero divide */
Packit Service a343c1
#define FPSCR_ZX_MASK (FPSCR_MASK (FPSCR_ZX))
Packit Service 82fcde
  FPSCR_XX,        /* inexact */
Packit Service a343c1
#define FPSCR_XX_MASK (FPSCR_MASK (FPSCR_XX))
Packit Service 82fcde
  FPSCR_VXSNAN,    /* invalid operation for sNaN */
Packit Service a343c1
#define FPSCR_VXSNAN_MASK (FPSCR_MASK (FPSCR_VXSNAN))
Packit Service 82fcde
  FPSCR_VXISI,     /* invalid operation for Inf-Inf */
Packit Service a343c1
#define FPSCR_VXISI_MASK (FPSCR_MASK (FPSCR_VXISI))
Packit Service 82fcde
  FPSCR_VXIDI,     /* invalid operation for Inf/Inf */
Packit Service a343c1
#define FPSCR_VXIDI_MASK (FPSCR_MASK (FPSCR_VXIDI))
Packit Service 82fcde
  FPSCR_VXZDZ,     /* invalid operation for 0/0 */
Packit Service a343c1
#define FPSCR_VXZDZ_MASK (FPSCR_MASK (FPSCR_VXZDZ))
Packit Service 82fcde
  FPSCR_VXIMZ,     /* invalid operation for Inf*0 */
Packit Service a343c1
#define FPSCR_VXIMZ_MASK (FPSCR_MASK (FPSCR_VXIMZ))
Packit Service 82fcde
  FPSCR_VXVC,      /* invalid operation for invalid compare */
Packit Service a343c1
#define FPSCR_VXVC_MASK (FPSCR_MASK (FPSCR_VXVC))
Packit Service 82fcde
  FPSCR_FR,        /* fraction rounded [fraction was incremented by round] */
Packit Service a343c1
#define FPSCR_FR_MASK (FPSCR_MASK (FPSCR_FR))
Packit Service 82fcde
  FPSCR_FI,        /* fraction inexact */
Packit Service a343c1
#define FPSCR_FI_MASK (FPSCR_MASK (FPSCR_FI))
Packit Service 82fcde
  FPSCR_FPRF_C,    /* result class descriptor */
Packit Service a343c1
#define FPSCR_FPRF_C_MASK (FPSCR_MASK (FPSCR_FPRF_C))
Packit Service 82fcde
  FPSCR_FPRF_FL,   /* result less than (usually, less than 0) */
Packit Service a343c1
#define FPSCR_FPRF_FL_MASK (FPSCR_MASK (FPSCR_FPRF_FL))
Packit Service 82fcde
  FPSCR_FPRF_FG,   /* result greater than */
Packit Service a343c1
#define FPSCR_FPRF_FG_MASK (FPSCR_MASK (FPSCR_FPRF_FG))
Packit Service 82fcde
  FPSCR_FPRF_FE,   /* result equal to */
Packit Service a343c1
#define FPSCR_FPRF_FE_MASK (FPSCR_MASK (FPSCR_FPRF_FE))
Packit Service 82fcde
  FPSCR_FPRF_FU,   /* result unordered */
Packit Service a343c1
#define FPSCR_FPRF_FU_MASK (FPSCR_MASK (FPSCR_FPRF_FU))
Packit Service 82fcde
  FPSCR_20,        /* reserved */
Packit Service 82fcde
  FPSCR_VXSOFT,    /* invalid operation set by software */
Packit Service a343c1
#define FPSCR_VXSOFT_MASK (FPSCR_MASK (FPSCR_VXSOFT))
Packit Service 82fcde
  FPSCR_VXSQRT,    /* invalid operation for square root */
Packit Service a343c1
#define FPSCR_VXSQRT_MASK (FPSCR_MASK (FPSCR_VXSQRT))
Packit Service 82fcde
  FPSCR_VXCVI,     /* invalid operation for invalid integer convert */
Packit Service a343c1
#define FPSCR_VXCVI_MASK (FPSCR_MASK (FPSCR_VXCVI))
Packit Service 82fcde
  FPSCR_VE,        /* invalid operation exception enable */
Packit Service a343c1
#define FPSCR_VE_MASK (FPSCR_MASK (FPSCR_VE))
Packit Service 82fcde
  FPSCR_OE,        /* overflow exception enable */
Packit Service a343c1
#define FPSCR_OE_MASK (FPSCR_MASK (FPSCR_OE))
Packit Service 82fcde
  FPSCR_UE,        /* underflow exception enable */
Packit Service a343c1
#define FPSCR_UE_MASK (FPSCR_MASK (FPSCR_UE))
Packit Service 82fcde
  FPSCR_ZE,        /* zero divide exception enable */
Packit Service a343c1
#define FPSCR_ZE_MASK (FPSCR_MASK (FPSCR_ZE))
Packit Service 82fcde
  FPSCR_XE,        /* inexact exception enable */
Packit Service a343c1
#define FPSCR_XE_MASK (FPSCR_MASK (FPSCR_XE))
Packit Service 82fcde
#ifdef _ARCH_PWR6
Packit Service 82fcde
  FPSCR_29,        /* Reserved in ISA 2.05  */
Packit Service a343c1
#define FPSCR_NI_MASK (FPSCR_MASK (FPSCR_29))
Packit Service 82fcde
#else
Packit Service a343c1
  FPSCR_NI,        /* non-IEEE mode (typically, no denormalised numbers) */
Packit Service a343c1
#define FPSCR_NI_MASK (FPSCR_MASK (FPSCR_NI))
Packit Service 82fcde
#endif /* _ARCH_PWR6 */
Packit Service 82fcde
  /* the remaining two least-significant bits keep the rounding mode */
Packit Service a343c1
  FPSCR_RN_hi,
Packit Service a343c1
#define FPSCR_RN_hi_MASK (FPSCR_MASK (FPSCR_RN_hi))
Packit Service a343c1
  FPSCR_RN_lo
Packit Service a343c1
#define FPSCR_RN_lo_MASK (FPSCR_MASK (FPSCR_RN_lo))
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service a343c1
#define FPSCR_RN_MASK (FPSCR_RN_hi_MASK|FPSCR_RN_lo_MASK)
Packit Service a343c1
#define FPSCR_ENABLES_MASK \
Packit Service a343c1
  (FPSCR_VE_MASK|FPSCR_OE_MASK|FPSCR_UE_MASK|FPSCR_ZE_MASK|FPSCR_XE_MASK)
Packit Service a343c1
#define FPSCR_BASIC_EXCEPTIONS_MASK \
Packit Service a343c1
  (FPSCR_VX_MASK|FPSCR_OX_MASK|FPSCR_UX_MASK|FPSCR_ZX_MASK|FPSCR_XX_MASK)
Packit Service f7885b
#define FPSCR_FPRF_MASK \
Packit Service f7885b
  (FPSCR_FPRF_C_MASK|FPSCR_FPRF_FL_MASK|FPSCR_FPRF_FG_MASK| \
Packit Service f7885b
   FPSCR_FPRF_FE_MASK|FPSCR_FPRF_FU_MASK)
Packit Service a343c1
#define FPSCR_CONTROL_MASK (FPSCR_ENABLES_MASK|FPSCR_NI_MASK|FPSCR_RN_MASK)
Packit Service f7885b
#define FPSCR_STATUS_MASK (FPSCR_FR_MASK|FPSCR_FI_MASK|FPSCR_FPRF_MASK)
Packit Service a343c1
Packit Service a343c1
/* The bits in the FENV(1) ABI for exceptions correspond one-to-one with bits
Packit Service a343c1
   in the FPSCR, albeit shifted to different but corresponding locations.
Packit Service a343c1
   Similarly, the exception indicator bits in the FPSCR correspond one-to-one
Packit Service a343c1
   with the exception enable bits. It is thus possible to map the FENV(1)
Packit Service a343c1
   exceptions directly to the FPSCR enables with a simple mask and shift,
Packit Service a343c1
   and vice versa. */
Packit Service a343c1
#define FPSCR_EXCEPT_TO_ENABLE_SHIFT 22
Packit Service a343c1
Packit Service 82fcde
static inline int
Packit Service 82fcde
fenv_reg_to_exceptions (unsigned long long l)
Packit Service 82fcde
{
Packit Service a343c1
  return (((int)l) & FPSCR_ENABLES_MASK) << FPSCR_EXCEPT_TO_ENABLE_SHIFT;
Packit Service a343c1
}
Packit Service a343c1
Packit Service a343c1
static inline unsigned long long
Packit Service a343c1
fenv_exceptions_to_reg (int excepts)
Packit Service a343c1
{
Packit Service a343c1
  return (unsigned long long)
Packit Service a343c1
    (excepts & FE_ALL_EXCEPT) >> FPSCR_EXCEPT_TO_ENABLE_SHIFT;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#ifdef _ARCH_PWR6
Packit Service 82fcde
  /* Not supported in ISA 2.05.  Provided for source compat only.  */
Packit Service 82fcde
# define FPSCR_NI 29
Packit Service 82fcde
#endif /* _ARCH_PWR6 */
Packit Service 82fcde
Packit Service 82fcde
/* This operation (i) sets the appropriate FPSCR bits for its
Packit Service 82fcde
   parameter, (ii) converts sNaN to the corresponding qNaN, and (iii)
Packit Service 82fcde
   otherwise passes its parameter through unchanged (in particular, -0
Packit Service 82fcde
   and +0 stay as they were).  The `obvious' way to do this is optimised
Packit Service 82fcde
   out by gcc.  */
Packit Service 82fcde
#define f_wash(x) \
Packit Service 82fcde
   ({ double d; asm volatile ("fmul %0,%1,%2" \
Packit Service 82fcde
			      : "=f"(d) \
Packit Service 82fcde
			      : "f" (x), "f"((float)1.0)); d; })
Packit Service 82fcde
#define f_washf(x) \
Packit Service 82fcde
   ({ float f; asm volatile ("fmuls %0,%1,%2" \
Packit Service 82fcde
			     : "=f"(f) \
Packit Service 82fcde
			     : "f" (x), "f"((float)1.0)); f; })
Packit Service 82fcde
Packit Service 82fcde
#endif /* fenv_libc.h */