aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-aarch64.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2014-11-18 14:08:28 +0100
committerJan Beulich <jbeulich@suse.com>2014-11-18 14:08:28 +0100
commitae527cd876fe35de72d876d3484e194ccc66232f (patch)
tree506c344ade8b18b6a142c10931eb4644b4a7e3b2 /gas/config/tc-aarch64.c
parent0a9ce86dafbd889ab3dfc8f61db364a2426be99b (diff)
downloadgdb-ae527cd876fe35de72d876d3484e194ccc66232f.zip
gdb-ae527cd876fe35de72d876d3484e194ccc66232f.tar.gz
gdb-ae527cd876fe35de72d876d3484e194ccc66232f.tar.bz2
aarch64: allow adding/removing just feature flags via .arch_extension
Rather than requiring to always also set/change the base architecture, allow just en-/disabling of architecture extensions, matching what ARM has.
Diffstat (limited to 'gas/config/tc-aarch64.c')
-rw-r--r--gas/config/tc-aarch64.c51
1 files changed, 39 insertions, 12 deletions
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 7f22ba4..8cecfd0 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -1917,6 +1917,7 @@ s_tlsdesccall (int ignored ATTRIBUTE_UNUSED)
static void s_aarch64_arch (int);
static void s_aarch64_cpu (int);
+static void s_aarch64_arch_extension (int);
/* This table describes all the machine specific pseudo-ops the assembler
has to support. The fields are:
@@ -1934,6 +1935,7 @@ const pseudo_typeS md_pseudo_table[] = {
{"pool", s_ltorg, 0},
{"cpu", s_aarch64_cpu, 0},
{"arch", s_aarch64_arch, 0},
+ {"arch_extension", s_aarch64_arch_extension, 0},
{"inst", s_aarch64_inst, 0},
#ifdef OBJ_ELF
{"tlsdesccall", s_tlsdesccall, 0},
@@ -7238,7 +7240,8 @@ struct aarch64_long_option_table
};
static int
-aarch64_parse_features (char *str, const aarch64_feature_set **opt_p)
+aarch64_parse_features (char *str, const aarch64_feature_set **opt_p,
+ bfd_boolean ext_only)
{
/* We insist on extensions being added before being removed. We achieve
this by using the ADDING_VALUE variable to indicate whether we are
@@ -7254,17 +7257,19 @@ aarch64_parse_features (char *str, const aarch64_feature_set **opt_p)
while (str != NULL && *str != 0)
{
const struct aarch64_option_cpu_value_table *opt;
- char *ext;
+ char *ext = NULL;
int optlen;
- if (*str != '+')
+ if (!ext_only)
{
- as_bad (_("invalid architectural extension"));
- return 0;
- }
+ if (*str != '+')
+ {
+ as_bad (_("invalid architectural extension"));
+ return 0;
+ }
- str++;
- ext = strchr (str, '+');
+ ext = strchr (++str, '+');
+ }
if (ext != NULL)
optlen = ext - str;
@@ -7344,7 +7349,7 @@ aarch64_parse_cpu (char *str)
{
mcpu_cpu_opt = &opt->value;
if (ext != NULL)
- return aarch64_parse_features (ext, &mcpu_cpu_opt);
+ return aarch64_parse_features (ext, &mcpu_cpu_opt, FALSE);
return 1;
}
@@ -7376,7 +7381,7 @@ aarch64_parse_arch (char *str)
{
march_cpu_opt = &opt->value;
if (ext != NULL)
- return aarch64_parse_features (ext, &march_cpu_opt);
+ return aarch64_parse_features (ext, &march_cpu_opt, FALSE);
return 1;
}
@@ -7559,7 +7564,7 @@ s_aarch64_cpu (int ignored ATTRIBUTE_UNUSED)
{
mcpu_cpu_opt = &opt->value;
if (ext != NULL)
- if (!aarch64_parse_features (ext, &mcpu_cpu_opt))
+ if (!aarch64_parse_features (ext, &mcpu_cpu_opt, FALSE))
return;
cpu_variant = *mcpu_cpu_opt;
@@ -7605,7 +7610,7 @@ s_aarch64_arch (int ignored ATTRIBUTE_UNUSED)
{
mcpu_cpu_opt = &opt->value;
if (ext != NULL)
- if (!aarch64_parse_features (ext, &mcpu_cpu_opt))
+ if (!aarch64_parse_features (ext, &mcpu_cpu_opt, FALSE))
return;
cpu_variant = *mcpu_cpu_opt;
@@ -7620,6 +7625,28 @@ s_aarch64_arch (int ignored ATTRIBUTE_UNUSED)
ignore_rest_of_line ();
}
+/* Parse a .arch_extension directive. */
+
+static void
+s_aarch64_arch_extension (int ignored ATTRIBUTE_UNUSED)
+{
+ char saved_char;
+ char *ext = input_line_pointer;;
+
+ while (*input_line_pointer && !ISSPACE (*input_line_pointer))
+ input_line_pointer++;
+ saved_char = *input_line_pointer;
+ *input_line_pointer = 0;
+
+ if (!aarch64_parse_features (ext, &mcpu_cpu_opt, TRUE))
+ return;
+
+ cpu_variant = *mcpu_cpu_opt;
+
+ *input_line_pointer = saved_char;
+ demand_empty_rest_of_line ();
+}
+
/* Copy symbol information. */
void