1 /* 2 * Copyright 2013, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <portability.h> 18 #include <sys/types.h> 19 #include <fenv.h> 20 #include <fenv_portable.h> 21 22 static inline int mips64_change_except(int flags) { 23 int mips64flags = 0; 24 int exception = flags & FE_ALL_EXCEPT_PORTABLE; 25 26 // exception flags 27 if (exception & FE_INVALID_PORTABLE) 28 mips64flags |= FE_INVALID; 29 if (exception & FE_DIVBYZERO_PORTABLE) 30 mips64flags |= FE_DIVBYZERO; 31 if (exception & FE_OVERFLOW_PORTABLE) 32 mips64flags |= FE_OVERFLOW; 33 if (exception & FE_UNDERFLOW_PORTABLE) 34 mips64flags |= FE_UNDERFLOW; 35 if (exception & FE_INEXACT_PORTABLE) 36 mips64flags |= FE_INEXACT; 37 38 return mips64flags; 39 } 40 41 static inline int mips64_change_rounding(int flags) { 42 int mips64flags = 0; 43 int rounding = flags & 0x03; 44 45 // rounding flags 46 switch(rounding) 47 { 48 case FE_TONEAREST_PORTABLE: 49 mips64flags = FE_TONEAREST; 50 break; 51 case FE_DOWNWARD_PORTABLE: 52 mips64flags = FE_DOWNWARD; 53 break; 54 case FE_UPWARD_PORTABLE: 55 mips64flags = FE_UPWARD; 56 break; 57 case FE_TOWARDZERO_PORTABLE: 58 mips64flags = FE_TOWARDZERO; 59 break; 60 } 61 return mips64flags; 62 } 63 64 static inline int mips64_get_except(int mips64flags) { 65 int flags = 0; 66 int exception = mips64flags & FE_ALL_EXCEPT; 67 68 // exception flags 69 if (exception & FE_INVALID) 70 flags |= FE_INVALID_PORTABLE; 71 if (exception & FE_DIVBYZERO) 72 flags |= FE_DIVBYZERO_PORTABLE; 73 if (exception & FE_OVERFLOW) 74 flags |= FE_OVERFLOW_PORTABLE; 75 if (exception & FE_UNDERFLOW) 76 flags |= FE_UNDERFLOW_PORTABLE; 77 if (exception & FE_INEXACT) 78 flags |= FE_INEXACT_PORTABLE; 79 return flags; 80 } 81 82 static inline int mips64_get_rounding(int mips64flags) { 83 int flags = 0; 84 int rounding = mips64flags & _FCSR_RMASK; 85 86 // rounding flags 87 switch(rounding) 88 { 89 case FE_TONEAREST: 90 flags = FE_TONEAREST_PORTABLE; 91 break; 92 case FE_DOWNWARD: 93 flags = FE_DOWNWARD_PORTABLE; 94 break; 95 case FE_UPWARD: 96 flags = FE_UPWARD_PORTABLE; 97 break; 98 case FE_TOWARDZERO: 99 flags = FE_TOWARDZERO_PORTABLE; 100 break; 101 } 102 return flags; 103 } 104 105 106 int WRAP(feclearexcept)(int flag) { 107 return REAL(feclearexcept)(mips64_change_except(flag)); 108 } 109 110 int WRAP(fegetexceptflag)(fexcept_t_portable *obj, int flag) { 111 int ret = REAL(fegetexceptflag)((fexcept_t*)obj, mips64_change_except(flag)); 112 *obj = (fexcept_t_portable) mips64_get_except(*obj); 113 return ret; 114 } 115 116 int WRAP(feraiseexcept)(int flag) { 117 return REAL(feraiseexcept)(mips64_change_except(flag)); 118 } 119 120 int WRAP(fesetexceptflag)(const fexcept_t_portable *obj, int flag) { 121 const fexcept_t mips64obj = mips64_change_except(*obj); 122 int mips64flag = mips64_change_except(flag); 123 return REAL(fesetexceptflag)(&mips64obj, mips64flag); 124 } 125 126 int WRAP(fetestexcept)(int flag) { 127 int ret = REAL(fetestexcept)(mips64_change_except(flag)); 128 return mips64_get_except(ret); 129 } 130 131 int WRAP(fegetround)(void) { 132 int round = REAL(fegetround)(); 133 return mips64_get_rounding(round); 134 } 135 136 int WRAP(fesetround)(int round) { 137 return REAL(fesetround)(mips64_change_rounding(round)); 138 } 139 140 int WRAP(fegetenv)(fenv_t_portable *obj) { 141 return REAL(fegetenv)((fenv_t*)obj); 142 } 143 144 int WRAP(feholdexcept)(fenv_t_portable *obj) { 145 return REAL(feholdexcept)((fenv_t*)obj); 146 } 147 148 int WRAP(fesetenv)(const fenv_t_portable *obj) { 149 return REAL(fesetenv)((const fenv_t*)obj); 150 } 151 152 int WRAP(feupdateenv)(const fenv_t_portable *obj) { 153 return REAL(feupdateenv)((const fenv_t*)obj); 154 } 155 156 int WRAP(fegetexcept)(void) { 157 int flag = REAL(fegetexcept)(); 158 return mips64_get_except(flag); 159 } 160 161