OSDN Git Service

* decl2.c (is_late_template_attribute): Don't defer attribute
[pf3gnuchains/gcc-fork.git] / gcc / config / c4x / c4x.c
index 6743990..3cef36b 100644 (file)
@@ -1,30 +1,32 @@
 /* Subroutines for assembler code output on the TMS320C[34]x
-   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
+   2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
               and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* Some output-actions in c4x.md need these.  */
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tree.h"
 #include "regs.h"
@@ -40,15 +42,14 @@ Boston, MA 02111-1307, USA.  */
 #include "optabs.h"
 #include "libfuncs.h"
 #include "flags.h"
-#include "loop.h"
 #include "recog.h"
-#include "c-tree.h"
 #include "ggc.h"
 #include "cpplib.h"
 #include "toplev.h"
-#include "c4x-protos.h"
+#include "tm_p.h"
 #include "target.h"
 #include "target-def.h"
+#include "langhooks.h"
 
 rtx smulhi3_libfunc;
 rtx umulhi3_libfunc;
@@ -148,12 +149,9 @@ enum machine_mode c4x_caller_save_map[FIRST_PSEUDO_REGISTER] =
 /* Test and compare insns in c4x.md store the information needed to
    generate branch and scc insns here.  */
 
-struct rtx_def *c4x_compare_op0 = NULL_RTX;
-struct rtx_def *c4x_compare_op1 = NULL_RTX;
+rtx c4x_compare_op0;
+rtx c4x_compare_op1;
 
-const char *c4x_rpts_cycles_string;
-int c4x_rpts_cycles = 0;       /* Max. cycles for RPTS.  */
-const char *c4x_cpu_version_string;
 int c4x_cpu_version = 40;      /* CPU version C30/31/32/33/40/44.  */
 
 /* Pragma definitions.  */
@@ -163,36 +161,39 @@ tree data_tree = NULL_TREE;
 tree pure_tree = NULL_TREE;
 tree noreturn_tree = NULL_TREE;
 tree interrupt_tree = NULL_TREE;
+tree naked_tree = NULL_TREE;
 
 /* Forward declarations */
-static void c4x_add_gc_roots PARAMS ((void));
-static int c4x_isr_reg_used_p PARAMS ((unsigned int));
-static int c4x_leaf_function_p PARAMS ((void));
-static int c4x_assembler_function_p PARAMS ((void));
-static int c4x_immed_float_p PARAMS ((rtx));
-static int c4x_a_register PARAMS ((rtx));
-static int c4x_x_register PARAMS ((rtx));
-static int c4x_immed_int_constant PARAMS ((rtx));
-static int c4x_immed_float_constant PARAMS ((rtx));
-static int c4x_K_constant PARAMS ((rtx));
-static int c4x_N_constant PARAMS ((rtx));
-static int c4x_O_constant PARAMS ((rtx));
-static int c4x_R_indirect PARAMS ((rtx));
-static int c4x_S_indirect PARAMS ((rtx));
-static void c4x_S_address_parse PARAMS ((rtx , int *, int *, int *, int *));
-static int c4x_valid_operands PARAMS ((enum rtx_code, rtx *,
-                                      enum machine_mode, int));
-static int c4x_arn_reg_operand PARAMS ((rtx, enum machine_mode, unsigned int));
-static int c4x_arn_mem_operand PARAMS ((rtx, enum machine_mode, unsigned int));
-static void c4x_check_attribute PARAMS ((const char *, tree, tree, tree *));
-static int c4x_r11_set_p PARAMS ((rtx));
-static int c4x_rptb_valid_p PARAMS ((rtx, rtx));
-static int c4x_label_ref_used_p PARAMS ((rtx, rtx));
-static tree c4x_handle_fntype_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static bool c4x_handle_option (size_t, const char *, int);
+static int c4x_isr_reg_used_p (unsigned int);
+static int c4x_leaf_function_p (void);
+static int c4x_naked_function_p (void);
+static int c4x_immed_int_constant (rtx);
+static int c4x_immed_float_constant (rtx);
+static int c4x_R_indirect (rtx);
+static void c4x_S_address_parse (rtx , int *, int *, int *, int *);
+static int c4x_valid_operands (enum rtx_code, rtx *, enum machine_mode, int);
+static int c4x_arn_reg_operand (rtx, enum machine_mode, unsigned int);
+static int c4x_arn_mem_operand (rtx, enum machine_mode, unsigned int);
+static void c4x_file_start (void);
+static void c4x_file_end (void);
+static void c4x_check_attribute (const char *, tree, tree, tree *);
+static int c4x_r11_set_p (rtx);
+static int c4x_rptb_valid_p (rtx, rtx);
+static void c4x_reorg (void);
+static int c4x_label_ref_used_p (rtx, rtx);
+static tree c4x_handle_fntype_attribute (tree *, tree, tree, int, bool *);
 const struct attribute_spec c4x_attribute_table[];
-static void c4x_insert_attributes PARAMS ((tree, tree *));
-static void c4x_asm_named_section PARAMS ((const char *, unsigned int));
-static int c4x_adjust_cost PARAMS ((rtx, rtx, rtx, int));
+static void c4x_insert_attributes (tree, tree *);
+static void c4x_asm_named_section (const char *, unsigned int, tree);
+static int c4x_adjust_cost (rtx, rtx, rtx, int);
+static void c4x_globalize_label (FILE *, const char *);
+static bool c4x_rtx_costs (rtx, int, int, int *);
+static int c4x_address_cost (rtx);
+static void c4x_init_libfuncs (void);
+static void c4x_external_libcall (rtx);
+static rtx c4x_struct_value_rtx (tree, int);
+static tree c4x_gimplify_va_arg_expr (tree, tree, tree *, tree *);
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_BYTE_OP
@@ -201,6 +202,22 @@ static int c4x_adjust_cost PARAMS ((rtx, rtx, rtx, int));
 #define TARGET_ASM_ALIGNED_HI_OP NULL
 #undef TARGET_ASM_ALIGNED_SI_OP
 #define TARGET_ASM_ALIGNED_SI_OP NULL
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START c4x_file_start
+#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
+#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END c4x_file_end
+
+#undef TARGET_ASM_EXTERNAL_LIBCALL
+#define TARGET_ASM_EXTERNAL_LIBCALL c4x_external_libcall
+
+/* Play safe, not the fastest code.  */
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS (MASK_ALIASES | MASK_PARALLEL \
+                                    | MASK_PARALLEL_MPY | MASK_RPTB)
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION c4x_handle_option
 
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE c4x_attribute_table
@@ -217,33 +234,58 @@ static int c4x_adjust_cost PARAMS ((rtx, rtx, rtx, int));
 #undef TARGET_SCHED_ADJUST_COST
 #define TARGET_SCHED_ADJUST_COST c4x_adjust_cost
 
+#undef TARGET_ASM_GLOBALIZE_LABEL
+#define TARGET_ASM_GLOBALIZE_LABEL c4x_globalize_label
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS c4x_rtx_costs
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST c4x_address_cost
+
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG c4x_reorg
+
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS c4x_init_libfuncs
+
+#undef TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX c4x_struct_value_rtx
+
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR c4x_gimplify_va_arg_expr
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
-/* Called to register all of our global variables with the garbage
-   collector.  */
+/* Implement TARGET_HANDLE_OPTION.  */
 
-static void
-c4x_add_gc_roots ()
+static bool
+c4x_handle_option (size_t code, const char *arg, int value)
 {
-  ggc_add_rtx_root (&c4x_compare_op0, 1);
-  ggc_add_rtx_root (&c4x_compare_op1, 1);
-  ggc_add_tree_root (&code_tree, 1);
-  ggc_add_tree_root (&data_tree, 1);
-  ggc_add_tree_root (&pure_tree, 1);
-  ggc_add_tree_root (&noreturn_tree, 1);
-  ggc_add_tree_root (&interrupt_tree, 1);
-  ggc_add_rtx_root (&smulhi3_libfunc, 1);
-  ggc_add_rtx_root (&umulhi3_libfunc, 1);
-  ggc_add_rtx_root (&fix_truncqfhi2_libfunc, 1);
-  ggc_add_rtx_root (&fixuns_truncqfhi2_libfunc, 1);
-  ggc_add_rtx_root (&fix_trunchfhi2_libfunc, 1);
-  ggc_add_rtx_root (&fixuns_trunchfhi2_libfunc, 1);
-  ggc_add_rtx_root (&floathiqf2_libfunc, 1);
-  ggc_add_rtx_root (&floatunshiqf2_libfunc, 1);
-  ggc_add_rtx_root (&floathihf2_libfunc, 1);
-  ggc_add_rtx_root (&floatunshihf2_libfunc, 1);
-}
+  switch (code)
+    {
+    case OPT_m30: c4x_cpu_version = 30; return true;
+    case OPT_m31: c4x_cpu_version = 31; return true;
+    case OPT_m32: c4x_cpu_version = 32; return true;
+    case OPT_m33: c4x_cpu_version = 33; return true;
+    case OPT_m40: c4x_cpu_version = 40; return true;
+    case OPT_m44: c4x_cpu_version = 44; return true;
+
+    case OPT_mcpu_:
+      if (arg[0] == 'c' || arg[0] == 'C')
+       arg++;
+      value = atoi (arg);
+      switch (value)
+       {
+       case 30: case 31: case 32: case 33: case 40: case 44:
+         c4x_cpu_version = value;
+         return true;
+       }
+      return false;
 
+    default:
+      return true;
+    }
+}
 
 /* Override command line options.
    Called once after all options have been parsed.
@@ -251,80 +293,32 @@ c4x_add_gc_roots ()
    type and sometimes adjust other TARGET_ options.  */
 
 void
-c4x_override_options ()
+c4x_override_options (void)
 {
-  if (c4x_rpts_cycles_string)
-    c4x_rpts_cycles = atoi (c4x_rpts_cycles_string);
-  else
-    c4x_rpts_cycles = 0;
-
-  if (TARGET_C30)
-    c4x_cpu_version = 30;
-  else if (TARGET_C31)
-    c4x_cpu_version = 31;
-  else if (TARGET_C32)
-    c4x_cpu_version = 32;
-  else if (TARGET_C33)
-    c4x_cpu_version = 33;
-  else if (TARGET_C40)
-    c4x_cpu_version = 40;
-  else if (TARGET_C44)
-    c4x_cpu_version = 44;
-  else
-    c4x_cpu_version = 40;             
-
-  /* -mcpu=xx overrides -m40 etc.  */
-  if (c4x_cpu_version_string)
-    {
-      const char *p = c4x_cpu_version_string;
-      
-      /* Also allow -mcpu=c30 etc.  */
-      if (*p == 'c' || *p == 'C')
-       p++;
-      c4x_cpu_version = atoi (p);
-    }
-
-  target_flags &= ~(C30_FLAG | C31_FLAG | C32_FLAG | C33_FLAG |
-                   C40_FLAG | C44_FLAG);
-
-  switch (c4x_cpu_version)
-    {
-    case 30: target_flags |= C30_FLAG; break;
-    case 31: target_flags |= C31_FLAG; break;
-    case 32: target_flags |= C32_FLAG; break;
-    case 33: target_flags |= C33_FLAG; break;
-    case 40: target_flags |= C40_FLAG; break;
-    case 44: target_flags |= C44_FLAG; break;
-    default:
-      warning ("unknown CPU version %d, using 40.\n", c4x_cpu_version);
-      c4x_cpu_version = 40;
-      target_flags |= C40_FLAG;
-    }
-
-  if (TARGET_C30 || TARGET_C31 || TARGET_C32 || TARGET_C33)
-    target_flags |= C3X_FLAG;
-  else
-    target_flags &= ~C3X_FLAG;
-
   /* Convert foo / 8.0 into foo * 0.125, etc.  */
-  set_fast_math_flags();
+  set_fast_math_flags (1);
 
   /* We should phase out the following at some stage.
      This provides compatibility with the old -mno-aliases option.  */
   if (! TARGET_ALIASES && ! flag_argument_noalias)
     flag_argument_noalias = 1;
 
-  /* Register global variables with the garbage collector.  */
-  c4x_add_gc_roots ();
+  if (!TARGET_C3X)
+    target_flags |= MASK_MPYI | MASK_DB;
+
+  if (optimize < 2)
+    target_flags &= ~(MASK_RPTB | MASK_PARALLEL);
+
+  if (!TARGET_PARALLEL)
+    target_flags &= ~MASK_PARALLEL_MPY;
 }
 
 
 /* This is called before c4x_override_options.  */
 
 void
