Index: lib/Target/ARM/ARM.td =================================================================== --- lib/Target/ARM/ARM.td +++ lib/Target/ARM/ARM.td @@ -89,6 +89,8 @@ "Enable support for Performance Monitor extensions">; def FeatureTrustZone : SubtargetFeature<"trustzone", "HasTrustZone", "true", "Enable support for TrustZone security extensions">; +def Feature8MSecExt : SubtargetFeature<"8msecext", "Has8MSecExt", "true", + "Enable support for ARMv8-M Security Extensions">; def FeatureCrypto : SubtargetFeature<"crypto", "HasCrypto", "true", "Enable support for Cryptography extensions", [FeatureNEON]>; @@ -394,6 +396,7 @@ FeatureDB, FeatureHWDiv, FeatureV7Clrex, + Feature8MSecExt, FeatureAcquireRelease, FeatureMClass]>; @@ -402,6 +405,7 @@ FeatureNoARM, FeatureDB, FeatureHWDiv, + Feature8MSecExt, FeatureAcquireRelease, FeatureMClass]>; Index: lib/Target/ARM/ARMInstrInfo.td =================================================================== --- lib/Target/ARM/ARMInstrInfo.td +++ lib/Target/ARM/ARMInstrInfo.td @@ -272,6 +272,9 @@ def HasTrustZone : Predicate<"Subtarget->hasTrustZone()">, AssemblerPredicate<"FeatureTrustZone", "TrustZone">; +def Has8MSecExt : Predicate<"Subtarget->has8MSecExt()">, + AssemblerPredicate<"Feature8MSecExt", + "ARMv8-M Security Extensions">; def HasZCZ : Predicate<"Subtarget->hasZeroCycleZeroing()">; def UseNEONForFP : Predicate<"Subtarget->useNEONForSinglePrecisionFP()">; def DontUseNEONForFP : Predicate<"!Subtarget->useNEONForSinglePrecisionFP()">; Index: lib/Target/ARM/ARMInstrThumb.td =================================================================== --- lib/Target/ARM/ARMInstrThumb.td +++ lib/Target/ARM/ARMInstrThumb.td @@ -439,6 +439,14 @@ let Inst{2-0} = 0b000; let Unpredictable{2-0} = 0b111; } + def tBXNS : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bxns${p}\t$Rm", []>, + Requires<[IsThumb, Has8MSecExt]>, + T1Special<{1,1,0,?}>, Sched<[WriteBr]> { + bits<4> Rm; + let Inst{6-3} = Rm; + let Inst{2-0} = 0b100; + let Unpredictable{1-0} = 0b11; + } } let isReturn = 1, isTerminator = 1, isBarrier = 1 in { @@ -496,6 +504,17 @@ let Inst{2-0} = 0b000; } + // ARMv8-M Security Extensions + def tBLXNSr : TI<(outs), (ins pred:$p, GPRnopc:$func), IIC_Br, + "blxns${p}\t$func", []>, + Requires<[IsThumb, Has8MSecExt]>, + T1Special<{1,1,1,?}>, Sched<[WriteBrL]> { + bits<4> func; + let Inst{6-3} = func; + let Inst{2-0} = 0b100; + let Unpredictable{1-0} = 0b11; + } + // ARMv4T def tBX_CALL : tPseudoInst<(outs), (ins tGPR:$func), 4, IIC_Br, Index: lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- lib/Target/ARM/ARMInstrThumb2.td +++ lib/Target/ARM/ARMInstrThumb2.td @@ -4336,6 +4336,37 @@ } //===----------------------------------------------------------------------===// +// ARMv8-M Security Extensions instructions +// + +let hasSideEffects = 1 in +def t2SG : T2I<(outs), (ins), NoItinerary, "sg", "", []>, + Requires<[Has8MSecExt]> { + let Inst = 0xe97fe97f; +} + +class T2TT at, string asm, list pattern> + : T2I<(outs rGPR:$Rt), (ins GPRnopc:$Rn), NoItinerary, asm, "\t$Rt, $Rn", + pattern> { + bits<4> Rn; + bits<4> Rt; + + let Inst{31-20} = 0b111010000100; + let Inst{19-16} = Rn; + let Inst{15-12} = 0b1111; + let Inst{11-8} = Rt; + let Inst{7-6} = at; + let Inst{5-0} = 0b000000; + + let Unpredictable{5-0} = 0b111111; +} + +def t2TT : T2TT<0b00, "tt", []>, Requires<[IsThumb,Has8MSecExt]>; +def t2TTT : T2TT<0b01, "ttt", []>, Requires<[IsThumb,Has8MSecExt]>; +def t2TTA : T2TT<0b10, "tta", []>, Requires<[IsThumb,Has8MSecExt]>; +def t2TTAT : T2TT<0b11, "ttat", []>, Requires<[IsThumb,Has8MSecExt]>; + +//===----------------------------------------------------------------------===// // Non-Instruction Patterns // Index: lib/Target/ARM/ARMInstrVFP.td =================================================================== --- lib/Target/ARM/ARMInstrVFP.td +++ lib/Target/ARM/ARMInstrVFP.td @@ -200,6 +200,37 @@ def : MnemonicAlias<"vldm", "vldmia">; def : MnemonicAlias<"vstm", "vstmia">; + +//===----------------------------------------------------------------------===// +// Lazy load / store multiple Instructions +// +let mayLoad = 1 in +def VLLDM : AXSI4<(outs), (ins GPRnopc:$Rn, pred:$p), IndexModeNone, + IIC_fpLoad_m, "vlldm${p}\t$Rn", "", []>, + Requires<[HasV8MMainline, Has8MSecExt]> { + let Inst{24-23} = 0b00; + let Inst{22} = 0; + let Inst{21} = 1; + let Inst{20} = 1; + let Inst{15-12} = 0; + let Inst{7-0} = 0; + let mayLoad = 1; +} + +let mayStore = 1 in +def VLSTM : AXSI4<(outs), (ins GPRnopc:$Rn, pred:$p), IndexModeNone, + IIC_fpStore_m, "vlstm${p}\t$Rn", "", []>, + Requires<[HasV8MMainline, Has8MSecExt]> { + let Inst{24-23} = 0b00; + let Inst{22} = 0; + let Inst{21} = 1; + let Inst{20} = 0; + let Inst{15-12} = 0; + let Inst{7-0} = 0; + let mayStore = 1; +} + + // FLDM/FSTM - Load / Store multiple single / double precision registers for // pre-ARMv6 cores. // These instructions are deprecated! Index: lib/Target/ARM/ARMSubtarget.h =================================================================== --- lib/Target/ARM/ARMSubtarget.h +++ lib/Target/ARM/ARMSubtarget.h @@ -201,6 +201,9 @@ /// HasTrustZone - if true, processor supports TrustZone security extensions bool HasTrustZone; + /// Has8MSecExt - if true, processor supports ARMv8-M Security Extensions + bool Has8MSecExt; + /// HasCrypto - if true, processor supports Cryptography extensions bool HasCrypto; @@ -366,6 +369,7 @@ bool isFPOnlySP() const { return FPOnlySP; } bool hasPerfMon() const { return HasPerfMon; } bool hasTrustZone() const { return HasTrustZone; } + bool has8MSecExt() const { return Has8MSecExt; } bool hasZeroCycleZeroing() const { return HasZeroCycleZeroing; } bool prefers32BitThumb() const { return Pref32BitThumb; } bool avoidCPSRPartialUpdate() const { return AvoidCPSRPartialUpdate; } Index: lib/Target/ARM/ARMSubtarget.cpp =================================================================== --- lib/Target/ARM/ARMSubtarget.cpp +++ lib/Target/ARM/ARMSubtarget.cpp @@ -148,6 +148,7 @@ FPOnlySP = false; HasPerfMon = false; HasTrustZone = false; + Has8MSecExt = false; HasCrypto = false; HasCRC = false; HasZeroCycleZeroing = false; Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5268,7 +5268,7 @@ Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" || Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic == "hvc" || - Mnemonic.startswith("vsel")) + Mnemonic == "bxns" || Mnemonic == "blxns" || Mnemonic.startswith("vsel")) return Mnemonic; // First, split out any predication code. Ignore mnemonics we know aren't Index: test/MC/ARM/thumbv8m.s =================================================================== --- test/MC/ARM/thumbv8m.s +++ test/MC/ARM/thumbv8m.s @@ -1,8 +1,8 @@ // RUN: not llvm-mc -triple=thumbv8m.base -show-encoding < %s 2>%t \ -// RUN: | FileCheck --check-prefix=CHECK %s +// RUN: | FileCheck --check-prefix=CHECK-BASELINE --check-prefix=CHECK %s // RUN: FileCheck --check-prefix=UNDEF-BASELINE --check-prefix=UNDEF < %t %s // RUN: not llvm-mc -triple=thumbv8m.main -show-encoding < %s 2>%t \ -// RUN: | FileCheck --check-prefix=CHECK %s +// RUN: | FileCheck --check-prefix=CHECK-MAINLINE --check-prefix=CHECK %s // RUN: FileCheck --check-prefix=UNDEF-MAINLINE --check-prefix=UNDEF < %t %s // Simple check that baseline is v6M and mainline is v7M @@ -123,3 +123,94 @@ // UNDEF: error: instruction requires: !armv*m stlexd r0, r1, r2, [r2] + +// ARMv8-M Security Extensions + +// CHECK: sg @ encoding: [0x7f,0xe9,0x7f,0xe9] +sg + +// CHECK: bxns r0 @ encoding: [0x04,0x47] +bxns r0 + +// CHECK: bxns lr @ encoding: [0x74,0x47] +bxns lr + +// CHECK: blxns r0 @ encoding: [0x84,0x47] +blxns r0 + +// CHECK: tt r0, r1 @ encoding: [0x41,0xe8,0x00,0xf0] +tt r0, r1 + +// CHECK: tt r0, sp @ encoding: [0x4d,0xe8,0x00,0xf0] +tt r0, sp + +// CHECK: tta r0, r1 @ encoding: [0x41,0xe8,0x80,0xf0] +tta r0, r1 + +// CHECK: ttt r0, r1 @ encoding: [0x41,0xe8,0x40,0xf0] +ttt r0, r1 + +// CHECK: ttat r0, r1 @ encoding: [0x41,0xe8,0xc0,0xf0] +ttat r0, r1 + +// 'Lazy Load/Store Multiple' + +// UNDEF-BASELINE: error: instruction requires: armv8m.main +// CHECK-MAINLINE: vlldm r5 @ encoding: [0x35,0xec,0x00,0x0a] +vlldm r5 + +// UNDEF-BASELINE: error: instruction requires: armv8m.main +// CHECK-MAINLINE: vlstm r10 @ encoding: [0x2a,0xec,0x00,0x0a] +vlstm r10 + + +// Invalid operand tests +// UNDEF: error: invalid operand for instruction +// UNDEF: sg #0 +sg #0 +// UNDEF: error: invalid operand for instruction +// UNDEF: sg r0 +sg r0 +// UNDEF: error: invalid operand for instruction +// UNDEF: bxns r0, r1 +bxns r0, r1 +// UNDEF: error: invalid operand for instruction +// UNDEF: blxns r0, #0 +blxns r0, #0 +// UNDEF: error: invalid operand for instruction +// UNDEF: blxns label +blxns label +// UNDEF: error: invalid operand for instruction +// UNDEF: tt r0, r1, r2 +tt r0, r1, r2 +// UNDEF: error: invalid operand for instruction +// UNDEF: tt r0, [r1] +tt r0, [r1] +// UNDEF: error: invalid operand for instruction +// UNDEF: tt r0, r1, #4 +tt r0, r1, #4 +// UNDEF: error: invalid operand for instruction +// UNDEF: tt r0, #4 +tt r0, #4 + +// Unpredictable operands +// UNDEF: error: invalid operand for instruction +// UNDEF: blxns pc +blxns pc +// UNDEF: error: invalid operand for instruction +// UNDEF: tt sp, r0 +tt sp, r0 +// UNDEF: error: invalid operand for instruction +// UNDEF: tt pc, r0 +tt pc, r0 +// UNDEF: error: invalid operand for instruction +// UNDEF: tt r0, pc +tt r0, pc + +// UNDEF: error: invalid operand for instruction +// UNDEF: vlldm pc +vlldm pc + +// UNDEF: error: invalid operand for instruction +// UNDEF: vlstm pc +vlstm pc