From 9c9db02569e45024ab2ceb8a08fb2fd288731c99 Mon Sep 17 00:00:00 2001 From: rearnsha Date: Tue, 24 Aug 2004 20:16:41 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@86512 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 29 ++ gcc/config/arm/arm-protos.h | 43 --- gcc/config/arm/arm.c | 726 +------------------------------------------ gcc/config/arm/arm.h | 51 --- gcc/config/arm/arm.md | 2 + gcc/config/arm/predicates.md | 470 ++++++++++++++++++++++++++++ gcc/config/arm/t-arm | 3 +- 7 files changed, 510 insertions(+), 814 deletions(-) create mode 100644 gcc/config/arm/predicates.md diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 31adda24fe3..71573960708 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2004-08-24 Richard Earnshaw + + * 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 * config/mips/mips.c (mips_gen_conditional_trap): Fix mode. diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index efe12074a17..7a75002ffec 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -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); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index f2f167c5501..ce9a27c231a 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -4624,243 +4624,6 @@ neg_const_double_rtx_ok_for_fpa (rtx x) /* Predicates for `match_operand' and `match_operator'. */ -/* s_register_operand is the same as register_operand, but it doesn't accept - (SUBREG (MEM)...). - - This function exists because at the time it was put in it led to better - code. SUBREG(MEM) always needs a reload in the places where - s_register_operand is used, and this seemed to lead to excessive - reloading. */ -int -s_register_operand (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return 0; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - /* We don't consider registers whose class is NO_REGS - to be a register operand. */ - /* XXX might have to check for lo regs only for thumb ??? */ - return (GET_CODE (op) == REG - && (REGNO (op) >= FIRST_PSEUDO_REGISTER - || REGNO_REG_CLASS (REGNO (op)) != NO_REGS)); -} - -/* A hard register operand (even before reload. */ -int -arm_hard_register_operand (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return 0; - - return (GET_CODE (op) == REG - && REGNO (op) < FIRST_PSEUDO_REGISTER); -} - -/* An arm register operand. */ -int -arm_general_register_operand (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return 0; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - return (GET_CODE (op) == REG - && (REGNO (op) <= LAST_ARM_REGNUM - || REGNO (op) >= FIRST_PSEUDO_REGISTER)); -} - -/* Only accept reg, subreg(reg), const_int. */ -int -reg_or_int_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == CONST_INT) - return 1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return 0; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - /* We don't consider registers whose class is NO_REGS - to be a register operand. */ - return (GET_CODE (op) == REG - && (REGNO (op) >= FIRST_PSEUDO_REGISTER - || REGNO_REG_CLASS (REGNO (op)) != NO_REGS)); -} - -/* Return 1 if OP is an item in memory, given that we are in reload. */ -int -arm_reload_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int regno = true_regnum (op); - - return (!CONSTANT_P (op) - && (regno == -1 - || (GET_CODE (op) == REG - && REGNO (op) >= FIRST_PSEUDO_REGISTER))); -} - -/* Return TRUE for valid operands for the rhs of an ARM instruction. */ -int -arm_rhs_operand (rtx op, enum machine_mode mode) -{ - return (s_register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op)))); -} - -/* Return TRUE for valid operands for the - rhs of an ARM instruction, or a load. */ -int -arm_rhsm_operand (rtx op, enum machine_mode mode) -{ - return (s_register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op))) - || memory_operand (op, mode)); -} - -/* Return TRUE for valid operands for the rhs of an ARM instruction, or if a - constant that is valid when negated. */ -int -arm_add_operand (rtx op, enum machine_mode mode) -{ - if (TARGET_THUMB) - return thumb_cmp_operand (op, mode); - - return (s_register_operand (op, mode) - || (GET_CODE (op) == CONST_INT - && (const_ok_for_arm (INTVAL (op)) - || const_ok_for_arm (-INTVAL (op))))); -} - -/* Return TRUE for valid ARM constants (or when valid if negated). */ -int -arm_addimm_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT - && (const_ok_for_arm (INTVAL (op)) - || const_ok_for_arm (-INTVAL (op)))); -} - -int -arm_not_operand (rtx op, enum machine_mode mode) -{ - return (s_register_operand (op, mode) - || (GET_CODE (op) == CONST_INT - && (const_ok_for_arm (INTVAL (op)) - || const_ok_for_arm (~INTVAL (op))))); -} - -/* Return TRUE if the operand is a memory reference which contains an - offsettable address. */ -int -offsettable_memory_operand (rtx op, enum machine_mode mode) -{ - if (mode == VOIDmode) - mode = GET_MODE (op); - - return (mode == GET_MODE (op) - && GET_CODE (op) == MEM - && offsettable_address_p (reload_completed | reload_in_progress, - mode, XEXP (op, 0))); -} - -/* Return TRUE if the operand is a memory reference which is, or can be - made word aligned by adjusting the offset. */ -int -alignable_memory_operand (rtx op, enum machine_mode mode) -{ - rtx reg; - - if (mode == VOIDmode) - mode = GET_MODE (op); - - if (mode != GET_MODE (op) || GET_CODE (op) != MEM) - return 0; - - op = XEXP (op, 0); - - return ((GET_CODE (reg = op) == REG - || (GET_CODE (op) == SUBREG - && GET_CODE (reg = SUBREG_REG (op)) == REG) - || (GET_CODE (op) == PLUS - && GET_CODE (XEXP (op, 1)) == CONST_INT - && (GET_CODE (reg = XEXP (op, 0)) == REG - || (GET_CODE (XEXP (op, 0)) == SUBREG - && GET_CODE (reg = SUBREG_REG (XEXP (op, 0))) == REG)))) - && REGNO_POINTER_ALIGN (REGNO (reg)) >= 32); -} - -/* Similar to s_register_operand, but does not allow hard integer - registers. */ -int -f_register_operand (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return 0; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - /* We don't consider registers whose class is NO_REGS - to be a register operand. */ - return (GET_CODE (op) == REG - && (REGNO (op) >= FIRST_PSEUDO_REGISTER - || REGNO_REG_CLASS (REGNO (op)) == FPA_REGS)); -} - -/* Return TRUE for valid operands for the rhs of an floating point insns. - Allows regs or certain consts on FPA, just regs for everything else. */ -int -arm_float_rhs_operand (rtx op, enum machine_mode mode) -{ - if (s_register_operand (op, mode)) - return TRUE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (TARGET_FPA && GET_CODE (op) == CONST_DOUBLE) - return arm_const_double_rtx (op); - - return FALSE; -} - -int -arm_float_add_operand (rtx op, enum machine_mode mode) -{ - if (s_register_operand (op, mode)) - return TRUE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (TARGET_FPA && GET_CODE (op) == CONST_DOUBLE) - return (arm_const_double_rtx (op) - || neg_const_double_rtx_ok_for_fpa (op)); - - return FALSE; -} - - -/* Return TRUE if OP is suitable for the rhs of a floating point comparison. - Depends which fpu we are targeting. */ - -int -arm_float_compare_operand (rtx op, enum machine_mode mode) -{ - if (TARGET_VFP) - return vfp_compare_operand (op, mode); - else - return arm_float_rhs_operand (op, mode); -} - - /* Return nonzero if OP is a valid Cirrus memory address pattern. */ int cirrus_memory_offset (rtx op) @@ -4898,55 +4661,6 @@ cirrus_memory_offset (rtx op) return 0; } -int -arm_extendqisi_mem_op (rtx op, enum machine_mode mode) -{ - if (!memory_operand (op, mode)) - return 0; - - return arm_legitimate_address_p (mode, XEXP (op, 0), SIGN_EXTEND, 0); -} - -/* Return nonzero if OP is a Cirrus or general register. */ -int -cirrus_register_operand (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - return (GET_CODE (op) == REG - && (REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS - || REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS)); -} - -/* Return nonzero if OP is a cirrus FP register. */ -int -cirrus_fp_register (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - return (GET_CODE (op) == REG - && (REGNO (op) >= FIRST_PSEUDO_REGISTER - || REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS)); -} - -/* Return nonzero if OP is a 6bit constant (0..63). */ -int -cirrus_shift_const (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT - && INTVAL (op) >= 0 - && INTVAL (op) < 64); -} - - /* Return TRUE if OP is a valid VFP memory address pattern. WB if true if writeback address modes are allowed. */ @@ -5014,18 +4728,6 @@ arm_coproc_mem_operand (rtx op, bool wb) } -/* Return TRUE if OP is a REG or constant zero. */ -int -vfp_compare_operand (rtx op, enum machine_mode mode) -{ - if (s_register_operand (op, mode)) - return TRUE; - - return (GET_CODE (op) == CONST_DOUBLE - && arm_const_double_rtx (op)); -} - - /* Return GENERAL_REGS if a scratch register required to reload x to/from VFP registers. Otherwise return NO_REGS. */ @@ -5211,262 +4913,6 @@ cirrus_reorg (rtx first) } } -/* Return nonzero if OP is a constant power of two. */ -int -power_of_two_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (op); - - return value != 0 && (value & (value - 1)) == 0; - } - - return FALSE; -} - -/* Return TRUE for a valid operand of a DImode operation. - Either: REG, SUBREG, CONST_DOUBLE or MEM(DImode_address). - Note that this disallows MEM(REG+REG), but allows - MEM(PRE/POST_INC/DEC(REG)). */ -int -di_operand (rtx op, enum machine_mode mode) -{ - if (s_register_operand (op, mode)) - return TRUE; - - if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - switch (GET_CODE (op)) - { - case CONST_DOUBLE: - case CONST_INT: - return TRUE; - - case MEM: - return memory_address_p (DImode, XEXP (op, 0)); - - default: - return FALSE; - } -} - -/* Like di_operand, but don't accept constants. */ -int -nonimmediate_di_operand (rtx op, enum machine_mode mode) -{ - if (s_register_operand (op, mode)) - return TRUE; - - if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) == MEM) - return memory_address_p (DImode, XEXP (op, 0)); - - return FALSE; -} - -/* Return TRUE for a valid operand of a DFmode operation when soft-float. - Either: REG, SUBREG, CONST_DOUBLE or MEM(DImode_address). - Note that this disallows MEM(REG+REG), but allows - MEM(PRE/POST_INC/DEC(REG)). */ -int -soft_df_operand (rtx op, enum machine_mode mode) -{ - if (s_register_operand (op, mode)) - return TRUE; - - if (mode != VOIDmode && GET_MODE (op) != mode) - return FALSE; - - if (GET_CODE (op) == SUBREG && CONSTANT_P (SUBREG_REG (op))) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - switch (GET_CODE (op)) - { - case CONST_DOUBLE: - return TRUE; - - case MEM: - return memory_address_p (DFmode, XEXP (op, 0)); - - default: - return FALSE; - } -} - -/* Like soft_df_operand, but don't accept constants. */ -int -nonimmediate_soft_df_operand (rtx op, enum machine_mode mode) -{ - if (s_register_operand (op, mode)) - return TRUE; - - if (mode != VOIDmode && GET_MODE (op) != mode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) == MEM) - return memory_address_p (DFmode, XEXP (op, 0)); - return FALSE; -} - -/* Return TRUE for valid index operands. */ -int -index_operand (rtx op, enum machine_mode mode) -{ - return (s_register_operand (op, mode) - || (immediate_operand (op, mode) - && (GET_CODE (op) != CONST_INT - || (INTVAL (op) < 4096 && INTVAL (op) > -4096)))); -} - -/* Return TRUE for valid shifts by a constant. This also accepts any - power of two on the (somewhat overly relaxed) assumption that the - shift operator in this case was a mult. */ -int -const_shift_operand (rtx op, enum machine_mode mode) -{ - return (power_of_two_operand (op, mode) - || (immediate_operand (op, mode) - && (GET_CODE (op) != CONST_INT - || (INTVAL (op) < 32 && INTVAL (op) > 0)))); -} - -/* Return TRUE for arithmetic operators which can be combined with a multiply - (shift). */ -int -shiftable_operator (rtx x, enum machine_mode mode) -{ - enum rtx_code code; - - if (GET_MODE (x) != mode) - return FALSE; - - code = GET_CODE (x); - - return (code == PLUS || code == MINUS - || code == IOR || code == XOR || code == AND); -} - -/* Return TRUE for binary logical operators. */ -int -logical_binary_operator (rtx x, enum machine_mode mode) -{ - enum rtx_code code; - - if (GET_MODE (x) != mode) - return FALSE; - - code = GET_CODE (x); - - return (code == IOR || code == XOR || code == AND); -} - -/* Return TRUE for shift operators. */ -int -shift_operator (rtx x,enum machine_mode mode) -{ - enum rtx_code code; - - if (GET_MODE (x) != mode) - return FALSE; - - code = GET_CODE (x); - - if (code == MULT) - return power_of_two_operand (XEXP (x, 1), mode); - - return (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT - || code == ROTATERT); -} - -/* Return TRUE if x is EQ or NE. */ -int -equality_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return GET_CODE (x) == EQ || GET_CODE (x) == NE; -} - -/* Return TRUE if x is a comparison operator other than LTGT or UNEQ. */ -int -arm_comparison_operator (rtx x, enum machine_mode mode) -{ - return (comparison_operator (x, mode) - && GET_CODE (x) != LTGT - && GET_CODE (x) != UNEQ); -} - -/* Return TRUE for SMIN SMAX UMIN UMAX operators. */ -int -minmax_operator (rtx x, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (x); - - if (GET_MODE (x) != mode) - return FALSE; - - return code == SMIN || code == SMAX || code == UMIN || code == UMAX; -} - -/* Return TRUE if this is the condition code register, if we aren't given - a mode, accept any class CCmode register. */ -int -cc_register (rtx x, enum machine_mode mode) -{ - if (mode == VOIDmode) - { - mode = GET_MODE (x); - - if (GET_MODE_CLASS (mode) != MODE_CC) - return FALSE; - } - - if ( GET_MODE (x) == mode - && GET_CODE (x) == REG - && REGNO (x) == CC_REGNUM) - return TRUE; - - return FALSE; -} - -/* Return TRUE if this is the condition code register, if we aren't given - a mode, accept any class CCmode register which indicates a dominance - expression. */ -int -dominant_cc_register (rtx x, enum machine_mode mode) -{ - if (mode == VOIDmode) - { - mode = GET_MODE (x); - - if (GET_MODE_CLASS (mode) != MODE_CC) - return FALSE; - } - - if (mode != CC_DNEmode && mode != CC_DEQmode - && mode != CC_DLEmode && mode != CC_DLTmode - && mode != CC_DGEmode && mode != CC_DGTmode - && mode != CC_DLEUmode && mode != CC_DLTUmode - && mode != CC_DGEUmode && mode != CC_DGTUmode) - return FALSE; - - return cc_register (x, mode); -} - /* Return TRUE if X references a SYMBOL_REF. */ int symbol_mentioned_p (rtx x) @@ -5582,124 +5028,6 @@ adjacent_mem_locations (rtx a, rtx b) return 0; } -/* Return 1 if OP is a load multiple operation. It is known to be - parallel and the first section will be tested. */ -int -load_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - HOST_WIDE_INT count = XVECLEN (op, 0); - int dest_regno; - rtx src_addr; - HOST_WIDE_INT i = 1, base = 0; - rtx elt; - - if (count <= 1 - || GET_CODE (XVECEXP (op, 0, 0)) != SET) - return 0; - - /* Check to see if this might be a write-back. */ - if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS) - { - i++; - base = 1; - - /* Now check it more carefully. */ - if (GET_CODE (SET_DEST (elt)) != REG - || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG - || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT - || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4) - return 0; - } - - /* Perform a quick check so we don't blow up below. */ - if (count <= i - || GET_CODE (XVECEXP (op, 0, i - 1)) != SET - || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG - || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != MEM) - return 0; - - dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1))); - src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0); - - for (; i < count; i++) - { - elt = XVECEXP (op, 0, i); - - if (GET_CODE (elt) != SET - || GET_CODE (SET_DEST (elt)) != REG - || GET_MODE (SET_DEST (elt)) != SImode - || REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base) - || GET_CODE (SET_SRC (elt)) != MEM - || GET_MODE (SET_SRC (elt)) != SImode - || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS - || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) - || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT - || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != (i - base) * 4) - return 0; - } - - return 1; -} - -/* Return 1 if OP is a store multiple operation. It is known to be - parallel and the first section will be tested. */ -int -store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - HOST_WIDE_INT count = XVECLEN (op, 0); - int src_regno; - rtx dest_addr; - HOST_WIDE_INT i = 1, base = 0; - rtx elt; - - if (count <= 1 - || GET_CODE (XVECEXP (op, 0, 0)) != SET) - return 0; - - /* Check to see if this might be a write-back. */ - if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS) - { - i++; - base = 1; - - /* Now check it more carefully. */ - if (GET_CODE (SET_DEST (elt)) != REG - || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG - || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT - || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4) - return 0; - } - - /* Perform a quick check so we don't blow up below. */ - if (count <= i - || GET_CODE (XVECEXP (op, 0, i - 1)) != SET - || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM - || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != REG) - return 0; - - src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1))); - dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0); - - for (; i < count; i++) - { - elt = XVECEXP (op, 0, i); - - if (GET_CODE (elt) != SET - || GET_CODE (SET_SRC (elt)) != REG - || GET_MODE (SET_SRC (elt)) != SImode - || REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base) - || GET_CODE (SET_DEST (elt)) != MEM - || GET_MODE (SET_DEST (elt)) != SImode - || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS - || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) - || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT - || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4) - return 0; - } - - return 1; -} - int load_multiple_sequence (rtx *operands, int nops, int *regs, int *base, HOST_WIDE_INT *load_offset) @@ -6106,17 +5434,6 @@ emit_stm_seq (rtx *operands, int nops) return ""; } -int -multi_register_push (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) != PARALLEL - || (GET_CODE (XVECEXP (op, 0, 0)) != SET) - || (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC) - || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPEC_PUSH_MULT)) - return 0; - - return 1; -} /* Routines for use in generating RTL. */ @@ -9093,6 +8410,13 @@ shift_op (rtx op, HOST_WIDE_INT *amountp) mnem = "lsr"; break; + case ROTATE: + if (*amountp == -1) + abort (); + *amountp = 32 - *amountp; + + /* Fall through. */ + case ROTATERT: mnem = "ror"; break; @@ -14177,42 +13501,6 @@ thumb_expand_movmemqi (rtx *operands) } } -int -thumb_cmp_operand (rtx op, enum machine_mode mode) -{ - return ((GET_CODE (op) == CONST_INT - && INTVAL (op) < 256 - && INTVAL (op) >= 0) - || s_register_operand (op, mode)); -} - -int -thumb_cmpneg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT - && INTVAL (op) < 0 - && INTVAL (op) > -256); -} - -/* Return TRUE if a result can be stored in OP without clobbering the - condition code register. Prior to reload we only accept a - register. After reload we have to be able to handle memory as - well, since a pseudo may not get a hard reg and reload cannot - handle output-reloads on jump insns. - - We could possibly handle mem before reload as well, but that might - complicate things with the need to handle increment - side-effects. */ - -int -thumb_cbrch_target_operand (rtx op, enum machine_mode mode) -{ - return (s_register_operand (op, mode) - || ((reload_in_progress || reload_completed) - && memory_operand (op, mode))); -} - -/* Handle storing a half-word to memory during reload. */ void thumb_reload_out_hi (rtx *operands) { diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 0ba70f9b923..23e72ab184d 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -2594,57 +2594,6 @@ extern int making_const_table; : arm_gen_return_addr_mask ()) -/* Define the codes that are matched by predicates in arm.c */ -#define PREDICATE_CODES \ - {"s_register_operand", {SUBREG, REG}}, \ - {"arm_general_register_operand", {SUBREG, REG}}, \ - {"arm_hard_register_operand", {REG}}, \ - {"f_register_operand", {SUBREG, REG}}, \ - {"arm_add_operand", {SUBREG, REG, CONST_INT}}, \ - {"arm_addimm_operand", {CONST_INT}}, \ - {"arm_float_add_operand", {SUBREG, REG, CONST_DOUBLE}}, \ - {"arm_float_rhs_operand", {SUBREG, REG, CONST_DOUBLE}}, \ - {"arm_rhs_operand", {SUBREG, REG, CONST_INT}}, \ - {"arm_not_operand", {SUBREG, REG, CONST_INT}}, \ - {"reg_or_int_operand", {SUBREG, REG, CONST_INT}}, \ - {"index_operand", {SUBREG, REG, CONST_INT}}, \ - {"thumb_cmp_operand", {SUBREG, REG, CONST_INT}}, \ - {"thumb_cmpneg_operand", {CONST_INT}}, \ - {"thumb_cbrch_target_operand", {SUBREG, REG, MEM}}, \ - {"offsettable_memory_operand", {MEM}}, \ - {"alignable_memory_operand", {MEM}}, \ - {"shiftable_operator", {PLUS, MINUS, AND, IOR, XOR}}, \ - {"minmax_operator", {SMIN, SMAX, UMIN, UMAX}}, \ - {"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT, ROTATERT, MULT}}, \ - {"di_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM}}, \ - {"nonimmediate_di_operand", {SUBREG, REG, MEM}}, \ - {"soft_df_operand", {SUBREG, REG, CONST_DOUBLE, MEM}}, \ - {"nonimmediate_soft_df_operand", {SUBREG, REG, MEM}}, \ - {"load_multiple_operation", {PARALLEL}}, \ - {"store_multiple_operation", {PARALLEL}}, \ - {"equality_operator", {EQ, NE}}, \ - {"arm_comparison_operator", {EQ, NE, LE, LT, GE, GT, GEU, GTU, LEU, \ - LTU, UNORDERED, ORDERED, UNLT, UNLE, \ - UNGE, UNGT}}, \ - {"arm_rhsm_operand", {SUBREG, REG, CONST_INT, MEM}}, \ - {"const_shift_operand", {CONST_INT}}, \ - {"multi_register_push", {PARALLEL}}, \ - {"cc_register", {REG}}, \ - {"logical_binary_operator", {AND, IOR, XOR}}, \ - {"cirrus_register_operand", {REG}}, \ - {"cirrus_fp_register", {REG}}, \ - {"cirrus_shift_const", {CONST_INT}}, \ - {"dominant_cc_register", {REG}}, \ - {"arm_float_compare_operand", {REG, CONST_DOUBLE}}, \ - {"vfp_compare_operand", {REG, CONST_DOUBLE}}, - -/* Define this if you have special predicates that know special things - about modes. Genrecog will warn about certain forms of - match_operand without a mode; if the operand predicate is listed in - SPECIAL_MODE_PREDICATES, the warning will be suppressed. */ -#define SPECIAL_MODE_PREDICATES \ - "cc_register", "dominant_cc_register", - enum arm_builtins { ARM_BUILTIN_GETWCX, diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index e6e72db9525..08d62e95a5a 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -286,6 +286,8 @@ ;; distant label. Only applicable to Thumb code. (define_attr "far_jump" "yes,no" (const_string "no")) +(include "predicates.md") + ;;--------------------------------------------------------------------------- ;; Pipeline descriptions diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md new file mode 100644 index 00000000000..ed438026f01 --- /dev/null +++ b/gcc/config/arm/predicates.md @@ -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"))) + + diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm index 4f801ce939a..21cab03cf6e 100644 --- a/gcc/config/arm/t-arm +++ b/gcc/config/arm/t-arm @@ -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 \ -- 2.11.0