From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10327 invoked by alias); 2 Apr 2010 14:42:03 -0000 Received: (qmail 10218 invoked by uid 22791); 2 Apr 2010 14:41:49 -0000 X-SWARE-Spam-Status: No, hits=-1.4 required=5.0 tests=BAYES_00,TW_AV,TW_CP,TW_EG,TW_GP,TW_MX,TW_XC,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from sibelius.xs4all.nl (HELO glazunov.sibelius.xs4all.nl) (83.163.83.176) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 02 Apr 2010 14:41:37 +0000 Received: from glazunov.sibelius.xs4all.nl (kettenis@localhost [127.0.0.1]) by glazunov.sibelius.xs4all.nl (8.14.3/8.14.3) with ESMTP id o32EfUqb022204; Fri, 2 Apr 2010 16:41:30 +0200 (CEST) Received: (from kettenis@localhost) by glazunov.sibelius.xs4all.nl (8.14.3/8.14.3/Submit) id o32EfT7s024414; Fri, 2 Apr 2010 16:41:29 +0200 (CEST) Date: Fri, 02 Apr 2010 14:42:00 -0000 Message-Id: <201004021441.o32EfT7s024414@glazunov.sibelius.xs4all.nl> From: Mark Kettenis To: hjl.tools@gmail.com CC: gdb-patches@sourceware.org In-reply-to: <20100402143107.GA24450@intel.com> (hongjiu.lu@intel.com) Subject: Re: PATCH: 3/6 [3rd try]: Add AVX support (i386 changes) References: <20100304180219.GA10826@intel.com> <20100304180408.GA10869@intel.com> <20100304180643.GB10869@intel.com> <20100306222037.GD21133@intel.com> <20100312164930.GB6144@intel.com> <20100329011124.GA27275@intel.com> <20100402143107.GA24450@intel.com> Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-04/txt/msg00046.txt.bz2 > Date: Fri, 2 Apr 2010 07:31:07 -0700 > From: "H.J. Lu" > > On Sun, Mar 28, 2010 at 06:11:24PM -0700, H.J. Lu wrote: > > Hi, > > > > Here are i386 changes to support AVX. OK to install? > > > > Here is the updated i386 changes to support AVX. OK to install? Sorry, but I'm still unhappy with the way you modify the i386_linux_regset_sections[] array at run time. I think the best thing to do is to have gcore *always* create a NT_X86_XSTATE note of the maximum size supported by GDB. That way you can remove a lot of code (including the duplication of code in i387_collect_xsave). > H.J. > ---- > 2010-04-02 H.J. Lu > > * i386-linux-nat.c: Include "regset.h", "elf/common.h", > and "i386-xstate.h". > (PTRACE_GETREGSET): New. > (PTRACE_SETREGSET): Likewise. > (fetch_xstateregs): Likewise. > (store_xstateregs): Likewise. > (GETXSTATEREGS_SUPPLIES): Likewise. > (regmap): Include 8 upper YMM registers. > (i386_linux_fetch_inferior_registers): Support XSAVE extended > state. > (i386_linux_store_inferior_registers): Likewise. > (i386_linux_read_description): Check and enable AVX target > descriptions. > > * i386-linux-tdep.c: Include "regset.h", "i387-tdep.h", > "i386-xstate.h" and "features/i386/i386-avx-linux.c". > (i386_linux_regset_sections): Add ".reg-xstate". > (i386_linux_gregset_reg_offset): Include 8 upper YMM registers. > (i386_linux_update_xstateregset): New. > (i386_linux_core_read_xcr0): Likewise. > (i386_linux_core_read_description): Check and enable AVX target > description. > (i386_linux_init_abi): Set xsave_xcr0_offset. > (_initialize_i386_linux_tdep): Call > initialize_tdesc_i386_avx_linux. > > * i386-linux-tdep.h (I386_LINUX_ORIG_EAX_REGNUM): Replace > I386_SSE_NUM_REGS with I386_AVX_NUM_REGS. > (i386_linux_core_read_xcr0): New. > (tdesc_i386_avx_linux): Likewise. > (i386_linux_update_xstateregset): Likewise. > (I386_LINUX_XSAVE_XCR0_OFFSET): Likewise. > > * i386-tdep.c: Include "i386-xstate.h" and > "features/i386/i386-avx.c". > (i386_ymm_names): New. > (i386_ymmh_names): Likewise. > (i386_ymmh_regnum_p): Likewise. > (i386_ymm_regnum_p): Likewise. > (i386_xmm_regnum_p): Likewise. > (i386_register_name): Likewise. > (i386_ymm_type): Likewise. > (i386_supply_xstateregset): Likewise. > (i386_collect_xstateregset): Likewise. > (i386_sse_regnum_p): Removed. > (i386_pseudo_register_name): Support pseudo YMM registers. > (i386_pseudo_register_type): Likewise. > (i386_pseudo_register_read): Likewise. > (i386_pseudo_register_write): Likewise. > (i386_dbx_reg_to_regnum): Return %ymmN register number for > %xmmN if AVX is available. > (i386_regset_from_core_section): Support .reg-xstate section. > (i386_register_reggroup_p): Supper upper YMM and YMM registers. > (i386_process_record): Replace i386_sse_regnum_p with > i386_xmm_regnum_p. > (i386_validate_tdesc_p): Support org.gnu.gdb.i386.avx feature. > Set ymmh_register_names, num_ymm_regs, ymm0h_regnum and xcr0. > (i386_gdbarch_init): Set xstateregset. Set xsave_xcr0_offset. > Call set_gdbarch_register_name. Replace I386_SSE_NUM_REGS with > I386_AVX_NUM_REGS. Set ymmh_register_names, ymm0h_regnum and > num_ymm_regs. Add num_ymm_regs to set_gdbarch_num_pseudo_regs. > Set ymm0_regnum. > (_initialize_i386_tdep): Call initialize_tdesc_i386_avx. > > * i386-tdep.h (gdbarch_tdep): Add xstateregset, ymm0_regnum, > xcr0, xsave_xcr0_offset, ymm0h_regnum, ymmh_register_names and > i386_ymm_type. > (i386_regnum): Add I386_YMM0H_REGNUM, and I386_YMM7H_REGNUM. > (I386_AVX_NUM_REGS): New. > (i386_xmm_regnum_p): Likewise. > (i386_ymm_regnum_p): Likewise. > (i386_ymmh_regnum_p): Likewise. > > * common/i386-xstate.h: New. > > diff --git a/gdb/common/i386-xstate.h b/gdb/common/i386-xstate.h > new file mode 100644 > index 0000000..5e16015 > --- /dev/null > +++ b/gdb/common/i386-xstate.h > @@ -0,0 +1,41 @@ > +/* Common code for i386 XSAVE extended state. > + > + Copyright (C) 2010 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#ifndef I386_XSTATE_H > +#define I386_XSTATE_H 1 > + > +/* The extended state feature bits. */ > +#define I386_XSTATE_X87 (1ULL << 0) > +#define I386_XSTATE_SSE (1ULL << 1) > +#define I386_XSTATE_AVX (1ULL << 2) > + > +/* Supported mask and size of the extended state. */ > +#define I386_XSTATE_SSE_MASK (I386_XSTATE_X87 | I386_XSTATE_SSE) > +#define I386_XSTATE_AVX_MASK (I386_XSTATE_SSE_MASK | I386_XSTATE_AVX) > + > +#define I386_XSTATE_SSE_SIZE 576 > +#define I386_XSTATE_AVX_SIZE 832 > +#define I386_XSTATE_MAX_SIZE 832 > + > +/* Get I386 XSAVE extended state size. */ > +#define I386_XSTATE_SIZE(XCR0) \ > + (((XCR0) & I386_XSTATE_AVX) != 0 \ > + ? I386_XSTATE_AVX_SIZE : I386_XSTATE_SSE_SIZE) > + > +#endif /* I386_XSTATE_H */ > diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c > index 31b9086..d1048eb 100644 > --- a/gdb/i386-linux-nat.c > +++ b/gdb/i386-linux-nat.c > @@ -23,11 +23,14 @@ > #include "inferior.h" > #include "gdbcore.h" > #include "regcache.h" > +#include "regset.h" > #include "target.h" > #include "linux-nat.h" > > #include "gdb_assert.h" > #include "gdb_string.h" > +#include "elf/common.h" > +#include > #include > #include > #include > @@ -69,6 +72,19 @@ > > /* Defines ps_err_e, struct ps_prochandle. */ > #include "gdb_proc_service.h" > + > +#include "i386-xstate.h" > + > +#ifndef PTRACE_GETREGSET > +#define PTRACE_GETREGSET 0x4204 > +#endif > + > +#ifndef PTRACE_SETREGSET > +#define PTRACE_SETREGSET 0x4205 > +#endif > + > +/* Does the current host support PTRACE_GETREGSET? */ > +static int have_ptrace_getregset = -1; > > > /* The register sets used in GNU/Linux ELF core-dumps are identical to > @@ -98,6 +114,8 @@ static int regmap[] = > -1, -1, -1, -1, /* xmm0, xmm1, xmm2, xmm3 */ > -1, -1, -1, -1, /* xmm4, xmm5, xmm6, xmm6 */ > -1, /* mxcsr */ > + -1, -1, -1, -1, /* ymm0h, ymm1h, ymm2h, ymm3h */ > + -1, -1, -1, -1, /* ymm4h, ymm5h, ymm6h, ymm6h */ > ORIG_EAX > }; > > @@ -110,6 +128,9 @@ static int regmap[] = > #define GETFPXREGS_SUPPLIES(regno) \ > (I386_ST0_REGNUM <= (regno) && (regno) < I386_SSE_NUM_REGS) > > +#define GETXSTATEREGS_SUPPLIES(regno) \ > + (I386_ST0_REGNUM <= (regno) && (regno) < I386_AVX_NUM_REGS) > + > /* Does the current host support the GETREGS request? */ > int have_ptrace_getregs = > #ifdef HAVE_PTRACE_GETREGS > @@ -355,6 +376,57 @@ static void store_fpregs (const struct regcache *regcache, int tid, int regno) { > > /* Transfering floating-point and SSE registers to and from GDB. */ > > +/* Fetch all registers covered by the PTRACE_GETREGSET request from > + process/thread TID and store their values in GDB's register array. > + Return non-zero if successful, zero otherwise. */ > + > +static int > +fetch_xstateregs (struct regcache *regcache, int tid) > +{ > + char xstateregs[I386_XSTATE_MAX_SIZE]; > + struct iovec iov; > + > + if (!have_ptrace_getregset) > + return 0; > + > + iov.iov_base = xstateregs; > + iov.iov_len = sizeof(xstateregs); > + if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE, > + &iov) < 0) > + perror_with_name (_("Couldn't read extended state status")); > + > + i387_supply_xsave (regcache, -1, xstateregs); > + return 1; > +} > + > +/* Store all valid registers in GDB's register array covered by the > + PTRACE_SETREGSET request into the process/thread specified by TID. > + Return non-zero if successful, zero otherwise. */ > + > +static int > +store_xstateregs (const struct regcache *regcache, int tid, int regno) > +{ > + char xstateregs[I386_XSTATE_MAX_SIZE]; > + struct iovec iov; > + > + if (!have_ptrace_getregset) > + return 0; > + > + iov.iov_base = xstateregs; > + iov.iov_len = sizeof(xstateregs); > + if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE, > + &iov) < 0) > + perror_with_name (_("Couldn't read extended state status")); > + > + i387_collect_xsave (regcache, regno, xstateregs, 0); > + > + if (ptrace (PTRACE_SETREGSET, tid, (unsigned int) NT_X86_XSTATE, > + (int) &iov) < 0) > + perror_with_name (_("Couldn't write extended state status")); > + > + return 1; > +} > + > #ifdef HAVE_PTRACE_GETFPXREGS > > /* Fill GDB's register array with the floating-point and SSE register > @@ -489,6 +561,8 @@ i386_linux_fetch_inferior_registers (struct target_ops *ops, > return; > } > > + if (fetch_xstateregs (regcache, tid)) > + return; > if (fetch_fpxregs (regcache, tid)) > return; > fetch_fpregs (regcache, tid); > @@ -501,6 +575,12 @@ i386_linux_fetch_inferior_registers (struct target_ops *ops, > return; > } > > + if (GETXSTATEREGS_SUPPLIES (regno)) > + { > + if (fetch_xstateregs (regcache, tid)) > + return; > + } > + > if (GETFPXREGS_SUPPLIES (regno)) > { > if (fetch_fpxregs (regcache, tid)) > @@ -553,6 +633,8 @@ i386_linux_store_inferior_registers (struct target_ops *ops, > if (regno == -1) > { > store_regs (regcache, tid, regno); > + if (store_xstateregs (regcache, tid, regno)) > + return; > if (store_fpxregs (regcache, tid, regno)) > return; > store_fpregs (regcache, tid, regno); > @@ -565,6 +647,12 @@ i386_linux_store_inferior_registers (struct target_ops *ops, > return; > } > > + if (GETXSTATEREGS_SUPPLIES (regno)) > + { > + if (store_xstateregs (regcache, tid, regno)) > + return; > + } > + > if (GETFPXREGS_SUPPLIES (regno)) > { > if (store_fpxregs (regcache, tid, regno)) > @@ -858,7 +946,50 @@ i386_linux_child_post_startup_inferior (ptid_t ptid) > static const struct target_desc * > i386_linux_read_description (struct target_ops *ops) > { > - return tdesc_i386_linux; > + static uint64_t xcr0; > + > + if (have_ptrace_getregset == -1) > + { > + int tid; > + uint64_t xstateregs[(I386_XSTATE_SSE_SIZE / sizeof (uint64_t))]; > + struct iovec iov; > + unsigned int xstate_size; > + > + /* GNU/Linux LWP ID's are process ID's. */ > + tid = TIDGET (inferior_ptid); > + if (tid == 0) > + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ > + > + iov.iov_base = xstateregs; > + iov.iov_len = sizeof (xstateregs); > + > + /* Check if PTRACE_GETREGSET works. */ > + if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE, > + &iov) < 0) > + { > + have_ptrace_getregset = 0; > + xstate_size = 0; > + } > + else > + { > + have_ptrace_getregset = 1; > + > + /* Get XCR0 from XSAVE extended state. */ > + xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET > + / sizeof (long long))]; > + > + xstate_size = I386_XSTATE_SIZE (xcr0); > + } > + > + i386_linux_update_xstateregset (xstate_size); > + } > + > + /* Check the native XCR0 only if PTRACE_GETREGSET is available. */ > + if (have_ptrace_getregset > + && (xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK) > + return tdesc_i386_avx_linux; > + else > + return tdesc_i386_linux; > } > > void > diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c > index b23c109..bda5d19 100644 > --- a/gdb/i386-linux-tdep.c > +++ b/gdb/i386-linux-tdep.c > @@ -23,6 +23,7 @@ > #include "frame.h" > #include "value.h" > #include "regcache.h" > +#include "regset.h" > #include "inferior.h" > #include "osabi.h" > #include "reggroups.h" > @@ -36,9 +37,11 @@ > #include "solib-svr4.h" > #include "symtab.h" > #include "arch-utils.h" > -#include "regset.h" > #include "xml-syscall.h" > > +#include "i387-tdep.h" > +#include "i386-xstate.h" > + > /* The syscall's XML filename for i386. */ > #define XML_SYSCALL_FILENAME_I386 "syscalls/i386-linux.xml" > > @@ -47,6 +50,7 @@ > #include > > #include "features/i386/i386-linux.c" > +#include "features/i386/i386-avx-linux.c" > > /* Supported register note sections. */ > static struct core_regset_section i386_linux_regset_sections[] = > @@ -54,6 +58,7 @@ static struct core_regset_section i386_linux_regset_sections[] = > { ".reg", 144, "general-purpose" }, > { ".reg2", 108, "floating-point" }, > { ".reg-xfp", 512, "extended floating-point" }, > + { ".reg-xstate", 0, "XSAVE extended state" }, > { NULL, 0 } > }; > > @@ -533,6 +538,7 @@ static int i386_linux_gregset_reg_offset[] = > -1, -1, -1, -1, -1, -1, -1, -1, > -1, -1, -1, -1, -1, -1, -1, -1, > -1, > + -1, -1, -1, -1, -1, -1, -1, -1, > 11 * 4 /* "orig_eax" */ > }; > > @@ -560,6 +566,59 @@ static int i386_linux_sc_reg_offset[] = > 0 * 4 /* %gs */ > }; > > +/* Update XSAVE extended state register note section. */ > + > +void > +i386_linux_update_xstateregset (unsigned int xstate_size) > +{ > + struct core_regset_section *xstate = &i386_linux_regset_sections[3]; > + > + /* Update the XSAVE extended state register note section for "gcore". > + Disable it if its size is 0. */ > + gdb_assert (strcmp (xstate->sect_name, ".reg-xstate") == 0); > + if (xstate_size) > + xstate->size = xstate_size; > + else > + xstate->sect_name = NULL; > +} > + > +/* Get XSAVE extended state xcr0 from core dump. */ > + > +uint64_t > +i386_linux_core_read_xcr0 (struct gdbarch *gdbarch, > + struct target_ops *target, bfd *abfd) > +{ > + asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate"); > + uint64_t xcr0; > + > + if (xstate) > + { > + size_t size = bfd_section_size (abfd, xstate); > + > + /* Check extended state size. */ > + if (size < I386_XSTATE_AVX_SIZE) > + xcr0 = I386_XSTATE_SSE_MASK; > + else > + { > + char contents[8]; > + > + if (! bfd_get_section_contents (abfd, xstate, contents, > + I386_LINUX_XSAVE_XCR0_OFFSET, > + 8)) > + { > + warning (_("Couldn't read `xcr0' bytes from `.reg-xstate' section in core file.")); > + return 0; > + } > + > + xcr0 = bfd_get_64 (abfd, contents); > + } > + } > + else > + xcr0 = I386_XSTATE_SSE_MASK; > + > + return xcr0; > +} > + > /* Get Linux/x86 target description from core dump. */ > > static const struct target_desc * > @@ -568,12 +627,17 @@ i386_linux_core_read_description (struct gdbarch *gdbarch, > bfd *abfd) > { > asection *section = bfd_get_section_by_name (abfd, ".reg2"); > + uint64_t xcr0; > > if (section == NULL) > return NULL; > > /* Linux/i386. */ > - return tdesc_i386_linux; > + xcr0 = i386_linux_core_read_xcr0 (gdbarch, target, abfd); > + if ((xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK) > + return tdesc_i386_avx_linux; > + else > + return tdesc_i386_linux; > } > > static void > @@ -623,6 +687,8 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) > tdep->sc_reg_offset = i386_linux_sc_reg_offset; > tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset); > > + tdep->xsave_xcr0_offset = I386_LINUX_XSAVE_XCR0_OFFSET; > + > set_gdbarch_process_record (gdbarch, i386_process_record); > set_gdbarch_process_record_signal (gdbarch, i386_linux_record_signal); > > @@ -840,4 +906,5 @@ _initialize_i386_linux_tdep (void) > > /* Initialize the Linux target description */ > initialize_tdesc_i386_linux (); > + initialize_tdesc_i386_avx_linux (); > } > diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h > index 11f7295..187769b 100644 > --- a/gdb/i386-linux-tdep.h > +++ b/gdb/i386-linux-tdep.h > @@ -30,12 +30,41 @@ > /* Register number for the "orig_eax" pseudo-register. If this > pseudo-register contains a value >= 0 it is interpreted as the > system call number that the kernel is supposed to restart. */ > -#define I386_LINUX_ORIG_EAX_REGNUM I386_SSE_NUM_REGS > +#define I386_LINUX_ORIG_EAX_REGNUM I386_AVX_NUM_REGS > > /* Total number of registers for GNU/Linux. */ > #define I386_LINUX_NUM_REGS (I386_LINUX_ORIG_EAX_REGNUM + 1) > > +/* Get XSAVE extended state xcr0 from core dump. */ > +extern uint64_t i386_linux_core_read_xcr0 > + (struct gdbarch *gdbarch, struct target_ops *target, bfd *abfd); > + > /* Linux target description. */ > extern struct target_desc *tdesc_i386_linux; > +extern struct target_desc *tdesc_i386_avx_linux; > + > +/* Update XSAVE extended state register note section. */ > +extern void i386_linux_update_xstateregset (unsigned int xstate_size); > + > +/* Format of XSAVE extended state is: > + struct > + { > + fxsave_bytes[0..463] > + sw_usable_bytes[464..511] > + xstate_hdr_bytes[512..575] > + avx_bytes[576..831] > + future_state etc > + }; > + > + Same memory layout will be used for the coredump NT_X86_XSTATE > + representing the XSAVE extended state registers. > + > + The first 8 bytes of the sw_usable_bytes[464..467] is the OS enabled > + extended state mask, which is the same as the extended control register > + 0 (the XFEATURE_ENABLED_MASK register), XCR0. We can use this mask > + together with the mask saved in the xstate_hdr_bytes to determine what > + states the processor/OS supports and what state, used or initialized, > + the process/thread is in. */ > +#define I386_LINUX_XSAVE_XCR0_OFFSET 464 > > #endif /* i386-linux-tdep.h */ > diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c > index 703d003..ce658cd 100644 > --- a/gdb/i386-tdep.c > +++ b/gdb/i386-tdep.c > @@ -51,11 +51,13 @@ > > #include "i386-tdep.h" > #include "i387-tdep.h" > +#include "i386-xstate.h" > > #include "record.h" > #include > > #include "features/i386/i386.c" > +#include "features/i386/i386-avx.c" > > /* Register names. */ > > @@ -74,6 +76,18 @@ static const char *i386_register_names[] = > "mxcsr" > }; > > +static const char *i386_ymm_names[] = > +{ > + "ymm0", "ymm1", "ymm2", "ymm3", > + "ymm4", "ymm5", "ymm6", "ymm7", > +}; > + > +static const char *i386_ymmh_names[] = > +{ > + "ymm0h", "ymm1h", "ymm2h", "ymm3h", > + "ymm4h", "ymm5h", "ymm6h", "ymm7h", > +}; > + > /* Register names for MMX pseudo-registers. */ > > static const char *i386_mmx_names[] = > @@ -150,18 +164,47 @@ i386_dword_regnum_p (struct gdbarch *gdbarch, int regnum) > return regnum >= 0 && regnum < tdep->num_dword_regs; > } > > +int > +i386_ymmh_regnum_p (struct gdbarch *gdbarch, int regnum) > +{ > + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); > + int ymm0h_regnum = tdep->ymm0h_regnum; > + > + if (ymm0h_regnum < 0) > + return 0; > + > + regnum -= ymm0h_regnum; > + return regnum >= 0 && regnum < tdep->num_ymm_regs; > +} > + > +/* AVX register? */ > + > +int > +i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum) > +{ > + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); > + int ymm0_regnum = tdep->ymm0_regnum; > + > + if (ymm0_regnum < 0) > + return 0; > + > + regnum -= ymm0_regnum; > + return regnum >= 0 && regnum < tdep->num_ymm_regs; > +} > + > /* SSE register? */ > > -static int > -i386_sse_regnum_p (struct gdbarch *gdbarch, int regnum) > +int > +i386_xmm_regnum_p (struct gdbarch *gdbarch, int regnum) > { > struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); > + int num_xmm_regs = I387_NUM_XMM_REGS (tdep); > > - if (I387_NUM_XMM_REGS (tdep) == 0) > + if (num_xmm_regs == 0) > return 0; > > - return (I387_XMM0_REGNUM (tdep) <= regnum > - && regnum < I387_MXCSR_REGNUM (tdep)); > + regnum -= I387_XMM0_REGNUM (tdep); > + return regnum >= 0 && regnum < num_xmm_regs; > } > > static int > @@ -201,6 +244,19 @@ i386_fpc_regnum_p (struct gdbarch *gdbarch, int regnum) > && regnum < I387_XMM0_REGNUM (tdep)); > } > > +/* Return the name of register REGNUM, or the empty string if it is > + an anonymous register. */ > + > +static const char * > +i386_register_name (struct gdbarch *gdbarch, int regnum) > +{ > + /* Hide the upper YMM registers. */ > + if (i386_ymmh_regnum_p (gdbarch, regnum)) > + return ""; > + > + return tdesc_register_name (gdbarch, regnum); > +} > + > /* Return the name of register REGNUM. */ > > const char * > @@ -209,6 +265,8 @@ i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum) > struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); > if (i386_mmx_regnum_p (gdbarch, regnum)) > return i386_mmx_names[regnum - I387_MM0_REGNUM (tdep)]; > + else if (i386_ymm_regnum_p (gdbarch, regnum)) > + return i386_ymm_names[regnum - tdep->ymm0_regnum]; > else if (i386_byte_regnum_p (gdbarch, regnum)) > return i386_byte_names[regnum - tdep->al_regnum]; > else if (i386_word_regnum_p (gdbarch, regnum)) > @@ -246,7 +304,13 @@ i386_dbx_reg_to_regnum (struct gdbarch *gdbarch, int reg) > else if (reg >= 21 && reg <= 28) > { > /* SSE registers. */ > - return reg - 21 + I387_XMM0_REGNUM (tdep); > + int ymm0_regnum = tdep->ymm0_regnum; > + > + if (ymm0_regnum >= 0 > + && i386_xmm_regnum_p (gdbarch, reg)) > + return reg - 21 + ymm0_regnum; > + else > + return reg - 21 + I387_XMM0_REGNUM (tdep); > } > else if (reg >= 29 && reg <= 36) > { > @@ -2184,6 +2248,59 @@ i387_ext_type (struct gdbarch *gdbarch) > return tdep->i387_ext_type; > } > > +/* Construct vector type for pseudo YMM registers. We can't use > + tdesc_find_type since YMM isn't described in target description. */ > + > +static struct type * > +i386_ymm_type (struct gdbarch *gdbarch) > +{ > + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); > + > + if (!tdep->i386_ymm_type) > + { > + const struct builtin_type *bt = builtin_type (gdbarch); > + > + /* The type we're building is this: */ > +#if 0 > + union __gdb_builtin_type_vec256i > + { > + int128_t uint128[2]; > + int64_t v2_int64[4]; > + int32_t v4_int32[8]; > + int16_t v8_int16[16]; > + int8_t v16_int8[32]; > + double v2_double[4]; > + float v4_float[8]; > + }; > +#endif > + > + struct type *t; > + > + t = arch_composite_type (gdbarch, > + "__gdb_builtin_type_vec256i", TYPE_CODE_UNION); > + append_composite_type_field (t, "v8_float", > + init_vector_type (bt->builtin_float, 8)); > + append_composite_type_field (t, "v4_double", > + init_vector_type (bt->builtin_double, 4)); > + append_composite_type_field (t, "v32_int8", > + init_vector_type (bt->builtin_int8, 32)); > + append_composite_type_field (t, "v16_int16", > + init_vector_type (bt->builtin_int16, 16)); > + append_composite_type_field (t, "v8_int32", > + init_vector_type (bt->builtin_int32, 8)); > + append_composite_type_field (t, "v4_int64", > + init_vector_type (bt->builtin_int64, 4)); > + append_composite_type_field (t, "v2_int128", > + init_vector_type (bt->builtin_int128, 2)); > + > + TYPE_VECTOR (t) = 1; > + TYPE_NAME (t) = "builtin_type_vec128i"; > + tdep->i386_ymm_type = t; > + } > + > + return tdep->i386_ymm_type; > +} > + > /* Construct vector type for MMX registers. */ > static struct type * > i386_mmx_type (struct gdbarch *gdbarch) > @@ -2234,6 +2351,8 @@ i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum) > { > if (i386_mmx_regnum_p (gdbarch, regnum)) > return i386_mmx_type (gdbarch); > + else if (i386_ymm_regnum_p (gdbarch, regnum)) > + return i386_ymm_type (gdbarch); > else > { > const struct builtin_type *bt = builtin_type (gdbarch); > @@ -2285,7 +2404,22 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, > { > struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); > > - if (i386_word_regnum_p (gdbarch, regnum)) > + if (i386_ymm_regnum_p (gdbarch, regnum)) > + { > + regnum -= tdep->ymm0_regnum; > + > + /* Extract (always little endian). Read lower 128bits. */ > + regcache_raw_read (regcache, > + I387_XMM0_REGNUM (tdep) + regnum, > + raw_buf); > + memcpy (buf, raw_buf, 16); > + /* Read upper 128bits. */ > + regcache_raw_read (regcache, > + tdep->ymm0h_regnum + regnum, > + raw_buf); > + memcpy (buf + 16, raw_buf, 16); > + } > + else if (i386_word_regnum_p (gdbarch, regnum)) > { > int gpnum = regnum - tdep->ax_regnum; > > @@ -2334,7 +2468,20 @@ i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, > { > struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); > > - if (i386_word_regnum_p (gdbarch, regnum)) > + if (i386_ymm_regnum_p (gdbarch, regnum)) > + { > + regnum -= tdep->ymm0_regnum; > + > + /* ... Write lower 128bits. */ > + regcache_raw_write (regcache, > + I387_XMM0_REGNUM (tdep) + regnum, > + buf); > + /* ... Write upper 128bits. */ > + regcache_raw_write (regcache, > + tdep->ymm0h_regnum + regnum, > + buf + 16); > + } > + else if (i386_word_regnum_p (gdbarch, regnum)) > { > int gpnum = regnum - tdep->ax_regnum; > > @@ -2581,6 +2728,28 @@ i386_collect_fpregset (const struct regset *regset, > i387_collect_fsave (regcache, regnum, fpregs); > } > > +/* Similar to i386_supply_fpregset, but use XSAVE extended state. */ > + > +static void > +i386_supply_xstateregset (const struct regset *regset, > + struct regcache *regcache, int regnum, > + const void *xstateregs, size_t len) > +{ > + const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch); > + i387_supply_xsave (regcache, regnum, xstateregs); > +} > + > +/* Similar to i386_collect_fpregset , but use XSAVE extended state. */ > + > +static void > +i386_collect_xstateregset (const struct regset *regset, > + const struct regcache *regcache, > + int regnum, void *xstateregs, size_t len) > +{ > + const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch); > + i387_collect_xsave (regcache, regnum, xstateregs, 1); > +} > + > /* Return the appropriate register set for the core section identified > by SECT_NAME and SECT_SIZE. */ > > @@ -2608,6 +2777,16 @@ i386_regset_from_core_section (struct gdbarch *gdbarch, > return tdep->fpregset; > } > > + if (strcmp (sect_name, ".reg-xstate") == 0) > + { > + if (tdep->xstateregset == NULL) > + tdep->xstateregset = regset_alloc (gdbarch, > + i386_supply_xstateregset, > + i386_collect_xstateregset); > + > + return tdep->xstateregset; > + } > + > return NULL; > } > > @@ -2801,46 +2980,60 @@ int > i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum, > struct reggroup *group) > { > - int sse_regnum_p, fp_regnum_p, mmx_regnum_p, byte_regnum_p, > - word_regnum_p, dword_regnum_p; > + const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); > + int fp_regnum_p, mmx_regnum_p, xmm_regnum_p, mxcsr_regnum_p, > + ymm_regnum_p, ymmh_regnum_p; > > /* Don't include pseudo registers, except for MMX, in any register > groups. */ > - byte_regnum_p = i386_byte_regnum_p (gdbarch, regnum); > - if (byte_regnum_p) > + if (i386_byte_regnum_p (gdbarch, regnum)) > return 0; > > - word_regnum_p = i386_word_regnum_p (gdbarch, regnum); > - if (word_regnum_p) > + if (i386_word_regnum_p (gdbarch, regnum)) > return 0; > > - dword_regnum_p = i386_dword_regnum_p (gdbarch, regnum); > - if (dword_regnum_p) > + if (i386_dword_regnum_p (gdbarch, regnum)) > return 0; > > mmx_regnum_p = i386_mmx_regnum_p (gdbarch, regnum); > if (group == i386_mmx_reggroup) > return mmx_regnum_p; > > - sse_regnum_p = (i386_sse_regnum_p (gdbarch, regnum) > - || i386_mxcsr_regnum_p (gdbarch, regnum)); > + xmm_regnum_p = i386_xmm_regnum_p (gdbarch, regnum); > + mxcsr_regnum_p = i386_mxcsr_regnum_p (gdbarch, regnum); > if (group == i386_sse_reggroup) > - return sse_regnum_p; > + return xmm_regnum_p || mxcsr_regnum_p; > + > + ymm_regnum_p = i386_ymm_regnum_p (gdbarch, regnum); > if (group == vector_reggroup) > - return mmx_regnum_p || sse_regnum_p; > + return (mmx_regnum_p > + || ymm_regnum_p > + || mxcsr_regnum_p > + || (xmm_regnum_p > + && ((tdep->xcr0 & I386_XSTATE_AVX_MASK) > + == I386_XSTATE_SSE_MASK))); > > fp_regnum_p = (i386_fp_regnum_p (gdbarch, regnum) > || i386_fpc_regnum_p (gdbarch, regnum)); > if (group == float_reggroup) > return fp_regnum_p; > > + /* For "info reg all", don't include upper YMM registers nor XMM > + registers when AVX is supported. */ > + ymmh_regnum_p = i386_ymmh_regnum_p (gdbarch, regnum); > + if (group == all_reggroup > + && ((xmm_regnum_p > + && (tdep->xcr0 & I386_XSTATE_AVX)) > + || ymmh_regnum_p)) > + return 0; > + > if (group == general_reggroup) > return (!fp_regnum_p > && !mmx_regnum_p > - && !sse_regnum_p > - && !byte_regnum_p > - && !word_regnum_p > - && !dword_regnum_p); > + && !mxcsr_regnum_p > + && !xmm_regnum_p > + && !ymm_regnum_p > + && !ymmh_regnum_p); > > return default_register_reggroup_p (gdbarch, regnum, group); > } > @@ -5665,7 +5858,7 @@ no_support_3dnow_data: > record_arch_list_add_reg (ir.regcache, i); > > for (i = I387_XMM0_REGNUM (tdep); > - i386_sse_regnum_p (gdbarch, i); i++) > + i386_xmm_regnum_p (gdbarch, i); i++) > record_arch_list_add_reg (ir.regcache, i); > > if (i386_mxcsr_regnum_p (gdbarch, I387_MXCSR_REGNUM(tdep))) > @@ -6065,7 +6258,7 @@ reswitch_prefix_add: > if (i386_record_modrm (&ir)) > return -1; > ir.reg |= rex_r; > - if (!i386_sse_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.reg)) > + if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.reg)) > goto no_support; > record_arch_list_add_reg (ir.regcache, > I387_XMM0_REGNUM (tdep) + ir.reg); > @@ -6097,7 +6290,7 @@ reswitch_prefix_add: > || opcode == 0x0f17 || opcode == 0x660f17) > goto no_support; > ir.rm |= ir.rex_b; > - if (!i386_sse_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm)) > + if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm)) > goto no_support; > record_arch_list_add_reg (ir.regcache, > I387_XMM0_REGNUM (tdep) + ir.rm); > @@ -6275,7 +6468,7 @@ reswitch_prefix_add: > if (i386_record_modrm (&ir)) > return -1; > ir.rm |= ir.rex_b; > - if (!i386_sse_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm)) > + if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm)) > goto no_support; > record_arch_list_add_reg (ir.regcache, > I387_XMM0_REGNUM (tdep) + ir.rm); > @@ -6329,7 +6522,7 @@ reswitch_prefix_add: > if (ir.mod == 3) > { > ir.rm |= ir.rex_b; > - if (!i386_sse_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm)) > + if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm)) > goto no_support; > record_arch_list_add_reg (ir.regcache, > I387_XMM0_REGNUM (tdep) + ir.rm); > @@ -6449,7 +6642,8 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, > struct tdesc_arch_data *tdesc_data) > { > const struct target_desc *tdesc = tdep->tdesc; > - const struct tdesc_feature *feature_core, *feature_vector; > + const struct tdesc_feature *feature_core; > + const struct tdesc_feature *feature_sse, *feature_avx; > int i, num_regs, valid_p; > > if (! tdesc_has_registers (tdesc)) > @@ -6459,13 +6653,37 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, > feature_core = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.core"); > > /* Get SSE registers. */ > - feature_vector = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.sse"); > + feature_sse = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.sse"); > > - if (feature_core == NULL || feature_vector == NULL) > + if (feature_core == NULL || feature_sse == NULL) > return 0; > > + /* Try AVX registers. */ > + feature_avx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx"); > + > valid_p = 1; > > + /* The XCR0 bits. */ > + if (feature_avx) > + { > + tdep->xcr0 = I386_XSTATE_AVX_MASK; > + > + /* It may have been set by OSABI initialization function. */ > + if (tdep->num_ymm_regs == 0) > + { > + tdep->ymmh_register_names = i386_ymmh_names; > + tdep->num_ymm_regs = 8; > + tdep->ymm0h_regnum = I386_YMM0H_REGNUM; > + } > + > + for (i = 0; i < tdep->num_ymm_regs; i++) > + valid_p &= tdesc_numbered_register (feature_avx, tdesc_data, > + tdep->ymm0h_regnum + i, > + tdep->ymmh_register_names[i]); > + } > + else > + tdep->xcr0 = I386_XSTATE_SSE_MASK; > + > num_regs = tdep->num_core_regs; > for (i = 0; i < num_regs; i++) > valid_p &= tdesc_numbered_register (feature_core, tdesc_data, i, > @@ -6474,7 +6692,7 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, > /* Need to include %mxcsr, so add one. */ > num_regs += tdep->num_xmm_regs + 1; > for (; i < num_regs; i++) > - valid_p &= tdesc_numbered_register (feature_vector, tdesc_data, i, > + valid_p &= tdesc_numbered_register (feature_sse, tdesc_data, i, > tdep->register_names[i]); > > return valid_p; > @@ -6489,6 +6707,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > struct tdesc_arch_data *tdesc_data; > const struct target_desc *tdesc; > int mm0_regnum; > + int ymm0_regnum; > > /* If there is already a candidate, use it. */ > arches = gdbarch_list_lookup_by_info (arches, &info); > @@ -6509,6 +6728,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > tdep->fpregset = NULL; > tdep->sizeof_fpregset = I387_SIZEOF_FSAVE; > > + tdep->xstateregset = NULL; > + > /* The default settings include the FPU registers, the MMX registers > and the SSE registers. This can be overridden for a specific ABI > by adjusting the members `st0_regnum', `mm0_regnum' and > @@ -6538,6 +6759,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > tdep->sc_pc_offset = -1; > tdep->sc_sp_offset = -1; > > + tdep->xsave_xcr0_offset = -1; > + > tdep->record_regmap = i386_record_regmap; > > /* The format used for `long double' on almost all i386 targets is > @@ -6654,9 +6877,14 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > set_tdesc_pseudo_register_type (gdbarch, i386_pseudo_register_type); > set_tdesc_pseudo_register_name (gdbarch, i386_pseudo_register_name); > > - /* The default ABI includes general-purpose registers, > - floating-point registers, and the SSE registers. */ > - set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS); > + /* Override the normal target description method to make the AVX > + upper halves anonymous. */ > + set_gdbarch_register_name (gdbarch, i386_register_name); > + > + /* Even though the default ABI only includes general-purpose registers, > + floating-point registers and the SSE registers, we have to leave a > + gap for the upper AVX registers. */ > + set_gdbarch_num_regs (gdbarch, I386_AVX_NUM_REGS); > > /* Get the x86 target description from INFO. */ > tdesc = info.target_desc; > @@ -6667,10 +6895,15 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > tdep->num_core_regs = I386_NUM_GREGS + I387_NUM_REGS; > tdep->register_names = i386_register_names; > > + /* No upper YMM registers. */ > + tdep->ymmh_register_names = NULL; > + tdep->ymm0h_regnum = -1; > + > tdep->num_byte_regs = 8; > tdep->num_word_regs = 8; > tdep->num_dword_regs = 0; > tdep->num_mmx_regs = 8; > + tdep->num_ymm_regs = 0; > > tdesc_data = tdesc_data_alloc (); > > @@ -6678,24 +6911,25 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > info.tdep_info = (void *) tdesc_data; > gdbarch_init_osabi (info, gdbarch); > > + if (!i386_validate_tdesc_p (tdep, tdesc_data)) > + { > + tdesc_data_cleanup (tdesc_data); > + xfree (tdep); > + gdbarch_free (gdbarch); > + return NULL; > + } > + > /* Wire in pseudo registers. Number of pseudo registers may be > changed. */ > set_gdbarch_num_pseudo_regs (gdbarch, (tdep->num_byte_regs > + tdep->num_word_regs > + tdep->num_dword_regs > - + tdep->num_mmx_regs)); > + + tdep->num_mmx_regs > + + tdep->num_ymm_regs)); > > /* Target description may be changed. */ > tdesc = tdep->tdesc; > > - if (!i386_validate_tdesc_p (tdep, tdesc_data)) > - { > - tdesc_data_cleanup (tdesc_data); > - xfree (tdep); > - gdbarch_free (gdbarch); > - return NULL; > - } > - > tdesc_use_registers (gdbarch, tdesc, tdesc_data); > > /* Override gdbarch_register_reggroup_p set in tdesc_use_registers. */ > @@ -6705,16 +6939,26 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > tdep->al_regnum = gdbarch_num_regs (gdbarch); > tdep->ax_regnum = tdep->al_regnum + tdep->num_byte_regs; > > - mm0_regnum = tdep->ax_regnum + tdep->num_word_regs; > + ymm0_regnum = tdep->ax_regnum + tdep->num_word_regs; > if (tdep->num_dword_regs) > { > /* Support dword pseudo-registesr if it hasn't been disabled, */ > - tdep->eax_regnum = mm0_regnum; > - mm0_regnum = tdep->eax_regnum + tdep->num_dword_regs; > + tdep->eax_regnum = ymm0_regnum; > + ymm0_regnum += tdep->num_dword_regs; > } > else > tdep->eax_regnum = -1; > > + mm0_regnum = ymm0_regnum; > + if (tdep->num_ymm_regs) > + { > + /* Support YMM pseudo-registesr if it is available, */ > + tdep->ymm0_regnum = ymm0_regnum; > + mm0_regnum += tdep->num_ymm_regs; > + } > + else > + tdep->ymm0_regnum = -1; > + > if (tdep->num_mmx_regs != 0) > { > /* Support MMX pseudo-registesr if MMX hasn't been disabled, */ > @@ -6797,6 +7041,7 @@ is \"default\"."), > > /* Initialize the standard target descriptions. */ > initialize_tdesc_i386 (); > + initialize_tdesc_i386_avx (); > > /* Tell remote stub that we support XML target description. */ > register_remote_support_xml ("i386"); > diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h > index 72c634e..6520d67 100644 > --- a/gdb/i386-tdep.h > +++ b/gdb/i386-tdep.h > @@ -109,6 +109,9 @@ struct gdbarch_tdep > struct regset *fpregset; > size_t sizeof_fpregset; > > + /* XSAVE extended state. */ > + struct regset *xstateregset; > + > /* Register number for %st(0). The register numbers for the other > registers follow from this one. Set this to -1 to indicate the > absence of an FPU. */ > @@ -121,6 +124,13 @@ struct gdbarch_tdep > of MMX support. */ > int mm0_regnum; > > + /* Number of pseudo YMM registers. */ > + int num_ymm_regs; > + > + /* Register number for %ymm0. Set this to -1 to indicate the absence > + of pseudo YMM register support. */ > + int ymm0_regnum; > + > /* Number of byte registers. */ > int num_byte_regs; > > @@ -146,9 +156,24 @@ struct gdbarch_tdep > /* Number of SSE registers. */ > int num_xmm_regs; > > + /* Bits of the extended control register 0 (the XFEATURE_ENABLED_MASK > + register), excluding the x87 bit, which are supported by this GDB. > + */ > + uint64_t xcr0; > + > + /* Offset of XCR0 in XSAVE extended state. */ > + int xsave_xcr0_offset; > + > /* Register names. */ > const char **register_names; > > + /* Register number for %ymm0h. Set this to -1 to indicate the absence > + of upper YMM register support. */ > + int ymm0h_regnum; > + > + /* Upper YMM register names. Only used for tdesc_numbered_register. */ > + const char **ymmh_register_names; > + > /* Target description. */ > const struct target_desc *tdesc; > > @@ -182,6 +207,7 @@ struct gdbarch_tdep > > /* ISA-specific data types. */ > struct type *i386_mmx_type; > + struct type *i386_ymm_type; > struct type *i387_ext_type; > > /* Process record/replay target. */ > @@ -228,7 +254,9 @@ enum i386_regnum > I386_FS_REGNUM, /* %fs */ > I386_GS_REGNUM, /* %gs */ > I386_ST0_REGNUM, /* %st(0) */ > - I386_MXCSR_REGNUM = 40 /* %mxcsr */ > + I386_MXCSR_REGNUM = 40, /* %mxcsr */ > + I386_YMM0H_REGNUM, /* %ymm0h */ > + I386_YMM7H_REGNUM = I386_YMM0H_REGNUM + 7 > }; > > /* Register numbers of RECORD_REGMAP. */ > @@ -265,6 +293,7 @@ enum record_i386_regnum > #define I386_NUM_XREGS 9 > > #define I386_SSE_NUM_REGS (I386_MXCSR_REGNUM + 1) > +#define I386_AVX_NUM_REGS (I386_YMM7H_REGNUM + 1) > > /* Size of the largest register. */ > #define I386_MAX_REGISTER_SIZE 16 > @@ -276,6 +305,9 @@ extern struct type *i387_ext_type (struct gdbarch *gdbarch); > extern int i386_byte_regnum_p (struct gdbarch *gdbarch, int regnum); > extern int i386_word_regnum_p (struct gdbarch *gdbarch, int regnum); > extern int i386_dword_regnum_p (struct gdbarch *gdbarch, int regnum); > +extern int i386_xmm_regnum_p (struct gdbarch *gdbarch, int regnum); > +extern int i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum); > +extern int i386_ymmh_regnum_p (struct gdbarch *gdbarch, int regnum); > > extern const char *i386_pseudo_register_name (struct gdbarch *gdbarch, > int regnum); >