Statistics
| Branch: | Revision:

root / fpu / softfloat-specialize.h @ b1d8e52e

History | View | Annotate | Download (19.7 kB)

1

    
2
/*============================================================================
3

4
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
5
Arithmetic Package, Release 2b.
6

7
Written by John R. Hauser.  This work was made possible in part by the
8
International Computer Science Institute, located at Suite 600, 1947 Center
9
Street, Berkeley, California 94704.  Funding was partially provided by the
10
National Science Foundation under grant MIP-9311980.  The original version
11
of this code was written as part of a project to build a fixed-point vector
12
processor in collaboration with the University of California at Berkeley,
13
overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
14
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
15
arithmetic/SoftFloat.html'.
16

17
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
18
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
19
RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
20
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
21
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
22
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
23
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
24
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
25

26
Derivative works are acceptable, even for commercial purposes, so long as
27
(1) the source code for the derivative work includes prominent notice that
28
the work is derivative, and (2) the source code includes prominent notice with
29
these four paragraphs for those parts of this code that are retained.
30

31
=============================================================================*/
32

    
33
#if defined(TARGET_MIPS) || defined(TARGET_HPPA)
34
#define SNAN_BIT_IS_ONE                1
35
#else
36
#define SNAN_BIT_IS_ONE                0
37
#endif
38

    
39
/*----------------------------------------------------------------------------
40
| Raises the exceptions specified by `flags'.  Floating-point traps can be
41
| defined here if desired.  It is currently not possible for such a trap
42
| to substitute a result value.  If traps are not implemented, this routine
43
| should be simply `float_exception_flags |= flags;'.
44
*----------------------------------------------------------------------------*/
45

    
46
void float_raise( int8 flags STATUS_PARAM )
47
{
48
    STATUS(float_exception_flags) |= flags;
49
}
50

    
51
/*----------------------------------------------------------------------------
52
| Internal canonical NaN format.
53
*----------------------------------------------------------------------------*/
54
typedef struct {
55
    flag sign;
56
    bits64 high, low;
57
} commonNaNT;
58

    
59
/*----------------------------------------------------------------------------
60
| The pattern for a default generated single-precision NaN.
61
*----------------------------------------------------------------------------*/
62
#if defined(TARGET_SPARC)
63
#define float32_default_nan make_float32(0x7FFFFFFF)
64
#elif defined(TARGET_POWERPC)
65
#define float32_default_nan make_float32(0x7FC00000)
66
#elif defined(TARGET_HPPA)
67
#define float32_default_nan make_float32(0x7FA00000)
68
#elif SNAN_BIT_IS_ONE
69
#define float32_default_nan make_float32(0x7FBFFFFF)
70
#else
71
#define float32_default_nan make_float32(0xFFC00000)
72
#endif
73

    
74
/*----------------------------------------------------------------------------
75
| Returns 1 if the single-precision floating-point value `a' is a quiet
76
| NaN; otherwise returns 0.
77
*----------------------------------------------------------------------------*/
78

    
79
int float32_is_nan( float32 a_ )
80
{
81
    uint32_t a = float32_val(a_);
82
#if SNAN_BIT_IS_ONE
83
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
84
#else
85
    return ( 0xFF800000 <= (bits32) ( a<<1 ) );
86
#endif
87
}
88

    
89
/*----------------------------------------------------------------------------
90
| Returns 1 if the single-precision floating-point value `a' is a signaling
91
| NaN; otherwise returns 0.
92
*----------------------------------------------------------------------------*/
93

    
94
int float32_is_signaling_nan( float32 a_ )
95
{
96
    uint32_t a = float32_val(a_);
97
#if SNAN_BIT_IS_ONE
98
    return ( 0xFF800000 <= (bits32) ( a<<1 ) );
99
#else
100
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
101
#endif
102
}
103

    
104
/*----------------------------------------------------------------------------
105
| Returns the result of converting the single-precision floating-point NaN
106
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
107
| exception is raised.
108
*----------------------------------------------------------------------------*/
109

    
110
static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
111
{
112
    commonNaNT z;
113

    
114
    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
115
    z.sign = float32_val(a)>>31;
116
    z.low = 0;
117
    z.high = ( (bits64) float32_val(a) )<<41;
118
    return z;
119
}
120

    
121
/*----------------------------------------------------------------------------
122
| Returns the result of converting the canonical NaN `a' to the single-
123
| precision floating-point format.
124
*----------------------------------------------------------------------------*/
125

    
126
static float32 commonNaNToFloat32( commonNaNT a )
127
{
128
    bits32 mantissa = a.high>>41;
129
    if ( mantissa )
130
        return make_float32(
131
            ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
132
    else
133
        return float32_default_nan;
134
}
135

    
136
/*----------------------------------------------------------------------------
137
| Takes two single-precision floating-point values `a' and `b', one of which
138
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
139
| signaling NaN, the invalid exception is raised.
140
*----------------------------------------------------------------------------*/
141

    
142
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
143
{
144
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
145
    bits32 av, bv, res;
146

    
147
    aIsNaN = float32_is_nan( a );
148
    aIsSignalingNaN = float32_is_signaling_nan( a );
149
    bIsNaN = float32_is_nan( b );
150
    bIsSignalingNaN = float32_is_signaling_nan( b );
151
    av = float32_val(a);
152
    bv = float32_val(b);
153
#if SNAN_BIT_IS_ONE
154
    av &= ~0x00400000;
155
    bv &= ~0x00400000;
156
#else
157
    av |= 0x00400000;
158
    bv |= 0x00400000;
159
#endif
160
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
161
    if ( aIsSignalingNaN ) {
162
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
163
        res = bIsNaN ? bv : av;
164
    }
165
    else if ( aIsNaN ) {
166
        if ( bIsSignalingNaN | ! bIsNaN )
167
            res = av;
168
        else {
169
 returnLargerSignificand:
170
            if ( (bits32) ( av<<1 ) < (bits32) ( bv<<1 ) )
171
                res = bv;
172
            else if ( (bits32) ( bv<<1 ) < (bits32) ( av<<1 ) )
173
                res = av;
174
            else
175
                res = ( av < bv ) ? av : bv;
176
        }
177
    }
178
    else {
179
        res = bv;
180
    }
181
    return make_float32(res);
182
}
183

    
184
/*----------------------------------------------------------------------------
185
| The pattern for a default generated double-precision NaN.
186
*----------------------------------------------------------------------------*/
187
#if defined(TARGET_SPARC)
188
#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
189
#elif defined(TARGET_POWERPC)
190
#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
191
#elif defined(TARGET_HPPA)
192
#define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 ))
193
#elif SNAN_BIT_IS_ONE
194
#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
195
#else
196
#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
197
#endif
198

    
199
/*----------------------------------------------------------------------------
200
| Returns 1 if the double-precision floating-point value `a' is a quiet
201
| NaN; otherwise returns 0.
202
*----------------------------------------------------------------------------*/
203

    
204
int float64_is_nan( float64 a_ )
205
{
206
    bits64 a = float64_val(a_);
207
#if SNAN_BIT_IS_ONE
208
    return
209
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
210
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
211
#else
212
    return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
213
#endif
214
}
215

    
216
/*----------------------------------------------------------------------------
217
| Returns 1 if the double-precision floating-point value `a' is a signaling
218
| NaN; otherwise returns 0.
219
*----------------------------------------------------------------------------*/
220

    
221
int float64_is_signaling_nan( float64 a_ )
222
{
223
    bits64 a = float64_val(a_);
224
#if SNAN_BIT_IS_ONE
225
    return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
226
#else
227
    return
228
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
229
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
230
#endif
231
}
232

    
233
/*----------------------------------------------------------------------------
234
| Returns the result of converting the double-precision floating-point NaN
235
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
236
| exception is raised.
237
*----------------------------------------------------------------------------*/
238

    
239
static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
240
{
241
    commonNaNT z;
242

    
243
    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
244
    z.sign = float64_val(a)>>63;
245
    z.low = 0;
246
    z.high = float64_val(a)<<12;
247
    return z;
248
}
249

    
250
/*----------------------------------------------------------------------------
251
| Returns the result of converting the canonical NaN `a' to the double-
252
| precision floating-point format.
253
*----------------------------------------------------------------------------*/
254

    
255
static float64 commonNaNToFloat64( commonNaNT a )
256
{
257
    bits64 mantissa = a.high>>12;
258

    
259
    if ( mantissa )
260
        return make_float64(
261
              ( ( (bits64) a.sign )<<63 )
262
            | LIT64( 0x7FF0000000000000 )
263
            | ( a.high>>12 ));
264
    else
265
        return float64_default_nan;
266
}
267

    
268
/*----------------------------------------------------------------------------
269
| Takes two double-precision floating-point values `a' and `b', one of which
270
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
271
| signaling NaN, the invalid exception is raised.
272
*----------------------------------------------------------------------------*/
273

    
274
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
275
{
276
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
277
    bits64 av, bv, res;
278

    
279
    aIsNaN = float64_is_nan( a );
280
    aIsSignalingNaN = float64_is_signaling_nan( a );
281
    bIsNaN = float64_is_nan( b );
282
    bIsSignalingNaN = float64_is_signaling_nan( b );
283
    av = float64_val(a);
284
    bv = float64_val(b);
285
#if SNAN_BIT_IS_ONE
286
    av &= ~LIT64( 0x0008000000000000 );
287
    bv &= ~LIT64( 0x0008000000000000 );
288
#else
289
    av |= LIT64( 0x0008000000000000 );
290
    bv |= LIT64( 0x0008000000000000 );
291
#endif
292
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
293
    if ( aIsSignalingNaN ) {
294
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
295
        res = bIsNaN ? bv : av;
296
    }
297
    else if ( aIsNaN ) {
298
        if ( bIsSignalingNaN | ! bIsNaN )
299
            res = av;
300
        else {
301
 returnLargerSignificand:
302
            if ( (bits64) ( av<<1 ) < (bits64) ( bv<<1 ) )
303
                res = bv;
304
            else if ( (bits64) ( bv<<1 ) < (bits64) ( av<<1 ) )
305
                res = av;
306
            else
307
                res = ( av < bv ) ? av : bv;
308
        }
309
    }
310
    else {
311
        res = bv;
312
    }
313
    return make_float64(res);
314
}
315

    
316
#ifdef FLOATX80
317

    
318
/*----------------------------------------------------------------------------
319
| The pattern for a default generated extended double-precision NaN.  The
320
| `high' and `low' values hold the most- and least-significant bits,
321
| respectively.
322
*----------------------------------------------------------------------------*/
323
#if SNAN_BIT_IS_ONE
324
#define floatx80_default_nan_high 0x7FFF
325
#define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
326
#else
327
#define floatx80_default_nan_high 0xFFFF
328
#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
329
#endif
330

    
331
/*----------------------------------------------------------------------------
332
| Returns 1 if the extended double-precision floating-point value `a' is a
333
| quiet NaN; otherwise returns 0.
334
*----------------------------------------------------------------------------*/
335

    
336
int floatx80_is_nan( floatx80 a )
337
{
338
#if SNAN_BIT_IS_ONE
339
    bits64 aLow;
340

    
341
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
342
    return
343
           ( ( a.high & 0x7FFF ) == 0x7FFF )
344
        && (bits64) ( aLow<<1 )
345
        && ( a.low == aLow );
346
#else
347
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
348
#endif
349
}
350

    
351
/*----------------------------------------------------------------------------
352
| Returns 1 if the extended double-precision floating-point value `a' is a
353
| signaling NaN; otherwise returns 0.
354
*----------------------------------------------------------------------------*/
355

    
356
int floatx80_is_signaling_nan( floatx80 a )
357
{
358
#if SNAN_BIT_IS_ONE
359
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
360
#else
361
    bits64 aLow;
362

    
363
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
364
    return
365
           ( ( a.high & 0x7FFF ) == 0x7FFF )
366
        && (bits64) ( aLow<<1 )
367
        && ( a.low == aLow );
368
#endif
369
}
370

    
371
/*----------------------------------------------------------------------------
372
| Returns the result of converting the extended double-precision floating-
373
| point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
374
| invalid exception is raised.
375
*----------------------------------------------------------------------------*/
376

    
377
static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
378
{
379
    commonNaNT z;
380

    
381
    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
382
    z.sign = a.high>>15;
383
    z.low = 0;
384
    z.high = a.low;
385
    return z;
386
}
387

    
388
/*----------------------------------------------------------------------------
389
| Returns the result of converting the canonical NaN `a' to the extended
390
| double-precision floating-point format.
391
*----------------------------------------------------------------------------*/
392

    
393
static floatx80 commonNaNToFloatx80( commonNaNT a )
394
{
395
    floatx80 z;
396

    
397
    if (a.high)
398
        z.low = a.high;
399
    else
400
        z.low = floatx80_default_nan_low;
401
    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
402
    return z;
403
}
404

    
405
/*----------------------------------------------------------------------------
406
| Takes two extended double-precision floating-point values `a' and `b', one
407
| of which is a NaN, and returns the appropriate NaN result.  If either `a' or
408
| `b' is a signaling NaN, the invalid exception is raised.
409
*----------------------------------------------------------------------------*/
410

    
411
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
412
{
413
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
414

    
415
    aIsNaN = floatx80_is_nan( a );
416
    aIsSignalingNaN = floatx80_is_signaling_nan( a );
417
    bIsNaN = floatx80_is_nan( b );
418
    bIsSignalingNaN = floatx80_is_signaling_nan( b );
419
#if SNAN_BIT_IS_ONE
420
    a.low &= ~LIT64( 0xC000000000000000 );
421
    b.low &= ~LIT64( 0xC000000000000000 );
422
#else
423
    a.low |= LIT64( 0xC000000000000000 );
424
    b.low |= LIT64( 0xC000000000000000 );
425
#endif
426
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
427
    if ( aIsSignalingNaN ) {
428
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
429
        return bIsNaN ? b : a;
430
    }
431
    else if ( aIsNaN ) {
432
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
433
 returnLargerSignificand:
434
        if ( a.low < b.low ) return b;
435
        if ( b.low < a.low ) return a;
436
        return ( a.high < b.high ) ? a : b;
437
    }
438
    else {
439
        return b;
440
    }
441
}
442

    
443
#endif
444

    
445
#ifdef FLOAT128
446

    
447
/*----------------------------------------------------------------------------
448
| The pattern for a default generated quadruple-precision NaN.  The `high' and
449
| `low' values hold the most- and least-significant bits, respectively.
450
*----------------------------------------------------------------------------*/
451
#if SNAN_BIT_IS_ONE
452
#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
453
#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
454
#else
455
#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
456
#define float128_default_nan_low  LIT64( 0x0000000000000000 )
457
#endif
458

    
459
/*----------------------------------------------------------------------------
460
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
461
| NaN; otherwise returns 0.
462
*----------------------------------------------------------------------------*/
463

    
464
int float128_is_nan( float128 a )
465
{
466
#if SNAN_BIT_IS_ONE
467
    return
468
           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
469
        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
470
#else
471
    return
472
           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
473
        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
474
#endif
475
}
476

    
477
/*----------------------------------------------------------------------------
478
| Returns 1 if the quadruple-precision floating-point value `a' is a
479
| signaling NaN; otherwise returns 0.
480
*----------------------------------------------------------------------------*/
481

    
482
int float128_is_signaling_nan( float128 a )
483
{
484
#if SNAN_BIT_IS_ONE
485
    return
486
           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
487
        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
488
#else
489
    return
490
           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
491
        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
492
#endif
493
}
494

    
495
/*----------------------------------------------------------------------------
496
| Returns the result of converting the quadruple-precision floating-point NaN
497
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
498
| exception is raised.
499
*----------------------------------------------------------------------------*/
500

    
501
static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
502
{
503
    commonNaNT z;
504

    
505
    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
506
    z.sign = a.high>>63;
507
    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
508
    return z;
509
}
510

    
511
/*----------------------------------------------------------------------------
512
| Returns the result of converting the canonical NaN `a' to the quadruple-
513
| precision floating-point format.
514
*----------------------------------------------------------------------------*/
515

    
516
static float128 commonNaNToFloat128( commonNaNT a )
517
{
518
    float128 z;
519

    
520
    shift128Right( a.high, a.low, 16, &z.high, &z.low );
521
    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
522
    return z;
523
}
524

    
525
/*----------------------------------------------------------------------------
526
| Takes two quadruple-precision floating-point values `a' and `b', one of
527
| which is a NaN, and returns the appropriate NaN result.  If either `a' or
528
| `b' is a signaling NaN, the invalid exception is raised.
529
*----------------------------------------------------------------------------*/
530

    
531
static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
532
{
533
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
534

    
535
    aIsNaN = float128_is_nan( a );
536
    aIsSignalingNaN = float128_is_signaling_nan( a );
537
    bIsNaN = float128_is_nan( b );
538
    bIsSignalingNaN = float128_is_signaling_nan( b );
539
#if SNAN_BIT_IS_ONE
540
    a.high &= ~LIT64( 0x0000800000000000 );
541
    b.high &= ~LIT64( 0x0000800000000000 );
542
#else
543
    a.high |= LIT64( 0x0000800000000000 );
544
    b.high |= LIT64( 0x0000800000000000 );
545
#endif
546
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
547
    if ( aIsSignalingNaN ) {
548
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
549
        return bIsNaN ? b : a;
550
    }
551
    else if ( aIsNaN ) {
552
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
553
 returnLargerSignificand:
554
        if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
555
        if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
556
        return ( a.high < b.high ) ? a : b;
557
    }
558
    else {
559
        return b;
560
    }
561
}
562

    
563
#endif