aboutsummaryrefslogtreecommitdiff
path: root/gdb/i387-tdep.c
diff options
context:
space:
mode:
authorMichael Sturm <michael.sturm@intel.com>2013-12-16 16:43:05 +0100
committerMichael Sturm <michael.sturm@intel.com>2014-04-24 16:30:03 +0200
commit01f9f808e2e86187c95e7cff4aeb014a421a53ce (patch)
treed4adda2ec2f59976e6a349f4291d6420c47df8b5 /gdb/i387-tdep.c
parent93ee1e3683a12f4774b8beb4f821910982e21ce2 (diff)
downloadfsf-binutils-gdb-01f9f808e2e86187c95e7cff4aeb014a421a53ce.zip
fsf-binutils-gdb-01f9f808e2e86187c95e7cff4aeb014a421a53ce.tar.gz
fsf-binutils-gdb-01f9f808e2e86187c95e7cff4aeb014a421a53ce.tar.bz2
Add AVX512 registers support to GDB and GDBserver.
This patch adds support for the Intel(R) Advanced Vector Extensions 512 (Intel(R) AVX-512) registers. Native and remote debugging are covered by this patch. Intel(R) AVX-512 is an extension to AVX to support 512-bit wide SIMD registers in 64-bit mode (XMM0-XMM31, YMM0-YMM31, ZMM0-ZMM31). The number of available registers in 32-bit mode is still 8 (XMM0-7, YMM0-7, ZMM0-7). The lower 256-bits of the ZMM registers are aliased to the respective 256-bit YMM registers. The lower 128-bits are aliased to the respective 128-bit XMM registers. There are also 8 new, dedicated mask registers (K0-K7) in both 32-bit mode and 64-bit mode. For more information please see Intel(R) Developer Zone: Intel(R) AVX http://software.intel.com/en-us/intel-isa-extensions#pid-16007-1495 Intel(R) Architecture Instruction Set Extensions Programming Reference: http://software.intel.com/en-us/file/319433-017pdf 2014-04-24 Michael Sturm <michael.sturm@mintel.com> Walfred Tedeschi <walfred.tedeschi@intel.com> * amd64-linux-nat.c (amd64_linux_gregset32_reg_offset): Add AVX512 registers. (amd64_linux_read_description): Add code to handle AVX512 xstate mask and return respective tdesc. * amd64-linux-tdep.c: Include features/i386/amd64-avx512-linux.c and features/i386/x32-avx512-linux.c. (amd64_linux_gregset_reg_offset): Add AVX512 registers. (amd64_linux_core_read_description): Add code to handle AVX512 xstate mask and return respective tdesc. (_initialize_amd64_linux_tdep): Initialize AVX512 tdesc. * amd64-linux-tdep.h (AMD64_LINUX_ORIG_RAX_REGNUM): Adjust regnum calculation. (AMD64_LINUX_NUM_REGS): Adjust to new number of registers. (tdesc_amd64_avx512_linux): New prototype. (tdesc_x32_avx512_linux): Likewise. * amd64-tdep.c: Include features/i386/amd64-avx512.c and features/i386/x32-avx512.c. (amd64_ymm_avx512_names): New register names for pseudo registers YMM16-31. (amd64_ymmh_avx512_names): New register names for raw registers YMMH16-31. (amd64_k_names): New register names for K registers. (amd64_zmmh_names): New register names for ZMM raw registers. (amd64_zmm_names): New registers names for ZMM pseudo registers. (amd64_xmm_avx512_names): New register names for XMM16-31 registers. (amd64_pseudo_register_name): Add code to return AVX512 pseudo registers. (amd64_init_abi): Add code to intitialize AVX512 tdep variables if feature is present. (_initialize_amd64_tdep): Call AVX512 tdesc initializers. * amd64-tdep.h (enum amd64_regnum): Add AVX512 registers. (AMD64_NUM_REGS): Adjust to new number of registers. * i386-linux-nat.c (GETXSTATEREGS_SUPPLIES): Extend range of registers supplied via XSTATE by AVX512 registers. (i386_linux_read_description): Add case for AVX512. * i386-linux-tdep.c: Include i386-avx512-linux.c. (i386_linux_gregset_reg_offset): Add AVX512 registers. (i386_linux_core_read_description): Add case for AVX512. (i386_linux_init_abi): Install supported register note section for AVX512. (_initialize_i386_linux_tdep): Add call to tdesc init function for AVX512. * i386-linux-tdep.h (I386_LINUX_NUM_REGS): Set number of registers to be number of zmm7h + 1. (tdesc_i386_avx512_linux): Add tdesc for AVX512 registers. * i386-tdep.c: Include features/i386/i386-avx512.c. (i386_zmm_names): Add ZMM pseudo register names array. (i386_zmmh_names): Add ZMM raw register names array. (i386_k_names): Add K raw register names array. (num_lower_zmm_regs): Add constant for the number of lower ZMM registers. AVX512 has 16 more ZMM registers than there are YMM registers. (i386_zmmh_regnum_p): Add function to look up register number of ZMM raw registers. (i386_zmm_regnum_p): Likewise for ZMM pseudo registers. (i386_k_regnum_p): Likewise for K raw registers. (i386_ymmh_avx512_regnum_p): Likewise for additional YMM raw registers added by AVX512. (i386_ymm_avx512_regnum_p): Likewise for additional YMM pseudo registers added by AVX512. (i386_xmm_avx512_regnum_p): Likewise for additional XMM registers added by AVX512. (i386_register_name): Add code to hide YMMH16-31 and ZMMH0-31. (i386_pseudo_register_name): Add ZMM pseudo registers. (i386_zmm_type): Construct and return vector registers type for ZMM registers. (i386_pseudo_register_type): Return appropriate type for YMM16-31, ZMM0-31 pseudo registers and K registers. (i386_pseudo_register_read_into_value): Add code to read K, ZMM and YMM16-31 registers from register cache. (i386_pseudo_register_write): Add code to write K, ZMM and YMM16-31 registers. (i386_register_reggroup_p): Add code to include/exclude AVX512 registers in/from respective register groups. (i386_validate_tdesc_p): Handle AVX512 feature, add AVX512 registers if feature is present in xcr0. (i386_gdbarch_init): Add code to initialize AVX512 feature variables in tdep structure, wire in pseudo registers and call initialize_tdesc_i386_avx512. * i386-tdep.h (struct gdbarch_tdep): Add AVX512 related variables. (i386_regnum): Add AVX512 registers. (I386_SSE_NUM_REGS): New define for number of SSE registers. (I386_AVX_NUM_REGS): Likewise for AVX registers. (I386_AVX512_NUM_REGS): Likewise for AVX512 registers. (I386_MAX_REGISTER_SIZE): Change to 64 bytes, ZMM registers are 512 bits wide. (i386_xmm_avx512_regnum_p): New prototype for register look up. (i386_ymm_avx512_regnum_p): Likewise. (i386_k_regnum_p): Likewise. (i386_zmm_regnum_p): Likewise. (i386_zmmh_regnum_p): Likewise. * i387-tdep.c : Update year in copyright notice. (xsave_ymm_avx512_offset): New table for YMM16-31 offsets in XSAVE buffer. (XSAVE_YMM_AVX512_ADDR): New macro. (xsave_xmm_avx512_offset): New table for XMM16-31 offsets in XSAVE buffer. (XSAVE_XMM_AVX512_ADDR): New macro. (xsave_avx512_k_offset): New table for K register offsets in XSAVE buffer. (XSAVE_AVX512_K_ADDR): New macro. (xsave_avx512_zmm_h_offset): New table for ZMM register offsets in XSAVE buffer. (XSAVE_AVX512_ZMM_H_ADDR): New macro. (i387_supply_xsave): Add code to supply AVX512 registers to XSAVE buffer. (i387_collect_xsave): Add code to collect AVX512 registers from XSAVE buffer. * i387-tdep.h (I387_NUM_XMM_AVX512_REGS): New define for number of XMM16-31 registers. (I387_NUM_K_REGS): New define for number of K registers. (I387_K0_REGNUM): New define for K0 register number. (I387_NUM_ZMMH_REGS): New define for number of ZMMH registers. (I387_ZMM0H_REGNUM): New define for ZMM0H register number. (I387_NUM_YMM_AVX512_REGS): New define for number of YMM16-31 registers. (I387_YMM16H_REGNUM): New define for YMM16H register number. (I387_XMM16_REGNUM): New define for XMM16 register number. (I387_YMM0_REGNUM): New define for YMM0 register number. (I387_KEND_REGNUM): New define for last K register number. (I387_ZMMENDH_REGNUM): New define for last ZMMH register number. (I387_YMMH_AVX512_END_REGNUM): New define for YMM31 register number. (I387_XMM_AVX512_END_REGNUM): New define for XMM31 register number. * common/i386-xstate.h: Add AVX 3.1 feature bits, mask and XSTATE size. * features/Makefile: Add AVX512 related files. * features/i386/32bit-avx512.xml: New file. * features/i386/64bit-avx512.xml: Likewise. * features/i386/amd64-avx512-linux.c: Likewise. * features/i386/amd64-avx512-linux.xml: Likewise. * features/i386/amd64-avx512.c: Likewise. * features/i386/amd64-avx512.xml: Likewise. * features/i386/i386-avx512-linux.c: Likewise. * features/i386/i386-avx512-linux.xml: Likewise. * features/i386/i386-avx512.c: Likewise. * features/i386/i386-avx512.xml: Likewise. * features/i386/x32-avx512-linux.c: Likewise. * features/i386/x32-avx512-linux.xml: Likewise. * features/i386/x32-avx512.c: Likewise. * features/i386/x32-avx512.xml: Likewise. * regformats/i386/amd64-avx512-linux.dat: New file. * regformats/i386/amd64-avx512.dat: Likewise. * regformats/i386/i386-avx512-linux.dat: Likewise. * regformats/i386/i386-avx512.dat: Likewise. * regformats/i386/x32-avx512-linux.dat: Likewise. * regformats/i386/x32-avx512.dat: Likewise. * NEWS: Add note about new support for AVX512. testsuite/ * Makefile.in (EXECUTABLES): Added i386-avx512. * gdb.arch/i386-avx512.c: New file. * gdb.arch/i386-avx512.exp: Likewise. gdbserver/ * Makefile.in: Added rules to handle new files i386-avx512.c i386-avx512-linux.c amd64-avx512.c amd64-avx512-linux.c x32-avx512.c x32-avx512-linux.c. * configure.srv (srv_i386_regobj): Add i386-avx512.o. (srv_i386_linux_regobj): Add i386-avx512-linux.o. (srv_amd64_regobj): Add amd64-avx512.o and x32-avx512.o. (srv_amd64_linux_regobj): Add amd64-avx512-linux.o and x32-avx512-linux.o. (srv_i386_32bit_xmlfiles): Add i386/32bit-avx512.xml. (srv_i386_64bit_xmlfiles): Add i386/64bit-avx512.xml. (srv_amd64_xmlfiles): Add i386/amd64-avx512.xml and i386/x32-avx512.xml. (srv_i386_linux_xmlfiles): Add i386/i386-avx512-linux.xml. (srv_amd64_linux_xmlfiles): Add i386/amd64-avx512-linux.xml and i386/x32-avx512-linux.xml. * i387-fp.c (num_avx512_k_registers): New constant for number of K registers. (num_avx512_zmmh_low_registers): New constant for number of lower ZMM registers (0-15). (num_avx512_zmmh_high_registers): New constant for number of higher ZMM registers (16-31). (num_avx512_ymmh_registers): New contant for number of higher YMM registers (ymm16-31 added by avx521 on x86_64). (num_avx512_xmm_registers): New constant for number of higher XMM registers (xmm16-31 added by AVX512 on x86_64). (struct i387_xsave): Add space for AVX512 registers. (i387_cache_to_xsave): Change raw buffer size to 64 characters. Add code to handle AVX512 registers. (i387_xsave_to_cache): Add code to handle AVX512 registers. * linux-x86-low.c (init_registers_amd64_avx512_linux): New prototypei from generated file. (tdesc_amd64_avx512_linux): Likewise. (init_registers_x32_avx512_linux): Likewise. (tdesc_x32_avx512_linux): Likewise. (init_registers_i386_avx512_linux): Likewise. (tdesc_i386_avx512_linux): Likewise. (x86_64_regmap): Add AVX512 registers. (x86_linux_read_description): Add code to handle AVX512 XSTATE mask. (initialize_low_arch): Add code to initialize AVX512 registers. doc/ * gdb.texinfo (i386 Features): Add description of AVX512 registers. Change-Id: Ifc4c08c76b85dbec18d02efdbe6182e851584438 Signed-off-by: Michael Sturm <michael.sturm@intel.com>
Diffstat (limited to 'gdb/i387-tdep.c')
-rw-r--r--gdb/i387-tdep.c384
1 files changed, 375 insertions, 9 deletions
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index d24d322..c58a000 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -763,8 +763,61 @@ static int xsave_avxh_offset[] =
576 + 15 * 16 /* Upper 128bit of ... %ymm15 (128 bits each). */
};
-static int xsave_mpx_offset[] =
+#define XSAVE_AVXH_ADDR(tdep, xsave, regnum) \
+ (xsave + 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"
+ 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). */
+};
+
+#define XSAVE_YMM_AVX512_ADDR(tdep, xsave, regnum) \
+ (xsave + xsave_ymm_avx512_offset[regnum - I387_YMM16H_REGNUM (tdep)])
+
+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). */
+};
+
+#define XSAVE_XMM_AVX512_ADDR(tdep, xsave, regnum) \
+ (xsave + 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,
@@ -773,19 +826,79 @@ static int xsave_mpx_offset[] =
1024 + 1 * 8,
};
-#define XSAVE_AVXH_ADDR(tdep, xsave, regnum) \
- (xsave + xsave_avxh_offset[regnum - I387_YMM0H_REGNUM (tdep)])
-
#define XSAVE_MPX_ADDR(tdep, xsave, regnum) \
(xsave + xsave_mpx_offset[regnum - I387_BND0R_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"
+ instruction where GDB register REGNUM is stored. */
+
+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). */
+};
+
+#define XSAVE_AVX512_K_ADDR(tdep, xsave, regnum) \
+ (xsave + 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[] =
+{
+ 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). */
+};
+
+#define XSAVE_AVX512_ZMM_H_ADDR(tdep, xsave, regnum) \
+ (xsave + xsave_avx512_zmm_h_offset[regnum - I387_ZMM0H_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));
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
const gdb_byte *regs = xsave;
int i;
unsigned int clear_bv;
@@ -797,7 +910,12 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
sse = 0x2,
avxh = 0x4,
mpx = 0x8,
- all = x87 | sse | avxh | mpx
+ avx512_k = 0x10,
+ avx512_zmm_h = 0x20,
+ avx512_ymmh_avx512 = 0x40,
+ avx512_xmm_avx512 = 0x80,
+ all = x87 | sse | avxh | mpx | avx512_k | avx512_zmm_h
+ | avx512_ymmh_avx512 | avx512_xmm_avx512
} regclass;
gdb_assert (regs != NULL);
@@ -806,13 +924,25 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
if (regnum == -1)
regclass = all;
+ else if (regnum >= I387_ZMM0H_REGNUM (tdep)
+ && regnum < I387_ZMMENDH_REGNUM (tdep))
+ regclass = avx512_zmm_h;
+ else if (regnum >= I387_K0_REGNUM (tdep)
+ && regnum < I387_KEND_REGNUM (tdep))
+ regclass = avx512_k;
+ else if (regnum >= I387_YMM16H_REGNUM (tdep)
+ && regnum < I387_YMMH_AVX512_END_REGNUM (tdep))
+ regclass = avx512_ymmh_avx512;
+ else if (regnum >= I387_XMM16_REGNUM (tdep)
+ && regnum < I387_XMM_AVX512_END_REGNUM (tdep))
+ regclass = avx512_xmm_avx512;
else if (regnum >= I387_YMM0H_REGNUM (tdep)
&& regnum < I387_YMMENDH_REGNUM (tdep))
regclass = avxh;
else if (regnum >= I387_BND0R_REGNUM (tdep)
&& regnum < I387_MPXEND_REGNUM (tdep))
regclass = mpx;
- else if (regnum >= I387_XMM0_REGNUM(tdep)
+ else if (regnum >= I387_XMM0_REGNUM (tdep)
&& regnum < I387_MXCSR_REGNUM (tdep))
regclass = sse;
else if (regnum >= I387_ST0_REGNUM (tdep)
@@ -847,6 +977,38 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
case none:
break;
+ case avx512_zmm_h:
+ if ((clear_bv & (I386_XSTATE_ZMM_H | I386_XSTATE_ZMM)))
+ regcache_raw_supply (regcache, regnum, zero);
+ else
+ regcache_raw_supply (regcache, regnum,
+ XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, regnum));
+ return;
+
+ case avx512_k:
+ if ((clear_bv & I386_XSTATE_K))
+ regcache_raw_supply (regcache, regnum, zero);
+ else
+ regcache_raw_supply (regcache, regnum,
+ XSAVE_AVX512_K_ADDR (tdep, regs, regnum));
+ return;
+
+ case avx512_ymmh_avx512:
+ if ((clear_bv & I386_XSTATE_ZMM))
+ regcache_raw_supply (regcache, regnum, zero);
+ else
+ regcache_raw_supply (regcache, regnum,
+ XSAVE_YMM_AVX512_ADDR (tdep, regs, regnum));
+ return;
+
+ case avx512_xmm_avx512:
+ if ((clear_bv & I386_XSTATE_ZMM))
+ regcache_raw_supply (regcache, regnum, zero);
+ else
+ regcache_raw_supply (regcache, regnum,
+ XSAVE_XMM_AVX512_ADDR (tdep, regs, regnum));
+ return;
+
case avxh:
if ((clear_bv & I386_XSTATE_AVX))
regcache_raw_supply (regcache, regnum, zero);
@@ -880,6 +1042,74 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
return;
case all:
+ /* Handle the upper ZMM registers. */
+ if ((tdep->xcr0 & (I386_XSTATE_ZMM_H | I386_XSTATE_ZMM)))
+ {
+ if ((clear_bv & (I386_XSTATE_ZMM_H | I386_XSTATE_ZMM)))
+ {
+ for (i = I387_ZMM0H_REGNUM (tdep);
+ i < I387_ZMMENDH_REGNUM (tdep);
+ i++)
+ regcache_raw_supply (regcache, i, zero);
+ }
+ else
+ {
+ for (i = I387_ZMM0H_REGNUM (tdep);
+ i < I387_ZMMENDH_REGNUM (tdep);
+ i++)
+ regcache_raw_supply (regcache, i,
+ XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i));
+ }
+ }
+
+ /* Handle AVX512 OpMask registers. */
+ if ((tdep->xcr0 & I386_XSTATE_K))
+ {
+ if ((clear_bv & I386_XSTATE_K))
+ {
+ for (i = I387_K0_REGNUM (tdep);
+ i < I387_KEND_REGNUM (tdep);
+ i++)
+ regcache_raw_supply (regcache, i, zero);
+ }
+ else
+ {
+ for (i = I387_K0_REGNUM (tdep);
+ i < I387_KEND_REGNUM (tdep);
+ i++)
+ regcache_raw_supply (regcache, i,
+ XSAVE_AVX512_K_ADDR (tdep, regs, i));
+ }
+ }
+
+ /* Handle the YMM_AVX512 registers. */
+ if ((tdep->xcr0 & I386_XSTATE_ZMM))
+ {
+ if ((clear_bv & I386_XSTATE_ZMM))
+ {
+ for (i = I387_YMM16H_REGNUM (tdep);
+ i < I387_YMMH_AVX512_END_REGNUM (tdep);
+ i++)
+ regcache_raw_supply (regcache, i, zero);
+ for (i = I387_XMM16_REGNUM (tdep);
+ i < I387_XMM_AVX512_END_REGNUM (tdep);
+ i++)
+ regcache_raw_supply (regcache, i, zero);
+ }
+ else
+ {
+ for (i = I387_YMM16H_REGNUM (tdep);
+ i < I387_YMMH_AVX512_END_REGNUM (tdep);
+ i++)
+ regcache_raw_supply (regcache, i,
+ XSAVE_YMM_AVX512_ADDR (tdep, regs, i));
+ for (i = I387_XMM16_REGNUM (tdep);
+ i < I387_XMM_AVX512_END_REGNUM (tdep);
+ i++)
+ regcache_raw_supply (regcache, i,
+ XSAVE_XMM_AVX512_ADDR (tdep, regs, i));
+ }
+ }
/* Handle the upper YMM registers. */
if ((tdep->xcr0 & I386_XSTATE_AVX))
{
@@ -1040,7 +1270,8 @@ void
i387_collect_xsave (const struct regcache *regcache, int regnum,
void *xsave, int gcore)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
gdb_byte *regs = xsave;
int i;
enum
@@ -1051,7 +1282,12 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
sse = 0x4 | check,
avxh = 0x8 | check,
mpx = 0x10 | check,
- all = x87 | sse | avxh | mpx
+ avx512_k = 0x20 | check,
+ avx512_zmm_h = 0x40 | check,
+ avx512_ymmh_avx512 = 0x80 | check,
+ avx512_xmm_avx512 = 0x100 | check,
+ all = x87 | sse | avxh | mpx | avx512_k | avx512_zmm_h
+ | avx512_ymmh_avx512 | avx512_xmm_avx512
} regclass;
gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
@@ -1059,6 +1295,18 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
if (regnum == -1)
regclass = all;
+ else if (regnum >= I387_ZMM0H_REGNUM (tdep)
+ && regnum < I387_ZMMENDH_REGNUM (tdep))
+ regclass = avx512_zmm_h;
+ else if (regnum >= I387_K0_REGNUM (tdep)
+ && regnum < I387_KEND_REGNUM (tdep))
+ regclass = avx512_k;
+ else if (regnum >= I387_YMM16H_REGNUM (tdep)
+ && regnum < I387_YMMH_AVX512_END_REGNUM (tdep))
+ regclass = avx512_ymmh_avx512;
+ else if (regnum >= I387_XMM16_REGNUM (tdep)
+ && regnum < I387_XMM_AVX512_END_REGNUM (tdep))
+ regclass = avx512_xmm_avx512;
else if (regnum >= I387_YMM0H_REGNUM (tdep)
&& regnum < I387_YMMENDH_REGNUM (tdep))
regclass = avxh;
@@ -1107,6 +1355,26 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
i < I387_MPXEND_REGNUM (tdep); i++)
memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 8);
+ if ((clear_bv & (I386_XSTATE_ZMM_H | I386_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 & I386_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 & I386_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 & I386_XSTATE_AVX))
for (i = I387_YMM0H_REGNUM (tdep);
i < I387_YMMENDH_REGNUM (tdep); i++)
@@ -1125,6 +1393,61 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
if (regclass == all)
{
+ /* Check if any ZMMH registers are changed. */
+ if ((tdep->xcr0 & (I386_XSTATE_ZMM_H | I386_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)
+ {
+ xstate_bv |= (I386_XSTATE_ZMM_H | I386_XSTATE_ZMM);
+ memcpy (p, raw, 32);
+ }
+ }
+
+ /* Check if any K registers are changed. */
+ if ((tdep->xcr0 & I386_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)
+ {
+ xstate_bv |= I386_XSTATE_K;
+ memcpy (p, raw, 8);
+ }
+ }
+
+ /* Check if any XMM or upper YMM registers are changed. */
+ if ((tdep->xcr0 & I386_XSTATE_ZMM))
+ {
+ 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)
+ {
+ xstate_bv |= I386_XSTATE_ZMM;
+ memcpy (p, raw, 16);
+ }
+ }
+ 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)
+ {
+ xstate_bv |= I386_XSTATE_ZMM;
+ memcpy (p, raw, 16);
+ }
+ }
+ }
+
/* Check if any upper YMM registers are changed. */
if ((tdep->xcr0 & I386_XSTATE_AVX))
for (i = I387_YMM0H_REGNUM (tdep);
@@ -1205,6 +1528,45 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
internal_error (__FILE__, __LINE__,
_("invalid i387 regclass"));
+ 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 |= (I386_XSTATE_ZMM_H | I386_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 |= I386_XSTATE_K;
+ memcpy (p, raw, 8);
+ }
+ 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 |= I386_XSTATE_ZMM;
+ 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 |= I386_XSTATE_ZMM;
+ memcpy (p, raw, 16);
+ }
+ break;
+
case avxh:
/* This is an upper YMM register. */
p = XSAVE_AVXH_ADDR (tdep, regs, regnum);
@@ -1276,6 +1638,10 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
case sse:
case avxh:
case mpx:
+ case avx512_k:
+ case avx512_zmm_h:
+ case avx512_ymmh_avx512:
+ case avx512_xmm_avx512:
/* Register REGNUM has been updated. Return. */
return;
}