6f3b6a98a1e64f8603100c8ee06e35ec04780943
[qemu] / fpu / softfloat-native.h
1 /* Native implementation of soft float functions */
2 #include <math.h>
3 #if defined(_BSD) && !defined(__APPLE__)
4 #include <ieeefp.h>
5 #else
6 #if !defined(_PRESOLARIS10)
7 #include <fenv.h>
8 #endif
9 #endif
10 #include "gnu-c99-math.h"
11
12 typedef float float32;
13 typedef double float64;
14 #ifdef FLOATX80
15 typedef long double floatx80;
16 #endif
17
18 typedef union {
19     float32 f;
20     uint32_t i;
21 } float32u;
22 typedef union {
23     float64 f;
24     uint64_t i;
25 } float64u;
26 #ifdef FLOATX80
27 typedef union {
28     floatx80 f;
29     struct {
30         uint64_t low;
31         uint16_t high;
32     } i;
33 } floatx80u;
34 #endif
35
36 /*----------------------------------------------------------------------------
37 | Software IEC/IEEE floating-point rounding mode.
38 *----------------------------------------------------------------------------*/
39 #if defined(_BSD) && !defined(__APPLE__)
40 enum {
41     float_round_nearest_even = FP_RN,
42     float_round_down         = FE_RM,
43     float_round_up           = FE_RP,
44     float_round_to_zero      = FE_RZ
45 };
46 #elif defined(__arm__)
47 enum {
48     float_round_nearest_even = 0,
49     float_round_down         = 1,
50     float_round_up           = 2,
51     float_round_to_zero      = 3
52 };
53 #else
54 enum {
55     float_round_nearest_even = FE_TONEAREST,
56     float_round_down         = FE_DOWNWARD,
57     float_round_up           = FE_UPWARD,
58     float_round_to_zero      = FE_TOWARDZERO
59 };
60 #endif
61
62 typedef struct float_status {
63     signed char float_rounding_mode;
64 #ifdef FLOATX80
65     signed char floatx80_rounding_precision;
66 #endif
67 } float_status;
68
69 void set_float_rounding_mode(int val STATUS_PARAM);
70 #ifdef FLOATX80
71 void set_floatx80_rounding_precision(int val STATUS_PARAM);
72 #endif
73
74 /*----------------------------------------------------------------------------
75 | Software IEC/IEEE integer-to-floating-point conversion routines.
76 *----------------------------------------------------------------------------*/
77 float32 int32_to_float32( int STATUS_PARAM);
78 float64 int32_to_float64( int STATUS_PARAM);
79 #ifdef FLOATX80
80 floatx80 int32_to_floatx80( int STATUS_PARAM);
81 #endif
82 #ifdef FLOAT128
83 float128 int32_to_float128( int STATUS_PARAM);
84 #endif
85 float32 int64_to_float32( int64_t STATUS_PARAM);
86 float64 int64_to_float64( int64_t STATUS_PARAM);
87 #ifdef FLOATX80
88 floatx80 int64_to_floatx80( int64_t STATUS_PARAM);
89 #endif
90 #ifdef FLOAT128
91 float128 int64_to_float128( int64_t STATUS_PARAM);
92 #endif
93
94 /*----------------------------------------------------------------------------
95 | Software IEC/IEEE single-precision conversion routines.
96 *----------------------------------------------------------------------------*/
97 int float32_to_int32( float32  STATUS_PARAM);
98 int float32_to_int32_round_to_zero( float32  STATUS_PARAM);
99 int64_t float32_to_int64( float32  STATUS_PARAM);
100 int64_t float32_to_int64_round_to_zero( float32  STATUS_PARAM);
101 float64 float32_to_float64( float32  STATUS_PARAM);
102 #ifdef FLOATX80
103 floatx80 float32_to_floatx80( float32  STATUS_PARAM);
104 #endif
105 #ifdef FLOAT128
106 float128 float32_to_float128( float32  STATUS_PARAM);
107 #endif
108
109 /*----------------------------------------------------------------------------
110 | Software IEC/IEEE single-precision operations.
111 *----------------------------------------------------------------------------*/
112 float32 float32_round_to_int( float32  STATUS_PARAM);
113 INLINE float32 float32_add( float32 a, float32 b STATUS_PARAM)
114 {
115     return a + b;
116 }
117 INLINE float32 float32_sub( float32 a, float32 b STATUS_PARAM)
118 {
119     return a - b;
120 }
121 INLINE float32 float32_mul( float32 a, float32 b STATUS_PARAM)
122 {
123     return a * b;
124 }
125 INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM)
126 {
127     return a / b;
128 }
129 float32 float32_rem( float32, float32  STATUS_PARAM);
130 float32 float32_sqrt( float32  STATUS_PARAM);
131 INLINE char float32_eq( float32 a, float32 b STATUS_PARAM)
132 {
133     return a == b;
134 }
135 INLINE char float32_le( float32 a, float32 b STATUS_PARAM)
136 {
137     return a <= b;
138 }
139 INLINE char float32_lt( float32 a, float32 b STATUS_PARAM)
140 {
141     return a < b;
142 }
143 INLINE char float32_eq_signaling( float32 a, float32 b STATUS_PARAM)
144 {
145     return a <= b && a >= b;
146 }
147 INLINE char float32_le_quiet( float32 a, float32 b STATUS_PARAM)
148 {
149     return islessequal(a, b);
150 }
151 INLINE char float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
152 {
153     return isless(a, b);
154 }
155 INLINE char float32_unordered( float32 a, float32 b STATUS_PARAM)
156 {
157     return isunordered(a, b);
158
159 }
160 char float32_compare( float32, float32 STATUS_PARAM );
161 char float32_compare_quiet( float32, float32 STATUS_PARAM );
162 char float32_is_signaling_nan( float32 );
163
164 INLINE float32 float32_abs(float32 a)
165 {
166     return fabsf(a);
167 }
168
169 INLINE float32 float32_chs(float32 a)
170 {
171     return -a;
172 }
173
174 /*----------------------------------------------------------------------------
175 | Software IEC/IEEE double-precision conversion routines.
176 *----------------------------------------------------------------------------*/
177 int float64_to_int32( float64 STATUS_PARAM );
178 int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
179 int64_t float64_to_int64( float64 STATUS_PARAM );
180 int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
181 float32 float64_to_float32( float64 STATUS_PARAM );
182 #ifdef FLOATX80
183 floatx80 float64_to_floatx80( float64 STATUS_PARAM );
184 #endif
185 #ifdef FLOAT128
186 float128 float64_to_float128( float64 STATUS_PARAM );
187 #endif
188
189 /*----------------------------------------------------------------------------
190 | Software IEC/IEEE double-precision operations.
191 *----------------------------------------------------------------------------*/
192 float64 float64_round_to_int( float64 STATUS_PARAM );
193 INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM)
194 {
195     return a + b;
196 }
197 INLINE float64 float64_sub( float64 a, float64 b STATUS_PARAM)
198 {
199     return a - b;
200 }
201 INLINE float64 float64_mul( float64 a, float64 b STATUS_PARAM)
202 {
203     return a * b;
204 }
205 INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM)
206 {
207     return a / b;
208 }
209 float64 float64_rem( float64, float64 STATUS_PARAM );
210 float64 float64_sqrt( float64 STATUS_PARAM );
211 INLINE char float64_eq( float64 a, float64 b STATUS_PARAM)
212 {
213     return a == b;
214 }
215 INLINE char float64_le( float64 a, float64 b STATUS_PARAM)
216 {
217     return a <= b;
218 }
219 INLINE char float64_lt( float64 a, float64 b STATUS_PARAM)
220 {
221     return a < b;
222 }
223 INLINE char float64_eq_signaling( float64 a, float64 b STATUS_PARAM)
224 {
225     return a <= b && a >= b;
226 }
227 INLINE char float64_le_quiet( float64 a, float64 b STATUS_PARAM)
228 {
229     return islessequal(a, b);
230 }
231 INLINE char float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
232 {
233     return isless(a, b);
234
235 }
236 INLINE char float64_unordered( float64 a, float64 b STATUS_PARAM)
237 {
238     return isunordered(a, b);
239
240 }
241 char float64_compare( float64, float64 STATUS_PARAM );
242 char float64_compare_quiet( float64, float64 STATUS_PARAM );
243 char float64_is_signaling_nan( float64 );
244
245 INLINE float64 float64_abs(float64 a)
246 {
247     return fabs(a);
248 }
249
250 INLINE float64 float64_chs(float64 a)
251 {
252     return -a;
253 }
254
255 #ifdef FLOATX80
256
257 /*----------------------------------------------------------------------------
258 | Software IEC/IEEE extended double-precision conversion routines.
259 *----------------------------------------------------------------------------*/
260 int floatx80_to_int32( floatx80 STATUS_PARAM );
261 int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM );
262 int64_t floatx80_to_int64( floatx80 STATUS_PARAM);
263 int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM);
264 float32 floatx80_to_float32( floatx80 STATUS_PARAM );
265 float64 floatx80_to_float64( floatx80 STATUS_PARAM );
266 #ifdef FLOAT128
267 float128 floatx80_to_float128( floatx80 STATUS_PARAM );
268 #endif
269
270 /*----------------------------------------------------------------------------
271 | Software IEC/IEEE extended double-precision operations.
272 *----------------------------------------------------------------------------*/
273 floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM );
274 INLINE floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM)
275 {
276     return a + b;
277 }
278 INLINE floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM)
279 {
280     return a - b;
281 }
282 INLINE floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM)
283 {
284     return a * b;
285 }
286 INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM)
287 {
288     return a / b;
289 }
290 floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
291 floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
292 INLINE char floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
293 {
294     return a == b;
295 }
296 INLINE char floatx80_le( floatx80 a, floatx80 b STATUS_PARAM)
297 {
298     return a <= b;
299 }
300 INLINE char floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
301 {
302     return a < b;
303 }
304 INLINE char floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM)
305 {
306     return a <= b && a >= b;
307 }
308 INLINE char floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM)
309 {
310     return islessequal(a, b);
311 }
312 INLINE char floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
313 {
314     return isless(a, b);
315
316 }
317 INLINE char floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
318 {
319     return isunordered(a, b);
320
321 }
322 char floatx80_compare( floatx80, floatx80 STATUS_PARAM );
323 char floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
324 char floatx80_is_signaling_nan( floatx80 );
325
326 INLINE floatx80 floatx80_abs(floatx80 a)
327 {
328     return fabsl(a);
329 }
330
331 INLINE floatx80 floatx80_chs(floatx80 a)
332 {
333     return -a;
334 }
335 #endif