blob: e39400d27e9e075ffa159bdb79c86423dd170962 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
require_extension('D');
require_extension(EXT_ZFA);
require_fp;
uint64_t a = FRS1_D.v;
uint32_t sign = signF64UI(a);
uint32_t exp = expF64UI(a);
uint64_t frac = fracF64UI(a);
bool inexact = false;
bool invalid = false;
if (exp == 0) {
inexact = (frac != 0);
frac = 0;
} else if (exp == 0x7ff) {
/* inf or NaN */
invalid = true;
frac = 0;
} else {
int true_exp = exp - 1023;
int shift = true_exp - 52;
/* Restore implicit bit. */
frac |= 1ull << 52;
/* Shift the fraction into place. */
if (shift >= 64) {
/* The fraction is shifted out entirely. */
frac = 0;
} else if ((shift >= 0) && (shift < 64)) {
/* The number is so large we must shift the fraction left. */
frac <<= shift;
} else if ((shift > -64) && (shift < 0)) {
/* Normal case -- shift right and notice if bits shift out. */
inexact = (frac << (64 + shift)) != 0;
frac >>= -shift;
} else {
/* The fraction is shifted out entirely. */
frac = 0;
inexact = true;
}
/* Handle overflows */
if (true_exp > 31 || frac > (sign ? 0x80000000ull : 0x7fffffff)) {
/* Overflow, for which this operation raises invalid. */
invalid = true;
inexact = false; /* invalid takes precedence */
}
/* Honor the sign. */
if (sign) {
frac = -frac;
}
}
WRITE_RD(sext32(frac));
STATE.fflags->write(STATE.fflags->read() |
(inexact ? softfloat_flag_inexact : 0) |
(invalid ? softfloat_flag_invalid : 0));
|