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