summaryrefslogtreecommitdiff
path: root/gcc/config/m32r/m32r.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/m32r/m32r.c')
-rw-r--r--gcc/config/m32r/m32r.c109
1 files changed, 108 insertions, 1 deletions
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 410882766c7..444f16efbbe 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -1,6 +1,6 @@
/* Subroutines used for code generation on the Renesas M32R cpu.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -66,6 +66,7 @@ static void m32r_option_override (void);
static void init_reg_tables (void);
static void block_move_call (rtx, rtx, rtx);
static int m32r_is_insn (rtx);
+static bool m32r_legitimate_address_p (enum machine_mode, rtx, bool);
static rtx m32r_legitimize_address (rtx, rtx, enum machine_mode);
static bool m32r_mode_dependent_address_p (const_rtx);
static tree m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
@@ -124,6 +125,8 @@ static const struct default_options m32r_option_optimization_table[] =
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE m32r_attribute_table
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P m32r_legitimate_address_p
#undef TARGET_LEGITIMIZE_ADDRESS
#define TARGET_LEGITIMIZE_ADDRESS m32r_legitimize_address
#undef TARGET_MODE_DEPENDENT_ADDRESS_P
@@ -210,6 +213,9 @@ static const struct default_options m32r_option_optimization_table[] =
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT m32r_trampoline_init
+#undef TARGET_EXCEPT_UNWIND_INFO
+#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Implement TARGET_HANDLE_OPTION. */
@@ -2841,6 +2847,107 @@ m32r_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
GEN_INT (3), SImode);
}
+/* True if X is a reg that can be used as a base reg. */
+
+static bool
+m32r_rtx_ok_for_base_p (const_rtx x, bool strict)
+{
+ if (! REG_P (x))
+ return false;
+
+ if (strict)
+ {
+ if (GPR_P (REGNO (x)))
+ return true;
+ }
+ else
+ {
+ if (GPR_P (REGNO (x))
+ || REGNO (x) == ARG_POINTER_REGNUM
+ || ! HARD_REGISTER_P (x))
+ return true;
+ }
+
+ return false;
+}
+
+static inline bool
+m32r_rtx_ok_for_offset_p (const_rtx x)
+{
+ return (CONST_INT_P (x) && INT16_P (INTVAL (x)));
+}
+
+static inline bool
+m32r_legitimate_offset_addres_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+ const_rtx x, bool strict)
+{
+ if (GET_CODE (x) == PLUS
+ && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict)
+ && m32r_rtx_ok_for_offset_p (XEXP (x, 1)))
+ return true;
+
+ return false;
+}
+
+/* For LO_SUM addresses, do not allow them if the MODE is > 1 word,
+ since more than one instruction will be required. */
+
+static inline bool
+m32r_legitimate_lo_sum_addres_p (enum machine_mode mode, const_rtx x,
+ bool strict)
+{
+ if (GET_CODE (x) == LO_SUM
+ && (mode != BLKmode && GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
+ && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict)
+ && CONSTANT_P (XEXP (x, 1)))
+ return true;
+
+ return false;
+}
+
+/* Is this a load and increment operation. */
+
+static inline bool
+m32r_load_postinc_p (enum machine_mode mode, const_rtx x, bool strict)
+{
+ if ((mode == SImode || mode == SFmode)
+ && GET_CODE (x) == POST_INC
+ && REG_P (XEXP (x, 0))
+ && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict))
+ return true;
+
+ return false;
+}
+
+/* Is this an increment/decrement and store operation. */
+
+static inline bool
+m32r_store_preinc_predec_p (enum machine_mode mode, const_rtx x, bool strict)
+{
+ if ((mode == SImode || mode == SFmode)
+ && (GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
+ && REG_P (XEXP (x, 0)) \
+ && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict))
+ return true;
+
+ return false;
+}
+
+/* Implement TARGET_LEGITIMATE_ADDRESS_P. */
+
+static bool
+m32r_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+{
+ if (m32r_rtx_ok_for_base_p (x, strict)
+ || m32r_legitimate_offset_addres_p (mode, x, strict)
+ || m32r_legitimate_lo_sum_addres_p (mode, x, strict)
+ || m32r_load_postinc_p (mode, x, strict)
+ || m32r_store_preinc_predec_p (mode, x, strict))
+ return true;
+
+ return false;
+}
+
static void
m32r_conditional_register_usage (void)
{