[llvm] 15af3aa - [AArch64][SME] Add system registers and related instructions

Cullen Rhodes via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 20 01:14:33 PDT 2021


Author: Cullen Rhodes
Date: 2021-07-20T08:06:26Z
New Revision: 15af3aaa2e8a23745295d363977bf6abeb0cda23

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

LOG: [AArch64][SME] Add system registers and related instructions

This patch adds the new system registers introduced in SME:

  - ID_AA64SMFR0_EL1 (ro) SME feature identifier.
  - SMCR_ELx (r/w) streaming mode control register for configuring
    effective SVE Streaming SVE Vector length when the PE is in
    Streaming SVE mode.
  - SVCR (r/w) streaming vector control register, visible at all
    exception levels. Provides access to PSTATE.SM and PSTATE.ZA
    using MSR and MRS instructions.
  - SMPRI_EL1 (r/w) streaming mode execution priority register.
  - SMPRIMAP_EL2 (r/w) streaming mode priority mapping register.
  - SMIDR_EL1 (ro) streaming mode identification register.
  - TPIDR2_EL0 (r/w) for use by SME software to manage per-thread
    SME context.
  - MPAMSM_EL1 (r/w) MPAM (v8.4) streaming mode register, for
    labelling memory accesses performed in streaming mode.

Also added in this patch are the SME mode change instructions.
Three MSR immediate instructions are implemented to set or clear
PSTATE.SM, PSTATE.ZA, or both respectively:

  - MSR SVCRSM, #<imm1>
  - MSR SVCRZA, #<imm1>
  - MSR SVCRSMZA, #<imm1>

The following smstart/smstop aliases are also implemented for
convenience:

  smstart    -> MSR SVCRSMZA, #1
  smstart sm -> MSR SVCRSM,   #1
  smstart za -> MSR SVCRZA,   #1

  smstop     -> MSR SVCRSMZA, #0
  smstop sm  -> MSR SVCRSM,   #0
  smstop za  -> MSR SVCRZA,   #0

The reference can be found here:
https://developer.arm.com/documentation/ddi0602/2021-06

Reviewed By: david-arm

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

Added: 
    llvm/test/MC/AArch64/SME/smstart-diagnostics.s
    llvm/test/MC/AArch64/SME/smstart.s
    llvm/test/MC/AArch64/SME/smstop-diagnostics.s
    llvm/test/MC/AArch64/SME/smstop.s
    llvm/test/MC/AArch64/SME/system-regs-diagnostics.s
    llvm/test/MC/AArch64/SME/system-regs-mpam.s
    llvm/test/MC/AArch64/SME/system-regs.s

Modified: 
    llvm/lib/Target/AArch64/AArch64RegisterInfo.td
    llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
    llvm/lib/Target/AArch64/AArch64SystemOperands.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/Utils/AArch64BaseInfo.cpp
    llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
