diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 1fea26409ae..d555465c2f9 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -3372,13 +3372,23 @@ amd64_supply_xsave (struct regcache *regcache, int regnum,
       && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       const gdb_byte *regs = (const gdb_byte *) xsave;
+      static const gdb_byte zero[I386_MAX_REGISTER_SIZE] = { 0 };
+      ULONGEST clear_bv;
 
-      if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
-	regcache_raw_supply (regcache, I387_FISEG_REGNUM (tdep),
-			     regs + 12);
-      if (regnum == -1 || regnum == I387_FOSEG_REGNUM (tdep))
-	regcache_raw_supply (regcache, I387_FOSEG_REGNUM (tdep),
-			     regs + 20);
+      clear_bv = i387_xsave_get_clear_bv (gdbarch, xsave);
+
+      /* If the FISEG and FOSEG registers have not been initialised yet
+	 (their CLEAR_BV bit is set) then their default values of zero will
+	 have already been setup by I387_SUPPLY_XSAVE.  */
+      if (!(clear_bv & X86_XSTATE_X87))
+	{
+	  if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
+	    regcache_raw_supply (regcache, I387_FISEG_REGNUM (tdep),
+				 regs + 12);
+	  if (regnum == -1 || regnum == I387_FOSEG_REGNUM (tdep))
+	    regcache_raw_supply (regcache, I387_FOSEG_REGNUM (tdep),
+				 regs + 20);
+	}
     }
 }
 
diff --git a/gdb/gdbserver/i387-fp.c b/gdb/gdbserver/i387-fp.c
index f1f7d844537..ba3ccac5a16 100644
--- a/gdb/gdbserver/i387-fp.c
+++ b/gdb/gdbserver/i387-fp.c
@@ -294,17 +294,31 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
   if (clear_bv)
     {
       if ((clear_bv & X86_XSTATE_X87))
-	for (i = 0; i < 8; i++)
-	  memset (((char *) &fp->st_space[0]) + i * 16, 0, 10);
+	{
+	  for (i = 0; i < 8; i++)
+	    memset (((char *) &fp->st_space[0]) + i * 16, 0, 10);
+
+	  fp->fioff = 0;
+	  fp->fooff = 0;
+	  fp->fctrl = 0x37f;
+	  fp->fstat = 0;
+	  fp->ftag = 0;
+	  fp->fiseg = 0;
+	  fp->foseg = 0;
+	  fp->fop = 0;
+	}
 
       if ((clear_bv & X86_XSTATE_SSE))
-	for (i = 0; i < num_xmm_registers; i++) 
+	for (i = 0; i < num_xmm_registers; i++)
 	  memset (((char *) &fp->xmm_space[0]) + i * 16, 0, 16);
 
       if ((clear_bv & X86_XSTATE_AVX))
-	for (i = 0; i < num_xmm_registers; i++) 
+	for (i = 0; i < num_xmm_registers; i++)
 	  memset (((char *) &fp->ymmh_space[0]) + i * 16, 0, 16);
 
+      if ((clear_bv & X86_XSTATE_SSE) && (clear_bv & X86_XSTATE_AVX))
+	memset (((char *) &fp->mxcsr), 0, 4);
+
       if ((clear_bv & X86_XSTATE_BNDREGS))
 	for (i = 0; i < num_mpx_bnd_registers; i++)
 	  memset (((char *) &fp->mpx_bnd_space[0]) + i * 16, 0, 16);
@@ -523,43 +537,93 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
 	}
     }
 
-  /* Update the corresponding bits in xstate_bv if any SSE/AVX
-     registers are changed.  */
-  fp->xstate_bv |= xstate_bv;
+  if ((x86_xcr0 & X86_XSTATE_SSE) || (x86_xcr0 & X86_XSTATE_AVX))
+    {
+      collect_register_by_name (regcache, "mxcsr", raw);
+      if (memcmp (raw, &fp->mxcsr, 4) != 0)
+	{
+	  if (((fp->xstate_bv | xstate_bv)
+	       & (X86_XSTATE_SSE | X86_XSTATE_AVX)) == 0)
+	    xstate_bv |= X86_XSTATE_SSE;
+	  memcpy (&fp->mxcsr, raw, 4);
+	}
+    }
 
-  collect_register_by_name (regcache, "fioff", &fp->fioff);
-  collect_register_by_name (regcache, "fooff", &fp->fooff);
-  collect_register_by_name (regcache, "mxcsr", &fp->mxcsr);
+  if (x86_xcr0 & X86_XSTATE_X87)
+    {
+      collect_register_by_name (regcache, "fioff", raw);
+      if (memcmp (raw, &fp->fioff, 4) != 0)
+	{
+	  xstate_bv |= X86_XSTATE_X87;
+	  memcpy (&fp->fioff, raw, 4);
+	}
 
-  /* This one's 11 bits... */
-  collect_register_by_name (regcache, "fop", &val2);
-  fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
+      collect_register_by_name (regcache, "fooff", raw);
+      if (memcmp (raw, &fp->fooff, 4) != 0)
+	{
+	  xstate_bv |= X86_XSTATE_X87;
+	  memcpy (&fp->fooff, raw, 4);
+	}
 
-  /* Some registers are 16-bit.  */
-  collect_register_by_name (regcache, "fctrl", &val);
-  fp->fctrl = val;
+      /* This one's 11 bits... */
+      collect_register_by_name (regcache, "fop", &val2);
+      val2 = (val2 & 0x7FF) | (fp->fop & 0xF800);
+      if (fp->fop != val2)
+	{
+	  xstate_bv |= X86_XSTATE_X87;
+	  fp->fop = val2;
+	}
 
-  collect_register_by_name (regcache, "fstat", &val);
-  fp->fstat = val;
+      /* Some registers are 16-bit.  */
+      collect_register_by_name (regcache, "fctrl", &val);
+      if (fp->fctrl != val)
+	{
+	  xstate_bv |= X86_XSTATE_X87;
+	  fp->fctrl = val;
+	}
 
-  /* Convert to the simplifed tag form stored in fxsave data.  */
-  collect_register_by_name (regcache, "ftag", &val);
-  val &= 0xFFFF;
-  val2 = 0;
-  for (i = 7; i >= 0; i--)
-    {
-      int tag = (val >> (i * 2)) & 3;
+      collect_register_by_name (regcache, "fstat", &val);
+      if (fp->fstat != val)
+	{
+	  xstate_bv |= X86_XSTATE_X87;
+	  fp->fstat = val;
+	}
 
-      if (tag != 3)
-	val2 |= (1 << i);
-    }
-  fp->ftag = val2;
+      /* Convert to the simplifed tag form stored in fxsave data.  */
+      collect_register_by_name (regcache, "ftag", &val);
+      val &= 0xFFFF;
+      val2 = 0;
+      for (i = 7; i >= 0; i--)
+	{
+	  int tag = (val >> (i * 2)) & 3;
 
-  collect_register_by_name (regcache, "fiseg", &val);
-  fp->fiseg = val;
+	  if (tag != 3)
+	    val2 |= (1 << i);
+	}
+      if (fp->ftag != val2)
+	{
+	  xstate_bv |= X86_XSTATE_X87;
+	  fp->ftag = val2;
+	}
 
-  collect_register_by_name (regcache, "foseg", &val);
-  fp->foseg = val;
+      collect_register_by_name (regcache, "fiseg", &val);
+      if (fp->fiseg != val)
+	{
+	  xstate_bv |= X86_XSTATE_X87;
+	  fp->fiseg = val;
+	}
+
+      collect_register_by_name (regcache, "foseg", &val);
+      if (fp->foseg != val)
+	{
+	  xstate_bv |= X86_XSTATE_X87;
+	  fp->foseg = val;
+	}
+    }
+
+  /* Update the corresponding bits in xstate_bv if any SSE/AVX
+     registers are changed.  */
+  fp->xstate_bv |= xstate_bv;
 }
 
 static int
