Reimplement ravenscar registers using tables
authorTom Tromey <tromey@adacore.com>
Tue, 3 May 2022 14:18:14 +0000 (08:18 -0600)
committerTom Tromey <tromey@adacore.com>
Tue, 14 Jun 2022 15:08:29 +0000 (09:08 -0600)
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.

gdb/aarch64-ravenscar-thread.c
gdb/amd64-ravenscar-thread.c
gdb/ppc-ravenscar-thread.c
gdb/ravenscar-thread.c
gdb/ravenscar-thread.h
gdb/riscv-ravenscar-thread.c
gdb/sparc-ravenscar-thread.c

index dc35537e3d589edf66b465d34a56b0a71ea3ea62..045d022fc23d427f29993e41b420c2337200709f 100644 (file)
@@ -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.  */
 
index d06cdf8b7a210c63296afde6b7d49ec509275a33..18c000dc9883939fc9b2c39fbb296ae9f3e40697 100644 (file)
 #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.  */
 
index 42d7334b93f9b06c5b44049b66d7071b07cef4e5..0691a6317d5ef46537032505777ad44fa8578719 100644 (file)
@@ -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.  */
 
index aae6e397327f601bd4e624b9a16f885ce6481d14..e300095b53ff7c08fa3c64b16c1ccbb4e62698a9 100644 (file)
@@ -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 ();
 
index df750667ab9795e95560b3be5cba9884f8c873a9..5d5661f48dff9906ae56ef4e85253c2cc82c9f22 100644 (file)
 
 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) */
index b2a7b6e0096784255acc2d7715b57d2b8dd4f3d3..e28e17878c3ab5140e53c0d2b4b4b45818acb597 100644 (file)
 #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));
 }
index 014d8981d7b74e18ca8548cf4cfcbb388781a2ac..b199afb99c098bbe0968113d0427eed5b41b8c60 100644 (file)
 #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.  */