freebsd.h (CPP_CPU64_DEFAULT_SPEC): Replace with...
[gcc.git] / gcc / config / crx / crx.c
index 838993e8174ff0205c6235761805f3bfe49e9c4d..8f635d5a171e1516727d1f5c9155835c39dd0c7d 100644 (file)
@@ -1,12 +1,13 @@
 /* Output routines for GCC for CRX.
    Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004  Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
 
    This file is part of GCC.
 
    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
+   by the Free Software Foundation; either version 3, or (at your
    option) any later version.
 
    GCC is distributed in the hope that it will be useful, but WITHOUT
@@ -15,9 +16,8 @@
    License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING.  If not, write to
-   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
 
 /*****************************************************************************/
 /* HEADER INCLUDES                                                          */
@@ -32,7 +32,6 @@
 #include "tm_p.h"
 #include "regs.h"
 #include "hard-reg-set.h"
-#include "real.h"
 #include "insn-config.h"
 #include "conditions.h"
 #include "output.h"
@@ -44,8 +43,9 @@
 #include "recog.h"
 #include "expr.h"
 #include "optabs.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "basic-block.h"
+#include "df.h"
 #include "target.h"
 #include "target-def.h"
 
@@ -118,17 +118,6 @@ static int size_for_adjusting_sp;
  * of the memory reference from PRINT_OPERAND to PRINT_OPERAND_ADDRESS. */
 static enum machine_mode output_memory_reference_mode;
 
-/*****************************************************************************/
-/* GLOBAL VARIABLES                                                         */
-/*****************************************************************************/
-
-/* Table of machine attributes.  */
-const struct attribute_spec crx_attribute_table[];
-
-/* Test and compare insns use these globals to generate branch insns.  */
-rtx crx_compare_op0 = NULL_RTX;
-rtx crx_compare_op1 = NULL_RTX;
-
 /*****************************************************************************/
 /* TARGETM FUNCTION PROTOTYPES                                              */
 /*****************************************************************************/
@@ -136,8 +125,24 @@ rtx crx_compare_op1 = NULL_RTX;
 static bool crx_fixed_condition_code_regs (unsigned int *, unsigned int *);
 static rtx crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
                                 int incoming ATTRIBUTE_UNUSED);
-static bool crx_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED);
-static int crx_address_cost (rtx);
+static bool crx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED);
+static int crx_address_cost (rtx, bool);
+static bool crx_legitimate_address_p (enum machine_mode, rtx, bool);
+static bool crx_can_eliminate (const int, const int);
+static rtx crx_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+                            const_tree, bool);
+static void crx_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+                                     const_tree, bool);
+
+/*****************************************************************************/
+/* RTL VALIDITY                                                                     */
+/*****************************************************************************/
+
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P    crx_legitimate_address_p
+
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE           crx_can_eliminate
 
 /*****************************************************************************/
 /* STACK LAYOUT AND CALLING CONVENTIONS                                             */
@@ -152,6 +157,16 @@ static int crx_address_cost (rtx);
 #undef TARGET_RETURN_IN_MEMORY
 #define        TARGET_RETURN_IN_MEMORY         crx_return_in_memory
 
+/*****************************************************************************/
+/* PASSING FUNCTION ARGUMENTS                                               */
+/*****************************************************************************/
+
+#undef  TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG            crx_function_arg
+
+#undef  TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE    crx_function_arg_advance
+
 /*****************************************************************************/
 /* RELATIVE COSTS OF OPERATIONS                                                     */
 /*****************************************************************************/
@@ -166,12 +181,25 @@ static int crx_address_cost (rtx);
 #undef  TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE         crx_attribute_table
 
