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