i386.c (struct machine_function): Add save_varrargs_registers.
* i386.c (struct machine_function): Add save_varrargs_registers. (ix86_save_varrargs_registers): New macro. (ix86_frame_layout): Support 64bit; support red zones and varrargs area. (ix86_expand_prologue): Likewise. (ix86_emit_epilogue_esp_adjustement): Likewise. (ix86_expand_epilogue): Likewise. * i386.md (pro_epilogue_adjust_stack): Turn to expander; support 64bit. (pro_epilogue_adjust_stack_1): New insn. (pro_epilogue_adjust_stack_rex64): Likewise. * i386.h (MASK_NO_RED_ZONE): New constant. (TARGET_RED_ZONE): New macro. (TARGET_OPTIONS): Add "red-zone" and "no-red-zone" (RED_ZONE_SIZE): New constant. (RED_ZONE_RESERVE): New constant. From-SVN: r40846
This commit is contained in:
parent
788bf0e34e
commit
8362f4207e
@ -1,3 +1,20 @@
|
||||
Mon Mar 26 14:35:18 CEST 2001 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* i386.c (struct machine_function): Add save_varrargs_registers.
|
||||
(ix86_save_varrargs_registers): New macro.
|
||||
(ix86_frame_layout): Support 64bit; support red zones and varrargs area.
|
||||
(ix86_expand_prologue): Likewise.
|
||||
(ix86_emit_epilogue_esp_adjustement): Likewise.
|
||||
(ix86_expand_epilogue): Likewise.
|
||||
* i386.md (pro_epilogue_adjust_stack): Turn to expander; support 64bit.
|
||||
(pro_epilogue_adjust_stack_1): New insn.
|
||||
(pro_epilogue_adjust_stack_rex64): Likewise.
|
||||
* i386.h (MASK_NO_RED_ZONE): New constant.
|
||||
(TARGET_RED_ZONE): New macro.
|
||||
(TARGET_OPTIONS): Add "red-zone" and "no-red-zone"
|
||||
(RED_ZONE_SIZE): New constant.
|
||||
(RED_ZONE_RESERVE): New constant.
|
||||
|
||||
2001-03-25 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
|
||||
* toplev.c (set_float_handler): Use memcpy, not bcopy.
|
||||
|
@ -442,15 +442,19 @@ struct rtx_def *ix86_compare_op0 = NULL_RTX;
|
||||
struct rtx_def *ix86_compare_op1 = NULL_RTX;
|
||||
|
||||
#define MAX_386_STACK_LOCALS 2
|
||||
/* 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:
|
||||
@ -475,9 +479,11 @@ 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. */
|
||||
@ -2338,6 +2344,15 @@ ix86_compute_frame_layout (frame)
|
||||
/* Register save area */
|
||||
offset += frame->nregs * UNITS_PER_WORD;
|
||||
|
||||
/* Va-arg area */
|
||||
if (ix86_save_varrargs_registers)
|
||||
{
|
||||
offset += X86_64_VARARGS_SIZE;
|
||||
frame->va_arg_size = X86_64_VARARGS_SIZE;
|
||||
}
|
||||
else
|
||||
frame->va_arg_size = 0;
|
||||
|
||||
/* Align start of frame for local function. */
|
||||
frame->padding1 = ((offset + stack_alignment_needed - 1)
|
||||
& -stack_alignment_needed) - offset;
|
||||
@ -2370,15 +2385,28 @@ ix86_compute_frame_layout (frame)
|
||||
/* Size prologue needs to allocate. */
|
||||
frame->to_allocate =
|
||||
(size + frame->padding1 + frame->padding2
|
||||
+ frame->outgoing_arguments_size);
|
||||
+ frame->outgoing_arguments_size + frame->va_arg_size);
|
||||
|
||||
if (TARGET_64BIT && TARGET_RED_ZONE && current_function_sp_is_unchanging
|
||||
&& current_function_is_leaf)
|
||||
{
|
||||
frame->red_zone_size = frame->to_allocate;
|
||||
if (frame->red_zone_size > RED_ZONE_SIZE - RED_ZONE_RESERVE)
|
||||
frame->red_zone_size = RED_ZONE_SIZE - RED_ZONE_RESERVE;
|
||||
}
|
||||
else
|
||||
frame->red_zone_size = 0;
|
||||
frame->to_allocate -= frame->red_zone_size;
|
||||
frame->stack_pointer_offset -= frame->red_zone_size;
|
||||
#if 0
|
||||
fprintf (stderr, "nregs: %i\n", frame->nregs);
|
||||
fprintf (stderr, "size: %i\n", size);
|
||||
fprintf (stderr, "alignment1: %i\n", stack_alignment_needed);
|
||||
fprintf (stderr, "padding1: %i\n", frame->padding1);
|
||||
fprintf (stderr, "va_arg: %i\n", frame->va_arg_size);
|
||||
fprintf (stderr, "padding2: %i\n", frame->padding2);
|
||||
fprintf (stderr, "to_allocate: %i\n", frame->to_allocate);
|
||||
fprintf (stderr, "red_zone_size: %i\n", frame->red_zone_size);
|
||||
fprintf (stderr, "frame_pointer_offset: %i\n", frame->frame_pointer_offset);
|
||||
fprintf (stderr, "hard_frame_pointer_offset: %i\n",
|
||||
frame->hard_frame_pointer_offset);
|
||||
@ -2438,8 +2466,12 @@ ix86_expand_prologue ()
|
||||
(stack_pointer_rtx, stack_pointer_rtx,
|
||||
GEN_INT (-frame.to_allocate), hard_frame_pointer_rtx));
|
||||
else
|
||||
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
|
||||
GEN_INT (-frame.to_allocate)));
|
||||
if (TARGET_64BIT)
|
||||
insn = emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
|
||||
GEN_INT (-frame.to_allocate)));
|
||||
else
|
||||
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
|
||||
GEN_INT (-frame.to_allocate)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else
|
||||
@ -2448,6 +2480,9 @@ ix86_expand_prologue ()
|
||||
|
||||
rtx arg0, sym;
|
||||
|
||||
if (TARGET_64BIT)
|
||||
abort();
|
||||
|
||||
arg0 = gen_rtx_REG (SImode, 0);
|
||||
emit_move_insn (arg0, GEN_INT (frame.to_allocate));
|
||||
|
||||
@ -2489,8 +2524,12 @@ ix86_emit_epilogue_esp_adjustment (tsize)
|
||||
GEN_INT (tsize),
|
||||
hard_frame_pointer_rtx));
|
||||
else
|
||||
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
|
||||
GEN_INT (tsize)));
|
||||
if (TARGET_64BIT)
|
||||
emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
|
||||
GEN_INT (tsize)));
|
||||
else
|
||||
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
|
||||
GEN_INT (tsize)));
|
||||
}
|
||||
|
||||
/* Emit code to restore saved registers using MOV insns. First register
|
||||
@ -2563,18 +2602,20 @@ ix86_expand_epilogue (emit_return)
|
||||
ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx, offset);
|
||||
|
||||
if (!frame_pointer_needed)
|
||||
ix86_emit_epilogue_esp_adjustment (frame.to_allocate
|
||||
+ frame.nregs * UNITS_PER_WORD);
|
||||
ix86_emit_epilogue_esp_adjustment (frame.to_allocate + frame.nregs * UNITS_PER_WORD);
|
||||
/* If not an i386, mov & pop is faster than "leave". */
|
||||
else if (TARGET_USE_LEAVE || optimize_size)
|
||||
emit_insn (gen_leave ());
|
||||
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,
|
||||
hard_frame_pointer_rtx));
|
||||
emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
|
||||
if (TARGET_64BIT)
|
||||
emit_insn (gen_popdi1 (hard_frame_pointer_rtx));
|
||||
else
|
||||
emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2595,9 +2636,19 @@ ix86_expand_epilogue (emit_return)
|
||||
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
if (ix86_save_reg (regno))
|
||||
emit_insn (gen_popsi1 (gen_rtx_REG (SImode, regno)));
|
||||
{
|
||||
if (TARGET_64BIT)
|
||||
emit_insn (gen_popdi1 (gen_rtx_REG (Pmode, regno)));
|
||||
else
|
||||
emit_insn (gen_popsi1 (gen_rtx_REG (Pmode, regno)));
|
||||
}
|
||||
if (frame_pointer_needed)
|
||||
emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
|
||||
{
|
||||
if (TARGET_64BIT)
|
||||
emit_insn (gen_popdi1 (hard_frame_pointer_rtx));
|
||||
else
|
||||
emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
|
||||
}
|
||||
}
|
||||
|
||||
/* Sibcall epilogues don't want a return instruction. */
|
||||
@ -2616,6 +2667,10 @@ ix86_expand_epilogue (emit_return)
|
||||
{
|
||||
rtx ecx = gen_rtx_REG (SImode, 2);
|
||||
|
||||
/* There are is no "pascal" calling convention in 64bit ABI. */
|
||||
if (TARGET_64BIT)
|
||||
abort();
|
||||
|
||||
emit_insn (gen_popsi1 (ecx));
|
||||
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, popc));
|
||||
emit_jump_insn (gen_return_indirect_internal (ecx));
|
||||
|
@ -120,6 +120,7 @@ extern int target_flags;
|
||||
#define MASK_128BIT_LONG_DOUBLE 0x00080000 /* long double size is 128bit */
|
||||
#define MASK_MIX_SSE_I387 0x00100000 /* Mix SSE and i387 instructions */
|
||||
#define MASK_64BIT 0x00200000 /* Produce 64bit code */
|
||||
#define MASK_NO_RED_ZONE 0x00400000 /* Do not use red zone */
|
||||
|
||||
/* Temporary codegen switches */
|
||||
#define MASK_INTEL_SYNTAX 0x00000200
|
||||
@ -250,6 +251,8 @@ extern const int x86_partial_reg_dependency, x86_memory_mismatch_stall;
|
||||
#define TARGET_MIX_SSE_I387 ((target_flags & MASK_MIX_SSE_I387) != 0)
|
||||
#define TARGET_MMX ((target_flags & MASK_MMX) != 0)
|
||||
|
||||
#define TARGET_RED_ZONE (!(target_flags & MASK_NO_RED_ZONE))
|
||||
|
||||
#define TARGET_SWITCHES \
|
||||
{ { "80387", MASK_80387, N_("Use hardware fp") }, \
|
||||
{ "no-80387", -MASK_80387, N_("Do not use hardware fp") }, \
|
||||
@ -338,6 +341,10 @@ extern const int x86_partial_reg_dependency, x86_memory_mismatch_stall;
|
||||
N_("Generate 64bit x86-64 code") }, \
|
||||
{ "32", -MASK_64BIT, \
|
||||
N_("Generate 32bit i386 code") }, \
|
||||
{ "red-zone", -MASK_NO_RED_ZONE, \
|
||||
N_("Use red-zone in the x86-64 code") }, \
|
||||
{ "no-red-zone", MASK_NO_RED_ZONE, \
|
||||
N_("do not use red-zone in the x86-64 code") }, \
|
||||
SUBTARGET_SWITCHES \
|
||||
{ "", TARGET_DEFAULT, 0 }}
|
||||
|
||||
@ -3106,6 +3113,10 @@ enum cmodel {
|
||||
CM_SMALL_PIC
|
||||
};
|
||||
|
||||
/* Size of the RED_ZONE area. */
|
||||
#define RED_ZONE_SIZE 128
|
||||
/* Reserved area of the red zone for temporaries. */
|
||||
#define RED_ZONE_RESERVE 8
|
||||
/* Valud of -mcmodel specified by user. */
|
||||
extern const char *ix86_cmodel_string;
|
||||
extern enum cmodel ix86_cmodel;
|
||||
|
@ -6885,7 +6885,7 @@
|
||||
(zero_extend:DI
|
||||
(minus:SI (match_dup 1)
|
||||
(match_dup 2))))]
|
||||
"ix86_match_ccmode (insn, CCmode)
|
||||
"TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
|
||||
&& ix86_binary_operator_ok (MINUS, SImode, operands)"
|
||||
"sub{q}\\t{%2, %0|%0, %2}"
|
||||
[(set_attr "type" "alu")
|
||||
@ -13028,6 +13028,18 @@
|
||||
(set_attr "modrm" "0")
|
||||
(set_attr "athlon_decode" "vector")
|
||||
(set_attr "ppro_uops" "few")])
|
||||
|
||||
(define_insn "leave_rex64"
|
||||
[(set (reg:DI 7) (reg:DI 6))
|
||||
(set (reg:DI 6) (mem:DI (pre_dec:DI (reg:DI 7))))]
|
||||
"TARGET_64BIT"
|
||||
"leave"
|
||||
[(set_attr "length_immediate" "0")
|
||||
(set_attr "length" "1")
|
||||
(set_attr "modrm" "0")
|
||||
(set_attr "modrm" "0")
|
||||
(set_attr "athlon_decode" "vector")
|
||||
(set_attr "ppro_uops" "few")])
|
||||
|
||||
(define_expand "ffssi2"
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "")
|
||||
@ -15367,15 +15379,32 @@
|
||||
;; [(set (mem (plus (reg ebp) (const_int -160000))) (const_int 0))]
|
||||
;;
|
||||
;; in proper program order.
|
||||
(define_expand "pro_epilogue_adjust_stack"
|
||||
[(parallel [(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(plus:SI (match_operand:SI 1 "register_operand" "0,r")
|
||||
(match_operand:SI 2 "immediate_operand" "i,i")))
|
||||
(set (match_operand:SI 3 "register_operand" "+r,r")
|
||||
(match_dup 3))
|
||||
(clobber (reg:CC 17))])]
|
||||
""
|
||||
"
|
||||
{
|
||||
if (TARGET_64BIT)
|
||||
{
|
||||
emit_insn (gen_pro_epilogue_adjust_stack_rex64 (operands[0], operands[1],
|
||||
operands[2], operands[3]));
|
||||
DONE;
|
||||
}
|
||||
}")
|
||||
|
||||
(define_insn "pro_epilogue_adjust_stack"
|
||||
(define_insn "*pro_epilogue_adjust_stack_1"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(plus:SI (match_operand:SI 1 "register_operand" "0,r")
|
||||
(match_operand:SI 2 "immediate_operand" "i,i")))
|
||||
(set (match_operand:SI 3 "register_operand" "+r,r")
|
||||
(match_dup 3))
|
||||
(clobber (reg:CC 17))]
|
||||
""
|
||||
"!TARGET_64BIT"
|
||||
"*
|
||||
{
|
||||
switch (get_attr_type (insn))
|
||||
@ -15411,6 +15440,50 @@
|
||||
(const_string "lea")))
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "pro_epilogue_adjust_stack_rex64"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r,r")
|
||||
(plus:DI (match_operand:DI 1 "register_operand" "0,r")
|
||||
(match_operand:DI 2 "x86_64_immediate_operand" "e,e")))
|
||||
(set (match_operand:DI 3 "register_operand" "+r,r")
|
||||
(match_dup 3))
|
||||
(clobber (reg:CC 17))]
|
||||
"TARGET_64BIT"
|
||||
"*
|
||||
{
|
||||
switch (get_attr_type (insn))
|
||||
{
|
||||
case TYPE_IMOV:
|
||||
return \"mov{q}\\t{%1, %0|%0, %1}\";
|
||||
|
||||
case TYPE_ALU:
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& (INTVAL (operands[2]) == 128
|
||||
|| (INTVAL (operands[2]) < 0
|
||||
&& INTVAL (operands[2]) != -128)))
|
||||
{
|
||||
operands[2] = GEN_INT (-INTVAL (operands[2]));
|
||||
return \"sub{q}\\t{%2, %0|%0, %2}\";
|
||||
}
|
||||
return \"add{q}\\t{%2, %0|%0, %2}\";
|
||||
|
||||
case TYPE_LEA:
|
||||
operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
|
||||
return \"lea{q}\\t{%a2, %0|%0, %a2}\";
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}"
|
||||
[(set (attr "type")
|
||||
(cond [(eq_attr "alternative" "0")
|
||||
(const_string "alu")
|
||||
(match_operand:DI 2 "const0_operand" "")
|
||||
(const_string "imov")
|
||||
]
|
||||
(const_string "lea")))
|
||||
(set_attr "mode" "DI")])
|
||||
|
||||
|
||||
;; Placeholder for the conditional moves. This one is split eighter to SSE
|
||||
;; based moves emulation or to usual cmove sequence. Little bit unfortunate
|
||||
;; fact is that compares supported by the cmp??ss instructions are exactly
|
||||
|
Loading…
Reference in New Issue
Block a user