-c4x_optimization_options (level, size)
-     int level ATTRIBUTE_UNUSED;
-     int size ATTRIBUTE_UNUSED;
+c4x_optimization_options (int level ATTRIBUTE_UNUSED,
+                         int size ATTRIBUTE_UNUSED)
 {
   /* Scheduling before register allocation can screw up global
      register allocation, especially for functions that use MPY||ADD
@@ -339,10 +333,7 @@ c4x_optimization_options (level, size)
 #define C4X_ASCII_LIMIT 40
 
 void
-c4x_output_ascii (stream, ptr, len)
-     FILE *stream;
-     const char *ptr;
-     int len;
+c4x_output_ascii (FILE *stream, const char *ptr, int len)
 {
   char sbuf[C4X_ASCII_LIMIT + 1];
   int s, l, special, first = 1, onlys;
@@ -423,9 +414,7 @@ c4x_output_ascii (stream, ptr, len)
 
 
 int
-c4x_hard_regno_mode_ok (regno, mode)
-     unsigned int regno;
-     enum machine_mode mode;
+c4x_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
 {
   switch (mode)
     {
@@ -458,13 +447,11 @@ c4x_hard_regno_mode_ok (regno, mode)
   return 0;
 }
 
-/* Return non-zero if REGNO1 can be renamed to REGNO2.  */
+/* Return nonzero if REGNO1 can be renamed to REGNO2.  */
 int
-c4x_hard_regno_rename_ok (regno1, regno2)
-     unsigned int regno1;
-     unsigned int regno2;
+c4x_hard_regno_rename_ok (unsigned int regno1, unsigned int regno2)
 {
-  /* We can not copy call saved registers from mode QI into QF or from
+  /* We cannot copy call saved registers from mode QI into QF or from
      mode QF into QI.  */
   if (IS_FLOAT_CALL_SAVED_REGNO (regno1) && IS_INT_CALL_SAVED_REGNO (regno2))
     return 0;
@@ -514,7 +501,7 @@ static const int c4x_int_reglist[3][6] =
   {AR2_REGNO, RC_REGNO, RS_REGNO, RE_REGNO, 0, 0}
 };
 
-static int c4x_fp_reglist[2] = {R2_REGNO, R3_REGNO};
+static const int c4x_fp_reglist[2] = {R2_REGNO, R3_REGNO};
 
 
 /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a
@@ -522,10 +509,7 @@ static int c4x_fp_reglist[2] = {R2_REGNO, R3_REGNO};
    For a library call, FNTYPE is  0.  */
 
 void
-c4x_init_cumulative_args (cum, fntype, libname)
-     CUMULATIVE_ARGS *cum;     /* Argument info to initialize.  */
-     tree fntype;              /* Tree ptr for function decl.  */
-     rtx libname;              /* SYMBOL_REF of library name or 0.  */
+c4x_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname)
 {
   tree param, next_param;
 
@@ -573,7 +557,7 @@ c4x_init_cumulative_args (cum, fntype, libname)
 
          if ((mode = TYPE_MODE (type)))
            {
-             if (! MUST_PASS_IN_STACK (mode, type))
+             if (! targetm.calls.must_pass_in_stack (mode, type))
                {
                  /* Look for float, double, or long double argument.  */
                  if (mode == QFmode || mode == HFmode)
@@ -601,11 +585,8 @@ c4x_init_cumulative_args (cum, fntype, libname)
    (TYPE is null for libcalls where that information may not be available.)  */
 
 void
-c4x_function_arg_advance (cum, mode, type, named)
-     CUMULATIVE_ARGS *cum;     /* Current arg information.  */
-     enum machine_mode mode;   /* Current arg mode.  */
-     tree type;                        /* Type of the arg or 0 if lib support.  */
-     int named;                        /* Whether or not the argument was named.  */
+c4x_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                         tree type, int named)
 {
   if (TARGET_DEBUG)
     fprintf (stderr, "c4x_function_adv(mode=%s, named=%d)\n\n",
@@ -613,7 +594,7 @@ c4x_function_arg_advance (cum, mode, type, named)
   if (! TARGET_MEMPARM 
       && named
       && type
-      && ! MUST_PASS_IN_STACK (mode, type))
+      && ! targetm.calls.must_pass_in_stack (mode, type))
     {
       /* Look for float, double, or long double argument.  */
       if (mode == QFmode || mode == HFmode)
@@ -648,11 +629,8 @@ c4x_function_arg_advance (cum, mode, type, named)
    (otherwise it is an extra parameter matching an ellipsis).  */
 
 struct rtx_def *
-c4x_function_arg (cum, mode, type, named)
-     CUMULATIVE_ARGS *cum;     /* Current arg information.  */
-     enum machine_mode mode;   /* Current arg mode.  */
-     tree type;                        /* Type of the arg or 0 if lib support.  */
-     int named;                        /* != 0 for normal args, == 0 for ... args.  */
+c4x_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                 tree type, int named)
 {
   int reg = 0;                 /* Default to passing argument on stack.  */
 
@@ -682,7 +660,7 @@ c4x_function_arg (cum, mode, type, named)
   if (! TARGET_MEMPARM 
       && named 
       && type
-      && ! MUST_PASS_IN_STACK (mode, type))
+      && ! targetm.calls.must_pass_in_stack (mode, type))
     {
       /* Look for float, double, or long double argument.  */
       if (mode == QFmode || mode == HFmode)
@@ -728,38 +706,35 @@ c4x_function_arg (cum, mode, type, named)
     return NULL_RTX;
 }
 
-
-void
-c4x_va_start (stdarg_p, valist, nextarg)
-     int stdarg_p;
-     tree valist;
-     rtx nextarg;
-{
-  nextarg = plus_constant (nextarg, stdarg_p ? 0 : UNITS_PER_WORD * 2);
-
-  std_expand_builtin_va_start (stdarg_p, valist, nextarg);
-}
-
-
 /* C[34]x arguments grow in weird ways (downwards) that the standard
    varargs stuff can't handle..  */
-rtx
-c4x_va_arg (valist, type)
-     tree valist, type;
+
+static tree
+c4x_gimplify_va_arg_expr (tree valist, tree type,
+                         tree *pre_p ATTRIBUTE_UNUSED,
+                         tree *post_p ATTRIBUTE_UNUSED)
 {
   tree t;
+  bool indirect;
+
+  indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  if (indirect)
+    type = build_pointer_type (type);
+
+  t = build2 (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
+             build_int_cst (NULL_TREE, int_size_in_bytes (type)));
+  t = fold_convert (build_pointer_type (type), t);
+  t = build_va_arg_indirect_ref (t);
 
-  t = build (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
-            build_int_2 (int_size_in_bytes (type), 0));
-  TREE_SIDE_EFFECTS (t) = 1;
+  if (indirect)
+    t = build_va_arg_indirect_ref (t);
 
-  return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
+  return t;
 }
 
 
 static int
-c4x_isr_reg_used_p (regno)
-     unsigned int regno;
+c4x_isr_reg_used_p (unsigned int regno)
 {
   /* Don't save/restore FP or ST, we handle them separately.  */
   if (regno == FRAME_POINTER_REGNUM
@@ -774,25 +749,25 @@ c4x_isr_reg_used_p (regno)
 
   /* Only save/restore regs in leaf function that are used.  */
   if (c4x_leaf_function)
-    return regs_ever_live[regno] && fixed_regs[regno] == 0;
+    return df_regs_ever_live_p (regno) && fixed_regs[regno] == 0;
 
   /* Only save/restore regs that are used by the ISR and regs
      that are likely to be used by functions the ISR calls
      if they are not fixed.  */
   return IS_EXT_REGNO (regno)
-    || ((regs_ever_live[regno] || call_used_regs[regno]) 
+    || ((df_regs_ever_live_p (regno) || call_used_regs[regno]) 
        && fixed_regs[regno] == 0);
 }
 
 
 static int
-c4x_leaf_function_p ()
+c4x_leaf_function_p (void)
 {
   /* A leaf function makes no calls, so we only need
      to save/restore the registers we actually use.
      For the global variable leaf_function to be set, we need
      to define LEAF_REGISTERS and all that it entails.
-     Let's check ourselves...   */
+     Let's check ourselves....  */
 
   if (lookup_attribute ("leaf_pretend",
                        TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
@@ -813,35 +788,36 @@ c4x_leaf_function_p ()
 
 
 static int
-c4x_assembler_function_p ()
+c4x_naked_function_p (void)
 {
   tree type;
 
   type = TREE_TYPE (current_function_decl);
-  return (lookup_attribute ("assembler", TYPE_ATTRIBUTES (type)) != NULL)
-    || (lookup_attribute ("naked", TYPE_ATTRIBUTES (type)) != NULL);
+  return lookup_attribute ("naked", TYPE_ATTRIBUTES (type)) != NULL;
 }
 
 
 int
-c4x_interrupt_function_p ()
+c4x_interrupt_function_p (void)
 {
+  const char *cfun_name;
   if (lookup_attribute ("interrupt",
                        TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
     return 1;
 
   /* Look for TI style c_intnn.  */
-  return current_function_name[0] == 'c'
-    && current_function_name[1] == '_'
-    && current_function_name[2] == 'i'
-    && current_function_name[3] == 'n' 
-    && current_function_name[4] == 't'
-    && ISDIGIT (current_function_name[5])
-    && ISDIGIT (current_function_name[6]);
+  cfun_name = current_function_name ();
+  return cfun_name[0] == 'c'
+    && cfun_name[1] == '_'
+    && cfun_name[2] == 'i'
+    && cfun_name[3] == 'n' 
+    && cfun_name[4] == 't'
+    && ISDIGIT (cfun_name[5])
+    && ISDIGIT (cfun_name[6]);
 }
 
 void
-c4x_expand_prologue ()
+c4x_expand_prologue (void)
 {
   unsigned int regno;
   int size = get_frame_size ();
@@ -852,8 +828,8 @@ c4x_expand_prologue ()
      is used so it won't needlessly push the frame pointer.  */
   int dont_push_ar3;
 
-  /* For __assembler__ function don't build a prologue.  */
-  if (c4x_assembler_function_p ())
+  /* For __naked__ function don't build a prologue.  */
+  if (c4x_naked_function_p ())
     {
       return;
     }
@@ -881,7 +857,7 @@ c4x_expand_prologue ()
             storage!  */
          if (size > 32767)
            error ("ISR %s requires %d words of local vars, max is 32767",
-                  current_function_name, size);
+                  current_function_name (), size);
 
          insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO),
                                        gen_rtx_REG (QImode, SP_REGNO),
@@ -913,9 +889,9 @@ c4x_expand_prologue ()
       /* We need to clear the repeat mode flag if the ISR is
          going to use a RPTB instruction or uses the RC, RS, or RE
          registers.  */
-      if (regs_ever_live[RC_REGNO] 
-         || regs_ever_live[RS_REGNO] 
-         || regs_ever_live[RE_REGNO])
+      if (df_regs_ever_live_p (RC_REGNO) 
+         || df_regs_ever_live_p (RS_REGNO) 
+         || df_regs_ever_live_p (RE_REGNO))
        {
           insn = emit_insn (gen_andn_st (GEN_INT(~0x100)));
           RTX_FRAME_RELATED_P (insn) = 1;
@@ -954,7 +930,7 @@ c4x_expand_prologue ()
        }
       else
        {
-         /* If we use ar3, we need to push it.   */
+         /* If we use ar3, we need to push it.  */
          dont_push_ar3 = 0;
          if ((size != 0) || (current_function_args_size != 0))
            {
@@ -1006,7 +982,7 @@ c4x_expand_prologue ()
       
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
        {
-         if (regs_ever_live[regno] && ! call_used_regs[regno])
+         if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
            {
              if (IS_FLOAT_CALL_SAVED_REGNO (regno))
                {
@@ -1031,7 +1007,7 @@ c4x_expand_prologue ()
 
 
 void
-c4x_expand_epilogue()
+c4x_expand_epilogue(void)
 {
   int regno;
   int jump = 0;
@@ -1039,8 +1015,8 @@ c4x_expand_epilogue()
   rtx insn;
   int size = get_frame_size ();
   
-  /* For __assembler__ function build no epilogue.  */
-  if (c4x_assembler_function_p ())
+  /* For __naked__ function build no epilogue.  */
+  if (c4x_naked_function_p ())
     {
       insn = emit_jump_insn (gen_return_from_epilogue ());
       RTX_FRAME_RELATED_P (insn) = 1;
@@ -1102,7 +1078,7 @@ c4x_expand_epilogue()
                                         gen_rtx_PLUS 
                                         (QImode, gen_rtx_REG (QImode,
                                                               AR3_REGNO),
-                                         GEN_INT(-1)))));
+                                         constm1_rtx))));
              RTX_FRAME_RELATED_P (insn) = 1;
              
              /* We already have the return value and the fp,
@@ -1123,7 +1099,7 @@ c4x_expand_epilogue()
          dont_pop_ar3 = 0;     /* If we use ar3, we need to pop it.  */
          if (size || current_function_args_size)
            {
-             /* If we are ommitting the frame pointer, we still have
+             /* If we are omitting the frame pointer, we still have
                 to make space for it so the offsets are correct
                 unless we don't use anything on the stack at all.  */
              size += 1;
@@ -1134,7 +1110,7 @@ c4x_expand_epilogue()
          where required.  */
       for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
        {
-         if (regs_ever_live[regno] && ! call_used_regs[regno])
+         if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
            {
              if (regno == AR3_REGNO && dont_pop_ar3)
                continue;
@@ -1230,12 +1206,12 @@ c4x_expand_epilogue()
 
 
 int
-c4x_null_epilogue_p ()
+c4x_null_epilogue_p (void)
 {
   int regno;
 
   if (reload_completed
-      && ! c4x_assembler_function_p ()
+      && ! c4x_naked_function_p ()
       && ! c4x_interrupt_function_p ()
       && ! current_function_calls_alloca
       && ! current_function_args_size
@@ -1243,19 +1219,17 @@ c4x_null_epilogue_p ()
       && ! get_frame_size ())
     {
       for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
-       if (regs_ever_live[regno] && ! call_used_regs[regno]
+       if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]
            && (regno != AR3_REGNO))
-         return 0;
-      return 1;
+         return 1;
+      return 0;
     }
-  return 0;
+  return 1;
 }
 
 
 int
-c4x_emit_move_sequence (operands, mode)
-     rtx *operands;
-     enum machine_mode mode;     
+c4x_emit_move_sequence (rtx *operands, enum machine_mode mode)
 {
   rtx op0 = operands[0];
   rtx op1 = operands[1];
@@ -1271,10 +1245,11 @@ c4x_emit_move_sequence (operands, mode)
       && dp_reg_operand (XEXP (op1, 0), mode))
     {
       /* expand_increment will sometimes create a LO_SUM immediate
-        address.  */
+        address.  Undo this silliness.  */
       op1 = XEXP (op1, 1);
     }
-  else if (symbolic_address_operand (op1, mode))
+  
+  if (symbolic_address_operand (op1, mode))
     {
       if (TARGET_LOAD_ADDRESS)
        {
@@ -1402,13 +1377,9 @@ c4x_emit_move_sequence (operands, mode)
 
 
 void
-c4x_emit_libcall (libcall, code, dmode, smode, noperands, operands)
-     rtx libcall;
-     enum rtx_code code;
-     enum machine_mode dmode;
-     enum machine_mode smode;
-     int noperands;
-     rtx *operands;
+c4x_emit_libcall (rtx libcall, enum rtx_code code,
+                 enum machine_mode dmode, enum machine_mode smode,
+                 int noperands, rtx *operands)
 {
   rtx ret;
   rtx insns;
@@ -1420,13 +1391,13 @@ c4x_emit_libcall (libcall, code, dmode, smode, noperands, operands)
     case 2:
       ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 1,
                                     operands[1], smode);
-      equiv = gen_rtx (code, dmode, operands[1]);
+      equiv = gen_rtx_fmt_e (code, dmode, operands[1]);
       break;
 
     case 3:
       ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 2,
                                     operands[1], smode, operands[2], smode);
-      equiv = gen_rtx (code, dmode, operands[1], operands[2]);
+      equiv = gen_rtx_fmt_ee (code, dmode, operands[1], operands[2]);
       break;
 
     default:
@@ -1440,22 +1411,16 @@ c4x_emit_libcall (libcall, code, dmode, smode, noperands, operands)
 
 
 void
-c4x_emit_libcall3 (libcall, code, mode, operands)
-     rtx libcall;
-     enum rtx_code code;
-     enum machine_mode mode;
-     rtx *operands;
+c4x_emit_libcall3 (rtx libcall, enum rtx_code code,
+                  enum machine_mode mode, rtx *operands)
 {
   c4x_emit_libcall (libcall, code, mode, mode, 3, operands);
 }
 
 
 void
-c4x_emit_libcall_mulhi (libcall, code, mode, operands)
-     rtx libcall;
-     enum rtx_code code;
-     enum machine_mode mode;
-     rtx *operands;
+c4x_emit_libcall_mulhi (rtx libcall, enum rtx_code code,
+                       enum machine_mode mode, rtx *operands)
 {
   rtx ret;
   rtx insns;
@@ -1467,8 +1432,8 @@ c4x_emit_libcall_mulhi (libcall, code, mode, operands)
   equiv = gen_rtx_TRUNCATE (mode,
                    gen_rtx_LSHIFTRT (HImode,
                             gen_rtx_MULT (HImode,
-                                     gen_rtx (code, HImode, operands[1]),
-                                     gen_rtx (code, HImode, operands[2])),
+                                     gen_rtx_fmt_e (code, HImode, operands[1]),
+                                     gen_rtx_fmt_e (code, HImode, operands[2])),
                                      GEN_INT (32)));
   insns = get_insns ();
   end_sequence ();
@@ -1476,23 +1441,8 @@ c4x_emit_libcall_mulhi (libcall, code, mode, operands)
 }
 
 
-/* Set the SYMBOL_REF_FLAG for a function decl.  However, wo do not
-   yet use this info.  */
-void
-c4x_encode_section_info (decl, first)
-     tree decl;
-     int first ATTRIBUTE_UNUSED;
-{
-  if (TREE_CODE (decl) == FUNCTION_DECL)   
-    SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
-}
-
-
 int
-c4x_check_legit_addr (mode, addr, strict)
-     enum machine_mode mode;
-     rtx addr;
-     int strict;
+c4x_legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
 {
   rtx base = NULL_RTX;         /* Base register (AR0-AR7).  */
   rtx indx = NULL_RTX;         /* Index register (IR0,IR1).  */
@@ -1503,7 +1453,7 @@ c4x_check_legit_addr (mode, addr, strict)
   switch (code)
     {
       /* Register indirect with auto increment/decrement.  We don't
-        allow SP here---push_operand should recognise an operand
+        allow SP here---push_operand should recognize an operand
         being pushed on the stack.  */
 
     case PRE_DEC:
@@ -1531,7 +1481,9 @@ c4x_check_legit_addr (mode, addr, strict)
            || (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS))
          return 0;
        base = XEXP (op1, 0);
-       if (base != op0)
+       if (! REG_P (base))
+           return 0;
+       if (REGNO (base) != REGNO (op0))
          return 0;
        if (REG_P (XEXP (op1, 1)))
          indx = XEXP (op1, 1);
@@ -1686,9 +1638,8 @@ c4x_check_legit_addr (mode, addr, strict)
 
 
 rtx
-c4x_legitimize_address (orig, mode)
-     rtx orig ATTRIBUTE_UNUSED;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+c4x_legitimize_address (rtx orig ATTRIBUTE_UNUSED,
+                       enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (GET_CODE (orig) == SYMBOL_REF
       || GET_CODE (orig) == LABEL_REF)
@@ -1718,13 +1669,12 @@ c4x_legitimize_address (orig, mode)
 
 /* Provide the costs of an addressing mode that contains ADDR.
    If ADDR is not a valid address, its cost is irrelevant.  
-   This is used in cse and loop optimisation to determine
+   This is used in cse and loop optimization to determine
    if it is worthwhile storing a common address into a register. 
    Unfortunately, the C4x address cost depends on other operands.  */
 
-int 
-c4x_address_cost (addr)
-     rtx addr;
+static int 
+c4x_address_cost (rtx addr)
 {
   switch (GET_CODE (addr))
     {
@@ -1814,9 +1764,7 @@ c4x_address_cost (addr)
 
 
 rtx
-c4x_gen_compare_reg (code, x, y)
-     enum rtx_code code;
-     rtx x, y;
+c4x_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
 {
   enum machine_mode mode = SELECT_CC_MODE (code, x, y);
   rtx cc_reg;
@@ -1832,9 +1780,7 @@ c4x_gen_compare_reg (code, x, y)
 }
 
 char *
-c4x_output_cbranch (form, seq)
-     const char *form;
-     rtx seq;
+c4x_output_cbranch (const char *form, rtx seq)
 {
   int delayed = 0;
   int annultrue = 0;
@@ -1876,10 +1822,7 @@ c4x_output_cbranch (form, seq)
 }
 
 void
-c4x_print_operand (file, op, letter)
-     FILE *file;               /* File to write to.  */
-     rtx op;                   /* Operand to print.  */
-     int letter;               /* %<letter> or 0.  */
+c4x_print_operand (FILE *file, rtx op, int letter)
 {
   rtx op1;
   enum rtx_code code;
@@ -1888,7 +1831,7 @@ c4x_print_operand (file, op, letter)
     {
     case '#':                  /* Delayed.  */
       if (final_sequence)
-       asm_fprintf (file, "d");
+       fprintf (file, "d");
       return;
     }
 
@@ -1897,7 +1840,7 @@ c4x_print_operand (file, op, letter)
     {
     case 'A':                  /* Direct address.  */
       if (code == CONST_INT || code == SYMBOL_REF || code == CONST)
-       asm_fprintf (file, "@");
+       fprintf (file, "@");
       break;
 
     case 'H':                  /* Sethi.  */
@@ -1917,7 +1860,7 @@ c4x_print_operand (file, op, letter)
     case 'N':                  /* Ones complement of small constant.  */
       if (code != CONST_INT)
        fatal_insn ("c4x_print_operand: %%N inconsistency", op);
-      fprintf (file, "%d", ~INTVAL (op));
+      fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~INTVAL (op));
       return;
 
     case 'K':                  /* Generate ldp(k) if direct address.  */
@@ -1930,9 +1873,9 @@ c4x_print_operand (file, op, letter)
          op1 = XEXP (XEXP (op, 0), 1);
           if (GET_CODE(op1) == CONST_INT || GET_CODE(op1) == SYMBOL_REF)
            {
-             asm_fprintf (file, "\t%s\t@", TARGET_C3X ? "ldp" : "ldpk");
+             fprintf (file, "\t%s\t@", TARGET_C3X ? "ldp" : "ldpk");
              output_address (XEXP (adjust_address (op, VOIDmode, 1), 0));
-             asm_fprintf (file, "\n");
+             fprintf (file, "\n");
            }
        }
       return;
@@ -1943,9 +1886,9 @@ c4x_print_operand (file, op, letter)
          && (GET_CODE (XEXP (op, 0)) == CONST
              || GET_CODE (XEXP (op, 0)) == SYMBOL_REF))
        {
-         asm_fprintf (file, "%s\t@", TARGET_C3X ? "ldp" : "ldpk");
+         fprintf (file, "%s\t@", TARGET_C3X ? "ldp" : "ldpk");
           output_address (XEXP (op, 0));
-         asm_fprintf (file, "\n\t");
+         fprintf (file, "\n\t");
        }
       return;
 
@@ -1965,7 +1908,7 @@ c4x_print_operand (file, op, letter)
 
     case 'U':                  /* Call/callu.  */
       if (code != SYMBOL_REF)
-       asm_fprintf (file, "u");
+       fprintf (file, "u");
       return;
 
     default:
@@ -1988,57 +1931,56 @@ c4x_print_operand (file, op, letter)
       
     case CONST_DOUBLE:
       {
-       char str[30];
-       REAL_VALUE_TYPE r;
+       char str[64];
        
-       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
-       REAL_VALUE_TO_DECIMAL (r, "%20f", str);
+       real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (op),
+                        sizeof (str), 0, 1);
        fprintf (file, "%s", str);
       }
       break;
       
     case CONST_INT:
-      fprintf (file, "%d", INTVAL (op));
+      fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op));
       break;
       
     case NE:
-      asm_fprintf (file, "ne");
+      fprintf (file, "ne");
       break;
       
     case EQ:
-      asm_fprintf (file, "eq");
+      fprintf (file, "eq");
       break;
       
     case GE:
-      asm_fprintf (file, "ge");
+      fprintf (file, "ge");
       break;
 
     case GT:
-      asm_fprintf (file, "gt");
+      fprintf (file, "gt");
       break;
 
     case LE:
-      asm_fprintf (file, "le");
+      fprintf (file, "le");
       break;
 
     case LT:
-      asm_fprintf (file, "lt");
+      fprintf (file, "lt");
       break;
 
     case GEU:
-      asm_fprintf (file, "hs");
+      fprintf (file, "hs");
       break;
 
     case GTU:
-      asm_fprintf (file, "hi");
+      fprintf (file, "hi");
       break;
 
     case LEU:
-      asm_fprintf (file, "ls");
+      fprintf (file, "ls");
       break;
 
     case LTU:
-      asm_fprintf (file, "lo");
+      fprintf (file, "lo");
       break;
 
     case SYMBOL_REF:
@@ -2060,9 +2002,7 @@ c4x_print_operand (file, op, letter)
 
 
 void
-c4x_print_operand_address (file, addr)
-     FILE *file;
-     rtx addr;
+c4x_print_operand_address (FILE *file, rtx addr)
 {
   switch (GET_CODE (addr))
     {
@@ -2087,11 +2027,11 @@ c4x_print_operand_address (file, addr)
          fprintf (file, "*%s++(%s)", reg_names[REGNO (op0)],
                   reg_names[REGNO (op1)]);
        else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0)
-         fprintf (file, "*%s++(%d)", reg_names[REGNO (op0)],
-                  INTVAL (op1));
+         fprintf (file, "*%s++(" HOST_WIDE_INT_PRINT_DEC ")",
+                  reg_names[REGNO (op0)], INTVAL (op1));
        else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0)
-         fprintf (file, "*%s--(%d)", reg_names[REGNO (op0)],
-                  -INTVAL (op1));
+         fprintf (file, "*%s--(" HOST_WIDE_INT_PRINT_DEC ")",
+                  reg_names[REGNO (op0)], -INTVAL (op1));
        else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1))
          fprintf (file, "*%s--(%s)", reg_names[REGNO (op0)],
                   reg_names[REGNO (op1)]);
@@ -2109,11 +2049,11 @@ c4x_print_operand_address (file, addr)
          fprintf (file, "*++%s(%s)", reg_names[REGNO (op0)],
                   reg_names[REGNO (op1)]);
        else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0)
-         fprintf (file, "*++%s(%d)", reg_names[REGNO (op0)],
-                  INTVAL (op1));
+         fprintf (file, "*++%s(" HOST_WIDE_INT_PRINT_DEC ")",
+                  reg_names[REGNO (op0)], INTVAL (op1));
        else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0)
-         fprintf (file, "*--%s(%d)", reg_names[REGNO (op0)],
-                  -INTVAL (op1));
+         fprintf (file, "*--%s(" HOST_WIDE_INT_PRINT_DEC ")",
+                  reg_names[REGNO (op0)], -INTVAL (op1));
        else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1))
          fprintf (file, "*--%s(%s)", reg_names[REGNO (op0)],
                   reg_names[REGNO (op1)]);
@@ -2154,13 +2094,13 @@ c4x_print_operand_address (file, addr)
              }
            else if (INTVAL (op1) < 0)
              {
-               fprintf (file, "*-%s(%d)",
+               fprintf (file, "*-%s(" HOST_WIDE_INT_PRINT_DEC ")",
                         reg_names[REGNO (op0)],
                         -INTVAL (op1));        /* Base - displacement.  */
              }
            else
              {
-               fprintf (file, "*+%s(%d)",
+               fprintf (file, "*+%s(" HOST_WIDE_INT_PRINT_DEC ")",
                         reg_names[REGNO (op0)],
                         INTVAL (op1)); /* Base + displacement.  */
              }
@@ -2202,9 +2142,8 @@ c4x_print_operand_address (file, addr)
 /* Return nonzero if the floating point operand will fit
    in the immediate field.  */
 
-static int
-c4x_immed_float_p (op)
-     rtx op;
+int
+c4x_immed_float_p (rtx op)
 {
   long convval[2];
   int exponent;
@@ -2250,8 +2189,7 @@ c4x_immed_float_p (op)
    !!! FIXME.  The rptb_top insn may be sucked into a SEQUENCE.  */
 
 int
-c4x_rptb_nop_p (insn)
-     rtx insn;
+c4x_rptb_nop_p (rtx insn)
 {
   rtx start_label;
   int i;
@@ -2306,11 +2244,10 @@ c4x_rptb_nop_p (insn)
   Before we can create a repeat block looping instruction we have to
   verify that there are no jumps outside the loop and no jumps outside
   the loop go into this loop. This can happen in the basic blocks reorder
-  pass. The C4x cpu can not handle this.  */
+  pass. The C4x cpu cannot handle this.  */
 
 static int
-c4x_label_ref_used_p (x, code_label)
-     rtx x, code_label;
+c4x_label_ref_used_p (rtx x, rtx code_label)
 {
   enum rtx_code code;
   int i, j;
@@ -2341,8 +2278,7 @@ c4x_label_ref_used_p (x, code_label)
 
 
 static int
-c4x_rptb_valid_p (insn, start_label)
-     rtx insn, start_label;
+c4x_rptb_valid_p (rtx insn, rtx start_label)
 {
   rtx end = insn;
   rtx start;
@@ -2353,7 +2289,7 @@ c4x_rptb_valid_p (insn, start_label)
     if (insn == start_label)
       break;
 
-  /* Note found then we can not use a rptb or rpts.  The label was
+  /* Note found then we cannot use a rptb or rpts.  The label was
      probably moved by the basic block reorder pass.  */
   if (! insn)
     return 0;
@@ -2402,8 +2338,7 @@ c4x_rptb_valid_p (insn, start_label)
 
 
 void
-c4x_rptb_insert (insn)
-     rtx insn;
+c4x_rptb_insert (rtx insn)
 {
   rtx end_label;
   rtx start_label;
@@ -2411,7 +2346,7 @@ c4x_rptb_insert (insn)
   rtx count_reg;
 
   /* If the count register has not been allocated to RC, say if
-     there is a movstr pattern in the loop, then do not insert a
+     there is a movmem pattern in the loop, then do not insert a
      RPTB instruction.  Instead we emit a decrement and branch
      at the end of the loop.  */
   count_reg = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0), 0);
@@ -2423,10 +2358,10 @@ c4x_rptb_insert (insn)
   
   if (! c4x_rptb_valid_p (insn, start_label))
     {
-      /* We can not use the rptb insn.  Replace it so reorg can use
+      /* We cannot use the rptb insn.  Replace it so reorg can use
          the delay slots of the jump insn.  */
-      emit_insn_before (gen_addqi3 (count_reg, count_reg, GEN_INT (-1)), insn);
-      emit_insn_before (gen_cmpqi (count_reg, GEN_INT (0)), insn);
+      emit_insn_before (gen_addqi3 (count_reg, count_reg, constm1_rtx), insn);
+      emit_insn_before (gen_cmpqi (count_reg, const0_rtx), insn);
       emit_insn_before (gen_bge (start_label), insn);
       LABEL_NUSES (start_label)++;
       delete_insn (insn);
@@ -2462,17 +2397,22 @@ c4x_rptb_insert (insn)
 }
 
 
-/* This function is a C4x special called immediately before delayed
-   branch scheduling.  We fix up RTPB style loops that didn't get RC
+/* We need to use direct addressing for large constants and addresses
+   that cannot fit within an instruction.  We must check for these
+   after after the final jump optimization pass, since this may
+   introduce a local_move insn for a SYMBOL_REF.  This pass
+   must come before delayed branch slot filling since it can generate
+   additional instructions.
+
+   This function also fixes up RTPB style loops that didn't get RC
    allocated as the loop counter.  */
 
-void
-c4x_process_after_reload (first)
-     rtx first;
+static void
+c4x_reorg (void)
 {
   rtx insn;
 
-  for (insn = first; insn; insn = NEXT_INSN (insn))
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     {
       /* Look for insn.  */
       if (INSN_P (insn))
@@ -2502,48 +2442,40 @@ c4x_process_after_reload (first)
             with only the 'deleted' bit set.  Transform it into a note
             to avoid confusion of subsequent processing.  */
          if (INSN_DELETED_P (old))
-           {
-             PUT_CODE (old, NOTE);
-             NOTE_LINE_NUMBER (old) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (old) = 0;
-           }
+           SET_INSN_DELETED (old);
        }
     }
 }
 
 
-static int
-c4x_a_register (op)
-     rtx op;
+int
+c4x_a_register (rtx op)
 {
   return REG_P (op) && IS_ADDR_OR_PSEUDO_REG (op);
 }
 
 
-static int
-c4x_x_register (op)
-     rtx op;
+int
+c4x_x_register (rtx op)
 {
   return REG_P (op) && IS_INDEX_OR_PSEUDO_REG (op);
 }
 
 
 static int
-c4x_immed_int_constant (op)
-     rtx op;
+c4x_immed_int_constant (rtx op)
 {
   if (GET_CODE (op) != CONST_INT)
     return 0;
 
   return GET_MODE (op) == VOIDmode
-    || GET_MODE_CLASS (op) == MODE_INT
-    || GET_MODE_CLASS (op) == MODE_PARTIAL_INT;
+    || GET_MODE_CLASS (GET_MODE (op)) == MODE_INT
+    || GET_MODE_CLASS (GET_MODE (op)) == MODE_PARTIAL_INT;
 }
 
 
 static int
-c4x_immed_float_constant (op)
-     rtx op;
+c4x_immed_float_constant (rtx op)
 {
   if (GET_CODE (op) != CONST_DOUBLE)
     return 0;
@@ -2557,8 +2489,7 @@ c4x_immed_float_constant (op)
 
 
 int
-c4x_shiftable_constant (op)
-     rtx op;
+c4x_shiftable_constant (rtx op)
 {
   int i;
   int mask;
@@ -2578,24 +2509,21 @@ c4x_shiftable_constant (op)
 
 
 int
-c4x_H_constant (op)
-     rtx op;
+c4x_H_constant (rtx op)
 {
   return c4x_immed_float_constant (op) && c4x_immed_float_p (op);
 }
 
 
 int
-c4x_I_constant (op)
-     rtx op;
+c4x_I_constant (rtx op)
 {
   return c4x_immed_int_constant (op) && IS_INT16_CONST (INTVAL (op));
 }
 
 
 int
-c4x_J_constant (op)
-     rtx op;
+c4x_J_constant (rtx op)
 {
   if (TARGET_C3X)
     return 0;
@@ -2603,9 +2531,8 @@ c4x_J_constant (op)
 }
 
 
-static int
-c4x_K_constant (op)
-     rtx op;
+int
+c4x_K_constant (rtx op)
 {
   if (TARGET_C3X || ! c4x_immed_int_constant (op))
     return 0;
@@ -2614,24 +2541,21 @@ c4x_K_constant (op)
 
 
 int
-c4x_L_constant (op)
-     rtx op;
+c4x_L_constant (rtx op)
 {
   return c4x_immed_int_constant (op) && IS_UINT16_CONST (INTVAL (op));
 }
 
 
-static int
-c4x_N_constant (op)
-     rtx op;
+int
+c4x_N_constant (rtx op)
 {
   return c4x_immed_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op));
 }
 
 
-static int
-c4x_O_constant (op)
-     rtx op;
+int
+c4x_O_constant (rtx op)
 {
   return c4x_immed_int_constant (op) && IS_HIGH_CONST (INTVAL (op));
 }
@@ -2647,8 +2571,7 @@ c4x_O_constant (op)
    they are handled by the <> constraints.  */
 
 int
-c4x_Q_constraint (op)
-     rtx op;
+c4x_Q_constraint (rtx op)
 {
   enum machine_mode mode = GET_MODE (op);
 
@@ -2693,8 +2616,7 @@ c4x_Q_constraint (op)
    *ARx, *+ARx(n) for n < 32.  */
 
 int
-c4x_R_constraint (op)
-     rtx op;
+c4x_R_constraint (rtx op)
 {
   enum machine_mode mode = GET_MODE (op);
 
@@ -2735,8 +2657,7 @@ c4x_R_constraint (op)
 
 
 static int
-c4x_R_indirect (op)
-     rtx op;
+c4x_R_indirect (rtx op)
 {
   enum machine_mode mode = GET_MODE (op);
 
@@ -2780,8 +2701,7 @@ c4x_R_indirect (op)
    they are handled by the <> constraints.  */
 
 int
-c4x_S_constraint (op)
-     rtx op;
+c4x_S_constraint (rtx op)
 {
   enum machine_mode mode = GET_MODE (op);
   if (GET_CODE (op) != MEM)
@@ -2839,9 +2759,8 @@ c4x_S_constraint (op)
 }
 
 
-static int
-c4x_S_indirect (op)
-     rtx op;
+int
+c4x_S_indirect (rtx op)
 {
   enum machine_mode mode = GET_MODE (op);
   if (GET_CODE (op) != MEM)
@@ -2918,8 +2837,7 @@ c4x_S_indirect (op)
 /* Direct memory operand.  */
 
 int
-c4x_T_constraint (op)
-     rtx op;
+c4x_T_constraint (rtx op)
 {
   if (GET_CODE (op) != MEM)
     return 0;
@@ -2930,7 +2848,7 @@ c4x_T_constraint (op)
       /* Allow call operands.  */
       return GET_CODE (op) == SYMBOL_REF
        && GET_MODE (op) == Pmode
-       && SYMBOL_REF_FLAG (op);
+       && SYMBOL_REF_FUNCTION_P (op);
     }
 
   /* HImode and HFmode are not offsettable.  */
@@ -2948,8 +2866,7 @@ c4x_T_constraint (op)
 /* Symbolic operand.  */
 
 int
-c4x_U_constraint (op)
-     rtx op;
+c4x_U_constraint (rtx op)
 {
   /* Don't allow direct addressing to an arbitrary constant.  */
   return GET_CODE (op) == CONST
@@ -2959,9 +2876,7 @@ c4x_U_constraint (op)
 
 
 int
-c4x_autoinc_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+c4x_autoinc_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (GET_CODE (op) == MEM)
     {
@@ -2980,106 +2895,8 @@ c4x_autoinc_operand (op, mode)
 }
 
 
-/* Match any operand.  */
-
-int
-any_operand (op, mode)
-     register rtx op ATTRIBUTE_UNUSED;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return 1;
-}
-
-
-/* Nonzero if OP is a floating point value with value 0.0.  */
-
-int
-fp_zero_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  REAL_VALUE_TYPE r;
-
-  if (GET_CODE (op) != CONST_DOUBLE)
-    return 0;
-  REAL_VALUE_FROM_CONST_DOUBLE (r, op);
-  return REAL_VALUES_EQUAL (r, dconst0);
-}
-
-
 int
-const_operand (op, mode)
-     register rtx op;
-     register enum machine_mode mode;
-{
-  switch (mode)
-    {
-    case QFmode:
-    case HFmode:
-      if (GET_CODE (op) != CONST_DOUBLE
-         || GET_MODE (op) != mode
-         || GET_MODE_CLASS (mode) != MODE_FLOAT)
-       return 0;
-
-      return c4x_immed_float_p (op);
-
-#if Pmode != QImode
-    case Pmode:
-#endif
-    case QImode:
-      if (GET_CODE (op) == CONSTANT_P_RTX)
-       return 1;
-
-      if (GET_CODE (op) != CONST_INT
-         || (GET_MODE (op) != VOIDmode && GET_MODE (op) != mode)
-         || GET_MODE_CLASS (mode) != MODE_INT)
-       return 0;
-
-      return IS_HIGH_CONST (INTVAL (op)) || IS_INT16_CONST (INTVAL (op));
-
-    case HImode:
-      return 0;
-
-    default:
-      return 0;
-    }
-}
-
-
-int
-stik_const_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return c4x_K_constant (op);
-}
-
-
-int
-not_const_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return c4x_N_constant (op);
-}
-
-
-int
-reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (GET_CODE (op) == SUBREG
-      && GET_MODE (op) == QFmode)
-    return 0;
-  return register_operand (op, mode);
-}
-
-
-int
-mixed_subreg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+mixed_subreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   /* Allow (subreg:HF (reg:HI)) that be generated for a union of an
      int and a long double.  */
@@ -3093,9 +2910,7 @@ mixed_subreg_operand (op, mode)
 
 
 int
-reg_imm_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+reg_imm_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (REG_P (op) || CONSTANT_P (op))
     return 1;
@@ -3104,9 +2919,7 @@ reg_imm_operand (op, mode)
 
 
 int
-not_modify_reg (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+not_modify_reg (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (REG_P (op) || CONSTANT_P (op))
     return 1;
@@ -3152,9 +2965,7 @@ not_modify_reg (op, mode)
 
 
 int
-not_rc_reg (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+not_rc_reg (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (REG_P (op) && REGNO (op) == RC_REGNO)
     return 0;
@@ -3162,350 +2973,8 @@ not_rc_reg (op, mode)
 }
 
 
-/* Extended precision register R0-R1.  */
-
-int
-r0r1_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! reg_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  return REG_P (op) && IS_R0R1_OR_PSEUDO_REG (op);
-}
-
-
-/* Extended precision register R2-R3.  */
-
-int
-r2r3_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! reg_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  return REG_P (op) && IS_R2R3_OR_PSEUDO_REG (op);
-}
-
-
-/* Low extended precision register R0-R7.  */
-
-int
-ext_low_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! reg_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  return REG_P (op) && IS_EXT_LOW_OR_PSEUDO_REG (op);
-}
-
-
-/* Extended precision register.  */
-
-int
-ext_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! reg_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  if (! REG_P (op))
-    return 0;
-  return IS_EXT_OR_PSEUDO_REG (op);
-}
-
-
-/* Standard precision register.  */
-
-int
-std_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! reg_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  return REG_P (op) && IS_STD_OR_PSEUDO_REG (op);
-}
-
-/* Standard precision or normal register.  */
-
-int
-std_or_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (reload_in_progress)
-    return std_reg_operand (op, mode);
-  return reg_operand (op, mode);
-}
-
-/* Address register.  */
-
-int
-addr_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! reg_operand (op, mode))
-    return 0;
-  return c4x_a_register (op);
-}
-
-
-/* Index register.  */
-
-int
-index_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! reg_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  return c4x_x_register (op);
-}
-
-
-/* DP register.  */
-
-int
-dp_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return REG_P (op) && IS_DP_OR_PSEUDO_REG (op);
-}
-
-
-/* SP register.  */
-
-int
-sp_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return REG_P (op) && IS_SP_OR_PSEUDO_REG (op);
-}
-
-
-/* ST register.  */
-
-int
-st_reg_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return REG_P (op) && IS_ST_OR_PSEUDO_REG (op);
-}
-
-
-/* RC register.  */
-
-int
-rc_reg_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return REG_P (op) && IS_RC_OR_PSEUDO_REG (op);
-}
-
-
-int
-call_address_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return (REG_P (op) || symbolic_address_operand (op, mode));
-}
-
-
-/* Symbolic address operand.  */
-
-int
-symbolic_address_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  switch (GET_CODE (op))
-    {
-    case CONST:
-    case SYMBOL_REF:
-    case LABEL_REF:
-      return 1;
-    default:
-      return 0;
-    }
-}
-
-
-/* Check dst operand of a move instruction.  */
-
-int
-dst_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (GET_CODE (op) == SUBREG
-      && mixed_subreg_operand (op, mode))
-    return 0;
-
-  if (REG_P (op))
-    return reg_operand (op, mode);
-
-  return nonimmediate_operand (op, mode);
-}
-
-
-/* Check src operand of two operand arithmetic instructions.  */
-
-int
-src_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (GET_CODE (op) == SUBREG
-      && mixed_subreg_operand (op, mode))
-    return 0;
-
-  if (REG_P (op))
-    return reg_operand (op, mode);
-
-  if (mode == VOIDmode)
-    mode = GET_MODE (op);
-
-  if (GET_CODE (op) == CONST_INT)
-    return (mode == QImode || mode == Pmode || mode == HImode)
-      && c4x_I_constant (op);
-
-  /* We don't like CONST_DOUBLE integers.  */
-  if (GET_CODE (op) == CONST_DOUBLE)
-    return c4x_H_constant (op);
-
-  /* Disallow symbolic addresses.  Only the predicate
-     symbolic_address_operand will match these.  */
-  if (GET_CODE (op) == SYMBOL_REF
-      || GET_CODE (op) == LABEL_REF
-      || GET_CODE (op) == CONST)
-    return 0;
-
-  /* If TARGET_LOAD_DIRECT_MEMS is non-zero, disallow direct memory
-     access to symbolic addresses.  These operands will get forced
-     into a register and the movqi expander will generate a
-     HIGH/LO_SUM pair if TARGET_EXPOSE_LDP is non-zero.  */
-  if (GET_CODE (op) == MEM
-      && ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
-          || GET_CODE (XEXP (op, 0)) == LABEL_REF
-          || GET_CODE (XEXP (op, 0)) == CONST)))
-    return ! TARGET_LOAD_DIRECT_MEMS && GET_MODE (op) == mode;
-
-  return general_operand (op, mode);
-}
-
-
-int
-src_hi_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (c4x_O_constant (op))
-    return 1;
-  return src_operand (op, mode);
-}
-
-
-/* Check src operand of two operand logical instructions.  */
-
-int
-lsrc_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (mode == VOIDmode)
-    mode = GET_MODE (op);
-
-  if (mode != QImode && mode != Pmode)
-    fatal_insn ("mode not QImode", op);
-
-  if (GET_CODE (op) == CONST_INT)
-    return c4x_L_constant (op) || c4x_J_constant (op);
-
-  return src_operand (op, mode);
-}
-
-
-/* Check src operand of two operand tricky instructions.  */
-
-int
-tsrc_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (mode == VOIDmode)
-    mode = GET_MODE (op);
-
-  if (mode != QImode && mode != Pmode)
-    fatal_insn ("mode not QImode", op);
-
-  if (GET_CODE (op) == CONST_INT)
-    return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op);
-
-  return src_operand (op, mode);
-}
-
-
-int
-reg_or_const_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return reg_operand (op, mode) || const_operand (op, mode);
-}
-
-
-/* Check for indirect operands allowable in parallel instruction.  */
-
-int
-par_ind_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (mode != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  return c4x_S_indirect (op);
-}
-
-
-/* Check for operands allowable in parallel instruction.  */
-
-int
-parallel_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return ext_low_reg_operand (op, mode) || par_ind_operand (op, mode);
-}
-
-
 static void 
-c4x_S_address_parse (op, base, incdec, index, disp)
-     rtx op;
-     int *base;
-     int *incdec;
-     int *index;
-     int *disp;
+c4x_S_address_parse (rtx op, int *base, int *incdec, int *index, int *disp)
 {
   *base = 0;
   *incdec = 0;
@@ -3599,7 +3068,7 @@ c4x_S_address_parse (op, base, incdec, index, disp)
            return;
          }
       }
-      /* Fallthrough.  */
+      /* Fall through.  */
 
     default:
       fatal_insn ("invalid indirect (S) memory address", op);
@@ -3608,11 +3077,7 @@ c4x_S_address_parse (op, base, incdec, index, disp)
 
 
 int
-c4x_address_conflict (op0, op1, store0, store1)
-     rtx op0;
-     rtx op1;
-     int store0;
-     int store1;
+c4x_address_conflict (rtx op0, rtx op1, int store0, int store1)
 {
   int base0;
   int base1;
@@ -3636,7 +3101,7 @@ c4x_address_conflict (op0, op1, store0, store1)
         cause problems except when writing to a hardware device such
         as a FIFO since the second write will be lost.  The user
         should flag the hardware location as being volatile so that
-        we don't do this optimisation.  While it is unlikely that we
+        we don't do this optimization.  While it is unlikely that we
         have an aliased address if both locations are not marked
         volatile, it is probably safer to flag a potential conflict
         if either location is volatile.  */
@@ -3662,7 +3127,7 @@ c4x_address_conflict (op0, op1, store0, store1)
   if (! TARGET_DEVEL && base0 == base1 && (incdec0 || incdec1))
     return 1;
 
-  /* We can not optimize the case where op1 and op2 refer to the same
+  /* We cannot optimize the case where op1 and op2 refer to the same
      address.  */
   if (base0 == base1 && disp0 == disp1 && index0 == index1)
     return 1;
@@ -3675,10 +3140,7 @@ c4x_address_conflict (op0, op1, store0, store1)
 /* Check for while loop inside a decrement and branch loop.  */
 
 int
-c4x_label_conflict (insn, jump, db)
-     rtx insn;
-     rtx jump;
-     rtx db;
+c4x_label_conflict (rtx insn, rtx jump, rtx db)
 {
   while (insn)
     {
@@ -3698,9 +3160,8 @@ c4x_label_conflict (insn, jump, db)
 /* Validate combination of operands for parallel load/store instructions.  */
 
 int
-valid_parallel_load_store (operands, mode)
-     rtx *operands;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+valid_parallel_load_store (rtx *operands,
+                          enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   rtx op0 = operands[0];
   rtx op1 = operands[1];
@@ -3754,9 +3215,8 @@ valid_parallel_load_store (operands, mode)
 
 
 int
-valid_parallel_operands_4 (operands, mode)
-     rtx *operands;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+valid_parallel_operands_4 (rtx *operands,
+                          enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   rtx op0 = operands[0];
   rtx op2 = operands[2];
@@ -3779,9 +3239,8 @@ valid_parallel_operands_4 (operands, mode)
 
 
 int
-valid_parallel_operands_5 (operands, mode)
-     rtx *operands;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+valid_parallel_operands_5 (rtx *operands,
+                          enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   int regs = 0;
   rtx op0 = operands[0];
@@ -3820,9 +3279,8 @@ valid_parallel_operands_5 (operands, mode)
 
 
 int
-valid_parallel_operands_6 (operands, mode)
-     rtx *operands;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+valid_parallel_operands_6 (rtx *operands,
+                          enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   int regs = 0;
   rtx op0 = operands[0];
@@ -3876,17 +3334,21 @@ valid_parallel_operands_6 (operands, mode)
    that the destination regno is valid if we have a 2 operand insn.  */
 
 static int
-c4x_valid_operands (code, operands, mode, force)
-     enum rtx_code code;
-     rtx *operands;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-     int force;
+c4x_valid_operands (enum rtx_code code, rtx *operands,
+                   enum machine_mode mode ATTRIBUTE_UNUSED,
+                   int force)
 {
+  rtx op0;
   rtx op1;
   rtx op2;
   enum rtx_code code1;
   enum rtx_code code2;
 
+
+  /* FIXME, why can't we tighten the operands for IF_THEN_ELSE?  */
+  if (code == IF_THEN_ELSE)
+      return 1 || (operands[0] == operands[2] || operands[0] == operands[3]);
+
   if (code == COMPARE)
     {
       op1 = operands[0];
@@ -3898,6 +3360,10 @@ c4x_valid_operands (code, operands, mode, force)
       op2 = operands[2];
     }
 
+  op0 = operands[0];
+
+  if (GET_CODE (op0) == SUBREG)
+    op0 = SUBREG_REG (op0);
   if (GET_CODE (op1) == SUBREG)
     op1 = SUBREG_REG (op1);
   if (GET_CODE (op2) == SUBREG)
@@ -3906,6 +3372,7 @@ c4x_valid_operands (code, operands, mode, force)
   code1 = GET_CODE (op1);
   code2 = GET_CODE (op2);
 
+  
   if (code1 == REG && code2 == REG)
     return 1;
 
@@ -3916,6 +3383,7 @@ c4x_valid_operands (code, operands, mode, force)
       return c4x_R_indirect (op1) && c4x_R_indirect (op2);
     }
 
+  /* We cannot handle two MEMs or two CONSTS, etc.  */
   if (code1 == code2)
     return 0;
 
@@ -3935,11 +3403,6 @@ c4x_valid_operands (code, operands, mode, force)
 
          /* Any valid memory operand screened by src_operand is OK.  */
        case MEM:
-         
-         /* After CSE, any remaining (ADDRESSOF:P reg) gets converted
-            into a stack slot memory address comprising a PLUS and a
-            constant.  */
-       case ADDRESSOF:
          break;
          
        default:
@@ -3947,61 +3410,69 @@ c4x_valid_operands (code, operands, mode, force)
          break;
        }
       
+      if (GET_CODE (op0) == SCRATCH)
+         return 1;
+
+      if (!REG_P (op0))
+         return 0;
+
       /* Check that we have a valid destination register for a two operand
         instruction.  */
-      return ! force || code == COMPARE || REGNO (op1) == REGNO (operands[0]);
+      return ! force || code == COMPARE || REGNO (op1) == REGNO (op0);
     }
 
-  /* We assume MINUS is commutative since the subtract patterns
-     also support the reverse subtract instructions.  Since op1
-     is not a register, and op2 is a register, op1 can only
-     be a restricted memory operand for a shift instruction.  */
+
+  /* Check non-commutative operators.  */
   if (code == ASHIFTRT || code == LSHIFTRT
       || code == ASHIFT || code == COMPARE)
     return code2 == REG
       && (c4x_S_indirect (op1) || c4x_R_indirect (op1));
-  
-  switch (code1)
+
+
+  /* Assume MINUS is commutative since the subtract patterns
+     also support the reverse subtract instructions.  Since op1
+     is not a register, and op2 is a register, op1 can only
+     be a restricted memory operand for a shift instruction.  */
+  if (code2 == REG)
     {
-    case CONST_INT:
-      if (c4x_J_constant (op1) && c4x_R_indirect (op2))
-       return 1;
-      break;
+      switch (code1)
+       {
+       case CONST_INT:
+         break;
       
-    case CONST_DOUBLE:
-      if (! c4x_H_constant (op1))
-       return 0;
-      break;
+       case CONST_DOUBLE:
+         if (! c4x_H_constant (op1))
+           return 0;
+         break;
 
-      /* Any valid memory operand screened by src_operand is OK.  */      
-    case MEM:
-#if 0
-      if (code2 != REG)
-       return 0;
-#endif
-      break;
+         /* Any valid memory operand screened by src_operand is OK.  */      
+       case MEM:
+         break;
+         
+       default:
+         abort ();
+         break;
+       }
 
-      /* After CSE, any remaining (ADDRESSOF:P reg) gets converted
-        into a stack slot memory address comprising a PLUS and a
-        constant.  */
-    case ADDRESSOF:
-      break;
-      
-    default:
-      abort ();
-      break;
+      if (GET_CODE (op0) == SCRATCH)
+         return 1;
+
+      if (!REG_P (op0))
+         return 0;
+
+      /* Check that we have a valid destination register for a two operand
+        instruction.  */
+      return ! force || REGNO (op1) == REGNO (op0);
     }
       
-  /* Check that we have a valid destination register for a two operand
-     instruction.  */
-  return ! force || REGNO (op1) == REGNO (operands[0]);
+  if (c4x_J_constant (op1) && c4x_R_indirect (op2))
+    return 1;
+
+  return 0;
 }
 
 
-int valid_operands (code, operands, mode)
-     enum rtx_code code;
-     rtx *operands;
-     enum machine_mode mode;
+int valid_operands (enum rtx_code code, rtx *operands, enum machine_mode mode)
 {
 
   /* If we are not optimizing then we have to let anything go and let
@@ -4017,10 +3488,7 @@ int valid_operands (code, operands, mode)
 
 
 int
-legitimize_operands (code, operands, mode)
-     enum rtx_code code;
-     rtx *operands;
-     enum machine_mode mode;
+legitimize_operands (enum rtx_code code, rtx *operands, enum machine_mode mode)
 {
   /* Compare only has 2 operands.  */
   if (code == COMPARE)
@@ -4028,7 +3496,7 @@ legitimize_operands (code, operands, mode)
       /* During RTL generation, force constants into pseudos so that
         they can get hoisted out of loops.  This will tie up an extra
         register but can save an extra cycle.  Only do this if loop
-        optimisation enabled.  (We cannot pull this trick for add and
+        optimization enabled.  (We cannot pull this trick for add and
         sub instructions since the flow pass won't find
         autoincrements etc.)  This allows us to generate compare
         instructions like CMPI R0, *AR0++ where R0 = 42, say, instead
@@ -4043,7 +3511,6 @@ legitimize_operands (code, operands, mode)
          && TARGET_HOIST
          && optimize > 0
          && GET_CODE (operands[1]) == CONST_INT 
-         && preserve_subexpressions_p ()
          && rtx_cost (operands[1], code) > 1)
        operands[1] = force_reg (mode, operands[1]);
       
@@ -4061,13 +3528,12 @@ legitimize_operands (code, operands, mode)
       && TARGET_HOIST
       && optimize > 1
       && GET_CODE (operands[2]) == CONST_INT
-      && preserve_subexpressions_p ()
       && rtx_cost (operands[2], code) > 1)
     operands[2] = force_reg (mode, operands[2]);
 
   /* We can get better code on a C30 if we force constant shift counts
      into a register.  This way they can get hoisted out of loops,
-     tying up a register, but saving an instruction.  The downside is
+     tying up a register but saving an instruction.  The downside is
      that they may get allocated to an address or index register, and
      thus we will get a pipeline conflict if there is a nearby
      indirect address using an address register. 
@@ -4101,6 +3567,17 @@ legitimize_operands (code, operands, mode)
       && (GET_CODE (operands[2]) != CONST_INT))
     operands[2] = gen_rtx_NEG (mode, negate_rtx (mode, operands[2]));
   
+
+  /* When the shift count is greater than 32 then the result 
+     can be implementation dependent.  We truncate the result to
+     fit in 5 bits so that we do not emit invalid code when
+     optimizing---such as trying to generate lhu2 with 20021124-1.c.  */
+  if (((code == ASHIFTRT || code == LSHIFTRT || code == ASHIFT)
+      && (GET_CODE (operands[2]) == CONST_INT))
+      && INTVAL (operands[2]) > (GET_MODE_BITSIZE (mode) - 1))
+      operands[2]
+         = GEN_INT (INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1));
+
   return 1;
 }
 
@@ -4108,9 +3585,7 @@ legitimize_operands (code, operands, mode)
 /* The following predicates are used for instruction scheduling.  */
 
 int
-group1_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+group1_reg_operand (rtx op, enum machine_mode mode)
 {
   if (mode != VOIDmode && mode != GET_MODE (op))
     return 0;
@@ -4121,9 +3596,7 @@ group1_reg_operand (op, mode)
 
 
 int
-group1_mem_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+group1_mem_operand (rtx op, enum machine_mode mode)
 {
   if (mode != VOIDmode && mode != GET_MODE (op))
     return 0;
@@ -4151,9 +3624,7 @@ group1_mem_operand (op, mode)
 /* Return true if any one of the address registers.  */
 
 int
-arx_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+arx_reg_operand (rtx op, enum machine_mode mode)
 {
   if (mode != VOIDmode && mode != GET_MODE (op))
     return 0;
@@ -4164,10 +3635,7 @@ arx_reg_operand (op, mode)
 
 
 static int
-c4x_arn_reg_operand (op, mode, regno)
-     rtx op;
-     enum machine_mode mode;
-     unsigned int regno;
+c4x_arn_reg_operand (rtx op, enum machine_mode mode, unsigned int regno)
 {
   if (mode != VOIDmode && mode != GET_MODE (op))
     return 0;
@@ -4178,10 +3646,7 @@ c4x_arn_reg_operand (op, mode, regno)
 
 
 static int
-c4x_arn_mem_operand (op, mode, regno)
-     rtx op;
-     enum machine_mode mode;
-     unsigned int regno;
+c4x_arn_mem_operand (rtx op, enum machine_mode mode, unsigned int regno)
 {
   if (mode != VOIDmode && mode != GET_MODE (op))
     return 0;
@@ -4233,180 +3698,140 @@ c4x_arn_mem_operand (op, mode, regno)
 
 
 int
-ar0_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar0_reg_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_reg_operand (op, mode, AR0_REGNO);
 }
 
 
 int
-ar0_mem_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar0_mem_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_mem_operand (op, mode, AR0_REGNO);
 }
 
 
 int
-ar1_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar1_reg_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_reg_operand (op, mode, AR1_REGNO);
 }
 
 
 int
-ar1_mem_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar1_mem_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_mem_operand (op, mode, AR1_REGNO);
 }
 
 
 int
-ar2_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar2_reg_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_reg_operand (op, mode, AR2_REGNO);
 }
 
 
 int
-ar2_mem_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar2_mem_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_mem_operand (op, mode, AR2_REGNO);
 }
 
 
 int
-ar3_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar3_reg_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_reg_operand (op, mode, AR3_REGNO);
 }
 
 
 int
-ar3_mem_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar3_mem_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_mem_operand (op, mode, AR3_REGNO);
 }
 
 
 int
