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