Statistics
| Branch: | Revision:

root / fpu / softfloat-native.c @ 5fafdf24

History | View | Annotate | Download (10.5 kB)

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__) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
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) || (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))
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
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;
62
    if (x < 0)
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

    
81
float32 uint32_to_float32(unsigned int v STATUS_PARAM)
82
{
83
    return (float32)v;
84
}
85

    
86
float64 int32_to_float64(int v STATUS_PARAM)
87
{
88
    return (float64)v;
89
}
90

    
91
float64 uint32_to_float64(unsigned int v STATUS_PARAM)
92
{
93
    return (float64)v;
94
}
95

    
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
}
106
float32 uint64_to_float32( uint64_t v STATUS_PARAM)
107
{
108
    return (float32)v;
109
}
110
float64 int64_to_float64( int64_t v STATUS_PARAM)
111
{
112
    return (float64)v;
113
}
114
float64 uint64_to_float64( uint64_t v STATUS_PARAM)
115
{
116
    return (float64)v;
117
}
118
#ifdef FLOATX80
119
floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
120
{
121
    return (floatx80)v;
122
}
123
#endif
124

    
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
{
134
    if (a != (int32_t)a)
135
        a = 0x80000000;
136
    return a;
137
}
138
#endif
139

    
140
/*----------------------------------------------------------------------------
141
| Software IEC/IEEE single-precision conversion routines.
142
*----------------------------------------------------------------------------*/
143
int float32_to_int32( float32 a STATUS_PARAM)
144
{
145
    return long_to_int32(lrintf(a));
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

    
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

    
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
}
220
int float32_compare( float32 a, float32 b STATUS_PARAM )
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
}
232
int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
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
}
244
int float32_is_signaling_nan( float32 a1)
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
{
258
    return long_to_int32(lrint(a));
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

    
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

    
336
/*----------------------------------------------------------------------------
337
| Software IEC/IEEE double-precision operations.
338
*----------------------------------------------------------------------------*/
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
345
float64 float64_trunc_to_int( float64 a STATUS_PARAM )
346
{
347
    return trunc(a);
348
}
349

    
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
}
382
int float64_compare( float64 a, float64 b STATUS_PARAM )
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
}
394
int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
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
}
406
int float64_is_signaling_nan( float64 a1)
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

    
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

    
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
{
436
    return long_to_int32(lrintl(a));
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
}
474
int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
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
}
486
int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
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
}
498
int floatx80_is_signaling_nan( floatx80 a1)
499
{
500
    floatx80u u;
501
    u.f = a1;
502
    return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
503
}
504

    
505
#endif