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