@@ -844,39 +908,67 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
     }
 
-  supply_register_by_name (regcache, "fioff", &fp->fioff);
-  supply_register_by_name (regcache, "fooff", &fp->fooff);
-  supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
+  if ((clear_bv & (X86_XSTATE_SSE | X86_XSTATE_AVX)) ==
+      (X86_XSTATE_SSE | X86_XSTATE_AVX))
+    {
+      unsigned int default_mxcsr = 0x1f80;
+      supply_register_by_name (regcache, "mxcsr", &default_mxcsr);
+    }
+  else
+    supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
 
-  /* Some registers are 16-bit.  */
-  val = fp->fctrl & 0xFFFF;
-  supply_register_by_name (regcache, "fctrl", &val);
+  if ((clear_bv & X86_XSTATE_X87) != 0)
+    {
+      supply_register_by_name_zeroed (regcache, "fioff");
+      supply_register_by_name_zeroed (regcache, "fooff");
 
-  val = fp->fstat & 0xFFFF;
-  supply_register_by_name (regcache, "fstat", &val);
+      val = 0x037f;
+      supply_register_by_name (regcache, "fctrl", &val);
 
-  /* Generate the form of ftag data that GDB expects.  */
-  top = (fp->fstat >> 11) & 0x7;
-  val = 0;
-  for (i = 7; i >= 0; i--)
-    {
-      int tag;
-      if (fp->ftag & (1 << i))
-	tag = i387_ftag (fxp, (i + 8 - top) % 8);
-      else
-	tag = 3;
-      val |= tag << (2 * i);
+      supply_register_by_name_zeroed (regcache, "fstat");
+
+      val = 0xFFFF;
+      supply_register_by_name (regcache, "ftag", &val);
+
+      supply_register_by_name_zeroed (regcache, "fiseg");
+      supply_register_by_name_zeroed (regcache, "foseg");
+      supply_register_by_name_zeroed (regcache, "fop");
     }
-  supply_register_by_name (regcache, "ftag", &val);
+  else
+    {
+      supply_register_by_name (regcache, "fioff", &fp->fioff);
+      supply_register_by_name (regcache, "fooff", &fp->fooff);
 
-  val = fp->fiseg & 0xFFFF;
-  supply_register_by_name (regcache, "fiseg", &val);
+      /* Some registers are 16-bit.  */
+      val = fp->fctrl & 0xFFFF;
+      supply_register_by_name (regcache, "fctrl", &val);
 
-  val = fp->foseg & 0xFFFF;
-  supply_register_by_name (regcache, "foseg", &val);
+      val = fp->fstat & 0xFFFF;
+      supply_register_by_name (regcache, "fstat", &val);
 
-  val = (fp->fop) & 0x7FF;
-  supply_register_by_name (regcache, "fop", &val);
+      /* Generate the form of ftag data that GDB expects.  */
+      top = (fp->fstat >> 11) & 0x7;
+      val = 0;
+      for (i = 7; i >= 0; i--)
+	{
+	  int tag;
+	  if (fp->ftag & (1 << i))
+	    tag = i387_ftag (fxp, (i + 8 - top) % 8);
+	  else
+	    tag = 3;
+	  val |= tag << (2 * i);
+	}
+      supply_register_by_name (regcache, "ftag", &val);
+
+      val = fp->fiseg & 0xFFFF;
+      supply_register_by_name (regcache, "fiseg", &val);
+
+      val = fp->foseg & 0xFFFF;
+      supply_register_by_name (regcache, "foseg", &val);
+
+      val = (fp->fop) & 0x7FF;
+      supply_register_by_name (regcache, "fop", &val);
+    }
 }
 
 /* Default to SSE.  */
diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c
index cbdf766df2c..9f56944e12a 100644
--- a/gdb/gdbserver/regcache.c
+++ b/gdb/gdbserver/regcache.c
@@ -346,6 +346,17 @@ supply_register_zeroed (struct regcache *regcache, int n)
 #endif
 }
 
+#ifndef IN_PROCESS_AGENT
+
+void
+supply_register_by_name_zeroed (struct regcache *regcache,
+				const char *name)
+{
+  supply_register_zeroed (regcache, find_regno (regcache->tdesc, name));
+}
+
+#endif
+
 /* Supply the whole register set whose contents are stored in BUF, to
    REGCACHE.  If BUF is NULL, all the registers' values are recorded
    as unavailable.  */
diff --git a/gdb/gdbserver/regcache.h b/gdb/gdbserver/regcache.h
index 6ff13084b0f..2c0df648f6d 100644
--- a/gdb/gdbserver/regcache.h
+++ b/gdb/gdbserver/regcache.h
@@ -107,6 +107,9 @@ void supply_register_zeroed (struct regcache *regcache, int n);
 void supply_register_by_name (struct regcache *regcache,
 			      const char *name, const void *buf);
 
+void supply_register_by_name_zeroed (struct regcache *regcache,
+				     const char *name);
+
 void supply_regblock (struct regcache *regcache, const void *buf);
 
 void collect_register (struct regcache *regcache, int n, void *buf);
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index 19387929c59..021f8d9cb46 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -215,7 +215,7 @@ i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
   int fiseg_p;
   ULONGEST fioff;
   int fioff_p;
-  ULONGEST foseg;
+  ULONGEST foseg = 0;
   int foseg_p;
   ULONGEST fooff;
   int fooff_p;
@@ -892,6 +892,28 @@ static int xsave_pkeys_offset[] =
 #define XSAVE_PKEYS_ADDR(tdep, xsave, regnum) \
   (xsave + xsave_pkeys_offset[regnum - I387_PKRU_REGNUM (tdep)])
 
+
+/* Extract from XSAVE a bitset of the features that are available on the
+   target, but which have not yet been enabled.  */
+
+ULONGEST
+i387_xsave_get_clear_bv (struct gdbarch *gdbarch, const void *xsave)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  const gdb_byte *regs = (const gdb_byte *) xsave;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ULONGEST clear_bv, xstate_bv = 0;
+
+  /* Get `xstat_bv'.  The supported bits in `xstat_bv' are 8 bytes.  */
+  xstate_bv = extract_unsigned_integer (XSAVE_XSTATE_BV_ADDR (regs),
+					8, byte_order);
+
+  /* Clear part in vector registers if its bit in xstat_bv is zero.  */
+  clear_bv = (~(xstate_bv)) & tdep->xcr0;
+
+  return clear_bv;
+}
+
 /* Similar to i387_supply_fxsave, but use XSAVE extended state.  */
 
 void
