|
|
1.1 root 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_before_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 to
42: | 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 )
47: {
48:
49: float_exception_flags |= flags;
50:
51: }
52:
53: #ifdef SOFTFLOAT_I860
54: void float_raise2( int8 flags )
55: {
56:
57: float_exception_flags2 |= flags;
58:
59: }
60: #endif
61:
62: /*----------------------------------------------------------------------------
63: | Internal canonical NaN format.
64: *----------------------------------------------------------------------------*/
65: typedef struct {
66: flag sign;
67: bits64 high, low;
68: } commonNaNT;
69:
70: /*----------------------------------------------------------------------------
71: | Returns 1 if the single-precision floating-point value `a' is a NaN;
72: | otherwise returns 0.
73: *----------------------------------------------------------------------------*/
74:
75: flag float32_is_nan( float32 a )
76: {
77:
78: return ( 0xFF000000 < (bits32) ( a<<1 ) );
79:
80: }
81:
82: /*----------------------------------------------------------------------------
83: | Returns 1 if the single-precision floating-point value `a' is a signaling
84: | NaN; otherwise returns 0.
85: *----------------------------------------------------------------------------*/
86:
87: flag float32_is_signaling_nan( float32 a )
88: {
89:
90: return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
91:
92: }
93:
94: /*----------------------------------------------------------------------------
95: | Returns the result of converting the single-precision floating-point NaN
96: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
97: | exception is raised.
98: *----------------------------------------------------------------------------*/
99:
100: static commonNaNT float32ToCommonNaN( float32 a )
101: {
102: commonNaNT z;
103:
104: #ifdef SOFTFLOAT_I860
105: if ( float32_is_signaling_nan( a ) ) float_raise2( float_flag_signaling );
106: #else
107: if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_signaling );
108: #endif
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 )
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: a |= 0x00400000;
143: b |= 0x00400000;
144: #ifdef SOFTFLOAT_I860
145: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise2( float_flag_signaling );
146: #else
147: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling );
148: #endif
149: if ( aIsNaN ) {
150: return ( aIsSignalingNaN & bIsNaN ) ? b : a;
151: }
152: else {
153: return b;
154: }
155:
156: }
157:
158: /*----------------------------------------------------------------------------
159: | Returns 1 if the double-precision floating-point value `a' is a NaN;
160: | otherwise returns 0.
161: *----------------------------------------------------------------------------*/
162:
163: flag float64_is_nan( float64 a )
164: {
165:
166: return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
167:
168: }
169:
170: /*----------------------------------------------------------------------------
171: | Returns 1 if the double-precision floating-point value `a' is a signaling
172: | NaN; otherwise returns 0.
173: *----------------------------------------------------------------------------*/
174:
175: flag float64_is_signaling_nan( float64 a )
176: {
177:
178: return
179: ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
180: && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
181:
182: }
183:
184: /*----------------------------------------------------------------------------
185: | Returns the result of converting the double-precision floating-point NaN
186: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
187: | exception is raised.
188: *----------------------------------------------------------------------------*/
189:
190: static commonNaNT float64ToCommonNaN( float64 a )
191: {
192: commonNaNT z;
193:
194: #ifdef SOFTFLOAT_I860
195: if ( float64_is_signaling_nan( a ) ) float_raise2( float_flag_signaling );
196: #else
197: if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_signaling );
198: #endif
199: z.sign = a>>63;
200: z.low = 0;
201: z.high = a<<12;
202: return z;
203:
204: }
205:
206: /*----------------------------------------------------------------------------
207: | Returns the result of converting the canonical NaN `a' to the double-
208: | precision floating-point format.
209: *----------------------------------------------------------------------------*/
210:
211: static float64 commonNaNToFloat64( commonNaNT a )
212: {
213:
214: return
215: ( ( (bits64) a.sign )<<63 )
216: | LIT64( 0x7FF8000000000000 )
217: | ( a.high>>12 );
218:
219: }
220:
221: /*----------------------------------------------------------------------------
222: | Takes two double-precision floating-point values `a' and `b', one of which
223: | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
224: | signaling NaN, the invalid exception is raised.
225: *----------------------------------------------------------------------------*/
226:
227: static float64 propagateFloat64NaN( float64 a, float64 b )
228: {
229: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
230:
231: aIsNaN = float64_is_nan( a );
232: aIsSignalingNaN = float64_is_signaling_nan( a );
233: bIsNaN = float64_is_nan( b );
234: bIsSignalingNaN = float64_is_signaling_nan( b );
235: a |= LIT64( 0x0008000000000000 );
236: b |= LIT64( 0x0008000000000000 );
237: #ifdef SOFTFLOAT_I860
238: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise2( float_flag_signaling );
239: #else
240: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling );
241: #endif
242: if ( aIsNaN ) {
243: return ( aIsSignalingNaN & bIsNaN ) ? b : a;
244: }
245: else {
246: return b;
247: }
248:
249: }
250:
251: #ifdef FLOATX80
252:
253: /*----------------------------------------------------------------------------
254: | Returns 1 if the extended double-precision floating-point value `a' is a
255: | NaN; otherwise returns 0.
256: *----------------------------------------------------------------------------*/
257:
258: flag floatx80_is_nan( floatx80 a )
259: {
260:
261: return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
262:
263: }
264:
265: /*----------------------------------------------------------------------------
266: | Returns 1 if the extended double-precision floating-point value `a' is a
267: | signaling NaN; otherwise returns 0.
268: *----------------------------------------------------------------------------*/
269:
270: flag floatx80_is_signaling_nan( floatx80 a )
271: {
272: bits64 aLow;
273:
274: aLow = a.low & ~ LIT64( 0x4000000000000000 );
275: return
276: ( ( a.high & 0x7FFF ) == 0x7FFF )
277: && (bits64) ( aLow<<1 )
278: && ( a.low == aLow );
279:
280: }
281:
282: #ifdef SOFTFLOAT_68K // 28-12-2016: Added for Previous:
283:
284: /*----------------------------------------------------------------------------
285: | Returns 1 if the extended double-precision floating-point value `a' is
286: | zero; otherwise returns 0.
287: *----------------------------------------------------------------------------*/
288:
289: flag floatx80_is_zero( floatx80 a )
290: {
291:
292: return ( ( a.high & 0x7FFF ) < 0x7FFF ) && ( a.low == 0 );
293:
294: }
295:
296: /*----------------------------------------------------------------------------
297: | Returns 1 if the extended double-precision floating-point value `a' is
298: | infinity; otherwise returns 0.
299: *----------------------------------------------------------------------------*/
300:
301: flag floatx80_is_infinity( floatx80 a )
302: {
303:
304: return ( ( a.high & 0x7FFF ) == 0x7FFF ) && ( (bits64) ( a.low<<1 ) == 0 );
305:
306: }
307:
308: /*----------------------------------------------------------------------------
309: | Returns 1 if the extended double-precision floating-point value `a' is
310: | negative; otherwise returns 0.
311: *----------------------------------------------------------------------------*/
312:
313: flag floatx80_is_negative( floatx80 a )
314: {
315:
316: return ( ( a.high & 0x8000 ) == 0x8000 );
317:
318: }
319:
320: /*----------------------------------------------------------------------------
321: | Returns 1 if the extended double-precision floating-point value `a' is
322: | denormal; otherwise returns 0.
323: *----------------------------------------------------------------------------*/
324:
325: flag floatx80_is_denormal( floatx80 a )
326: {
327:
328: return
329: ( ( a.high & 0x7FFF ) == 0 )
330: && ( (bits64) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x0000000000000000 ) )
331: && (bits64) ( a.low<<1 );
332:
333: }
334:
335: /*----------------------------------------------------------------------------
336: | Returns 1 if the extended double-precision floating-point value `a' is
337: | unnormal; otherwise returns 0.
338: *----------------------------------------------------------------------------*/
339:
340: flag floatx80_is_unnormal( floatx80 a )
341: {
342:
343: return
344: ( ( a.high & 0x7FFF ) > 0 )
345: && ( ( a.high & 0x7FFF ) < 0x7FFF)
346: && ( (bits64) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x0000000000000000 ) );
347:
348: }
349:
350: /*----------------------------------------------------------------------------
351: | Returns 1 if the extended double-precision floating-point value `a' is
352: | normal; otherwise returns 0.
353: *----------------------------------------------------------------------------*/
354:
355: flag floatx80_is_normal( floatx80 a )
356: {
357:
358: return
359: ( ( a.high & 0x7FFF ) < 0x7FFF )
360: && ( (bits64) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x8000000000000000 ) );
361:
362: }
363:
364: #endif // End of addition for Previous
365:
366: /*----------------------------------------------------------------------------
367: | Returns the result of converting the extended double-precision floating-
368: | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
369: | invalid exception is raised.
370: *----------------------------------------------------------------------------*/
371:
372: static commonNaNT floatx80ToCommonNaN( floatx80 a )
373: {
374: commonNaNT z;
375:
376: if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_signaling );
377: z.sign = a.high>>15;
378: z.low = 0;
379: z.high = a.low<<1;
380: return z;
381:
382: }
383:
384: /*----------------------------------------------------------------------------
385: | Returns the result of converting the canonical NaN `a' to the extended
386: | double-precision floating-point format.
387: *----------------------------------------------------------------------------*/
388:
389: static floatx80 commonNaNToFloatx80( commonNaNT a )
390: {
391: floatx80 z;
392: #ifdef SOFTFLOAT_68K
393: z.low = LIT64( 0x4000000000000000 ) | ( a.high>>1 );
394: #else
395: z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
396: #endif
397: z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
398: return z;
399:
400: }
401:
402: /*----------------------------------------------------------------------------
403: | Takes two extended double-precision floating-point values `a' and `b', one
404: | of which is a NaN, and returns the appropriate NaN result. If either `a' or
405: | `b' is a signaling NaN, the invalid exception is raised.
406: *----------------------------------------------------------------------------*/
407:
408: floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
409: {
410: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
411:
412: aIsNaN = floatx80_is_nan( a );
413: aIsSignalingNaN = floatx80_is_signaling_nan( a );
414: bIsNaN = floatx80_is_nan( b );
415: bIsSignalingNaN = floatx80_is_signaling_nan( b );
416: #ifdef SOFTFLOAT_68K
417: a.low |= LIT64( 0x4000000000000000 );
418: b.low |= LIT64( 0x4000000000000000 );
419: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling );
420: return aIsNaN ? a : b;
421: #else
422: a.low |= LIT64( 0xC000000000000000 );
423: b.low |= LIT64( 0xC000000000000000 );
424: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling );
425: if ( aIsNaN ) {
426: return ( aIsSignalingNaN & bIsNaN ) ? b : a;
427: }
428: else {
429: return b;
430: }
431: #endif
432:
433: }
434:
435: #ifdef SOFTFLOAT_68K
436: /*----------------------------------------------------------------------------
437: | Takes extended double-precision floating-point NaN `a' and returns the
438: | appropriate NaN result. If `a' is a signaling NaN, the invalid exception
439: | is raised.
440: *----------------------------------------------------------------------------*/
441:
442: floatx80 propagateFloatx80NaNOneArg(floatx80 a)
443: {
444: if ( floatx80_is_signaling_nan( a ) )
445: float_raise( float_flag_signaling );
446:
447: a.low |= LIT64( 0x4000000000000000 );
448:
449: return a;
450: }
451: #endif
452:
453: #define EXP_BIAS 0x3FFF
454:
455: /*----------------------------------------------------------------------------
456: | Returns the fraction bits of the extended double-precision floating-point
457: | value `a'.
458: *----------------------------------------------------------------------------*/
459:
460: bits64 extractFloatx80Frac( floatx80 a )
461: {
462:
463: return a.low;
464:
465: }
466:
467: /*----------------------------------------------------------------------------
468: | Returns the exponent bits of the extended double-precision floating-point
469: | value `a'.
470: *----------------------------------------------------------------------------*/
471:
472: int32 extractFloatx80Exp( floatx80 a )
473: {
474:
475: return a.high & 0x7FFF;
476:
477: }
478:
479: /*----------------------------------------------------------------------------
480: | Returns the sign bit of the extended double-precision floating-point value
481: | `a'.
482: *----------------------------------------------------------------------------*/
483:
484: flag extractFloatx80Sign( floatx80 a )
485: {
486:
487: return a.high>>15;
488:
489: }
490:
491: #endif
492:
493: #ifdef FLOAT128
494:
495: /*----------------------------------------------------------------------------
496: | Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
497: | otherwise returns 0.
498: *----------------------------------------------------------------------------*/
499:
500: flag float128_is_nan( float128 a )
501: {
502:
503: return
504: ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
505: && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
506:
507: }
508:
509: /*----------------------------------------------------------------------------
510: | Returns 1 if the quadruple-precision floating-point value `a' is a
511: | signaling NaN; otherwise returns 0.
512: *----------------------------------------------------------------------------*/
513:
514: flag float128_is_signaling_nan( float128 a )
515: {
516:
517: return
518: ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
519: && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
520:
521: }
522:
523: /*----------------------------------------------------------------------------
524: | Returns the result of converting the quadruple-precision floating-point NaN
525: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
526: | exception is raised.
527: *----------------------------------------------------------------------------*/
528:
529: static commonNaNT float128ToCommonNaN( float128 a )
530: {
531: commonNaNT z;
532:
533: if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_signaling );
534: z.sign = a.high>>63;
535: shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
536: return z;
537:
538: }
539:
540: /*----------------------------------------------------------------------------
541: | Returns the result of converting the canonical NaN `a' to the quadruple-
542: | precision floating-point format.
543: *----------------------------------------------------------------------------*/
544:
545: static float128 commonNaNToFloat128( commonNaNT a )
546: {
547: float128 z;
548:
549: shift128Right( a.high, a.low, 16, &z.high, &z.low );
550: z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
551: return z;
552:
553: }
554:
555: /*----------------------------------------------------------------------------
556: | Takes two quadruple-precision floating-point values `a' and `b', one of
557: | which is a NaN, and returns the appropriate NaN result. If either `a' or
558: | `b' is a signaling NaN, the invalid exception is raised.
559: *----------------------------------------------------------------------------*/
560:
561: static float128 propagateFloat128NaN( float128 a, float128 b )
562: {
563: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
564:
565: aIsNaN = float128_is_nan( a );
566: aIsSignalingNaN = float128_is_signaling_nan( a );
567: bIsNaN = float128_is_nan( b );
568: bIsSignalingNaN = float128_is_signaling_nan( b );
569: a.high |= LIT64( 0x0000800000000000 );
570: b.high |= LIT64( 0x0000800000000000 );
571: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling );
572: if ( aIsNaN ) {
573: return ( aIsSignalingNaN & bIsNaN ) ? b : a;
574: }
575: else {
576: return b;
577: }
578:
579: }
580:
581: #endif
582:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.