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