Index: gcc/gcc/real.c |
diff --git a/gcc/gcc/real.c b/gcc/gcc/real.c |
index d4a3941e67e59fbef153e2699ccddb34b2437f2a..25e599dfe352e4f2d57a0721c87f6d9702c9cc63 100644 |
--- a/gcc/gcc/real.c |
+++ b/gcc/gcc/real.c |
@@ -57,7 +57,7 @@ |
Both of these requirements are easily satisfied. The largest target |
significand is 113 bits; we store at least 160. The smallest |
- denormal number fits in 17 exponent bits; we store 27. |
+ denormal number fits in 17 exponent bits; we store 26. |
Note that the decimal string conversion routines are sensitive to |
rounding errors. Since the raw arithmetic routines do not themselves |
@@ -1000,10 +1000,10 @@ bool |
real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0, |
const REAL_VALUE_TYPE *op1) |
{ |
- enum tree_code code = icode; |
+ enum tree_code code = (enum tree_code) icode; |
if (op0->decimal || (op1 && op1->decimal)) |
- return decimal_real_arithmetic (r, icode, op0, op1); |
+ return decimal_real_arithmetic (r, code, op0, op1); |
switch (code) |
{ |
@@ -1072,7 +1072,7 @@ bool |
real_compare (int icode, const REAL_VALUE_TYPE *op0, |
const REAL_VALUE_TYPE *op1) |
{ |
- enum tree_code code = icode; |
+ enum tree_code code = (enum tree_code) icode; |
switch (code) |
{ |
@@ -1343,7 +1343,7 @@ real_to_integer (const REAL_VALUE_TYPE *r) |
if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG) |
i = r->sig[SIGSZ-1]; |
- else |
+ else |
{ |
gcc_assert (HOST_BITS_PER_WIDE_INT == 2 * HOST_BITS_PER_LONG); |
i = r->sig[SIGSZ-1]; |
@@ -1394,11 +1394,11 @@ real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh, |
case rvc_normal: |
if (r->decimal) |
- { |
+ { |
decimal_real_to_integer2 (plow, phigh, r); |
return; |
} |
- |
+ |
exp = REAL_EXP (r); |
if (exp <= 0) |
goto underflow; |
@@ -1415,7 +1415,7 @@ real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh, |
high = t.sig[SIGSZ-1]; |
low = t.sig[SIGSZ-2]; |
} |
- else |
+ else |
{ |
gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG); |
high = t.sig[SIGSZ-1]; |
@@ -2117,7 +2117,7 @@ real_from_string2 (const char *s, enum machine_mode mode) |
/* Initialize R from string S and desired MODE. */ |
-void |
+void |
real_from_string3 (REAL_VALUE_TYPE *r, const char *s, enum machine_mode mode) |
{ |
if (DECIMAL_FLOAT_MODE_P (mode)) |
@@ -2126,8 +2126,8 @@ real_from_string3 (REAL_VALUE_TYPE *r, const char *s, enum machine_mode mode) |
real_from_string (r, s); |
if (mode != VOIDmode) |
- real_convert (r, mode, r); |
-} |
+ real_convert (r, mode, r); |
+} |
/* Initialize R from the integer pair HIGH+LOW. */ |
@@ -2342,7 +2342,7 @@ dconst_e_ptr (void) |
mpfr_exp (m, m, GMP_RNDN); |
real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN); |
mpfr_clear (m); |
- |
+ |
} |
return &value; |
} |
@@ -2497,7 +2497,7 @@ real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode) |
fmt = REAL_MODE_FORMAT (mode); |
gcc_assert (fmt); |
memset (r, 0, sizeof (*r)); |
- |
+ |
if (fmt->b == 10) |
decimal_real_maxval (r, sign, mode); |
else |
@@ -4459,41 +4459,41 @@ const struct real_format vax_g_format = |
/* Encode real R into a single precision DFP value in BUF. */ |
static void |
encode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED, |
- long *buf ATTRIBUTE_UNUSED, |
+ long *buf ATTRIBUTE_UNUSED, |
const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED) |
{ |
encode_decimal32 (fmt, buf, r); |
} |
/* Decode a single precision DFP value in BUF into a real R. */ |
-static void |
+static void |
decode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED, |
- REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED, |
+ REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED, |
const long *buf ATTRIBUTE_UNUSED) |
{ |
decode_decimal32 (fmt, r, buf); |
} |
/* Encode real R into a double precision DFP value in BUF. */ |
-static void |
+static void |
encode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED, |
- long *buf ATTRIBUTE_UNUSED, |
+ long *buf ATTRIBUTE_UNUSED, |
const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED) |
{ |
encode_decimal64 (fmt, buf, r); |
} |
/* Decode a double precision DFP value in BUF into a real R. */ |
-static void |
+static void |
decode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED, |
- REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED, |
+ REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED, |
const long *buf ATTRIBUTE_UNUSED) |
{ |
decode_decimal64 (fmt, r, buf); |
} |
/* Encode real R into a quad precision DFP value in BUF. */ |
-static void |
+static void |
encode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED, |
long *buf ATTRIBUTE_UNUSED, |
const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED) |
@@ -4502,7 +4502,7 @@ encode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED, |
} |
/* Decode a quad precision DFP value in BUF into a real R. */ |
-static void |
+static void |
decode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED, |
REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED, |
const long *buf ATTRIBUTE_UNUSED) |
@@ -4515,7 +4515,7 @@ const struct real_format decimal_single_format = |
{ |
encode_decimal_single, |
decode_decimal_single, |
- 10, |
+ 10, |
7, |
7, |
-94, |
@@ -4527,7 +4527,7 @@ const struct real_format decimal_single_format = |
true, |
true, |
true, |
- true, |
+ true, |
true, |
false |
}; |
@@ -4570,11 +4570,172 @@ const struct real_format decimal_quad_format = |
true, |
true, |
true, |
- true, |
- true, |
+ true, |
+ true, |
+ true, |
+ false |
+ }; |
+ |
+/* Encode half-precision floats. This routine is used both for the IEEE |
+ ARM alternative encodings. */ |
+static void |
+encode_ieee_half (const struct real_format *fmt, long *buf, |
+ const REAL_VALUE_TYPE *r) |
+{ |
+ unsigned long image, sig, exp; |
+ unsigned long sign = r->sign; |
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; |
+ |
+ image = sign << 15; |
+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 11)) & 0x3ff; |
+ |
+ switch (r->cl) |
+ { |
+ case rvc_zero: |
+ break; |
+ |
+ case rvc_inf: |
+ if (fmt->has_inf) |
+ image |= 31 << 10; |
+ else |
+ image |= 0x7fff; |
+ break; |
+ |
+ case rvc_nan: |
+ if (fmt->has_nans) |
+ { |
+ if (r->canonical) |
+ sig = (fmt->canonical_nan_lsbs_set ? (1 << 9) - 1 : 0); |
+ if (r->signalling == fmt->qnan_msb_set) |
+ sig &= ~(1 << 9); |
+ else |
+ sig |= 1 << 9; |
+ if (sig == 0) |
+ sig = 1 << 8; |
+ |
+ image |= 31 << 10; |
+ image |= sig; |
+ } |
+ else |
+ image |= 0x3ff; |
+ break; |
+ |
+ case rvc_normal: |
+ /* Recall that IEEE numbers are interpreted as 1.F x 2**exp, |
+ whereas the intermediate representation is 0.F x 2**exp. |
+ Which means we're off by one. */ |
+ if (denormal) |
+ exp = 0; |
+ else |
+ exp = REAL_EXP (r) + 15 - 1; |
+ image |= exp << 10; |
+ image |= sig; |
+ break; |
+ |
+ default: |
+ gcc_unreachable (); |
+ } |
+ |
+ buf[0] = image; |
+} |
+ |
+/* Decode half-precision floats. This routine is used both for the IEEE |
+ ARM alternative encodings. */ |
+static void |
+decode_ieee_half (const struct real_format *fmt, REAL_VALUE_TYPE *r, |
+ const long *buf) |
+{ |
+ unsigned long image = buf[0] & 0xffff; |
+ bool sign = (image >> 15) & 1; |
+ int exp = (image >> 10) & 0x1f; |
+ |
+ memset (r, 0, sizeof (*r)); |
+ image <<= HOST_BITS_PER_LONG - 11; |
+ image &= ~SIG_MSB; |
+ |
+ if (exp == 0) |
+ { |
+ if (image && fmt->has_denorm) |
+ { |
+ r->cl = rvc_normal; |
+ r->sign = sign; |
+ SET_REAL_EXP (r, -14); |
+ r->sig[SIGSZ-1] = image << 1; |
+ normalize (r); |
+ } |
+ else if (fmt->has_signed_zero) |
+ r->sign = sign; |
+ } |
+ else if (exp == 31 && (fmt->has_nans || fmt->has_inf)) |
+ { |
+ if (image) |
+ { |
+ r->cl = rvc_nan; |
+ r->sign = sign; |
+ r->signalling = (((image >> (HOST_BITS_PER_LONG - 2)) & 1) |
+ ^ fmt->qnan_msb_set); |
+ r->sig[SIGSZ-1] = image; |
+ } |
+ else |
+ { |
+ r->cl = rvc_inf; |
+ r->sign = sign; |
+ } |
+ } |
+ else |
+ { |
+ r->cl = rvc_normal; |
+ r->sign = sign; |
+ SET_REAL_EXP (r, exp - 15 + 1); |
+ r->sig[SIGSZ-1] = image | SIG_MSB; |
+ } |
+} |
+ |
+/* Half-precision format, as specified in IEEE 754R. */ |
+const struct real_format ieee_half_format = |
+ { |
+ encode_ieee_half, |
+ decode_ieee_half, |
+ 2, |
+ 11, |
+ 11, |
+ -13, |
+ 16, |
+ 15, |
+ 15, |
+ false, |
+ true, |
+ true, |
+ true, |
+ true, |
+ true, |
true, |
false |
}; |
+ |
+/* ARM's alternative half-precision format, similar to IEEE but with |
+ no reserved exponent value for NaNs and infinities; rather, it just |
+ extends the range of exponents by one. */ |
+const struct real_format arm_half_format = |
+ { |
+ encode_ieee_half, |
+ decode_ieee_half, |
+ 2, |
+ 11, |
+ 11, |
+ -13, |
+ 17, |
+ 15, |
+ 15, |
+ false, |
+ true, |
+ false, |
+ false, |
+ true, |
+ true, |
+ false, |
+ false |
+ }; |
/* A synthetic "format" for internal arithmetic. It's the size of the |
internal significand minus the two bits needed for proper rounding. |
@@ -4837,13 +4998,13 @@ mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r, mp_rnd_t rndmode) |
mpfr_set_inf (m, r->sign == 1 ? -1 : 1); |
return; |
} |
- |
+ |
if (r->cl == rvc_nan) |
{ |
mpfr_set_nan (m); |
return; |
} |
- |
+ |
real_to_hexadecimal (buf, r, sizeof (buf), 0, 1); |
/* mpfr_set_str() parses hexadecimal floats from strings in the same |
format that GCC will output them. Nothing extra is needed. */ |
@@ -4893,7 +5054,7 @@ real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, tree type, mp_rnd_t rndmode) |
sprintf (buf, "0x.%sp%d", rstr, (int) exp); |
mpfr_free_str (rstr); |
- |
+ |
real_from_string (r, buf); |
} |