Home | History | Annotate | Download | only in alpha
      1 /*-
      2  * Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG>
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     24  * SUCH DAMAGE.
     25  *
     26  * $FreeBSD: src/lib/msun/alpha/fenv.h,v 1.3 2005/03/16 19:03:44 das Exp $
     27  */
     28 
     29 #ifndef	_FENV_H_
     30 #define	_FENV_H_
     31 
     32 #include <sys/_types.h>
     33 
     34 typedef	__uint64_t	fenv_t;
     35 typedef	__uint16_t	fexcept_t;
     36 
     37 /* Exception flags */
     38 #define	FE_INVALID	0x02
     39 #define	FE_DIVBYZERO	0x04
     40 #define	FE_OVERFLOW	0x08
     41 #define	FE_UNDERFLOW	0x10
     42 #define	FE_INEXACT	0x20
     43 #define	FE_INTOVF	0x40	/* not maskable */
     44 #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | FE_INTOVF | \
     45 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
     46 
     47 /* Rounding modes */
     48 #define	FE_TOWARDZERO	0x00
     49 #define	FE_DOWNWARD	0x01
     50 #define	FE_TONEAREST	0x02
     51 #define	FE_UPWARD	0x03
     52 #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
     53 			 FE_UPWARD | FE_TOWARDZERO)
     54 #define	_ROUND_SHIFT	58
     55 
     56 #define	_FPUSW_SHIFT	51
     57 
     58 #define	__excb()	__asm __volatile("excb")
     59 #define	__mf_fpcr(__cw)	__asm __volatile("mf_fpcr %0" : "=f" (*(__cw)))
     60 #define	__mt_fpcr(__cw)	__asm __volatile("mt_fpcr %0" : : "f" (__cw))
     61 
     62 union __fpcr {
     63 	double __d;
     64 	fenv_t __bits;
     65 };
     66 
     67 __BEGIN_DECLS
     68 
     69 /* Default floating-point environment */
     70 extern const fenv_t	__fe_dfl_env;
     71 #define	FE_DFL_ENV	(&__fe_dfl_env)
     72 
     73 static __inline int
     74 feclearexcept(int __excepts)
     75 {
     76 	union __fpcr __r;
     77 
     78 	__excb();
     79 	__mf_fpcr(&__r.__d);
     80 	__r.__bits &= ~((fenv_t)__excepts << _FPUSW_SHIFT);
     81 	__mt_fpcr(__r.__d);
     82 	__excb();
     83 	return (0);
     84 }
     85 
     86 static __inline int
     87 fegetexceptflag(fexcept_t *__flagp, int __excepts)
     88 {
     89 	union __fpcr __r;
     90 
     91 	__excb();
     92 	__mf_fpcr(&__r.__d);
     93 	__excb();
     94 	*__flagp = (__r.__bits >> _FPUSW_SHIFT) & __excepts;
     95 	return (0);
     96 }
     97 
     98 static __inline int
     99 fesetexceptflag(const fexcept_t *__flagp, int __excepts)
    100 {
    101 	union __fpcr __r;
    102 	fenv_t __xflag, __xexcepts;
    103 
    104 	__xflag = (fenv_t)*__flagp << _FPUSW_SHIFT;
    105 	__xexcepts = (fenv_t)__excepts << _FPUSW_SHIFT;
    106 	__excb();
    107 	__mf_fpcr(&__r.__d);
    108 	__r.__bits &= ~__xexcepts;
    109 	__r.__bits |= __xflag & __xexcepts;
    110 	__mt_fpcr(__r.__d);
    111 	__excb();
    112 	return (0);
    113 }
    114 
    115 static __inline int
    116 feraiseexcept(int __excepts)
    117 {
    118 
    119 	/*
    120 	 * XXX Generating exceptions this way does not actually invoke
    121 	 * a userland trap handler when enabled, but neither do
    122 	 * arithmetic operations as far as I can tell.  Perhaps there
    123 	 * are more bugs in the kernel trap handler.
    124 	 */
    125 	fexcept_t __ex = __excepts;
    126 	fesetexceptflag(&__ex, __excepts);
    127 	return (0);
    128 }
    129 
    130 static __inline int
    131 fetestexcept(int __excepts)
    132 {
    133 	union __fpcr __r;
    134 
    135 	__excb();
    136 	__mf_fpcr(&__r.__d);
    137 	__excb();
    138 	return ((__r.__bits >> _FPUSW_SHIFT) & __excepts);
    139 }
    140 
    141 static __inline int
    142 fegetround(void)
    143 {
    144 	union __fpcr __r;
    145 
    146 	/*
    147 	 * No exception barriers should be required here if we assume
    148 	 * that only fesetround() can change the rounding mode.
    149 	 */
    150 	__mf_fpcr(&__r.__d);
    151 	return ((int)(__r.__bits >> _ROUND_SHIFT) & _ROUND_MASK);
    152 }
    153 
    154 static __inline int
    155 fesetround(int __round)
    156 {
    157 	union __fpcr __r;
    158 
    159 	if (__round & ~_ROUND_MASK)
    160 		return (-1);
    161 	__excb();
    162 	__mf_fpcr(&__r.__d);
    163 	__r.__bits &= ~((fenv_t)_ROUND_MASK << _ROUND_SHIFT);
    164 	__r.__bits |= (fenv_t)__round << _ROUND_SHIFT;
    165 	__mt_fpcr(__r.__d);
    166 	__excb();
    167 	return (0);
    168 }
    169 
    170 int	fegetenv(fenv_t *__envp);
    171 int	feholdexcept(fenv_t *__envp);
    172 int	fesetenv(const fenv_t *__envp);
    173 int	feupdateenv(const fenv_t *__envp);
    174 
    175 #if __BSD_VISIBLE
    176 
    177 int	feenableexcept(int __mask);
    178 int	fedisableexcept(int __mask);
    179 int	fegetexcept(void);
    180 
    181 #endif /* __BSD_VISIBLE */
    182 
    183 __END_DECLS
    184 
    185 #endif	/* !_FENV_H_ */
    186