From 67fd78c3fa5894e0038c09a858cb518c20340abf Mon Sep 17 00:00:00 2001
From: Mahesh Bodapati <mbodapat@xilinx.com>
Date: Tue, 9 Nov 2021 16:19:17 +0530
Subject: [PATCH 10/10] [Patch,MicroBlaze] : Added m64 abi for 64 bit target
 descriptions. set m64 abi for 64 bit elf.

---
 gdb/features/microblaze64.xml |   1 +
 gdb/microblaze-tdep.c         | 150 ++++++++++++++++++++++++++++++++--
 gdb/microblaze-tdep.h         |  11 +++
 3 files changed, 155 insertions(+), 7 deletions(-)

diff --git a/gdb/features/microblaze64.xml b/gdb/features/microblaze64.xml
index 515d18e65cf..9c1b7d22003 100644
--- a/gdb/features/microblaze64.xml
+++ b/gdb/features/microblaze64.xml
@@ -7,5 +7,6 @@
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
 <target>
+  <architecture>microblaze64</architecture>
   <xi:include href="microblaze64-core.xml"/>
 </target>
diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
index e51c022c1ba..3bffbbe4b3d 100644
--- a/gdb/microblaze-tdep.c
+++ b/gdb/microblaze-tdep.c
@@ -65,8 +65,94 @@
 #define IS_SAVE_HIDDEN_PTR(op, rd, ra, rb) \
   ((op == add || op == addik) && ra == MICROBLAZE_FIRST_ARGREG && rb == 0)
 
+static const char *microblaze_abi_string;
+
+static const char *const microblaze_abi_strings[] = {
+  "auto",
+  "m64",
+};
+
+enum microblaze_abi
+microblaze_abi (struct gdbarch *gdbarch)
+{
+  return gdbarch_tdep (gdbarch)->microblaze_abi;
+}
 /* The registers of the Xilinx microblaze processor.  */
 
