From patchwork Mon Jun 27 14:49:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhushan Attarde X-Patchwork-Id: 13396 Received: (qmail 13955 invoked by alias); 27 Jun 2016 14:51:08 -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 13882 invoked by uid 89); 27 Jun 2016 14:51:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=3.9 required=5.0 tests=AWL, BAYES_00, GARBLED_SUBJECT, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, SPF_PASS autolearn=no version=3.3.2 spammy=2317, 5127, msa, memcpy X-HELO: mailapp01.imgtec.com Received: from mailapp01.imgtec.com (HELO mailapp01.imgtec.com) (195.59.15.196) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 27 Jun 2016 14:51:04 +0000 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id 6112C36A84468 for ; Mon, 27 Jun 2016 15:50:57 +0100 (IST) Received: from pudesk170.pu.imgtec.org (192.168.93.65) by hhmail02.hh.imgtec.org (10.100.10.20) with Microsoft SMTP Server (TLS) id 14.3.294.0; Mon, 27 Jun 2016 15:51:00 +0100 From: Bhushan Attarde To: CC: , , , , , Bhushan Attarde Subject: [PATCH 18/24] mips-linux-nat: get msa registers Date: Mon, 27 Jun 2016 20:19:45 +0530 Message-ID: <1467038991-6600-18-git-send-email-bhushan.attarde@imgtec.com> In-Reply-To: <1467038991-6600-1-git-send-email-bhushan.attarde@imgtec.com> References: <1467038991-6600-1-git-send-email-bhushan.attarde@imgtec.com> MIME-Version: 1.0 This patch gets MSA registers using ptrace and sets up internal register state. gdb/gdbserver/ChangeLog: * mips-linux-nat.c (have_ptrace_getregset_msa): New variable. (mips64_linux_regsets_store_registers): Likewaise. (mips64_linux_regsets_fetch_registers): New is_vec variable. Get MSA regset first and then fp regset. (mips64_linux_regsets_store_registers): Likewaise. include/ChangeLog: * elf/common.h (NT_MIPS_MSA): New definition. --- gdb/mips-linux-nat.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++--- include/elf/common.h | 1 + 2 files changed, 156 insertions(+), 8 deletions(-) diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c index 20e3d17..a674885 100644 --- a/gdb/mips-linux-nat.c +++ b/gdb/mips-linux-nat.c @@ -68,6 +68,7 @@ static int have_ptrace_regsets = 1; /* Does the current host support PTRACE_GETREGSET? */ static int have_ptrace_getregset_gp = 1; static int have_ptrace_getregset_fp = 1; +static int have_ptrace_getregset_msa = 1; /* Saved function pointers to fetch and store a single register using PTRACE_PEEKUSER and PTRACE_POKEUSER. */ @@ -231,7 +232,7 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops, { struct gdbarch *gdbarch = get_regcache_arch (regcache); int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG); - int is_fp, is_dsp; + int is_fp, is_dsp, is_vec; int have_dsp; int regi; int tid; @@ -252,6 +253,14 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops, else is_fp = 0; + /* Vector registers are optional but overlap fp registers */ + if (regno == mips_regnum (gdbarch)->msa_csr) + is_vec = 1; + else if (regno == mips_regnum (gdbarch)->msa_ir) + is_vec = 1; + else + is_vec = 0; + /* DSP registers are optional and not a part of any set. */ have_dsp = mips_regnum (gdbarch)->dspctl != -1; if (!have_dsp) @@ -268,7 +277,7 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops, if (tid == 0) tid = ptid_get_pid (inferior_ptid); - if (regno == -1 || (!is_fp && !is_dsp)) + if (regno == -1 || (!is_fp && !is_dsp && !is_vec)) { mips64_elf_gregset_t regs; @@ -286,13 +295,72 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops, (const mips64_elf_gregset_t *) ®s); } - if (is_fp) + if (is_fp || is_vec) { const struct mips_regnum *rn = mips_regnum (gdbarch); int float_regnum = rn->fp0; + /* Try the MSA regset first if vector registers are desired */ + if (rn->msa_csr != -1 + && have_ptrace_getregset_gp && have_ptrace_getregset_msa) + { + unsigned char w_regs[34][16]; + unsigned char buf[16]; + struct iovec iovec; + int ret; + + iovec.iov_base = &w_regs; + iovec.iov_len = sizeof (w_regs); + + ret = ptrace (PTRACE_GETREGSET, tid, NT_MIPS_MSA, &iovec); + if (ret < 0) + { + if (errno == EIO) + have_ptrace_getregset_gp = 0; + else if (errno == EINVAL) + have_ptrace_getregset_msa = 0; + else + perror_with_name (_("Unable to fetch FP/MSA registers.")); + } + else + { + /* full vector including float */ + if (big_endian) + for (regi = 0; regi < 32; regi++) + { + /* swap 64-bit halves, so it's a single word */ + memcpy(buf, w_regs[regi] + 8, 8); + memcpy(buf + 8, w_regs[regi], 8); + regcache_raw_supply (regcache, float_regnum + regi, buf); + } + else + for (regi = 0; regi < 32; regi++) + regcache_raw_supply (regcache, float_regnum + regi, + (char *) w_regs[regi]); + + if (iovec.iov_len >= 32*16 + 4) + regcache_raw_supply (regcache, rn->fp_implementation_revision, + (char *) (w_regs + 32) + 0); + if (iovec.iov_len >= 32*16 + 8) + regcache_raw_supply (regcache, rn->fp_control_status, + (char *) (w_regs + 32) + 4); + if (iovec.iov_len >= 32*16 + 12) + regcache_raw_supply (regcache, rn->msa_ir, + (char *) (w_regs + 32) + 8); + if (iovec.iov_len >= 32*16 + 16) + regcache_raw_supply (regcache, rn->msa_csr, + (char *) (w_regs + 32) + 12); + if (iovec.iov_len >= 33*16 + 4) + regcache_raw_supply (regcache, rn->config5, + (char *) (w_regs + 33) + 0); + + /* we've got fp registers now */ + is_fp = 0; + } + } + /* Try the FP regset next as it may contain Config5 */ - if (have_ptrace_getregset_gp && have_ptrace_getregset_fp) + if (is_fp && have_ptrace_getregset_gp && have_ptrace_getregset_fp) { unsigned char fp_regs[34][8]; struct iovec iovec; @@ -396,7 +464,7 @@ mips64_linux_regsets_store_registers (struct target_ops *ops, { struct gdbarch *gdbarch = get_regcache_arch (regcache); int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG); - int is_fp, is_dsp; + int is_fp, is_dsp, is_vec; int have_dsp; int regi; int tid; @@ -417,6 +485,17 @@ mips64_linux_regsets_store_registers (struct target_ops *ops, else is_fp = 0; + /* Vector registers are optional but overlap fp registers */ + if (regno >= mips_regnum (gdbarch)->w0 + && regno <= mips_regnum (gdbarch)->w0 + 32) + is_vec = 1; + else if (regno == mips_regnum (gdbarch)->msa_csr) + is_vec = 1; + else if (regno == mips_regnum (gdbarch)->msa_ir) + is_vec = 1; + else + is_vec = 0; + /* DSP registers are optional and not a part of any set. */ have_dsp = mips_regnum (gdbarch)->dspctl != -1; if (!have_dsp) @@ -433,7 +512,7 @@ mips64_linux_regsets_store_registers (struct target_ops *ops, if (tid == 0) tid = ptid_get_pid (inferior_ptid); - if (regno == -1 || (!is_fp && !is_dsp)) + if (regno == -1 || (!is_fp && !is_dsp && !is_vec)) { mips64_elf_gregset_t regs; @@ -446,13 +525,81 @@ mips64_linux_regsets_store_registers (struct target_ops *ops, perror_with_name (_("Couldn't set registers")); } - if (is_fp) + if (is_fp || is_vec) { const struct mips_regnum *rn = mips_regnum (gdbarch); int float_regnum = rn->fp0; + /* Try the MSA regset first if vector registers are desired */ + if (rn->msa_csr != -1 + && have_ptrace_getregset_gp && have_ptrace_getregset_msa) + { + unsigned char w_regs[34][16]; + unsigned char buf[16]; + struct iovec iovec; + int ret; + + iovec.iov_base = &w_regs; + iovec.iov_len = sizeof (w_regs); + + ret = ptrace (PTRACE_GETREGSET, tid, NT_MIPS_MSA, &iovec); + if (ret < 0) + { + if (errno == EIO) + have_ptrace_getregset_gp = 0; + else if (errno == EINVAL) + have_ptrace_getregset_msa = 0; + else + perror_with_name (_("Unable to fetch FP/MSA registers.")); + } + else + { + /* full vector including float */ + if (big_endian) + for (regi = 0; regi < 32; regi++) + { + regcache_raw_collect (regcache, float_regnum + regi, buf); + /* swap 64-bit halves, as it's a single word */ + memcpy(w_regs[regi], buf + 8, 8); + memcpy(w_regs[regi] + 8, buf, 8); + } + else + for (regi = 0; regi < 32; regi++) + regcache_raw_collect (regcache, float_regnum + regi, + (char *) w_regs[regi]); + + regcache_raw_collect (regcache, rn->fp_implementation_revision, + (char *) (w_regs + 32) + 0); + regcache_raw_collect (regcache, rn->fp_control_status, + (char *) (w_regs + 32) + 4); + regcache_raw_collect (regcache, rn->msa_ir, + (char *) (w_regs + 32) + 8); + regcache_raw_collect (regcache, rn->msa_csr, + (char *) (w_regs + 32) + 12); + regcache_raw_collect (regcache, rn->config5, + (char *) (w_regs + 33) + 0); + + /* don't modify iovec length from amount of data returned */ + ret = ptrace (PTRACE_SETREGSET, tid, NT_MIPS_MSA, &iovec); + if (ret < 0) + { + if (errno == EIO) + have_ptrace_getregset_gp = 0; + if (errno == EINVAL) + have_ptrace_getregset_msa = 0; + else + perror_with_name (_("Unable to store FP/MSA registers.")); + } + else + { + /* we've written fp registers now */ + is_fp = 0; + } + } + } + /* Try the FP regset next as it may contain Config5 */ - if (have_ptrace_getregset_gp && have_ptrace_getregset_fp) + if (is_fp && have_ptrace_getregset_gp && have_ptrace_getregset_fp) { unsigned char fp_regs[34][8]; struct iovec iovec; diff --git a/include/elf/common.h b/include/elf/common.h index 087d876..5955874 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -580,6 +580,7 @@ /* note name must be "LINUX". */ #define NT_ARM_HW_WATCH 0x403 /* AArch hardware watchpoint registers */ /* note name must be "LINUX". */ +#define NT_MIPS_MSA 0x600 /* MIPS MSA vector registers. */ #define NT_SIGINFO 0x53494749 /* Fields of siginfo_t. */ #define NT_FILE 0x46494c45 /* Description of mapped files. */