Rename _BSD to HOST_BSD so that it's more obvious that it's defined by configure
[qemu] / fpu / softfloat-native.c
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;
9 #if defined(HOST_BSD) && !defined(__APPLE__) ||         \
10     (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
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
26 #if defined(HOST_BSD) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
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))
34 #if !defined(__sparc__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10
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
53 #endif
54
55 #if defined(_ARCH_PPC)
56
57 /* correct (but slow) PowerPC rint() (glibc version is incorrect) */
58 static double qemu_rint(double x)
59 {
60     double y = 4503599627370496.0;
61     if (fabs(x) >= y)
62         return x;
63     if (x < 0)
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
82 float32 uint32_to_float32(unsigned int v STATUS_PARAM)
83 {
84     return (float32)v;
85 }
86
87 float64 int32_to_float64(int v STATUS_PARAM)
88 {
89     return (float64)v;
90 }
91
92 float64 uint32_to_float64(unsigned int v STATUS_PARAM)
93 {
94     return (float64)v;
95 }
96
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 }
107 float32 uint64_to_float32( uint64_t v STATUS_PARAM)
108 {
109     return (float32)v;
110 }
111 float64 int64_to_float64( int64_t v STATUS_PARAM)
112 {
113     return (float64)v;
114 }
115 float64 uint64_to_float64( uint64_t v STATUS_PARAM)
116 {
117     return (float64)v;
118 }
119 #ifdef FLOATX80
120 floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
121 {
122     return (floatx80)v;
123 }
124 #endif
125
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 {
135     if (a != (int32_t)a)
136         a = 0x80000000;
137     return a;
138 }
139 #endif
140
141 /*----------------------------------------------------------------------------
142 | Software IEC/IEEE single-precision conversion routines.
143 *----------------------------------------------------------------------------*/
144 int float32_to_int32( float32 a STATUS_PARAM)
145 {
146     return long_to_int32(lrintf(a));
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
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
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
212 float32 float32_rem( float32 a, float32 b STATUS_PARAM)
213 {
214     return remainderf(a, b);
215 }
216
217 float32 float32_sqrt( float32 a STATUS_PARAM)
218 {
219     return sqrtf(a);
220 }
221 int float32_compare( float32 a, float32 b STATUS_PARAM )
222 {
223     if (a < b) {
224         return float_relation_less;
225     } else if (a == b) {
226         return float_relation_equal;
227     } else if (a > b) {
228         return float_relation_greater;
229     } else {
230         return float_relation_unordered;
231     }
232 }
233 int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
234 {
235     if (isless(a, b)) {
236         return float_relation_less;
237     } else if (a == b) {
238         return float_relation_equal;
239     } else if (isgreater(a, b)) {
240         return float_relation_greater;
241     } else {
242         return float_relation_unordered;
243     }
244 }
245 int float32_is_signaling_nan( float32 a1)
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
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
263 /*----------------------------------------------------------------------------
264 | Software IEC/IEEE double-precision conversion routines.
265 *----------------------------------------------------------------------------*/
266 int float64_to_int32( float64 a STATUS_PARAM)
267 {
268     return long_to_int32(lrint(a));
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
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
346 /*----------------------------------------------------------------------------
347 | Software IEC/IEEE double-precision operations.
348 *----------------------------------------------------------------------------*/
349 #if defined(__sun__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10
350 static inline float64 trunc(float64 x)
351 {
352     return x < 0 ? -floor(-x) : floor(x);
353 }
354 #endif
355 float64 float64_trunc_to_int( float64 a STATUS_PARAM )
356 {
357     return trunc(a);
358 }
359
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
383 float64 float64_rem( float64 a, float64 b STATUS_PARAM)
384 {
385     return remainder(a, b);
386 }
387
388 float64 float64_sqrt( float64 a STATUS_PARAM)
389 {
390     return sqrt(a);
391 }
392 int float64_compare( float64 a, float64 b STATUS_PARAM )
393 {
394     if (a < b) {
395         return float_relation_less;
396     } else if (a == b) {
397         return float_relation_equal;
398     } else if (a > b) {
399         return float_relation_greater;
400     } else {
401         return float_relation_unordered;
402     }
403 }
404 int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
405 {
406     if (isless(a, b)) {
407         return float_relation_less;
408     } else if (a == b) {
409         return float_relation_equal;
410     } else if (isgreater(a, b)) {
411         return float_relation_greater;
412     } else {
413         return float_relation_unordered;
414     }
415 }
416 int float64_is_signaling_nan( float64 a1)
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
428 int float64_is_nan( float64 a1 )
429 {
430     float64u u;
431     uint64_t a;
432     u.f = a1;
433     a = u.i;
434
435     return ( LIT64( 0xFFF0000000000000 ) < (bits64) ( a<<1 ) );
436
437 }
438
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 {
446     return long_to_int32(lrintl(a));
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 }
476 floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM)
477 {
478     return remainderl(a, b);
479 }
480 floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
481 {
482     return sqrtl(a);
483 }
484 int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
485 {
486     if (a < b) {
487         return float_relation_less;
488     } else if (a == b) {
489         return float_relation_equal;
490     } else if (a > b) {
491         return float_relation_greater;
492     } else {
493         return float_relation_unordered;
494     }
495 }
496 int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
497 {
498     if (isless(a, b)) {
499         return float_relation_less;
500     } else if (a == b) {
501         return float_relation_equal;
502     } else if (isgreater(a, b)) {
503         return float_relation_greater;
504     } else {
505         return float_relation_unordered;
506     }
507 }
508 int floatx80_is_signaling_nan( floatx80 a1)
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 )
522 {
523     floatx80u u;
524     u.f = a1;
525     return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
526 }
527
528 #endif