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