Statistics
| Branch: | Revision:

root / fpu / softfloat-specialize.h @ f090c9d4

History | View | Annotate | Download (19.3 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 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
    return make_float32(
129
        ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ) );
130
}
131

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

    
138
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
139
{
140
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
141
    bits32 av, bv, res;
142

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

    
180
/*----------------------------------------------------------------------------
181
| The pattern for a default generated double-precision NaN.
182
*----------------------------------------------------------------------------*/
183
#if SNAN_BIT_IS_ONE
184
#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
185
#else
186
#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
187
#endif
188

    
189
/*----------------------------------------------------------------------------
190
| Returns 1 if the double-precision floating-point value `a' is a quiet
191
| NaN; otherwise returns 0.
192
*----------------------------------------------------------------------------*/
193

    
194
int float64_is_nan( float64 a_ )
195
{
196
    bits64 a = float64_val(a_);
197
#if SNAN_BIT_IS_ONE
198
    return
199
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
200
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
201
#else
202
    return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
203
#endif
204
}
205

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

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

    
223
/*----------------------------------------------------------------------------
224
| Returns the result of converting the double-precision floating-point NaN
225
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
226
| exception is raised.
227
*----------------------------------------------------------------------------*/
228

    
229
static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
230
{
231
    commonNaNT z;
232

    
233
    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
234
    z.sign = float64_val(a)>>63;
235
    z.low = 0;
236
    z.high = float64_val(a)<<12;
237
    return z;
238
}
239

    
240
/*----------------------------------------------------------------------------
241
| Returns the result of converting the canonical NaN `a' to the double-
242
| precision floating-point format.
243
*----------------------------------------------------------------------------*/
244

    
245
static float64 commonNaNToFloat64( commonNaNT a )
246
{
247
    return make_float64(
248
          ( ( (bits64) a.sign )<<63 )
249
        | LIT64( 0x7FF8000000000000 )
250
        | ( a.high>>12 ));
251
}
252

    
253
/*----------------------------------------------------------------------------
254
| Takes two double-precision floating-point values `a' and `b', one of which
255
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
256
| signaling NaN, the invalid exception is raised.
257
*----------------------------------------------------------------------------*/
258

    
259
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
260
{
261
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
262
    bits64 av, bv, res;
263

    
264
    aIsNaN = float64_is_nan( a );
265
    aIsSignalingNaN = float64_is_signaling_nan( a );
266
    bIsNaN = float64_is_nan( b );
267
    bIsSignalingNaN = float64_is_signaling_nan( b );
268
    av = float64_val(a);
269
    bv = float64_val(b);
270
#if SNAN_BIT_IS_ONE
271
    av &= ~LIT64( 0x0008000000000000 );
272
    bv &= ~LIT64( 0x0008000000000000 );
273
#else
274
    av |= LIT64( 0x0008000000000000 );
275
    bv |= LIT64( 0x0008000000000000 );
276
#endif
277
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
278
    if ( aIsSignalingNaN ) {
279
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
280
        res = bIsNaN ? bv : av;
281
    }
282
    else if ( aIsNaN ) {
283
        if ( bIsSignalingNaN | ! bIsNaN )
284
            res = av;
285
        else {
286
 returnLargerSignificand:
287
            if ( (bits64) ( av<<1 ) < (bits64) ( bv<<1 ) )
288
                res = bv;
289
            else if ( (bits64) ( bv<<1 ) < (bits64) ( av<<1 ) )
290
                res = av;
291
            else
292
                res = ( av < bv ) ? av : bv;
293
        }
294
    }
295
    else {
296
        res = bv;
297
    }
298
    return make_float64(res);
299
}
300

    
301
#ifdef FLOATX80
302

    
303
/*----------------------------------------------------------------------------
304
| The pattern for a default generated extended double-precision NaN.  The
305
| `high' and `low' values hold the most- and least-significant bits,
306
| respectively.
307
*----------------------------------------------------------------------------*/
308
#if SNAN_BIT_IS_ONE
309
#define floatx80_default_nan_high 0x7FFF
310
#define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
311
#else
312
#define floatx80_default_nan_high 0xFFFF
313
#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
314
#endif
315

    
316
/*----------------------------------------------------------------------------
317
| Returns 1 if the extended double-precision floating-point value `a' is a
318
| quiet NaN; otherwise returns 0.
319
*----------------------------------------------------------------------------*/
320

    
321
int floatx80_is_nan( floatx80 a )
322
{
323
#if SNAN_BIT_IS_ONE
324
    bits64 aLow;
325

    
326
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
327
    return
328
           ( ( a.high & 0x7FFF ) == 0x7FFF )
329
        && (bits64) ( aLow<<1 )
330
        && ( a.low == aLow );
331
#else
332
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
333
#endif
334
}
335

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

    
341
int floatx80_is_signaling_nan( floatx80 a )
342
{
343
#if SNAN_BIT_IS_ONE
344
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
345
#else
346
    bits64 aLow;
347

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

    
356
/*----------------------------------------------------------------------------
357
| Returns the result of converting the extended double-precision floating-
358
| point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
359
| invalid exception is raised.
360
*----------------------------------------------------------------------------*/
361

    
362
static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
363
{
364
    commonNaNT z;
365

    
366
    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
367
    z.sign = a.high>>15;
368
    z.low = 0;
369
    z.high = a.low<<1;
370
    return z;
371
}
372

    
373
/*----------------------------------------------------------------------------
374
| Returns the result of converting the canonical NaN `a' to the extended
375
| double-precision floating-point format.
376
*----------------------------------------------------------------------------*/
377

    
378
static floatx80 commonNaNToFloatx80( commonNaNT a )
379
{
380
    floatx80 z;
381

    
382
    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
383
    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
384
    return z;
385
}
386

    
387
/*----------------------------------------------------------------------------
388
| Takes two extended double-precision floating-point values `a' and `b', one
389
| of which is a NaN, and returns the appropriate NaN result.  If either `a' or
390
| `b' is a signaling NaN, the invalid exception is raised.
391
*----------------------------------------------------------------------------*/
392

    
393
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
394
{
395
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
396

    
397
    aIsNaN = floatx80_is_nan( a );
398
    aIsSignalingNaN = floatx80_is_signaling_nan( a );
399
    bIsNaN = floatx80_is_nan( b );
400
    bIsSignalingNaN = floatx80_is_signaling_nan( b );
401
#if SNAN_BIT_IS_ONE
402
    a.low &= ~LIT64( 0xC000000000000000 );
403
    b.low &= ~LIT64( 0xC000000000000000 );
404
#else
405
    a.low |= LIT64( 0xC000000000000000 );
406
    b.low |= LIT64( 0xC000000000000000 );
407
#endif
408
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
409
    if ( aIsSignalingNaN ) {
410
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
411
        return bIsNaN ? b : a;
412
    }
413
    else if ( aIsNaN ) {
414
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
415
 returnLargerSignificand:
416
        if ( a.low < b.low ) return b;
417
        if ( b.low < a.low ) return a;
418
        return ( a.high < b.high ) ? a : b;
419
    }
420
    else {
421
        return b;
422
    }
423
}
424

    
425
#endif
426

    
427
#ifdef FLOAT128
428

    
429
/*----------------------------------------------------------------------------
430
| The pattern for a default generated quadruple-precision NaN.  The `high' and
431
| `low' values hold the most- and least-significant bits, respectively.
432
*----------------------------------------------------------------------------*/
433
#if SNAN_BIT_IS_ONE
434
#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
435
#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
436
#else
437
#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
438
#define float128_default_nan_low  LIT64( 0x0000000000000000 )
439
#endif
440

    
441
/*----------------------------------------------------------------------------
442
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
443
| NaN; otherwise returns 0.
444
*----------------------------------------------------------------------------*/
445

    
446
int float128_is_nan( float128 a )
447
{
448
#if SNAN_BIT_IS_ONE
449
    return
450
           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
451
        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
452
#else
453
    return
454
           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
455
        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
456
#endif
457
}
458

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

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

    
477
/*----------------------------------------------------------------------------
478
| Returns the result of converting the quadruple-precision floating-point NaN
479
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
480
| exception is raised.
481
*----------------------------------------------------------------------------*/
482

    
483
static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
484
{
485
    commonNaNT z;
486

    
487
    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
488
    z.sign = a.high>>63;
489
    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
490
    return z;
491
}
492

    
493
/*----------------------------------------------------------------------------
494
| Returns the result of converting the canonical NaN `a' to the quadruple-
495
| precision floating-point format.
496
*----------------------------------------------------------------------------*/
497

    
498
static float128 commonNaNToFloat128( commonNaNT a )
499
{
500
    float128 z;
501

    
502
    shift128Right( a.high, a.low, 16, &z.high, &z.low );
503
    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
504
    return z;
505
}
506

    
507
/*----------------------------------------------------------------------------
508
| Takes two quadruple-precision floating-point values `a' and `b', one of
509
| which is a NaN, and returns the appropriate NaN result.  If either `a' or
510
| `b' is a signaling NaN, the invalid exception is raised.
511
*----------------------------------------------------------------------------*/
512

    
513
static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
514
{
515
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
516

    
517
    aIsNaN = float128_is_nan( a );
518
    aIsSignalingNaN = float128_is_signaling_nan( a );
519
    bIsNaN = float128_is_nan( b );
520
    bIsSignalingNaN = float128_is_signaling_nan( b );
521
#if SNAN_BIT_IS_ONE
522
    a.high &= ~LIT64( 0x0000800000000000 );
523
    b.high &= ~LIT64( 0x0000800000000000 );
524
#else
525
    a.high |= LIT64( 0x0000800000000000 );
526
    b.high |= LIT64( 0x0000800000000000 );
527
#endif
528
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
529
    if ( aIsSignalingNaN ) {
530
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
531
        return bIsNaN ? b : a;
532
    }
533
    else if ( aIsNaN ) {
534
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
535
 returnLargerSignificand:
536
        if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
537
        if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
538
        return ( a.high < b.high ) ? a : b;
539
    }
540
    else {
541
        return b;
542
    }
543
}
544

    
545
#endif