[llvm] a20112a - [AArch64]SME2 instructions that use ZTO operand

Caroline Concatto via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 3 00:48:07 PDT 2022


Author: Caroline Concatto
Date: 2022-11-03T07:35:21Z
New Revision: a20112a74cb34fa967d10e07185167cbc2906c0d

URL: https://github.com/llvm/llvm-project/commit/a20112a74cb34fa967d10e07185167cbc2906c0d
DIFF: https://github.com/llvm/llvm-project/commit/a20112a74cb34fa967d10e07185167cbc2906c0d.diff

LOG: [AArch64]SME2 instructions that use ZTO operand

This patch adds the assembly/disassembly for the following instructions:
  ZERO (ZT0): Zero ZT0.
  LDR (ZT0): Load ZT0 register.
  STR (ZT0): Store ZT0 register.
  MOVT (scalar to ZT0): Move 8 bytes from general-purpose register to ZT0.
       (ZT0 to scalar): Move 8 bytes from ZT0 to general-purpose register.
 Consecutive:
   LUTI2 (single): Lookup table read with 2-bit indexes.
         (two registers): Lookup table read with 2-bit indexes.
         (four registers): Lookup table read with 2-bit indexes.
   LUTI4 (single): Lookup table read with 4-bit indexes.
         (two registers): Lookup table read with 4-bit indexes.
         (four registers): Lookup table read with 4-bit indexes.

The reference can be found here:

https://developer.arm.com/documentation/ddi0602/2022-09

This patch also adds a new register class and operand for zt0
and a another index operand uimm3s8

Differential Revision: https://reviews.llvm.org/D136088

Added: 
    llvm/test/MC/AArch64/SME2/ldr-diagnostics.s
    llvm/test/MC/AArch64/SME2/ldr.s
    llvm/test/MC/AArch64/SME2/luti2-diagnostics.s
    llvm/test/MC/AArch64/SME2/luti2.s
    llvm/test/MC/AArch64/SME2/luti4-diagnostics.s
    llvm/test/MC/AArch64/SME2/luti4.s
    llvm/test/MC/AArch64/SME2/movt-diagnostics.s
    llvm/test/MC/AArch64/SME2/movt.s
    llvm/test/MC/AArch64/SME2/str-diagnostics.s
    llvm/test/MC/AArch64/SME2/str.s
    llvm/test/MC/AArch64/SME2/zero.s

