diff mbox

[RFA/ARM] Add ACLE Predefined macro support

Message ID 4FE8783A.3060905@arm.com
State New
Headers show

Commit Message

Matthew Gretton-Dann June 25, 2012, 2:39 p.m. UTC
Further testing has found a couple of failures to build with a C++ compiler, 
and trunk has moved on a bit so the patch doesn't apply cleanly.

An updated patch is attached.

OK for trunk?

Same ChangeLog as before.

Thanks,

Matt

On 20/06/12 11:18, Matthew Gretton-Dann wrote:
> PING.
>
> On Mon, May 28, 2012 at 10:51:27AM +0100, Matthew Gretton-Dann wrote:
>> All,
>>
>> This patch adds a variety of predefined macros to reveal the presence of
>> various features of the ARM architecture.  These are detailed in the ARM
>> C Language Extensions specification, available here:
>> http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053-/index.html
>>
>> This patch then adds compiler predefines for:
>>
>> __ARM_SIZEOF_MINIMAL_ENUM which is defined as the size in bytes
>> of the smallest enum.
>>
>> __ARM_ARCH which is defined as the major revision of the ARM
>> instruction set which the target implements.
>>
>> __ARM_ARCH_ISA_THUMB which is defined as the major revision of
>> the thumb instruction set which the target implements.
>>
>> __ARM_ARCH_PROFILE which is defined on ARMv7 targets, and ARMv6-M
>> targets to be the character value of `A', `R' or `M', as defined
>> by the target's architecture profile.
>>
>> __ARM_FEATURE_LDREX which is defined as a bit mask, composed of
>> the widths of `ldrex' available on the target. These widths are:
>> bit 0 - byte.
>> bit 1 - 16-bit halfword.
>> bit 2 - 32-bit word.
>> bit 3 - 64-bit doubleword.
>>
>> __ARM_FEATURE_CLZ which is defined for targets which support
>> the `clz' instruction.
>>
>> __ARM_FEATURE_SIMD32 which is defined when the ARMv6 integer
>> SIMD instructions are available.
>>
>> __ARM_FEATURE_QBIT which is defined when the Q-Bit is present in the
>> APSR.
>>
>> __ARM_FEATURE_SAT which is defined when the saturation instructions are
>> available.
>>
>> __ARM_FP which is defined as a bit mask composed of the widths
>> of floating-point types with hardware support on the target.
>> These widths are:
>> bit 1 - 16-bit half precision.
>> bit 2 - 32-bit single precision.
>> bit 3 - 64-bit double precision.
>>
>> __ARM_FP16_FORMAT_IEEE which is defined when the IEEE 754-2008
>> standard for 16-bit floating point representation is used.
>>
>> __ARM_FP16_FORMAT_ALTERNATIVE which is defined when the ARM
>> alternative standard for 16-bit floating point representation
>> is used.
>>
>> __ARM_FEATURE_FMA which is defined when the fused multiply-accumulate
>> instructions are available for floating-point and/or Advanced SIMD
>> values.
>>
>> __ARM_NEON_FP which is defined as a bit mask composed of the widths
>> of floating point values supported by the NEON hardware. These widths
>> are, as with __ARM_FP:
>> bit 1 - 16-bit half precision.
>> bit 2 - 32-bit single precision.
>> bit 3 - 64-bit double precision.
>>
>> __ARM_WMMX which is defined where iwmmx operations are available
>> on the target.
>>
>> As these macros may expand to something other than `1', we also update
>> cpp.texi to reflect this fact.
>>
>> OK?
>>
>> Thanks,
>>
>> Matt
>>
>> gcc/ChangeLog:
>> 2012-05-28  Matthew Gretton-Dann  <matthew.gretton-dann@arm.com>
>>               James Greenhalgh  <james.greenhalgh@arm.com>
>>
>>        * config/arm/arm.h (TARGET_CPU_CPP_BUILTINS): Add new built-ins.
>>        (TARGET_FMA): New macro.
>>        (TARGET_ARM_QBIT, TARGET_ARM_SAT): Likewise.
>>        (TARGET_ARM_ARCH): Likewise.
>>        (TARGET_ARM_ARCH_ISA_THUMB): Likewise.
>>        (TARGET_V6M, TARGET_V7M): Likewise.
>>        (TARGET_ARM_ARCH_PROFILE): Likewise.
>>        (TARGET_ARM_FEATURE_LDREX): Likewise.
>>        (TARGET_ARM_FP, TARGET_NEON_FP): Likewise.
>>        (ARM_MIN_ENUM_SIZE): Likewise.
>>        * config/arm/arm.c (arm_file_start): Refactor appropriately.
>>        (base_architecture): New enumeration.
>>        (arm_base_arch): New global variable.
>>        (processors): Add field base_arch.
>>        (ARM_ARCH, ARM_CORE): Adjust accordingly.
>>        (arm_option_override): Add initialization of arm_base_arch.
>>        * doc/cpp.texi (system-specific predefined macros.): Change.
>>
>> gcc/testsuite/ChangeLog:
>> 2012-05-28  Matthew Gretton-Dann  <matthew.gretton-dann@arm.com>
>>               James Greenhalgh  <james.greenhalgh@arm.com>
>>
>>        * gcc.target/arm/ftest-support-arm.h New testcase.
>>        * gcc.target/arm/ftest-support-thumb.h Likewise.
>>        * gcc.target/arm/ftest-support.h Likewise.
>>        * gcc.target/arm/ftest-armv4-arm.c: Likewise.
>>        * gcc.target/arm/ftest-armv4t-arm.c: Likewise.
>>        * gcc.target/arm/ftest-armv4t-thumb.c: Likewise.
>>        * gcc.target/arm/ftest-armv5t-arm.c Likewise.
>>        * gcc.target/arm/ftest-armv5t-thumb.c Likewise.
>>        * gcc.target/arm/ftest-armv5te-arm.c: Likewise.
>>        * gcc.target/arm/ftest-armv5te-thumb.c: Likewise.
>>        * gcc.target/arm/ftest-armv6-arm.c Likewise.
>>        * gcc.target/arm/ftest-armv6-thumb.c Likewise.
>>        * gcc.target/arm/ftest-armv6k-arm.c Likewise.
>>        * gcc.target/arm/ftest-armv6k-thumb.c Likewise.
>>        * gcc.target/arm/ftest-armv6m-thumb.c: Likewise.
>>        * gcc.target/arm/ftest-armv6t2-arm.c: Likewise.
>>        * gcc.target/arm/ftest-armv6t2-thumb.c: Likewise.
>>        * gcc.target/arm/ftest-armv6z-arm.c: Likewise.
>>        * gcc.target/arm/ftest-armv6z-thumb.c: Likewise.
>>        * gcc.target/arm/ftest-armv7a-arm.c Likewise.
>>        * gcc.target/arm/ftest-armv7a-thumb.c Likewise.
>>        * gcc.target/arm/ftest-armv7m-thumb.c: Likewise.
>>        * gcc.target/arm/ftest-armv7em-thumb.c: Likewise.
>>        * gcc.target/arm/ftest-armv7r-arm.c Likewise.
>>        * gcc.target/arm/ftest-armv7r-thumb.c Likewise.
>>        * gcc/testsuite/lib/target-supports.exp
>>        (check_effective_target_arm_arch_FUNC): Add support for more
>>        architectures.
>>           (add_options_for_arm_arch_FUNC): Likewise.
>>        (check_effective_target_arm_arch_FUNC_multilib): New functions.

Comments

Richard Earnshaw June 25, 2012, 4:10 p.m. UTC | #1
On 25/06/12 15:39, Matthew Gretton-Dann wrote:
> Further testing has found a couple of failures to build with a C++ compiler, 
> and trunk has moved on a bit so the patch doesn't apply cleanly.
> 
> An updated patch is attached.
> 
> OK for trunk?
> 
> Same ChangeLog as before.
> 

OK.

R.
diff mbox

Patch

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index b7ae20f..cba98f9 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -717,6 +717,10 @@  static unsigned long insn_flags = 0;
    be used.  */
 static unsigned long tune_flags = 0;
 
+/* The highest ARM architecture version supported by the
+   target.  */
+enum base_architecture arm_base_arch = BASE_ARCH_0;
+
 /* The following are used in the arm.md file as equivalents to bits
    in the above two flag variables.  */
 
@@ -854,6 +858,7 @@  struct processors
   const char *const name;
   enum processor_type core;
   const char *arch;
+  enum base_architecture base_arch;
   const unsigned long flags;
   const struct tune_params *const tune;
 };
@@ -989,10 +994,11 @@  static const struct processors all_cores[] =
 {
   /* ARM Cores */
 #define ARM_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \
-  {NAME, IDENT, #ARCH, FLAGS | FL_FOR_ARCH##ARCH, &arm_##COSTS##_tune},
+  {NAME, IDENT, #ARCH, BASE_ARCH_##ARCH,	  \
+    FLAGS | FL_FOR_ARCH##ARCH, &arm_##COSTS##_tune},
 #include "arm-cores.def"
 #undef ARM_CORE
-  {NULL, arm_none, NULL, 0, NULL}
+  {NULL, arm_none, NULL, BASE_ARCH_0, 0, NULL}
 };
 
 static const struct processors all_architectures[] =
@@ -1002,10 +1008,10 @@  static const struct processors all_architectures[] =
      from the core.  */
 
 #define ARM_ARCH(NAME, CORE, ARCH, FLAGS) \
-  {NAME, CORE, #ARCH, FLAGS, NULL},
+  {NAME, CORE, #ARCH, BASE_ARCH_##ARCH, FLAGS, NULL},
 #include "arm-arches.def"
 #undef ARM_ARCH
-  {NULL, arm_none, NULL, 0 , NULL}
+  {NULL, arm_none, NULL, BASE_ARCH_0, 0, NULL}
 };
 
 
@@ -1621,6 +1627,7 @@  arm_option_override (void)
 
   sprintf (arm_arch_name, "__ARM_ARCH_%s__", arm_selected_cpu->arch);
   insn_flags = arm_selected_cpu->flags;
+  arm_base_arch = arm_selected_cpu->base_arch;
 
   arm_tune = arm_selected_tune->core;
   tune_flags = arm_selected_tune->flags;
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 27f0f3e..b83f341 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -47,20 +47,52 @@  extern char arm_arch_name[];
     {							\
 	if (TARGET_DSP_MULTIPLY)			\
 	   builtin_define ("__ARM_FEATURE_DSP");	\
+        if (TARGET_ARM_QBIT)				\
+           builtin_define ("__ARM_FEATURE_QBIT");	\
+        if (TARGET_ARM_SAT)				\
+           builtin_define ("__ARM_FEATURE_SAT");	\
 	if (unaligned_access)				\
 	  builtin_define ("__ARM_FEATURE_UNALIGNED");	\
+	if (TARGET_ARM_FEATURE_LDREX)				\
+	  builtin_define_with_int_value (			\
+	    "__ARM_FEATURE_LDREX", TARGET_ARM_FEATURE_LDREX);	\
+	if ((TARGET_ARM_ARCH >= 5 && !TARGET_THUMB)		\
+	     || TARGET_ARM_ARCH_ISA_THUMB >=2)			\
+	  builtin_define ("__ARM_FEATURE_CLZ");			\
+	if (TARGET_INT_SIMD)					\
+	  builtin_define ("__ARM_FEATURE_SIMD32");		\
+								\
+	builtin_define_with_int_value (				\
+	  "__ARM_SIZEOF_MINIMAL_ENUM",				\
+	  flag_short_enums ? 1 : 4);				\
+	builtin_define_with_int_value (				\
+	  "__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE);		\
+	if (TARGET_ARM_ARCH_PROFILE)				\
+	  builtin_define_with_int_value (			\
+	    "__ARM_ARCH_PROFILE", TARGET_ARM_ARCH_PROFILE);	\
+								\
 	/* Define __arm__ even when in thumb mode, for	\
 	   consistency with armcc.  */			\
 	builtin_define ("__arm__");			\
+	if (TARGET_ARM_ARCH)				\
+	  builtin_define_with_int_value (		\
+	    "__ARM_ARCH", TARGET_ARM_ARCH);		\
+	if (arm_arch_notm)				\
+	  builtin_define ("__ARM_ARCH_ISA_ARM");	\
 	builtin_define ("__APCS_32__");			\
 	if (TARGET_THUMB)				\
 	  builtin_define ("__thumb__");			\
 	if (TARGET_THUMB2)				\
 	  builtin_define ("__thumb2__");		\
+	if (TARGET_ARM_ARCH_ISA_THUMB)			\
+	  builtin_define_with_int_value (		\
+	    "__ARM_ARCH_ISA_THUMB",			\
+	    TARGET_ARM_ARCH_ISA_THUMB);			\
 							\
 	if (TARGET_BIG_END)				\
 	  {						\
 	    builtin_define ("__ARMEB__");		\
+	    builtin_define ("__ARM_BIG_ENDIAN");	\
 	    if (TARGET_THUMB)				\
 	      builtin_define ("__THUMBEB__");		\
 	    if (TARGET_LITTLE_WORDS)			\
@@ -79,8 +111,24 @@  extern char arm_arch_name[];
 	if (TARGET_VFP)					\
 	  builtin_define ("__VFP_FP__");		\
 							\
+	if (TARGET_ARM_FP)				\
+	  builtin_define_with_int_value (		\
+	    "__ARM_FP", TARGET_ARM_FP);			\
+	if (arm_fp16_format == ARM_FP16_FORMAT_IEEE)		\
+	  builtin_define ("__ARM_FP16_FORMAT_IEEE");		\
+	if (arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE)	\
+	  builtin_define ("__ARM_FP16_FORMAT_ALTERNATIVE");	\
+        if (TARGET_FMA)					\
+          builtin_define ("__ARM_FEATURE_FMA");		\
+							\
 	if (TARGET_NEON)				\
-	  builtin_define ("__ARM_NEON__");		\
+	  {						\
+	    builtin_define ("__ARM_NEON__");		\
+	    builtin_define ("__ARM_NEON");		\
+	  }						\
+	if (TARGET_NEON_FP)				\
+	  builtin_define_with_int_value (		\
+	    "__ARM_NEON_FP", TARGET_NEON_FP);		\
 							\
 	/* Add a define for interworking.		\
 	   Needed when building libgcc.a.  */		\
@@ -96,7 +144,10 @@  extern char arm_arch_name[];
 	if (arm_arch_xscale)				\
 	  builtin_define ("__XSCALE__");		\
 	if (arm_arch_iwmmxt)				\
-	  builtin_define ("__IWMMXT__");		\
+          {						\
+	    builtin_define ("__IWMMXT__");		\
+	    builtin_define ("__ARM_WMMX");		\
+	  }						\
 	if (arm_arch_iwmmxt2)				\
 	  builtin_define ("__IWMMXT2__");		\
 	if (TARGET_AAPCS_BASED)				\
@@ -248,6 +299,9 @@  extern void (*arm_lang_output_object_attributes_hook)(void);
 /* FPU supports VFP half-precision floating-point.  */
 #define TARGET_FP16 (TARGET_VFP && arm_fpu_desc->fp16)
 
+/* FPU supports fused-multiply-add operations.  */
+#define TARGET_FMA (TARGET_VFP && arm_fpu_desc->rev >= 4)
+
 /* FPU supports Neon instructions.  The setting of this macro gets
    revealed via __ARM_NEON__ so we add extra guards upon TARGET_32BIT
    and TARGET_HARD_FLOAT to ensure that NEON instructions are
@@ -255,6 +309,12 @@  extern void (*arm_lang_output_object_attributes_hook)(void);
 #define TARGET_NEON (TARGET_32BIT && TARGET_HARD_FLOAT \
 		     && TARGET_VFP && arm_fpu_desc->neon)
 
+/* Q-bit is present.  */
+#define TARGET_ARM_QBIT \
+  (TARGET_32BIT && arm_arch5e && (arm_arch_notm || arm_arch7))
+/* Saturation operation, e.g. SSAT.  */
+#define TARGET_ARM_SAT \
+  (TARGET_32BIT && arm_arch6 && (arm_arch_notm || arm_arch7))
 /* "DSP" multiply instructions, eg. SMULxy.  */
 #define TARGET_DSP_MULTIPLY \
   (TARGET_32BIT && arm_arch5e && (arm_arch_notm || arm_arch7em))
@@ -366,6 +426,39 @@  extern int arm_fpu_attr;
 #define ARM_DEFAULT_ABI ARM_ABI_APCS
 #endif
 
+/* Map each of the micro-architecture variants to their corresponding
+   major architecture revision.  */
+
+enum base_architecture
+{
+  BASE_ARCH_0 = 0,
+  BASE_ARCH_2 = 2,
+  BASE_ARCH_3 = 3,
+  BASE_ARCH_3M = 3,
+  BASE_ARCH_4 = 4,
+  BASE_ARCH_4T = 4,
+  BASE_ARCH_5 = 5,
+  BASE_ARCH_5E = 5,
+  BASE_ARCH_5T = 5,
+  BASE_ARCH_5TE = 5,
+  BASE_ARCH_5TEJ = 5,
+  BASE_ARCH_6 = 6,
+  BASE_ARCH_6J = 6,
+  BASE_ARCH_6ZK = 6,
+  BASE_ARCH_6K = 6,
+  BASE_ARCH_6T2 = 6,
+  BASE_ARCH_6M = 6,
+  BASE_ARCH_6Z = 6,
+  BASE_ARCH_7 = 7,
+  BASE_ARCH_7A = 7,
+  BASE_ARCH_7R = 7,
+  BASE_ARCH_7M = 7,
+  BASE_ARCH_7EM = 7
+};
+
+/* The major revision number of the ARM Architecture implemented by the target.  */
+extern enum base_architecture arm_base_arch;
+
 /* Nonzero if this chip supports the ARM Architecture 3M extensions.  */
 extern int arm_arch3m;
 
@@ -2183,6 +2276,51 @@  extern int making_const_table;
 #define NEED_INDICATE_EXEC_STACK	0
 #endif
 
+#define TARGET_ARM_ARCH	\
+  (arm_base_arch)	\
+
+#define TARGET_ARM_V6M (!arm_arch_notm && !arm_arch_thumb2)
+#define TARGET_ARM_V7M (!arm_arch_notm && arm_arch_thumb2)
+
+/* The highest Thumb instruction set version supported by the chip.  */
+#define TARGET_ARM_ARCH_ISA_THUMB 		\
+  (arm_arch_thumb2 ? 2				\
+	           : ((TARGET_ARM_ARCH >= 5 || arm_arch4t) ? 1 : 0))
+
+/* Expands to an upper-case char of the target's architectural
+   profile.  */
+#define TARGET_ARM_ARCH_PROFILE				\
+  (!arm_arch_notm					\
+    ? 'M'						\
+    : (arm_arch7					\
+      ? (strlen (arm_arch_name) >=3			\
+	? (arm_arch_name[strlen (arm_arch_name) - 3])	\
+      	: 0)						\
+      : 0))
+
+/* Bit-field indicating what size LDREX/STREX loads/stores are available.
+   Bit 0 for bytes, up to bit 3 for double-words.  */
+#define TARGET_ARM_FEATURE_LDREX				\
+  ((TARGET_HAVE_LDREX ? 4 : 0)					\
+   | (TARGET_HAVE_LDREXBH ? 3 : 0)				\
+   | (TARGET_HAVE_LDREXD ? 8 : 0))
+
+/* Set as a bit mask indicating the available widths of hardware floating
+   point types.  Where bit 1 indicates 16-bit support, bit 2 indicates
+   32-bit support, bit 3 indicates 64-bit support.  */
+#define TARGET_ARM_FP			\
+  (TARGET_VFP_SINGLE ? 4		\
+  		     : (TARGET_VFP_DOUBLE ? (TARGET_FP16 ? 14 : 12) : 0))
+
+
+/* Set as a bit mask indicating the available widths of floating point
+   types for hardware NEON floating point.  This is the same as
+   TARGET_ARM_FP without the 64-bit bit set.  */
+#ifdef TARGET_NEON
+#define TARGET_NEON_FP		\
+  (TARGET_ARM_FP & (0xff ^ 0x08))
+#endif
+
 /* The maximum number of parallel loads or stores we support in an ldm/stm
    instruction.  */
 #define MAX_LDM_STM_OPS 4
diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi
index 658ab98..508f447 100644
--- a/gcc/doc/cpp.texi
+++ b/gcc/doc/cpp.texi
@@ -2397,7 +2397,7 @@  type of system and machine is in use.  They are obviously different on
 each target supported by GCC@.  This manual, being for all systems and
 machines, cannot tell you what their names are, but you can use
 @command{cpp -dM} to see them all.  @xref{Invocation}.  All system-specific
-predefined macros expand to the constant 1, so you can test them with
+predefined macros expand to a constant value, so you can test them with
 either @samp{#ifdef} or @samp{#if}.
 
 The C standard requires that all system-specific macros be part of the
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv4-arm.c b/gcc/testsuite/gcc.target/arm/ftest-armv4-arm.c
new file mode 100644
index 0000000..acaf72e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv4-arm.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_nothumb } */
+/* { dg-require-effective-target arm_arch_v4_multilib } */
+/* { dg-options "-marm" } */
+/* { dg-add-options arm_arch_v4 } */
+
+#include "ftest-support-arm.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V4);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv4t-arm.c b/gcc/testsuite/gcc.target/arm/ftest-armv4t-arm.c
new file mode 100644
index 0000000..7af6167
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv4t-arm.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_nothumb } */
+/* { dg-require-effective-target arm_arch_v4t_multilib } */
+/* { dg-options "-marm" } */
+/* { dg-add-options arm_arch_v4t } */
+
+#include "ftest-support-arm.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V4T);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv4t-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv4t-thumb.c
new file mode 100644
index 0000000..1e6a2da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv4t-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v4t_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v4t } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V4T);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv5t-arm.c b/gcc/testsuite/gcc.target/arm/ftest-armv5t-arm.c
new file mode 100644
index 0000000..cc7fc71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv5t-arm.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_nothumb } */
+/* { dg-require-effective-target arm_arch_v5t_multilib } */
+/* { dg-options "-marm" } */
+/* { dg-add-options arm_arch_v5t } */
+
+#include "ftest-support-arm.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V5T);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv5t-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv5t-thumb.c
new file mode 100644
index 0000000..b2b4727
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv5t-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v5t_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v5t } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V5T);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv5te-arm.c b/gcc/testsuite/gcc.target/arm/ftest-armv5te-arm.c
new file mode 100644
index 0000000..7595e19
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv5te-arm.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_nothumb } */
+/* { dg-require-effective-target arm_arch_v5te_multilib } */
+/* { dg-options "-marm" } */
+/* { dg-add-options arm_arch_v5te } */
+
+#include "ftest-support-arm.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V5TE);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv5te-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv5te-thumb.c
new file mode 100644
index 0000000..a18ea52
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv5te-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v5te_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v5te } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V5TE);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv6-arm.c b/gcc/testsuite/gcc.target/arm/ftest-armv6-arm.c
new file mode 100644
index 0000000..465d187
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv6-arm.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_nothumb } */
+/* { dg-require-effective-target arm_arch_v6_multilib } */
+/* { dg-options "-marm" } */
+/* { dg-add-options arm_arch_v6 } */
+
+#include "ftest-support-arm.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V6);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv6-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv6-thumb.c
new file mode 100644
index 0000000..0445587
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv6-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v6_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v6 } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V6);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv6k-arm.c b/gcc/testsuite/gcc.target/arm/ftest-armv6k-arm.c
new file mode 100644
index 0000000..c059b77
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv6k-arm.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_nothumb } */
+/* { dg-require-effective-target arm_arch_v6k_multilib } */
+/* { dg-options "-marm" } */
+/* { dg-add-options arm_arch_v6k } */
+
+#include "ftest-support-arm.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V6K);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv6k-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv6k-thumb.c
new file mode 100644
index 0000000..8f19587
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv6k-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v6k_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v6k } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V6K);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv6m-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv6m-thumb.c
new file mode 100644
index 0000000..1042761
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv6m-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v6m_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v6m } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V6M);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv6t2-arm.c b/gcc/testsuite/gcc.target/arm/ftest-armv6t2-arm.c
new file mode 100644
index 0000000..5f7f874
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv6t2-arm.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_nothumb } */
+/* { dg-require-effective-target arm_arch_v6t2_multilib } */
+/* { dg-options "-marm" } */
+/* { dg-add-options arm_arch_v6t2 } */
+
+#include "ftest-support-arm.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V6T2);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv6t2-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv6t2-thumb.c
new file mode 100644
index 0000000..e3695c4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv6t2-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v6t2_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v6t2 } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V6T2);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv6z-arm.c b/gcc/testsuite/gcc.target/arm/ftest-armv6z-arm.c
new file mode 100644
index 0000000..0797890
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv6z-arm.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_nothumb } */
+/* { dg-require-effective-target arm_arch_v6z_multilib } */
+/* { dg-options "-marm" } */
+/* { dg-add-options arm_arch_v6z } */
+
+#include "ftest-support-arm.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V6Z);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv6z-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv6z-thumb.c
new file mode 100644
index 0000000..c5a2e49
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv6z-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v6z_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v6z } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V6Z);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv7a-arm.c b/gcc/testsuite/gcc.target/arm/ftest-armv7a-arm.c
new file mode 100644
index 0000000..e84559a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv7a-arm.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_nothumb } */
+/* { dg-require-effective-target arm_arch_v7a_multilib } */
+/* { dg-options "-marm" } */
+/* { dg-add-options arm_arch_v7a } */
+
+#include "ftest-support-arm.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V7A);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv7a-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv7a-thumb.c
new file mode 100644
index 0000000..ad9b4e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv7a-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v7a_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v7a } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V7A);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv7em-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv7em-thumb.c
new file mode 100644
index 0000000..7ef9210
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv7em-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v7em_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v7em } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V7EM);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv7m-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv7m-thumb.c
new file mode 100644
index 0000000..8bf875e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv7m-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v7m_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v7m } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V7M);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv7r-arm.c b/gcc/testsuite/gcc.target/arm/ftest-armv7r-arm.c
new file mode 100644
index 0000000..4422564
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv7r-arm.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_nothumb } */
+/* { dg-require-effective-target arm_arch_v7r_multilib } */
+/* { dg-options "-marm" } */
+/* { dg-add-options arm_arch_v7r } */
+
+#include "ftest-support-arm.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V7R);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-armv7r-thumb.c b/gcc/testsuite/gcc.target/arm/ftest-armv7r-thumb.c
new file mode 100644
index 0000000..da866e4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-armv7r-thumb.c
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-require-effective-target arm_arch_v7r_multilib } */
+/* { dg-options "-mthumb" } */
+/* { dg-add-options arm_arch_v7r } */
+
+#include "ftest-support-thumb.h"
+
+int
+main (void)
+{
+  return ftest (ARCH_V7R);
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/ftest-support-arm.h b/gcc/testsuite/gcc.target/arm/ftest-support-arm.h
new file mode 100644
index 0000000..512d50e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-support-arm.h
@@ -0,0 +1,29 @@ 
+#include "ftest-support.h"
+
+  /*Feature matrix layout:
+    __ARM_ARCH
+    __ARM_ARCH_ISA_ARM
+    __ARM_ARCH_ISA_THUMB
+    __ARM_ARCH_PROFILE
+    __ARM_FEATURE_UNALIGNED
+    __ARM_FEATURE_LDREX
+    __ARM_FEATURE_CLZ
+    __ARM_FEATURE_DSP
+    __ARM_FEATURE_SIMD32
+    __ARM_FEATURE_QBIT
+    __ARM_FEATURE_SAT
+  */
+int feature_matrix[ARCH_COUNT][NUM_FEATURES] =
+  {{4, 1, 0, 0,   0, 0,  0, 0, 0, 0, 0},  /* ARCH_V4.  */
+   {4, 1, 1, 0,   0, 0,  0, 0, 0, 0, 0},  /* ARCH_V4T.  */
+   {5, 1, 1, 0,   0, 0,  1, 0, 0, 0, 0},  /* ARCH_V5T.  */
+   {5, 1, 1, 0,   0, 0,  1, 1, 0, 1, 0},  /* ARCH_V5TE.  */
+   {6, 1, 1, 0,   1, 4,  1, 1, 1, 1, 1},  /* ARCH_V6.  */
+   {6, 1, 1, 0,   1, 15, 1, 1, 1, 1, 1},  /* ARCH_V6K.  */
+   {6, 1, 2, 0,   1, 4,  1, 1, 1, 1, 1},  /* ARCH_V6T2.  */
+   {6, 1, 1, 0,   1, 4,  1, 1, 1, 1, 1},  /* ARCH_V6Z.  */
+   {6, 0, 1, 'M', 0, 0,  1, 0, 0, 0, 0},  /* ARCH_V6M.  */
+   {7, 1, 2, 'A', 1, 15, 1, 1, 1, 1, 1},  /* ARCH_V7A.  */
+   {7, 1, 2, 'R', 1, 15, 1, 1, 1, 1, 1},  /* ARCH_V7R.  */
+   {7, 0, 2, 'M', 1, 7,  1, 0, 0, 1, 1},  /* ARCH_V7M.  */
+   {7, 0, 2, 'M', 1, 7,  1, 1, 0, 1, 1}}; /* ARCH_V7EM.  */
diff --git a/gcc/testsuite/gcc.target/arm/ftest-support-thumb.h b/gcc/testsuite/gcc.target/arm/ftest-support-thumb.h
new file mode 100644
index 0000000..9991831
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-support-thumb.h
@@ -0,0 +1,29 @@ 
+#include "ftest-support.h"
+
+  /*Feature matrix layout:
+    __ARM_ARCH
+    __ARM_ARCH_ISA_ARM
+    __ARM_ARCH_ISA_THUMB
+    __ARM_ARCH_PROFILE
+    __ARM_FEATURE_UNALIGNED
+    __ARM_FEATURE_LDREX
+    __ARM_FEATURE_CLZ
+    __ARM_FEATURE_DSP
+    __ARM_FEATURE_SIMD32
+    __ARM_FEATURE_QBIT
+    __ARM_FEATURE_SAT
+  */
+int feature_matrix[ARCH_COUNT][NUM_FEATURES] =
+  {{4, 1, 0, 0,   0, 0,  0, 0, 0, 0, 0},  /* ARCH_V4.  */
+   {4, 1, 1, 0,   0, 0,  0, 0, 0, 0, 0},  /* ARCH_V4T.  */
+   {5, 1, 1, 0,   0, 0,  0, 0, 0, 0, 0},  /* ARCH_V5T.  */
+   {5, 1, 1, 0,   0, 0,  0, 0, 0, 0, 0},  /* ARCH_V5TE.  */
+   {6, 1, 1, 0,   1, 0,  0, 0, 0, 0, 0},  /* ARCH_V6.  */
+   {6, 1, 1, 0,   1, 0,  0, 0, 0, 0, 0},  /* ARCH_V6K.  */
+   {6, 1, 2, 0,   1, 0,  1, 1, 1, 1, 1},  /* ARCH_V6T2.  */
+   {6, 1, 1, 0,   1, 0,  0, 0, 0, 0, 0},  /* ARCH_V6Z.  */
+   {6, 0, 1, 'M', 0, 0,  0, 0, 0, 0, 0},  /* ARCH_V6M.  */
+   {7, 1, 2, 'A', 1, 15, 1, 1, 1, 1, 1},  /* ARCH_V7A.  */
+   {7, 1, 2, 'R', 1, 15, 1, 1, 1, 1, 1},  /* ARCH_V7R.  */
+   {7, 0, 2, 'M', 1, 7,  1, 0, 0, 1, 1},  /* ARCH_V7M.  */
+   {7, 0, 2, 'M', 1, 7,  1, 1, 1, 1, 1}}; /* ARCH_V7EM.  */
diff --git a/gcc/testsuite/gcc.target/arm/ftest-support.h b/gcc/testsuite/gcc.target/arm/ftest-support.h
new file mode 100644
index 0000000..c5f9810
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ftest-support.h
@@ -0,0 +1,83 @@ 
+#if 0
+#define INTERNAL_DEBUG 1
+#endif
+
+#ifdef INTERNAL_DEBUG
+#include <stdio.h>
+#endif
+
+extern void abort (void);
+
+enum architecture {
+  ARCH_V4 = 0,
+  ARCH_V4T,
+  ARCH_V5T,
+  ARCH_V5TE,
+  ARCH_V6,
+  ARCH_V6K,
+  ARCH_V6T2,
+  ARCH_V6Z,
+  ARCH_V6M,
+  ARCH_V7A,
+  ARCH_V7R,
+  ARCH_V7M,
+  ARCH_V7EM,
+  ARCH_COUNT
+};
+
+#define NUM_FEATURES 11
+int feature_matrix[ARCH_COUNT][NUM_FEATURES];
+
+int
+ftest (int arch)
+{
+  int features[NUM_FEATURES] = {0};
+  int y;
+
+  for (y = 0; y < NUM_FEATURES; ++y)
+    features[y] = 0;
+
+#ifdef __ARM_ARCH
+  features[0] = __ARM_ARCH;
+#endif
+#ifdef __ARM_ARCH_ISA_ARM
+  features[1] = __ARM_ARCH_ISA_ARM;
+#endif
+#ifdef __ARM_ARCH_ISA_THUMB
+  features[2] = __ARM_ARCH_ISA_THUMB;
+#endif
+#ifdef __ARM_ARCH_PROFILE
+  features[3] = __ARM_ARCH_PROFILE;
+#endif
+#ifdef __ARM_FEATURE_UNALIGNED
+  features[4] = __ARM_FEATURE_UNALIGNED;
+#endif
+#ifdef __ARM_FEATURE_LDREX
+  features[5] = __ARM_FEATURE_LDREX;
+#endif
+#ifdef __ARM_FEATURE_CLZ
+  features[6] = __ARM_FEATURE_CLZ;
+#endif
+#ifdef __ARM_FEATURE_DSP
+  features[7] = __ARM_FEATURE_DSP;
+#endif
+#ifdef __ARM_FEATURE_SIMD32
+  features[8] = __ARM_FEATURE_SIMD32;
+#endif
+#ifdef __ARM_FEATURE_QBIT
+  features[9] = __ARM_FEATURE_QBIT;
+#endif
+#ifdef __ARM_FEATURE_SAT
+  features[10] = __ARM_FEATURE_SAT;
+#endif
+  for (y = 0; y < NUM_FEATURES; ++y)
+    if (feature_matrix[arch][y] != features[y])
+      {
+#ifdef INTERNAL_DEBUG
+	printf ("%d, %d, %d, %d\n", arch, y, feature_matrix[arch][y], features[y]);
+#endif
+        abort ();
+      }
+  return 0;
+}
+
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index c937484..bc5baa7 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2169,10 +2169,21 @@  proc check_effective_target_arm_fp16_ok { } {
 # (Thumb in particular - but others may be added in the future)
 # Usage: /* { dg-require-effective-target arm_arch_v5_ok } */
 #        /* { dg-add-options arm_arch_v5 } */
-foreach { armfunc armflag armdef } { v5 "-march=armv5 -marm" __ARM_ARCH_5__
+#	 /* { dg-require-effective-target arm_arch_v5_multilib } */
+foreach { armfunc armflag armdef } { v4 "-march=armv4 -marm" __ARM_ARCH_4__
+				     v4t "-march=armv4t" __ARM_ARCH_4T__
+				     v5 "-march=armv5 -marm" __ARM_ARCH_5__
+				     v5t "-march=armv5t" __ARM_ARCH_5T__
+				     v5te "-march=armv5te" __ARM_ARCH_5TE__
 				     v6 "-march=armv6" __ARM_ARCH_6__
 				     v6k "-march=armv6k" __ARM_ARCH_6K__
-				     v7a "-march=armv7-a" __ARM_ARCH_7A__ } {
+				     v6t2 "-march=armv6t2" __ARM_ARCH_6T2__
+				     v6z "-march=armv6z" __ARM_ARCH_6Z__
+				     v6m "-march=armv6-m -mthumb" __ARM_ARCH_6M__
+				     v7a "-march=armv7-a" __ARM_ARCH_7A__
+				     v7r "-march=armv7-r" __ARM_ARCH_7R__
+				     v7m "-march=armv7-m -mthumb" __ARM_ARCH_7M__
+				     v7em "-march=armv7e-m -mthumb" __ARM_ARCH_7EM__ } {
     eval [string map [list FUNC $armfunc FLAG $armflag DEF $armdef ] {
 	proc check_effective_target_arm_arch_FUNC_ok { } {
 	    if { [ string match "*-marm*" "FLAG" ] &&
@@ -2189,6 +2200,16 @@  foreach { armfunc armflag armdef } { v5 "-march=armv5 -marm" __ARM_ARCH_5__
 	proc add_options_for_arm_arch_FUNC { flags } {
 	    return "$flags FLAG"
 	}
+
+	proc check_effective_target_arm_arch_FUNC_multilib { } {
+	    return [check_runtime arm_arch_FUNC_multilib {
+		int
+		main (void)
+		{
+		    return 0;
+		}
+	    } [add_options_for_arm_arch_FUNC ""]]
+        }
     }]
 }