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	sigqueueinfo(getpid(), &info);
96    }
97}
98#undef float_exception_mask
99
100/*
101-------------------------------------------------------------------------------
102Internal canonical NaN format.
103-------------------------------------------------------------------------------
104*/
105typedef struct {
106    flag sign;
107    bits64 high, low;
108} commonNaNT;
109
110/*
111-------------------------------------------------------------------------------
112The pattern for a default generated single-precision NaN.
113-------------------------------------------------------------------------------
114*/
115#define float32_default_nan 0xFFFFFFFF
116
117/*
118-------------------------------------------------------------------------------
119Returns 1 if the single-precision floating-point value `a' is a NaN;
120otherwise returns 0.
121-------------------------------------------------------------------------------
122*/
123#ifdef SOFTFLOAT_FOR_GCC
124static
125#endif
126flag float32_is_nan( float32 a )
127{
128
129    return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) );
130
131}
132
133/*
134-------------------------------------------------------------------------------
135Returns 1 if the single-precision floating-point value `a' is a signaling
136NaN; otherwise returns 0.
137-------------------------------------------------------------------------------
138*/
139#if defined(SOFTFLOAT_FOR_GCC) \
140    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
141    && !defined(SOFTFLOATSPARC64_FOR_GCC) \
142    && !defined(SOFTFLOATM68K_FOR_GCC)
143static
144#endif
145flag float32_is_signaling_nan( float32 a )
146{
147
148    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
149
150}
151
152/*
153-------------------------------------------------------------------------------
154Returns the result of converting the single-precision floating-point NaN
155`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
156exception is raised.
157-------------------------------------------------------------------------------
158*/
159static commonNaNT float32ToCommonNaN( float32 a )
160{
161    commonNaNT z;
162
163    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
164    z.sign = a>>31;
165    z.low = 0;
166    z.high = ( (bits64) a )<<41;
167    return z;
168
169}
170
171/*
172-------------------------------------------------------------------------------
173Returns the result of converting the canonical NaN `a' to the single-
174precision floating-point format.
175-------------------------------------------------------------------------------
176*/
177static float32 commonNaNToFloat32( commonNaNT a )
178{
179
180    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 );
181
182}
183
184/*
185-------------------------------------------------------------------------------
186Takes two single-precision floating-point values `a' and `b', one of which
187is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
188signaling NaN, the invalid exception is raised.
189-------------------------------------------------------------------------------
190*/
191static float32 propagateFloat32NaN( float32 a, float32 b )
192{
193    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
194
195    aIsNaN = float32_is_nan( a );
196    aIsSignalingNaN = float32_is_signaling_nan( a );
197    bIsNaN = float32_is_nan( b );
198    bIsSignalingNaN = float32_is_signaling_nan( b );
199    a |= 0x00400000;
200    b |= 0x00400000;
201    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
202    if ( aIsNaN ) {
203        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
204    }
205    else {
206        return b;
207    }
208
209}
210
211/*
212-------------------------------------------------------------------------------
213The pattern for a default generated double-precision NaN.
214-------------------------------------------------------------------------------
215*/
216#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
217
218/*
219-------------------------------------------------------------------------------
220Returns 1 if the double-precision floating-point value `a' is a NaN;
221otherwise returns 0.
222-------------------------------------------------------------------------------
223*/
224#ifdef SOFTFLOAT_FOR_GCC
225static
226#endif
227flag float64_is_nan( float64 a )
228{
229
230    return ( (bits64)LIT64( 0xFFE0000000000000 ) <
231	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
232
233}
234
235/*
236-------------------------------------------------------------------------------
237Returns 1 if the double-precision floating-point value `a' is a signaling
238NaN; otherwise returns 0.
239-------------------------------------------------------------------------------
240*/
241#if defined(SOFTFLOAT_FOR_GCC) \
242    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
243    && !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