From 05f15256d0274b8321eec4cad4273340e1a8521f Mon Sep 17 00:00:00 2001 From: Andrew Carlotti Date: Fri, 21 Jun 2024 19:31:06 +0100 Subject: [PATCH] aarch64: Add support for virtual features These features will be used to gate instructions that can be enabled by either of two (or more) different sets of command line feature flags. This patch add a postprocessing step to the feature parsing code to set the value of the virtual bits. --- gas/config/tc-aarch64.c | 64 +++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index 1717ca7eb70..2bd87d149b8 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -10684,6 +10684,32 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = { {NULL, AARCH64_NO_FEATURES, AARCH64_NO_FEATURES}, }; +/* If all features in the TEST feature set are present, then every virtual + feature in the ENABLES feature set should also be enabled. */ +struct aarch64_virtual_dependency_table +{ + const aarch64_feature_set test; + const aarch64_feature_set enables; +}; + +static const struct aarch64_virtual_dependency_table aarch64_dependencies[] = { + {AARCH64_NO_FEATURES, AARCH64_NO_FEATURES} +}; + +static aarch64_feature_set +aarch64_update_virtual_dependencies (aarch64_feature_set set) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE (aarch64_dependencies); i++) + AARCH64_CLEAR_FEATURES (set, set, aarch64_dependencies[i].enables); + + for (i = 0; i < ARRAY_SIZE (aarch64_dependencies); i++) + if (AARCH64_CPU_HAS_ALL_FEATURES (set, aarch64_dependencies[i].test)) + AARCH64_MERGE_FEATURE_SETS (set, set, aarch64_dependencies[i].enables); + + return set; +} + /* Transitive closure of features depending on set. */ static aarch64_feature_set aarch64_feature_disable_set (aarch64_feature_set set) @@ -10722,16 +10748,23 @@ static int aarch64_parse_features (const char *str, const aarch64_feature_set **opt_p, bool ext_only) { + /* Copy the feature set, so that we can modify it. */ + aarch64_feature_set *ext_set = XNEW (aarch64_feature_set); + *ext_set = **opt_p; + *opt_p = ext_set; + + if (str == NULL) + { + /* No extensions, so just set the virtual feature bits and return. */ + *ext_set = aarch64_update_virtual_dependencies (*ext_set); + return 1; + } + /* We insist on extensions being added before being removed. We achieve this by using the ADDING_VALUE variable to indicate whether we are adding an extension (1) or removing it (0) and only allowing it to change in the order -1 -> 1 -> 0. */ int adding_value = -1; - aarch64_feature_set *ext_set = XNEW (aarch64_feature_set); - - /* Copy the feature set, so that we can modify it. */ - *ext_set = **opt_p; - *opt_p = ext_set; while (str != NULL && *str != 0) { @@ -10811,6 +10844,7 @@ aarch64_parse_features (const char *str, const aarch64_feature_set **opt_p, str = ext; }; + *ext_set = aarch64_update_virtual_dependencies (*ext_set); return 1; } @@ -10836,10 +10870,7 @@ aarch64_parse_cpu (const char *str) if (strlen (opt->name) == optlen && strncmp (str, opt->name, optlen) == 0) { mcpu_cpu_opt = &opt->value; - if (ext != NULL) - return aarch64_parse_features (ext, &mcpu_cpu_opt, false); - - return 1; + return aarch64_parse_features (ext, &mcpu_cpu_opt, false); } as_bad (_("unknown cpu `%s'"), str); @@ -10868,10 +10899,7 @@ aarch64_parse_arch (const char *str) if (strlen (opt->name) == optlen && strncmp (str, opt->name, optlen) == 0) { march_cpu_opt = &opt->value; - if (ext != NULL) - return aarch64_parse_features (ext, &march_cpu_opt, false); - - return 1; + return aarch64_parse_features (ext, &march_cpu_opt, false); } as_bad (_("unknown architecture `%s'\n"), str); @@ -11057,9 +11085,8 @@ s_aarch64_cpu (int ignored ATTRIBUTE_UNUSED) && strncmp (name, opt->name, optlen) == 0) { mcpu_cpu_opt = &opt->value; - if (ext != NULL) - if (!aarch64_parse_features (ext, &mcpu_cpu_opt, false)) - return; + if (!aarch64_parse_features (ext, &mcpu_cpu_opt, false)) + return; cpu_variant = *mcpu_cpu_opt; @@ -11102,9 +11129,8 @@ s_aarch64_arch (int ignored ATTRIBUTE_UNUSED) && strncmp (name, opt->name, optlen) == 0) { mcpu_cpu_opt = &opt->value; - if (ext != NULL) - if (!aarch64_parse_features (ext, &mcpu_cpu_opt, false)) - return; + if (!aarch64_parse_features (ext, &mcpu_cpu_opt, false)) + return; cpu_variant = *mcpu_cpu_opt; -- 2.39.5