public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: John Baldwin <jhb@FreeBSD.org>
To: gdb-patches@sourceware.org
Subject: [RFC PATCH 1/4] x86: Add an xsave_offsets structure to handle variable XSAVE layouts.
Date: Wed, 16 Mar 2022 12:46:05 -0700	[thread overview]
Message-ID: <20220316194608.89528-2-jhb@FreeBSD.org> (raw)
In-Reply-To: <20220316194608.89528-1-jhb@FreeBSD.org>

The standard layout of the XSAVE extended state area consists of three
primary regions.  The first 512 bytes (legacy region) match the layout
of the FXSAVE instruction including floating point registers, MMX
registers, and SSE registers.  The next 64 bytes (XSAVE header)
contains a header with a fixed layout.  The final region (extended
region) contains zero or more optional state components.  Examples of
these include the upper 128 bits of YMM registers for AVX.

These optional state components generally have an
architecturally-fixed size, but they are not assigned architectural
offsets in the extended region.  Instead, processors provide
additional CPUID leafs describing the size and offset of each
component in the "standard" layout for a given CPU.  (There is also a
"compat" format which uses an alternate layout, but existing OS's
currently export the "standard" layout when exporting XSAVE data via
ptrace() and core dumps.)

To date, GDB has assumed the layout used on current Intel processors
for state components in the extended region and hardcoding those
offsets in the tables in i387-tdep.c.  However, this fails on recent
AMD processors which use a different layout.  Specifically, AMD Ryzen
9 processors do not leave space for the MPX register set in between
the AVX and AVX512 register sets.

To rectify this, add an xsave_offsets structure which contains the
offset of each known optional state component.  i387_collect_xsave and
i386_supply_xsave fetch this structure from the current target as a
TARGET_OBJECT_X86_XSAVE_OFFSETS object.  All of the tables describing
the offsets of indvidual registers for XSAVE state components now hold
relative offsets rather than absolute offsets.  Some tables (those for
MPX registers and ZMMH registers) had to be split into separate tables
as they held entries that spanned multiple state components.

Current OS's do not export these offsets either via ptrace or in core
dumps, so provide an i387_set_xsave_offsets helper function to set
offsets based on known combinations of XCR0 masks and total state
sizes.  This can be used as a fallback when individual offsets are not
available.

Note that no targets yet provide support for reading
TARGET_OBJECT_X86_XSAVE_OFFSETS.  These will be added to existing
targets which support fetching XSAVE state in subsequent commits.
---
 gdb/i387-tdep.c | 592 +++++++++++++++++++++++++++++++-----------------
 gdb/i387-tdep.h |  22 ++
 gdb/target.h    |   2 +
 3 files changed, 414 insertions(+), 202 deletions(-)

diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index 2f0b6509457..3e4c6378def 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -738,89 +738,104 @@ i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave)
 
 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).  */
+  0 * 16,		/* Upper 128bit of %ymm0 through ...  */
+  1 * 16,
+  2 * 16,
+  3 * 16,
+  4 * 16,
+  5 * 16,
+  6 * 16,
+  7 * 16,
+  8 * 16,
+  9 * 16,
+  10 * 16,
+  11 * 16,
+  12 * 16,
+  13 * 16,
+  14 * 16,
+  15 * 16		/* Upper 128bit of ... %ymm15 (128 bits each).  */
 };
 
-#define XSAVE_AVXH_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_avxh_offset[regnum - I387_YMM0H_REGNUM (tdep)])
+#define XSAVE_AVXH_ADDR(tdep, xsave, offsets, regnum)		\
+  (xsave + (offsets)->avx_offset				\
+   + xsave_avxh_offset[regnum - I387_YMM0H_REGNUM (tdep)])
 
 /* At xsave_ymm_avx512_offset[REGNUM] you'll find the offset to the location in
-   the upper 128bit of ZMM register data structure used by the "xsave"
+   the second 128bits of ZMM register data structure used by the "xsave"
    instruction where GDB register REGNUM is stored.  */
 
 static int xsave_ymm_avx512_offset[] =
 {
   /* HI16_ZMM_area + 16 bytes + regnum* 64 bytes.  */
-  1664 + 16 + 0 * 64,		/* %ymm16 through...  */
-  1664 + 16 + 1 * 64,
-  1664 + 16 + 2 * 64,
-  1664 + 16 + 3 * 64,
-  1664 + 16 + 4 * 64,
-  1664 + 16 + 5 * 64,
-  1664 + 16 + 6 * 64,
-  1664 + 16 + 7 * 64,
-  1664 + 16 + 8 * 64,
-  1664 + 16 + 9 * 64,
-  1664 + 16 + 10 * 64,
-  1664 + 16 + 11 * 64,
-  1664 + 16 + 12 * 64,
-  1664 + 16 + 13 * 64,
-  1664 + 16 + 14 * 64,
-  1664 + 16 + 15 * 64		/* ...  %ymm31 (128 bits each).  */
+  16 + 0 * 64,		/* %ymm16 through...  */
+  16 + 1 * 64,
+  16 + 2 * 64,
+  16 + 3 * 64,
+  16 + 4 * 64,
+  16 + 5 * 64,
+  16 + 6 * 64,
+  16 + 7 * 64,
+  16 + 8 * 64,
+  16 + 9 * 64,
+  16 + 10 * 64,
+  16 + 11 * 64,
+  16 + 12 * 64,
+  16 + 13 * 64,
+  16 + 14 * 64,
+  16 + 15 * 64		/* ...  %ymm31 (128 bits each).  */
 };
 
