1 /* fpu.c --- FPU emulator for stand-alone RX simulator.
3 Copyright (C) 2008-2019 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
6 This file is part of the GNU simulators.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
28 /* FPU encodings are as follows:
31 1 12345678 12345678901234567890123
33 0 00000000 00000000000000000000000 +0
34 1 00000000 00000000000000000000000 -0
36 X 00000000 00000000000000000000001 Denormals
37 X 00000000 11111111111111111111111
39 X 00000001 XXXXXXXXXXXXXXXXXXXXXXX Normals
40 X 11111110 XXXXXXXXXXXXXXXXXXXXXXX
42 0 11111111 00000000000000000000000 +Inf
43 1 11111111 00000000000000000000000 -Inf
45 X 11111111 0XXXXXXXXXXXXXXXXXXXXXX SNaN (X != 0)
46 X 11111111 1XXXXXXXXXXXXXXXXXXXXXX QNaN (X != 0)
51 #define tprintf if (trace) printf
53 /* Some magic numbers. */
54 #define PLUS_MAX 0x7f7fffffUL
55 #define MINUS_MAX 0xff7fffffUL
56 #define PLUS_INF 0x7f800000UL
57 #define MINUS_INF 0xff800000UL
58 #define PLUS_ZERO 0x00000000UL
59 #define MINUS_ZERO 0x80000000UL
61 #define FP_RAISE(e) fp_raise(FPSWBITS_C##e)
66 if (mask != FPSWBITS_CE)
68 if (regs.r_fpsw & (mask << FPSW_CESH))
69 regs.r_fpsw |= (mask << FPSW_CFSH);
70 if (regs.r_fpsw & FPSWBITS_FMASK)
71 regs.r_fpsw |= FPSWBITS_FSUM;
73 regs.r_fpsw &= ~FPSWBITS_FSUM;
77 /* We classify all numbers as one of these. They correspond to the
78 rows/colums in the exception tables. */
91 static const char *fpt_names[] = {
92 "Normal", "+0", "-0", "+Inf", "-Inf", "Denormal", "QNaN", "SNaN"
100 #define MANT_BIAS 0x00080000UL
104 unsigned int mant; /* 24 bits */
111 fp_explode (fp_t f, FP_Parts *p)
115 exp = ((f & 0x7f800000UL) >> 23);
116 mant = f & 0x007fffffUL;
117 sign = f & 0x80000000UL;
118 /*printf("explode: %08x %x %2x %6x\n", f, sign, exp, mant);*/
120 p->sign = sign ? -1 : 1;
121 p->exp = exp - EXP_BIAS;
123 p->mant = mant | 0x00800000UL;
125 if (p->exp == EXP_ZERO)
127 if (regs.r_fpsw & FPSWBITS_DN)
130 p->type = FP_DENORMAL;
134 p->type = sign ? FP_NZERO : FP_PZERO;
137 else if (p->exp == EXP_INF)
140 p->type = sign ? FP_NINFINITY : FP_PINFINITY;
141 else if (mant & 0x00400000UL)
151 fp_implode (FP_Parts *p)
155 exp = p->exp + EXP_BIAS;
157 /*printf("implode: exp %d mant 0x%x\n", exp, mant);*/
158 if (p->type == FP_NORMAL)
162 && mant < 0x00800000UL)
167 while (mant > 0x00ffffffUL)
187 mant &= 0x007fffffUL;
191 mant |= 0x80000000UL;
197 unsigned long long ll;
201 static int checked_format = 0;
203 /* We assume a double format like this:
208 fp_to_double (FP_Parts *p)
215 if (u.ll != 0x3ff8000000000000ULL)
218 if (u.ll != 0xc06c200000000000ULL)
221 if (u.ll != 0x4024333333333333ULL)
228 u.ll |= (1ULL << 63);
229 /* Make sure a zero encoding stays a zero. */
230 if (p->exp != -EXP_BIAS)
231 u.ll |= ((unsigned long long)p->exp + 1023ULL) << 52;
232 u.ll |= (unsigned long long) (p->mant & 0x007fffffUL) << (52 - 23);
237 double_to_fp (double d, FP_Parts *p)
245 sign = (u.ll & 0x8000000000000000ULL) ? 1 : 0;
251 /* A generated denormal should show up as an underflow, not
254 fp_explode (MINUS_ZERO, p);
256 fp_explode (PLUS_ZERO, p);
261 if ((exp + EXP_BIAS) > 254)
264 switch (regs.r_fpsw & FPSWBITS_RM)
268 fp_explode (MINUS_INF, p);
270 fp_explode (PLUS_INF, p);
274 fp_explode (MINUS_MAX, p);
276 fp_explode (PLUS_MAX, p);
280 fp_explode (MINUS_MAX, p);
282 fp_explode (PLUS_INF, p);
286 fp_explode (MINUS_INF, p);
288 fp_explode (PLUS_MAX, p);
293 if ((exp + EXP_BIAS) < 1)
296 fp_explode (MINUS_ZERO, p);
298 fp_explode (PLUS_ZERO, p);
302 p->sign = sign ? -1 : 1;
304 p->mant = u.ll >> (52-23) & 0x007fffffUL;
305 p->mant |= 0x00800000UL;
308 if (u.ll & 0x1fffffffULL)
310 switch (regs.r_fpsw & FPSWBITS_RM)
313 if (u.ll & 0x10000000ULL)
333 eNR, /* Use the normal result. */
334 ePZ, eNZ, /* +- zero */
335 eSZ, /* signed zero - XOR signs of ops together. */
336 eRZ, /* +- zero depending on rounding mode. */
337 ePI, eNI, /* +- Infinity */
338 eSI, /* signed infinity - XOR signs of ops together. */
339 eQN, eSN, /* Quiet/Signalling NANs */
341 eUn, /* Unimplemented. */
342 eDZ, /* Divide-by-zero. */
344 eGT, /* greater than */
349 static const char *ex_names[] = {
350 "NR", "PZ", "NZ", "SZ", "RZ", "PI", "NI", "SI", "QN", "SN", "IN", "Un", "DZ", "LT", "GT", "EQ"
354 /* This checks for all exceptional cases (not all FP exceptions) and
355 returns TRUE if it is providing the result in *c. If it returns
356 FALSE, the caller should do the "normal" operation. */
358 check_exceptions (FP_Parts *a, FP_Parts *b, fp_t *c,
359 FP_ExceptionCases ex_tab[5][5],
360 FP_ExceptionCases *case_ret)
362 FP_ExceptionCases fpec;
364 if (a->type == FP_SNAN
365 || b->type == FP_SNAN)
367 else if (a->type == FP_QNAN
368 || b->type == FP_QNAN)
370 else if (a->type == FP_DENORMAL
371 || b->type == FP_DENORMAL)
374 fpec = ex_tab[(int)(a->type)][(int)(b->type)];
376 /*printf("%s %s -> %s\n", fpt_names[(int)(a->type)], fpt_names[(int)(b->type)], ex_names[(int)(fpec)]);*/
383 case eNR: /* Use the normal result. */
386 case ePZ: /* + zero */
390 case eNZ: /* - zero */
394 case eSZ: /* signed zero */
395 *c = (a->sign == b->sign) ? PLUS_ZERO : MINUS_ZERO;
398 case eRZ: /* +- zero depending on rounding mode. */
399 if ((regs.r_fpsw & FPSWBITS_RM) == FPRM_NINF)
405 case ePI: /* + Infinity */
409 case eNI: /* - Infinity */
413 case eSI: /* sign Infinity */
414 *c = (a->sign == b->sign) ? PLUS_INF : MINUS_INF;
417 case eQN: /* Quiet NANs */
418 if (a->type == FP_QNAN)
424 case eSN: /* Signalling NANs */
425 if (a->type == FP_SNAN)
432 case eIn: /* Invalid. */
434 if (a->type == FP_SNAN)
435 *c = a->orig_value | 0x00400000;
436 else if (b->type == FP_SNAN)
437 *c = b->orig_value | 0x00400000;
442 case eUn: /* Unimplemented. */
446 case eDZ: /* Division-by-zero. */
447 *c = (a->sign == b->sign) ? PLUS_INF : MINUS_INF;
456 #define CHECK_EXCEPTIONS(FPPa, FPPb, fpc, ex_tab) \
457 if (check_exceptions (&FPPa, &FPPb, &fpc, ex_tab, 0)) \
460 /* For each operation, we have two tables of how nonnormal cases are
461 handled. The DN=0 case is first, followed by the DN=1 case, with
462 each table using the following layout: */
464 static FP_ExceptionCases ex_add_tab[5][5] = {
465 /* N +0 -0 +In -In */
466 { eNR, eNR, eNR, ePI, eNI }, /* Normal */
467 { eNR, ePZ, eRZ, ePI, eNI }, /* +0 */
468 { eNR, eRZ, eNZ, ePI, eNI }, /* -0 */
469 { ePI, ePI, ePI, ePI, eIn }, /* +Inf */
470 { eNI, eNI, eNI, eIn, eNI }, /* -Inf */
474 rxfp_add (fp_t fa, fp_t fb)
482 CHECK_EXCEPTIONS (a, b, rv, ex_add_tab);
484 da = fp_to_double (&a);
485 db = fp_to_double (&b);
486 tprintf("%g + %g = %g\n", da, db, da+db);
488 double_to_fp (da+db, &c);
489 rv = fp_implode (&c);
493 static FP_ExceptionCases ex_sub_tab[5][5] = {
494 /* N +0 -0 +In -In */
495 { eNR, eNR, eNR, eNI, ePI }, /* Normal */
496 { eNR, eRZ, ePZ, eNI, ePI }, /* +0 */
497 { eNR, eNZ, eRZ, eNI, ePI }, /* -0 */
498 { ePI, ePI, ePI, eIn, ePI }, /* +Inf */
499 { eNI, eNI, eNI, eNI, eIn }, /* -Inf */
503 rxfp_sub (fp_t fa, fp_t fb)
511 CHECK_EXCEPTIONS (a, b, rv, ex_sub_tab);
513 da = fp_to_double (&a);
514 db = fp_to_double (&b);
515 tprintf("%g - %g = %g\n", da, db, da-db);
517 double_to_fp (da-db, &c);
518 rv = fp_implode (&c);
523 static FP_ExceptionCases ex_mul_tab[5][5] = {
524 /* N +0 -0 +In -In */
525 { eNR, eNR, eNR, eSI, eSI }, /* Normal */
526 { eNR, ePZ, eNZ, eIn, eIn }, /* +0 */
527 { eNR, eNZ, ePZ, eIn, eIn }, /* -0 */
528 { eSI, eIn, eIn, ePI, eNI }, /* +Inf */
529 { eSI, eIn, eIn, eNI, ePI }, /* -Inf */
533 rxfp_mul (fp_t fa, fp_t fb)
541 CHECK_EXCEPTIONS (a, b, rv, ex_mul_tab);
543 da = fp_to_double (&a);
544 db = fp_to_double (&b);
545 tprintf("%g x %g = %g\n", da, db, da*db);
547 double_to_fp (da*db, &c);
548 rv = fp_implode (&c);
553 static FP_ExceptionCases ex_div_tab[5][5] = {
554 /* N +0 -0 +In -In */
555 { eNR, eDZ, eDZ, eSZ, eSZ }, /* Normal */
556 { eSZ, eIn, eIn, ePZ, eNZ }, /* +0 */
557 { eSZ, eIn, eIn, eNZ, ePZ }, /* -0 */
558 { eSI, ePI, eNI, eIn, eIn }, /* +Inf */
559 { eSI, eNI, ePI, eIn, eIn }, /* -Inf */
563 rxfp_div (fp_t fa, fp_t fb)
571 CHECK_EXCEPTIONS (a, b, rv, ex_div_tab);
573 da = fp_to_double (&a);
574 db = fp_to_double (&b);
575 tprintf("%g / %g = %g\n", da, db, da/db);
577 double_to_fp (da/db, &c);
578 rv = fp_implode (&c);
583 static FP_ExceptionCases ex_cmp_tab[5][5] = {
584 /* N +0 -0 +In -In */
585 { eNR, eNR, eNR, eLT, eGT }, /* Normal */
586 { eNR, eEQ, eEQ, eLT, eGT }, /* +0 */
587 { eNR, eEQ, eEQ, eLT, eGT }, /* -0 */
588 { eGT, eGT, eGT, eEQ, eGT }, /* +Inf */
589 { eLT, eLT, eLT, eLT, eEQ }, /* -Inf */
593 rxfp_cmp (fp_t fa, fp_t fb)
597 FP_ExceptionCases reason;
604 if (check_exceptions (&a, &b, &c, ex_cmp_tab, &reason))
608 /* Special case - incomparable. */
609 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, FLAGBIT_O);
627 da = fp_to_double (&a);
628 db = fp_to_double (&b);
629 tprintf("fcmp: %g cmp %g\n", da, db);
641 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, flags);
645 rxfp_ftoi (fp_t fa, int round_mode)
650 int whole_bits, frac_bits;
653 sign = fa & 0x80000000UL;
674 return sign ? 0x80000000U : 0x7fffffff;
680 return sign ? 0x80000000U : 0x7fffffff;
687 /* Less than 0.49999 */
693 frac_bits = a.mant << (32 + a.exp);
694 whole_bits = a.mant >> (-a.exp);
699 whole_bits = a.mant << a.exp;
704 switch (round_mode & 3)
707 if (frac_bits & 0x80000000UL)
723 rv = sign ? -whole_bits : whole_bits;
729 rxfp_itof (long fa, int round_mode)
733 unsigned int frac_bits;
734 volatile unsigned int whole_bits;
752 while (! (whole_bits & 0x80000000UL))
757 frac_bits = whole_bits & 0xff;
758 whole_bits = whole_bits >> 8;
763 switch (round_mode & 3)
766 if (frac_bits & 0x80)
783 if (whole_bits & 0xff000000UL)
789 rv = fp_implode (&a);