* gdbarch.sh (software_single_step): Replace REGCACHE argument by
[deliverable/binutils-gdb.git] / gdb / doublest.c
index 3b640f5519d0331f29492f9013130ad6d76d6b89..f05740d0eb9b44b46dd6285b9902afe4d63af038 100644 (file)
@@ -180,10 +180,23 @@ convert_floatformat_to_doublest (const struct floatformat *fmt,
   int special_exponent;                /* It's a NaN, denorm or zero */
   enum floatformat_byteorders order;
   unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES];
+  enum float_kind kind;
   
   gdb_assert (fmt->totalsize
              <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
 
+  /* For non-numbers, reuse libiberty's logic to find the correct
+     format.  We do not lose any precision in this case by passing
+     through a double.  */
+  kind = floatformat_classify (fmt, from);
+  if (kind == float_infinite || kind == float_nan)
+    {
+      double dto;
+      floatformat_to_double (fmt, from, &dto);
+      *to = (DOUBLEST) dto;
+      return;
+    }
+
   order = floatformat_normalize_byteorder (fmt, ufrom, newfrom);
 
   if (order != fmt->byteorder)
@@ -495,9 +508,9 @@ floatformat_is_negative (const struct floatformat *fmt,
 
 /* Check if VAL is "not a number" (NaN) for FMT.  */
 
-int
-floatformat_is_nan (const struct floatformat *fmt,
-                   const bfd_byte *uval)
+enum float_kind
+floatformat_classify (const struct floatformat *fmt,
+                     const bfd_byte *uval)
 {
   long exponent;
   unsigned long mant;
@@ -505,6 +518,7 @@ floatformat_is_nan (const struct floatformat *fmt,
   int mant_bits_left;
   enum floatformat_byteorders order;
   unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES];
+  int mant_zero;
   
   gdb_assert (fmt != NULL);
   gdb_assert (fmt->totalsize
@@ -515,18 +529,13 @@ floatformat_is_nan (const struct floatformat *fmt,
   if (order != fmt->byteorder)
     uval = newfrom;
 
-  if (! fmt->exp_nan)
-    return 0;
-
   exponent = get_field (uval, order, 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;
 
+  mant_zero = 1;
   while (mant_bits_left > 0)
     {
       mant_bits = min (mant_bits_left, 32);
@@ -539,13 +548,40 @@ floatformat_is_nan (const struct floatformat *fmt,
        mant &= ~(1 << (mant_bits - 1));
 
       if (mant)
-       return 1;
+       {
+         mant_zero = 0;
+         break;
+       }
 
       mant_off += mant_bits;
       mant_bits_left -= mant_bits;
     }
 
-  return 0;
+  /* If exp_nan is not set, assume that inf, NaN, and subnormals are not
+     supported.  */
+  if (! fmt->exp_nan)
+    {
+      if (mant_zero)
+       return float_zero;
+      else
+       return float_normal;
+    }
+
+  if (exponent == 0 && !mant_zero)
+    return float_subnormal;
+
+  if (exponent == fmt->exp_nan)
+    {
+      if (mant_zero)
+       return float_infinite;
+      else
+       return float_nan;
+    }
+
+  if (mant_zero)
+    return float_zero;
+
+  return float_normal;
 }
 
 /* Convert the mantissa of VAL (which is assumed to be a floating
@@ -688,20 +724,24 @@ static const struct floatformat *
 floatformat_from_length (int len)
 {
   const struct floatformat *format;
-  if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT)
-    format = TARGET_FLOAT_FORMAT[TARGET_BYTE_ORDER];
-  else if (len * TARGET_CHAR_BIT == TARGET_DOUBLE_BIT)
-    format = TARGET_DOUBLE_FORMAT[TARGET_BYTE_ORDER];
-  else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT)
-    format = TARGET_LONG_DOUBLE_FORMAT[TARGET_BYTE_ORDER];
+  if (len * TARGET_CHAR_BIT == gdbarch_float_bit (current_gdbarch))
+    format = gdbarch_float_format (current_gdbarch)
+              [gdbarch_byte_order (current_gdbarch)];
+  else if (len * TARGET_CHAR_BIT == gdbarch_double_bit (current_gdbarch))
+    format = gdbarch_double_format (current_gdbarch)
+              [gdbarch_byte_order (current_gdbarch)];
+  else if (len * TARGET_CHAR_BIT == gdbarch_long_double_bit (current_gdbarch))
+    format = gdbarch_long_double_format (current_gdbarch)
+              [gdbarch_byte_order (current_gdbarch)];
   /* 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) 
+  else if ((gdbarch_long_double_format (current_gdbarch) != NULL) 
           && (len * TARGET_CHAR_BIT ==
-               TARGET_LONG_DOUBLE_FORMAT[0]->totalsize))
-    format = TARGET_LONG_DOUBLE_FORMAT[TARGET_BYTE_ORDER];
+               gdbarch_long_double_format (current_gdbarch)[0]->totalsize))
+    format = gdbarch_long_double_format (current_gdbarch)
+              [gdbarch_byte_order (current_gdbarch)];
   else
     format = NULL;
   if (format == NULL)
@@ -715,7 +755,7 @@ floatformat_from_type (const struct type *type)
 {
   gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
   if (TYPE_FLOATFORMAT (type) != NULL)
-    return TYPE_FLOATFORMAT (type)[TARGET_BYTE_ORDER];
+    return TYPE_FLOATFORMAT (type)[gdbarch_byte_order (current_gdbarch)];
   else
     return floatformat_from_length (TYPE_LENGTH (type));
 }
@@ -776,7 +816,8 @@ extract_typed_floating (const void *addr, const struct type *type)
        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)[TARGET_BYTE_ORDER],
+  floatformat_to_doublest 
+       (TYPE_FLOATFORMAT (type)[gdbarch_byte_order (current_gdbarch)],
                           addr, &retval);
   return retval;
 }
@@ -814,8 +855,9 @@ store_typed_floating (void *addr, const struct type *type, DOUBLEST val)
        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)[TARGET_BYTE_ORDER],
-                              &val, addr);
+    floatformat_from_doublest
+       (TYPE_FLOATFORMAT (type)[gdbarch_byte_order (current_gdbarch)],
+       &val, addr);
 }
 
 /* Convert a floating-point number of type FROM_TYPE from a
This page took 0.027861 seconds and 4 git commands to generate.