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, &reg_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

Reply via email to