]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/m32r/m32r.c
Update copyright years.
[thirdparty/gcc.git] / gcc / config / m32r / m32r.c
index 444f16efbbea939c58691c9d8c1165cb5a99a4ee..4efb4b9c28726ec3593116276709b095def23d1e 100644 (file)
@@ -1,6 +1,5 @@
 /* Subroutines used for code generation on the Renesas M32R cpu.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
+#include "backend.h"
+#include "target.h"
 #include "rtl.h"
-#include "regs.h"
-#include "hard-reg-set.h"
+#include "tree.h"
+#include "df.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "stringpool.h"
 #include "insn-config.h"
-#include "conditions.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 "output.h"
 #include "insn-attr.h"
-#include "flags.h"
+#include "explow.h"
 #include "expr.h"
-#include "function.h"
-#include "recog.h"
-#include "diagnostic-core.h"
-#include "ggc.h"
-#include "integrate.h"
-#include "df.h"
-#include "tm_p.h"
-#include "target.h"
-#include "target-def.h"
 #include "tm-constrs.h"
+#include "builtins.h"
+
+/* This file should be included last.  */
+#include "target-def.h"
 
 /* Array of valid operand punctuation characters.  */
 static char m32r_punct_chars[256];
 
-/* Selected code model.  */
-enum m32r_model m32r_model = M32R_MODEL_DEFAULT;
-
-/* Selected SDA support.  */
-enum m32r_sdata m32r_sdata = M32R_SDATA_DEFAULT;
-
 /* Machine-specific symbol_ref flags.  */
 #define SYMBOL_FLAG_MODEL_SHIFT                SYMBOL_FLAG_MACH_DEP_SHIFT
 #define SYMBOL_REF_MODEL(X) \
@@ -61,69 +58,70 @@ enum m32r_sdata m32r_sdata = M32R_SDATA_DEFAULT;
 #define LIT_NAME_P(NAME) ((NAME)[0] == '*' && (NAME)[1] == '.')
 
 /* Forward declaration.  */
-static bool  m32r_handle_option (size_t, const char *, int);
 static void  m32r_option_override (void);
 static void  init_reg_tables (void);
 static void  block_move_call (rtx, rtx, rtx);
 static int   m32r_is_insn (rtx);
-static bool  m32r_legitimate_address_p (enum machine_mode, rtx, bool);
-static rtx   m32r_legitimize_address (rtx, rtx, enum machine_mode);
-static bool  m32r_mode_dependent_address_p (const_rtx);
+static bool  m32r_legitimate_address_p (machine_mode, rtx, bool);
+static rtx   m32r_legitimize_address (rtx, rtx, machine_mode);
+static bool  m32r_mode_dependent_address_p (const_rtx, addr_space_t);
 static tree  m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
 static void  m32r_print_operand (FILE *, rtx, int);
-static void  m32r_print_operand_address (FILE *, rtx);
+static void  m32r_print_operand_address (FILE *, machine_mode, rtx);
 static bool  m32r_print_operand_punct_valid_p (unsigned char code);
 static void  m32r_output_function_prologue (FILE *, HOST_WIDE_INT);
 static void  m32r_output_function_epilogue (FILE *, HOST_WIDE_INT);
 
 static void  m32r_file_start (void);
 
-static int    m32r_adjust_priority (rtx, int);
+static int    m32r_adjust_priority (rtx_insn *, int);
 static int    m32r_issue_rate (void);
 
 static void m32r_encode_section_info (tree, rtx, int);
 static bool m32r_in_small_data_p (const_tree);
 static bool m32r_return_in_memory (const_tree, const_tree);
 static rtx m32r_function_value (const_tree, const_tree, bool);
-static rtx m32r_libcall_value (enum machine_mode, const_rtx);
+static rtx m32r_libcall_value (machine_mode, const_rtx);
 static bool m32r_function_value_regno_p (const unsigned int);
-static void m32r_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
+static void m32r_setup_incoming_varargs (cumulative_args_t, machine_mode,
                                         tree, int *, int);
 static void init_idents (void);
