|
|
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>
1.1.1.8 ! root 5: #if defined(CONFIG_SOLARIS)
1.1.1.7 root 6: #include <fenv.h>
7: #endif
1.1 root 8:
9: void set_float_rounding_mode(int val STATUS_PARAM)
10: {
11: STATUS(float_rounding_mode) = val;
1.1.1.8 ! root 12: #if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) || \
! 13: (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
1.1 root 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:
1.1.1.8 ! root 29: #if defined(CONFIG_BSD) || \
! 30: (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
1.1.1.3 root 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))
1.1.1.8 ! root 38: #if !defined(__sparc__) && \
! 39: (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
1.1.1.5 root 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
1.1 root 58: #endif
59:
1.1.1.6 root 60: #if defined(_ARCH_PPC)
1.1 root 61:
62: /* correct (but slow) PowerPC rint() (glibc version is incorrect) */
1.1.1.6 root 63: static double qemu_rint(double x)
1.1 root 64: {
65: double y = 4503599627370496.0;
66: if (fabs(x) >= y)
67: return x;
1.1.1.5 root 68: if (x < 0)
1.1 root 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:
1.1.1.5 root 87: float32 uint32_to_float32(unsigned int v STATUS_PARAM)
88: {
89: return (float32)v;
90: }
91:
1.1 root 92: float64 int32_to_float64(int v STATUS_PARAM)
93: {
94: return (float64)v;
95: }
96:
1.1.1.5 root 97: float64 uint32_to_float64(unsigned int v STATUS_PARAM)
98: {
99: return (float64)v;
100: }
101:
1.1 root 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: }
1.1.1.5 root 112: float32 uint64_to_float32( uint64_t v STATUS_PARAM)
113: {
114: return (float32)v;
115: }
1.1 root 116: float64 int64_to_float64( int64_t v STATUS_PARAM)
117: {
118: return (float64)v;
119: }
1.1.1.5 root 120: float64 uint64_to_float64( uint64_t v STATUS_PARAM)
121: {
122: return (float64)v;
123: }
1.1 root 124: #ifdef FLOATX80
125: floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
126: {
127: return (floatx80)v;
128: }
129: #endif
130:
1.1.1.2 root 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: {
1.1.1.5 root 140: if (a != (int32_t)a)
1.1.1.2 root 141: a = 0x80000000;
142: return a;
143: }
144: #endif
145:
1.1 root 146: /*----------------------------------------------------------------------------
147: | Software IEC/IEEE single-precision conversion routines.
148: *----------------------------------------------------------------------------*/
149: int float32_to_int32( float32 a STATUS_PARAM)
150: {
1.1.1.2 root 151: return long_to_int32(lrintf(a));
1.1 root 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:
1.1.1.5 root 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:
1.1 root 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: }
1.1.1.4 root 226: int float32_compare( float32 a, float32 b STATUS_PARAM )
1.1 root 227: {
228: if (a < b) {
1.1.1.6 root 229: return float_relation_less;
1.1 root 230: } else if (a == b) {
1.1.1.6 root 231: return float_relation_equal;
1.1 root 232: } else if (a > b) {
1.1.1.6 root 233: return float_relation_greater;
1.1 root 234: } else {
1.1.1.6 root 235: return float_relation_unordered;
1.1 root 236: }
237: }
1.1.1.4 root 238: int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
1.1 root 239: {
240: if (isless(a, b)) {
1.1.1.6 root 241: return float_relation_less;
1.1 root 242: } else if (a == b) {
1.1.1.6 root 243: return float_relation_equal;
1.1 root 244: } else if (isgreater(a, b)) {
1.1.1.6 root 245: return float_relation_greater;
1.1 root 246: } else {
1.1.1.6 root 247: return float_relation_unordered;
1.1 root 248: }
249: }
1.1.1.4 root 250: int float32_is_signaling_nan( float32 a1)
1.1 root 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:
1.1.1.6 root 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:
1.1 root 268: /*----------------------------------------------------------------------------
269: | Software IEC/IEEE double-precision conversion routines.
270: *----------------------------------------------------------------------------*/
271: int float64_to_int32( float64 a STATUS_PARAM)
272: {
1.1.1.2 root 273: return long_to_int32(lrint(a));
1.1 root 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:
1.1.1.5 root 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:
1.1 root 351: /*----------------------------------------------------------------------------
352: | Software IEC/IEEE double-precision operations.
353: *----------------------------------------------------------------------------*/
1.1.1.8 ! root 354: #if defined(__sun__) && \
! 355: (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
1.1.1.5 root 356: static inline float64 trunc(float64 x)
357: {
358: return x < 0 ? -floor(-x) : floor(x);
359: }
360: #endif
1.1.1.4 root 361: float64 float64_trunc_to_int( float64 a STATUS_PARAM )
362: {
363: return trunc(a);
364: }
365:
1.1 root 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: }
1.1.1.4 root 398: int float64_compare( float64 a, float64 b STATUS_PARAM )
1.1 root 399: {
400: if (a < b) {
1.1.1.6 root 401: return float_relation_less;
1.1 root 402: } else if (a == b) {
1.1.1.6 root 403: return float_relation_equal;
1.1 root 404: } else if (a > b) {
1.1.1.6 root 405: return float_relation_greater;
1.1 root 406: } else {
1.1.1.6 root 407: return float_relation_unordered;
1.1 root 408: }
409: }
1.1.1.4 root 410: int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
1.1 root 411: {
412: if (isless(a, b)) {
1.1.1.6 root 413: return float_relation_less;
1.1 root 414: } else if (a == b) {
1.1.1.6 root 415: return float_relation_equal;
1.1 root 416: } else if (isgreater(a, b)) {
1.1.1.6 root 417: return float_relation_greater;
1.1 root 418: } else {
1.1.1.6 root 419: return float_relation_unordered;
1.1 root 420: }
421: }
1.1.1.4 root 422: int float64_is_signaling_nan( float64 a1)
1.1 root 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:
1.1.1.4 root 434: int float64_is_nan( float64 a1 )
435: {
436: float64u u;
437: uint64_t a;
438: u.f = a1;
439: a = u.i;
440:
1.1.1.6 root 441: return ( LIT64( 0xFFF0000000000000 ) < (bits64) ( a<<1 ) );
1.1.1.4 root 442:
443: }
444:
1.1 root 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: {
1.1.1.2 root 452: return long_to_int32(lrintl(a));
1.1 root 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: }
1.1.1.4 root 490: int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
1.1 root 491: {
492: if (a < b) {
1.1.1.6 root 493: return float_relation_less;
1.1 root 494: } else if (a == b) {
1.1.1.6 root 495: return float_relation_equal;
1.1 root 496: } else if (a > b) {
1.1.1.6 root 497: return float_relation_greater;
1.1 root 498: } else {
1.1.1.6 root 499: return float_relation_unordered;
1.1 root 500: }
501: }
1.1.1.4 root 502: int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
1.1 root 503: {
504: if (isless(a, b)) {
1.1.1.6 root 505: return float_relation_less;
1.1 root 506: } else if (a == b) {
1.1.1.6 root 507: return float_relation_equal;
1.1 root 508: } else if (isgreater(a, b)) {
1.1.1.6 root 509: return float_relation_greater;
1.1 root 510: } else {
1.1.1.6 root 511: return float_relation_unordered;
1.1 root 512: }
513: }
1.1.1.4 root 514: int floatx80_is_signaling_nan( floatx80 a1)
1.1 root 515: {
516: floatx80u u;
1.1.1.6 root 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;
1.1 root 530: u.f = a1;
531: return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
532: }
533:
534: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.