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