diff options
-rw-r--r-- | gdb/ChangeLog | 29 | ||||
-rw-r--r-- | gdb/arch/riscv.h | 15 | ||||
-rw-r--r-- | gdb/riscv-tdep.c | 81 | ||||
-rw-r--r-- | gdb/riscv-tdep.h | 37 |
4 files changed, 105 insertions, 57 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a6a42e4..6bb9ce7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,32 @@ +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 diff --git a/gdb/arch/riscv.h b/gdb/arch/riscv.h index 4a9a80d..05c1905 100644 --- a/gdb/arch/riscv.h +++ b/gdb/arch/riscv.h @@ -46,19 +46,10 @@ struct riscv_gdbarch_features that there are no f-registers. No other value is valid. */ int flen = 0; - /* This indicates if hardware floating point abi is in use. If the FLEN - field is 0 then this value _must_ be false. If the FLEN field is - non-zero and this field is false then this indicates the target has - floating point registers, but is still using the soft-float abi. If - this field is true then the hardware floating point abi is in use, and - values are passed in f-registers matching the size of FLEN. */ - bool hw_float_abi = false; - /* Equality operator. */ bool operator== (const struct riscv_gdbarch_features &rhs) const { - return (xlen == rhs.xlen && flen == rhs.flen - && hw_float_abi == rhs.hw_float_abi); + return (xlen == rhs.xlen && flen == rhs.flen); } /* Inequality operator. */ @@ -70,9 +61,7 @@ struct riscv_gdbarch_features /* Used by std::unordered_map to hash feature sets. */ std::size_t hash () const noexcept { - std::size_t val = ((xlen & 0x1f) << 6 - | (flen & 0x1f) << 1 - | (hw_float_abi ? 1 : 0)); + std::size_t val = ((xlen & 0x1f) << 5 | (flen & 0x1f) << 0); return val; } }; diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index ac3dd38..33c1c44 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -361,7 +361,15 @@ static unsigned int riscv_debug_gdbarch = 0; 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. */ @@ -369,7 +377,15 @@ riscv_isa_xlen (struct gdbarch *gdbarch) 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. */ @@ -385,7 +401,7 @@ riscv_has_fp_regs (struct gdbarch *gdbarch) 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. */ @@ -1786,8 +1802,8 @@ struct riscv_call_info : 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)) @@ -1807,7 +1823,7 @@ struct riscv_call_info 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; }; @@ -2148,9 +2164,6 @@ riscv_call_arg_struct (struct riscv_arg_info *ainfo, { 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)) @@ -2174,9 +2187,6 @@ riscv_call_arg_struct (struct riscv_arg_info *ainfo, { 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))); @@ -2889,15 +2899,9 @@ riscv_features_from_gdbarch_info (const struct gdbarch_info info) _("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 { @@ -3115,25 +3119,26 @@ riscv_gdbarch_init (struct gdbarch_info info, /* 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); @@ -3145,7 +3150,8 @@ riscv_gdbarch_init (struct gdbarch_info 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; @@ -3160,7 +3166,8 @@ riscv_gdbarch_init (struct gdbarch_info info, /* 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); diff --git a/gdb/riscv-tdep.h b/gdb/riscv-tdep.h index 212c1bb..4268839 100644 --- a/gdb/riscv-tdep.h +++ b/gdb/riscv-tdep.h @@ -68,9 +68,14 @@ enum /* 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; @@ -82,12 +87,30 @@ struct gdbarch_tdep 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); |