public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] Reimplement ravenscar registers using tables
@ 2022-06-14 15:13 Tom Tromey
  0 siblings, 0 replies; only message in thread
From: Tom Tromey @ 2022-06-14 15:13 UTC (permalink / raw)
  To: gdb-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e73434e38f55e21cc33457ce3b218fa7b4592fec

commit e73434e38f55e21cc33457ce3b218fa7b4592fec
Author: Tom Tromey <tromey@adacore.com>
Date:   Tue May 3 08:18:14 2022 -0600

    Reimplement ravenscar registers using tables
    
    Currently, the ravenscar-thread implementation for each architecture
    is written by hand.  However, these are actually written by
    copy-paste.  It seems better to switch to a table-driven approach.
    
    The previous code also fetched all registers whenever any register was
    requested.  This is corrected in the new implementation.

Diff:
---
 gdb/aarch64-ravenscar-thread.c | 121 +-------------------------------
 gdb/amd64-ravenscar-thread.c   | 112 +++++-------------------------
 gdb/ppc-ravenscar-thread.c     | 154 +----------------------------------------
 gdb/ravenscar-thread.c         | 113 +++++++++++++++++++++++++++++-
 gdb/ravenscar-thread.h         |  42 ++++++++++-
 gdb/riscv-ravenscar-thread.c   | 120 ++++++++------------------------
 gdb/sparc-ravenscar-thread.c   | 124 +--------------------------------
 7 files changed, 206 insertions(+), 580 deletions(-)

diff --git a/gdb/aarch64-ravenscar-thread.c b/gdb/aarch64-ravenscar-thread.c
index dc35537e3d5..045d022fc23 100644
--- a/gdb/aarch64-ravenscar-thread.c
+++ b/gdb/aarch64-ravenscar-thread.c
@@ -61,127 +61,10 @@ static const int aarch64_context_offsets[] =
   112,       116,
 };
 
-/* The register layout info.  */
-
-struct ravenscar_reg_info
-{
-  /* A table providing the offset relative to the context structure
-     where each register is saved.  */
-  const int *context_offsets;
-
-  /* The number of elements in the context_offsets table above.  */
-  int context_offsets_size;
-};
-
-/* supply register REGNUM, which has been saved on REGISTER_ADDR, to the
-   regcache.  */
-
-static void
-supply_register_at_address (struct regcache *regcache, int regnum,
-			    CORE_ADDR register_addr)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  int buf_size = register_size (gdbarch, regnum);
-  gdb_byte *buf;
-
-  buf = (gdb_byte *) alloca (buf_size);
-  read_memory (register_addr, buf, buf_size);
-  regcache->raw_supply (regnum, buf);
-}
-
-/* Return true if, for a non-running thread, REGNUM has been saved on the
-   Thread_Descriptor.  */
-
-static int
-register_in_thread_descriptor_p (const struct ravenscar_reg_info *reg_info,
-				 int regnum)
-{
-  /* Check FPU registers */
-  return (regnum < reg_info->context_offsets_size
-	  && reg_info->context_offsets[regnum] != NO_OFFSET);
-}
-
-/* to_fetch_registers when inferior_ptid is different from the running
-   thread.  */
-
-static void
-aarch64_ravenscar_generic_fetch_registers
-  (const struct ravenscar_reg_info *reg_info,
-   struct regcache *regcache, int regnum)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  const int num_regs = gdbarch_num_regs (gdbarch);
-  int current_regnum;
-  CORE_ADDR current_address;
-  CORE_ADDR thread_descriptor_address;
-
-  /* The tid is the thread_id field, which is a pointer to the thread.  */
-  thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid ();
-
-  /* Read registers.  */
-  for (current_regnum = 0; current_regnum < num_regs; current_regnum++)
-    {
-      if (register_in_thread_descriptor_p (reg_info, current_regnum))
-	{
-	  current_address = thread_descriptor_address
-	    + reg_info->context_offsets[current_regnum];
-	  supply_register_at_address (regcache, current_regnum,
-				      current_address);
-	}
-    }
-}
-
-/* to_store_registers when inferior_ptid is different from the running
-   thread.  */
-
-static void
-aarch64_ravenscar_generic_store_registers
-  (const struct ravenscar_reg_info *reg_info,
-   struct regcache *regcache, int regnum)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  int buf_size = register_size (gdbarch, regnum);
-  gdb_byte buf[buf_size];
-  ULONGEST register_address;
-
-  if (register_in_thread_descriptor_p (reg_info, regnum))
-    register_address
-      = inferior_ptid.tid () + reg_info->context_offsets [regnum];
-  else
-    return;
-
-  regcache->raw_collect (regnum, buf);
-  write_memory (register_address,
-		buf,
-		buf_size);
-}
-
-/* The ravenscar_reg_info for most Aarch64 targets.  */
-
-static const struct ravenscar_reg_info aarch64_reg_info =
-{
-  aarch64_context_offsets,
-  ARRAY_SIZE (aarch64_context_offsets),
-};
-
-struct aarch64_ravenscar_ops : public ravenscar_arch_ops
-{
-  void fetch_registers (struct regcache *regcache, int regnum) override
-  {
-    aarch64_ravenscar_generic_fetch_registers
-      (&aarch64_reg_info, regcache, regnum);
-  }
-
-  void store_registers (struct regcache *regcache, int regnum) override
-  {
-    aarch64_ravenscar_generic_store_registers
-      (&aarch64_reg_info, regcache, regnum);
-  }
-};
-
 /* The ravenscar_arch_ops vector for most Aarch64 targets.  */
 
