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