arm.md: Include predicates.md.

* arm.md: Include predicates.md.
* predicates.md: New file.
* arm.c (s_register_operand, arm_hard_register_operand)
(arm_general_register_operand, f_register_operand, reg_or_int_operand)
(arm_immediate_operand, arm_neg_immediate_operand)
(arm_not_immediate_operand, arm_rhs_operand, arm_rhsm_operand)
(arm_add_operand, arm_addimm_operand, arm_not_operand)
(offsettable_memory_operand, alignable_memory_operand)
(arm_reload_memory_operand, arm_float_rhs_operand)
(arm_float_add_operand, vfp_compare_operand, arm_float_compare_operand)
(index_operand, shiftable_operator, logical_binary_operator)
(shift_operator, equality_operator, arm_comparison_operator)
(minmax_operator, cc_register, dominant_cc_register)
(arm_extendqisi_mem_op, power_of_two_operand, nonimmediate_di_operand)
(di_operand, nonimmediate_soft_df_operand, soft_df_operand)
(const_shift_operand, load_multiple_operation)
(store_multiple_operation, multi_register_push, thumb_cmp_operand)
(thumb_cmpneg_operand, thumb_cbrch_target_operand)
(cirrus_register_operand, cirrus_fp_register)
(cirrus_shift_const): Delete, replaced with equivalents in
predicates.md.
(shift_op): Handle ROTATE.
* arm-protos.h: Delete declarations for above.
* arm.h (PREDICATE_CODES, SPECIAL_MODE_PREDICATES): Delete.
* t-arm (MD_INCLUDES): Add predicates.md.
(s-preds): Depends on MD_INCLUDES.

From-SVN: r86512
This commit is contained in:
Richard Earnshaw 2004-08-24 20:16:41 +00:00 committed by Richard Earnshaw
parent 886ce862cb
commit a657c98a58
7 changed files with 510 additions and 814 deletions

View File

@ -1,3 +1,32 @@
2004-08-24 Richard Earnshaw <rearnsha@arm.com>
* arm.md: Include predicates.md.
* predicates.md: New file.
* arm.c (s_register_operand, arm_hard_register_operand)
(arm_general_register_operand, f_register_operand, reg_or_int_operand)
(arm_immediate_operand, arm_neg_immediate_operand)
(arm_not_immediate_operand, arm_rhs_operand, arm_rhsm_operand)
(arm_add_operand, arm_addimm_operand, arm_not_operand)
(offsettable_memory_operand, alignable_memory_operand)
(arm_reload_memory_operand, arm_float_rhs_operand)
(arm_float_add_operand, vfp_compare_operand, arm_float_compare_operand)
(index_operand, shiftable_operator, logical_binary_operator)
(shift_operator, equality_operator, arm_comparison_operator)
(minmax_operator, cc_register, dominant_cc_register)
(arm_extendqisi_mem_op, power_of_two_operand, nonimmediate_di_operand)
(di_operand, nonimmediate_soft_df_operand, soft_df_operand)
(const_shift_operand, load_multiple_operation)
(store_multiple_operation, multi_register_push, thumb_cmp_operand)
(thumb_cmpneg_operand, thumb_cbrch_target_operand)
(cirrus_register_operand, cirrus_fp_register)
(cirrus_shift_const): Delete, replaced with equivalents in
predicates.md.
(shift_op): Handle ROTATE.
* arm-protos.h: Delete declarations for above.
* arm.h (PREDICATE_CODES, SPECIAL_MODE_PREDICATES): Delete.
* t-arm (MD_INCLUDES): Add predicates.md.
(s-preds): Depends on MD_INCLUDES.
2004-08-24 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.c (mips_gen_conditional_trap): Fix mode.

View File

