Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AArch64] Add assembly/disassembly for multi-vector AES instructions #113307

Merged
merged 1 commit into from
Oct 24, 2024

Conversation

SpencerAbson
Copy link
Contributor

@SpencerAbson SpencerAbson commented Oct 22, 2024

This patch adds assembly/disassembly for the following multi-vector SVE instructions

  - AESE (two/four registers)
  - AESD (two/four registers)
  - AESDIMC (two/four registers)
  - AESEMC (two/four registers)

…ions

- Add assembly/disassembly for the following instructions
	- AESE (two/four, four registers)
	- AESD (two/four, four registers)
	- AESDIMC (two/four registers)
	- AESEMC (two/four registers)

- Introduce assembler extension tests for the new Armv9.6 sve-aes2 and ssve-aes features
- In accordance with: https://developer.arm.com/documentation/ddi0602/latest/
@llvmbot
Copy link
Member

llvmbot commented Oct 22, 2024

@llvm/pr-subscribers-backend-aarch64

@llvm/pr-subscribers-mc

Author: None (SpencerAbson)

Changes

This patch adds assembly/disassembly for the following instructions

  - AESE (two/four, four registers)
  - AESD (two/four, four registers)
  - AESDIMC (two/four registers)
  - AESEMC (two/four registers)

Patch is 38.04 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/113307.diff

19 Files Affected:

  • (modified) llvm/lib/Target/AArch64/AArch64.td (+1-1)
  • (modified) llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td (+13)
  • (modified) llvm/lib/Target/AArch64/SVEInstrFormats.td (+48)
  • (modified) llvm/test/MC/AArch64/SME2p1/directive-arch-negative.s (+6)
  • (modified) llvm/test/MC/AArch64/SME2p1/directive-arch.s (+4)
  • (modified) llvm/test/MC/AArch64/SME2p1/directive-arch_extension-negative.s (+8-1)
  • (modified) llvm/test/MC/AArch64/SME2p1/directive-arch_extension.s (+6-1)
  • (added) llvm/test/MC/AArch64/SVE2p1/aesd-diagnostics.s (+83)
  • (added) llvm/test/MC/AArch64/SVE2p1/aesd.s (+53)
  • (added) llvm/test/MC/AArch64/SVE2p1/aesdimc-diagnostics.s (+83)
  • (added) llvm/test/MC/AArch64/SVE2p1/aesdimc.s (+54)
  • (added) llvm/test/MC/AArch64/SVE2p1/aese-diagnostics.s (+83)
  • (added) llvm/test/MC/AArch64/SVE2p1/aese.s (+53)
  • (added) llvm/test/MC/AArch64/SVE2p1/aesemc-diagnostics.s (+83)
  • (added) llvm/test/MC/AArch64/SVE2p1/aesemc.s (+53)
  • (modified) llvm/test/MC/AArch64/SVE2p1/directive-arch-negative.s (+6)
  • (modified) llvm/test/MC/AArch64/SVE2p1/directive-arch.s (+5-1)
  • (modified) llvm/test/MC/AArch64/SVE2p1/directive-arch_extension-negative.s (+7-1)
  • (modified) llvm/test/MC/AArch64/SVE2p1/directive-arch_extension.s (+5-1)
diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td
index cdfbd3db64736f..2262ad1dfd0cc9 100644
--- a/llvm/lib/Target/AArch64/AArch64.td
+++ b/llvm/lib/Target/AArch64/AArch64.td
@@ -73,7 +73,7 @@ def SVEUnsupported : AArch64Unsupported {
                       SVE2Unsupported.F);
 }
 