-static bool m32r_rtx_costs (rtx, int, int, int *, bool speed);
-static int m32r_memory_move_cost (enum machine_mode, reg_class_t, bool);
-static bool m32r_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
+static bool m32r_rtx_costs (rtx, machine_mode, int, int, int *, bool speed);
+static int m32r_memory_move_cost (machine_mode, reg_class_t, bool);
+static bool m32r_pass_by_reference (cumulative_args_t, machine_mode,
                                    const_tree, bool);
-static int m32r_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
+static int m32r_arg_partial_bytes (cumulative_args_t, machine_mode,
                                   tree, bool);
-static rtx m32r_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+static rtx m32r_function_arg (cumulative_args_t, machine_mode,
                              const_tree, bool);
-static void m32r_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+static void m32r_function_arg_advance (cumulative_args_t, machine_mode,
                                       const_tree, bool);
 static bool m32r_can_eliminate (const int, const int);
 static void m32r_conditional_register_usage (void);
 static void m32r_trampoline_init (rtx, tree, rtx);
+static bool m32r_legitimate_constant_p (machine_mode, rtx);
+static bool m32r_attribute_identifier (const_tree);
 \f
 /* M32R specific attributes.  */
 
 static const struct attribute_spec m32r_attribute_table[] =
 {
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-  { "interrupt", 0, 0, true,  false, false, NULL },
-  { "model",     1, 1, true,  false, false, m32r_handle_model_attribute },
-  { NULL,        0, 0, false, false, false, NULL }
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+       affects_type_identity } */
+  { "interrupt", 0, 0, true,  false, false, NULL, false },
+  { "model",     1, 1, true,  false, false, m32r_handle_model_attribute,
+    false },
+  { NULL,        0, 0, false, false, false, NULL, false }
 };
