summaryrefslogtreecommitdiff
path: root/gcc/config/cris/cris.c
diff options
context:
space:
mode:
authoraesok <aesok@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-29 09:08:13 +0000
committeraesok <aesok@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-29 09:08:13 +0000
commit5b96044e26742da745c5a4f6f09d5d6a1a207449 (patch)
tree84a1d7603e4cb9f8c57e6c7606db56d7c07ed46b /gcc/config/cris/cris.c
parent25a28b4458b79989e2661d885d066a272ca7655b (diff)
downloadgcc-5b96044e26742da745c5a4f6f09d5d6a1a207449.tar.gz
* config/cris/cris.c (reg_ok_for_base_p, reg_ok_for_index_p,
cris_constant_index_p, cris_base_p, cris_index_p, cris_base_or_autoincr_p, cris_bdap_index_p, cris_biap_index_p, cris_legitimate_address_p): New functions. (TARGET_LEGITIMATE_ADDRESS_P): Define. (cris_pic_symbol_type, cris_valid_pic_const): Change arguments type from rtx to const_rtx. (cris_print_operand_address, cris_address_cost, cris_side_effect_mode_ok): Use cris_constant_index_p, cris_base_p, cris_base_or_autoincr_p, cris_biap_index_p and cris_bdap_index_p. * config/cris/cris.h (CONSTANT_INDEX_P, BASE_P, BASE_OR_AUTOINCR_P, BDAP_INDEX_P, BIAP_INDEX_P, GO_IF_LEGITIMATE_ADDRESS, REG_OK_FOR_BASE_P, REG_OK_FOR_INDEX_P): Remove. (EXTRA_CONSTRAINT_Q, EXTRA_CONSTRAINT_R, EXTRA_CONSTRAINT_T): Use cris_constant_index_p, cris_base_p, cris_base_or_autoincr_p, cris_biap_index_p and cris_bdap_index_p. * config/cris/cris.md (moversideqi movemsideqi peephole2): Use cris_base_p. * config/cris/cris-protos.h (cris_constant_index_p, cris_base_p, cris_base_or_autoincr_p, cris_bdap_index_p, cris_biap_index_p): New prototype. (cris_pic_symbol_type, cris_valid_pic_const): Update prototype. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180651 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/cris/cris.c')
-rw-r--r--gcc/config/cris/cris.c175
1 files changed, 158 insertions, 17 deletions
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 35ecaa8e2fd..4a08ae03aee 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -125,6 +125,8 @@ static void cris_init_libfuncs (void);
static reg_class_t cris_preferred_reload_class (rtx, reg_class_t);
+static bool cris_legitimate_address_p (enum machine_mode, rtx, bool);
+
static int cris_register_move_cost (enum machine_mode, reg_class_t, reg_class_t);
static int cris_memory_move_cost (enum machine_mode, reg_class_t, bool);
static bool cris_rtx_costs (rtx, int, int, int, int *, bool);
@@ -200,6 +202,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS cris_init_libfuncs
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P cris_legitimate_address_p
+
#undef TARGET_PREFERRED_RELOAD_CLASS
#define TARGET_PREFERRED_RELOAD_CLASS cris_preferred_reload_class
@@ -1122,7 +1127,7 @@ cris_print_operand_address (FILE *file, rtx x)
if (CONSTANT_ADDRESS_P (x))
cris_output_addr_const (file, x);
- else if (BASE_OR_AUTOINCR_P (x))
+ else if (cris_base_or_autoincr_p (x, true))
cris_print_base (x, file);
else if (GET_CODE (x) == PLUS)
{
@@ -1130,12 +1135,12 @@ cris_print_operand_address (FILE *file, rtx x)
x1 = XEXP (x, 0);
x2 = XEXP (x, 1);
- if (BASE_P (x1))
+ if (cris_base_p (x1, true))
{
cris_print_base (x1, file);
cris_print_index (x2, file);
}
- else if (BASE_P (x2))
+ else if (cris_base_p (x2, true))
{
cris_print_base (x2, file);
cris_print_index (x1, file);
@@ -1272,6 +1277,136 @@ cris_initial_elimination_offset (int fromreg, int toreg)
gcc_unreachable ();
}
+/* Nonzero if X is a hard reg that can be used as an index. */
+static inline bool
+reg_ok_for_base_p (const_rtx x, bool strict)
+{
+ return ((! strict && ! HARD_REGISTER_P (x))
+ || REGNO_OK_FOR_BASE_P (REGNO (x)));
+}
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+static inline bool
+reg_ok_for_index_p (const_rtx x, bool strict)
+{
+ return reg_ok_for_base_p (x, strict);
+}
+
+/* No symbol can be used as an index (or more correct, as a base) together
+ with a register with PIC; the PIC register must be there. */
+
+bool
+cris_constant_index_p (const_rtx x)
+{
+ return (CONSTANT_P (x) && (!flag_pic || cris_valid_pic_const (x, true)));
+}
+
+/* True if X is a valid base register. */
+
+bool
+cris_base_p (const_rtx x, bool strict)
+{
+ return (REG_P (x) && reg_ok_for_base_p (x, strict));
+}
+
+/* True if X is a valid index register. */
+
+static inline bool
+cris_index_p (const_rtx x, bool strict)
+{
+ return (REG_P (x) && reg_ok_for_index_p (x, strict));
+}
+
+/* True if X is a valid base register with or without autoincrement. */
+
+bool
+cris_base_or_autoincr_p (const_rtx x, bool strict)
+{
+ return (cris_base_p (x, strict)
+ || (GET_CODE (x) == POST_INC
+ && cris_base_p (XEXP (x, 0), strict)
+ && REGNO (XEXP (x, 0)) != CRIS_ACR_REGNUM));
+}
+
+/* True if X is a valid (register) index for BDAP, i.e. [Rs].S or [Rs+].S. */
+
+bool
+cris_bdap_index_p (const_rtx x, bool strict)
+{
+ return ((MEM_P (x)
+ && GET_MODE (x) == SImode
+ && cris_base_or_autoincr_p (XEXP (x, 0), strict))
+ || (GET_CODE (x) == SIGN_EXTEND
+ && MEM_P (XEXP (x, 0))
+ && (GET_MODE (XEXP (x, 0)) == HImode
+ || GET_MODE (XEXP (x, 0)) == QImode)
+ && cris_base_or_autoincr_p (XEXP (XEXP (x, 0), 0), strict)));
+}
+
+/* True if X is a valid (register) index for BIAP, i.e. Rd.m. */
+
+bool
+cris_biap_index_p (const_rtx x, bool strict)
+{
+ return (cris_index_p (x, strict)
+ || (GET_CODE (x) == MULT
+ && cris_index_p (XEXP (x, 0), strict)
+ && cris_scale_int_operand (XEXP (x, 1), VOIDmode)));
+}
+
+/* Worker function for TARGET_LEGITIMATE_ADDRESS_P.
+
+ A PIC operand looks like a normal symbol here. At output we dress it
+ in "[rPIC+symbol:GOT]" (global symbol) or "rPIC+symbol:GOTOFF" (local
+ symbol) so we exclude all addressing modes where we can't replace a
+ plain "symbol" with that. A global PIC symbol does not fit anywhere
+ here (but is thankfully a general_operand in itself). A local PIC
+ symbol is valid for the plain "symbol + offset" case. */
+
+static bool
+cris_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+{
+ const_rtx x1, x2;
+
+ if (cris_base_or_autoincr_p (x, strict))
+ return true;
+ else if (TARGET_V32)
+ /* Nothing else is valid then. */
+ return false;
+ else if (cris_constant_index_p (x))
+ return true;
+ /* Indexed? */
+ else if (GET_CODE (x) == PLUS)
+ {
+ x1 = XEXP (x, 0);
+ x2 = XEXP (x, 1);
+ /* BDAP o, Rd. */
+ if ((cris_base_p (x1, strict) && cris_constant_index_p (x2))
+ || (cris_base_p (x2, strict) && cris_constant_index_p (x1))
+ /* BDAP Rs[+], Rd. */
+ || (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+ && ((cris_base_p (x1, strict)
+ && cris_bdap_index_p (x2, strict))
+ || (cris_base_p (x2, strict)
+ && cris_bdap_index_p (x1, strict))
+ /* BIAP.m Rs, Rd */
+ || (cris_base_p (x1, strict)
+ && cris_biap_index_p (x2, strict))
+ || (cris_base_p (x2, strict)
+ && cris_biap_index_p (x1, strict)))))
+ return true;
+ }
+ else if (MEM_P (x))
+ {
+ /* DIP (Rs). Reject [[reg+]] and [[reg]] for DImode (long long). */
+ if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+ && cris_base_or_autoincr_p (XEXP (x, 0), strict))
+ return true;
+ }
+
+ return false;
+}
+
/* Worker function for LEGITIMIZE_RELOAD_ADDRESS. */
bool
@@ -1860,7 +1995,7 @@ cris_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
FIXME: this case is a stop-gap for 4.3 and 4.4, this whole
function should be rewritten. */
- if (outer_code == PLUS && BIAP_INDEX_P (x))
+ if (outer_code == PLUS && cris_biap_index_p (x, false))
{
*total = 0;
return true;
@@ -1942,7 +2077,7 @@ cris_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
loop there, without apparent reason. */
/* The cheapest addressing modes get 0, since nothing extra is needed. */
- if (BASE_OR_AUTOINCR_P (x))
+ if (cris_base_or_autoincr_p (x, false))
return 0;
/* An indirect mem must be a DIP. This means two bytes extra for code,
@@ -1972,7 +2107,7 @@ cris_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
/* A BIAP is 2 extra bytes for the prefix insn, nothing more. We
recognize the typical MULT which is always in tem1 because of
insn canonicalization. */
- if ((GET_CODE (tem1) == MULT && BIAP_INDEX_P (tem1))
+ if ((GET_CODE (tem1) == MULT && cris_biap_index_p (tem1, false))
|| REG_P (tem2))
return 2 / 2;
@@ -2030,12 +2165,12 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
/* The operands may be swapped. Canonicalize them in reg_rtx and
val_rtx, where reg_rtx always is a reg (for this constraint to
match). */
- if (! BASE_P (reg_rtx))
+ if (! cris_base_p (reg_rtx, reload_in_progress || reload_completed))
reg_rtx = val_rtx, val_rtx = ops[rreg];
/* Don't forget to check that reg_rtx really is a reg. If it isn't,
we have no business. */
- if (! BASE_P (reg_rtx))
+ if (! cris_base_p (reg_rtx, reload_in_progress || reload_completed))
return 0;
/* Don't do this when -mno-split. */
@@ -2060,8 +2195,9 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
/* Check if the lvalue register is the same as the "other
operand". If so, the result is undefined and we shouldn't do
this. FIXME: Check again. */
- if ((BASE_P (ops[lreg])
- && BASE_P (ops[other_op])
+ if ((cris_base_p (ops[lreg], reload_in_progress || reload_completed)
+ && cris_base_p (ops[other_op],
+ reload_in_progress || reload_completed)
&& REGNO (ops[lreg]) == REGNO (ops[other_op]))
|| rtx_equal_p (ops[other_op], ops[lreg]))
return 0;
@@ -2074,7 +2210,7 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
return 0;
if (code == PLUS
- && ! BASE_P (val_rtx))
+ && ! cris_base_p (val_rtx, reload_in_progress || reload_completed))
{
/* Do not allow rx = rx + n if a normal add or sub with same size
@@ -2088,19 +2224,24 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
if (CONSTANT_P (val_rtx))
return 1;
- if (MEM_P (val_rtx) && BASE_OR_AUTOINCR_P (XEXP (val_rtx, 0)))
+ if (MEM_P (val_rtx)
+ && cris_base_or_autoincr_p (XEXP (val_rtx, 0),
+ reload_in_progress || reload_completed))
return 1;
if (GET_CODE (val_rtx) == SIGN_EXTEND
&& MEM_P (XEXP (val_rtx, 0))
- && BASE_OR_AUTOINCR_P (XEXP (XEXP (val_rtx, 0), 0)))
+ && cris_base_or_autoincr_p (XEXP (XEXP (val_rtx, 0), 0),
+ reload_in_progress || reload_completed))
return 1;
/* If we got here, it's not a valid addressing mode. */
return 0;
}
else if (code == MULT
- || (code == PLUS && BASE_P (val_rtx)))
+ || (code == PLUS
+ && cris_base_p (val_rtx,
+ reload_in_progress || reload_completed)))
{
/* Do not allow rx = rx + ry.S, since it doesn't give better code. */
if (rtx_equal_p (ops[lreg], reg_rtx)
@@ -2112,7 +2253,7 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
return 0;
/* Only allow r + ... */
- if (! BASE_P (reg_rtx))
+ if (! cris_base_p (reg_rtx, reload_in_progress || reload_completed))
return 0;
/* If we got here, all seems ok.
@@ -2202,7 +2343,7 @@ cris_target_asm_named_section (const char *name, unsigned int flags,
elsewhere. */
bool
-cris_valid_pic_const (rtx x, bool any_operand)
+cris_valid_pic_const (const_rtx x, bool any_operand)
{
gcc_assert (flag_pic);
@@ -2252,7 +2393,7 @@ cris_valid_pic_const (rtx x, bool any_operand)
given the original (non-PIC) representation. */
enum cris_pic_symbol_type
-cris_pic_symbol_type_of (rtx x)
+cris_pic_symbol_type_of (const_rtx x)
{
switch (GET_CODE (x))
{