index 0853db7d567f0..bdccf11a6ca05 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
@@ -1356,3 +1356,20 @@ def MatrixIndexGPR32_12_15 : RegisterClass<"AArch64", [i32], 32, (sequence "W%u"
 def MatrixIndexGPR32Op12_15 : RegisterOperand<MatrixIndexGPR32_12_15> {
   let EncoderMethod = "encodeMatrixIndexGPR32";
 }
+
+def SVCROperand : AsmOperandClass {
+  let Name = "SVCR";
+  let ParserMethod = "tryParseSVCR";
+  let DiagnosticType = "Invalid" # Name;
+}
+
+def svcr_op : Operand<i32> {
+  let ParserMatchClass = SVCROperand;
+  let PrintMethod = "printSVCROp";
+  let DecoderMethod = "DecodeSVCROp";
+  let MCOperandPredicate = [{
+    if (!MCOp.isImm())
+      return false;
+    return AArch64SVCR::lookupSVCRByEncoding(MCOp.getImm()) != nullptr;
+  }];
+}

diff  --git a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
index 2c1595bdb70f9..3ac189f301eeb 100644
--- a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
@@ -74,6 +74,41 @@ let Predicates = [HasSME] in {
 defm LD1_MXIPXX : sme_mem_ld_ss<"ld1">;
 defm ST1_MXIPXX : sme_mem_st_ss<"st1">;
 
+//===----------------------------------------------------------------------===//
+// Mode selection and state access instructions
+//===----------------------------------------------------------------------===//
+
+// SME defines three pstate fields to set or clear PSTATE.SM, PSTATE.ZA, or
+// both fields:
+//
+//   MSR SVCRSM, #<imm1>
+//   MSR SVCRZA, #<imm1>
+//   MSR SVCRSMZA, #<imm1>
+//
+// It's tricky to using the existing pstate operand defined in
+// AArch64SystemOperands.td since it only encodes 5 bits including op1;op2,
+// when these fields are also encoded in CRm[3:1].
+class MSRpstatesvcrImm0_1
+  : PstateWriteSimple<(ins svcr_op:$pstatefield, imm0_1:$imm), "msr",
+                      "\t$pstatefield, $imm">,
+    Sched<[WriteSys]> {
+  bits<3> pstatefield;
+  bit imm;
+  let Inst{18-16} = 0b011; // op1
+  let Inst{11-9} = pstatefield;
+  let Inst{8} = imm;
+  let Inst{7-5} = 0b011; // op2
+}
+
+def MSRpstatesvcrImm1 : MSRpstatesvcrImm0_1;
+def : InstAlias<"smstart",    (MSRpstatesvcrImm1 0b011, 0b1)>;
+def : InstAlias<"smstart sm", (MSRpstatesvcrImm1 0b001, 0b1)>;
+def : InstAlias<"smstart za", (MSRpstatesvcrImm1 0b010, 0b1)>;
+
+def : InstAlias<"smstop",     (MSRpstatesvcrImm1 0b011, 0b0)>;
+def : InstAlias<"smstop sm",  (MSRpstatesvcrImm1 0b001, 0b0)>;
+def : InstAlias<"smstop za",  (MSRpstatesvcrImm1 0b010, 0b0)>;
+
 //===----------------------------------------------------------------------===//
 // SVE2 instructions
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/lib/Target/AArch64/AArch64SystemOperands.td b/llvm/lib/Target/AArch64/AArch64SystemOperands.td
index 8594ec9dac729..f400916c97c93 100644
--- a/llvm/lib/Target/AArch64/AArch64SystemOperands.td
+++ b/llvm/lib/Target/AArch64/AArch64SystemOperands.td
@@ -368,6 +368,26 @@ def : PState<"SSBS",    0b11001>;
 let Requires = [{ {AArch64::FeatureMTE} }] in
 def : PState<"TCO",     0b11100>;
 
+//===----------------------------------------------------------------------===//
+// SVCR instruction options.
+//===----------------------------------------------------------------------===//
+
+class SVCR<string name, bits<3> encoding> : SearchableTable {
+  let SearchableFields = ["Name", "Encoding"];
+  let EnumValueField = "Encoding";
+
+  string Name = name;
+  bits<3> Encoding;
+  let Encoding = encoding;
+  code Requires = [{ {} }];
+}
+
+let Requires = [{ {AArch64::FeatureSME} }] in {
+def : SVCR<"SVCRSM",   0b001>;
+def : SVCR<"SVCRZA",   0b010>;
+def : SVCR<"SVCRSMZA", 0b011>;
+}
+
 //===----------------------------------------------------------------------===//
 // PSB instruction options.
 //===----------------------------------------------------------------------===//
@@ -758,6 +778,12 @@ def : RWSysReg<"GPCCR_EL3", 0b11, 0b110, 0b0010, 0b0001, 0b110>;
 def : RWSysReg<"GPTBR_EL3", 0b11, 0b110, 0b0010, 0b0001, 0b100>;
 }
 
+// v9-a Scalable Matrix Extension (SME) registers
+//                                 Op0   Op1    CRn     CRm     Op2
+let Requires = [{ {AArch64::FeatureSME} }] in {
+def : ROSysReg<"ID_AA64SMFR0_EL1", 0b11, 0b000, 0b0000, 0b0100, 0b101>;
+}
+
 //===----------------------
 // Write-only regs
 //===----------------------
@@ -1616,3 +1642,23 @@ def : RWSysReg<"PMSNEVFR_EL1",      0b11, 0b000, 0b1001, 0b1001, 0b001>;
 //                                 Op0    Op1     CRn     CRm    Op2
 let Requires = [{ {AArch64::ProcAppleA7} }] in
 def : RWSysReg<"CPM_IOACC_CTL_EL3", 0b11, 0b111, 0b1111, 0b0010, 0b000>;
+
+// Scalable Matrix Extension (SME)
+//                                 Op0   Op1    CRn     CRm     Op2
+let Requires = [{ {AArch64::FeatureSME} }] in {
+def : RWSysReg<"SMCR_EL1",         0b11, 0b000, 0b0001, 0b0010, 0b110>;
+def : RWSysReg<"SMCR_EL2",         0b11, 0b100, 0b0001, 0b0010, 0b110>;
+def : RWSysReg<"SMCR_EL3",         0b11, 0b110, 0b0001, 0b0010, 0b110>;
+def : RWSysReg<"SMCR_EL12",        0b11, 0b101, 0b0001, 0b0010, 0b110>;
+def : RWSysReg<"SVCR",             0b11, 0b011, 0b0100, 0b0010, 0b010>;
+def : RWSysReg<"SMPRI_EL1",        0b11, 0b000, 0b0001, 0b0010, 0b100>;
+def : RWSysReg<"SMPRIMAP_EL2",     0b11, 0b100, 0b0001, 0b0010, 0b101>;
+def : ROSysReg<"SMIDR_EL1",        0b11, 0b001, 0b0000, 0b0000, 0b110>;
+def : RWSysReg<"TPIDR2_EL0",       0b11, 0b011, 0b1101, 0b0000, 0b101>;
+} // HasSME
+
+// v8.4a MPAM and SME registers
+//                              Op0   Op1    CRn     CRm     Op2
+let Requires = [{ {AArch64::FeatureMPAM, AArch64::FeatureSME} }] in {
+def : RWSysReg<"MPAMSM_EL1",    0b11, 0b000, 0b1010, 0b0101, 0b011>;
+} // HasMPAM, HasSME

diff  --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 418ce74584afd..7067050b1947a 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -233,6 +233,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
   OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
                                               RegKind MatchKind);
   OperandMatchResultTy tryParseMatrixRegister(OperandVector &Operands);
