typedef struct minipool_node Mnode;
typedef struct minipool_fixup Mfix;
-/* The last .arch and .fpu assembly strings that we printed. */
-static std::string arm_last_printed_arch_string;
-static std::string arm_last_printed_fpu_string;
-
void (*arm_lang_output_object_attributes_hook)(void);
struct four_ints
vec<machine_mode> &,
vec<const char *> &, vec<rtx> &,
HARD_REG_SET &, location_t);
+static const char *arm_identify_fpu_from_isa (sbitmap);
\f
/* Table of machine attributes. */
static const struct attribute_spec arm_attribute_table[] =
bitmap_ior (target->isa, target->isa, fpu_bits);
}
+ /* If we have the soft-float ABI, clear any feature bits relating to use of
+ floating-point operations. They'll just confuse things later on. */
+ if (arm_float_abi == ARM_FLOAT_ABI_SOFT)
+ bitmap_and_compl (target->isa, target->isa, isa_all_fpbits);
+
/* There may be implied bits which we still need to enable. These are
non-named features which are needed to complete other sets of features,
but cannot be enabled from arm-cpus.in due to being shared between
(int) current_tune->sched_autopref);
}
+/* The last set of target options used to emit .arch directives, etc. This
+ could be a function-local static if it were not required to expose it as a
+ root to the garbage collector. */
+static GTY(()) cl_target_option *last_asm_targ_options = NULL;
+
/* Print .arch and .arch_extension directives corresponding to the
current architecture configuration. */
static void
-arm_print_asm_arch_directives ()
+arm_print_asm_arch_directives (FILE *stream, cl_target_option *targ_options)
{
+ arm_build_target build_target;
+ /* If the target options haven't changed since the last time we were called
+ there is nothing to do. This should be sufficient to suppress the
+ majority of redundant work. */
+ if (last_asm_targ_options == targ_options)
+ return;
+
+ last_asm_targ_options = targ_options;
+
+ build_target.isa = sbitmap_alloc (isa_num_bits);
+ arm_configure_build_target (&build_target, targ_options, false);
+
+ if (build_target.core_name
+ && !bitmap_bit_p (build_target.isa, isa_bit_quirk_no_asmcpu))
+ {
+ const char* truncated_name
+ = arm_rewrite_selected_cpu (build_target.core_name);
+ asm_fprintf (stream, "\t.cpu %s\n", truncated_name);
+ }
+
const arch_option *arch
= arm_parse_arch_option_name (all_architectures, "-march",
- arm_active_target.arch_name);
+ build_target.arch_name);
auto_sbitmap opt_bits (isa_num_bits);
gcc_assert (arch);
- asm_fprintf (asm_out_file, "\t.arch %s\n", arm_active_target.arch_name);
- arm_last_printed_arch_string = arm_active_target.arch_name;
+ if (strcmp (build_target.arch_name, "armv7ve") == 0)
+ {
+ /* Keep backward compatability for assemblers which don't support
+ armv7ve. Fortunately, none of the following extensions are reset
+ by a .fpu directive. */
+ asm_fprintf (stream, "\t.arch armv7-a\n");
+ asm_fprintf (stream, "\t.arch_extension virt\n");
+ asm_fprintf (stream, "\t.arch_extension idiv\n");
+ asm_fprintf (stream, "\t.arch_extension sec\n");
+ asm_fprintf (stream, "\t.arch_extension mp\n");
+ }
+ else
+ asm_fprintf (stream, "\t.arch %s\n", build_target.arch_name);
+
+ /* The .fpu directive will reset any architecture extensions from the
+ assembler that relate to the fp/vector extensions. So put this out before
+ any .arch_extension directives. */
+ const char *fpu_name = (TARGET_SOFT_FLOAT
+ ? "softvfp"
+ : arm_identify_fpu_from_isa (build_target.isa));
+ asm_fprintf (stream, "\t.fpu %s\n", fpu_name);
+
if (!arch->common.extensions)
return;
&& !TARGET_HAVE_MVE_FLOAT))
continue;
- /* If every feature bit of this option is set in the target
- ISA specification, print out the option name. However,
- don't print anything if all the bits are part of the
- FPU specification. */
- if (bitmap_subset_p (opt_bits, arm_active_target.isa)
+ /* If every feature bit of this option is set in the target ISA
+ specification, print out the option name. However, don't print
+ anything if all the bits are part of the FPU specification. */
+ if (bitmap_subset_p (opt_bits, build_target.isa)
&& !bitmap_subset_p (opt_bits, isa_all_fpubits_internal))
- asm_fprintf (asm_out_file, "\t.arch_extension %s\n", opt->name);
+ asm_fprintf (stream, "\t.arch_extension %s\n", opt->name);
}
}
}
{
int val;
+ arm_print_asm_arch_directives
+ (asm_out_file, TREE_TARGET_OPTION (target_option_default_node));
+
if (TARGET_BPABI)
{
- /* We don't have a specified CPU. Use the architecture to
- generate the tags.
-
- Note: it might be better to do this unconditionally, then the
- assembler would not need to know about all new CPU names as
- they are added. */
- if (!arm_active_target.core_name)
- {
- /* armv7ve doesn't support any extensions. */
- if (strcmp (arm_active_target.arch_name, "armv7ve") == 0)
- {
- /* Keep backward compatability for assemblers
- which don't support armv7ve. */
- asm_fprintf (asm_out_file, "\t.arch armv7-a\n");
- asm_fprintf (asm_out_file, "\t.arch_extension virt\n");
- asm_fprintf (asm_out_file, "\t.arch_extension idiv\n");
- asm_fprintf (asm_out_file, "\t.arch_extension sec\n");
- asm_fprintf (asm_out_file, "\t.arch_extension mp\n");
- arm_last_printed_arch_string = "armv7ve";
- }
- else
- arm_print_asm_arch_directives ();
- }
- else if (startswith (arm_active_target.core_name, "generic"))
- {
- asm_fprintf (asm_out_file, "\t.arch %s\n",
- arm_active_target.core_name + 8);
- arm_last_printed_arch_string = arm_active_target.core_name + 8;
- }
- else
+ /* If we have a named cpu, but we the assembler does not support that
+ name via .cpu, put out a cpu name attribute; but don't do this if the
+ name starts with the fictitious prefix, 'generic'. */
+ if (arm_active_target.core_name
+ && bitmap_bit_p (arm_active_target.isa, isa_bit_quirk_no_asmcpu)
+ && !startswith (arm_active_target.core_name, "generic"))
{
const char* truncated_name
= arm_rewrite_selected_cpu (arm_active_target.core_name);
if (bitmap_bit_p (arm_active_target.isa, isa_bit_quirk_no_asmcpu))
asm_fprintf (asm_out_file, "\t.eabi_attribute 5, \"%s\"\n",
truncated_name);
- else
- asm_fprintf (asm_out_file, "\t.cpu %s\n", truncated_name);
}
if (print_tune_info)
{
int regno;
+ /* Just in case the last function output in the assembler had non-default
+ architecture directives, we force the assembler state back to the default
+ set, so that any 'calculated' build attributes are based on the default
+ options rather than the special options for that function. */
+ arm_print_asm_arch_directives
+ (asm_out_file, TREE_TARGET_OPTION (target_option_default_node));
+
if (NEED_INDICATE_EXEC_STACK)
/* Add .note.GNU-stack. */
file_end_indicate_exec_stack ();
targ_options = TREE_TARGET_OPTION (target_option_current_node);
gcc_assert (targ_options);
- /* Only update the assembler .arch string if it is distinct from the last
- such string we printed. arch_to_print is set conditionally in case
- targ_options->x_arm_arch_string is NULL which can be the case
- when cc1 is invoked directly without passing -march option. */
- std::string arch_to_print;
- if (targ_options->x_arm_arch_string)
- arch_to_print = targ_options->x_arm_arch_string;
-
- if (arch_to_print != arm_last_printed_arch_string)
- {
- std::string arch_name
- = arch_to_print.substr (0, arch_to_print.find ("+"));
- asm_fprintf (asm_out_file, "\t.arch %s\n", arch_name.c_str ());
- const arch_option *arch
- = arm_parse_arch_option_name (all_architectures, "-march",
- targ_options->x_arm_arch_string);
- auto_sbitmap opt_bits (isa_num_bits);
-
- gcc_assert (arch);
- if (arch->common.extensions)
- {
- for (const struct cpu_arch_extension *opt = arch->common.extensions;
- opt->name != NULL;
- opt++)
- {
- if (!opt->remove)
- {
- arm_initialize_isa (opt_bits, opt->isa_bits);
- /* For the cases "-march=armv8.1-m.main+mve -mfloat-abi=soft"
- and "-march=armv8.1-m.main+mve.fp -mfloat-abi=soft" MVE and
- MVE with floating point instructions is disabled. So the
- following check restricts the printing of ".arch_extension
- mve" and ".arch_extension fp" (for mve.fp) in the assembly
- file. MVE needs this special behaviour because the
- feature bit "mve" and "mve_float" are not part of
- "fpu bits", so they are not cleared when -mfloat-abi=soft
- (i.e nofp) but the marco TARGET_HAVE_MVE and
- TARGET_HAVE_MVE_FLOAT are disabled. */
- if ((bitmap_bit_p (opt_bits, isa_bit_mve) && !TARGET_HAVE_MVE)
- || (bitmap_bit_p (opt_bits, isa_bit_mve_float)
- && !TARGET_HAVE_MVE_FLOAT))
- continue;
- if (bitmap_subset_p (opt_bits, arm_active_target.isa)
- && !bitmap_subset_p (opt_bits, isa_all_fpubits_internal))
- asm_fprintf (asm_out_file, "\t.arch_extension %s\n",
- opt->name);
- }
- }
- }
-
- arm_last_printed_arch_string = arch_to_print;
- }
+ arm_print_asm_arch_directives (stream, targ_options);
fprintf (stream, "\t.syntax unified\n");
else
fprintf (stream, "\t.arm\n");
- std::string fpu_to_print
- = TARGET_SOFT_FLOAT
- ? "softvfp" : arm_identify_fpu_from_isa (arm_active_target.isa);
-
- if (!(!strcmp (fpu_to_print.c_str (), "softvfp") && TARGET_VFP_BASE)
- && (fpu_to_print != arm_last_printed_arch_string))
- {
- asm_fprintf (asm_out_file, "\t.fpu %s\n", fpu_to_print.c_str ());
- arm_last_printed_fpu_string = fpu_to_print;
- }
-
if (TARGET_POKE_FUNCTION_NAME)
arm_poke_function_name (stream, (const char *) name);
}