This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH/RFA] SH: DWARF2 exception handling


Joern Rennecke <joern.rennecke@superh.com> wrote:
> One interesting detail is that the set of sh_media_register_for_return
> can become dead if we don't do an ordinary return.  But that should be
> all right, since we already add a REG_MAYBE_DEAD note to the instruction
> that sets sh_media_register_for_return.

I see. I didn't take care of it.

Here is a revised (Take 3) patch and ChangeLog entries. Is it OK?

Regards,
	kaz
--
2002-11-19  Kaz Kojima  <kkojima@gcc.gnu.org>

	* config.gcc (sh*-*-linux*): Add t-slibgcc-elf-ver and t-linux
	to tmake_file. Remove setting gas and gnu_ld here.
	* config/sh/libgcc-glibc.ver: New file.
	* config/sh/t-linux (EXTRA_MULTILIB_PARTS): Add crtbeginT.o.
	(SHLIB_MAPFILES): New.
	* config/sh/linux.h (MD_EXEC_PREFIX): Undefine.
	(MD_STARTFILE_PREFIX): Likewise.
	(HANDLE_PRAGMA_PACK_PACK_PUSH_POP): Define.
	(DWARF2_UNWIND_INFO): Redefine.
	(ASM_PREFERRED_EH_DATA_FORMAT): Define.
	(LINK_EH_SPEC): Redefine.
	(MD_FALLBACK_FRAME_STATE_FOR): Define except for SH-media.
	(SH_FALLBACK_FRAME_FLOAT_STATE): Define.
	(SH_DWARF_FRAME_GP0, SH_DWARF_FRAME_FP0, SH_DWARF_FRAME_XD0,
	SH_DWARF_FRAME_BT0, SH_DWARF_FRAME_PR, SH_DWARF_FRAME_PR_MEDIA,
	SH_DWARF_FRAME_GBR, SH_DWARF_FRAME_MACH, SH_DWARF_FRAME_MACL,
	SH_DWARF_FRAME_PC, SH_DWARF_FRAME_SR, SH_DWARF_FRAME_FPUL,
	SH_DWARF_FRAME_FPSCR): Likewise.
	* config/sh/sh-protos.h (sh_set_return_address): Declare.
	* config/sh/sh.c (calc_live_regs): Count EH_RETURN_DATA_REGNO
	registers if the current function calls EH return.
	(sh_expand_epilogue): Handle EH stack adjustments.
	(sh_set_return_address): New function.
	* config/sh/sh.h (SH_DBX_REGISTER_NUMBER): Handle PR_MEDIA_REG.
	Don't abort even if the number is mapped to -1.
	(EH_RETURN_DATA_REGNO): Define.
	(EH_RETURN_STACKADJ_RTX): Define.
	* config/sh/sh.md (UNSPEC_EH_RETURN): New.
	(eh_return): New pattern.
	(eh_set_ra_di, eh_set_ra_si): Likewise.
	Add splitter to perform EH return after reload.

diff -u3prN ORIG/gccbib/gcc/config.gcc LOCAL/gccbib/gcc/config.gcc
--- ORIG/gccbib/gcc/config.gcc	Mon Nov 18 09:15:05 2002
+++ LOCAL/gccbib/gcc/config.gcc	Tue Nov 19 08:27:34 2002
@@ -2180,7 +2180,7 @@ sh-*-rtems*)
 	fi
 	;;
 sh-*-linux* | sh[2346lbe]*-*-linux*)
-	tmake_file="sh/t-sh sh/t-elf sh/t-linux"
+	tmake_file="sh/t-sh sh/t-elf t-slibgcc-elf-ver t-linux sh/t-linux"
 	case $machine in
 	sh*be-*-* | sh*eb-*-*) ;;
 	*)
@@ -2189,7 +2189,6 @@ sh-*-linux* | sh[2346lbe]*-*-linux*)
 		;;
 	esac
 	tm_file="${tm_file} dbxelf.h elfos.h svr4.h sh/elf.h sh/linux.h"
