Index: binutils-gdb/gdb/doublest.c
===================================================================
--- binutils-gdb.orig/gdb/doublest.c
+++ binutils-gdb/gdb/doublest.c
@@ -861,6 +861,35 @@ floatformat_to_string (const struct floa
   floatformat_to_doublest (fmt, in, &doub);
   return string_printf (host_format.c_str (), doub);
 }
+
+/* Parse string STRING into a target floating-number of format FMT and
+   store it as byte-stream ADDR.  Return whether parsing succeeded.  */
+bool
+floatformat_from_string (const struct floatformat *fmt, gdb_byte *out,
+			 std::string in)
+{
+  DOUBLEST doub;
+  int n, num;
+#ifdef HAVE_LONG_DOUBLE
+  const char *scan_format = "%Lg%n";
+#else
+  const char *scan_format = "%lg%n";
+#endif
+  num = sscanf (in.c_str (), scan_format, &doub, &n);
+
+  /* The sscanf man page suggests not making any assumptions on the effect
+     of %n on the result, so we don't.
+     That is why we simply test num == 0.  */
+  if (num == 0)
+    return false;
+
+  /* We only accept the whole string.  */
+  if (in[n])
+    return false;
+
+  floatformat_from_doublest (fmt, &doub, out);
+  return true;
+}
 
 /* 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
@@ -74,6 +74,8 @@ extern const char *floatformat_mantissa
 extern std::string floatformat_to_string (const struct floatformat *fmt,
 					  const gdb_byte *in,
 					  const char *format = nullptr);
+extern bool floatformat_from_string (const struct floatformat *fmt,
+				     gdb_byte *out, std::string in);
 
 /* Return the floatformat's total size in host bytes.  */
 
Index: binutils-gdb/gdb/std-operator.def
===================================================================
--- binutils-gdb.orig/gdb/std-operator.def
+++ binutils-gdb/gdb/std-operator.def
@@ -114,9 +114,9 @@ OP (MULTI_SUBSCRIPT)
    Thus, the operation occupies four exp_elements.  */
 OP (OP_LONG)
 
-/* OP_DOUBLE is similar but takes a DOUBLEST constant instead of a
-   long.  */
-OP (OP_DOUBLE)
+/* OP_FLOAT is similar but takes a floating-point constant encoded in
+   the target format for the given type instead of a long.  */
+OP (OP_FLOAT)
 
 /* OP_VAR_VALUE takes one struct block * in the following element,
    and one struct symbol * in the following exp_element, followed
@@ -325,11 +325,6 @@ OP (OP_OBJC_NSSTRING)
    ":exp" and ":").  */
 OP (OP_RANGE)
 
-/* OP_DECFLOAT is followed by a type pointer in the next exp_element
-   and a dec long constant value in the following exp_element.
-   Then comes another OP_DECFLOAT.  */
-OP (OP_DECFLOAT)
-
 /* OP_ADL_FUNC specifies that the function is to be looked up in an
    Argument Dependent manner (Koenig lookup).  */
 OP (OP_ADL_FUNC)
Index: binutils-gdb/gdb/expression.h
===================================================================
--- binutils-gdb.orig/gdb/expression.h
+++ binutils-gdb/gdb/expression.h
@@ -22,7 +22,6 @@
 
 
 #include "symtab.h"		/* Needed for "struct block" type.  */
-#include "doublest.h"		/* Needed for DOUBLEST.  */
 
 
 /* Definitions for saved C expressions.  */
@@ -66,8 +65,7 @@ union exp_element
     struct symbol *symbol;
     struct minimal_symbol *msymbol;
     LONGEST longconst;
-    DOUBLEST doubleconst;
-    gdb_byte decfloatconst[16];
+    gdb_byte floatconst[16];
     /* Really sizeof (union exp_element) characters (or less for the last
        element of a string).  */
     char string;
