This patch adds target support to or32.
Registers names and groups are dynamically created from the tdesc
remote file.
For example, we could have:
<feature name="org.gnu.gdb.or32.group10">
<reg name="ttmr" bitsize="32" regnum="2216" group="timer"/>
<reg name="ttcr" bitsize="32" regnum="2217" group="timer"/>
</feature>
Then, a group "timer" would be created and timer registers would
be accessible using "info registers timer" and "set $ttmr ..."
While receiving the tdesc file, found registers and groups are
displayed. For example:
Remote debugging using :50001
Found 93 registers in feature org.gnu.gdb.or32.group0
Found 1035 registers in feature org.gnu.gdb.or32.group1
Found 1035 registers in feature org.gnu.gdb.or32.group2
Found 6 registers in feature org.gnu.gdb.or32.group3
Found 4 registers in feature org.gnu.gdb.or32.group4
Found 2 registers in feature org.gnu.gdb.or32.group5
Found 22 registers in feature org.gnu.gdb.or32.group6
Found 16 registers in feature org.gnu.gdb.or32.group7
Found 1 registers in feature org.gnu.gdb.or32.group8
Found 2 registers in feature org.gnu.gdb.or32.group9
Found 2 registers in feature org.gnu.gdb.or32.group10
Found 2218 registers in the tdesc file
Available groups can be displayed with:
(gdb) maintenance print reggroups
Group Type
system user
dmmu user
immu user
dcache user
icache user
mac user
debug user
perf user
power user
pic user
timer user
Signed-off-by: Franck Jullien <[email protected]>
---
gdb/or32-tdep.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 214 insertions(+), 7 deletions(-)
diff --git a/gdb/or32-tdep.c b/gdb/or32-tdep.c
index aa0e953..56f81cf 100644
--- a/gdb/or32-tdep.c
+++ b/gdb/or32-tdep.c
@@ -7,6 +7,8 @@
and by Per Bothner([email protected]) at U.Wisconsin.
Contributor Jeremy Bennett <[email protected]>
+ Contributor Franck Jullien <[email protected]>
+
This file is part of GDB.
This program is free software; you can redistribute it and/or modify it
@@ -101,6 +103,8 @@
#include "dwarf2-frame.h"
#include "trad-frame.h"
#include "regset.h"
+#include "remote.h"
+#include "target-descriptions.h"
#include <inttypes.h>
@@ -651,12 +655,23 @@ or32_register_name (struct gdbarch *gdbarch,
"ppc", "npc", "sr"
/* Floating point and vector registers may appear as pseudo registers in
- the future. */
+ the future. */
};
- return or32_gdb_reg_names[regnum];
+ /* If we have a target description, use it */
+ if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
+ return tdesc_register_name (gdbarch, regnum);
+ else
+ {
+ if (0 <= regnum && regnum < OR32_NUM_REGS_CACHED)
+ {
+ return or32_gdb_reg_names[regnum];
+ }
+ else
+ return NULL;
+ }
-} /* or32_register_name() */
+} /* or32_register_name() */
/*----------------------------------------------------------------------------*/
@@ -736,6 +751,8 @@ or32_registers_info (struct gdbarch *gdbarch,
int regnum,
int all)
{
+ struct regcache *regcache = get_current_regcache ();
+
if (-1 == regnum)
{
/* Do all (valid) registers */
@@ -751,12 +768,19 @@ or32_registers_info (struct gdbarch *gdbarch,
else
{
/* Do one specified register - if it is part of this architecture */
- if ('\0' == *(or32_register_name (gdbarch, regnum)))
+ if ((regnum < OR32_NUM_REGS_CACHED)
+ && ('\0' == *(or32_register_name (gdbarch, regnum))))
{
error ("Not a valid register for the current processor type");
}
else
{
+ /* If the register is not in the g/G packet, fetch it from the
+ * target with a p/P packet.
+ */
+ if (regnum >= OR32_NUM_REGS_CACHED)
+ target_fetch_registers (regcache, regnum);
+
default_print_registers_info (gdbarch, file, frame, regnum, all);
}
}
@@ -815,8 +839,16 @@ or32_register_reggroup_p (struct gdbarch *gdbarch,
return 0; /* No vector regs. */
}
- /* For any that are not handled above. */
- return default_register_reggroup_p (gdbarch, regnum, group);
+ if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
+ {
+ if ((tdesc_register_in_reggroup_p (gdbarch, regnum, group)) != 1)
+ return 0;
+ else
+ return 1;
+ }
+ else
+ /* For any that are not handled above. */
+ return default_register_reggroup_p (gdbarch, regnum, group);
} /* or32_register_reggroup_p() */
@@ -1752,6 +1784,112 @@ or32_regset_from_core_section (struct gdbarch *gdbarch,
} /* or32_regset_from_core_section () */
+/* --------------------------------------------------------------------------
*/
+/*!Create a register group based on a group name.
+
+ We create a group only if group_name is not already a register group name.
+
+ @param[in] gdbarch The GDB architecture we are using.
+ @param[in] group_name Name of the new register group.
+
+ @return 1 if the group has been created, 0 otherwise. */
+/* --------------------------------------------------------------------------
*/
+static int
+create_register_group (struct gdbarch *gdbarch, const char *group_name)
+{
+ struct reggroup *group;
+ static int first = 1;
+ int group_exist = 0;
+
+ if (!first)
+ {
+ for (group = reggroup_next (gdbarch, NULL);
+ group != NULL; group = reggroup_next (gdbarch, group))
+ {
+ if (strcmp (group_name, reggroup_name (group)) == 0)
+ group_exist = 1;
+ }
+
+ if (!group_exist)
+ {
+ /* If the group doesn't exist, create it */
+ reggroup_add (gdbarch, reggroup_new (group_name, USER_REGGROUP));
+ return 1;
+ }
+ }
+ else
+ {
+ /* reggroup_next cannot be called during architecture. However,
+ * a first call to reggroup_add execute reggroups_init and then
+ * reggroup_next can be use. We assume the first group name we
+ * create does not exist.
+ */
+ reggroup_add (gdbarch, reggroup_new (group_name, USER_REGGROUP));
+ first = 0;
+ }
+
+ return 0;
+}
+
+/* --------------------------------------------------------------------------
*/
+/*!Register all reg found in a feature section.
+
+ Register all reg found in a feature section and create a group for each
+ new register group name found in the tdesc file.
+
+ @param[in] feature The feature to search for registers.
+ @param[out] tdesc_data The target descriptor data to fill.
+ @param[out] reg_index Register index in tdesc_data.
+ @param[in] gdbarch The GDB architecture we are using.
+
+ @return Number of registers found, -1 if error.
*/
+/* --------------------------------------------------------------------------
*/
+static int
+get_feature_registers (const struct tdesc_feature *feature,
+ struct tdesc_arch_data *tdesc_data, int *reg_index,
+ struct gdbarch *gdbarch)
+{
+ int valid_p;
+ int i;
+ char *name;
+ char *group_name;
+
+ if (feature)
+ {
+ valid_p = 1;
+ i = 0;
+ while (1)
+ {
+ name = tdesc_find_register_name (feature, i);
+ if (name)
+ {
+ valid_p &=
+ tdesc_numbered_register (feature, tdesc_data, (*reg_index)++,
+ name);
+ if (valid_p)
+ {
+ group_name = tdesc_find_register_group_name (feature, i);
+ if (group_name)
+ create_register_group (gdbarch, group_name);
+ }
+ i++;
+ }
+ else
+ break;
+ }
+
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return -1;
+ }
+
+ return i;
+
+ }
+
+ return 0;
+}
/* --------------------------------------------------------------------------
*/
/*!Architecture initialization for OpenRISC 1000
@@ -1772,6 +1910,12 @@ or32_gdbarch_init (struct gdbarch_info info,
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
const struct bfd_arch_info *binfo;
+ struct tdesc_arch_data *tdesc_data = NULL;
+
+ int i;
+ int reg_index = 0;
+ int retval;
+ int group;
/* Find a candidate among the list of pre-declared architectures. */
arches = gdbarch_list_lookup_by_info (arches, &info);
@@ -1874,9 +2018,69 @@ or32_gdbarch_init (struct gdbarch_info info,
dwarf2_append_unwinders (gdbarch);
frame_unwind_append_unwinder (gdbarch, &or32_frame_unwind);
+ /* Check any target description for validity. */
+ if (tdesc_has_registers (info.target_desc))
+ {
+
+ const struct tdesc_feature *feature;
+ int total_regs = 0;
+ int nb_features;
+ char feature_name[30];
+
+ tdesc_data = tdesc_data_alloc ();
+
+ /* OpenRisc architecture manual define a maximum of 32 registers group */
+ for (group = 0; group < 32; group++)
+ {
+
+ sprintf (feature_name, "org.gnu.gdb.or32.group%d", group);
+ feature = tdesc_find_feature (info.target_desc, feature_name);
+
+ retval =
+ get_feature_registers (feature, tdesc_data, ®_index, gdbarch);
+
+ if (retval < 0)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+ else
+ {
+ total_regs += retval;
+ if (retval)
+ printf ("Found %4d registers in feature %s\n", retval,
+ feature_name);
+ }
+ }
+
+ printf ("Found %4d registers in the tdesc file\n", total_regs);
+
+ if (!total_regs)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+ }
+
+ if (tdesc_data)
+ {
+ tdesc_use_registers (gdbarch, info.target_desc, tdesc_data);
+
+ /* Override the normal target description methods to handle our
+ dual real and pseudo registers. */
+ set_gdbarch_register_name (gdbarch, or32_register_name);
+ set_gdbarch_register_reggroup_p (gdbarch, or32_register_reggroup_p);
+
+ set_gdbarch_register_name (gdbarch, or32_register_name);
+ set_gdbarch_sp_regnum (gdbarch, OR32_SP_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, OR32_NPC_REGNUM);
+ set_gdbarch_num_pseudo_regs (gdbarch, OR32_NUM_PSEUDO_REGS);
+ }
+
return gdbarch;
-} /* or32_gdbarch_init() */
+} /* or32_gdbarch_init() */
+
/*----------------------------------------------------------------------------*/
@@ -2921,6 +3125,9 @@ _initialize_or32_tdep (void)
/* Initialize the automata for the assembler */
build_automata();
+ /* Tell remote stub that we support XML target description. */
+ register_remote_support_xml ("or32");
+
/* Commands to show and set special purpose registers */
add_info ("spr", or32_info_spr_command,
"Show the value of a special purpose register");
--
1.7.1
_______________________________________________
OpenRISC mailing list
[email protected]
http://lists.openrisc.net/listinfo/openrisc