Index: binutils-gdb/gdb/doublest.c
===================================================================
--- binutils-gdb.orig/gdb/doublest.c
+++ binutils-gdb/gdb/doublest.c
@@ -680,6 +680,25 @@ floatformat_mantissa (const struct float
   return res;
 }
 
+/* Return the precision of the floating point format FMT.  */
+
+static int
+floatformat_precision (const struct floatformat *fmt)
+{
+  /* Assume the precision of and IBM long double is twice the precision
+     of the underlying double.  This matches what GCC does.  */
+  if (fmt->split_half)
+    return 2 * floatformat_precision (fmt->split_half);
+
+  /* Otherwise, the precision is the size of mantissa in bits,
+     including the implicit bit if present.  */
+  int prec = fmt->man_len;
+  if (fmt->intbit == floatformat_intbit_no)
+    prec++;
+
+  return prec;
+}
+
 
 /* Convert TO/FROM target to the hosts DOUBLEST floating-point format.
 
@@ -769,6 +788,51 @@ floatformat_from_doublest (const struct
     convert_doublest_to_floatformat (fmt, in, out);
 }
 
+/* Convert the byte-stream ADDR, interpreted as floating-point format FMT,
+   to a string.  */
+std::string
+floatformat_to_string (const struct floatformat *fmt,
+		       const gdb_byte *in)
+{
+  /* Detect invalid representations.  */
+  if (!floatformat_is_valid (fmt, in))
+    return "<invalid float value>";
+
+  /* Handle NaN and Inf.  */
+  enum float_kind kind = floatformat_classify (fmt, in);
+  if (kind == float_nan)
+    {
+      const char *sign = floatformat_is_negative (fmt, in)? "-" : "";
+      const char *mantissa = floatformat_mantissa (fmt, in);
+      return string_printf ("%snan(0x%s)", sign, mantissa);
+    }
+  else if (kind == float_infinite)
+    {
+      const char *sign = floatformat_is_negative (fmt, in)? "-" : "";
+      return string_printf ("%sinf", sign);
+    }
+
+  /* Print the number using a format string where the precision is set
+     to the DECIMAL_DIG value for the given floating-point format.
+     This value is computed as
+
+		ceil(1 + p * log10(b)),
+
+     where p is the precision of the floating-point format in bits, and
+     b is the base (which is always 2 for the formats we support).  */
+  const double log10_2 = .30102999566398119521;
+  double d_decimal_dig = 1 + floatformat_precision (fmt) * log10_2;
+  int decimal_dig = d_decimal_dig;
+  if (decimal_dig < d_decimal_dig)
+    decimal_dig++;
+
+  std::string host_format
+    = string_printf ("%%.%d" DOUBLEST_PRINT_FORMAT, decimal_dig);
+
+  DOUBLEST doub;
+  floatformat_to_doublest (fmt, in, &doub);
+  return string_printf (host_format.c_str (), doub);
+}
 
 /* Extract a floating-point number of type TYPE from a target-order
    byte-stream at ADDR.  Returns the value as type DOUBLEST.  */
Index: binutils-gdb/gdb/doublest.h
===================================================================
--- binutils-gdb.orig/gdb/doublest.h
+++ binutils-gdb/gdb/doublest.h
@@ -71,6 +71,9 @@ extern enum float_kind floatformat_class
 extern const char *floatformat_mantissa (const struct floatformat *,
 					 const bfd_byte *);
 
+extern std::string floatformat_to_string (const struct floatformat *fmt,
+					  const gdb_byte *in);
+
 /* Return the floatformat's total size in host bytes.  */
 
 extern size_t floatformat_totalsize_bytes (const struct floatformat *fmt);
Index: binutils-gdb/gdb/printcmd.c
===================================================================
--- binutils-gdb.orig/gdb/printcmd.c
+++ binutils-gdb/gdb/printcmd.c
@@ -424,7 +424,18 @@ print_scalar_formatted (const gdb_byte *
       valaddr = converted_float_bytes.data ();
     }
 
-  switch (options->format)
+  /* Printing a non-float type as 'f' will interpret the data as if it were
+     of a floating-point type of the same length, if that exists.  Otherwise,
+     the data is printed as integer.  */
+  char format = options->format;
+  if (format == 'f' && TYPE_CODE (type) != TYPE_CODE_FLT)
+    {
+      type = float_type_from_length (type);
+      if (TYPE_CODE (type) != TYPE_CODE_FLT)
+        format = 0;
+    }
+
+  switch (format)
     {
     case 'o':
       print_octal_chars (stream, valaddr, len, byte_order);
@@ -444,7 +455,6 @@ print_scalar_formatted (const gdb_byte *
 	}
       /* FALLTHROUGH */
     case 'f':
-      type = float_type_from_length (type);
       print_floating (valaddr, type, stream);
       break;
 
@@ -482,7 +492,7 @@ print_scalar_formatted (const gdb_byte *
       break;
 
     default:
-      error (_("Undefined output format \"%c\"."), options->format);
+      error (_("Undefined output format \"%c\"."), format);
     }
 }
 
Index: binutils-gdb/gdb/valprint.c
===================================================================
--- binutils-gdb.orig/gdb/valprint.c
+++ binutils-gdb/gdb/valprint.c
@@ -27,7 +27,6 @@
 #include "language.h"
 #include "annotate.h"
 #include "valprint.h"
-#include "floatformat.h"
 #include "doublest.h"
 #include "dfp.h"
 #include "extension.h"
@@ -826,7 +825,7 @@ generic_val_print_char (struct type *typ
     }
 }
 
-/* generic_val_print helper for TYPE_CODE_FLT.  */
+/* generic_val_print helper for TYPE_CODE_FLT and TYPE_CODE_DECFLOAT.  */
 
 static void
 generic_val_print_float (struct type *type,
@@ -850,29 +849,6 @@ generic_val_print_float (struct type *ty
     }
 }
 
-/* generic_val_print helper for TYPE_CODE_DECFLOAT.  */
-
-static void
-generic_val_print_decfloat (struct type *type,
-			    int embedded_offset, struct ui_file *stream,
-			    struct value *original_value,
-			    const struct value_print_options *options)
-{
-  struct gdbarch *gdbarch = get_type_arch (type);
-  int unit_size = gdbarch_addressable_memory_unit_size (gdbarch);
-
-  if (options->format)
-    val_print_scalar_formatted (type, embedded_offset, original_value,
-				options, 0, stream);
-  else
-    {
-      const gdb_byte *valaddr = value_contents_for_printing (original_value);
-
-      print_decimal_floating (valaddr + embedded_offset * unit_size, type,
-			      stream);
-    }
-}
-
 /* generic_val_print helper for TYPE_CODE_COMPLEX.  */
 
 static void
@@ -996,15 +972,11 @@ generic_val_print (struct type *type,
       break;
 
     case TYPE_CODE_FLT:
+    case TYPE_CODE_DECFLOAT:
       generic_val_print_float (type, embedded_offset, stream,
 			       original_value, options);
       break;
 
-    case TYPE_CODE_DECFLOAT:
-      generic_val_print_decfloat (type, embedded_offset, stream,
-				  original_value, options);
-      break;
-
     case TYPE_CODE_VOID:
       fputs_filtered (decorations->void_name, stream);
       break;
@@ -1397,90 +1369,25 @@ longest_to_int (LONGEST arg)
   return (rtnval);
 }
 
-/* Print a floating point value of type TYPE (not always a
-   TYPE_CODE_FLT), pointed to in GDB by VALADDR, on STREAM.  */
+/* Print a floating point value of floating-point type TYPE,
+   pointed to in GDB by VALADDR, on STREAM.  */
 
 void
 print_floating (const gdb_byte *valaddr, struct type *type,
 		struct ui_file *stream)
 {
-  DOUBLEST doub;
-  int inv;
-  const struct floatformat *fmt = NULL;
-  unsigned len = TYPE_LENGTH (type);
-  enum float_kind kind;
-
-  /* If it is a floating-point, check for obvious problems.  */
+  std::string str;
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
-    fmt = floatformat_from_type (type);
-  if (fmt != NULL)
     {
-      kind = floatformat_classify (fmt, valaddr);
-      if (kind == float_nan)
-	{
-	  if (floatformat_is_negative (fmt, valaddr))
-	    fprintf_filtered (stream, "-");
-	  fprintf_filtered (stream, "nan(");
-	  fputs_filtered ("0x", stream);
-	  fputs_filtered (floatformat_mantissa (fmt, valaddr), stream);
-	  fprintf_filtered (stream, ")");
-	  return;
-	}
-      else if (kind == float_infinite)
-	{
-	  if (floatformat_is_negative (fmt, valaddr))
-	    fputs_filtered ("-", stream);
-	  fputs_filtered ("inf", stream);
-	  return;
-	}
+      const struct floatformat *fmt = floatformat_from_type (type);
+      str = floatformat_to_string (fmt, valaddr);
     }
-
-  /* NOTE: cagney/2002-01-15: The TYPE passed into print_floating()
-     isn't necessarily a TYPE_CODE_FLT.  Consequently, unpack_double
-     needs to be used as that takes care of any necessary type
-     conversions.  Such conversions are of course direct to DOUBLEST
-     and disregard any possible target floating point limitations.
-     For instance, a u64 would be converted and displayed exactly on a
-     host with 80 bit DOUBLEST but with loss of information on a host
-     with 64 bit DOUBLEST.  */
-
-  doub = unpack_double (type, valaddr, &inv);
-  if (inv)
+  else
     {
-      fprintf_filtered (stream, "<invalid float value>");
-      return;
+      enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
+      unsigned len = TYPE_LENGTH (type);
+      std::string str = decimal_to_string (valaddr, len, byte_order);
     }
-
-  /* FIXME: kettenis/2001-01-20: The following code makes too much
-     assumptions about the host and target floating point format.  */
-
-  /* NOTE: cagney/2002-02-03: Since the TYPE of what was passed in may
-     not necessarily be a TYPE_CODE_FLT, the below ignores that and
-     instead uses the type's length to determine the precision of the
-     floating-point value being printed.  */
-
-  if (len < sizeof (double))
-      fprintf_filtered (stream, "%.9g", (double) doub);
-  else if (len == sizeof (double))
-      fprintf_filtered (stream, "%.17g", (double) doub);
-  else
-#ifdef PRINTF_HAS_LONG_DOUBLE
-    fprintf_filtered (stream, "%.35Lg", doub);
-#else
-    /* This at least wins with values that are representable as
-       doubles.  */
-    fprintf_filtered (stream, "%.17g", (double) doub);
-#endif
-}
-
-void
-print_decimal_floating (const gdb_byte *valaddr, struct type *type,
-			struct ui_file *stream)
-{
-  enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
-  unsigned len = TYPE_LENGTH (type);
-
-  std::string str = decimal_to_string (valaddr, len, byte_order);
   fputs_filtered (str.c_str (), stream);
 }
 
Index: binutils-gdb/gdb/value.h
===================================================================
--- binutils-gdb.orig/gdb/value.h
+++ binutils-gdb/gdb/value.h
@@ -1046,9 +1046,6 @@ extern void print_longest (struct ui_fil
 extern void print_floating (const gdb_byte *valaddr, struct type *type,
 			    struct ui_file *stream);
 
-extern void print_decimal_floating (const gdb_byte *valaddr, struct type *type,
-				    struct ui_file *stream);
-
 extern void value_print (struct value *val, struct ui_file *stream,
 			 const struct value_print_options *options);
 
Index: binutils-gdb/gdb/Makefile.in
===================================================================
--- binutils-gdb.orig/gdb/Makefile.in
+++ binutils-gdb/gdb/Makefile.in
@@ -2724,6 +2724,11 @@ printcmd.o: $(srcdir)/printcmd.c
 		$(COMPILE.post) $(srcdir)/printcmd.c
 	$(POSTCOMPILE)
 
+# Same for "doublest.c".
+doublest.o: $(srcdir)/doublest.c
+	$(COMPILE.pre) $(INTERNAL_CFLAGS) $(GDB_WARN_CFLAGS_NO_FORMAT) \
+		$(COMPILE.post) $(srcdir)/doublest.c
+
 # ada-exp.c can appear in srcdir, for releases; or in ., for
 # development builds.
 ADA_EXP_C = `if test -f ada-exp.c; then echo ada-exp.c; else echo $(srcdir)/ada-exp.c; fi`
