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