[v4,8/9] Windows gdb: Implement AVX-512 register support

Message ID 20260930151403.774660-8-ssbssa@yahoo.de
State New
Headers
Series [v4,1/9] gdb/testsuite: Add Windows replacement for aligned_alloc |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Build passed

Commit Message

Hannes Domani Sept. 30, 2026, 3:11 p.m. UTC
  Similar to commit 01f9f808e2e86187c95e7cff4aeb014a421a53ce for Linux,
this patch adds support for the Intel AVX-512 registers for 32 and 64-bit
mode on Windows.
It enables accessing registers $ymm0 - $ymm31, $zmm0 - $zmm31, and
$k0 - $k7 where they are available.

After this patch gdb.arch/i386-avx512.exp passes on windows.
---
v3:
  - merged gdb+gdbserver parts, and split again AVX/AVX-512 parts
v4:
  - Add reference to equivalent Linux commit in commit message
  - Add check for enabled xstate_features in get_context_reg_ptr of
    x86-windows-nat.c
  - Changed all NULL to nullptr
---
 gdb/NEWS                    |  4 +++-
 gdb/nat/windows-nat.c       |  4 ++--
 gdb/x86-windows-nat.c       | 40 +++++++++++++++++++++++++++++++
 gdbserver/win32-i386-low.cc | 48 ++++++++++++++++++++++++++++++++++++-
 4 files changed, 92 insertions(+), 4 deletions(-)
  

Comments

Rohr, Stephan Oct. 5, 2026, 2:08 p.m. UTC | #1
Hi Hanns,

also here, some minor findings below.

Thanks
Stephan

> -----Original Message-----
> From: Hannes Domani <ssbssa@yahoo.de>
> Sent: Wednesday, 30 September 2026 17:12
> To: gdb-patches@sourceware.org
> Subject: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
> 
> Similar to commit 01f9f808e2e86187c95e7cff4aeb014a421a53ce for Linux,

Maybe name the commit title instead of the hash.  Not sure what is best
practice for this.

> this patch adds support for the Intel AVX-512 registers for 32 and 64-bit
> mode on Windows.
> It enables accessing registers $ymm0 - $ymm31, $zmm0 - $zmm31, and
> $k0 - $k7 where they are available.
> 

Wouldn't we want to mention "It enables accessing registers
$ymm16 - $ymm31 [..]" instead?

> After this patch gdb.arch/i386-avx512.exp passes on windows.
> ---
> v3:
>   - merged gdb+gdbserver parts, and split again AVX/AVX-512 parts
> v4:
>   - Add reference to equivalent Linux commit in commit message
>   - Add check for enabled xstate_features in get_context_reg_ptr of
>     x86-windows-nat.c
>   - Changed all NULL to nullptr
> ---
>  gdb/NEWS                    |  4 +++-
>  gdb/nat/windows-nat.c       |  4 ++--
>  gdb/x86-windows-nat.c       | 40 +++++++++++++++++++++++++++++++
>  gdbserver/win32-i386-low.cc | 48
> ++++++++++++++++++++++++++++++++++++-
>  4 files changed, 92 insertions(+), 4 deletions(-)
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index da4bc811c3a..704e6a7c8ba 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -195,7 +195,9 @@ info locals
>    The s390 64-bit target (s390x-*) remains supported.
> 
>  * Support for Intel AVX registers on Windows.
> -  Support displaying and modifying Intel AVX registers $ymm0 - $ymm15.
> +  Support displaying and modifying Intel AVX registers $ymm0 - $ymm31.

AVX is limited to $ymm0 - $ymm15.  Maybe add another bullet
"Support for Intel AVX-512 registers on Windows." and list what's introduced
in this patch. 

