aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Gretton-Dann <matthew.gretton-dann@arm.com>2010-09-23 15:11:56 +0000
committerMatthew Gretton-Dann <matthew.gretton-dann@arm.com>2010-09-23 15:11:56 +0000
commit691338631685cad7a3b8d8e330df408c999e423a (patch)
tree9f47bbcf3a3aca9070749bf8304e4952adcf8837
parent78336cd61ff68d284420bb8c5498ffc125579ed3 (diff)
downloadgdb-691338631685cad7a3b8d8e330df408c999e423a.zip
gdb-691338631685cad7a3b8d8e330df408c999e423a.tar.gz
gdb-691338631685cad7a3b8d8e330df408c999e423a.tar.bz2
* gas/config/tc-arm.c (md_pseduo_table): Add .arch_extension directive.
(arm_option_extension_value_table): Add. (arm_extensions): Change type. (arm_option_cpu_table): Rename... (arm_option_fpu_table): ...to this. (arm_fpus): Change type. (arm_parse_extension): Enforce alphabetical order. Allow extensions to be removed. (arm_parse_arch): Allow extensions to be specified with -march. (s_arm_arch_extension): Add. (s_arm_fpu): Update for type changes. * gas/doc/c-arm.texi: Document changes to infrastructure.
-rw-r--r--gas/ChangeLog15
-rw-r--r--gas/config/tc-arm.c170
-rw-r--r--gas/doc/c-arm.texi37
3 files changed, 199 insertions, 23 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 0df70c7..70015a0 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,18 @@
+2010-09-23 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
+
+ * config/tc-arm.c (md_pseduo_table): Add .arch_extension directive.
+ (arm_option_extension_value_table): Add.
+ (arm_extensions): Change type.
+ (arm_option_cpu_table): Rename...
+ (arm_option_fpu_table): ...to this.
+ (arm_fpus): Change type.
+ (arm_parse_extension): Enforce alphabetical order. Allow
+ extensions to be removed.
+ (arm_parse_arch): Allow extensions to be specified with -march.
+ (s_arm_arch_extension): Add.
+ (s_arm_fpu): Update for type changes.
+ * doc/c-arm.texi: Document changes to infrastructure.
+
2010-09-23 Alan Modra <amodra@gmail.com>
* config/tc-mn10300.c (tc_gen_reloc): Replace absolute symbols
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 136e04e..fde0bc4 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -4270,6 +4270,7 @@ static void s_arm_arch (int);
static void s_arm_object_arch (int);
static void s_arm_cpu (int);
static void s_arm_fpu (int);
+static void s_arm_arch_extension (int);
#ifdef TE_PE
@@ -4323,6 +4324,7 @@ const pseudo_typeS md_pseudo_table[] =
{ "arch", s_arm_arch, 0 },
{ "object_arch", s_arm_object_arch, 0 },
{ "fpu", s_arm_fpu, 0 },
+ { "arch_extension", s_arm_arch_extension, 0 },
#ifdef OBJ_ELF
{ "word", s_arm_elf_cons, 4 },
{ "long", s_arm_elf_cons, 4 },
@@ -22451,25 +22453,35 @@ static const struct arm_arch_option_table arm_archs[] =
{NULL, ARM_ARCH_NONE, ARM_ARCH_NONE}
};
-/* ISA extensions in the co-processor space. */
-struct arm_option_cpu_value_table
+/* ISA extensions in the co-processor and main instruction set space. */
+struct arm_option_extension_value_table
{
char *name;
const arm_feature_set value;
+ const arm_feature_set allowed_archs;
};
-static const struct arm_option_cpu_value_table arm_extensions[] =
+/* The following table must be in alphabetical order with a NULL last entry.
+ */
+static const struct arm_option_extension_value_table arm_extensions[] =
{
- {"maverick", ARM_FEATURE (0, ARM_CEXT_MAVERICK)},
- {"xscale", ARM_FEATURE (0, ARM_CEXT_XSCALE)},
- {"iwmmxt", ARM_FEATURE (0, ARM_CEXT_IWMMXT)},
- {"iwmmxt2", ARM_FEATURE (0, ARM_CEXT_IWMMXT2)},
- {NULL, ARM_ARCH_NONE}
+ {"iwmmxt", ARM_FEATURE (0, ARM_CEXT_IWMMXT), ARM_ANY},
+ {"iwmmxt2", ARM_FEATURE (0, ARM_CEXT_IWMMXT2), ARM_ANY},
+ {"maverick", ARM_FEATURE (0, ARM_CEXT_MAVERICK), ARM_ANY},
+ {"xscale", ARM_FEATURE (0, ARM_CEXT_XSCALE), ARM_ANY},
+ {NULL, ARM_ARCH_NONE, ARM_ARCH_NONE}
+};
+
+/* ISA floating-point and Advanced SIMD extensions. */
+struct arm_option_fpu_value_table
+{
+ char *name;
+ const arm_feature_set value;
};
/* This list should, at a minimum, contain all the fpu names
recognized by GCC. */
-static const struct arm_option_cpu_value_table arm_fpus[] =
+static const struct arm_option_fpu_value_table arm_fpus[] =
{
{"softfpa", FPU_NONE},
{"fpe", FPU_ARCH_FPE},
@@ -22547,15 +22559,23 @@ arm_parse_extension (char * str, const arm_feature_set **opt_p)
arm_feature_set *ext_set = (arm_feature_set *)
xmalloc (sizeof (arm_feature_set));
+ /* We insist on extensions being specified in alphabetical order, and with
+ extensions being added before being removed. We achieve this by having
+ the global ARM_EXTENSIONS table in alphabetical order, and 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. */
+ const struct arm_option_extension_value_table * opt = NULL;
+ int adding_value = -1;
+
/* Copy the feature set, so that we can modify it. */
*ext_set = **opt_p;
*opt_p = ext_set;
while (str != NULL && *str != 0)
{
- const struct arm_option_cpu_value_table * opt;
char * ext;
- int optlen;
+ size_t optlen;
if (*str != '+')
{
@@ -22571,24 +22591,86 @@ arm_parse_extension (char * str, const arm_feature_set **opt_p)
else
optlen = strlen (str);
+ if (optlen >= 2
+ && strncmp (str, "no", 2) == 0)
+ {
+ if (adding_value != 0)
+ {
+ adding_value = 0;
+ opt = arm_extensions;
+ }
+
+ optlen -= 2;
+ str += 2;
+ }
+ else if (optlen > 0)
+ {
+ if (adding_value == -1)
+ {
+ adding_value = 1;
+ opt = arm_extensions;
+ }
+ else if (adding_value != 1)
+ {
+ as_bad (_("must specify extensions to add before specifying "
+ "those to remove"));
+ return FALSE;
+ }
+ }
+
if (optlen == 0)
{
as_bad (_("missing architectural extension"));
return FALSE;
}
- for (opt = arm_extensions; opt->name != NULL; opt++)
- if (strncmp (opt->name, str, optlen) == 0)
+ gas_assert (adding_value != -1);
+ gas_assert (opt != NULL);
+
+ /* Scan over the options table trying to find an exact match. */
+ for (; opt->name != NULL; opt++)
+ if (strncmp (opt->name, str, optlen) == 0
+ && strlen (opt->name) == optlen)
{
- ARM_MERGE_FEATURE_SETS (*ext_set, *ext_set, opt->value);
+ /* Check we can apply the extension to this architecture. */
+ if (!ARM_CPU_HAS_FEATURE (*ext_set, opt->allowed_archs))
+ {
+ as_bad (_("extension does not apply to the base architecture"));
+ return FALSE;
+ }
+
+ /* Add or remove the extension. */
+ if (adding_value)
+ ARM_MERGE_FEATURE_SETS (*ext_set, *ext_set, opt->value);
+ else
+ ARM_CLEAR_FEATURE (*ext_set, *ext_set, opt->value);
+
break;
}
if (opt->name == NULL)
{
- as_bad (_("unknown architectural extension `%s'"), str);
+ /* Did we fail to find an extension because it wasn't specified in
+ alphabetical order, or because it does not exist? */
+
+ for (opt = arm_extensions; opt->name != NULL; opt++)
+ if (strncmp (opt->name, str, optlen) == 0)
+ break;
+
+ if (opt->name == NULL)
+ as_bad (_("unknown architectural extension `%s'"), str);
+ else
+ as_bad (_("architectural extensions must be specified in "
+ "alphabetical order"));
+
return FALSE;
}
+ else
+ {
+ /* We should skip the extension we've just matched the next time
+ round. */
+ opt++;
+ }
str = ext;
};
@@ -22659,7 +22741,7 @@ arm_parse_arch (char * str)
}
for (opt = arm_archs; opt->name != NULL; opt++)
- if (streq (opt->name, str))
+ if (strncmp (opt->name, str, optlen) == 0)
{
march_cpu_opt = &opt->value;
march_fpu_opt = &opt->default_fpu;
@@ -22678,7 +22760,7 @@ arm_parse_arch (char * str)
static bfd_boolean
arm_parse_fpu (char * str)
{
- const struct arm_option_cpu_value_table * opt;
+ const struct arm_option_fpu_value_table * opt;
for (opt = arm_fpus; opt->name != NULL; opt++)
if (streq (opt->name, str))
@@ -23183,12 +23265,64 @@ s_arm_object_arch (int ignored ATTRIBUTE_UNUSED)
ignore_rest_of_line ();
}
+/* Parse a .arch_extension directive. */
+
+static void
+s_arm_arch_extension (int ignored ATTRIBUTE_UNUSED)
+{
+ const struct arm_option_extension_value_table *opt;
+ char saved_char;
+ char *name;
+ int adding_value = 1;
+
+ name = input_line_pointer;
+ while (*input_line_pointer && !ISSPACE (*input_line_pointer))
+ input_line_pointer++;
+ saved_char = *input_line_pointer;
+ *input_line_pointer = 0;
+
+ if (strlen (name) >= 2
+ && strncmp (name, "no", 2) == 0)
+ {
+ adding_value = 0;
+ name += 2;
+ }
+
+ for (opt = arm_extensions; opt->name != NULL; opt++)
+ if (streq (opt->name, name))
+ {
+ if (!ARM_CPU_HAS_FEATURE (*mcpu_cpu_opt, opt->allowed_archs))
+ {
+ as_bad (_("architectural extension `%s' is not allowed for the "
+ "current base architecture"), name);
+ break;
+ }
+
+ if (adding_value)
+ ARM_MERGE_FEATURE_SETS (selected_cpu, selected_cpu, opt->value);
+ else
+ ARM_CLEAR_FEATURE (selected_cpu, selected_cpu, opt->value);
+
+ mcpu_cpu_opt = &selected_cpu;
+ ARM_MERGE_FEATURE_SETS (cpu_variant, *mcpu_cpu_opt, *mfpu_opt);
+ *input_line_pointer = saved_char;
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if (opt->name == NULL)
+ as_bad (_("unknown architecture `%s'\n"), name);
+
+ *input_line_pointer = saved_char;
+ ignore_rest_of_line ();
+}
+
/* Parse a .fpu directive. */
static void
s_arm_fpu (int ignored ATTRIBUTE_UNUSED)
{
- const struct arm_option_cpu_value_table *opt;
+ const struct arm_option_fpu_value_table *opt;
char saved_char;
char *name;
diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi
index f64b554..479d6fa 100644
--- a/gas/doc/c-arm.texi
+++ b/gas/doc/c-arm.texi
@@ -133,12 +133,24 @@ assembler to accept instructions valid for any ARM processor.
In addition to the basic instruction set, the assembler can be told to
accept various extension mnemonics that extend the processor using the
co-processor instruction space. For example, @code{-mcpu=arm920+maverick}
-is equivalent to specifying @code{-mcpu=ep9312}. The following extensions
-are currently supported:
-@code{+maverick}
-@code{+iwmmxt}
+is equivalent to specifying @code{-mcpu=ep9312}.
+
+Multiple extensions may be specified, separated by a @code{+}. The
+extensions should be specified in ascending alphabetical order.
+
+Extension mnemonics may also be removed from those the assembler accepts.
+This is done be prepending @code{no} to the option that adds the extension.
+Extensions that are removed should be listed after all extensions which have
+been added, again in ascending alphabetical order. For example,
+@code{-mcpu=ep9312+nomaverick} is equivalent to specifying @code{-mcpu=arm920}.
+
+
+The following extensions are currently supported:
+@code{iwmmxt},
+@code{iwmmxt2},
+@code{maverick},
and
-@code{+xscale}.
+@code{xscale}.
@cindex @code{-march=} command line option, ARM
@item -march=@var{architecture}[+@var{extension}@dots{}]
@@ -503,6 +515,18 @@ boundary). This is for compatibility with ARM's own assembler.
Select the target architecture. Valid values for @var{name} are the same as
for the @option{-march} commandline option.
+Specifying @code{.arch} clears any previously selected architecture
+extensions.
+
+@cindex @code{.arch_extension} directive, ARM
+@item .arch_extension @var{name}
+Add or remove an architecture extension to the target architecture. Valid
+values for @var{name} are the same as those accepted as architectural
+extensions by the @option{-mcpu} commandline option.
+
+@code{.arch_extension} may be used multiple times to add or remove extensions
+incrementally to the architecture being compiled for.
+
@cindex @code{.arm} directive, ARM
@item .arm
This performs the same action as @var{.code 32}.
@@ -537,6 +561,9 @@ selects Thumb, with the value 32 selecting ARM.
Select the target processor. Valid values for @var{name} are the same as
for the @option{-mcpu} commandline option.
+Specifying @code{.cpu} clears any previously selected architecture
+extensions.
+
@c DDDDDDDDDDDDDDDDDDDDDDDDDD
@cindex @code{.dn} and @code{.qn} directives, ARM