Merge commit '4cff0a5994d0300e6e77e90d3354aa517a120539' into upstream-merge
[qemu-kvm/stefanha.git] / fpu / softfloat-native.c
blobf89b82d8cc5e352bdc14bf55f18d0ecab480887d
1 /* Native implementation of soft float functions. Only a single status
2 context is supported */
3 #include "softfloat.h"
4 #include <math.h>
5 #if defined(CONFIG_SOLARIS)
6 #include <fenv.h>
7 #endif
8 #include "config-host.h"
10 void set_float_rounding_mode(int val STATUS_PARAM)
12 STATUS(float_rounding_mode) = val;
13 #if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) || \
14 (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
15 fpsetround(val);
16 #else
17 fesetround(val);
18 #endif
21 #ifdef FLOATX80
22 void set_floatx80_rounding_precision(int val STATUS_PARAM)
24 STATUS(floatx80_rounding_precision) = val;
26 #endif
28 #if defined(CONFIG_BSD) || \
29 (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
30 #define lrint(d) ((int32_t)rint(d))
31 #define llrint(d) ((int64_t)rint(d))
32 #define lrintf(f) ((int32_t)rint(f))
33 #define llrintf(f) ((int64_t)rint(f))
34 #define sqrtf(f) ((float)sqrt(f))
35 #define remainderf(fa, fb) ((float)remainder(fa, fb))
36 #define rintf(f) ((float)rint(f))
37 #if !defined(__sparc__) && \
38 (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
39 extern long double rintl(long double);
40 extern long double scalbnl(long double, int);
42 long long
43 llrintl(long double x) {
44 return ((long long) rintl(x));
47 long
48 lrintl(long double x) {
49 return ((long) rintl(x));
52 long double
53 ldexpl(long double x, int n) {
54 return (scalbnl(x, n));
56 #endif
57 #endif
59 #if defined(_ARCH_PPC)
61 /* correct (but slow) PowerPC rint() (glibc version is incorrect) */
62 static double qemu_rint(double x)
64 double y = 4503599627370496.0;
65 if (fabs(x) >= y)
66 return x;
67 if (x < 0)
68 y = -y;
69 y = (x + y) - y;
70 if (y == 0.0)
71 y = copysign(y, x);
72 return y;
75 #define rint qemu_rint
76 #endif
78 /*----------------------------------------------------------------------------
79 | Software IEC/IEEE integer-to-floating-point conversion routines.
80 *----------------------------------------------------------------------------*/
81 float32 int32_to_float32(int v STATUS_PARAM)
83 return (float32)v;
86 float32 uint32_to_float32(unsigned int v STATUS_PARAM)
88 return (float32)v;
91 float64 int32_to_float64(int v STATUS_PARAM)
93 return (float64)v;
96 float64 uint32_to_float64(unsigned int v STATUS_PARAM)
98 return (float64)v;
101 #ifdef FLOATX80
102 floatx80 int32_to_floatx80(int v STATUS_PARAM)
104 return (floatx80)v;
106 #endif
107 float32 int64_to_float32( int64_t v STATUS_PARAM)
109 return (float32)v;
111 float32 uint64_to_float32( uint64_t v STATUS_PARAM)
113 return (float32)v;
115 float64 int64_to_float64( int64_t v STATUS_PARAM)
117 return (float64)v;
119 float64 uint64_to_float64( uint64_t v STATUS_PARAM)
121 return (float64)v;
123 #ifdef FLOATX80
124 floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
126 return (floatx80)v;
128 #endif
130 /* XXX: this code implements the x86 behaviour, not the IEEE one. */
131 #if HOST_LONG_BITS == 32
132 static inline int long_to_int32(long a)
134 return a;
136 #else
137 static inline int long_to_int32(long a)
139 if (a != (int32_t)a)
140 a = 0x80000000;
141 return a;
143 #endif
145 /*----------------------------------------------------------------------------
146 | Software IEC/IEEE single-precision conversion routines.
147 *----------------------------------------------------------------------------*/
148 int float32_to_int32( float32 a STATUS_PARAM)
150 return long_to_int32(lrintf(a));
152 int float32_to_int32_round_to_zero( float32 a STATUS_PARAM)
154 return (int)a;
156 int64_t float32_to_int64( float32 a STATUS_PARAM)
158 return llrintf(a);
161 int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM)
163 return (int64_t)a;
166 float64 float32_to_float64( float32 a STATUS_PARAM)
168 return a;
170 #ifdef FLOATX80
171 floatx80 float32_to_floatx80( float32 a STATUS_PARAM)
173 return a;
175 #endif
177 unsigned int float32_to_uint32( float32 a STATUS_PARAM)
179 int64_t v;
180 unsigned int res;
182 v = llrintf(a);
183 if (v < 0) {
184 res = 0;
185 } else if (v > 0xffffffff) {
186 res = 0xffffffff;
187 } else {
188 res = v;
190 return res;
192 unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM)
194 int64_t v;
195 unsigned int res;
197 v = (int64_t)a;
198 if (v < 0) {
199 res = 0;
200 } else if (v > 0xffffffff) {
201 res = 0xffffffff;
202 } else {
203 res = v;
205 return res;
208 /*----------------------------------------------------------------------------
209 | Software IEC/IEEE single-precision operations.
210 *----------------------------------------------------------------------------*/
211 float32 float32_round_to_int( float32 a STATUS_PARAM)
213 return rintf(a);
216 float32 float32_rem( float32 a, float32 b STATUS_PARAM)
218 return remainderf(a, b);
221 float32 float32_sqrt( float32 a STATUS_PARAM)
223 return sqrtf(a);
225 int float32_compare( float32 a, float32 b STATUS_PARAM )
227 if (a < b) {
228 return float_relation_less;
229 } else if (a == b) {
230 return float_relation_equal;
231 } else if (a > b) {
232 return float_relation_greater;
233 } else {
234 return float_relation_unordered;
237 int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
239 if (isless(a, b)) {
240 return float_relation_less;
241 } else if (a == b) {
242 return float_relation_equal;
243 } else if (isgreater(a, b)) {
244 return float_relation_greater;
245 } else {
246 return float_relation_unordered;
249 int float32_is_signaling_nan( float32 a1)
251 float32u u;
252 uint32_t a;
253 u.f = a1;
254 a = u.i;
255 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
258 int float32_is_nan( float32 a1 )
260 float32u u;
261 uint64_t a;
262 u.f = a1;
263 a = u.i;
264 return ( 0xFF800000 < ( a<<1 ) );
267 /*----------------------------------------------------------------------------
268 | Software IEC/IEEE double-precision conversion routines.
269 *----------------------------------------------------------------------------*/
270 int float64_to_int32( float64 a STATUS_PARAM)
272 return long_to_int32(lrint(a));
274 int float64_to_int32_round_to_zero( float64 a STATUS_PARAM)
276 return (int)a;
278 int64_t float64_to_int64( float64 a STATUS_PARAM)
280 return llrint(a);
282 int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM)
284 return (int64_t)a;
286 float32 float64_to_float32( float64 a STATUS_PARAM)
288 return a;
290 #ifdef FLOATX80
291 floatx80 float64_to_floatx80( float64 a STATUS_PARAM)
293 return a;
295 #endif
296 #ifdef FLOAT128
297 float128 float64_to_float128( float64 a STATUS_PARAM)
299 return a;
301 #endif
303 unsigned int float64_to_uint32( float64 a STATUS_PARAM)
305 int64_t v;
306 unsigned int res;
308 v = llrint(a);
309 if (v < 0) {
310 res = 0;
311 } else if (v > 0xffffffff) {
312 res = 0xffffffff;
313 } else {
314 res = v;
316 return res;
318 unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM)
320 int64_t v;
321 unsigned int res;
323 v = (int64_t)a;
324 if (v < 0) {
325 res = 0;
326 } else if (v > 0xffffffff) {
327 res = 0xffffffff;
328 } else {
329 res = v;
331 return res;
333 uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
335 int64_t v;
337 v = llrint(a + (float64)INT64_MIN);
339 return v - INT64_MIN;
341 uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
343 int64_t v;
345 v = (int64_t)(a + (float64)INT64_MIN);
347 return v - INT64_MIN;
350 /*----------------------------------------------------------------------------
351 | Software IEC/IEEE double-precision operations.
352 *----------------------------------------------------------------------------*/
353 #if defined(__sun__) && \
354 (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
355 static inline float64 trunc(float64 x)
357 return x < 0 ? -floor(-x) : floor(x);
359 #endif
360 float64 float64_trunc_to_int( float64 a STATUS_PARAM )
362 return trunc(a);
365 float64 float64_round_to_int( float64 a STATUS_PARAM )
367 return rint(a);
370 float64 float64_rem( float64 a, float64 b STATUS_PARAM)
372 return remainder(a, b);
375 float64 float64_sqrt( float64 a STATUS_PARAM)
377 return sqrt(a);
379 int float64_compare( float64 a, float64 b STATUS_PARAM )
381 if (a < b) {
382 return float_relation_less;
383 } else if (a == b) {
384 return float_relation_equal;
385 } else if (a > b) {
386 return float_relation_greater;
387 } else {
388 return float_relation_unordered;
391 int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
393 if (isless(a, b)) {
394 return float_relation_less;
395 } else if (a == b) {
396 return float_relation_equal;
397 } else if (isgreater(a, b)) {
398 return float_relation_greater;
399 } else {
400 return float_relation_unordered;
403 int float64_is_signaling_nan( float64 a1)
405 float64u u;
406 uint64_t a;
407 u.f = a1;
408 a = u.i;
409 return
410 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
411 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
415 int float64_is_nan( float64 a1 )
417 float64u u;
418 uint64_t a;
419 u.f = a1;
420 a = u.i;
422 return ( LIT64( 0xFFF0000000000000 ) < (bits64) ( a<<1 ) );
426 #ifdef FLOATX80
428 /*----------------------------------------------------------------------------
429 | Software IEC/IEEE extended double-precision conversion routines.
430 *----------------------------------------------------------------------------*/
431 int floatx80_to_int32( floatx80 a STATUS_PARAM)
433 return long_to_int32(lrintl(a));
435 int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM)
437 return (int)a;
439 int64_t floatx80_to_int64( floatx80 a STATUS_PARAM)
441 return llrintl(a);
443 int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM)
445 return (int64_t)a;
447 float32 floatx80_to_float32( floatx80 a STATUS_PARAM)
449 return a;
451 float64 floatx80_to_float64( floatx80 a STATUS_PARAM)
453 return a;
456 /*----------------------------------------------------------------------------
457 | Software IEC/IEEE extended double-precision operations.
458 *----------------------------------------------------------------------------*/
459 floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
461 return rintl(a);
463 floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM)
465 return remainderl(a, b);
467 floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
469 return sqrtl(a);
471 int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
473 if (a < b) {
474 return float_relation_less;
475 } else if (a == b) {
476 return float_relation_equal;
477 } else if (a > b) {
478 return float_relation_greater;
479 } else {
480 return float_relation_unordered;
483 int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
485 if (isless(a, b)) {
486 return float_relation_less;
487 } else if (a == b) {
488 return float_relation_equal;
489 } else if (isgreater(a, b)) {
490 return float_relation_greater;
491 } else {
492 return float_relation_unordered;
495 int floatx80_is_signaling_nan( floatx80 a1)
497 floatx80u u;
498 uint64_t aLow;
499 u.f = a1;
501 aLow = u.i.low & ~ LIT64( 0x4000000000000000 );
502 return
503 ( ( u.i.high & 0x7FFF ) == 0x7FFF )
504 && (bits64) ( aLow<<1 )
505 && ( u.i.low == aLow );
508 int floatx80_is_nan( floatx80 a1 )
510 floatx80u u;
511 u.f = a1;
512 return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
515 #endif