Index: binutils-gdb/gdb/ada-lang.c
===================================================================
--- binutils-gdb.orig/gdb/ada-lang.c
+++ binutils-gdb/gdb/ada-lang.c
@@ -3383,7 +3383,7 @@ resolve_subexp (struct expression **expp
       break;
 
     case OP_LONG:
-    case OP_DOUBLE:
+    case OP_FLOAT:
     case OP_VAR_VALUE:
     case OP_VAR_MSYM_VALUE:
       *pos += 4;
@@ -10420,7 +10420,7 @@ ada_evaluate_subexp (struct type *expect
       if (noside == EVAL_NORMAL)
 	arg1 = unwrap_value (arg1);
 
-      /* If evaluating an OP_DOUBLE and an EXPECT_TYPE was provided,
+      /* If evaluating an OP_FLOAT and an EXPECT_TYPE was provided,
          then we need to perform the conversion manually, because
          evaluate_subexp_standard doesn't do it.  This conversion is
          necessary in Ada because the different kinds of float/fixed
@@ -10428,7 +10428,7 @@ ada_evaluate_subexp (struct type *expect
 
          Similarly, we need to perform the conversion from OP_LONG
          ourselves.  */
-      if ((op == OP_DOUBLE || op == OP_LONG) && expect_type != NULL)
+      if ((op == OP_FLOAT || op == OP_LONG) && expect_type != NULL)
         arg1 = ada_value_cast (expect_type, arg1, noside);
 
       return arg1;
Index: binutils-gdb/gdb/eval.c
===================================================================
--- binutils-gdb.orig/gdb/eval.c
+++ binutils-gdb/gdb/eval.c
@@ -1259,15 +1259,10 @@ evaluate_subexp_standard (struct type *e
       return value_from_longest (exp->elts[pc + 1].type,
 				 exp->elts[pc + 2].longconst);
 
-    case OP_DOUBLE:
+    case OP_FLOAT:
       (*pos) += 3;
-      return value_from_double (exp->elts[pc + 1].type,
-				exp->elts[pc + 2].doubleconst);
-
-    case OP_DECFLOAT:
-      (*pos) += 3;
-      return value_from_decfloat (exp->elts[pc + 1].type,
-				  exp->elts[pc + 2].decfloatconst);
+      return value_from_contents (exp->elts[pc + 1].type,
+				  exp->elts[pc + 2].floatconst);
 
     case OP_ADL_FUNC:
     case OP_VAR_VALUE:
Index: binutils-gdb/gdb/expprint.c
===================================================================
--- binutils-gdb.orig/gdb/expprint.c
+++ binutils-gdb/gdb/expprint.c
@@ -105,14 +105,14 @@ print_subexp_standard (struct expression
       }
       return;
 
-    case OP_DOUBLE:
+    case OP_FLOAT:
       {
 	struct value_print_options opts;
 
 	get_no_prettyformat_print_options (&opts);
 	(*pos) += 3;
-	value_print (value_from_double (exp->elts[pc + 1].type,
-					exp->elts[pc + 2].doubleconst),
+	value_print (value_from_contents (exp->elts[pc + 1].type,
+					  exp->elts[pc + 2].floatconst),
 		     stream, &opts);
       }
       return;
@@ -871,13 +871,14 @@ dump_subexp_body_standard (struct expres
 			(long) exp->elts[elt + 1].longconst);
       elt += 3;
       break;
-    case OP_DOUBLE:
+    case OP_FLOAT:
       fprintf_filtered (stream, "Type @");
       gdb_print_host_address (exp->elts[elt].type, stream);
       fprintf_filtered (stream, " (");
       type_print (exp->elts[elt].type, NULL, stream, 0);
-      fprintf_filtered (stream, "), value %g",
-			(double) exp->elts[elt + 1].doubleconst);
+      fprintf_filtered (stream, "), value ");
+      print_floating (exp->elts[elt + 1].floatconst,
+		      exp->elts[elt].type, stream);
       elt += 3;
       break;
     case OP_VAR_VALUE:
Index: binutils-gdb/gdb/breakpoint.c
===================================================================
--- binutils-gdb.orig/gdb/breakpoint.c
+++ binutils-gdb/gdb/breakpoint.c
@@ -10352,8 +10352,7 @@ watchpoint_exp_is_const (const struct ex
 	case TERNOP_SLICE:
 
 	case OP_LONG:
-	case OP_DOUBLE:
-	case OP_DECFLOAT:
+	case OP_FLOAT:
 	case OP_LAST:
 	case OP_COMPLEX:
 	case OP_STRING:
Index: binutils-gdb/gdb/parse.c
===================================================================
--- binutils-gdb.orig/gdb/parse.c
+++ binutils-gdb/gdb/parse.c
@@ -45,6 +45,7 @@
 #include "symfile.h"		/* for overlay functions */
 #include "inferior.h"
 #include "doublest.h"
+#include "dfp.h"
 #include "block.h"
 #include "source.h"
 #include "objfiles.h"
@@ -296,23 +297,13 @@ write_exp_elt_longcst (struct parser_sta
 }
 
 void
-write_exp_elt_dblcst (struct parser_state *ps, DOUBLEST expelt)
-{
-  union exp_element tmp;
-
-  memset (&tmp, 0, sizeof (union exp_element));
-  tmp.doubleconst = expelt;
-  write_exp_elt (ps, &tmp);
-}
-
-void
-write_exp_elt_decfloatcst (struct parser_state *ps, gdb_byte expelt[16])
+write_exp_elt_floatcst (struct parser_state *ps, const gdb_byte expelt[16])
 {
   union exp_element tmp;
   int index;
 
   for (index = 0; index < 16; index++)
-    tmp.decfloatconst[index] = expelt[index];
+    tmp.floatconst[index] = expelt[index];
 
   write_exp_elt (ps, &tmp);
 }
@@ -894,8 +885,7 @@ operator_length_standard (const struct e
       break;
 
     case OP_LONG:
-    case OP_DOUBLE:
-    case OP_DECFLOAT:
+    case OP_FLOAT:
     case OP_VAR_VALUE:
     case OP_VAR_MSYM_VALUE:
       oplen = 4;
@@ -1364,69 +1354,23 @@ null_post_parser (struct expression **ex
 }
 
 /* Parse floating point value P of length LEN.
-   Return 0 (false) if invalid, 1 (true) if valid.
-   The successfully parsed number is stored in D.
-   *SUFFIX points to the suffix of the number in P.
+   Return false if invalid, true if valid.
+   The successfully parsed number is stored in DATA in
+   target format for floating-point type TYPE.
 
    NOTE: This accepts the floating point syntax that sscanf accepts.  */
 
-int
-parse_float (const char *p, int len, DOUBLEST *d, const char **suffix)
-{
-  char *copy;
-  int n, num;
-
-  copy = (char *) xmalloc (len + 1);
-  memcpy (copy, p, len);
-  copy[len] = 0;
-
-  num = sscanf (copy, "%" DOUBLEST_SCAN_FORMAT "%n", d, &n);
-  xfree (copy);
-
-  /* The sscanf man page suggests not making any assumptions on the effect
-     of %n on the result, so we don't.
-     That is why we simply test num == 0.  */
-  if (num == 0)
-    return 0;
-
-  *suffix = p + n;
-  return 1;
-}
-
-/* Parse floating point value P of length LEN, using the C syntax for floats.
-   Return 0 (false) if invalid, 1 (true) if valid.
-   The successfully parsed number is stored in *D.
-   Its type is taken from builtin_type (gdbarch) and is stored in *T.  */
-
-int
-parse_c_float (struct gdbarch *gdbarch, const char *p, int len,
-	       DOUBLEST *d, struct type **t)
-{
-  const char *suffix;
-  int suffix_len;
-  const struct builtin_type *builtin_types = builtin_type (gdbarch);
-
-  if (! parse_float (p, len, d, &suffix))
-    return 0;
-
-  suffix_len = p + len - suffix;
-
-  if (suffix_len == 0)
-    *t = builtin_types->builtin_double;
-  else if (suffix_len == 1)
-    {
-      /* Handle suffixes: 'f' for float, 'l' for long double.  */
-      if (tolower (*suffix) == 'f')
-	*t = builtin_types->builtin_float;
-      else if (tolower (*suffix) == 'l')
-	*t = builtin_types->builtin_long_double;
-      else
-	return 0;
-    }
+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 0;
-
-  return 1;
+    return decimal_from_string (data, TYPE_LENGTH (type),
+				gdbarch_byte_order (get_type_arch (type)),
+				std::string (p, len));
 }
 
 /* Stuff for maintaining a stack of types.  Currently just used by C, but
@@ -1834,8 +1778,7 @@ operator_check_standard (struct expressi
     {
     case BINOP_VAL:
     case OP_COMPLEX:
-    case OP_DECFLOAT:
-    case OP_DOUBLE:
+    case OP_FLOAT:
     case OP_LONG:
     case OP_SCOPE:
     case OP_TYPE:
Index: binutils-gdb/gdb/parser-defs.h
===================================================================
--- binutils-gdb.orig/gdb/parser-defs.h
+++ binutils-gdb/gdb/parser-defs.h
@@ -23,7 +23,6 @@
 #if !defined (PARSER_DEFS_H)
 #define PARSER_DEFS_H 1
 
-#include "doublest.h"
 #include "vec.h"
 #include "expression.h"
 
@@ -189,9 +188,7 @@ extern void write_exp_elt_sym (struct pa
 
 extern void write_exp_elt_longcst (struct parser_state *, LONGEST);
 
-extern void write_exp_elt_dblcst (struct parser_state *, DOUBLEST);
-
-extern void write_exp_elt_decfloatcst (struct parser_state *, gdb_byte *);
+extern void write_exp_elt_floatcst (struct parser_state *, const gdb_byte *);
 
 extern void write_exp_elt_type (struct parser_state *, struct type *);
 
@@ -270,11 +267,8 @@ extern type_instance_flags follow_type_i
 
 extern void null_post_parser (struct expression **, int);
 
-extern int parse_float (const char *p, int len, DOUBLEST *d,
-			const char **suffix);
-
-extern int parse_c_float (struct gdbarch *gdbarch, const char *p, int len,
-			  DOUBLEST *d, struct type **t);
+extern bool parse_float (const char *p, int len,
+			 const struct type *type, gdb_byte *data);
 
 /* During parsing of a C expression, the pointer to the next character
    is in this variable.  */
Index: binutils-gdb/gdb/c-exp.y
===================================================================
--- binutils-gdb.orig/gdb/c-exp.y
+++ binutils-gdb/gdb/c-exp.y
@@ -48,7 +48,6 @@
 #include "charset.h"
 #include "block.h"
 #include "cp-support.h"
-#include "dfp.h"
 #include "macroscope.h"
 #include "objc-lang.h"
 #include "typeprint.h"
@@ -88,13 +87,9 @@ static int type_aggregate_p (struct type
       struct type *type;
     } typed_val_int;
     struct {
-      DOUBLEST dval;
-      struct type *type;
-    } typed_val_float;
-    struct {
       gdb_byte val[16];
       struct type *type;
-    } typed_val_decfloat;
+    } typed_val_float;
     struct type *tval;
     struct stoken sval;
     struct typed_stoken tsval;
@@ -142,7 +137,6 @@ static void c_print_token (FILE *file, i
 
 %token <typed_val_int> INT
 %token <typed_val_float> FLOAT
-%token <typed_val_decfloat> DECFLOAT
 
 /* Both NAME and TYPENAME tokens represent symbols in the input,
    and both convey their data as strings.
@@ -749,17 +743,10 @@ exp	:	NAME_OR_INT
 
 
 exp	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
 			  write_exp_elt_type (pstate, $1.type);
-			  write_exp_elt_dblcst (pstate, $1.dval);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE); }
-	;
-
-exp	:	DECFLOAT
-			{ write_exp_elt_opcode (pstate, OP_DECFLOAT);
-			  write_exp_elt_type (pstate, $1.type);
-			  write_exp_elt_decfloatcst (pstate, $1.val);
-			  write_exp_elt_opcode (pstate, OP_DECFLOAT); }
+			  write_exp_elt_floatcst (pstate, $1.val);
+			  write_exp_elt_opcode (pstate, OP_FLOAT); }
 	;
 
 exp	:	variable
@@ -1786,43 +1773,49 @@ parse_number (struct parser_state *par_s
 
   if (parsed_float)
     {
-      /* If it ends at "df", "dd" or "dl", take it as type of decimal floating
-         point.  Return DECFLOAT.  */
-
+      /* Handle suffixes for decimal floating-point: "df", "dd" or "dl".  */
       if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'f')
 	{
-	  putithere->typed_val_decfloat.type
+	  putithere->typed_val_float.type
 	    = parse_type (par_state)->builtin_decfloat;
-	  decimal_from_string (putithere->typed_val_decfloat.val, 4,
-			       gdbarch_byte_order (parse_gdbarch (par_state)),
-			       std::string (p, len - 2));
-	  return DECFLOAT;
+	  len -= 2;
 	}
-
-      if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd')
+      else if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd')
 	{
-	  putithere->typed_val_decfloat.type
+	  putithere->typed_val_float.type
 	    = parse_type (par_state)->builtin_decdouble;
-	  decimal_from_string (putithere->typed_val_decfloat.val, 8,
-			       gdbarch_byte_order (parse_gdbarch (par_state)),
-			       std::string (p, len - 2));
-	  return DECFLOAT;
+	  len -= 2;
 	}
-
-      if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l')
+      else if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l')
 	{
-	  putithere->typed_val_decfloat.type
+	  putithere->typed_val_float.type
 	    = parse_type (par_state)->builtin_declong;
-	  decimal_from_string (putithere->typed_val_decfloat.val, 16,
-			       gdbarch_byte_order (parse_gdbarch (par_state)),
-			       std::string (p, len - 2));
-	  return DECFLOAT;
+	  len -= 2;
+	}
+      /* Handle suffixes: 'f' for float, 'l' for long double.  */
+      else if (len >= 1 && tolower (p[len - 1]) == 'f')
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_float;
+	  len -= 1;
+	}
+      else if (len >= 1 && tolower (p[len - 1]) == 'l')
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_long_double;
+	  len -= 1;
+	}
+      /* Default type for floating-point literals is double.  */
+      else
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_double;
 	}
 
-      if (! parse_c_float (parse_gdbarch (par_state), p, len,
-			   &putithere->typed_val_float.dval,
-			   &putithere->typed_val_float.type))
-	return ERROR;
+      if (!parse_float (p, len,
+			putithere->typed_val_float.type,
+			putithere->typed_val_float.val))
+        return ERROR;
       return FLOAT;
     }
 
Index: binutils-gdb/gdb/d-exp.y
===================================================================
--- binutils-gdb.orig/gdb/d-exp.y
+++ binutils-gdb/gdb/d-exp.y
@@ -86,7 +86,7 @@ static int type_aggregate_p (struct type
       struct type *type;
     } typed_val_int;
     struct {
-      DOUBLEST dval;
+      gdb_byte val[16];
       struct type *type;
     } typed_val_float;
     struct symbol *sym;
@@ -540,10 +540,10 @@ PrimaryExpression:
 		  write_exp_elt_longcst (pstate, (LONGEST)($1.val));
 		  write_exp_elt_opcode (pstate, OP_LONG); }
 |	FLOAT_LITERAL
