diff --git a/lib/Target/AArch64/AArch64.td b/lib/Target/AArch64/AArch64.td index 79bae03b4b83a..8d2085030c083 100644 --- a/lib/Target/AArch64/AArch64.td +++ b/lib/Target/AArch64/AArch64.td @@ -214,6 +214,9 @@ def FeatureFRInt3264 : SubtargetFeature<"fptoint", "HasFRInt3264", "true", def FeatureSpecCtrl : SubtargetFeature<"specctrl", "HasSpecCtrl", "true", "Enable speculation control barrier" >; +def FeaturePredCtrl : SubtargetFeature<"predctrl", "HasPredCtrl", "true", + "Enable execution and data prediction invalidation instructions" >; + //===----------------------------------------------------------------------===// // Architectures. // @@ -232,7 +235,8 @@ def HasV8_4aOps : SubtargetFeature<"v8.4a", "HasV8_4aOps", "true", def HasV8_5aOps : SubtargetFeature< "v8.5a", "HasV8_5aOps", "true", "Support ARM v8.5a instructions", - [HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecCtrl] + [HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecCtrl, + FeaturePredCtrl] >; //===----------------------------------------------------------------------===// diff --git a/lib/Target/AArch64/AArch64InstrInfo.td b/lib/Target/AArch64/AArch64InstrInfo.td index 310c1b60bf7c6..1192fad94bd2f 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.td +++ b/lib/Target/AArch64/AArch64InstrInfo.td @@ -68,6 +68,8 @@ def HasFRInt3264 : Predicate<"Subtarget->hasFRInt3264()">, AssemblerPredicate<"FeatureFRInt3264", "frint3264">; def HasSpecCtrl : Predicate<"Subtarget->hasSpecCtrl()">, AssemblerPredicate<"FeatureSpecCtrl", "specctrl">; +def HasPredCtrl : Predicate<"Subtarget->hasPredCtrl()">, + AssemblerPredicate<"FeaturePredCtrl", "predctrl">; def IsLE : Predicate<"Subtarget->isLittleEndian()">; def IsBE : Predicate<"!Subtarget->isLittleEndian()">; def UseAlternateSExtLoadCVTF32 diff --git a/lib/Target/AArch64/AArch64Subtarget.h b/lib/Target/AArch64/AArch64Subtarget.h index 8df6e5a657033..cc901e1c64424 100644 --- a/lib/Target/AArch64/AArch64Subtarget.h +++ b/lib/Target/AArch64/AArch64Subtarget.h @@ -98,6 +98,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo { bool HasAlternativeNZCV = false; bool HasFRInt3264 = false; bool HasSpecCtrl = false; + bool HasPredCtrl = false; // HasZeroCycleRegMove - Has zero-cycle register mov instructions. bool HasZeroCycleRegMove = false; @@ -314,6 +315,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo { bool hasAlternativeNZCV() const { return HasAlternativeNZCV; } bool hasFRInt3264() const { return HasFRInt3264; } bool hasSpecCtrl() { return HasSpecCtrl; } + bool hasPredCtrl() { return HasPredCtrl; } bool isLittleEndian() const { return IsLittle; } diff --git a/lib/Target/AArch64/AArch64SystemOperands.td b/lib/Target/AArch64/AArch64SystemOperands.td index dbc4deaf3f9f3..1b3887ed5e013 100644 --- a/lib/Target/AArch64/AArch64SystemOperands.td +++ b/lib/Target/AArch64/AArch64SystemOperands.td @@ -420,6 +420,23 @@ def : TLBI<"RVAE3OS", 0b110, 0b1000, 0b0101, 0b001>; def : TLBI<"RVALE3OS", 0b110, 0b1000, 0b0101, 0b101>; } +// Armv8.5-A Prediction Restriction by Context instruction options: +class PRCTX crm> : SearchableTable { + let SearchableFields = ["Name", "Encoding"]; + let EnumValueField = "Encoding"; + + string Name = name; + bits<11> Encoding; + let Encoding{10-4} = 0b0110111; + let Encoding{3-0} = crm; + bit NeedsReg = 1; + code Requires = [{ {} }]; +} + +let Requires = [{ {AArch64::FeaturePredCtrl} }] in { +def : PRCTX<"RCTX", 0b0011>; +} + //===----------------------------------------------------------------------===// // MRS/MSR (system register read/write) instruction options. //===----------------------------------------------------------------------===// diff --git a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 0f156185387d1..acbea2b5dcf05 100644 --- a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -2756,6 +2756,7 @@ static const struct Extension { { "simd", {AArch64::FeatureNEON} }, { "ras", {AArch64::FeatureRAS} }, { "lse", {AArch64::FeatureLSE} }, + { "predctrl", {AArch64::FeaturePredCtrl} }, // FIXME: Unsupported extensions { "pan", {} }, @@ -2864,6 +2865,23 @@ bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc, return TokError(Str.c_str()); } createSysAlias(TLBI->Encoding, Operands, S); + } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp") { + const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByName(Op); + if (!PRCTX) + return TokError("invalid operand for prediction restriction instruction"); + else if (!PRCTX->haveFeatures(getSTI().getFeatureBits())) { + std::string Str( + Mnemonic.upper() + std::string(PRCTX->Name) + " requires "); + setRequiredFeatureString(PRCTX->getRequiredFeatures(), Str); + return TokError(Str.c_str()); + } + uint16_t PRCTX_Op2 = + Mnemonic == "cfp" ? 4 : + Mnemonic == "dvp" ? 5 : + Mnemonic == "cpp" ? 7 : + 0; + assert(PRCTX_Op2 && "Invalid mnemonic for prediction restriction instruction"); + createSysAlias(PRCTX->Encoding << 3 | PRCTX_Op2 , Operands, S); } Parser.Lex(); // Eat operand. @@ -3682,8 +3700,10 @@ bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info, size_t Start = 0, Next = Name.find('.'); StringRef Head = Name.slice(Start, Next); - // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction. - if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi") + // IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for + // the SYS instruction. + if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" || + Head == "cfp" || Head == "dvp" || Head == "cpp") return parseSysAlias(Head, NameLoc, Operands); Operands.push_back( diff --git a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp index 26e41215afc64..aa537abf6abd2 100644 --- a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp +++ b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp @@ -775,8 +775,33 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI, if (CnVal == 7) { switch (CmVal) { default: return false; + // Maybe IC, maybe Prediction Restriction + case 1: + switch (Op1Val) { + default: return false; + case 0: goto Search_IC; + case 3: goto Search_PRCTX; + } + // Prediction Restriction aliases + case 3: { + Search_PRCTX: + const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByEncoding(Encoding >> 3); + if (!PRCTX || !PRCTX->haveFeatures(STI.getFeatureBits())) + return false; + + NeedsReg = PRCTX->NeedsReg; + switch (Op2Val) { + default: return false; + case 4: Ins = "cfp\t"; break; + case 5: Ins = "dvp\t"; break; + case 7: Ins = "cpp\t"; break; + } + Name = std::string(PRCTX->Name); + } + break; // IC aliases - case 1: case 5: { + case 5: { + Search_IC: const AArch64IC::IC *IC = AArch64IC::lookupICByEncoding(Encoding); if (!IC || !IC->haveFeatures(STI.getFeatureBits())) return false; diff --git a/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp b/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp index 23cc21ce2e7cf..9c415aa8496ad 100644 --- a/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp +++ b/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp @@ -61,6 +61,13 @@ namespace llvm { } } +namespace llvm { + namespace AArch64PRCTX { +#define GET_PRCTX_IMPL +#include "AArch64GenSystemOperands.inc" + } +} + namespace llvm { namespace AArch64PRFM { #define GET_PRFM_IMPL diff --git a/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/lib/Target/AArch64/Utils/AArch64BaseInfo.h index 461a7dcf09040..675adad2a6917 100644 --- a/lib/Target/AArch64/Utils/AArch64BaseInfo.h +++ b/lib/Target/AArch64/Utils/AArch64BaseInfo.h @@ -499,6 +499,14 @@ namespace AArch64TLBI { #include "AArch64GenSystemOperands.inc" } +namespace AArch64PRCTX { + struct PRCTX : SysAliasReg { + using SysAliasReg::SysAliasReg; + }; + #define GET_PRCTX_DECL + #include "AArch64GenSystemOperands.inc" +} + namespace AArch64II { /// Target Operand Flag enum. enum TOF { diff --git a/test/MC/AArch64/armv8.5a-predctrl-error.s b/test/MC/AArch64/armv8.5a-predctrl-error.s new file mode 100644 index 0000000000000..0fd49b02bee07 --- /dev/null +++ b/test/MC/AArch64/armv8.5a-predctrl-error.s @@ -0,0 +1,20 @@ +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+predctrl < %s 2>&1| FileCheck %s + +cfp rctx +dvp rctx +cpp rctx + +// CHECK: specified cfp op requires a register +// CHECK: specified dvp op requires a register +// CHECK: specified cpp op requires a register + +cfp x0, x1 +dvp x1, x2 +cpp x2, x3 + +// CHECK: invalid operand for prediction restriction instruction +// CHECK-NEXT: cfp +// CHECK: invalid operand for prediction restriction instruction +// CHECK-NEXT: dvp +// CHECK: invalid operand for prediction restriction instruction +// CHECK-NEXT: cpp diff --git a/test/MC/AArch64/armv8.5a-predctrl.s b/test/MC/AArch64/armv8.5a-predctrl.s new file mode 100644 index 0000000000000..af7dda76862d8 --- /dev/null +++ b/test/MC/AArch64/armv8.5a-predctrl.s @@ -0,0 +1,18 @@ +// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+predctrl < %s | FileCheck %s +// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.5a < %s | FileCheck %s +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=-predctrl < %s 2>&1 | FileCheck %s --check-prefix=NOPREDCTRL + +cfp rctx, x0 +dvp rctx, x1 +cpp rctx, x2 + +// CHECK: cfp rctx, x0 // encoding: [0x80,0x73,0x0b,0xd5] +// CHECK: dvp rctx, x1 // encoding: [0xa1,0x73,0x0b,0xd5] +// CHECK: cpp rctx, x2 // encoding: [0xe2,0x73,0x0b,0xd5] + +// NOPREDCTRL: CFPRCTX requires predctrl +// NOPREDCTRL-NEXT: cfp +// NOPREDCTRL: DVPRCTX requires predctrl +// NOPREDCTRL-NEXT: dvp +// NOPREDCTRL: CPPRCTX requires predctrl +// NOPREDCTRL-NEXT: cpp diff --git a/test/MC/Disassembler/AArch64/armv8.5a-predctrl.txt b/test/MC/Disassembler/AArch64/armv8.5a-predctrl.txt new file mode 100644 index 0000000000000..ecfdeec86f115 --- /dev/null +++ b/test/MC/Disassembler/AArch64/armv8.5a-predctrl.txt @@ -0,0 +1,15 @@ +# RUN: llvm-mc -triple=aarch64 -mattr=+predctrl -disassemble < %s | FileCheck %s +# RUN: llvm-mc -triple=aarch64 -mattr=+v8.5a -disassemble < %s | FileCheck %s +# RUN: llvm-mc -triple=aarch64 -mattr=-predctrl -disassemble < %s 2>&1 | FileCheck %s --check-prefix=NOSB + +[0x80 0x73 0x0b 0xd5] +[0xa1 0x73 0x0b 0xd5] +[0xe2 0x73 0x0b 0xd5] + +# CHECK: cfp rctx, x0 +# CHECK: dvp rctx, x1 +# CHECK: cpp rctx, x2 + +# NOSB: sys #3, c7, c3, #4, x0 +# NOSB: sys #3, c7, c3, #5, x1 +# NOSB: sys #3, c7, c3, #7, x2