softfloat-specialize revision 129203
1189251Ssam/* $FreeBSD: head/lib/libc/softfloat/templates/softfloat-specialize 129203 2004-05-14 12:13:06Z cognet $ */
2189251Ssam
3189251Ssam/*
4189251Ssam===============================================================================
5252726Srpaulo
6252726SrpauloThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point
7189251SsamArithmetic Package, Release 2a.
8189251Ssam
9189251SsamWritten by John R. Hauser.  This work was made possible in part by the
10189251SsamInternational Computer Science Institute, located at Suite 600, 1947 Center
11189251SsamStreet, Berkeley, California 94704.  Funding was partially provided by the
12189251SsamNational Science Foundation under grant MIP-9311980.  The original version
13189251Ssamof this code was written as part of a project to build a fixed-point vector
14189251Ssamprocessor in collaboration with the University of California at Berkeley,
15189251Ssamoverseen by Profs. Nelson Morgan and John Wawrzynek.  More information
16189251Ssamis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
17189251Ssamarithmetic/SoftFloat.html'.
18189251Ssam
19189251SsamTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
20189251Ssamhas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
21189251SsamTIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
22189251SsamPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
23189251SsamAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
24189251Ssam
25189251SsamDerivative works are acceptable, even for commercial purposes, so long as
26189251Ssam(1) they include prominent notice that the work is derivative, and (2) they
27189251Ssaminclude prominent notice akin to these four paragraphs for those parts of
28189251Ssamthis code that are retained.
29189251Ssam
30189251Ssam===============================================================================
31189251Ssam*/
32189251Ssam
33189251Ssam/*
34189251Ssam-------------------------------------------------------------------------------
35189251SsamUnderflow tininess-detection mode, statically initialized to default value.
36189251Ssam(The declaration in `softfloat.h' must match the `int8' type here.)
37189251Ssam-------------------------------------------------------------------------------
38189251Ssam*/
39189251Ssamint8 float_detect_tininess = float_tininess_after_rounding;
40189251Ssam
41189251Ssam/*
42189251Ssam-------------------------------------------------------------------------------
43189251SsamRaises the exceptions specified by `flags'.  Floating-point traps can be
44189251Ssamdefined here if desired.  It is currently not possible for such a trap to
45189251Ssamsubstitute a result value.  If traps are not implemented, this routine
46189251Ssamshould be simply `float_exception_flags |= flags;'.
47189251Ssam-------------------------------------------------------------------------------
48189251Ssam*/
49189251Ssamvoid float_raise( int8 flags )
50189251Ssam{
51189251Ssam
52189251Ssam    float_exception_flags |= flags;
53189251Ssam
54189251Ssam}
55189251Ssam
56189251Ssam/*
57189251Ssam-------------------------------------------------------------------------------
58189251SsamInternal canonical NaN format.
59189251Ssam-------------------------------------------------------------------------------
60189251Ssam*/
61189251Ssamtypedef struct {
62189251Ssam    flag sign;
63189251Ssam    bits64 high, low;
64189251Ssam} commonNaNT;
65189251Ssam
66189251Ssam/*
67189251Ssam-------------------------------------------------------------------------------
68189251SsamThe pattern for a default generated single-precision NaN.
69189251Ssam-------------------------------------------------------------------------------
70189251Ssam*/
71189251Ssam#define float32_default_nan 0xFFFFFFFF
72189251Ssam
73189251Ssam/*
74189251Ssam-------------------------------------------------------------------------------
75189251SsamReturns 1 if the single-precision floating-point value `a' is a NaN;
76189251Ssamotherwise returns 0.
77189251Ssam-------------------------------------------------------------------------------
78189251Ssam*/
79189251Ssamflag float32_is_nan( float32 a )
80189251Ssam{
81189251Ssam
82189251Ssam    return ( 0xFF000000 < (bits32) ( a<<1 ) );
83189251Ssam
84189251Ssam}
85189251Ssam
86189251Ssam/*
87189251Ssam-------------------------------------------------------------------------------
88189251SsamReturns 1 if the single-precision floating-point value `a' is a signaling
89189251SsamNaN; otherwise returns 0.
90189251Ssam-------------------------------------------------------------------------------
91189251Ssam*/
92189251Ssamflag float32_is_signaling_nan( float32 a )
93189251Ssam{
94189251Ssam
95189251Ssam    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
96189251Ssam
97189251Ssam}
98189251Ssam
99189251Ssam/*
100189251Ssam-------------------------------------------------------------------------------
101189251SsamReturns the result of converting the single-precision floating-point NaN
102189251Ssam`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
103189251Ssamexception is raised.
104189251Ssam-------------------------------------------------------------------------------
105189251Ssam*/
106189251Ssamstatic commonNaNT float32ToCommonNaN( float32 a )
107189251Ssam{
108189251Ssam    commonNaNT z;
109189251Ssam
110189251Ssam    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
111189251Ssam    z.sign = a>>31;
112189251Ssam    z.low = 0;
113189251Ssam    z.high = ( (bits64) a )<<41;
114189251Ssam    return z;
115189251Ssam
116189251Ssam}
117189251Ssam
118189251Ssam/*
119189251Ssam-------------------------------------------------------------------------------
120189251SsamReturns the result of converting the canonical NaN `a' to the single-
121189251Ssamprecision floating-point format.
122189251Ssam-------------------------------------------------------------------------------
123189251Ssam*/
124189251Ssamstatic float32 commonNaNToFloat32( commonNaNT a )
125189251Ssam{
126189251Ssam
127    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
128
129}
130
131/*
132-------------------------------------------------------------------------------
133Takes two single-precision floating-point values `a' and `b', one of which
134is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
135signaling NaN, the invalid exception is raised.
136-------------------------------------------------------------------------------
137*/
138static float32 propagateFloat32NaN( float32 a, float32 b )
139{
140    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
141
142    aIsNaN = float32_is_nan( a );
143    aIsSignalingNaN = float32_is_signaling_nan( a );
144    bIsNaN = float32_is_nan( b );
145    bIsSignalingNaN = float32_is_signaling_nan( b );
146    a |= 0x00400000;
147    b |= 0x00400000;
148    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
149    if ( aIsNaN ) {
150        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
151    }
152    else {
153        return b;
154    }
155
156}
157
158/*
159-------------------------------------------------------------------------------
160The pattern for a default generated double-precision NaN.
161-------------------------------------------------------------------------------
162*/
163#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
164
165/*
166-------------------------------------------------------------------------------
167Returns 1 if the double-precision floating-point value `a' is a NaN;
168otherwise returns 0.
169-------------------------------------------------------------------------------
170*/
171flag float64_is_nan( float64 a )
172{
173
174    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
175
176}
177
178/*
179-------------------------------------------------------------------------------
180Returns 1 if the double-precision floating-point value `a' is a signaling
181NaN; otherwise returns 0.
182-------------------------------------------------------------------------------
183*/
184flag float64_is_signaling_nan( float64 a )
185{
186
187    return
188           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
189        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
190
191}
192
193/*
194-------------------------------------------------------------------------------
195Returns the result of converting the double-precision floating-point NaN
196`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
197exception is raised.
198-------------------------------------------------------------------------------
199*/
200static commonNaNT float64ToCommonNaN( float64 a )
201{
202    commonNaNT z;
203
204    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
205    z.sign = a>>63;
206    z.low = 0;
207    z.high = a<<12;
208    return z;
209
210}
211
212/*
213-------------------------------------------------------------------------------
214Returns the result of converting the canonical NaN `a' to the double-
215precision floating-point format.
216-------------------------------------------------------------------------------
217*/
218static float64 commonNaNToFloat64( commonNaNT a )
219{
220
221    return
222          ( ( (bits64) a.sign )<<63 )
223        | LIT64( 0x7FF8000000000000 )
224        | ( a.high>>12 );
225
226}
227
228/*
229-------------------------------------------------------------------------------
230Takes two double-precision floating-point values `a' and `b', one of which
231is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
232signaling NaN, the invalid exception is raised.
233-------------------------------------------------------------------------------
234*/
235static float64 propagateFloat64NaN( float64 a, float64 b )
236{
237    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
238
239    aIsNaN = float64_is_nan( a );
240    aIsSignalingNaN = float64_is_signaling_nan( a );
241    bIsNaN = float64_is_nan( b );
242    bIsSignalingNaN = float64_is_signaling_nan( b );
243    a |= LIT64( 0x0008000000000000 );
244    b |= LIT64( 0x0008000000000000 );
245    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
246    if ( aIsNaN ) {
247        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
248    }
249    else {
250        return b;
251    }
252
253}
254
255#ifdef FLOATX80
256
257/*
258-------------------------------------------------------------------------------
259The pattern for a default generated extended double-precision NaN.  The
260`high' and `low' values hold the most- and least-significant bits,
261respectively.
262-------------------------------------------------------------------------------
263*/
264#define floatx80_default_nan_high 0xFFFF
265#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
266
267/*
268-------------------------------------------------------------------------------
269Returns 1 if the extended double-precision floating-point value `a' is a
270NaN; otherwise returns 0.
271-------------------------------------------------------------------------------
272*/
273flag floatx80_is_nan( floatx80 a )
274{
275
276    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
277
278}
279
280/*
281-------------------------------------------------------------------------------
282Returns 1 if the extended double-precision floating-point value `a' is a
283signaling NaN; otherwise returns 0.
284-------------------------------------------------------------------------------
285*/
286flag floatx80_is_signaling_nan( floatx80 a )
287{
288    bits64 aLow;
289
290    aLow = a.low & ~ LIT64( 0x4000000000000000 );
291    return
292           ( ( a.high & 0x7FFF ) == 0x7FFF )
293        && (bits64) ( aLow<<1 )
294        && ( a.low == aLow );
295
296}
297
298/*
299-------------------------------------------------------------------------------
300Returns the result of converting the extended double-precision floating-
301point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
302invalid exception is raised.
303-------------------------------------------------------------------------------
304*/
305static commonNaNT floatx80ToCommonNaN( floatx80 a )
306{
307    commonNaNT z;
308
309    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
310    z.sign = a.high>>15;
311    z.low = 0;
312    z.high = a.low<<1;
313    return z;
314
315}
316
317/*
318-------------------------------------------------------------------------------
319Returns the result of converting the canonical NaN `a' to the extended
320double-precision floating-point format.
321-------------------------------------------------------------------------------
322*/
323static floatx80 commonNaNToFloatx80( commonNaNT a )
324{
325    floatx80 z;
326
327    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
328    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
329    return z;
330
331}
332
333/*
334-------------------------------------------------------------------------------
335Takes two extended double-precision floating-point values `a' and `b', one
336of which is a NaN, and returns the appropriate NaN result.  If either `a' or
337`b' is a signaling NaN, the invalid exception is raised.
338-------------------------------------------------------------------------------
339*/
340static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
341{
342    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
343
344    aIsNaN = floatx80_is_nan( a );
345    aIsSignalingNaN = floatx80_is_signaling_nan( a );
346    bIsNaN = floatx80_is_nan( b );
347    bIsSignalingNaN = floatx80_is_signaling_nan( b );
348    a.low |= LIT64( 0xC000000000000000 );
349    b.low |= LIT64( 0xC000000000000000 );
350    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
351    if ( aIsNaN ) {
352        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
353    }
354    else {
355        return b;
356    }
357
358}
359
360#endif
361
362#ifdef FLOAT128
363
364/*
365-------------------------------------------------------------------------------
366The pattern for a default generated quadruple-precision NaN.  The `high' and
367`low' values hold the most- and least-significant bits, respectively.
368-------------------------------------------------------------------------------
369*/
370#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
371#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
372
373/*
374-------------------------------------------------------------------------------
375Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
376otherwise returns 0.
377-------------------------------------------------------------------------------
378*/
379flag float128_is_nan( float128 a )
380{
381
382    return
383           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
384        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
385
386}
387
388/*
389-------------------------------------------------------------------------------
390Returns 1 if the quadruple-precision floating-point value `a' is a
391signaling NaN; otherwise returns 0.
392-------------------------------------------------------------------------------
393*/
394flag float128_is_signaling_nan( float128 a )
395{
396
397    return
398           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
399        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
400
401}
402
403/*
404-------------------------------------------------------------------------------
405Returns the result of converting the quadruple-precision floating-point NaN
406`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
407exception is raised.
408-------------------------------------------------------------------------------
409*/
410static commonNaNT float128ToCommonNaN( float128 a )
411{
412    commonNaNT z;
413
414    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
415    z.sign = a.high>>63;
416    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
417    return z;
418
419}
420
421/*
422-------------------------------------------------------------------------------
423Returns the result of converting the canonical NaN `a' to the quadruple-
424precision floating-point format.
425-------------------------------------------------------------------------------
426*/
427static float128 commonNaNToFloat128( commonNaNT a )
428{
429    float128 z;
430
431    shift128Right( a.high, a.low, 16, &z.high, &z.low );
432    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
433    return z;
434
435}
436
437/*
438-------------------------------------------------------------------------------
439Takes two quadruple-precision floating-point values `a' and `b', one of
440which is a NaN, and returns the appropriate NaN result.  If either `a' or
441`b' is a signaling NaN, the invalid exception is raised.
442-------------------------------------------------------------------------------
443*/
444static float128 propagateFloat128NaN( float128 a, float128 b )
445{
446    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
447
448    aIsNaN = float128_is_nan( a );
449    aIsSignalingNaN = float128_is_signaling_nan( a );
450    bIsNaN = float128_is_nan( b );
451    bIsSignalingNaN = float128_is_signaling_nan( b );
452    a.high |= LIT64( 0x0000800000000000 );
453    b.high |= LIT64( 0x0000800000000000 );
454    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
455    if ( aIsNaN ) {
456        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
457    }
458    else {
459        return b;
460    }
461
462}
463
464#endif
465
466