@@ -899,6 +921,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 		   const void *xsave)
 {
   struct gdbarch *gdbarch = regcache->arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   const gdb_byte *regs = (const gdb_byte *) xsave;
   int i;
@@ -956,20 +979,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
   else
     regclass = none;
 
-  if (regclass != none)
-    {
-      /* Get `xstat_bv'.  The supported bits in `xstat_bv' are 8 bytes.  */
-      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-      ULONGEST xstate_bv = 0;
-
-      xstate_bv = extract_unsigned_integer (XSAVE_XSTATE_BV_ADDR (regs),
-					    8, byte_order);
-
-      /* Clear part in vector registers if its bit in xstat_bv is zero.  */
-      clear_bv = (~(xstate_bv)) & tdep->xcr0;
-    }
-  else
-    clear_bv = X86_XSTATE_ALL_MASK;
+  clear_bv = i387_xsave_get_clear_bv (gdbarch, xsave);
 
   /* With the delayed xsave mechanism, in between the program
      starting, and the program accessing the vector registers for the
@@ -1246,10 +1256,31 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
   for (i = I387_FCTRL_REGNUM (tdep); i < I387_XMM0_REGNUM (tdep); i++)
     if (regnum == -1 || regnum == i)
       {
+	if (clear_bv & X86_XSTATE_X87)
+	  {
+	    if (i == I387_FCTRL_REGNUM (tdep))
+	      {
+		gdb_byte buf[4];
+
+		/* Initial value for fctrl register, as defined in the X86
+		   manual, and confirmed in the (Linux) kernel source.  */
+		store_unsigned_integer (buf, 4, byte_order, 0x037f);
+		regcache_raw_supply (regcache, i, buf);
+	      }
+	    else if (i == I387_FTAG_REGNUM (tdep))
+	      {
+		gdb_byte buf[4];
+
+		store_unsigned_integer (buf, 4, byte_order, 0xffff);
+		regcache_raw_supply (regcache, i, buf);
+	      }
+	    else
+	      regcache_raw_supply (regcache, i, zero);
+	  }
 	/* Most of the FPU control registers occupy only 16 bits in
 	   the xsave extended state.  Give those a special treatment.  */
-	if (i != I387_FIOFF_REGNUM (tdep)
-	    && i != I387_FOOFF_REGNUM (tdep))
+	else if (i != I387_FIOFF_REGNUM (tdep)
+		 && i != I387_FOOFF_REGNUM (tdep))
 	  {
 	    gdb_byte val[4];
 
@@ -1257,7 +1288,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	    val[2] = val[3] = 0;
 	    if (i == I387_FOP_REGNUM (tdep))
 	      val[1] &= ((1 << 3) - 1);
-	    else if (i== I387_FTAG_REGNUM (tdep))
+	    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
@@ -1291,13 +1322,26 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	      }
 	    regcache_raw_supply (regcache, i, val);
 	  }
-	else 
+	else
 	  regcache_raw_supply (regcache, i, FXSAVE_ADDR (tdep, regs, i));
       }
 
   if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
-    regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep),
-			 FXSAVE_MXCSR_ADDR (regs));
+    {
+      /* The MXCSR register is placed into the xsave buffer if either the
+	 AVX or SSE features are enabled.  */
+      if ((clear_bv & (X86_XSTATE_AVX | X86_XSTATE_SSE))
+	  == (X86_XSTATE_AVX | X86_XSTATE_SSE))
+	{
+	  gdb_byte buf[4];
+
+	  store_unsigned_integer (buf, 4, byte_order, 0x1f80);
+	  regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep), buf);
+	}
+      else
+	regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep),
+			     FXSAVE_MXCSR_ADDR (regs));
+    }
 }
 
 /* Similar to i387_collect_fxsave, but use XSAVE extended state.  */
@@ -1307,22 +1351,24 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 		    void *xsave, int gcore)
 {
   struct gdbarch *gdbarch = regcache->arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  gdb_byte *regs = (gdb_byte *) xsave;
+  gdb_byte *p, *regs = (gdb_byte *) xsave;
+  gdb_byte raw[I386_MAX_REGISTER_SIZE];
+  ULONGEST initial_xstate_bv, clear_bv, xstate_bv = 0;
   int i;
   enum
     {
-      none = 0x0,
-      check = 0x1,
-      x87 = 0x2 | check,
-      sse = 0x4 | check,
-      avxh = 0x8 | check,
-      mpx  = 0x10 | check,
-      avx512_k = 0x20 | check,
-      avx512_zmm_h = 0x40 | check,
-      avx512_ymmh_avx512 = 0x80 | check,
-      avx512_xmm_avx512 = 0x100 | check,
-      pkeys = 0x200 | check,
+      x87_ctrl_or_mxcsr = 0x1,
+      x87 = 0x2,
+      sse = 0x4,
+      avxh = 0x8,
+      mpx  = 0x10,
+      avx512_k = 0x20,
+      avx512_zmm_h = 0x40,
+      avx512_ymmh_avx512 = 0x80,
+      avx512_xmm_avx512 = 0x100,
+      pkeys = 0x200,
       all = x87 | sse | avxh | mpx | avx512_k | avx512_zmm_h
 	    | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
     } regclass;
@@ -1359,8 +1405,12 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
   else if (regnum >= I387_ST0_REGNUM (tdep)
 	   && regnum < I387_FCTRL_REGNUM (tdep))
     regclass = x87;
+  else if ((regnum >= I387_FCTRL_REGNUM (tdep)
+	    && regnum < I387_XMM0_REGNUM (tdep))
+	   || regnum == I387_MXCSR_REGNUM (tdep))
+    regclass = x87_ctrl_or_mxcsr;
   else
-    regclass = none;
+    internal_error (__FILE__, __LINE__, _("invalid i387 regnum %d"), regnum);
 
   if (gcore)
     {
@@ -1373,361 +1423,394 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
       memcpy (XSAVE_XSTATE_BV_ADDR (regs), &tdep->xcr0, 8);
     }
 
-  if ((regclass & check))
+  /* The supported bits in `xstat_bv' are 8 bytes.  */
+  initial_xstate_bv = extract_unsigned_integer (XSAVE_XSTATE_BV_ADDR (regs),
+						8, byte_order);
+  clear_bv = (~(initial_xstate_bv)) & tdep->xcr0;
+
+  /* The XSAVE buffer was filled lazily by the kernel.  Only those
+     features that are enabled were written into the buffer, disabled
+     features left the buffer uninitialised.  In order to identify if any
+     registers have changed we will be comparing the register cache
+     version to the version in the XSAVE buffer, it is important then that
+     at this point we initialise to the default values any features in
+     XSAVE that are not yet initialised.
+
+     This could be made more efficient, we know which features (from
+     REGNUM) we will be potentially updating, and could limit ourselves to
+     only clearing that feature.  However, the extra complexity does not
+     seem justified at this point.  */
+  if (clear_bv)
     {
-      gdb_byte raw[I386_MAX_REGISTER_SIZE];
-      ULONGEST initial_xstate_bv, clear_bv, xstate_bv = 0;
-      gdb_byte *p;
-      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      if ((clear_bv & X86_XSTATE_PKRU))
+	for (i = I387_PKRU_REGNUM (tdep);
+	     i < I387_PKEYSEND_REGNUM (tdep); i++)
+	  memset (XSAVE_PKEYS_ADDR (tdep, regs, i), 0, 4);
 
-      /* The supported bits in `xstat_bv' are 8 bytes.  */
-      initial_xstate_bv = extract_unsigned_integer (XSAVE_XSTATE_BV_ADDR (regs),
-						    8, byte_order);
-      clear_bv = (~(initial_xstate_bv)) & tdep->xcr0;
+      if ((clear_bv & X86_XSTATE_BNDREGS))
+	for (i = I387_BND0R_REGNUM (tdep);
+	     i < I387_BNDCFGU_REGNUM (tdep); i++)
+	  memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 16);
 
-      /* Clear register set if its bit in xstat_bv is zero.  */
-      if (clear_bv)
-	{
-	  if ((clear_bv & X86_XSTATE_PKRU))
-	    for (i = I387_PKRU_REGNUM (tdep);
-		 i < I387_PKEYSEND_REGNUM (tdep); i++)
-	      memset (XSAVE_PKEYS_ADDR (tdep, regs, i), 0, 4);
+      if ((clear_bv & X86_XSTATE_BNDCFG))
+	for (i = I387_BNDCFGU_REGNUM (tdep);
+	     i < I387_MPXEND_REGNUM (tdep); i++)
+	  memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 8);
 
-	  if ((clear_bv & X86_XSTATE_BNDREGS))
-	    for (i = I387_BND0R_REGNUM (tdep);
-		 i < I387_BNDCFGU_REGNUM (tdep); i++)
-	      memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 16);
+      if ((clear_bv & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM)))
+	for (i = I387_ZMM0H_REGNUM (tdep);
+	     i < I387_ZMMENDH_REGNUM (tdep); i++)
+	  memset (XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i), 0, 32);
 
