• 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 
18 #include <portability.h>
19 
20 #include <sys/cdefs.h>
21 #include <sys/types.h>
22 #include <fenv.h>
23 #include <fenv_portable.h>
24 
x86_change_except(int flags)25 static inline int x86_change_except(int flags)
26 {
27     int x86flags = 0;
28     int exception = flags & FE_ALL_EXCEPT_PORTABLE;
29 
30     // exception flags
31     if (exception & FE_INVALID_PORTABLE)
32         x86flags |= FE_INVALID;
33     if (exception & FE_DIVBYZERO_PORTABLE)
34         x86flags |= FE_DIVBYZERO;
35     if (exception & FE_OVERFLOW_PORTABLE)
36         x86flags |= FE_OVERFLOW;
37     if (exception & FE_UNDERFLOW_PORTABLE)
38         x86flags |= FE_UNDERFLOW;
39     if (exception & FE_INEXACT_PORTABLE)
40         x86flags |= FE_INEXACT;
41 
42     return x86flags;
43 }
44 
x86_change_rounding(int flags)45 static inline int x86_change_rounding(int flags)
46 {
47     int x86flags = 0;
48     int rounding = flags & 0x03;
49 
50     // rounding flags
51     switch(rounding)
52     {
53         case FE_TONEAREST_PORTABLE:
54             x86flags = FE_TONEAREST;
55             break;
56         case FE_DOWNWARD_PORTABLE:
57             x86flags = FE_DOWNWARD;
58             break;
59         case FE_UPWARD_PORTABLE:
60             x86flags = FE_UPWARD;
61             break;
62         case FE_TOWARDZERO_PORTABLE:
63             x86flags = FE_TOWARDZERO;
64             break;
65     }
66     return x86flags;
67 }
68 
x86_get_except(int x86flags)69 static inline int x86_get_except(int x86flags)
70 {
71     int flags = 0;
72     int exception = x86flags & FE_ALL_EXCEPT;
73 
74     // exception flags
75     if (exception & FE_INVALID)
76         flags |= FE_INVALID_PORTABLE;
77     if (exception & FE_DIVBYZERO)
78         flags |= FE_DIVBYZERO_PORTABLE;
79     if (exception & FE_OVERFLOW)
80         flags |= FE_OVERFLOW_PORTABLE;
81     if (exception & FE_UNDERFLOW)
82         flags |= FE_UNDERFLOW_PORTABLE;
83     if (exception & FE_INEXACT)
84         flags |= FE_INEXACT_PORTABLE;
85 
86     return flags;
87 }
x86_get_rounding(int x86flags)88 static inline int x86_get_rounding(int x86flags)
89 {
90     int flags = 0;
91     int rounding = x86flags & _ROUND_MASK;
92 
93     // rounding flags
94     switch(rounding)
95     {
96         case FE_TONEAREST:
97             flags = FE_TONEAREST_PORTABLE;
98             break;
99         case FE_DOWNWARD:
100             flags = FE_DOWNWARD_PORTABLE;
101             break;
102         case FE_UPWARD:
103             flags = FE_UPWARD_PORTABLE;
104             break;
105         case FE_TOWARDZERO:
106             flags = FE_TOWARDZERO_PORTABLE;
107             break;
108     }
109 
110     return flags;
111 }
112 
113 int
WRAP(fesetexceptflag)114 WRAP(fesetexceptflag)(const fexcept_t *flagp, int excepts)
115 {
116     const fexcept_t flagp_ = x86_change_except(*flagp);
117     int excepts_ = x86_change_except(excepts);
118     return REAL(fesetexceptflag)(&flagp_, excepts_);
119 }
120 
121 int
WRAP(fegetexceptflag)122 WRAP(fegetexceptflag)(fexcept_t *flagp, int excepts)
123 {
124     REAL(fegetexceptflag)(flagp, x86_change_except(excepts));
125     *flagp = x86_get_except(*flagp);
126     return 0;
127 }
128 
129 int
WRAP(feraiseexcept)130 WRAP(feraiseexcept)(int excepts)
131 {
132     return REAL(feraiseexcept)(x86_change_except(excepts));
133 }
134 
135 int
WRAP(feclearexcept)136 WRAP(feclearexcept)(int excepts)
137 {
138     return REAL(feclearexcept)(x86_change_except(excepts));
139 }
140 
141 int
WRAP(fetestexcept)142 WRAP(fetestexcept)(int excepts)
143 {
144     int ret = REAL(fetestexcept)(x86_change_except(excepts));
145     return x86_get_except(ret);
146 }
147 
148 int
WRAP(fegetround)149 WRAP(fegetround)(void)
150 {
151     int round = REAL(fegetround)();
152     return x86_get_rounding(round);
153 }
154 
155 int
WRAP(fesetround)156 WRAP(fesetround)(int round)
157 {
158     return REAL(fesetround)(x86_change_rounding(round));
159 }
160 
161 int
WRAP(fegetexcept)162 WRAP(fegetexcept)(void)
163 {
164     int flags = REAL(fegetexcept)();
165     return x86_get_except(flags);
166 }
167 
168