diff options
Diffstat (limited to 'gcc/config/i386/i386.c')
-rw-r--r-- | gcc/config/i386/i386.c | 334 |
1 files changed, 204 insertions, 130 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 8fdf24dad46..d4653ace834 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -830,7 +830,8 @@ static void x86_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, static bool x86_can_output_mi_thunk (tree, HOST_WIDE_INT, HOST_WIDE_INT, tree); static void x86_file_start (void); static void ix86_reorg (void); -bool ix86_expand_carry_flag_compare (enum rtx_code, rtx, rtx, rtx*); +static bool ix86_expand_carry_flag_compare (enum rtx_code, rtx, rtx, rtx*); +static tree ix86_build_builtin_va_list (void); struct ix86_address { @@ -1012,6 +1013,9 @@ static void init_ext_80387_constants (void); #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG ix86_reorg +#undef TARGET_BUILD_BUILTIN_VA_LIST +#define TARGET_BUILD_BUILTIN_VA_LIST ix86_build_builtin_va_list + struct gcc_target targetm = TARGET_INITIALIZER; /* The svr4 ABI for the i386 says that records and unions are returned @@ -1662,7 +1666,7 @@ ix86_comp_type_attributes (tree type1, tree type2) /* Return the regparm value for a fuctio with the indicated TYPE and DECL. DECL may be NULL when calling function indirectly - or considerling a libcall. */ + or considering a libcall. */ static int ix86_function_regparm (tree type, tree decl) @@ -1930,7 +1934,7 @@ static int classify_argument (enum machine_mode mode, tree type, enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset) { - int bytes = + HOST_WIDE_INT bytes = (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode); int words = (bytes + (bit_offset % 64) / 8 + UNITS_PER_WORD - 1) / UNITS_PER_WORD; @@ -2193,11 +2197,14 @@ classify_argument (enum machine_mode mode, tree type, case DFmode: classes[0] = X86_64_SSEDF_CLASS; return 1; - case TFmode: + case XFmode: classes[0] = X86_64_X87_CLASS; classes[1] = X86_64_X87UP_CLASS; return 2; + case TFmode: case TCmode: + return 0; + case XCmode: classes[0] = X86_64_X87_CLASS; classes[1] = X86_64_X87UP_CLASS; classes[2] = X86_64_X87_CLASS; @@ -2334,16 +2341,16 @@ construct_container (enum machine_mode mode, tree type, int in_return, return gen_rtx_REG (mode, SSE_REGNO (sse_regno)); if (n == 2 && class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS) - return gen_rtx_REG (TFmode, FIRST_STACK_REG); + return gen_rtx_REG (XFmode, FIRST_STACK_REG); if (n == 2 && class[0] == X86_64_INTEGER_CLASS && class[1] == X86_64_INTEGER_CLASS - && (mode == CDImode || mode == TImode) + && (mode == CDImode || mode == TImode || mode == TFmode) && intreg[0] + 1 == intreg[1]) return gen_rtx_REG (mode, intreg[0]); if (n == 4 && class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS && class[2] == X86_64_X87_CLASS && class[3] == X86_64_X87UP_CLASS) - return gen_rtx_REG (TCmode, FIRST_STACK_REG); + return gen_rtx_REG (XCmode, FIRST_STACK_REG); /* Otherwise figure out the entries of the PARALLEL. */ for (i = 0; i < n; i++) @@ -2775,8 +2782,9 @@ ix86_return_in_memory (tree type) } } - if (mode == TFmode) + if (mode == XFmode) return 0; + if (size > 12) return 1; return 0; @@ -2791,20 +2799,23 @@ ix86_libcall_value (enum machine_mode mode) { switch (mode) { - case SFmode: - case SCmode: - case DFmode: - case DCmode: - return gen_rtx_REG (mode, FIRST_SSE_REG); - case TFmode: - case TCmode: - return gen_rtx_REG (mode, FIRST_FLOAT_REG); - default: - return gen_rtx_REG (mode, 0); + case SFmode: + case SCmode: + case DFmode: + case DCmode: + return gen_rtx_REG (mode, FIRST_SSE_REG); + case XFmode: + case XCmode: + return gen_rtx_REG (mode, FIRST_FLOAT_REG); + case TFmode: + case TCmode: + return NULL; + default: + return gen_rtx_REG (mode, 0); } } else - return gen_rtx_REG (mode, ix86_value_regno (mode)); + return gen_rtx_REG (mode, ix86_value_regno (mode)); } /* Given a mode, return the register to use for a return value. */ @@ -2825,8 +2836,8 @@ ix86_value_regno (enum machine_mode mode) /* Create the va_list data type. */ -tree -ix86_build_va_list (void) +static tree +ix86_build_builtin_va_list (void) { tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl; @@ -3430,7 +3441,7 @@ const_int_1_31_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) reference and a constant. */ int -symbolic_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { switch (GET_CODE (op)) { @@ -3474,7 +3485,7 @@ symbolic_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) /* Return true if the operand contains a @GOT or @GOTOFF reference. */ int -pic_symbolic_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +pic_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { if (GET_CODE (op) != CONST) return 0; @@ -3537,7 +3548,7 @@ local_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) /* Test for various thread-local symbols. */ int -tls_symbolic_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { if (GET_CODE (op) != SYMBOL_REF) return 0; @@ -3553,29 +3564,27 @@ tls_symbolic_operand_1 (rtx op, enum tls_model kind) } int -global_dynamic_symbolic_operand (register rtx op, +global_dynamic_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return tls_symbolic_operand_1 (op, TLS_MODEL_GLOBAL_DYNAMIC); } int -local_dynamic_symbolic_operand (register rtx op, +local_dynamic_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return tls_symbolic_operand_1 (op, TLS_MODEL_LOCAL_DYNAMIC); } int -initial_exec_symbolic_operand (register rtx op, - enum machine_mode mode ATTRIBUTE_UNUSED) +initial_exec_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return tls_symbolic_operand_1 (op, TLS_MODEL_INITIAL_EXEC); } int -local_exec_symbolic_operand (register rtx op, - enum machine_mode mode ATTRIBUTE_UNUSED) +local_exec_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return tls_symbolic_operand_1 (op, TLS_MODEL_LOCAL_EXEC); } @@ -3646,13 +3655,13 @@ constant_call_address_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) /* Match exactly zero and one. */ int -const0_operand (register rtx op, enum machine_mode mode) +const0_operand (rtx op, enum machine_mode mode) { return op == CONST0_RTX (mode); } int -const1_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +const1_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return op == const1_rtx; } @@ -3660,33 +3669,32 @@ const1_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) /* Match 2, 4, or 8. Used for leal multiplicands. */ int -const248_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +const248_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return (GET_CODE (op) == CONST_INT && (INTVAL (op) == 2 || INTVAL (op) == 4 || INTVAL (op) == 8)); } int -const_0_to_3_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +const_0_to_3_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 4); } int -const_0_to_7_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +const_0_to_7_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 8); } int -const_0_to_15_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +const_0_to_15_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 16); } int -const_0_to_255_operand (register rtx op, - enum machine_mode mode ATTRIBUTE_UNUSED) +const_0_to_255_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 256); } @@ -3695,7 +3703,7 @@ const_0_to_255_operand (register rtx op, /* True if this is a constant appropriate for an increment or decrement. */ int -incdec_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +incdec_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { /* On Pentium4, the inc and dec operations causes extra dependency on flag registers, since carry flag is not set. */ @@ -3724,7 +3732,7 @@ shiftdi_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) Which would only happen in pathological cases. */ int -reg_no_sp_operand (register rtx op, enum machine_mode mode) +reg_no_sp_operand (rtx op, enum machine_mode mode) { rtx t = op; if (GET_CODE (t) == SUBREG) @@ -3736,7 +3744,7 @@ reg_no_sp_operand (register rtx op, enum machine_mode mode) } int -mmx_reg_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +mmx_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return MMX_REG_P (op); } @@ -3745,7 +3753,7 @@ mmx_reg_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) general_operand. */ int -general_no_elim_operand (register rtx op, enum machine_mode mode) +general_no_elim_operand (rtx op, enum machine_mode mode) { rtx t = op; if (GET_CODE (t) == SUBREG) @@ -3766,7 +3774,7 @@ general_no_elim_operand (register rtx op, enum machine_mode mode) register_operand or const_int. */ int -nonmemory_no_elim_operand (register rtx op, enum machine_mode mode) +nonmemory_no_elim_operand (rtx op, enum machine_mode mode) { rtx t = op; if (GET_CODE (t) == SUBREG) @@ -3783,7 +3791,7 @@ nonmemory_no_elim_operand (register rtx op, enum machine_mode mode) otherwise work like register_operand. */ int -index_register_operand (register rtx op, enum machine_mode mode) +index_register_operand (rtx op, enum machine_mode mode) { rtx t = op; if (GET_CODE (t) == SUBREG) @@ -3804,7 +3812,7 @@ index_register_operand (register rtx op, enum machine_mode mode) /* Return true if op is a Q_REGS class register. */ int -q_regs_operand (register rtx op, enum machine_mode mode) +q_regs_operand (rtx op, enum machine_mode mode) { if (mode != VOIDmode && GET_MODE (op) != mode) return 0; @@ -3816,7 +3824,7 @@ q_regs_operand (register rtx op, enum machine_mode mode) /* Return true if op is an flags register. */ int -flags_reg_operand (register rtx op, enum machine_mode mode) +flags_reg_operand (rtx op, enum machine_mode mode) { if (mode != VOIDmode && GET_MODE (op) != mode) return 0; @@ -3826,7 +3834,7 @@ flags_reg_operand (register rtx op, enum machine_mode mode) /* Return true if op is a NON_Q_REGS class register. */ int -non_q_regs_operand (register rtx op, enum machine_mode mode) +non_q_regs_operand (rtx op, enum machine_mode mode) { if (mode != VOIDmode && GET_MODE (op) != mode) return 0; @@ -3874,7 +3882,7 @@ vector_move_operand (rtx op, enum machine_mode mode) a segment override. */ int -no_seg_address_operand (register rtx op, enum machine_mode mode) +no_seg_address_operand (rtx op, enum machine_mode mode) { struct ix86_address parts; @@ -3919,7 +3927,7 @@ sse_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) } /* Return 1 if OP is a valid comparison operator in valid mode. */ int -ix86_comparison_operator (register rtx op, enum machine_mode mode) +ix86_comparison_operator (rtx op, enum machine_mode mode) { enum machine_mode inmode; enum rtx_code code = GET_CODE (op); @@ -3960,7 +3968,7 @@ ix86_comparison_operator (register rtx op, enum machine_mode mode) /* Return 1 if OP is a valid comparison operator testing carry flag to be set. */ int -ix86_carry_flag_operator (register rtx op, enum machine_mode mode) +ix86_carry_flag_operator (rtx op, enum machine_mode mode) { enum machine_mode inmode; enum rtx_code code = GET_CODE (op); @@ -3992,7 +4000,7 @@ ix86_carry_flag_operator (register rtx op, enum machine_mode mode) /* Return 1 if OP is a comparison operator that can be issued by fcmov. */ int -fcmov_comparison_operator (register rtx op, enum machine_mode mode) +fcmov_comparison_operator (rtx op, enum machine_mode mode) { enum machine_mode inmode; enum rtx_code code = GET_CODE (op); @@ -4029,8 +4037,7 @@ fcmov_comparison_operator (register rtx op, enum machine_mode mode) /* Return 1 if OP is a binary operator that can be promoted to wider mode. */ int -promotable_binary_operator (register rtx op, - enum machine_mode mode ATTRIBUTE_UNUSED) +promotable_binary_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { switch (GET_CODE (op)) { @@ -4054,7 +4061,7 @@ promotable_binary_operator (register rtx op, into registers. */ int -cmp_fp_expander_operand (register rtx op, enum machine_mode mode) +cmp_fp_expander_operand (rtx op, enum machine_mode mode) { if (mode != VOIDmode && mode != GET_MODE (op)) return 0; @@ -4066,7 +4073,7 @@ cmp_fp_expander_operand (register rtx op, enum machine_mode mode) /* Match an SI or HImode register for a zero_extract. */ int -ext_register_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +ext_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { int regno; if ((!TARGET_64BIT || GET_MODE (op) != DImode) @@ -4085,7 +4092,7 @@ ext_register_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) OP is the expression matched, and MODE is its mode. */ int -binary_fp_operator (register rtx op, enum machine_mode mode) +binary_fp_operator (rtx op, enum machine_mode mode) { if (mode != VOIDmode && mode != GET_MODE (op)) return 0; @@ -4104,13 +4111,13 @@ binary_fp_operator (register rtx op, enum machine_mode mode) } int -mult_operator (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +mult_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return GET_CODE (op) == MULT; } int -div_operator (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +div_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return GET_CODE (op) == DIV; } @@ -4126,7 +4133,7 @@ arith_or_logical_operator (rtx op, enum machine_mode mode) /* Returns 1 if OP is memory operand with a displacement. */ int -memory_displacement_operand (register rtx op, enum machine_mode mode) +memory_displacement_operand (rtx op, enum machine_mode mode) { struct ix86_address parts; @@ -4168,7 +4175,7 @@ cmpsi_operand (rtx op, enum machine_mode mode) modRM array. */ int -long_memory_operand (register rtx op, enum machine_mode mode) +long_memory_operand (rtx op, enum machine_mode mode) { if (! memory_operand (op, mode)) return 0; @@ -4253,8 +4260,7 @@ init_ext_80387_constants (void) real_from_string (&ext_80387_constants_table[i], cst[i]); /* Ensure each constant is rounded to XFmode precision. */ real_convert (&ext_80387_constants_table[i], - TARGET_128BIT_LONG_DOUBLE ? TFmode : XFmode, - &ext_80387_constants_table[i]); + XFmode, &ext_80387_constants_table[i]); } ext_80387_constants_init = 1; @@ -4276,7 +4282,7 @@ standard_80387_constant_p (rtx x) /* For XFmode constants, try to find a special 80387 instruction on those CPUs that benefit from them. */ - if ((GET_MODE (x) == XFmode || GET_MODE (x) == TFmode) + if (GET_MODE (x) == XFmode && x86_ext_80387_constants & TUNEMASK) { REAL_VALUE_TYPE r; @@ -4347,7 +4353,7 @@ standard_80387_constant_rtx (int idx) } return CONST_DOUBLE_FROM_REAL_VALUE (ext_80387_constants_table[i], - TARGET_128BIT_LONG_DOUBLE ? TFmode : XFmode); + XFmode); } /* Return 1 if X is FP constant we can load to SSE register w/o using memory. @@ -4365,8 +4371,8 @@ standard_sse_constant_p (rtx x) int symbolic_reference_mentioned_p (rtx op) { - register const char *fmt; - register int i; + const char *fmt; + int i; if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) return 1; @@ -4376,7 +4382,7 @@ symbolic_reference_mentioned_p (rtx op) { if (fmt[i] == 'E') { - register int j; + int j; for (j = XVECLEN (op, i) - 1; j >= 0; j--) if (symbolic_reference_mentioned_p (XVECEXP (op, i, j))) @@ -4449,6 +4455,9 @@ x86_64_sign_extended_value (rtx value) library. Don't count TLS SYMBOL_REFs here, since they should fit only if inside of UNSPEC handled below. */ case SYMBOL_REF: + /* TLS symbols are not constant. */ + if (tls_symbolic_operand (value, Pmode)) + return false; return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL); /* For certain code models, the code is near as well. */ @@ -4554,6 +4563,9 @@ x86_64_zero_extended_value (rtx value) /* For certain code models, the symbolic references are known to fit. */ case SYMBOL_REF: + /* TLS symbols are not constant. */ + if (tls_symbolic_operand (value, Pmode)) + return false; return ix86_cmodel == CM_SMALL; /* For certain code models, the code is near as well. */ @@ -4882,7 +4894,7 @@ ix86_compute_frame_layout (struct ix86_frame *frame) { HOST_WIDE_INT total_size; int stack_alignment_needed = cfun->stack_alignment_needed / BITS_PER_UNIT; - int offset; + HOST_WIDE_INT offset; int preferred_alignment = cfun->preferred_stack_boundary / BITS_PER_UNIT; HOST_WIDE_INT size = get_frame_size (); @@ -4998,7 +5010,8 @@ ix86_compute_frame_layout (struct ix86_frame *frame) (size + frame->padding1 + frame->padding2 + frame->outgoing_arguments_size + frame->va_arg_size); - if (!frame->to_allocate && frame->nregs <= 1) + if ((!frame->to_allocate && frame->nregs <= 1) + || (TARGET_64BIT && frame->to_allocate >= (HOST_WIDE_INT) 0x80000000)) frame->save_regs_using_mov = false; if (TARGET_RED_ZONE && current_function_sp_is_unchanging @@ -5035,7 +5048,7 @@ ix86_compute_frame_layout (struct ix86_frame *frame) static void ix86_emit_save_regs (void) { - register int regno; + int regno; rtx insn; for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) @@ -5065,6 +5078,41 @@ ix86_emit_save_regs_using_mov (rtx pointer, HOST_WIDE_INT offset) } } +/* Expand prologue or epilogue stack adjustment. + The pattern exist to put a dependency on all ebp-based memory accesses. + STYLE should be negative if instructions should be marked as frame related, + zero if %r11 register is live and cannot be freely used and positive + otherwise. */ + +static void +pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, int style) +{ + rtx insn; + + if (! TARGET_64BIT) + insn = emit_insn (gen_pro_epilogue_adjust_stack_1 (dest, src, offset)); + else if (x86_64_immediate_operand (offset, DImode)) + insn = emit_insn (gen_pro_epilogue_adjust_stack_rex64 (dest, src, offset)); + else + { + rtx r11; + /* r11 is used by indirect sibcall return as well, set before the + epilogue and used after the epilogue. ATM indirect sibcall + shouldn't be used together with huge frame sizes in one + function because of the frame_size check in sibcall.c. */ + if (style == 0) + abort (); + r11 = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 3 /* R11 */); + insn = emit_insn (gen_rtx_SET (DImode, r11, offset)); + if (style < 0) + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_insn (gen_pro_epilogue_adjust_stack_rex64_2 (dest, src, r11, + offset)); + } + if (style < 0) + RTX_FRAME_RELATED_P (insn) = 1; +} + /* Expand the prologue into a bunch of separate insns. */ void @@ -5106,12 +5154,8 @@ ix86_expand_prologue (void) if (allocate == 0) ; else if (! TARGET_STACK_PROBE || allocate < CHECK_STACK_LIMIT) - { - insn = emit_insn (gen_pro_epilogue_adjust_stack - (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-allocate))); - RTX_FRAME_RELATED_P (insn) = 1; - } + pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (-allocate), -1); else { /* Only valid for Win32. */ @@ -5266,8 +5310,8 @@ ix86_expand_epilogue (int style) tmp = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx); emit_move_insn (hard_frame_pointer_rtx, tmp); - emit_insn (gen_pro_epilogue_adjust_stack - (stack_pointer_rtx, sa, const0_rtx)); + pro_epilogue_adjust_stack (stack_pointer_rtx, sa, + const0_rtx, style); } else { @@ -5278,19 +5322,19 @@ ix86_expand_epilogue (int style) } } else if (!frame_pointer_needed) - emit_insn (gen_pro_epilogue_adjust_stack - (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (frame.to_allocate - + frame.nregs * UNITS_PER_WORD))); + pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (frame.to_allocate + + frame.nregs * UNITS_PER_WORD), + style); /* If not an i386, mov & pop is faster than "leave". */ else if (TARGET_USE_LEAVE || optimize_size || !cfun->machine->use_fast_prologue_epilogue) emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ()); else { - emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx, - hard_frame_pointer_rtx, - const0_rtx)); + pro_epilogue_adjust_stack (stack_pointer_rtx, + hard_frame_pointer_rtx, + const0_rtx, style); if (TARGET_64BIT) emit_insn (gen_popdi1 (hard_frame_pointer_rtx)); else @@ -5305,14 +5349,13 @@ ix86_expand_epilogue (int style) { if (!frame_pointer_needed) abort (); - emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx, - hard_frame_pointer_rtx, - GEN_INT (offset))); + pro_epilogue_adjust_stack (stack_pointer_rtx, + hard_frame_pointer_rtx, + GEN_INT (offset), style); } else if (frame.to_allocate) - emit_insn (gen_pro_epilogue_adjust_stack - (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (frame.to_allocate))); + pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (frame.to_allocate), style); for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (ix86_save_reg (regno, false)) @@ -5351,7 +5394,7 @@ ix86_expand_epilogue (int style) { rtx ecx = gen_rtx_REG (SImode, 2); - /* There are is no "pascal" calling convention in 64bit ABI. */ + /* There is no "pascal" calling convention in 64bit ABI. */ if (TARGET_64BIT) abort (); @@ -5382,7 +5425,7 @@ ix86_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, strictly valid, but still used for computing length of lea instruction. */ static int -ix86_decompose_address (register rtx addr, struct ix86_address *out) +ix86_decompose_address (rtx addr, struct ix86_address *out) { rtx base = NULL_RTX; rtx index = NULL_RTX; @@ -5744,7 +5787,7 @@ legitimate_pic_operand_p (rtx x) in PIC mode. */ int -legitimate_pic_address_disp_p (register rtx disp) +legitimate_pic_address_disp_p (rtx disp) { bool saw_plus; @@ -5858,7 +5901,7 @@ legitimate_pic_address_disp_p (register rtx disp) be recognized. */ int -legitimate_address_p (enum machine_mode mode, register rtx addr, int strict) +legitimate_address_p (enum machine_mode mode, rtx addr, int strict) { struct ix86_address parts; rtx base, index, disp; @@ -6426,8 +6469,7 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov) See comments by legitimize_pic_address in i386.c for details. */ rtx -legitimize_address (register rtx x, register rtx oldx ATTRIBUTE_UNUSED, - enum machine_mode mode) +legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode) { int changed = 0; unsigned log; @@ -6567,8 +6609,8 @@ legitimize_address (register rtx x, register rtx oldx ATTRIBUTE_UNUSED, if (GET_CODE (XEXP (x, 0)) == REG) { - register rtx temp = gen_reg_rtx (Pmode); - register rtx val = force_operand (XEXP (x, 1), temp); + rtx temp = gen_reg_rtx (Pmode); + rtx val = force_operand (XEXP (x, 1), temp); if (val != temp) emit_move_insn (temp, val); @@ -6578,8 +6620,8 @@ legitimize_address (register rtx x, register rtx oldx ATTRIBUTE_UNUSED, else if (GET_CODE (XEXP (x, 1)) == REG) { - register rtx temp = gen_reg_rtx (Pmode); - register rtx val = force_operand (XEXP (x, 0), temp); + rtx temp = gen_reg_rtx (Pmode); + rtx val = force_operand (XEXP (x, 0), temp); if (val != temp) emit_move_insn (temp, val); @@ -6937,11 +6979,14 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, int reverse, void print_reg (rtx x, int code, FILE *file) { - if ((REGNO (x) == ARG_POINTER_REGNUM - || REGNO (x) == FRAME_POINTER_REGNUM - || REGNO (x) == FLAGS_REG - || REGNO (x) == FPSR_REG) - && file == asm_out_file) + /* Code -1 indicates we are called from print_rtx, and it is not + an error for a virtual register to appear here. */ + if (code == -1) + code = 0; + else if (REGNO (x) == ARG_POINTER_REGNUM + || REGNO (x) == FRAME_POINTER_REGNUM + || REGNO (x) == FLAGS_REG + || REGNO (x) == FPSR_REG) abort (); if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0) @@ -7008,12 +7053,17 @@ print_reg (rtx x, int code, FILE *file) /* FALLTHRU */ case 16: case 2: + normal: fputs (hi_reg_name[REGNO (x)], file); break; case 1: + if (REGNO (x) >= ARRAY_SIZE (qi_reg_name)) + goto normal; fputs (qi_reg_name[REGNO (x)], file); break; case 0: + if (REGNO (x) >= ARRAY_SIZE (qi_high_reg_name)) + goto normal; fputs (qi_high_reg_name[REGNO (x)], file); break; default: @@ -7402,7 +7452,7 @@ print_operand (FILE *file, rtx x, int code) if (ASSEMBLER_DIALECT == ASM_ATT) putc ('$', file); - fprintf (file, "0x%lx", l); + fprintf (file, "0x%08lx", l); } /* These float cases don't actually occur as immediate operands. */ @@ -7415,7 +7465,7 @@ print_operand (FILE *file, rtx x, int code) } else if (GET_CODE (x) == CONST_DOUBLE - && (GET_MODE (x) == XFmode || GET_MODE (x) == TFmode)) + && GET_MODE (x) == XFmode) { char dstr[30]; @@ -7453,7 +7503,7 @@ print_operand (FILE *file, rtx x, int code) /* Print a memory operand whose address is ADDR. */ void -print_operand_address (FILE *file, register rtx addr) +print_operand_address (FILE *file, rtx addr) { struct ix86_address parts; rtx base, index, disp; @@ -8655,7 +8705,6 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1) if (!is_sse && (fpcmp_mode == CCFPUmode || op_mode == XFmode - || op_mode == TFmode || ix86_use_fcomi_compare (code))) { op0 = force_reg (op_mode, op0); @@ -9130,7 +9179,6 @@ ix86_expand_branch (enum rtx_code code, rtx label) case SFmode: case DFmode: case XFmode: - case TFmode: { rtvec vec; int use_fcomi; @@ -9423,9 +9471,9 @@ ix86_expand_setcc (enum rtx_code code, rtx dest) return 1; /* DONE */ } -/* Expand comparison setting or clearing carry flag. Return true when successful - and set pop for the operation. */ -bool +/* Expand comparison setting or clearing carry flag. Return true when + successful and set pop for the operation. */ +static bool ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop) { enum machine_mode mode = @@ -10321,7 +10369,7 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode) int size; if (!TARGET_64BIT) - size = mode == TFmode ? 3 : (GET_MODE_SIZE (mode) / 4); + size = mode==XFmode ? 3 : GET_MODE_SIZE (mode) / 4; else size = (GET_MODE_SIZE (mode) + 4) / 8; @@ -10381,7 +10429,6 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode) switch (mode) { case XFmode: - case TFmode: REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l); parts[2] = gen_int_mode (l[2], SImode); break; @@ -10404,18 +10451,19 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode) split_ti (&operand, 1, &parts[0], &parts[1]); if (mode == XFmode || mode == TFmode) { + enum machine_mode upper_mode = mode==XFmode ? SImode : DImode; if (REG_P (operand)) { if (!reload_completed) abort (); parts[0] = gen_rtx_REG (DImode, REGNO (operand) + 0); - parts[1] = gen_rtx_REG (SImode, REGNO (operand) + 1); + parts[1] = gen_rtx_REG (upper_mode, REGNO (operand) + 1); } else if (offsettable_memref_p (operand)) { operand = adjust_address (operand, DImode, 0); parts[0] = operand; - parts[1] = adjust_address (operand, SImode, 8); + parts[1] = adjust_address (operand, upper_mode, 8); } else if (GET_CODE (operand) == CONST_DOUBLE) { @@ -10433,7 +10481,16 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode) DImode); else parts[0] = immed_double_const (l[0], l[1], DImode); - parts[1] = gen_int_mode (l[2], SImode); + if (upper_mode == SImode) + parts[1] = gen_int_mode (l[2], SImode); + else if (HOST_BITS_PER_WIDE_INT >= 64) + parts[1] + = gen_int_mode + ((l[2] & (((HOST_WIDE_INT) 2 << 31) - 1)) + + ((((HOST_WIDE_INT) l[3]) << 31) << 1), + DImode); + else + parts[1] = immed_double_const (l[2], l[3], DImode); } else abort (); @@ -10554,12 +10611,8 @@ ix86_split_long_move (rtx operands[]) { if (nparts == 3) { - /* We use only first 12 bytes of TFmode value, but for pushing we - are required to adjust stack as if we were pushing real 16byte - value. */ - if (mode == TFmode && !TARGET_64BIT) - emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-4))); + if (TARGET_128BIT_LONG_DOUBLE && mode == XFmode) + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (-4))); emit_move_insn (part[0][2], part[1][2]); } } @@ -11556,7 +11609,8 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx align_rtx) } void -ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx callarg2, +ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, + rtx callarg2 ATTRIBUTE_UNUSED, rtx pop, int sibcall) { rtx use = NULL, call; @@ -11594,7 +11648,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx callarg2, { rtx addr; addr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0)); - fnaddr = gen_rtx_REG (Pmode, 40); + fnaddr = gen_rtx_REG (Pmode, FIRST_REX_INT_REG + 3 /* R11 */); emit_move_insn (fnaddr, addr); fnaddr = gen_rtx_MEM (QImode, fnaddr); } @@ -13270,6 +13324,27 @@ ix86_init_mmx_sse_builtins (void) tree v2di_ftype_v2di = build_function_type_list (V2DI_type_node, V2DI_type_node, NULL_TREE); + tree float80_type; + tree float128_type; + + /* The __float80 type. */ + if (TYPE_MODE (long_double_type_node) == XFmode) + (*lang_hooks.types.register_builtin_type) (long_double_type_node, + "__float80"); + else + { + /* The __float80 type. */ + float80_type = make_node (REAL_TYPE); + TYPE_PRECISION (float80_type) = 96; + layout_type (float80_type); + (*lang_hooks.types.register_builtin_type) (float80_type, "__float80"); + } + + float128_type = make_node (REAL_TYPE); + TYPE_PRECISION (float128_type) = 128; + layout_type (float128_type); + (*lang_hooks.types.register_builtin_type) (float128_type, "__float128"); + /* Add all builtins that are more or less simple operations on two operands. */ for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++) @@ -14710,7 +14785,6 @@ ix86_memory_move_cost (enum machine_mode mode, enum reg_class class, int in) index = 1; break; case XFmode: - case TFmode: index = 2; break; default: @@ -15384,7 +15458,7 @@ x86_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED, #if TARGET_MACHO if (TARGET_MACHO) { - char *ip = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)); + const char *ip = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)); tmp = gen_rtx_SYMBOL_REF (Pmode, machopic_stub_name (ip)); tmp = gen_rtx_MEM (QImode, tmp); xops[0] = tmp; @@ -15595,7 +15669,7 @@ ix86_reorg (void) for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next) { basic_block bb = e->src; - rtx ret = bb->end; + rtx ret = BB_END (bb); rtx prev; bool replace = false; |