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]

applied to SH port: prologue / epiloge & warning patches


2003-07-16  J"orn Rennecke <joern.rennecke@superh.com>
	    Con Bradley <con.bradley@superh.com>

	* sh-protos.h (sh_get_pr_initial_val): Declare.
	* sh.c (regno_reg_class): Make its elements type enum reg_class.
	(output_stack_adjust): Remove emit_fn argument.  Add epilogue_p
	and live_regs_mask arguments.  Changed all callers.
	(save_schedule_s): New structure.
	(save_schedule): New typedef.
	(scavenge_reg, sh5_schedule_saves, sh5_schedule_saves): New functions.
	(calc_live_regs): For TARGET_SHMEDIA, use leaf_function_p.
	In interrupts handlers, also save registers that are usually
	partially saved, and make sure there is at least one general purpose
	register saved if a target register needs saving.
	Add casts in comparisons to avoid warnings.
	(sh_media_register_for_return): return -1 for interrupt handlers.
	(MAX_SAVED_REGS, MAX_TEMPS): New defines.
	(sh_expand_prologue): Use sh5_schedule_saves.  Check that any temp
	registers used are available.
	Set RTX_FRAME_RELATED_P where appropriate.
	Add an REG_FRAME_RELATED_EXPR for r0 + offset addressing.
	(sh_expand_epilogue, sh_set_return_address): Use sh5_schedule_saves.
	(initial_elimination_offset): Likewise.
	* sh.h (DWARF_CIE_DATA_ALIGNMENT): Set to -4.
	(LOCAL_ALIGNMENT, GENERAL_REGISTER_P): Add casts to avoid warnings.
	(FP_REGISTER_P): Add casts to fix broken handling of unsigned REGNO.
	(XD_REGISTER_P, TARGET_REGISTER_P): Likewise.
	(HARD_REGNO_CALL_PART_CLOBBERED): Also yield nonzero for r15,
	and for target registers.
	(RETURN_IN_MEMORY): Add parentheses to avoid warnings.
	(regno_reg_class): Make its elements type enum reg_class.
	(CONSTRAINT_LEN): Don't use isdigit.
	(FUNCTION_ARG_REGNO_P): Add casts to avoid warnings.
	(FUNCTION_ARG): Add parentheses to avoid warnings.
	(RETURN_ADDR_RTX): Use sh_get_pr_initial_val.
	(RETURN_ADDR_OFFSET): Define to -1 for TARGET_SH5.
	(SH_DBX_REGISTER_NUMBER): Add casts to avoid warnings.
	(EH_RETURN_DATA_REGNO): Use unsigned constants to avoid warnings.
	* sh.md (xordi3+1): Remove unused variable regno.
	(return_media): Check that tr0 is available before using it.

