Statistics
| Branch: | Revision:

root / fpu / softfloat-native.c @ 63a654bb

History | View | Annotate | Download (8.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
#endif
34

    
35
#if defined(__powerpc__)
36

    
37
/* correct (but slow) PowerPC rint() (glibc version is incorrect) */
38
double qemu_rint(double x)
39
{
40
    double y = 4503599627370496.0;
41
    if (fabs(x) >= y)
42
        return x;
43
    if (x < 0) 
44
        y = -y;
45
    y = (x + y) - y;
46
    if (y == 0.0)
47
        y = copysign(y, x);
48
    return y;
49
}
50

    
51
#define rint qemu_rint
52
#endif
53

    
54
/*----------------------------------------------------------------------------
55
| Software IEC/IEEE integer-to-floating-point conversion routines.
56
*----------------------------------------------------------------------------*/
57
float32 int32_to_float32(int v STATUS_PARAM)
58
{
59
    return (float32)v;
60
}
61

    
62
float64 int32_to_float64(int v STATUS_PARAM)
63
{
64
    return (float64)v;
65
}
66

    
67
#ifdef FLOATX80
68
floatx80 int32_to_floatx80(int v STATUS_PARAM)
69
{
70
    return (floatx80)v;
71
}
72
#endif
73
float32 int64_to_float32( int64_t v STATUS_PARAM)
74
{
75
    return (float32)v;
76
}
77
float64 int64_to_float64( int64_t v STATUS_PARAM)
78
{
79
    return (float64)v;
80
}
81
#ifdef FLOATX80
82
floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
83
{
84
    return (floatx80)v;
85
}
86
#endif
87

    
88
/* XXX: this code implements the x86 behaviour, not the IEEE one.  */
89
#if HOST_LONG_BITS == 32
90
static inline int long_to_int32(long a)
91
{
92
    return a;
93
}
94
#else
95
static inline int long_to_int32(long a)
96
{
97
    if (a != (int32_t)a) 
98
        a = 0x80000000;
99
    return a;
100
}
101
#endif
102

    
103
/*----------------------------------------------------------------------------
104
| Software IEC/IEEE single-precision conversion routines.
105
*----------------------------------------------------------------------------*/
106
int float32_to_int32( float32 a STATUS_PARAM)
107
{
108
    return long_to_int32(lrintf(a));
109
}
110
int float32_to_int32_round_to_zero( float32 a STATUS_PARAM)
111
{
112
    return (int)a;
113
}
114
int64_t float32_to_int64( float32 a STATUS_PARAM)
115
{
116
    return llrintf(a);
117
}
118

    
119
int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM)
120
{
121
    return (int64_t)a;
122
}
123

    
124
float64 float32_to_float64( float32 a STATUS_PARAM)
125
{
126
    return a;
127
}
128
#ifdef FLOATX80
129
floatx80 float32_to_floatx80( float32 a STATUS_PARAM)
130
{
131
    return a;
132
}
133
#endif
134

    
135
/*----------------------------------------------------------------------------
136
| Software IEC/IEEE single-precision operations.
137
*----------------------------------------------------------------------------*/
138
float32 float32_round_to_int( float32 a STATUS_PARAM)
139
{
140
    return rintf(a);
141
}
142

    
143
float32 float32_rem( float32 a, float32 b STATUS_PARAM)
144
{
145
    return remainderf(a, b);
146
}
147

    
148
float32 float32_sqrt( float32 a STATUS_PARAM)
149
{
150
    return sqrtf(a);
151
}
152
int float32_compare( float32 a, float32 b STATUS_PARAM )
153
{
154
    if (a < b) {
155
        return -1;
156
    } else if (a == b) {
157
        return 0;
158
    } else if (a > b) {
159
        return 1;
160
    } else {
161
        return 2;
162
    }
163
}
164
int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
165
{
166
    if (isless(a, b)) {
167
        return -1;
168
    } else if (a == b) {
169
        return 0;
170
    } else if (isgreater(a, b)) {
171
        return 1;
172
    } else {
173
        return 2;
174
    }
175
}
176
int float32_is_signaling_nan( float32 a1)
177
{
178
    float32u u;
179
    uint32_t a;
180
    u.f = a1;
181
    a = u.i;
182
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
183
}
184

    
185
/*----------------------------------------------------------------------------
186
| Software IEC/IEEE double-precision conversion routines.
187
*----------------------------------------------------------------------------*/
188
int float64_to_int32( float64 a STATUS_PARAM)
189
{
190
    return long_to_int32(lrint(a));
191
}
192
int float64_to_int32_round_to_zero( float64 a STATUS_PARAM)
193
{
194
    return (int)a;
195
}
196
int64_t float64_to_int64( float64 a STATUS_PARAM)
197
{
198
    return llrint(a);
199
}
200
int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM)
201
{
202
    return (int64_t)a;
203
}
204
float32 float64_to_float32( float64 a STATUS_PARAM)
205
{
206
    return a;
207
}
208
#ifdef FLOATX80
209
floatx80 float64_to_floatx80( float64 a STATUS_PARAM)
210
{
211
    return a;
212
}
213
#endif
214
#ifdef FLOAT128
215
float128 float64_to_float128( float64 a STATUS_PARAM)
216
{
217
    return a;
218
}
219
#endif
220

    
221
/*----------------------------------------------------------------------------
222
| Software IEC/IEEE double-precision operations.
223
*----------------------------------------------------------------------------*/
224
#if ( defined(__sun__) && ( HOST_SOLARIS < 10 ))
225
static inline float64 trunc(float64 x)
226
{
227
    return x < 0 ? -floor(-x) : floor(x);
228
}
229
#endif
230
float64 float64_trunc_to_int( float64 a STATUS_PARAM )
231
{
232
    return trunc(a);
233
}
234

    
235
float64 float64_round_to_int( float64 a STATUS_PARAM )
236
{
237
#if defined(__arm__)
238
    switch(STATUS(float_rounding_mode)) {
239
    default:
240
    case float_round_nearest_even:
241
        asm("rndd %0, %1" : "=f" (a) : "f"(a));
242
        break;
243
    case float_round_down:
244
        asm("rnddm %0, %1" : "=f" (a) : "f"(a));
245
        break;
246
    case float_round_up:
247
        asm("rnddp %0, %1" : "=f" (a) : "f"(a));
248
        break;
249
    case float_round_to_zero:
250
        asm("rnddz %0, %1" : "=f" (a) : "f"(a));
251
        break;
252
    }
253
#else
254
    return rint(a);
255
#endif
256
}
257

    
258
float64 float64_rem( float64 a, float64 b STATUS_PARAM)
259
{
260
    return remainder(a, b);
261
}
262

    
263
float64 float64_sqrt( float64 a STATUS_PARAM)
264
{
265
    return sqrt(a);
266
}
267
int float64_compare( float64 a, float64 b STATUS_PARAM )
268
{
269
    if (a < b) {
270
        return -1;
271
    } else if (a == b) {
272
        return 0;
273
    } else if (a > b) {
274
        return 1;
275
    } else {
276
        return 2;
277
    }
278
}
279
int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
280
{
281
    if (isless(a, b)) {
282
        return -1;
283
    } else if (a == b) {
284
        return 0;
285
    } else if (isgreater(a, b)) {
286
        return 1;
287
    } else {
288
        return 2;
289
    }
290
}
291
int float64_is_signaling_nan( float64 a1)
292
{
293
    float64u u;
294
    uint64_t a;
295
    u.f = a1;
296
    a = u.i;
297
    return
298
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
299
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
300

    
301
}
302

    
303
int float64_is_nan( float64 a1 )
304
{
305
    float64u u;
306
    uint64_t a;
307
    u.f = a1;
308
    a = u.i;
309

    
310
    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
311

    
312
}
313

    
314
#ifdef FLOATX80
315

    
316
/*----------------------------------------------------------------------------
317
| Software IEC/IEEE extended double-precision conversion routines.
318
*----------------------------------------------------------------------------*/
319
int floatx80_to_int32( floatx80 a STATUS_PARAM)
320
{
321
    return long_to_int32(lrintl(a));
322
}
323
int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM)
324
{
325
    return (int)a;
326
}
327
int64_t floatx80_to_int64( floatx80 a STATUS_PARAM)
328
{
329
    return llrintl(a);
330
}
331
int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM)
332
{
333
    return (int64_t)a;
334
}
335
float32 floatx80_to_float32( floatx80 a STATUS_PARAM)
336
{
337
    return a;
338
}
339
float64 floatx80_to_float64( floatx80 a STATUS_PARAM)
340
{
341
    return a;
342
}
343

    
344
/*----------------------------------------------------------------------------
345
| Software IEC/IEEE extended double-precision operations.
346
*----------------------------------------------------------------------------*/
347
floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
348
{
349
    return rintl(a);
350
}
351
floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM)
352
{
353
    return remainderl(a, b);
354
}
355
floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
356
{
357
    return sqrtl(a);
358
}
359
int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
360
{
361
    if (a < b) {
362
        return -1;
363
    } else if (a == b) {
364
        return 0;
365
    } else if (a > b) {
366
        return 1;
367
    } else {
368
        return 2;
369
    }
370
}
371
int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
372
{
373
    if (isless(a, b)) {
374
        return -1;
375
    } else if (a == b) {
376
        return 0;
377
    } else if (isgreater(a, b)) {
378
        return 1;
379
    } else {
380
        return 2;
381
    }
382
}
383
int floatx80_is_signaling_nan( floatx80 a1)
384
{
385
    floatx80u u;
386
    u.f = a1;
387
    return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
388
}
389

    
390
#endif