This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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/
2016-06-28  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.

include/
2016-06-28  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.
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/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,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]