aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/h8300/h8300.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/h8300/h8300.c')
-rw-r--r--gcc/config/h8300/h8300.c73
1 files changed, 62 insertions, 11 deletions
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index f75a4961d73..02b3ff6094a 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -1,6 +1,6 @@
/* Subroutines for insn-output.c for Renesas H8/300.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com),
Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
@@ -1226,6 +1226,11 @@ h8300_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
*total = 20;
return true;
+ case COMPARE:
+ if (XEXP (x, 1) == const0_rtx)
+ *total = 0;
+ return false;
+
case AND:
if (!h8300_dst_operand (XEXP (x, 0), VOIDmode)
|| !h8300_src_operand (XEXP (x, 1), VOIDmode))
@@ -1820,6 +1825,20 @@ h8300_expand_movsi (rtx operands[])
return 0;
}
+/* Given FROM and TO register numbers, say whether this elimination is allowed.
+ Frame pointer elimination is automatically handled.
+
+ For the h8300, if frame pointer elimination is being done, we would like to
+ convert ap and rp into sp, not fp.
+
+ All other eliminations are valid. */
+
+static bool
+h8300_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+ return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
+}
+
/* Function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET).
Define the offset between two registers, one to be eliminated, and
the other its replacement, at the start of a routine. */
@@ -3503,16 +3522,42 @@ compute_logical_op_cc (enum machine_mode mode, rtx *operands)
/* Expand a conditional branch. */
void
-h8300_expand_branch (enum rtx_code code, rtx label)
+h8300_expand_branch (rtx operands[])
{
+ enum rtx_code code = GET_CODE (operands[0]);
+ rtx op0 = operands[1];
+ rtx op1 = operands[2];
+ rtx label = operands[3];
rtx tmp;
+ tmp = gen_rtx_COMPARE (VOIDmode, op0, op1);
+ emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp));
+
tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
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));
}
+
+
+/* Expand a conditional store. */
+
+void
+h8300_expand_store (rtx operands[])
+{
+ rtx dest = operands[0];
+ enum rtx_code code = GET_CODE (operands[1]);
+ rtx op0 = operands[2];
+ rtx op1 = operands[3];
+ rtx tmp;
+
+ tmp = gen_rtx_COMPARE (VOIDmode, op0, op1);
+ emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp));
+
+ tmp = gen_rtx_fmt_ee (code, GET_MODE (dest), cc0_rtx, const0_rtx);
+ emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
+}
/* Shifts.
@@ -5232,7 +5277,7 @@ h8300_insert_attributes (tree node, tree *attributes)
tiny_data: This variable lives in the tiny data area and can be
referenced with 16-bit absolute memory references. */
-const struct attribute_spec h8300_attribute_table[] =
+static const struct attribute_spec h8300_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
{ "interrupt_handler", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
@@ -5256,8 +5301,8 @@ h8300_handle_fndecl_attribute (tree *node, tree name,
{
if (TREE_CODE (*node) != FUNCTION_DECL)
{
- warning (OPT_Wattributes, "%qs attribute only applies to functions",
- IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute only applies to functions",
+ name);
*no_add_attrs = true;
}
@@ -5280,8 +5325,8 @@ h8300_handle_eightbit_data_attribute (tree *node, tree name,
}
else
{
- warning (OPT_Wattributes, "%qs attribute ignored",
- IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored",
+ name);
*no_add_attrs = true;
}
@@ -5304,8 +5349,8 @@ h8300_handle_tiny_data_attribute (tree *node, tree name,
}
else
{
- warning (OPT_Wattributes, "%qs attribute ignored",
- IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored",
+ name);
*no_add_attrs = true;
}
@@ -5655,8 +5700,8 @@ h8300_rtx_ok_for_base_p (rtx x, int strict)
legitimate address has the form REG, REG+CONSTANT_ADDRESS or
CONSTANT_ADDRESS. */
-int
-h8300_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
+static bool
+h8300_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
{
/* The register indirect addresses like @er0 is always valid. */
if (h8300_rtx_ok_for_base_p (x, strict))
@@ -5764,7 +5809,13 @@ h8300_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
#undef TARGET_HARD_REGNO_SCRATCH_OK
#define TARGET_HARD_REGNO_SCRATCH_OK h8300_hard_regno_scratch_ok
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P h8300_legitimate_address_p
+
#undef TARGET_DEFAULT_TARGET_FLAGS
#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE h8300_can_eliminate
+
struct gcc_target targetm = TARGET_INITIALIZER;