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 4719220bc1SDavid Schultz #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 4819220bc1SDavid Schultz FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 4919220bc1SDavid Schultz 5015d3b4dbSOlivier Houchard /* Rounding modes */ 5115d3b4dbSOlivier Houchard #define FE_TONEAREST 0x0000 5215d3b4dbSOlivier Houchard #define FE_TOWARDZERO 0x0001 5315d3b4dbSOlivier Houchard #define FE_UPWARD 0x0002 5415d3b4dbSOlivier Houchard #define FE_DOWNWARD 0x0003 5515d3b4dbSOlivier Houchard #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 5615d3b4dbSOlivier Houchard FE_UPWARD | FE_TOWARDZERO) 5719220bc1SDavid Schultz __BEGIN_DECLS 5819220bc1SDavid Schultz 5919220bc1SDavid Schultz /* Default floating-point environment */ 6019220bc1SDavid Schultz extern const fenv_t __fe_dfl_env; 6119220bc1SDavid Schultz #define FE_DFL_ENV (&__fe_dfl_env) 6219220bc1SDavid Schultz 6319220bc1SDavid Schultz /* We need to be able to map status flag positions to mask flag positions */ 6419220bc1SDavid Schultz #define _FPUSW_SHIFT 16 6519220bc1SDavid Schultz #define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) 6619220bc1SDavid Schultz 677bde21b1SDavid Schultz #ifndef ARM_HARD_FLOAT 68*7082a2cfSDavid Schultz 69*7082a2cfSDavid Schultz int feclearexcept(int __excepts); 70*7082a2cfSDavid Schultz int fegetexceptflag(fexcept_t *__flagp, int __excepts); 71*7082a2cfSDavid Schultz int fesetexceptflag(const fexcept_t *__flagp, int __excepts); 72*7082a2cfSDavid Schultz int feraiseexcept(int __excepts); 73*7082a2cfSDavid Schultz int fetestexcept(int __excepts); 74*7082a2cfSDavid Schultz int fegetround(void); 75*7082a2cfSDavid Schultz int fesetround(int __round); 76*7082a2cfSDavid Schultz int fegetenv(fenv_t *__envp); 77*7082a2cfSDavid Schultz int feholdexcept(fenv_t *__envp); 78*7082a2cfSDavid Schultz int fesetenv(const fenv_t *__envp); 79*7082a2cfSDavid Schultz int feupdateenv(const fenv_t *__envp); 807bde21b1SDavid Schultz 817bde21b1SDavid Schultz #else /* ARM_HARD_FLOAT */ 827bde21b1SDavid Schultz 83f365db00SDavid Schultz #define __rfs(__fpsr) __asm __volatile("rfs %0" : "=r" (*(__fpsr))) 8460b22cf1SOlivier Houchard #define __wfs(__fpsr) __asm __volatile("wfs %0" : : "r" (__fpsr)) 8519220bc1SDavid Schultz 86d78e594bSDavid Schultz __fenv_static inline int 8719220bc1SDavid Schultz feclearexcept(int __excepts) 8819220bc1SDavid Schultz { 8919220bc1SDavid Schultz fexcept_t __fpsr; 9019220bc1SDavid Schultz 9119220bc1SDavid Schultz __rfs(&__fpsr); 9219220bc1SDavid Schultz __fpsr &= ~__excepts; 9319220bc1SDavid Schultz __wfs(__fpsr); 9419220bc1SDavid Schultz return (0); 9519220bc1SDavid Schultz } 9619220bc1SDavid Schultz 97d78e594bSDavid Schultz __fenv_static inline int 9819220bc1SDavid Schultz fegetexceptflag(fexcept_t *__flagp, int __excepts) 9919220bc1SDavid Schultz { 10019220bc1SDavid Schultz fexcept_t __fpsr; 10119220bc1SDavid Schultz 10219220bc1SDavid Schultz __rfs(&__fpsr); 10319220bc1SDavid Schultz *__flagp = __fpsr & __excepts; 10419220bc1SDavid Schultz return (0); 10519220bc1SDavid Schultz } 10619220bc1SDavid Schultz 107d78e594bSDavid Schultz __fenv_static inline int 10819220bc1SDavid Schultz fesetexceptflag(const fexcept_t *__flagp, int __excepts) 10919220bc1SDavid Schultz { 11019220bc1SDavid Schultz fexcept_t __fpsr; 11119220bc1SDavid Schultz 11219220bc1SDavid Schultz __rfs(&__fpsr); 11319220bc1SDavid Schultz __fpsr &= ~__excepts; 11419220bc1SDavid Schultz __fpsr |= *__flagp & __excepts; 11519220bc1SDavid Schultz __wfs(__fpsr); 11619220bc1SDavid Schultz return (0); 11719220bc1SDavid Schultz } 11819220bc1SDavid Schultz 119d78e594bSDavid Schultz __fenv_static inline int 12019220bc1SDavid Schultz feraiseexcept(int __excepts) 12119220bc1SDavid Schultz { 12219220bc1SDavid Schultz fexcept_t __ex = __excepts; 12319220bc1SDavid Schultz 12419220bc1SDavid Schultz fesetexceptflag(&__ex, __excepts); /* XXX */ 12519220bc1SDavid Schultz return (0); 12619220bc1SDavid Schultz } 12719220bc1SDavid Schultz 128d78e594bSDavid Schultz __fenv_static inline int 12919220bc1SDavid Schultz fetestexcept(int __excepts) 13019220bc1SDavid Schultz { 13119220bc1SDavid Schultz fexcept_t __fpsr; 13219220bc1SDavid Schultz 13319220bc1SDavid Schultz __rfs(&__fpsr); 13419220bc1SDavid Schultz return (__fpsr & __excepts); 13519220bc1SDavid Schultz } 13619220bc1SDavid Schultz 137d78e594bSDavid Schultz __fenv_static inline int 13819220bc1SDavid Schultz fegetround(void) 13919220bc1SDavid Schultz { 14019220bc1SDavid Schultz 14119220bc1SDavid Schultz /* 14219220bc1SDavid Schultz * Apparently, the rounding mode is specified as part of the 14319220bc1SDavid Schultz * instruction format on ARM, so the dynamic rounding mode is 14419220bc1SDavid Schultz * indeterminate. Some FPUs may differ. 14519220bc1SDavid Schultz */ 14619220bc1SDavid Schultz return (-1); 14719220bc1SDavid Schultz } 14819220bc1SDavid Schultz 149d78e594bSDavid Schultz __fenv_static inline int 15019220bc1SDavid Schultz fesetround(int __round) 15119220bc1SDavid Schultz { 15219220bc1SDavid Schultz 15319220bc1SDavid Schultz return (-1); 15419220bc1SDavid Schultz } 15519220bc1SDavid Schultz 156d78e594bSDavid Schultz __fenv_static inline int 15719220bc1SDavid Schultz fegetenv(fenv_t *__envp) 15819220bc1SDavid Schultz { 15919220bc1SDavid Schultz 16019220bc1SDavid Schultz __rfs(__envp); 16119220bc1SDavid Schultz return (0); 16219220bc1SDavid Schultz } 16319220bc1SDavid Schultz 164d78e594bSDavid Schultz __fenv_static inline int 16519220bc1SDavid Schultz feholdexcept(fenv_t *__envp) 16619220bc1SDavid Schultz { 16719220bc1SDavid Schultz fenv_t __env; 16819220bc1SDavid Schultz 16919220bc1SDavid Schultz __rfs(&__env); 17019220bc1SDavid Schultz *__envp = __env; 17119220bc1SDavid Schultz __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); 17219220bc1SDavid Schultz __wfs(__env); 17319220bc1SDavid Schultz return (0); 17419220bc1SDavid Schultz } 17519220bc1SDavid Schultz 176d78e594bSDavid Schultz __fenv_static inline int 17719220bc1SDavid Schultz fesetenv(const fenv_t *__envp) 17819220bc1SDavid Schultz { 17919220bc1SDavid Schultz 18019220bc1SDavid Schultz __wfs(*__envp); 18119220bc1SDavid Schultz return (0); 18219220bc1SDavid Schultz } 18319220bc1SDavid Schultz 184d78e594bSDavid Schultz __fenv_static inline int 18519220bc1SDavid Schultz feupdateenv(const fenv_t *__envp) 18619220bc1SDavid Schultz { 18719220bc1SDavid Schultz fexcept_t __fpsr; 18819220bc1SDavid Schultz 18919220bc1SDavid Schultz __rfs(&__fpsr); 19019220bc1SDavid Schultz __wfs(*__envp); 19119220bc1SDavid Schultz feraiseexcept(__fpsr & FE_ALL_EXCEPT); 19219220bc1SDavid Schultz return (0); 19319220bc1SDavid Schultz } 19419220bc1SDavid Schultz 19519220bc1SDavid Schultz #if __BSD_VISIBLE 19619220bc1SDavid Schultz 197d78e594bSDavid Schultz /* We currently provide no external definitions of the functions below. */ 198d78e594bSDavid Schultz 199d78e594bSDavid Schultz static inline int 20010b01832SDavid Schultz feenableexcept(int __mask) 20119220bc1SDavid Schultz { 20210b01832SDavid Schultz fenv_t __old_fpsr, __new_fpsr; 20319220bc1SDavid Schultz 20410b01832SDavid Schultz __rfs(&__old_fpsr); 20510b01832SDavid Schultz __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT; 20610b01832SDavid Schultz __wfs(__new_fpsr); 20710b01832SDavid Schultz return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); 20819220bc1SDavid Schultz } 20919220bc1SDavid Schultz 210d78e594bSDavid Schultz static inline int 21110b01832SDavid Schultz fedisableexcept(int __mask) 21210b01832SDavid Schultz { 21310b01832SDavid Schultz fenv_t __old_fpsr, __new_fpsr; 21410b01832SDavid Schultz 21510b01832SDavid Schultz __rfs(&__old_fpsr); 21610b01832SDavid Schultz __new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT); 21710b01832SDavid Schultz __wfs(__new_fpsr); 21810b01832SDavid Schultz return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); 21910b01832SDavid Schultz } 22010b01832SDavid Schultz 221d78e594bSDavid Schultz static inline int 22210b01832SDavid Schultz fegetexcept(void) 22319220bc1SDavid Schultz { 22419220bc1SDavid Schultz fenv_t __fpsr; 22519220bc1SDavid Schultz 22619220bc1SDavid Schultz __rfs(&__fpsr); 22719220bc1SDavid Schultz return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT); 22819220bc1SDavid Schultz } 22919220bc1SDavid Schultz 23019220bc1SDavid Schultz #endif /* __BSD_VISIBLE */ 23119220bc1SDavid Schultz 2327bde21b1SDavid Schultz #endif /* ARM_HARD_FLOAT */ 2337bde21b1SDavid Schultz 23419220bc1SDavid Schultz __END_DECLS 23519220bc1SDavid Schultz 23619220bc1SDavid Schultz #endif /* !_FENV_H_ */ 237