diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b6d3eb9f2e55508019d016440d1802ab7031ff87..6b66ea64c6956aee5bea251554c5642e85a1edec 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
 2001-03-28  Richard Henderson  <rth@redhat.com>
 
+	* config/sparc/sparc.c (eligible_for_epilogue_delay): False if
+	current_function_calls_eh_return.
+	(output_function_epilogue): Handle eh_return.
+	* config/sparc/sparc.h (DOESNT_NEED_UNWINDER): Remove.
+	(EH_RETURN_DATA_REGNO): New.
+	(EH_RETURN_STACKADJ_RTX): New.
+	(EH_RETURN_HANDLER_RTX): New.
+	* config/sparc/sparc.md (call/short branch peepholes): Check
+	can_throw_internal instead of in_same_eh_region.
+
 	* config/rs6000/rs6000.c (rs6000_stack_info): Allocate space
 	for eh_return data registers.
 	(rs6000_emit_prologue): Save eh_return data registers.
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index e4850271c6c04b670e90b301eb68030e0ffb0874..9cb4c5ccf09f51804c1b3c3adb9da69fe37d387b 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -2377,6 +2377,11 @@ eligible_for_epilogue_delay (trial, slot)
   if (num_gfregs)
     return 0;
 
+  /* If the function uses __builtin_eh_return, the eh_return machinery
+     occupies the delay slot.  */
+  if (current_function_calls_eh_return)
+    return 0;
+
   /* In the case of a true leaf function, anything can go into the delay slot.
      A delay slot only exists however if the frame size is zero, otherwise
      we will put an insn to adjust the stack after the return.  */
@@ -3594,8 +3599,17 @@ output_function_epilogue (file, size, leaf_function)
 
       if (! leaf_function)
 	{
+	  if (current_function_calls_eh_return)
+	    {
+	      if (current_function_epilogue_delay_list)
+		abort ();
+	      if (SKIP_CALLERS_UNIMP_P)
+		abort ();
+
+	      fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
+	    }
 	  /* If we wound up with things in our delay slot, flush them here.  */
-	  if (current_function_epilogue_delay_list)
+	  else if (current_function_epilogue_delay_list)
 	    {
 	      rtx delay = PATTERN (XEXP (current_function_epilogue_delay_list, 0));
 
@@ -3635,6 +3649,8 @@ output_function_epilogue (file, size, leaf_function)
 	  else
 	    fprintf (file, "\t%s\n\trestore\n", ret);
 	}
+      else if (current_function_calls_eh_return)
+	abort ();
       /* All of the following cases are for leaf functions.  */
       else if (current_function_epilogue_delay_list)
 	{
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index cc6b014900f6b4bb25b24cc186d6be7d6a141b7e..9e49eadb02daa6031c47ed24d48878c0d1f4bd2f 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -2235,7 +2235,10 @@ LFLGRET"ID":\n\
    bias if present.  */
 #define INCOMING_FRAME_SP_OFFSET SPARC_STACK_BIAS
 
-#define DOESNT_NEED_UNWINDER (! TARGET_FLAT)
+/* Describe how we implement __builtin_eh_return.  */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 24 : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX	gen_rtx_REG (Pmode, 1)	/* %g1 */
+#define EH_RETURN_HANDLER_RTX	gen_rtx_REG (Pmode, 31)	/* %i7 */
 
 /* Addressing modes, and classification of registers for them.  */
 
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index abfad793115c782c727eb26425e7f7c991aa4225..8167af887ecd0029e9cb44b4320f24c4ff4a195d 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -9453,8 +9453,7 @@
 	      (clobber (reg:SI 15))])
    (set (pc) (label_ref (match_operand 3 "" "")))]
   "short_branch (INSN_UID (insn), INSN_UID (operands[3]))
-   && in_same_eh_region (insn, operands[3])
-   && in_same_eh_region (insn, ins1)"
+   && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (insn))"
   "call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
 
 (define_peephole
@@ -9463,8 +9462,7 @@
 	      (clobber (reg:SI 15))])
    (set (pc) (label_ref (match_operand 2 "" "")))]
   "short_branch (INSN_UID (insn), INSN_UID (operands[2]))
-   && in_same_eh_region (insn, operands[2])
-   && in_same_eh_region (insn, ins1)"
+   && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (insn))"
   "call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
 
 (define_peephole
@@ -9475,8 +9473,7 @@
    (set (pc) (label_ref (match_operand 3 "" "")))]
   "TARGET_ARCH64
    && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
-   && in_same_eh_region (insn, operands[3])
-   && in_same_eh_region (insn, ins1)"
+   && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (insn))"
   "call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
 
 (define_peephole
@@ -9486,8 +9483,7 @@
    (set (pc) (label_ref (match_operand 2 "" "")))]
   "TARGET_ARCH64
    && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
-   && in_same_eh_region (insn, operands[2])
-   && in_same_eh_region (insn, ins1)"
+   && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (insn))"
   "call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
 
 (define_expand "prologue"