📄 i386.c
字号:
Relative to reg-reg move (2). */ {2, 3, 2}, /* cost of storing integer registers */ 2, /* cost of reg,reg fld/fst */ {2, 2, 6}, /* cost of loading fp registers in SFmode, DFmode and XFmode */ {4, 4, 6}, /* cost of loading integer registers */ 2, /* cost of moving MMX register */ {2, 2}, /* cost of loading MMX registers in SImode and DImode */ {2, 2}, /* cost of storing MMX registers in SImode and DImode */ 12, /* cost of moving SSE register */ {12, 12, 12}, /* cost of loading SSE registers in SImode, DImode and TImode */ {2, 2, 8}, /* cost of storing SSE registers in SImode, DImode and TImode */ 10, /* MMX or SSE register to integer */ 64, /* size of prefetch block */ 6, /* number of parallel prefetches */ 5, /* cost of FADD and FSUB insns. */ 7, /* cost of FMUL instruction. */ 43, /* cost of FDIV instruction. */ 2, /* cost of FABS instruction. */ 2, /* cost of FCHS instruction. */ 43, /* cost of FSQRT instruction. */};const struct processor_costs *ix86_cost = &pentium_cost;/* Processor feature/optimization bitmasks. */#define m_386 (1<<PROCESSOR_I386)#define m_486 (1<<PROCESSOR_I486)#define m_PENT (1<<PROCESSOR_PENTIUM)#define m_PPRO (1<<PROCESSOR_PENTIUMPRO)#define m_K6 (1<<PROCESSOR_K6)#define m_ATHLON (1<<PROCESSOR_ATHLON)#define m_PENT4 (1<<PROCESSOR_PENTIUM4)const int x86_use_leave = m_386 | m_K6 | m_ATHLON;const int x86_push_memory = m_386 | m_K6 | m_ATHLON | m_PENT4;const int x86_zero_extend_with_and = m_486 | m_PENT;const int x86_movx = m_ATHLON | m_PPRO | m_PENT4 /* m_386 | m_K6 */;const int x86_double_with_add = ~m_386;const int x86_use_bit_test = m_386;const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO | m_ATHLON | m_K6;const int x86_cmove = m_PPRO | m_ATHLON | m_PENT4;const int x86_3dnow_a = m_ATHLON;const int x86_deep_branch = m_PPRO | m_K6 | m_ATHLON | m_PENT4;const int x86_branch_hints = m_PENT4;const int x86_use_sahf = m_PPRO | m_K6 | m_PENT4;const int x86_partial_reg_stall = m_PPRO;const int x86_use_loop = m_K6;const int x86_use_fiop = ~(m_PPRO | m_ATHLON | m_PENT);const int x86_use_mov0 = m_K6;const int x86_use_cltd = ~(m_PENT | m_K6);const int x86_read_modify_write = ~m_PENT;const int x86_read_modify = ~(m_PENT | m_PPRO);const int x86_split_long_moves = m_PPRO;const int x86_promote_QImode = m_K6 | m_PENT | m_386 | m_486 | m_ATHLON;const int x86_fast_prefix = ~(m_PENT | m_486 | m_386);const int x86_single_stringop = m_386 | m_PENT4;const int x86_qimode_math = ~(0);const int x86_promote_qi_regs = 0;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 | m_PPRO);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_shift1 = ~m_486;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;/* Names for 8 (low), 8 (high), and 16-bit registers, respectively. */static const char *const qi_reg_name[] = QI_REGISTER_NAMES;static const char *const qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES;static const char *const hi_reg_name[] = HI_REGISTER_NAMES;/* 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 /*RDI*/, 4 /*RSI*/};/* 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;/* The encoding characters for the four TLS models present in ELF. */static char const tls_model_chars[] = " GLil";#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 GTY(()){ rtx stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS]; const char *some_ld_name; 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;/* TLS dialext. */const char *ix86_tls_dialect_string;enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU;/* Which unit we are generating floating point math for. */enum fpmath_unit ix86_fpmath;/* Which cpu are we scheduling for. */enum processor_type ix86_cpu;/* Which instruction set architecture to use. */enum processor_type 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 int tls_symbolic_operand_1 PARAMS ((rtx, enum tls_model));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 const char *get_some_local_dynamic_name PARAMS ((void));static int get_some_local_dynamic_name_1 PARAMS ((rtx *, void *));static rtx maybe_get_pool_constant PARAMS ((rtx));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 bool ix86_fixed_condition_code_regs PARAMS ((unsigned int *, unsigned int *));static enum machine_mode ix86_cc_modes_compatible PARAMS ((enum machine_mode, enum machine_mode));static rtx get_thread_pointer PARAMS ((void));static void get_pc_thunk_name PARAMS ((char [32], unsigned int));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 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 struct machine_function * ix86_init_machine_status PARAMS ((void));static int ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));static int ix86_nsaved_regs PARAMS ((void));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -