1 /* $NetBSD: fenv.h,v 1.4 2017/03/22 23:11:09 chs 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 /* Exception flags */ 37 #define FE_INEXACT 0x0004 38 #define FE_UNDERFLOW 0x0008 39 #define FE_OVERFLOW 0x0010 40 #define FE_DIVBYZERO 0x0020 41 #define FE_INVALID 0x0040 42 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 43 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 44 45 /* Rounding modes */ 46 #define FE_TONEAREST 0x0000 47 #define FE_TOWARDZERO 0x0001 48 #define FE_UPWARD 0x0002 49 #define FE_DOWNWARD 0x0003 50 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 51 FE_UPWARD | FE_TOWARDZERO) 52 53 #ifndef __mips_soft_float 54 55 #ifndef __fenv_static 56 #define __fenv_static static 57 #endif 58 59 typedef uint32_t fpu_control_t __attribute__((__mode__(__SI__))); 60 typedef fpu_control_t fenv_t; 61 typedef fpu_control_t fexcept_t; 62 63 __BEGIN_DECLS 64 65 /* Default floating-point environment */ 66 extern const fenv_t __fe_dfl_env; 67 #define FE_DFL_ENV (&__fe_dfl_env) 68 69 /* We need to be able to map status flag positions to mask flag positions */ 70 #define _ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT) 71 #define _ENABLE_SHIFT 5 72 73 static inline fpu_control_t 74 __rfs(void) 75 { 76 fpu_control_t __fpsr; 77 78 __asm __volatile("cfc1 %0,$31" : "=r" (__fpsr)); 79 return __fpsr; 80 } 81 82 static inline void 83 __wfs(fpu_control_t __fpsr) 84 { 85 86 __asm __volatile("ctc1 %0,$31" : : "r" (__fpsr)); 87 } 88 89 __fenv_static inline int 90 feclearexcept(int __excepts) 91 { 92 fexcept_t __fpsr; 93 94 __excepts &= FE_ALL_EXCEPT; 95 __fpsr = __rfs(); 96 __fpsr &= ~(__excepts | (__excepts << _ENABLE_SHIFT)); 97 __wfs(__fpsr); 98 return 0; 99 } 100 101 __fenv_static inline int 102 fegetexceptflag(fexcept_t *__flagp, int __excepts) 103 { 104 fexcept_t __fpsr; 105 106 __fpsr = __rfs(); 107 *__flagp = __fpsr & __excepts; 108 return (0); 109 } 110 111 __fenv_static inline int 112 fesetexceptflag(const fexcept_t *__flagp, int __excepts) 113 { 114 fexcept_t __fpsr; 115 116 __fpsr = __rfs(); 117 __fpsr &= ~__excepts; 118 __fpsr |= *__flagp & __excepts; 119 __wfs(__fpsr); 120 return (0); 121 } 122 123 __fenv_static inline int 124 feraiseexcept(int __excepts) 125 { 126 fexcept_t __ex = __excepts; 127 128 fesetexceptflag(&__ex, __excepts); /* XXX */ 129 return (0); 130 } 131 132 __fenv_static inline int 133 fetestexcept(int __excepts) 134 { 135 fexcept_t __fpsr; 136 137 __fpsr = __rfs(); 138 return (__fpsr & __excepts); 139 } 140 141 __fenv_static inline int 142 fegetround(void) 143 { 144 fexcept_t __fpsr; 145 146 __fpsr = __rfs(); 147 return __fpsr & _ROUND_MASK; 148 } 149 150 __fenv_static inline int 151 fesetround(int __round) 152 { 153 fexcept_t __fpsr; 154 155 if (__round & ~_ROUND_MASK) 156 return 1; 157 __fpsr = __rfs(); 158 __fpsr &= ~_ROUND_MASK; 159 __fpsr |= __round; 160 __wfs(__fpsr); 161 162 return 0; 163 } 164 165 __fenv_static inline int 166 fegetenv(fenv_t *__envp) 167 { 168 169 *__envp = __rfs(); 170 return (0); 171 } 172 173 __fenv_static inline int 174 feholdexcept(fenv_t *__envp) 175 { 176 fenv_t __env; 177 178 __env = __rfs(); 179 *__envp = __env; 180 __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); 181 __wfs(__env); 182 return (0); 183 } 184 185 __fenv_static inline int 186 fesetenv(const fenv_t *__envp) 187 { 188 189 __wfs(*__envp); 190 return (0); 191 } 192 193 __fenv_static inline int 194 feupdateenv(const fenv_t *__envp) 195 { 196 fexcept_t __fpsr; 197 198 __fpsr = __rfs(); 199 __wfs(*__envp); 200 feraiseexcept(__fpsr & FE_ALL_EXCEPT); 201 return (0); 202 } 203 204 #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE) 205 206 __fenv_static inline int 207 feenableexcept(int __excepts) 208 { 209 fenv_t __old_fpsr, __new_fpsr; 210 211 __new_fpsr = __rfs(); 212 __old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT; 213 __excepts &= FE_ALL_EXCEPT; 214 __new_fpsr |= __excepts << _ENABLE_SHIFT; 215 __wfs(__new_fpsr); 216 return __old_fpsr; 217 } 218 219 __fenv_static inline int 220 fedisableexcept(int __excepts) 221 { 222 fenv_t __old_fpsr, __new_fpsr; 223 224 __new_fpsr = __rfs(); 225 __old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT; 226 __excepts &= FE_ALL_EXCEPT; 227 __new_fpsr &= ~(__excepts << _ENABLE_SHIFT); 228 __wfs(__new_fpsr); 229 return __old_fpsr; 230 } 231 232 __fenv_static inline int 233 fegetexcept(void) 234 { 235 fenv_t __fpsr; 236 237 __fpsr = __rfs(); 238 return ((__fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT); 239 } 240 241 #endif /* _NETBSD_SOURCE || _GNU_SOURCE */ 242 243 __END_DECLS 244 245 #endif /* __mips_soft_float */ 246 247 #endif /* !_FENV_H_ */ 248