softfloat-specialize revision 206492
1264377Sdes/*	$NetBSD: softfloat-specialize,v 1.3 2002/05/12 13:12:45 bjh21 Exp $	*/
2180744Sdes/* $FreeBSD: head/lib/libc/softfloat/softfloat-specialize 206492 2010-04-11 21:22:02Z marius $ */
3180744Sdes
4180744Sdes/* This is a derivative work. */
5180744Sdes
6180744Sdes/*
7180744Sdes===============================================================================
8180744Sdes
9180744SdesThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point
10180744SdesArithmetic Package, Release 2a.
11180744Sdes
12180744SdesWritten by John R. Hauser.  This work was made possible in part by the
13180744SdesInternational Computer Science Institute, located at Suite 600, 1947 Center
14180744SdesStreet, Berkeley, California 94704.  Funding was partially provided by the
15180744SdesNational Science Foundation under grant MIP-9311980.  The original version
16180744Sdesof this code was written as part of a project to build a fixed-point vector
17180744Sdesprocessor in collaboration with the University of California at Berkeley,
18180744Sdesoverseen by Profs. Nelson Morgan and John Wawrzynek.  More information
19180744Sdesis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
20180746Sdesarithmetic/SoftFloat.html'.
21180744Sdes
22262566SdesTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
23262566Sdeshas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
24180744SdesTIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
25180744SdesPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
26180744SdesAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
27180744Sdes
28262566SdesDerivative works are acceptable, even for commercial purposes, so long as
29180750Sdes(1) they include prominent notice that the work is derivative, and (2) they
30262566Sdesinclude prominent notice akin to these four paragraphs for those parts of
31180744Sdesthis code that are retained.
32180744Sdes
33180744Sdes===============================================================================
34180744Sdes*/
35180744Sdes
36180744Sdes#include <signal.h>
37180744Sdes
38180744Sdes/*
39180744Sdes-------------------------------------------------------------------------------
40180744SdesUnderflow tininess-detection mode, statically initialized to default value.
41180744Sdes(The declaration in `softfloat.h' must match the `int8' type here.)
42180744Sdes-------------------------------------------------------------------------------
43180744Sdes*/
44180744Sdes#ifdef SOFTFLOAT_FOR_GCC
45180744Sdesstatic
46180744Sdes#endif
47180744Sdes#ifdef __sparc64__
48180744Sdesint8 float_detect_tininess = float_tininess_before_rounding;
49180744Sdes#else
50180744Sdesint8 float_detect_tininess = float_tininess_after_rounding;
51180744Sdes#endif
52192595Sdes
53180744Sdes/*
54180744Sdes-------------------------------------------------------------------------------
55180744SdesRaises the exceptions specified by `flags'.  Floating-point traps can be
56180744Sdesdefined here if desired.  It is currently not possible for such a trap to
57192595Sdessubstitute a result value.  If traps are not implemented, this routine
58180744Sdesshould be simply `float_exception_flags |= flags;'.
59180744Sdes-------------------------------------------------------------------------------
60180744Sdes*/
61180744Sdesfp_except float_exception_mask = 0;
62180744Sdesvoid float_raise( fp_except flags )
63180744Sdes{
64180744Sdes
65180744Sdes    float_exception_flags |= flags;
66180744Sdes
67180744Sdes    if ( flags & float_exception_mask ) {
68180744Sdes	raise( SIGFPE );
69180744Sdes    }
70180744Sdes}
71180744Sdes
72180744Sdes/*
73180744Sdes-------------------------------------------------------------------------------
74180744SdesInternal canonical NaN format.
75180744Sdes-------------------------------------------------------------------------------
76180744Sdes*/
77180744Sdestypedef struct {
78180744Sdes    flag sign;
79180744Sdes    bits64 high, low;
80180744Sdes} commonNaNT;
81180744Sdes
82180744Sdes/*
83180744Sdes-------------------------------------------------------------------------------
84180744SdesThe pattern for a default generated single-precision NaN.
85180744Sdes-------------------------------------------------------------------------------
86180744Sdes*/
87180744Sdes#define float32_default_nan 0xFFFFFFFF
88180744Sdes
89180744Sdes/*
90180744Sdes-------------------------------------------------------------------------------
91180744SdesReturns 1 if the single-precision floating-point value `a' is a NaN;
92180744Sdesotherwise returns 0.
93180744Sdes-------------------------------------------------------------------------------
94180744Sdes*/
95180744Sdes#ifdef SOFTFLOAT_FOR_GCC
96180744Sdesstatic
97180744Sdes#endif
98180744Sdesflag float32_is_nan( float32 a )
99180744Sdes{
100180744Sdes
101180744Sdes    return ( 0xFF000000 < (bits32) ( a<<1 ) );
102180744Sdes
103180744Sdes}
104180744Sdes
105180744Sdes/*
106180744Sdes-------------------------------------------------------------------------------
107180744SdesReturns 1 if the single-precision floating-point value `a' is a signaling
108180744SdesNaN; otherwise returns 0.
109180744Sdes-------------------------------------------------------------------------------
110180744Sdes*/
111180744Sdes#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC)
112264377Sdesstatic
113264377Sdes#endif
114264377Sdesflag float32_is_signaling_nan( float32 a )
115180744Sdes{
116180744Sdes
117180744Sdes    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
118180744Sdes
119180744Sdes}
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 ( aIsNaN ) {
172        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
173    }
174    else {
175        return b;
176    }
177
178}
179
180/*
181-------------------------------------------------------------------------------
182The pattern for a default generated double-precision NaN.
183-------------------------------------------------------------------------------
184*/
185#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
186
187/*
188-------------------------------------------------------------------------------
189Returns 1 if the double-precision floating-point value `a' is a NaN;
190otherwise returns 0.
191-------------------------------------------------------------------------------
192*/
193#ifdef SOFTFLOAT_FOR_GCC
194static
195#endif
196flag float64_is_nan( float64 a )
197{
198
199    return ( LIT64( 0xFFE0000000000000 ) <
200	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
201
202}
203
204/*
205-------------------------------------------------------------------------------
206Returns 1 if the double-precision floating-point value `a' is a signaling
207NaN; otherwise returns 0.
208-------------------------------------------------------------------------------
209*/
210#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC)
211static
212#endif
213flag float64_is_signaling_nan( float64 a )
214{
215
216    return
217           ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
218        && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
219
220}
221
222/*
223-------------------------------------------------------------------------------
224Returns the result of converting the double-precision floating-point NaN
225`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
226exception is raised.
227-------------------------------------------------------------------------------
228*/
229static commonNaNT float64ToCommonNaN( float64 a )
230{
231    commonNaNT z;
232
233    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
234    z.sign = FLOAT64_DEMANGLE(a)>>63;
235    z.low = 0;
236    z.high = FLOAT64_DEMANGLE(a)<<12;
237    return z;
238
239}
240
241/*
242-------------------------------------------------------------------------------
243Returns the result of converting the canonical NaN `a' to the double-
244precision floating-point format.
245-------------------------------------------------------------------------------
246*/
247static float64 commonNaNToFloat64( commonNaNT a )
248{
249
250    return FLOAT64_MANGLE(
251	( ( (bits64) a.sign )<<63 )
252        | LIT64( 0x7FF8000000000000 )
253        | ( a.high>>12 ) );
254
255}
256
257/*
258-------------------------------------------------------------------------------
259Takes two double-precision floating-point values `a' and `b', one of which
260is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
261signaling NaN, the invalid exception is raised.
262-------------------------------------------------------------------------------
263*/
264static float64 propagateFloat64NaN( float64 a, float64 b )
265{
266    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
267
268    aIsNaN = float64_is_nan( a );
269    aIsSignalingNaN = float64_is_signaling_nan( a );
270    bIsNaN = float64_is_nan( b );
271    bIsSignalingNaN = float64_is_signaling_nan( b );
272    a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
273    b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
274    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
275    if ( aIsNaN ) {
276        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
277    }
278    else {
279        return b;
280    }
281
282}
283
284#ifdef FLOATX80
285
286/*
287-------------------------------------------------------------------------------
288The pattern for a default generated extended double-precision NaN.  The
289`high' and `low' values hold the most- and least-significant bits,
290respectively.
291-------------------------------------------------------------------------------
292*/
293#define floatx80_default_nan_high 0xFFFF
294#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
295
296/*
297-------------------------------------------------------------------------------
298Returns 1 if the extended double-precision floating-point value `a' is a
299NaN; otherwise returns 0.
300-------------------------------------------------------------------------------
301*/
302flag floatx80_is_nan( floatx80 a )
303{
304
305    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
306
307}
308
309/*
310-------------------------------------------------------------------------------
311Returns 1 if the extended double-precision floating-point value `a' is a
312signaling NaN; otherwise returns 0.
313-------------------------------------------------------------------------------
314*/
315flag floatx80_is_signaling_nan( floatx80 a )
316{
317    bits64 aLow;
318
319    aLow = a.low & ~ LIT64( 0x4000000000000000 );
320    return
321           ( ( a.high & 0x7FFF ) == 0x7FFF )
322        && (bits64) ( aLow<<1 )
323        && ( a.low == aLow );
324
325}
326
327/*
328-------------------------------------------------------------------------------
329Returns the result of converting the extended double-precision floating-
330point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
331invalid exception is raised.
332-------------------------------------------------------------------------------
333*/
334static commonNaNT floatx80ToCommonNaN( floatx80 a )
335{
336    commonNaNT z;
337
338    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
339    z.sign = a.high>>15;
340    z.low = 0;
341    z.high = a.low<<1;
342    return z;
343
344}
345
346/*
347-------------------------------------------------------------------------------
348Returns the result of converting the canonical NaN `a' to the extended
349double-precision floating-point format.
350-------------------------------------------------------------------------------
351*/
352static floatx80 commonNaNToFloatx80( commonNaNT a )
353{
354    floatx80 z;
355
356    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
357    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
358    return z;
359
360}
361
362/*
363-------------------------------------------------------------------------------
364Takes two extended double-precision floating-point values `a' and `b', one
365of which is a NaN, and returns the appropriate NaN result.  If either `a' or
366`b' is a signaling NaN, the invalid exception is raised.
367-------------------------------------------------------------------------------
368*/
369static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
370{
371    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
372
373    aIsNaN = floatx80_is_nan( a );
374    aIsSignalingNaN = floatx80_is_signaling_nan( a );
375    bIsNaN = floatx80_is_nan( b );
376    bIsSignalingNaN = floatx80_is_signaling_nan( b );
377    a.low |= LIT64( 0xC000000000000000 );
378    b.low |= LIT64( 0xC000000000000000 );
379    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
380    if ( aIsNaN ) {
381        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
382    }
383    else {
384        return b;
385    }
386
387}
388
389#endif
390
391#ifdef FLOAT128
392
393/*
394-------------------------------------------------------------------------------
395The pattern for a default generated quadruple-precision NaN.  The `high' and
396`low' values hold the most- and least-significant bits, respectively.
397-------------------------------------------------------------------------------
398*/
399#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
400#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
401
402/*
403-------------------------------------------------------------------------------
404Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
405otherwise returns 0.
406-------------------------------------------------------------------------------
407*/
408flag float128_is_nan( float128 a )
409{
410
411    return
412           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
413        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
414
415}
416
417/*
418-------------------------------------------------------------------------------
419Returns 1 if the quadruple-precision floating-point value `a' is a
420signaling NaN; otherwise returns 0.
421-------------------------------------------------------------------------------
422*/
423flag float128_is_signaling_nan( float128 a )
424{
425
426    return
427           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
428        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
429
430}
431
432/*
433-------------------------------------------------------------------------------
434Returns the result of converting the quadruple-precision floating-point NaN
435`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
436exception is raised.
437-------------------------------------------------------------------------------
438*/
439static commonNaNT float128ToCommonNaN( float128 a )
440{
441    commonNaNT z;
442
443    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
444    z.sign = a.high>>63;
445    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
446    return z;
447
448}
449
450/*
451-------------------------------------------------------------------------------
452Returns the result of converting the canonical NaN `a' to the quadruple-
453precision floating-point format.
454-------------------------------------------------------------------------------
455*/
456static float128 commonNaNToFloat128( commonNaNT a )
457{
458    float128 z;
459
460    shift128Right( a.high, a.low, 16, &z.high, &z.low );
461    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
462    return z;
463
464}
465
466/*
467-------------------------------------------------------------------------------
468Takes two quadruple-precision floating-point values `a' and `b', one of
469which is a NaN, and returns the appropriate NaN result.  If either `a' or
470`b' is a signaling NaN, the invalid exception is raised.
471-------------------------------------------------------------------------------
472*/
473static float128 propagateFloat128NaN( float128 a, float128 b )
474{
475    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
476
477    aIsNaN = float128_is_nan( a );
478    aIsSignalingNaN = float128_is_signaling_nan( a );
479    bIsNaN = float128_is_nan( b );
480    bIsSignalingNaN = float128_is_signaling_nan( b );
481    a.high |= LIT64( 0x0000800000000000 );
482    b.high |= LIT64( 0x0000800000000000 );
483    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
484    if ( aIsNaN ) {
485        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
486    }
487    else {
488        return b;
489    }
490
491}
492
493#endif
494
495