VirtualBox

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

Last change on this file since 37613 was 36175, checked in by vboxsync, 14 years ago

rem: Synced up to v0.11.1 (35bfc7324e2e6946c4113ada5db30553a1a7c40b) from git://git.savannah.nongnu.org/qemu.git.

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