VirtualBox

source: vbox/trunk/src/recompiler/fpu/softfloat-native.c@ 30976

Last change on this file since 30976 was 21292, checked in by vboxsync, 15 years ago

svn:eol-style native

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette