xref: /minix3/lib/libc/softfloat/softfloat-specialize (revision b5e2faaaaf60a8b9a02f8d72f64caa56a87eb312)
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    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) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
144    !defined(SOFTFLOAT_M68K_FOR_GCC)
145static
146#endif
147flag float32_is_signaling_nan( float32 a )
148{
149
150    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
151
152}
153
154/*
155-------------------------------------------------------------------------------
156Returns the result of converting the single-precision floating-point NaN
157`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
158exception is raised.
159-------------------------------------------------------------------------------
160*/
161static commonNaNT float32ToCommonNaN( float32 a )
162{
163    commonNaNT z;
164
165    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
166    z.sign = a>>31;
167    z.low = 0;
168    z.high = ( (bits64) a )<<41;
169    return z;
170
171}
172
173/*
174-------------------------------------------------------------------------------
175Returns the result of converting the canonical NaN `a' to the single-
176precision floating-point format.
177-------------------------------------------------------------------------------
178*/
179static float32 commonNaNToFloat32( commonNaNT a )
180{
181
182    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 );
183
184}
185
186/*
187-------------------------------------------------------------------------------
188Takes two single-precision floating-point values `a' and `b', one of which
189is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
190signaling NaN, the invalid exception is raised.
191-------------------------------------------------------------------------------
192*/
193static float32 propagateFloat32NaN( float32 a, float32 b )
194{
195    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
196
197    aIsNaN = float32_is_nan( a );
198    aIsSignalingNaN = float32_is_signaling_nan( a );
199    bIsNaN = float32_is_nan( b );
200    bIsSignalingNaN = float32_is_signaling_nan( b );
201    a |= 0x00400000;
202    b |= 0x00400000;
203    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
204    if ( aIsNaN ) {
205        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
206    }
207    else {
208        return b;
209    }
210
211}
212
213/*
214-------------------------------------------------------------------------------
215The pattern for a default generated double-precision NaN.
216-------------------------------------------------------------------------------
217*/
218#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
219
220/*
221-------------------------------------------------------------------------------
222Returns 1 if the double-precision floating-point value `a' is a NaN;
223otherwise returns 0.
224-------------------------------------------------------------------------------
225*/
226#ifdef SOFTFLOAT_FOR_GCC
227static
228#endif
229flag float64_is_nan( float64 a )
230{
231
232    return ( (bits64)LIT64( 0xFFE0000000000000 ) <
233	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
234
235}
236
237/*
238-------------------------------------------------------------------------------
239Returns 1 if the double-precision floating-point value `a' is a signaling
240NaN; otherwise returns 0.
241-------------------------------------------------------------------------------
242*/
243#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
244    !defined(SOFTFLOATM68K_FOR_GCC)
245static
246#endif
247flag float64_is_signaling_nan( float64 a )
248{
249
250    return
251           ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
252        && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
253
254}
255
256/*
257-------------------------------------------------------------------------------
258Returns the result of converting the double-precision floating-point NaN
259`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
260exception is raised.
261-------------------------------------------------------------------------------
262*/
263static commonNaNT float64ToCommonNaN( float64 a )
264{
265    commonNaNT z;
266
267    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
268    z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63);
269    z.low = 0;
270    z.high = FLOAT64_DEMANGLE(a)<<12;
271    return z;
272
273}
274
275/*
276-------------------------------------------------------------------------------
277Returns the result of converting the canonical NaN `a' to the double-
278precision floating-point format.
279-------------------------------------------------------------------------------
280*/
281static float64 commonNaNToFloat64( commonNaNT a )
282{
283
284    return FLOAT64_MANGLE(
285	( ( (bits64) a.sign )<<63 )
286        | LIT64( 0x7FF8000000000000 )
287        | ( a.high>>12 ) );
288
289}
290
291/*
292-------------------------------------------------------------------------------
293Takes two double-precision floating-point values `a' and `b', one of which
294is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
295signaling NaN, the invalid exception is raised.
296-------------------------------------------------------------------------------
297*/
298static float64 propagateFloat64NaN( float64 a, float64 b )
299{
300    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
301
302    aIsNaN = float64_is_nan( a );
303    aIsSignalingNaN = float64_is_signaling_nan( a );
304    bIsNaN = float64_is_nan( b );
305    bIsSignalingNaN = float64_is_signaling_nan( b );
306    a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
307    b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
308    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
309    if ( aIsNaN ) {
310        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
311    }
312    else {
313        return b;
314    }
315
316}
317
318#ifdef FLOATX80
319
320/*
321-------------------------------------------------------------------------------
322The pattern for a default generated extended double-precision NaN.  The
323`high' and `low' values hold the most- and least-significant bits,
324respectively.
325-------------------------------------------------------------------------------
326*/
327#define floatx80_default_nan_high 0xFFFF
328#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
329
330/*
331-------------------------------------------------------------------------------
332Returns 1 if the extended double-precision floating-point value `a' is a
333NaN; otherwise returns 0.
334-------------------------------------------------------------------------------
335*/
336flag floatx80_is_nan( floatx80 a )
337{
338
339    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
340
341}
342
343/*
344-------------------------------------------------------------------------------
345Returns 1 if the extended double-precision floating-point value `a' is a
346signaling NaN; otherwise returns 0.
347-------------------------------------------------------------------------------
348*/
349flag floatx80_is_signaling_nan( floatx80 a )
350{
351    bits64 aLow;
352
353    aLow = a.low & ~ LIT64( 0x4000000000000000 );
354    return
355           ( ( a.high & 0x7FFF ) == 0x7FFF )
356        && (bits64) ( aLow<<1 )
357        && ( a.low == aLow );
358
359}
360
361/*
362-------------------------------------------------------------------------------
363Returns the result of converting the extended double-precision floating-
364point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
365invalid exception is raised.
366-------------------------------------------------------------------------------
367*/
368static commonNaNT floatx80ToCommonNaN( floatx80 a )
369{
370    commonNaNT z;
371
372    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
373    z.sign = a.high>>15;
374    z.low = 0;
375    z.high = a.low<<1;
376    return z;
377
378}
379
380/*
381-------------------------------------------------------------------------------
382Returns the result of converting the canonical NaN `a' to the extended
383double-precision floating-point format.
384-------------------------------------------------------------------------------
385*/
386static floatx80 commonNaNToFloatx80( commonNaNT a )
387{
388    floatx80 z;
389
390    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
391    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
392    return z;
393
394}
395
396/*
397-------------------------------------------------------------------------------
398Takes two extended double-precision floating-point values `a' and `b', one
399of which is a NaN, and returns the appropriate NaN result.  If either `a' or
400`b' is a signaling NaN, the invalid exception is raised.
401-------------------------------------------------------------------------------
402*/
403static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
404{
405    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
406
407    aIsNaN = floatx80_is_nan( a );
408    aIsSignalingNaN = floatx80_is_signaling_nan( a );
409    bIsNaN = floatx80_is_nan( b );
410    bIsSignalingNaN = floatx80_is_signaling_nan( b );
411    a.low |= LIT64( 0xC000000000000000 );
412    b.low |= LIT64( 0xC000000000000000 );
413    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
414    if ( aIsNaN ) {
415        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
416    }
417    else {
418        return b;
419    }
420
421}
422
423#endif
424
425#ifdef FLOAT128
426
427/*
428-------------------------------------------------------------------------------
429The pattern for a default generated quadruple-precision NaN.  The `high' and
430`low' values hold the most- and least-significant bits, respectively.
431-------------------------------------------------------------------------------
432*/
433#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
434#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
435
436/*
437-------------------------------------------------------------------------------
438Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
439otherwise returns 0.
440-------------------------------------------------------------------------------
441*/
442flag float128_is_nan( float128 a )
443{
444
445    return
446           ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
447        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
448
449}
450
451/*
452-------------------------------------------------------------------------------
453Returns 1 if the quadruple-precision floating-point value `a' is a
454signaling NaN; otherwise returns 0.
455-------------------------------------------------------------------------------
456*/
457flag float128_is_signaling_nan( float128 a )
458{
459
460    return
461           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
462        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
463
464}
465
466/*
467-------------------------------------------------------------------------------
468Returns the result of converting the quadruple-precision floating-point NaN
469`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
470exception is raised.
471-------------------------------------------------------------------------------
472*/
473static commonNaNT float128ToCommonNaN( float128 a )
474{
475    commonNaNT z;
476
477    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
478    z.sign = (flag)(a.high>>63);
479    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
480    return z;
481
482}
483
484/*
485-------------------------------------------------------------------------------
486Returns the result of converting the canonical NaN `a' to the quadruple-
487precision floating-point format.
488-------------------------------------------------------------------------------
489*/
490static float128 commonNaNToFloat128( commonNaNT a )
491{
492    float128 z;
493
494    shift128Right( a.high, a.low, 16, &z.high, &z.low );
495    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
496    return z;
497
498}
499
500/*
501-------------------------------------------------------------------------------
502Takes two quadruple-precision floating-point values `a' and `b', one of
503which is a NaN, and returns the appropriate NaN result.  If either `a' or
504`b' is a signaling NaN, the invalid exception is raised.
505-------------------------------------------------------------------------------
506*/
507static float128 propagateFloat128NaN( float128 a, float128 b )
508{
509    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
510
511    aIsNaN = float128_is_nan( a );
512    aIsSignalingNaN = float128_is_signaling_nan( a );
513    bIsNaN = float128_is_nan( b );
514    bIsSignalingNaN = float128_is_signaling_nan( b );
515    a.high |= LIT64( 0x0000800000000000 );
516    b.high |= LIT64( 0x0000800000000000 );
517    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
518    if ( aIsNaN ) {
519        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
520    }
521    else {
522        return b;
523    }
524
525}
526
527#endif
528
529