From 1d75a65809b49d41e97518b99c551a4bb2517500 Mon Sep 17 00:00:00 2001 From: Pedro Franco de Carvalho Date: Tue, 22 May 2018 11:09:05 -0300 Subject: [PATCH] [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 * 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 * 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. --- gdb/ChangeLog | 48 +++++++++++ gdb/gdbserver/ChangeLog | 10 +++ gdb/gdbserver/linux-ppc-low.c | 19 ++++- gdb/ppc-fbsd-tdep.c | 16 +--- gdb/ppc-linux-nat.c | 153 ++++++---------------------------- gdb/ppc-linux-tdep.c | 82 ++++++++++++++---- gdb/ppc-linux-tdep.h | 3 + gdb/ppc-nbsd-tdep.c | 4 - gdb/ppc-obsd-nat.c | 5 -- gdb/ppc-obsd-tdep.c | 4 - gdb/ppc-tdep.h | 5 -- gdb/rs6000-aix-tdep.c | 14 +--- gdb/rs6000-tdep.c | 110 ------------------------ 13 files changed, 170 insertions(+), 303 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d99f5c078a5..b234da8ceb1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,51 @@ +2018-05-22 Pedro Franco de Carvalho + + * 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 * arch/ppc-linux-common.h (PPC_LINUX_SIZEOF_VRREGSET) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 1efddc44a15..13e34262ef5 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,13 @@ +2018-05-22 Pedro Franco de Carvalho + + * 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 * linux-ppc-low.c (SIZEOF_VSXREGS, SIZEOF_VRREGS): Remove. diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c index 367851836e4..c6e00b7eb8b 100644 --- a/gdb/gdbserver/linux-ppc-low.c +++ b/gdb/gdbserver/linux-ppc-low.c @@ -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]); } diff --git a/gdb/ppc-fbsd-tdep.c b/gdb/ppc-fbsd-tdep.c index 3ce4f0657e1..495ccca8f18 100644 --- a/gdb/ppc-fbsd-tdep.c +++ b/gdb/ppc-fbsd-tdep.c @@ -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. */ diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index a8f202dd335..e00831a2483 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -24,6 +24,7 @@ #include "gdbthread.h" #include "gdbcore.h" #include "regcache.h" +#include "regset.h" #include "target.h" #include "linux-nat.h" #include @@ -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); diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 344069d752e..7362c4bbe19 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -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, diff --git a/gdb/ppc-linux-tdep.h b/gdb/ppc-linux-tdep.h index 5e7c4be16ba..a8715bd4184 100644 --- a/gdb/ppc-linux-tdep.h +++ b/gdb/ppc-linux-tdep.h @@ -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 diff --git a/gdb/ppc-nbsd-tdep.c b/gdb/ppc-nbsd-tdep.c index 129ebc03426..c86aeb8a295 100644 --- a/gdb/ppc-nbsd-tdep.c +++ b/gdb/ppc-nbsd-tdep.c @@ -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; } } diff --git a/gdb/ppc-obsd-nat.c b/gdb/ppc-obsd-nat.c index 781b09c7fe4..4428dabd7b9 100644 --- a/gdb/ppc-obsd-nat.c +++ b/gdb/ppc-obsd-nat.c @@ -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); } diff --git a/gdb/ppc-obsd-tdep.c b/gdb/ppc-obsd-tdep.c index 986ab041339..838783111a2 100644 --- a/gdb/ppc-obsd-tdep.c +++ b/gdb/ppc-obsd-tdep.c @@ -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) diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h index 156f82d39b4..c3571cbd51b 100644 --- a/gdb/ppc-tdep.h +++ b/gdb/ppc-tdep.h @@ -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, diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c index e3e086c2102..ecf6191df01 100644 --- a/gdb/rs6000-aix-tdep.c +++ b/gdb/rs6000-aix-tdep.c @@ -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 */ }; diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index c5b49c5f465..4ef6f9e9805 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -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) { -- 2.30.2