Statistics
| Branch: | Revision:

root / fpu / softfloat-specialize.h @ 5a6932d5

History | View | Annotate | Download (18.6 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 0x7FBFFFFF
70
#else
71
#define float32_default_nan 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
#if SNAN_BIT_IS_ONE
82
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
83
#else
84
    return ( 0xFF800000 <= (bits32) ( a<<1 ) );
85
#endif
86
}
87

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

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

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

    
108
static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
109
{
110
    commonNaNT z;
111

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

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

    
124
static float32 commonNaNToFloat32( commonNaNT a )
125
{
126
    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
127
}
128

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

    
135
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
136
{
137
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
138

    
139
    aIsNaN = float32_is_nan( a );
140
    aIsSignalingNaN = float32_is_signaling_nan( a );
141
    bIsNaN = float32_is_nan( b );
142
    bIsSignalingNaN = float32_is_signaling_nan( b );
143
#if SNAN_BIT_IS_ONE
144
    a &= ~0x00400000;
145
    b &= ~0x00400000;
146
#else
147
    a |= 0x00400000;
148
    b |= 0x00400000;
149
#endif
150
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
151
    if ( aIsSignalingNaN ) {
152
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
153
        return bIsNaN ? b : a;
154
    }
155
    else if ( aIsNaN ) {
156
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
157
 returnLargerSignificand:
158
        if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
159
        if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
160
        return ( a < b ) ? a : b;
161
    }
162
    else {
163
        return b;
164
    }
165
}
166

    
167
/*----------------------------------------------------------------------------
168
| The pattern for a default generated double-precision NaN.
169
*----------------------------------------------------------------------------*/
170
#if SNAN_BIT_IS_ONE
171
#define float64_default_nan LIT64( 0x7FF7FFFFFFFFFFFF )
172
#else
173
#define float64_default_nan LIT64( 0xFFF8000000000000 )
174
#endif
175

    
176
/*----------------------------------------------------------------------------
177
| Returns 1 if the double-precision floating-point value `a' is a quiet
178
| NaN; otherwise returns 0.
179
*----------------------------------------------------------------------------*/
180

    
181
int float64_is_nan( float64 a )
182
{
183
#if SNAN_BIT_IS_ONE
184
    return
185
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
186
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
187
#else
188
    return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
189
#endif
190
}
191

    
192
/*----------------------------------------------------------------------------
193
| Returns 1 if the double-precision floating-point value `a' is a signaling
194
| NaN; otherwise returns 0.
195
*----------------------------------------------------------------------------*/
196

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

    
208
/*----------------------------------------------------------------------------
209
| Returns the result of converting the double-precision floating-point NaN
210
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
211
| exception is raised.
212
*----------------------------------------------------------------------------*/
213

    
214
static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
215
{
216
    commonNaNT z;
217

    
218
    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
219
    z.sign = a>>63;
220
    z.low = 0;
221
    z.high = a<<12;
222
    return z;
223
}
224

    
225
/*----------------------------------------------------------------------------
226
| Returns the result of converting the canonical NaN `a' to the double-
227
| precision floating-point format.
228
*----------------------------------------------------------------------------*/
229

    
230
static float64 commonNaNToFloat64( commonNaNT a )
231
{
232
    return
233
          ( ( (bits64) a.sign )<<63 )
234
        | LIT64( 0x7FF8000000000000 )
235
        | ( a.high>>12 );
236
}
237

    
238
/*----------------------------------------------------------------------------
239
| Takes two double-precision floating-point values `a' and `b', one of which
240
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
241
| signaling NaN, the invalid exception is raised.
242
*----------------------------------------------------------------------------*/
243

    
244
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
245
{
246
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
247

    
248
    aIsNaN = float64_is_nan( a );
249
    aIsSignalingNaN = float64_is_signaling_nan( a );
250
    bIsNaN = float64_is_nan( b );
251
    bIsSignalingNaN = float64_is_signaling_nan( b );
252
#if SNAN_BIT_IS_ONE
253
    a &= ~LIT64( 0x0008000000000000 );
254
    b &= ~LIT64( 0x0008000000000000 );
255
#else
256
    a |= LIT64( 0x0008000000000000 );
257
    b |= LIT64( 0x0008000000000000 );
258
#endif
259
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
260
    if ( aIsSignalingNaN ) {
261
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
262
        return bIsNaN ? b : a;
263
    }
264
    else if ( aIsNaN ) {
265
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
266
 returnLargerSignificand:
267
        if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
268
        if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
269
        return ( a < b ) ? a : b;
270
    }
271
    else {
272
        return b;
273
    }
274
}
275

    
276
#ifdef FLOATX80
277

    
278
/*----------------------------------------------------------------------------
279
| The pattern for a default generated extended double-precision NaN.  The
280
| `high' and `low' values hold the most- and least-significant bits,
281
| respectively.
282
*----------------------------------------------------------------------------*/
283
#if SNAN_BIT_IS_ONE
284
#define floatx80_default_nan_high 0x7FFF
285
#define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
286
#else
287
#define floatx80_default_nan_high 0xFFFF
288
#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
289
#endif
290

    
291
/*----------------------------------------------------------------------------
292
| Returns 1 if the extended double-precision floating-point value `a' is a
293
| quiet NaN; otherwise returns 0.
294
*----------------------------------------------------------------------------*/
295

    
296
int floatx80_is_nan( floatx80 a )
297
{
298
#if SNAN_BIT_IS_ONE
299
    bits64 aLow;
300

    
301
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
302
    return
303
           ( ( a.high & 0x7FFF ) == 0x7FFF )
304
        && (bits64) ( aLow<<1 )
305
        && ( a.low == aLow );
306
#else
307
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
308
#endif
309
}
310

    
311
/*----------------------------------------------------------------------------
312
| Returns 1 if the extended double-precision floating-point value `a' is a
313
| signaling NaN; otherwise returns 0.
314
*----------------------------------------------------------------------------*/
315

    
316
int floatx80_is_signaling_nan( floatx80 a )
317
{
318
#if SNAN_BIT_IS_ONE
319
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
320
#else
321
    bits64 aLow;
322

    
323
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
324
    return
325
           ( ( a.high & 0x7FFF ) == 0x7FFF )
326
        && (bits64) ( aLow<<1 )
327
        && ( a.low == aLow );
328
#endif
329
}
330

    
331
/*----------------------------------------------------------------------------
332
| Returns the result of converting the extended double-precision floating-
333
| point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
334
| invalid exception is raised.
335
*----------------------------------------------------------------------------*/
336

    
337
static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
338
{
339
    commonNaNT z;
340

    
341
    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
342
    z.sign = a.high>>15;
343
    z.low = 0;
344
    z.high = a.low<<1;
345
    return z;
346
}
347

    
348
/*----------------------------------------------------------------------------
349
| Returns the result of converting the canonical NaN `a' to the extended
350
| double-precision floating-point format.
351
*----------------------------------------------------------------------------*/
352

    
353
static floatx80 commonNaNToFloatx80( commonNaNT a )
354
{
355
    floatx80 z;
356

    
357
    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
358
    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
359
    return z;
360
}
361

    
362
/*----------------------------------------------------------------------------
363
| Takes two extended double-precision floating-point values `a' and `b', one
364
| of which is a NaN, and returns the appropriate NaN result.  If either `a' or
365
| `b' is a signaling NaN, the invalid exception is raised.
366
*----------------------------------------------------------------------------*/
367

    
368
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
369
{
370
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
371

    
372
    aIsNaN = floatx80_is_nan( a );
373
    aIsSignalingNaN = floatx80_is_signaling_nan( a );
374
    bIsNaN = floatx80_is_nan( b );
375
    bIsSignalingNaN = floatx80_is_signaling_nan( b );
376
#if SNAN_BIT_IS_ONE
377
    a.low &= ~LIT64( 0xC000000000000000 );
378
    b.low &= ~LIT64( 0xC000000000000000 );
379
#else
380
    a.low |= LIT64( 0xC000000000000000 );
381
    b.low |= LIT64( 0xC000000000000000 );
382
#endif
383
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
384
    if ( aIsSignalingNaN ) {
385
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
386
        return bIsNaN ? b : a;
387
    }
388
    else if ( aIsNaN ) {
389
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
390
 returnLargerSignificand:
391
        if ( a.low < b.low ) return b;
392
        if ( b.low < a.low ) return a;
393
        return ( a.high < b.high ) ? a : b;
394
    }
395
    else {
396
        return b;
397
    }
398
}
399

    
400
#endif
401

    
402
#ifdef FLOAT128
403

    
404
/*----------------------------------------------------------------------------
405
| The pattern for a default generated quadruple-precision NaN.  The `high' and
406
| `low' values hold the most- and least-significant bits, respectively.
407
*----------------------------------------------------------------------------*/
408
#if SNAN_BIT_IS_ONE
409
#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
410
#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
411
#else
412
#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
413
#define float128_default_nan_low  LIT64( 0x0000000000000000 )
414
#endif
415

    
416
/*----------------------------------------------------------------------------
417
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
418
| NaN; otherwise returns 0.
419
*----------------------------------------------------------------------------*/
420

    
421
int float128_is_nan( float128 a )
422
{
423
#if SNAN_BIT_IS_ONE
424
    return
425
           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
426
        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
427
#else
428
    return
429
           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
430
        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
431
#endif
432
}
433

    
434
/*----------------------------------------------------------------------------
435
| Returns 1 if the quadruple-precision floating-point value `a' is a
436
| signaling NaN; otherwise returns 0.
437
*----------------------------------------------------------------------------*/
438

    
439
int float128_is_signaling_nan( float128 a )
440
{
441
#if SNAN_BIT_IS_ONE
442
    return
443
           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
444
        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
445
#else
446
    return
447
           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
448
        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
449
#endif
450
}
451

    
452
/*----------------------------------------------------------------------------
453
| Returns the result of converting the quadruple-precision floating-point NaN
454
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
455
| exception is raised.
456
*----------------------------------------------------------------------------*/
457

    
458
static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
459
{
460
    commonNaNT z;
461

    
462
    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
463
    z.sign = a.high>>63;
464
    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
465
    return z;
466
}
467

    
468
/*----------------------------------------------------------------------------
469
| Returns the result of converting the canonical NaN `a' to the quadruple-
470
| precision floating-point format.
471
*----------------------------------------------------------------------------*/
472

    
473
static float128 commonNaNToFloat128( commonNaNT a )
474
{
475
    float128 z;
476

    
477
    shift128Right( a.high, a.low, 16, &z.high, &z.low );
478
    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
479
    return z;
480
}
481

    
482
/*----------------------------------------------------------------------------
483
| Takes two quadruple-precision floating-point values `a' and `b', one of
484
| which is a NaN, and returns the appropriate NaN result.  If either `a' or
485
| `b' is a signaling NaN, the invalid exception is raised.
486
*----------------------------------------------------------------------------*/
487

    
488
static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
489
{
490
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
491

    
492
    aIsNaN = float128_is_nan( a );
493
    aIsSignalingNaN = float128_is_signaling_nan( a );
494
    bIsNaN = float128_is_nan( b );
495
    bIsSignalingNaN = float128_is_signaling_nan( b );
496
#if SNAN_BIT_IS_ONE
497
    a.high &= ~LIT64( 0x0000800000000000 );
498
    b.high &= ~LIT64( 0x0000800000000000 );
499
#else
500
    a.high |= LIT64( 0x0000800000000000 );
501
    b.high |= LIT64( 0x0000800000000000 );
502
#endif
503
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
504
    if ( aIsSignalingNaN ) {
505
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
506
        return bIsNaN ? b : a;
507
    }
508
    else if ( aIsNaN ) {
509
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
510
 returnLargerSignificand:
511
        if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
512
        if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
513
        return ( a.high < b.high ) ? a : b;
514
    }
515
    else {
516
        return b;
517
    }
518
}
519

    
520
#endif