-		{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+		{ write_exp_elt_opcode (pstate, OP_FLOAT);
 		  write_exp_elt_type (pstate, $1.type);
-		  write_exp_elt_dblcst (pstate, $1.dval);
-		  write_exp_elt_opcode (pstate, OP_DOUBLE); }
+		  write_exp_elt_floatcst (pstate, $1.val);
+		  write_exp_elt_opcode (pstate, OP_FLOAT); }
 |	CHARACTER_LITERAL
 		{ struct stoken_vector vec;
 		  vec.len = 1;
@@ -682,8 +682,6 @@ parse_number (struct parser_state *ps, c
 
   if (parsed_float)
     {
-      const char *suffix;
-      int suffix_len;
       char *s, *sp;
 
       /* Strip out all embedded '_' before passing to parse_float.  */
@@ -698,54 +696,51 @@ parse_number (struct parser_state *ps, c
       *sp = '\0';
       len = strlen (s);
 
-      if (! parse_float (s, len, &putithere->typed_val_float.dval, &suffix))
-	return ERROR;
-
-      suffix_len = s + len - suffix;
-
-      if (suffix_len == 0)
-	{
-	  putithere->typed_val_float.type
-	    = parse_d_type (ps)->builtin_double;
-	}
-      else if (suffix_len == 1)
+      /* Check suffix for `i' , `fi' or `li' (idouble, ifloat or ireal).  */
+      if (len >= 1 && tolower (s[len - 1]) == 'i')
 	{
-	  /* Check suffix for `f', `l', or `i' (float, real, or idouble).  */
-	  if (tolower (*suffix) == 'f')
+	  if (len >= 2 && tolower (s[len - 2]) == 'f')
 	    {
 	      putithere->typed_val_float.type
-		= parse_d_type (ps)->builtin_float;
+		= parse_d_type (ps)->builtin_ifloat;
+	      len -= 2;
 	    }
-	  else if (tolower (*suffix) == 'l')
+	  else if (len >= 2 && tolower (s[len - 2]) == 'l')
 	    {
 	      putithere->typed_val_float.type
-		= parse_d_type (ps)->builtin_real;
+		= parse_d_type (ps)->builtin_ireal;
+	      len -= 2;
 	    }
-	  else if (tolower (*suffix) == 'i')
+	  else
 	    {
 	      putithere->typed_val_float.type
 		= parse_d_type (ps)->builtin_idouble;
+	      len -= 1;
 	    }
-	  else
-	    return ERROR;
 	}
-      else if (suffix_len == 2)
+      /* Check suffix for `f' or `l'' (float or real).  */
+      else if (len >= 1 && tolower (s[len - 1]) == 'f')
 	{
-	  /* Check suffix for `fi' or `li' (ifloat or ireal).  */
-	  if (tolower (suffix[0]) == 'f' && tolower (suffix[1] == 'i'))
-	    {
-	      putithere->typed_val_float.type
-		= parse_d_type (ps)->builtin_ifloat;
-	    }
-	  else if (tolower (suffix[0]) == 'l' && tolower (suffix[1] == 'i'))
-	    {
-	      putithere->typed_val_float.type
-		= parse_d_type (ps)->builtin_ireal;
-	    }
-	  else
-	    return ERROR;
+	  putithere->typed_val_float.type
+	    = parse_d_type (ps)->builtin_float;
+	  len -= 1;
+	}
+      else if (len >= 1 && tolower (s[len - 1]) == 'l')
+	{
+	  putithere->typed_val_float.type
+	    = parse_d_type (ps)->builtin_real;
+	  len -= 1;
 	}
+      /* Default type if no suffix.  */
       else
+	{
+	  putithere->typed_val_float.type
+	    = parse_d_type (ps)->builtin_double;
+	}
+
+      if (!parse_float (s, len,
+			putithere->typed_val_float.type,
+			putithere->typed_val_float.val))
 	return ERROR;
 
       return FLOAT_LITERAL;
Index: binutils-gdb/gdb/f-exp.y
===================================================================
--- binutils-gdb.orig/gdb/f-exp.y
+++ binutils-gdb/gdb/f-exp.y
@@ -91,7 +91,10 @@ static int match_string_literal (void);
       LONGEST val;
       struct type *type;
     } typed_val;
-    DOUBLEST dval;
+    struct {
+      gdb_byte val[16];
+      struct type *type;
+    } typed_val_float;
     struct symbol *sym;
     struct type *tval;
     struct stoken sval;
@@ -122,7 +125,7 @@ static int parse_number (struct parser_s
 %type <tval> ptype
 
 %token <typed_val> INT
-%token <dval> FLOAT
+%token <typed_val_float> FLOAT
 
 /* Both NAME and TYPENAME tokens represent symbols in the input,
    and both convey their data as strings.
@@ -414,12 +417,10 @@ exp	:	NAME_OR_INT
 	;
 
 exp	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
-			  write_exp_elt_type (pstate,
-					      parse_f_type (pstate)
-					      ->builtin_real_s8);
-			  write_exp_elt_dblcst (pstate, $1);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE); }
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
+			  write_exp_elt_type (pstate, $1.type);
+			  write_exp_elt_floatcst (pstate, $1.val);
+			  write_exp_elt_opcode (pstate, OP_FLOAT); }
 	;
 
 exp	:	variable
@@ -647,16 +648,22 @@ parse_number (struct parser_state *par_s
   if (parsed_float)
     {
       /* It's a float since it contains a point or an exponent.  */
-      /* [dD] is not understood as an exponent by atof, change it to 'e'.  */
+      /* [dD] is not understood as an exponent by parse_float,
+	 change it to 'e'.  */
       char *tmp, *tmp2;
 
       tmp = xstrdup (p);
       for (tmp2 = tmp; *tmp2; ++tmp2)
 	if (*tmp2 == 'd' || *tmp2 == 'D')
 	  *tmp2 = 'e';
-      putithere->dval = atof (tmp);
+
+      /* FIXME: Should this use different types?  */
+      putithere->typed_val_float.type = parse_f_type (pstate)->builtin_real_s8;
+      bool parsed = parse_float (tmp, len,
+				 putithere->typed_val_float.type,
+				 putithere->typed_val_float.val);
       free (tmp);
-      return FLOAT;
+      return parsed? FLOAT : ERROR;
     }
 
   /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
Index: binutils-gdb/gdb/go-exp.y
===================================================================
--- binutils-gdb.orig/gdb/go-exp.y
+++ binutils-gdb/gdb/go-exp.y
@@ -97,7 +97,7 @@ void yyerror (const char *);
       struct type *type;
     } typed_val_int;
     struct {
-      DOUBLEST dval;
+      gdb_byte val[16];
       struct type *type;
     } typed_val_float;
     struct stoken sval;
@@ -115,8 +115,6 @@ void yyerror (const char *);
 /* YYSTYPE gets defined by %union.  */
 static int parse_number (struct parser_state *,
 			 const char *, int, int, YYSTYPE *);
-static int parse_go_float (struct gdbarch *gdbarch, const char *p, int len,
-			   DOUBLEST *d, struct type **t);
 %}
 
 %type <voidval> exp exp1 type_exp start variable lcurly
@@ -436,10 +434,10 @@ exp	:	NAME_OR_INT
 
 
 exp	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
 			  write_exp_elt_type (pstate, $1.type);
-			  write_exp_elt_dblcst (pstate, $1.dval);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE); }
+			  write_exp_elt_floatcst (pstate, $1.val);
+			  write_exp_elt_opcode (pstate, OP_FLOAT); }
 	;
 
 exp	:	variable
@@ -634,24 +632,6 @@ name_not_typename
 
 %%
 
-/* Wrapper on parse_c_float to get the type right for Go.  */
-
-static int
-parse_go_float (struct gdbarch *gdbarch, const char *p, int len,
-		DOUBLEST *d, struct type **t)
-{
-  int result = parse_c_float (gdbarch, p, len, d, t);
-  const struct builtin_type *builtin_types = builtin_type (gdbarch);
-  const struct builtin_go_type *builtin_go_types = builtin_go_type (gdbarch);
-
-  if (*t == builtin_types->builtin_float)
-    *t = builtin_go_types->builtin_float32;
-  else if (*t == builtin_types->builtin_double)
-    *t = builtin_go_types->builtin_float64;
-
-  return result;
-}
-
 /* Take care of parsing a number (anything that starts with a digit).
    Set yylval and return the token type; update lexptr.
    LEN is the number of characters in it.  */
@@ -688,10 +668,34 @@ parse_number (struct parser_state *par_s
 
   if (parsed_float)
     {
-      if (! parse_go_float (parse_gdbarch (par_state), p, len,
-			    &putithere->typed_val_float.dval,
-			    &putithere->typed_val_float.type))
-	return ERROR;
+      const struct builtin_go_type *builtin_go_types
+	= builtin_go_type (parse_gdbarch (par_state));
+
+      /* Handle suffixes: 'f' for float32, 'l' for long double.
+	 FIXME: This appears to be an extension -- do we want this?  */
+      if (len >= 1 && tolower (p[len - 1]) == 'f')
+	{
+	  putithere->typed_val_float.type
+	    = builtin_go_types->builtin_float32;
+	  len--;
+	}
+      else if (len >= 1 && tolower (p[len - 1]) == 'l')
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_long_double;
+	  len--;
+	}
+      /* Default type for floating-point literals is float64.  */
+      else
+        {
+	  putithere->typed_val_float.type
+	    = builtin_go_types->builtin_float64;
+        }
+
+      if (!parse_float (p, len,
+			putithere->typed_val_float.type,
+			putithere->typed_val_float.val))
+        return ERROR;
       return FLOAT;
     }
 
Index: binutils-gdb/gdb/p-exp.y
===================================================================
--- binutils-gdb.orig/gdb/p-exp.y
+++ binutils-gdb/gdb/p-exp.y
@@ -89,7 +89,7 @@ static char *uptok (const char *, int);
       struct type *type;
     } typed_val_int;
     struct {
-      DOUBLEST dval;
+      gdb_byte val[16];
       struct type *type;
     } typed_val_float;
     struct symbol *sym;
@@ -511,11 +511,11 @@ exp	:	NAME_OR_INT
 
 
 exp	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
 			  write_exp_elt_type (pstate, $1.type);
 			  current_type = $1.type;
-			  write_exp_elt_dblcst (pstate, $1.dval);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE); }
+			  write_exp_elt_floatcst (pstate, $1.val);
+			  write_exp_elt_opcode (pstate, OP_FLOAT); }
 	;
 
 exp	:	variable
@@ -854,9 +854,30 @@ parse_number (struct parser_state *par_s
 
   if (parsed_float)
     {
-      if (! parse_c_float (parse_gdbarch (par_state), p, len,
-			   &putithere->typed_val_float.dval,
-			   &putithere->typed_val_float.type))
+      /* Handle suffixes: 'f' for float, 'l' for long double.
+         FIXME: This appears to be an extension -- do we want this?  */
+      if (len >= 1 && tolower (p[len - 1]) == 'f')
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_float;
+	  len--;
+	}
+      else if (len >= 1 && tolower (p[len - 1]) == 'l')
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_long_double;
+	  len--;
+	}
+      /* Default type for floating-point literals is double.  */
+      else
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_double;
+	}
+
+      if (!parse_float (p, len,
+			putithere->typed_val_float.type,
+			putithere->typed_val_float.val))
 	return ERROR;
       return FLOAT;
     }
