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