summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Blandy <jimb@codesourcery.com>2004-09-01 18:09:58 +0000
committerJim Blandy <jimb@codesourcery.com>2004-09-01 18:09:58 +0000
commit5b8919bf5f6cad5b72516e20bf1e80fb9713c5a1 (patch)
tree416df583986ba60bde3cbfc97bc520cc6a860461
parent2b6538ed8eba1c07f12efb198940a1cb853dc6d1 (diff)
downloadgdb-5b8919bf5f6cad5b72516e20bf1e80fb9713c5a1.tar.gz
Allow access to all 64 bits of the SPE GPR's in multi-threaded
programs. * ppc-tdep.h (struct speregset): New struct type. * ppc-linux-tdep.c: #include "gdb_assert.h". (ppc_linux_supply_speregset, ppc_linux_collect_speregset): New functions. (ppc_linux_speregset): New structure. (ppc_linux_init_abi): Describe how to pass the full 64-bit values of the SPE GPRs across the thread-db interface. * ppc-linux-nat.c (struct gdb_evrregset_t): Doc fix. * Makefile.in (ppc-linux-tdep.o): Update dependencies. Allow targets to specify an extended register set, to be passed through libthread_db via its 'xregs' functions. * gdbarch.sh (XREGS_REGSET, XREGS_SIZE, XREGS_NAME): New gdbarch members. * gdbarch.c, gdbarch.h: Regenerated. * proc-service.c: #include "regset.h" and "regcache.h". (ps_lgetxregsize, ps_lgetxregs, ps_lsetxregs): Fill in real implementations of these functions. * thread-db.c: #include "regset.h". (td_thr_getxregsize_p, td_thr_getxregs_p, td_thr_setxregs_p): New variables. (thread_db_load): Initialize them. (warned_xregs_not_implemented): New variable. (thread_db_new_objfile): Clear it here. (thread_db_fetch_registers, thread_db_store_registers): Supply and collect the xregset, too, if the architecture says it has one, and libthread_db seems to be able to support it. * Makefile.in (proc-service.o, thread-db.o): Update dependencies.
-rw-r--r--gdb/ChangeLog33
-rw-r--r--gdb/ppc-linux-nat.c7
-rw-r--r--gdb/ppc-linux-tdep.c105
3 files changed, 144 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index faeb4c79aa8..e0de9328b70 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,36 @@
+2004-09-01 Jim Blandy <jimb@redhat.com>
+
+ Allow access to all 64 bits of the SPE GPR's in multi-threaded
+ programs.
+ * ppc-tdep.h (struct speregset): New struct type.
+ * ppc-linux-tdep.c: #include "gdb_assert.h".
+ (ppc_linux_supply_speregset, ppc_linux_collect_speregset): New
+ functions.
+ (ppc_linux_speregset): New structure.
+ (ppc_linux_init_abi): Describe how to pass the full 64-bit values
+ of the SPE GPRs across the thread-db interface.
+ * ppc-linux-nat.c (struct gdb_evrregset_t): Doc fix.
+ * Makefile.in (ppc-linux-tdep.o): Update dependencies.
+
+ Allow targets to specify an extended register set, to be passed
+ through libthread_db via its 'xregs' functions.
+ * gdbarch.sh (XREGS_REGSET, XREGS_SIZE, XREGS_NAME): New gdbarch
+ members.
+ * gdbarch.c, gdbarch.h: Regenerated.
+ * proc-service.c: #include "regset.h" and "regcache.h".
+ (ps_lgetxregsize, ps_lgetxregs, ps_lsetxregs): Fill in real
+ implementations of these functions.
+ * thread-db.c: #include "regset.h".
+ (td_thr_getxregsize_p, td_thr_getxregs_p, td_thr_setxregs_p): New
+ variables.
+ (thread_db_load): Initialize them.
+ (warned_xregs_not_implemented): New variable.
+ (thread_db_new_objfile): Clear it here.
+ (thread_db_fetch_registers, thread_db_store_registers): Supply and
+ collect the xregset, too, if the architecture says it has one, and
+ libthread_db seems to be able to support it.
+ * Makefile.in (proc-service.o, thread-db.o): Update dependencies.
+
2004-08-25 Jim Blandy <jimb@redhat.com>
Merge changes from trunk:
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index c98bb93f879..e57f742ad9a 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -129,7 +129,12 @@ typedef char gdb_vrregset_t[SIZEOF_VRREGS];
bottom halves together.
This is the structure filled in by PTRACE_GETEVRREGS and written to
- the inferior's registers by PTRACE_SETEVRREGS. */
+ the inferior's registers by PTRACE_SETEVRREGS.
+
+ Note that this is not the same as 'struct speregset', which
+ describes how the ABI says the kernel dumps SPE-style 64-bit GPR's
+ in core files. It would be nicer if PTRACE_{GET,SET}EVRREGS and
+ core files used the same layout, but they don't. */
struct gdb_evrregset_t
{
unsigned long evr[32];
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 585260bf416..f9f2d84ff28 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -37,6 +37,7 @@
#include "ppc-tdep.h"
#include "trad-frame.h"
#include "frame-unwind.h"
+#include "gdb_assert.h"
/* The following instructions are used in the signal trampoline code
on GNU/Linux PPC. The kernel used to use magic syscalls 0x6666 and
@@ -1058,6 +1059,98 @@ ppc_linux_regset_from_core_section (struct gdbarch *core_arch,
}
static void
+ppc_linux_supply_speregset (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum,
+ const void *buf,
+ size_t len)
+{
+ struct gdbarch *arch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+ const struct speregset *speregset = buf;
+
+ gdb_assert (len == sizeof (*speregset));
+ gdb_assert (register_size (arch, tdep->ppc_ev0_regnum)
+ == sizeof (speregset->gpr[0]));
+ gdb_assert (register_size (arch, tdep->ppc_acc_regnum)
+ == sizeof (speregset->acc));
+ gdb_assert (register_size (arch, tdep->ppc_spefscr_regnum)
+ == sizeof (speregset->spefscr));
+
+ if (regnum == -1)
+ {
+ int i;
+
+ for (i = 0; i < 32; i++)
+ regcache_raw_supply (regcache, tdep->ppc_ev0_regnum + i,
+ &speregset->gpr[i]);
+ }
+ else if (tdep->ppc_ev0_regnum <= regnum
+ && regnum <= tdep->ppc_ev31_regnum)
+ regcache_raw_supply (regcache, tdep->ppc_ev0_regnum + regnum,
+ &speregset->gpr[regnum - tdep->ppc_ev0_regnum]);
+
+ if (regnum == tdep->ppc_acc_regnum
+ || regnum == -1)
+ regcache_raw_supply (regcache, tdep->ppc_acc_regnum,
+ &speregset->acc);
+
+ if (regnum == tdep->ppc_spefscr_regnum
+ || regnum == -1)
+ regcache_raw_supply (regcache, tdep->ppc_spefscr_regnum,
+ &speregset->spefscr);
+}
+
+static void
+ppc_linux_collect_speregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum,
+ void *buf,
+ size_t len)
+{
+ struct gdbarch *arch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+ struct speregset *speregset = buf;
+
+ gdb_assert (len == sizeof (*speregset));
+ gdb_assert (register_size (arch, tdep->ppc_ev0_regnum)
+ == sizeof (speregset->gpr[0]));
+ gdb_assert (register_size (arch, tdep->ppc_acc_regnum)
+ == sizeof (speregset->acc));
+ gdb_assert (register_size (arch, tdep->ppc_spefscr_regnum)
+ == sizeof (speregset->spefscr));
+
+ if (regnum == -1)
+ {
+ int i;
+
+ for (i = 0; i < 32; i++)
+ regcache_raw_collect (regcache, tdep->ppc_ev0_regnum + i,
+ &speregset->gpr[i]);
+ }
+ else if (tdep->ppc_ev0_regnum <= regnum
+ && regnum <= tdep->ppc_ev31_regnum)
+ regcache_raw_collect (regcache, regnum,
+ &speregset->gpr[regnum - tdep->ppc_ev0_regnum]);
+
+ if (regnum == tdep->ppc_acc_regnum
+ || regnum == -1)
+ regcache_raw_collect (regcache, tdep->ppc_acc_regnum, &speregset->acc);
+
+ if (regnum == tdep->ppc_spefscr_regnum
+ || regnum == -1)
+ regcache_raw_collect (regcache, tdep->ppc_spefscr_regnum,
+ &speregset->spefscr);
+}
+
+static const struct regset ppc_linux_speregset =
+{
+ 0,
+ ppc_linux_supply_speregset,
+ ppc_linux_collect_speregset
+};
+
+static void
ppc_linux_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch)
{
@@ -1093,6 +1186,18 @@ ppc_linux_init_abi (struct gdbarch_info info,
set_solib_svr4_fetch_link_map_offsets
(gdbarch, ppc_linux_svr4_fetch_link_map_offsets);
}
+
+ if (info.bfd_arch_info->arch == bfd_arch_powerpc
+ && info.bfd_arch_info->mach == bfd_mach_ppc_e500)
+ {
+ /* On the e500, the GPR's are really 64 bits long. However, we
+ continue to treat the gpr's as if they were 32 bits long, and
+ handle the upper haves separately. This means that we need a
+ special way to pass the upper halves through thread_db. */
+ set_gdbarch_xregs_regset (gdbarch, &ppc_linux_speregset);
+ set_gdbarch_xregs_size (gdbarch, sizeof (struct speregset));
+ set_gdbarch_xregs_name (gdbarch, "SPE vector");
+ }
if (tdep->wordsize == 8)
{