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.


> 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.

> 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?

> 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"?

> +
> +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.

>    /* 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.


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