-let F = [HasSME2p1, HasSVE2p1_or_HasSME2p1] in
+let F = [HasSME2p1, HasSVE2p1_or_HasSME2p1, HasSVE2p1orSSVE_AES] in
 def SME2p1Unsupported : AArch64Unsupported;
 
 def SME2Unsupported : AArch64Unsupported {
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index 2a857234c7d745..1c5f7953e327ca 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -3917,6 +3917,19 @@ let Predicates = [HasSVE2BitPerm] in {
   defm BGRP_ZZZ : sve2_misc_bitwise<0b1110, "bgrp", int_aarch64_sve_bgrp_x>;
 } // End HasSVE2BitPerm
 
+let Predicates = [HasSVEAES2, HasSVE2p1orSSVE_AES] in {
+  // SVE_AES2 multi-vector instructions (x2)
+  def AESE_2ZZI_B    : sve_crypto_binary_multi2<0b000, "aese">;
+  def AESD_2ZZI_B    : sve_crypto_binary_multi2<0b010, "aesd">;
+  def AESEMC_2ZZI_B  : sve_crypto_binary_multi2<0b100, "aesemc">;
+  def AESDMIC_2ZZI_B : sve_crypto_binary_multi2<0b110, "aesdimc">;
+  // SVE_AES2 multi-vector instructions (x4)
+  def AESE_4ZZI_B    : sve_crypto_binary_multi4<0b0000, "aese">;
+  def AESD_4ZZI_B    : sve_crypto_binary_multi4<0b0100, "aesd">;
+  def AESEMC_4ZZI_B  : sve_crypto_binary_multi4<0b1000, "aesemc">;
+  def AESDMIC_4ZZI_B : sve_crypto_binary_multi4<0b1100, "aesdimc">;
+} // End HasSVEAES2, HasSVE2p1orSSVE_AES
+
 //===----------------------------------------------------------------------===//
 // SME or SVE2.1 instructions
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td
index f655526fa81cfe..3a75ec6a1e5a2d 100644
--- a/llvm/lib/Target/AArch64/SVEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td
@@ -8698,6 +8698,54 @@ multiclass sve2_crypto_unary_op<bit opc, string asm, SDPatternOperator op> {
   def : SVE_1_Op_Pat<nxv16i8, op, nxv16i8, !cast<Instruction>(NAME)>;
 }
 
+class sve_crypto_binary_multi2<bits<3> opc, string asm>
+: I<(outs ZZ_b_mul_r:$Zdn),
+    (ins ZZ_b_mul_r:$_Zdn, ZPR128:$Zm, VectorIndexS32b_timm:$imm2),
+  asm,
+  "\t$Zdn, $_Zdn, $Zm$imm2",
+  "",
+  []>, Sched<[]> {
+  bits<5> Zm;
+  bits<4> Zdn;
+  bits<2> imm2;
+  let Inst{31-21} = 0b01000101001;
+  let Inst{20-19} = imm2;
+  let Inst{18-17} = 0b01;
+  let Inst{16}    = opc{2};
+  let Inst{15-11} = 0b11101;
+  let Inst{10}    = opc{1};
+  let Inst{9-5}   = Zm;
+  let Inst{4-1}   = Zdn;
+  let Inst{0}     = opc{0};
+
+  let Constraints = "$Zdn = $_Zdn";
+  let hasSideEffects = 0;
+}
+
+class sve_crypto_binary_multi4<bits<4> opc, string asm>
+: I<(outs ZZZZ_b_mul_r:$Zdn),
+    (ins ZZZZ_b_mul_r:$_Zdn, ZPR128:$Zm, VectorIndexS32b_timm:$imm2),
+  asm,
+  "\t$Zdn, $_Zdn, $Zm$imm2",
+  "",
+  []>, Sched<[]> {
+  bits<5> Zm;
+  bits<3> Zdn;
+  bits<2> imm2;
+  let Inst{31-21} = 0b01000101001;
+  let Inst{20-19} = imm2;
+  let Inst{18-17} = 0b11;
+  let Inst{16}    = opc{3};
+  let Inst{15-11} = 0b11101;
+  let Inst{10}    = opc{2};
+  let Inst{9-5}   = Zm;
+  let Inst{4-2}   = Zdn;
+  let Inst{1-0}   = opc{1-0};
+
+  let Constraints = "$Zdn = $_Zdn";
+  let hasSideEffects = 0;
+}
+
 //===----------------------------------------------------------------------===//
 // SVE BFloat16 Group
 //===----------------------------------------------------------------------===//
diff --git a/llvm/test/MC/AArch64/SME2p1/directive-arch-negative.s b/llvm/test/MC/AArch64/SME2p1/directive-arch-negative.s
index 87ac6e3f34ae74..06bc5ec2339789 100644
--- a/llvm/test/MC/AArch64/SME2p1/directive-arch-negative.s
+++ b/llvm/test/MC/AArch64/SME2p1/directive-arch-negative.s
@@ -17,3 +17,9 @@ bfclamp { z0.h, z1.h }, z0.h, z0.h
 bfadd za.h[w8, 3], {z20.h-z21.h}
 // CHECK: error: instruction requires: sme-b16b16
 // CHECK: bfadd za.h[w8, 3], {z20.h-z21.h} 
+
+.arch armv9-a+sve-aes2+ssve-aes
+.arch armv9-a+nossve-aes
+aesdimc {z0.b-z3.b}, {z0.b-z3.b}, z0.q[0]
+// CHECK: error: instruction requires: sve2p1 or ssve-aes sve-aes2
+// CHECK: aesdimc {z0.b-z3.b}, {z0.b-z3.b}, z0.q[0]
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SME2p1/directive-arch.s b/llvm/test/MC/AArch64/SME2p1/directive-arch.s
index 085a38cef007c6..51d259af30e813 100644
--- a/llvm/test/MC/AArch64/SME2p1/directive-arch.s
+++ b/llvm/test/MC/AArch64/SME2p1/directive-arch.s
@@ -8,3 +8,7 @@ sqcvt z0.h, {z0.s, z1.s}
 .arch armv9-a+sme2+sve-b16b16
 bfclamp { z0.h, z1.h }, z0.h, z0.h
 // CHECK: bfclamp { z0.h, z1.h }, z0.h, z0.h
+
+.arch armv9-a+sve-aes2+ssve-aes
+aesdimc {z0.b-z3.b}, {z0.b-z3.b}, z0.q[0]
+// CHECK: aesdimc { z0.b - z3.b }, { z0.b - z3.b }, z0.q[0]
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SME2p1/directive-arch_extension-negative.s b/llvm/test/MC/AArch64/SME2p1/directive-arch_extension-negative.s
index 84705d69ca362d..6e185a7ff8cc34 100644
--- a/llvm/test/MC/AArch64/SME2p1/directive-arch_extension-negative.s
+++ b/llvm/test/MC/AArch64/SME2p1/directive-arch_extension-negative.s
@@ -17,4 +17,11 @@ bfclamp { z0.h, z1.h }, z0.h, z0.h
 .arch_extension nosme-b16b16
 bfadd za.h[w8, 3], {z20.h-z21.h}
 // CHECK: error: instruction requires: sme-b16b16
-// CHECK: bfadd za.h[w8, 3], {z20.h-z21.h}
\ No newline at end of file
+// CHECK: bfadd za.h[w8, 3], {z20.h-z21.h}
+
+.arch_extension sve-aes2
+.arch_extension ssve-aes
+.arch_extension nossve-aes
+aesdimc {z0.b-z3.b}, {z0.b-z3.b}, z0.q[0]
+// CHECK: error: instruction requires: sve2p1 or ssve-aes
+// CHECK: aesdimc {z0.b-z3.b}, {z0.b-z3.b}, z0.q[0]
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SME2p1/directive-arch_extension.s b/llvm/test/MC/AArch64/SME2p1/directive-arch_extension.s
index 297e8b7769750d..3700325e6a5fe3 100644
--- a/llvm/test/MC/AArch64/SME2p1/directive-arch_extension.s
+++ b/llvm/test/MC/AArch64/SME2p1/directive-arch_extension.s
@@ -11,4 +11,9 @@ bfclamp { z0.h, z1.h }, z0.h, z0.h
 
 .arch_extension sme-b16b16
 bfadd za.h[w8, 3], {z20.h-z21.h}
-// CHECK: bfadd za.h[w8, 3, vgx2], { z20.h, z21.h }
\ No newline at end of file
+// CHECK: bfadd za.h[w8, 3, vgx2], { z20.h, z21.h }
+
+.arch_extension sve-aes2
+.arch_extension ssve-aes
+aesdimc {z0.b-z3.b}, {z0.b-z3.b}, z0.q[0]
+// CHECK: aesdimc { z0.b - z3.b }, { z0.b - z3.b }, z0.q[0]
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SVE2p1/aesd-diagnostics.s b/llvm/test/MC/AArch64/SVE2p1/aesd-diagnostics.s
new file mode 100644
index 00000000000000..6c7daadb371fff
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p1/aesd-diagnostics.s
@@ -0,0 +1,83 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve-aes2,+sve2p1 2>&1 < %s| FileCheck %s
+
+// --------------------------------------------------------------------------//
+// Invalid vector list
+
+aesd {z0.b-z2.b}, {z0.b-z2.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: aesd {z0.b-z2.b}, {z0.b-z2.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesd {z0.d-z1.d}, {z0.d-z1.d}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: aesd {z0.d-z1.d}, {z0.d-z1.d}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesd {z0.s-z3.s}, {z0.s-z3.s}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: aesd {z0.s-z3.s}, {z0.s-z3.s}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesd {z0.b-z0.b}, {z0.b-z0.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+// CHECK-NEXT: aesd {z0.b-z0.b}, {z0.b-z0.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesd {z3.b-z7.b}, {z3.b-z7.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+// CHECK-NEXT: aesd {z3.b-z7.b}, {z3.b-z7.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesd {z3.b-z4.b}, {z3.b-z4.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+// CHECK-NEXT: aesd {z3.b-z4.b}, {z3.b-z4.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesd {z5.b-z8.b}, {z5.b-z8.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+// CHECK-NEXT: aesd {z5.b-z8.b}, {z5.b-z8.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid second source vector width
+
+aesd {z0.b-z1.b}, {z0.b-z1.b}, z0.d[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: aesd {z0.b-z1.b}, {z0.b-z1.b}, z0.d[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesd {z0.b-z3.b}, {z0.b-z3.b}, z0.s[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: aesd {z0.b-z3.b}, {z0.b-z3.b}, z0.s[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid immediate index
+
+aesd {z0.b-z1.b}, {z0.b-z1.b}, z0.q[4]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3].
+// CHECK-NEXT: aesd {z0.b-z1.b}, {z0.b-z1.b}, z0.q[4]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesd {z0.b-z3.b}, {z0.b-z3.b}, z0.q[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3].
+// CHECK-NEXT: aesd {z0.b-z3.b}, {z0.b-z3.b}, z0.q[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Source and Destination Registers must match
+
+aesd {z0.b-z1.b}, {z2.b-z3.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register list
+// CHECK-NEXT: aesd {z0.b-z1.b}, {z2.b-z3.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesd {z0.b-z3.b}, {z4.b-z7.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register list
+// CHECK-NEXT: aesd {z0.b-z3.b}, {z4.b-z7.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesd {z0.b-z3.b}, {z0.h-z3.h}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: aesd {z0.b-z3.b}, {z0.h-z3.h}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SVE2p1/aesd.s b/llvm/test/MC/AArch64/SVE2p1/aesd.s
new file mode 100644
index 00000000000000..e2731d221a8425
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p1/aesd.s
@@ -0,0 +1,53 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve-aes2,+sve2p1 < %s \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve-aes2,+ssve-aes < %s \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \
+// RUN:        | FileCheck %s --check-prefix=CHECK-ERROR
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve-aes2,+sve2p1 < %s \
+// RUN:        | llvm-objdump -d --mattr=+sve-aes2,+sve2p1 --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve-aes2,+sve2p1 < %s \
+// RUN:        | llvm-objdump -d --mattr=-sme2 --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve-aes2,+sve2p1 < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sve-aes2,+sve2p1 -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+// x2
+aesd    {z0.b-z1.b}, {z0.b-z1.b}, z0.q[0]  // 01000101-00100010-11101100-00000000
+// CHECK-INST: aesd    { z0.b, z1.b }, { z0.b, z1.b }, z0.q[0]
+// CHECK-ENCODING: [0x00,0xec,0x22,0x45]
+// CHECK-ERROR: instruction requires: sve2p1 or ssve-aes sve-aes2
+// CHECK-UNKNOWN: 4522ec00 <unknown>
+
+aesd    {z20.b-z21.b}, {z20.b-z21.b}, z10.q[2]  // 01000101-00110010-11101101-01010100
+// CHECK-INST: aesd    { z20.b, z21.b }, { z20.b, z21.b }, z10.q[2]
+// CHECK-ENCODING: [0x54,0xed,0x32,0x45]
+// CHECK-ERROR: instruction requires: sve2p1 or ssve-aes sve-aes2
+// CHECK-UNKNOWN: 4532ed54 <unknown>
+
+aesd    {z30.b-z31.b}, {z30.b-z31.b}, z31.q[3]  // 01000101-00111010-11101111-11111110
+// CHECK-INST: aesd    { z30.b, z31.b }, { z30.b, z31.b }, z31.q[3]
+// CHECK-ENCODING: [0xfe,0xef,0x3a,0x45]
+// CHECK-ERROR: instruction requires: sve2p1 or ssve-aes sve-aes2
+// CHECK-UNKNOWN: 453aeffe <unknown>
+
+// x4
+aesd    {z0.b-z3.b}, {z0.b-z3.b}, z0.q[0]  // 01000101-00100110-11101100-00000000
+// CHECK-INST: aesd    { z0.b - z3.b }, { z0.b - z3.b }, z0.q[0]
+// CHECK-ENCODING: [0x00,0xec,0x26,0x45]
+// CHECK-ERROR: instruction requires: sve2p1 or ssve-aes sve-aes2
+// CHECK-UNKNOWN: 4526ec00 <unknown>
+
+aesd    {z20.b-z23.b}, {z20.b-z23.b}, z13.q[1]  // 01000101-00101110-11101101-10110100
+// CHECK-INST: aesd    { z20.b - z23.b }, { z20.b - z23.b }, z13.q[1]
+// CHECK-ENCODING: [0xb4,0xed,0x2e,0x45]
+// CHECK-ERROR: instruction requires: sve2p1 or ssve-aes sve-aes2
+// CHECK-UNKNOWN: 452eedb4 <unknown>
+
+aesd    {z28.b-z31.b}, {z28.b-z31.b}, z31.q[3]  // 01000101-00111110-11101111-11111100
+// CHECK-INST: aesd    { z28.b - z31.b }, { z28.b - z31.b }, z31.q[3]
+// CHECK-ENCODING: [0xfc,0xef,0x3e,0x45]
+// CHECK-ERROR: instruction requires: sve2p1 or ssve-aes sve-aes2
+// CHECK-UNKNOWN: 453eeffc <unknown>
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SVE2p1/aesdimc-diagnostics.s b/llvm/test/MC/AArch64/SVE2p1/aesdimc-diagnostics.s
new file mode 100644
index 00000000000000..b4b311e7c9699a
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p1/aesdimc-diagnostics.s
@@ -0,0 +1,83 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve-aes2,+sve2p1 2>&1 < %s| FileCheck %s
+
+// --------------------------------------------------------------------------//
+// Invalid vector list
+
+aesdimc {z0.b-z2.b}, {z0.b-z2.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: aesdimc {z0.b-z2.b}, {z0.b-z2.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesdimc {z0.d-z1.d}, {z0.d-z1.d}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: aesdimc {z0.d-z1.d}, {z0.d-z1.d}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesdimc {z0.s-z3.s}, {z0.s-z3.s}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: aesdimc {z0.s-z3.s}, {z0.s-z3.s}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesdimc {z0.b-z0.b}, {z0.b-z0.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+// CHECK-NEXT: aesdimc {z0.b-z0.b}, {z0.b-z0.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesdimc {z3.b-z7.b}, {z3.b-z7.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+// CHECK-NEXT: aesdimc {z3.b-z7.b}, {z3.b-z7.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesdimc {z3.b-z4.b}, {z3.b-z4.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+// CHECK-NEXT: aesdimc {z3.b-z4.b}, {z3.b-z4.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesdimc {z5.b-z8.b}, {z5.b-z8.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+// CHECK-NEXT: aesdimc {z5.b-z8.b}, {z5.b-z8.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid second source vector width
+
+aesdimc {z0.b-z1.b}, {z0.b-z1.b}, z0.d[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: aesdimc {z0.b-z1.b}, {z0.b-z1.b}, z0.d[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesdimc {z0.b-z3.b}, {z0.b-z3.b}, z0.s[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: aesdimc {z0.b-z3.b}, {z0.b-z3.b}, z0.s[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid immediate index
+
+aesdimc {z0.b-z1.b}, {z0.b-z1.b}, z0.q[4]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3].
+// CHECK-NEXT: aesdimc {z0.b-z1.b}, {z0.b-z1.b}, z0.q[4]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesdimc {z0.b-z3.b}, {z0.b-z3.b}, z0.q[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3].
+// CHECK-NEXT: aesdimc {z0.b-z3.b}, {z0.b-z3.b}, z0.q[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Source and Destination Registers must match
+
+aesdimc {z0.b-z1.b}, {z2.b-z3.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register list
+// CHECK-NEXT: aesdimc {z0.b-z1.b}, {z2.b-z3.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesdimc {z0.b-z3.b}, {z4.b-z7.b}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register list
+// CHECK-NEXT: aesdimc {z0.b-z3.b}, {z4.b-z7.b}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+aesdimc {z0.b-z3.b}, {z0.h-z3.h}, z0.q[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: aesdimc {z0.b-z3.b}, {z0.h-z3.h}, z0.q[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SVE2p1/aesdimc.s b/llvm/test/MC/AArch64/SVE2p1/aesdimc.s
new file mode 100644
index 00000000000000..6aa0e0d3d2baa7
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p1/aesdimc.s
@@ -0,0 +1,54 @@
+
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve-aes2,+sve2p1 < %s \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve-aes2,+ssve-aes < %s \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \
+// RUN:        | FileCheck %s --check-prefix=CHECK-ERROR
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve-aes2,+sve2p1 < %s \
+// RUN:        | llvm-objdump -d --mattr=+sve-aes2,+sve2p1 --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve-aes2,+sve2p1 < %s \
+// RUN:        | llvm-objdump -d --mattr=-sme2 --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve-aes2,+sve2p1 < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sve-aes2,+sve2p1 -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+// x2
+aesdimc {z0.b-z1.b}, {z0.b-z1.b}, z0.q[0]  // 01000101-00100011-11101100-00000000
+// CHECK-INST: aesdimc { z0.b, z1.b }, { z0.b, z1.b }, z0.q[0]
+// CHECK-ENCODING: [0x00,0xec,0x23,0x45]
+// CHECK-ERROR: instruction requires: sve2p1 or ssve-aes sve-aes2
+// CHECK-UNKNOWN: 4523ec00 <unknown>
+
+aesdimc {z20.b-z21.b}, {z20.b-z21.b}, z10.q[2]  // 01000101-00110011-11101101-01010100
+// CHECK-INST: aesdimc { z20.b, z21.b }, { z20.b, z21.b }, z10.q[2]
+// CHECK-ENCODING: [0x54,0xed,0x33,0x45]
+// CHECK-ERROR: instruction requires: sve2p1 or ssve-aes sve-aes2
+// CHECK-UNKNOWN: 4533ed54 <unknown>
+
+aesdimc {z30.b-z31.b}, {z30.b-z31.b}, z31.q[3]  // 01000101-00111011-11101111-11111110
+// CHECK-INST: aesdimc { z30.b, z31.b }, { z30.b, z31.b }, z31.q[3]
+// CHECK-ENCODING: [0xfe,0xef,0x3b,0x45]
+// CHECK-ERROR: instruction requires: sve2p1 or ssve-aes sve-aes2
+// CHECK-UNKNOWN: 453beffe <unknown>
+
+// x4
+aesdimc {z0.b-z3.b}, {z0.b-z3.b}, z0.q[0]  // 01000101-00100111-11101100-0...
[truncated]

@SpencerAbson SpencerAbson changed the title [AArch64] Add assembly/disassembly for SVE_AES2 instructions [AArch64] Add assembly/disassembly for multi-vector AES instructions Oct 22, 2024
Copy link
Contributor

@jthackray jthackray left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@SpencerAbson SpencerAbson merged commit 17bfd21 into llvm:main Oct 24, 2024
11 checks passed
@frobtech frobtech mentioned this pull request Oct 25, 2024
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
…lvm#113307)

This patch adds assembly/disassembly for the following multi-vector SVE
instructions

      - AESE (two/four registers)
      - AESD (two/four registers)
      - AESDIMC (two/four registers)
      - AESEMC (two/four registers)

- Introduce assembler extension tests for the new Armv9.6 sve-aes2 and
ssve-aes features
- In accordance with:
https://developer.arm.com/documentation/ddi0602/latest/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants