Re: PATCH: 5/6: Add AVX support (i387 changes)

Hui Zhu
2010-03-05T03:20:15Z

-#define I387_XMM0_REGNUM(tdep) (I387_ST0_REGNUM (tdep) + 16)
+#define I387_VECTOR0_REGNUM(tdep) (I387_ST0_REGNUM (tdep) + 16)

We need this name change?

Thanks,
Hui

On Fri, Mar 5, 2010 at 02:09, H.J. Lu <hongjiu.lu@intel.com> wrote:
> Hi,
>
> Here are i387 changes to support AVX.  OK to install?
>
> Thanks.
>
>
> H.J.
> ---
> 2010-03-03  H.J. Lu  <hongjiu.lu@intel.com>
>
>        * i387-tdep.c: Include "i386-xstate.h".
>        (i387_supply_fsave): Replace I387_XMM0_REGNUM with
>        I387_VECTOR0_REGNUM.
>        (i387_collect_fsave): Likewise.
>        (i387_supply_fxsave): Replace I387_XMM0_REGNUM with
>        I387_VECTOR0_REGNUM.  Replace num_xmm_regs with num_vector_regs.
>        Check tdep->xcr0 for AVX.
>        (i387_collect_fxsave): Likewise.
>        (xsave_sse_offset): New.
>        (XSAVE_XSTATE_BV_ADDR): Likewise.
>        (XSAVE_SSE_ADDR): Likewise.
>        (xsave_avxh_offset): Likewise.
>        (XSAVE_AVXH_ADDR): Likewise.
>        (i387_supply_xsave): Likewise.
>        (i387_collect_xsave): Likewise.
>
>        * i387-tdep.h (I387_NUM_XMM_REGS): Renamed to ...
>        (I387_NUM_VECTOR_REGS): This.
>        (I387_XMM0_REGNUM): Renamed to ...
>        (I387_VECTOR0_REGNUM): This.
>        (I387_MXCSR_REGNUM): Updated.
>        (i387_supply_xsave): New.
>        (i387_collect_xsave): Likewise.
>
> diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
> index 3fb5b56..1f4547d 100644
> --- a/gdb/i387-tdep.c
> +++ b/gdb/i387-tdep.c
> @@ -34,6 +34,7 @@
>
>  #include "i386-tdep.h"
>  #include "i387-tdep.h"
> +#include "i386-xstate.h"
>
>  /* Print the floating point number specified by RAW.  */
>
> @@ -398,7 +399,7 @@ i387_supply_fsave (struct regcache *regcache, int regnum, const void *fsave)
>
>   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
>
> -  for (i = I387_ST0_REGNUM (tdep); i < I387_XMM0_REGNUM (tdep); i++)
> +  for (i = I387_ST0_REGNUM (tdep); i < I387_VECTOR0_REGNUM (tdep); i++)
>     if (regnum == -1 || regnum == i)
>       {
>        if (fsave == NULL)
> @@ -425,7 +426,7 @@ i387_supply_fsave (struct regcache *regcache, int regnum, const void *fsave)
>       }
>
>   /* Provide dummy values for the SSE registers.  */
> -  for (i = I387_XMM0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
> +  for (i = I387_VECTOR0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
>     if (regnum == -1 || regnum == i)
>       regcache_raw_supply (regcache, i, NULL);
>   if (regnum == -1 || regnum == I387_MXCSR_REGNUM (tdep))
> @@ -451,7 +452,7 @@ i387_collect_fsave (const struct regcache *regcache, int regnum, void *fsave)
>
>   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
>
> -  for (i = I387_ST0_REGNUM (tdep); i < I387_XMM0_REGNUM (tdep); i++)
> +  for (i = I387_ST0_REGNUM (tdep); i < I387_VECTOR0_REGNUM (tdep); i++)
>     if (regnum == -1 || regnum == i)
>       {
>        /* Most of the FPU control registers occupy only 16 bits in
> @@ -541,9 +542,11 @@ i387_supply_fxsave (struct regcache *regcache, int regnum, const void *fxsave)
>   struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
>   const gdb_byte *regs = fxsave;
>   int i;
> +  gdb_byte raw[I386_MAX_REGISTER_SIZE];
> +  const gdb_byte *xmm;
>
>   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
> -  gdb_assert (tdep->num_xmm_regs > 0);
> +  gdb_assert (tdep->num_vector_regs > 0);
>
>   for (i = I387_ST0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
>     if (regnum == -1 || regnum == i)
> @@ -556,7 +559,7 @@ i387_supply_fxsave (struct regcache *regcache, int regnum, const void *fxsave)
>
>        /* Most of the FPU control registers occupy only 16 bits in
>           the fxsave area.  Give those a special treatment.  */
> -       if (i >= I387_FCTRL_REGNUM (tdep) && i < I387_XMM0_REGNUM (tdep)
> +       if (i >= I387_FCTRL_REGNUM (tdep) && i < I387_VECTOR0_REGNUM (tdep)
>            && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
>          {
>            gdb_byte val[4];
> @@ -600,7 +603,17 @@ i387_supply_fxsave (struct regcache *regcache, int regnum, const void *fxsave)
>            regcache_raw_supply (regcache, i, val);
>          }
>        else
> -         regcache_raw_supply (regcache, i, FXSAVE_ADDR (tdep, regs, i));
> +         {
> +           if ((tdep->xcr0 & I386_XSTATE_AVX_MASK)
> +               == I386_XSTATE_AVX_MASK)
> +             {
> +               memcpy (raw, FXSAVE_ADDR (tdep, regs, i), 16);
> +               xmm = raw;
> +             }
> +           else
> +             xmm = FXSAVE_ADDR (tdep, regs, i);
> +           regcache_raw_supply (regcache, i, xmm);
> +         }
>       }
>
>   if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
> @@ -624,16 +637,18 @@ i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave)
>   struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
>   gdb_byte *regs = fxsave;
>   int i;
> +  gdb_byte raw[I386_MAX_REGISTER_SIZE];
> +  gdb_byte *xmm;
>
>   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
> -  gdb_assert (tdep->num_xmm_regs > 0);
> +  gdb_assert (tdep->num_vector_regs > 0);
>
>   for (i = I387_ST0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
>     if (regnum == -1 || regnum == i)
>       {
>        /* Most of the FPU control registers occupy only 16 bits in
>            the fxsave area.  Give those a special treatment.  */
> -       if (i >= I387_FCTRL_REGNUM (tdep) && i < I387_XMM0_REGNUM (tdep)
> +       if (i >= I387_FCTRL_REGNUM (tdep) && i < I387_VECTOR0_REGNUM (tdep)
>            && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
>          {
>            gdb_byte buf[4];
> @@ -669,7 +684,465 @@ i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave)
>            memcpy (FXSAVE_ADDR (tdep, regs, i), buf, 2);
>          }
>        else
> +         {
> +           if ((tdep->xcr0 & I386_XSTATE_AVX_MASK)
> +               == I386_XSTATE_AVX_MASK)
> +             {
> +               memcpy (raw, FXSAVE_ADDR (tdep, regs, i), 16);
> +               xmm = raw;
> +             }
> +           else
> +             xmm = FXSAVE_ADDR (tdep, regs, i);
> +           regcache_raw_collect (regcache, i, xmm);
> +         }
> +      }
> +
> +  if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
> +    regcache_raw_collect (regcache, I387_MXCSR_REGNUM (tdep),
> +                         FXSAVE_MXCSR_ADDR (regs));
> +}
> +
> +/* At xsave_sse_offset[REGNUM] you'll find the offset to the location in
> +   the SSE register data structure used by the "xsave" instruction where
> +   GDB register REGNUM is stored.  */
> +
> +static int xsave_sse_offset[] =
> +{
> +  160 + 0 * 16,                /* %xmm0 through ...  */
> +  160 + 1 * 16,
> +  160 + 2 * 16,
> +  160 + 3 * 16,
> +  160 + 4 * 16,
> +  160 + 5 * 16,
> +  160 + 6 * 16,
> +  160 + 7 * 16,
> +  160 + 8 * 16,
> +  160 + 9 * 16,
> +  160 + 10 * 16,
> +  160 + 11 * 16,
> +  160 + 12 * 16,
> +  160 + 13 * 16,
> +  160 + 14 * 16,
> +  160 + 15 * 16,       /* ... %xmm15 (128 bits each).  */
> +};
> +
> +/* `xstate_bv' is at byte offset 512.  */
> +#define XSAVE_XSTATE_BV_ADDR(xsave) (xsave + 512)
> +
> +#define XSAVE_SSE_ADDR(tdep, xsave, regnum) \
> +  (xsave + xsave_sse_offset[regnum - I387_VECTOR0_REGNUM (tdep)])
> +
> +/* At xsave_avxh_offset[REGNUM] you'll find the offset to the location in
> +   the upper 128bit of AVX register data structure used by the "xsave"
> +   instruction where GDB register REGNUM is stored.  */
> +
> +static int xsave_avxh_offset[] =
> +{
> +  576 + 0 * 16,                /* Upper 128bit of %ymm0 through ...  */
> +  576 + 1 * 16,
> +  576 + 2 * 16,
> +  576 + 3 * 16,
> +  576 + 4 * 16,
> +  576 + 5 * 16,
> +  576 + 6 * 16,
> +  576 + 7 * 16,
> +  576 + 8 * 16,
> +  576 + 9 * 16,
> +  576 + 10 * 16,
> +  576 + 11 * 16,
> +  576 + 12 * 16,
> +  576 + 13 * 16,
> +  576 + 14 * 16,
> +  576 + 15 * 16,       /* Upper 128bit of ... %ymm15 (128 bits each).  */
> +};
> +
> +#define XSAVE_AVXH_ADDR(tdep, xsave, regnum) \
> +  (xsave + xsave_avxh_offset[regnum - I387_VECTOR0_REGNUM (tdep)])
> +
> +/* Similar to i387_supply_fxsave, but use XSAVE extended state.  */
> +
> +void
> +i387_supply_xsave (struct regcache *regcache, int regnum,
> +                  const void *xsave)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
> +  const gdb_byte *regs = xsave;
> +  int i;
> +  unsigned int clear_bv;
> +  gdb_byte raw[I386_MAX_REGISTER_SIZE];
> +  const gdb_byte *p;
> +
> +  gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
> +  gdb_assert (tdep->num_vector_regs > 0);
> +
> +  if (regs != NULL
> +      && (regnum == -1
> +         || (regnum >= I387_VECTOR0_REGNUM(tdep)
> +             && regnum < I387_MXCSR_REGNUM (tdep))
> +         || (regnum >= I387_ST0_REGNUM (tdep)
> +             && regnum < I387_FCTRL_REGNUM (tdep))))
> +    {
> +      /* Get `xstat_bv'.  */
> +      const gdb_byte *xstate_bv_p = XSAVE_XSTATE_BV_ADDR (regs);
> +
> +      /* The supported bits in `xstat_bv' are 1 byte.  Clear part in
> +        vector registers if its bit in xstat_bv is zero.  */
> +      clear_bv = (~(*xstate_bv_p)) & tdep->xcr0;
> +    }
> +  else
> +    clear_bv = 0;
> +
> +  for (i = I387_ST0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
> +    if (regnum == -1 || regnum == i)
> +      {
> +       if (regs == NULL)
> +         {
> +           regcache_raw_supply (regcache, i, NULL);
> +           continue;
> +         }
> +
> +       /* Most of the FPU control registers occupy only 16 bits in
> +          the xsave extended state.  Give those a special treatment.  */
> +       if (i >= I387_FCTRL_REGNUM (tdep)
> +           && i < I387_VECTOR0_REGNUM (tdep)
> +           && i != I387_FIOFF_REGNUM (tdep)
> +           && i != I387_FOOFF_REGNUM (tdep))
> +         {
> +           gdb_byte val[4];
> +
> +           memcpy (val, FXSAVE_ADDR (tdep, regs, i), 2);
> +           val[2] = val[3] = 0;
> +           if (i == I387_FOP_REGNUM (tdep))
> +             val[1] &= ((1 << 3) - 1);
> +           else if (i== I387_FTAG_REGNUM (tdep))
> +             {
> +               /* The fxsave area contains a simplified version of
> +                  the tag word.  We have to look at the actual 80-bit
> +                  FP data to recreate the traditional i387 tag word.  */
> +
> +               unsigned long ftag = 0;
> +               int fpreg;
> +               int top;
> +
> +               top = ((FXSAVE_ADDR (tdep, regs,
> +                                    I387_FSTAT_REGNUM (tdep)))[1] >> 3);
> +               top &= 0x7;
> +
> +               for (fpreg = 7; fpreg >= 0; fpreg--)
> +                 {
> +                   int tag;
> +
> +                   if (val[0] & (1 << fpreg))
> +                     {
> +                       int regnum = (fpreg + 8 - top) % 8
> +                                      + I387_ST0_REGNUM (tdep);
> +                       tag = i387_tag (FXSAVE_ADDR (tdep, regs, regnum));
> +                     }
> +                   else
> +                     tag = 3;          /* Empty */
> +
> +                   ftag |= tag << (2 * fpreg);
> +                 }
> +               val[0] = ftag & 0xff;
> +               val[1] = (ftag >> 8) & 0xff;
> +             }
> +           regcache_raw_supply (regcache, i, val);
> +         }
> +       else if (i < I387_VECTOR0_REGNUM (tdep))
> +         {
> +           if (i < I387_FCTRL_REGNUM (tdep)
> +               && (clear_bv & bit_I386_XSTATE_X87))
> +             p = NULL;
> +           else
> +             p = FXSAVE_ADDR (tdep, regs, i);
> +           regcache_raw_supply (regcache, i, p);
> +         }
> +       else
> +         {
> +           if ((tdep->xcr0 & I386_XSTATE_AVX_MASK)
> +               == I386_XSTATE_AVX_MASK)
> +             {
> +               if ((clear_bv & (bit_I386_XSTATE_SSE | bit_I386_XSTATE_AVX))
> +                   == (bit_I386_XSTATE_SSE | bit_I386_XSTATE_AVX))
> +                 p = NULL;
> +               else
> +                 {
> +                   p = raw;
> +                   if ((clear_bv & bit_I386_XSTATE_SSE))
> +                     memset (raw, 0, 16);
> +                   else
> +                     memcpy (raw, XSAVE_SSE_ADDR (tdep, regs, i), 16);
> +                   if ((clear_bv & bit_I386_XSTATE_AVX))
> +                     memset (raw + 16, 0, 16);
> +                   else
> +                     memcpy (raw + 16, XSAVE_AVXH_ADDR (tdep, regs, i),
> +                             16);
> +                 }
> +             }
> +           else
> +             {
> +               if ((clear_bv & bit_I386_XSTATE_SSE))
> +                 p = NULL;
> +               else
> +                 p = XSAVE_SSE_ADDR (tdep, regs, i);
> +             }
> +           regcache_raw_supply (regcache, i, p);
> +         }
> +      }
> +
> +  if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
> +    {
> +      if (regs == NULL)
> +       regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep), NULL);
> +      else
> +       regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep),
> +                            FXSAVE_MXCSR_ADDR (regs));
> +    }
> +}
> +
> +/* Similar to i387_collect_fxsave, but use XSAVE extended state.  */
> +
> +void
> +i387_collect_xsave (const struct regcache *regcache, int regnum,
> +                   void *xsave, int gcore)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
> +  gdb_byte *regs = xsave;
> +  int i;
> +  gdb_byte raw[I386_MAX_REGISTER_SIZE];
> +
> +  gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
> +  gdb_assert (tdep->num_vector_regs > 0);
> +
> +  if (gcore)
> +    {
> +      /* Update XCR0 and `xstate_bv' with XCR0 for gcore.  */
> +      if (tdep->xsave_xcr0_offset != -1)
> +       memcpy (regs + tdep->xsave_xcr0_offset, &tdep->xcr0, 8);
> +      memcpy (XSAVE_XSTATE_BV_ADDR (regs), &tdep->xcr0, 8);
> +    }
> +  else
> +    {
> +      enum
> +       {
> +         none = 0x0,
> +         check = 0x1,
> +         x87 = 0x2 | check,
> +         vector = 0x4 | check,
> +         all = 0x8 | check
> +       } regclass;
> +
> +      if (regnum == -1)
> +       regclass = all;
> +      else if (regnum >= I387_VECTOR0_REGNUM(tdep)
> +              && regnum < I387_MXCSR_REGNUM (tdep))
> +       regclass = vector;
> +      else if (regnum >= I387_ST0_REGNUM (tdep)
> +              && regnum < I387_FCTRL_REGNUM (tdep))
> +       regclass = x87;
> +      else
> +       regclass = none;
> +
> +      if ((regclass & check))
> +       {
> +         gdb_byte *xstate_bv_p = XSAVE_XSTATE_BV_ADDR (regs);
> +         int num_vector_regs;
> +         unsigned int xstate_bv = 0;
> +         /* The supported bits in `xstat_bv' are 1 byte. */
> +         unsigned int clear_bv = (~(*xstate_bv_p)) & tdep->xcr0;
> +
> +         /* Clear part in vector registers if its bit in xstat_bv is
> +            zero.  */
> +         if (clear_bv)
> +           {
> +             i = I387_VECTOR0_REGNUM (tdep);
> +             num_vector_regs = I387_NUM_VECTOR_REGS(tdep);
> +             for (; num_vector_regs; num_vector_regs--, i++)
> +               {
> +                 if ((clear_bv & bit_I386_XSTATE_AVX))
> +                   memset (XSAVE_AVXH_ADDR (tdep, regs, i), 0, 16);
> +                 if ((clear_bv & bit_I386_XSTATE_SSE))
> +                   memset (XSAVE_SSE_ADDR (tdep, regs, i), 0, 16);
> +               }
> +
> +             if ((clear_bv & bit_I386_XSTATE_X87))
> +               for (i = I387_ST0_REGNUM (tdep);
> +                    i < I387_FCTRL_REGNUM (tdep); i++)
> +                 memset (FXSAVE_ADDR (tdep, regs, i), 0, 10);
> +           }
> +
> +         if (regclass == all)
> +           {
> +             i = I387_VECTOR0_REGNUM (tdep);
> +             num_vector_regs = I387_NUM_VECTOR_REGS(tdep);
> +
> +             if ((tdep->xcr0 & I386_XSTATE_AVX_MASK)
> +                 == I386_XSTATE_AVX_MASK)
> +               {
> +                 /* Check if any AVX registers are changed.  */
> +                 for (; num_vector_regs; num_vector_regs--, i++)
> +                   {
> +                     regcache_raw_read ((struct regcache *) regcache,
> +                                        i, raw);
> +                     if (memcmp (raw + 16,
> +                                 XSAVE_AVXH_ADDR (tdep, regs, i), 16))
> +                       xstate_bv |= bit_I386_XSTATE_AVX;
> +                     if (memcmp (raw, XSAVE_SSE_ADDR (tdep, regs, i), 16))
> +                       xstate_bv |= bit_I386_XSTATE_SSE;
> +
> +                     if (xstate_bv
> +                         == (bit_I386_XSTATE_AVX | bit_I386_XSTATE_SSE))
> +                       break;
> +                   }
> +               }
> +             else
> +               {
> +                 /* Check if any SSE registers are changed.  */
> +                 for (; num_vector_regs; num_vector_regs--, i++)
> +                   {
> +                     regcache_raw_read ((struct regcache *) regcache,
> +                                        i, raw);
> +                     if (memcmp (raw, XSAVE_SSE_ADDR (tdep, regs, i), 16))
> +                       {
> +                         xstate_bv |= bit_I386_XSTATE_SSE;
> +                         break;
> +                       }
> +                   }
> +               }
> +
> +             /* Check if any X87 registers are changed.  */
> +             for (i = I387_ST0_REGNUM (tdep);
> +                  i < I387_FCTRL_REGNUM (tdep); i++)
> +               {
> +                 regcache_raw_read ((struct regcache *) regcache, i, raw);
> +                 if (memcmp (raw, FXSAVE_ADDR (tdep, regs, i), 10))
> +                   {
> +                     xstate_bv |= bit_I386_XSTATE_X87;
> +                     break;
> +                   }
> +               }
> +           }
> +         else
> +           {
> +             /* Check if REGNUM is changed.  */
> +             regcache_raw_read ((struct regcache *) regcache, regnum, raw);
> +
> +             if (regclass == x87)
> +               {
> +                 /* This is an x87 register.  */
> +                 if (memcmp (raw, FXSAVE_ADDR (tdep, regs, regnum), 10))
> +                   xstate_bv |= bit_I386_XSTATE_X87;
> +               }
> +             else
> +               {
> +                 /* This is an SSE/AVX register.  */
> +                 if ((tdep->xcr0 & I386_XSTATE_AVX_MASK)
> +                     == I386_XSTATE_AVX_MASK)
> +                   {
> +                     if (memcmp (raw + 16,
> +                                 XSAVE_AVXH_ADDR (tdep, regs, regnum), 16))
> +                       xstate_bv |= bit_I386_XSTATE_AVX;
> +                   }
> +
> +                 if (memcmp (raw, XSAVE_SSE_ADDR (tdep, regs, regnum), 16))
> +                   xstate_bv |= bit_I386_XSTATE_SSE;
> +               }
> +           }
> +
> +         /* Update the corresponding bits in `xstate_bv' if any SSE/AVX
> +            registers are changed.  */
> +         if (xstate_bv)
> +           {
> +             /* The supported bits in `xstat_bv' are 1 byte.  */
> +             *xstate_bv_p |= (gdb_byte) xstate_bv;
> +
> +             /* Update REGNUM and return.  */
> +             if (regclass != all)
> +               {
> +                 if (regclass == x87)
> +                   {
> +                     /* x87 register.  */
> +                     memcpy (FXSAVE_ADDR (tdep, regs, regnum), raw, 10);
> +                   }
> +                 else
> +                   {
> +                     /* SSE/AVX register.  */
> +                     if ((xstate_bv & bit_I386_XSTATE_AVX))
> +                       memcpy (XSAVE_AVXH_ADDR (tdep, regs, regnum),
> +                               raw + 16, 16);
> +                     if ((xstate_bv & bit_I386_XSTATE_SSE))
> +                       memcpy (XSAVE_SSE_ADDR (tdep, regs, regnum), raw, 16);
> +                   }
> +                 return;
> +               }
> +           }
> +         else
> +           {
> +             /* Return if REGNUM isn't changed.  */
> +             if (regclass != all)
> +               return;
> +           }
> +       }
> +    }
> +
> +  for (i = I387_ST0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
> +    if (regnum == -1 || regnum == i)
> +      {
> +       /* Most of the FPU control registers occupy only 16 bits in
> +          the xsave extended state.  Give those a special treatment.  */
> +       if (i >= I387_FCTRL_REGNUM (tdep)
> +           && i < I387_VECTOR0_REGNUM (tdep)
> +           && i != I387_FIOFF_REGNUM (tdep)
> +           && i != I387_FOOFF_REGNUM (tdep))
> +         {
> +           gdb_byte buf[4];
> +
> +           regcache_raw_collect (regcache, i, buf);
> +
> +           if (i == I387_FOP_REGNUM (tdep))
> +             {
> +               /* The opcode occupies only 11 bits.  Make sure we
> +                   don't touch the other bits.  */
> +               buf[1] &= ((1 << 3) - 1);
> +               buf[1] |= ((FXSAVE_ADDR (tdep, regs, i))[1] & ~((1 << 3) - 1));
> +             }
> +           else if (i == I387_FTAG_REGNUM (tdep))
> +             {
> +               /* Converting back is much easier.  */
> +
> +               unsigned short ftag;
> +               int fpreg;
> +
> +               ftag = (buf[1] << 8) | buf[0];
> +               buf[0] = 0;
> +               buf[1] = 0;
> +
> +               for (fpreg = 7; fpreg >= 0; fpreg--)
> +                 {
> +                   int tag = (ftag >> (fpreg * 2)) & 3;
> +
> +                   if (tag != 3)
> +                     buf[0] |= (1 << fpreg);
> +                 }
> +             }
> +           memcpy (FXSAVE_ADDR (tdep, regs, i), buf, 2);
> +         }
> +       else if (i < I387_VECTOR0_REGNUM (tdep))
>          regcache_raw_collect (regcache, i, FXSAVE_ADDR (tdep, regs, i));
> +       else
> +         {
> +           if ((tdep->xcr0 & I386_XSTATE_AVX_MASK)
> +               == I386_XSTATE_AVX_MASK)
> +             {
> +               regcache_raw_collect (regcache, i, raw);
> +               memcpy (XSAVE_SSE_ADDR (tdep, regs, i), raw, 16);
> +               memcpy (XSAVE_AVXH_ADDR (tdep, regs, i),
> +                       raw + 16, 16);
> +             }
> +           else
> +             regcache_raw_collect (regcache, i,
> +                                   XSAVE_SSE_ADDR (tdep, regs, i));
> +         }
>       }
>
>   if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
> diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
> index 645eb91..f867a1f 100644
> --- a/gdb/i387-tdep.h
> +++ b/gdb/i387-tdep.h
> @@ -31,7 +31,7 @@ struct ui_file;
>  #define I387_NUM_REGS  16
>
>  #define I387_ST0_REGNUM(tdep) ((tdep)->st0_regnum)
> -#define I387_NUM_XMM_REGS(tdep) ((tdep)->num_xmm_regs)
> +#define I387_NUM_VECTOR_REGS(tdep) ((tdep)->num_vector_regs)
>  #define I387_MM0_REGNUM(tdep) ((tdep)->mm0_regnum)
>
>  #define I387_FCTRL_REGNUM(tdep) (I387_ST0_REGNUM (tdep) + 8)
> @@ -42,9 +42,9 @@ struct ui_file;
>  #define I387_FOSEG_REGNUM(tdep) (I387_FCTRL_REGNUM (tdep) + 5)
>  #define I387_FOOFF_REGNUM(tdep) (I387_FCTRL_REGNUM (tdep) + 6)
>  #define I387_FOP_REGNUM(tdep) (I387_FCTRL_REGNUM (tdep) + 7)
> -#define I387_XMM0_REGNUM(tdep) (I387_ST0_REGNUM (tdep) + 16)
> +#define I387_VECTOR0_REGNUM(tdep) (I387_ST0_REGNUM (tdep) + 16)
>  #define I387_MXCSR_REGNUM(tdep) \
> -  (I387_XMM0_REGNUM (tdep) + I387_NUM_XMM_REGS (tdep))
> +  (I387_VECTOR0_REGNUM (tdep) + I387_NUM_VECTOR_REGS (tdep))
>
>  /* Print out the i387 floating point state.  */
>
> @@ -99,6 +99,11 @@ extern void i387_collect_fsave (const struct regcache *regcache, int regnum,
>  extern void i387_supply_fxsave (struct regcache *regcache, int regnum,
>                                const void *fxsave);
>
> +/* Similar to i387_supply_fxsave, but use XSAVE extended state.  */
> +
> +extern void i387_supply_xsave (struct regcache *regcache, int regnum,
> +                              const void *xsave);
> +
>  /* Fill register REGNUM (if it is a floating-point or SSE register) in
>    *FXSAVE with the value from REGCACHE.  If REGNUM is -1, do this for
>    all registers.  This function doesn't touch any of the reserved
> @@ -107,6 +112,11 @@ extern void i387_supply_fxsave (struct regcache *regcache, int regnum,
>  extern void i387_collect_fxsave (const struct regcache *regcache, int regnum,
>                                 void *fxsave);
>
> +/* Similar to i387_collect_fxsave, but use XSAVE extended state.  */
> +
> +extern void i387_collect_xsave (const struct regcache *regcache,
> +                               int regnum, void *xsave, int gcore);
> +
>  /* Prepare the FPU stack in REGCACHE for a function return.  */
>
>  extern void i387_return_value (struct gdbarch *gdbarch,
>