OSDN Git Service

* config/sh/sh.c (sh_use_dfa_interface): Add TARGET_SH1.
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.c
index 425ab4c..d996ec4 100644 (file)
@@ -200,7 +200,7 @@ static int branch_dest (rtx);
 static void force_into (rtx, rtx);
 static void print_slot (rtx);
 static rtx add_constant (rtx, enum machine_mode, rtx);
-static void dump_table (rtx);
+static void dump_table (rtx, rtx);
 static int hi_const (rtx);
 static int broken_move (rtx);
 static int mova_p (rtx);
@@ -272,7 +272,6 @@ struct save_schedule_s;
 static struct save_entry_s *sh5_schedule_saves (HARD_REG_SET *,
                                                struct save_schedule_s *, int);
 
-static bool sh_promote_prototypes (tree);
 static rtx sh_struct_value_rtx (tree, int);
 static bool sh_return_in_memory (tree, tree);
 static rtx sh_builtin_saveregs (void);
@@ -339,7 +338,7 @@ static tree sh_build_builtin_va_list (void);
    TARGET_SCHED_INIT_GLOBAL: Added a new target hook in the generic
    scheduler; it is called inside the sched_init function just after
    find_insn_reg_weights function call. It is used to calculate the SImode
-   and SFmode weights of insns of basic blocks; much similiar to what
+   and SFmode weights of insns of basic blocks; much similar to what
    find_insn_reg_weights does. 
    TARGET_SCHED_FINISH_GLOBAL: Corresponding cleanup hook.
 
@@ -944,13 +943,13 @@ prepare_move_operands (rtx operands[], enum machine_mode mode)
            {
            case TLS_MODEL_GLOBAL_DYNAMIC:
              tga_ret = gen_rtx_REG (Pmode, R0_REG);
-             emit_insn (gen_tls_global_dynamic (tga_ret, op1));
+             emit_call_insn (gen_tls_global_dynamic (tga_ret, op1));
              op1 = tga_ret;
              break;
 
            case TLS_MODEL_LOCAL_DYNAMIC:
              tga_ret = gen_rtx_REG (Pmode, R0_REG);
-             emit_insn (gen_tls_local_dynamic (tga_ret, op1));
+             emit_call_insn (gen_tls_local_dynamic (tga_ret, op1));
 
              tmp = gen_reg_rtx (Pmode);
              emit_move_insn (tmp, tga_ret);
@@ -2757,11 +2756,16 @@ add_constant (rtx x, enum machine_mode mode, rtx last_value)
   return lab;
 }
 
-/* Output the literal table.  */
+/* Output the literal table.  START, if nonzero, is the first instruction
+   this table is needed for, and also indicates that there is at least one
+   casesi_worker_2 instruction; We have to emit the operand3 labels from
+   these insns at a 4-byte  aligned position.  BARRIER is the barrier
+   after which we are to place the table.  */
 
 static void
-dump_table (rtx scan)
+dump_table (rtx start, rtx barrier)
 {
+  rtx scan = barrier;
   int i;
   int need_align = 1;
   rtx lab, ref;
@@ -2796,6 +2800,20 @@ dump_table (rtx scan)
 
   need_align = 1;
 
+  if (start)
+    {
+      scan = emit_insn_after (gen_align_4 (), scan);
+      need_align = 0;
+      for (; start != barrier; start = NEXT_INSN (start))
+       if (GET_CODE (start) == INSN
+           && recog_memoized (start) == CODE_FOR_casesi_worker_2)
+         {
+           rtx src = SET_SRC (XVECEXP (PATTERN (start), 0, 0));
+           rtx lab = XEXP (XVECEXP (src, 0, 3), 0);
+
+           scan = emit_label_after (lab, scan);
+         }
+    }
   if (TARGET_FMOVD && TARGET_ALIGN_DOUBLE && have_df)
     {
       rtx align_insn = NULL_RTX;
@@ -2996,6 +3014,46 @@ mova_p (rtx insn)
          && GET_CODE (XVECEXP (SET_SRC (PATTERN (insn)), 0, 0)) == LABEL_REF);
 }
 