-#define XSAVE_YMM_AVX512_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_ymm_avx512_offset[regnum - I387_YMM16H_REGNUM (tdep)])
+#define XSAVE_YMM_AVX512_ADDR(tdep, xsave, offsets, regnum)		\
+  (xsave + (offsets)->avx512_zmm_offset					\
+   + xsave_ymm_avx512_offset[regnum - I387_YMM16H_REGNUM (tdep)])
+
+/* At xsave_xmm_avx512_offset[REGNUM] you'll find the offset to the location in
+   the first 128bits of ZMM register data structure used by the "xsave"
+   instruction where GDB register REGNUM is stored.  */
 
 static int xsave_xmm_avx512_offset[] =
 {
-  1664 + 0 * 64,		/* %ymm16 through...  */
-  1664 + 1 * 64,
-  1664 + 2 * 64,
-  1664 + 3 * 64,
-  1664 + 4 * 64,
-  1664 + 5 * 64,
-  1664 + 6 * 64,
-  1664 + 7 * 64,
-  1664 + 8 * 64,
-  1664 + 9 * 64,
-  1664 + 10 * 64,
-  1664 + 11 * 64,
-  1664 + 12 * 64,
-  1664 + 13 * 64,
-  1664 + 14 * 64,
-  1664 + 15 * 64		/* ...  %ymm31 (128 bits each).  */
+  0 * 64,			/* %xmm16 through...  */
+  1 * 64,
+  2 * 64,
+  3 * 64,
+  4 * 64,
+  5 * 64,
+  6 * 64,
+  7 * 64,
+  8 * 64,
+  9 * 64,
+  10 * 64,
+  11 * 64,
+  12 * 64,
+  13 * 64,
+  14 * 64,
+  15 * 64			/* ...  %xmm31 (128 bits each).  */
 };
 
-#define XSAVE_XMM_AVX512_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_xmm_avx512_offset[regnum - I387_XMM16_REGNUM (tdep)])
+#define XSAVE_XMM_AVX512_ADDR(tdep, xsave, offsets, regnum)		\
+  (xsave + (offsets)->avx512_zmm_offset					\
+   + xsave_xmm_avx512_offset[regnum - I387_XMM16_REGNUM (tdep)])
 
-static int xsave_mpx_offset[] = {
-  960 + 0 * 16,			/* bnd0r...bnd3r registers.  */
-  960 + 1 * 16,
-  960 + 2 * 16,
-  960 + 3 * 16,
-  1024 + 0 * 8,			/* bndcfg ... bndstatus.  */
-  1024 + 1 * 8,
+static int xsave_bndregs_offset[] = {
+  0 * 16,			/* bnd0r...bnd3r registers.  */
+  1 * 16,
+  2 * 16,
+  3 * 16
 };
 
-#define XSAVE_MPX_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_mpx_offset[regnum - I387_BND0R_REGNUM (tdep)])
+#define XSAVE_BNDREGS_ADDR(tdep, xsave, offsets, regnum)	\
+  (xsave + (offsets)->bndregs_offset				\
+   + xsave_bndregs_offset[regnum - I387_BND0R_REGNUM (tdep)])
+
+static int xsave_bndcfg_offset[] = {
+  0 * 8,			/* bndcfg ... bndstatus.  */
+  1 * 8,
+};
+
+#define XSAVE_BNDCFG_ADDR(tdep, xsave, offsets, regnum)		\
+  (xsave + (offsets)->bndcfg_offset				\
+   + xsave_bndcfg_offset[regnum - I387_BNDCFGU_REGNUM (tdep)])
 
   /* At xsave_avx512__h_offset[REGNUM] you find the offset to the location
    of the AVX512 opmask register data structure used by the "xsave"
@@ -828,61 +843,78 @@ static int xsave_mpx_offset[] = {
 
 static int xsave_avx512_k_offset[] =
 {
-  1088 + 0 * 8,			/* %k0 through...  */
-  1088 + 1 * 8,
-  1088 + 2 * 8,
-  1088 + 3 * 8,
-  1088 + 4 * 8,
-  1088 + 5 * 8,
-  1088 + 6 * 8,
-  1088 + 7 * 8     		/* %k7 (64 bits each).  */
+  0 * 8,			/* %k0 through...  */
+  1 * 8,
+  2 * 8,
+  3 * 8,
+  4 * 8,
+  5 * 8,
+  6 * 8,
+  7 * 8				/* %k7 (64 bits each).	*/
 };
 
-#define XSAVE_AVX512_K_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_avx512_k_offset[regnum - I387_K0_REGNUM (tdep)])
+#define XSAVE_AVX512_K_ADDR(tdep, xsave, offsets, regnum)	\
+  (xsave + (offsets)->avx512_k_offset				\
+   + xsave_avx512_k_offset[regnum - I387_K0_REGNUM (tdep)])
 
-/* At xsave_avx512_zmm_h_offset[REGNUM] you find the offset to the location in
-   the upper 256bit of AVX512 ZMMH register data structure used by the "xsave"
-   instruction where GDB register REGNUM is stored.  */
 