> +  Support displaying and modifying Intel AVX-512 registers $zmm0 - $zmm31
> +  and $k0 - $k7.
> 
>  * Configure changes
> 
> diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
> index cd3c827a5d5..3940465d06b 100644
> --- a/gdb/nat/windows-nat.c
> +++ b/gdb/nat/windows-nat.c
> @@ -290,7 +290,7 @@ windows_thread_info::zero_xstate_features ()
>        if (zeroed_features == 0)
>  	return;
> 
> -      for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_AVX_ID; f++)
> +      for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_ZMM_ID; f++)
>  	{
>  	  DWORD64 flag = 1ULL << f;
>  	  if ((zeroed_features & flag) != 0)
> @@ -1373,7 +1373,7 @@ initialize_loadable ()
>      {
>        /* Available XState features masked with implemented features.  */
>        xstate_features = (GetEnabledXStateFeatures ()
> -			 & X86_XSTATE_AVX_MASK);
> +			 & X86_XSTATE_AVX_AVX512_MASK);

I think it makes sense to add a check that bits X86_XSTATE_K, X86_XSTATE_ZMM_H
and X86_XSTATE_ZMM are all set.  x86-xstate.h explicitly mentions
"AVX 512 adds three feature bits.  All three must be enabled.".  I know this is a
theoretical example but it doesn't hurt, e.g.,

if ((xstate_features & X86_XSTATE_AVX512) != X86_XSTATE_AVX512)
  xstate_features &= ~X86_XSTATE_AVX512;

>        /* The extended XState functions are only needed if the available
>  	 features exceed SSE.  */
>        if ((xstate_features & ~X86_XSTATE_SSE_MASK) == 0)
> diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
> index 1e44a45171c..afc71b4ef61 100644
> --- a/gdb/x86-windows-nat.c
> +++ b/gdb/x86-windows-nat.c
> @@ -275,6 +275,46 @@ get_context_reg_ptr (Context *context, int r,
> i386_gdbarch_tdep *tdep)
>  	(context, X86_XSTATE_AVX_ID, nullptr);
>        context_offset += 16 * (r - I387_YMM0H_REGNUM (tdep));
>      }
> +  else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
> +	   && I387_ZMM0H_REGNUM (tdep) > 0 && r >=
> I387_ZMM0H_REGNUM (tdep)
> +	   && r < I387_ZMM16H_REGNUM (tdep) && r <
> I387_ZMMENDH_REGNUM (tdep))
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_H_ID, nullptr);
> +      context_offset += 32 * (r - I387_ZMM0H_REGNUM (tdep));
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && I387_ZMM0H_REGNUM (tdep) > 0 && r >=
> I387_ZMM16H_REGNUM (tdep)
> +	   && r < I387_ZMMENDH_REGNUM (tdep))
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 32 + 64 * (r - I387_ZMM16H_REGNUM (tdep));
> +    }
> +  else if ((xstate_features & X86_XSTATE_K) != 0
> +	   && I387_K0_REGNUM (tdep) > 0 && r >= I387_K0_REGNUM (tdep)
> +	   && r < I387_KEND_REGNUM (tdep))
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_K_ID, nullptr);
> +      context_offset += 8 * (r - I387_K0_REGNUM (tdep));
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && I387_YMM16H_REGNUM (tdep) > 0 && r >=
> I387_YMM16H_REGNUM (tdep)
> +	   && r < I387_YMMH_AVX512_END_REGNUM (tdep))
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 16 + 64 * (r - I387_YMM16H_REGNUM (tdep));
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && I387_XMM16_REGNUM (tdep) > 0 && r >=
> I387_XMM16_REGNUM (tdep)
> +	   && r < I387_XMM_AVX512_END_REGNUM (tdep))
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 64 * (r - I387_XMM16_REGNUM (tdep));
> +    }
>    else
>      gdb_assert_not_reached ("invalid register number %d", r);
> 
> diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
> index 1a45b15e0cf..8c62787a31b 100644
> --- a/gdbserver/win32-i386-low.cc
> +++ b/gdbserver/win32-i386-low.cc
> @@ -515,8 +515,11 @@ get_context_reg_ptr (Context *context, int r, const
> target_desc *tdesc)
>        amd64 = false;
>      }
> 
> -  int ymm0h_regnum;
> +  int ymm0h_regnum, zmm0h_regnum, k0_regnum;
> +  int xmm16_regnum, ymm16h_regnum, zmm16h_regnum;
>    const int num_xmm_registers = amd64 ? 16 : 8;
> +  const int num_zmm_high_registers = amd64 ? 16 : 0;
> +  const int num_avx512_k_registers = 8;
> 
>    char *context_offset;
>    if (r < mappings_count)
> @@ -529,6 +532,49 @@ get_context_reg_ptr (Context *context, int r, const
> target_desc *tdesc)
>  	(context, X86_XSTATE_AVX_ID, nullptr);
>        context_offset += 16 * (r - ymm0h_regnum);
>      }
> +  else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
> +	   && r >= (zmm0h_regnum = find_regno (tdesc, "zmm0h"))
> +	   && r < zmm0h_regnum + num_xmm_registers)
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_H_ID, nullptr);
> +      context_offset += 32 * (r - zmm0h_regnum);
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && num_zmm_high_registers != 0
> +	   && r >= (zmm16h_regnum = find_regno (tdesc, "zmm16h"))
> +	   && r < zmm16h_regnum + num_zmm_high_registers)
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 32 + 64 * (r - zmm16h_regnum);
> +    }
> +  else if ((xstate_features & X86_XSTATE_K) != 0
> +	   && r >= (k0_regnum = find_regno (tdesc, "k0"))
> +	   && r < k0_regnum + num_avx512_k_registers)
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_K_ID, nullptr);
> +      context_offset += 8 * (r - k0_regnum);
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && num_zmm_high_registers != 0
> +	   && r >= (ymm16h_regnum = find_regno (tdesc, "ymm16h"))
> +	   && r < ymm16h_regnum + num_zmm_high_registers)
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 16 + 64 * (r - ymm16h_regnum);
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && num_zmm_high_registers != 0
> +	   && r >= (xmm16_regnum = find_regno (tdesc, "xmm16"))
> +	   && r < xmm16_regnum + num_zmm_high_registers)
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 64 * (r - xmm16_regnum);
> +    }
>    else
>      gdb_assert_not_reached ("invalid register number %d", r);
> 
> --
> 2.55.0

