OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / config / rx / rx.c
index 0179b1f..4a73285 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines used for code generation on Renesas RX processors.
-   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
    Contributed by Red Hat.
 
    This file is part of GCC.
 #include "target.h"
 #include "target-def.h"
 #include "langhooks.h"
+#include "opts.h"
+
+static unsigned int rx_gp_base_regnum_val = INVALID_REGNUM;
+static unsigned int rx_pid_base_regnum_val = INVALID_REGNUM;
+static unsigned int rx_num_interrupt_regs;
 \f
+static unsigned int
+rx_gp_base_regnum (void)
+{
+  if (rx_gp_base_regnum_val == INVALID_REGNUM)
+    gcc_unreachable ();
+  return rx_gp_base_regnum_val;
+}
+
+static unsigned int
+rx_pid_base_regnum (void)
+{
+  if (rx_pid_base_regnum_val == INVALID_REGNUM)
+    gcc_unreachable ();
+  return rx_pid_base_regnum_val;
+}
+
+/* Find a SYMBOL_REF in a "standard" MEM address and return its decl.  */
+
+static tree
+rx_decl_for_addr (rtx op)
+{
+  if (GET_CODE (op) == MEM)
+    op = XEXP (op, 0);
+  if (GET_CODE (op) == CONST)
+    op = XEXP (op, 0);
+  while (GET_CODE (op) == PLUS)
+    op = XEXP (op, 0);
+  if (GET_CODE (op) == SYMBOL_REF)
+    return SYMBOL_REF_DECL (op);
+  return NULL_TREE;
+}
+
 static void rx_print_operand (FILE *, rtx, int);
 
 #define CC_FLAG_S      (1 << 0)
 #define CC_FLAG_Z      (1 << 1)
 #define CC_FLAG_O      (1 << 2)
 #define CC_FLAG_C      (1 << 3)
-#define CC_FLAG_FP     (1 << 4)        /* fake, to differentiate CC_Fmode */
+#define CC_FLAG_FP     (1 << 4)        /* Fake, to differentiate CC_Fmode.  */
 
 static unsigned int flags_from_mode (enum machine_mode mode);
 static unsigned int flags_from_code (enum rtx_code code);
-
-enum rx_cpu_types  rx_cpu_type = RX600;
 \f
+/* Return true if OP is a reference to an object in a PID data area.  */
+
+enum pid_type
+{
+  PID_NOT_PID = 0,     /* The object is not in the PID data area.  */
+  PID_ENCODED,         /* The object is in the PID data area.  */
+  PID_UNENCODED                /* The object will be placed in the PID data area, but it has not been placed there yet.  */
+};
+
+static enum pid_type
+rx_pid_data_operand (rtx op)
+{
+  tree op_decl;
+
+  if (!TARGET_PID)
+    return PID_NOT_PID;
+
+  if (GET_CODE (op) == PLUS
+      && GET_CODE (XEXP (op, 0)) == REG
+      && GET_CODE (XEXP (op, 1)) == CONST
+      && GET_CODE (XEXP (XEXP (op, 1), 0)) == UNSPEC)
+    return PID_ENCODED;
+
+  op_decl = rx_decl_for_addr (op);
+
+  if (op_decl)
+    {
+      if (TREE_READONLY (op_decl))
+       return PID_UNENCODED;
+    }
+  else
+    {
+      /* Sigh, some special cases.  */
+      if (GET_CODE (op) == SYMBOL_REF
+         || GET_CODE (op) == LABEL_REF)
+       return PID_UNENCODED;
+    }
+
+  return PID_NOT_PID;
+}
+
+static rtx
+rx_legitimize_address (rtx x,
+                      rtx oldx ATTRIBUTE_UNUSED,
+                      enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  if (rx_pid_data_operand (x) == PID_UNENCODED)
+    {
+      rtx rv = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), x);
+      return rv;
+    }
+
+  if (GET_CODE (x) == PLUS
+      && GET_CODE (XEXP (x, 0)) == PLUS
+      && REG_P (XEXP (XEXP (x, 0), 0)) 
+      && REG_P (XEXP (x, 1)))
+    return force_reg (SImode, x);
+
+  return x;
+}
+
 /* Return true if OP is a reference to an object in a small data area.  */
 
 static bool
@@ -79,18 +175,31 @@ rx_small_data_operand (rtx op)
 }
 
 static bool