-	gas=yes gnu_ld=yes
 	case $machine in
 	sh64*)
 		tmake_file="${tmake_file} sh/t-sh64"
diff -u3prN ORIG/gccbib/gcc/config/sh/libgcc-glibc.ver LOCAL/gccbib/gcc/config/sh/libgcc-glibc.ver
--- ORIG/gccbib/gcc/config/sh/libgcc-glibc.ver	Thu Jan  1 09:00:00 1970
+++ LOCAL/gccbib/gcc/config/sh/libgcc-glibc.ver	Tue Nov 19 08:27:34 2002
@@ -0,0 +1,21 @@
+# In order to work around the very problems that force us to now generally
+# create a libgcc.so, glibc reexported a number of routines from libgcc.a.
+# By now choosing the same version tags for these specific routines, we
+# maintain enough binary compatibility to allow future versions of glibc
+# to defer implementation of these routines to libgcc.so via DT_AUXILIARY.
+
+# Note that we cannot use the default libgcc-glibc.ver file on sh,
+# because GLIBC_2.0 does not exist on this architecture, as the first 
+# ever glibc release on the platform was GLIBC_2.2.
+
+%inherit GCC_3.0 GLIBC_2.2
+GLIBC_2.2 {
+  __register_frame
+  __register_frame_table
+  __deregister_frame
+  __register_frame_info
+  __deregister_frame_info
+  __frame_state_for
+  __register_frame_info_table
+}
+
diff -u3prN ORIG/gccbib/gcc/config/sh/t-linux LOCAL/gccbib/gcc/config/sh/t-linux
--- ORIG/gccbib/gcc/config/sh/t-linux	Wed Jun 19 04:56:53 2002
+++ LOCAL/gccbib/gcc/config/sh/t-linux	Tue Nov 19 08:27:34 2002
@@ -8,4 +8,8 @@
 MULTILIB_MATCHES = 
 MULTILIB_EXCEPTIONS=
 
-EXTRA_MULTILIB_PARTS= crtbegin.o crtend.o crtbeginS.o crtendS.o
+EXTRA_MULTILIB_PARTS= crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
+
+# Override t-slibgcc-elf-ver to export some libgcc symbols with
+# the symbol versions that glibc used.
+SHLIB_MAPFILES =  $(srcdir)/libgcc-std.ver $(srcdir)/config/sh/libgcc-glibc.ver
diff -u3prN ORIG/gccbib/gcc/config/sh/linux.h LOCAL/gccbib/gcc/config/sh/linux.h
--- ORIG/gccbib/gcc/config/sh/linux.h	Sun Oct 20 10:03:51 2002
+++ LOCAL/gccbib/gcc/config/sh/linux.h	Tue Nov 19 08:27:34 2002
@@ -23,6 +23,22 @@ Boston, MA 02111-1307, USA.  */
 #undef TARGET_VERSION
 #define TARGET_VERSION  fputs (" (SH GNU/Linux with ELF)", stderr);
 