-const struct attribute_spec crx_attribute_table[] = {
+static const struct attribute_spec crx_attribute_table[] = {
   /* ISRs have special prologue and epilogue requirements. */
-  {"interrupt", 0, 0, false, true, true, NULL},
-  {NULL, 0, 0, false, false, false, NULL}
+  {"interrupt", 0, 0, false, true, true, NULL, false},
+  {NULL, 0, 0, false, false, false, NULL, false}
 };
 
+/* Option handling.  */
+
+#undef TARGET_OPTION_OPTIMIZATION_TABLE
+#define        TARGET_OPTION_OPTIMIZATION_TABLE        crx_option_optimization_table
+
+static const struct default_options crx_option_optimization_table[] =
+  {
+    /* Put each function in its own section so that PAGE-instruction
+       relaxation can do its best.  */
+    { OPT_LEVELS_1_PLUS, OPT_ffunction_sections, NULL, 1 },
+    { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
+    { OPT_LEVELS_NONE, 0, NULL, 0 }
+  };
 
 /* Initialize 'targetm' variable which contains pointers to functions and data
  * relating to the target machine.  */
@@ -205,7 +233,7 @@ crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
 /* Implements hook TARGET_RETURN_IN_MEMORY.  */
 
 static bool
-crx_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+crx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
 {
   if (TYPE_MODE (type) == BLKmode)
     {
@@ -272,7 +300,7 @@ crx_compute_save_regs (void)
             * for the sake of its sons.  */
            save_regs[regno] = 1;
 
-         else if (regs_ever_live[regno])
+         else if (df_regs_ever_live_p (regno))
            /* This reg is used - save it.  */
            save_regs[regno] = 1;
          else
@@ -282,7 +310,7 @@ crx_compute_save_regs (void)
       else
        {
          /* If this reg is used and not call-used (except RA), save it. */
-         if (regs_ever_live[regno]
+         if (df_regs_ever_live_p (regno)
              && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
            save_regs[regno] = 1;
          else
@@ -319,7 +347,15 @@ crx_compute_frame (void)
   local_vars_size += padding_locals;
 
   size_for_adjusting_sp = local_vars_size + (ACCUMULATE_OUTGOING_ARGS ?
-                                    current_function_outgoing_args_size : 0);
+                                    crtl->outgoing_args_size : 0);
+}
+
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+bool
+crx_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
 }
 
 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
@@ -335,13 +371,13 @@ crx_initial_elimination_offset (int from, int to)
 
   if ((from) == FRAME_POINTER_REGNUM && (to) == STACK_POINTER_REGNUM)
     return (ACCUMULATE_OUTGOING_ARGS ?
-           current_function_outgoing_args_size : 0);
+           crtl->outgoing_args_size : 0);
   else if ((from) == ARG_POINTER_REGNUM && (to) == FRAME_POINTER_REGNUM)
     return (sum_regs + local_vars_size);
   else if ((from) == ARG_POINTER_REGNUM && (to) == STACK_POINTER_REGNUM)
     return (sum_regs + local_vars_size +
            (ACCUMULATE_OUTGOING_ARGS ?
-            current_function_outgoing_args_size : 0));
+            crtl->outgoing_args_size : 0));
   else
     abort ();
 }
@@ -372,11 +408,11 @@ crx_regno_reg_class (int regno)
 /* Transfer between HILO_REGS and memory via secondary reloading. */
 
 enum reg_class
