[clang] 5cff77c - [clang][ARM] PACBTI-M assembly support
via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 30 01:29:37 PST 2021
Author: Ties Stuij
Date: 2021-11-30T09:28:18Z
New Revision: 5cff77c23f43130887b566dd0fe237e1c482e23b
URL: https://github.com/llvm/llvm-project/commit/5cff77c23f43130887b566dd0fe237e1c482e23b
DIFF: https://github.com/llvm/llvm-project/commit/5cff77c23f43130887b566dd0fe237e1c482e23b.diff
LOG: [clang][ARM] PACBTI-M assembly support
Introduce assembly support for Armv8.1-M PACBTI extension. This is an optional
extension in v8.1-M.
There are 10 new system registers and 5 new instructions, all predicated on the
feature.
The attribute for llvm-mc is called "pacbti". For armclang, an architecture
extension also called "pacbti" was created.
This patch is part of a series that adds support for the PACBTI-M extension of
the Armv8.1-M architecture, as detailed here:
https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension
The PACBTI-M specification can be found in the Armv8-M Architecture Reference
Manual:
https://developer.arm.com/documentation/ddi0553/latest
The following people contributed to this patch:
- Victor Campos
- Ties Stuij
Reviewed By: labrinea
Differential Revision: https://reviews.llvm.org/D112420
Added:
llvm/test/MC/ARM/armv8.1m-pacbti-error.s
llvm/test/MC/ARM/armv8.1m-pacbti.s
llvm/test/MC/ARM/implicit-it-generation-v8.s
llvm/test/MC/Disassembler/ARM/armv8.1m-pacbti.txt
Modified:
clang/test/Driver/armv8.1m.main.c
llvm/include/llvm/Support/ARMTargetParser.def
llvm/include/llvm/Support/ARMTargetParser.h
llvm/lib/Target/ARM/ARM.td
llvm/lib/Target/ARM/ARMInstrThumb2.td
llvm/lib/Target/ARM/ARMPredicates.td
llvm/lib/Target/ARM/ARMRegisterInfo.td
llvm/lib/Target/ARM/ARMSubtarget.h
llvm/lib/Target/ARM/ARMSystemRegister.td
llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
llvm/test/CodeGen/Thumb/high-reg-clobber.mir
Removed:
################################################################################
diff --git a/clang/test/Driver/armv8.1m.main.c b/clang/test/Driver/armv8.1m.main.c
index 15b91237f62ea..eef395c98891e 100644
--- a/clang/test/Driver/armv8.1m.main.c
+++ b/clang/test/Driver/armv8.1m.main.c
@@ -2,6 +2,10 @@
// RUN: FileCheck --check-prefix=CHECK-DSP < %t %s
// CHECK-DSP: "-target-feature" "+dsp"
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main+pacbti -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-PACBTI < %t %s
+// CHECK-PACBTI: "-target-feature" "+pacbti"
+
// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main+fp -### %s 2> %t
// RUN: FileCheck --check-prefix=CHECK-FP < %t %s
// CHECK-FP-DAG: "-target-feature" "+fp-armv8d16sp"
diff --git a/llvm/include/llvm/Support/ARMTargetParser.def b/llvm/include/llvm/Support/ARMTargetParser.def
index fd08f3e6960c0..7d29808f05012 100644
--- a/llvm/include/llvm/Support/ARMTargetParser.def
+++ b/llvm/include/llvm/Support/ARMTargetParser.def
@@ -201,6 +201,7 @@ ARM_ARCH_EXT_NAME("cdecp4", ARM::AEK_CDECP4, "+cdecp4", "-cdecp4")
ARM_ARCH_EXT_NAME("cdecp5", ARM::AEK_CDECP5, "+cdecp5", "-cdecp5")
ARM_ARCH_EXT_NAME("cdecp6", ARM::AEK_CDECP6, "+cdecp6", "-cdecp6")
ARM_ARCH_EXT_NAME("cdecp7", ARM::AEK_CDECP7, "+cdecp7", "-cdecp7")
+ARM_ARCH_EXT_NAME("pacbti", ARM::AEK_PACBTI, "+pacbti", "-pacbti")
#undef ARM_ARCH_EXT_NAME
#ifndef ARM_HW_DIV_NAME
diff --git a/llvm/include/llvm/Support/ARMTargetParser.h b/llvm/include/llvm/Support/ARMTargetParser.h
index b1ffcfb34552a..b40704c24e87c 100644
--- a/llvm/include/llvm/Support/ARMTargetParser.h
+++ b/llvm/include/llvm/Support/ARMTargetParser.h
@@ -59,7 +59,7 @@ enum ArchExtKind : uint64_t {
AEK_CDECP5 = 1 << 27,
AEK_CDECP6 = 1 << 28,
AEK_CDECP7 = 1 << 29,
-
+ AEK_PACBTI = 1 << 30,
// Unsupported extensions.
AEK_OS = 1ULL << 59,
AEK_IWMMXT = 1ULL << 60,
diff --git a/llvm/lib/Target/ARM/ARM.td b/llvm/lib/Target/ARM/ARM.td
index 8cbd80f1bf652..e03dd597eb650 100644
--- a/llvm/lib/Target/ARM/ARM.td
+++ b/llvm/lib/Target/ARM/ARM.td
@@ -442,6 +442,10 @@ def FeatureFixCMSE_CVE_2021_35465 : SubtargetFeature<"fix-cmse-cve-2021-35465",
"Mitigate against the cve-2021-35465 "
"security vulnurability">;
+def FeaturePACBTI : SubtargetFeature<"pacbti", "HasPACBTI", "true",
+ "Enable Pointer Authentication and Branch "
+ "Target Identification">;
+
//===----------------------------------------------------------------------===//
// ARM architecture class
//
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index 5b9ae7ac8730f..d216207a97fc7 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -4055,6 +4055,8 @@ def t2HINT : T2I<(outs), (ins imm0_239:$imm), NoItinerary, "hint", ".w\t$imm",
bits<8> imm;
let Inst{31-3} = 0b11110011101011111000000000000;
let Inst{7-0} = imm;
+
+ let DecoderMethod = "DecodeT2HintSpaceInstruction";
}
def : t2InstAlias<"hint$p $imm", (t2HINT imm0_239:$imm, pred:$p), 0>;
@@ -4075,6 +4077,11 @@ def : t2InstAlias<"esb$p", (t2HINT 16, pred:$p), 0> {
def : t2InstAlias<"csdb$p.w", (t2HINT 20, pred:$p), 0>;
def : t2InstAlias<"csdb$p", (t2HINT 20, pred:$p), 1>;
+def : t2InstAlias<"pacbti$p r12,lr,sp", (t2HINT 13, pred:$p), 1>;
+def : t2InstAlias<"bti$p", (t2HINT 15, pred:$p), 1>;
+def : t2InstAlias<"pac$p r12,lr,sp", (t2HINT 29, pred:$p), 1>;
+def : t2InstAlias<"aut$p r12,lr,sp", (t2HINT 45, pred:$p), 1>;
+
def t2DBG : T2I<(outs), (ins imm0_15:$opt), NoItinerary, "dbg", "\t$opt",
[(int_arm_dbg imm0_15:$opt)]> {
bits<4> opt;
@@ -5654,3 +5661,78 @@ let Predicates = [HasV8_1MMainline] in {
def : InstAlias<"cneg\t$Rd, $Rn, $fcond",
(t2CSNEG rGPR:$Rd, GPRwithZRnosp:$Rn, GPRwithZRnosp:$Rn, pred_noal_inv:$fcond)>;
}
+
+
+// PACBTI
+let Predicates = [IsThumb2, HasV8_1MMainline, HasPACBTI] in {
+def t2PACG : V8_1MI<(outs rGPR:$Rd),
+ (ins pred:$p, GPRnopc:$Rn, GPRnopc:$Rm),
+ AddrModeNone, NoItinerary, "pacg${p}", "$Rd, $Rn, $Rm", "", []> {
+ bits<4> Rd;
+ bits<4> Rn;
+ bits<4> Rm;
+ let Inst{31-20} = 0b111110110110;
+ let Inst{19-16} = Rn;
+ let Inst{15-12} = 0b1111;
+ let Inst{11-8} = Rd;
+ let Inst{7-4} = 0b0000;
+ let Inst{3-0} = Rm;
+}
+
+let hasSideEffects = 1 in {
+class PACBTIAut<dag iops, string asm, bit b>
+ : V8_1MI<(outs), iops,
+ AddrModeNone, NoItinerary, asm, "$Ra, $Rn, $Rm", "", []> {
+ bits<4> Ra;
+ bits<4> Rn;
+ bits<4> Rm;
+ let Inst{31-20} = 0b111110110101;
+ let Inst{19-16} = Rn;
+ let Inst{15-12} = Ra;
+ let Inst{11-5} = 0b1111000;
+ let Inst{4} = b;
+ let Inst{3-0} = Rm;
+}
+}
+
+def t2AUTG : PACBTIAut<(ins pred:$p, GPRnosp:$Ra, GPRnopc:$Rn, GPRnopc:$Rm),
+ "autg${p}", 0>;
+
+let isBranch = 1, isTerminator = 1, isIndirectBranch = 1 in {
+ def t2BXAUT : PACBTIAut<(ins pred:$p, GPRnosp:$Ra, rGPR:$Rn, GPRnopc:$Rm),
+ "bxaut${p}", 1>;
+}
+}
+
+
+class PACBTIHintSpaceInst<string asm, string ops, bits<8> imm>
+ : V8_1MI<(outs), (ins), AddrModeNone, NoItinerary, asm, ops, "", []> {
+ let Inst{31-8} = 0b111100111010111110000000;
+ let Inst{7-0} = imm;
+
+ let Unpredictable{19-16} = 0b1111;
+ let Unpredictable{13-11} = 0b101;
+
+ let DecoderMethod = "DecodeT2HintSpaceInstruction";
+}
+
+class PACBTIHintSpaceNoOpsInst<string asm, bits<8> imm>
+ : PACBTIHintSpaceInst<asm, "", imm>;
+
+class PACBTIHintSpaceDefInst<string asm, bits<8> imm>
+ : PACBTIHintSpaceInst<asm, "r12, lr, sp", imm> {
+ let Defs = [R12];
+ let Uses = [LR, SP];
+}
+
+class PACBTIHintSpaceUseInst<string asm, bits<8> imm>
+ : PACBTIHintSpaceInst<asm, "r12, lr, sp", imm> {
+ let Uses = [R12, LR, SP];
+}
+
+def t2PAC : PACBTIHintSpaceDefInst<"pac", 0b00011101>;
+def t2PACBTI : PACBTIHintSpaceDefInst<"pacbti", 0b00001101>;
+def t2BTI : PACBTIHintSpaceNoOpsInst<"bti", 0b00001111>;
+def t2AUT : PACBTIHintSpaceUseInst<"aut", 0b00101101> {
+ let hasSideEffects = 1;
+}
diff --git a/llvm/lib/Target/ARM/ARMPredicates.td b/llvm/lib/Target/ARM/ARMPredicates.td
index 2dc097566d144..c0dc6a3634715 100644
--- a/llvm/lib/Target/ARM/ARMPredicates.td
+++ b/llvm/lib/Target/ARM/ARMPredicates.td
@@ -107,6 +107,8 @@ def HasRAS : Predicate<"Subtarget->hasRAS()">,
AssemblerPredicate<(all_of FeatureRAS), "ras">;
def HasLOB : Predicate<"Subtarget->hasLOB()">,
AssemblerPredicate<(all_of FeatureLOB), "lob">;
+def HasPACBTI : Predicate<"Subtarget->hasPACBTI()">,
+ AssemblerPredicate<(all_of FeaturePACBTI), "pacbti">;
def HasFP16 : Predicate<"Subtarget->hasFP16()">,
AssemblerPredicate<(all_of FeatureFP16),"half-float conversions">;
def HasFullFP16 : Predicate<"Subtarget->hasFullFP16()">,
diff --git a/llvm/lib/Target/ARM/ARMRegisterInfo.td b/llvm/lib/Target/ARM/ARMRegisterInfo.td
index 9752b3166b454..760a5a5a20cf7 100644
--- a/llvm/lib/Target/ARM/ARMRegisterInfo.td
+++ b/llvm/lib/Target/ARM/ARMRegisterInfo.td
@@ -277,6 +277,16 @@ def GPRwithAPSR : RegisterClass<"ARM", [i32], 32, (add (sub GPR, PC), APSR_NZCV)
let DiagnosticString = "operand must be a register in range [r0, r14] or apsr_nzcv";
}
+// GPRs without the SP register. Used for BXAUT and AUTG
+def GPRnosp : RegisterClass<"ARM", [i32], 32, (add (sequence "R%u", 0, 12), LR, PC)> {
+ let AltOrders = [(add LR, GPRnosp), (trunc GPRnosp, 8),
+ (add (trunc GPRnosp, 8), R12, LR, (shl GPRnosp, 8))];
+ let AltOrderSelect = [{
+ return MF.getSubtarget<ARMSubtarget>().getGPRAllocationOrder(MF);
+ }];
+ let DiagnosticString = "operand must be a register in range [r0, r12] or LR or PC";
+}
+
// GPRs without the PC and SP registers but with APSR. Used by CLRM instruction.
def GPRwithAPSRnosp : RegisterClass<"ARM", [i32], 32, (add (sequence "R%u", 0, 12), LR, APSR)> {
let isAllocatable = 0;
diff --git a/llvm/lib/Target/ARM/ARMSubtarget.h b/llvm/lib/Target/ARM/ARMSubtarget.h
index 5e1217b6a468a..d51a888c951fe 100644
--- a/llvm/lib/Target/ARM/ARMSubtarget.h
+++ b/llvm/lib/Target/ARM/ARMSubtarget.h
@@ -373,6 +373,8 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
/// HasLOB - if true, the processor supports the Low Overhead Branch extension
bool HasLOB = false;
+ bool HasPACBTI = false;
+
/// If true, the instructions "vmov.i32 d0, #0" and "vmov.i32 q0, #0" are
/// particularly effective at zeroing a VFP register.
bool HasZeroCycleZeroing = false;
@@ -671,6 +673,7 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
bool hasCRC() const { return HasCRC; }
bool hasRAS() const { return HasRAS; }
bool hasLOB() const { return HasLOB; }
+ bool hasPACBTI() const { return HasPACBTI; }
bool hasVirtualization() const { return HasVirtualization; }
bool useNEONForSinglePrecisionFP() const {
diff --git a/llvm/lib/Target/ARM/ARMSystemRegister.td b/llvm/lib/Target/ARM/ARMSystemRegister.td
index f21c7f0246f91..c03db15d10411 100644
--- a/llvm/lib/Target/ARM/ARMSystemRegister.td
+++ b/llvm/lib/Target/ARM/ARMSystemRegister.td
@@ -106,6 +106,24 @@ def : MClassSysReg<0, 0, 1, 0x894, "control_ns">;
def : MClassSysReg<0, 0, 1, 0x898, "sp_ns">;
}
+let Requires = [{ {ARM::FeaturePACBTI} }] in {
+def : MClassSysReg<0, 0, 1, 0x820, "pac_key_p_0">;
+def : MClassSysReg<0, 0, 1, 0x821, "pac_key_p_1">;
+def : MClassSysReg<0, 0, 1, 0x822, "pac_key_p_2">;
+def : MClassSysReg<0, 0, 1, 0x823, "pac_key_p_3">;
+def : MClassSysReg<0, 0, 1, 0x824, "pac_key_u_0">;
+def : MClassSysReg<0, 0, 1, 0x825, "pac_key_u_1">;
+def : MClassSysReg<0, 0, 1, 0x826, "pac_key_u_2">;
+def : MClassSysReg<0, 0, 1, 0x827, "pac_key_u_3">;
+def : MClassSysReg<0, 0, 1, 0x8a0, "pac_key_p_0_ns">;
+def : MClassSysReg<0, 0, 1, 0x8a1, "pac_key_p_1_ns">;
+def : MClassSysReg<0, 0, 1, 0x8a2, "pac_key_p_2_ns">;
+def : MClassSysReg<0, 0, 1, 0x8a3, "pac_key_p_3_ns">;
+def : MClassSysReg<0, 0, 1, 0x8a4, "pac_key_u_0_ns">;
+def : MClassSysReg<0, 0, 1, 0x8a5, "pac_key_u_1_ns">;
+def : MClassSysReg<0, 0, 1, 0x8a6, "pac_key_u_2_ns">;
+def : MClassSysReg<0, 0, 1, 0x8a7, "pac_key_u_3_ns">;
+}
// Banked Registers
//
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 64d2e1bfa9b23..39f407ba71492 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -6429,15 +6429,17 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic == "hvc" ||
Mnemonic.startswith("vsel") || Mnemonic == "vins" || Mnemonic == "vmovx" ||
Mnemonic == "bxns" || Mnemonic == "blxns" ||
- Mnemonic == "vdot" || Mnemonic == "vmmla" ||
+ Mnemonic == "vdot" || Mnemonic == "vmmla" ||
Mnemonic == "vudot" || Mnemonic == "vsdot" ||
Mnemonic == "vcmla" || Mnemonic == "vcadd" ||
Mnemonic == "vfmal" || Mnemonic == "vfmsl" ||
- Mnemonic == "wls" || Mnemonic == "le" || Mnemonic == "dls" ||
- Mnemonic == "csel" || Mnemonic == "csinc" ||
+ Mnemonic == "wls" || Mnemonic == "le" || Mnemonic == "dls" ||
+ Mnemonic == "csel" || Mnemonic == "csinc" ||
Mnemonic == "csinv" || Mnemonic == "csneg" || Mnemonic == "cinc" ||
- Mnemonic == "cinv" || Mnemonic == "cneg" || Mnemonic == "cset" ||
- Mnemonic == "csetm")
+ Mnemonic == "cinv" || Mnemonic == "cneg" || Mnemonic == "cset" ||
+ Mnemonic == "csetm" ||
+ Mnemonic == "aut" || Mnemonic == "pac" || Mnemonic == "pacbti" ||
+ Mnemonic == "bti")
return Mnemonic;
// First, split out any predication code. Ignore mnemonics we know aren't
@@ -6581,9 +6583,11 @@ void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic,
Mnemonic == "csinc" || Mnemonic == "csinv" || Mnemonic == "csneg" ||
Mnemonic == "cinc" || Mnemonic == "cinv" || Mnemonic == "cneg" ||
Mnemonic == "cset" || Mnemonic == "csetm" ||
- Mnemonic.startswith("vpt") || Mnemonic.startswith("vpst") ||
(hasCDE() && MS.isCDEInstr(Mnemonic) &&
!MS.isITPredicableCDEInstr(Mnemonic)) ||
+ Mnemonic.startswith("vpt") || Mnemonic.startswith("vpst") ||
+ Mnemonic == "pac" || Mnemonic == "pacbti" || Mnemonic == "aut" ||
+ Mnemonic == "bti" ||
(hasMVE() &&
(Mnemonic.startswith("vst2") || Mnemonic.startswith("vld2") ||
Mnemonic.startswith("vst4") || Mnemonic.startswith("vld4") ||
@@ -12272,6 +12276,7 @@ bool ARMAsmParser::enableArchExtFeature(StringRef Name, SMLoc &ExtLoc) {
{ARM::FeatureFPARMv8, ARM::FeatureFullFP16}},
{ARM::AEK_RAS, {Feature_HasV8Bit}, {ARM::FeatureRAS}},
{ARM::AEK_LOB, {Feature_HasV8_1MMainlineBit}, {ARM::FeatureLOB}},
+ {ARM::AEK_PACBTI, {Feature_HasV8_1MMainlineBit}, {ARM::FeaturePACBTI}},
// FIXME: Unsupported extensions.
{ARM::AEK_OS, {}, {}},
{ARM::AEK_IWMMXT, {}, {}},
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index 9caef9f09ea96..c3df7dc88d791 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -185,8 +185,11 @@ static DecodeStatus DecodetGPREvenRegisterClass(MCInst &Inst, unsigned RegNo,
static DecodeStatus
DecodeGPRwithAPSR_NZCVnospRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
-static DecodeStatus DecodeGPRnopcRegisterClass(MCInst &Inst,
- unsigned RegNo, uint64_t Address,
+static DecodeStatus DecodeGPRnopcRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder);
+static DecodeStatus DecodeGPRnospRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPRwithAPSRRegisterClass(MCInst &Inst,
unsigned RegNo, uint64_t Address,
@@ -287,6 +290,9 @@ static DecodeStatus DecodeSETPANInstruction(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2CPSInstruction(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2HintSpaceInstruction(MCInst &Inst, unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
static DecodeStatus DecodeAddrModeImm12Operand(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeAddrMode5Operand(MCInst &Inst, unsigned Val,
@@ -1172,6 +1178,19 @@ DecodeGPRnopcRegisterClass(MCInst &Inst, unsigned RegNo,
return S;
}
+static DecodeStatus DecodeGPRnospRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ if (RegNo == 13)
+ S = MCDisassembler::SoftFail;
+
+ Check(S, DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder));
+
+ return S;
+}
+
static DecodeStatus
DecodeGPRwithAPSRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
@@ -2441,6 +2460,31 @@ static DecodeStatus DecodeT2CPSInstruction(MCInst &Inst, unsigned Insn,
return S;
}
+static DecodeStatus DecodeT2HintSpaceInstruction(MCInst &Inst, unsigned Insn,
+ uint64_t Address,
+ const void *Decoder) {
+ unsigned imm = fieldFromInstruction(Insn, 0, 8);
+
+ unsigned Opcode = ARM::t2HINT;
+
+ if (imm == 0x0D) {
+ Opcode = ARM::t2PACBTI;
+ } else if (imm == 0x1D) {
+ Opcode = ARM::t2PAC;
+ } else if (imm == 0x2D) {
+ Opcode = ARM::t2AUT;
+ } else if (imm == 0x0F) {
+ Opcode = ARM::t2BTI;
+ }
+
+ Inst.setOpcode(Opcode);
+ if (Opcode == ARM::t2HINT) {
+ Inst.addOperand(MCOperand::createImm(imm));
+ }
+
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeT2MOVTWInstruction(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
@@ -4726,6 +4770,25 @@ static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
if (!(FeatureBits[ARM::Feature8MSecExt]))
return MCDisassembler::Fail;
break;
+ case 0x20: // pac_key_p_0
+ case 0x21: // pac_key_p_1
+ case 0x22: // pac_key_p_2
+ case 0x23: // pac_key_p_3
+ case 0x24: // pac_key_u_0
+ case 0x25: // pac_key_u_1
+ case 0x26: // pac_key_u_2
+ case 0x27: // pac_key_u_3
+ case 0xa0: // pac_key_p_0_ns
+ case 0xa1: // pac_key_p_1_ns
+ case 0xa2: // pac_key_p_2_ns
+ case 0xa3: // pac_key_p_3_ns
+ case 0xa4: // pac_key_u_0_ns
+ case 0xa5: // pac_key_u_1_ns
+ case 0xa6: // pac_key_u_2_ns
+ case 0xa7: // pac_key_u_3_ns
+ if (!(FeatureBits[ARM::FeaturePACBTI]))
+ return MCDisassembler::Fail;
+ break;
default:
// Architecturally defined as unpredictable
S = MCDisassembler::SoftFail;
diff --git a/llvm/test/CodeGen/Thumb/high-reg-clobber.mir b/llvm/test/CodeGen/Thumb/high-reg-clobber.mir
index 7b292aee7f7ea..ab73f1448d715 100644
--- a/llvm/test/CodeGen/Thumb/high-reg-clobber.mir
+++ b/llvm/test/CodeGen/Thumb/high-reg-clobber.mir
@@ -31,14 +31,14 @@ body: |
; CHECK: tSTRspi [[COPY]], %stack.0, 0, 14 /* CC::al */, $noreg
; CHECK: [[tLDRspi:%[0-9]+]]:tgpr = tLDRspi %stack.0, 0, 14 /* CC::al */, $noreg
; CHECK: [[COPY1:%[0-9]+]]:hgpr = COPY [[tLDRspi]]
- ; CHECK: INLINEASM &"mov r12, $0", 1 /* sideeffect attdialect */, 1048585 /* reguse:GPRnoip_and_GPRwithAPSR_NZCVnosp */, [[COPY1]], 12 /* clobber */, implicit-def early-clobber $r12
+ ; CHECK: INLINEASM &"mov r12, $0", 1 /* sideeffect attdialect */, 1048585 /* reguse:GPRnoip_and_GPRnopc */, %1, 12 /* clobber */, implicit-def early-clobber $r12
; CHECK: tBX_RET 14 /* CC::al */, $noreg
; FAST-LABEL: name: constraint_h
; FAST: liveins: $r0
; FAST: tSTRspi killed renamable $r0, %stack.0, 0, 14 /* CC::al */, $noreg
; FAST: renamable $r0 = tLDRspi %stack.0, 0, 14 /* CC::al */, $noreg
; FAST: renamable $r8 = COPY killed renamable $r0
- ; FAST: INLINEASM &"mov r12, $0", 1 /* sideeffect attdialect */, 1048585 /* reguse:GPRnoip_and_GPRwithAPSR_NZCVnosp */, killed renamable $r8, 12 /* clobber */, implicit-def dead early-clobber $r12
+ ; FAST: INLINEASM &"mov r12, $0", 1 /* sideeffect attdialect */, 1048585 /* reguse:GPRnoip_and_GPRnopc */, killed renamable $r8, 12 /* clobber */, implicit-def dead early-clobber $r12
; FAST: tBX_RET 14 /* CC::al */, $noreg
%0:tgpr = COPY $r0
tSTRspi %0, %stack.0, 0, 14 /* CC::al */, $noreg
diff --git a/llvm/test/MC/ARM/armv8.1m-pacbti-error.s b/llvm/test/MC/ARM/armv8.1m-pacbti-error.s
new file mode 100644
index 0000000000000..cb42ff39ecc90
--- /dev/null
+++ b/llvm/test/MC/ARM/armv8.1m-pacbti-error.s
@@ -0,0 +1,40 @@
+// RUN: not llvm-mc -triple thumbv8.1m.main-arm-none-eabi -mattr=+pacbti %s -show-encoding -o - 2>&1 | FileCheck %s
+
+// CHECK: error: invalid operand for instruction
+pac r0, lr, sp
+// CHECK: error: invalid operand for instruction
+pac r12, r1, sp
+// CHECK: error: operand must be a register sp
+pac r12, lr, r2
+
+// CHECK: error: invalid operand for instruction
+aut r0, lr, sp
+// CHECK: error: invalid operand for instruction
+aut r12, r1, sp
+// CHECK: error: operand must be a register sp
+aut r12, lr, r2
+
+// CHECK: operand must be a register in range [r0, r12] or LR or PC
+autg sp, r1, r2
+// CHECK: operand must be a register in range [r0, r14]
+autg r0, pc, r2
+// CHECK: operand must be a register in range [r0, r14]
+autg r0, r1, pc
+
+// CHECK: operand must be a register in range [r0, r12] or r14
+pacg sp, r1, r2
+// CHECK: operand must be a register in range [r0, r12] or r14
+pacg pc, r1, r2
+// CHECK: operand must be a register in range [r0, r14]
+pacg r0, pc, r2
+// CHECK: operand must be a register in range [r0, r14]
+pacg r0, r1, pc
+
+// CHECK: operand must be a register in range [r0, r12] or LR or PC
+bxaut sp, r1, r2
+// CHECK: operand must be a register in range [r0, r12] or r14
+bxaut r0, sp, r2
+// CHECK: operand must be a register in range [r0, r12] or r14
+bxaut r0, pc, r2
+// CHECK: operand must be a register in range [r0, r14]
+bxaut r0, r1, pc
diff --git a/llvm/test/MC/ARM/armv8.1m-pacbti.s b/llvm/test/MC/ARM/armv8.1m-pacbti.s
new file mode 100644
index 0000000000000..ec09142e8da84
--- /dev/null
+++ b/llvm/test/MC/ARM/armv8.1m-pacbti.s
@@ -0,0 +1,134 @@
+// RUN: llvm-mc -triple thumbv8.1m.main-arm-none-eabi -mattr=+pacbti %s -show-encoding -o - | FileCheck %s
+// RUN: not llvm-mc -triple thumbv8.1m.main-arm-none-eabi -mattr=-pacbti %s -show-encoding -o - 2>&1 | FileCheck %s --check-prefix=CHECK-NOPACBTI
+
+// CHECK: autg r0, r1, r2 @ encoding: [0x51,0xfb,0x02,0x0f]
+// CHECK-NOPACBTI: error: instruction requires: pacbti
+autg r0, r1, r2
+// CHECK: autg r12, lr, sp @ encoding: [0x5e,0xfb,0x0d,0xcf]
+// CHECK-NOPACBTI: error: instruction requires: pacbti
+autg ip, lr, sp
+// CHECK: aut r12, lr, sp @ encoding: [0xaf,0xf3,0x2d,0x80]
+aut ip, lr, sp
+// CHECK: aut r12,lr,sp @ encoding: [0xaf,0xf3,0x2d,0x80]
+hint.w #45
+// CHECK: bxaut r0, r1, r2 @ encoding: [0x51,0xfb,0x12,0x0f]
+// CHECK-NOPACBTI: error: instruction requires: pacbti
+bxaut r0, r1, r2
+
+// CHECK: bti @ encoding: [0xaf,0xf3,0x0f,0x80]
+bti
+// CHECK: bti @ encoding: [0xaf,0xf3,0x0f,0x80]
+hint.w #15
+
+// CHECK: pacg r0, r1, r2 @ encoding: [0x61,0xfb,0x02,0xf0]
+// CHECK-NOPACBTI: error: instruction requires: pacbti
+pacg r0, r1, r2
+// CHECK: pacg r12, lr, sp @ encoding: [0x6e,0xfb,0x0d,0xfc]
+// CHECK-NOPACBTI: error: instruction requires: pacbti
+pacg ip, lr, sp
+// CHECK: pac r12, lr, sp @ encoding: [0xaf,0xf3,0x1d,0x80]
+pac ip, lr, sp
+// CHECK: pac r12,lr,sp @ encoding: [0xaf,0xf3,0x1d,0x80]
+hint.w #29
+// CHECK: pacbti r12, lr, sp @ encoding: [0xaf,0xf3,0x0d,0x80]
+pacbti ip, lr, sp
+// CHECK: pacbti r12,lr,sp @ encoding: [0xaf,0xf3,0x0d,0x80]
+hint.w #13
+
+// CHECK: msr pac_key_p_0, r0 @ encoding: [0x80,0xf3,0x20,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_p_0, r0
+// CHECK: msr pac_key_p_1, r0 @ encoding: [0x80,0xf3,0x21,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_p_1, r0
+// CHECK: msr pac_key_p_2, r0 @ encoding: [0x80,0xf3,0x22,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_p_2, r0
+// CHECK: msr pac_key_p_3, r0 @ encoding: [0x80,0xf3,0x23,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_p_3, r0
+// CHECK: msr pac_key_u_0, r0 @ encoding: [0x80,0xf3,0x24,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_u_0, r0
+// CHECK: msr pac_key_u_1, r0 @ encoding: [0x80,0xf3,0x25,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_u_1, r0
+// CHECK: msr pac_key_u_2, r0 @ encoding: [0x80,0xf3,0x26,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_u_2, r0
+// CHECK: msr pac_key_u_3, r0 @ encoding: [0x80,0xf3,0x27,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_u_3, r0
+// CHECK: msr pac_key_p_0_ns, r0 @ encoding: [0x80,0xf3,0xa0,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_p_0_ns, r0
+// CHECK: msr pac_key_p_1_ns, r0 @ encoding: [0x80,0xf3,0xa1,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_p_1_ns, r0
+// CHECK: msr pac_key_p_2_ns, r0 @ encoding: [0x80,0xf3,0xa2,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_p_2_ns, r0
+// CHECK: msr pac_key_p_3_ns, r0 @ encoding: [0x80,0xf3,0xa3,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_p_3_ns, r0
+// CHECK: msr pac_key_u_0_ns, r0 @ encoding: [0x80,0xf3,0xa4,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_u_0_ns, r0
+// CHECK: msr pac_key_u_1_ns, r0 @ encoding: [0x80,0xf3,0xa5,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_u_1_ns, r0
+// CHECK: msr pac_key_u_2_ns, r0 @ encoding: [0x80,0xf3,0xa6,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_u_2_ns, r0
+// CHECK: msr pac_key_u_3_ns, r0 @ encoding: [0x80,0xf3,0xa7,0x88]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+msr pac_key_u_3_ns, r0
+
+// CHECK: mrs r0, pac_key_p_0 @ encoding: [0xef,0xf3,0x20,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_p_0
+// CHECK: mrs r0, pac_key_p_1 @ encoding: [0xef,0xf3,0x21,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_p_1
+// CHECK: mrs r0, pac_key_p_2 @ encoding: [0xef,0xf3,0x22,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_p_2
+// CHECK: mrs r0, pac_key_p_3 @ encoding: [0xef,0xf3,0x23,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_p_3
+// CHECK: mrs r0, pac_key_u_0 @ encoding: [0xef,0xf3,0x24,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_u_0
+// CHECK: mrs r0, pac_key_u_1 @ encoding: [0xef,0xf3,0x25,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_u_1
+// CHECK: mrs r0, pac_key_u_2 @ encoding: [0xef,0xf3,0x26,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_u_2
+// CHECK: mrs r0, pac_key_u_3 @ encoding: [0xef,0xf3,0x27,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_u_3
+// CHECK: mrs r0, pac_key_p_0_ns @ encoding: [0xef,0xf3,0xa0,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_p_0_ns
+// CHECK: mrs r0, pac_key_p_1_ns @ encoding: [0xef,0xf3,0xa1,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_p_1_ns
+// CHECK: mrs r0, pac_key_p_2_ns @ encoding: [0xef,0xf3,0xa2,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_p_2_ns
+// CHECK: mrs r0, pac_key_p_3_ns @ encoding: [0xef,0xf3,0xa3,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_p_3_ns
+// CHECK: mrs r0, pac_key_u_0_ns @ encoding: [0xef,0xf3,0xa4,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_u_0_ns
+// CHECK: mrs r0, pac_key_u_1_ns @ encoding: [0xef,0xf3,0xa5,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_u_1_ns
+// CHECK: mrs r0, pac_key_u_2_ns @ encoding: [0xef,0xf3,0xa6,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_u_2_ns
+// CHECK: mrs r0, pac_key_u_3_ns @ encoding: [0xef,0xf3,0xa7,0x80]
+// CHECK-NOPACBTI: error: invalid operand for instruction
+mrs r0, pac_key_u_3_ns
diff --git a/llvm/test/MC/ARM/implicit-it-generation-v8.s b/llvm/test/MC/ARM/implicit-it-generation-v8.s
new file mode 100644
index 0000000000000..5a18da87ec88a
--- /dev/null
+++ b/llvm/test/MC/ARM/implicit-it-generation-v8.s
@@ -0,0 +1,9 @@
+@ RUN: llvm-mc -triple thumbv8.1m.main-arm-none-eabi -arm-implicit-it=always -mattr=+pacbti < %s -show-encoding | FileCheck %s
+
+autgeq r0, r1, r2
+pacgeq r0, r1, r2
+bxauteq r0, r1, r2
+@ CHECK: ittt eq
+@ CHECK: autgeq r0, r1, r2
+@ CHECK: pacgeq r0, r1, r2
+@ CHECK: bxauteq r0, r1, r2
diff --git a/llvm/test/MC/Disassembler/ARM/armv8.1m-pacbti.txt b/llvm/test/MC/Disassembler/ARM/armv8.1m-pacbti.txt
new file mode 100644
index 0000000000000..1861bf4241e40
--- /dev/null
+++ b/llvm/test/MC/Disassembler/ARM/armv8.1m-pacbti.txt
@@ -0,0 +1,137 @@
+# RUN: llvm-mc -triple thumbv8.1m.main-arm-none-eabi -mattr=+pacbti -disassemble %s 2> /dev/null | FileCheck %s
+
+0x51,0xfb,0x02,0x0f
+0x5e,0xfb,0x0d,0xcf
+0xaf,0xf3,0x2d,0x80
+0x51,0xfb,0x12,0x0f
+0xaf,0xf3,0x0f,0x80
+0x61,0xfb,0x02,0xf0
+0x6e,0xfb,0x0d,0xfc
+0xaf,0xf3,0x1d,0x80
+0xaf,0xf3,0x0d,0x80
+0x80,0xf3,0x20,0x88
+0x80,0xf3,0x21,0x88
+0x80,0xf3,0x22,0x88
+0x80,0xf3,0x23,0x88
+0x80,0xf3,0x24,0x88
+0x80,0xf3,0x25,0x88
+0x80,0xf3,0x26,0x88
+0x80,0xf3,0x27,0x88
+0x80,0xf3,0xa0,0x88
+0x80,0xf3,0xa1,0x88
+0x80,0xf3,0xa2,0x88
+0x80,0xf3,0xa3,0x88
+0x80,0xf3,0xa4,0x88
+0x80,0xf3,0xa5,0x88
+0x80,0xf3,0xa6,0x88
+0x80,0xf3,0xa7,0x88
+0xef,0xf3,0x20,0x80
+0xef,0xf3,0x21,0x80
+0xef,0xf3,0x22,0x80
+0xef,0xf3,0x23,0x80
+0xef,0xf3,0x24,0x80
+0xef,0xf3,0x25,0x80
+0xef,0xf3,0x26,0x80
+0xef,0xf3,0x27,0x80
+0xef,0xf3,0xa0,0x80
+0xef,0xf3,0xa1,0x80
+0xef,0xf3,0xa2,0x80
+0xef,0xf3,0xa3,0x80
+0xef,0xf3,0xa4,0x80
+0xef,0xf3,0xa5,0x80
+0xef,0xf3,0xa6,0x80
+0xef,0xf3,0xa7,0x80
+
+# Test softfail encodings
+0xa7,0xf3,0x1d,0x80
+0xab,0xf3,0x1d,0x80
+0xad,0xf3,0x1d,0x80
+0xae,0xf3,0x1d,0x80
+0xaf,0xf3,0x1d,0x88
+0xaf,0xf3,0x1d,0xa0
+0xaf,0xf3,0x2d,0x80
+0xab,0xf3,0x2d,0x80
+0xad,0xf3,0x2d,0x80
+0xae,0xf3,0x2d,0x80
+0xaf,0xf3,0x2d,0x88
+0xaf,0xf3,0x2d,0xa0
+0xa7,0xf3,0x0f,0x80
+0xab,0xf3,0x0f,0x80
+0xad,0xf3,0x0f,0x80
+0xae,0xf3,0x0f,0x80
+0xaf,0xf3,0x0f,0x88
+0xaf,0xf3,0x0f,0xa0
+0xa7,0xf3,0x0d,0x80
+0xab,0xf3,0x0d,0x80
+0xad,0xf3,0x0d,0x80
+0xae,0xf3,0x0d,0x80
+0xaf,0xf3,0x0d,0x88
+0xaf,0xf3,0x0d,0xa0
+
+# CHECK: autg r0, r1, r2
+# CHECK: autg r12, lr, sp
+# CHECK: aut r12, lr, sp
+# CHECK: bxaut r0, r1, r2
+# CHECK: bti
+# CHECK: pacg r0, r1, r2
+# CHECK: pacg r12, lr, sp
+# CHECK: pac r12, lr, sp
+# CHECK: pacbti r12, lr, sp
+# CHECK: msr pac_key_p_0, r0
+# CHECK: msr pac_key_p_1, r0
+# CHECK: msr pac_key_p_2, r0
+# CHECK: msr pac_key_p_3, r0
+# CHECK: msr pac_key_u_0, r0
+# CHECK: msr pac_key_u_1, r0
+# CHECK: msr pac_key_u_2, r0
+# CHECK: msr pac_key_u_3, r0
+# CHECK: msr pac_key_p_0_ns, r0
+# CHECK: msr pac_key_p_1_ns, r0
+# CHECK: msr pac_key_p_2_ns, r0
+# CHECK: msr pac_key_p_3_ns, r0
+# CHECK: msr pac_key_u_0_ns, r0
+# CHECK: msr pac_key_u_1_ns, r0
+# CHECK: msr pac_key_u_2_ns, r0
+# CHECK: msr pac_key_u_3_ns, r0
+# CHECK: mrs r0, pac_key_p_0
+# CHECK: mrs r0, pac_key_p_1
+# CHECK: mrs r0, pac_key_p_2
+# CHECK: mrs r0, pac_key_p_3
+# CHECK: mrs r0, pac_key_u_0
+# CHECK: mrs r0, pac_key_u_1
+# CHECK: mrs r0, pac_key_u_2
+# CHECK: mrs r0, pac_key_u_3
+# CHECK: mrs r0, pac_key_p_0_ns
+# CHECK: mrs r0, pac_key_p_1_ns
+# CHECK: mrs r0, pac_key_p_2_ns
+# CHECK: mrs r0, pac_key_p_3_ns
+# CHECK: mrs r0, pac_key_u_0_ns
+# CHECK: mrs r0, pac_key_u_1_ns
+# CHECK: mrs r0, pac_key_u_2_ns
+# CHECK: mrs r0, pac_key_u_3_ns
+
+# Softfail encodings
+# CHECK: pac r12, lr, sp
+# CHECK: pac r12, lr, sp
+# CHECK: pac r12, lr, sp
+# CHECK: pac r12, lr, sp
+# CHECK: pac r12, lr, sp
+# CHECK: pac r12, lr, sp
+# CHECK: aut r12, lr, sp
+# CHECK: aut r12, lr, sp
+# CHECK: aut r12, lr, sp
+# CHECK: aut r12, lr, sp
+# CHECK: aut r12, lr, sp
+# CHECK: aut r12, lr, sp
+# CHECK: bti
+# CHECK: bti
+# CHECK: bti
+# CHECK: bti
+# CHECK: bti
+# CHECK: bti
+# CHECK: pacbti r12, lr, sp
+# CHECK: pacbti r12, lr, sp
+# CHECK: pacbti r12, lr, sp
+# CHECK: pacbti r12, lr, sp
+# CHECK: pacbti r12, lr, sp
+# CHECK: pacbti r12, lr, sp
More information about the cfe-commits
mailing list