-static struct aarch64_ravenscar_ops aarch64_ravenscar_ops;
+static struct ravenscar_arch_ops aarch64_ravenscar_ops
+     (aarch64_context_offsets);
 
 /* Register aarch64_ravenscar_ops in GDBARCH.  */
 
diff --git a/gdb/amd64-ravenscar-thread.c b/gdb/amd64-ravenscar-thread.c
index d06cdf8b7a2..18c000dc988 100644
--- a/gdb/amd64-ravenscar-thread.c
+++ b/gdb/amd64-ravenscar-thread.c
@@ -26,17 +26,6 @@
 #include "ravenscar-thread.h"
 #include "amd64-ravenscar-thread.h"
 
-struct amd64_ravenscar_ops : public ravenscar_arch_ops
-{
-  void fetch_registers (struct regcache *regcache, int regnum) override;
-  void store_registers (struct regcache *regcache, int regnum) override;
-
-private:
-
-  /* Return the offset of the register in the context buffer.  */
-  int register_offset (struct gdbarch *arch, int regnum);
-};
-
 /* x86-64 Ravenscar stores registers as:
 
    type Context_Buffer is record
@@ -54,92 +43,29 @@ private:
 */
 static const int register_layout[] =
 {
-  AMD64_RIP_REGNUM,
-  AMD64_EFLAGS_REGNUM,
-  AMD64_RSP_REGNUM,
-  AMD64_RBX_REGNUM,
-  AMD64_RBP_REGNUM,
-  AMD64_R12_REGNUM,
-  AMD64_R13_REGNUM,
-  AMD64_R14_REGNUM,
-  AMD64_R15_REGNUM,
+  /* RAX */ -1,
+  /* RBX */ 3 * 8,
+  /* RCX */ -1,
+  /* RDX */ -1,
+  /* RSI */ -1,
+  /* RDI */ -1,
+  /* RBP */ 4 * 8,
+  /* RSP */ 2 * 8,
+  /* R8 */ -1,
+  /* R9 */ -1,
+  /* R10 */ -1,
+  /* R11 */ -1,
+  /* R12 */ 5 * 8,
+  /* R13 */ 6 * 8,
+  /* R14 */ 7 * 8,
+  /* R15 */ 8 * 8,
+  /* RIP */ 0 * 8,
+  /* EFLAGS */ 1 * 8,
 };
 