-rx_is_legitimate_address (Mmode mode, rtx x, bool strict ATTRIBUTE_UNUSED)
+rx_is_legitimate_address (enum machine_mode mode, rtx x,
+                         bool strict ATTRIBUTE_UNUSED)
 {
   if (RTX_OK_FOR_BASE (x, strict))
     /* Register Indirect.  */
     return true;
 
-  if (GET_MODE_SIZE (mode) == 4
+  if ((GET_MODE_SIZE (mode) == 4
+       || GET_MODE_SIZE (mode) == 2
+       || GET_MODE_SIZE (mode) == 1)
       && (GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC))
     /* Pre-decrement Register Indirect or
        Post-increment Register Indirect.  */
     return RTX_OK_FOR_BASE (XEXP (x, 0), strict);
 
+  switch (rx_pid_data_operand (x))
+    {
+    case PID_UNENCODED:
+      return false;
+    case PID_ENCODED:
+      return true;
+    default:
+      break;
+    }
+
   if (GET_CODE (x) == PLUS)
     {
       rtx arg1 = XEXP (x, 0);
@@ -116,7 +225,7 @@ rx_is_legitimate_address (Mmode mode, rtx x, bool strict ATTRIBUTE_UNUSED)
 
            if (val < 0)
              return false;
-           
+
            switch (GET_MODE_SIZE (mode))
              {
              default: 
@@ -166,8 +275,6 @@ rx_is_legitimate_address (Mmode mode, rtx x, bool strict ATTRIBUTE_UNUSED)
 bool
 rx_is_restricted_memory_address (rtx mem, enum machine_mode mode)
 {
-  rtx base, index;
-
   if (! rx_is_legitimate_address
       (mode, mem, reload_in_progress || reload_completed))
     return false;
@@ -183,11 +290,18 @@ rx_is_restricted_memory_address (rtx mem, enum machine_mode mode)
       return false;
 
     case PLUS:
-      /* Only allow REG+INT addressing.  */
-      base = XEXP (mem, 0);
-      index = XEXP (mem, 1);
+      {
+       rtx base, index;
+       
+       /* Only allow REG+INT addressing.  */
+       base = XEXP (mem, 0);
+       index = XEXP (mem, 1);
 
-      return RX_REG_P (base) && CONST_INT_P (index);
+       if (! RX_REG_P (base) || ! CONST_INT_P (index))
+         return false;
+
+       return IN_RANGE (INTVAL (index), 0, (0x10000 * GET_MODE_SIZE (mode)) - 1);
+      }
 
     case SYMBOL_REF:
       /* Can happen when small data is being supported.
@@ -199,8 +313,10 @@ rx_is_restricted_memory_address (rtx mem, enum machine_mode mode)
     }
 }
 
-bool
-rx_is_mode_dependent_addr (rtx addr)
+/* Implement TARGET_MODE_DEPENDENT_ADDRESS_P.  */
+
+static bool
+rx_mode_dependent_address_p (const_rtx addr)
 {
   if (GET_CODE (addr) == CONST)
     addr = XEXP (addr, 0);
@@ -323,10 +439,22 @@ rx_print_operand_address (FILE * file, rtx addr)
        break;
       }
 
+    case CONST:
+      if (GET_CODE (XEXP (addr, 0)) == UNSPEC)
+       {
+         addr = XEXP (addr, 0);
+         gcc_assert (XINT (addr, 1) == UNSPEC_CONST);
+
+         /* FIXME: Putting this case label here is an appalling abuse of the C language.  */
+       case UNSPEC:
+          addr = XVECEXP (addr, 0, 0);
+         gcc_assert (CONST_INT_P (addr));
+       }
+      /* Fall through.  */
     case LABEL_REF:
     case SYMBOL_REF:
-    case CONST:
       fprintf (file, "#");
+      /* Fall through.  */
     default:
       output_addr_const (file, addr);
       break;
@@ -370,15 +498,30 @@ rx_assemble_integer (rtx x, unsigned int size, int is_aligned)
      %B  Print an integer comparison name.
      %C  Print a control register name.
      %F  Print a condition code flag name.
+     %G  Register used for small-data-area addressing
      %H  Print high part of a DImode register, integer or address.
      %L  Print low part of a DImode register, integer or address.
      %N  Print the negation of the immediate value.
+     %P  Register used for PID addressing
      %Q  If the operand is a MEM, then correctly generate
-         register indirect or register relative addressing.  */
+         register indirect or register relative addressing.
+     %R  Like %Q but for zero-extending loads.  */
 
 static void
 rx_print_operand (FILE * file, rtx op, int letter)
 {
+  bool unsigned_load = false;
+  bool print_hash = true;
+
+  if (letter == 'A'
+      && ((GET_CODE (op) == CONST
+          && GET_CODE (XEXP (op, 0)) == UNSPEC)
+         || GET_CODE (op) == UNSPEC))
+    {
+      print_hash = false;
+      letter = 0;
+    }
+
   switch (letter)
     {
     case 'A':
@@ -437,13 +580,15 @@ rx_print_operand (FILE * file, rtx op, int letter)
          }
        else
          {
+           unsigned int flags = flags_from_mode (mode);
+
            switch (code)
              {
              case LT:
-               ret = "n";
+               ret = (flags & CC_FLAG_O ? "lt" : "n");
                break;
              case GE:
-               ret = "pz";
+               ret = (flags & CC_FLAG_O ? "ge" : "pz");
                break;
              case GT:
                ret = "gt";
@@ -472,8 +617,7 @@ rx_print_operand (FILE * file, rtx op, int letter)
              default:
                gcc_unreachable ();
              }
-           gcc_checking_assert ((flags_from_code (code)
-                                 & ~flags_from_mode (mode)) == 0);
+           gcc_checking_assert ((flags_from_code (code) & ~flags) == 0);
          }
        fputs (ret, file);
        break;
@@ -493,7 +637,7 @@ rx_print_operand (FILE * file, rtx op, int letter)
        case 0xb: fprintf (file, "fintv"); break;
        case 0xc: fprintf (file, "intb"); break;
        default:
-         warning (0, "unreocgnized control register number: %d - using 'psw'",
+         warning (0, "unrecognized control register number: %d - using 'psw'",
                   (int) INTVAL (op));
          fprintf (file, "psw");
          break;
@@ -515,6 +659,10 @@ rx_print_operand (FILE * file, rtx op, int letter)
        }
       break;
 
+    case 'G':
+      fprintf (file, "%s", reg_names [rx_gp_base_regnum ()]);
+      break;
+
     case 'H':
       switch (GET_CODE (op))
        {
@@ -576,10 +724,19 @@ rx_print_operand (FILE * file, rtx op, int letter)
       rx_print_integer (file, - INTVAL (op));
       break;
 
+    case 'P':
+      fprintf (file, "%s", reg_names [rx_pid_base_regnum ()]);
+      break;
+
+    case 'R':
+      gcc_assert (GET_MODE_SIZE (GET_MODE (op)) < 4);
+      unsigned_load = true;
+      /* Fall through.  */
     case 'Q':
       if (MEM_P (op))
        {
          HOST_WIDE_INT offset;
+         rtx mem = op;
 
          op = XEXP (op, 0);
 
@@ -614,22 +771,24 @@ rx_print_operand (FILE * file, rtx op, int letter)
          rx_print_operand (file, op, 0);
          fprintf (file, "].");
 
-         switch (GET_MODE_SIZE (GET_MODE (op)))
+         switch (GET_MODE_SIZE (GET_MODE (mem)))
            {
            case 1:
-             gcc_assert (offset < 65535 * 1);
-             fprintf (file, "B");
+             gcc_assert (offset <= 65535 * 1);
+             fprintf (file, unsigned_load ? "UB" : "B");
              break;
            case 2:
              gcc_assert (offset % 2 == 0);
-             gcc_assert (offset < 65535 * 2);
-             fprintf (file, "W");
+             gcc_assert (offset <= 65535 * 2);
+             fprintf (file, unsigned_load ? "UW" : "W");
              break;
-           default:
+           case 4:
              gcc_assert (offset % 4 == 0);
-             gcc_assert (offset < 65535 * 4);
+             gcc_assert (offset <= 65535 * 4);
              fprintf (file, "L");
              break;
+           default:
+             gcc_unreachable ();
            }
          break;
        }
@@ -637,6 +796,24 @@ rx_print_operand (FILE * file, rtx op, int letter)
       /* Fall through.  */
 
     default:
+      if (GET_CODE (op) == CONST
+         && GET_CODE (XEXP (op, 0)) == UNSPEC)
+       op = XEXP (op, 0);
+      else if (GET_CODE (op) == CONST
+              && GET_CODE (XEXP (op, 0)) == PLUS
+              && GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC
+              && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+       {
+         if (print_hash)
+           fprintf (file, "#");
+         fprintf (file, "(");
+         rx_print_operand (file, XEXP (XEXP (op, 0), 0), 'A');
+         fprintf (file, " + ");
+         output_addr_const (file, XEXP (XEXP (op, 0), 1));
+         fprintf (file, ")");
+         return;
+       }
+
       switch (GET_CODE (op))
        {
        case MULT:
@@ -691,20 +868,52 @@ rx_print_operand (FILE * file, rtx op, int letter)
 
            REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
            REAL_VALUE_TO_TARGET_SINGLE (rv, val);
-           fprintf (file, TARGET_AS100_SYNTAX ? "#0%lxH" : "#0x%lx", val);
+           if (print_hash)
+             fprintf (file, "#");
+           fprintf (file, TARGET_AS100_SYNTAX ? "0%lxH" : "0x%lx", val);
            break;
          }
 
        case CONST_INT:
-         fprintf (file, "#");
+         if (print_hash)
+           fprintf (file, "#");
          rx_print_integer (file, INTVAL (op));
          break;
 
-       case SYMBOL_REF:
+       case UNSPEC:
+         switch (XINT (op, 1))
+           {
+           case UNSPEC_PID_ADDR:
+             {
+               rtx sym, add;
+
+               if (print_hash)
+                 fprintf (file, "#");
+               sym = XVECEXP (op, 0, 0);
+               add = NULL_RTX;
+               fprintf (file, "(");
+               if (GET_CODE (sym) == PLUS)
+                 {
+                   add = XEXP (sym, 1);
+                   sym = XEXP (sym, 0);
+                 }
+               output_addr_const (file, sym);
+               if (add != NULL_RTX)
+                 {
+                   fprintf (file, "+");
+                   output_addr_const (file, add);
+                 }
+               fprintf (file, "-__pid_base");
+               fprintf (file, ")");
+               return;
+             }
+           }
+         /* Fall through */
+
        case CONST:
+       case SYMBOL_REF:
        case LABEL_REF:
        case CODE_LABEL:
-       case UNSPEC:
          rx_print_operand_address (file, op);
          break;
 
@@ -715,6 +924,29 @@ rx_print_operand (FILE * file, rtx op, int letter)
     }
 }
 
+/* Maybe convert an operand into its PID format.  */
+
+rtx
+rx_maybe_pidify_operand (rtx op, int copy_to_reg)
+{
+  if (rx_pid_data_operand (op) == PID_UNENCODED)
+    {
+      if (GET_CODE (op) == MEM)
+       {
+         rtx a = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), XEXP (op, 0));
+         op = replace_equiv_address (op, a);
+       }
+      else
+       {
+         op = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), op);
+       }
+
+      if (copy_to_reg)
+       op = copy_to_mode_reg (GET_MODE (op), op);
+    }
+  return op;
+}
+
 /* Returns an assembler template for a move instruction.  */
 
 char *
@@ -754,13 +986,15 @@ rx_gen_move_template (rtx * operands, bool is_movu)
       gcc_unreachable ();
     }
 
-  if (MEM_P (src) && rx_small_data_operand (XEXP (src, 0)))
-    src_template = "%%gp(%A1)[r13]";
+  if (MEM_P (src) && rx_pid_data_operand (XEXP (src, 0)) == PID_UNENCODED)
+    src_template = "(%A1-__pid_base)[%P1]";
+  else if (MEM_P (src) && rx_small_data_operand (XEXP (src, 0)))
+    src_template = "%%gp(%A1)[%G1]";
   else
     src_template = "%1";
 
   if (MEM_P (dest) && rx_small_data_operand (XEXP (dest, 0)))
-    dst_template = "%%gp(%A0)[r13]";
+    dst_template = "%%gp(%A0)[%G0]";
   else
     dst_template = "%0";
 
@@ -782,7 +1016,7 @@ rx_round_up (unsigned int value, unsigned int alignment)
    occupied by an argument of type TYPE and mode MODE.  */
 
 static unsigned int
-rx_function_arg_size (Mmode mode, const_tree type)
+rx_function_arg_size (enum machine_mode mode, const_tree type)
 {
   unsigned int num_bytes;
 
@@ -802,10 +1036,11 @@ rx_function_arg_size (Mmode mode, const_tree type)
    variable parameter list.  */
 
 static rtx
-rx_function_arg (Fargs * cum, Mmode mode, const_tree type, bool named)
+rx_function_arg (cumulative_args_t cum, enum machine_mode mode,
+                const_tree type, bool named)
 {
   unsigned int next_reg;
-  unsigned int bytes_so_far = *cum;
+  unsigned int bytes_so_far = *get_cumulative_args (cum);
   unsigned int size;
   unsigned int rounded_size;
 
@@ -839,14 +1074,14 @@ rx_function_arg (Fargs * cum, Mmode mode, const_tree type, bool named)
 }
 
 static void
-rx_function_arg_advance (Fargs * cum, Mmode mode, const_tree type,
-                        bool named ATTRIBUTE_UNUSED)
+rx_function_arg_advance (cumulative_args_t cum, enum machine_mode mode,
+                        const_tree type, bool named ATTRIBUTE_UNUSED)
 {
-  *cum += rx_function_arg_size (mode, type);
+  *get_cumulative_args (cum) += rx_function_arg_size (mode, type);
 }
 
 static unsigned int
-rx_function_arg_boundary (Mmode mode ATTRIBUTE_UNUSED,
+rx_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
                          const_tree type ATTRIBUTE_UNUSED)
 {
   return 32;
@@ -864,7 +1099,10 @@ rx_function_value (const_tree ret_type,
 
   /* RX ABI specifies that small integer types are
      promoted to int when returned by a function.  */
-  if (GET_MODE_SIZE (mode) > 0 && GET_MODE_SIZE (mode) < 4)
+  if (GET_MODE_SIZE (mode) > 0
+      && GET_MODE_SIZE (mode) < 4
+      && ! COMPLEX_MODE_P (mode)
+      )
     return gen_rtx_REG (SImode, FUNC_RETURN_REGNUM);
     
   return gen_rtx_REG (mode, FUNC_RETURN_REGNUM);
@@ -882,6 +1120,7 @@ rx_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
 {
   if (for_return != 1
       || GET_MODE_SIZE (mode) >= 4
+      || COMPLEX_MODE_P (mode)
       || GET_MODE_SIZE (mode) < 1)
     return mode;
 
@@ -961,8 +1200,21 @@ rx_conditional_register_usage (void)
 {
   static bool using_fixed_regs = false;
 
+  if (TARGET_PID)
+    {
+      rx_pid_base_regnum_val = GP_BASE_REGNUM - rx_num_interrupt_regs;
+      fixed_regs[rx_pid_base_regnum_val] = call_used_regs [rx_pid_base_regnum_val] = 1;
+    }
+
   if (rx_small_data_limit > 0)
-    fixed_regs[GP_BASE_REGNUM] = call_used_regs [GP_BASE_REGNUM] = 1;
+    {
+      if (TARGET_PID)
+       rx_gp_base_regnum_val = rx_pid_base_regnum_val - 1;
+      else
+       rx_gp_base_regnum_val = GP_BASE_REGNUM - rx_num_interrupt_regs;
+
+      fixed_regs[rx_gp_base_regnum_val] = call_used_regs [rx_gp_base_regnum_val] = 1;
+    }
 
   if (use_fixed_regs != using_fixed_regs)
     {
@@ -1123,10 +1375,12 @@ rx_get_stack_layout (unsigned int * lowest,
   for (save_mask = high = low = 0, reg = 1; reg < CC_REGNUM; reg++)
     {
       if ((df_regs_ever_live_p (reg)
-          /* Always save all call clobbered registers inside interrupt
-             handlers, even if they are not live - they may be used in
-             routines called from this one.  */
-          || (call_used_regs[reg] && is_interrupt_func (NULL_TREE)))
+          /* Always save all call clobbered registers inside non-leaf
+             interrupt handlers, even if they are not live - they may
+             be used in (non-interrupt aware) routines called from this one.  */
+          || (call_used_regs[reg]
+              && is_interrupt_func (NULL_TREE)
+              && ! current_function_is_leaf))
          && (! call_used_regs[reg]
              /* Even call clobbered registered must
                 be pushed inside interrupt handlers.  */
@@ -1281,6 +1535,59 @@ mark_frame_related (rtx insn)
     }
 }
 
+static bool
+ok_for_max_constant (HOST_WIDE_INT val)
+{
+  if (rx_max_constant_size == 0  || rx_max_constant_size == 4)
+    /* If there is no constraint on the size of constants
+       used as operands, then any value is legitimate.  */
+    return true;
+
+  /* rx_max_constant_size specifies the maximum number
+     of bytes that can be used to hold a signed value.  */
+  return IN_RANGE (val, (-1 << (rx_max_constant_size * 8)),
+                       ( 1 << (rx_max_constant_size * 8)));
+}
+
+/* Generate an ADD of SRC plus VAL into DEST.
+   Handles the case where VAL is too big for max_constant_value.
+   Sets FRAME_RELATED_P on the insn if IS_FRAME_RELATED is true.  */
+
+static void
+gen_safe_add (rtx dest, rtx src, rtx val, bool is_frame_related)
+{
+  rtx insn;
+
+  if (val == NULL_RTX || INTVAL (val) == 0)
+    {
+      gcc_assert (dest != src);
+
+      insn = emit_move_insn (dest, src);
+    }
+  else if (ok_for_max_constant (INTVAL (val)))
+    insn = emit_insn (gen_addsi3 (dest, src, val));
+  else
+    {
+      /* Wrap VAL in an UNSPEC so that rx_is_legitimate_constant
+        will not reject it.  */
+      val = gen_rtx_CONST (SImode, gen_rtx_UNSPEC (SImode, gen_rtvec (1, val), UNSPEC_CONST));
+      insn = emit_insn (gen_addsi3 (dest, src, val));
+
+      if (is_frame_related)
+       /* We have to provide our own frame related note here
+          as the dwarf2out code cannot be expected to grok
+          our unspec.  */
+       add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+                     gen_rtx_SET (SImode, dest,
+                                  gen_rtx_PLUS (SImode, src, val)));
+      return;
+    }
+
+  if (is_frame_related)
+    RTX_FRAME_RELATED_P (insn) = 1;
+  return;
+}
+
 void
 rx_expand_prologue (void)
 {
@@ -1370,17 +1677,8 @@ rx_expand_prologue (void)
 
   /* If needed, set up the frame pointer.  */
   if (frame_pointer_needed)
-    {
-      if (frame_size)
-       insn = emit_insn (gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
-                                     GEN_INT (- (HOST_WIDE_INT) frame_size)));
-      else
-       insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
-
-      RTX_FRAME_RELATED_P (insn) = 1;
-    }
-
-  insn = NULL_RTX;
+    gen_safe_add (frame_pointer_rtx, stack_pointer_rtx,
+                 GEN_INT (- (HOST_WIDE_INT) frame_size), true);
 
   /* Allocate space for the outgoing args.
      If the stack frame has not already been set up then handle this as well.  */
@@ -1389,29 +1687,26 @@ rx_expand_prologue (void)
       if (frame_size)
        {
          if (frame_pointer_needed)
-           insn = emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx,
-                                         GEN_INT (- (HOST_WIDE_INT)
-                                                  stack_size)));
+           gen_safe_add (stack_pointer_rtx, frame_pointer_rtx,
+                         GEN_INT (- (HOST_WIDE_INT) stack_size), true);
          else
-           insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                         GEN_INT (- (HOST_WIDE_INT)
-                                                  (frame_size + stack_size))));
+           gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
+                         GEN_INT (- (HOST_WIDE_INT) (frame_size + stack_size)),
+                         true);
        }
       else
-       insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                     GEN_INT (- (HOST_WIDE_INT) stack_size)));
+       gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
+                     GEN_INT (- (HOST_WIDE_INT) stack_size), true);
     }
   else if (frame_size)
     {
       if (! frame_pointer_needed)
-       insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                     GEN_INT (- (HOST_WIDE_INT) frame_size)));
+       gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
+                     GEN_INT (- (HOST_WIDE_INT) frame_size), true);
       else