+/* Fix up a mova from a switch that went out of range.  */
+static void
+fixup_mova (rtx mova)
+{
+  if (! flag_pic)
+    {
+      SET_SRC (PATTERN (mova)) = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
+      INSN_CODE (mova) = -1;
+    }
+  else
+    {
+      rtx worker = mova;
+      rtx lab = gen_label_rtx ();
+      rtx wpat, wpat0, wpat1, wsrc, diff;
+
+      do
+       {
+         worker = NEXT_INSN (worker);
+         if (! worker
+             || GET_CODE (worker) == CODE_LABEL
+             || GET_CODE (worker) == JUMP_INSN)
+           abort ();
+       } while (recog_memoized (worker) != CODE_FOR_casesi_worker_1);
+      wpat = PATTERN (worker);
+      wpat0 = XVECEXP (wpat, 0, 0);
+      wpat1 = XVECEXP (wpat, 0, 1);
+      wsrc = SET_SRC (wpat0);
+      PATTERN (worker) = (gen_casesi_worker_2
+                         (SET_DEST (wpat0), XVECEXP (wsrc, 0, 1),
+                          XEXP (XVECEXP (wsrc, 0, 2), 0), lab,
+                          XEXP (wpat1, 0)));
+      INSN_CODE (worker) = -1;
+      diff = gen_rtx_MINUS (Pmode, XVECEXP (SET_SRC (PATTERN (mova)), 0, 0),
+                           gen_rtx_LABEL_REF (Pmode, lab));
+      diff = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, diff), UNSPEC_PIC);
+      SET_SRC (PATTERN (mova)) = gen_rtx_CONST (Pmode, diff);
+      INSN_CODE (mova) = -1;
+    }
+}
+
 /* Find the last barrier from insn FROM which is close enough to hold the
    constant pool.  If we can't find one, then create one near the end of
    the range.  */
@@ -3187,8 +3245,7 @@ find_barrier (int num_mova, rtx mova, rtx from)
        {
          /* Try as we might, the leading mova is out of range.  Change
             it into a load (which will become a pcload) and retry.  */
-         SET_SRC (PATTERN (mova)) = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
-         INSN_CODE (mova) = -1;
+         fixup_mova (mova);
          return find_barrier (0, 0, mova);
        }
       else
@@ -3514,7 +3571,7 @@ gen_block_redirect (rtx jump, int addr, int need_block)
          if (INSN_DELETED_P (scan))
            continue;
          code = GET_CODE (scan);