-	  if ((clear_bv & X86_XSTATE_BNDCFG))
-	    for (i = I387_BNDCFGU_REGNUM (tdep);
-		 i < I387_MPXEND_REGNUM (tdep); i++)
-	      memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 8);
+      if ((clear_bv & X86_XSTATE_K))
+	for (i = I387_K0_REGNUM (tdep);
+	     i < I387_KEND_REGNUM (tdep); i++)
+	  memset (XSAVE_AVX512_K_ADDR (tdep, regs, i), 0, 8);
 
-	  if ((clear_bv & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM)))
-	    for (i = I387_ZMM0H_REGNUM (tdep);
-		i < I387_ZMMENDH_REGNUM (tdep); i++)
-	      memset (XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i), 0, 32);
+      if ((clear_bv & X86_XSTATE_ZMM))
+	{
+	  for (i = I387_YMM16H_REGNUM (tdep);
+	       i < I387_YMMH_AVX512_END_REGNUM (tdep); i++)
+	    memset (XSAVE_YMM_AVX512_ADDR (tdep, regs, i), 0, 16);
+	  for (i = I387_XMM16_REGNUM (tdep);
+	       i < I387_XMM_AVX512_END_REGNUM (tdep); i++)
+	    memset (XSAVE_XMM_AVX512_ADDR (tdep, regs, i), 0, 16);
+	}
 
-	  if ((clear_bv & X86_XSTATE_K))
-	    for (i = I387_K0_REGNUM (tdep);
-		i < I387_KEND_REGNUM (tdep); i++)
-	      memset (XSAVE_AVX512_K_ADDR (tdep, regs, i), 0, 8);
+      if ((clear_bv & X86_XSTATE_AVX))
+	for (i = I387_YMM0H_REGNUM (tdep);
+	     i < I387_YMMENDH_REGNUM (tdep); i++)
+	  memset (XSAVE_AVXH_ADDR (tdep, regs, i), 0, 16);
 
-	  if ((clear_bv & X86_XSTATE_ZMM))
-	    {
-	      for (i = I387_YMM16H_REGNUM (tdep);
-		  i < I387_YMMH_AVX512_END_REGNUM (tdep); i++)
-		memset (XSAVE_YMM_AVX512_ADDR (tdep, regs, i), 0, 16);
-	      for (i = I387_XMM16_REGNUM (tdep);
-	          i < I387_XMM_AVX512_END_REGNUM (tdep); i++)
-		memset (XSAVE_XMM_AVX512_ADDR (tdep, regs, i), 0, 16);
-	    }
+      if ((clear_bv & X86_XSTATE_SSE))
+	for (i = I387_XMM0_REGNUM (tdep);
+	     i < I387_MXCSR_REGNUM (tdep); i++)
+	  memset (FXSAVE_ADDR (tdep, regs, i), 0, 16);
+
+      /* The mxcsr register is written into the xsave buffer if either AVX
+	 or SSE is enabled, so only clear it if both of those features
+	 require clearing.  */
+      if ((clear_bv & (X86_XSTATE_AVX | X86_XSTATE_SSE))
+	  == (X86_XSTATE_AVX | X86_XSTATE_SSE))
+	{
+	  gdb_byte buf[2];
 
-	  if ((clear_bv & X86_XSTATE_AVX))
-	    for (i = I387_YMM0H_REGNUM (tdep);
-		 i < I387_YMMENDH_REGNUM (tdep); i++)
-	      memset (XSAVE_AVXH_ADDR (tdep, regs, i), 0, 16);
+	  store_unsigned_integer (buf, 2, byte_order, 0x1f80);
+	  memcpy (FXSAVE_ADDR (tdep, regs, i), buf, 2);
+	}
 
-	  if ((clear_bv & X86_XSTATE_SSE))
-	    for (i = I387_XMM0_REGNUM (tdep);
-		 i < I387_MXCSR_REGNUM (tdep); i++)
-	      memset (FXSAVE_ADDR (tdep, regs, i), 0, 16);
+      if ((clear_bv & X86_XSTATE_X87))
+	{
+	  for (i = I387_ST0_REGNUM (tdep);
+	       i < I387_FCTRL_REGNUM (tdep); i++)
+	    memset (FXSAVE_ADDR (tdep, regs, i), 0, 10);
 
-	  if ((clear_bv & X86_XSTATE_X87))
-	    for (i = I387_ST0_REGNUM (tdep);
-		 i < I387_FCTRL_REGNUM (tdep); i++)
-	      memset (FXSAVE_ADDR (tdep, regs, i), 0, 10);
+	  for (i = I387_FCTRL_REGNUM (tdep);
+	       i < I387_XMM0_REGNUM (tdep); i++)
+	    {
+	      if (i == I387_FCTRL_REGNUM (tdep))
+		{
+		  gdb_byte buf[2];
+
+		  store_unsigned_integer (buf, 2, byte_order, 0x037f);
+		  memcpy (FXSAVE_ADDR (tdep, regs, i), buf, 2);
+		}
+	      else
+		memset (FXSAVE_ADDR (tdep, regs, i), 0,
+			regcache_register_size (regcache, i));
+	    }
 	}
+    }
 
