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