+2017-11-06  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * target-float.c (floatformat_to_host_double): New function.
+       (floatformat_from_host_double): Likewise.
+       (target_float_to_host_double): Likewise.
+       (target_float_from_host_double): Likewise.
+       * target-float.h (target_float_to_host_double): Add prototype.
+       (target_float_from_host_double): Likewise.
+
+       * guile/scm-value.c: Include "target-float.h".
+       (gdbscm_value_to_real): Use target_float_to_host_double.
+       Handle integer source values via value_as_long.
+       * guile/scm-math.c: Include "target-float.h".  Do not include
+       "doublest.h", "dfp.h", and "expression.h".
+       (vlscm_convert_typed_number): Use target_float_from_host_double.
+       (vlscm_convert_number): Likewise.
+
+       * python/py-value.c (valpy_float): Use target_float_to_host_double.
+       (convert_value_from_python): Use target_float_from_host_double.
+
 2017-11-06  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * ada-lang.c (cast_to_fixed): Reimplement in target arithmetic.
 
 #include "arch-utils.h"
 #include "charset.h"
 #include "cp-abi.h"
-#include "doublest.h" /* Needed by dfp.h.  */
-#include "expression.h" /* Needed by dfp.h.  */
-#include "dfp.h"
+#include "target-float.h"
 #include "symtab.h" /* Needed by language.h.  */
 #include "language.h"
 #include "valprint.h"
        }
     }
   else if (TYPE_CODE (type) == TYPE_CODE_FLT)
-    return value_from_double (type, scm_to_double (obj));
+    {
+      struct value *value = allocate_value (type);
+      target_float_from_host_double (value_contents_raw (value),
+                                    value_type (value),
+                                    scm_to_double (obj));
+      return value;
+    }
   else
     {
       *except_scmp = gdbscm_make_type_error (func_name, obj_arg_pos, obj,
                                   gdbscm_scm_to_ulongest (obj));
     }
   else if (scm_is_real (obj))
-    return value_from_double (bt->builtin_double, scm_to_double (obj));
+    {
+      struct value *value = allocate_value (bt->builtin_double);
+      target_float_from_host_double (value_contents_raw (value),
+                                    value_type (value),
+                                    scm_to_double (obj));
+      return value;
+    }
 
   *except_scmp = gdbscm_make_out_of_range_error (func_name, obj_arg_pos, obj,
                        _("value not a number representable on the target"));
 
 #include "arch-utils.h"
 #include "charset.h"
 #include "cp-abi.h"
+#include "target-float.h"
 #include "infcall.h"
 #include "symtab.h" /* Needed by language.h.  */
 #include "language.h"
     = vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   struct value *value = v_smob->value;
   struct type *type;
-  DOUBLEST d = 0;
+  double d = 0;
+  struct value *check = nullptr;
 
   type = value_type (value);
 
 
   TRY
     {
-      d = value_as_double (value);
+      if (is_floating_value (value))
+       {
+         d = target_float_to_host_double (value_contents (value), type);
+         check = allocate_value (type);
+         target_float_from_host_double (value_contents_raw (check), type, d);
+       }
+      else if (TYPE_UNSIGNED (type))
+       {
+         d = (ULONGEST) value_as_long (value);
+         check = value_from_ulongest (type, (ULONGEST) d);
+       }
+      else
+       {
+         d = value_as_long (value);
+         check = value_from_longest (type, (LONGEST) d);
+       }
     }
   CATCH (except, RETURN_MASK_ALL)
     {
   END_CATCH
 
   /* TODO: Is there a better way to check if the value fits?  */
-  if (d != (double) d)
+  if (!value_equal (value, check))
     gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, self,
                               _("number can't be converted to a double"));
 
 
     {
       type = check_typedef (type);
 
-      if (TYPE_CODE (type) != TYPE_CODE_FLT)
+      if (TYPE_CODE (type) != TYPE_CODE_FLT || !is_floating_value (value))
        error (_("Cannot convert value to float."));
 
-      d = value_as_double (value);
+      d = target_float_to_host_double (value_contents (value), type);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
          double d = PyFloat_AsDouble (obj);
 
          if (! PyErr_Occurred ())
-           value = value_from_double (builtin_type_pyfloat, d);
+           {
+             value = allocate_value (builtin_type_pyfloat);
+             target_float_from_host_double (value_contents_raw (value),
+                                            value_type (value), d);
+           }
        }
       else if (gdbpy_is_string (obj))
        {
 
   floatformat_from_doublest (fmt, &d, addr);
 }
 
+/* Convert the byte-stream ADDR, interpreted as floating-point format FMT,
+   to a floating-point value in the host "double" format.  */
+static double
+floatformat_to_host_double (const struct floatformat *fmt,
+                           const gdb_byte *addr)
+{
+  DOUBLEST d;
+  floatformat_to_doublest (fmt, addr, &d);
+  return (double) d;
+}
+
+/* Convert floating-point value VAL in the host "double" format to a target
+   floating-number of format FMT and store it as byte-stream ADDR.  */
+static void
+floatformat_from_host_double (const struct floatformat *fmt, gdb_byte *addr,
+                             double val)
+{
+  DOUBLEST d = (DOUBLEST) val;
+  floatformat_from_doublest (fmt, &d, addr);
+}
+
 /* Convert a floating-point number of format FROM_FMT from the target
    byte-stream FROM to a floating-point number of format TO_FMT, and
    store it to the target byte-stream TO.  */
   gdb_assert_not_reached ("unexpected type code");
 }
 
+/* Convert the byte-stream ADDR, interpreted as floating-point type TYPE,
+   to a floating-point value in the host "double" format.  */
+double
+target_float_to_host_double (const gdb_byte *addr,
+                            const struct type *type)
+{
+  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+    return floatformat_to_host_double (floatformat_from_type (type), addr);
+
+  /* We don't support conversions between target decimal floating-point
+     types and the host double type here.  */
+
+  gdb_assert_not_reached ("unexpected type code");
+}
+
+/* Convert floating-point value VAL in the host "double" format to a target
+   floating-number of type TYPE and store it as byte-stream ADDR.  */
+void
+target_float_from_host_double (gdb_byte *addr, const struct type *type,
+                              double val)
+{
+  /* Ensure possible padding bytes in the target buffer are zeroed out.  */
+  memset (addr, 0, TYPE_LENGTH (type));
+
+  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+    {
+      floatformat_from_host_double (floatformat_from_type (type), addr, val);
+      return;
+    }
+
+  /* We don't support conversions between target decimal floating-point
+     types and the host double type here.  */
+
+  gdb_assert_not_reached ("unexpected type code");
+}
+
 /* Convert a floating-point number of type FROM_TYPE from the target
    byte-stream FROM to a floating-point number of type TO_TYPE, and
    store it to the target byte-stream TO.  */
 
 extern void target_float_from_ulongest (gdb_byte *addr,
                                        const struct type *type,
                                        ULONGEST val);
+extern double target_float_to_host_double (const gdb_byte *addr,
+                                          const struct type *type);
+extern void target_float_from_host_double (gdb_byte *addr,
+                                          const struct type *type,
+                                          double val);
 extern void target_float_convert (const gdb_byte *from,
                                  const struct type *from_type,
                                  gdb_byte *to, const struct type *to_type);