Index: binutils-gdb/gdb/target-float.c
===================================================================
--- binutils-gdb.orig/gdb/target-float.c
+++ binutils-gdb/gdb/target-float.c
@@ -60,3 +60,40 @@ target_float_is_zero (const gdb_byte *ad
   gdb_assert_not_reached ("unexpected type code");
 }
 
+/* Convert the byte-stream ADDR, interpreted as floating-point type TYPE,
+   to a string, optionally using the print format FORMAT.  */
+std::string
+target_float_to_string (const gdb_byte *addr, const struct type *type,
+			const char *format)
+{
+  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+    return floatformat_to_string (floatformat_from_type (type), addr, format);
+
+  if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+    return decimal_to_string (addr, TYPE_LENGTH (type),
+			      gdbarch_byte_order (get_type_arch (type)),
+			      format);
+
+  gdb_assert_not_reached ("unexpected type code");
+}
+
+/* Parse string STRING into a target floating-number of type TYPE and
+   store it as byte-stream ADDR.  Return whether parsing succeeded.  */
+bool
+target_float_from_string (gdb_byte *addr, const struct type *type,
+			  const std::string &string)
+{
+  /* Ensure possible padding bytes in the target buffer are zeroed out.  */
+  memset (addr, 0, TYPE_LENGTH (type));
+
+  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+    return floatformat_from_string (floatformat_from_type (type), addr,
+				    string);
+
+  if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+    return decimal_from_string (addr, TYPE_LENGTH (type),
+				gdbarch_byte_order (get_type_arch (type)),
+				string);
+
+  gdb_assert_not_reached ("unexpected type code");
+}
Index: binutils-gdb/gdb/target-float.h
===================================================================
--- binutils-gdb.orig/gdb/target-float.h
+++ binutils-gdb/gdb/target-float.h
@@ -25,4 +25,11 @@ extern bool target_float_is_valid (const
 extern bool target_float_is_zero (const gdb_byte *addr,
 				  const struct type *type);
 
+extern std::string target_float_to_string (const gdb_byte *addr,
+					   const struct type *type,
+					   const char *format = nullptr);
+extern bool target_float_from_string (gdb_byte *addr,
+				      const struct type *type,
+				      const std::string &string);
+
 #endif
Index: binutils-gdb/gdb/valprint.c
===================================================================
--- binutils-gdb.orig/gdb/valprint.c
+++ binutils-gdb/gdb/valprint.c
@@ -27,8 +27,7 @@
 #include "language.h"
 #include "annotate.h"
 #include "valprint.h"
-#include "doublest.h"
-#include "dfp.h"
+#include "target-float.h"
 #include "extension.h"
 #include "ada-lang.h"
 #include "gdb_obstack.h"
@@ -1366,18 +1365,7 @@ void
 print_floating (const gdb_byte *valaddr, struct type *type,
 		struct ui_file *stream)
 {
-  std::string str;
-  if (TYPE_CODE (type) == TYPE_CODE_FLT)
-    {
-      const struct floatformat *fmt = floatformat_from_type (type);
-      str = floatformat_to_string (fmt, valaddr);
-    }
-  else
-    {
-      enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
-      unsigned len = TYPE_LENGTH (type);
-      str = decimal_to_string (valaddr, len, byte_order);
-    }
+  std::string str = target_float_to_string (valaddr, type);
   fputs_filtered (str.c_str (), stream);
 }
 
Index: binutils-gdb/gdb/printcmd.c
===================================================================
--- binutils-gdb.orig/gdb/printcmd.c
+++ binutils-gdb/gdb/printcmd.c
@@ -38,7 +38,7 @@
 #include "ui-out.h"
 #include "block.h"
 #include "disasm.h"
-#include "dfp.h"
+#include "target-float.h"
 #include "observer.h"
 #include "solist.h"
 #include "parser-defs.h"
@@ -2360,13 +2360,8 @@ printf_floating (struct ui_file *stream,
   value = value_cast (fmt_type, value);
 
   /* Convert the value to a string and print it.  */
-  std::string str;
-  if (TYPE_CODE (fmt_type) == TYPE_CODE_FLT)
-    str = floatformat_to_string (floatformat_from_type (fmt_type),
-				 value_contents (value), format);
-  else
-    str = decimal_to_string (value_contents (value),
-			     TYPE_LENGTH (fmt_type), byte_order, format);
+  std::string str
+    = target_float_to_string (value_contents (value), fmt_type, format);
   fputs_filtered (str.c_str (), stream);
 }
 
Index: binutils-gdb/gdb/i387-tdep.c
===================================================================
--- binutils-gdb.orig/gdb/i387-tdep.c
+++ binutils-gdb/gdb/i387-tdep.c
@@ -18,12 +18,12 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
-#include "doublest.h"
 #include "frame.h"
 #include "gdbcore.h"
 #include "inferior.h"
 #include "language.h"
 #include "regcache.h"
+#include "target-float.h"
 #include "value.h"
 
 #include "i386-tdep.h"
@@ -40,9 +40,8 @@ print_i387_value (struct gdbarch *gdbarc
      garbage, but we'd better print one too many.  We need enough room
      to print the value, 1 position for the sign, 1 for the decimal
      point, 19 for the digits and 6 for the exponent adds up to 27.  */
-  const struct floatformat *fmt
-    = floatformat_from_type (i387_ext_type (gdbarch));
-  std::string str = floatformat_to_string (fmt, raw, " %-+27.19g");
+  const struct type *type = i387_ext_type (gdbarch);
+  std::string str = target_float_to_string (raw, type, " %-+27.19g");
   fprintf_filtered (file, "%s", str.c_str ());
 }
 
Index: binutils-gdb/gdb/mips-tdep.c
===================================================================
--- binutils-gdb.orig/gdb/mips-tdep.c
+++ binutils-gdb/gdb/mips-tdep.c
@@ -55,6 +55,7 @@
 #include "user-regs.h"
 #include "valprint.h"
 #include "ax.h"
+#include "target-float.h"
 #include <algorithm>
 
 static const struct objfile_data *mips_pdr_data;
@@ -6258,10 +6259,8 @@ mips_print_fp_register (struct ui_file *
   gdb_byte *raw_buffer;
   std::string flt_str, dbl_str;
 
-  const struct floatformat *flt_fmt
-    = floatformat_from_type (builtin_type (gdbarch)->builtin_float);
-  const struct floatformat *dbl_fmt
-    = floatformat_from_type (builtin_type (gdbarch)->builtin_double);
+  const struct type *flt_type = builtin_type (gdbarch)->builtin_float;
+  const struct type *dbl_type = builtin_type (gdbarch)->builtin_double;
 
   raw_buffer
     = ((gdb_byte *)
@@ -6279,7 +6278,7 @@ mips_print_fp_register (struct ui_file *
       /* 4-byte registers: Print hex and floating.  Also print even
          numbered registers as doubles.  */
       mips_read_fp_register_single (frame, regnum, raw_buffer);
-      flt_str = floatformat_to_string (flt_fmt, raw_buffer, "%-17.9g");
+      flt_str = target_float_to_string (raw_buffer, flt_type, "%-17.9g");
 
       get_formatted_print_options (&opts, 'x');
       print_scalar_formatted (raw_buffer,
@@ -6291,7 +6290,7 @@ mips_print_fp_register (struct ui_file *
       if ((regnum - gdbarch_num_regs (gdbarch)) % 2 == 0)
 	{
 	  mips_read_fp_register_double (frame, regnum, raw_buffer);
-	  dbl_str = floatformat_to_string (dbl_fmt, raw_buffer, "%-24.17g");
+	  dbl_str = target_float_to_string (raw_buffer, dbl_type, "%-24.17g");
 
 	  fprintf_filtered (file, " dbl: %s", dbl_str.c_str ());
 	}
@@ -6302,10 +6301,10 @@ mips_print_fp_register (struct ui_file *
 
       /* Eight byte registers: print each one as hex, float and double.  */
       mips_read_fp_register_single (frame, regnum, raw_buffer);
-      flt_str = floatformat_to_string (flt_fmt, raw_buffer, "%-17.9g");
+      flt_str = target_float_to_string (raw_buffer, flt_type, "%-17.9g");
 
       mips_read_fp_register_double (frame, regnum, raw_buffer);
-      dbl_str = floatformat_to_string (dbl_fmt, raw_buffer, "%-24.17g");
+      dbl_str = target_float_to_string (raw_buffer, dbl_type, "%-24.17g");
 
       get_formatted_print_options (&opts, 'x');
       print_scalar_formatted (raw_buffer,
Index: binutils-gdb/gdb/sh64-tdep.c
===================================================================
--- binutils-gdb.orig/gdb/sh64-tdep.c
+++ binutils-gdb/gdb/sh64-tdep.c
@@ -35,6 +35,7 @@
 #include "arch-utils.h"
 #include "regcache.h"
 #include "osabi.h"
+#include "target-float.h"
 #include "valprint.h"
 
 #include "elf-bfd.h"
@@ -1931,9 +1932,8 @@ sh64_do_fp_register (struct gdbarch *gdb
 					(gdbarch, regnum)), file);
 
   /* Print the value.  */
-  const struct floatformat *fmt
-    = floatformat_from_type (builtin_type (gdbarch)->builtin_float);
-  std::string str = floatformat_to_string (fmt, raw_buffer, "%-10.9g");
+  const struct type *flt_type = builtin_type (gdbarch)->builtin_float;
+  std::string str = target_float_to_string (raw_buffer, flt_type, "%-10.9g");
   fprintf_filtered (file, "%s", str.c_str ());
 
   /* Print the fp register as hex.  */
Index: binutils-gdb/gdb/parse.c
===================================================================
--- binutils-gdb.orig/gdb/parse.c
+++ binutils-gdb/gdb/parse.c
@@ -44,8 +44,7 @@
 #include "gdbcmd.h"
 #include "symfile.h"		/* for overlay functions */
 #include "inferior.h"
-#include "doublest.h"
-#include "dfp.h"
+#include "target-float.h"
 #include "block.h"
 #include "source.h"
 #include "objfiles.h"
@@ -1338,13 +1337,7 @@ bool
 parse_float (const char *p, int len,
 	     const struct type *type, gdb_byte *data)
 {
-  if (TYPE_CODE (type) == TYPE_CODE_FLT)
-    return floatformat_from_string (floatformat_from_type (type),
-				    data, std::string (p, len));
-  else
-    return decimal_from_string (data, TYPE_LENGTH (type),
-				gdbarch_byte_order (get_type_arch (type)),
-				std::string (p, len));
+  return target_float_from_string (data, type, std::string (p, len));
 }
 
 /* Stuff for maintaining a stack of types.  Currently just used by C, but
Index: binutils-gdb/gdb/stabsread.c
===================================================================
--- binutils-gdb.orig/gdb/stabsread.c
+++ binutils-gdb/gdb/stabsread.c
@@ -41,7 +41,7 @@
 #include "demangle.h"
 #include "gdb-demangle.h"
 #include "language.h"
-#include "doublest.h"
+#include "target-float.h"
 #include "cp-abi.h"
 #include "cp-support.h"
 #include <ctype.h>
@@ -798,19 +798,15 @@ define_symbol (CORE_ADDR valu, const cha
 	{
 	case 'r':
 	  {
-	    double d = atof (p);
 	    gdb_byte *dbl_valu;
 	    struct type *dbl_type;
 
-	    /* FIXME-if-picky-about-floating-accuracy: Should be using
-	       target arithmetic to get the value.  real.c in GCC
-	       probably has the necessary code.  */
-
 	    dbl_type = objfile_type (objfile)->builtin_double;
 	    dbl_valu
 	      = (gdb_byte *) obstack_alloc (&objfile->objfile_obstack,
 					    TYPE_LENGTH (dbl_type));
-	    store_typed_floating (dbl_valu, dbl_type, d);
+
+	    target_float_from_string (dbl_valu, dbl_type, std::string (p));
 
 	    SYMBOL_TYPE (sym) = dbl_type;
 	    SYMBOL_VALUE_BYTES (sym) = dbl_valu;
Index: binutils-gdb/gdb/gdbarch-selftests.c
===================================================================
--- binutils-gdb.orig/gdb/gdbarch-selftests.c
+++ binutils-gdb/gdb/gdbarch-selftests.c
@@ -24,6 +24,7 @@
 #include "inferior.h"
 #include "gdbthread.h"
 #include "target.h"
+#include "target-float.h"
 
 namespace selftests {
 
@@ -178,11 +179,8 @@ register_to_value_test (struct gdbarch *
 
 	      if (TYPE_CODE (type) == TYPE_CODE_FLT)
 		{
-		  DOUBLEST d = 1.25;
-
 		  /* Generate valid float format.  */
-		  floatformat_from_doublest (floatformat_from_type (type),
-					     &d, expected.data ());
+		  target_float_from_string (expected.data (), type, "1.25");
 		}
 	      else
 		{
