This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH v2 1/3] Add AVX512 registers support to GDB.


Hi Mark,

thanks a lot for the review. Please see comments below.

Regards,
Michael & Fred


On 23/02/2014 23:52, Mark Kettenis wrote:
From: Michael Sturm<michael.sturm@intel.com>
Date: Thu, 20 Feb 2014 15:52:43 +0100

2013-09-11  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.

testsuite/
      * Makefile.in (EXECUTABLES): Added i386-avx512.
      * gdb.arch/i386-avx512.c: New file.
      * gdb.arch/i386-avx512.exp: Likewise.

Hi Michael,

Finally found some time to review this diff.  Sorry for the delay.

Any particular reason why you didn't make %zmm16-%zmm31 the real "raw"
registers and %ymm16-%ymm31 and %xmm16-%ymm31 pseudo-register views
into those?  Seems more logical as they are provided as contigious
512-bit areas in the xsave storage area.  I think that would actually
simply the code, but I may be wrong.  It certainly would simply the
on-the-wire formats for remote debugging as specified in the xml files.
Interesting question! Actually, we've started implementation following this approach. But when we did first internal reviews of the patch, we found that the symmetry with existing code for XMM and YMM registers would be broken and code would be duplicated in some points and more complex and asymmetrical in others:

- the type definitions for xmm16-31 and ymm16-31 pseudo registers in the XML files would
  need to be repeated in the code.
- the implementation of xmm16-31 and ymm16-31 would be different from the implementation of
  xmm0-15 and ymm0-15
- there would be different code for zmm0-15 and zmm16-31.

So we opted for simpler and more symmetric code.
diff --git a/gdb/common/i386-xstate.h b/gdb/common/i386-xstate.h
index 3638142..bd1dcc3 100644
--- a/gdb/common/i386-xstate.h
+++ b/gdb/common/i386-xstate.h
@@ -28,28 +28,40 @@
  #define I386_XSTATE_BNDCFG	(1ULL << 4)
  #define I386_XSTATE_MPX		(I386_XSTATE_BNDREGS | I386_XSTATE_BNDCFG)
+/* AVX 512 adds three feature bits. All three must be enabled. */
+#define I386_XSTATE_K		(1ULL << 5)
+#define I386_XSTATE_ZMM_H	(1ULL << 6)
+#define I386_XSTATE_ZMM		(1ULL << 7)
+#define I386_XSTATE_AVX512	(I386_XSTATE_K | I386_XSTATE_ZMM_H \
+				 | I386_XSTATE_ZMM)
+
  /* Supported mask and size of the extended state.  */
  #define I386_XSTATE_X87_MASK	I386_XSTATE_X87
  #define I386_XSTATE_SSE_MASK	(I386_XSTATE_X87 | I386_XSTATE_SSE)
  #define I386_XSTATE_AVX_MASK	(I386_XSTATE_SSE_MASK | I386_XSTATE_AVX)
  #define I386_XSTATE_MPX_MASK	(I386_XSTATE_AVX_MASK | I386_XSTATE_MPX)
+#define I386_XSTATE_AVX512_MASK	(I386_XSTATE_AVX_MASK | I386_XSTATE_AVX512)
+#define I386_XSTATE_MPX_AVX512_MASK (I386_XSTATE_MPX_MASK | I386_XSTATE_AVX512)
So you can have AVX512 support without MPX support?
We should not discard this option... ;-)

diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 57f18cb..ca7688e 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -1,3 +1,4 @@
+
  /* Intel 386 target-dependent stuff.
Copyright (C) 1988-2014 Free Software Foundation, Inc.
@@ -58,6 +59,7 @@
  #include "features/i386/i386.c"
  #include "features/i386/i386-avx.c"
  #include "features/i386/i386-mpx.c"
+#include "features/i386/i386-avx512.c"
  #include "features/i386/i386-mmx.c"
#include "ax.h"
@@ -87,6 +89,24 @@ static const char *i386_register_names[] =
    "mxcsr"
  };
+static const char *i386_zmm_names[] =
+{
+  "zmm0",  "zmm1",   "zmm2",  "zmm3",
+  "zmm4",  "zmm5",   "zmm6",  "zmm7"
+};
+
+static const char *i386_zmmh_names[] =
+{
+  "zmm0h",  "zmm1h",   "zmm2h",  "zmm3h",
+  "zmm4h",  "zmm5h",   "zmm6h",  "zmm7h"
+};
+
+static const char *i386_k_names[] =
+{
+  "k0",  "k1",   "k2",  "k3",
+  "k4",  "k5",   "k6",  "k7"
+};
+
  static const char *i386_ymm_names[] =
  {
    "ymm0",  "ymm1",   "ymm2",  "ymm3",
@@ -135,6 +155,12 @@ static const char *i386_word_names[] =
    "", "bp", "si", "di"
  };
+/* Constant used for reading/writing pseudo registers. In amd64, we have
+   16 lower ZMM regs that extend corresponding xmm/ymm registers.  In addition,
+   we have 16 upper ZMM regs that have to be handled differently.  */
Perhaps "In 64-bit mode" instead of "In amd64"?
Ok.
+
+const int num_lower_zmm_regs = 16;
+
  /* MMX register?  */
static int
@@ -187,6 +213,47 @@ i386_dword_regnum_p (struct gdbarch *gdbarch, int regnum)
    return regnum >= 0 && regnum < tdep->num_dword_regs;
  }
+/* AVX512 register? */
+
+int
+i386_zmmh_regnum_p (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int zmm0h_regnum = tdep->zmm0h_regnum;
+
+  if (zmm0h_regnum < 0)
+    return 0;
+
+  regnum -= zmm0h_regnum;
+  return regnum >= 0 && regnum < tdep->num_zmm_regs;
+}
+
+int
+i386_zmm_regnum_p (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int zmm0_regnum = tdep->zmm0_regnum;
+
+  if (zmm0_regnum < 0)
+    return 0;
+
+  regnum -= zmm0_regnum;
+  return regnum >= 0 && regnum < tdep->num_zmm_regs;
+}
+
+int
+i386_k_regnum_p (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int k0_regnum = tdep->k0_regnum;
+
+  if (k0_regnum < 0)
+    return 0;
+
+  regnum -= k0_regnum;
+  return regnum >= 0 && regnum < I387_NUM_K_REGS;
+}
+
  static int
  i386_ymmh_regnum_p (struct gdbarch *gdbarch, int regnum)
  {
@@ -215,6 +282,32 @@ i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum)
    return regnum >= 0 && regnum < tdep->num_ymm_regs;
  }
+static int
+i386_ymmh_avx512_regnum_p (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int ymm16h_regnum = tdep->ymm16h_regnum;
+
+  if (ymm16h_regnum < 0)
+    return 0;
+
+  regnum -= ymm16h_regnum;
+  return regnum >= 0 && regnum < tdep->num_ymm_avx512_regs;
+}
+
+int
+i386_ymm_avx512_regnum_p (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int ymm16_regnum = tdep->ymm16_regnum;
+
+  if (ymm16_regnum < 0)
+    return 0;
+
+  regnum -= ymm16_regnum;
+  return regnum >= 0 && regnum < tdep->num_ymm_avx512_regs;
+}
+
  /* BND register?  */
int
@@ -245,6 +338,21 @@ i386_xmm_regnum_p (struct gdbarch *gdbarch, int regnum)
    return regnum >= 0 && regnum < num_xmm_regs;
  }
