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