blob: 67bab17a9d77a54b69394505e55d67d4ab4416d5 [file] [log] [blame]
/* Output routines for GCC for ARM.
Copyright (C) 1991-2015 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/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "hash-table.h"
#include "tm.h"
#include "rtl.h"
#include "hash-set.h"
#include "machmode.h"
#include "vec.h"
#include "double-int.h"
#include "input.h"
#include "alias.h"
#include "symtab.h"
#include "wide-int.h"
#include "inchash.h"
#include "tree.h"
#include "fold-const.h"
#include "stringpool.h"
#include "stor-layout.h"
#include "calls.h"
#include "varasm.h"
#include "obstack.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "insn-config.h"
#include "conditions.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
#include "reload.h"
#include "function.h"
#include "hashtab.h"
#include "statistics.h"
#include "real.h"
#include "fixed-value.h"
#include "expmed.h"
#include "dojump.h"
#include "explow.h"
#include "emit-rtl.h"
#include "stmt.h"
#include "expr.h"
#include "insn-codes.h"
#include "optabs.h"
#include "diagnostic-core.h"
#include "recog.h"
#include "predict.h"
#include "dominance.h"
#include "cfg.h"
#include "cfgrtl.h"
#include "cfganal.h"
#include "lcm.h"
#include "cfgbuild.h"
#include "cfgcleanup.h"
#include "basic-block.h"
#include "hash-map.h"
#include "is-a.h"
#include "plugin-api.h"
#include "ipa-ref.h"
#include "cgraph.h"
#include "ggc.h"
#include "except.h"
#include "tm_p.h"
#include "target.h"
#include "sched-int.h"
#include "target-def.h"
#include "debug.h"
#include "langhooks.h"
#include "df.h"
#include "intl.h"
#include "libfuncs.h"
#include "params.h"
#include "opts.h"
#include "dumpfile.h"
#include "gimple-expr.h"
#include "builtins.h"
#include "tm-constrs.h"
#include "rtl-iter.h"
#include "sched-int.h"
/* Forward definitions of types. */
typedef struct minipool_node Mnode;
typedef struct minipool_fixup Mfix;
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 bool 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_add_gc_roots (void);
static int arm_gen_constant (enum rtx_code, machine_mode, rtx,
HOST_WIDE_INT, rtx, rtx, int, int);
static unsigned bit_count (unsigned long);
static int arm_address_register_rtx_p (rtx, int);
static int arm_legitimate_index_p (machine_mode, rtx, RTX_CODE, int);
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 *, 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 HOST_WIDE_INT int_log2 (HOST_WIDE_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);
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_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 void arm_output_function_epilogue (FILE *, HOST_WIDE_INT);
static void arm_output_function_prologue (FILE *, HOST_WIDE_INT);
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 *, rtx, rtx_insn *, 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_1 (rtx, enum rtx_code, int*, bool);
static bool arm_size_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *);
static bool arm_slowmul_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
static bool arm_fastmul_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
static bool arm_xscale_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
static bool arm_9e_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
static bool arm_rtx_costs (rtx, int, int, int, int *, 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, machine_mode,
tree, bool);
static rtx arm_function_arg (cumulative_args_t, machine_mode,
const_tree, bool);
static void arm_function_arg_advance (cumulative_args_t, machine_mode,
const_tree, bool);
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_setup_incoming_varargs (cumulative_args_t, machine_mode,
tree, int *, int);
static bool arm_pass_by_reference (cumulative_args_t,
machine_mode, const_tree, bool);
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 (machine_mode, const_tree);
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);
static void arm_asm_init_sections (void);
#endif
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 unsigned HOST_WIDE_INT arm_shift_truncation_mask (machine_mode);
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_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 const char *arm_invalid_parameter_type (const_tree t);
static const char *arm_invalid_return_type (const_tree t);
static tree arm_promoted_type (const_tree t);
static tree arm_convert_to_type (tree type, tree expr);
static bool arm_scalar_mode_supported_p (machine_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 arm_pic_static_addr (rtx orig, rtx reg);
static bool cortex_a9_sched_adjust_cost (rtx_insn *, rtx, rtx_insn *, int *);
static bool xscale_sched_adjust_cost (rtx_insn *, rtx, rtx_insn *, int *);
static bool fa726te_sched_adjust_cost (rtx_insn *, rtx, rtx_insn *, int *);
static bool arm_array_mode_supported_p (machine_mode,
unsigned HOST_WIDE_INT);
static machine_mode arm_preferred_simd_mode (machine_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 reg_class_t arm_preferred_rename_class (reg_class_t rclass);
static unsigned int arm_autovectorize_vector_sizes (void);
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_ok (machine_mode vmode,
const unsigned char *sel);
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*);
/* Table of machine attributes. */
static const struct attribute_spec arm_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
affects_type_identity } */
/* 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, NULL, false },
/* Whereas these functions are always known to reside within the 26 bit
addressing range. */
{ "short_call", 0, 0, false, true, true, NULL, false },
/* Specify the procedure call conventions for a function. */
{ "pcs", 1, 1, false, true, true, arm_handle_pcs_attribute,
false },
/* Interrupt Service Routines have special prologue and epilogue requirements. */
{ "isr", 0, 1, false, false, false, arm_handle_isr_attribute,
false },
{ "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute,
false },
{ "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute,
false },
#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, NULL, false },
{ "dllexport", 0, 0, true, false, false, NULL, false },
{ "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute,
false },
#elif TARGET_DLLIMPORT_DECL_ATTRIBUTES
{ "dllimport", 0, 0, false, false, false, handle_dll_attribute, false },
{ "dllexport", 0, 0, false, false, false, handle_dll_attribute, false },
{ "notshared", 0, 0, false, true, false, arm_handle_notshared_attribute,
false },
#endif
{ NULL, 0, 0, false, false, false, NULL, false }
};
/* 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_LEGITIMIZE_ADDRESS
#define TARGET_LEGITIMIZE_ADDRESS arm_legitimize_address
#undef TARGET_LRA_P
#define TARGET_LRA_P hook_bool_void_true
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE arm_attribute_table
#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_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE arm_option_override
#undef TARGET_COMP_TYPE_ATTRIBUTES
#define TARGET_COMP_TYPE_ATTRIBUTES arm_comp_type_attributes
#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_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_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 default_can_output_mi_thunk_no_vcall
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS arm_rtx_costs
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST arm_address_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_SIZES
#define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES \
arm_autovectorize_vector_sizes
#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_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
#undef TARGET_ASM_INIT_SECTIONS
#define TARGET_ASM_INIT_SECTIONS arm_asm_init_sections
#endif /* ARM_UNWIND_INFO */
#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_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_INVALID_PARAMETER_TYPE
#define TARGET_INVALID_PARAMETER_TYPE arm_invalid_parameter_type
#undef TARGET_INVALID_RETURN_TYPE
#define TARGET_INVALID_RETURN_TYPE arm_invalid_return_type
#undef TARGET_PROMOTED_TYPE
#define TARGET_PROMOTED_TYPE arm_promoted_type
#undef TARGET_CONVERT_TO_TYPE
#define TARGET_CONVERT_TO_TYPE arm_convert_to_type
#undef TARGET_SCALAR_MODE_SUPPORTED_P
#define TARGET_SCALAR_MODE_SUPPORTED_P arm_scalar_mode_supported_p
#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_OK
#define TARGET_VECTORIZE_VEC_PERM_CONST_OK \
arm_vectorize_vec_perm_const_ok
#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
struct gcc_target targetm = TARGET_INITIALIZER;
/* 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 = arm_none;
/* The current tuning set. */
const struct tune_params *current_tune;
/* Which floating point hardware to schedule for. */
int arm_fpu_attr;
/* Which floating popint hardware to use. */
const struct arm_fpu_desc *arm_fpu_desc;
/* 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
instructions we are allowed to generate. */
unsigned long insn_flags = 0;
/* The bits in this mask specify which instruction scheduling options should
be used. */
unsigned long tune_flags = 0;
/* The highest ARM architecture version supported by the
target. */
enum base_architecture arm_base_arch = BASE_ARCH_0;
/* 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 3M extensions. */
int arm_arch3m = 0;
/* 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 5 extensions. */
int arm_arch5 = 0;
/* Nonzero if this chip supports the ARM Architecture 5E extensions. */
int arm_arch5e = 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 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 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 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 generating Thumb instructions. */
int thumb_code = 0;
/* Nonzero if generating Thumb-1 instructions. */
int thumb1_code = 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 2. */
int arm_arch_thumb2;
/* Nonzero if chip supports integer division instruction. */
int arm_arch_arm_hwdiv;
int arm_arch_thumb_hwdiv;
/* Nonzero if this chip supports the Large Physical Address Extension. */
int arm_arch_lpae;
/* Nonzero if chip disallows volatile memory access in IT block. */
int arm_arch_no_volatile_ce;
/* Nonzero if we should use Neon to handle 64-bits operations rather
than core registers. */
int prefer_neon_for_64bits = 0;
/* Nonzero if we shouldn't use literal pools. */
bool arm_disable_literal_pool = false;
/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference,
we must report the mode of the memory reference from
TARGET_PRINT_OPERAND to TARGET_PRINT_OPERAND_ADDRESS. */
machine_mode output_memory_reference_mode;
/* 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 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 (TARGET_UNIFIED_ASM ? "lsl" : "asl")
#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 processors
{
const char *const name;
enum processor_type core;
const char *arch;
enum base_architecture base_arch;
const unsigned long flags;
const struct tune_params *const tune;
};
#define ARM_PREFETCH_NOT_BENEFICIAL 0, -1, -1
#define ARM_PREFETCH_BENEFICIAL(prefetch_slots,l1_size,l1_line_size) \
prefetch_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. */
},
{
/* 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. */
},
{
/* 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. */
},
{
/* 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. */
},
{
/* 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. */
},
{
/* 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. */
},
{
/* 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. */
},
{
/* 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. */
}
};
#define ARM_FUSE_NOTHING (0)
#define ARM_FUSE_MOVW_MOVT (1 << 0)
const struct tune_params arm_slowmul_tune =
{
arm_slowmul_rtx_costs,
NULL,
NULL, /* Sched adj cost. */
3, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
true, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
const struct tune_params arm_fastmul_tune =
{
arm_fastmul_rtx_costs,
NULL,
NULL, /* Sched adj cost. */
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
true, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
/* 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 =
{
arm_fastmul_rtx_costs,
NULL,
NULL, /* Sched adj cost. */
1, /* Constant limit. */
3, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
true, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
const struct tune_params arm_xscale_tune =
{
arm_xscale_rtx_costs,
NULL,
xscale_sched_adjust_cost,
2, /* Constant limit. */
3, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
true, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
const struct tune_params arm_9e_tune =
{
arm_9e_rtx_costs,
NULL,
NULL, /* Sched adj cost. */
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
true, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
const struct tune_params arm_v6t2_tune =
{
arm_9e_rtx_costs,
NULL,
NULL, /* Sched adj cost. */
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
false, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
/* Generic Cortex tuning. Use more specific tunings if appropriate. */
const struct tune_params arm_cortex_tune =
{
arm_9e_rtx_costs,
&generic_extra_costs,
NULL, /* Sched adj cost. */
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
false, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
const struct tune_params arm_cortex_a8_tune =
{
arm_9e_rtx_costs,
&cortexa8_extra_costs,
NULL, /* Sched adj cost. */
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
false, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
true, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
const struct tune_params arm_cortex_a7_tune =
{
arm_9e_rtx_costs,
&cortexa7_extra_costs,
NULL,
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
false, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
true, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
const struct tune_params arm_cortex_a15_tune =
{
arm_9e_rtx_costs,
&cortexa15_extra_costs,
NULL, /* Sched adj cost. */
1, /* Constant limit. */
2, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
false, /* Prefer constant pool. */
arm_default_branch_cost,
true, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
true, true, /* Prefer 32-bit encodings. */
true, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_FULL /* Sched L2 autopref. */
};
const struct tune_params arm_cortex_a53_tune =
{
arm_9e_rtx_costs,
&cortexa53_extra_costs,
NULL, /* Scheduler cost adjustment. */
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
false, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
true, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_MOVW_MOVT, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
const struct tune_params arm_cortex_a57_tune =
{
arm_9e_rtx_costs,
&cortexa57_extra_costs,
NULL, /* Scheduler cost adjustment. */
1, /* Constant limit. */
2, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
false, /* Prefer constant pool. */
arm_default_branch_cost,
true, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
true, true, /* Prefer 32-bit encodings. */
true, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_MOVW_MOVT, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_FULL /* Sched L2 autopref. */
};
const struct tune_params arm_xgene1_tune =
{
arm_9e_rtx_costs,
&xgene1_extra_costs,
NULL, /* Scheduler cost adjustment. */
1, /* Constant limit. */
2, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
false, /* Prefer constant pool. */
arm_default_branch_cost,
true, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
true, true, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
32, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
/* 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 =
{
arm_9e_rtx_costs,
&cortexa5_extra_costs,
NULL, /* Sched adj cost. */
1, /* Constant limit. */
1, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
false, /* Prefer constant pool. */
arm_cortex_a5_branch_cost,
false, /* Prefer LDRD/STRD. */
{false, false}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
true, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
const struct tune_params arm_cortex_a9_tune =
{
arm_9e_rtx_costs,
&cortexa9_extra_costs,
cortex_a9_sched_adjust_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_BENEFICIAL(4,32,32),
false, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
const struct tune_params arm_cortex_a12_tune =
{
arm_9e_rtx_costs,
&cortexa12_extra_costs,
NULL, /* Sched adj cost. */
1, /* Constant limit. */
2, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
false, /* Prefer constant pool. */
arm_default_branch_cost,
true, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
true, true, /* Prefer 32-bit encodings. */
true, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_MOVW_MOVT, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
/* 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 =
{
arm_9e_rtx_costs,
&v7m_extra_costs,
NULL, /* Sched adj cost. */
1, /* Constant limit. */
2, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
true, /* Prefer constant pool. */
arm_cortex_m_branch_cost,
false, /* Prefer LDRD/STRD. */
{false, false}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
/* Cortex-M7 tuning. */
const struct tune_params arm_cortex_m7_tune =
{
arm_9e_rtx_costs,
&v7m_extra_costs,
NULL, /* Sched adj cost. */
0, /* Constant limit. */
1, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
true, /* Prefer constant pool. */
arm_cortex_m7_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
/* The arm_v6m_tune is duplicated from arm_cortex_tune, rather than
arm_v6t2_tune. It is used for cortex-m0, cortex-m1 and cortex-m0plus. */
const struct tune_params arm_v6m_tune =
{
arm_9e_rtx_costs,
NULL,
NULL, /* Sched adj cost. */
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
false, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{false, false}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
const struct tune_params arm_fa726te_tune =
{
arm_9e_rtx_costs,
NULL,
fa726te_sched_adjust_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
true, /* Prefer constant pool. */
arm_default_branch_cost,
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
false, /* Prefer Neon for 64-bits bitops. */
false, false, /* Prefer 32-bit encodings. */
false, /* Prefer Neon for stringops. */
8, /* Maximum insns to inline memset. */
ARM_FUSE_NOTHING, /* Fuseable pairs of instructions. */
ARM_SCHED_AUTOPREF_OFF /* Sched L2 autopref. */
};
/* Not all of these give usefully different compilation alternatives,
but there is no simple way of generalizing them. */
static const struct processors all_cores[] =
{
/* ARM Cores */
#define ARM_CORE(NAME, X, IDENT, ARCH, FLAGS, COSTS) \
{NAME, IDENT, #ARCH, BASE_ARCH_##ARCH, \
FLAGS | FL_FOR_ARCH##ARCH, &arm_##COSTS##_tune},
#include "arm-cores.def"
#undef ARM_CORE
{NULL, arm_none, NULL, BASE_ARCH_0, 0, NULL}
};
static const struct processors all_architectures[] =
{
/* ARM Architectures */
/* We don't specify tuning costs here as it will be figured out
from the core. */
#define ARM_ARCH(NAME, CORE, ARCH, FLAGS) \
{NAME, CORE, #ARCH, BASE_ARCH_##ARCH, FLAGS, NULL},
#include "arm-arches.def"
#undef ARM_ARCH
{NULL, arm_none, NULL, BASE_ARCH_0, 0, NULL}
};
/* These are populated as commandline arguments are processed, or NULL
if not specified. */
static const struct processors *arm_selected_arch;
static const struct processors *arm_selected_cpu;
static const struct processors *arm_selected_tune;
/* The name of the preprocessor macro to define for this architecture. */
char arm_arch_name[] = "__ARM_ARCH_0UNK__";
/* Available values for -mfpu=. */
static const struct arm_fpu_desc all_fpus[] =
{
#define ARM_FPU(NAME, MODEL, REV, VFP_REGS, NEON, FP16, CRYPTO) \
{ NAME, MODEL, REV, VFP_REGS, NEON, FP16, CRYPTO },
#include "arm-fpus.def"
#undef ARM_FPU
};
/* Supported TLS relocations. */
enum tls_reloc {
TLS_GD32,
TLS_LDM32,
TLS_LDO32,
TLS_IE32,
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 (VOIDmode, 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;
}
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);
}
/* 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"));
/* 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[] =
{
{ QQmode, "qq" },
{ UQQmode, "uqq" },
{ HQmode, "hq" },
{ UHQmode, "uhq" },
{ SQmode, "sq" },
{ USQmode, "usq" },
{ DQmode, "dq" },
{ UDQmode, "udq" },
{ TQmode, "tq" },
{ UTQmode, "utq" },
{ HAmode, "ha" },
{ UHAmode, "uha" },
{ SAmode, "sa" },
{ USAmode, "usa" },
{ DAmode, "da" },
{ UDAmode, "uda" },
{ TAmode, "ta" },
{ UTAmode, "uta" }
};
const arm_fixed_mode_set fixed_conv_modes[] =
{
{ QQmode, "qq" },
{ UQQmode, "uqq" },
{ HQmode, "hq" },
{ UHQmode, "uhq" },
{ SQmode, "sq" },
{ USQmode, "usq" },
{ DQmode, "dq" },
{ UDQmode, "udq" },
{ TQmode, "tq" },
{ UTQmode, "utq" },
{ HAmode, "ha" },
{ UHAmode, "uha" },
{ SAmode, "sa" },
{ USAmode, "usa" },
{ DAmode, "da" },
{ UDAmode, "uda" },
{ TAmode, "ta" },
{ UTAmode, "uta" },
{ QImode, "qi" },
{ HImode, "hi" },
{ SImode, "si" },
{ DImode, "di" },
{ TImode, "ti" },
{ SFmode, "sf" },
{ 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");
}
/* 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);
}
/* Fix up any incompatible options that the user has specified. */
static void
arm_option_override (void)
{
arm_selected_arch = NULL;
arm_selected_cpu = NULL;
arm_selected_tune = NULL;
if (global_options_set.x_arm_arch_option)
arm_selected_arch = &all_architectures[arm_arch_option];
if (global_options_set.x_arm_cpu_option)
{
arm_selected_cpu = &all_cores[(int) arm_cpu_option];
arm_selected_tune = &all_cores[(int) arm_cpu_option];
}
if (global_options_set.x_arm_tune_option)
arm_selected_tune = &all_cores[(int) arm_tune_option];
#ifdef SUBTARGET_OVERRIDE_OPTIONS
SUBTARGET_OVERRIDE_OPTIONS;
#endif
if (arm_selected_arch)
{
if (arm_selected_cpu)
{
/* Check for conflict between mcpu and march. */
if ((arm_selected_cpu->flags ^ arm_selected_arch->flags) & ~FL_TUNE)
{
warning (0, "switch -mcpu=%s conflicts with -march=%s switch",
arm_selected_cpu->name, arm_selected_arch->name);
/* -march wins for code generation.
-mcpu wins for default tuning. */
if (!arm_selected_tune)
arm_selected_tune = arm_selected_cpu;
arm_selected_cpu = arm_selected_arch;
}
else
/* -mcpu wins. */
arm_selected_arch = NULL;
}
else
/* Pick a CPU based on the architecture. */
arm_selected_cpu = arm_selected_arch;
}
/* If the user did not specify a processor, choose one for them. */
if (!arm_selected_cpu)
{
const struct processors * sel;
unsigned int sought;
arm_selected_cpu = &all_cores[TARGET_CPU_DEFAULT];
if (!arm_selected_cpu->name)
{
#ifdef SUBTARGET_CPU_DEFAULT
/* Use the subtarget default CPU if none was specified by
configure. */
arm_selected_cpu = &all_cores[SUBTARGET_CPU_DEFAULT];
#endif
/* Default to ARM6. */
if (!arm_selected_cpu->name)
arm_selected_cpu = &all_cores[arm6];
}
sel = arm_selected_cpu;
insn_flags = sel->flags;
/* Now check to see if the user has specified some command line
switch that require certain abilities from the cpu. */
sought = 0;
if (TARGET_INTERWORK || TARGET_THUMB)
{
sought |= (FL_THUMB | FL_MODE32);
/* There are no ARM processors that support both APCS-26 and
interworking. Therefore we force FL_MODE26 to be removed
from insn_flags here (if it was set), so that the search
below will always be able to find a compatible processor. */
insn_flags &= ~FL_MODE26;
}
if (sought != 0 && ((sought & insn_flags) != sought))
{
/* Try to locate a CPU type that supports all of the abilities
of the default CPU, plus the extra abilities requested by
the user. */
for (sel = all_cores; sel->name != NULL; sel++)
if ((sel->flags & sought) == (sought | insn_flags))
break;
if (sel->name == NULL)
{
unsigned current_bit_count = 0;
const struct processors * 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 both the
characteristics of the default cpu and the given
command line options we scan the array again looking
for a best match. */
for (sel = all_cores; sel->name != NULL; sel++)
if ((sel->flags & sought) == sought)
{
unsigned count;
count = bit_count (sel->flags & insn_flags);
if (count >= current_bit_count)
{
best_fit = sel;
current_bit_count = count;
}
}
gcc_assert (best_fit);
sel = best_fit;
}
arm_selected_cpu = sel;
}
}
gcc_assert (arm_selected_cpu);
/* The selected cpu may be an architecture, so lookup tuning by core ID. */
if (!arm_selected_tune)
arm_selected_tune = &all_cores[arm_selected_cpu->core];
sprintf (arm_arch_name, "__ARM_ARCH_%s__", arm_selected_cpu->arch);
insn_flags = arm_selected_cpu->flags;
arm_base_arch = arm_selected_cpu->base_arch;
arm_tune = arm_selected_tune->core;
tune_flags = arm_selected_tune->flags;
current_tune = arm_selected_tune->tune;
/* Make sure that the processor choice does not conflict with any of the
other command line choices. */
if (TARGET_ARM && !(insn_flags & FL_NOTM))
error ("target CPU does not support ARM mode");
/* BPABI targets use linker tricks to allow interworking on cores
without thumb support. */
if (TARGET_INTERWORK && !((insn_flags & FL_THUMB) || TARGET_BPABI))
{
warning (0, "target CPU does not support interworking" );
target_flags &= ~MASK_INTERWORK;
}
if (TARGET_THUMB && !(insn_flags & FL_THUMB))
{
warning (0, "target CPU does not support THUMB instructions");
target_flags &= ~MASK_THUMB;
}
if (TARGET_APCS_FRAME && TARGET_THUMB)
{
/* warning (0, "ignoring -mapcs-frame because -mthumb was used"); */
target_flags &= ~MASK_APCS_FRAME;
}
/* Callee super interworking implies thumb interworking. Adding
this to the flags here simplifies the logic elsewhere. */
if (TARGET_THUMB && TARGET_CALLEE_INTERWORKING)
target_flags |= MASK_INTERWORK;
/* TARGET_BACKTRACE calls leaf_function_p, which causes a crash if done
from here where no function is being compiled currently. */
if ((TARGET_TPCS_FRAME || TARGET_TPCS_LEAF_FRAME) && TARGET_ARM)
warning (0, "enabling backtrace support is only meaningful when compiling for the Thumb");
if (TARGET_ARM && TARGET_CALLEE_INTERWORKING)
warning (0, "enabling callee interworking support is only meaningful when compiling for the Thumb");
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");
/* If this target is normally configured to use APCS frames, warn if they
are turned off and debugging is turned on. */
if (TARGET_ARM
&& write_symbols != NO_DEBUG
&& !TARGET_APCS_FRAME
&& (TARGET_DEFAULT & MASK_APCS_FRAME))
warning (0, "-g with -mno-apcs-frame may not give sensible debugging");
if (TARGET_APCS_FLOAT)
warning (0, "passing floating point arguments in fp regs not yet supported");
/* Initialize boolean versions of the flags, for use in the arm.md file. */
arm_arch3m = (insn_flags & FL_ARCH3M) != 0;
arm_arch4 = (insn_flags & FL_ARCH4) != 0;
arm_arch4t = arm_arch4 & ((insn_flags & FL_THUMB) != 0);
arm_arch5 = (insn_flags & FL_ARCH5) != 0;
arm_arch5e = (insn_flags & FL_ARCH5E) != 0;
arm_arch6 = (insn_flags & FL_ARCH6) != 0;
arm_arch6k = (insn_flags & FL_ARCH6K) != 0;
arm_arch_notm = (insn_flags & FL_NOTM) != 0;
arm_arch6m = arm_arch6 && !arm_arch_notm;
arm_arch7 = (insn_flags & FL_ARCH7) != 0;
arm_arch7em = (insn_flags & FL_ARCH7EM) != 0;
arm_arch8 = (insn_flags & FL_ARCH8) != 0;
arm_arch_thumb2 = (insn_flags & FL_THUMB2) != 0;
arm_arch_xscale = (insn_flags & FL_XSCALE) != 0;
arm_ld_sched = (tune_flags & FL_LDSCHED) != 0;
arm_tune_strongarm = (tune_flags & FL_STRONG) != 0;
thumb_code = TARGET_ARM == 0;
thumb1_code = TARGET_THUMB1 != 0;
arm_tune_wbuf = (tune_flags & FL_WBUF) != 0;
arm_tune_xscale = (tune_flags & FL_XSCALE) != 0;
arm_arch_iwmmxt = (insn_flags & FL_IWMMXT) != 0;
arm_arch_iwmmxt2 = (insn_flags & FL_IWMMXT2) != 0;
arm_arch_thumb_hwdiv = (insn_flags & FL_THUMB_DIV) != 0;
arm_arch_arm_hwdiv = (insn_flags & FL_ARM_DIV) != 0;
arm_arch_lpae = (insn_flags & FL_LPAE) != 0;
arm_arch_no_volatile_ce = (insn_flags & FL_NO_VOLATILE_CE) != 0;
arm_tune_cortex_a9 = (arm_tune == cortexa9) != 0;
arm_arch_crc = (insn_flags & FL_CRC32) != 0;
arm_m_profile_small_mul = (insn_flags & FL_SMALLMUL) != 0;
if (arm_restrict_it == 2)
arm_restrict_it = arm_arch8 && TARGET_THUMB2;
if (!TARGET_THUMB2)
arm_restrict_it = 0;
/* 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;
}
/* V5 code we generate is completely interworking capable, so we turn off
TARGET_INTERWORK here to avoid many tests later on. */
/* XXX However, we must pass the right pre-processor defines to CPP
or GLD can get confused. This is a hack. */
if (TARGET_INTERWORK)
arm_cpp_interwork = 1;
if (arm_arch5)
target_flags &= ~MASK_INTERWORK;
if (TARGET_IWMMXT && !ARM_DOUBLEWORD_ALIGN)
error ("iwmmxt requires an AAPCS compatible ABI for proper operation");
if (TARGET_IWMMXT_ABI && !TARGET_IWMMXT)
error ("iwmmxt abi requires an iwmmxt capable cpu");
if (!global_options_set.x_arm_fpu_index)
{
const char *target_fpu_name;
bool ok;
#ifdef FPUTYPE_DEFAULT
target_fpu_name = FPUTYPE_DEFAULT;
#else
target_fpu_name = "vfp";
#endif
ok = opt_enum_arg_to_value (OPT_mfpu_, target_fpu_name, &arm_fpu_index,
CL_TARGET);
gcc_assert (ok);
}
arm_fpu_desc = &all_fpus[arm_fpu_index];
switch (arm_fpu_desc->model)
{
case ARM_FP_MODEL_VFP:
arm_fpu_attr = FPU_VFP;
break;
default:
gcc_unreachable();
}
if (TARGET_AAPCS_BASED)
{
if (TARGET_CALLER_INTERWORKING)
error ("AAPCS does not support -mcaller-super-interworking");
else
if (TARGET_CALLEE_INTERWORKING)
error ("AAPCS does not support -mcallee-super-interworking");
}
/* iWMMXt and NEON are incompatible. */
if (TARGET_IWMMXT && TARGET_NEON)
error ("iWMMXt and NEON are incompatible");
/* iWMMXt unsupported under Thumb mode. */
if (TARGET_THUMB && TARGET_IWMMXT)
error ("iWMMXt unsupported under Thumb mode");
/* __fp16 support currently assumes the core has ldrh. */
if (!arm_arch4 && arm_fp16_format != ARM_FP16_FORMAT_NONE)
sorry ("__fp16 and no ldrh");
/* If soft-float is specified then don't use FPU. */
if (TARGET_SOFT_FLOAT)
arm_fpu_attr = FPU_NONE;
if (TARGET_AAPCS_BASED)
{
if (arm_abi == ARM_ABI_IWMMXT)
arm_pcs_default = ARM_PCS_AAPCS_IWMMXT;
else if (arm_float_abi == ARM_FLOAT_ABI_HARD
&& TARGET_HARD_FLOAT
&& TARGET_VFP)
arm_pcs_default = ARM_PCS_AAPCS_VFP;
else
arm_pcs_default = ARM_PCS_AAPCS;
}
else
{
if (arm_float_abi == ARM_FLOAT_ABI_HARD && TARGET_VFP)
sorry ("-mfloat-abi=hard and VFP");
if (arm_abi == ARM_ABI_APCS)
arm_pcs_default = ARM_PCS_APCS;
else
arm_pcs_default = ARM_PCS_ATPCS;
}
/* For arm2/3 there is no need to do any scheduling if we are doing
software floating-point. */
if (TARGET_SOFT_FLOAT && (tune_flags & FL_MODE32) == 0)
flag_schedule_insns = flag_schedule_insns_after_reload = 0;
/* Use the cp15 method if it is available. */
if (target_thread_pointer == TP_AUTO)
{
if (arm_arch6k && !TARGET_THUMB1)
target_thread_pointer = TP_CP15;
else
target_thread_pointer = TP_SOFT;
}
if (TARGET_HARD_TP && TARGET_THUMB1)
error ("can not use -mtp=cp15 with 16-bit Thumb");
/* 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
{
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_ARM && TARGET_VXWORKS_RTP && flag_pic)
{
error ("RTP PIC is incompatible with Thumb");
flag_pic = 0;
}
/* 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 (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_regs[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 '%s' for PIC register", arm_pic_register_string);
else
arm_pic_register = pic_register;
}
if (TARGET_VXWORKS_RTP
&& !global_options_set.x_arm_pic_data_is_text_relative)
arm_pic_data_is_text_relative = 0;
/* Enable -mfix-cortex-m3-ldrd by default for Cortex-M3 cores. */
if (fix_cm3_ldrd == 2)
{
if (arm_selected_cpu->core == cortexm3)
fix_cm3_ldrd = 1;
else
fix_cm3_ldrd = 0;
}
/* Enable -munaligned-access by default for
- all ARMv6 architecture-based processors
- 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. */
if (unaligned_access == 2)
{
if (arm_arch6 && (arm_arch_notm || arm_arch7))
unaligned_access = 1;
else
unaligned_access = 0;
}
else if (unaligned_access == 1
&& !(arm_arch6 && (arm_arch_notm || arm_arch7)))
{
warning (0, "target CPU does not support unaligned accesses");
unaligned_access = 0;
}
if (TARGET_THUMB1 && flag_schedule_insns)
{
/* Don't warn since it's on by default in -O2. */
flag_schedule_insns = 0;
}
if (optimize_size)
{
/* If optimizing for size, bump the number of instructions that we
are prepared to conditionally execute (even on a StrongARM). */
max_insns_skipped = 6;
/* For THUMB2, we limit the conditional sequence to one IT block. */
if (TARGET_THUMB2)
max_insns_skipped = MAX_INSN_PER_IT_BLOCK;
}
else
max_insns_skipped = current_tune->max_insns_skipped;
/* 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. */
maybe_set_param_value (PARAM_GCSE_UNRESTRICTED_COST, 2,
global_options.x_param_values,
global_options_set.x_param_values);
/* 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 num_prefetch_slots to 1 or more.) */
if (flag_prefetch_loop_arrays < 0
&& HAVE