Index: binutils-gdb/gdb/gdbarch.sh
===================================================================
--- binutils-gdb.orig/gdb/gdbarch.sh	2016-08-25 13:11:36.762781562 +0200
+++ binutils-gdb/gdb/gdbarch.sh	2016-08-25 13:11:52.524850596 +0200
@@ -383,6 +383,11 @@ v:const struct floatformat **:double_for
 v:int:long_double_bit:::8 * sizeof (long double):8*TARGET_CHAR_BIT::0
 v:const struct floatformat **:long_double_format:::::floatformats_ieee_double::pformat (gdbarch->long_double_format)
 
+# Returns the floating-point format to be used for values of length LENGTH.
+# NAME, if non-NULL, is the type name, which may be used to distinguish
+# different target formats of the same length.
+m:const struct floatformat **:floatformat_for_type:const char *name, int length:name, length:0:default_floatformat_for_type::0
+
 # For most targets, a pointer on the target and its representation as an
 # address in GDB have the same size and "look the same".  For such a
 # target, you need only set gdbarch_ptr_bit and gdbarch_addr_bit
Index: binutils-gdb/gdb/gdbarch.h
===================================================================
--- binutils-gdb.orig/gdb/gdbarch.h	2016-08-25 13:11:36.762781562 +0200
+++ binutils-gdb/gdb/gdbarch.h	2016-08-25 13:11:52.527850608 +0200
@@ -187,6 +187,14 @@ extern void set_gdbarch_long_double_bit 
 extern const struct floatformat ** gdbarch_long_double_format (struct gdbarch *gdbarch);
 extern void set_gdbarch_long_double_format (struct gdbarch *gdbarch, const struct floatformat ** long_double_format);
 
+/* Returns the floating-point format to be used for values of length LENGTH.
+   NAME, if non-NULL, is the type name, which may be used to distinguish
+   different target formats of the same length. */
+
+typedef const struct floatformat ** (gdbarch_floatformat_for_type_ftype) (struct gdbarch *gdbarch, const char *name, int length);
+extern const struct floatformat ** gdbarch_floatformat_for_type (struct gdbarch *gdbarch, const char *name, int length);
+extern void set_gdbarch_floatformat_for_type (struct gdbarch *gdbarch, gdbarch_floatformat_for_type_ftype *floatformat_for_type);
+
 /* For most targets, a pointer on the target and its representation as an
    address in GDB have the same size and "look the same".  For such a
    target, you need only set gdbarch_ptr_bit and gdbarch_addr_bit
Index: binutils-gdb/gdb/gdbarch.c
===================================================================
--- binutils-gdb.orig/gdb/gdbarch.c	2016-08-25 13:11:36.762781562 +0200
+++ binutils-gdb/gdb/gdbarch.c	2016-08-25 13:11:52.529850616 +0200
@@ -176,6 +176,7 @@ struct gdbarch
   const struct floatformat ** double_format;
   int long_double_bit;
   const struct floatformat ** long_double_format;
+  gdbarch_floatformat_for_type_ftype *floatformat_for_type;
   int ptr_bit;
   int addr_bit;
   int dwarf2_addr_size;
@@ -376,6 +377,7 @@ gdbarch_alloc (const struct gdbarch_info
   gdbarch->float_bit = 4*TARGET_CHAR_BIT;
   gdbarch->double_bit = 8*TARGET_CHAR_BIT;
   gdbarch->long_double_bit = 8*TARGET_CHAR_BIT;
+  gdbarch->floatformat_for_type = default_floatformat_for_type;
   gdbarch->ptr_bit = gdbarch->int_bit;
   gdbarch->char_signed = -1;
   gdbarch->virtual_frame_pointer = legacy_virtual_frame_pointer;
@@ -522,6 +524,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of long_double_bit, invalid_p == 0 */
   if (gdbarch->long_double_format == 0)
     gdbarch->long_double_format = floatformats_ieee_double;
+  /* Skip verify of floatformat_for_type, invalid_p == 0 */
   /* Skip verify of ptr_bit, invalid_p == 0 */
   if (gdbarch->addr_bit == 0)
     gdbarch->addr_bit = gdbarch_ptr_bit (gdbarch);
