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