-static int xsave_avx512_zmm_h_offset[] =
+/* At xsave_avx512_zmm0_h_offset[REGNUM] you find the offset to the
+   location in the upper 256bit of AVX512 ZMM0-15H register data
+   structure used by the "xsave" instruction where GDB register REGNUM
+   is stored.  */
+
+/* At xsave_avx512_zmm16_h_offset[REGNUM] you find the offset to the
+   location in the upper 256bit of AVX512 ZMMH register data structure
+   used by the "xsave" instruction where GDB register REGNUM is
+   stored.  */
+
+static int xsave_avx512_zmm0_h_offset[] =
+{
+  0 * 32,		/* Upper 256bit of %zmmh0 through...  */
+  1 * 32,
+  2 * 32,
+  3 * 32,
+  4 * 32,
+  5 * 32,
+  6 * 32,
+  7 * 32,
+  8 * 32,
+  9 * 32,
+  10 * 32,
+  11 * 32,
+  12 * 32,
+  13 * 32,
+  14 * 32,
+  15 * 32		/* Upper 256bit of...  %zmmh15 (256 bits each).  */
+};
+
+#define XSAVE_AVX512_ZMM0_H_ADDR(tdep, xsave, offsets, regnum)		\
+  (xsave + (offsets)->avx512_zmm_h_offset				\
+   + xsave_avx512_zmm0_h_offset[regnum - I387_ZMM0H_REGNUM (tdep)])
+
+static int xsave_avx512_zmm16_h_offset[] =
 {
-  1152 + 0 * 32,
-  1152 + 1 * 32,	/* Upper 256bit of %zmmh0 through...  */
-  1152 + 2 * 32,
-  1152 + 3 * 32,
-  1152 + 4 * 32,
-  1152 + 5 * 32,
-  1152 + 6 * 32,
-  1152 + 7 * 32,
-  1152 + 8 * 32,
-  1152 + 9 * 32,
-  1152 + 10 * 32,
-  1152 + 11 * 32,
-  1152 + 12 * 32,
-  1152 + 13 * 32,
-  1152 + 14 * 32,
-  1152 + 15 * 32,	/* Upper 256bit of...  %zmmh15 (256 bits each).  */
-  1664 + 32 + 0 * 64,   /* Upper 256bit of...  %zmmh16 (256 bits each).  */
-  1664 + 32 + 1 * 64,
-  1664 + 32 + 2 * 64,
-  1664 + 32 + 3 * 64,
-  1664 + 32 + 4 * 64,
-  1664 + 32 + 5 * 64,
-  1664 + 32 + 6 * 64,
-  1664 + 32 + 7 * 64,
-  1664 + 32 + 8 * 64,
-  1664 + 32 + 9 * 64,
-  1664 + 32 + 10 * 64,
-  1664 + 32 + 11 * 64,
-  1664 + 32 + 12 * 64,
-  1664 + 32 + 13 * 64,
-  1664 + 32 + 14 * 64,
-  1664 + 32 + 15 * 64   /* Upper 256bit of... %zmmh31 (256 bits each).  */
+  32 + 0 * 64,		/* Upper 256bit of...  %zmmh16 (256 bits each).  */
+  32 + 1 * 64,
+  32 + 2 * 64,
+  32 + 3 * 64,
+  32 + 4 * 64,
+  32 + 5 * 64,
+  32 + 6 * 64,
+  32 + 7 * 64,
+  32 + 8 * 64,
+  32 + 9 * 64,
+  32 + 10 * 64,
+  32 + 11 * 64,
+  32 + 12 * 64,
+  32 + 13 * 64,
+  32 + 14 * 64,
+  32 + 15 * 64		/* Upper 256bit of... %zmmh31 (256 bits each).  */
 };
 
-#define XSAVE_AVX512_ZMM_H_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_avx512_zmm_h_offset[regnum - I387_ZMM0H_REGNUM (tdep)])
+#define XSAVE_AVX512_ZMM16_H_ADDR(tdep, xsave, offsets, regnum)		\
+  (xsave + (offsets)->avx512_zmm_offset					\
+   + xsave_avx512_zmm16_h_offset[regnum - I387_ZMM16H_REGNUM (tdep)])
 
 /* At xsave_pkeys_offset[REGNUM] you find the offset to the location
    of the PKRU register data structure used by the "xsave"
@@ -890,14 +922,93 @@ static int xsave_avx512_zmm_h_offset[] =
 
 static int xsave_pkeys_offset[] =
 {
-2688 + 0 * 8		/* %pkru (64 bits in XSTATE, 32-bit actually used by
+  0 * 8			/* %pkru (64 bits in XSTATE, 32-bit actually used by
 			   instructions and applications).  */
 };
 
-#define XSAVE_PKEYS_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_pkeys_offset[regnum - I387_PKRU_REGNUM (tdep)])
+#define XSAVE_PKEYS_ADDR(tdep, xsave, offsets, regnum)		\
+  (xsave + (offsets)->pkru_offset				\
+   + xsave_pkeys_offset[regnum - I387_PKRU_REGNUM (tdep)])
 
 
+/* See i387-tdep.h.  */
+
+void
+i387_set_xsave_offsets (uint64_t xcr0, size_t xsave_size,
+			struct xsave_offsets *offsets)
+{
+  if (HAS_PKRU(xcr0) && xsave_size == 2696)
+    {
+      offsets->avx_offset = 576;
+      offsets->bndregs_offset = 960;
+      offsets->bndcfg_offset = 1024;
+      offsets->avx512_k_offset = 1088;
+      offsets->avx512_zmm_h_offset = 1152;
+      offsets->avx512_zmm_offset = 1664;
+      offsets->pkru_offset = 2688;
+    }
+  else if (HAS_PKRU(xcr0) && xsave_size == 2440)
+    {
+      offsets->avx_offset = 576;
+      offsets->bndregs_offset = -1;
+      offsets->bndcfg_offset = -1;
+      offsets->avx512_k_offset = 832;
+      offsets->avx512_zmm_h_offset = 896;
+      offsets->avx512_zmm_offset = 1408;
+      offsets->pkru_offset = 2432;
+    }
+  else if (HAS_AVX512(xcr0) && xsave_size == 2688)
+    {
+      offsets->avx_offset = 576;
+      offsets->bndregs_offset = 960;
+      offsets->bndcfg_offset = 1024;
+      offsets->avx512_k_offset = 1088;
+      offsets->avx512_zmm_h_offset = 1152;
+      offsets->avx512_zmm_offset = 1664;
+      offsets->pkru_offset = -1;
+    }
+  else if (HAS_MPX(xcr0) && xsave_size == 1088)
+    {
+      offsets->avx_offset = 576;
+      offsets->bndregs_offset = 960;
+      offsets->bndcfg_offset = 1024;
+      offsets->avx512_k_offset = -1;
+      offsets->avx512_zmm_h_offset = -1;
+      offsets->avx512_zmm_offset = -1;
+      offsets->pkru_offset = -1;
+    }
+  else if (HAS_AVX(xcr0) && xsave_size == 832)
+    {
+      offsets->avx_offset = 576;
+      offsets->bndregs_offset = -1;
+      offsets->bndcfg_offset = -1;
+      offsets->avx512_k_offset = -1;
+      offsets->avx512_zmm_h_offset = -1;
+      offsets->avx512_zmm_offset = -1;
+      offsets->pkru_offset = -1;
+    }
+  else
+    {
+      offsets->bndregs_offset = -1;
+      offsets->bndcfg_offset = -1;
+      offsets->avx512_k_offset = -1;
+      offsets->avx512_zmm_h_offset = -1;
+      offsets->avx512_zmm_offset = -1;
+      offsets->pkru_offset = -1;
+    }
+}
+
+/* Fetch the XSAVE offsets for the current target.  */
+
+static void
+i387_fetch_xsave_offsets (struct xsave_offsets *offsets)
+{
+  LONGEST len = target_read (current_inferior ()->top_target (),
+			     TARGET_OBJECT_X86_XSAVE_OFFSETS, nullptr,
+			     (gdb_byte *) offsets, 0, sizeof (*offsets));
+  gdb_assert (len == sizeof (*offsets));
+}
+
 /* Extract from XSAVE a bitset of the features that are available on the
    target, but which have not yet been enabled.  */
 
