1 /*- 2 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 3 * Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com> 4 * All rights reserved. 5 * 6 * Portions of this software were developed by SRI International and the 7 * University of Cambridge Computer Laboratory under DARPA/AFRL contract 8 * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. 9 * 10 * Portions of this software were developed by the University of Cambridge 11 * Computer Laboratory as part of the CTSRD Project, with support from the 12 * UK Higher Education Innovation Fund (HEIF). 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #ifndef _FENV_H_ 37 #define _FENV_H_ 38 39 #include <sys/cdefs.h> 40 #include <sys/_types.h> 41 42 #ifndef __fenv_static 43 #define __fenv_static static 44 #endif 45 46 typedef __uint64_t fenv_t; 47 typedef __uint64_t femode_t; 48 typedef __uint64_t fexcept_t; 49 50 /* Exception flags */ 51 #define FE_INVALID 0x0010 52 #define FE_DIVBYZERO 0x0008 53 #define FE_OVERFLOW 0x0004 54 #define FE_UNDERFLOW 0x0002 55 #define FE_INEXACT 0x0001 56 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 57 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 58 59 /* 60 * RISC-V Rounding modes 61 */ 62 #define _ROUND_SHIFT 5 63 #define FE_TONEAREST (0x00 << _ROUND_SHIFT) 64 #define FE_TOWARDZERO (0x01 << _ROUND_SHIFT) 65 #define FE_DOWNWARD (0x02 << _ROUND_SHIFT) 66 #define FE_UPWARD (0x03 << _ROUND_SHIFT) 67 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 68 FE_UPWARD | FE_TOWARDZERO) 69 70 __BEGIN_DECLS 71 72 /* Default floating-point environment */ 73 extern const fenv_t __fe_dfl_env; 74 #define FE_DFL_ENV (&__fe_dfl_env) 75 76 /* Default floating-point control modes */ 77 extern const femode_t __fe_dfl_mode; 78 #define FE_DFL_MODE (&__fe_dfl_mode) 79 80 #ifndef __riscv_float_abi_double 81 #error only double hard float ABI supported 82 #endif 83 84 #define __rfs(__fcsr) __asm __volatile("csrr %0, fcsr" : "=r" (__fcsr)) 85 #define __wfs(__fcsr) __asm __volatile("csrw fcsr, %0" :: "r" (__fcsr)) 86 87 int feclearexcept(int); 88 int fegetexceptflag(fexcept_t *, int); 89 int fesetexceptflag(const fexcept_t *, int); 90 int feraiseexcept(int); 91 int fetestexcept(int); 92 int fegetround(void); 93 int fesetround(int); 94 int fegetmode(femode_t *); 95 int fesetmode(const femode_t *); 96 int fegetenv(fenv_t *); 97 int feholdexcept(fenv_t *); 98 int fesetenv(const fenv_t *); 99 int feupdateenv(const fenv_t *); 100 101 /* 102 * C permits a standard library function to also be exposed as a function-like 103 * macro (C23 7.1.4), and msun uses that here to inline the fast path. C++ 104 * forbids it: <cfenv> imports these names into namespace std (using 105 * ::feclearexcept; etc.), so std::feclearexcept() and friends must denote the 106 * actual functions. Expose the inlining macros to C only; C++ uses the real 107 * extern functions (defined in the matching lib/msun/<arch>/fenv.c). 108 */ 109 #ifndef __cplusplus 110 #define feclearexcept(a) __feclearexcept_int(a) 111 #define fegetexceptflag(e, a) __fegetexceptflag_int(e, a) 112 #define fesetexceptflag(e, a) __fesetexceptflag_int(e, a) 113 #define feraiseexcept(a) __feraiseexcept_int(a) 114 #define fetestexcept(a) __fetestexcept_int(a) 115 #define fegetround() __fegetround_int() 116 #define fesetround(a) __fesetround_int(a) 117 #define fegetmode(m) __fegetmode_int(m) 118 #define fesetmode(m) __fesetmode_int(m) 119 #define fegetenv(e) __fegetenv_int(e) 120 #define feholdexcept(e) __feholdexcept_int(e) 121 #define fesetenv(e) __fesetenv_int(e) 122 #define feupdateenv(e) __feupdateenv_int(e) 123 #endif /* !__cplusplus */ 124 125 __fenv_static inline int 126 __feclearexcept_int(int __excepts) 127 { 128 129 __asm __volatile("csrc fflags, %0" :: "r"(__excepts)); 130 131 return (0); 132 } 133 134 __fenv_static inline int 135 __fegetexceptflag_int(fexcept_t *__flagp, int __excepts) 136 { 137 fexcept_t __fcsr; 138 139 __rfs(__fcsr); 140 *__flagp = __fcsr & __excepts; 141 142 return (0); 143 } 144 145 __fenv_static inline int 146 __fesetexceptflag_int(const fexcept_t *__flagp, int __excepts) 147 { 148 fexcept_t __fcsr; 149 150 __fcsr = *__flagp; 151 __asm __volatile("csrc fflags, %0" :: "r"(__excepts)); 152 __asm __volatile("csrs fflags, %0" :: "r"(__fcsr & __excepts)); 153 154 return (0); 155 } 156 157 __fenv_static inline int 158 __feraiseexcept_int(int __excepts) 159 { 160 161 __asm __volatile("csrs fflags, %0" :: "r"(__excepts)); 162 163 return (0); 164 } 165 166 __fenv_static inline int 167 __fetestexcept_int(int __excepts) 168 { 169 fexcept_t __fcsr; 170 171 __rfs(__fcsr); 172 173 return (__fcsr & __excepts); 174 } 175 176 __fenv_static inline int 177 __fegetround_int(void) 178 { 179 fexcept_t __fcsr; 180 181 __rfs(__fcsr); 182 183 return (__fcsr & _ROUND_MASK); 184 } 185 186 __fenv_static inline int 187 __fesetround_int(int __round) 188 { 189 fexcept_t __fcsr; 190 191 if (__round & ~_ROUND_MASK) 192 return (-1); 193 194 __rfs(__fcsr); 195 __fcsr &= ~_ROUND_MASK; 196 __fcsr |= __round; 197 __wfs(__fcsr); 198 199 return (0); 200 } 201 202 __fenv_static inline int 203 __fegetmode_int(femode_t *__modep) 204 { 205 fexcept_t __fcsr; 206 207 __rfs(__fcsr); 208 *__modep = __fcsr & ~FE_ALL_EXCEPT; 209 210 return (0); 211 } 212 213 __fenv_static inline int 214 __fesetmode_int(const femode_t *__modep) 215 { 216 fexcept_t __fcsr; 217 218 __rfs(__fcsr); 219 __fcsr &= FE_ALL_EXCEPT; 220 __fcsr |= *__modep & ~FE_ALL_EXCEPT; 221 __wfs(__fcsr); 222 223 return (0); 224 } 225 226 __fenv_static inline int 227 __fegetenv_int(fenv_t *__envp) 228 { 229 230 __rfs(*__envp); 231 232 return (0); 233 } 234 235 __fenv_static inline int 236 __feholdexcept_int(fenv_t *__envp __unused) 237 { 238 239 /* No exception traps. */ 240 241 return (-1); 242 } 243 244 __fenv_static inline int 245 __fesetenv_int(const fenv_t *__envp) 246 { 247 248 __wfs(*__envp); 249 250 return (0); 251 } 252 253 __fenv_static inline int 254 __feupdateenv_int(const fenv_t *__envp) 255 { 256 fexcept_t __fcsr; 257 258 __rfs(__fcsr); 259 __wfs(*__envp); 260 feraiseexcept(__fcsr & FE_ALL_EXCEPT); 261 262 return (0); 263 } 264 265 #if __BSD_VISIBLE 266 267 int feenableexcept(int); 268 int fedisableexcept(int); 269 270 #ifndef __cplusplus /* see the note above; C++ uses the real functions */ 271 #define feenableexcept(a) __feenableexcept_int(a) 272 #define fedisableexcept(a) __fedisableexcept_int(a) 273 #endif 274 275 __fenv_static inline int 276 __feenableexcept_int(int __mask __unused) 277 { 278 279 /* No exception traps. */ 280 281 return (0); 282 } 283 284 __fenv_static inline int 285 __fedisableexcept_int(int __mask __unused) 286 { 287 288 /* No exception traps. */ 289 290 return (0); 291 } 292 293 /* We currently provide no external definition of fegetexcept(). */ 294 static inline int 295 fegetexcept(void) 296 { 297 298 /* No exception traps. */ 299 300 return (0); 301 } 302 303 #endif /* __BSD_VISIBLE */ 304 305 __END_DECLS 306 307 #endif /* !_FENV_H_ */ 308