• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
mips_change_except(int flags)22 static inline int mips_change_except(int flags)
23 {
24     int mipsflags = 0;
25     int exception = flags & FE_ALL_EXCEPT_PORTABLE;
26 
27     // exception flags
28     if (exception & FE_INVALID_PORTABLE)
29         mipsflags |= FE_INVALID;
30     if (exception & FE_DIVBYZERO_PORTABLE)
31         mipsflags |= FE_DIVBYZERO;
32     if (exception & FE_OVERFLOW_PORTABLE)
33         mipsflags |= FE_OVERFLOW;
34     if (exception & FE_UNDERFLOW_PORTABLE)
35         mipsflags |= FE_UNDERFLOW;
36     if (exception & FE_INEXACT_PORTABLE)
37         mipsflags |= FE_INEXACT;
38 
39     return mipsflags;
40 }
41 
mips_change_rounding(int flags)42 static inline int mips_change_rounding(int flags)
43 {
44     int mipsflags = 0;
45     int rounding = flags & 0x03;
46 
47     // rounding flags
48     switch(rounding)
49     {
50       case FE_TONEAREST_PORTABLE:
51         mipsflags = FE_TONEAREST;
52         break;
53       case FE_DOWNWARD_PORTABLE:
54         mipsflags = FE_DOWNWARD;
55         break;
56       case FE_UPWARD_PORTABLE:
57         mipsflags = FE_UPWARD;
58         break;
59       case FE_TOWARDZERO_PORTABLE:
60         mipsflags = FE_TOWARDZERO;
61         break;
62     }
63     return mipsflags;
64 }
65 
mips_get_except(int mipsflags)66 static inline int mips_get_except(int mipsflags)
67 {
68     int flags = 0;
69     int exception = mipsflags & FE_ALL_EXCEPT;
70 
71     // exception flags
72     if (exception & FE_INVALID)
73         flags |= FE_INVALID_PORTABLE;
74     if (exception & FE_DIVBYZERO)
75         flags |= FE_DIVBYZERO_PORTABLE;
76     if (exception & FE_OVERFLOW)
77         flags |= FE_OVERFLOW_PORTABLE;
78     if (exception & FE_UNDERFLOW)
79         flags |= FE_UNDERFLOW_PORTABLE;
80     if (exception & FE_INEXACT)
81         flags |= FE_INEXACT_PORTABLE;
82     return flags;
83 }
84 
mips_get_rounding(int mipsflags)85 static inline int mips_get_rounding(int mipsflags)
86 {
87     int flags = 0;
88     int rounding = mipsflags & _FCSR_RMASK;
89 
90     // rounding flags
91     switch(rounding)
92     {
93       case FE_TONEAREST:
94         flags = FE_TONEAREST_PORTABLE;
95         break;
96       case FE_DOWNWARD:
97         flags = FE_DOWNWARD_PORTABLE;
98         break;
99       case FE_UPWARD:
100         flags = FE_UPWARD_PORTABLE;
101         break;
102       case FE_TOWARDZERO:
103         flags = FE_TOWARDZERO_PORTABLE;
104         break;
105     }
106     return flags;
107 }
108 
WRAP(fegetenv)109 int WRAP(fegetenv)(fenv_t* __envp) {
110    fenv_t _fcsr = 0;
111 #ifdef  __mips_hard_float
112    __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
113 #endif
114    *__envp = _fcsr;
115    return 0;
116 }
117 
WRAP(fesetenv)118 int WRAP(fesetenv)(const fenv_t* __envp) {
119   fenv_t _fcsr = *__envp;
120 #ifdef  __mips_hard_float
121   __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
122 #endif
123   return 0;
124 }
125 
WRAP(feclearexcept)126 int WRAP(feclearexcept)(int __excepts) {
127   __excepts = mips_change_except(__excepts);
128   fexcept_t __fcsr;
129   WRAP(fegetenv)(&__fcsr);
130   __excepts &= FE_ALL_EXCEPT;
131   __fcsr &= ~(__excepts | (__excepts << _FCSR_CAUSE_SHIFT));
132   WRAP(fesetenv)(&__fcsr);
133   return 0;
134 }
135 
WRAP(fegetexceptflag)136 int WRAP(fegetexceptflag)(fexcept_t* __flagp, int __excepts) {
137   __excepts = mips_change_except(__excepts);
138   fexcept_t __fcsr;
139   WRAP(fegetenv)(&__fcsr);
140   *__flagp = mips_get_except(__fcsr & __excepts & FE_ALL_EXCEPT);
141   return 0;
142 }
143 
WRAP(fesetexceptflag)144 int WRAP(fesetexceptflag)(const fexcept_t* __flagp, int __excepts) {
145   int __flagp_ = mips_change_except(*__flagp);
146   __excepts = mips_change_except(__excepts);
147   fexcept_t __fcsr;
148   WRAP(fegetenv)(&__fcsr);
149   /* Ensure that flags are all legal */
150   __excepts &= FE_ALL_EXCEPT;
151   __fcsr &= ~__excepts;
152   __fcsr |= __flagp_ & __excepts;
153   WRAP(fesetenv)(&__fcsr);
154   return 0;
155 }
156 
WRAP(feraiseexcept)157 int WRAP(feraiseexcept)(int __excepts) {
158   __excepts = mips_change_except(__excepts);
159   fexcept_t __fcsr;
160   WRAP(fegetenv)(&__fcsr);
161   /* Ensure that flags are all legal */
162   __excepts &= FE_ALL_EXCEPT;
163   /* Cause bit needs to be set as well for generating the exception*/
164   __fcsr |= __excepts | (__excepts << _FCSR_CAUSE_SHIFT);
165   WRAP(fesetenv)(&__fcsr);
166   return 0;
167 }
168 
WRAP(fetestexcept)169 int WRAP(fetestexcept)(int __excepts) {
170    __excepts = mips_change_except(__excepts);
171   fexcept_t __FCSR;
172   WRAP(fegetenv)(&__FCSR);
173   return mips_get_except(__FCSR & __excepts & FE_ALL_EXCEPT);
174 }
175 
WRAP(fegetround)176 int WRAP(fegetround)(void) {
177   fenv_t _fcsr;
178   WRAP(fegetenv)(&_fcsr);
179   return mips_get_rounding(_fcsr & _FCSR_RMASK);
180 }
181 
WRAP(fesetround)182 int WRAP(fesetround)(int __round) {
183   __round = mips_change_rounding(__round);
184   fenv_t _fcsr;
185   WRAP(fegetenv)(&_fcsr);
186   _fcsr &= ~_FCSR_RMASK;
187   _fcsr |= (__round & _FCSR_RMASK );
188   WRAP(fesetenv)(&_fcsr);
189   return 0;
190 }
191 
WRAP(feholdexcept)192 int WRAP(feholdexcept)(fenv_t* __envp) {
193   fenv_t __env;
194   WRAP(fegetenv)(&__env);
195   *__envp = __env;
196   __env &= ~(FE_ALL_EXCEPT | _FCSR_ENABLE_MASK);
197   WRAP(fesetenv)(&__env);
198   return 0;
199 }
200 
WRAP(feupdateenv)201 int WRAP(feupdateenv)(const fenv_t* __envp) {
202   fexcept_t __fcsr;
203   WRAP(fegetenv)(&__fcsr);
204   WRAP(fesetenv)(__envp);
205   WRAP(feraiseexcept)(__fcsr & FE_ALL_EXCEPT);
206   return 0;
207 }
208 
209