* 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
+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.
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);
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);
\f
/* 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)
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. */
}
-/* 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. */
}
}
-/* 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)
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)
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;
-}
\f
/* Routines for use in generating RTL. */
mnem = "lsr";
break;
+ case ROTATE:
+ if (*amountp == -1)
+ abort ();
+ *amountp = 32 - *amountp;
+
+ /* Fall through. */
+
case ROTATERT:
mnem = "ror";
break;
}
}
-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)
{
: arm_gen_return_addr_mask ())
\f
-/* 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,
;; distant label. Only applicable to Thumb code.
(define_attr "far_jump" "yes,no" (const_string "no"))
+(include "predicates.md")
+
;;---------------------------------------------------------------------------
;; Pipeline descriptions
--- /dev/null
+;; 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")))
+
+
# 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 \
$(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 \