-      if (regclass == all)
-	{
-	  /* Check if any PKEYS registers are changed.  */
-	  if ((tdep->xcr0 & X86_XSTATE_PKRU))
-	    for (i = I387_PKRU_REGNUM (tdep);
-		 i < I387_PKEYSEND_REGNUM (tdep); i++)
+  if (regclass == all)
+    {
+      /* Check if any PKEYS registers are changed.  */
+      if ((tdep->xcr0 & X86_XSTATE_PKRU))
+	for (i = I387_PKRU_REGNUM (tdep);
+	     i < I387_PKEYSEND_REGNUM (tdep); i++)
+	  {
+	    regcache_raw_collect (regcache, i, raw);
+	    p = XSAVE_PKEYS_ADDR (tdep, regs, i);
+	    if (memcmp (raw, p, 4) != 0)
 	      {
-		regcache_raw_collect (regcache, i, raw);
-		p = XSAVE_PKEYS_ADDR (tdep, regs, i);
-		if (memcmp (raw, p, 4) != 0)
-		  {
-		    xstate_bv |= X86_XSTATE_PKRU;
-		    memcpy (p, raw, 4);
-		  }
+		xstate_bv |= X86_XSTATE_PKRU;
+		memcpy (p, raw, 4);
 	      }
+	  }
 
-	  /* Check if any ZMMH registers are changed.  */
-	  if ((tdep->xcr0 & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM)))
-	    for (i = I387_ZMM0H_REGNUM (tdep);
-		 i < I387_ZMMENDH_REGNUM (tdep); i++)
+      /* Check if any ZMMH registers are changed.  */
+      if ((tdep->xcr0 & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM)))
+	for (i = I387_ZMM0H_REGNUM (tdep);
+	     i < I387_ZMMENDH_REGNUM (tdep); i++)
+	  {
+	    regcache_raw_collect (regcache, i, raw);
+	    p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i);
+	    if (memcmp (raw, p, 32) != 0)
 	      {
-		regcache_raw_collect (regcache, i, raw);
-		p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i);
-		if (memcmp (raw, p, 32) != 0)
-		  {
-		    xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM);
-		    memcpy (p, raw, 32);
-		  }
+		xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM);
+		memcpy (p, raw, 32);
 	      }
+	  }
 
-	  /* Check if any K registers are changed.  */
-	  if ((tdep->xcr0 & X86_XSTATE_K))
-	    for (i = I387_K0_REGNUM (tdep);
-		 i < I387_KEND_REGNUM (tdep); i++)
+      /* Check if any K registers are changed.  */
+      if ((tdep->xcr0 & X86_XSTATE_K))
+	for (i = I387_K0_REGNUM (tdep);
+	     i < I387_KEND_REGNUM (tdep); i++)
+	  {
+	    regcache_raw_collect (regcache, i, raw);
+	    p = XSAVE_AVX512_K_ADDR (tdep, regs, i);
+	    if (memcmp (raw, p, 8) != 0)
 	      {
-		regcache_raw_collect (regcache, i, raw);
-		p = XSAVE_AVX512_K_ADDR (tdep, regs, i);
-		if (memcmp (raw, p, 8) != 0)
-		  {
-		    xstate_bv |= X86_XSTATE_K;
-		    memcpy (p, raw, 8);
-		  }
+		xstate_bv |= X86_XSTATE_K;
+		memcpy (p, raw, 8);
 	      }
+	  }
 
-	  /* Check if any XMM or upper YMM registers are changed.  */
-	  if ((tdep->xcr0 & X86_XSTATE_ZMM))
+      /* Check if any XMM or upper YMM registers are changed.  */
+      if ((tdep->xcr0 & X86_XSTATE_ZMM))
+	{
+	  for (i = I387_YMM16H_REGNUM (tdep);
+	       i < I387_YMMH_AVX512_END_REGNUM (tdep); i++)
 	    {
-	      for (i = I387_YMM16H_REGNUM (tdep);
-		   i < I387_YMMH_AVX512_END_REGNUM (tdep); i++)
+	      regcache_raw_collect (regcache, i, raw);
+	      p = XSAVE_YMM_AVX512_ADDR (tdep, regs, i);
+	      if (memcmp (raw, p, 16) != 0)
 		{
-		  regcache_raw_collect (regcache, i, raw);
-		  p = XSAVE_YMM_AVX512_ADDR (tdep, regs, i);
-		  if (memcmp (raw, p, 16) != 0)
-		    {
-		      xstate_bv |= X86_XSTATE_ZMM;
-		      memcpy (p, raw, 16);
-		    }
+		  xstate_bv |= X86_XSTATE_ZMM;
+		  memcpy (p, raw, 16);
 		}
-	      for (i = I387_XMM16_REGNUM (tdep);
-		   i < I387_XMM_AVX512_END_REGNUM (tdep); i++)
+	    }
+	  for (i = I387_XMM16_REGNUM (tdep);
+	       i < I387_XMM_AVX512_END_REGNUM (tdep); i++)
+	    {
+	      regcache_raw_collect (regcache, i, raw);
+	      p = XSAVE_XMM_AVX512_ADDR (tdep, regs, i);
+	      if (memcmp (raw, p, 16) != 0)
 		{
-		  regcache_raw_collect (regcache, i, raw);
-		  p = XSAVE_XMM_AVX512_ADDR (tdep, regs, i);
-		  if (memcmp (raw, p, 16) != 0)
-		    {
-		      xstate_bv |= X86_XSTATE_ZMM;
-		      memcpy (p, raw, 16);
-		    }
+		  xstate_bv |= X86_XSTATE_ZMM;
+		  memcpy (p, raw, 16);
 		}
 	    }
+	}
 
-	  /* Check if any upper YMM registers are changed.  */
-	  if ((tdep->xcr0 & X86_XSTATE_AVX))
-	    for (i = I387_YMM0H_REGNUM (tdep);
-		 i < I387_YMMENDH_REGNUM (tdep); i++)
+      /* Check if any upper MPX registers are changed.  */
+      if ((tdep->xcr0 & X86_XSTATE_BNDREGS))
+	for (i = I387_BND0R_REGNUM (tdep);
+	     i < I387_BNDCFGU_REGNUM (tdep); i++)
+	  {
+	    regcache_raw_collect (regcache, i, raw);
+	    p = XSAVE_MPX_ADDR (tdep, regs, i);
+	    if (memcmp (raw, p, 16))
 	      {
-		regcache_raw_collect (regcache, i, raw);
-		p = XSAVE_AVXH_ADDR (tdep, regs, i);
-		if (memcmp (raw, p, 16))
-		  {
-		    xstate_bv |= X86_XSTATE_AVX;
-		    memcpy (p, raw, 16);
-		  }
+		xstate_bv |= X86_XSTATE_BNDREGS;
+		memcpy (p, raw, 16);
 	      }
-	  /* Check if any upper MPX registers are changed.  */
-	  if ((tdep->xcr0 & X86_XSTATE_BNDREGS))
-	    for (i = I387_BND0R_REGNUM (tdep);
-		 i < I387_BNDCFGU_REGNUM (tdep); i++)
+	  }
+
+      /* Check if any upper MPX registers are changed.  */
+      if ((tdep->xcr0 & X86_XSTATE_BNDCFG))
+	for (i = I387_BNDCFGU_REGNUM (tdep);
+	     i < I387_MPXEND_REGNUM (tdep); i++)
+	  {
+	    regcache_raw_collect (regcache, i, raw);
+	    p = XSAVE_MPX_ADDR (tdep, regs, i);
+	    if (memcmp (raw, p, 8))
 	      {
-		regcache_raw_collect (regcache, i, raw);
-		p = XSAVE_MPX_ADDR (tdep, regs, i);
-		if (memcmp (raw, p, 16))
-		  {
-		    xstate_bv |= X86_XSTATE_BNDREGS;
-		    memcpy (p, raw, 16);
-		  }
+		xstate_bv |= X86_XSTATE_BNDCFG;
+		memcpy (p, raw, 8);
 	      }
+	  }
 