________________________________________
Intel Deutschland GmbH 

Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany 

Tel: +49 (89) 99143-0 

www.intel.de 

Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman

Chairperson of the Supervisory Board: Sonja Pierer

Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
  

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index da4bc811c3a..704e6a7c8ba 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -195,7 +195,9 @@  info locals
   The s390 64-bit target (s390x-*) remains supported.
 
 * Support for Intel AVX registers on Windows.
-  Support displaying and modifying Intel AVX registers $ymm0 - $ymm15.
+  Support displaying and modifying Intel AVX registers $ymm0 - $ymm31.
+  Support displaying and modifying Intel AVX-512 registers $zmm0 - $zmm31
+  and $k0 - $k7.
 
 * Configure changes
 
diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index cd3c827a5d5..3940465d06b 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -290,7 +290,7 @@  windows_thread_info::zero_xstate_features ()
       if (zeroed_features == 0)
 	return;
 
-      for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_AVX_ID; f++)
+      for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_ZMM_ID; f++)
 	{
 	  DWORD64 flag = 1ULL << f;
 	  if ((zeroed_features & flag) != 0)
@@ -1373,7 +1373,7 @@  initialize_loadable ()
     {
       /* Available XState features masked with implemented features.  */
       xstate_features = (GetEnabledXStateFeatures ()
-			 & X86_XSTATE_AVX_MASK);
+			 & X86_XSTATE_AVX_AVX512_MASK);
       /* The extended XState functions are only needed if the available
 	 features exceed SSE.  */
       if ((xstate_features & ~X86_XSTATE_SSE_MASK) == 0)
diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
index 1e44a45171c..afc71b4ef61 100644
--- a/gdb/x86-windows-nat.c
+++ b/gdb/x86-windows-nat.c
@@ -275,6 +275,46 @@  get_context_reg_ptr (Context *context, int r, i386_gdbarch_tdep *tdep)
 	(context, X86_XSTATE_AVX_ID, nullptr);
       context_offset += 16 * (r - I387_YMM0H_REGNUM (tdep));
     }
