predicates.md: New file.
* config/cris/predicates.md: New file. * config/cris/cris-protos.h (cris_store_multiple_op_p) (cris_movem_load_rest_p): Declare. * config/cris/cris.c (cris_store_multiple_op): Return bool, not int. (cris_movem_load_rest_p): Ditto. Globalize. (cris_bdap_operand, cris_bdap_biap_operand, cris_orthogonal_operator, cris_commutative_orth_op, cris_operand_extend_operator, cris_additive_operand_extend_operator, cris_extend_operator, cris_plus_or_bound_operator, cris_mem_op, cris_general_operand_or_symbol, cris_general_operand_or_gotless_symbol, cris_general_operand_or_plt_symbol, cris_mem_call_operand, cris_load_multiple_op): Remove predicate functions. (cris_symbol, cris_gotless_symbol) <case UNSPEC>: Return 0, don't abort, for UNSPECs other than CRIS_UNSPEC_PLT. * config/cris/cris.h (PREDICATE_CODES): Don't define. * config/cris/cris.md: Include predicates.md. ("call", "call_value"): Generate CONSTs of Pmode, not VOIDmode. From-SVN: r98471
This commit is contained in:
parent
c3e5898be3
commit
68a813322b
@ -1,3 +1,25 @@
|
||||
2005-04-21 Hans-Peter Nilsson <hp@axis.com>
|
||||
|
||||
* config/cris/predicates.md: New file.
|
||||
* config/cris/cris-protos.h (cris_store_multiple_op_p)
|
||||
(cris_movem_load_rest_p): Declare.
|
||||
* config/cris/cris.c (cris_store_multiple_op): Return bool, not int.
|
||||
(cris_movem_load_rest_p): Ditto. Globalize.
|
||||
(cris_bdap_operand, cris_bdap_biap_operand,
|
||||
cris_orthogonal_operator, cris_commutative_orth_op,
|
||||
cris_operand_extend_operator,
|
||||
cris_additive_operand_extend_operator, cris_extend_operator,
|
||||
cris_plus_or_bound_operator, cris_mem_op,
|
||||
cris_general_operand_or_symbol,
|
||||
cris_general_operand_or_gotless_symbol,
|
||||
cris_general_operand_or_plt_symbol, cris_mem_call_operand,
|
||||
cris_load_multiple_op): Remove predicate functions.
|
||||
(cris_symbol, cris_gotless_symbol) <case UNSPEC>: Return 0, don't
|
||||
abort, for UNSPECs other than CRIS_UNSPEC_PLT.
|
||||
* config/cris/cris.h (PREDICATE_CODES): Don't define.
|
||||
* config/cris/cris.md: Include predicates.md.
|
||||
("call", "call_value"): Generate CONSTs of Pmode, not VOIDmode.
|
||||
|
||||
2005-04-20 Ian Lance Taylor <ian@airs.com>
|
||||
|
||||
* c-common.def: Remove STMT_EXPR (moved to cp/cp-tree.def).
|
||||
|
@ -41,6 +41,8 @@ extern int cris_legitimate_pic_operand (rtx);
|
||||
extern int cris_gotless_symbol (rtx);
|
||||
extern int cris_got_symbol (rtx);
|
||||
extern int cris_symbol (rtx);
|
||||
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);
|
||||
extern bool cris_output_addr_const_extra (FILE *, rtx);
|
||||
extern int cris_cfun_uses_pic_table (void);
|
||||
|
@ -120,8 +120,6 @@ static void cris_operand_lossage (const char *, rtx);
|
||||
|
||||
static int cris_reg_saved_in_regsave_area (unsigned int, bool);
|
||||
|
||||
static int cris_movem_load_rest_p (rtx, int);
|
||||
|
||||
static void cris_asm_output_mi_thunk
|
||||
(FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
|
||||
|
||||
@ -205,280 +203,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Predicate functions. */
|
||||
|
||||
/* This checks a part of an address, the one that is not a plain register
|
||||
for an addressing mode using BDAP.
|
||||
Allowed operands is either:
|
||||
a) a register
|
||||
b) a CONST operand (but not a symbol when generating PIC)
|
||||
c) a [r] or [r+] in SImode, or sign-extend from HI or QI. */
|
||||
|
||||
int
|
||||
cris_bdap_operand (rtx op, enum machine_mode mode)
|
||||
{
|
||||
register enum rtx_code code = GET_CODE (op);
|
||||
|
||||
if (mode != SImode && (mode != VOIDmode || GET_MODE (op) != VOIDmode))
|
||||
return 0;
|
||||
|
||||
/* Just return whether this is a simple register or constant. */
|
||||
if (register_operand (op, mode)
|
||||
|| (CONSTANT_P (op) && !(flag_pic && cris_symbol (op))))
|
||||
return 1;
|
||||
|
||||
/* Is it a [r] or possibly a [r+]? */
|
||||
if (code == MEM)
|
||||
{
|
||||
rtx tem = XEXP (op, 0);
|
||||
|
||||
if (mode == SImode
|
||||
&& (register_operand (tem, SImode)
|
||||
|| (GET_CODE (tem) == POST_INC
|
||||
&& register_operand (XEXP (tem, 0), SImode))))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perhaps a sign-extended mem: [r].(b|w) or [r+].(b|w)? */
|
||||
if (code == SIGN_EXTEND)
|
||||
{
|
||||
rtx tem = XEXP (op, 0);
|
||||
|
||||
if (GET_CODE (tem) != MEM)
|
||||
return 0;
|
||||
|
||||
tem = XEXP (tem, 0);
|
||||
if (mode == SImode
|
||||
&& (register_operand (tem, SImode)
|
||||
|| (GET_CODE (tem) == POST_INC
|
||||
&& register_operand (XEXP (tem, 0), SImode))))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is similar to cris_bdap_operand:
|
||||
It checks a part of an address, the one that is not a plain register
|
||||
for an addressing mode using BDAP *or* BIAP.
|
||||
Allowed operands is either:
|
||||
a) a register
|
||||
b) a CONST operand (but not a symbol when generating PIC)
|
||||
c) a mult of (1, 2 or 4) and a register
|
||||
d) a [r] or [r+] in SImode, or sign-extend from HI or QI. */
|
||||
|
||||
int
|
||||
cris_bdap_biap_operand (rtx op, enum machine_mode mode)
|
||||
{
|
||||
register enum rtx_code code = GET_CODE (op);
|
||||
rtx reg;
|
||||
rtx val;
|
||||
|
||||
/* Check for bdap operand. */
|
||||
if (cris_bdap_operand (op, mode))
|
||||
return 1;
|
||||
|
||||
if (mode != SImode && (mode != VOIDmode || GET_MODE (op) != VOIDmode))
|
||||
return 0;
|
||||
|
||||
/* Check that we're looking at a BIAP operand. */
|
||||
if (code != MULT)
|
||||
return 0;
|
||||
|
||||
/* Canonicalize register and multiplicand. */
|
||||
if (GET_CODE (XEXP (op, 0)) == CONST_INT)
|
||||
{
|
||||
val = XEXP (op, 0);
|
||||
reg = XEXP (op, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = XEXP (op, 1);
|
||||
reg = XEXP (op, 0);
|
||||
}
|
||||
|
||||
/* Check that the operands are correct after canonicalization. */
|
||||
if (! register_operand (reg, SImode) || GET_CODE (val) != CONST_INT)
|
||||
return 0;
|
||||
|
||||
/* Check that the multiplicand has a valid value. */
|
||||
if ((code == MULT
|
||||
&& (INTVAL (val) == 1 || INTVAL (val) == 2 || INTVAL (val) == 4)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if MODE is same as mode for X, and X is PLUS, MINUS, IOR or
|
||||
AND or UMIN. */
|
||||
|
||||
int
|
||||
cris_orthogonal_operator (rtx x, enum machine_mode mode)
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (x);
|
||||
|
||||
return (GET_MODE (x) == mode
|
||||
&& (code == PLUS || code == MINUS
|
||||
|| code == IOR || code == AND || code == UMIN));
|
||||
}
|
||||
|
||||
/* Check if MODE is same as mode for X, and X is PLUS, IOR or AND or
|
||||
UMIN. */
|
||||
|
||||
int
|
||||
cris_commutative_orth_op (rtx x, enum machine_mode mode)
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (x);
|
||||
|
||||
return (GET_MODE (x) == mode &&
|
||||
(code == PLUS
|
||||
|| code == IOR || code == AND || code == UMIN));
|
||||
}
|
||||
|
||||
/* Check if MODE is same as mode for X, and X is PLUS or MINUS or UMIN.
|
||||
By the name, you might think we should include MULT. We don't because
|
||||
it doesn't accept the same addressing modes as the others (ony
|
||||
registers) and there's also the problem of handling TARGET_MUL_BUG. */
|
||||
|
||||
int
|
||||
cris_operand_extend_operator (rtx x, enum machine_mode mode)
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (x);
|
||||
|
||||
return (GET_MODE (x) == mode
|
||||
&& (code == PLUS || code == MINUS || code == UMIN));
|
||||
}
|
||||
|
||||
/* Check if MODE is same as mode for X, and X is PLUS or MINUS. */
|
||||
|
||||
int
|
||||
cris_additive_operand_extend_operator (rtx x, enum machine_mode mode)
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (x);
|
||||
|
||||
return (GET_MODE (x) == mode
|
||||
&& (code == PLUS || code == MINUS));
|
||||
}
|
||||
|
||||
/* Check to see if MODE is same as mode for X, and X is SIGN_EXTEND or
|
||||
ZERO_EXTEND. */
|
||||
|
||||
int
|
||||
cris_extend_operator (rtx x, enum machine_mode mode)
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (x);
|
||||
|
||||
return
|
||||
(GET_MODE (x) == mode && (code == SIGN_EXTEND || code == ZERO_EXTEND));
|
||||
}
|
||||
|
||||
/* Check to see if MODE is same as mode for X, and X is PLUS or BOUND. */
|
||||
|
||||
int
|
||||
cris_plus_or_bound_operator (rtx x, enum machine_mode mode)
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (x);
|
||||
|
||||
return
|
||||
(GET_MODE (x) == mode && (code == UMIN || code == PLUS));
|
||||
}
|
||||
|
||||
/* Used as an operator to get a handle on a already-known-valid MEM rtx:es
|
||||
(no need to validate the address), where some address expression parts
|
||||
have their own match_operand. */
|
||||
|
||||
int
|
||||
cris_mem_op (rtx x, enum machine_mode mode)
|
||||
{
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (x);
|
||||
|
||||
return GET_MODE (x) == mode && GET_CODE (x) == MEM;
|
||||
}
|
||||
|
||||
/* Since with -fPIC, not all symbols are valid PIC symbols or indeed
|
||||
general_operands, we have to have a predicate that matches it for the
|
||||
"movsi" expander. */
|
||||
|
||||
int
|
||||
cris_general_operand_or_symbol (rtx op, enum machine_mode mode)
|
||||
{
|
||||
return general_operand (op, mode)
|
||||
|| (CONSTANT_P (op) && cris_symbol (op));
|
||||
}
|
||||
|
||||
/* Since a PIC symbol without a GOT entry is not a general_operand, we
|
||||
have to have a predicate that matches it. We use this in the expanded
|
||||
"movsi" anonymous pattern. */
|
||||
|
||||
int
|
||||
cris_general_operand_or_gotless_symbol (rtx op, enum machine_mode mode)
|
||||
{
|
||||
return general_operand (op, mode)
|
||||
|| (GET_CODE (op) == UNSPEC && XINT (op, 1) == CRIS_UNSPEC_GOT)
|
||||
|| (CONSTANT_P (op) && cris_gotless_symbol (op));
|
||||
}
|
||||
|
||||
/* Since a PLT symbol is not a general_operand, we have to have a
|
||||
predicate that matches it when we need it. We use this in the expanded
|
||||
"call" and "call_value" anonymous patterns. */
|
||||
|
||||
int
|
||||
cris_general_operand_or_plt_symbol (rtx op, enum machine_mode mode)
|
||||
{
|
||||
return general_operand (op, mode)
|
||||
|| (GET_CODE (op) == CONST
|
||||
&& GET_CODE (XEXP (op, 0)) == UNSPEC
|
||||
&& !TARGET_AVOID_GOTPLT);
|
||||
}
|
||||
|
||||
/* This matches a (MEM (general_operand)) or
|
||||
(MEM (cris_general_operand_or_symbol)). The second one isn't a valid
|
||||
memory_operand, so we need this predicate to recognize call
|
||||
destinations before we change them to a PLT operand (by wrapping in
|
||||
UNSPEC CRIS_UNSPEC_PLT). */
|
||||
|
||||
int
|
||||
cris_mem_call_operand (rtx op, enum machine_mode mode)
|
||||
{
|
||||
rtx xmem;
|
||||
|
||||
if (GET_CODE (op) != MEM)
|
||||
return 0;
|
||||
|
||||
if (memory_operand (op, mode))
|
||||
return 1;
|
||||
|
||||
xmem = XEXP (op, 0);
|
||||
|
||||
return cris_general_operand_or_symbol (xmem, GET_MODE (op));
|
||||
}
|
||||
|
||||
/* Helper for cris_load_multiple_op and cris_ret_movem_op. */
|
||||
|
||||
static int
|
||||
bool
|
||||
cris_movem_load_rest_p (rtx op, int offs)
|
||||
{
|
||||
unsigned int reg_count = XVECLEN (op, 0) - offs;
|
||||
@ -495,7 +222,7 @@ cris_movem_load_rest_p (rtx op, int offs)
|
||||
|| GET_CODE (XVECEXP (op, 0, offs)) != SET
|
||||
|| GET_CODE (SET_DEST (XVECEXP (op, 0, offs))) != REG
|
||||
|| GET_CODE (SET_SRC (XVECEXP (op, 0, offs))) != MEM)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* Check a possible post-inc indicator. */
|
||||
if (GET_CODE (SET_SRC (XVECEXP (op, 0, offs + 1))) == PLUS)
|
||||
@ -511,7 +238,7 @@ cris_movem_load_rest_p (rtx op, int offs)
|
||||
|| REGNO (reg) != REGNO (SET_DEST (XVECEXP (op, 0, offs + 1)))
|
||||
|| GET_CODE (inc) != CONST_INT
|
||||
|| INTVAL (inc) != (HOST_WIDE_INT) reg_count * 4)
|
||||
return 0;
|
||||
return false;
|
||||
i = offs + 2;
|
||||
}
|
||||
else
|
||||
@ -531,7 +258,7 @@ cris_movem_load_rest_p (rtx op, int offs)
|
||||
|| GET_CODE (SET_SRC (elt)) != MEM
|
||||
|| GET_MODE (SET_SRC (elt)) != SImode
|
||||
|| !memory_address_p (SImode, src_addr))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
for (setno = 1; i < XVECLEN (op, 0); setno++, i++)
|
||||
{
|
||||
@ -548,24 +275,17 @@ cris_movem_load_rest_p (rtx op, int offs)
|
||||
|| ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
|
||||
|| GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
|
||||
|| INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != setno * 4)
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Predicate for the parallel contents in a movem from-memory. */
|
||||
/* Worker function for predicate for the parallel contents in a movem
|
||||
to-memory. */
|
||||
|
||||
int
|
||||
cris_load_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return cris_movem_load_rest_p (op, 0);
|
||||
}
|
||||
|
||||
/* Predicate for the parallel contents in a movem to-memory. */
|
||||
|
||||
int
|
||||
cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||
bool
|
||||
cris_store_multiple_op_p (rtx op)
|
||||
{
|
||||
int reg_count = XVECLEN (op, 0);
|
||||
rtx dest;
|
||||
@ -581,18 +301,18 @@ cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||
/* Perform a quick check so we don't blow up below. FIXME: Adjust for
|
||||
other than (MEM reg) and (MEM (PLUS reg const)). */
|
||||
if (reg_count <= 1)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
elt = XVECEXP (op, 0, 0);
|
||||
|
||||
if (GET_CODE (elt) != SET)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
dest = SET_DEST (elt);
|
||||
|
||||
if (GET_CODE (SET_SRC (elt)) != REG
|
||||
|| GET_CODE (dest) != MEM)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
dest_addr = XEXP (dest, 0);
|
||||
|
||||
@ -620,7 +340,7 @@ cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||
&& REGNO (XEXP (dest_addr, 0)) == REGNO (reg)
|
||||
&& GET_CODE (XEXP (dest_addr, 1)) == CONST_INT
|
||||
&& INTVAL (XEXP (dest_addr, 1)) == INTVAL (inc))))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
i = 2;
|
||||
}
|
||||
@ -637,7 +357,7 @@ cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||
|| REGNO (SET_SRC (elt)) != (unsigned int) regno
|
||||
|| GET_CODE (SET_DEST (elt)) != MEM
|
||||
|| GET_MODE (SET_DEST (elt)) != SImode)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (REG_P (dest_addr))
|
||||
{
|
||||
@ -652,7 +372,7 @@ cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||
offset = INTVAL (XEXP (dest_addr, 1));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
for (setno = 1; i < XVECLEN (op, 0); setno++, i++)
|
||||
{
|
||||
@ -669,10 +389,10 @@ cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||
|| ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_base)
|
||||
|| GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
|
||||
|| INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != setno * 4 + offset)
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The CONDITIONAL_REGISTER_USAGE worker. */
|
||||
@ -2176,7 +1896,7 @@ cris_symbol (rtx x)
|
||||
return 1;
|
||||
|
||||
case UNSPEC:
|
||||
if (XINT (x, 1) == CRIS_UNSPEC_GOT)
|
||||
if (XINT (x, 1) == CRIS_UNSPEC_GOT || XINT (x, 1) != CRIS_UNSPEC_PLT)
|
||||
return 0;
|
||||
/* A PLT reference. */
|
||||
ASSERT_PLT_UNSPEC (x);
|
||||
@ -2218,6 +1938,8 @@ cris_gotless_symbol (rtx x)
|
||||
case UNSPEC:
|
||||
if (XINT (x, 1) == CRIS_UNSPEC_GOT)
|
||||
return 1;
|
||||
if (XINT (x, 1) != CRIS_UNSPEC_PLT)
|
||||
return 0;
|
||||
ASSERT_PLT_UNSPEC (x);
|
||||
return 1;
|
||||
|
||||
|
@ -1616,44 +1616,6 @@ struct cum_args {int regs;};
|
||||
|
||||
/* Node: Misc */
|
||||
|
||||
/* FIXME: Check this one more time. */
|
||||
#define PREDICATE_CODES \
|
||||
{"cris_orthogonal_operator", \
|
||||
{PLUS, MINUS, IOR, AND, UMIN}}, \
|
||||
{"cris_commutative_orth_op", \
|
||||
{PLUS, IOR, AND, UMIN}}, \
|
||||
{"cris_operand_extend_operator", \
|
||||
{PLUS, MINUS, UMIN}}, \
|
||||
{"cris_additive_operand_extend_operator", \
|
||||
{PLUS, MINUS}}, \
|
||||
{"cris_extend_operator", \
|
||||
{ZERO_EXTEND, SIGN_EXTEND}}, \
|
||||
{"cris_plus_or_bound_operator", \
|
||||
{PLUS, UMIN}}, \
|
||||
{"cris_mem_op", \
|
||||
{MEM}}, \
|
||||
{"cris_load_multiple_op", \
|
||||
{PARALLEL}}, \
|
||||
{"cris_store_multiple_op", \
|
||||
{PARALLEL}}, \
|
||||
{"cris_bdap_operand", \
|
||||
{SUBREG, REG, LABEL_REF, SYMBOL_REF, MEM, CONST_INT, \
|
||||
CONST_DOUBLE, CONST, SIGN_EXTEND}}, \
|
||||
{"cris_bdap_biap_operand", \
|
||||
{SUBREG, REG, LABEL_REF, SYMBOL_REF, MEM, CONST_INT, \
|
||||
CONST_DOUBLE, CONST, SIGN_EXTEND, MULT}}, \
|
||||
{"cris_general_operand_or_gotless_symbol", \
|
||||
{CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
|
||||
LABEL_REF, SUBREG, REG, MEM, UNSPEC}}, \
|
||||
{"cris_general_operand_or_symbol", \
|
||||
{CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
|
||||
LABEL_REF, SUBREG, REG, MEM}}, \
|
||||
{"cris_general_operand_or_plt_symbol", \
|
||||
{CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
|
||||
LABEL_REF, SUBREG, REG, MEM}}, \
|
||||
{"cris_mem_call_operand", \
|
||||
{MEM}},
|
||||
|
||||
/* A combination of the bound (umin) insn together with a
|
||||
sign-extended add via the table to PC seems optimal.
|
||||
If the table overflows, the assembler will take care of it.
|
||||
|
@ -141,6 +141,10 @@
|
||||
(define_delay (eq_attr "slottable" "has_slot")
|
||||
[(eq_attr "slottable" "yes") (nil) (nil)])
|
||||
|
||||
;; Operand and operator predicates.
|
||||
|
||||
(include "predicates.md")
|
||||
|
||||
;; Test insns.
|
||||
|
||||
;; DImode
|
||||
@ -3944,7 +3948,7 @@
|
||||
for the symbol cause bad recombinatorial effects? */
|
||||
op0 = force_reg (Pmode,
|
||||
gen_rtx_CONST
|
||||
(VOIDmode,
|
||||
(Pmode,
|
||||
gen_rtx_UNSPEC (VOIDmode,
|
||||
gen_rtvec (1, op0),
|
||||
CRIS_UNSPEC_PLT)));
|
||||
@ -4009,7 +4013,7 @@
|
||||
for the symbol cause bad recombinatorial effects? */
|
||||
op1 = force_reg (Pmode,
|
||||
gen_rtx_CONST
|
||||
(VOIDmode,
|
||||
(Pmode,
|
||||
gen_rtx_UNSPEC (VOIDmode,
|
||||
gen_rtvec (1, op1),
|
||||
CRIS_UNSPEC_PLT)));
|
||||
|
170
gcc/config/cris/predicates.md
Normal file
170
gcc/config/cris/predicates.md
Normal file
@ -0,0 +1,170 @@
|
||||
;; Operand and operator predicates for the GCC CRIS port.
|
||||
;; Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
;; This file is part of GCC.
|
||||
;;
|
||||
;; GCC is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
;;
|
||||
;; GCC is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GCC; see the file COPYING. If not, write to
|
||||
;; the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
;; Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
;; Operator predicates.
|
||||
|
||||
(define_predicate "cris_orthogonal_operator"
|
||||
(match_code "plus, minus, ior, and, umin"))
|
||||
|
||||
(define_predicate "cris_commutative_orth_op"
|
||||
(match_code "plus, ior, and, umin"))
|
||||
|
||||
;; By the name, you might think we should include MULT. We don't because
|
||||
;; it doesn't accept the same addressing modes as the others (only
|
||||
;; registers) and there's also the problem of handling TARGET_MUL_BUG.
|
||||
|
||||
(define_predicate "cris_operand_extend_operator"
|
||||
(match_code "plus, minus, umin"))
|
||||
|
||||
(define_predicate "cris_additive_operand_extend_operator"
|
||||
(match_code "plus, minus"))
|
||||
|
||||
(define_predicate "cris_extend_operator"
|
||||
(match_code "zero_extend, sign_extend"))
|
||||
|
||||
(define_predicate "cris_plus_or_bound_operator"
|
||||
(match_code "plus, umin"))
|
||||
|
||||
;; Used as an operator to get a handle on a already-known-valid MEM rtx:es
|
||||
;; (no need to validate the address), where some address expression parts
|
||||
;; have their own match_operand.
|
||||
|
||||
(define_predicate "cris_mem_op"
|
||||
(match_code "mem"))
|
||||
|
||||
(define_predicate "cris_load_multiple_op"
|
||||
(and (match_code "parallel")
|
||||
(match_test "cris_movem_load_rest_p (op, 0)")))
|
||||
|
||||
(define_predicate "cris_store_multiple_op"
|
||||
(and (match_code "parallel")
|
||||
(match_test "cris_store_multiple_op_p (op)")))
|
||||
|
||||
|
||||
;; Operand helper predicates.
|
||||
|
||||
(define_predicate "cris_bdap_const_operand"
|
||||
(and (match_code "label_ref, symbol_ref, const_int, const_double, const")
|
||||
(not (and (match_test "flag_pic")
|
||||
(match_test "cris_symbol (op)")))))
|
||||
|
||||
(define_predicate "cris_simple_address_operand"
|
||||
(ior (match_operand:SI 0 "register_operand")
|
||||
(and (match_code "post_inc")
|
||||
(match_test "register_operand (XEXP (op, 0), Pmode)"))))
|
||||
|
||||
(define_predicate "cris_simple_operand"
|
||||
(ior (match_operand 0 "register_operand")
|
||||
(and (match_code "mem")
|
||||
(match_test "cris_simple_address_operand (XEXP (op, 0),
|
||||
Pmode)"))))
|
||||
|
||||
;; The caller needs to use :SI.
|
||||
(define_predicate "cris_bdap_sign_extend_operand"
|
||||
(and (match_code "sign_extend")
|
||||
(and (match_test "MEM_P (XEXP (op, 0))")
|
||||
(match_test "cris_simple_address_operand (XEXP (XEXP (op, 0), 0),
|
||||
Pmode)"))))
|
||||
|
||||
;; FIXME: Should not have to test for 1.
|
||||
(define_predicate "cris_scale_int_operand"
|
||||
(and (match_code "const_int")
|
||||
(ior (ior (match_test "op == GEN_INT (4)")
|
||||
(match_test "op == const2_rtx"))
|
||||
(match_test "op == const1_rtx"))))
|
||||
|
||||
;; FIXME: Should be able to assume (reg int).
|
||||
(define_predicate "cris_biap_mult_operand"
|
||||
(and (match_code "mult")
|
||||
(ior (and (match_test "register_operand (XEXP (op, 0), Pmode)")
|
||||
(match_test "cris_scale_int_operand (XEXP (op, 1), Pmode)"))
|
||||
(and (match_test "cris_scale_int_operand (XEXP (op, 0), Pmode)")
|
||||
(match_test "register_operand (XEXP (op, 1), Pmode)")))))
|
||||
|
||||
|
||||
;; Operand predicates.
|
||||
|
||||
;; This checks a part of an address, the one that is not a plain register
|
||||
;; for an addressing mode using BDAP.
|
||||
;; Allowed operands are either:
|
||||
;; a) a register
|
||||
;; b) a CONST operand (but not a symbol when generating PIC)
|
||||
;; c) a [r] or [r+] in SImode, or sign-extend from HI or QI.
|
||||
|
||||
(define_predicate "cris_bdap_operand"
|
||||
(ior (match_operand 0 "cris_bdap_const_operand")
|
||||
(ior (match_operand:SI 0 "cris_simple_operand")
|
||||
(match_operand:SI 0 "cris_bdap_sign_extend_operand"))))
|
||||
|
||||
;; This is similar to cris_bdap_operand:
|
||||
;; It checks a part of an address, the one that is not a plain register
|
||||
;; for an addressing mode using BDAP or BIAP.
|
||||
;; Allowed operands are either:
|
||||
;; a) a register
|
||||
;; b) a CONST operand (but not a symbol when generating PIC)
|
||||
;; c) a mult of (1, 2 or 4) and a register
|
||||
;; d) a [r] or [r+] in SImode, or sign-extend from HI or QI. */
|
||||
|
||||
(define_predicate "cris_bdap_biap_operand"
|
||||
(ior (match_operand 0 "cris_bdap_operand")
|
||||
(match_operand 0 "cris_biap_mult_operand")))
|
||||
|
||||
;; Since a PIC symbol without a GOT entry is not a general_operand, we
|
||||
;; have to have a predicate that matches it. We use this in the expanded
|
||||
;; "movsi" anonymous pattern.
|
||||
;; FIXME: Can s/special_// when PR 20413 is fixed.
|
||||
|
||||
(define_special_predicate "cris_general_operand_or_gotless_symbol"
|
||||
(ior (match_operand 0 "general_operand")
|
||||
(and (match_code "const, symbol_ref, label_ref, unspec")
|
||||
(match_test "cris_gotless_symbol (op)"))))
|
||||
|
||||
;; Since with -fPIC, not all symbols are valid PIC symbols or indeed
|
||||
;; general_operands, we have to have a predicate that matches it for the
|
||||
;; "movsi" expander.
|
||||
;; FIXME: Can s/special_// when PR 20413 is fixed.
|
||||
|
||||
(define_special_predicate "cris_general_operand_or_symbol"
|
||||
(ior (match_operand 0 "general_operand")
|
||||
(and (match_code "const, symbol_ref, label_ref")
|
||||
(match_test "cris_symbol (op)"))))
|
||||
|
||||
;; Since a PLT symbol is not a general_operand, we have to have a
|
||||
;; predicate that matches it when we need it. We use this in the expanded
|
||||
;; "call" and "call_value" anonymous patterns.
|
||||
|
||||
(define_predicate "cris_general_operand_or_plt_symbol"
|
||||
(ior (match_operand 0 "general_operand")
|
||||
(and (match_code "const")
|
||||
(and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC")
|
||||
(not (match_test "TARGET_AVOID_GOTPLT"))))))
|
||||
|
||||
;; This matches a (MEM (general_operand)) or
|
||||
;; (MEM (cris_general_operand_or_symbol)). The second one isn't a valid
|
||||
;; memory_operand, so we need this predicate to recognize call
|
||||
;; destinations before we change them to a PLT operand (by wrapping in
|
||||
;; UNSPEC CRIS_UNSPEC_PLT).
|
||||
|
||||
(define_predicate "cris_mem_call_operand"
|
||||
(and (match_code "mem")
|
||||
(ior (match_operand 0 "memory_operand")
|
||||
(match_test "cris_general_operand_or_symbol (XEXP (op, 0),
|
||||
Pmode)"))))
|
Loading…
Reference in New Issue
Block a user