Home | History | Annotate | Download | only in include
      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/mips/fenv.h,v 1.1 2008/04/26 12:20:29 imp Exp $
     27  */
     28 
     29 #ifndef	_FENV_H_
     30 #define	_FENV_H_
     31 
     32 #include <sys/cdefs.h>
     33 #include <sys/_types.h>
     34 
     35 __BEGIN_DECLS
     36 
     37 typedef	__uint32_t	fenv_t;
     38 typedef	__uint32_t	fexcept_t;
     39 
     40 /* Exception flags */
     41 #define	FE_INVALID	0x0001
     42 #define	FE_DIVBYZERO	0x0002
     43 #define	FE_OVERFLOW	0x0004
     44 #define	FE_UNDERFLOW	0x0008
     45 #define	FE_INEXACT	0x0010
     46 #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
     47 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
     48 
     49 /* Rounding modes */
     50 #define	FE_TONEAREST	0x0000
     51 #define	FE_TOWARDZERO	0x0001
     52 #define	FE_UPWARD	0x0002
     53 #define	FE_DOWNWARD	0x0003
     54 #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
     55 			 FE_UPWARD | FE_TOWARDZERO)
     56 
     57 /* Default floating-point environment */
     58 extern const fenv_t	__fe_dfl_env;
     59 #define	FE_DFL_ENV	(&__fe_dfl_env)
     60 
     61 /* We need to be able to map status flag positions to mask flag positions */
     62 #define _FPUSW_SHIFT	16
     63 #define	_ENABLE_MASK	(FE_ALL_EXCEPT << _FPUSW_SHIFT)
     64 
     65 #ifdef	ARM_HARD_FLOAT
     66 #define	__rfs(__fpsr)	__asm __volatile("rfs %0" : "=r" (*(__fpsr)))
     67 #define	__wfs(__fpsr)	__asm __volatile("wfs %0" : : "r" (__fpsr))
     68 #else
     69 #define __rfs(__fpsr)
     70 #define __wfs(__fpsr)
     71 #endif
     72 
     73 static __inline int
     74 feclearexcept(int __excepts)
     75 {
     76 	fexcept_t __fpsr;
     77 
     78 	__rfs(&__fpsr);
     79 	__fpsr &= ~__excepts;
     80 	__wfs(__fpsr);
     81 	return (0);
     82 }
     83 
     84 static __inline int
     85 fegetexceptflag(fexcept_t *__flagp, int __excepts)
     86 {
     87 	fexcept_t __fpsr;
     88 
     89 	__rfs(&__fpsr);
     90 	*__flagp = __fpsr & __excepts;
     91 	return (0);
     92 }
     93 
     94 static __inline int
     95 fesetexceptflag(const fexcept_t *__flagp, int __excepts)
     96 {
     97 	fexcept_t __fpsr;
     98 
     99 	__rfs(&__fpsr);
    100 	__fpsr &= ~__excepts;
    101 	__fpsr |= *__flagp & __excepts;
    102 	__wfs(__fpsr);
    103 	return (0);
    104 }
    105 
    106 static __inline int
    107 feraiseexcept(int __excepts)
    108 {
    109 	fexcept_t __ex = __excepts;
    110 
    111 	fesetexceptflag(&__ex, __excepts);	/* XXX */
    112 	return (0);
    113 }
    114 
    115 static __inline int
    116 fetestexcept(int __excepts)
    117 {
    118 	fexcept_t __fpsr;
    119 
    120 	__rfs(&__fpsr);
    121 	return (__fpsr & __excepts);
    122 }
    123 
    124 static __inline int
    125 fegetround(void)
    126 {
    127 
    128 	/*
    129 	 * Apparently, the rounding mode is specified as part of the
    130 	 * instruction format on ARM, so the dynamic rounding mode is
    131 	 * indeterminate.  Some FPUs may differ.
    132 	 */
    133 	return (-1);
    134 }
    135 
    136 static __inline int
    137 fesetround(int __round)
    138 {
    139 
    140 	return (-1);
    141 }
    142 
    143 static __inline int
    144 fegetenv(fenv_t *__envp)
    145 {
    146 
    147 	__rfs(__envp);
    148 	return (0);
    149 }
    150 
    151 static __inline int
    152 feholdexcept(fenv_t *__envp)
    153 {
    154 	fenv_t __env;
    155 
    156 	__rfs(&__env);
    157 	*__envp = __env;
    158 	__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
    159 	__wfs(__env);
    160 	return (0);
    161 }
    162 
    163 static __inline int
    164 fesetenv(const fenv_t *__envp)
    165 {
    166 
    167 	__wfs(*__envp);
    168 	return (0);
    169 }
    170 
    171 static __inline int
    172 feupdateenv(const fenv_t *__envp)
    173 {
    174 	fexcept_t __fpsr;
    175 
    176 	__rfs(&__fpsr);
    177 	__wfs(*__envp);
    178 	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
    179 	return (0);
    180 }
    181 
    182 #if __BSD_VISIBLE
    183 
    184 static __inline int
    185 feenableexcept(int __mask)
    186 {
    187 	fenv_t __old_fpsr, __new_fpsr;
    188 
    189 	__rfs(&__old_fpsr);
    190 	__new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
    191 	__wfs(__new_fpsr);
    192 	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
    193 }
    194 
    195 static __inline int
    196 fedisableexcept(int __mask)
    197 {
    198 	fenv_t __old_fpsr, __new_fpsr;
    199 
    200 	__rfs(&__old_fpsr);
    201 	__new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
    202 	__wfs(__new_fpsr);
    203 	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
    204 }
    205 
    206 static __inline int
    207 fegetexcept(void)
    208 {
    209 	fenv_t __fpsr;
    210 
    211 	__rfs(&__fpsr);
    212 	return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
    213 }
    214 
    215 #endif /* __BSD_VISIBLE */
    216 
    217 __END_DECLS
    218 
    219 #endif	/* !_FENV_H_ */
    220 
    221