diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index fe28d55..084d111 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -460,7 +460,6 @@ static unsigned int sparc_function_arg_boundary (enum machine_mode,
 						 const_tree);
 static int sparc_arg_partial_bytes (cumulative_args_t,
 				    enum machine_mode, tree, bool);
-static void sparc_dwarf_handle_frame_unspec (const char *, rtx, int);
 static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
 static void sparc_file_end (void);
 static bool sparc_frame_pointer_required (void);
@@ -611,9 +610,6 @@ char sparc_hard_reg_printed[8];
 #undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE sparc_preferred_simd_mode
 
-#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
-#define TARGET_DWARF_HANDLE_FRAME_UNSPEC sparc_dwarf_handle_frame_unspec
-
 #ifdef SUBTARGET_INSERT_ATTRIBUTES
 #undef TARGET_INSERT_ATTRIBUTES
 #define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES
@@ -4597,12 +4593,26 @@ emit_save_or_restore_local_in_regs (rtx base, int offset, sorr_act_t action)
 /* Generate a save_register_window insn.  */
 
 static rtx
-gen_save_register_window (rtx increment)
+emit_save_register_window (rtx increment)
 {
-  if (TARGET_ARCH64)
-    return gen_save_register_windowdi (increment);
-  else
-    return gen_save_register_windowsi (increment);
+  rtx insn;
+
+  insn = emit_insn (gen_save_register_window_1 (increment));
+  RTX_FRAME_RELATED_P (insn) = 1;
+
+  /* The return address (%i7) is saved in %o7.  */
+  add_reg_note (insn, REG_CFA_REGISTER,
+		gen_rtx_SET (VOIDmode,
+			     gen_rtx_REG (Pmode, 31),
+			     gen_rtx_REG (Pmode, 15)));
+
+  /* The window save event.  */
+  add_reg_note (insn, REG_CFA_WINDOW_SAVE, const0_rtx);
+
+  /* The CFA is %o6, the hard frame pointer.  */
+  add_reg_note (insn, REG_CFA_DEF_CFA, hard_frame_pointer_rtx);
+
+  return insn;
 }
 
 /* Generate a create_flat_frame_1 insn.  */
@@ -4671,7 +4681,6 @@ sparc_expand_prologue (void)
 {
   HOST_WIDE_INT size;
   rtx insn;
-  int i;
 
   /* Compute a snapshot of current_function_uses_only_leaf_regs.  Relying
      on the final value of the flag means deferring the prologue/epilogue
@@ -4733,10 +4742,10 @@ sparc_expand_prologue (void)
   else
     {
       if (size <= 4096)
-	insn = emit_insn (gen_save_register_window (GEN_INT (-size)));
+	emit_save_register_window (GEN_INT (-size));
       else if (size <= 8192)
 	{
-	  insn = emit_insn (gen_save_register_window (GEN_INT (-4096)));
+	  emit_save_register_window (GEN_INT (-4096));
 	  /* %sp is not the CFA register anymore.  */
 	  emit_insn (gen_stack_pointer_inc (GEN_INT (4096 - size)));
 	}
@@ -4744,12 +4753,8 @@ sparc_expand_prologue (void)
 	{
 	  rtx reg = gen_rtx_REG (Pmode, 1);
 	  emit_move_insn (reg, GEN_INT (-size));
-	  insn = emit_insn (gen_save_register_window (reg));
+	  emit_save_register_window (reg);
 	}
-
-      RTX_FRAME_RELATED_P (insn) = 1;
-      for (i=0; i < XVECLEN (PATTERN (insn), 0); i++)
-        RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, i)) = 1;
     }
 
   if (sparc_leaf_function_p)
@@ -10000,20 +10005,6 @@ get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
   return 0;
 }
 
-/* Handle the TARGET_DWARF_HANDLE_FRAME_UNSPEC hook.
-
-   This is called from dwarf2out.c to emit call frame instructions
-   for frame-related insns containing UNSPECs and UNSPEC_VOLATILEs.  */
-
-static void
-sparc_dwarf_handle_frame_unspec (const char *label,
-				 rtx pattern ATTRIBUTE_UNUSED,
-				 int index ATTRIBUTE_UNUSED)
-{
-  gcc_assert (index == UNSPECV_SAVEW);
-  dwarf2out_window_save (label);
-}
-
 /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
    We need to emit DTP-relative relocations.  */
 
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index acf317d..017b689 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -6276,24 +6276,18 @@
   DONE;
 })
 