Index: binutils-gdb/gdb/m2-exp.y
===================================================================
--- binutils-gdb.orig/gdb/m2-exp.y
+++ binutils-gdb/gdb/m2-exp.y
@@ -82,7 +82,7 @@ static int number_sign = 1;
   {
     LONGEST lval;
     ULONGEST ulval;
-    DOUBLEST dval;
+    gdb_byte val[16];
     struct symbol *sym;
     struct type *tval;
     struct stoken sval;
@@ -103,7 +103,7 @@ static int number_sign = 1;
 
 %token <lval> INT HEX ERROR
 %token <ulval> UINT M2_TRUE M2_FALSE CHAR
-%token <dval> FLOAT
+%token <val> FLOAT
 
 /* Both NAME and TYPENAME tokens represent symbols in the input,
    and both convey their data as strings.
@@ -474,12 +474,12 @@ exp	:	CHAR
 
 
 exp	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
 			  write_exp_elt_type (pstate,
 					      parse_m2_type (pstate)
 					      ->builtin_real);
-			  write_exp_elt_dblcst (pstate, $1);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE); }
+			  write_exp_elt_floatcst (pstate, $1);
+			  write_exp_elt_opcode (pstate, OP_FLOAT); }
 	;
 
 exp	:	variable
@@ -650,7 +650,11 @@ parse_number (int olen)
     if (p[c] == '.' && base == 10)
       {
 	/* It's a float since it contains a point.  */
-	yylval.dval = atof (p);
+	if (!parse_float (p, len,
+			  parse_m2_type (pstate)->builtin_real,
+			  yylval.val))
+	  return ERROR;
+
 	lexptr += len;
 	return FLOAT;
       }
