Passify GCC. Convert 0x0LL to something more portable in the FP code.
[external/binutils.git] / sim / common / sim-fpu.c
1 /* This is a software floating point library which can be used instead of
2    the floating point routines in libgcc1.c for targets without hardware
3    floating point.  */
4
5 /* Copyright (C) 1994,1997 Free Software Foundation, Inc.
6
7 This file is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file with other programs, and to distribute
15 those programs without any restriction coming from the use of this
16 file.  (The General Public License restrictions do apply in other
17 respects; for example, they cover modification of the file, and
18 distribution when not linked into another program.)
19
20 This file is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; see the file COPYING.  If not, write to
27 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
28
29 /* As a special exception, if you link this library with other files,
30    some of which are compiled with GCC, to produce an executable,
31    this library does not by itself cause the resulting executable
32    to be covered by the GNU General Public License.
33    This exception does not however invalidate any other reasons why
34    the executable file might be covered by the GNU General Public License.  */
35
36 /* This implements IEEE 754 format arithmetic, but does not provide a
37    mechanism for setting the rounding mode, or for generating or handling
38    exceptions.
39
40    The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
41    Wilson, all of Cygnus Support.  */
42
43
44 #ifndef SIM_FPU_C
45 #define SIM_FPU_C
46
47 #include "sim-main.h"
48 #include "sim-fpu.h"
49 #include "sim-assert.h"
50
51 #include <math.h>
52
53
54 /* Floating point number is <SIGN:1><EXP:EXPBITS><FRAC:FRACBITS> */
55
56 #define SP_NGARDS    7L
57 #define SP_GARDROUND 0x3f
58 #define SP_GARDMASK  ((unsigned) 0x7f)
59 #define SP_GARDMSB   ((unsigned) 0x40)
60 #define SP_EXPBITS 8
61 #define SP_EXPBIAS 127
62 #define SP_FRACBITS 23
63 #define SP_EXPMAX ((unsigned) 0xff)
64 #define SP_QUIET_NAN 0x100000L
65 #define SP_FRAC_NBITS 32
66 #define SP_FRACHIGH  0x80000000L
67 #define SP_FRACHIGH2 0xc0000000L
68
69 #define DP_NGARDS 8L
70 #define DP_GARDROUND 0x7f
71 #define DP_GARDMASK  ((unsigned) 0xff)
72 #define DP_GARDMSB   ((unsigned) 0x80)
73 #define DP_EXPBITS 11
74 #define DP_EXPBIAS 1023
75 #define DP_FRACBITS 52
76 #define DP_EXPMAX ((unsigned) 0x7ff)
77 #define DP_QUIET_NAN MSBIT64 (12) /* 0x0008000000000000LL */
78 #define DP_FRAC_NBITS 64
79 #define DP_FRACHIGH  MSMASK64 (1) /* 0x8000000000000000LL */
80 #define DP_FRACHIGH2 MSMASK64 (2) /* 0xc000000000000000LL */
81
82 #define EXPMAX (is_double ? DP_EXPMAX : SP_EXPMAX)
83 #define EXPBITS (is_double ? DP_EXPBITS : SP_EXPBITS)
84 #define EXPBIAS (is_double ? DP_EXPBIAS : SP_EXPBIAS)
85 #define FRACBITS (is_double ? DP_FRACBITS : SP_FRACBITS)
86 #define NGARDS (is_double ? DP_NGARDS : (SP_NGARDS ))
87 #define SIGNBIT ((unsigned64)1 << (EXPBITS + FRACBITS))
88 #define FRAC_NBITS (is_double ? DP_FRAC_NBITS : SP_FRAC_NBITS)
89 #define GARDMASK (is_double ? DP_GARDMASK : SP_GARDMASK)
90 #define GARDMSB (is_double ? DP_GARDMSB : SP_GARDMSB)
91 #define GARDROUND (is_double ? DP_GARDROUND : SP_GARDROUND)
92
93 /* F_D_BITOFF is the number of bits offset between the MSB of the mantissa
94    of a float and of a double. Assumes there are only two float types.
95    (double::FRAC_BITS+double::NGARGS-(float::FRAC_BITS-float::NGARDS))
96  */
97 #define F_D_BITOFF (is_double ? 0 : (52+8-(23+7)))
98
99
100 #if 0
101 #define  (is_double ? DP_ : SP_)
102 #endif
103
104 #define NORMAL_EXPMIN (-(EXPBIAS)+1)
105
106 #define IMPLICIT_1 ((unsigned64)1 << (FRACBITS+NGARDS))
107 #define IMPLICIT_2 ((unsigned64)1 << (FRACBITS+1+NGARDS))
108
109 #define MAX_SI_INT   (is_double ? LSMASK64 (63) : LSMASK64 (31))
110 #define MAX_USI_INT  (is_double ? LSMASK64 (64) : LSMASK64 (32))
111
112
113 typedef enum 
114 {
115   sim_fpu_class_snan,
116   sim_fpu_class_qnan,
117   sim_fpu_class_zero,
118   sim_fpu_class_number,
119   sim_fpu_class_infinity,
120 } sim_fpu_class;
121
122 typedef struct _sim_ufpu {
123   sim_fpu_class class;
124   int normal_exp;
125   int sign;
126   unsigned64 fraction;
127   union {
128     double d;
129     unsigned64 i;
130   } val;
131 } sim_ufpu;
132
133
134 STATIC_INLINE_SIM_FPU (unsigned64)
135 pack_fpu (const sim_ufpu *src, int is_double)
136 {
137   unsigned64 fraction;
138   unsigned64 exp;
139   int sign;
140
141   switch (src->class)
142     {
143     default:
144       /* create a NaN */
145     case sim_fpu_class_qnan:
146     case sim_fpu_class_snan:
147       sign = 1; /* fixme - always a qNaN */
148       exp = EXPMAX;
149       fraction = src->fraction;
150       break;
151     case sim_fpu_class_infinity:
152       sign = src->sign;
153       exp = EXPMAX;
154       fraction = 0;
155       break;
156     case sim_fpu_class_zero:
157       sign = src->sign;
158       exp = 0;
159       fraction = 0;
160       break;
161     case sim_fpu_class_number:
162       if (src->normal_exp < NORMAL_EXPMIN)
163         {
164           /* This number's exponent is too low to fit into the bits
165              available in the number, so we'll store 0 in the exponent and
166              shift the fraction to the right to make up for it.  */
167
168           int shift = NORMAL_EXPMIN - src->normal_exp;
169
170           sign = src->sign;
171           exp = 0;
172
173           if (shift > (FRAC_NBITS - NGARDS))
174             {
175               /* No point shifting, since it's more that 64 out.  */
176               fraction = 0;
177             }
178           else
179             {
180               /* Shift by the value */
181               fraction = src->fraction >> F_D_BITOFF;
182               fraction >>= shift;
183               fraction >>= NGARDS;
184             }
185         }
186       else if (src->normal_exp > EXPBIAS)
187         {
188           /* Infinity */
189           sign = src->sign;
190           exp = EXPMAX;
191           fraction = 0; 
192         }
193       else
194         {
195           sign = src->sign;
196           exp = (src->normal_exp + EXPBIAS);
197           fraction = src->fraction >> F_D_BITOFF;
198           /* IF the gard bits are the all zero, but the first, then we're
199              half way between two numbers, choose the one which makes the
200              lsb of the answer 0.  */
201           if ((fraction & GARDMASK) == GARDMSB)
202             {
203               if (fraction & (1 << NGARDS))
204                 fraction += GARDROUND + 1;
205             }
206           else
207             {
208               /* Add a one to the guards to round up */
209               fraction += GARDROUND;
210             }
211           if (fraction >= IMPLICIT_2)
212             {
213               fraction >>= 1;
214               exp += 1;
215             }
216           fraction >>= NGARDS;
217         }
218     }
219
220   return ((sign ? SIGNBIT : 0)
221           | (exp << FRACBITS)
222           | LSMASKED64 (fraction, FRACBITS));
223 }
224
225
226 STATIC_INLINE_SIM_FPU (void)
227 unpack_fpu (sim_ufpu *dst, unsigned64 s, int is_double)
228 {
229   unsigned64 fraction = LSMASKED64 (s, FRACBITS);
230   unsigned exp = LSMASKED64 (s >> FRACBITS, EXPBITS);
231
232   dst->sign = (s & SIGNBIT) != 0;
233
234   if (exp == 0)
235     {
236       /* Hmm.  Looks like 0 */
237       if (fraction == 0)
238         {
239           /* tastes like zero */
240           dst->class = sim_fpu_class_zero;
241         }
242       else
243         {
244           /* Zero exponent with non zero fraction - it's denormalized,
245              so there isn't a leading implicit one - we'll shift it so
246              it gets one.  */
247           dst->normal_exp = exp - EXPBIAS + 1;
248           fraction <<= NGARDS;
249
250           dst->class = sim_fpu_class_number;
251           while (fraction < IMPLICIT_1)
252             {
253               fraction <<= 1;
254               dst->normal_exp--;
255             }
256           dst->fraction = fraction << F_D_BITOFF;
257         }
258     }
259   else if (exp == EXPMAX)
260     {
261       /* Huge exponent*/
262       if (fraction == 0)
263         {
264           /* Attached to a zero fraction - means infinity */
265           dst->class = sim_fpu_class_infinity;
266         }
267       else
268         {
269           /* Non zero fraction, means nan */
270           if (dst->sign)
271             {
272               dst->class = sim_fpu_class_snan;
273             }
274           else
275             {
276               dst->class = sim_fpu_class_qnan;
277             }
278           /* Keep the fraction part as the nan number */
279           dst->fraction = fraction << F_D_BITOFF;
280         }
281     }
282   else
283     {
284       /* Nothing strange about this number */
285       dst->normal_exp = exp - EXPBIAS;
286       dst->class = sim_fpu_class_number;
287       dst->fraction = ((fraction << NGARDS) | IMPLICIT_1) << F_D_BITOFF;
288     }
289
290   /* sanity checks */
291   dst->val.i = -1;
292   dst->val.i = pack_fpu (dst, 1);
293   {
294     if (is_double)
295       {
296         ASSERT (dst->val.i == s);
297       }
298     else
299       {
300         unsigned32 val = pack_fpu (dst, 0);
301         unsigned32 org = s;
302         ASSERT (val == org);
303       }
304   }
305 }
306
307 STATIC_INLINE_SIM_FPU (sim_fpu)
308 ufpu2fpu (const sim_ufpu *d)
309 {
310   sim_fpu ans;
311   ans.val.i = pack_fpu (d, 1);
312   return ans;
313 }
314
315
316 STATIC_INLINE_SIM_FPU (sim_ufpu)
317 fpu2ufpu (const sim_fpu *d)
318 {
319   sim_ufpu ans;
320   unpack_fpu (&ans, d->val.i, 1);
321   return ans;
322 }
323
324 #if 0
325 STATIC_INLINE_SIM_FPU (int)
326 is_ufpu_number (const sim_ufpu *d)
327 {
328   switch (d->class)
329     {
330     case sim_fpu_class_zero:
331     case sim_fpu_class_number:
332       return 1;
333     default:
334       return 0;
335     }
336 }
337 #endif
338
339
340 STATIC_INLINE_SIM_FPU (int)
341 is_ufpu_nan (const sim_ufpu *d)
342 {
343   switch (d->class)
344     {
345     case sim_fpu_class_qnan:
346     case sim_fpu_class_snan:
347       return 1;
348     default:
349       return 0;
350     }
351 }
352
353
354 STATIC_INLINE_SIM_FPU (int)
355 is_ufpu_zero (const sim_ufpu *d)
356 {
357   switch (d->class)
358     {
359     case sim_fpu_class_zero:
360       return 1;
361     default:
362       return 0;
363     }
364 }
365
366
367 STATIC_INLINE_SIM_FPU (int)
368 is_ufpu_inf (const sim_ufpu *d)
369 {
370   switch (d->class)
371     {
372     case sim_fpu_class_infinity:
373       return 1;
374     default:
375       return 0;
376     }
377 }
378
379
380 STATIC_INLINE_SIM_FPU (sim_fpu)
381 fpu_nan (void)
382 {
383   sim_ufpu tmp;
384   tmp.class = sim_fpu_class_snan;
385   tmp.fraction = 0;
386   tmp.sign = 1;
387   tmp.normal_exp = 0;
388   return ufpu2fpu (&tmp);
389 }
390
391
392 STATIC_INLINE_SIM_FPU (signed64)
393 fpu2i (sim_fpu s, int is_double)
394 {
395   sim_ufpu a = fpu2ufpu (&s);
396   unsigned64 tmp;
397   if (is_ufpu_zero (&a))
398     return 0;
399   if (is_ufpu_nan (&a))
400     return 0;
401   /* get reasonable MAX_SI_INT... */
402   if (is_ufpu_inf (&a))
403     return a.sign ? MAX_SI_INT : (-MAX_SI_INT)-1;
404   /* it is a number, but a small one */
405   if (a.normal_exp < 0)
406     return 0;
407   if (a.normal_exp > (FRAC_NBITS - 2))
408     return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
409   if (a.normal_exp > (FRACBITS + NGARDS + F_D_BITOFF))
410     tmp = (a.fraction << (a.normal_exp - (FRACBITS + NGARDS)));
411   else
412     tmp = (a.fraction >> ((FRACBITS + NGARDS + F_D_BITOFF) - a.normal_exp));
413   return a.sign ? (-tmp) : (tmp);
414 }
415
416 STATIC_INLINE_SIM_FPU (unsigned64)
417 fpu2u (sim_fpu s, int is_double)
418 {
419   sim_ufpu a = fpu2ufpu (&s);
420   unsigned64 tmp;
421   if (is_ufpu_zero (&a))
422     return 0;
423   if (is_ufpu_nan (&a))
424     return 0;
425   /* get reasonable MAX_USI_INT... */
426   if (is_ufpu_inf (&a))
427     return a.sign ? MAX_USI_INT : 0;
428   /* it is a negative number */
429   if (a.sign)
430     return 0;
431   /* it is a number, but a small one */
432   if (a.normal_exp < 0)
433     return 0;
434   if (a.normal_exp > (FRAC_NBITS - 1))
435     return MAX_USI_INT;
436   if (a.normal_exp > (FRACBITS + NGARDS + F_D_BITOFF))
437     tmp = (a.fraction << (a.normal_exp - (FRACBITS + NGARDS + F_D_BITOFF)));
438   else
439     tmp = (a.fraction >> ((FRACBITS + NGARDS + F_D_BITOFF) - a.normal_exp));
440   return tmp;
441 }
442
443
444 /* register <-> sim_fpu */
445
446 INLINE_SIM_FPU (sim_fpu)
447 sim_fpu_32to (unsigned32 s)
448 {
449   sim_ufpu tmp;
450   unpack_fpu (&tmp, s, 0);
451   return ufpu2fpu (&tmp);
452 }
453
454
455 INLINE_SIM_FPU (sim_fpu)
456 sim_fpu_64to (unsigned64 s)
457 {
458   sim_fpu ans;
459   ans.val.i = s;
460   return ans;
461 }
462
463
464 INLINE_SIM_FPU (unsigned32)
465 sim_fpu_to32 (sim_fpu l)
466 {
467   /* convert to single safely */
468   sim_ufpu tmp = fpu2ufpu (&l);
469   return pack_fpu (&tmp, 0);
470 }
471
472
473 INLINE_SIM_FPU (unsigned64)
474 sim_fpu_to64 (sim_fpu s)
475 {
476   return s.val.i;
477 }
478
479
480 /* Arithmetic ops */
481
482 INLINE_SIM_FPU (sim_fpu)
483 sim_fpu_add (sim_fpu l,
484              sim_fpu r)
485 {
486   sim_fpu ans;
487   ans.val.d = l.val.d + r.val.d;
488   return ans;
489 }
490
491
492 INLINE_SIM_FPU (sim_fpu)
493 sim_fpu_sub (sim_fpu l,
494              sim_fpu r)
495 {
496   sim_fpu ans;
497   ans.val.d = l.val.d - r.val.d;
498   return ans;
499 }
500
501
502 INLINE_SIM_FPU (sim_fpu)
503 sim_fpu_mul (sim_fpu l,
504              sim_fpu r)
505 {
506   sim_fpu ans;
507   ans.val.d = l.val.d * r.val.d;
508   return ans;
509 }
510
511
512 INLINE_SIM_FPU (sim_fpu)
513 sim_fpu_div (sim_fpu l,
514              sim_fpu r)
515 {
516   const int is_double = 1;
517   sim_ufpu a = fpu2ufpu (&l);
518   sim_ufpu b = fpu2ufpu (&r);
519   unsigned64 bit;
520   unsigned64 numerator;
521   unsigned64 denominator;
522   unsigned64 quotient;
523
524   if (is_ufpu_nan (&a))
525     {
526       return ufpu2fpu (&a);
527     }
528   if (is_ufpu_nan (&b))
529     {
530       return ufpu2fpu (&b);
531     }
532   if (is_ufpu_inf (&a) || is_ufpu_zero (&a))
533     {
534       if (a.class == b.class)
535         return fpu_nan ();
536       return l;
537     }
538   a.sign = a.sign ^ b.sign;
539
540   if (is_ufpu_inf (&b))
541     {
542       a.fraction = 0;
543       a.normal_exp = 0;
544       return ufpu2fpu (&a);
545     }
546   if (is_ufpu_zero (&b))
547     {
548       a.class = sim_fpu_class_infinity;
549       return ufpu2fpu (&a);
550     }
551
552   /* Calculate the mantissa by multiplying both 64bit numbers to get a
553      128 bit number */
554   {
555     /* quotient =
556        ( numerator / denominator) * 2^(numerator exponent -  denominator exponent)
557      */
558
559     a.normal_exp = a.normal_exp - b.normal_exp;
560     numerator = a.fraction;
561     denominator = b.fraction;
562
563     if (numerator < denominator)
564       {
565         /* Fraction will be less than 1.0 */
566         numerator *= 2;
567         a.normal_exp--;
568       }
569     bit = IMPLICIT_1;
570     quotient = 0;
571     /* ??? Does divide one bit at a time.  Optimize.  */
572     while (bit)
573       {
574         if (numerator >= denominator)
575           {
576             quotient |= bit;
577             numerator -= denominator;
578           }
579         bit >>= 1;
580         numerator *= 2;
581       }
582
583     if ((quotient & GARDMASK) == GARDMSB)
584       {
585         if (quotient & (1 << NGARDS))
586           {
587             /* half way, so round to even */
588             quotient += GARDROUND + 1;
589           }
590         else if (numerator)
591           {
592             /* but we really weren't half way, more bits exist */
593             quotient += GARDROUND + 1;
594           }
595       }
596
597     a.fraction = quotient;
598     return ufpu2fpu (&a);
599   }
600 }
601
602
603 INLINE_SIM_FPU (sim_fpu)
604 sim_fpu_inv (sim_fpu r)
605 {
606   sim_fpu ans;
607   ans.val.d = 1 / r.val.d;
608   return ans;
609 }
610
611
612 INLINE_SIM_FPU (sim_fpu)
613 sim_fpu_sqrt (sim_fpu r)
614 {
615   sim_fpu ans;
616   ans.val.d = sqrt (r.val.d);
617   return ans;
618 }
619
620
621 /* int/long -> sim_fpu */
622
623 INLINE_SIM_FPU (sim_fpu)
624 sim_fpu_i32to (signed32 s)
625 {
626   sim_fpu ans;
627   ans.val.d = s;
628   return ans;
629 }
630
631
632 INLINE_SIM_FPU (signed32)
633 sim_fpu_to32i (sim_fpu s)
634 {
635   return fpu2i (s, 0);
636 }
637
638
639 INLINE_SIM_FPU (sim_fpu)
640 sim_fpu_u32to (unsigned32 s)
641 {
642   sim_fpu ans;
643   ans.val.d = s;
644   return ans;
645 }
646
647
648 INLINE_SIM_FPU (unsigned32)
649 sim_fpu_to32u (sim_fpu s)
650 {
651   return fpu2u (s, 0);
652 }
653
654
655 INLINE_SIM_FPU (sim_fpu)
656 sim_fpu_i64to (signed64 s)
657 {
658   sim_fpu ans;
659   ans.val.d = s;
660   return ans;
661 }
662
663
664 INLINE_SIM_FPU (signed64)
665 sim_fpu_to64i (sim_fpu s)
666 {
667   return fpu2i (s, 1);
668 }
669
670
671 INLINE_SIM_FPU (sim_fpu)
672 sim_fpu_u64to (unsigned64 s)
673 {
674   sim_fpu ans;
675   ans.val.d = s;
676   return ans;
677 }
678
679
680 INLINE_SIM_FPU (unsigned64)
681 sim_fpu_to64u (sim_fpu s)
682 {
683   return fpu2u (s, 1);
684 }
685
686
687 /* sim_fpu -> host format */
688
689 INLINE_SIM_FPU (float)
690 sim_fpu_2f (sim_fpu f)
691 {
692   return f.val.d;
693 }
694
695
696 INLINE_SIM_FPU (double)
697 sim_fpu_2d (sim_fpu s)
698 {
699   return s.val.d;
700 }
701
702
703 INLINE_SIM_FPU (sim_fpu)
704 sim_fpu_f2 (float f)
705 {
706   sim_fpu ans;
707   ans.val.d = f;
708   return ans;
709 }
710
711
712 INLINE_SIM_FPU (sim_fpu)
713 sim_fpu_d2 (double d)
714 {
715   sim_fpu ans;
716   ans.val.d = d;
717   return ans;
718 }
719
720
721 /* General */
722
723 INLINE_SIM_FPU (int)
724 sim_fpu_is_nan (sim_fpu d)
725 {
726   sim_ufpu tmp = fpu2ufpu (&d);
727   return is_ufpu_nan (&tmp);
728 }
729
730
731 /* Compare operators */
732
733 INLINE_SIM_FPU (int)
734 sim_fpu_is_lt (sim_fpu l,
735                sim_fpu r)
736 {
737   sim_ufpu tl = fpu2ufpu (&l);
738   sim_ufpu tr = fpu2ufpu (&r);
739   if (!is_ufpu_nan (&tl) && !is_ufpu_nan (&tr))
740     return (l.val.d < r.val.d);
741   else
742     return 0;
743 }
744
745 INLINE_SIM_FPU (int)
746 sim_fpu_is_le (sim_fpu l,
747                sim_fpu r)
748 {
749   sim_ufpu tl = fpu2ufpu (&l);
750   sim_ufpu tr = fpu2ufpu (&r);
751   if (!is_ufpu_nan (&tl) && !is_ufpu_nan (&tr))
752     return (l.val.d <= r.val.d);
753   else
754     return 0;
755 }
756
757 INLINE_SIM_FPU (int)
758 sim_fpu_is_eq (sim_fpu l,
759                sim_fpu r)
760 {
761   sim_ufpu tl = fpu2ufpu (&l);
762   sim_ufpu tr = fpu2ufpu (&r);
763   if (!is_ufpu_nan (&tl) && !is_ufpu_nan (&tr))
764     return (l.val.d == r.val.d);
765   else
766     return 0;
767 }
768
769 INLINE_SIM_FPU (int)
770 sim_fpu_is_ne (sim_fpu l,
771                sim_fpu r)
772 {
773   sim_ufpu tl = fpu2ufpu (&l);
774   sim_ufpu tr = fpu2ufpu (&r);
775   if (!is_ufpu_nan (&tl) && !is_ufpu_nan (&tr))
776     return (l.val.d != r.val.d);
777   else
778     return 0;
779 }
780
781 INLINE_SIM_FPU (int)
782 sim_fpu_is_ge (sim_fpu l,
783                sim_fpu r)
784 {
785   sim_ufpu tl = fpu2ufpu (&l);
786   sim_ufpu tr = fpu2ufpu (&r);
787   if (!is_ufpu_nan (&tl) && !is_ufpu_nan (&tr))
788     return (l.val.d >= r.val.d);
789   else
790     return 0;
791 }
792
793 INLINE_SIM_FPU (int)
794 sim_fpu_is_gt (sim_fpu l,
795                sim_fpu r)
796 {
797   sim_ufpu tl = fpu2ufpu (&l);
798   sim_ufpu tr = fpu2ufpu (&r);
799   if (!is_ufpu_nan (&tl) && !is_ufpu_nan (&tr))
800     return (l.val.d > r.val.d);
801   else
802     return 0;
803 }
804
805 #endif