xref: /netbsd-src/sys/lib/libkern/softfloat-specialize.h (revision e450f2e45d724b0ec51c4cff35a6f0592db866ac)
1 /* $NetBSD: softfloat-specialize.h,v 1.3 2020/09/02 03:41:56 thorpej 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 This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point
37 Arithmetic Package, Release 2c, by John R. Hauser.
38 
39 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
40 been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
41 RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
42 AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
43 PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
44 THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
45 INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
46 (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
47 PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
48 INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
49 SOFTWARE.
50 
51 Derivative works require also that (1) the source code for the derivative work
52 includes prominent notice that the work is derivative, and (2) the source code
53 includes prominent notice of these three paragraphs for those parts of this
54 code that are retained.
55 
56 =============================================================================*/
57 
58 /*----------------------------------------------------------------------------
59 | Underflow tininess-detection mode, statically initialized to default value.
60 | (The declaration in `softfloat.h' must match the `int8' type here.)
61 *----------------------------------------------------------------------------*/
62 /* [ MP safe, does not change dynamically ] */
63 int float_detect_tininess = float_tininess_after_rounding;
64 
65 /*----------------------------------------------------------------------------
66 | Internal canonical NaN format.
67 *----------------------------------------------------------------------------*/
68 typedef struct {
69     flag sign;
70     bits64 high, low;
71 } commonNaNT;
72 
73 /*----------------------------------------------------------------------------
74 | The pattern for a default generated single-precision NaN.
75 *----------------------------------------------------------------------------*/
76 #define float32_default_nan 0xFFC00000
77 
78 /*----------------------------------------------------------------------------
79 | Returns 1 if the single-precision floating-point value `a' is a NaN;
80 | otherwise returns 0.
81 *----------------------------------------------------------------------------*/
82 
float32_is_nan(float32 a)83 static flag float32_is_nan( float32 a )
84 {
85 
86     return ( 0xFF000000 < (bits32) ( a<<1 ) );
87 
88 }
89 
90 /*----------------------------------------------------------------------------
91 | Returns 1 if the single-precision floating-point value `a' is a signaling
92 | NaN; otherwise returns 0.
93 *----------------------------------------------------------------------------*/
94 
float32_is_signaling_nan(float32 a)95 flag float32_is_signaling_nan( float32 a )
96 {
97 
98     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
99 
100 }
101 
102 /*----------------------------------------------------------------------------
103 | Returns the result of converting the single-precision floating-point NaN
104 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
105 | exception is raised.
106 *----------------------------------------------------------------------------*/
107 
float32ToCommonNaN(float32 a)108 static commonNaNT float32ToCommonNaN( float32 a )
109 {
110     commonNaNT z;
111 
112     if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
113     z.sign = a>>31;
114     z.low = 0;
115     z.high = ( (bits64) a )<<41;
116     return z;
117 
118 }
119 
120 /*----------------------------------------------------------------------------
121 | Returns the result of converting the canonical NaN `a' to the single-
122 | precision floating-point format.
123 *----------------------------------------------------------------------------*/
124 
commonNaNToFloat32(commonNaNT a)125 static float32 commonNaNToFloat32( commonNaNT a )
126 {
127 
128     return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
129 
130 }
131 
132 /*----------------------------------------------------------------------------
133 | Takes two single-precision floating-point values `a' and `b', one of which
134 | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
135 | signaling NaN, the invalid exception is raised.
136 *----------------------------------------------------------------------------*/
137 
propagateFloat32NaN(float32 a,float32 b)138 static float32 propagateFloat32NaN( float32 a, float32 b )
139 {
140     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
141 
142     aIsNaN = float32_is_nan( a );
143     aIsSignalingNaN = float32_is_signaling_nan( a );
144     bIsNaN = float32_is_nan( b );
145     bIsSignalingNaN = float32_is_signaling_nan( b );
146     a |= 0x00400000;
147     b |= 0x00400000;
148     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
149     if ( aIsSignalingNaN ) {
150         if ( bIsSignalingNaN ) goto returnLargerSignificand;
151         return bIsNaN ? b : a;
152     }
153     else if ( aIsNaN ) {
154         if ( bIsSignalingNaN | ! bIsNaN ) return a;
155  returnLargerSignificand:
156         if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
157         if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
158         return ( a < b ) ? a : b;
159     }
160     else {
161         return b;
162     }
163 
164 }
165 
166 /*
167  * float64_default_nan, float64_is_nan(), float64_is_signaling_nan()
168  * have moved to softfloat.h.
169  */
170 
171 /*----------------------------------------------------------------------------
172 | Returns the result of converting the double-precision floating-point NaN
173 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
174 | exception is raised.
175 *----------------------------------------------------------------------------*/
176 
float64ToCommonNaN(float64 a)177 static commonNaNT float64ToCommonNaN( float64 a )
178 {
179     commonNaNT z;
180 
181     if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
182     z.sign = a>>63;
183     z.low = 0;
184     z.high = a<<12;
185     return z;
186 
187 }
188 
189 /*----------------------------------------------------------------------------
190 | Returns the result of converting the canonical NaN `a' to the double-
191 | precision floating-point format.
192 *----------------------------------------------------------------------------*/
193 
commonNaNToFloat64(commonNaNT a)194 static float64 commonNaNToFloat64( commonNaNT a )
195 {
196 
197     return
198           ( ( (bits64) a.sign )<<63 )
199         | LIT64( 0x7FF8000000000000 )
200         | ( a.high>>12 );
201 
202 }
203 
204 /*----------------------------------------------------------------------------
205 | Takes two double-precision floating-point values `a' and `b', one of which
206 | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
207 | signaling NaN, the invalid exception is raised.
208 *----------------------------------------------------------------------------*/
209 
propagateFloat64NaN(float64 a,float64 b)210 static float64 propagateFloat64NaN( float64 a, float64 b )
211 {
212     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
213 
214     aIsNaN = float64_is_nan( a );
215     aIsSignalingNaN = float64_is_signaling_nan( a );
216     bIsNaN = float64_is_nan( b );
217     bIsSignalingNaN = float64_is_signaling_nan( b );
218     a |= LIT64( 0x0008000000000000 );
219     b |= LIT64( 0x0008000000000000 );
220     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
221     if ( aIsSignalingNaN ) {
222         if ( bIsSignalingNaN ) goto returnLargerSignificand;
223         return bIsNaN ? b : a;
224     }
225     else if ( aIsNaN ) {
226         if ( bIsSignalingNaN | ! bIsNaN ) return a;
227  returnLargerSignificand:
228         if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
229         if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
230         return ( a < b ) ? a : b;
231     }
232     else {
233         return b;
234     }
235 
236 }
237 
238 #ifdef FLOATX80
239 
240 /*----------------------------------------------------------------------------
241 | The pattern for a default generated double-extended-precision NaN.
242 | The `high' and `low' values hold the most- and least-significant bits,
243 | respectively.
244 *----------------------------------------------------------------------------*/
245 #define floatx80_default_nan_high 0xFFFF
246 #define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
247 
248 /*----------------------------------------------------------------------------
249 | Returns 1 if the double-extended-precision floating-point value `a' is a
250 | NaN; otherwise returns 0.
251 *----------------------------------------------------------------------------*/
252 
floatx80_is_nan(floatx80 a)253 static flag floatx80_is_nan( floatx80 a )
254 {
255 
256     return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
257 
258 }
259 
260 /*----------------------------------------------------------------------------
261 | Returns 1 if the double-extended-precision floating-point value `a' is a
262 | signaling NaN; otherwise returns 0.
263 *----------------------------------------------------------------------------*/
264 
floatx80_is_signaling_nan(floatx80 a)265 flag floatx80_is_signaling_nan( floatx80 a )
266 {
267     bits64 aLow;
268 
269     aLow = a.low & ~ LIT64( 0x4000000000000000 );
270     return
271            ( ( a.high & 0x7FFF ) == 0x7FFF )
272         && (bits64) ( aLow<<1 )
273         && ( a.low == aLow );
274 
275 }
276 
277 /*----------------------------------------------------------------------------
278 | Returns the result of converting the double-extended-precision floating-
279 | point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
280 | invalid exception is raised.
281 *----------------------------------------------------------------------------*/
282 
floatx80ToCommonNaN(floatx80 a)283 static commonNaNT floatx80ToCommonNaN( floatx80 a )
284 {
285     commonNaNT z;
286 
287     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
288     z.sign = a.high>>15;
289     z.low = 0;
290     z.high = a.low<<1;
291     return z;
292 
293 }
294 
295 /*----------------------------------------------------------------------------
296 | Returns the result of converting the canonical NaN `a' to the double-
297 | extended-precision floating-point format.
298 *----------------------------------------------------------------------------*/
299 
commonNaNToFloatx80(commonNaNT a)300 static floatx80 commonNaNToFloatx80( commonNaNT a )
301 {
302     floatx80 z;
303 
304     z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
305     z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
306     return z;
307 
308 }
309 
310 /*----------------------------------------------------------------------------
311 | Takes two double-extended-precision floating-point values `a' and `b', one
312 | of which is a NaN, and returns the appropriate NaN result.  If either `a' or
313 | `b' is a signaling NaN, the invalid exception is raised.
314 *----------------------------------------------------------------------------*/
315 
propagateFloatx80NaN(floatx80 a,floatx80 b)316 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
317 {
318     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
319 
320     aIsNaN = floatx80_is_nan( a );
321     aIsSignalingNaN = floatx80_is_signaling_nan( a );
322     bIsNaN = floatx80_is_nan( b );
323     bIsSignalingNaN = floatx80_is_signaling_nan( b );
324     a.low |= LIT64( 0xC000000000000000 );
325     b.low |= LIT64( 0xC000000000000000 );
326     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
327     if ( aIsSignalingNaN ) {
328         if ( bIsSignalingNaN ) goto returnLargerSignificand;
329         return bIsNaN ? b : a;
330     }
331     else if ( aIsNaN ) {
332         if ( bIsSignalingNaN | ! bIsNaN ) return a;
333  returnLargerSignificand:
334         if ( a.low < b.low ) return b;
335         if ( b.low < a.low ) return a;
336         return ( a.high < b.high ) ? a : b;
337     }
338     else {
339         return b;
340     }
341 
342 }
343 
344 #endif
345 
346 #ifdef FLOAT128
347 
348 /*----------------------------------------------------------------------------
349 | The pattern for a default generated quadruple-precision NaN.  The `high' and
350 | `low' values hold the most- and least-significant bits, respectively.
351 *----------------------------------------------------------------------------*/
352 #define float128_default_nan_high LIT64( 0xFFFF800000000000 )
353 #define float128_default_nan_low  LIT64( 0x0000000000000000 )
354 
355 /*----------------------------------------------------------------------------
356 | Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
357 | otherwise returns 0.
358 *----------------------------------------------------------------------------*/
359 
float128_is_nan(float128 a)360 flag float128_is_nan( float128 a )
361 {
362 
363     return
364            ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
365         && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
366 
367 }
368 
369 /*----------------------------------------------------------------------------
370 | Returns 1 if the quadruple-precision floating-point value `a' is a
371 | signaling NaN; otherwise returns 0.
372 *----------------------------------------------------------------------------*/
373 
float128_is_signaling_nan(float128 a)374 flag float128_is_signaling_nan( float128 a )
375 {
376 
377     return
378            ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
379         && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
380 
381 }
382 
383 /*----------------------------------------------------------------------------
384 | Returns the result of converting the quadruple-precision floating-point NaN
385 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
386 | exception is raised.
387 *----------------------------------------------------------------------------*/
388 
float128ToCommonNaN(float128 a)389 static commonNaNT float128ToCommonNaN( float128 a )
390 {
391     commonNaNT z;
392 
393     if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
394     z.sign = a.high>>63;
395     shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
396     return z;
397 
398 }
399 
400 /*----------------------------------------------------------------------------
401 | Returns the result of converting the canonical NaN `a' to the quadruple-
402 | precision floating-point format.
403 *----------------------------------------------------------------------------*/
404 
commonNaNToFloat128(commonNaNT a)405 static float128 commonNaNToFloat128( commonNaNT a )
406 {
407     float128 z;
408 
409     shift128Right( a.high, a.low, 16, &z.high, &z.low );
410     z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
411     return z;
412 
413 }
414 
415 /*----------------------------------------------------------------------------
416 | Takes two quadruple-precision floating-point values `a' and `b', one of
417 | which is a NaN, and returns the appropriate NaN result.  If either `a' or
418 | `b' is a signaling NaN, the invalid exception is raised.
419 *----------------------------------------------------------------------------*/
420 
propagateFloat128NaN(float128 a,float128 b)421 static float128 propagateFloat128NaN( float128 a, float128 b )
422 {
423     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
424 
425     aIsNaN = float128_is_nan( a );
426     aIsSignalingNaN = float128_is_signaling_nan( a );
427     bIsNaN = float128_is_nan( b );
428     bIsSignalingNaN = float128_is_signaling_nan( b );
429     a.high |= LIT64( 0x0000800000000000 );
430     b.high |= LIT64( 0x0000800000000000 );
431     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
432     if ( aIsSignalingNaN ) {
433         if ( bIsSignalingNaN ) goto returnLargerSignificand;
434         return bIsNaN ? b : a;
435     }
436     else if ( aIsNaN ) {
437         if ( bIsSignalingNaN | ! bIsNaN ) return a;
438  returnLargerSignificand:
439         if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
440         if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
441         return ( a.high < b.high ) ? a : b;
442     }
443     else {
444         return b;
445     }
446 
447 }
448 
449 #endif
450 
451