/* Output routines for GCC for CRX.
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
This file is part of GCC.
#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 */
/*****************************************************************************/
int incoming ATTRIBUTE_UNUSED);
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. */
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. */
int
* 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
* 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)
+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 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)));
}
-