Home | History | Annotate | Download | only in arch-mips64
      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