Index: config/sh/sh-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh-protos.h,v
retrieving revision 1.44
diff -p -r1.44 sh-protos.h
*** config/sh/sh-protos.h	19 Jun 2003 21:47:23 -0000	1.44
--- config/sh/sh-protos.h	16 Jul 2003 21:38:34 -0000
*************** extern void sh_pr_interrupt PARAMS ((str
*** 136,140 ****
--- 136,141 ----
  extern void sh_pr_trapa PARAMS ((struct cpp_reader *));
  extern void sh_pr_nosave_low_regs PARAMS ((struct cpp_reader *));
  extern rtx function_symbol (const char *);
+ extern rtx sh_get_pr_initial_val (void);
  
  #endif /* ! GCC_SH_PROTOS_H */
Index: config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.229
diff -p -r1.229 sh.c
*** config/sh/sh.c	10 Jul 2003 18:04:25 -0000	1.229
--- config/sh/sh.c	16 Jul 2003 21:38:35 -0000
*************** rtx sh_compare_op1;
*** 108,114 ****
  /* Provides the class number of the smallest class containing
     reg number.  */
  
! int regno_reg_class[FIRST_PSEUDO_REGISTER] =
  {
    R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
    GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
--- 108,114 ----
  /* Provides the class number of the smallest class containing
     reg number.  */
  
! enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER] =
  {
    R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
    GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
*************** static rtx find_barrier PARAMS ((int, rt
*** 190,196 ****
  static int noncall_uses_reg PARAMS ((rtx, rtx, rtx *));
  static rtx gen_block_redirect PARAMS ((rtx, int, int));
  static void sh_reorg PARAMS ((void));
! static void output_stack_adjust PARAMS ((int, rtx, int, rtx (*) (rtx)));
  static rtx frame_insn PARAMS ((rtx));
  static rtx push PARAMS ((int));
  static void pop PARAMS ((int));
--- 190,196 ----
  static int noncall_uses_reg PARAMS ((rtx, rtx, rtx *));
  static rtx gen_block_redirect PARAMS ((rtx, int, int));
  static void sh_reorg PARAMS ((void));
! static void output_stack_adjust (int, rtx, int, HARD_REG_SET *);
  static rtx frame_insn PARAMS ((rtx));
  static rtx push PARAMS ((int));
  static void pop PARAMS ((int));
*************** static int sh_address_cost PARAMS ((rtx)
*** 234,239 ****
--- 234,243 ----
  static int shmedia_target_regs_stack_space (HARD_REG_SET *);
  static int shmedia_reserve_space_for_target_registers_p (int, HARD_REG_SET *);
  static int shmedia_target_regs_stack_adjust (HARD_REG_SET *);
+ static int scavenge_reg (HARD_REG_SET *s);
+ struct save_schedule_s;
+ static struct save_entry_s *sh5_schedule_saves (HARD_REG_SET *,
+ 						struct save_schedule_s *, int);
  
  /* Initialize the GCC target structure.  */
  #undef TARGET_ATTRIBUTE_TABLE
*************** output_jump_label_table ()
*** 4558,4574 ****
  
  static int extra_push;
  
! /* Adjust the stack by SIZE bytes.  REG holds the rtl of the register
!   to be adjusted, and TEMP, if nonnegative, holds the register number
!   of a general register that we may clobber.  */
  
  static void
! output_stack_adjust (size, reg, temp, emit_fn)
!      int size;
!      rtx reg;
!      int temp;
!      rtx (*emit_fn) PARAMS ((rtx));
  {
    if (size)
      {
        HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT;
--- 4562,4577 ----
  
  static int extra_push;
  
! /* Adjust the stack by SIZE bytes.  REG holds the rtl of the register to be
!    adjusted.  If epilogue_p is zero, this is for a prologue; otherwise, it's
!    for an epilogue.  If LIVE_REGS_MASK is nonzero, it points to a HARD_REG_SET
!    of all the registers that are about to be restored, and hence dead.  */
  
  static void
! output_stack_adjust (int size, rtx reg, int epilogue_p,
! 		     HARD_REG_SET *live_regs_mask)
  {
+   rtx (*emit_fn) (rtx) = epilogue_p ? &emit_insn : &frame_insn;
    if (size)
      {
        HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT;
*************** output_stack_adjust (size, reg, temp, em
*** 4591,4600 ****
--- 4594,4636 ----
  	{
  	  rtx const_reg;
  	  rtx insn;
+ 	  int temp = epilogue_p ? 7 : (TARGET_SH5 ? 0 : 1);
+ 	  int i;
  
  	  /* If TEMP is invalid, we could temporarily save a general
  	     register to MACL.  However, there is currently no need
  	     to handle this case, so just abort when we see it.  */
+ 	  if (current_function_interrupt
+ 	      || ! call_used_regs[temp] || fixed_regs[temp])
+ 	    temp = -1;
+ 	  if (temp < 0 && ! current_function_interrupt)
+ 	    {
+ 	      HARD_REG_SET temps;
+ 	      COPY_HARD_REG_SET (temps, call_used_reg_set);
+ 	      AND_COMPL_HARD_REG_SET (temps, call_fixed_reg_set);
+ 	      if (epilogue_p)
+ 		{
+ 		  for (i = 0; i < HARD_REGNO_NREGS (FIRST_RET_REG, DImode); i++)
+ 		    CLEAR_HARD_REG_BIT (temps, FIRST_RET_REG + i);
+ 		  if (current_function_calls_eh_return)
+ 		    {
+ 		      CLEAR_HARD_REG_BIT (temps, EH_RETURN_STACKADJ_REGNO);
+ 		      for (i = 0; i <= 3; i++)
+ 			CLEAR_HARD_REG_BIT (temps, EH_RETURN_DATA_REGNO (i));
+ 		    }
+ 		}
+ 	      else
+ 		{
+ 		  for (i = FIRST_PARM_REG;
+ 		       i < FIRST_PARM_REG + NPARM_REGS (SImode); i++)
+ 		    CLEAR_HARD_REG_BIT (temps, i);
+ 		  if (current_function_needs_context)
+ 		    CLEAR_HARD_REG_BIT (temps, STATIC_CHAIN_REGNUM);
+ 		}
+ 	      temp = scavenge_reg (&temps);
+ 	    }
+ 	  if (temp < 0 && live_regs_mask)
+ 	    temp = scavenge_reg (live_regs_mask);
  	  if (temp < 0)
  	    abort ();
  	  const_reg = gen_rtx_REG (GET_MODE (reg), temp);
*************** output_stack_adjust (size, reg, temp, em
*** 4612,4618 ****
  	      emit_insn (GEN_MOV (const_reg, GEN_INT (size)));
  	      insn = emit_fn (GEN_ADD3 (reg, reg, const_reg));
  	    }
! 	  if (emit_fn == frame_insn)
  	    REG_NOTES (insn)
  	      = (gen_rtx_EXPR_LIST
  		 (REG_FRAME_RELATED_EXPR,
--- 4648,4654 ----
  	      emit_insn (GEN_MOV (const_reg, GEN_INT (size)));
  	      insn = emit_fn (GEN_ADD3 (reg, reg, const_reg));
  	    }
! 	  if (! epilogue_p)
  	    REG_NOTES (insn)
  	      = (gen_rtx_EXPR_LIST
  		 (REG_FRAME_RELATED_EXPR,
*************** calc_live_regs (live_regs_mask)
*** 4789,4800 ****
    int reg;
    int count;
    int interrupt_handler;
!   int pr_live;
  
    interrupt_handler = sh_cfun_interrupt_handler_p ();
  
!   for (count = 0; 32 * count < FIRST_PSEUDO_REGISTER; count++)
!     CLEAR_HARD_REG_SET (*live_regs_mask);
    if (TARGET_SH4 && TARGET_FMOVD && interrupt_handler
        && regs_ever_live[FPSCR_REG])
      target_flags &= ~FPU_SINGLE_BIT;
--- 4825,4835 ----
    int reg;
    int count;
    int interrupt_handler;
!   int pr_live, has_call;
  
    interrupt_handler = sh_cfun_interrupt_handler_p ();
  
!   CLEAR_HARD_REG_SET (*live_regs_mask);
    if (TARGET_SH4 && TARGET_FMOVD && interrupt_handler
        && regs_ever_live[FPSCR_REG])
      target_flags &= ~FPU_SINGLE_BIT;
*************** calc_live_regs (live_regs_mask)
*** 4829,4844 ****
  	   & ~ CALL_COOKIE_RET_TRAMP (1))
  	  || current_function_has_nonlocal_label))
      pr_live = 1;
    for (count = 0, reg = FIRST_PSEUDO_REGISTER - 1; reg >= 0; reg--)
      {
!       if (reg == (TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG)
  	  ? pr_live
  	  : (interrupt_handler && ! pragma_trapa)
  	  ? (/* Need to save all the regs ever live.  */
  	     (regs_ever_live[reg]
  	      || (call_used_regs[reg]
  		  && (! fixed_regs[reg] || reg == MACH_REG || reg == MACL_REG)
! 		  && pr_live))
  	     && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM
  	     && reg != RETURN_ADDRESS_POINTER_REGNUM
  	     && reg != T_REG && reg != GBR_REG
--- 4864,4882 ----
  	   & ~ CALL_COOKIE_RET_TRAMP (1))
  	  || current_function_has_nonlocal_label))
      pr_live = 1;
+   has_call = TARGET_SHMEDIA ? ! leaf_function_p () : pr_live;
    for (count = 0, reg = FIRST_PSEUDO_REGISTER - 1; reg >= 0; reg--)
      {
!       if ((! TARGET_SHMEDIA && reg == PR_REG)
  	  ? pr_live
  	  : (interrupt_handler && ! pragma_trapa)
  	  ? (/* Need to save all the regs ever live.  */
  	     (regs_ever_live[reg]
  	      || (call_used_regs[reg]
  		  && (! fixed_regs[reg] || reg == MACH_REG || reg == MACL_REG)
! 		  && has_call)
! 	      || (has_call && REGISTER_NATURAL_MODE (reg) == SImode
! 		  && (GENERAL_REGISTER_P (reg) || TARGET_REGISTER_P (reg))))
  	     && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM
  	     && reg != RETURN_ADDRESS_POINTER_REGNUM
  	     && reg != T_REG && reg != GBR_REG
*************** calc_live_regs (live_regs_mask)
*** 4848,4860 ****
  	     (TARGET_SHCOMPACT
  	      && flag_pic
  	      && current_function_args_info.call_cookie
! 	      && reg == PIC_OFFSET_TABLE_REGNUM)
  	     || (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)))))
  	{
  	  SET_HARD_REG_BIT (*live_regs_mask, reg);
  	  count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
--- 4886,4898 ----
  	     (TARGET_SHCOMPACT
  	      && flag_pic
  	      && current_function_args_info.call_cookie
! 	      && reg == (int) PIC_OFFSET_TABLE_REGNUM)
  	     || (regs_ever_live[reg] && ! call_used_regs[reg])
  	     || (current_function_calls_eh_return
! 		 && (reg == (int) EH_RETURN_DATA_REGNO (0)
! 		     || reg == (int) EH_RETURN_DATA_REGNO (1)
! 		     || reg == (int) EH_RETURN_DATA_REGNO (2)
! 		     || reg == (int) EH_RETURN_DATA_REGNO (3)))))
  	{
  	  SET_HARD_REG_BIT (*live_regs_mask, reg);
  	  count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
*************** calc_live_regs (live_regs_mask)
*** 4891,4896 ****
--- 4929,4947 ----
  	  SET_HARD_REG_BIT (*live_regs_mask, reg);
  	  count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
  	}
+   /* If this is an interrupt handler, we don't have any call-clobbered
+      registers we can conveniently use for target register save/restore.
+      Make sure we save at least one general purpose register when we need
+      to save target registers.  */
+   if (interrupt_handler
+       && hard_regs_intersect_p (live_regs_mask,
+ 				&reg_class_contents[TARGET_REGS])
+       && ! hard_regs_intersect_p (live_regs_mask,
+ 				  &reg_class_contents[GENERAL_REGS]))
+     {
+       SET_HARD_REG_BIT (*live_regs_mask, R0_REG);
+       count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (R0_REG));
+     }
  
    return count;
  }
*************** sh_media_register_for_return ()
*** 4921,4926 ****
--- 4972,4980 ----
  
    if (! current_function_is_leaf)
      return -1;
+   if (lookup_attribute ("interrupt_handler",
+ 			DECL_ATTRIBUTES (current_function_decl)))
+     return -1;
  
    tr0_used = flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM];
  
*************** sh_media_register_for_return ()
*** 4931,4936 ****
--- 4985,5114 ----
    return -1;
  }
  
+ /* The maximum registers we need to save are:
+    - 62 general purpose registers (r15 is stack pointer, r63 is zero)
+    - 32 floating point registers (for each pair, we save none,
+          one single precision value, or a double precision value).
+    -  8 target registers
+    -  add 1 entry for a delimiter.  */
+ #define MAX_SAVED_REGS (62+32+8)
+ 
+ typedef struct save_entry_s
+ {
+   unsigned char reg;
+   unsigned char mode;
+   short offset;
+ } save_entry;
+ 
+ #define MAX_TEMPS 4
+ 
+ /* There will be a delimiter entry with VOIDmode both at the start and the
+    end of a filled in schedule.  The end delimiter has the offset of the
+    save with the smallest (i.e. most negative) offset.  */
+ typedef struct save_schedule_s
+ {
+   save_entry entries[MAX_SAVED_REGS + 2];
+   int temps[MAX_TEMPS+1];
+ } save_schedule;
+ 
+ /* Fill in SCHEDULE according to LIVE_REGS_MASK.  If RESTORE is nonzero,
+    use reverse order.  Returns the last entry written to (not counting
+    the delimiter).  OFFSET_BASE is a number to be added to all offset
+    entries.  */
+    
+ static save_entry *
+ sh5_schedule_saves (HARD_REG_SET *live_regs_mask, save_schedule *schedule,
+ 		    int offset_base)
+ {
+   int align, i;
+   save_entry *entry = schedule->entries;
+   int tmpx = 0;
+   int offset;
+ 
+   if (! current_function_interrupt)
+     for (i = FIRST_GENERAL_REG; tmpx < MAX_TEMPS && i <= LAST_GENERAL_REG; i++)
+       if (call_used_regs[i] && ! fixed_regs[i]
+ 	  && ! FUNCTION_ARG_REGNO_P (i)
+ 	  && i != FIRST_RET_REG
+ 	  && ! (current_function_needs_context && i == STATIC_CHAIN_REGNUM)
+ 	  && ! (current_function_calls_eh_return
+ 		&& (i == EH_RETURN_STACKADJ_REGNO
+ 		    || ((unsigned)i <= EH_RETURN_DATA_REGNO (0)
+ 			&& (unsigned)i >= EH_RETURN_DATA_REGNO (3)))))
+ 	schedule->temps[tmpx++] = i;
+   entry->reg = -1;
+   entry->mode = VOIDmode;
+   entry->offset = offset_base;
+   entry++;
+   /* 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.
+      If this is an interrupt function, all registers that need saving
+      need to be saved in full.  moreover, we need to postpone saving
+      target registers till we have saved some general purpose registers
+      we can then use as scratch registers.  */
+   offset = offset_base;
+   for (align = 1; align >= 0; align--)
+     {
+       for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
+ 	if (TEST_HARD_REG_BIT (*live_regs_mask, i))
+ 	  {
+ 	    enum machine_mode mode = REGISTER_NATURAL_MODE (i);
+ 	    int reg = i;
+ 
+ 	    if (current_function_interrupt)
+ 	      {
+ 		if (TARGET_REGISTER_P (i))
+ 		  continue;
+ 		if (GENERAL_REGISTER_P (i))
+ 		  mode = DImode;
+ 	      }
+ 	    if (mode == SFmode && (i % 2) == 1
+ 		&& ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
+ 		&& (TEST_HARD_REG_BIT (*live_regs_mask, (i ^ 1))))
+ 	      {
+ 		mode = DFmode;
+ 		i--;
+ 		reg--;
+ 	      }
+ 
+ 	    /* 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 (current_function_interrupt
+ 		&& GENERAL_REGISTER_P (i)
+ 		&& tmpx < MAX_TEMPS)
+ 	      schedule->temps[tmpx++] = i;
+ 
+ 	    offset -= GET_MODE_SIZE (mode);
+ 	    entry->reg = i;
+ 	    entry->mode = mode;
+ 	    entry->offset = offset;
+ 	    entry++;
+ 	  }
+       if (align && current_function_interrupt)
+ 	for (i = LAST_TARGET_REG; i >= FIRST_TARGET_REG; i--)
+ 	  if (TEST_HARD_REG_BIT (*live_regs_mask, i))
+ 	    {
+ 	      offset -= GET_MODE_SIZE (DImode);
+ 	      entry->reg = i;
+ 	      entry->mode = DImode;
+ 	      entry->offset = offset;
+ 	      entry++;
+ 	    }
+     }
+   entry->reg = -1;
+   entry->mode = VOIDmode;
+   entry->offset = offset;
+   schedule->temps[tmpx] = -1;
+   return entry - 1;
+ }
+ 
  void
  sh_expand_prologue ()
  {
*************** sh_expand_prologue ()
*** 4945,4951 ****
       and partially on the stack, e.g. a large structure.  */
    output_stack_adjust (-current_function_pretend_args_size
  		       - current_function_args_info.stack_regs * 8,
! 		       stack_pointer_rtx, TARGET_SH5 ? 0 : 1, frame_insn);
  
    extra_push = 0;
  
--- 5123,5129 ----
       and partially on the stack, e.g. a large structure.  */
    output_stack_adjust (-current_function_pretend_args_size
  		       - current_function_args_info.stack_regs * 8,
! 		       stack_pointer_rtx, 0, NULL);
  
    extra_push = 0;
  
*************** sh_expand_prologue ()
*** 5034,5047 ****
      
    if (TARGET_SH5)
      {
!       int i;
!       int offset;
!       int align;
!       rtx r0 = gen_rtx_REG (Pmode, R0_REG);
        int offset_in_r0 = -1;
        int sp_in_r0 = 0;
        int tregs_space = shmedia_target_regs_stack_adjust (&live_regs_mask);
        int total_size, save_size;
  
        /* D is the actual number of bytes that we need for saving registers,
  	 however, in initial_elimination_offset we have committed to using
--- 5212,5230 ----
      
    if (TARGET_SH5)
      {
!       int offset_base, offset;
!       rtx r0 = NULL_RTX;
        int offset_in_r0 = -1;
        int sp_in_r0 = 0;
        int tregs_space = shmedia_target_regs_stack_adjust (&live_regs_mask);
        int total_size, save_size;
+       save_schedule schedule;
+       save_entry *entry;
+       int *tmp_pnt;
+ 
+       if (call_used_regs[R0_REG] && ! fixed_regs[R0_REG]
+ 	  && ! current_function_interrupt)
+ 	r0 = gen_rtx_REG (Pmode, R0_REG);
  
        /* D is the actual number of bytes that we need for saving registers,
  	 however, in initial_elimination_offset we have committed to using
*************** sh_expand_prologue ()
*** 5067,5212 ****
  		  && total_size <= 2044)))
  	d_rounding = total_size - save_size;
  
!       offset = d + d_rounding;
  
        output_stack_adjust (-(save_size + d_rounding), stack_pointer_rtx,
! 			   1, frame_insn);
  
!       /* 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.  */
!       /* Note that if you change this code in a way that affects where
! 	 the return register is saved, you have to update not only
! 	 sh_expand_epilogue, but also sh_set_return_address.  */
!       for (align = 1; align >= 0; align--)
! 	for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
! 	  if (TEST_HARD_REG_BIT (live_regs_mask, i))
! 	    {
! 	      enum machine_mode mode = REGISTER_NATURAL_MODE (i);
! 	      int reg = i;
! 	      rtx reg_rtx, mem_rtx, pre_dec = NULL_RTX;
! 
! 	      if (mode == SFmode && (i % 2) == 1
! 		  && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
! 		  && (TEST_HARD_REG_BIT (live_regs_mask, (i ^ 1))))
! 		{
! 		  mode = DFmode;
! 		  i--;
! 		  reg--;
! 		}
! 		
! 	      /* 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;
  
! 	      offset -= GET_MODE_SIZE (mode);
  
! 	      reg_rtx = gen_rtx_REG (mode, reg);
  
! 	      mem_rtx = gen_rtx_MEM (mode,
! 				     gen_rtx_PLUS (Pmode,
! 						   stack_pointer_rtx,
! 						   GEN_INT (offset)));
  
! 	      GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_pre_dec);
  
! 	      mem_rtx = NULL_RTX;
  
! 	    try_pre_dec:
! 	      do
! 		if (HAVE_PRE_DECREMENT
! 		    && (offset_in_r0 - offset == GET_MODE_SIZE (mode)
! 			|| mem_rtx == NULL_RTX
! 			|| i == PR_REG || SPECIAL_REGISTER_P (i)))
! 		  {
! 		    pre_dec = gen_rtx_MEM (mode,
! 					   gen_rtx_PRE_DEC (Pmode, r0));
  
! 		    GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (pre_dec, 0),
! 					      pre_dec_ok);
  
! 		    pre_dec = NULL_RTX;
  
! 		    break;
  
! 		  pre_dec_ok:
! 		    mem_rtx = NULL_RTX;
! 		    offset += GET_MODE_SIZE (mode);
! 		  }
! 	      while (0);
  
! 	      if (mem_rtx != NULL_RTX)
! 		goto addr_ok;
  
! 	      if (offset_in_r0 == -1)
! 		{
! 		  emit_move_insn (r0, GEN_INT (offset));
! 		  offset_in_r0 = offset;
! 		}
! 	      else if (offset != offset_in_r0)
  		{
  		  emit_move_insn (r0,
  				  gen_rtx_PLUS
! 				  (Pmode, r0,
! 				   GEN_INT (offset - offset_in_r0)));
! 		  offset_in_r0 += offset - offset_in_r0;
  		}
- 						  
- 	      if (pre_dec != NULL_RTX)
- 		{
- 		  if (! sp_in_r0)
- 		    {
- 		      emit_move_insn (r0,
- 				      gen_rtx_PLUS
- 				      (Pmode, r0, stack_pointer_rtx));
- 		      sp_in_r0 = 1;
- 		    }
  
! 		  offset -= GET_MODE_SIZE (mode);
! 		  offset_in_r0 -= GET_MODE_SIZE (mode);
  
! 		  mem_rtx = pre_dec;
! 		}
! 	      else if (sp_in_r0)
! 		mem_rtx = gen_rtx_MEM (mode, r0);
! 	      else
! 		mem_rtx = gen_rtx_MEM (mode,
! 				       gen_rtx_PLUS (Pmode,
! 						     stack_pointer_rtx,
! 						     r0));
! 
! 	      /* We must not use an r0-based address for target-branch
! 		 registers or for special registers without pre-dec
! 		 memory addresses, since we store their values in r0
! 		 first.  */
! 	      if (TARGET_REGISTER_P (i)
! 		  || ((i == PR_REG || SPECIAL_REGISTER_P (i))
! 		      && mem_rtx != pre_dec))
! 		abort ();
! 
! 	    addr_ok:
! 	      if (TARGET_REGISTER_P (i)
! 		  || ((i == PR_REG || SPECIAL_REGISTER_P (i))
! 		      && mem_rtx != pre_dec))
! 		{
! 		  rtx r0mode = gen_rtx_REG (GET_MODE (reg_rtx), R0_REG);
  
! 		  emit_move_insn (r0mode, reg_rtx);
  
  		  offset_in_r0 = -1;
  		  sp_in_r0 = 0;
! 
! 		  reg_rtx = r0mode;
  		}
  
! 	      emit_move_insn (mem_rtx, reg_rtx);
  	    }
  
!       if (offset != d_rounding)
  	abort ();
      }
    else
--- 5250,5402 ----
  		  && total_size <= 2044)))
  	d_rounding = total_size - save_size;
  
!       offset_base = d + d_rounding;
  
        output_stack_adjust (-(save_size + d_rounding), stack_pointer_rtx,
! 			   0, NULL);
  
!       sh5_schedule_saves (&live_regs_mask, &schedule, offset_base);
!       tmp_pnt = schedule.temps;
!       for (entry = &schedule.entries[1]; entry->mode != VOIDmode; entry++)
!         {
! 	  enum machine_mode mode = entry->mode;
! 	  int reg = entry->reg;
! 	  rtx reg_rtx, mem_rtx, pre_dec = NULL_RTX;
  
! 	  offset = entry->offset;
  
! 	  reg_rtx = gen_rtx_REG (mode, reg);
  
! 	  mem_rtx = gen_rtx_MEM (mode,
! 				 gen_rtx_PLUS (Pmode,
! 					       stack_pointer_rtx,
! 					       GEN_INT (offset)));
  
! 	  GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_pre_dec);
  
! 	  if (! r0)
! 	    abort ();
! 	  mem_rtx = NULL_RTX;
  
! 	try_pre_dec:
! 	  do
! 	    if (HAVE_PRE_DECREMENT
! 		&& (offset_in_r0 - offset == GET_MODE_SIZE (mode)
! 		    || mem_rtx == NULL_RTX
! 		    || reg == PR_REG || SPECIAL_REGISTER_P (reg)))
! 	      {
! 		pre_dec = gen_rtx_MEM (mode,
! 				       gen_rtx_PRE_DEC (Pmode, r0));
  
! 		GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (pre_dec, 0),
! 					  pre_dec_ok);
  
! 		pre_dec = NULL_RTX;
  
! 		break;
  
! 	      pre_dec_ok:
! 		mem_rtx = NULL_RTX;
! 		offset += GET_MODE_SIZE (mode);
! 	      }
! 	  while (0);
  
! 	  if (mem_rtx != NULL_RTX)
! 	    goto addr_ok;
  
! 	  if (offset_in_r0 == -1)
! 	    {
! 	      emit_move_insn (r0, GEN_INT (offset));
! 	      offset_in_r0 = offset;
! 	    }
! 	  else if (offset != offset_in_r0)
! 	    {
! 	      emit_move_insn (r0,
! 			      gen_rtx_PLUS
! 			      (Pmode, r0,
! 			       GEN_INT (offset - offset_in_r0)));
! 	      offset_in_r0 += offset - offset_in_r0;
! 	    }
! 					      
! 	  if (pre_dec != NULL_RTX)
! 	    {
! 	      if (! sp_in_r0)
  		{
  		  emit_move_insn (r0,
  				  gen_rtx_PLUS
! 				  (Pmode, r0, stack_pointer_rtx));
! 		  sp_in_r0 = 1;
  		}
  
! 	      offset -= GET_MODE_SIZE (mode);
! 	      offset_in_r0 -= GET_MODE_SIZE (mode);
! 
! 	      mem_rtx = pre_dec;
! 	    }
! 	  else if (sp_in_r0)
! 	    mem_rtx = gen_rtx_MEM (mode, r0);
! 	  else
! 	    mem_rtx = gen_rtx_MEM (mode,
! 				   gen_rtx_PLUS (Pmode,
! 						 stack_pointer_rtx,
! 						 r0));
! 
! 	  /* We must not use an r0-based address for target-branch
! 	     registers or for special registers without pre-dec
! 	     memory addresses, since we store their values in r0
! 	     first.  */
! 	  if (TARGET_REGISTER_P (reg)
! 	      || ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
! 		  && mem_rtx != pre_dec))
! 	    abort ();
  
! 	addr_ok:
! 	  if (TARGET_REGISTER_P (reg)
! 	      || ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
! 		  && mem_rtx != pre_dec))
! 	    {
! 	      rtx tmp_reg = gen_rtx_REG (GET_MODE (reg_rtx), *tmp_pnt);
  
! 	      emit_move_insn (tmp_reg, reg_rtx);
  
+ 	      if (REGNO (tmp_reg) == R0_REG)
+ 		{
  		  offset_in_r0 = -1;
  		  sp_in_r0 = 0;
! 		  if (refers_to_regno_p (R0_REG, R0_REG+1, mem_rtx, (rtx *) 0))
! 		    abort ();
  		}
  
! 	      if (*++tmp_pnt <= 0)
! 		tmp_pnt = schedule.temps;
! 
! 	      reg_rtx = tmp_reg;
  	    }
+ 	  {
+ 	    rtx insn;
+ 
+ 	    /* Mark as interesting for dwarf cfi generator */
+ 	    insn = emit_move_insn (mem_rtx, reg_rtx);
+ 	    RTX_FRAME_RELATED_P (insn) = 1;
  
! 	    if (TARGET_SHCOMPACT && (offset_in_r0 != -1)) 
! 	      {
! 		rtx reg_rtx = gen_rtx_REG (mode, reg);
! 		rtx set, note_rtx;
! 		rtx mem_rtx = gen_rtx_MEM (mode,
! 					   gen_rtx_PLUS (Pmode,
! 							 stack_pointer_rtx,
! 							 GEN_INT (offset)));
! 
! 		set = gen_rtx_SET (VOIDmode, mem_rtx, reg_rtx);
! 		note_rtx = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, set,
! 					      REG_NOTES (insn));
! 		REG_NOTES (insn) = note_rtx;
! 	      }
! 	  }
! 	}
! 
!       if (entry->offset != d_rounding)
  	abort ();
      }
    else