@@ -973,6 +976,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                       "gdbarch_dump: float_format = %s\n",
                       pformat (gdbarch->float_format));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: floatformat_for_type = <%s>\n",
+                      host_address_to_string (gdbarch->floatformat_for_type));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: fp0_regnum = %s\n",
                       plongest (gdbarch->fp0_regnum));
   fprintf_unfiltered (file,
@@ -1729,6 +1735,23 @@ set_gdbarch_long_double_format (struct g
   gdbarch->long_double_format = long_double_format;
 }
 
+const struct floatformat **
+gdbarch_floatformat_for_type (struct gdbarch *gdbarch, const char *name, int length)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->floatformat_for_type != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_floatformat_for_type called\n");
+  return gdbarch->floatformat_for_type (gdbarch, name, length);
+}
+
+void
+set_gdbarch_floatformat_for_type (struct gdbarch *gdbarch,
+                                  gdbarch_floatformat_for_type_ftype floatformat_for_type)
+{
+  gdbarch->floatformat_for_type = floatformat_for_type;
+}
+
 int
 gdbarch_ptr_bit (struct gdbarch *gdbarch)
 {
Index: binutils-gdb/gdb/arch-utils.h
===================================================================
--- binutils-gdb.orig/gdb/arch-utils.h	2016-08-25 13:11:36.762781562 +0200
+++ binutils-gdb/gdb/arch-utils.h	2016-08-25 13:11:52.533850634 +0200
@@ -95,6 +95,11 @@ int cannot_register_not (struct gdbarch 
 
 extern gdbarch_virtual_frame_pointer_ftype legacy_virtual_frame_pointer;
 
+/* Default implementation of gdbarch_floatformat_for_type.  */
+extern const struct floatformat **
+  default_floatformat_for_type (struct gdbarch *gdbarch,
+				const char *name, int len);
+
 extern CORE_ADDR generic_skip_trampoline_code (struct frame_info *frame,
 					       CORE_ADDR pc);
 
Index: binutils-gdb/gdb/arch-utils.c
===================================================================
--- binutils-gdb.orig/gdb/arch-utils.c	2016-08-25 13:11:36.762781562 +0200
+++ binutils-gdb/gdb/arch-utils.c	2016-08-25 13:11:52.537850652 +0200
@@ -241,6 +241,34 @@ legacy_virtual_frame_pointer (struct gdb
   *frame_offset = 0;
 }
 
+/* Return a floating-point format for a floating-point variable of
+   length LEN in bits.  If non-NULL, NAME is the name of its type.
+   If no suitable type is found, return NULL.  */
+
+const struct floatformat **
+default_floatformat_for_type (struct gdbarch *gdbarch,
+			      const char *name, int len)
+{
+  const struct floatformat **format = NULL;
+
+  if (len == gdbarch_half_bit (gdbarch))
+    format = gdbarch_half_format (gdbarch);
+  else if (len == gdbarch_float_bit (gdbarch))
+    format = gdbarch_float_format (gdbarch);
+  else if (len == gdbarch_double_bit (gdbarch))
+    format = gdbarch_double_format (gdbarch);
+  else if (len == gdbarch_long_double_bit (gdbarch))
+    format = gdbarch_long_double_format (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 (gdbarch_long_double_format (gdbarch) != NULL
+	   && len == gdbarch_long_double_format (gdbarch)[0]->totalsize)
+    format = gdbarch_long_double_format (gdbarch);
+
+  return format;
+}
 
 int
 generic_convert_register_p (struct gdbarch *gdbarch, int regnum,
Index: binutils-gdb/gdb/doublest.c
===================================================================
--- binutils-gdb.orig/gdb/doublest.c	2016-08-25 13:11:36.762781562 +0200
+++ binutils-gdb/gdb/doublest.c	2016-08-25 13:11:52.541850668 +0200
@@ -770,52 +770,8 @@ floatformat_from_doublest (const struct 
 }
 
 
-/* Return a floating-point format for a floating-point variable of
-   length LEN.  If no suitable floating-point format is found, an
-   error is thrown.
-
-   We need this functionality since information about the
-   floating-point format of a type is not always available to GDB; the
-   debug information typically only tells us the size of a
-   floating-point type.
-
-   FIXME: kettenis/2001-10-28: In many places, particularly in
-   target-dependent code, the format of floating-point types is known,
-   but not passed on by GDB.  This should be fixed.  */
-
-static const struct floatformat *
-floatformat_from_length (struct gdbarch *gdbarch, int len)
-{
-  const struct floatformat *format;
-
-  if (len * TARGET_CHAR_BIT == gdbarch_half_bit (gdbarch))
-    format = gdbarch_half_format (gdbarch)
-	       [gdbarch_byte_order (gdbarch)];
-  else if (len * TARGET_CHAR_BIT == gdbarch_float_bit (gdbarch))
-    format = gdbarch_float_format (gdbarch)
-	       [gdbarch_byte_order (gdbarch)];
-  else if (len * TARGET_CHAR_BIT == gdbarch_double_bit (gdbarch))
-    format = gdbarch_double_format (gdbarch)
-	       [gdbarch_byte_order (gdbarch)];
-  else if (len * TARGET_CHAR_BIT == gdbarch_long_double_bit (gdbarch))
-    format = gdbarch_long_double_format (gdbarch)
-	       [gdbarch_byte_order (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 ((gdbarch_long_double_format (gdbarch) != NULL)
-	   && (len * TARGET_CHAR_BIT
-               == gdbarch_long_double_format (gdbarch)[0]->totalsize))
-    format = gdbarch_long_double_format (gdbarch)
-	       [gdbarch_byte_order (gdbarch)];
-  else
-    format = NULL;
-  if (format == NULL)
-    error (_("Unrecognized %d-bit floating-point type."),
-	   len * TARGET_CHAR_BIT);
-  return format;
-}
+/* Return the floating-point format for a floating-point variable of
+   type TYPE.  */
 
 const struct floatformat *
 floatformat_from_type (const struct type *type)
@@ -824,11 +780,8 @@ floatformat_from_type (const struct type
   const struct floatformat *fmt;
 
   gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
-  if (TYPE_FLOATFORMAT (type) != NULL)
-    fmt = TYPE_FLOATFORMAT (type)[gdbarch_byte_order (gdbarch)];
-  else
-    fmt = floatformat_from_length (gdbarch, TYPE_LENGTH (type));
-
+  gdb_assert (TYPE_FLOATFORMAT (type));
+  fmt = TYPE_FLOATFORMAT (type)[gdbarch_byte_order (gdbarch)];
   gdb_assert (TYPE_LENGTH (type) >= floatformat_totalsize_bytes (fmt));
   return fmt;
 }
Index: binutils-gdb/gdb/gdbtypes.c
===================================================================
--- binutils-gdb.orig/gdb/gdbtypes.c	2016-08-25 13:11:50.766842886 +0200
+++ binutils-gdb/gdb/gdbtypes.c	2016-08-25 13:11:52.546850692 +0200
@@ -2712,21 +2712,16 @@ set_type_code (struct type *type, enum t
 static int
 verify_floatformat (int bit, const struct floatformat **floatformats)
 {
+  gdb_assert (floatformats != NULL);
+  gdb_assert (floatformats[0] != NULL && floatformats[1] != NULL);
+
   if (bit == -1)
-    {
-      gdb_assert (floatformats != NULL);
-      gdb_assert (floatformats[0] != NULL && floatformats[1] != NULL);
-      bit = floatformats[0]->totalsize;
-    }
+    bit = floatformats[0]->totalsize;
   gdb_assert (bit >= 0);
 
-  if (floatformats != NULL)
-    {
-      size_t len = bit / TARGET_CHAR_BIT;
-
-      gdb_assert (len >= floatformat_totalsize_bytes (floatformats[0]));
-      gdb_assert (len >= floatformat_totalsize_bytes (floatformats[1]));
-    }
+  size_t len = bit / TARGET_CHAR_BIT;
+  gdb_assert (len >= floatformat_totalsize_bytes (floatformats[0]));
+  gdb_assert (len >= floatformat_totalsize_bytes (floatformats[1]));
 
   return bit;
 }
Index: binutils-gdb/gdb/dwarf2read.c
===================================================================
--- binutils-gdb.orig/gdb/dwarf2read.c	2016-08-25 13:11:49.268836321 +0200
+++ binutils-gdb/gdb/dwarf2read.c	2016-08-25 13:11:52.556850735 +0200
@@ -14757,6 +14757,27 @@ read_typedef (struct die_info *die, stru
   return this_type;
 }
 
+/* Allocate a floating-point type of size BITS and name NAME.  Pass NAME_HINT
+   (which may be different from NAME) to the architecture back-end to allow
+   it to guess the correct format if necessary.  */
+
+static struct type *
+dwarf2_init_float_type (struct objfile *objfile, int bits, const char *name,
+			const char *name_hint)
+{
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  const struct floatformat **format;
+  struct type *type;
+
+  format = gdbarch_floatformat_for_type (gdbarch, name_hint, bits);
+  if (format)
+    type = init_float_type (objfile, bits, name, format);
+  else
+    type = init_type (objfile, TYPE_CODE_ERROR, bits / TARGET_CHAR_BIT, name);
+
+  return type;
+}
+
 /* Find a representation of a given base type and install
    it in the TYPE field of the die.  */
 
@@ -14797,14 +14818,14 @@ read_base_type (struct die_info *die, st
 	type = init_boolean_type (objfile, bits, 1, name);
 	break;
       case DW_ATE_complex_float:
-	type = init_float_type (objfile, bits / 2, NULL, NULL);
+	type = dwarf2_init_float_type (objfile, bits / 2, NULL, name);
 	type = init_complex_type (objfile, name, type);
 	break;
       case DW_ATE_decimal_float:
 	type = init_decfloat_type (objfile, bits, name);
 	break;
       case DW_ATE_float:
-	type = init_float_type (objfile, bits, name, NULL);
+	type = dwarf2_init_float_type (objfile, bits, name, name);
 	break;
       case DW_ATE_signed:
 	type = init_integer_type (objfile, bits, 0, name);
Index: binutils-gdb/gdb/stabsread.c
===================================================================
--- binutils-gdb.orig/gdb/stabsread.c	2016-08-25 13:11:51.623846644 +0200
+++ binutils-gdb/gdb/stabsread.c	2016-08-25 13:11:52.562850760 +0200
@@ -353,6 +353,24 @@ dbx_alloc_type (int typenums[2], struct 
   return (*type_addr);
 }
 
+/* Allocate a floating-point type of size BITS.  */
+
+static struct type *
+dbx_init_float_type (struct objfile *objfile, int bits)
+{
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  const struct floatformat **format;
+  struct type *type;
+
+  format = gdbarch_floatformat_for_type (gdbarch, NULL, bits);
+  if (format)
+    type = init_float_type (objfile, bits, NULL, format);
+  else
+    type = init_type (objfile, TYPE_CODE_ERROR, bits / TARGET_CHAR_BIT, NULL);
+
+  return type;
+}
+
 /* for all the stabs in a given stab vector, build appropriate types 
    and fix their symbols in given symbol vector.  */
 
@@ -3847,11 +3865,11 @@ read_sun_floating_type (char **pp, int t
   if (details == NF_COMPLEX || details == NF_COMPLEX16
       || details == NF_COMPLEX32)
     {
-      rettype = init_float_type (objfile, nbits / 2, NULL, NULL);
+      rettype = dbx_init_float_type (objfile, nbits / 2);
       return init_complex_type (objfile, NULL, rettype);
     }
 
-  return init_float_type (objfile, nbits, NULL, NULL);
+  return dbx_init_float_type (objfile, nbits);
 }
 
 /* Read a number from the string pointed to by *PP.
@@ -4138,7 +4156,7 @@ read_range_type (char **pp, int typenums
   if (n3 == 0 && n2 > 0)
     {
       struct type *float_type
-	= init_float_type (objfile, n2 * TARGET_CHAR_BIT, NULL, NULL);
+	= dbx_init_float_type (objfile, n2 * TARGET_CHAR_BIT);
 
       if (self_subrange)
 	return init_complex_type (objfile, NULL, float_type);
