Statistics
| Branch: | Revision:

root / fpu / softfloat-specialize.h @ 3d575329

History | View | Annotate | Download (20 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
| Underflow tininess-detection mode, statically initialized to default value.
41
| (The declaration in `softfloat.h' must match the `int8' type here.)
42
*----------------------------------------------------------------------------*/
43
int8 float_detect_tininess = float_tininess_after_rounding;
44

    
45
/*----------------------------------------------------------------------------
46
| Raises the exceptions specified by `flags'.  Floating-point traps can be
47
| defined here if desired.  It is currently not possible for such a trap
48
| to substitute a result value.  If traps are not implemented, this routine
49
| should be simply `float_exception_flags |= flags;'.
50
*----------------------------------------------------------------------------*/
51

    
52
void float_raise( int8 flags STATUS_PARAM )
53
{
54
    STATUS(float_exception_flags) |= flags;
55
}
56

    
57
/*----------------------------------------------------------------------------
58
| Internal canonical NaN format.
59
*----------------------------------------------------------------------------*/
60
typedef struct {
61
    flag sign;
62
    bits64 high, low;
63
} commonNaNT;
64

    
65
/*----------------------------------------------------------------------------
66
| The pattern for a default generated single-precision NaN.
67
*----------------------------------------------------------------------------*/
68
#if defined(TARGET_SPARC)
69
#define float32_default_nan make_float32(0x7FFFFFFF)
70
#elif defined(TARGET_POWERPC)
71
#define float32_default_nan make_float32(0x7FC00000)
72
#elif defined(TARGET_HPPA)
73
#define float32_default_nan make_float32(0x7FA00000)
74
#elif SNAN_BIT_IS_ONE
75
#define float32_default_nan make_float32(0x7FBFFFFF)
76
#else
77
#define float32_default_nan make_float32(0xFFC00000)
78
#endif
79

    
80
/*----------------------------------------------------------------------------
81
| Returns 1 if the single-precision floating-point value `a' is a quiet
82
| NaN; otherwise returns 0.
83
*----------------------------------------------------------------------------*/
84

    
85
int float32_is_nan( float32 a_ )
86
{
87
    uint32_t a = float32_val(a_);
88
#if SNAN_BIT_IS_ONE
89
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
90
#else
91
    return ( 0xFF800000 <= (bits32) ( a<<1 ) );
92
#endif
93
}
94

    
95
/*----------------------------------------------------------------------------
96
| Returns 1 if the single-precision floating-point value `a' is a signaling
97
| NaN; otherwise returns 0.
98
*----------------------------------------------------------------------------*/
99

    
100
int float32_is_signaling_nan( float32 a_ )
101
{
102
    uint32_t a = float32_val(a_);
103
#if SNAN_BIT_IS_ONE
104
    return ( 0xFF800000 <= (bits32) ( a<<1 ) );
105
#else
106
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
107
#endif
108
}
109

    
110
/*----------------------------------------------------------------------------
111
| Returns the result of converting the single-precision floating-point NaN
112
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
113
| exception is raised.
114
*----------------------------------------------------------------------------*/
115

    
116
static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
117
{
118
    commonNaNT z;
119

    
120
    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
121
    z.sign = float32_val(a)>>31;
122
    z.low = 0;
123
    z.high = ( (bits64) float32_val(a) )<<41;
124
    return z;
125
}
126

    
127
/*----------------------------------------------------------------------------
128
| Returns the result of converting the canonical NaN `a' to the single-
129
| precision floating-point format.
130
*----------------------------------------------------------------------------*/
131

    
132
static float32 commonNaNToFloat32( commonNaNT a )
133
{
134
    bits32 mantissa = a.high>>41;
135
    if ( mantissa )
136
        return make_float32(
137
            ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
138
    else
139
        return float32_default_nan;
140
}
141

    
142
/*----------------------------------------------------------------------------
143
| Takes two single-precision floating-point values `a' and `b', one of which
144
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
145
| signaling NaN, the invalid exception is raised.
146
*----------------------------------------------------------------------------*/
147

    
148
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
149
{
150
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
151
    bits32 av, bv, res;
152

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

    
190
/*----------------------------------------------------------------------------
191
| The pattern for a default generated double-precision NaN.
192
*----------------------------------------------------------------------------*/
193
#if defined(TARGET_SPARC)
194
#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
195
#elif defined(TARGET_POWERPC)
196
#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
197
#elif defined(TARGET_HPPA)
198
#define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 ))
199
#elif SNAN_BIT_IS_ONE
200
#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
201
#else
202
#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
203
#endif
204

    
205
/*----------------------------------------------------------------------------
206
| Returns 1 if the double-precision floating-point value `a' is a quiet
207
| NaN; otherwise returns 0.
208
*----------------------------------------------------------------------------*/
209

    
210
int float64_is_nan( float64 a_ )
211
{
212
    bits64 a = float64_val(a_);
213
#if SNAN_BIT_IS_ONE
214
    return
215
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
216
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
217
#else
218
    return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
219
#endif
220
}
221

    
222
/*----------------------------------------------------------------------------
223
| Returns 1 if the double-precision floating-point value `a' is a signaling
224
| NaN; otherwise returns 0.
225
*----------------------------------------------------------------------------*/
226

    
227
int float64_is_signaling_nan( float64 a_ )
228
{
229
    bits64 a = float64_val(a_);
230
#if SNAN_BIT_IS_ONE
231
    return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
232
#else
233
    return
234
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
235
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
236
#endif
237
}
238

    
239
/*----------------------------------------------------------------------------
240
| Returns the result of converting the double-precision floating-point NaN
241
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
242
| exception is raised.
243
*----------------------------------------------------------------------------*/
244

    
245
static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
246
{
247
    commonNaNT z;
248

    
249
    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
250
    z.sign = float64_val(a)>>63;
251
    z.low = 0;
252
    z.high = float64_val(a)<<12;
253
    return z;
254
}
255

    
256
/*----------------------------------------------------------------------------
257
| Returns the result of converting the canonical NaN `a' to the double-
258
| precision floating-point format.
259
*----------------------------------------------------------------------------*/
260

    
261
static float64 commonNaNToFloat64( commonNaNT a )
262
{
263
    bits64 mantissa = a.high>>12;
264

    
265
    if ( mantissa )
266
        return make_float64(
267
              ( ( (bits64) a.sign )<<63 )
268
            | LIT64( 0x7FF0000000000000 )
269
            | ( a.high>>12 ));
270
    else
271
        return float64_default_nan;
272
}
273

    
274
/*----------------------------------------------------------------------------
275
| Takes two double-precision floating-point values `a' and `b', one of which
276
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
277
| signaling NaN, the invalid exception is raised.
278
*----------------------------------------------------------------------------*/
279

    
280
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
281
{
282
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
283
    bits64 av, bv, res;
284

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

    
322
#ifdef FLOATX80
323

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

    
337
/*----------------------------------------------------------------------------
338
| Returns 1 if the extended double-precision floating-point value `a' is a
339
| quiet NaN; otherwise returns 0.
340
*----------------------------------------------------------------------------*/
341

    
342
int floatx80_is_nan( floatx80 a )
343
{
344
#if SNAN_BIT_IS_ONE
345
    bits64 aLow;
346

    
347
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
348
    return
349
           ( ( a.high & 0x7FFF ) == 0x7FFF )
350
        && (bits64) ( aLow<<1 )
351
        && ( a.low == aLow );
352
#else
353
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
354
#endif
355
}
356

    
357
/*----------------------------------------------------------------------------
358
| Returns 1 if the extended double-precision floating-point value `a' is a
359
| signaling NaN; otherwise returns 0.
360
*----------------------------------------------------------------------------*/
361

    
362
int floatx80_is_signaling_nan( floatx80 a )
363
{
364
#if SNAN_BIT_IS_ONE
365
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
366
#else
367
    bits64 aLow;
368

    
369
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
370
    return
371
           ( ( a.high & 0x7FFF ) == 0x7FFF )
372
        && (bits64) ( aLow<<1 )
373
        && ( a.low == aLow );
374
#endif
375
}
376

    
377
/*----------------------------------------------------------------------------
378
| Returns the result of converting the extended double-precision floating-
379
| point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
380
| invalid exception is raised.
381
*----------------------------------------------------------------------------*/
382

    
383
static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
384
{
385
    commonNaNT z;
386

    
387
    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
388
    z.sign = a.high>>15;
389
    z.low = 0;
390
    z.high = a.low;
391
    return z;
392
}
393

    
394
/*----------------------------------------------------------------------------
395
| Returns the result of converting the canonical NaN `a' to the extended
396
| double-precision floating-point format.
397
*----------------------------------------------------------------------------*/
398

    
399
static floatx80 commonNaNToFloatx80( commonNaNT a )
400
{
401
    floatx80 z;
402

    
403
    if (a.high)
404
        z.low = a.high;
405
    else
406
        z.low = floatx80_default_nan_low;
407
    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
408
    return z;
409
}
410

    
411
/*----------------------------------------------------------------------------
412
| Takes two extended double-precision floating-point values `a' and `b', one
413
| of which is a NaN, and returns the appropriate NaN result.  If either `a' or
414
| `b' is a signaling NaN, the invalid exception is raised.
415
*----------------------------------------------------------------------------*/
416

    
417
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
418
{
419
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
420

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

    
449
#endif
450

    
451
#ifdef FLOAT128
452

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

    
465
/*----------------------------------------------------------------------------
466
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
467
| NaN; otherwise returns 0.
468
*----------------------------------------------------------------------------*/
469

    
470
int float128_is_nan( float128 a )
471
{
472
#if SNAN_BIT_IS_ONE
473
    return
474
           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
475
        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
476
#else
477
    return
478
           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
479
        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
480
#endif
481
}
482

    
483
/*----------------------------------------------------------------------------
484
| Returns 1 if the quadruple-precision floating-point value `a' is a
485
| signaling NaN; otherwise returns 0.
486
*----------------------------------------------------------------------------*/
487

    
488
int float128_is_signaling_nan( float128 a )
489
{
490
#if SNAN_BIT_IS_ONE
491
    return
492
           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
493
        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
494
#else
495
    return
496
           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
497
        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
498
#endif
499
}
500

    
501
/*----------------------------------------------------------------------------
502
| Returns the result of converting the quadruple-precision floating-point NaN
503
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
504
| exception is raised.
505
*----------------------------------------------------------------------------*/
506

    
507
static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
508
{
509
    commonNaNT z;
510

    
511
    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
512
    z.sign = a.high>>63;
513
    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
514
    return z;
515
}
516

    
517
/*----------------------------------------------------------------------------
518
| Returns the result of converting the canonical NaN `a' to the quadruple-
519
| precision floating-point format.
520
*----------------------------------------------------------------------------*/
521

    
522
static float128 commonNaNToFloat128( commonNaNT a )
523
{
524
    float128 z;
525

    
526
    shift128Right( a.high, a.low, 16, &z.high, &z.low );
527
    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
528
    return z;
529
}
530

    
531
/*----------------------------------------------------------------------------
532
| Takes two quadruple-precision floating-point values `a' and `b', one of
533
| which is a NaN, and returns the appropriate NaN result.  If either `a' or
534
| `b' is a signaling NaN, the invalid exception is raised.
535
*----------------------------------------------------------------------------*/
536

    
537
static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
538
{
539
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
540

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

    
569
#endif