+/* We're not SYSVR4, not having /usr/ccs */
+#undef MD_EXEC_PREFIX
+#undef MD_STARTFILE_PREFIX
+
+/* This was defined in linux.h.  Define it here also. */
+#define HANDLE_PRAGMA_PACK_PUSH_POP
+
+/* Enable DWARF 2 exceptions.  */
+#undef DWARF2_UNWIND_INFO
+#define DWARF2_UNWIND_INFO 1
+
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL)                      \
+  (flag_pic                                                             \
+    ? ((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4 \
+   : DW_EH_PE_absptr)
+
 #undef SUBTARGET_CPP_SPEC
 #define SUBTARGET_CPP_SPEC "\
    %{posix:-D_POSIX_SOURCE} \
@@ -59,6 +75,11 @@ do { \
    %{!shared: %{pthread:-lthread} \
      %{profile:-lc_p} %{!profile: -lc}}"
 
+#if defined(HAVE_LD_EH_FRAME_HDR)
+#undef LINK_EH_SPEC
+#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
+#endif
+
 #undef STARTFILE_SPEC
 #define STARTFILE_SPEC \
   "%{!shared: \
@@ -66,3 +87,146 @@ do { \
 		       %{!p:%{profile:gcrt1.o%s} \
 			 %{!profile:crt1.o%s}}}} \
    crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
+
+/* Do code reading to identify a signal frame, and set the frame
+   state data appropriately.  See unwind-dw2.c for the structs.  */
+
+#ifdef IN_LIBGCC2
+#include <signal.h>
+#include <sys/ucontext.h>
+#include "insn-constants.h"
+
+# if defined (__SH5__)
+#define SH_DWARF_FRAME_GP0	0
+#define SH_DWARF_FRAME_FP0	(__SH5__ == 32 ? 245 : 77)
+#define SH_DWARF_FRAME_XD0	289
+#define SH_DWARF_FRAME_BT0	68
+#define SH_DWARF_FRAME_PR	241
+#define SH_DWARF_FRAME_PR_MEDIA	18
+#define SH_DWARF_FRAME_GBR	238
+#define SH_DWARF_FRAME_MACH	239
+#define SH_DWARF_FRAME_MACL	240
+#define SH_DWARF_FRAME_PC	64
+#define SH_DWARF_FRAME_SR	65
+#define SH_DWARF_FRAME_FPUL	244
+#define SH_DWARF_FRAME_FPSCR	243
+#else
+#define SH_DWARF_FRAME_GP0	0
+#define SH_DWARF_FRAME_FP0	25
+#define SH_DWARF_FRAME_XD0	87
+#define SH_DWARF_FRAME_PR	17
+#define SH_DWARF_FRAME_GBR	19
+#define SH_DWARF_FRAME_MACH	20
+#define SH_DWARF_FRAME_MACL	21
+#define SH_DWARF_FRAME_PC	16
+#define SH_DWARF_FRAME_SR	22
+#define SH_DWARF_FRAME_FPUL	23
+#define SH_DWARF_FRAME_FPSCR	24
+#endif /* defined (__SH5__) */
+
+#if defined (__SH5__) && __SH5__ != 32
+/* MD_FALLBACK_FRAME_STATE_FOR is not yet defiened for SHMEDIA.  */
+#else /* defined (__SH5__) && __SH5__ != 32 */
+
+#if defined (__SH3E__) || defined (__SH4__) || defined (__SH5__)
+#define SH_FALLBACK_FRAME_FLOAT_STATE(SC, FS, CFA)			\
+  do {									\
+    int i_, r_;								\
+									\
+    r_ = SH_DWARF_FRAME_FP0;						\
+    for (i_ = 0; i_ < 16; i_++)						\
+      {		    							\
+	(FS)->regs.reg[r_+i_].how = REG_SAVED_OFFSET;			\
+	(FS)->regs.reg[r_+i_].loc.offset 				\
+	  = (long)&((SC)->sc_fpregs[i_]) - (CFA);			\
+      }									\
+									\
+    r_ = SH_DWARF_FRAME_XD0	;					\
+    for (i_ = 0; i_ < 8; i_++)						\
+      {		    							\
+	(FS)->regs.reg[i_].how = REG_SAVED_OFFSET;			\
+	(FS)->regs.reg[i_].loc.offset	 				\
+	  = (long)&((SC)->sc_xfpregs[2*i_]) - (CFA);			\
+      }									\
+									\
+    (FS)->regs.reg[SH_DWARF_FRAME_FPUL].how = REG_SAVED_OFFSET;		\
+    (FS)->regs.reg[SH_DWARF_FRAME_FPUL].loc.offset			\
+      = (long)&((SC)->sc_fpul) - (CFA);					\
+    (FS)->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET;	\
+    (FS)->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset			\
+      = (long)&((SC)->sc_fpscr) - (CFA);				\
+  } while (0)
+
+#else
+#define SH_FALLBACK_FRAME_FLOAT_STATE(SC, FS, CFA)
+#endif
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)		\
+  do {									\
+    unsigned char *pc_ = (CONTEXT)->ra;					\
+    struct sigcontext *sc_;						\
+    long new_cfa_;							\
+    int i_;								\
+									\
+    /* mov.w 1f,r3; trapa #0x10; 1: .short 0x77  (sigreturn)  */	\
+    /* mov.w 1f,r3; trapa #0x10; 1: .short 0xad  (rt_sigreturn)  */	\
+    if ((*(unsigned short *) (pc_+0)  == 0x9300)			\
+	&& (*(unsigned short *) (pc_+2)  == 0xc310)			\
+	&& (*(unsigned short *) (pc_+4)  == 0x0077))			\
+      sc_ = (CONTEXT)->cfa;						\
+    else if ((*(unsigned short *) (pc_+0) == 0x9300)			\
+	&& (*(unsigned short *) (pc_+2)  == 0xc310)			\
+	&& (*(unsigned short *) (pc_+4)  == 0x00ad))			\
+      {									\
+	struct rt_sigframe {						\
+	  struct siginfo info;						\
+	  struct ucontext uc;						\
+	} *rt_ = (CONTEXT)->cfa;					\
+	sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext;		\
+      }									\
+    else								\
+      break;								\
+    									\
+    new_cfa_ = sc_->sc_regs[15];					\
+    (FS)->cfa_how = CFA_REG_OFFSET;					\
+    (FS)->cfa_reg = 15;							\
+    (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa;		\
+    									\
+    for (i_ = 0; i_ < 15; i_++)						\
+      {		    							\
+	(FS)->regs.reg[i_].how = REG_SAVED_OFFSET;			\
+	(FS)->regs.reg[i_].loc.offset	 				\
+	  = (long)&(sc_->sc_regs[i_]) - new_cfa_;			\
+      }									\
+									\
+    (FS)->regs.reg[SH_DWARF_FRAME_PR].how = REG_SAVED_OFFSET;		\
+    (FS)->regs.reg[SH_DWARF_FRAME_PR].loc.offset			\
+      = (long)&(sc_->sc_pr) - new_cfa_;					\
+    (FS)->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET;		\
+    (FS)->regs.reg[SH_DWARF_FRAME_SR].loc.offset			\
+      = (long)&(sc_->sc_sr) - new_cfa_;					\
+    (FS)->regs.reg[SH_DWARF_FRAME_GBR].how = REG_SAVED_OFFSET;		\
+    (FS)->regs.reg[SH_DWARF_FRAME_GBR].loc.offset			\
+      = (long)&(sc_->sc_gbr) - new_cfa_;				\
+    (FS)->regs.reg[SH_DWARF_FRAME_MACH].how = REG_SAVED_OFFSET;		\
+    (FS)->regs.reg[SH_DWARF_FRAME_MACH].loc.offset			\
+      = (long)&(sc_->sc_mach) - new_cfa_;				\
+    (FS)->regs.reg[SH_DWARF_FRAME_MACL].how = REG_SAVED_OFFSET;		\
+    (FS)->regs.reg[SH_DWARF_FRAME_MACL].loc.offset			\
+      = (long)&(sc_->sc_macl) - new_cfa_;				\
+									\
+     SH_FALLBACK_FRAME_FLOAT_STATE(sc_, (FS), new_cfa_);		\
+									\
+    /* The unwinder expects the PC to point to the following insn,	\
+       whereas the kernel returns the address of the actual		\
+       faulting insn.  */						\
+    sc_->sc_pc += 2;	  						\
+    (FS)->regs.reg[SH_DWARF_FRAME_PC].how = REG_SAVED_OFFSET;		\
+    (FS)->regs.reg[SH_DWARF_FRAME_PC].loc.offset			\
+      = (long)&(sc_->sc_pc) - new_cfa_;					\
+    (FS)->retaddr_column = SH_DWARF_FRAME_PC;				\
+    goto SUCCESS;							\
+  } while (0)
+
+#endif /* defined (__SH5__) && __SH5__ != 32 */
+#endif /* IN_LIBGCC2 */
diff -u3prN ORIG/gccbib/gcc/config/sh/sh-protos.h LOCAL/gccbib/gcc/config/sh/sh-protos.h
--- ORIG/gccbib/gcc/config/sh/sh-protos.h	Wed Nov  6 04:12:15 2002
+++ LOCAL/gccbib/gcc/config/sh/sh-protos.h	Tue Nov 19 08:27:34 2002
@@ -120,6 +120,7 @@ extern int sh_media_register_for_return 
 extern void sh_expand_prologue PARAMS ((void));
 extern void sh_expand_epilogue PARAMS ((void));
 extern int sh_need_epilogue PARAMS ((void));
+extern void sh_set_return_address PARAMS ((rtx, rtx));
 extern int initial_elimination_offset PARAMS ((int, int));
 extern int fldi_ok PARAMS ((void));
 extern int sh_pr_n_sets PARAMS ((void));
diff -u3prN ORIG/gccbib/gcc/config/sh/sh.c LOCAL/gccbib/gcc/config/sh/sh.c
--- ORIG/gccbib/gcc/config/sh/sh.c	Wed Nov  6 04:12:15 2002
+++ LOCAL/gccbib/gcc/config/sh/sh.c	Tue Nov 19 08:27:34 2002
@@ -4446,7 +4446,12 @@ calc_live_regs (count_ptr, live_regs_mas
 	     && reg != RETURN_ADDRESS_POINTER_REGNUM
 	     && reg != T_REG && reg != GBR_REG)
 	  : (/* Only push those regs which are used and need to be saved.  */
-	     regs_ever_live[reg] && ! call_used_regs[reg]))
+	     (regs_ever_live[reg] && ! call_used_regs[reg])
+	     || (current_function_calls_eh_return
+		 && (reg == EH_RETURN_DATA_REGNO (0)
+		     || reg == EH_RETURN_DATA_REGNO (1)
+		     || reg == EH_RETURN_DATA_REGNO (2)
+		     || reg == EH_RETURN_DATA_REGNO (3)))))
 	{
 	  live_regs_mask[reg / 32] |= 1 << (reg % 32);
 	  count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
@@ -5042,6 +5047,10 @@ sh_expand_epilogue ()
 		       + current_function_args_info.stack_regs * 8,
 		       stack_pointer_rtx, 7, emit_insn);
 
+  if (current_function_calls_eh_return)
+    emit_insn (GEN_ADD3 (stack_pointer_rtx, stack_pointer_rtx,
+			 EH_RETURN_STACKADJ_RTX));
+
   /* Switch back to the normal stack if necessary.  */
   if (sp_switch)
     emit_insn (gen_sp_switch_2 ());
@@ -5070,6 +5079,105 @@ sh_need_epilogue ()
       sh_need_epilogue_known = (epilogue == NULL ? -1 : 1);
     }
   return sh_need_epilogue_known > 0;
+}
+
+/* Emit code to change the current function's return address to RA.
+   TEMP is available as a scratch register, if needed.  */
+
+void
+sh_set_return_address (ra, tmp)
+     rtx ra, tmp;
+{
+  HOST_WIDE_INT live_regs_mask[(FIRST_PSEUDO_REGISTER + 31) / 32];
+  int d;
+  int d_rounding = 0;
+  int pr_reg = TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG;
+  int pr_offset;
+
+  calc_live_regs (&d, live_regs_mask);
+
+  /* If pr_reg isn't life, we can set it (or the register given in
+     sh_media_register_for_return) directly.  */
+  if ((live_regs_mask[pr_reg / 32] & (1 << (pr_reg % 32))) == 0)
+    {
+      rtx rr;
+
+      if (TARGET_SHMEDIA)
+	{
+	  int rr_regno = sh_media_register_for_return ();
+
+	  if (rr_regno < 0)
+	    rr_regno = pr_reg;
+
+	  rr = gen_rtx_REG (DImode, rr_regno);
+	}
+      else
+	rr = gen_rtx_REG (SImode, pr_reg);
+
+      emit_insn (GEN_MOV (rr, ra));
+      /* Tell flow the register for return isn't dead.  */
+      emit_insn (gen_rtx_USE (VOIDmode, rr));
+      return;
+    }
+
+  if (TARGET_SH5)
+    {
+      int i;
+      int offset;
+      int align;
+      
+      if (d % (STACK_BOUNDARY / BITS_PER_UNIT))
+	d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
+		      - d % (STACK_BOUNDARY / BITS_PER_UNIT));
+
+      offset = 0;
+
+      /* We loop twice: first, we save 8-byte aligned registers in the
+	 higher addresses, that are known to be aligned.  Then, we
+	 proceed to saving 32-bit registers that don't need 8-byte
+	 alignment.  */
+      for (align = 0; align <= 1; align++)
+	for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	  if (live_regs_mask[i/32] & (1 << (i % 32)))
+	    {
+	      enum machine_mode mode = REGISTER_NATURAL_MODE (i);
+
+	      if (mode == SFmode && (i % 2) == 0
+		  && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
+		  && (live_regs_mask[(i ^ 1) / 32] & (1 << ((i ^ 1) % 32))))
+		{
+		  mode = DFmode;
+		  i++;
+		}
+
+	      /* If we're doing the aligned pass and this is not aligned,
+		 or we're doing the unaligned pass and this is aligned,
+		 skip it.  */
+	      if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT)
+		   == 0) != align)
+		continue;
+
+	      if (i == pr_reg)
+		goto found;
+
+	      offset += GET_MODE_SIZE (mode);
+	    }
+
+      /* We can't find pr register.  */
+      abort ();
+
+    found:
+      pr_offset = (rounded_frame_size (d) - d_rounding + offset
+		   + SHMEDIA_REGS_STACK_ADJUST ());
+    }
+  else
+    pr_offset = rounded_frame_size (d) - d_rounding;
+
+  emit_insn (GEN_MOV (tmp, GEN_INT (pr_offset)));
+  emit_insn (GEN_ADD3 (tmp, tmp, frame_pointer_rtx));
+
+  tmp = gen_rtx_MEM (Pmode, tmp);
+  emit_insn (GEN_MOV (tmp, ra));
 }
 
 /* Clear variables at function end.  */
