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