softfloat-specialize revision 1.5
1/*	$NetBSD: softfloat-specialize,v 1.5 2011/03/04 11:48:58 martin 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#include <string.h>
37#include <unistd.h>
38
39/*
40-------------------------------------------------------------------------------
41Underflow tininess-detection mode, statically initialized to default value.
42(The declaration in `softfloat.h' must match the `int8' type here.)
43-------------------------------------------------------------------------------
44*/
45#ifdef SOFTFLOAT_FOR_GCC
46static
47#endif
48int8 float_detect_tininess = float_tininess_after_rounding;
49
50/*
51-------------------------------------------------------------------------------
52Raises the exceptions specified by `flags'.  Floating-point traps can be
53defined here if desired.  It is currently not possible for such a trap to
54substitute a result value.  If traps are not implemented, this routine
55should be simply `float_exception_flags |= flags;'.
56-------------------------------------------------------------------------------
57*/
58fp_except float_exception_mask = 0;
59void float_raise( fp_except flags )
60{
61    siginfo_t info;
62
63    float_exception_flags |= flags;
64
65    if ( flags & float_exception_mask ) {
66	memset(&info, 0, sizeof info);
67	info.si_signo = SIGFPE;
68	info.si_pid = getpid();
69	info.si_uid = geteuid();
70	if (flags & float_flag_underflow)
71	    info.si_code = FPE_FLTUND;
72	else if (flags & float_flag_overflow)
73	    info.si_code = FPE_FLTOVF;
74	else if (flags & float_flag_divbyzero)
75	    info.si_code = FPE_FLTDIV;
76	else if (flags & float_flag_invalid)
77	    info.si_code = FPE_FLTINV;
78	else if (flags & float_flag_inexact)
79	    info.si_code = FPE_FLTRES;
80	sigqueueinfo(getpid(), &info);
81    }
82}
83
84/*
85-------------------------------------------------------------------------------
86Internal canonical NaN format.
87-------------------------------------------------------------------------------
88*/
89typedef struct {
90    flag sign;
91    bits64 high, low;
92} commonNaNT;
93
94/*
95-------------------------------------------------------------------------------
96The pattern for a default generated single-precision NaN.
97-------------------------------------------------------------------------------
98*/
99#define float32_default_nan 0xFFFFFFFF
100
101/*
102-------------------------------------------------------------------------------
103Returns 1 if the single-precision floating-point value `a' is a NaN;
104otherwise returns 0.
105-------------------------------------------------------------------------------
106*/
107#ifdef SOFTFLOAT_FOR_GCC
108static
109#endif
110flag float32_is_nan( float32 a )
111{
112
113    return ( 0xFF000000 < (bits32) ( a<<1 ) );
114
115}
116
117/*
118-------------------------------------------------------------------------------
119Returns 1 if the single-precision floating-point value `a' is a signaling
120NaN; otherwise returns 0.
121-------------------------------------------------------------------------------
122*/
123#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
124    !defined(SOFTFLOAT_M68K_FOR_GCC)
125static
126#endif
127flag float32_is_signaling_nan( float32 a )
128{
129
130    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
131
132}
133
134/*
135-------------------------------------------------------------------------------
136Returns the result of converting the single-precision floating-point NaN
137`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
138exception is raised.
139-------------------------------------------------------------------------------
140*/
141static commonNaNT float32ToCommonNaN( float32 a )
142{
143    commonNaNT z;
144
145    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
146    z.sign = a>>31;
147    z.low = 0;
148    z.high = ( (bits64) a )<<41;
149    return z;
150
151}
152
153/*
154-------------------------------------------------------------------------------
155Returns the result of converting the canonical NaN `a' to the single-
156precision floating-point format.
157-------------------------------------------------------------------------------
158*/
159static float32 commonNaNToFloat32( commonNaNT a )
160{
161
162    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
163
164}
165
166/*
167-------------------------------------------------------------------------------
168Takes two single-precision floating-point values `a' and `b', one of which
169is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
170signaling NaN, the invalid exception is raised.
171-------------------------------------------------------------------------------
172*/
173static float32 propagateFloat32NaN( float32 a, float32 b )
174{
175    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
176
177    aIsNaN = float32_is_nan( a );
178    aIsSignalingNaN = float32_is_signaling_nan( a );
179    bIsNaN = float32_is_nan( b );
180    bIsSignalingNaN = float32_is_signaling_nan( b );
181    a |= 0x00400000;
182    b |= 0x00400000;
183    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
184    if ( aIsNaN ) {
185        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
186    }
187    else {
188        return b;
189    }
190
191}
192
193/*
194-------------------------------------------------------------------------------
195The pattern for a default generated double-precision NaN.
196-------------------------------------------------------------------------------
197*/
198#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
199
200/*
201-------------------------------------------------------------------------------
202Returns 1 if the double-precision floating-point value `a' is a NaN;
203otherwise returns 0.
204-------------------------------------------------------------------------------
205*/
206#ifdef SOFTFLOAT_FOR_GCC
207static
208#endif
209flag float64_is_nan( float64 a )
210{
211
212    return ( LIT64( 0xFFE0000000000000 ) <
213	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
214
215}
216
217/*
218-------------------------------------------------------------------------------
219Returns 1 if the double-precision floating-point value `a' is a signaling
220NaN; otherwise returns 0.
221-------------------------------------------------------------------------------
222*/
223#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
224    !defined(SOFTFLOATM68K_FOR_GCC)
225static
226#endif
227flag float64_is_signaling_nan( float64 a )
228{
229
230    return
231           ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
232        && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
233
234}
235
236/*
237-------------------------------------------------------------------------------
238Returns the result of converting the double-precision floating-point NaN
239`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
240exception is raised.
241-------------------------------------------------------------------------------
242*/
243static commonNaNT float64ToCommonNaN( float64 a )
244{
245    commonNaNT z;
246
247    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
248    z.sign = FLOAT64_DEMANGLE(a)>>63;
249    z.low = 0;
250    z.high = FLOAT64_DEMANGLE(a)<<12;
251    return z;
252
253}
254
255/*
256-------------------------------------------------------------------------------
257Returns the result of converting the canonical NaN `a' to the double-
258precision floating-point format.
259-------------------------------------------------------------------------------
260*/
261static float64 commonNaNToFloat64( commonNaNT a )
262{
263
264    return FLOAT64_MANGLE(
265	( ( (bits64) a.sign )<<63 )
266        | LIT64( 0x7FF8000000000000 )
267        | ( a.high>>12 ) );
268
269}
270
271/*
272-------------------------------------------------------------------------------
273Takes two double-precision floating-point values `a' and `b', one of which
274is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
275signaling NaN, the invalid exception is raised.
276-------------------------------------------------------------------------------
277*/
278static float64 propagateFloat64NaN( float64 a, float64 b )
279{
280    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
281
282    aIsNaN = float64_is_nan( a );
283    aIsSignalingNaN = float64_is_signaling_nan( a );
284    bIsNaN = float64_is_nan( b );
285    bIsSignalingNaN = float64_is_signaling_nan( b );
286    a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
287    b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
288    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
289    if ( aIsNaN ) {
290        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
291    }
292    else {
293        return b;
294    }
295
296}
297
298#ifdef FLOATX80
299
300/*
301-------------------------------------------------------------------------------
302The pattern for a default generated extended double-precision NaN.  The
303`high' and `low' values hold the most- and least-significant bits,
304respectively.
305-------------------------------------------------------------------------------
306*/
307#define floatx80_default_nan_high 0xFFFF
308#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
309
310/*
311-------------------------------------------------------------------------------
312Returns 1 if the extended double-precision floating-point value `a' is a
313NaN; otherwise returns 0.
314-------------------------------------------------------------------------------
315*/
316flag floatx80_is_nan( floatx80 a )
317{
318
319    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
320
321}
322
323/*
324-------------------------------------------------------------------------------
325Returns 1 if the extended double-precision floating-point value `a' is a
326signaling NaN; otherwise returns 0.
327-------------------------------------------------------------------------------
328*/
329flag floatx80_is_signaling_nan( floatx80 a )
330{
331    bits64 aLow;
332
333    aLow = a.low & ~ LIT64( 0x4000000000000000 );
334    return
335           ( ( a.high & 0x7FFF ) == 0x7FFF )
336        && (bits64) ( aLow<<1 )
337        && ( a.low == aLow );
338
339}
340
341/*
342-------------------------------------------------------------------------------
343Returns the result of converting the extended double-precision floating-
344point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
345invalid exception is raised.
346-------------------------------------------------------------------------------
347*/
348static commonNaNT floatx80ToCommonNaN( floatx80 a )
349{
350    commonNaNT z;
351
352    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
353    z.sign = a.high>>15;
354    z.low = 0;
355    z.high = a.low<<1;
356    return z;
357
358}
359
360/*
361-------------------------------------------------------------------------------
362Returns the result of converting the canonical NaN `a' to the extended
363double-precision floating-point format.
364-------------------------------------------------------------------------------
365*/
366static floatx80 commonNaNToFloatx80( commonNaNT a )
367{
368    floatx80 z;
369
370    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
371    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
372    return z;
373
374}
375
376/*
377-------------------------------------------------------------------------------
378Takes two extended double-precision floating-point values `a' and `b', one
379of which is a NaN, and returns the appropriate NaN result.  If either `a' or
380`b' is a signaling NaN, the invalid exception is raised.
381-------------------------------------------------------------------------------
382*/
383static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
384{
385    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
386
387    aIsNaN = floatx80_is_nan( a );
388    aIsSignalingNaN = floatx80_is_signaling_nan( a );
389    bIsNaN = floatx80_is_nan( b );
390    bIsSignalingNaN = floatx80_is_signaling_nan( b );
391    a.low |= LIT64( 0xC000000000000000 );
392    b.low |= LIT64( 0xC000000000000000 );
393    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
394    if ( aIsNaN ) {
395        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
396    }
397    else {
398        return b;
399    }
400
401}
402
403#endif
404
405#ifdef FLOAT128
406
407/*
408-------------------------------------------------------------------------------
409The pattern for a default generated quadruple-precision NaN.  The `high' and
410`low' values hold the most- and least-significant bits, respectively.
411-------------------------------------------------------------------------------
412*/
413#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
414#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
415
416/*
417-------------------------------------------------------------------------------
418Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
419otherwise returns 0.
420-------------------------------------------------------------------------------
421*/
422flag float128_is_nan( float128 a )
423{
424
425    return
426           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
427        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
428
429}
430
431/*
432-------------------------------------------------------------------------------
433Returns 1 if the quadruple-precision floating-point value `a' is a
434signaling NaN; otherwise returns 0.
435-------------------------------------------------------------------------------
436*/
437flag float128_is_signaling_nan( float128 a )
438{
439
440    return
441           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
442        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
443
444}
445
446/*
447-------------------------------------------------------------------------------
448Returns the result of converting the quadruple-precision floating-point NaN
449`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
450exception is raised.
451-------------------------------------------------------------------------------
452*/
453static commonNaNT float128ToCommonNaN( float128 a )
454{
455    commonNaNT z;
456
457    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
458    z.sign = a.high>>63;
459    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
460    return z;
461
462}
463
464/*
465-------------------------------------------------------------------------------
466Returns the result of converting the canonical NaN `a' to the quadruple-
467precision floating-point format.
468-------------------------------------------------------------------------------
469*/
470static float128 commonNaNToFloat128( commonNaNT a )
471{
472    float128 z;
473
474    shift128Right( a.high, a.low, 16, &z.high, &z.low );
475    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
476    return z;
477
478}
479
480/*
481-------------------------------------------------------------------------------
482Takes two quadruple-precision floating-point values `a' and `b', one of
483which is a NaN, and returns the appropriate NaN result.  If either `a' or
484`b' is a signaling NaN, the invalid exception is raised.
485-------------------------------------------------------------------------------
486*/
487static float128 propagateFloat128NaN( float128 a, float128 b )
488{
489    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
490
491    aIsNaN = float128_is_nan( a );
492    aIsSignalingNaN = float128_is_signaling_nan( a );
493    bIsNaN = float128_is_nan( b );
494    bIsSignalingNaN = float128_is_signaling_nan( b );
495    a.high |= LIT64( 0x0000800000000000 );
496    b.high |= LIT64( 0x0000800000000000 );
497    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
498    if ( aIsNaN ) {
499        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
500    }
501    else {
502        return b;
503    }
504
505}
506
507#endif
508
509