Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -4050,6 +4050,11 @@ return ArchName.endswith("v6t2") || ArchName.endswith("v7") || ArchName.endswith("v8") || CPUArch == "6T2" || CPUArchVer >= 7; } + bool hasQFlag(StringRef ArchName, unsigned CPUArchVer) const { + // ARMv5 variant 'e' and later have bit[27] of the CPSR defined as the Q bit + return CPUArchVer > 5 || ArchName.endswith("v5e") || + ArchName.endswith("v5te"); + } void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override { // Target identification. @@ -4096,6 +4101,10 @@ // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex) + // ACLE 6.4.6 Q (saturation) flag + if (hasQFlag(ArchName, CPUArchVer)) + Builder.defineMacro("__ARM_FEATURE_QBIT", "1"); + // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset. if (!CPUProfile.empty()) Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'"); Index: lib/Headers/arm_acle.h =================================================================== --- lib/Headers/arm_acle.h +++ lib/Headers/arm_acle.h @@ -107,6 +107,25 @@ } /* 9 DATA-PROCESSING INTRINSICS */ + +/* 9.1.1 The Q (saturation) flag */ +static __inline__ int __attribute__((always_inline, nodebug)) +__saturation_occurred(void) { + uint32_t cpsr; + __asm__ __volatile__("mrs %0, cpsr" : "=r"(cpsr)); + return cpsr & 0x08000000; +} + +static __inline__ void __attribute__((always_inline, nodebug)) +__set_saturation_occurred(int occurred) { + __asm__ __volatile__ ("msr cpsr_q, %0" : : "r" (occurred)); +} + +static __inline__ void __attribute__((always_inline, nodebug)) +__ignore_saturation(void) { + /* not yet implemented */ +} + /* 9.2 Miscellaneous data-processing intrinsics */ /* ROR */ static __inline__ uint32_t __attribute__((always_inline, nodebug)) Index: test/Preprocessor/arm-acle-6.4.c =================================================================== --- test/Preprocessor/arm-acle-6.4.c +++ test/Preprocessor/arm-acle-6.4.c @@ -5,6 +5,7 @@ // CHECK-CORTEX-M0-NOT: __ARM_ARCH_ISA_ARM // CHECK-CORTEX-M0: __ARM_ARCH_ISA_THUMB 1 // CHECK-CORTEX-M0: __ARM_ARCH_PROFILE 'M' +// CHECK-CORTEX-M0: __ARM_FEATURE_QBIT 1 // CHECK-CORTEX-M0-NOT: __ARM_FEATURE_NUMERIC_MAXMIN // CHECK-CORTEX-M0-NOT: __ARM_FEATURE_DIRECTED_ROUNDING @@ -15,6 +16,7 @@ // CHECK-ARM810: __ARM_ARCH_ISA_ARM 1 // CHECK-ARM810-NOT: __ARM_ARCH_ISA_THUMB // CHECK-ARM810-NOT: __ARM_ARCH_PROFILE +// CHECK-ARM810-NOT: __ARM_FEATURE_QBIT // CHECK-ARM810-NOT: __ARM_FEATURE_NUMERIC_MAXMIN // CHECK-ARM810-NOT: __ARM_FEATURE_DIRECTED_ROUNDING @@ -25,6 +27,7 @@ // CHECK-ARM7TDMI: __ARM_ARCH_ISA_ARM 1 // CHECK-ARM7TDMI: __ARM_ARCH_ISA_THUMB 1 // CHECK-ARM7TDMI-NOT: __ARM_ARCH_PROFILE +// CHECK-ARM7TDMI-NOT: __ARM_FEATURE_QBIT // RUN: %clang -target arm-eabi -mcpu=cortex-a7 -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-CORTEX-A7 @@ -33,6 +36,7 @@ // CHECK-CORTEX-A7: __ARM_ARCH_ISA_ARM 1 // CHECK-CORTEX-A7: __ARM_ARCH_ISA_THUMB 2 // CHECK-CORTEX-A7: __ARM_ARCH_PROFILE 'A' +// CHECK-CORTEX-A7: __ARM_FEATURE_QBIT // CHECK-CORTEX-A7-NOT: __ARM_FEATURE_NUMERIC_MAXMIN // CHECK-CORTEX-A7-NOT: __ARM_FEATURE_DIRECTED_ROUNDING @@ -43,4 +47,13 @@ // CHECK-CORTEX-R4: __ARM_ARCH_ISA_ARM 1 // CHECK-CORTEX-R4: __ARM_ARCH_ISA_THUMB 2 // CHECK-CORTEX-R4: __ARM_ARCH_PROFILE 'R' +// CHECK-CORTEX-R4: __ARM_FEATURE_QBIT + +// RUN: %clang -target arm-eabi -mcpu=arm10tdmi -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-ARMv5 + +// CHECK-ARMv5-NOT: __ARM_FEATURE_QBIT + +// RUN: %clang -target arm-eabi -mcpu=arm10e -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-ARMv5TE + +// CHECK-ARMv5TE: __ARM_FEATURE_QBIT