-       insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+       gen_safe_add (stack_pointer_rtx, frame_pointer_rtx, NULL_RTX,
+                     true);
     }
-
-  if (insn != NULL_RTX)
-    RTX_FRAME_RELATED_P (insn) = 1;
 }
 
 static void
@@ -1491,7 +1786,7 @@ gen_rx_rtsd_vector (unsigned int adjust, unsigned int low, unsigned int high)
                                : plus_constant (stack_pointer_rtx,
                                                 i * UNITS_PER_WORD)));
 
-  XVECEXP (vector, 0, count - 1) = gen_rtx_RETURN (VOIDmode);
+  XVECEXP (vector, 0, count - 1) = ret_rtx;
 
   return vector;
 }
@@ -1589,8 +1884,8 @@ rx_expand_epilogue (bool is_sibcall)
     {
       /* Cannot use the special instructions - deconstruct by hand.  */
       if (total_size)
-       emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                              GEN_INT (total_size)));
+       gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
+                     GEN_INT (total_size), false);
 
       if (MUST_SAVE_ACC_REGISTER)
        {
@@ -1682,8 +1977,8 @@ rx_expand_epilogue (bool is_sibcall)
          return;
        }
 
-      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                            GEN_INT (total_size)));
+      gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
+                   GEN_INT (total_size), false);
     }
 
   if (low)