@ -61,49 +61,8 @@ extern int arm_const_double_rtx (rtx);
extern int neg_const_double_rtx_ok_for_fpa (rtx);
extern enum reg_class vfp_secondary_reload_class (enum machine_mode, rtx);
/* Predicates. */
extern int s_register_operand (rtx, enum machine_mode);
extern int arm_hard_register_operand (rtx, enum machine_mode);
extern int arm_general_register_operand (rtx, enum machine_mode);
extern int f_register_operand (rtx, enum machine_mode);
extern int reg_or_int_operand (rtx, enum machine_mode);
extern int arm_reload_memory_operand (rtx, enum machine_mode);
extern int arm_rhs_operand (rtx, enum machine_mode);
extern int arm_rhsm_operand (rtx, enum machine_mode);
extern int arm_add_operand (rtx, enum machine_mode);
extern int arm_addimm_operand (rtx, enum machine_mode);
extern int arm_not_operand (rtx, enum machine_mode);
extern int arm_extendqisi_mem_op (rtx, enum machine_mode);
extern int offsettable_memory_operand (rtx, enum machine_mode);
extern int alignable_memory_operand (rtx, enum machine_mode);
extern int arm_float_rhs_operand (rtx, enum machine_mode);
extern int arm_float_add_operand (rtx, enum machine_mode);
extern int power_of_two_operand (rtx, enum machine_mode);
extern int nonimmediate_di_operand (rtx, enum machine_mode);
extern int di_operand (rtx, enum machine_mode);
extern int nonimmediate_soft_df_operand (rtx, enum machine_mode);
extern int soft_df_operand (rtx, enum machine_mode);
extern int index_operand (rtx, enum machine_mode);
extern int const_shift_operand (rtx, enum machine_mode);
extern int arm_comparison_operator (rtx, enum machine_mode);
extern int shiftable_operator (rtx, enum machine_mode);
extern int shift_operator (rtx, enum machine_mode);
extern int equality_operator (rtx, enum machine_mode);
extern int minmax_operator (rtx, enum machine_mode);
extern int cc_register (rtx, enum machine_mode);
extern int dominant_cc_register (rtx, enum machine_mode);
extern int logical_binary_operator (rtx, enum machine_mode);
extern int multi_register_push (rtx, enum machine_mode);
extern int load_multiple_operation (rtx, enum machine_mode);
extern int store_multiple_operation (rtx, enum machine_mode);
extern int cirrus_fp_register (rtx, enum machine_mode);
extern int cirrus_general_operand (rtx, enum machine_mode);
extern int cirrus_register_operand (rtx, enum machine_mode);
extern int cirrus_shift_const (rtx, enum machine_mode);
extern int cirrus_memory_offset (rtx);
extern int arm_coproc_mem_operand (rtx, bool);
extern int vfp_compare_operand (rtx, enum machine_mode);
extern int arm_float_compare_operand (rtx, enum machine_mode);
extern int arm_no_early_store_addr_dep (rtx, rtx);
extern int arm_no_early_alu_shift_dep (rtx, rtx);
extern int arm_no_early_alu_shift_value_dep (rtx, rtx);
@ -191,8 +150,6 @@ extern void thumb_final_prescan_insn (rtx);
extern const char *thumb_load_double_from_address (rtx *);
extern const char *thumb_output_move_mem_multiple (int, rtx *);
extern void thumb_expand_movmemqi (rtx *);
extern int thumb_cmp_operand (rtx, enum machine_mode);
extern int thumb_cbrch_target_operand (rtx, enum machine_mode);
extern rtx *thumb_legitimize_pic_address (rtx, enum machine_mode, rtx);
extern int thumb_go_if_legitimate_address (enum machine_mode, rtx);
extern rtx arm_return_addr (int, rtx);

View File

