Statistics
| Branch: | Revision:

root / fpu / softfloat-specialize.h @ 750afe93

History | View | Annotate | Download (16.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
#define float32_default_nan 0xFFC00000
65

    
66
/*----------------------------------------------------------------------------
67
| Returns 1 if the single-precision floating-point value `a' is a NaN;
68
| otherwise returns 0.
69
*----------------------------------------------------------------------------*/
70

    
71
int float32_is_nan( float32 a )
72
{
73

    
74
    return ( 0xFF000000 < (bits32) ( a<<1 ) );
75

    
76
}
77

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

    
83
int float32_is_signaling_nan( float32 a )
84
{
85

    
86
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
87

    
88
}
89

    
90
/*----------------------------------------------------------------------------
91
| Returns the result of converting the single-precision floating-point NaN
92
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
93
| exception is raised.
94
*----------------------------------------------------------------------------*/
95

    
96
static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
97
{
98
    commonNaNT z;
99

    
100
    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
101
    z.sign = a>>31;
102
    z.low = 0;
103
    z.high = ( (bits64) a )<<41;
104
    return z;
105

    
106
}
107

    
108
/*----------------------------------------------------------------------------
109
| Returns the result of converting the canonical NaN `a' to the single-
110
| precision floating-point format.
111
*----------------------------------------------------------------------------*/
112

    
113
static float32 commonNaNToFloat32( commonNaNT a )
114
{
115

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

    
118
}
119

    
120
/*----------------------------------------------------------------------------
121
| Takes two single-precision floating-point values `a' and `b', one of which
122
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
123
| signaling NaN, the invalid exception is raised.
124
*----------------------------------------------------------------------------*/
125

    
126
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
127
{
128
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
129

    
130
    aIsNaN = float32_is_nan( a );
131
    aIsSignalingNaN = float32_is_signaling_nan( a );
132
    bIsNaN = float32_is_nan( b );
133
    bIsSignalingNaN = float32_is_signaling_nan( b );
134
    a |= 0x00400000;
135
    b |= 0x00400000;
136
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
137
    if ( aIsSignalingNaN ) {
138
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
139
        return bIsNaN ? b : a;
140
    }
141
    else if ( aIsNaN ) {
142
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
143
 returnLargerSignificand:
144
        if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
145
        if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
146
        return ( a < b ) ? a : b;
147
    }
148
    else {
149
        return b;
150
    }
151

    
152
}
153

    
154
/*----------------------------------------------------------------------------
155
| The pattern for a default generated double-precision NaN.
156
*----------------------------------------------------------------------------*/
157
#define float64_default_nan LIT64( 0xFFF8000000000000 )
158

    
159
/*----------------------------------------------------------------------------
160
| Returns 1 if the double-precision floating-point value `a' is a NaN;
161
| otherwise returns 0.
162
*----------------------------------------------------------------------------*/
163

    
164
int float64_is_nan( float64 a )
165
{
166

    
167
    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
168

    
169
}
170

    
171
/*----------------------------------------------------------------------------
172
| Returns 1 if the double-precision floating-point value `a' is a signaling
173
| NaN; otherwise returns 0.
174
*----------------------------------------------------------------------------*/
175

    
176
int float64_is_signaling_nan( float64 a )
177
{
178

    
179
    return
180
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
181
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
182

    
183
}
184

    
185
/*----------------------------------------------------------------------------
186
| Returns the result of converting the double-precision floating-point NaN
187
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
188
| exception is raised.
189
*----------------------------------------------------------------------------*/
190

    
191
static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
192
{
193
    commonNaNT z;
194

    
195
    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
196
    z.sign = a>>63;
197
    z.low = 0;
198
    z.high = a<<12;
199
    return z;
200

    
201
}
202

    
203
/*----------------------------------------------------------------------------
204
| Returns the result of converting the canonical NaN `a' to the double-
205
| precision floating-point format.
206
*----------------------------------------------------------------------------*/
207

    
208
static float64 commonNaNToFloat64( commonNaNT a )
209
{
210

    
211
    return
212
          ( ( (bits64) a.sign )<<63 )
213
        | LIT64( 0x7FF8000000000000 )
214
        | ( a.high>>12 );
215

    
216
}
217

    
218
/*----------------------------------------------------------------------------
219
| Takes two double-precision floating-point values `a' and `b', one of which
220
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
221
| signaling NaN, the invalid exception is raised.
222
*----------------------------------------------------------------------------*/
223

    
224
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
225
{
226
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
227

    
228
    aIsNaN = float64_is_nan( a );
229
    aIsSignalingNaN = float64_is_signaling_nan( a );
230
    bIsNaN = float64_is_nan( b );
231
    bIsSignalingNaN = float64_is_signaling_nan( b );
232
    a |= LIT64( 0x0008000000000000 );
233
    b |= LIT64( 0x0008000000000000 );
234
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
235
    if ( aIsSignalingNaN ) {
236
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
237
        return bIsNaN ? b : a;
238
    }
239
    else if ( aIsNaN ) {
240
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
241
 returnLargerSignificand:
242
        if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
243
        if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
244
        return ( a < b ) ? a : b;
245
    }
246
    else {
247
        return b;
248
    }
249

    
250
}
251

    
252
#ifdef FLOATX80
253

    
254
/*----------------------------------------------------------------------------
255
| The pattern for a default generated extended double-precision NaN.  The
256
| `high' and `low' values hold the most- and least-significant bits,
257
| respectively.
258
*----------------------------------------------------------------------------*/
259
#define floatx80_default_nan_high 0xFFFF
260
#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
261

    
262
/*----------------------------------------------------------------------------
263
| Returns 1 if the extended double-precision floating-point value `a' is a
264
| NaN; otherwise returns 0.
265
*----------------------------------------------------------------------------*/
266

    
267
int floatx80_is_nan( floatx80 a )
268
{
269

    
270
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
271

    
272
}
273

    
274
/*----------------------------------------------------------------------------
275
| Returns 1 if the extended double-precision floating-point value `a' is a
276
| signaling NaN; otherwise returns 0.
277
*----------------------------------------------------------------------------*/
278

    
279
int floatx80_is_signaling_nan( floatx80 a )
280
{
281
    bits64 aLow;
282

    
283
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
284
    return
285
           ( ( a.high & 0x7FFF ) == 0x7FFF )
286
        && (bits64) ( aLow<<1 )
287
        && ( a.low == aLow );
288

    
289
}
290

    
291
/*----------------------------------------------------------------------------
292
| Returns the result of converting the extended double-precision floating-
293
| point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
294
| invalid exception is raised.
295
*----------------------------------------------------------------------------*/
296

    
297
static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
298
{
299
    commonNaNT z;
300

    
301
    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
302
    z.sign = a.high>>15;
303
    z.low = 0;
304
    z.high = a.low<<1;
305
    return z;
306

    
307
}
308

    
309
/*----------------------------------------------------------------------------
310
| Returns the result of converting the canonical NaN `a' to the extended
311
| double-precision floating-point format.
312
*----------------------------------------------------------------------------*/
313

    
314
static floatx80 commonNaNToFloatx80( commonNaNT a )
315
{
316
    floatx80 z;
317

    
318
    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
319
    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
320
    return z;
321

    
322
}
323

    
324
/*----------------------------------------------------------------------------
325
| Takes two extended double-precision floating-point values `a' and `b', one
326
| of which is a NaN, and returns the appropriate NaN result.  If either `a' or
327
| `b' is a signaling NaN, the invalid exception is raised.
328
*----------------------------------------------------------------------------*/
329

    
330
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
331
{
332
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
333

    
334
    aIsNaN = floatx80_is_nan( a );
335
    aIsSignalingNaN = floatx80_is_signaling_nan( a );
336
    bIsNaN = floatx80_is_nan( b );
337
    bIsSignalingNaN = floatx80_is_signaling_nan( b );
338
    a.low |= LIT64( 0xC000000000000000 );
339
    b.low |= LIT64( 0xC000000000000000 );
340
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
341
    if ( aIsSignalingNaN ) {
342
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
343
        return bIsNaN ? b : a;
344
    }
345
    else if ( aIsNaN ) {
346
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
347
 returnLargerSignificand:
348
        if ( a.low < b.low ) return b;
349
        if ( b.low < a.low ) return a;
350
        return ( a.high < b.high ) ? a : b;
351
    }
352
    else {
353
        return b;
354
    }
355

    
356
}
357

    
358
#endif
359

    
360
#ifdef FLOAT128
361

    
362
/*----------------------------------------------------------------------------
363
| The pattern for a default generated quadruple-precision NaN.  The `high' and
364
| `low' values hold the most- and least-significant bits, respectively.
365
*----------------------------------------------------------------------------*/
366
#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
367
#define float128_default_nan_low  LIT64( 0x0000000000000000 )
368

    
369
/*----------------------------------------------------------------------------
370
| Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
371
| otherwise returns 0.
372
*----------------------------------------------------------------------------*/
373

    
374
int float128_is_nan( float128 a )
375
{
376

    
377
    return
378
           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
379
        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
380

    
381
}
382

    
383
/*----------------------------------------------------------------------------
384
| Returns 1 if the quadruple-precision floating-point value `a' is a
385
| signaling NaN; otherwise returns 0.
386
*----------------------------------------------------------------------------*/
387

    
388
int float128_is_signaling_nan( float128 a )
389
{
390

    
391
    return
392
           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
393
        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
394

    
395
}
396

    
397
/*----------------------------------------------------------------------------
398
| Returns the result of converting the quadruple-precision floating-point NaN
399
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
400
| exception is raised.
401
*----------------------------------------------------------------------------*/
402

    
403
static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
404
{
405
    commonNaNT z;
406

    
407
    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
408
    z.sign = a.high>>63;
409
    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
410
    return z;
411

    
412
}
413

    
414
/*----------------------------------------------------------------------------
415
| Returns the result of converting the canonical NaN `a' to the quadruple-
416
| precision floating-point format.
417
*----------------------------------------------------------------------------*/
418

    
419
static float128 commonNaNToFloat128( commonNaNT a )
420
{
421
    float128 z;
422

    
423
    shift128Right( a.high, a.low, 16, &z.high, &z.low );
424
    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
425
    return z;
426

    
427
}
428

    
429
/*----------------------------------------------------------------------------
430
| Takes two quadruple-precision floating-point values `a' and `b', one of
431
| which is a NaN, and returns the appropriate NaN result.  If either `a' or
432
| `b' is a signaling NaN, the invalid exception is raised.
433
*----------------------------------------------------------------------------*/
434

    
435
static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
436
{
437
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
438

    
439
    aIsNaN = float128_is_nan( a );
440
    aIsSignalingNaN = float128_is_signaling_nan( a );
441
    bIsNaN = float128_is_nan( b );
442
    bIsSignalingNaN = float128_is_signaling_nan( b );
443
    a.high |= LIT64( 0x0000800000000000 );
444
    b.high |= LIT64( 0x0000800000000000 );
445
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
446
    if ( aIsSignalingNaN ) {
447
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
448
        return bIsNaN ? b : a;
449
    }
450
    else if ( aIsNaN ) {
451
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
452
 returnLargerSignificand:
453
        if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
454
        if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
455
        return ( a.high < b.high ) ? a : b;
456
    }
457
    else {
458
        return b;
459
    }
460

    
461
}
462

    
463
#endif
464