+  OperandMatchResultTy tryParseSVCR(OperandVector &Operands);
   OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
   OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
   OperandMatchResultTy tryParseBarriernXSOperand(OperandVector &Operands);
@@ -321,6 +322,7 @@ class AArch64Operand : public MCParsedAsmOperand {
     k_CondCode,
     k_Register,
     k_MatrixRegister,
+    k_SVCR,
     k_VectorList,
     k_VectorIndex,
     k_Token,
@@ -448,6 +450,12 @@ class AArch64Operand : public MCParsedAsmOperand {
     unsigned Val;
   };
 
+  struct SVCROp {
+    const char *Data;
+    unsigned Length;
+    unsigned PStateField;
+  };
+
   union {
     struct TokOp Tok;
     struct RegOp Reg;
@@ -465,6 +473,7 @@ class AArch64Operand : public MCParsedAsmOperand {
     struct PSBHintOp PSBHint;
     struct BTIHintOp BTIHint;
     struct ShiftExtendOp ShiftExtend;
+    struct SVCROp SVCR;
   };
 
   // Keep the MCContext around as the MCExprs may need manipulated during
@@ -527,6 +536,9 @@ class AArch64Operand : public MCParsedAsmOperand {
     case k_ShiftExtend:
       ShiftExtend = o.ShiftExtend;
       break;
+    case k_SVCR:
+      SVCR = o.SVCR;
+      break;
     }
   }
 
@@ -665,6 +677,11 @@ class AArch64Operand : public MCParsedAsmOperand {
     return StringRef(BTIHint.Data, BTIHint.Length);
   }
 
+  StringRef getSVCR() const {
+    assert(Kind == k_SVCR && "Invalid access!");
+    return StringRef(SVCR.Data, SVCR.Length);
+  }
+
   StringRef getPrefetchName() const {
     assert(Kind == k_Prefetch && "Invalid access!");
     return StringRef(Prefetch.Data, Prefetch.Length);
@@ -1099,6 +1116,12 @@ class AArch64Operand : public MCParsedAsmOperand {
     return SysReg.PStateField != -1U;
   }
 
+  bool isSVCR() const {
+    if (Kind != k_SVCR)
+      return false;
+    return SVCR.PStateField != -1U;
+  }
+
   bool isReg() const override {
     return Kind == k_Register;
   }
@@ -1809,6 +1832,12 @@ class AArch64Operand : public MCParsedAsmOperand {
     Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
   }
 
+  void addSVCROperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+
+    Inst.addOperand(MCOperand::createImm(SVCR.PStateField));
+  }
+
   void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
 
@@ -2114,6 +2143,17 @@ class AArch64Operand : public MCParsedAsmOperand {
     return Op;
   }
 
+  static std::unique_ptr<AArch64Operand>
+  CreateSVCR(uint32_t PStateField, StringRef Str, SMLoc S, MCContext &Ctx) {
+    auto Op = std::make_unique<AArch64Operand>(k_SVCR, Ctx);
+    Op->SVCR.PStateField = PStateField;
+    Op->SVCR.Data = Str.data();
+    Op->SVCR.Length = Str.size();
+    Op->StartLoc = S;
+    Op->EndLoc = S;
+    return Op;
+  }
+
   static std::unique_ptr<AArch64Operand>
   CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
                     bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
@@ -2195,6 +2235,10 @@ void AArch64Operand::print(raw_ostream &OS) const {
   case k_MatrixRegister:
     OS << "<matrix " << getMatrixReg() << ">";
     break;
+  case k_SVCR: {
+    OS << getSVCR();
+    break;
+  }
   case k_Register:
     OS << "<register " << getReg() << ">";
     if (!getShiftExtendAmount() && !hasShiftExtendAmount())
@@ -2975,6 +3019,28 @@ bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
   return false;
 }
 
+OperandMatchResultTy
+AArch64AsmParser::tryParseSVCR(OperandVector &Operands) {
+  MCAsmParser &Parser = getParser();
+  const AsmToken &Tok = Parser.getTok();
+  SMLoc S = getLoc();
+
+  if (Tok.isNot(AsmToken::Identifier)) {
+    TokError("invalid operand for instruction");
+    return MatchOperand_ParseFail;
+  }
+
+  unsigned PStateImm = -1;
+  const auto *SVCR = AArch64SVCR::lookupSVCRByName(Tok.getString());
+  if (SVCR && SVCR->haveFeatures(getSTI().getFeatureBits()))
+    PStateImm = SVCR->Encoding;
+
+  Operands.push_back(
+      AArch64Operand::CreateSVCR(PStateImm, Tok.getString(), S, getContext()));
+  Parser.Lex(); // Eat identifier token.
+  return MatchOperand_Success;
+}
+
 OperandMatchResultTy
 AArch64AsmParser::tryParseMatrixRegister(OperandVector &Operands) {
   MCAsmParser &Parser = getParser();
@@ -3431,6 +3497,9 @@ AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
   if (Tok.isNot(AsmToken::Identifier))
     return MatchOperand_NoMatch;
 
+  if (AArch64SVCR::lookupSVCRByName(Tok.getString()))
+    return MatchOperand_NoMatch;
+
   int MRSReg, MSRReg;
   auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
   if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
@@ -3946,8 +4015,15 @@ bool AArch64AsmParser::parseKeywordOperand(OperandVector &Operands) {
   auto Tok = Parser.getTok();
   if (Tok.isNot(AsmToken::Identifier))
     return true;
-  Operands.push_back(AArch64Operand::CreateToken(Tok.getString(), false,
-                                                 Tok.getLoc(), getContext()));
+
+  auto Keyword = Tok.getString();
+  Keyword = StringSwitch<StringRef>(Keyword.lower())
+                .Case("sm", "sm")
+                .Case("za", "za")
+                .Default(Keyword);
+  Operands.push_back(
+      AArch64Operand::CreateToken(Keyword, false, Tok.getLoc(), getContext()));
+
   Parser.Lex();
   return false;
 }
@@ -4021,6 +4097,11 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
     if (!parseOptionalMulOperand(Operands))
       return false;
 
+    // If this is an "smstart" or "smstop" instruction, parse its special
+    // keyword operand as an identifier.
+    if (Mnemonic == "smstart" || Mnemonic == "smstop")
+      return parseKeywordOperand(Operands);
+
     // This could be an optional "shift" or "extend" operand.
     OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
     // We can only continue if no tokens were eaten.
@@ -4876,6 +4957,7 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
   case Match_MRS:
     return Error(Loc, "expected readable system register");
   case Match_MSR:
+  case Match_InvalidSVCR:
     return Error(Loc, "expected writable system register or pstate");
   case Match_InvalidComplexRotationEven:
     return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
@@ -5551,6 +5633,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidMatrixTileVectorV32:
   case Match_InvalidMatrixTileVectorV64:
   case Match_InvalidMatrixTileVectorV128:
+  case Match_InvalidSVCR:
   case Match_MSR:
   case Match_MRS: {
     if (ErrorInfo >= Operands.size())
@@ -6435,6 +6518,14 @@ unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
   case MCK__HASH_8:
     ExpectedVal = 8;
     break;
+  case MCK_MPR:
+    // If the Kind is a token for the MPR register class which has the "za"
+    // register (SME accumulator array), check if the asm is a literal "za"
+    // token. This is for the "smstart za" alias that defines the register
+    // as a literal token.
+    if (Op.isTokenEqual("za"))
+      return Match_Success;
+    break;
   }
   if (!Op.isImm())
     return Match_InvalidOperand;

diff  --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 6c1ecfb2591a8..d858f47db5691 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -233,6 +233,8 @@ static DecodeStatus DecodeImm8OptLsl(MCInst &Inst, unsigned Imm,
                                      uint64_t Addr, const void *Decoder);
 static DecodeStatus DecodeSVEIncDecImm(MCInst &Inst, unsigned Imm,
                                        uint64_t Addr, const void *Decoder);
+static DecodeStatus DecodeSVCROp(MCInst &Inst, unsigned Imm, uint64_t Address,
+                                 const void *Decoder);
 
 static bool Check(DecodeStatus &Out, DecodeStatus In) {
   switch (In) {
@@ -1992,3 +1994,12 @@ static DecodeStatus DecodeSVEIncDecImm(MCInst &Inst, unsigned Imm,
   Inst.addOperand(MCOperand::createImm(Imm + 1));
   return Success;
 }
+
+static DecodeStatus DecodeSVCROp(MCInst &Inst, unsigned Imm, uint64_t Address,
+                                 const void *Decoder) {
+  if (AArch64SVCR::lookupSVCRByEncoding(Imm)) {
+    Inst.addOperand(MCOperand::createImm(Imm));
+    return Success;
+  }
+  return Fail;
+}

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 9ef35c5b047b9..1e0980515ae3c 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -933,6 +933,17 @@ void AArch64InstPrinter::printMatrixTile(const MCInst *MI, unsigned OpNum,
   O << getRegisterName(RegOp.getReg());
 }
 
+void AArch64InstPrinter::printSVCROp(const MCInst *MI, unsigned OpNum,
+                                     const MCSubtargetInfo &STI,
+                                     raw_ostream &O) {
+  const MCOperand &MO = MI->getOperand(OpNum);
+  assert(MO.isImm() && "Unexpected operand type!");
+  unsigned svcrop = MO.getImm();
+  const auto *SVCR = AArch64SVCR::lookupSVCRByEncoding(svcrop);
+  assert(SVCR && "Unexpected SVCR operand!");
+  O << SVCR->Name;
+}
+
 void AArch64InstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
                                       const MCSubtargetInfo &STI,
                                       raw_ostream &O) {

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
index 109d25507e613..566a946d521ab 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
@@ -196,6 +196,8 @@ class AArch64InstPrinter : public MCInstPrinter {
   template <int EltSize>
   void printMatrix(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
                    raw_ostream &O);
+  void printSVCROp(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
+                   raw_ostream &O);
   template <char = 0>
   void printSVERegOp(const MCInst *MI, unsigned OpNum,
                     const MCSubtargetInfo &STI, raw_ostream &O);

diff  --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
index ac59d73fd9fd6..20aec47b39d3a 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
+++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
@@ -169,3 +169,10 @@ namespace llvm {
 #include "AArch64GenSystemOperands.inc"
   }
 }
+
+namespace llvm {
+  namespace AArch64SVCR {
+#define GET_SVCR_IMPL
+#include "AArch64GenSystemOperands.inc"
+  }
+}

diff  --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
index 1b13c94389cb5..ce68661542421 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
+++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
@@ -346,6 +346,14 @@ struct SysAliasImm : SysAlias {
       : SysAlias(N, E, F), ImmValue(I) {}
 };
 
+namespace AArch64SVCR {
+  struct SVCR : SysAlias{
+    using SysAlias::SysAlias;
+  };
+  #define GET_SVCR_DECL
+  #include "AArch64GenSystemOperands.inc"
+}
+
 namespace AArch64AT{
   struct AT : SysAlias {
     using SysAlias::SysAlias;

diff  --git a/llvm/test/MC/AArch64/SME/smstart-diagnostics.s b/llvm/test/MC/AArch64/SME/smstart-diagnostics.s
new file mode 100644
index 0000000000000..5cd04cbf8ba15
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME/smstart-diagnostics.s
@@ -0,0 +1,9 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme 2>&1 < %s| FileCheck %s
+
+// ------------------------------------------------------------------------- //
+// Invalid keyword
+
+smstart foo
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: smstart foo
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:

diff  --git a/llvm/test/MC/AArch64/SME/smstart.s b/llvm/test/MC/AArch64/SME/smstart.s
new file mode 100644
index 0000000000000..d7a6c8a39baad
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME/smstart.s
@@ -0,0 +1,38 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme < %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=+sme < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme < %s \
+// RUN:        | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+
+smstart
+// CHECK-INST: smstart
+// CHECK-ENCODING: [0x7f,0x47,0x03,0xd5]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 7f 47 03 d5   msr   S0_3_C4_C7_3, xzr
+
+smstart sm
+// CHECK-INST: smstart sm
+// CHECK-ENCODING: [0x7f,0x43,0x03,0xd5]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 7f 43 03 d5   msr   S0_3_C4_C3_3, xzr
+
+smstart za
+// CHECK-INST: smstart za
+// CHECK-ENCODING: [0x7f,0x45,0x03,0xd5]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 7f 45 03 d5   msr   S0_3_C4_C5_3, xzr
+
+smstart SM
+// CHECK-INST: smstart sm
+// CHECK-ENCODING: [0x7f,0x43,0x03,0xd5]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 7f 43 03 d5   msr   S0_3_C4_C3_3, xzr
+
+smstart ZA
+// CHECK-INST: smstart za
+// CHECK-ENCODING: [0x7f,0x45,0x03,0xd5]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 7f 45 03 d5   msr   S0_3_C4_C5_3, xzr

diff  --git a/llvm/test/MC/AArch64/SME/smstop-diagnostics.s b/llvm/test/MC/AArch64/SME/smstop-diagnostics.s
new file mode 100644
index 0000000000000..68fda5074c1f4
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME/smstop-diagnostics.s
@@ -0,0 +1,9 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme 2>&1 < %s| FileCheck %s
+
+// ------------------------------------------------------------------------- //
+// Invalid keyword
+
+smstop foo
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: smstop foo
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:

diff  --git a/llvm/test/MC/AArch64/SME/smstop.s b/llvm/test/MC/AArch64/SME/smstop.s
new file mode 100644
index 0000000000000..b1d8f2a70229d
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME/smstop.s
@@ -0,0 +1,38 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme < %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=+sme < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme < %s \
+// RUN:        | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+
+smstop
+// CHECK-INST: smstop
+// CHECK-ENCODING: [0x7f,0x46,0x03,0xd5]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 7f 46 03 d5   msr   S0_3_C4_C6_3, xzr
+
+smstop sm
+// CHECK-INST: smstop sm
+// CHECK-ENCODING: [0x7f,0x42,0x03,0xd5]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 7f 42 03 d5   msr   S0_3_C4_C2_3, xzr
+
+smstop za
+// CHECK-INST: smstop za
+// CHECK-ENCODING: [0x7f,0x44,0x03,0xd5]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 7f 44 03 d5   msr   S0_3_C4_C4_3, xzr
+
+smstop SM
+// CHECK-INST: smstop sm
+// CHECK-ENCODING: [0x7f,0x42,0x03,0xd5]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 7f 42 03 d5   msr   S0_3_C4_C2_3, xzr
+
+smstop ZA
+// CHECK-INST: smstop za
+// CHECK-ENCODING: [0x7f,0x44,0x03,0xd5]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 7f 44 03 d5   msr   S0_3_C4_C4_3, xzr

diff  --git a/llvm/test/MC/AArch64/SME/system-regs-diagnostics.s b/llvm/test/MC/AArch64/SME/system-regs-diagnostics.s
new file mode 100644
index 0000000000000..669c9cace7f9e
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME/system-regs-diagnostics.s
@@ -0,0 +1,28 @@
+// RUN: not llvm-mc -triple aarch64 -mattr=+sme -show-encoding < %s 2>&1 | FileCheck %s
+
+
+// --------------------------------------------------------------------------//
+// Check read-only
+
+msr ID_AA64SMFR0_EL1, x3
+// CHECK: error: expected writable system register or pstate
+// CHECK-NEXT: msr ID_AA64SMFR0_EL1, x3
+
+msr SMIDR_EL1, x3
+// CHECK: error: expected writable system register or pstate
+// CHECK-NEXT: msr SMIDR_EL1, x3
+
+// --------------------------------------------------------------------------//
+// Check MSR SVCR immediate is in range [0, 1]
+
+msr SVCRSM, #-1
+// CHECK: error: immediate must be an integer in range [0, 1].
+// CHECK-NEXT: msr SVCRSM, #-1
+
+msr SVCRZA, #2
+// CHECK: error: immediate must be an integer in range [0, 1].
+// CHECK-NEXT: msr SVCRZA, #2
+
+msr SVCRSMZA, #4
+// CHECK: error: immediate must be an integer in range [0, 1].
+// CHECK-NEXT: msr SVCRSMZA, #4

diff  --git a/llvm/test/MC/AArch64/SME/system-regs-mpam.s b/llvm/test/MC/AArch64/SME/system-regs-mpam.s
new file mode 100644
index 0000000000000..1bd473d9da00a
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME/system-regs-mpam.s
@@ -0,0 +1,34 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme,+mpam < %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: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme < %s 2>&1 \
+// RUN:        | FileCheck %s --check-prefix=CHECK-ERROR
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+mpam < %s 2>&1 \
+// RUN:        | FileCheck %s --check-prefix=CHECK-ERROR
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme,+mpam < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme,+mpam - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme,+mpam < %s \
+// RUN:        | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme,+mpam < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme,+mpam < %s \
+// RUN:        | llvm-objdump -d --mattr=+mpam - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+
+// --------------------------------------------------------------------------//
+// read
+
+mrs x3, MPAMSM_EL1
+// CHECK-INST: mrs x3, MPAMSM_EL1
+// CHECK-ENCODING: [0x63,0xa5,0x38,0xd5]
+// CHECK-ERROR: expected readable system register
+// CHECK-UNKNOWN: 63 a5 38 d5   mrs   x3, S3_0_C10_C5_3
+
+// --------------------------------------------------------------------------//
+// write
+
+msr MPAMSM_EL1, x3
+// CHECK-INST: msr MPAMSM_EL1, x3
+// CHECK-ENCODING: [0x63,0xa5,0x18,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: 63 a5 18 d5   msr   S3_0_C10_C5_3, x3

diff  --git a/llvm/test/MC/AArch64/SME/system-regs.s b/llvm/test/MC/AArch64/SME/system-regs.s
new file mode 100644
index 0000000000000..c09a420e2396b
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME/system-regs.s
@@ -0,0 +1,158 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme < %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=+sme < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme < %s \
+// RUN:        | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+
+// --------------------------------------------------------------------------//
+// read
+
+mrs x3, ID_AA64SMFR0_EL1
+// CHECK-INST: mrs x3, ID_AA64SMFR0_EL1
+// CHECK-ENCODING: [0xa3,0x04,0x38,0xd5]
+// CHECK-ERROR: expected readable system register
+// CHECK-UNKNOWN: a3 04 38 d5   mrs   x3, S3_0_C0_C4_5
+
+mrs x3, SMCR_EL1
+// CHECK-INST: mrs x3, SMCR_EL1
+// CHECK-ENCODING: [0xc3,0x12,0x38,0xd5]
+// CHECK-ERROR: expected readable system register
+// CHECK-UNKNOWN: c3 12 38 d5   mrs   x3, S3_0_C1_C2_6
+
+mrs x3, SMCR_EL2
+// CHECK-INST: mrs x3, SMCR_EL2
+// CHECK-ENCODING: [0xc3,0x12,0x3c,0xd5]
+// CHECK-ERROR: expected readable system register
+// CHECK-UNKNOWN: c3 12 3c d5   mrs   x3, S3_4_C1_C2_6
+
+mrs x3, SMCR_EL3
+// CHECK-INST: mrs x3, SMCR_EL3
+// CHECK-ENCODING: [0xc3,0x12,0x3e,0xd5]
+// CHECK-ERROR: expected readable system register
+// CHECK-UNKNOWN: c3 12 3e d5   mrs   x3, S3_6_C1_C2_6
+
+mrs x3, SMCR_EL12
+// CHECK-INST: mrs x3, SMCR_EL12
+// CHECK-ENCODING: [0xc3,0x12,0x3d,0xd5]
+// CHECK-ERROR: expected readable system register
+// CHECK-UNKNOWN: c3 12 3d d5   mrs   x3, S3_5_C1_C2_6
+
+mrs x3, SVCR
+// CHECK-INST: mrs x3, SVCR
+// CHECK-ENCODING: [0x43,0x42,0x3b,0xd5]
+// CHECK-ERROR: expected readable system register
+// CHECK-UNKNOWN: 43 42 3b d5   mrs   x3, S3_3_C4_C2_2
+
+mrs x3, SMPRI_EL1
+// CHECK-INST: mrs x3, SMPRI_EL1
+// CHECK-ENCODING: [0x83,0x12,0x38,0xd5]
+// CHECK-ERROR: expected readable system register
+// CHECK-UNKNOWN: 83 12 38 d5   mrs   x3, S3_0_C1_C2_4
+
+mrs x3, SMPRIMAP_EL2
+// CHECK-INST: mrs x3, SMPRIMAP_EL2
+// CHECK-ENCODING: [0xa3,0x12,0x3c,0xd5]
+// CHECK-ERROR: expected readable system register
+// CHECK-UNKNOWN: a3 12 3c d5   mrs   x3, S3_4_C1_C2_5
+
+mrs x3, SMIDR_EL1
+// CHECK-INST: mrs x3, SMIDR_EL1
+// CHECK-ENCODING: [0xc3,0x00,0x39,0xd5]
+// CHECK-ERROR: expected readable system register
+// CHECK-UNKNOWN: c3 00 39 d5   mrs   x3, S3_1_C0_C0_6
+
+mrs x3, TPIDR2_EL0
+// CHECK-INST: mrs x3, TPIDR2_EL0
+// CHECK-ENCODING: [0xa3,0xd0,0x3b,0xd5]
+// CHECK-ERROR: expected readable system register
+// CHECK-UNKNOWN: a3 d0 3b d5   mrs   x3, S3_3_C13_C0_5
+
+// --------------------------------------------------------------------------//
+// write
+
+msr SMCR_EL1, x3
+// CHECK-INST: msr SMCR_EL1, x3
+// CHECK-ENCODING: [0xc3,0x12,0x18,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: c3 12 18 d5   msr   S3_0_C1_C2_6, x3
+
+msr SMCR_EL2, x3
+// CHECK-INST: msr SMCR_EL2, x3
+// CHECK-ENCODING: [0xc3,0x12,0x1c,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: c3 12 1c d5   msr   S3_4_C1_C2_6, x3
+
+msr SMCR_EL3, x3
+// CHECK-INST: msr SMCR_EL3, x3
+// CHECK-ENCODING: [0xc3,0x12,0x1e,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: c3 12 1e d5   msr   S3_6_C1_C2_6, x3
+
+msr SMCR_EL12, x3
+// CHECK-INST: msr SMCR_EL12, x3
+// CHECK-ENCODING: [0xc3,0x12,0x1d,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: c3 12 1d d5   msr   S3_5_C1_C2_6, x3
+
+msr SVCR, x3
+// CHECK-INST: msr SVCR, x3
+// CHECK-ENCODING: [0x43,0x42,0x1b,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: 43 42 1b d5   msr   S3_3_C4_C2_2, x3
+
+msr SMPRI_EL1, x3
+// CHECK-INST: msr SMPRI_EL1, x3
+// CHECK-ENCODING: [0x83,0x12,0x18,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: 83 12 18 d5   msr   S3_0_C1_C2_4, x3
+
+msr SMPRIMAP_EL2, x3
+// CHECK-INST: msr SMPRIMAP_EL2, x3
+// CHECK-ENCODING: [0xa3,0x12,0x1c,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: a3 12 1c d5   msr   S3_4_C1_C2_5, x3
+
+msr SVCRSM, #0
+// CHECK-INST: smstop sm
+// CHECK-ENCODING: [0x7f,0x42,0x03,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: 7f 42 03 d5   msr   S0_3_C4_C2_3, xzr
+
+msr SVCRSM, #1
+// CHECK-INST: smstart
+// CHECK-ENCODING: [0x7f,0x43,0x03,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: 7f 43 03 d5   msr   S0_3_C4_C3_3, xzr
+
+msr SVCRZA, #0
+// CHECK-INST: smstop za
+// CHECK-ENCODING: [0x7f,0x44,0x03,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: 7f 44 03 d5   msr   S0_3_C4_C4_3, xzr
+
+msr SVCRZA, #1
+// CHECK-INST: smstart za
+// CHECK-ENCODING: [0x7f,0x45,0x03,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: 7f 45 03 d5   msr   S0_3_C4_C5_3, xzr
+
+msr SVCRSMZA, #0
+// CHECK-INST: smstop
+// CHECK-ENCODING: [0x7f,0x46,0x03,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: 7f 46 03 d5   msr   S0_3_C4_C6_3, xzr
+
+msr SVCRSMZA, #1
+// CHECK-INST: smstart
+// CHECK-ENCODING: [0x7f,0x47,0x03,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: 7f 47 03 d5   msr   S0_3_C4_C7_3, xzr
+
+msr TPIDR2_EL0, x3
+// CHECK-INST: msr TPIDR2_EL0, x3
+// CHECK-ENCODING: [0xa3,0xd0,0x1b,0xd5]
+// CHECK-ERROR: expected writable system register or pstate
+// CHECK-UNKNOWN: a3 d0 1b d5   msr   S3_3_C13_C0_5, x3


        


More information about the llvm-commits mailing list