-
-static const struct default_options m32r_option_optimization_table[] =
-  {
-    { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
-    { OPT_LEVELS_1_PLUS, OPT_fregmove, NULL, 1 },
-    { OPT_LEVELS_NONE, 0, NULL, 0 }
-  };
 \f
 /* Initialize the GCC target structure.  */
 #undef  TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE m32r_attribute_table
+#undef  TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P
+#define TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P m32r_attribute_identifier
+
+#undef TARGET_LRA_P
+#define TARGET_LRA_P hook_bool_void_false
 
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P m32r_legitimate_address_p
@@ -157,14 +155,8 @@ static const struct default_options m32r_option_optimization_table[] =
 #undef  TARGET_SCHED_ISSUE_RATE
 #define TARGET_SCHED_ISSUE_RATE m32r_issue_rate
 
-#undef  TARGET_DEFAULT_TARGET_FLAGS
-#define TARGET_DEFAULT_TARGET_FLAGS TARGET_CPU_DEFAULT
-#undef  TARGET_HANDLE_OPTION
-#define TARGET_HANDLE_OPTION m32r_handle_option
 #undef  TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE m32r_option_override
-#undef  TARGET_OPTION_OPTIMIZATION_TABLE
-#define TARGET_OPTION_OPTIMIZATION_TABLE m32r_option_optimization_table
 
 #undef  TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO m32r_encode_section_info
@@ -177,7 +169,7 @@ static const struct default_options m32r_option_optimization_table[] =
 #undef  TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS m32r_rtx_costs
 #undef  TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
+#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
 
 #undef  TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
@@ -213,60 +205,11 @@ static const struct default_options m32r_option_optimization_table[] =
 #undef TARGET_TRAMPOLINE_INIT
 #define TARGET_TRAMPOLINE_INIT m32r_trampoline_init
 
-#undef  TARGET_EXCEPT_UNWIND_INFO
-#define TARGET_EXCEPT_UNWIND_INFO              sjlj_except_unwind_info
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P m32r_legitimate_constant_p
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
-/* Implement TARGET_HANDLE_OPTION.  */
-
-static bool
-m32r_handle_option (size_t code, const char *arg, int value)
-{
-  switch (code)
-    {
-    case OPT_m32r:
-      target_flags &= ~(MASK_M32R2 | MASK_M32RX);
-      return true;
-
-    case OPT_mmodel_:
-      if (strcmp (arg, "small") == 0)
-       m32r_model = M32R_MODEL_SMALL;
-      else if (strcmp (arg, "medium") == 0)
-       m32r_model = M32R_MODEL_MEDIUM;
-      else if (strcmp (arg, "large") == 0)
-       m32r_model = M32R_MODEL_LARGE;
-      else
-       return false;
-      return true;
-
-    case OPT_msdata_:
-      if (strcmp (arg, "none") == 0)
-       m32r_sdata = M32R_SDATA_NONE;
-      else if (strcmp (arg, "sdata") == 0)
-       m32r_sdata = M32R_SDATA_SDATA;
-      else if (strcmp (arg, "use") == 0)
-       m32r_sdata = M32R_SDATA_USE;
-      else
-       return false;
-      return true;
-
-    case OPT_mno_flush_func:
-      m32r_cache_flush_func = NULL;
-      return true;
-
-    case OPT_mflush_trap_:
-      return value <= 15;
-
-    case OPT_mno_flush_trap:
-      m32r_cache_flush_trap = -1;
-      return true;
-
-    default:
-      return true;
-    }
-}
-
 /* Called by m32r_option_override to initialize various things.  */
 
 void
@@ -344,31 +287,33 @@ init_reg_tables (void)
 
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {
-      switch (GET_MODE_CLASS (i))
+      machine_mode m = (machine_mode) i;
+      
+      switch (GET_MODE_CLASS (m))
        {
        case MODE_INT:
        case MODE_PARTIAL_INT:
        case MODE_COMPLEX_INT:
-         if (GET_MODE_SIZE (i) <= 4)
+         if (GET_MODE_SIZE (m) <= 4)
            m32r_mode_class[i] = 1 << (int) S_MODE;
-         else if (GET_MODE_SIZE (i) == 8)
+         else if (GET_MODE_SIZE (m) == 8)
            m32r_mode_class[i] = 1 << (int) D_MODE;
-         else if (GET_MODE_SIZE (i) == 16)
+         else if (GET_MODE_SIZE (m) == 16)
            m32r_mode_class[i] = 1 << (int) T_MODE;
-         else if (GET_MODE_SIZE (i) == 32)
+         else if (GET_MODE_SIZE (m) == 32)
            m32r_mode_class[i] = 1 << (int) O_MODE;
          else
            m32r_mode_class[i] = 0;
          break;
        case MODE_FLOAT:
        case MODE_COMPLEX_FLOAT:
-         if (GET_MODE_SIZE (i) <= 4)
+         if (GET_MODE_SIZE (m) <= 4)
            m32r_mode_class[i] = 1 << (int) SF_MODE;
-         else if (GET_MODE_SIZE (i) == 8)
+         else if (GET_MODE_SIZE (m) == 8)
            m32r_mode_class[i] = 1 << (int) DF_MODE;
-         else if (GET_MODE_SIZE (i) == 16)
+         else if (GET_MODE_SIZE (m) == 16)
            m32r_mode_class[i] = 1 << (int) TF_MODE;
-         else if (GET_MODE_SIZE (i) == 32)
+         else if (GET_MODE_SIZE (m) == 32)
            m32r_mode_class[i] = 1 << (int) OF_MODE;
          else
            m32r_mode_class[i] = 0;
@@ -452,6 +397,13 @@ m32r_handle_model_attribute (tree *node ATTRIBUTE_UNUSED, tree name,
 
   return NULL_TREE;
 }
+
+static bool
+m32r_attribute_identifier (const_tree name)
+{
+  return strcmp (IDENTIFIER_POINTER (name), "model") == 0
+    ||   strcmp (IDENTIFIER_POINTER (name), "__model__") == 0;
+}
 \f
 /* Encode section information of DECL, which is either a VAR_DECL,
    FUNCTION_DECL, STRING_CST, CONSTRUCTOR, or ???.
@@ -522,7 +474,7 @@ m32r_encode_section_info (tree decl, rtx rtl, int first)
 static bool
 m32r_in_small_data_p (const_tree decl)
 {
-  const_tree section;
+  const char *section;
 
   if (TREE_CODE (decl) != VAR_DECL)
     return false;
@@ -533,8 +485,7 @@ m32r_in_small_data_p (const_tree decl)
   section = DECL_SECTION_NAME (decl);
   if (section)
     {
-      const char *const name = TREE_STRING_POINTER (section);
-      if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0)
+      if (strcmp (section, ".sdata") == 0 || strcmp (section, ".sbss") == 0)
        return true;
     }
   else
@@ -561,7 +512,7 @@ m32r_init_expanders (void)
 }
 \f
 int
-call_operand (rtx op, enum machine_mode mode)
+call_operand (rtx op, machine_mode mode)
 {
   if (!MEM_P (op))
     return 0;
@@ -572,7 +523,7 @@ call_operand (rtx op, enum machine_mode mode)
 /* Return 1 if OP is a reference to an object in .sdata/.sbss.  */
 
 int
-small_data_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+small_data_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (! TARGET_SDATA_USE)
     return 0;
@@ -592,7 +543,7 @@ small_data_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 /* Return 1 if OP is a symbol that can use 24-bit addressing.  */
 
 int
-addr24_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+addr24_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
 {
   rtx sym;
 
@@ -626,7 +577,7 @@ addr24_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 /* Return 1 if OP is a symbol that needs 32-bit addressing.  */
 
 int
-addr32_operand (rtx op, enum machine_mode mode)
+addr32_operand (rtx op, machine_mode mode)
 {
   rtx sym;
 
@@ -651,7 +602,7 @@ addr32_operand (rtx op, enum machine_mode mode)
 /* Return 1 if OP is a function that can be called with the `bl' insn.  */
 
 int
-call26_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+call26_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (flag_pic)
     return 1;
@@ -664,7 +615,7 @@ call26_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 
 /* Return 1 if OP is a DImode const we want to handle inline.
    This must match the code in the movdi pattern.
-   It is used by the 'G' CONST_DOUBLE_OK_FOR_LETTER.  */
+   It is used by the 'G' constraint.  */
 
 int
 easy_di_const (rtx op)
@@ -684,16 +635,14 @@ easy_di_const (rtx op)
 
 /* Return 1 if OP is a DFmode const we want to handle inline.
    This must match the code in the movdf pattern.
-   It is used by the 'H' CONST_DOUBLE_OK_FOR_LETTER.  */
+   It is used by the 'H' constraint.  */
 
 int
 easy_df_const (rtx op)
 {
-  REAL_VALUE_TYPE r;
   long l[2];
 
-  REAL_VALUE_FROM_CONST_DOUBLE (r, op);
-  REAL_VALUE_TO_TARGET_DOUBLE (r, l);
+  REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), l);
   if (l[0] == 0 && l[1] == 0)
     return 1;
   if ((l[0] & 0xffff) == 0 && l[1] == 0)
@@ -705,7 +654,7 @@ easy_df_const (rtx op)
    This is used in insn length calcs.  */
 
 int
-memreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+memreg_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
 {
   return MEM_P (op) && REG_P (XEXP (op, 0));
 }
@@ -713,8 +662,8 @@ memreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 /* Return nonzero if TYPE must be passed by indirect reference.  */
 
 static bool
-m32r_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
-                       enum machine_mode mode, const_tree type,
+m32r_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
+                       machine_mode mode, const_tree type,
                        bool named ATTRIBUTE_UNUSED)
 {
   int size;
@@ -939,7 +888,7 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare)
 bool
 gen_cond_store (enum rtx_code code, rtx op0, rtx op1, rtx op2)
 {
-  enum machine_mode mode = GET_MODE (op0);
+  machine_mode mode = GET_MODE (op0);
 
   gcc_assert (mode == SImode);
   switch (code)
@@ -1086,7 +1035,7 @@ gen_cond_store (enum rtx_code code, rtx op0, rtx op1, rtx op2)
 rtx
 gen_split_move_double (rtx operands[])
 {
-  enum machine_mode mode = GET_MODE (operands[0]);
+  machine_mode mode = GET_MODE (operands[0]);
   rtx dest = operands[0];
   rtx src  = operands[1];
   rtx val;
@@ -1095,9 +1044,9 @@ gen_split_move_double (rtx operands[])
      subregs to make this code simpler.  It is safe to call
      alter_subreg any time after reload.  */
   if (GET_CODE (dest) == SUBREG)
-    alter_subreg (&dest);
+    alter_subreg (&dest, true);
   if (GET_CODE (src) == SUBREG)
-    alter_subreg (&src);
+    alter_subreg (&src, true);
 
   start_sequence ();
   if (REG_P (dest))
@@ -1114,12 +1063,10 @@ gen_split_move_double (rtx operands[])
          /* We normally copy the low-numbered register first.  However, if
             the first register operand 0 is the same as the second register of
             operand 1, we must copy in the opposite order.  */
-         emit_insn (gen_rtx_SET (VOIDmode,
-                                 operand_subword (dest, reverse, TRUE, mode),
+         emit_insn (gen_rtx_SET (operand_subword (dest, reverse, TRUE, mode),
                                  operand_subword (src,  reverse, TRUE, mode)));
 
-         emit_insn (gen_rtx_SET (VOIDmode,
-                                 operand_subword (dest, !reverse, TRUE, mode),
+         emit_insn (gen_rtx_SET (operand_subword (dest, !reverse, TRUE, mode),
                                  operand_subword (src,  !reverse, TRUE, mode)));
        }
 
@@ -1128,12 +1075,10 @@ gen_split_move_double (rtx operands[])
        {
          rtx words[2];
          split_double (src, &words[0], &words[1]);
-         emit_insn (gen_rtx_SET (VOIDmode,
-                                 operand_subword (dest, 0, TRUE, mode),
+         emit_insn (gen_rtx_SET (operand_subword (dest, 0, TRUE, mode),
                                  words[0]));
 
-         emit_insn (gen_rtx_SET (VOIDmode,
-                                 operand_subword (dest, 1, TRUE, mode),
+         emit_insn (gen_rtx_SET (operand_subword (dest, 1, TRUE, mode),
                                  words[1]));
        }
 
@@ -1142,8 +1087,7 @@ gen_split_move_double (rtx operands[])
        {
          /* If the high-address word is used in the address, we must load it
             last.  Otherwise, load it first.  */
-         int reverse
-           = (refers_to_regno_p (dregno, dregno + 1, XEXP (src, 0), 0) != 0);
+         int reverse = refers_to_regno_p (dregno, XEXP (src, 0));
 
          /* We used to optimize loads from single registers as
 
@@ -1156,13 +1100,11 @@ gen_split_move_double (rtx operands[])
                ld r1,r3+; ld r2,r3; addi r3,-4
 
             which saves 2 bytes and doesn't force longword alignment.  */
-         emit_insn (gen_rtx_SET (VOIDmode,
-                                 operand_subword (dest, reverse, TRUE, mode),
+         emit_insn (gen_rtx_SET (operand_subword (dest, reverse, TRUE, mode),
                                  adjust_address (src, SImode,
                                                  reverse * UNITS_PER_WORD)));
 
-         emit_insn (gen_rtx_SET (VOIDmode,
-                                 operand_subword (dest, !reverse, TRUE, mode),
+         emit_insn (gen_rtx_SET (operand_subword (dest, !reverse, TRUE, mode),
                                  adjust_address (src, SImode,
                                                  !reverse * UNITS_PER_WORD)));
        }
@@ -1184,12 +1126,10 @@ gen_split_move_double (rtx operands[])
      which saves 2 bytes and doesn't force longword alignment.  */
   else if (MEM_P (dest) && REG_P (src))
     {
-      emit_insn (gen_rtx_SET (VOIDmode,
-                             adjust_address (dest, SImode, 0),
+      emit_insn (gen_rtx_SET (adjust_address (dest, SImode, 0),
                              operand_subword (src, 0, TRUE, mode)));
 
-      emit_insn (gen_rtx_SET (VOIDmode,
-                             adjust_address (dest, SImode, UNITS_PER_WORD),
+      emit_insn (gen_rtx_SET (adjust_address (dest, SImode, UNITS_PER_WORD),
                              operand_subword (src, 1, TRUE, mode)));
     }
 
@@ -1203,9 +1143,11 @@ gen_split_move_double (rtx operands[])
 
 \f
 static int
-m32r_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+m32r_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
                        tree type, bool named ATTRIBUTE_UNUSED)
 {
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+
   int words;
   unsigned int size =
     (((mode == BLKmode && type)
@@ -1261,10 +1203,12 @@ m32r_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
    and the rest are pushed.  */
 
 static rtx
-m32r_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+m32r_function_arg (cumulative_args_t cum_v, machine_mode mode,
                   const_tree type ATTRIBUTE_UNUSED,
                   bool named ATTRIBUTE_UNUSED)
 {
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+
   return (PASS_IN_REG_P (*cum, mode, type)
          ? gen_rtx_REG (mode, ROUND_ADVANCE_CUM (*cum, mode, type))
          : NULL_RTX);
@@ -1275,9 +1219,11 @@ m32r_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
    (TYPE is null for libcalls where that information may not be available.)  */
 
 static void
-m32r_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+m32r_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
                           const_tree type, bool named ATTRIBUTE_UNUSED)
 {
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+
   *cum = (ROUND_ADVANCE_CUM (*cum, mode, type)
          + ROUND_ADVANCE_ARG (mode, type));
 }
@@ -1287,7 +1233,9 @@ m32r_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 static bool
 m32r_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
 {
-  return m32r_pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  cumulative_args_t dummy = pack_cumulative_args (NULL);
+
+  return m32r_pass_by_reference (dummy, TYPE_MODE (type), type, false);
 }
 
 /* Worker function for TARGET_FUNCTION_VALUE.  */
@@ -1303,7 +1251,7 @@ m32r_function_value (const_tree valtype,
 /* Worker function for TARGET_LIBCALL_VALUE.  */
 
 static rtx
-m32r_libcall_value (enum machine_mode mode,
+m32r_libcall_value (machine_mode mode,
                const_rtx fun ATTRIBUTE_UNUSED)
 {
   return gen_rtx_REG (mode, 0);
@@ -1327,7 +1275,7 @@ m32r_function_value_regno_p (const unsigned int regno)
    and mode MODE, and we rely on this fact.  */
 
 static void
-m32r_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+m32r_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
                             tree type, int *pretend_size, int no_rtl)
 {
   int first_anon_arg;
@@ -1338,7 +1286,7 @@ m32r_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
   /* All BLKmode values are passed by reference.  */
   gcc_assert (mode != BLKmode);
 
-  first_anon_arg = (ROUND_ADVANCE_CUM (*cum, mode, type)
+  first_anon_arg = (ROUND_ADVANCE_CUM (*get_cumulative_args (cum), mode, type)
                    + ROUND_ADVANCE_ARG (mode, type));
 
   if (first_anon_arg < M32R_MAX_PARM_REGS)
@@ -1350,7 +1298,7 @@ m32r_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
       rtx regblock;
 
       regblock = gen_frame_mem (BLKmode,
-                               plus_constant (arg_pointer_rtx,
+                               plus_constant (Pmode, arg_pointer_rtx,
                                               FIRST_PARM_OFFSET (0)));
       set_mem_alias_set (regblock, get_varargs_alias_set ());
       move_block_from_reg (first_reg_offset, regblock, size);
@@ -1367,15 +1315,14 @@ m32r_is_insn (rtx insn)
 {
   return (NONDEBUG_INSN_P (insn)
          && GET_CODE (PATTERN (insn)) != USE
-         && GET_CODE (PATTERN (insn)) != CLOBBER
-         && GET_CODE (PATTERN (insn)) != ADDR_VEC);
+         && GET_CODE (PATTERN (insn)) != CLOBBER);
 }
 
 /* Increase the priority of long instructions so that the
    short instructions are scheduled ahead of the long ones.  */
 
 static int
-m32r_adjust_priority (rtx insn, int priority)
+m32r_adjust_priority (rtx_insn *insn, int priority)
 {
   if (m32r_is_insn (insn)
       && get_attr_insn_size (insn) != INSN_SIZE_SHORT)
@@ -1398,14 +1345,11 @@ m32r_issue_rate (void)
 }
 \f
 /* Cost functions.  */
-
-/* Implement TARGET_HANDLE_OPTION.
-
-   Memory is 3 times as expensive as registers.
+/* Memory is 3 times as expensive as registers.
    ??? Is that the right way to look at it?  */
 
 static int
-m32r_memory_move_cost (enum machine_mode mode,
+m32r_memory_move_cost (machine_mode mode,
                       reg_class_t rclass ATTRIBUTE_UNUSED,
                       bool in ATTRIBUTE_UNUSED)
 {
@@ -1416,9 +1360,13 @@ m32r_memory_move_cost (enum machine_mode mode,
 }
 
 static bool
-m32r_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
+m32r_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+               int outer_code ATTRIBUTE_UNUSED,
+               int opno ATTRIBUTE_UNUSED, int *total,
                bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
       /* Small integers are as cheap as registers.  4 byte values can be
@@ -1714,6 +1662,9 @@ m32r_expand_prologue (void)
   if (! current_frame_info.initialized)
     m32r_compute_frame_size (get_frame_size ());
 
+  if (flag_stack_usage_info)
+    current_function_static_stack_size = current_frame_info.total_size;
+
   gmask = current_frame_info.gmask;
 
   /* These cases shouldn't happen.  Catch them now.  */
@@ -1839,7 +1790,7 @@ m32r_expand_epilogue (void)
 
   if (total_size == 0)
     {
-      rtx insn = get_last_insn ();
+      rtx_insn *insn = get_last_insn ();
 
       /* If the last insn was a BARRIER, we don't have to write any code
         because a jump (aka return) was put there.  */
@@ -2043,7 +1994,7 @@ m32r_legitimize_pic_address (rtx orig, rtx reg)
       if (CONST_INT_P (offset))
         {
           if (INT16_P (INTVAL (offset)))
-            return plus_constant (base, INTVAL (offset));
+            return plus_constant (Pmode, base, INTVAL (offset));
           else
            {
              gcc_assert (! reload_in_progress && ! reload_completed);
@@ -2059,7 +2010,7 @@ m32r_legitimize_pic_address (rtx orig, rtx reg)
 
 static rtx
 m32r_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
-                        enum machine_mode mode ATTRIBUTE_UNUSED)
+                        machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (flag_pic)
     return m32r_legitimize_pic_address (x, NULL_RTX);
@@ -2070,7 +2021,7 @@ m32r_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
 /* Worker function for TARGET_MODE_DEPENDENT_ADDRESS_P.  */
 
 static bool
-m32r_mode_dependent_address_p (const_rtx addr)
+m32r_mode_dependent_address_p (const_rtx addr, addr_space_t as ATTRIBUTE_UNUSED)
 {
   if (GET_CODE (addr) == LO_SUM)
     return true;
@@ -2139,6 +2090,8 @@ m32r_print_operand (FILE * file, rtx x, int code)
        fputs (reg_names[REGNO (x)+1], file);
       else if (MEM_P (x))
        {
+         machine_mode mode = GET_MODE (x);
+
          fprintf (file, "@(");
          /* Handle possible auto-increment.  Since it is pre-increment and
             we have already done it, we can just use an offset of four.  */
@@ -2146,9 +2099,10 @@ m32r_print_operand (FILE * file, rtx x, int code)
             currently necessary, but keep it around.  */
          if (GET_CODE (XEXP (x, 0)) == PRE_INC
              || GET_CODE (XEXP (x, 0)) == PRE_DEC)
-           output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4));
+           output_address (mode, plus_constant (Pmode,
+                                                XEXP (XEXP (x, 0), 0), 4));
          else
-           output_address (plus_constant (XEXP (x, 0), 4));
+           output_address (mode, plus_constant (Pmode, XEXP (x, 0), 4));
          fputc (')', file);
        }
       else
@@ -2308,7 +2262,7 @@ m32r_print_operand (FILE * file, rtx x, int code)
       else
        {
          fputs ("@(", file);
-         output_address (XEXP (x, 0));
+         output_address (GET_MODE (x), addr);
          fputc (')', file);
        }
       break;
@@ -2317,16 +2271,15 @@ m32r_print_operand (FILE * file, rtx x, int code)
       /* We handle SFmode constants here as output_addr_const doesn't.  */
       if (GET_MODE (x) == SFmode)
        {
-         REAL_VALUE_TYPE d;
          long l;
 
-         REAL_VALUE_FROM_CONST_DOUBLE (d, x);
-         REAL_VALUE_TO_TARGET_SINGLE (d, l);
+         REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), l);
          fprintf (file, "0x%08lx", l);
          break;
        }
 
-      /* Fall through.  Let output_addr_const deal with it.  */
+      /* FALLTHRU */
+      /* Let output_addr_const deal with it.  */
 
     default :
       output_addr_const (file, x);
@@ -2337,7 +2290,7 @@ m32r_print_operand (FILE * file, rtx x, int code)
 /* Print a memory address as an operand to reference that memory location.  */
 
 static void
-m32r_print_operand_address (FILE * file, rtx addr)
+m32r_print_operand_address (FILE * file, machine_mode /*mode*/, rtx addr)
 {
   rtx base;
   rtx index = 0;
@@ -2386,7 +2339,8 @@ m32r_print_operand_address (FILE * file, rtx addr)
            fputs ("sda(", file);
          else
            fputs ("low(", file);
-         output_addr_const (file, plus_constant (XEXP (base, 1), offset));
+         output_addr_const (file, plus_constant (Pmode, XEXP (base, 1),
+                                                 offset));
          fputs ("),", file);
          fputs (reg_names[REGNO (XEXP (base, 0))], file);
        }
@@ -2593,7 +2547,7 @@ m32r_expand_block_move (rtx operands[])
   /* If necessary, generate a loop to handle the bulk of the copy.  */
   if (bytes)
     {
-      rtx label = NULL_RTX;
+      rtx_code_label *label = NULL;
       rtx final_src = NULL_RTX;
       rtx at_a_time = GEN_INT (MAX_MOVE_BYTES);
       rtx rounded_total = GEN_INT (bytes);
@@ -2878,7 +2832,7 @@ m32r_rtx_ok_for_offset_p (const_rtx x)
 }
 
 static inline bool
-m32r_legitimate_offset_addres_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+m32r_legitimate_offset_addres_p (machine_mode mode ATTRIBUTE_UNUSED,
                                 const_rtx x, bool strict)
 {
   if (GET_CODE (x) == PLUS
@@ -2893,7 +2847,7 @@ m32r_legitimate_offset_addres_p (enum machine_mode mode ATTRIBUTE_UNUSED,
    since more than one instruction will be required.  */
 
 static inline bool
-m32r_legitimate_lo_sum_addres_p (enum machine_mode mode, const_rtx x,
+m32r_legitimate_lo_sum_addres_p (machine_mode mode, const_rtx x,
                                 bool strict)
 {
   if (GET_CODE (x) == LO_SUM
@@ -2908,7 +2862,7 @@ m32r_legitimate_lo_sum_addres_p (enum machine_mode mode, const_rtx x,
 /* Is this a load and increment operation.  */
 
 static inline bool
-m32r_load_postinc_p (enum machine_mode mode, const_rtx x, bool strict)
+m32r_load_postinc_p (machine_mode mode, const_rtx x, bool strict)
 {
   if ((mode == SImode || mode == SFmode)
       && GET_CODE (x) == POST_INC
@@ -2922,7 +2876,7 @@ m32r_load_postinc_p (enum machine_mode mode, const_rtx x, bool strict)
 /* Is this an increment/decrement and store operation.  */
 
 static inline bool
-m32r_store_preinc_predec_p (enum machine_mode mode, const_rtx x, bool strict)
+m32r_store_preinc_predec_p (machine_mode mode, const_rtx x, bool strict)
 {
   if ((mode == SImode || mode == SFmode)
       && (GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
@@ -2936,7 +2890,7 @@ m32r_store_preinc_predec_p (enum machine_mode mode, const_rtx x, bool strict)
 /* Implement  TARGET_LEGITIMATE_ADDRESS_P.  */
 
 static bool
-m32r_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict)
 {
   if (m32r_rtx_ok_for_base_p (x, strict)
       || m32r_legitimate_offset_addres_p (mode, x, strict)
@@ -2957,3 +2911,21 @@ m32r_conditional_register_usage (void)
       call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
     }
 }
+
+/* Implement TARGET_LEGITIMATE_CONSTANT_P
+
+   We don't allow (plus symbol large-constant) as the relocations can't
+   describe it.  INTVAL > 32767 handles both 16-bit and 24-bit relocations.
+   We allow all CONST_DOUBLE's as the md file patterns will force the
+   constant to memory if they can't handle them.  */
+
+static bool
+m32r_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  return !(GET_CODE (x) == CONST
+          && GET_CODE (XEXP (x, 0)) == PLUS
+          && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+              || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
+          && CONST_INT_P (XEXP (XEXP (x, 0), 1))
+          && UINTVAL (XEXP (XEXP (x, 0), 1)) > 32767);
+}