-ar4_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar4_reg_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_reg_operand (op, mode, AR4_REGNO);
 }
 
 
 int
-ar4_mem_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar4_mem_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_mem_operand (op, mode, AR4_REGNO);
 }
 
 
 int
-ar5_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar5_reg_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_reg_operand (op, mode, AR5_REGNO);
 }
 
 
 int
-ar5_mem_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar5_mem_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_mem_operand (op, mode, AR5_REGNO);
 }
 
 
 int
-ar6_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar6_reg_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_reg_operand (op, mode, AR6_REGNO);
 }
 
 
 int
-ar6_mem_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar6_mem_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_mem_operand (op, mode, AR6_REGNO);
 }
 
 
 int
-ar7_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar7_reg_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_reg_operand (op, mode, AR7_REGNO);
 }
 
 
 int
-ar7_mem_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ar7_mem_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_mem_operand (op, mode, AR7_REGNO);
 }
 
 
 int
-ir0_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ir0_reg_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_reg_operand (op, mode, IR0_REGNO);
 }
 
 
 int
-ir0_mem_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ir0_mem_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_mem_operand (op, mode, IR0_REGNO);
 }
 
 
 int
-ir1_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ir1_reg_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_reg_operand (op, mode, IR1_REGNO);
 }
 
 
 int
