Remove some of the flake from the c80 floating point.
[deliverable/binutils-gdb.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
This page took 0.064161 seconds and 5 git commands to generate.