Statistics
| Branch: | Revision:

root / fpu / softfloat-specialize.h @ b645bb48

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

    
49
    STATUS(float_exception_flags) |= flags;
50

    
51
}
52

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

    
61
/*----------------------------------------------------------------------------
62
| The pattern for a default generated single-precision NaN.
63
*----------------------------------------------------------------------------*/
64
#if defined(TARGET_MIPS) || defined(TARGET_HPPA)
65
#define float32_default_nan 0xFF800000
66
#else
67
#define float32_default_nan 0xFFC00000
68
#endif
69

    
70
/*----------------------------------------------------------------------------
71
| Returns 1 if the single-precision floating-point value `a' is a NaN;
72
| otherwise returns 0.
73
*----------------------------------------------------------------------------*/
74

    
75
int float32_is_nan( float32 a )
76
{
77
#if defined(TARGET_MIPS) || defined(TARGET_HPPA)
78
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
79
#else
80
    return ( 0xFF800000 <= (bits32) ( a<<1 ) );
81
#endif
82
}
83

    
84
/*----------------------------------------------------------------------------
85
| Returns 1 if the single-precision floating-point value `a' is a signaling
86
| NaN; otherwise returns 0.
87
*----------------------------------------------------------------------------*/
88

    
89
int float32_is_signaling_nan( float32 a )
90
{
91
#if defined(TARGET_MIPS) || defined(TARGET_HPPA)
92
    return ( 0xFF800000 <= (bits32) ( a<<1 ) );
93
#else
94
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
95
#endif
96
}
97

    
98
/*----------------------------------------------------------------------------
99
| Returns the result of converting the single-precision floating-point NaN
100
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
101
| exception is raised.
102
*----------------------------------------------------------------------------*/
103

    
104
static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
105
{
106
    commonNaNT z;
107

    
108
    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
109
    z.sign = a>>31;
110
    z.low = 0;
111
    z.high = ( (bits64) a )<<41;
112
    return z;
113

    
114
}
115

    
116
/*----------------------------------------------------------------------------
117
| Returns the result of converting the canonical NaN `a' to the single-
118
| precision floating-point format.
119
*----------------------------------------------------------------------------*/
120

    
121
static float32 commonNaNToFloat32( commonNaNT a )
122
{
123

    
124
    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
125

    
126
}
127

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

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

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

    
165
}
166

    
167
/*----------------------------------------------------------------------------
168
| The pattern for a default generated double-precision NaN.
169
*----------------------------------------------------------------------------*/
170
#if defined(TARGET_MIPS) || defined(TARGET_HPPA)
171
#define float64_default_nan LIT64( 0xFFF0000000000000 )
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 NaN;
178
| otherwise returns 0.
179
*----------------------------------------------------------------------------*/
180

    
181
int float64_is_nan( float64 a )
182
{
183
#if defined(TARGET_MIPS) || defined(TARGET_HPPA)
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 defined(TARGET_MIPS) || defined(TARGET_HPPA)
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
/*----------------------------------------------------------------------------
227
| Returns the result of converting the canonical NaN `a' to the double-
228
| precision floating-point format.
229
*----------------------------------------------------------------------------*/
230

    
231
static float64 commonNaNToFloat64( commonNaNT a )
232
{
233

    
234
    return
235
          ( ( (bits64) a.sign )<<63 )
236
        | LIT64( 0x7FF8000000000000 )
237
        | ( a.high>>12 );
238

    
239
}
240

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

    
247
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
248
{
249
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
250

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

    
278
}
279

    
280
#ifdef FLOATX80
281

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

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

    
295
int floatx80_is_nan( floatx80 a )
296
{
297

    
298
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
299

    
300
}
301

    
302
/*----------------------------------------------------------------------------
303
| Returns 1 if the extended double-precision floating-point value `a' is a
304
| signaling NaN; otherwise returns 0.
305
*----------------------------------------------------------------------------*/
306

    
307
int floatx80_is_signaling_nan( floatx80 a )
308
{
309
    bits64 aLow;
310

    
311
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
312
    return
313
           ( ( a.high & 0x7FFF ) == 0x7FFF )
314
        && (bits64) ( aLow<<1 )
315
        && ( a.low == aLow );
316

    
317
}
318

    
319
/*----------------------------------------------------------------------------
320
| Returns the result of converting the extended double-precision floating-
321
| point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
322
| invalid exception is raised.
323
*----------------------------------------------------------------------------*/
324

    
325
static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
326
{
327
    commonNaNT z;
328

    
329
    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
330
    z.sign = a.high>>15;
331
    z.low = 0;
332
    z.high = a.low<<1;
333
    return z;
334

    
335
}
336

    
337
/*----------------------------------------------------------------------------
338
| Returns the result of converting the canonical NaN `a' to the extended
339
| double-precision floating-point format.
340
*----------------------------------------------------------------------------*/
341

    
342
static floatx80 commonNaNToFloatx80( commonNaNT a )
343
{
344
    floatx80 z;
345

    
346
    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
347
    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
348
    return z;
349

    
350
}
351

    
352
/*----------------------------------------------------------------------------
353
| Takes two extended double-precision floating-point values `a' and `b', one
354
| of which is a NaN, and returns the appropriate NaN result.  If either `a' or
355
| `b' is a signaling NaN, the invalid exception is raised.
356
*----------------------------------------------------------------------------*/
357

    
358
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
359
{
360
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
361

    
362
    aIsNaN = floatx80_is_nan( a );
363
    aIsSignalingNaN = floatx80_is_signaling_nan( a );
364
    bIsNaN = floatx80_is_nan( b );
365
    bIsSignalingNaN = floatx80_is_signaling_nan( b );
366
    a.low |= LIT64( 0xC000000000000000 );
367
    b.low |= LIT64( 0xC000000000000000 );
368
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
369
    if ( aIsSignalingNaN ) {
370
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
371
        return bIsNaN ? b : a;
372
    }
373
    else if ( aIsNaN ) {
374
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
375
 returnLargerSignificand:
376
        if ( a.low < b.low ) return b;
377
        if ( b.low < a.low ) return a;
378
        return ( a.high < b.high ) ? a : b;
379
    }
380
    else {
381
        return b;
382
    }
383

    
384
}
385

    
386
#endif
387

    
388
#ifdef FLOAT128
389

    
390
/*----------------------------------------------------------------------------
391
| The pattern for a default generated quadruple-precision NaN.  The `high' and
392
| `low' values hold the most- and least-significant bits, respectively.
393
*----------------------------------------------------------------------------*/
394
#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
395
#define float128_default_nan_low  LIT64( 0x0000000000000000 )
396

    
397
/*----------------------------------------------------------------------------
398
| Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
399
| otherwise returns 0.
400
*----------------------------------------------------------------------------*/
401

    
402
int float128_is_nan( float128 a )
403
{
404

    
405
    return
406
           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
407
        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
408

    
409
}
410

    
411
/*----------------------------------------------------------------------------
412
| Returns 1 if the quadruple-precision floating-point value `a' is a
413
| signaling NaN; otherwise returns 0.
414
*----------------------------------------------------------------------------*/
415

    
416
int float128_is_signaling_nan( float128 a )
417
{
418

    
419
    return
420
           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
421
        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
422

    
423
}
424

    
425
/*----------------------------------------------------------------------------
426
| Returns the result of converting the quadruple-precision floating-point NaN
427
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
428
| exception is raised.
429
*----------------------------------------------------------------------------*/
430

    
431
static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
432
{
433
    commonNaNT z;
434

    
435
    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
436
    z.sign = a.high>>63;
437
    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
438
    return z;
439

    
440
}
441

    
442
/*----------------------------------------------------------------------------
443
| Returns the result of converting the canonical NaN `a' to the quadruple-
444
| precision floating-point format.
445
*----------------------------------------------------------------------------*/
446

    
447
static float128 commonNaNToFloat128( commonNaNT a )
448
{
449
    float128 z;
450

    
451
    shift128Right( a.high, a.low, 16, &z.high, &z.low );
452
    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
453
    return z;
454

    
455
}
456

    
457
/*----------------------------------------------------------------------------
458
| Takes two quadruple-precision floating-point values `a' and `b', one of
459
| which is a NaN, and returns the appropriate NaN result.  If either `a' or
460
| `b' is a signaling NaN, the invalid exception is raised.
461
*----------------------------------------------------------------------------*/
462

    
463
static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
464
{
465
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
466

    
467
    aIsNaN = float128_is_nan( a );
468
    aIsSignalingNaN = float128_is_signaling_nan( a );
469
    bIsNaN = float128_is_nan( b );
470
    bIsSignalingNaN = float128_is_signaling_nan( b );
471
    a.high |= LIT64( 0x0000800000000000 );
472
    b.high |= LIT64( 0x0000800000000000 );
473
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
474
    if ( aIsSignalingNaN ) {
475
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
476
        return bIsNaN ? b : a;
477
    }
478
    else if ( aIsNaN ) {
479
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
480
 returnLargerSignificand:
481
        if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
482
        if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
483
        return ( a.high < b.high ) ? a : b;
484
    }
485
    else {
486
        return b;
487
    }
488

    
489
}
490

    
491
#endif
492