-ir1_mem_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+ir1_mem_operand (rtx op, enum machine_mode mode)
 {
   return c4x_arn_mem_operand (op, mode, IR1_REGNO);
 }
@@ -4416,11 +3841,8 @@ ir1_mem_operand (op, mode)
    addressing.  */
 
 rtx
-c4x_operand_subword (op, i, validate_address, mode)
-     rtx op;
-     int i;
-     int validate_address;
-     enum machine_mode mode;
+c4x_operand_subword (rtx op, int i, int validate_address,
+                    enum machine_mode  mode)
 {
   if (mode != HImode && mode != HFmode)
     fatal_insn ("c4x_operand_subword: invalid mode", op);
@@ -4493,8 +3915,7 @@ static struct name_list *extern_head;
    present on external list.  */
 
 void
-c4x_global_label (name)
-     const char *name;
+c4x_global_label (const char *name)
 {
   struct name_list *p, *last;
 
@@ -4507,7 +3928,7 @@ c4x_global_label (name)
        return;
       p = p->next;
     }
-  p = (struct name_list *) permalloc (sizeof *p);
+  p = (struct name_list *) xmalloc (sizeof *p);
   p->next = global_head;
   p->name = name;
   global_head = p;
@@ -4534,8 +3955,7 @@ c4x_global_label (name)
 /* Add NAME to list of external symbols.  */
 
 void
-c4x_external_ref (name)
-     const char *name;
+c4x_external_ref (const char *name)
 {
   struct name_list *p;
 
@@ -4556,16 +3976,27 @@ c4x_external_ref (name)
        return;
       p = p->next;
     }
-  p = (struct name_list *) permalloc (sizeof *p);
+  p = (struct name_list *) xmalloc (sizeof *p);
   p->next = extern_head;
   p->name = name;
   extern_head = p;
 }
 
