/* 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
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 */
#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"
#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"
* 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 */
/*****************************************************************************/
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 */
#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 */
/*****************************************************************************/
#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. */
/* 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)
{
* 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
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
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. */
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 ();
}
/* 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;
* 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;
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;
}
}
-/* 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;
/* 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
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;
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;
/* 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;
}
/* 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",
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)
{
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);
else
emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));
}
-