-	  /* Check if any upper MPX registers are changed.  */
-	  if ((tdep->xcr0 & X86_XSTATE_BNDCFG))
-	    for (i = I387_BNDCFGU_REGNUM (tdep);
-		 i < I387_MPXEND_REGNUM (tdep); i++)
+      /* Check if any upper YMM registers are changed.  */
+      if ((tdep->xcr0 & X86_XSTATE_AVX))
+	for (i = I387_YMM0H_REGNUM (tdep);
+	     i < I387_YMMENDH_REGNUM (tdep); i++)
+	  {
+	    regcache_raw_collect (regcache, i, raw);
+	    p = XSAVE_AVXH_ADDR (tdep, regs, i);
+	    if (memcmp (raw, p, 16))
 	      {
-		regcache_raw_collect (regcache, i, raw);
-		p = XSAVE_MPX_ADDR (tdep, regs, i);
-		if (memcmp (raw, p, 8))
-		  {
-		    xstate_bv |= X86_XSTATE_BNDCFG;
-		    memcpy (p, raw, 8);
-		  }
+		xstate_bv |= X86_XSTATE_AVX;
+		memcpy (p, raw, 16);
 	      }
+	  }
 
-	  /* Check if any SSE registers are changed.  */
-	  if ((tdep->xcr0 & X86_XSTATE_SSE))
-	    for (i = I387_XMM0_REGNUM (tdep);
-		 i < I387_MXCSR_REGNUM (tdep); i++)
+      /* Check if any SSE registers are changed.  */
+      if ((tdep->xcr0 & X86_XSTATE_SSE))
+	for (i = I387_XMM0_REGNUM (tdep);
+	     i < I387_MXCSR_REGNUM (tdep); i++)
+	  {
+	    regcache_raw_collect (regcache, i, raw);
+	    p = FXSAVE_ADDR (tdep, regs, i);
+	    if (memcmp (raw, p, 16))
 	      {
-		regcache_raw_collect (regcache, i, raw);
-		p = FXSAVE_ADDR (tdep, regs, i);
-		if (memcmp (raw, p, 16))
-		  {
-		    xstate_bv |= X86_XSTATE_SSE;
-		    memcpy (p, raw, 16);
-		  }
+		xstate_bv |= X86_XSTATE_SSE;
+		memcpy (p, raw, 16);
 	      }
+	  }
 
-	  /* Check if any X87 registers are changed.  */
-	  if ((tdep->xcr0 & X86_XSTATE_X87))
-	    for (i = I387_ST0_REGNUM (tdep);
-		 i < I387_FCTRL_REGNUM (tdep); i++)
+      if ((tdep->xcr0 & X86_XSTATE_AVX) || (tdep->xcr0 & X86_XSTATE_SSE))
+	{
+	  i = I387_MXCSR_REGNUM (tdep);
+	  regcache_raw_collect (regcache, i, raw);
+	  p = FXSAVE_ADDR (tdep, regs, i);
+	  if (memcmp (raw, p, 4))
+	    {
+	      /* Now, we need to mark one of either SSE of AVX as enabled.
+		 We could pick either.  What we do is check to see if one
+		 of the features is already enabled, if it is then we leave
+		 it at that, otherwise we pick SSE.  */
+	      if ((xstate_bv & (X86_XSTATE_SSE | X86_XSTATE_AVX)) == 0)
+		xstate_bv |= X86_XSTATE_SSE;
+	      memcpy (p, raw, 4);
+	    }
+	}
+
+      /* Check if any X87 registers are changed.  Only the non-control
+	 registers are handled here, the control registers are all */
+      if ((tdep->xcr0 & X86_XSTATE_X87))
+	for (i = I387_ST0_REGNUM (tdep);
+	     i < I387_FCTRL_REGNUM (tdep); i++)
+	  {
+	    regcache_raw_collect (regcache, i, raw);
+	    p = FXSAVE_ADDR (tdep, regs, i);
+	    if (memcmp (raw, p, 10))
 	      {
-		regcache_raw_collect (regcache, i, raw);
-		p = FXSAVE_ADDR (tdep, regs, i);
-		if (memcmp (raw, p, 10))
-		  {
-		    xstate_bv |= X86_XSTATE_X87;
-		    memcpy (p, raw, 10);
-		  }
+		xstate_bv |= X86_XSTATE_X87;
+		memcpy (p, raw, 10);
 	      }
-	}
-      else
-	{
-	  /* Check if REGNUM is changed.  */
-	  regcache_raw_collect (regcache, regnum, raw);
+	  }
+    }
+  else
+    {
+      /* Check if REGNUM is changed.  */
+      regcache_raw_collect (regcache, regnum, raw);
 
-	  switch (regclass)
+      switch (regclass)
+	{
+	default:
+	  internal_error (__FILE__, __LINE__,
+			  _("invalid i387 regclass"));
+
+	case pkeys:
+	  /* This is a PKEYS register.  */
+	  p = XSAVE_PKEYS_ADDR (tdep, regs, regnum);
+	  if (memcmp (raw, p, 4) != 0)
 	    {
-	    default:
-	      internal_error (__FILE__, __LINE__,
-			      _("invalid i387 regclass"));
-
-	    case pkeys:
-	      /* This is a PKEYS register.  */
-	      p = XSAVE_PKEYS_ADDR (tdep, regs, regnum);
-	      if (memcmp (raw, p, 4) != 0)
-		{
-		  xstate_bv |= X86_XSTATE_PKRU;
-		  memcpy (p, raw, 4);
-		}
-	      break;
-
-	    case avx512_zmm_h:
-	      /* This is a ZMM register.  */
-	      p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, regnum);
-	      if (memcmp (raw, p, 32) != 0)
-		{
-		  xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM);
-		  memcpy (p, raw, 32);
-		}
-	      break;
-	    case avx512_k:
-	      /* This is a AVX512 mask register.  */
-	      p = XSAVE_AVX512_K_ADDR (tdep, regs, regnum);
-	      if (memcmp (raw, p, 8) != 0)
-		{
-		  xstate_bv |= X86_XSTATE_K;
-		  memcpy (p, raw, 8);
-		}
-	      break;
+	      xstate_bv |= X86_XSTATE_PKRU;
+	      memcpy (p, raw, 4);
+	    }
+	  break;
 
-	    case avx512_ymmh_avx512:
-	      /* This is an upper YMM16-31 register.  */
-	      p = XSAVE_YMM_AVX512_ADDR (tdep, regs, regnum);
-	      if (memcmp (raw, p, 16) != 0)
-		{
-		  xstate_bv |= X86_XSTATE_ZMM;
-		  memcpy (p, raw, 16);
-		}
-	      break;
+	case avx512_zmm_h:
+	  /* This is a ZMM register.  */
+	  p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, regnum);
+	  if (memcmp (raw, p, 32) != 0)
+	    {
+	      xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM);
+	      memcpy (p, raw, 32);
+	    }
+	  break;
+	case avx512_k:
+	  /* This is a AVX512 mask register.  */
+	  p = XSAVE_AVX512_K_ADDR (tdep, regs, regnum);
+	  if (memcmp (raw, p, 8) != 0)
+	    {
+	      xstate_bv |= X86_XSTATE_K;
+	      memcpy (p, raw, 8);
+	    }
+	  break;
 