-int
-amd64_ravenscar_ops::register_offset (struct gdbarch *arch, int regnum)
-{
-  for (int i = 0; i < ARRAY_SIZE (register_layout); ++i)
-    if (register_layout[i] == regnum)
-      return i * 8;
-  /* Not saved.  */
-  return -1;
-}
-
-/* Supply register REGNUM, which has been saved at REGISTER_ADDR, to
-   the regcache.  */
-
-static void
-supply_register_at_address (struct regcache *regcache, int regnum,
-                            CORE_ADDR register_addr)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  int buf_size = register_size (gdbarch, regnum);
-  gdb_byte *buf;
-
-  buf = (gdb_byte *) alloca (buf_size);
-  read_memory (register_addr, buf, buf_size);
-  regcache->raw_supply (regnum, buf);
-}
-
-void
-amd64_ravenscar_ops::fetch_registers (struct regcache *regcache, int regnum)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  const int num_regs = gdbarch_num_regs (gdbarch);
-  int current_regnum;
-  CORE_ADDR current_address;
-  CORE_ADDR thread_descriptor_address;
-
-  /* The tid is the thread_id field, which is a pointer to the thread.  */
-  thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid ();
-
-  /* Read registers.  */
-  for (current_regnum = 0; current_regnum < num_regs; current_regnum++)
-    {
-      int offset = register_offset (gdbarch, current_regnum);
-
-      if (offset != -1)
-        {
-          current_address = thread_descriptor_address + offset;
-          supply_register_at_address (regcache, current_regnum,
-                                      current_address);
-        }
-    }
-}
-
-void
-amd64_ravenscar_ops::store_registers (struct regcache *regcache, int regnum)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  int buf_size = register_size (gdbarch, regnum);
-  gdb_byte buf[buf_size];
-  CORE_ADDR register_address;
-
-  int offset = register_offset (gdbarch, regnum);
-  if (offset != -1)
-    {
-      register_address = inferior_ptid.tid () + offset;
-
-      regcache->raw_collect (regnum, buf);
-      write_memory (register_address,
-		    buf,
-		    buf_size);
-    }
-}
-
 /* The ravenscar_arch_ops vector for AMD64 targets.  */
 
-static struct amd64_ravenscar_ops amd64_ravenscar_ops;
+static struct ravenscar_arch_ops amd64_ravenscar_ops (register_layout);
 
 /* Register amd64_ravenscar_ops in GDBARCH.  */
 
diff --git a/gdb/ppc-ravenscar-thread.c b/gdb/ppc-ravenscar-thread.c
index 42d7334b93f..0691a6317d5 100644
--- a/gdb/ppc-ravenscar-thread.c
+++ b/gdb/ppc-ravenscar-thread.c
@@ -100,129 +100,10 @@ static const int e500_context_offsets[] =
   NO_OFFSET, 176
 };
 
-/* The register layout info.  */
-
-struct ravenscar_reg_info
-{
-  /* A table providing the offset relative to the context structure
-     where each register is saved.  */
-  const int *context_offsets;
-
-  /* The number of elements in the context_offsets table above.  */
-  int context_offsets_size;
-};
-
-/* supply register REGNUM, which has been saved on REGISTER_ADDR, to the
-   regcache.  */
-
-static void
-supply_register_at_address (struct regcache *regcache, int regnum,
-			    CORE_ADDR register_addr)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  int buf_size = register_size (gdbarch, regnum);
-  gdb_byte *buf;
-
-  buf = (gdb_byte *) alloca (buf_size);
-  read_memory (register_addr, buf, buf_size);
-  regcache->raw_supply (regnum, buf);
-}
-
-/* Return true if, for a non-running thread, REGNUM has been saved on the
-   Thread_Descriptor.  */
-
-static int
-register_in_thread_descriptor_p (const struct ravenscar_reg_info *reg_info,
-				 int regnum)
-{
-  return (regnum < reg_info->context_offsets_size
-	  && reg_info->context_offsets[regnum] != NO_OFFSET);
-}
-
-/* to_fetch_registers when inferior_ptid is different from the running
-   thread.  */
-
-static void
-ppc_ravenscar_generic_fetch_registers
-  (const struct ravenscar_reg_info *reg_info,
-   struct regcache *regcache, int regnum)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  const int num_regs = gdbarch_num_regs (gdbarch);
-  int current_regnum;
-  CORE_ADDR current_address;
-  CORE_ADDR thread_descriptor_address;
-
-  /* The tid is the thread_id field, which is a pointer to the thread.  */
-  thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid ();
-
-  /* Read registers.  */
-  for (current_regnum = 0; current_regnum < num_regs; current_regnum++)
-    {
-      if (register_in_thread_descriptor_p (reg_info, current_regnum))
-	{
-	  current_address = thread_descriptor_address
-	    + reg_info->context_offsets[current_regnum];
-	  supply_register_at_address (regcache, current_regnum,
-				      current_address);
-	}
-    }
-}
-
-/* to_store_registers when inferior_ptid is different from the running
-   thread.  */
-
-static void
-ppc_ravenscar_generic_store_registers
-  (const struct ravenscar_reg_info *reg_info,
-   struct regcache *regcache, int regnum)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  int buf_size = register_size (gdbarch, regnum);
-  gdb_byte buf[buf_size];
-  ULONGEST register_address;
-
-  if (register_in_thread_descriptor_p (reg_info, regnum))
-    register_address
-      = inferior_ptid.tid () + reg_info->context_offsets [regnum];
-  else
-    return;
-
-  regcache->raw_collect (regnum, buf);
-  write_memory (register_address,
-		buf,
-		buf_size);
-}
-
-/* The ravenscar_reg_info for most PowerPC targets.  */
-
-static const struct ravenscar_reg_info ppc_reg_info =
-{
-  powerpc_context_offsets,
-  ARRAY_SIZE (powerpc_context_offsets),
-};
-
-struct ppc_ravenscar_powerpc_ops : public ravenscar_arch_ops
-{
-  void fetch_registers (struct regcache *, int) override;
-  void store_registers (struct regcache *, int) override;
-};
-
-void
-ppc_ravenscar_powerpc_ops::fetch_registers (struct regcache *regcache, int regnum)
-{
-  ppc_ravenscar_generic_fetch_registers (&ppc_reg_info, regcache, regnum);
-}
-
-void
-ppc_ravenscar_powerpc_ops::store_registers (struct regcache *regcache, int regnum)
-{
-  ppc_ravenscar_generic_store_registers (&ppc_reg_info, regcache, regnum);
-}
-
 /* The ravenscar_arch_ops vector for most PowerPC targets.  */
 