@@ -1852,11 +2147,14 @@ enum rx_builtin
   RX_BUILTIN_max
 };
 
+static GTY(()) tree rx_builtins[(int) RX_BUILTIN_max];
+
 static void
 rx_init_builtins (void)
 {
 #define ADD_RX_BUILTIN1(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE)          \
-  add_builtin_function ("__builtin_rx_" LC_NAME,                       \
+   rx_builtins[RX_BUILTIN_##UC_NAME] =                                 \
+   add_builtin_function ("__builtin_rx_" LC_NAME,                      \
                        build_function_type_list (RET_TYPE##_type_node, \
                                                  ARG_TYPE##_type_node, \
                                                  NULL_TREE),           \
@@ -1864,6 +2162,7 @@ rx_init_builtins (void)
                        BUILT_IN_MD, NULL, NULL_TREE)
 
 #define ADD_RX_BUILTIN2(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE1, ARG_TYPE2) \
+  rx_builtins[RX_BUILTIN_##UC_NAME] =                                  \
   add_builtin_function ("__builtin_rx_" LC_NAME,                       \
                        build_function_type_list (RET_TYPE##_type_node, \
                                                  ARG_TYPE1##_type_node,\
@@ -1873,6 +2172,7 @@ rx_init_builtins (void)
                        BUILT_IN_MD, NULL, NULL_TREE)
 
 #define ADD_RX_BUILTIN3(UC_NAME,LC_NAME,RET_TYPE,ARG_TYPE1,ARG_TYPE2,ARG_TYPE3) \
+  rx_builtins[RX_BUILTIN_##UC_NAME] =                                  \
   add_builtin_function ("__builtin_rx_" LC_NAME,                       \
                        build_function_type_list (RET_TYPE##_type_node, \
                                                  ARG_TYPE1##_type_node,\
@@ -1904,6 +2204,17 @@ rx_init_builtins (void)
   ADD_RX_BUILTIN1 (WAIT,    "wait",    void,  void);
 }
 
+/* Return the RX builtin for CODE.  */
+
+static tree
+rx_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
+{
+  if (code >= RX_BUILTIN_max)
+    return error_mark_node;
+
+  return rx_builtins[code];
+}
+
 static rtx
 rx_expand_void_builtin_1_arg (rtx arg, rtx (* gen_func)(rtx), bool reg)
 {
@@ -2178,70 +2489,17 @@ rx_handle_func_attribute (tree * node,
 /* Table of RX specific attributes.  */
 const struct attribute_spec rx_attribute_table[] =
 {
-  /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler.  */
-  { "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute },
-  { "interrupt",      0, 0, true, false, false, rx_handle_func_attribute },
-  { "naked",          0, 0, true, false, false, rx_handle_func_attribute },
-  { NULL,             0, 0, false, false, false, NULL }
+  /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+     affects_type_identity.  */
+  { "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
+    false },
+  { "interrupt",      0, 0, true, false, false, rx_handle_func_attribute,
+    false },
+  { "naked",          0, 0, true, false, false, rx_handle_func_attribute,
+    false },
+  { NULL,             0, 0, false, false, false, NULL, false }
 };
 
-/* Extra processing for target specific command line options.  */
-
-static bool
-rx_handle_option (size_t code, const char *  arg ATTRIBUTE_UNUSED, int value)
-{
-  switch (code)
-    {
-    case OPT_mint_register_:
-      switch (value)
-       {
-       case 4:
-         fixed_regs[10] = call_used_regs [10] = 1;
-         /* Fall through.  */
-       case 3:
-         fixed_regs[11] = call_used_regs [11] = 1;
-         /* Fall through.  */
-       case 2:
-         fixed_regs[12] = call_used_regs [12] = 1;
-         /* Fall through.  */
-       case 1:
-         fixed_regs[13] = call_used_regs [13] = 1;
-         /* Fall through.  */
-       case 0:
-         return true;
-       default:
-         return false;
-       }
-      break;
-
-    case OPT_mmax_constant_size_:
-      /* Make sure that the -mmax-constant_size option is in range.  */
-      return value >= 0 && value <= 4;
-
-    case OPT_mcpu_:
-      if (strcasecmp (arg, "RX610") == 0)
-       rx_cpu_type = RX610;
-      else if (strcasecmp (arg, "RX200") == 0)
-       {
-         target_flags |= MASK_NO_USE_FPU;
-         rx_cpu_type = RX200;
-       }
-      else if (strcasecmp (arg, "RX600") != 0)
-       warning (0, "unrecognized argument '%s' to -mcpu= option", arg);
-      break;
-      
-    case OPT_fpu:
-      if (rx_cpu_type == RX200)
-       error ("the RX200 cpu does not have FPU hardware");
-      break;
-
-    default:
-      break;
-    }
-
-  return true;
-}
-
 /* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE.  */
 
 static void
@@ -2272,19 +2530,59 @@ rx_override_options_after_change (void)
 static void
 rx_option_override (void)
 {
+  unsigned int i;
+  cl_deferred_option *opt;
+  VEC(cl_deferred_option,heap) *vec
+    = (VEC(cl_deferred_option,heap) *) rx_deferred_options;
+
+  FOR_EACH_VEC_ELT (cl_deferred_option, vec, i, opt)
+    {
+      switch (opt->opt_index)
+       {
+       case OPT_mint_register_:
+         switch (opt->value)
+           {
+           case 4:
+             fixed_regs[10] = call_used_regs [10] = 1;
+             /* Fall through.  */
+           case 3:
+             fixed_regs[11] = call_used_regs [11] = 1;
+             /* Fall through.  */
+           case 2:
+             fixed_regs[12] = call_used_regs [12] = 1;
+             /* Fall through.  */
+           case 1:
+             fixed_regs[13] = call_used_regs [13] = 1;
+             /* Fall through.  */
+           case 0:
+             rx_num_interrupt_regs = opt->value;
+             break;
+           default:
+             rx_num_interrupt_regs = 0;
+             /* Error message already given because rx_handle_option
+                returned false.  */
+             break;
+           }
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+    }
+
   /* This target defaults to strict volatile bitfields.  */
-  if (flag_strict_volatile_bitfields < 0)
+  if (flag_strict_volatile_bitfields < 0 && abi_version_at_least(2))
     flag_strict_volatile_bitfields = 1;
 
   rx_override_options_after_change ();
-}
 
-/* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
-static const struct default_options rx_option_optimization_table[] =
-  {
-    { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
-    { OPT_LEVELS_NONE, 0, NULL, 0 }
-  };
+  if (align_jumps == 0 && ! optimize_size)
+    align_jumps = 3;
+  if (align_loops == 0 && ! optimize_size)
+    align_loops = 3;
+  if (align_labels == 0 && ! optimize_size)
+    align_labels = 3;
+}
 
 \f
 static bool
@@ -2340,10 +2638,8 @@ rx_is_ms_bitfield_layout (const_tree record_type ATTRIBUTE_UNUSED)
    operand on the RX.  X is already known to satisfy CONSTANT_P.  */
 
 bool
-rx_is_legitimate_constant (rtx x)
+rx_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 {
-  HOST_WIDE_INT val;
-
   switch (GET_CODE (x))
     {
     case CONST:
@@ -2366,11 +2662,12 @@ rx_is_legitimate_constant (rtx x)
        case SYMBOL_REF:
          return true;
 
-         /* One day we may have to handle UNSPEC constants here.  */
+       case UNSPEC:
+         return XINT (x, 1) == UNSPEC_CONST || XINT (x, 1) == UNSPEC_PID_ADDR;
+
        default:
          /* FIXME: Can this ever happen ?  */
-         abort ();
-         return false;
+         gcc_unreachable ();
        }
       break;
       
@@ -2386,17 +2683,7 @@ rx_is_legitimate_constant (rtx x)
       break;
     }
 
-  if (rx_max_constant_size == 0  || rx_max_constant_size == 4)
-    /* If there is no constraint on the size of constants
-       used as operands, then any value is legitimate.  */
-    return true;
-
-  val = INTVAL (x);
-
-  /* rx_max_constant_size specifies the maximum number
-     of bytes that can be used to hold a signed value.  */
-  return IN_RANGE (val, (-1 << (rx_max_constant_size * 8)),
-                       ( 1 << (rx_max_constant_size * 8)));
+  return ok_for_max_constant (INTVAL (x));
 }
 
 static int
@@ -2521,9 +2808,11 @@ rx_trampoline_init (rtx tramp, tree fndecl, rtx chain)
 }
 \f
 static int
-rx_memory_move_cost (enum machine_mode mode, reg_class_t regclass, bool in)
+rx_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                    reg_class_t regclass ATTRIBUTE_UNUSED,
+                    bool in)
 {
-  return 2 + memory_move_secondary_cost (mode, regclass, in);
+  return (in ? 2 : 0) + REGISTER_MOVE_COST (mode, regclass, regclass);
 }
 
 /* Convert a CC_MODE to the set of flags that it represents.  */
@@ -2619,74 +2908,15 @@ rx_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
 /* Return the minimal CC mode needed to implement (CMP_CODE X Y).  */
 
 enum machine_mode
-rx_select_cc_mode (enum rtx_code cmp_code, rtx x, rtx y ATTRIBUTE_UNUSED)
+rx_select_cc_mode (enum rtx_code cmp_code, rtx x, rtx y)
 {
   if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
     return CC_Fmode;
 
-  return mode_from_flags (flags_from_code (cmp_code));
-}
-
-/* Split the floating-point comparison IN into individual comparisons
-   O1 and O2.  O2 may be UNKNOWN if there is no second comparison.
-   Return true iff the comparison operands must be swapped.  */
-
-bool
-rx_split_fp_compare (enum rtx_code in, enum rtx_code *o1, enum rtx_code *o2)
-{
-  enum rtx_code cmp1 = in, cmp2 = UNKNOWN;
-  bool swap = false;
-
-  switch (in)
-    {
-    case ORDERED:
-    case UNORDERED:
-    case LT:
-    case GE:
-    case EQ:
-    case NE:
-      break;
-
-    case GT:
-    case LE:
-      cmp1 = swap_condition (cmp1);
-      swap = true;
-      break;
-
-    case UNEQ:
-      cmp1 = UNORDERED;
-      cmp2 = EQ;
-      break;
-    case UNLT:
-      cmp1 = UNORDERED;
-      cmp2 = LT;
-      break;
-    case UNGE:
-      cmp1 = UNORDERED;
-      cmp2 = GE;
-      break;
-    case UNLE:
-      cmp1 = UNORDERED;
-      cmp2 = GT;
-      swap = true;
-      break;
-    case UNGT:
-      cmp1 = UNORDERED;
-      cmp2 = LE;
-      swap = true;
-      break;
-    case LTGT:
-      cmp1 = ORDERED;
-      cmp2 = NE;
-      break;
+  if (y != const0_rtx)
+    return CCmode;
 
-    default:
-      gcc_unreachable ();
-    }
-
-  *o1 = cmp1;
-  *o2 = cmp2;
-  return swap;
+  return mode_from_flags (flags_from_code (cmp_code));
 }
 
 /* Split the conditional branch.  Emit (COMPARE C1 C2) into CC_REG with
@@ -2736,8 +2966,161 @@ rx_match_ccmode (rtx insn, enum machine_mode cc_mode)
 
   return true;
 }
+\f
+int
+rx_align_for_label (rtx lab, int uses_threshold)
+{
+  /* This is a simple heuristic to guess when an alignment would not be useful
+     because the delay due to the inserted NOPs would be greater than the delay
+     due to the misaligned branch.  If uses_threshold is zero then the alignment
+     is always useful.  */
+  if (LABEL_P (lab) && LABEL_NUSES (lab) < uses_threshold)
+    return 0;
 
+  return optimize_size ? 1 : 3;
+}
+
+static int
+rx_max_skip_for_label (rtx lab)
+{
+  int opsize;
+  rtx op;
+
+  if (lab == NULL_RTX)
+    return 0;
+
+  op = lab;
+  do
+    {
+      op = next_nonnote_nondebug_insn (op);
+    }
+  while (op && (LABEL_P (op)
+               || (INSN_P (op) && GET_CODE (PATTERN (op)) == USE)));
+  if (!op)
+    return 0;
+
+  opsize = get_attr_length (op);
+  if (opsize >= 0 && opsize < 8)
+    return opsize - 1;
+  return 0;
+}
+
+/* Compute the real length of the extending load-and-op instructions.  */
+
+int
+rx_adjust_insn_length (rtx insn, int current_length)
+{
+  rtx extend, mem, offset;
+  bool zero;
+  int factor;
+
+  switch (INSN_CODE (insn))
+    {
+    default:
+      return current_length;
+
+    case CODE_FOR_plussi3_zero_extendhi:
+    case CODE_FOR_andsi3_zero_extendhi:
+    case CODE_FOR_iorsi3_zero_extendhi:
+    case CODE_FOR_xorsi3_zero_extendhi:
+    case CODE_FOR_divsi3_zero_extendhi:
+    case CODE_FOR_udivsi3_zero_extendhi:
+    case CODE_FOR_minussi3_zero_extendhi:
+    case CODE_FOR_smaxsi3_zero_extendhi:
+    case CODE_FOR_sminsi3_zero_extendhi:
+    case CODE_FOR_multsi3_zero_extendhi:
+    case CODE_FOR_comparesi3_zero_extendhi:
+      zero = true;
+      factor = 2;
+      break;
+
+    case CODE_FOR_plussi3_sign_extendhi:
+    case CODE_FOR_andsi3_sign_extendhi:
+    case CODE_FOR_iorsi3_sign_extendhi:
+    case CODE_FOR_xorsi3_sign_extendhi:
+    case CODE_FOR_divsi3_sign_extendhi:
+    case CODE_FOR_udivsi3_sign_extendhi:
+    case CODE_FOR_minussi3_sign_extendhi:
+    case CODE_FOR_smaxsi3_sign_extendhi:
+    case CODE_FOR_sminsi3_sign_extendhi:
+    case CODE_FOR_multsi3_sign_extendhi:
+    case CODE_FOR_comparesi3_sign_extendhi:
+      zero = false;
+      factor = 2;
+      break;
+      
+    case CODE_FOR_plussi3_zero_extendqi:
+    case CODE_FOR_andsi3_zero_extendqi:
+    case CODE_FOR_iorsi3_zero_extendqi:
+    case CODE_FOR_xorsi3_zero_extendqi:
+    case CODE_FOR_divsi3_zero_extendqi:
+    case CODE_FOR_udivsi3_zero_extendqi:
+    case CODE_FOR_minussi3_zero_extendqi:
+    case CODE_FOR_smaxsi3_zero_extendqi:
+    case CODE_FOR_sminsi3_zero_extendqi:
+    case CODE_FOR_multsi3_zero_extendqi:
+    case CODE_FOR_comparesi3_zero_extendqi:
+      zero = true;
+      factor = 1;
+      break;
+      
+    case CODE_FOR_plussi3_sign_extendqi:
+    case CODE_FOR_andsi3_sign_extendqi:
+    case CODE_FOR_iorsi3_sign_extendqi:
+    case CODE_FOR_xorsi3_sign_extendqi:
+    case CODE_FOR_divsi3_sign_extendqi:
+    case CODE_FOR_udivsi3_sign_extendqi:
+    case CODE_FOR_minussi3_sign_extendqi:
+    case CODE_FOR_smaxsi3_sign_extendqi:
+    case CODE_FOR_sminsi3_sign_extendqi:
+    case CODE_FOR_multsi3_sign_extendqi:
+    case CODE_FOR_comparesi3_sign_extendqi:
+      zero = false;
+      factor = 1;
+      break;
+    }      
+
+  /* We are expecting: (SET (REG) (<OP> (REG) (<EXTEND> (MEM)))).  */
+  extend = single_set (insn);
+  gcc_assert (extend != NULL_RTX);
+
+  extend = SET_SRC (extend);
+  if (GET_CODE (XEXP (extend, 0)) == ZERO_EXTEND
+      || GET_CODE (XEXP (extend, 0)) == SIGN_EXTEND)
+    extend = XEXP (extend, 0);
+  else
+    extend = XEXP (extend, 1);
+
+  gcc_assert ((zero && (GET_CODE (extend) == ZERO_EXTEND))
+             || (! zero && (GET_CODE (extend) == SIGN_EXTEND)));
+    
+  mem = XEXP (extend, 0);
+  gcc_checking_assert (MEM_P (mem));
+  if (REG_P (XEXP (mem, 0)))
+    return (zero && factor == 1) ? 2 : 3;
+
+  /* We are expecting: (MEM (PLUS (REG) (CONST_INT))).  */
+  gcc_checking_assert (GET_CODE (XEXP (mem, 0)) == PLUS);
+  gcc_checking_assert (REG_P (XEXP (XEXP (mem, 0), 0)));
+
+  offset = XEXP (XEXP (mem, 0), 1);
+  gcc_checking_assert (GET_CODE (offset) == CONST_INT);
+
+  if (IN_RANGE (INTVAL (offset), 0, 255 * factor))
+    return (zero && factor == 1) ? 3 : 4;
+
+  return (zero && factor == 1) ? 4 : 5;
+}
 \f
+#undef  TARGET_ASM_JUMP_ALIGN_MAX_SKIP
+#define TARGET_ASM_JUMP_ALIGN_MAX_SKIP                 rx_max_skip_for_label
+#undef  TARGET_ASM_LOOP_ALIGN_MAX_SKIP
+#define TARGET_ASM_LOOP_ALIGN_MAX_SKIP                 rx_max_skip_for_label
+#undef  TARGET_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
+#define TARGET_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP      rx_max_skip_for_label
+#undef  TARGET_ASM_LABEL_ALIGN_MAX_SKIP
+#define TARGET_ASM_LABEL_ALIGN_MAX_SKIP                        rx_max_skip_for_label
+
 #undef  TARGET_FUNCTION_VALUE
 #define TARGET_FUNCTION_VALUE          rx_function_value
 
@@ -2762,6 +3145,9 @@ rx_match_ccmode (rtx insn, enum machine_mode cc_mode)
 #undef  TARGET_INIT_BUILTINS
 #define TARGET_INIT_BUILTINS           rx_init_builtins
 
+#undef  TARGET_BUILTIN_DECL
+#define TARGET_BUILTIN_DECL            rx_builtin_decl
+
 #undef  TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN          rx_expand_builtin
 
@@ -2786,6 +3172,9 @@ rx_match_ccmode (rtx insn, enum machine_mode cc_mode)
 #undef  TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P            rx_is_legitimate_address
 
+#undef  TARGET_MODE_DEPENDENT_ADDRESS_P
+#define TARGET_MODE_DEPENDENT_ADDRESS_P                rx_mode_dependent_address_p
+
 #undef  TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS   rx_allocate_stack_slots_for_args
 
@@ -2810,9 +3199,6 @@ rx_match_ccmode (rtx insn, enum machine_mode cc_mode)
 #undef  TARGET_SET_CURRENT_FUNCTION
 #define TARGET_SET_CURRENT_FUNCTION            rx_set_current_function
 
-#undef  TARGET_HANDLE_OPTION
-#define TARGET_HANDLE_OPTION                   rx_handle_option
-
 #undef  TARGET_ASM_INTEGER
 #define TARGET_ASM_INTEGER                     rx_assemble_integer
 
@@ -2852,18 +3238,21 @@ rx_match_ccmode (rtx insn, enum machine_mode cc_mode)
 #undef  TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE                 rx_option_override
 
-#undef  TARGET_OPTION_OPTIMIZATION_TABLE
-#define TARGET_OPTION_OPTIMIZATION_TABLE       rx_option_optimization_table
-
 #undef  TARGET_PROMOTE_FUNCTION_MODE
 #define TARGET_PROMOTE_FUNCTION_MODE           rx_promote_function_mode
 
 #undef  TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
 #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE   rx_override_options_after_change
 
-#undef  TARGET_EXCEPT_UNWIND_INFO
-#define TARGET_EXCEPT_UNWIND_INFO              sjlj_except_unwind_info
+#undef  TARGET_FLAGS_REGNUM
+#define TARGET_FLAGS_REGNUM                    CC_REG
+
+#undef  TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P           rx_is_legitimate_constant
+
+#undef  TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS              rx_legitimize_address
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
-/* #include "gt-rx.h" */
+#include "gt-rx.h"