@ -4624,243 +4624,6 @@ neg_const_double_rtx_ok_for_fpa (rtx x)
/* Predicates for `match_operand' and `match_operator'. */
/* s_register_operand is the same as register_operand, but it doesn't accept
(SUBREG (MEM)...).
This function exists because at the time it was put in it led to better
code. SUBREG(MEM) always needs a reload in the places where
s_register_operand is used, and this seemed to lead to excessive
reloading. */
int
s_register_operand (rtx op, enum machine_mode mode)
{
if (GET_MODE (op) != mode && mode != VOIDmode)
return 0;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
/* We don't consider registers whose class is NO_REGS
to be a register operand. */
/* XXX might have to check for lo regs only for thumb ??? */
return (GET_CODE (op) == REG
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
}
/* A hard register operand (even before reload. */
int
arm_hard_register_operand (rtx op, enum machine_mode mode)
{
if (GET_MODE (op) != mode && mode != VOIDmode)
return 0;
return (GET_CODE (op) == REG
&& REGNO (op) < FIRST_PSEUDO_REGISTER);
}
/* An arm register operand. */
int
arm_general_register_operand (rtx op, enum machine_mode mode)
{
if (GET_MODE (op) != mode && mode != VOIDmode)
return 0;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
return (GET_CODE (op) == REG
&& (REGNO (op) <= LAST_ARM_REGNUM
|| REGNO (op) >= FIRST_PSEUDO_REGISTER));
}
/* Only accept reg, subreg(reg), const_int. */
int
reg_or_int_operand (rtx op, enum machine_mode mode)
{
if (GET_CODE (op) == CONST_INT)
return 1;
if (GET_MODE (op) != mode && mode != VOIDmode)
return 0;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
/* We don't consider registers whose class is NO_REGS
to be a register operand. */
return (GET_CODE (op) == REG
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
}
/* Return 1 if OP is an item in memory, given that we are in reload. */
int
arm_reload_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
int regno = true_regnum (op);
return (!CONSTANT_P (op)
&& (regno == -1
|| (GET_CODE (op) == REG
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)));
}
/* Return TRUE for valid operands for the rhs of an ARM instruction. */
int
arm_rhs_operand (rtx op, enum machine_mode mode)
{
return (s_register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op))));
}
/* Return TRUE for valid operands for the
rhs of an ARM instruction, or a load. */
int
arm_rhsm_operand (rtx op, enum machine_mode mode)
{
return (s_register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op)))
|| memory_operand (op, mode));
}
/* Return TRUE for valid operands for the rhs of an ARM instruction, or if a
constant that is valid when negated. */
int
arm_add_operand (rtx op, enum machine_mode mode)
{
if (TARGET_THUMB)
return thumb_cmp_operand (op, mode);
return (s_register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT
&& (const_ok_for_arm (INTVAL (op))
|| const_ok_for_arm (-INTVAL (op)))));
}
/* Return TRUE for valid ARM constants (or when valid if negated). */
int
arm_addimm_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (GET_CODE (op) == CONST_INT
&& (const_ok_for_arm (INTVAL (op))
|| const_ok_for_arm (-INTVAL (op))));
}
int
arm_not_operand (rtx op, enum machine_mode mode)
{
return (s_register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT
&& (const_ok_for_arm (INTVAL (op))
|| const_ok_for_arm (~INTVAL (op)))));
}
/* Return TRUE if the operand is a memory reference which contains an
offsettable address. */
int
offsettable_memory_operand (rtx op, enum machine_mode mode)
{
if (mode == VOIDmode)
mode = GET_MODE (op);
return (mode == GET_MODE (op)
&& GET_CODE (op) == MEM
&& offsettable_address_p (reload_completed | reload_in_progress,
mode, XEXP (op, 0)));
}
/* Return TRUE if the operand is a memory reference which is, or can be
made word aligned by adjusting the offset. */
int
alignable_memory_operand (rtx op, enum machine_mode mode)
{
rtx reg;
if (mode == VOIDmode)
mode = GET_MODE (op);
if (mode != GET_MODE (op) || GET_CODE (op) != MEM)
return 0;
op = XEXP (op, 0);
return ((GET_CODE (reg = op) == REG
|| (GET_CODE (op) == SUBREG
&& GET_CODE (reg = SUBREG_REG (op)) == REG)
|| (GET_CODE (op) == PLUS
&& GET_CODE (XEXP (op, 1)) == CONST_INT
&& (GET_CODE (reg = XEXP (op, 0)) == REG
|| (GET_CODE (XEXP (op, 0)) == SUBREG
&& GET_CODE (reg = SUBREG_REG (XEXP (op, 0))) == REG))))
&& REGNO_POINTER_ALIGN (REGNO (reg)) >= 32);
}
/* Similar to s_register_operand, but does not allow hard integer
registers. */
int
f_register_operand (rtx op, enum machine_mode mode)
{
if (GET_MODE (op) != mode && mode != VOIDmode)
return 0;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
/* We don't consider registers whose class is NO_REGS
to be a register operand. */
return (GET_CODE (op) == REG
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) == FPA_REGS));
}
/* Return TRUE for valid operands for the rhs of an floating point insns.
Allows regs or certain consts on FPA, just regs for everything else. */
int
arm_float_rhs_operand (rtx op, enum machine_mode mode)
{
if (s_register_operand (op, mode))
return TRUE;
if (GET_MODE (op) != mode && mode != VOIDmode)
return FALSE;
if (TARGET_FPA && GET_CODE (op) == CONST_DOUBLE)
return arm_const_double_rtx (op);
return FALSE;
}
int
arm_float_add_operand (rtx op, enum machine_mode mode)
{
if (s_register_operand (op, mode))
return TRUE;
if (GET_MODE (op) != mode && mode != VOIDmode)
return FALSE;
if (TARGET_FPA && GET_CODE (op) == CONST_DOUBLE)
return (arm_const_double_rtx (op)
|| neg_const_double_rtx_ok_for_fpa (op));
return FALSE;
}
/* Return TRUE if OP is suitable for the rhs of a floating point comparison.
Depends which fpu we are targeting. */
int
arm_float_compare_operand (rtx op, enum machine_mode mode)
{
if (TARGET_VFP)
return vfp_compare_operand (op, mode);
else
return arm_float_rhs_operand (op, mode);
}
/* Return nonzero if OP is a valid Cirrus memory address pattern. */
int
cirrus_memory_offset (rtx op)
@ -4898,55 +4661,6 @@ cirrus_memory_offset (rtx op)
return 0;
}
int
arm_extendqisi_mem_op (rtx op, enum machine_mode mode)
{
if (!memory_operand (op, mode))
return 0;
return arm_legitimate_address_p (mode, XEXP (op, 0), SIGN_EXTEND, 0);
}
/* Return nonzero if OP is a Cirrus or general register. */
int
cirrus_register_operand (rtx op, enum machine_mode mode)
{
if (GET_MODE (op) != mode && mode != VOIDmode)
return FALSE;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
return (GET_CODE (op) == REG
&& (REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS
|| REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS));
}
/* Return nonzero if OP is a cirrus FP register. */
int
cirrus_fp_register (rtx op, enum machine_mode mode)
{
if (GET_MODE (op) != mode && mode != VOIDmode)
return FALSE;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
return (GET_CODE (op) == REG
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS));
}
/* Return nonzero if OP is a 6bit constant (0..63). */
int
cirrus_shift_const (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (GET_CODE (op) == CONST_INT
&& INTVAL (op) >= 0
&& INTVAL (op) < 64);
}
/* Return TRUE if OP is a valid VFP memory address pattern.
WB if true if writeback address modes are allowed. */
@ -5014,18 +4728,6 @@ arm_coproc_mem_operand (rtx op, bool wb)
}
/* Return TRUE if OP is a REG or constant zero. */
int
vfp_compare_operand (rtx op, enum machine_mode mode)
{
if (s_register_operand (op, mode))
return TRUE;
return (GET_CODE (op) == CONST_DOUBLE
&& arm_const_double_rtx (op));
}
/* Return GENERAL_REGS if a scratch register required to reload x to/from
VFP registers. Otherwise return NO_REGS. */
@ -5211,262 +4913,6 @@ cirrus_reorg (rtx first)
}
}
/* Return nonzero if OP is a constant power of two. */
int
power_of_two_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) == CONST_INT)
{
HOST_WIDE_INT value = INTVAL (op);
return value != 0 && (value & (value - 1)) == 0;
}
return FALSE;
}
/* Return TRUE for a valid operand of a DImode operation.
Either: REG, SUBREG, CONST_DOUBLE or MEM(DImode_address).
Note that this disallows MEM(REG+REG), but allows
MEM(PRE/POST_INC/DEC(REG)). */
int
di_operand (rtx op, enum machine_mode mode)
{
if (s_register_operand (op, mode))
return TRUE;
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
return FALSE;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
switch (GET_CODE (op))
{
case CONST_DOUBLE:
case CONST_INT:
return TRUE;
case MEM:
return memory_address_p (DImode, XEXP (op, 0));
default:
return FALSE;
}
}
/* Like di_operand, but don't accept constants. */
int
nonimmediate_di_operand (rtx op, enum machine_mode mode)
{
if (s_register_operand (op, mode))
return TRUE;
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
return FALSE;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
if (GET_CODE (op) == MEM)
return memory_address_p (DImode, XEXP (op, 0));
return FALSE;
}
/* Return TRUE for a valid operand of a DFmode operation when soft-float.
Either: REG, SUBREG, CONST_DOUBLE or MEM(DImode_address).
Note that this disallows MEM(REG+REG), but allows
MEM(PRE/POST_INC/DEC(REG)). */
int
soft_df_operand (rtx op, enum machine_mode mode)
{
if (s_register_operand (op, mode))
return TRUE;
if (mode != VOIDmode && GET_MODE (op) != mode)
return FALSE;
if (GET_CODE (op) == SUBREG && CONSTANT_P (SUBREG_REG (op)))
return FALSE;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
switch (GET_CODE (op))
{
case CONST_DOUBLE:
return TRUE;
case MEM:
return memory_address_p (DFmode, XEXP (op, 0));
default:
return FALSE;
}
}
/* Like soft_df_operand, but don't accept constants. */
int
nonimmediate_soft_df_operand (rtx op, enum machine_mode mode)
{
if (s_register_operand (op, mode))
return TRUE;
if (mode != VOIDmode && GET_MODE (op) != mode)
return FALSE;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
if (GET_CODE (op) == MEM)
return memory_address_p (DFmode, XEXP (op, 0));
return FALSE;
}
/* Return TRUE for valid index operands. */
int
index_operand (rtx op, enum machine_mode mode)
{
return (s_register_operand (op, mode)
|| (immediate_operand (op, mode)
&& (GET_CODE (op) != CONST_INT
|| (INTVAL (op) < 4096 && INTVAL (op) > -4096))));
}
/* Return TRUE for valid shifts by a constant. This also accepts any
power of two on the (somewhat overly relaxed) assumption that the
shift operator in this case was a mult. */
int
const_shift_operand (rtx op, enum machine_mode mode)
{
return (power_of_two_operand (op, mode)
|| (immediate_operand (op, mode)
&& (GET_CODE (op) != CONST_INT
|| (INTVAL (op) < 32 && INTVAL (op) > 0))));
}
/* Return TRUE for arithmetic operators which can be combined with a multiply
(shift). */
int
shiftable_operator (rtx x, enum machine_mode mode)
{
enum rtx_code code;
if (GET_MODE (x) != mode)
return FALSE;
code = GET_CODE (x);
return (code == PLUS || code == MINUS
|| code == IOR || code == XOR || code == AND);
}
/* Return TRUE for binary logical operators. */
int
logical_binary_operator (rtx x, enum machine_mode mode)
{
enum rtx_code code;
if (GET_MODE (x) != mode)
return FALSE;
code = GET_CODE (x);
return (code == IOR || code == XOR || code == AND);
}
/* Return TRUE for shift operators. */
int
shift_operator (rtx x,enum machine_mode mode)
{
enum rtx_code code;
if (GET_MODE (x) != mode)
return FALSE;
code = GET_CODE (x);
if (code == MULT)
return power_of_two_operand (XEXP (x, 1), mode);
return (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT
|| code == ROTATERT);
}
/* Return TRUE if x is EQ or NE. */
int
equality_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return GET_CODE (x) == EQ || GET_CODE (x) == NE;
}
/* Return TRUE if x is a comparison operator other than LTGT or UNEQ. */
int
arm_comparison_operator (rtx x, enum machine_mode mode)
{
return (comparison_operator (x, mode)
&& GET_CODE (x) != LTGT
&& GET_CODE (x) != UNEQ);
}
/* Return TRUE for SMIN SMAX UMIN UMAX operators. */
int
minmax_operator (rtx x, enum machine_mode mode)
{
enum rtx_code code = GET_CODE (x);
if (GET_MODE (x) != mode)
return FALSE;
return code == SMIN || code == SMAX || code == UMIN || code == UMAX;
}
/* Return TRUE if this is the condition code register, if we aren't given
a mode, accept any class CCmode register. */
int
cc_register (rtx x, enum machine_mode mode)
{
if (mode == VOIDmode)
{
mode = GET_MODE (x);
if (GET_MODE_CLASS (mode) != MODE_CC)
return FALSE;
}
if ( GET_MODE (x) == mode
&& GET_CODE (x) == REG
&& REGNO (x) == CC_REGNUM)
return TRUE;
return FALSE;
}
/* Return TRUE if this is the condition code register, if we aren't given
a mode, accept any class CCmode register which indicates a dominance
expression. */
int
dominant_cc_register (rtx x, enum machine_mode mode)
{
if (mode == VOIDmode)
{
mode = GET_MODE (x);
if (GET_MODE_CLASS (mode) != MODE_CC)
return FALSE;
}
if (mode != CC_DNEmode && mode != CC_DEQmode
&& mode != CC_DLEmode && mode != CC_DLTmode
&& mode != CC_DGEmode && mode != CC_DGTmode
&& mode != CC_DLEUmode && mode != CC_DLTUmode
&& mode != CC_DGEUmode && mode != CC_DGTUmode)
return FALSE;
return cc_register (x, mode);
}
/* Return TRUE if X references a SYMBOL_REF. */
int
symbol_mentioned_p (rtx x)
@ -5582,124 +5028,6 @@ adjacent_mem_locations (rtx a, rtx b)
return 0;
}
/* Return 1 if OP is a load multiple operation. It is known to be
parallel and the first section will be tested. */
int
load_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
HOST_WIDE_INT count = XVECLEN (op, 0);
int dest_regno;
rtx src_addr;
HOST_WIDE_INT i = 1, base = 0;
rtx elt;
if (count <= 1
|| GET_CODE (XVECEXP (op, 0, 0)) != SET)
return 0;
/* Check to see if this might be a write-back. */
if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
{
i++;
base = 1;
/* Now check it more carefully. */
if (GET_CODE (SET_DEST (elt)) != REG
|| GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
|| GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
|| INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
return 0;
}
/* Perform a quick check so we don't blow up below. */
if (count <= i
|| GET_CODE (XVECEXP (op, 0, i - 1)) != SET
|| GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG
|| GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != MEM)
return 0;
dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
for (; i < count; i++)
{
elt = XVECEXP (op, 0, i);
if (GET_CODE (elt) != SET
|| GET_CODE (SET_DEST (elt)) != REG
|| GET_MODE (SET_DEST (elt)) != SImode
|| REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base)
|| GET_CODE (SET_SRC (elt)) != MEM
|| GET_MODE (SET_SRC (elt)) != SImode
|| GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
|| !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)) != (i - base) * 4)
return 0;
}
return 1;
}
/* Return 1 if OP is a store multiple operation. It is known to be
parallel and the first section will be tested. */
int
store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
HOST_WIDE_INT count = XVECLEN (op, 0);
int src_regno;
rtx dest_addr;
HOST_WIDE_INT i = 1, base = 0;
rtx elt;
if (count <= 1
|| GET_CODE (XVECEXP (op, 0, 0)) != SET)
return 0;
/* Check to see if this might be a write-back. */
if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
{
i++;
base = 1;
/* Now check it more carefully. */
if (GET_CODE (SET_DEST (elt)) != REG
|| GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
|| GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
|| INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
return 0;
}
/* Perform a quick check so we don't blow up below. */
if (count <= i
|| GET_CODE (XVECEXP (op, 0, i - 1)) != SET
|| GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM
|| GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != REG)
return 0;
src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
for (; i < count; i++)
{
elt = XVECEXP (op, 0, i);
if (GET_CODE (elt) != SET
|| GET_CODE (SET_SRC (elt)) != REG
|| GET_MODE (SET_SRC (elt)) != SImode
|| REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base)
|| GET_CODE (SET_DEST (elt)) != MEM
|| GET_MODE (SET_DEST (elt)) != SImode
|| GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
|| !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
|| GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
|| INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4)
return 0;
}
return 1;
}
int
load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
HOST_WIDE_INT *load_offset)
@ -6106,17 +5434,6 @@ emit_stm_seq (rtx *operands, int nops)
return "";
}
int
multi_register_push (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) != PARALLEL
|| (GET_CODE (XVECEXP (op, 0, 0)) != SET)
|| (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC)
|| (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPEC_PUSH_MULT))
return 0;
return 1;
}
/* Routines for use in generating RTL. */
@ -9093,6 +8410,13 @@ shift_op (rtx op, HOST_WIDE_INT *amountp)
mnem = "lsr";
break;
case ROTATE:
if (*amountp == -1)
abort ();
*amountp = 32 - *amountp;
/* Fall through. */
case ROTATERT:
mnem = "ror";
break;
@ -14177,42 +13501,6 @@ thumb_expand_movmemqi (rtx *operands)
}
}
int
thumb_cmp_operand (rtx op, enum machine_mode mode)
{
return ((GET_CODE (op) == CONST_INT
&& INTVAL (op) < 256
&& INTVAL (op) >= 0)
|| s_register_operand (op, mode));
}
int
thumb_cmpneg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (GET_CODE (op) == CONST_INT
&& INTVAL (op) < 0
&& INTVAL (op) > -256);
}
/* Return TRUE if a result can be stored in OP without clobbering the
condition code register. Prior to reload we only accept a
register. After reload we have to be able to handle memory as
well, since a pseudo may not get a hard reg and reload cannot
handle output-reloads on jump insns.
We could possibly handle mem before reload as well, but that might
complicate things with the need to handle increment
side-effects. */
int
thumb_cbrch_target_operand (rtx op, enum machine_mode mode)
{
return (s_register_operand (op, mode)
|| ((reload_in_progress || reload_completed)
&& memory_operand (op, mode)));
}
/* Handle storing a half-word to memory during reload. */
void
thumb_reload_out_hi (rtx *operands)
{

View File

@ -2594,57 +2594,6 @@ extern int making_const_table;
: arm_gen_return_addr_mask ())
/* Define the codes that are matched by predicates in arm.c */
#define PREDICATE_CODES \
{"s_register_operand", {SUBREG, REG}}, \
{"arm_general_register_operand", {SUBREG, REG}}, \
{"arm_hard_register_operand", {REG}}, \
{"f_register_operand", {SUBREG, REG}}, \
{"arm_add_operand", {SUBREG, REG, CONST_INT}}, \
{"arm_addimm_operand", {CONST_INT}}, \
{"arm_float_add_operand", {SUBREG, REG, CONST_DOUBLE}}, \
{"arm_float_rhs_operand", {SUBREG, REG, CONST_DOUBLE}}, \
{"arm_rhs_operand", {SUBREG, REG, CONST_INT}}, \
{"arm_not_operand", {SUBREG, REG, CONST_INT}}, \
{"reg_or_int_operand", {SUBREG, REG, CONST_INT}}, \
{"index_operand", {SUBREG, REG, CONST_INT}}, \
{"thumb_cmp_operand", {SUBREG, REG, CONST_INT}}, \
{"thumb_cmpneg_operand", {CONST_INT}}, \
{"thumb_cbrch_target_operand", {SUBREG, REG, MEM}}, \
{"offsettable_memory_operand", {MEM}}, \
{"alignable_memory_operand", {MEM}}, \
{"shiftable_operator", {PLUS, MINUS, AND, IOR, XOR}}, \
{"minmax_operator", {SMIN, SMAX, UMIN, UMAX}}, \
{"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT, ROTATERT, MULT}}, \
{"di_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM}}, \
{"nonimmediate_di_operand", {SUBREG, REG, MEM}}, \
{"soft_df_operand", {SUBREG, REG, CONST_DOUBLE, MEM}}, \
{"nonimmediate_soft_df_operand", {SUBREG, REG, MEM}}, \
{"load_multiple_operation", {PARALLEL}}, \
{"store_multiple_operation", {PARALLEL}}, \
{"equality_operator", {EQ, NE}}, \
{"arm_comparison_operator", {EQ, NE, LE, LT, GE, GT, GEU, GTU, LEU, \
LTU, UNORDERED, ORDERED, UNLT, UNLE, \
UNGE, UNGT}}, \
{"arm_rhsm_operand", {SUBREG, REG, CONST_INT, MEM}}, \
{"const_shift_operand", {CONST_INT}}, \
{"multi_register_push", {PARALLEL}}, \
{"cc_register", {REG}}, \
{"logical_binary_operator", {AND, IOR, XOR}}, \
{"cirrus_register_operand", {REG}}, \
{"cirrus_fp_register", {REG}}, \
{"cirrus_shift_const", {CONST_INT}}, \
{"dominant_cc_register", {REG}}, \
{"arm_float_compare_operand", {REG, CONST_DOUBLE}}, \
{"vfp_compare_operand", {REG, CONST_DOUBLE}},
/* Define this if you have special predicates that know special things
about modes. Genrecog will warn about certain forms of
match_operand without a mode; if the operand predicate is listed in
SPECIAL_MODE_PREDICATES, the warning will be suppressed. */
#define SPECIAL_MODE_PREDICATES \
"cc_register", "dominant_cc_register",
enum arm_builtins
{
ARM_BUILTIN_GETWCX,

View File

@ -286,6 +286,8 @@
;; distant label. Only applicable to Thumb code.
(define_attr "far_jump" "yes,no" (const_string "no"))
(include "predicates.md")
;;---------------------------------------------------------------------------
;; Pipeline descriptions

View File

@ -0,0 +1,470 @@
;; Predicate definitions for ARM and Thumb
;; Copyright (C) 2004 Free Software Foundation, Inc.
;; Contributed by ARM Ltd.
;; 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.
(define_predicate "s_register_operand"
(match_code "reg,subreg")
{
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
/* We don't consider registers whose class is NO_REGS
to be a register operand. */
/* XXX might have to check for lo regs only for thumb ??? */
return (GET_CODE (op) == REG
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
})
;; Any hard register.
(define_predicate "arm_hard_register_operand"
(match_code "reg")
{
return REGNO (op) < FIRST_PSEUDO_REGISTER;
})
;; Any core register, or any pseudo. */
(define_predicate "arm_general_register_operand"
(match_code "reg,subreg")
{
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
return (GET_CODE (op) == REG
&& (REGNO (op) <= LAST_ARM_REGNUM
|| REGNO (op) >= FIRST_PSEUDO_REGISTER));
})
(define_predicate "f_register_operand"
(match_code "reg,subreg")
{
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
/* We don't consider registers whose class is NO_REGS
to be a register operand. */
return (GET_CODE (op) == REG
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) == FPA_REGS));
})
;; Reg, subreg(reg) or const_int.
(define_predicate "reg_or_int_operand"
(ior (match_code "const_int")
(match_operand 0 "s_register_operand")))
(define_predicate "arm_immediate_operand"
(and (match_code "const_int")
(match_test "const_ok_for_arm (INTVAL (op))")))
(define_predicate "arm_neg_immediate_operand"
(and (match_code "const_int")
(match_test "const_ok_for_arm (-INTVAL (op))")))
(define_predicate "arm_not_immediate_operand"
(and (match_code "const_int")
(match_test "const_ok_for_arm (~INTVAL (op))")))
;; Something valid on the RHS of an ARM data-processing instruction
(define_predicate "arm_rhs_operand"
(ior (match_operand 0 "s_register_operand")
(match_operand 0 "arm_immediate_operand")))
(define_predicate "arm_rhsm_operand"
(ior (match_operand 0 "arm_rhs_operand")
(match_operand 0 "memory_operand")))
(define_predicate "arm_add_operand"
(ior (match_operand 0 "arm_rhs_operand")
(match_operand 0 "arm_neg_immediate_operand")))
(define_predicate "arm_addimm_operand"
(ior (match_operand 0 "arm_immediate_operand")
(match_operand 0 "arm_neg_immediate_operand")))
(define_predicate "arm_not_operand"
(ior (match_operand 0 "arm_rhs_operand")
(match_operand 0 "arm_not_immediate_operand")))
;; True if the operand is a memory reference which contains an
;; offsettable address.
(define_predicate "offsettable_memory_operand"
(and (match_code "mem")
(match_test
"offsettable_address_p (reload_completed | reload_in_progress,
mode, XEXP (op, 0))")))
;; True if the operand is a memory reference which is, or can be made,
;; word aligned by adjusting the offset.
(define_predicate "alignable_memory_operand"
(match_code "mem")
{
rtx reg;
op = XEXP (op, 0);
return ((GET_CODE (reg = op) == REG
|| (GET_CODE (op) == SUBREG
&& GET_CODE (reg = SUBREG_REG (op)) == REG)
|| (GET_CODE (op) == PLUS
&& GET_CODE (XEXP (op, 1)) == CONST_INT
&& (GET_CODE (reg = XEXP (op, 0)) == REG
|| (GET_CODE (XEXP (op, 0)) == SUBREG
&& GET_CODE (reg = SUBREG_REG (XEXP (op, 0))) == REG))))
&& REGNO_POINTER_ALIGN (REGNO (reg)) >= 32);
})
(define_predicate "arm_reload_memory_operand"
(and (match_code "reg,subreg")
(match_test "(!CONSTANT_P (op)
&& (true_regnum(op) == -1
|| (GET_CODE (op) == REG
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)))")))
;; True for valid operands for the rhs of an floating point insns.
;; Allows regs or certain consts on FPA, just regs for everything else.
(define_predicate "arm_float_rhs_operand"
(ior (match_operand 0 "s_register_operand")
(and (match_code "const_double")
(match_test "TARGET_FPA && arm_const_double_rtx (op)"))))
(define_predicate "arm_float_add_operand"
(ior (match_operand 0 "arm_float_rhs_operand")
(and (match_code "const_double")
(match_test "TARGET_FPA && neg_const_double_rtx_ok_for_fpa (op)"))))
(define_predicate "vfp_compare_operand"
(ior (match_operand 0 "s_register_operand")
(and (match_code "const_double")
(match_test "arm_const_double_rtx (op)"))))
(define_predicate "arm_float_compare_operand"
(if_then_else (match_test "TARGET_VFP")
(match_operand 0 "vfp_compare_operand")
(match_operand 0 "arm_float_rhs_operand")))
;; True for valid index operands.
(define_predicate "index_operand"
(ior (match_operand 0 "s_register_operand")
(and (match_operand 0 "immediate_operand")
(match_test "(GET_CODE (op) != CONST_INT
|| (INTVAL (op) < 4096 && INTVAL (op) > -4096))"))))
;; True for operators that can be combined with a shift in ARM state.
(define_special_predicate "shiftable_operator"
(and (match_code "plus,minus,ior,xor,and")
(match_test "mode == GET_MODE (op)")))
;; True for logical binary opertors.
(define_special_predicate "logical_binary_operator"
(and (match_code "ior,xor,and")
(match_test "mode == GET_MODE (op)")))
;; True for shift operators.
(define_special_predicate "shift_operator"
(and (ior (ior (and (match_code "mult")
(match_test "power_of_two_operand (XEXP (op, 1), mode)"))
(and (match_code "rotate")
(match_test "GET_CODE (XEXP (op, 1)) == CONST_INT
&& ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32")))
(match_code "ashift,ashiftrt,lshiftrt,rotatert"))
(match_test "mode == GET_MODE (op)")))
;; True for EQ & NE
(define_special_predicate "equality_operator"
(match_code "eq,ne"))
;; True for comparisons other than LTGT or UNEQ.
(define_special_predicate "arm_comparison_operator"
(match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,unordered,ordered,unlt,unle,unge,ungt"))
(define_special_predicate "minmax_operator"
(and (match_code "smin,smax,umin,umax")
(match_test "mode == GET_MODE (op)")))
(define_special_predicate "cc_register"
(and (match_code "reg")
(and (match_test "REGNO (op) == CC_REGNUM")
(ior (match_test "mode == GET_MODE (op)")
(match_test "mode == VOIDmode && GET_MODE_CLASS (GET_MODE (op)) == MODE_CC")))))
(define_special_predicate "dominant_cc_register"
(match_code "reg")
{
if (mode == VOIDmode)
{
mode = GET_MODE (op);
if (GET_MODE_CLASS (mode) != MODE_CC)
return false;
}
return (cc_register (op, mode)
&& (mode == CC_DNEmode
|| mode == CC_DEQmode
|| mode == CC_DLEmode
|| mode == CC_DLTmode
|| mode == CC_DGEmode
|| mode == CC_DGTmode
|| mode == CC_DLEUmode
|| mode == CC_DLTUmode
|| mode == CC_DGEUmode
|| mode == CC_DGTUmode));
})
(define_special_predicate "arm_extendqisi_mem_op"
(and (match_operand 0 "memory_operand")
(match_test "arm_legitimate_address_p (mode, XEXP (op, 0), SIGN_EXTEND,
0)")))
(define_predicate "power_of_two_operand"
(match_code "const_int")
{
HOST_WIDE_INT value = INTVAL (op);
return value != 0 && (value & (value - 1)) == 0;
})
(define_predicate "nonimmediate_di_operand"
(match_code "reg,subreg,mem")
{
if (s_register_operand (op, mode))
return true;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
return GET_CODE (op) == MEM && memory_address_p (DImode, XEXP (op, 0));
})
(define_predicate "di_operand"
(ior (match_code "const_int,const_double")
(and (match_code "reg,subreg,mem")
(match_operand 0 "nonimmediate_di_operand"))))
(define_predicate "nonimmediate_soft_df_operand"
(match_code "reg,subreg,mem")
{
if (s_register_operand (op, mode))
return true;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
return GET_CODE (op) == MEM && memory_address_p (DFmode, XEXP (op, 0));
})
(define_predicate "soft_df_operand"
(ior (match_code "const_double")
(and (match_code "reg,subreg,mem")
(match_operand 0 "nonimmediate_soft_df_operand"))))
(define_predicate "const_shift_operand"
(and (match_code "const_int")
(ior (match_operand 0 "power_of_two_operand")
(match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 32"))))
(define_special_predicate "load_multiple_operation"
(match_code "parallel")
{
HOST_WIDE_INT count = XVECLEN (op, 0);
int dest_regno;
rtx src_addr;
HOST_WIDE_INT i = 1, base = 0;
rtx elt;
if (count <= 1
|| GET_CODE (XVECEXP (op, 0, 0)) != SET)
return false;
/* Check to see if this might be a write-back. */
if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
{
i++;
base = 1;
/* Now check it more carefully. */
if (GET_CODE (SET_DEST (elt)) != REG
|| GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
|| GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
|| INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
return false;
}
/* Perform a quick check so we don't blow up below. */
if (count <= i
|| GET_CODE (XVECEXP (op, 0, i - 1)) != SET
|| GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG
|| GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != MEM)
return false;
dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
for (; i < count; i++)
{
elt = XVECEXP (op, 0, i);
if (GET_CODE (elt) != SET
|| GET_CODE (SET_DEST (elt)) != REG
|| GET_MODE (SET_DEST (elt)) != SImode
|| REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base)
|| GET_CODE (SET_SRC (elt)) != MEM
|| GET_MODE (SET_SRC (elt)) != SImode
|| GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
|| !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)) != (i - base) * 4)
return false;
}
return true;
})
(define_special_predicate "store_multiple_operation"
(match_code "parallel")
{
HOST_WIDE_INT count = XVECLEN (op, 0);
int src_regno;
rtx dest_addr;
HOST_WIDE_INT i = 1, base = 0;
rtx elt;
if (count <= 1
|| GET_CODE (XVECEXP (op, 0, 0)) != SET)
return false;
/* Check to see if this might be a write-back. */
if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
{
i++;
base = 1;
/* Now check it more carefully. */
if (GET_CODE (SET_DEST (elt)) != REG
|| GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
|| GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
|| INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
return false;
}
/* Perform a quick check so we don't blow up below. */
if (count <= i
|| GET_CODE (XVECEXP (op, 0, i - 1)) != SET
|| GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM
|| GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != REG)
return false;
src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
for (; i < count; i++)
{
elt = XVECEXP (op, 0, i);
if (GET_CODE (elt) != SET
|| GET_CODE (SET_SRC (elt)) != REG
|| GET_MODE (SET_SRC (elt)) != SImode
|| REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base)
|| GET_CODE (SET_DEST (elt)) != MEM
|| GET_MODE (SET_DEST (elt)) != SImode
|| GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
|| !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
|| GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
|| INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4)
return false;
}
return true;
})
(define_special_predicate "multi_register_push"
(match_code "parallel")
{
if ((GET_CODE (XVECEXP (op, 0, 0)) != SET)
|| (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC)
|| (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPEC_PUSH_MULT))
return false;
return true;
})
;;-------------------------------------------------------------------------
;;
;; Thumb predicates
;;
(define_predicate "thumb_cmp_operand"
(ior (and (match_code "reg,subreg")
(match_operand 0 "s_register_operand"))
(and (match_code "const_int")
(match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 256"))))
(define_predicate "thumb_cmpneg_operand"
(and (match_code "const_int")
(match_test "INTVAL (op) < 0 && INTVAL (op) > -256")))
;; Return TRUE if a result can be stored in OP without clobbering the
;; condition code register. Prior to reload we only accept a
;; register. After reload we have to be able to handle memory as
;; well, since a pseudo may not get a hard reg and reload cannot
;; handle output-reloads on jump insns.
;; We could possibly handle mem before reload as well, but that might
;; complicate things with the need to handle increment
;; side-effects.
(define_predicate "thumb_cbrch_target_operand"
(and (match_code "reg,subreg,mem")
(ior (match_operand 0 "s_register_operand")
(and (match_test "reload_in_progress || reload_completed")
(match_operand 0 "memory_operand")))))
;;-------------------------------------------------------------------------
;;
;; MAVERICK predicates
;;
(define_predicate "cirrus_register_operand"
(match_code "reg,subreg")
{
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
return (GET_CODE (op) == REG
&& (REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS
|| REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS));
})
(define_predicate "cirrus_fp_register"
(match_code "reg,subreg")
{
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
return (GET_CODE (op) == REG
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS));
})
(define_predicate "cirrus_shift_const"
(and (match_code "const_int")
(match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 64")))

View File

@ -1,6 +1,7 @@
# Rules common to all arm targets
MD_INCLUDES= $(srcdir)/config/arm/arm-tune.md \
$(srcdir)/config/arm/predicates.md \
$(srcdir)/config/arm/arm-generic.md \
$(srcdir)/config/arm/arm1026ejs.md \
$(srcdir)/config/arm/arm1136jfs.md \
@ -10,7 +11,7 @@ MD_INCLUDES= $(srcdir)/config/arm/arm-tune.md \
$(srcdir)/config/arm/iwmmxt.md \
$(srcdir)/config/arm/vfp.md
s-config s-conditions s-flags s-codes s-constants s-emit s-recog \
s-config s-conditions s-flags s-codes s-constants s-emit s-recog s-preds \
s-opinit s-extract s-peep s-attr s-attrtab s-output: $(MD_INCLUDES)
$(srcdir)/config/arm/arm-tune.md: $(srcdir)/config/arm/gentune.sh \