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/_types.h> 40 41 #ifndef __fenv_static 42 #define __fenv_static static 43 #endif 44 45 typedef __uint64_t fenv_t; 46 typedef __uint64_t fexcept_t; 47 48 /* Exception flags */ 49 #define FE_INVALID 0x0010 50 #define FE_DIVBYZERO 0x0008 51 #define FE_OVERFLOW 0x0004 52 #define FE_UNDERFLOW 0x0002 53 #define FE_INEXACT 0x0001 54 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 55 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 56 57 /* 58 * RISC-V Rounding modes 59 */ 60 #define _ROUND_SHIFT 5 61 #define FE_TONEAREST (0x00 << _ROUND_SHIFT) 62 #define FE_TOWARDZERO (0x01 << _ROUND_SHIFT) 63 #define FE_DOWNWARD (0x02 << _ROUND_SHIFT) 64 #define FE_UPWARD (0x03 << _ROUND_SHIFT) 65 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 66 FE_UPWARD | FE_TOWARDZERO) 67 68 __BEGIN_DECLS 69 70 /* Default floating-point environment */ 71 extern const fenv_t __fe_dfl_env; 72 #define FE_DFL_ENV (&__fe_dfl_env) 73 74 #if !defined(__riscv_float_abi_soft) && !defined(__riscv_float_abi_double) 75 #if defined(__riscv_float_abi_single) 76 #error single precision floating point ABI not supported 77 #else 78 #error compiler did not set soft/hard float macros 79 #endif 80 #endif 81 82 #ifndef __riscv_float_abi_soft 83 #define __rfs(__fcsr) __asm __volatile("csrr %0, fcsr" : "=r" (__fcsr)) 84 #define __wfs(__fcsr) __asm __volatile("csrw fcsr, %0" :: "r" (__fcsr)) 85 #endif 86 87 #ifdef __riscv_float_abi_soft 88 int feclearexcept(int __excepts); 89 int fegetexceptflag(fexcept_t *__flagp, int __excepts); 90 int fesetexceptflag(const fexcept_t *__flagp, int __excepts); 91 int feraiseexcept(int __excepts); 92 int fetestexcept(int __excepts); 93 int fegetround(void); 94 int fesetround(int __round); 95 int fegetenv(fenv_t *__envp); 96 int feholdexcept(fenv_t *__envp); 97 int fesetenv(const fenv_t *__envp); 98 int feupdateenv(const fenv_t *__envp); 99 #else 100 __fenv_static inline int 101 feclearexcept(int __excepts) 102 { 103 104 __asm __volatile("csrc fflags, %0" :: "r"(__excepts)); 105 106 return (0); 107 } 108 109 __fenv_static inline int 110 fegetexceptflag(fexcept_t *__flagp, int __excepts) 111 { 112 fexcept_t __fcsr; 113 114 __rfs(__fcsr); 115 *__flagp = __fcsr & __excepts; 116 117 return (0); 118 } 119 120 __fenv_static inline int 121 fesetexceptflag(const fexcept_t *__flagp, int __excepts) 122 { 123 fexcept_t __fcsr; 124 125 __fcsr = *__flagp; 126 __asm __volatile("csrc fflags, %0" :: "r"(__excepts)); 127 __asm __volatile("csrs fflags, %0" :: "r"(__fcsr & __excepts)); 128 129 return (0); 130 } 131 132 __fenv_static inline int 133 feraiseexcept(int __excepts) 134 { 135 136 __asm __volatile("csrs fflags, %0" :: "r"(__excepts)); 137 138 return (0); 139 } 140 141 __fenv_static inline int 142 fetestexcept(int __excepts) 143 { 144 fexcept_t __fcsr; 145 146 __rfs(__fcsr); 147 148 return (__fcsr & __excepts); 149 } 150 151 __fenv_static inline int 152 fegetround(void) 153 { 154 fexcept_t __fcsr; 155 156 __rfs(__fcsr); 157 158 return (__fcsr & _ROUND_MASK); 159 } 160 161 __fenv_static inline int 162 fesetround(int __round) 163 { 164 fexcept_t __fcsr; 165 166 if (__round & ~_ROUND_MASK) 167 return (-1); 168 169 __rfs(__fcsr); 170 __fcsr &= ~_ROUND_MASK; 171 __fcsr |= __round; 172 __wfs(__fcsr); 173 174 return (0); 175 } 176 177 __fenv_static inline int 178 fegetenv(fenv_t *__envp) 179 { 180 181 __rfs(*__envp); 182 183 return (0); 184 } 185 186 __fenv_static inline int 187 feholdexcept(fenv_t *__envp __unused) 188 { 189 190 /* No exception traps. */ 191 192 return (-1); 193 } 194 195 __fenv_static inline int 196 fesetenv(const fenv_t *__envp) 197 { 198 199 __wfs(*__envp); 200 201 return (0); 202 } 203 204 __fenv_static inline int 205 feupdateenv(const fenv_t *__envp) 206 { 207 fexcept_t __fcsr; 208 209 __rfs(__fcsr); 210 __wfs(*__envp); 211 feraiseexcept(__fcsr & FE_ALL_EXCEPT); 212 213 return (0); 214 } 215 #endif /* !__riscv_float_abi_soft */ 216 217 #if __BSD_VISIBLE 218 219 /* We currently provide no external definitions of the functions below. */ 220 221 #ifdef __riscv_float_abi_soft 222 int feenableexcept(int __mask); 223 int fedisableexcept(int __mask); 224 int fegetexcept(void); 225 #else 226 static inline int 227 feenableexcept(int __mask __unused) 228 { 229 230 /* No exception traps. */ 231 232 return (0); 233 } 234 235 static inline int 236 fedisableexcept(int __mask __unused) 237 { 238 239 /* No exception traps. */ 240 241 return (0); 242 } 243 244 static inline int 245 fegetexcept(void) 246 { 247 248 /* No exception traps. */ 249 250 return (0); 251 } 252 #endif /* !__riscv_float_abi_soft */ 253 254 #endif /* __BSD_VISIBLE */ 255 256 __END_DECLS 257 258 #endif /* !_FENV_H_ */ 259