@@ -924,6 +1035,7 @@ void
 i387_supply_xsave (struct regcache *regcache, int regnum,
 		   const void *xsave)
 {
+  struct xsave_offsets offsets;
   struct gdbarch *gdbarch = regcache->arch ();
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
@@ -943,28 +1055,35 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
       x87 = 0x1,
       sse = 0x2,
       avxh = 0x4,
-      mpx  = 0x8,
-      avx512_k = 0x10,
-      avx512_zmm_h = 0x20,
-      avx512_ymmh_avx512 = 0x40,
-      avx512_xmm_avx512 = 0x80,
-      pkeys = 0x100,
-      all = x87 | sse | avxh | mpx | avx512_k | avx512_zmm_h
-	    | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
+      bndregs = 0x8,
+      bndcfg = 0x10,
+      avx512_k = 0x20,
+      avx512_zmm0_h = 0x40,
+      avx512_zmm16_h = 0x80,
+      avx512_ymmh_avx512 = 0x100,
+      avx512_xmm_avx512 = 0x200,
+      pkeys = 0x400,
+      all = x87 | sse | avxh | bndregs | bndcfg | avx512_k | avx512_zmm0_h
+	    | avx512_zmm16_h | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
     } regclass;
 
   gdb_assert (regs != NULL);
   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
   gdb_assert (tdep->num_xmm_regs > 0);
 
+  i387_fetch_xsave_offsets (&offsets);
+
   if (regnum == -1)
     regclass = all;
   else if (regnum >= I387_PKRU_REGNUM (tdep)
 	   && regnum < I387_PKEYSEND_REGNUM (tdep))
     regclass = pkeys;
   else if (regnum >= I387_ZMM0H_REGNUM (tdep)
+	   && regnum < I387_ZMM16H_REGNUM (tdep))
+    regclass = avx512_zmm0_h;
+  else if (regnum >= I387_ZMM16H_REGNUM (tdep)
 	   && regnum < I387_ZMMENDH_REGNUM (tdep))
-    regclass = avx512_zmm_h;
+    regclass = avx512_zmm16_h;
   else if (regnum >= I387_K0_REGNUM (tdep)
 	   && regnum < I387_KEND_REGNUM (tdep))
     regclass = avx512_k;
@@ -978,8 +1097,11 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	   && regnum < I387_YMMENDH_REGNUM (tdep))
     regclass = avxh;
   else if (regnum >= I387_BND0R_REGNUM (tdep)
+	   && regnum < I387_BNDCFGU_REGNUM (tdep))
+    regclass = bndregs;
+  else if (regnum >= I387_BNDCFGU_REGNUM (tdep)
 	   && regnum < I387_MPXEND_REGNUM (tdep))
-    regclass = mpx;
+    regclass = bndcfg;
   else if (regnum >= I387_XMM0_REGNUM (tdep)
 	   && regnum < I387_MXCSR_REGNUM (tdep))
     regclass = sse;
@@ -1009,23 +1131,34 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
       if ((clear_bv & X86_XSTATE_PKRU))
 	regcache->raw_supply (regnum, zero);
       else
-	regcache->raw_supply (regnum, XSAVE_PKEYS_ADDR (tdep, regs, regnum));
+	regcache->raw_supply (regnum, XSAVE_PKEYS_ADDR (tdep, regs, &offsets,
+							regnum));
       return;
 
-    case avx512_zmm_h:
-      if ((clear_bv & (regnum < zmm_endlo_regnum ? X86_XSTATE_ZMM_H
-						 : X86_XSTATE_ZMM)))
+    case avx512_zmm0_h:
+      if ((clear_bv & X86_XSTATE_ZMM_H))
 	regcache->raw_supply (regnum, zero);
       else
 	regcache->raw_supply (regnum,
-			      XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, regnum));
+			      XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, &offsets,
+							regnum));
+      return;
+
+    case avx512_zmm16_h:
+      if ((clear_bv & X86_XSTATE_ZMM))
+	regcache->raw_supply (regnum, zero);
+      else
+	regcache->raw_supply (regnum,
+			      XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, &offsets,
+							 regnum));
       return;
 
     case avx512_k:
       if ((clear_bv & X86_XSTATE_K))
 	regcache->raw_supply (regnum, zero);
       else
