From 93d8990cba700abdf9d2be06a5022e588d097fc8 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Fri, 1 Jul 2016 16:20:50 +0100 Subject: [PATCH] [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. --- gas/ChangeLog | 12 ++++ gas/config/tc-aarch64.c | 84 +++++++++++++++++----- gas/testsuite/gas/aarch64/illegal-nofp16.d | 2 + gas/testsuite/gas/aarch64/illegal-nofp16.l | 3 + gas/testsuite/gas/aarch64/illegal-nofp16.s | 7 ++ include/ChangeLog | 7 ++ include/opcode/aarch64.h | 11 +-- 7 files changed, 105 insertions(+), 21 deletions(-) create mode 100644 gas/testsuite/gas/aarch64/illegal-nofp16.d create mode 100644 gas/testsuite/gas/aarch64/illegal-nofp16.l create mode 100644 gas/testsuite/gas/aarch64/illegal-nofp16.s diff --git a/gas/ChangeLog b/gas/ChangeLog index 40a9a2b88ab..5cb62e2aa32 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,15 @@ +2016-07-01 Szabolcs Nagy + + * 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 * 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 ddc40f28f26..2d491f6ab25 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 00000000000..669e85d38a0 --- /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 00000000000..99d586b4747 --- /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 00000000000..77184449db8 --- /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 a766ecf9dc3..e4db8b8aea9 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,10 @@ +2016-07-01 Szabolcs Nagy + + * 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 * 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 b35a818a657..1e38749c301 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, -- 2.30.2