[v4,6/7] x86: add ACE v1 support for tile move instructions

Message ID b117c00537d1b432398465a95a36320ce935989d.1790705096.git.RohanRadhesh.Shenoy@amd.com
State New
Headers
Series x86: add ACE V1 ISA support |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

Shenoy, Rohan Radhesh Sept. 29, 2026, 6:30 p.m. UTC
  Enable assembly and disassembly support for TILEMOVROW and TILEMOVCOL.
Their register selector is always 32-bit, but using VexGdq prints a 64-bit
register when W=1, hence we use VexGd instead.

Reference: AI Compute Extensions (ACE) Specification, v1.16.2
https://x86ecosystem.org/wp-content/uploads/2026/06/ACE_v1_Specification_public.pdf

Co-authored-by: Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com>
Co-authored-by: Umesh Kalvakuntla <Umesh.Kalvakuntla@amd.com>
---
 gas/testsuite/gas/i386/x86-64-ace_v1.d |  4 +++
 gas/testsuite/gas/i386/x86-64-ace_v1.s |  4 +++
 opcodes/i386-dis-evex-len.h            | 23 ++++++++++++++++
 opcodes/i386-dis-evex-prefix.h         | 36 +++++++++++++++++++++-----
 opcodes/i386-dis-evex-w.h              | 12 +++++++++
 opcodes/i386-dis-evex-x86-64.h         |  5 ++++
 opcodes/i386-dis-evex.h                |  2 +-
 opcodes/i386-dis.c                     | 15 +++++++++++
 opcodes/i386-opc.tbl                   |  5 ++++
 9 files changed, 99 insertions(+), 7 deletions(-)
  

Comments

Jan Beulich Oct. 2, 2026, 9:22 a.m. UTC | #1
On 29.09.2026 20:30, Rohan Shenoy wrote:
> @@ -112,6 +121,13 @@ static const struct dis386 evex_len_table[][3] = {
>      { PREFIX_TABLE (PREFIX_EVEX_0F3A07_X86_64_W_0_L_2) },
>    },
>  
> +  /* EVEX_LEN_0F3A07_X86_64_W_1 */
> +  {
> +    { Bad_Opcode },
> +    { Bad_Opcode },
> +    { PREFIX_TABLE (PREFIX_EVEX_0F3A07_X86_64_W_1_L_2) },
> +  },

Decode for this opcode would apparently benefit from swapping decode
of L'L and W, much like I said in reply to patch 5 as well.

> @@ -14271,6 +14282,10 @@ OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
>  
>        return true;
>  
> +    case d_mode:
> +      oappend_register (ins, att_names32[reg]);
> +      return true;
> +
>      case v_mode:
>      case dq_mode:
>        if (ins->rex & REX_W)

Please can this new case block move down a little, between b_mode and
q_mode handling?

Jan
  

Patch

diff --git a/gas/testsuite/gas/i386/x86-64-ace_v1.d b/gas/testsuite/gas/i386/x86-64-ace_v1.d
index 256792a8248..030a5dd4425 100644
--- a/gas/testsuite/gas/i386/x86-64-ace_v1.d
+++ b/gas/testsuite/gas/i386/x86-64-ace_v1.d
@@ -14,6 +14,10 @@  Disassembly of section \.text:
 [ 	]*[a-f0-9]+:[ 	]*c4 e2 78 49 c0[ 	]+tilerelease
 [ 	]*[a-f0-9]+:[ 	]*62 f2 65 48 4a ca[ 	]+tilemovrow %ebx,%tmm2,%zmm1
 [ 	]*[a-f0-9]+:[ 	]*62 f3 7d 48 07 ca 08[ 	]+tilemovrow \$0x8,%tmm2,%zmm1
