1156888Srwatson/* $NetBSD: fenv.h,v 1.3 2019/10/27 21:27:10 christos Exp $ */ 2156888Srwatson 3156888Srwatson/*- 4156888Srwatson * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 5156888Srwatson * All rights reserved. 6156888Srwatson * 7156888Srwatson * Redistribution and use in source and binary forms, with or without 8156888Srwatson * modification, are permitted provided that the following conditions 9156888Srwatson * are met: 10156888Srwatson * 1. Redistributions of source code must retain the above copyright 11156888Srwatson * notice, this list of conditions and the following disclaimer. 12156888Srwatson * 2. Redistributions in binary form must reproduce the above copyright 13156888Srwatson * notice, this list of conditions and the following disclaimer in the 14156888Srwatson * documentation and/or other materials provided with the distribution. 15156888Srwatson * 16156888Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17156888Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18156888Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19156888Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20156888Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21156888Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22156888Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23156888Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24156888Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25156888Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26156888Srwatson * SUCH DAMAGE. 27156888Srwatson * 28156888Srwatson * $FreeBSD: src/lib/msun/alpha/fenv.h,v 1.3 2005/03/16 19:03:44 das Exp $ 29156888Srwatson */ 30156888Srwatson 31156888Srwatson#ifndef _ALPHA_FENV_H_ 32156888Srwatson#define _ALPHA_FENV_H_ 33156888Srwatson 34156888Srwatson#include <sys/stdint.h> 35156888Srwatson 36156888Srwatsontypedef __uint64_t fenv_t; 37156888Srwatsontypedef __uint16_t fexcept_t; 38156888Srwatson 39156888Srwatson/* Exception flags */ 40156888Srwatson#define FE_INVALID 0x01 41156888Srwatson#define FE_DIVBYZERO 0x02 42156888Srwatson#define FE_OVERFLOW 0x04 43156888Srwatson#define FE_UNDERFLOW 0x08 44156888Srwatson#define FE_INEXACT 0x10 45156888Srwatson#define FE_INTOVF 0x20 /* not maskable */ 46156888Srwatson#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INTOVF | \ 47156888Srwatson FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 48156888Srwatson 49156888Srwatson/* Rounding modes */ 50156888Srwatson#define FE_TOWARDZERO 0x00 51156888Srwatson#define FE_DOWNWARD 0x01 52156888Srwatson#define FE_TONEAREST 0x02 53156888Srwatson#define FE_UPWARD 0x03 54156888Srwatson#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 55156888Srwatson FE_UPWARD | FE_TOWARDZERO) 56156888Srwatson#define _ROUND_SHIFT 58 57156888Srwatson 58156888Srwatson#define _FPUSW_SHIFT 52 59156888Srwatson 60156888Srwatson#define __excb() __asm __volatile("excb") 61156888Srwatson#define __mf_fpcr(__cw) __asm __volatile("mf_fpcr %0" : "=f" (*(__cw))) 62156888Srwatson#define __mt_fpcr(__cw) __asm __volatile("mt_fpcr %0" : : "f" (__cw)) 63156888Srwatson 64156888Srwatsonunion __fpcr { 65156888Srwatson double __d; 66156888Srwatson fenv_t __bits; 67156888Srwatson}; 68156888Srwatson 69156888Srwatson__BEGIN_DECLS 70156888Srwatson 71156888Srwatson/* Default floating-point environment */ 72156888Srwatsonextern const fenv_t __fe_dfl_env; 73156888Srwatson#define FE_DFL_ENV (&__fe_dfl_env) 74156889Srwatson 75156888Srwatson#if __GNUC_PREREQ__(8, 0) 76156888Srwatson#pragma GCC diagnostic push 77156888Srwatson#pragma GCC diagnostic ignored "-Wshadow" 78156889Srwatson#endif 79156889Srwatson 80156889Srwatsonstatic __inline int 81156889Srwatsonfeclearexcept(int __excepts) 82156889Srwatson{ 83156889Srwatson union __fpcr __r; 84156889Srwatson 85156889Srwatson __excb(); 86156889Srwatson __mf_fpcr(&__r.__d); 87156889Srwatson __r.__bits &= ~((fenv_t)__excepts << _FPUSW_SHIFT); 88156889Srwatson __mt_fpcr(__r.__d); 89156889Srwatson __excb(); 90156888Srwatson return 0; 91156888Srwatson} 92156888Srwatson 93156888Srwatsonstatic __inline int 94156888Srwatsonfegetexceptflag(fexcept_t *__flagp, int __excepts) 95156888Srwatson{ 96156888Srwatson union __fpcr __r; 97156888Srwatson 98156888Srwatson __excb(); 99156888Srwatson __mf_fpcr(&__r.__d); 100156888Srwatson __excb(); 101156888Srwatson *__flagp = (__r.__bits >> _FPUSW_SHIFT) & __excepts; 102156888Srwatson return 0; 103156888Srwatson} 104156888Srwatson 105156888Srwatsonstatic __inline int 106156889Srwatsonfesetexceptflag(const fexcept_t *__flagp, int __excepts) 107156889Srwatson{ 108156889Srwatson union __fpcr __r; 109156889Srwatson fenv_t __xflag, __xexcepts; 110156888Srwatson 111156888Srwatson __xflag = (fenv_t)*__flagp << _FPUSW_SHIFT; 112156889Srwatson __xexcepts = (fenv_t)__excepts << _FPUSW_SHIFT; 113156888Srwatson __excb(); 114156888Srwatson __mf_fpcr(&__r.__d); 115156888Srwatson __r.__bits &= ~__xexcepts; 116156888Srwatson __r.__bits |= __xflag & __xexcepts; 117156888Srwatson __mt_fpcr(__r.__d); 118156888Srwatson __excb(); 119156888Srwatson return 0; 120156888Srwatson} 121156888Srwatson 122156888Srwatsonstatic __inline int 123156888Srwatsonferaiseexcept(int __excepts) 124156888Srwatson{ 125156889Srwatson 126156889Srwatson /* 127156889Srwatson * XXX Generating exceptions this way does not actually invoke 128156889Srwatson * a userland trap handler when enabled, but neither do 129156888Srwatson * arithmetic operations as far as I can tell. Perhaps there 130156888Srwatson * are more bugs in the kernel trap handler. 131156888Srwatson */ 132156888Srwatson fexcept_t __ex = __excepts; 133156888Srwatson fesetexceptflag(&__ex, __excepts); 134156888Srwatson return 0; 135156888Srwatson} 136156888Srwatson 137156888Srwatsonstatic __inline int 138156888Srwatsonfetestexcept(int __excepts) 139156888Srwatson{ 140156888Srwatson union __fpcr __r; 141156888Srwatson 142156889Srwatson __excb(); 143156888Srwatson __mf_fpcr(&__r.__d); 144156888Srwatson __excb(); 145156888Srwatson return (__r.__bits >> _FPUSW_SHIFT) & __excepts; 146156888Srwatson} 147156888Srwatson 148156888Srwatsonstatic __inline int 149156889Srwatsonfegetround(void) 150156888Srwatson{ 151156888Srwatson union __fpcr __r; 152156889Srwatson 153156889Srwatson /* 154156889Srwatson * No exception barriers should be required here if we assume 155156888Srwatson * that only fesetround() can change the rounding mode. 156156888Srwatson */ 157156888Srwatson __mf_fpcr(&__r.__d); 158156889Srwatson return (int)(__r.__bits >> _ROUND_SHIFT) & _ROUND_MASK; 159156889Srwatson} 160156888Srwatson 161156888Srwatsonstatic __inline int 162156888Srwatsonfesetround(int __round) 163156888Srwatson{ 164156888Srwatson union __fpcr __r; 165156888Srwatson 166156888Srwatson if (__round & ~_ROUND_MASK) 167156888Srwatson return (-1); 168156888Srwatson __excb(); 169156888Srwatson __mf_fpcr(&__r.__d); 170156888Srwatson __r.__bits &= ~((fenv_t)_ROUND_MASK << _ROUND_SHIFT); 171156889Srwatson __r.__bits |= (fenv_t)__round << _ROUND_SHIFT; 172156889Srwatson __mt_fpcr(__r.__d); 173156889Srwatson __excb(); 174156888Srwatson return 0; 175156888Srwatson} 176156888Srwatson 177156888Srwatson#if __GNUC_PREREQ__(8, 0) 178156889Srwatson#pragma GCC diagnostic pop 179156888Srwatson#endif 180156888Srwatson 181156888Srwatsonint fegetenv(fenv_t *); 182156888Srwatsonint feholdexcept(fenv_t *); 183156888Srwatsonint fesetenv(const fenv_t *); 184156889Srwatsonint feupdateenv(const fenv_t *); 185156889Srwatson 186156889Srwatson#if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE) 187156889Srwatsonint feenableexcept(int); 188156889Srwatsonint fedisableexcept(int); 189156888Srwatsonint fegetexcept(void); 190156888Srwatson#endif /* _NETBSD_SOURCE || _GNU_SOURCE */ 191156889Srwatson 192156888Srwatson 193156888Srwatson__END_DECLS 194156888Srwatson 195156888Srwatson#endif /* !_ALPHA_FENV_H_ */ 196156888Srwatson