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 */