aboutsummaryrefslogtreecommitdiff
path: root/gdb/arch
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/arch')
-rw-r--r--gdb/arch/arc.c108
-rw-r--r--gdb/arch/arc.h79
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 */