Index: gcc/gcc/config/i386/i386.c
===================================================================
--- gcc.orig/gcc/config/i386/i386.c	2010-07-18 12:25:33.137270400 +0200
+++ gcc/gcc/config/i386/i386.c	2010-07-18 12:25:34.287336200 +0200
@@ -3691,13 +3691,41 @@ override_options (bool main_args_p)
 #if defined(MCOUNT_NAME) && defined(MCOUNT_NAME_BEFORE_PROLOGUE)
     only_default = 0;
 #endif
+    if (!TARGET_64BIT && flag_framex64)
+      {
+	sorry ("-mframe-x64 isn't supported for 32-bit");
+
+	flag_framex64 = 0;
+      }
+    if (only_default && default_profile_top_flag == 0 && profile_flag
+	&& flag_framex64)
+      {
+	sorry ("-mframe-x64 option requires unsupported -mfentry");
+	flag_framex64 = 0;
+      }
+    else if(!only_default && flag_framex64)
+      {
+	default_profile_top_flag = 1;
+      }
 
     if (flag_fentry == -1)
       flag_fentry = default_profile_top_flag;
+
+    if (flag_framex64 && flag_fentry == 0 && profile_flag)
+      {
+	if (!only_default)
+	  sorry ("-mframe-x64 together with -pg requires -mfentry");
+	else
+	  sorry ("-mframe-x64 together with -pg isn't supported by this"
+	         " target");
+	flag_framex64 = 0;
+      }
+
     if (flag_fentry != 0 && force_default_profile_top_flag)
       {
 	sorry ("-mfentry isn't support for x86 in combination with -fpic");
 	flag_fentry = 0;
+	flag_framex64 = 0;
       }
     else if (flag_fentry != default_profile_top_flag && only_default)
       {
@@ -8473,6 +8501,12 @@ ix86_compute_frame_layout (struct ix86_f
   /* We've reached end of stack frame.  */
   frame->stack_pointer_offset = offset;
 
+  /* Adjust hard_frame_pointer so that it points
+     to end of frame.  */
+  if (frame_pointer_needed && flag_framex64)
+      frame->hard_frame_pointer_offset = offset;
+
+
   /* Size prologue needs to allocate.  */
   frame->to_allocate =
     (size + frame->padding1 + frame->padding2
@@ -9217,6 +9251,7 @@ ix86_expand_prologue (void)
   struct ix86_frame frame;
   HOST_WIDE_INT allocate;
   int gen_frame_pointer = frame_pointer_needed;
+  int be_x64frame = frame_pointer_needed && flag_framex64;
 
   ix86_finalize_stack_realign_flags ();
 
@@ -9348,11 +9383,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)
@@ -9407,7 +9445,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,
@@ -9451,7 +9489,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
@@ -9466,7 +9504,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,
@@ -9476,7 +9514,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,
@@ -9530,6 +9568,15 @@ ix86_expand_prologue (void)
   if (crtl->profile && !flag_fentry && pic_reg_used)
     emit_insn (gen_prologue_use (pic_offset_table_rtx));
 
+  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 (crtl->drap_reg && !crtl->stack_realign_needed)
     {
       /* vDRAP is setup but after reload it turns out stack realign
@@ -9742,19 +9789,28 @@ 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 = frame_pointer_needed && flag_framex64;
+
 
   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;
@@ -9805,7 +9861,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
@@ -9816,7 +9873,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)
 	{
@@ -9857,7 +9914,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);
@@ -9906,6 +9963,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
@@ -9935,7 +10002,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);
@@ -9966,7 +10033,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.  */
Index: gcc/gcc/config/i386/i386.opt
===================================================================
--- gcc.orig/gcc/config/i386/i386.opt	2010-07-18 12:25:33.140270600 +0200
+++ gcc/gcc/config/i386/i386.opt	2010-07-18 12:25:34.293336600 +0200
@@ -379,3 +379,8 @@ Support F16C built-in functions and code
 mfentry
 Target Report Var(flag_fentry) Init(-1)
 Emit profiling counter call at function entry before prologue.
+
+mframe-x64
+Target Report Var(flag_framex64) Init(0)
+Set the frame-pointer to the stack location at the end of prologue for 64-bit.
+
Index: gcc/gcc/doc/invoke.texi
===================================================================
--- gcc.orig/gcc/doc/invoke.texi	2010-07-18 12:25:33.149271100 +0200
+++ gcc/gcc/doc/invoke.texi	2010-07-18 12:25:34.320338100 +0200
@@ -601,7 +601,7 @@ Objective-C and Objective-C++ Dialects}.
 -momit-leaf-frame-pointer  -mno-red-zone -mno-tls-direct-seg-refs @gol
 -mcmodel=@var{code-model} -mabi=@var{name} @gol
 -m32  -m64 -mlarge-data-threshold=@var{num} @gol
--msse2avx -mfentry}
+-msse2avx -mfentry -mframe-x64}
 
 @emph{IA-64 Options}
 @gccoptlist{-mbig-endian  -mlittle-endian  -mgnu-as  -mgnu-ld  -mno-pic @gol
@@ -12474,6 +12474,14 @@ If profiling is active @option{-pg} put
 counter call before prologue.
 Note: On x86 architectures the attribute @code{ms_hook_prologue}
 isn't possible at the moment for @option{-mfentry} and @option{-pg}.
+
+@item -mframe-x64
+@itemx -mno-frame-x64
+@opindex mframe-x64
+Specifies that the frame-pointer register points to the
+stack-pointer at the end of prologue. For profiling this
+option requires that @option{-mfentry} is active, too.
+Note: On x86 architectures this option is disallowed.
 @end table
 
 These @samp{-m} switches are supported in addition to the above
