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