OSDN Git Service

* arm.md: Include predicates.md.
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 Aug 2004 20:16:41 +0000 (20:16 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 Aug 2004 20:16:41 +0000 (20:16 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@86512 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/arm/arm.md
gcc/config/arm/predicates.md [new file with mode: 0644]
gcc/config/arm/t-arm

index 31adda2..7157396 100644 (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.
index efe1207..7a75002 100644 (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);
index f2f167c..ce9a27c 100644 (file)
@@ -4624,243 +4624,6 @@ neg_const_double_rtx_ok_for_fpa (rtx x)
 \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)
@@ -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;
-}
 \f
 /* 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)
 {
index 0ba70f9..23e72ab 100644 (file)
@@ -2594,57 +2594,6 @@ extern int making_const_table;
    : 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,
index e6e72db..08d62e9 100644 (file)
 ;; distant label.  Only applicable to Thumb code.
 (define_attr "far_jump" "yes,no" (const_string "no"))
 
+(include "predicates.md")
+
 ;;---------------------------------------------------------------------------
 ;; Pipeline descriptions
 
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
new file mode 100644 (file)
index 0000000..ed43802
--- /dev/null
@@ -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")))
+
+
index 4f801ce..21cab03 100644 (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 \