Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
0 recent contributors

Users who have contributed to this file recently

32534 lines (27903 sloc) 943 KB
/* Output routines for GCC for ARM.
Copyright (C) 1991-2019 Free Software Foundation, Inc.
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
More major hacks by Richard Earnshaw (rearnsha@arm.com).
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3, or (at your
option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#define IN_TARGET_CODE 1
#include "config.h"
#define INCLUDE_STRING
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "rtl.h"
#include "tree.h"
#include "memmodel.h"
#include "cfghooks.h"
#include "df.h"
#include "tm_p.h"
#include "stringpool.h"
#include "attribs.h"
#include "optabs.h"
#include "regs.h"
#include "emit-rtl.h"
#include "recog.h"
#include "cgraph.h"
#include "diagnostic-core.h"
#include "alias.h"
#include "fold-const.h"
#include "stor-layout.h"
#include "calls.h"
#include "varasm.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
#include "reload.h"
#include "explow.h"
#include "expr.h"
#include "cfgrtl.h"
#include "sched-int.h"
#include "common/common-target.h"
#include "langhooks.h"
#include "intl.h"
#include "libfuncs.h"
#include "opts.h"
#include "dumpfile.h"
#include "target-globals.h"
#include "builtins.h"
#include "tm-constrs.h"
#include "rtl-iter.h"
#include "optabs-libfuncs.h"
#include "gimplify.h"
#include "gimple.h"
#include "selftest.h"
/* This file should be included last. */
#include "target-def.h"
/* Forward definitions of types. */
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
{
int i[4];
};
/* Forward function declarations. */
static bool arm_const_not_ok_for_debug_p (rtx);
static int arm_needs_doubleword_align (machine_mode, const_tree);
static int arm_compute_static_chain_stack_bytes (void);
static arm_stack_offsets *arm_get_frame_offsets (void);
static void arm_compute_frame_layout (void);
static void arm_add_gc_roots (void);
static int arm_gen_constant (enum rtx_code, machine_mode, rtx,
unsigned HOST_WIDE_INT, rtx, rtx, int, int);
static unsigned bit_count (unsigned long);
static unsigned bitmap_popcount (const sbitmap);
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);
static int thumb2_legitimate_index_p (machine_mode, rtx, int);
static int thumb1_base_register_rtx_p (rtx, machine_mode, int);
static rtx arm_legitimize_address (rtx, rtx, machine_mode);
static reg_class_t arm_preferred_reload_class (rtx, reg_class_t);
static rtx thumb_legitimize_address (rtx, rtx, machine_mode);
inline static int thumb1_index_register_rtx_p (rtx, int);
static int thumb_far_jump_used_p (void);
static bool thumb_force_lr_save (void);
static unsigned arm_size_return_regs (void);
static bool arm_assemble_integer (rtx, unsigned int, int);
static void arm_print_operand (FILE *, rtx, int);
static void arm_print_operand_address (FILE *, machine_mode, rtx);
static bool arm_print_operand_punct_valid_p (unsigned char code);
static const char *fp_const_from_val (REAL_VALUE_TYPE *);
static arm_cc get_arm_condition_code (rtx);
static bool arm_fixed_condition_code_regs (unsigned int *, unsigned int *);
static const char *output_multi_immediate (rtx *, const char *, const char *,
int, HOST_WIDE_INT);
static const char *shift_op (rtx, HOST_WIDE_INT *);
static struct machine_function *arm_init_machine_status (void);
static void thumb_exit (FILE *, int);
static HOST_WIDE_INT get_jump_table_size (rtx_jump_table_data *);
static Mnode *move_minipool_fix_forward_ref (Mnode *, Mnode *, HOST_WIDE_INT);
static Mnode *add_minipool_forward_ref (Mfix *);
static Mnode *move_minipool_fix_backward_ref (Mnode *, Mnode *, HOST_WIDE_INT);
static Mnode *add_minipool_backward_ref (Mfix *);
static void assign_minipool_offsets (Mfix *);
static void arm_print_value (FILE *, rtx);
static void dump_minipool (rtx_insn *);
static int arm_barrier_cost (rtx_insn *);
static Mfix *create_fix_barrier (Mfix *, HOST_WIDE_INT);
static void push_minipool_barrier (rtx_insn *, HOST_WIDE_INT);
static void push_minipool_fix (rtx_insn *, HOST_WIDE_INT, rtx *,
machine_mode, rtx);
static void arm_reorg (void);
static void note_invalid_constants (rtx_insn *, HOST_WIDE_INT, int);
static unsigned long arm_compute_save_reg0_reg12_mask (void);
static unsigned long arm_compute_save_core_reg_mask (void);
static unsigned long arm_isr_value (tree);
static unsigned long arm_compute_func_type (void);
static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree arm_handle_pcs_attribute (tree *, tree, tree, int, bool *);
static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *);
#endif
static tree arm_handle_cmse_nonsecure_entry (tree *, tree, tree, int, bool *);
static tree arm_handle_cmse_nonsecure_call (tree *, tree, tree, int, bool *);
static void arm_output_function_epilogue (FILE *);
static void arm_output_function_prologue (FILE *);
static int arm_comp_type_attributes (const_tree, const_tree);
static void arm_set_default_type_attributes (tree);
static int arm_adjust_cost (rtx_insn *, int, rtx_insn *, int, unsigned int);
static int arm_sched_reorder (FILE *, int, rtx_insn **, int *, int);
static int optimal_immediate_sequence (enum rtx_code code,
unsigned HOST_WIDE_INT val,
struct four_ints *return_sequence);
static int optimal_immediate_sequence_1 (enum rtx_code code,
unsigned HOST_WIDE_INT val,
struct four_ints *return_sequence,
int i);
static int arm_get_strip_length (int);
static bool arm_function_ok_for_sibcall (tree, tree);
static machine_mode arm_promote_function_mode (const_tree,
machine_mode, int *,
const_tree, int);
static bool arm_return_in_memory (const_tree, const_tree);
static rtx arm_function_value (const_tree, const_tree, bool);
static rtx arm_libcall_value_1 (machine_mode);
static rtx arm_libcall_value (machine_mode, const_rtx);
static bool arm_function_value_regno_p (const unsigned int);
static void arm_internal_label (FILE *, const char *, unsigned long);
static void arm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
tree);
static bool arm_have_conditional_execution (void);
static bool arm_cannot_force_const_mem (machine_mode, rtx);
static bool arm_legitimate_constant_p (machine_mode, rtx);
static bool arm_rtx_costs (rtx, machine_mode, int, int, int *, bool);
static int arm_insn_cost (rtx_insn *, bool);
static int arm_address_cost (rtx, machine_mode, addr_space_t, bool);
static int arm_register_move_cost (machine_mode, reg_class_t, reg_class_t);
static int arm_memory_move_cost (machine_mode, reg_class_t, bool);
static void emit_constant_insn (rtx cond, rtx pattern);
static rtx_insn *emit_set_insn (rtx, rtx);
static rtx emit_multi_reg_push (unsigned long, unsigned long);
static int arm_arg_partial_bytes (cumulative_args_t,
const function_arg_info &);
static rtx arm_function_arg (cumulative_args_t, const function_arg_info &);
static void arm_function_arg_advance (cumulative_args_t,
const function_arg_info &);
static pad_direction arm_function_arg_padding (machine_mode, const_tree);
static unsigned int arm_function_arg_boundary (machine_mode, const_tree);
static rtx aapcs_allocate_return_reg (machine_mode, const_tree,
const_tree);
static rtx aapcs_libcall_value (machine_mode);
static int aapcs_select_return_coproc (const_tree, const_tree);
#ifdef OBJECT_FORMAT_ELF
static void arm_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED;
static void arm_elf_asm_destructor (rtx, int) ATTRIBUTE_UNUSED;
#endif
#ifndef ARM_PE
static void arm_encode_section_info (tree, rtx, int);
#endif
static void arm_file_end (void);
static void arm_file_start (void);
static void arm_insert_attributes (tree, tree *);
static void arm_setup_incoming_varargs (cumulative_args_t,
const function_arg_info &, int *, int);
static bool arm_pass_by_reference (cumulative_args_t,
const function_arg_info &);
static bool arm_promote_prototypes (const_tree);
static bool arm_default_short_enums (void);
static bool arm_align_anon_bitfield (void);
static bool arm_return_in_msb (const_tree);
static bool arm_must_pass_in_stack (const function_arg_info &);
static bool arm_return_in_memory (const_tree, const_tree);
#if ARM_UNWIND_INFO
static void arm_unwind_emit (FILE *, rtx_insn *);
static bool arm_output_ttype (rtx);
static void arm_asm_emit_except_personality (rtx);
#endif
static void arm_asm_init_sections (void);
static rtx arm_dwarf_register_span (rtx);
static tree arm_cxx_guard_type (void);
static bool arm_cxx_guard_mask_bit (void);
static tree arm_get_cookie_size (tree);
static bool arm_cookie_has_size (void);
static bool arm_cxx_cdtor_returns_this (void);
static bool arm_cxx_key_method_may_be_inline (void);
static void arm_cxx_determine_class_data_visibility (tree);
static bool arm_cxx_class_data_always_comdat (void);
static bool arm_cxx_use_aeabi_atexit (void);
static void arm_init_libfuncs (void);
static tree arm_build_builtin_va_list (void);
static void arm_expand_builtin_va_start (tree, rtx);
static tree arm_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
static void arm_option_override (void);
static void arm_option_save (struct cl_target_option *, struct gcc_options *);
static void arm_option_restore (struct gcc_options *,
struct cl_target_option *);
static void arm_override_options_after_change (void);
static void arm_option_print (FILE *, int, struct cl_target_option *);
static void arm_set_current_function (tree);
static bool arm_can_inline_p (tree, tree);
static void arm_relayout_function (tree);
static bool arm_valid_target_attribute_p (tree, tree, tree, int);
static unsigned HOST_WIDE_INT arm_shift_truncation_mask (machine_mode);
static bool arm_sched_can_speculate_insn (rtx_insn *);
static bool arm_macro_fusion_p (void);
static bool arm_cannot_copy_insn_p (rtx_insn *);
static int arm_issue_rate (void);
static int arm_sched_variable_issue (FILE *, int, rtx_insn *, int);
static int arm_first_cycle_multipass_dfa_lookahead (void);
static int arm_first_cycle_multipass_dfa_lookahead_guard (rtx_insn *, int);
static void arm_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
static bool arm_output_addr_const_extra (FILE *, rtx);
static bool arm_allocate_stack_slots_for_args (void);
static bool arm_warn_func_return (tree);
static tree arm_promoted_type (const_tree t);
static bool arm_scalar_mode_supported_p (scalar_mode);
static bool arm_frame_pointer_required (void);
static bool arm_can_eliminate (const int, const int);
static void arm_asm_trampoline_template (FILE *);
static void arm_trampoline_init (rtx, tree, rtx);
static rtx arm_trampoline_adjust_address (rtx);
static rtx_insn *arm_pic_static_addr (rtx orig, rtx reg);
static bool cortex_a9_sched_adjust_cost (rtx_insn *, int, rtx_insn *, int *);
static bool xscale_sched_adjust_cost (rtx_insn *, int, rtx_insn *, int *);
static bool fa726te_sched_adjust_cost (rtx_insn *, int, rtx_insn *, int *);
static bool arm_array_mode_supported_p (machine_mode,
unsigned HOST_WIDE_INT);
static machine_mode arm_preferred_simd_mode (scalar_mode);
static bool arm_class_likely_spilled_p (reg_class_t);
static HOST_WIDE_INT arm_vector_alignment (const_tree type);
static bool arm_vector_alignment_reachable (const_tree type, bool is_packed);
static bool arm_builtin_support_vector_misalignment (machine_mode mode,
const_tree type,
int misalignment,
bool is_packed);
static void arm_conditional_register_usage (void);
static enum flt_eval_method arm_excess_precision (enum excess_precision_type);
static reg_class_t arm_preferred_rename_class (reg_class_t rclass);
static unsigned int arm_autovectorize_vector_modes (vector_modes *, bool);
static int arm_default_branch_cost (bool, bool);
static int arm_cortex_a5_branch_cost (bool, bool);
static int arm_cortex_m_branch_cost (bool, bool);
static int arm_cortex_m7_branch_cost (bool, bool);
static bool arm_vectorize_vec_perm_const (machine_mode, rtx, rtx, rtx,
const vec_perm_indices &);
static bool aarch_macro_fusion_pair_p (rtx_insn*, rtx_insn*);
static int arm_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
tree vectype,
int misalign ATTRIBUTE_UNUSED);
static unsigned arm_add_stmt_cost (void *data, int count,
enum vect_cost_for_stmt kind,
struct _stmt_vec_info *stmt_info,
int misalign,
enum vect_cost_model_location where);
static void arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
bool op0_preserve_value);
static unsigned HOST_WIDE_INT arm_asan_shadow_offset (void);
static void arm_sched_fusion_priority (rtx_insn *, int, int *, int*);
static bool arm_can_output_mi_thunk (const_tree, HOST_WIDE_INT, HOST_WIDE_INT,
const_tree);
static section *arm_function_section (tree, enum node_frequency, bool, bool);
static bool arm_asm_elf_flags_numeric (unsigned int flags, unsigned int *num);
static unsigned int arm_elf_section_type_flags (tree decl, const char *name,
int reloc);
static void arm_expand_divmod_libfunc (rtx, machine_mode, rtx, rtx, rtx *, rtx *);
static opt_scalar_float_mode arm_floatn_mode (int, bool);
static unsigned int arm_hard_regno_nregs (unsigned int, machine_mode);
static bool arm_hard_regno_mode_ok (unsigned int, machine_mode);
static bool arm_modes_tieable_p (machine_mode, machine_mode);
static HOST_WIDE_INT arm_constant_alignment (const_tree, HOST_WIDE_INT);
/* Table of machine attributes. */
static const struct attribute_spec arm_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req,
affects_type_identity, handler, exclude } */
/* Function calls made to this symbol must be done indirectly, because
it may lie outside of the 26 bit addressing range of a normal function
call. */
{ "long_call", 0, 0, false, true, true, false, NULL, NULL },
/* Whereas these functions are always known to reside within the 26 bit
addressing range. */
{ "short_call", 0, 0, false, true, true, false, NULL, NULL },
/* Specify the procedure call conventions for a function. */
{ "pcs", 1, 1, false, true, true, false, arm_handle_pcs_attribute,
NULL },
/* Interrupt Service Routines have special prologue and epilogue requirements. */
{ "isr", 0, 1, false, false, false, false, arm_handle_isr_attribute,
NULL },
{ "interrupt", 0, 1, false, false, false, false, arm_handle_isr_attribute,
NULL },
{ "naked", 0, 0, true, false, false, false,
arm_handle_fndecl_attribute, NULL },
#ifdef ARM_PE
/* ARM/PE has three new attributes:
interfacearm - ?
dllexport - for exporting a function/variable that will live in a dll
dllimport - for importing a function/variable from a dll
Microsoft allows multiple declspecs in one __declspec, separating
them with spaces. We do NOT support this. Instead, use __declspec
multiple times.
*/
{ "dllimport", 0, 0, true, false, false, false, NULL, NULL },
{ "dllexport", 0, 0, true, false, false, false, NULL, NULL },
{ "interfacearm", 0, 0, true, false, false, false,
arm_handle_fndecl_attribute, NULL },
#elif TARGET_DLLIMPORT_DECL_ATTRIBUTES
{ "dllimport", 0, 0, false, false, false, false, handle_dll_attribute,
NULL },
{ "dllexport", 0, 0, false, false, false, false, handle_dll_attribute,
NULL },
{ "notshared", 0, 0, false, true, false, false,
arm_handle_notshared_attribute, NULL },
#endif
/* ARMv8-M Security Extensions support. */
{ "cmse_nonsecure_entry", 0, 0, true, false, false, false,
arm_handle_cmse_nonsecure_entry, NULL },
{ "cmse_nonsecure_call", 0, 0, true, false, false, true,
arm_handle_cmse_nonsecure_call, NULL },
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
/* Initialize the GCC target structure. */
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
#undef TARGET_MERGE_DECL_ATTRIBUTES
#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
#endif
#undef TARGET_CHECK_BUILTIN_CALL
#define TARGET_CHECK_BUILTIN_CALL arm_check_builtin_call
#undef TARGET_LEGITIMIZE_ADDRESS
#define TARGET_LEGITIMIZE_ADDRESS arm_legitimize_address
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE arm_attribute_table
#undef TARGET_INSERT_ATTRIBUTES
#define TARGET_INSERT_ATTRIBUTES arm_insert_attributes
#undef TARGET_ASM_FILE_START
#define TARGET_ASM_FILE_START arm_file_start
#undef TARGET_ASM_FILE_END
#define TARGET_ASM_FILE_END arm_file_end
#undef TARGET_ASM_ALIGNED_SI_OP
#define TARGET_ASM_ALIGNED_SI_OP NULL
#undef TARGET_ASM_INTEGER
#define TARGET_ASM_INTEGER arm_assemble_integer
#undef TARGET_PRINT_OPERAND
#define TARGET_PRINT_OPERAND arm_print_operand
#undef TARGET_PRINT_OPERAND_ADDRESS
#define TARGET_PRINT_OPERAND_ADDRESS arm_print_operand_address
#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
#define TARGET_PRINT_OPERAND_PUNCT_VALID_P arm_print_operand_punct_valid_p
#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA arm_output_addr_const_extra
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE arm_output_function_epilogue
#undef TARGET_CAN_INLINE_P
#define TARGET_CAN_INLINE_P arm_can_inline_p
#undef TARGET_RELAYOUT_FUNCTION
#define TARGET_RELAYOUT_FUNCTION arm_relayout_function
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE arm_option_override
#undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
#define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE arm_override_options_after_change
#undef TARGET_OPTION_SAVE
#define TARGET_OPTION_SAVE arm_option_save
#undef TARGET_OPTION_RESTORE
#define TARGET_OPTION_RESTORE arm_option_restore
#undef TARGET_OPTION_PRINT
#define TARGET_OPTION_PRINT arm_option_print
#undef TARGET_COMP_TYPE_ATTRIBUTES
#define TARGET_COMP_TYPE_ATTRIBUTES arm_comp_type_attributes
#undef TARGET_SCHED_CAN_SPECULATE_INSN
#define TARGET_SCHED_CAN_SPECULATE_INSN arm_sched_can_speculate_insn
#undef TARGET_SCHED_MACRO_FUSION_P
#define TARGET_SCHED_MACRO_FUSION_P arm_macro_fusion_p
#undef TARGET_SCHED_MACRO_FUSION_PAIR_P
#define TARGET_SCHED_MACRO_FUSION_PAIR_P aarch_macro_fusion_pair_p
#undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES arm_set_default_type_attributes
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST arm_adjust_cost
#undef TARGET_SET_CURRENT_FUNCTION
#define TARGET_SET_CURRENT_FUNCTION arm_set_current_function
#undef TARGET_OPTION_VALID_ATTRIBUTE_P
#define TARGET_OPTION_VALID_ATTRIBUTE_P arm_valid_target_attribute_p
#undef TARGET_SCHED_REORDER
#define TARGET_SCHED_REORDER arm_sched_reorder
#undef TARGET_REGISTER_MOVE_COST
#define TARGET_REGISTER_MOVE_COST arm_register_move_cost
#undef TARGET_MEMORY_MOVE_COST
#define TARGET_MEMORY_MOVE_COST arm_memory_move_cost
#undef TARGET_ENCODE_SECTION_INFO
#ifdef ARM_PE
#define TARGET_ENCODE_SECTION_INFO arm_pe_encode_section_info
#else
#define TARGET_ENCODE_SECTION_INFO arm_encode_section_info
#endif
#undef TARGET_STRIP_NAME_ENCODING
#define TARGET_STRIP_NAME_ENCODING arm_strip_name_encoding
#undef TARGET_ASM_INTERNAL_LABEL
#define TARGET_ASM_INTERNAL_LABEL arm_internal_label
#undef TARGET_FLOATN_MODE
#define TARGET_FLOATN_MODE arm_floatn_mode
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL arm_function_ok_for_sibcall
#undef TARGET_FUNCTION_VALUE
#define TARGET_FUNCTION_VALUE arm_function_value
#undef TARGET_LIBCALL_VALUE
#define TARGET_LIBCALL_VALUE arm_libcall_value
#undef TARGET_FUNCTION_VALUE_REGNO_P
#define TARGET_FUNCTION_VALUE_REGNO_P arm_function_value_regno_p
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK arm_output_mi_thunk
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK arm_can_output_mi_thunk
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS arm_rtx_costs
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST arm_address_cost
#undef TARGET_INSN_COST
#define TARGET_INSN_COST arm_insn_cost
#undef TARGET_SHIFT_TRUNCATION_MASK
#define TARGET_SHIFT_TRUNCATION_MASK arm_shift_truncation_mask
#undef TARGET_VECTOR_MODE_SUPPORTED_P
#define TARGET_VECTOR_MODE_SUPPORTED_P arm_vector_mode_supported_p
#undef TARGET_ARRAY_MODE_SUPPORTED_P
#define TARGET_ARRAY_MODE_SUPPORTED_P arm_array_mode_supported_p
#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE arm_preferred_simd_mode
#undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES
#define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES \
arm_autovectorize_vector_modes
#undef TARGET_MACHINE_DEPENDENT_REORG
#define TARGET_MACHINE_DEPENDENT_REORG arm_reorg
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS arm_init_builtins
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN arm_expand_builtin
#undef TARGET_BUILTIN_DECL
#define TARGET_BUILTIN_DECL arm_builtin_decl
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS arm_init_libfuncs
#undef TARGET_PROMOTE_FUNCTION_MODE
#define TARGET_PROMOTE_FUNCTION_MODE arm_promote_function_mode
#undef TARGET_PROMOTE_PROTOTYPES
#define TARGET_PROMOTE_PROTOTYPES arm_promote_prototypes
#undef TARGET_PASS_BY_REFERENCE
#define TARGET_PASS_BY_REFERENCE arm_pass_by_reference
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES arm_arg_partial_bytes
#undef TARGET_FUNCTION_ARG
#define TARGET_FUNCTION_ARG arm_function_arg
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE arm_function_arg_advance
#undef TARGET_FUNCTION_ARG_PADDING
#define TARGET_FUNCTION_ARG_PADDING arm_function_arg_padding
#undef TARGET_FUNCTION_ARG_BOUNDARY
#define TARGET_FUNCTION_ARG_BOUNDARY arm_function_arg_boundary
#undef TARGET_SETUP_INCOMING_VARARGS
#define TARGET_SETUP_INCOMING_VARARGS arm_setup_incoming_varargs
#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS arm_allocate_stack_slots_for_args
#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
#define TARGET_ASM_TRAMPOLINE_TEMPLATE arm_asm_trampoline_template
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT arm_trampoline_init
#undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
#define TARGET_TRAMPOLINE_ADJUST_ADDRESS arm_trampoline_adjust_address
#undef TARGET_WARN_FUNC_RETURN
#define TARGET_WARN_FUNC_RETURN arm_warn_func_return
#undef TARGET_DEFAULT_SHORT_ENUMS
#define TARGET_DEFAULT_SHORT_ENUMS arm_default_short_enums
#undef TARGET_ALIGN_ANON_BITFIELD
#define TARGET_ALIGN_ANON_BITFIELD arm_align_anon_bitfield
#undef TARGET_NARROW_VOLATILE_BITFIELD
#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
#undef TARGET_CXX_GUARD_TYPE
#define TARGET_CXX_GUARD_TYPE arm_cxx_guard_type
#undef TARGET_CXX_GUARD_MASK_BIT
#define TARGET_CXX_GUARD_MASK_BIT arm_cxx_guard_mask_bit
#undef TARGET_CXX_GET_COOKIE_SIZE
#define TARGET_CXX_GET_COOKIE_SIZE arm_get_cookie_size
#undef TARGET_CXX_COOKIE_HAS_SIZE
#define TARGET_CXX_COOKIE_HAS_SIZE arm_cookie_has_size
#undef TARGET_CXX_CDTOR_RETURNS_THIS
#define TARGET_CXX_CDTOR_RETURNS_THIS arm_cxx_cdtor_returns_this
#undef TARGET_CXX_KEY_METHOD_MAY_BE_INLINE
#define TARGET_CXX_KEY_METHOD_MAY_BE_INLINE arm_cxx_key_method_may_be_inline
#undef TARGET_CXX_USE_AEABI_ATEXIT
#define TARGET_CXX_USE_AEABI_ATEXIT arm_cxx_use_aeabi_atexit
#undef TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY
#define TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY \
arm_cxx_determine_class_data_visibility
#undef TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT
#define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT arm_cxx_class_data_always_comdat
#undef TARGET_RETURN_IN_MSB
#define TARGET_RETURN_IN_MSB arm_return_in_msb
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY arm_return_in_memory
#undef TARGET_MUST_PASS_IN_STACK
#define TARGET_MUST_PASS_IN_STACK arm_must_pass_in_stack
#if ARM_UNWIND_INFO
#undef TARGET_ASM_UNWIND_EMIT
#define TARGET_ASM_UNWIND_EMIT arm_unwind_emit
/* EABI unwinding tables use a different format for the typeinfo tables. */
#undef TARGET_ASM_TTYPE
#define TARGET_ASM_TTYPE arm_output_ttype
#undef TARGET_ARM_EABI_UNWINDER
#define TARGET_ARM_EABI_UNWINDER true
#undef TARGET_ASM_EMIT_EXCEPT_PERSONALITY
#define TARGET_ASM_EMIT_EXCEPT_PERSONALITY arm_asm_emit_except_personality
#endif /* ARM_UNWIND_INFO */
#undef TARGET_ASM_INIT_SECTIONS
#define TARGET_ASM_INIT_SECTIONS arm_asm_init_sections
#undef TARGET_DWARF_REGISTER_SPAN
#define TARGET_DWARF_REGISTER_SPAN arm_dwarf_register_span
#undef TARGET_CANNOT_COPY_INSN_P
#define TARGET_CANNOT_COPY_INSN_P arm_cannot_copy_insn_p
#ifdef HAVE_AS_TLS
#undef TARGET_HAVE_TLS
#define TARGET_HAVE_TLS true
#endif
#undef TARGET_HAVE_CONDITIONAL_EXECUTION
#define TARGET_HAVE_CONDITIONAL_EXECUTION arm_have_conditional_execution
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P arm_legitimate_constant_p
#undef TARGET_CANNOT_FORCE_CONST_MEM
#define TARGET_CANNOT_FORCE_CONST_MEM arm_cannot_force_const_mem
#undef TARGET_MAX_ANCHOR_OFFSET
#define TARGET_MAX_ANCHOR_OFFSET 4095
/* The minimum is set such that the total size of the block
for a particular anchor is -4088 + 1 + 4095 bytes, which is
divisible by eight, ensuring natural spacing of anchors. */
#undef TARGET_MIN_ANCHOR_OFFSET
#define TARGET_MIN_ANCHOR_OFFSET -4088
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE arm_issue_rate
#undef TARGET_SCHED_VARIABLE_ISSUE
#define TARGET_SCHED_VARIABLE_ISSUE arm_sched_variable_issue
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
arm_first_cycle_multipass_dfa_lookahead
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD \
arm_first_cycle_multipass_dfa_lookahead_guard
#undef TARGET_MANGLE_TYPE
#define TARGET_MANGLE_TYPE arm_mangle_type
#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV arm_atomic_assign_expand_fenv
#undef TARGET_BUILD_BUILTIN_VA_LIST
#define TARGET_BUILD_BUILTIN_VA_LIST arm_build_builtin_va_list
#undef TARGET_EXPAND_BUILTIN_VA_START
#define TARGET_EXPAND_BUILTIN_VA_START arm_expand_builtin_va_start
#undef TARGET_GIMPLIFY_VA_ARG_EXPR
#define TARGET_GIMPLIFY_VA_ARG_EXPR arm_gimplify_va_arg_expr
#ifdef HAVE_AS_TLS
#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
#define TARGET_ASM_OUTPUT_DWARF_DTPREL arm_output_dwarf_dtprel
#endif
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P arm_legitimate_address_p
#undef TARGET_PREFERRED_RELOAD_CLASS
#define TARGET_PREFERRED_RELOAD_CLASS arm_preferred_reload_class
#undef TARGET_PROMOTED_TYPE
#define TARGET_PROMOTED_TYPE arm_promoted_type
#undef TARGET_SCALAR_MODE_SUPPORTED_P
#define TARGET_SCALAR_MODE_SUPPORTED_P arm_scalar_mode_supported_p
#undef TARGET_COMPUTE_FRAME_LAYOUT
#define TARGET_COMPUTE_FRAME_LAYOUT arm_compute_frame_layout
#undef TARGET_FRAME_POINTER_REQUIRED
#define TARGET_FRAME_POINTER_REQUIRED arm_frame_pointer_required
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE arm_can_eliminate
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE arm_conditional_register_usage
#undef TARGET_CLASS_LIKELY_SPILLED_P
#define TARGET_CLASS_LIKELY_SPILLED_P arm_class_likely_spilled_p
#undef TARGET_VECTORIZE_BUILTINS
#define TARGET_VECTORIZE_BUILTINS
#undef TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION
#define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION \
arm_builtin_vectorized_function
#undef TARGET_VECTOR_ALIGNMENT
#define TARGET_VECTOR_ALIGNMENT arm_vector_alignment
#undef TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE
#define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE \
arm_vector_alignment_reachable
#undef TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT
#define TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT \
arm_builtin_support_vector_misalignment
#undef TARGET_PREFERRED_RENAME_CLASS
#define TARGET_PREFERRED_RENAME_CLASS \
arm_preferred_rename_class
#undef TARGET_VECTORIZE_VEC_PERM_CONST
#define TARGET_VECTORIZE_VEC_PERM_CONST arm_vectorize_vec_perm_const
#undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
#define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST \
arm_builtin_vectorization_cost
#undef TARGET_VECTORIZE_ADD_STMT_COST
#define TARGET_VECTORIZE_ADD_STMT_COST arm_add_stmt_cost
#undef TARGET_CANONICALIZE_COMPARISON
#define TARGET_CANONICALIZE_COMPARISON \
arm_canonicalize_comparison
#undef TARGET_ASAN_SHADOW_OFFSET
#define TARGET_ASAN_SHADOW_OFFSET arm_asan_shadow_offset
#undef MAX_INSN_PER_IT_BLOCK
#define MAX_INSN_PER_IT_BLOCK (arm_restrict_it ? 1 : 4)
#undef TARGET_CAN_USE_DOLOOP_P
#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
#undef TARGET_CONST_NOT_OK_FOR_DEBUG_P
#define TARGET_CONST_NOT_OK_FOR_DEBUG_P arm_const_not_ok_for_debug_p
#undef TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS
#define TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS true
#undef TARGET_SCHED_FUSION_PRIORITY
#define TARGET_SCHED_FUSION_PRIORITY arm_sched_fusion_priority
#undef TARGET_ASM_FUNCTION_SECTION
#define TARGET_ASM_FUNCTION_SECTION arm_function_section
#undef TARGET_ASM_ELF_FLAGS_NUMERIC
#define TARGET_ASM_ELF_FLAGS_NUMERIC arm_asm_elf_flags_numeric
#undef TARGET_SECTION_TYPE_FLAGS
#define TARGET_SECTION_TYPE_FLAGS arm_elf_section_type_flags
#undef TARGET_EXPAND_DIVMOD_LIBFUNC
#define TARGET_EXPAND_DIVMOD_LIBFUNC arm_expand_divmod_libfunc
#undef TARGET_C_EXCESS_PRECISION
#define TARGET_C_EXCESS_PRECISION arm_excess_precision
/* Although the architecture reserves bits 0 and 1, only the former is
used for ARM/Thumb ISA selection in v7 and earlier versions. */
#undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2
#undef TARGET_FIXED_CONDITION_CODE_REGS
#define TARGET_FIXED_CONDITION_CODE_REGS arm_fixed_condition_code_regs
#undef TARGET_HARD_REGNO_NREGS
#define TARGET_HARD_REGNO_NREGS arm_hard_regno_nregs
#undef TARGET_HARD_REGNO_MODE_OK
#define TARGET_HARD_REGNO_MODE_OK arm_hard_regno_mode_ok
#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P arm_modes_tieable_p
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS arm_can_change_mode_class
#undef TARGET_CONSTANT_ALIGNMENT
#define TARGET_CONSTANT_ALIGNMENT arm_constant_alignment
#undef TARGET_MD_ASM_ADJUST
#define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
/* Obstack for minipool constant handling. */
static struct obstack minipool_obstack;
static char * minipool_startobj;
/* The maximum number of insns skipped which
will be conditionalised if possible. */
static int max_insns_skipped = 5;
extern FILE * asm_out_file;
/* True if we are currently building a constant table. */
int making_const_table;
/* The processor for which instructions should be scheduled. */
enum processor_type arm_tune = TARGET_CPU_arm_none;
/* The current tuning set. */
const struct tune_params *current_tune;
/* Which floating point hardware to schedule for. */
int arm_fpu_attr;
/* Used for Thumb call_via trampolines. */
rtx thumb_call_via_label[14];
static int thumb_call_reg_needed;
/* The bits in this mask specify which instruction scheduling options should
be used. */
unsigned int tune_flags = 0;
/* The highest ARM architecture version supported by the
target. */
enum base_architecture arm_base_arch = BASE_ARCH_0;
/* Active target architecture and tuning. */
struct arm_build_target arm_active_target;
/* The following are used in the arm.md file as equivalents to bits
in the above two flag variables. */
/* Nonzero if this chip supports the ARM Architecture 4 extensions. */
int arm_arch4 = 0;
/* Nonzero if this chip supports the ARM Architecture 4t extensions. */
int arm_arch4t = 0;
/* Nonzero if this chip supports the ARM Architecture 5T extensions. */
int arm_arch5t = 0;
/* Nonzero if this chip supports the ARM Architecture 5TE extensions. */
int arm_arch5te = 0;
/* Nonzero if this chip supports the ARM Architecture 6 extensions. */
int arm_arch6 = 0;
/* Nonzero if this chip supports the ARM 6K extensions. */
int arm_arch6k = 0;
/* Nonzero if this chip supports the ARM 6KZ extensions. */
int arm_arch6kz = 0;
/* Nonzero if instructions present in ARMv6-M can be used. */
int arm_arch6m = 0;
/* Nonzero if this chip supports the ARM 7 extensions. */
int arm_arch7 = 0;
/* Nonzero if this chip supports the Large Physical Address Extension. */
int arm_arch_lpae = 0;
/* Nonzero if instructions not present in the 'M' profile can be used. */
int arm_arch_notm = 0;
/* Nonzero if instructions present in ARMv7E-M can be used. */
int arm_arch7em = 0;
/* Nonzero if instructions present in ARMv8 can be used. */
int arm_arch8 = 0;
/* Nonzero if this chip supports the ARMv8.1 extensions. */
int arm_arch8_1 = 0;
/* Nonzero if this chip supports the ARM Architecture 8.2 extensions. */
int arm_arch8_2 = 0;
/* Nonzero if this chip supports the ARM Architecture 8.3 extensions. */
int arm_arch8_3 = 0;
/* Nonzero if this chip supports the ARM Architecture 8.4 extensions. */
int arm_arch8_4 = 0;
/* Nonzero if this chip supports the FP16 instructions extension of ARM
Architecture 8.2. */
int arm_fp16_inst = 0;
/* Nonzero if this chip can benefit from load scheduling. */
int arm_ld_sched = 0;
/* Nonzero if this chip is a StrongARM. */
int arm_tune_strongarm = 0;
/* Nonzero if this chip supports Intel Wireless MMX technology. */
int arm_arch_iwmmxt = 0;
/* Nonzero if this chip supports Intel Wireless MMX2 technology. */
int arm_arch_iwmmxt2 = 0;
/* Nonzero if this chip is an XScale. */
int arm_arch_xscale = 0;
/* Nonzero if tuning for XScale */
int arm_tune_xscale = 0;
/* Nonzero if we want to tune for stores that access the write-buffer.
This typically means an ARM6 or ARM7 with MMU or MPU. */
int arm_tune_wbuf = 0;
/* Nonzero if tuning for Cortex-A9. */
int arm_tune_cortex_a9 = 0;
/* Nonzero if we should define __THUMB_INTERWORK__ in the
preprocessor.
XXX This is a bit of a hack, it's intended to help work around
problems in GLD which doesn't understand that armv5t code is
interworking clean. */
int arm_cpp_interwork = 0;
/* Nonzero if chip supports Thumb 1. */
int arm_arch_thumb1;
/* Nonzero if chip supports Thumb 2. */
int arm_arch_thumb2;
/* Nonzero if chip supports integer division instruction. */
int arm_arch_arm_hwdiv;
int arm_arch_thumb_hwdiv;
/* Nonzero if chip disallows volatile memory access in IT block. */
int arm_arch_no_volatile_ce;
/* Nonzero if we shouldn't use literal pools. */
bool arm_disable_literal_pool = false;
/* The register number to be used for the PIC offset register. */
unsigned arm_pic_register = INVALID_REGNUM;
enum arm_pcs arm_pcs_default;
/* For an explanation of these variables, see final_prescan_insn below. */
int arm_ccfsm_state;
/* arm_current_cc is also used for Thumb-2 cond_exec blocks. */
enum arm_cond_code arm_current_cc;
rtx arm_target_insn;
int arm_target_label;
/* The number of conditionally executed insns, including the current insn. */
int arm_condexec_count = 0;
/* A bitmask specifying the patterns for the IT block.
Zero means do not output an IT block before this insn. */
int arm_condexec_mask = 0;
/* The number of bits used in arm_condexec_mask. */
int arm_condexec_masklen = 0;
/* Nonzero if chip supports the ARMv8 CRC instructions. */
int arm_arch_crc = 0;
/* Nonzero if chip supports the AdvSIMD Dot Product instructions. */
int arm_arch_dotprod = 0;
/* Nonzero if chip supports the ARMv8-M security extensions. */
int arm_arch_cmse = 0;
/* Nonzero if the core has a very small, high-latency, multiply unit. */
int arm_m_profile_small_mul = 0;
/* The condition codes of the ARM, and the inverse function. */
static const char * const arm_condition_codes[] =
{
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
};
/* The register numbers in sequence, for passing to arm_gen_load_multiple. */
int arm_regs_in_sequence[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
#define ARM_LSL_NAME "lsl"
#define streq(string1, string2) (strcmp (string1, string2) == 0)
#define THUMB2_WORK_REGS (0xff & ~( (1 << THUMB_HARD_FRAME_POINTER_REGNUM) \
| (1 << SP_REGNUM) | (1 << PC_REGNUM) \
| (1 << PIC_OFFSET_TABLE_REGNUM)))
/* Initialization code. */
struct cpu_tune
{
enum processor_type scheduler;
unsigned int tune_flags;
const struct tune_params *tune;
};
#define ARM_PREFETCH_NOT_BENEFICIAL { 0, -1, -1 }
#define ARM_PREFETCH_BENEFICIAL(num_slots,l1_size,l1_line_size) \
{ \
num_slots, \
l1_size, \
l1_line_size \
}
/* arm generic vectorizer costs. */
static const
struct cpu_vec_costs arm_default_vec_cost = {
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
1, /* vec_stmt_cost. */
1, /* vec_to_scalar_cost. */
1, /* scalar_to_vec_cost. */
1, /* vec_align_load_cost. */
1, /* vec_unalign_load_cost. */
1, /* vec_unalign_store_cost. */
1, /* vec_store_cost. */
3, /* cond_taken_branch_cost. */
1, /* cond_not_taken_branch_cost. */
};
/* Cost tables for AArch32 + AArch64 cores should go in aarch-cost-tables.h */
#include "aarch-cost-tables.h"
const struct cpu_cost_table cortexa9_extra_costs =
{
/* ALU */
{
0, /* arith. */
0, /* logical. */
0, /* shift. */
COSTS_N_INSNS (1), /* shift_reg. */
COSTS_N_INSNS (1), /* arith_shift. */
COSTS_N_INSNS (2), /* arith_shift_reg. */
0, /* log_shift. */
COSTS_N_INSNS (1), /* log_shift_reg. */
COSTS_N_INSNS (1), /* extend. */
COSTS_N_INSNS (2), /* extend_arith. */
COSTS_N_INSNS (1), /* bfi. */
COSTS_N_INSNS (1), /* bfx. */
0, /* clz. */
0, /* rev. */
0, /* non_exec. */
true /* non_exec_costs_exec. */
},
{
/* MULT SImode */
{
COSTS_N_INSNS (3), /* simple. */
COSTS_N_INSNS (3), /* flag_setting. */
COSTS_N_INSNS (2), /* extend. */
COSTS_N_INSNS (3), /* add. */
COSTS_N_INSNS (2), /* extend_add. */
COSTS_N_INSNS (30) /* idiv. No HW div on Cortex A9. */
},
/* MULT DImode */
{
0, /* simple (N/A). */
0, /* flag_setting (N/A). */
COSTS_N_INSNS (4), /* extend. */
0, /* add (N/A). */
COSTS_N_INSNS (4), /* extend_add. */
0 /* idiv (N/A). */
}
},
/* LD/ST */
{
COSTS_N_INSNS (2), /* load. */
COSTS_N_INSNS (2), /* load_sign_extend. */
COSTS_N_INSNS (2), /* ldrd. */
COSTS_N_INSNS (2), /* ldm_1st. */
1, /* ldm_regs_per_insn_1st. */
2, /* ldm_regs_per_insn_subsequent. */
COSTS_N_INSNS (5), /* loadf. */
COSTS_N_INSNS (5), /* loadd. */
COSTS_N_INSNS (1), /* load_unaligned. */
COSTS_N_INSNS (2), /* store. */
COSTS_N_INSNS (2), /* strd. */
COSTS_N_INSNS (2), /* stm_1st. */
1, /* stm_regs_per_insn_1st. */
2, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (1), /* storef. */
COSTS_N_INSNS (1), /* stored. */
COSTS_N_INSNS (1), /* store_unaligned. */
COSTS_N_INSNS (1), /* loadv. */
COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
{
COSTS_N_INSNS (14), /* div. */
COSTS_N_INSNS (4), /* mult. */
COSTS_N_INSNS (7), /* mult_addsub. */
COSTS_N_INSNS (30), /* fma. */
COSTS_N_INSNS (3), /* addsub. */
COSTS_N_INSNS (1), /* fpconst. */
COSTS_N_INSNS (1), /* neg. */
COSTS_N_INSNS (3), /* compare. */
COSTS_N_INSNS (3), /* widen. */
COSTS_N_INSNS (3), /* narrow. */
COSTS_N_INSNS (3), /* toint. */
COSTS_N_INSNS (3), /* fromint. */
COSTS_N_INSNS (3) /* roundint. */
},
/* FP DFmode */
{
COSTS_N_INSNS (24), /* div. */
COSTS_N_INSNS (5), /* mult. */
COSTS_N_INSNS (8), /* mult_addsub. */
COSTS_N_INSNS (30), /* fma. */
COSTS_N_INSNS (3), /* addsub. */
COSTS_N_INSNS (1), /* fpconst. */
COSTS_N_INSNS (1), /* neg. */
COSTS_N_INSNS (3), /* compare. */
COSTS_N_INSNS (3), /* widen. */
COSTS_N_INSNS (3), /* narrow. */
COSTS_N_INSNS (3), /* toint. */
COSTS_N_INSNS (3), /* fromint. */
COSTS_N_INSNS (3) /* roundint. */
}
},
/* Vector */
{
COSTS_N_INSNS (1) /* alu. */
}
};
const struct cpu_cost_table cortexa8_extra_costs =
{
/* ALU */
{
0, /* arith. */
0, /* logical. */
COSTS_N_INSNS (1), /* shift. */
0, /* shift_reg. */
COSTS_N_INSNS (1), /* arith_shift. */
0, /* arith_shift_reg. */
COSTS_N_INSNS (1), /* log_shift. */
0, /* log_shift_reg. */
0, /* extend. */
0, /* extend_arith. */
0, /* bfi. */
0, /* bfx. */
0, /* clz. */
0, /* rev. */
0, /* non_exec. */
true /* non_exec_costs_exec. */
},
{
/* MULT SImode */
{
COSTS_N_INSNS (1), /* simple. */
COSTS_N_INSNS (1), /* flag_setting. */
COSTS_N_INSNS (1), /* extend. */
COSTS_N_INSNS (1), /* add. */
COSTS_N_INSNS (1), /* extend_add. */
COSTS_N_INSNS (30) /* idiv. No HW div on Cortex A8. */
},
/* MULT DImode */
{
0, /* simple (N/A). */
0, /* flag_setting (N/A). */
COSTS_N_INSNS (2), /* extend. */
0, /* add (N/A). */
COSTS_N_INSNS (2), /* extend_add. */
0 /* idiv (N/A). */
}
},
/* LD/ST */
{
COSTS_N_INSNS (1), /* load. */
COSTS_N_INSNS (1), /* load_sign_extend. */
COSTS_N_INSNS (1), /* ldrd. */
COSTS_N_INSNS (1), /* ldm_1st. */
1, /* ldm_regs_per_insn_1st. */
2, /* ldm_regs_per_insn_subsequent. */
COSTS_N_INSNS (1), /* loadf. */
COSTS_N_INSNS (1), /* loadd. */
COSTS_N_INSNS (1), /* load_unaligned. */
COSTS_N_INSNS (1), /* store. */
COSTS_N_INSNS (1), /* strd. */
COSTS_N_INSNS (1), /* stm_1st. */
1, /* stm_regs_per_insn_1st. */
2, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (1), /* storef. */
COSTS_N_INSNS (1), /* stored. */
COSTS_N_INSNS (1), /* store_unaligned. */
COSTS_N_INSNS (1), /* loadv. */
COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
{
COSTS_N_INSNS (36), /* div. */
COSTS_N_INSNS (11), /* mult. */
COSTS_N_INSNS (20), /* mult_addsub. */
COSTS_N_INSNS (30), /* fma. */
COSTS_N_INSNS (9), /* addsub. */
COSTS_N_INSNS (3), /* fpconst. */
COSTS_N_INSNS (3), /* neg. */
COSTS_N_INSNS (6), /* compare. */
COSTS_N_INSNS (4), /* widen. */
COSTS_N_INSNS (4), /* narrow. */
COSTS_N_INSNS (8), /* toint. */
COSTS_N_INSNS (8), /* fromint. */
COSTS_N_INSNS (8) /* roundint. */
},
/* FP DFmode */
{
COSTS_N_INSNS (64), /* div. */
COSTS_N_INSNS (16), /* mult. */
COSTS_N_INSNS (25), /* mult_addsub. */
COSTS_N_INSNS (30), /* fma. */
COSTS_N_INSNS (9), /* addsub. */
COSTS_N_INSNS (3), /* fpconst. */
COSTS_N_INSNS (3), /* neg. */
COSTS_N_INSNS (6), /* compare. */
COSTS_N_INSNS (6), /* widen. */
COSTS_N_INSNS (6), /* narrow. */
COSTS_N_INSNS (8), /* toint. */
COSTS_N_INSNS (8), /* fromint. */
COSTS_N_INSNS (8) /* roundint. */
}
},
/* Vector */
{
COSTS_N_INSNS (1) /* alu. */
}
};
const struct cpu_cost_table cortexa5_extra_costs =
{
/* ALU */
{
0, /* arith. */
0, /* logical. */
COSTS_N_INSNS (1), /* shift. */
COSTS_N_INSNS (1), /* shift_reg. */
COSTS_N_INSNS (1), /* arith_shift. */
COSTS_N_INSNS (1), /* arith_shift_reg. */
COSTS_N_INSNS (1), /* log_shift. */
COSTS_N_INSNS (1), /* log_shift_reg. */
COSTS_N_INSNS (1), /* extend. */
COSTS_N_INSNS (1), /* extend_arith. */
COSTS_N_INSNS (1), /* bfi. */
COSTS_N_INSNS (1), /* bfx. */
COSTS_N_INSNS (1), /* clz. */
COSTS_N_INSNS (1), /* rev. */
0, /* non_exec. */
true /* non_exec_costs_exec. */
},
{
/* MULT SImode */
{
0, /* simple. */
COSTS_N_INSNS (1), /* flag_setting. */
COSTS_N_INSNS (1), /* extend. */
COSTS_N_INSNS (1), /* add. */
COSTS_N_INSNS (1), /* extend_add. */
COSTS_N_INSNS (7) /* idiv. */
},
/* MULT DImode */
{
0, /* simple (N/A). */
0, /* flag_setting (N/A). */
COSTS_N_INSNS (1), /* extend. */
0, /* add. */
COSTS_N_INSNS (2), /* extend_add. */
0 /* idiv (N/A). */
}
},
/* LD/ST */
{
COSTS_N_INSNS (1), /* load. */
COSTS_N_INSNS (1), /* load_sign_extend. */
COSTS_N_INSNS (6), /* ldrd. */
COSTS_N_INSNS (1), /* ldm_1st. */
1, /* ldm_regs_per_insn_1st. */
2, /* ldm_regs_per_insn_subsequent. */
COSTS_N_INSNS (2), /* loadf. */
COSTS_N_INSNS (4), /* loadd. */
COSTS_N_INSNS (1), /* load_unaligned. */
COSTS_N_INSNS (1), /* store. */
COSTS_N_INSNS (3), /* strd. */
COSTS_N_INSNS (1), /* stm_1st. */
1, /* stm_regs_per_insn_1st. */
2, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (2), /* storef. */
COSTS_N_INSNS (2), /* stored. */
COSTS_N_INSNS (1), /* store_unaligned. */
COSTS_N_INSNS (1), /* loadv. */
COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
{
COSTS_N_INSNS (15), /* div. */
COSTS_N_INSNS (3), /* mult. */
COSTS_N_INSNS (7), /* mult_addsub. */
COSTS_N_INSNS (7), /* fma. */
COSTS_N_INSNS (3), /* addsub. */
COSTS_N_INSNS (3), /* fpconst. */
COSTS_N_INSNS (3), /* neg. */
COSTS_N_INSNS (3), /* compare. */
COSTS_N_INSNS (3), /* widen. */
COSTS_N_INSNS (3), /* narrow. */
COSTS_N_INSNS (3), /* toint. */
COSTS_N_INSNS (3), /* fromint. */
COSTS_N_INSNS (3) /* roundint. */
},
/* FP DFmode */
{
COSTS_N_INSNS (30), /* div. */
COSTS_N_INSNS (6), /* mult. */
COSTS_N_INSNS (10), /* mult_addsub. */
COSTS_N_INSNS (7), /* fma. */
COSTS_N_INSNS (3), /* addsub. */
COSTS_N_INSNS (3), /* fpconst. */
COSTS_N_INSNS (3), /* neg. */
COSTS_N_INSNS (3), /* compare. */
COSTS_N_INSNS (3), /* widen. */
COSTS_N_INSNS (3), /* narrow. */
COSTS_N_INSNS (3), /* toint. */
COSTS_N_INSNS (3), /* fromint. */
COSTS_N_INSNS (3) /* roundint. */
}
},
/* Vector */
{
COSTS_N_INSNS (1) /* alu. */
}
};
const struct cpu_cost_table cortexa7_extra_costs =
{
/* ALU */
{
0, /* arith. */
0, /* logical. */
COSTS_N_INSNS (1), /* shift. */
COSTS_N_INSNS (1), /* shift_reg. */
COSTS_N_INSNS (1), /* arith_shift. */
COSTS_N_INSNS (1), /* arith_shift_reg. */
COSTS_N_INSNS (1), /* log_shift. */
COSTS_N_INSNS (1), /* log_shift_reg. */
COSTS_N_INSNS (1), /* extend. */
COSTS_N_INSNS (1), /* extend_arith. */
COSTS_N_INSNS (1), /* bfi. */
COSTS_N_INSNS (1), /* bfx. */
COSTS_N_INSNS (1), /* clz. */
COSTS_N_INSNS (1), /* rev. */
0, /* non_exec. */
true /* non_exec_costs_exec. */
},
{
/* MULT SImode */
{
0, /* simple. */
COSTS_N_INSNS (1), /* flag_setting. */
COSTS_N_INSNS (1), /* extend. */
COSTS_N_INSNS (1), /* add. */
COSTS_N_INSNS (1), /* extend_add. */
COSTS_N_INSNS (7) /* idiv. */
},
/* MULT DImode */
{
0, /* simple (N/A). */
0, /* flag_setting (N/A). */
COSTS_N_INSNS (1), /* extend. */
0, /* add. */
COSTS_N_INSNS (2), /* extend_add. */
0 /* idiv (N/A). */
}
},
/* LD/ST */
{
COSTS_N_INSNS (1), /* load. */
COSTS_N_INSNS (1), /* load_sign_extend. */
COSTS_N_INSNS (3), /* ldrd. */
COSTS_N_INSNS (1), /* ldm_1st. */
1, /* ldm_regs_per_insn_1st. */
2, /* ldm_regs_per_insn_subsequent. */
COSTS_N_INSNS (2), /* loadf. */
COSTS_N_INSNS (2), /* loadd. */
COSTS_N_INSNS (1), /* load_unaligned. */
COSTS_N_INSNS (1), /* store. */
COSTS_N_INSNS (3), /* strd. */
COSTS_N_INSNS (1), /* stm_1st. */
1, /* stm_regs_per_insn_1st. */
2, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (2), /* storef. */
COSTS_N_INSNS (2), /* stored. */
COSTS_N_INSNS (1), /* store_unaligned. */
COSTS_N_INSNS (1), /* loadv. */
COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
{
COSTS_N_INSNS (15), /* div. */
COSTS_N_INSNS (3), /* mult. */
COSTS_N_INSNS (7), /* mult_addsub. */
COSTS_N_INSNS (7), /* fma. */
COSTS_N_INSNS (3), /* addsub. */
COSTS_N_INSNS (3), /* fpconst. */
COSTS_N_INSNS (3), /* neg. */
COSTS_N_INSNS (3), /* compare. */
COSTS_N_INSNS (3), /* widen. */
COSTS_N_INSNS (3), /* narrow. */
COSTS_N_INSNS (3), /* toint. */
COSTS_N_INSNS (3), /* fromint. */
COSTS_N_INSNS (3) /* roundint. */
},
/* FP DFmode */
{
COSTS_N_INSNS (30), /* div. */
COSTS_N_INSNS (6), /* mult. */
COSTS_N_INSNS (10), /* mult_addsub. */
COSTS_N_INSNS (7), /* fma. */
COSTS_N_INSNS (3), /* addsub. */
COSTS_N_INSNS (3), /* fpconst. */
COSTS_N_INSNS (3), /* neg. */
COSTS_N_INSNS (3), /* compare. */
COSTS_N_INSNS (3), /* widen. */
COSTS_N_INSNS (3), /* narrow. */
COSTS_N_INSNS (3), /* toint. */
COSTS_N_INSNS (3), /* fromint. */
COSTS_N_INSNS (3) /* roundint. */
}
},
/* Vector */
{
COSTS_N_INSNS (1) /* alu. */
}
};
const struct cpu_cost_table cortexa12_extra_costs =
{
/* ALU */
{
0, /* arith. */
0, /* logical. */
0, /* shift. */
COSTS_N_INSNS (1), /* shift_reg. */
COSTS_N_INSNS (1), /* arith_shift. */
COSTS_N_INSNS (1), /* arith_shift_reg. */
COSTS_N_INSNS (1), /* log_shift. */
COSTS_N_INSNS (1), /* log_shift_reg. */
0, /* extend. */
COSTS_N_INSNS (1), /* extend_arith. */
0, /* bfi. */
COSTS_N_INSNS (1), /* bfx. */
COSTS_N_INSNS (1), /* clz. */
COSTS_N_INSNS (1), /* rev. */
0, /* non_exec. */
true /* non_exec_costs_exec. */
},
/* MULT SImode */
{
{
COSTS_N_INSNS (2), /* simple. */
COSTS_N_INSNS (3), /* flag_setting. */
COSTS_N_INSNS (2), /* extend. */
COSTS_N_INSNS (3), /* add. */
COSTS_N_INSNS (2), /* extend_add. */
COSTS_N_INSNS (18) /* idiv. */
},
/* MULT DImode */
{
0, /* simple (N/A). */
0, /* flag_setting (N/A). */
COSTS_N_INSNS (3), /* extend. */
0, /* add (N/A). */
COSTS_N_INSNS (3), /* extend_add. */
0 /* idiv (N/A). */
}
},
/* LD/ST */
{
COSTS_N_INSNS (3), /* load. */
COSTS_N_INSNS (3), /* load_sign_extend. */
COSTS_N_INSNS (3), /* ldrd. */
COSTS_N_INSNS (3), /* ldm_1st. */
1, /* ldm_regs_per_insn_1st. */
2, /* ldm_regs_per_insn_subsequent. */
COSTS_N_INSNS (3), /* loadf. */
COSTS_N_INSNS (3), /* loadd. */
0, /* load_unaligned. */
0, /* store. */
0, /* strd. */
0, /* stm_1st. */
1, /* stm_regs_per_insn_1st. */
2, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (2), /* storef. */
COSTS_N_INSNS (2), /* stored. */
0, /* store_unaligned. */
COSTS_N_INSNS (1), /* loadv. */
COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
{
COSTS_N_INSNS (17), /* div. */
COSTS_N_INSNS (4), /* mult. */
COSTS_N_INSNS (8), /* mult_addsub. */
COSTS_N_INSNS (8), /* fma. */
COSTS_N_INSNS (4), /* addsub. */
COSTS_N_INSNS (2), /* fpconst. */
COSTS_N_INSNS (2), /* neg. */
COSTS_N_INSNS (2), /* compare. */
COSTS_N_INSNS (4), /* widen. */
COSTS_N_INSNS (4), /* narrow. */
COSTS_N_INSNS (4), /* toint. */
COSTS_N_INSNS (4), /* fromint. */
COSTS_N_INSNS (4) /* roundint. */
},
/* FP DFmode */
{
COSTS_N_INSNS (31), /* div. */
COSTS_N_INSNS (4), /* mult. */
COSTS_N_INSNS (8), /* mult_addsub. */
COSTS_N_INSNS (8), /* fma. */
COSTS_N_INSNS (4), /* addsub. */
COSTS_N_INSNS (2), /* fpconst. */
COSTS_N_INSNS (2), /* neg. */
COSTS_N_INSNS (2), /* compare. */
COSTS_N_INSNS (4), /* widen. */
COSTS_N_INSNS (4), /* narrow. */
COSTS_N_INSNS (4), /* toint. */
COSTS_N_INSNS (4), /* fromint. */
COSTS_N_INSNS (4) /* roundint. */
}
},
/* Vector */
{
COSTS_N_INSNS (1) /* alu. */
}
};
const struct cpu_cost_table cortexa15_extra_costs =
{
/* ALU */
{
0, /* arith. */
0, /* logical. */
0, /* shift. */
0, /* shift_reg. */
COSTS_N_INSNS (1), /* arith_shift. */
COSTS_N_INSNS (1), /* arith_shift_reg. */
COSTS_N_INSNS (1), /* log_shift. */
COSTS_N_INSNS (1), /* log_shift_reg. */
0, /* extend. */
COSTS_N_INSNS (1), /* extend_arith. */
COSTS_N_INSNS (1), /* bfi. */
0, /* bfx. */
0, /* clz. */
0, /* rev. */
0, /* non_exec. */
true /* non_exec_costs_exec. */
},
/* MULT SImode */
{
{
COSTS_N_INSNS (2), /* simple. */
COSTS_N_INSNS (3), /* flag_setting. */
COSTS_N_INSNS (2), /* extend. */
COSTS_N_INSNS (2), /* add. */
COSTS_N_INSNS (2), /* extend_add. */
COSTS_N_INSNS (18) /* idiv. */
},
/* MULT DImode */
{
0, /* simple (N/A). */
0, /* flag_setting (N/A). */
COSTS_N_INSNS (3), /* extend. */
0, /* add (N/A). */
COSTS_N_INSNS (3), /* extend_add. */
0 /* idiv (N/A). */
}
},
/* LD/ST */
{
COSTS_N_INSNS (3), /* load. */
COSTS_N_INSNS (3), /* load_sign_extend. */
COSTS_N_INSNS (3), /* ldrd. */
COSTS_N_INSNS (4), /* ldm_1st. */
1, /* ldm_regs_per_insn_1st. */
2, /* ldm_regs_per_insn_subsequent. */
COSTS_N_INSNS (4), /* loadf. */
COSTS_N_INSNS (4), /* loadd. */
0, /* load_unaligned. */
0, /* store. */
0, /* strd. */
COSTS_N_INSNS (1), /* stm_1st. */
1, /* stm_regs_per_insn_1st. */
2, /* stm_regs_per_insn_subsequent. */
0, /* storef. */
0, /* stored. */
0, /* store_unaligned. */
COSTS_N_INSNS (1), /* loadv. */
COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
{
COSTS_N_INSNS (17), /* div. */
COSTS_N_INSNS (4), /* mult. */
COSTS_N_INSNS (8), /* mult_addsub. */
COSTS_N_INSNS (8), /* fma. */
COSTS_N_INSNS (4), /* addsub. */
COSTS_N_INSNS (2), /* fpconst. */
COSTS_N_INSNS (2), /* neg. */
COSTS_N_INSNS (5), /* compare. */
COSTS_N_INSNS (4), /* widen. */
COSTS_N_INSNS (4), /* narrow. */
COSTS_N_INSNS (4), /* toint. */
COSTS_N_INSNS (4), /* fromint. */
COSTS_N_INSNS (4) /* roundint. */
},
/* FP DFmode */
{
COSTS_N_INSNS (31), /* div. */
COSTS_N_INSNS (4), /* mult. */
COSTS_N_INSNS (8), /* mult_addsub. */
COSTS_N_INSNS (8), /* fma. */
COSTS_N_INSNS (4), /* addsub. */
COSTS_N_INSNS (2), /* fpconst. */
COSTS_N_INSNS (2), /* neg. */
COSTS_N_INSNS (2), /* compare. */
COSTS_N_INSNS (4), /* widen. */
COSTS_N_INSNS (4), /* narrow. */
COSTS_N_INSNS (4), /* toint. */
COSTS_N_INSNS (4), /* fromint. */
COSTS_N_INSNS (4) /* roundint. */
}
},
/* Vector */
{
COSTS_N_INSNS (1) /* alu. */
}
};
const struct cpu_cost_table v7m_extra_costs =
{
/* ALU */
{
0, /* arith. */
0, /* logical. */
0, /* shift. */
0, /* shift_reg. */
0, /* arith_shift. */
COSTS_N_INSNS (1), /* arith_shift_reg. */
0, /* log_shift. */
COSTS_N_INSNS (1), /* log_shift_reg. */
0, /* extend. */
COSTS_N_INSNS (1), /* extend_arith. */
0, /* bfi. */
0, /* bfx. */
0, /* clz. */
0, /* rev. */
COSTS_N_INSNS (1), /* non_exec. */
false /* non_exec_costs_exec. */
},
{
/* MULT SImode */
{
COSTS_N_INSNS (1), /* simple. */
COSTS_N_INSNS (1), /* flag_setting. */
COSTS_N_INSNS (2), /* extend. */
COSTS_N_INSNS (1), /* add. */
COSTS_N_INSNS (3), /* extend_add. */
COSTS_N_INSNS (8) /* idiv. */
},
/* MULT DImode */
{
0, /* simple (N/A). */
0, /* flag_setting (N/A). */
COSTS_N_INSNS (2), /* extend. */
0, /* add (N/A). */
COSTS_N_INSNS (3), /* extend_add. */
0 /* idiv (N/A). */
}
},
/* LD/ST */
{
COSTS_N_INSNS (2), /* load. */
0, /* load_sign_extend. */
COSTS_N_INSNS (3), /* ldrd. */
COSTS_N_INSNS (2), /* ldm_1st. */
1, /* ldm_regs_per_insn_1st. */
1, /* ldm_regs_per_insn_subsequent. */
COSTS_N_INSNS (2), /* loadf. */
COSTS_N_INSNS (3), /* loadd. */
COSTS_N_INSNS (1), /* load_unaligned. */
COSTS_N_INSNS (2), /* store. */
COSTS_N_INSNS (3), /* strd. */
COSTS_N_INSNS (2), /* stm_1st. */
1, /* stm_regs_per_insn_1st. */
1, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (2), /* storef. */
COSTS_N_INSNS (3), /* stored. */
COSTS_N_INSNS (1), /* store_unaligned. */
COSTS_N_INSNS (1), /* loadv. */
COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
{
COSTS_N_INSNS (7), /* div. */
COSTS_N_INSNS (2), /* mult. */
COSTS_N_INSNS (5), /* mult_addsub. */
COSTS_N_INSNS (3), /* fma. */
COSTS_N_INSNS (1), /* addsub. */
0, /* fpconst. */
0, /* neg. */
0, /* compare. */
0, /* widen. */
0, /* narrow. */
0, /* toint. */
0, /* fromint. */
0 /* roundint. */
},
/* FP DFmode */
{
COSTS_N_INSNS (15), /* div. */
COSTS_N_INSNS (5), /* mult. */
COSTS_N_INSNS (7), /* mult_addsub. */
COSTS_N_INSNS (7), /* fma. */
COSTS_N_INSNS (3), /* addsub. */
0, /* fpconst. */
0, /* neg. */
0, /* compare. */
0, /* widen. */
0, /* narrow. */
0, /* toint. */
0, /* fromint. */
0 /* roundint. */
}
},
/* Vector */
{
COSTS_N_INSNS (1) /* alu. */
}
};
const struct addr_mode_cost_table generic_addr_mode_costs =
{
/* int. */
{
COSTS_N_INSNS (0), /* AMO_DEFAULT. */
COSTS_N_INSNS (0), /* AMO_NO_WB. */
COSTS_N_INSNS (0) /* AMO_WB. */
},
/* float. */
{
COSTS_N_INSNS (0), /* AMO_DEFAULT. */
COSTS_N_INSNS (0), /* AMO_NO_WB. */
COSTS_N_INSNS (0) /* AMO_WB. */
},
/* vector. */
{
COSTS_N_INSNS (0), /* AMO_DEFAULT. */
COSTS_N_INSNS (0), /* AMO_NO_WB. */
COSTS_N_INSNS (0) /* AMO_WB. */
}
};
const struct tune_params arm_slowmul_tune =
{
&generic_extra_costs, /* Insn extra costs. */
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
3, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
1, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_TRUE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_fastmul_tune =
{
&generic_extra_costs, /* Insn extra costs. */
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
1, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_TRUE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
/* StrongARM has early execution of branches, so a sequence that is worth
skipping is shorter. Set max_insns_skipped to a lower value. */
const struct tune_params arm_strongarm_tune =
{
&generic_extra_costs, /* Insn extra costs. */
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
3, /* Max cond insns. */
8, /* Memset max inline. */
1, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_TRUE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_xscale_tune =
{
&generic_extra_costs, /* Insn extra costs. */
&generic_addr_mode_costs, /* Addressing mode costs. */
xscale_sched_adjust_cost,
arm_default_branch_cost,
&arm_default_vec_cost,
2, /* Constant limit. */
3, /* Max cond insns. */
8, /* Memset max inline. */
1, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_TRUE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_9e_tune =
{
&generic_extra_costs, /* Insn extra costs. */
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
1, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_TRUE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_marvell_pj4_tune =
{
&generic_extra_costs, /* Insn extra costs. */
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
2, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_TRUE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_v6t2_tune =
{
&generic_extra_costs, /* Insn extra costs. */
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
1, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
/* Generic Cortex tuning. Use more specific tunings if appropriate. */
const struct tune_params arm_cortex_tune =
{
&generic_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
2, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_cortex_a8_tune =
{
&cortexa8_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
2, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_TRUE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_cortex_a7_tune =
{
&cortexa7_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
2, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_TRUE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_cortex_a15_tune =
{
&cortexa15_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
2, /* Max cond insns. */
8, /* Memset max inline. */
3, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_TRUE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_ALL,
tune_params::PREF_NEON_STRINGOPS_TRUE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_FULL
};
const struct tune_params arm_cortex_a35_tune =
{
&cortexa53_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
1, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_TRUE,
FUSE_OPS (tune_params::FUSE_MOVW_MOVT),
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_cortex_a53_tune =
{
&cortexa53_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
2, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_TRUE,
FUSE_OPS (tune_params::FUSE_MOVW_MOVT | tune_params::FUSE_AES_AESMC),
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_cortex_a57_tune =
{
&cortexa57_extra_costs,
&generic_addr_mode_costs, /* addressing mode costs */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
2, /* Max cond insns. */
8, /* Memset max inline. */
3, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_TRUE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_ALL,
tune_params::PREF_NEON_STRINGOPS_TRUE,
FUSE_OPS (tune_params::FUSE_MOVW_MOVT | tune_params::FUSE_AES_AESMC),
tune_params::SCHED_AUTOPREF_FULL
};
const struct tune_params arm_exynosm1_tune =
{
&exynosm1_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
2, /* Max cond insns. */
8, /* Memset max inline. */
3, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_TRUE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_FALSE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_FALSE, /* ARM. */
tune_params::DISPARAGE_FLAGS_ALL,
tune_params::PREF_NEON_STRINGOPS_TRUE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_xgene1_tune =
{
&xgene1_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
2, /* Max cond insns. */
32, /* Memset max inline. */
4, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_TRUE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_ALL,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
/* Branches can be dual-issued on Cortex-A5, so conditional execution is
less appealing. Set max_insns_skipped to a low value. */
const struct tune_params arm_cortex_a5_tune =
{
&cortexa5_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_cortex_a5_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
1, /* Max cond insns. */
8, /* Memset max inline. */
2, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_FALSE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_FALSE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_TRUE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_cortex_a9_tune =
{
&cortexa9_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
cortex_a9_sched_adjust_cost,
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
2, /* Issue rate. */
ARM_PREFETCH_BENEFICIAL(4,32,32),
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_cortex_a12_tune =
{
&cortexa12_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost, /* Vectorizer costs. */
1, /* Constant limit. */
2, /* Max cond insns. */
8, /* Memset max inline. */
2, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_TRUE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_ALL,
tune_params::PREF_NEON_STRINGOPS_TRUE,
FUSE_OPS (tune_params::FUSE_MOVW_MOVT),
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_cortex_a73_tune =
{
&cortexa57_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost, /* Vectorizer costs. */
1, /* Constant limit. */
2, /* Max cond insns. */
8, /* Memset max inline. */
2, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_TRUE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_ALL,
tune_params::PREF_NEON_STRINGOPS_TRUE,
FUSE_OPS (tune_params::FUSE_AES_AESMC | tune_params::FUSE_MOVW_MOVT),
tune_params::SCHED_AUTOPREF_FULL
};
/* armv7m tuning. On Cortex-M4 cores for example, MOVW/MOVT take a single
cycle to execute each. An LDR from the constant pool also takes two cycles
to execute, but mildly increases pipelining opportunity (consecutive
loads/stores can be pipelined together, saving one cycle), and may also
improve icache utilisation. Hence we prefer the constant pool for such
processors. */
const struct tune_params arm_v7m_tune =
{
&v7m_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_cortex_m_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
2, /* Max cond insns. */
8, /* Memset max inline. */
1, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_TRUE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_FALSE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_FALSE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
/* Cortex-M7 tuning. */
const struct tune_params arm_cortex_m7_tune =
{
&v7m_extra_costs,
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_cortex_m7_branch_cost,
&arm_default_vec_cost,
0, /* Constant limit. */
1, /* Max cond insns. */
8, /* Memset max inline. */
2, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_TRUE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
/* The arm_v6m_tune is duplicated from arm_cortex_tune, rather than
arm_v6t2_tune. It is used for cortex-m0, cortex-m1, cortex-m0plus and
cortex-m23. */
const struct tune_params arm_v6m_tune =
{
&generic_extra_costs, /* Insn extra costs. */
&generic_addr_mode_costs, /* Addressing mode costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost, /* Vectorizer costs. */
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
1, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_FALSE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_FALSE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_FALSE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
const struct tune_params arm_fa726te_tune =
{
&generic_extra_costs, /* Insn extra costs. */
&generic_addr_mode_costs, /* Addressing mode costs. */
fa726te_sched_adjust_cost,
arm_default_branch_cost,
&arm_default_vec_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
8, /* Memset max inline. */
2, /* Issue rate. */
ARM_PREFETCH_NOT_BENEFICIAL,
tune_params::PREF_CONST_POOL_TRUE,
tune_params::PREF_LDRD_FALSE,
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* Thumb. */
tune_params::LOG_OP_NON_SHORT_CIRCUIT_TRUE, /* ARM. */
tune_params::DISPARAGE_FLAGS_NEITHER,
tune_params::PREF_NEON_STRINGOPS_FALSE,
tune_params::FUSE_NOTHING,
tune_params::SCHED_AUTOPREF_OFF
};
/* Auto-generated CPU, FPU and architecture tables. */
#include "arm-cpu-data.h"
/* The name of the preprocessor macro to define for this architecture. PROFILE
is replaced by the architecture name (eg. 8A) in arm_option_override () and
is thus chosen to be big enough to hold the longest architecture name. */
char arm_arch_name[] = "__ARM_ARCH_PROFILE__";
/* Supported TLS relocations. */
enum tls_reloc {
TLS_GD32,
TLS_GD32_FDPIC,
TLS_LDM32,
TLS_LDM32_FDPIC,
TLS_LDO32,
TLS_IE32,
TLS_IE32_FDPIC,
TLS_LE32,
TLS_DESCSEQ /* GNU scheme */
};
/* The maximum number of insns to be used when loading a constant. */
inline static int
arm_constant_limit (bool size_p)
{
return size_p ? 1 : current_tune->constant_limit;
}
/* Emit an insn that's a simple single-set. Both the operands must be known
to be valid. */
inline static rtx_insn *
emit_set_insn (rtx x, rtx y)
{
return emit_insn (gen_rtx_SET (x, y));
}
/* Return the number of bits set in VALUE. */
static unsigned
bit_count (unsigned long value)
{
unsigned long count = 0;
while (value)
{
count++;
value &= value - 1; /* Clear the least-significant set bit. */
}
return count;
}
/* Return the number of bits set in BMAP. */
static unsigned
bitmap_popcount (const sbitmap bmap)
{
unsigned int count = 0;
unsigned int n = 0;
sbitmap_iterator sbi;
EXECUTE_IF_SET_IN_BITMAP (bmap, 0, n, sbi)
count++;
return count;
}
typedef struct
{
machine_mode mode;
const char *name;
} arm_fixed_mode_set;
/* A small helper for setting fixed-point library libfuncs. */
static void
arm_set_fixed_optab_libfunc (optab optable, machine_mode mode,
const char *funcname, const char *modename,
int num_suffix)
{
char buffer[50];
if (num_suffix == 0)
sprintf (buffer, "__gnu_%s%s", funcname, modename);
else
sprintf (buffer, "__gnu_%s%s%d", funcname, modename, num_suffix);
set_optab_libfunc (optable, mode, buffer);
}
static void
arm_set_fixed_conv_libfunc (convert_optab optable, machine_mode to,
machine_mode from, const char *funcname,
const char *toname, const char *fromname)
{
char buffer[50];
const char *maybe_suffix_2 = "";
/* Follow the logic for selecting a "2" suffix in fixed-bit.h. */
if (ALL_FIXED_POINT_MODE_P (from) && ALL_FIXED_POINT_MODE_P (to)
&& UNSIGNED_FIXED_POINT_MODE_P (from) == UNSIGNED_FIXED_POINT_MODE_P (to)
&& ALL_FRACT_MODE_P (from) == ALL_FRACT_MODE_P (to))
maybe_suffix_2 = "2";
sprintf (buffer, "__gnu_%s%s%s%s", funcname, fromname, toname,
maybe_suffix_2);
set_conv_libfunc (optable, to, from, buffer);
}
static GTY(()) rtx speculation_barrier_libfunc;
/* Set up library functions unique to ARM. */
static void
arm_init_libfuncs (void)
{
/* For Linux, we have access to kernel support for atomic operations. */
if (arm_abi == ARM_ABI_AAPCS_LINUX)
init_sync_libfuncs (MAX_SYNC_LIBFUNC_SIZE);
/* There are no special library functions unless we are using the
ARM BPABI. */
if (!TARGET_BPABI)
return;
/* The functions below are described in Section 4 of the "Run-Time
ABI for the ARM architecture", Version 1.0. */
/* Double-precision floating-point arithmetic. Table 2. */
set_optab_libfunc (add_optab, DFmode, "__aeabi_dadd");
set_optab_libfunc (sdiv_optab, DFmode, "__aeabi_ddiv");
set_optab_libfunc (smul_optab, DFmode, "__aeabi_dmul");
set_optab_libfunc (neg_optab, DFmode, "__aeabi_dneg");
set_optab_libfunc (sub_optab, DFmode, "__aeabi_dsub");
/* Double-precision comparisons. Table 3. */
set_optab_libfunc (eq_optab, DFmode, "__aeabi_dcmpeq");
set_optab_libfunc (ne_optab, DFmode, NULL);
set_optab_libfunc (lt_optab, DFmode, "__aeabi_dcmplt");
set_optab_libfunc (le_optab, DFmode, "__aeabi_dcmple");
set_optab_libfunc (ge_optab, DFmode, "__aeabi_dcmpge");
set_optab_libfunc (gt_optab, DFmode, "__aeabi_dcmpgt");
set_optab_libfunc (unord_optab, DFmode, "__aeabi_dcmpun");
/* Single-precision floating-point arithmetic. Table 4. */
set_optab_libfunc (add_optab, SFmode, "__aeabi_fadd");
set_optab_libfunc (sdiv_optab, SFmode, "__aeabi_fdiv");
set_optab_libfunc (smul_optab, SFmode, "__aeabi_fmul");
set_optab_libfunc (neg_optab, SFmode, "__aeabi_fneg");
set_optab_libfunc (sub_optab, SFmode, "__aeabi_fsub");
/* Single-precision comparisons. Table 5. */
set_optab_libfunc (eq_optab, SFmode, "__aeabi_fcmpeq");
set_optab_libfunc (ne_optab, SFmode, NULL);
set_optab_libfunc (lt_optab, SFmode, "__aeabi_fcmplt");
set_optab_libfunc (le_optab, SFmode, "__aeabi_fcmple");
set_optab_libfunc (ge_optab, SFmode, "__aeabi_fcmpge");
set_optab_libfunc (gt_optab, SFmode, "__aeabi_fcmpgt");
set_optab_libfunc (unord_optab, SFmode, "__aeabi_fcmpun");
/* Floating-point to integer conversions. Table 6. */
set_conv_libfunc (sfix_optab, SImode, DFmode, "__aeabi_d2iz");
set_conv_libfunc (ufix_optab, SImode, DFmode, "__aeabi_d2uiz");
set_conv_libfunc (sfix_optab, DImode, DFmode, "__aeabi_d2lz");
set_conv_libfunc (ufix_optab, DImode, DFmode, "__aeabi_d2ulz");
set_conv_libfunc (sfix_optab, SImode, SFmode, "__aeabi_f2iz");
set_conv_libfunc (ufix_optab, SImode, SFmode, "__aeabi_f2uiz");
set_conv_libfunc (sfix_optab, DImode, SFmode, "__aeabi_f2lz");
set_conv_libfunc (ufix_optab, DImode, SFmode, "__aeabi_f2ulz");
/* Conversions between floating types. Table 7. */
set_conv_libfunc (trunc_optab, SFmode, DFmode, "__aeabi_d2f");
set_conv_libfunc (sext_optab, DFmode, SFmode, "__aeabi_f2d");
/* Integer to floating-point conversions. Table 8. */
set_conv_libfunc (sfloat_optab, DFmode, SImode, "__aeabi_i2d");
set_conv_libfunc (ufloat_optab, DFmode, SImode, "__aeabi_ui2d");
set_conv_libfunc (sfloat_optab, DFmode, DImode, "__aeabi_l2d");
set_conv_libfunc (ufloat_optab, DFmode, DImode, "__aeabi_ul2d");
set_conv_libfunc (sfloat_optab, SFmode, SImode, "__aeabi_i2f");
set_conv_libfunc (ufloat_optab, SFmode, SImode, "__aeabi_ui2f");
set_conv_libfunc (sfloat_optab, SFmode, DImode, "__aeabi_l2f");
set_conv_libfunc (ufloat_optab, SFmode, DImode, "__aeabi_ul2f");
/* Long long. Table 9. */
set_optab_libfunc (smul_optab, DImode, "__aeabi_lmul");
set_optab_libfunc (sdivmod_optab, DImode, "__aeabi_ldivmod");
set_optab_libfunc (udivmod_optab, DImode, "__aeabi_uldivmod");
set_optab_libfunc (ashl_optab, DImode, "__aeabi_llsl");
set_optab_libfunc (lshr_optab, DImode, "__aeabi_llsr");
set_optab_libfunc (ashr_optab, DImode, "__aeabi_lasr");
set_optab_libfunc (cmp_optab, DImode, "__aeabi_lcmp");
set_optab_libfunc (ucmp_optab, DImode, "__aeabi_ulcmp");
/* Integer (32/32->32) division. \S 4.3.1. */
set_optab_libfunc (sdivmod_optab, SImode, "__aeabi_idivmod");
set_optab_libfunc (udivmod_optab, SImode, "__aeabi_uidivmod");
/* The divmod functions are designed so that they can be used for
plain division, even though they return both the quotient and the
remainder. The quotient is returned in the usual location (i.e.,
r0 for SImode, {r0, r1} for DImode), just as would be expected
for an ordinary division routine. Because the AAPCS calling
conventions specify that all of { r0, r1, r2, r3 } are
callee-saved registers, there is no need to tell the compiler
explicitly that those registers are clobbered by these
routines. */
set_optab_libfunc (sdiv_optab, DImode, "__aeabi_ldivmod");
set_optab_libfunc (udiv_optab, DImode, "__aeabi_uldivmod");
/* For SImode division the ABI provides div-without-mod routines,
which are faster. */
set_optab_libfunc (sdiv_optab, SImode, "__aeabi_idiv");
set_optab_libfunc (udiv_optab, SImode, "__aeabi_uidiv");
/* We don't have mod libcalls. Fortunately gcc knows how to use the
divmod libcalls instead. */
set_optab_libfunc (smod_optab, DImode, NULL);
set_optab_libfunc (umod_optab, DImode, NULL);
set_optab_libfunc (smod_optab, SImode, NULL);
set_optab_libfunc (umod_optab, SImode, NULL);
/* Half-precision float operations. The compiler handles all operations
with NULL libfuncs by converting the SFmode. */
switch (arm_fp16_format)
{
case ARM_FP16_FORMAT_IEEE:
case ARM_FP16_FORMAT_ALTERNATIVE:
/* Conversions. */
set_conv_libfunc (trunc_optab, HFmode, SFmode,
(arm_fp16_format == ARM_FP16_FORMAT_IEEE
? "__gnu_f2h_ieee"
: "__gnu_f2h_alternative"));
set_conv_libfunc (sext_optab, SFmode, HFmode,
(arm_fp16_format == ARM_FP16_FORMAT_IEEE
? "__gnu_h2f_ieee"
: "__gnu_h2f_alternative"));
set_conv_libfunc (trunc_optab, HFmode, DFmode,
(arm_fp16_format == ARM_FP16_FORMAT_IEEE
? "__gnu_d2h_ieee"
: "__gnu_d2h_alternative"));
/* Arithmetic. */
set_optab_libfunc (add_optab, HFmode, NULL);
set_optab_libfunc (sdiv_optab, HFmode, NULL);
set_optab_libfunc (smul_optab, HFmode, NULL);
set_optab_libfunc (neg_optab, HFmode, NULL);
set_optab_libfunc (sub_optab, HFmode, NULL);
/* Comparisons. */
set_optab_libfunc (eq_optab, HFmode, NULL);
set_optab_libfunc (ne_optab, HFmode, NULL);
set_optab_libfunc (lt_optab, HFmode, NULL);
set_optab_libfunc (le_optab, HFmode, NULL);
set_optab_libfunc (ge_optab, HFmode, NULL);
set_optab_libfunc (gt_optab, HFmode, NULL);
set_optab_libfunc (unord_optab, HFmode, NULL);
break;
default:
break;
}
/* Use names prefixed with __gnu_ for fixed-point helper functions. */
{
const arm_fixed_mode_set fixed_arith_modes[] =
{
{ E_QQmode, "qq" },
{ E_UQQmode, "uqq" },
{ E_HQmode, "hq" },
{ E_UHQmode, "uhq" },
{ E_SQmode, "sq" },
{ E_USQmode, "usq" },
{ E_DQmode, "dq" },
{ E_UDQmode, "udq" },
{ E_TQmode, "tq" },
{ E_UTQmode, "utq" },
{ E_HAmode, "ha" },
{ E_UHAmode, "uha" },
{ E_SAmode, "sa" },
{ E_USAmode, "usa" },
{ E_DAmode, "da" },
{ E_UDAmode, "uda" },
{ E_TAmode, "ta" },
{ E_UTAmode, "uta" }
};
const arm_fixed_mode_set fixed_conv_modes[] =
{
{ E_QQmode, "qq" },
{ E_UQQmode, "uqq" },
{ E_HQmode, "hq" },
{ E_UHQmode, "uhq" },
{ E_SQmode, "sq" },
{ E_USQmode, "usq" },
{ E_DQmode, "dq" },
{ E_UDQmode, "udq" },
{ E_TQmode, "tq" },
{ E_UTQmode, "utq" },
{ E_HAmode, "ha" },
{ E_UHAmode, "uha" },
{ E_SAmode, "sa" },
{ E_USAmode, "usa" },
{ E_DAmode, "da" },
{ E_UDAmode, "uda" },
{ E_TAmode, "ta" },
{ E_UTAmode, "uta" },
{ E_QImode, "qi" },
{ E_HImode, "hi" },
{ E_SImode, "si" },
{ E_DImode, "di" },
{ E_TImode, "ti" },
{ E_SFmode, "sf" },
{ E_DFmode, "df" }
};
unsigned int i, j;
for (i = 0; i < ARRAY_SIZE (fixed_arith_modes); i++)
{
arm_set_fixed_optab_libfunc (add_optab, fixed_arith_modes[i].mode,
"add", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ssadd_optab, fixed_arith_modes[i].mode,
"ssadd", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (usadd_optab, fixed_arith_modes[i].mode,
"usadd", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (sub_optab, fixed_arith_modes[i].mode,
"sub", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (sssub_optab, fixed_arith_modes[i].mode,
"sssub", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ussub_optab, fixed_arith_modes[i].mode,
"ussub", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (smul_optab, fixed_arith_modes[i].mode,
"mul", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ssmul_optab, fixed_arith_modes[i].mode,
"ssmul", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (usmul_optab, fixed_arith_modes[i].mode,
"usmul", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (sdiv_optab, fixed_arith_modes[i].mode,
"div", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (udiv_optab, fixed_arith_modes[i].mode,
"udiv", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ssdiv_optab, fixed_arith_modes[i].mode,
"ssdiv", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (usdiv_optab, fixed_arith_modes[i].mode,
"usdiv", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (neg_optab, fixed_arith_modes[i].mode,
"neg", fixed_arith_modes[i].name, 2);
arm_set_fixed_optab_libfunc (ssneg_optab, fixed_arith_modes[i].mode,
"ssneg", fixed_arith_modes[i].name, 2);
arm_set_fixed_optab_libfunc (usneg_optab, fixed_arith_modes[i].mode,
"usneg", fixed_arith_modes[i].name, 2);
arm_set_fixed_optab_libfunc (ashl_optab, fixed_arith_modes[i].mode,
"ashl", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ashr_optab, fixed_arith_modes[i].mode,
"ashr", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (lshr_optab, fixed_arith_modes[i].mode,
"lshr", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ssashl_optab, fixed_arith_modes[i].mode,
"ssashl", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (usashl_optab, fixed_arith_modes[i].mode,
"usashl", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (cmp_optab, fixed_arith_modes[i].mode,
"cmp", fixed_arith_modes[i].name, 2);
}
for (i = 0; i < ARRAY_SIZE (fixed_conv_modes); i++)
for (j = 0; j < ARRAY_SIZE (fixed_conv_modes); j++)
{
if (i == j
|| (!ALL_FIXED_POINT_MODE_P (fixed_conv_modes[i].mode)
&& !ALL_FIXED_POINT_MODE_P (fixed_conv_modes[j].mode)))
continue;
arm_set_fixed_conv_libfunc (fract_optab, fixed_conv_modes[i].mode,
fixed_conv_modes[j].mode, "fract",
fixed_conv_modes[i].name,
fixed_conv_modes[j].name);
arm_set_fixed_conv_libfunc (satfract_optab,
fixed_conv_modes[i].mode,
fixed_conv_modes[j].mode, "satfract",
fixed_conv_modes[i].name,
fixed_conv_modes[j].name);
arm_set_fixed_conv_libfunc (fractuns_optab,
fixed_conv_modes[i].mode,
fixed_conv_modes[j].mode, "fractuns",
fixed_conv_modes[i].name,
fixed_conv_modes[j].name);
arm_set_fixed_conv_libfunc (satfractuns_optab,
fixed_conv_modes[i].mode,
fixed_conv_modes[j].mode, "satfractuns",
fixed_conv_modes[i].name,
fixed_conv_modes[j].name);
}
}
if (TARGET_AAPCS_BASED)
synchronize_libfunc = init_one_libfunc ("__sync_synchronize");
speculation_barrier_libfunc = init_one_libfunc ("__speculation_barrier");
}
/* On AAPCS systems, this is the "struct __va_list". */
static GTY(()) tree va_list_type;
/* Return the type to use as __builtin_va_list. */
static tree
arm_build_builtin_va_list (void)
{
tree va_list_name;
tree ap_field;
if (!TARGET_AAPCS_BASED)
return std_build_builtin_va_list ();
/* AAPCS \S 7.1.4 requires that va_list be a typedef for a type
defined as:
struct __va_list
{
void *__ap;
};
The C Library ABI further reinforces this definition in \S
4.1.
We must follow this definition exactly. The structure tag
name is visible in C++ mangled names, and thus forms a part
of the ABI. The field name may be used by people who
#include <stdarg.h>. */
/* Create the type. */
va_list_type = lang_hooks.types.make_type (RECORD_TYPE);
/* Give it the required name. */
va_list_name = build_decl (BUILTINS_LOCATION,
TYPE_DECL,
get_identifier ("__va_list"),
va_list_type);
DECL_ARTIFICIAL (va_list_name) = 1;
TYPE_NAME (va_list_type) = va_list_name;
TYPE_STUB_DECL (va_list_type) = va_list_name;
/* Create the __ap field. */
ap_field = build_decl (BUILTINS_LOCATION,
FIELD_DECL,
get_identifier ("__ap"),
ptr_type_node);
DECL_ARTIFICIAL (ap_field) = 1;
DECL_FIELD_CONTEXT (ap_field) = va_list_type;
TYPE_FIELDS (va_list_type) = ap_field;
/* Compute its layout. */
layout_type (va_list_type);
return va_list_type;
}
/* Return an expression of type "void *" pointing to the next
available argument in a variable-argument list. VALIST is the
user-level va_list object, of type __builtin_va_list. */
static tree
arm_extract_valist_ptr (tree valist)
{
if (TREE_TYPE (valist) == error_mark_node)
return error_mark_node;
/* On an AAPCS target, the pointer is stored within "struct
va_list". */
if (TARGET_AAPCS_BASED)
{
tree ap_field = TYPE_FIELDS (TREE_TYPE (valist));
valist = build3 (COMPONENT_REF, TREE_TYPE (ap_field),
valist, ap_field, NULL_TREE);
}
return valist;
}
/* Implement TARGET_EXPAND_BUILTIN_VA_START. */
static void
arm_expand_builtin_va_start (tree valist, rtx nextarg)
{
valist = arm_extract_valist_ptr (valist);
std_expand_builtin_va_start (valist, nextarg);
}
/* Implement TARGET_GIMPLIFY_VA_ARG_EXPR. */
static tree
arm_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
gimple_seq *post_p)
{
valist = arm_extract_valist_ptr (valist);
return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
}
/* Check any incompatible options that the user has specified. */
static void
arm_option_check_internal (struct gcc_options *opts)
{
int flags = opts->x_target_flags;
/* iWMMXt and NEON are incompatible. */
if (TARGET_IWMMXT
&& bitmap_bit_p (arm_active_target.isa, isa_bit_neon))
error ("iWMMXt and NEON are incompatible");
/* Make sure that the processor choice does not conflict with any of the
other command line choices. */
if (TARGET_ARM_P (flags)
&& !bitmap_bit_p (arm_active_target.isa, isa_bit_notm))
error ("target CPU does not support ARM mode");
/* TARGET_BACKTRACE cannot be used here as crtl->is_leaf is not set yet. */
if ((TARGET_TPCS_FRAME || TARGET_TPCS_LEAF_FRAME) && TARGET_ARM_P (flags))
warning (0, "enabling backtrace support is only meaningful when compiling for the Thumb");
if (TARGET_ARM_P (flags) && TARGET_CALLEE_INTERWORKING)
warning (0, "enabling callee interworking support is only meaningful when compiling for the Thumb");
/* If this target is normally configured to use APCS frames, warn if they
are turned off and debugging is turned on. */
if (TARGET_ARM_P (flags)
&& write_symbols != NO_DEBUG
&& !TARGET_APCS_FRAME
&& (TARGET_DEFAULT & MASK_APCS_FRAME))
warning (0, "%<-g%> with %<-mno-apcs-frame%> may not give sensible "
"debugging");
/* iWMMXt unsupported under Thumb mode. */
if (TARGET_THUMB_P (flags) && TARGET_IWMMXT)
error ("iWMMXt unsupported under Thumb mode");
if (TARGET_HARD_TP && TARGET_THUMB1_P (flags))
error ("cannot use %<-mtp=cp15%> with 16-bit Thumb");
if (TARGET_THUMB_P (flags) && TARGET_VXWORKS_RTP && flag_pic)
{
error ("RTP PIC is incompatible with Thumb");
flag_pic = 0;
}
if (target_pure_code || target_slow_flash_data)
{
const char *flag = (target_pure_code ? "-mpure-code" :
"-mslow-flash-data");
/* We only support -mpure-code and -mslow-flash-data on M-profile targets
with MOVT. */
if (!TARGET_HAVE_MOVT || arm_arch_notm || flag_pic || TARGET_NEON)
error ("%s only supports non-pic code on M-profile targets with the "
"MOVT instruction", flag);
/* Cannot load addresses: -mslow-flash-data forbids literal pool and
-mword-relocations forbids relocation of MOVT/MOVW. */
if (target_word_relocations)
error ("%s incompatible with %<-mword-relocations%>", flag);
}
}
/* Recompute the global settings depending on target attribute options. */
static void
arm_option_params_internal (void)
{
/* If we are not using the default (ARM mode) section anchor offset
ranges, then set the correct ranges now. */
if (TARGET_THUMB1)
{
/* Thumb-1 LDR instructions cannot have negative offsets.
Permissible positive offset ranges are 5-bit (for byte loads),
6-bit (for halfword loads), or 7-bit (for word loads).
Empirical results suggest a 7-bit anchor range gives the best
overall code size. */
targetm.min_anchor_offset = 0;
targetm.max_anchor_offset = 127;
}
else if (TARGET_THUMB2)
{
/* The minimum is set such that the total size of the block
for a particular anchor is 248 + 1 + 4095 bytes, which is
divisible by eight, ensuring natural spacing of anchors. */
targetm.min_anchor_offset = -248;
targetm.max_anchor_offset = 4095;
}
else
{
targetm.min_anchor_offset = TARGET_MIN_ANCHOR_OFFSET;
targetm.max_anchor_offset = TARGET_MAX_ANCHOR_OFFSET;
}
/* Increase the number of conditional instructions with -Os. */
max_insns_skipped = optimize_size ? 4 : current_tune->max_insns_skipped;
/* For THUMB2, we limit the conditional sequence to one IT block. */
if (TARGET_THUMB2)
max_insns_skipped = MIN (max_insns_skipped, MAX_INSN_PER_IT_BLOCK);
}
/* True if -mflip-thumb should next add an attribute for the default
mode, false if it should next add an attribute for the opposite mode. */
static GTY(()) bool thumb_flipper;
/* Options after initial target override. */
static GTY(()) tree init_optimize;
static void
arm_override_options_after_change_1 (struct gcc_options *opts)
{
/* -falign-functions without argument: supply one. */
if (opts->x_flag_align_functions && !opts->x_str_align_functions)
opts->x_str_align_functions = TARGET_THUMB_P (opts->x_target_flags)
&& opts->x_optimize_size ? "2" : "4";
}
/* Implement targetm.override_options_after_change. */
static void
arm_override_options_after_change (void)
{
arm_configure_build_target (&arm_active_target,
TREE_TARGET_OPTION (target_option_default_node),
&global_options_set, false);
arm_override_options_after_change_1 (&global_options);
}
/* Implement TARGET_OPTION_SAVE. */
static void
arm_option_save (struct cl_target_option *ptr, struct gcc_options *opts)
{
ptr->x_arm_arch_string = opts->x_arm_arch_string;
ptr->x_arm_cpu_string = opts->x_arm_cpu_string;
ptr->x_arm_tune_string = opts->x_arm_tune_string;
}
/* Implement TARGET_OPTION_RESTORE. */
static void
arm_option_restore (struct gcc_options *opts, struct cl_target_option *ptr)
{
opts->x_arm_arch_string = ptr->x_arm_arch_string;
opts->x_arm_cpu_string = ptr->x_arm_cpu_string;
opts->x_arm_tune_string = ptr->x_arm_tune_string;
arm_configure_build_target (&arm_active_target, ptr, &global_options_set,
false);
}
/* Reset options between modes that the user has specified. */
static void
arm_option_override_internal (struct gcc_options *opts,
struct gcc_options *opts_set)
{
arm_override_options_after_change_1 (opts);
if (TARGET_INTERWORK && !bitmap_bit_p (arm_active_target.isa, isa_bit_thumb))
{
/* The default is to enable interworking, so this warning message would
be confusing to users who have just compiled with
eg, -march=armv4. */
/* warning (0, "ignoring -minterwork because target CPU does not support THUMB"); */
opts->x_target_flags &= ~MASK_INTERWORK;
}
if (TARGET_THUMB_P (opts->x_target_flags)
&& !bitmap_bit_p (arm_active_target.isa, isa_bit_thumb))
{
warning (0, "target CPU does not support THUMB instructions");
opts->x_target_flags &= ~MASK_THUMB;
}
if (TARGET_APCS_FRAME && TARGET_THUMB_P (opts->x_target_flags))
{
/* warning (0, "ignoring -mapcs-frame because -mthumb was used"); */
opts->x_target_flags &= ~MASK_APCS_FRAME;
}
/* Callee super interworking implies thumb interworking. Adding
this to the flags here simplifies the logic elsewhere. */
if (TARGET_THUMB_P (opts->x_target_flags) && TARGET_CALLEE_INTERWORKING)
opts->x_target_flags |= MASK_INTERWORK;
/* need to remember initial values so combinaisons of options like
-mflip-thumb -mthumb -fno-schedule-insns work for any attribute. */
cl_optimization *to = TREE_OPTIMIZATION (init_optimize);
if (! opts_set->x_arm_restrict_it)
opts->x_arm_restrict_it = arm_arch8;
/* ARM execution state and M profile don't have [restrict] IT. */
if (!TARGET_THUMB2_P (opts->x_target_flags) || !arm_arch_notm)
opts->x_arm_restrict_it = 0;
/* Enable -munaligned-access by default for
- all ARMv6 architecture-based processors when compiling for a 32-bit ISA
i.e. Thumb2 and ARM state only.
- ARMv7-A, ARMv7-R, and ARMv7-M architecture-based processors.
- ARMv8 architecture-base processors.
Disable -munaligned-access by default for
- all pre-ARMv6 architecture-based processors
- ARMv6-M architecture-based processors
- ARMv8-M Baseline processors. */
if (! opts_set->x_unaligned_access)
{
opts->x_unaligned_access = (TARGET_32BIT_P (opts->x_target_flags)
&& arm_arch6 && (arm_arch_notm || arm_arch7));
}
else if (opts->x_unaligned_access == 1
&& !(arm_arch6 && (arm_arch_notm || arm_arch7)))
{
warning (0, "target CPU does not support unaligned accesses");
opts->x_unaligned_access = 0;
}
/* Don't warn since it's on by default in -O2. */
if (TARGET_THUMB1_P (opts->x_target_flags))
opts->x_flag_schedule_insns = 0;
else
opts->x_flag_schedule_insns = to->x_flag_schedule_insns;
/* Disable shrink-wrap when optimizing function for size, since it tends to
generate additional returns. */
if (optimize_function_for_size_p (cfun)
&& TARGET_THUMB2_P (opts->x_target_flags))
opts->x_flag_shrink_wrap = false;
else
opts->x_flag_shrink_wrap = to->x_flag_shrink_wrap;
/* In Thumb1 mode, we emit the epilogue in RTL, but the last insn
- epilogue_insns - does not accurately model the corresponding insns
emitted in the asm file. In particular, see the comment in thumb_exit
'Find out how many of the (return) argument registers we can corrupt'.
As a consequence, the epilogue may clobber registers without fipa-ra
finding out about it. Therefore, disable fipa-ra in Thumb1 mode.
TODO: Accurately model clobbers for epilogue_insns and reenable
fipa-ra. */
if (TARGET_THUMB1_P (opts->x_target_flags))
opts->x_flag_ipa_ra = 0;
else
opts->x_flag_ipa_ra = to->x_flag_ipa_ra;
/* Thumb2 inline assembly code should always use unified syntax.
This will apply to ARM and Thumb1 eventually. */
if (TARGET_THUMB2_P (opts->x_target_flags))
opts->x_inline_asm_unified = true;
#ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS
SUBTARGET_OVERRIDE_INTERNAL_OPTIONS;
#endif
}
static sbitmap isa_all_fpubits;
static sbitmap isa_quirkbits;
/* Configure a build target TARGET from the user-specified options OPTS and
OPTS_SET. If WARN_COMPATIBLE, emit a diagnostic if both the CPU and
architecture have been specified, but the two are not identical. */
void
arm_configure_build_target (struct arm_build_target *target,
struct cl_target_option *opts,
struct gcc_options *opts_set,
bool warn_compatible)
{
const cpu_option *arm_selected_tune = NULL;
const arch_option *arm_selected_arch = NULL;
const cpu_option *arm_selected_cpu = NULL;
const arm_fpu_desc *arm_selected_fpu = NULL;
const char *tune_opts = NULL;
const char *arch_opts = NULL;
const char *cpu_opts = NULL;
bitmap_clear (target->isa);
target->core_name = NULL;
target->arch_name = NULL;
if (opts_set->x_arm_arch_string)
{
arm_selected_arch = arm_parse_arch_option_name (all_architectures,
"-march",
opts->x_arm_arch_string);
arch_opts = strchr (opts->x_arm_arch_string, '+');
}
if (opts_set->x_arm_cpu_string)
{
arm_selected_cpu = arm_parse_cpu_option_name (all_cores, "-mcpu",
opts->x_arm_cpu_string);
cpu_opts = strchr (opts->x_arm_cpu_string, '+');
arm_selected_tune = arm_selected_cpu;
/* If taking the tuning from -mcpu, we don't need to rescan the
options for tuning. */
}
if (opts_set->x_arm_tune_string)
{
arm_selected_tune = arm_parse_cpu_option_name (all_cores, "-mtune",
opts->x_arm_tune_string);
tune_opts = strchr (opts->x_arm_tune_string, '+');
}
if (arm_selected_arch)
{
arm_initialize_isa (target->isa, arm_selected_arch->common.isa_bits);
arm_parse_option_features (target->isa, &arm_selected_arch->common,
arch_opts);
if (arm_selected_cpu)
{
auto_sbitmap cpu_isa (isa_num_bits);
auto_sbitmap isa_delta (isa_num_bits);
arm_initialize_isa (cpu_isa, arm_selected_cpu->common.isa_bits);
arm_parse_option_features (cpu_isa, &arm_selected_cpu->common,
cpu_opts);
bitmap_xor (isa_delta, cpu_isa, target->isa);
/* Ignore any bits that are quirk bits. */
bitmap_and_compl (isa_delta, isa_delta, isa_quirkbits);
/* Ignore (for now) any bits that might be set by -mfpu. */
bitmap_and_compl (isa_delta, isa_delta, isa_all_fpubits);
if (!bitmap_empty_p (isa_delta))
{
if (warn_compatible)
warning (0, "switch %<-mcpu=%s%> conflicts "
"with %<-march=%s%> switch",
arm_selected_cpu->common.name,
arm_selected_arch->common.name);
/* -march wins for code generation.
-mcpu wins for default tuning. */
if (!arm_selected_tune)
arm_selected_tune = arm_selected_cpu;
arm_selected_cpu = all_cores + arm_selected_arch->tune_id;
target->arch_name = arm_selected_arch->common.name;
}
else
{
/* Architecture and CPU are essentially the same.
Prefer the CPU setting. */
arm_selected_arch = all_architectures + arm_selected_cpu->arch;
target->core_name = arm_selected_cpu->common.name;
/* Copy the CPU's capabilities, so that we inherit the
appropriate extensions and quirks. */
bitmap_copy (target->isa, cpu_isa);
}
}
else
{
/* Pick a CPU based on the architecture. */
arm_selected_cpu = all_cores + arm_selected_arch->tune_id;
target->arch_name = arm_selected_arch->common.name;
/* Note: target->core_name is left unset in this path. */
}
}
else if (arm_selected_cpu)
{
target->core_name = arm_selected_cpu->common.name;
arm_initialize_isa (target->isa, arm_selected_cpu->common.isa_bits);
arm_parse_option_features (target->isa, &arm_selected_cpu->common,
cpu_opts);
arm_selected_arch = all_architectures + arm_selected_cpu->arch;
}
/* If the user did not specify a processor or architecture, choose
one for them. */
else
{
const cpu_option *sel;
auto_sbitmap sought_isa (isa_num_bits);
bitmap_clear (sought_isa);
auto_sbitmap default_isa (isa_num_bits);
arm_selected_cpu = arm_parse_cpu_option_name (all_cores, "default CPU",
TARGET_CPU_DEFAULT);
cpu_opts = strchr (TARGET_CPU_DEFAULT, '+');
gcc_assert (arm_selected_cpu->common.name);
/* RWE: All of the selection logic below (to the end of this
'if' clause) looks somewhat suspect. It appears to be mostly
there to support forcing thumb support when the default CPU
does not have thumb (somewhat dubious in terms of what the
user might be expecting). I think it should be removed once
support for the pre-thumb era cores is removed. */
sel = arm_selected_cpu;
arm_initialize_isa (default_isa, sel->common.isa_bits);
arm_parse_option_features (default_isa, &arm_selected_cpu->common,
cpu_opts);
/* Now check to see if the user has specified any command line
switches that require certain abilities from the cpu. */
if (TARGET_INTERWORK || TARGET_THUMB)
bitmap_set_bit (sought_isa, isa_bit_thumb);
/* If there are such requirements and the default CPU does not
satisfy them, we need to run over the complete list of
cores looking for one that is satisfactory. */
if (!bitmap_empty_p (sought_isa)
&& !bitmap_subset_p (sought_isa, default_isa))
{
auto_sbitmap candidate_isa (isa_num_bits);
/* We're only interested in a CPU with at least the
capabilities of the default CPU and the required
additional features. */
bitmap_ior (default_isa, default_isa, sought_isa);
/* 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->common.name != NULL; sel++)
{
arm_initialize_isa (candidate_isa, sel->common.isa_bits);
/* An exact match? */
if (bitmap_equal_p (default_isa, candidate_isa))
break;
}
if (sel->common.name == NULL)
{
unsigned current_bit_count = isa_num_bits;
const cpu_option *best_fit = NULL;
/* Ideally we would like to issue an error message here
saying that it was not possible to find a CPU compatible
with the default CPU, but which also supports the command
line options specified by the programmer, and so they
ought to use the -mcpu=<name> command line option to
override the default CPU type.
If we cannot find a CPU that has exactly the
characteristics of the default CPU and the given
command line options we scan the array again looking
for a best match. The best match must have at least
the capabilities of the perfect match. */
for (sel = all_cores; sel->common.name != NULL; sel++)
{
arm_initialize_isa (candidate_isa, sel->common.isa_bits);
if (bitmap_subset_p (default_isa, candidate_isa))
{
unsigned count;
bitmap_and_compl (candidate_isa, candidate_isa,
default_isa);
count = bitmap_popcount (candidate_isa);
if (count < current_bit_count)
{
best_fit = sel;
current_bit_count = count;
}
}
gcc_assert (best_fit);
sel = best_fit;
}
}
arm_selected_cpu = sel;
}
/* Now we know the CPU, we can finally initialize the target
structure. */
target->core_name = arm_selected_cpu->common.name;
arm_initialize_isa (target->isa, arm_selected_cpu->common.isa_bits);
arm_parse_option_features (target->isa, &arm_selected_cpu->common,
cpu_opts);
arm_selected_arch = all_architectures + arm_selected_cpu->arch;
}
gcc_assert (arm_selected_cpu);
gcc_assert (arm_selected_arch);
if (opts->x_arm_fpu_index != TARGET_FPU_auto)
{
arm_selected_fpu = &all_fpus[opts->x_arm_fpu_index];
auto_sbitmap fpu_bits (isa_num_bits);
arm_initialize_isa (fpu_bits, arm_selected_fpu->isa_bits);
bitmap_and_compl (target->isa, target->isa, isa_all_fpubits);
bitmap_ior (target->isa, target->isa, fpu_bits);
}
if (!arm_selected_tune)
arm_selected_tune = arm_selected_cpu;
else /* Validate the features passed to -mtune. */
arm_parse_option_features (NULL, &arm_selected_tune->common, tune_opts);
const cpu_tune *tune_data = &all_tunes[arm_selected_tune - all_cores];
/* Finish initializing the target structure. */
target->arch_pp_name = arm_selected_arch->arch;
target->base_arch = arm_selected_arch->base_arch;
target->profile = arm_selected_arch->profile;
target->tune_flags = tune_data->tune_flags;
target->tune = tune_data->tune;
target->tune_core = tune_data->scheduler;
arm_option_reconfigure_globals ();
}
/* Fix up any incompatible options that the user has specified. */
static void
arm_option_override (void)
{
static const enum isa_feature fpu_bitlist[]
= { ISA_ALL_FPU_INTERNAL, isa_nobit };
static const enum isa_feature quirk_bitlist[] = { ISA_ALL_QUIRKS, isa_nobit};
cl_target_option opts;
isa_quirkbits = sbitmap_alloc (isa_num_bits);
arm_initialize_isa (isa_quirkbits, quirk_bitlist);
isa_all_fpubits = sbitmap_alloc (isa_num_bits);
arm_initialize_isa (isa_all_fpubits, fpu_bitlist);
arm_active_target.isa = sbitmap_alloc (isa_num_bits);
if (!global_options_set.x_arm_fpu_index)
{
bool ok;
int fpu_index;
ok = opt_enum_arg_to_value (OPT_mfpu_, FPUTYPE_AUTO, &fpu_index,
CL_TARGET);
gcc_assert (ok);
arm_fpu_index = (enum fpu_type) fpu_index;
}
cl_target_option_save (&opts, &global_options);
arm_configure_build_target (&arm_active_target, &opts, &global_options_set,
true);
#ifdef SUBTARGET_OVERRIDE_OPTIONS
SUBTARGET_OVERRIDE_OPTIONS;
#endif
/* Initialize boolean versions of the architectural flags, for use
in the arm.md file and for enabling feature flags. */
arm_option_reconfigure_globals ();
arm_tune = arm_active_target.tune_core;
tune_flags = arm_active_target.tune_flags;
current_tune = arm_active_target.tune;
/* TBD: Dwarf info for apcs frame is not handled yet. */
if (TARGET_APCS_FRAME)
flag_shrink_wrap = false;
if (TARGET_APCS_STACK && !TARGET_APCS_FRAME)
{
warning (0, "%<-mapcs-stack-check%> incompatible with "
"%<-mno-apcs-frame%>");
target_flags |= MASK_APCS_FRAME;
}
if (TARGET_POKE_FUNCTION_NAME)
target_flags |= MASK_APCS_FRAME;
if (TARGET_APCS_REENT && flag_pic)
error ("%<-fpic%> and %<-mapcs-reent%> are incompatible");
if (TARGET_APCS_REENT)
warning (0, "APCS reentrant code not supported. Ignored");
/* Set up some tuning parameters. */
arm_ld_sched = (tune_flags & TF_LDSCHED) != 0;
arm_tune_strongarm = (tune_flags & TF_STRONG) != 0;
arm_tune_wbuf = (tune_flags & TF_WBUF) != 0;
arm_tune_xscale = (tune_flags & TF_XSCALE) != 0;
arm_tune_cortex_a9 = (arm_tune == TARGET_CPU_cortexa9) != 0;
arm_m_profile_small_mul = (tune_flags & TF_SMALLMUL) != 0;
/* For arm2/3 there is no need to do any scheduling if we are doing
software floating-point. */
if (TARGET_SOFT_FLOAT && (tune_flags & TF_NO_MODE32))
flag_schedule_insns = flag_schedule_insns_after_reload = 0;
/* Override the default structure alignment for AAPCS ABI. */
if (!global_options_set.x_arm_structure_size_boundary)
{
if (TARGET_AAPCS_BASED)
arm_structure_size_boundary = 8;
}
else
{
warning (0, "option %<-mstructure-size-boundary%> is deprecated");
if (arm_structure_size_boundary != 8
&& arm_structure_size_boundary != 32
&& !(ARM_DOUBLEWORD_ALIGN && arm_structure_size_boundary == 64))
{
if (ARM_DOUBLEWORD_ALIGN)
warning (0,
"structure size boundary can only be set to 8, 32 or 64");
else
warning (0, "structure size boundary can only be set to 8 or 32");
arm_structure_size_boundary
= (TARGET_AAPCS_BASED ? 8 : DEFAULT_STRUCTURE_SIZE_BOUNDARY);
}
}
if (TARGET_VXWORKS_RTP)
{
if (!global_options_set.x_arm_pic_data_is_text_relative)
arm_pic_data_is_text_relative = 0;
}
else if (flag_pic
&& !arm_pic_data_is_text_relative
&& !(global_options_set.x_target_flags & MASK_SINGLE_PIC_BASE))
/* When text & data segments don't have a fixed displacement, the
intended use is with a single, read only, pic base register.
Unless the user explicitly requested not to do that, set
it. */
target_flags |= MASK_SINGLE_PIC_BASE;
/* If stack checking is disabled, we can use r10 as the PIC register,
which keeps r9 available. The EABI specifies r9 as the PIC register. */
if (flag_pic && TARGET_SINGLE_PIC_BASE)
{
if (TARGET_VXWORKS_RTP)
warning (0, "RTP PIC is incompatible with %<-msingle-pic-base%>");
arm_pic_register = (TARGET_APCS_STACK || TARGET_AAPCS_BASED) ? 9 : 10;
}
if (flag_pic && TARGET_VXWORKS_RTP)
arm_pic_register = 9;
/* If in FDPIC mode then force arm_pic_register to be r9. */
if (TARGET_FDPIC)
{
arm_pic_register = FDPIC_REGNUM;
if (TARGET_THUMB1)
sorry ("FDPIC mode is not supported in Thumb-1 mode");
}
if (arm_pic_register_string != NULL)
{
int pic_register = decode_reg_name (arm_pic_register_string);
if (!flag_pic)
warning (0, "%<-mpic-register=%> is useless without %<-fpic%>");
/* Prevent the user from choosing an obviously stupid PIC register. */
else if (pic_register < 0 || call_used_or_fixed_reg_p (pic_register)
|| pic_register == HARD_FRAME_POINTER_REGNUM
|| pic_register == STACK_POINTER_REGNUM
|| pic_register >= PC_REGNUM
|| (TARGET_VXWORKS_RTP
&& (unsigned int) pic_register != arm_pic_register))
error ("unable to use %qs for PIC register", arm_pic_register_string);
else
arm_pic_register = pic_register;
}
if (flag_pic)
target_word_relocations = 1;
/* Enable -mfix-cortex-m3-ldrd by default for Cortex-M3 cores. */
if (fix_cm3_ldrd == 2)
{
if (bitmap_bit_p (arm_active_target.isa, isa_bit_quirk_cm3_ldrd))
fix_cm3_ldrd = 1;
else
fix_cm3_ldrd = 0;
}
/* Hot/Cold partitioning is not currently supported, since we can't
handle literal pool placement in that case. */
if (flag_reorder_blocks_and_partition)
{
inform (input_location,
"%<-freorder-blocks-and-partition%> not supported "
"on this architecture");
flag_reorder_blocks_and_partition = 0;
flag_reorder_blocks = 1;
}
if (flag_pic)
/* Hoisting PIC address calculations more aggressively provides a small,
but measurable, size reduction for PIC code. Therefore, we decrease
the bar for unrestricted expression hoisting to the cost of PIC address
calculation, which is 2 instructions. */
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_gcse_unrestricted_cost, 2);
/* ARM EABI defaults to strict volatile bitfields. */
if (TARGET_AAPCS_BASED && flag_strict_volatile_bitfields < 0
&& abi_version_at_least(2))
flag_strict_volatile_bitfields = 1;
/* Enable sw prefetching at -O3 for CPUS that have prefetch, and we
have deemed it beneficial (signified by setting
prefetch.num_slots to 1 or more). */
if (flag_prefetch_loop_arrays < 0
&& HAVE_prefetch
&& optimize >= 3
&& current_tune->prefetch.num_slots > 0)
flag_prefetch_loop_arrays = 1;
/* Set up parameters to be used in prefetching algorithm. Do not
override the defaults unless we are tuning for a core we have
researched values for. */
if (current_tune->prefetch.num_slots > 0)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_simultaneous_prefetches,
current_tune->prefetch.num_slots);
if (current_tune->prefetch.l1_cache_line_size >= 0)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_l1_cache_line_size,
current_tune->prefetch.l1_cache_line_size);
if (current_tune->prefetch.l1_cache_size >= 0)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_l1_cache_size,
current_tune->prefetch.l1_cache_size);
/* Look through ready list and all of queue for instructions
relevant for L2 auto-prefetcher. */
int sched_autopref_queue_depth;
switch (current_tune->sched_autopref)
{
case tune_params::SCHED_AUTOPREF_OFF:
sched_autopref_queue_depth = -1;
break;
case tune_params::SCHED_AUTOPREF_RANK:
sched_autopref_queue_depth = 0;
break;
case tune_params::SCHED_AUTOPREF_FULL:
sched_autopref_queue_depth = max_insn_queue_index + 1;
break;
default:
gcc_unreachable ();
}
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_sched_autopref_queue_depth,
sched_autopref_queue_depth);
/* Currently, for slow flash data, we just disable literal pools. We also
disable it for pure-code. */
if (target_slow_flash_data || target_pure_code)
arm_disable_literal_pool = true;
/* Disable scheduling fusion by default if it's not armv7 processor
or doesn't prefer ldrd/strd. */
if (flag_schedule_fusion == 2
&& (!arm_arch7 || !current_tune->prefer_ldrd_strd))
flag_schedule_fusion = 0;
/* Need to remember initial options before they are overriden. */
init_optimize = build_optimization_node (&global_options);
arm_options_perform_arch_sanity_checks ();
arm_option_override_internal (&global_options, &global_options_set);
arm_option_check_internal (&global_options);
arm_option_params_internal ();
/* Create the default target_options structure. */
target_option_default_node = target_option_current_node
= build_target_option_node (&global_options);
/* Register global variables with the garbage collector. */
arm_add_gc_roots ();