-static struct ppc_ravenscar_powerpc_ops ppc_ravenscar_powerpc_ops;
+static struct ravenscar_arch_ops ppc_ravenscar_powerpc_ops
+     (powerpc_context_offsets);
 
 /* Register ppc_ravenscar_powerpc_ops in GDBARCH.  */
 
@@ -232,38 +113,9 @@ register_ppc_ravenscar_ops (struct gdbarch *gdbarch)
   set_gdbarch_ravenscar_ops (gdbarch, &ppc_ravenscar_powerpc_ops);
 }
 
-/* The ravenscar_reg_info for E500 targets.  */
-
-static const struct ravenscar_reg_info e500_reg_info =
-{
-  e500_context_offsets,
-  ARRAY_SIZE (e500_context_offsets),
-};
-
-struct ppc_ravenscar_e500_ops : public ravenscar_arch_ops
-{
-  void fetch_registers (struct regcache *, int) override;
-  void store_registers (struct regcache *, int) override;
-};
-
-void
-ppc_ravenscar_e500_ops::fetch_registers (struct regcache *regcache, int regnum)
-{
-  ppc_ravenscar_generic_fetch_registers (&e500_reg_info, regcache, regnum);
-}
-
-/* Implement the to_store_registers ravenscar_arch_ops method
-   for E500 targets.  */
-
-void
-ppc_ravenscar_e500_ops::store_registers (struct regcache *regcache, int regnum)
-{
-  ppc_ravenscar_generic_store_registers (&e500_reg_info, regcache, regnum);
-}
-
 /* The ravenscar_arch_ops vector for E500 targets.  */
 
-static struct ppc_ravenscar_e500_ops ppc_ravenscar_e500_ops;
+static struct ravenscar_arch_ops ppc_ravenscar_e500_ops (e500_context_offsets);
 
 /* Register ppc_ravenscar_e500_ops in GDBARCH.  */
 
diff --git a/gdb/ravenscar-thread.c b/gdb/ravenscar-thread.c
index aae6e397327..e300095b53f 100644
--- a/gdb/ravenscar-thread.c
+++ b/gdb/ravenscar-thread.c
@@ -477,6 +477,116 @@ ravenscar_thread_target::pid_to_str (ptid_t ptid)
 			phex_nz (ptid.tid (), sizeof (ULONGEST)));
 }
 
