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/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $ 27 */ 28 29 /* 30 Rewritten for Android. 31 */ 32 33 /* MIPS FPU floating point control register bits. 34 * 35 * 31-25 -> floating point conditions code bits set by FP compare 36 * instructions 37 * 24 -> flush denormalized results to zero instead of 38 * causing unimplemented operation exception. 39 * 23 -> Condition bit 40 * 22 -> In conjunction with FS detects denormalized 41 * operands and replaces them internally with 0. 42 * 21 -> In conjunction with FS forces denormalized operands 43 * to the closest normalized value. 44 * 20-18 -> reserved (read as 0, write with 0) 45 * 17 -> cause bit for unimplemented operation 46 * 16 -> cause bit for invalid exception 47 * 15 -> cause bit for division by zero exception 48 * 14 -> cause bit for overflow exception 49 * 13 -> cause bit for underflow exception 50 * 12 -> cause bit for inexact exception 51 * 11 -> enable exception for invalid exception 52 * 10 -> enable exception for division by zero exception 53 * 9 -> enable exception for overflow exception 54 * 8 -> enable exception for underflow exception 55 * 7 -> enable exception for inexact exception 56 * 6 -> flag invalid exception 57 * 5 -> flag division by zero exception 58 * 4 -> flag overflow exception 59 * 3 -> flag underflow exception 60 * 2 -> flag inexact exception 61 * 1-0 -> rounding control 62 * 63 * 64 * Rounding Control: 65 * 00 - rounding to nearest (RN) 66 * 01 - rounding toward zero (RZ) 67 * 10 - rounding (up) toward plus infinity (RP) 68 * 11 - rounding (down)toward minus infinity (RM) 69 */ 70 71 #ifndef _FENV_H_ 72 #define _FENV_H_ 73 74 #include <machine/fenv.h> 75 #include <sys/types.h> 76 77 __BEGIN_DECLS 78 79 #define _FCSR_CAUSE_SHIFT 10 80 #define _ENABLE_SHIFT 5 81 #define _FCSR_ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT) 82 83 #define _FCSR_RMODE_SHIFT 0 84 #define _FCSR_RMASK 0x3 85 86 /* Default floating-point environment */ 87 extern const fenv_t __fe_dfl_env; 88 #define FE_DFL_ENV (&__fe_dfl_env) 89 90 static __inline int fegetenv(fenv_t* __envp) { 91 fenv_t _fcsr = 0; 92 #ifdef __mips_hard_float 93 __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr)); 94 #endif 95 *__envp = _fcsr; 96 return 0; 97 } 98 99 static __inline int fesetenv(const fenv_t* __envp) { 100 fenv_t _fcsr = *__envp; 101 #ifdef __mips_hard_float 102 __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr)); 103 #endif 104 return 0; 105 } 106 107 static __inline int feclearexcept(int __excepts) { 108 fexcept_t __fcsr; 109 fegetenv(&__fcsr); 110 __excepts &= FE_ALL_EXCEPT; 111 __fcsr &= ~(__excepts | (__excepts << _FCSR_CAUSE_SHIFT)); 112 fesetenv(&__fcsr); 113 return 0; 114 } 115 116 static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) { 117 fexcept_t __fcsr; 118 fegetenv(&__fcsr); 119 *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT; 120 return 0; 121 } 122 123 static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) { 124 fexcept_t __fcsr; 125 fegetenv(&__fcsr); 126 /* Ensure that flags are all legal */ 127 __excepts &= FE_ALL_EXCEPT; 128 __fcsr &= ~__excepts; 129 __fcsr |= *__flagp & __excepts; 130 fesetenv(&__fcsr); 131 return 0; 132 } 133 134 static __inline int feraiseexcept(int __excepts) { 135 fexcept_t __fcsr; 136 fegetenv(&__fcsr); 137 /* Ensure that flags are all legal */ 138 __excepts &= FE_ALL_EXCEPT; 139 /* Cause bit needs to be set as well for generating the exception*/ 140 __fcsr |= __excepts | (__excepts << _FCSR_CAUSE_SHIFT); 141 fesetenv(&__fcsr); 142 return 0; 143 } 144 145 static __inline int fetestexcept(int __excepts) { 146 fexcept_t __FCSR; 147 fegetenv(&__FCSR); 148 return (__FCSR & __excepts & FE_ALL_EXCEPT); 149 } 150 151 static __inline int fegetround(void) { 152 fenv_t _fcsr; 153 fegetenv(&_fcsr); 154 return (_fcsr & _FCSR_RMASK); 155 } 156 157 static __inline int fesetround(int __round) { 158 fenv_t _fcsr; 159 fegetenv(&_fcsr); 160 _fcsr &= ~_FCSR_RMASK; 161 _fcsr |= (__round & _FCSR_RMASK ) ; 162 fesetenv(&_fcsr); 163 return 0; 164 } 165 166 static __inline int feholdexcept(fenv_t* __envp) { 167 fenv_t __env; 168 fegetenv(&__env); 169 *__envp = __env; 170 __env &= ~(FE_ALL_EXCEPT | _FCSR_ENABLE_MASK); 171 fesetenv(&__env); 172 return 0; 173 } 174 175 static __inline int feupdateenv(const fenv_t* __envp) { 176 fexcept_t __fcsr; 177 fegetenv(&__fcsr); 178 fesetenv(__envp); 179 feraiseexcept(__fcsr & FE_ALL_EXCEPT); 180 return 0; 181 } 182 183 #if __BSD_VISIBLE 184 185 static __inline int feenableexcept(int __mask) { 186 fenv_t __old_fcsr, __new_fcsr; 187 fegetenv(&__old_fcsr); 188 __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT; 189 fesetenv(&__new_fcsr); 190 return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT); 191 } 192 193 static __inline int fedisableexcept(int __mask) { 194 fenv_t __old_fcsr, __new_fcsr; 195 fegetenv(&__old_fcsr); 196 __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT); 197 fesetenv(&__new_fcsr); 198 return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT); 199 } 200 201 static __inline int fegetexcept(void) { 202 fenv_t __fcsr; 203 fegetenv(&__fcsr); 204 return ((__fcsr & _FCSR_ENABLE_MASK) >> _ENABLE_SHIFT); 205 } 206 207 #endif /* __BSD_VISIBLE */ 208 209 __END_DECLS 210 211 #endif /* !_FENV_H_ */ 212