[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