+ static struct cmd_list_element *setmicroblazecmdlist = NULL;
+ static struct cmd_list_element *showmicroblazecmdlist = NULL;
+
+static void
+microblaze_abi_update (const char *ignore_args,
+                 int from_tty, struct cmd_list_element *c)
+{
+  struct gdbarch_info info;
+
+  /* Force the architecture to update, and (if it's a microblaze architecture)
+ *      microblaze_gdbarch_init will take care of the rest.  */
+  gdbarch_info_init (&info);
+  gdbarch_update_p (info);
+}
+
+
+static enum microblaze_abi
+global_microblaze_abi (void)
+{
+  int i;
+
+  for (i = 0; microblaze_abi_strings[i] != NULL; i++)
+    if (microblaze_abi_strings[i] == microblaze_abi_string)
+      return (enum microblaze_abi) i;
+
+//  internal_error (__FILE__, __LINE__, _("unknown ABI string"));
+}
+
+static void
+show_microblaze_abi (struct ui_file *file,
+               int from_tty,
+               struct cmd_list_element *ignored_cmd,
+               const char *ignored_value)
+{
+      enum microblaze_abi global_abi = global_microblaze_abi ();
+      enum microblaze_abi actual_abi = microblaze_abi (target_gdbarch ());
+      const char *actual_abi_str = microblaze_abi_strings[actual_abi];
+
+#if 1 
+      if (global_abi == MICROBLAZE_ABI_AUTO)
+        fprintf_filtered
+          (file,
+           "The microblaze ABI is set automatically (currently \"%s\").\n",
+           actual_abi_str);	
+      else if (global_abi == actual_abi)
+        fprintf_filtered
+          (file,
+           "The microblaze ABI is assumed to be \"%s\" (due to user setting).\n",
+           actual_abi_str);
+      else
+        {
+#endif
+          /* Probably shouldn't happen...  */
+          fprintf_filtered (file,
+                            "The (auto detected) microblaze ABI \"%s\" is in use "
+                            "even though the user setting was \"%s\".\n",
+             actual_abi_str, microblaze_abi_strings[global_abi]);
+        }
+}		   
+
+static void
+show_microblaze_command (const char *args, int from_tty)
+{
+  help_list (showmicroblazecmdlist, "show microblaze ", all_commands, gdb_stdout);
+}
+
+static void
+set_microblaze_command (const char *args, int from_tty)
+{
+  printf_unfiltered
+    ("\"set microblaze\" must be followed by an appropriate subcommand.\n");
+  help_list (setmicroblazecmdlist, "set microblaze ", all_commands, gdb_stdout);
+}
+
 static const char *microblaze_register_names[] =
 {
   "r0",   "r1",  "r2",    "r3",   "r4",   "r5",   "r6",   "r7",
@@ -85,6 +171,18 @@ static const char *microblaze_register_names[] =
 static unsigned int microblaze_debug_flag = 0;
 int reg_size = 4;
 
+unsigned int
+microblaze_abi_regsize (struct gdbarch *gdbarch)
+{
+  switch (microblaze_abi (gdbarch))
+    {
+    case MICROBLAZE_ABI_M64:
+      return 8;
+    default:
+      return 4;
+    }
+}
+
 static void ATTRIBUTE_PRINTF (1, 2)
 microblaze_debug (const char *fmt, ...)
 { 
@@ -855,15 +953,30 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   struct gdbarch_tdep *tdep;
   struct gdbarch *gdbarch;
   struct tdesc_arch_data *tdesc_data = NULL;
+  enum microblaze_abi microblaze_abi, found_abi, wanted_abi;
   const struct target_desc *tdesc = info.target_desc;
 
+ /* What has the user specified from the command line?  */
+  wanted_abi = global_microblaze_abi ();
+  if (gdbarch_debug)
+    fprintf_unfiltered (gdb_stdlog, "microblaze_gdbarch_init: wanted_abi = %d\n",
+                        wanted_abi);
+  if (wanted_abi != MICROBLAZE_ABI_AUTO)
+    microblaze_abi = wanted_abi;
+
   /* If there is already a candidate, use it.  */
   arches = gdbarch_list_lookup_by_info (arches, &info);
-  if (arches != NULL)
+  if ((arches != NULL) && (microblaze_abi != MICROBLAZE_ABI_M64))
     return arches->gdbarch;
+
+  if (microblaze_abi == MICROBLAZE_ABI_M64)
+    {
+          tdesc = tdesc_microblaze64;
+          reg_size = 8;
+    }
   if (tdesc == NULL)
     {
-      if (info.bfd_arch_info->mach == bfd_mach_microblaze64) 
+      if ((info.bfd_arch_info->mach == bfd_mach_microblaze64) || (microblaze_abi == MICROBLAZE_ABI_M64)) 
         {
     	  tdesc = tdesc_microblaze64;
           reg_size = 8;
@@ -878,7 +991,7 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       int valid_p;
       int i;
 
-      if (info.bfd_arch_info->mach == bfd_mach_microblaze64)
+      if ((info.bfd_arch_info->mach == bfd_mach_microblaze64) || (microblaze_abi == MICROBLAZE_ABI_M64))
         feature = tdesc_find_feature (tdesc,
                                     "org.gnu.gdb.microblaze64.core");
       else
@@ -892,7 +1005,7 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       for (i = 0; i < MICROBLAZE_NUM_REGS; i++)
         valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
                                             microblaze_register_names[i]);
-      if (info.bfd_arch_info->mach == bfd_mach_microblaze64)
+      if ((info.bfd_arch_info->mach == bfd_mach_microblaze64) || (microblaze_abi == MICROBLAZE_ABI_M64))
         feature = tdesc_find_feature (tdesc,
                                     "org.gnu.gdb.microblaze64.stack-protect");
       else
@@ -943,7 +1056,8 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_ptr_bit (gdbarch, 64);
     break;
     }
-
+  if(microblaze_abi == MICROBLAZE_ABI_M64)
+    set_gdbarch_ptr_bit (gdbarch, 64);
   
   /* Map Dwarf2 registers to GDB registers.  */
   set_gdbarch_dwarf2_reg_to_regnum (gdbarch, microblaze_dwarf2_reg_to_regnum);
@@ -1000,7 +1114,30 @@ void
 _initialize_microblaze_tdep ()
 {
   register_gdbarch_init (bfd_arch_microblaze, microblaze_gdbarch_init);
-
+// static struct cmd_list_element *setmicroblazecmdlist = NULL;
+// static struct cmd_list_element *showmicroblazecmdlist = NULL;
+
+  /* Add root prefix command for all "set microblaze"/"show microblaze" commands.  */
+  add_prefix_cmd ("microblaze", no_class, set_microblaze_command,
+                  _("Various microblaze specific commands."),
+                  &setmicroblazecmdlist, "set microblaze ", 0, &setlist);
+
+  add_prefix_cmd ("microblaze", no_class, show_microblaze_command,
+                  _("Various microblaze specific commands."),
+                  &showmicroblazecmdlist, "show microblaze ", 0, &showlist);
+
+  /* Allow the user to override the ABI.  */
+  add_setshow_enum_cmd ("abi", class_obscure, microblaze_abi_strings,
+                        &microblaze_abi_string, _("\
+Set the microblaze ABI used by this program."), _("\
+Show the microblaze ABI used by this program."), _("\
+This option can be set to one of:\n\
+  auto  - the default ABI associated with the current binary\n\
+  m64"),
+                       microblaze_abi_update,
+		       show_microblaze_abi,
+                       &setmicroblazecmdlist, &showmicroblazecmdlist);
+  
   initialize_tdesc_microblaze_with_stack_protect ();
   initialize_tdesc_microblaze ();
   initialize_tdesc_microblaze64_with_stack_protect ();
@@ -1015,5 +1152,4 @@ When non-zero, microblaze specific debugging is enabled."),
 			     NULL,
 			     &setdebuglist, &showdebuglist);
 
-
 }
diff --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h
index a5c12c10e0b..29da6d29dcb 100644
--- a/gdb/microblaze-tdep.h
+++ b/gdb/microblaze-tdep.h
@@ -19,8 +19,16 @@
 
 #ifndef MICROBLAZE_TDEP_H
 #define MICROBLAZE_TDEP_H 1
+#include "objfiles.h"
 
+struct gdbarch;
+enum microblaze_abi
+  {
+    MICROBLAZE_ABI_AUTO = 0,
+    MICROBLAZE_ABI_M64,
+ };
 
+enum microblaze_abi microblaze_abi (struct gdbarch *gdbarch);
 /* Microblaze architecture-specific information.  */
 struct microblaze_gregset
 {
@@ -34,11 +42,14 @@ struct gdbarch_tdep
 {
   int dummy;		// declare something.
 
+  enum microblaze_abi microblaze_abi;
+  enum microblaze_abi found_abi;
   /* Register sets.  */
   struct regset *gregset;
   size_t sizeof_gregset;
   struct regset *fpregset;
   size_t sizeof_fpregset;
+  int register_size;
 };
 
 /* Register numbers.  */
-- 
2.17.1

