1 /* $NetBSD: fenv.h,v 1.7 2024/10/30 15:56:11 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD: head/lib/msun/mips/fenv.h 226218 2011-10-10 15:43:09Z das $ 29 */ 30 31 #ifndef _MIPS_FENV_H_ 32 #define _MIPS_FENV_H_ 33 34 #include <sys/featuretest.h> 35 #include <sys/stdint.h> 36 37 /* Exception flags */ 38 #define FE_INEXACT 0x0004 39 #define FE_UNDERFLOW 0x0008 40 #define FE_OVERFLOW 0x0010 41 #define FE_DIVBYZERO 0x0020 42 #define FE_INVALID 0x0040 43 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 44 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 45 46 /* Rounding modes */ 47 #define FE_TONEAREST 0x0000 48 #define FE_TOWARDZERO 0x0001 49 #define FE_UPWARD 0x0002 50 #define FE_DOWNWARD 0x0003 51 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 52 FE_UPWARD | FE_TOWARDZERO) 53 54 #ifndef __mips_soft_float 55 56 #ifndef __fenv_static 57 #define __fenv_static static 58 #endif 59 60 typedef uint32_t fpu_control_t __attribute__((__mode__(__SI__))); 61 typedef fpu_control_t fenv_t; 62 typedef fpu_control_t fexcept_t; 63 64 __BEGIN_DECLS 65 66 /* Default floating-point environment */ 67 extern const fenv_t __fe_dfl_env; 68 #define FE_DFL_ENV (&__fe_dfl_env) 69 70 /* We need to be able to map status flag positions to mask flag positions */ 71 #define _ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT) 72 #define _ENABLE_SHIFT 5 73 74 static inline fpu_control_t 75 __rfs(void) 76 { 77 fpu_control_t __fpsr; 78 79 __asm __volatile("cfc1 %0,$31" : "=r" (__fpsr)); 80 return __fpsr; 81 } 82 83 static inline void 84 __wfs(fpu_control_t __fpsr) 85 { 86 87 __asm __volatile("ctc1 %0,$31" : : "r" (__fpsr)); 88 } 89 90 #if __GNUC_PREREQ__(8, 0) 91 #pragma GCC diagnostic push 92 #pragma GCC diagnostic ignored "-Wshadow" 93 #endif 94 95 __fenv_static inline int 96 feclearexcept(int __excepts) 97 { 98 fexcept_t __fpsr; 99 100 __excepts &= FE_ALL_EXCEPT; 101 __fpsr = __rfs(); 102 __fpsr &= ~(__excepts | (__excepts << _ENABLE_SHIFT)); 103 __wfs(__fpsr); 104 return 0; 105 } 106 107 __fenv_static inline int 108 fegetexceptflag(fexcept_t *__flagp, int __excepts) 109 { 110 fexcept_t __fpsr; 111 112 __fpsr = __rfs(); 113 *__flagp = __fpsr & __excepts; 114 return (0); 115 } 116 117 __fenv_static inline int 118 fesetexceptflag(const fexcept_t *__flagp, int __excepts) 119 { 120 fexcept_t __fpsr; 121 122 __fpsr = __rfs(); 123 __fpsr &= ~__excepts; 124 __fpsr |= *__flagp & __excepts; 125 __wfs(__fpsr); 126 return (0); 127 } 128 129 __fenv_static inline int 130 feraiseexcept(int __excepts) 131 { 132 fexcept_t __ex = __excepts; 133 134 fesetexceptflag(&__ex, __excepts); /* XXX */ 135 return (0); 136 } 137 138 __fenv_static inline int 139 fetestexcept(int __excepts) 140 { 141 fexcept_t __fpsr; 142 143 __fpsr = __rfs(); 144 return (__fpsr & __excepts); 145 } 146 147 __fenv_static inline int 148 fegetround(void) 149 { 150 fexcept_t __fpsr; 151 152 __fpsr = __rfs(); 153 return __fpsr & _ROUND_MASK; 154 } 155 156 __fenv_static inline int 157 fesetround(int __round) 158 { 159 fexcept_t __fpsr; 160 161 if (__round & ~_ROUND_MASK) 162 return 1; 163 __fpsr = __rfs(); 164 __fpsr &= ~_ROUND_MASK; 165 __fpsr |= __round; 166 __wfs(__fpsr); 167 168 return 0; 169 } 170 171 __fenv_static inline int 172 fegetenv(fenv_t *__envp) 173 { 174 175 *__envp = __rfs(); 176 return (0); 177 } 178 179 __fenv_static inline int 180 feholdexcept(fenv_t *__envp) 181 { 182 fenv_t __env; 183 184 __env = __rfs(); 185 *__envp = __env; 186 __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); 187 __wfs(__env); 188 return (0); 189 } 190 191 __fenv_static inline int 192 fesetenv(const fenv_t *__envp) 193 { 194 195 __wfs(*__envp); 196 return (0); 197 } 198 199 __fenv_static inline int 200 feupdateenv(const fenv_t *__envp) 201 { 202 fexcept_t __fpsr; 203 204 __fpsr = __rfs(); 205 __wfs(*__envp); 206 feraiseexcept(__fpsr & FE_ALL_EXCEPT); 207 return (0); 208 } 209 210 #if __GNUC_PREREQ__(8, 0) 211 #pragma GCC diagnostic pop 212 #endif 213 214 #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE) 215 216 __fenv_static inline int 217 feenableexcept(int __excepts) 218 { 219 fenv_t __old_fpsr, __new_fpsr; 220 221 __new_fpsr = __rfs(); 222 __old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT; 223 __excepts &= FE_ALL_EXCEPT; 224 __new_fpsr |= __excepts << _ENABLE_SHIFT; 225 __wfs(__new_fpsr); 226 return __old_fpsr; 227 } 228 229 __fenv_static inline int 230 fedisableexcept(int __excepts) 231 { 232 fenv_t __old_fpsr, __new_fpsr; 233 234 __new_fpsr = __rfs(); 235 __old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT; 236 __excepts &= FE_ALL_EXCEPT; 237 __new_fpsr &= ~(__excepts << _ENABLE_SHIFT); 238 __wfs(__new_fpsr); 239 return __old_fpsr; 240 } 241 242 __fenv_static inline int 243 fegetexcept(void) 244 { 245 fenv_t __fpsr; 246 247 __fpsr = __rfs(); 248 return ((__fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT); 249 } 250 251 #endif /* _NETBSD_SOURCE || _GNU_SOURCE */ 252 253 __END_DECLS 254 255 #endif /* __mips_soft_float */ 256 257 #endif /* !_FENV_H_ */ 258