aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2001-03-07 16:09:03 +0000
committerMark Kettenis <kettenis@gnu.org>2001-03-07 16:09:03 +0000
commit39424bef9143202f0b7fc25b73c81db580eb253c (patch)
treeb0005bf91d34da2269e757c75722bbd9ed51139f
parentbcdd92f3e09bfbb42f46281bab7619f8c40d10a3 (diff)
downloadgdb-39424bef9143202f0b7fc25b73c81db580eb253c.zip
gdb-39424bef9143202f0b7fc25b73c81db580eb253c.tar.gz
gdb-39424bef9143202f0b7fc25b73c81db580eb253c.tar.bz2
* 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.
-rw-r--r--gdb/ChangeLog14
-rw-r--r--gdb/defs.h6
-rw-r--r--gdb/utils.c101
-rw-r--r--gdb/valprint.c106
4 files changed, 149 insertions, 78 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e3737d7..32e592f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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
diff --git a/gdb/defs.h b/gdb/defs.h
index 6974fe2..c6a4637 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -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
diff --git a/gdb/utils.c b/gdb/utils.c
index df6046a..5ece78d 100644
--- a/gdb/utils.c
+++ b/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 */
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 2a80b9c..ccd4542 100644
--- a/gdb/valprint.c
+++ b/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)
- {
- 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. */
+ /* 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. */
- /* 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 (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 (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_nan (fmt, valaddr))
+ {
+ 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
}