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