diff options
author | Jan Hubicka <jh@suse.cz> | 2001-03-26 14:36:35 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2001-03-26 12:36:35 +0000 |
commit | 8362f4207eaa70dbee88b09a893cd5aa0515ee7f (patch) | |
tree | a20a91b60dc63fff8194a25f5fd90ad81a145397 /gcc | |
parent | 788bf0e34ebec318ef42f6a7ffd9e8632756908a (diff) | |
download | gcc-8362f4207eaa70dbee88b09a893cd5aa0515ee7f.zip gcc-8362f4207eaa70dbee88b09a893cd5aa0515ee7f.tar.gz gcc-8362f4207eaa70dbee88b09a893cd5aa0515ee7f.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 77 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 11 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 79 |
4 files changed, 170 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 55ef8ed..db3c86d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index fa6633d..b12d625 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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)); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 7312108..1552b41 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 4850ca4..6a23023 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -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 |