|
|
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;
9: #if defined(_BSD) && !defined(__APPLE__)
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:
25: #if defined(_BSD)
1.1.1.2 ! root 26: #define lrint(d) ((long)rint(d))
! 27: #define llrint(d) ((long long)rint(d))
1.1 root 28: #endif
29:
30: #if defined(__powerpc__)
31:
32: /* correct (but slow) PowerPC rint() (glibc version is incorrect) */
33: double qemu_rint(double x)
34: {
35: double y = 4503599627370496.0;
36: if (fabs(x) >= y)
37: return x;
38: if (x < 0)
39: y = -y;
40: y = (x + y) - y;
41: if (y == 0.0)
42: y = copysign(y, x);
43: return y;
44: }
45:
46: #define rint qemu_rint
47: #endif
48:
49: /*----------------------------------------------------------------------------
50: | Software IEC/IEEE integer-to-floating-point conversion routines.
51: *----------------------------------------------------------------------------*/
52: float32 int32_to_float32(int v STATUS_PARAM)
53: {
54: return (float32)v;
55: }
56:
57: float64 int32_to_float64(int v STATUS_PARAM)
58: {
59: return (float64)v;
60: }
61:
62: #ifdef FLOATX80
63: floatx80 int32_to_floatx80(int v STATUS_PARAM)
64: {
65: return (floatx80)v;
66: }
67: #endif
68: float32 int64_to_float32( int64_t v STATUS_PARAM)
69: {
70: return (float32)v;
71: }
72: float64 int64_to_float64( int64_t v STATUS_PARAM)
73: {
74: return (float64)v;
75: }
76: #ifdef FLOATX80
77: floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
78: {
79: return (floatx80)v;
80: }
81: #endif
82:
1.1.1.2 ! root 83: /* XXX: this code implements the x86 behaviour, not the IEEE one. */
! 84: #if HOST_LONG_BITS == 32
! 85: static inline int long_to_int32(long a)
! 86: {
! 87: return a;
! 88: }
! 89: #else
! 90: static inline int long_to_int32(long a)
! 91: {
! 92: if (a != (int32_t)a)
! 93: a = 0x80000000;
! 94: return a;
! 95: }
! 96: #endif
! 97:
1.1 root 98: /*----------------------------------------------------------------------------
99: | Software IEC/IEEE single-precision conversion routines.
100: *----------------------------------------------------------------------------*/
101: int float32_to_int32( float32 a STATUS_PARAM)
102: {
1.1.1.2 ! root 103: return long_to_int32(lrintf(a));
1.1 root 104: }
105: int float32_to_int32_round_to_zero( float32 a STATUS_PARAM)
106: {
107: return (int)a;
108: }
109: int64_t float32_to_int64( float32 a STATUS_PARAM)
110: {
111: return llrintf(a);
112: }
113:
114: int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM)
115: {
116: return (int64_t)a;
117: }
118:
119: float64 float32_to_float64( float32 a STATUS_PARAM)
120: {
121: return a;
122: }
123: #ifdef FLOATX80
124: floatx80 float32_to_floatx80( float32 a STATUS_PARAM)
125: {
126: return a;
127: }
128: #endif
129:
130: /*----------------------------------------------------------------------------
131: | Software IEC/IEEE single-precision operations.
132: *----------------------------------------------------------------------------*/
133: float32 float32_round_to_int( float32 a STATUS_PARAM)
134: {
135: return rintf(a);
136: }
137:
138: float32 float32_rem( float32 a, float32 b STATUS_PARAM)
139: {
140: return remainderf(a, b);
141: }
142:
143: float32 float32_sqrt( float32 a STATUS_PARAM)
144: {
145: return sqrtf(a);
146: }
147: char float32_compare( float32 a, float32 b STATUS_PARAM )
148: {
149: if (a < b) {
150: return -1;
151: } else if (a == b) {
152: return 0;
153: } else if (a > b) {
154: return 1;
155: } else {
156: return 2;
157: }
158: }
159: char float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
160: {
161: if (isless(a, b)) {
162: return -1;
163: } else if (a == b) {
164: return 0;
165: } else if (isgreater(a, b)) {
166: return 1;
167: } else {
168: return 2;
169: }
170: }
171: char float32_is_signaling_nan( float32 a1)
172: {
173: float32u u;
174: uint32_t a;
175: u.f = a1;
176: a = u.i;
177: return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
178: }
179:
180: /*----------------------------------------------------------------------------
181: | Software IEC/IEEE double-precision conversion routines.
182: *----------------------------------------------------------------------------*/
183: int float64_to_int32( float64 a STATUS_PARAM)
184: {
1.1.1.2 ! root 185: return long_to_int32(lrint(a));
1.1 root 186: }
187: int float64_to_int32_round_to_zero( float64 a STATUS_PARAM)
188: {
189: return (int)a;
190: }
191: int64_t float64_to_int64( float64 a STATUS_PARAM)
192: {
193: return llrint(a);
194: }
195: int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM)
196: {
197: return (int64_t)a;
198: }
199: float32 float64_to_float32( float64 a STATUS_PARAM)
200: {
201: return a;
202: }
203: #ifdef FLOATX80
204: floatx80 float64_to_floatx80( float64 a STATUS_PARAM)
205: {
206: return a;
207: }
208: #endif
209: #ifdef FLOAT128
210: float128 float64_to_float128( float64 a STATUS_PARAM)
211: {
212: return a;
213: }
214: #endif
215:
216: /*----------------------------------------------------------------------------
217: | Software IEC/IEEE double-precision operations.
218: *----------------------------------------------------------------------------*/
219: float64 float64_round_to_int( float64 a STATUS_PARAM )
220: {
221: #if defined(__arm__)
222: switch(STATUS(float_rounding_mode)) {
223: default:
224: case float_round_nearest_even:
225: asm("rndd %0, %1" : "=f" (a) : "f"(a));
226: break;
227: case float_round_down:
228: asm("rnddm %0, %1" : "=f" (a) : "f"(a));
229: break;
230: case float_round_up:
231: asm("rnddp %0, %1" : "=f" (a) : "f"(a));
232: break;
233: case float_round_to_zero:
234: asm("rnddz %0, %1" : "=f" (a) : "f"(a));
235: break;
236: }
237: #else
238: return rint(a);
239: #endif
240: }
241:
242: float64 float64_rem( float64 a, float64 b STATUS_PARAM)
243: {
244: return remainder(a, b);
245: }
246:
247: float64 float64_sqrt( float64 a STATUS_PARAM)
248: {
249: return sqrt(a);
250: }
251: char float64_compare( float64 a, float64 b STATUS_PARAM )
252: {
253: if (a < b) {
254: return -1;
255: } else if (a == b) {
256: return 0;
257: } else if (a > b) {
258: return 1;
259: } else {
260: return 2;
261: }
262: }
263: char float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
264: {
265: if (isless(a, b)) {
266: return -1;
267: } else if (a == b) {
268: return 0;
269: } else if (isgreater(a, b)) {
270: return 1;
271: } else {
272: return 2;
273: }
274: }
275: char float64_is_signaling_nan( float64 a1)
276: {
277: float64u u;
278: uint64_t a;
279: u.f = a1;
280: a = u.i;
281: return
282: ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
283: && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
284:
285: }
286:
287: #ifdef FLOATX80
288:
289: /*----------------------------------------------------------------------------
290: | Software IEC/IEEE extended double-precision conversion routines.
291: *----------------------------------------------------------------------------*/
292: int floatx80_to_int32( floatx80 a STATUS_PARAM)
293: {
1.1.1.2 ! root 294: return long_to_int32(lrintl(a));
1.1 root 295: }
296: int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM)
297: {
298: return (int)a;
299: }
300: int64_t floatx80_to_int64( floatx80 a STATUS_PARAM)
301: {
302: return llrintl(a);
303: }
304: int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM)
305: {
306: return (int64_t)a;
307: }
308: float32 floatx80_to_float32( floatx80 a STATUS_PARAM)
309: {
310: return a;
311: }
312: float64 floatx80_to_float64( floatx80 a STATUS_PARAM)
313: {
314: return a;
315: }
316:
317: /*----------------------------------------------------------------------------
318: | Software IEC/IEEE extended double-precision operations.
319: *----------------------------------------------------------------------------*/
320: floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
321: {
322: return rintl(a);
323: }
324: floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM)
325: {
326: return remainderl(a, b);
327: }
328: floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
329: {
330: return sqrtl(a);
331: }
332: char floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
333: {
334: if (a < b) {
335: return -1;
336: } else if (a == b) {
337: return 0;
338: } else if (a > b) {
339: return 1;
340: } else {
341: return 2;
342: }
343: }
344: char floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
345: {
346: if (isless(a, b)) {
347: return -1;
348: } else if (a == b) {
349: return 0;
350: } else if (isgreater(a, b)) {
351: return 1;
352: } else {
353: return 2;
354: }
355: }
356: char floatx80_is_signaling_nan( floatx80 a1)
357: {
358: floatx80u u;
359: u.f = a1;
360: return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
361: }
362:
363: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.