*************** sh_expand_prologue ()
*** 5258,5264 ****
    target_flags = save_flags;
  
    output_stack_adjust (-rounded_frame_size (d) + d_rounding,
! 		       stack_pointer_rtx, TARGET_SH5 ? 0 : 1, frame_insn);
  
    if (frame_pointer_needed)
      frame_insn (GEN_MOV (frame_pointer_rtx, stack_pointer_rtx));
--- 5448,5454 ----
    target_flags = save_flags;
  
    output_stack_adjust (-rounded_frame_size (d) + d_rounding,
! 		       stack_pointer_rtx, 0, NULL);
  
    if (frame_pointer_needed)
      frame_insn (GEN_MOV (frame_pointer_rtx, stack_pointer_rtx));
*************** sh_expand_epilogue ()
*** 5318,5324 ****
  
    if (frame_pointer_needed)
      {
!       output_stack_adjust (frame_size, frame_pointer_rtx, 7, emit_insn);
  
        /* We must avoid moving the stack pointer adjustment past code
  	 which reads from the local frame, else an interrupt could
--- 5508,5514 ----
  
    if (frame_pointer_needed)
      {
!       output_stack_adjust (frame_size, frame_pointer_rtx, 1, &live_regs_mask);
  
        /* We must avoid moving the stack pointer adjustment past code
  	 which reads from the local frame, else an interrupt could
*************** sh_expand_epilogue ()
*** 5334,5340 ****
  	 occur after the SP adjustment and clobber data in the local
  	 frame.  */
        emit_insn (gen_blockage ());
!       output_stack_adjust (frame_size, stack_pointer_rtx, 7, emit_insn);
      }
  
    if (SHMEDIA_REGS_STACK_ADJUST ())