+/* XMM_512 register? */
+
+int
+i386_xmm_avx512_regnum_p (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int num_xmm_avx512_regs = I387_NUM_XMM_AVX512_REGS (tdep);
+
+  if (num_xmm_avx512_regs == 0)
+    return 0;
+
+  regnum -= I387_XMM16_REGNUM (tdep);
+  return regnum >= 0 && regnum < num_xmm_avx512_regs;
+}
+
  static int
  i386_mxcsr_regnum_p (struct gdbarch *gdbarch, int regnum)
  {
@@ -320,6 +428,14 @@ i386_register_name (struct gdbarch *gdbarch, int regnum)
    if (i386_ymmh_regnum_p (gdbarch, regnum))
      return "";
+ /* Hide the upper YMM16-31 registers. */
+  if (i386_ymmh_avx512_regnum_p (gdbarch, regnum))
+    return "";
+
+  /* Hide the upper ZMM registers.  */
+  if (i386_zmmh_regnum_p (gdbarch, regnum))
+    return "";
+
    return tdesc_register_name (gdbarch, regnum);
  }
@@ -335,6 +451,8 @@ i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
      return i386_mmx_names[regnum - I387_MM0_REGNUM (tdep)];
    else if (i386_ymm_regnum_p (gdbarch, regnum))
      return i386_ymm_names[regnum - tdep->ymm0_regnum];
+  else if (i386_zmm_regnum_p (gdbarch, regnum))
+    return i386_zmm_names[regnum - tdep->zmm0_regnum];
    else if (i386_byte_regnum_p (gdbarch, regnum))
      return i386_byte_names[regnum - tdep->al_regnum];
    else if (i386_word_regnum_p (gdbarch, regnum))
@@ -2908,6 +3026,59 @@ i386_bnd_type (struct gdbarch *gdbarch)
    return tdep->i386_bnd_type;
  }
+/* Construct vector type for pseudo ZMM registers. We can't use
+   tdesc_find_type since ZMM isn't described in target description.  */
+
+static struct type *
+i386_zmm_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (!tdep->i386_zmm_type)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+
+      /* The type we're building is this:  */
+#if 0
+      union __gdb_builtin_type_vec512i
+      {
+	int128_t uint128[4];
+	int64_t v4_int64[8];
+	int32_t v8_int32[16];
+	int16_t v16_int16[32];
+	int8_t v32_int8[64];
+	double v4_double[8];
+	float v8_float[16];
+      };
+#endif
+
+      struct type *t;
+
+      t = arch_composite_type (gdbarch,
+			       "__gdb_builtin_type_vec512i", TYPE_CODE_UNION);
+      append_composite_type_field (t, "v16_float",
+				   init_vector_type (bt->builtin_float, 16));
+      append_composite_type_field (t, "v8_double",
+				   init_vector_type (bt->builtin_double, 8));
+      append_composite_type_field (t, "v64_int8",
+				   init_vector_type (bt->builtin_int8, 64));
+      append_composite_type_field (t, "v32_int16",
+				   init_vector_type (bt->builtin_int16, 32));
+      append_composite_type_field (t, "v16_int32",
+				   init_vector_type (bt->builtin_int32, 16));
+      append_composite_type_field (t, "v8_int64",
+				   init_vector_type (bt->builtin_int64, 8));
+      append_composite_type_field (t, "v4_int128",
+				   init_vector_type (bt->builtin_int128, 4));
+
+      TYPE_VECTOR (t) = 1;
+      TYPE_NAME (t) = "builtin_type_vec512i";
+      tdep->i386_zmm_type = t;
+    }
+
+  return tdep->i386_zmm_type;
+}
+
  /* Construct vector type for pseudo YMM registers.  We can't use
     tdesc_find_type since YMM isn't described in target description.  */
@@ -3015,6 +3186,10 @@ i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
      return i386_mmx_type (gdbarch);
    else if (i386_ymm_regnum_p (gdbarch, regnum))
      return i386_ymm_type (gdbarch);
+  else if (i386_ymm_avx512_regnum_p (gdbarch, regnum))
+    return i386_ymm_type (gdbarch);
+  else if (i386_zmm_regnum_p (gdbarch, regnum))
+    return i386_zmm_type (gdbarch);
    else
      {
        const struct builtin_type *bt = builtin_type (gdbarch);
@@ -3024,6 +3199,8 @@ i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
  	return bt->builtin_int16;
        else if (i386_dword_regnum_p (gdbarch, regnum))
  	return bt->builtin_int32;
+      else if (i386_k_regnum_p (gdbarch, regnum))
+	return bt->builtin_int64;
      }