+CORE_ADDR
+ravenscar_arch_ops::get_stack_base (struct regcache *regcache) const
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  const int sp_regnum = gdbarch_sp_regnum (gdbarch);
+  ULONGEST stack_address;
+  regcache_cooked_read_unsigned (regcache, sp_regnum, &stack_address);
+  return (CORE_ADDR) stack_address;
+}
+
+void
+ravenscar_arch_ops::supply_one_register (struct regcache *regcache,
+					 int regnum,
+					 CORE_ADDR descriptor,
+					 CORE_ADDR stack_base) const
+{
+  CORE_ADDR addr;
+  if (regnum >= first_stack_register && regnum <= last_stack_register)
+    addr = stack_base;
+  else
+    addr = descriptor;
+  addr += offsets[regnum];
+
+  struct gdbarch *gdbarch = regcache->arch ();
+  int size = register_size (gdbarch, regnum);
+  gdb_byte *buf = (gdb_byte *) alloca (size);
+  read_memory (addr, buf, size);
+  regcache->raw_supply (regnum, buf);
+}
+
+void
+ravenscar_arch_ops::fetch_registers (struct regcache *regcache,
+				     int regnum) const
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  /* The tid is the thread_id field, which is a pointer to the thread.  */
+  CORE_ADDR thread_descriptor_address
+    = (CORE_ADDR) regcache->ptid ().tid ();
+
+  int sp_regno = -1;
+  CORE_ADDR stack_address = 0;
+  if (regnum == -1
+      || (regnum >= first_stack_register && regnum <= last_stack_register))
+    {
+      /* We must supply SP for get_stack_base, so recurse.  */
+      sp_regno = gdbarch_sp_regnum (gdbarch);
+      gdb_assert (!(sp_regno >= first_stack_register
+		    && sp_regno <= last_stack_register));
+      fetch_registers (regcache, sp_regno);
+      stack_address = get_stack_base (regcache);
+    }
+
+  if (regnum == -1)
+    {
+      /* Fetch all registers.  */
+      for (int reg = 0; reg < offsets.size (); ++reg)
+	if (reg != sp_regno && offsets[reg] != -1)
+	  supply_one_register (regcache, reg, thread_descriptor_address,
+			       stack_address);
+    }
+  else if (regnum < offsets.size () && offsets[regnum] != -1)
+    supply_one_register (regcache, regnum, thread_descriptor_address,
+			 stack_address);
+}
+
+void
+ravenscar_arch_ops::store_one_register (struct regcache *regcache, int regnum,
+					CORE_ADDR descriptor,
+					CORE_ADDR stack_base) const
+{
+  CORE_ADDR addr;
+  if (regnum >= first_stack_register && regnum <= last_stack_register)
+    addr = stack_base;
+  else
+    addr = descriptor;
+  addr += offsets[regnum];
+
+  struct gdbarch *gdbarch = regcache->arch ();
+  int size = register_size (gdbarch, regnum);
+  gdb_byte *buf = (gdb_byte *) alloca (size);
+  regcache->raw_collect (regnum, buf);
+  write_memory (addr, buf, size);
+}
+
+void
+ravenscar_arch_ops::store_registers (struct regcache *regcache,
+				     int regnum) const
+{
+  /* The tid is the thread_id field, which is a pointer to the thread.  */
+  CORE_ADDR thread_descriptor_address
+    = (CORE_ADDR) regcache->ptid ().tid ();
+
+  CORE_ADDR stack_address = 0;
+  if (regnum == -1
+      || (regnum >= first_stack_register && regnum <= last_stack_register))
+    stack_address = get_stack_base (regcache);
+
+  if (regnum == -1)
+    {
+      /* Store all registers.  */
+      for (int reg = 0; reg < offsets.size (); ++reg)
+	if (offsets[reg] != -1)
+	  store_one_register (regcache, reg, thread_descriptor_address,
+			      stack_address);
+    }
+  else if (regnum < offsets.size () && offsets[regnum] != -1)
+    store_one_register (regcache, regnum, thread_descriptor_address,
+			stack_address);
+}
+
 /* Temporarily set the ptid of a regcache to some other value.  When
    this object is destroyed, the regcache's original ptid is
    restored.  */
@@ -506,7 +616,8 @@ private:
 };
 
 void
