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