internal_error (__FILE__, __LINE__, _("invalid regnum"));
@@ -3101,6 +3278,75 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
  	      memcpy (buf + size, &upper, size);
  	    }
  	}
+      else if (i386_k_regnum_p (gdbarch, regnum))
+	{
+	  regnum -= tdep->k0_regnum;
+
+	  /* Extract (always little endian).  */
+	  status = regcache_raw_read (regcache,
+				      tdep->k0_regnum + regnum,
+				      raw_buf);
+	  if (status != REG_VALID)
+	    mark_value_bytes_unavailable (result_value, 0, 8);
+	  else
+	    memcpy (buf, raw_buf, 8);
+	}
+      else if (i386_zmm_regnum_p (gdbarch, regnum))
+	{
+	  regnum -= tdep->zmm0_regnum;
+
+	  if (regnum < num_lower_zmm_regs)
+	    {
+	      /* Extract (always little endian).  Read lower 128bits.  */
+	      status = regcache_raw_read (regcache,
+					  I387_XMM0_REGNUM (tdep) + regnum,
+					  raw_buf);
+	      if (status != REG_VALID)
+		mark_value_bytes_unavailable (result_value, 0, 16);
+	      else
+		memcpy (buf, raw_buf, 16);
+
+	      /* Extract (always little endian).  Read upper 128bits.  */
+	      status = regcache_raw_read (regcache,
+					  tdep->ymm0h_regnum + regnum,
+					  raw_buf);
+	      if (status != REG_VALID)
+		mark_value_bytes_unavailable (result_value, 16, 16);
+	      else
+		memcpy (buf + 16, raw_buf, 16);
+	    }
+	  else
+	    {
+	      /* Extract (always little endian).  Read lower 128bits.  */
+	      status = regcache_raw_read (regcache,
+					  I387_XMM16_REGNUM (tdep) + regnum
+					  - num_lower_zmm_regs,
+					  raw_buf);
+	      if (status != REG_VALID)
+		mark_value_bytes_unavailable (result_value, 0, 16);
+	      else
+		memcpy (buf, raw_buf, 16);
+
+	      /* Extract (always little endian).  Read upper 128bits.  */
+	      status = regcache_raw_read (regcache,
+					  I387_YMM16H_REGNUM (tdep) + regnum
+					  - num_lower_zmm_regs,
+					  raw_buf);
+	      if (status != REG_VALID)
+		mark_value_bytes_unavailable (result_value, 16, 16);
+	      else
+		memcpy (buf + 16, raw_buf, 16);
+	    }
+
+	  /* Read upper 256bits.  */
+	  status = regcache_raw_read (regcache,
+				      tdep->zmm0h_regnum + regnum,
+				      raw_buf);
+	  if (status != REG_VALID)
+	    mark_value_bytes_unavailable (result_value, 32, 32);
+	  else
+	    memcpy (buf + 32, raw_buf, 32);
+	}
        else if (i386_ymm_regnum_p (gdbarch, regnum))
  	{
  	  regnum -= tdep->ymm0_regnum;
@@ -3122,6 +3368,26 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
  	  else
  	    memcpy (buf + 16, raw_buf, 16);
  	}
+      else if (i386_ymm_avx512_regnum_p (gdbarch, regnum))
+	{
+	  regnum -= tdep->ymm16_regnum;
+	  /* Extract (always little endian).  Read lower 128bits.  */
+	  status = regcache_raw_read (regcache,
+				      I387_XMM16_REGNUM (tdep) + regnum,
+				      raw_buf);
+	  if (status != REG_VALID)
+	    mark_value_bytes_unavailable (result_value, 0, 16);
+	  else
+	    memcpy (buf, raw_buf, 16);
+	  /* Read upper 128bits.  */
+	  status = regcache_raw_read (regcache,
+				      tdep->ymm16h_regnum + regnum,
+				      raw_buf);
+	  if (status != REG_VALID)
+	    mark_value_bytes_unavailable (result_value, 16, 16);
+	  else
+	    memcpy (buf + 16, raw_buf, 16);
+	}
        else if (i386_word_regnum_p (gdbarch, regnum))
  	{
  	  int gpnum = regnum - tdep->ax_regnum;
@@ -3221,6 +3487,47 @@ i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
  			      I387_BND0R_REGNUM (tdep) + regnum,
  			      raw_buf);
  	}
+      else if (i386_k_regnum_p (gdbarch, regnum))
+	{
+	  regnum -= tdep->k0_regnum;
+
+	  regcache_raw_write (regcache,
+			      tdep->k0_regnum + regnum,
+			      buf);
+	}
+      else if (i386_zmm_regnum_p (gdbarch, regnum))
+	{
+	  regnum -= tdep->zmm0_regnum;
+
+	  if (regnum < num_lower_zmm_regs)
+	    {
+	      /* Write lower 128bits.  */
+	      regcache_raw_write (regcache,
+				  I387_XMM0_REGNUM (tdep) + regnum,
+				  buf);
+	      /* Write upper 128bits.  */
+	      regcache_raw_write (regcache,
+				  I387_YMM0_REGNUM (tdep) + regnum,
+				  buf + 16);
+	    }
+	  else
+	    {
+	      /* Write lower 128bits.  */
+	      regcache_raw_write (regcache,
+				  I387_XMM16_REGNUM (tdep) + regnum
+				  - num_lower_zmm_regs,
+				  buf);
+	      /* Write upper 128bits.  */
+	      regcache_raw_write (regcache,
+				  I387_YMM16H_REGNUM (tdep) + regnum
+				  - num_lower_zmm_regs,
+				  buf + 16);
+	    }
+	  /* Write upper 256bits.  */
+	  regcache_raw_write (regcache,
+			      tdep->zmm0h_regnum + regnum,
+			      buf + 32);
+	}
        else if (i386_ymm_regnum_p (gdbarch, regnum))
  	{
  	  regnum -= tdep->ymm0_regnum;
@@ -3234,6 +3541,19 @@ i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
  			     tdep->ymm0h_regnum + regnum,
  			     buf + 16);
  	}
