Statistics
| Branch: | Revision:

root / fpu / softfloat-native.c @ d7585251

History | View | Annotate | Download (11.4 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(HOST_BSD) && !defined(__APPLE__) ||         \
10
    (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
11
    fpsetround(val);
12
#elif defined(__arm__)
13
    /* nothing to do */
14
#else
15
    fesetround(val);
16
#endif
17
}
18

    
19
#ifdef FLOATX80
20
void set_floatx80_rounding_precision(int val STATUS_PARAM)
21
{
22
    STATUS(floatx80_rounding_precision) = val;
23
}
24
#endif
25

    
26
#if defined(HOST_BSD) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
27
#define lrint(d)                ((int32_t)rint(d))
28
#define llrint(d)                ((int64_t)rint(d))
29
#define lrintf(f)                ((int32_t)rint(f))
30
#define llrintf(f)                ((int64_t)rint(f))
31
#define sqrtf(f)                ((float)sqrt(f))
32
#define remainderf(fa, fb)        ((float)remainder(fa, fb))
33
#define rintf(f)                ((float)rint(f))
34
#if !defined(__sparc__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10
35
extern long double rintl(long double);
36
extern long double scalbnl(long double, int);
37

    
38
long long
39
llrintl(long double x) {
40
        return ((long long) rintl(x));
41
}
42

    
43
long
44
lrintl(long double x) {
45
        return ((long) rintl(x));
46
}
47

    
48
long double
49
ldexpl(long double x, int n) {
50
        return (scalbnl(x, n));
51
}
52
#endif
53
#endif
54

    
55
#if defined(_ARCH_PPC)
56

    
57
/* correct (but slow) PowerPC rint() (glibc version is incorrect) */
58
static double qemu_rint(double x)
59
{
60
    double y = 4503599627370496.0;
61
    if (fabs(x) >= y)
62
        return x;
63
    if (x < 0)
64
        y = -y;
65
    y = (x + y) - y;
66
    if (y == 0.0)
67
        y = copysign(y, x);
68
    return y;
69
}
70

    
71
#define rint qemu_rint
72
#endif
73

    
74
/*----------------------------------------------------------------------------
75
| Software IEC/IEEE integer-to-floating-point conversion routines.
76
*----------------------------------------------------------------------------*/
77
float32 int32_to_float32(int v STATUS_PARAM)
78
{
79
    return (float32)v;
80
}
81

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

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

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

    
97
#ifdef FLOATX80
98
floatx80 int32_to_floatx80(int v STATUS_PARAM)
99
{
100
    return (floatx80)v;
101
}
102
#endif
103
float32 int64_to_float32( int64_t v STATUS_PARAM)
104
{
105
    return (float32)v;
106
}
107
float32 uint64_to_float32( uint64_t v STATUS_PARAM)
108
{
109
    return (float32)v;
110
}
111
float64 int64_to_float64( int64_t v STATUS_PARAM)
112
{
113
    return (float64)v;
114
}
115
float64 uint64_to_float64( uint64_t v STATUS_PARAM)
116
{
117
    return (float64)v;
118
}
119
#ifdef FLOATX80
120
floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
121
{
122
    return (floatx80)v;
123
}
124
#endif
125

    
126
/* XXX: this code implements the x86 behaviour, not the IEEE one.  */
127
#if HOST_LONG_BITS == 32
128
static inline int long_to_int32(long a)
129
{
130
    return a;
131
}
132
#else
133
static inline int long_to_int32(long a)
134
{
135
    if (a != (int32_t)a)
136
        a = 0x80000000;
137
    return a;
138
}
139
#endif
140

    
141
/*----------------------------------------------------------------------------
142
| Software IEC/IEEE single-precision conversion routines.
143
*----------------------------------------------------------------------------*/
144
int float32_to_int32( float32 a STATUS_PARAM)
145
{
146
    return long_to_int32(lrintf(a));
147
}
148
int float32_to_int32_round_to_zero( float32 a STATUS_PARAM)
149
{
150
    return (int)a;
151
}
152
int64_t float32_to_int64( float32 a STATUS_PARAM)
153
{
154
    return llrintf(a);
155
}
156

    
157
int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM)
158
{
159
    return (int64_t)a;
160
}
161

    
162
float64 float32_to_float64( float32 a STATUS_PARAM)
163
{
164
    return a;
165
}
166
#ifdef FLOATX80
167
floatx80 float32_to_floatx80( float32 a STATUS_PARAM)
168
{
169
    return a;
170
}
171
#endif
172

    
173
unsigned int float32_to_uint32( float32 a STATUS_PARAM)
174
{
175
    int64_t v;
176
    unsigned int res;
177

    
178
    v = llrintf(a);
179
    if (v < 0) {
180
        res = 0;
181
    } else if (v > 0xffffffff) {
182
        res = 0xffffffff;
183
    } else {
184
        res = v;
185
    }
186
    return res;
187
}
188
unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM)
189
{
190
    int64_t v;
191
    unsigned int res;
192

    
193
    v = (int64_t)a;
194
    if (v < 0) {
195
        res = 0;
196
    } else if (v > 0xffffffff) {
197
        res = 0xffffffff;
198
    } else {
199
        res = v;
200
    }
201
    return res;
202
}
203

    
204
/*----------------------------------------------------------------------------
205
| Software IEC/IEEE single-precision operations.
206
*----------------------------------------------------------------------------*/
207
float32 float32_round_to_int( float32 a STATUS_PARAM)
208
{
209
    return rintf(a);
210
}
211

    
212
float32 float32_rem( float32 a, float32 b STATUS_PARAM)
213
{
214
    return remainderf(a, b);
215
}
216

    
217
float32 float32_sqrt( float32 a STATUS_PARAM)
218
{
219
    return sqrtf(a);
220
}
221
int float32_compare( float32 a, float32 b STATUS_PARAM )
222
{
223
    if (a < b) {
224
        return float_relation_less;
225
    } else if (a == b) {
226
        return float_relation_equal;
227
    } else if (a > b) {
228
        return float_relation_greater;
229
    } else {
230
        return float_relation_unordered;
231
    }
232
}
233
int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
234
{
235
    if (isless(a, b)) {
236
        return float_relation_less;
237
    } else if (a == b) {
238
        return float_relation_equal;
239
    } else if (isgreater(a, b)) {
240
        return float_relation_greater;
241
    } else {
242
        return float_relation_unordered;
243
    }
244
}
245
int float32_is_signaling_nan( float32 a1)
246
{
247
    float32u u;
248
    uint32_t a;
249
    u.f = a1;
250
    a = u.i;
251
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
252
}
253

    
254
int float32_is_nan( float32 a1 )
255
{
256
    float32u u;
257
    uint64_t a;
258
    u.f = a1;
259
    a = u.i;
260
    return ( 0xFF800000 < ( a<<1 ) );
261
}
262

    
263
/*----------------------------------------------------------------------------
264
| Software IEC/IEEE double-precision conversion routines.
265
*----------------------------------------------------------------------------*/
266
int float64_to_int32( float64 a STATUS_PARAM)
267
{
268
    return long_to_int32(lrint(a));
269
}
270
int float64_to_int32_round_to_zero( float64 a STATUS_PARAM)
271
{
272
    return (int)a;
273
}
274
int64_t float64_to_int64( float64 a STATUS_PARAM)
275
{
276
    return llrint(a);
277
}
278
int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM)
279
{
280
    return (int64_t)a;
281
}
282
float32 float64_to_float32( float64 a STATUS_PARAM)
283
{
284
    return a;
285
}
286
#ifdef FLOATX80
287
floatx80 float64_to_floatx80( float64 a STATUS_PARAM)
288
{
289
    return a;
290
}
291
#endif
292
#ifdef FLOAT128
293
float128 float64_to_float128( float64 a STATUS_PARAM)
294
{
295
    return a;
296
}
297
#endif
298

    
299
unsigned int float64_to_uint32( float64 a STATUS_PARAM)
300
{
301
    int64_t v;
302
    unsigned int res;
303

    
304
    v = llrint(a);
305
    if (v < 0) {
306
        res = 0;
307
    } else if (v > 0xffffffff) {
308
        res = 0xffffffff;
309
    } else {
310
        res = v;
311
    }
312
    return res;
313
}
314
unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM)
315
{
316
    int64_t v;
317
    unsigned int res;
318

    
319
    v = (int64_t)a;
320
    if (v < 0) {
321
        res = 0;
322
    } else if (v > 0xffffffff) {
323
        res = 0xffffffff;
324
    } else {
325
        res = v;
326
    }
327
    return res;
328
}
329
uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
330
{
331
    int64_t v;
332

    
333
    v = llrint(a + (float64)INT64_MIN);
334

    
335
    return v - INT64_MIN;
336
}
337
uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
338
{
339
    int64_t v;
340

    
341
    v = (int64_t)(a + (float64)INT64_MIN);
342

    
343
    return v - INT64_MIN;
344
}
345

    
346
/*----------------------------------------------------------------------------
347
| Software IEC/IEEE double-precision operations.
348
*----------------------------------------------------------------------------*/
349
#if defined(__sun__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10
350
static inline float64 trunc(float64 x)
351
{
352
    return x < 0 ? -floor(-x) : floor(x);
353
}
354
#endif
355
float64 float64_trunc_to_int( float64 a STATUS_PARAM )
356
{
357
    return trunc(a);
358
}
359

    
360
float64 float64_round_to_int( float64 a STATUS_PARAM )
361
{
362
#if defined(__arm__)
363
    switch(STATUS(float_rounding_mode)) {
364
    default:
365
    case float_round_nearest_even:
366
        asm("rndd %0, %1" : "=f" (a) : "f"(a));
367
        break;
368
    case float_round_down:
369
        asm("rnddm %0, %1" : "=f" (a) : "f"(a));
370
        break;
371
    case float_round_up:
372
        asm("rnddp %0, %1" : "=f" (a) : "f"(a));
373
        break;
374
    case float_round_to_zero:
375
        asm("rnddz %0, %1" : "=f" (a) : "f"(a));
376
        break;
377
    }
378
#else
379
    return rint(a);
380
#endif
381
}
382

    
383
float64 float64_rem( float64 a, float64 b STATUS_PARAM)
384
{
385
    return remainder(a, b);
386
}
387

    
388
float64 float64_sqrt( float64 a STATUS_PARAM)
389
{
390
    return sqrt(a);
391
}
392
int float64_compare( float64 a, float64 b STATUS_PARAM )
393
{
394
    if (a < b) {
395
        return float_relation_less;
396
    } else if (a == b) {
397
        return float_relation_equal;
398
    } else if (a > b) {
399
        return float_relation_greater;
400
    } else {
401
        return float_relation_unordered;
402
    }
403
}
404
int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
405
{
406
    if (isless(a, b)) {
407
        return float_relation_less;
408
    } else if (a == b) {
409
        return float_relation_equal;
410
    } else if (isgreater(a, b)) {
411
        return float_relation_greater;
412
    } else {
413
        return float_relation_unordered;
414
    }
415
}
416
int float64_is_signaling_nan( float64 a1)
417
{
418
    float64u u;
419
    uint64_t a;
420
    u.f = a1;
421
    a = u.i;
422
    return
423
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
424
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
425

    
426
}
427

    
428
int float64_is_nan( float64 a1 )
429
{
430
    float64u u;
431
    uint64_t a;
432
    u.f = a1;
433
    a = u.i;
434

    
435
    return ( LIT64( 0xFFF0000000000000 ) < (bits64) ( a<<1 ) );
436

    
437
}
438

    
439
#ifdef FLOATX80
440

    
441
/*----------------------------------------------------------------------------
442
| Software IEC/IEEE extended double-precision conversion routines.
443
*----------------------------------------------------------------------------*/
444
int floatx80_to_int32( floatx80 a STATUS_PARAM)
445
{
446
    return long_to_int32(lrintl(a));
447
}
448
int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM)
449
{
450
    return (int)a;
451
}
452
int64_t floatx80_to_int64( floatx80 a STATUS_PARAM)
453
{
454
    return llrintl(a);
455
}
456
int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM)
457
{
458
    return (int64_t)a;
459
}
460
float32 floatx80_to_float32( floatx80 a STATUS_PARAM)
461
{
462
    return a;
463
}
464
float64 floatx80_to_float64( floatx80 a STATUS_PARAM)
465
{
466
    return a;
467
}
468

    
469
/*----------------------------------------------------------------------------
470
| Software IEC/IEEE extended double-precision operations.
471
*----------------------------------------------------------------------------*/
472
floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
473
{
474
    return rintl(a);
475
}
476
floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM)
477
{
478
    return remainderl(a, b);
479
}
480
floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
481
{
482
    return sqrtl(a);
483
}
484
int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
485
{
486
    if (a < b) {
487
        return float_relation_less;
488
    } else if (a == b) {
489
        return float_relation_equal;
490
    } else if (a > b) {
491
        return float_relation_greater;
492
    } else {
493
        return float_relation_unordered;
494
    }
495
}
496
int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
497
{
498
    if (isless(a, b)) {
499
        return float_relation_less;
500
    } else if (a == b) {
501
        return float_relation_equal;
502
    } else if (isgreater(a, b)) {
503
        return float_relation_greater;
504
    } else {
505
        return float_relation_unordered;
506
    }
507
}
508
int floatx80_is_signaling_nan( floatx80 a1)
509
{
510
    floatx80u u;
511
    uint64_t aLow;
512
    u.f = a1;
513

    
514
    aLow = u.i.low & ~ LIT64( 0x4000000000000000 );
515
    return
516
           ( ( u.i.high & 0x7FFF ) == 0x7FFF )
517
        && (bits64) ( aLow<<1 )
518
        && ( u.i.low == aLow );
519
}
520

    
521
int floatx80_is_nan( floatx80 a1 )
522
{
523
    floatx80u u;
524
    u.f = a1;
525
    return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
526
}
527

    
528
#endif