-	regcache->raw_supply (regnum, XSAVE_AVX512_K_ADDR (tdep, regs, regnum));
+	regcache->raw_supply (regnum, XSAVE_AVX512_K_ADDR (tdep, regs, &offsets,
+							   regnum));
       return;
 
     case avx512_ymmh_avx512:
@@ -1033,7 +1166,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	regcache->raw_supply (regnum, zero);
       else
 	regcache->raw_supply (regnum,
-			      XSAVE_YMM_AVX512_ADDR (tdep, regs, regnum));
+			      XSAVE_YMM_AVX512_ADDR (tdep, regs, &offsets,
+						     regnum));
       return;
 
     case avx512_xmm_avx512:
@@ -1041,21 +1175,32 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	regcache->raw_supply (regnum, zero);
       else
 	regcache->raw_supply (regnum,
-			      XSAVE_XMM_AVX512_ADDR (tdep, regs, regnum));
+			      XSAVE_XMM_AVX512_ADDR (tdep, regs, &offsets,
+						     regnum));
       return;
 
     case avxh:
       if ((clear_bv & X86_XSTATE_AVX))
 	regcache->raw_supply (regnum, zero);
       else
-	regcache->raw_supply (regnum, XSAVE_AVXH_ADDR (tdep, regs, regnum));
+	regcache->raw_supply (regnum, XSAVE_AVXH_ADDR (tdep, regs, &offsets,
+						       regnum));
       return;
 
-    case mpx:
+    case bndcfg:
+      if ((clear_bv & X86_XSTATE_BNDCFG))
+	regcache->raw_supply (regnum, zero);
+      else
+	regcache->raw_supply (regnum, XSAVE_BNDCFG_ADDR (tdep, regs, &offsets,
+							 regnum));
+      return;
+
+    case bndregs:
       if ((clear_bv & X86_XSTATE_BNDREGS))
 	regcache->raw_supply (regnum, zero);
       else
-	regcache->raw_supply (regnum, XSAVE_MPX_ADDR (tdep, regs, regnum));
+	regcache->raw_supply (regnum, XSAVE_BNDREGS_ADDR (tdep, regs, &offsets,
+							  regnum));
       return;
 
     case sse:
@@ -1088,7 +1233,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	      for (i = I387_PKRU_REGNUM (tdep);
 		   i < I387_PKEYSEND_REGNUM (tdep);
 		   i++)
-		regcache->raw_supply (i, XSAVE_PKEYS_ADDR (tdep, regs, i));
+		regcache->raw_supply (i, XSAVE_PKEYS_ADDR (tdep, regs, &offsets,
+							   i));
 	    }
 	}
 
@@ -1104,7 +1250,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	    {
 	      for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++)
 		regcache->raw_supply (i,
-				      XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i));
+				      XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs,
+								&offsets, i));
 	    }
 	}
 
@@ -1123,7 +1270,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	      for (i = I387_K0_REGNUM (tdep);
 		   i < I387_KEND_REGNUM (tdep);
 		   i++)
-		regcache->raw_supply (i, XSAVE_AVX512_K_ADDR (tdep, regs, i));
+		regcache->raw_supply (i, XSAVE_AVX512_K_ADDR (tdep, regs,
+							      &offsets, i));
 	    }
 	}
 
@@ -1132,7 +1280,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	{
 	  if ((clear_bv & X86_XSTATE_ZMM))
 	    {
-	      for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++)
+	      for (i = I387_ZMM16H_REGNUM (tdep);
+		   i < I387_ZMMENDH_REGNUM (tdep); i++)
 		regcache->raw_supply (i, zero);
 	      for (i = I387_YMM16H_REGNUM (tdep);
 		   i < I387_YMMH_AVX512_END_REGNUM (tdep);
@@ -1145,17 +1294,21 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	    }
 	  else
 	    {
-	      for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++)
+	      for (i = I387_ZMM16H_REGNUM (tdep);
+		   i < I387_ZMMENDH_REGNUM (tdep); i++)
 		regcache->raw_supply (i,
-				      XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i));
+				      XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs,
+								 &offsets, i));
 	      for (i = I387_YMM16H_REGNUM (tdep);
 		   i < I387_YMMH_AVX512_END_REGNUM (tdep);
 		   i++)
-		regcache->raw_supply (i, XSAVE_YMM_AVX512_ADDR (tdep, regs, i));
+		regcache->raw_supply (i, XSAVE_YMM_AVX512_ADDR (tdep, regs,
+								&offsets, i));
 	      for (i = I387_XMM16_REGNUM (tdep);
 		   i < I387_XMM_AVX512_END_REGNUM (tdep);
 		   i++)
-		regcache->raw_supply (i, XSAVE_XMM_AVX512_ADDR (tdep, regs, i));
+		regcache->raw_supply (i, XSAVE_XMM_AVX512_ADDR (tdep, regs,
+								&offsets, i));
 	    }
 	}
       /* Handle the upper YMM registers.  */
@@ -1173,7 +1326,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	      for (i = I387_YMM0H_REGNUM (tdep);
 		   i < I387_YMMENDH_REGNUM (tdep);
 		   i++)
-		regcache->raw_supply (i, XSAVE_AVXH_ADDR (tdep, regs, i));
+		regcache->raw_supply (i, XSAVE_AVXH_ADDR (tdep, regs,
+							  &offsets, i));
 	    }
 	}
 
