added abs, chs and compare functions
[qemu] / fpu / softfloat.c
1
2 /*============================================================================
3
4 This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
5 Package, Release 2b.
6
7 Written by John R. Hauser.  This work was made possible in part by the
8 International Computer Science Institute, located at Suite 600, 1947 Center
9 Street, Berkeley, California 94704.  Funding was partially provided by the
10 National Science Foundation under grant MIP-9311980.  The original version
11 of this code was written as part of a project to build a fixed-point vector
12 processor in collaboration with the University of California at Berkeley,
13 overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
14 is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
15 arithmetic/SoftFloat.html'.
16
17 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
18 been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
19 RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
20 AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
21 COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
22 EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
23 INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
24 OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
25
26 Derivative works are acceptable, even for commercial purposes, so long as
27 (1) the source code for the derivative work includes prominent notice that
28 the work is derivative, and (2) the source code includes prominent notice with
29 these four paragraphs for those parts of this code that are retained.
30
31 =============================================================================*/
32
33 #include "softfloat.h"
34
35 /*----------------------------------------------------------------------------
36 | Primitive arithmetic functions, including multi-word arithmetic, and
37 | division and square root approximations.  (Can be specialized to target if
38 | desired.)
39 *----------------------------------------------------------------------------*/
40 #include "softfloat-macros.h"
41
42 /*----------------------------------------------------------------------------
43 | Functions and definitions to determine:  (1) whether tininess for underflow
44 | is detected before or after rounding by default, (2) what (if anything)
45 | happens when exceptions are raised, (3) how signaling NaNs are distinguished
46 | from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
47 | are propagated from function inputs to output.  These details are target-
48 | specific.
49 *----------------------------------------------------------------------------*/
50 #include "softfloat-specialize.h"
51
52 void set_float_rounding_mode(int val STATUS_PARAM)
53 {
54     STATUS(float_rounding_mode) = val;
55 }
56
57 void set_float_exception_flags(int val STATUS_PARAM)
58 {
59     STATUS(float_exception_flags) = val;
60 }
61
62 #ifdef FLOATX80
63 void set_floatx80_rounding_precision(int val STATUS_PARAM)
64 {
65     STATUS(floatx80_rounding_precision) = val;
66 }
67 #endif
68
69 /*----------------------------------------------------------------------------
70 | Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
71 | and 7, and returns the properly rounded 32-bit integer corresponding to the
72 | input.  If `zSign' is 1, the input is negated before being converted to an
73 | integer.  Bit 63 of `absZ' must be zero.  Ordinarily, the fixed-point input
74 | is simply rounded to an integer, with the inexact exception raised if the
75 | input cannot be represented exactly as an integer.  However, if the fixed-
76 | point input is too large, the invalid exception is raised and the largest
77 | positive or negative integer is returned.
78 *----------------------------------------------------------------------------*/
79
80 static int32 roundAndPackInt32( flag zSign, bits64 absZ STATUS_PARAM)
81 {
82     int8 roundingMode;
83     flag roundNearestEven;
84     int8 roundIncrement, roundBits;
85     int32 z;
86
87     roundingMode = STATUS(float_rounding_mode);
88     roundNearestEven = ( roundingMode == float_round_nearest_even );
89     roundIncrement = 0x40;
90     if ( ! roundNearestEven ) {
91         if ( roundingMode == float_round_to_zero ) {
92             roundIncrement = 0;
93         }
94         else {
95             roundIncrement = 0x7F;
96             if ( zSign ) {
97                 if ( roundingMode == float_round_up ) roundIncrement = 0;
98             }
99             else {
100                 if ( roundingMode == float_round_down ) roundIncrement = 0;
101             }
102         }
103     }
104     roundBits = absZ & 0x7F;
105     absZ = ( absZ + roundIncrement )>>7;
106     absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
107     z = absZ;
108     if ( zSign ) z = - z;
109     if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
110         float_raise( float_flag_invalid STATUS_VAR);
111         return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
112     }
113     if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
114     return z;
115
116 }
117
118 /*----------------------------------------------------------------------------
119 | Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
120 | `absZ1', with binary point between bits 63 and 64 (between the input words),
121 | and returns the properly rounded 64-bit integer corresponding to the input.
122 | If `zSign' is 1, the input is negated before being converted to an integer.
123 | Ordinarily, the fixed-point input is simply rounded to an integer, with
124 | the inexact exception raised if the input cannot be represented exactly as
125 | an integer.  However, if the fixed-point input is too large, the invalid
126 | exception is raised and the largest positive or negative integer is
127 | returned.
128 *----------------------------------------------------------------------------*/
129
130 static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 STATUS_PARAM)
131 {
132     int8 roundingMode;
133     flag roundNearestEven, increment;
134     int64 z;
135
136     roundingMode = STATUS(float_rounding_mode);
137     roundNearestEven = ( roundingMode == float_round_nearest_even );
138     increment = ( (sbits64) absZ1 < 0 );
139     if ( ! roundNearestEven ) {
140         if ( roundingMode == float_round_to_zero ) {
141             increment = 0;
142         }
143         else {
144             if ( zSign ) {
145                 increment = ( roundingMode == float_round_down ) && absZ1;
146             }
147             else {
148                 increment = ( roundingMode == float_round_up ) && absZ1;
149             }
150         }
151     }
152     if ( increment ) {
153         ++absZ0;
154         if ( absZ0 == 0 ) goto overflow;
155         absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven );
156     }
157     z = absZ0;
158     if ( zSign ) z = - z;
159     if ( z && ( ( z < 0 ) ^ zSign ) ) {
160  overflow:
161         float_raise( float_flag_invalid STATUS_VAR);
162         return
163               zSign ? (sbits64) LIT64( 0x8000000000000000 )
164             : LIT64( 0x7FFFFFFFFFFFFFFF );
165     }
166     if ( absZ1 ) STATUS(float_exception_flags) |= float_flag_inexact;
167     return z;
168
169 }
170
171 /*----------------------------------------------------------------------------
172 | Returns the fraction bits of the single-precision floating-point value `a'.
173 *----------------------------------------------------------------------------*/
174
175 INLINE bits32 extractFloat32Frac( float32 a )
176 {
177
178     return a & 0x007FFFFF;
179
180 }
181
182 /*----------------------------------------------------------------------------
183 | Returns the exponent bits of the single-precision floating-point value `a'.
184 *----------------------------------------------------------------------------*/
185
186 INLINE int16 extractFloat32Exp( float32 a )
187 {
188
189     return ( a>>23 ) & 0xFF;
190
191 }
192
193 /*----------------------------------------------------------------------------
194 | Returns the sign bit of the single-precision floating-point value `a'.
195 *----------------------------------------------------------------------------*/
196
197 INLINE flag extractFloat32Sign( float32 a )
198 {
199
200     return a>>31;
201
202 }
203
204 /*----------------------------------------------------------------------------
205 | Normalizes the subnormal single-precision floating-point value represented
206 | by the denormalized significand `aSig'.  The normalized exponent and
207 | significand are stored at the locations pointed to by `zExpPtr' and
208 | `zSigPtr', respectively.
209 *----------------------------------------------------------------------------*/
210
211 static void
212  normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr )
213 {
214     int8 shiftCount;
215
216     shiftCount = countLeadingZeros32( aSig ) - 8;
217     *zSigPtr = aSig<<shiftCount;
218     *zExpPtr = 1 - shiftCount;
219
220 }
221
222 /*----------------------------------------------------------------------------
223 | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
224 | single-precision floating-point value, returning the result.  After being
225 | shifted into the proper positions, the three fields are simply added
226 | together to form the result.  This means that any integer portion of `zSig'
227 | will be added into the exponent.  Since a properly normalized significand
228 | will have an integer portion equal to 1, the `zExp' input should be 1 less
229 | than the desired result exponent whenever `zSig' is a complete, normalized
230 | significand.
231 *----------------------------------------------------------------------------*/
232
233 INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
234 {
235
236     return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig;
237
238 }
239
240 /*----------------------------------------------------------------------------
241 | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
242 | and significand `zSig', and returns the proper single-precision floating-
243 | point value corresponding to the abstract input.  Ordinarily, the abstract
244 | value is simply rounded and packed into the single-precision format, with
245 | the inexact exception raised if the abstract input cannot be represented
246 | exactly.  However, if the abstract value is too large, the overflow and
247 | inexact exceptions are raised and an infinity or maximal finite value is
248 | returned.  If the abstract value is too small, the input value is rounded to
249 | a subnormal number, and the underflow and inexact exceptions are raised if
250 | the abstract input cannot be represented exactly as a subnormal single-
251 | precision floating-point number.
252 |     The input significand `zSig' has its binary point between bits 30
253 | and 29, which is 7 bits to the left of the usual location.  This shifted
254 | significand must be normalized or smaller.  If `zSig' is not normalized,
255 | `zExp' must be 0; in that case, the result returned is a subnormal number,
256 | and it must not require rounding.  In the usual case that `zSig' is
257 | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
258 | The handling of underflow and overflow follows the IEC/IEEE Standard for
259 | Binary Floating-Point Arithmetic.
260 *----------------------------------------------------------------------------*/
261
262 static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_PARAM)
263 {
264     int8 roundingMode;
265     flag roundNearestEven;
266     int8 roundIncrement, roundBits;
267     flag isTiny;
268
269     roundingMode = STATUS(float_rounding_mode);
270     roundNearestEven = ( roundingMode == float_round_nearest_even );
271     roundIncrement = 0x40;
272     if ( ! roundNearestEven ) {
273         if ( roundingMode == float_round_to_zero ) {
274             roundIncrement = 0;
275         }
276         else {
277             roundIncrement = 0x7F;
278             if ( zSign ) {
279                 if ( roundingMode == float_round_up ) roundIncrement = 0;
280             }
281             else {
282                 if ( roundingMode == float_round_down ) roundIncrement = 0;
283             }
284         }
285     }
286     roundBits = zSig & 0x7F;
287     if ( 0xFD <= (bits16) zExp ) {
288         if (    ( 0xFD < zExp )
289              || (    ( zExp == 0xFD )
290                   && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
291            ) {
292             float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
293             return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
294         }
295         if ( zExp < 0 ) {
296             isTiny =
297                    ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
298                 || ( zExp < -1 )
299                 || ( zSig + roundIncrement < 0x80000000 );
300             shift32RightJamming( zSig, - zExp, &zSig );
301             zExp = 0;
302             roundBits = zSig & 0x7F;
303             if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR);
304         }
305     }
306     if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
307     zSig = ( zSig + roundIncrement )>>7;
308     zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
309     if ( zSig == 0 ) zExp = 0;
310     return packFloat32( zSign, zExp, zSig );
311
312 }
313
314 /*----------------------------------------------------------------------------
315 | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
316 | and significand `zSig', and returns the proper single-precision floating-
317 | point value corresponding to the abstract input.  This routine is just like
318 | `roundAndPackFloat32' except that `zSig' does not have to be normalized.
319 | Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
320 | floating-point exponent.
321 *----------------------------------------------------------------------------*/
322
323 static float32
324  normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_PARAM)
325 {
326     int8 shiftCount;
327
328     shiftCount = countLeadingZeros32( zSig ) - 1;
329     return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount STATUS_VAR);
330
331 }
332
333 /*----------------------------------------------------------------------------
334 | Returns the fraction bits of the double-precision floating-point value `a'.
335 *----------------------------------------------------------------------------*/
336
337 INLINE bits64 extractFloat64Frac( float64 a )
338 {
339
340     return a & LIT64( 0x000FFFFFFFFFFFFF );
341
342 }
343
344 /*----------------------------------------------------------------------------
345 | Returns the exponent bits of the double-precision floating-point value `a'.
346 *----------------------------------------------------------------------------*/
347
348 INLINE int16 extractFloat64Exp( float64 a )
349 {
350
351     return ( a>>52 ) & 0x7FF;
352
353 }
354
355 /*----------------------------------------------------------------------------
356 | Returns the sign bit of the double-precision floating-point value `a'.
357 *----------------------------------------------------------------------------*/
358
359 INLINE flag extractFloat64Sign( float64 a )
360 {
361
362     return a>>63;
363
364 }
365
366 /*----------------------------------------------------------------------------
367 | Normalizes the subnormal double-precision floating-point value represented
368 | by the denormalized significand `aSig'.  The normalized exponent and
369 | significand are stored at the locations pointed to by `zExpPtr' and
370 | `zSigPtr', respectively.
371 *----------------------------------------------------------------------------*/
372
373 static void
374  normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr )
375 {
376     int8 shiftCount;
377
378     shiftCount = countLeadingZeros64( aSig ) - 11;
379     *zSigPtr = aSig<<shiftCount;
380     *zExpPtr = 1 - shiftCount;
381
382 }
383
384 /*----------------------------------------------------------------------------
385 | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
386 | double-precision floating-point value, returning the result.  After being
387 | shifted into the proper positions, the three fields are simply added
388 | together to form the result.  This means that any integer portion of `zSig'
389 | will be added into the exponent.  Since a properly normalized significand
390 | will have an integer portion equal to 1, the `zExp' input should be 1 less
391 | than the desired result exponent whenever `zSig' is a complete, normalized
392 | significand.
393 *----------------------------------------------------------------------------*/
394
395 INLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig )
396 {
397
398     return ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<52 ) + zSig;
399
400 }
401
402 /*----------------------------------------------------------------------------
403 | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
404 | and significand `zSig', and returns the proper double-precision floating-
405 | point value corresponding to the abstract input.  Ordinarily, the abstract
406 | value is simply rounded and packed into the double-precision format, with
407 | the inexact exception raised if the abstract input cannot be represented
408 | exactly.  However, if the abstract value is too large, the overflow and
409 | inexact exceptions are raised and an infinity or maximal finite value is
410 | returned.  If the abstract value is too small, the input value is rounded
411 | to a subnormal number, and the underflow and inexact exceptions are raised
412 | if the abstract input cannot be represented exactly as a subnormal double-
413 | precision floating-point number.
414 |     The input significand `zSig' has its binary point between bits 62
415 | and 61, which is 10 bits to the left of the usual location.  This shifted
416 | significand must be normalized or smaller.  If `zSig' is not normalized,
417 | `zExp' must be 0; in that case, the result returned is a subnormal number,
418 | and it must not require rounding.  In the usual case that `zSig' is
419 | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
420 | The handling of underflow and overflow follows the IEC/IEEE Standard for
421 | Binary Floating-Point Arithmetic.
422 *----------------------------------------------------------------------------*/
423
424 static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_PARAM)
425 {
426     int8 roundingMode;
427     flag roundNearestEven;
428     int16 roundIncrement, roundBits;
429     flag isTiny;
430
431     roundingMode = STATUS(float_rounding_mode);
432     roundNearestEven = ( roundingMode == float_round_nearest_even );
433     roundIncrement = 0x200;
434     if ( ! roundNearestEven ) {
435         if ( roundingMode == float_round_to_zero ) {
436             roundIncrement = 0;
437         }
438         else {
439             roundIncrement = 0x3FF;
440             if ( zSign ) {
441                 if ( roundingMode == float_round_up ) roundIncrement = 0;
442             }
443             else {
444                 if ( roundingMode == float_round_down ) roundIncrement = 0;
445             }
446         }
447     }
448     roundBits = zSig & 0x3FF;
449     if ( 0x7FD <= (bits16) zExp ) {
450         if (    ( 0x7FD < zExp )
451              || (    ( zExp == 0x7FD )
452                   && ( (sbits64) ( zSig + roundIncrement ) < 0 ) )
453            ) {
454             float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
455             return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 );
456         }
457         if ( zExp < 0 ) {
458             isTiny =
459                    ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
460                 || ( zExp < -1 )
461                 || ( zSig + roundIncrement < LIT64( 0x8000000000000000 ) );
462             shift64RightJamming( zSig, - zExp, &zSig );
463             zExp = 0;
464             roundBits = zSig & 0x3FF;
465             if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR);
466         }
467     }
468     if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
469     zSig = ( zSig + roundIncrement )>>10;
470     zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
471     if ( zSig == 0 ) zExp = 0;
472     return packFloat64( zSign, zExp, zSig );
473
474 }
475
476 /*----------------------------------------------------------------------------
477 | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
478 | and significand `zSig', and returns the proper double-precision floating-
479 | point value corresponding to the abstract input.  This routine is just like
480 | `roundAndPackFloat64' except that `zSig' does not have to be normalized.
481 | Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
482 | floating-point exponent.
483 *----------------------------------------------------------------------------*/
484
485 static float64
486  normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_PARAM)
487 {
488     int8 shiftCount;
489
490     shiftCount = countLeadingZeros64( zSig ) - 1;
491     return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<<shiftCount STATUS_VAR);
492
493 }
494
495 #ifdef FLOATX80
496
497 /*----------------------------------------------------------------------------
498 | Returns the fraction bits of the extended double-precision floating-point
499 | value `a'.
500 *----------------------------------------------------------------------------*/
501
502 INLINE bits64 extractFloatx80Frac( floatx80 a )
503 {
504
505     return a.low;
506
507 }
508
509 /*----------------------------------------------------------------------------
510 | Returns the exponent bits of the extended double-precision floating-point
511 | value `a'.
512 *----------------------------------------------------------------------------*/
513
514 INLINE int32 extractFloatx80Exp( floatx80 a )
515 {
516
517     return a.high & 0x7FFF;
518
519 }
520
521 /*----------------------------------------------------------------------------
522 | Returns the sign bit of the extended double-precision floating-point value
523 | `a'.
524 *----------------------------------------------------------------------------*/
525
526 INLINE flag extractFloatx80Sign( floatx80 a )
527 {
528
529     return a.high>>15;
530
531 }
532
533 /*----------------------------------------------------------------------------
534 | Normalizes the subnormal extended double-precision floating-point value
535 | represented by the denormalized significand `aSig'.  The normalized exponent
536 | and significand are stored at the locations pointed to by `zExpPtr' and
537 | `zSigPtr', respectively.
538 *----------------------------------------------------------------------------*/
539
540 static void
541  normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr )
542 {
543     int8 shiftCount;
544
545     shiftCount = countLeadingZeros64( aSig );
546     *zSigPtr = aSig<<shiftCount;
547     *zExpPtr = 1 - shiftCount;
548
549 }
550
551 /*----------------------------------------------------------------------------
552 | Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
553 | extended double-precision floating-point value, returning the result.
554 *----------------------------------------------------------------------------*/
555
556 INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig )
557 {
558     floatx80 z;
559
560     z.low = zSig;
561     z.high = ( ( (bits16) zSign )<<15 ) + zExp;
562     return z;
563
564 }
565
566 /*----------------------------------------------------------------------------
567 | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
568 | and extended significand formed by the concatenation of `zSig0' and `zSig1',
569 | and returns the proper extended double-precision floating-point value
570 | corresponding to the abstract input.  Ordinarily, the abstract value is
571 | rounded and packed into the extended double-precision format, with the
572 | inexact exception raised if the abstract input cannot be represented
573 | exactly.  However, if the abstract value is too large, the overflow and
574 | inexact exceptions are raised and an infinity or maximal finite value is
575 | returned.  If the abstract value is too small, the input value is rounded to
576 | a subnormal number, and the underflow and inexact exceptions are raised if
577 | the abstract input cannot be represented exactly as a subnormal extended
578 | double-precision floating-point number.
579 |     If `roundingPrecision' is 32 or 64, the result is rounded to the same
580 | number of bits as single or double precision, respectively.  Otherwise, the
581 | result is rounded to the full precision of the extended double-precision
582 | format.
583 |     The input significand must be normalized or smaller.  If the input
584 | significand is not normalized, `zExp' must be 0; in that case, the result
585 | returned is a subnormal number, and it must not require rounding.  The
586 | handling of underflow and overflow follows the IEC/IEEE Standard for Binary
587 | Floating-Point Arithmetic.
588 *----------------------------------------------------------------------------*/
589
590 static floatx80
591  roundAndPackFloatx80(
592      int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
593  STATUS_PARAM)
594 {
595     int8 roundingMode;
596     flag roundNearestEven, increment, isTiny;
597     int64 roundIncrement, roundMask, roundBits;
598
599     roundingMode = STATUS(float_rounding_mode);
600     roundNearestEven = ( roundingMode == float_round_nearest_even );
601     if ( roundingPrecision == 80 ) goto precision80;
602     if ( roundingPrecision == 64 ) {
603         roundIncrement = LIT64( 0x0000000000000400 );
604         roundMask = LIT64( 0x00000000000007FF );
605     }
606     else if ( roundingPrecision == 32 ) {
607         roundIncrement = LIT64( 0x0000008000000000 );
608         roundMask = LIT64( 0x000000FFFFFFFFFF );
609     }
610     else {
611         goto precision80;
612     }
613     zSig0 |= ( zSig1 != 0 );
614     if ( ! roundNearestEven ) {
615         if ( roundingMode == float_round_to_zero ) {
616             roundIncrement = 0;
617         }
618         else {
619             roundIncrement = roundMask;
620             if ( zSign ) {
621                 if ( roundingMode == float_round_up ) roundIncrement = 0;
622             }
623             else {
624                 if ( roundingMode == float_round_down ) roundIncrement = 0;
625             }
626         }
627     }
628     roundBits = zSig0 & roundMask;
629     if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
630         if (    ( 0x7FFE < zExp )
631              || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) )
632            ) {
633             goto overflow;
634         }
635         if ( zExp <= 0 ) {
636             isTiny =
637                    ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
638                 || ( zExp < 0 )
639                 || ( zSig0 <= zSig0 + roundIncrement );
640             shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
641             zExp = 0;
642             roundBits = zSig0 & roundMask;
643             if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR);
644             if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
645             zSig0 += roundIncrement;
646             if ( (sbits64) zSig0 < 0 ) zExp = 1;
647             roundIncrement = roundMask + 1;
648             if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
649                 roundMask |= roundIncrement;
650             }
651             zSig0 &= ~ roundMask;
652             return packFloatx80( zSign, zExp, zSig0 );
653         }
654     }
655     if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
656     zSig0 += roundIncrement;
657     if ( zSig0 < roundIncrement ) {
658         ++zExp;
659         zSig0 = LIT64( 0x8000000000000000 );
660     }
661     roundIncrement = roundMask + 1;
662     if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
663         roundMask |= roundIncrement;
664     }
665     zSig0 &= ~ roundMask;
666     if ( zSig0 == 0 ) zExp = 0;
667     return packFloatx80( zSign, zExp, zSig0 );
668  precision80:
669     increment = ( (sbits64) zSig1 < 0 );
670     if ( ! roundNearestEven ) {
671         if ( roundingMode == float_round_to_zero ) {
672             increment = 0;
673         }
674         else {
675             if ( zSign ) {
676                 increment = ( roundingMode == float_round_down ) && zSig1;
677             }
678             else {
679                 increment = ( roundingMode == float_round_up ) && zSig1;
680             }
681         }
682     }
683     if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
684         if (    ( 0x7FFE < zExp )
685              || (    ( zExp == 0x7FFE )
686                   && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) )
687                   && increment
688                 )
689            ) {
690             roundMask = 0;
691  overflow:
692             float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
693             if (    ( roundingMode == float_round_to_zero )
694                  || ( zSign && ( roundingMode == float_round_up ) )
695                  || ( ! zSign && ( roundingMode == float_round_down ) )
696                ) {
697                 return packFloatx80( zSign, 0x7FFE, ~ roundMask );
698             }
699             return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
700         }
701         if ( zExp <= 0 ) {
702             isTiny =
703                    ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
704                 || ( zExp < 0 )
705                 || ! increment
706                 || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
707             shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
708             zExp = 0;
709             if ( isTiny && zSig1 ) float_raise( float_flag_underflow STATUS_VAR);
710             if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
711             if ( roundNearestEven ) {
712                 increment = ( (sbits64) zSig1 < 0 );
713             }
714             else {
715                 if ( zSign ) {
716                     increment = ( roundingMode == float_round_down ) && zSig1;
717                 }
718                 else {
719                     increment = ( roundingMode == float_round_up ) && zSig1;
720                 }
721             }
722             if ( increment ) {
723                 ++zSig0;
724                 zSig0 &=
725                     ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven );
726                 if ( (sbits64) zSig0 < 0 ) zExp = 1;
727             }
728             return packFloatx80( zSign, zExp, zSig0 );
729         }
730     }
731     if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
732     if ( increment ) {
733         ++zSig0;
734         if ( zSig0 == 0 ) {
735             ++zExp;
736             zSig0 = LIT64( 0x8000000000000000 );
737         }
738         else {
739             zSig0 &= ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven );
740         }
741     }
742     else {
743         if ( zSig0 == 0 ) zExp = 0;
744     }
745     return packFloatx80( zSign, zExp, zSig0 );
746
747 }
748
749 /*----------------------------------------------------------------------------
750 | Takes an abstract floating-point value having sign `zSign', exponent
751 | `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
752 | and returns the proper extended double-precision floating-point value
753 | corresponding to the abstract input.  This routine is just like
754 | `roundAndPackFloatx80' except that the input significand does not have to be
755 | normalized.
756 *----------------------------------------------------------------------------*/
757
758 static floatx80
759  normalizeRoundAndPackFloatx80(
760      int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
761  STATUS_PARAM)
762 {
763     int8 shiftCount;
764
765     if ( zSig0 == 0 ) {
766         zSig0 = zSig1;
767         zSig1 = 0;
768         zExp -= 64;
769     }
770     shiftCount = countLeadingZeros64( zSig0 );
771     shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
772     zExp -= shiftCount;
773     return
774         roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 STATUS_VAR);
775
776 }
777
778 #endif
779
780 #ifdef FLOAT128
781
782 /*----------------------------------------------------------------------------
783 | Returns the least-significant 64 fraction bits of the quadruple-precision
784 | floating-point value `a'.
785 *----------------------------------------------------------------------------*/
786
787 INLINE bits64 extractFloat128Frac1( float128 a )
788 {
789
790     return a.low;
791
792 }
793
794 /*----------------------------------------------------------------------------
795 | Returns the most-significant 48 fraction bits of the quadruple-precision
796 | floating-point value `a'.
797 *----------------------------------------------------------------------------*/
798
799 INLINE bits64 extractFloat128Frac0( float128 a )
800 {
801
802     return a.high & LIT64( 0x0000FFFFFFFFFFFF );
803
804 }
805
806 /*----------------------------------------------------------------------------
807 | Returns the exponent bits of the quadruple-precision floating-point value
808 | `a'.
809 *----------------------------------------------------------------------------*/
810
811 INLINE int32 extractFloat128Exp( float128 a )
812 {
813
814     return ( a.high>>48 ) & 0x7FFF;
815
816 }
817
818 /*----------------------------------------------------------------------------
819 | Returns the sign bit of the quadruple-precision floating-point value `a'.
820 *----------------------------------------------------------------------------*/
821
822 INLINE flag extractFloat128Sign( float128 a )
823 {
824
825     return a.high>>63;
826
827 }
828
829 /*----------------------------------------------------------------------------
830 | Normalizes the subnormal quadruple-precision floating-point value
831 | represented by the denormalized significand formed by the concatenation of
832 | `aSig0' and `aSig1'.  The normalized exponent is stored at the location
833 | pointed to by `zExpPtr'.  The most significant 49 bits of the normalized
834 | significand are stored at the location pointed to by `zSig0Ptr', and the
835 | least significant 64 bits of the normalized significand are stored at the
836 | location pointed to by `zSig1Ptr'.
837 *----------------------------------------------------------------------------*/
838
839 static void
840  normalizeFloat128Subnormal(
841      bits64 aSig0,
842      bits64 aSig1,
843      int32 *zExpPtr,
844      bits64 *zSig0Ptr,
845      bits64 *zSig1Ptr
846  )
847 {
848     int8 shiftCount;
849
850     if ( aSig0 == 0 ) {
851         shiftCount = countLeadingZeros64( aSig1 ) - 15;
852         if ( shiftCount < 0 ) {
853             *zSig0Ptr = aSig1>>( - shiftCount );
854             *zSig1Ptr = aSig1<<( shiftCount & 63 );
855         }
856         else {
857             *zSig0Ptr = aSig1<<shiftCount;
858             *zSig1Ptr = 0;
859         }
860         *zExpPtr = - shiftCount - 63;
861     }
862     else {
863         shiftCount = countLeadingZeros64( aSig0 ) - 15;
864         shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
865         *zExpPtr = 1 - shiftCount;
866     }
867
868 }
869
870 /*----------------------------------------------------------------------------
871 | Packs the sign `zSign', the exponent `zExp', and the significand formed
872 | by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
873 | floating-point value, returning the result.  After being shifted into the
874 | proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
875 | added together to form the most significant 32 bits of the result.  This
876 | means that any integer portion of `zSig0' will be added into the exponent.
877 | Since a properly normalized significand will have an integer portion equal
878 | to 1, the `zExp' input should be 1 less than the desired result exponent
879 | whenever `zSig0' and `zSig1' concatenated form a complete, normalized
880 | significand.
881 *----------------------------------------------------------------------------*/
882
883 INLINE float128
884  packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 )
885 {
886     float128 z;
887
888     z.low = zSig1;
889     z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0;
890     return z;
891
892 }
893
894 /*----------------------------------------------------------------------------
895 | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
896 | and extended significand formed by the concatenation of `zSig0', `zSig1',
897 | and `zSig2', and returns the proper quadruple-precision floating-point value
898 | corresponding to the abstract input.  Ordinarily, the abstract value is
899 | simply rounded and packed into the quadruple-precision format, with the
900 | inexact exception raised if the abstract input cannot be represented
901 | exactly.  However, if the abstract value is too large, the overflow and
902 | inexact exceptions are raised and an infinity or maximal finite value is
903 | returned.  If the abstract value is too small, the input value is rounded to
904 | a subnormal number, and the underflow and inexact exceptions are raised if
905 | the abstract input cannot be represented exactly as a subnormal quadruple-
906 | precision floating-point number.
907 |     The input significand must be normalized or smaller.  If the input
908 | significand is not normalized, `zExp' must be 0; in that case, the result
909 | returned is a subnormal number, and it must not require rounding.  In the
910 | usual case that the input significand is normalized, `zExp' must be 1 less
911 | than the ``true'' floating-point exponent.  The handling of underflow and
912 | overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
913 *----------------------------------------------------------------------------*/
914
915 static float128
916  roundAndPackFloat128(
917      flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 STATUS_PARAM)
918 {
919     int8 roundingMode;
920     flag roundNearestEven, increment, isTiny;
921
922     roundingMode = STATUS(float_rounding_mode);
923     roundNearestEven = ( roundingMode == float_round_nearest_even );
924     increment = ( (sbits64) zSig2 < 0 );
925     if ( ! roundNearestEven ) {
926         if ( roundingMode == float_round_to_zero ) {
927             increment = 0;
928         }
929         else {
930             if ( zSign ) {
931                 increment = ( roundingMode == float_round_down ) && zSig2;
932             }
933             else {
934                 increment = ( roundingMode == float_round_up ) && zSig2;
935             }
936         }
937     }
938     if ( 0x7FFD <= (bits32) zExp ) {
939         if (    ( 0x7FFD < zExp )
940              || (    ( zExp == 0x7FFD )
941                   && eq128(
942                          LIT64( 0x0001FFFFFFFFFFFF ),
943                          LIT64( 0xFFFFFFFFFFFFFFFF ),
944                          zSig0,
945                          zSig1
946                      )
947                   && increment
948                 )
949            ) {
950             float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
951             if (    ( roundingMode == float_round_to_zero )
952                  || ( zSign && ( roundingMode == float_round_up ) )
953                  || ( ! zSign && ( roundingMode == float_round_down ) )
954                ) {
955                 return
956                     packFloat128(
957                         zSign,
958                         0x7FFE,
959                         LIT64( 0x0000FFFFFFFFFFFF ),
960                         LIT64( 0xFFFFFFFFFFFFFFFF )
961                     );
962             }
963             return packFloat128( zSign, 0x7FFF, 0, 0 );
964         }
965         if ( zExp < 0 ) {
966             isTiny =
967                    ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
968                 || ( zExp < -1 )
969                 || ! increment
970                 || lt128(
971                        zSig0,
972                        zSig1,
973                        LIT64( 0x0001FFFFFFFFFFFF ),
974                        LIT64( 0xFFFFFFFFFFFFFFFF )
975                    );
976             shift128ExtraRightJamming(
977                 zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 );
978             zExp = 0;
979             if ( isTiny && zSig2 ) float_raise( float_flag_underflow STATUS_VAR);
980             if ( roundNearestEven ) {
981                 increment = ( (sbits64) zSig2 < 0 );
982             }
983             else {
984                 if ( zSign ) {
985                     increment = ( roundingMode == float_round_down ) && zSig2;
986                 }
987                 else {
988                     increment = ( roundingMode == float_round_up ) && zSig2;
989                 }
990             }
991         }
992     }
993     if ( zSig2 ) STATUS(float_exception_flags) |= float_flag_inexact;
994     if ( increment ) {
995         add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 );
996         zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven );
997     }
998     else {
999         if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0;
1000     }
1001     return packFloat128( zSign, zExp, zSig0, zSig1 );
1002
1003 }
1004
1005 /*----------------------------------------------------------------------------
1006 | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
1007 | and significand formed by the concatenation of `zSig0' and `zSig1', and
1008 | returns the proper quadruple-precision floating-point value corresponding
1009 | to the abstract input.  This routine is just like `roundAndPackFloat128'
1010 | except that the input significand has fewer bits and does not have to be
1011 | normalized.  In all cases, `zExp' must be 1 less than the ``true'' floating-
1012 | point exponent.
1013 *----------------------------------------------------------------------------*/
1014
1015 static float128
1016  normalizeRoundAndPackFloat128(
1017      flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 STATUS_PARAM)
1018 {
1019     int8 shiftCount;
1020     bits64 zSig2;
1021
1022     if ( zSig0 == 0 ) {
1023         zSig0 = zSig1;
1024         zSig1 = 0;
1025         zExp -= 64;
1026     }
1027     shiftCount = countLeadingZeros64( zSig0 ) - 15;
1028     if ( 0 <= shiftCount ) {
1029         zSig2 = 0;
1030         shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
1031     }
1032     else {
1033         shift128ExtraRightJamming(
1034             zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 );
1035     }
1036     zExp -= shiftCount;
1037     return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR);
1038
1039 }
1040
1041 #endif
1042
1043 /*----------------------------------------------------------------------------
1044 | Returns the result of converting the 32-bit two's complement integer `a'
1045 | to the single-precision floating-point format.  The conversion is performed
1046 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1047 *----------------------------------------------------------------------------*/
1048
1049 float32 int32_to_float32( int32 a STATUS_PARAM )
1050 {
1051     flag zSign;
1052
1053     if ( a == 0 ) return 0;
1054     if ( a == (sbits32) 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
1055     zSign = ( a < 0 );
1056     return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a STATUS_VAR );
1057
1058 }
1059
1060 /*----------------------------------------------------------------------------
1061 | Returns the result of converting the 32-bit two's complement integer `a'
1062 | to the double-precision floating-point format.  The conversion is performed
1063 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1064 *----------------------------------------------------------------------------*/
1065
1066 float64 int32_to_float64( int32 a STATUS_PARAM )
1067 {
1068     flag zSign;
1069     uint32 absA;
1070     int8 shiftCount;
1071     bits64 zSig;
1072
1073     if ( a == 0 ) return 0;
1074     zSign = ( a < 0 );
1075     absA = zSign ? - a : a;
1076     shiftCount = countLeadingZeros32( absA ) + 21;
1077     zSig = absA;
1078     return packFloat64( zSign, 0x432 - shiftCount, zSig<<shiftCount );
1079
1080 }
1081
1082 #ifdef FLOATX80
1083
1084 /*----------------------------------------------------------------------------
1085 | Returns the result of converting the 32-bit two's complement integer `a'
1086 | to the extended double-precision floating-point format.  The conversion
1087 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
1088 | Arithmetic.
1089 *----------------------------------------------------------------------------*/
1090
1091 floatx80 int32_to_floatx80( int32 a STATUS_PARAM )
1092 {
1093     flag zSign;
1094     uint32 absA;
1095     int8 shiftCount;
1096     bits64 zSig;
1097
1098     if ( a == 0 ) return packFloatx80( 0, 0, 0 );
1099     zSign = ( a < 0 );
1100     absA = zSign ? - a : a;
1101     shiftCount = countLeadingZeros32( absA ) + 32;
1102     zSig = absA;
1103     return packFloatx80( zSign, 0x403E - shiftCount, zSig<<shiftCount );
1104
1105 }
1106
1107 #endif
1108
1109 #ifdef FLOAT128
1110
1111 /*----------------------------------------------------------------------------
1112 | Returns the result of converting the 32-bit two's complement integer `a' to
1113 | the quadruple-precision floating-point format.  The conversion is performed
1114 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1115 *----------------------------------------------------------------------------*/
1116
1117 float128 int32_to_float128( int32 a STATUS_PARAM )
1118 {
1119     flag zSign;
1120     uint32 absA;
1121     int8 shiftCount;
1122     bits64 zSig0;
1123
1124     if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
1125     zSign = ( a < 0 );
1126     absA = zSign ? - a : a;
1127     shiftCount = countLeadingZeros32( absA ) + 17;
1128     zSig0 = absA;
1129     return packFloat128( zSign, 0x402E - shiftCount, zSig0<<shiftCount, 0 );
1130
1131 }
1132
1133 #endif
1134
1135 /*----------------------------------------------------------------------------
1136 | Returns the result of converting the 64-bit two's complement integer `a'
1137 | to the single-precision floating-point format.  The conversion is performed
1138 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1139 *----------------------------------------------------------------------------*/
1140
1141 float32 int64_to_float32( int64 a STATUS_PARAM )
1142 {
1143     flag zSign;
1144     uint64 absA;
1145     int8 shiftCount;
1146
1147     if ( a == 0 ) return 0;
1148     zSign = ( a < 0 );
1149     absA = zSign ? - a : a;
1150     shiftCount = countLeadingZeros64( absA ) - 40;
1151     if ( 0 <= shiftCount ) {
1152         return packFloat32( zSign, 0x95 - shiftCount, absA<<shiftCount );
1153     }
1154     else {
1155         shiftCount += 7;
1156         if ( shiftCount < 0 ) {
1157             shift64RightJamming( absA, - shiftCount, &absA );
1158         }
1159         else {
1160             absA <<= shiftCount;
1161         }
1162         return roundAndPackFloat32( zSign, 0x9C - shiftCount, absA STATUS_VAR );
1163     }
1164
1165 }
1166
1167 /*----------------------------------------------------------------------------
1168 | Returns the result of converting the 64-bit two's complement integer `a'
1169 | to the double-precision floating-point format.  The conversion is performed
1170 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1171 *----------------------------------------------------------------------------*/
1172
1173 float64 int64_to_float64( int64 a STATUS_PARAM )
1174 {
1175     flag zSign;
1176
1177     if ( a == 0 ) return 0;
1178     if ( a == (sbits64) LIT64( 0x8000000000000000 ) ) {
1179         return packFloat64( 1, 0x43E, 0 );
1180     }
1181     zSign = ( a < 0 );
1182     return normalizeRoundAndPackFloat64( zSign, 0x43C, zSign ? - a : a STATUS_VAR );
1183
1184 }
1185
1186 #ifdef FLOATX80
1187
1188 /*----------------------------------------------------------------------------
1189 | Returns the result of converting the 64-bit two's complement integer `a'
1190 | to the extended double-precision floating-point format.  The conversion
1191 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
1192 | Arithmetic.
1193 *----------------------------------------------------------------------------*/
1194
1195 floatx80 int64_to_floatx80( int64 a STATUS_PARAM )
1196 {
1197     flag zSign;
1198     uint64 absA;
1199     int8 shiftCount;
1200
1201     if ( a == 0 ) return packFloatx80( 0, 0, 0 );
1202     zSign = ( a < 0 );
1203     absA = zSign ? - a : a;
1204     shiftCount = countLeadingZeros64( absA );
1205     return packFloatx80( zSign, 0x403E - shiftCount, absA<<shiftCount );
1206
1207 }
1208
1209 #endif
1210
1211 #ifdef FLOAT128
1212
1213 /*----------------------------------------------------------------------------
1214 | Returns the result of converting the 64-bit two's complement integer `a' to
1215 | the quadruple-precision floating-point format.  The conversion is performed
1216 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1217 *----------------------------------------------------------------------------*/
1218
1219 float128 int64_to_float128( int64 a STATUS_PARAM )
1220 {
1221     flag zSign;
1222     uint64 absA;
1223     int8 shiftCount;
1224     int32 zExp;
1225     bits64 zSig0, zSig1;
1226
1227     if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
1228     zSign = ( a < 0 );
1229     absA = zSign ? - a : a;
1230     shiftCount = countLeadingZeros64( absA ) + 49;
1231     zExp = 0x406E - shiftCount;
1232     if ( 64 <= shiftCount ) {
1233         zSig1 = 0;
1234         zSig0 = absA;
1235         shiftCount -= 64;
1236     }
1237     else {
1238         zSig1 = absA;
1239         zSig0 = 0;
1240     }
1241     shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
1242     return packFloat128( zSign, zExp, zSig0, zSig1 );
1243
1244 }
1245
1246 #endif
1247
1248 /*----------------------------------------------------------------------------
1249 | Returns the result of converting the single-precision floating-point value
1250 | `a' to the 32-bit two's complement integer format.  The conversion is
1251 | performed according to the IEC/IEEE Standard for Binary Floating-Point
1252 | Arithmetic---which means in particular that the conversion is rounded
1253 | according to the current rounding mode.  If `a' is a NaN, the largest
1254 | positive integer is returned.  Otherwise, if the conversion overflows, the
1255 | largest integer with the same sign as `a' is returned.
1256 *----------------------------------------------------------------------------*/
1257
1258 int32 float32_to_int32( float32 a STATUS_PARAM )
1259 {
1260     flag aSign;
1261     int16 aExp, shiftCount;
1262     bits32 aSig;
1263     bits64 aSig64;
1264
1265     aSig = extractFloat32Frac( a );
1266     aExp = extractFloat32Exp( a );
1267     aSign = extractFloat32Sign( a );
1268     if ( ( aExp == 0xFF ) && aSig ) aSign = 0;
1269     if ( aExp ) aSig |= 0x00800000;
1270     shiftCount = 0xAF - aExp;
1271     aSig64 = aSig;
1272     aSig64 <<= 32;
1273     if ( 0 < shiftCount ) shift64RightJamming( aSig64, shiftCount, &aSig64 );
1274     return roundAndPackInt32( aSign, aSig64 STATUS_VAR );
1275
1276 }
1277
1278 /*----------------------------------------------------------------------------
1279 | Returns the result of converting the single-precision floating-point value
1280 | `a' to the 32-bit two's complement integer format.  The conversion is
1281 | performed according to the IEC/IEEE Standard for Binary Floating-Point
1282 | Arithmetic, except that the conversion is always rounded toward zero.
1283 | If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
1284 | the conversion overflows, the largest integer with the same sign as `a' is
1285 | returned.
1286 *----------------------------------------------------------------------------*/
1287
1288 int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
1289 {
1290     flag aSign;
1291     int16 aExp, shiftCount;
1292     bits32 aSig;
1293     int32 z;
1294
1295     aSig = extractFloat32Frac( a );
1296     aExp = extractFloat32Exp( a );
1297     aSign = extractFloat32Sign( a );
1298     shiftCount = aExp - 0x9E;
1299     if ( 0 <= shiftCount ) {
1300         if ( a != 0xCF000000 ) {
1301             float_raise( float_flag_invalid STATUS_VAR);
1302             if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF;
1303         }
1304         return (sbits32) 0x80000000;
1305     }
1306     else if ( aExp <= 0x7E ) {
1307         if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
1308         return 0;
1309     }
1310     aSig = ( aSig | 0x00800000 )<<8;
1311     z = aSig>>( - shiftCount );
1312     if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
1313         STATUS(float_exception_flags) |= float_flag_inexact;
1314     }
1315     if ( aSign ) z = - z;
1316     return z;
1317
1318 }
1319
1320 /*----------------------------------------------------------------------------
1321 | Returns the result of converting the single-precision floating-point value
1322 | `a' to the 64-bit two's complement integer format.  The conversion is
1323 | performed according to the IEC/IEEE Standard for Binary Floating-Point
1324 | Arithmetic---which means in particular that the conversion is rounded
1325 | according to the current rounding mode.  If `a' is a NaN, the largest
1326 | positive integer is returned.  Otherwise, if the conversion overflows, the
1327 | largest integer with the same sign as `a' is returned.
1328 *----------------------------------------------------------------------------*/
1329
1330 int64 float32_to_int64( float32 a STATUS_PARAM )
1331 {
1332     flag aSign;
1333     int16 aExp, shiftCount;
1334     bits32 aSig;
1335     bits64 aSig64, aSigExtra;
1336
1337     aSig = extractFloat32Frac( a );
1338     aExp = extractFloat32Exp( a );
1339     aSign = extractFloat32Sign( a );
1340     shiftCount = 0xBE - aExp;
1341     if ( shiftCount < 0 ) {
1342         float_raise( float_flag_invalid STATUS_VAR);
1343         if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
1344             return LIT64( 0x7FFFFFFFFFFFFFFF );
1345         }
1346         return (sbits64) LIT64( 0x8000000000000000 );
1347     }
1348     if ( aExp ) aSig |= 0x00800000;
1349     aSig64 = aSig;
1350     aSig64 <<= 40;
1351     shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra );
1352     return roundAndPackInt64( aSign, aSig64, aSigExtra STATUS_VAR );
1353
1354 }
1355
1356 /*----------------------------------------------------------------------------
1357 | Returns the result of converting the single-precision floating-point value
1358 | `a' to the 64-bit two's complement integer format.  The conversion is
1359 | performed according to the IEC/IEEE Standard for Binary Floating-Point
1360 | Arithmetic, except that the conversion is always rounded toward zero.  If
1361 | `a' is a NaN, the largest positive integer is returned.  Otherwise, if the
1362 | conversion overflows, the largest integer with the same sign as `a' is
1363 | returned.
1364 *----------------------------------------------------------------------------*/
1365
1366 int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
1367 {
1368     flag aSign;
1369     int16 aExp, shiftCount;
1370     bits32 aSig;
1371     bits64 aSig64;
1372     int64 z;
1373
1374     aSig = extractFloat32Frac( a );
1375     aExp = extractFloat32Exp( a );
1376     aSign = extractFloat32Sign( a );
1377     shiftCount = aExp - 0xBE;
1378     if ( 0 <= shiftCount ) {
1379         if ( a != 0xDF000000 ) {
1380             float_raise( float_flag_invalid STATUS_VAR);
1381             if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
1382                 return LIT64( 0x7FFFFFFFFFFFFFFF );
1383             }
1384         }
1385         return (sbits64) LIT64( 0x8000000000000000 );
1386     }
1387     else if ( aExp <= 0x7E ) {
1388         if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
1389         return 0;
1390     }
1391     aSig64 = aSig | 0x00800000;
1392     aSig64 <<= 40;
1393     z = aSig64>>( - shiftCount );
1394     if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) {
1395         STATUS(float_exception_flags) |= float_flag_inexact;
1396     }
1397     if ( aSign ) z = - z;
1398     return z;
1399
1400 }
1401
1402 /*----------------------------------------------------------------------------
1403 | Returns the result of converting the single-precision floating-point value
1404 | `a' to the double-precision floating-point format.  The conversion is
1405 | performed according to the IEC/IEEE Standard for Binary Floating-Point
1406 | Arithmetic.
1407 *----------------------------------------------------------------------------*/
1408
1409 float64 float32_to_float64( float32 a STATUS_PARAM )
1410 {
1411     flag aSign;
1412     int16 aExp;
1413     bits32 aSig;
1414
1415     aSig = extractFloat32Frac( a );
1416     aExp = extractFloat32Exp( a );
1417     aSign = extractFloat32Sign( a );
1418     if ( aExp == 0xFF ) {
1419         if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR ));
1420         return packFloat64( aSign, 0x7FF, 0 );
1421     }
1422     if ( aExp == 0 ) {
1423         if ( aSig == 0 ) return packFloat64( aSign, 0, 0 );
1424         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1425         --aExp;
1426     }
1427     return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 );
1428
1429 }
1430
1431 #ifdef FLOATX80
1432
1433 /*----------------------------------------------------------------------------
1434 | Returns the result of converting the single-precision floating-point value
1435 | `a' to the extended double-precision floating-point format.  The conversion
1436 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
1437 | Arithmetic.
1438 *----------------------------------------------------------------------------*/
1439
1440 floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
1441 {
1442     flag aSign;
1443     int16 aExp;
1444     bits32 aSig;
1445
1446     aSig = extractFloat32Frac( a );
1447     aExp = extractFloat32Exp( a );
1448     aSign = extractFloat32Sign( a );
1449     if ( aExp == 0xFF ) {
1450         if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) );
1451         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
1452     }
1453     if ( aExp == 0 ) {
1454         if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
1455         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1456     }
1457     aSig |= 0x00800000;
1458     return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 );
1459
1460 }
1461
1462 #endif
1463
1464 #ifdef FLOAT128
1465
1466 /*----------------------------------------------------------------------------
1467 | Returns the result of converting the single-precision floating-point value
1468 | `a' to the double-precision floating-point format.  The conversion is
1469 | performed according to the IEC/IEEE Standard for Binary Floating-Point
1470 | Arithmetic.
1471 *----------------------------------------------------------------------------*/
1472
1473 float128 float32_to_float128( float32 a STATUS_PARAM )
1474 {
1475     flag aSign;
1476     int16 aExp;
1477     bits32 aSig;
1478
1479     aSig = extractFloat32Frac( a );
1480     aExp = extractFloat32Exp( a );
1481     aSign = extractFloat32Sign( a );
1482     if ( aExp == 0xFF ) {
1483         if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) );
1484         return packFloat128( aSign, 0x7FFF, 0, 0 );
1485     }
1486     if ( aExp == 0 ) {
1487         if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 );
1488         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1489         --aExp;
1490     }
1491     return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 );
1492
1493 }
1494
1495 #endif
1496
1497 /*----------------------------------------------------------------------------
1498 | Rounds the single-precision floating-point value `a' to an integer, and
1499 | returns the result as a single-precision floating-point value.  The
1500 | operation is performed according to the IEC/IEEE Standard for Binary
1501 | Floating-Point Arithmetic.
1502 *----------------------------------------------------------------------------*/
1503
1504 float32 float32_round_to_int( float32 a STATUS_PARAM)
1505 {
1506     flag aSign;
1507     int16 aExp;
1508     bits32 lastBitMask, roundBitsMask;
1509     int8 roundingMode;
1510     float32 z;
1511
1512     aExp = extractFloat32Exp( a );
1513     if ( 0x96 <= aExp ) {
1514         if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) {
1515             return propagateFloat32NaN( a, a STATUS_VAR );
1516         }
1517         return a;
1518     }
1519     if ( aExp <= 0x7E ) {
1520         if ( (bits32) ( a<<1 ) == 0 ) return a;
1521         STATUS(float_exception_flags) |= float_flag_inexact;
1522         aSign = extractFloat32Sign( a );
1523         switch ( STATUS(float_rounding_mode) ) {
1524          case float_round_nearest_even:
1525             if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
1526                 return packFloat32( aSign, 0x7F, 0 );
1527             }
1528             break;
1529          case float_round_down:
1530             return aSign ? 0xBF800000 : 0;
1531          case float_round_up:
1532             return aSign ? 0x80000000 : 0x3F800000;
1533         }
1534         return packFloat32( aSign, 0, 0 );
1535     }
1536     lastBitMask = 1;
1537     lastBitMask <<= 0x96 - aExp;
1538     roundBitsMask = lastBitMask - 1;
1539     z = a;
1540     roundingMode = STATUS(float_rounding_mode);
1541     if ( roundingMode == float_round_nearest_even ) {
1542         z += lastBitMask>>1;
1543         if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
1544     }
1545     else if ( roundingMode != float_round_to_zero ) {
1546         if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) {
1547             z += roundBitsMask;
1548         }
1549     }
1550     z &= ~ roundBitsMask;
1551     if ( z != a ) STATUS(float_exception_flags) |= float_flag_inexact;
1552     return z;
1553
1554 }
1555
1556 /*----------------------------------------------------------------------------
1557 | Returns the result of adding the absolute values of the single-precision
1558 | floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
1559 | before being returned.  `zSign' is ignored if the result is a NaN.
1560 | The addition is performed according to the IEC/IEEE Standard for Binary
1561 | Floating-Point Arithmetic.
1562 *----------------------------------------------------------------------------*/
1563
1564 static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
1565 {
1566     int16 aExp, bExp, zExp;
1567     bits32 aSig, bSig, zSig;
1568     int16 expDiff;
1569
1570     aSig = extractFloat32Frac( a );
1571     aExp = extractFloat32Exp( a );
1572     bSig = extractFloat32Frac( b );
1573     bExp = extractFloat32Exp( b );
1574     expDiff = aExp - bExp;
1575     aSig <<= 6;
1576     bSig <<= 6;
1577     if ( 0 < expDiff ) {
1578         if ( aExp == 0xFF ) {
1579             if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1580             return a;
1581         }
1582         if ( bExp == 0 ) {
1583             --expDiff;
1584         }
1585         else {
1586             bSig |= 0x20000000;
1587         }
1588         shift32RightJamming( bSig, expDiff, &bSig );
1589         zExp = aExp;
1590     }
1591     else if ( expDiff < 0 ) {
1592         if ( bExp == 0xFF ) {
1593             if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1594             return packFloat32( zSign, 0xFF, 0 );
1595         }
1596         if ( aExp == 0 ) {
1597             ++expDiff;
1598         }
1599         else {
1600             aSig |= 0x20000000;
1601         }
1602         shift32RightJamming( aSig, - expDiff, &aSig );
1603         zExp = bExp;
1604     }
1605     else {
1606         if ( aExp == 0xFF ) {
1607             if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1608             return a;
1609         }
1610         if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
1611         zSig = 0x40000000 + aSig + bSig;
1612         zExp = aExp;
1613         goto roundAndPack;
1614     }
1615     aSig |= 0x20000000;
1616     zSig = ( aSig + bSig )<<1;
1617     --zExp;
1618     if ( (sbits32) zSig < 0 ) {
1619         zSig = aSig + bSig;
1620         ++zExp;
1621     }
1622  roundAndPack:
1623     return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
1624
1625 }
1626
1627 /*----------------------------------------------------------------------------
1628 | Returns the result of subtracting the absolute values of the single-
1629 | precision floating-point values `a' and `b'.  If `zSign' is 1, the
1630 | difference is negated before being returned.  `zSign' is ignored if the
1631 | result is a NaN.  The subtraction is performed according to the IEC/IEEE
1632 | Standard for Binary Floating-Point Arithmetic.
1633 *----------------------------------------------------------------------------*/
1634
1635 static float32 subFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
1636 {
1637     int16 aExp, bExp, zExp;
1638     bits32 aSig, bSig, zSig;
1639     int16 expDiff;
1640
1641     aSig = extractFloat32Frac( a );
1642     aExp = extractFloat32Exp( a );
1643     bSig = extractFloat32Frac( b );
1644     bExp = extractFloat32Exp( b );
1645     expDiff = aExp - bExp;
1646     aSig <<= 7;
1647     bSig <<= 7;
1648     if ( 0 < expDiff ) goto aExpBigger;
1649     if ( expDiff < 0 ) goto bExpBigger;
1650     if ( aExp == 0xFF ) {
1651         if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1652         float_raise( float_flag_invalid STATUS_VAR);
1653         return float32_default_nan;
1654     }
1655     if ( aExp == 0 ) {
1656         aExp = 1;
1657         bExp = 1;
1658     }
1659     if ( bSig < aSig ) goto aBigger;
1660     if ( aSig < bSig ) goto bBigger;
1661     return packFloat32( STATUS(float_rounding_mode) == float_round_down, 0, 0 );
1662  bExpBigger:
1663     if ( bExp == 0xFF ) {
1664         if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1665         return packFloat32( zSign ^ 1, 0xFF, 0 );
1666     }
1667     if ( aExp == 0 ) {
1668         ++expDiff;
1669     }
1670     else {
1671         aSig |= 0x40000000;
1672     }
1673     shift32RightJamming( aSig, - expDiff, &aSig );
1674     bSig |= 0x40000000;
1675  bBigger:
1676     zSig = bSig - aSig;
1677     zExp = bExp;
1678     zSign ^= 1;
1679     goto normalizeRoundAndPack;
1680  aExpBigger:
1681     if ( aExp == 0xFF ) {
1682         if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1683         return a;
1684     }
1685     if ( bExp == 0 ) {
1686         --expDiff;
1687     }
1688     else {
1689         bSig |= 0x40000000;
1690     }
1691     shift32RightJamming( bSig, expDiff, &bSig );
1692     aSig |= 0x40000000;
1693  aBigger:
1694     zSig = aSig - bSig;
1695     zExp = aExp;
1696  normalizeRoundAndPack:
1697     --zExp;
1698     return normalizeRoundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
1699
1700 }
1701
1702 /*----------------------------------------------------------------------------
1703 | Returns the result of adding the single-precision floating-point values `a'
1704 | and `b'.  The operation is performed according to the IEC/IEEE Standard for
1705 | Binary Floating-Point Arithmetic.
1706 *----------------------------------------------------------------------------*/
1707
1708 float32 float32_add( float32 a, float32 b STATUS_PARAM )
1709 {
1710     flag aSign, bSign;
1711
1712     aSign = extractFloat32Sign( a );
1713     bSign = extractFloat32Sign( b );
1714     if ( aSign == bSign ) {
1715         return addFloat32Sigs( a, b, aSign STATUS_VAR);
1716     }
1717     else {
1718         return subFloat32Sigs( a, b, aSign STATUS_VAR );
1719     }
1720
1721 }
1722
1723 /*----------------------------------------------------------------------------
1724 | Returns the result of subtracting the single-precision floating-point values
1725 | `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
1726 | for Binary Floating-Point Arithmetic.
1727 *----------------------------------------------------------------------------*/
1728
1729 float32 float32_sub( float32 a, float32 b STATUS_PARAM )
1730 {
1731     flag aSign, bSign;
1732
1733     aSign = extractFloat32Sign( a );
1734     bSign = extractFloat32Sign( b );
1735     if ( aSign == bSign ) {
1736         return subFloat32Sigs( a, b, aSign STATUS_VAR );
1737     }
1738     else {
1739         return addFloat32Sigs( a, b, aSign STATUS_VAR );
1740     }
1741
1742 }
1743
1744 /*----------------------------------------------------------------------------
1745 | Returns the result of multiplying the single-precision floating-point values
1746 | `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
1747 | for Binary Floating-Point Arithmetic.
1748 *----------------------------------------------------------------------------*/
1749
1750 float32 float32_mul( float32 a, float32 b STATUS_PARAM )
1751 {
1752     flag aSign, bSign, zSign;
1753     int16 aExp, bExp, zExp;
1754     bits32 aSig, bSig;
1755     bits64 zSig64;
1756     bits32 zSig;
1757
1758     aSig = extractFloat32Frac( a );
1759     aExp = extractFloat32Exp( a );
1760     aSign = extractFloat32Sign( a );
1761     bSig = extractFloat32Frac( b );
1762     bExp = extractFloat32Exp( b );
1763     bSign = extractFloat32Sign( b );
1764     zSign = aSign ^ bSign;
1765     if ( aExp == 0xFF ) {
1766         if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
1767             return propagateFloat32NaN( a, b STATUS_VAR );
1768         }
1769         if ( ( bExp | bSig ) == 0 ) {
1770             float_raise( float_flag_invalid STATUS_VAR);
1771             return float32_default_nan;
1772         }
1773         return packFloat32( zSign, 0xFF, 0 );
1774     }
1775     if ( bExp == 0xFF ) {
1776         if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1777         if ( ( aExp | aSig ) == 0 ) {
1778             float_raise( float_flag_invalid STATUS_VAR);
1779             return float32_default_nan;
1780         }
1781         return packFloat32( zSign, 0xFF, 0 );
1782     }
1783     if ( aExp == 0 ) {
1784         if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
1785         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1786     }
1787     if ( bExp == 0 ) {
1788         if ( bSig == 0 ) return packFloat32( zSign, 0, 0 );
1789         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
1790     }
1791     zExp = aExp + bExp - 0x7F;
1792     aSig = ( aSig | 0x00800000 )<<7;
1793     bSig = ( bSig | 0x00800000 )<<8;
1794     shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 );
1795     zSig = zSig64;
1796     if ( 0 <= (sbits32) ( zSig<<1 ) ) {
1797         zSig <<= 1;
1798         --zExp;
1799     }
1800     return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
1801
1802 }
1803
1804 /*----------------------------------------------------------------------------
1805 | Returns the result of dividing the single-precision floating-point value `a'
1806 | by the corresponding value `b'.  The operation is performed according to the
1807 | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1808 *----------------------------------------------------------------------------*/
1809
1810 float32 float32_div( float32 a, float32 b STATUS_PARAM )
1811 {
1812     flag aSign, bSign, zSign;
1813     int16 aExp, bExp, zExp;
1814     bits32 aSig, bSig, zSig;
1815
1816     aSig = extractFloat32Frac( a );
1817     aExp = extractFloat32Exp( a );
1818     aSign = extractFloat32Sign( a );
1819     bSig = extractFloat32Frac( b );
1820     bExp = extractFloat32Exp( b );
1821     bSign = extractFloat32Sign( b );
1822     zSign = aSign ^ bSign;
1823     if ( aExp == 0xFF ) {
1824         if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1825         if ( bExp == 0xFF ) {
1826             if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1827             float_raise( float_flag_invalid STATUS_VAR);
1828             return float32_default_nan;
1829         }
1830         return packFloat32( zSign, 0xFF, 0 );
1831     }
1832     if ( bExp == 0xFF ) {
1833         if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1834         return packFloat32( zSign, 0, 0 );
1835     }
1836     if ( bExp == 0 ) {
1837         if ( bSig == 0 ) {
1838             if ( ( aExp | aSig ) == 0 ) {
1839                 float_raise( float_flag_invalid STATUS_VAR);
1840                 return float32_default_nan;
1841             }
1842             float_raise( float_flag_divbyzero STATUS_VAR);
1843             return packFloat32( zSign, 0xFF, 0 );
1844         }
1845         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
1846     }
1847     if ( aExp == 0 ) {
1848         if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
1849         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1850     }
1851     zExp = aExp - bExp + 0x7D;
1852     aSig = ( aSig | 0x00800000 )<<7;
1853     bSig = ( bSig | 0x00800000 )<<8;
1854     if ( bSig <= ( aSig + aSig ) ) {
1855         aSig >>= 1;
1856         ++zExp;
1857     }
1858     zSig = ( ( (bits64) aSig )<<32 ) / bSig;
1859     if ( ( zSig & 0x3F ) == 0 ) {
1860         zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 );
1861     }
1862     return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
1863
1864 }
1865
1866 /*----------------------------------------------------------------------------
1867 | Returns the remainder of the single-precision floating-point value `a'
1868 | with respect to the corresponding value `b'.  The operation is performed
1869 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1870 *----------------------------------------------------------------------------*/
1871
1872 float32 float32_rem( float32 a, float32 b STATUS_PARAM )
1873 {
1874     flag aSign, bSign, zSign;
1875     int16 aExp, bExp, expDiff;
1876     bits32 aSig, bSig;
1877     bits32 q;
1878     bits64 aSig64, bSig64, q64;
1879     bits32 alternateASig;
1880     sbits32 sigMean;
1881
1882     aSig = extractFloat32Frac( a );
1883     aExp = extractFloat32Exp( a );
1884     aSign = extractFloat32Sign( a );
1885     bSig = extractFloat32Frac( b );
1886     bExp = extractFloat32Exp( b );
1887     bSign = extractFloat32Sign( b );
1888     if ( aExp == 0xFF ) {
1889         if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
1890             return propagateFloat32NaN( a, b STATUS_VAR );
1891         }
1892         float_raise( float_flag_invalid STATUS_VAR);
1893         return float32_default_nan;
1894     }
1895     if ( bExp == 0xFF ) {
1896         if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1897         return a;
1898     }
1899     if ( bExp == 0 ) {
1900         if ( bSig == 0 ) {
1901             float_raise( float_flag_invalid STATUS_VAR);
1902             return float32_default_nan;
1903         }
1904         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
1905     }
1906     if ( aExp == 0 ) {
1907         if ( aSig == 0 ) return a;
1908         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1909     }
1910     expDiff = aExp - bExp;
1911     aSig |= 0x00800000;
1912     bSig |= 0x00800000;
1913     if ( expDiff < 32 ) {
1914         aSig <<= 8;
1915         bSig <<= 8;
1916         if ( expDiff < 0 ) {
1917             if ( expDiff < -1 ) return a;
1918             aSig >>= 1;
1919         }
1920         q = ( bSig <= aSig );
1921         if ( q ) aSig -= bSig;
1922         if ( 0 < expDiff ) {
1923             q = ( ( (bits64) aSig )<<32 ) / bSig;
1924             q >>= 32 - expDiff;
1925             bSig >>= 2;
1926             aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
1927         }
1928         else {
1929             aSig >>= 2;
1930             bSig >>= 2;
1931         }
1932     }
1933     else {
1934         if ( bSig <= aSig ) aSig -= bSig;
1935         aSig64 = ( (bits64) aSig )<<40;
1936         bSig64 = ( (bits64) bSig )<<40;
1937         expDiff -= 64;
1938         while ( 0 < expDiff ) {
1939             q64 = estimateDiv128To64( aSig64, 0, bSig64 );
1940             q64 = ( 2 < q64 ) ? q64 - 2 : 0;
1941             aSig64 = - ( ( bSig * q64 )<<38 );
1942             expDiff -= 62;
1943         }
1944         expDiff += 64;
1945         q64 = estimateDiv128To64( aSig64, 0, bSig64 );
1946         q64 = ( 2 < q64 ) ? q64 - 2 : 0;
1947         q = q64>>( 64 - expDiff );
1948         bSig <<= 6;
1949         aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q;
1950     }
1951     do {
1952         alternateASig = aSig;
1953         ++q;
1954         aSig -= bSig;
1955     } while ( 0 <= (sbits32) aSig );
1956     sigMean = aSig + alternateASig;
1957     if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
1958         aSig = alternateASig;
1959     }
1960     zSign = ( (sbits32) aSig < 0 );
1961     if ( zSign ) aSig = - aSig;
1962     return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig STATUS_VAR );
1963
1964 }
1965
1966 /*----------------------------------------------------------------------------
1967 | Returns the square root of the single-precision floating-point value `a'.
1968 | The operation is performed according to the IEC/IEEE Standard for Binary
1969 | Floating-Point Arithmetic.
1970 *----------------------------------------------------------------------------*/
1971
1972 float32 float32_sqrt( float32 a STATUS_PARAM )
1973 {
1974     flag aSign;
1975     int16 aExp, zExp;
1976     bits32 aSig, zSig;
1977     bits64 rem, term;
1978
1979     aSig = extractFloat32Frac( a );
1980     aExp = extractFloat32Exp( a );
1981     aSign = extractFloat32Sign( a );
1982     if ( aExp == 0xFF ) {
1983         if ( aSig ) return propagateFloat32NaN( a, 0 STATUS_VAR );
1984         if ( ! aSign ) return a;
1985         float_raise( float_flag_invalid STATUS_VAR);
1986         return float32_default_nan;
1987     }
1988     if ( aSign ) {
1989         if ( ( aExp | aSig ) == 0 ) return a;
1990         float_raise( float_flag_invalid STATUS_VAR);
1991         return float32_default_nan;
1992     }
1993     if ( aExp == 0 ) {
1994         if ( aSig == 0 ) return 0;
1995         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1996     }
1997     zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;
1998     aSig = ( aSig | 0x00800000 )<<8;
1999     zSig = estimateSqrt32( aExp, aSig ) + 2;
2000     if ( ( zSig & 0x7F ) <= 5 ) {
2001         if ( zSig < 2 ) {
2002             zSig = 0x7FFFFFFF;
2003             goto roundAndPack;
2004         }
2005         aSig >>= aExp & 1;
2006         term = ( (bits64) zSig ) * zSig;
2007         rem = ( ( (bits64) aSig )<<32 ) - term;
2008         while ( (sbits64) rem < 0 ) {
2009             --zSig;
2010             rem += ( ( (bits64) zSig )<<1 ) | 1;
2011         }
2012         zSig |= ( rem != 0 );
2013     }
2014     shift32RightJamming( zSig, 1, &zSig );
2015  roundAndPack:
2016     return roundAndPackFloat32( 0, zExp, zSig STATUS_VAR );
2017
2018 }
2019
2020 /*----------------------------------------------------------------------------
2021 | Returns 1 if the single-precision floating-point value `a' is equal to
2022 | the corresponding value `b', and 0 otherwise.  The comparison is performed
2023 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2024 *----------------------------------------------------------------------------*/
2025
2026 flag float32_eq( float32 a, float32 b STATUS_PARAM )
2027 {
2028
2029     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2030          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2031        ) {
2032         if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
2033             float_raise( float_flag_invalid STATUS_VAR);
2034         }
2035         return 0;
2036     }
2037     return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
2038
2039 }
2040
2041 /*----------------------------------------------------------------------------
2042 | Returns 1 if the single-precision floating-point value `a' is less than
2043 | or equal to the corresponding value `b', and 0 otherwise.  The comparison
2044 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
2045 | Arithmetic.
2046 *----------------------------------------------------------------------------*/
2047
2048 flag float32_le( float32 a, float32 b STATUS_PARAM )
2049 {
2050     flag aSign, bSign;
2051
2052     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2053          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2054        ) {
2055         float_raise( float_flag_invalid STATUS_VAR);
2056         return 0;
2057     }
2058     aSign = extractFloat32Sign( a );
2059     bSign = extractFloat32Sign( b );
2060     if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
2061     return ( a == b ) || ( aSign ^ ( a < b ) );
2062
2063 }
2064
2065 /*----------------------------------------------------------------------------
2066 | Returns 1 if the single-precision floating-point value `a' is less than
2067 | the corresponding value `b', and 0 otherwise.  The comparison is performed
2068 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2069 *----------------------------------------------------------------------------*/
2070
2071 flag float32_lt( float32 a, float32 b STATUS_PARAM )
2072 {
2073     flag aSign, bSign;
2074
2075     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2076          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2077        ) {
2078         float_raise( float_flag_invalid STATUS_VAR);
2079         return 0;
2080     }
2081     aSign = extractFloat32Sign( a );
2082     bSign = extractFloat32Sign( b );
2083     if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
2084     return ( a != b ) && ( aSign ^ ( a < b ) );
2085
2086 }
2087
2088 /*----------------------------------------------------------------------------
2089 | Returns 1 if the single-precision floating-point value `a' is equal to
2090 | the corresponding value `b', and 0 otherwise.  The invalid exception is
2091 | raised if either operand is a NaN.  Otherwise, the comparison is performed
2092 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2093 *----------------------------------------------------------------------------*/
2094
2095 flag float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
2096 {
2097
2098     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2099          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2100        ) {
2101         float_raise( float_flag_invalid STATUS_VAR);
2102         return 0;
2103     }
2104     return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
2105
2106 }
2107
2108 /*----------------------------------------------------------------------------
2109 | Returns 1 if the single-precision floating-point value `a' is less than or
2110 | equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
2111 | cause an exception.  Otherwise, the comparison is performed according to the
2112 | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2113 *----------------------------------------------------------------------------*/
2114
2115 flag float32_le_quiet( float32 a, float32 b STATUS_PARAM )
2116 {
2117     flag aSign, bSign;
2118
2119     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2120          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2121        ) {
2122         if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
2123             float_raise( float_flag_invalid STATUS_VAR);
2124         }
2125         return 0;
2126     }
2127     aSign = extractFloat32Sign( a );
2128     bSign = extractFloat32Sign( b );
2129     if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
2130     return ( a == b ) || ( aSign ^ ( a < b ) );
2131
2132 }
2133
2134 /*----------------------------------------------------------------------------
2135 | Returns 1 if the single-precision floating-point value `a' is less than
2136 | the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
2137 | exception.  Otherwise, the comparison is performed according to the IEC/IEEE
2138 | Standard for Binary Floating-Point Arithmetic.
2139 *----------------------------------------------------------------------------*/
2140
2141 flag float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
2142 {
2143     flag aSign, bSign;
2144
2145     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2146          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2147        ) {
2148         if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
2149             float_raise( float_flag_invalid STATUS_VAR);
2150         }
2151         return 0;
2152     }
2153     aSign = extractFloat32Sign( a );
2154     bSign = extractFloat32Sign( b );
2155     if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
2156     return ( a != b ) && ( aSign ^ ( a < b ) );
2157
2158 }
2159
2160 /*----------------------------------------------------------------------------
2161 | Returns the result of converting the double-precision floating-point value
2162 | `a' to the 32-bit two's complement integer format.  The conversion is
2163 | performed according to the IEC/IEEE Standard for Binary Floating-Point
2164 | Arithmetic---which means in particular that the conversion is rounded
2165 | according to the current rounding mode.  If `a' is a NaN, the largest
2166 | positive integer is returned.  Otherwise, if the conversion overflows, the
2167 | largest integer with the same sign as `a' is returned.
2168 *----------------------------------------------------------------------------*/
2169
2170 int32 float64_to_int32( float64 a STATUS_PARAM )
2171 {
2172     flag aSign;
2173     int16 aExp, shiftCount;
2174     bits64 aSig;
2175
2176     aSig = extractFloat64Frac( a );
2177     aExp = extractFloat64Exp( a );
2178     aSign = extractFloat64Sign( a );
2179     if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
2180     if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
2181     shiftCount = 0x42C - aExp;
2182     if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
2183     return roundAndPackInt32( aSign, aSig STATUS_VAR );
2184
2185 }
2186
2187 /*----------------------------------------------------------------------------
2188 | Returns the result of converting the double-precision floating-point value
2189 | `a' to the 32-bit two's complement integer format.  The conversion is
2190 | performed according to the IEC/IEEE Standard for Binary Floating-Point
2191 | Arithmetic, except that the conversion is always rounded toward zero.
2192 | If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
2193 | the conversion overflows, the largest integer with the same sign as `a' is
2194 | returned.
2195 *----------------------------------------------------------------------------*/
2196
2197 int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
2198 {
2199     flag aSign;
2200     int16 aExp, shiftCount;
2201     bits64 aSig, savedASig;
2202     int32 z;
2203
2204     aSig = extractFloat64Frac( a );
2205     aExp = extractFloat64Exp( a );
2206     aSign = extractFloat64Sign( a );
2207     if ( 0x41E < aExp ) {
2208         if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
2209         goto invalid;
2210     }
2211     else if ( aExp < 0x3FF ) {
2212         if ( aExp || aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
2213         return 0;
2214     }
2215     aSig |= LIT64( 0x0010000000000000 );
2216     shiftCount = 0x433 - aExp;
2217     savedASig = aSig;
2218     aSig >>= shiftCount;
2219     z = aSig;
2220     if ( aSign ) z = - z;
2221     if ( ( z < 0 ) ^ aSign ) {
2222  invalid:
2223         float_raise( float_flag_invalid STATUS_VAR);
2224         return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
2225     }
2226     if ( ( aSig<<shiftCount ) != savedASig ) {
2227         STATUS(float_exception_flags) |= float_flag_inexact;
2228     }
2229     return z;
2230
2231 }
2232
2233 /*----------------------------------------------------------------------------
2234 | Returns the result of converting the double-precision floating-point value
2235 | `a' to the 64-bit two's complement integer format.  The conversion is
2236 | performed according to the IEC/IEEE Standard for Binary Floating-Point
2237 | Arithmetic---which means in particular that the conversion is rounded
2238 | according to the current rounding mode.  If `a' is a NaN, the largest
2239 | positive integer is returned.  Otherwise, if the conversion overflows, the
2240 | largest integer with the same sign as `a' is returned.
2241 *----------------------------------------------------------------------------*/
2242
2243 int64 float64_to_int64( float64 a STATUS_PARAM )
2244 {
2245     flag aSign;
2246     int16 aExp, shiftCount;
2247     bits64 aSig, aSigExtra;
2248
2249     aSig = extractFloat64Frac( a );
2250     aExp = extractFloat64Exp( a );
2251     aSign = extractFloat64Sign( a );
2252     if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
2253     shiftCount = 0x433 - aExp;
2254     if ( shiftCount <= 0 ) {
2255         if ( 0x43E < aExp ) {
2256             float_raise( float_flag_invalid STATUS_VAR);
2257             if (    ! aSign
2258                  || (    ( aExp == 0x7FF )
2259                       && ( aSig != LIT64( 0x0010000000000000 ) ) )
2260                ) {
2261                 return LIT64( 0x7FFFFFFFFFFFFFFF );
2262             }
2263             return (sbits64) LIT64( 0x8000000000000000 );
2264         }
2265         aSigExtra = 0;
2266         aSig <<= - shiftCount;
2267     }
2268     else {
2269         shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
2270     }
2271     return roundAndPackInt64( aSign, aSig, aSigExtra STATUS_VAR );
2272
2273 }
2274
2275 /*----------------------------------------------------------------------------
2276 | Returns the result of converting the double-precision floating-point value
2277 | `a' to the 64-bit two's complement integer format.  The conversion is
2278 | performed according to the IEC/IEEE Standard for Binary Floating-Point
2279 | Arithmetic, except that the conversion is always rounded toward zero.
2280 | If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
2281 | the conversion overflows, the largest integer with the same sign as `a' is
2282 | returned.
2283 *----------------------------------------------------------------------------*/
2284
2285 int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
2286 {
2287     flag aSign;
2288     int16 aExp, shiftCount;
2289     bits64 aSig;
2290     int64 z;
2291
2292     aSig = extractFloat64Frac( a );
2293     aExp = extractFloat64Exp( a );
2294     aSign = extractFloat64Sign( a );
2295     if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
2296     shiftCount = aExp - 0x433;
2297     if ( 0 <= shiftCount ) {
2298         if ( 0x43E <= aExp ) {
2299             if ( a != LIT64( 0xC3E0000000000000 ) ) {
2300                 float_raise( float_flag_invalid STATUS_VAR);
2301                 if (    ! aSign
2302                      || (    ( aExp == 0x7FF )
2303                           && ( aSig != LIT64( 0x0010000000000000 ) ) )
2304                    ) {
2305                     return LIT64( 0x7FFFFFFFFFFFFFFF );
2306                 }
2307             }
2308             return (sbits64) LIT64( 0x8000000000000000 );
2309         }
2310         z = aSig<<shiftCount;
2311     }
2312     else {
2313         if ( aExp < 0x3FE ) {
2314             if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
2315             return 0;
2316         }
2317         z = aSig>>( - shiftCount );
2318         if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) {
2319             STATUS(float_exception_flags) |= float_flag_inexact;
2320         }
2321     }
2322     if ( aSign ) z = - z;
2323     return z;
2324
2325 }
2326
2327 /*----------------------------------------------------------------------------
2328 | Returns the result of converting the double-precision floating-point value
2329 | `a' to the single-precision floating-point format.  The conversion is
2330 | performed according to the IEC/IEEE Standard for Binary Floating-Point
2331 | Arithmetic.
2332 *----------------------------------------------------------------------------*/
2333
2334 float32 float64_to_float32( float64 a STATUS_PARAM )
2335 {
2336     flag aSign;
2337     int16 aExp;
2338     bits64 aSig;
2339     bits32 zSig;
2340
2341     aSig = extractFloat64Frac( a );
2342     aExp = extractFloat64Exp( a );
2343     aSign = extractFloat64Sign( a );
2344     if ( aExp == 0x7FF ) {
2345         if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) );
2346         return packFloat32( aSign, 0xFF, 0 );
2347     }
2348     shift64RightJamming( aSig, 22, &aSig );
2349     zSig = aSig;
2350     if ( aExp || zSig ) {
2351         zSig |= 0x40000000;
2352         aExp -= 0x381;
2353     }
2354     return roundAndPackFloat32( aSign, aExp, zSig STATUS_VAR );
2355
2356 }
2357
2358 #ifdef FLOATX80
2359
2360 /*----------------------------------------------------------------------------
2361 | Returns the result of converting the double-precision floating-point value
2362 | `a' to the extended double-precision floating-point format.  The conversion
2363 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
2364 | Arithmetic.
2365 *----------------------------------------------------------------------------*/
2366
2367 floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
2368 {
2369     flag aSign;
2370     int16 aExp;
2371     bits64 aSig;
2372
2373     aSig = extractFloat64Frac( a );
2374     aExp = extractFloat64Exp( a );
2375     aSign = extractFloat64Sign( a );
2376     if ( aExp == 0x7FF ) {
2377         if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) );
2378         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
2379     }
2380     if ( aExp == 0 ) {
2381         if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
2382         normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2383     }
2384     return
2385         packFloatx80(
2386             aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 );
2387
2388 }
2389
2390 #endif
2391
2392 #ifdef FLOAT128
2393
2394 /*----------------------------------------------------------------------------
2395 | Returns the result of converting the double-precision floating-point value
2396 | `a' to the quadruple-precision floating-point format.  The conversion is
2397 | performed according to the IEC/IEEE Standard for Binary Floating-Point
2398 | Arithmetic.
2399 *----------------------------------------------------------------------------*/
2400
2401 float128 float64_to_float128( float64 a STATUS_PARAM )
2402 {
2403     flag aSign;
2404     int16 aExp;
2405     bits64 aSig, zSig0, zSig1;
2406
2407     aSig = extractFloat64Frac( a );
2408     aExp = extractFloat64Exp( a );
2409     aSign = extractFloat64Sign( a );
2410     if ( aExp == 0x7FF ) {
2411         if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) );
2412         return packFloat128( aSign, 0x7FFF, 0, 0 );
2413     }
2414     if ( aExp == 0 ) {
2415         if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 );
2416         normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2417         --aExp;
2418     }
2419     shift128Right( aSig, 0, 4, &zSig0, &zSig1 );
2420     return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 );
2421
2422 }
2423
2424 #endif
2425
2426 /*----------------------------------------------------------------------------
2427 | Rounds the double-precision floating-point value `a' to an integer, and
2428 | returns the result as a double-precision floating-point value.  The
2429 | operation is performed according to the IEC/IEEE Standard for Binary
2430 | Floating-Point Arithmetic.
2431 *----------------------------------------------------------------------------*/
2432
2433 float64 float64_round_to_int( float64 a STATUS_PARAM )
2434 {
2435     flag aSign;
2436     int16 aExp;
2437     bits64 lastBitMask, roundBitsMask;
2438     int8 roundingMode;
2439     float64 z;
2440
2441     aExp = extractFloat64Exp( a );
2442     if ( 0x433 <= aExp ) {
2443         if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) {
2444             return propagateFloat64NaN( a, a STATUS_VAR );
2445         }
2446         return a;
2447     }
2448     if ( aExp < 0x3FF ) {
2449         if ( (bits64) ( a<<1 ) == 0 ) return a;
2450         STATUS(float_exception_flags) |= float_flag_inexact;
2451         aSign = extractFloat64Sign( a );
2452         switch ( STATUS(float_rounding_mode) ) {
2453          case float_round_nearest_even:
2454             if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {
2455                 return packFloat64( aSign, 0x3FF, 0 );
2456             }
2457             break;
2458          case float_round_down:
2459             return aSign ? LIT64( 0xBFF0000000000000 ) : 0;
2460          case float_round_up:
2461             return
2462             aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 );
2463         }
2464         return packFloat64( aSign, 0, 0 );
2465     }
2466     lastBitMask = 1;
2467     lastBitMask <<= 0x433 - aExp;
2468     roundBitsMask = lastBitMask - 1;
2469     z = a;
2470     roundingMode = STATUS(float_rounding_mode);
2471     if ( roundingMode == float_round_nearest_even ) {
2472         z += lastBitMask>>1;
2473         if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
2474     }
2475     else if ( roundingMode != float_round_to_zero ) {
2476         if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) {
2477             z += roundBitsMask;
2478         }
2479     }
2480     z &= ~ roundBitsMask;
2481     if ( z != a ) STATUS(float_exception_flags) |= float_flag_inexact;
2482     return z;
2483
2484 }
2485
2486 /*----------------------------------------------------------------------------
2487 | Returns the result of adding the absolute values of the double-precision
2488 | floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
2489 | before being returned.  `zSign' is ignored if the result is a NaN.
2490 | The addition is performed according to the IEC/IEEE Standard for Binary
2491 | Floating-Point Arithmetic.
2492 *----------------------------------------------------------------------------*/
2493
2494 static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
2495 {
2496     int16 aExp, bExp, zExp;
2497     bits64 aSig, bSig, zSig;
2498     int16 expDiff;
2499
2500     aSig = extractFloat64Frac( a );
2501     aExp = extractFloat64Exp( a );
2502     bSig = extractFloat64Frac( b );
2503     bExp = extractFloat64Exp( b );
2504     expDiff = aExp - bExp;
2505     aSig <<= 9;
2506     bSig <<= 9;
2507     if ( 0 < expDiff ) {
2508         if ( aExp == 0x7FF ) {
2509             if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2510             return a;
2511         }
2512         if ( bExp == 0 ) {
2513             --expDiff;
2514         }
2515         else {
2516             bSig |= LIT64( 0x2000000000000000 );
2517         }
2518         shift64RightJamming( bSig, expDiff, &bSig );
2519         zExp = aExp;
2520     }
2521     else if ( expDiff < 0 ) {
2522         if ( bExp == 0x7FF ) {
2523             if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2524             return packFloat64( zSign, 0x7FF, 0 );
2525         }
2526         if ( aExp == 0 ) {
2527             ++expDiff;
2528         }
2529         else {
2530             aSig |= LIT64( 0x2000000000000000 );
2531         }
2532         shift64RightJamming( aSig, - expDiff, &aSig );
2533         zExp = bExp;
2534     }
2535     else {
2536         if ( aExp == 0x7FF ) {
2537             if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2538             return a;
2539         }
2540         if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 );
2541         zSig = LIT64( 0x4000000000000000 ) + aSig + bSig;
2542         zExp = aExp;
2543         goto roundAndPack;
2544     }
2545     aSig |= LIT64( 0x2000000000000000 );
2546     zSig = ( aSig + bSig )<<1;
2547     --zExp;
2548     if ( (sbits64) zSig < 0 ) {
2549         zSig = aSig + bSig;
2550         ++zExp;
2551     }
2552  roundAndPack:
2553     return roundAndPackFloat64( zSign, zExp, zSig STATUS_VAR );
2554
2555 }
2556
2557 /*----------------------------------------------------------------------------
2558 | Returns the result of subtracting the absolute values of the double-
2559 | precision floating-point values `a' and `b'.  If `zSign' is 1, the
2560 | difference is negated before being returned.  `zSign' is ignored if the
2561 | result is a NaN.  The subtraction is performed according to the IEC/IEEE
2562 | Standard for Binary Floating-Point Arithmetic.
2563 *----------------------------------------------------------------------------*/
2564
2565 static float64 subFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
2566 {
2567     int16 aExp, bExp, zExp;
2568     bits64 aSig, bSig, zSig;
2569     int16 expDiff;
2570
2571     aSig = extractFloat64Frac( a );
2572     aExp = extractFloat64Exp( a );
2573     bSig = extractFloat64Frac( b );
2574     bExp = extractFloat64Exp( b );
2575     expDiff = aExp - bExp;
2576     aSig <<= 10;
2577     bSig <<= 10;
2578     if ( 0 < expDiff ) goto aExpBigger;
2579     if ( expDiff < 0 ) goto bExpBigger;
2580     if ( aExp == 0x7FF ) {
2581         if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2582         float_raise( float_flag_invalid STATUS_VAR);
2583         return float64_default_nan;
2584     }
2585     if ( aExp == 0 ) {
2586         aExp = 1;
2587         bExp = 1;
2588     }
2589     if ( bSig < aSig ) goto aBigger;
2590     if ( aSig < bSig ) goto bBigger;
2591     return packFloat64( STATUS(float_rounding_mode) == float_round_down, 0, 0 );
2592  bExpBigger:
2593     if ( bExp == 0x7FF ) {
2594         if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2595         return packFloat64( zSign ^ 1, 0x7FF, 0 );
2596     }
2597     if ( aExp == 0 ) {
2598         ++expDiff;
2599     }
2600     else {
2601         aSig |= LIT64( 0x4000000000000000 );
2602     }
2603     shift64RightJamming( aSig, - expDiff, &aSig );
2604     bSig |= LIT64( 0x4000000000000000 );
2605  bBigger:
2606     zSig = bSig - aSig;
2607     zExp = bExp;
2608     zSign ^= 1;
2609     goto normalizeRoundAndPack;
2610  aExpBigger:
2611     if ( aExp == 0x7FF ) {
2612         if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2613         return a;
2614     }
2615     if ( bExp == 0 ) {
2616         --expDiff;
2617     }
2618     else {
2619         bSig |= LIT64( 0x4000000000000000 );
2620     }
2621     shift64RightJamming( bSig, expDiff, &bSig );
2622     aSig |= LIT64( 0x4000000000000000 );
2623  aBigger:
2624     zSig = aSig - bSig;
2625     zExp = aExp;
2626  normalizeRoundAndPack:
2627     --zExp;
2628     return normalizeRoundAndPackFloat64( zSign, zExp, zSig STATUS_VAR );
2629
2630 }
2631
2632 /*----------------------------------------------------------------------------
2633 | Returns the result of adding the double-precision floating-point values `a'
2634 | and `b'.  The operation is performed according to the IEC/IEEE Standard for
2635 | Binary Floating-Point Arithmetic.
2636 *----------------------------------------------------------------------------*/
2637
2638 float64 float64_add( float64 a, float64 b STATUS_PARAM )
2639 {
2640     flag aSign, bSign;
2641
2642     aSign = extractFloat64Sign( a );
2643     bSign = extractFloat64Sign( b );
2644     if ( aSign == bSign ) {
2645         return addFloat64Sigs( a, b, aSign STATUS_VAR );
2646     }
2647     else {
2648         return subFloat64Sigs( a, b, aSign STATUS_VAR );
2649     }
2650
2651 }
2652
2653 /*----------------------------------------------------------------------------
2654 | Returns the result of subtracting the double-precision floating-point values
2655 | `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
2656 | for Binary Floating-Point Arithmetic.
2657 *----------------------------------------------------------------------------*/
2658
2659 float64 float64_sub( float64 a, float64 b STATUS_PARAM )
2660 {
2661     flag aSign, bSign;
2662
2663     aSign = extractFloat64Sign( a );
2664     bSign = extractFloat64Sign( b );
2665     if ( aSign == bSign ) {
2666         return subFloat64Sigs( a, b, aSign STATUS_VAR );
2667     }
2668     else {
2669         return addFloat64Sigs( a, b, aSign STATUS_VAR );
2670     }
2671
2672 }
2673
2674 /*----------------------------------------------------------------------------
2675 | Returns the result of multiplying the double-precision floating-point values
2676 | `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
2677 | for Binary Floating-Point Arithmetic.
2678 *----------------------------------------------------------------------------*/
2679
2680 float64 float64_mul( float64 a, float64 b STATUS_PARAM )
2681 {
2682     flag aSign, bSign, zSign;
2683     int16 aExp, bExp, zExp;
2684     bits64 aSig, bSig, zSig0, zSig1;
2685
2686     aSig = extractFloat64Frac( a );
2687     aExp = extractFloat64Exp( a );
2688     aSign = extractFloat64Sign( a );
2689     bSig = extractFloat64Frac( b );
2690     bExp = extractFloat64Exp( b );
2691     bSign = extractFloat64Sign( b );
2692     zSign = aSign ^ bSign;
2693     if ( aExp == 0x7FF ) {
2694         if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
2695             return propagateFloat64NaN( a, b STATUS_VAR );
2696         }
2697         if ( ( bExp | bSig ) == 0 ) {
2698             float_raise( float_flag_invalid STATUS_VAR);
2699             return float64_default_nan;
2700         }
2701         return packFloat64( zSign, 0x7FF, 0 );
2702     }
2703     if ( bExp == 0x7FF ) {
2704         if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2705         if ( ( aExp | aSig ) == 0 ) {
2706             float_raise( float_flag_invalid STATUS_VAR);
2707             return float64_default_nan;
2708         }
2709         return packFloat64( zSign, 0x7FF, 0 );
2710     }
2711     if ( aExp == 0 ) {
2712         if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
2713         normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2714     }
2715     if ( bExp == 0 ) {
2716         if ( bSig == 0 ) return packFloat64( zSign, 0, 0 );
2717         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
2718     }
2719     zExp = aExp + bExp - 0x3FF;
2720     aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
2721     bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
2722     mul64To128( aSig, bSig, &zSig0, &zSig1 );
2723     zSig0 |= ( zSig1 != 0 );
2724     if ( 0 <= (sbits64) ( zSig0<<1 ) ) {
2725         zSig0 <<= 1;
2726         --zExp;
2727     }
2728     return roundAndPackFloat64( zSign, zExp, zSig0 STATUS_VAR );
2729
2730 }
2731
2732 /*----------------------------------------------------------------------------
2733 | Returns the result of dividing the double-precision floating-point value `a'
2734 | by the corresponding value `b'.  The operation is performed according to
2735 | the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2736 *----------------------------------------------------------------------------*/
2737
2738 float64 float64_div( float64 a, float64 b STATUS_PARAM )
2739 {
2740     flag aSign, bSign, zSign;
2741     int16 aExp, bExp, zExp;
2742     bits64 aSig, bSig, zSig;
2743     bits64 rem0, rem1;
2744     bits64 term0, term1;
2745
2746     aSig = extractFloat64Frac( a );
2747     aExp = extractFloat64Exp( a );
2748     aSign = extractFloat64Sign( a );
2749     bSig = extractFloat64Frac( b );
2750     bExp = extractFloat64Exp( b );
2751     bSign = extractFloat64Sign( b );
2752     zSign = aSign ^ bSign;
2753     if ( aExp == 0x7FF ) {
2754         if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2755         if ( bExp == 0x7FF ) {
2756             if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2757             float_raise( float_flag_invalid STATUS_VAR);
2758             return float64_default_nan;
2759         }
2760         return packFloat64( zSign, 0x7FF, 0 );
2761     }
2762     if ( bExp == 0x7FF ) {
2763         if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2764         return packFloat64( zSign, 0, 0 );
2765     }
2766     if ( bExp == 0 ) {
2767         if ( bSig == 0 ) {
2768             if ( ( aExp | aSig ) == 0 ) {
2769                 float_raise( float_flag_invalid STATUS_VAR);
2770                 return float64_default_nan;
2771             }
2772             float_raise( float_flag_divbyzero STATUS_VAR);
2773             return packFloat64( zSign, 0x7FF, 0 );
2774         }
2775         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
2776     }
2777     if ( aExp == 0 ) {
2778         if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
2779         normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2780     }
2781     zExp = aExp - bExp + 0x3FD;
2782     aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
2783     bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
2784     if ( bSig <= ( aSig + aSig ) ) {
2785         aSig >>= 1;
2786         ++zExp;
2787     }
2788     zSig = estimateDiv128To64( aSig, 0, bSig );
2789     if ( ( zSig & 0x1FF ) <= 2 ) {
2790         mul64To128( bSig, zSig, &term0, &term1 );
2791         sub128( aSig, 0, term0, term1, &rem0, &rem1 );
2792         while ( (sbits64) rem0 < 0 ) {
2793             --zSig;
2794             add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
2795         }
2796         zSig |= ( rem1 != 0 );
2797     }
2798     return roundAndPackFloat64( zSign, zExp, zSig STATUS_VAR );
2799
2800 }
2801
2802 /*----------------------------------------------------------------------------
2803 | Returns the remainder of the double-precision floating-point value `a'
2804 | with respect to the corresponding value `b'.  The operation is performed
2805 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2806 *----------------------------------------------------------------------------*/
2807
2808 float64 float64_rem( float64 a, float64 b STATUS_PARAM )
2809 {
2810     flag aSign, bSign, zSign;
2811     int16 aExp, bExp, expDiff;
2812     bits64 aSig, bSig;
2813     bits64 q, alternateASig;
2814     sbits64 sigMean;
2815
2816     aSig = extractFloat64Frac( a );
2817     aExp = extractFloat64Exp( a );
2818     aSign = extractFloat64Sign( a );
2819     bSig = extractFloat64Frac( b );
2820     bExp = extractFloat64Exp( b );
2821     bSign = extractFloat64Sign( b );
2822     if ( aExp == 0x7FF ) {
2823         if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
2824             return propagateFloat64NaN( a, b STATUS_VAR );
2825         }
2826         float_raise( float_flag_invalid STATUS_VAR);
2827         return float64_default_nan;
2828     }
2829     if ( bExp == 0x7FF ) {
2830         if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2831         return a;
2832     }
2833     if ( bExp == 0 ) {
2834         if ( bSig == 0 ) {
2835             float_raise( float_flag_invalid STATUS_VAR);
2836             return float64_default_nan;
2837         }
2838         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
2839     }
2840     if ( aExp == 0 ) {
2841         if ( aSig == 0 ) return a;
2842         normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2843     }
2844     expDiff = aExp - bExp;
2845     aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11;
2846     bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
2847     if ( expDiff < 0 ) {
2848         if ( expDiff < -1 ) return a;
2849         aSig >>= 1;
2850     }
2851     q = ( bSig <= aSig );
2852     if ( q ) aSig -= bSig;
2853     expDiff -= 64;
2854     while ( 0 < expDiff ) {
2855         q = estimateDiv128To64( aSig, 0, bSig );
2856         q = ( 2 < q ) ? q - 2 : 0;
2857         aSig = - ( ( bSig>>2 ) * q );
2858         expDiff -= 62;
2859     }
2860     expDiff += 64;
2861     if ( 0 < expDiff ) {
2862         q = estimateDiv128To64( aSig, 0, bSig );
2863         q = ( 2 < q ) ? q - 2 : 0;
2864         q >>= 64 - expDiff;
2865         bSig >>= 2;
2866         aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
2867     }
2868     else {
2869         aSig >>= 2;
2870         bSig >>= 2;
2871     }
2872     do {
2873         alternateASig = aSig;
2874         ++q;
2875         aSig -= bSig;
2876     } while ( 0 <= (sbits64) aSig );
2877     sigMean = aSig + alternateASig;
2878     if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
2879         aSig = alternateASig;
2880     }
2881     zSign = ( (sbits64) aSig < 0 );
2882     if ( zSign ) aSig = - aSig;
2883     return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig STATUS_VAR );
2884
2885 }
2886
2887 /*----------------------------------------------------------------------------
2888 | Returns the square root of the double-precision floating-point value `a'.
2889 | The operation is performed according to the IEC/IEEE Standard for Binary
2890 | Floating-Point Arithmetic.
2891 *----------------------------------------------------------------------------*/
2892
2893 float64 float64_sqrt( float64 a STATUS_PARAM )
2894 {
2895     flag aSign;
2896     int16 aExp, zExp;
2897     bits64 aSig, zSig, doubleZSig;
2898     bits64 rem0, rem1, term0, term1;
2899
2900     aSig = extractFloat64Frac( a );
2901     aExp = extractFloat64Exp( a );
2902     aSign = extractFloat64Sign( a );
2903     if ( aExp == 0x7FF ) {
2904         if ( aSig ) return propagateFloat64NaN( a, a STATUS_VAR );
2905         if ( ! aSign ) return a;
2906         float_raise( float_flag_invalid STATUS_VAR);
2907         return float64_default_nan;
2908     }
2909     if ( aSign ) {
2910         if ( ( aExp | aSig ) == 0 ) return a;
2911         float_raise( float_flag_invalid STATUS_VAR);
2912         return float64_default_nan;
2913     }
2914     if ( aExp == 0 ) {
2915         if ( aSig == 0 ) return 0;
2916         normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2917     }
2918     zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE;
2919     aSig |= LIT64( 0x0010000000000000 );
2920     zSig = estimateSqrt32( aExp, aSig>>21 );
2921     aSig <<= 9 - ( aExp & 1 );
2922     zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 );
2923     if ( ( zSig & 0x1FF ) <= 5 ) {
2924         doubleZSig = zSig<<1;
2925         mul64To128( zSig, zSig, &term0, &term1 );
2926         sub128( aSig, 0, term0, term1, &rem0, &rem1 );
2927         while ( (sbits64) rem0 < 0 ) {
2928             --zSig;
2929             doubleZSig -= 2;
2930             add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 );
2931         }
2932         zSig |= ( ( rem0 | rem1 ) != 0 );
2933     }
2934     return roundAndPackFloat64( 0, zExp, zSig STATUS_VAR );
2935
2936 }
2937
2938 /*----------------------------------------------------------------------------
2939 | Returns 1 if the double-precision floating-point value `a' is equal to the
2940 | corresponding value `b', and 0 otherwise.  The comparison is performed
2941 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2942 *----------------------------------------------------------------------------*/
2943
2944 flag float64_eq( float64 a, float64 b STATUS_PARAM )
2945 {
2946
2947     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2948          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2949        ) {
2950         if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
2951             float_raise( float_flag_invalid STATUS_VAR);
2952         }
2953         return 0;
2954     }
2955     return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
2956
2957 }
2958
2959 /*----------------------------------------------------------------------------
2960 | Returns 1 if the double-precision floating-point value `a' is less than or
2961 | equal to the corresponding value `b', and 0 otherwise.  The comparison is
2962 | performed according to the IEC/IEEE Standard for Binary Floating-Point
2963 | Arithmetic.
2964 *----------------------------------------------------------------------------*/
2965
2966 flag float64_le( float64 a, float64 b STATUS_PARAM )
2967 {
2968     flag aSign, bSign;
2969
2970     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2971          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2972        ) {
2973         float_raise( float_flag_invalid STATUS_VAR);
2974         return 0;
2975     }
2976     aSign = extractFloat64Sign( a );
2977     bSign = extractFloat64Sign( b );
2978     if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
2979     return ( a == b ) || ( aSign ^ ( a < b ) );
2980
2981 }
2982
2983 /*----------------------------------------------------------------------------
2984 | Returns 1 if the double-precision floating-point value `a' is less than
2985 | the corresponding value `b', and 0 otherwise.  The comparison is performed
2986 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2987 *----------------------------------------------------------------------------*/
2988
2989 flag float64_lt( float64 a, float64 b STATUS_PARAM )
2990 {
2991     flag aSign, bSign;
2992
2993     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2994          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2995        ) {
2996         float_raise( float_flag_invalid STATUS_VAR);
2997         return 0;
2998     }
2999     aSign = extractFloat64Sign( a );
3000     bSign = extractFloat64Sign( b );
3001     if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
3002     return ( a != b ) && ( aSign ^ ( a < b ) );
3003
3004 }
3005
3006 /*----------------------------------------------------------------------------
3007 | Returns 1 if the double-precision floating-point value `a' is equal to the
3008 | corresponding value `b', and 0 otherwise.  The invalid exception is raised
3009 | if either operand is a NaN.  Otherwise, the comparison is performed
3010 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3011 *----------------------------------------------------------------------------*/
3012
3013 flag float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
3014 {
3015
3016     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
3017          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
3018        ) {
3019         float_raise( float_flag_invalid STATUS_VAR);
3020         return 0;
3021     }
3022     return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
3023
3024 }
3025
3026 /*----------------------------------------------------------------------------
3027 | Returns 1 if the double-precision floating-point value `a' is less than or
3028 | equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
3029 | cause an exception.  Otherwise, the comparison is performed according to the
3030 | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3031 *----------------------------------------------------------------------------*/
3032
3033 flag float64_le_quiet( float64 a, float64 b STATUS_PARAM )
3034 {
3035     flag aSign, bSign;
3036
3037     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
3038          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
3039        ) {
3040         if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
3041             float_raise( float_flag_invalid STATUS_VAR);
3042         }
3043         return 0;
3044     }
3045     aSign = extractFloat64Sign( a );
3046     bSign = extractFloat64Sign( b );
3047     if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
3048     return ( a == b ) || ( aSign ^ ( a < b ) );
3049
3050 }
3051
3052 /*----------------------------------------------------------------------------
3053 | Returns 1 if the double-precision floating-point value `a' is less than
3054 | the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
3055 | exception.  Otherwise, the comparison is performed according to the IEC/IEEE
3056 | Standard for Binary Floating-Point Arithmetic.
3057 *----------------------------------------------------------------------------*/
3058
3059 flag float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
3060 {
3061     flag aSign, bSign;
3062
3063     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
3064          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
3065        ) {
3066         if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
3067             float_raise( float_flag_invalid STATUS_VAR);
3068         }
3069         return 0;
3070     }
3071     aSign = extractFloat64Sign( a );
3072     bSign = extractFloat64Sign( b );
3073     if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
3074     return ( a != b ) && ( aSign ^ ( a < b ) );
3075
3076 }
3077
3078 #ifdef FLOATX80
3079
3080 /*----------------------------------------------------------------------------
3081 | Returns the result of converting the extended double-precision floating-
3082 | point value `a' to the 32-bit two's complement integer format.  The
3083 | conversion is performed according to the IEC/IEEE Standard for Binary
3084 | Floating-Point Arithmetic---which means in particular that the conversion
3085 | is rounded according to the current rounding mode.  If `a' is a NaN, the
3086 | largest positive integer is returned.  Otherwise, if the conversion
3087 | overflows, the largest integer with the same sign as `a' is returned.
3088 *----------------------------------------------------------------------------*/
3089
3090 int32 floatx80_to_int32( floatx80 a STATUS_PARAM )
3091 {
3092     flag aSign;
3093     int32 aExp, shiftCount;
3094     bits64 aSig;
3095
3096     aSig = extractFloatx80Frac( a );
3097     aExp = extractFloatx80Exp( a );
3098     aSign = extractFloatx80Sign( a );
3099     if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
3100     shiftCount = 0x4037 - aExp;
3101     if ( shiftCount <= 0 ) shiftCount = 1;
3102     shift64RightJamming( aSig, shiftCount, &aSig );
3103     return roundAndPackInt32( aSign, aSig STATUS_VAR );
3104
3105 }
3106
3107 /*----------------------------------------------------------------------------
3108 | Returns the result of converting the extended double-precision floating-
3109 | point value `a' to the 32-bit two's complement integer format.  The
3110 | conversion is performed according to the IEC/IEEE Standard for Binary
3111 | Floating-Point Arithmetic, except that the conversion is always rounded
3112 | toward zero.  If `a' is a NaN, the largest positive integer is returned.
3113 | Otherwise, if the conversion overflows, the largest integer with the same
3114 | sign as `a' is returned.
3115 *----------------------------------------------------------------------------*/
3116
3117 int32 floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM )
3118 {
3119     flag aSign;
3120     int32 aExp, shiftCount;
3121     bits64 aSig, savedASig;
3122     int32 z;
3123
3124     aSig = extractFloatx80Frac( a );
3125     aExp = extractFloatx80Exp( a );
3126     aSign = extractFloatx80Sign( a );
3127     if ( 0x401E < aExp ) {
3128         if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
3129         goto invalid;
3130     }
3131     else if ( aExp < 0x3FFF ) {
3132         if ( aExp || aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
3133         return 0;
3134     }
3135     shiftCount = 0x403E - aExp;
3136     savedASig = aSig;
3137     aSig >>= shiftCount;
3138     z = aSig;
3139     if ( aSign ) z = - z;
3140     if ( ( z < 0 ) ^ aSign ) {
3141  invalid:
3142         float_raise( float_flag_invalid STATUS_VAR);
3143         return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
3144     }
3145     if ( ( aSig<<shiftCount ) != savedASig ) {
3146         STATUS(float_exception_flags) |= float_flag_inexact;
3147     }
3148     return z;
3149
3150 }
3151
3152 /*----------------------------------------------------------------------------
3153 | Returns the result of converting the extended double-precision floating-
3154 | point value `a' to the 64-bit two's complement integer format.  The
3155 | conversion is performed according to the IEC/IEEE Standard for Binary
3156 | Floating-Point Arithmetic---which means in particular that the conversion
3157 | is rounded according to the current rounding mode.  If `a' is a NaN,
3158 | the largest positive integer is returned.  Otherwise, if the conversion
3159 | overflows, the largest integer with the same sign as `a' is returned.
3160 *----------------------------------------------------------------------------*/
3161
3162 int64 floatx80_to_int64( floatx80 a STATUS_PARAM )
3163 {
3164     flag aSign;
3165     int32 aExp, shiftCount;
3166     bits64 aSig, aSigExtra;
3167
3168     aSig = extractFloatx80Frac( a );
3169     aExp = extractFloatx80Exp( a );
3170     aSign = extractFloatx80Sign( a );
3171     shiftCount = 0x403E - aExp;
3172     if ( shiftCount <= 0 ) {
3173         if ( shiftCount ) {
3174             float_raise( float_flag_invalid STATUS_VAR);
3175             if (    ! aSign
3176                  || (    ( aExp == 0x7FFF )
3177                       && ( aSig != LIT64( 0x8000000000000000 ) ) )
3178                ) {
3179                 return LIT64( 0x7FFFFFFFFFFFFFFF );
3180             }
3181             return (sbits64) LIT64( 0x8000000000000000 );
3182         }
3183         aSigExtra = 0;
3184     }
3185     else {
3186         shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
3187     }
3188     return roundAndPackInt64( aSign, aSig, aSigExtra STATUS_VAR );
3189
3190 }
3191
3192 /*----------------------------------------------------------------------------
3193 | Returns the result of converting the extended double-precision floating-
3194 | point value `a' to the 64-bit two's complement integer format.  The
3195 | conversion is performed according to the IEC/IEEE Standard for Binary
3196 | Floating-Point Arithmetic, except that the conversion is always rounded
3197 | toward zero.  If `a' is a NaN, the largest positive integer is returned.
3198 | Otherwise, if the conversion overflows, the largest integer with the same
3199 | sign as `a' is returned.
3200 *----------------------------------------------------------------------------*/
3201
3202 int64 floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM )
3203 {
3204     flag aSign;
3205     int32 aExp, shiftCount;
3206     bits64 aSig;
3207     int64 z;
3208
3209     aSig = extractFloatx80Frac( a );
3210     aExp = extractFloatx80Exp( a );
3211     aSign = extractFloatx80Sign( a );
3212     shiftCount = aExp - 0x403E;
3213     if ( 0 <= shiftCount ) {
3214         aSig &= LIT64( 0x7FFFFFFFFFFFFFFF );
3215         if ( ( a.high != 0xC03E ) || aSig ) {
3216             float_raise( float_flag_invalid STATUS_VAR);
3217             if ( ! aSign || ( ( aExp == 0x7FFF ) && aSig ) ) {
3218                 return LIT64( 0x7FFFFFFFFFFFFFFF );
3219             }
3220         }
3221         return (sbits64) LIT64( 0x8000000000000000 );
3222     }
3223     else if ( aExp < 0x3FFF ) {
3224         if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
3225         return 0;
3226     }
3227     z = aSig>>( - shiftCount );
3228     if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) {
3229         STATUS(float_exception_flags) |= float_flag_inexact;
3230     }
3231     if ( aSign ) z = - z;
3232     return z;
3233
3234 }
3235
3236 /*----------------------------------------------------------------------------
3237 | Returns the result of converting the extended double-precision floating-
3238 | point value `a' to the single-precision floating-point format.  The
3239 | conversion is performed according to the IEC/IEEE Standard for Binary
3240 | Floating-Point Arithmetic.
3241 *----------------------------------------------------------------------------*/
3242
3243 float32 floatx80_to_float32( floatx80 a STATUS_PARAM )
3244 {
3245     flag aSign;
3246     int32 aExp;
3247     bits64 aSig;
3248
3249     aSig = extractFloatx80Frac( a );
3250     aExp = extractFloatx80Exp( a );
3251     aSign = extractFloatx80Sign( a );
3252     if ( aExp == 0x7FFF ) {
3253         if ( (bits64) ( aSig<<1 ) ) {
3254             return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) );
3255         }
3256         return packFloat32( aSign, 0xFF, 0 );
3257     }
3258     shift64RightJamming( aSig, 33, &aSig );
3259     if ( aExp || aSig ) aExp -= 0x3F81;
3260     return roundAndPackFloat32( aSign, aExp, aSig STATUS_VAR );
3261
3262 }
3263
3264 /*----------------------------------------------------------------------------
3265 | Returns the result of converting the extended double-precision floating-
3266 | point value `a' to the double-precision floating-point format.  The
3267 | conversion is performed according to the IEC/IEEE Standard for Binary
3268 | Floating-Point Arithmetic.
3269 *----------------------------------------------------------------------------*/
3270
3271 float64 floatx80_to_float64( floatx80 a STATUS_PARAM )
3272 {
3273     flag aSign;
3274     int32 aExp;
3275     bits64 aSig, zSig;
3276
3277     aSig = extractFloatx80Frac( a );
3278     aExp = extractFloatx80Exp( a );
3279     aSign = extractFloatx80Sign( a );
3280     if ( aExp == 0x7FFF ) {
3281         if ( (bits64) ( aSig<<1 ) ) {
3282             return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) );
3283         }
3284         return packFloat64( aSign, 0x7FF, 0 );
3285     }
3286     shift64RightJamming( aSig, 1, &zSig );
3287     if ( aExp || aSig ) aExp -= 0x3C01;
3288     return roundAndPackFloat64( aSign, aExp, zSig STATUS_VAR );
3289
3290 }
3291
3292 #ifdef FLOAT128
3293
3294 /*----------------------------------------------------------------------------
3295 | Returns the result of converting the extended double-precision floating-
3296 | point value `a' to the quadruple-precision floating-point format.  The
3297 | conversion is performed according to the IEC/IEEE Standard for Binary
3298 | Floating-Point Arithmetic.
3299 *----------------------------------------------------------------------------*/
3300
3301 float128 floatx80_to_float128( floatx80 a STATUS_PARAM )
3302 {
3303     flag aSign;
3304     int16 aExp;
3305     bits64 aSig, zSig0, zSig1;
3306
3307     aSig = extractFloatx80Frac( a );
3308     aExp = extractFloatx80Exp( a );
3309     aSign = extractFloatx80Sign( a );
3310     if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) {
3311         return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) );
3312     }
3313     shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
3314     return packFloat128( aSign, aExp, zSig0, zSig1 );
3315
3316 }
3317
3318 #endif
3319
3320 /*----------------------------------------------------------------------------
3321 | Rounds the extended double-precision floating-point value `a' to an integer,
3322 | and returns the result as an extended quadruple-precision floating-point
3323 | value.  The operation is performed according to the IEC/IEEE Standard for
3324 | Binary Floating-Point Arithmetic.
3325 *----------------------------------------------------------------------------*/
3326
3327 floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
3328 {
3329     flag aSign;
3330     int32 aExp;
3331     bits64 lastBitMask, roundBitsMask;
3332     int8 roundingMode;
3333     floatx80 z;
3334
3335     aExp = extractFloatx80Exp( a );
3336     if ( 0x403E <= aExp ) {
3337         if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) {
3338             return propagateFloatx80NaN( a, a STATUS_VAR );
3339         }
3340         return a;
3341     }
3342     if ( aExp < 0x3FFF ) {
3343         if (    ( aExp == 0 )
3344              && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
3345             return a;
3346         }
3347         STATUS(float_exception_flags) |= float_flag_inexact;
3348         aSign = extractFloatx80Sign( a );
3349         switch ( STATUS(float_rounding_mode) ) {
3350          case float_round_nearest_even:
3351             if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
3352                ) {
3353                 return
3354                     packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
3355             }
3356             break;
3357          case float_round_down:
3358             return
3359                   aSign ?
3360                       packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) )
3361                 : packFloatx80( 0, 0, 0 );
3362          case float_round_up:
3363             return
3364                   aSign ? packFloatx80( 1, 0, 0 )
3365                 : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) );
3366         }
3367         return packFloatx80( aSign, 0, 0 );
3368     }
3369     lastBitMask = 1;
3370     lastBitMask <<= 0x403E - aExp;
3371     roundBitsMask = lastBitMask - 1;
3372     z = a;
3373     roundingMode = STATUS(float_rounding_mode);
3374     if ( roundingMode == float_round_nearest_even ) {
3375         z.low += lastBitMask>>1;
3376         if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
3377     }
3378     else if ( roundingMode != float_round_to_zero ) {
3379         if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) {
3380             z.low += roundBitsMask;
3381         }
3382     }
3383     z.low &= ~ roundBitsMask;
3384     if ( z.low == 0 ) {
3385         ++z.high;
3386         z.low = LIT64( 0x8000000000000000 );
3387     }
3388     if ( z.low != a.low ) STATUS(float_exception_flags) |= float_flag_inexact;
3389     return z;
3390
3391 }
3392
3393 /*----------------------------------------------------------------------------
3394 | Returns the result of adding the absolute values of the extended double-
3395 | precision floating-point values `a' and `b'.  If `zSign' is 1, the sum is
3396 | negated before being returned.  `zSign' is ignored if the result is a NaN.
3397 | The addition is performed according to the IEC/IEEE Standard for Binary
3398 | Floating-Point Arithmetic.
3399 *----------------------------------------------------------------------------*/
3400
3401 static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM)
3402 {
3403     int32 aExp, bExp, zExp;
3404     bits64 aSig, bSig, zSig0, zSig1;
3405     int32 expDiff;
3406
3407     aSig = extractFloatx80Frac( a );
3408     aExp = extractFloatx80Exp( a );
3409     bSig = extractFloatx80Frac( b );
3410     bExp = extractFloatx80Exp( b );
3411     expDiff = aExp - bExp;
3412     if ( 0 < expDiff ) {
3413         if ( aExp == 0x7FFF ) {
3414             if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3415             return a;
3416         }
3417         if ( bExp == 0 ) --expDiff;
3418         shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
3419         zExp = aExp;
3420     }
3421     else if ( expDiff < 0 ) {
3422         if ( bExp == 0x7FFF ) {
3423             if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3424             return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3425         }
3426         if ( aExp == 0 ) ++expDiff;
3427         shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
3428         zExp = bExp;
3429     }
3430     else {
3431         if ( aExp == 0x7FFF ) {
3432             if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
3433                 return propagateFloatx80NaN( a, b STATUS_VAR );
3434             }
3435             return a;
3436         }
3437         zSig1 = 0;
3438         zSig0 = aSig + bSig;
3439         if ( aExp == 0 ) {
3440             normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 );
3441             goto roundAndPack;
3442         }
3443         zExp = aExp;
3444         goto shiftRight1;
3445     }
3446     zSig0 = aSig + bSig;
3447     if ( (sbits64) zSig0 < 0 ) goto roundAndPack;
3448  shiftRight1:
3449     shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 );
3450     zSig0 |= LIT64( 0x8000000000000000 );
3451     ++zExp;
3452  roundAndPack:
3453     return
3454         roundAndPackFloatx80(
3455             STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
3456
3457 }
3458
3459 /*----------------------------------------------------------------------------
3460 | Returns the result of subtracting the absolute values of the extended
3461 | double-precision floating-point values `a' and `b'.  If `zSign' is 1, the
3462 | difference is negated before being returned.  `zSign' is ignored if the
3463 | result is a NaN.  The subtraction is performed according to the IEC/IEEE
3464 | Standard for Binary Floating-Point Arithmetic.
3465 *----------------------------------------------------------------------------*/
3466
3467 static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM )
3468 {
3469     int32 aExp, bExp, zExp;
3470     bits64 aSig, bSig, zSig0, zSig1;
3471     int32 expDiff;
3472     floatx80 z;
3473
3474     aSig = extractFloatx80Frac( a );
3475     aExp = extractFloatx80Exp( a );
3476     bSig = extractFloatx80Frac( b );
3477     bExp = extractFloatx80Exp( b );
3478     expDiff = aExp - bExp;
3479     if ( 0 < expDiff ) goto aExpBigger;
3480     if ( expDiff < 0 ) goto bExpBigger;
3481     if ( aExp == 0x7FFF ) {
3482         if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
3483             return propagateFloatx80NaN( a, b STATUS_VAR );
3484         }
3485         float_raise( float_flag_invalid STATUS_VAR);
3486         z.low = floatx80_default_nan_low;
3487         z.high = floatx80_default_nan_high;
3488         return z;
3489     }
3490     if ( aExp == 0 ) {
3491         aExp = 1;
3492         bExp = 1;
3493     }
3494     zSig1 = 0;
3495     if ( bSig < aSig ) goto aBigger;
3496     if ( aSig < bSig ) goto bBigger;
3497     return packFloatx80( STATUS(float_rounding_mode) == float_round_down, 0, 0 );
3498  bExpBigger:
3499     if ( bExp == 0x7FFF ) {
3500         if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3501         return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) );
3502     }
3503     if ( aExp == 0 ) ++expDiff;
3504     shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
3505  bBigger:
3506     sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 );
3507     zExp = bExp;
3508     zSign ^= 1;
3509     goto normalizeRoundAndPack;
3510  aExpBigger:
3511     if ( aExp == 0x7FFF ) {
3512         if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3513         return a;
3514     }
3515     if ( bExp == 0 ) --expDiff;
3516     shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
3517  aBigger:
3518     sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 );
3519     zExp = aExp;
3520  normalizeRoundAndPack:
3521     return
3522         normalizeRoundAndPackFloatx80(
3523             STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
3524
3525 }
3526
3527 /*----------------------------------------------------------------------------
3528 | Returns the result of adding the extended double-precision floating-point
3529 | values `a' and `b'.  The operation is performed according to the IEC/IEEE
3530 | Standard for Binary Floating-Point Arithmetic.
3531 *----------------------------------------------------------------------------*/
3532
3533 floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM )
3534 {
3535     flag aSign, bSign;
3536
3537     aSign = extractFloatx80Sign( a );
3538     bSign = extractFloatx80Sign( b );
3539     if ( aSign == bSign ) {
3540         return addFloatx80Sigs( a, b, aSign STATUS_VAR );
3541     }
3542     else {
3543         return subFloatx80Sigs( a, b, aSign STATUS_VAR );
3544     }
3545
3546 }
3547
3548 /*----------------------------------------------------------------------------
3549 | Returns the result of subtracting the extended double-precision floating-
3550 | point values `a' and `b'.  The operation is performed according to the
3551 | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3552 *----------------------------------------------------------------------------*/
3553
3554 floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM )
3555 {
3556     flag aSign, bSign;
3557
3558     aSign = extractFloatx80Sign( a );
3559     bSign = extractFloatx80Sign( b );
3560     if ( aSign == bSign ) {
3561         return subFloatx80Sigs( a, b, aSign STATUS_VAR );
3562     }
3563     else {
3564         return addFloatx80Sigs( a, b, aSign STATUS_VAR );
3565     }
3566
3567 }
3568
3569 /*----------------------------------------------------------------------------
3570 | Returns the result of multiplying the extended double-precision floating-
3571 | point values `a' and `b'.  The operation is performed according to the
3572 | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3573 *----------------------------------------------------------------------------*/
3574
3575 floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM )
3576 {
3577     flag aSign, bSign, zSign;
3578     int32 aExp, bExp, zExp;
3579     bits64 aSig, bSig, zSig0, zSig1;
3580     floatx80 z;
3581
3582     aSig = extractFloatx80Frac( a );
3583     aExp = extractFloatx80Exp( a );
3584     aSign = extractFloatx80Sign( a );
3585     bSig = extractFloatx80Frac( b );
3586     bExp = extractFloatx80Exp( b );
3587     bSign = extractFloatx80Sign( b );
3588     zSign = aSign ^ bSign;
3589     if ( aExp == 0x7FFF ) {
3590         if (    (bits64) ( aSig<<1 )
3591              || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
3592             return propagateFloatx80NaN( a, b STATUS_VAR );
3593         }
3594         if ( ( bExp | bSig ) == 0 ) goto invalid;
3595         return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3596     }
3597     if ( bExp == 0x7FFF ) {
3598         if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3599         if ( ( aExp | aSig ) == 0 ) {
3600  invalid:
3601             float_raise( float_flag_invalid STATUS_VAR);
3602             z.low = floatx80_default_nan_low;
3603             z.high = floatx80_default_nan_high;
3604             return z;
3605         }
3606         return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3607     }
3608     if ( aExp == 0 ) {
3609         if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
3610         normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
3611     }
3612     if ( bExp == 0 ) {
3613         if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 );
3614         normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
3615     }
3616     zExp = aExp + bExp - 0x3FFE;
3617     mul64To128( aSig, bSig, &zSig0, &zSig1 );
3618     if ( 0 < (sbits64) zSig0 ) {
3619         shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
3620         --zExp;
3621     }
3622     return
3623         roundAndPackFloatx80(
3624             STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
3625
3626 }
3627
3628 /*----------------------------------------------------------------------------
3629 | Returns the result of dividing the extended double-precision floating-point
3630 | value `a' by the corresponding value `b'.  The operation is performed
3631 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3632 *----------------------------------------------------------------------------*/
3633
3634 floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM )
3635 {
3636     flag aSign, bSign, zSign;
3637     int32 aExp, bExp, zExp;
3638     bits64 aSig, bSig, zSig0, zSig1;
3639     bits64 rem0, rem1, rem2, term0, term1, term2;
3640     floatx80 z;
3641
3642     aSig = extractFloatx80Frac( a );
3643     aExp = extractFloatx80Exp( a );
3644     aSign = extractFloatx80Sign( a );
3645     bSig = extractFloatx80Frac( b );
3646     bExp = extractFloatx80Exp( b );
3647     bSign = extractFloatx80Sign( b );
3648     zSign = aSign ^ bSign;
3649     if ( aExp == 0x7FFF ) {
3650         if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3651         if ( bExp == 0x7FFF ) {
3652             if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3653             goto invalid;
3654         }
3655         return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3656     }
3657     if ( bExp == 0x7FFF ) {
3658         if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3659         return packFloatx80( zSign, 0, 0 );
3660     }
3661     if ( bExp == 0 ) {
3662         if ( bSig == 0 ) {
3663             if ( ( aExp | aSig ) == 0 ) {
3664  invalid:
3665                 float_raise( float_flag_invalid STATUS_VAR);
3666                 z.low = floatx80_default_nan_low;
3667                 z.high = floatx80_default_nan_high;
3668                 return z;
3669             }
3670             float_raise( float_flag_divbyzero STATUS_VAR);
3671             return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3672         }
3673         normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
3674     }
3675     if ( aExp == 0 ) {
3676         if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
3677         normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
3678     }
3679     zExp = aExp - bExp + 0x3FFE;
3680     rem1 = 0;
3681     if ( bSig <= aSig ) {
3682         shift128Right( aSig, 0, 1, &aSig, &rem1 );
3683         ++zExp;
3684     }
3685     zSig0 = estimateDiv128To64( aSig, rem1, bSig );
3686     mul64To128( bSig, zSig0, &term0, &term1 );
3687     sub128( aSig, rem1, term0, term1, &rem0, &rem1 );
3688     while ( (sbits64) rem0 < 0 ) {
3689         --zSig0;
3690         add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
3691     }
3692     zSig1 = estimateDiv128To64( rem1, 0, bSig );
3693     if ( (bits64) ( zSig1<<1 ) <= 8 ) {
3694         mul64To128( bSig, zSig1, &term1, &term2 );
3695         sub128( rem1, 0, term1, term2, &rem1, &rem2 );
3696         while ( (sbits64) rem1 < 0 ) {
3697             --zSig1;
3698             add128( rem1, rem2, 0, bSig, &rem1, &rem2 );
3699         }
3700         zSig1 |= ( ( rem1 | rem2 ) != 0 );
3701     }
3702     return
3703         roundAndPackFloatx80(
3704             STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
3705
3706 }
3707
3708 /*----------------------------------------------------------------------------
3709 | Returns the remainder of the extended double-precision floating-point value
3710 | `a' with respect to the corresponding value `b'.  The operation is performed
3711 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3712 *----------------------------------------------------------------------------*/
3713
3714 floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM )
3715 {
3716     flag aSign, bSign, zSign;
3717     int32 aExp, bExp, expDiff;
3718     bits64 aSig0, aSig1, bSig;
3719     bits64 q, term0, term1, alternateASig0, alternateASig1;
3720     floatx80 z;
3721
3722     aSig0 = extractFloatx80Frac( a );
3723     aExp = extractFloatx80Exp( a );
3724     aSign = extractFloatx80Sign( a );
3725     bSig = extractFloatx80Frac( b );
3726     bExp = extractFloatx80Exp( b );
3727     bSign = extractFloatx80Sign( b );
3728     if ( aExp == 0x7FFF ) {
3729         if (    (bits64) ( aSig0<<1 )
3730              || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
3731             return propagateFloatx80NaN( a, b STATUS_VAR );
3732         }
3733         goto invalid;
3734     }
3735     if ( bExp == 0x7FFF ) {
3736         if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3737         return a;
3738     }
3739     if ( bExp == 0 ) {
3740         if ( bSig == 0 ) {
3741  invalid:
3742             float_raise( float_flag_invalid STATUS_VAR);
3743             z.low = floatx80_default_nan_low;
3744             z.high = floatx80_default_nan_high;
3745             return z;
3746         }
3747         normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
3748     }
3749     if ( aExp == 0 ) {
3750         if ( (bits64) ( aSig0<<1 ) == 0 ) return a;
3751         normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
3752     }
3753     bSig |= LIT64( 0x8000000000000000 );
3754     zSign = aSign;
3755     expDiff = aExp - bExp;
3756     aSig1 = 0;
3757     if ( expDiff < 0 ) {
3758         if ( expDiff < -1 ) return a;
3759         shift128Right( aSig0, 0, 1, &aSig0, &aSig1 );
3760         expDiff = 0;
3761     }
3762     q = ( bSig <= aSig0 );
3763     if ( q ) aSig0 -= bSig;
3764     expDiff -= 64;
3765     while ( 0 < expDiff ) {
3766         q = estimateDiv128To64( aSig0, aSig1, bSig );
3767         q = ( 2 < q ) ? q - 2 : 0;
3768         mul64To128( bSig, q, &term0, &term1 );
3769         sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
3770         shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
3771         expDiff -= 62;
3772     }
3773     expDiff += 64;
3774     if ( 0 < expDiff ) {
3775         q = estimateDiv128To64( aSig0, aSig1, bSig );
3776         q = ( 2 < q ) ? q - 2 : 0;
3777         q >>= 64 - expDiff;
3778         mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 );
3779         sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
3780         shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 );
3781         while ( le128( term0, term1, aSig0, aSig1 ) ) {
3782             ++q;
3783             sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
3784         }
3785     }
3786     else {
3787         term1 = 0;
3788         term0 = bSig;
3789     }
3790     sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 );
3791     if (    lt128( alternateASig0, alternateASig1, aSig0, aSig1 )
3792          || (    eq128( alternateASig0, alternateASig1, aSig0, aSig1 )
3793               && ( q & 1 ) )
3794        ) {
3795         aSig0 = alternateASig0;
3796         aSig1 = alternateASig1;
3797         zSign = ! zSign;
3798     }
3799     return
3800         normalizeRoundAndPackFloatx80(
3801             80, zSign, bExp + expDiff, aSig0, aSig1 STATUS_VAR );
3802
3803 }
3804
3805 /*----------------------------------------------------------------------------
3806 | Returns the square root of the extended double-precision floating-point
3807 | value `a'.  The operation is performed according to the IEC/IEEE Standard
3808 | for Binary Floating-Point Arithmetic.
3809 *----------------------------------------------------------------------------*/
3810
3811 floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
3812 {
3813     flag aSign;
3814     int32 aExp, zExp;
3815     bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0;
3816     bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
3817     floatx80 z;
3818
3819     aSig0 = extractFloatx80Frac( a );
3820     aExp = extractFloatx80Exp( a );
3821     aSign = extractFloatx80Sign( a );
3822     if ( aExp == 0x7FFF ) {
3823         if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a STATUS_VAR );
3824         if ( ! aSign ) return a;
3825         goto invalid;
3826     }
3827     if ( aSign ) {
3828         if ( ( aExp | aSig0 ) == 0 ) return a;
3829  invalid:
3830         float_raise( float_flag_invalid STATUS_VAR);
3831         z.low = floatx80_default_nan_low;
3832         z.high = floatx80_default_nan_high;
3833         return z;
3834     }
3835     if ( aExp == 0 ) {
3836         if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 );
3837         normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
3838     }
3839     zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF;
3840     zSig0 = estimateSqrt32( aExp, aSig0>>32 );
3841     shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 );
3842     zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 );
3843     doubleZSig0 = zSig0<<1;
3844     mul64To128( zSig0, zSig0, &term0, &term1 );
3845     sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
3846     while ( (sbits64) rem0 < 0 ) {
3847         --zSig0;
3848         doubleZSig0 -= 2;
3849         add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
3850     }
3851     zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 );
3852     if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) {
3853         if ( zSig1 == 0 ) zSig1 = 1;
3854         mul64To128( doubleZSig0, zSig1, &term1, &term2 );
3855         sub128( rem1, 0, term1, term2, &rem1, &rem2 );
3856         mul64To128( zSig1, zSig1, &term2, &term3 );
3857         sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
3858         while ( (sbits64) rem1 < 0 ) {
3859             --zSig1;
3860             shortShift128Left( 0, zSig1, 1, &term2, &term3 );
3861             term3 |= 1;
3862             term2 |= doubleZSig0;
3863             add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
3864         }
3865         zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
3866     }
3867     shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 );
3868     zSig0 |= doubleZSig0;
3869     return
3870         roundAndPackFloatx80(
3871             STATUS(floatx80_rounding_precision), 0, zExp, zSig0, zSig1 STATUS_VAR );
3872
3873 }
3874
3875 /*----------------------------------------------------------------------------
3876 | Returns 1 if the extended double-precision floating-point value `a' is
3877 | equal to the corresponding value `b', and 0 otherwise.  The comparison is
3878 | performed according to the IEC/IEEE Standard for Binary Floating-Point
3879 | Arithmetic.
3880 *----------------------------------------------------------------------------*/
3881
3882 flag floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
3883 {
3884
3885     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
3886               && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3887          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
3888               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3889        ) {
3890         if (    floatx80_is_signaling_nan( a )
3891              || floatx80_is_signaling_nan( b ) ) {
3892             float_raise( float_flag_invalid STATUS_VAR);
3893         }
3894         return 0;
3895     }
3896     return
3897            ( a.low == b.low )
3898         && (    ( a.high == b.high )
3899              || (    ( a.low == 0 )
3900                   && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
3901            );
3902
3903 }
3904
3905 /*----------------------------------------------------------------------------
3906 | Returns 1 if the extended double-precision floating-point value `a' is
3907 | less than or equal to the corresponding value `b', and 0 otherwise.  The
3908 | comparison is performed according to the IEC/IEEE Standard for Binary
3909 | Floating-Point Arithmetic.
3910 *----------------------------------------------------------------------------*/
3911
3912 flag floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
3913 {
3914     flag aSign, bSign;
3915
3916     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
3917               && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3918          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
3919               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3920        ) {
3921         float_raise( float_flag_invalid STATUS_VAR);
3922         return 0;
3923     }
3924     aSign = extractFloatx80Sign( a );
3925     bSign = extractFloatx80Sign( b );
3926     if ( aSign != bSign ) {
3927         return
3928                aSign
3929             || (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
3930                  == 0 );
3931     }
3932     return
3933           aSign ? le128( b.high, b.low, a.high, a.low )
3934         : le128( a.high, a.low, b.high, b.low );
3935
3936 }
3937
3938 /*----------------------------------------------------------------------------
3939 | Returns 1 if the extended double-precision floating-point value `a' is
3940 | less than the corresponding value `b', and 0 otherwise.  The comparison
3941 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
3942 | Arithmetic.
3943 *----------------------------------------------------------------------------*/
3944
3945 flag floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
3946 {
3947     flag aSign, bSign;
3948
3949     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
3950               && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3951          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
3952               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3953        ) {
3954         float_raise( float_flag_invalid STATUS_VAR);
3955         return 0;
3956     }
3957     aSign = extractFloatx80Sign( a );
3958     bSign = extractFloatx80Sign( b );
3959     if ( aSign != bSign ) {
3960         return
3961                aSign
3962             && (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
3963                  != 0 );
3964     }
3965     return
3966           aSign ? lt128( b.high, b.low, a.high, a.low )
3967         : lt128( a.high, a.low, b.high, b.low );
3968
3969 }
3970
3971 /*----------------------------------------------------------------------------
3972 | Returns 1 if the extended double-precision floating-point value `a' is equal
3973 | to the corresponding value `b', and 0 otherwise.  The invalid exception is
3974 | raised if either operand is a NaN.  Otherwise, the comparison is performed
3975 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3976 *----------------------------------------------------------------------------*/
3977
3978 flag floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
3979 {
3980
3981     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
3982               && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3983          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
3984               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3985        ) {
3986         float_raise( float_flag_invalid STATUS_VAR);
3987         return 0;
3988     }
3989     return
3990            ( a.low == b.low )
3991         && (    ( a.high == b.high )
3992              || (    ( a.low == 0 )
3993                   && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
3994            );
3995
3996 }
3997
3998 /*----------------------------------------------------------------------------
3999 | Returns 1 if the extended double-precision floating-point value `a' is less
4000 | than or equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs
4001 | do not cause an exception.  Otherwise, the comparison is performed according
4002 | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4003 *----------------------------------------------------------------------------*/
4004
4005 flag floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
4006 {
4007     flag aSign, bSign;
4008
4009     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
4010               && (bits64) ( extractFloatx80Frac( a )<<1 ) )
4011          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
4012               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
4013        ) {
4014         if (    floatx80_is_signaling_nan( a )
4015              || floatx80_is_signaling_nan( b ) ) {
4016             float_raise( float_flag_invalid STATUS_VAR);
4017         }
4018         return 0;
4019     }
4020     aSign = extractFloatx80Sign( a );
4021     bSign = extractFloatx80Sign( b );
4022     if ( aSign != bSign ) {
4023         return
4024                aSign
4025             || (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
4026                  == 0 );
4027     }
4028     return
4029           aSign ? le128( b.high, b.low, a.high, a.low )
4030         : le128( a.high, a.low, b.high, b.low );
4031
4032 }
4033
4034 /*----------------------------------------------------------------------------
4035 | Returns 1 if the extended double-precision floating-point value `a' is less
4036 | than the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause
4037 | an exception.  Otherwise, the comparison is performed according to the
4038 | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4039 *----------------------------------------------------------------------------*/
4040
4041 flag floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
4042 {
4043     flag aSign, bSign;
4044
4045     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
4046               && (bits64) ( extractFloatx80Frac( a )<<1 ) )
4047          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
4048               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
4049        ) {
4050         if (    floatx80_is_signaling_nan( a )
4051              || floatx80_is_signaling_nan( b ) ) {
4052             float_raise( float_flag_invalid STATUS_VAR);
4053         }
4054         return 0;
4055     }
4056     aSign = extractFloatx80Sign( a );
4057     bSign = extractFloatx80Sign( b );
4058     if ( aSign != bSign ) {
4059         return
4060                aSign
4061             && (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
4062                  != 0 );
4063     }
4064     return
4065           aSign ? lt128( b.high, b.low, a.high, a.low )
4066         : lt128( a.high, a.low, b.high, b.low );
4067
4068 }
4069
4070 #endif
4071
4072 #ifdef FLOAT128
4073
4074 /*----------------------------------------------------------------------------
4075 | Returns the result of converting the quadruple-precision floating-point
4076 | value `a' to the 32-bit two's complement integer format.  The conversion
4077 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4078 | Arithmetic---which means in particular that the conversion is rounded
4079 | according to the current rounding mode.  If `a' is a NaN, the largest
4080 | positive integer is returned.  Otherwise, if the conversion overflows, the
4081 | largest integer with the same sign as `a' is returned.
4082 *----------------------------------------------------------------------------*/
4083
4084 int32 float128_to_int32( float128 a STATUS_PARAM )
4085 {
4086     flag aSign;
4087     int32 aExp, shiftCount;
4088     bits64 aSig0, aSig1;
4089
4090     aSig1 = extractFloat128Frac1( a );
4091     aSig0 = extractFloat128Frac0( a );
4092     aExp = extractFloat128Exp( a );
4093     aSign = extractFloat128Sign( a );
4094     if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0;
4095     if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
4096     aSig0 |= ( aSig1 != 0 );
4097     shiftCount = 0x4028 - aExp;
4098     if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 );
4099     return roundAndPackInt32( aSign, aSig0 STATUS_VAR );
4100
4101 }
4102
4103 /*----------------------------------------------------------------------------
4104 | Returns the result of converting the quadruple-precision floating-point
4105 | value `a' to the 32-bit two's complement integer format.  The conversion
4106 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4107 | Arithmetic, except that the conversion is always rounded toward zero.  If
4108 | `a' is a NaN, the largest positive integer is returned.  Otherwise, if the
4109 | conversion overflows, the largest integer with the same sign as `a' is
4110 | returned.
4111 *----------------------------------------------------------------------------*/
4112
4113 int32 float128_to_int32_round_to_zero( float128 a STATUS_PARAM )
4114 {
4115     flag aSign;
4116     int32 aExp, shiftCount;
4117     bits64 aSig0, aSig1, savedASig;
4118     int32 z;
4119
4120     aSig1 = extractFloat128Frac1( a );
4121     aSig0 = extractFloat128Frac0( a );
4122     aExp = extractFloat128Exp( a );
4123     aSign = extractFloat128Sign( a );
4124     aSig0 |= ( aSig1 != 0 );
4125     if ( 0x401E < aExp ) {
4126         if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0;
4127         goto invalid;
4128     }
4129     else if ( aExp < 0x3FFF ) {
4130         if ( aExp || aSig0 ) STATUS(float_exception_flags) |= float_flag_inexact;
4131         return 0;
4132     }
4133     aSig0 |= LIT64( 0x0001000000000000 );
4134     shiftCount = 0x402F - aExp;
4135     savedASig = aSig0;
4136     aSig0 >>= shiftCount;
4137     z = aSig0;
4138     if ( aSign ) z = - z;
4139     if ( ( z < 0 ) ^ aSign ) {
4140  invalid:
4141         float_raise( float_flag_invalid STATUS_VAR);
4142         return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
4143     }
4144     if ( ( aSig0<<shiftCount ) != savedASig ) {
4145         STATUS(float_exception_flags) |= float_flag_inexact;
4146     }
4147     return z;
4148
4149 }
4150
4151 /*----------------------------------------------------------------------------
4152 | Returns the result of converting the quadruple-precision floating-point
4153 | value `a' to the 64-bit two's complement integer format.  The conversion
4154 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4155 | Arithmetic---which means in particular that the conversion is rounded
4156 | according to the current rounding mode.  If `a' is a NaN, the largest
4157 | positive integer is returned.  Otherwise, if the conversion overflows, the
4158 | largest integer with the same sign as `a' is returned.
4159 *----------------------------------------------------------------------------*/
4160
4161 int64 float128_to_int64( float128 a STATUS_PARAM )
4162 {
4163     flag aSign;
4164     int32 aExp, shiftCount;
4165     bits64 aSig0, aSig1;
4166
4167     aSig1 = extractFloat128Frac1( a );
4168     aSig0 = extractFloat128Frac0( a );
4169     aExp = extractFloat128Exp( a );
4170     aSign = extractFloat128Sign( a );
4171     if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
4172     shiftCount = 0x402F - aExp;
4173     if ( shiftCount <= 0 ) {
4174         if ( 0x403E < aExp ) {
4175             float_raise( float_flag_invalid STATUS_VAR);
4176             if (    ! aSign
4177                  || (    ( aExp == 0x7FFF )
4178                       && ( aSig1 || ( aSig0 != LIT64( 0x0001000000000000 ) ) )
4179                     )
4180                ) {
4181                 return LIT64( 0x7FFFFFFFFFFFFFFF );
4182             }
4183             return (sbits64) LIT64( 0x8000000000000000 );
4184         }
4185         shortShift128Left( aSig0, aSig1, - shiftCount, &aSig0, &aSig1 );
4186     }
4187     else {
4188         shift64ExtraRightJamming( aSig0, aSig1, shiftCount, &aSig0, &aSig1 );
4189     }
4190     return roundAndPackInt64( aSign, aSig0, aSig1 STATUS_VAR );
4191
4192 }
4193
4194 /*----------------------------------------------------------------------------
4195 | Returns the result of converting the quadruple-precision floating-point
4196 | value `a' to the 64-bit two's complement integer format.  The conversion
4197 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4198 | Arithmetic, except that the conversion is always rounded toward zero.
4199 | If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
4200 | the conversion overflows, the largest integer with the same sign as `a' is
4201 | returned.
4202 *----------------------------------------------------------------------------*/
4203
4204 int64 float128_to_int64_round_to_zero( float128 a STATUS_PARAM )
4205 {
4206     flag aSign;
4207     int32 aExp, shiftCount;
4208     bits64 aSig0, aSig1;
4209     int64 z;
4210
4211     aSig1 = extractFloat128Frac1( a );
4212     aSig0 = extractFloat128Frac0( a );
4213     aExp = extractFloat128Exp( a );
4214     aSign = extractFloat128Sign( a );
4215     if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
4216     shiftCount = aExp - 0x402F;
4217     if ( 0 < shiftCount ) {
4218         if ( 0x403E <= aExp ) {
4219             aSig0 &= LIT64( 0x0000FFFFFFFFFFFF );
4220             if (    ( a.high == LIT64( 0xC03E000000000000 ) )
4221                  && ( aSig1 < LIT64( 0x0002000000000000 ) ) ) {
4222                 if ( aSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
4223             }
4224             else {
4225                 float_raise( float_flag_invalid STATUS_VAR);
4226                 if ( ! aSign || ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) ) {
4227                     return LIT64( 0x7FFFFFFFFFFFFFFF );
4228                 }
4229             }
4230             return (sbits64) LIT64( 0x8000000000000000 );
4231         }
4232         z = ( aSig0<<shiftCount ) | ( aSig1>>( ( - shiftCount ) & 63 ) );
4233         if ( (bits64) ( aSig1<<shiftCount ) ) {
4234             STATUS(float_exception_flags) |= float_flag_inexact;
4235         }
4236     }
4237     else {
4238         if ( aExp < 0x3FFF ) {
4239             if ( aExp | aSig0 | aSig1 ) {
4240                 STATUS(float_exception_flags) |= float_flag_inexact;
4241             }
4242             return 0;
4243         }
4244         z = aSig0>>( - shiftCount );
4245         if (    aSig1
4246              || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) {
4247             STATUS(float_exception_flags) |= float_flag_inexact;
4248         }
4249     }
4250     if ( aSign ) z = - z;
4251     return z;
4252
4253 }
4254
4255 /*----------------------------------------------------------------------------
4256 | Returns the result of converting the quadruple-precision floating-point
4257 | value `a' to the single-precision floating-point format.  The conversion
4258 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4259 | Arithmetic.
4260 *----------------------------------------------------------------------------*/
4261
4262 float32 float128_to_float32( float128 a STATUS_PARAM )
4263 {
4264     flag aSign;
4265     int32 aExp;
4266     bits64 aSig0, aSig1;
4267     bits32 zSig;
4268
4269     aSig1 = extractFloat128Frac1( a );
4270     aSig0 = extractFloat128Frac0( a );
4271     aExp = extractFloat128Exp( a );
4272     aSign = extractFloat128Sign( a );
4273     if ( aExp == 0x7FFF ) {
4274         if ( aSig0 | aSig1 ) {
4275             return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) );
4276         }
4277         return packFloat32( aSign, 0xFF, 0 );
4278     }
4279     aSig0 |= ( aSig1 != 0 );
4280     shift64RightJamming( aSig0, 18, &aSig0 );
4281     zSig = aSig0;
4282     if ( aExp || zSig ) {
4283         zSig |= 0x40000000;
4284         aExp -= 0x3F81;
4285     }
4286     return roundAndPackFloat32( aSign, aExp, zSig STATUS_VAR );
4287
4288 }
4289
4290 /*----------------------------------------------------------------------------
4291 | Returns the result of converting the quadruple-precision floating-point
4292 | value `a' to the double-precision floating-point format.  The conversion
4293 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4294 | Arithmetic.
4295 *----------------------------------------------------------------------------*/
4296
4297 float64 float128_to_float64( float128 a STATUS_PARAM )
4298 {
4299     flag aSign;
4300     int32 aExp;
4301     bits64 aSig0, aSig1;
4302
4303     aSig1 = extractFloat128Frac1( a );
4304     aSig0 = extractFloat128Frac0( a );
4305     aExp = extractFloat128Exp( a );
4306     aSign = extractFloat128Sign( a );
4307     if ( aExp == 0x7FFF ) {
4308         if ( aSig0 | aSig1 ) {
4309             return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) );
4310         }
4311         return packFloat64( aSign, 0x7FF, 0 );
4312     }
4313     shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
4314     aSig0 |= ( aSig1 != 0 );
4315     if ( aExp || aSig0 ) {
4316         aSig0 |= LIT64( 0x4000000000000000 );
4317         aExp -= 0x3C01;
4318     }
4319     return roundAndPackFloat64( aSign, aExp, aSig0 STATUS_VAR );
4320
4321 }
4322
4323 #ifdef FLOATX80
4324
4325 /*----------------------------------------------------------------------------
4326 | Returns the result of converting the quadruple-precision floating-point
4327 | value `a' to the extended double-precision floating-point format.  The
4328 | conversion is performed according to the IEC/IEEE Standard for Binary
4329 | Floating-Point Arithmetic.
4330 *----------------------------------------------------------------------------*/
4331
4332 floatx80 float128_to_floatx80( float128 a STATUS_PARAM )
4333 {
4334     flag aSign;
4335     int32 aExp;
4336     bits64 aSig0, aSig1;
4337
4338     aSig1 = extractFloat128Frac1( a );
4339     aSig0 = extractFloat128Frac0( a );
4340     aExp = extractFloat128Exp( a );
4341     aSign = extractFloat128Sign( a );
4342     if ( aExp == 0x7FFF ) {
4343         if ( aSig0 | aSig1 ) {
4344             return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) );
4345         }
4346         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
4347     }
4348     if ( aExp == 0 ) {
4349         if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 );
4350         normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
4351     }
4352     else {
4353         aSig0 |= LIT64( 0x0001000000000000 );
4354     }
4355     shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 );
4356     return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 STATUS_VAR );
4357
4358 }
4359
4360 #endif
4361
4362 /*----------------------------------------------------------------------------
4363 | Rounds the quadruple-precision floating-point value `a' to an integer, and
4364 | returns the result as a quadruple-precision floating-point value.  The
4365 | operation is performed according to the IEC/IEEE Standard for Binary
4366 | Floating-Point Arithmetic.
4367 *----------------------------------------------------------------------------*/
4368
4369 float128 float128_round_to_int( float128 a STATUS_PARAM )
4370 {
4371     flag aSign;
4372     int32 aExp;
4373     bits64 lastBitMask, roundBitsMask;
4374     int8 roundingMode;
4375     float128 z;
4376
4377     aExp = extractFloat128Exp( a );
4378     if ( 0x402F <= aExp ) {
4379         if ( 0x406F <= aExp ) {
4380             if (    ( aExp == 0x7FFF )
4381                  && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) )
4382                ) {
4383                 return propagateFloat128NaN( a, a STATUS_VAR );
4384             }
4385             return a;
4386         }
4387         lastBitMask = 1;
4388         lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1;
4389         roundBitsMask = lastBitMask - 1;
4390         z = a;
4391         roundingMode = STATUS(float_rounding_mode);
4392         if ( roundingMode == float_round_nearest_even ) {
4393             if ( lastBitMask ) {
4394                 add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low );
4395                 if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
4396             }
4397             else {
4398                 if ( (sbits64) z.low < 0 ) {
4399                     ++z.high;
4400                     if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1;
4401                 }
4402             }
4403         }
4404         else if ( roundingMode != float_round_to_zero ) {
4405             if (   extractFloat128Sign( z )
4406                  ^ ( roundingMode == float_round_up ) ) {
4407                 add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low );
4408             }
4409         }
4410         z.low &= ~ roundBitsMask;
4411     }
4412     else {
4413         if ( aExp < 0x3FFF ) {
4414             if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a;
4415             STATUS(float_exception_flags) |= float_flag_inexact;
4416             aSign = extractFloat128Sign( a );
4417             switch ( STATUS(float_rounding_mode) ) {
4418              case float_round_nearest_even:
4419                 if (    ( aExp == 0x3FFE )
4420                      && (   extractFloat128Frac0( a )
4421                           | extractFloat128Frac1( a ) )
4422                    ) {
4423                     return packFloat128( aSign, 0x3FFF, 0, 0 );
4424                 }
4425                 break;
4426              case float_round_down:
4427                 return
4428                       aSign ? packFloat128( 1, 0x3FFF, 0, 0 )
4429                     : packFloat128( 0, 0, 0, 0 );
4430              case float_round_up:
4431                 return
4432                       aSign ? packFloat128( 1, 0, 0, 0 )
4433                     : packFloat128( 0, 0x3FFF, 0, 0 );
4434             }
4435             return packFloat128( aSign, 0, 0, 0 );
4436         }
4437         lastBitMask = 1;
4438         lastBitMask <<= 0x402F - aExp;
4439         roundBitsMask = lastBitMask - 1;
4440         z.low = 0;
4441         z.high = a.high;
4442         roundingMode = STATUS(float_rounding_mode);
4443         if ( roundingMode == float_round_nearest_even ) {
4444             z.high += lastBitMask>>1;
4445             if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) {
4446                 z.high &= ~ lastBitMask;
4447             }
4448         }
4449         else if ( roundingMode != float_round_to_zero ) {
4450             if (   extractFloat128Sign( z )
4451                  ^ ( roundingMode == float_round_up ) ) {
4452                 z.high |= ( a.low != 0 );
4453                 z.high += roundBitsMask;
4454             }
4455         }
4456         z.high &= ~ roundBitsMask;
4457     }
4458     if ( ( z.low != a.low ) || ( z.high != a.high ) ) {
4459         STATUS(float_exception_flags) |= float_flag_inexact;
4460     }
4461     return z;
4462
4463 }
4464
4465 /*----------------------------------------------------------------------------
4466 | Returns the result of adding the absolute values of the quadruple-precision
4467 | floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
4468 | before being returned.  `zSign' is ignored if the result is a NaN.
4469 | The addition is performed according to the IEC/IEEE Standard for Binary
4470 | Floating-Point Arithmetic.
4471 *----------------------------------------------------------------------------*/
4472
4473 static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM)
4474 {
4475     int32 aExp, bExp, zExp;
4476     bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
4477     int32 expDiff;
4478
4479     aSig1 = extractFloat128Frac1( a );
4480     aSig0 = extractFloat128Frac0( a );
4481     aExp = extractFloat128Exp( a );
4482     bSig1 = extractFloat128Frac1( b );
4483     bSig0 = extractFloat128Frac0( b );
4484     bExp = extractFloat128Exp( b );
4485     expDiff = aExp - bExp;
4486     if ( 0 < expDiff ) {
4487         if ( aExp == 0x7FFF ) {
4488             if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4489             return a;
4490         }
4491         if ( bExp == 0 ) {
4492             --expDiff;
4493         }
4494         else {
4495             bSig0 |= LIT64( 0x0001000000000000 );
4496         }
4497         shift128ExtraRightJamming(
4498             bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 );
4499         zExp = aExp;
4500     }
4501     else if ( expDiff < 0 ) {
4502         if ( bExp == 0x7FFF ) {
4503             if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4504             return packFloat128( zSign, 0x7FFF, 0, 0 );
4505         }
4506         if ( aExp == 0 ) {
4507             ++expDiff;
4508         }
4509         else {
4510             aSig0 |= LIT64( 0x0001000000000000 );
4511         }
4512         shift128ExtraRightJamming(
4513             aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 );
4514         zExp = bExp;
4515     }
4516     else {
4517         if ( aExp == 0x7FFF ) {
4518             if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
4519                 return propagateFloat128NaN( a, b STATUS_VAR );
4520             }
4521             return a;
4522         }
4523         add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
4524         if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 );
4525         zSig2 = 0;
4526         zSig0 |= LIT64( 0x0002000000000000 );
4527         zExp = aExp;
4528         goto shiftRight1;
4529     }
4530     aSig0 |= LIT64( 0x0001000000000000 );
4531     add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
4532     --zExp;
4533     if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack;
4534     ++zExp;
4535  shiftRight1:
4536     shift128ExtraRightJamming(
4537         zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
4538  roundAndPack:
4539     return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
4540
4541 }
4542
4543 /*----------------------------------------------------------------------------
4544 | Returns the result of subtracting the absolute values of the quadruple-
4545 | precision floating-point values `a' and `b'.  If `zSign' is 1, the
4546 | difference is negated before being returned.  `zSign' is ignored if the
4547 | result is a NaN.  The subtraction is performed according to the IEC/IEEE
4548 | Standard for Binary Floating-Point Arithmetic.
4549 *----------------------------------------------------------------------------*/
4550
4551 static float128 subFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM)
4552 {
4553     int32 aExp, bExp, zExp;
4554     bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
4555     int32 expDiff;
4556     float128 z;
4557
4558     aSig1 = extractFloat128Frac1( a );
4559     aSig0 = extractFloat128Frac0( a );
4560     aExp = extractFloat128Exp( a );
4561     bSig1 = extractFloat128Frac1( b );
4562     bSig0 = extractFloat128Frac0( b );
4563     bExp = extractFloat128Exp( b );
4564     expDiff = aExp - bExp;
4565     shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
4566     shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 );
4567     if ( 0 < expDiff ) goto aExpBigger;
4568     if ( expDiff < 0 ) goto bExpBigger;
4569     if ( aExp == 0x7FFF ) {
4570         if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
4571             return propagateFloat128NaN( a, b STATUS_VAR );
4572         }
4573         float_raise( float_flag_invalid STATUS_VAR);
4574         z.low = float128_default_nan_low;
4575         z.high = float128_default_nan_high;
4576         return z;
4577     }
4578     if ( aExp == 0 ) {
4579         aExp = 1;
4580         bExp = 1;
4581     }
4582     if ( bSig0 < aSig0 ) goto aBigger;
4583     if ( aSig0 < bSig0 ) goto bBigger;
4584     if ( bSig1 < aSig1 ) goto aBigger;
4585     if ( aSig1 < bSig1 ) goto bBigger;
4586     return packFloat128( STATUS(float_rounding_mode) == float_round_down, 0, 0, 0 );
4587  bExpBigger:
4588     if ( bExp == 0x7FFF ) {
4589         if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4590         return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 );
4591     }
4592     if ( aExp == 0 ) {
4593         ++expDiff;
4594     }
4595     else {
4596         aSig0 |= LIT64( 0x4000000000000000 );
4597     }
4598     shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
4599     bSig0 |= LIT64( 0x4000000000000000 );
4600  bBigger:
4601     sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 );
4602     zExp = bExp;
4603     zSign ^= 1;
4604     goto normalizeRoundAndPack;
4605  aExpBigger:
4606     if ( aExp == 0x7FFF ) {
4607         if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4608         return a;
4609     }
4610     if ( bExp == 0 ) {
4611         --expDiff;
4612     }
4613     else {
4614         bSig0 |= LIT64( 0x4000000000000000 );
4615     }
4616     shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 );
4617     aSig0 |= LIT64( 0x4000000000000000 );
4618  aBigger:
4619     sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
4620     zExp = aExp;
4621  normalizeRoundAndPack:
4622     --zExp;
4623     return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 STATUS_VAR );
4624
4625 }
4626
4627 /*----------------------------------------------------------------------------
4628 | Returns the result of adding the quadruple-precision floating-point values
4629 | `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
4630 | for Binary Floating-Point Arithmetic.
4631 *----------------------------------------------------------------------------*/
4632
4633 float128 float128_add( float128 a, float128 b STATUS_PARAM )
4634 {
4635     flag aSign, bSign;
4636
4637     aSign = extractFloat128Sign( a );
4638     bSign = extractFloat128Sign( b );
4639     if ( aSign == bSign ) {
4640         return addFloat128Sigs( a, b, aSign STATUS_VAR );
4641     }
4642     else {
4643         return subFloat128Sigs( a, b, aSign STATUS_VAR );
4644     }
4645
4646 }
4647
4648 /*----------------------------------------------------------------------------
4649 | Returns the result of subtracting the quadruple-precision floating-point
4650 | values `a' and `b'.  The operation is performed according to the IEC/IEEE
4651 | Standard for Binary Floating-Point Arithmetic.
4652 *----------------------------------------------------------------------------*/
4653
4654 float128 float128_sub( float128 a, float128 b STATUS_PARAM )
4655 {
4656     flag aSign, bSign;
4657
4658     aSign = extractFloat128Sign( a );
4659     bSign = extractFloat128Sign( b );
4660     if ( aSign == bSign ) {
4661         return subFloat128Sigs( a, b, aSign STATUS_VAR );
4662     }
4663     else {
4664         return addFloat128Sigs( a, b, aSign STATUS_VAR );
4665     }
4666
4667 }
4668
4669 /*----------------------------------------------------------------------------
4670 | Returns the result of multiplying the quadruple-precision floating-point
4671 | values `a' and `b'.  The operation is performed according to the IEC/IEEE
4672 | Standard for Binary Floating-Point Arithmetic.
4673 *----------------------------------------------------------------------------*/
4674
4675 float128 float128_mul( float128 a, float128 b STATUS_PARAM )
4676 {
4677     flag aSign, bSign, zSign;
4678     int32 aExp, bExp, zExp;
4679     bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
4680     float128 z;
4681
4682     aSig1 = extractFloat128Frac1( a );
4683     aSig0 = extractFloat128Frac0( a );
4684     aExp = extractFloat128Exp( a );
4685     aSign = extractFloat128Sign( a );
4686     bSig1 = extractFloat128Frac1( b );
4687     bSig0 = extractFloat128Frac0( b );
4688     bExp = extractFloat128Exp( b );
4689     bSign = extractFloat128Sign( b );
4690     zSign = aSign ^ bSign;
4691     if ( aExp == 0x7FFF ) {
4692         if (    ( aSig0 | aSig1 )
4693              || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) {
4694             return propagateFloat128NaN( a, b STATUS_VAR );
4695         }
4696         if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid;
4697         return packFloat128( zSign, 0x7FFF, 0, 0 );
4698     }
4699     if ( bExp == 0x7FFF ) {
4700         if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4701         if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
4702  invalid:
4703             float_raise( float_flag_invalid STATUS_VAR);
4704             z.low = float128_default_nan_low;
4705             z.high = float128_default_nan_high;
4706             return z;
4707         }
4708         return packFloat128( zSign, 0x7FFF, 0, 0 );
4709     }
4710     if ( aExp == 0 ) {
4711         if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
4712         normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
4713     }
4714     if ( bExp == 0 ) {
4715         if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
4716         normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
4717     }
4718     zExp = aExp + bExp - 0x4000;
4719     aSig0 |= LIT64( 0x0001000000000000 );
4720     shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 );
4721     mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 );
4722     add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 );
4723     zSig2 |= ( zSig3 != 0 );
4724     if ( LIT64( 0x0002000000000000 ) <= zSig0 ) {
4725         shift128ExtraRightJamming(
4726             zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
4727         ++zExp;
4728     }
4729     return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
4730
4731 }
4732
4733 /*----------------------------------------------------------------------------
4734 | Returns the result of dividing the quadruple-precision floating-point value
4735 | `a' by the corresponding value `b'.  The operation is performed according to
4736 | the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4737 *----------------------------------------------------------------------------*/
4738
4739 float128 float128_div( float128 a, float128 b STATUS_PARAM )
4740 {
4741     flag aSign, bSign, zSign;
4742     int32 aExp, bExp, zExp;
4743     bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
4744     bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
4745     float128 z;
4746
4747     aSig1 = extractFloat128Frac1( a );
4748     aSig0 = extractFloat128Frac0( a );
4749     aExp = extractFloat128Exp( a );
4750     aSign = extractFloat128Sign( a );
4751     bSig1 = extractFloat128Frac1( b );
4752     bSig0 = extractFloat128Frac0( b );
4753     bExp = extractFloat128Exp( b );
4754     bSign = extractFloat128Sign( b );
4755     zSign = aSign ^ bSign;
4756     if ( aExp == 0x7FFF ) {
4757         if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4758         if ( bExp == 0x7FFF ) {
4759             if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4760             goto invalid;
4761         }
4762         return packFloat128( zSign, 0x7FFF, 0, 0 );
4763     }
4764     if ( bExp == 0x7FFF ) {
4765         if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4766         return packFloat128( zSign, 0, 0, 0 );
4767     }
4768     if ( bExp == 0 ) {
4769         if ( ( bSig0 | bSig1 ) == 0 ) {
4770             if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
4771  invalid:
4772                 float_raise( float_flag_invalid STATUS_VAR);
4773                 z.low = float128_default_nan_low;
4774                 z.high = float128_default_nan_high;
4775                 return z;
4776             }
4777             float_raise( float_flag_divbyzero STATUS_VAR);
4778             return packFloat128( zSign, 0x7FFF, 0, 0 );
4779         }
4780         normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
4781     }
4782     if ( aExp == 0 ) {
4783         if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
4784         normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
4785     }
4786     zExp = aExp - bExp + 0x3FFD;
4787     shortShift128Left(
4788         aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 );
4789     shortShift128Left(
4790         bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
4791     if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) {
4792         shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 );
4793         ++zExp;
4794     }
4795     zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 );
4796     mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
4797     sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
4798     while ( (sbits64) rem0 < 0 ) {
4799         --zSig0;
4800         add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
4801     }
4802     zSig1 = estimateDiv128To64( rem1, rem2, bSig0 );
4803     if ( ( zSig1 & 0x3FFF ) <= 4 ) {
4804         mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
4805         sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
4806         while ( (sbits64) rem1 < 0 ) {
4807             --zSig1;
4808             add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
4809         }
4810         zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
4811     }
4812     shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 );
4813     return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
4814
4815 }
4816
4817 /*----------------------------------------------------------------------------
4818 | Returns the remainder of the quadruple-precision floating-point value `a'
4819 | with respect to the corresponding value `b'.  The operation is performed
4820 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4821 *----------------------------------------------------------------------------*/
4822
4823 float128 float128_rem( float128 a, float128 b STATUS_PARAM )
4824 {
4825     flag aSign, bSign, zSign;
4826     int32 aExp, bExp, expDiff;
4827     bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
4828     bits64 allZero, alternateASig0, alternateASig1, sigMean1;
4829     sbits64 sigMean0;
4830     float128 z;
4831
4832     aSig1 = extractFloat128Frac1( a );
4833     aSig0 = extractFloat128Frac0( a );
4834     aExp = extractFloat128Exp( a );
4835     aSign = extractFloat128Sign( a );
4836     bSig1 = extractFloat128Frac1( b );
4837     bSig0 = extractFloat128Frac0( b );
4838     bExp = extractFloat128Exp( b );
4839     bSign = extractFloat128Sign( b );
4840     if ( aExp == 0x7FFF ) {
4841         if (    ( aSig0 | aSig1 )
4842              || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) {
4843             return propagateFloat128NaN( a, b STATUS_VAR );
4844         }
4845         goto invalid;
4846     }
4847     if ( bExp == 0x7FFF ) {
4848         if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4849         return a;
4850     }
4851     if ( bExp == 0 ) {
4852         if ( ( bSig0 | bSig1 ) == 0 ) {
4853  invalid:
4854             float_raise( float_flag_invalid STATUS_VAR);
4855             z.low = float128_default_nan_low;
4856             z.high = float128_default_nan_high;
4857             return z;
4858         }
4859         normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
4860     }
4861     if ( aExp == 0 ) {
4862         if ( ( aSig0 | aSig1 ) == 0 ) return a;
4863         normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
4864     }
4865     expDiff = aExp - bExp;
4866     if ( expDiff < -1 ) return a;
4867     shortShift128Left(
4868         aSig0 | LIT64( 0x0001000000000000 ),
4869         aSig1,
4870         15 - ( expDiff < 0 ),
4871         &aSig0,
4872         &aSig1
4873     );
4874     shortShift128Left(
4875         bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
4876     q = le128( bSig0, bSig1, aSig0, aSig1 );
4877     if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
4878     expDiff -= 64;
4879     while ( 0 < expDiff ) {
4880         q = estimateDiv128To64( aSig0, aSig1, bSig0 );
4881         q = ( 4 < q ) ? q - 4 : 0;
4882         mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
4883         shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero );
4884         shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero );
4885         sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 );
4886         expDiff -= 61;
4887     }
4888     if ( -64 < expDiff ) {
4889         q = estimateDiv128To64( aSig0, aSig1, bSig0 );
4890         q = ( 4 < q ) ? q - 4 : 0;
4891         q >>= - expDiff;
4892         shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
4893         expDiff += 52;
4894         if ( expDiff < 0 ) {
4895             shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
4896         }
4897         else {
4898             shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 );
4899         }
4900         mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
4901         sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 );
4902     }
4903     else {
4904         shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 );
4905         shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
4906     }
4907     do {
4908         alternateASig0 = aSig0;
4909         alternateASig1 = aSig1;
4910         ++q;
4911         sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
4912     } while ( 0 <= (sbits64) aSig0 );
4913     add128(
4914         aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 );
4915     if (    ( sigMean0 < 0 )
4916          || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) {
4917         aSig0 = alternateASig0;
4918         aSig1 = alternateASig1;
4919     }
4920     zSign = ( (sbits64) aSig0 < 0 );
4921     if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 );
4922     return
4923         normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 STATUS_VAR );
4924
4925 }
4926
4927 /*----------------------------------------------------------------------------
4928 | Returns the square root of the quadruple-precision floating-point value `a'.
4929 | The operation is performed according to the IEC/IEEE Standard for Binary
4930 | Floating-Point Arithmetic.
4931 *----------------------------------------------------------------------------*/
4932
4933 float128 float128_sqrt( float128 a STATUS_PARAM )
4934 {
4935     flag aSign;
4936     int32 aExp, zExp;
4937     bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
4938     bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
4939     float128 z;
4940
4941     aSig1 = extractFloat128Frac1( a );
4942     aSig0 = extractFloat128Frac0( a );
4943     aExp = extractFloat128Exp( a );
4944     aSign = extractFloat128Sign( a );
4945     if ( aExp == 0x7FFF ) {
4946         if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a STATUS_VAR );
4947         if ( ! aSign ) return a;
4948         goto invalid;
4949     }
4950     if ( aSign ) {
4951         if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a;
4952  invalid:
4953         float_raise( float_flag_invalid STATUS_VAR);
4954         z.low = float128_default_nan_low;
4955         z.high = float128_default_nan_high;
4956         return z;
4957     }
4958     if ( aExp == 0 ) {
4959         if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 );
4960         normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
4961     }
4962     zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE;
4963     aSig0 |= LIT64( 0x0001000000000000 );
4964     zSig0 = estimateSqrt32( aExp, aSig0>>17 );
4965     shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 );
4966     zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 );
4967     doubleZSig0 = zSig0<<1;
4968     mul64To128( zSig0, zSig0, &term0, &term1 );
4969     sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
4970     while ( (sbits64) rem0 < 0 ) {
4971         --zSig0;
4972         doubleZSig0 -= 2;
4973         add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
4974     }
4975     zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 );
4976     if ( ( zSig1 & 0x1FFF ) <= 5 ) {
4977         if ( zSig1 == 0 ) zSig1 = 1;
4978         mul64To128( doubleZSig0, zSig1, &term1, &term2 );
4979         sub128( rem1, 0, term1, term2, &rem1, &rem2 );
4980         mul64To128( zSig1, zSig1, &term2, &term3 );
4981         sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
4982         while ( (sbits64) rem1 < 0 ) {
4983             --zSig1;
4984             shortShift128Left( 0, zSig1, 1, &term2, &term3 );
4985             term3 |= 1;
4986             term2 |= doubleZSig0;
4987             add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
4988         }
4989         zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
4990     }
4991     shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 );
4992     return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
4993
4994 }
4995
4996 /*----------------------------------------------------------------------------
4997 | Returns 1 if the quadruple-precision floating-point value `a' is equal to
4998 | the corresponding value `b', and 0 otherwise.  The comparison is performed
4999 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5000 *----------------------------------------------------------------------------*/
5001
5002 flag float128_eq( float128 a, float128 b STATUS_PARAM )
5003 {
5004
5005     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
5006               && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5007          || (    ( extractFloat128Exp( b ) == 0x7FFF )
5008               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5009        ) {
5010         if (    float128_is_signaling_nan( a )
5011              || float128_is_signaling_nan( b ) ) {
5012             float_raise( float_flag_invalid STATUS_VAR);
5013         }
5014         return 0;
5015     }
5016     return
5017            ( a.low == b.low )
5018         && (    ( a.high == b.high )
5019              || (    ( a.low == 0 )
5020                   && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) )
5021            );
5022
5023 }
5024
5025 /*----------------------------------------------------------------------------
5026 | Returns 1 if the quadruple-precision floating-point value `a' is less than
5027 | or equal to the corresponding value `b', and 0 otherwise.  The comparison
5028 | is performed according to the IEC/IEEE Standard for Binary Floating-Point
5029 | Arithmetic.
5030 *----------------------------------------------------------------------------*/
5031
5032 flag float128_le( float128 a, float128 b STATUS_PARAM )
5033 {
5034     flag aSign, bSign;
5035
5036     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
5037               && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5038          || (    ( extractFloat128Exp( b ) == 0x7FFF )
5039               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5040        ) {
5041         float_raise( float_flag_invalid STATUS_VAR);
5042         return 0;
5043     }
5044     aSign = extractFloat128Sign( a );
5045     bSign = extractFloat128Sign( b );
5046     if ( aSign != bSign ) {
5047         return
5048                aSign
5049             || (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
5050                  == 0 );
5051     }
5052     return
5053           aSign ? le128( b.high, b.low, a.high, a.low )
5054         : le128( a.high, a.low, b.high, b.low );
5055
5056 }
5057
5058 /*----------------------------------------------------------------------------
5059 | Returns 1 if the quadruple-precision floating-point value `a' is less than
5060 | the corresponding value `b', and 0 otherwise.  The comparison is performed
5061 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5062 *----------------------------------------------------------------------------*/
5063
5064 flag float128_lt( float128 a, float128 b STATUS_PARAM )
5065 {
5066     flag aSign, bSign;
5067
5068     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
5069               && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5070          || (    ( extractFloat128Exp( b ) == 0x7FFF )
5071               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5072        ) {
5073         float_raise( float_flag_invalid STATUS_VAR);
5074         return 0;
5075     }
5076     aSign = extractFloat128Sign( a );
5077     bSign = extractFloat128Sign( b );
5078     if ( aSign != bSign ) {
5079         return
5080                aSign
5081             && (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
5082                  != 0 );
5083     }
5084     return
5085           aSign ? lt128( b.high, b.low, a.high, a.low )
5086         : lt128( a.high, a.low, b.high, b.low );
5087
5088 }
5089
5090 /*----------------------------------------------------------------------------
5091 | Returns 1 if the quadruple-precision floating-point value `a' is equal to
5092 | the corresponding value `b', and 0 otherwise.  The invalid exception is
5093 | raised if either operand is a NaN.  Otherwise, the comparison is performed
5094 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5095 *----------------------------------------------------------------------------*/
5096
5097 flag float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
5098 {
5099
5100     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
5101               && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5102          || (    ( extractFloat128Exp( b ) == 0x7FFF )
5103               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5104        ) {
5105         float_raise( float_flag_invalid STATUS_VAR);
5106         return 0;
5107     }
5108     return
5109            ( a.low == b.low )
5110         && (    ( a.high == b.high )
5111              || (    ( a.low == 0 )
5112                   && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) )
5113            );
5114
5115 }
5116
5117 /*----------------------------------------------------------------------------
5118 | Returns 1 if the quadruple-precision floating-point value `a' is less than
5119 | or equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
5120 | cause an exception.  Otherwise, the comparison is performed according to the
5121 | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5122 *----------------------------------------------------------------------------*/
5123
5124 flag float128_le_quiet( float128 a, float128 b STATUS_PARAM )
5125 {
5126     flag aSign, bSign;
5127
5128     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
5129               && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5130          || (    ( extractFloat128Exp( b ) == 0x7FFF )
5131               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5132        ) {
5133         if (    float128_is_signaling_nan( a )
5134              || float128_is_signaling_nan( b ) ) {
5135             float_raise( float_flag_invalid STATUS_VAR);
5136         }
5137         return 0;
5138     }
5139     aSign = extractFloat128Sign( a );
5140     bSign = extractFloat128Sign( b );
5141     if ( aSign != bSign ) {
5142         return
5143                aSign
5144             || (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
5145                  == 0 );
5146     }
5147     return
5148           aSign ? le128( b.high, b.low, a.high, a.low )
5149         : le128( a.high, a.low, b.high, b.low );
5150
5151 }
5152
5153 /*----------------------------------------------------------------------------
5154 | Returns 1 if the quadruple-precision floating-point value `a' is less than
5155 | the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
5156 | exception.  Otherwise, the comparison is performed according to the IEC/IEEE
5157 | Standard for Binary Floating-Point Arithmetic.
5158 *----------------------------------------------------------------------------*/
5159
5160 flag float128_lt_quiet( float128 a, float128 b STATUS_PARAM )
5161 {
5162     flag aSign, bSign;
5163
5164     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
5165               && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5166          || (    ( extractFloat128Exp( b ) == 0x7FFF )
5167               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5168        ) {
5169         if (    float128_is_signaling_nan( a )
5170              || float128_is_signaling_nan( b ) ) {
5171             float_raise( float_flag_invalid STATUS_VAR);
5172         }
5173         return 0;
5174     }
5175     aSign = extractFloat128Sign( a );
5176     bSign = extractFloat128Sign( b );
5177     if ( aSign != bSign ) {
5178         return
5179                aSign
5180             && (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
5181                  != 0 );
5182     }
5183     return
5184           aSign ? lt128( b.high, b.low, a.high, a.low )
5185         : lt128( a.high, a.low, b.high, b.low );
5186
5187 }
5188
5189 #endif
5190
5191 /* misc functions */
5192 float32 uint32_to_float32( unsigned int a STATUS_PARAM )
5193 {
5194     return int64_to_float32(a STATUS_VAR);
5195 }
5196
5197 float64 uint32_to_float64( unsigned int a STATUS_PARAM )
5198 {
5199     return int64_to_float64(a STATUS_VAR);
5200 }
5201
5202 unsigned int float32_to_uint32( float32 a STATUS_PARAM )
5203 {
5204     int64_t v;
5205     unsigned int res;
5206
5207     v = float32_to_int64(a STATUS_VAR);
5208     if (v < 0) {
5209         res = 0;
5210         float_raise( float_flag_invalid STATUS_VAR);
5211     } else if (v > 0xffffffff) {
5212         res = 0xffffffff;
5213         float_raise( float_flag_invalid STATUS_VAR);
5214     } else {
5215         res = v;
5216     }
5217     return res;
5218 }
5219
5220 unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM )
5221 {
5222     int64_t v;
5223     unsigned int res;
5224
5225     v = float32_to_int64_round_to_zero(a STATUS_VAR);
5226     if (v < 0) {
5227         res = 0;
5228         float_raise( float_flag_invalid STATUS_VAR);
5229     } else if (v > 0xffffffff) {
5230         res = 0xffffffff;
5231         float_raise( float_flag_invalid STATUS_VAR);
5232     } else {
5233         res = v;
5234     }
5235     return res;
5236 }
5237
5238 unsigned int float64_to_uint32( float64 a STATUS_PARAM )
5239 {
5240     int64_t v;
5241     unsigned int res;
5242
5243     v = float64_to_int64(a STATUS_VAR);
5244     if (v < 0) {
5245         res = 0;
5246         float_raise( float_flag_invalid STATUS_VAR);
5247     } else if (v > 0xffffffff) {
5248         res = 0xffffffff;
5249         float_raise( float_flag_invalid STATUS_VAR);
5250     } else {
5251         res = v;
5252     }
5253     return res;
5254 }
5255
5256 unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM )
5257 {
5258     int64_t v;
5259     unsigned int res;
5260
5261     v = float64_to_int64_round_to_zero(a STATUS_VAR);
5262     if (v < 0) {
5263         res = 0;
5264         float_raise( float_flag_invalid STATUS_VAR);
5265     } else if (v > 0xffffffff) {
5266         res = 0xffffffff;
5267         float_raise( float_flag_invalid STATUS_VAR);
5268     } else {
5269         res = v;
5270     }
5271     return res;
5272 }
5273
5274 #define COMPARE(s, nan_exp)                                                  \
5275 INLINE char float ## s ## _compare_internal( float ## s a, float ## s b,     \
5276                                       int is_quiet STATUS_PARAM )            \
5277 {                                                                            \
5278     flag aSign, bSign;                                                       \
5279                                                                              \
5280     if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) &&                    \
5281          extractFloat ## s ## Frac( a ) ) ||                                 \
5282         ( ( extractFloat ## s ## Exp( b ) == nan_exp ) &&                    \
5283           extractFloat ## s ## Frac( b ) )) {                                \
5284         if (!is_quiet ||                                                     \
5285             float ## s ## _is_signaling_nan( a ) ||                          \
5286             float ## s ## _is_signaling_nan( b ) ) {                         \
5287             float_raise( float_flag_invalid STATUS_VAR);                     \
5288         }                                                                    \
5289         return float_relation_unordered;                                     \
5290     }                                                                        \
5291     aSign = extractFloat ## s ## Sign( a );                                  \
5292     bSign = extractFloat ## s ## Sign( b );                                  \
5293     if ( aSign != bSign ) {                                                  \
5294         if ( (bits ## s) ( ( a | b )<<1 ) == 0 ) {                           \
5295             /* zero case */                                                  \
5296             return float_relation_equal;                                     \
5297         } else {                                                             \
5298             return 1 - (2 * aSign);                                          \
5299         }                                                                    \
5300     } else {                                                                 \
5301         if (a == b) {                                                        \
5302             return float_relation_equal;                                     \
5303         } else {                                                             \
5304             return 1 - 2 * (aSign ^ ( a < b ));                              \
5305         }                                                                    \
5306     }                                                                        \
5307 }                                                                            \
5308                                                                              \
5309 char float ## s ## _compare( float ## s a, float ## s b STATUS_PARAM )       \
5310 {                                                                            \
5311     return float ## s ## _compare_internal(a, b, 0 STATUS_VAR);              \
5312 }                                                                            \
5313                                                                              \
5314 char float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
5315 {                                                                            \
5316     return float ## s ## _compare_internal(a, b, 1 STATUS_VAR);              \
5317 }
5318
5319 COMPARE(32, 0xff)
5320 COMPARE(64, 0x7ff)