Modified: 
    llvm/lib/Target/AArch64/AArch64InstrFormats.td
    llvm/lib/Target/AArch64/AArch64RegisterInfo.td
    llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
    llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
    llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
    llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
    llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
    llvm/lib/Target/AArch64/SMEInstrFormats.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 19ff399d5ed4a..b7c1cb6a47831 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -1408,6 +1408,18 @@ def sme_elm_idx0_15 : Operand<i32>, TImmLeaf<i32, [{
   let PrintMethod = "printMatrixIndex";
 }
 
+// SME2 vector select offset operands
+
+// uimm3s8 predicate
+// True if the immediate is a multiple of 8 in the range [0,56].
+def UImm3s8Operand : UImmScaledMemoryIndexed<3, 8>;
+
+def uimm3s8 : Operand<i64>, ImmLeaf<i64,
+[{ return Imm >= 0 && Imm <= 56 && ((Imm % 8) == 0); }], UImmS8XForm> {
+  let PrintMethod = "printVectorIndex<8>";
+  let ParserMatchClass = UImm3s8Operand;
+}
+
 class UImmScaledMemoryIndexedRange<int Width, int Scale, int OffsetVal> : AsmOperandClass {
   let Name = "UImm" # Width # "s" # Scale # "Range";
   let DiagnosticType = "InvalidMemoryIndexedRange" # Scale # "UImm" # Width;

diff  --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
index 8a41cd5c4d49b..b541deb837795 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
@@ -1390,6 +1390,8 @@ let SubRegIndices = [zasubb] in {
   def ZA : AArch64Reg<0, "za", [ZAB0]>;
 }
 
+def ZT0 : AArch64Reg<0, "zt0">;
+
 // SME Register Classes
 
 let isAllocatable = 0 in {
@@ -1416,6 +1418,10 @@ let isAllocatable = 0 in {
   }
 }
 
+def ZTR : RegisterClass<"AArch64", [untyped], 512, (add ZT0)> {
+  let Size = 512;
+  let DiagnosticType = "InvalidLookupTable";
+}
 // SME Register Operands
 // There are three types of SME matrix register operands:
 // * Tiles:

diff  --git a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
index 5a8149cf38500..55dc210c22fb7 100644
--- a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
@@ -559,6 +559,22 @@ defm SMOPS_MPPZZ_HtoS : sme2_int_mopx_tile<"smops", 0b001>;
 
 defm UMOPA_MPPZZ_HtoS : sme2_int_mopx_tile<"umopa", 0b100>;
 defm UMOPS_MPPZZ_HtoS : sme2_int_mopx_tile<"umops", 0b101>;
+
+def ZERO_T : sme2_zero_zt<"zero", 0b0001>;
+
+def LDR_TX : sme2_spill_fill_vector<"ldr", 0b01111100>;
+def STR_TX : sme2_spill_fill_vector<"str", 0b11111100>;
+
+def MOVT_XTI : sme2_movt_zt_to_scalar<"movt", 0b0011111>;
+def MOVT_TIX : sme2_movt_scalar_to_zt<"movt", 0b0011111>;
+
+defm LUTI2_ZTZI  : sme2_luti2_vector_index<"luti2">;
+defm LUTI2_2ZTZI : sme2_luti2_vector_vg2_index<"luti2">;
+defm LUTI2_4ZTZI : sme2_luti2_vector_vg4_index<"luti2">;
+
+defm LUTI4_ZTZI  : sme2_luti4_vector_index<"luti4">;
+defm LUTI4_2ZTZI : sme2_luti4_vector_vg2_index<"luti4">;
+defm LUTI4_4ZTZI : sme2_luti4_vector_vg4_index<"luti4">;
 }
 
 let Predicates = [HasSME2, HasSMEI16I64] in {

diff  --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 49d54f8e9a849..578c5140fd30b 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -70,7 +70,8 @@ enum class RegKind {
   SVEDataVector,
   SVEPredicateAsCounter,
   SVEPredicateVector,
-  Matrix
+  Matrix,
+  LookupTable
 };
 
 enum class MatrixKind { Array, Tile, Row, Col };
@@ -265,6 +266,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
   template <bool ParseShiftExtend,
             RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
   OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
+  OperandMatchResultTy tryParseZTOperand(OperandVector &Operands);
   template <bool ParseShiftExtend, bool ParseSuffix>
   OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
   template <RegKind RK>
@@ -2786,9 +2788,12 @@ unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
   if ((RegNum = matchMatrixRegName(Name)))
     return Kind == RegKind::Matrix ? RegNum : 0;
 
+ if (Name.equals_insensitive("zt0"))
+    return Kind == RegKind::LookupTable ? AArch64::ZT0 : 0;
+
   // The parsed register must be of RegKind Scalar
   if ((RegNum = MatchRegisterName(Name)))
-    return Kind == RegKind::Scalar ? RegNum : 0;
+    return (Kind == RegKind::Scalar) ? RegNum : 0;
 
   if (!RegNum) {
     // Handle a few common aliases of registers.
@@ -3966,6 +3971,9 @@ bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
   if (!tryParseNeonVectorRegister(Operands))
     return false;
 
+  if (tryParseZTOperand(Operands) == MatchOperand_Success)
+    return false;
+
   // Otherwise try for a scalar register.
   if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
     return false;
@@ -4179,6 +4187,10 @@ AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
       llvm_unreachable("Expected a valid vector kind");
     }
 
+    if (RegTok.is(AsmToken::Identifier) && ParseRes == MatchOperand_NoMatch &&
+        RegTok.getString().equals_insensitive("zt0"))
+      return MatchOperand_NoMatch;
+
     if (RegTok.isNot(AsmToken::Identifier) ||
         ParseRes == MatchOperand_ParseFail ||
         (ParseRes == MatchOperand_NoMatch && NoMatchIsError &&
@@ -4328,6 +4340,42 @@ AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
   return MatchOperand_Success;
 }
 
+OperandMatchResultTy
+AArch64AsmParser::tryParseZTOperand(OperandVector &Operands) {
+  SMLoc StartLoc = getLoc();
+  const AsmToken &Tok = getTok();
+  StringRef Name = Tok.getString().lower();
+
+  unsigned RegNum = matchRegisterNameAlias(Name, RegKind::LookupTable);
+
+  if (RegNum == 0)
+    return MatchOperand_NoMatch;
+
+  Operands.push_back(AArch64Operand::CreateReg(
+      RegNum, RegKind::LookupTable, StartLoc, getLoc(), getContext()));
+  Lex(); // Eat identifier token.
+
+  // Check if register is followed by an index
+  if (parseOptionalToken(AsmToken::LBrac)) {
+    const MCExpr *ImmVal;
+    if (getParser().parseExpression(ImmVal))
+      return MatchOperand_NoMatch;
+    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
+    if (!MCE) {
+      TokError("immediate value expected for vector index");
+      return MatchOperand_ParseFail;
+    }
+    if (parseToken(AsmToken::RBrac, "']' expected"))
+      return MatchOperand_ParseFail;
+
+    Operands.push_back(AArch64Operand::CreateImm(
+        MCConstantExpr::create(MCE->getValue(), getContext()), StartLoc,
+        getLoc(), getContext()));
+  }
+
+  return MatchOperand_Success;
+}
+
 template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
 OperandMatchResultTy
 AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
@@ -5434,6 +5482,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
     return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
   case Match_InvalidMemoryIndexed8UImm5:
     return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
+  case Match_InvalidMemoryIndexed8UImm3:
+    return Error(Loc, "index must be a multiple of 8 in range [0, 56].");
   case Match_InvalidMemoryIndexed4UImm5:
     return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
   case Match_InvalidMemoryIndexed2UImm5:
@@ -5762,6 +5812,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
     return Error(Loc, "Invalid vector list, expected list with 4 consecutive "
                       "SVE vectors, where the first vector is a multiple of 4 "
                       "and with matching element types");
+  case Match_InvalidLookupTable:
+    return Error(Loc, "Invalid lookup table, expected zt0");
   default:
     llvm_unreachable("unexpected error code!");
   }
@@ -6176,6 +6228,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidMemoryIndexed8SImm7:
   case Match_InvalidMemoryIndexed16SImm7:
   case Match_InvalidMemoryIndexed8UImm5:
+  case Match_InvalidMemoryIndexed8UImm3:
   case Match_InvalidMemoryIndexed4UImm5:
   case Match_InvalidMemoryIndexed2UImm5:
   case Match_InvalidMemoryIndexed1UImm6:
@@ -6318,6 +6371,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidSVCR:
   case Match_InvalidMatrixIndexGPR32_12_15:
   case Match_InvalidMatrixIndexGPR32_8_11:
+  case Match_InvalidLookupTable:
   case Match_InvalidSVEVectorListMul2x8:
   case Match_InvalidSVEVectorListMul2x16:
   case Match_InvalidSVEVectorListMul2x32:

diff  --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 1438f026f6792..0ef906b583c06 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -329,6 +329,9 @@ DecodeStatus AArch64Disassembler::getInstruction(MCInst &MI, uint64_t &Size,
         case AArch64::MPR8RegClassID:
           MI.insert(MI.begin() + i, MCOperand::createReg(AArch64::ZAB0));
           break;
+        case AArch64::ZTRRegClassID:
+          MI.insert(MI.begin() + i, MCOperand::createReg(AArch64::ZT0));
+          break;
         }
       } else if (Desc.OpInfo[i].OperandType ==
                  AArch64::OPERAND_IMPLICIT_IMM_0) {

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 9324ee41c3123..c11150a5a1230 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -1244,7 +1244,7 @@ void AArch64InstPrinter::printAMNoIndex(const MCInst *MI, unsigned OpNum,
   O << ']';
 }
 
-template<int Scale>
+template <int Scale>
 void AArch64InstPrinter::printImmScale(const MCInst *MI, unsigned OpNum,
                                        const MCSubtargetInfo &STI,
                                        raw_ostream &O) {
@@ -1576,10 +1576,11 @@ void AArch64InstPrinter::printTypedVectorList(const MCInst *MI, unsigned OpNum,
   printVectorList(MI, OpNum, STI, O, Suffix);
 }
 
+template <unsigned Scale>
 void AArch64InstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
                                           const MCSubtargetInfo &STI,
                                           raw_ostream &O) {
-  O << "[" << MI->getOperand(OpNum).getImm() << "]";
+  O << "[" << Scale * MI->getOperand(OpNum).getImm() << "]";
 }
 
 void AArch64InstPrinter::printMatrixIndex(const MCInst *MI, unsigned OpNum,

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
index 7bfb095b5873c..aa4aad1dc7fc7 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
@@ -164,6 +164,7 @@ class AArch64InstPrinter : public MCInstPrinter {
   void printTypedVectorList(const MCInst *MI, unsigned OpNum,
                             const MCSubtargetInfo &STI, raw_ostream &O);
 
+  template <unsigned Scale = 1>
   void printVectorIndex(const MCInst *MI, unsigned OpNum,
                         const MCSubtargetInfo &STI, raw_ostream &O);
   void printMatrixIndex(const MCInst *MI, unsigned OpNum,

diff  --git a/llvm/lib/Target/AArch64/SMEInstrFormats.td b/llvm/lib/Target/AArch64/SMEInstrFormats.td
index 98f1c861a5c26..b3941fdaeaa61 100644
--- a/llvm/lib/Target/AArch64/SMEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SMEInstrFormats.td
@@ -2379,3 +2379,191 @@ multiclass sme2_int_mopx_tile<string mnemonic, bits<3> op> {
 multiclass  sme2_bfp_mopx_tile<string mnemonic, bits<3> op> {
   def NAME : sme_outer_product_widening_inst<op, ZPR32, mnemonic>;
 }
+
+//===----------------------------------------------------------------------===///
+// SME2 Zero Lookup Table.
+class sme2_zero_zt<string mnemonic, bits<4> opc>
+    : I<(outs ZTR:$ZT), (ins ),
+         mnemonic, "\t\\{ $ZT \\}",
+         "", []>, Sched<[]> {
+  let Inst{31-4} = 0b1100000001001000000000000000;
+  let Inst{3-0}  = opc;
+}
+
+//===----------------------------------------------------------------------===//
+// SME2 lookup table load/store
+class sme2_spill_fill_vector<string mnemonic, bits<8> opc>
+    : I<!if(opc{7}, (outs ), (outs ZTR:$ZTt)),
+        !if(opc{7}, (ins ZTR:$ZTt, GPR64sp:$Rn), (ins GPR64sp:$Rn)),
+        mnemonic, "\t$ZTt, [$Rn]",
+        "", []>, Sched<[]> {
+  bits<5> Rn;
+  let Inst{31-22} = 0b1110000100;
+  let Inst{21-16} = opc{7-2};
+  let Inst{15-10} = 0b100000;
+  let Inst{9-5}   = Rn;
+  let Inst{4-2}   = 0b000;
+  let Inst{1-0}   = opc{1-0};
+
+  let mayLoad     = !not(opc{7});
+  let mayStore    = opc{7};
+}
+
+//===----------------------------------------------------------------------===///
+// SME2 move to/from lookup table
+class sme2_movt_zt_to_scalar<string mnemonic, bits<7> opc>
+    : I<(outs GPR64:$Rt), (ins ZTR:$ZTt, uimm3s8:$imm3),
+         mnemonic, "\t$Rt, $ZTt$imm3",
+         "", []>, Sched<[]> {
+  bits<3> imm3;
+  bits<5> Rt;
+  let Inst{31-15} = 0b11000000010011000;
+  let Inst{14-12} = imm3;
+  let Inst{11-5}  = opc;
+  let Inst{4-0}   = Rt;
+}
+
+class sme2_movt_scalar_to_zt<string mnemonic, bits<7> opc>
+    : I<(outs ZTR:$ZTt), (ins uimm3s8:$imm3, GPR64:$Rt),
+         mnemonic, "\t$ZTt$imm3, $Rt",
+         "", []>, Sched<[]> {
+  bits<3> imm3;
+  bits<5> Rt;
+  let Inst{31-15} = 0b11000000010011100;
+  let Inst{14-12} = imm3;
+  let Inst{11-5}  = opc;
+  let Inst{4-0}   = Rt;
+}
+
+//===----------------------------------------------------------------------===//
+// SME2 lookup table expand one register
+class sme2_luti_vector_index<bits<2> sz, bits<7> opc, RegisterOperand vector_ty,
+                             AsmVectorIndexOpnd index_ty, string mnemonic>
+    : I<(outs vector_ty:$Zd),
+        (ins ZTR:$ZTt, ZPRAny:$Zn, index_ty:$i),
+        mnemonic, "\t$Zd, $ZTt, $Zn$i",
+        "", []>, Sched<[]> {
+  bits<5> Zn;
+  bits<5> Zd;
+  let Inst{31-19} = 0b1100000011001;
+  let Inst{18-14} = opc{6-2};
+  let Inst{13-12} = sz;
+  let Inst{11-10} = opc{1-0};
+  let Inst{9-5}   = Zn;
+  let Inst{4-0}   = Zd;
+}
+
+class sme2_luti2_vector_index<bits<2> sz, RegisterOperand vector_ty,
+                              string mnemonic>
+    : sme2_luti_vector_index<sz, {1,?,?,?,?,0,0}, vector_ty, VectorIndexB, mnemonic> {
+  bits<4> i;
+  let Inst{17-14} = i;
+}
+
+multiclass sme2_luti2_vector_index<string mnemonic> {
+  def _B : sme2_luti2_vector_index<0b00, ZPR8, mnemonic>;
+  def _H : sme2_luti2_vector_index<0b01, ZPR16, mnemonic>;
+  def _S : sme2_luti2_vector_index<0b10, ZPR32, mnemonic>;
+}
+
+class sme2_luti4_vector_index<bits<2> sz, RegisterOperand vector_ty,
+                              string mnemonic>
+    : sme2_luti_vector_index<sz, {0,1,?,?,?,0,0}, vector_ty, VectorIndexH, mnemonic> {
+  bits<3> i;
+  let Inst{16-14} = i;
+}
+
+multiclass sme2_luti4_vector_index<string mnemonic> {
+  def _B : sme2_luti4_vector_index<0b00, ZPR8, mnemonic>;
+  def _H : sme2_luti4_vector_index<0b01, ZPR16, mnemonic>;
+  def _S : sme2_luti4_vector_index<0b10, ZPR32, mnemonic>;
+}
+
+// SME2 lookup table expand two contiguous registers
+class sme2_luti_vector_vg2_index<bits<2> sz, bits<6> opc, RegisterOperand vector_ty,
+                                 AsmVectorIndexOpnd index_ty, string mnemonic>
+    : I<(outs vector_ty:$Zd),
+        (ins ZTR:$ZTt, ZPRAny:$Zn, index_ty:$i),
+        mnemonic, "\t$Zd, $ZTt, $Zn$i",
+        "", []>, Sched<[]> {
+  bits<5> Zn;
+  bits<4> Zd;
+  let Inst{31-19} = 0b1100000010001;
+  let Inst{18-15} = opc{5-2};
+  let Inst{14}    = 0b1;
+  let Inst{13-12} = sz;
+  let Inst{11-10} = opc{1-0};
+  let Inst{9-5}   = Zn;
+  let Inst{4-1}   = Zd;
+  let Inst{0}     = 0b0;
+}
+
+class sme2_luti2_vector_vg2_index<bits<2> sz, RegisterOperand vector_ty,
+                                  string mnemonic>
+    : sme2_luti_vector_vg2_index<sz, {1,?,?,?,0,0}, vector_ty, VectorIndexH, mnemonic> {
+  bits<3> i;
+  let Inst{17-15} = i;
+}
+
+multiclass sme2_luti2_vector_vg2_index<string mnemonic> {
+  def _B : sme2_luti2_vector_vg2_index<0b00, ZZ_b_mul_r, mnemonic>;
+  def _H : sme2_luti2_vector_vg2_index<0b01, ZZ_h_mul_r, mnemonic>;
+  def _S : sme2_luti2_vector_vg2_index<0b10, ZZ_s_mul_r, mnemonic>;
+}
+
+class sme2_luti4_vector_vg2_index<bits<2> sz, RegisterOperand vector_ty,
+                                 string mnemonic>
+    : sme2_luti_vector_vg2_index<sz, {0,1,?,?,0,0}, vector_ty, VectorIndexS, mnemonic> {
+  bits<2> i;
+  let Inst{16-15} = i;
+}
+
+multiclass sme2_luti4_vector_vg2_index<string mnemonic> {
+  def _B : sme2_luti4_vector_vg2_index<0b00, ZZ_b_mul_r, mnemonic>;
+  def _H : sme2_luti4_vector_vg2_index<0b01, ZZ_h_mul_r, mnemonic>;
+  def _S : sme2_luti4_vector_vg2_index<0b10, ZZ_s_mul_r, mnemonic>;
+}
+
+// SME2 lookup table expand four contiguous registers
+class sme2_luti_vector_vg4_index<bits<2> sz, bits<5>opc, RegisterOperand vector_ty,
+                                 AsmVectorIndexOpnd index_ty, string mnemonic>
+    : I<(outs vector_ty:$Zd),
+        (ins ZTR:$ZTt, ZPRAny:$Zn, index_ty:$i),
+        mnemonic, "\t$Zd, $ZTt, $Zn$i",
+        "", []>, Sched<[]> {
+  bits<5> Zn;
+  bits<3> Zd;
+  let Inst{31-19} = 0b1100000010001;
+  let Inst{18-16} = opc{4-2};
+  let Inst{15-14} = 0b10;
+  let Inst{13-12} = sz;
+  let Inst{11-10} = opc{1-0};
+  let Inst{9-5}   = Zn;
+  let Inst{4-2}   = Zd;
+  let Inst{1-0}   = 0b00;
+}
+
+class sme2_luti2_vector_vg4_index<bits<2> sz, RegisterOperand vector_ty,
+                                  string mnemonic>
+    : sme2_luti_vector_vg4_index<sz, {1,?,?,0,0}, vector_ty, VectorIndexS, mnemonic> {
+  bits<2> i;
+  let Inst{17-16} = i;
+}
+
+multiclass sme2_luti2_vector_vg4_index<string mnemonic> {
+  def _B : sme2_luti2_vector_vg4_index<0b00, ZZZZ_b_mul_r, mnemonic>;
+  def _H : sme2_luti2_vector_vg4_index<0b01, ZZZZ_h_mul_r, mnemonic>;
+  def _S : sme2_luti2_vector_vg4_index<0b10, ZZZZ_s_mul_r, mnemonic>;
+}
+
+class sme2_luti4_vector_vg4_index<bits<2> sz, RegisterOperand vector_ty,
+                                  string mnemonic>
+    : sme2_luti_vector_vg4_index<sz, {0,1,?,0,0}, vector_ty, VectorIndexD, mnemonic> {
+  bits<1> i;
+  let Inst{16}    = i;
+}
+
+multiclass sme2_luti4_vector_vg4_index<string mnemonic> {
+  def _H : sme2_luti4_vector_vg4_index<0b01, ZZZZ_h_mul_r, mnemonic>;
+  def _S : sme2_luti4_vector_vg4_index<0b10, ZZZZ_s_mul_r, mnemonic>;
+}

diff  --git a/llvm/test/MC/AArch64/SME2/ldr-diagnostics.s b/llvm/test/MC/AArch64/SME2/ldr-diagnostics.s
new file mode 100644
index 0000000000000..29c19316529fc
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/ldr-diagnostics.s
@@ -0,0 +1,6 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2  2>&1 < %s| FileCheck %s
+
+ldr zt1, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid lookup table, expected zt0
+// CHECK-NEXT: ldr zt1, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:

diff  --git a/llvm/test/MC/AArch64/SME2/ldr.s b/llvm/test/MC/AArch64/SME2/ldr.s
new file mode 100644
index 0000000000000..4038b39ad3f92
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/ldr.s
@@ -0,0 +1,38 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %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=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme2 - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=-sme2 - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sme2 -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+
+ldr     zt0, [x0]  // 11100001-00011111-10000000-00000000
+// CHECK-INST: ldr     zt0, [x0]
+// CHECK-ENCODING: [0x00,0x80,0x1f,0xe1]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: e11f8000 <unknown>
+
+ldr     zt0, [x10]  // 11100001-00011111-10000001-01000000
+// CHECK-INST: ldr     zt0, [x10]
+// CHECK-ENCODING: [0x40,0x81,0x1f,0xe1]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: e11f8140 <unknown>
+
+ldr     zt0, [x13]  // 11100001-00011111-10000001-10100000
+// CHECK-INST: ldr     zt0, [x13]
+// CHECK-ENCODING: [0xa0,0x81,0x1f,0xe1]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: e11f81a0 <unknown>
+
+ldr     zt0, [sp]  // 11100001-00011111-10000011-11100000
+// CHECK-INST: ldr     zt0, [sp]
+// CHECK-ENCODING: [0xe0,0x83,0x1f,0xe1]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: e11f83e0 <unknown>
+

diff  --git a/llvm/test/MC/AArch64/SME2/luti2-diagnostics.s b/llvm/test/MC/AArch64/SME2/luti2-diagnostics.s
new file mode 100644
index 0000000000000..730f3e7532335
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/luti2-diagnostics.s
@@ -0,0 +1,60 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 2>&1 < %s | FileCheck %s
+
+// --------------------------------------------------------------------------//
+// Invalid lane indices
+
+luti2 z0.h, zt0, z0[16]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: luti2 z0.h, zt0, z0[16]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti2 z0.s, zt0, z0[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: luti2 z0.s, zt0, z0[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti2 {z0.b-z1.b}, zt0, z0[8]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 7].
+// CHECK-NEXT: luti2 {z0.b-z1.b}, zt0, z0[8]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti2 {z0.h-z1.h}, zt0, z0[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 7].
+// CHECK-NEXT: luti2 {z0.h-z1.h}, zt0, z0[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti2 {z0.s-z3.s}, zt0, z0[4]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3].
+// CHECK-NEXT: luti2 {z0.s-z3.s}, zt0, z0[4]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti2 {z0.b-z3.b}, zt0, z0[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3].
+// CHECK-NEXT: luti2 {z0.b-z3.b}, zt0, z0[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid vector lists
+
+luti2 {z0.h-z2.h}, zt0, z0[3]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: luti2 {z0.h-z2.h}, zt0, z0[3]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti2 {z1.s-z2.s}, zt0, z0[3]
+// 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: luti2 {z1.s-z2.s}, zt0, z0[3]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti2 {z1.s-z4.s}, zt0, z0[3]
+// 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: luti2 {z1.s-z4.s}, zt0, z0[3]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid vector suffix
+
+luti2 {z0.d-z1.d}, zt0, z0[3]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: luti2 {z0.d-z1.d}, zt0, z0[3]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:

diff  --git a/llvm/test/MC/AArch64/SME2/luti2.s b/llvm/test/MC/AArch64/SME2/luti2.s
new file mode 100644
index 0000000000000..c622ed0a4285c
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/luti2.s
@@ -0,0 +1,238 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %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=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme2 - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=-sme2 - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sme2 -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+
+luti2   z0.h, zt0, z0[0]  // 11000000-11001100-00010000-00000000
+// CHECK-INST: luti2   z0.h, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x10,0xcc,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cc1000 <unknown>
+
+luti2   z21.h, zt0, z10[5]  // 11000000-11001101-01010001-01010101
+// CHECK-INST: luti2   z21.h, zt0, z10[5]
+// CHECK-ENCODING: [0x55,0x51,0xcd,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cd5155 <unknown>
+
+luti2   z23.h, zt0, z13[3]  // 11000000-11001100-11010001-10110111
+// CHECK-INST: luti2   z23.h, zt0, z13[3]
+// CHECK-ENCODING: [0xb7,0xd1,0xcc,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0ccd1b7 <unknown>
+
+luti2   z31.h, zt0, z31[15]  // 11000000-11001111-11010011-11111111
+// CHECK-INST: luti2   z31.h, zt0, z31[15]
+// CHECK-ENCODING: [0xff,0xd3,0xcf,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cfd3ff <unknown>
+
+
+luti2   z0.s, zt0, z0[0]  // 11000000-11001100-00100000-00000000
+// CHECK-INST: luti2   z0.s, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x20,0xcc,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cc2000 <unknown>
+
+luti2   z21.s, zt0, z10[5]  // 11000000-11001101-01100001-01010101
+// CHECK-INST: luti2   z21.s, zt0, z10[5]
+// CHECK-ENCODING: [0x55,0x61,0xcd,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cd6155 <unknown>
+
+luti2   z23.s, zt0, z13[3]  // 11000000-11001100-11100001-10110111
+// CHECK-INST: luti2   z23.s, zt0, z13[3]
+// CHECK-ENCODING: [0xb7,0xe1,0xcc,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cce1b7 <unknown>
+
+luti2   z31.s, zt0, z31[15]  // 11000000-11001111-11100011-11111111
+// CHECK-INST: luti2   z31.s, zt0, z31[15]
+// CHECK-ENCODING: [0xff,0xe3,0xcf,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cfe3ff <unknown>
+
+
+luti2   z0.b, zt0, z0[0]  // 11000000-11001100-00000000-00000000
+// CHECK-INST: luti2   z0.b, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x00,0xcc,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cc0000 <unknown>
+
+luti2   z21.b, zt0, z10[5]  // 11000000-11001101-01000001-01010101
+// CHECK-INST: luti2   z21.b, zt0, z10[5]
+// CHECK-ENCODING: [0x55,0x41,0xcd,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cd4155 <unknown>
+
+luti2   z23.b, zt0, z13[3]  // 11000000-11001100-11000001-10110111
+// CHECK-INST: luti2   z23.b, zt0, z13[3]
+// CHECK-ENCODING: [0xb7,0xc1,0xcc,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0ccc1b7 <unknown>
+
+luti2   z31.b, zt0, z31[15]  // 11000000-11001111-11000011-11111111
+// CHECK-INST: luti2   z31.b, zt0, z31[15]
+// CHECK-ENCODING: [0xff,0xc3,0xcf,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cfc3ff <unknown>
+
+
+luti2   {z0.h - z1.h}, zt0, z0[0]  // 11000000-10001100-01010000-00000000
+// CHECK-INST: luti2   { z0.h, z1.h }, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x50,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08c5000 <unknown>
+
+luti2   {z20.h - z21.h}, zt0, z10[2]  // 11000000-10001101-01010001-01010100
+// CHECK-INST: luti2   { z20.h, z21.h }, zt0, z10[2]
+// CHECK-ENCODING: [0x54,0x51,0x8d,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08d5154 <unknown>
+
+luti2   {z22.h - z23.h}, zt0, z13[1]  // 11000000-10001100-11010001-10110110
+// CHECK-INST: luti2   { z22.h, z23.h }, zt0, z13[1]
+// CHECK-ENCODING: [0xb6,0xd1,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08cd1b6 <unknown>
+
+luti2   {z30.h - z31.h}, zt0, z31[7]  // 11000000-10001111-11010011-11111110
+// CHECK-INST: luti2   { z30.h, z31.h }, zt0, z31[7]
+// CHECK-ENCODING: [0xfe,0xd3,0x8f,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08fd3fe <unknown>
+
+
+luti2   {z0.s - z1.s}, zt0, z0[0]  // 11000000-10001100-01100000-00000000
+// CHECK-INST: luti2   { z0.s, z1.s }, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x60,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08c6000 <unknown>
+
+luti2   {z20.s - z21.s}, zt0, z10[2]  // 11000000-10001101-01100001-01010100
+// CHECK-INST: luti2   { z20.s, z21.s }, zt0, z10[2]
+// CHECK-ENCODING: [0x54,0x61,0x8d,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08d6154 <unknown>
+
+luti2   {z22.s - z23.s}, zt0, z13[1]  // 11000000-10001100-11100001-10110110
+// CHECK-INST: luti2   { z22.s, z23.s }, zt0, z13[1]
+// CHECK-ENCODING: [0xb6,0xe1,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08ce1b6 <unknown>
+
+luti2   {z30.s - z31.s}, zt0, z31[7]  // 11000000-10001111-11100011-11111110
+// CHECK-INST: luti2   { z30.s, z31.s }, zt0, z31[7]
+// CHECK-ENCODING: [0xfe,0xe3,0x8f,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08fe3fe <unknown>
+
+
+luti2   {z0.b - z1.b}, zt0, z0[0]  // 11000000-10001100-01000000-00000000
+// CHECK-INST: luti2   { z0.b, z1.b }, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x40,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08c4000 <unknown>
+
+luti2   {z20.b - z21.b}, zt0, z10[2]  // 11000000-10001101-01000001-01010100
+// CHECK-INST: luti2   { z20.b, z21.b }, zt0, z10[2]
+// CHECK-ENCODING: [0x54,0x41,0x8d,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08d4154 <unknown>
+
+luti2   {z22.b - z23.b}, zt0, z13[1]  // 11000000-10001100-11000001-10110110
+// CHECK-INST: luti2   { z22.b, z23.b }, zt0, z13[1]
+// CHECK-ENCODING: [0xb6,0xc1,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08cc1b6 <unknown>
+
+luti2   {z30.b - z31.b}, zt0, z31[7]  // 11000000-10001111-11000011-11111110
+// CHECK-INST: luti2   { z30.b, z31.b }, zt0, z31[7]
+// CHECK-ENCODING: [0xfe,0xc3,0x8f,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08fc3fe <unknown>
+
+
+luti2   {z0.h - z3.h}, zt0, z0[0]  // 11000000-10001100-10010000-00000000
+// CHECK-INST: luti2   { z0.h - z3.h }, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x90,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08c9000 <unknown>
+
+luti2   {z20.h - z23.h}, zt0, z10[1]  // 11000000-10001101-10010001-01010100
+// CHECK-INST: luti2   { z20.h - z23.h }, zt0, z10[1]
+// CHECK-ENCODING: [0x54,0x91,0x8d,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08d9154 <unknown>
+
+luti2   {z20.h - z23.h}, zt0, z13[0]  // 11000000-10001100-10010001-10110100
+// CHECK-INST: luti2   { z20.h - z23.h }, zt0, z13[0]
+// CHECK-ENCODING: [0xb4,0x91,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08c91b4 <unknown>
+
+luti2   {z28.h - z31.h}, zt0, z31[3]  // 11000000-10001111-10010011-11111100
+// CHECK-INST: luti2   { z28.h - z31.h }, zt0, z31[3]
+// CHECK-ENCODING: [0xfc,0x93,0x8f,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08f93fc <unknown>
+
+
+luti2   {z0.s - z3.s}, zt0, z0[0]  // 11000000-10001100-10100000-00000000
+// CHECK-INST: luti2   { z0.s - z3.s }, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0xa0,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08ca000 <unknown>
+
+luti2   {z20.s - z23.s}, zt0, z10[1]  // 11000000-10001101-10100001-01010100
+// CHECK-INST: luti2   { z20.s - z23.s }, zt0, z10[1]
+// CHECK-ENCODING: [0x54,0xa1,0x8d,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08da154 <unknown>
+
+luti2   {z20.s - z23.s}, zt0, z13[0]  // 11000000-10001100-10100001-10110100
+// CHECK-INST: luti2   { z20.s - z23.s }, zt0, z13[0]
+// CHECK-ENCODING: [0xb4,0xa1,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08ca1b4 <unknown>
+
+luti2   {z28.s - z31.s}, zt0, z31[3]  // 11000000-10001111-10100011-11111100
+// CHECK-INST: luti2   { z28.s - z31.s }, zt0, z31[3]
+// CHECK-ENCODING: [0xfc,0xa3,0x8f,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08fa3fc <unknown>
+
+
+luti2   {z0.b - z3.b}, zt0, z0[0]  // 11000000-10001100-10000000-00000000
+// CHECK-INST: luti2   { z0.b - z3.b }, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x80,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08c8000 <unknown>
+
+luti2   {z20.b - z23.b}, zt0, z10[1]  // 11000000-10001101-10000001-01010100
+// CHECK-INST: luti2   { z20.b - z23.b }, zt0, z10[1]
+// CHECK-ENCODING: [0x54,0x81,0x8d,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08d8154 <unknown>
+
+luti2   {z20.b - z23.b}, zt0, z13[0]  // 11000000-10001100-10000001-10110100
+// CHECK-INST: luti2   { z20.b - z23.b }, zt0, z13[0]
+// CHECK-ENCODING: [0xb4,0x81,0x8c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08c81b4 <unknown>
+
+luti2   {z28.b - z31.b}, zt0, z31[3]  // 11000000-10001111-10000011-11111100
+// CHECK-INST: luti2   { z28.b - z31.b }, zt0, z31[3]
+// CHECK-ENCODING: [0xfc,0x83,0x8f,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08f83fc <unknown>
+

diff  --git a/llvm/test/MC/AArch64/SME2/luti4-diagnostics.s b/llvm/test/MC/AArch64/SME2/luti4-diagnostics.s
new file mode 100644
index 0000000000000..7a8590d0bac29
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/luti4-diagnostics.s
@@ -0,0 +1,60 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 2>&1 < %s | FileCheck %s
+
+// --------------------------------------------------------------------------//
+// Invalid lane indices
+
+luti4 z0.h, zt0, z0[8]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 7].
+// CHECK-NEXT: luti4 z0.h, zt0, z0[8]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti4 z0.s, zt0, z0[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 7].
+// CHECK-NEXT: luti4 z0.s, zt0, z0[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti4 {z0.b-z1.b}, zt0, z0[4]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3].
+// CHECK-NEXT: luti4 {z0.b-z1.b}, zt0, z0[4]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti4 {z0.h-z1.h}, zt0, z0[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3].
+// CHECK-NEXT: luti4 {z0.h-z1.h}, zt0, z0[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti4 {z0.s-z3.s}, zt0, z0[2]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 1].
+// CHECK-NEXT: luti4 {z0.s-z3.s}, zt0, z0[2]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti4 {z0.h-z3.h}, zt0, z0[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 1].
+// CHECK-NEXT: luti4 {z0.h-z3.h}, zt0, z0[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid vector lists
+
+luti4 {z0.h-z2.h}, zt0, z0[3]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: luti4 {z0.h-z2.h}, zt0, z0[3]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti4 {z1.s-z2.s}, zt0, z0[3]
+// 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: luti4 {z1.s-z2.s}, zt0, z0[3]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+luti4 {z1.s-z4.s}, zt0, z0[3]
+// 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: luti4 {z1.s-z4.s}, zt0, z0[3]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid vector suffix
+
+luti4 {z0.d-z1.d}, zt0, z0[3]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: luti4 {z0.d-z1.d}, zt0, z0[3]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:

diff  --git a/llvm/test/MC/AArch64/SME2/luti4.s b/llvm/test/MC/AArch64/SME2/luti4.s
new file mode 100644
index 0000000000000..c784d823eba45
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/luti4.s
@@ -0,0 +1,213 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %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=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme2 - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=-sme2 - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sme2 -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+
+luti4   z0.h, zt0, z0[0]  // 11000000-11001010-00010000-00000000
+// CHECK-INST: luti4   z0.h, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x10,0xca,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0ca1000 <unknown>
+
+luti4   z21.h, zt0, z10[5]  // 11000000-11001011-01010001-01010101
+// CHECK-INST: luti4   z21.h, zt0, z10[5]
+// CHECK-ENCODING: [0x55,0x51,0xcb,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cb5155 <unknown>
+
+luti4   z23.h, zt0, z13[3]  // 11000000-11001010-11010001-10110111
+// CHECK-INST: luti4   z23.h, zt0, z13[3]
+// CHECK-ENCODING: [0xb7,0xd1,0xca,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cad1b7 <unknown>
+
+luti4   z31.h, zt0, z31[7]  // 11000000-11001011-11010011-11111111
+// CHECK-INST: luti4   z31.h, zt0, z31[7]
+// CHECK-ENCODING: [0xff,0xd3,0xcb,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cbd3ff <unknown>
+
+
+luti4   z0.s, zt0, z0[0]  // 11000000-11001010-00100000-00000000
+// CHECK-INST: luti4   z0.s, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x20,0xca,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0ca2000 <unknown>
+
+luti4   z21.s, zt0, z10[5]  // 11000000-11001011-01100001-01010101
+// CHECK-INST: luti4   z21.s, zt0, z10[5]
+// CHECK-ENCODING: [0x55,0x61,0xcb,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cb6155 <unknown>
+
+luti4   z23.s, zt0, z13[3]  // 11000000-11001010-11100001-10110111
+// CHECK-INST: luti4   z23.s, zt0, z13[3]
+// CHECK-ENCODING: [0xb7,0xe1,0xca,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cae1b7 <unknown>
+
+luti4   z31.s, zt0, z31[7]  // 11000000-11001011-11100011-11111111
+// CHECK-INST: luti4   z31.s, zt0, z31[7]
+// CHECK-ENCODING: [0xff,0xe3,0xcb,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cbe3ff <unknown>
+
+
+luti4   z0.b, zt0, z0[0]  // 11000000-11001010-00000000-00000000
+// CHECK-INST: luti4   z0.b, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x00,0xca,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0ca0000 <unknown>
+
+luti4   z21.b, zt0, z10[5]  // 11000000-11001011-01000001-01010101
+// CHECK-INST: luti4   z21.b, zt0, z10[5]
+// CHECK-ENCODING: [0x55,0x41,0xcb,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cb4155 <unknown>
+
+luti4   z23.b, zt0, z13[3]  // 11000000-11001010-11000001-10110111
+// CHECK-INST: luti4   z23.b, zt0, z13[3]
+// CHECK-ENCODING: [0xb7,0xc1,0xca,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cac1b7 <unknown>
+
+luti4   z31.b, zt0, z31[7]  // 11000000-11001011-11000011-11111111
+// CHECK-INST: luti4   z31.b, zt0, z31[7]
+// CHECK-ENCODING: [0xff,0xc3,0xcb,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0cbc3ff <unknown>
+
+
+luti4   {z0.h - z1.h}, zt0, z0[0]  // 11000000-10001010-01010000-00000000
+// CHECK-INST: luti4   { z0.h, z1.h }, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x50,0x8a,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08a5000 <unknown>
+
+luti4   {z20.h - z21.h}, zt0, z10[2]  // 11000000-10001011-01010001-01010100
+// CHECK-INST: luti4   { z20.h, z21.h }, zt0, z10[2]
+// CHECK-ENCODING: [0x54,0x51,0x8b,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08b5154 <unknown>
+
+luti4   {z22.h - z23.h}, zt0, z13[1]  // 11000000-10001010-11010001-10110110
+// CHECK-INST: luti4   { z22.h, z23.h }, zt0, z13[1]
+// CHECK-ENCODING: [0xb6,0xd1,0x8a,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08ad1b6 <unknown>
+
+luti4   {z30.h - z31.h}, zt0, z31[3]  // 11000000-10001011-11010011-11111110
+// CHECK-INST: luti4   { z30.h, z31.h }, zt0, z31[3]
+// CHECK-ENCODING: [0xfe,0xd3,0x8b,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08bd3fe <unknown>
+
+
+luti4   {z0.s - z1.s}, zt0, z0[0]  // 11000000-10001010-01100000-00000000
+// CHECK-INST: luti4   { z0.s, z1.s }, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x60,0x8a,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08a6000 <unknown>
+
+luti4   {z20.s - z21.s}, zt0, z10[2]  // 11000000-10001011-01100001-01010100
+// CHECK-INST: luti4   { z20.s, z21.s }, zt0, z10[2]
+// CHECK-ENCODING: [0x54,0x61,0x8b,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08b6154 <unknown>
+
+luti4   {z22.s - z23.s}, zt0, z13[1]  // 11000000-10001010-11100001-10110110
+// CHECK-INST: luti4   { z22.s, z23.s }, zt0, z13[1]
+// CHECK-ENCODING: [0xb6,0xe1,0x8a,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08ae1b6 <unknown>
+
+luti4   {z30.s - z31.s}, zt0, z31[3]  // 11000000-10001011-11100011-11111110
+// CHECK-INST: luti4   { z30.s, z31.s }, zt0, z31[3]
+// CHECK-ENCODING: [0xfe,0xe3,0x8b,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08be3fe <unknown>
+
+
+luti4   {z0.b - z1.b}, zt0, z0[0]  // 11000000-10001010-01000000-00000000
+// CHECK-INST: luti4   { z0.b, z1.b }, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x40,0x8a,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08a4000 <unknown>
+
+luti4   {z20.b - z21.b}, zt0, z10[2]  // 11000000-10001011-01000001-01010100
+// CHECK-INST: luti4   { z20.b, z21.b }, zt0, z10[2]
+// CHECK-ENCODING: [0x54,0x41,0x8b,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08b4154 <unknown>
+
+luti4   {z22.b - z23.b}, zt0, z13[1]  // 11000000-10001010-11000001-10110110
+// CHECK-INST: luti4   { z22.b, z23.b }, zt0, z13[1]
+// CHECK-ENCODING: [0xb6,0xc1,0x8a,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08ac1b6 <unknown>
+
+luti4   {z30.b - z31.b}, zt0, z31[3]  // 11000000-10001011-11000011-11111110
+// CHECK-INST: luti4   { z30.b, z31.b }, zt0, z31[3]
+// CHECK-ENCODING: [0xfe,0xc3,0x8b,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08bc3fe <unknown>
+
+
+luti4   {z0.h - z3.h}, zt0, z0[0]  // 11000000-10001010-10010000-00000000
+// CHECK-INST: luti4   { z0.h - z3.h }, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0x90,0x8a,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08a9000 <unknown>
+
+luti4   {z20.h - z23.h}, zt0, z10[1]  // 11000000-10001011-10010001-01010100
+// CHECK-INST: luti4   { z20.h - z23.h }, zt0, z10[1]
+// CHECK-ENCODING: [0x54,0x91,0x8b,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08b9154 <unknown>
+
+luti4   {z20.h - z23.h}, zt0, z13[0]  // 11000000-10001010-10010001-10110100
+// CHECK-INST: luti4   { z20.h - z23.h }, zt0, z13[0]
+// CHECK-ENCODING: [0xb4,0x91,0x8a,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08a91b4 <unknown>
+
+luti4   {z28.h - z31.h}, zt0, z31[1]  // 11000000-10001011-10010011-11111100
+// CHECK-INST: luti4   { z28.h - z31.h }, zt0, z31[1]
+// CHECK-ENCODING: [0xfc,0x93,0x8b,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08b93fc <unknown>
+
+
+luti4   {z0.s - z3.s}, zt0, z0[0]  // 11000000-10001010-10100000-00000000
+// CHECK-INST: luti4   { z0.s - z3.s }, zt0, z0[0]
+// CHECK-ENCODING: [0x00,0xa0,0x8a,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08aa000 <unknown>
+
+luti4   {z20.s - z23.s}, zt0, z10[1]  // 11000000-10001011-10100001-01010100
+// CHECK-INST: luti4   { z20.s - z23.s }, zt0, z10[1]
+// CHECK-ENCODING: [0x54,0xa1,0x8b,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08ba154 <unknown>
+
+luti4   {z20.s - z23.s}, zt0, z13[0]  // 11000000-10001010-10100001-10110100
+// CHECK-INST: luti4   { z20.s - z23.s }, zt0, z13[0]
+// CHECK-ENCODING: [0xb4,0xa1,0x8a,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08aa1b4 <unknown>
+
+luti4   {z28.s - z31.s}, zt0, z31[1]  // 11000000-10001011-10100011-11111100
+// CHECK-INST: luti4   { z28.s - z31.s }, zt0, z31[1]
+// CHECK-ENCODING: [0xfc,0xa3,0x8b,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c08ba3fc <unknown>
+

diff  --git a/llvm/test/MC/AArch64/SME2/movt-diagnostics.s b/llvm/test/MC/AArch64/SME2/movt-diagnostics.s
new file mode 100644
index 0000000000000..d3696bf114623
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/movt-diagnostics.s
@@ -0,0 +1,32 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 2>&1 < %s| FileCheck %s
+
+// index must be a multiple of 8 in range [0, 56].
+// --------------------------------------------------------------------------//
+
+movt x0, zt0[57]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 8 in range [0, 56].
+// CHECK-NEXT: movt x0, zt0[57]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+movt x0, zt0[58]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 8 in range [0, 56].
+// CHECK-NEXT: movt x0, zt0[58]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+movt x0, zt0[64]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 8 in range [0, 56].
+// CHECK-NEXT: movt x0, zt0[64]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+movt x0, zt0[72]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 8 in range [0, 56].
+// CHECK-NEXT: movt x0, zt0[72]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid zt0 register
+
+movt x0, zt1[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+// CHECK-NEXT: movt x0, zt1[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:

diff  --git a/llvm/test/MC/AArch64/SME2/movt.s b/llvm/test/MC/AArch64/SME2/movt.s
new file mode 100644
index 0000000000000..a673eceeebed4
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/movt.s
@@ -0,0 +1,63 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %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=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme2 - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=-sme2 - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sme2 -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+
+movt    x0, zt0[0]  // 11000000-01001100-00000011-11100000
+// CHECK-INST: movt    x0, zt0[0]
+// CHECK-ENCODING: [0xe0,0x03,0x4c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c04c03e0 <unknown>
+
+movt    x21, zt0[40]  // 11000000-01001100-01010011-11110101
+// CHECK-INST: movt    x21, zt0[40]
+// CHECK-ENCODING: [0xf5,0x53,0x4c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c04c53f5 <unknown>
+
+movt    x23, zt0[48]  // 11000000-01001100-01100011-11110111
+// CHECK-INST: movt    x23, zt0[48]
+// CHECK-ENCODING: [0xf7,0x63,0x4c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c04c63f7 <unknown>
+
+movt    xzr, zt0[56]  // 11000000-01001100-01110011-11111111
+// CHECK-INST: movt    xzr, zt0[56]
+// CHECK-ENCODING: [0xff,0x73,0x4c,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c04c73ff <unknown>
+
+
+movt    zt0[0], x0  // 11000000-01001110-00000011-11100000
+// CHECK-INST: movt    zt0[0], x0
+// CHECK-ENCODING: [0xe0,0x03,0x4e,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c04e03e0 <unknown>
+
+movt    zt0[40], x21  // 11000000-01001110-01010011-11110101
+// CHECK-INST: movt    zt0[40], x21
+// CHECK-ENCODING: [0xf5,0x53,0x4e,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c04e53f5 <unknown>
+
+movt    zt0[48], x23  // 11000000-01001110-01100011-11110111
+// CHECK-INST: movt    zt0[48], x23
+// CHECK-ENCODING: [0xf7,0x63,0x4e,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c04e63f7 <unknown>
+
+movt    zt0[56], xzr  // 11000000-01001110-01110011-11111111
+// CHECK-INST: movt    zt0[56], xzr
+// CHECK-ENCODING: [0xff,0x73,0x4e,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c04e73ff <unknown>
+

diff  --git a/llvm/test/MC/AArch64/SME2/str-diagnostics.s b/llvm/test/MC/AArch64/SME2/str-diagnostics.s
new file mode 100644
index 0000000000000..00659829fe616
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/str-diagnostics.s
@@ -0,0 +1,6 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2  2>&1 < %s| FileCheck %s
+
+str zt, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid lookup table, expected zt0
+// CHECK-NEXT: str zt, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:

diff  --git a/llvm/test/MC/AArch64/SME2/str.s b/llvm/test/MC/AArch64/SME2/str.s
new file mode 100644
index 0000000000000..97abc4ce01cd6
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/str.s
@@ -0,0 +1,38 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %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=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme2 - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=-sme2 - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sme2 -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+
+str     zt0, [x0]  // 11100001-00111111-10000000-00000000
+// CHECK-INST: str     zt0, [x0]
+// CHECK-ENCODING: [0x00,0x80,0x3f,0xe1]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: e13f8000 <unknown>
+
+str     zt0, [x10]  // 11100001-00111111-10000001-01000000
+// CHECK-INST: str     zt0, [x10]
+// CHECK-ENCODING: [0x40,0x81,0x3f,0xe1]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: e13f8140 <unknown>
+
+str     zt0, [x13]  // 11100001-00111111-10000001-10100000
+// CHECK-INST: str     zt0, [x13]
+// CHECK-ENCODING: [0xa0,0x81,0x3f,0xe1]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: e13f81a0 <unknown>
+
+str     zt0, [sp]  // 11100001-00111111-10000011-11100000
+// CHECK-INST: str     zt0, [sp]
+// CHECK-ENCODING: [0xe0,0x83,0x3f,0xe1]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: e13f83e0 <unknown>
+

diff  --git a/llvm/test/MC/AArch64/SME2/zero.s b/llvm/test/MC/AArch64/SME2/zero.s
new file mode 100644
index 0000000000000..511aff8d57e8c
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/zero.s
@@ -0,0 +1,20 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %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=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme2 - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2 < %s \
+// RUN:        | llvm-objdump -d --mattr=-sme2 - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sme2 -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+
+zero    {zt0}  // 11000000-01001000-00000000-00000001
+// CHECK-INST: zero    { zt0 }
+// CHECK-ENCODING: [0x01,0x00,0x48,0xc0]
+// CHECK-ERROR: instruction requires: sme2
+// CHECK-UNKNOWN: c0480001 <unknown>
+


        


More information about the llvm-commits mailing list