⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arm.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Output routines for GCC for ARM.   Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002   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 GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */    #include "config.h"#include "system.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"/* Forward definitions of types.  */typedef struct minipool_node    Mnode;typedef struct minipool_fixup   Mfix;/* In order to improve the layout of the prototypes below   some short type abbreviations are defined here.  */#define Hint     HOST_WIDE_INT#define Mmode    enum machine_mode#define Ulong    unsigned long#define Ccstar   const char *const struct attribute_spec arm_attribute_table[];/* Forward function declarations.  */static void      arm_add_gc_roots 		PARAMS ((void));static int       arm_gen_constant		PARAMS ((enum rtx_code, Mmode, Hint, rtx, rtx, int, int));static unsigned  bit_count 			PARAMS ((Ulong));static int       const_ok_for_op 		PARAMS ((Hint, enum rtx_code));static rtx	 emit_multi_reg_push		PARAMS ((int));static rtx	 emit_sfm			PARAMS ((int, int));#ifndef AOF_ASSEMBLERstatic bool	 arm_assemble_integer		PARAMS ((rtx, unsigned int, int));#endifstatic Ccstar    fp_const_from_val		PARAMS ((REAL_VALUE_TYPE *));static arm_cc    get_arm_condition_code		PARAMS ((rtx));static void      init_fpa_table			PARAMS ((void));static Hint      int_log2			PARAMS ((Hint));static rtx       is_jump_table 			PARAMS ((rtx));static Ccstar    output_multi_immediate		PARAMS ((rtx *, Ccstar, Ccstar, int, Hint));static void      print_multi_reg		PARAMS ((FILE *, Ccstar, int, int));static Mmode     select_dominance_cc_mode	PARAMS ((rtx, rtx, Hint));static Ccstar    shift_op			PARAMS ((rtx, Hint *));static struct machine_function * arm_init_machine_status PARAMS ((void));static int       number_of_first_bit_set        PARAMS ((int));static void      replace_symbols_in_block       PARAMS ((tree, rtx, rtx));static void      thumb_exit                     PARAMS ((FILE *, int, rtx));static void      thumb_pushpop                  PARAMS ((FILE *, int, int));static Ccstar    thumb_condition_code           PARAMS ((rtx, int));static rtx	 is_jump_table		        PARAMS ((rtx));static Hint	 get_jump_table_size	        PARAMS ((rtx));static Mnode *   move_minipool_fix_forward_ref  PARAMS ((Mnode *, Mnode *, Hint));static Mnode *   add_minipool_forward_ref	PARAMS ((Mfix *));static Mnode *   move_minipool_fix_backward_ref PARAMS ((Mnode *, Mnode *, Hint));static Mnode *   add_minipool_backward_ref      PARAMS ((Mfix *));static void	 assign_minipool_offsets	PARAMS ((Mfix *));static void	 arm_print_value		PARAMS ((FILE *, rtx));static void	 dump_minipool		        PARAMS ((rtx));static int	 arm_barrier_cost		PARAMS ((rtx));static Mfix *    create_fix_barrier		PARAMS ((Mfix *, Hint));static void	 push_minipool_barrier	        PARAMS ((rtx, Hint));static void	 push_minipool_fix		PARAMS ((rtx, Hint, rtx *, Mmode, rtx));static void	 note_invalid_constants	        PARAMS ((rtx, Hint));static int       current_file_function_operand	PARAMS ((rtx));static Ulong	 arm_compute_save_reg0_reg12_mask  PARAMS ((void));static Ulong     arm_compute_save_reg_mask	PARAMS ((void));static Ulong     arm_isr_value 			PARAMS ((tree));static Ulong     arm_compute_func_type		PARAMS ((void));static tree      arm_handle_fndecl_attribute    PARAMS ((tree *, tree, tree, int, bool *));static tree      arm_handle_isr_attribute       PARAMS ((tree *, tree, tree, int, bool *));static void	 arm_output_function_epilogue	PARAMS ((FILE *, Hint));static void	 arm_output_function_prologue	PARAMS ((FILE *, Hint));static void	 thumb_output_function_prologue PARAMS ((FILE *, Hint));static int	 arm_comp_type_attributes	PARAMS ((tree, tree));static void	 arm_set_default_type_attributes  PARAMS ((tree));static int	 arm_adjust_cost		PARAMS ((rtx, rtx, rtx, int));static int	 count_insns_for_constant	PARAMS ((HOST_WIDE_INT, int));static int	 arm_get_strip_length		PARAMS ((int));#ifdef OBJECT_FORMAT_ELFstatic void	 arm_elf_asm_named_section	PARAMS ((const char *, unsigned int));#endif#ifndef ARM_PEstatic void	 arm_encode_section_info	PARAMS ((tree, int));#endif#ifdef AOF_ASSEMBLERstatic void	 aof_globalize_label		PARAMS ((FILE *, const char *));#endifstatic void arm_output_mi_thunk			PARAMS ((FILE *, tree,							 HOST_WIDE_INT,							 HOST_WIDE_INT, tree));#undef Hint#undef Mmode#undef Ulong#undef Ccstar/* Initialize the GCC target structure.  */#ifdef 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#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#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_INIT_BUILTINS#define TARGET_INIT_BUILTINS arm_init_builtins#undef  TARGET_EXPAND_BUILTIN#define TARGET_EXPAND_BUILTIN arm_expand_builtin#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_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_vcallstruct 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;/* What type of floating point are we tuning for?  */enum floating_point_type arm_fpu;/* What type of floating point instructions are available?  */enum floating_point_type arm_fpu_arch;/* What program mode is the cpu running in? 26-bit mode or 32-bit mode.  */enum prog_mode_type arm_prgmode;/* Set by the -mfp=... option.  */const char * target_fp_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;/* Bit values used to identify processor capabilities.  */#define FL_CO_PROC    (1 << 0)        /* Has external co-processor bus */#define FL_FAST_MULT  (1 << 1)        /* Fast 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 extenstions to v5 */#define FL_XSCALE     (1 << 10)	      /* XScale *//* 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.  Note - there is an overlap with the FL_FAST_MULT.  For some   hardware we want to be able to generate the multiply instructions, but to   tune as if they were not present in the architecture.  */static unsigned long tune_flags = 0;/* The following are used in the arm.md file as equivalents to bits   in the above two flag variables.  *//* Nonzero if this is an "M" variant of the processor.  */int arm_fast_multiply = 0;/* Nonzero if this chip supports the ARM Architecture 4 extensions.  */int arm_arch4 = 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 can benefit from load scheduling.  */int arm_ld_sched = 0;/* Nonzero if this chip is a StrongARM.  */int arm_is_strong = 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 this chip is an ARM6 or an ARM7.  */int arm_is_6_or_7 = 0;/* Nonzero if generating Thumb instructions.  */int thumb_code = 0;/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we   must report the mode of the memory reference from PRINT_OPERAND to   PRINT_OPERAND_ADDRESS.  */enum machine_mode output_memory_reference_mode;/* The register number to be used for the PIC offset register.  */const char * arm_pic_register_string = NULL;int arm_pic_register = INVALID_REGNUM;/* Set to 1 when a return insn is output, this means that the epilogue   is not needed.  */int return_used_this_function;/* Set to 1 after arm_reorg has started.  Reset to start at the start of   the next function.  */static int after_arm_reorg = 0;/* The maximum number of insns to be used when loading a constant.  */static int arm_constant_limit = 3;/* For an explanation of these variables, see final_prescan_insn below.  */int arm_ccfsm_state;enum arm_cond_code arm_current_cc;rtx arm_target_insn;int arm_target_label;/* 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"};#define streq(string1, string2) (strcmp (string1, string2) == 0)/* Initialization code.  */struct processors{  const char *const name;  const unsigned long flags;};/* 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 */    {"arm2",	FL_CO_PROC | FL_MODE26 },  {"arm250",	FL_CO_PROC | FL_MODE26 },  {"arm3",	FL_CO_PROC | FL_MODE26 },  {"arm6",	FL_CO_PROC | FL_MODE26 | FL_MODE32 },  {"arm60",	FL_CO_PROC | FL_MODE26 | FL_MODE32 },  {"arm600",	FL_CO_PROC | FL_MODE26 | FL_MODE32 },  {"arm610",	             FL_MODE26 | FL_MODE32 },  {"arm620",	FL_CO_PROC | FL_MODE26 | FL_MODE32 },  {"arm7",	FL_CO_PROC | FL_MODE26 | FL_MODE32 },  /* arm7m doesn't exist on its own, but only with D, (and I), but     those don't alter the code, so arm7m is sometimes used.  */  {"arm7m",	FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },  {"arm7d",	FL_CO_PROC | FL_MODE26 | FL_MODE32 },  {"arm7dm",	FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },  {"arm7di",	FL_CO_PROC | FL_MODE26 | FL_MODE32 },  {"arm7dmi",	FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },  {"arm70",	FL_CO_PROC | FL_MODE26 | FL_MODE32 },  {"arm700",	FL_CO_PROC | FL_MODE26 | FL_MODE32 },  {"arm700i",	FL_CO_PROC | FL_MODE26 | FL_MODE32 },  {"arm710",	             FL_MODE26 | FL_MODE32 },  {"arm710t",	             FL_MODE26 | FL_MODE32                           | FL_THUMB },  {"arm720",	             FL_MODE26 | FL_MODE32 },  {"arm720t",	             FL_MODE26 | FL_MODE32                           | FL_THUMB },  {"arm740t",	             FL_MODE26 | FL_MODE32                           | FL_THUMB },  {"arm710c",	             FL_MODE26 | FL_MODE32 },  {"arm7100",	             FL_MODE26 | FL_MODE32 },  {"arm7500",	             FL_MODE26 | FL_MODE32 },  /* Doesn't have an external co-proc, but does have embedded fpu.  */  {"arm7500fe",	FL_CO_PROC | FL_MODE26 | FL_MODE32 },  {"arm7tdmi",	FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB },  {"arm8",	             FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED },  {"arm810",	             FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED },  {"arm9",	                         FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },  {"arm920",	                         FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED },  {"arm920t",	                         FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },  {"arm940t",	                         FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },  {"arm9tdmi",	                         FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },  {"arm9e",	       	      		 FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED },  {"strongarm",	             FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },  {"strongarm110",           FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },  {"strongarm1100",          FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },  {"strongarm1110",          FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },  {"arm10tdmi",	                         FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED             | FL_ARCH5 },  {"arm1020t",	                         FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED             | FL_ARCH5 },  {"xscale",                             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_STRONG | FL_ARCH5 | FL_ARCH5E | FL_XSCALE },  {NULL, 0}};static const struct processors all_architectures[] ={  /* ARM Architectures */    { "armv2",     FL_CO_PROC | FL_MODE26 },  { "armv2a",    FL_CO_PROC | FL_MODE26 },  { "armv3",     FL_CO_PROC | FL_MODE26 | FL_MODE32 },  { "armv3m",    FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },  { "armv4",     FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 },  /* Strictly, FL_MODE26 is a permitted option for v4t, but there are no     implementations that support it, so we will leave it out for now.  */  { "armv4t",    FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB },  { "armv5",     FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 },  { "armv5t",    FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 },  { "armv5te",   FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 | FL_ARCH5E },  { NULL, 0 }};/* This is a magic stucture.  The 'string' field is magically filled in   with a pointer to the value specified by the user on the command line   assuming that the user has specified such a value.  */struct arm_cpu_select arm_select[] ={  /* string	  name            processors  */	  { NULL,	"-mcpu=",	all_cores  },  { NULL,	"-march=",	all_architectures },  { NULL,	"-mtune=",	all_cores }};/* Return the number of bits set in VALUE.  */static unsignedbit_count (value)     unsigned long value;{  unsigned long count = 0;    while (value)    {      count++;      value &= value - 1;  /* Clear the least-significant set bit.  */    }  return count;}/* Fix up any incompatible options that the user has specified.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -