Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions clang/test/Driver/aarch64-v97a.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@
// RUN: %clang -target aarch64 -march=armv9.7a+mtetc -### -c %s 2>&1 | FileCheck -check-prefix=V97A-MTETC %s
// RUN: %clang -target aarch64 -march=armv9.7-a+mtetc -### -c %s 2>&1 | FileCheck -check-prefix=V97A-MTETC %s
// V97A-MTETC: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}} "-target-feature" "+mtetc"

// RUN: %clang -target aarch64 -march=armv9.7a+gcie -### -c %s 2>&1 | FileCheck -check-prefix=V97A-GCIE %s
// RUN: %clang -target aarch64 -march=armv9.7-a+gcie -### -c %s 2>&1 | FileCheck -check-prefix=V97A-GCIE %s
// V97A-GCIE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}} "-target-feature" "+gcie"
1 change: 1 addition & 0 deletions clang/test/Driver/print-supported-extensions-aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
// CHECK-NEXT: fp8fma FEAT_FP8FMA Enable Armv9.5-A FP8 multiply-add instructions
// CHECK-NEXT: fprcvt FEAT_FPRCVT Enable Armv9.6-A base convert instructions for SIMD&FP scalar register operands of different input and output sizes
// CHECK-NEXT: fp16 FEAT_FP16 Enable half-precision floating-point data processing
// CHECK-NEXT: gcie FEAT_GCIE Enable Armv9.7-A GICv5 (Generic Interrupt Controller) CPU Interface Extension
// CHECK-NEXT: gcs FEAT_GCS Enable Armv9.4-A Guarded Call Stack Extension
// CHECK-NEXT: hbc FEAT_HBC Enable Armv8.8-A Hinted Conditional Branches Extension
// CHECK-NEXT: i8mm FEAT_I8MM Enable Matrix Multiply Int8 Extension
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/AArch64/AArch64Features.td
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,9 @@ def FeatureMPAMv2: ExtensionWithMArch<"mpamv2", "MPAMv2", "FEAT_MPAMv2",
def FeatureMTETC: ExtensionWithMArch<"mtetc", "MTETC", "FEAT_MTETC",
"Enable Virtual Memory Tagging Extension">;

def FeatureGCIE: ExtensionWithMArch<"gcie", "GCIE", "FEAT_GCIE",
"Enable Armv9.7-A GICv5 (Generic Interrupt Controller) CPU Interface Extension", [FeatureNMI]>;

//===----------------------------------------------------------------------===//
// Other Features
//===----------------------------------------------------------------------===//
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ def HasMPAMv2 : Predicate<"Subtarget->hasMPAMv2()">,
AssemblerPredicateWithAll<(all_of FeatureMPAMv2), "mpamv2">;
def HasMTETC : Predicate<"Subtarget->hasMTETC()">,
AssemblerPredicateWithAll<(all_of FeatureMTETC), "mtetc">;
def HasGCIE : Predicate<"Subtarget->hasGCIE()">,
AssemblerPredicateWithAll<(all_of FeatureGCIE), "gcie">;
def IsLE : Predicate<"Subtarget->isLittleEndian()">;
def IsBE : Predicate<"!Subtarget->isLittleEndian()">;
def IsWindows : Predicate<"Subtarget->isTargetWindows()">;
Expand Down
208 changes: 208 additions & 0 deletions llvm/lib/Target/AArch64/AArch64SystemOperands.td
Original file line number Diff line number Diff line change
Expand Up @@ -2480,3 +2480,211 @@ def : MLBI<"ALLE1", 0b100, 0b0111, 0b0000, 0b100, 0>;
def : MLBI<"VMALLE1", 0b100, 0b0111, 0b0000, 0b101, 0>;
def : MLBI<"VPIDE1", 0b100, 0b0111, 0b0000, 0b110, 1>;
def : MLBI<"VPMGE1", 0b100, 0b0111, 0b0000, 0b111, 1>;


// v9.7-A GICv5 (FEAT_GCIE)
// CPU Interface Registers
// Op0 Op1 CRn CRm Op2
def : RWSysReg<"ICC_APR_EL1", 0b11, 0b001, 0b1100, 0b0000, 0b000>;
def : RWSysReg<"ICC_APR_EL3", 0b11, 0b110, 0b1100, 0b1000, 0b000>;
def : RWSysReg<"ICC_CR0_EL1", 0b11, 0b001, 0b1100, 0b0000, 0b001>;
def : RWSysReg<"ICC_CR0_EL3", 0b11, 0b110, 0b1100, 0b1001, 0b000>;
def : ROSysReg<"ICC_DOMHPPIR_EL3", 0b11, 0b110, 0b1100, 0b1000, 0b010>;
def : ROSysReg<"ICC_HAPR_EL1", 0b11, 0b001, 0b1100, 0b0000, 0b011>;
def : ROSysReg<"ICC_HPPIR_EL1", 0b11, 0b000, 0b1100, 0b1010, 0b011>;
def : ROSysReg<"ICC_HPPIR_EL3", 0b11, 0b110, 0b1100, 0b1001, 0b001>;
def : ROSysReg<"ICC_IAFFIDR_EL1", 0b11, 0b000, 0b1100, 0b1010, 0b101>;
def : RWSysReg<"ICC_ICSR_EL1", 0b11, 0b000, 0b1100, 0b1010, 0b100>;
def : ROSysReg<"ICC_IDR0_EL1", 0b11, 0b000, 0b1100, 0b1010, 0b010>;
def : RWSysReg<"ICC_PCR_EL1", 0b11, 0b001, 0b1100, 0b0000, 0b010>;
def : RWSysReg<"ICC_PCR_EL3", 0b11, 0b110, 0b1100, 0b1000, 0b001>;

// Virtual CPU Interface Registers
// Op0 Op1 CRn CRm Op2
def : RWSysReg<"ICV_APR_EL1", 0b11, 0b001, 0b1100, 0b0000, 0b000>;
def : RWSysReg<"ICV_CR0_EL1", 0b11, 0b001, 0b1100, 0b0000, 0b001>;
def : RWSysReg<"ICV_HAPR_EL1", 0b11, 0b001, 0b1100, 0b0000, 0b011>;
def : RWSysReg<"ICV_HPPIR_EL1", 0b11, 0b000, 0b1100, 0b1010, 0b011>;
def : RWSysReg<"ICV_PCR_EL1", 0b11, 0b001, 0b1100, 0b0000, 0b010>;

// PPI Registers
foreach n=0-1 in {
defvar nb = !cast<bit>(n);
// Op0 Op1 CRn CRm Op2
def : RWSysReg<"ICC_PPI_CACTIVER"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1101, {0b00,nb}>;
def : RWSysReg<"ICC_PPI_CPENDR"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1101, {0b10,nb}>;
def : RWSysReg<"ICC_PPI_ENABLER"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1010, {0b11,nb}>;
def : RWSysReg<"ICC_PPI_SACTIVER"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1101, {0b01,nb}>;
def : RWSysReg<"ICC_PPI_SPENDR"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1101, {0b11,nb}>;
def : ROSysReg<"ICC_PPI_HMR"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1010, {0b00,nb}>;
}

foreach n=0-3 in {
defvar nb = !cast<bits<2>>(n);
// Op0 Op1 CRn CRm Op2
def : RWSysReg<"ICC_PPI_DOMAINR"#n#"_EL3", 0b11, 0b110, 0b1100, 0b1000, {0b1,nb{1-0}}>;

}

foreach n=0-15 in{
defvar nb = !cast<bits<4>>(n);
// Op0 Op1 CRn CRm Op2
def : RWSysReg<"ICC_PPI_PRIORITYR"#n#"_EL1", 0b11, 0b000, 0b1100, {0b111,nb{3}}, nb{2-0}>;
}

// Virtual PPI Registers
foreach n=0-1 in {
defvar nb = !cast<bit>(n);
// Op0 Op1 CRn CRm Op2
def : RWSysReg<"ICV_PPI_CACTIVER"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1101, {0b00,nb}>;
def : RWSysReg<"ICV_PPI_CPENDR"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1101, {0b10,nb}>;
def : RWSysReg<"ICV_PPI_ENABLER"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1010, {0b11,nb}>;
def : RWSysReg<"ICV_PPI_SACTIVER"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1101, {0b01,nb}>;
def : RWSysReg<"ICV_PPI_SPENDR"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1101, {0b11,nb}>;
def : RWSysReg<"ICV_PPI_HMR"#n#"_EL1", 0b11, 0b000, 0b1100, 0b1010, {0b00,nb}>;
}