diff -u3prN ORIG/gccbib/gcc/config/sh/sh.h LOCAL/gccbib/gcc/config/sh/sh.h
--- ORIG/gccbib/gcc/config/sh/sh.h	Mon Nov 18 09:15:35 2002
+++ LOCAL/gccbib/gcc/config/sh/sh.h	Tue Nov 19 08:29:18 2002
@@ -2939,6 +2939,8 @@ while (0)
    to match gdb.  */
 /* svr4.h undefines this macro, yet we really want to use the same numbers
    for coff as for elf, so we go via another macro: SH_DBX_REGISTER_NUMBER.  */
+/* expand_builtin_init_dwarf_reg_sizes uses this to test if a
+   register exists, so we should return -1 for invalid register numbers.  */
 #define DBX_REGISTER_NUMBER(REGNO) SH_DBX_REGISTER_NUMBER (REGNO)
 
 #define SH_DBX_REGISTER_NUMBER(REGNO) \
@@ -2953,6 +2955,8 @@ while (0)
    ? ((REGNO) - FIRST_TARGET_REG + 68) \
    : (REGNO) == PR_REG \
    ? (TARGET_SH5 ? 241 : 17) \
+   : (REGNO) == PR_MEDIA_REG \
+   ? (TARGET_SH5 ? 18 : -1) \
    : (REGNO) == T_REG \
    ? (TARGET_SH5 ? 242 : 18) \
    : (REGNO) == GBR_REG \
