static void
store_cregs_to_thread (const struct regcache *regcache)
{
- /* Can't modify capability registers, do nothing. */
+ struct gdbarch *gdbarch = regcache->arch ();
+ gdb_assert (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64);
+
+ int tid = regcache->ptid ().lwp ();
+
+ struct user_morello_state cregset;
+ struct iovec iovec;
+ iovec.iov_base = &cregset;
+ iovec.iov_len = sizeof (cregset);
+
+ if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_MORELLO, &iovec) < 0)
+ perror_with_name (_("Unable to fetch capability registers."));
+
+ struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
+
+ /* Stored the C registers. */
+ int regno, i;
+ for (regno = tdep->cap_reg_base, i = 0;
+ regno < tdep->cap_reg_base + AARCH64_C_REGS_NUM;
+ regno++, i++)
+ regcache->raw_collect (regno, &cregset.cregs[i]);
+
+ /* Store the other registers. */
+ regcache->raw_collect (regno++, &cregset.csp);
+ regcache->raw_collect (regno++, &cregset.pcc);
+ regcache->raw_collect (regno++, &cregset.ddc);
+ regcache->raw_collect (regno++, &cregset.ctpidr);
+ regcache->raw_collect (regno++, &cregset.rcsp);
+ regcache->raw_collect (regno++, &cregset.rddc);
+ regcache->raw_collect (regno++, &cregset.rctpidr);
+ regcache->raw_collect (regno++, &cregset.cid);
+ regcache->raw_collect (regno++, &cregset.tag_map);
+ regcache->raw_collect (regno++, &cregset.cctlr);
+
+ if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_MORELLO, &iovec) < 0)
+ perror_with_name (_("Unable to store capability registers."));
}
/* Implement the "fetch_registers" target_ops method. */
store_tlsregs_to_thread (regcache);
if (tdep->has_capability ())
- {
- /* Due to the aliasing of X/C registers and due to register merging
- by the kernel (see documentation in the kernel), we should force
- a read of the C registers whenever the X registers are written
- to. */
- fetch_cregs_from_thread (regcache);
- store_cregs_to_thread (regcache);
- }
+ store_cregs_to_thread (regcache);
}
else if (tdep->has_capability () && regno >= tdep->cap_reg_base
&& regno < tdep->cap_reg_base + AARCH64_MORELLO_REGS_NUM)
- store_cregs_to_thread (regcache);
+ {
+ store_cregs_to_thread (regcache);
+ fetch_gregs_from_thread (regcache);
+ }
else if (regno < AARCH64_V0_REGNUM)
{
store_gregs_to_thread (regcache);
|| regnum == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base));
}
- if (tdep->has_capability ())
- {
- /* Capability register set is read-only for now. */
- return (regnum >= tdep->cap_reg_base && regnum < tdep->cap_reg_last);
- }
-
return 0;
}
regcache_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
struct gdbarch *gdbarch = regcache->arch ();
+ int regnum = gdbarch_pc_regnum (gdbarch);
+ int reg_size = register_size (gdbarch, regnum);
if (gdbarch_write_pc_p (gdbarch))
gdbarch_write_pc (gdbarch, regcache, pc);
else if (gdbarch_pc_regnum (gdbarch) >= 0)
- regcache_cooked_write_unsigned (regcache,
- gdbarch_pc_regnum (gdbarch), pc);
+ {
+ /* If our PC is bigger than a CORE_ADDR, only modify the required
+ bits. Leave the unmodified bits alone. */
+ if (reg_size > sizeof (pc))
+ regcache->cooked_write_part (regnum, 0, sizeof (pc),
+ (const gdb_byte *) &pc);
+ else
+ {
+ regcache_cooked_write_unsigned (regcache, regnum, pc);
+ }
+ }
else
internal_error (__FILE__, __LINE__,
_("regcache_write_pc: Unable to update PC"));
supply_register (regcache, tls_regnum, buf);
}
+/* Capability registers fill hook implementation. */
+
+static void
+aarch64_fill_cregset (struct regcache *regcache, void *buf)
+{
+ struct user_morello_state *cregset
+ = (struct user_morello_state *) buf;
+
+ int cregs_base = find_regno (regcache->tdesc, "c0");
+
+ /* Store the C registers to the buffer. */
+ int i, regno;
+ for (regno = cregs_base, i = 0;
+ regno < cregs_base + AARCH64_C_REGS_NUM;
+ regno++, i++)
+ collect_register (regcache, regno, &cregset->cregs[i]);
+
+ /* Store the other registers to the buffer. */
+ collect_register (regcache, regno++, &cregset->csp);
+ collect_register (regcache, regno++, &cregset->pcc);
+ collect_register (regcache, regno++, &cregset->ddc);
+ collect_register (regcache, regno++, &cregset->ctpidr);
+ collect_register (regcache, regno++, &cregset->rcsp);
+ collect_register (regcache, regno++, &cregset->rddc);
+ collect_register (regcache, regno++, &cregset->rctpidr);
+ collect_register (regcache, regno++, &cregset->cid);
+ collect_register (regcache, regno++, &cregset->tag_map);
+ collect_register (regcache, regno++, &cregset->cctlr);
+}
+
/* Capability registers store hook implementation. */
static void
/* FIXME-Morello: Fixup the register set size. */
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_MORELLO,
0, OPTIONAL_REGS,
- nullptr, aarch64_store_cregset },
+ aarch64_fill_cregset, aarch64_store_cregset },
NULL_REGSET
};