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