-         if (GET_RTX_CLASS (code) == 'i')
+         if (INSN_P (scan))
            {
              used |= regs_used (PATTERN (scan), 0);
              if (code == CALL_INSN)
@@ -4100,7 +4157,20 @@ sh_reorg (void)
     {
       if (mova_p (insn))
        {
-         if (! num_mova++)
+         /* ??? basic block reordering can move a switch table dispatch
+            below the switch table.  Check if that has happened.
+            We only have the addresses available when optimizing; but then,
+            this check shouldn't be needed when not optimizing.  */
+         rtx label_ref = XVECEXP (SET_SRC (PATTERN (insn)), 0, 0);
+         if (optimize
+             && (INSN_ADDRESSES (INSN_UID (insn))
+                 > INSN_ADDRESSES (INSN_UID (XEXP (label_ref, 0)))))
+           {
+             /* Change the mova into a load.
+                broken_move will then return true for it.  */
+             fixup_mova (insn);
+           }
+         else if (! num_mova++)
            mova = insn;
        }
       else if (GET_CODE (insn) == JUMP_INSN
@@ -4125,19 +4195,20 @@ sh_reorg (void)
            {
              /* Change the mova into a load, and restart scanning
                 there.  broken_move will then return true for mova.  */
-             SET_SRC (PATTERN (mova))
-               = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
-             INSN_CODE (mova) = -1;
+             fixup_mova (mova);
              insn = mova;
            }
        }
-      if (broken_move (insn))
+      if (broken_move (insn)
+         || (GET_CODE (insn) == INSN
+             && recog_memoized (insn) == CODE_FOR_casesi_worker_2))
        {
          rtx scan;
          /* Scan ahead looking for a barrier to stick the constant table
             behind.  */
          rtx barrier = find_barrier (num_mova, mova, insn);
          rtx last_float_move = NULL_RTX, last_float = 0, *last_float_addr = NULL;
+         int need_aligned_label = 0;
 
          if (num_mova && ! mova_p (mova))
            {
@@ -4151,6 +4222,9 @@ sh_reorg (void)
            {
              if (GET_CODE (scan) == CODE_LABEL)
                last_float = 0;
+             if (GET_CODE (scan) == INSN
+                 && recog_memoized (scan) == CODE_FOR_casesi_worker_2)
+               need_aligned_label = 1;
              if (broken_move (scan))
                {
                  rtx *patp = &PATTERN (scan), pat = *patp;
@@ -4181,7 +4255,6 @@ sh_reorg (void)
                        }
                      dst = gen_rtx_REG (HImode, REGNO (dst) + offset);
                    }
-
                  if (GET_CODE (dst) == REG && FP_ANY_REGISTER_P (REGNO (dst)))
                    {
                      /* This must be an insn that clobbers r0.  */
@@ -4258,7 +4331,7 @@ sh_reorg (void)
                  INSN_CODE (scan) = -1;
                }
            }
-         dump_table (barrier);
+         dump_table (need_aligned_label ? insn : 0, barrier);
          insn = barrier;
        }
     }
@@ -4627,12 +4700,11 @@ output_jump_label_table (void)
 /* Number of bytes pushed for anonymous args, used to pass information
    between expand_prologue and expand_epilogue.  */
 
-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.  */
+   for an epilogue and a negative value means that it's for a sibcall
+   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,
@@ -4667,17 +4739,27 @@ output_stack_adjust (int size, rtx reg, int epilogue_p,
          /* 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
+         if (epilogue_p < 0
+             || current_function_interrupt
              || ! call_used_regs[temp] || fixed_regs[temp])
            temp = -1;
-         if (temp < 0 && ! current_function_interrupt)
+         if (temp < 0 && ! current_function_interrupt
+             && (TARGET_SHMEDIA || epilogue_p >= 0))
            {
              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)
+             if (epilogue_p > 0)
                {
-                 for (i = 0; i < HARD_REGNO_NREGS (FIRST_RET_REG, DImode); i++)
+                 int nreg = 0;
+                 if (current_function_return_rtx)
+                   {
+                     enum machine_mode mode;
+                     mode = GET_MODE (current_function_return_rtx);
+                     if (BASE_RETURN_VALUE_REG (mode) == FIRST_RET_REG)
+                       nreg = HARD_REGNO_NREGS (FIRST_RET_REG, mode);
+                   }
+                 for (i = 0; i < nreg; i++)
                    CLEAR_HARD_REG_BIT (temps, FIRST_RET_REG + i);
                  if (current_function_calls_eh_return)
                    {
@@ -4686,12 +4768,15 @@ output_stack_adjust (int size, rtx reg, int epilogue_p,
                        CLEAR_HARD_REG_BIT (temps, EH_RETURN_DATA_REGNO (i));
                    }
                }
-             else
+             if (TARGET_SHMEDIA && epilogue_p < 0)
+               for (i = FIRST_TARGET_REG; i <= LAST_TARGET_REG; i++)
+                 CLEAR_HARD_REG_BIT (temps, i);
+             if (epilogue_p <= 0)
                {
                  for (i = FIRST_PARM_REG;
                       i < FIRST_PARM_REG + NPARM_REGS (SImode); i++)
                    CLEAR_HARD_REG_BIT (temps, i);
-                 if (current_function_needs_context)
+                 if (cfun->static_chain_decl != NULL)
                    CLEAR_HARD_REG_BIT (temps, STATIC_CHAIN_REGNUM);
                }
              temp = scavenge_reg (&temps);
@@ -4699,7 +4784,55 @@ output_stack_adjust (int size, rtx reg, int epilogue_p,
          if (temp < 0 && live_regs_mask)
            temp = scavenge_reg (live_regs_mask);
          if (temp < 0)
-           abort ();
+           {
+             /* If we reached here, the most likely case is the (sibcall)
+                epilogue for non SHmedia.  Put a special push/pop sequence
+                for such case as the last resort.  This looks lengthy but
+                would not be problem because it seems to be very rare.  */
+             if (! TARGET_SHMEDIA && epilogue_p)
+               {
+                 rtx adj_reg, tmp_reg, mem;
+
+                 /* ??? There is still the slight possibility that r4 or r5
+                    have been reserved as fixed registers or assigned as
+                    global registers, and they change during an interrupt.
+                    There are possible ways to handle this:
+                    - If we are adjusting the frame pointer (r14), we can do
+                      with a single temp register and an ordinary push / pop
+                      on the stack.
+                    - Grab any call-used or call-saved registers (i.e. not
+                      fixed or globals) for the temps we need.  We might
+                      also grab r14 if we are adjusting the stack pointer.
+                      If we can't find enough available registers, issue
+                      a diagnostic and abort - the user must have reserved
+                      way too many registers.
+                    But since all this is rather unlikely to happen and
+                    would require extra testing, we just abort if r4 / r5
+                    are not available.  */
+                 if (fixed_regs[4] || fixed_regs[5]
+                     || global_regs[4] || global_regs[5])
+                   abort ();
+
+                 adj_reg = gen_rtx_REG (GET_MODE (reg), 4);
+                 tmp_reg = gen_rtx_REG (GET_MODE (reg), 5);
+                 emit_move_insn (gen_rtx_MEM (Pmode, reg), adj_reg);
+                 emit_insn (GEN_MOV (adj_reg, GEN_INT (size)));
+                 emit_insn (GEN_ADD3 (adj_reg, adj_reg, reg));
+                 mem = gen_rtx_MEM (Pmode, gen_rtx_PRE_DEC (Pmode, adj_reg));
+                 emit_move_insn (mem, tmp_reg);
+                 emit_move_insn (tmp_reg, gen_rtx_MEM (Pmode, reg));
+                 mem = gen_rtx_MEM (Pmode, gen_rtx_PRE_DEC (Pmode, adj_reg));
+                 emit_move_insn (mem, tmp_reg);
+                 emit_move_insn (reg, adj_reg);
+                 mem = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, reg));
+                 emit_move_insn (adj_reg, mem);
+                 mem = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, reg));
+                 emit_move_insn (tmp_reg, mem);
+                 return;
+               }
+             else
+               abort ();
+           }
          const_reg = gen_rtx_REG (GET_MODE (reg), temp);
 
          /* If SIZE is negative, subtract the positive value.
@@ -5100,7 +5233,7 @@ sh5_schedule_saves (HARD_REG_SET *live_regs_mask, save_schedule *schedule,
       if (call_used_regs[i] && ! fixed_regs[i] && i != PR_MEDIA_REG
          && ! FUNCTION_ARG_REGNO_P (i)
          && i != FIRST_RET_REG
-         && ! (current_function_needs_context && i == STATIC_CHAIN_REGNUM)
+         && ! (cfun->static_chain_decl != NULL && i == STATIC_CHAIN_REGNUM)
          && ! (current_function_calls_eh_return
                && (i == EH_RETURN_STACKADJ_REGNO
                    || ((unsigned) i <= EH_RETURN_DATA_REGNO (0)
@@ -5186,17 +5319,21 @@ sh_expand_prologue (void)
   int d, i;
   int d_rounding = 0;
   int save_flags = target_flags;
+  int pretend_args;
 
   current_function_interrupt = sh_cfun_interrupt_handler_p ();
 
   /* We have pretend args if we had an object sent partially in registers
      and partially on the stack, e.g. a large structure.  */
