static int arm_gen_constant (enum rtx_code, machine_mode, rtx,
HOST_WIDE_INT, rtx, rtx, int, int);
static unsigned bit_count (unsigned long);
+static unsigned feature_count (const arm_feature_set*);
static int arm_address_register_rtx_p (rtx, int);
static int arm_legitimate_index_p (machine_mode, rtx, RTX_CODE, int);
static bool is_called_in_ARM_mode (tree);
/* The bits in this mask specify which
instructions we are allowed to generate. */
-unsigned long insn_flags = 0;
+arm_feature_set insn_flags = ARM_FSET_EMPTY;
/* The bits in this mask specify which instruction scheduling options should
be used. */
-unsigned long tune_flags = 0;
+arm_feature_set tune_flags = ARM_FSET_EMPTY;
/* The highest ARM architecture version supported by the
target. */
enum processor_type core;
const char *arch;
enum base_architecture base_arch;
- const unsigned long flags;
+ const arm_feature_set flags;
const struct tune_params *const tune;
};
/* ARM Cores */
#define ARM_CORE(NAME, X, IDENT, ARCH, FLAGS, COSTS) \
{NAME, IDENT, #ARCH, BASE_ARCH_##ARCH, \
- FLAGS, &arm_##COSTS##_tune},
+ ARM_FSET_MAKE_CPU1 (FLAGS), &arm_##COSTS##_tune},
#include "arm-cores.def"
#undef ARM_CORE
- {NULL, arm_none, NULL, BASE_ARCH_0, 0, NULL}
+ {NULL, arm_none, NULL, BASE_ARCH_0, ARM_FSET_EMPTY, NULL}
};
static const struct processors all_architectures[] =
from the core. */
#define ARM_ARCH(NAME, CORE, ARCH, FLAGS) \
- {NAME, CORE, #ARCH, BASE_ARCH_##ARCH, FLAGS, NULL},
+ {NAME, CORE, #ARCH, BASE_ARCH_##ARCH, ARM_FSET_MAKE_CPU1 (FLAGS), NULL},
#include "arm-arches.def"
#undef ARM_ARCH
- {NULL, arm_none, NULL, BASE_ARCH_0, 0, NULL}
+ {NULL, arm_none, NULL, BASE_ARCH_0, ARM_FSET_EMPTY, NULL}
};
return count;
}
+/* Return the number of features in feature-set SET. */
+static unsigned
+feature_count (const arm_feature_set * set)
+{
+ return (bit_count (ARM_FSET_CPU1 (*set))
+ + bit_count (ARM_FSET_CPU2 (*set)));
+}
+
typedef struct
{
machine_mode mode;
/* Make sure that the processor choice does not conflict with any of the
other command line choices. */
- if (TARGET_ARM_P (flags) && !(insn_flags & FL_NOTM))
+ if (TARGET_ARM_P (flags) && !ARM_FSET_HAS_CPU1 (insn_flags, FL_NOTM))
error ("target CPU does not support ARM mode");
/* TARGET_BACKTRACE calls leaf_function_p, which causes a crash if done
arm_option_override_internal (struct gcc_options *opts,
struct gcc_options *opts_set)
{
- if (TARGET_THUMB_P (opts->x_target_flags) && !(insn_flags & FL_THUMB))
+ if (TARGET_THUMB_P (opts->x_target_flags)
+ && !(ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB)))
{
warning (0, "target CPU does not support THUMB instructions");
opts->x_target_flags &= ~MASK_THUMB;
{
if (arm_selected_cpu)
{
+ const arm_feature_set tuning_flags = ARM_FSET_MAKE_CPU1 (FL_TUNE);
+ arm_feature_set selected_flags;
+ ARM_FSET_XOR (selected_flags, arm_selected_cpu->flags,
+ arm_selected_arch->flags);
+ ARM_FSET_EXCLUDE (selected_flags, selected_flags, tuning_flags);
/* Check for conflict between mcpu and march. */
- if ((arm_selected_cpu->flags ^ arm_selected_arch->flags) & ~FL_TUNE)
+ if (!ARM_FSET_IS_EMPTY (selected_flags))
{
warning (0, "switch -mcpu=%s conflicts with -march=%s switch",
arm_selected_cpu->name, arm_selected_arch->name);
if (!arm_selected_cpu)
{
const struct processors * sel;
- unsigned int sought;
+ arm_feature_set sought = ARM_FSET_EMPTY;;
arm_selected_cpu = &all_cores[TARGET_CPU_DEFAULT];
if (!arm_selected_cpu->name)
/* Now check to see if the user has specified some command line
switch that require certain abilities from the cpu. */
- sought = 0;
if (TARGET_INTERWORK || TARGET_THUMB)
{
- sought |= (FL_THUMB | FL_MODE32);
+ ARM_FSET_ADD_CPU1 (sought, FL_THUMB);
+ ARM_FSET_ADD_CPU1 (sought, FL_MODE32);
/* There are no ARM processors that support both APCS-26 and
interworking. Therefore we force FL_MODE26 to be removed
from insn_flags here (if it was set), so that the search
below will always be able to find a compatible processor. */
- insn_flags &= ~FL_MODE26;
+ ARM_FSET_DEL_CPU1 (insn_flags, FL_MODE26);
}
- if (sought != 0 && ((sought & insn_flags) != sought))
+ if (!ARM_FSET_IS_EMPTY (sought)
+ && !(ARM_FSET_CPU_SUBSET (sought, insn_flags)))
{
/* Try to locate a CPU type that supports all of the abilities
of the default CPU, plus the extra abilities requested by
the user. */
for (sel = all_cores; sel->name != NULL; sel++)
- if ((sel->flags & sought) == (sought | insn_flags))
+ if (ARM_FSET_CPU_SUBSET (sought, sel->flags))
break;
if (sel->name == NULL)
command line options we scan the array again looking
for a best match. */
for (sel = all_cores; sel->name != NULL; sel++)
- if ((sel->flags & sought) == sought)
- {
- unsigned count;
-
- count = bit_count (sel->flags & insn_flags);
-
- if (count >= current_bit_count)
- {
- best_fit = sel;
- current_bit_count = count;
- }
- }
+ {
+ arm_feature_set required = ARM_FSET_EMPTY;
+ ARM_FSET_UNION (required, sought, insn_flags);
+ if (ARM_FSET_CPU_SUBSET (required, sel->flags))
+ {
+ unsigned count;
+ arm_feature_set flags;
+ ARM_FSET_INTER (flags, sel->flags, insn_flags);
+ count = feature_count (&flags);
+ if (count >= current_bit_count)
+ {
+ best_fit = sel;
+ current_bit_count = count;
+ }
+ }
+ }
gcc_assert (best_fit);
sel = best_fit;
}
/* BPABI targets use linker tricks to allow interworking on cores
without thumb support. */
- if (TARGET_INTERWORK && !((insn_flags & FL_THUMB) || TARGET_BPABI))
+ if (TARGET_INTERWORK
+ && !(ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB) || TARGET_BPABI))
{
warning (0, "target CPU does not support interworking" );
target_flags &= ~MASK_INTERWORK;
warning (0, "passing floating point arguments in fp regs not yet supported");
/* Initialize boolean versions of the flags, for use in the arm.md file. */
- arm_arch3m = (insn_flags & FL_ARCH3M) != 0;
- arm_arch4 = (insn_flags & FL_ARCH4) != 0;
- arm_arch4t = arm_arch4 & ((insn_flags & FL_THUMB) != 0);
- arm_arch5 = (insn_flags & FL_ARCH5) != 0;
- arm_arch5e = (insn_flags & FL_ARCH5E) != 0;
- arm_arch6 = (insn_flags & FL_ARCH6) != 0;
- arm_arch6k = (insn_flags & FL_ARCH6K) != 0;
- arm_arch6kz = arm_arch6k && (insn_flags & FL_ARCH6KZ);
- arm_arch_notm = (insn_flags & FL_NOTM) != 0;
+ arm_arch3m = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH3M);
+ arm_arch4 = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH4);
+ arm_arch4t = arm_arch4 && (ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB));
+ arm_arch5 = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH5);
+ arm_arch5e = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH5E);
+ arm_arch6 = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH6);
+ arm_arch6k = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH6K);
+ arm_arch6kz = arm_arch6k && ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH6KZ);
+ arm_arch_notm = ARM_FSET_HAS_CPU1 (insn_flags, FL_NOTM);
arm_arch6m = arm_arch6 && !arm_arch_notm;
- arm_arch7 = (insn_flags & FL_ARCH7) != 0;
- arm_arch7em = (insn_flags & FL_ARCH7EM) != 0;
- arm_arch8 = (insn_flags & FL_ARCH8) != 0;
- arm_arch_thumb2 = (insn_flags & FL_THUMB2) != 0;
- arm_arch_xscale = (insn_flags & FL_XSCALE) != 0;
-
- arm_ld_sched = (tune_flags & FL_LDSCHED) != 0;
- arm_tune_strongarm = (tune_flags & FL_STRONG) != 0;
- arm_tune_wbuf = (tune_flags & FL_WBUF) != 0;
- arm_tune_xscale = (tune_flags & FL_XSCALE) != 0;
- arm_arch_iwmmxt = (insn_flags & FL_IWMMXT) != 0;
- arm_arch_iwmmxt2 = (insn_flags & FL_IWMMXT2) != 0;
- arm_arch_thumb_hwdiv = (insn_flags & FL_THUMB_DIV) != 0;
- arm_arch_arm_hwdiv = (insn_flags & FL_ARM_DIV) != 0;
- arm_arch_no_volatile_ce = (insn_flags & FL_NO_VOLATILE_CE) != 0;
+ arm_arch7 = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH7);
+ arm_arch7em = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH7EM);
+ arm_arch8 = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH8);
+ arm_arch_thumb2 = ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB2);
+ arm_arch_xscale = ARM_FSET_HAS_CPU1 (insn_flags, FL_XSCALE);
+
+ arm_ld_sched = ARM_FSET_HAS_CPU1 (tune_flags, FL_LDSCHED);
+ arm_tune_strongarm = ARM_FSET_HAS_CPU1 (tune_flags, FL_STRONG);
+ arm_tune_wbuf = ARM_FSET_HAS_CPU1 (tune_flags, FL_WBUF);
+ arm_tune_xscale = ARM_FSET_HAS_CPU1 (tune_flags, FL_XSCALE);
+ arm_arch_iwmmxt = ARM_FSET_HAS_CPU1 (insn_flags, FL_IWMMXT);
+ arm_arch_iwmmxt2 = ARM_FSET_HAS_CPU1 (insn_flags, FL_IWMMXT2);
+ arm_arch_thumb_hwdiv = ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB_DIV);
+ arm_arch_arm_hwdiv = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARM_DIV);
+ arm_arch_no_volatile_ce = ARM_FSET_HAS_CPU1 (insn_flags, FL_NO_VOLATILE_CE);
arm_tune_cortex_a9 = (arm_tune == cortexa9) != 0;
- arm_arch_crc = (insn_flags & FL_CRC32) != 0;
- arm_m_profile_small_mul = (insn_flags & FL_SMALLMUL) != 0;
+ arm_arch_crc = ARM_FSET_HAS_CPU1 (insn_flags, FL_CRC32);
+ arm_m_profile_small_mul = ARM_FSET_HAS_CPU1 (insn_flags, FL_SMALLMUL);
/* V5 code we generate is completely interworking capable, so we turn off
TARGET_INTERWORK here to avoid many tests later on. */
/* For arm2/3 there is no need to do any scheduling if we are doing
software floating-point. */
- if (TARGET_SOFT_FLOAT && (tune_flags & FL_MODE32) == 0)
+ if (TARGET_SOFT_FLOAT && !ARM_FSET_HAS_CPU1 (tune_flags, FL_MODE32))
flag_schedule_insns = flag_schedule_insns_after_reload = 0;
/* Use the cp15 method if it is available. */