+  else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
+	   && I387_ZMM0H_REGNUM (tdep) > 0 && r >= I387_ZMM0H_REGNUM (tdep)
+	   && r < I387_ZMM16H_REGNUM (tdep) && r < I387_ZMMENDH_REGNUM (tdep))
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_H_ID, nullptr);
+      context_offset += 32 * (r - I387_ZMM0H_REGNUM (tdep));
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && I387_ZMM0H_REGNUM (tdep) > 0 && r >= I387_ZMM16H_REGNUM (tdep)
+	   && r < I387_ZMMENDH_REGNUM (tdep))
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 32 + 64 * (r - I387_ZMM16H_REGNUM (tdep));
+    }
+  else if ((xstate_features & X86_XSTATE_K) != 0
+	   && I387_K0_REGNUM (tdep) > 0 && r >= I387_K0_REGNUM (tdep)
+	   && r < I387_KEND_REGNUM (tdep))
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_K_ID, nullptr);
+      context_offset += 8 * (r - I387_K0_REGNUM (tdep));
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && I387_YMM16H_REGNUM (tdep) > 0 && r >= I387_YMM16H_REGNUM (tdep)
+	   && r < I387_YMMH_AVX512_END_REGNUM (tdep))
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 16 + 64 * (r - I387_YMM16H_REGNUM (tdep));
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && I387_XMM16_REGNUM (tdep) > 0 && r >= I387_XMM16_REGNUM (tdep)
+	   && r < I387_XMM_AVX512_END_REGNUM (tdep))
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 64 * (r - I387_XMM16_REGNUM (tdep));
+    }
   else
     gdb_assert_not_reached ("invalid register number %d", r);
 
diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
index 1a45b15e0cf..8c62787a31b 100644
--- a/gdbserver/win32-i386-low.cc
+++ b/gdbserver/win32-i386-low.cc
@@ -515,8 +515,11 @@  get_context_reg_ptr (Context *context, int r, const target_desc *tdesc)
       amd64 = false;
     }
 
-  int ymm0h_regnum;
+  int ymm0h_regnum, zmm0h_regnum, k0_regnum;
+  int xmm16_regnum, ymm16h_regnum, zmm16h_regnum;
   const int num_xmm_registers = amd64 ? 16 : 8;
+  const int num_zmm_high_registers = amd64 ? 16 : 0;
+  const int num_avx512_k_registers = 8;
 
   char *context_offset;
   if (r < mappings_count)
@@ -529,6 +532,49 @@  get_context_reg_ptr (Context *context, int r, const target_desc *tdesc)
 	(context, X86_XSTATE_AVX_ID, nullptr);
       context_offset += 16 * (r - ymm0h_regnum);
     }
+  else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
+	   && r >= (zmm0h_regnum = find_regno (tdesc, "zmm0h"))
+	   && r < zmm0h_regnum + num_xmm_registers)
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_H_ID, nullptr);
+      context_offset += 32 * (r - zmm0h_regnum);
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && num_zmm_high_registers != 0
+	   && r >= (zmm16h_regnum = find_regno (tdesc, "zmm16h"))
+	   && r < zmm16h_regnum + num_zmm_high_registers)
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 32 + 64 * (r - zmm16h_regnum);
+    }
+  else if ((xstate_features & X86_XSTATE_K) != 0
+	   && r >= (k0_regnum = find_regno (tdesc, "k0"))
+	   && r < k0_regnum + num_avx512_k_registers)
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_K_ID, nullptr);
+      context_offset += 8 * (r - k0_regnum);
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && num_zmm_high_registers != 0
+	   && r >= (ymm16h_regnum = find_regno (tdesc, "ymm16h"))
+	   && r < ymm16h_regnum + num_zmm_high_registers)
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 16 + 64 * (r - ymm16h_regnum);
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && num_zmm_high_registers != 0
+	   && r >= (xmm16_regnum = find_regno (tdesc, "xmm16"))
+	   && r < xmm16_regnum + num_zmm_high_registers)
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 64 * (r - xmm16_regnum);
+    }
   else
     gdb_assert_not_reached ("invalid register number %d", r);