-	    case avx512_xmm_avx512:
-	      /* This is an upper XMM16-31 register.  */
-	      p = XSAVE_XMM_AVX512_ADDR (tdep, regs, regnum);
-	      if (memcmp (raw, p, 16) != 0)
-		{
-		  xstate_bv |= X86_XSTATE_ZMM;
-		  memcpy (p, raw, 16);
-		}
-	      break;
+	case avx512_ymmh_avx512:
+	  /* This is an upper YMM16-31 register.  */
+	  p = XSAVE_YMM_AVX512_ADDR (tdep, regs, regnum);
+	  if (memcmp (raw, p, 16) != 0)
+	    {
+	      xstate_bv |= X86_XSTATE_ZMM;
+	      memcpy (p, raw, 16);
+	    }
+	  break;
 
-	    case avxh:
-	      /* This is an upper YMM register.  */
-	      p = XSAVE_AVXH_ADDR (tdep, regs, regnum);
-	      if (memcmp (raw, p, 16))
-		{
-		  xstate_bv |= X86_XSTATE_AVX;
-		  memcpy (p, raw, 16);
-		}
-	      break;
+	case avx512_xmm_avx512:
+	  /* This is an upper XMM16-31 register.  */
+	  p = XSAVE_XMM_AVX512_ADDR (tdep, regs, regnum);
+	  if (memcmp (raw, p, 16) != 0)
+	    {
+	      xstate_bv |= X86_XSTATE_ZMM;
+	      memcpy (p, raw, 16);
+	    }
+	  break;
 
-	    case mpx:
-	      if (regnum < I387_BNDCFGU_REGNUM (tdep))
-		{
-		  regcache_raw_collect (regcache, regnum, raw);
-		  p = XSAVE_MPX_ADDR (tdep, regs, regnum);
-		  if (memcmp (raw, p, 16))
-		    {
-		      xstate_bv |= X86_XSTATE_BNDREGS;
-		      memcpy (p, raw, 16);
-		    }
-		}
-	      else
-		{
-		  p = XSAVE_MPX_ADDR (tdep, regs, regnum);
-		  xstate_bv |= X86_XSTATE_BNDCFG;
-		  memcpy (p, raw, 8);
-		}
-	      break;
+	case avxh:
+	  /* This is an upper YMM register.  */
+	  p = XSAVE_AVXH_ADDR (tdep, regs, regnum);
+	  if (memcmp (raw, p, 16))
+	    {
+	      xstate_bv |= X86_XSTATE_AVX;
+	      memcpy (p, raw, 16);
+	    }
+	  break;
 
-	    case sse:
-	      /* This is an SSE register.  */
-	      p = FXSAVE_ADDR (tdep, regs, regnum);
+	case mpx:
+	  if (regnum < I387_BNDCFGU_REGNUM (tdep))
+	    {
+	      regcache_raw_collect (regcache, regnum, raw);
+	      p = XSAVE_MPX_ADDR (tdep, regs, regnum);
 	      if (memcmp (raw, p, 16))
 		{
-		  xstate_bv |= X86_XSTATE_SSE;
+		  xstate_bv |= X86_XSTATE_BNDREGS;
 		  memcpy (p, raw, 16);
 		}
-	      break;
+	    }
+	  else
+	    {
+	      p = XSAVE_MPX_ADDR (tdep, regs, regnum);
+	      xstate_bv |= X86_XSTATE_BNDCFG;
+	      memcpy (p, raw, 8);
+	    }
+	  break;
 
-	    case x87:
-	      /* This is an x87 register.  */
-	      p = FXSAVE_ADDR (tdep, regs, regnum);
-	      if (memcmp (raw, p, 10))
-		{
-		  xstate_bv |= X86_XSTATE_X87;
-		  memcpy (p, raw, 10);
-		}
-	      break;
+	case sse:
+	  /* This is an SSE register.  */
+	  p = FXSAVE_ADDR (tdep, regs, regnum);
+	  if (memcmp (raw, p, 16))
+	    {
+	      xstate_bv |= X86_XSTATE_SSE;
+	      memcpy (p, raw, 16);
 	    }
-	}
+	  break;
 
-      /* Update the corresponding bits in `xstate_bv' if any SSE/AVX
-	 registers are changed.  */
-      if (xstate_bv)
-	{
-	  /* The supported bits in `xstat_bv' are 8 bytes.  */
-	  initial_xstate_bv |= xstate_bv;
-	  store_unsigned_integer (XSAVE_XSTATE_BV_ADDR (regs),
-				  8, byte_order,
-				  initial_xstate_bv);
+	case x87:
+	  /* This is an x87 register.  */
+	  p = FXSAVE_ADDR (tdep, regs, regnum);
+	  if (memcmp (raw, p, 10))
+	    {
+	      xstate_bv |= X86_XSTATE_X87;
+	      memcpy (p, raw, 10);
+	    }
+	  break;
 
-	  switch (regclass)
+	case x87_ctrl_or_mxcsr:
+	  /* We only handle MXCSR here.  All other x87 control registers
+	     are handled separately below.  */
+	  if (regnum == I387_MXCSR_REGNUM (tdep))
 	    {
-	    default:
-	      internal_error (__FILE__, __LINE__,
-			      _("invalid i387 regclass"));
-
-	    case all:
-	      break;
-
-	    case x87:
-	    case sse:
-	    case avxh:
-	    case mpx:
-	    case avx512_k:
-	    case avx512_zmm_h:
-	    case avx512_ymmh_avx512:
-	    case avx512_xmm_avx512:
-	    case pkeys:
-	      /* Register REGNUM has been updated.  Return.  */
-	      return;
+	      p = FXSAVE_MXCSR_ADDR (regs);
+	      if (memcmp (raw, p, 2))
+		{
+		  /* We're only setting MXCSR, so check the initial state
+		     to see if either of AVX or SSE are already enabled.
+		     If they are then we'll attribute this changed MXCSR to
+		     that feature.  If neither feature is enabled, then
+		     we'll attribute this change to the SSE feature.  */
+		  xstate_bv |=
+		    (initial_xstate_bv & (X86_XSTATE_AVX | X86_XSTATE_SSE));
+		  if ((xstate_bv & (X86_XSTATE_AVX | X86_XSTATE_SSE)) == 0)
+		    xstate_bv |= X86_XSTATE_SSE;
+		  memcpy (p, raw, 2);
+		}
 	    }
 	}
-      else
-	{
-	  /* Return if REGNUM isn't changed.  */
-	  if (regclass != all)
-	    return;
-	}
     }
 
   /* Only handle x87 control registers.  */
@@ -1769,15 +1852,38 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 		      buf[0] |= (1 << fpreg);
 		  }
 	      }
-	    memcpy (FXSAVE_ADDR (tdep, regs, i), buf, 2);
+	    p = FXSAVE_ADDR (tdep, regs, i);
+	    if (memcmp (p, buf, 2))
+	      {
+		xstate_bv |= X86_XSTATE_X87;
+		memcpy (p, buf, 2);
+	      }
 	  }
 	else
-	  regcache_raw_collect (regcache, i, FXSAVE_ADDR (tdep, regs, i));
+	  {
+	    int regsize;
+
+	    regcache_raw_collect (regcache, i, raw);
+	    regsize = regcache_register_size (regcache, i);
+	    p = FXSAVE_ADDR (tdep, regs, i);
+	    if (memcmp (raw, p, regsize))
+	      {
+		xstate_bv |= X86_XSTATE_X87;
+		memcpy (p, raw, regsize);
+	      }
+	  }
       }
 
