Home | History | Annotate | Line # | Download | only in include
fenv.h revision 1.5
      1 /*	$NetBSD: fenv.h,v 1.5 2019/10/29 04:55:36 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  *
     28  * $FreeBSD: head/lib/msun/mips/fenv.h 226218 2011-10-10 15:43:09Z das $
     29  */
     30 
     31 #ifndef	_MIPS_FENV_H_
     32 #define	_MIPS_FENV_H_
     33 
     34 #include <sys/stdint.h>
     35 
     36 /* Exception flags */
     37 #define	FE_INEXACT	0x0004
     38 #define	FE_UNDERFLOW	0x0008
     39 #define	FE_OVERFLOW	0x0010
     40 #define	FE_DIVBYZERO	0x0020
     41 #define	FE_INVALID	0x0040
     42 #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
     43 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
     44 
     45 /* Rounding modes */
     46 #define	FE_TONEAREST	0x0000
     47 #define	FE_TOWARDZERO	0x0001
     48 #define	FE_UPWARD	0x0002
     49 #define	FE_DOWNWARD	0x0003
     50 #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
     51 			 FE_UPWARD | FE_TOWARDZERO)
     52 
     53 #ifndef __mips_soft_float
     54 
     55 #ifndef	__fenv_static
     56 #define	__fenv_static	static
     57 #endif
     58 
     59 typedef	uint32_t 	fpu_control_t __attribute__((__mode__(__SI__)));
     60 typedef	fpu_control_t	fenv_t;
     61 typedef	fpu_control_t	fexcept_t;
     62 
     63 __BEGIN_DECLS
     64 
     65 /* Default floating-point environment */
     66 extern const fenv_t	__fe_dfl_env;
     67 #define	FE_DFL_ENV	(&__fe_dfl_env)
     68 
     69 /* We need to be able to map status flag positions to mask flag positions */
     70 #define	_ENABLE_MASK	(FE_ALL_EXCEPT << _ENABLE_SHIFT)
     71 #define _ENABLE_SHIFT    5
     72 
     73 static inline fpu_control_t
     74 __rfs(void)
     75 {
     76 	fpu_control_t __fpsr;
     77 
     78 	__asm __volatile("cfc1 %0,$31" : "=r" (__fpsr));
     79 	return __fpsr;
     80 }
     81 
     82 static inline void
     83 __wfs(fpu_control_t __fpsr)
     84 {
     85 
     86 	__asm __volatile("ctc1 %0,$31" : : "r" (__fpsr));
     87 }
     88 
     89 #if __GNUC_PREREQ__(8, 0)
     90 #pragma GCC diagnostic push
     91 #pragma GCC diagnostic ignored "-Wshadow"
     92 #endif
     93 
     94 __fenv_static inline int
     95 feclearexcept(int __excepts)
     96 {
     97 	fexcept_t __fpsr;
     98 
     99 	__excepts &= FE_ALL_EXCEPT;
    100 	__fpsr = __rfs();
    101 	__fpsr &= ~(__excepts | (__excepts << _ENABLE_SHIFT));
    102 	__wfs(__fpsr);
    103 	return 0;
    104 }
    105 
    106 __fenv_static inline int
    107 fegetexceptflag(fexcept_t *__flagp, int __excepts)
    108 {
    109 	fexcept_t __fpsr;
    110 
    111 	__fpsr = __rfs();
    112 	*__flagp = __fpsr & __excepts;
    113 	return (0);
    114 }
    115 
    116 __fenv_static inline int
    117 fesetexceptflag(const fexcept_t *__flagp, int __excepts)
    118 {
    119 	fexcept_t __fpsr;
    120 
    121 	__fpsr = __rfs();
    122 	__fpsr &= ~__excepts;
    123 	__fpsr |= *__flagp & __excepts;
    124 	__wfs(__fpsr);
    125 	return (0);
    126 }
    127 
    128 __fenv_static inline int
    129 feraiseexcept(int __excepts)
    130 {
    131 	fexcept_t __ex = __excepts;
    132 
    133 	fesetexceptflag(&__ex, __excepts);	/* XXX */
    134 	return (0);
    135 }
    136 
    137 __fenv_static inline int
    138 fetestexcept(int __excepts)
    139 {
    140 	fexcept_t __fpsr;
    141 
    142 	__fpsr = __rfs();
    143 	return (__fpsr & __excepts);
    144 }
    145 
    146 __fenv_static inline int
    147 fegetround(void)
    148 {
    149 	fexcept_t __fpsr;
    150 
    151 	__fpsr = __rfs();
    152 	return __fpsr & _ROUND_MASK;
    153 }
    154 
    155 __fenv_static inline int
    156 fesetround(int __round)
    157 {
    158 	fexcept_t __fpsr;
    159 
    160 	if (__round & ~_ROUND_MASK)
    161 		return 1;
    162 	__fpsr = __rfs();
    163 	__fpsr &= ~_ROUND_MASK;
    164 	__fpsr |= __round;
    165 	__wfs(__fpsr);
    166 
    167 	return 0;
    168 }
    169 
    170 __fenv_static inline int
    171 fegetenv(fenv_t *__envp)
    172 {
    173 
    174 	*__envp = __rfs();
    175 	return (0);
    176 }
    177 
    178 __fenv_static inline int
    179 feholdexcept(fenv_t *__envp)
    180 {
    181 	fenv_t __env;
    182 
    183 	__env = __rfs();
    184 	*__envp = __env;
    185 	__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
    186 	__wfs(__env);
    187 	return (0);
    188 }
    189 
    190 __fenv_static inline int
    191 fesetenv(const fenv_t *__envp)
    192 {
    193 
    194 	__wfs(*__envp);
    195 	return (0);
    196 }
    197 
    198 __fenv_static inline int
    199 feupdateenv(const fenv_t *__envp)
    200 {
    201 	fexcept_t __fpsr;
    202 
    203 	__fpsr = __rfs();
    204 	__wfs(*__envp);
    205 	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
    206 	return (0);
    207 }
    208 
    209 #if __GNUC_PREREQ__(8, 0)
    210 #pragma GCC diagnostic pop
    211 #endif
    212 
    213 #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE)
    214 
    215 __fenv_static inline int
    216 feenableexcept(int __excepts)
    217 {
    218 	fenv_t __old_fpsr, __new_fpsr;
    219 
    220 	__new_fpsr = __rfs();
    221 	__old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT;
    222 	__excepts &= FE_ALL_EXCEPT;
    223 	__new_fpsr |= __excepts << _ENABLE_SHIFT;
    224 	__wfs(__new_fpsr);
    225 	return __old_fpsr;
    226 }
    227 
    228 __fenv_static inline int
    229 fedisableexcept(int __excepts)
    230 {
    231 	fenv_t __old_fpsr, __new_fpsr;
    232 
    233 	__new_fpsr = __rfs();
    234 	__old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT;
    235 	__excepts &= FE_ALL_EXCEPT;
    236 	__new_fpsr &= ~(__excepts << _ENABLE_SHIFT);
    237 	__wfs(__new_fpsr);
    238 	return __old_fpsr;
    239 }
    240 
    241 __fenv_static inline int
    242 fegetexcept(void)
    243 {
    244 	fenv_t __fpsr;
    245 
    246 	__fpsr = __rfs();
    247 	return ((__fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT);
    248 }
    249 
    250 #endif /* _NETBSD_SOURCE || _GNU_SOURCE */
    251 
    252 __END_DECLS
    253 
    254 #endif /* __mips_soft_float */
    255 
    256 #endif	/* !_FENV_H_ */
    257