Statistics
| Branch: | Revision:

root / fpu / softfloat-native.c @ 8d7b0fbb

History | View | Annotate | Download (8.1 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
char 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
char 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
char 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
float64 float64_round_to_int( float64 a STATUS_PARAM )
225
{
226
#if defined(__arm__)
227
    switch(STATUS(float_rounding_mode)) {
228
    default:
229
    case float_round_nearest_even:
230
        asm("rndd %0, %1" : "=f" (a) : "f"(a));
231
        break;
232
    case float_round_down:
233
        asm("rnddm %0, %1" : "=f" (a) : "f"(a));
234
        break;
235
    case float_round_up:
236
        asm("rnddp %0, %1" : "=f" (a) : "f"(a));
237
        break;
238
    case float_round_to_zero:
239
        asm("rnddz %0, %1" : "=f" (a) : "f"(a));
240
        break;
241
    }
242
#else
243
    return rint(a);
244
#endif
245
}
246

    
247
float64 float64_rem( float64 a, float64 b STATUS_PARAM)
248
{
249
    return remainder(a, b);
250
}
251

    
252
float64 float64_sqrt( float64 a STATUS_PARAM)
253
{
254
    return sqrt(a);
255
}
256
char float64_compare( float64 a, float64 b STATUS_PARAM )
257
{
258
    if (a < b) {
259
        return -1;
260
    } else if (a == b) {
261
        return 0;
262
    } else if (a > b) {
263
        return 1;
264
    } else {
265
        return 2;
266
    }
267
}
268
char float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
269
{
270
    if (isless(a, b)) {
271
        return -1;
272
    } else if (a == b) {
273
        return 0;
274
    } else if (isgreater(a, b)) {
275
        return 1;
276
    } else {
277
        return 2;
278
    }
279
}
280
char float64_is_signaling_nan( float64 a1)
281
{
282
    float64u u;
283
    uint64_t a;
284
    u.f = a1;
285
    a = u.i;
286
    return
287
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
288
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
289

    
290
}
291

    
292
#ifdef FLOATX80
293

    
294
/*----------------------------------------------------------------------------
295
| Software IEC/IEEE extended double-precision conversion routines.
296
*----------------------------------------------------------------------------*/
297
int floatx80_to_int32( floatx80 a STATUS_PARAM)
298
{
299
    return long_to_int32(lrintl(a));
300
}
301
int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM)
302
{
303
    return (int)a;
304
}
305
int64_t floatx80_to_int64( floatx80 a STATUS_PARAM)
306
{
307
    return llrintl(a);
308
}
309
int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM)
310
{
311
    return (int64_t)a;
312
}
313
float32 floatx80_to_float32( floatx80 a STATUS_PARAM)
314
{
315
    return a;
316
}
317
float64 floatx80_to_float64( floatx80 a STATUS_PARAM)
318
{
319
    return a;
320
}
321

    
322
/*----------------------------------------------------------------------------
323
| Software IEC/IEEE extended double-precision operations.
324
*----------------------------------------------------------------------------*/
325
floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
326
{
327
    return rintl(a);
328
}
329
floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM)
330
{
331
    return remainderl(a, b);
332
}
333
floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
334
{
335
    return sqrtl(a);
336
}
337
char floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
338
{
339
    if (a < b) {
340
        return -1;
341
    } else if (a == b) {
342
        return 0;
343
    } else if (a > b) {
344
        return 1;
345
    } else {
346
        return 2;
347
    }
348
}
349
char floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
350
{
351
    if (isless(a, b)) {
352
        return -1;
353
    } else if (a == b) {
354
        return 0;
355
    } else if (isgreater(a, b)) {
356
        return 1;
357
    } else {
358
        return 2;
359
    }
360
}
361
char floatx80_is_signaling_nan( floatx80 a1)
362
{
363
    floatx80u u;
364
    u.f = a1;
365
    return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
366
}
367

    
368
#endif