diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -434,10 +434,13 @@ def HasV8_6aOps : SubtargetFeature< "v8.6a", "HasV8_6aOps", "true", "Support ARM v8.6a instructions", - [HasV8_5aOps, FeatureAMVS, FeatureBF16, FeatureFineGrainedTraps, FeatureEnhancedCounterVirtualization, FeatureMatMulInt8]>; +def HasV8_7aOps : SubtargetFeature< + "v8.7a", "HasV8_7aOps", "true", "Support ARM v8.7a instructions", + [HasV8_6aOps]>; + def HasV8_0rOps : SubtargetFeature< "v8r", "HasV8_0rOps", "true", "Support ARM v8r instructions", [//v8.1 diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -1296,8 +1296,9 @@ } // System instructions which have an Rt register. -class RtSystemI - : BaseSystemI, +class RtSystemI pattern = []> + : BaseSystemI, Sched<[WriteSys]> { bits<5> Rt; let Inst{4-0} = Rt; @@ -1325,6 +1326,16 @@ let Inst{4-0} = Rt; } +// System instructions that pass a register argument +// This class assumes the register is for input rather than output. +class RegInputSystemI CRm, bits<3> Op2, string asm, + list pattern = []> + : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> { + let Inst{20-12} = 0b000110001; + let Inst{11-8} = CRm; + let Inst{7-5} = Op2; +} + // System instructions for transactional memory - no operand class TMSystemINoOperand CRm, string asm, list pattern> : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> { @@ -1365,6 +1376,14 @@ let PrintMethod = "printBarrierOption"; let ParserMatchClass = BarrierAsmOperand; } +def BarriernXSAsmOperand : AsmOperandClass { + let Name = "BarriernXS"; + let ParserMethod = "tryParseBarriernXSOperand"; +} +def barrier_nxs_op : Operand { + let PrintMethod = "printBarriernXSOption"; + let ParserMatchClass = BarriernXSAsmOperand; +} class CRmSystemI opc, string asm, list pattern = []> : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>, diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -25,6 +25,8 @@ AssemblerPredicate<(all_of HasV8_5aOps), "armv8.5a">; def HasV8_6a : Predicate<"Subtarget->hasV8_6aOps()">, AssemblerPredicate<(all_of HasV8_6aOps), "armv8.6a">; +def HasV8_7a : Predicate<"Subtarget->hasV8_7aOps()">, + AssemblerPredicate<(all_of HasV8_7aOps), "armv8.7a">; def HasVH : Predicate<"Subtarget->hasVH()">, AssemblerPredicate<(all_of FeatureVH), "vh">; @@ -783,6 +785,16 @@ let Inst{12} = 0; let Predicates = [HasTRACEV8_4]; } + +let Predicates = [HasV8_7a] in { +def DSBnXS : CRmSystemI { + let CRm{1-0} = 0b11; + let Inst{9-8} = 0b10; +} +def WFET : RegInputSystemI<0b0000, 0b000, "wfet">; +def WFIT : RegInputSystemI<0b0000, 0b001, "wfit">; +} + } // ARMv8.2-A Dot Product diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -85,6 +85,7 @@ bool HasV8_4aOps = false; bool HasV8_5aOps = false; bool HasV8_6aOps = false; + bool HasV8_7aOps = false; bool HasV8_0rOps = false; bool HasCONTEXTIDREL2 = false; diff --git a/llvm/lib/Target/AArch64/AArch64SystemOperands.td b/llvm/lib/Target/AArch64/AArch64SystemOperands.td --- a/llvm/lib/Target/AArch64/AArch64SystemOperands.td +++ b/llvm/lib/Target/AArch64/AArch64SystemOperands.td @@ -604,6 +604,7 @@ def : ROSysReg<"ID_AA64AFR1_EL1", 0b11, 0b000, 0b0000, 0b0101, 0b101>; def : ROSysReg<"ID_AA64ISAR0_EL1", 0b11, 0b000, 0b0000, 0b0110, 0b000>; def : ROSysReg<"ID_AA64ISAR1_EL1", 0b11, 0b000, 0b0000, 0b0110, 0b001>; +def : ROSysReg<"ID_AA64ISAR2_EL1", 0b11, 0b000, 0b0000, 0b0110, 0b010>; def : ROSysReg<"ID_AA64MMFR0_EL1", 0b11, 0b000, 0b0000, 0b0111, 0b000>; def : ROSysReg<"ID_AA64MMFR1_EL1", 0b11, 0b000, 0b0000, 0b0111, 0b001>; def : ROSysReg<"ID_AA64MMFR2_EL1", 0b11, 0b000, 0b0000, 0b0111, 0b010>; @@ -819,6 +820,9 @@ def : RWSysReg<"ACTLR_EL2", 0b11, 0b100, 0b0001, 0b0000, 0b001>; def : RWSysReg<"ACTLR_EL3", 0b11, 0b110, 0b0001, 0b0000, 0b001>; def : RWSysReg<"HCR_EL2", 0b11, 0b100, 0b0001, 0b0001, 0b000>; +def : RWSysReg<"HCRX_EL2", 0b11, 0b100, 0b0001, 0b0010, 0b010> { + let Requires = [{ {AArch64::HasV8_7aOps} }]; +} def : RWSysReg<"SCR_EL3", 0b11, 0b110, 0b0001, 0b0001, 0b000>; def : RWSysReg<"MDCR_EL2", 0b11, 0b100, 0b0001, 0b0001, 0b001>; def : RWSysReg<"SDER32_EL3", 0b11, 0b110, 0b0001, 0b0001, 0b001>; diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -230,6 +230,7 @@ RegKind MatchKind); OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands); OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands); + OperandMatchResultTy tryParseBarriernXSOperand(OperandVector &Operands); OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands); OperandMatchResultTy tryParseSysReg(OperandVector &Operands); OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands); @@ -401,6 +402,7 @@ const char *Data; unsigned Length; unsigned Val; // Not the enum since not all values have names. + bool HasnXSModifier; }; struct SysRegOp { @@ -570,6 +572,11 @@ return StringRef(Barrier.Data, Barrier.Length); } + bool getBarriernXSModifier() const { + assert(Kind == k_Barrier && "Invalid access!"); + return Barrier.HasnXSModifier; + } + unsigned getReg() const override { assert(Kind == k_Register && "Invalid access!"); return Reg.RegNum; @@ -1031,7 +1038,12 @@ AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1; } - bool isBarrier() const { return Kind == k_Barrier; } + bool isBarrier() const { + return Kind == k_Barrier && !getBarriernXSModifier(); + } + bool isBarriernXS() const { + return Kind == k_Barrier && getBarriernXSModifier(); + } bool isSysReg() const { return Kind == k_SysReg; } bool isMRSSystemRegister() const { @@ -1721,6 +1733,11 @@ Inst.addOperand(MCOperand::createImm(getBarrier())); } + void addBarriernXSOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createImm(getBarrier())); + } + void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); @@ -1956,11 +1973,13 @@ static std::unique_ptr CreateBarrier(unsigned Val, StringRef Str, SMLoc S, - MCContext &Ctx) { + MCContext &Ctx, + bool HasnXSModifier) { auto Op = std::make_unique(k_Barrier, Ctx); Op->Barrier.Val = Val; Op->Barrier.Data = Str.data(); Op->Barrier.Length = Str.size(); + Op->Barrier.HasnXSModifier = HasnXSModifier; Op->StartLoc = S; Op->EndLoc = S; return Op; @@ -2906,6 +2925,8 @@ Str += "ARMv8.5a"; else if (FBS[AArch64::HasV8_6aOps]) Str += "ARMv8.6a"; + else if (FBS[AArch64::HasV8_7aOps]) + Str += "ARMv8.7a"; else { auto ext = std::find_if(std::begin(ExtensionMap), std::end(ExtensionMap), @@ -2985,15 +3006,25 @@ } createSysAlias(AT->Encoding, Operands, S); } else if (Mnemonic == "tlbi") { - const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op); - if (!TLBI) + bool HasnXSQualifier = Op.endswith_lower("nXS"); + if (HasnXSQualifier) { + Op = Op.drop_back(3); + } + const AArch64TLBI::TLBI *TLBIorig = AArch64TLBI::lookupTLBIByName(Op); + if (!TLBIorig) return TokError("invalid operand for TLBI instruction"); - else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) { - std::string Str("TLBI " + std::string(TLBI->Name) + " requires "); - setRequiredFeatureString(TLBI->getRequiredFeatures(), Str); + const AArch64TLBI::TLBI TLBI( + TLBIorig->Name, TLBIorig->Encoding | (HasnXSQualifier ? (1 << 7) : 0), + TLBIorig->NeedsReg, + TLBIorig->FeaturesRequired); + if (!TLBI.haveFeatures(getSTI().getFeatureBits())) { + std::string Name = + std::string(TLBI.Name) + (HasnXSQualifier ? "nXS" : ""); + std::string Str("TLBI " + Name + " requires "); + setRequiredFeatureString(TLBI.getRequiredFeatures(), Str); return TokError(Str.c_str()); } - createSysAlias(TLBI->Encoding, Operands, S); + createSysAlias(TLBI.Encoding, Operands, S); } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp") { const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByName(Op); if (!PRCTX) @@ -3044,11 +3075,11 @@ if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) { TokError("'csync' operand expected"); return MatchOperand_ParseFail; - // Can be either a #imm style literal or an option name } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) { // Immediate operand. const MCExpr *ImmVal; SMLoc ExprLoc = getLoc(); + AsmToken IntTok = Tok; if (getParser().parseExpression(ImmVal)) return MatchOperand_ParseFail; const MCConstantExpr *MCE = dyn_cast(ImmVal); @@ -3056,13 +3087,22 @@ Error(ExprLoc, "immediate value expected for barrier operand"); return MatchOperand_ParseFail; } - if (MCE->getValue() < 0 || MCE->getValue() > 15) { + int64_t Value = MCE->getValue(); + if (Mnemonic == "dsb" && Value > 15) { + // This case is a no match here, but it might be matched by the nXS + // variant. Deliberately not unlex the optional '#' as it is not necessary + // to characterize an integer immediate. + Parser.getLexer().UnLex(IntTok); + return MatchOperand_NoMatch; + } + if (Value < 0 || Value > 15) { Error(ExprLoc, "barrier operand out of range"); return MatchOperand_ParseFail; } - auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue()); - Operands.push_back(AArch64Operand::CreateBarrier( - MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext())); + auto DB = AArch64DB::lookupDBByEncoding(Value); + Operands.push_back(AArch64Operand::CreateBarrier(Value, DB ? DB->Name : "", + ExprLoc, getContext(), + false /*hasnXSModifier*/)); return MatchOperand_Success; } @@ -3071,9 +3111,10 @@ return MatchOperand_ParseFail; } - auto TSB = AArch64TSB::lookupTSBByName(Tok.getString()); + StringRef Operand = Tok.getString(); + auto TSB = AArch64TSB::lookupTSBByName(Operand); + auto DB = AArch64DB::lookupDBByName(Operand); // The only valid named option for ISB is 'sy' - auto DB = AArch64DB::lookupDBByName(Tok.getString()); if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) { TokError("'sy' or #imm operand expected"); return MatchOperand_ParseFail; @@ -3082,12 +3123,91 @@ TokError("'csync' operand expected"); return MatchOperand_ParseFail; } else if (!DB && !TSB) { + if (Mnemonic == "dsb") { + // This case is a no match here, but it might be matched by the nXS + // variant. + return MatchOperand_NoMatch; + } TokError("invalid barrier option name"); return MatchOperand_ParseFail; } Operands.push_back(AArch64Operand::CreateBarrier( - DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext())); + DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), + getContext(), false /*hasnXSModifier*/)); + Parser.Lex(); // Consume the option + + return MatchOperand_Success; +} + +OperandMatchResultTy +AArch64AsmParser::tryParseBarriernXSOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + const AsmToken &Tok = Parser.getTok(); + + assert(Mnemonic == "dsb" && "Instruction does not accept nXS operands"); + if (Mnemonic != "dsb") + return MatchOperand_ParseFail; + + if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) { + // Immediate operand. + const MCExpr *ImmVal; + SMLoc ExprLoc = getLoc(); + if (getParser().parseExpression(ImmVal)) + return MatchOperand_ParseFail; + const MCConstantExpr *MCE = dyn_cast(ImmVal); + if (!MCE) { + Error(ExprLoc, "immediate value expected for barrier operand"); + return MatchOperand_ParseFail; + } + int64_t Value = MCE->getValue(); + // v8.7-A DSB in the nXS variant accepts only the following immediate + // values: 16, 20, 24, 28. + if (Value != 16 && Value != 20 && Value != 24 && Value != 28) { + Error(ExprLoc, "barrier operand out of range"); + return MatchOperand_ParseFail; + } + // Prepare immediate value for encoding lookup. The regular DSB instruction + // lookup, also used here, expects encodings in the regular variant form. + // The lowest two bits are set and the fifth bit is discarded. + Value = (Value | 0x3) & 0xF; + if (Value < 0 || Value > 15) { + Error(ExprLoc, "barrier operand out of range"); + return MatchOperand_ParseFail; + } + auto DB = AArch64DB::lookupDBByEncoding(Value); + Operands.push_back(AArch64Operand::CreateBarrier(Value, DB ? DB->Name : "", + ExprLoc, getContext(), + true /*hasnXSModifier*/)); + return MatchOperand_Success; + } + + if (Tok.isNot(AsmToken::Identifier)) { + TokError("invalid operand for instruction"); + return MatchOperand_ParseFail; + } + + StringRef Operand = Tok.getString(); + // v8.7-A supports the "nXS" qualifier after the first operand. This + // corresponds to the DSBnXS instruction. + if (!Operand.endswith_lower("nXS")) { + TokError("invalid barrier option name"); + return MatchOperand_ParseFail; + } + Operand = Operand.drop_back(3); + auto DB = AArch64DB::lookupDBByName(Operand); + + if (DB && (DB->Encoding & 3) != 3) { + TokError("invalid barrier option for DSBnXS instruction"); + return MatchOperand_ParseFail; + } else if (!DB) { + TokError("invalid barrier option name"); + return MatchOperand_ParseFail; + } + + Operands.push_back( + AArch64Operand::CreateBarrier(DB->Encoding, Tok.getString(), getLoc(), + getContext(), true /*hasnXSModifier*/)); Parser.Lex(); // Consume the option return MatchOperand_Success; diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h @@ -160,6 +160,8 @@ const MCSubtargetInfo &STI, raw_ostream &O); void printBarrierOption(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O); + void printBarriernXSOption(const MCInst *MI, unsigned OpNum, + const MCSubtargetInfo &STI, raw_ostream &O); void printMSRSystemRegister(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O); void printMRSSystemRegister(const MCInst *MI, unsigned OpNum, diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp @@ -849,8 +849,12 @@ } break; } - } else if (CnVal == 8) { + } else if (CnVal == 8 || CnVal == 9) { // TLBI aliases + if (CnVal == 9) { + Encoding &= ~(1 << 7); + } + const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByEncoding(Encoding); if (!TLBI || !TLBI->haveFeatures(STI.getFeatureBits())) return false; @@ -858,6 +862,8 @@ NeedsReg = TLBI->NeedsReg; Ins = "tlbi\t"; Name = std::string(TLBI->Name); + if (CnVal == 9) + Name += "nXS"; } else return false; @@ -1416,6 +1422,22 @@ O << "#" << Val; } +void AArch64InstPrinter::printBarriernXSOption(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, + raw_ostream &O) { + unsigned Val = MI->getOperand(OpNo).getImm(); + assert(MI->getOpcode() == AArch64::DSBnXS); + + StringRef Name; + auto DB = AArch64DB::lookupDBByEncoding(Val); + Name = DB ? DB->Name : ""; + + if (!Name.empty()) + O << Name << "nxs"; + else + O << "#" << Val; +} + void AArch64InstPrinter::printMRSSystemRegister(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O) { diff --git a/llvm/lib/Target/ARM/ARMSubtarget.h b/llvm/lib/Target/ARM/ARMSubtarget.h --- a/llvm/lib/Target/ARM/ARMSubtarget.h +++ b/llvm/lib/Target/ARM/ARMSubtarget.h @@ -164,6 +164,7 @@ bool HasV8_4aOps = false; bool HasV8_5aOps = false; bool HasV8_6aOps = false; + bool HasV8_7aOps = false; bool HasV8MBaselineOps = false; bool HasV8MMainlineOps = false; bool HasV8_1MMainlineOps = false; @@ -595,6 +596,7 @@ bool hasV8_4aOps() const { return HasV8_4aOps; } bool hasV8_5aOps() const { return HasV8_5aOps; } bool hasV8_6aOps() const { return HasV8_6aOps; } + bool hasV8_7aOps() const { return HasV8_7aOps; } bool hasV8MBaselineOps() const { return HasV8MBaselineOps; } bool hasV8MMainlineOps() const { return HasV8MMainlineOps; } bool hasV8_1MMainlineOps() const { return HasV8_1MMainlineOps; } diff --git a/llvm/test/MC/AArch64/arm64-system-encoding.s b/llvm/test/MC/AArch64/arm64-system-encoding.s --- a/llvm/test/MC/AArch64/arm64-system-encoding.s +++ b/llvm/test/MC/AArch64/arm64-system-encoding.s @@ -277,6 +277,7 @@ mrs x3, ID_AA64DFR1_EL1 mrs x3, ID_AA64ISAR0_EL1 mrs x3, ID_AA64ISAR1_EL1 + mrs x3, ID_AA64ISAR2_EL1 mrs x3, ID_AA64MMFR0_EL1 mrs x3, ID_AA64MMFR1_EL1 mrs x3, ID_AA64PFR0_EL1 @@ -463,6 +464,7 @@ ; CHECK: mrs x3, ID_AA64DFR1_EL1 ; encoding: [0x23,0x05,0x38,0xd5] ; CHECK: mrs x3, ID_AA64ISAR0_EL1 ; encoding: [0x03,0x06,0x38,0xd5] ; CHECK: mrs x3, ID_AA64ISAR1_EL1 ; encoding: [0x23,0x06,0x38,0xd5] +; CHECK: mrs x3, ID_AA64ISAR2_EL1 ; encoding: [0x43,0x06,0x38,0xd5] ; CHECK: mrs x3, ID_AA64MMFR0_EL1 ; encoding: [0x03,0x07,0x38,0xd5] ; CHECK: mrs x3, ID_AA64MMFR1_EL1 ; encoding: [0x23,0x07,0x38,0xd5] ; CHECK: mrs x3, ID_AA64PFR0_EL1 ; encoding: [0x03,0x04,0x38,0xd5] diff --git a/llvm/test/MC/AArch64/armv8.7a-general.s b/llvm/test/MC/AArch64/armv8.7a-general.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/armv8.7a-general.s @@ -0,0 +1,46 @@ +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.7a < %s 2>%t | FileCheck %s +// RUN: FileCheck --check-prefix=CHECK-ERR --check-prefix=CHECK-V87-ERR %s < %t +// RUN: not llvm-mc -triple aarch64-none-linux-gnu < %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-ERR --check-prefix=CHECK-NO-V87-ERR %s < %t + + mrs x2, HCRX_EL2 +// CHECK: mrs x2, HCRX_EL2 // encoding: [0x42,0x12,0x3c,0xd5] +// CHECK-NO-V87-ERR: [[@LINE-2]]:11: error: expected readable system register + + msr HCRX_EL2, x3 +// CHECK: msr HCRX_EL2, x3 // encoding: [0x43,0x12,0x1c,0xd5] +// CHECK-NO-V87-ERR: [[@LINE-2]]:7: error: expected writable system register + + dsb #16 + dsb #20 + dsb #24 + dsb #28 + dsb oshnxs + dsb nshnxs + dsb ishnxs + dsb synxs +// CHECK: dsb oshnxs // encoding: [0x3f,0x32,0x03,0xd5] +// CHECK: dsb nshnxs // encoding: [0x3f,0x36,0x03,0xd5] +// CHECK: dsb ishnxs // encoding: [0x3f,0x3a,0x03,0xd5] +// CHECK: dsb synxs // encoding: [0x3f,0x3e,0x03,0xd5] +// CHECK: dsb oshnxs // encoding: [0x3f,0x32,0x03,0xd5] +// CHECK: dsb nshnxs // encoding: [0x3f,0x36,0x03,0xd5] +// CHECK: dsb ishnxs // encoding: [0x3f,0x3a,0x03,0xd5] +// CHECK: dsb synxs // encoding: [0x3f,0x3e,0x03,0xd5] +// CHECK-NO-V87-ERR: [[@LINE-16]]:3: error: instruction requires: armv8.7a +// CHECK-NO-V87-ERR: [[@LINE-16]]:3: error: instruction requires: armv8.7a +// CHECK-NO-V87-ERR: [[@LINE-16]]:3: error: instruction requires: armv8.7a +// CHECK-NO-V87-ERR: [[@LINE-16]]:3: error: instruction requires: armv8.7a +// CHECK-NO-V87-ERR: [[@LINE-16]]:3: error: instruction requires: armv8.7a +// CHECK-NO-V87-ERR: [[@LINE-16]]:3: error: instruction requires: armv8.7a +// CHECK-NO-V87-ERR: [[@LINE-16]]:3: error: instruction requires: armv8.7a +// CHECK-NO-V87-ERR: [[@LINE-16]]:3: error: instruction requires: armv8.7a + + dsb #17 + dsb nshstnxs +// CHECK-ERR: [[@LINE-2]]:8: error: barrier operand out of range +// CHECK-ERR: [[@LINE-2]]:7: error: invalid barrier option for DSBnXS instruction + + wfet x17 +// CHECK: wfet x17 // encoding: [0x11,0x10,0x03,0xd5] +// CHECK-NO-V87-ERR: [[@LINE-2]]:3: error: instruction requires: armv8.7a diff --git a/llvm/test/MC/AArch64/basic-a64-diagnostics.s b/llvm/test/MC/AArch64/basic-a64-diagnostics.s --- a/llvm/test/MC/AArch64/basic-a64-diagnostics.s +++ b/llvm/test/MC/AArch64/basic-a64-diagnostics.s @@ -3334,16 +3334,16 @@ // CHECK-ERROR-NEXT: ^ dsb #-1 - dsb #16 + dsb #17 dsb foo dmb #-1 - dmb #16 + dmb #17 dmb foo // CHECK-ERROR-NEXT: error: {{Invalid immediate for instruction|barrier operand out of range}} // CHECK-ERROR-NEXT: dsb #-1 // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{Invalid immediate for instruction|barrier operand out of range}} -// CHECK-ERROR-NEXT: dsb #16 +// CHECK-ERROR-NEXT: dsb #17 // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: invalid barrier option name // CHECK-ERROR-NEXT: dsb foo @@ -3352,7 +3352,7 @@ // CHECK-ERROR-NEXT: dmb #-1 // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{Invalid immediate for instruction|barrier operand out of range}} -// CHECK-ERROR-NEXT: dmb #16 +// CHECK-ERROR-NEXT: dmb #17 // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: invalid barrier option name // CHECK-ERROR-NEXT: dmb foo diff --git a/llvm/test/MC/Disassembler/AArch64/armv8.7a-general.txt b/llvm/test/MC/Disassembler/AArch64/armv8.7a-general.txt new file mode 100644 --- /dev/null +++ b/llvm/test/MC/Disassembler/AArch64/armv8.7a-general.txt @@ -0,0 +1,37 @@ +# RUN: llvm-mc -triple=aarch64 -mattr=+v8.7a -disassemble %s | FileCheck %s +# RUN: llvm-mc -triple=aarch64 -disassemble %s | FileCheck --check-prefix=CHECK-NO-V87 %s + +[0x42,0x12,0x3c,0xd5] +# CHECK: mrs x2, HCRX_EL2 +# CHECK-NO-V87: mrs x2, S3_4_C1_C2_2 + +[0x43,0x12,0x1c,0xd5] +# CHECK: msr HCRX_EL2, x3 +# CHECK-NO-V87: msr S3_4_C1_C2_2, x3 + +[0x3f,0x32,0x03,0xd5] +[0x3f,0x36,0x03,0xd5] +[0x3f,0x3a,0x03,0xd5] +[0x3f,0x3e,0x03,0xd5] +# CHECK: dsb oshnxs +# CHECK: dsb nshnxs +# CHECK: dsb ishnxs +# CHECK: dsb synxs +# CHECK-NO-V87: msr S0_3_C3_C2_1, xzr +# CHECK-NO-V87: msr S0_3_C3_C6_1, xzr +# CHECK-NO-V87: msr S0_3_C3_C10_1, xzr +# CHECK-NO-V87: msr S0_3_C3_C14_1, xzr + +[0x3f,0x30,0x03,0xd5] +[0x3f,0x35,0x03,0xd5] +[0x3f,0x3f,0x03,0xd5] +# CHECK: msr S0_3_C3_C0_1, xzr +# CHECK: msr S0_3_C3_C5_1, xzr +# CHECK: msr S0_3_C3_C15_1, xzr +# CHECK-NO-V87: msr S0_3_C3_C0_1, xzr +# CHECK-NO-V87: msr S0_3_C3_C5_1, xzr +# CHECK-NO-V87: msr S0_3_C3_C15_1, xzr + +[0x11,0x10,0x03,0xd5] +# CHECK: wfet x17 +# CHECK-NO-V87: msr S0_3_C1_C0_0, x17 diff --git a/llvm/test/MC/Disassembler/AArch64/basic-a64-instructions.txt b/llvm/test/MC/Disassembler/AArch64/basic-a64-instructions.txt --- a/llvm/test/MC/Disassembler/AArch64/basic-a64-instructions.txt +++ b/llvm/test/MC/Disassembler/AArch64/basic-a64-instructions.txt @@ -3533,6 +3533,7 @@ # CHECK: mrs x9, {{id_aa64afr1_el1|ID_AA64AFR1_EL1}} # CHECK: mrs x9, {{id_aa64isar0_el1|ID_AA64ISAR0_EL1}} # CHECK: mrs x9, {{id_aa64isar1_el1|ID_AA64ISAR1_EL1}} +# CHECK: mrs x9, {{id_aa64isar2_el1|ID_AA64ISAR2_EL1}} # CHECK: mrs x9, {{id_aa64mmfr0_el1|ID_AA64MMFR0_EL1}} # CHECK: mrs x9, {{id_aa64mmfr1_el1|ID_AA64MMFR1_EL1}} # CHECK: mrs x9, {{sctlr_el1|SCTLR_EL1}} @@ -4090,6 +4091,7 @@ 0xa9 0x5 0x38 0xd5 0x9 0x6 0x38 0xd5 0x29 0x6 0x38 0xd5 +0x49 0x06 0x38 0xd5 0x9 0x7 0x38 0xd5 0x29 0x7 0x38 0xd5 0x9 0x10 0x38 0xd5