119220bc1SDavid Schultz /*- 210b01832SDavid Schultz * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 319220bc1SDavid Schultz * All rights reserved. 419220bc1SDavid Schultz * 519220bc1SDavid Schultz * Redistribution and use in source and binary forms, with or without 619220bc1SDavid Schultz * modification, are permitted provided that the following conditions 719220bc1SDavid Schultz * are met: 819220bc1SDavid Schultz * 1. Redistributions of source code must retain the above copyright 919220bc1SDavid Schultz * notice, this list of conditions and the following disclaimer. 1019220bc1SDavid Schultz * 2. Redistributions in binary form must reproduce the above copyright 1119220bc1SDavid Schultz * notice, this list of conditions and the following disclaimer in the 1219220bc1SDavid Schultz * documentation and/or other materials provided with the distribution. 1319220bc1SDavid Schultz * 1419220bc1SDavid Schultz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1519220bc1SDavid Schultz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1619220bc1SDavid Schultz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1719220bc1SDavid Schultz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1819220bc1SDavid Schultz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1919220bc1SDavid Schultz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2019220bc1SDavid Schultz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2119220bc1SDavid Schultz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2219220bc1SDavid Schultz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2319220bc1SDavid Schultz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2419220bc1SDavid Schultz * SUCH DAMAGE. 2519220bc1SDavid Schultz * 2619220bc1SDavid Schultz * $FreeBSD$ 2719220bc1SDavid Schultz */ 2819220bc1SDavid Schultz 2919220bc1SDavid Schultz #ifndef _FENV_H_ 3019220bc1SDavid Schultz #define _FENV_H_ 3119220bc1SDavid Schultz 3219220bc1SDavid Schultz #include <sys/_types.h> 3319220bc1SDavid Schultz 34d78e594bSDavid Schultz #ifndef __fenv_static 35d78e594bSDavid Schultz #define __fenv_static static 36d78e594bSDavid Schultz #endif 37d78e594bSDavid Schultz 3819220bc1SDavid Schultz typedef __uint32_t fenv_t; 3919220bc1SDavid Schultz typedef __uint32_t fexcept_t; 4019220bc1SDavid Schultz 4119220bc1SDavid Schultz /* Exception flags */ 4219220bc1SDavid Schultz #define FE_INVALID 0x0001 4319220bc1SDavid Schultz #define FE_DIVBYZERO 0x0002 4419220bc1SDavid Schultz #define FE_OVERFLOW 0x0004 4519220bc1SDavid Schultz #define FE_UNDERFLOW 0x0008 4619220bc1SDavid Schultz #define FE_INEXACT 0x0010 47c9081a6cSAndrew Turner #ifdef __ARM_PCS_VFP 48c9081a6cSAndrew Turner #define FE_DENORMAL 0x0080 49c9081a6cSAndrew Turner #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 50c9081a6cSAndrew Turner FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL) 51c9081a6cSAndrew Turner #else 5219220bc1SDavid Schultz #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 5319220bc1SDavid Schultz FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 54c9081a6cSAndrew Turner #endif 5519220bc1SDavid Schultz 5615d3b4dbSOlivier Houchard /* Rounding modes */ 57*bb6c193eSAndrew Turner #define VFP_FE_TONEAREST 0x00000000 58*bb6c193eSAndrew Turner #define VFP_FE_UPWARD 0x00400000 59*bb6c193eSAndrew Turner #define VFP_FE_DOWNWARD 0x00800000 60*bb6c193eSAndrew Turner #define VFP_FE_TOWARDZERO 0x00c00000 61*bb6c193eSAndrew Turner 62c9081a6cSAndrew Turner #ifdef __ARM_PCS_VFP 63*bb6c193eSAndrew Turner #define FE_TONEAREST VFP_FE_TONEAREST 64*bb6c193eSAndrew Turner #define FE_UPWARD VFP_FE_UPWARD 65*bb6c193eSAndrew Turner #define FE_DOWNWARD VFP_FE_DOWNWARD 66*bb6c193eSAndrew Turner #define FE_TOWARDZERO VFP_FE_TOWARDZERO 67c9081a6cSAndrew Turner #else 6815d3b4dbSOlivier Houchard #define FE_TONEAREST 0x0000 6915d3b4dbSOlivier Houchard #define FE_TOWARDZERO 0x0001 7015d3b4dbSOlivier Houchard #define FE_UPWARD 0x0002 7115d3b4dbSOlivier Houchard #define FE_DOWNWARD 0x0003 72c9081a6cSAndrew Turner #endif 7315d3b4dbSOlivier Houchard #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 7415d3b4dbSOlivier Houchard FE_UPWARD | FE_TOWARDZERO) 7519220bc1SDavid Schultz __BEGIN_DECLS 7619220bc1SDavid Schultz 7719220bc1SDavid Schultz /* Default floating-point environment */ 7819220bc1SDavid Schultz extern const fenv_t __fe_dfl_env; 7919220bc1SDavid Schultz #define FE_DFL_ENV (&__fe_dfl_env) 8019220bc1SDavid Schultz 8119220bc1SDavid Schultz /* We need to be able to map status flag positions to mask flag positions */ 82c9081a6cSAndrew Turner #ifndef __ARM_PCS_VFP 8319220bc1SDavid Schultz #define _FPUSW_SHIFT 16 8419220bc1SDavid Schultz #define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) 85c9081a6cSAndrew Turner #endif 8619220bc1SDavid Schultz 87c9081a6cSAndrew Turner #ifndef __ARM_PCS_VFP 887082a2cfSDavid Schultz 897082a2cfSDavid Schultz int feclearexcept(int __excepts); 907082a2cfSDavid Schultz int fegetexceptflag(fexcept_t *__flagp, int __excepts); 917082a2cfSDavid Schultz int fesetexceptflag(const fexcept_t *__flagp, int __excepts); 927082a2cfSDavid Schultz int feraiseexcept(int __excepts); 937082a2cfSDavid Schultz int fetestexcept(int __excepts); 947082a2cfSDavid Schultz int fegetround(void); 957082a2cfSDavid Schultz int fesetround(int __round); 967082a2cfSDavid Schultz int fegetenv(fenv_t *__envp); 977082a2cfSDavid Schultz int feholdexcept(fenv_t *__envp); 987082a2cfSDavid Schultz int fesetenv(const fenv_t *__envp); 997082a2cfSDavid Schultz int feupdateenv(const fenv_t *__envp); 100*bb6c193eSAndrew Turner #if __BSD_VISIBLE 101*bb6c193eSAndrew Turner int feenableexcept(int __mask); 102*bb6c193eSAndrew Turner int fedisableexcept(int __mask); 103*bb6c193eSAndrew Turner int fegetexcept(void); 104*bb6c193eSAndrew Turner #endif 1057bde21b1SDavid Schultz 106c9081a6cSAndrew Turner #else /* __ARM_PCS_VFP */ 1077bde21b1SDavid Schultz 108c9081a6cSAndrew Turner #define vmrs_fpscr(__r) __asm __volatile("vmrs %0, fpscr" : "=&r"(__r)) 109c9081a6cSAndrew Turner #define vmsr_fpscr(__r) __asm __volatile("vmsr fpscr, %0" : : "r"(__r)) 11019220bc1SDavid Schultz 111a541d15cSAndrew Turner #define _FPU_MASK_SHIFT 8 112a541d15cSAndrew Turner 113d78e594bSDavid Schultz __fenv_static inline int 11419220bc1SDavid Schultz feclearexcept(int __excepts) 11519220bc1SDavid Schultz { 11619220bc1SDavid Schultz fexcept_t __fpsr; 11719220bc1SDavid Schultz 118c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 11919220bc1SDavid Schultz __fpsr &= ~__excepts; 120c9081a6cSAndrew Turner vmsr_fpscr(__fpsr); 12119220bc1SDavid Schultz return (0); 12219220bc1SDavid Schultz } 12319220bc1SDavid Schultz 124d78e594bSDavid Schultz __fenv_static inline int 12519220bc1SDavid Schultz fegetexceptflag(fexcept_t *__flagp, int __excepts) 12619220bc1SDavid Schultz { 12719220bc1SDavid Schultz fexcept_t __fpsr; 12819220bc1SDavid Schultz 129c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 13019220bc1SDavid Schultz *__flagp = __fpsr & __excepts; 13119220bc1SDavid Schultz return (0); 13219220bc1SDavid Schultz } 13319220bc1SDavid Schultz 134d78e594bSDavid Schultz __fenv_static inline int 13519220bc1SDavid Schultz fesetexceptflag(const fexcept_t *__flagp, int __excepts) 13619220bc1SDavid Schultz { 13719220bc1SDavid Schultz fexcept_t __fpsr; 13819220bc1SDavid Schultz 139c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 14019220bc1SDavid Schultz __fpsr &= ~__excepts; 14119220bc1SDavid Schultz __fpsr |= *__flagp & __excepts; 142c9081a6cSAndrew Turner vmsr_fpscr(__fpsr); 14319220bc1SDavid Schultz return (0); 14419220bc1SDavid Schultz } 14519220bc1SDavid Schultz 146d78e594bSDavid Schultz __fenv_static inline int 14719220bc1SDavid Schultz feraiseexcept(int __excepts) 14819220bc1SDavid Schultz { 14919220bc1SDavid Schultz fexcept_t __ex = __excepts; 15019220bc1SDavid Schultz 15119220bc1SDavid Schultz fesetexceptflag(&__ex, __excepts); /* XXX */ 15219220bc1SDavid Schultz return (0); 15319220bc1SDavid Schultz } 15419220bc1SDavid Schultz 155d78e594bSDavid Schultz __fenv_static inline int 15619220bc1SDavid Schultz fetestexcept(int __excepts) 15719220bc1SDavid Schultz { 15819220bc1SDavid Schultz fexcept_t __fpsr; 15919220bc1SDavid Schultz 160c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 16119220bc1SDavid Schultz return (__fpsr & __excepts); 16219220bc1SDavid Schultz } 16319220bc1SDavid Schultz 164d78e594bSDavid Schultz __fenv_static inline int 16519220bc1SDavid Schultz fegetround(void) 16619220bc1SDavid Schultz { 167c9081a6cSAndrew Turner fenv_t __fpsr; 16819220bc1SDavid Schultz 169c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 170c9081a6cSAndrew Turner return (__fpsr & _ROUND_MASK); 17119220bc1SDavid Schultz } 17219220bc1SDavid Schultz 173d78e594bSDavid Schultz __fenv_static inline int 17419220bc1SDavid Schultz fesetround(int __round) 17519220bc1SDavid Schultz { 176c9081a6cSAndrew Turner fenv_t __fpsr; 17719220bc1SDavid Schultz 178c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 179c9081a6cSAndrew Turner __fpsr &= ~(_ROUND_MASK); 180c9081a6cSAndrew Turner __fpsr |= __round; 181c9081a6cSAndrew Turner vmsr_fpscr(__fpsr); 182c9081a6cSAndrew Turner return (0); 18319220bc1SDavid Schultz } 18419220bc1SDavid Schultz 185d78e594bSDavid Schultz __fenv_static inline int 18619220bc1SDavid Schultz fegetenv(fenv_t *__envp) 18719220bc1SDavid Schultz { 18819220bc1SDavid Schultz 189c9081a6cSAndrew Turner vmrs_fpscr(*__envp); 19019220bc1SDavid Schultz return (0); 19119220bc1SDavid Schultz } 19219220bc1SDavid Schultz 193d78e594bSDavid Schultz __fenv_static inline int 19419220bc1SDavid Schultz feholdexcept(fenv_t *__envp) 19519220bc1SDavid Schultz { 19619220bc1SDavid Schultz fenv_t __env; 19719220bc1SDavid Schultz 198c9081a6cSAndrew Turner vmrs_fpscr(__env); 19919220bc1SDavid Schultz *__envp = __env; 200c9081a6cSAndrew Turner __env &= ~(FE_ALL_EXCEPT); 201c9081a6cSAndrew Turner vmsr_fpscr(__env); 20219220bc1SDavid Schultz return (0); 20319220bc1SDavid Schultz } 20419220bc1SDavid Schultz 205d78e594bSDavid Schultz __fenv_static inline int 20619220bc1SDavid Schultz fesetenv(const fenv_t *__envp) 20719220bc1SDavid Schultz { 20819220bc1SDavid Schultz 209c9081a6cSAndrew Turner vmsr_fpscr(*__envp); 21019220bc1SDavid Schultz return (0); 21119220bc1SDavid Schultz } 21219220bc1SDavid Schultz 213d78e594bSDavid Schultz __fenv_static inline int 21419220bc1SDavid Schultz feupdateenv(const fenv_t *__envp) 21519220bc1SDavid Schultz { 21619220bc1SDavid Schultz fexcept_t __fpsr; 21719220bc1SDavid Schultz 218c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 219c9081a6cSAndrew Turner vmsr_fpscr(*__envp); 22019220bc1SDavid Schultz feraiseexcept(__fpsr & FE_ALL_EXCEPT); 22119220bc1SDavid Schultz return (0); 22219220bc1SDavid Schultz } 22319220bc1SDavid Schultz 22419220bc1SDavid Schultz #if __BSD_VISIBLE 22519220bc1SDavid Schultz 226d78e594bSDavid Schultz /* We currently provide no external definitions of the functions below. */ 227d78e594bSDavid Schultz 228a541d15cSAndrew Turner __fenv_static inline int 22910b01832SDavid Schultz feenableexcept(int __mask) 23019220bc1SDavid Schultz { 23110b01832SDavid Schultz fenv_t __old_fpsr, __new_fpsr; 23219220bc1SDavid Schultz 233c9081a6cSAndrew Turner vmrs_fpscr(__old_fpsr); 234a541d15cSAndrew Turner __new_fpsr = __old_fpsr | 235a541d15cSAndrew Turner ((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT); 236c9081a6cSAndrew Turner vmsr_fpscr(__new_fpsr); 237a541d15cSAndrew Turner return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT); 23819220bc1SDavid Schultz } 23919220bc1SDavid Schultz 240a541d15cSAndrew Turner __fenv_static inline int 24110b01832SDavid Schultz fedisableexcept(int __mask) 24210b01832SDavid Schultz { 24310b01832SDavid Schultz fenv_t __old_fpsr, __new_fpsr; 24410b01832SDavid Schultz 245c9081a6cSAndrew Turner vmrs_fpscr(__old_fpsr); 246a541d15cSAndrew Turner __new_fpsr = __old_fpsr & 247a541d15cSAndrew Turner ~((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT); 248c9081a6cSAndrew Turner vmsr_fpscr(__new_fpsr); 249a541d15cSAndrew Turner return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT); 25010b01832SDavid Schultz } 25110b01832SDavid Schultz 252a541d15cSAndrew Turner __fenv_static inline int 25310b01832SDavid Schultz fegetexcept(void) 25419220bc1SDavid Schultz { 25519220bc1SDavid Schultz fenv_t __fpsr; 25619220bc1SDavid Schultz 257c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 258c9081a6cSAndrew Turner return (__fpsr & FE_ALL_EXCEPT); 25919220bc1SDavid Schultz } 26019220bc1SDavid Schultz 26119220bc1SDavid Schultz #endif /* __BSD_VISIBLE */ 26219220bc1SDavid Schultz 263c9081a6cSAndrew Turner #endif /* __ARM_PCS_VFP */ 2647bde21b1SDavid Schultz 26519220bc1SDavid Schultz __END_DECLS 26619220bc1SDavid Schultz 26719220bc1SDavid Schultz #endif /* !_FENV_H_ */ 268