~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to fpu/softfloat-native.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2008-08-25 04:38:35 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825043835-8e3tftavy8bujdch
Tags: 0.9.1-6
[ Aurelien Jarno ]
* debian/control: 
  - Update list of supported targets (Closes: bug#488339).
* debian/qemu-make-debian-root:
  - Use mktemp instead of $$ to create temporary directories (Closes: 
    bug#496394).
* debian/links:
  - Add missing links to manpages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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