-  output_stack_adjust (-current_function_pretend_args_size
+  pretend_args = current_function_pretend_args_size;
+  if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl)
+      && (NPARM_REGS(SImode)
+         > current_function_args_info.arg_count[(int) SH_ARG_INT]))
+    pretend_args = 0;
+  output_stack_adjust (-pretend_args
                       - current_function_args_info.stack_regs * 8,
                       stack_pointer_rtx, 0, NULL);
 
-  extra_push = 0;
-
   if (TARGET_SHCOMPACT && flag_pic && current_function_args_info.call_cookie)
     /* We're going to use the PIC register to load the address of the
        incoming-argument decoder and/or of the return trampoline from
@@ -5253,9 +5390,7 @@ sh_expand_prologue (void)
   /* Emit the code for SETUP_VARARGS.  */
   if (current_function_stdarg)
     {
-      /* This is not used by the SH2E calling convention  */
-      if (TARGET_SH1 && ! TARGET_SH2E && ! TARGET_SH5
-         && ! (TARGET_HITACHI || sh_cfun_attr_renesas_p ()))
+      if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl))
        {
          /* Push arg regs as if they'd been provided by caller in stack.  */
          for (i = 0; i < NPARM_REGS(SImode); i++)
@@ -5269,7 +5404,6 @@ sh_expand_prologue (void)
                break;
              insn = push (rn);
              RTX_FRAME_RELATED_P (insn) = 0;
-             extra_push += 4;
            }
        }
     }
@@ -5539,7 +5673,7 @@ sh_expand_prologue (void)
 }
 
 void
-sh_expand_epilogue (void)
+sh_expand_epilogue (bool sibcall_p)
 {
   HARD_REG_SET live_regs_mask;
   int d, i;
@@ -5548,6 +5682,7 @@ sh_expand_epilogue (void)
   int save_flags = target_flags;
   int frame_size, save_size;
   int fpscr_deferred = 0;
+  int e = sibcall_p ? -1 : 1;
 
   d = calc_live_regs (&live_regs_mask);
 
@@ -5582,7 +5717,7 @@ sh_expand_epilogue (void)
 
   if (frame_pointer_needed)
     {
-      output_stack_adjust (frame_size, frame_pointer_rtx, 1, &live_regs_mask);
+      output_stack_adjust (frame_size, frame_pointer_rtx, e, &live_regs_mask);
 
       /* We must avoid moving the stack pointer adjustment past code
         which reads from the local frame, else an interrupt could
@@ -5598,7 +5733,7 @@ sh_expand_epilogue (void)
         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);
+      output_stack_adjust (frame_size, stack_pointer_rtx, e, &live_regs_mask);
     }
 
   if (SHMEDIA_REGS_STACK_ADJUST ())
@@ -5768,10 +5903,10 @@ sh_expand_epilogue (void)
     emit_insn (gen_toggle_sz ());
   target_flags = save_flags;
 
-  output_stack_adjust (extra_push + current_function_pretend_args_size
+  output_stack_adjust (current_function_pretend_args_size
                       + save_size + d_rounding
                       + current_function_args_info.stack_regs * 8,
-                      stack_pointer_rtx, 1, NULL);
+                      stack_pointer_rtx, e, NULL);
 
   if (current_function_calls_eh_return)
     emit_insn (GEN_ADD3 (stack_pointer_rtx, stack_pointer_rtx,
@@ -5799,7 +5934,7 @@ sh_need_epilogue (void)
       rtx epilogue;
 
       start_sequence ();
-      sh_expand_epilogue ();
+      sh_expand_epilogue (0);
       epilogue = get_insns ();
       end_sequence ();
       sh_need_epilogue_known = (epilogue == NULL ? -1 : 1);
@@ -6101,14 +6236,16 @@ sh_va_start (tree valist, rtx nextarg)
   f_next_fp_limit = TREE_CHAIN (f_next_fp);
   f_next_stack = TREE_CHAIN (f_next_fp_limit);
 
-  next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o);
+  next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o,
+                 NULL_TREE);
   next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
-                       valist, f_next_o_limit);
-  next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp), valist, f_next_fp);
+                       valist, f_next_o_limit, NULL_TREE);
+  next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp), valist, f_next_fp,
+                  NULL_TREE);
   next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
-                        valist, f_next_fp_limit);
+                        valist, f_next_fp_limit, NULL_TREE);
   next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
-                     valist, f_next_stack);
+                     valist, f_next_stack, NULL_TREE);
 
   /* Call __builtin_saveregs.  */
   u = make_tree (ptr_type_node, expand_builtin_saveregs ());
@@ -6181,15 +6318,16 @@ sh_va_arg (tree valist, tree type)
       f_next_fp_limit = TREE_CHAIN (f_next_fp);
       f_next_stack = TREE_CHAIN (f_next_fp_limit);
 
-      next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o);
+      next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o,
+                     NULL_TREE);
       next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
-                           valist, f_next_o_limit);
+                           valist, f_next_o_limit, NULL_TREE);
       next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp),
-                      valist, f_next_fp);
+                      valist, f_next_fp, NULL_TREE);
       next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
-                            valist, f_next_fp_limit);
+                            valist, f_next_fp_limit, NULL_TREE);
       next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
-                         valist, f_next_stack);
+                         valist, f_next_stack, NULL_TREE);
 
       /* Structures with a single member with a distinct mode are passed
         like their member.  This is relevant if the latter has a REAL_TYPE
@@ -6352,7 +6490,7 @@ sh_va_arg (tree valist, tree type)
   return result;
 }
 
-static bool
+bool
 sh_promote_prototypes (tree type)
 {
   if (TARGET_HITACHI)
@@ -6650,14 +6788,26 @@ sh_return_in_memory (tree type, tree fndecl)
    later.  Fortunately, we already have two flags that are part of struct
    function that tell if a function uses varargs or stdarg.  */
 static void
