summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog19
-rw-r--r--gas/config/tc-arm.c275
-rw-r--r--gas/testsuite/gas/arm/attr-march-armv1.d1
-rw-r--r--gas/testsuite/gas/arm/attr-march-armv2.d1
-rw-r--r--gas/testsuite/gas/arm/attr-march-armv2a.d1
-rw-r--r--gas/testsuite/gas/arm/attr-march-armv2s.d1
-rw-r--r--gas/testsuite/gas/arm/attr-march-armv3.d1
-rw-r--r--gas/testsuite/gas/arm/attr-march-armv3m.d1
-rw-r--r--include/ChangeLog4
-rw-r--r--include/opcode/arm.h1
10 files changed, 236 insertions, 69 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 16f0c4b1a24..87eea613b36 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,22 @@
+2017-06-21 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * config/tc-arm.c (fpu_any): Defined from FPU_ANY.
+ (cpu_arch_ver): Add all architectures and sort by release date.
+ (have_ext_for_needed_feat_p): New.
+ (get_aeabi_cpu_arch_from_fset): New.
+ (aeabi_set_public_attributes): Call above function to determine
+ Tag_CPU_arch and Tag_CPU_arch_profile values. Adapt Tag_ARM_ISA_use
+ and Tag_THUMB_ISA_use selection logic to check absence of feature bit
+ accordingly.
+ * testsuite/gas/arm/attr-march-armv1.d: Fix expected Tag_CPU_arch build
+ attribute value.
+ * testsuite/gas/arm/attr-march-armv2.d: Likewise.
+ * testsuite/gas/arm/attr-march-armv2a.d: Likewise.
+ * testsuite/gas/arm/attr-march-armv2s.d: Likewise.
+ * testsuite/gas/arm/attr-march-armv3.d: Likewise.
+ * testsuite/gas/arm/attr-march-armv3m.d: Likewise.
+ * testsuite/gas/arm/pr12198-2.d: Likewise.
+
2017-06-21 H.J. Lu <hongjiu.lu@intel.com>
* testsuite/gas/i386/cet-intel.d: Updated.
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index a62c5f29d98..7767aa6dddc 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -240,6 +240,7 @@ static const arm_feature_set arm_ext_v8_3 =
ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_3A);
static const arm_feature_set arm_arch_any = ARM_ANY;
+static const arm_feature_set fpu_any = FPU_ANY;
static const arm_feature_set arm_arch_full ATTRIBUTE_UNUSED = ARM_FEATURE (-1, -1, -1);
static const arm_feature_set arm_arch_t2 = ARM_ARCH_THUMB2;
static const arm_feature_set arm_arch_none = ARM_ARCH_NONE;
@@ -26558,30 +26559,61 @@ typedef struct
arm_feature_set flags;
} cpu_arch_ver_table;
-/* Mapping from CPU features to EABI CPU arch values. As a general rule, table
- must be sorted least features first but some reordering is needed, eg. for
- Thumb-2 instructions to be detected as coming from ARMv6T2. */
+/* Mapping from CPU features to EABI CPU arch values. Table must be sorted
+ chronologically for architectures, with an exception for ARMv6-M and
+ ARMv6S-M due to legacy reasons. No new architecture should have a
+ special case. This allows for build attribute selection results to be
+ stable when new architectures are added. */
static const cpu_arch_ver_table cpu_arch_ver[] =
{
+ {0, ARM_ARCH_V1},
+ {0, ARM_ARCH_V2},
+ {0, ARM_ARCH_V2S},
+ {0, ARM_ARCH_V3},
+ {0, ARM_ARCH_V3M},
+ {1, ARM_ARCH_V4xM},
{1, ARM_ARCH_V4},
+ {2, ARM_ARCH_V4TxM},
{2, ARM_ARCH_V4T},
+ {3, ARM_ARCH_V5xM},
{3, ARM_ARCH_V5},
+ {3, ARM_ARCH_V5TxM},
{3, ARM_ARCH_V5T},
+ {4, ARM_ARCH_V5TExP},
{4, ARM_ARCH_V5TE},
{5, ARM_ARCH_V5TEJ},
{6, ARM_ARCH_V6},
- {9, ARM_ARCH_V6K},
{7, ARM_ARCH_V6Z},
+ {7, ARM_ARCH_V6KZ},
+ {9, ARM_ARCH_V6K},
+ {8, ARM_ARCH_V6T2},
+ {8, ARM_ARCH_V6KT2},
+ {8, ARM_ARCH_V6ZT2},
+ {8, ARM_ARCH_V6KZT2},
+
+ /* When assembling a file with only ARMv6-M or ARMv6S-M instruction, GNU as
+ always selected build attributes to match those of ARMv6-M
+ (resp. ARMv6S-M). However, due to these architectures being a strict
+ subset of ARMv7-M in terms of instructions available, ARMv7-M attributes
+ would be selected when fully respecting chronology of architectures.
+ It is thus necessary to make a special case of ARMv6-M and ARMv6S-M and
+ move them before ARMv7 architectures. */
{11, ARM_ARCH_V6M},
{12, ARM_ARCH_V6SM},
- {8, ARM_ARCH_V6T2},
- {10, ARM_ARCH_V7VE},
+
+ {10, ARM_ARCH_V7},
+ {10, ARM_ARCH_V7A},
{10, ARM_ARCH_V7R},
{10, ARM_ARCH_V7M},
+ {10, ARM_ARCH_V7VE},
+ {13, ARM_ARCH_V7EM},
{14, ARM_ARCH_V8A},
+ {14, ARM_ARCH_V8_1A},
+ {14, ARM_ARCH_V8_2A},
+ {14, ARM_ARCH_V8_3A},
{16, ARM_ARCH_V8M_BASE},
{17, ARM_ARCH_V8M_MAIN},
- {0, ARM_ARCH_NONE}
+ {-1, ARM_ARCH_NONE}
};
/* Set an attribute if it has not already been set by the user. */
@@ -26603,18 +26635,162 @@ aeabi_set_attribute_string (int tag, const char *value)
bfd_elf_add_proc_attr_string (stdoutput, tag, value);
}
+/* Return whether features in the *NEEDED feature set are available via
+ extensions for the architecture whose feature set is *ARCH_FSET. */
+static bfd_boolean
+have_ext_for_needed_feat_p (const arm_feature_set *arch_fset,
+ const arm_feature_set *needed)
+{
+ int i, nb_allowed_archs;
+ arm_feature_set ext_fset;
+ const struct arm_option_extension_value_table *opt;
+
+ ext_fset = arm_arch_none;
+ for (opt = arm_extensions; opt->name != NULL; opt++)
+ {
+ /* Extension does not provide any feature we need. */
+ if (!ARM_CPU_HAS_FEATURE (*needed, opt->merge_value))
+ continue;
+
+ nb_allowed_archs =
+ sizeof (opt->allowed_archs) / sizeof (opt->allowed_archs[0]);
+ for (i = 0; i < nb_allowed_archs; i++)
+ {
+ /* Empty entry. */
+ if (ARM_FEATURE_EQUAL (opt->allowed_archs[i], arm_arch_any))
+ break;
+
+ /* Extension is available, add it. */
+ if (ARM_FSET_CPU_SUBSET (opt->allowed_archs[i], *arch_fset))
+ ARM_MERGE_FEATURE_SETS (ext_fset, ext_fset, opt->merge_value);
+ }
+ }
+
+ /* Can we enable all features in *needed? */
+ return ARM_FSET_CPU_SUBSET (*needed, ext_fset);
+}
+
+/* Select value for Tag_CPU_arch and Tag_CPU_arch_profile build attributes for
+ a given architecture feature set *ARCH_EXT_FSET including extension feature
+ set *EXT_FSET. Selection logic used depend on EXACT_MATCH:
+ - if true, check for an exact match of the architecture modulo extensions;
+ - otherwise, select build attribute value of the first superset
+ architecture released so that results remains stable when new architectures
+ are added.
+ For -march/-mcpu=all the build attribute value of the most featureful
+ architecture is returned. Tag_CPU_arch_profile result is returned in
+ PROFILE. */
+static int
+get_aeabi_cpu_arch_from_fset (const arm_feature_set *arch_ext_fset,
+ const arm_feature_set *ext_fset,
+ char *profile, int exact_match)
+{
+ arm_feature_set arch_fset;
+ const cpu_arch_ver_table *p_ver, *p_ver_ret = NULL;
+
+ /* Select most featureful architecture with all its extensions if building
+ for -march=all as the feature sets used to set build attributes. */
+ if (ARM_FEATURE_EQUAL (*arch_ext_fset, arm_arch_any))
+ {
+ /* Force revisiting of decision for each new architecture. */
+ gas_assert (MAX_TAG_CPU_ARCH <= TAG_CPU_ARCH_V8M_MAIN);
+ *profile = 'A';
+ return TAG_CPU_ARCH_V8;
+ }
+
+ ARM_CLEAR_FEATURE (arch_fset, *arch_ext_fset, *ext_fset);
+
+ for (p_ver = cpu_arch_ver; p_ver->val != -1; p_ver++)
+ {
+ arm_feature_set known_arch_fset;
+
+ ARM_CLEAR_FEATURE (known_arch_fset, p_ver->flags, fpu_any);
+ if (exact_match)
+ {
+ /* Base architecture match user-specified architecture and
+ extensions, eg. ARMv6S-M matching -march=armv6-m+os. */
+ if (ARM_FEATURE_EQUAL (*arch_ext_fset, known_arch_fset))
+ {
+ p_ver_ret = p_ver;
+ goto found;
+ }
+ /* Base architecture match user-specified architecture only
+ (eg. ARMv6-M in the same case as above). Record it in case we
+ find a match with above condition. */
+ else if (p_ver_ret == NULL
+ && ARM_FEATURE_EQUAL (arch_fset, known_arch_fset))
+ p_ver_ret = p_ver;
+ }
+ else
+ {
+
+ /* Architecture has all features wanted. */
+ if (ARM_FSET_CPU_SUBSET (arch_fset, known_arch_fset))
+ {
+ arm_feature_set added_fset;
+
+ /* Compute features added by this architecture over the one
+ recorded in p_ver_ret. */
+ if (p_ver_ret != NULL)
+ ARM_CLEAR_FEATURE (added_fset, known_arch_fset,
+ p_ver_ret->flags);
+ /* First architecture that match incl. with extensions, or the
+ only difference in features over the recorded match is
+ features that were optional and are now mandatory. */
+ if (p_ver_ret == NULL
+ || ARM_FSET_CPU_SUBSET (added_fset, arch_fset))
+ {
+ p_ver_ret = p_ver;
+ goto found;
+ }
+ }
+ else if (p_ver_ret == NULL)
+ {
+ arm_feature_set needed_ext_fset;
+
+ ARM_CLEAR_FEATURE (needed_ext_fset, arch_fset, known_arch_fset);
+
+ /* Architecture has all features needed when using some
+ extensions. Record it and continue searching in case there
+ exist an architecture providing all needed features without
+ the need for extensions (eg. ARMv6S-M Vs ARMv6-M with
+ OS extension). */
+ if (have_ext_for_needed_feat_p (&known_arch_fset,
+ &needed_ext_fset))
+ p_ver_ret = p_ver;
+ }
+ }
+ }
+
+ if (p_ver_ret == NULL)
+ return -1;
+
+found:
+ /* Tag_CPU_arch_profile. */
+ if (ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v7a)
+ || ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v8)
+ || (ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_atomics)
+ && !ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v8m_m_only)))
+ *profile = 'A';
+ else if (ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v7r))
+ *profile = 'R';
+ else if (ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_m))
+ *profile = 'M';
+ else
+ *profile = '\0';
+ return p_ver_ret->val;
+}
+
/* Set the public EABI object attributes. */
static void
aeabi_set_public_attributes (void)
{
- int arch;
char profile;
+ int arch = -1;
int virt_sec = 0;
int fp16_optional = 0;
- arm_feature_set flags;
- arm_feature_set tmp;
- arm_feature_set arm_arch_v8m_base = ARM_ARCH_V8M_BASE;
- const cpu_arch_ver_table *p;
+ int skip_exact_match = 0;
+ arm_feature_set flags, flags_arch, flags_ext;
/* Autodetection mode, choose the architecture based the instructions
actually used. */
@@ -26647,45 +26823,29 @@ aeabi_set_public_attributes (void)
/* Allow the user to override the reported architecture. */
if (object_arch)
{
- ARM_CLEAR_FEATURE (flags, flags, arm_arch_any);
- ARM_MERGE_FEATURE_SETS (flags, flags, *object_arch);
+ ARM_CLEAR_FEATURE (flags_arch, *object_arch, fpu_any);
+ flags_ext = arm_arch_none;
}
-
- tmp = flags;
- arch = 0;
- for (p = cpu_arch_ver; p->val; p++)
+ else
{
- if (ARM_CPU_HAS_FEATURE (tmp, p->flags))
- {
- arch = p->val;
- ARM_CLEAR_FEATURE (tmp, tmp, p->flags);
- }
- }
-
- /* The table lookup above finds the last architecture to contribute
- a new feature. Unfortunately, Tag13 is a subset of the union of
- v6T2 and v7-M, so it is never seen as contributing a new feature.
- We can not search for the last entry which is entirely used,
- because if no CPU is specified we build up only those flags
- actually used. Perhaps we should separate out the specified
- and implicit cases. Avoid taking this path for -march=all by
- checking for contradictory v7-A / v7-M features. */
- if (arch == TAG_CPU_ARCH_V7
- && !ARM_CPU_HAS_FEATURE (flags, arm_ext_v7a)
- && ARM_CPU_HAS_FEATURE (flags, arm_ext_v7m)
- && ARM_CPU_HAS_FEATURE (flags, arm_ext_v6_dsp))
- arch = TAG_CPU_ARCH_V7E_M;
-
- ARM_CLEAR_FEATURE (tmp, flags, arm_arch_v8m_base);
- if (arch == TAG_CPU_ARCH_V8M_BASE && ARM_CPU_HAS_FEATURE (tmp, arm_arch_any))
- arch = TAG_CPU_ARCH_V8M_MAIN;
-
- /* In cpu_arch_ver ARMv8-A is before ARMv8-M for atomics to be detected as
- coming from ARMv8-A. However, since ARMv8-A has more instructions than
- ARMv8-M, -march=all must be detected as ARMv8-A. */
- if (arch == TAG_CPU_ARCH_V8M_MAIN
- && ARM_FEATURE_CORE_EQUAL (selected_cpu, arm_arch_any))
- arch = TAG_CPU_ARCH_V8;
+ ARM_CLEAR_FEATURE (flags_arch, flags, fpu_any);
+ flags_ext = dyn_mcpu_ext_opt ? *dyn_mcpu_ext_opt : arm_arch_none;
+ skip_exact_match = ARM_FEATURE_EQUAL (selected_cpu, arm_arch_any);
+ }
+
+ /* When this function is run again after relaxation has happened there is no
+ way to determine whether an architecture or CPU was specified by the user:
+ - selected_cpu is set above for relaxation to work;
+ - march_cpu_opt is not set if only -mcpu or .cpu is used;
+ - mcpu_cpu_opt is set to arm_arch_any for autodetection.
+ Therefore, if not in -march=all case we first try an exact match and fall
+ back to autodetection. */
+ if (!skip_exact_match)
+ arch = get_aeabi_cpu_arch_from_fset (&flags_arch, &flags_ext, &profile, 1);
+ if (arch == -1)
+ arch = get_aeabi_cpu_arch_from_fset (&flags_arch, &flags_ext, &profile, 0);
+ if (arch == -1)
+ as_bad (_("no architecture contains all the instructions used\n"));
/* Tag_CPU_name. */
if (selected_cpu_name[0])
@@ -26708,18 +26868,6 @@ aeabi_set_public_attributes (void)
aeabi_set_attribute_int (Tag_CPU_arch, arch);
/* Tag_CPU_arch_profile. */
- if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7a)
- || ARM_CPU_HAS_FEATURE (flags, arm_ext_v8)
- || (ARM_CPU_HAS_FEATURE (flags, arm_ext_atomics)
- && !ARM_CPU_HAS_FEATURE (flags, arm_ext_v8m_m_only)))
- profile = 'A';
- else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7r))
- profile = 'R';
- else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_m))
- profile = 'M';
- else
- profile = '\0';
-
if (profile != '\0')
aeabi_set_attribute_int (Tag_CPU_arch_profile, profile);
@@ -26727,14 +26875,15 @@ aeabi_set_public_attributes (void)
if (dyn_mcpu_ext_opt && ARM_CPU_HAS_FEATURE (*dyn_mcpu_ext_opt, arm_ext_dsp))
aeabi_set_attribute_int (Tag_DSP_extension, 1);
+ ARM_CLEAR_FEATURE (flags_arch, flags, fpu_any);
/* Tag_ARM_ISA_use. */
if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v1)
- || arch == 0)
+ || ARM_FEATURE_ZERO (flags_arch))
aeabi_set_attribute_int (Tag_ARM_ISA_use, 1);
/* Tag_THUMB_ISA_use. */
if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v4t)
- || arch == 0)
+ || ARM_FEATURE_ZERO (flags_arch))
{
int thumb_isa_use;
diff --git a/gas/testsuite/gas/arm/attr-march-armv1.d b/gas/testsuite/gas/arm/attr-march-armv1.d
index ac6597743ea..d9730b5d58b 100644
--- a/gas/testsuite/gas/arm/attr-march-armv1.d
+++ b/gas/testsuite/gas/arm/attr-march-armv1.d
@@ -8,5 +8,4 @@
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "1"
- Tag_CPU_arch: v4
Tag_ARM_ISA_use: Yes
diff --git a/gas/testsuite/gas/arm/attr-march-armv2.d b/gas/testsuite/gas/arm/attr-march-armv2.d
index 0b574efbbbc..39e33719295 100644
--- a/gas/testsuite/gas/arm/attr-march-armv2.d
+++ b/gas/testsuite/gas/arm/attr-march-armv2.d
@@ -8,5 +8,4 @@
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "2"
- Tag_CPU_arch: v4
Tag_ARM_ISA_use: Yes
diff --git a/gas/testsuite/gas/arm/attr-march-armv2a.d b/gas/testsuite/gas/arm/attr-march-armv2a.d
index 387e4a31804..2c4dd620d3d 100644
--- a/gas/testsuite/gas/arm/attr-march-armv2a.d
+++ b/gas/testsuite/gas/arm/attr-march-armv2a.d
@@ -8,5 +8,4 @@
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "2A"
- Tag_CPU_arch: v4
Tag_ARM_ISA_use: Yes
diff --git a/gas/testsuite/gas/arm/attr-march-armv2s.d b/gas/testsuite/gas/arm/attr-march-armv2s.d
index 3bd06e62f07..dfd17d2b377 100644
--- a/gas/testsuite/gas/arm/attr-march-armv2s.d
+++ b/gas/testsuite/gas/arm/attr-march-armv2s.d
@@ -8,5 +8,4 @@
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "2S"
- Tag_CPU_arch: v4
Tag_ARM_ISA_use: Yes
diff --git a/gas/testsuite/gas/arm/attr-march-armv3.d b/gas/testsuite/gas/arm/attr-march-armv3.d
index 13d5d183946..988f8965293 100644
--- a/gas/testsuite/gas/arm/attr-march-armv3.d
+++ b/gas/testsuite/gas/arm/attr-march-armv3.d
@@ -8,5 +8,4 @@
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "3"
- Tag_CPU_arch: v4
Tag_ARM_ISA_use: Yes
diff --git a/gas/testsuite/gas/arm/attr-march-armv3m.d b/gas/testsuite/gas/arm/attr-march-armv3m.d
index 4e2439972d8..c946b37177a 100644
--- a/gas/testsuite/gas/arm/attr-march-armv3m.d
+++ b/gas/testsuite/gas/arm/attr-march-armv3m.d
@@ -8,5 +8,4 @@
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "3M"
- Tag_CPU_arch: v4
Tag_ARM_ISA_use: Yes
diff --git a/include/ChangeLog b/include/ChangeLog
index 44905d7da9f..b48df0913ff 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2017-06-21 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * opcode/arm.h (FPU_ANY): New macro.
+
2017-06-16 Alan Modra <amodra@gmail.com>
PR ld/20022
diff --git a/include/opcode/arm.h b/include/opcode/arm.h
index bb68a78154a..5691a85545c 100644
--- a/include/opcode/arm.h
+++ b/include/opcode/arm.h
@@ -285,6 +285,7 @@
#define ARM_ARCH_NONE ARM_FEATURE_LOW (0, 0)
#define FPU_NONE ARM_FEATURE_LOW (0, 0)
#define ARM_ANY ARM_FEATURE (-1, -1, 0) /* Any basic core. */
+#define FPU_ANY ARM_FEATURE_COPROC (-1) /* Any FPU. */
#define ARM_FEATURE_ALL ARM_FEATURE (-1, -1, -1)/* All CPU and FPU features. */
#define FPU_ANY_HARD ARM_FEATURE_COPROC (FPU_FPA | FPU_VFP_HARD | FPU_MAVERICK)
/* Extensions containing some Thumb-2 instructions. If any is present, Thumb