From patchwork Mon May 21 20:44:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: pedromfc X-Patchwork-Id: 27377 Received: (qmail 13502 invoked by alias); 21 May 2018 20:46:17 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 13076 invoked by uid 89); 21 May 2018 20:45:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, NO_DNS_FOR_FROM, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=5578 X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0a-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.156.1) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 21 May 2018 20:45:54 +0000 Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w4LKiHKw044284 for ; Mon, 21 May 2018 16:45:53 -0400 Received: from e13.ny.us.ibm.com (e13.ny.us.ibm.com [129.33.205.203]) by mx0a-001b2d01.pphosted.com with ESMTP id 2j41bbsva1-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 21 May 2018 16:45:53 -0400 Received: from localhost by e13.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 21 May 2018 16:45:51 -0400 Received: from b01cxnp23033.gho.pok.ibm.com (9.57.198.28) by e13.ny.us.ibm.com (146.89.104.200) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 21 May 2018 16:45:49 -0400 Received: from b01ledav006.gho.pok.ibm.com (b01ledav006.gho.pok.ibm.com [9.57.199.111]) by b01cxnp23033.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w4LKjmqc2228546; Mon, 21 May 2018 20:45:48 GMT Received: from b01ledav006.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1A2F1AC046; Mon, 21 May 2018 16:47:18 -0400 (EDT) Received: from pedro.localdomain (unknown [9.18.235.153]) by b01ledav006.gho.pok.ibm.com (Postfix) with ESMTP id BAED1AC03A; Mon, 21 May 2018 16:47:17 -0400 (EDT) Received: by pedro.localdomain (Postfix, from userid 1000) id 6F1BA3C03E1; Mon, 21 May 2018 17:45:45 -0300 (-03) From: Pedro Franco de Carvalho To: gdb-patches@sourceware.org Cc: uweigand@de.ibm.com Subject: [PATCH v2 5/8] [PowerPC] Fix access to VSCR in linux targets Date: Mon, 21 May 2018 17:44:55 -0300 In-Reply-To: <20180521204458.19070-1-pedromfc@linux.vnet.ibm.com> References: <20180510195840.17734-1-pedromfc@linux.vnet.ibm.com> <20180521204458.19070-1-pedromfc@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18052120-0008-0000-0000-0000030AE9F7 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00009062; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000261; SDB=6.01035688; UDB=6.00529761; IPR=6.00814816; MB=3.00021228; MTD=3.00000008; XFM=3.00000015; UTC=2018-05-21 20:45:50 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18052120-0009-0000-0000-00003953E836 Message-Id: <20180521204458.19070-5-pedromfc@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-05-21_08:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1805210246 X-IsSubscribed: yes 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: yyyy-mm-dd 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: yyyy-mm-dd 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/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 ------------------------------ 11 files changed, 112 insertions(+), 303 deletions(-) diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c index 367851836e..c6e00b7eb8 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 3ce4f0657e..495ccca8f1 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 a8f202dd33..e00831a248 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 @@ -647,31 +640,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) { int ret; @@ -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)) @@ -1111,29 +1052,6 @@ fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp) } 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) { int ret; @@ -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 344069d752..7362c4bbe1 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 5e7c4be16b..a8715bd418 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 129ebc0342..c86aeb8a29 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 781b09c7fe..4428dabd7b 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 986ab04133..838783111a 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 156f82d39b..c3571cbd51 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 e3e086c210..ecf6191df0 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 c5b49c5f46..4ef6f9e980 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) {