-sh_setup_incoming_varargs (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
-                          enum machine_mode mode ATTRIBUTE_UNUSED,
-                          tree type ATTRIBUTE_UNUSED,
-                          int *pretend_arg_size ATTRIBUTE_UNUSED,
+sh_setup_incoming_varargs (CUMULATIVE_ARGS *ca,
+                          enum machine_mode mode,
+                          tree type,
+                          int *pretend_arg_size,
                           int second_time ATTRIBUTE_UNUSED)
 {
   if (! current_function_stdarg)
     abort ();
+  if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl))
+    {
+      int named_parm_regs, anon_parm_regs;
+
+      named_parm_regs = (ROUND_REG (*ca, mode)
+                        + (mode == BLKmode
+                           ? ROUND_ADVANCE (int_size_in_bytes (type))
+                           : ROUND_ADVANCE (GET_MODE_SIZE (mode))));
+      anon_parm_regs = NPARM_REGS (SImode) - named_parm_regs;
+      if (anon_parm_regs > 0)
+       *pretend_arg_size = anon_parm_regs * 4;
+    }
 }
 
 static bool
@@ -7667,6 +7817,10 @@ reg_unused_after (rtx reg, rtx insn)
 
   while ((insn = NEXT_INSN (insn)))
     {
+      rtx set;
+      if (!INSN_P (insn))
+       continue;
+
       code = GET_CODE (insn);
 
 #if 0
@@ -7723,17 +7877,14 @@ reg_unused_after (rtx reg, rtx insn)
          else if (code == JUMP_INSN)
            return 0;
        }
-      else if (GET_RTX_CLASS (code) == 'i')
-       {
-         rtx set = single_set (insn);
 
-         if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
-           return 0;
-         if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
-           return GET_CODE (SET_DEST (set)) != MEM;
-         if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
-           return 0;
-       }
+      set = single_set (insn);
+      if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
+       return 0;
+      if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
+       return GET_CODE (SET_DEST (set)) != MEM;
+      if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
+       return 0;
 
       if (code == CALL_INSN && call_used_regs[REGNO (reg)])
        return 1;
@@ -8337,11 +8488,13 @@ sh_pr_n_sets (void)
 }
 
 /* This Function returns nonzero if the DFA based scheduler interface
-   is to be used.  At present this is supported for the SH4 only.  */
+   is to be used.  At present this is only supported properly for the SH4.
+   For the SH1 the current DFA model is just the converted form of the old
+   pipeline model description.  */
 static int
 sh_use_dfa_interface (void)
 {
-  if (TARGET_HARD_SH4)
+  if (TARGET_SH1)
     return 1;
   else
     return 0;
@@ -8562,7 +8715,7 @@ sh_md_init (FILE *dump ATTRIBUTE_UNUSED,
    functions that already have high pressure on r0. */
 #define R0_MAX_LIFE_REGIONS 2
 #define R0_MAX_LIVE_LENGTH 12
-/* Register Pressure threshols for SImode and SFmode registers.  */
+/* Register Pressure thresholds for SImode and SFmode registers.  */
 #define SIMODE_MAX_WEIGHT 5
 #define SFMODE_MAX_WEIGHT 10
 
@@ -9343,6 +9496,7 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   epilogue_completed = 1;
   no_new_pseudos = 1;
   current_function_uses_only_leaf_regs = 1;
+  reset_block_changes ();
 
   emit_note (NOTE_INSN_PROLOGUE_END);
 
@@ -9463,7 +9617,7 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   if (optimize > 0 && flag_schedule_insns_after_reload)
     {
       find_basic_blocks (insns, max_reg_num (), dump_file);
-      life_analysis (insns, dump_file, PROP_FINAL);
+      life_analysis (dump_file, PROP_FINAL);
 
       split_all_insns (1);
 
@@ -9482,7 +9636,7 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   if (optimize > 0 && flag_schedule_insns_after_reload)
     {
       /* Release all memory allocated by flow.  */
-      free_basic_block_vars (0);
+      free_basic_block_vars ();
 
       /* Release all memory held by regsets now.  */
       regset_release_memory ();