/* real.c - software floating point emulation.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2002, 2003 Free Software Foundation, Inc.
+ 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Stephen L. Moshier (moshier@world.std.com).
- Re-written by Richard Henderson <rth@redhat.com>
+ Re-written by Richard Henderson <rth@redhat.com>
This file is part of GCC.
#include "tm_p.h"
/* The floating point model used internally is not exactly IEEE 754
- compliant, and close to the description in the ISO C standard,
+ compliant, and close to the description in the ISO C99 standard,
section 5.2.4.2.2 Characteristics of floating types.
Specifically
significand is fractional. Normalized significands are in the
range [0.5, 1.0).
- A requirement of the model is that P be larger than than the
- largest supported target floating-point type by at least 2 bits.
- This gives us proper rounding when we truncate to the target type.
- In addition, E must be large enough to hold the smallest supported
- denormal number in a normalized form.
+ A requirement of the model is that P be larger than the largest
+ supported target floating-point type by at least 2 bits. This gives
+ us proper rounding when we truncate to the target type. In addition,
+ E must be large enough to hold the smallest supported denormal number
+ in a normalized form.
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 29.
+ denormal number fits in 17 exponent bits; we store 27.
- Note that the decimal string conversion routines are sensitive to
- rounding error. Since the raw arithmetic routines do not themselves
+ Note that the decimal string conversion routines are sensitive to
+ rounding errors. Since the raw arithmetic routines do not themselves
have guard digits or rounding, the computation of 10**exp can
accumulate more than a few digits of error. The previous incarnation
- of real.c successfully used a 144 bit fraction; given the current
+ of real.c successfully used a 144-bit fraction; given the current
layout of REAL_VALUE_TYPE we're forced to expand to at least 160 bits.
Target floating point models that use base 16 instead of base 2
#error "Some constant folding done by hand to avoid shift count warnings"
#endif
-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 bool sticky_rshift_significand PARAMS ((REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *,
- unsigned int));
-static void rshift_significand PARAMS ((REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *,
- unsigned int));
-static void lshift_significand PARAMS ((REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *,
- unsigned int));
-static void lshift_significand_1 PARAMS ((REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *));
-static bool add_significands PARAMS ((REAL_VALUE_TYPE *r,
- const REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *));
-static bool sub_significands PARAMS ((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 *,
- const REAL_VALUE_TYPE *));
-static int cmp_significand_0 PARAMS ((const REAL_VALUE_TYPE *));
-static void set_significand_bit PARAMS ((REAL_VALUE_TYPE *, unsigned int));
-static void clear_significand_bit PARAMS ((REAL_VALUE_TYPE *, unsigned int));
-static bool test_significand_bit PARAMS ((REAL_VALUE_TYPE *, unsigned int));
-static void clear_significand_below PARAMS ((REAL_VALUE_TYPE *,
- unsigned int));
-static bool div_significands PARAMS ((REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *));
-static void normalize PARAMS ((REAL_VALUE_TYPE *));
-
-static bool do_add PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *, int));
-static bool do_multiply PARAMS ((REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *));
-static bool do_divide PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *));
-static int do_compare PARAMS ((const REAL_VALUE_TYPE *,
- const REAL_VALUE_TYPE *, int));
-static void do_fix_trunc PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *));
-
-static unsigned long rtd_divmod PARAMS ((REAL_VALUE_TYPE *,
- REAL_VALUE_TYPE *));
-
-static const REAL_VALUE_TYPE * ten_to_ptwo PARAMS ((int));
-static const REAL_VALUE_TYPE * ten_to_mptwo PARAMS ((int));
-static const REAL_VALUE_TYPE * real_digit PARAMS ((int));
-static void times_pten PARAMS ((REAL_VALUE_TYPE *, int));
-
-static void round_for_format PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *));
+static void get_zero (REAL_VALUE_TYPE *, int);
+static void get_canonical_qnan (REAL_VALUE_TYPE *, int);
+static void get_canonical_snan (REAL_VALUE_TYPE *, int);
+static void get_inf (REAL_VALUE_TYPE *, int);
+static bool sticky_rshift_significand (REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *, unsigned int);
+static void rshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+ unsigned int);
+static void lshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+ unsigned int);
+static void lshift_significand_1 (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
+static bool add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *);
+static bool sub_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *, int);
+static void neg_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
+static int cmp_significands (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
+static int cmp_significand_0 (const REAL_VALUE_TYPE *);
+static void set_significand_bit (REAL_VALUE_TYPE *, unsigned int);
+static void clear_significand_bit (REAL_VALUE_TYPE *, unsigned int);
+static bool test_significand_bit (REAL_VALUE_TYPE *, unsigned int);
+static void clear_significand_below (REAL_VALUE_TYPE *, unsigned int);
+static bool div_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *);
+static void normalize (REAL_VALUE_TYPE *);
+
+static bool do_add (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *, int);
+static bool do_multiply (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *);
+static bool do_divide (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *);
+static int do_compare (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
+static void do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
+
+static unsigned long rtd_divmod (REAL_VALUE_TYPE *, REAL_VALUE_TYPE *);
+
+static const REAL_VALUE_TYPE * ten_to_ptwo (int);
+static const REAL_VALUE_TYPE * ten_to_mptwo (int);
+static const REAL_VALUE_TYPE * real_digit (int);
+static void times_pten (REAL_VALUE_TYPE *, int);
+
+static void round_for_format (const struct real_format *, REAL_VALUE_TYPE *);
\f
/* Initialize R with a positive zero. */
static inline void
-get_zero (r, sign)
- REAL_VALUE_TYPE *r;
- int sign;
+get_zero (REAL_VALUE_TYPE *r, int sign)
{
memset (r, 0, sizeof (*r));
r->sign = sign;
/* Initialize R with the canonical quiet NaN. */
static inline void
-get_canonical_qnan (r, sign)
- REAL_VALUE_TYPE *r;
- int sign;
+get_canonical_qnan (REAL_VALUE_TYPE *r, int sign)
{
memset (r, 0, sizeof (*r));
r->class = rvc_nan;
}
static inline void
-get_canonical_snan (r, sign)
- REAL_VALUE_TYPE *r;
- int sign;
+get_canonical_snan (REAL_VALUE_TYPE *r, int sign)
{
memset (r, 0, sizeof (*r));
r->class = rvc_nan;
}
static inline void
-get_inf (r, sign)
- REAL_VALUE_TYPE *r;
- int sign;
+get_inf (REAL_VALUE_TYPE *r, int sign)
{
memset (r, 0, sizeof (*r));
r->class = rvc_inf;
significand of R. If any one bits are shifted out, return true. */
static bool
-sticky_rshift_significand (r, a, n)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a;
- unsigned int n;
+sticky_rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
+ unsigned int n)
{
unsigned long sticky = 0;
unsigned int i, ofs = 0;
significand of R. */
static void
-rshift_significand (r, a, n)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a;
- unsigned int n;
+rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
+ unsigned int n)
{
unsigned int i, ofs = n / HOST_BITS_PER_LONG;
significand of R. */
static void
-lshift_significand (r, a, n)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a;
- unsigned int n;
+lshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
+ unsigned int n)
{
unsigned int i, ofs = n / HOST_BITS_PER_LONG;
/* Likewise, but N is specialized to 1. */
static inline void
-lshift_significand_1 (r, a)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a;
+lshift_significand_1 (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
{
unsigned int i;
true if there was carry out of the most significant word. */
static inline bool
-add_significands (r, a, b)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a, *b;
+add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
+ const REAL_VALUE_TYPE *b)
{
bool carry = false;
int i;
Return true if there was borrow out of the most significant word. */
static inline bool
-sub_significands (r, a, b, carry)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a, *b;
- int carry;
+sub_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
+ const REAL_VALUE_TYPE *b, int carry)
{
int i;
}
return carry;
-}
+}
/* Negate the significand A, placing the result in R. */
static inline void
-neg_significand (r, a)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a;
+neg_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
{
bool carry = true;
int i;
r->sig[i] = ri;
}
-}
+}
/* Compare significands. Return tri-state vs zero. */
-static inline int
-cmp_significands (a, b)
- const REAL_VALUE_TYPE *a, *b;
+static inline int
+cmp_significands (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b)
{
int i;
/* Return true if A is nonzero. */
-static inline int
-cmp_significand_0 (a)
- const REAL_VALUE_TYPE *a;
+static inline int
+cmp_significand_0 (const REAL_VALUE_TYPE *a)
{
int i;
/* Set bit N of the significand of R. */
static inline void
-set_significand_bit (r, n)
- REAL_VALUE_TYPE *r;
- unsigned int n;
+set_significand_bit (REAL_VALUE_TYPE *r, unsigned int n)
{
r->sig[n / HOST_BITS_PER_LONG]
|= (unsigned long)1 << (n % HOST_BITS_PER_LONG);
/* Clear bit N of the significand of R. */
static inline void
-clear_significand_bit (r, n)
- REAL_VALUE_TYPE *r;
- unsigned int n;
+clear_significand_bit (REAL_VALUE_TYPE *r, unsigned int n)
{
r->sig[n / HOST_BITS_PER_LONG]
&= ~((unsigned long)1 << (n % HOST_BITS_PER_LONG));
/* Test bit N of the significand of R. */
static inline bool
-test_significand_bit (r, n)
- REAL_VALUE_TYPE *r;
- unsigned int n;
+test_significand_bit (REAL_VALUE_TYPE *r, unsigned int n)
{
/* ??? Compiler bug here if we return this expression directly.
The conversion to bool strips the "&1" and we wind up testing
/* Clear bits 0..N-1 of the significand of R. */
static void
-clear_significand_below (r, n)
- REAL_VALUE_TYPE *r;
- unsigned int n;
+clear_significand_below (REAL_VALUE_TYPE *r, unsigned int n)
{
int i, w = n / HOST_BITS_PER_LONG;
true if the division was inexact. */
static inline bool
-div_significands (r, a, b)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a, *b;
+div_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
+ const REAL_VALUE_TYPE *b)
{
REAL_VALUE_TYPE u;
int i, bit = SIGNIFICAND_BITS - 1;
exponent is large enough to handle target denormals normalized.) */
static void
-normalize (r)
- REAL_VALUE_TYPE *r;
+normalize (REAL_VALUE_TYPE *r)
{
int shift = 0, exp;
int i, j;
if (i < 0)
{
r->class = rvc_zero;
- r->exp = 0;
+ SET_REAL_EXP (r, 0);
return;
}
if (shift > 0)
{
- exp = r->exp - shift;
+ exp = REAL_EXP (r) - shift;
if (exp > MAX_EXP)
get_inf (r, r->sign);
else if (exp < -MAX_EXP)
get_zero (r, r->sign);
else
{
- r->exp = exp;
+ SET_REAL_EXP (r, exp);
lshift_significand (r, r, shift);
}
}
result may be inexact due to a loss of precision. */
static bool
-do_add (r, a, b, subtract_p)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a, *b;
- int subtract_p;
+do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
+ const REAL_VALUE_TYPE *b, int subtract_p)
{
int dexp, sign, exp;
REAL_VALUE_TYPE t;
}
/* Swap the arguments such that A has the larger exponent. */
- dexp = a->exp - b->exp;
+ dexp = REAL_EXP (a) - REAL_EXP (b);
if (dexp < 0)
{
const REAL_VALUE_TYPE *t;
dexp = -dexp;
sign ^= subtract_p;
}
- exp = a->exp;
+ exp = REAL_EXP (a);
/* If the exponents are not identical, we need to shift the
significand of B down. */
r->class = rvc_normal;
r->sign = sign;
- r->exp = exp;
+ SET_REAL_EXP (r, exp);
/* Re-normalize the result. */
normalize (r);
/* Calculate R = A * B. Return true if the result may be inexact. */
static bool
-do_multiply (r, a, b)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a, *b;
+do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
+ const REAL_VALUE_TYPE *b)
{
REAL_VALUE_TYPE u, t, *rr;
unsigned int i, j, k;
for (j = 0; j < 2; ++j)
{
- int exp = (a->exp - (2*SIGSZ-1-i)*(HOST_BITS_PER_LONG/2)
- + (b->exp - (1-j)*(HOST_BITS_PER_LONG/2)));
+ int exp = (REAL_EXP (a) - (2*SIGSZ-1-i)*(HOST_BITS_PER_LONG/2)
+ + (REAL_EXP (b) - (1-j)*(HOST_BITS_PER_LONG/2)));
if (exp > MAX_EXP)
{
continue;
}
+ memset (&u, 0, sizeof (u));
u.class = rvc_normal;
- u.sign = 0;
- u.exp = exp;
+ SET_REAL_EXP (&u, exp);
for (k = j; k < SIGSZ * 2; k += 2)
{
/* Calculate R = A / B. Return true if the result may be inexact. */
static bool
-do_divide (r, a, b)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a, *b;
+do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
+ const REAL_VALUE_TYPE *b)
{
int exp, sign = a->sign ^ b->sign;
REAL_VALUE_TYPE t, *rr;
else
rr = r;
+ /* Make sure all fields in the result are initialized. */
+ get_zero (rr, 0);
rr->class = rvc_normal;
rr->sign = sign;
- exp = a->exp - b->exp + 1;
+ exp = REAL_EXP (a) - REAL_EXP (b) + 1;
if (exp > MAX_EXP)
{
get_inf (r, sign);
get_zero (r, sign);
return true;
}
- rr->exp = exp;
+ SET_REAL_EXP (rr, exp);
inexact = div_significands (rr, a, b);
one of the two operands is a NaN. */
static int
-do_compare (a, b, nan_result)
- const REAL_VALUE_TYPE *a, *b;
- int nan_result;
+do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b,
+ int nan_result)
{
int ret;
if (a->sign != b->sign)
return -a->sign - -b->sign;
- if (a->exp > b->exp)
+ if (REAL_EXP (a) > REAL_EXP (b))
ret = 1;
- else if (a->exp < b->exp)
+ else if (REAL_EXP (a) < REAL_EXP (b))
ret = -1;
else
ret = cmp_significands (a, b);
/* Return A truncated to an integral value toward zero. */
static void
-do_fix_trunc (r, a)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *a;
+do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
{
*r = *a;
break;
case rvc_normal:
- if (r->exp <= 0)
+ if (REAL_EXP (r) <= 0)
get_zero (r, r->sign);
- else if (r->exp < SIGNIFICAND_BITS)
- clear_significand_below (r, SIGNIFICAND_BITS - r->exp);
+ else if (REAL_EXP (r) < SIGNIFICAND_BITS)
+ clear_significand_below (r, SIGNIFICAND_BITS - REAL_EXP (r));
break;
default:
For a unary operation, leave OP1 NULL. */
void
-real_arithmetic (r, icode, op0, op1)
- REAL_VALUE_TYPE *r;
- int icode;
- const REAL_VALUE_TYPE *op0, *op1;
+real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
+ const REAL_VALUE_TYPE *op1)
{
enum tree_code code = icode;
/* Legacy. Similar, but return the result directly. */
REAL_VALUE_TYPE
-real_arithmetic2 (icode, op0, op1)
- int icode;
- const REAL_VALUE_TYPE *op0, *op1;
+real_arithmetic2 (int icode, const REAL_VALUE_TYPE *op0,
+ const REAL_VALUE_TYPE *op1)
{
REAL_VALUE_TYPE r;
real_arithmetic (&r, icode, op0, op1);
}
bool
-real_compare (icode, op0, op1)
- int icode;
- const REAL_VALUE_TYPE *op0, *op1;
+real_compare (int icode, const REAL_VALUE_TYPE *op0,
+ const REAL_VALUE_TYPE *op1)
{
enum tree_code code = icode;
return do_compare (op0, op1, 1) >= 0;
case UNEQ_EXPR:
return do_compare (op0, op1, 0) == 0;
+ case LTGT_EXPR:
+ return do_compare (op0, op1, 0) != 0;
default:
abort ();
/* Return floor log2(R). */
int
-real_exponent (r)
- const REAL_VALUE_TYPE *r;
+real_exponent (const REAL_VALUE_TYPE *r)
{
switch (r->class)
{
case rvc_nan:
return (unsigned int)-1 >> 1;
case rvc_normal:
- return r->exp;
+ return REAL_EXP (r);
default:
abort ();
}
/* R = OP0 * 2**EXP. */
void
-real_ldexp (r, op0, exp)
- REAL_VALUE_TYPE *r;
- const REAL_VALUE_TYPE *op0;
- int exp;
+real_ldexp (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, int exp)
{
*r = *op0;
switch (r->class)
break;
case rvc_normal:
- exp += op0->exp;
+ exp += REAL_EXP (op0);
if (exp > MAX_EXP)
get_inf (r, r->sign);
else if (exp < -MAX_EXP)
get_zero (r, r->sign);
else
- r->exp = exp;
+ SET_REAL_EXP (r, exp);
break;
default:
/* Determine whether a floating-point value X is infinite. */
bool
-real_isinf (r)
- const REAL_VALUE_TYPE *r;
+real_isinf (const REAL_VALUE_TYPE *r)
{
return (r->class == rvc_inf);
}
/* Determine whether a floating-point value X is a NaN. */
bool
-real_isnan (r)
- const REAL_VALUE_TYPE *r;
+real_isnan (const REAL_VALUE_TYPE *r)
{
return (r->class == rvc_nan);
}
/* Determine whether a floating-point value X is negative. */
bool
-real_isneg (r)
- const REAL_VALUE_TYPE *r;
+real_isneg (const REAL_VALUE_TYPE *r)
{
return r->sign;
}
/* Determine whether a floating-point value X is minus zero. */
bool
-real_isnegzero (r)
- const REAL_VALUE_TYPE *r;
+real_isnegzero (const REAL_VALUE_TYPE *r)
{
return r->sign && r->class == rvc_zero;
}
/* Compare two floating-point objects for bitwise identity. */
bool
-real_identical (a, b)
- const REAL_VALUE_TYPE *a, *b;
+real_identical (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b)
{
int i;
return true;
case rvc_normal:
- if (a->exp != b->exp)
- return false;
+ if (REAL_EXP (a) != REAL_EXP (b))
+ return false;
break;
case rvc_nan:
mode MODE. Return true if successful. */
bool
-exact_real_inverse (mode, r)
- enum machine_mode mode;
- REAL_VALUE_TYPE *r;
+exact_real_inverse (enum machine_mode mode, REAL_VALUE_TYPE *r)
{
const REAL_VALUE_TYPE *one = real_digit (1);
REAL_VALUE_TYPE u;
int i;
-
+
if (r->class != rvc_normal)
return false;
/* Find the inverse and truncate to the required mode. */
do_divide (&u, one, r);
real_convert (&u, mode, &u);
-
+
/* The rounding may have overflowed. */
if (u.class != rvc_normal)
return false;
/* Render R as an integer. */
HOST_WIDE_INT
-real_to_integer (r)
- const REAL_VALUE_TYPE *r;
+real_to_integer (const REAL_VALUE_TYPE *r)
{
unsigned HOST_WIDE_INT i;
return i;
case rvc_normal:
- if (r->exp <= 0)
+ if (REAL_EXP (r) <= 0)
goto underflow;
/* Only force overflow for unsigned overflow. Signed overflow is
undefined, so it doesn't matter what we return, and some callers
- expect to be able to use this routine for both signed and
+ expect to be able to use this routine for both signed and
unsigned conversions. */
- if (r->exp > HOST_BITS_PER_WIDE_INT)
+ if (REAL_EXP (r) > HOST_BITS_PER_WIDE_INT)
goto overflow;
if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
else
abort ();
- i >>= HOST_BITS_PER_WIDE_INT - r->exp;
+ i >>= HOST_BITS_PER_WIDE_INT - REAL_EXP (r);
if (r->sign)
i = -i;
/* Likewise, but to an integer pair, HI+LOW. */
void
-real_to_integer2 (plow, phigh, r)
- HOST_WIDE_INT *plow, *phigh;
- const REAL_VALUE_TYPE *r;
+real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
+ const REAL_VALUE_TYPE *r)
{
REAL_VALUE_TYPE t;
HOST_WIDE_INT low, high;
break;
case rvc_normal:
- exp = r->exp;
+ exp = REAL_EXP (r);
if (exp <= 0)
goto underflow;
/* Only force overflow for unsigned overflow. Signed overflow is
undefined, so it doesn't matter what we return, and some callers
- expect to be able to use this routine for both signed and
+ expect to be able to use this routine for both signed and
unsigned conversions. */
if (exp > 2*HOST_BITS_PER_WIDE_INT)
goto overflow;
small. */
static unsigned long
-rtd_divmod (num, den)
- REAL_VALUE_TYPE *num, *den;
+rtd_divmod (REAL_VALUE_TYPE *num, REAL_VALUE_TYPE *den)
{
unsigned long q, msb;
- int expn = num->exp, expd = den->exp;
+ int expn = REAL_EXP (num), expd = REAL_EXP (den);
if (expn < expd)
return 0;
}
while (--expn >= expd);
- num->exp = expd;
+ SET_REAL_EXP (num, expd);
normalize (num);
return q;
#define M_LOG10_2 0.30102999566398119521
void
-real_to_decimal (str, r_orig, buf_size, digits, crop_trailing_zeros)
- char *str;
- const REAL_VALUE_TYPE *r_orig;
- size_t buf_size, digits;
- int crop_trailing_zeros;
+real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
+ size_t digits, int crop_trailing_zeros)
{
const REAL_VALUE_TYPE *one, *ten;
REAL_VALUE_TYPE r, pten, u, v;
/* Estimate the decimal exponent, and compute the length of the string it
will print as. Be conservative and add one to account for possible
overflow or rounding error. */
- dec_exp = r.exp * M_LOG10_2;
+ dec_exp = REAL_EXP (&r) * M_LOG10_2;
for (max_digits = 1; dec_exp ; max_digits++)
dec_exp /= 10;
and strip trailing decimal zeros. */
u = r;
- u.exp = SIGNIFICAND_BITS - 1;
+ SET_REAL_EXP (&u, SIGNIFICAND_BITS - 1);
/* Largest M, such that 10**2**M fits within SIGNIFICAND_BITS. */
m = floor_log2 (max_digits);
/* Iterate over the bits of the possible powers of 10 that might
be present in U and eliminate them. That is, if we find that
- 10**2**M divides U evenly, keep the division and increase
+ 10**2**M divides U evenly, keep the division and increase
DEC_EXP by 2**M. */
do
{
while (--m >= 0);
/* Revert the scaling to integer that we performed earlier. */
- u.exp += r.exp - (SIGNIFICAND_BITS - 1);
+ SET_REAL_EXP (&u, REAL_EXP (&u) + REAL_EXP (&r)
+ - (SIGNIFICAND_BITS - 1));
r = u;
/* Find power of 10. Do this by dividing out 10**2**M when
- this is larger than the current remainder. Fill PTEN with
+ this is larger than the current remainder. Fill PTEN with
the power of 10 that we compute. */
- if (r.exp > 0)
+ if (REAL_EXP (&r) > 0)
{
- m = floor_log2 ((int)(r.exp * M_LOG10_2)) + 1;
+ m = floor_log2 ((int)(REAL_EXP (&r) * M_LOG10_2)) + 1;
do
{
const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m);
do_multiply (&u, &v, ten);
/* Stop if we're now >= 1. */
- if (u.exp > 0)
+ if (REAL_EXP (&u) > 0)
break;
v = u;
/* Find power of 10. Do this by multiplying in P=10**2**M when
the current remainder is smaller than 1/P. Fill PTEN with the
power of 10 that we compute. */
- m = floor_log2 ((int)(-r.exp * M_LOG10_2)) + 1;
+ m = floor_log2 ((int)(-REAL_EXP (&r) * M_LOG10_2)) + 1;
do
{
const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m);
dec_exp++;
}
}
-
+
/* Insert the decimal point. */
first[0] = first[1];
first[1] = '.';
strip trailing zeros. */
void
-real_to_hexadecimal (str, r, buf_size, digits, crop_trailing_zeros)
- char *str;
- const REAL_VALUE_TYPE *r;
- size_t buf_size, digits;
- int crop_trailing_zeros;
+real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size,
+ size_t digits, int crop_trailing_zeros)
{
- int i, j, exp = r->exp;
+ int i, j, exp = REAL_EXP (r);
char *p, *first;
char exp_buf[16];
size_t max_digits;
assumed to have been syntax checked already. */
void
-real_from_string (r, str)
- REAL_VALUE_TYPE *r;
- const char *str;
+real_from_string (REAL_VALUE_TYPE *r, const char *str)
{
int exp = 0;
bool sign = false;
else if (*str == '+')
str++;
- if (str[0] == '0' && str[1] == 'x')
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
{
/* Hexadecimal floating point. */
int pos = SIGNIFICAND_BITS - 4, d;
}
r->class = rvc_normal;
- r->exp = exp;
+ SET_REAL_EXP (r, exp);
normalize (r);
}
/* Legacy. Similar, but return the result directly. */
REAL_VALUE_TYPE
-real_from_string2 (s, mode)
- const char *s;
- enum machine_mode mode;
+real_from_string2 (const char *s, enum machine_mode mode)
{
REAL_VALUE_TYPE r;
/* Initialize R from the integer pair HIGH+LOW. */
void
-real_from_integer (r, mode, low, high, unsigned_p)
- REAL_VALUE_TYPE *r;
- enum machine_mode mode;
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
- int unsigned_p;
+real_from_integer (REAL_VALUE_TYPE *r, enum machine_mode mode,
+ unsigned HOST_WIDE_INT low, HOST_WIDE_INT high,
+ int unsigned_p)
{
if (low == 0 && high == 0)
get_zero (r, 0);
{
r->class = rvc_normal;
r->sign = high < 0 && !unsigned_p;
- r->exp = 2 * HOST_BITS_PER_WIDE_INT;
+ SET_REAL_EXP (r, 2 * HOST_BITS_PER_WIDE_INT);
if (r->sign)
{
/* Returns 10**2**N. */
static const REAL_VALUE_TYPE *
-ten_to_ptwo (n)
- int n;
+ten_to_ptwo (int n)
{
static REAL_VALUE_TYPE tens[EXP_BITS];
/* Returns 10**(-2**N). */
static const REAL_VALUE_TYPE *
-ten_to_mptwo (n)
- int n;
+ten_to_mptwo (int n)
{
static REAL_VALUE_TYPE tens[EXP_BITS];
/* Returns N. */
static const REAL_VALUE_TYPE *
-real_digit (n)
- int n;
+real_digit (int n)
{
static REAL_VALUE_TYPE num[10];
/* Multiply R by 10**EXP. */
static void
-times_pten (r, exp)
- REAL_VALUE_TYPE *r;
- int exp;
+times_pten (REAL_VALUE_TYPE *r, int exp)
{
REAL_VALUE_TYPE pten, *rr;
bool negative = (exp < 0);
/* Fills R with +Inf. */
void
-real_inf (r)
- REAL_VALUE_TYPE *r;
+real_inf (REAL_VALUE_TYPE *r)
{
get_inf (r, 0);
}
if the string was successfully parsed. */
bool
-real_nan (r, str, quiet, mode)
- REAL_VALUE_TYPE *r;
- const char *str;
- int quiet;
- enum machine_mode mode;
+real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet,
+ enum machine_mode mode)
{
const struct real_format *fmt;
- fmt = real_format_for_mode[mode - QFmode];
+ fmt = REAL_MODE_FORMAT (mode);
if (fmt == NULL)
abort ();
If SIGN is nonzero, R is set to the most negative finite value. */
void
-real_maxval (r, sign, mode)
- REAL_VALUE_TYPE *r;
- int sign;
- enum machine_mode mode;
+real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
{
const struct real_format *fmt;
int np2;
- fmt = real_format_for_mode[mode - QFmode];
+ fmt = REAL_MODE_FORMAT (mode);
if (fmt == NULL)
abort ();
r->sign = sign;
r->signalling = 0;
r->canonical = 0;
- r->exp = fmt->emax * fmt->log2_b;
+ SET_REAL_EXP (r, fmt->emax * fmt->log2_b);
np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b;
memset (r->sig, -1, SIGSZ * sizeof (unsigned long));
/* Fills R with 2**N. */
void
-real_2expN (r, n)
- REAL_VALUE_TYPE *r;
- int n;
+real_2expN (REAL_VALUE_TYPE *r, int n)
{
memset (r, 0, sizeof (*r));
else
{
r->class = rvc_normal;
- r->exp = n;
+ SET_REAL_EXP (r, n);
r->sig[SIGSZ-1] = SIG_MSB;
}
}
\f
static void
-round_for_format (fmt, r)
- const struct real_format *fmt;
- REAL_VALUE_TYPE *r;
+round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
{
int p2, np2, i, w;
unsigned long sticky;
the true base. */
if (fmt->log2_b != 1)
{
- int shift = r->exp & (fmt->log2_b - 1);
+ int shift = REAL_EXP (r) & (fmt->log2_b - 1);
if (shift)
{
shift = fmt->log2_b - shift;
r->sig[0] |= sticky_rshift_significand (r, r, shift);
- r->exp += shift;
+ SET_REAL_EXP (r, REAL_EXP (r) + shift);
}
}
/* Check the range of the exponent. If we're out of range,
either underflow or overflow. */
- if (r->exp > emax2)
+ if (REAL_EXP (r) > emax2)
goto overflow;
- else if (r->exp <= emin2m1)
+ else if (REAL_EXP (r) <= emin2m1)
{
int diff;
if (!fmt->has_denorm)
{
/* Don't underflow completely until we've had a chance to round. */
- if (r->exp < emin2m1)
+ if (REAL_EXP (r) < emin2m1)
goto underflow;
}
else
{
- diff = emin2m1 - r->exp + 1;
+ diff = emin2m1 - REAL_EXP (r) + 1;
if (diff > p2)
goto underflow;
/* De-normalize the significand. */
r->sig[0] |= sticky_rshift_significand (r, r, diff);
- r->exp += diff;
+ SET_REAL_EXP (r, REAL_EXP (r) + diff);
}
}
/* Overflow. Means the significand had been all ones, and
is now all zeros. Need to increase the exponent, and
possibly re-normalize it. */
- if (++r->exp > emax2)
+ SET_REAL_EXP (r, REAL_EXP (r) + 1);
+ if (REAL_EXP (r) > emax2)
goto overflow;
r->sig[SIGSZ-1] = SIG_MSB;
if (fmt->log2_b != 1)
{
- int shift = r->exp & (fmt->log2_b - 1);
+ int shift = REAL_EXP (r) & (fmt->log2_b - 1);
if (shift)
{
shift = fmt->log2_b - shift;
rshift_significand (r, r, shift);
- r->exp += shift;
- if (r->exp > emax2)
+ SET_REAL_EXP (r, REAL_EXP (r) + shift);
+ if (REAL_EXP (r) > emax2)
goto overflow;
}
}
}
/* Catch underflow that we deferred until after rounding. */
- if (r->exp <= emin2m1)
+ if (REAL_EXP (r) <= emin2m1)
goto underflow;
/* Clear out trailing garbage. */
/* Extend or truncate to a new mode. */
void
-real_convert (r, mode, a)
- REAL_VALUE_TYPE *r;
- enum machine_mode mode;
- const REAL_VALUE_TYPE *a;
+real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode,
+ const REAL_VALUE_TYPE *a)
{
const struct real_format *fmt;
- fmt = real_format_for_mode[mode - QFmode];
+ fmt = REAL_MODE_FORMAT (mode);
if (fmt == NULL)
abort ();
/* Legacy. Likewise, except return the struct directly. */
REAL_VALUE_TYPE
-real_value_truncate (mode, a)
- enum machine_mode mode;
- REAL_VALUE_TYPE a;
+real_value_truncate (enum machine_mode mode, REAL_VALUE_TYPE a)
{
REAL_VALUE_TYPE r;
real_convert (&r, mode, &a);
/* Return true if truncating to MODE is exact. */
bool
-exact_real_truncate (mode, a)
- enum machine_mode mode;
- const REAL_VALUE_TYPE *a;
+exact_real_truncate (enum machine_mode mode, const REAL_VALUE_TYPE *a)
{
REAL_VALUE_TYPE t;
real_convert (&t, mode, a);
Legacy: return word 0 for implementing REAL_VALUE_TO_TARGET_SINGLE. */
long
-real_to_target_fmt (buf, r_orig, fmt)
- long *buf;
- const REAL_VALUE_TYPE *r_orig;
- const struct real_format *fmt;
+real_to_target_fmt (long *buf, const REAL_VALUE_TYPE *r_orig,
+ const struct real_format *fmt)
{
REAL_VALUE_TYPE r;
long buf1;
/* Similar, but look up the format from MODE. */
long
-real_to_target (buf, r, mode)
- long *buf;
- const REAL_VALUE_TYPE *r;
- enum machine_mode mode;
+real_to_target (long *buf, const REAL_VALUE_TYPE *r, enum machine_mode mode)
{
const struct real_format *fmt;
- fmt = real_format_for_mode[mode - QFmode];
+ fmt = REAL_MODE_FORMAT (mode);
if (fmt == NULL)
abort ();
long, no matter the size of the host long. */
void
-real_from_target_fmt (r, buf, fmt)
- REAL_VALUE_TYPE *r;
- const long *buf;
- const struct real_format *fmt;
+real_from_target_fmt (REAL_VALUE_TYPE *r, const long *buf,
+ const struct real_format *fmt)
{
(*fmt->decode) (fmt, r, buf);
-}
+}
/* Similar, but look up the format from MODE. */
void
-real_from_target (r, buf, mode)
- REAL_VALUE_TYPE *r;
- const long *buf;
- enum machine_mode mode;
+real_from_target (REAL_VALUE_TYPE *r, const long *buf, enum machine_mode mode)
{
const struct real_format *fmt;
- fmt = real_format_for_mode[mode - QFmode];
+ fmt = REAL_MODE_FORMAT (mode);
if (fmt == NULL)
abort ();
(*fmt->decode) (fmt, r, buf);
-}
+}
/* Return the number of bits in the significand for MODE. */
/* ??? Legacy. Should get access to real_format directly. */
int
-significand_size (mode)
- enum machine_mode mode;
+significand_size (enum machine_mode mode)
{
const struct real_format *fmt;
- fmt = real_format_for_mode[mode - QFmode];
+ fmt = REAL_MODE_FORMAT (mode);
if (fmt == NULL)
return 0;
but I didn't want to pull hashtab.h into real.h. */
unsigned int
-real_hash (r)
- const REAL_VALUE_TYPE *r;
+real_hash (const REAL_VALUE_TYPE *r)
{
unsigned int h;
size_t i;
return h;
case rvc_normal:
- h |= r->exp << 3;
+ h |= REAL_EXP (r) << 3;
break;
case rvc_nan:
\f
/* IEEE single-precision format. */
-static void encode_ieee_single PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_ieee_single PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
+static void encode_ieee_single (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_ieee_single (const struct real_format *,
+ REAL_VALUE_TYPE *, const long *);
static void
-encode_ieee_single (fmt, buf, r)
- const struct real_format *fmt;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_ieee_single (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 = r->sign << 31;
+ image = sign << 31;
sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
switch (r->class)
if (denormal)
exp = 0;
else
- exp = r->exp + 127 - 1;
+ exp = REAL_EXP (r) + 127 - 1;
image |= exp << 23;
image |= sig;
break;
}
static void
-decode_ieee_single (fmt, r, buf)
- const struct real_format *fmt;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_ieee_single (const struct real_format *fmt, REAL_VALUE_TYPE *r,
+ const long *buf)
{
unsigned long image = buf[0] & 0xffffffff;
bool sign = (image >> 31) & 1;
{
r->class = rvc_normal;
r->sign = sign;
- r->exp = -126;
+ SET_REAL_EXP (r, -126);
r->sig[SIGSZ-1] = image << 1;
normalize (r);
}
{
r->class = rvc_normal;
r->sign = sign;
- r->exp = exp - 127 + 1;
+ SET_REAL_EXP (r, exp - 127 + 1);
r->sig[SIGSZ-1] = image | SIG_MSB;
}
}
-const struct real_format ieee_single_format =
+const struct real_format ieee_single_format =
{
encode_ieee_single,
decode_ieee_single,
true
};
-const struct real_format mips_single_format =
+const struct real_format mips_single_format =
{
encode_ieee_single,
decode_ieee_single,
\f
/* IEEE double-precision format. */
-static void encode_ieee_double PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_ieee_double PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
+static void encode_ieee_double (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_ieee_double (const struct real_format *,
+ REAL_VALUE_TYPE *, const long *);
static void
-encode_ieee_double (fmt, buf, r)
- const struct real_format *fmt;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_ieee_double (const struct real_format *fmt, long *buf,
+ const REAL_VALUE_TYPE *r)
{
unsigned long image_lo, image_hi, sig_lo, sig_hi, exp;
bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
if (denormal)
exp = 0;
else
- exp = r->exp + 1023 - 1;
+ exp = REAL_EXP (r) + 1023 - 1;
image_hi |= exp << 20;
image_hi |= sig_hi;
image_lo = sig_lo;
}
static void
-decode_ieee_double (fmt, r, buf)
- const struct real_format *fmt;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_ieee_double (const struct real_format *fmt, REAL_VALUE_TYPE *r,
+ const long *buf)
{
unsigned long image_hi, image_lo;
bool sign;
{
r->class = rvc_normal;
r->sign = sign;
- r->exp = -1022;
+ SET_REAL_EXP (r, -1022);
if (HOST_BITS_PER_LONG == 32)
{
image_hi = (image_hi << 1) | (image_lo >> 31);
{
r->class = rvc_normal;
r->sign = sign;
- r->exp = exp - 1023 + 1;
+ SET_REAL_EXP (r, exp - 1023 + 1);
if (HOST_BITS_PER_LONG == 32)
{
r->sig[SIGSZ-1] = image_hi | SIG_MSB;
}
}
-const struct real_format ieee_double_format =
+const struct real_format ieee_double_format =
{
encode_ieee_double,
decode_ieee_double,
true
};
-const struct real_format mips_double_format =
+const struct real_format mips_double_format =
{
encode_ieee_double,
decode_ieee_double,
};
\f
-/* IEEE extended double precision format. This comes in three
- flavors: Intel's as a 12 byte image, Intel's as a 16 byte image,
- and Motorola's. */
-
-static void encode_ieee_extended PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_ieee_extended PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
-
-static void encode_ieee_extended_128 PARAMS ((const struct real_format *fmt,
- long *,
- const REAL_VALUE_TYPE *));
-static void decode_ieee_extended_128 PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *,
- const long *));
-
+/* IEEE extended real format. This comes in three flavors: Intel's as
+ a 12 byte image, Intel's as a 16 byte image, and Motorola's. Intel
+ 12- and 16-byte images may be big- or little endian; Motorola's is
+ always big endian. */
+
+/* Helper subroutine which converts from the internal format to the
+ 12-byte little-endian Intel format. Functions below adjust this
+ for the other possible formats. */
static void
-encode_ieee_extended (fmt, buf, r)
- const struct real_format *fmt;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_ieee_extended (const struct real_format *fmt, long *buf,
+ const REAL_VALUE_TYPE *r)
{
unsigned long image_hi, sig_hi, sig_lo;
bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
case rvc_normal:
{
- int exp = r->exp;
+ int exp = REAL_EXP (r);
/* 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.
+ Which means we're off by one.
Except for Motorola, which consider exp=0 and explicit
integer bit set to continue to be normalized. In theory
abort ();
}
+ buf[0] = sig_lo, buf[1] = sig_hi, buf[2] = image_hi;
+}
+
+/* Convert from the internal format to the 12-byte Motorola format
+ for an IEEE extended real. */
+static void
+encode_ieee_extended_motorola (const struct real_format *fmt, long *buf,
+ const REAL_VALUE_TYPE *r)
+{
+ long intermed[3];
+ encode_ieee_extended (fmt, intermed, r);
+
+ /* Motorola chips are assumed always to be big-endian. Also, the
+ padding in a Motorola extended real goes between the exponent and
+ the mantissa. At this point the mantissa is entirely within
+ elements 0 and 1 of intermed, and the exponent entirely within
+ element 2, so all we have to do is swap the order around, and
+ shift element 2 left 16 bits. */
+ buf[0] = intermed[2] << 16;
+ buf[1] = intermed[1];
+ buf[2] = intermed[0];
+}
+
+/* Convert from the internal format to the 12-byte Intel format for
+ an IEEE extended real. */
+static void
+encode_ieee_extended_intel_96 (const struct real_format *fmt, long *buf,
+ const REAL_VALUE_TYPE *r)
+{
if (FLOAT_WORDS_BIG_ENDIAN)
- buf[0] = image_hi << 16, buf[1] = sig_hi, buf[2] = sig_lo;
+ {
+ /* All the padding in an Intel-format extended real goes at the high
+ end, which in this case is after the mantissa, not the exponent.
+ Therefore we must shift everything down 16 bits. */
+ long intermed[3];
+ encode_ieee_extended (fmt, intermed, r);
+ buf[0] = ((intermed[2] << 16) | ((unsigned long)(intermed[1] & 0xFFFF0000) >> 16));
+ buf[1] = ((intermed[1] << 16) | ((unsigned long)(intermed[0] & 0xFFFF0000) >> 16));
+ buf[2] = (intermed[0] << 16);
+ }
else
- buf[0] = sig_lo, buf[1] = sig_hi, buf[2] = image_hi;
+ /* encode_ieee_extended produces what we want directly. */
+ encode_ieee_extended (fmt, buf, r);
}
+/* Convert from the internal format to the 16-byte Intel format for
+ an IEEE extended real. */
static void
-encode_ieee_extended_128 (fmt, buf, r)
- const struct real_format *fmt;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_ieee_extended_intel_128 (const struct real_format *fmt, long *buf,
+ const REAL_VALUE_TYPE *r)
{
- buf[3 * !FLOAT_WORDS_BIG_ENDIAN] = 0;
- encode_ieee_extended (fmt, buf+!!FLOAT_WORDS_BIG_ENDIAN, r);
+ /* All the padding in an Intel-format extended real goes at the high end. */
+ encode_ieee_extended_intel_96 (fmt, buf, r);
+ buf[3] = 0;
}
+/* As above, we have a helper function which converts from 12-byte
+ little-endian Intel format to internal format. Functions below
+ adjust for the other possible formats. */
static void
-decode_ieee_extended (fmt, r, buf)
- const struct real_format *fmt;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_ieee_extended (const struct real_format *fmt, REAL_VALUE_TYPE *r,
+ const long *buf)
{
unsigned long image_hi, sig_hi, sig_lo;
bool sign;
int exp;
- if (FLOAT_WORDS_BIG_ENDIAN)
- image_hi = buf[0] >> 16, sig_hi = buf[1], sig_lo = buf[2];
- else
- sig_lo = buf[0], sig_hi = buf[1], image_hi = buf[2];
+ sig_lo = buf[0], sig_hi = buf[1], image_hi = buf[2];
sig_lo &= 0xffffffff;
sig_hi &= 0xffffffff;
image_hi &= 0xffffffff;
and decrease the exponent to match. In this case, Motorola
defines the explicit integer bit to be valid, so we don't
know whether the msb is set or not. */
- r->exp = fmt->emin;
+ SET_REAL_EXP (r, fmt->emin);
if (HOST_BITS_PER_LONG == 32)
{
r->sig[SIGSZ-1] = sig_hi;
{
r->class = rvc_normal;
r->sign = sign;
- r->exp = exp - 16383 + 1;
+ SET_REAL_EXP (r, exp - 16383 + 1);
if (HOST_BITS_PER_LONG == 32)
{
r->sig[SIGSZ-1] = sig_hi;
}
}
+/* Convert from the internal format to the 12-byte Motorola format
+ for an IEEE extended real. */
static void
-decode_ieee_extended_128 (fmt, r, buf)
- const struct real_format *fmt;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_ieee_extended_motorola (const struct real_format *fmt, REAL_VALUE_TYPE *r,
+ const long *buf)
{
- decode_ieee_extended (fmt, r, buf+!!FLOAT_WORDS_BIG_ENDIAN);
+ long intermed[3];
+
+ /* Motorola chips are assumed always to be big-endian. Also, the
+ padding in a Motorola extended real goes between the exponent and
+ the mantissa; remove it. */
+ intermed[0] = buf[2];
+ intermed[1] = buf[1];
+ intermed[2] = (unsigned long)buf[0] >> 16;
+
+ decode_ieee_extended (fmt, r, intermed);
+}
+
+/* Convert from the internal format to the 12-byte Intel format for
+ an IEEE extended real. */
+static void
+decode_ieee_extended_intel_96 (const struct real_format *fmt, REAL_VALUE_TYPE *r,
+ const long *buf)
+{
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ {
+ /* All the padding in an Intel-format extended real goes at the high
+ end, which in this case is after the mantissa, not the exponent.
+ Therefore we must shift everything up 16 bits. */
+ long intermed[3];
+
+ intermed[0] = (((unsigned long)buf[2] >> 16) | (buf[1] << 16));
+ intermed[1] = (((unsigned long)buf[1] >> 16) | (buf[0] << 16));
+ intermed[2] = ((unsigned long)buf[0] >> 16);
+
+ decode_ieee_extended (fmt, r, intermed);
+ }
+ else
+ /* decode_ieee_extended produces what we want directly. */
+ decode_ieee_extended (fmt, r, buf);
}
-const struct real_format ieee_extended_motorola_format =
+/* Convert from the internal format to the 16-byte Intel format for
+ an IEEE extended real. */
+static void
+decode_ieee_extended_intel_128 (const struct real_format *fmt, REAL_VALUE_TYPE *r,
+ const long *buf)
+{
+ /* All the padding in an Intel-format extended real goes at the high end. */
+ decode_ieee_extended_intel_96 (fmt, r, buf);
+}
+
+const struct real_format ieee_extended_motorola_format =
{
- encode_ieee_extended,
- decode_ieee_extended,
+ encode_ieee_extended_motorola,
+ decode_ieee_extended_motorola,
2,
1,
64,
true
};
-const struct real_format ieee_extended_intel_96_format =
+const struct real_format ieee_extended_intel_96_format =
{
- encode_ieee_extended,
- decode_ieee_extended,
+ encode_ieee_extended_intel_96,
+ decode_ieee_extended_intel_96,
2,
1,
64,
true
};
-const struct real_format ieee_extended_intel_128_format =
+const struct real_format ieee_extended_intel_128_format =
{
- encode_ieee_extended_128,
- decode_ieee_extended_128,
+ encode_ieee_extended_intel_128,
+ decode_ieee_extended_intel_128,
2,
1,
64,
/* The following caters to i386 systems that set the rounding precision
to 53 bits instead of 64, e.g. FreeBSD. */
-const struct real_format ieee_extended_intel_96_round_53_format =
+const struct real_format ieee_extended_intel_96_round_53_format =
{
- encode_ieee_extended,
- decode_ieee_extended,
+ encode_ieee_extended_intel_96,
+ decode_ieee_extended_intel_96,
2,
1,
53,
ignored. Zeroes, Infinities, and NaNs are set in both doubles
due to precedent. */
-static void encode_ibm_extended PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_ibm_extended PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
+static void encode_ibm_extended (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_ibm_extended (const struct real_format *,
+ REAL_VALUE_TYPE *, const long *);
static void
-encode_ibm_extended (fmt, buf, r)
- const struct real_format *fmt;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_ibm_extended (const struct real_format *fmt, long *buf,
+ const REAL_VALUE_TYPE *r)
{
- REAL_VALUE_TYPE u, v;
+ REAL_VALUE_TYPE u, normr, v;
const struct real_format *base_fmt;
base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
- switch (r->class)
- {
- case rvc_zero:
- /* Both doubles have sign bit set. */
- buf[0] = FLOAT_WORDS_BIG_ENDIAN ? r->sign << 31 : 0;
- buf[1] = FLOAT_WORDS_BIG_ENDIAN ? 0 : r->sign << 31;
- buf[2] = buf[0];
- buf[3] = buf[1];
- break;
+ /* Renormlize R before doing any arithmetic on it. */
+ normr = *r;
+ if (normr.class == rvc_normal)
+ normalize (&normr);
- case rvc_inf:
- case rvc_nan:
- /* Both doubles set to Inf / NaN. */
- encode_ieee_double (base_fmt, &buf[0], r);
- buf[2] = buf[0];
- buf[3] = buf[1];
- return;
-
- case rvc_normal:
- /* u = IEEE double precision portion of significand. */
- u = *r;
- clear_significand_below (&u, SIGNIFICAND_BITS - 53);
-
- normalize (&u);
- /* If the upper double is zero, we have a denormal double, so
- move it to the first double and leave the second as zero. */
- if (u.class == rvc_zero)
- {
- v = u;
- u = *r;
- normalize (&u);
- }
- else
- {
- /* v = remainder containing additional 53 bits of significand. */
- do_add (&v, r, &u, 1);
- round_for_format (base_fmt, &v);
- }
+ /* u = IEEE double precision portion of significand. */
+ u = normr;
+ round_for_format (base_fmt, &u);
+ encode_ieee_double (base_fmt, &buf[0], &u);
- round_for_format (base_fmt, &u);
-
- encode_ieee_double (base_fmt, &buf[0], &u);
+ if (u.class == rvc_normal)
+ {
+ do_add (&v, &normr, &u, 1);
+ /* Call round_for_format since we might need to denormalize. */
+ round_for_format (base_fmt, &v);
encode_ieee_double (base_fmt, &buf[2], &v);
- break;
-
- default:
- abort ();
+ }
+ else
+ {
+ /* Inf, NaN, 0 are all representable as doubles, so the
+ least-significant part can be 0.0. */
+ buf[2] = 0;
+ buf[3] = 0;
}
}
static void
-decode_ibm_extended (fmt, r, buf)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_ibm_extended (const struct real_format *fmt ATTRIBUTE_UNUSED, REAL_VALUE_TYPE *r,
+ const long *buf)
{
REAL_VALUE_TYPE u, v;
const struct real_format *base_fmt;
*r = u;
}
-const struct real_format ibm_extended_format =
+const struct real_format ibm_extended_format =
{
encode_ibm_extended,
decode_ibm_extended,
true
};
-const struct real_format mips_extended_format =
+const struct real_format mips_extended_format =
{
encode_ibm_extended,
decode_ibm_extended,
\f
/* IEEE quad precision format. */
-static void encode_ieee_quad PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_ieee_quad PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
+static void encode_ieee_quad (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_ieee_quad (const struct real_format *,
+ REAL_VALUE_TYPE *, const long *);
static void
-encode_ieee_quad (fmt, buf, r)
- const struct real_format *fmt;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_ieee_quad (const struct real_format *fmt, long *buf,
+ const REAL_VALUE_TYPE *r)
{
unsigned long image3, image2, image1, image0, exp;
bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
if (denormal)
exp = 0;
else
- exp = r->exp + 16383 - 1;
+ exp = REAL_EXP (r) + 16383 - 1;
image3 |= exp << 16;
if (HOST_BITS_PER_LONG == 32)
}
static void
-decode_ieee_quad (fmt, r, buf)
- const struct real_format *fmt;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_ieee_quad (const struct real_format *fmt, REAL_VALUE_TYPE *r,
+ const long *buf)
{
unsigned long image3, image2, image1, image0;
bool sign;
r->class = rvc_normal;
r->sign = sign;
- r->exp = -16382 + (SIGNIFICAND_BITS - 112);
+ SET_REAL_EXP (r, -16382 + (SIGNIFICAND_BITS - 112));
if (HOST_BITS_PER_LONG == 32)
{
r->sig[0] = image0;
{
r->class = rvc_normal;
r->sign = sign;
- r->exp = exp - 16383 + 1;
+ SET_REAL_EXP (r, exp - 16383 + 1);
if (HOST_BITS_PER_LONG == 32)
{
}
}
-const struct real_format ieee_quad_format =
+const struct real_format ieee_quad_format =
{
encode_ieee_quad,
decode_ieee_quad,
true
};
-const struct real_format mips_quad_format =
+const struct real_format mips_quad_format =
{
encode_ieee_quad,
decode_ieee_quad,
\f
/* Descriptions of VAX floating point formats can be found beginning at
- http://www.openvms.compaq.com:8000/73final/4515/4515pro_013.html#f_floating_point_format
+ http://h71000.www7.hp.com/doc/73FINAL/4515/4515pro_013.html#f_floating_point_format
The thing to remember is that they're almost IEEE, except for word
order, exponent bias, and the lack of infinities, nans, and denormals.
We don't implement the H_floating format here, simply because neither
the VAX or Alpha ports use it. */
-
-static void encode_vax_f PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_vax_f PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
-static void encode_vax_d PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_vax_d PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
-static void encode_vax_g PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_vax_g PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
+
+static void encode_vax_f (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_vax_f (const struct real_format *,
+ REAL_VALUE_TYPE *, const long *);
+static void encode_vax_d (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_vax_d (const struct real_format *,
+ REAL_VALUE_TYPE *, const long *);
+static void encode_vax_g (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_vax_g (const struct real_format *,
+ REAL_VALUE_TYPE *, const long *);
static void
-encode_vax_f (fmt, buf, r)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_vax_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
+ const REAL_VALUE_TYPE *r)
{
unsigned long sign, exp, sig, image;
case rvc_normal:
sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
- exp = r->exp + 128;
+ exp = REAL_EXP (r) + 128;
image = (sig << 16) & 0xffff0000;
image |= sign;
}
static void
-decode_vax_f (fmt, r, buf)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_vax_f (const struct real_format *fmt ATTRIBUTE_UNUSED,
+ REAL_VALUE_TYPE *r, const long *buf)
{
unsigned long image = buf[0] & 0xffffffff;
int exp = (image >> 7) & 0xff;
{
r->class = rvc_normal;
r->sign = (image >> 15) & 1;
- r->exp = exp - 128;
+ SET_REAL_EXP (r, exp - 128);
image = ((image & 0x7f) << 16) | ((image >> 16) & 0xffff);
r->sig[SIGSZ-1] = (image << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
}
static void
-encode_vax_d (fmt, buf, r)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_vax_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
+ const REAL_VALUE_TYPE *r)
{
unsigned long image0, image1, sign = r->sign << 15;
/* Add the sign and exponent. */
image0 |= sign;
- image0 |= (r->exp + 128) << 7;
+ image0 |= (REAL_EXP (r) + 128) << 7;
break;
default:
}
static void
-decode_vax_d (fmt, r, buf)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_vax_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
+ REAL_VALUE_TYPE *r, const long *buf)
{
unsigned long image0, image1;
int exp;
image0 &= 0xffffffff;
image1 &= 0xffffffff;
- exp = (image0 >> 7) & 0x7f;
+ exp = (image0 >> 7) & 0xff;
memset (r, 0, sizeof (*r));
{
r->class = rvc_normal;
r->sign = (image0 >> 15) & 1;
- r->exp = exp - 128;
+ SET_REAL_EXP (r, exp - 128);
/* Rearrange the half-words of the external format into
proper ascending order. */
}
static void
-encode_vax_g (fmt, buf, r)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_vax_g (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
+ const REAL_VALUE_TYPE *r)
{
unsigned long image0, image1, sign = r->sign << 15;
/* Add the sign and exponent. */
image0 |= sign;
- image0 |= (r->exp + 1024) << 4;
+ image0 |= (REAL_EXP (r) + 1024) << 4;
break;
default:
}
static void
-decode_vax_g (fmt, r, buf)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_vax_g (const struct real_format *fmt ATTRIBUTE_UNUSED,
+ REAL_VALUE_TYPE *r, const long *buf)
{
unsigned long image0, image1;
int exp;
{
r->class = rvc_normal;
r->sign = (image0 >> 15) & 1;
- r->exp = exp - 1024;
+ SET_REAL_EXP (r, exp - 1024);
/* Rearrange the half-words of the external format into
proper ascending order. */
}
}
-const struct real_format vax_f_format =
+const struct real_format vax_f_format =
{
encode_vax_f,
decode_vax_f,
false
};
-const struct real_format vax_d_format =
+const struct real_format vax_d_format =
{
encode_vax_d,
decode_vax_d,
false
};
-const struct real_format vax_g_format =
+const struct real_format vax_g_format =
{
encode_vax_g,
decode_vax_g,
http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/DZ9AR001/9.1?DT=19930923083613
*/
-static void encode_i370_single PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_i370_single PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
-static void encode_i370_double PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_i370_double PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
+static void encode_i370_single (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_i370_single (const struct real_format *,
+ REAL_VALUE_TYPE *, const long *);
+static void encode_i370_double (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_i370_double (const struct real_format *,
+ REAL_VALUE_TYPE *, const long *);
static void
-encode_i370_single (fmt, buf, r)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
+ long *buf, const REAL_VALUE_TYPE *r)
{
unsigned long sign, exp, sig, image;
case rvc_normal:
sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0xffffff;
- exp = ((r->exp / 4) + 64) << 24;
+ exp = ((REAL_EXP (r) / 4) + 64) << 24;
image = sign | exp | sig;
break;
}
static void
-decode_i370_single (fmt, r, buf)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
+ REAL_VALUE_TYPE *r, const long *buf)
{
unsigned long sign, sig, image = buf[0];
int exp;
{
r->class = rvc_normal;
r->sign = sign;
- r->exp = (exp - 64) * 4;
+ SET_REAL_EXP (r, (exp - 64) * 4);
r->sig[SIGSZ-1] = sig << (HOST_BITS_PER_LONG - 24);
normalize (r);
}
}
static void
-encode_i370_double (fmt, buf, r)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_i370_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
+ long *buf, const REAL_VALUE_TYPE *r)
{
unsigned long sign, exp, image_hi, image_lo;
image_hi >>= 8;
}
- exp = ((r->exp / 4) + 64) << 24;
+ exp = ((REAL_EXP (r) / 4) + 64) << 24;
image_hi |= sign | exp;
break;
}
static void
-decode_i370_double (fmt, r, buf)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_i370_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
+ REAL_VALUE_TYPE *r, const long *buf)
{
unsigned long sign, image_hi, image_lo;
int exp;
{
r->class = rvc_normal;
r->sign = sign;
- r->exp = (exp - 64) * 4 + (SIGNIFICAND_BITS - 56);
+ SET_REAL_EXP (r, (exp - 64) * 4 + (SIGNIFICAND_BITS - 56));
if (HOST_BITS_PER_LONG == 32)
{
See http://www-s.ti.com/sc/psheets/spru063c/spru063c.pdf */
-static void encode_c4x_single PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_c4x_single PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
-static void encode_c4x_extended PARAMS ((const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *));
-static void decode_c4x_extended PARAMS ((const struct real_format *,
- REAL_VALUE_TYPE *, const long *));
+static void encode_c4x_single (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_c4x_single (const struct real_format *,
+ REAL_VALUE_TYPE *, const long *);
+static void encode_c4x_extended (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_c4x_extended (const struct real_format *,
+ REAL_VALUE_TYPE *, const long *);
static void
-encode_c4x_single (fmt, buf, r)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
+ long *buf, const REAL_VALUE_TYPE *r)
{
unsigned long image, exp, sig;
-
+
switch (r->class)
{
case rvc_zero:
break;
case rvc_normal:
- exp = r->exp - 1;
+ exp = REAL_EXP (r) - 1;
sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
if (r->sign)
{
}
static void
-decode_c4x_single (fmt, r, buf)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
+ REAL_VALUE_TYPE *r, const long *buf)
{
unsigned long image = buf[0];
unsigned long sig;
}
sig = (sig << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
- r->exp = exp + 1;
+ SET_REAL_EXP (r, exp + 1);
r->sig[SIGSZ-1] = sig;
}
}
static void
-encode_c4x_extended (fmt, buf, r)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- long *buf;
- const REAL_VALUE_TYPE *r;
+encode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED,
+ long *buf, const REAL_VALUE_TYPE *r)
{
unsigned long exp, sig;
-
+
switch (r->class)
{
case rvc_zero:
break;
case rvc_normal:
- exp = r->exp - 1;
+ exp = REAL_EXP (r) - 1;
sig = r->sig[SIGSZ-1];
if (HOST_BITS_PER_LONG == 64)
}
static void
-decode_c4x_extended (fmt, r, buf)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
- REAL_VALUE_TYPE *r;
- const long *buf;
+decode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED,
+ REAL_VALUE_TYPE *r, const long *buf)
{
unsigned long sig;
int exp, sf;
sig = sig << 1 << 31;
sig |= SIG_MSB;
- r->exp = exp + 1;
+ SET_REAL_EXP (r, exp + 1);
r->sig[SIGSZ-1] = sig;
}
}
-const struct real_format c4x_single_format =
+const struct real_format c4x_single_format =
{
encode_c4x_single,
decode_c4x_single,
false
};
-const struct real_format c4x_extended_format =
+const struct real_format c4x_extended_format =
{
encode_c4x_extended,
decode_c4x_extended,
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 (const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *);
+static void decode_internal (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;
+encode_internal (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;
+decode_internal (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 =
+const struct real_format real_internal_format =
{
encode_internal,
decode_internal,
true,
false,
true,
- true
+ true
};
\f
-/* Set up default mode to format mapping for IEEE. Everyone else has
- to set these values in OVERRIDE_OPTIONS. */
-
-const struct real_format *real_format_for_mode[TFmode - QFmode + 1] =
-{
- NULL, /* QFmode */
- NULL, /* HFmode */
- NULL, /* TQFmode */
- &ieee_single_format, /* SFmode */
- &ieee_double_format, /* DFmode */
-
- /* We explicitly don't handle XFmode. There are two formats,
- pretty much equally common. Choose one in OVERRIDE_OPTIONS. */
- NULL, /* XFmode */
- &ieee_quad_format /* TFmode */
-};
-
-\f
/* Calculate the square root of X in mode MODE, and store the result
in R. Return TRUE if the operation does not raise an exception.
For details see "High Precision Division and Square Root",
1993. http://www.hpl.hp.com/techreports/93/HPL-93-42.pdf. */
bool
-real_sqrt (r, mode, x)
- REAL_VALUE_TYPE *r;
- enum machine_mode mode;
- const REAL_VALUE_TYPE *x;
+real_sqrt (REAL_VALUE_TYPE *r, enum machine_mode mode,
+ const REAL_VALUE_TYPE *x)
{
static REAL_VALUE_TYPE halfthree;
static bool init = false;
/* Negative arguments return NaN. */
if (real_isneg (x))
{
- /* Mode is ignored for canonical NaN. */
- real_nan (r, "", 1, SFmode);
+ get_canonical_qnan (r, 0);
return false;
}
Algorithms", "The Art of Computer Programming", Volume 2. */
bool
-real_powi (r, mode, x, n)
- REAL_VALUE_TYPE *r;
- enum machine_mode mode;
- const REAL_VALUE_TYPE *x;
- HOST_WIDE_INT n;
+real_powi (REAL_VALUE_TYPE *r, enum machine_mode mode,
+ const REAL_VALUE_TYPE *x, HOST_WIDE_INT n)
{
unsigned HOST_WIDE_INT bit;
REAL_VALUE_TYPE t;
towards zero, placing the result in R in mode MODE. */
void
-real_trunc (r, mode, x)
- REAL_VALUE_TYPE *r;
- enum machine_mode mode;
- const REAL_VALUE_TYPE *x;
+real_trunc (REAL_VALUE_TYPE *r, enum machine_mode mode,
+ const REAL_VALUE_TYPE *x)
{
do_fix_trunc (r, x);
if (mode != VOIDmode)
down, placing the result in R in mode MODE. */
void
-real_floor (r, mode, x)
- REAL_VALUE_TYPE *r;
- enum machine_mode mode;
- const REAL_VALUE_TYPE *x;
+real_floor (REAL_VALUE_TYPE *r, enum machine_mode mode,
+ const REAL_VALUE_TYPE *x)
{
- do_fix_trunc (r, x);
- if (! real_identical (r, x) && r->sign)
- do_add (r, r, &dconstm1, 0);
+ REAL_VALUE_TYPE t;
+
+ do_fix_trunc (&t, x);
+ if (! real_identical (&t, x) && x->sign)
+ do_add (&t, &t, &dconstm1, 0);
if (mode != VOIDmode)
- real_convert (r, mode, r);
+ real_convert (r, mode, &t);
}
/* Round X to the smallest integer not less then argument, i.e. round
up, placing the result in R in mode MODE. */
void
-real_ceil (r, mode, x)
- REAL_VALUE_TYPE *r;
- enum machine_mode mode;
- const REAL_VALUE_TYPE *x;
+real_ceil (REAL_VALUE_TYPE *r, enum machine_mode mode,
+ const REAL_VALUE_TYPE *x)
{
- do_fix_trunc (r, x);
- if (! real_identical (r, x) && ! r->sign)
- do_add (r, r, &dconst1, 0);
+ REAL_VALUE_TYPE t;
+
+ do_fix_trunc (&t, x);
+ if (! real_identical (&t, x) && ! x->sign)
+ do_add (&t, &t, &dconst1, 0);
+ if (mode != VOIDmode)
+ real_convert (r, mode, &t);
+}
+
+/* Round X to the nearest integer, but round halfway cases away from
+ zero. */
+
+void
+real_round (REAL_VALUE_TYPE *r, enum machine_mode mode,
+ const REAL_VALUE_TYPE *x)
+{
+ do_add (r, x, &dconsthalf, x->sign);
+ do_fix_trunc (r, r);
if (mode != VOIDmode)
real_convert (r, mode, r);
}
+/* Set the sign of R to the sign of X. */
+
+void
+real_copysign (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *x)
+{
+ r->sign = x->sign;
+}
+