1 /* fpu.c --- FPU emulator for stand-alone RX simulator.
3 Copyright (C) 2008, 2009 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/>. */
27 /* FPU encodings are as follows:
30 1 12345678 12345678901234567890123
32 0 00000000 00000000000000000000000 +0
33 1 00000000 00000000000000000000000 -0
35 X 00000000 00000000000000000000001 Denormals
36 X 00000000 11111111111111111111111
38 X 00000001 XXXXXXXXXXXXXXXXXXXXXXX Normals
39 X 11111110 XXXXXXXXXXXXXXXXXXXXXXX
41 0 11111111 00000000000000000000000 +Inf
42 1 11111111 00000000000000000000000 -Inf
44 X 11111111 0XXXXXXXXXXXXXXXXXXXXXX SNaN (X != 0)
45 X 11111111 1XXXXXXXXXXXXXXXXXXXXXX QNaN (X != 0)
50 #define tprintf if (trace) printf
52 /* Some magic numbers. */
53 #define PLUS_MAX 0x7f7fffffUL
54 #define MINUS_MAX 0xff7fffffUL
55 #define PLUS_INF 0x7f800000UL
56 #define MINUS_INF 0xff800000UL
57 #define PLUS_ZERO 0x00000000UL
58 #define MINUS_ZERO 0x80000000UL
60 #define FP_RAISE(e) fp_raise(FPSWBITS_C##e)
65 if (mask
!= FPSWBITS_CE
)
67 if (regs
.r_fpsw
& (mask
<< FPSW_CESH
))
68 regs
.r_fpsw
|= (mask
<< FPSW_CFSH
);
69 if (regs
.r_fpsw
& FPSWBITS_FMASK
)
70 regs
.r_fpsw
|= FPSWBITS_FSUM
;
72 regs
.r_fpsw
&= ~FPSWBITS_FSUM
;
76 /* We classify all numbers as one of these. They correspond to the
77 rows/colums in the exception tables. */
90 static const char *fpt_names
[] = {
91 "Normal", "+0", "-0", "+Inf", "-Inf", "Denormal", "QNaN", "SNaN"
99 #define MANT_BIAS 0x00080000UL
103 unsigned int mant
; /* 24 bits */
110 fp_explode (fp_t f
, FP_Parts
*p
)
114 exp
= ((f
& 0x7f800000UL
) >> 23);
115 mant
= f
& 0x007fffffUL
;
116 sign
= f
& 0x80000000UL
;
117 /*printf("explode: %08x %x %2x %6x\n", f, sign, exp, mant);*/
119 p
->sign
= sign
? -1 : 1;
120 p
->exp
= exp
- EXP_BIAS
;
122 p
->mant
= mant
| 0x00800000UL
;
124 if (p
->exp
== EXP_ZERO
)
126 if (regs
.r_fpsw
& FPSWBITS_DN
)
129 p
->type
= FP_DENORMAL
;
133 p
->type
= sign
? FP_NZERO
: FP_PZERO
;
136 else if (p
->exp
== EXP_INF
)
139 p
->type
= sign
? FP_NINFINITY
: FP_PINFINITY
;
140 else if (mant
& 0x00400000UL
)
150 fp_implode (FP_Parts
*p
)
154 exp
= p
->exp
+ EXP_BIAS
;
156 /*printf("implode: exp %d mant 0x%x\n", exp, mant);*/
157 if (p
->type
== FP_NORMAL
)
161 && mant
< 0x00800000UL
)
166 while (mant
> 0x00ffffffUL
)
186 mant
&= 0x007fffffUL
;
190 mant
|= 0x80000000UL
;
196 unsigned long long ll
;
200 static int checked_format
= 0;
202 /* We assume a double format like this:
207 fp_to_double (FP_Parts
*p
)
214 if (u
.ll
!= 0x3ff8000000000000ULL
)
217 if (u
.ll
!= 0xc06c200000000000ULL
)
220 if (u
.ll
!= 0x4024333333333333ULL
)
227 u
.ll
|= (1ULL << 63);
228 /* Make sure a zero encoding stays a zero. */
229 if (p
->exp
!= -EXP_BIAS
)
230 u
.ll
|= ((unsigned long long)p
->exp
+ 1023ULL) << 52;
231 u
.ll
|= (unsigned long long) (p
->mant
& 0x007fffffUL
) << (52 - 23);
236 double_to_fp (double d
, FP_Parts
*p
)
244 sign
= (u
.ll
& 0x8000000000000000ULL
) ? 1 : 0;
250 /* A generated denormal should show up as an underflow, not
253 fp_explode (MINUS_ZERO
, p
);
255 fp_explode (PLUS_ZERO
, p
);
260 if ((exp
+ EXP_BIAS
) > 254)
263 switch (regs
.r_fpsw
& FPSWBITS_RM
)
267 fp_explode (MINUS_INF
, p
);
269 fp_explode (PLUS_INF
, p
);
273 fp_explode (MINUS_MAX
, p
);
275 fp_explode (PLUS_MAX
, p
);
279 fp_explode (MINUS_MAX
, p
);
281 fp_explode (PLUS_INF
, p
);
285 fp_explode (MINUS_INF
, p
);
287 fp_explode (PLUS_MAX
, p
);
292 if ((exp
+ EXP_BIAS
) < 1)
295 fp_explode (MINUS_ZERO
, p
);
297 fp_explode (PLUS_ZERO
, p
);
301 p
->sign
= sign
? -1 : 1;
303 p
->mant
= u
.ll
>> (52-23) & 0x007fffffUL
;
304 p
->mant
|= 0x00800000UL
;
307 if (u
.ll
& 0x1fffffffULL
)
309 switch (regs
.r_fpsw
& FPSWBITS_RM
)
312 if (u
.ll
& 0x10000000ULL
)
332 eNR
, /* Use the normal result. */
333 ePZ
, eNZ
, /* +- zero */
334 eSZ
, /* signed zero - XOR signs of ops together. */
335 eRZ
, /* +- zero depending on rounding mode. */
336 ePI
, eNI
, /* +- Infinity */
337 eSI
, /* signed infinity - XOR signs of ops together. */
338 eQN
, eSN
, /* Quiet/Signalling NANs */
340 eUn
, /* Unimplemented. */
341 eDZ
, /* Divide-by-zero. */
343 eGT
, /* greater than */
348 static const char *ex_names
[] = {
349 "NR", "PZ", "NZ", "SZ", "RZ", "PI", "NI", "SI", "QN", "SN", "IN", "Un", "DZ", "LT", "GT", "EQ"
353 /* This checks for all exceptional cases (not all FP exceptions) and
354 returns TRUE if it is providing the result in *c. If it returns
355 FALSE, the caller should do the "normal" operation. */
357 check_exceptions (FP_Parts
*a
, FP_Parts
*b
, fp_t
*c
,
358 FP_ExceptionCases ex_tab
[5][5],
359 FP_ExceptionCases
*case_ret
)
361 FP_ExceptionCases fpec
;
363 if (a
->type
== FP_SNAN
364 || b
->type
== FP_SNAN
)
366 else if (a
->type
== FP_QNAN
367 || b
->type
== FP_QNAN
)
369 else if (a
->type
== FP_DENORMAL
370 || b
->type
== FP_DENORMAL
)
373 fpec
= ex_tab
[(int)(a
->type
)][(int)(b
->type
)];
375 /*printf("%s %s -> %s\n", fpt_names[(int)(a->type)], fpt_names[(int)(b->type)], ex_names[(int)(fpec)]);*/
382 case eNR
: /* Use the normal result. */
385 case ePZ
: /* + zero */
389 case eNZ
: /* - zero */
393 case eSZ
: /* signed zero */
394 *c
= (a
->sign
== b
->sign
) ? PLUS_ZERO
: MINUS_ZERO
;
397 case eRZ
: /* +- zero depending on rounding mode. */
398 if ((regs
.r_fpsw
& FPSWBITS_RM
) == FPRM_NINF
)
404 case ePI
: /* + Infinity */
408 case eNI
: /* - Infinity */
412 case eSI
: /* sign Infinity */
413 *c
= (a
->sign
== b
->sign
) ? PLUS_INF
: MINUS_INF
;
416 case eQN
: /* Quiet NANs */
417 if (a
->type
== FP_QNAN
)
423 case eSN
: /* Signalling NANs */
424 if (a
->type
== FP_SNAN
)
431 case eIn
: /* Invalid. */
433 if (a
->type
== FP_SNAN
)
434 *c
= a
->orig_value
| 0x00400000;
435 else if (a
->type
== FP_SNAN
)
436 *c
= b
->orig_value
| 0x00400000;
441 case eUn
: /* Unimplemented. */
445 case eDZ
: /* Division-by-zero. */
446 *c
= (a
->sign
== b
->sign
) ? PLUS_INF
: MINUS_INF
;
455 #define CHECK_EXCEPTIONS(FPPa, FPPb, fpc, ex_tab) \
456 if (check_exceptions (&FPPa, &FPPb, &fpc, ex_tab, 0)) \
459 /* For each operation, we have two tables of how nonnormal cases are
460 handled. The DN=0 case is first, followed by the DN=1 case, with
461 each table using the following layout: */
463 static FP_ExceptionCases ex_add_tab
[5][5] = {
464 /* N +0 -0 +In -In */
465 { eNR
, eNR
, eNR
, ePI
, eNI
}, /* Normal */
466 { eNR
, ePZ
, eRZ
, ePI
, eNI
}, /* +0 */
467 { eNR
, eRZ
, eNZ
, ePI
, eNI
}, /* -0 */
468 { ePI
, ePI
, ePI
, ePI
, eIn
}, /* +Inf */
469 { eNI
, eNI
, eNI
, eIn
, eNI
}, /* -Inf */
473 rxfp_add (fp_t fa
, fp_t fb
)
481 CHECK_EXCEPTIONS (a
, b
, rv
, ex_add_tab
);
483 da
= fp_to_double (&a
);
484 db
= fp_to_double (&b
);
485 tprintf("%g + %g = %g\n", da
, db
, da
+db
);
487 double_to_fp (da
+db
, &c
);
488 rv
= fp_implode (&c
);
492 static FP_ExceptionCases ex_sub_tab
[5][5] = {
493 /* N +0 -0 +In -In */
494 { eNR
, eNR
, eNR
, eNI
, ePI
}, /* Normal */
495 { eNR
, eRZ
, ePZ
, eNI
, ePI
}, /* +0 */
496 { eNR
, eNZ
, eRZ
, eNI
, ePI
}, /* -0 */
497 { ePI
, ePI
, ePI
, eIn
, ePI
}, /* +Inf */
498 { eNI
, eNI
, eNI
, eNI
, eIn
}, /* -Inf */
502 rxfp_sub (fp_t fa
, fp_t fb
)
510 CHECK_EXCEPTIONS (a
, b
, rv
, ex_sub_tab
);
512 da
= fp_to_double (&a
);
513 db
= fp_to_double (&b
);
514 tprintf("%g - %g = %g\n", da
, db
, da
-db
);
516 double_to_fp (da
-db
, &c
);
517 rv
= fp_implode (&c
);
522 static FP_ExceptionCases ex_mul_tab
[5][5] = {
523 /* N +0 -0 +In -In */
524 { eNR
, eNR
, eNR
, eSI
, eSI
}, /* Normal */
525 { eNR
, ePZ
, eNZ
, eIn
, eIn
}, /* +0 */
526 { eNR
, eNZ
, ePZ
, eIn
, eIn
}, /* -0 */
527 { eSI
, eIn
, eIn
, ePI
, eNI
}, /* +Inf */
528 { eSI
, eIn
, eIn
, eNI
, ePI
}, /* -Inf */
532 rxfp_mul (fp_t fa
, fp_t fb
)
540 CHECK_EXCEPTIONS (a
, b
, rv
, ex_mul_tab
);
542 da
= fp_to_double (&a
);
543 db
= fp_to_double (&b
);
544 tprintf("%g x %g = %g\n", da
, db
, da
*db
);
546 double_to_fp (da
*db
, &c
);
547 rv
= fp_implode (&c
);
552 static FP_ExceptionCases ex_div_tab
[5][5] = {
553 /* N +0 -0 +In -In */
554 { eNR
, eDZ
, eDZ
, eSZ
, eSZ
}, /* Normal */
555 { eSZ
, eIn
, eIn
, ePZ
, eNZ
}, /* +0 */
556 { eSZ
, eIn
, eIn
, eNZ
, ePZ
}, /* -0 */
557 { eSI
, ePI
, eNI
, eIn
, eIn
}, /* +Inf */
558 { eSI
, eNI
, ePI
, eIn
, eIn
}, /* -Inf */
562 rxfp_div (fp_t fa
, fp_t fb
)
570 CHECK_EXCEPTIONS (a
, b
, rv
, ex_div_tab
);
572 da
= fp_to_double (&a
);
573 db
= fp_to_double (&b
);
574 tprintf("%g / %g = %g\n", da
, db
, da
/db
);
576 double_to_fp (da
/db
, &c
);
577 rv
= fp_implode (&c
);
582 static FP_ExceptionCases ex_cmp_tab
[5][5] = {
583 /* N +0 -0 +In -In */
584 { eNR
, eNR
, eNR
, eLT
, eGT
}, /* Normal */
585 { eNR
, eEQ
, eEQ
, eLT
, eGT
}, /* +0 */
586 { eNR
, eEQ
, eEQ
, eLT
, eGT
}, /* -0 */
587 { eGT
, eGT
, eGT
, eEQ
, eGT
}, /* +Inf */
588 { eLT
, eLT
, eLT
, eLT
, eEQ
}, /* -Inf */
592 rxfp_cmp (fp_t fa
, fp_t fb
)
596 FP_ExceptionCases reason
;
603 if (check_exceptions (&a
, &b
, &c
, ex_cmp_tab
, &reason
))
607 /* Special case - incomparable. */
608 set_flags (FLAGBIT_Z
| FLAGBIT_S
| FLAGBIT_O
, FLAGBIT_O
);
626 da
= fp_to_double (&a
);
627 db
= fp_to_double (&b
);
628 tprintf("fcmp: %g cmp %g\n", da
, db
);
640 set_flags (FLAGBIT_Z
| FLAGBIT_S
| FLAGBIT_O
, flags
);
644 rxfp_ftoi (fp_t fa
, int round_mode
)
649 int whole_bits
, frac_bits
;
652 sign
= fa
& 0x80000000UL
;
673 return sign
? 0x80000000U
: 0x7fffffff;
679 return sign
? 0x80000000U
: 0x7fffffff;
686 /* Less than 0.49999 */
692 frac_bits
= a
.mant
<< (32 + a
.exp
);
693 whole_bits
= a
.mant
>> (-a
.exp
);
698 whole_bits
= a
.mant
<< a
.exp
;
703 switch (round_mode
& 3)
706 if (frac_bits
& 0x80000000UL
)
722 rv
= sign
? -whole_bits
: whole_bits
;
728 rxfp_itof (long fa
, int round_mode
)
732 unsigned int frac_bits
;
733 volatile unsigned int whole_bits
;
751 while (! (whole_bits
& 0x80000000UL
))
756 frac_bits
= whole_bits
& 0xff;
757 whole_bits
= whole_bits
>> 8;
762 switch (round_mode
& 3)
765 if (frac_bits
& 0x80)
782 if (whole_bits
& 0xff000000UL
)
788 rv
= fp_implode (&a
);