| Index: gdb/doublest.c
|
| diff --git a/gdb/doublest.c b/gdb/doublest.c
|
| index c8c9e05932c29de15524a5af8c704014d2a8f091..a4889c976cd78be19ad851eb9184f5556fa96263 100644
|
| --- a/gdb/doublest.c
|
| +++ b/gdb/doublest.c
|
| @@ -1,7 +1,6 @@
|
| /* Floating point routines for GDB, the GNU debugger.
|
|
|
| - Copyright (C) 1986, 1988-2001, 2003-2005, 2007-2012 Free Software
|
| - Foundation, Inc.
|
| + Copyright (C) 1986-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -28,7 +27,7 @@
|
| #include "doublest.h"
|
| #include "floatformat.h"
|
| #include "gdb_assert.h"
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
| #include "gdbtypes.h"
|
| #include <math.h> /* ldexp */
|
|
|
| @@ -191,7 +190,8 @@ convert_floatformat_to_doublest (const struct floatformat *fmt,
|
| {
|
| double dto;
|
|
|
| - floatformat_to_double (fmt, from, &dto);
|
| + floatformat_to_double (fmt->split_half ? fmt->split_half : fmt,
|
| + from, &dto);
|
| *to = (DOUBLEST) dto;
|
| return;
|
| }
|
| @@ -337,53 +337,6 @@ put_field (unsigned char *data, enum floatformat_byteorders order,
|
| }
|
| }
|
|
|
| -#ifdef HAVE_LONG_DOUBLE
|
| -/* Return the fractional part of VALUE, and put the exponent of VALUE in *EPTR.
|
| - The range of the returned value is >= 0.5 and < 1.0. This is equivalent to
|
| - frexp, but operates on the long double data type. */
|
| -
|
| -static long double ldfrexp (long double value, int *eptr);
|
| -
|
| -static long double
|
| -ldfrexp (long double value, int *eptr)
|
| -{
|
| - long double tmp;
|
| - int exp;
|
| -
|
| - /* Unfortunately, there are no portable functions for extracting the
|
| - exponent of a long double, so we have to do it iteratively by
|
| - multiplying or dividing by two until the fraction is between 0.5
|
| - and 1.0. */
|
| -
|
| - if (value < 0.0l)
|
| - value = -value;
|
| -
|
| - tmp = 1.0l;
|
| - exp = 0;
|
| -
|
| - if (value >= tmp) /* Value >= 1.0 */
|
| - while (value >= tmp)
|
| - {
|
| - tmp *= 2.0l;
|
| - exp++;
|
| - }
|
| - else if (value != 0.0l) /* Value < 1.0 and > 0.0 */
|
| - {
|
| - while (value < tmp)
|
| - {
|
| - tmp /= 2.0l;
|
| - exp--;
|
| - }
|
| - tmp *= 2.0l;
|
| - exp++;
|
| - }
|
| -
|
| - *eptr = exp;
|
| - return value / tmp;
|
| -}
|
| -#endif /* HAVE_LONG_DOUBLE */
|
| -
|
| -
|
| /* The converse: convert the DOUBLEST *FROM to an extended float and
|
| store where TO points. Neither FROM nor TO have any alignment
|
| restrictions. */
|
| @@ -467,11 +420,33 @@ convert_doublest_to_floatformat (CONST struct floatformat *fmt,
|
| }
|
|
|
| #ifdef HAVE_LONG_DOUBLE
|
| - mant = ldfrexp (dfrom, &exponent);
|
| + mant = frexpl (dfrom, &exponent);
|
| #else
|
| mant = frexp (dfrom, &exponent);
|
| #endif
|
|
|
| + if (exponent + fmt->exp_bias <= 0)
|
| + {
|
| + /* The value is too small to be expressed in the destination
|
| + type (not enough bits in the exponent. Treat as 0. */
|
| + put_field (uto, order, fmt->totalsize, fmt->exp_start,
|
| + fmt->exp_len, 0);
|
| + put_field (uto, order, fmt->totalsize, fmt->man_start,
|
| + fmt->man_len, 0);
|
| + goto finalize_byteorder;
|
| + }
|
| +
|
| + if (exponent + fmt->exp_bias >= (1 << fmt->exp_len))
|
| + {
|
| + /* The value is too large to fit into the destination.
|
| + Treat as infinity. */
|
| + put_field (uto, order, fmt->totalsize, fmt->exp_start,
|
| + fmt->exp_len, fmt->exp_nan);
|
| + put_field (uto, order, fmt->totalsize, fmt->man_start,
|
| + fmt->man_len, 0);
|
| + goto finalize_byteorder;
|
| + }
|
| +
|
| put_field (uto, order, fmt->totalsize, fmt->exp_start, fmt->exp_len,
|
| exponent + fmt->exp_bias - 1);
|
|
|
| @@ -540,6 +515,11 @@ floatformat_is_negative (const struct floatformat *fmt,
|
| gdb_assert (fmt->totalsize
|
| <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
|
|
|
| + /* An IBM long double (a two element array of double) always takes the
|
| + sign of the first double. */
|
| + if (fmt->split_half)
|
| + fmt = fmt->split_half;
|
| +
|
| order = floatformat_normalize_byteorder (fmt, uval, newfrom);
|
|
|
| if (order != fmt->byteorder)
|
| @@ -566,6 +546,13 @@ floatformat_classify (const struct floatformat *fmt,
|
| gdb_assert (fmt->totalsize
|
| <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
|
|
|
| + /* An IBM long double (a two element array of double) can be classified
|
| + by looking at the first double. inf and nan are specified as
|
| + ignoring the second double. zero and subnormal will always have
|
| + the second double 0.0 if the long double is correctly rounded. */
|
| + if (fmt->split_half)
|
| + fmt = fmt->split_half;
|
| +
|
| order = floatformat_normalize_byteorder (fmt, uval, newfrom);
|
|
|
| if (order != fmt->byteorder)
|
| @@ -648,6 +635,16 @@ floatformat_mantissa (const struct floatformat *fmt,
|
| gdb_assert (fmt->totalsize
|
| <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
|
|
|
| + /* For IBM long double (a two element array of double), return the
|
| + mantissa of the first double. The problem with returning the
|
| + actual mantissa from both doubles is that there can be an
|
| + arbitrary number of implied 0's or 1's between the mantissas
|
| + of the first and second double. In any case, this function
|
| + is only used for dumping out nans, and a nan is specified to
|
| + ignore the value in the second double. */
|
| + if (fmt->split_half)
|
| + fmt = fmt->split_half;
|
| +
|
| order = floatformat_normalize_byteorder (fmt, uval, newfrom);
|
|
|
| if (order != fmt->byteorder)
|
| @@ -905,27 +902,3 @@ convert_typed_floating (const void *from, const struct type *from_type,
|
| floatformat_from_doublest (to_fmt, &d, to);
|
| }
|
| }
|
| -
|
| -const struct floatformat *floatformat_ieee_single[BFD_ENDIAN_UNKNOWN];
|
| -const struct floatformat *floatformat_ieee_double[BFD_ENDIAN_UNKNOWN];
|
| -const struct floatformat *floatformat_ieee_quad[BFD_ENDIAN_UNKNOWN];
|
| -const struct floatformat *floatformat_arm_ext[BFD_ENDIAN_UNKNOWN];
|
| -const struct floatformat *floatformat_ia64_spill[BFD_ENDIAN_UNKNOWN];
|
| -
|
| -extern void _initialize_doublest (void);
|
| -
|
| -extern void
|
| -_initialize_doublest (void)
|
| -{
|
| - floatformat_ieee_single[BFD_ENDIAN_LITTLE] = &floatformat_ieee_single_little;
|
| - floatformat_ieee_single[BFD_ENDIAN_BIG] = &floatformat_ieee_single_big;
|
| - floatformat_ieee_double[BFD_ENDIAN_LITTLE] = &floatformat_ieee_double_little;
|
| - floatformat_ieee_double[BFD_ENDIAN_BIG] = &floatformat_ieee_double_big;
|
| - floatformat_arm_ext[BFD_ENDIAN_LITTLE]
|
| - = &floatformat_arm_ext_littlebyte_bigword;
|
| - floatformat_arm_ext[BFD_ENDIAN_BIG] = &floatformat_arm_ext_big;
|
| - floatformat_ia64_spill[BFD_ENDIAN_LITTLE] = &floatformat_ia64_spill_little;
|
| - floatformat_ia64_spill[BFD_ENDIAN_BIG] = &floatformat_ia64_spill_big;
|
| - floatformat_ieee_quad[BFD_ENDIAN_LITTLE] = &floatformat_ia64_quad_little;
|
| - floatformat_ieee_quad[BFD_ENDIAN_BIG] = &floatformat_ia64_quad_big;
|
| -}
|
|
|