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