]>
Commit | Line | Data |
---|---|---|
158142c2 FB |
1 | /* Native implementation of soft float functions. Only a single status |
2 | context is supported */ | |
3 | #include "softfloat.h" | |
4 | #include <math.h> | |
5 | ||
6 | void set_float_rounding_mode(int val STATUS_PARAM) | |
7 | { | |
8 | STATUS(float_rounding_mode) = val; | |
179a2c19 BS |
9 | #if defined(HOST_BSD) && !defined(__APPLE__) || \ |
10 | (defined(HOST_SOLARIS) && HOST_SOLARIS < 10) | |
158142c2 FB |
11 | fpsetround(val); |
12 | #elif defined(__arm__) | |
13 | /* nothing to do */ | |
14 | #else | |
15 | fesetround(val); | |
16 | #endif | |
17 | } | |
18 | ||
19 | #ifdef FLOATX80 | |
20 | void set_floatx80_rounding_precision(int val STATUS_PARAM) | |
21 | { | |
22 | STATUS(floatx80_rounding_precision) = val; | |
23 | } | |
24 | #endif | |
25 | ||
179a2c19 | 26 | #if defined(HOST_BSD) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10) |
fdbb4691 FB |
27 | #define lrint(d) ((int32_t)rint(d)) |
28 | #define llrint(d) ((int64_t)rint(d)) | |
29 | #define lrintf(f) ((int32_t)rint(f)) | |
30 | #define llrintf(f) ((int64_t)rint(f)) | |
31 | #define sqrtf(f) ((float)sqrt(f)) | |
32 | #define remainderf(fa, fb) ((float)remainder(fa, fb)) | |
33 | #define rintf(f) ((float)rint(f)) | |
fc81ba53 | 34 | #if !defined(__sparc__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10 |
0475a5ca TS |
35 | extern long double rintl(long double); |
36 | extern long double scalbnl(long double, int); | |
37 | ||
38 | long long | |
39 | llrintl(long double x) { | |
40 | return ((long long) rintl(x)); | |
41 | } | |
42 | ||
43 | long | |
44 | lrintl(long double x) { | |
45 | return ((long) rintl(x)); | |
46 | } | |
47 | ||
48 | long double | |
49 | ldexpl(long double x, int n) { | |
50 | return (scalbnl(x, n)); | |
51 | } | |
52 | #endif | |
158142c2 FB |
53 | #endif |
54 | ||
e58ffeb3 | 55 | #if defined(_ARCH_PPC) |
158142c2 FB |
56 | |
57 | /* correct (but slow) PowerPC rint() (glibc version is incorrect) */ | |
947f5fcb | 58 | static double qemu_rint(double x) |
158142c2 FB |
59 | { |
60 | double y = 4503599627370496.0; | |
61 | if (fabs(x) >= y) | |
62 | return x; | |
5fafdf24 | 63 | if (x < 0) |
158142c2 FB |
64 | y = -y; |
65 | y = (x + y) - y; | |
66 | if (y == 0.0) | |
67 | y = copysign(y, x); | |
68 | return y; | |
69 | } | |
70 | ||
71 | #define rint qemu_rint | |
72 | #endif | |
73 | ||
74 | /*---------------------------------------------------------------------------- | |
75 | | Software IEC/IEEE integer-to-floating-point conversion routines. | |
76 | *----------------------------------------------------------------------------*/ | |
77 | float32 int32_to_float32(int v STATUS_PARAM) | |
78 | { | |
79 | return (float32)v; | |
80 | } | |
81 | ||
75d62a58 JM |
82 | float32 uint32_to_float32(unsigned int v STATUS_PARAM) |
83 | { | |
84 | return (float32)v; | |
85 | } | |
86 | ||
158142c2 FB |
87 | float64 int32_to_float64(int v STATUS_PARAM) |
88 | { | |
89 | return (float64)v; | |
90 | } | |
91 | ||
75d62a58 JM |
92 | float64 uint32_to_float64(unsigned int v STATUS_PARAM) |
93 | { | |
94 | return (float64)v; | |
95 | } | |
96 | ||
158142c2 FB |
97 | #ifdef FLOATX80 |
98 | floatx80 int32_to_floatx80(int v STATUS_PARAM) | |
99 | { | |
100 | return (floatx80)v; | |
101 | } | |
102 | #endif | |
103 | float32 int64_to_float32( int64_t v STATUS_PARAM) | |
104 | { | |
105 | return (float32)v; | |
106 | } | |
75d62a58 JM |
107 | float32 uint64_to_float32( uint64_t v STATUS_PARAM) |
108 | { | |
109 | return (float32)v; | |
110 | } | |
158142c2 FB |
111 | float64 int64_to_float64( int64_t v STATUS_PARAM) |
112 | { | |
113 | return (float64)v; | |
114 | } | |
75d62a58 JM |
115 | float64 uint64_to_float64( uint64_t v STATUS_PARAM) |
116 | { | |
117 | return (float64)v; | |
118 | } | |
158142c2 FB |
119 | #ifdef FLOATX80 |
120 | floatx80 int64_to_floatx80( int64_t v STATUS_PARAM) | |
121 | { | |
122 | return (floatx80)v; | |
123 | } | |
124 | #endif | |
125 | ||
1b2b0af5 FB |
126 | /* XXX: this code implements the x86 behaviour, not the IEEE one. */ |
127 | #if HOST_LONG_BITS == 32 | |
128 | static inline int long_to_int32(long a) | |
129 | { | |
130 | return a; | |
131 | } | |
132 | #else | |
133 | static inline int long_to_int32(long a) | |
134 | { | |
5fafdf24 | 135 | if (a != (int32_t)a) |
1b2b0af5 FB |
136 | a = 0x80000000; |
137 | return a; | |
138 | } | |
139 | #endif | |
140 | ||
158142c2 FB |
141 | /*---------------------------------------------------------------------------- |
142 | | Software IEC/IEEE single-precision conversion routines. | |
143 | *----------------------------------------------------------------------------*/ | |
144 | int float32_to_int32( float32 a STATUS_PARAM) | |
145 | { | |
1b2b0af5 | 146 | return long_to_int32(lrintf(a)); |
158142c2 FB |
147 | } |
148 | int float32_to_int32_round_to_zero( float32 a STATUS_PARAM) | |
149 | { | |
150 | return (int)a; | |
151 | } | |
152 | int64_t float32_to_int64( float32 a STATUS_PARAM) | |
153 | { | |
154 | return llrintf(a); | |
155 | } | |
156 | ||
157 | int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM) | |
158 | { | |
159 | return (int64_t)a; | |
160 | } | |
161 | ||
162 | float64 float32_to_float64( float32 a STATUS_PARAM) | |
163 | { | |
164 | return a; | |
165 | } | |
166 | #ifdef FLOATX80 | |
167 | floatx80 float32_to_floatx80( float32 a STATUS_PARAM) | |
168 | { | |
169 | return a; | |
170 | } | |
171 | #endif | |
172 | ||
75d62a58 JM |
173 | unsigned int float32_to_uint32( float32 a STATUS_PARAM) |
174 | { | |
175 | int64_t v; | |
176 | unsigned int res; | |
177 | ||
178 | v = llrintf(a); | |
179 | if (v < 0) { | |
180 | res = 0; | |
181 | } else if (v > 0xffffffff) { | |
182 | res = 0xffffffff; | |
183 | } else { | |
184 | res = v; | |
185 | } | |
186 | return res; | |
187 | } | |
188 | unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM) | |
189 | { | |
190 | int64_t v; | |
191 | unsigned int res; | |
192 | ||
193 | v = (int64_t)a; | |
194 | if (v < 0) { | |
195 | res = 0; | |
196 | } else if (v > 0xffffffff) { | |
197 | res = 0xffffffff; | |
198 | } else { | |
199 | res = v; | |
200 | } | |
201 | return res; | |
202 | } | |
203 | ||
158142c2 FB |
204 | /*---------------------------------------------------------------------------- |
205 | | Software IEC/IEEE single-precision operations. | |
206 | *----------------------------------------------------------------------------*/ | |
207 | float32 float32_round_to_int( float32 a STATUS_PARAM) | |
208 | { | |
209 | return rintf(a); | |
210 | } | |
211 | ||
b109f9f8 FB |
212 | float32 float32_rem( float32 a, float32 b STATUS_PARAM) |
213 | { | |
214 | return remainderf(a, b); | |
215 | } | |
216 | ||
158142c2 FB |
217 | float32 float32_sqrt( float32 a STATUS_PARAM) |
218 | { | |
219 | return sqrtf(a); | |
220 | } | |
750afe93 | 221 | int float32_compare( float32 a, float32 b STATUS_PARAM ) |
b109f9f8 FB |
222 | { |
223 | if (a < b) { | |
30e7a22e | 224 | return float_relation_less; |
b109f9f8 | 225 | } else if (a == b) { |
30e7a22e | 226 | return float_relation_equal; |
b109f9f8 | 227 | } else if (a > b) { |
30e7a22e | 228 | return float_relation_greater; |
b109f9f8 | 229 | } else { |
30e7a22e | 230 | return float_relation_unordered; |
b109f9f8 FB |
231 | } |
232 | } | |
750afe93 | 233 | int float32_compare_quiet( float32 a, float32 b STATUS_PARAM ) |
b109f9f8 FB |
234 | { |
235 | if (isless(a, b)) { | |
30e7a22e | 236 | return float_relation_less; |
b109f9f8 | 237 | } else if (a == b) { |
30e7a22e | 238 | return float_relation_equal; |
b109f9f8 | 239 | } else if (isgreater(a, b)) { |
30e7a22e | 240 | return float_relation_greater; |
b109f9f8 | 241 | } else { |
30e7a22e | 242 | return float_relation_unordered; |
b109f9f8 FB |
243 | } |
244 | } | |
750afe93 | 245 | int float32_is_signaling_nan( float32 a1) |
158142c2 FB |
246 | { |
247 | float32u u; | |
248 | uint32_t a; | |
249 | u.f = a1; | |
250 | a = u.i; | |
251 | return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); | |
252 | } | |
253 | ||
629bd74a AJ |
254 | int float32_is_nan( float32 a1 ) |
255 | { | |
256 | float32u u; | |
257 | uint64_t a; | |
258 | u.f = a1; | |
259 | a = u.i; | |
260 | return ( 0xFF800000 < ( a<<1 ) ); | |
261 | } | |
262 | ||
158142c2 FB |
263 | /*---------------------------------------------------------------------------- |
264 | | Software IEC/IEEE double-precision conversion routines. | |
265 | *----------------------------------------------------------------------------*/ | |
266 | int float64_to_int32( float64 a STATUS_PARAM) | |
267 | { | |
1b2b0af5 | 268 | return long_to_int32(lrint(a)); |
158142c2 FB |
269 | } |
270 | int float64_to_int32_round_to_zero( float64 a STATUS_PARAM) | |
271 | { | |
272 | return (int)a; | |
273 | } | |
274 | int64_t float64_to_int64( float64 a STATUS_PARAM) | |
275 | { | |
276 | return llrint(a); | |
277 | } | |
278 | int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM) | |
279 | { | |
280 | return (int64_t)a; | |
281 | } | |
282 | float32 float64_to_float32( float64 a STATUS_PARAM) | |
283 | { | |
284 | return a; | |
285 | } | |
286 | #ifdef FLOATX80 | |
287 | floatx80 float64_to_floatx80( float64 a STATUS_PARAM) | |
288 | { | |
289 | return a; | |
290 | } | |
291 | #endif | |
292 | #ifdef FLOAT128 | |
293 | float128 float64_to_float128( float64 a STATUS_PARAM) | |
294 | { | |
295 | return a; | |
296 | } | |
297 | #endif | |
298 | ||
75d62a58 JM |
299 | unsigned int float64_to_uint32( float64 a STATUS_PARAM) |
300 | { | |
301 | int64_t v; | |
302 | unsigned int res; | |
303 | ||
304 | v = llrint(a); | |
305 | if (v < 0) { | |
306 | res = 0; | |
307 | } else if (v > 0xffffffff) { | |
308 | res = 0xffffffff; | |
309 | } else { | |
310 | res = v; | |
311 | } | |
312 | return res; | |
313 | } | |
314 | unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM) | |
315 | { | |
316 | int64_t v; | |
317 | unsigned int res; | |
318 | ||
319 | v = (int64_t)a; | |
320 | if (v < 0) { | |
321 | res = 0; | |
322 | } else if (v > 0xffffffff) { | |
323 | res = 0xffffffff; | |
324 | } else { | |
325 | res = v; | |
326 | } | |
327 | return res; | |
328 | } | |
329 | uint64_t float64_to_uint64 (float64 a STATUS_PARAM) | |
330 | { | |
331 | int64_t v; | |
332 | ||
333 | v = llrint(a + (float64)INT64_MIN); | |
334 | ||
335 | return v - INT64_MIN; | |
336 | } | |
337 | uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM) | |
338 | { | |
339 | int64_t v; | |
340 | ||
341 | v = (int64_t)(a + (float64)INT64_MIN); | |
342 | ||
343 | return v - INT64_MIN; | |
344 | } | |
345 | ||
158142c2 FB |
346 | /*---------------------------------------------------------------------------- |
347 | | Software IEC/IEEE double-precision operations. | |
348 | *----------------------------------------------------------------------------*/ | |
fc81ba53 | 349 | #if defined(__sun__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10 |
63a654bb TS |
350 | static inline float64 trunc(float64 x) |
351 | { | |
352 | return x < 0 ? -floor(-x) : floor(x); | |
353 | } | |
354 | #endif | |
e6e5906b PB |
355 | float64 float64_trunc_to_int( float64 a STATUS_PARAM ) |
356 | { | |
357 | return trunc(a); | |
358 | } | |
359 | ||
158142c2 FB |
360 | float64 float64_round_to_int( float64 a STATUS_PARAM ) |
361 | { | |
362 | #if defined(__arm__) | |
363 | switch(STATUS(float_rounding_mode)) { | |
364 | default: | |
365 | case float_round_nearest_even: | |
366 | asm("rndd %0, %1" : "=f" (a) : "f"(a)); | |
367 | break; | |
368 | case float_round_down: | |
369 | asm("rnddm %0, %1" : "=f" (a) : "f"(a)); | |
370 | break; | |
371 | case float_round_up: | |
372 | asm("rnddp %0, %1" : "=f" (a) : "f"(a)); | |
373 | break; | |
374 | case float_round_to_zero: | |
375 | asm("rnddz %0, %1" : "=f" (a) : "f"(a)); | |
376 | break; | |
377 | } | |
378 | #else | |
379 | return rint(a); | |
380 | #endif | |
381 | } | |
382 | ||
b109f9f8 FB |
383 | float64 float64_rem( float64 a, float64 b STATUS_PARAM) |
384 | { | |
385 | return remainder(a, b); | |
386 | } | |
387 | ||
158142c2 FB |
388 | float64 float64_sqrt( float64 a STATUS_PARAM) |
389 | { | |
390 | return sqrt(a); | |
391 | } | |
750afe93 | 392 | int float64_compare( float64 a, float64 b STATUS_PARAM ) |
b109f9f8 FB |
393 | { |
394 | if (a < b) { | |
30e7a22e | 395 | return float_relation_less; |
b109f9f8 | 396 | } else if (a == b) { |
30e7a22e | 397 | return float_relation_equal; |
b109f9f8 | 398 | } else if (a > b) { |
30e7a22e | 399 | return float_relation_greater; |
b109f9f8 | 400 | } else { |
30e7a22e | 401 | return float_relation_unordered; |
b109f9f8 FB |
402 | } |
403 | } | |
750afe93 | 404 | int float64_compare_quiet( float64 a, float64 b STATUS_PARAM ) |
b109f9f8 FB |
405 | { |
406 | if (isless(a, b)) { | |
30e7a22e | 407 | return float_relation_less; |
b109f9f8 | 408 | } else if (a == b) { |
30e7a22e | 409 | return float_relation_equal; |
b109f9f8 | 410 | } else if (isgreater(a, b)) { |
30e7a22e | 411 | return float_relation_greater; |
b109f9f8 | 412 | } else { |
30e7a22e | 413 | return float_relation_unordered; |
b109f9f8 FB |
414 | } |
415 | } | |
750afe93 | 416 | int float64_is_signaling_nan( float64 a1) |
158142c2 FB |
417 | { |
418 | float64u u; | |
419 | uint64_t a; | |
420 | u.f = a1; | |
421 | a = u.i; | |
422 | return | |
423 | ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) | |
424 | && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); | |
425 | ||
426 | } | |
427 | ||
750afe93 | 428 | int float64_is_nan( float64 a1 ) |
e6e5906b PB |
429 | { |
430 | float64u u; | |
431 | uint64_t a; | |
432 | u.f = a1; | |
433 | a = u.i; | |
434 | ||
1b2ad2ec | 435 | return ( LIT64( 0xFFF0000000000000 ) < (bits64) ( a<<1 ) ); |
e6e5906b PB |
436 | |
437 | } | |
438 | ||
158142c2 FB |
439 | #ifdef FLOATX80 |
440 | ||
441 | /*---------------------------------------------------------------------------- | |
442 | | Software IEC/IEEE extended double-precision conversion routines. | |
443 | *----------------------------------------------------------------------------*/ | |
444 | int floatx80_to_int32( floatx80 a STATUS_PARAM) | |
445 | { | |
1b2b0af5 | 446 | return long_to_int32(lrintl(a)); |
158142c2 FB |
447 | } |
448 | int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM) | |
449 | { | |
450 | return (int)a; | |
451 | } | |
452 | int64_t floatx80_to_int64( floatx80 a STATUS_PARAM) | |
453 | { | |
454 | return llrintl(a); | |
455 | } | |
456 | int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM) | |
457 | { | |
458 | return (int64_t)a; | |
459 | } | |
460 | float32 floatx80_to_float32( floatx80 a STATUS_PARAM) | |
461 | { | |
462 | return a; | |
463 | } | |
464 | float64 floatx80_to_float64( floatx80 a STATUS_PARAM) | |
465 | { | |
466 | return a; | |
467 | } | |
468 | ||
469 | /*---------------------------------------------------------------------------- | |
470 | | Software IEC/IEEE extended double-precision operations. | |
471 | *----------------------------------------------------------------------------*/ | |
472 | floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM) | |
473 | { | |
474 | return rintl(a); | |
475 | } | |
b109f9f8 FB |
476 | floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM) |
477 | { | |
478 | return remainderl(a, b); | |
479 | } | |
158142c2 FB |
480 | floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM) |
481 | { | |
482 | return sqrtl(a); | |
483 | } | |
750afe93 | 484 | int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM ) |
b109f9f8 FB |
485 | { |
486 | if (a < b) { | |
30e7a22e | 487 | return float_relation_less; |
b109f9f8 | 488 | } else if (a == b) { |
30e7a22e | 489 | return float_relation_equal; |
b109f9f8 | 490 | } else if (a > b) { |
30e7a22e | 491 | return float_relation_greater; |
b109f9f8 | 492 | } else { |
30e7a22e | 493 | return float_relation_unordered; |
b109f9f8 FB |
494 | } |
495 | } | |
750afe93 | 496 | int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM ) |
b109f9f8 FB |
497 | { |
498 | if (isless(a, b)) { | |
30e7a22e | 499 | return float_relation_less; |
b109f9f8 | 500 | } else if (a == b) { |
30e7a22e | 501 | return float_relation_equal; |
b109f9f8 | 502 | } else if (isgreater(a, b)) { |
30e7a22e | 503 | return float_relation_greater; |
b109f9f8 | 504 | } else { |
30e7a22e | 505 | return float_relation_unordered; |
b109f9f8 FB |
506 | } |
507 | } | |
750afe93 | 508 | int floatx80_is_signaling_nan( floatx80 a1) |
1b2ad2ec AJ |
509 | { |
510 | floatx80u u; | |
511 | uint64_t aLow; | |
512 | u.f = a1; | |
513 | ||
514 | aLow = u.i.low & ~ LIT64( 0x4000000000000000 ); | |
515 | return | |
516 | ( ( u.i.high & 0x7FFF ) == 0x7FFF ) | |
517 | && (bits64) ( aLow<<1 ) | |
518 | && ( u.i.low == aLow ); | |
519 | } | |
520 | ||
521 | int floatx80_is_nan( floatx80 a1 ) | |
158142c2 FB |
522 | { |
523 | floatx80u u; | |
524 | u.f = a1; | |
525 | return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 ); | |
526 | } | |
527 | ||
528 | #endif |