* arm-tdep.c (arm_use_struct_convention): Look through typedefs.
[deliverable/binutils-gdb.git] / gdb / doublest.c
index 083a50a98aa1f2dc4570f2a9c6d1ec64b2f95bc4..3f283e13ffa55842eba72b08a4515b52fe0ca38e 100644 (file)
@@ -1,7 +1,8 @@
 /* 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.
 
@@ -172,8 +173,10 @@ convert_floatformat_to_doublest (const struct floatformat *fmt,
 
   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)
@@ -401,7 +404,15 @@ convert_doublest_to_floatformat (CONST struct floatformat *fmt,
        {
          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)
@@ -439,7 +450,7 @@ int
 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);
 }
 
@@ -454,6 +465,8 @@ floatformat_is_nan (const struct floatformat *fmt, char *val)
   unsigned int mant_bits, mant_off;
   int mant_bits_left;
 
+  gdb_assert (fmt != NULL);
+
   if (! fmt->exp_nan)
     return 0;
 
@@ -503,6 +516,7 @@ floatformat_mantissa (const struct floatformat *fmt, char *val)
   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;
@@ -628,10 +642,28 @@ floatformat_from_length (int len)
     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;
 }
 
+const struct floatformat *
+floatformat_from_type (const struct type *type)
+{
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
+  if (TYPE_FLOATFORMAT (type) != NULL)
+    return TYPE_FLOATFORMAT (type);
+  else
+    return floatformat_from_length (TYPE_LENGTH (type));
+}
+
 /* If the host doesn't define NAN, use zero instead.  */
 #ifndef NAN
 #define NAN 0.0
@@ -640,15 +672,15 @@ floatformat_from_length (int len)
 /* 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;
     }
 
@@ -656,11 +688,17 @@ extract_floating (const void *addr, int len)
   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);
 
@@ -668,11 +706,18 @@ store_floating (void *addr, int len, DOUBLEST val)
     {
       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.  */
 
@@ -684,7 +729,9 @@ extract_typed_floating (const void *addr, const struct type *type)
   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;
@@ -719,9 +766,11 @@ store_typed_floating (void *addr, const struct type *type, DOUBLEST val)
   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
@@ -732,19 +781,12 @@ void
 convert_typed_floating (const void *from, const struct type *from_type,
                         void *to, const struct type *to_type)
 {
-  const struct floatformat *from_fmt = TYPE_FLOATFORMAT (from_type);
-  const struct floatformat *to_fmt = TYPE_FLOATFORMAT (to_type);
+  const struct floatformat *from_fmt = floatformat_from_type (from_type);
+  const struct floatformat *to_fmt = floatformat_from_type (to_type);
 
   gdb_assert (TYPE_CODE (from_type) == TYPE_CODE_FLT);
   gdb_assert (TYPE_CODE (to_type) == TYPE_CODE_FLT);
 
-  /* If the floating-point format of FROM_TYPE or TO_TYPE isn't known,
-     try to guess it from the type's length.  */
-  if (from_fmt == NULL)
-    from_fmt = floatformat_from_length (TYPE_LENGTH (from_type));
-  if (to_fmt == NULL)
-    to_fmt = floatformat_from_length (TYPE_LENGTH (to_type));
-
   if (from_fmt == NULL || to_fmt == NULL)
     {
       /* If we don't know the floating-point format of FROM_TYPE or
This page took 0.025413 seconds and 4 git commands to generate.