]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/h8300/h8300.c
Update copyright years.
[thirdparty/gcc.git] / gcc / config / h8300 / h8300.c
index 1eef7bf796b1d9c38ec883aae5c76cb99e78cbc2..6c84b0abea7eca52904a17aca1d57114e61c304d 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines for insn-output.c for Renesas H8/300.
-   Copyright (C) 1992-2015 Free Software Foundation, Inc.
+   Copyright (C) 1992-2020 Free Software Foundation, Inc.
    Contributed by Steve Chamberlain (sac@cygnus.com),
    Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
 
@@ -19,44 +19,36 @@ You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
 #include "backend.h"
-#include "cfghooks.h"
-#include "tree.h"
+#include "target.h"
 #include "rtl.h"
+#include "tree.h"
 #include "df.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "optabs.h"
+#include "regs.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "diagnostic-core.h"
 #include "alias.h"
 #include "stor-layout.h"
 #include "varasm.h"
 #include "calls.h"
-#include "stringpool.h"
-#include "regs.h"
-#include "insn-config.h"
 #include "conditions.h"
 #include "output.h"
 #include "insn-attr.h"
 #include "flags.h"
-#include "recog.h"
-#include "expmed.h"
-#include "dojump.h"
 #include "explow.h"
-#include "emit-rtl.h"
-#include "stmt.h"
 #include "expr.h"
-#include "insn-codes.h"
-#include "optabs.h"
-#include "diagnostic-core.h"
-#include "c-family/c-pragma.h" /* ??? */
-#include "tm_p.h"
 #include "tm-constrs.h"
-#include "target.h"
-#include "cfgrtl.h"
-#include "cfganal.h"
-#include "lcm.h"
-#include "cfgbuild.h"
-#include "cfgcleanup.h"
 #include "builtins.h"
 
 /* This file should be included last.  */
@@ -107,7 +99,7 @@ static unsigned int h8300_asm_insn_count (const char *);
 static tree h8300_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
 static tree h8300_handle_eightbit_data_attribute (tree *, tree, tree, int, bool *);
 static tree h8300_handle_tiny_data_attribute (tree *, tree, tree, int, bool *);
-static void h8300_print_operand_address (FILE *, rtx);
+static void h8300_print_operand_address (FILE *, machine_mode, rtx);
 static void h8300_print_operand (FILE *, rtx, int);
 static bool h8300_print_operand_punct_valid_p (unsigned char code);
 #ifndef OBJECT_FORMAT_ELF
@@ -334,7 +326,7 @@ h8300_option_override (void)
 #ifndef OBJECT_FORMAT_ELF
   if (TARGET_H8300SX)
     {
-      error ("-msx is not supported in coff");
+      error ("%<-msx%> is not supported in coff");
       target_flags |= MASK_H8300S;
     }
 #endif
@@ -356,44 +348,44 @@ h8300_option_override (void)
 
   if (!TARGET_H8300S && TARGET_MAC)
     {
-      error ("-ms2600 is used without -ms");
+      error ("%<-ms2600%> is used without %<-ms%>");
       target_flags |= MASK_H8300S_1;
     }
 
   if (TARGET_H8300 && TARGET_NORMAL_MODE)
     {
-      error ("-mn is used without -mh or -ms or -msx");
+      error ("%<-mn%> is used without %<-mh%> or %<-ms%> or %<-msx%>");
       target_flags ^= MASK_NORMAL_MODE;
     }
 
   if (! TARGET_H8300S &&  TARGET_EXR)
     {
-      error ("-mexr is used without -ms");
+      error ("%<-mexr%> is used without %<-ms%>");
       target_flags |= MASK_H8300S_1;
     }
 
   if (TARGET_H8300 && TARGET_INT32)
    {
-      error ("-mint32 is not supported for H8300 and H8300L targets");
+      error ("%<-mint32%> is not supported for H8300 and H8300L targets");
       target_flags ^= MASK_INT32;
    }
 
  if ((!TARGET_H8300S  &&  TARGET_EXR) && (!TARGET_H8300SX && TARGET_EXR))
    {
-      error ("-mexr is used without -ms or -msx");
+      error ("%<-mexr%> is used without %<-ms%> or %<-msx%>");
       target_flags |= MASK_H8300S_1;
    }
 
  if ((!TARGET_H8300S  &&  TARGET_NEXR) && (!TARGET_H8300SX && TARGET_NEXR))
    {
-      warning (OPT_mno_exr, "-mno-exr valid only with -ms or -msx    \
-               - Option ignored!");
+      warning (OPT_mno_exr, "%<-mno-exr%> valid only with %<-ms%> or "
+              "%<-msx%> - Option ignored!");
    }
 
 #ifdef H8300_LINUX 
  if ((TARGET_NORMAL_MODE))
    {
-      error ("-mn is not supported for linux targets");
+      error ("%<-mn%> is not supported for linux targets");
       target_flags ^= MASK_NORMAL_MODE;
    }
 #endif
