1 1.8 riastrad /* $NetBSD: fenv.h,v 1.8 2024/10/30 15:56:11 riastradh Exp $ */ 2 1.1 christos 3 1.1 christos /*- 4 1.1 christos * Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG> 5 1.1 christos * All rights reserved. 6 1.1 christos * 7 1.1 christos * Redistribution and use in source and binary forms, with or without 8 1.1 christos * modification, are permitted provided that the following conditions 9 1.1 christos * are met: 10 1.1 christos * 1. Redistributions of source code must retain the above copyright 11 1.1 christos * notice, this list of conditions and the following disclaimer. 12 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 christos * notice, this list of conditions and the following disclaimer in the 14 1.1 christos * documentation and/or other materials provided with the distribution. 15 1.1 christos * 16 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 1.1 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.1 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 christos * SUCH DAMAGE. 27 1.1 christos * 28 1.1 christos * $FreeBSD: head/lib/msun/powerpc/fenv.h 226218 2011-10-10 15:43:09Z das $ 29 1.1 christos */ 30 1.1 christos 31 1.1 christos #ifndef _POWERPC_FENV_H_ 32 1.1 christos #define _POWERPC_FENV_H_ 33 1.1 christos 34 1.8 riastrad #include <sys/featuretest.h> 35 1.1 christos #include <sys/stdint.h> 36 1.1 christos 37 1.1 christos /* Exception flags */ 38 1.1 christos #define FE_INEXACT 0x02000000 39 1.1 christos #define FE_DIVBYZERO 0x04000000 40 1.1 christos #define FE_UNDERFLOW 0x08000000 41 1.1 christos #define FE_OVERFLOW 0x10000000 42 1.1 christos #define FE_INVALID 0x20000000 /* all types of invalid FP ops */ 43 1.1 christos 44 1.1 christos /* 45 1.1 christos * The PowerPC architecture has extra invalid flags that indicate the 46 1.1 christos * specific type of invalid operation occurred. These flags may be 47 1.1 christos * tested, set, and cleared---but not masked---separately. All of 48 1.1 christos * these bits are cleared when FE_INVALID is cleared, but only 49 1.1 christos * FE_VXSOFT is set when FE_INVALID is explicitly set in software. 50 1.1 christos */ 51 1.1 christos #define FE_VXCVI 0x00000100 /* invalid integer convert */ 52 1.1 christos #define FE_VXSQRT 0x00000200 /* square root of a negative */ 53 1.1 christos #define FE_VXSOFT 0x00000400 /* software-requested exception */ 54 1.1 christos #define FE_VXVC 0x00080000 /* ordered comparison involving NaN */ 55 1.1 christos #define FE_VXIMZ 0x00100000 /* inf * 0 */ 56 1.1 christos #define FE_VXZDZ 0x00200000 /* 0 / 0 */ 57 1.1 christos #define FE_VXIDI 0x00400000 /* inf / inf */ 58 1.1 christos #define FE_VXISI 0x00800000 /* inf - inf */ 59 1.1 christos #define FE_VXSNAN 0x01000000 /* operation on a signalling NaN */ 60 1.1 christos #define FE_ALL_INVALID (FE_VXCVI | FE_VXSQRT | FE_VXSOFT | FE_VXVC | \ 61 1.1 christos FE_VXIMZ | FE_VXZDZ | FE_VXIDI | FE_VXISI | \ 62 1.1 christos FE_VXSNAN | FE_INVALID) 63 1.1 christos #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 64 1.1 christos FE_ALL_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 65 1.1 christos 66 1.1 christos /* Rounding modes */ 67 1.1 christos #define FE_TONEAREST 0x0000 68 1.1 christos #define FE_TOWARDZERO 0x0001 69 1.1 christos #define FE_UPWARD 0x0002 70 1.1 christos #define FE_DOWNWARD 0x0003 71 1.1 christos #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 72 1.1 christos FE_UPWARD | FE_TOWARDZERO) 73 1.1 christos 74 1.3 chs #ifndef _SOFT_FLOAT 75 1.3 chs 76 1.3 chs #ifndef __fenv_static 77 1.3 chs #define __fenv_static static 78 1.3 chs #endif 79 1.3 chs 80 1.3 chs typedef uint32_t fenv_t; 81 1.3 chs typedef uint32_t fexcept_t; 82 1.3 chs 83 1.1 christos #ifndef _KERNEL 84 1.1 christos __BEGIN_DECLS 85 1.1 christos 86 1.1 christos /* Default floating-point environment */ 87 1.1 christos extern const fenv_t __fe_dfl_env; 88 1.1 christos #define FE_DFL_ENV (&__fe_dfl_env) 89 1.1 christos 90 1.1 christos /* We need to be able to map status flag positions to mask flag positions */ 91 1.1 christos #define _FPUSW_SHIFT 22 92 1.1 christos #define _ENABLE_MASK ((FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ 93 1.1 christos FE_OVERFLOW | FE_UNDERFLOW) >> _FPUSW_SHIFT) 94 1.1 christos 95 1.1 christos #ifndef _SOFT_FLOAT 96 1.1 christos #define __mffs(__env) __asm __volatile("mffs %0" : "=f" (*(__env))) 97 1.1 christos #define __mtfsf(__env) __asm __volatile("mtfsf 255,%0" : : "f" (__env)) 98 1.2 chs 99 1.5 christos static __inline uint32_t 100 1.2 chs __mfmsr(void) 101 1.2 chs { 102 1.2 chs uint32_t __msr; 103 1.2 chs 104 1.2 chs __asm volatile ("mfmsr %0" : "=r"(__msr)); 105 1.2 chs return __msr; 106 1.2 chs } 107 1.2 chs 108 1.5 christos static __inline void 109 1.2 chs __mtmsr(uint32_t __msr) 110 1.2 chs { 111 1.2 chs 112 1.2 chs __asm volatile ("mtmsr %0" : : "r"(__msr)); 113 1.2 chs } 114 1.2 chs 115 1.2 chs #define __MSR_FE_MASK (0x00000800 | 0x00000100) 116 1.2 chs #define __MSR_FE_DIS (0) 117 1.2 chs #define __MSR_FE_PREC (0x00000800 | 0x00000100) 118 1.2 chs 119 1.5 christos static __inline void 120 1.2 chs __updatemsr(uint32_t __reg) 121 1.2 chs { 122 1.2 chs uint32_t __msr; 123 1.2 chs 124 1.2 chs __msr = __mfmsr() & ~__MSR_FE_MASK; 125 1.2 chs if (__reg != 0) { 126 1.2 chs __msr |= __MSR_FE_PREC; 127 1.2 chs } else { 128 1.2 chs __msr |= __MSR_FE_DIS; 129 1.2 chs } 130 1.2 chs __mtmsr(__msr); 131 1.2 chs } 132 1.2 chs 133 1.1 christos #else 134 1.1 christos #define __mffs(__env) 135 1.1 christos #define __mtfsf(__env) 136 1.2 chs #define __updatemsr(__reg) 137 1.1 christos #endif 138 1.1 christos 139 1.1 christos union __fpscr { 140 1.1 christos double __d; 141 1.1 christos struct { 142 1.1 christos uint32_t __junk; 143 1.1 christos fenv_t __reg; 144 1.1 christos } __bits; 145 1.1 christos }; 146 1.1 christos 147 1.6 christos #if __GNUC_PREREQ__(8, 0) 148 1.6 christos #pragma GCC diagnostic push 149 1.6 christos #pragma GCC diagnostic ignored "-Wshadow" 150 1.6 christos #endif 151 1.6 christos 152 1.5 christos __fenv_static __inline int 153 1.1 christos feclearexcept(int __excepts) 154 1.1 christos { 155 1.1 christos union __fpscr __r; 156 1.1 christos 157 1.1 christos if (__excepts & FE_INVALID) 158 1.1 christos __excepts |= FE_ALL_INVALID; 159 1.1 christos __mffs(&__r.__d); 160 1.1 christos __r.__bits.__reg &= ~__excepts; 161 1.1 christos __mtfsf(__r.__d); 162 1.1 christos return (0); 163 1.1 christos } 164 1.1 christos 165 1.5 christos __fenv_static __inline int 166 1.1 christos fegetexceptflag(fexcept_t *__flagp, int __excepts) 167 1.1 christos { 168 1.1 christos union __fpscr __r; 169 1.1 christos 170 1.1 christos __mffs(&__r.__d); 171 1.1 christos *__flagp = __r.__bits.__reg & __excepts; 172 1.1 christos return (0); 173 1.1 christos } 174 1.1 christos 175 1.5 christos __fenv_static __inline int 176 1.1 christos fesetexceptflag(const fexcept_t *__flagp, int __excepts) 177 1.1 christos { 178 1.1 christos union __fpscr __r; 179 1.1 christos 180 1.1 christos if (__excepts & FE_INVALID) 181 1.7 rin __excepts |= FE_ALL_INVALID; 182 1.1 christos __mffs(&__r.__d); 183 1.1 christos __r.__bits.__reg &= ~__excepts; 184 1.1 christos __r.__bits.__reg |= *__flagp & __excepts; 185 1.1 christos __mtfsf(__r.__d); 186 1.1 christos return (0); 187 1.1 christos } 188 1.1 christos 189 1.5 christos __fenv_static __inline int 190 1.1 christos feraiseexcept(int __excepts) 191 1.1 christos { 192 1.1 christos union __fpscr __r; 193 1.1 christos 194 1.1 christos if (__excepts & FE_INVALID) 195 1.1 christos __excepts |= FE_VXSOFT; 196 1.1 christos __mffs(&__r.__d); 197 1.1 christos __r.__bits.__reg |= __excepts; 198 1.1 christos __mtfsf(__r.__d); 199 1.1 christos return (0); 200 1.1 christos } 201 1.1 christos 202 1.5 christos __fenv_static __inline int 203 1.1 christos fetestexcept(int __excepts) 204 1.1 christos { 205 1.1 christos union __fpscr __r; 206 1.1 christos 207 1.1 christos __mffs(&__r.__d); 208 1.1 christos return (__r.__bits.__reg & __excepts); 209 1.1 christos } 210 1.1 christos 211 1.5 christos __fenv_static __inline int 212 1.1 christos fegetround(void) 213 1.1 christos { 214 1.1 christos union __fpscr __r; 215 1.1 christos 216 1.1 christos __mffs(&__r.__d); 217 1.1 christos return (__r.__bits.__reg & _ROUND_MASK); 218 1.1 christos } 219 1.1 christos 220 1.5 christos __fenv_static __inline int 221 1.1 christos fesetround(int __round) 222 1.1 christos { 223 1.1 christos union __fpscr __r; 224 1.1 christos 225 1.1 christos if (__round & ~_ROUND_MASK) 226 1.1 christos return (-1); 227 1.1 christos __mffs(&__r.__d); 228 1.1 christos __r.__bits.__reg &= ~_ROUND_MASK; 229 1.1 christos __r.__bits.__reg |= __round; 230 1.1 christos __mtfsf(__r.__d); 231 1.1 christos return (0); 232 1.1 christos } 233 1.1 christos 234 1.5 christos __fenv_static __inline int 235 1.1 christos fegetenv(fenv_t *__envp) 236 1.1 christos { 237 1.1 christos union __fpscr __r; 238 1.1 christos 239 1.1 christos __mffs(&__r.__d); 240 1.1 christos *__envp = __r.__bits.__reg; 241 1.1 christos return (0); 242 1.1 christos } 243 1.1 christos 244 1.5 christos __fenv_static __inline int 245 1.1 christos feholdexcept(fenv_t *__envp) 246 1.1 christos { 247 1.1 christos union __fpscr __r; 248 1.2 chs uint32_t msr; 249 1.1 christos 250 1.1 christos __mffs(&__r.__d); 251 1.4 phx *__envp = __r.__bits.__reg; 252 1.1 christos __r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); 253 1.1 christos __mtfsf(__r.__d); 254 1.2 chs __updatemsr(__r.__bits.__reg); 255 1.1 christos return (0); 256 1.1 christos } 257 1.1 christos 258 1.5 christos __fenv_static __inline int 259 1.1 christos fesetenv(const fenv_t *__envp) 260 1.1 christos { 261 1.1 christos union __fpscr __r; 262 1.1 christos 263 1.1 christos __r.__bits.__reg = *__envp; 264 1.1 christos __mtfsf(__r.__d); 265 1.2 chs __updatemsr(__r.__bits.__reg); 266 1.1 christos return (0); 267 1.1 christos } 268 1.1 christos 269 1.5 christos __fenv_static __inline int 270 1.1 christos feupdateenv(const fenv_t *__envp) 271 1.1 christos { 272 1.1 christos union __fpscr __r; 273 1.1 christos 274 1.1 christos __mffs(&__r.__d); 275 1.1 christos __r.__bits.__reg &= FE_ALL_EXCEPT; 276 1.1 christos __r.__bits.__reg |= *__envp; 277 1.1 christos __mtfsf(__r.__d); 278 1.2 chs __updatemsr(__r.__bits.__reg); 279 1.1 christos return (0); 280 1.1 christos } 281 1.1 christos 282 1.6 christos #if __GNUC_PREREQ__(8, 0) 283 1.6 christos #pragma GCC diagnostic pop 284 1.6 christos #endif 285 1.6 christos 286 1.1 christos #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE) 287 1.1 christos 288 1.5 christos __fenv_static __inline int 289 1.1 christos feenableexcept(int __mask) 290 1.1 christos { 291 1.1 christos union __fpscr __r; 292 1.1 christos fenv_t __oldmask; 293 1.1 christos 294 1.1 christos __mffs(&__r.__d); 295 1.1 christos __oldmask = __r.__bits.__reg; 296 1.1 christos __r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT; 297 1.1 christos __mtfsf(__r.__d); 298 1.2 chs __updatemsr(__r.__bits.__reg); 299 1.1 christos return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT); 300 1.1 christos } 301 1.1 christos 302 1.5 christos __fenv_static __inline int 303 1.1 christos fedisableexcept(int __mask) 304 1.1 christos { 305 1.1 christos union __fpscr __r; 306 1.1 christos fenv_t __oldmask; 307 1.1 christos 308 1.1 christos __mffs(&__r.__d); 309 1.1 christos __oldmask = __r.__bits.__reg; 310 1.1 christos __r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT); 311 1.1 christos __mtfsf(__r.__d); 312 1.2 chs __updatemsr(__r.__bits.__reg); 313 1.1 christos return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT); 314 1.1 christos } 315 1.1 christos 316 1.5 christos __fenv_static __inline int 317 1.1 christos fegetexcept(void) 318 1.1 christos { 319 1.1 christos union __fpscr __r; 320 1.1 christos 321 1.1 christos __mffs(&__r.__d); 322 1.1 christos return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT); 323 1.1 christos } 324 1.1 christos 325 1.1 christos #endif /* _NETBSD_SOURCE || _GNU_SOURCE */ 326 1.1 christos 327 1.1 christos __END_DECLS 328 1.3 chs 329 1.1 christos #endif 330 1.3 chs #endif /* _SOFT_FLOAT */ 331 1.1 christos 332 1.1 christos #endif /* !_POWERPC_FENV_H_ */ 333