i386.c

来自「gcc3.2.1源代码」· C语言 代码 · 共 1,901 行 · 第 1/5 页

C
1,901
字号
const int x86_himode_math = ~(m_PPRO);const int x86_promote_hi_regs = m_PPRO;const int x86_sub_esp_4 = m_ATHLON | m_PPRO | m_PENT4;const int x86_sub_esp_8 = m_ATHLON | m_PPRO | m_386 | m_486 | m_PENT4;const int x86_add_esp_4 = m_ATHLON | m_K6 | m_PENT4;const int x86_add_esp_8 = m_ATHLON | m_PPRO | m_K6 | m_386 | m_486 | m_PENT4;const int x86_integer_DFmode_moves = ~(m_ATHLON | m_PENT4);const int x86_partial_reg_dependency = m_ATHLON | m_PENT4;const int x86_memory_mismatch_stall = m_ATHLON | m_PENT4;const int x86_accumulate_outgoing_args = m_ATHLON | m_PENT4 | m_PPRO;const int x86_prologue_using_move = m_ATHLON | m_PENT4 | m_PPRO;const int x86_epilogue_using_move = m_ATHLON | m_PENT4 | m_PPRO;const int x86_decompose_lea = m_PENT4;const int x86_arch_always_fancy_math_387 = m_PENT|m_PPRO|m_ATHLON|m_PENT4;/* In case the avreage insn count for single function invocation is   lower than this constant, emit fast (but longer) prologue and   epilogue code.  */#define FAST_PROLOGUE_INSN_COUNT 30/* Set by prologue expander and used by epilogue expander to determine   the style used.  */static int use_fast_prologue_epilogue;#define AT_BP(MODE) (gen_rtx_MEM ((MODE), hard_frame_pointer_rtx))static const char *const hi_reg_name[] = HI_REGISTER_NAMES; /* names for 16 bit regs */static const char *const qi_reg_name[] = QI_REGISTER_NAMES; /* names for 8 bit regs (low) */static const char *const qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES; /* names for 8 bit regs (high) *//* Array of the smallest class containing reg number REGNO, indexed by   REGNO.  Used by REGNO_REG_CLASS in i386.h.  */enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] ={  /* ax, dx, cx, bx */  AREG, DREG, CREG, BREG,  /* si, di, bp, sp */  SIREG, DIREG, NON_Q_REGS, NON_Q_REGS,  /* FP registers */  FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS,  FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,  /* arg pointer */  NON_Q_REGS,  /* flags, fpsr, dirflag, frame */  NO_REGS, NO_REGS, NO_REGS, NON_Q_REGS,  SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,  SSE_REGS, SSE_REGS,  MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS,  MMX_REGS, MMX_REGS,  NON_Q_REGS, NON_Q_REGS, NON_Q_REGS, NON_Q_REGS,  NON_Q_REGS, NON_Q_REGS, NON_Q_REGS, NON_Q_REGS,  SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,  SSE_REGS, SSE_REGS,};/* The "default" register map used in 32bit mode.  */int const dbx_register_map[FIRST_PSEUDO_REGISTER] ={  0, 2, 1, 3, 6, 7, 4, 5,		/* general regs */  12, 13, 14, 15, 16, 17, 18, 19,	/* fp regs */  -1, -1, -1, -1, -1,			/* arg, flags, fpsr, dir, frame */  21, 22, 23, 24, 25, 26, 27, 28,	/* SSE */  29, 30, 31, 32, 33, 34, 35, 36,       /* MMX */  -1, -1, -1, -1, -1, -1, -1, -1,	/* extended integer registers */  -1, -1, -1, -1, -1, -1, -1, -1,	/* extended SSE registers */};static int const x86_64_int_parameter_registers[6] = {5 /*RDI*/, 4 /*RSI*/,					        1 /*RDX*/, 2 /*RCX*/,					        FIRST_REX_INT_REG /*R8 */,					        FIRST_REX_INT_REG + 1 /*R9 */};static int const x86_64_int_return_registers[4] = {0 /*RAX*/, 1 /*RDI*/, 5, 4};/* The "default" register map used in 64bit mode.  */int const dbx64_register_map[FIRST_PSEUDO_REGISTER] ={  0, 1, 2, 3, 4, 5, 6, 7,		/* general regs */  33, 34, 35, 36, 37, 38, 39, 40,	/* fp regs */  -1, -1, -1, -1, -1,			/* arg, flags, fpsr, dir, frame */  17, 18, 19, 20, 21, 22, 23, 24,	/* SSE */  41, 42, 43, 44, 45, 46, 47, 48,       /* MMX */  8,9,10,11,12,13,14,15,		/* extended integer registers */  25, 26, 27, 28, 29, 30, 31, 32,	/* extended SSE registers */};/* Define the register numbers to be used in Dwarf debugging information.   The SVR4 reference port C compiler uses the following register numbers   in its Dwarf output code:	0 for %eax (gcc regno = 0)	1 for %ecx (gcc regno = 2)	2 for %edx (gcc regno = 1)	3 for %ebx (gcc regno = 3)	4 for %esp (gcc regno = 7)	5 for %ebp (gcc regno = 6)	6 for %esi (gcc regno = 4)	7 for %edi (gcc regno = 5)   The following three DWARF register numbers are never generated by   the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4   believes these numbers have these meanings.	8  for %eip    (no gcc equivalent)	9  for %eflags (gcc regno = 17)	10 for %trapno (no gcc equivalent)   It is not at all clear how we should number the FP stack registers   for the x86 architecture.  If the version of SDB on x86/svr4 were   a bit less brain dead with respect to floating-point then we would   have a precedent to follow with respect to DWARF register numbers   for x86 FP registers, but the SDB on x86/svr4 is so completely   broken with respect to FP registers that it is hardly worth thinking   of it as something to strive for compatibility with.   The version of x86/svr4 SDB I have at the moment does (partially)   seem to believe that DWARF register number 11 is associated with   the x86 register %st(0), but that's about all.  Higher DWARF   register numbers don't seem to be associated with anything in   particular, and even for DWARF regno 11, SDB only seems to under-   stand that it should say that a variable lives in %st(0) (when   asked via an `=' command) if we said it was in DWARF regno 11,   but SDB still prints garbage when asked for the value of the   variable in question (via a `/' command).   (Also note that the labels SDB prints for various FP stack regs   when doing an `x' command are all wrong.)   Note that these problems generally don't affect the native SVR4   C compiler because it doesn't allow the use of -O with -g and   because when it is *not* optimizing, it allocates a memory   location for each floating-point variable, and the memory   location is what gets described in the DWARF AT_location   attribute for the variable in question.   Regardless of the severe mental illness of the x86/svr4 SDB, we   do something sensible here and we use the following DWARF   register numbers.  Note that these are all stack-top-relative   numbers.	11 for %st(0) (gcc regno = 8)	12 for %st(1) (gcc regno = 9)	13 for %st(2) (gcc regno = 10)	14 for %st(3) (gcc regno = 11)	15 for %st(4) (gcc regno = 12)	16 for %st(5) (gcc regno = 13)	17 for %st(6) (gcc regno = 14)	18 for %st(7) (gcc regno = 15)*/int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] ={  0, 2, 1, 3, 6, 7, 5, 4,		/* general regs */  11, 12, 13, 14, 15, 16, 17, 18,	/* fp regs */  -1, 9, -1, -1, -1,			/* arg, flags, fpsr, dir, frame */  21, 22, 23, 24, 25, 26, 27, 28,	/* SSE registers */  29, 30, 31, 32, 33, 34, 35, 36,	/* MMX registers */  -1, -1, -1, -1, -1, -1, -1, -1,	/* extemded integer registers */  -1, -1, -1, -1, -1, -1, -1, -1,	/* extemded SSE registers */};/* Test and compare insns in i386.md store the information needed to   generate branch and scc insns here.  */rtx ix86_compare_op0 = NULL_RTX;rtx ix86_compare_op1 = NULL_RTX;#define MAX_386_STACK_LOCALS 3/* Size of the register save area.  */#define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16)/* Define the structure for the machine field in struct function.  */struct machine_function{  rtx stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];  int save_varrargs_registers;  int accesses_prev_frame;};#define ix86_stack_locals (cfun->machine->stack_locals)#define ix86_save_varrargs_registers (cfun->machine->save_varrargs_registers)/* Structure describing stack frame layout.   Stack grows downward:   [arguments]					      <- ARG_POINTER   saved pc   saved frame pointer if frame_pointer_needed					      <- HARD_FRAME_POINTER   [saved regs]   [padding1]          \		        )   [va_arg registers]  (		        > to_allocate	      <- FRAME_POINTER   [frame]	       (		        )   [padding2]	       /  */struct ix86_frame{  int nregs;  int padding1;  int va_arg_size;  HOST_WIDE_INT frame;  int padding2;  int outgoing_arguments_size;  int red_zone_size;  HOST_WIDE_INT to_allocate;  /* The offsets relative to ARG_POINTER.  */  HOST_WIDE_INT frame_pointer_offset;  HOST_WIDE_INT hard_frame_pointer_offset;  HOST_WIDE_INT stack_pointer_offset;};/* Used to enable/disable debugging features.  */const char *ix86_debug_arg_string, *ix86_debug_addr_string;/* Code model option as passed by user.  */const char *ix86_cmodel_string;/* Parsed value.  */enum cmodel ix86_cmodel;/* Asm dialect.  */const char *ix86_asm_string;enum asm_dialect ix86_asm_dialect = ASM_ATT;/* which cpu are we scheduling for */enum processor_type ix86_cpu;/* which unit we are generating floating point math for */enum fpmath_unit ix86_fpmath;/* which instruction set architecture to use.  */int ix86_arch;/* Strings to hold which cpu and instruction set architecture  to use.  */const char *ix86_cpu_string;		/* for -mcpu=<xxx> */const char *ix86_arch_string;		/* for -march=<xxx> */const char *ix86_fpmath_string;		/* for -mfpmath=<xxx> *//* # of registers to use to pass arguments.  */const char *ix86_regparm_string;/* true if sse prefetch instruction is not NOOP.  */int x86_prefetch_sse;/* ix86_regparm_string as a number */int ix86_regparm;/* Alignment to use for loops and jumps:  *//* Power of two alignment for loops.  */const char *ix86_align_loops_string;/* Power of two alignment for non-loop jumps.  */const char *ix86_align_jumps_string;/* Power of two alignment for stack boundary in bytes.  */const char *ix86_preferred_stack_boundary_string;/* Preferred alignment for stack boundary in bits.  */int ix86_preferred_stack_boundary;/* Values 1-5: see jump.c */int ix86_branch_cost;const char *ix86_branch_cost_string;/* Power of two alignment for functions.  */const char *ix86_align_funcs_string;/* Prefix built by ASM_GENERATE_INTERNAL_LABEL.  */static char internal_label_prefix[16];static int internal_label_prefix_len;static int local_symbolic_operand PARAMS ((rtx, enum machine_mode));static void output_pic_addr_const PARAMS ((FILE *, rtx, int));static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode,				       int, int, FILE *));static rtx ix86_expand_int_compare PARAMS ((enum rtx_code, rtx, rtx));static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,							   rtx *, rtx *));static rtx gen_push PARAMS ((rtx));static int memory_address_length PARAMS ((rtx addr));static int ix86_flags_dependant PARAMS ((rtx, rtx, enum attr_type));static int ix86_agi_dependant PARAMS ((rtx, rtx, enum attr_type));static int ix86_safe_length PARAMS ((rtx));static enum attr_memory ix86_safe_memory PARAMS ((rtx));static enum attr_pent_pair ix86_safe_pent_pair PARAMS ((rtx));static enum attr_ppro_uops ix86_safe_ppro_uops PARAMS ((rtx));static void ix86_dump_ppro_packet PARAMS ((FILE *));static void ix86_reorder_insn PARAMS ((rtx *, rtx *));static rtx * ix86_pent_find_pair PARAMS ((rtx *, rtx *, enum attr_pent_pair,					 rtx));static void ix86_init_machine_status PARAMS ((struct function *));static void ix86_mark_machine_status PARAMS ((struct function *));static void ix86_free_machine_status PARAMS ((struct function *));static int ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));static int ix86_safe_length_prefix PARAMS ((rtx));static int ix86_nsaved_regs PARAMS ((void));static void ix86_emit_save_regs PARAMS ((void));static void ix86_emit_save_regs_using_mov PARAMS ((rtx, HOST_WIDE_INT));static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int, int));static void ix86_set_move_mem_attrs_1 PARAMS ((rtx, rtx, rtx, rtx, rtx));static void ix86_sched_reorder_pentium PARAMS ((rtx *, rtx *));static void ix86_sched_reorder_ppro PARAMS ((rtx *, rtx *));static HOST_WIDE_INT ix86_GOT_alias_set PARAMS ((void));static void ix86_adjust_counter PARAMS ((rtx, HOST_WIDE_INT));static rtx ix86_expand_aligntest PARAMS ((rtx, int));static void ix86_expand_strlensi_unroll_1 PARAMS ((rtx, rtx));static int ix86_issue_rate PARAMS ((void));static int ix86_adjust_cost PARAMS ((rtx, rtx, rtx, int));static void ix86_sched_init PARAMS ((FILE *, int, int));static int ix86_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));static int ix86_variable_issue PARAMS ((FILE *, int, rtx, int));static void ix86_init_mmx_sse_builtins PARAMS ((void));struct ix86_address{  rtx base, index, disp;  HOST_WIDE_INT scale;};static int ix86_decompose_address PARAMS ((rtx, struct ix86_address *));struct builtin_description;static rtx ix86_expand_sse_comi PARAMS ((const struct builtin_description *,					 tree, rtx));static rtx ix86_expand_sse_compare PARAMS ((const struct builtin_description *,					    tree, rtx));static rtx ix86_expand_unop1_builtin PARAMS ((enum insn_code, tree, rtx));static rtx ix86_expand_unop_builtin PARAMS ((enum insn_code, tree, rtx, int));static rtx ix86_expand_binop_builtin PARAMS ((enum insn_code, tree, rtx));static rtx ix86_expand_timode_binop_builtin PARAMS ((enum insn_code,						     tree, rtx));static rtx ix86_expand_store_builtin PARAMS ((enum insn_code, tree));static rtx safe_vector_operand PARAMS ((rtx, enum machine_mode));static enum rtx_code ix86_fp_compare_code_to_integer PARAMS ((enum rtx_code));static void ix86_fp_comparison_codes PARAMS ((enum rtx_code code,					      enum rtx_code *,					      enum rtx_code *,					      enum rtx_code *));static rtx ix86_expand_fp_compare PARAMS ((enum rtx_code, rtx, rtx, rtx,					  rtx *, rtx *));static int ix86_fp_comparison_arithmetics_cost PARAMS ((enum rtx_code code));static int ix86_fp_comparison_fcomi_cost PARAMS ((enum rtx_code code));static int ix86_fp_comparison_sahf_cost PARAMS ((enum rtx_code code));static int ix86_fp_comparison_cost PARAMS ((enum rtx_code code));static int ix86_save_reg PARAMS ((int, int));static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));static int ix86_comp_type_attributes PARAMS ((tree, tree));const struct attribute_spec ix86_attribute_table[];static tree ix86_handle_cdecl_attribute PARAMS ((tree *, tree, tree, int, bool *));static tree ix86_handle_regparm_attribute PARAMS ((tree *, tree, tree, int, bool *));#ifdef DO_GLOBAL_CTORS_BODYstatic void ix86_svr3_asm_out_constructor PARAMS ((rtx, int));#endif/* Register class used for passing given 64bit part of the argument.   These represent classes as documented by the PS ABI, with the exception   of SSESF, SSEDF classes, that are basically SSE class, just gcc will   use SF or DFmode move instead of DImode to avoid reformating penalties.   Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves   whenever possible (upper half does contain padding). */enum x86_64_reg_class  {    X86_64_NO_CLASS,    X86_64_INTEGER_CLASS,    X86_64_INTEGERSI_CLASS,    X86_64_SSE_CLASS,    X86_64_SSESF_CLASS,    X86_64_SSEDF_CLASS,    X86_64_SSEUP_CLASS,    X86_64_X87_CLASS,    X86_64_X87UP_CLASS,    X86_64_MEMORY_CLASS  };static const char * const x86_64_reg_class_name[] =   {"no", "integer", "integerSI", "sse", "sseSF", "sseDF", "sseup", "x87", "x87up", "no"};#define MAX_CLASSES 4static int classify_argument PARAMS ((enum machine_mode, tree,				      enum x86_64_reg_class [MAX_CLASSES],				      int));static int examine_argument PARAMS ((enum machine_mode, tree, int, int *,				     int *));static rtx construct_container PARAMS ((enum machine_mode, tree, int, int, int,

⌨️ 快捷键说明

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