* defs.h: Provide prototypes for floatformat_is_negative,
floatformat_is_nan and floatformat_mantissa. * utils.c: Include "gdb_assert.h". (floatformat_is_negative): New function. (floatformat_is_nan): New function. (floatformat_mantissa): New function. * valprint.c: Include "floatformat.h". (print_floating): Get rid of the Linux-specific TARGET_ANALYZE_FLOATING macro and rewrite NaN detection with the help these new functions. Print NaN's in a format conforming to ISO C99.
This commit is contained in:
parent
bcdd92f3e0
commit
39424bef91
@ -1,3 +1,17 @@
|
||||
2001-03-07 Mark Kettenis <kettenis@gnu.org>
|
||||
|
||||
* defs.h: Provide prototypes for floatformat_is_negative,
|
||||
floatformat_is_nan and floatformat_mantissa.
|
||||
* utils.c: Include "gdb_assert.h".
|
||||
(floatformat_is_negative): New function.
|
||||
(floatformat_is_nan): New function.
|
||||
(floatformat_mantissa): New function.
|
||||
* valprint.c: Include "floatformat.h".
|
||||
(print_floating): Get rid of the Linux-specific
|
||||
TARGET_ANALYZE_FLOATING macro and rewrite NaN detection with the
|
||||
help these new functions. Print NaN's in a format conforming to
|
||||
ISO C99.
|
||||
|
||||
2001-03-07 Eli Zaretskii <eliz@is.elta.co.il>
|
||||
|
||||
* top.c (init_main): Make `set history file name' complete on file
|
||||
|
@ -1124,8 +1124,12 @@ extern void floatformat_to_doublest (const struct floatformat *,
|
||||
char *, DOUBLEST *);
|
||||
extern void floatformat_from_doublest (const struct floatformat *,
|
||||
DOUBLEST *, char *);
|
||||
extern DOUBLEST extract_floating (void *, int);
|
||||
|
||||
extern int floatformat_is_negative (const struct floatformat *, char *);
|
||||
extern int floatformat_is_nan (const struct floatformat *, char *);
|
||||
extern char *floatformat_mantissa (const struct floatformat *, char *);
|
||||
|
||||
extern DOUBLEST extract_floating (void *, int);
|
||||
extern void store_floating (void *, int, DOUBLEST);
|
||||
|
||||
/* On some machines there are bits in addresses which are not really
|
||||
|
101
gdb/utils.c
101
gdb/utils.c
@ -21,6 +21,7 @@
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdb_assert.h"
|
||||
#include <ctype.h>
|
||||
#include "gdb_string.h"
|
||||
#include "event-top.h"
|
||||
@ -2741,6 +2742,106 @@ floatformat_from_doublest (CONST struct floatformat *fmt, DOUBLEST *from,
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if VAL (which is assumed to be a floating point number whose
|
||||
format is described by FMT) is negative. */
|
||||
|
||||
int
|
||||
floatformat_is_negative (const struct floatformat *fmt, char *val)
|
||||
{
|
||||
unsigned char *uval = (unsigned char *) val;
|
||||
|
||||
return get_field (uval, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1);
|
||||
}
|
||||
|
||||
/* Check if VAL is "not a number" (NaN) for FMT. */
|
||||
|
||||
int
|
||||
floatformat_is_nan (const struct floatformat *fmt, char *val)
|
||||
{
|
||||
unsigned char *uval = (unsigned char *) val;
|
||||
long exponent;
|
||||
unsigned long mant;
|
||||
unsigned int mant_bits, mant_off;
|
||||
int mant_bits_left;
|
||||
|
||||
if (! fmt->exp_nan)
|
||||
return 0;
|
||||
|
||||
exponent = get_field (uval, fmt->byteorder, fmt->totalsize,
|
||||
fmt->exp_start, fmt->exp_len);
|
||||
|
||||
if (exponent != fmt->exp_nan)
|
||||
return 0;
|
||||
|
||||
mant_bits_left = fmt->man_len;
|
||||
mant_off = fmt->man_start;
|
||||
|
||||
while (mant_bits_left > 0)
|
||||
{
|
||||
mant_bits = min (mant_bits_left, 32);
|
||||
|
||||
mant = get_field (uval, fmt->byteorder, fmt->totalsize,
|
||||
mant_off, mant_bits);
|
||||
|
||||
/* If there is an explicit integer bit, mask it off. */
|
||||
if (mant_off == fmt->man_start
|
||||
&& fmt->intbit == floatformat_intbit_yes)
|
||||
mant &= ~(1 << (mant_bits - 1));
|
||||
|
||||
if (mant)
|
||||
return 1;
|
||||
|
||||
mant_off += mant_bits;
|
||||
mant_bits_left -= mant_bits;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert the mantissa of VAL (which is assumed to be a floating
|
||||
point number whose format is described by FMT) into a hexadecimal
|
||||
and store it in a static string. Return a pointer to that string. */
|
||||
|
||||
char *
|
||||
floatformat_mantissa (const struct floatformat *fmt, char *val)
|
||||
{
|
||||
unsigned char *uval = (unsigned char *) val;
|
||||
unsigned long mant;
|
||||
unsigned int mant_bits, mant_off;
|
||||
int mant_bits_left;
|
||||
static char res[50];
|
||||
char buf[9];
|
||||
|
||||
/* Make sure we have enough room to store the mantissa. */
|
||||
gdb_assert (sizeof res > ((fmt->man_len + 7) / 8) * 2);
|
||||
|
||||
mant_off = fmt->man_start;
|
||||
mant_bits_left = fmt->man_len;
|
||||
mant_bits = (mant_bits_left % 32) > 0 ? mant_bits_left % 32 : 32;
|
||||
|
||||
mant = get_field (uval, fmt->byteorder, fmt->totalsize,
|
||||
mant_off, mant_bits);
|
||||
|
||||
sprintf (res, "%lx", mant);
|
||||
|
||||
mant_off += mant_bits;
|
||||
mant_bits_left -= mant_bits;
|
||||
|
||||
while (mant_bits_left > 0)
|
||||
{
|
||||
mant = get_field (uval, fmt->byteorder, fmt->totalsize,
|
||||
mant_off, 32);
|
||||
|
||||
sprintf (buf, "%08lx", mant);
|
||||
strcat (res, buf);
|
||||
|
||||
mant_off += 32;
|
||||
mant_bits_left -= 32;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* print routines to handle variable size regs, etc. */
|
||||
|
||||
/* temporary storage using circular buffer */
|
||||
|
108
gdb/valprint.c
108
gdb/valprint.c
@ -32,6 +32,7 @@
|
||||
#include "language.h"
|
||||
#include "annotate.h"
|
||||
#include "valprint.h"
|
||||
#include "floatformat.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
@ -538,92 +539,39 @@ longest_to_int (LONGEST arg)
|
||||
return (rtnval);
|
||||
}
|
||||
|
||||
|
||||
/* Print a floating point value of type TYPE, pointed to in GDB by VALADDR,
|
||||
on STREAM. */
|
||||
/* Print a floating point value of type TYPE, pointed to in GDB by
|
||||
VALADDR, on STREAM. */
|
||||
|
||||
void
|
||||
print_floating (char *valaddr, struct type *type, struct ui_file *stream)
|
||||
{
|
||||
DOUBLEST doub;
|
||||
int inv;
|
||||
const struct floatformat *fmt = &floatformat_unknown;
|
||||
unsigned len = TYPE_LENGTH (type);
|
||||
|
||||
/* Check for NaN's. Note that this code does not depend on us being
|
||||
on an IEEE conforming system. It only depends on the target
|
||||
machine using IEEE representation. This means (a)
|
||||
cross-debugging works right, and (2) IEEE_FLOAT can (and should)
|
||||
be non-zero for systems like the 68881, which uses IEEE
|
||||
representation, but is not IEEE conforming. */
|
||||
if (IEEE_FLOAT)
|
||||
/* FIXME: kettenis/2001-01-20: The check for IEEE_FLOAT is probably
|
||||
still necessary since GDB by default assumes that the target uses
|
||||
the IEEE 754 representation for its floats and doubles. Of
|
||||
course this is all crock and should be cleaned up. */
|
||||
|
||||
if (len == TARGET_FLOAT_BIT / TARGET_CHAR_BIT && IEEE_FLOAT)
|
||||
fmt = TARGET_FLOAT_FORMAT;
|
||||
else if (len == TARGET_DOUBLE_BIT / TARGET_CHAR_BIT && IEEE_FLOAT)
|
||||
fmt = TARGET_DOUBLE_FORMAT;
|
||||
else if (len == TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT)
|
||||
fmt = TARGET_LONG_DOUBLE_FORMAT;
|
||||
|
||||
if (floatformat_is_nan (fmt, valaddr))
|
||||
{
|
||||
unsigned long low, high;
|
||||
/* Is the sign bit 0? */
|
||||
int nonnegative;
|
||||
/* Is it is a NaN (i.e. the exponent is all ones and
|
||||
the fraction is nonzero)? */
|
||||
int is_nan;
|
||||
|
||||
/* For lint, initialize these two variables to suppress warning: */
|
||||
low = high = nonnegative = 0;
|
||||
if (len == 4)
|
||||
{
|
||||
/* It's single precision. */
|
||||
/* Assume that floating point byte order is the same as
|
||||
integer byte order. */
|
||||
low = extract_unsigned_integer (valaddr, 4);
|
||||
nonnegative = ((low & 0x80000000) == 0);
|
||||
is_nan = ((((low >> 23) & 0xFF) == 0xFF)
|
||||
&& 0 != (low & 0x7FFFFF));
|
||||
low &= 0x7fffff;
|
||||
high = 0;
|
||||
}
|
||||
else if (len == 8)
|
||||
{
|
||||
/* It's double precision. Get the high and low words. */
|
||||
|
||||
/* Assume that floating point byte order is the same as
|
||||
integer byte order. */
|
||||
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
|
||||
{
|
||||
low = extract_unsigned_integer (valaddr + 4, 4);
|
||||
high = extract_unsigned_integer (valaddr, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
low = extract_unsigned_integer (valaddr, 4);
|
||||
high = extract_unsigned_integer (valaddr + 4, 4);
|
||||
}
|
||||
nonnegative = ((high & 0x80000000) == 0);
|
||||
is_nan = (((high >> 20) & 0x7ff) == 0x7ff
|
||||
&& !((((high & 0xfffff) == 0)) && (low == 0)));
|
||||
high &= 0xfffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef TARGET_ANALYZE_FLOATING
|
||||
TARGET_ANALYZE_FLOATING;
|
||||
#else
|
||||
/* Extended. We can't detect extended NaNs for this target.
|
||||
Also note that currently extendeds get nuked to double in
|
||||
REGISTER_CONVERTIBLE. */
|
||||
is_nan = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (is_nan)
|
||||
{
|
||||
/* The meaning of the sign and fraction is not defined by IEEE.
|
||||
But the user might know what they mean. For example, they
|
||||
(in an implementation-defined manner) distinguish between
|
||||
signaling and quiet NaN's. */
|
||||
if (high)
|
||||
fprintf_filtered (stream, "-NaN(0x%lx%.8lx)" + !!nonnegative,
|
||||
high, low);
|
||||
else
|
||||
fprintf_filtered (stream, "-NaN(0x%lx)" + nonnegative, low);
|
||||
return;
|
||||
}
|
||||
if (floatformat_is_negative (fmt, valaddr))
|
||||
fprintf_filtered (stream, "-");
|
||||
fprintf_filtered (stream, "nan(");
|
||||
fprintf_filtered (stream, local_hex_format_prefix ());
|
||||
fprintf_filtered (stream, floatformat_mantissa (fmt, valaddr));
|
||||
fprintf_filtered (stream, local_hex_format_suffix ());
|
||||
fprintf_filtered (stream, ")");
|
||||
return;
|
||||
}
|
||||
|
||||
doub = unpack_double (type, valaddr, &inv);
|
||||
@ -633,6 +581,9 @@ print_floating (char *valaddr, struct type *type, struct ui_file *stream)
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: kettenis/2001-01-20: The following code makes too much
|
||||
assumptions about the host and target floating point format. */
|
||||
|
||||
if (len < sizeof (double))
|
||||
fprintf_filtered (stream, "%.9g", (double) doub);
|
||||
else if (len == sizeof (double))
|
||||
@ -641,7 +592,8 @@ print_floating (char *valaddr, struct type *type, struct ui_file *stream)
|
||||
#ifdef PRINTF_HAS_LONG_DOUBLE
|
||||
fprintf_filtered (stream, "%.35Lg", doub);
|
||||
#else
|
||||
/* This at least wins with values that are representable as doubles */
|
||||
/* This at least wins with values that are representable as
|
||||
doubles. */
|
||||
fprintf_filtered (stream, "%.17g", (double) doub);
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user