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