[PowerPC] Fix access to VSCR in linux targets
The 4-byte VSCR register is found inside a 16-byte field in the regset returned by ptrace and in core files. The position of VSCR depends on the endianess of the target, which was previously assumed to be big-endian for the purpose of getting VSCR. This patch removes this assumption to fix access to VSCR in little-endian mode. gdb/ChangeLog: 2018-05-22 Pedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com> * ppc-tdep.h (struct ppc_reg_offsets): Remove vector register offset fields. * ppc-fbsd-tdep.c (ppc32_fbsd_reg_offsets): Remove initializers for vector register offset fields. (ppc64_fbsd_reg_offsets): Likewise. * ppc-nbsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment to vector register offset fields. * ppc-obsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment to vector register offset fields. * ppc-obsd-nat.c (_initialize_ppcobsd_nat): Remove assignment to vector register offset fields. * rs6000-aix-tdep.c (rs6000_aix32_reg_offsets): Remove initializers for vector register offset fields. (rs6000_aix64_reg_offsets): Likewise. * rs6000-tdep.c (ppc_vrreg_offset): Remove. (ppc_supply_vrregset): Remove. (ppc_collect_vrregset): Remove. * ppc-linux-tdep.c (ppc_linux_collect_vrregset): New function. (ppc_linux_vrregset) : New function. (ppc32_le_linux_vrregmap, ppc32_be_linux_vrregmap) (ppc32_le_linux_vrregset, ppc32_be_linux_vrregset): New globals. (ppc32_linux_vrregset): Remove. (ppc_linux_iterate_over_regset_sections): Call ppc_linux_vrregset and use result instead of ppc32_linux_vrregset. (ppc32_linux_reg_offsets): Remove initializers for vector register offset fields. (ppc64_linux_reg_offsets): Likewise. * ppc-linux-tdep.h (ppc_linux_vrregset): New declaration. * ppc-linux-nat.c: Include regset.h. (gdb_vrregset_t): Adjust comment to account for little-endian mode. (supply_vrregset, fill_vrregset): Remove. (fetch_altivec_register, store_altivec_register): Remove. (fetch_altivec_registers): Add regno parameter. Get regset using ppc_linux_vrregset. Use regset to supply registers. (store_altivec_registers): Add regno parameter. Get regset using ppc_linux_vrregset. Use regset to collect registers. (fetch_register): Call fetch_altivec_registers instead of fetch_altivec_register. (store_register): Call store_altivec_registers instead of store_altivec_register. (fetch_ppc_registers): Call fetch_altivec_registers with -1 for the new regno parameter. (store_ppc_registers): Call store_altivec_registers with -1 for the new regno parameter. gdb/gdbserver/ChangeLog: 2018-05-22 Pedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com> * linux-ppc-low.c (ppc_fill_vrregset): Add vscr_offset variable. Set vscr_offset to 0 in little-endian mode and 12 in big-endian mode. Call collect_register_by_name with vscr using vscr_offset. Zero-pad vscr and vrsave fields in collector buffer. (ppc_store_vrregset): Add and set vscr_offset variable as in ppc_fill_vrregset. Call supply_register_by_name with vscr using vscr_offset.
This commit is contained in:
parent
d078308a2e
commit
1d75a65809
@ -1,3 +1,51 @@
|
||||
2018-05-22 Pedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com>
|
||||
|
||||
* ppc-tdep.h (struct ppc_reg_offsets): Remove vector register
|
||||
offset fields.
|
||||
* ppc-fbsd-tdep.c (ppc32_fbsd_reg_offsets): Remove initializers
|
||||
for vector register offset fields.
|
||||
(ppc64_fbsd_reg_offsets): Likewise.
|
||||
* ppc-nbsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment
|
||||
to vector register offset fields.
|
||||
* ppc-obsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment
|
||||
to vector register offset fields.
|
||||
* ppc-obsd-nat.c (_initialize_ppcobsd_nat): Remove assignment to
|
||||
vector register offset fields.
|
||||
* rs6000-aix-tdep.c (rs6000_aix32_reg_offsets): Remove
|
||||
initializers for vector register offset fields.
|
||||
(rs6000_aix64_reg_offsets): Likewise.
|
||||
* rs6000-tdep.c (ppc_vrreg_offset): Remove.
|
||||
(ppc_supply_vrregset): Remove.
|
||||
(ppc_collect_vrregset): Remove.
|
||||
* ppc-linux-tdep.c (ppc_linux_collect_vrregset): New function.
|
||||
(ppc_linux_vrregset) : New function.
|
||||
(ppc32_le_linux_vrregmap, ppc32_be_linux_vrregmap)
|
||||
(ppc32_le_linux_vrregset, ppc32_be_linux_vrregset): New globals.
|
||||
(ppc32_linux_vrregset): Remove.
|
||||
(ppc_linux_iterate_over_regset_sections): Call ppc_linux_vrregset
|
||||
and use result instead of ppc32_linux_vrregset.
|
||||
(ppc32_linux_reg_offsets): Remove initializers for vector register
|
||||
offset fields.
|
||||
(ppc64_linux_reg_offsets): Likewise.
|
||||
* ppc-linux-tdep.h (ppc_linux_vrregset): New declaration.
|
||||
* ppc-linux-nat.c: Include regset.h.
|
||||
(gdb_vrregset_t): Adjust comment to account for little-endian
|
||||
mode.
|
||||
(supply_vrregset, fill_vrregset): Remove.
|
||||
(fetch_altivec_register, store_altivec_register): Remove.
|
||||
(fetch_altivec_registers): Add regno parameter. Get regset using
|
||||
ppc_linux_vrregset. Use regset to supply registers.
|
||||
(store_altivec_registers): Add regno parameter. Get regset using
|
||||
ppc_linux_vrregset. Use regset to collect registers.
|
||||
(fetch_register): Call fetch_altivec_registers instead of
|
||||
fetch_altivec_register.
|
||||
(store_register): Call store_altivec_registers instead of
|
||||
store_altivec_register.
|
||||
(fetch_ppc_registers): Call fetch_altivec_registers with -1 for
|
||||
the new regno parameter.
|
||||
(store_ppc_registers): Call store_altivec_registers with -1 for
|
||||
the new regno parameter.
|
||||
|
||||
2018-05-22 Pedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com>
|
||||
|
||||
* arch/ppc-linux-common.h (PPC_LINUX_SIZEOF_VRREGSET)
|
||||
|
@ -1,3 +1,13 @@
|
||||
2018-05-22 Pedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com>
|
||||
|
||||
* linux-ppc-low.c (ppc_fill_vrregset): Add vscr_offset variable.
|
||||
Set vscr_offset to 0 in little-endian mode and 12 in big-endian
|
||||
mode. Call collect_register_by_name with vscr using
|
||||
vscr_offset. Zero-pad vscr and vrsave fields in collector buffer.
|
||||
(ppc_store_vrregset): Add and set vscr_offset variable as in
|
||||
ppc_fill_vrregset. Call supply_register_by_name with vscr using
|
||||
vscr_offset.
|
||||
|
||||
2018-05-22 Pedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com>
|
||||
|
||||
* linux-ppc-low.c (SIZEOF_VSXREGS, SIZEOF_VRREGS): Remove.
|
||||
|
@ -486,12 +486,22 @@ ppc_fill_vrregset (struct regcache *regcache, void *buf)
|
||||
{
|
||||
int i, base;
|
||||
char *regset = (char *) buf;
|
||||
int vscr_offset = 0;
|
||||
|
||||
base = find_regno (regcache->tdesc, "vr0");
|
||||
for (i = 0; i < 32; i++)
|
||||
collect_register (regcache, base + i, ®set[i * 16]);
|
||||
|
||||
collect_register_by_name (regcache, "vscr", ®set[32 * 16 + 12]);
|
||||
if (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
vscr_offset = 12;
|
||||
|
||||
/* Zero-pad the unused bytes in the fields for vscr and vrsave in
|
||||
case they get displayed somewhere. */
|
||||
memset (®set[32 * 16], 0, 16);
|
||||
collect_register_by_name (regcache, "vscr",
|
||||
®set[32 * 16 + vscr_offset]);
|
||||
|
||||
memset (®set[33 * 16], 0, 16);
|
||||
collect_register_by_name (regcache, "vrsave", ®set[33 * 16]);
|
||||
}
|
||||
|
||||
@ -500,12 +510,17 @@ ppc_store_vrregset (struct regcache *regcache, const void *buf)
|
||||
{
|
||||
int i, base;
|
||||
const char *regset = (const char *) buf;
|
||||
int vscr_offset = 0;
|
||||
|
||||
base = find_regno (regcache->tdesc, "vr0");
|
||||
for (i = 0; i < 32; i++)
|
||||
supply_register (regcache, base + i, ®set[i * 16]);
|
||||
|
||||
supply_register_by_name (regcache, "vscr", ®set[32 * 16 + 12]);
|
||||
if (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
vscr_offset = 12;
|
||||
|
||||
supply_register_by_name (regcache, "vscr",
|
||||
®set[32 * 16 + vscr_offset]);
|
||||
supply_register_by_name (regcache, "vrsave", ®set[33 * 16]);
|
||||
}
|
||||
|
||||
|
@ -56,13 +56,7 @@ static const struct ppc_reg_offsets ppc32_fbsd_reg_offsets =
|
||||
/* Floating-point registers. */
|
||||
/* .f0_offset = */ 0,
|
||||
/* .fpscr_offset = */ 256,
|
||||
/* .fpscr_size = */ 8,
|
||||
#ifdef NOTYET
|
||||
/* AltiVec registers. */
|
||||
/* .vr0_offset = */ 0,
|
||||
/* .vscr_offset = */ 512 + 12,
|
||||
/* .vrsave_offset = */ 512
|
||||
#endif
|
||||
/* .fpscr_size = */ 8
|
||||
};
|
||||
|
||||
/* 64-bit regset descriptions. */
|
||||
@ -84,13 +78,7 @@ static const struct ppc_reg_offsets ppc64_fbsd_reg_offsets =
|
||||
/* Floating-point registers. */
|
||||
/* .f0_offset = */ 0,
|
||||
/* .fpscr_offset = */ 256,
|
||||
/* .fpscr_size = */ 8,
|
||||
#ifdef NOYET
|
||||
/* AltiVec registers. */
|
||||
/* .vr0_offset = */ 0,
|
||||
/* .vscr_offset = */ 512 + 12,
|
||||
/* .vrsave_offset = */ 528
|
||||
#endif
|
||||
/* .fpscr_size = */ 8
|
||||
};
|
||||
|
||||
/* 32-bit general-purpose register set. */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "gdbthread.h"
|
||||
#include "gdbcore.h"
|
||||
#include "regcache.h"
|
||||
#include "regset.h"
|
||||
#include "target.h"
|
||||
#include "linux-nat.h"
|
||||
#include <sys/types.h>
|
||||
@ -160,17 +161,18 @@ struct ppc_hw_breakpoint
|
||||
Even though this vrsave register is not included in the regset
|
||||
typedef, it is handled by the ptrace requests.
|
||||
|
||||
Note that GNU/Linux doesn't support little endian PPC hardware,
|
||||
therefore the offset at which the real value of the VSCR register
|
||||
is located will be always 12 bytes.
|
||||
|
||||
The layout is like this (where x is the actual value of the vscr reg): */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
/*
|
||||
Big-Endian:
|
||||
|.|.|.|.|.....|.|.|.|.||.|.|.|x||.|
|
||||
<-------> <-------><-------><->
|
||||
VR0 VR31 VSCR VRSAVE
|
||||
Little-Endian:
|
||||
|.|.|.|.|.....|.|.|.|.||X|.|.|.||.|
|
||||
<-------> <-------><-------><->
|
||||
VR0 VR31 VSCR VRSAVE
|
||||
*/
|
||||
/* *INDENT-ON* */
|
||||
|
||||
@ -435,14 +437,13 @@ fetch_vsx_register (struct regcache *regcache, int tid, int regno)
|
||||
registers set mechanism, as opposed to the interface for all the
|
||||
other registers, that stores/fetches each register individually. */
|
||||
static void
|
||||
fetch_altivec_register (struct regcache *regcache, int tid, int regno)
|
||||
fetch_altivec_registers (struct regcache *regcache, int tid,
|
||||
int regno)
|
||||
{
|
||||
int ret;
|
||||
int offset = 0;
|
||||
gdb_vrregset_t regs;
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
|
||||
const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
|
||||
|
||||
ret = ptrace (PTRACE_GETVRREGS, tid, 0, ®s);
|
||||
if (ret < 0)
|
||||
@ -452,19 +453,11 @@ fetch_altivec_register (struct regcache *regcache, int tid, int regno)
|
||||
have_ptrace_getvrregs = 0;
|
||||
return;
|
||||
}
|
||||
perror_with_name (_("Unable to fetch AltiVec register"));
|
||||
perror_with_name (_("Unable to fetch AltiVec registers"));
|
||||
}
|
||||
|
||||
/* VSCR is fetched as a 16 bytes quantity, but it is really 4 bytes
|
||||
long on the hardware. We deal only with the lower 4 bytes of the
|
||||
vector. VRSAVE is at the end of the array in a 4 bytes slot, so
|
||||
there is no need to define an offset for it. */
|
||||
if (regno == (tdep->ppc_vrsave_regnum - 1))
|
||||
offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
|
||||
|
||||
regcache_raw_supply (regcache, regno,
|
||||
regs + (regno
|
||||
- tdep->ppc_vr0_regnum) * vrregsize + offset);
|
||||
|
||||
vrregset->supply_regset (vrregset, regcache, regno, ®s,
|
||||
PPC_LINUX_SIZEOF_VRREGSET);
|
||||
}
|
||||
|
||||
/* Fetch the top 32 bits of TID's general-purpose registers and the
|
||||
@ -559,7 +552,7 @@ fetch_register (struct regcache *regcache, int tid, int regno)
|
||||
register. */
|
||||
if (have_ptrace_getvrregs)
|
||||
{
|
||||
fetch_altivec_register (regcache, tid, regno);
|
||||
fetch_altivec_registers (regcache, tid, regno);
|
||||
return;
|
||||
}
|
||||
/* If we have discovered that there is no ptrace support for
|
||||
@ -646,31 +639,6 @@ supply_vsxregset (struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
supply_vrregset (struct regcache *regcache, gdb_vrregset_t *vrregsetp)
|
||||
{
|
||||
int i;
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
|
||||
int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
|
||||
int offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
|
||||
|
||||
for (i = 0; i < num_of_vrregs; i++)
|
||||
{
|
||||
/* The last 2 registers of this set are only 32 bit long, not
|
||||
128. However an offset is necessary only for VSCR because it
|
||||
occupies a whole vector, while VRSAVE occupies a full 4 bytes
|
||||
slot. */
|
||||
if (i == (num_of_vrregs - 2))
|
||||
regcache_raw_supply (regcache, tdep->ppc_vr0_regnum + i,
|
||||
*vrregsetp + i * vrregsize + offset);
|
||||
else
|
||||
regcache_raw_supply (regcache, tdep->ppc_vr0_regnum + i,
|
||||
*vrregsetp + i * vrregsize);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_vsx_registers (struct regcache *regcache, int tid)
|
||||
{
|
||||
@ -690,25 +658,6 @@ fetch_vsx_registers (struct regcache *regcache, int tid)
|
||||
supply_vsxregset (regcache, ®s);
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_altivec_registers (struct regcache *regcache, int tid)
|
||||
{
|
||||
int ret;
|
||||
gdb_vrregset_t regs;
|
||||
|
||||
ret = ptrace (PTRACE_GETVRREGS, tid, 0, ®s);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (errno == EIO)
|
||||
{
|
||||
have_ptrace_getvrregs = 0;
|
||||
return;
|
||||
}
|
||||
perror_with_name (_("Unable to fetch AltiVec registers"));
|
||||
}
|
||||
supply_vrregset (regcache, ®s);
|
||||
}
|
||||
|
||||
/* This function actually issues the request to ptrace, telling
|
||||
it to get all general-purpose registers and put them into the
|
||||
specified regset.
|
||||
@ -847,7 +796,7 @@ fetch_ppc_registers (struct regcache *regcache, int tid)
|
||||
fetch_register (regcache, tid, tdep->ppc_fpscr_regnum);
|
||||
if (have_ptrace_getvrregs)
|
||||
if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
|
||||
fetch_altivec_registers (regcache, tid);
|
||||
fetch_altivec_registers (regcache, tid, -1);
|
||||
if (have_ptrace_getsetvsxregs)
|
||||
if (tdep->ppc_vsr0_upper_regnum != -1)
|
||||
fetch_vsx_registers (regcache, tid);
|
||||
@ -898,16 +847,14 @@ store_vsx_register (const struct regcache *regcache, int tid, int regno)
|
||||
perror_with_name (_("Unable to store VSX register"));
|
||||
}
|
||||
|
||||
/* Store one register. */
|
||||
static void
|
||||
store_altivec_register (const struct regcache *regcache, int tid, int regno)
|
||||
store_altivec_registers (const struct regcache *regcache, int tid,
|
||||
int regno)
|
||||
{
|
||||
int ret;
|
||||
int offset = 0;
|
||||
gdb_vrregset_t regs;
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
|
||||
const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
|
||||
|
||||
ret = ptrace (PTRACE_GETVRREGS, tid, 0, ®s);
|
||||
if (ret < 0)
|
||||
@ -917,21 +864,15 @@ store_altivec_register (const struct regcache *regcache, int tid, int regno)
|
||||
have_ptrace_getvrregs = 0;
|
||||
return;
|
||||
}
|
||||
perror_with_name (_("Unable to fetch AltiVec register"));
|
||||
perror_with_name (_("Unable to fetch AltiVec registers"));
|
||||
}
|
||||
|
||||
/* VSCR is fetched as a 16 bytes quantity, but it is really 4 bytes
|
||||
long on the hardware. */
|
||||
if (regno == (tdep->ppc_vrsave_regnum - 1))
|
||||
offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
|
||||
|
||||
regcache_raw_collect (regcache, regno,
|
||||
regs + (regno
|
||||
- tdep->ppc_vr0_regnum) * vrregsize + offset);
|
||||
vrregset->collect_regset (vrregset, regcache, regno, ®s,
|
||||
PPC_LINUX_SIZEOF_VRREGSET);
|
||||
|
||||
ret = ptrace (PTRACE_SETVRREGS, tid, 0, ®s);
|
||||
if (ret < 0)
|
||||
perror_with_name (_("Unable to store AltiVec register"));
|
||||
perror_with_name (_("Unable to store AltiVec registers"));
|
||||
}
|
||||
|
||||
/* Assuming TID referrs to an SPE process, set the top halves of TID's
|
||||
@ -1034,7 +975,7 @@ store_register (const struct regcache *regcache, int tid, int regno)
|
||||
|
||||
if (altivec_register_p (gdbarch, regno))
|
||||
{
|
||||
store_altivec_register (regcache, tid, regno);
|
||||
store_altivec_registers (regcache, tid, regno);
|
||||
return;
|
||||
}
|
||||
if (vsx_register_p (gdbarch, regno))
|
||||
@ -1110,29 +1051,6 @@ fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
|
||||
*vsxregsetp + i * vsxregsize);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_vrregset (const struct regcache *regcache, gdb_vrregset_t *vrregsetp)
|
||||
{
|
||||
int i;
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
|
||||
int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
|
||||
int offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
|
||||
|
||||
for (i = 0; i < num_of_vrregs; i++)
|
||||
{
|
||||
/* The last 2 registers of this set are only 32 bit long, not
|
||||
128, but only VSCR is fetched as a 16 bytes quantity. */
|
||||
if (i == (num_of_vrregs - 2))
|
||||
regcache_raw_collect (regcache, tdep->ppc_vr0_regnum + i,
|
||||
*vrregsetp + i * vrregsize + offset);
|
||||
else
|
||||
regcache_raw_collect (regcache, tdep->ppc_vr0_regnum + i,
|
||||
*vrregsetp + i * vrregsize);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
store_vsx_registers (const struct regcache *regcache, int tid)
|
||||
{
|
||||
@ -1156,29 +1074,6 @@ store_vsx_registers (const struct regcache *regcache, int tid)
|
||||
perror_with_name (_("Couldn't write VSX registers"));
|
||||
}
|
||||
|
||||
static void
|
||||
store_altivec_registers (const struct regcache *regcache, int tid)
|
||||
{
|
||||
int ret;
|
||||
gdb_vrregset_t regs;
|
||||
|
||||
ret = ptrace (PTRACE_GETVRREGS, tid, 0, ®s);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (errno == EIO)
|
||||
{
|
||||
have_ptrace_getvrregs = 0;
|
||||
return;
|
||||
}
|
||||
perror_with_name (_("Couldn't get AltiVec registers"));
|
||||
}
|
||||
|
||||
fill_vrregset (regcache, ®s);
|
||||
|
||||
if (ptrace (PTRACE_SETVRREGS, tid, 0, ®s) < 0)
|
||||
perror_with_name (_("Couldn't write AltiVec registers"));
|
||||
}
|
||||
|
||||
/* This function actually issues the request to ptrace, telling
|
||||
it to store all general-purpose registers present in the specified
|
||||
regset.
|
||||
@ -1337,7 +1232,7 @@ store_ppc_registers (const struct regcache *regcache, int tid)
|
||||
}
|
||||
if (have_ptrace_getvrregs)
|
||||
if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
|
||||
store_altivec_registers (regcache, tid);
|
||||
store_altivec_registers (regcache, tid, -1);
|
||||
if (have_ptrace_getsetvsxregs)
|
||||
if (tdep->ppc_vsr0_upper_regnum != -1)
|
||||
store_vsx_registers (regcache, tid);
|
||||
|
@ -444,6 +444,24 @@ ppc_linux_collect_gregset (const struct regset *regset,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ppc_linux_collect_vrregset (const struct regset *regset,
|
||||
const struct regcache *regcache,
|
||||
int regnum, void *buf, size_t len)
|
||||
{
|
||||
gdb_byte *vrregs = (gdb_byte *) buf;
|
||||
|
||||
/* Zero-pad the unused bytes in the fields for vscr and vrsave
|
||||
in case they get displayed somewhere (e.g. in core files). */
|
||||
if (regnum == PPC_VSCR_REGNUM || regnum == -1)
|
||||
memset (&vrregs[32 * 16], 0, 16);
|
||||
|
||||
if (regnum == PPC_VRSAVE_REGNUM || regnum == -1)
|
||||
memset (&vrregs[33 * 16], 0, 16);
|
||||
|
||||
regcache_collect_regset (regset, regcache, regnum, buf, len);
|
||||
}
|
||||
|
||||
/* Regset descriptions. */
|
||||
static const struct ppc_reg_offsets ppc32_linux_reg_offsets =
|
||||
{
|
||||
@ -462,12 +480,7 @@ static const struct ppc_reg_offsets ppc32_linux_reg_offsets =
|
||||
/* Floating-point registers. */
|
||||
/* .f0_offset = */ 0,
|
||||
/* .fpscr_offset = */ 256,
|
||||
/* .fpscr_size = */ 8,
|
||||
|
||||
/* AltiVec registers. */
|
||||
/* .vr0_offset = */ 0,
|
||||
/* .vscr_offset = */ 512 + 12,
|
||||
/* .vrsave_offset = */ 528
|
||||
/* .fpscr_size = */ 8
|
||||
};
|
||||
|
||||
static const struct ppc_reg_offsets ppc64_linux_reg_offsets =
|
||||
@ -487,12 +500,7 @@ static const struct ppc_reg_offsets ppc64_linux_reg_offsets =
|
||||
/* Floating-point registers. */
|
||||
/* .f0_offset = */ 0,
|
||||
/* .fpscr_offset = */ 256,
|
||||
/* .fpscr_size = */ 8,
|
||||
|
||||
/* AltiVec registers. */
|
||||
/* .vr0_offset = */ 0,
|
||||
/* .vscr_offset = */ 512 + 12,
|
||||
/* .vrsave_offset = */ 528
|
||||
/* .fpscr_size = */ 8
|
||||
};
|
||||
|
||||
static const struct regset ppc32_linux_gregset = {
|
||||
@ -513,10 +521,36 @@ static const struct regset ppc32_linux_fpregset = {
|
||||
ppc_collect_fpregset
|
||||
};
|
||||
|
||||
static const struct regset ppc32_linux_vrregset = {
|
||||
&ppc32_linux_reg_offsets,
|
||||
ppc_supply_vrregset,
|
||||
ppc_collect_vrregset
|
||||
static const struct regcache_map_entry ppc32_le_linux_vrregmap[] =
|
||||
{
|
||||
{ 32, PPC_VR0_REGNUM, 16 },
|
||||
{ 1, PPC_VSCR_REGNUM, 4 },
|
||||
{ 1, REGCACHE_MAP_SKIP, 12 },
|
||||
{ 1, PPC_VRSAVE_REGNUM, 4 },
|
||||
{ 1, REGCACHE_MAP_SKIP, 12 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct regcache_map_entry ppc32_be_linux_vrregmap[] =
|
||||
{
|
||||
{ 32, PPC_VR0_REGNUM, 16 },
|
||||
{ 1, REGCACHE_MAP_SKIP, 12},
|
||||
{ 1, PPC_VSCR_REGNUM, 4 },
|
||||
{ 1, PPC_VRSAVE_REGNUM, 4 },
|
||||
{ 1, REGCACHE_MAP_SKIP, 12 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct regset ppc32_le_linux_vrregset = {
|
||||
ppc32_le_linux_vrregmap,
|
||||
regcache_supply_regset,
|
||||
ppc_linux_collect_vrregset
|
||||
};
|
||||
|
||||
static const struct regset ppc32_be_linux_vrregset = {
|
||||
ppc32_be_linux_vrregmap,
|
||||
regcache_supply_regset,
|
||||
ppc_linux_collect_vrregset
|
||||
};
|
||||
|
||||
static const struct regset ppc32_linux_vsxregset = {
|
||||
@ -537,6 +571,15 @@ ppc_linux_fpregset (void)
|
||||
return &ppc32_linux_fpregset;
|
||||
}
|
||||
|
||||
const struct regset *
|
||||
ppc_linux_vrregset (struct gdbarch *gdbarch)
|
||||
{
|
||||
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
|
||||
return &ppc32_be_linux_vrregset;
|
||||
else
|
||||
return &ppc32_le_linux_vrregset;
|
||||
}
|
||||
|
||||
/* Iterate over supported core file register note sections. */
|
||||
|
||||
static void
|
||||
@ -557,8 +600,11 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
|
||||
cb (".reg2", 264, &ppc32_linux_fpregset, NULL, cb_data);
|
||||
|
||||
if (have_altivec)
|
||||
cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, &ppc32_linux_vrregset,
|
||||
"ppc Altivec", cb_data);
|
||||
{
|
||||
const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
|
||||
cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, vrregset,
|
||||
"ppc Altivec", cb_data);
|
||||
}
|
||||
|
||||
if (have_vsx)
|
||||
cb (".reg-ppc-vsx", PPC_LINUX_SIZEOF_VSXREGSET,
|
||||
|
@ -28,6 +28,9 @@ struct regset;
|
||||
const struct regset *ppc_linux_gregset (int);
|
||||
const struct regset *ppc_linux_fpregset (void);
|
||||
|
||||
/* Get the vector regset that matches the target byte order. */
|
||||
const struct regset *ppc_linux_vrregset (struct gdbarch *gdbarch);
|
||||
|
||||
/* Extra register number constants. The Linux kernel stores a
|
||||
"trap" code and the original value of r3 into special "registers";
|
||||
these need to be saved and restored when performing an inferior
|
||||
|
@ -215,9 +215,5 @@ _initialize_ppcnbsd_tdep (void)
|
||||
ppcnbsd_reg_offsets.fpscr_offset = 256;
|
||||
ppcnbsd_reg_offsets.fpscr_size = 4;
|
||||
|
||||
/* AltiVec registers. */
|
||||
ppcnbsd_reg_offsets.vr0_offset = 0;
|
||||
ppcnbsd_reg_offsets.vrsave_offset = 512;
|
||||
ppcnbsd_reg_offsets.vscr_offset = 524;
|
||||
}
|
||||
}
|
||||
|
@ -213,11 +213,6 @@ _initialize_ppcobsd_nat (void)
|
||||
ppcobsd_fpreg_offsets.fpscr_size = 4;
|
||||
#endif
|
||||
|
||||
/* AltiVec registers. */
|
||||
ppcobsd_reg_offsets.vr0_offset = offsetof (struct vreg, vreg);
|
||||
ppcobsd_reg_offsets.vscr_offset = offsetof (struct vreg, vscr);
|
||||
ppcobsd_reg_offsets.vrsave_offset = offsetof (struct vreg, vrsave);
|
||||
|
||||
/* Support debugging kernel virtual memory images. */
|
||||
bsd_kvm_add_target (ppcobsd_supply_pcb);
|
||||
}
|
||||
|
@ -289,10 +289,6 @@ _initialize_ppcobsd_tdep (void)
|
||||
ppcobsd_reg_offsets.f0_offset = 128;
|
||||
ppcobsd_reg_offsets.fpscr_offset = -1;
|
||||
|
||||
/* AltiVec registers. */
|
||||
ppcobsd_reg_offsets.vr0_offset = 0;
|
||||
ppcobsd_reg_offsets.vscr_offset = 512;
|
||||
ppcobsd_reg_offsets.vrsave_offset = 520;
|
||||
}
|
||||
|
||||
if (ppcobsd_fpreg_offsets.fpscr_offset == 0)
|
||||
|
@ -100,11 +100,6 @@ struct ppc_reg_offsets
|
||||
int f0_offset;
|
||||
int fpscr_offset;
|
||||
int fpscr_size;
|
||||
|
||||
/* AltiVec registers. */
|
||||
int vr0_offset;
|
||||
int vscr_offset;
|
||||
int vrsave_offset;
|
||||
};
|
||||
|
||||
extern void ppc_supply_reg (struct regcache *regcache, int regnum,
|
||||
|
@ -70,12 +70,7 @@ static struct ppc_reg_offsets rs6000_aix32_reg_offsets =
|
||||
/* Floating-point registers. */
|
||||
336, /* f0_offset */
|
||||
56, /* fpscr_offset */
|
||||
4, /* fpscr_size */
|
||||
|
||||
/* AltiVec registers. */
|
||||
-1, /* vr0_offset */
|
||||
-1, /* vscr_offset */
|
||||
-1 /* vrsave_offset */
|
||||
4 /* fpscr_size */
|
||||
};
|
||||
|
||||
static struct ppc_reg_offsets rs6000_aix64_reg_offsets =
|
||||
@ -95,12 +90,7 @@ static struct ppc_reg_offsets rs6000_aix64_reg_offsets =
|
||||
/* Floating-point registers. */
|
||||
312, /* f0_offset */
|
||||
296, /* fpscr_offset */
|
||||
4, /* fpscr_size */
|
||||
|
||||
/* AltiVec registers. */
|
||||
-1, /* vr0_offset */
|
||||
-1, /* vscr_offset */
|
||||
-1 /* vrsave_offset */
|
||||
4 /* fpscr_size */
|
||||
};
|
||||
|
||||
|
||||
|
@ -485,24 +485,6 @@ ppc_fpreg_offset (struct gdbarch_tdep *tdep,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
ppc_vrreg_offset (struct gdbarch_tdep *tdep,
|
||||
const struct ppc_reg_offsets *offsets,
|
||||
int regnum)
|
||||
{
|
||||
if (regnum >= tdep->ppc_vr0_regnum
|
||||
&& regnum < tdep->ppc_vr0_regnum + ppc_num_vrs)
|
||||
return offsets->vr0_offset + (regnum - tdep->ppc_vr0_regnum) * 16;
|
||||
|
||||
if (regnum == tdep->ppc_vrsave_regnum - 1)
|
||||
return offsets->vscr_offset;
|
||||
|
||||
if (regnum == tdep->ppc_vrsave_regnum)
|
||||
return offsets->vrsave_offset;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Supply register REGNUM in the general-purpose register set REGSET
|
||||
from the buffer specified by GREGS and LEN to register cache
|
||||
REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
|
||||
@ -622,50 +604,6 @@ ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache,
|
||||
ppc_supply_reg (regcache, regnum, (const gdb_byte *) vsxregs, 0, 8);
|
||||
}
|
||||
|
||||
/* Supply register REGNUM in the Altivec register set REGSET
|
||||
from the buffer specified by VRREGS and LEN to register cache
|
||||
REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
|
||||
|
||||
void
|
||||
ppc_supply_vrregset (const struct regset *regset, struct regcache *regcache,
|
||||
int regnum, const void *vrregs, size_t len)
|
||||
{
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
struct gdbarch_tdep *tdep;
|
||||
const struct ppc_reg_offsets *offsets;
|
||||
size_t offset;
|
||||
|
||||
if (!ppc_altivec_support_p (gdbarch))
|
||||
return;
|
||||
|
||||
tdep = gdbarch_tdep (gdbarch);
|
||||
offsets = (const struct ppc_reg_offsets *) regset->regmap;
|
||||
if (regnum == -1)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
|
||||
i < tdep->ppc_vr0_regnum + ppc_num_vrs;
|
||||
i++, offset += 16)
|
||||
ppc_supply_reg (regcache, i, (const gdb_byte *) vrregs, offset, 16);
|
||||
|
||||
ppc_supply_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
|
||||
(const gdb_byte *) vrregs, offsets->vscr_offset, 4);
|
||||
|
||||
ppc_supply_reg (regcache, tdep->ppc_vrsave_regnum,
|
||||
(const gdb_byte *) vrregs, offsets->vrsave_offset, 4);
|
||||
return;
|
||||
}
|
||||
|
||||
offset = ppc_vrreg_offset (tdep, offsets, regnum);
|
||||
if (regnum != tdep->ppc_vrsave_regnum
|
||||
&& regnum != tdep->ppc_vrsave_regnum - 1)
|
||||
ppc_supply_reg (regcache, regnum, (const gdb_byte *) vrregs, offset, 16);
|
||||
else
|
||||
ppc_supply_reg (regcache, regnum,
|
||||
(const gdb_byte *) vrregs, offset, 4);
|
||||
}
|
||||
|
||||
/* Collect register REGNUM in the general-purpose register set
|
||||
REGSET from register cache REGCACHE into the buffer specified by
|
||||
GREGS and LEN. If REGNUM is -1, do this for all registers in
|
||||
@ -790,54 +728,6 @@ ppc_collect_vsxregset (const struct regset *regset,
|
||||
ppc_collect_reg (regcache, regnum, (gdb_byte *) vsxregs, 0, 8);
|
||||
}
|
||||
|
||||
|
||||
/* Collect register REGNUM in the Altivec register set
|
||||
REGSET from register cache REGCACHE into the buffer specified by
|
||||
VRREGS and LEN. If REGNUM is -1, do this for all registers in
|
||||
REGSET. */
|
||||
|
||||
void
|
||||
ppc_collect_vrregset (const struct regset *regset,
|
||||
const struct regcache *regcache,
|
||||
int regnum, void *vrregs, size_t len)
|
||||
{
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
struct gdbarch_tdep *tdep;
|
||||
const struct ppc_reg_offsets *offsets;
|
||||
size_t offset;
|
||||
|
||||
if (!ppc_altivec_support_p (gdbarch))
|
||||
return;
|
||||
|
||||
tdep = gdbarch_tdep (gdbarch);
|
||||
offsets = (const struct ppc_reg_offsets *) regset->regmap;
|
||||
if (regnum == -1)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
|
||||
i < tdep->ppc_vr0_regnum + ppc_num_vrs;
|
||||
i++, offset += 16)
|
||||
ppc_collect_reg (regcache, i, (gdb_byte *) vrregs, offset, 16);
|
||||
|
||||
ppc_collect_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
|
||||
(gdb_byte *) vrregs, offsets->vscr_offset, 4);
|
||||
|
||||
ppc_collect_reg (regcache, tdep->ppc_vrsave_regnum,
|
||||
(gdb_byte *) vrregs, offsets->vrsave_offset, 4);
|
||||
return;
|
||||
}
|
||||
|
||||
offset = ppc_vrreg_offset (tdep, offsets, regnum);
|
||||
if (regnum != tdep->ppc_vrsave_regnum
|
||||
&& regnum != tdep->ppc_vrsave_regnum - 1)
|
||||
ppc_collect_reg (regcache, regnum, (gdb_byte *) vrregs, offset, 16);
|
||||
else
|
||||
ppc_collect_reg (regcache, regnum,
|
||||
(gdb_byte *) vrregs, offset, 4);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
insn_changes_sp_or_jumps (unsigned long insn)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user