xref: /netbsd-src/regress/lib/libc/ieeefp/testfloat/include/softfloat-specialize (revision 5e4c038a45edbc7d63b7c2daa76e29f88b64a4e3)
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
44This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
45Arithmetic Package, Release 2a.
46
47Written by John R. Hauser.  This work was made possible in part by the
48International Computer Science Institute, located at Suite 600, 1947 Center
49Street, Berkeley, California 94704.  Funding was partially provided by the
50National Science Foundation under grant MIP-9311980.  The original version
51of this code was written as part of a project to build a fixed-point vector
52processor in collaboration with the University of California at Berkeley,
53overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
54is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
55arithmetic/SoftFloat.html'.
56
57THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
58has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
59TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
60PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
61AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
62
63Derivative works are acceptable, even for commercial purposes, so long as
64(1) they include prominent notice that the work is derivative, and (2) they
65include prominent notice akin to these four paragraphs for those parts of
66this code that are retained.
67
68===============================================================================
69*/
70
71/*
72-------------------------------------------------------------------------------
73Underflow tininess-detection mode, statically initialized to default value.
74-------------------------------------------------------------------------------
75*/
76int float_detect_tininess = float_tininess_after_rounding;
77
78/*
79-------------------------------------------------------------------------------
80Raises the exceptions specified by `flags'.  Floating-point traps can be
81defined here if desired.  It is currently not possible for such a trap
82to substitute a result value.  If traps are not implemented, this routine
83should be simply `float_exception_flags |= flags;'.
84-------------------------------------------------------------------------------
85*/
86void float_raise( int flags )
87{
88
89    float_exception_flags |= flags;
90
91}
92
93/*
94-------------------------------------------------------------------------------
95Internal canonical NaN format.
96-------------------------------------------------------------------------------
97*/
98typedef struct {
99    flag sign;
100    bits64 high, low;
101} commonNaNT;
102
103/*
104-------------------------------------------------------------------------------
105The pattern for a default generated single-precision NaN.
106-------------------------------------------------------------------------------
107*/
108#define float32_default_nan 0xFFC00000
109
110/*
111-------------------------------------------------------------------------------
112Returns 1 if the single-precision floating-point value `a' is a NaN;
113otherwise returns 0.
114-------------------------------------------------------------------------------
115*/
116static flag float32_is_nan( float32 a )
117{
118
119    return ( 0xFF000000 < (bits32) ( a<<1 ) );
120
121}
122
123/*
124-------------------------------------------------------------------------------
125Returns 1 if the single-precision floating-point value `a' is a signaling
126NaN; otherwise returns 0.
127-------------------------------------------------------------------------------
128*/
129flag float32_is_signaling_nan( float32 a )
130{
131
132    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
133
134}
135
136/*
137-------------------------------------------------------------------------------
138Returns 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
140exception is raised.
141-------------------------------------------------------------------------------
142*/
143static 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-------------------------------------------------------------------------------
157Returns the result of converting the canonical NaN `a' to the single-
158precision floating-point format.
159-------------------------------------------------------------------------------
160*/
161static float32 commonNaNToFloat32( commonNaNT a )
162{
163
164    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
165
166}
167
168/*
169-------------------------------------------------------------------------------
170Takes two single-precision floating-point values `a' and `b', one of which
171is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
172signaling NaN, the invalid exception is raised.
173-------------------------------------------------------------------------------
174*/
175static 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-------------------------------------------------------------------------------
205The pattern for a default generated double-precision NaN.
206-------------------------------------------------------------------------------
207*/
208#define float64_default_nan LIT64( 0xFFF8000000000000 )
209
210/*
211-------------------------------------------------------------------------------
212Returns 1 if the double-precision floating-point value `a' is a NaN;
213otherwise returns 0.
214-------------------------------------------------------------------------------
215*/
216static flag float64_is_nan( float64 a )
217{
218
219    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
220
221}
222
223/*
224-------------------------------------------------------------------------------
225Returns 1 if the double-precision floating-point value `a' is a signaling
226NaN; otherwise returns 0.
227-------------------------------------------------------------------------------
228*/
229flag float64_is_signaling_nan( float64 a )
230{
231
232    return
233           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
234        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
235
236}
237
238/*
239-------------------------------------------------------------------------------
240Returns 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
242exception is raised.
243-------------------------------------------------------------------------------
244*/
245static 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-------------------------------------------------------------------------------
259Returns the result of converting the canonical NaN `a' to the double-
260precision floating-point format.
261-------------------------------------------------------------------------------
262*/
263static 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-------------------------------------------------------------------------------
275Takes two double-precision floating-point values `a' and `b', one of which
276is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
277signaling NaN, the invalid exception is raised.
278-------------------------------------------------------------------------------
279*/
280static 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-------------------------------------------------------------------------------
312The pattern for a default generated extended double-precision NaN.  The
313`high' and `low' values hold the most- and least-significant bits,
314respectively.
315-------------------------------------------------------------------------------
316*/
317#define floatx80_default_nan_high 0xFFFF
318#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
319
320/*
321-------------------------------------------------------------------------------
322Returns 1 if the extended double-precision floating-point value `a' is a
323NaN; otherwise returns 0.
324-------------------------------------------------------------------------------
325*/
326static flag floatx80_is_nan( floatx80 a )
327{
328
329    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
330
331}
332
333/*
334-------------------------------------------------------------------------------
335Returns 1 if the extended double-precision floating-point value `a' is a
336signaling NaN; otherwise returns 0.
337-------------------------------------------------------------------------------
338*/
339flag 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-------------------------------------------------------------------------------
353Returns the result of converting the extended double-precision floating-
354point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
355invalid exception is raised.
356-------------------------------------------------------------------------------
357*/
358static 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-------------------------------------------------------------------------------
372Returns the result of converting the canonical NaN `a' to the extended
373double-precision floating-point format.
374-------------------------------------------------------------------------------
375*/
376static 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-------------------------------------------------------------------------------
388Takes two extended double-precision floating-point values `a' and `b', one
389of 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*/
393static 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-------------------------------------------------------------------------------
427The 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-------------------------------------------------------------------------------
436Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
437otherwise returns 0.
438-------------------------------------------------------------------------------
439*/
440flag 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-------------------------------------------------------------------------------
451Returns 1 if the quadruple-precision floating-point value `a' is a
452signaling NaN; otherwise returns 0.
453-------------------------------------------------------------------------------
454*/
455flag 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-------------------------------------------------------------------------------
466Returns 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
468exception is raised.
469-------------------------------------------------------------------------------
470*/
471static 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-------------------------------------------------------------------------------
484Returns the result of converting the canonical NaN `a' to the quadruple-
485precision floating-point format.
486-------------------------------------------------------------------------------
487*/
488static 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-------------------------------------------------------------------------------
500Takes two quadruple-precision floating-point values `a' and `b', one of
501which 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*/
505static 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