Index: binutils-gdb/gdb/rust-exp.y
===================================================================
--- binutils-gdb.orig/gdb/rust-exp.y
+++ binutils-gdb/gdb/rust-exp.y
@@ -56,7 +56,7 @@ struct typed_val_int
 
 struct typed_val_float
 {
-  DOUBLEST dval;
+  gdb_byte val[16];
   struct type *type;
 };
 
@@ -175,10 +175,6 @@ static const char *number_regex_text =
 
 static regex_t number_regex;
 
-/* True if we're running unit tests.  */
-
-static int unit_testing;
-
 /* Obstack for data temporarily allocated during parsing.  Points to
    the obstack in the rust_parser, or to a temporary obstack during
    unit testing.  */
@@ -1070,11 +1066,6 @@ rust_type (const char *name)
 {
   struct type *type;
 
-  /* When unit testing, we don't bother checking the types, so avoid a
-     possibly-failing lookup here.  */
-  if (unit_testing)
-    return NULL;
-
   type = language_lookup_primitive_type (current_parser->language (),
 					 current_parser->arch (),
 					 name);
@@ -1588,8 +1579,11 @@ lex_number (void)
     }
   else
     {
-      rustyylval.typed_val_float.dval = strtod (number.c_str (), NULL);
       rustyylval.typed_val_float.type = type;
+      bool parsed = parse_float (number.c_str (), number.length (),
+				 rustyylval.typed_val_float.type,
+				 rustyylval.typed_val_float.val);
+      gdb_assert (parsed);
     }
 
   return is_integer ? (could_be_decimal ? DECIMAL_INTEGER : INTEGER) : FLOAT;
