Annotation of sys/lib/libkern/softfloat-specialize.h, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: softfloat-specialize.h,v 1.1 2002/04/28 20:55:14 pvalchev Exp $ */
2: /* $NetBSD: softfloat-specialize.h,v 1.1 2001/04/26 03:10:47 ross Exp $ */
3:
4: /* This is a derivative work. */
5:
6: /*-
7: * Copyright (c) 2001 The NetBSD Foundation, Inc.
8: * All rights reserved.
9: *
10: * This code is derived from software contributed to The NetBSD Foundation
11: * by Ross Harvey.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. All advertising materials mentioning features or use of this software
22: * must display the following acknowledgement:
23: * This product includes software developed by the NetBSD
24: * Foundation, Inc. and its contributors.
25: * 4. Neither the name of The NetBSD Foundation nor the names of its
26: * contributors may be used to endorse or promote products derived
27: * from this software without specific prior written permission.
28: *
29: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39: * POSSIBILITY OF SUCH DAMAGE.
40: */
41:
42: /*
43: ===============================================================================
44:
45: This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
46: Arithmetic Package, Release 2a.
47:
48: Written by John R. Hauser. This work was made possible in part by the
49: International Computer Science Institute, located at Suite 600, 1947 Center
50: Street, Berkeley, California 94704. Funding was partially provided by the
51: National Science Foundation under grant MIP-9311980. The original version
52: of this code was written as part of a project to build a fixed-point vector
53: processor in collaboration with the University of California at Berkeley,
54: overseen by Profs. Nelson Morgan and John Wawrzynek. More information
55: is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
56: arithmetic/SoftFloat.html'.
57:
58: THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable
59: effort has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT
60: WILL AT TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS
61: RESTRICTED TO PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL
62: RESPONSIBILITY FOR ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM
63: THEIR OWN USE OF THE SOFTWARE, AND WHO ALSO EFFECTIVELY INDEMNIFY
64: (possibly via similar legal warning) JOHN HAUSER AND THE INTERNATIONAL
65: COMPUTER SCIENCE INSTITUTE AGAINST ALL LOSSES, COSTS, OR OTHER PROBLEMS
66: ARISING FROM THE USE OF THE SOFTWARE BY THEIR CUSTOMERS AND CLIENTS.
67:
68: Derivative works are acceptable, even for commercial purposes, so long as
69: (1) they include prominent notice that the work is derivative, and (2) they
70: include prominent notice akin to these four paragraphs for those parts of
71: this code that are retained.
72:
73: ===============================================================================
74: */
75:
76: /*
77: -------------------------------------------------------------------------------
78: Underflow tininess-detection mode, statically initialized to default value.
79: -------------------------------------------------------------------------------
80: */
81:
82: #ifndef NO_IEEE
83:
84: /* [ MP safe, does not change dynamically ] */
85: int float_detect_tininess = float_tininess_after_rounding;
86:
87: /*
88: -------------------------------------------------------------------------------
89: Internal canonical NaN format.
90: -------------------------------------------------------------------------------
91: */
92: typedef struct {
93: flag sign;
94: bits64 high, low;
95: } commonNaNT;
96:
97: /*
98: -------------------------------------------------------------------------------
99: The pattern for a default generated single-precision NaN.
100: -------------------------------------------------------------------------------
101: */
102: #define float32_default_nan 0xFFC00000
103:
104: /*
105: -------------------------------------------------------------------------------
106: Returns 1 if the single-precision floating-point value `a' is a NaN;
107: otherwise returns 0.
108: -------------------------------------------------------------------------------
109: */
110: static flag float32_is_nan( float32 a )
111: {
112:
113: return ( 0xFF000000 < (bits32) ( a<<1 ) );
114:
115: }
116:
117: /*
118: -------------------------------------------------------------------------------
119: Returns 1 if the single-precision floating-point value `a' is a signaling
120: NaN; otherwise returns 0.
121: -------------------------------------------------------------------------------
122: */
123: flag float32_is_signaling_nan( float32 a )
124: {
125:
126: return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
127:
128: }
129:
130: /*
131: -------------------------------------------------------------------------------
132: Returns the result of converting the single-precision floating-point NaN
133: `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
134: exception is raised.
135: -------------------------------------------------------------------------------
136: */
137: static commonNaNT float32ToCommonNaN( float32 a )
138: {
139: commonNaNT z;
140:
141: if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
142: z.sign = a>>31;
143: z.low = 0;
144: z.high = ( (bits64) a )<<41;
145: return z;
146:
147: }
148:
149: /*
150: -------------------------------------------------------------------------------
151: Returns the result of converting the canonical NaN `a' to the single-
152: precision floating-point format.
153: -------------------------------------------------------------------------------
154: */
155: static float32 commonNaNToFloat32( commonNaNT a )
156: {
157:
158: return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
159:
160: }
161:
162: /*
163: -------------------------------------------------------------------------------
164: Takes two single-precision floating-point values `a' and `b', one of which
165: is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
166: signaling NaN, the invalid exception is raised.
167: -------------------------------------------------------------------------------
168: */
169: static float32 propagateFloat32NaN( float32 a, float32 b )
170: {
171: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
172:
173: aIsNaN = float32_is_nan( a );
174: aIsSignalingNaN = float32_is_signaling_nan( a );
175: bIsNaN = float32_is_nan( b );
176: bIsSignalingNaN = float32_is_signaling_nan( b );
177: a |= 0x00400000;
178: b |= 0x00400000;
179: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
180: if ( aIsSignalingNaN ) {
181: if ( bIsSignalingNaN ) goto returnLargerSignificand;
182: return bIsNaN ? b : a;
183: }
184: else if ( aIsNaN ) {
185: if ( bIsSignalingNaN | ! bIsNaN ) return a;
186: returnLargerSignificand:
187: if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
188: if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
189: return ( a < b ) ? a : b;
190: }
191: else {
192: return b;
193: }
194:
195: }
196:
197:
198: /*
199: -------------------------------------------------------------------------------
200: Returns the result of converting the double-precision floating-point NaN
201: `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
202: exception is raised.
203: -------------------------------------------------------------------------------
204: */
205: static commonNaNT float64ToCommonNaN( float64 a )
206: {
207: commonNaNT z;
208:
209: if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
210: z.sign = a>>63;
211: z.low = 0;
212: z.high = a<<12;
213: return z;
214:
215: }
216:
217: /*
218: -------------------------------------------------------------------------------
219: Returns the result of converting the canonical NaN `a' to the double-
220: precision floating-point format.
221: -------------------------------------------------------------------------------
222: */
223: static float64 commonNaNToFloat64( commonNaNT a )
224: {
225:
226: return
227: ( ( (bits64) a.sign )<<63 )
228: | LIT64( 0x7FF8000000000000 )
229: | ( a.high>>12 );
230:
231: }
232:
233: /*
234: -------------------------------------------------------------------------------
235: Takes two double-precision floating-point values `a' and `b', one of which
236: is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
237: signaling NaN, the invalid exception is raised.
238: -------------------------------------------------------------------------------
239: */
240: static float64 propagateFloat64NaN( float64 a, float64 b )
241: {
242: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
243:
244: aIsNaN = float64_is_nan( a );
245: aIsSignalingNaN = float64_is_signaling_nan( a );
246: bIsNaN = float64_is_nan( b );
247: bIsSignalingNaN = float64_is_signaling_nan( b );
248: a |= LIT64( 0x0008000000000000 );
249: b |= LIT64( 0x0008000000000000 );
250: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
251: if ( aIsSignalingNaN ) {
252: if ( bIsSignalingNaN ) goto returnLargerSignificand;
253: return bIsNaN ? b : a;
254: }
255: else if ( aIsNaN ) {
256: if ( bIsSignalingNaN | ! bIsNaN ) return a;
257: returnLargerSignificand:
258: if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
259: if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
260: return ( a < b ) ? a : b;
261: }
262: else {
263: return b;
264: }
265:
266: }
267:
268: #ifdef FLOATX80
269:
270: /*
271: -------------------------------------------------------------------------------
272: The pattern for a default generated extended double-precision NaN. The
273: `high' and `low' values hold the most- and least-significant bits,
274: respectively.
275: -------------------------------------------------------------------------------
276: */
277: #define floatx80_default_nan_high 0xFFFF
278: #define floatx80_default_nan_low LIT64( 0xC000000000000000 )
279:
280: /*
281: -------------------------------------------------------------------------------
282: Returns 1 if the extended double-precision floating-point value `a' is a
283: NaN; otherwise returns 0.
284: -------------------------------------------------------------------------------
285: */
286: static flag floatx80_is_nan( floatx80 a )
287: {
288:
289: return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
290:
291: }
292:
293: /*
294: -------------------------------------------------------------------------------
295: Returns 1 if the extended double-precision floating-point value `a' is a
296: signaling NaN; otherwise returns 0.
297: -------------------------------------------------------------------------------
298: */
299: flag floatx80_is_signaling_nan( floatx80 a )
300: {
301: bits64 aLow;
302:
303: aLow = a.low & ~ LIT64( 0x4000000000000000 );
304: return
305: ( ( a.high & 0x7FFF ) == 0x7FFF )
306: && (bits64) ( aLow<<1 )
307: && ( a.low == aLow );
308:
309: }
310:
311: /*
312: -------------------------------------------------------------------------------
313: Returns the result of converting the extended double-precision floating-
314: point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
315: invalid exception is raised.
316: -------------------------------------------------------------------------------
317: */
318: static commonNaNT floatx80ToCommonNaN( floatx80 a )
319: {
320: commonNaNT z;
321:
322: if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
323: z.sign = a.high>>15;
324: z.low = 0;
325: z.high = a.low<<1;
326: return z;
327:
328: }
329:
330: /*
331: -------------------------------------------------------------------------------
332: Returns the result of converting the canonical NaN `a' to the extended
333: double-precision floating-point format.
334: -------------------------------------------------------------------------------
335: */
336: static floatx80 commonNaNToFloatx80( commonNaNT a )
337: {
338: floatx80 z;
339:
340: z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
341: z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
342: return z;
343:
344: }
345:
346: /*
347: -------------------------------------------------------------------------------
348: Takes two extended double-precision floating-point values `a' and `b', one
349: of which is a NaN, and returns the appropriate NaN result. If either `a' or
350: `b' is a signaling NaN, the invalid exception is raised.
351: -------------------------------------------------------------------------------
352: */
353: static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
354: {
355: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
356:
357: aIsNaN = floatx80_is_nan( a );
358: aIsSignalingNaN = floatx80_is_signaling_nan( a );
359: bIsNaN = floatx80_is_nan( b );
360: bIsSignalingNaN = floatx80_is_signaling_nan( b );
361: a.low |= LIT64( 0xC000000000000000 );
362: b.low |= LIT64( 0xC000000000000000 );
363: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
364: if ( aIsSignalingNaN ) {
365: if ( bIsSignalingNaN ) goto returnLargerSignificand;
366: return bIsNaN ? b : a;
367: }
368: else if ( aIsNaN ) {
369: if ( bIsSignalingNaN | ! bIsNaN ) return a;
370: returnLargerSignificand:
371: if ( a.low < b.low ) return b;
372: if ( b.low < a.low ) return a;
373: return ( a.high < b.high ) ? a : b;
374: }
375: else {
376: return b;
377: }
378:
379: }
380:
381: #endif
382:
383: #ifdef FLOAT128
384:
385: /*
386: -------------------------------------------------------------------------------
387: The pattern for a default generated quadruple-precision NaN. The `high' and
388: `low' values hold the most- and least-significant bits, respectively.
389: -------------------------------------------------------------------------------
390: */
391: #define float128_default_nan_high LIT64( 0xFFFF800000000000 )
392: #define float128_default_nan_low LIT64( 0x0000000000000000 )
393:
394: /*
395: -------------------------------------------------------------------------------
396: Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
397: otherwise returns 0.
398: -------------------------------------------------------------------------------
399: */
400: flag float128_is_nan( float128 a )
401: {
402:
403: return
404: ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
405: && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
406:
407: }
408:
409: /*
410: -------------------------------------------------------------------------------
411: Returns 1 if the quadruple-precision floating-point value `a' is a
412: signaling NaN; otherwise returns 0.
413: -------------------------------------------------------------------------------
414: */
415: flag float128_is_signaling_nan( float128 a )
416: {
417:
418: return
419: ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
420: && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
421:
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 )
432: {
433: commonNaNT z;
434:
435: if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
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: -------------------------------------------------------------------------------
444: Returns the result of converting the canonical NaN `a' to the quadruple-
445: precision floating-point format.
446: -------------------------------------------------------------------------------
447: */
448: static float128 commonNaNToFloat128( commonNaNT a )
449: {
450: float128 z;
451:
452: shift128Right( a.high, a.low, 16, &z.high, &z.low );
453: z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
454: return z;
455:
456: }
457:
458: /*
459: -------------------------------------------------------------------------------
460: Takes two quadruple-precision floating-point values `a' and `b', one of
461: which is a NaN, and returns the appropriate NaN result. If either `a' or
462: `b' is a signaling NaN, the invalid exception is raised.
463: -------------------------------------------------------------------------------
464: */
465: static float128 propagateFloat128NaN( float128 a, float128 b )
466: {
467: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
468:
469: aIsNaN = float128_is_nan( a );
470: aIsSignalingNaN = float128_is_signaling_nan( a );
471: bIsNaN = float128_is_nan( b );
472: bIsSignalingNaN = float128_is_signaling_nan( b );
473: a.high |= LIT64( 0x0000800000000000 );
474: b.high |= LIT64( 0x0000800000000000 );
475: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
476: if ( aIsSignalingNaN ) {
477: if ( bIsSignalingNaN ) goto returnLargerSignificand;
478: return bIsNaN ? b : a;
479: }
480: else if ( aIsNaN ) {
481: if ( bIsSignalingNaN | ! bIsNaN ) return a;
482: returnLargerSignificand:
483: if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
484: if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
485: return ( a.high < b.high ) ? a : b;
486: }
487: else {
488: return b;
489: }
490:
491: }
492:
493: #endif
494:
495: #endif /* !NO_IEEE */
CVSweb