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 67*7bde21b1SDavid Schultz #ifndef ARM_HARD_FLOAT 68*7bde21b1SDavid Schultz /* 69*7bde21b1SDavid Schultz * The following macros map between the softfloat emulator's flags and 70*7bde21b1SDavid Schultz * the hardware's FPSR. The hardware this file was written for doesn't 71*7bde21b1SDavid Schultz * have rounding control bits, so we stick those in the system ID byte. 72*7bde21b1SDavid Schultz */ 73*7bde21b1SDavid Schultz #define __set_env(env, flags, mask, rnd) env = ((flags) \ 74*7bde21b1SDavid Schultz | (mask)<<_FPUSW_SHIFT \ 75*7bde21b1SDavid Schultz | (rnd) << 24) 76*7bde21b1SDavid Schultz #define __env_flags(env) ((env) & FE_ALL_EXCEPT) 77*7bde21b1SDavid Schultz #define __env_mask(env) (((env) >> _FPUSW_SHIFT) \ 78*7bde21b1SDavid Schultz & FE_ALL_EXCEPT) 79*7bde21b1SDavid Schultz #define __env_round(env) (((env) >> 24) & _ROUND_MASK) 80*7bde21b1SDavid Schultz #include <fenv-softfloat.h> 81*7bde21b1SDavid Schultz 82*7bde21b1SDavid Schultz #else /* ARM_HARD_FLOAT */ 83*7bde21b1SDavid Schultz 84f365db00SDavid Schultz #define __rfs(__fpsr) __asm __volatile("rfs %0" : "=r" (*(__fpsr))) 8560b22cf1SOlivier Houchard #define __wfs(__fpsr) __asm __volatile("wfs %0" : : "r" (__fpsr)) 8619220bc1SDavid Schultz 87d78e594bSDavid Schultz __fenv_static inline int 8819220bc1SDavid Schultz feclearexcept(int __excepts) 8919220bc1SDavid Schultz { 9019220bc1SDavid Schultz fexcept_t __fpsr; 9119220bc1SDavid Schultz 9219220bc1SDavid Schultz __rfs(&__fpsr); 9319220bc1SDavid Schultz __fpsr &= ~__excepts; 9419220bc1SDavid Schultz __wfs(__fpsr); 9519220bc1SDavid Schultz return (0); 9619220bc1SDavid Schultz } 9719220bc1SDavid Schultz 98d78e594bSDavid Schultz __fenv_static inline int 9919220bc1SDavid Schultz fegetexceptflag(fexcept_t *__flagp, int __excepts) 10019220bc1SDavid Schultz { 10119220bc1SDavid Schultz fexcept_t __fpsr; 10219220bc1SDavid Schultz 10319220bc1SDavid Schultz __rfs(&__fpsr); 10419220bc1SDavid Schultz *__flagp = __fpsr & __excepts; 10519220bc1SDavid Schultz return (0); 10619220bc1SDavid Schultz } 10719220bc1SDavid Schultz 108d78e594bSDavid Schultz __fenv_static inline int 10919220bc1SDavid Schultz fesetexceptflag(const fexcept_t *__flagp, int __excepts) 11019220bc1SDavid Schultz { 11119220bc1SDavid Schultz fexcept_t __fpsr; 11219220bc1SDavid Schultz 11319220bc1SDavid Schultz __rfs(&__fpsr); 11419220bc1SDavid Schultz __fpsr &= ~__excepts; 11519220bc1SDavid Schultz __fpsr |= *__flagp & __excepts; 11619220bc1SDavid Schultz __wfs(__fpsr); 11719220bc1SDavid Schultz return (0); 11819220bc1SDavid Schultz } 11919220bc1SDavid Schultz 120d78e594bSDavid Schultz __fenv_static inline int 12119220bc1SDavid Schultz feraiseexcept(int __excepts) 12219220bc1SDavid Schultz { 12319220bc1SDavid Schultz fexcept_t __ex = __excepts; 12419220bc1SDavid Schultz 12519220bc1SDavid Schultz fesetexceptflag(&__ex, __excepts); /* XXX */ 12619220bc1SDavid Schultz return (0); 12719220bc1SDavid Schultz } 12819220bc1SDavid Schultz 129d78e594bSDavid Schultz __fenv_static inline int 13019220bc1SDavid Schultz fetestexcept(int __excepts) 13119220bc1SDavid Schultz { 13219220bc1SDavid Schultz fexcept_t __fpsr; 13319220bc1SDavid Schultz 13419220bc1SDavid Schultz __rfs(&__fpsr); 13519220bc1SDavid Schultz return (__fpsr & __excepts); 13619220bc1SDavid Schultz } 13719220bc1SDavid Schultz 138d78e594bSDavid Schultz __fenv_static inline int 13919220bc1SDavid Schultz fegetround(void) 14019220bc1SDavid Schultz { 14119220bc1SDavid Schultz 14219220bc1SDavid Schultz /* 14319220bc1SDavid Schultz * Apparently, the rounding mode is specified as part of the 14419220bc1SDavid Schultz * instruction format on ARM, so the dynamic rounding mode is 14519220bc1SDavid Schultz * indeterminate. Some FPUs may differ. 14619220bc1SDavid Schultz */ 14719220bc1SDavid Schultz return (-1); 14819220bc1SDavid Schultz } 14919220bc1SDavid Schultz 150d78e594bSDavid Schultz __fenv_static inline int 15119220bc1SDavid Schultz fesetround(int __round) 15219220bc1SDavid Schultz { 15319220bc1SDavid Schultz 15419220bc1SDavid Schultz return (-1); 15519220bc1SDavid Schultz } 15619220bc1SDavid Schultz 157d78e594bSDavid Schultz __fenv_static inline int 15819220bc1SDavid Schultz fegetenv(fenv_t *__envp) 15919220bc1SDavid Schultz { 16019220bc1SDavid Schultz 16119220bc1SDavid Schultz __rfs(__envp); 16219220bc1SDavid Schultz return (0); 16319220bc1SDavid Schultz } 16419220bc1SDavid Schultz 165d78e594bSDavid Schultz __fenv_static inline int 16619220bc1SDavid Schultz feholdexcept(fenv_t *__envp) 16719220bc1SDavid Schultz { 16819220bc1SDavid Schultz fenv_t __env; 16919220bc1SDavid Schultz 17019220bc1SDavid Schultz __rfs(&__env); 17119220bc1SDavid Schultz *__envp = __env; 17219220bc1SDavid Schultz __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); 17319220bc1SDavid Schultz __wfs(__env); 17419220bc1SDavid Schultz return (0); 17519220bc1SDavid Schultz } 17619220bc1SDavid Schultz 177d78e594bSDavid Schultz __fenv_static inline int 17819220bc1SDavid Schultz fesetenv(const fenv_t *__envp) 17919220bc1SDavid Schultz { 18019220bc1SDavid Schultz 18119220bc1SDavid Schultz __wfs(*__envp); 18219220bc1SDavid Schultz return (0); 18319220bc1SDavid Schultz } 18419220bc1SDavid Schultz 185d78e594bSDavid Schultz __fenv_static inline int 18619220bc1SDavid Schultz feupdateenv(const fenv_t *__envp) 18719220bc1SDavid Schultz { 18819220bc1SDavid Schultz fexcept_t __fpsr; 18919220bc1SDavid Schultz 19019220bc1SDavid Schultz __rfs(&__fpsr); 19119220bc1SDavid Schultz __wfs(*__envp); 19219220bc1SDavid Schultz feraiseexcept(__fpsr & FE_ALL_EXCEPT); 19319220bc1SDavid Schultz return (0); 19419220bc1SDavid Schultz } 19519220bc1SDavid Schultz 19619220bc1SDavid Schultz #if __BSD_VISIBLE 19719220bc1SDavid Schultz 198d78e594bSDavid Schultz /* We currently provide no external definitions of the functions below. */ 199d78e594bSDavid Schultz 200d78e594bSDavid Schultz static inline int 20110b01832SDavid Schultz feenableexcept(int __mask) 20219220bc1SDavid Schultz { 20310b01832SDavid Schultz fenv_t __old_fpsr, __new_fpsr; 20419220bc1SDavid Schultz 20510b01832SDavid Schultz __rfs(&__old_fpsr); 20610b01832SDavid Schultz __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT; 20710b01832SDavid Schultz __wfs(__new_fpsr); 20810b01832SDavid Schultz return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); 20919220bc1SDavid Schultz } 21019220bc1SDavid Schultz 211d78e594bSDavid Schultz static inline int 21210b01832SDavid Schultz fedisableexcept(int __mask) 21310b01832SDavid Schultz { 21410b01832SDavid Schultz fenv_t __old_fpsr, __new_fpsr; 21510b01832SDavid Schultz 21610b01832SDavid Schultz __rfs(&__old_fpsr); 21710b01832SDavid Schultz __new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT); 21810b01832SDavid Schultz __wfs(__new_fpsr); 21910b01832SDavid Schultz return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); 22010b01832SDavid Schultz } 22110b01832SDavid Schultz 222d78e594bSDavid Schultz static inline int 22310b01832SDavid Schultz fegetexcept(void) 22419220bc1SDavid Schultz { 22519220bc1SDavid Schultz fenv_t __fpsr; 22619220bc1SDavid Schultz 22719220bc1SDavid Schultz __rfs(&__fpsr); 22819220bc1SDavid Schultz return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT); 22919220bc1SDavid Schultz } 23019220bc1SDavid Schultz 23119220bc1SDavid Schultz #endif /* __BSD_VISIBLE */ 23219220bc1SDavid Schultz 233*7bde21b1SDavid Schultz #endif /* ARM_HARD_FLOAT */ 234*7bde21b1SDavid Schultz 23519220bc1SDavid Schultz __END_DECLS 23619220bc1SDavid Schultz 23719220bc1SDavid Schultz #endif /* !_FENV_H_ */ 238