+[ 	]*[a-f0-9]+:[ 	]*62 f2 e5 48 4a ca[ 	]+tilemovrow %ebx,%zmm2,%tmm1
+[ 	]*[a-f0-9]+:[ 	]*62 f3 fd 48 07 ca 08[ 	]+tilemovrow \$0x8,%zmm2,%tmm1
+[ 	]*[a-f0-9]+:[ 	]*62 f2 e5 48 4b ca[ 	]+tilemovcol %ebx,%zmm2,%tmm1
+[ 	]*[a-f0-9]+:[ 	]*62 f3 fd 48 2f ca 08[ 	]+tilemovcol \$0x8,%zmm2,%tmm1
 [ 	]*[a-f0-9]+:[ 	]*62 62 6e 48 4a f5[ 	]+tcvtrowd2ps %edx,%tmm5,%zmm30
 [ 	]*[a-f0-9]+:[ 	]*62 63 7e 48 07 f5 08[ 	]+tcvtrowd2ps \$0x8,%tmm5,%zmm30
 [ 	]*[a-f0-9]+:[ 	]*62 62 6f 48 6d f5[ 	]+tcvtrowps2bf16h %edx,%tmm5,%zmm30
diff --git a/gas/testsuite/gas/i386/x86-64-ace_v1.s b/gas/testsuite/gas/i386/x86-64-ace_v1.s
index 4bb4152789a..76bf8b5b927 100644
--- a/gas/testsuite/gas/i386/x86-64-ace_v1.s
+++ b/gas/testsuite/gas/i386/x86-64-ace_v1.s
@@ -9,6 +9,10 @@  start:
 
 	tilemovrow %ebx, %tmm2, %zmm1
 	tilemovrow $8, %tmm2, %zmm1
+	tilemovrow %ebx, %zmm2, %tmm1
+	tilemovrow $8, %zmm2, %tmm1
+	tilemovcol %ebx, %zmm2, %tmm1
+	tilemovcol $8, %zmm2, %tmm1
 
 	tcvtrowd2ps     %edx, %tmm5, %zmm30
 	tcvtrowd2ps     $8, %tmm5, %zmm30
diff --git a/opcodes/i386-dis-evex-len.h b/opcodes/i386-dis-evex-len.h
index 178ad1c3ff0..7adc8c2081e 100644
--- a/opcodes/i386-dis-evex-len.h
+++ b/opcodes/i386-dis-evex-len.h
@@ -51,9 +51,18 @@  static const struct dis386 evex_len_table[][3] = {
     { PREFIX_TABLE (PREFIX_EVEX_0F384A_X86_64_W_0_L_2) },
   },
 
+  /* EVEX_LEN_0F384A_X86_64_W_1 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_EVEX_0F384A_X86_64_W_1_L_2) },
+  },
+
   /* EVEX_LEN_0F384B_X86_64 */
   {
     { X86_64_EVEX_MEM_W_TABLE (VEX_W_0F384B_X86_64_L_0) },
+    { Bad_Opcode },
+    { VEX_W_TABLE (EVEX_W_0F384B_X86_64_L_2) },
   },
 
   /* EVEX_LEN_0F385A */
@@ -112,6 +121,13 @@  static const struct dis386 evex_len_table[][3] = {
     { PREFIX_TABLE (PREFIX_EVEX_0F3A07_X86_64_W_0_L_2) },
   },
 
