aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/i386/i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i386/i386.c')
-rw-r--r--gcc/config/i386/i386.c334
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;