foreach n=0-15 in {
defvar nb = !cast<bits<4>>(n);
// Op0 Op1 CRn CRm Op2
def : RWSysReg<"ICV_PPI_PRIORITYR"#n#"_EL1", 0b11, 0b000, 0b1100, {0b111,nb{3}}, nb{2-0}>;
}

// Hypervisor Control Registers
// Op0 Op1 CRn CRm Op2
def : RWSysReg<"ICH_APR_EL2", 0b11, 0b100, 0b1100, 0b1000, 0b100>;
def : RWSysReg<"ICH_CONTEXTR_EL2", 0b11, 0b100, 0b1100, 0b1011, 0b110>;
def : RWSysReg<"ICH_HFGITR_EL2", 0b11, 0b100, 0b1100, 0b1001, 0b111>;
def : RWSysReg<"ICH_HFGRTR_EL2", 0b11, 0b100, 0b1100, 0b1001, 0b100>;
def : RWSysReg<"ICH_HFGWTR_EL2", 0b11, 0b100, 0b1100, 0b1001, 0b110>;
def : ROSysReg<"ICH_HPPIR_EL2", 0b11, 0b100, 0b1100, 0b1000, 0b101>;
def : RWSysReg<"ICH_VCTLR_EL2", 0b11, 0b100, 0b1100, 0b1011, 0b100>;

foreach n=0-1 in {
defvar nb = !cast<bit>(n);
// Op0 Op1 CRn CRm Op2
def : RWSysReg<"ICH_PPI_ACTIVER"#n#"_EL2", 0b11, 0b100, 0b1100, 0b1010, {0b11,nb}>;
def : RWSysReg<"ICH_PPI_DVIR"#n#"_EL2", 0b11, 0b100, 0b1100, 0b1010, {0b00,nb}>;
def : RWSysReg<"ICH_PPI_ENABLER"#n#"_EL2", 0b11, 0b100, 0b1100, 0b1010, {0b01,nb}>;
def : RWSysReg<"ICH_PPI_PENDR"#n#"_EL2", 0b11, 0b100, 0b1100, 0b1010, {0b10,nb}>;
}

foreach n=0-15 in {
defvar nb = !cast<bits<4>>(n);
// Op0 Op1 CRn CRm Op2
def : RWSysReg<"ICH_PPI_PRIORITYR"#n#"_EL2", 0b11, 0b100, 0b1100, {0b111,nb{3}}, nb{2-0}>;
}

//===----------------------------------------------------------------------===//
// GICv5 instruction options.
//===----------------------------------------------------------------------===//

// GIC
class GIC<string name, bits<3> op1, bits<4> crn, bits<4> crm, bits<3> op2, bit needsreg> {
string Name = name;
bits<14> Encoding;
let Encoding{13-11} = op1;
let Encoding{10-7} = crn;
let Encoding{6-3} = crm;
let Encoding{2-0} = op2;
bit NeedsReg = needsreg;
string RequiresStr = [{ {AArch64::FeatureGCIE} }];
}

// GSB
class GSB<string name, bits<3> op1, bits<4> crn, bits<4> crm, bits<3> op2> {
string Name = name;
bits<14> Encoding;
let Encoding{13-11} = op1;
let Encoding{10-7} = crn;
let Encoding{6-3} = crm;
let Encoding{2-0} = op2;
string RequiresStr = [{ {AArch64::FeatureGCIE} }];
}

// GICR
class GICR<string name, bits<3> op1, bits<4> crn, bits<4> crm, bits<3> op2, bit needsreg> {
string Name = name;
bits<14> Encoding;
let Encoding{13-11} = op1;
let Encoding{10-7} = crn;
let Encoding{6-3} = crm;
let Encoding{2-0} = op2;
bit NeedsReg = needsreg;
string RequiresStr = [{ {AArch64::FeatureGCIE} }];
}

def GICTable : GenericTable {
let FilterClass = "GIC";
let CppTypeName = "GIC";
let Fields = ["Name", "Encoding", "NeedsReg", "RequiresStr"];

let PrimaryKey = ["Encoding"];
let PrimaryKeyName = "lookupGICByEncoding";
}

def GSBTable : GenericTable {
let FilterClass = "GSB";
let CppTypeName = "GSB";
let Fields = ["Name", "Encoding", "RequiresStr"];

let PrimaryKey = ["Encoding"];
let PrimaryKeyName = "lookupGSBByEncoding";
}

