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