aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzabolcs Nagy <szabolcs.nagy@arm.com>2016-07-01 16:20:50 +0100
committerSzabolcs Nagy <szabolcs.nagy@arm.com>2016-07-01 16:50:59 +0100
commit93d8990cba700abdf9d2be06a5022e588d097fc8 (patch)
tree4e26591d6134671659c2bea61ec81f3c50452662
parent2c5c2a3321706c28cbf1b85a970a2e32912eb0c8 (diff)
downloadfsf-binutils-gdb-93d8990cba700abdf9d2be06a5022e588d097fc8.zip
fsf-binutils-gdb-93d8990cba700abdf9d2be06a5022e588d097fc8.tar.gz
fsf-binutils-gdb-93d8990cba700abdf9d2be06a5022e588d097fc8.tar.bz2
[AArch64] Fix +nofp16 handling
Feature flag handling was not perfect, +nofp16 disabled fp instructions too. New feature flag macros were added to check features with multiple bits set (matters for FP_F16 and SIMD_F16 opcode feature tests). The unused AARCH64_OPCODE_HAS_FEATURE was removed, all checks should use one of the AARCH64_CPU_HAS_* macros. AARCH64_CPU_HAS_FEATURE now checks all feature bits. The aarch64_features table now contains the dependencies as a separate field (so when the feature is enabled all dependencies are enabled and when it is disabled everything that depends on it is disabled). Note that armv8-a+foo+nofoo is not equivalent to armv8-a if +foo turns on dependent features that nofoo does not turn off. gas/ * config/tc-aarch64.c (struct aarch64_option_cpu_value_table): Add require field. (aarch64_features): Initialize require fields. (aarch64_parse_features): Handle dependencies. (aarch64_feature_enable_set, aarch64_feature_disable_set): New. (md_assemble): Use AARCH64_CPU_HAS_ALL_FEATURES. * testsuite/gas/aarch64/illegal-nofp16.s: New. * testsuite/gas/aarch64/illegal-nofp16.l: New. * testsuite/gas/aarch64/illegal-nofp16.d: New. include/ * opcode/aarch64.h (AARCH64_CPU_HAS_ALL_FEATURES): New. (AARCH64_CPU_HAS_ANY_FEATURES): New. (AARCH64_CPU_HAS_FEATURE): Define as AARCH64_CPU_HAS_ALL_FEATURES. (AARCH64_OPCODE_HAS_FEATURE): Remove.
-rw-r--r--gas/ChangeLog12
-rw-r--r--gas/config/tc-aarch64.c84
-rw-r--r--gas/testsuite/gas/aarch64/illegal-nofp16.d2
-rw-r--r--gas/testsuite/gas/aarch64/illegal-nofp16.l3
-rw-r--r--gas/testsuite/gas/aarch64/illegal-nofp16.s7
-rw-r--r--include/ChangeLog7
-rw-r--r--include/opcode/aarch64.h11
7 files changed, 105 insertions, 21 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 40a9a2b..5cb62e2 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,15 @@
+2016-07-01 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * config/tc-aarch64.c (struct aarch64_option_cpu_value_table): Add
+ require field.
+ (aarch64_features): Initialize require fields.
+ (aarch64_parse_features): Handle dependencies.
+ (aarch64_feature_enable_set, aarch64_feature_disable_set): New.
+ (md_assemble): Use AARCH64_CPU_HAS_ALL_FEATURES.
+ * testsuite/gas/aarch64/illegal-nofp16.s: New.
+ * testsuite/gas/aarch64/illegal-nofp16.l: New.
+ * testsuite/gas/aarch64/illegal-nofp16.d: New.
+
2016-07-01 Nick Clifton <nickc@redhat.com>
* macro.c (macro_expand_body): Use a buffer big enough to hold an
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index ddc40f2..2d491f6 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -6080,7 +6080,7 @@ md_assemble (char *str)
{
/* Check that this instruction is supported for this CPU. */
if (!opcode->avariant
- || !AARCH64_CPU_HAS_FEATURE (cpu_variant, *opcode->avariant))
+ || !AARCH64_CPU_HAS_ALL_FEATURES (cpu_variant, *opcode->avariant))
{
as_bad (_("selected processor does not support `%s'"), str);
return;
@@ -7801,23 +7801,33 @@ struct aarch64_option_cpu_value_table
{
const char *name;
const aarch64_feature_set value;
+ const aarch64_feature_set require; /* Feature dependencies. */
};
static const struct aarch64_option_cpu_value_table aarch64_features[] = {
- {"crc", AARCH64_FEATURE (AARCH64_FEATURE_CRC, 0)},
- {"crypto", AARCH64_FEATURE (AARCH64_FEATURE_CRYPTO, 0)},
- {"fp", AARCH64_FEATURE (AARCH64_FEATURE_FP, 0)},
- {"lse", AARCH64_FEATURE (AARCH64_FEATURE_LSE, 0)},
- {"simd", AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0)},
- {"pan", AARCH64_FEATURE (AARCH64_FEATURE_PAN, 0)},
- {"lor", AARCH64_FEATURE (AARCH64_FEATURE_LOR, 0)},
- {"ras", AARCH64_FEATURE (AARCH64_FEATURE_RAS, 0)},
- {"rdma", AARCH64_FEATURE (AARCH64_FEATURE_SIMD
- | AARCH64_FEATURE_RDMA, 0)},
- {"fp16", AARCH64_FEATURE (AARCH64_FEATURE_F16
- | AARCH64_FEATURE_FP, 0)},
- {"profile", AARCH64_FEATURE (AARCH64_FEATURE_PROFILE, 0)},
- {NULL, AARCH64_ARCH_NONE}
+ {"crc", AARCH64_FEATURE (AARCH64_FEATURE_CRC, 0),
+ AARCH64_ARCH_NONE},
+ {"crypto", AARCH64_FEATURE (AARCH64_FEATURE_CRYPTO, 0),
+ AARCH64_ARCH_NONE},
+ {"fp", AARCH64_FEATURE (AARCH64_FEATURE_FP, 0),
+ AARCH64_ARCH_NONE},
+ {"lse", AARCH64_FEATURE (AARCH64_FEATURE_LSE, 0),
+ AARCH64_ARCH_NONE},
+ {"simd", AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0),
+ AARCH64_ARCH_NONE},
+ {"pan", AARCH64_FEATURE (AARCH64_FEATURE_PAN, 0),
+ AARCH64_ARCH_NONE},
+ {"lor", AARCH64_FEATURE (AARCH64_FEATURE_LOR, 0),
+ AARCH64_ARCH_NONE},
+ {"ras", AARCH64_FEATURE (AARCH64_FEATURE_RAS, 0),
+ AARCH64_ARCH_NONE},
+ {"rdma", AARCH64_FEATURE (AARCH64_FEATURE_RDMA, 0),
+ AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0)},
+ {"fp16", AARCH64_FEATURE (AARCH64_FEATURE_F16, 0),
+ AARCH64_FEATURE (AARCH64_FEATURE_FP, 0)},
+ {"profile", AARCH64_FEATURE (AARCH64_FEATURE_PROFILE, 0),
+ AARCH64_ARCH_NONE},
+ {NULL, AARCH64_ARCH_NONE, AARCH64_ARCH_NONE},
};
struct aarch64_long_option_table
@@ -7828,6 +7838,38 @@ struct aarch64_long_option_table
char *deprecated; /* If non-null, print this message. */
};
+/* Transitive closure of features depending on set. */
+static aarch64_feature_set
+aarch64_feature_disable_set (aarch64_feature_set set)
+{
+ const struct aarch64_option_cpu_value_table *opt;
+ aarch64_feature_set prev = 0;
+
+ while (prev != set) {
+ prev = set;
+ for (opt = aarch64_features; opt->name != NULL; opt++)
+ if (AARCH64_CPU_HAS_ANY_FEATURES (opt->require, set))
+ AARCH64_MERGE_FEATURE_SETS (set, set, opt->value);
+ }
+ return set;
+}
+
+/* Transitive closure of dependencies of set. */
+static aarch64_feature_set
+aarch64_feature_enable_set (aarch64_feature_set set)
+{
+ const struct aarch64_option_cpu_value_table *opt;
+ aarch64_feature_set prev = 0;
+
+ while (prev != set) {
+ prev = set;
+ for (opt = aarch64_features; opt->name != NULL; opt++)
+ if (AARCH64_CPU_HAS_FEATURE (set, opt->value))
+ AARCH64_MERGE_FEATURE_SETS (set, set, opt->require);
+ }
+ return set;
+}
+
static int
aarch64_parse_features (const char *str, const aarch64_feature_set **opt_p,
bfd_boolean ext_only)
@@ -7895,11 +7937,19 @@ aarch64_parse_features (const char *str, const aarch64_feature_set **opt_p,
for (opt = aarch64_features; opt->name != NULL; opt++)
if (strncmp (opt->name, str, optlen) == 0)
{
+ aarch64_feature_set set;
+
/* Add or remove the extension. */
if (adding_value)
- AARCH64_MERGE_FEATURE_SETS (*ext_set, *ext_set, opt->value);
+ {
+ set = aarch64_feature_enable_set (opt->value);
+ AARCH64_MERGE_FEATURE_SETS (*ext_set, *ext_set, set);
+ }
else
- AARCH64_CLEAR_FEATURE (*ext_set, *ext_set, opt->value);
+ {
+ set = aarch64_feature_disable_set (opt->value);
+ AARCH64_CLEAR_FEATURE (*ext_set, *ext_set, set);
+ }
break;
}
diff --git a/gas/testsuite/gas/aarch64/illegal-nofp16.d b/gas/testsuite/gas/aarch64/illegal-nofp16.d
new file mode 100644
index 0000000..669e85d
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/illegal-nofp16.d
@@ -0,0 +1,2 @@
+#as: -march=armv8.2-a+nofp16 -mno-verbose-error
+#error-output: illegal-nofp16.l
diff --git a/gas/testsuite/gas/aarch64/illegal-nofp16.l b/gas/testsuite/gas/aarch64/illegal-nofp16.l
new file mode 100644
index 0000000..99d586b
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/illegal-nofp16.l
@@ -0,0 +1,3 @@
+[^:]*: Assembler messages:
+^[^:]+:4: Error: selected processor does not support `fneg h0,h1'
+^[^:]+:6: Error: selected processor does not support `fneg v0\.8h,v1\.8h'
diff --git a/gas/testsuite/gas/aarch64/illegal-nofp16.s b/gas/testsuite/gas/aarch64/illegal-nofp16.s
new file mode 100644
index 0000000..7718444
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/illegal-nofp16.s
@@ -0,0 +1,7 @@
+// Test -march=armv8.2-a+nofp16 to only disable fp16, not fp.
+.text
+ fneg s0, s1
+ fneg h0, h1
+ fneg v0.4s, v1.4s
+ fneg v0.8h, v1.8h
+ neg v0.16b, v1.16b
diff --git a/include/ChangeLog b/include/ChangeLog
index a766ecf..e4db8b8 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,10 @@
+2016-07-01 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * opcode/aarch64.h (AARCH64_CPU_HAS_ALL_FEATURES): New.
+ (AARCH64_CPU_HAS_ANY_FEATURES): New.
+ (AARCH64_CPU_HAS_FEATURE): Define as AARCH64_CPU_HAS_ALL_FEATURES.
+ (AARCH64_OPCODE_HAS_FEATURE): Remove.
+
2016-06-30 Matthew Wahab <matthew.wahab@arm.com>
* opcode/arm.h (ARM_ARCH_V8_2a): Add FPU_NEON_EXT_RDMA to the set
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index b35a818..1e38749 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -84,9 +84,15 @@ typedef uint32_t aarch64_insn;
/* CPU-specific features. */
typedef unsigned long aarch64_feature_set;
-#define AARCH64_CPU_HAS_FEATURE(CPU,FEAT) \
+#define AARCH64_CPU_HAS_ALL_FEATURES(CPU,FEAT) \
+ ((~(CPU) & (FEAT)) == 0)
+
+#define AARCH64_CPU_HAS_ANY_FEATURES(CPU,FEAT) \
(((CPU) & (FEAT)) != 0)
+#define AARCH64_CPU_HAS_FEATURE(CPU,FEAT) \
+ AARCH64_CPU_HAS_ALL_FEATURES (CPU,FEAT)
+
#define AARCH64_MERGE_FEATURE_SETS(TARG,F1,F2) \
do \
{ \
@@ -103,9 +109,6 @@ typedef unsigned long aarch64_feature_set;
#define AARCH64_FEATURE(core,coproc) ((core) | (coproc))
-#define AARCH64_OPCODE_HAS_FEATURE(OPC,FEAT) \
- (((OPC) & (FEAT)) != 0)
-
enum aarch64_operand_class
{
AARCH64_OPND_CLASS_NIL,