xref: /freebsd/lib/libc/softfloat/softfloat-specialize (revision 7ef62cebc2f965b0f640263e179276928885e33d)
1/*	$NetBSD: softfloat-specialize,v 1.6 2011/03/06 10:27:37 martin Exp $	*/
2/* $FreeBSD$ */
3
4/* This is a derivative work. */
5
6/*
7===============================================================================
8
9This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
10Arithmetic Package, Release 2a.
11
12Written by John R. Hauser.  This work was made possible in part by the
13International Computer Science Institute, located at Suite 600, 1947 Center
14Street, Berkeley, California 94704.  Funding was partially provided by the
15National Science Foundation under grant MIP-9311980.  The original version
16of this code was written as part of a project to build a fixed-point vector
17processor in collaboration with the University of California at Berkeley,
18overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
19is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
20arithmetic/SoftFloat.html'.
21
22THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
23has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
24TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
25PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
26AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
27
28Derivative works are acceptable, even for commercial purposes, so long as
29(1) they include prominent notice that the work is derivative, and (2) they
30include prominent notice akin to these four paragraphs for those parts of
31this code that are retained.
32
33===============================================================================
34*/
35
36#include <signal.h>
37#include <string.h>
38#include <unistd.h>
39
40/*
41-------------------------------------------------------------------------------
42Underflow tininess-detection mode, statically initialized to default value.
43(The declaration in `softfloat.h' must match the `int8' type here.)
44-------------------------------------------------------------------------------
45*/
46#ifdef SOFTFLOAT_FOR_GCC
47static
48#endif
49#ifdef __sparc64__
50int8 float_detect_tininess = float_tininess_before_rounding;
51#else
52int8 float_detect_tininess = float_tininess_after_rounding;
53#endif
54
55/*
56-------------------------------------------------------------------------------
57Raises the exceptions specified by `flags'.  Floating-point traps can be
58defined here if desired.  It is currently not possible for such a trap to
59substitute a result value.  If traps are not implemented, this routine
60should be simply `float_exception_flags |= flags;'.
61-------------------------------------------------------------------------------
62*/
63#ifdef SOFTFLOAT_FOR_GCC
64#define float_exception_mask	__softfloat_float_exception_mask
65#endif
66int float_exception_mask = 0;
67void float_raise( int flags )
68{
69
70    float_exception_flags |= flags;
71
72    if ( flags & float_exception_mask ) {
73#if 0
74	siginfo_t info;
75	memset(&info, 0, sizeof info);
76	info.si_signo = SIGFPE;
77	info.si_pid = getpid();
78	info.si_uid = geteuid();
79	if (flags & float_flag_underflow)
80	    info.si_code = FPE_FLTUND;
81	else if (flags & float_flag_overflow)
82	    info.si_code = FPE_FLTOVF;
83	else if (flags & float_flag_divbyzero)
84	    info.si_code = FPE_FLTDIV;
85	else if (flags & float_flag_invalid)
86	    info.si_code = FPE_FLTINV;
87	else if (flags & float_flag_inexact)
88	    info.si_code = FPE_FLTRES;
89	sigqueueinfo(getpid(), &info);
90#else
91	raise( SIGFPE );
92#endif
93    }
94}
95#undef float_exception_mask
96
97/*
98-------------------------------------------------------------------------------
99Internal canonical NaN format.
100-------------------------------------------------------------------------------
101*/
102typedef struct {
103    flag sign;
104    bits64 high, low;
105} commonNaNT;
106
107/*
108-------------------------------------------------------------------------------
109The pattern for a default generated single-precision NaN.
110-------------------------------------------------------------------------------
111*/
112#define float32_default_nan 0xFFFFFFFF
113
114/*
115-------------------------------------------------------------------------------
116Returns 1 if the single-precision floating-point value `a' is a NaN;
117otherwise returns 0.
118-------------------------------------------------------------------------------
119*/
120#ifdef SOFTFLOAT_FOR_GCC
121static
122#endif
123flag float32_is_nan( float32 a )
124{
125
126    return ( 0xFF000000 < (bits32) ( a<<1 ) );
127
128}
129
130/*
131-------------------------------------------------------------------------------
132Returns 1 if the single-precision floating-point value `a' is a signaling
133NaN; otherwise returns 0.
134-------------------------------------------------------------------------------
135*/
136#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
137    !defined(SOFTFLOAT_M68K_FOR_GCC)
138static
139#endif
140flag float32_is_signaling_nan( float32 a )
141{
142
143    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
144
145}
146
147/*
148-------------------------------------------------------------------------------
149Returns the result of converting the single-precision floating-point NaN
150`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
151exception is raised.
152-------------------------------------------------------------------------------
153*/
154static commonNaNT float32ToCommonNaN( float32 a )
155{
156    commonNaNT z;
157
158    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
159    z.sign = a>>31;
160    z.low = 0;
161    z.high = ( (bits64) a )<<41;
162    return z;
163
164}
165
166/*
167-------------------------------------------------------------------------------
168Returns the result of converting the canonical NaN `a' to the single-
169precision floating-point format.
170-------------------------------------------------------------------------------
171*/
172static float32 commonNaNToFloat32( commonNaNT a )
173{
174
175    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
176
177}
178
179/*
180-------------------------------------------------------------------------------
181Takes two single-precision floating-point values `a' and `b', one of which
182is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
183signaling NaN, the invalid exception is raised.
184-------------------------------------------------------------------------------
185*/
186static float32 propagateFloat32NaN( float32 a, float32 b )
187{
188    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
189
190    aIsNaN = float32_is_nan( a );
191    aIsSignalingNaN = float32_is_signaling_nan( a );
192    bIsNaN = float32_is_nan( b );
193    bIsSignalingNaN = float32_is_signaling_nan( b );
194    a |= 0x00400000;
195    b |= 0x00400000;
196    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
197    if ( aIsNaN ) {
198        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
199    }
200    else {
201        return b;
202    }
203
204}
205
206/*
207-------------------------------------------------------------------------------
208The pattern for a default generated double-precision NaN.
209-------------------------------------------------------------------------------
210*/
211#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
212
213/*
214-------------------------------------------------------------------------------
215Returns 1 if the double-precision floating-point value `a' is a NaN;
216otherwise returns 0.
217-------------------------------------------------------------------------------
218*/
219#ifdef SOFTFLOAT_FOR_GCC
220static
221#endif
222flag float64_is_nan( float64 a )
223{
224
225    return ( LIT64( 0xFFE0000000000000 ) <
226	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
227
228}
229
230/*
231-------------------------------------------------------------------------------
232Returns 1 if the double-precision floating-point value `a' is a signaling
233NaN; otherwise returns 0.
234-------------------------------------------------------------------------------
235*/
236#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
237    !defined(SOFTFLOATM68K_FOR_GCC)
238static
239#endif
240flag float64_is_signaling_nan( float64 a )
241{
242
243    return
244           ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
245        && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
246
247}
248
249/*
250-------------------------------------------------------------------------------
251Returns the result of converting the double-precision floating-point NaN
252`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
253exception is raised.
254-------------------------------------------------------------------------------
255*/
256static commonNaNT float64ToCommonNaN( float64 a )
257{
258    commonNaNT z;
259
260    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
261    z.sign = FLOAT64_DEMANGLE(a)>>63;
262    z.low = 0;
263    z.high = FLOAT64_DEMANGLE(a)<<12;
264    return z;
265
266}
267
268/*
269-------------------------------------------------------------------------------
270Returns the result of converting the canonical NaN `a' to the double-
271precision floating-point format.
272-------------------------------------------------------------------------------
273*/
274static float64 commonNaNToFloat64( commonNaNT a )
275{
276
277    return FLOAT64_MANGLE(
278	( ( (bits64) a.sign )<<63 )
279        | LIT64( 0x7FF8000000000000 )
280        | ( a.high>>12 ) );
281
282}
283
284/*
285-------------------------------------------------------------------------------
286Takes two double-precision floating-point values `a' and `b', one of which
287is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
288signaling NaN, the invalid exception is raised.
289-------------------------------------------------------------------------------
290*/
291static float64 propagateFloat64NaN( float64 a, float64 b )
292{
293    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
294
295    aIsNaN = float64_is_nan( a );
296    aIsSignalingNaN = float64_is_signaling_nan( a );
297    bIsNaN = float64_is_nan( b );
298    bIsSignalingNaN = float64_is_signaling_nan( b );
299    a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
300    b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
301    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
302    if ( aIsNaN ) {
303        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
304    }
305    else {
306        return b;
307    }
308
309}
310
311#ifdef FLOATX80
312
313/*
314-------------------------------------------------------------------------------
315The pattern for a default generated extended double-precision NaN.  The
316`high' and `low' values hold the most- and least-significant bits,
317respectively.
318-------------------------------------------------------------------------------
319*/
320#define floatx80_default_nan_high 0xFFFF
321#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
322
323/*
324-------------------------------------------------------------------------------
325Returns 1 if the extended double-precision floating-point value `a' is a
326NaN; otherwise returns 0.
327-------------------------------------------------------------------------------
328*/
329flag floatx80_is_nan( floatx80 a )
330{
331
332    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
333
334}
335
336/*
337-------------------------------------------------------------------------------
338Returns 1 if the extended double-precision floating-point value `a' is a
339signaling NaN; otherwise returns 0.
340-------------------------------------------------------------------------------
341*/
342flag floatx80_is_signaling_nan( floatx80 a )
343{
344    bits64 aLow;
345
346    aLow = a.low & ~ LIT64( 0x4000000000000000 );
347    return
348           ( ( a.high & 0x7FFF ) == 0x7FFF )
349        && (bits64) ( aLow<<1 )
350        && ( a.low == aLow );
351
352}
353
354/*
355-------------------------------------------------------------------------------
356Returns the result of converting the extended double-precision floating-
357point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
358invalid exception is raised.
359-------------------------------------------------------------------------------
360*/
361static commonNaNT floatx80ToCommonNaN( floatx80 a )
362{
363    commonNaNT z;
364
365    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
366    z.sign = a.high>>15;
367    z.low = 0;
368    z.high = a.low<<1;
369    return z;
370
371}
372
373/*
374-------------------------------------------------------------------------------
375Returns the result of converting the canonical NaN `a' to the extended
376double-precision floating-point format.
377-------------------------------------------------------------------------------
378*/
379static floatx80 commonNaNToFloatx80( commonNaNT a )
380{
381    floatx80 z;
382
383    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
384    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
385    return z;
386
387}
388
389/*
390-------------------------------------------------------------------------------
391Takes two extended double-precision floating-point values `a' and `b', one
392of which is a NaN, and returns the appropriate NaN result.  If either `a' or
393`b' is a signaling NaN, the invalid exception is raised.
394-------------------------------------------------------------------------------
395*/
396static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
397{
398    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
399
400    aIsNaN = floatx80_is_nan( a );
401    aIsSignalingNaN = floatx80_is_signaling_nan( a );
402    bIsNaN = floatx80_is_nan( b );
403    bIsSignalingNaN = floatx80_is_signaling_nan( b );
404    a.low |= LIT64( 0xC000000000000000 );
405    b.low |= LIT64( 0xC000000000000000 );
406    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
407    if ( aIsNaN ) {
408        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
409    }
410    else {
411        return b;
412    }
413
414}
415
416#endif
417
418#ifdef FLOAT128
419
420/*
421-------------------------------------------------------------------------------
422The pattern for a default generated quadruple-precision NaN.  The `high' and
423`low' values hold the most- and least-significant bits, respectively.
424-------------------------------------------------------------------------------
425*/
426#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
427#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
428
429/*
430-------------------------------------------------------------------------------
431Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
432otherwise returns 0.
433-------------------------------------------------------------------------------
434*/
435flag float128_is_nan( float128 a )
436{
437
438    return
439           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
440        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
441
442}
443
444/*
445-------------------------------------------------------------------------------
446Returns 1 if the quadruple-precision floating-point value `a' is a
447signaling NaN; otherwise returns 0.
448-------------------------------------------------------------------------------
449*/
450flag float128_is_signaling_nan( float128 a )
451{
452
453    return
454           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
455        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
456
457}
458
459/*
460-------------------------------------------------------------------------------
461Returns the result of converting the quadruple-precision floating-point NaN
462`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
463exception is raised.
464-------------------------------------------------------------------------------
465*/
466static commonNaNT float128ToCommonNaN( float128 a )
467{
468    commonNaNT z;
469
470    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
471    z.sign = a.high>>63;
472    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
473    return z;
474
475}
476
477/*
478-------------------------------------------------------------------------------
479Returns the result of converting the canonical NaN `a' to the quadruple-
480precision floating-point format.
481-------------------------------------------------------------------------------
482*/
483static float128 commonNaNToFloat128( commonNaNT a )
484{
485    float128 z;
486
487    shift128Right( a.high, a.low, 16, &z.high, &z.low );
488    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
489    return z;
490
491}
492
493/*
494-------------------------------------------------------------------------------
495Takes two quadruple-precision floating-point values `a' and `b', one of
496which is a NaN, and returns the appropriate NaN result.  If either `a' or
497`b' is a signaling NaN, the invalid exception is raised.
498-------------------------------------------------------------------------------
499*/
500static float128 propagateFloat128NaN( float128 a, float128 b )
501{
502    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
503
504    aIsNaN = float128_is_nan( a );
505    aIsSignalingNaN = float128_is_signaling_nan( a );
506    bIsNaN = float128_is_nan( b );
507    bIsSignalingNaN = float128_is_signaling_nan( b );
508    a.high |= LIT64( 0x0000800000000000 );
509    b.high |= LIT64( 0x0000800000000000 );
510    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
511    if ( aIsNaN ) {
512        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
513    }
514    else {
515        return b;
516    }
517
518}
519
520#endif
521
522