[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.
This commit is contained in:
Szabolcs Nagy
2016-07-01 16:20:50 +01:00
parent 2c5c2a3321
commit 93d8990cba
7 changed files with 105 additions and 21 deletions

View File

@ -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> 2016-07-01 Nick Clifton <nickc@redhat.com>
* macro.c (macro_expand_body): Use a buffer big enough to hold an * macro.c (macro_expand_body): Use a buffer big enough to hold an

View File

@ -6080,7 +6080,7 @@ md_assemble (char *str)
{ {
/* Check that this instruction is supported for this CPU. */ /* Check that this instruction is supported for this CPU. */
if (!opcode->avariant 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); as_bad (_("selected processor does not support `%s'"), str);
return; return;
@ -7801,23 +7801,33 @@ struct aarch64_option_cpu_value_table
{ {
const char *name; const char *name;
const aarch64_feature_set value; const aarch64_feature_set value;
const aarch64_feature_set require; /* Feature dependencies. */
}; };
static const struct aarch64_option_cpu_value_table aarch64_features[] = { static const struct aarch64_option_cpu_value_table aarch64_features[] = {
{"crc", AARCH64_FEATURE (AARCH64_FEATURE_CRC, 0)}, {"crc", AARCH64_FEATURE (AARCH64_FEATURE_CRC, 0),
{"crypto", AARCH64_FEATURE (AARCH64_FEATURE_CRYPTO, 0)}, AARCH64_ARCH_NONE},
{"fp", AARCH64_FEATURE (AARCH64_FEATURE_FP, 0)}, {"crypto", AARCH64_FEATURE (AARCH64_FEATURE_CRYPTO, 0),
{"lse", AARCH64_FEATURE (AARCH64_FEATURE_LSE, 0)}, AARCH64_ARCH_NONE},
{"simd", AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0)}, {"fp", AARCH64_FEATURE (AARCH64_FEATURE_FP, 0),
{"pan", AARCH64_FEATURE (AARCH64_FEATURE_PAN, 0)}, AARCH64_ARCH_NONE},
{"lor", AARCH64_FEATURE (AARCH64_FEATURE_LOR, 0)}, {"lse", AARCH64_FEATURE (AARCH64_FEATURE_LSE, 0),
{"ras", AARCH64_FEATURE (AARCH64_FEATURE_RAS, 0)}, AARCH64_ARCH_NONE},
{"rdma", AARCH64_FEATURE (AARCH64_FEATURE_SIMD {"simd", AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0),
| AARCH64_FEATURE_RDMA, 0)}, AARCH64_ARCH_NONE},
{"fp16", AARCH64_FEATURE (AARCH64_FEATURE_F16 {"pan", AARCH64_FEATURE (AARCH64_FEATURE_PAN, 0),
| AARCH64_FEATURE_FP, 0)}, AARCH64_ARCH_NONE},
{"profile", AARCH64_FEATURE (AARCH64_FEATURE_PROFILE, 0)}, {"lor", AARCH64_FEATURE (AARCH64_FEATURE_LOR, 0),
{NULL, AARCH64_ARCH_NONE} 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 struct aarch64_long_option_table
@ -7828,6 +7838,38 @@ struct aarch64_long_option_table
char *deprecated; /* If non-null, print this message. */ 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 static int
aarch64_parse_features (const char *str, const aarch64_feature_set **opt_p, aarch64_parse_features (const char *str, const aarch64_feature_set **opt_p,
bfd_boolean ext_only) 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++) for (opt = aarch64_features; opt->name != NULL; opt++)
if (strncmp (opt->name, str, optlen) == 0) if (strncmp (opt->name, str, optlen) == 0)
{ {
aarch64_feature_set set;
/* Add or remove the extension. */ /* Add or remove the extension. */
if (adding_value) 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 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; break;
} }

View File

@ -0,0 +1,2 @@
#as: -march=armv8.2-a+nofp16 -mno-verbose-error
#error-output: illegal-nofp16.l

View File

@ -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'

View File

@ -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

View File

@ -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> 2016-06-30 Matthew Wahab <matthew.wahab@arm.com>
* opcode/arm.h (ARM_ARCH_V8_2a): Add FPU_NEON_EXT_RDMA to the set * opcode/arm.h (ARM_ARCH_V8_2a): Add FPU_NEON_EXT_RDMA to the set

View File

@ -84,9 +84,15 @@ typedef uint32_t aarch64_insn;
/* CPU-specific features. */ /* CPU-specific features. */
typedef unsigned long aarch64_feature_set; 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) (((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) \ #define AARCH64_MERGE_FEATURE_SETS(TARG,F1,F2) \
do \ do \
{ \ { \
@ -103,9 +109,6 @@ typedef unsigned long aarch64_feature_set;
#define AARCH64_FEATURE(core,coproc) ((core) | (coproc)) #define AARCH64_FEATURE(core,coproc) ((core) | (coproc))
#define AARCH64_OPCODE_HAS_FEATURE(OPC,FEAT) \
(((OPC) & (FEAT)) != 0)
enum aarch64_operand_class enum aarch64_operand_class
{ {
AARCH64_OPND_CLASS_NIL, AARCH64_OPND_CLASS_NIL,