119220bc1SDavid Schultz /*- 2*5e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*5e53a4f9SPedro F. Giffuni * 410b01832SDavid Schultz * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 519220bc1SDavid Schultz * All rights reserved. 619220bc1SDavid Schultz * 719220bc1SDavid Schultz * Redistribution and use in source and binary forms, with or without 819220bc1SDavid Schultz * modification, are permitted provided that the following conditions 919220bc1SDavid Schultz * are met: 1019220bc1SDavid Schultz * 1. Redistributions of source code must retain the above copyright 1119220bc1SDavid Schultz * notice, this list of conditions and the following disclaimer. 1219220bc1SDavid Schultz * 2. Redistributions in binary form must reproduce the above copyright 1319220bc1SDavid Schultz * notice, this list of conditions and the following disclaimer in the 1419220bc1SDavid Schultz * documentation and/or other materials provided with the distribution. 1519220bc1SDavid Schultz * 1619220bc1SDavid Schultz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1719220bc1SDavid Schultz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1819220bc1SDavid Schultz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1919220bc1SDavid Schultz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2019220bc1SDavid Schultz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2119220bc1SDavid Schultz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2219220bc1SDavid Schultz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2319220bc1SDavid Schultz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2419220bc1SDavid Schultz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2519220bc1SDavid Schultz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2619220bc1SDavid Schultz * SUCH DAMAGE. 2719220bc1SDavid Schultz * 2819220bc1SDavid Schultz * $FreeBSD$ 2919220bc1SDavid Schultz */ 3019220bc1SDavid Schultz 3119220bc1SDavid Schultz #ifndef _FENV_H_ 3219220bc1SDavid Schultz #define _FENV_H_ 3319220bc1SDavid Schultz 3419220bc1SDavid Schultz #include <sys/_types.h> 3519220bc1SDavid Schultz 36d78e594bSDavid Schultz #ifndef __fenv_static 37d78e594bSDavid Schultz #define __fenv_static static 38d78e594bSDavid Schultz #endif 39d78e594bSDavid Schultz 4019220bc1SDavid Schultz typedef __uint32_t fenv_t; 4119220bc1SDavid Schultz typedef __uint32_t fexcept_t; 4219220bc1SDavid Schultz 4319220bc1SDavid Schultz /* Exception flags */ 4419220bc1SDavid Schultz #define FE_INVALID 0x0001 4519220bc1SDavid Schultz #define FE_DIVBYZERO 0x0002 4619220bc1SDavid Schultz #define FE_OVERFLOW 0x0004 4719220bc1SDavid Schultz #define FE_UNDERFLOW 0x0008 4819220bc1SDavid Schultz #define FE_INEXACT 0x0010 49c9081a6cSAndrew Turner #ifdef __ARM_PCS_VFP 50c9081a6cSAndrew Turner #define FE_DENORMAL 0x0080 51c9081a6cSAndrew Turner #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 52c9081a6cSAndrew Turner FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL) 53c9081a6cSAndrew Turner #else 5419220bc1SDavid Schultz #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 5519220bc1SDavid Schultz FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 56c9081a6cSAndrew Turner #endif 5719220bc1SDavid Schultz 5815d3b4dbSOlivier Houchard /* Rounding modes */ 59bb6c193eSAndrew Turner #define VFP_FE_TONEAREST 0x00000000 60bb6c193eSAndrew Turner #define VFP_FE_UPWARD 0x00400000 61bb6c193eSAndrew Turner #define VFP_FE_DOWNWARD 0x00800000 62bb6c193eSAndrew Turner #define VFP_FE_TOWARDZERO 0x00c00000 63bb6c193eSAndrew Turner 64c9081a6cSAndrew Turner #ifdef __ARM_PCS_VFP 65bb6c193eSAndrew Turner #define FE_TONEAREST VFP_FE_TONEAREST 66bb6c193eSAndrew Turner #define FE_UPWARD VFP_FE_UPWARD 67bb6c193eSAndrew Turner #define FE_DOWNWARD VFP_FE_DOWNWARD 68bb6c193eSAndrew Turner #define FE_TOWARDZERO VFP_FE_TOWARDZERO 69c9081a6cSAndrew Turner #else 7015d3b4dbSOlivier Houchard #define FE_TONEAREST 0x0000 7115d3b4dbSOlivier Houchard #define FE_TOWARDZERO 0x0001 7215d3b4dbSOlivier Houchard #define FE_UPWARD 0x0002 7315d3b4dbSOlivier Houchard #define FE_DOWNWARD 0x0003 74c9081a6cSAndrew Turner #endif 7515d3b4dbSOlivier Houchard #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 7615d3b4dbSOlivier Houchard FE_UPWARD | FE_TOWARDZERO) 7719220bc1SDavid Schultz __BEGIN_DECLS 7819220bc1SDavid Schultz 7919220bc1SDavid Schultz /* Default floating-point environment */ 8019220bc1SDavid Schultz extern const fenv_t __fe_dfl_env; 8119220bc1SDavid Schultz #define FE_DFL_ENV (&__fe_dfl_env) 8219220bc1SDavid Schultz 8319220bc1SDavid Schultz /* We need to be able to map status flag positions to mask flag positions */ 84c9081a6cSAndrew Turner #ifndef __ARM_PCS_VFP 8519220bc1SDavid Schultz #define _FPUSW_SHIFT 16 8619220bc1SDavid Schultz #define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) 87c9081a6cSAndrew Turner #endif 8819220bc1SDavid Schultz 89c9081a6cSAndrew Turner #ifndef __ARM_PCS_VFP 907082a2cfSDavid Schultz 917082a2cfSDavid Schultz int feclearexcept(int __excepts); 927082a2cfSDavid Schultz int fegetexceptflag(fexcept_t *__flagp, int __excepts); 937082a2cfSDavid Schultz int fesetexceptflag(const fexcept_t *__flagp, int __excepts); 947082a2cfSDavid Schultz int feraiseexcept(int __excepts); 957082a2cfSDavid Schultz int fetestexcept(int __excepts); 967082a2cfSDavid Schultz int fegetround(void); 977082a2cfSDavid Schultz int fesetround(int __round); 987082a2cfSDavid Schultz int fegetenv(fenv_t *__envp); 997082a2cfSDavid Schultz int feholdexcept(fenv_t *__envp); 1007082a2cfSDavid Schultz int fesetenv(const fenv_t *__envp); 1017082a2cfSDavid Schultz int feupdateenv(const fenv_t *__envp); 102bb6c193eSAndrew Turner #if __BSD_VISIBLE 103bb6c193eSAndrew Turner int feenableexcept(int __mask); 104bb6c193eSAndrew Turner int fedisableexcept(int __mask); 105bb6c193eSAndrew Turner int fegetexcept(void); 106bb6c193eSAndrew Turner #endif 1077bde21b1SDavid Schultz 108c9081a6cSAndrew Turner #else /* __ARM_PCS_VFP */ 1097bde21b1SDavid Schultz 110c9081a6cSAndrew Turner #define vmrs_fpscr(__r) __asm __volatile("vmrs %0, fpscr" : "=&r"(__r)) 111c9081a6cSAndrew Turner #define vmsr_fpscr(__r) __asm __volatile("vmsr fpscr, %0" : : "r"(__r)) 11219220bc1SDavid Schultz 113a541d15cSAndrew Turner #define _FPU_MASK_SHIFT 8 114a541d15cSAndrew Turner 115d78e594bSDavid Schultz __fenv_static inline int 11619220bc1SDavid Schultz feclearexcept(int __excepts) 11719220bc1SDavid Schultz { 11819220bc1SDavid Schultz fexcept_t __fpsr; 11919220bc1SDavid Schultz 120c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 12119220bc1SDavid Schultz __fpsr &= ~__excepts; 122c9081a6cSAndrew Turner vmsr_fpscr(__fpsr); 12319220bc1SDavid Schultz return (0); 12419220bc1SDavid Schultz } 12519220bc1SDavid Schultz 126d78e594bSDavid Schultz __fenv_static inline int 12719220bc1SDavid Schultz fegetexceptflag(fexcept_t *__flagp, int __excepts) 12819220bc1SDavid Schultz { 12919220bc1SDavid Schultz fexcept_t __fpsr; 13019220bc1SDavid Schultz 131c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 13219220bc1SDavid Schultz *__flagp = __fpsr & __excepts; 13319220bc1SDavid Schultz return (0); 13419220bc1SDavid Schultz } 13519220bc1SDavid Schultz 136d78e594bSDavid Schultz __fenv_static inline int 13719220bc1SDavid Schultz fesetexceptflag(const fexcept_t *__flagp, int __excepts) 13819220bc1SDavid Schultz { 13919220bc1SDavid Schultz fexcept_t __fpsr; 14019220bc1SDavid Schultz 141c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 14219220bc1SDavid Schultz __fpsr &= ~__excepts; 14319220bc1SDavid Schultz __fpsr |= *__flagp & __excepts; 144c9081a6cSAndrew Turner vmsr_fpscr(__fpsr); 14519220bc1SDavid Schultz return (0); 14619220bc1SDavid Schultz } 14719220bc1SDavid Schultz 148d78e594bSDavid Schultz __fenv_static inline int 14919220bc1SDavid Schultz feraiseexcept(int __excepts) 15019220bc1SDavid Schultz { 15119220bc1SDavid Schultz fexcept_t __ex = __excepts; 15219220bc1SDavid Schultz 15319220bc1SDavid Schultz fesetexceptflag(&__ex, __excepts); /* XXX */ 15419220bc1SDavid Schultz return (0); 15519220bc1SDavid Schultz } 15619220bc1SDavid Schultz 157d78e594bSDavid Schultz __fenv_static inline int 15819220bc1SDavid Schultz fetestexcept(int __excepts) 15919220bc1SDavid Schultz { 16019220bc1SDavid Schultz fexcept_t __fpsr; 16119220bc1SDavid Schultz 162c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 16319220bc1SDavid Schultz return (__fpsr & __excepts); 16419220bc1SDavid Schultz } 16519220bc1SDavid Schultz 166d78e594bSDavid Schultz __fenv_static inline int 16719220bc1SDavid Schultz fegetround(void) 16819220bc1SDavid Schultz { 169c9081a6cSAndrew Turner fenv_t __fpsr; 17019220bc1SDavid Schultz 171c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 172c9081a6cSAndrew Turner return (__fpsr & _ROUND_MASK); 17319220bc1SDavid Schultz } 17419220bc1SDavid Schultz 175d78e594bSDavid Schultz __fenv_static inline int 17619220bc1SDavid Schultz fesetround(int __round) 17719220bc1SDavid Schultz { 178c9081a6cSAndrew Turner fenv_t __fpsr; 17919220bc1SDavid Schultz 180c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 181c9081a6cSAndrew Turner __fpsr &= ~(_ROUND_MASK); 182c9081a6cSAndrew Turner __fpsr |= __round; 183c9081a6cSAndrew Turner vmsr_fpscr(__fpsr); 184c9081a6cSAndrew Turner return (0); 18519220bc1SDavid Schultz } 18619220bc1SDavid Schultz 187d78e594bSDavid Schultz __fenv_static inline int 18819220bc1SDavid Schultz fegetenv(fenv_t *__envp) 18919220bc1SDavid Schultz { 19019220bc1SDavid Schultz 191c9081a6cSAndrew Turner vmrs_fpscr(*__envp); 19219220bc1SDavid Schultz return (0); 19319220bc1SDavid Schultz } 19419220bc1SDavid Schultz 195d78e594bSDavid Schultz __fenv_static inline int 19619220bc1SDavid Schultz feholdexcept(fenv_t *__envp) 19719220bc1SDavid Schultz { 19819220bc1SDavid Schultz fenv_t __env; 19919220bc1SDavid Schultz 200c9081a6cSAndrew Turner vmrs_fpscr(__env); 20119220bc1SDavid Schultz *__envp = __env; 202c9081a6cSAndrew Turner __env &= ~(FE_ALL_EXCEPT); 203c9081a6cSAndrew Turner vmsr_fpscr(__env); 20419220bc1SDavid Schultz return (0); 20519220bc1SDavid Schultz } 20619220bc1SDavid Schultz 207d78e594bSDavid Schultz __fenv_static inline int 20819220bc1SDavid Schultz fesetenv(const fenv_t *__envp) 20919220bc1SDavid Schultz { 21019220bc1SDavid Schultz 211c9081a6cSAndrew Turner vmsr_fpscr(*__envp); 21219220bc1SDavid Schultz return (0); 21319220bc1SDavid Schultz } 21419220bc1SDavid Schultz 215d78e594bSDavid Schultz __fenv_static inline int 21619220bc1SDavid Schultz feupdateenv(const fenv_t *__envp) 21719220bc1SDavid Schultz { 21819220bc1SDavid Schultz fexcept_t __fpsr; 21919220bc1SDavid Schultz 220c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 221c9081a6cSAndrew Turner vmsr_fpscr(*__envp); 22219220bc1SDavid Schultz feraiseexcept(__fpsr & FE_ALL_EXCEPT); 22319220bc1SDavid Schultz return (0); 22419220bc1SDavid Schultz } 22519220bc1SDavid Schultz 22619220bc1SDavid Schultz #if __BSD_VISIBLE 22719220bc1SDavid Schultz 228d78e594bSDavid Schultz /* We currently provide no external definitions of the functions below. */ 229d78e594bSDavid Schultz 230a541d15cSAndrew Turner __fenv_static inline int 23110b01832SDavid Schultz feenableexcept(int __mask) 23219220bc1SDavid Schultz { 23310b01832SDavid Schultz fenv_t __old_fpsr, __new_fpsr; 23419220bc1SDavid Schultz 235c9081a6cSAndrew Turner vmrs_fpscr(__old_fpsr); 236a541d15cSAndrew Turner __new_fpsr = __old_fpsr | 237a541d15cSAndrew Turner ((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT); 238c9081a6cSAndrew Turner vmsr_fpscr(__new_fpsr); 239a541d15cSAndrew Turner return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT); 24019220bc1SDavid Schultz } 24119220bc1SDavid Schultz 242a541d15cSAndrew Turner __fenv_static inline int 24310b01832SDavid Schultz fedisableexcept(int __mask) 24410b01832SDavid Schultz { 24510b01832SDavid Schultz fenv_t __old_fpsr, __new_fpsr; 24610b01832SDavid Schultz 247c9081a6cSAndrew Turner vmrs_fpscr(__old_fpsr); 248a541d15cSAndrew Turner __new_fpsr = __old_fpsr & 249a541d15cSAndrew Turner ~((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT); 250c9081a6cSAndrew Turner vmsr_fpscr(__new_fpsr); 251a541d15cSAndrew Turner return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT); 25210b01832SDavid Schultz } 25310b01832SDavid Schultz 254a541d15cSAndrew Turner __fenv_static inline int 25510b01832SDavid Schultz fegetexcept(void) 25619220bc1SDavid Schultz { 25719220bc1SDavid Schultz fenv_t __fpsr; 25819220bc1SDavid Schultz 259c9081a6cSAndrew Turner vmrs_fpscr(__fpsr); 260c9081a6cSAndrew Turner return (__fpsr & FE_ALL_EXCEPT); 26119220bc1SDavid Schultz } 26219220bc1SDavid Schultz 26319220bc1SDavid Schultz #endif /* __BSD_VISIBLE */ 26419220bc1SDavid Schultz 265c9081a6cSAndrew Turner #endif /* __ARM_PCS_VFP */ 2667bde21b1SDavid Schultz 26719220bc1SDavid Schultz __END_DECLS 26819220bc1SDavid Schultz 26919220bc1SDavid Schultz #endif /* !_FENV_H_ */ 270