@@ -1190,7 +1344,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	    {
 	      for (i = I387_BND0R_REGNUM (tdep);
 		   i < I387_BNDCFGU_REGNUM (tdep); i++)
-		regcache->raw_supply (i, XSAVE_MPX_ADDR (tdep, regs, i));
+		regcache->raw_supply (i, XSAVE_BNDREGS_ADDR (tdep, regs,
+							     &offsets, i));
 	    }
 	}
 
@@ -1207,7 +1362,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	    {
 	      for (i = I387_BNDCFGU_REGNUM (tdep);
 		   i < I387_MPXEND_REGNUM (tdep); i++)
-		regcache->raw_supply (i, XSAVE_MPX_ADDR (tdep, regs, i));
+		regcache->raw_supply (i, XSAVE_BNDCFG_ADDR (tdep, regs,
+							    &offsets, i));
 	    }
 	}
 
@@ -1347,6 +1503,7 @@ void
 i387_collect_xsave (const struct regcache *regcache, int regnum,
 		    void *xsave, int gcore)
 {
+  struct xsave_offsets offsets;
   struct gdbarch *gdbarch = regcache->arch ();
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
@@ -1363,27 +1520,34 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
       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
+      bndregs = 0x10,
+      bndcfg = 0x20,
+      avx512_k = 0x40,
+      avx512_zmm0_h = 0x80,
+      avx512_zmm16_h = 0x100,
+      avx512_ymmh_avx512 = 0x200,
+      avx512_xmm_avx512 = 0x400,
+      pkeys = 0x800,
+      all = x87 | sse | avxh | bndregs | bndcfg | avx512_k | avx512_zmm0_h
+	    | avx512_zmm16_h | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
     } regclass;
 
   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
   gdb_assert (tdep->num_xmm_regs > 0);
 
+  i387_fetch_xsave_offsets (&offsets);
+
   if (regnum == -1)
     regclass = all;
   else if (regnum >= I387_PKRU_REGNUM (tdep)
 	   && regnum < I387_PKEYSEND_REGNUM (tdep))
     regclass = pkeys;
   else if (regnum >= I387_ZMM0H_REGNUM (tdep)
+	   && regnum < I387_ZMM16H_REGNUM (tdep))
+    regclass = avx512_zmm0_h;
+  else if (regnum >= I387_ZMM16H_REGNUM (tdep)
 	   && regnum < I387_ZMMENDH_REGNUM (tdep))
-    regclass = avx512_zmm_h;
+    regclass = avx512_zmm16_h;
   else if (regnum >= I387_K0_REGNUM (tdep)
 	   && regnum < I387_KEND_REGNUM (tdep))
     regclass = avx512_k;
@@ -1397,8 +1561,11 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	   && regnum < I387_YMMENDH_REGNUM (tdep))
     regclass = avxh;
   else if (regnum >= I387_BND0R_REGNUM (tdep)
+	   && regnum < I387_BNDCFGU_REGNUM (tdep))
+    regclass = bndregs;
+  else if (regnum >= I387_BNDCFGU_REGNUM (tdep)
 	   && regnum < I387_MPXEND_REGNUM (tdep))
-    regclass = mpx;
+    regclass = bndcfg;
   else if (regnum >= I387_XMM0_REGNUM (tdep)
 	   && regnum < I387_MXCSR_REGNUM (tdep))
     regclass = sse;
@@ -1445,43 +1612,44 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
       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);
+	  memset (XSAVE_PKEYS_ADDR (tdep, regs, &offsets, i), 0, 4);
 
       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);
+	  memset (XSAVE_BNDREGS_ADDR (tdep, regs, &offsets, i), 0, 16);
 
       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);
+	  memset (XSAVE_BNDCFG_ADDR (tdep, regs, &offsets, i), 0, 8);
 
       if ((clear_bv & X86_XSTATE_ZMM_H))
 	for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++)
-	  memset (XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i), 0, 32);
+	  memset (XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, &offsets, i), 0, 32);
 
       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);
+	  memset (XSAVE_AVX512_K_ADDR (tdep, regs, &offsets, i), 0, 8);
 
       if ((clear_bv & X86_XSTATE_ZMM))
 	{
-	  for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++)
-	    memset (XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i), 0, 32);
+	  for (i = I387_ZMM16H_REGNUM (tdep); i < I387_ZMMENDH_REGNUM (tdep);
+	       i++)
+	    memset (XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, &offsets, i), 0, 32);
 	  for (i = I387_YMM16H_REGNUM (tdep);
 	       i < I387_YMMH_AVX512_END_REGNUM (tdep); i++)
-	    memset (XSAVE_YMM_AVX512_ADDR (tdep, regs, i), 0, 16);
+	    memset (XSAVE_YMM_AVX512_ADDR (tdep, regs, &offsets, 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);
+	    memset (XSAVE_XMM_AVX512_ADDR (tdep, regs, &offsets, i), 0, 16);
 	}
 
       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);
+	  memset (XSAVE_AVXH_ADDR (tdep, regs, &offsets, i), 0, 16);
 
       if ((clear_bv & X86_XSTATE_SSE))
 	for (i = I387_XMM0_REGNUM (tdep);
@@ -1523,7 +1691,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	     i < I387_PKEYSEND_REGNUM (tdep); i++)
 	  {
 	    regcache->raw_collect (i, raw);
-	    p = XSAVE_PKEYS_ADDR (tdep, regs, i);
+	    p = XSAVE_PKEYS_ADDR (tdep, regs, &offsets, i);
 	    if (memcmp (raw, p, 4) != 0)
 	      {
 		xstate_bv |= X86_XSTATE_PKRU;
@@ -1532,15 +1700,27 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	  }
 
       /* Check if any ZMMH registers are changed.  */
-      if ((tdep->xcr0 & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM)))
-	for (i = I387_ZMM0H_REGNUM (tdep);
+      if ((tdep->xcr0 & X86_XSTATE_ZMM))
+	for (i = I387_ZMM16H_REGNUM (tdep);
 	     i < I387_ZMMENDH_REGNUM (tdep); i++)
 	  {
 	    regcache->raw_collect (i, raw);
-	    p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i);
+	    p = XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, &offsets, i);
 	    if (memcmp (raw, p, 32) != 0)
 	      {
-		xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM);
+		xstate_bv |= X86_XSTATE_ZMM;
+		memcpy (p, raw, 32);
+	      }
+	  }
+
+      if ((tdep->xcr0 & X86_XSTATE_ZMM_H))
+	for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++)
+	  {
+	    regcache->raw_collect (i, raw);
+	    p = XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, &offsets, i);
+	    if (memcmp (raw, p, 32) != 0)
+	      {
+		xstate_bv |= X86_XSTATE_ZMM_H;
 		memcpy (p, raw, 32);
 	      }
 	  }
