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