xref: /openbsd-src/sys/lib/libkern/softfloat-specialize.h (revision daf88648c0e349d5c02e1504293082072c981640)
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 */
496