sim: Factor out NaN handling in floating point operations
[binutils-gdb.git] / sim / common / sim-fpu.c
1 /* This is a software floating point library which can be used instead
2 of the floating point routines in libgcc1.c for targets without
3 hardware floating point. */
4
5 /* Copyright 1994-2022 Free Software Foundation, Inc.
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 3 of the License, or
10 (at your option) 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
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 /* As a special exception, if you link this library with other files,
21 some of which are compiled with GCC, to produce an executable,
22 this library does not by itself cause the resulting executable
23 to be covered by the GNU General Public License.
24 This exception does not however invalidate any other reasons why
25 the executable file might be covered by the GNU General Public License. */
26
27 /* This implements IEEE 754 format arithmetic, but does not provide a
28 mechanism for setting the rounding mode, or for generating or handling
29 exceptions.
30
31 The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
32 Wilson, all of Cygnus Support. */
33
34
35 #ifndef SIM_FPU_C
36 #define SIM_FPU_C
37
38 /* This must come before any other includes. */
39 #include "defs.h"
40
41 #include <stdlib.h>
42
43 #include "sim-basics.h"
44 #include "sim-fpu.h"
45
46 #include "sim-io.h"
47 #include "sim-assert.h"
48
49 /* Debugging support.
50 If digits is -1, then print all digits. */
51
52 static void
53 print_bits (uint64_t x,
54 int msbit,
55 int digits,
56 sim_fpu_print_func print,
57 void *arg)
58 {
59 uint64_t bit = LSBIT64 (msbit);
60 int i = 4;
61 while (bit && digits)
62 {
63 if (i == 0)
64 print (arg, ",");
65
66 if ((x & bit))
67 print (arg, "1");
68 else
69 print (arg, "0");
70 bit >>= 1;
71
72 if (digits > 0)
73 digits--;
74 i = (i + 1) % 4;
75 }
76 }
77
78
79
80 /* Quick and dirty conversion between a host double and host 64bit int. */
81
82 typedef union
83 {
84 double d;
85 uint64_t i;
86 } sim_fpu_map;
87
88
89 /* A packed IEEE floating point number.
90
91 Form is <SIGN:1><BIASEDEXP:NR_EXPBITS><FRAC:NR_FRACBITS> for both
92 32 and 64 bit numbers. This number is interpreted as:
93
94 Normalized (0 < BIASEDEXP && BIASEDEXP < EXPMAX):
95 (sign ? '-' : '+') 1.<FRAC> x 2 ^ (BIASEDEXP - EXPBIAS)
96
97 Denormalized (0 == BIASEDEXP && FRAC != 0):
98 (sign ? "-" : "+") 0.<FRAC> x 2 ^ (- EXPBIAS)
99
100 Zero (0 == BIASEDEXP && FRAC == 0):
101 (sign ? "-" : "+") 0.0
102
103 Infinity (BIASEDEXP == EXPMAX && FRAC == 0):
104 (sign ? "-" : "+") "infinity"
105
106 SignalingNaN (BIASEDEXP == EXPMAX && FRAC > 0 && FRAC < QUIET_NAN):
107 SNaN.FRAC
108
109 QuietNaN (BIASEDEXP == EXPMAX && FRAC > 0 && FRAC > QUIET_NAN):
110 QNaN.FRAC
111
112 */
113
114 #define NR_EXPBITS (is_double ? 11 : 8)
115 #define NR_FRACBITS (is_double ? 52 : 23)
116 #define SIGNBIT (is_double ? MSBIT64 (0) : MSBIT64 (32))
117
118 #define EXPMAX32 (255)
119 #define EXMPAX64 (2047)
120 #define EXPMAX ((unsigned) (is_double ? EXMPAX64 : EXPMAX32))
121
122 #define EXPBIAS32 (127)
123 #define EXPBIAS64 (1023)
124 #define EXPBIAS (is_double ? EXPBIAS64 : EXPBIAS32)
125
126 #define QUIET_NAN LSBIT64 (NR_FRACBITS - 1)
127
128
129
130 /* An unpacked floating point number.
131
132 When unpacked, the fraction of both a 32 and 64 bit floating point
133 number is stored using the same format:
134
135 64 bit - <IMPLICIT_1:1><FRACBITS:52><GUARDS:8><PAD:00>
136 32 bit - <IMPLICIT_1:1><FRACBITS:23><GUARDS:7><PAD:30> */
137
138 #define NR_PAD32 (30)
139 #define NR_PAD64 (0)
140 #define NR_PAD (is_double ? NR_PAD64 : NR_PAD32)
141 #define PADMASK (is_double ? 0 : LSMASK64 (NR_PAD32 - 1, 0))
142
143 #define NR_GUARDS32 (7 + NR_PAD32)
144 #define NR_GUARDS64 (8 + NR_PAD64)
145 #define NR_GUARDS (is_double ? NR_GUARDS64 : NR_GUARDS32)
146 #define GUARDMASK LSMASK64 (NR_GUARDS - 1, 0)
147
148 #define GUARDMSB LSBIT64 (NR_GUARDS - 1)
149 #define GUARDLSB LSBIT64 (NR_PAD)
150 #define GUARDROUND LSMASK64 (NR_GUARDS - 2, 0)
151
152 #define NR_FRAC_GUARD (60)
153 #define IMPLICIT_1 LSBIT64 (NR_FRAC_GUARD)
154 #define IMPLICIT_2 LSBIT64 (NR_FRAC_GUARD + 1)
155 #define IMPLICIT_4 LSBIT64 (NR_FRAC_GUARD + 2)
156 #define NR_SPARE 2
157
158 #define FRAC32MASK LSMASK64 (63, NR_FRAC_GUARD - 32 + 1)
159
160 #define NORMAL_EXPMIN (-(EXPBIAS)+1)
161
162 #define NORMAL_EXPMAX32 (EXPBIAS32)
163 #define NORMAL_EXPMAX64 (EXPBIAS64)
164 #define NORMAL_EXPMAX (EXPBIAS)
165
166
167 /* Integer constants */
168
169 #define MAX_INT32 ((int64_t) LSMASK64 (30, 0))
170 #define MAX_UINT32 LSMASK64 (31, 0)
171 #define MIN_INT32 ((int64_t) LSMASK64 (63, 31))
172
173 #define MAX_INT64 ((int64_t) LSMASK64 (62, 0))
174 #define MAX_UINT64 LSMASK64 (63, 0)
175 #define MIN_INT64 ((int64_t) LSMASK64 (63, 63))
176
177 #define MAX_INT (is_64bit ? MAX_INT64 : MAX_INT32)
178 #define MIN_INT (is_64bit ? MIN_INT64 : MIN_INT32)
179 #define MAX_UINT (is_64bit ? MAX_UINT64 : MAX_UINT32)
180 #define NR_INTBITS (is_64bit ? 64 : 32)
181
182 /* Squeeze an unpacked sim_fpu struct into a 32/64 bit integer. */
183 STATIC_INLINE_SIM_FPU (uint64_t)
184 pack_fpu (const sim_fpu *src,
185 int is_double)
186 {
187 int sign;
188 uint64_t exp;
189 uint64_t fraction;
190 uint64_t packed;
191
192 switch (src->class)
193 {
194 /* Create a NaN. */
195 case sim_fpu_class_qnan:
196 sign = src->sign;
197 exp = EXPMAX;
198 /* Force fraction to correct class. */
199 fraction = src->fraction;
200 fraction >>= NR_GUARDS;
201 if (sim_fpu_quiet_nan_inverted)
202 fraction |= QUIET_NAN - 1;
203 else
204 fraction |= QUIET_NAN;
205 break;
206 case sim_fpu_class_snan:
207 sign = src->sign;
208 exp = EXPMAX;
209 /* Force fraction to correct class. */
210 fraction = src->fraction;
211 fraction >>= NR_GUARDS;
212 if (sim_fpu_quiet_nan_inverted)
213 fraction |= QUIET_NAN;
214 else
215 fraction &= ~QUIET_NAN;
216 break;
217 case sim_fpu_class_infinity:
218 sign = src->sign;
219 exp = EXPMAX;
220 fraction = 0;
221 break;
222 case sim_fpu_class_zero:
223 sign = src->sign;
224 exp = 0;
225 fraction = 0;
226 break;
227 case sim_fpu_class_number:
228 case sim_fpu_class_denorm:
229 ASSERT (src->fraction >= IMPLICIT_1);
230 ASSERT (src->fraction < IMPLICIT_2);
231 if (src->normal_exp < NORMAL_EXPMIN)
232 {
233 /* This number's exponent is too low to fit into the bits
234 available in the number We'll denormalize the number by
235 storing zero in the exponent and shift the fraction to
236 the right to make up for it. */
237 int nr_shift = NORMAL_EXPMIN - src->normal_exp;
238 if (nr_shift > NR_FRACBITS)
239 {
240 /* Underflow, just make the number zero. */
241 sign = src->sign;
242 exp = 0;
243 fraction = 0;
244 }
245 else
246 {
247 sign = src->sign;
248 exp = 0;
249 /* Shift by the value. */
250 fraction = src->fraction;
251 fraction >>= NR_GUARDS;
252 fraction >>= nr_shift;
253 }
254 }
255 else if (src->normal_exp > NORMAL_EXPMAX)
256 {
257 /* Infinity */
258 sign = src->sign;
259 exp = EXPMAX;
260 fraction = 0;
261 }
262 else
263 {
264 exp = (src->normal_exp + EXPBIAS);
265 sign = src->sign;
266 fraction = src->fraction;
267 /* FIXME: Need to round according to WITH_SIM_FPU_ROUNDING
268 or some such. */
269 /* Round to nearest: If the guard bits are the all zero, but
270 the first, then we're half way between two numbers,
271 choose the one which makes the lsb of the answer 0. */
272 if ((fraction & GUARDMASK) == GUARDMSB)
273 {
274 if ((fraction & (GUARDMSB << 1)))
275 fraction += (GUARDMSB << 1);
276 }
277 else
278 {
279 /* Add a one to the guards to force round to nearest. */
280 fraction += GUARDROUND;
281 }
282 if ((fraction & IMPLICIT_2)) /* Rounding resulted in carry. */
283 {
284 exp += 1;
285 fraction >>= 1;
286 }
287 fraction >>= NR_GUARDS;
288 /* When exp == EXPMAX (overflow from carry) fraction must
289 have been made zero. */
290 ASSERT ((exp == EXPMAX) <= ((fraction & ~IMPLICIT_1) == 0));
291 }
292 break;
293 default:
294 abort ();
295 }
296
297 packed = ((sign ? SIGNBIT : 0)
298 | (exp << NR_FRACBITS)
299 | LSMASKED64 (fraction, NR_FRACBITS - 1, 0));
300
301 /* Trace operation. */
302 #if 0
303 if (is_double)
304 {
305 }
306 else
307 {
308 printf ("pack_fpu: ");
309 printf ("-> %c%0lX.%06lX\n",
310 LSMASKED32 (packed, 31, 31) ? '8' : '0',
311 (long) LSEXTRACTED32 (packed, 30, 23),
312 (long) LSEXTRACTED32 (packed, 23 - 1, 0));
313 }
314 #endif
315
316 return packed;
317 }
318
319
320 /* Unpack a 32/64 bit integer into a sim_fpu structure. */
321 STATIC_INLINE_SIM_FPU (void)
322 unpack_fpu (sim_fpu *dst, uint64_t packed, int is_double)
323 {
324 uint64_t fraction = LSMASKED64 (packed, NR_FRACBITS - 1, 0);
325 unsigned exp = LSEXTRACTED64 (packed, NR_EXPBITS + NR_FRACBITS - 1, NR_FRACBITS);
326 int sign = (packed & SIGNBIT) != 0;
327
328 if (exp == 0)
329 {
330 /* Hmm. Looks like 0 */
331 if (fraction == 0)
332 {
333 /* Tastes like zero. */
334 dst->class = sim_fpu_class_zero;
335 dst->sign = sign;
336 dst->normal_exp = 0;
337 }
338 else
339 {
340 /* Zero exponent with non zero fraction - it's denormalized,
341 so there isn't a leading implicit one - we'll shift it so
342 it gets one. */
343 dst->normal_exp = exp - EXPBIAS + 1;
344 dst->class = sim_fpu_class_denorm;
345 dst->sign = sign;
346 fraction <<= NR_GUARDS;
347 while (fraction < IMPLICIT_1)
348 {
349 fraction <<= 1;
350 dst->normal_exp--;
351 }
352 dst->fraction = fraction;
353 }
354 }
355 else if (exp == EXPMAX)
356 {
357 /* Huge exponent*/
358 if (fraction == 0)
359 {
360 /* Attached to a zero fraction - means infinity. */
361 dst->class = sim_fpu_class_infinity;
362 dst->sign = sign;
363 /* dst->normal_exp = EXPBIAS; */
364 /* dst->fraction = 0; */
365 }
366 else
367 {
368 int qnan;
369
370 /* Non zero fraction, means NaN. */
371 dst->sign = sign;
372 dst->fraction = (fraction << NR_GUARDS);
373 if (sim_fpu_quiet_nan_inverted)
374 qnan = (fraction & QUIET_NAN) == 0;
375 else
376 qnan = fraction >= QUIET_NAN;
377 if (qnan)
378 dst->class = sim_fpu_class_qnan;
379 else
380 dst->class = sim_fpu_class_snan;
381 }
382 }
383 else
384 {
385 /* Nothing strange about this number. */
386 dst->class = sim_fpu_class_number;
387 dst->sign = sign;
388 dst->fraction = ((fraction << NR_GUARDS) | IMPLICIT_1);
389 dst->normal_exp = exp - EXPBIAS;
390 }
391
392 /* Trace operation. */
393 #if 0
394 if (is_double)
395 {
396 }
397 else
398 {
399 printf ("unpack_fpu: %c%02lX.%06lX ->\n",
400 LSMASKED32 (packed, 31, 31) ? '8' : '0',
401 (long) LSEXTRACTED32 (packed, 30, 23),
402 (long) LSEXTRACTED32 (packed, 23 - 1, 0));
403 }
404 #endif
405
406 /* sanity checks */
407 {
408 sim_fpu_map val;
409 val.i = pack_fpu (dst, 1);
410 if (is_double)
411 {
412 ASSERT (val.i == packed);
413 }
414 else
415 {
416 uint32_t val = pack_fpu (dst, 0);
417 uint32_t org = packed;
418 ASSERT (val == org);
419 }
420 }
421 }
422
423
424 /* Convert a floating point into an integer. */
425 STATIC_INLINE_SIM_FPU (int)
426 fpu2i (int64_t *i,
427 const sim_fpu *s,
428 int is_64bit,
429 sim_fpu_round round)
430 {
431 uint64_t tmp;
432 int shift;
433 int status = 0;
434 if (sim_fpu_is_zero (s))
435 {
436 *i = 0;
437 return 0;
438 }
439 if (sim_fpu_is_snan (s))
440 {
441 *i = MIN_INT; /* FIXME */
442 return sim_fpu_status_invalid_cvi;
443 }
444 if (sim_fpu_is_qnan (s))
445 {
446 *i = MIN_INT; /* FIXME */
447 return sim_fpu_status_invalid_cvi;
448 }
449 /* Map infinity onto MAX_INT... */
450 if (sim_fpu_is_infinity (s))
451 {
452 *i = s->sign ? MIN_INT : MAX_INT;
453 return sim_fpu_status_invalid_cvi;
454 }
455 /* It is a number, but a small one. */
456 if (s->normal_exp < 0)
457 {
458 *i = 0;
459 return sim_fpu_status_inexact;
460 }
461 /* Is the floating point MIN_INT or just close? */
462 if (s->sign && s->normal_exp == (NR_INTBITS - 1))
463 {
464 *i = MIN_INT;
465 ASSERT (s->fraction >= IMPLICIT_1);
466 if (s->fraction == IMPLICIT_1)
467 return 0; /* exact */
468 if (is_64bit) /* can't round */
469 return sim_fpu_status_invalid_cvi; /* must be overflow */
470 /* For a 32bit with MAX_INT, rounding is possible. */
471 switch (round)
472 {
473 case sim_fpu_round_default:
474 abort ();
475 case sim_fpu_round_zero:
476 if ((s->fraction & FRAC32MASK) != IMPLICIT_1)
477 return sim_fpu_status_invalid_cvi;
478 else
479 return sim_fpu_status_inexact;
480 break;
481 case sim_fpu_round_near:
482 {
483 if ((s->fraction & FRAC32MASK) != IMPLICIT_1)
484 return sim_fpu_status_invalid_cvi;
485 else if ((s->fraction & !FRAC32MASK) >= (~FRAC32MASK >> 1))
486 return sim_fpu_status_invalid_cvi;
487 else
488 return sim_fpu_status_inexact;
489 }
490 case sim_fpu_round_up:
491 if ((s->fraction & FRAC32MASK) == IMPLICIT_1)
492 return sim_fpu_status_inexact;
493 else
494 return sim_fpu_status_invalid_cvi;
495 case sim_fpu_round_down:
496 return sim_fpu_status_invalid_cvi;
497 }
498 }
499 /* Would right shifting result in the FRAC being shifted into
500 (through) the integer's sign bit? */
501 if (s->normal_exp > (NR_INTBITS - 2))
502 {
503 *i = s->sign ? MIN_INT : MAX_INT;
504 return sim_fpu_status_invalid_cvi;
505 }
506 /* Normal number, shift it into place. */
507 tmp = s->fraction;
508 shift = (s->normal_exp - (NR_FRAC_GUARD));
509 if (shift > 0)
510 {
511 tmp <<= shift;
512 }
513 else
514 {
515 shift = -shift;
516 if (tmp & ((SIGNED64 (1) << shift) - 1))
517 status |= sim_fpu_status_inexact;
518 tmp >>= shift;
519 }
520 *i = s->sign ? (-tmp) : (tmp);
521 return status;
522 }
523
524 /* Convert an integer into a floating point. */
525 STATIC_INLINE_SIM_FPU (int)
526 i2fpu (sim_fpu *f, int64_t i, int is_64bit)
527 {
528 int status = 0;
529 if (i == 0)
530 {
531 f->class = sim_fpu_class_zero;
532 f->sign = 0;
533 f->normal_exp = 0;
534 }
535 else
536 {
537 f->class = sim_fpu_class_number;
538 f->sign = (i < 0);
539 f->normal_exp = NR_FRAC_GUARD;
540
541 if (f->sign)
542 {
543 /* Special case for minint, since there is no corresponding
544 +ve integer representation for it. */
545 if (i == MIN_INT)
546 {
547 f->fraction = IMPLICIT_1;
548 f->normal_exp = NR_INTBITS - 1;
549 }
550 else
551 f->fraction = (-i);
552 }
553 else
554 f->fraction = i;
555
556 if (f->fraction >= IMPLICIT_2)
557 {
558 do
559 {
560 f->fraction = (f->fraction >> 1) | (f->fraction & 1);
561 f->normal_exp += 1;
562 }
563 while (f->fraction >= IMPLICIT_2);
564 }
565 else if (f->fraction < IMPLICIT_1)
566 {
567 do
568 {
569 f->fraction <<= 1;
570 f->normal_exp -= 1;
571 }
572 while (f->fraction < IMPLICIT_1);
573 }
574 }
575
576 /* trace operation */
577 #if 0
578 {
579 printf ("i2fpu: 0x%08lX ->\n", (long) i);
580 }
581 #endif
582
583 /* sanity check */
584 {
585 int64_t val;
586 fpu2i (&val, f, is_64bit, sim_fpu_round_zero);
587 if (i >= MIN_INT32 && i <= MAX_INT32)
588 {
589 ASSERT (val == i);
590 }
591 }
592
593 return status;
594 }
595
596
597 /* Convert a floating point into an integer. */
598 STATIC_INLINE_SIM_FPU (int)
599 fpu2u (uint64_t *u, const sim_fpu *s, int is_64bit)
600 {
601 const int is_double = 1;
602 uint64_t tmp;
603 int shift;
604 if (sim_fpu_is_zero (s))
605 {
606 *u = 0;
607 return 0;
608 }
609 if (sim_fpu_is_nan (s))
610 {
611 *u = 0;
612 return 0;
613 }
614 /* It is a negative number. */
615 if (s->sign)
616 {
617 *u = 0;
618 return 0;
619 }
620 /* Get reasonable MAX_USI_INT... */
621 if (sim_fpu_is_infinity (s))
622 {
623 *u = MAX_UINT;
624 return 0;
625 }
626 /* It is a number, but a small one. */
627 if (s->normal_exp < 0)
628 {
629 *u = 0;
630 return 0;
631 }
632 /* overflow */
633 if (s->normal_exp > (NR_INTBITS - 1))
634 {
635 *u = MAX_UINT;
636 return 0;
637 }
638 /* normal number */
639 tmp = (s->fraction & ~PADMASK);
640 shift = (s->normal_exp - (NR_FRACBITS + NR_GUARDS));
641 if (shift > 0)
642 {
643 tmp <<= shift;
644 }
645 else
646 {
647 shift = -shift;
648 tmp >>= shift;
649 }
650 *u = tmp;
651 return 0;
652 }
653
654 /* Convert an unsigned integer into a floating point. */
655 STATIC_INLINE_SIM_FPU (int)
656 u2fpu (sim_fpu *f, uint64_t u, int is_64bit)
657 {
658 if (u == 0)
659 {
660 f->class = sim_fpu_class_zero;
661 f->sign = 0;
662 f->normal_exp = 0;
663 }
664 else
665 {
666 f->class = sim_fpu_class_number;
667 f->sign = 0;
668 f->normal_exp = NR_FRAC_GUARD;
669 f->fraction = u;
670
671 while (f->fraction < IMPLICIT_1)
672 {
673 f->fraction <<= 1;
674 f->normal_exp -= 1;
675 }
676 }
677 return 0;
678 }
679
680
681 /* register <-> sim_fpu */
682
683 INLINE_SIM_FPU (void)
684 sim_fpu_32to (sim_fpu *f, uint32_t s)
685 {
686 unpack_fpu (f, s, 0);
687 }
688
689
690 INLINE_SIM_FPU (void)
691 sim_fpu_232to (sim_fpu *f, uint32_t h, uint32_t l)
692 {
693 uint64_t s = h;
694 s = (s << 32) | l;
695 unpack_fpu (f, s, 1);
696 }
697
698
699 INLINE_SIM_FPU (void)
700 sim_fpu_64to (sim_fpu *f, uint64_t s)
701 {
702 unpack_fpu (f, s, 1);
703 }
704
705
706 INLINE_SIM_FPU (void)
707 sim_fpu_to32 (uint32_t *s,
708 const sim_fpu *f)
709 {
710 *s = pack_fpu (f, 0);
711 }
712
713
714 INLINE_SIM_FPU (void)
715 sim_fpu_to232 (uint32_t *h, uint32_t *l,
716 const sim_fpu *f)
717 {
718 uint64_t s = pack_fpu (f, 1);
719 *l = s;
720 *h = (s >> 32);
721 }
722
723
724 INLINE_SIM_FPU (void)
725 sim_fpu_to64 (uint64_t *u,
726 const sim_fpu *f)
727 {
728 *u = pack_fpu (f, 1);
729 }
730
731
732 INLINE_SIM_FPU (void)
733 sim_fpu_fractionto (sim_fpu *f,
734 int sign,
735 int normal_exp,
736 uint64_t fraction,
737 int precision)
738 {
739 int shift = (NR_FRAC_GUARD - precision);
740 f->class = sim_fpu_class_number;
741 f->sign = sign;
742 f->normal_exp = normal_exp;
743 /* Shift the fraction to where sim-fpu expects it. */
744 if (shift >= 0)
745 f->fraction = (fraction << shift);
746 else
747 f->fraction = (fraction >> -shift);
748 f->fraction |= IMPLICIT_1;
749 }
750
751
752 INLINE_SIM_FPU (uint64_t)
753 sim_fpu_tofraction (const sim_fpu *d,
754 int precision)
755 {
756 /* We have NR_FRAC_GUARD bits, we want only PRECISION bits. */
757 int shift = (NR_FRAC_GUARD - precision);
758 uint64_t fraction = (d->fraction & ~IMPLICIT_1);
759 if (shift >= 0)
760 return fraction >> shift;
761 else
762 return fraction << -shift;
763 }
764
765
766 /* Rounding */
767
768 STATIC_INLINE_SIM_FPU (int)
769 do_normal_overflow (sim_fpu *f,
770 int is_double,
771 sim_fpu_round round)
772 {
773 switch (round)
774 {
775 case sim_fpu_round_default:
776 return 0;
777 case sim_fpu_round_near:
778 f->class = sim_fpu_class_infinity;
779 break;
780 case sim_fpu_round_up:
781 if (!f->sign)
782 f->class = sim_fpu_class_infinity;
783 break;
784 case sim_fpu_round_down:
785 if (f->sign)
786 f->class = sim_fpu_class_infinity;
787 break;
788 case sim_fpu_round_zero:
789 break;
790 }
791 f->normal_exp = NORMAL_EXPMAX;
792 f->fraction = LSMASK64 (NR_FRAC_GUARD, NR_GUARDS);
793 return (sim_fpu_status_overflow | sim_fpu_status_inexact);
794 }
795
796 STATIC_INLINE_SIM_FPU (int)
797 do_normal_underflow (sim_fpu *f,
798 int is_double,
799 sim_fpu_round round)
800 {
801 switch (round)
802 {
803 case sim_fpu_round_default:
804 return 0;
805 case sim_fpu_round_near:
806 f->class = sim_fpu_class_zero;
807 break;
808 case sim_fpu_round_up:
809 if (f->sign)
810 f->class = sim_fpu_class_zero;
811 break;
812 case sim_fpu_round_down:
813 if (!f->sign)
814 f->class = sim_fpu_class_zero;
815 break;
816 case sim_fpu_round_zero:
817 f->class = sim_fpu_class_zero;
818 break;
819 }
820 f->normal_exp = NORMAL_EXPMIN - NR_FRACBITS;
821 f->fraction = IMPLICIT_1;
822 return (sim_fpu_status_inexact | sim_fpu_status_underflow);
823 }
824
825
826
827 /* Round a number using NR_GUARDS.
828 Will return the rounded number or F->FRACTION == 0 when underflow. */
829
830 STATIC_INLINE_SIM_FPU (int)
831 do_normal_round (sim_fpu *f,
832 int nr_guards,
833 sim_fpu_round round)
834 {
835 uint64_t guardmask = LSMASK64 (nr_guards - 1, 0);
836 uint64_t guardmsb = LSBIT64 (nr_guards - 1);
837 uint64_t fraclsb = guardmsb << 1;
838 if ((f->fraction & guardmask))
839 {
840 int status = sim_fpu_status_inexact;
841 switch (round)
842 {
843 case sim_fpu_round_default:
844 return 0;
845 case sim_fpu_round_near:
846 if ((f->fraction & guardmsb))
847 {
848 if ((f->fraction & fraclsb))
849 {
850 status |= sim_fpu_status_rounded;
851 }
852 else if ((f->fraction & (guardmask >> 1)))
853 {
854 status |= sim_fpu_status_rounded;
855 }
856 }
857 break;
858 case sim_fpu_round_up:
859 if (!f->sign)
860 status |= sim_fpu_status_rounded;
861 break;
862 case sim_fpu_round_down:
863 if (f->sign)
864 status |= sim_fpu_status_rounded;
865 break;
866 case sim_fpu_round_zero:
867 break;
868 }
869 f->fraction &= ~guardmask;
870 /* Round if needed, handle resulting overflow. */
871 if ((status & sim_fpu_status_rounded))
872 {
873 f->fraction += fraclsb;
874 if ((f->fraction & IMPLICIT_2))
875 {
876 f->fraction >>= 1;
877 f->normal_exp += 1;
878 }
879 }
880 return status;
881 }
882 else
883 return 0;
884 }
885
886
887 STATIC_INLINE_SIM_FPU (int)
888 do_round (sim_fpu *f,
889 int is_double,
890 sim_fpu_round round,
891 sim_fpu_denorm denorm)
892 {
893 switch (f->class)
894 {
895 case sim_fpu_class_qnan:
896 case sim_fpu_class_zero:
897 case sim_fpu_class_infinity:
898 return 0;
899 break;
900 case sim_fpu_class_snan:
901 /* Quieten a SignalingNaN. */
902 f->class = sim_fpu_class_qnan;
903 return sim_fpu_status_invalid_snan;
904 break;
905 case sim_fpu_class_number:
906 case sim_fpu_class_denorm:
907 {
908 int status;
909 ASSERT (f->fraction < IMPLICIT_2);
910 ASSERT (f->fraction >= IMPLICIT_1);
911 if (f->normal_exp < NORMAL_EXPMIN)
912 {
913 /* This number's exponent is too low to fit into the bits
914 available in the number. Round off any bits that will be
915 discarded as a result of denormalization. Edge case is
916 the implicit bit shifted to GUARD0 and then rounded
917 up. */
918 int shift = NORMAL_EXPMIN - f->normal_exp;
919 if (shift + NR_GUARDS <= NR_FRAC_GUARD + 1
920 && !(denorm & sim_fpu_denorm_zero))
921 {
922 status = do_normal_round (f, shift + NR_GUARDS, round);
923 if (f->fraction == 0) /* Rounding underflowed. */
924 {
925 status |= do_normal_underflow (f, is_double, round);
926 }
927 else if (f->normal_exp < NORMAL_EXPMIN) /* still underflow? */
928 {
929 status |= sim_fpu_status_denorm;
930 /* Any loss of precision when denormalizing is
931 underflow. Some processors check for underflow
932 before rounding, some after! */
933 if (status & sim_fpu_status_inexact)
934 status |= sim_fpu_status_underflow;
935 /* Flag that resultant value has been denormalized. */
936 f->class = sim_fpu_class_denorm;
937 }
938 else if ((denorm & sim_fpu_denorm_underflow_inexact))
939 {
940 if ((status & sim_fpu_status_inexact))
941 status |= sim_fpu_status_underflow;
942 }
943 }
944 else
945 {
946 status = do_normal_underflow (f, is_double, round);
947 }
948 }
949 else if (f->normal_exp > NORMAL_EXPMAX)
950 {
951 /* Infinity */
952 status = do_normal_overflow (f, is_double, round);
953 }
954 else
955 {
956 status = do_normal_round (f, NR_GUARDS, round);
957 if (f->fraction == 0)
958 /* f->class = sim_fpu_class_zero; */
959 status |= do_normal_underflow (f, is_double, round);
960 else if (f->normal_exp > NORMAL_EXPMAX)
961 /* Oops! rounding caused overflow. */
962 status |= do_normal_overflow (f, is_double, round);
963 }
964 ASSERT ((f->class == sim_fpu_class_number
965 || f->class == sim_fpu_class_denorm)
966 <= (f->fraction < IMPLICIT_2 && f->fraction >= IMPLICIT_1));
967 return status;
968 }
969 }
970 return 0;
971 }
972
973 INLINE_SIM_FPU (int)
974 sim_fpu_round_32 (sim_fpu *f,
975 sim_fpu_round round,
976 sim_fpu_denorm denorm)
977 {
978 return do_round (f, 0, round, denorm);
979 }
980
981 INLINE_SIM_FPU (int)
982 sim_fpu_round_64 (sim_fpu *f,
983 sim_fpu_round round,
984 sim_fpu_denorm denorm)
985 {
986 return do_round (f, 1, round, denorm);
987 }
988
989 /* NaN handling for binary operations. */
990
991 INLINE_SIM_FPU (int)
992 sim_fpu_op_nan (sim_fpu *f, const sim_fpu *l, const sim_fpu *r)
993 {
994 if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r))
995 {
996 *f = sim_fpu_is_snan (l) ? *l : *r;
997 f->class = sim_fpu_class_qnan;
998 return sim_fpu_status_invalid_snan;
999 }
1000 ASSERT (sim_fpu_is_nan (l) || sim_fpu_is_nan (r));
1001 if (sim_fpu_is_qnan (l))
1002 *f = *l;
1003 else /* if (sim_fpu_is_qnan (r)) */
1004 *f = *r;
1005 return 0;
1006 }
1007
1008 /* Arithmetic ops */
1009
1010 INLINE_SIM_FPU (int)
1011 sim_fpu_add (sim_fpu *f,
1012 const sim_fpu *l,
1013 const sim_fpu *r)
1014 {
1015 if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
1016 return sim_fpu_op_nan (f, l, r);
1017 if (sim_fpu_is_infinity (l))
1018 {
1019 if (sim_fpu_is_infinity (r)
1020 && l->sign != r->sign)
1021 {
1022 *f = sim_fpu_qnan;
1023 return sim_fpu_status_invalid_isi;
1024 }
1025 *f = *l;
1026 return 0;
1027 }
1028 if (sim_fpu_is_infinity (r))
1029 {
1030 *f = *r;
1031 return 0;
1032 }
1033 if (sim_fpu_is_zero (l))
1034 {
1035 if (sim_fpu_is_zero (r))
1036 {
1037 *f = sim_fpu_zero;
1038 f->sign = l->sign & r->sign;
1039 }
1040 else
1041 *f = *r;
1042 return 0;
1043 }
1044 if (sim_fpu_is_zero (r))
1045 {
1046 *f = *l;
1047 return 0;
1048 }
1049 {
1050 int status = 0;
1051 int shift = l->normal_exp - r->normal_exp;
1052 uint64_t lfraction;
1053 uint64_t rfraction;
1054 /* use exp of larger */
1055 if (shift >= NR_FRAC_GUARD)
1056 {
1057 /* left has much bigger magnitude */
1058 *f = *l;
1059 return sim_fpu_status_inexact;
1060 }
1061 if (shift <= - NR_FRAC_GUARD)
1062 {
1063 /* right has much bigger magnitude */
1064 *f = *r;
1065 return sim_fpu_status_inexact;
1066 }
1067 lfraction = l->fraction;
1068 rfraction = r->fraction;
1069 if (shift > 0)
1070 {
1071 f->normal_exp = l->normal_exp;
1072 if (rfraction & LSMASK64 (shift - 1, 0))
1073 {
1074 status |= sim_fpu_status_inexact;
1075 rfraction |= LSBIT64 (shift); /* Stick LSBit. */
1076 }
1077 rfraction >>= shift;
1078 }
1079 else if (shift < 0)
1080 {
1081 f->normal_exp = r->normal_exp;
1082 if (lfraction & LSMASK64 (- shift - 1, 0))
1083 {
1084 status |= sim_fpu_status_inexact;
1085 lfraction |= LSBIT64 (- shift); /* Stick LSBit. */
1086 }
1087 lfraction >>= -shift;
1088 }
1089 else
1090 {
1091 f->normal_exp = r->normal_exp;
1092 }
1093
1094 /* Perform the addition. */
1095 if (l->sign)
1096 lfraction = - lfraction;
1097 if (r->sign)
1098 rfraction = - rfraction;
1099 f->fraction = lfraction + rfraction;
1100
1101 /* zero? */
1102 if (f->fraction == 0)
1103 {
1104 *f = sim_fpu_zero;
1105 return 0;
1106 }
1107
1108 /* sign? */
1109 f->class = sim_fpu_class_number;
1110 if (((int64_t) f->fraction) >= 0)
1111 f->sign = 0;
1112 else
1113 {
1114 f->sign = 1;
1115 f->fraction = - f->fraction;
1116 }
1117
1118 /* Normalize it. */
1119 if ((f->fraction & IMPLICIT_2))
1120 {
1121 f->fraction = (f->fraction >> 1) | (f->fraction & 1);
1122 f->normal_exp ++;
1123 }
1124 else if (f->fraction < IMPLICIT_1)
1125 {
1126 do
1127 {
1128 f->fraction <<= 1;
1129 f->normal_exp --;
1130 }
1131 while (f->fraction < IMPLICIT_1);
1132 }
1133 ASSERT (f->fraction >= IMPLICIT_1 && f->fraction < IMPLICIT_2);
1134 return status;
1135 }
1136 }
1137
1138
1139 INLINE_SIM_FPU (int)
1140 sim_fpu_sub (sim_fpu *f,
1141 const sim_fpu *l,
1142 const sim_fpu *r)
1143 {
1144 if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
1145 return sim_fpu_op_nan (f, l, r);
1146 if (sim_fpu_is_infinity (l))
1147 {
1148 if (sim_fpu_is_infinity (r)
1149 && l->sign == r->sign)
1150 {
1151 *f = sim_fpu_qnan;
1152 return sim_fpu_status_invalid_isi;
1153 }
1154 *f = *l;
1155 return 0;
1156 }
1157 if (sim_fpu_is_infinity (r))
1158 {
1159 *f = *r;
1160 f->sign = !r->sign;
1161 return 0;
1162 }
1163 if (sim_fpu_is_zero (l))
1164 {
1165 if (sim_fpu_is_zero (r))
1166 {
1167 *f = sim_fpu_zero;
1168 f->sign = l->sign & !r->sign;
1169 }
1170 else
1171 {
1172 *f = *r;
1173 f->sign = !r->sign;
1174 }
1175 return 0;
1176 }
1177 if (sim_fpu_is_zero (r))
1178 {
1179 *f = *l;
1180 return 0;
1181 }
1182 {
1183 int status = 0;
1184 int shift = l->normal_exp - r->normal_exp;
1185 uint64_t lfraction;
1186 uint64_t rfraction;
1187 /* use exp of larger */
1188 if (shift >= NR_FRAC_GUARD)
1189 {
1190 /* left has much bigger magnitude */
1191 *f = *l;
1192 return sim_fpu_status_inexact;
1193 }
1194 if (shift <= - NR_FRAC_GUARD)
1195 {
1196 /* right has much bigger magnitude */
1197 *f = *r;
1198 f->sign = !r->sign;
1199 return sim_fpu_status_inexact;
1200 }
1201 lfraction = l->fraction;
1202 rfraction = r->fraction;
1203 if (shift > 0)
1204 {
1205 f->normal_exp = l->normal_exp;
1206 if (rfraction & LSMASK64 (shift - 1, 0))
1207 {
1208 status |= sim_fpu_status_inexact;
1209 rfraction |= LSBIT64 (shift); /* Stick LSBit. */
1210 }
1211 rfraction >>= shift;
1212 }
1213 else if (shift < 0)
1214 {
1215 f->normal_exp = r->normal_exp;
1216 if (lfraction & LSMASK64 (- shift - 1, 0))
1217 {
1218 status |= sim_fpu_status_inexact;
1219 lfraction |= LSBIT64 (- shift); /* Stick LSBit. */
1220 }
1221 lfraction >>= -shift;
1222 }
1223 else
1224 {
1225 f->normal_exp = r->normal_exp;
1226 }
1227
1228 /* Perform the subtraction. */
1229 if (l->sign)
1230 lfraction = - lfraction;
1231 if (!r->sign)
1232 rfraction = - rfraction;
1233 f->fraction = lfraction + rfraction;
1234
1235 /* zero? */
1236 if (f->fraction == 0)
1237 {
1238 *f = sim_fpu_zero;
1239 return 0;
1240 }
1241
1242 /* sign? */
1243 f->class = sim_fpu_class_number;
1244 if (((int64_t) f->fraction) >= 0)
1245 f->sign = 0;
1246 else
1247 {
1248 f->sign = 1;
1249 f->fraction = - f->fraction;
1250 }
1251
1252 /* Normalize it. */
1253 if ((f->fraction & IMPLICIT_2))
1254 {
1255 f->fraction = (f->fraction >> 1) | (f->fraction & 1);
1256 f->normal_exp ++;
1257 }
1258 else if (f->fraction < IMPLICIT_1)
1259 {
1260 do
1261 {
1262 f->fraction <<= 1;
1263 f->normal_exp --;
1264 }
1265 while (f->fraction < IMPLICIT_1);
1266 }
1267 ASSERT (f->fraction >= IMPLICIT_1 && f->fraction < IMPLICIT_2);
1268 return status;
1269 }
1270 }
1271
1272
1273 INLINE_SIM_FPU (int)
1274 sim_fpu_mul (sim_fpu *f,
1275 const sim_fpu *l,
1276 const sim_fpu *r)
1277 {
1278 if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
1279 return sim_fpu_op_nan (f, l, r);
1280 if (sim_fpu_is_infinity (l))
1281 {
1282 if (sim_fpu_is_zero (r))
1283 {
1284 *f = sim_fpu_qnan;
1285 return sim_fpu_status_invalid_imz;
1286 }
1287 *f = *l;
1288 f->sign = l->sign ^ r->sign;
1289 return 0;
1290 }
1291 if (sim_fpu_is_infinity (r))
1292 {
1293 if (sim_fpu_is_zero (l))
1294 {
1295 *f = sim_fpu_qnan;
1296 return sim_fpu_status_invalid_imz;
1297 }
1298 *f = *r;
1299 f->sign = l->sign ^ r->sign;
1300 return 0;
1301 }
1302 if (sim_fpu_is_zero (l) || sim_fpu_is_zero (r))
1303 {
1304 *f = sim_fpu_zero;
1305 f->sign = l->sign ^ r->sign;
1306 return 0;
1307 }
1308 /* Calculate the mantissa by multiplying both 64bit numbers to get a
1309 128 bit number. */
1310 {
1311 uint64_t low;
1312 uint64_t high;
1313 uint64_t nl = l->fraction & 0xffffffff;
1314 uint64_t nh = l->fraction >> 32;
1315 uint64_t ml = r->fraction & 0xffffffff;
1316 uint64_t mh = r->fraction >>32;
1317 uint64_t pp_ll = ml * nl;
1318 uint64_t pp_hl = mh * nl;
1319 uint64_t pp_lh = ml * nh;
1320 uint64_t pp_hh = mh * nh;
1321 uint64_t res2 = 0;
1322 uint64_t res0 = 0;
1323 uint64_t ps_hh__ = pp_hl + pp_lh;
1324 if (ps_hh__ < pp_hl)
1325 res2 += UNSIGNED64 (0x100000000);
1326 pp_hl = (ps_hh__ << 32) & UNSIGNED64 (0xffffffff00000000);
1327 res0 = pp_ll + pp_hl;
1328 if (res0 < pp_ll)
1329 res2++;
1330 res2 += ((ps_hh__ >> 32) & 0xffffffff) + pp_hh;
1331 high = res2;
1332 low = res0;
1333
1334 f->normal_exp = l->normal_exp + r->normal_exp;
1335 f->sign = l->sign ^ r->sign;
1336 f->class = sim_fpu_class_number;
1337
1338 /* Input is bounded by [1,2) ; [2^60,2^61)
1339 Output is bounded by [1,4) ; [2^120,2^122) */
1340
1341 /* Adjust the exponent according to where the decimal point ended
1342 up in the high 64 bit word. In the source the decimal point
1343 was at NR_FRAC_GUARD. */
1344 f->normal_exp += NR_FRAC_GUARD + 64 - (NR_FRAC_GUARD * 2);
1345
1346 /* The high word is bounded according to the above. Consequently
1347 it has never overflowed into IMPLICIT_2. */
1348 ASSERT (high < LSBIT64 (((NR_FRAC_GUARD + 1) * 2) - 64));
1349 ASSERT (high >= LSBIT64 ((NR_FRAC_GUARD * 2) - 64));
1350 ASSERT (LSBIT64 (((NR_FRAC_GUARD + 1) * 2) - 64) < IMPLICIT_1);
1351
1352 /* Normalize. */
1353 do
1354 {
1355 f->normal_exp--;
1356 high <<= 1;
1357 if (low & LSBIT64 (63))
1358 high |= 1;
1359 low <<= 1;
1360 }
1361 while (high < IMPLICIT_1);
1362
1363 ASSERT (high >= IMPLICIT_1 && high < IMPLICIT_2);
1364 if (low != 0)
1365 {
1366 f->fraction = (high | 1); /* sticky */
1367 return sim_fpu_status_inexact;
1368 }
1369 else
1370 {
1371 f->fraction = high;
1372 return 0;
1373 }
1374 return 0;
1375 }
1376 }
1377
1378 INLINE_SIM_FPU (int)
1379 sim_fpu_div (sim_fpu *f,
1380 const sim_fpu *l,
1381 const sim_fpu *r)
1382 {
1383 if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
1384 return sim_fpu_op_nan (f, l, r);
1385 if (sim_fpu_is_infinity (l))
1386 {
1387 if (sim_fpu_is_infinity (r))
1388 {
1389 *f = sim_fpu_qnan;
1390 return sim_fpu_status_invalid_idi;
1391 }
1392 else
1393 {
1394 *f = *l;
1395 f->sign = l->sign ^ r->sign;
1396 return 0;
1397 }
1398 }
1399 if (sim_fpu_is_zero (l))
1400 {
1401 if (sim_fpu_is_zero (r))
1402 {
1403 *f = sim_fpu_qnan;
1404 return sim_fpu_status_invalid_zdz;
1405 }
1406 else
1407 {
1408 *f = *l;
1409 f->sign = l->sign ^ r->sign;
1410 return 0;
1411 }
1412 }
1413 if (sim_fpu_is_infinity (r))
1414 {
1415 *f = sim_fpu_zero;
1416 f->sign = l->sign ^ r->sign;
1417 return 0;
1418 }
1419 if (sim_fpu_is_zero (r))
1420 {
1421 f->class = sim_fpu_class_infinity;
1422 f->sign = l->sign ^ r->sign;
1423 return sim_fpu_status_invalid_div0;
1424 }
1425
1426 /* Calculate the mantissa by multiplying both 64bit numbers to get a
1427 128 bit number. */
1428 {
1429 /* quotient = ( ( numerator / denominator)
1430 x 2^(numerator exponent - denominator exponent)
1431 */
1432 uint64_t numerator;
1433 uint64_t denominator;
1434 uint64_t quotient;
1435 uint64_t bit;
1436
1437 f->class = sim_fpu_class_number;
1438 f->sign = l->sign ^ r->sign;
1439 f->normal_exp = l->normal_exp - r->normal_exp;
1440
1441 numerator = l->fraction;
1442 denominator = r->fraction;
1443
1444 /* Fraction will be less than 1.0 */
1445 if (numerator < denominator)
1446 {
1447 numerator <<= 1;
1448 f->normal_exp--;
1449 }
1450 ASSERT (numerator >= denominator);
1451
1452 /* Gain extra precision, already used one spare bit. */
1453 numerator <<= NR_SPARE;
1454 denominator <<= NR_SPARE;
1455
1456 /* Does divide one bit at a time. Optimize??? */
1457 quotient = 0;
1458 bit = (IMPLICIT_1 << NR_SPARE);
1459 while (bit)
1460 {
1461 if (numerator >= denominator)
1462 {
1463 quotient |= bit;
1464 numerator -= denominator;
1465 }
1466 bit >>= 1;
1467 numerator <<= 1;
1468 }
1469
1470 /* Discard (but save) the extra bits. */
1471 if ((quotient & LSMASK64 (NR_SPARE -1, 0)))
1472 quotient = (quotient >> NR_SPARE) | 1;
1473 else
1474 quotient = (quotient >> NR_SPARE);
1475
1476 f->fraction = quotient;
1477 ASSERT (f->fraction >= IMPLICIT_1 && f->fraction < IMPLICIT_2);
1478 if (numerator != 0)
1479 {
1480 f->fraction |= 1; /* Stick remaining bits. */
1481 return sim_fpu_status_inexact;
1482 }
1483 else
1484 return 0;
1485 }
1486 }
1487
1488
1489 INLINE_SIM_FPU (int)
1490 sim_fpu_rem (sim_fpu *f,
1491 const sim_fpu *l,
1492 const sim_fpu *r)
1493 {
1494 if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
1495 return sim_fpu_op_nan (f, l, r);
1496 if (sim_fpu_is_infinity (l))
1497 {
1498 *f = sim_fpu_qnan;
1499 return sim_fpu_status_invalid_irx;
1500 }
1501 if (sim_fpu_is_zero (r))
1502 {
1503 *f = sim_fpu_qnan;
1504 return sim_fpu_status_invalid_div0;
1505 }
1506 if (sim_fpu_is_zero (l))
1507 {
1508 *f = *l;
1509 return 0;
1510 }
1511 if (sim_fpu_is_infinity (r))
1512 {
1513 *f = *l;
1514 return 0;
1515 }
1516 {
1517 sim_fpu n, tmp;
1518
1519 /* Remainder is calculated as l-n*r, where n is l/r rounded to the
1520 nearest integer. The variable n is rounded half even. */
1521
1522 sim_fpu_div (&n, l, r);
1523 sim_fpu_round_64 (&n, 0, 0);
1524
1525 if (n.normal_exp < -1) /* If n looks like zero just return l. */
1526 {
1527 *f = *l;
1528 return 0;
1529 }
1530 else if (n.class == sim_fpu_class_number
1531 && n.normal_exp <= (NR_FRAC_GUARD)) /* If not too large round. */
1532 do_normal_round (&n, (NR_FRAC_GUARD) - n.normal_exp, sim_fpu_round_near);
1533
1534 /* Mark 0's as zero so multiply can detect zero. */
1535 if (n.fraction == 0)
1536 n.class = sim_fpu_class_zero;
1537
1538 /* Calculate n*r. */
1539 sim_fpu_mul (&tmp, &n, r);
1540 sim_fpu_round_64 (&tmp, 0, 0);
1541
1542 /* Finally calculate l-n*r. */
1543 sim_fpu_sub (f, l, &tmp);
1544
1545 return 0;
1546 }
1547 }
1548
1549
1550 INLINE_SIM_FPU (int)
1551 sim_fpu_max (sim_fpu *f,
1552 const sim_fpu *l,
1553 const sim_fpu *r)
1554 {
1555 if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
1556 return sim_fpu_op_nan (f, l, r);
1557 if (sim_fpu_is_infinity (l))
1558 {
1559 if (sim_fpu_is_infinity (r)
1560 && l->sign == r->sign)
1561 {
1562 *f = sim_fpu_qnan;
1563 return sim_fpu_status_invalid_isi;
1564 }
1565 if (l->sign)
1566 *f = *r; /* -inf < anything */
1567 else
1568 *f = *l; /* +inf > anything */
1569 return 0;
1570 }
1571 if (sim_fpu_is_infinity (r))
1572 {
1573 if (r->sign)
1574 *f = *l; /* anything > -inf */
1575 else
1576 *f = *r; /* anything < +inf */
1577 return 0;
1578 }
1579 if (l->sign > r->sign)
1580 {
1581 *f = *r; /* -ve < +ve */
1582 return 0;
1583 }
1584 if (l->sign < r->sign)
1585 {
1586 *f = *l; /* +ve > -ve */
1587 return 0;
1588 }
1589 ASSERT (l->sign == r->sign);
1590 if (l->normal_exp > r->normal_exp
1591 || (l->normal_exp == r->normal_exp
1592 && l->fraction > r->fraction))
1593 {
1594 /* |l| > |r| */
1595 if (l->sign)
1596 *f = *r; /* -ve < -ve */
1597 else
1598 *f = *l; /* +ve > +ve */
1599 return 0;
1600 }
1601 else
1602 {
1603 /* |l| <= |r| */
1604 if (l->sign)
1605 *f = *l; /* -ve > -ve */
1606 else
1607 *f = *r; /* +ve < +ve */
1608 return 0;
1609 }
1610 }
1611
1612
1613 INLINE_SIM_FPU (int)
1614 sim_fpu_min (sim_fpu *f,
1615 const sim_fpu *l,
1616 const sim_fpu *r)
1617 {
1618 if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
1619 return sim_fpu_op_nan (f, l, r);
1620 if (sim_fpu_is_infinity (l))
1621 {
1622 if (sim_fpu_is_infinity (r)
1623 && l->sign == r->sign)
1624 {
1625 *f = sim_fpu_qnan;
1626 return sim_fpu_status_invalid_isi;
1627 }
1628 if (l->sign)
1629 *f = *l; /* -inf < anything */
1630 else
1631 *f = *r; /* +inf > anthing */
1632 return 0;
1633 }
1634 if (sim_fpu_is_infinity (r))
1635 {
1636 if (r->sign)
1637 *f = *r; /* anything > -inf */
1638 else
1639 *f = *l; /* anything < +inf */
1640 return 0;
1641 }
1642 if (l->sign > r->sign)
1643 {
1644 *f = *l; /* -ve < +ve */
1645 return 0;
1646 }
1647 if (l->sign < r->sign)
1648 {
1649 *f = *r; /* +ve > -ve */
1650 return 0;
1651 }
1652 ASSERT (l->sign == r->sign);
1653 if (l->normal_exp > r->normal_exp
1654 || (l->normal_exp == r->normal_exp
1655 && l->fraction > r->fraction))
1656 {
1657 /* |l| > |r| */
1658 if (l->sign)
1659 *f = *l; /* -ve < -ve */
1660 else
1661 *f = *r; /* +ve > +ve */
1662 return 0;
1663 }
1664 else
1665 {
1666 /* |l| <= |r| */
1667 if (l->sign)
1668 *f = *r; /* -ve > -ve */
1669 else
1670 *f = *l; /* +ve < +ve */
1671 return 0;
1672 }
1673 }
1674
1675
1676 INLINE_SIM_FPU (int)
1677 sim_fpu_neg (sim_fpu *f,
1678 const sim_fpu *r)
1679 {
1680 if (sim_fpu_is_snan (r))
1681 {
1682 *f = *r;
1683 f->class = sim_fpu_class_qnan;
1684 return sim_fpu_status_invalid_snan;
1685 }
1686 if (sim_fpu_is_qnan (r))
1687 {
1688 *f = *r;
1689 return 0;
1690 }
1691 *f = *r;
1692 f->sign = !r->sign;
1693 return 0;
1694 }
1695
1696
1697 INLINE_SIM_FPU (int)
1698 sim_fpu_abs (sim_fpu *f,
1699 const sim_fpu *r)
1700 {
1701 *f = *r;
1702 f->sign = 0;
1703 if (sim_fpu_is_snan (r))
1704 {
1705 f->class = sim_fpu_class_qnan;
1706 return sim_fpu_status_invalid_snan;
1707 }
1708 return 0;
1709 }
1710
1711
1712 INLINE_SIM_FPU (int)
1713 sim_fpu_inv (sim_fpu *f,
1714 const sim_fpu *r)
1715 {
1716 return sim_fpu_div (f, &sim_fpu_one, r);
1717 }
1718
1719
1720 INLINE_SIM_FPU (int)
1721 sim_fpu_sqrt (sim_fpu *f,
1722 const sim_fpu *r)
1723 {
1724 if (sim_fpu_is_snan (r))
1725 {
1726 *f = sim_fpu_qnan;
1727 return sim_fpu_status_invalid_snan;
1728 }
1729 if (sim_fpu_is_qnan (r))
1730 {
1731 *f = sim_fpu_qnan;
1732 return 0;
1733 }
1734 if (sim_fpu_is_zero (r))
1735 {
1736 f->class = sim_fpu_class_zero;
1737 f->sign = r->sign;
1738 f->normal_exp = 0;
1739 return 0;
1740 }
1741 if (sim_fpu_is_infinity (r))
1742 {
1743 if (r->sign)
1744 {
1745 *f = sim_fpu_qnan;
1746 return sim_fpu_status_invalid_sqrt;
1747 }
1748 else
1749 {
1750 f->class = sim_fpu_class_infinity;
1751 f->sign = 0;
1752 f->sign = 0;
1753 return 0;
1754 }
1755 }
1756 if (r->sign)
1757 {
1758 *f = sim_fpu_qnan;
1759 return sim_fpu_status_invalid_sqrt;
1760 }
1761
1762 /* @(#)e_sqrt.c 5.1 93/09/24 */
1763 /*
1764 * ====================================================
1765 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
1766 *
1767 * Developed at SunPro, a Sun Microsystems, Inc. business.
1768 * Permission to use, copy, modify, and distribute this
1769 * software is freely granted, provided that this notice
1770 * is preserved.
1771 * ====================================================
1772 */
1773
1774 /* __ieee754_sqrt(x)
1775 * Return correctly rounded sqrt.
1776 * ------------------------------------------
1777 * | Use the hardware sqrt if you have one |
1778 * ------------------------------------------
1779 * Method:
1780 * Bit by bit method using integer arithmetic. (Slow, but portable)
1781 * 1. Normalization
1782 * Scale x to y in [1,4) with even powers of 2:
1783 * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then
1784 * sqrt(x) = 2^k * sqrt(y)
1785 -
1786 - Since:
1787 - sqrt ( x*2^(2m) ) = sqrt(x).2^m ; m even
1788 - sqrt ( x*2^(2m + 1) ) = sqrt(2.x).2^m ; m odd
1789 - Define:
1790 - y = ((m even) ? x : 2.x)
1791 - Then:
1792 - y in [1, 4) ; [IMPLICIT_1,IMPLICIT_4)
1793 - And:
1794 - sqrt (y) in [1, 2) ; [IMPLICIT_1,IMPLICIT_2)
1795 -
1796 * 2. Bit by bit computation
1797 * Let q = sqrt(y) truncated to i bit after binary point (q = 1),
1798 * i 0
1799 * i+1 2
1800 * s = 2*q , and y = 2 * ( y - q ). (1)
1801 * i i i i
1802 *
1803 * To compute q from q , one checks whether
1804 * i+1 i
1805 *
1806 * -(i+1) 2
1807 * (q + 2 ) <= y. (2)
1808 * i
1809 * -(i+1)
1810 * If (2) is false, then q = q ; otherwise q = q + 2 .
1811 * i+1 i i+1 i
1812 *
1813 * With some algebraic manipulation, it is not difficult to see
1814 * that (2) is equivalent to
1815 * -(i+1)
1816 * s + 2 <= y (3)
1817 * i i
1818 *
1819 * The advantage of (3) is that s and y can be computed by
1820 * i i
1821 * the following recurrence formula:
1822 * if (3) is false
1823 *
1824 * s = s , y = y ; (4)
1825 * i+1 i i+1 i
1826 *
1827 -
1828 - NOTE: y = 2*y
1829 - i+1 i
1830 -
1831 * otherwise,
1832 * -i -(i+1)
1833 * s = s + 2 , y = y - s - 2 (5)
1834 * i+1 i i+1 i i
1835 *
1836 -
1837 - -(i+1)
1838 - NOTE: y = 2 (y - s - 2 )
1839 - i+1 i i
1840 -
1841 * One may easily use induction to prove (4) and (5).
1842 * Note. Since the left hand side of (3) contain only i+2 bits,
1843 * it does not necessary to do a full (53-bit) comparison
1844 * in (3).
1845 * 3. Final rounding
1846 * After generating the 53 bits result, we compute one more bit.
1847 * Together with the remainder, we can decide whether the
1848 * result is exact, bigger than 1/2ulp, or less than 1/2ulp
1849 * (it will never equal to 1/2ulp).
1850 * The rounding mode can be detected by checking whether
1851 * huge + tiny is equal to huge, and whether huge - tiny is
1852 * equal to huge for some floating point number "huge" and "tiny".
1853 *
1854 * Special cases:
1855 * sqrt(+-0) = +-0 ... exact
1856 * sqrt(inf) = inf
1857 * sqrt(-ve) = NaN ... with invalid signal
1858 * sqrt(NaN) = NaN ... with invalid signal for signalling NaN
1859 *
1860 * Other methods : see the appended file at the end of the program below.
1861 *---------------
1862 */
1863
1864 {
1865 /* Generate sqrt(x) bit by bit. */
1866 uint64_t y;
1867 uint64_t q;
1868 uint64_t s;
1869 uint64_t b;
1870
1871 f->class = sim_fpu_class_number;
1872 f->sign = 0;
1873 y = r->fraction;
1874 f->normal_exp = (r->normal_exp >> 1); /* exp = [exp/2] */
1875
1876 /* Odd exp, double x to make it even. */
1877 ASSERT (y >= IMPLICIT_1 && y < IMPLICIT_4);
1878 if ((r->normal_exp & 1))
1879 {
1880 y += y;
1881 }
1882 ASSERT (y >= IMPLICIT_1 && y < (IMPLICIT_2 << 1));
1883
1884 /* Let loop determine first value of s (either 1 or 2) */
1885 b = IMPLICIT_1;
1886 q = 0;
1887 s = 0;
1888
1889 while (b)
1890 {
1891 uint64_t t = s + b;
1892 if (t <= y)
1893 {
1894 s |= (b << 1);
1895 y -= t;
1896 q |= b;
1897 }
1898 y <<= 1;
1899 b >>= 1;
1900 }
1901
1902 ASSERT (q >= IMPLICIT_1 && q < IMPLICIT_2);
1903 f->fraction = q;
1904 if (y != 0)
1905 {
1906 f->fraction |= 1; /* Stick remaining bits. */
1907 return sim_fpu_status_inexact;
1908 }
1909 else
1910 return 0;
1911 }
1912 }
1913
1914
1915 /* int/long <-> sim_fpu */
1916
1917 INLINE_SIM_FPU (int)
1918 sim_fpu_i32to (sim_fpu *f,
1919 int32_t i,
1920 sim_fpu_round round)
1921 {
1922 i2fpu (f, i, 0);
1923 return 0;
1924 }
1925
1926 INLINE_SIM_FPU (int)
1927 sim_fpu_u32to (sim_fpu *f,
1928 uint32_t u,
1929 sim_fpu_round round)
1930 {
1931 u2fpu (f, u, 0);
1932 return 0;
1933 }
1934
1935 INLINE_SIM_FPU (int)
1936 sim_fpu_i64to (sim_fpu *f,
1937 int64_t i,
1938 sim_fpu_round round)
1939 {
1940 i2fpu (f, i, 1);
1941 return 0;
1942 }
1943
1944 INLINE_SIM_FPU (int)
1945 sim_fpu_u64to (sim_fpu *f,
1946 uint64_t u,
1947 sim_fpu_round round)
1948 {
1949 u2fpu (f, u, 1);
1950 return 0;
1951 }
1952
1953
1954 INLINE_SIM_FPU (int)
1955 sim_fpu_to32i (int32_t *i,
1956 const sim_fpu *f,
1957 sim_fpu_round round)
1958 {
1959 int64_t i64;
1960 int status = fpu2i (&i64, f, 0, round);
1961 *i = i64;
1962 return status;
1963 }
1964
1965 INLINE_SIM_FPU (int)
1966 sim_fpu_to32u (uint32_t *u,
1967 const sim_fpu *f,
1968 sim_fpu_round round)
1969 {
1970 uint64_t u64;
1971 int status = fpu2u (&u64, f, 0);
1972 *u = u64;
1973 return status;
1974 }
1975
1976 INLINE_SIM_FPU (int)
1977 sim_fpu_to64i (int64_t *i,
1978 const sim_fpu *f,
1979 sim_fpu_round round)
1980 {
1981 return fpu2i (i, f, 1, round);
1982 }
1983
1984
1985 INLINE_SIM_FPU (int)
1986 sim_fpu_to64u (uint64_t *u,
1987 const sim_fpu *f,
1988 sim_fpu_round round)
1989 {
1990 return fpu2u (u, f, 1);
1991 }
1992
1993
1994
1995 /* sim_fpu -> host format */
1996
1997 #if 0
1998 INLINE_SIM_FPU (float)
1999 sim_fpu_2f (const sim_fpu *f)
2000 {
2001 return fval.d;
2002 }
2003 #endif
2004
2005
2006 INLINE_SIM_FPU (double)
2007 sim_fpu_2d (const sim_fpu *s)
2008 {
2009 sim_fpu_map val;
2010 if (sim_fpu_is_snan (s))
2011 {
2012 /* gag SNaN's */
2013 sim_fpu n = *s;
2014 n.class = sim_fpu_class_qnan;
2015 val.i = pack_fpu (&n, 1);
2016 }
2017 else
2018 {
2019 val.i = pack_fpu (s, 1);
2020 }
2021 return val.d;
2022 }
2023
2024
2025 #if 0
2026 INLINE_SIM_FPU (void)
2027 sim_fpu_f2 (sim_fpu *f,
2028 float s)
2029 {
2030 sim_fpu_map val;
2031 val.d = s;
2032 unpack_fpu (f, val.i, 1);
2033 }
2034 #endif
2035
2036
2037 INLINE_SIM_FPU (void)
2038 sim_fpu_d2 (sim_fpu *f,
2039 double d)
2040 {
2041 sim_fpu_map val;
2042 val.d = d;
2043 unpack_fpu (f, val.i, 1);
2044 }
2045
2046
2047 /* General */
2048
2049 INLINE_SIM_FPU (int)
2050 sim_fpu_is_nan (const sim_fpu *d)
2051 {
2052 switch (d->class)
2053 {
2054 case sim_fpu_class_qnan:
2055 case sim_fpu_class_snan:
2056 return 1;
2057 default:
2058 return 0;
2059 }
2060 }
2061
2062 INLINE_SIM_FPU (int)
2063 sim_fpu_is_qnan (const sim_fpu *d)
2064 {
2065 switch (d->class)
2066 {
2067 case sim_fpu_class_qnan:
2068 return 1;
2069 default:
2070 return 0;
2071 }
2072 }
2073
2074 INLINE_SIM_FPU (int)
2075 sim_fpu_is_snan (const sim_fpu *d)
2076 {
2077 switch (d->class)
2078 {
2079 case sim_fpu_class_snan:
2080 return 1;
2081 default:
2082 return 0;
2083 }
2084 }
2085
2086 INLINE_SIM_FPU (int)
2087 sim_fpu_is_zero (const sim_fpu *d)
2088 {
2089 switch (d->class)
2090 {
2091 case sim_fpu_class_zero:
2092 return 1;
2093 default:
2094 return 0;
2095 }
2096 }
2097
2098 INLINE_SIM_FPU (int)
2099 sim_fpu_is_infinity (const sim_fpu *d)
2100 {
2101 switch (d->class)
2102 {
2103 case sim_fpu_class_infinity:
2104 return 1;
2105 default:
2106 return 0;
2107 }
2108 }
2109
2110 INLINE_SIM_FPU (int)
2111 sim_fpu_is_number (const sim_fpu *d)
2112 {
2113 switch (d->class)
2114 {
2115 case sim_fpu_class_denorm:
2116 case sim_fpu_class_number:
2117 return 1;
2118 default:
2119 return 0;
2120 }
2121 }
2122
2123 INLINE_SIM_FPU (int)
2124 sim_fpu_is_denorm (const sim_fpu *d)
2125 {
2126 switch (d->class)
2127 {
2128 case sim_fpu_class_denorm:
2129 return 1;
2130 default:
2131 return 0;
2132 }
2133 }
2134
2135
2136 INLINE_SIM_FPU (int)
2137 sim_fpu_sign (const sim_fpu *d)
2138 {
2139 return d->sign;
2140 }
2141
2142
2143 INLINE_SIM_FPU (int)
2144 sim_fpu_exp (const sim_fpu *d)
2145 {
2146 return d->normal_exp;
2147 }
2148
2149
2150 INLINE_SIM_FPU (uint64_t)
2151 sim_fpu_fraction (const sim_fpu *d)
2152 {
2153 return d->fraction;
2154 }
2155
2156
2157 INLINE_SIM_FPU (uint64_t)
2158 sim_fpu_guard (const sim_fpu *d, int is_double)
2159 {
2160 uint64_t rv;
2161 uint64_t guardmask = LSMASK64 (NR_GUARDS - 1, 0);
2162 rv = (d->fraction & guardmask) >> NR_PAD;
2163 return rv;
2164 }
2165
2166
2167 INLINE_SIM_FPU (int)
2168 sim_fpu_is (const sim_fpu *d)
2169 {
2170 switch (d->class)
2171 {
2172 case sim_fpu_class_qnan:
2173 return SIM_FPU_IS_QNAN;
2174 case sim_fpu_class_snan:
2175 return SIM_FPU_IS_SNAN;
2176 case sim_fpu_class_infinity:
2177 if (d->sign)
2178 return SIM_FPU_IS_NINF;
2179 else
2180 return SIM_FPU_IS_PINF;
2181 case sim_fpu_class_number:
2182 if (d->sign)
2183 return SIM_FPU_IS_NNUMBER;
2184 else
2185 return SIM_FPU_IS_PNUMBER;
2186 case sim_fpu_class_denorm:
2187 if (d->sign)
2188 return SIM_FPU_IS_NDENORM;
2189 else
2190 return SIM_FPU_IS_PDENORM;
2191 case sim_fpu_class_zero:
2192 if (d->sign)
2193 return SIM_FPU_IS_NZERO;
2194 else
2195 return SIM_FPU_IS_PZERO;
2196 default:
2197 return -1;
2198 abort ();
2199 }
2200 }
2201
2202 INLINE_SIM_FPU (int)
2203 sim_fpu_cmp (const sim_fpu *l, const sim_fpu *r)
2204 {
2205 sim_fpu res;
2206 sim_fpu_sub (&res, l, r);
2207 return sim_fpu_is (&res);
2208 }
2209
2210 INLINE_SIM_FPU (int)
2211 sim_fpu_is_lt (const sim_fpu *l, const sim_fpu *r)
2212 {
2213 int status;
2214 sim_fpu_lt (&status, l, r);
2215 return status;
2216 }
2217
2218 INLINE_SIM_FPU (int)
2219 sim_fpu_is_le (const sim_fpu *l, const sim_fpu *r)
2220 {
2221 int is;
2222 sim_fpu_le (&is, l, r);
2223 return is;
2224 }
2225
2226 INLINE_SIM_FPU (int)
2227 sim_fpu_is_eq (const sim_fpu *l, const sim_fpu *r)
2228 {
2229 int is;
2230 sim_fpu_eq (&is, l, r);
2231 return is;
2232 }
2233
2234 INLINE_SIM_FPU (int)
2235 sim_fpu_is_ne (const sim_fpu *l, const sim_fpu *r)
2236 {
2237 int is;
2238 sim_fpu_ne (&is, l, r);
2239 return is;
2240 }
2241
2242 INLINE_SIM_FPU (int)
2243 sim_fpu_is_ge (const sim_fpu *l, const sim_fpu *r)
2244 {
2245 int is;
2246 sim_fpu_ge (&is, l, r);
2247 return is;
2248 }
2249
2250 INLINE_SIM_FPU (int)
2251 sim_fpu_is_gt (const sim_fpu *l, const sim_fpu *r)
2252 {
2253 int is;
2254 sim_fpu_gt (&is, l, r);
2255 return is;
2256 }
2257
2258
2259 /* Compare operators */
2260
2261 INLINE_SIM_FPU (int)
2262 sim_fpu_lt (int *is,
2263 const sim_fpu *l,
2264 const sim_fpu *r)
2265 {
2266 if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r))
2267 {
2268 sim_fpu_map lval;
2269 sim_fpu_map rval;
2270 lval.i = pack_fpu (l, 1);
2271 rval.i = pack_fpu (r, 1);
2272 (*is) = (lval.d < rval.d);
2273 return 0;
2274 }
2275 else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r))
2276 {
2277 *is = 0;
2278 return sim_fpu_status_invalid_snan;
2279 }
2280 else
2281 {
2282 *is = 0;
2283 return sim_fpu_status_invalid_qnan;
2284 }
2285 }
2286
2287 INLINE_SIM_FPU (int)
2288 sim_fpu_le (int *is,
2289 const sim_fpu *l,
2290 const sim_fpu *r)
2291 {
2292 if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r))
2293 {
2294 sim_fpu_map lval;
2295 sim_fpu_map rval;
2296 lval.i = pack_fpu (l, 1);
2297 rval.i = pack_fpu (r, 1);
2298 *is = (lval.d <= rval.d);
2299 return 0;
2300 }
2301 else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r))
2302 {
2303 *is = 0;
2304 return sim_fpu_status_invalid_snan;
2305 }
2306 else
2307 {
2308 *is = 0;
2309 return sim_fpu_status_invalid_qnan;
2310 }
2311 }
2312
2313 INLINE_SIM_FPU (int)
2314 sim_fpu_eq (int *is,
2315 const sim_fpu *l,
2316 const sim_fpu *r)
2317 {
2318 if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r))
2319 {
2320 sim_fpu_map lval;
2321 sim_fpu_map rval;
2322 lval.i = pack_fpu (l, 1);
2323 rval.i = pack_fpu (r, 1);
2324 (*is) = (lval.d == rval.d);
2325 return 0;
2326 }
2327 else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r))
2328 {
2329 *is = 0;
2330 return sim_fpu_status_invalid_snan;
2331 }
2332 else
2333 {
2334 *is = 0;
2335 return sim_fpu_status_invalid_qnan;
2336 }
2337 }
2338
2339 INLINE_SIM_FPU (int)
2340 sim_fpu_ne (int *is,
2341 const sim_fpu *l,
2342 const sim_fpu *r)
2343 {
2344 if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r))
2345 {
2346 sim_fpu_map lval;
2347 sim_fpu_map rval;
2348 lval.i = pack_fpu (l, 1);
2349 rval.i = pack_fpu (r, 1);
2350 (*is) = (lval.d != rval.d);
2351 return 0;
2352 }
2353 else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r))
2354 {
2355 *is = 0;
2356 return sim_fpu_status_invalid_snan;
2357 }
2358 else
2359 {
2360 *is = 0;
2361 return sim_fpu_status_invalid_qnan;
2362 }
2363 }
2364
2365 INLINE_SIM_FPU (int)
2366 sim_fpu_ge (int *is,
2367 const sim_fpu *l,
2368 const sim_fpu *r)
2369 {
2370 return sim_fpu_le (is, r, l);
2371 }
2372
2373 INLINE_SIM_FPU (int)
2374 sim_fpu_gt (int *is,
2375 const sim_fpu *l,
2376 const sim_fpu *r)
2377 {
2378 return sim_fpu_lt (is, r, l);
2379 }
2380
2381
2382 /* A number of useful constants */
2383
2384 #if EXTERN_SIM_FPU_P
2385 sim_fpu_state _sim_fpu = {
2386 .quiet_nan_inverted = false,
2387 };
2388
2389 const sim_fpu sim_fpu_zero = {
2390 sim_fpu_class_zero, 0, 0, 0
2391 };
2392 const sim_fpu sim_fpu_qnan = {
2393 sim_fpu_class_qnan, 0, 0, 0
2394 };
2395 const sim_fpu sim_fpu_one = {
2396 sim_fpu_class_number, 0, IMPLICIT_1, 0
2397 };
2398 const sim_fpu sim_fpu_two = {
2399 sim_fpu_class_number, 0, IMPLICIT_1, 1
2400 };
2401 const sim_fpu sim_fpu_max32 = {
2402 sim_fpu_class_number, 0, LSMASK64 (NR_FRAC_GUARD, NR_GUARDS32), NORMAL_EXPMAX32
2403 };
2404 const sim_fpu sim_fpu_max64 = {
2405 sim_fpu_class_number, 0, LSMASK64 (NR_FRAC_GUARD, NR_GUARDS64), NORMAL_EXPMAX64
2406 };
2407 #endif
2408
2409
2410 /* For debugging */
2411
2412 INLINE_SIM_FPU (void)
2413 sim_fpu_print_fpu (const sim_fpu *f,
2414 sim_fpu_print_func *print,
2415 void *arg)
2416 {
2417 sim_fpu_printn_fpu (f, print, -1, arg);
2418 }
2419
2420 INLINE_SIM_FPU (void)
2421 sim_fpu_printn_fpu (const sim_fpu *f,
2422 sim_fpu_print_func *print,
2423 int digits,
2424 void *arg)
2425 {
2426 print (arg, "%s", f->sign ? "-" : "+");
2427 switch (f->class)
2428 {
2429 case sim_fpu_class_qnan:
2430 print (arg, "0.");
2431 print_bits (f->fraction, NR_FRAC_GUARD - 1, digits, print, arg);
2432 print (arg, "*QuietNaN");
2433 break;
2434 case sim_fpu_class_snan:
2435 print (arg, "0.");
2436 print_bits (f->fraction, NR_FRAC_GUARD - 1, digits, print, arg);
2437 print (arg, "*SignalNaN");
2438 break;
2439 case sim_fpu_class_zero:
2440 print (arg, "0.0");
2441 break;
2442 case sim_fpu_class_infinity:
2443 print (arg, "INF");
2444 break;
2445 case sim_fpu_class_number:
2446 case sim_fpu_class_denorm:
2447 print (arg, "1.");
2448 print_bits (f->fraction, NR_FRAC_GUARD - 1, digits, print, arg);
2449 print (arg, "*2^%+d", f->normal_exp);
2450 ASSERT (f->fraction >= IMPLICIT_1);
2451 ASSERT (f->fraction < IMPLICIT_2);
2452 }
2453 }
2454
2455
2456 INLINE_SIM_FPU (void)
2457 sim_fpu_print_status (int status,
2458 sim_fpu_print_func *print,
2459 void *arg)
2460 {
2461 int i = 1;
2462 const char *prefix = "";
2463 while (status >= i)
2464 {
2465 switch ((sim_fpu_status) (status & i))
2466 {
2467 case sim_fpu_status_denorm:
2468 print (arg, "%sD", prefix);
2469 break;
2470 case sim_fpu_status_invalid_snan:
2471 print (arg, "%sSNaN", prefix);
2472 break;
2473 case sim_fpu_status_invalid_qnan:
2474 print (arg, "%sQNaN", prefix);
2475 break;
2476 case sim_fpu_status_invalid_isi:
2477 print (arg, "%sISI", prefix);
2478 break;
2479 case sim_fpu_status_invalid_idi:
2480 print (arg, "%sIDI", prefix);
2481 break;
2482 case sim_fpu_status_invalid_zdz:
2483 print (arg, "%sZDZ", prefix);
2484 break;
2485 case sim_fpu_status_invalid_imz:
2486 print (arg, "%sIMZ", prefix);
2487 break;
2488 case sim_fpu_status_invalid_cvi:
2489 print (arg, "%sCVI", prefix);
2490 break;
2491 case sim_fpu_status_invalid_cmp:
2492 print (arg, "%sCMP", prefix);
2493 break;
2494 case sim_fpu_status_invalid_sqrt:
2495 print (arg, "%sSQRT", prefix);
2496 break;
2497 case sim_fpu_status_invalid_irx:
2498 print (arg, "%sIRX", prefix);
2499 break;
2500 case sim_fpu_status_inexact:
2501 print (arg, "%sX", prefix);
2502 break;
2503 case sim_fpu_status_overflow:
2504 print (arg, "%sO", prefix);
2505 break;
2506 case sim_fpu_status_underflow:
2507 print (arg, "%sU", prefix);
2508 break;
2509 case sim_fpu_status_invalid_div0:
2510 print (arg, "%s/", prefix);
2511 break;
2512 case sim_fpu_status_rounded:
2513 print (arg, "%sR", prefix);
2514 break;
2515 }
2516 i <<= 1;
2517 prefix = ",";
2518 }
2519 }
2520
2521 #endif