+/* We need to have a data section we can identify so that we can set
+   the DP register back to a data pointer in the small memory model.
+   This is only required for ISRs if we are paranoid that someone
+   may have quietly changed this register on the sly.  */
+static void
+c4x_file_start (void)
+{
+  default_file_start ();
+  fprintf (asm_out_file, "\t.version\t%d\n", c4x_cpu_version);
+  fputs ("\n\t.data\ndata_sec:\n", asm_out_file);
+}
 
-void
-c4x_file_end (fp)
-     FILE *fp;
+
+static void
+c4x_file_end (void)
 {
   struct name_list *p;
   
@@ -4573,19 +4004,17 @@ c4x_file_end (fp)
   p = extern_head;
   while (p)
     {
-      fprintf (fp, "\t.ref\t");
-      assemble_name (fp, p->name);
-      fprintf (fp, "\n");
+      fprintf (asm_out_file, "\t.ref\t");
+      assemble_name (asm_out_file, p->name);
+      fprintf (asm_out_file, "\n");
       p = p->next;
     }
-  fprintf (fp, "\t.end\n");
+  fprintf (asm_out_file, "\t.end\n");
 }
 
 
 static void
-c4x_check_attribute (attrib, list, decl, attributes)
-     const char *attrib;
-     tree list, decl, *attributes;
+c4x_check_attribute (const char *attrib, tree list, tree decl, tree *attributes)
 {
   while (list != NULL_TREE
          && IDENTIFIER_POINTER (TREE_PURPOSE (list))
@@ -4598,8 +4027,7 @@ c4x_check_attribute (attrib, list, decl, attributes)
 
 
 static void
-c4x_insert_attributes (decl, attributes)
-     tree decl, *attributes;
+c4x_insert_attributes (tree decl, tree *attributes)
 {
   switch (TREE_CODE (decl))
     {
@@ -4608,6 +4036,7 @@ c4x_insert_attributes (decl, attributes)
       c4x_check_attribute ("const", pure_tree, decl, attributes);
       c4x_check_attribute ("noreturn", noreturn_tree, decl, attributes);
       c4x_check_attribute ("interrupt", interrupt_tree, decl, attributes);
+      c4x_check_attribute ("naked", naked_tree, decl, attributes);
       break;
 
     case VAR_DECL:
@@ -4624,9 +4053,7 @@ const struct attribute_spec c4x_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   { "interrupt",    0, 0, false, true,  true,  c4x_handle_fntype_attribute },
-  /* FIXME: code elsewhere in this file treats "naked" as a synonym of
-     "interrupt"; should it be accepted here?  */
-  { "assembler",    0, 0, false, true,  true,  c4x_handle_fntype_attribute },
+  { "naked",    0, 0, false, true,  true,  c4x_handle_fntype_attribute },
   { "leaf_pretend", 0, 0, false, true,  true,  c4x_handle_fntype_attribute },
   { NULL,           0, 0, false, false, false, NULL }
 };
@@ -4634,16 +4061,14 @@ const struct attribute_spec c4x_attribute_table[] =
 /* Handle an attribute requiring a FUNCTION_TYPE;
    arguments as in struct attribute_spec.handler.  */
 static tree
-c4x_handle_fntype_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
+c4x_handle_fntype_attribute (tree *node, tree name,
+                            tree args ATTRIBUTE_UNUSED,
+                            int flags ATTRIBUTE_UNUSED,
+                            bool *no_add_attrs)
 {
   if (TREE_CODE (*node) != FUNCTION_TYPE)
     {
-      warning ("`%s' attribute only applies to functions",
+      warning (OPT_Wattributes, "%qs attribute only applies to functions",
               IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
@@ -4655,8 +4080,7 @@ c4x_handle_fntype_attribute (node, name, args, flags, no_add_attrs)
 /* !!! FIXME to emit RPTS correctly.  */
 
 int
-c4x_rptb_rpts_p (insn, op)
-     rtx insn, op;
+c4x_rptb_rpts_p (rtx insn, rtx op)
 {
   /* The next insn should be our label marking where the
      repeat block starts.  */
@@ -4669,8 +4093,8 @@ c4x_rptb_rpts_p (insn, op)
          where they are and print a warning.  We should
          probably move these insns before the repeat block insn.  */
       if (TARGET_DEBUG)
-       fatal_insn("c4x_rptb_rpts_p: Repeat block top label moved\n",
-                  insn);
+       fatal_insn ("c4x_rptb_rpts_p: Repeat block top label moved",
+                   insn);
       return 0;
     }
 
@@ -4700,8 +4124,7 @@ c4x_rptb_rpts_p (insn, op)
 /* Check if register r11 is used as the destination of an insn.  */
 
 static int
-c4x_r11_set_p(x)
-    rtx x;
+c4x_r11_set_p(rtx x)
 {
   rtx set;
   int i, j;
@@ -4740,8 +4163,7 @@ c4x_r11_set_p(x)
    sets the r11 register.  Check for this situation.  */
 
 int
-c4x_check_laj_p (insn)
-     rtx insn;
+c4x_check_laj_p (rtx insn)
 {
   insn = prev_nonnote_insn (insn);
 
@@ -4775,11 +4197,7 @@ c4x_check_laj_p (insn)
 #define        READ_USE_COST   2
 
 static int
-c4x_adjust_cost (insn, link, dep_insn, cost)
-     rtx insn;
-     rtx link;
-     rtx dep_insn;
-     int cost;
+c4x_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
 {
   /* Don't worry about this until we know what registers have been
      assigned.  */
@@ -4912,78 +4330,84 @@ c4x_adjust_cost (insn, link, dep_insn, cost)
 }
 
 void
-c4x_init_builtins ()
+c4x_init_builtins (void)
 {
   tree endlink = void_list_node;
 
-  builtin_function ("fast_ftoi",
-                   build_function_type 
-                   (integer_type_node,
-                    tree_cons (NULL_TREE, double_type_node, endlink)),
-                   C4X_BUILTIN_FIX, BUILT_IN_MD, NULL);
-  builtin_function ("ansi_ftoi",
-                   build_function_type 
-                   (integer_type_node, 
-                    tree_cons (NULL_TREE, double_type_node, endlink)),
-                   C4X_BUILTIN_FIX_ANSI, BUILT_IN_MD, NULL);
+  add_builtin_function ("fast_ftoi",
+                       build_function_type 
+                       (integer_type_node,
+                        tree_cons (NULL_TREE, double_type_node,
+                                   endlink)),
+                       C4X_BUILTIN_FIX, BUILT_IN_MD, NULL, NULL_TREE);
+  add_builtin_function ("ansi_ftoi",
+                       build_function_type 
+                       (integer_type_node, 
+                        tree_cons (NULL_TREE, double_type_node,
+                                   endlink)),
+                       C4X_BUILTIN_FIX_ANSI, BUILT_IN_MD, NULL,
+                       NULL_TREE);
   if (TARGET_C3X)
-    builtin_function ("fast_imult",
-                     build_function_type
-                     (integer_type_node, 
-                      tree_cons (NULL_TREE, integer_type_node,
-                                 tree_cons (NULL_TREE,
-                                            integer_type_node, endlink))),
-                     C4X_BUILTIN_MPYI, BUILT_IN_MD, NULL);
+    add_builtin_function ("fast_imult",
+                         build_function_type
+                         (integer_type_node, 
+                          tree_cons (NULL_TREE, integer_type_node,
+                                     tree_cons (NULL_TREE,
+                                                integer_type_node,
+                                                endlink))),
+                         C4X_BUILTIN_MPYI, BUILT_IN_MD, NULL,
+                         NULL_TREE);
   else
     {
-      builtin_function ("toieee",
-                       build_function_type 
-                       (double_type_node,
-                        tree_cons (NULL_TREE, double_type_node, endlink)),
-                       C4X_BUILTIN_TOIEEE, BUILT_IN_MD, NULL);
-      builtin_function ("frieee",
-                       build_function_type
-                       (double_type_node, 
-                        tree_cons (NULL_TREE, double_type_node, endlink)),
-                       C4X_BUILTIN_FRIEEE, BUILT_IN_MD, NULL);
-      builtin_function ("fast_invf",
-                       build_function_type 
-                       (double_type_node, 
-                        tree_cons (NULL_TREE, double_type_node, endlink)),
-                       C4X_BUILTIN_RCPF, BUILT_IN_MD, NULL);
+      add_builtin_function ("toieee",
+                           build_function_type 
+                           (double_type_node,
+                            tree_cons (NULL_TREE, double_type_node,
+                                       endlink)),
+                           C4X_BUILTIN_TOIEEE, BUILT_IN_MD, NULL,
+                           NULL_TREE);
+      add_builtin_function ("frieee",
+                           build_function_type
+                           (double_type_node, 
+                            tree_cons (NULL_TREE, double_type_node,
+                                       endlink)),
+                           C4X_BUILTIN_FRIEEE, BUILT_IN_MD, NULL,
+                           NULL_TREE);
+      add_builtin_function ("fast_invf",
+                           build_function_type 
+                           (double_type_node, 
+                            tree_cons (NULL_TREE, double_type_node,
+                                       endlink)),
+                           C4X_BUILTIN_RCPF, BUILT_IN_MD, NULL,
+                           NULL_TREE);
     }
 }
 
 
 rtx
-c4x_expand_builtin (exp, target, subtarget, mode, ignore)
-     tree exp;
-     rtx target;
-     rtx subtarget ATTRIBUTE_UNUSED;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-     int ignore ATTRIBUTE_UNUSED;
+c4x_expand_builtin (tree exp, rtx target,
+                   rtx subtarget ATTRIBUTE_UNUSED,
+                   enum machine_mode mode ATTRIBUTE_UNUSED,
+                   int ignore ATTRIBUTE_UNUSED)
 {
-  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
-  tree arglist = TREE_OPERAND (exp, 1);
   tree arg0, arg1;
   rtx r0, r1;
 
   switch (fcode)
     {
     case C4X_BUILTIN_FIX:
-      arg0 = TREE_VALUE (arglist);
+      arg0 = CALL_EXPR_ARG (exp, 0);
       r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
-      r0 = protect_from_queue (r0, 0);
       if (! target || ! register_operand (target, QImode))
        target = gen_reg_rtx (QImode);
       emit_insn (gen_fixqfqi_clobber (target, r0));
       return target;
 
     case C4X_BUILTIN_FIX_ANSI:
-      arg0 = TREE_VALUE (arglist);
+      arg0 = CALL_EXPR_ARG (exp, 0);
       r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
-      r0 = protect_from_queue (r0, 0);
       if (! target || ! register_operand (target, QImode))
        target = gen_reg_rtx (QImode);
       emit_insn (gen_fix_truncqfqi2 (target, r0));
@@ -4992,12 +4416,10 @@ c4x_expand_builtin (exp, target, subtarget, mode, ignore)
     case C4X_BUILTIN_MPYI:
       if (! TARGET_C3X)
        break;
-      arg0 = TREE_VALUE (arglist);
-      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      arg1 = CALL_EXPR_ARG (exp, 1);
       r0 = expand_expr (arg0, NULL_RTX, QImode, 0);
       r1 = expand_expr (arg1, NULL_RTX, QImode, 0);
-      r0 = protect_from_queue (r0, 0);
-      r1 = protect_from_queue (r1, 0);
       if (! target || ! register_operand (target, QImode))
        target = gen_reg_rtx (QImode);
       emit_insn (gen_mulqi3_24_clobber (target, r0, r1));
@@ -5006,9 +4428,8 @@ c4x_expand_builtin (exp, target, subtarget, mode, ignore)
     case C4X_BUILTIN_TOIEEE:
       if (TARGET_C3X)
        break;
-      arg0 = TREE_VALUE (arglist);
+      arg0 = CALL_EXPR_ARG (exp, 0);
       r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
-      r0 = protect_from_queue (r0, 0);
       if (! target || ! register_operand (target, QFmode))
        target = gen_reg_rtx (QFmode);
       emit_insn (gen_toieee (target, r0));
@@ -5017,11 +4438,8 @@ c4x_expand_builtin (exp, target, subtarget, mode, ignore)
     case C4X_BUILTIN_FRIEEE:
       if (TARGET_C3X)
        break;
-      arg0 = TREE_VALUE (arglist);
-      if (TREE_CODE (arg0) == VAR_DECL || TREE_CODE (arg0) == PARM_DECL)
-       put_var_into_stack (arg0);
+      arg0 = CALL_EXPR_ARG (exp, 0);
       r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
-      r0 = protect_from_queue (r0, 0);
       if (register_operand (r0, QFmode))
        {
          r1 = assign_stack_local (QFmode, GET_MODE_SIZE (QFmode), 0);
@@ -5036,9 +4454,8 @@ c4x_expand_builtin (exp, target, subtarget, mode, ignore)
     case C4X_BUILTIN_RCPF:
       if (TARGET_C3X)
        break;
-      arg0 = TREE_VALUE (arglist);
+      arg0 = CALL_EXPR_ARG (exp, 0);
       r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
-      r0 = protect_from_queue (r0, 0);
       if (! target || ! register_operand (target, QFmode))
        target = gen_reg_rtx (QFmode);
       emit_insn (gen_rcpfqf_clobber (target, r0));
@@ -5048,9 +4465,154 @@ c4x_expand_builtin (exp, target, subtarget, mode, ignore)
 }
 
 static void
-c4x_asm_named_section (name, flags)
-     const char *name;
-     unsigned int flags ATTRIBUTE_UNUSED;
+c4x_init_libfuncs (void)
+{
+  set_optab_libfunc (smul_optab, QImode, "__mulqi3");
+  set_optab_libfunc (sdiv_optab, QImode, "__divqi3");
+  set_optab_libfunc (udiv_optab, QImode, "__udivqi3");
+  set_optab_libfunc (smod_optab, QImode, "__modqi3");
+  set_optab_libfunc (umod_optab, QImode, "__umodqi3");
+  set_optab_libfunc (sdiv_optab, QFmode, "__divqf3");
+  set_optab_libfunc (smul_optab, HFmode, "__mulhf3");
+  set_optab_libfunc (sdiv_optab, HFmode, "__divhf3");
+  set_optab_libfunc (smul_optab, HImode, "__mulhi3");
+  set_optab_libfunc (sdiv_optab, HImode, "__divhi3");
+  set_optab_libfunc (udiv_optab, HImode, "__udivhi3");
+  set_optab_libfunc (smod_optab, HImode, "__modhi3");
+  set_optab_libfunc (umod_optab, HImode, "__umodhi3");
+  set_optab_libfunc (ffs_optab,  QImode, "__ffs");
+  smulhi3_libfunc           = init_one_libfunc ("__smulhi3_high");
+  umulhi3_libfunc           = init_one_libfunc ("__umulhi3_high");
+  fix_truncqfhi2_libfunc    = init_one_libfunc ("__fix_truncqfhi2");
+  fixuns_truncqfhi2_libfunc = init_one_libfunc ("__ufix_truncqfhi2");
+  fix_trunchfhi2_libfunc    = init_one_libfunc ("__fix_trunchfhi2");
+  fixuns_trunchfhi2_libfunc = init_one_libfunc ("__ufix_trunchfhi2");
+  floathiqf2_libfunc        = init_one_libfunc ("__floathiqf2");
+  floatunshiqf2_libfunc     = init_one_libfunc ("__ufloathiqf2");
+  floathihf2_libfunc        = init_one_libfunc ("__floathihf2");
+  floatunshihf2_libfunc     = init_one_libfunc ("__ufloathihf2");
+}
+
+static void
+c4x_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED,
+                      tree decl ATTRIBUTE_UNUSED)
 {
   fprintf (asm_out_file, "\t.sect\t\"%s\"\n", name);
 }
+
+static void
+c4x_globalize_label (FILE *stream, const char *name)
+{
+  default_globalize_label (stream, name);
+  c4x_global_label (name);
+}
+\f
+#define SHIFT_CODE_P(C) \
+  ((C) == ASHIFT || (C) == ASHIFTRT || (C) == LSHIFTRT)
+#define LOGICAL_CODE_P(C) \
+  ((C) == NOT || (C) == AND || (C) == IOR || (C) == XOR)
+
+/* Compute a (partial) cost for rtx X.  Return true if the complete
+   cost has been computed, and false if subexpressions should be
+   scanned.  In either case, *TOTAL contains the cost result.  */
+
+static bool
+c4x_rtx_costs (rtx x, int code, int outer_code, int *total)
+{
+  HOST_WIDE_INT val;
+
+  switch (code)
+    {
+      /* Some small integers are effectively free for the C40.  We should
+         also consider if we are using the small memory model.  With
+         the big memory model we require an extra insn for a constant
+         loaded from memory.  */
+
+    case CONST_INT:
+      val = INTVAL (x);
+      if (c4x_J_constant (x))
+       *total = 0;
+      else if (! TARGET_C3X
+              && outer_code == AND
+              && (val == 255 || val == 65535))
+       *total = 0;
+      else if (! TARGET_C3X
+              && (outer_code == ASHIFTRT || outer_code == LSHIFTRT)
+              && (val == 16 || val == 24))
+       *total = 0;
+      else if (TARGET_C3X && SHIFT_CODE_P (outer_code))
+       *total = 3;
+      else if (LOGICAL_CODE_P (outer_code)
+               ? c4x_L_constant (x) : c4x_I_constant (x))
+       *total = 2;
+      else
+       *total = 4;
+      return true;
+
+    case CONST:
+    case LABEL_REF:
+    case SYMBOL_REF:
+      *total = 4;
+      return true;
+
+    case CONST_DOUBLE:
+      if (c4x_H_constant (x))
+       *total = 2;
+      else if (GET_MODE (x) == QFmode)
+       *total = 4;
+      else
+       *total = 8;
+      return true;
+
+    /* ??? Note that we return true, rather than false so that rtx_cost
+       doesn't include the constant costs.  Otherwise expand_mult will
+       think that it is cheaper to synthesize a multiply rather than to
+       use a multiply instruction.  I think this is because the algorithm
+       synth_mult doesn't take into account the loading of the operands,
+       whereas the calculation of mult_cost does.  */
+    case PLUS:
+    case MINUS:
+    case AND:
+    case IOR:
+    case XOR:
+    case ASHIFT:
+    case ASHIFTRT:
+    case LSHIFTRT:
+      *total = COSTS_N_INSNS (1);
+      return true;
+
+    case MULT:
+      *total = COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
+                             || TARGET_MPYI ? 1 : 14);
+      return true;
+
+    case DIV:
+    case UDIV:
+    case MOD:
+    case UMOD:
+      *total = COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
+                             ? 15 : 50);
+      return true;
+
+    default:
+      return false;
+    }
+}
+\f
+/* Worker function for TARGET_ASM_EXTERNAL_LIBCALL.  */
+
+static void
+c4x_external_libcall (rtx fun)
+{
+  /* This is only needed to keep asm30 happy for ___divqf3 etc.  */
+  c4x_external_ref (XSTR (fun, 0));
+}
+
+/* Worker function for TARGET_STRUCT_VALUE_RTX.  */
+
+static rtx
+c4x_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+                     int incoming ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (Pmode, AR0_REGNO);
+}