+2019-01-01  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * arch/riscv.h (struct riscv_gdbarch_features) <hw_float_abi>:
+       Delete.
+       <operator==>: Update with for removed field.
+       <hash>: Likewise.
+       * riscv-tdep.h (struct gdbarch_tdep) <features>: Renamed to...
+       <isa_features>: ...this.
+       <abi_features>: New field.
+       (riscv_isa_flen): Update comment.
+       (riscv_abi_xlen): New declaration.
+       (riscv_abi_flen): New declaration.
+       * riscv-tdep.c (riscv_isa_xlen): Update to get answer from
+       isa_features.
+       (riscv_abi_xlen): New function.
+       (riscv_isa_flen): Update to get answer from isa_features.
+       (riscv_abi_flen): New function.
+       (riscv_has_fp_abi): Update to get answer from abi_features.
+       (riscv_call_info::riscv_call_info): Use abi xlen and flen, not isa
+       xlen and flen.
+       (riscv_call_info) <xlen, flen>: Update comment.
+       (riscv_call_arg_struct): Remove invalid assertions
+       (riscv_features_from_gdbarch_info): Update now hw_float_abi field
+       is removed.
+       (riscv_gdbarch_init): Gather isa features and abi features
+       separately, ensure both match on the gdbarch when reusing an old
+       gdbarch.  Relax an error check to allow 32-bit abi float to run on
+       a target with 64-bit float hardware.
+
 2019-01-01  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
 
        * source.c (search_command_helper): Stop reverse search
 
 int
 riscv_isa_xlen (struct gdbarch *gdbarch)
 {
-  return gdbarch_tdep (gdbarch)->features.xlen;
+  return gdbarch_tdep (gdbarch)->isa_features.xlen;
+}
+
+/* See riscv-tdep.h.  */
+
+int
+riscv_abi_xlen (struct gdbarch *gdbarch)
+{
+  return gdbarch_tdep (gdbarch)->abi_features.xlen;
 }
 
 /* See riscv-tdep.h.  */
 int
 riscv_isa_flen (struct gdbarch *gdbarch)
 {
-  return gdbarch_tdep (gdbarch)->features.flen;
+  return gdbarch_tdep (gdbarch)->isa_features.flen;
+}
+
+/* See riscv-tdep.h.  */
+
+int
+riscv_abi_flen (struct gdbarch *gdbarch)
+{
+  return gdbarch_tdep (gdbarch)->abi_features.flen;
 }
 
 /* Return true if the target for GDBARCH has floating point hardware.  */
 static bool
 riscv_has_fp_abi (struct gdbarch *gdbarch)
 {
-  return gdbarch_tdep (gdbarch)->features.hw_float_abi;
+  return gdbarch_tdep (gdbarch)->abi_features.flen > 0;
 }
 
 /* Return true if REGNO is a floating pointer register.  */
     : int_regs (RISCV_A0_REGNUM, RISCV_A0_REGNUM + 7),
       float_regs (RISCV_FA0_REGNUM, RISCV_FA0_REGNUM + 7)
   {
-    xlen = riscv_isa_xlen (gdbarch);
-    flen = riscv_isa_flen (gdbarch);
+    xlen = riscv_abi_xlen (gdbarch);
+    flen = riscv_abi_flen (gdbarch);
 
     /* Disable use of floating point registers if needed.  */
     if (!riscv_has_fp_abi (gdbarch))
   struct riscv_arg_reg float_regs;
 
   /* The XLEN and FLEN are copied in to this structure for convenience, and
-     are just the results of calling RISCV_ISA_XLEN and RISCV_ISA_FLEN.  */
+     are just the results of calling RISCV_ABI_XLEN and RISCV_ABI_FLEN.  */
   int xlen;
   int flen;
 };
        {
          int len0, len1, offset;
 
-         gdb_assert (TYPE_LENGTH (ainfo->type)
-                     <= (cinfo->flen + cinfo->xlen));
-
          len0 = TYPE_LENGTH (sinfo.field_type (0));
          if (!riscv_assign_reg_location (&ainfo->argloc[0],
                                          &cinfo->float_regs, len0, 0))
        {
          int len0, len1, offset;
 
-         gdb_assert (TYPE_LENGTH (ainfo->type)
-                     <= (cinfo->flen + cinfo->xlen));
-
          len0 = TYPE_LENGTH (sinfo.field_type (0));
          len1 = TYPE_LENGTH (sinfo.field_type (1));
          offset = align_up (len0, riscv_type_alignment (sinfo.field_type (1)));
                        _("unknown ELF header class %d"), eclass);
 
       if (e_flags & EF_RISCV_FLOAT_ABI_DOUBLE)
-       {
-         features.flen = 8;
-         features.hw_float_abi = true;
-       }
+       features.flen = 8;
       else if (e_flags & EF_RISCV_FLOAT_ABI_SINGLE)
-       {
-         features.flen = 4;
-         features.hw_float_abi = true;
-       }
+       features.flen = 4;
     }
   else
     {
   /* Have a look at what the supplied (if any) bfd object requires of the
      target, then check that this matches with what the target is
      providing.  */
-  struct riscv_gdbarch_features info_features
+  struct riscv_gdbarch_features abi_features
     = riscv_features_from_gdbarch_info (info);
-  if (info_features.xlen != 0 && info_features.xlen != features.xlen)
+  /* In theory a binary compiled for RV32 could run on an RV64 target,
+     however, this has not been tested in GDB yet, so for now we require
+     that the requested xlen match the targets xlen.  */
+  if (abi_features.xlen != 0 && abi_features.xlen != features.xlen)
     error (_("bfd requires xlen %d, but target has xlen %d"),
-           info_features.xlen, features.xlen);
-  if (info_features.flen != 0 && info_features.flen != features.flen)
+            abi_features.xlen, features.xlen);
+  /* We do support running binaries compiled for 32-bit float on targets
+     with 64-bit float, so we only complain if the binary requires more
+     than the target has available.  */
+  if (abi_features.flen > features.flen)
     error (_("bfd requires flen %d, but target has flen %d"),
-           info_features.flen, features.flen);
-
-  /* If the xlen from INFO_FEATURES is 0 then this indicates either there
-     is no bfd object, or nothing useful could be extracted from it, in
-     this case we enable hardware float abi if the target has floating
-     point registers.
+            abi_features.flen, features.flen);
 
-     If the xlen from INFO_FEATURES is not 0, and the flen in
-     INFO_FEATURES is also not 0, then this indicates that the supplied
-     bfd does require hardware floating point abi.  */
-  if (info_features.xlen == 0 || info_features.flen != 0)
-    features.hw_float_abi = (features.flen > 0);
+  /* If the ABI_FEATURES xlen is 0 then this indicates we got no useful abi
+     features from the INFO object.  In this case we assume that the xlen
+     abi matches the hardware.  */
+  if (abi_features.xlen == 0)
+    abi_features.xlen = features.xlen;
 
   /* Find a candidate among the list of pre-declared architectures.  */
   for (arches = gdbarch_list_lookup_by_info (arches, &info);
          gdbarch.  */
       struct gdbarch_tdep *other_tdep = gdbarch_tdep (arches->gdbarch);
 
-      if (other_tdep->features != features)
+      if (other_tdep->isa_features != features
+         || other_tdep->abi_features != abi_features)
         continue;
 
       break;
   /* None found, so create a new architecture from the information provided.  */
   tdep = new (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
-  tdep->features = features;
+  tdep->isa_features = features;
+  tdep->abi_features = abi_features;
 
   /* Target data types.  */
   set_gdbarch_short_bit (gdbarch, 16);
 
 /* RISC-V specific per-architecture information.  */
 struct gdbarch_tdep
 {
-  /* Features about the target that impact how the gdbarch is configured.
-     Two gdbarch instances are compatible only if this field matches.  */
-  struct riscv_gdbarch_features features;
+  /* Features about the target hardware that impact how the gdbarch is
+     configured.  Two gdbarch instances are compatible only if this field
+     matches.  */
+  struct riscv_gdbarch_features isa_features;
+
+  /* Features about the abi that impact how the gdbarch is configured.  Two
+     gdbarch instances are compatible only if this field matches.  */
+  struct riscv_gdbarch_features abi_features;
 
   /* ISA-specific data types.  */
   struct type *riscv_fpreg_d_type = nullptr;
    RV128.  */
 extern int riscv_isa_xlen (struct gdbarch *gdbarch);
 
-/* Return the width in bytes of the floating point registers for GDBARCH.
-   If this architecture has no floating point registers, then return 0.
-   Possible values are 4, 8, or 16 for depending on which of single, double
-   or quad floating point support is available.  */
+/* Return the width in bytes of the hardware floating point registers for
+   GDBARCH.  If this architecture has no floating point registers, then
+   return 0.  Possible values are 4, 8, or 16 for depending on which of
+   single, double or quad floating point support is available.  */
 extern int riscv_isa_flen (struct gdbarch *gdbarch);
 
+/* Return the width in bytes of the general purpose register abi for
+   GDBARCH.  This can be equal to, or less than RISCV_ISA_XLEN and reflects
+   how the binary was compiled rather than the hardware that is available.
+   It is possible that a binary compiled for RV32 is being run on an RV64
+   target, in which case the isa xlen is 8-bytes, and the abi xlen is
+   4-bytes.  This will impact how inferior functions are called.  */
+extern int riscv_abi_xlen (struct gdbarch *gdbarch);
+
+/* Return the width in bytes of the floating point register abi for
+   GDBARCH.  This reflects how the binary was compiled rather than the
+   hardware that is available.  It is possible that a binary is compiled
+   for single precision floating point, and then run on a target with
+   double precision floating point.  A return value of 0 indicates that no
+   floating point abi is in use (floating point arguments will be passed
+   in integer registers) other possible return value are 4, 8, or 16 as
+   with RISCV_ISA_FLEN.  */
+extern int riscv_abi_flen (struct gdbarch *gdbarch);
+
 /* Single step based on where the current instruction will take us.  */
 extern std::vector<CORE_ADDR> riscv_software_single_step
   (struct regcache *regcache);