1 /* fpu.c --- FPU emulator for stand-alone RX simulator.
3 Copyright (C) 2008-2017 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
);