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