@@ -1718,7 +1712,7 @@ ast_dliteral (struct typed_val_float val
 {
   struct rust_op *result = OBSTACK_ZALLOC (work_obstack, struct rust_op);
 
-  result->opcode = OP_DOUBLE;
+  result->opcode = OP_FLOAT;
   result->left.typed_val_float = val;
 
   return result;
@@ -2183,11 +2177,11 @@ convert_ast_to_expression (struct parser
       write_exp_elt_opcode (state, OP_LONG);
       break;
 
-    case OP_DOUBLE:
-      write_exp_elt_opcode (state, OP_DOUBLE);
+    case OP_FLOAT:
+      write_exp_elt_opcode (state, OP_FLOAT);
       write_exp_elt_type (state, operation->left.typed_val_float.type);
-      write_exp_elt_dblcst (state, operation->left.typed_val_float.dval);
-      write_exp_elt_opcode (state, OP_DOUBLE);
+      write_exp_elt_floatcst (state, operation->left.typed_val_float.val);
+      write_exp_elt_opcode (state, OP_FLOAT);
       break;
 
     case STRUCTOP_STRUCT:
@@ -2677,7 +2671,10 @@ rust_lex_tests (void)
   scoped_restore obstack_holder = make_scoped_restore (&work_obstack,
 						       &test_obstack);
 
-  unit_testing = 1;
+  // Set up dummy "parser", so that rust_type works.
+  struct parser_state ps;
+  initialize_expout (&ps, 0, &rust_language_defn, target_gdbarch ());
+  rust_parser parser (&ps);
 
   rust_lex_test_one ("", 0);
   rust_lex_test_one ("    \t  \n \r  ", 0);
@@ -2766,8 +2763,6 @@ rust_lex_tests (void)
 
   rust_lex_test_completion ();
   rust_lex_test_push_back ();
-
-  unit_testing = 0;
 }
 
 #endif /* GDB_SELF_TEST */
Index: binutils-gdb/gdb/ada-exp.y
===================================================================
--- binutils-gdb.orig/gdb/ada-exp.y
+++ binutils-gdb/gdb/ada-exp.y
@@ -106,10 +106,6 @@ static struct type *type_long (struct pa
 
 static struct type *type_long_long (struct parser_state *);
 
-static struct type *type_float (struct parser_state *);
-
-static struct type *type_double (struct parser_state *);
-
 static struct type *type_long_double (struct parser_state *);
 
 static struct type *type_char (struct parser_state *);
@@ -128,7 +124,7 @@ static struct type *type_system_address
       struct type *type;
     } typed_val;
     struct {
-      DOUBLEST dval;
+      gdb_byte val[16];
       struct type *type;
     } typed_val_float;
     struct type *tval;
@@ -553,10 +549,10 @@ primary	:	CHARLIT
 	;
 
 primary	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
 			  write_exp_elt_type (pstate, $1.type);
-			  write_exp_elt_dblcst (pstate, $1.dval);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE);
+			  write_exp_elt_floatcst (pstate, $1.val);
+			  write_exp_elt_opcode (pstate, OP_FLOAT);
 			}
 	;
 
@@ -1444,18 +1440,6 @@ type_long_long (struct parser_state *par
 }
 
 static struct type *
-type_float (struct parser_state *par_state)
-{
-  return parse_type (par_state)->builtin_float;
-}
-
-static struct type *
-type_double (struct parser_state *par_state)
-{
-  return parse_type (par_state)->builtin_double;
-}
-
-static struct type *
 type_long_double (struct parser_state *par_state)
 {
   return parse_type (par_state)->builtin_long_double;
Index: binutils-gdb/gdb/ada-lex.l
===================================================================
--- binutils-gdb.orig/gdb/ada-lex.l
+++ binutils-gdb/gdb/ada-lex.l
@@ -403,16 +403,12 @@ processInt (struct parser_state *par_sta
 static int
 processReal (struct parser_state *par_state, const char *num0)
 {
-  sscanf (num0, "%" DOUBLEST_SCAN_FORMAT, &yylval.typed_val_float.dval);
-
-  yylval.typed_val_float.type = type_float (par_state);
-  if (sizeof(DOUBLEST) >= gdbarch_double_bit (parse_gdbarch (par_state))
-			    / TARGET_CHAR_BIT)
-    yylval.typed_val_float.type = type_double (par_state);
-  if (sizeof(DOUBLEST) >= gdbarch_long_double_bit (parse_gdbarch (par_state))
-			    / TARGET_CHAR_BIT)
-    yylval.typed_val_float.type = type_long_double (par_state);
+  yylval.typed_val_float.type = type_long_double (par_state);
 
+  bool parsed = parse_float (num0, strlen (num0),
+			     yylval.typed_val_float.type,
+			     yylval.typed_val_float.val);
+  gdb_assert (parsed);
   return FLOAT;
 }
 
