Statistics
| Branch: | Revision:

root / fpu / softfloat-native.c @ dfe5fff3

History | View | Annotate | Download (11.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
#if defined(CONFIG_SOLARIS)
6
#include <fenv.h>
7
#endif
8

    
9
void set_float_rounding_mode(int val STATUS_PARAM)
10
{
11
    STATUS(float_rounding_mode) = val;
12
#if defined(HOST_BSD) && !defined(__APPLE__) ||         \
13
    (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
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

    
29
#if defined(HOST_BSD) || \
30
    (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
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))
38
#if !defined(__sparc__) && \
39
    (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
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
58
#endif
59

    
60
#if defined(_ARCH_PPC)
61

    
62
/* correct (but slow) PowerPC rint() (glibc version is incorrect) */
63
static double qemu_rint(double x)
64
{
65
    double y = 4503599627370496.0;
66
    if (fabs(x) >= y)
67
        return x;
68
    if (x < 0)
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

    
87
float32 uint32_to_float32(unsigned int v STATUS_PARAM)
88
{
89
    return (float32)v;
90
}
91

    
92
float64 int32_to_float64(int v STATUS_PARAM)
93
{
94
    return (float64)v;
95
}
96

    
97
float64 uint32_to_float64(unsigned int v STATUS_PARAM)
98
{
99
    return (float64)v;
100
}
101

    
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
}
112
float32 uint64_to_float32( uint64_t v STATUS_PARAM)
113
{
114
    return (float32)v;
115
}
116
float64 int64_to_float64( int64_t v STATUS_PARAM)
117
{
118
    return (float64)v;
119
}
120
float64 uint64_to_float64( uint64_t v STATUS_PARAM)
121
{
122
    return (float64)v;
123
}
124
#ifdef FLOATX80
125
floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
126
{
127
    return (floatx80)v;
128
}
129
#endif
130

    
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
{
140
    if (a != (int32_t)a)
141
        a = 0x80000000;
142
    return a;
143
}
144
#endif
145

    
146
/*----------------------------------------------------------------------------
147
| Software IEC/IEEE single-precision conversion routines.
148
*----------------------------------------------------------------------------*/
149
int float32_to_int32( float32 a STATUS_PARAM)
150
{
151
    return long_to_int32(lrintf(a));
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

    
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

    
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
}
226
int float32_compare( float32 a, float32 b STATUS_PARAM )
227
{
228
    if (a < b) {
229
        return float_relation_less;
230
    } else if (a == b) {
231
        return float_relation_equal;
232
    } else if (a > b) {
233
        return float_relation_greater;
234
    } else {
235
        return float_relation_unordered;
236
    }
237
}
238
int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
239
{
240
    if (isless(a, b)) {
241
        return float_relation_less;
242
    } else if (a == b) {
243
        return float_relation_equal;
244
    } else if (isgreater(a, b)) {
245
        return float_relation_greater;
246
    } else {
247
        return float_relation_unordered;
248
    }
249
}
250
int float32_is_signaling_nan( float32 a1)
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

    
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

    
268
/*----------------------------------------------------------------------------
269
| Software IEC/IEEE double-precision conversion routines.
270
*----------------------------------------------------------------------------*/
271
int float64_to_int32( float64 a STATUS_PARAM)
272
{
273
    return long_to_int32(lrint(a));
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

    
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

    
351
/*----------------------------------------------------------------------------
352
| Software IEC/IEEE double-precision operations.
353
*----------------------------------------------------------------------------*/
354
#if defined(__sun__) && \
355
    (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
356
static inline float64 trunc(float64 x)
357
{
358
    return x < 0 ? -floor(-x) : floor(x);
359
}
360
#endif
361
float64 float64_trunc_to_int( float64 a STATUS_PARAM )
362
{
363
    return trunc(a);
364
}
365

    
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
}
398
int float64_compare( float64 a, float64 b STATUS_PARAM )
399
{
400
    if (a < b) {
401
        return float_relation_less;
402
    } else if (a == b) {
403
        return float_relation_equal;
404
    } else if (a > b) {
405
        return float_relation_greater;
406
    } else {
407
        return float_relation_unordered;
408
    }
409
}
410
int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
411
{
412
    if (isless(a, b)) {
413
        return float_relation_less;
414
    } else if (a == b) {
415
        return float_relation_equal;
416
    } else if (isgreater(a, b)) {
417
        return float_relation_greater;
418
    } else {
419
        return float_relation_unordered;
420
    }
421
}
422
int float64_is_signaling_nan( float64 a1)
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

    
434
int float64_is_nan( float64 a1 )
435
{
436
    float64u u;
437
    uint64_t a;
438
    u.f = a1;
439
    a = u.i;
440

    
441
    return ( LIT64( 0xFFF0000000000000 ) < (bits64) ( a<<1 ) );
442

    
443
}
444

    
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
{
452
    return long_to_int32(lrintl(a));
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
}
490
int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
491
{
492
    if (a < b) {
493
        return float_relation_less;
494
    } else if (a == b) {
495
        return float_relation_equal;
496
    } else if (a > b) {
497
        return float_relation_greater;
498
    } else {
499
        return float_relation_unordered;
500
    }
501
}
502
int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
503
{
504
    if (isless(a, b)) {
505
        return float_relation_less;
506
    } else if (a == b) {
507
        return float_relation_equal;
508
    } else if (isgreater(a, b)) {
509
        return float_relation_greater;
510
    } else {
511
        return float_relation_unordered;
512
    }
513
}
514
int floatx80_is_signaling_nan( floatx80 a1)
515
{
516
    floatx80u u;
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;
530
    u.f = a1;
531
    return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
532
}
533

    
534
#endif