-;; The "save register window" insn is modelled as follows so that the DWARF-2
-;; backend automatically emits the required call frame debugging information
-;; while it is parsing it.  Therefore, the pattern should not be modified
-;; without first studying the impact of the changes on the debug info.
-;; [(set (%fp) (%sp))
-;;  (set (%sp) (unspec_volatile [(%sp) (-frame_size)] UNSPECV_SAVEW))
-;;  (set (%i7) (%o7))]
-
-(define_insn "save_register_window<P:mode>"
-  [(set (reg:P 30) (reg:P 14))
-   (set (reg:P 14) (unspec_volatile:P [(reg:P 14)
-				       (match_operand:P 0 "arith_operand" "rI")] UNSPECV_SAVEW))
-   (set (reg:P 31) (reg:P 15))]
+;; The "save register window" insn is modelled as follows.  The dwarf2
+;; information is manually added in emit_save_register_window in sparc.c.
+
+(define_insn "save_register_window_1"
+  [(unspec_volatile
+	[(match_operand 0 "arith_operand" "rI")]
+	UNSPECV_SAVEW)]
   "!TARGET_FLAT"
   "save\t%%sp, %0, %%sp"
   [(set_attr "type" "savew")])
 
-;; Likewise for the "create flat frame" insns.  We need to use special insns
+;; For the "create flat frame" insns, we need to use special insns
 ;; because %fp cannot be clobbered until after the frame is established (so
 ;; that it contains the live register window save area) and %i7 changed with
 ;; a simple move as it is a fixed register and the move would be eliminated.
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 71ba002..2f4cd04 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -1232,22 +1232,6 @@ reg_save (const char *label, unsigned int reg, unsigned int sreg, HOST_WIDE_INT
   add_fde_cfi (label, cfi);
 }
 
-/* Add the CFI for saving a register window.  LABEL is passed to reg_save.
-   This CFI tells the unwinder that it needs to restore the window registers
-   from the previous frame's window save area.
-
-   ??? Perhaps we should note in the CIE where windows are saved (instead of
-   assuming 0(cfa)) and what registers are in the window.  */
-
-void
-dwarf2out_window_save (const char *label)
-{
-  dw_cfi_ref cfi = new_cfi ();
-
-  cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
-  add_fde_cfi (label, cfi);
-}
-
 Entry point for saving a register to the stack.  REG is the GCC register
    number.  LABEL and OFFSET are passed to reg_save.  */
 
@@ -2104,6 +2088,19 @@ dwarf2out_frame_debug_cfa_restore (rtx reg, const char *label)
   add_fde_cfi (label, cfi);
 }
 
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_WINDOW_SAVE.
+   ??? Perhaps we should note in the CIE where windows are saved (instead of
+   assuming 0(cfa)) and what registers are in the window.  */
+
+static void
+dwarf2out_frame_debug_cfa_window_save (const char *label)
+{
+  dw_cfi_ref cfi = new_cfi ();
+
+  cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
+  add_fde_cfi (label, cfi);
+}
+
 /* Record call frame debugging information for an expression EXPR,
    which either sets SP or FP (adjusting how we calculate the frame
    address) or saves a register to the stack or another register.
@@ -2900,6 +2897,11 @@ dwarf2out_frame_debug (rtx insn, bool after_p)
 	handled_one = true;
 	break;
 
+      case REG_CFA_WINDOW_SAVE:
+	dwarf2out_frame_debug_cfa_window_save (label);
+	handled_one = true;
+	break;
+
       default:
 	break;
       }
diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
index 329cd67..9924355 100644
--- a/gcc/reg-notes.def
+++ b/gcc/reg-notes.def
@@ -160,6 +160,11 @@ REG_NOTE (CFA_RESTORE)
    to the argument, if it is a MEM, it is ignored.  */
 REG_NOTE (CFA_SET_VDRAP)
 
+/* Attached to insn that are RTX_FRAME_RELATED_P, indicating a window
+   save operation, i.e. will result in a DW_CFA_GNU_window_save.
+   The argument is ignored.  */
+REG_NOTE (CFA_WINDOW_SAVE)
+
 /* Indicates that REG holds the exception context for the function.
    This context is shared by inline functions, so the code to acquire
    the real exception context is delayed until after inlining.  */
diff --git a/gcc/tree.h b/gcc/tree.h
index f55574d..d066b27 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5564,10 +5564,6 @@ extern char *dwarf2out_cfi_label (bool);
 
 extern void dwarf2out_def_cfa (const char *, unsigned, HOST_WIDE_INT);
 
-/* Add the CFI for saving a register window.  */
-
-extern void dwarf2out_window_save (const char *);
-
 /* Entry point for saving a register to the stack.  */
 
 extern void dwarf2out_reg_save (const char *, unsigned, HOST_WIDE_INT);
