1*cddc78eaSriastradh /* $NetBSD: fenv.h,v 1.7 2024/10/30 15:56:11 riastradh Exp $ */ 2257ef94eSchristos 3257ef94eSchristos /*- 4257ef94eSchristos * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 5257ef94eSchristos * All rights reserved. 6257ef94eSchristos * 7257ef94eSchristos * Redistribution and use in source and binary forms, with or without 8257ef94eSchristos * modification, are permitted provided that the following conditions 9257ef94eSchristos * are met: 10257ef94eSchristos * 1. Redistributions of source code must retain the above copyright 11257ef94eSchristos * notice, this list of conditions and the following disclaimer. 12257ef94eSchristos * 2. Redistributions in binary form must reproduce the above copyright 13257ef94eSchristos * notice, this list of conditions and the following disclaimer in the 14257ef94eSchristos * documentation and/or other materials provided with the distribution. 15257ef94eSchristos * 16257ef94eSchristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17257ef94eSchristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18257ef94eSchristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19257ef94eSchristos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20257ef94eSchristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21257ef94eSchristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22257ef94eSchristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23257ef94eSchristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24257ef94eSchristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25257ef94eSchristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26257ef94eSchristos * SUCH DAMAGE. 27257ef94eSchristos * 28257ef94eSchristos * $FreeBSD: head/lib/msun/mips/fenv.h 226218 2011-10-10 15:43:09Z das $ 29257ef94eSchristos */ 30257ef94eSchristos 31257ef94eSchristos #ifndef _MIPS_FENV_H_ 32257ef94eSchristos #define _MIPS_FENV_H_ 33257ef94eSchristos 34*cddc78eaSriastradh #include <sys/featuretest.h> 35257ef94eSchristos #include <sys/stdint.h> 36257ef94eSchristos 37257ef94eSchristos /* Exception flags */ 380905c615Schristos #define FE_INEXACT 0x0004 39257ef94eSchristos #define FE_UNDERFLOW 0x0008 400905c615Schristos #define FE_OVERFLOW 0x0010 410905c615Schristos #define FE_DIVBYZERO 0x0020 420905c615Schristos #define FE_INVALID 0x0040 43257ef94eSchristos #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 44257ef94eSchristos FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 45257ef94eSchristos 46257ef94eSchristos /* Rounding modes */ 47257ef94eSchristos #define FE_TONEAREST 0x0000 48257ef94eSchristos #define FE_TOWARDZERO 0x0001 49257ef94eSchristos #define FE_UPWARD 0x0002 50257ef94eSchristos #define FE_DOWNWARD 0x0003 51257ef94eSchristos #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 52257ef94eSchristos FE_UPWARD | FE_TOWARDZERO) 537e30e943Schs 547e30e943Schs #ifndef __mips_soft_float 557e30e943Schs 567e30e943Schs #ifndef __fenv_static 577e30e943Schs #define __fenv_static static 587e30e943Schs #endif 597e30e943Schs 607e30e943Schs typedef uint32_t fpu_control_t __attribute__((__mode__(__SI__))); 617e30e943Schs typedef fpu_control_t fenv_t; 627e30e943Schs typedef fpu_control_t fexcept_t; 637e30e943Schs 64257ef94eSchristos __BEGIN_DECLS 65257ef94eSchristos 66257ef94eSchristos /* Default floating-point environment */ 67257ef94eSchristos extern const fenv_t __fe_dfl_env; 68257ef94eSchristos #define FE_DFL_ENV (&__fe_dfl_env) 69257ef94eSchristos 70257ef94eSchristos /* We need to be able to map status flag positions to mask flag positions */ 710905c615Schristos #define _ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT) 720905c615Schristos #define _ENABLE_SHIFT 5 73257ef94eSchristos 74ec9b26b9Schs static inline fpu_control_t 75ec9b26b9Schs __rfs(void) 76ec9b26b9Schs { 77ec9b26b9Schs fpu_control_t __fpsr; 780905c615Schristos 79ec9b26b9Schs __asm __volatile("cfc1 %0,$31" : "=r" (__fpsr)); 80ec9b26b9Schs return __fpsr; 81ec9b26b9Schs } 82ec9b26b9Schs 83ec9b26b9Schs static inline void 84ec9b26b9Schs __wfs(fpu_control_t __fpsr) 85ec9b26b9Schs { 86ec9b26b9Schs 87ec9b26b9Schs __asm __volatile("ctc1 %0,$31" : : "r" (__fpsr)); 88ec9b26b9Schs } 89257ef94eSchristos 90afd5a45cSchristos #if __GNUC_PREREQ__(8, 0) 91afd5a45cSchristos #pragma GCC diagnostic push 92afd5a45cSchristos #pragma GCC diagnostic ignored "-Wshadow" 93afd5a45cSchristos #endif 94afd5a45cSchristos 95257ef94eSchristos __fenv_static inline int 96257ef94eSchristos feclearexcept(int __excepts) 97257ef94eSchristos { 98257ef94eSchristos fexcept_t __fpsr; 99257ef94eSchristos 1000905c615Schristos __excepts &= FE_ALL_EXCEPT; 101ec9b26b9Schs __fpsr = __rfs(); 1020905c615Schristos __fpsr &= ~(__excepts | (__excepts << _ENABLE_SHIFT)); 103257ef94eSchristos __wfs(__fpsr); 1040905c615Schristos return 0; 105257ef94eSchristos } 106257ef94eSchristos 107257ef94eSchristos __fenv_static inline int 108257ef94eSchristos fegetexceptflag(fexcept_t *__flagp, int __excepts) 109257ef94eSchristos { 110257ef94eSchristos fexcept_t __fpsr; 111257ef94eSchristos 112ec9b26b9Schs __fpsr = __rfs(); 113257ef94eSchristos *__flagp = __fpsr & __excepts; 114257ef94eSchristos return (0); 115257ef94eSchristos } 116257ef94eSchristos 117257ef94eSchristos __fenv_static inline int 118257ef94eSchristos fesetexceptflag(const fexcept_t *__flagp, int __excepts) 119257ef94eSchristos { 120257ef94eSchristos fexcept_t __fpsr; 121257ef94eSchristos 122ec9b26b9Schs __fpsr = __rfs(); 123257ef94eSchristos __fpsr &= ~__excepts; 124257ef94eSchristos __fpsr |= *__flagp & __excepts; 125257ef94eSchristos __wfs(__fpsr); 126257ef94eSchristos return (0); 127257ef94eSchristos } 128257ef94eSchristos 129257ef94eSchristos __fenv_static inline int 130257ef94eSchristos feraiseexcept(int __excepts) 131257ef94eSchristos { 132257ef94eSchristos fexcept_t __ex = __excepts; 133257ef94eSchristos 134257ef94eSchristos fesetexceptflag(&__ex, __excepts); /* XXX */ 135257ef94eSchristos return (0); 136257ef94eSchristos } 137257ef94eSchristos 138257ef94eSchristos __fenv_static inline int 139257ef94eSchristos fetestexcept(int __excepts) 140257ef94eSchristos { 141257ef94eSchristos fexcept_t __fpsr; 142257ef94eSchristos 143ec9b26b9Schs __fpsr = __rfs(); 144257ef94eSchristos return (__fpsr & __excepts); 145257ef94eSchristos } 146257ef94eSchristos 147257ef94eSchristos __fenv_static inline int 148257ef94eSchristos fegetround(void) 149257ef94eSchristos { 1500905c615Schristos fexcept_t __fpsr; 151257ef94eSchristos 152ec9b26b9Schs __fpsr = __rfs(); 1530905c615Schristos return __fpsr & _ROUND_MASK; 154257ef94eSchristos } 155257ef94eSchristos 156257ef94eSchristos __fenv_static inline int 157257ef94eSchristos fesetround(int __round) 158257ef94eSchristos { 1590905c615Schristos fexcept_t __fpsr; 160257ef94eSchristos 1610905c615Schristos if (__round & ~_ROUND_MASK) 1620905c615Schristos return 1; 163ec9b26b9Schs __fpsr = __rfs(); 1640905c615Schristos __fpsr &= ~_ROUND_MASK; 1650905c615Schristos __fpsr |= __round; 166ec9b26b9Schs __wfs(__fpsr); 1670905c615Schristos 1680905c615Schristos return 0; 169257ef94eSchristos } 170257ef94eSchristos 171257ef94eSchristos __fenv_static inline int 172257ef94eSchristos fegetenv(fenv_t *__envp) 173257ef94eSchristos { 174257ef94eSchristos 175ec9b26b9Schs *__envp = __rfs(); 176257ef94eSchristos return (0); 177257ef94eSchristos } 178257ef94eSchristos 179257ef94eSchristos __fenv_static inline int 180257ef94eSchristos feholdexcept(fenv_t *__envp) 181257ef94eSchristos { 182257ef94eSchristos fenv_t __env; 183257ef94eSchristos 184ec9b26b9Schs __env = __rfs(); 185257ef94eSchristos *__envp = __env; 186257ef94eSchristos __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); 187257ef94eSchristos __wfs(__env); 188257ef94eSchristos return (0); 189257ef94eSchristos } 190257ef94eSchristos 191257ef94eSchristos __fenv_static inline int 192257ef94eSchristos fesetenv(const fenv_t *__envp) 193257ef94eSchristos { 194257ef94eSchristos 195257ef94eSchristos __wfs(*__envp); 196257ef94eSchristos return (0); 197257ef94eSchristos } 198257ef94eSchristos 199257ef94eSchristos __fenv_static inline int 200257ef94eSchristos feupdateenv(const fenv_t *__envp) 201257ef94eSchristos { 202257ef94eSchristos fexcept_t __fpsr; 203257ef94eSchristos 204ec9b26b9Schs __fpsr = __rfs(); 205257ef94eSchristos __wfs(*__envp); 206257ef94eSchristos feraiseexcept(__fpsr & FE_ALL_EXCEPT); 207257ef94eSchristos return (0); 208257ef94eSchristos } 209257ef94eSchristos 210afd5a45cSchristos #if __GNUC_PREREQ__(8, 0) 211afd5a45cSchristos #pragma GCC diagnostic pop 212afd5a45cSchristos #endif 213afd5a45cSchristos 214257ef94eSchristos #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE) 215257ef94eSchristos 2167e30e943Schs __fenv_static inline int 2170905c615Schristos feenableexcept(int __excepts) 218257ef94eSchristos { 219257ef94eSchristos fenv_t __old_fpsr, __new_fpsr; 220257ef94eSchristos 221ec9b26b9Schs __new_fpsr = __rfs(); 2220905c615Schristos __old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT; 2230905c615Schristos __excepts &= FE_ALL_EXCEPT; 2240905c615Schristos __new_fpsr |= __excepts << _ENABLE_SHIFT; 225257ef94eSchristos __wfs(__new_fpsr); 2260905c615Schristos return __old_fpsr; 227257ef94eSchristos } 228257ef94eSchristos 2297e30e943Schs __fenv_static inline int 2300905c615Schristos fedisableexcept(int __excepts) 231257ef94eSchristos { 232257ef94eSchristos fenv_t __old_fpsr, __new_fpsr; 233257ef94eSchristos 234ec9b26b9Schs __new_fpsr = __rfs(); 2350905c615Schristos __old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT; 2360905c615Schristos __excepts &= FE_ALL_EXCEPT; 2370905c615Schristos __new_fpsr &= ~(__excepts << _ENABLE_SHIFT); 238257ef94eSchristos __wfs(__new_fpsr); 2390905c615Schristos return __old_fpsr; 240257ef94eSchristos } 241257ef94eSchristos 2427e30e943Schs __fenv_static inline int 243257ef94eSchristos fegetexcept(void) 244257ef94eSchristos { 245257ef94eSchristos fenv_t __fpsr; 246257ef94eSchristos 247ec9b26b9Schs __fpsr = __rfs(); 2480905c615Schristos return ((__fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT); 249257ef94eSchristos } 250257ef94eSchristos 251257ef94eSchristos #endif /* _NETBSD_SOURCE || _GNU_SOURCE */ 252257ef94eSchristos 253257ef94eSchristos __END_DECLS 254257ef94eSchristos 2557e30e943Schs #endif /* __mips_soft_float */ 2567e30e943Schs 257257ef94eSchristos #endif /* !_FENV_H_ */ 258