This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH v2 1/3] Add AVX512 registers support to GDB.
- From: Mark Kettenis <mark dot kettenis at xs4all dot nl>
- To: michael dot sturm at intel dot com
- Cc: palves at redhat dot com, eliz at gnu dot org, mark dot kettenis at xs4all dot nl, walfred dot tedeschi at intel dot com, gdb-patches at sourceware dot org, michael dot sturm at intel dot com
- Date: Sun, 23 Feb 2014 23:52:47 +0100 (CET)
- Subject: Re: [PATCH v2 1/3] Add AVX512 registers support to GDB.
- Authentication-results: sourceware.org; auth=none
- References: <1392907965-32637-1-git-send-email-michael dot sturm at intel dot com> <1392907965-32637-2-git-send-email-michael dot sturm at intel dot com>
> 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.