@@ -493,7 +485,8 @@ byte_reg (rtx x, int b)
    && ! TREE_THIS_VOLATILE (current_function_decl)                     \
    && (h8300_saveall_function_p (current_function_decl)                        \
        /* Save any call saved register that was used.  */              \
-       || (df_regs_ever_live_p (regno) && !call_used_regs[regno])      \
+       || (df_regs_ever_live_p (regno)                                 \
+          && !call_used_or_fixed_reg_p (regno))                        \
        /* Save the frame pointer if it was used.  */                   \
        || (regno == HARD_FRAME_POINTER_REGNUM && df_regs_ever_live_p (regno)) \
        /* Save any register used in an interrupt handler.  */          \
@@ -502,7 +495,7 @@ byte_reg (rtx x, int b)
        /* Save call clobbered registers in non-leaf interrupt          \
          handlers.  */                                                 \
        || (h8300_current_function_interrupt_function_p ()              \
-          && call_used_regs[regno]                                     \
+          && call_used_or_fixed_reg_p (regno)                          \
           && !crtl->is_leaf)))
 
 /* We use this to wrap all emitted insns in the prologue.  */
@@ -873,15 +866,15 @@ h8300_expand_prologue (void)
          if (TARGET_H8300S)
            {
              /* See how many registers we can push at the same time.  */
-             if ((!TARGET_H8300SX || (regno & 3) == 0)
+             if ((TARGET_H8300SX || (regno & 3) == 0)
                  && ((saved_regs >> regno) & 0x0f) == 0x0f)
                n_regs = 4;
 
-             else if ((!TARGET_H8300SX || (regno & 3) == 0)
+             else if ((TARGET_H8300SX || (regno & 3) == 0)
                       && ((saved_regs >> regno) & 0x07) == 0x07)
                n_regs = 3;
 
-             else if ((!TARGET_H8300SX || (regno & 1) == 0)
+             else if ((TARGET_H8300SX || (regno & 1) == 0)
                       && ((saved_regs >> regno) & 0x03) == 0x03)
                n_regs = 2;
            }
@@ -1043,11 +1036,11 @@ split_adds_subs (machine_mode mode, rtx *operands)
 
   switch (mode)
     {
-    case HImode:
+    case E_HImode:
       gen_add = gen_addhi3;
       break;
 
-    case SImode:
+    case E_SImode:
       gen_add = gen_addsi3;
       break;
 
@@ -1089,17 +1082,16 @@ h8300_pr_saveall (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
   pragma_saveall = 1;
 }
 
-/* If the next function argument with MODE and TYPE is to be passed in
-   a register, return a reg RTX for the hard register in which to pass
-   the argument.  CUM represents the state after the last argument.
-   If the argument is to be pushed, NULL_RTX is returned.
+/* If the next function argument ARG is to be passed in a register, return
+   a reg RTX for the hard register in which to pass the argument.  CUM
+   represents the state after the last argument.  If the argument is to
+   be pushed, NULL_RTX is returned.
 
    On the H8/300 all normal args are pushed, unless -mquickcall in which
    case the first 3 arguments are passed in registers.  */
 
 static rtx
-h8300_function_arg (cumulative_args_t cum_v, machine_mode mode,
-                   const_tree type, bool named)
+h8300_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
@@ -1127,7 +1119,7 @@ h8300_function_arg (cumulative_args_t cum_v, machine_mode mode,
   int regpass = 0;
 
   /* Never pass unnamed arguments in registers.  */
-  if (!named)
+  if (!arg.named)
     return NULL_RTX;
 
   /* Pass 3 regs worth of data in regs when user asked on the command line.  */
@@ -1151,34 +1143,25 @@ h8300_function_arg (cumulative_args_t cum_v, machine_mode mode,
 
   if (regpass)
     {
-      int size;
-
-      if (mode == BLKmode)
-       size = int_size_in_bytes (type);
-      else
-       size = GET_MODE_SIZE (mode);
-
+      int size = arg.promoted_size_in_bytes ();
       if (size + cum->nbytes <= regpass * UNITS_PER_WORD
          && cum->nbytes / UNITS_PER_WORD <= 3)
-       result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
+       result = gen_rtx_REG (arg.mode, cum->nbytes / UNITS_PER_WORD);
     }
 
   return result;
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-h8300_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-                           const_tree type, bool named ATTRIBUTE_UNUSED)
+h8300_function_arg_advance (cumulative_args_t cum_v,
+                           const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  cum->nbytes += (mode != BLKmode
-                 ? (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD
-                 : (int_size_in_bytes (type) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD);
+  cum->nbytes += ((arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1)
+                 & -UNITS_PER_WORD);
 }
 
 \f
@@ -1275,7 +1258,7 @@ h8300_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
            *total = 0;
            return true;
          }
-       if (-4 <= n && n <= 4)
+       if (n >= -4 && n <= 4)
          {
            switch ((int) n)
              {
@@ -1338,12 +1321,12 @@ h8300_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
       if (TARGET_H8300SX)
        switch (GET_MODE (x))
          {
-         case QImode:
-         case HImode:
+         case E_QImode:
+         case E_HImode:
            *total = COSTS_N_INSNS (!speed ? 4 : 10);
            return false;
 
-         case SImode:
+         case E_SImode:
            *total = COSTS_N_INSNS (!speed ? 4 : 18);
            return false;
 
@@ -1357,12 +1340,12 @@ h8300_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
       if (TARGET_H8300SX)
        switch (GET_MODE (x))
          {
-         case QImode:
-         case HImode:
+         case E_QImode:
+         case E_HImode:
            *total = COSTS_N_INSNS (2);
            return false;
 
-         case SImode:
+         case E_SImode:
            *total = COSTS_N_INSNS (5);
            return false;
 
@@ -1659,7 +1642,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
        }
       break;
     case 'o':
-      h8300_print_operand_address (file, x);
+      h8300_print_operand_address (file, VOIDmode, x);
       break;
     case 's':
       if (GET_CODE (x) == CONST_INT)
@@ -1707,18 +1690,18 @@ h8300_print_operand (FILE *file, rtx x, int code)
        case REG:
          switch (GET_MODE (x))
            {
-           case QImode:
+           case E_QImode:
 #if 0 /* Is it asm ("mov.b %0,r2l", ...) */
              fprintf (file, "%s", byte_reg (x, 0));
 #else /* ... or is it asm ("mov.b %0l,r2l", ...) */
              fprintf (file, "%s", names_big[REGNO (x)]);
 #endif
              break;
-           case HImode:
+           case E_HImode:
              fprintf (file, "%s", names_big[REGNO (x)]);
              break;
-           case SImode:
-           case SFmode:
+           case E_SImode:
+           case E_SFmode:
              fprintf (file, "%s", names_extended[REGNO (x)]);
              break;
            default:
@@ -1731,7 +1714,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
            rtx addr = XEXP (x, 0);
 
            fprintf (file, "@");
-           output_address (addr);
+           output_address (GET_MODE (x), addr);
 
            /* Add a length suffix to constant addresses.  Although this
               is often unnecessary, it helps to avoid ambiguity in the
@@ -1752,10 +1735,12 @@ h8300_print_operand (FILE *file, rtx x, int code)
                      break;
                    }
 
-                 /* Fall through.  We should not get here if we are
-                    processing bit operations on H8/300 or H8/300H
-                    because 'U' constraint does not allow bit
-                    operations on the tiny area on these machines.  */
+                 /* FALLTHRU */
+
+                 /* We should not get here if we are processing bit
+                    operations on H8/300 or H8/300H because 'U'
+                    constraint does not allow bit operations on the
+                    tiny area on these machines.  */
 
                case 'X':
                case 'T':
@@ -1776,7 +1761,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
        case CONST:
        case LABEL_REF:
          fprintf (file, "#");
-         h8300_print_operand_address (file, x);
+         h8300_print_operand_address (file, VOIDmode, x);
          break;
        case CONST_DOUBLE:
          {
@@ -1802,7 +1787,7 @@ h8300_print_operand_punct_valid_p (unsigned char code)
 /* Output assembly language output for the address ADDR to FILE.  */
 
 static void
-h8300_print_operand_address (FILE *file, rtx addr)
+h8300_print_operand_address (FILE *file, machine_mode mode, rtx addr)
 {
   rtx index;
   int size;
@@ -1836,12 +1821,12 @@ h8300_print_operand_address (FILE *file, rtx addr)
       if (GET_CODE (index) == REG)
        {
          /* reg,foo */
-         h8300_print_operand_address (file, XEXP (addr, 1));
+         h8300_print_operand_address (file, mode, XEXP (addr, 1));
          fprintf (file, ",");
          switch (size)
            {
            case 0:
-             h8300_print_operand_address (file, index);
+             h8300_print_operand_address (file, mode, index);
              break;
 
            case 1:
@@ -1864,9 +1849,9 @@ h8300_print_operand_address (FILE *file, rtx addr)
       else
        {
          /* foo+k */
-         h8300_print_operand_address (file, XEXP (addr, 0));
+         h8300_print_operand_address (file, mode, XEXP (addr, 0));
          fprintf (file, "+");
-         h8300_print_operand_address (file, XEXP (addr, 1));
+         h8300_print_operand_address (file, mode, XEXP (addr, 1));
        }
       fprintf (file, ")");
       break;
@@ -2557,14 +2542,14 @@ h8300_insn_length_from_table (rtx_insn *insn, rtx * operands)
     case LENGTH_TABLE_NONE:
       gcc_unreachable ();
 
-    case LENGTH_TABLE_ADDB:
-      return h8300_binary_length (insn, &addb_length_table);
-
-    case LENGTH_TABLE_ADDW:
-      return h8300_binary_length (insn, &addw_length_table);
-
-    case LENGTH_TABLE_ADDL:
-      return h8300_binary_length (insn, &addl_length_table);
+    case LENGTH_TABLE_ADD:
+      if (GET_MODE (operands[0]) == QImode)
+        return h8300_binary_length (insn, &addb_length_table);
+      else if (GET_MODE (operands[0]) == HImode)
+        return h8300_binary_length (insn, &addw_length_table);
+      else if (GET_MODE (operands[0]) == SImode)
+        return h8300_binary_length (insn, &addl_length_table);
+      gcc_unreachable ();
 
     case LENGTH_TABLE_LOGICB:
       return h8300_binary_length (insn, &logicb_length_table);
@@ -2816,7 +2801,7 @@ compute_mov_length (rtx *operands)
 
       switch (mode)
        {
-       case QImode:
+       case E_QImode:
          if (addr == NULL_RTX)
            return 2;
 
@@ -2828,7 +2813,7 @@ compute_mov_length (rtx *operands)
          base_length = 4;
          break;
 
-       case HImode:
+       case E_HImode:
          if (addr == NULL_RTX)
            {
              if (REG_P (src))
@@ -2843,7 +2828,7 @@ compute_mov_length (rtx *operands)
          base_length = 4;
          break;
 
-       case SImode:
+       case E_SImode:
          if (addr == NULL_RTX)
            {
              if (REG_P (src))
@@ -2870,7 +2855,7 @@ compute_mov_length (rtx *operands)
          base_length = 8;
          break;
 
-       case SFmode:
+       case E_SFmode:
          if (addr == NULL_RTX)
            {
              if (REG_P (src))
@@ -2922,7 +2907,7 @@ compute_mov_length (rtx *operands)
 
       switch (mode)
        {
-       case QImode:
+       case E_QImode:
          if (addr == NULL_RTX)
            return 2;
 
@@ -2934,7 +2919,7 @@ compute_mov_length (rtx *operands)
          base_length = 8;
          break;
 
-       case HImode:
+       case E_HImode:
          if (addr == NULL_RTX)
            {
              if (REG_P (src))
@@ -2949,7 +2934,7 @@ compute_mov_length (rtx *operands)
          base_length = 8;
          break;
 
-       case SImode:
+       case E_SImode:
          if (addr == NULL_RTX)
            {
              if (REG_P (src))
@@ -2990,7 +2975,7 @@ compute_mov_length (rtx *operands)
          base_length = 10;
          break;
 
-       case SFmode:
+       case E_SFmode:
          if (addr == NULL_RTX)
            {
              if (REG_P (src))
@@ -3312,7 +3297,7 @@ output_logical_op (machine_mode mode, rtx *operands)
 
   switch (mode)
     {
-    case HImode:
+    case E_HImode:
       /* First, see if we can finish with one insn.  */
       if ((TARGET_H8300H || TARGET_H8300S)
          && b0 != 0
@@ -3337,7 +3322,7 @@ output_logical_op (machine_mode mode, rtx *operands)
            }
        }
       break;
-    case SImode:
+    case E_SImode:
       if (TARGET_H8300H || TARGET_H8300S)
        {
          /* Determine if the lower half can be taken care of in no more
@@ -3477,7 +3462,7 @@ compute_logical_op_length (machine_mode mode, rtx *operands)
 
   switch (mode)
     {
-    case HImode:
+    case E_HImode:
       /* First, see if we can finish with one insn.  */
       if ((TARGET_H8300H || TARGET_H8300S)
          && b0 != 0
@@ -3497,7 +3482,7 @@ compute_logical_op_length (machine_mode mode, rtx *operands)
            length += 2;
        }
       break;
-    case SImode:
+    case E_SImode:
       if (TARGET_H8300H || TARGET_H8300S)
        {
          /* Determine if the lower half can be taken care of in no more
@@ -3621,7 +3606,7 @@ compute_logical_op_cc (machine_mode mode, rtx *operands)
 
   switch (mode)
     {
-    case HImode:
+    case E_HImode:
       /* First, see if we can finish with one insn.  */
       if ((TARGET_H8300H || TARGET_H8300S)
          && b0 != 0
@@ -3630,7 +3615,7 @@ compute_logical_op_cc (machine_mode mode, rtx *operands)
          cc = CC_SET_ZNV;
        }
       break;
-    case SImode:
+    case E_SImode:
       if (TARGET_H8300H || TARGET_H8300S)
        {
          /* Determine if the lower half can be taken care of in no more
@@ -4177,7 +4162,7 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
              goto end;
            }
        }
-      else if ((8 <= count && count <= 13)
+      else if ((count >= 8 && count <= 13)
               || (TARGET_H8300S && count == 14))
        {
          info->remainder = count - 8;
@@ -4257,7 +4242,7 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
       gcc_unreachable ();
 
     case SIshift:
-      if (TARGET_H8300 && 8 <= count && count <= 9)
+      if (TARGET_H8300 && count >= 8 && count <= 9)
        {
          info->remainder = count - 8;
 
@@ -4320,9 +4305,9 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
              gcc_unreachable ();
            }
        }
-      else if ((TARGET_H8300 && 16 <= count && count <= 20)
-              || (TARGET_H8300H && 16 <= count && count <= 19)
-              || (TARGET_H8300S && 16 <= count && count <= 21))
+      else if ((TARGET_H8300 && count >= 16 && count <= 20)
+              || (TARGET_H8300H && count >= 16 && count <= 19)
+              || (TARGET_H8300S && count >= 16 && count <= 21))
        {
          info->remainder = count - 16;
 
@@ -4359,7 +4344,7 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
              goto end;
            }
        }
-      else if (TARGET_H8300 && 24 <= count && count <= 28)
+      else if (TARGET_H8300 && count >= 24 && count <= 28)
        {
          info->remainder = count - 24;
 
@@ -4383,7 +4368,7 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
            }
        }
       else if ((TARGET_H8300H && count == 24)
-              || (TARGET_H8300S && 24 <= count && count <= 25))
+              || (TARGET_H8300S && count >= 24 && count <= 25))
        {
          info->remainder = count - 24;
 
@@ -4541,19 +4526,19 @@ h8300_shift_needs_scratch_p (int count, machine_mode mode)
   /* Find the shift algorithm.  */
   switch (mode)
     {
-    case QImode:
+    case E_QImode:
       a  = shift_alg_qi[cpu][SHIFT_ASHIFT][count];
       lr = shift_alg_qi[cpu][SHIFT_LSHIFTRT][count];
       ar = shift_alg_qi[cpu][SHIFT_ASHIFTRT][count];
       break;
 
-    case HImode:
+    case E_HImode:
       a  = shift_alg_hi[cpu][SHIFT_ASHIFT][count];
       lr = shift_alg_hi[cpu][SHIFT_LSHIFTRT][count];
       ar = shift_alg_hi[cpu][SHIFT_ASHIFTRT][count];
       break;
 
-    case SImode:
+    case E_SImode:
       a  = shift_alg_si[cpu][SHIFT_ASHIFT][count];
       lr = shift_alg_si[cpu][SHIFT_LSHIFTRT][count];
       ar = shift_alg_si[cpu][SHIFT_ASHIFTRT][count];
@@ -4586,13 +4571,13 @@ output_a_shift (rtx *operands)
 
   switch (mode)
     {
-    case QImode:
+    case E_QImode:
       shift_mode = QIshift;
       break;
-    case HImode:
+    case E_HImode:
       shift_mode = HIshift;
       break;
-    case SImode:
+    case E_SImode:
       shift_mode = SIshift;
       break;
     default:
@@ -4678,11 +4663,11 @@ output_a_shift (rtx *operands)
        /* Now mask off the high bits.  */
        switch (mode)
          {
-         case QImode:
+         case E_QImode:
            sprintf (insn_buf, "and\t#%d,%%X0", mask);
            break;
 
-         case HImode:
+         case E_HImode:
            gcc_assert (TARGET_H8300H || TARGET_H8300S);
            sprintf (insn_buf, "and.w\t#%d,%%T0", mask);
            break;
@@ -4754,13 +4739,13 @@ compute_a_shift_length (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
 
   switch (mode)
     {
-    case QImode:
+    case E_QImode:
       shift_mode = QIshift;
       break;
-    case HImode:
+    case E_HImode:
       shift_mode = HIshift;
       break;
-    case SImode:
+    case E_SImode:
       shift_mode = SIshift;
       break;
     default:
@@ -4850,13 +4835,13 @@ compute_a_shift_length (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
            /* Now mask off the high bits.  */
            switch (mode)
              {
-             case QImode:
+             case E_QImode:
                wlength += 1;
                break;
-             case HImode:
+             case E_HImode:
                wlength += 2;
                break;
-             case SImode:
+             case E_SImode:
                gcc_assert (!TARGET_H8300);
                wlength += 3;
                break;
@@ -4902,13 +4887,13 @@ compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
   
   switch (mode)
     {
-    case QImode:
+    case E_QImode:
       shift_mode = QIshift;
       break;
-    case HImode:
+    case E_HImode:
       shift_mode = HIshift;
       break;
-    case SImode:
+    case E_SImode:
       shift_mode = SIshift;
       break;
     default:
@@ -5015,13 +5000,13 @@ expand_a_rotate (rtx operands[])
       /* Rotate by one bit.  */
       switch (mode)
        {
-       case QImode:
+       case E_QImode:
          emit_insn (gen_rotlqi3_1 (dst, dst, const1_rtx));
          break;
-       case HImode:
+       case E_HImode:
          emit_insn (gen_rotlhi3_1 (dst, dst, const1_rtx));
          break;
-       case SImode:
+       case E_SImode:
          emit_insn (gen_rotlsi3_1 (dst, dst, const1_rtx));
          break;
        default:
@@ -5043,13 +5028,13 @@ expand_a_rotate (rtx operands[])
       /* Rotate by AMOUNT bits.  */
       switch (mode)
        {
-       case QImode:
+       case E_QImode:
          emit_insn (gen_rotlqi3_1 (dst, dst, rotate_amount));
          break;
-       case HImode:
+       case E_HImode:
          emit_insn (gen_rotlhi3_1 (dst, dst, rotate_amount));
          break;
-       case SImode:
+       case E_SImode:
          emit_insn (gen_rotlsi3_1 (dst, dst, rotate_amount));
          break;
        default:
@@ -5078,13 +5063,13 @@ output_a_rotate (enum rtx_code code, rtx *operands)
 
   switch (mode)
     {
-    case QImode:
+    case E_QImode:
       rotate_mode = QIshift;
       break;
-    case HImode:
+    case E_HImode:
       rotate_mode = HIshift;
       break;
-    case SImode:
+    case E_SImode:
       rotate_mode = SIshift;
       break;
     default:
@@ -5131,13 +5116,13 @@ output_a_rotate (enum rtx_code code, rtx *operands)
     {
       switch (mode)
        {
-       case HImode:
+       case E_HImode:
          /* This code works on any family.  */
          insn_buf = "xor.b\t%s0,%t0\n\txor.b\t%t0,%s0\n\txor.b\t%s0,%t0";
          output_asm_insn (insn_buf, operands);
          break;
 
-       case SImode:
+       case E_SImode:
          /* This code works on the H8/300H and H8S.  */
          insn_buf = "xor.w\t%e0,%f0\n\txor.w\t%f0,%e0\n\txor.w\t%e0,%f0";
          output_asm_insn (insn_buf, operands);
@@ -5432,23 +5417,23 @@ h8300_insert_attributes (tree node, tree *attributes)
 
 static const struct attribute_spec h8300_attribute_table[] =
 {
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
-       affects_type_identity } */
-  { "interrupt_handler", 0, 0, true,  false, false,
-    h8300_handle_fndecl_attribute, false },
-  { "saveall",           0, 0, true,  false, false,
-    h8300_handle_fndecl_attribute, false },
-  { "OS_Task",           0, 0, true,  false, false,
-    h8300_handle_fndecl_attribute, false },
-  { "monitor",           0, 0, true,  false, false,
-    h8300_handle_fndecl_attribute, false },
-  { "function_vector",   0, 0, true,  false, false,
-    h8300_handle_fndecl_attribute, false },
-  { "eightbit_data",     0, 0, true,  false, false,
-    h8300_handle_eightbit_data_attribute, false },
-  { "tiny_data",         0, 0, true,  false, false,
-    h8300_handle_tiny_data_attribute, false },
-  { NULL,                0, 0, false, false, false, NULL, false }
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+       affects_type_identity, handler, exclude } */
+  { "interrupt_handler", 0, 0, true,  false, false, false,
+    h8300_handle_fndecl_attribute, NULL },
+  { "saveall",           0, 0, true,  false, false, false,
+    h8300_handle_fndecl_attribute, NULL },
+  { "OS_Task",           0, 0, true,  false, false, false,
+    h8300_handle_fndecl_attribute, NULL },
+  { "monitor",           0, 0, true,  false, false, false,
+    h8300_handle_fndecl_attribute, NULL },
+  { "function_vector",   0, 0, true,  false, false, false,
+    h8300_handle_fndecl_attribute, NULL },
+  { "eightbit_data",     0, 0, true,  false, false, false,
+    h8300_handle_eightbit_data_attribute, NULL },
+  { "tiny_data",         0, 0, true,  false, false, false,
+    h8300_handle_tiny_data_attribute, NULL },
+  { NULL,                0, 0, false, false, false, false, NULL, NULL }
 };
 
 
@@ -5742,7 +5727,7 @@ byte_accesses_mergeable_p (rtx addr1, rtx addr2)
    before I3.  I3 is assumed to be a comparison insn.  */
 
 int
-same_cmp_preceding_p (rtx i3)
+same_cmp_preceding_p (rtx_insn *i3)
 {
   rtx_insn *i1, *i2;
 
@@ -5762,7 +5747,7 @@ same_cmp_preceding_p (rtx i3)
    after I1.  I1 is assumed to be a comparison insn.  */
 
 int
-same_cmp_following_p (rtx i1)
+same_cmp_following_p (rtx_insn *i1)
 {
   rtx_insn *i2, *i3;
 
@@ -5886,21 +5871,10 @@ h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
   return 0;
 }
 
-/* Worker function for HARD_REGNO_NREGS.
-
-   We pretend the MAC register is 32bits -- we don't have any data
-   types on the H8 series to handle more than 32bits.  */
-
-int
-h8300_hard_regno_nregs (int regno ATTRIBUTE_UNUSED, machine_mode mode)
-{
-  return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-}
-
-/* Worker function for HARD_REGNO_MODE_OK.  */
+/* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
-int
-h8300_hard_regno_mode_ok (int regno, machine_mode mode)
+static bool
+h8300_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
 {
   if (TARGET_H8300)
     /* If an even reg, then anything goes.  Otherwise the mode must be
@@ -5912,6 +5886,20 @@ h8300_hard_regno_mode_ok (int regno, machine_mode mode)
     return regno == MAC_REG ? mode == SImode : 1;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+h8300_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (mode1 == mode2
+         || ((mode1 == QImode
+              || mode1 == HImode
+              || ((TARGET_H8300H || TARGET_H8300S) && mode1 == SImode))
+             && (mode2 == QImode
+                 || mode2 == HImode
+                 || ((TARGET_H8300H || TARGET_H8300S) && mode2 == SImode))));
+}
+
 /* Helper function for the move patterns.  Make sure a move is legitimate.  */
 
 bool
@@ -6047,6 +6035,21 @@ h8300_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
       emit_move_insn (mem, tem);
     }
 }
+
+/* Implement PUSH_ROUNDING.
+
+   On the H8/300, @-sp really pushes a byte if you ask it to - but that's
+   dangerous, so we claim that it always pushes a word, then we catch
+   the mov.b rx,@-sp and turn it into a mov.w rx,@-sp on output.
+
+   On the H8/300H, we simplify TARGET_QUICKCALL by setting this to 4
+   and doing a similar thing.  */
+
+poly_int64
+h8300_push_rounding (poly_int64 bytes)
+{
+  return ((bytes + PARM_BOUNDARY / 8 - 1) & (-PARM_BOUNDARY / 8));
+}
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ATTRIBUTE_TABLE
@@ -6109,6 +6112,15 @@ h8300_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
 #undef TARGET_HARD_REGNO_SCRATCH_OK
 #define TARGET_HARD_REGNO_SCRATCH_OK h8300_hard_regno_scratch_ok
 
+#undef TARGET_HARD_REGNO_MODE_OK
+#define TARGET_HARD_REGNO_MODE_OK h8300_hard_regno_mode_ok
+
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P h8300_modes_tieable_p
+
+#undef TARGET_LRA_P
+#define TARGET_LRA_P hook_bool_void_false
+
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    h8300_legitimate_address_p
 
@@ -6127,4 +6139,7 @@ h8300_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
 #undef TARGET_MODE_DEPENDENT_ADDRESS_P
 #define TARGET_MODE_DEPENDENT_ADDRESS_P h8300_mode_dependent_address_p
 
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
 struct gcc_target targetm = TARGET_INITIALIZER;