* 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.
This commit is contained in:
Matthew Gretton-Dann 2010-09-23 15:11:56 +00:00
parent 78336cd61f
commit 6913386316
3 changed files with 202 additions and 26 deletions

View File

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

View File

@ -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;
};
/* The following table must be in alphabetical order with a NULL last entry.
*/
static const struct arm_option_extension_value_table arm_extensions[] =
{
{"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;
};
static const struct arm_option_cpu_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}
};
/* 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;

View File

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