/* Floating point routines for GDB, the GNU debugger.
- Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
- 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
+
+ Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+ 1996, 1997, 1998, 1999, 2000, 2001, 2003 Free Software Foundation,
+ Inc.
This file is part of GDB.
special_exponent = exponent == 0 || exponent == fmt->exp_nan;
-/* Don't bias NaNs. Use minimum exponent for denorms. For simplicity,
- we don't check for zero as the exponent doesn't matter. */
+ /* Don't bias NaNs. Use minimum exponent for denorms. For simplicity,
+ we don't check for zero as the exponent doesn't matter. Note the cast
+ to int; exp_bias is unsigned, so it's important to make sure the
+ operation is done in signed arithmetic. */
if (!special_exponent)
exponent -= fmt->exp_bias;
else if (exponent == 0)
{
mant_long <<= 1;
mant_long &= 0xffffffffL;
- mant_bits -= 1;
+ /* If we are processing the top 32 mantissa bits of a doublest
+ so as to convert to a float value with implied integer bit,
+ we will only be putting 31 of those 32 bits into the
+ final value due to the discarding of the top bit. In the
+ case of a small float value where the number of mantissa
+ bits is less than 32, discarding the top bit does not alter
+ the number of bits we will be adding to the result. */
+ if (mant_bits == 32)
+ mant_bits -= 1;
}
if (mant_bits < 32)
floatformat_is_negative (const struct floatformat *fmt, char *val)
{
unsigned char *uval = (unsigned char *) val;
-
+ gdb_assert (fmt != NULL);
return get_field (uval, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1);
}
unsigned int mant_bits, mant_off;
int mant_bits_left;
+ gdb_assert (fmt != NULL);
+
if (! fmt->exp_nan)
return 0;
char buf[9];
/* Make sure we have enough room to store the mantissa. */
+ gdb_assert (fmt != NULL);
gdb_assert (sizeof res > ((fmt->man_len + 7) / 8) * 2);
mant_off = fmt->man_start;
target-dependent code, the format of floating-point types is known,
but not passed on by GDB. This should be fixed. */
-const struct floatformat *
+static const struct floatformat *
floatformat_from_length (int len)
{
if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT)
return TARGET_DOUBLE_FORMAT;
else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT)
return TARGET_LONG_DOUBLE_FORMAT;
+ /* On i386 the 'long double' type takes 96 bits,
+ while the real number of used bits is only 80,
+ both in processor and in memory.
+ The code below accepts the real bit size. */
+ else if ((TARGET_LONG_DOUBLE_FORMAT != NULL)
+ && (len * TARGET_CHAR_BIT ==
+ TARGET_LONG_DOUBLE_FORMAT->totalsize))
+ return TARGET_LONG_DOUBLE_FORMAT;
return NULL;
}
/* Extract a floating-point number of length LEN from a target-order
byte-stream at ADDR. Returns the value as type DOUBLEST. */
-DOUBLEST
-extract_floating (const void *addr, int len)
+static DOUBLEST
+extract_floating_by_length (const void *addr, int len)
{
const struct floatformat *fmt = floatformat_from_length (len);
DOUBLEST val;
if (fmt == NULL)
{
- warning ("Can't store a floating-point number of %d bytes.", len);
+ warning ("Can't extract a floating-point number of %d bytes.", len);
return NAN;
}
return val;
}
+DOUBLEST
+deprecated_extract_floating (const void *addr, int len)
+{
+ return extract_floating_by_length (addr, len);
+}
+
/* Store VAL as a floating-point number of length LEN to a
target-order byte-stream at ADDR. */
-void
-store_floating (void *addr, int len, DOUBLEST val)
+static void
+store_floating_by_length (void *addr, int len, DOUBLEST val)
{
const struct floatformat *fmt = floatformat_from_length (len);
{
warning ("Can't store a floating-point number of %d bytes.", len);
memset (addr, 0, len);
+ return;
}
floatformat_from_doublest (fmt, &val, addr);
}
+void
+deprecated_store_floating (void *addr, int len, DOUBLEST val)
+{
+ store_floating_by_length (addr, len, val);
+}
+
/* Extract a floating-point number of type TYPE from a target-order
byte-stream at ADDR. Returns the value as type DOUBLEST. */
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
if (TYPE_FLOATFORMAT (type) == NULL)
- return extract_floating (addr, TYPE_LENGTH (type));
+ /* Not all code remembers to set the FLOATFORMAT (language
+ specific code? stabs?) so handle that here as a special case. */
+ return extract_floating_by_length (addr, TYPE_LENGTH (type));
floatformat_to_doublest (TYPE_FLOATFORMAT (type), addr, &retval);
return retval;
memset (addr, 0, TYPE_LENGTH (type));
if (TYPE_FLOATFORMAT (type) == NULL)
- return store_floating (addr, TYPE_LENGTH (type), val);
-
- floatformat_from_doublest (TYPE_FLOATFORMAT (type), &val, addr);
+ /* Not all code remembers to set the FLOATFORMAT (language
+ specific code? stabs?) so handle that here as a special case. */
+ store_floating_by_length (addr, TYPE_LENGTH (type), val);
+ else
+ floatformat_from_doublest (TYPE_FLOATFORMAT (type), &val, addr);
}
/* Convert a floating-point number of type FROM_TYPE from a