mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-16 13:01:21 +08:00
real.c (sticky_rshift_significand): Return inexact, don't or it in immediately.
* real.c (sticky_rshift_significand): Return inexact, don't or it in immediately. (sub_significands): Accept incomming carry. (div_significands, rtd_divmod): Update for sub_significands change. (round_for_format): Update for sticky_rshift_significand change. (do_add): Don't involve the inexact bit in addition, do give the inexact bit as the subtraction carry-in. (encode_internal, decode_internal, real_internal_format): New. * real.h (real_internal_format): Declare. From-SVN: r58396
This commit is contained in:
parent
ad03e4c4c7
commit
5e26e5a278
@ -1,3 +1,15 @@
|
||||
2002-10-21 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* real.c (sticky_rshift_significand): Return inexact, don't
|
||||
or it in immediately.
|
||||
(sub_significands): Accept incomming carry.
|
||||
(div_significands, rtd_divmod): Update for sub_significands change.
|
||||
(round_for_format): Update for sticky_rshift_significand change.
|
||||
(do_add): Don't involve the inexact bit in addition, do give the
|
||||
inexact bit as the subtraction carry-in.
|
||||
(encode_internal, decode_internal, real_internal_format): New.
|
||||
* real.h (real_internal_format): Declare.
|
||||
|
||||
2002-10-21 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* libgcc2.c: Fix __udiv_w_sdiv breakage on platforms that
|
||||
|
84
gcc/real.c
84
gcc/real.c
@ -81,7 +81,7 @@ static void get_zero PARAMS ((REAL_VALUE_TYPE *, int));
|
||||
static void get_canonical_qnan PARAMS ((REAL_VALUE_TYPE *, int));
|
||||
static void get_canonical_snan PARAMS ((REAL_VALUE_TYPE *, int));
|
||||
static void get_inf PARAMS ((REAL_VALUE_TYPE *, int));
|
||||
static void sticky_rshift_significand PARAMS ((REAL_VALUE_TYPE *,
|
||||
static bool sticky_rshift_significand PARAMS ((REAL_VALUE_TYPE *,
|
||||
const REAL_VALUE_TYPE *,
|
||||
unsigned int));
|
||||
static void rshift_significand PARAMS ((REAL_VALUE_TYPE *,
|
||||
@ -97,7 +97,7 @@ static bool add_significands PARAMS ((REAL_VALUE_TYPE *r,
|
||||
const REAL_VALUE_TYPE *));
|
||||
static bool sub_significands PARAMS ((REAL_VALUE_TYPE *,
|
||||
const REAL_VALUE_TYPE *,
|
||||
const REAL_VALUE_TYPE *));
|
||||
const REAL_VALUE_TYPE *, int));
|
||||
static void neg_significand PARAMS ((REAL_VALUE_TYPE *,
|
||||
const REAL_VALUE_TYPE *));
|
||||
static int cmp_significands PARAMS ((const REAL_VALUE_TYPE *,
|
||||
@ -182,10 +182,9 @@ get_inf (r, sign)
|
||||
|
||||
|
||||
/* Right-shift the significand of A by N bits; put the result in the
|
||||
significand of R. If any one bits are shifted out, set the least
|
||||
significant bit of R. */
|
||||
significand of R. If any one bits are shifted out, return true. */
|
||||
|
||||
static void
|
||||
static bool
|
||||
sticky_rshift_significand (r, a, n)
|
||||
REAL_VALUE_TYPE *r;
|
||||
const REAL_VALUE_TYPE *a;
|
||||
@ -220,7 +219,7 @@ sticky_rshift_significand (r, a, n)
|
||||
r->sig[i] = 0;
|
||||
}
|
||||
|
||||
r->sig[0] |= (sticky != 0);
|
||||
return sticky != 0;
|
||||
}
|
||||
|
||||
/* Right-shift the significand of A by N bits; put the result in the
|
||||
@ -327,15 +326,16 @@ add_significands (r, a, b)
|
||||
return carry;
|
||||
}
|
||||
|
||||
/* Subtract the significands of A and B, placing the result in R.
|
||||
Return true if there was carry out of the most significant word. */
|
||||
/* Subtract the significands of A and B, placing the result in R. CARRY is
|
||||
true if there's a borrow incoming to the least significant word.
|
||||
Return true if there was borrow out of the most significant word. */
|
||||
|
||||
static inline bool
|
||||
sub_significands (r, a, b)
|
||||
sub_significands (r, a, b, carry)
|
||||
REAL_VALUE_TYPE *r;
|
||||
const REAL_VALUE_TYPE *a, *b;
|
||||
int carry;
|
||||
{
|
||||
bool carry = false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIGSZ; ++i)
|
||||
@ -500,7 +500,7 @@ div_significands (r, a, b)
|
||||
start:
|
||||
if (msb || cmp_significands (&u, b) >= 0)
|
||||
{
|
||||
sub_significands (&u, &u, b);
|
||||
sub_significands (&u, &u, b, 0);
|
||||
set_significand_bit (r, bit);
|
||||
}
|
||||
}
|
||||
@ -570,6 +570,7 @@ do_add (r, a, b, subtract_p)
|
||||
{
|
||||
int dexp, sign, exp;
|
||||
REAL_VALUE_TYPE t;
|
||||
bool inexact = false;
|
||||
|
||||
/* Determine if we need to add or subtract. */
|
||||
sign = a->sign;
|
||||
@ -648,13 +649,13 @@ do_add (r, a, b, subtract_p)
|
||||
return;
|
||||
}
|
||||
|
||||
sticky_rshift_significand (&t, b, dexp);
|
||||
inexact |= sticky_rshift_significand (&t, b, dexp);
|
||||
b = &t;
|
||||
}
|
||||
|
||||
if (subtract_p)
|
||||
{
|
||||
if (sub_significands (r, a, b))
|
||||
if (sub_significands (r, a, b, inexact))
|
||||
{
|
||||
/* We got a borrow out of the subtraction. That means that
|
||||
A and B had the same exponent, and B had the larger
|
||||
@ -671,7 +672,7 @@ do_add (r, a, b, subtract_p)
|
||||
/* We got carry out of the addition. This means we need to
|
||||
shift the significand back down one bit and increase the
|
||||
exponent. */
|
||||
sticky_rshift_significand (r, r, 1);
|
||||
inexact |= sticky_rshift_significand (r, r, 1);
|
||||
r->sig[SIGSZ-1] |= SIG_MSB;
|
||||
if (++exp > MAX_EXP)
|
||||
{
|
||||
@ -692,6 +693,8 @@ do_add (r, a, b, subtract_p)
|
||||
is positive. */
|
||||
if (r->class == rvc_zero)
|
||||
r->sign = 0;
|
||||
else
|
||||
r->sig[0] |= inexact;
|
||||
}
|
||||
|
||||
/* Return R = A * B. */
|
||||
@ -1430,7 +1433,7 @@ rtd_divmod (num, den)
|
||||
start:
|
||||
if (msb || cmp_significands (num, den) >= 0)
|
||||
{
|
||||
sub_significands (num, num, den);
|
||||
sub_significands (num, num, den, 0);
|
||||
q |= 1;
|
||||
}
|
||||
}
|
||||
@ -2329,7 +2332,7 @@ round_for_format (fmt, r)
|
||||
if (shift)
|
||||
{
|
||||
shift = fmt->log2_b - shift;
|
||||
sticky_rshift_significand (r, r, shift);
|
||||
r->sig[0] |= sticky_rshift_significand (r, r, shift);
|
||||
r->exp += shift;
|
||||
}
|
||||
}
|
||||
@ -2355,7 +2358,7 @@ round_for_format (fmt, r)
|
||||
goto underflow;
|
||||
|
||||
/* De-normalize the significand. */
|
||||
sticky_rshift_significand (r, r, diff);
|
||||
r->sig[0] |= sticky_rshift_significand (r, r, diff);
|
||||
r->exp += diff;
|
||||
}
|
||||
}
|
||||
@ -2395,7 +2398,7 @@ round_for_format (fmt, r)
|
||||
if (shift)
|
||||
{
|
||||
shift = fmt->log2_b - shift;
|
||||
sticky_rshift_significand (r, r, shift);
|
||||
rshift_significand (r, r, shift);
|
||||
r->exp += shift;
|
||||
if (r->exp > emax2)
|
||||
goto overflow;
|
||||
@ -4308,6 +4311,51 @@ const struct real_format c4x_extended_format =
|
||||
false,
|
||||
false
|
||||
};
|
||||
|
||||
|
||||
/* A synthetic "format" for internal arithmetic. It's the size of the
|
||||
internal significand minus the two bits needed for proper rounding.
|
||||
The encode and decode routines exist only to satisfy our paranoia
|
||||
harness. */
|
||||
|
||||
static void encode_internal PARAMS ((const struct real_format *fmt,
|
||||
long *, const REAL_VALUE_TYPE *));
|
||||
static void decode_internal PARAMS ((const struct real_format *,
|
||||
REAL_VALUE_TYPE *, const long *));
|
||||
|
||||
static void
|
||||
encode_internal (fmt, buf, r)
|
||||
const struct real_format *fmt ATTRIBUTE_UNUSED;
|
||||
long *buf;
|
||||
const REAL_VALUE_TYPE *r;
|
||||
{
|
||||
memcpy (buf, r, sizeof (*r));
|
||||
}
|
||||
|
||||
static void
|
||||
decode_internal (fmt, r, buf)
|
||||
const struct real_format *fmt ATTRIBUTE_UNUSED;
|
||||
REAL_VALUE_TYPE *r;
|
||||
const long *buf;
|
||||
{
|
||||
memcpy (r, buf, sizeof (*r));
|
||||
}
|
||||
|
||||
const struct real_format real_internal_format =
|
||||
{
|
||||
encode_internal,
|
||||
decode_internal,
|
||||
2,
|
||||
1,
|
||||
SIGNIFICAND_BITS - 2,
|
||||
-MAX_EXP,
|
||||
MAX_EXP,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
};
|
||||
|
||||
/* Set up default mode to format mapping for IEEE. Everyone else has
|
||||
to set these values in OVERRIDE_OPTIONS. */
|
||||
|
@ -231,6 +231,7 @@ extern const struct real_format i370_single_format;
|
||||
extern const struct real_format i370_double_format;
|
||||
extern const struct real_format c4x_single_format;
|
||||
extern const struct real_format c4x_extended_format;
|
||||
extern const struct real_format real_internal_format;
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
|
Loading…
x
Reference in New Issue
Block a user