diff --git a/clang/test/Driver/armv8.1m.main.c b/clang/test/Driver/armv8.1m.main.c --- 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.h b/llvm/include/llvm/Support/ARMTargetParser.h --- a/llvm/include/llvm/Support/ARMTargetParser.h +++ b/llvm/include/llvm/Support/ARMTargetParser.h @@ -59,7 +59,7 @@ 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/include/llvm/Support/ARMTargetParser.def b/llvm/include/llvm/Support/ARMTargetParser.def --- a/llvm/include/llvm/Support/ARMTargetParser.def +++ b/llvm/include/llvm/Support/ARMTargetParser.def @@ -201,6 +201,7 @@ 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/lib/Target/ARM/ARM.td b/llvm/lib/Target/ARM/ARM.td --- a/llvm/lib/Target/ARM/ARM.td +++ b/llvm/lib/Target/ARM/ARM.td @@ -442,6 +442,10 @@ "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 --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -4055,6 +4055,8 @@ 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<"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; @@ -5641,3 +5648,78 @@ 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 + : 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 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 imm> + : PACBTIHintSpaceInst; + +class PACBTIHintSpaceDefInst imm> + : PACBTIHintSpaceInst { + let Defs = [R12]; + let Uses = [LR, SP]; +} + +class PACBTIHintSpaceUseInst imm> + : PACBTIHintSpaceInst { + 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 --- a/llvm/lib/Target/ARM/ARMPredicates.td +++ b/llvm/lib/Target/ARM/ARMPredicates.td @@ -107,6 +107,8 @@ 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 --- a/llvm/lib/Target/ARM/ARMRegisterInfo.td +++ b/llvm/lib/Target/ARM/ARMRegisterInfo.td @@ -277,6 +277,16 @@ 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().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 --- a/llvm/lib/Target/ARM/ARMSubtarget.h +++ b/llvm/lib/Target/ARM/ARMSubtarget.h @@ -373,6 +373,8 @@ /// 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 @@ 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 --- a/llvm/lib/Target/ARM/ARMSystemRegister.td +++ b/llvm/lib/Target/ARM/ARMSystemRegister.td @@ -106,6 +106,24 @@ 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 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -6429,15 +6429,17 @@ 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 @@ 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 @@ {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 --- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -185,8 +185,11 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 --- a/llvm/test/CodeGen/Thumb/high-reg-clobber.mir +++ b/llvm/test/CodeGen/Thumb/high-reg-clobber.mir @@ -31,14 +31,14 @@ ; 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 --- /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 --- /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 --- /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 --- /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