@@ -1551,7 +1731,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	     i < I387_KEND_REGNUM (tdep); i++)
 	  {
 	    regcache->raw_collect (i, raw);
-	    p = XSAVE_AVX512_K_ADDR (tdep, regs, i);
+	    p = XSAVE_AVX512_K_ADDR (tdep, regs, &offsets, i);
 	    if (memcmp (raw, p, 8) != 0)
 	      {
 		xstate_bv |= X86_XSTATE_K;
@@ -1566,7 +1746,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	       i < I387_YMMH_AVX512_END_REGNUM (tdep); i++)
 	    {
 	      regcache->raw_collect (i, raw);
-	      p = XSAVE_YMM_AVX512_ADDR (tdep, regs, i);
+	      p = XSAVE_YMM_AVX512_ADDR (tdep, regs, &offsets, i);
 	      if (memcmp (raw, p, 16) != 0)
 		{
 		  xstate_bv |= X86_XSTATE_ZMM;
@@ -1577,7 +1757,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	       i < I387_XMM_AVX512_END_REGNUM (tdep); i++)
 	    {
 	      regcache->raw_collect (i, raw);
-	      p = XSAVE_XMM_AVX512_ADDR (tdep, regs, i);
+	      p = XSAVE_XMM_AVX512_ADDR (tdep, regs, &offsets, i);
 	      if (memcmp (raw, p, 16) != 0)
 		{
 		  xstate_bv |= X86_XSTATE_ZMM;
@@ -1592,7 +1772,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	     i < I387_BNDCFGU_REGNUM (tdep); i++)
 	  {
 	    regcache->raw_collect (i, raw);
-	    p = XSAVE_MPX_ADDR (tdep, regs, i);
+	    p = XSAVE_BNDREGS_ADDR (tdep, regs, &offsets, i);
 	    if (memcmp (raw, p, 16))
 	      {
 		xstate_bv |= X86_XSTATE_BNDREGS;
@@ -1606,7 +1786,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	     i < I387_MPXEND_REGNUM (tdep); i++)
 	  {
 	    regcache->raw_collect (i, raw);
-	    p = XSAVE_MPX_ADDR (tdep, regs, i);
+	    p = XSAVE_BNDCFG_ADDR (tdep, regs, &offsets, i);
 	    if (memcmp (raw, p, 8))
 	      {
 		xstate_bv |= X86_XSTATE_BNDCFG;
@@ -1620,7 +1800,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	     i < I387_YMMENDH_REGNUM (tdep); i++)
 	  {
 	    regcache->raw_collect (i, raw);
-	    p = XSAVE_AVXH_ADDR (tdep, regs, i);
+	    p = XSAVE_AVXH_ADDR (tdep, regs, &offsets, i);
 	    if (memcmp (raw, p, 16))
 	      {
 		xstate_bv |= X86_XSTATE_AVX;
@@ -1688,7 +1868,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 
 	case pkeys:
 	  /* This is a PKEYS register.  */
-	  p = XSAVE_PKEYS_ADDR (tdep, regs, regnum);
+	  p = XSAVE_PKEYS_ADDR (tdep, regs, &offsets, regnum);
 	  if (memcmp (raw, p, 4) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_PKRU;
@@ -1696,18 +1876,29 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	    }
 	  break;
 
-	case avx512_zmm_h:
-	  /* This is a ZMM register.  */
-	  p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, regnum);
+	case avx512_zmm16_h:
+	  /* This is a ZMM16-31 register.  */
+	  p = XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, &offsets, regnum);
 	  if (memcmp (raw, p, 32) != 0)
 	    {
-	      xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM);
+	      xstate_bv |= X86_XSTATE_ZMM;
 	      memcpy (p, raw, 32);
 	    }
 	  break;
+
+	case avx512_zmm0_h:
+	  /* This is a ZMM0-15 register.  */
+	  p = XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, &offsets, regnum);
+	  if (memcmp (raw, p, 32) != 0)
+	    {
+	      xstate_bv |= X86_XSTATE_ZMM_H;
+	      memcpy (p, raw, 32);
+	    }
+	  break;
+
 	case avx512_k:
 	  /* This is a AVX512 mask register.  */
-	  p = XSAVE_AVX512_K_ADDR (tdep, regs, regnum);
+	  p = XSAVE_AVX512_K_ADDR (tdep, regs, &offsets, regnum);
 	  if (memcmp (raw, p, 8) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_K;
@@ -1717,7 +1908,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 
 	case avx512_ymmh_avx512:
 	  /* This is an upper YMM16-31 register.  */
-	  p = XSAVE_YMM_AVX512_ADDR (tdep, regs, regnum);
+	  p = XSAVE_YMM_AVX512_ADDR (tdep, regs, &offsets, regnum);
 	  if (memcmp (raw, p, 16) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_ZMM;
@@ -1727,7 +1918,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 
 	case avx512_xmm_avx512:
 	  /* This is an upper XMM16-31 register.  */
-	  p = XSAVE_XMM_AVX512_ADDR (tdep, regs, regnum);
+	  p = XSAVE_XMM_AVX512_ADDR (tdep, regs, &offsets, regnum);
 	  if (memcmp (raw, p, 16) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_ZMM;
@@ -1737,7 +1928,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 
 	case avxh:
 	  /* This is an upper YMM register.  */
-	  p = XSAVE_AVXH_ADDR (tdep, regs, regnum);
+	  p = XSAVE_AVXH_ADDR (tdep, regs, &offsets, regnum);
 	  if (memcmp (raw, p, 16))
 	    {
 	      xstate_bv |= X86_XSTATE_AVX;
@@ -1745,25 +1936,22 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	    }
 	  break;
 
-	case mpx:
-	  if (regnum < I387_BNDCFGU_REGNUM (tdep))
+	case bndregs:
+	  regcache->raw_collect (regnum, raw);
+	  p = XSAVE_BNDREGS_ADDR (tdep, regs, &offsets, regnum);
+	  if (memcmp (raw, p, 16))
 	    {
-	      regcache->raw_collect (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);
+	      xstate_bv |= X86_XSTATE_BNDREGS;
+	      memcpy (p, raw, 16);
 	    }
 	  break;
 
+	case bndcfg:
+	  p = XSAVE_BNDCFG_ADDR (tdep, regs, &offsets, regnum);
+	  xstate_bv |= X86_XSTATE_BNDCFG;
+	  memcpy (p, raw, 8);
+	  break;
+
 	case sse:
 	  /* This is an SSE register.  */
 	  p = FXSAVE_ADDR (tdep, regs, regnum);
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
index 698ff2ee206..bda7e2603d1 100644
--- a/gdb/i387-tdep.h
+++ b/gdb/i387-tdep.h
@@ -50,6 +50,7 @@ struct ui_file;
 #define I387_K0_REGNUM(tdep) ((tdep)->k0_regnum)
 #define I387_NUM_ZMMH_REGS(tdep) ((tdep)->num_zmm_regs)
 #define I387_ZMM0H_REGNUM(tdep) ((tdep)->zmm0h_regnum)
+#define I387_ZMM16H_REGNUM(tdep) ((tdep)->zmm0h_regnum + 16)
 #define I387_NUM_YMM_AVX512_REGS(tdep) ((tdep)->num_ymm_avx512_regs)
 #define I387_YMM16H_REGNUM(tdep) ((tdep)->ymm16h_regnum)
 
@@ -84,6 +85,21 @@ struct ui_file;
 #define I387_PKEYSEND_REGNUM(tdep) \
   (I387_PKRU_REGNUM (tdep) + I387_NUM_PKEYS_REGS)
 
+
+/* Offsets of register states in XSAVE area extended region.  Set to
+   -1 to indicate the absence of the associated registers.  */
+
+struct xsave_offsets
+{
+  int avx_offset = 0;
+  int bndregs_offset = 0;
+  int bndcfg_offset = 0;
+  int avx512_k_offset = 0;
+  int avx512_zmm_h_offset = 0;
+  int avx512_zmm_offset = 0;
+  int pkru_offset = 0;
+};
+
 /* Print out the i387 floating point state.  */
 
 extern void i387_print_float_info (struct gdbarch *gdbarch,
@@ -138,6 +154,12 @@ extern void i387_collect_fsave (const struct regcache *regcache, int regnum,
 extern void i387_supply_fxsave (struct regcache *regcache, int regnum,
 				const void *fxsave);
 
+/* Select an XSAVE layout based on the XCR0 bitmask and total XSAVE
+   extended state size.  */
+
+extern void i387_set_xsave_offsets (uint64_t xcr0, size_t xsave_size,
+				    struct xsave_offsets *offsets);
+
 /* Similar to i387_supply_fxsave, but use XSAVE extended state.  */
 
 extern void i387_supply_xsave (struct regcache *regcache, int regnum,
diff --git a/gdb/target.h b/gdb/target.h
index 4cc79df05b4..c4bd9bdf3d8 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -204,6 +204,8 @@ enum target_object
   TARGET_OBJECT_FREEBSD_VMMAP,
   /* FreeBSD process strings.  */
   TARGET_OBJECT_FREEBSD_PS_STRINGS,
+  /* x86 XSAVE area extended region offsets.  */
+  TARGET_OBJECT_X86_XSAVE_OFFSETS,
   /* Possible future objects: TARGET_OBJECT_FILE, ...  */
 };
 
-- 
2.34.1


  reply	other threads:[~2022-03-16 19:46 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-16 19:46 [RFC PATCH 0/4] Handle " John Baldwin
2022-03-16 19:46 ` John Baldwin [this message]
2022-03-16 19:46 ` [RFC PATCH 2/4] core: Support fetching TARGET_OBJECT_X86_XSAVE_OFFSETS from architectures John Baldwin
2022-03-16 19:46 ` [RFC PATCH 3/4] Update x86 FreeBSD architectures to support XSAVE offsets John Baldwin
2022-03-16 19:46 ` [RFC PATCH 4/4] Support XSAVE layouts for the current host in the FreeBSD/amd64 target John Baldwin
2022-03-17 13:17 ` [RFC PATCH 0/4] Handle variable XSAVE layouts Willgerodt, Felix
2022-03-17 16:20   ` John Baldwin
2022-03-17 18:03     ` John Baldwin
2022-03-18 13:49       ` Willgerodt, Felix
2022-03-18 17:27         ` John Baldwin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220316194608.89528-2-jhb@FreeBSD.org \
    --to=jhb@freebsd.org \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).