1b7d84476Sscole /*- 2b7d84476Sscole * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 3b7d84476Sscole * All rights reserved. 4b7d84476Sscole * 5b7d84476Sscole * Redistribution and use in source and binary forms, with or without 6b7d84476Sscole * modification, are permitted provided that the following conditions 7b7d84476Sscole * are met: 8b7d84476Sscole * 1. Redistributions of source code must retain the above copyright 9b7d84476Sscole * notice, this list of conditions and the following disclaimer. 10b7d84476Sscole * 2. Redistributions in binary form must reproduce the above copyright 11b7d84476Sscole * notice, this list of conditions and the following disclaimer in the 12b7d84476Sscole * documentation and/or other materials provided with the distribution. 13b7d84476Sscole * 14b7d84476Sscole * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15b7d84476Sscole * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16b7d84476Sscole * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17b7d84476Sscole * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18b7d84476Sscole * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19b7d84476Sscole * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20b7d84476Sscole * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21b7d84476Sscole * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22b7d84476Sscole * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23b7d84476Sscole * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24b7d84476Sscole * SUCH DAMAGE. 25b7d84476Sscole * 26b7d84476Sscole * $FreeBSD: releng/10.1/lib/msun/ia64/fenv.h 226218 2011-10-10 15:43:09Z das $ 27b7d84476Sscole */ 28b7d84476Sscole 29b7d84476Sscole #ifndef _IA64_FENV_H_ 30b7d84476Sscole #define _IA64_FENV_H_ 31b7d84476Sscole 32*cddc78eaSriastradh #include <sys/featuretest.h> 33b7d84476Sscole #include <sys/stdint.h> 34b7d84476Sscole 35b7d84476Sscole #ifndef __fenv_static 36b7d84476Sscole #define __fenv_static static 37b7d84476Sscole #endif 38b7d84476Sscole 39b7d84476Sscole typedef __uint64_t fenv_t; 40b7d84476Sscole typedef __uint16_t fexcept_t; 41b7d84476Sscole 42b7d84476Sscole /* Exception flags */ 43b7d84476Sscole #define FE_INVALID 0x01 44b7d84476Sscole #define FE_DENORMAL 0x02 45b7d84476Sscole #define FE_DIVBYZERO 0x04 46b7d84476Sscole #define FE_OVERFLOW 0x08 47b7d84476Sscole #define FE_UNDERFLOW 0x10 48b7d84476Sscole #define FE_INEXACT 0x20 49b7d84476Sscole #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \ 50b7d84476Sscole FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 51b7d84476Sscole 52b7d84476Sscole /* Rounding modes */ 53b7d84476Sscole #define FE_TONEAREST 0x0000 54b7d84476Sscole #define FE_DOWNWARD 0x0400 55b7d84476Sscole #define FE_UPWARD 0x0800 56b7d84476Sscole #define FE_TOWARDZERO 0x0c00 57b7d84476Sscole #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 58b7d84476Sscole FE_UPWARD | FE_TOWARDZERO) 59b7d84476Sscole 60b7d84476Sscole __BEGIN_DECLS 61b7d84476Sscole 62b7d84476Sscole /* Default floating-point environment */ 63b7d84476Sscole extern const fenv_t __fe_dfl_env; 64b7d84476Sscole #define FE_DFL_ENV (&__fe_dfl_env) 65b7d84476Sscole 66b7d84476Sscole #define _FPUSW_SHIFT 13 67b7d84476Sscole 68b7d84476Sscole #define __stfpsr(__r) __asm __volatile("mov %0=ar.fpsr" : "=r" (*(__r))) 69b7d84476Sscole #define __ldfpsr(__r) __asm __volatile("mov ar.fpsr=%0;;" : : "r" (__r)) 70b7d84476Sscole 7177fc877fSmrg #if __GNUC_PREREQ__(8, 0) 7277fc877fSmrg #pragma GCC diagnostic push 7377fc877fSmrg #pragma GCC diagnostic ignored "-Wshadow" 7477fc877fSmrg #endif 7577fc877fSmrg 76b7d84476Sscole __fenv_static inline int 77b7d84476Sscole feclearexcept(int __excepts) 78b7d84476Sscole { 79b7d84476Sscole fenv_t __fpsr; 80b7d84476Sscole 81b7d84476Sscole __stfpsr(&__fpsr); 82b7d84476Sscole __fpsr &= ~((fenv_t)__excepts << _FPUSW_SHIFT); 83b7d84476Sscole __ldfpsr(__fpsr); 84b7d84476Sscole return (0); 85b7d84476Sscole } 86b7d84476Sscole 87b7d84476Sscole __fenv_static inline int 88b7d84476Sscole fegetexceptflag(fexcept_t *__flagp, int __excepts) 89b7d84476Sscole { 90b7d84476Sscole fenv_t __fpsr; 91b7d84476Sscole 92b7d84476Sscole __stfpsr(&__fpsr); 93b7d84476Sscole *__flagp = (fexcept_t)(__fpsr >> _FPUSW_SHIFT) & __excepts; 94b7d84476Sscole return (0); 95b7d84476Sscole } 96b7d84476Sscole 97b7d84476Sscole __fenv_static inline int 98b7d84476Sscole fesetexceptflag(const fexcept_t *__flagp, int __excepts) 99b7d84476Sscole { 100b7d84476Sscole fenv_t __fpsr; 101b7d84476Sscole 102b7d84476Sscole __stfpsr(&__fpsr); 103b7d84476Sscole __fpsr &= ~((fenv_t)__excepts << _FPUSW_SHIFT); 104b7d84476Sscole __fpsr |= (fenv_t)(__excepts & *__flagp) << _FPUSW_SHIFT; 105b7d84476Sscole __ldfpsr(__fpsr); 106b7d84476Sscole return (0); 107b7d84476Sscole } 108b7d84476Sscole 109b7d84476Sscole /* 110b7d84476Sscole * It is worthwhile to use the inline version of this function iff it 111b7d84476Sscole * is called with arguments that are compile-time constants (due to 112b7d84476Sscole * dead code elimination). Unfortunately, gcc isn't smart enough to 113b7d84476Sscole * figure this out automatically, and there's no way to tell it. 114b7d84476Sscole * We assume that constant arguments will be the common case. 115b7d84476Sscole */ 116b7d84476Sscole __fenv_static inline int 117b7d84476Sscole feraiseexcept(int __excepts) 118b7d84476Sscole { 119b7d84476Sscole volatile double d; 120b7d84476Sscole 121b7d84476Sscole /* 122b7d84476Sscole * With a compiler that supports the FENV_ACCESS pragma 123b7d84476Sscole * properly, simple expressions like '0.0 / 0.0' should 124b7d84476Sscole * be sufficient to generate traps. Unfortunately, we 125b7d84476Sscole * need to bring a volatile variable into the equation 126b7d84476Sscole * to prevent incorrect optimizations. 127b7d84476Sscole */ 128b7d84476Sscole if (__excepts & FE_INVALID) { 129b7d84476Sscole d = 0.0; 130b7d84476Sscole d = 0.0 / d; 131b7d84476Sscole } 132b7d84476Sscole if (__excepts & FE_DIVBYZERO) { 133b7d84476Sscole d = 0.0; 134b7d84476Sscole d = 1.0 / d; 135b7d84476Sscole } 136b7d84476Sscole if (__excepts & FE_OVERFLOW) { 137b7d84476Sscole d = 0x1.ffp1023; 138b7d84476Sscole d *= 2.0; 139b7d84476Sscole } 140b7d84476Sscole if (__excepts & FE_UNDERFLOW) { 141b7d84476Sscole d = 0x1p-1022; 142b7d84476Sscole d /= 0x1p1023; 143b7d84476Sscole } 144b7d84476Sscole if (__excepts & FE_INEXACT) { 145b7d84476Sscole d = 0x1p-1022; 146b7d84476Sscole d += 1.0; 147b7d84476Sscole } 148b7d84476Sscole return (0); 149b7d84476Sscole } 150b7d84476Sscole 151b7d84476Sscole __fenv_static inline int 152b7d84476Sscole fetestexcept(int __excepts) 153b7d84476Sscole { 154b7d84476Sscole fenv_t __fpsr; 155b7d84476Sscole 156b7d84476Sscole __stfpsr(&__fpsr); 157b7d84476Sscole return ((__fpsr >> _FPUSW_SHIFT) & __excepts); 158b7d84476Sscole } 159b7d84476Sscole 160b7d84476Sscole 161b7d84476Sscole __fenv_static inline int 162b7d84476Sscole fegetround(void) 163b7d84476Sscole { 164b7d84476Sscole fenv_t __fpsr; 165b7d84476Sscole 166b7d84476Sscole __stfpsr(&__fpsr); 167b7d84476Sscole return (__fpsr & _ROUND_MASK); 168b7d84476Sscole } 169b7d84476Sscole 170b7d84476Sscole __fenv_static inline int 171b7d84476Sscole fesetround(int __round) 172b7d84476Sscole { 173b7d84476Sscole fenv_t __fpsr; 174b7d84476Sscole 175b7d84476Sscole if (__round & ~_ROUND_MASK) 176b7d84476Sscole return (-1); 177b7d84476Sscole __stfpsr(&__fpsr); 178b7d84476Sscole __fpsr &= ~_ROUND_MASK; 179b7d84476Sscole __fpsr |= __round; 180b7d84476Sscole __ldfpsr(__fpsr); 181b7d84476Sscole return (0); 182b7d84476Sscole } 183b7d84476Sscole 184b7d84476Sscole __fenv_static inline int 185b7d84476Sscole fegetenv(fenv_t *__envp) 186b7d84476Sscole { 187b7d84476Sscole 188b7d84476Sscole __stfpsr(__envp); 189b7d84476Sscole return (0); 190b7d84476Sscole } 191b7d84476Sscole 192b7d84476Sscole __fenv_static inline int 193b7d84476Sscole feholdexcept(fenv_t *__envp) 194b7d84476Sscole { 195b7d84476Sscole fenv_t __fpsr; 196b7d84476Sscole 197b7d84476Sscole __stfpsr(&__fpsr); 198b7d84476Sscole *__envp = __fpsr; 199b7d84476Sscole __fpsr &= ~((fenv_t)FE_ALL_EXCEPT << _FPUSW_SHIFT); 200b7d84476Sscole __fpsr |= FE_ALL_EXCEPT; 201b7d84476Sscole __ldfpsr(__fpsr); 202b7d84476Sscole return (0); 203b7d84476Sscole } 204b7d84476Sscole 205b7d84476Sscole __fenv_static inline int 206b7d84476Sscole fesetenv(const fenv_t *__envp) 207b7d84476Sscole { 208b7d84476Sscole 209b7d84476Sscole __ldfpsr(*__envp); 210b7d84476Sscole return (0); 211b7d84476Sscole } 212b7d84476Sscole 213b7d84476Sscole int feupdateenv(const fenv_t *__envp); 214b7d84476Sscole 21577fc877fSmrg #if __GNUC_PREREQ__(8, 0) 21677fc877fSmrg #pragma GCC diagnostic pop 21777fc877fSmrg #endif 21877fc877fSmrg 219b7d84476Sscole #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE) 220b7d84476Sscole 221c853a494Schs __fenv_static inline int 222b7d84476Sscole feenableexcept(int __mask) 223b7d84476Sscole { 224b7d84476Sscole fenv_t __newfpsr, __oldfpsr; 225b7d84476Sscole 226b7d84476Sscole __stfpsr(&__oldfpsr); 227b7d84476Sscole __newfpsr = __oldfpsr & ~(__mask & FE_ALL_EXCEPT); 228b7d84476Sscole __ldfpsr(__newfpsr); 229b7d84476Sscole return (~__oldfpsr & FE_ALL_EXCEPT); 230b7d84476Sscole } 231b7d84476Sscole 232c853a494Schs __fenv_static inline int 233b7d84476Sscole fedisableexcept(int __mask) 234b7d84476Sscole { 235b7d84476Sscole fenv_t __newfpsr, __oldfpsr; 236b7d84476Sscole 237b7d84476Sscole __stfpsr(&__oldfpsr); 238b7d84476Sscole __newfpsr = __oldfpsr | (__mask & FE_ALL_EXCEPT); 239b7d84476Sscole __ldfpsr(__newfpsr); 240b7d84476Sscole return (~__oldfpsr & FE_ALL_EXCEPT); 241b7d84476Sscole } 242b7d84476Sscole 243c853a494Schs __fenv_static inline int 244b7d84476Sscole fegetexcept(void) 245b7d84476Sscole { 246b7d84476Sscole fenv_t __fpsr; 247b7d84476Sscole 248b7d84476Sscole __stfpsr(&__fpsr); 249b7d84476Sscole return (~__fpsr & FE_ALL_EXCEPT); 250b7d84476Sscole } 251b7d84476Sscole 252b7d84476Sscole #endif /* _NETBSD_SOURCE || _GNU_SOURCE */ 253b7d84476Sscole 254b7d84476Sscole __END_DECLS 255b7d84476Sscole 256b7d84476Sscole #endif /* !_IA64_FENV_H_ */ 257