@@ -2963,7 +2967,7 @@ while (0)
    ? (TARGET_SH5 ? 240 : 21) \
    : (REGNO) == FPUL_REG \
    ? (TARGET_SH5 ? 244 : 23) \
-   : (abort(), -1))
+   : -1)
 
 /* This is how to output a reference to a user-level label named NAME.  */
 #define ASM_OUTPUT_LABELREF(FILE, NAME)			\
@@ -3304,6 +3308,11 @@ extern int rtx_equal_function_value_matt
 
 #define DWARF_FRAME_RETURN_COLUMN \
   (TARGET_SH5 ? DWARF_FRAME_REGNUM (PR_MEDIA_REG) : DWARF_FRAME_REGNUM (PR_REG))
+
+#define EH_RETURN_DATA_REGNO(N)	\
+  ((N) < 4 ? (N) + (TARGET_SH5 ? 2 : 4) : INVALID_REGNUM)
+
+#define EH_RETURN_STACKADJ_RTX	gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM)
 
 #if (defined CRT_BEGIN || defined CRT_END) && ! __SHMEDIA__
 /* SH constant pool breaks the devices in crtstuff.c to control section
diff -u3prN ORIG/gccbib/gcc/config/sh/sh.md LOCAL/gccbib/gcc/config/sh/sh.md
--- ORIG/gccbib/gcc/config/sh/sh.md	Wed Nov  6 04:12:16 2002
+++ LOCAL/gccbib/gcc/config/sh/sh.md	Tue Nov 19 08:27:34 2002
@@ -135,6 +135,7 @@
   (UNSPEC_FSINA		16)
   (UNSPEC_NSB		17)
   (UNSPEC_ALLOCO	18)
+  (UNSPEC_EH_RETURN	19)
 
   ;; These are used with unspec_volatile.
   (UNSPECV_BLOCKAGE	0)
@@ -7134,6 +7135,48 @@
 {
   sh_expand_epilogue ();
   emit_jump_insn (gen_return ());
+  DONE;
+}")
+
+(define_expand "eh_return"
+  [(use (match_operand 0 "register_operand" ""))
+   (use (match_operand 1 "register_operand" ""))]
+  ""
+{
+  rtx tmp, sa = operands[0], ra = operands[1];
+
+  if (TARGET_SHMEDIA64)
+    emit_insn (gen_eh_set_ra_di (ra));
+  else
+    emit_insn (gen_eh_set_ra_si (ra));
+
+  emit_move_insn (EH_RETURN_STACKADJ_RTX, sa);
+  DONE;
+})
+
+;; Clobber the return address on the stack.  We can't expand this
+;; until we know where it will be put in the stack frame.
+
+(define_insn "eh_set_ra_si"
+  [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
+   (clobber (match_scratch:SI 1 "=&r"))]
+  "! TARGET_SHMEDIA64"
+  "#")
+
+(define_insn "eh_set_ra_di"
+  [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
+   (clobber (match_scratch:DI 1 "=&r"))]
+  "TARGET_SHMEDIA64"
+  "#")
+
+(define_split
+  [(unspec [(match_operand 0 "register_operand" "")] UNSPEC_EH_RETURN)
+   (clobber (match_scratch 1 ""))]
+  "reload_completed"
+  [(const_int 0)]
+  "
+{
+  sh_set_return_address (operands[0], operands[1]);
   DONE;
 }")
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]