]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/test/testfloat/slowfloat-64.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / test / testfloat / slowfloat-64.c
1
2 /*
3 ===============================================================================
4
5 This C source file is part of TestFloat, Release 2a, a package of programs
6 for testing the correctness of floating-point arithmetic complying to the
7 IEC/IEEE Standard for Floating-Point.
8
9 Written by John R. Hauser.  More information is available through the Web
10 page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'.
11
12 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
13 has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
14 TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
15 PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
16 AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
17
18 Derivative works are acceptable, even for commercial purposes, so long as
19 (1) they include prominent notice that the work is derivative, and (2) they
20 include prominent notice akin to these four paragraphs for those parts of
21 this code that are retained.
22
23 ===============================================================================
24 */
25
26 int8 slow_float_rounding_mode;
27 int8 slow_float_exception_flags;
28 int8 slow_float_detect_tininess;
29 #ifdef FLOATX80
30 int8 slow_floatx80_rounding_precision;
31 #endif
32
33 typedef struct {
34     bits64 a0, a1;
35 } bits128X;
36
37 typedef struct {
38     flag isNaN;
39     flag isInf;
40     flag isZero;
41     flag sign;
42     int32 exp;
43     bits128X sig;
44 } floatX;
45
46 static const floatX floatXNaN = { TRUE, FALSE, FALSE, FALSE, 0, { 0, 0 } };
47 static const floatX floatXPositiveZero =
48     { FALSE, FALSE, TRUE, FALSE, 0, { 0, 0 } };
49 static const floatX floatXNegativeZero =
50     { FALSE, FALSE, TRUE, TRUE, 0, { 0, 0 } };
51
52 static bits128X shortShift128Left( bits128X a, int8 shiftCount )
53 {
54     int8 negShiftCount;
55
56     negShiftCount = ( - shiftCount & 63 );
57     a.a0 = ( a.a0<<shiftCount ) | ( a.a1>>negShiftCount );
58     a.a1 <<= shiftCount;
59     return a;
60
61 }
62
63 static bits128X shortShift128RightJamming( bits128X a, int8 shiftCount )
64 {
65     int8 negShiftCount;
66     bits64 extra;
67
68     negShiftCount = ( - shiftCount & 63 );
69     extra = a.a1<<negShiftCount;
70     a.a1 = ( a.a0<<negShiftCount ) | ( a.a1>>shiftCount ) | ( extra != 0 );
71     a.a0 >>= shiftCount;
72     return a;
73
74 }
75
76 static bits128X neg128( bits128X a )
77 {
78
79     if ( a.a1 == 0 ) {
80         a.a0 = - a.a0;
81     }
82     else {
83         a.a1 = - a.a1;
84         a.a0 = ~ a.a0;
85     }
86     return a;
87
88 }
89
90 static bits128X add128( bits128X a, bits128X b )
91 {
92
93     a.a1 += b.a1;
94     a.a0 += b.a0 + ( a.a1 < b.a1 );
95     return a;
96
97 }
98
99 static flag eq128( bits128X a, bits128X b )
100 {
101
102     return ( a.a0 == b.a0 ) && ( a.a1 == b.a1 );
103
104 }
105
106 static flag le128( bits128X a, bits128X b )
107 {
108
109     return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 <= b.a1 ) );
110
111 }
112
113 static flag lt128( bits128X a, bits128X b )
114 {
115
116     return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 < b.a1 ) );
117
118 }
119
120 static floatX roundFloatXTo24( flag isTiny, floatX zx )
121 {
122     bits32 roundBits;
123
124     zx.sig.a0 |= ( zx.sig.a1 != 0 );
125     zx.sig.a1 = 0;
126     roundBits = zx.sig.a0 & 0xFFFFFFFF;
127     zx.sig.a0 -= roundBits;
128     if ( roundBits ) {
129         slow_float_exception_flags |= float_flag_inexact;
130         if ( isTiny ) slow_float_exception_flags |= float_flag_underflow;
131         switch ( slow_float_rounding_mode ) {
132          case float_round_nearest_even:
133             if ( roundBits < 0x80000000 ) goto noIncrement;
134             if (    ( roundBits == 0x80000000 )
135                  && ! ( zx.sig.a0 & LIT64( 0x100000000 ) ) ) {
136                 goto noIncrement;
137             }
138             break;
139          case float_round_to_zero:
140             goto noIncrement;
141          case float_round_down:
142             if ( ! zx.sign ) goto noIncrement;
143             break;
144          case float_round_up:
145             if ( zx.sign ) goto noIncrement;
146             break;
147         }
148         zx.sig.a0 += LIT64( 0x100000000 );
149         if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) {
150             zx.sig.a0 = LIT64( 0x0080000000000000 );
151             ++zx.exp;
152         }
153     }
154  noIncrement:
155     return zx;
156
157 }
158
159 static floatX roundFloatXTo53( flag isTiny, floatX zx )
160 {
161     int8 roundBits;
162
163     zx.sig.a0 |= ( zx.sig.a1 != 0 );
164     zx.sig.a1 = 0;
165     roundBits = zx.sig.a0 & 7;
166     zx.sig.a0 -= roundBits;
167     if ( roundBits ) {
168         slow_float_exception_flags |= float_flag_inexact;
169         if ( isTiny ) slow_float_exception_flags |= float_flag_underflow;
170         switch ( slow_float_rounding_mode ) {
171          case float_round_nearest_even:
172             if ( roundBits < 4 ) goto noIncrement;
173             if ( ( roundBits == 4 ) && ! ( zx.sig.a0 & 8 ) ) goto noIncrement;
174             break;
175          case float_round_to_zero:
176             goto noIncrement;
177          case float_round_down:
178             if ( ! zx.sign ) goto noIncrement;
179             break;
180          case float_round_up:
181             if ( zx.sign ) goto noIncrement;
182             break;
183         }
184         zx.sig.a0 += 8;
185         if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) {
186             zx.sig.a0 = LIT64( 0x0080000000000000 );
187             ++zx.exp;
188         }
189     }
190  noIncrement:
191     return zx;
192
193 }
194
195 static floatX roundFloatXTo64( flag isTiny, floatX zx )
196 {
197     int64 roundBits;
198
199     roundBits = zx.sig.a1 & LIT64( 0x00FFFFFFFFFFFFFF );
200     zx.sig.a1 -= roundBits;
201     if ( roundBits ) {
202         slow_float_exception_flags |= float_flag_inexact;
203         if ( isTiny ) slow_float_exception_flags |= float_flag_underflow;
204         switch ( slow_float_rounding_mode ) {
205          case float_round_nearest_even:
206             if ( roundBits < LIT64( 0x0080000000000000 ) ) goto noIncrement;
207             if (    ( roundBits == LIT64( 0x0080000000000000 ) )
208                  && ! ( zx.sig.a1 & LIT64( 0x0100000000000000 ) ) ) {
209                 goto noIncrement;
210             }
211             break;
212          case float_round_to_zero:
213             goto noIncrement;
214          case float_round_down:
215             if ( ! zx.sign ) goto noIncrement;
216             break;
217          case float_round_up:
218             if ( zx.sign ) goto noIncrement;
219             break;
220         }
221         zx.sig.a1 += LIT64( 0x0100000000000000 );
222         zx.sig.a0 += ( zx.sig.a1 == 0 );
223         if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) {
224             zx.sig.a0 = LIT64( 0x0080000000000000 );
225             ++zx.exp;
226         }
227     }
228  noIncrement:
229     return zx;
230
231 }
232
233 static floatX roundFloatXTo113( flag isTiny, floatX zx )
234 {
235     int8 roundBits;
236
237     roundBits = zx.sig.a1 & 0x7F;
238     zx.sig.a1 -= roundBits;
239     if ( roundBits ) {
240         slow_float_exception_flags |= float_flag_inexact;
241         if ( isTiny ) slow_float_exception_flags |= float_flag_underflow;
242         switch ( slow_float_rounding_mode ) {
243          case float_round_nearest_even:
244             if ( roundBits < 0x40 ) goto noIncrement;
245             if (    ( roundBits == 0x40 )
246                  && ! ( zx.sig.a1 & 0x80 ) ) goto noIncrement;
247             break;
248          case float_round_to_zero:
249             goto noIncrement;
250          case float_round_down:
251             if ( ! zx.sign ) goto noIncrement;
252             break;
253          case float_round_up:
254             if ( zx.sign ) goto noIncrement;
255             break;
256         }
257         zx.sig.a1 += 0x80;
258         zx.sig.a0 += ( zx.sig.a1 == 0 );
259         if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) {
260             zx.sig.a0 = LIT64( 0x0080000000000000 );
261             ++zx.exp;
262         }
263     }
264  noIncrement:
265     return zx;
266
267 }
268
269 static floatX int32ToFloatX( int32 a )
270 {
271     floatX ax;
272
273     ax.isNaN = FALSE;
274     ax.isInf = FALSE;
275     ax.sign = ( a < 0 );
276     ax.sig.a1 = 0;
277     ax.sig.a0 = ax.sign ? - (bits64) a : a;
278     if ( a == 0 ) {
279         ax.isZero = TRUE;
280         return ax;
281     }
282     ax.isZero = FALSE;
283     ax.sig.a0 <<= 24;
284     ax.exp = 31;
285     while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) ) {
286         ax.sig.a0 <<= 1;
287         --ax.exp;
288     }
289     return ax;
290
291 }
292
293 static int32 floatXToInt32( floatX ax )
294 {
295     int8 savedExceptionFlags;
296     int32 shiftCount;
297     int32 z;
298
299     if ( ax.isInf || ax.isNaN ) {
300         slow_float_exception_flags |= float_flag_invalid;
301         return ( ax.isInf & ax.sign ) ? (sbits32) 0x80000000 : 0x7FFFFFFF;
302     }
303     if ( ax.isZero ) return 0;
304     savedExceptionFlags = slow_float_exception_flags;
305     shiftCount = 52 - ax.exp;
306     if ( 56 < shiftCount ) {
307         ax.sig.a1 = 1;
308         ax.sig.a0 = 0;
309     }
310     else {
311         while ( 0 < shiftCount ) {
312             ax.sig = shortShift128RightJamming( ax.sig, 1 );
313             --shiftCount;
314         }
315     }
316     ax = roundFloatXTo53( FALSE, ax );
317     ax.sig = shortShift128RightJamming( ax.sig, 3 );
318     z = ax.sig.a0;
319     if ( ax.sign ) z = - z;
320     if (    ( shiftCount < 0 )
321          || ( ax.sig.a0>>32 )
322          || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) )
323        ) {
324         slow_float_exception_flags = savedExceptionFlags | float_flag_invalid;
325         return ax.sign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
326     }
327     return z;
328
329 }
330
331 static floatX int64ToFloatX( int64 a )
332 {
333     uint64 absA;
334     floatX ax;
335
336     ax.isNaN = FALSE;
337     ax.isInf = FALSE;
338     ax.sign = ( a < 0 );
339     ax.sig.a1 = ax.sign ? - a : a;
340     ax.sig.a0 = 0;
341     if ( a == 0 ) {
342         ax.isZero = TRUE;
343         return ax;
344     }
345     ax.isZero = FALSE;
346     ax.sig = shortShift128Left( ax.sig, 56 );
347     ax.exp = 63;
348     while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) ) {
349         ax.sig = shortShift128Left( ax.sig, 1 );
350         --ax.exp;
351     }
352     return ax;
353
354 }
355
356 static int64 floatXToInt64( floatX ax )
357 {
358     int8 savedExceptionFlags;
359     int32 shiftCount;
360     int64 z;
361
362     if ( ax.isInf || ax.isNaN ) {
363         slow_float_exception_flags |= float_flag_invalid;
364         return
365               ( ax.isInf & ax.sign ) ? (sbits64) LIT64( 0x8000000000000000 )
366             : LIT64( 0x7FFFFFFFFFFFFFFF );
367     }
368     if ( ax.isZero ) return 0;
369     savedExceptionFlags = slow_float_exception_flags;
370     shiftCount = 112 - ax.exp;
371     if ( 116 < shiftCount ) {
372         ax.sig.a1 = 1;
373         ax.sig.a0 = 0;
374     }
375     else {
376         while ( 0 < shiftCount ) {
377             ax.sig = shortShift128RightJamming( ax.sig, 1 );
378             --shiftCount;
379         }
380     }
381     ax = roundFloatXTo113( FALSE, ax );
382     ax.sig = shortShift128RightJamming( ax.sig, 7 );
383     z = ax.sig.a1;
384     if ( ax.sign ) z = - z;
385     if (    ( shiftCount < 0 )
386          || ax.sig.a0
387          || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) )
388        ) {
389         slow_float_exception_flags = savedExceptionFlags | float_flag_invalid;
390         return
391               ax.sign ? (sbits64) LIT64( 0x8000000000000000 )
392             : LIT64( 0x7FFFFFFFFFFFFFFF );
393     }
394     return z;
395
396 }
397
398 static floatX float32ToFloatX( float32 a )
399 {
400     int16 expField;
401     floatX ax;
402
403     ax.isNaN = FALSE;
404     ax.isInf = FALSE;
405     ax.isZero = FALSE;
406     ax.sign = ( ( a & 0x80000000 ) != 0 );
407     expField = ( a>>23 ) & 0xFF;
408     ax.sig.a1 = 0;
409     ax.sig.a0 = a & 0x007FFFFF;
410     ax.sig.a0 <<= 32;
411     if ( expField == 0 ) {
412         if ( ax.sig.a0 == 0 ) {
413             ax.isZero = TRUE;
414         }
415         else {
416             expField = 1 - 0x7F;
417             do {
418                 ax.sig.a0 <<= 1;
419                 --expField;
420             } while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) );
421             ax.exp = expField;
422         }
423     }
424     else if ( expField == 0xFF ) {
425         if ( ax.sig.a0 == 0 ) {
426             ax.isInf = TRUE;
427         }
428         else {
429             ax.isNaN = TRUE;
430         }
431     }
432     else {
433         ax.sig.a0 |= LIT64( 0x0080000000000000 );
434         ax.exp = expField - 0x7F;
435     }
436     return ax;
437
438 }
439
440 static float32 floatXToFloat32( floatX zx )
441 {
442     floatX savedZ;
443     flag isTiny;
444     int32 expField;
445     float32 z;
446
447     if ( zx.isZero ) return zx.sign ? 0x80000000 : 0;
448     if ( zx.isInf ) return zx.sign ? 0xFF800000 : 0x7F800000;
449     if ( zx.isNaN ) return 0xFFFFFFFF;
450     while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) {
451         zx.sig = shortShift128RightJamming( zx.sig, 1 );
452         ++zx.exp;
453     }
454     while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) {
455         zx.sig = shortShift128Left( zx.sig, 1 );
456         --zx.exp;
457     }
458     savedZ = zx;
459     isTiny =
460            ( slow_float_detect_tininess == float_tininess_before_rounding )
461         && ( zx.exp + 0x7F <= 0 );
462     zx = roundFloatXTo24( isTiny, zx );
463     expField = zx.exp + 0x7F;
464     if ( 0xFF <= expField ) {
465         slow_float_exception_flags |=
466             float_flag_overflow | float_flag_inexact;
467         if ( zx.sign ) {
468             switch ( slow_float_rounding_mode ) {
469              case float_round_nearest_even:
470              case float_round_down:
471                 z = 0xFF800000;
472                 break;
473              case float_round_to_zero:
474              case float_round_up:
475                 z = 0xFF7FFFFF;
476                 break;
477             }
478         }
479         else {
480             switch ( slow_float_rounding_mode ) {
481              case float_round_nearest_even:
482              case float_round_up:
483                 z = 0x7F800000;
484                 break;
485              case float_round_to_zero:
486              case float_round_down:
487                 z = 0x7F7FFFFF;
488                 break;
489             }
490         }
491         return z;
492     }
493     if ( expField <= 0 ) {
494         isTiny = TRUE;
495         zx = savedZ;
496         expField = zx.exp + 0x7F;
497         if ( expField < -27 ) {
498             zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 );
499             zx.sig.a0 = 0;
500         }
501         else {
502             while ( expField <= 0 ) {
503                 zx.sig = shortShift128RightJamming( zx.sig, 1 );
504                 ++expField;
505             }
506         }
507         zx = roundFloatXTo24( isTiny, zx );
508         expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0;
509     }
510     z = expField;
511     z <<= 23;
512     if ( zx.sign ) z |= 0x80000000;
513     z |= ( zx.sig.a0>>32 ) & 0x007FFFFF;
514     return z;
515
516 }
517
518 static floatX float64ToFloatX( float64 a )
519 {
520     int16 expField;
521     floatX ax;
522
523     ax.isNaN = FALSE;
524     ax.isInf = FALSE;
525     ax.isZero = FALSE;
526     ax.sign = ( ( a & LIT64( 0x8000000000000000 ) ) != 0 );
527     expField = ( a>>52 ) & 0x7FF;
528     ax.sig.a1 = 0;
529     ax.sig.a0 = a & LIT64( 0x000FFFFFFFFFFFFF );
530     if ( expField == 0 ) {
531         if ( ax.sig.a0 == 0 ) {
532             ax.isZero = TRUE;
533         }
534         else {
535             expField = 1 - 0x3FF;
536             do {
537                 ax.sig.a0 <<= 1;
538                 --expField;
539             } while ( ax.sig.a0 < LIT64( 0x0010000000000000 ) );
540             ax.exp = expField;
541         }
542     }
543     else if ( expField == 0x7FF ) {
544         if ( ax.sig.a0 == 0 ) {
545             ax.isInf = TRUE;
546         }
547         else {
548             ax.isNaN = TRUE;
549         }
550     }
551     else {
552         ax.exp = expField - 0x3FF;
553         ax.sig.a0 |= LIT64( 0x0010000000000000 );
554     }
555     ax.sig.a0 <<= 3;
556     return ax;
557
558 }
559
560 static float64 floatXToFloat64( floatX zx )
561 {
562     floatX savedZ;
563     flag isTiny;
564     int32 expField;
565     float64 z;
566
567     if ( zx.isZero ) return zx.sign ? LIT64( 0x8000000000000000 ) : 0;
568     if ( zx.isInf ) {
569         return
570               zx.sign ? LIT64( 0xFFF0000000000000 )
571             : LIT64( 0x7FF0000000000000 );
572     }
573     if ( zx.isNaN ) return LIT64( 0xFFFFFFFFFFFFFFFF );
574     while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) {
575         zx.sig = shortShift128RightJamming( zx.sig, 1 );
576         ++zx.exp;
577     }
578     while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) {
579         zx.sig = shortShift128Left( zx.sig, 1 );
580         --zx.exp;
581     }
582     savedZ = zx;
583     isTiny =
584            ( slow_float_detect_tininess == float_tininess_before_rounding )
585         && ( zx.exp + 0x3FF <= 0 );
586     zx = roundFloatXTo53( isTiny, zx );
587     expField = zx.exp + 0x3FF;
588     if ( 0x7FF <= expField ) {
589         slow_float_exception_flags |=
590             float_flag_overflow | float_flag_inexact;
591         if ( zx.sign ) {
592             switch ( slow_float_rounding_mode ) {
593              case float_round_nearest_even:
594              case float_round_down:
595                 z = LIT64( 0xFFF0000000000000 );
596                 break;
597              case float_round_to_zero:
598              case float_round_up:
599                 z = LIT64( 0xFFEFFFFFFFFFFFFF );
600                 break;
601             }
602         }
603         else {
604             switch ( slow_float_rounding_mode ) {
605              case float_round_nearest_even:
606              case float_round_up:
607                 z = LIT64( 0x7FF0000000000000 );
608                 break;
609              case float_round_to_zero:
610              case float_round_down:
611                 z = LIT64( 0x7FEFFFFFFFFFFFFF );
612                 break;
613             }
614         }
615         return z;
616     }
617     if ( expField <= 0 ) {
618         isTiny = TRUE;
619         zx = savedZ;
620         expField = zx.exp + 0x3FF;
621         if ( expField < -56 ) {
622             zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 );
623             zx.sig.a0 = 0;
624         }
625         else {
626             while ( expField <= 0 ) {
627                 zx.sig = shortShift128RightJamming( zx.sig, 1 );
628                 ++expField;
629             }
630         }
631         zx = roundFloatXTo53( isTiny, zx );
632         expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0;
633     }
634     zx.sig.a0 >>= 3;
635     z = expField;
636     z <<= 52;
637     if ( zx.sign ) z |= LIT64( 0x8000000000000000 );
638     z |= zx.sig.a0 & LIT64( 0x000FFFFFFFFFFFFF );
639     return z;
640
641 }
642
643 #ifdef FLOATX80
644
645 static floatX floatx80ToFloatX( floatx80 a )
646 {
647     int32 expField;
648     floatX ax;
649
650     ax.isNaN = FALSE;
651     ax.isInf = FALSE;
652     ax.isZero = FALSE;
653     ax.sign = ( ( a.high & 0x8000 ) != 0 );
654     expField = a.high & 0x7FFF;
655     ax.sig.a1 = a.low;
656     ax.sig.a0 = 0;
657     if ( expField == 0 ) {
658         if ( ax.sig.a1 == 0 ) {
659             ax.isZero = TRUE;
660         }
661         else {
662             expField = 1 - 0x3FFF;
663             while ( ax.sig.a1 < LIT64( 0x8000000000000000 ) ) {
664                 ax.sig.a1 <<= 1;
665                 --expField;
666             }
667             ax.exp = expField;
668         }
669     }
670     else if ( expField == 0x7FFF ) {
671         if ( ( ax.sig.a1 & LIT64( 0x7FFFFFFFFFFFFFFF ) ) == 0 ) {
672             ax.isInf = TRUE;
673         }
674         else {
675             ax.isNaN = TRUE;
676         }
677     }
678     else {
679         ax.exp = expField - 0x3FFF;
680     }
681     ax.sig = shortShift128Left( ax.sig, 56 );
682     return ax;
683
684 }
685
686 static floatx80 floatXToFloatx80( floatX zx )
687 {
688     floatX savedZ;
689     flag isTiny;
690     int32 expField;
691     floatx80 z;
692
693     if ( zx.isZero ) {
694         z.low = 0;
695         z.high = zx.sign ? 0x8000 : 0;
696         return z;
697     }
698     if ( zx.isInf ) {
699         z.low = LIT64( 0x8000000000000000 );
700         z.high = zx.sign ? 0xFFFF : 0x7FFF;
701         return z;
702     }
703     if ( zx.isNaN ) {
704         z.low = LIT64( 0xFFFFFFFFFFFFFFFF );
705         z.high = 0xFFFF;
706         return z;
707     }
708     while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) {
709         zx.sig = shortShift128RightJamming( zx.sig, 1 );
710         ++zx.exp;
711     }
712     while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) {
713         zx.sig = shortShift128Left( zx.sig, 1 );
714         --zx.exp;
715     }
716     savedZ = zx;
717     isTiny =
718            ( slow_float_detect_tininess == float_tininess_before_rounding )
719         && ( zx.exp + 0x3FFF <= 0 );
720     switch ( slow_floatx80_rounding_precision ) {
721      case 32:
722         zx = roundFloatXTo24( isTiny, zx );
723         break;
724      case 64:
725         zx = roundFloatXTo53( isTiny, zx );
726         break;
727      default:
728         zx = roundFloatXTo64( isTiny, zx );
729         break;
730     }
731     expField = zx.exp + 0x3FFF;
732     if ( 0x7FFF <= expField ) {
733         slow_float_exception_flags |=
734             float_flag_overflow | float_flag_inexact;
735         if ( zx.sign ) {
736             switch ( slow_float_rounding_mode ) {
737              case float_round_nearest_even:
738              case float_round_down:
739                 z.low = LIT64( 0x8000000000000000 );
740                 z.high = 0xFFFF;
741                 break;
742              case float_round_to_zero:
743              case float_round_up:
744                 switch ( slow_floatx80_rounding_precision ) {
745                  case 32:
746                     z.low = LIT64( 0xFFFFFF0000000000 );
747                     break;
748                  case 64:
749                     z.low = LIT64( 0xFFFFFFFFFFFFF800 );
750                     break;
751                  default:
752                     z.low = LIT64( 0xFFFFFFFFFFFFFFFF );
753                     break;
754                 }
755                 z.high = 0xFFFE;
756                 break;
757             }
758         }
759         else {
760             switch ( slow_float_rounding_mode ) {
761              case float_round_nearest_even:
762              case float_round_up:
763                 z.low = LIT64( 0x8000000000000000 );
764                 z.high = 0x7FFF;
765                 break;
766              case float_round_to_zero:
767              case float_round_down:
768                 switch ( slow_floatx80_rounding_precision ) {
769                  case 32:
770                     z.low = LIT64( 0xFFFFFF0000000000 );
771                     break;
772                  case 64:
773                     z.low = LIT64( 0xFFFFFFFFFFFFF800 );
774                     break;
775                  default:
776                     z.low = LIT64( 0xFFFFFFFFFFFFFFFF );
777                     break;
778                 }
779                 z.high = 0x7FFE;
780                 break;
781             }
782         }
783         return z;
784     }
785     if ( expField <= 0 ) {
786         isTiny = TRUE;
787         zx = savedZ;
788         expField = zx.exp + 0x3FFF;
789         if ( expField < -70 ) {
790             zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 );
791             zx.sig.a0 = 0;
792         }
793         else {
794             while ( expField <= 0 ) {
795                 zx.sig = shortShift128RightJamming( zx.sig, 1 );
796                 ++expField;
797             }
798         }
799         switch ( slow_floatx80_rounding_precision ) {
800          case 32:
801             zx = roundFloatXTo24( isTiny, zx );
802             break;
803          case 64:
804             zx = roundFloatXTo53( isTiny, zx );
805             break;
806          default:
807             zx = roundFloatXTo64( isTiny, zx );
808             break;
809         }
810         expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0;
811     }
812     zx.sig = shortShift128RightJamming( zx.sig, 56 );
813     z.low = zx.sig.a1;
814     z.high = expField;
815     if ( zx.sign ) z.high |= 0x8000;
816     return z;
817
818 }
819
820 #endif
821
822 #ifdef FLOAT128
823
824 static floatX float128ToFloatX( float128 a )
825 {
826     int32 expField;
827     floatX ax;
828
829     ax.isNaN = FALSE;
830     ax.isInf = FALSE;
831     ax.isZero = FALSE;
832     ax.sign = ( ( a.high & LIT64( 0x8000000000000000 ) ) != 0 );
833     expField = ( a.high>>48 ) & 0x7FFF;
834     ax.sig.a1 = a.low;
835     ax.sig.a0 = a.high & LIT64( 0x0000FFFFFFFFFFFF );
836     if ( expField == 0 ) {
837         if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) {
838             ax.isZero = TRUE;
839         }
840         else {
841             expField = 1 - 0x3FFF;
842             do {
843                 ax.sig = shortShift128Left( ax.sig, 1 );
844                 --expField;
845             } while ( ax.sig.a0 < LIT64( 0x0001000000000000 ) );
846             ax.exp = expField;
847         }
848     }
849     else if ( expField == 0x7FFF ) {
850         if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) {
851             ax.isInf = TRUE;
852         }
853         else {
854             ax.isNaN = TRUE;
855         }
856     }
857     else {
858         ax.exp = expField - 0x3FFF;
859         ax.sig.a0 |= LIT64( 0x0001000000000000 );
860     }
861     ax.sig = shortShift128Left( ax.sig, 7 );
862     return ax;
863
864 }
865
866 static float128 floatXToFloat128( floatX zx )
867 {
868     floatX savedZ;
869     flag isTiny;
870     int32 expField;
871     float128 z;
872
873     if ( zx.isZero ) {
874         z.low = 0;
875         z.high = zx.sign ? LIT64( 0x8000000000000000 ) : 0;
876         return z;
877     }
878     if ( zx.isInf ) {
879         z.low = 0;
880         z.high =
881               zx.sign ? LIT64( 0xFFFF000000000000 )
882             : LIT64( 0x7FFF000000000000 );
883         return z;
884     }
885     if ( zx.isNaN ) {
886         z.high = z.low = LIT64( 0xFFFFFFFFFFFFFFFF );
887         return z;
888     }
889     while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) {
890         zx.sig = shortShift128RightJamming( zx.sig, 1 );
891         ++zx.exp;
892     }
893     while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) {
894         zx.sig = shortShift128Left( zx.sig, 1 );
895         --zx.exp;
896     }
897     savedZ = zx;
898     isTiny =
899            ( slow_float_detect_tininess == float_tininess_before_rounding )
900         && ( zx.exp + 0x3FFF <= 0 );
901     zx = roundFloatXTo113( isTiny, zx );
902     expField = zx.exp + 0x3FFF;
903     if ( 0x7FFF <= expField ) {
904         slow_float_exception_flags |=
905             float_flag_overflow | float_flag_inexact;
906         if ( zx.sign ) {
907             switch ( slow_float_rounding_mode ) {
908              case float_round_nearest_even:
909              case float_round_down:
910                 z.low = 0;
911                 z.high = LIT64( 0xFFFF000000000000 );
912                 break;
913              case float_round_to_zero:
914              case float_round_up:
915                 z.low = LIT64( 0xFFFFFFFFFFFFFFFF );
916                 z.high = LIT64( 0xFFFEFFFFFFFFFFFF );
917                 break;
918             }
919         }
920         else {
921             switch ( slow_float_rounding_mode ) {
922              case float_round_nearest_even:
923              case float_round_up:
924                 z.low = 0;
925                 z.high = LIT64( 0x7FFF000000000000 );
926                 break;
927              case float_round_to_zero:
928              case float_round_down:
929                 z.low = LIT64( 0xFFFFFFFFFFFFFFFF );
930                 z.high = LIT64( 0x7FFEFFFFFFFFFFFF );
931                 break;
932             }
933         }
934         return z;
935     }
936     if ( expField <= 0 ) {
937         isTiny = TRUE;
938         zx = savedZ;
939         expField = zx.exp + 0x3FFF;
940         if ( expField < -120 ) {
941             zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 );
942             zx.sig.a0 = 0;
943         }
944         else {
945             while ( expField <= 0 ) {
946                 zx.sig = shortShift128RightJamming( zx.sig, 1 );
947                 ++expField;
948             }
949         }
950         zx = roundFloatXTo113( isTiny, zx );
951         expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0;
952     }
953     zx.sig = shortShift128RightJamming( zx.sig, 7 );
954     z.low = zx.sig.a1;
955     z.high = expField;
956     z.high <<= 48;
957     if ( zx.sign ) z.high |= LIT64( 0x8000000000000000 );
958     z.high |= zx.sig.a0 & LIT64( 0x0000FFFFFFFFFFFF );
959     return z;
960
961 }
962
963 #endif
964
965 static floatX floatXInvalid( void )
966 {
967
968     slow_float_exception_flags |= float_flag_invalid;
969     return floatXNaN;
970
971 }
972
973 static floatX floatXRoundToInt( floatX ax )
974 {
975     int32 shiftCount, i;
976
977     if ( ax.isNaN || ax.isInf ) return ax;
978     shiftCount = 112 - ax.exp;
979     if ( shiftCount <= 0 ) return ax;
980     if ( 119 < shiftCount ) {
981         ax.exp = 112;
982         ax.sig.a1 = ! ax.isZero;
983         ax.sig.a0 = 0;
984     }
985     else {
986         while ( 0 < shiftCount ) {
987             ax.sig = shortShift128RightJamming( ax.sig, 1 );
988             ++ax.exp;
989             --shiftCount;
990         }
991     }
992     ax = roundFloatXTo113( FALSE, ax );
993     if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE;
994     return ax;
995
996 }
997
998 static floatX floatXAdd( floatX ax, floatX bx )
999 {
1000     int32 expDiff;
1001     floatX zx;
1002
1003     if ( ax.isNaN ) return ax;
1004     if ( bx.isNaN ) return bx;
1005     if ( ax.isInf && bx.isInf ) {
1006         if ( ax.sign == bx.sign ) return ax;
1007         return floatXInvalid();
1008     }
1009     if ( ax.isInf ) return ax;
1010     if ( bx.isInf ) return bx;
1011     if ( ax.isZero && bx.isZero ) {
1012         if ( ax.sign == bx.sign ) return ax;
1013         goto completeCancellation;
1014     }
1015     if (    ( ax.sign != bx.sign )
1016          && ( ax.exp == bx.exp )
1017          && eq128( ax.sig, bx.sig )
1018        ) {
1019  completeCancellation:
1020         return
1021               ( slow_float_rounding_mode == float_round_down ) ?
1022                   floatXNegativeZero
1023             : floatXPositiveZero;
1024     }
1025     if ( ax.isZero ) return bx;
1026     if ( bx.isZero ) return ax;
1027     expDiff = ax.exp - bx.exp;
1028     if ( expDiff < 0 ) {
1029         zx = ax;
1030         zx.exp = bx.exp;
1031         if ( expDiff < -120 ) {
1032             zx.sig.a1 = 1;
1033             zx.sig.a0 = 0;
1034         }
1035         else {
1036             while ( expDiff < 0 ) {
1037                 zx.sig = shortShift128RightJamming( zx.sig, 1 );
1038                 ++expDiff;
1039             }
1040         }
1041         if ( ax.sign != bx.sign ) zx.sig = neg128( zx.sig );
1042         zx.sign = bx.sign;
1043         zx.sig = add128( zx.sig, bx.sig );
1044     }
1045     else {
1046         zx = bx;
1047         zx.exp = ax.exp;
1048         if ( 120 < expDiff ) {
1049             zx.sig.a1 = 1;
1050             zx.sig.a0 = 0;
1051         }
1052         else {
1053             while ( 0 < expDiff ) {
1054                 zx.sig = shortShift128RightJamming( zx.sig, 1 );
1055                 --expDiff;
1056             }
1057         }
1058         if ( ax.sign != bx.sign ) zx.sig = neg128( zx.sig );
1059         zx.sign = ax.sign;
1060         zx.sig = add128( zx.sig, ax.sig );
1061     }
1062     if ( zx.sig.a0 & LIT64( 0x8000000000000000 ) ) {
1063         zx.sig = neg128( zx.sig );
1064         zx.sign = ! zx.sign;
1065     }
1066     return zx;
1067
1068 }
1069
1070 static floatX floatXMul( floatX ax, floatX bx )
1071 {
1072     int8 bitNum;
1073     floatX zx;
1074
1075     if ( ax.isNaN ) return ax;
1076     if ( bx.isNaN ) return bx;
1077     if ( ax.isInf ) {
1078         if ( bx.isZero ) return floatXInvalid();
1079         if ( bx.sign ) ax.sign = ! ax.sign;
1080         return ax;
1081     }
1082     if ( bx.isInf ) {
1083         if ( ax.isZero ) return floatXInvalid();
1084         if ( ax.sign ) bx.sign = ! bx.sign;
1085         return bx;
1086     }
1087     zx = ax;
1088     zx.sign ^= bx.sign;
1089     if ( ax.isZero || bx.isZero ) {
1090         return zx.sign ? floatXNegativeZero : floatXPositiveZero;
1091     }
1092     zx.exp += bx.exp + 1;
1093     zx.sig.a1 = 0;
1094     zx.sig.a0 = 0;
1095     for ( bitNum = 0; bitNum < 119; ++bitNum ) {
1096         if ( bx.sig.a1 & 2 ) zx.sig = add128( zx.sig, ax.sig );
1097         bx.sig = shortShift128RightJamming( bx.sig, 1 );
1098         zx.sig = shortShift128RightJamming( zx.sig, 1 );
1099     }
1100     return zx;
1101
1102 }
1103
1104 static floatX floatXDiv( floatX ax, floatX bx )
1105 {
1106     bits128X negBSig;
1107     int8 bitNum;
1108     floatX zx;
1109
1110     if ( ax.isNaN ) return ax;
1111     if ( bx.isNaN ) return bx;
1112     if ( ax.isInf ) {
1113         if ( bx.isInf ) return floatXInvalid();
1114         if ( bx.sign ) ax.sign = ! ax.sign;
1115         return ax;
1116     }
1117     if ( bx.isZero ) {
1118         if ( ax.isZero ) return floatXInvalid();
1119         slow_float_exception_flags |= float_flag_divbyzero;
1120         if ( ax.sign ) bx.sign = ! bx.sign;
1121         bx.isZero = FALSE;
1122         bx.isInf = TRUE;
1123         return bx;
1124     }
1125     zx = ax;
1126     zx.sign ^= bx.sign;
1127     if ( ax.isZero || bx.isInf ) {
1128         return zx.sign ? floatXNegativeZero : floatXPositiveZero;
1129     }
1130     zx.exp -= bx.exp + 1;
1131     zx.sig.a1 = 0;
1132     zx.sig.a0 = 0;
1133     negBSig = neg128( bx.sig );
1134     for ( bitNum = 0; bitNum < 120; ++bitNum ) {
1135         if ( le128( bx.sig, ax.sig ) ) {
1136             zx.sig.a1 |= 1;
1137             ax.sig = add128( ax.sig, negBSig );
1138         }
1139         ax.sig = shortShift128Left( ax.sig, 1 );
1140         zx.sig = shortShift128Left( zx.sig, 1 );
1141     }
1142     if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1;
1143     return zx;
1144
1145 }
1146
1147 static floatX floatXRem( floatX ax, floatX bx )
1148 {
1149     bits128X negBSig;
1150     flag lastQuotientBit;
1151     bits128X savedASig;
1152
1153     if ( ax.isNaN ) return ax;
1154     if ( bx.isNaN ) return bx;
1155     if ( ax.isInf || bx.isZero ) return floatXInvalid();
1156     if ( ax.isZero || bx.isInf ) return ax;
1157     --bx.exp;
1158     if ( ax.exp < bx.exp ) return ax;
1159     bx.sig = shortShift128Left( bx.sig, 1 );
1160     negBSig = neg128( bx.sig );
1161     while ( bx.exp < ax.exp ) {
1162         if ( le128( bx.sig, ax.sig ) ) ax.sig = add128( ax.sig, negBSig );
1163         ax.sig = shortShift128Left( ax.sig, 1 );
1164         --ax.exp;
1165     }
1166     lastQuotientBit = le128( bx.sig, ax.sig );
1167     if ( lastQuotientBit ) ax.sig = add128( ax.sig, negBSig );
1168     savedASig = ax.sig;
1169     ax.sig = neg128( add128( ax.sig, negBSig ) );
1170     if ( lt128( ax.sig, savedASig ) ) {
1171         ax.sign = ! ax.sign;
1172     }
1173     else if ( lt128( savedASig, ax.sig ) ) {
1174         ax.sig = savedASig;
1175     }
1176     else {
1177         if ( lastQuotientBit ) {
1178             ax.sign = ! ax.sign;
1179         }
1180         else {
1181             ax.sig = savedASig;
1182         }
1183     }
1184     if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE;
1185     return ax;
1186
1187 }
1188
1189 static floatX floatXSqrt( floatX ax )
1190 {
1191     int8 bitNum;
1192     bits128X bitSig, savedASig;
1193     floatX zx;
1194
1195     if ( ax.isNaN || ax.isZero ) return ax;
1196     if ( ax.sign ) return floatXInvalid();
1197     if ( ax.isInf ) return ax;
1198     zx = ax;
1199     zx.exp >>= 1;
1200     if ( ( ax.exp & 1 ) == 0 ) ax.sig = shortShift128RightJamming( ax.sig, 1 );
1201     zx.sig.a1 = 0;
1202     zx.sig.a0 = 0;
1203     bitSig.a1 = 0;
1204     bitSig.a0 = LIT64( 0x0080000000000000 );
1205     for ( bitNum = 0; bitNum < 120; ++bitNum ) {
1206         savedASig = ax.sig;
1207         ax.sig = add128( ax.sig, neg128( zx.sig ) );
1208         ax.sig = shortShift128Left( ax.sig, 1 );
1209         ax.sig = add128( ax.sig, neg128( bitSig ) );
1210         if ( ax.sig.a0 & LIT64( 0x8000000000000000 ) ) {
1211             ax.sig = shortShift128Left( savedASig, 1 );
1212         }
1213         else {
1214             zx.sig.a1 |= bitSig.a1;
1215             zx.sig.a0 |= bitSig.a0;
1216         }
1217         bitSig = shortShift128RightJamming( bitSig, 1 );
1218     }
1219     if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1;
1220     return zx;
1221
1222 }
1223
1224 static flag floatXEq( floatX ax, floatX bx )
1225 {
1226
1227     if ( ax.isNaN || bx.isNaN ) return FALSE;
1228     if ( ax.isZero && bx.isZero ) return TRUE;
1229     if ( ax.sign != bx.sign ) return FALSE;
1230     if ( ax.isInf || bx.isInf ) return ax.isInf && bx.isInf;
1231     return ( ax.exp == bx.exp ) && eq128( ax.sig, bx.sig );
1232
1233 }
1234
1235 static flag floatXLe( floatX ax, floatX bx )
1236 {
1237
1238     if ( ax.isNaN || bx.isNaN ) return FALSE;
1239     if ( ax.isZero && bx.isZero ) return TRUE;
1240     if ( ax.sign != bx.sign ) return ax.sign;
1241     if ( ax.sign ) {
1242         if ( ax.isInf || bx.isZero ) return TRUE;
1243         if ( bx.isInf || ax.isZero ) return FALSE;
1244         if ( bx.exp < ax.exp ) return TRUE;
1245         if ( ax.exp < bx.exp ) return FALSE;
1246         return le128( bx.sig, ax.sig );
1247     }
1248     else {
1249         if ( bx.isInf || ax.isZero ) return TRUE;
1250         if ( ax.isInf || bx.isZero ) return FALSE;
1251         if ( ax.exp < bx.exp ) return TRUE;
1252         if ( bx.exp < ax.exp ) return FALSE;
1253         return le128( ax.sig, bx.sig );
1254     }
1255
1256 }
1257
1258 static flag floatXLt( floatX ax, floatX bx )
1259 {
1260
1261     if ( ax.isNaN || bx.isNaN ) return FALSE;
1262     if ( ax.isZero && bx.isZero ) return FALSE;
1263     if ( ax.sign != bx.sign ) return ax.sign;
1264     if ( ax.isInf && bx.isInf ) return FALSE;
1265     if ( ax.sign ) {
1266         if ( ax.isInf || bx.isZero ) return TRUE;
1267         if ( bx.isInf || ax.isZero ) return FALSE;
1268         if ( bx.exp < ax.exp ) return TRUE;
1269         if ( ax.exp < bx.exp ) return FALSE;
1270         return lt128( bx.sig, ax.sig );
1271     }
1272     else {
1273         if ( bx.isInf || ax.isZero ) return TRUE;
1274         if ( ax.isInf || bx.isZero ) return FALSE;
1275         if ( ax.exp < bx.exp ) return TRUE;
1276         if ( bx.exp < ax.exp ) return FALSE;
1277         return lt128( ax.sig, bx.sig );
1278     }
1279
1280 }
1281
1282 float32 slow_int32_to_float32( int32 a )
1283 {
1284
1285     return floatXToFloat32( int32ToFloatX( a ) );
1286
1287 }
1288
1289 float64 slow_int32_to_float64( int32 a )
1290 {
1291
1292     return floatXToFloat64( int32ToFloatX( a ) );
1293
1294 }
1295
1296 #ifdef FLOATX80
1297
1298 floatx80 slow_int32_to_floatx80( int32 a )
1299 {
1300
1301     return floatXToFloatx80( int32ToFloatX( a ) );
1302
1303 }
1304
1305 #endif
1306
1307 #ifdef FLOAT128
1308
1309 float128 slow_int32_to_float128( int32 a )
1310 {
1311
1312     return floatXToFloat128( int32ToFloatX( a ) );
1313
1314 }
1315
1316 #endif
1317
1318 float32 slow_int64_to_float32( int64 a )
1319 {
1320
1321     return floatXToFloat32( int64ToFloatX( a ) );
1322
1323 }
1324
1325 float64 slow_int64_to_float64( int64 a )
1326 {
1327
1328     return floatXToFloat64( int64ToFloatX( a ) );
1329
1330 }
1331
1332 #ifdef FLOATX80
1333
1334 floatx80 slow_int64_to_floatx80( int64 a )
1335 {
1336
1337     return floatXToFloatx80( int64ToFloatX( a ) );
1338
1339 }
1340
1341 #endif
1342
1343 #ifdef FLOAT128
1344
1345 float128 slow_int64_to_float128( int64 a )
1346 {
1347
1348     return floatXToFloat128( int64ToFloatX( a ) );
1349
1350 }
1351
1352 #endif
1353
1354 int32 slow_float32_to_int32( float32 a )
1355 {
1356
1357     return floatXToInt32( float32ToFloatX( a ) );
1358
1359 }
1360
1361 int32 slow_float32_to_int32_round_to_zero( float32 a )
1362 {
1363     int8 savedRoundingMode;
1364     int32 z;
1365
1366     savedRoundingMode = slow_float_rounding_mode;
1367     slow_float_rounding_mode = float_round_to_zero;
1368     z = floatXToInt32( float32ToFloatX( a ) );
1369     slow_float_rounding_mode = savedRoundingMode;
1370     return z;
1371
1372 }
1373
1374 int64 slow_float32_to_int64( float32 a )
1375 {
1376
1377     return floatXToInt64( float32ToFloatX( a ) );
1378
1379 }
1380
1381 int64 slow_float32_to_int64_round_to_zero( float32 a )
1382 {
1383     int8 savedRoundingMode;
1384     int64 z;
1385
1386     savedRoundingMode = slow_float_rounding_mode;
1387     slow_float_rounding_mode = float_round_to_zero;
1388     z = floatXToInt64( float32ToFloatX( a ) );
1389     slow_float_rounding_mode = savedRoundingMode;
1390     return z;
1391
1392 }
1393
1394 float64 slow_float32_to_float64( float32 a )
1395 {
1396
1397     return floatXToFloat64( float32ToFloatX( a ) );
1398
1399 }
1400
1401 #ifdef FLOATX80
1402
1403 floatx80 slow_float32_to_floatx80( float32 a )
1404 {
1405
1406     return floatXToFloatx80( float32ToFloatX( a ) );
1407
1408 }
1409
1410 #endif
1411
1412 #ifdef FLOAT128
1413
1414 float128 slow_float32_to_float128( float32 a )
1415 {
1416
1417     return floatXToFloat128( float32ToFloatX( a ) );
1418
1419 }
1420
1421 #endif
1422
1423 float32 slow_float32_round_to_int( float32 a )
1424 {
1425
1426     return floatXToFloat32( floatXRoundToInt( float32ToFloatX( a ) ) );
1427
1428 }
1429
1430 float32 slow_float32_add( float32 a, float32 b )
1431 {
1432
1433     return
1434         floatXToFloat32(
1435             floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) );
1436
1437 }
1438
1439 float32 slow_float32_sub( float32 a, float32 b )
1440 {
1441
1442     b ^= 0x80000000;
1443     return
1444         floatXToFloat32(
1445             floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) );
1446
1447 }
1448
1449 float32 slow_float32_mul( float32 a, float32 b )
1450 {
1451
1452     return
1453         floatXToFloat32(
1454             floatXMul( float32ToFloatX( a ), float32ToFloatX( b ) ) );
1455
1456 }
1457
1458 float32 slow_float32_div( float32 a, float32 b )
1459 {
1460
1461     return
1462         floatXToFloat32(
1463             floatXDiv( float32ToFloatX( a ), float32ToFloatX( b ) ) );
1464
1465 }
1466
1467 float32 slow_float32_rem( float32 a, float32 b )
1468 {
1469
1470     return
1471         floatXToFloat32(
1472             floatXRem( float32ToFloatX( a ), float32ToFloatX( b ) ) );
1473
1474 }
1475
1476 float32 slow_float32_sqrt( float32 a )
1477 {
1478
1479     return floatXToFloat32( floatXSqrt( float32ToFloatX( a ) ) );
1480
1481 }
1482
1483 flag slow_float32_eq( float32 a, float32 b )
1484 {
1485
1486     return floatXEq( float32ToFloatX( a ), float32ToFloatX( b ) );
1487
1488 }
1489
1490 flag slow_float32_le( float32 a, float32 b )
1491 {
1492     floatX ax, bx;
1493
1494     ax = float32ToFloatX( a );
1495     bx = float32ToFloatX( b );
1496     if ( ax.isNaN || bx.isNaN ) {
1497         slow_float_exception_flags |= float_flag_invalid;
1498     }
1499     return floatXLe( ax, bx );
1500
1501 }
1502
1503 flag slow_float32_lt( float32 a, float32 b )
1504 {
1505     floatX ax, bx;
1506
1507     ax = float32ToFloatX( a );
1508     bx = float32ToFloatX( b );
1509     if ( ax.isNaN || bx.isNaN ) {
1510         slow_float_exception_flags |= float_flag_invalid;
1511     }
1512     return floatXLt( ax, bx );
1513
1514 }
1515
1516 flag slow_float32_eq_signaling( float32 a, float32 b )
1517 {
1518     floatX ax, bx;
1519
1520     ax = float32ToFloatX( a );
1521     bx = float32ToFloatX( b );
1522     if ( ax.isNaN || bx.isNaN ) {
1523         slow_float_exception_flags |= float_flag_invalid;
1524     }
1525     return floatXEq( ax, bx );
1526
1527 }
1528
1529 flag slow_float32_le_quiet( float32 a, float32 b )
1530 {
1531
1532     return floatXLe( float32ToFloatX( a ), float32ToFloatX( b ) );
1533
1534 }
1535
1536 flag slow_float32_lt_quiet( float32 a, float32 b )
1537 {
1538
1539     return floatXLt( float32ToFloatX( a ), float32ToFloatX( b ) );
1540
1541 }
1542
1543 int32 slow_float64_to_int32( float64 a )
1544 {
1545
1546     return floatXToInt32( float64ToFloatX( a ) );
1547
1548 }
1549
1550 int32 slow_float64_to_int32_round_to_zero( float64 a )
1551 {
1552     int8 savedRoundingMode;
1553     int32 z;
1554
1555     savedRoundingMode = slow_float_rounding_mode;
1556     slow_float_rounding_mode = float_round_to_zero;
1557     z = floatXToInt32( float64ToFloatX( a ) );
1558     slow_float_rounding_mode = savedRoundingMode;
1559     return z;
1560
1561 }
1562
1563 int64 slow_float64_to_int64( float64 a )
1564 {
1565
1566     return floatXToInt64( float64ToFloatX( a ) );
1567
1568 }
1569
1570 int64 slow_float64_to_int64_round_to_zero( float64 a )
1571 {
1572     int8 savedRoundingMode;
1573     int64 z;
1574
1575     savedRoundingMode = slow_float_rounding_mode;
1576     slow_float_rounding_mode = float_round_to_zero;
1577     z = floatXToInt64( float64ToFloatX( a ) );
1578     slow_float_rounding_mode = savedRoundingMode;
1579     return z;
1580
1581 }
1582
1583 float32 slow_float64_to_float32( float64 a )
1584 {
1585
1586     return floatXToFloat32( float64ToFloatX( a ) );
1587
1588 }
1589
1590 #ifdef FLOATX80
1591
1592 floatx80 slow_float64_to_floatx80( float64 a )
1593 {
1594
1595     return floatXToFloatx80( float64ToFloatX( a ) );
1596
1597 }
1598
1599 #endif
1600
1601 #ifdef FLOAT128
1602
1603 float128 slow_float64_to_float128( float64 a )
1604 {
1605
1606     return floatXToFloat128( float64ToFloatX( a ) );
1607
1608 }
1609
1610 #endif
1611
1612 float64 slow_float64_round_to_int( float64 a )
1613 {
1614
1615     return floatXToFloat64( floatXRoundToInt( float64ToFloatX( a ) ) );
1616
1617 }
1618
1619 float64 slow_float64_add( float64 a, float64 b )
1620 {
1621
1622     return
1623         floatXToFloat64(
1624             floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1625
1626 }
1627
1628 float64 slow_float64_sub( float64 a, float64 b )
1629 {
1630
1631     b ^= LIT64( 0x8000000000000000 );
1632     return
1633         floatXToFloat64(
1634             floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1635
1636 }
1637
1638 float64 slow_float64_mul( float64 a, float64 b )
1639 {
1640
1641     return
1642         floatXToFloat64(
1643             floatXMul( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1644
1645 }
1646
1647 float64 slow_float64_div( float64 a, float64 b )
1648 {
1649
1650     return
1651         floatXToFloat64(
1652             floatXDiv( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1653
1654 }
1655
1656 float64 slow_float64_rem( float64 a, float64 b )
1657 {
1658
1659     return
1660         floatXToFloat64(
1661             floatXRem( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1662
1663 }
1664
1665 float64 slow_float64_sqrt( float64 a )
1666 {
1667
1668     return floatXToFloat64( floatXSqrt( float64ToFloatX( a ) ) );
1669
1670 }
1671
1672 flag slow_float64_eq( float64 a, float64 b )
1673 {
1674
1675     return floatXEq( float64ToFloatX( a ), float64ToFloatX( b ) );
1676
1677 }
1678
1679 flag slow_float64_le( float64 a, float64 b )
1680 {
1681     floatX ax, bx;
1682
1683     ax = float64ToFloatX( a );
1684     bx = float64ToFloatX( b );
1685     if ( ax.isNaN || bx.isNaN ) {
1686         slow_float_exception_flags |= float_flag_invalid;
1687     }
1688     return floatXLe( ax, bx );
1689
1690 }
1691
1692 flag slow_float64_lt( float64 a, float64 b )
1693 {
1694     floatX ax, bx;
1695
1696     ax = float64ToFloatX( a );
1697     bx = float64ToFloatX( b );
1698     if ( ax.isNaN || bx.isNaN ) {
1699         slow_float_exception_flags |= float_flag_invalid;
1700     }
1701     return floatXLt( ax, bx );
1702
1703 }
1704
1705 flag slow_float64_eq_signaling( float64 a, float64 b )
1706 {
1707     floatX ax, bx;
1708
1709     ax = float64ToFloatX( a );
1710     bx = float64ToFloatX( b );
1711     if ( ax.isNaN || bx.isNaN ) {
1712         slow_float_exception_flags |= float_flag_invalid;
1713     }
1714     return floatXEq( ax, bx );
1715
1716 }
1717
1718 flag slow_float64_le_quiet( float64 a, float64 b )
1719 {
1720
1721     return floatXLe( float64ToFloatX( a ), float64ToFloatX( b ) );
1722
1723 }
1724
1725 flag slow_float64_lt_quiet( float64 a, float64 b )
1726 {
1727
1728     return floatXLt( float64ToFloatX( a ), float64ToFloatX( b ) );
1729
1730 }
1731
1732 #ifdef FLOATX80
1733
1734 int32 slow_floatx80_to_int32( floatx80 a )
1735 {
1736
1737     return floatXToInt32( floatx80ToFloatX( a ) );
1738
1739 }
1740
1741 int32 slow_floatx80_to_int32_round_to_zero( floatx80 a )
1742 {
1743     int8 savedRoundingMode;
1744     int32 z;
1745
1746     savedRoundingMode = slow_float_rounding_mode;
1747     slow_float_rounding_mode = float_round_to_zero;
1748     z = floatXToInt32( floatx80ToFloatX( a ) );
1749     slow_float_rounding_mode = savedRoundingMode;
1750     return z;
1751
1752 }
1753
1754 int64 slow_floatx80_to_int64( floatx80 a )
1755 {
1756
1757     return floatXToInt64( floatx80ToFloatX( a ) );
1758
1759 }
1760
1761 int64 slow_floatx80_to_int64_round_to_zero( floatx80 a )
1762 {
1763     int8 savedRoundingMode;
1764     int64 z;
1765
1766     savedRoundingMode = slow_float_rounding_mode;
1767     slow_float_rounding_mode = float_round_to_zero;
1768     z = floatXToInt64( floatx80ToFloatX( a ) );
1769     slow_float_rounding_mode = savedRoundingMode;
1770     return z;
1771
1772 }
1773
1774 float32 slow_floatx80_to_float32( floatx80 a )
1775 {
1776
1777     return floatXToFloat32( floatx80ToFloatX( a ) );
1778
1779 }
1780
1781 float64 slow_floatx80_to_float64( floatx80 a )
1782 {
1783
1784     return floatXToFloat64( floatx80ToFloatX( a ) );
1785
1786 }
1787
1788 #ifdef FLOAT128
1789
1790 float128 slow_floatx80_to_float128( floatx80 a )
1791 {
1792
1793     return floatXToFloat128( floatx80ToFloatX( a ) );
1794
1795 }
1796
1797 #endif
1798
1799 floatx80 slow_floatx80_round_to_int( floatx80 a )
1800 {
1801
1802     return floatXToFloatx80( floatXRoundToInt( floatx80ToFloatX( a ) ) );
1803
1804 }
1805
1806 floatx80 slow_floatx80_add( floatx80 a, floatx80 b )
1807 {
1808
1809     return
1810         floatXToFloatx80(
1811             floatXAdd( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) );
1812
1813 }
1814
1815 floatx80 slow_floatx80_sub( floatx80 a, floatx80 b )
1816 {
1817
1818     b.high ^= 0x8000;
1819     return
1820         floatXToFloatx80(
1821             floatXAdd( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) );
1822
1823 }
1824
1825 floatx80 slow_floatx80_mul( floatx80 a, floatx80 b )
1826 {
1827
1828     return
1829         floatXToFloatx80(
1830             floatXMul( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) );
1831
1832 }
1833
1834 floatx80 slow_floatx80_div( floatx80 a, floatx80 b )
1835 {
1836
1837     return
1838         floatXToFloatx80(
1839             floatXDiv( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) );
1840
1841 }
1842
1843 floatx80 slow_floatx80_rem( floatx80 a, floatx80 b )
1844 {
1845
1846     return
1847         floatXToFloatx80(
1848             floatXRem( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) );
1849
1850 }
1851
1852 floatx80 slow_floatx80_sqrt( floatx80 a )
1853 {
1854
1855     return floatXToFloatx80( floatXSqrt( floatx80ToFloatX( a ) ) );
1856
1857 }
1858
1859 flag slow_floatx80_eq( floatx80 a, floatx80 b )
1860 {
1861
1862     return floatXEq( floatx80ToFloatX( a ), floatx80ToFloatX( b ) );
1863
1864 }
1865
1866 flag slow_floatx80_le( floatx80 a, floatx80 b )
1867 {
1868     floatX ax, bx;
1869
1870     ax = floatx80ToFloatX( a );
1871     bx = floatx80ToFloatX( b );
1872     if ( ax.isNaN || bx.isNaN ) {
1873         slow_float_exception_flags |= float_flag_invalid;
1874     }
1875     return floatXLe( ax, bx );
1876
1877 }
1878
1879 flag slow_floatx80_lt( floatx80 a, floatx80 b )
1880 {
1881     floatX ax, bx;
1882
1883     ax = floatx80ToFloatX( a );
1884     bx = floatx80ToFloatX( b );
1885     if ( ax.isNaN || bx.isNaN ) {
1886         slow_float_exception_flags |= float_flag_invalid;
1887     }
1888     return floatXLt( ax, bx );
1889
1890 }
1891
1892 flag slow_floatx80_eq_signaling( floatx80 a, floatx80 b )
1893 {
1894     floatX ax, bx;
1895
1896     ax = floatx80ToFloatX( a );
1897     bx = floatx80ToFloatX( b );
1898     if ( ax.isNaN || bx.isNaN ) {
1899         slow_float_exception_flags |= float_flag_invalid;
1900     }
1901     return floatXEq( ax, bx );
1902
1903 }
1904
1905 flag slow_floatx80_le_quiet( floatx80 a, floatx80 b )
1906 {
1907
1908     return floatXLe( floatx80ToFloatX( a ), floatx80ToFloatX( b ) );
1909
1910 }
1911
1912 flag slow_floatx80_lt_quiet( floatx80 a, floatx80 b )
1913 {
1914
1915     return floatXLt( floatx80ToFloatX( a ), floatx80ToFloatX( b ) );
1916
1917 }
1918
1919 #endif
1920
1921 #ifdef FLOAT128
1922
1923 int32 slow_float128_to_int32( float128 a )
1924 {
1925
1926     return floatXToInt32( float128ToFloatX( a ) );
1927
1928 }
1929
1930 int32 slow_float128_to_int32_round_to_zero( float128 a )
1931 {
1932     int8 savedRoundingMode;
1933     int32 z;
1934
1935     savedRoundingMode = slow_float_rounding_mode;
1936     slow_float_rounding_mode = float_round_to_zero;
1937     z = floatXToInt32( float128ToFloatX( a ) );
1938     slow_float_rounding_mode = savedRoundingMode;
1939     return z;
1940
1941 }
1942
1943 int64 slow_float128_to_int64( float128 a )
1944 {
1945
1946     return floatXToInt64( float128ToFloatX( a ) );
1947
1948 }
1949
1950 int64 slow_float128_to_int64_round_to_zero( float128 a )
1951 {
1952     int8 savedRoundingMode;
1953     int64 z;
1954
1955     savedRoundingMode = slow_float_rounding_mode;
1956     slow_float_rounding_mode = float_round_to_zero;
1957     z = floatXToInt64( float128ToFloatX( a ) );
1958     slow_float_rounding_mode = savedRoundingMode;
1959     return z;
1960
1961 }
1962
1963 float32 slow_float128_to_float32( float128 a )
1964 {
1965
1966     return floatXToFloat32( float128ToFloatX( a ) );
1967
1968 }
1969
1970 float64 slow_float128_to_float64( float128 a )
1971 {
1972
1973     return floatXToFloat64( float128ToFloatX( a ) );
1974
1975 }
1976
1977 #ifdef FLOATX80
1978
1979 floatx80 slow_float128_to_floatx80( float128 a )
1980 {
1981
1982     return floatXToFloatx80( float128ToFloatX( a ) );
1983
1984 }
1985
1986 #endif
1987
1988 float128 slow_float128_round_to_int( float128 a )
1989 {
1990
1991     return floatXToFloat128( floatXRoundToInt( float128ToFloatX( a ) ) );
1992
1993 }
1994
1995 float128 slow_float128_add( float128 a, float128 b )
1996 {
1997
1998     return
1999         floatXToFloat128(
2000             floatXAdd( float128ToFloatX( a ), float128ToFloatX( b ) ) );
2001
2002 }
2003
2004 float128 slow_float128_sub( float128 a, float128 b )
2005 {
2006
2007     b.high ^= LIT64( 0x8000000000000000 );
2008     return
2009         floatXToFloat128(
2010             floatXAdd( float128ToFloatX( a ), float128ToFloatX( b ) ) );
2011
2012 }
2013
2014 float128 slow_float128_mul( float128 a, float128 b )
2015 {
2016
2017     return
2018         floatXToFloat128(
2019             floatXMul( float128ToFloatX( a ), float128ToFloatX( b ) ) );
2020
2021 }
2022
2023 float128 slow_float128_div( float128 a, float128 b )
2024 {
2025
2026     return
2027         floatXToFloat128(
2028             floatXDiv( float128ToFloatX( a ), float128ToFloatX( b ) ) );
2029
2030 }
2031
2032 float128 slow_float128_rem( float128 a, float128 b )
2033 {
2034
2035     return
2036         floatXToFloat128(
2037             floatXRem( float128ToFloatX( a ), float128ToFloatX( b ) ) );
2038
2039 }
2040
2041 float128 slow_float128_sqrt( float128 a )
2042 {
2043
2044     return floatXToFloat128( floatXSqrt( float128ToFloatX( a ) ) );
2045
2046 }
2047
2048 flag slow_float128_eq( float128 a, float128 b )
2049 {
2050
2051     return floatXEq( float128ToFloatX( a ), float128ToFloatX( b ) );
2052
2053 }
2054
2055 flag slow_float128_le( float128 a, float128 b )
2056 {
2057     floatX ax, bx;
2058
2059     ax = float128ToFloatX( a );
2060     bx = float128ToFloatX( b );
2061     if ( ax.isNaN || bx.isNaN ) {
2062         slow_float_exception_flags |= float_flag_invalid;
2063     }
2064     return floatXLe( ax, bx );
2065
2066 }
2067
2068 flag slow_float128_lt( float128 a, float128 b )
2069 {
2070     floatX ax, bx;
2071
2072     ax = float128ToFloatX( a );
2073     bx = float128ToFloatX( b );
2074     if ( ax.isNaN || bx.isNaN ) {
2075         slow_float_exception_flags |= float_flag_invalid;
2076     }
2077     return floatXLt( ax, bx );
2078
2079 }
2080
2081 flag slow_float128_eq_signaling( float128 a, float128 b )
2082 {
2083     floatX ax, bx;
2084
2085     ax = float128ToFloatX( a );
2086     bx = float128ToFloatX( b );
2087     if ( ax.isNaN || bx.isNaN ) {
2088         slow_float_exception_flags |= float_flag_invalid;
2089     }
2090     return floatXEq( ax, bx );
2091
2092 }
2093
2094 flag slow_float128_le_quiet( float128 a, float128 b )
2095 {
2096
2097     return floatXLe( float128ToFloatX( a ), float128ToFloatX( b ) );
2098
2099 }
2100
2101 flag slow_float128_lt_quiet( float128 a, float128 b )
2102 {
2103
2104     return floatXLt( float128ToFloatX( a ), float128ToFloatX( b ) );
2105
2106 }
2107
2108 #endif
2109