-  if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
-    regcache_raw_collect (regcache, I387_MXCSR_REGNUM (tdep),
-			  FXSAVE_MXCSR_ADDR (regs));
+  /* Update the corresponding bits in `xstate_bv' if any
+     registers are changed.  */
+  if (xstate_bv)
+    {
+      /* The supported bits in `xstat_bv' are 8 bytes.  */
+      initial_xstate_bv |= xstate_bv;
+      store_unsigned_integer (XSAVE_XSTATE_BV_ADDR (regs),
+			      8, byte_order,
+			      initial_xstate_bv);
+    }
 }
 
 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
index 86b16f37654..975be779acf 100644
--- a/gdb/i387-tdep.h
+++ b/gdb/i387-tdep.h
@@ -156,6 +156,13 @@ extern void i387_collect_fxsave (const struct regcache *regcache, int regnum,
 extern void i387_collect_xsave (const struct regcache *regcache,
 				int regnum, void *xsave, int gcore);
 
+
+/* Extract a bitset from XSAVE indicating which features are available in
+   the inferior, but not yet initialised.  */
+
+extern ULONGEST i387_xsave_get_clear_bv (struct gdbarch *gdbarch,
+					 const void *xsave);
+
 /* Prepare the FPU stack in REGCACHE for a function return.  */
 
 extern void i387_return_value (struct gdbarch *gdbarch,
diff --git a/gdb/testsuite/gdb.arch/amd64-init-x87-values.S b/gdb/testsuite/gdb.arch/amd64-init-x87-values.S
new file mode 100644
index 00000000000..86043a81148
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-init-x87-values.S
@@ -0,0 +1,31 @@
+/* Copyright 2018 Free Software Foundation, Inc.
+
+   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 <http://www.gnu.org/licenses/>.
+
+   This file is part of the gdb testsuite.
+
+   Test initial values of x87 control registers, before any x87
+   instructions have been executed in the inferior.  */
+
+        .global _start, main
+        .text
+_start:
+        nop
+
+main:
+        nop
+        fwait
+        nop
+        fld1
+        nop
diff --git a/gdb/testsuite/gdb.arch/amd64-init-x87-values.exp b/gdb/testsuite/gdb.arch/amd64-init-x87-values.exp
new file mode 100644
index 00000000000..79bbe2121e0
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-init-x87-values.exp
@@ -0,0 +1,144 @@
+# Copyright 2018 Free Software Foundation, Inc.
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite.
+
+# Test initial values of x87 control registers, before any x87
+# instructions have been executed in the inferior.
+
+if { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
+    return
+}
+
+standard_testfile .S
+
+set options [list debug \
+		 additional_flags=-static \
+		 additional_flags=-nostartfiles]
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} $options] } {
+    return -1
+}
+
+# Get things started.
+if ![runto_main] then {
+    fail "can't run to main"
+    return 0
+}
+
+# Check initial values of x87 control registers.  The MXCSR isn't part
+# of the x87 set, it belongs with SSE/AVX, however we test it here
+# too, it should have its default value in both cases.
+foreach {regname regvalue} { "fctrl" "0x37f" \
+		             "fstat" "0x0" \
+			     "ftag" "0xffff" \
+			     "fiseg" "0x0" \
+			     "fioff" "0x0" \
+			     "foseg" "0x0" \
+			     "fooff" "0x0" \
+			     "fop" "0x0" \
+			     "mxcsr" "0x1f80"} {
+    gdb_test "p/x \$${regname}" " = ${regvalue}"  "Check initial value of \$${regname}"
+}
+
+# No x87 instructions have been executed yet.  Step up to FWAIT
+# instruction.  Executing this instruction will enable the x87 unit,
+# causing the kernel to place the default values into all registers.
+# After this GDB will no longer supply the default values itself but
+# will instread read the values out of the xsave buffer.
+gdb_test "stepi" "fwait" "Step to FWAIT instruction"
+gdb_test "stepi" "nop" "Step past FWAIT instruction"
+
+# The x87 unit is now enabled, but the register values should be
+# unchanged.
+foreach {regname regvalue} { "fctrl" "0x37f" \
+		             "fstat" "0x0" \
+			     "ftag" "0xffff" \
+			     "fiseg" "0x0" \
+			     "fioff" "0x0" \
+			     "foseg" "0x0" \
+			     "fooff" "0x0" \
+			     "fop" "0x0" \
+			     "mxcsr" "0x1f80"} {
+    gdb_test "p/x \$${regname}" " = ${regvalue}"  "Check post FWAIT value of \$${regname}"
+}
+
+# Now step to an x87 instruction that modifies some state.
+gdb_test "stepi" "fld1" "Step to FLD1 instruction"
+
+# Grab the address of this instruction, it will appear in later
+# results.
+set addr [capture_command_output "p/x \$pc" "\\\$$decimal = "]
+
+# Step past the FLD1 instruction.
+gdb_test "stepi" "nop" "Step past FLD1 instruction"
+
+# Check new values of x87 control registers (and MXCSR).
+foreach {regname regvalue} [list "fctrl" "0x37f" \
+				 "fstat" "0x3800" \
+				 "ftag" "0x3fff" \
+			         "fiseg" "0x0" \
+			         "fioff" $addr \
+			         "foseg" "0x0" \
+			         "fooff" "0x0" \
+			         "fop" "0x0" \
+			         "mxcsr" "0x1f80" ] {
+    gdb_test "p/x \$${regname}" " = ${regvalue}"  "Check post FLD1 value of \$${regname}"
+}
+
+# ===========================================================
+
+clean_restart ${binfile}
+
+if ![runto_main] then {
+    fail "can't run to main"
+    return 0
+}
+
+gdb_test_no_output "set \$mxcsr=0x9f80" "Set a new value for MXCSR"
+gdb_test "stepi" "fwait" "Step forward one instruction for mxcsr test"
+gdb_test "p/x \$mxcsr" " = 0x9f80" "Check new value of MXCSR is still in place"
+
+# ===========================================================
+
+clean_restart ${binfile}
+
+if ![runto_main] then {
+    fail "can't run to main"
+    return 0
+}
+
+foreach {regname regvalue} [list "fctrl" "0x37f" \
+				 "fstat" "0x3800" \
+				 "ftag" "0x7777" \
+			         "fiseg" "0x12" \
+			         "fioff" "0x2418" \
+			         "foseg" "0x24" \
+			         "fooff" "0x36" \
+			         "fop" "0x100" ] {
+    gdb_test_no_output "set \$$regname=$regvalue" "Set a new value for $regname"
+}
+
+gdb_test "stepi" "fwait" "Step forward one instruction for x87 test"
+
+foreach {regname regvalue} [list "fctrl" "0x37f" \
+				 "fstat" "0x3800" \
+				 "ftag" "0x7777" \
+			         "fiseg" "0x12" \
+			         "fioff" "0x2418" \
+			         "foseg" "0x24" \
+			         "fooff" "0x36" \
+			         "fop" "0x100" ] {
+    gdb_test "p/x \$$regname" "= $regvalue" "Check new value of $regname"
+}