def GICRTable : GenericTable {
let FilterClass = "GICR";
let CppTypeName = "GICR";
let Fields = ["Name", "Encoding", "NeedsReg", "RequiresStr"];

let PrimaryKey = ["Encoding"];
let PrimaryKeyName = "lookupGICRByEncoding";
}

def lookupGICByName : SearchIndex {
let Table = GICTable;
let Key = ["Name"];
}

def lookupGSBByName : SearchIndex {
let Table = GSBTable;
let Key = ["Name"];
}

def lookupGICRByName : SearchIndex {
let Table = GICRTable;
let Key = ["Name"];
}

// Op1 CRn CRm Op2
def : GSB<"sys", 0b000, 0b1100, 0b0000, 0b000>;
def : GSB<"ack", 0b000, 0b1100, 0b0000, 0b001>;

// Op1 CRn CRm Op2 needsReg
def : GIC<"cdaff", 0b000, 0b1100, 0b0001, 0b011, 1>;
def : GIC<"cddi", 0b000, 0b1100, 0b0010, 0b000, 1>;
def : GIC<"cddis", 0b000, 0b1100, 0b0001, 0b000, 1>;
def : GIC<"cden", 0b000, 0b1100, 0b0001, 0b001, 1>;
def : GIC<"cdeoi", 0b000, 0b1100, 0b0001, 0b111, 1>;
def : GIC<"cdhm", 0b000, 0b1100, 0b0010, 0b001, 1>;
def : GIC<"cdpend", 0b000, 0b1100, 0b0001, 0b100, 1>;
def : GIC<"cdpri", 0b000, 0b1100, 0b0001, 0b010, 1>;
def : GIC<"cdrcfg", 0b000, 0b1100, 0b0001, 0b101, 1>;
def : GICR<"cdia", 0b000, 0b1100, 0b0011, 0b000, 1>;
def : GICR<"cdnmia", 0b000, 0b1100, 0b0011, 0b001, 1>;
def : GIC<"vdaff", 0b100, 0b1100, 0b0001, 0b011, 1>;
def : GIC<"vddi", 0b100, 0b1100, 0b0010, 0b000, 1>;
def : GIC<"vddis", 0b100, 0b1100, 0b0001, 0b000, 1>;
def : GIC<"vden", 0b100, 0b1100, 0b0001, 0b001, 1>;
def : GIC<"vdhm", 0b100, 0b1100, 0b0010, 0b001, 1>;
def : GIC<"vdpend", 0b100, 0b1100, 0b0001, 0b100, 1>;
def : GIC<"vdpri", 0b100, 0b1100, 0b0001, 0b010, 1>;
def : GIC<"vdrcfg", 0b100, 0b1100, 0b0001, 0b101, 1>;
def : GIC<"ldaff", 0b110, 0b1100, 0b0001, 0b011, 1>;
def : GIC<"lddi", 0b110, 0b1100, 0b0010, 0b000, 1>;
def : GIC<"lddis", 0b110, 0b1100, 0b0001, 0b000, 1>;
def : GIC<"lden", 0b110, 0b1100, 0b0001, 0b001, 1>;
def : GIC<"ldhm", 0b110, 0b1100, 0b0010, 0b001, 1>;
def : GIC<"ldpend", 0b110, 0b1100, 0b0001, 0b100, 1>;
def : GIC<"ldpri", 0b110, 0b1100, 0b0001, 0b010, 1>;
def : GIC<"ldrcfg", 0b110, 0b1100, 0b0001, 0b101, 1>;
85 changes: 81 additions & 4 deletions llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
SMLoc getLoc() const { return getParser().getTok().getLoc(); }

bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
bool parseSyslAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
bool parseSyspAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
AArch64CC::CondCode parseCondCodeString(StringRef Cond,
Expand Down Expand Up @@ -3888,6 +3889,7 @@ static const struct Extension {
{"tlbid", {AArch64::FeatureTLBID}},
{"mpamv2", {AArch64::FeatureMPAMv2}},
{"mtetc", {AArch64::FeatureMTETC}},
{"gcie", {AArch64::FeatureGCIE}},
};

static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
Expand Down Expand Up @@ -3960,7 +3962,7 @@ void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands
AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
}

