1 /*- 2 * Copyright (c) 2004 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.c,v 1.1 2008/04/26 12:20:29 imp Exp $ 27 */ 28 29 #ifndef ANDROID_LEGACY_FENV_INLINES_MIPS_H 30 #define ANDROID_LEGACY_FENV_INLINES_MIPS_H 31 32 #include <sys/cdefs.h> 33 34 #if __ANDROID_API__ < __ANDROID_API_L__ && (defined(__mips__) && !defined(__LP64__)) 35 36 #include <fenv.h> 37 38 __BEGIN_DECLS 39 40 #define FCSR_CAUSE_SHIFT 10 41 #define FCSR_ENABLE_SHIFT 5 42 #define FCSR_ENABLE_MASK (FE_ALL_EXCEPT << FCSR_ENABLE_SHIFT) 43 44 #define FCSR_RMASK 0x3 45 46 static __inline int fegetenv(fenv_t* __envp) { 47 fenv_t _fcsr = 0; 48 #ifdef __mips_hard_float 49 __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr)); 50 #endif 51 *__envp = _fcsr; 52 return 0; 53 } 54 55 static __inline int fesetenv(const fenv_t* __envp) { 56 fenv_t _fcsr = *__envp; 57 #ifdef __mips_hard_float 58 __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr)); 59 #endif 60 return 0; 61 } 62 63 static __inline int feclearexcept(int __excepts) { 64 fexcept_t __fcsr; 65 fegetenv(&__fcsr); 66 __excepts &= FE_ALL_EXCEPT; 67 __fcsr &= ~(__excepts | (__excepts << FCSR_CAUSE_SHIFT)); 68 fesetenv(&__fcsr); 69 return 0; 70 } 71 72 static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) { 73 fexcept_t __fcsr; 74 fegetenv(&__fcsr); 75 *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT; 76 return 0; 77 } 78 79 static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) { 80 fexcept_t __fcsr; 81 fegetenv(&__fcsr); 82 /* Ensure that flags are all legal */ 83 __excepts &= FE_ALL_EXCEPT; 84 __fcsr &= ~__excepts; 85 __fcsr |= *__flagp & __excepts; 86 fesetenv(&__fcsr); 87 return 0; 88 } 89 90 static __inline int feraiseexcept(int __excepts) { 91 fexcept_t __fcsr; 92 fegetenv(&__fcsr); 93 /* Ensure that flags are all legal */ 94 __excepts &= FE_ALL_EXCEPT; 95 /* Cause bit needs to be set as well for generating the exception*/ 96 __fcsr |= __excepts | (__excepts << FCSR_CAUSE_SHIFT); 97 fesetenv(&__fcsr); 98 return 0; 99 } 100 101 static __inline int fetestexcept(int __excepts) { 102 fexcept_t __FCSR; 103 fegetenv(&__FCSR); 104 return (__FCSR & __excepts & FE_ALL_EXCEPT); 105 } 106 107 static __inline int fegetround(void) { 108 fenv_t _fcsr; 109 fegetenv(&_fcsr); 110 return (_fcsr & FCSR_RMASK); 111 } 112 113 static __inline int fesetround(int __round) { 114 fenv_t _fcsr; 115 fegetenv(&_fcsr); 116 _fcsr &= ~FCSR_RMASK; 117 _fcsr |= (__round & FCSR_RMASK); 118 fesetenv(&_fcsr); 119 return 0; 120 } 121 122 static __inline int feholdexcept(fenv_t* __envp) { 123 fenv_t __env; 124 fegetenv(&__env); 125 *__envp = __env; 126 __env &= ~(FE_ALL_EXCEPT | FCSR_ENABLE_MASK); 127 fesetenv(&__env); 128 return 0; 129 } 130 131 static __inline int feupdateenv(const fenv_t* __envp) { 132 fexcept_t __fcsr; 133 fegetenv(&__fcsr); 134 fesetenv(__envp); 135 feraiseexcept(__fcsr & FE_ALL_EXCEPT); 136 return 0; 137 } 138 139 static __inline int feenableexcept(int __mask) { 140 fenv_t __old_fcsr, __new_fcsr; 141 fegetenv(&__old_fcsr); 142 __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT; 143 fesetenv(&__new_fcsr); 144 return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT); 145 } 146 147 static __inline int fedisableexcept(int __mask) { 148 fenv_t __old_fcsr, __new_fcsr; 149 fegetenv(&__old_fcsr); 150 __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT); 151 fesetenv(&__new_fcsr); 152 return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT); 153 } 154 155 static __inline int fegetexcept(void) { 156 fenv_t __fcsr; 157 fegetenv(&__fcsr); 158 return ((__fcsr & FCSR_ENABLE_MASK) >> FCSR_ENABLE_SHIFT); 159 } 160 161 #undef FCSR_CAUSE_SHIFT 162 #undef FCSR_ENABLE_SHIFT 163 #undef FCSR_ENABLE_MASK 164 #undef FCSR_RMASK 165 166 __END_DECLS 167 168 #endif /* __ANDROID_API__ < __ANDROID_API_L__ && (defined(__mips__) && !defined(__LP64__)) */ 169 170 #endif /* ANDROID_LEGACY_FENV_INLINES_MIPS_H */ 171