-crx_secondary_reload_class (enum reg_class class,
+crx_secondary_reload_class (enum reg_class rclass,
                            enum machine_mode mode ATTRIBUTE_UNUSED,
                            rtx x ATTRIBUTE_UNUSED)
 {
-  if (reg_classes_intersect_p (class, HILO_REGS)
+  if (reg_classes_intersect_p (rclass, HILO_REGS)
       && true_regnum (x) == -1)
     return GENERAL_REGS;
 
@@ -406,7 +442,7 @@ crx_hard_regno_mode_ok (int regno, enum machine_mode mode)
  * the number of registers needed else 0.  */
 
 static int
-enough_regs_for_param (CUMULATIVE_ARGS * cum, tree type,
+enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type,
                       enum machine_mode mode)
 {
   int type_size;
@@ -429,11 +465,11 @@ enough_regs_for_param (CUMULATIVE_ARGS * cum, tree type,
   return 0;
 }
 
-/* Implements the macro FUNCTION_ARG defined in crx.h.  */
+/* Implements TARGET_FUNCTION_ARG.  */
 
-rtx
-crx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode, tree type,
-             int named ATTRIBUTE_UNUSED)
+static rtx
+crx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+                 const_tree type, bool named ATTRIBUTE_UNUSED)
 {
   last_parm_in_reg = 0;
 
@@ -497,11 +533,11 @@ crx_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
     }
 }
 
-/* Implements the macro FUNCTION_ARG_ADVANCE defined in crx.h.  */
+/* Implements TARGET_FUNCTION_ARG_ADVANCE.  */
 
-void
+static void
 crx_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
-                     tree type, int named ATTRIBUTE_UNUSED)
+                         const_tree type, bool named ATTRIBUTE_UNUSED)
 {
   /* l holds the number of registers required */
   int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
@@ -542,41 +578,32 @@ crx_function_arg_regno_p (int n)
 /* ADDRESSING MODES */
 /* ---------------- */
 
-/* Implements the macro GO_IF_LEGITIMATE_ADDRESS defined in crx.h.
+/* Implements the hook for TARGET_LEGITIMATE_ADDRESS_P defined in crx.h.
  * The following addressing modes are supported on CRX:
  *
  * Relocations         --> const | symbol_ref | label_ref
- * Absolute address    --> 32 bit absolute
- * Post increment      --> reg + 12 bit disp.
- * Post modify         --> reg + 12 bit disp.
- * Register relative   --> reg | 32 bit disp. + reg | 4 bit + reg
- * Scaled index                --> reg + reg | 22 bit disp. + reg + reg |
- *                         22 disp. + reg + reg + (2 | 4 | 8) */
-
-static int crx_addr_reg_p (rtx addr_reg)
+ * Absolute address    --> 32-bit absolute
+ * Post increment      --> reg + 12-bit disp.
+ * Post modify         --> reg + 12-bit disp.
+ * Register relative   --> reg | 32-bit disp. + reg | 4 bit + reg
+ * Scaled index                --> reg + reg | 22-bit disp. + reg + reg |
+ *                         22-disp. + reg + reg + (2 | 4 | 8) */
+
+static rtx
+crx_addr_reg (rtx addr_reg)
 {
-  rtx reg;
+  if (GET_MODE (addr_reg) != Pmode)
+    return NULL_RTX;
 
   if (REG_P (addr_reg))
-    {
-      reg = addr_reg;
-    }
-  else if ((GET_CODE (addr_reg) == SUBREG
+    return addr_reg;
+  else if (GET_CODE (addr_reg) == SUBREG
           && REG_P (SUBREG_REG (addr_reg))
-          && GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
-          <= UNITS_PER_WORD))
-    {
-      reg = SUBREG_REG (addr_reg);
-    }
+          && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
+              <= UNITS_PER_WORD))
+    return SUBREG_REG (addr_reg);
   else
-    return FALSE;
-
-  if (GET_MODE (addr_reg) != Pmode)
-    {
-      return FALSE;
-    }
-
-  return TRUE;
+    return NULL_RTX;
 }
 
 enum crx_addrtype
@@ -715,8 +742,18 @@ crx_decompose_address (rtx addr, struct crx_address *out)
       return CRX_INVALID;
     }
 
-  if (base && !crx_addr_reg_p (base)) return CRX_INVALID;
-  if (index && !crx_addr_reg_p (index)) return CRX_INVALID;
+  if (base)
+    {
+      base = crx_addr_reg (base);
+      if (!base)
+       return CRX_INVALID;
+    }
+  if (index)
+    {
+      index = crx_addr_reg (index);
+      if (!index)
+       return CRX_INVALID;
+    }
   
   out->base = base;
   out->index = index;
@@ -727,9 +764,9 @@ crx_decompose_address (rtx addr, struct crx_address *out)
   return retval;
 }
 
-int
+bool
 crx_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
