|
|
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:
54: #if defined(__powerpc__)
55:
56: /* correct (but slow) PowerPC rint() (glibc version is incorrect) */
57: double qemu_rint(double x)
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) {
223: return -1;
224: } else if (a == b) {
225: return 0;
226: } else if (a > b) {
227: return 1;
228: } else {
229: return 2;
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)) {
235: return -1;
236: } else if (a == b) {
237: return 0;
238: } else if (isgreater(a, b)) {
239: return 1;
240: } else {
241: return 2;
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:
253: /*----------------------------------------------------------------------------
254: | Software IEC/IEEE double-precision conversion routines.
255: *----------------------------------------------------------------------------*/
256: int float64_to_int32( float64 a STATUS_PARAM)
257: {
1.1.1.2 root 258: return long_to_int32(lrint(a));
1.1 root 259: }
260: int float64_to_int32_round_to_zero( float64 a STATUS_PARAM)
261: {
262: return (int)a;
263: }
264: int64_t float64_to_int64( float64 a STATUS_PARAM)
265: {
266: return llrint(a);
267: }
268: int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM)
269: {
270: return (int64_t)a;
271: }
272: float32 float64_to_float32( float64 a STATUS_PARAM)
273: {
274: return a;
275: }
276: #ifdef FLOATX80
277: floatx80 float64_to_floatx80( float64 a STATUS_PARAM)
278: {
279: return a;
280: }
281: #endif
282: #ifdef FLOAT128
283: float128 float64_to_float128( float64 a STATUS_PARAM)
284: {
285: return a;
286: }
287: #endif
288:
1.1.1.5 ! root 289: unsigned int float64_to_uint32( float64 a STATUS_PARAM)
! 290: {
! 291: int64_t v;
! 292: unsigned int res;
! 293:
! 294: v = llrint(a);
! 295: if (v < 0) {
! 296: res = 0;
! 297: } else if (v > 0xffffffff) {
! 298: res = 0xffffffff;
! 299: } else {
! 300: res = v;
! 301: }
! 302: return res;
! 303: }
! 304: unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM)
! 305: {
! 306: int64_t v;
! 307: unsigned int res;
! 308:
! 309: v = (int64_t)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: uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
! 320: {
! 321: int64_t v;
! 322:
! 323: v = llrint(a + (float64)INT64_MIN);
! 324:
! 325: return v - INT64_MIN;
! 326: }
! 327: uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
! 328: {
! 329: int64_t v;
! 330:
! 331: v = (int64_t)(a + (float64)INT64_MIN);
! 332:
! 333: return v - INT64_MIN;
! 334: }
! 335:
1.1 root 336: /*----------------------------------------------------------------------------
337: | Software IEC/IEEE double-precision operations.
338: *----------------------------------------------------------------------------*/
1.1.1.5 ! root 339: #if defined(__sun__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10
! 340: static inline float64 trunc(float64 x)
! 341: {
! 342: return x < 0 ? -floor(-x) : floor(x);
! 343: }
! 344: #endif
1.1.1.4 root 345: float64 float64_trunc_to_int( float64 a STATUS_PARAM )
346: {
347: return trunc(a);
348: }
349:
1.1 root 350: float64 float64_round_to_int( float64 a STATUS_PARAM )
351: {
352: #if defined(__arm__)
353: switch(STATUS(float_rounding_mode)) {
354: default:
355: case float_round_nearest_even:
356: asm("rndd %0, %1" : "=f" (a) : "f"(a));
357: break;
358: case float_round_down:
359: asm("rnddm %0, %1" : "=f" (a) : "f"(a));
360: break;
361: case float_round_up:
362: asm("rnddp %0, %1" : "=f" (a) : "f"(a));
363: break;
364: case float_round_to_zero:
365: asm("rnddz %0, %1" : "=f" (a) : "f"(a));
366: break;
367: }
368: #else
369: return rint(a);
370: #endif
371: }
372:
373: float64 float64_rem( float64 a, float64 b STATUS_PARAM)
374: {
375: return remainder(a, b);
376: }
377:
378: float64 float64_sqrt( float64 a STATUS_PARAM)
379: {
380: return sqrt(a);
381: }
1.1.1.4 root 382: int float64_compare( float64 a, float64 b STATUS_PARAM )
1.1 root 383: {
384: if (a < b) {
385: return -1;
386: } else if (a == b) {
387: return 0;
388: } else if (a > b) {
389: return 1;
390: } else {
391: return 2;
392: }
393: }
1.1.1.4 root 394: int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
1.1 root 395: {
396: if (isless(a, b)) {
397: return -1;
398: } else if (a == b) {
399: return 0;
400: } else if (isgreater(a, b)) {
401: return 1;
402: } else {
403: return 2;
404: }
405: }
1.1.1.4 root 406: int float64_is_signaling_nan( float64 a1)
1.1 root 407: {
408: float64u u;
409: uint64_t a;
410: u.f = a1;
411: a = u.i;
412: return
413: ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
414: && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
415:
416: }
417:
1.1.1.4 root 418: int float64_is_nan( float64 a1 )
419: {
420: float64u u;
421: uint64_t a;
422: u.f = a1;
423: a = u.i;
424:
425: return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
426:
427: }
428:
1.1 root 429: #ifdef FLOATX80
430:
431: /*----------------------------------------------------------------------------
432: | Software IEC/IEEE extended double-precision conversion routines.
433: *----------------------------------------------------------------------------*/
434: int floatx80_to_int32( floatx80 a STATUS_PARAM)
435: {
1.1.1.2 root 436: return long_to_int32(lrintl(a));
1.1 root 437: }
438: int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM)
439: {
440: return (int)a;
441: }
442: int64_t floatx80_to_int64( floatx80 a STATUS_PARAM)
443: {
444: return llrintl(a);
445: }
446: int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM)
447: {
448: return (int64_t)a;
449: }
450: float32 floatx80_to_float32( floatx80 a STATUS_PARAM)
451: {
452: return a;
453: }
454: float64 floatx80_to_float64( floatx80 a STATUS_PARAM)
455: {
456: return a;
457: }
458:
459: /*----------------------------------------------------------------------------
460: | Software IEC/IEEE extended double-precision operations.
461: *----------------------------------------------------------------------------*/
462: floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
463: {
464: return rintl(a);
465: }
466: floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM)
467: {
468: return remainderl(a, b);
469: }
470: floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
471: {
472: return sqrtl(a);
473: }
1.1.1.4 root 474: int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
1.1 root 475: {
476: if (a < b) {
477: return -1;
478: } else if (a == b) {
479: return 0;
480: } else if (a > b) {
481: return 1;
482: } else {
483: return 2;
484: }
485: }
1.1.1.4 root 486: int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
1.1 root 487: {
488: if (isless(a, b)) {
489: return -1;
490: } else if (a == b) {
491: return 0;
492: } else if (isgreater(a, b)) {
493: return 1;
494: } else {
495: return 2;
496: }
497: }
1.1.1.4 root 498: int floatx80_is_signaling_nan( floatx80 a1)
1.1 root 499: {
500: floatx80u u;
501: u.f = a1;
502: return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
503: }
504:
505: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.