1/*- 2 * Copyright (c) 2004-2005 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: releng/11.0/lib/msun/arm/fenv.h 263210 2014-03-15 21:58:07Z andrew $ 27 */ 28 29#ifndef _FENV_H_ 30#define _FENV_H_ 31 32#include <sys/_types.h> 33 34#ifndef __fenv_static 35#define __fenv_static static 36#endif 37 38typedef __uint32_t fenv_t; 39typedef __uint32_t fexcept_t; 40 41/* Exception flags */ 42#define FE_INVALID 0x0001 43#define FE_DIVBYZERO 0x0002 44#define FE_OVERFLOW 0x0004 45#define FE_UNDERFLOW 0x0008 46#define FE_INEXACT 0x0010 47#ifdef __ARM_PCS_VFP 48#define FE_DENORMAL 0x0080 49#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 50 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL) 51#else 52#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 53 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 54#endif 55 56/* Rounding modes */ 57#define VFP_FE_TONEAREST 0x00000000 58#define VFP_FE_UPWARD 0x00400000 59#define VFP_FE_DOWNWARD 0x00800000 60#define VFP_FE_TOWARDZERO 0x00c00000 61 62#ifdef __ARM_PCS_VFP 63#define FE_TONEAREST VFP_FE_TONEAREST 64#define FE_UPWARD VFP_FE_UPWARD 65#define FE_DOWNWARD VFP_FE_DOWNWARD 66#define FE_TOWARDZERO VFP_FE_TOWARDZERO 67#else 68#define FE_TONEAREST 0x0000 69#define FE_TOWARDZERO 0x0001 70#define FE_UPWARD 0x0002 71#define FE_DOWNWARD 0x0003 72#endif 73#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 74 FE_UPWARD | FE_TOWARDZERO) 75__BEGIN_DECLS 76 77/* Default floating-point environment */ 78extern const fenv_t __fe_dfl_env; 79#define FE_DFL_ENV (&__fe_dfl_env) 80 81/* We need to be able to map status flag positions to mask flag positions */ 82#ifndef __ARM_PCS_VFP 83#define _FPUSW_SHIFT 16 84#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) 85#endif 86 87#ifndef __ARM_PCS_VFP 88 89int feclearexcept(int __excepts); 90int fegetexceptflag(fexcept_t *__flagp, int __excepts); 91int fesetexceptflag(const fexcept_t *__flagp, int __excepts); 92int feraiseexcept(int __excepts); 93int fetestexcept(int __excepts); 94int fegetround(void); 95int fesetround(int __round); 96int fegetenv(fenv_t *__envp); 97int feholdexcept(fenv_t *__envp); 98int fesetenv(const fenv_t *__envp); 99int feupdateenv(const fenv_t *__envp); 100#if __BSD_VISIBLE 101int feenableexcept(int __mask); 102int fedisableexcept(int __mask); 103int fegetexcept(void); 104#endif 105 106#else /* __ARM_PCS_VFP */ 107 108#define vmrs_fpscr(__r) __asm __volatile("vmrs %0, fpscr" : "=&r"(__r)) 109#define vmsr_fpscr(__r) __asm __volatile("vmsr fpscr, %0" : : "r"(__r)) 110 111#define _FPU_MASK_SHIFT 8 112 113__fenv_static inline int 114feclearexcept(int __excepts) 115{ 116 fexcept_t __fpsr; 117 118 vmrs_fpscr(__fpsr); 119 __fpsr &= ~__excepts; 120 vmsr_fpscr(__fpsr); 121 return (0); 122} 123 124__fenv_static inline int 125fegetexceptflag(fexcept_t *__flagp, int __excepts) 126{ 127 fexcept_t __fpsr; 128 129 vmrs_fpscr(__fpsr); 130 *__flagp = __fpsr & __excepts; 131 return (0); 132} 133 134__fenv_static inline int 135fesetexceptflag(const fexcept_t *__flagp, int __excepts) 136{ 137 fexcept_t __fpsr; 138 139 vmrs_fpscr(__fpsr); 140 __fpsr &= ~__excepts; 141 __fpsr |= *__flagp & __excepts; 142 vmsr_fpscr(__fpsr); 143 return (0); 144} 145 146__fenv_static inline int 147feraiseexcept(int __excepts) 148{ 149 fexcept_t __ex = __excepts; 150 151 fesetexceptflag(&__ex, __excepts); /* XXX */ 152 return (0); 153} 154 155__fenv_static inline int 156fetestexcept(int __excepts) 157{ 158 fexcept_t __fpsr; 159 160 vmrs_fpscr(__fpsr); 161 return (__fpsr & __excepts); 162} 163 164__fenv_static inline int 165fegetround(void) 166{ 167 fenv_t __fpsr; 168 169 vmrs_fpscr(__fpsr); 170 return (__fpsr & _ROUND_MASK); 171} 172 173__fenv_static inline int 174fesetround(int __round) 175{ 176 fenv_t __fpsr; 177 178 vmrs_fpscr(__fpsr); 179 __fpsr &= ~(_ROUND_MASK); 180 __fpsr |= __round; 181 vmsr_fpscr(__fpsr); 182 return (0); 183} 184 185__fenv_static inline int 186fegetenv(fenv_t *__envp) 187{ 188 189 vmrs_fpscr(*__envp); 190 return (0); 191} 192 193__fenv_static inline int 194feholdexcept(fenv_t *__envp) 195{ 196 fenv_t __env; 197 198 vmrs_fpscr(__env); 199 *__envp = __env; 200 __env &= ~(FE_ALL_EXCEPT); 201 vmsr_fpscr(__env); 202 return (0); 203} 204 205__fenv_static inline int 206fesetenv(const fenv_t *__envp) 207{ 208 209 vmsr_fpscr(*__envp); 210 return (0); 211} 212 213__fenv_static inline int 214feupdateenv(const fenv_t *__envp) 215{ 216 fexcept_t __fpsr; 217 218 vmrs_fpscr(__fpsr); 219 vmsr_fpscr(*__envp); 220 feraiseexcept(__fpsr & FE_ALL_EXCEPT); 221 return (0); 222} 223 224#if __BSD_VISIBLE 225 226/* We currently provide no external definitions of the functions below. */ 227 228__fenv_static inline int 229feenableexcept(int __mask) 230{ 231 fenv_t __old_fpsr, __new_fpsr; 232 233 vmrs_fpscr(__old_fpsr); 234 __new_fpsr = __old_fpsr | 235 ((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT); 236 vmsr_fpscr(__new_fpsr); 237 return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT); 238} 239 240__fenv_static inline int 241fedisableexcept(int __mask) 242{ 243 fenv_t __old_fpsr, __new_fpsr; 244 245 vmrs_fpscr(__old_fpsr); 246 __new_fpsr = __old_fpsr & 247 ~((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT); 248 vmsr_fpscr(__new_fpsr); 249 return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT); 250} 251 252__fenv_static inline int 253fegetexcept(void) 254{ 255 fenv_t __fpsr; 256 257 vmrs_fpscr(__fpsr); 258 return (__fpsr & FE_ALL_EXCEPT); 259} 260 261#endif /* __BSD_VISIBLE */ 262 263#endif /* __ARM_PCS_VFP */ 264 265__END_DECLS 266 267#endif /* !_FENV_H_ */ 268