-                         rtx addr, int strict)
+                         rtx addr, bool strict)
 {
   enum crx_addrtype addrtype;
   struct crx_address address;
@@ -801,7 +838,7 @@ crx_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
 /* Return cost of the memory address x. */
 
 static int
-crx_address_cost (rtx addr)
+crx_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
 {
   enum crx_addrtype addrtype;
   struct crx_address address;
@@ -840,22 +877,22 @@ crx_address_cost (rtx addr)
 }
 
 /* Return the cost of moving data of mode MODE between a register of class
- * CLASS and memory; IN is zero if the value is to be written to memory,
+ * RCLASS and memory; IN is zero if the value is to be written to memory,
  * nonzero if it is to be read in. This cost is relative to those in
  * REGISTER_MOVE_COST.  */
 
 int
 crx_memory_move_cost (enum machine_mode mode,
-                 enum reg_class class ATTRIBUTE_UNUSED,
+                 enum reg_class rclass ATTRIBUTE_UNUSED,
                  int in ATTRIBUTE_UNUSED)
 {
   /* One LD or ST takes twice the time of a simple reg-reg move */
-  if (reg_classes_intersect_p (class, GENERAL_REGS))
+  if (reg_classes_intersect_p (rclass, GENERAL_REGS))
     {
       /* printf ("GENERAL_REGS LD/ST = %d\n", 4 * HARD_REGNO_NREGS (0, mode));*/
       return 4 * HARD_REGNO_NREGS (0, mode);
     }  
-  else if (reg_classes_intersect_p (class, HILO_REGS))
+  else if (reg_classes_intersect_p (rclass, HILO_REGS))
     {
       /* HILO to memory and vice versa */
       /* printf ("HILO_REGS %s = %d\n", in ? "LD" : "ST",
@@ -1218,43 +1255,6 @@ crx_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp)
   return 1;
 }
 
-rtx
-crx_expand_compare (enum rtx_code code, enum machine_mode mode)
-{
-  rtx op0, op1, cc_reg, ret;
-
-  op0 = crx_compare_op0;
-  op1 = crx_compare_op1;
-
-  /* Emit the compare that writes into CC_REGNUM) */
-  cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
-  ret = gen_rtx_COMPARE (CCmode, op0, op1);
-  emit_insn (gen_rtx_SET (VOIDmode, cc_reg, ret));
-  /* debug_rtx (get_last_insn ()); */
-
-  /* Return the rtx for using the result in CC_REGNUM */
-  return gen_rtx_fmt_ee (code, mode, cc_reg, const0_rtx);
-}
-
-void
-crx_expand_branch (enum rtx_code code, rtx label)
-{
-  rtx tmp = crx_expand_compare (code, VOIDmode);
-  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
-                             gen_rtx_LABEL_REF (VOIDmode, label),
-                             pc_rtx);
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
-  /* debug_rtx (get_last_insn ()); */
-}
-
-void
-crx_expand_scond (enum rtx_code code, rtx dest)
-{
-  rtx tmp = crx_expand_compare (code, GET_MODE (dest));
-  emit_move_insn (dest, tmp);
-  /* debug_rtx (get_last_insn ()); */
-}
-
 static void
 mpushpop_str (char *stringbuffer, const char *mnemonic, char *mask)
 {
@@ -1439,17 +1439,12 @@ crx_expand_prologue (void)
 void
 crx_expand_epilogue (void)
 {
-  rtx return_reg;
-
   /* Nonzero if we need to return and pop only RA. This will generate a
    * different insn. This differentiate is for the peepholes for call as last
    * statement in function. */
   int only_popret_RA = (save_regs[RETURN_ADDRESS_REGNUM]
                        && (sum_regs == UNITS_PER_WORD));
 
-  /* Return register.  */
-  return_reg = gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM);
-
   if (frame_pointer_needed)
     /* Restore the stack pointer with the frame pointers value */
     emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
@@ -1469,4 +1464,3 @@ crx_expand_epilogue (void)
   else
     emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));
 }
-