/// parseSysAlias - The IC, DC, AT, TLBI, and MLBI instructions
/// parseSysAlias - The IC, DC, AT, TLBI, MLBI and GIC{R} and GSB instructions
/// are simple aliases for the SYS instruction. Parse them specially so that
/// we create a SYS MCInst.
bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
Expand Down Expand Up @@ -4035,6 +4037,28 @@ bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
}
ExpectRegister = MLBI->NeedsReg;
createSysAlias(MLBI->Encoding, Operands, S);
} else if (Mnemonic == "gic") {
const AArch64GIC::GIC *GIC = AArch64GIC::lookupGICByName(Op);
if (!GIC)
return TokError("invalid operand for GIC instruction");
else if (!GIC->haveFeatures(getSTI().getFeatureBits())) {
std::string Str("GIC " + std::string(GIC->Name) + " requires: ");
setRequiredFeatureString(GIC->getRequiredFeatures(), Str);
return TokError(Str);
}
ExpectRegister = GIC->NeedsReg;
createSysAlias(GIC->Encoding, Operands, S);
} else if (Mnemonic == "gsb") {
const AArch64GSB::GSB *GSB = AArch64GSB::lookupGSBByName(Op);
if (!GSB)
return TokError("invalid operand for GSB instruction");
else if (!GSB->haveFeatures(getSTI().getFeatureBits())) {
std::string Str("GSB " + std::string(GSB->Name) + " requires: ");
setRequiredFeatureString(GSB->getRequiredFeatures(), Str);
return TokError(Str);
}
ExpectRegister = false;
createSysAlias(GSB->Encoding, Operands, S);
} else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp" ||
Mnemonic == "cosp") {

Expand Down Expand Up @@ -4086,6 +4110,55 @@ bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
return false;
}

/// parseSyslAlias - The GICR instructions are simple aliases for
/// the SYSL instruction. Parse them specially so that we create a
/// SYS MCInst.
bool AArch64AsmParser::parseSyslAlias(StringRef Name, SMLoc NameLoc,
OperandVector &Operands) {

Mnemonic = Name;
Operands.push_back(
AArch64Operand::CreateToken("sysl", NameLoc, getContext()));

// Now expect two operands (identifier + register)
SMLoc startLoc = getLoc();
const AsmToken &regTok = getTok();
StringRef reg = regTok.getString();
unsigned RegNum = matchRegisterNameAlias(reg.lower(), RegKind::Scalar);
if (!RegNum)
return TokError("expected register operand");

Operands.push_back(AArch64Operand::CreateReg(
RegNum, RegKind::Scalar, startLoc, getLoc(), getContext(), EqualsReg));

Lex(); // Eat token
if (parseToken(AsmToken::Comma))
return true;

// Check for identifier
const AsmToken &operandTok = getTok();
StringRef Op = operandTok.getString();
SMLoc S2 = operandTok.getLoc();
Lex(); // Eat token

if (Mnemonic == "gicr") {
const AArch64GICR::GICR *GICR = AArch64GICR::lookupGICRByName(Op);
if (!GICR)
return Error(S2, "invalid operand for GICR instruction");
else if (!GICR->haveFeatures(getSTI().getFeatureBits())) {
std::string Str("GICR " + std::string(GICR->Name) + " requires: ");
setRequiredFeatureString(GICR->getRequiredFeatures(), Str);
return Error(S2, Str);
}
createSysAlias(GICR->Encoding, Operands, S2);
}

if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
return true;

return false;
}

/// parseSyspAlias - The TLBIP instructions are simple aliases for
/// the SYSP instruction. Parse them specially so that we create a SYSP MCInst.
bool AArch64AsmParser::parseSyspAlias(StringRef Name, SMLoc NameLoc,
Expand Down Expand Up @@ -5353,13 +5426,17 @@ bool AArch64AsmParser::parseInstruction(ParseInstructionInfo &Info,
size_t Start = 0, Next = Name.find('.');
StringRef Head = Name.slice(Start, Next);

// IC, DC, AT, TLBI, MLBI and Prediction invalidation instructions are aliases
// for the SYS instruction.
// IC, DC, AT, TLBI, MLBI, GIC{R}, GSB 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" || Head == "cosp" ||
Head == "mlbi")
Head == "mlbi" || Head == "gic" || Head == "gsb")
return parseSysAlias(Head, NameLoc, Operands);

// GICR instructions are aliases for the SYSL instruction.
if (Head == "gicr")
return parseSyslAlias(Head, NameLoc, Operands);

// TLBIP instructions are aliases for the SYSP instruction.
if (Head == "tlbip")
return parseSyspAlias(Head, NameLoc, Operands);
Expand Down
Loading