]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - libiberty/floatformat.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / libiberty / floatformat.c
index 07af7264df499c932b3d07662513a4a86304cc14..4feab3baaaf9050d5df394a1239beeec77d9e20a 100644 (file)
@@ -1,6 +1,5 @@
 /* IEEE floating point support routines, for GDB, the GNU Debugger.
-   Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1991-2021 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -19,7 +18,9 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /* This is needed to pick up the NAN macro on some systems.  */
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -77,7 +78,23 @@ floatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED,
    a system header, what we do if not, etc.  */
 #define FLOATFORMAT_CHAR_BIT 8
 
-/* floatformats for IEEE single and double, big and little endian.  */
+/* floatformats for IEEE half, single and double, big and little endian.  */
+const struct floatformat floatformat_ieee_half_big =
+{
+  floatformat_big, 16, 0, 1, 5, 15, 31, 6, 10,
+  floatformat_intbit_no,
+  "floatformat_ieee_half_big",
+  floatformat_always_valid,
+  NULL
+};
+const struct floatformat floatformat_ieee_half_little =
+{
+  floatformat_little, 16, 0, 1, 5, 15, 31, 6, 10,
+  floatformat_intbit_no,
+  "floatformat_ieee_half_little",
+  floatformat_always_valid,
+  NULL
+};
 const struct floatformat floatformat_ieee_single_big =
 {
   floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
@@ -283,7 +300,7 @@ floatformat_ibm_long_double_is_valid (const struct floatformat *fmt,
   bot_exp = get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize,
                       hfmt->exp_start, hfmt->exp_len);
 
-  if (top_exp == hfmt->exp_nan)
+  if ((unsigned long) top_exp == hfmt->exp_nan)
     top_nan = mant_bits_set (hfmt, ufrom);
 
   /* A NaN is valid with any low part.  */
@@ -292,11 +309,8 @@ floatformat_ibm_long_double_is_valid (const struct floatformat *fmt,
 
   /* An infinity, zero or denormal requires low part 0 (positive or
      negative).  */
-  if (top_exp == hfmt->exp_nan || top_exp == 0)
+  if ((unsigned long) top_exp == hfmt->exp_nan || top_exp == 0)
     {
-      unsigned int mant_bits, mant_off;
-      int mant_bits_left;
-
       if (bot_exp != 0)
        return 0;
 
@@ -318,7 +332,7 @@ floatformat_ibm_long_double_is_valid (const struct floatformat *fmt,
       /* The bottom part is 0 or denormal.  Determine which, and if
         denormal the first two set bits.  */
       int first_bit = -1, second_bit = -1, cur_bit;
-      for (cur_bit = 0; cur_bit < hfmt->man_len; cur_bit++)
+      for (cur_bit = 0; (unsigned int) cur_bit < hfmt->man_len; cur_bit++)
        if (get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize,
                       hfmt->man_start + cur_bit, 1))
          {
@@ -358,15 +372,41 @@ floatformat_ibm_long_double_is_valid (const struct floatformat *fmt,
     }
 }
 
-const struct floatformat floatformat_ibm_long_double =
+const struct floatformat floatformat_ibm_long_double_big =
 {
   floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52,
   floatformat_intbit_no,
-  "floatformat_ibm_long_double",
-  floatformat_always_valid,
+  "floatformat_ibm_long_double_big",
+  floatformat_ibm_long_double_is_valid,
   &floatformat_ieee_double_big
 };
-\f
+
+const struct floatformat floatformat_ibm_long_double_little =
+{
+  floatformat_little, 128, 0, 1, 11, 1023, 2047, 12, 52,
+  floatformat_intbit_no,
+  "floatformat_ibm_long_double_little",
+  floatformat_ibm_long_double_is_valid,
+  &floatformat_ieee_double_little
+};
+
+const struct floatformat floatformat_bfloat16_big =
+{
+  floatformat_big, 16, 0, 1, 8, 127, 255, 9, 7,
+  floatformat_intbit_no,
+  "floatformat_bfloat16_big",
+  floatformat_always_valid,
+  NULL
+};
+
+const struct floatformat floatformat_bfloat16_little =
+{
+  floatformat_little, 16, 0, 1, 8, 127, 255, 9, 7,
+  floatformat_intbit_no,
+  "floatformat_bfloat16_little",
+  floatformat_always_valid,
+  NULL
+};
 
 #ifndef min
 #define min(a, b) ((a) < (b) ? (a) : (b))
@@ -450,7 +490,6 @@ floatformat_to_double (const struct floatformat *fmt,
   unsigned long mant;
   unsigned int mant_bits, mant_off;
   int mant_bits_left;
-  int special_exponent;                /* It's a NaN, denorm or zero */
 
   /* Split values are not handled specially, since the top half has
      the correctly rounded double value (in the only supported case of
@@ -467,7 +506,7 @@ floatformat_to_double (const struct floatformat *fmt,
       int nan = mant_bits_set (fmt, ufrom);
 
       /* On certain systems (such as GNU/Linux), the use of the
-        INFINITY macro below may generate a warning that can not be
+        INFINITY macro below may generate a warning that cannot be
         silenced due to a bug in GCC (PR preprocessor/11931).  The
         preprocessor fails to recognise the __extension__ keyword in
         conjunction with the GNU/C99 extension for hexadecimal
@@ -490,20 +529,20 @@ floatformat_to_double (const struct floatformat *fmt,
   mant_off = fmt->man_start;
   dto = 0.0;
 
-  special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;
-
-  /* Don't bias zero's, denorms or NaNs.  */
-  if (!special_exponent)
-    exponent -= fmt->exp_bias;
-
   /* Build the result algebraically.  Might go infinite, underflow, etc;
      who cares. */
 
-  /* If this format uses a hidden bit, explicitly add it in now.  Otherwise,
-     increment the exponent by one to account for the integer bit.  */
-
-  if (!special_exponent)
+  /* For denorms use minimum exponent.  */
+  if (exponent == 0)
+    exponent = 1 - fmt->exp_bias;
+  else
     {
+      exponent -= fmt->exp_bias;
+
+      /* If this format uses a hidden bit, explicitly add it in now.
+        Otherwise, increment the exponent by one to account for the
+        integer bit.  */
+
       if (fmt->intbit == floatformat_intbit_no)
        dto = ldexp (1.0, exponent);
       else
@@ -517,18 +556,8 @@ floatformat_to_double (const struct floatformat *fmt,
       mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
                         mant_off, mant_bits);
 
-      /* Handle denormalized numbers.  FIXME: What should we do for
-        non-IEEE formats?  */
-      if (special_exponent && exponent == 0 && mant != 0)
-       dto += ldexp ((double)mant,
-                     (- fmt->exp_bias
-                      - mant_bits
-                      - (mant_off - fmt->man_start)
-                      + 1));
-      else
-       dto += ldexp ((double)mant, exponent - mant_bits);
-      if (exponent != 0)
-       exponent -= mant_bits;
+      dto += ldexp ((double) mant, exponent - mant_bits);
+      exponent -= mant_bits;
       mant_off += mant_bits;
       mant_bits_left -= mant_bits;
     }
@@ -743,6 +772,7 @@ main (void)
 {
   ieee_test (0.0);
   ieee_test (0.5);
+  ieee_test (1.1);
   ieee_test (256.0);
   ieee_test (0.12345);
   ieee_test (234235.78907234);