--- 5524,5530 ----
  	 occur after the SP adjustment and clobber data in the local
  	 frame.  */
        emit_insn (gen_blockage ());
!       output_stack_adjust (frame_size, stack_pointer_rtx, 1, &live_regs_mask);
      }
  
    if (SHMEDIA_REGS_STACK_ADJUST ())
*************** sh_expand_epilogue ()
*** 5355,5497 ****
      emit_insn (gen_toggle_sz ());
    if (TARGET_SH5)
      {
!       int offset = d_rounding;
        int offset_in_r0 = -1;
        int sp_in_r0 = 0;
-       int align;
        rtx r0 = gen_rtx_REG (Pmode, R0_REG);
!       int tmp_regno = R20_REG;
        
!       /* 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 (TEST_HARD_REG_BIT (live_regs_mask, i))
! 	    {
! 	      enum machine_mode mode = REGISTER_NATURAL_MODE (i);
! 	      int reg = i;
! 	      rtx reg_rtx, mem_rtx, post_inc = NULL_RTX, insn;
! 
! 	      if (mode == SFmode && (i % 2) == 0
! 		  && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
! 		  && (TEST_HARD_REG_BIT (live_regs_mask, (i ^ 1))))
! 		{
! 		  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;
  
! 	      reg_rtx = gen_rtx_REG (mode, reg);
  
! 	      mem_rtx = gen_rtx_MEM (mode,
! 				     gen_rtx_PLUS (Pmode,
! 						   stack_pointer_rtx,
! 						   GEN_INT (offset)));
  
! 	      GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_post_inc);
  
! 	      mem_rtx = NULL_RTX;
  
! 	    try_post_inc:
! 	      do
! 		if (HAVE_POST_INCREMENT
! 		    && (offset == offset_in_r0
! 			|| (offset + GET_MODE_SIZE (mode) != d + d_rounding
! 			    && mem_rtx == NULL_RTX)
! 			|| i == PR_REG || SPECIAL_REGISTER_P (i)))
! 		  {
! 		    post_inc = gen_rtx_MEM (mode,
! 					    gen_rtx_POST_INC (Pmode, r0));
  
! 		    GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (post_inc, 0),
! 					      post_inc_ok);
  
! 		    post_inc = NULL_RTX;
  
! 		    break;
! 		    
! 		  post_inc_ok:
! 		    mem_rtx = NULL_RTX;
! 		  }
! 	      while (0);
  	      
! 	      if (mem_rtx != NULL_RTX)
! 		goto addr_ok;
! 
! 	      if (offset_in_r0 == -1)
! 		{
! 		  emit_move_insn (r0, GEN_INT (offset));
! 		  offset_in_r0 = offset;
! 		}
! 	      else if (offset != offset_in_r0)
  		{
  		  emit_move_insn (r0,
  				  gen_rtx_PLUS
! 				  (Pmode, r0,
! 				   GEN_INT (offset - offset_in_r0)));
! 		  offset_in_r0 += offset - offset_in_r0;
  		}
! 		  
! 	      if (post_inc != NULL_RTX)
! 		{
! 		  if (! sp_in_r0)
! 		    {
! 		      emit_move_insn (r0,
! 				      gen_rtx_PLUS
! 				      (Pmode, r0, stack_pointer_rtx));
! 		      sp_in_r0 = 1;
! 		    }
! 		  
! 		  mem_rtx = post_inc;
  
! 		  offset_in_r0 += GET_MODE_SIZE (mode);
! 		}
! 	      else if (sp_in_r0)
! 		mem_rtx = gen_rtx_MEM (mode, r0);
! 	      else
! 		mem_rtx = gen_rtx_MEM (mode,
! 				       gen_rtx_PLUS (Pmode,
! 						     stack_pointer_rtx,
! 						     r0));
! 
! 	      if ((i == PR_REG || SPECIAL_REGISTER_P (i))
! 		  && mem_rtx != post_inc)
! 		abort ();
! 
! 	    addr_ok:
! 	      if ((i == PR_REG || SPECIAL_REGISTER_P (i))
! 		  && mem_rtx != post_inc)
! 		{
! 		  insn = emit_move_insn (r0, mem_rtx);
! 		  mem_rtx = r0;
! 		}
! 	      else if (TARGET_REGISTER_P (i))
! 		{
! 		  rtx tmp_reg = gen_rtx_REG (mode, tmp_regno);
  
! 		  /* Give the scheduler a bit of freedom by using R20..R23
! 		     in a round-robin fashion.  Don't use R1 here because
! 		     we want to use it for EH_RETURN_STACKADJ_RTX.  */
! 		  insn = emit_move_insn (tmp_reg, mem_rtx);
! 		  mem_rtx = tmp_reg;
! 		  if (++tmp_regno > R23_REG)
! 		    tmp_regno = R20_REG;
! 		}
  