-ravenscar_thread_target::fetch_registers (struct regcache *regcache, int regnum)
+ravenscar_thread_target::fetch_registers (struct regcache *regcache,
+					  int regnum)
 {
   ptid_t ptid = regcache->ptid ();
 
diff --git a/gdb/ravenscar-thread.h b/gdb/ravenscar-thread.h
index df750667ab9..5d5661f48df 100644
--- a/gdb/ravenscar-thread.h
+++ b/gdb/ravenscar-thread.h
@@ -24,12 +24,48 @@
 
 struct ravenscar_arch_ops
 {
-  virtual ~ravenscar_arch_ops ()
+  ravenscar_arch_ops (gdb::array_view<const int> offsets_,
+		      int first_stack = -1,
+		      int last_stack = -1)
+    : offsets (offsets_),
+      first_stack_register (first_stack),
+      last_stack_register (last_stack)
   {
+    /* These must either both be -1 or both be valid.  */
+    gdb_assert ((first_stack_register == -1) == (last_stack_register == -1));
+    /* They must also be ordered.  */
+    gdb_assert (last_stack_register >= first_stack_register);
   }
 
-  virtual void fetch_registers (struct regcache *, int) = 0;
-  virtual void store_registers (struct regcache *, int) = 0;
+  void fetch_registers (struct regcache *, int) const;
+  void store_registers (struct regcache *, int) const;
+
+private:
+
+  /* An array where the indices are register numbers and the contents
+     are offsets.  The offsets are either in the thread descriptor or
+     the stack, depending on the other fields.  An offset of -1 means
+     that the corresponding register is not stored.  */
+  const gdb::array_view<const int> offsets;
+
+  /* If these are -1, then all registers for this architecture are
+     stored in the thread descriptor.  Otherwise, these mark a range
+     of registers that are stored on the stack.  */
+  const int first_stack_register;
+  const int last_stack_register;
+
+  /* Helper function to supply one register.  */
+  void supply_one_register (struct regcache *regcache, int regnum,
+			    CORE_ADDR descriptor,
+			    CORE_ADDR stack_base) const;
+  /* Helper function to store one register.  */
+  void store_one_register (struct regcache *regcache, int regnum,
+			   CORE_ADDR descriptor,
+			   CORE_ADDR stack_base) const;
+  /* Helper function to find stack address where registers are stored.
+     This must be called with the stack pointer already supplied in
+     the register cache.  */
+  CORE_ADDR get_stack_base (struct regcache *) const;
 };
 
 #endif /* !defined (RAVENSCAR_THREAD_H) */
diff --git a/gdb/riscv-ravenscar-thread.c b/gdb/riscv-ravenscar-thread.c
index b2a7b6e0096..e28e17878c3 100644
--- a/gdb/riscv-ravenscar-thread.c
+++ b/gdb/riscv-ravenscar-thread.c
@@ -26,115 +26,51 @@
 #include "ravenscar-thread.h"
 #include "riscv-ravenscar-thread.h"
 
+#define LAST_REGISTER (RISCV_FIRST_FP_REGNUM + 14)
+
 struct riscv_ravenscar_ops : public ravenscar_arch_ops
 {
-  void fetch_registers (struct regcache *regcache, int regnum) override;
-  void store_registers (struct regcache *regcache, int regnum) override;
-
-private:
+  int reg_offsets[LAST_REGISTER + 1];
 
-  /* Return the offset of the register in the context buffer.  */
-  int register_offset (struct gdbarch *arch, int regnum);
+  riscv_ravenscar_ops (struct gdbarch *arch);
 };
 
-int
-riscv_ravenscar_ops::register_offset (struct gdbarch *arch, int regnum)
-{
-  int offset;
-  if (regnum == RISCV_RA_REGNUM || regnum == RISCV_PC_REGNUM)
-    offset = 0;
-  else if (regnum == RISCV_SP_REGNUM)
-    offset = 1;
-  else if (regnum == RISCV_ZERO_REGNUM + 8) /* S0 */
-    offset = 2;
-  else if (regnum == RISCV_ZERO_REGNUM + 9) /* S1 */
-    offset = 3;
-  else if (regnum >= RISCV_ZERO_REGNUM + 19
-	   && regnum <= RISCV_ZERO_REGNUM + 27) /* S2..S11 */
-    offset = regnum - (RISCV_ZERO_REGNUM + 19) + 4;
-  else if (regnum >= RISCV_FIRST_FP_REGNUM
-	   && regnum <= RISCV_FIRST_FP_REGNUM + 11)
-    offset = regnum - RISCV_FIRST_FP_REGNUM + 14; /* FS0..FS11 */
-  else
-    {
-      /* Not saved.  */
-      return -1;
-    }
-
-  int size = register_size (arch, regnum);
-  return offset * size;
-}
-
-/* Supply register REGNUM, which has been saved on REGISTER_ADDR, to the
-   regcache.  */
-
-static void
-supply_register_at_address (struct regcache *regcache, int regnum,
-			    CORE_ADDR register_addr)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  int buf_size = register_size (gdbarch, regnum);
-  gdb_byte *buf;
-
-  buf = (gdb_byte *) alloca (buf_size);
-  read_memory (register_addr, buf, buf_size);
-  regcache->raw_supply (regnum, buf);
-}
-
-void
-riscv_ravenscar_ops::fetch_registers (struct regcache *regcache, int regnum)
+riscv_ravenscar_ops::riscv_ravenscar_ops (struct gdbarch *arch)
+  : ravenscar_arch_ops (gdb::make_array_view (reg_offsets, LAST_REGISTER + 1))
 {
-  struct gdbarch *gdbarch = regcache->arch ();
-  const int num_regs = gdbarch_num_regs (gdbarch);
-  int current_regnum;
-  CORE_ADDR current_address;
-  CORE_ADDR thread_descriptor_address;
-
-  /* The tid is the thread_id field, which is a pointer to the thread.  */
-  thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid ();
+  int reg_size = riscv_isa_xlen (arch);
 
-  /* Read registers.  */
-  for (current_regnum = 0; current_regnum < num_regs; current_regnum++)
+  for (int regnum = 0; regnum <= LAST_REGISTER; ++regnum)
     {
-      int offset = register_offset (gdbarch, current_regnum);
+      int offset;
+      if (regnum == RISCV_RA_REGNUM || regnum == RISCV_PC_REGNUM)
+	offset = 0;
+      else if (regnum == RISCV_SP_REGNUM)
+	offset = 1;
+      else if (regnum == RISCV_ZERO_REGNUM + 8) /* S0 */
+	offset = 2;
+      else if (regnum == RISCV_ZERO_REGNUM + 9) /* S1 */
+	offset = 3;
+      else if (regnum >= RISCV_ZERO_REGNUM + 19
+	       && regnum <= RISCV_ZERO_REGNUM + 27) /* S2..S11 */
+	offset = regnum - (RISCV_ZERO_REGNUM + 19) + 4;
+      else if (regnum >= RISCV_FIRST_FP_REGNUM
+	       && regnum <= RISCV_FIRST_FP_REGNUM + 11)
+	offset = regnum - RISCV_FIRST_FP_REGNUM + 14; /* FS0..FS11 */
+      else
+	offset = -1;
 
       if (offset != -1)
-	{
-	  current_address = thread_descriptor_address + offset;
-	  supply_register_at_address (regcache, current_regnum,
-				      current_address);
-	}
-    }
-}
-
-void
-riscv_ravenscar_ops::store_registers (struct regcache *regcache, int regnum)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  int buf_size = register_size (gdbarch, regnum);
-  gdb_byte buf[buf_size];
-  CORE_ADDR register_address;
-
-  int offset = register_offset (gdbarch, regnum);
-  if (offset != -1)
-    {
-      register_address = inferior_ptid.tid () + offset;
+	offset *= reg_size;
 
-      regcache->raw_collect (regnum, buf);
-      write_memory (register_address,
-		    buf,
-		    buf_size);
+      reg_offsets[regnum] = offset;
     }
 }
 
