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