1 /* $NetBSD: fenv.h,v 1.1 2015/12/21 17:02:33 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD: head/lib/msun/mips/fenv.h 226218 2011-10-10 15:43:09Z das $ 29 */ 30 31 #ifndef _MIPS_FENV_H_ 32 #define _MIPS_FENV_H_ 33 34 #include <sys/stdint.h> 35 36 #ifndef __fenv_static 37 #define __fenv_static static 38 #endif 39 40 typedef uint32_t fenv_t; 41 typedef uint32_t fexcept_t; 42 43 /* Exception flags */ 44 #define FE_INVALID 0x0001 45 #define FE_DIVBYZERO 0x0002 46 #define FE_OVERFLOW 0x0004 47 #define FE_UNDERFLOW 0x0008 48 #define FE_INEXACT 0x0010 49 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 50 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 51 52 /* Rounding modes */ 53 #define FE_TONEAREST 0x0000 54 #define FE_TOWARDZERO 0x0001 55 #define FE_UPWARD 0x0002 56 #define FE_DOWNWARD 0x0003 57 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 58 FE_UPWARD | FE_TOWARDZERO) 59 __BEGIN_DECLS 60 61 /* Default floating-point environment */ 62 extern const fenv_t __fe_dfl_env; 63 #define FE_DFL_ENV (&__fe_dfl_env) 64 65 /* We need to be able to map status flag positions to mask flag positions */ 66 #define _FPUSW_SHIFT 16 67 #define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) 68 69 #ifdef ARM_HARD_FLOAT 70 #define __rfs(__fpsr) __asm __volatile("rfs %0" : "=r" (*(__fpsr))) 71 #define __wfs(__fpsr) __asm __volatile("wfs %0" : : "r" (__fpsr)) 72 #else 73 #define __rfs(__fpsr) 74 #define __wfs(__fpsr) 75 #endif 76 77 __fenv_static inline int 78 feclearexcept(int __excepts) 79 { 80 fexcept_t __fpsr; 81 82 __rfs(&__fpsr); 83 __fpsr &= ~__excepts; 84 __wfs(__fpsr); 85 return (0); 86 } 87 88 __fenv_static inline int 89 fegetexceptflag(fexcept_t *__flagp, int __excepts) 90 { 91 fexcept_t __fpsr; 92 93 __rfs(&__fpsr); 94 *__flagp = __fpsr & __excepts; 95 return (0); 96 } 97 98 __fenv_static inline int 99 fesetexceptflag(const fexcept_t *__flagp, int __excepts) 100 { 101 fexcept_t __fpsr; 102 103 __rfs(&__fpsr); 104 __fpsr &= ~__excepts; 105 __fpsr |= *__flagp & __excepts; 106 __wfs(__fpsr); 107 return (0); 108 } 109 110 __fenv_static inline int 111 feraiseexcept(int __excepts) 112 { 113 fexcept_t __ex = __excepts; 114 115 fesetexceptflag(&__ex, __excepts); /* XXX */ 116 return (0); 117 } 118 119 __fenv_static inline int 120 fetestexcept(int __excepts) 121 { 122 fexcept_t __fpsr; 123 124 __rfs(&__fpsr); 125 return (__fpsr & __excepts); 126 } 127 128 __fenv_static inline int 129 fegetround(void) 130 { 131 132 /* 133 * Apparently, the rounding mode is specified as part of the 134 * instruction format on ARM, so the dynamic rounding mode is 135 * indeterminate. Some FPUs may differ. 136 */ 137 return (-1); 138 } 139 140 __fenv_static inline int 141 fesetround(int __round) 142 { 143 144 return (-1); 145 } 146 147 __fenv_static inline int 148 fegetenv(fenv_t *__envp) 149 { 150 151 __rfs(__envp); 152 return (0); 153 } 154 155 __fenv_static inline int 156 feholdexcept(fenv_t *__envp) 157 { 158 fenv_t __env; 159 160 __rfs(&__env); 161 *__envp = __env; 162 __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); 163 __wfs(__env); 164 return (0); 165 } 166 167 __fenv_static inline int 168 fesetenv(const fenv_t *__envp) 169 { 170 171 __wfs(*__envp); 172 return (0); 173 } 174 175 __fenv_static inline int 176 feupdateenv(const fenv_t *__envp) 177 { 178 fexcept_t __fpsr; 179 180 __rfs(&__fpsr); 181 __wfs(*__envp); 182 feraiseexcept(__fpsr & FE_ALL_EXCEPT); 183 return (0); 184 } 185 186 #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE) 187 188 /* We currently provide no external definitions of the functions below. */ 189 190 static inline int 191 feenableexcept(int __mask) 192 { 193 fenv_t __old_fpsr, __new_fpsr; 194 195 __rfs(&__old_fpsr); 196 __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT; 197 __wfs(__new_fpsr); 198 return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); 199 } 200 201 static inline int 202 fedisableexcept(int __mask) 203 { 204 fenv_t __old_fpsr, __new_fpsr; 205 206 __rfs(&__old_fpsr); 207 __new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT); 208 __wfs(__new_fpsr); 209 return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); 210 } 211 212 static inline int 213 fegetexcept(void) 214 { 215 fenv_t __fpsr; 216 217 __rfs(&__fpsr); 218 return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT); 219 } 220 221 #endif /* _NETBSD_SOURCE || _GNU_SOURCE */ 222 223 __END_DECLS 224 225 #endif /* !_FENV_H_ */ 226