-/* The ravenscar_arch_ops vector for most RISC-V targets.  */
-
-static struct riscv_ravenscar_ops riscv_ravenscar_ops;
-
 /* Register riscv_ravenscar_ops in GDBARCH.  */
 
 void
 register_riscv_ravenscar_ops (struct gdbarch *gdbarch)
 {
-  set_gdbarch_ravenscar_ops (gdbarch, &riscv_ravenscar_ops);
+  set_gdbarch_ravenscar_ops (gdbarch, new riscv_ravenscar_ops (gdbarch));
 }
diff --git a/gdb/sparc-ravenscar-thread.c b/gdb/sparc-ravenscar-thread.c
index 014d8981d7b..b199afb99c0 100644
--- a/gdb/sparc-ravenscar-thread.c
+++ b/gdb/sparc-ravenscar-thread.c
@@ -26,12 +26,6 @@
 #include "sparc-ravenscar-thread.h"
 #include "gdbarch.h"
 
-struct sparc_ravenscar_ops : public ravenscar_arch_ops
-{
-  void fetch_registers (struct regcache *, int) override;
-  void store_registers (struct regcache *, int) override;
-};
-
 /* Register offsets from a referenced address (exempli gratia the
    Thread_Descriptor).  The referenced address depends on the register
    number.  The Thread_Descriptor layout and the stack layout are documented
@@ -56,121 +50,9 @@ static const int sparc_register_offsets[] =
   0x40, 0x20, 0x44, -1,   0x1C, -1,   0x4C, -1
 };
 
-/* supply register REGNUM, which has been saved on REGISTER_ADDR, to the
-   regcache.  */
-
-static void
-supply_register_at_address (struct regcache *regcache, int regnum,
-			    CORE_ADDR register_addr)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  int buf_size = register_size (gdbarch, regnum);
-  gdb_byte *buf;
-
-  buf = (gdb_byte *) alloca (buf_size);
-  read_memory (register_addr, buf, buf_size);
-  regcache->raw_supply (regnum, buf);
-}
-
-/* Return true if, for a non-running thread, REGNUM has been saved on the
-   stack.  */
-
-static int
-register_on_stack_p (int regnum)
-{
-  return (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM)
-    || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM);
-}
-
-/* Return true if, for a non-running thread, REGNUM has been saved on the
-   Thread_Descriptor.  */
-
-static int
-register_in_thread_descriptor_p (int regnum)
-{
-  return (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
-    || (regnum == SPARC32_PSR_REGNUM)
-    || (regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM)
-    || (regnum == SPARC32_Y_REGNUM)
-    || (regnum == SPARC32_WIM_REGNUM)
-    || (regnum == SPARC32_FSR_REGNUM)
-    || (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F0_REGNUM + 31)
-    || (regnum == SPARC32_PC_REGNUM);
-}
-
-/* to_fetch_registers when inferior_ptid is different from the running
-   thread.  */
-
-void
-sparc_ravenscar_ops::fetch_registers (struct regcache *regcache, int regnum)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  const int sp_regnum = gdbarch_sp_regnum (gdbarch);
-  const int num_regs = gdbarch_num_regs (gdbarch);
-  int current_regnum;
-  CORE_ADDR current_address;
-  CORE_ADDR thread_descriptor_address;
-  ULONGEST stack_address;
-
-  /* The tid is the thread_id field, which is a pointer to the thread.  */
-  thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid ();
-
-  /* Read the saved SP in the context buffer.  */
-  current_address = thread_descriptor_address
-    + sparc_register_offsets [sp_regnum];
-  supply_register_at_address (regcache, sp_regnum, current_address);
-  regcache_cooked_read_unsigned (regcache, sp_regnum, &stack_address);
-
-  /* Read registers.  */
-  for (current_regnum = 0; current_regnum < num_regs; current_regnum ++)
-    {
-      if (register_in_thread_descriptor_p (current_regnum))
-	{
-	  current_address = thread_descriptor_address
-	    + sparc_register_offsets [current_regnum];
-	  supply_register_at_address (regcache, current_regnum,
-				      current_address);
-	}
-      else if (register_on_stack_p (current_regnum))
-	{
-	  current_address = stack_address
-	    + sparc_register_offsets [current_regnum];
-	  supply_register_at_address (regcache, current_regnum,
-				      current_address);
-	}
-    }
-}
-
-/* to_store_registers when inferior_ptid is different from the running
-   thread.  */
-
-void
-sparc_ravenscar_ops::store_registers (struct regcache *regcache, int regnum)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  int buf_size = register_size (gdbarch, regnum);
-  gdb_byte buf[buf_size];
-  ULONGEST register_address;
-
-  if (register_in_thread_descriptor_p (regnum))
-    register_address =
-      inferior_ptid.tid () + sparc_register_offsets [regnum];
-  else if (register_on_stack_p (regnum))
-    {
-      regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM,
-				     &register_address);
-      register_address += sparc_register_offsets [regnum];
-    }
-  else
-    return;
-
-  regcache->raw_collect (regnum, buf);
-  write_memory (register_address,
-		buf,
-		buf_size);
-}
-
-static struct sparc_ravenscar_ops sparc_ravenscar_ops;
+static struct ravenscar_arch_ops sparc_ravenscar_ops (sparc_register_offsets,
+						      SPARC_L0_REGNUM,
+						      SPARC_I7_REGNUM);
 
 /* Register ravenscar_arch_ops in GDBARCH.  */


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-14 15:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-14 15:13 [binutils-gdb] Reimplement ravenscar registers using tables Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).