cris.c (reg_ok_for_base_p, [...]): New functions.
* 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. From-SVN: r180651
This commit is contained in:
parent
3bc5016331
commit
a08160c31c
@ -1,3 +1,29 @@
|
||||
2011-10-29 Anatoly Sokolov <aesok@post.ru>
|
||||
|
||||
* 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.
|
||||
|
||||
2011-10-21 Andi Kleen <ak@linux.intel.com>
|
||||
|
||||
* ggc-page (PAGE_ALIGN): Add.
|
||||
|
@ -33,8 +33,13 @@ extern bool cris_cc0_user_requires_cmp (rtx);
|
||||
extern rtx cris_return_addr_rtx (int, rtx);
|
||||
extern rtx cris_split_movdx (rtx *);
|
||||
extern int cris_legitimate_pic_operand (rtx);
|
||||
extern enum cris_pic_symbol_type cris_pic_symbol_type_of (rtx);
|
||||
extern bool cris_valid_pic_const (rtx, bool);
|
||||
extern enum cris_pic_symbol_type cris_pic_symbol_type_of (const_rtx);
|
||||
extern bool cris_valid_pic_const (const_rtx, bool);
|
||||
extern bool cris_constant_index_p (const_rtx);
|
||||
extern bool cris_base_p (const_rtx, bool);
|
||||
extern bool cris_base_or_autoincr_p (const_rtx, bool);
|
||||
extern bool cris_bdap_index_p (const_rtx, bool);
|
||||
extern bool cris_biap_index_p (const_rtx, bool);
|
||||
extern bool cris_store_multiple_op_p (rtx);
|
||||
extern bool cris_movem_load_rest_p (rtx, int);
|
||||
extern void cris_asm_output_symbol_ref (FILE *, rtx);
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -676,17 +676,18 @@ enum reg_class
|
||||
/* Just an indirect register (happens to also be \
|
||||
"all" slottable memory addressing modes not \
|
||||
covered by other constraints, i.e. '>'). */ \
|
||||
MEM_P (X) && BASE_P (XEXP (X, 0)) \
|
||||
MEM_P (X) \
|
||||
&& cris_base_p (XEXP (X, 0), reload_in_progress || reload_completed) \
|
||||
)
|
||||
|
||||
#define EXTRA_CONSTRAINT_R(X) \
|
||||
( \
|
||||
/* An operand to BDAP or BIAP: \
|
||||
A BIAP; r.S? */ \
|
||||
BIAP_INDEX_P (X) \
|
||||
cris_biap_index_p (X, reload_in_progress || reload_completed) \
|
||||
/* A [reg] or (int) [reg], maybe with post-increment. */ \
|
||||
|| BDAP_INDEX_P (X) \
|
||||
|| CONSTANT_INDEX_P (X) \
|
||||
|| cris_bdap_index_p (X, reload_in_progress || reload_completed) \
|
||||
|| cris_constant_index_p (X) \
|
||||
)
|
||||
|
||||
#define EXTRA_CONSTRAINT_T(X) \
|
||||
@ -695,25 +696,33 @@ enum reg_class
|
||||
MEM_P (X) \
|
||||
&& ((MEM_P (XEXP (X, 0)) \
|
||||
/* Double indirect: [[reg]] or [[reg+]]? */ \
|
||||
&& (BASE_OR_AUTOINCR_P (XEXP (XEXP (X, 0), 0)))) \
|
||||
&& (cris_base_or_autoincr_p (XEXP (XEXP (X, 0), 0), \
|
||||
reload_in_progress || reload_completed))) \
|
||||
/* Just an explicit indirect reference: [const]? */ \
|
||||
|| CONSTANT_P (XEXP (X, 0)) \
|
||||
/* Something that is indexed; [...+...]? */ \
|
||||
|| (GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
/* A BDAP constant: [reg+(8|16|32)bit offset]? */ \
|
||||
&& ((BASE_P (XEXP (XEXP (X, 0), 0)) \
|
||||
&& CONSTANT_INDEX_P (XEXP (XEXP (X, 0), 1))) \
|
||||
&& ((cris_base_p (XEXP (XEXP (X, 0), 0), \
|
||||
reload_in_progress || reload_completed) \
|
||||
&& cris_constant_index_p (XEXP (XEXP (X, 0), 1))) \
|
||||
/* A BDAP register: [reg+[reg(+)].S]? */ \
|
||||
|| (BASE_P (XEXP (XEXP (X, 0), 0)) \
|
||||
&& BDAP_INDEX_P(XEXP(XEXP(X, 0), 1))) \
|
||||
|| (cris_base_p (XEXP (XEXP (X, 0), 0), \
|
||||
reload_in_progress || reload_completed) \
|
||||
&& cris_bdap_index_p (XEXP(XEXP(X, 0), 1), \
|
||||
reload_in_progress || reload_completed)) \
|
||||
/* Same, but with swapped arguments (no canonical \
|
||||
ordering between e.g. REG and MEM as of LAST_UPDATED \
|
||||
"Thu May 12 03:59:11 UTC 2005"). */ \
|
||||
|| (BASE_P (XEXP (XEXP (X, 0), 1)) \
|
||||
&& BDAP_INDEX_P (XEXP (XEXP (X, 0), 0))) \
|
||||
|| (cris_base_p (XEXP (XEXP (X, 0), 1), \
|
||||
reload_in_progress | reload_completed) \
|
||||
&& cris_bdap_index_p (XEXP (XEXP (X, 0), 0), \
|
||||
reload_in_progress || reload_completed)) \
|
||||
/* A BIAP: [reg+reg.S] (MULT comes first). */ \
|
||||
|| (BASE_P (XEXP (XEXP (X, 0), 1)) \
|
||||
&& BIAP_INDEX_P (XEXP (XEXP (X, 0), 0)))))) \
|
||||
|| (cris_base_p (XEXP (XEXP (X, 0), 1), \
|
||||
reload_in_progress || reload_completed) \
|
||||
&& cris_biap_index_p (XEXP (XEXP (X, 0), 0), \
|
||||
reload_in_progress || reload_completed))))) \
|
||||
)
|
||||
|
||||
/* PIC-constructs for symbols. */
|
||||
@ -888,118 +897,6 @@ struct cum_args {int regs;};
|
||||
among all CRIS variants. */
|
||||
#define MAX_REGS_PER_ADDRESS 2
|
||||
|
||||
/* There are helper macros defined here which are used only in
|
||||
GO_IF_LEGITIMATE_ADDRESS.
|
||||
|
||||
Note that you *have to* reject invalid addressing modes for mode
|
||||
MODE, even if it is legal for normal addressing modes. You cannot
|
||||
rely on the constraints to do this work. They can only be used to
|
||||
doublecheck your intentions. One example is that you HAVE TO reject
|
||||
(mem:DI (plus:SI (reg:SI x) (reg:SI y))) because for some reason
|
||||
this cannot be reloaded. (Which of course you can argue that gcc
|
||||
should have done.) FIXME: Strange. Check. */
|
||||
|
||||
/* 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. */
|
||||
#define CONSTANT_INDEX_P(X) \
|
||||
(CONSTANT_P (X) && (!flag_pic || cris_valid_pic_const (X, true)))
|
||||
|
||||
/* True if X is a valid base register. */
|
||||
#define BASE_P(X) \
|
||||
(REG_P (X) && REG_OK_FOR_BASE_P (X))
|
||||
|
||||
/* True if X is a valid base register with or without autoincrement. */
|
||||
#define BASE_OR_AUTOINCR_P(X) \
|
||||
(BASE_P (X) \
|
||||
|| (GET_CODE (X) == POST_INC \
|
||||
&& BASE_P (XEXP (X, 0)) \
|
||||
&& REGNO (XEXP (X, 0)) != CRIS_ACR_REGNUM))
|
||||
|
||||
/* True if X is a valid (register) index for BDAP, i.e. [Rs].S or [Rs+].S. */
|
||||
#define BDAP_INDEX_P(X) \
|
||||
((MEM_P (X) && GET_MODE (X) == SImode \
|
||||
&& BASE_OR_AUTOINCR_P (XEXP (X, 0))) \
|
||||
|| (GET_CODE (X) == SIGN_EXTEND \
|
||||
&& MEM_P (XEXP (X, 0)) \
|
||||
&& (GET_MODE (XEXP (X, 0)) == HImode \
|
||||
|| GET_MODE (XEXP (X, 0)) == QImode) \
|
||||
&& BASE_OR_AUTOINCR_P (XEXP (XEXP (X, 0), 0))))
|
||||
|
||||
/* True if X is a valid (register) index for BIAP, i.e. Rd.m. */
|
||||
#define BIAP_INDEX_P(X) \
|
||||
((BASE_P (X) && REG_OK_FOR_INDEX_P (X)) \
|
||||
|| (GET_CODE (X) == MULT \
|
||||
&& BASE_P (XEXP (X, 0)) \
|
||||
&& REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
|
||||
&& CONST_INT_P (XEXP (X, 1)) \
|
||||
&& (INTVAL (XEXP (X, 1)) == 2 \
|
||||
|| INTVAL (XEXP (X, 1)) == 4)))
|
||||
|
||||
/* 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. */
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
||||
{ \
|
||||
rtx x1, x2; \
|
||||
if (BASE_OR_AUTOINCR_P (X)) \
|
||||
goto ADDR; \
|
||||
else if (TARGET_V32) \
|
||||
/* Nothing else is valid then. */ \
|
||||
; \
|
||||
else if (CONSTANT_INDEX_P (X)) \
|
||||
goto ADDR; \
|
||||
/* Indexed? */ \
|
||||
else if (GET_CODE (X) == PLUS) \
|
||||
{ \
|
||||
x1 = XEXP (X, 0); \
|
||||
x2 = XEXP (X, 1); \
|
||||
/* BDAP o, Rd. */ \
|
||||
if ((BASE_P (x1) && CONSTANT_INDEX_P (x2)) \
|
||||
|| (BASE_P (x2) && CONSTANT_INDEX_P (x1)) \
|
||||
/* BDAP Rs[+], Rd. */ \
|
||||
|| (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \
|
||||
&& ((BASE_P (x1) && BDAP_INDEX_P (x2)) \
|
||||
|| (BASE_P (x2) && BDAP_INDEX_P (x1)) \
|
||||
/* BIAP.m Rs, Rd */ \
|
||||
|| (BASE_P (x1) && BIAP_INDEX_P (x2)) \
|
||||
|| (BASE_P (x2) && BIAP_INDEX_P (x1))))) \
|
||||
goto ADDR; \
|
||||
} \
|
||||
else if (MEM_P (X)) \
|
||||
{ \
|
||||
/* DIP (Rs). Reject [[reg+]] and [[reg]] for \
|
||||
DImode (long long). */ \
|
||||
if (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \
|
||||
&& (BASE_P (XEXP (X, 0)) \
|
||||
|| BASE_OR_AUTOINCR_P (XEXP (X, 0)))) \
|
||||
goto ADDR; \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifndef REG_OK_STRICT
|
||||
/* Nonzero if X is a hard reg that can be used as a base reg
|
||||
or if it is a pseudo reg. */
|
||||
# define REG_OK_FOR_BASE_P(X) \
|
||||
(REGNO (X) <= CRIS_LAST_GENERAL_REGISTER \
|
||||
|| REGNO (X) == ARG_POINTER_REGNUM \
|
||||
|| REGNO (X) >= FIRST_PSEUDO_REGISTER)
|
||||
#else
|
||||
/* Nonzero if X is a hard reg that can be used as a base reg. */
|
||||
# define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
|
||||
#endif
|
||||
|
||||
#ifndef REG_OK_STRICT
|
||||
/* Nonzero if X is a hard reg that can be used as an index
|
||||
or if it is a pseudo reg. */
|
||||
# define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X)
|
||||
#else
|
||||
/* Nonzero if X is a hard reg that can be used as an index. */
|
||||
# define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
|
||||
#endif
|
||||
|
||||
/* Fix reloads known to cause suboptimal spilling. */
|
||||
#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, INDL, WIN) \
|
||||
do \
|
||||
|
@ -4680,7 +4680,7 @@
|
||||
(match_operator 4 "cris_mem_op" [(match_dup 0)]))]
|
||||
"GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
|
||||
&& REGNO (operands[3]) != REGNO (operands[0])
|
||||
&& (BASE_P (operands[1]) || BASE_P (operands[2]))
|
||||
&& (cris_base_p (operands[1], true) || cris_base_p (operands[2], true))
|
||||
&& !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
|
||||
&& !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
|
||||
&& (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)
|
||||
@ -4716,7 +4716,7 @@
|
||||
(match_operand 4 "register_operand" ""))]
|
||||
"GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
|
||||
&& REGNO (operands[4]) != REGNO (operands[0])
|
||||
&& (BASE_P (operands[1]) || BASE_P (operands[2]))
|
||||
&& (cris_base_p (operands[1], true) || cris_base_p (operands[2], true))
|
||||
&& !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
|
||||
&& !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
|
||||
&& (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)
|
||||
|
Loading…
Reference in New Issue
Block a user