diff options
Diffstat (limited to 'gdb/arch')
-rw-r--r-- | gdb/arch/arc.c | 108 | ||||
-rw-r--r-- | gdb/arch/arc.h | 79 |
2 files changed, 145 insertions, 42 deletions
diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c index 9552b4a..8e126ca 100644 --- a/gdb/arch/arc.c +++ b/gdb/arch/arc.c @@ -17,42 +17,106 @@ #include "gdbsupport/common-defs.h" -#include <stdlib.h> - #include "arc.h" +#include <stdlib.h> +#include <unordered_map> +#include <string> /* Target description features. */ -#include "features/arc/core-v2.c" -#include "features/arc/aux-v2.c" -#include "features/arc/core-arcompact.c" -#include "features/arc/aux-arcompact.c" +#include "features/arc/v1-core.c" +#include "features/arc/v1-aux.c" +#include "features/arc/v2-core.c" +#include "features/arc/v2-aux.c" -/* See arc.h. */ +#ifndef GDBSERVER +#define STATIC_IN_GDB static +#else +#define STATIC_IN_GDB +#endif -target_desc * -arc_create_target_description (arc_sys_type sys_type) +STATIC_IN_GDB target_desc * +arc_create_target_description (const struct arc_gdbarch_features &features) { + /* Create a new target description. */ target_desc *tdesc = allocate_target_description (); - long regnum = 0; - #ifndef IN_PROCESS_AGENT - if (sys_type == ARC_SYS_TYPE_ARCV2) - set_tdesc_architecture (tdesc, "arc:ARCv2"); - else - set_tdesc_architecture (tdesc, "arc:ARC700"); -#endif + std::string arch_name; - if (sys_type == ARC_SYS_TYPE_ARCV2) + /* Architecture names here must match the ones in + ARCH_INFO_STRUCT in bfd/cpu-arc.c. */ + if (features.isa == ARC_ISA_ARCV1 && features.reg_size == 4) + arch_name = "arc:ARC700"; + else if (features.isa == ARC_ISA_ARCV2 && features.reg_size == 4) + arch_name = "arc:ARCv2"; + else { - regnum = create_feature_arc_core_v2 (tdesc, regnum); - regnum = create_feature_arc_aux_v2 (tdesc, regnum); + std::string msg = string_printf + ("Cannot determine architecture: ISA=%d; bitness=%d", + features.isa, 8 * features.reg_size); + gdb_assert_not_reached (msg.c_str ()); } - else + + set_tdesc_architecture (tdesc, arch_name.c_str ()); +#endif + + long regnum = 0; + + switch (features.isa) { - regnum = create_feature_arc_core_arcompact (tdesc, regnum); - regnum = create_feature_arc_aux_arcompact (tdesc, regnum); + case ARC_ISA_ARCV1: + regnum = create_feature_arc_v1_core (tdesc, regnum); + regnum = create_feature_arc_v1_aux (tdesc, regnum); + break; + case ARC_ISA_ARCV2: + regnum = create_feature_arc_v2_core (tdesc, regnum); + regnum = create_feature_arc_v2_aux (tdesc, regnum); + break; + default: + std::string msg = string_printf + ("Cannot choose target description XML: %d", features.isa); + gdb_assert_not_reached (msg.c_str ()); } return tdesc; } + +#ifndef GDBSERVER + +/* Wrapper used by std::unordered_map to generate hash for features set. */ +struct arc_gdbarch_features_hasher +{ + std::size_t + operator() (const arc_gdbarch_features &features) const noexcept + { + return features.hash (); + } +}; + +/* Cache of previously created target descriptions, indexed by the hash + of the features set used to create them. */ +static std::unordered_map<arc_gdbarch_features, + const target_desc_up, + arc_gdbarch_features_hasher> arc_tdesc_cache; + +/* See arch/arc.h. */ + +const target_desc * +arc_lookup_target_description (const struct arc_gdbarch_features &features) +{ + /* Lookup in the cache first. If found, return the pointer from the + "target_desc_up" type which is a "unique_ptr". This should be fine + as the "arc_tdesc_cache" will persist until GDB terminates. */ + const auto it = arc_tdesc_cache.find (features); + if (it != arc_tdesc_cache.end ()) + return it->second.get (); + + target_desc *tdesc = arc_create_target_description (features); + + /* Add the newly created target description to the repertoire. */ + arc_tdesc_cache.emplace (features, tdesc); + + return tdesc; +} + +#endif /* !GDBSERVER */ diff --git a/gdb/arch/arc.h b/gdb/arch/arc.h index fd806ae..a5313b1 100644 --- a/gdb/arch/arc.h +++ b/gdb/arch/arc.h @@ -20,29 +20,68 @@ #include "gdbsupport/tdesc.h" -/* Supported ARC system hardware types. */ -enum arc_sys_type +/* Supported ARC ISAs. */ +enum arc_isa { - ARC_SYS_TYPE_ARCOMPACT = 0, /* ARC600 or ARC700 */ - ARC_SYS_TYPE_ARCV2, /* ARC EM or ARC HS */ - ARC_SYS_TYPE_NUM + ARC_ISA_ARCV1 = 1, /* a.k.a. ARCompact (ARC600, ARC700) */ + ARC_ISA_ARCV2 /* such as ARC EM and ARC HS */ }; -static inline const char * -arc_sys_type_to_str (const arc_sys_type type) +struct arc_gdbarch_features { - switch (type) - { - case ARC_SYS_TYPE_ARCOMPACT: - return "ARC_SYS_TYPE_ARCOMPACT"; - case ARC_SYS_TYPE_ARCV2: - return "ARC_SYS_TYPE_ARCV2"; - default: - return "Invalid"; - } -} - -/* Create target description for the specified system type. */ -target_desc *arc_create_target_description (arc_sys_type sys_type); + arc_gdbarch_features (int reg_size, arc_isa isa) + : reg_size (reg_size), isa (isa) + {} + + /* Register size in bytes. Possible values are 4, and 8. A 0 indicates + an uninitialised value. */ + const int reg_size; + + /* See ARC_ISA enum. */ + const arc_isa isa; + + /* Equality operator. */ + bool operator== (const struct arc_gdbarch_features &rhs) const + { + return (reg_size == rhs.reg_size && isa == rhs.isa); + } + + /* Inequality operator. */ + bool operator!= (const struct arc_gdbarch_features &rhs) const + { + return !(*this == rhs); + } + + /* Used by std::unordered_map to hash the feature sets. The hash is + calculated in the manner below: + REG_SIZE | ISA + 5-bits | 4-bits */ + + std::size_t hash () const noexcept + { + std::size_t val = ((reg_size & 0x1f) << 8 | (isa & 0xf) << 0); + return val; + } +}; + +#ifdef GDBSERVER + +/* Create and return a target description that is compatible with FEATURES. + The only external client of this must be the gdbserver which manipulates + the returned data. */ + +target_desc *arc_create_target_description + (const struct arc_gdbarch_features &features); + +#else + +/* Lookup the cache for a target description matching the FEATURES. + If nothing is found, then create one and return it. */ + +const target_desc *arc_lookup_target_description + (const struct arc_gdbarch_features &features); + +#endif /* GDBSERVER */ + #endif /* ARCH_ARC_H */ |