mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 02:52:53 +02:00
[AArch64][v8.5A] Add prediction invalidation instructions to AArch64
This adds new system instructions which act as barriers to speculative execution based on earlier execution within a particular execution context. Patch by Pablo Barrio! Differential revision: https://reviews.llvm.org/D52479 llvm-svn: 343214
This commit is contained in:
parent
9fd24e88bc
commit
e0b46dae60
@ -214,6 +214,9 @@ def FeatureFRInt3264 : SubtargetFeature<"fptoint", "HasFRInt3264", "true",
|
|||||||
def FeatureSpecCtrl : SubtargetFeature<"specctrl", "HasSpecCtrl", "true",
|
def FeatureSpecCtrl : SubtargetFeature<"specctrl", "HasSpecCtrl", "true",
|
||||||
"Enable speculation control barrier" >;
|
"Enable speculation control barrier" >;
|
||||||
|
|
||||||
|
def FeaturePredCtrl : SubtargetFeature<"predctrl", "HasPredCtrl", "true",
|
||||||
|
"Enable execution and data prediction invalidation instructions" >;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Architectures.
|
// Architectures.
|
||||||
//
|
//
|
||||||
@ -232,7 +235,8 @@ def HasV8_4aOps : SubtargetFeature<"v8.4a", "HasV8_4aOps", "true",
|
|||||||
|
|
||||||
def HasV8_5aOps : SubtargetFeature<
|
def HasV8_5aOps : SubtargetFeature<
|
||||||
"v8.5a", "HasV8_5aOps", "true", "Support ARM v8.5a instructions",
|
"v8.5a", "HasV8_5aOps", "true", "Support ARM v8.5a instructions",
|
||||||
[HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecCtrl]
|
[HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecCtrl,
|
||||||
|
FeaturePredCtrl]
|
||||||
>;
|
>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -68,6 +68,8 @@ def HasFRInt3264 : Predicate<"Subtarget->hasFRInt3264()">,
|
|||||||
AssemblerPredicate<"FeatureFRInt3264", "frint3264">;
|
AssemblerPredicate<"FeatureFRInt3264", "frint3264">;
|
||||||
def HasSpecCtrl : Predicate<"Subtarget->hasSpecCtrl()">,
|
def HasSpecCtrl : Predicate<"Subtarget->hasSpecCtrl()">,
|
||||||
AssemblerPredicate<"FeatureSpecCtrl", "specctrl">;
|
AssemblerPredicate<"FeatureSpecCtrl", "specctrl">;
|
||||||
|
def HasPredCtrl : Predicate<"Subtarget->hasPredCtrl()">,
|
||||||
|
AssemblerPredicate<"FeaturePredCtrl", "predctrl">;
|
||||||
def IsLE : Predicate<"Subtarget->isLittleEndian()">;
|
def IsLE : Predicate<"Subtarget->isLittleEndian()">;
|
||||||
def IsBE : Predicate<"!Subtarget->isLittleEndian()">;
|
def IsBE : Predicate<"!Subtarget->isLittleEndian()">;
|
||||||
def UseAlternateSExtLoadCVTF32
|
def UseAlternateSExtLoadCVTF32
|
||||||
|
@ -98,6 +98,7 @@ protected:
|
|||||||
bool HasAlternativeNZCV = false;
|
bool HasAlternativeNZCV = false;
|
||||||
bool HasFRInt3264 = false;
|
bool HasFRInt3264 = false;
|
||||||
bool HasSpecCtrl = false;
|
bool HasSpecCtrl = false;
|
||||||
|
bool HasPredCtrl = false;
|
||||||
|
|
||||||
// HasZeroCycleRegMove - Has zero-cycle register mov instructions.
|
// HasZeroCycleRegMove - Has zero-cycle register mov instructions.
|
||||||
bool HasZeroCycleRegMove = false;
|
bool HasZeroCycleRegMove = false;
|
||||||
@ -314,6 +315,7 @@ public:
|
|||||||
bool hasAlternativeNZCV() const { return HasAlternativeNZCV; }
|
bool hasAlternativeNZCV() const { return HasAlternativeNZCV; }
|
||||||
bool hasFRInt3264() const { return HasFRInt3264; }
|
bool hasFRInt3264() const { return HasFRInt3264; }
|
||||||
bool hasSpecCtrl() { return HasSpecCtrl; }
|
bool hasSpecCtrl() { return HasSpecCtrl; }
|
||||||
|
bool hasPredCtrl() { return HasPredCtrl; }
|
||||||
|
|
||||||
bool isLittleEndian() const { return IsLittle; }
|
bool isLittleEndian() const { return IsLittle; }
|
||||||
|
|
||||||
|
@ -420,6 +420,23 @@ def : TLBI<"RVAE3OS", 0b110, 0b1000, 0b0101, 0b001>;
|
|||||||
def : TLBI<"RVALE3OS", 0b110, 0b1000, 0b0101, 0b101>;
|
def : TLBI<"RVALE3OS", 0b110, 0b1000, 0b0101, 0b101>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Armv8.5-A Prediction Restriction by Context instruction options:
|
||||||
|
class PRCTX<string name, bits<4> 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.
|
// MRS/MSR (system register read/write) instruction options.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -2756,6 +2756,7 @@ static const struct Extension {
|
|||||||
{ "simd", {AArch64::FeatureNEON} },
|
{ "simd", {AArch64::FeatureNEON} },
|
||||||
{ "ras", {AArch64::FeatureRAS} },
|
{ "ras", {AArch64::FeatureRAS} },
|
||||||
{ "lse", {AArch64::FeatureLSE} },
|
{ "lse", {AArch64::FeatureLSE} },
|
||||||
|
{ "predctrl", {AArch64::FeaturePredCtrl} },
|
||||||
|
|
||||||
// FIXME: Unsupported extensions
|
// FIXME: Unsupported extensions
|
||||||
{ "pan", {} },
|
{ "pan", {} },
|
||||||
@ -2864,6 +2865,23 @@ bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
|
|||||||
return TokError(Str.c_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)
|
||||||
|
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.
|
Parser.Lex(); // Eat operand.
|
||||||
@ -3682,8 +3700,10 @@ bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
|
|||||||
size_t Start = 0, Next = Name.find('.');
|
size_t Start = 0, Next = Name.find('.');
|
||||||
StringRef Head = Name.slice(Start, Next);
|
StringRef Head = Name.slice(Start, Next);
|
||||||
|
|
||||||
// IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
|
// IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
|
||||||
if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
|
// the SYS instruction.
|
||||||
|
if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
|
||||||
|
Head == "cfp" || Head == "dvp" || Head == "cpp")
|
||||||
return parseSysAlias(Head, NameLoc, Operands);
|
return parseSysAlias(Head, NameLoc, Operands);
|
||||||
|
|
||||||
Operands.push_back(
|
Operands.push_back(
|
||||||
|
@ -775,8 +775,33 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
|
|||||||
if (CnVal == 7) {
|
if (CnVal == 7) {
|
||||||
switch (CmVal) {
|
switch (CmVal) {
|
||||||
default: return false;
|
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
|
// IC aliases
|
||||||
case 1: case 5: {
|
case 5: {
|
||||||
|
Search_IC:
|
||||||
const AArch64IC::IC *IC = AArch64IC::lookupICByEncoding(Encoding);
|
const AArch64IC::IC *IC = AArch64IC::lookupICByEncoding(Encoding);
|
||||||
if (!IC || !IC->haveFeatures(STI.getFeatureBits()))
|
if (!IC || !IC->haveFeatures(STI.getFeatureBits()))
|
||||||
return false;
|
return false;
|
||||||
|
@ -61,6 +61,13 @@ namespace llvm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace AArch64PRCTX {
|
||||||
|
#define GET_PRCTX_IMPL
|
||||||
|
#include "AArch64GenSystemOperands.inc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace AArch64PRFM {
|
namespace AArch64PRFM {
|
||||||
#define GET_PRFM_IMPL
|
#define GET_PRFM_IMPL
|
||||||
|
@ -499,6 +499,14 @@ namespace AArch64TLBI {
|
|||||||
#include "AArch64GenSystemOperands.inc"
|
#include "AArch64GenSystemOperands.inc"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace AArch64PRCTX {
|
||||||
|
struct PRCTX : SysAliasReg {
|
||||||
|
using SysAliasReg::SysAliasReg;
|
||||||
|
};
|
||||||
|
#define GET_PRCTX_DECL
|
||||||
|
#include "AArch64GenSystemOperands.inc"
|
||||||
|
}
|
||||||
|
|
||||||
namespace AArch64II {
|
namespace AArch64II {
|
||||||
/// Target Operand Flag enum.
|
/// Target Operand Flag enum.
|
||||||
enum TOF {
|
enum TOF {
|
||||||
|
20
test/MC/AArch64/armv8.5a-predctrl-error.s
Normal file
20
test/MC/AArch64/armv8.5a-predctrl-error.s
Normal file
@ -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
|
18
test/MC/AArch64/armv8.5a-predctrl.s
Normal file
18
test/MC/AArch64/armv8.5a-predctrl.s
Normal file
@ -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
|
15
test/MC/Disassembler/AArch64/armv8.5a-predctrl.txt
Normal file
15
test/MC/Disassembler/AArch64/armv8.5a-predctrl.txt
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user