1*cddc78eaSriastradh /* $NetBSD: fenv.h,v 1.4 2024/10/30 15:56:10 riastradh Exp $ */ 2253d8526Schristos 3253d8526Schristos /*- 4253d8526Schristos * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 5253d8526Schristos * All rights reserved. 6253d8526Schristos * 7253d8526Schristos * Redistribution and use in source and binary forms, with or without 8253d8526Schristos * modification, are permitted provided that the following conditions 9253d8526Schristos * are met: 10253d8526Schristos * 1. Redistributions of source code must retain the above copyright 11253d8526Schristos * notice, this list of conditions and the following disclaimer. 12253d8526Schristos * 2. Redistributions in binary form must reproduce the above copyright 13253d8526Schristos * notice, this list of conditions and the following disclaimer in the 14253d8526Schristos * documentation and/or other materials provided with the distribution. 15253d8526Schristos * 16253d8526Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17253d8526Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18253d8526Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19253d8526Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20253d8526Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21253d8526Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22253d8526Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23253d8526Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24253d8526Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25253d8526Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26253d8526Schristos * SUCH DAMAGE. 27253d8526Schristos * 28253d8526Schristos * $FreeBSD: src/lib/msun/alpha/fenv.h,v 1.3 2005/03/16 19:03:44 das Exp $ 29253d8526Schristos */ 30253d8526Schristos 31253d8526Schristos #ifndef _ALPHA_FENV_H_ 32253d8526Schristos #define _ALPHA_FENV_H_ 33253d8526Schristos 34*cddc78eaSriastradh #include <sys/featuretest.h> 35253d8526Schristos #include <sys/stdint.h> 36253d8526Schristos 37253d8526Schristos typedef __uint64_t fenv_t; 38253d8526Schristos typedef __uint16_t fexcept_t; 39253d8526Schristos 40253d8526Schristos /* Exception flags */ 41a8793139Schristos #define FE_INVALID 0x01 42a8793139Schristos #define FE_DIVBYZERO 0x02 43a8793139Schristos #define FE_OVERFLOW 0x04 44a8793139Schristos #define FE_UNDERFLOW 0x08 45a8793139Schristos #define FE_INEXACT 0x10 46a8793139Schristos #define FE_INTOVF 0x20 /* not maskable */ 47253d8526Schristos #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INTOVF | \ 48253d8526Schristos FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 49253d8526Schristos 50253d8526Schristos /* Rounding modes */ 51253d8526Schristos #define FE_TOWARDZERO 0x00 52253d8526Schristos #define FE_DOWNWARD 0x01 53253d8526Schristos #define FE_TONEAREST 0x02 54253d8526Schristos #define FE_UPWARD 0x03 55253d8526Schristos #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 56253d8526Schristos FE_UPWARD | FE_TOWARDZERO) 57253d8526Schristos #define _ROUND_SHIFT 58 58253d8526Schristos 59a8793139Schristos #define _FPUSW_SHIFT 52 60253d8526Schristos 61253d8526Schristos #define __excb() __asm __volatile("excb") 62253d8526Schristos #define __mf_fpcr(__cw) __asm __volatile("mf_fpcr %0" : "=f" (*(__cw))) 63253d8526Schristos #define __mt_fpcr(__cw) __asm __volatile("mt_fpcr %0" : : "f" (__cw)) 64253d8526Schristos 65253d8526Schristos union __fpcr { 66253d8526Schristos double __d; 67253d8526Schristos fenv_t __bits; 68253d8526Schristos }; 69253d8526Schristos 70253d8526Schristos __BEGIN_DECLS 71253d8526Schristos 72253d8526Schristos /* Default floating-point environment */ 73253d8526Schristos extern const fenv_t __fe_dfl_env; 74253d8526Schristos #define FE_DFL_ENV (&__fe_dfl_env) 75253d8526Schristos 76b97fcb9bSchristos #if __GNUC_PREREQ__(8, 0) 77b97fcb9bSchristos #pragma GCC diagnostic push 78b97fcb9bSchristos #pragma GCC diagnostic ignored "-Wshadow" 79b97fcb9bSchristos #endif 80b97fcb9bSchristos 81253d8526Schristos static __inline int 82253d8526Schristos feclearexcept(int __excepts) 83253d8526Schristos { 84253d8526Schristos union __fpcr __r; 85253d8526Schristos 86253d8526Schristos __excb(); 87253d8526Schristos __mf_fpcr(&__r.__d); 88253d8526Schristos __r.__bits &= ~((fenv_t)__excepts << _FPUSW_SHIFT); 89253d8526Schristos __mt_fpcr(__r.__d); 90253d8526Schristos __excb(); 91253d8526Schristos return 0; 92253d8526Schristos } 93253d8526Schristos 94253d8526Schristos static __inline int 95253d8526Schristos fegetexceptflag(fexcept_t *__flagp, int __excepts) 96253d8526Schristos { 97253d8526Schristos union __fpcr __r; 98253d8526Schristos 99253d8526Schristos __excb(); 100253d8526Schristos __mf_fpcr(&__r.__d); 101253d8526Schristos __excb(); 102253d8526Schristos *__flagp = (__r.__bits >> _FPUSW_SHIFT) & __excepts; 103253d8526Schristos return 0; 104253d8526Schristos } 105253d8526Schristos 106253d8526Schristos static __inline int 107253d8526Schristos fesetexceptflag(const fexcept_t *__flagp, int __excepts) 108253d8526Schristos { 109253d8526Schristos union __fpcr __r; 110253d8526Schristos fenv_t __xflag, __xexcepts; 111253d8526Schristos 112253d8526Schristos __xflag = (fenv_t)*__flagp << _FPUSW_SHIFT; 113253d8526Schristos __xexcepts = (fenv_t)__excepts << _FPUSW_SHIFT; 114253d8526Schristos __excb(); 115253d8526Schristos __mf_fpcr(&__r.__d); 116253d8526Schristos __r.__bits &= ~__xexcepts; 117253d8526Schristos __r.__bits |= __xflag & __xexcepts; 118253d8526Schristos __mt_fpcr(__r.__d); 119253d8526Schristos __excb(); 120253d8526Schristos return 0; 121253d8526Schristos } 122253d8526Schristos 123253d8526Schristos static __inline int 124253d8526Schristos feraiseexcept(int __excepts) 125253d8526Schristos { 126253d8526Schristos 127253d8526Schristos /* 128253d8526Schristos * XXX Generating exceptions this way does not actually invoke 129253d8526Schristos * a userland trap handler when enabled, but neither do 130253d8526Schristos * arithmetic operations as far as I can tell. Perhaps there 131253d8526Schristos * are more bugs in the kernel trap handler. 132253d8526Schristos */ 133253d8526Schristos fexcept_t __ex = __excepts; 134253d8526Schristos fesetexceptflag(&__ex, __excepts); 135253d8526Schristos return 0; 136253d8526Schristos } 137253d8526Schristos 138253d8526Schristos static __inline int 139253d8526Schristos fetestexcept(int __excepts) 140253d8526Schristos { 141253d8526Schristos union __fpcr __r; 142253d8526Schristos 143253d8526Schristos __excb(); 144253d8526Schristos __mf_fpcr(&__r.__d); 145253d8526Schristos __excb(); 146253d8526Schristos return (__r.__bits >> _FPUSW_SHIFT) & __excepts; 147253d8526Schristos } 148253d8526Schristos 149253d8526Schristos static __inline int 150253d8526Schristos fegetround(void) 151253d8526Schristos { 152253d8526Schristos union __fpcr __r; 153253d8526Schristos 154253d8526Schristos /* 155253d8526Schristos * No exception barriers should be required here if we assume 156253d8526Schristos * that only fesetround() can change the rounding mode. 157253d8526Schristos */ 158253d8526Schristos __mf_fpcr(&__r.__d); 159253d8526Schristos return (int)(__r.__bits >> _ROUND_SHIFT) & _ROUND_MASK; 160253d8526Schristos } 161253d8526Schristos 162253d8526Schristos static __inline int 163253d8526Schristos fesetround(int __round) 164253d8526Schristos { 165253d8526Schristos union __fpcr __r; 166253d8526Schristos 167253d8526Schristos if (__round & ~_ROUND_MASK) 168253d8526Schristos return (-1); 169253d8526Schristos __excb(); 170253d8526Schristos __mf_fpcr(&__r.__d); 171253d8526Schristos __r.__bits &= ~((fenv_t)_ROUND_MASK << _ROUND_SHIFT); 172253d8526Schristos __r.__bits |= (fenv_t)__round << _ROUND_SHIFT; 173253d8526Schristos __mt_fpcr(__r.__d); 174253d8526Schristos __excb(); 175253d8526Schristos return 0; 176253d8526Schristos } 177253d8526Schristos 178b97fcb9bSchristos #if __GNUC_PREREQ__(8, 0) 179b97fcb9bSchristos #pragma GCC diagnostic pop 180b97fcb9bSchristos #endif 181b97fcb9bSchristos 182253d8526Schristos int fegetenv(fenv_t *); 183253d8526Schristos int feholdexcept(fenv_t *); 184253d8526Schristos int fesetenv(const fenv_t *); 185253d8526Schristos int feupdateenv(const fenv_t *); 186253d8526Schristos 187253d8526Schristos #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE) 188253d8526Schristos int feenableexcept(int); 189253d8526Schristos int fedisableexcept(int); 190253d8526Schristos int fegetexcept(void); 191253d8526Schristos #endif /* _NETBSD_SOURCE || _GNU_SOURCE */ 192253d8526Schristos 193253d8526Schristos 194253d8526Schristos __END_DECLS 195253d8526Schristos 196253d8526Schristos #endif /* !_ALPHA_FENV_H_ */ 197