+      else if (i386_ymm_avx512_regnum_p (gdbarch, regnum))
+	{
+	  regnum -= tdep->ymm16_regnum;
+
+	  /* ... Write lower 128bits.  */
+	  regcache_raw_write (regcache,
+			      I387_XMM16_REGNUM (tdep) + regnum,
+			      buf);
+	  /* ... Write upper 128bits.  */
+	  regcache_raw_write (regcache,
+			      tdep->ymm16h_regnum + regnum,
+			      buf + 16);
+	}
        else if (i386_word_regnum_p (gdbarch, regnum))
  	{
  	  int gpnum = regnum - tdep->ax_regnum;
@@ -4112,8 +4432,10 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
  {
    const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
    int fp_regnum_p, mmx_regnum_p, xmm_regnum_p, mxcsr_regnum_p,
-      ymm_regnum_p, ymmh_regnum_p, bndr_regnum_p, bnd_regnum_p,
-      mpx_ctrl_regnum_p;
+      ymm_regnum_p, ymmh_regnum_p, ymm_avx512_regnum_p, ymmh_avx512_regnum_p,
+      bndr_regnum_p, bnd_regnum_p, k_regnum_p, zmm_regnum_p, zmmh_regnum_p,
+      zmm_avx512_regnum_p, mpx_ctrl_regnum_p, xmm_avx512_regnum_p,
+      is_AVX512, is_AVX, is_SSE;
Please don't use capital letters in variable names.  And for
consistency's sake, use _p instead of is_, so avx512_p, avx_p, sse_p.
So avx512_p, avx_p and sse_p.
Ok, we'll update the patch accordingly.

    /* Don't include pseudo registers, except for MMX, in any register
       groups.  */
@@ -4131,18 +4453,28 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
      return mmx_regnum_p;
xmm_regnum_p = i386_xmm_regnum_p (gdbarch, regnum);
+  xmm_avx512_regnum_p = i386_xmm_avx512_regnum_p (gdbarch, regnum);
    mxcsr_regnum_p = i386_mxcsr_regnum_p (gdbarch, regnum);
    if (group == i386_sse_reggroup)
-    return xmm_regnum_p || mxcsr_regnum_p;
+    return xmm_regnum_p || xmm_avx512_regnum_p || mxcsr_regnum_p;
ymm_regnum_p = i386_ymm_regnum_p (gdbarch, regnum);
+  ymm_avx512_regnum_p = i386_ymm_avx512_regnum_p (gdbarch, regnum);
+  zmm_regnum_p = i386_zmm_regnum_p (gdbarch, regnum);
+
+  is_AVX512 = ((tdep->xcr0 & I386_XSTATE_AVX512_MASK)
+	       == I386_XSTATE_AVX512_MASK);
+  is_AVX = ((tdep->xcr0 & I386_XSTATE_AVX512_MASK)
+	    == I386_XSTATE_AVX_MASK) && !is_AVX512;
+  is_SSE = ((tdep->xcr0 & I386_XSTATE_AVX512_MASK)
+	    == I386_XSTATE_SSE_MASK) && !is_AVX512 && ! is_AVX;
+
    if (group == vector_reggroup)
      return (mmx_regnum_p
-	    || ymm_regnum_p
-	    || mxcsr_regnum_p
-	    || (xmm_regnum_p
-		&& ((tdep->xcr0 & I386_XSTATE_AVX_MASK)
-		    == I386_XSTATE_SSE_MASK)));
+	    || (zmm_regnum_p && is_AVX512)
+	    || ((ymm_regnum_p || ymm_avx512_regnum_p) && is_AVX)
+	    || ((xmm_regnum_p || xmm_avx512_regnum_p) && is_SSE)
+	    || mxcsr_regnum_p);
fp_regnum_p = (i386_fp_regnum_p (gdbarch, regnum)
  		 || i386_fpc_regnum_p (gdbarch, regnum));
@@ -4152,10 +4484,14 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
    /* For "info reg all", don't include upper YMM registers nor XMM
       registers when AVX is supported.  */
    ymmh_regnum_p = i386_ymmh_regnum_p (gdbarch, regnum);
+  ymmh_avx512_regnum_p = i386_ymmh_avx512_regnum_p (gdbarch, regnum);
+  zmmh_regnum_p = i386_zmmh_regnum_p (gdbarch, regnum);
    if (group == all_reggroup
-      && ((xmm_regnum_p
-	   && (tdep->xcr0 & I386_XSTATE_AVX))
-	  || ymmh_regnum_p))
+      && (((xmm_regnum_p || xmm_avx512_regnum_p) && !is_SSE)
+	  || ((ymm_regnum_p || ymm_avx512_regnum_p) && !is_AVX)
+	  || ymmh_regnum_p
+	  || ymmh_avx512_regnum_p
+	  || zmmh_regnum_p))
      return 0;
bnd_regnum_p = i386_bnd_regnum_p (gdbarch, regnum);
@@ -4178,11 +4514,16 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
  	    && !mmx_regnum_p
  	    && !mxcsr_regnum_p
  	    && !xmm_regnum_p
+	    && !xmm_avx512_regnum_p
  	    && !ymm_regnum_p
  	    && !ymmh_regnum_p
+	    && !ymm_avx512_regnum_p
+	    && !ymmh_avx512_regnum_p
  	    && !bndr_regnum_p
  	    && !bnd_regnum_p
-	    && !mpx_ctrl_regnum_p);
+	    && !mpx_ctrl_regnum_p
+	    && !zmm_regnum_p
+	    && !zmmh_regnum_p);
Insanity!  This architecture should have died at least a decade ago...
There's got to be a better way to do this, bet let's leave that for an
other day.
We could not agree more.


Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]