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