From patchwork Wed Jun 29 12:45:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhushan Attarde X-Patchwork-Id: 13473 Received: (qmail 56796 invoked by alias); 29 Jun 2016 12:46:30 -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 56752 invoked by uid 89); 29 Jun 2016 12:46:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00, GARBLED_SUBJECT, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, SPF_PASS, UNWANTED_LANGUAGE_BODY autolearn=no version=3.3.2 spammy=1810 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; Wed, 29 Jun 2016 12:46:26 +0000 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id 80CEC546799D5 for ; Wed, 29 Jun 2016 13:46:20 +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; Wed, 29 Jun 2016 13:46:22 +0100 From: Bhushan Attarde To: CC: , , , , , Bhushan Attarde Subject: [PATCH 17/24] Add msa support etc to gdbserver Date: Wed, 29 Jun 2016 18:15:55 +0530 Message-ID: <1467204355-4904-4-git-send-email-bhushan.attarde@imgtec.com> In-Reply-To: <1467204355-4904-1-git-send-email-bhushan.attarde@imgtec.com> References: <1467204355-4904-1-git-send-email-bhushan.attarde@imgtec.com> MIME-Version: 1.0 gdb/gdbserver/ChangeLog: * linux-mips-low.c: Include "elf/common.h" and "sys/uio.h". (init_registers_mips_fpu64_linux): New declaration. (init_registers_mips_fpu64_dsp_linux, init_registers_mips_msa_linux, init_registers_mips64_msa_linux): Likewise. (tdesc_mips_fpu64_linux): New variable. (tdesc_mips_fpu64_dsp_linux, tdesc_mips_msa_linux, tdesc_mips64_msa_linux): Likewise. (PTRACE_GETREGSET, PTRACE_SETREGSET): New fallback definitions. (have_fpu64, have_msa): New variables. (mips_read_description): Set have_fpu64, have_msa appropriately and return target decription based on that. (mips_fill_fpregset, mips_store_fpregset): New fp_use_64bit variable. (mips_fill_msa_regset): New function. (mips_store_msa_regset): Likewise. (mips_regsets): Add MSA registers. (initialize_low_arch): Add initilizer functions for fpu64 and MSA. --- gdb/gdbserver/linux-mips-low.c | 199 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 191 insertions(+), 8 deletions(-) diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c index e9f0b06..f170144 100644 --- a/gdb/gdbserver/linux-mips-low.c +++ b/gdb/gdbserver/linux-mips-low.c @@ -18,8 +18,10 @@ #include "server.h" #include "linux-low.h" +#include "elf/common.h" #include "nat/gdb_ptrace.h" +#include #include #include "nat/mips-linux-watch.h" @@ -33,6 +35,18 @@ extern const struct target_desc *tdesc_mips_linux; void init_registers_mips_dsp_linux (void); extern const struct target_desc *tdesc_mips_dsp_linux; +/* Defined in auto-generated file mips-fpu64-linux.c. */ +void init_registers_mips_fpu64_linux (void); +extern const struct target_desc *tdesc_mips_fpu64_linux; + +/* Defined in auto-generated file mips-fpu64-dsp-linux.c. */ +void init_registers_mips_fpu64_dsp_linux (void); +extern const struct target_desc *tdesc_mips_fpu64_dsp_linux; + +/* Defined in auto-generated file mips-msa-linux.c. */ +void init_registers_mips_msa_linux (void); +extern const struct target_desc *tdesc_mips_msa_linux; + /* Defined in auto-generated file mips64-linux.c. */ void init_registers_mips64_linux (void); extern const struct target_desc *tdesc_mips64_linux; @@ -41,15 +55,30 @@ extern const struct target_desc *tdesc_mips64_linux; void init_registers_mips64_dsp_linux (void); extern const struct target_desc *tdesc_mips64_dsp_linux; +/* Defined in auto-generated file mips64-msa-linux.c. */ +void init_registers_mips64_msa_linux (void); +extern const struct target_desc *tdesc_mips64_msa_linux; + #ifdef __mips64 #define tdesc_mips_linux tdesc_mips64_linux #define tdesc_mips_dsp_linux tdesc_mips64_dsp_linux +#define tdesc_mips_fpu64_linux tdesc_mips64_linux +#define tdesc_mips_fpu64_dsp_linux tdesc_mips64_dsp_linux +#define tdesc_mips_msa_linux tdesc_mips64_msa_linux #endif #ifndef PTRACE_GET_THREAD_AREA #define PTRACE_GET_THREAD_AREA 25 #endif +#ifndef PTRACE_GETREGSET +#define PTRACE_GETREGSET 0x4204 +#endif + +#ifndef PTRACE_SETREGSET +#define PTRACE_SETREGSET 0x4205 +#endif + #ifdef HAVE_SYS_REG_H #include #endif @@ -64,6 +93,9 @@ extern const struct target_desc *tdesc_mips64_dsp_linux; #define DSP_CONTROL 77 #endif +#define ST0_FR (1 << 26) +#define FIR_F64 (1 << 22) + union mips_register { unsigned char buf[8]; @@ -117,17 +149,68 @@ static unsigned char mips_dsp_regset_bitmap[(mips_dsp_num_regs + 7) / 8] = { }; static int have_dsp = -1; +static int have_fpu64 = -1; +static int have_msa = -1; -/* Try peeking at an arbitrarily chosen DSP register and pick the available - user register set accordingly. */ +/* Try peeking at registers and pick the available user register set + accordingly. */ static const struct target_desc * mips_read_description (void) { + const struct target_desc *tdescs[2][2] = + { + /* have_fpu64 = 0 have_fpu64 = 1 */ + { tdesc_mips_linux, tdesc_mips_fpu64_linux }, /* have_dsp = 0 */ + { tdesc_mips_dsp_linux, tdesc_mips_fpu64_dsp_linux }, /* have_dsp = 1 */ + }; + + if (have_fpu64 < 0) + { + int pid = lwpid_of (current_thread); + long fir; + + /* Try peeking at FIR.F64 bit */ + errno = 0; + fir = ptrace (PTRACE_PEEKUSER, pid, FPC_EIR, 0); + switch (errno) + { + case 0: + have_fpu64 = !!(fir & FIR_F64); + break; + case EIO: + have_fpu64 = 0; + have_msa = 0; + break; + default: + perror_with_name ("ptrace"); + break; + } + } + + /* Check for MSA, which requires FR=1 */ + if (have_msa < 0) + { + int pid = lwpid_of (current_thread); + int res; + uint32_t regs[32*4 + 8]; + struct iovec iov; + + /* this'd probably be better */ + //have_msa = (getauxval(AT_HWCAP) & 0x2) != 0; + + /* Test MSAIR */ + iov.iov_base = regs; + iov.iov_len = sizeof(regs); + res = ptrace (PTRACE_GETREGSET, pid, NT_MIPS_MSA, &iov); + have_msa = (res >= 0) && regs[32*4 + 0]; + } + if (have_dsp < 0) { int pid = lwpid_of (current_thread); + /* Try peeking at an arbitrarily chosen DSP register */ errno = 0; ptrace (PTRACE_PEEKUSER, pid, DSP_CONTROL, 0); switch (errno) @@ -144,7 +227,8 @@ mips_read_description (void) } } - return have_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux; + return have_msa ? tdesc_mips_msa_linux + : tdescs[have_dsp][have_fpu64]; } static void @@ -770,22 +854,24 @@ static void mips_fill_fpregset (struct regcache *regcache, void *buf) { union mips_register *regset = (union mips_register *) buf; - int i, use_64bit, first_fp, big_endian; + int i, use_64bit, fp_use_64bit, first_fp, big_endian; use_64bit = (register_size (regcache->tdesc, 0) == 8); first_fp = find_regno (regcache->tdesc, "f0"); + fp_use_64bit = (register_size (regcache->tdesc, first_fp) >= 8); big_endian = (__BYTE_ORDER == __BIG_ENDIAN); /* See GDB for a discussion of this peculiar layout. */ for (i = 0; i < 32; i++) - if (use_64bit) + if (fp_use_64bit) collect_register (regcache, first_fp + i, regset[i].buf); else collect_register (regcache, first_fp + i, regset[i & ~1].buf + 4 * (big_endian != (i & 1))); mips_collect_register_32bit (regcache, use_64bit, - find_regno (regcache->tdesc, "fcsr"), regset[32].buf); + find_regno (regcache->tdesc, "fcsr"), + regset[32].buf); mips_collect_register_32bit (regcache, use_64bit, find_regno (regcache->tdesc, "fir"), regset[32].buf + 4); @@ -795,15 +881,16 @@ static void mips_store_fpregset (struct regcache *regcache, const void *buf) { const union mips_register *regset = (const union mips_register *) buf; - int i, use_64bit, first_fp, big_endian; + int i, use_64bit, fp_use_64bit, first_fp, big_endian; use_64bit = (register_size (regcache->tdesc, 0) == 8); first_fp = find_regno (regcache->tdesc, "f0"); + fp_use_64bit = (register_size (regcache->tdesc, first_fp) >= 8); big_endian = (__BYTE_ORDER == __BIG_ENDIAN); /* See GDB for a discussion of this peculiar layout. */ for (i = 0; i < 32; i++) - if (use_64bit) + if (fp_use_64bit) supply_register (regcache, first_fp + i, regset[i].buf); else supply_register (regcache, first_fp + i, @@ -818,12 +905,104 @@ mips_store_fpregset (struct regcache *regcache, const void *buf) } #endif /* HAVE_PTRACE_GETREGS */ +static void +mips_fill_msa_regset (struct regcache *regcache, void *buf) +{ + unsigned char *bufp = buf; + int i, first_fp, fir, fcsr, msair, msacsr, config5; + unsigned char tmp[16]; + + if (!have_msa) + return; + + first_fp = find_regno (regcache->tdesc, "f0"); + fir = find_regno (regcache->tdesc, "fir"); + fcsr = find_regno (regcache->tdesc, "fcsr"); + msair = find_regno (regcache->tdesc, "msair"); + msacsr = find_regno (regcache->tdesc, "msacsr"); + config5 = find_regno (regcache->tdesc, "config5"); + + /* full vector including float */ + if (__BYTE_ORDER == __BIG_ENDIAN) + for (i = 0; i < 32; i++) + { + collect_register (regcache, first_fp + i, tmp); + /* swap 64-bit halves, so it's a single word */ + memcpy(bufp, tmp + 8, 8); + memcpy(bufp + 8, tmp, 8); + bufp += 16; + } + else + for (i = 0; i < 32; i++) + { + collect_register (regcache, first_fp + i, bufp); + bufp += 16; + } + + collect_register (regcache, fir, bufp); + bufp += 4; + collect_register (regcache, fcsr, bufp); + bufp += 4; + collect_register (regcache, msair, bufp); + bufp += 4; + collect_register (regcache, msacsr, bufp); + bufp += 4; + collect_register (regcache, config5, bufp); +} + +static void +mips_store_msa_regset (struct regcache *regcache, const void *buf) +{ + const unsigned char *bufp = buf; + int i, first_fp, fir, fcsr, msair, msacsr, config5; + unsigned char tmp[16]; + + if (!have_msa) + return; + + first_fp = find_regno (regcache->tdesc, "f0"); + fir = find_regno (regcache->tdesc, "fir"); + fcsr = find_regno (regcache->tdesc, "fcsr"); + msair = find_regno (regcache->tdesc, "msair"); + msacsr = find_regno (regcache->tdesc, "msacsr"); + config5 = find_regno (regcache->tdesc, "config5"); + + /* full vector including float */ + if (__BYTE_ORDER == __BIG_ENDIAN) + for (i = 0; i < 32; i++) + { + /* swap 64-bit halves, as it's a single word */ + memcpy(tmp, bufp + 8, 8); + memcpy(tmp + 8, bufp, 8); + supply_register (regcache, first_fp + i, tmp); + bufp += 16; + } + else + for (i = 0; i < 32; i++) + { + supply_register (regcache, first_fp + i, bufp); + bufp += 16; + } + + supply_register (regcache, fir, bufp); + bufp += 4; + supply_register (regcache, fcsr, bufp); + bufp += 4; + supply_register (regcache, msair, bufp); + bufp += 4; + supply_register (regcache, msacsr, bufp); + bufp += 4; + supply_register (regcache, config5, bufp); +} + static struct regset_info mips_regsets[] = { #ifdef HAVE_PTRACE_GETREGS { PTRACE_GETREGS, PTRACE_SETREGS, 0, 38 * 8, GENERAL_REGS, mips_fill_gregset, mips_store_gregset }, { PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, 33 * 8, FP_REGS, mips_fill_fpregset, mips_store_fpregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_MIPS_MSA, 34*16, EXTENDED_REGS, + mips_fill_msa_regset, mips_store_msa_regset }, #endif /* HAVE_PTRACE_GETREGS */ NULL_REGSET }; @@ -903,8 +1082,12 @@ initialize_low_arch (void) /* Initialize the Linux target descriptions. */ init_registers_mips_linux (); init_registers_mips_dsp_linux (); + init_registers_mips_fpu64_linux (); + init_registers_mips_fpu64_dsp_linux (); + init_registers_mips_msa_linux (); init_registers_mips64_linux (); init_registers_mips64_dsp_linux (); + init_registers_mips64_msa_linux (); initialize_regsets_info (&mips_regsets_info); }