+  /* EVEX_LEN_0F3A07_X86_64_W_1 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_EVEX_0F3A07_X86_64_W_1_L_2) },
+  },
+
   /* EVEX_LEN_0F3A18 */
   {
     { Bad_Opcode },
@@ -147,6 +163,13 @@  static const struct dis386 evex_len_table[][3] = {
     { VEX_W_TABLE (EVEX_W_0F3A23_L_n) },
   },
 
+  /* EVEX_LEN_0F3A2F_X86_64_W_1 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_EVEX_0F3A2F_X86_64_W_1_L_2) },
+  },
+
   /* EVEX_LEN_0F3A38 */
   {
     { Bad_Opcode },
diff --git a/opcodes/i386-dis-evex-prefix.h b/opcodes/i386-dis-evex-prefix.h
index 9ec02d184a3..9a1e2ba984f 100644
--- a/opcodes/i386-dis-evex-prefix.h
+++ b/opcodes/i386-dis-evex-prefix.h
@@ -251,8 +251,20 @@ 
   /* PREFIX_EVEX_0F384A_W_0_L_2 */
   {
     { Bad_Opcode },
-    { "tcvtrowd2ps",	{ XM, Rtmm, VexGdq }, 0 },
-    { "tilemovrow",	{ XM, Rtmm, VexGdq }, 0 },
+    { "tcvtrowd2ps",	{ XM, Rtmm, VexGd }, 0 },
+    { "tilemovrow",	{ XM, Rtmm, VexGd }, 0 },
+  },
+  /* PREFIX_EVEX_0F384A_X86_64_W_1_L_2 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "tilemovrow",	{ TMM, Ux, VexGd }, 0 },
+  },
+  /* PREFIX_EVEX_0F384B_X86_64_W_1_L_2 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "tilemovcol",	{ TMM, Ux, VexGd }, 0 },
   },
   /* PREFIX_EVEX_0F3852 */
   {
@@ -277,10 +289,10 @@ 
   },
   /* PREFIX_EVEX_0F386D_W_0_L_2 */
   {
-    { "tcvtrowps2phh",	{ XM, Rtmm, VexGdq }, 0 },
-    { "tcvtrowps2bf16l",	{ XM, Rtmm, VexGdq }, 0 },
-    { "tcvtrowps2phl",	{ XM, Rtmm, VexGdq }, 0 },
-    { "tcvtrowps2bf16h",	{ XM, Rtmm, VexGdq }, 0 },
+    { "tcvtrowps2phh",	{ XM, Rtmm, VexGd }, 0 },
+    { "tcvtrowps2bf16l",	{ XM, Rtmm, VexGd }, 0 },
+    { "tcvtrowps2phl",	{ XM, Rtmm, VexGd }, 0 },
+    { "tcvtrowps2bf16h",	{ XM, Rtmm, VexGd }, 0 },
   },
   /* PREFIX_EVEX_0F3872 */
   {
@@ -331,6 +343,12 @@ 
     { "tilemovrow",	{ XM, Rtmm, Ib }, 0 },
     { "tcvtrowps2bf16h",	{ XM, Rtmm, Ib }, 0 },
   },
+  /* PREFIX_EVEX_0F3A07_X86_64_W_1_L_2 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "tilemovrow",	{ TMM, Ux, Ib }, 0 },
+  },
   /* PREFIX_EVEX_0F3A08 */
   {
     { "vrndscalep%XH",  { XM, EXxh, EXxEVexS, Ib }, 0 },
@@ -357,6 +375,12 @@ 
     { Bad_Opcode },
     { "vgetmants%XW",	{ XMScalar, VexScalar, EXdq, EXxEVexS, Ib }, 0 },
   },
+  /* PREFIX_EVEX_0F3A2F_X86_64_W_1_L_2 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "tilemovcol",	{ TMM, Ux, Ib }, 0 },
+  },
   /* PREFIX_EVEX_0F3A42_W_0 */
   {
     { Bad_Opcode },
diff --git a/opcodes/i386-dis-evex-w.h b/opcodes/i386-dis-evex-w.h
index 0d8ccb1769e..589745fb628 100644
--- a/opcodes/i386-dis-evex-w.h
+++ b/opcodes/i386-dis-evex-w.h
@@ -353,6 +353,12 @@ 
   /* EVEX_W_0F384A_X86_64 */
   {
     { EVEX_LEN_TABLE (EVEX_LEN_0F384A_X86_64_W_0) },
+    { EVEX_LEN_TABLE (EVEX_LEN_0F384A_X86_64_W_1) },
+  },
+  /* EVEX_W_0F384B_X86_64_L_2 */
+  {
+    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_EVEX_0F384B_X86_64_W_1_L_2) },
   },
   /* EVEX_W_0F3859 */
   {
@@ -399,6 +405,7 @@ 
   /* EVEX_W_0F3A07_X86_64 */
   {
     { EVEX_LEN_TABLE (EVEX_LEN_0F3A07_X86_64_W_0) },
+    { EVEX_LEN_TABLE (EVEX_LEN_0F3A07_X86_64_W_1) },
   },
   /* EVEX_W_0F3A18_L_n */
   {
@@ -429,6 +436,11 @@ 
     { "vshuff32x4",	{ XM, Vex, EXx, Ib }, PREFIX_DATA },
     { "vshuff64x2",	{ XM, Vex, EXx, Ib }, PREFIX_DATA },
   },
+  /* EVEX_W_0F3A2F_X86_64 */
+  {
+    { Bad_Opcode },
+    { EVEX_LEN_TABLE (EVEX_LEN_0F3A2F_X86_64_W_1) },
+  },
   /* EVEX_W_0F3A38_L_n */
   {
     { "vinserti32x4",	{ XM, Vex, EXxmm, Ib }, PREFIX_DATA },
diff --git a/opcodes/i386-dis-evex-x86-64.h b/opcodes/i386-dis-evex-x86-64.h
index c59e12657de..79b2ed618c5 100644
--- a/opcodes/i386-dis-evex-x86-64.h
+++ b/opcodes/i386-dis-evex-x86-64.h
@@ -18,6 +18,11 @@ 
     { Bad_Opcode },
     { VEX_W_TABLE (EVEX_W_0F3A07_X86_64) },
   },
+  /* X86_64_EVEX_0F3A2F */
+  {
+    { Bad_Opcode },
+    { VEX_W_TABLE (EVEX_W_0F3A2F_X86_64) },
+  },
   /* X86_64_EVEX_0F3A77 */
   {
     { Bad_Opcode },
diff --git a/opcodes/i386-dis-evex.h b/opcodes/i386-dis-evex.h
index 283287b6138..9e92abba55c 100644
--- a/opcodes/i386-dis-evex.h
+++ b/opcodes/i386-dis-evex.h
@@ -636,7 +636,7 @@  static const struct dis386 evex_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { Bad_Opcode },
+    { X86_64_TABLE (X86_64_EVEX_0F3A2F) },
     /* 30 */
     { Bad_Opcode },
     { Bad_Opcode },
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index a9377a6f0da..fdd165f2e05 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -600,6 +600,7 @@  fetch_error (const instr_info *ins)
 #define VexGatherD { OP_VEX, vex_vsib_d_w_dq_mode }
 #define VexGatherQ { OP_VEX, vex_vsib_q_w_dq_mode }
 #define VexGdq { OP_VEX, dq_mode }
+#define VexGd { OP_VEX, d_mode }
 #define VexGb { OP_VEX, b_mode }
 #define VexGv { OP_VEX, v_mode }
 #define VexTmm { OP_VEX, tmm_mode }
@@ -1220,6 +1221,8 @@  enum
   PREFIX_EVEX_0F383A,
   PREFIX_EVEX_0F3841_W_0,
   PREFIX_EVEX_0F384A_X86_64_W_0_L_2,
+  PREFIX_EVEX_0F384A_X86_64_W_1_L_2,
+  PREFIX_EVEX_0F384B_X86_64_W_1_L_2,
   PREFIX_EVEX_0F3852,
   PREFIX_EVEX_0F3853,
   PREFIX_EVEX_0F3868,
@@ -1232,10 +1235,12 @@  enum
   PREFIX_EVEX_0F38AB,
 
   PREFIX_EVEX_0F3A07_X86_64_W_0_L_2,
+  PREFIX_EVEX_0F3A07_X86_64_W_1_L_2,
   PREFIX_EVEX_0F3A08,
   PREFIX_EVEX_0F3A0A,
   PREFIX_EVEX_0F3A26,
   PREFIX_EVEX_0F3A27,
+  PREFIX_EVEX_0F3A2F_X86_64_W_1_L_2,
   PREFIX_EVEX_0F3A42_W_0,
   PREFIX_EVEX_0F3A52,
   PREFIX_EVEX_0F3A53,
@@ -1415,6 +1420,7 @@  enum
   X86_64_EVEX_0F384B,
   X86_64_EVEX_0F386D,
   X86_64_EVEX_0F3A07,
+  X86_64_EVEX_0F3A2F,
   X86_64_EVEX_0F3A77,
 
   X86_64_EVEX_MAP5_6F,
@@ -1614,6 +1620,7 @@  enum
   EVEX_LEN_0F381B,
   EVEX_LEN_0F3836,
   EVEX_LEN_0F384A_X86_64_W_0,
+  EVEX_LEN_0F384A_X86_64_W_1,
   EVEX_LEN_0F384B_X86_64,
   EVEX_LEN_0F385A,
   EVEX_LEN_0F385B,
@@ -1623,11 +1630,13 @@  enum
   EVEX_LEN_0F3A00,
   EVEX_LEN_0F3A01,
   EVEX_LEN_0F3A07_X86_64_W_0,
+  EVEX_LEN_0F3A07_X86_64_W_1,
   EVEX_LEN_0F3A18,
   EVEX_LEN_0F3A19,
   EVEX_LEN_0F3A1A,
   EVEX_LEN_0F3A1B,
   EVEX_LEN_0F3A23,
+  EVEX_LEN_0F3A2F_X86_64_W_1,
   EVEX_LEN_0F3A38,
   EVEX_LEN_0F3A39,
   EVEX_LEN_0F3A3A,
@@ -1855,6 +1864,7 @@  enum
   EVEX_W_0F383A_P_1,
   EVEX_W_0F3841,
   EVEX_W_0F384A_X86_64,
+  EVEX_W_0F384B_X86_64_L_2,
   EVEX_W_0F3859,
   EVEX_W_0F385A_L_n,
   EVEX_W_0F385B_L_2,
@@ -1872,6 +1882,7 @@  enum
   EVEX_W_0F3A1B_L_2,
   EVEX_W_0F3A21,
   EVEX_W_0F3A23_L_n,
+  EVEX_W_0F3A2F_X86_64,
   EVEX_W_0F3A38_L_n,
   EVEX_W_0F3A39_L_n,
   EVEX_W_0F3A3A_L_2,
@@ -14271,6 +14282,10 @@  OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
 
       return true;
 
+    case d_mode:
+      oappend_register (ins, att_names32[reg]);
+      return true;
+
     case v_mode:
     case dq_mode:
       if (ins->rex & REX_W)
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index f1fa86b76c3..7eeb5219d04 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -3325,6 +3325,11 @@  bsrmovf, 0x95, ACE_V1, Modrm|EVex512|Map6|VexW1|Src1VVVV|Disp8MemShift=6|NoSuf,
 bsrmovh, 0xf295, ACE_V1, D|Modrm|EVex512|Map6|VexW1|Disp8MemShift=6|NoSuf, { RegZMM|Unspecified|BaseIndex, RegBSR }
 bsrmovl, 0xf395, ACE_V1, D|Modrm|EVex512|Map6|VexW1|Disp8MemShift=6|NoSuf, { RegZMM|Unspecified|BaseIndex, RegBSR }
 
+tilemovcol, 0x662f, ACE_V1, Modrm|EVex512|Space0F3A|VexW1|NoSuf, { Imm8, RegZMM, RegTMM }
+tilemovcol, 0x664b, ACE_V1, Modrm|EVex512|Space0F38|VexW1|Src2VVVV|NoSuf, { Reg32, RegZMM, RegTMM }
+tilemovrow, 0x6607, ACE_V1, Modrm|EVex512|Space0F3A|VexW1|NoSuf, { Imm8, RegZMM, RegTMM }
+tilemovrow, 0x664a, ACE_V1, Modrm|EVex512|Space0F38|VexW1|Src2VVVV|NoSuf, { Reg32, RegZMM, RegTMM }
+
 // ACE instructions end.
 
 // KEYLOCKER instructions.