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