diff options
Diffstat (limited to 'gcc/config/h8300/h8300.c')
-rw-r--r-- | gcc/config/h8300/h8300.c | 73 |
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; |