! 	      insn = emit_move_insn (reg_rtx, mem_rtx);
  
! 	      offset += GET_MODE_SIZE (mode);
  	    }
  
!       if (offset != d + d_rounding)
  	abort ();
      }
    else /* ! TARGET_SH5 */
--- 5545,5670 ----
      emit_insn (gen_toggle_sz ());
    if (TARGET_SH5)
      {
!       int offset_base, offset;
        int offset_in_r0 = -1;
        int sp_in_r0 = 0;
        rtx r0 = gen_rtx_REG (Pmode, R0_REG);
!       save_schedule schedule;
!       save_entry *entry;
!       int *tmp_pnt;
        
!       entry = sh5_schedule_saves (&live_regs_mask, &schedule, d_rounding);
!       offset_base = -entry[1].offset + d_rounding;
!       tmp_pnt = schedule.temps;
!       for (; entry->mode != VOIDmode; entry--)
! 	{
! 	  enum machine_mode mode = entry->mode;
! 	  int reg = entry->reg;
! 	  rtx reg_rtx, mem_rtx, post_inc = NULL_RTX, insn;
  
! 	  offset = offset_base + entry->offset;
! 	  reg_rtx = gen_rtx_REG (mode, reg);
  
! 	  mem_rtx = gen_rtx_MEM (mode,
! 				 gen_rtx_PLUS (Pmode,
! 					       stack_pointer_rtx,
! 					       GEN_INT (offset)));
  
! 	  GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_post_inc);
  
! 	  mem_rtx = NULL_RTX;
  
! 	try_post_inc:
! 	  do
! 	    if (HAVE_POST_INCREMENT
! 		&& (offset == offset_in_r0
! 		    || (offset + GET_MODE_SIZE (mode) != d + d_rounding
! 			&& mem_rtx == NULL_RTX)
! 		    || reg == PR_REG || SPECIAL_REGISTER_P (reg)))
! 	      {
! 		post_inc = gen_rtx_MEM (mode,
! 					gen_rtx_POST_INC (Pmode, r0));
  
! 		GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (post_inc, 0),
! 					  post_inc_ok);
  
! 		post_inc = NULL_RTX;
  
! 		break;
! 		
! 	      post_inc_ok:
! 		mem_rtx = NULL_RTX;
! 	      }
! 	  while (0);
! 	  
! 	  if (mem_rtx != NULL_RTX)
! 	    goto addr_ok;
  
! 	  if (offset_in_r0 == -1)
! 	    {
! 	      emit_move_insn (r0, GEN_INT (offset));
! 	      offset_in_r0 = offset;
! 	    }
! 	  else if (offset != offset_in_r0)
! 	    {
! 	      emit_move_insn (r0,
! 			      gen_rtx_PLUS
! 			      (Pmode, r0,
! 			       GEN_INT (offset - offset_in_r0)));
! 	      offset_in_r0 += offset - offset_in_r0;
! 	    }
  	      
! 	  if (post_inc != NULL_RTX)
! 	    {
! 	      if (! sp_in_r0)
  		{
  		  emit_move_insn (r0,
  				  gen_rtx_PLUS
! 				  (Pmode, r0, stack_pointer_rtx));
! 		  sp_in_r0 = 1;
  		}
! 	      
! 	      mem_rtx = post_inc;
  
! 	      offset_in_r0 += GET_MODE_SIZE (mode);
! 	    }
! 	  else if (sp_in_r0)
! 	    mem_rtx = gen_rtx_MEM (mode, r0);
! 	  else
! 	    mem_rtx = gen_rtx_MEM (mode,
! 				   gen_rtx_PLUS (Pmode,
! 						 stack_pointer_rtx,
! 						 r0));
  
