Statistics
| Branch: | Revision:

root / fpu / softfloat-specialize.h @ 52621688

History | View | Annotate | Download (17.5 kB)

1 158142c2 bellard
2 158142c2 bellard
/*============================================================================
3 158142c2 bellard

4 158142c2 bellard
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
5 158142c2 bellard
Arithmetic Package, Release 2b.
6 158142c2 bellard

7 158142c2 bellard
Written by John R. Hauser.  This work was made possible in part by the
8 158142c2 bellard
International Computer Science Institute, located at Suite 600, 1947 Center
9 158142c2 bellard
Street, Berkeley, California 94704.  Funding was partially provided by the
10 158142c2 bellard
National Science Foundation under grant MIP-9311980.  The original version
11 158142c2 bellard
of this code was written as part of a project to build a fixed-point vector
12 158142c2 bellard
processor in collaboration with the University of California at Berkeley,
13 158142c2 bellard
overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
14 158142c2 bellard
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
15 158142c2 bellard
arithmetic/SoftFloat.html'.
16 158142c2 bellard

17 158142c2 bellard
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
18 158142c2 bellard
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
19 158142c2 bellard
RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
20 158142c2 bellard
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
21 158142c2 bellard
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
22 158142c2 bellard
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
23 158142c2 bellard
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
24 158142c2 bellard
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
25 158142c2 bellard

26 158142c2 bellard
Derivative works are acceptable, even for commercial purposes, so long as
27 158142c2 bellard
(1) the source code for the derivative work includes prominent notice that
28 158142c2 bellard
the work is derivative, and (2) the source code includes prominent notice with
29 158142c2 bellard
these four paragraphs for those parts of this code that are retained.
30 158142c2 bellard

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