📄 arm.c
字号:
/* Output routines for GCC for ARM. Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 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 2, 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 COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.h"#include "rtl.h"#include "tree.h"#include "obstack.h"#include "regs.h"#include "hard-reg-set.h"#include "real.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 "expr.h"#include "optabs.h"#include "toplev.h"#include "recog.h"#include "ggc.h"#include "except.h"#include "c-pragma.h"#include "integrate.h"#include "tm_p.h"#include "target.h"#include "target-def.h"#include "debug.h"#include "langhooks.h"/* Forward definitions of types. */typedef struct minipool_node Mnode;typedef struct minipool_fixup Mfix;const struct attribute_spec arm_attribute_table[];/* Forward function declarations. */static arm_stack_offsets *arm_get_frame_offsets (void);static void arm_add_gc_roots (void);static int arm_gen_constant (enum rtx_code, enum 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 (enum machine_mode, rtx, RTX_CODE, int);static int thumb_base_register_rtx_p (rtx, enum machine_mode, int);inline static int thumb_index_register_rtx_p (rtx, int);static int thumb_far_jump_used_p (void);static bool thumb_force_lr_save (void);static unsigned long thumb_compute_save_reg_mask (void);static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);static rtx emit_multi_reg_push (int);static rtx emit_sfm (int, int);#ifndef AOF_ASSEMBLERstatic bool arm_assemble_integer (rtx, unsigned int, int);#endifstatic 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 rtx is_jump_table (rtx);static const char *output_multi_immediate (rtx *, const char *, const char *, int, HOST_WIDE_INT);static void print_multi_reg (FILE *, const char *, int, int);static const char *shift_op (rtx, HOST_WIDE_INT *);static struct machine_function *arm_init_machine_status (void);static int number_of_first_bit_set (int);static void replace_symbols_in_block (tree, rtx, rtx);static void thumb_exit (FILE *, int);static void thumb_pushpop (FILE *, int, int, int *, int);static rtx is_jump_table (rtx);static HOST_WIDE_INT get_jump_table_size (rtx);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);static int arm_barrier_cost (rtx);static Mfix *create_fix_barrier (Mfix *, HOST_WIDE_INT);static void push_minipool_barrier (rtx, HOST_WIDE_INT);static void push_minipool_fix (rtx, HOST_WIDE_INT, rtx *, enum machine_mode, rtx);static void arm_reorg (void);static bool note_invalid_constants (rtx, HOST_WIDE_INT, int);static int current_file_function_operand (rtx);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_isr_attribute (tree *, tree, tree, int, bool *);#if TARGET_DLLIMPORT_DECL_ATTRIBUTESstatic tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *);#endifstatic void arm_output_function_epilogue (FILE *, HOST_WIDE_INT);static void arm_output_function_prologue (FILE *, HOST_WIDE_INT);static void thumb_output_function_prologue (FILE *, HOST_WIDE_INT);static int arm_comp_type_attributes (tree, tree);static void arm_set_default_type_attributes (tree);static int arm_adjust_cost (rtx, rtx, rtx, int);static int count_insns_for_constant (HOST_WIDE_INT, int);static int arm_get_strip_length (int);static bool arm_function_ok_for_sibcall (tree, tree);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 int arm_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code);static bool arm_size_rtx_costs (rtx, int, int, int *);static bool arm_slowmul_rtx_costs (rtx, int, int, int *);static bool arm_fastmul_rtx_costs (rtx, int, int, int *);static bool arm_xscale_rtx_costs (rtx, int, int, int *);static bool arm_9e_rtx_costs (rtx, int, int, int *);static int arm_address_cost (rtx);static bool arm_memory_load_p (rtx);static bool arm_cirrus_insn_p (rtx);static void cirrus_reorg (rtx);static void arm_init_builtins (void);static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int);static void arm_init_iwmmxt_builtins (void);static rtx safe_vector_operand (rtx, enum machine_mode);static rtx arm_expand_binop_builtin (enum insn_code, tree, rtx);static rtx arm_expand_unop_builtin (enum insn_code, tree, rtx, int);static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int);static void emit_constant_insn (rtx cond, rtx pattern);static int arm_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, tree, bool);#ifndef ARM_PEstatic void arm_encode_section_info (tree, rtx, int);#endifstatic void arm_file_end (void);#ifdef AOF_ASSEMBLERstatic void aof_globalize_label (FILE *, const char *);static void aof_dump_imports (FILE *);static void aof_dump_pic_table (FILE *);static void aof_file_start (void);static void aof_file_end (void);#endifstatic rtx arm_struct_value_rtx (tree, int);static void arm_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int);static bool arm_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, tree, bool);static bool arm_promote_prototypes (tree);static bool arm_default_short_enums (void);static bool arm_align_anon_bitfield (void);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 bool arm_cxx_export_class_data (void);static void arm_init_libfuncs (void);static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode);/* 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_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE arm_attribute_table#undef TARGET_ASM_FILE_END#define TARGET_ASM_FILE_END arm_file_end#ifdef AOF_ASSEMBLER#undef TARGET_ASM_BYTE_OP#define TARGET_ASM_BYTE_OP "\tDCB\t"#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\tDCW\t"#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP "\tDCD\t"#undef TARGET_ASM_GLOBALIZE_LABEL#define TARGET_ASM_GLOBALIZE_LABEL aof_globalize_label#undef TARGET_ASM_FILE_START#define TARGET_ASM_FILE_START aof_file_start#undef TARGET_ASM_FILE_END#define TARGET_ASM_FILE_END aof_file_end#else#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP NULL#undef TARGET_ASM_INTEGER#define TARGET_ASM_INTEGER arm_assemble_integer#endif#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_COMP_TYPE_ATTRIBUTES#define TARGET_COMP_TYPE_ATTRIBUTES arm_comp_type_attributes#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_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_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/* This will be overridden in arm_override_options. */#undef TARGET_RTX_COSTS#define TARGET_RTX_COSTS arm_slowmul_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_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_INIT_LIBFUNCS#define TARGET_INIT_LIBFUNCS arm_init_libfuncs#undef TARGET_PROMOTE_FUNCTION_ARGS#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true#undef TARGET_PROMOTE_FUNCTION_RETURN#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true#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_STRUCT_VALUE_RTX#define TARGET_STRUCT_VALUE_RTX arm_struct_value_rtx#undef TARGET_SETUP_INCOMING_VARARGS#define TARGET_SETUP_INCOMING_VARARGS arm_setup_incoming_varargs#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_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_EXPORT_CLASS_DATA#define TARGET_CXX_EXPORT_CLASS_DATA arm_cxx_export_class_datastruct 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;/* Define the information needed to generate branch insns. This is stored from the compare operation. */rtx arm_compare_op0, arm_compare_op1;/* The processor for which instructions should be scheduled. */enum processor_type arm_tune = arm_none;/* Which floating point model to use. */enum arm_fp_model arm_fp_model;/* Which floating point hardware is available. */enum fputype arm_fpu_arch;/* Which floating point hardware to schedule for. */enum fputype arm_fpu_tune;/* Whether to use floating point hardware. */enum float_abi_type arm_float_abi;/* Which ABI to use. */enum arm_abi_type arm_abi;/* Set by the -mfpu=... option. */const char * target_fpu_name = NULL;/* Set by the -mfpe=... option. */const char * target_fpe_name = NULL;/* Set by the -mfloat-abi=... option. */const char * target_float_abi_name = NULL;/* Set by the legacy -mhard-float and -msoft-float options. */const char * target_float_switch = NULL;/* Set by the -mabi=... option. */const char * target_abi_name = NULL;/* Used to parse -mstructure_size_boundary command line option. */const char * structure_size_string = NULL;int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;/* Used for Thumb call_via trampolines. */rtx thumb_call_via_label[14];static int thumb_call_reg_needed;/* Bit values used to identify processor capabilities. */#define FL_CO_PROC (1 << 0) /* Has external co-processor bus */#define FL_ARCH3M (1 << 1) /* Extended multiply */#define FL_MODE26 (1 << 2) /* 26-bit mode support */#define FL_MODE32 (1 << 3) /* 32-bit mode support */#define FL_ARCH4 (1 << 4) /* Architecture rel 4 */#define FL_ARCH5 (1 << 5) /* Architecture rel 5 */#define FL_THUMB (1 << 6) /* Thumb aware */#define FL_LDSCHED (1 << 7) /* Load scheduling necessary */#define FL_STRONG (1 << 8) /* StrongARM */#define FL_ARCH5E (1 << 9) /* DSP extensions to v5 */#define FL_XSCALE (1 << 10) /* XScale */#define FL_CIRRUS (1 << 11) /* Cirrus/DSP. */#define FL_ARCH6 (1 << 12) /* Architecture rel 6. Adds media instructions. */#define FL_VFPV2 (1 << 13) /* Vector Floating Point V2. */#define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */#define FL_FOR_ARCH2 0#define FL_FOR_ARCH3 FL_MODE32#define FL_FOR_ARCH3M (FL_FOR_ARCH3 | FL_ARCH3M)#define FL_FOR_ARCH4 (FL_FOR_ARCH3M | FL_ARCH4)#define FL_FOR_ARCH4T (FL_FOR_ARCH4 | FL_THUMB)#define FL_FOR_ARCH5 (FL_FOR_ARCH4 | FL_ARCH5)#define FL_FOR_ARCH5T (FL_FOR_ARCH5 | FL_THUMB)#define FL_FOR_ARCH5E (FL_FOR_ARCH5 | FL_ARCH5E)#define FL_FOR_ARCH5TE (FL_FOR_ARCH5E | FL_THUMB)#define FL_FOR_ARCH5TEJ FL_FOR_ARCH5TE#define FL_FOR_ARCH6 (FL_FOR_ARCH5TE | FL_ARCH6)#define FL_FOR_ARCH6J FL_FOR_ARCH6#define FL_FOR_ARCH6K FL_FOR_ARCH6#define FL_FOR_ARCH6Z FL_FOR_ARCH6#define FL_FOR_ARCH6ZK FL_FOR_ARCH6/* The bits in this mask specify which instructions we are allowed to generate. */static unsigned long insn_flags = 0;/* The bits in this mask specify which instruction scheduling options should be used. */static unsigned long tune_flags = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -