Index: include/llvm/ADT/Triple.h =================================================================== --- include/llvm/ADT/Triple.h +++ include/llvm/ADT/Triple.h @@ -96,6 +96,8 @@ ARMSubArch_v8_2a, ARMSubArch_v8_1a, ARMSubArch_v8, + ARMSubArch_v8m_baseline, + ARMSubArch_v8m_mainline, ARMSubArch_v7, ARMSubArch_v7em, ARMSubArch_v7m, Index: include/llvm/Support/ARMBuildAttributes.h =================================================================== --- include/llvm/Support/ARMBuildAttributes.h +++ include/llvm/Support/ARMBuildAttributes.h @@ -106,7 +106,9 @@ v6_M = 11, // e.g. Cortex M1 v6S_M = 12, // v6_M with the System extensions v7E_M = 13, // v7_M with DSP extensions - v8 = 14, // v8,v8.1a AArch32 + v8_A = 14, // v8_A AArch32 + v8_M_Base= 16, // v8_M_Base AArch32 + v8_M_Main= 17, // v8_M_Main AArch32 }; enum CPUArchProfile { // (=7), uleb128 @@ -126,6 +128,7 @@ // Tag_THUMB_ISA_use, (=9), uleb128 AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions) + AllowThumbDerived = 3, // Thumb allowed, derived from arch/profile // Tag_FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10) AllowFPv2 = 2, // v2 FP ISA permitted (implies use of the v1 FP ISA) Index: include/llvm/Support/ARMTargetParser.def =================================================================== --- include/llvm/Support/ARMTargetParser.def +++ include/llvm/Support/ARMTargetParser.def @@ -82,15 +82,19 @@ FK_NONE, AEK_HWDIV) ARM_ARCH("armv7e-m", AK_ARMV7EM, "7E-M", "v7em", ARMBuildAttrs::CPUArch::v7E_M, FK_NONE, (AEK_HWDIV | AEK_DSP)) -ARM_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8, +ARM_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | AEK_HWDIV | AEK_DSP | AEK_CRC)) -ARM_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a", ARMBuildAttrs::CPUArch::v8, +ARM_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a", ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | AEK_HWDIV | AEK_DSP | AEK_CRC)) -ARM_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a", ARMBuildAttrs::CPUArch::v8, +ARM_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a", ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | AEK_HWDIV | AEK_DSP | AEK_CRC)) +ARM_ARCH("armv8-m.base", AK_ARMV8MBaseline, "8-M.Baseline", "v8m.base", + ARMBuildAttrs::CPUArch::v8_M_Base, FK_NONE, AEK_HWDIV) +ARM_ARCH("armv8-m.main", AK_ARMV8MMainline, "8-M.Mainline", "v8m.main", + ARMBuildAttrs::CPUArch::v8_M_Main, FK_FPV5_D16, AEK_HWDIV) // Non-standard Arch names. ARM_ARCH("iwmmxt", AK_IWMMXT, "iwmmxt", "", ARMBuildAttrs::CPUArch::v5TE, FK_NONE, AEK_NONE) Index: lib/Support/TargetParser.cpp =================================================================== --- lib/Support/TargetParser.cpp +++ lib/Support/TargetParser.cpp @@ -411,6 +411,8 @@ .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") .Case("v8.1a", "v8.1-a") .Case("v8.2a", "v8.2-a") + .Case("v8m.base", "v8-m.base") + .Case("v8m.main", "v8-m.main") .Default(Arch); } @@ -548,6 +550,8 @@ case ARM::AK_ARMV6M: case ARM::AK_ARMV7M: case ARM::AK_ARMV7EM: + case ARM::AK_ARMV8MMainline: + case ARM::AK_ARMV8MBaseline: return ARM::PK_M; case ARM::AK_ARMV7R: return ARM::PK_R; @@ -597,6 +601,8 @@ case ARM::AK_ARMV8A: case ARM::AK_ARMV8_1A: case ARM::AK_ARMV8_2A: + case ARM::AK_ARMV8MBaseline: + case ARM::AK_ARMV8MMainline: return 8; } return 0; Index: lib/Support/Triple.cpp =================================================================== --- lib/Support/Triple.cpp +++ lib/Support/Triple.cpp @@ -521,6 +521,10 @@ return Triple::ARMSubArch_v8_1a; case ARM::AK_ARMV8_2A: return Triple::ARMSubArch_v8_2a; + case ARM::AK_ARMV8MBaseline: + return Triple::ARMSubArch_v8m_baseline; + case ARM::AK_ARMV8MMainline: + return Triple::ARMSubArch_v8m_mainline; default: return Triple::NoSubArch; } Index: lib/Target/ARM/ARM.td =================================================================== --- lib/Target/ARM/ARM.td +++ lib/Target/ARM/ARM.td @@ -205,12 +205,15 @@ def HasV6MOps : SubtargetFeature<"v6m", "HasV6MOps", "true", "Support ARM v6M instructions", [HasV6Ops]>; +def HasV8MBaselineOps : SubtargetFeature<"v8m", "HasV8MBaselineOps", "true", + "Support ARM v8M Baseline instructions", + [HasV6MOps]>; def HasV6KOps : SubtargetFeature<"v6k", "HasV6KOps", "true", "Support ARM v6k instructions", [HasV6Ops]>; def HasV6T2Ops : SubtargetFeature<"v6t2", "HasV6T2Ops", "true", "Support ARM v6t2 instructions", - [HasV6MOps, HasV6KOps, FeatureThumb2]>; + [HasV8MBaselineOps, HasV6KOps, FeatureThumb2]>; def HasV7Ops : SubtargetFeature<"v7", "HasV7Ops", "true", "Support ARM v7 instructions", [HasV6T2Ops, FeaturePerfMon, @@ -224,6 +227,9 @@ def HasV8_2aOps : SubtargetFeature<"v8.2a", "HasV8_2aOps", "true", "Support ARM v8.2a instructions", [HasV8_1aOps]>; +def HasV8MMainlineOps : SubtargetFeature<"v8m.main", "HasV8MMainlineOps", "true", + "Support ARM v8M Mainline instructions", + [HasV7Ops]>; //===----------------------------------------------------------------------===// @@ -380,6 +386,23 @@ FeatureCrypto, FeatureCRC]>; +def ARMv8mBaseline : Architecture<"armv8-m.base", "ARMv8mBaseline", + [HasV8MBaselineOps, + FeatureNoARM, + FeatureDB, + FeatureHWDiv, + FeatureV7Exclusives, + FeatureAcquireRelease, + FeatureMClass]>; + +def ARMv8mMainline : Architecture<"armv8-m.main", "ARMv8mMainline", + [HasV8MMainlineOps, + FeatureNoARM, + FeatureDB, + FeatureHWDiv, + FeatureAcquireRelease, + FeatureMClass]>; + // Aliases def IWMMXT : Architecture<"iwmmxt", "ARMv5te", [ARMv5te]>; def IWMMXT2 : Architecture<"iwmmxt2", "ARMv5te", [ARMv5te]>; Index: lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- lib/Target/ARM/ARMAsmPrinter.cpp +++ lib/Target/ARM/ARMAsmPrinter.cpp @@ -548,6 +548,12 @@ ATS.finishAttributeSection(); } +static bool isV8M(const ARMSubtarget *Subtarget) { + // Note that v8M Baseline is a subset of v6T2! + return (Subtarget->hasV8MBaselineOps() && !Subtarget->hasV6T2Ops()) || + Subtarget->hasV8MMainlineOps(); +} + //===----------------------------------------------------------------------===// // Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile() // FIXME: @@ -561,13 +567,17 @@ return ARMBuildAttrs::v5TEJ; if (Subtarget->hasV8Ops()) - return ARMBuildAttrs::v8; + return ARMBuildAttrs::v8_A; + else if (Subtarget->hasV8MMainlineOps()) + return ARMBuildAttrs::v8_M_Main; else if (Subtarget->hasV7Ops()) { if (Subtarget->isMClass() && Subtarget->hasDSP()) return ARMBuildAttrs::v7E_M; return ARMBuildAttrs::v7; } else if (Subtarget->hasV6T2Ops()) return ARMBuildAttrs::v6T2; + else if (Subtarget->hasV8MBaselineOps()) + return ARMBuildAttrs::v8_M_Base; else if (Subtarget->hasV6MOps()) return ARMBuildAttrs::v6S_M; else if (Subtarget->hasV6Ops()) @@ -627,7 +637,7 @@ // Tag_CPU_arch_profile must have the default value of 0 when "Architecture // profile is not applicable (e.g. pre v7, or cross-profile code)". - if (STI.hasV7Ops()) { + if (STI.hasV7Ops() || isV8M(&STI)) { if (STI.isAClass()) { ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile, ARMBuildAttrs::ApplicationProfile); @@ -643,7 +653,10 @@ ATS.emitAttribute(ARMBuildAttrs::ARM_ISA_use, STI.hasARMOps() ? ARMBuildAttrs::Allowed : ARMBuildAttrs::Not_Allowed); - if (STI.isThumb1Only()) { + if (isV8M(&STI)) { + ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use, + ARMBuildAttrs::AllowThumbDerived); + } else if (STI.isThumb1Only()) { ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use, ARMBuildAttrs::Allowed); } else if (STI.hasThumb2()) { ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use, Index: lib/Target/ARM/ARMInstrInfo.td =================================================================== --- lib/Target/ARM/ARMInstrInfo.td +++ lib/Target/ARM/ARMInstrInfo.td @@ -201,6 +201,12 @@ def HasV6M : Predicate<"Subtarget->hasV6MOps()">, AssemblerPredicate<"HasV6MOps", "armv6m or armv6t2">; +def HasV8MBaseline : Predicate<"Subtarget->hasV8MBaselineOps()">, + AssemblerPredicate<"HasV8MBaselineOps", + "armv8m.base">; +def HasV8MMainline : Predicate<"Subtarget->hasV8MMainlineOps()">, + AssemblerPredicate<"HasV8MMainlineOps", + "armv8m.main">; def HasV6T2 : Predicate<"Subtarget->hasV6T2Ops()">, AssemblerPredicate<"HasV6T2Ops", "armv6t2">; def NoV6T2 : Predicate<"!Subtarget->hasV6T2Ops()">; Index: lib/Target/ARM/ARMSubtarget.h =================================================================== --- lib/Target/ARM/ARMSubtarget.h +++ lib/Target/ARM/ARMSubtarget.h @@ -52,7 +52,7 @@ enum ARMArchEnum { ARMv2, ARMv2a, ARMv3, ARMv3m, ARMv4, ARMv4t, ARMv5, ARMv5t, ARMv5te, ARMv5tej, ARMv6, ARMv6k, ARMv6kz, ARMv6t2, ARMv6m, ARMv6sm, ARMv7a, ARMv7r, - ARMv7m, ARMv7em, ARMv8a, ARMv81a, ARMv82a + ARMv7m, ARMv7em, ARMv8a, ARMv81a, ARMv82a, ARMv8mMainline, ARMv8mBaseline }; /// ARMProcFamily - ARM processor family: Cortex-A8, Cortex-A9, and others. @@ -78,6 +78,8 @@ bool HasV8Ops; bool HasV8_1aOps; bool HasV8_2aOps; + bool HasV8MBaselineOps; + bool HasV8MMainlineOps; /// HasVFPv2, HasVFPv3, HasVFPv4, HasFPARMv8, HasNEON - Specify what /// floating point ISAs are supported. @@ -320,6 +322,8 @@ bool hasV8Ops() const { return HasV8Ops; } bool hasV8_1aOps() const { return HasV8_1aOps; } bool hasV8_2aOps() const { return HasV8_2aOps; } + bool hasV8MBaselineOps() const { return HasV8MBaselineOps; } + bool hasV8MMainlineOps() const { return HasV8MMainlineOps; } bool isCortexA5() const { return ARMProcFamily == CortexA5; } bool isCortexA7() const { return ARMProcFamily == CortexA7; } Index: lib/Target/ARM/ARMSubtarget.cpp =================================================================== --- lib/Target/ARM/ARMSubtarget.cpp +++ lib/Target/ARM/ARMSubtarget.cpp @@ -113,6 +113,8 @@ HasV8Ops = false; HasV8_1aOps = false; HasV8_2aOps = false; + HasV8MBaselineOps = false; + HasV8MMainlineOps = false; HasVFPv2 = false; HasVFPv3 = false; HasVFPv4 = false; Index: lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -757,6 +757,12 @@ setAttributeItem(Virtualization_use, AllowTZVirtualization, false); break; + case ARM::AK_ARMV8MBaseline: + case ARM::AK_ARMV8MMainline: + setAttributeItem(THUMB_ISA_use, AllowThumbDerived, false); + setAttributeItem(CPU_arch_profile, MicroControllerProfile, false); + break; + case ARM::AK_IWMMXT: setAttributeItem(ARM_ISA_use, Allowed, false); setAttributeItem(THUMB_ISA_use, Allowed, false); Index: test/CodeGen/ARM/build-attributes.ll =================================================================== --- test/CodeGen/ARM/build-attributes.ll +++ test/CodeGen/ARM/build-attributes.ll @@ -27,6 +27,8 @@ ; RUN: llc < %s -mtriple=armv8-linux-gnueabi -mattr=-fp-armv8,-crypto | FileCheck %s --check-prefix=V8-NEON ; RUN: llc < %s -mtriple=armv8-linux-gnueabi -mattr=-crypto | FileCheck %s --check-prefix=V8-FPARMv8-NEON ; RUN: llc < %s -mtriple=armv8-linux-gnueabi | FileCheck %s --check-prefix=V8-FPARMv8-NEON-CRYPTO +; RUN: llc < %s -mtriple=thumbv8m.base-linux-gnueabi | FileCheck %s --check-prefix=V8MBASELINE +; RUN: llc < %s -mtriple=thumbv8m.main-linux-gnueabi | FileCheck %s --check-prefix=V8MMAINLINE ; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a5 | FileCheck %s --check-prefix=CORTEX-A5-DEFAULT ; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a5 -enable-unsafe-fp-math -disable-fp-elim -enable-no-infs-fp-math -enable-no-nans-fp-math -fp-contract=fast | FileCheck %s --check-prefix=CORTEX-A5-DEFAULT-FAST ; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a5 -enable-sign-dependent-rounding-fp-math | FileCheck %s --check-prefix=DYN-ROUNDING @@ -367,6 +369,23 @@ ; V8-FPARMv8-NEON-CRYPTO: .fpu crypto-neon-fp-armv8 ; V8-FPARMv8-NEON-CRYPTO: .eabi_attribute 12, 3 +; V8MBASELINE: .syntax unified +; '6' is Tag_CPU_arch, '16' is ARM v8-M Baseline +; V8MBASELINE: .eabi_attribute 6, 16 +; '7' is Tag_CPU_arch_profile, '77' is 'M' +; V8MBASELINE: .eabi_attribute 7, 77 +; '8' is Tag_ARM_ISA_use +; V8MBASELINE: .eabi_attribute 8, 0 +; '9' is Tag_Thumb_ISA_use +; V8MBASELINE: .eabi_attribute 9, 3 + +; V8MMAINLINE: .syntax unified +; '6' is Tag_CPU_arch, '17' is ARM v8-M Mainline +; V8MMAINLINE: .eabi_attribute 6, 17 +; V8MMAINLINE: .eabi_attribute 7, 77 +; V8MMAINLINE: .eabi_attribute 8, 0 +; V8MMAINLINE: .eabi_attribute 9, 3 + ; Tag_CPU_unaligned_access ; NO-STRICT-ALIGN: .eabi_attribute 34, 1 ; STRICT-ALIGN: .eabi_attribute 34, 0 Index: test/MC/ARM/thumbv8m.s =================================================================== --- /dev/null +++ test/MC/ARM/thumbv8m.s @@ -0,0 +1,22 @@ +// RUN: not llvm-mc -triple=thumbv8m.base -show-encoding < %s 2>%t \ +// RUN: | FileCheck --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=UNDEF-MAINLINE --check-prefix=UNDEF < %t %s + +// Simple check that baseline is v6M and mainline is v7M +// UNDEF-BASELINE: error: instruction requires: thumb2 +// UNDEF-MAINLINE-NOT: error: instruction requires: +mov.w r0, r0 + +// Check that .arm is invalid +// UNDEF: target does not support ARM mode +.arm + +// Instruction availibility checks + +// 'Barrier instructions' + +// CHECK: isb sy @ encoding: [0xbf,0xf3,0x6f,0x8f] +isb sy