Statistics
| Branch: | Revision:

root / fpu / softfloat-native.c @ 1b2b0af5

History | View | Annotate | Download (7.8 kB)

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