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