Index: gcc/gcc/config/i386/i386.c =================================================================== --- gcc.orig/gcc/config/i386/i386.c 2010-07-03 10:58:48.000000000 +0200 +++ gcc/gcc/config/i386/i386.c 2010-07-04 22:54:54.765066400 +0200 @@ -8347,6 +8347,12 @@ ix86_compute_frame_layout (struct ix86_f /* We've reached end of stack frame. */ frame->stack_pointer_offset = offset; + /* Adjust hard_frame_pointer for x64 abi, so that it points + to end of frame. */ + if (TARGET_64BIT && DEFAULT_ABI == MS_ABI && frame_pointer_needed) + frame->hard_frame_pointer_offset = offset; + + /* Size prologue needs to allocate. */ frame->to_allocate = (size + frame->padding1 + frame->padding2 @@ -8720,6 +8726,8 @@ ix86_expand_prologue (void) struct ix86_frame frame; HOST_WIDE_INT allocate; int gen_frame_pointer = frame_pointer_needed; + int be_x64frame = TARGET_64BIT && DEFAULT_ABI == MS_ABI + && frame_pointer_needed; ix86_finalize_stack_realign_flags (); @@ -8851,11 +8859,14 @@ ix86_expand_prologue (void) insn = emit_insn (gen_push (hard_frame_pointer_rtx)); RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); - RTX_FRAME_RELATED_P (insn) = 1; + if (!be_x64frame) + { + insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); + RTX_FRAME_RELATED_P (insn) = 1; - if (ix86_cfa_state->reg == stack_pointer_rtx) - ix86_cfa_state->reg = hard_frame_pointer_rtx; + if (ix86_cfa_state->reg == stack_pointer_rtx) + ix86_cfa_state->reg = hard_frame_pointer_rtx; + } } if (stack_realign_fp) @@ -8884,7 +8895,7 @@ ix86_expand_prologue (void) a red zone location */ if (!TARGET_64BIT_MS_ABI && TARGET_RED_ZONE && frame.save_regs_using_mov && (! TARGET_STACK_PROBE || allocate < CHECK_STACK_LIMIT)) - ix86_emit_save_regs_using_mov ((frame_pointer_needed + ix86_emit_save_regs_using_mov ((frame_pointer_needed && !be_x64frame && !crtl->stack_realign_needed) ? hard_frame_pointer_rtx : stack_pointer_rtx, @@ -8932,7 +8943,7 @@ ix86_expand_prologue (void) if (eax_live) { - if (frame_pointer_needed) + if (frame_pointer_needed && !be_x64frame) t = plus_constant (hard_frame_pointer_rtx, allocate - frame.to_allocate @@ -8947,7 +8958,7 @@ ix86_expand_prologue (void) && !(!TARGET_64BIT_MS_ABI && TARGET_RED_ZONE && (! TARGET_STACK_PROBE || allocate < CHECK_STACK_LIMIT))) { - if (!frame_pointer_needed + if (!frame_pointer_needed || be_x64frame || !(frame.to_allocate + frame.padding0) || crtl->stack_realign_needed) ix86_emit_save_regs_using_mov (stack_pointer_rtx, @@ -8957,7 +8968,7 @@ ix86_expand_prologue (void) ix86_emit_save_regs_using_mov (hard_frame_pointer_rtx, -frame.nregs * UNITS_PER_WORD); } - if (!frame_pointer_needed + if (!frame_pointer_needed || be_x64frame || !(frame.to_allocate + frame.padding0) || crtl->stack_realign_needed) ix86_emit_save_sse_regs_using_mov (stack_pointer_rtx, @@ -9011,6 +9022,17 @@ ix86_expand_prologue (void) if (crtl->profile && pic_reg_used) emit_insn (gen_prologue_use (pic_offset_table_rtx)); + if (be_x64frame) + { + rtx t; + + insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); + RTX_FRAME_RELATED_P (insn) = 1; + + if (ix86_cfa_state->reg == stack_pointer_rtx) + ix86_cfa_state->reg = hard_frame_pointer_rtx; + } + if (crtl->drap_reg && !crtl->stack_realign_needed) { /* vDRAP is setup but after reload it turns out stack realign @@ -9223,19 +9245,29 @@ ix86_expand_epilogue (int style) HOST_WIDE_INT offset, red_offset; struct machine_cfa_state cfa_state_save = *ix86_cfa_state; bool using_drap; + int be_x64frame = TARGET_64BIT && DEFAULT_ABI == MS_ABI + && frame_pointer_needed; + ix86_finalize_stack_realign_flags (); /* When stack is realigned, SP must be valid. */ - sp_valid = (!frame_pointer_needed + sp_valid = (!frame_pointer_needed || be_x64frame || current_function_sp_is_unchanging || stack_realign_fp); ix86_compute_frame_layout (&frame); + if (be_x64frame) + { + pro_epilogue_adjust_stack (stack_pointer_rtx, + hard_frame_pointer_rtx, + const0_rtx, style, 0); + } + /* See the comment about red zone and frame pointer usage in ix86_expand_prologue. */ - if (frame_pointer_needed && frame.red_zone_size) + if (frame_pointer_needed && (frame.red_zone_size || be_x64frame)) emit_insn (gen_memory_blockage ()); using_drap = crtl->drap_reg && crtl->stack_realign_needed; @@ -9286,7 +9318,8 @@ ix86_expand_epilogue (int style) || (frame_pointer_needed && TARGET_USE_LEAVE && cfun->machine->use_fast_prologue_epilogue && (frame.nregs + frame.nsseregs) == 1) - || crtl->calls_eh_return) + || crtl->calls_eh_return + || be_x64frame) { /* Restore registers. We can use ebp or esp to address the memory locations. If both are available, default to ebp, since offsets @@ -9297,7 +9330,7 @@ ix86_expand_epilogue (int style) If we are realigning stack with bp and sp, regs restore can't be addressed by bp. sp must be used instead. */ - if (!frame_pointer_needed + if (!frame_pointer_needed || be_x64frame || (sp_valid && !(frame.to_allocate + frame.padding0)) || stack_realign_fp) { @@ -9338,7 +9371,7 @@ ix86_expand_epilogue (int style) /* Neither does regparm nested functions. */ gcc_assert (!ix86_static_chain_on_stack); - if (frame_pointer_needed) + if (frame_pointer_needed && !be_x64frame) { tmp = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, sa); tmp = plus_constant (tmp, UNITS_PER_WORD); @@ -9387,6 +9420,16 @@ ix86_expand_epilogue (int style) } } } + else if (be_x64frame) + { + pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (frame.to_allocate + + frame.nregs * UNITS_PER_WORD + + frame.nsseregs * 16 + + frame.padding0), + style, 0); + ix86_emit_restore_reg_using_pop (hard_frame_pointer_rtx, red_offset); + } else if (!frame_pointer_needed) pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (frame.to_allocate @@ -9416,7 +9459,7 @@ ix86_expand_epilogue (int style) won't be able to recover via lea $offset(%bp), %sp, because there is a padding area between bp and sp for realign. "add $to_allocate, %sp" must be used instead. */ - if (!sp_valid) + if (!sp_valid && !be_x64frame) { gcc_assert (frame_pointer_needed); gcc_assert (!stack_realign_fp); @@ -9447,7 +9490,7 @@ ix86_expand_epilogue (int style) + frame.padding0); red_offset -= offset; - if (frame_pointer_needed) + if (frame_pointer_needed && !be_x64frame) { /* Leave results in shorter dependency chains on CPUs that are able to grok it fast. */