Statistics
| Branch: | Revision:

root / fpu / softfloat-specialize.h @ 09b26c5e

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