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.
This commit is contained in:
Tom Tromey 2022-05-03 08:18:14 -06:00
parent 2808125fbb
commit e73434e38f
7 changed files with 208 additions and 582 deletions

View 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. */

View file

@ -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. */

View 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. */

View 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 ();

View file

@ -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) */

View file

@ -26,19 +26,21 @@
#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;
int reg_offsets[LAST_REGISTER + 1];
private:
/* 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)
riscv_ravenscar_ops::riscv_ravenscar_ops (struct gdbarch *arch)
: ravenscar_arch_ops (gdb::make_array_view (reg_offsets, LAST_REGISTER + 1))
{
int reg_size = riscv_isa_xlen (arch);
for (int regnum = 0; regnum <= LAST_REGISTER; ++regnum)
{
int offset;
if (regnum == RISCV_RA_REGNUM || regnum == RISCV_PC_REGNUM)
@ -56,85 +58,19 @@ riscv_ravenscar_ops::register_offset (struct gdbarch *arch, int 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)
{
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);
offset = -1;
if (offset != -1)
{
current_address = thread_descriptor_address + offset;
supply_register_at_address (regcache, current_regnum,
current_address);
offset *= reg_size;
reg_offsets[regnum] = offset;
}
}
}
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;
regcache->raw_collect (regnum, buf);
write_memory (register_address,
buf,
buf_size);
}
}
/* 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));
}

View file

@ -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. */