aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2022-05-03 08:18:14 -0600
committerTom Tromey <tromey@adacore.com>2022-06-14 09:08:29 -0600
commite73434e38f55e21cc33457ce3b218fa7b4592fec (patch)
treee3e443b6bbd889dc8cc9ff321a946a09052dbdd4
parent2808125fbb5f9c55f52e863283b7f1c5f0ef1a65 (diff)
downloadgdb-e73434e38f55e21cc33457ce3b218fa7b4592fec.zip
gdb-e73434e38f55e21cc33457ce3b218fa7b4592fec.tar.gz
gdb-e73434e38f55e21cc33457ce3b218fa7b4592fec.tar.bz2
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.
-rw-r--r--gdb/aarch64-ravenscar-thread.c121
-rw-r--r--gdb/amd64-ravenscar-thread.c112
-rw-r--r--gdb/ppc-ravenscar-thread.c154
-rw-r--r--gdb/ravenscar-thread.c113
-rw-r--r--gdb/ravenscar-thread.h42
-rw-r--r--gdb/riscv-ravenscar-thread.c120
-rw-r--r--gdb/sparc-ravenscar-thread.c124
7 files changed, 206 insertions, 580 deletions
diff --git a/gdb/aarch64-ravenscar-thread.c b/gdb/aarch64-ravenscar-thread.c
index dc35537..045d022 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 d06cdf8..18c000d 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 42d7334..0691a63 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 aae6e39..e300095 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 df75066..5d5661f 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 b2a7b6e..e28e178 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 014d898..b199afb 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. */