! 	  if ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
! 	      && mem_rtx != post_inc)
! 	    abort ();
  
! 	addr_ok:
! 	  if ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
! 	      && mem_rtx != post_inc)
! 	    {
! 	      insn = emit_move_insn (r0, mem_rtx);
! 	      mem_rtx = r0;
! 	    }
! 	  else if (TARGET_REGISTER_P (reg))
! 	    {
! 	      rtx tmp_reg = gen_rtx_REG (mode, *tmp_pnt);
  
! 	      /* Give the scheduler a bit of freedom by using up to
! 		 MAX_TEMPS registers in a round-robin fashion.  */
! 	      insn = emit_move_insn (tmp_reg, mem_rtx);
! 	      mem_rtx = tmp_reg;
! 	      if (*++tmp_pnt < 0)
! 		tmp_pnt = schedule.temps;
  	    }
  
! 	  insn = emit_move_insn (reg_rtx, mem_rtx);
! 
! 	  offset += GET_MODE_SIZE (mode);
! 	}
! 
!       if (entry->offset + offset_base != d + d_rounding)
  	abort ();
      }
    else /* ! TARGET_SH5 */
*************** sh_expand_epilogue ()
*** 5521,5527 ****
    output_stack_adjust (extra_push + current_function_pretend_args_size
  		       + save_size + d_rounding
  		       + 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,
--- 5694,5700 ----
    output_stack_adjust (extra_push + current_function_pretend_args_size
  		       + save_size + d_rounding
  		       + current_function_args_info.stack_regs * 8,
! 		       stack_pointer_rtx, 1, NULL);
  
    if (current_function_calls_eh_return)
      emit_insn (GEN_ADD3 (stack_pointer_rtx, stack_pointer_rtx,
*************** sh_set_return_address (ra, tmp)
*** 5566,5572 ****
  {
    HARD_REG_SET live_regs_mask;
    int d;
-   int d_rounding = 0;
    int pr_reg = TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG;
    int pr_offset;
  
--- 5739,5744 ----
*************** sh_set_return_address (ra, tmp)
*** 5598,5653 ****
  
    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 (TEST_HARD_REG_BIT (live_regs_mask, i))
! 	    {
! 	      enum machine_mode mode = REGISTER_NATURAL_MODE (i);
! 
! 	      if (mode == SFmode && (i % 2) == 0
! 		  && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
! 		  && (TEST_HARD_REG_BIT (live_regs_mask, (i ^ 1))))
! 		{
! 		  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));
--- 5770,5795 ----
  
    if (TARGET_SH5)
      {
        int offset;
!       save_schedule schedule;
!       save_entry *entry;
        
!       entry = sh5_schedule_saves (&live_regs_mask, &schedule, 0);
!       offset = entry[1].offset;
!       for (; entry->mode != VOIDmode; entry--)
! 	if (entry->reg == pr_reg)
! 	  goto found;
  
        /* We can't find pr register.  */
        abort ();
  
      found:
!       offset = entry->offset - offset;
!       pr_offset = (rounded_frame_size (d) + offset
  		   + SHMEDIA_REGS_STACK_ADJUST ());
      }
    else
!     pr_offset = rounded_frame_size (d);
  
    emit_insn (GEN_MOV (tmp, GEN_INT (pr_offset)));
    emit_insn (GEN_ADD3 (tmp, tmp, frame_pointer_rtx));
*************** initial_elimination_offset (from, to)
*** 6188,6196 ****
      {
        if (TARGET_SH5)
  	{
! 	  int i, n = total_saved_regs_space;
! 	  int align;
  	  int pr_reg = TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG;
  	  
  	  n += total_auto_space;
  
--- 6330,6339 ----
      {
        if (TARGET_SH5)
  	{
! 	  int n = total_saved_regs_space;
  	  int pr_reg = TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG;
+ 	  save_schedule schedule;
+ 	  save_entry *entry;
  	  
  	  n += total_auto_space;
  
*************** initial_elimination_offset (from, to)
*** 6200,6239 ****
  
  	  target_flags = copy_flags;
  
! 	  /* We loop twice: first, check 8-byte aligned registers,
! 	     that are stored in the higher addresses, that are known
! 	     to be aligned.  Then, check 32-bit registers that don't
! 	     need 8-byte alignment.  */
! 	  for (align = 1; align >= 0; align--)
! 	    for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
! 	      if (TEST_HARD_REG_BIT (live_regs_mask, i))
! 		{
! 		  enum machine_mode mode = REGISTER_NATURAL_MODE (i);
! 
! 		  if (mode == SFmode && (i % 2) == 1
! 		      && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
! 		      && TEST_HARD_REG_BIT (live_regs_mask, (i ^ 1)))
! 		    {
! 		      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;
! 
! 		  n -= GET_MODE_SIZE (mode);
! 
! 		  if (i == pr_reg)
! 		    {
! 		      target_flags = save_flags;
! 		      return n;
! 		    }
! 		}
! 
  	  abort ();
  	}
        else
--- 6343,6355 ----
  
  	  target_flags = copy_flags;
  
! 	  sh5_schedule_saves (&live_regs_mask, &schedule, n);
! 	  for (entry = &schedule.entries[1]; entry->mode != VOIDmode; entry++)
! 	    if (entry->reg == pr_reg)
! 	      {
! 		target_flags = save_flags;
! 		return entry->offset;
! 	      }
  	  abort ();
  	}
        else
*************** function_symbol (const char *name)
*** 8703,8708 ****
--- 8819,8842 ----
    rtx sym = gen_rtx_SYMBOL_REF (Pmode, name);
    SYMBOL_REF_FLAGS (sym) = SYMBOL_FLAG_FUNCTION;
    return sym;
+ }
+ 
+ /* Find the number of a general purpose register in S.  */
+ static int
+ scavenge_reg (HARD_REG_SET *s)
+ {
+   int r;
+   for (r = FIRST_GENERAL_REG; r <= LAST_GENERAL_REG; r++)
+     if (TEST_HARD_REG_BIT (*s, r))
+       return r;
+   return -1;
+ }
+ 
+ rtx
+ sh_get_pr_initial_val (void)
+ {
+   return
+     get_hard_reg_initial_val (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG);
  }
  
  #include "gt-sh.h"
Index: config/sh/sh.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.216
diff -p -r1.216 sh.h
*** config/sh/sh.h	3 Jul 2003 16:25:51 -0000	1.216
--- config/sh/sh.h	16 Jul 2003 21:38:35 -0000
*************** do {									\
*** 591,596 ****
--- 591,603 ----
  #define UNITS_PER_WORD	(TARGET_SHMEDIA ? 8 : 4)
  #define MIN_UNITS_PER_WORD 4
  
+ /* Scaling factor for Dwarf data offsets for CFI information.
+    The dwarf2out.c default would use -UNITS_PER_WORD, which is -8 for
+    SHmedia; however, since we do partial register saves for the registers
+    visible to SHcompact, and for target registers for SHMEDIA32, we have
+    to allow saves that are only 4-byte aligned.  */
+ #define DWARF_CIE_DATA_ALIGNMENT -4
+ 
  /* Width in bits of a pointer.
     See also the macro `Pmode' defined below.  */
  #define POINTER_SIZE  (TARGET_SHMEDIA64 ? 64 : 32)
*************** do {									\
*** 639,646 ****
  #define LOCAL_ALIGNMENT(TYPE, ALIGN) \
    ((GET_MODE_CLASS (TYPE_MODE (TYPE)) == MODE_COMPLEX_INT \
      || GET_MODE_CLASS (TYPE_MODE (TYPE)) == MODE_COMPLEX_FLOAT) \
!    ? MIN (BIGGEST_ALIGNMENT, GET_MODE_BITSIZE (TYPE_MODE (TYPE))) \
!    : ALIGN)
  
  /* Make arrays of chars word-aligned for the same reasons.  */
  #define DATA_ALIGNMENT(TYPE, ALIGN)		\
--- 646,653 ----
  #define LOCAL_ALIGNMENT(TYPE, ALIGN) \
    ((GET_MODE_CLASS (TYPE_MODE (TYPE)) == MODE_COMPLEX_INT \
      || GET_MODE_CLASS (TYPE_MODE (TYPE)) == MODE_COMPLEX_FLOAT) \
!    ? (unsigned) MIN (BIGGEST_ALIGNMENT, GET_MODE_BITSIZE (TYPE_MODE (TYPE))) \
!    : (unsigned) ALIGN)
  
  /* Make arrays of chars word-aligned for the same reasons.  */
  #define DATA_ALIGNMENT(TYPE, ALIGN)		\
*************** extern char sh_additional_register_names
*** 816,831 ****
  #define LAST_TARGET_REG  (FIRST_TARGET_REG + (TARGET_SHMEDIA ? 7 : -1))
  
  #define GENERAL_REGISTER_P(REGNO) \
!   IN_RANGE ((REGNO), FIRST_GENERAL_REG, LAST_GENERAL_REG)
  
  #define GENERAL_OR_AP_REGISTER_P(REGNO) \
    (GENERAL_REGISTER_P (REGNO) || ((REGNO) == AP_REG))
  
  #define FP_REGISTER_P(REGNO) \
!   ((REGNO) >= FIRST_FP_REG && (REGNO) <= LAST_FP_REG)
  
  #define XD_REGISTER_P(REGNO) \
!   ((REGNO) >= FIRST_XD_REG && (REGNO) <= LAST_XD_REG)
  
  #define FP_OR_XD_REGISTER_P(REGNO) \
    (FP_REGISTER_P (REGNO) || XD_REGISTER_P (REGNO))
--- 823,840 ----
  #define LAST_TARGET_REG  (FIRST_TARGET_REG + (TARGET_SHMEDIA ? 7 : -1))
  
  #define GENERAL_REGISTER_P(REGNO) \
!   IN_RANGE ((REGNO), \
! 	    (unsigned HOST_WIDE_INT) FIRST_GENERAL_REG, \
! 	    (unsigned HOST_WIDE_INT) LAST_GENERAL_REG)
  
  #define GENERAL_OR_AP_REGISTER_P(REGNO) \
    (GENERAL_REGISTER_P (REGNO) || ((REGNO) == AP_REG))
  
  #define FP_REGISTER_P(REGNO) \
!   ((int) (REGNO) >= FIRST_FP_REG && (int) (REGNO) <= LAST_FP_REG)
  
  #define XD_REGISTER_P(REGNO) \
!   ((int) (REGNO) >= FIRST_XD_REG && (int) (REGNO) <= LAST_XD_REG)
  
  #define FP_OR_XD_REGISTER_P(REGNO) \
    (FP_REGISTER_P (REGNO) || XD_REGISTER_P (REGNO))
*************** extern char sh_additional_register_names
*** 838,844 ****
     || (REGNO) == MACH_REG || (REGNO) == MACL_REG)
  
  #define TARGET_REGISTER_P(REGNO) \
!   ((REGNO) >= FIRST_TARGET_REG && (REGNO) <= LAST_TARGET_REG)
  
  #define SHMEDIA_REGISTER_P(REGNO) \
    (GENERAL_REGISTER_P (REGNO) || FP_REGISTER_P (REGNO) \
--- 847,853 ----
     || (REGNO) == MACH_REG || (REGNO) == MACL_REG)
  
  #define TARGET_REGISTER_P(REGNO) \
!   ((int) (REGNO) >= FIRST_TARGET_REG && (int) (REGNO) <= LAST_TARGET_REG)
  
  #define SHMEDIA_REGISTER_P(REGNO) \
    (GENERAL_REGISTER_P (REGNO) || FP_REGISTER_P (REGNO) \
*************** extern char sh_additional_register_names
*** 951,957 ****
    (TARGET_SHMEDIA32 \
     && GET_MODE_SIZE (MODE) > 4 \
     && (((REGNO) >= FIRST_GENERAL_REG + 10 \
!         && (REGNO) <= FIRST_GENERAL_REG + 14) \
         || (REGNO) == PR_MEDIA_REG))
  
  /* Return number of consecutive hard regs needed starting at reg REGNO
--- 960,967 ----
    (TARGET_SHMEDIA32 \
     && GET_MODE_SIZE (MODE) > 4 \
     && (((REGNO) >= FIRST_GENERAL_REG + 10 \
!         && (REGNO) <= FIRST_GENERAL_REG + 15) \
!        || TARGET_REGISTER_P (REGNO) \
         || (REGNO) == PR_MEDIA_REG))
  
  /* Return number of consecutive hard regs needed starting at reg REGNO
*************** extern char sh_additional_register_names
*** 1137,1143 ****
         ? (unsigned HOST_WIDE_INT) int_size_in_bytes (TYPE) \
         : GET_MODE_SIZE (TYPE_MODE (TYPE))) > 8) \
     : (TYPE_MODE (TYPE) == BLKmode \
!       || TARGET_HITACHI && TREE_CODE (TYPE) == RECORD_TYPE))
  
  /* Don't default to pcc-struct-return, because we have already specified
     exactly how to return structures in the RETURN_IN_MEMORY macro.  */
--- 1147,1153 ----
         ? (unsigned HOST_WIDE_INT) int_size_in_bytes (TYPE) \
         : GET_MODE_SIZE (TYPE_MODE (TYPE))) > 8) \
     : (TYPE_MODE (TYPE) == BLKmode \
!       || (TARGET_HITACHI && TREE_CODE (TYPE) == RECORD_TYPE)))
  
  /* Don't default to pcc-struct-return, because we have already specified
     exactly how to return structures in the RETURN_IN_MEMORY macro.  */
*************** enum reg_class
*** 1273,1279 ****
     reg number REGNO.  This could be a conditional expression
     or could index an array.  */
  
! extern int regno_reg_class[FIRST_PSEUDO_REGISTER];
  #define REGNO_REG_CLASS(REGNO) regno_reg_class[(REGNO)]
  
  /* When defined, the compiler allows registers explicitly used in the
--- 1283,1289 ----
     reg number REGNO.  This could be a conditional expression
     or could index an array.  */
  
! extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
  #define REGNO_REG_CLASS(REGNO) regno_reg_class[(REGNO)]
  
  /* When defined, the compiler allows registers explicitly used in the
*************** extern enum reg_class reg_class_from_let
*** 1363,1369 ****
  #define CONSTRAINT_LEN(C,STR) \
    (((C) == 'L' || (C) == 'O' || (C) == 'D' || (C) == 'T' || (C) == 'U' \
      || (C) == 'Y' \
!     || ((C) == 'I' && (((STR)[1] != '0' && (STR)[1] != '1') || ! isdigit ((STR)[2]))) \
      || ((C) == 'B' && ((STR)[1] != 's' || (STR)[2] != 'c')) \
      || ((C) == 'J' && ((STR)[1] != '1' || (STR)[2] != '6')) \
      || ((C) == 'K' && ((STR)[1] != '0' || (STR)[2] != '8')) \
--- 1373,1381 ----
  #define CONSTRAINT_LEN(C,STR) \
    (((C) == 'L' || (C) == 'O' || (C) == 'D' || (C) == 'T' || (C) == 'U' \
      || (C) == 'Y' \
!     || ((C) == 'I' \
!         && (((STR)[1] != '0' && (STR)[1] != '1') \
! 	    || (STR)[2] < '0' || (STR)[2] > '9')) \
      || ((C) == 'B' && ((STR)[1] != 's' || (STR)[2] != 'c')) \
      || ((C) == 'J' && ((STR)[1] != '1' || (STR)[2] != '6')) \
      || ((C) == 'K' && ((STR)[1] != '0' || (STR)[2] != '8')) \
*************** extern enum reg_class reg_class_from_let
*** 1667,1678 ****
     || (TARGET_SHMEDIA_FPU && (REGNO) == FIRST_FP_RET_REG))
  
  /* 1 if N is a possible register number for function argument passing.  */
  #define FUNCTION_ARG_REGNO_P(REGNO) \
!   (((REGNO) >= FIRST_PARM_REG && (REGNO) < (FIRST_PARM_REG		\
! 					    + NPARM_REGS (SImode)))	\
     || (TARGET_FPU_ANY                                                   \
!        && (REGNO) >= FIRST_FP_PARM_REG && (REGNO) < (FIRST_FP_PARM_REG	\
! 						     + NPARM_REGS (SFmode))))
  
  /* Define a data type for recording info about an argument list
     during the scan of that argument list.  This data type should
--- 1679,1693 ----
     || (TARGET_SHMEDIA_FPU && (REGNO) == FIRST_FP_RET_REG))
  
  /* 1 if N is a possible register number for function argument passing.  */
+ /* ??? There are some callers that pass REGNO as int, and others that pass
+    it as unsigned.  We get warnings unless we do casts everywhere.  */
  #define FUNCTION_ARG_REGNO_P(REGNO) \
!   (((unsigned) (REGNO) >= (unsigned) FIRST_PARM_REG			\
!     && (unsigned) (REGNO) < (unsigned) (FIRST_PARM_REG + NPARM_REGS (SImode)))\
     || (TARGET_FPU_ANY                                                   \
!        && (unsigned) (REGNO) >= (unsigned) FIRST_FP_PARM_REG		\
!        && (unsigned) (REGNO) < (unsigned) (FIRST_FP_PARM_REG		\
! 					   + NPARM_REGS (SFmode))))
  
  /* Define a data type for recording info about an argument list
     during the scan of that argument list.  This data type should
*************** struct sh_args {
*** 2057,2069 ****
  	     (VOIDmode,							\
  	      gen_rtx_REG (SFmode,					\
  			   BASE_ARG_REG (MODE)				\
! 			   + ROUND_REG ((CUM), (MODE)) ^ 1),		\
  	      const0_rtx)),						\
  	    (gen_rtx_EXPR_LIST						\
  	     (VOIDmode,							\
  	      gen_rtx_REG (SFmode,					\
  			   BASE_ARG_REG (MODE)				\
! 			   + (ROUND_REG ((CUM), (MODE)) + 1) ^ 1),	\
  	      GEN_INT (4)))))))						\
        : gen_rtx_REG ((MODE),						\
  		     ((BASE_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE))) \
--- 2072,2084 ----
  	     (VOIDmode,							\
  	      gen_rtx_REG (SFmode,					\
  			   BASE_ARG_REG (MODE)				\
! 			   + (ROUND_REG ((CUM), (MODE)) ^ 1)),		\
  	      const0_rtx)),						\
  	    (gen_rtx_EXPR_LIST						\
  	     (VOIDmode,							\
  	      gen_rtx_REG (SFmode,					\
  			   BASE_ARG_REG (MODE)				\
! 			   + ((ROUND_REG ((CUM), (MODE)) + 1) ^ 1)),	\
  	      GEN_INT (4)))))))						\
        : gen_rtx_REG ((MODE),						\
  		     ((BASE_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE))) \
*************** while (0)
*** 2311,2319 ****
     can ignore COUNT.  */
  
  #define RETURN_ADDR_RTX(COUNT, FRAME)	\
!   (((COUNT) == 0)				\
!    ? get_hard_reg_initial_val (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG) \
!    : (rtx) 0)
  
  /* A C expression whose value is RTL representing the location of the
     incoming return address at the beginning of any function, before the
--- 2326,2332 ----
     can ignore COUNT.  */
  
  #define RETURN_ADDR_RTX(COUNT, FRAME)	\
!   (((COUNT) == 0) ? sh_get_pr_initial_val () : (rtx) 0)
  
  /* A C expression whose value is RTL representing the location of the
     incoming return address at the beginning of any function, before the
*************** while (0)
*** 2322,2327 ****
--- 2335,2345 ----
     the stack.  */
  #define INCOMING_RETURN_ADDR_RTX \
    gen_rtx_REG (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG)
+ 
+ /* libstdc++-v3/libsupc++/eh_personality.cc:__gxx_personality_v0
+    can get confused by SHmedia return addresses when it does:
+    ip = _Unwind_GetIP (context) - 1;  */
+ #define RETURN_ADDR_OFFSET (TARGET_SH5 ? -1 : 0)
  
  /* Generate necessary RTL for __builtin_saveregs().  */
  #define EXPAND_BUILTIN_SAVEREGS() sh_builtin_saveregs ()
*************** while (0)
*** 3085,3102 ****
  
  #define SH_DBX_REGISTER_NUMBER(REGNO) \
    (GENERAL_REGISTER_P (REGNO) \
!    ? ((REGNO) - FIRST_GENERAL_REG) \
     : FP_REGISTER_P (REGNO) \
!    ? ((REGNO) - FIRST_FP_REG + (TARGET_SH5 ? (TARGET_SHCOMPACT ? 245 \
! 					      : 77) : 25)) \
     : XD_REGISTER_P (REGNO) \
!    ? ((REGNO) - FIRST_XD_REG + (TARGET_SH5 ? 289 : 87)) \
     : TARGET_REGISTER_P (REGNO) \
!    ? ((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 \
--- 3103,3120 ----
  
  #define SH_DBX_REGISTER_NUMBER(REGNO) \
    (GENERAL_REGISTER_P (REGNO) \
!    ? ((unsigned) (REGNO) - FIRST_GENERAL_REG) \
     : FP_REGISTER_P (REGNO) \
!    ? ((unsigned) (REGNO) - FIRST_FP_REG \
!       + (TARGET_SH5 ? (TARGET_SHCOMPACT ? 245 : 77) : 25)) \
     : XD_REGISTER_P (REGNO) \
!    ? ((unsigned) (REGNO) - FIRST_XD_REG + (TARGET_SH5 ? 289 : 87)) \
     : TARGET_REGISTER_P (REGNO) \
!    ? ((unsigned) (REGNO) - FIRST_TARGET_REG + 68) \
     : (REGNO) == PR_REG \
     ? (TARGET_SH5 ? 241 : 17) \
     : (REGNO) == PR_MEDIA_REG \
!    ? (TARGET_SH5 ? 18 : (unsigned) -1) \
     : (REGNO) == T_REG \
     ? (TARGET_SH5 ? 242 : 18) \
     : (REGNO) == GBR_REG \
*************** while (0)
*** 3107,3113 ****
     ? (TARGET_SH5 ? 240 : 21) \
     : (REGNO) == FPUL_REG \
     ? (TARGET_SH5 ? 244 : 23) \
!    : -1)
  
  /* This is how to output a reference to a symbol_ref.  On SH5,
     references to non-code symbols must be preceded by `datalabel'.  */
--- 3125,3131 ----
     ? (TARGET_SH5 ? 240 : 21) \
     : (REGNO) == FPUL_REG \
     ? (TARGET_SH5 ? 244 : 23) \
!    : (unsigned) -1)
  
  /* This is how to output a reference to a symbol_ref.  On SH5,
     references to non-code symbols must be preceded by `datalabel'.  */
*************** extern int rtx_equal_function_value_matt
*** 3449,3457 ****
    (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
--- 3467,3476 ----
    (TARGET_SH5 ? DWARF_FRAME_REGNUM (PR_MEDIA_REG) : DWARF_FRAME_REGNUM (PR_REG))
  
  #define EH_RETURN_DATA_REGNO(N)	\
!   ((N) < 4 ? (N) + (TARGET_SH5 ? 2U : 4U) : INVALID_REGNUM)
  
! #define EH_RETURN_STACKADJ_REGNO STATIC_CHAIN_REGNUM
! #define EH_RETURN_STACKADJ_RTX	gen_rtx_REG (Pmode, EH_RETURN_STACKADJ_REGNO)
  
  #if (defined CRT_BEGIN || defined CRT_END) && ! __SHMEDIA__
  /* SH constant pool breaks the devices in crtstuff.c to control section
Index: config/sh/sh.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.md,v
retrieving revision 1.153
diff -p -r1.153 sh.md
*** config/sh/sh.md	3 Jul 2003 16:25:51 -0000	1.153
--- config/sh/sh.md	16 Jul 2003 21:38:35 -0000
***************
*** 2052,2058 ****
  "
  {
    enum machine_mode inmode = GET_MODE (operands[1]);
!   int regno, offset = 0;
  
    if (GET_CODE (operands[0]) == SUBREG)
      {
--- 2052,2058 ----
  "
  {
    enum machine_mode inmode = GET_MODE (operands[1]);
!   int offset = 0;
  
    if (GET_CODE (operands[0]) == SUBREG)
      {
*************** mov.l\\t1f,r0\\n\\
*** 7247,7252 ****
--- 7247,7254 ----
      {
        rtx r18 = gen_rtx_REG (DImode, PR_MEDIA_REG);
  
+       if (! call_used_regs[TR0_REG] || fixed_regs[TR0_REG])
+ 	abort ();
        tr_regno = TR0_REG;
        tr = gen_rtx_REG (DImode, tr_regno);
        emit_move_insn (tr, r18);


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