1 /*- 2 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 3 * Copyright (c) 2015 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 FE_TONEAREST (0x00 << 5) 63 #define FE_TOWARDZERO (0x01 << 5) 64 #define FE_DOWNWARD (0x02 << 5) 65 #define FE_UPWARD (0x03 << 5) 66 #define _ROUND_SHIFT 5 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 /* We need to be able to map status flag positions to mask flag positions */ 77 #define _FPUSW_SHIFT 0 78 #define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) 79 80 #define __rfs(__fpsr) __asm __volatile("csrr %0, fcsr" : "=r" (*(__fpsr))) 81 #define __wfs(__fpsr) __asm __volatile("csrw fcsr, %0" :: "r" (__fpsr)) 82 83 __fenv_static inline int 84 feclearexcept(int __excepts) 85 { 86 fexcept_t __fpsr; 87 88 __rfs(&__fpsr); 89 __fpsr &= ~__excepts; 90 __wfs(__fpsr); 91 return (0); 92 } 93 94 __fenv_static inline int 95 fegetexceptflag(fexcept_t *__flagp, int __excepts) 96 { 97 fexcept_t __fpsr; 98 99 __rfs(&__fpsr); 100 *__flagp = __fpsr & __excepts; 101 return (0); 102 } 103 104 __fenv_static inline int 105 fesetexceptflag(const fexcept_t *__flagp, int __excepts) 106 { 107 fexcept_t __fpsr; 108 109 __rfs(&__fpsr); 110 __fpsr &= ~__excepts; 111 __fpsr |= *__flagp & __excepts; 112 __wfs(__fpsr); 113 return (0); 114 } 115 116 __fenv_static inline int 117 feraiseexcept(int __excepts) 118 { 119 fexcept_t __ex = __excepts; 120 121 fesetexceptflag(&__ex, __excepts); /* XXX */ 122 return (0); 123 } 124 125 __fenv_static inline int 126 fetestexcept(int __excepts) 127 { 128 fexcept_t __fpsr; 129 130 __rfs(&__fpsr); 131 return (__fpsr & __excepts); 132 } 133 134 __fenv_static inline int 135 fegetround(void) 136 { 137 138 return (-1); 139 } 140 141 __fenv_static inline int 142 fesetround(int __round) 143 { 144 145 return (-1); 146 } 147 148 __fenv_static inline int 149 fegetenv(fenv_t *__envp) 150 { 151 152 __rfs(__envp); 153 return (0); 154 } 155 156 __fenv_static inline int 157 feholdexcept(fenv_t *__envp) 158 { 159 fenv_t __env; 160 161 __rfs(&__env); 162 *__envp = __env; 163 __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); 164 __wfs(__env); 165 return (0); 166 } 167 168 __fenv_static inline int 169 fesetenv(const fenv_t *__envp) 170 { 171 172 __wfs(*__envp); 173 return (0); 174 } 175 176 __fenv_static inline int 177 feupdateenv(const fenv_t *__envp) 178 { 179 fexcept_t __fpsr; 180 181 __rfs(&__fpsr); 182 __wfs(*__envp); 183 feraiseexcept(__fpsr & FE_ALL_EXCEPT); 184 return (0); 185 } 186 187 #if __BSD_VISIBLE 188 189 /* We currently provide no external definitions of the functions below. */ 190 191 static inline int 192 feenableexcept(int __mask) 193 { 194 fenv_t __old_fpsr; 195 fenv_t __new_fpsr; 196 197 __rfs(&__old_fpsr); 198 __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT; 199 __wfs(__new_fpsr); 200 return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); 201 } 202 203 static inline int 204 fedisableexcept(int __mask) 205 { 206 fenv_t __old_fpsr; 207 fenv_t __new_fpsr; 208 209 __rfs(&__old_fpsr); 210 __new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT); 211 __wfs(__new_fpsr); 212 return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); 213 } 214 215 static inline int 216 fegetexcept(void) 217 { 218 fenv_t __fpsr; 219 220 __rfs(&__fpsr); 221 return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT); 222 } 223 224 #endif /* __BSD_VISIBLE */ 225 226 __END_DECLS 227 228 #endif /* !_FENV_H_ */ 229