+/* Extract a set of required target features out of INFO, specifically the
+ bfd being executed is examined to see what target features it requires.
+ IF there is no current bfd, or the bfd doesn't indicate any useful
+ features then a RISCV_GDBARCH_FEATURES is returned in its default state. */
+
+static struct riscv_gdbarch_features
+riscv_features_from_gdbarch_info (const struct gdbarch_info info)
+{
+ struct riscv_gdbarch_features features;
+
+ /* Now try to improve on the defaults by looking at the binary we are
+ going to execute. We assume the user knows what they are doing and
+ that the target will match the binary. Remember, this code path is
+ only used at all if the target hasn't given us a description, so this
+ is really a last ditched effort to do something sane before giving
+ up. */
+ if (info.abfd != NULL
+ && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
+ {
+ unsigned char eclass = elf_elfheader (info.abfd)->e_ident[EI_CLASS];
+ int e_flags = elf_elfheader (info.abfd)->e_flags;
+
+ if (eclass == ELFCLASS32)
+ features.xlen = 4;
+ else if (eclass == ELFCLASS64)
+ features.xlen = 8;
+ else
+ internal_error (__FILE__, __LINE__,
+ _("unknown ELF header class %d"), eclass);
+
+ if (e_flags & EF_RISCV_FLOAT_ABI_DOUBLE)
+ features.flen = 8;
+ else if (e_flags & EF_RISCV_FLOAT_ABI_SINGLE)
+ features.flen = 4;
+ }
+
+ return features;
+}
+
+/* Find a suitable default target description. Use the contents of INFO,
+ specifically the bfd object being executed, to guide the selection of a
+ suitable default target description. */
+
+static const struct target_desc *
+riscv_find_default_target_description (const struct gdbarch_info info)
+{
+ /* Extract desired feature set from INFO. */
+ struct riscv_gdbarch_features features
+ = riscv_features_from_gdbarch_info (info);
+
+ /* If the XLEN field is still 0 then we got nothing useful from INFO. In
+ this case we fall back to a minimal useful target, 8-byte x-registers,
+ with no floating point. */
+ if (features.xlen == 0)
+ features.xlen = 8;
+
+ /* Now build a target description based on the feature set. */
+ return riscv_lookup_target_description (features);
+}
+
+/* All of the registers in REG_SET are checked for in FEATURE, TDESC_DATA
+ is updated with the register numbers for each register as listed in
+ REG_SET. If any register marked as required in REG_SET is not found in
+ FEATURE then this function returns false, otherwise, it returns true. */
+
+static bool
+riscv_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
+ const struct tdesc_feature *feature,
+ const struct riscv_register_feature *reg_set)
+{
+ for (const auto ® : reg_set->registers)
+ {
+ bool found = false;
+
+ for (const char *name : reg.names)
+ {
+ found =
+ tdesc_numbered_register (feature, tdesc_data, reg.regnum, name);
+
+ if (found)
+ break;
+ }
+
+ if (!found && reg.required_p)
+ return false;
+ }
+
+ return true;
+}
+
+/* Add all the expected register sets into GDBARCH. */
+
+static void
+riscv_add_reggroups (struct gdbarch *gdbarch)
+{
+ /* Add predefined register groups. */
+ reggroup_add (gdbarch, all_reggroup);
+ reggroup_add (gdbarch, save_reggroup);
+ reggroup_add (gdbarch, restore_reggroup);
+ reggroup_add (gdbarch, system_reggroup);
+ reggroup_add (gdbarch, vector_reggroup);
+ reggroup_add (gdbarch, general_reggroup);
+ reggroup_add (gdbarch, float_reggroup);
+
+ /* Add RISC-V specific register groups. */
+ reggroup_add (gdbarch, csr_reggroup);
+}
+
+/* Create register aliases for all the alternative names that exist for
+ registers in REG_SET. */
+
+static void
+riscv_setup_register_aliases (struct gdbarch *gdbarch,
+ const struct riscv_register_feature *reg_set)
+{
+ for (auto ® : reg_set->registers)
+ {
+ /* The first item in the names list is the preferred name for the
+ register, this is what RISCV_REGISTER_NAME returns, and so we
+ don't need to create an alias with that name here. */
+ for (int i = 1; i < reg.names.size (); ++i)
+ user_reg_add (gdbarch, reg.names[i], value_of_riscv_user_reg,
+ ®.regnum);
+ }
+}
+
+/* Implement the "dwarf2_reg_to_regnum" gdbarch method. */
+
+static int
+riscv_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
+{
+ if (reg < RISCV_DWARF_REGNUM_X31)
+ return RISCV_ZERO_REGNUM + (reg - RISCV_DWARF_REGNUM_X0);
+
+ else if (reg < RISCV_DWARF_REGNUM_F31)
+ return RISCV_FIRST_FP_REGNUM + (reg - RISCV_DWARF_REGNUM_F0);
+
+ return -1;
+}
+
+/* Implement the gcc_target_options method. We have to select the arch and abi
+ from the feature info. We have enough feature info to select the abi, but
+ not enough info for the arch given all of the possible architecture
+ extensions. So choose reasonable defaults for now. */
+
+static std::string
+riscv_gcc_target_options (struct gdbarch *gdbarch)
+{
+ int isa_xlen = riscv_isa_xlen (gdbarch);
+ int isa_flen = riscv_isa_flen (gdbarch);
+ int abi_xlen = riscv_abi_xlen (gdbarch);
+ int abi_flen = riscv_abi_flen (gdbarch);
+ std::string target_options;
+
+ target_options = "-march=rv";
+ if (isa_xlen == 8)
+ target_options += "64";
+ else
+ target_options += "32";
+ if (isa_flen == 8)
+ target_options += "gc";
+ else if (isa_flen == 4)
+ target_options += "imafc";
+ else
+ target_options += "imac";
+
+ target_options += " -mabi=";
+ if (abi_xlen == 8)
+ target_options += "lp64";
+ else
+ target_options += "ilp32";
+ if (abi_flen == 8)
+ target_options += "d";
+ else if (abi_flen == 4)
+ target_options += "f";
+
+ /* The gdb loader doesn't handle link-time relaxation relocations. */
+ target_options += " -mno-relax";
+
+ return target_options;
+}
+
+/* Implement the gnu_triplet_regexp method. A single compiler supports both
+ 32-bit and 64-bit code, and may be named riscv32 or riscv64 or (not
+ recommended) riscv. */
+
+static const char *
+riscv_gnu_triplet_regexp (struct gdbarch *gdbarch)
+{
+ return "riscv(32|64)?";
+}
+