diff options
author | Kazu Hirata <kazu@cs.umass.edu> | 2005-03-18 18:10:48 +0000 |
---|---|---|
committer | Kazu Hirata <kazu@gcc.gnu.org> | 2005-03-18 18:10:48 +0000 |
commit | c9a881907525e22505d63851ccda7e15ebbee104 (patch) | |
tree | 1ce65784d75bd4e965b457946948ee55cffd03fe | |
parent | 22a14e0dccd8e24ace4f1c617e47c96d2d69bba6 (diff) | |
download | gcc-c9a881907525e22505d63851ccda7e15ebbee104.zip gcc-c9a881907525e22505d63851ccda7e15ebbee104.tar.gz gcc-c9a881907525e22505d63851ccda7e15ebbee104.tar.bz2 |
pa-protos.h: Add prototypes for magic_milli and shadd_constant_p.
* config/pa/pa-protos.h: Add prototypes for magic_milli and
shadd_constant_p.
* config/pa/pa.c (reg_or_0_operand, call_operand_address,
symbolic_operand, symbolic_memory_operand,
reg_or_0_or_nonsymb_mem_operand, reg_before_reload_operand,
indexed_memory_operand, move_dest_operand, move_src_operand,
prefetch_cc_operand, prefetch_nocc_operand,
reg_or_cint_move_operand, pic_label_operand, fp_reg_operand,
arith_operand, arith11_operand, pre_cint_operand,
post_cint_operan, arith_double_operand, ireg_or_int5_operand,
ireg_operand, int5_operand, uint5_operand, int11_operand,
uint32_operand, arith5_operand, and_operand, ior_operand,
lhs_lshift_operand, lhs_lshift_cint_operand, arith32_operand,
pc_or_label_operand, div_operand, plus_xor_ior_operator,
shadd_operand, movb_comparison_operator,
cmpib_comparison_operator): Move to predicates.md.
(magic_milli, shadd_constant_p): Make it extern.
* config/pa/pa.h (PREDICATE_CODES): Remove.
* config/pa/pa.md: Include predicates.md.
* config/pa/predicates.md: New.
From-SVN: r96692
-rw-r--r-- | gcc/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/config/pa/pa-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/pa/pa.c | 489 | ||||
-rw-r--r-- | gcc/config/pa/pa.h | 43 | ||||
-rw-r--r-- | gcc/config/pa/pa.md | 2 | ||||
-rw-r--r-- | gcc/config/pa/predicates.md | 550 |
6 files changed, 578 insertions, 532 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6adc260..395ecce 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,4 @@ -2005-03-18 2005-03-18 Kazu Hirata <kazu@cs.umass.edu> +2005-03-18 Kazu Hirata <kazu@cs.umass.edu> * config/m32r/m32r-protos.h: Remove the prototypes for call_address_operand, symbolic_operand, seth_add3_operand, @@ -26,6 +26,27 @@ * config/m32r/m32r.md: Include predicates.md. * config/m32r/predicates.md: New. + * config/pa/pa-protos.h: Add prototypes for magic_milli and + shadd_constant_p. + * config/pa/pa.c (reg_or_0_operand, call_operand_address, + symbolic_operand, symbolic_memory_operand, + reg_or_0_or_nonsymb_mem_operand, reg_before_reload_operand, + indexed_memory_operand, move_dest_operand, move_src_operand, + prefetch_cc_operand, prefetch_nocc_operand, + reg_or_cint_move_operand, pic_label_operand, fp_reg_operand, + arith_operand, arith11_operand, pre_cint_operand, + post_cint_operan, arith_double_operand, ireg_or_int5_operand, + ireg_operand, int5_operand, uint5_operand, int11_operand, + uint32_operand, arith5_operand, and_operand, ior_operand, + lhs_lshift_operand, lhs_lshift_cint_operand, arith32_operand, + pc_or_label_operand, div_operand, plus_xor_ior_operator, + shadd_operand, movb_comparison_operator, + cmpib_comparison_operator): Move to predicates.md. + (magic_milli, shadd_constant_p): Make it extern. + * config/pa/pa.h (PREDICATE_CODES): Remove. + * config/pa/pa.md: Include predicates.md. + * config/pa/predicates.md: New. + 2005-03-18 Kazu Hirata <kazu@cs.umass.edu> * hooks.c, hooks.h, intl.c, opts.h, prefix.c, tree-gimple.c, diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h index 065433a..87bb7f2 100644 --- a/gcc/config/pa/pa-protos.h +++ b/gcc/config/pa/pa-protos.h @@ -176,6 +176,9 @@ extern void pa_asm_output_aligned_local (FILE *, const char *, unsigned int); extern void pa_hpux_asm_output_external (FILE *, tree, const char *); +extern const int magic_milli[]; +extern int shadd_constant_p (int); + /* Functions in varasm.c used by pa.c. */ extern void som_readonly_data_section (void); extern void som_one_only_readonly_data_section (void); diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index fce8c8c..70484c2 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -91,7 +91,6 @@ static void pa_reorg (void); static void pa_combine_instructions (void); static int pa_can_combine_p (rtx, rtx, rtx, int, rtx, rtx, rtx); static int forward_branch_p (rtx); -static int shadd_constant_p (int); static void compute_zdepwi_operands (unsigned HOST_WIDE_INT, unsigned *); static int compute_movmem_length (rtx); static int compute_clrmem_length (rtx); @@ -550,26 +549,6 @@ copy_reg_pointer (rtx to, rtx from) mark_reg_pointer (to, REGNO_POINTER_ALIGN (REGNO (from))); } -/* Return nonzero only if OP is a register of mode MODE, - or CONST0_RTX. */ -int -reg_or_0_operand (rtx op, enum machine_mode mode) -{ - return (op == CONST0_RTX (mode) || register_operand (op, mode)); -} - -/* Return nonzero if OP is suitable for use in a call to a named - function. - - For 2.5 try to eliminate either call_operand_address or - function_label_operand, they perform very similar functions. */ -int -call_operand_address (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_MODE (op) == word_mode - && CONSTANT_P (op) && ! TARGET_PORTABLE_RUNTIME); -} - /* Return 1 if X contains a symbolic expression. We know these expressions will have one of a few well defined forms, so we need only check those forms. */ @@ -584,95 +563,6 @@ symbolic_expression_p (rtx x) return (symbolic_operand (x, VOIDmode)); } -int -symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - switch (GET_CODE (op)) - { - case SYMBOL_REF: - case LABEL_REF: - return 1; - case CONST: - op = XEXP (op, 0); - return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF - || GET_CODE (XEXP (op, 0)) == LABEL_REF) - && GET_CODE (XEXP (op, 1)) == CONST_INT); - default: - return 0; - } -} - -/* Return truth value of statement that OP is a symbolic memory - operand of mode MODE. */ - -int -symbolic_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST - || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF); -} - -/* Return 1 if the operand is either a register, zero, or a memory operand - that is not symbolic. */ - -int -reg_or_0_or_nonsymb_mem_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (op == CONST0_RTX (mode)) - return 1; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != MEM) - return 0; - - /* Until problems with management of the REG_POINTER flag are resolved, - we need to delay creating move insns with unscaled indexed addresses - until CSE is not expected. */ - if (!TARGET_NO_SPACE_REGS - && !cse_not_expected - && GET_CODE (XEXP (op, 0)) == PLUS - && REG_P (XEXP (XEXP (op, 0), 0)) - && REG_P (XEXP (XEXP (op, 0), 1))) - return 0; - - return (!symbolic_memory_operand (op, mode) - && memory_address_p (mode, XEXP (op, 0))); -} - -/* Return 1 if the operand is a register operand or a non-symbolic memory - operand after reload. This predicate is used for branch patterns that - internally handle register reloading. We need to accept non-symbolic - memory operands after reload to ensure that the pattern is still valid - if reload didn't find a hard register for the operand. */ - -int -reg_before_reload_operand (rtx op, enum machine_mode mode) -{ - /* Don't accept a SUBREG since it will need a reload. */ - if (GET_CODE (op) == SUBREG) - return 0; - - if (register_operand (op, mode)) - return 1; - - if (reload_completed - && memory_operand (op, mode) - && !symbolic_memory_operand (op, mode)) - return 1; - - return 0; -} - /* Accept any constant that can be moved in one instruction into a general register. */ int @@ -683,198 +573,7 @@ cint_ok_for_move (HOST_WIDE_INT intval) || CONST_OK_FOR_LETTER_P (intval, 'N') || CONST_OK_FOR_LETTER_P (intval, 'K')); } - -/* Return 1 iff OP is an indexed memory operand. */ -int -indexed_memory_operand (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode) - return 0; - - /* Before reload, a (SUBREG (MEM...)) forces reloading into a register. */ - if (reload_completed && GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != MEM || symbolic_memory_operand (op, mode)) - return 0; - - op = XEXP (op, 0); - - return (memory_address_p (mode, op) && IS_INDEX_ADDR_P (op)); -} - -/* Accept anything that can be used as a destination operand for a - move instruction. We don't accept indexed memory operands since - they are supported only for floating point stores. */ -int -move_dest_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (GET_MODE (op) != mode) - return 0; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != MEM || symbolic_memory_operand (op, mode)) - return 0; - - op = XEXP (op, 0); - - return (memory_address_p (mode, op) - && !IS_INDEX_ADDR_P (op) - && !IS_LO_SUM_DLT_ADDR_P (op)); -} - -/* Accept anything that can be used as a source operand for a move - instruction. */ -int -move_src_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONST_INT) - return cint_ok_for_move (INTVAL (op)); - - if (GET_MODE (op) != mode) - return 0; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != MEM) - return 0; - - /* Until problems with management of the REG_POINTER flag are resolved, - we need to delay creating move insns with unscaled indexed addresses - until CSE is not expected. */ - if (!TARGET_NO_SPACE_REGS - && !cse_not_expected - && GET_CODE (XEXP (op, 0)) == PLUS - && REG_P (XEXP (XEXP (op, 0), 0)) - && REG_P (XEXP (XEXP (op, 0), 1))) - return 0; - - return memory_address_p (mode, XEXP (op, 0)); -} - -/* Accept anything that can be used as the source operand for a prefetch - instruction with a cache-control completer. */ -int -prefetch_cc_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) != MEM) - return 0; - - op = XEXP (op, 0); - - /* We must reject virtual registers as we don't allow REG+D. */ - if (op == virtual_incoming_args_rtx - || op == virtual_stack_vars_rtx - || op == virtual_stack_dynamic_rtx - || op == virtual_outgoing_args_rtx - || op == virtual_cfa_rtx) - return 0; - - if (!REG_P (op) && !IS_INDEX_ADDR_P (op)) - return 0; - - /* Until problems with management of the REG_POINTER flag are resolved, - we need to delay creating prefetch insns with unscaled indexed addresses - until CSE is not expected. */ - if (!TARGET_NO_SPACE_REGS - && !cse_not_expected - && GET_CODE (op) == PLUS - && REG_P (XEXP (op, 0))) - return 0; - - return memory_address_p (mode, op); -} - -/* Accept anything that can be used as the source operand for a prefetch - instruction with no cache-control completer. */ -int -prefetch_nocc_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) != MEM) - return 0; - - op = XEXP (op, 0); - - /* Until problems with management of the REG_POINTER flag are resolved, - we need to delay creating prefetch insns with unscaled indexed addresses - until CSE is not expected. */ - if (!TARGET_NO_SPACE_REGS - && !cse_not_expected - && GET_CODE (op) == PLUS - && REG_P (XEXP (op, 0)) - && REG_P (XEXP (op, 1))) - return 0; - - return memory_address_p (mode, op); -} - -/* Accept REG and any CONST_INT that can be moved in one instruction into a - general register. */ -int -reg_or_cint_move_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - return (GET_CODE (op) == CONST_INT && cint_ok_for_move (INTVAL (op))); -} - -int -pic_label_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (!flag_pic) - return 0; - - switch (GET_CODE (op)) - { - case LABEL_REF: - return 1; - case CONST: - op = XEXP (op, 0); - return (GET_CODE (XEXP (op, 0)) == LABEL_REF - && GET_CODE (XEXP (op, 1)) == CONST_INT); - default: - return 0; - } -} - -int -fp_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return reg_renumber && FP_REG_P (op); -} - - -/* Return truth value of whether OP can be used as an operand in a - three operand arithmetic insn that accepts registers of mode MODE - or 14-bit signed integers. */ -int -arith_operand (rtx op, enum machine_mode mode) -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && INT_14_BITS (op))); -} - -/* Return truth value of whether OP can be used as an operand in a - three operand arithmetic insn that accepts registers of mode MODE - or 11-bit signed integers. */ -int -arith11_operand (rtx op, enum machine_mode mode) -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && INT_11_BITS (op))); -} - /* Return truth value of whether OP can be used as an operand in a adddi3 insn. */ int @@ -885,94 +584,6 @@ adddi3_operand (rtx op, enum machine_mode mode) && (TARGET_64BIT ? INT_14_BITS (op) : INT_11_BITS (op)))); } -/* A constant integer suitable for use in a PRE_MODIFY memory - reference. */ -int -pre_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT - && INTVAL (op) >= -0x2000 && INTVAL (op) < 0x10); -} - -/* A constant integer suitable for use in a POST_MODIFY memory - reference. */ -int -post_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT - && INTVAL (op) < 0x2000 && INTVAL (op) >= -0x10); -} - -int -arith_double_operand (rtx op, enum machine_mode mode) -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_DOUBLE - && GET_MODE (op) == mode - && VAL_14_BITS_P (CONST_DOUBLE_LOW (op)) - && ((CONST_DOUBLE_HIGH (op) >= 0) - == ((CONST_DOUBLE_LOW (op) & 0x1000) == 0)))); -} - -/* Return truth value of whether OP is an integer which fits the - range constraining immediate operands in three-address insns, or - is an integer register. */ - -int -ireg_or_int5_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return ((GET_CODE (op) == CONST_INT && INT_5_BITS (op)) - || (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32)); -} - -/* Return nonzero if OP is an integer register, else return zero. */ -int -ireg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32); -} - -/* Return truth value of whether OP is an integer which fits the - range constraining immediate operands in three-address insns. */ - -int -int5_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT && INT_5_BITS (op)); -} - -int -uint5_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT && INT_U5_BITS (op)); -} - -int -int11_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT && INT_11_BITS (op)); -} - -int -uint32_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ -#if HOST_BITS_PER_WIDE_INT > 32 - /* All allowed constants will fit a CONST_INT. */ - return (GET_CODE (op) == CONST_INT - && (INTVAL (op) >= 0 && INTVAL (op) < (HOST_WIDE_INT) 1 << 32)); -#else - return (GET_CODE (op) == CONST_INT - || (GET_CODE (op) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (op) == 0)); -#endif -} - -int -arith5_operand (rtx op, enum machine_mode mode) -{ - return register_operand (op, mode) || int5_operand (op, mode); -} - /* True iff zdepi can be used to generate this CONST_INT. zdepi first sign extends a 5 bit signed number to a given field length, then places this field anywhere in a zero. */ @@ -1002,14 +613,6 @@ and_mask_p (unsigned HOST_WIDE_INT mask) return (mask & (mask - 1)) == 0; } -/* True iff depi or extru can be used to compute (reg & OP). */ -int -and_operand (rtx op, enum machine_mode mode) -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && and_mask_p (INTVAL (op)))); -} - /* True iff depi can be used to compute (reg | MASK). */ int ior_mask_p (unsigned HOST_WIDE_INT mask) @@ -1017,44 +620,6 @@ ior_mask_p (unsigned HOST_WIDE_INT mask) mask += mask & -mask; return (mask & (mask - 1)) == 0; } - -/* True iff depi can be used to compute (reg | OP). */ -int -ior_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op))); -} - -int -lhs_lshift_operand (rtx op, enum machine_mode mode) -{ - return register_operand (op, mode) || lhs_lshift_cint_operand (op, mode); -} - -/* True iff OP is a CONST_INT of the forms 0...0xxxx or 0...01...1xxxx. - Such values can be the left hand side x in (x << r), using the zvdepi - instruction. */ -int -lhs_lshift_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - unsigned HOST_WIDE_INT x; - if (GET_CODE (op) != CONST_INT) - return 0; - x = INTVAL (op) >> 4; - return (x & (x + 1)) == 0; -} - -int -arith32_operand (rtx op, enum machine_mode mode) -{ - return register_operand (op, mode) || GET_CODE (op) == CONST_INT; -} - -int -pc_or_label_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF); -} /* Legitimize PIC addresses. If the address is already position-independent, we return ORIG. Newly generated @@ -5741,8 +5306,7 @@ output_mul_insn (int unsignedp ATTRIBUTE_UNUSED, rtx insn) /* Emit the rtl for doing a division by a constant. */ /* Do magic division millicodes exist for this value? */ -static const int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, - 1, 1}; +const int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1}; /* We'll use an array to keep track of the magic millicodes and whether or not we've used them already. [n][0] is signed, [n][1] is @@ -5751,15 +5315,6 @@ static const int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, static int div_milli[16][2]; int -div_operand (rtx op, enum machine_mode mode) -{ - return (mode == SImode - && ((GET_CODE (op) == REG && REGNO (op) == 25) - || (GET_CODE (op) == CONST_INT && INTVAL (op) > 0 - && INTVAL (op) < 16 && magic_milli[INTVAL (op)]))); -} - -int emit_hpdiv_const (rtx *operands, int unsignedp) { if (GET_CODE (operands[2]) == CONST_INT @@ -8440,16 +7995,9 @@ fmpysuboperands (rtx *operands) return 1; } -int -plus_xor_ior_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == PLUS || GET_CODE (op) == XOR - || GET_CODE (op) == IOR); -} - /* Return 1 if the given constant is 2, 4, or 8. These are the valid constants for shadd instructions. */ -static int +int shadd_constant_p (int val) { if (val == 2 || val == 4 || val == 8) @@ -8458,14 +8006,6 @@ shadd_constant_p (int val) return 0; } -/* Return 1 if OP is a CONST_INT with the value 2, 4, or 8. These are - the valid constant for shadd instructions. */ -int -shadd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT && shadd_constant_p (INTVAL (op))); -} - /* Return 1 if OP is valid as a base or index register in a REG+REG address. */ @@ -8528,14 +8068,6 @@ eq_neq_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) return (GET_CODE (op) == EQ || GET_CODE (op) == NE); } -/* Return 1 if OP is an operator suitable for use in a movb instruction. */ -int -movb_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == EQ || GET_CODE (op) == NE - || GET_CODE (op) == LT || GET_CODE (op) == GE); -} - /* Return 1 if INSN is in the delay slot of a call instruction. */ int jump_in_call_delay (rtx insn) @@ -9367,23 +8899,6 @@ pa_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode, } -/* Return 1 if this is a comparison operator. This allows the use of - MATCH_OPERATOR to recognize all the branch insns. */ - -int -cmpib_comparison_operator (rtx op, enum machine_mode mode) -{ - return ((mode == VOIDmode || GET_MODE (op) == mode) - && (GET_CODE (op) == EQ - || GET_CODE (op) == NE - || GET_CODE (op) == GT - || GET_CODE (op) == GTU - || GET_CODE (op) == GE - || GET_CODE (op) == LT - || GET_CODE (op) == LE - || GET_CODE (op) == LEU)); -} - /* Return a string to output before text in the current function. This function is only used with SOM. Because we don't support diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index 30b982a..26201f8 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -2128,49 +2128,6 @@ forget_section (void) \ /* The number of Pmode words for the setjmp buffer. */ #define JMP_BUF_SIZE 50 -#define PREDICATE_CODES \ - {"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \ - {"call_operand_address", {LABEL_REF, SYMBOL_REF, CONST_INT, \ - CONST_DOUBLE, CONST, HIGH}}, \ - {"indexed_memory_operand", {SUBREG, MEM}}, \ - {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \ - {"symbolic_memory_operand", {SUBREG, MEM}}, \ - {"reg_before_reload_operand", {REG, MEM}}, \ - {"reg_or_0_or_nonsymb_mem_operand", {SUBREG, REG, MEM, CONST_INT, \ - CONST_DOUBLE}}, \ - {"move_dest_operand", {SUBREG, REG, MEM}}, \ - {"move_src_operand", {SUBREG, REG, CONST_INT, MEM}}, \ - {"prefetch_cc_operand", {MEM}}, \ - {"prefetch_nocc_operand", {MEM}}, \ - {"reg_or_cint_move_operand", {SUBREG, REG, CONST_INT}}, \ - {"pic_label_operand", {LABEL_REF, CONST}}, \ - {"fp_reg_operand", {REG}}, \ - {"arith_operand", {SUBREG, REG, CONST_INT}}, \ - {"arith11_operand", {SUBREG, REG, CONST_INT}}, \ - {"pre_cint_operand", {CONST_INT}}, \ - {"post_cint_operand", {CONST_INT}}, \ - {"arith_double_operand", {SUBREG, REG, CONST_DOUBLE}}, \ - {"ireg_or_int5_operand", {CONST_INT, REG}}, \ - {"int5_operand", {CONST_INT}}, \ - {"uint5_operand", {CONST_INT}}, \ - {"int11_operand", {CONST_INT}}, \ - {"uint32_operand", {CONST_INT, \ - HOST_BITS_PER_WIDE_INT > 32 ? 0 : CONST_DOUBLE}}, \ - {"arith5_operand", {SUBREG, REG, CONST_INT}}, \ - {"and_operand", {SUBREG, REG, CONST_INT}}, \ - {"ior_operand", {CONST_INT}}, \ - {"lhs_lshift_cint_operand", {CONST_INT}}, \ - {"lhs_lshift_operand", {SUBREG, REG, CONST_INT}}, \ - {"arith32_operand", {SUBREG, REG, CONST_INT}}, \ - {"pc_or_label_operand", {PC, LABEL_REF}}, \ - {"plus_xor_ior_operator", {PLUS, XOR, IOR}}, \ - {"shadd_operand", {CONST_INT}}, \ - {"div_operand", {REG, CONST_INT}}, \ - {"ireg_operand", {REG}}, \ - {"cmpib_comparison_operator", {EQ, NE, LT, LE, LEU, \ - GT, GTU, GE}}, \ - {"movb_comparison_operator", {EQ, NE, LT, GE}}, - /* We need a libcall to canonicalize function pointers on TARGET_ELF32. */ #define CANONICALIZE_FUNCPTR_FOR_COMPARE_LIBCALL \ "__canonicalize_funcptr_for_compare" diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 6f8f42d..6b8c77b 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -561,7 +561,7 @@ (eq_attr "cpu" "8000")) "inm_8000,fdivsqrt_8000*6,rnm_8000") - +(include "predicates.md") ;; Compare instructions. ;; This controls RTL generation and register allocation. diff --git a/gcc/config/pa/predicates.md b/gcc/config/pa/predicates.md new file mode 100644 index 0000000..23f62e3 --- /dev/null +++ b/gcc/config/pa/predicates.md @@ -0,0 +1,550 @@ +;; Predicate definitions for HP PA-RISC. +;; Copyright (C) 2005 Free Software Foundation, Inc. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING. If not, write to +;; the Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;; Return nonzero only if OP is a register of mode MODE, or +;; CONST0_RTX. + +(define_predicate "reg_or_0_operand" + (match_code "subreg,reg,const_int,const_double") +{ + return (op == CONST0_RTX (mode) || register_operand (op, mode)); +}) + +;; Return nonzero if OP is suitable for use in a call to a named +;; function. +;; +;; For 2.5 try to eliminate either call_operand_address or +;; function_label_operand, they perform very similar functions. + +(define_predicate "call_operand_address" + (match_code "label_ref,symbol_ref,const_int,const_double,const,high") +{ + return (GET_MODE (op) == word_mode + && CONSTANT_P (op) && ! TARGET_PORTABLE_RUNTIME); +}) + +;; Return 1 iff OP is an indexed memory operand. + +(define_predicate "indexed_memory_operand" + (match_code "subreg,mem") +{ + if (GET_MODE (op) != mode) + return 0; + + /* Before reload, a (SUBREG (MEM...)) forces reloading into a register. */ + if (reload_completed && GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (GET_CODE (op) != MEM || symbolic_memory_operand (op, mode)) + return 0; + + op = XEXP (op, 0); + + return (memory_address_p (mode, op) && IS_INDEX_ADDR_P (op)); +}) + +;; TODO: Add a comment. + +(define_predicate "symbolic_operand" + (match_code "symbol_ref,label_ref,const") +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF: + case LABEL_REF: + return 1; + case CONST: + op = XEXP (op, 0); + return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF + || GET_CODE (XEXP (op, 0)) == LABEL_REF) + && GET_CODE (XEXP (op, 1)) == CONST_INT); + default: + return 0; + } +}) + +;; Return truth value of statement that OP is a symbolic memory +;; operand of mode MODE. + +(define_predicate "symbolic_memory_operand" + (match_code "subreg,mem") +{ + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + if (GET_CODE (op) != MEM) + return 0; + op = XEXP (op, 0); + return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST + || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF); +}) + +;; Return 1 if the operand is a register operand or a non-symbolic +;; memory operand after reload. This predicate is used for branch +;; patterns that internally handle register reloading. We need to +;; accept non-symbolic memory operands after reload to ensure that the +;; pattern is still valid if reload didn't find a hard register for +;; the operand. + +(define_predicate "reg_before_reload_operand" + (match_code "reg,mem") +{ + /* Don't accept a SUBREG since it will need a reload. */ + if (GET_CODE (op) == SUBREG) + return 0; + + if (register_operand (op, mode)) + return 1; + + if (reload_completed + && memory_operand (op, mode) + && !symbolic_memory_operand (op, mode)) + return 1; + + return 0; +}) + +;; Return 1 if the operand is either a register, zero, or a memory +;; operand that is not symbolic. + +(define_predicate "reg_or_0_or_nonsymb_mem_operand" + (match_code "subreg,reg,mem,const_int,const_double") +{ + if (register_operand (op, mode)) + return 1; + + if (op == CONST0_RTX (mode)) + return 1; + + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (GET_CODE (op) != MEM) + return 0; + + /* Until problems with management of the REG_POINTER flag are resolved, + we need to delay creating move insns with unscaled indexed addresses + until CSE is not expected. */ + if (!TARGET_NO_SPACE_REGS + && !cse_not_expected + && GET_CODE (XEXP (op, 0)) == PLUS + && REG_P (XEXP (XEXP (op, 0), 0)) + && REG_P (XEXP (XEXP (op, 0), 1))) + return 0; + + return (!symbolic_memory_operand (op, mode) + && memory_address_p (mode, XEXP (op, 0))); +}) + +;; Accept anything that can be used as a destination operand for a +;; move instruction. We don't accept indexed memory operands since +;; they are supported only for floating point stores. + +(define_predicate "move_dest_operand" + (match_code "subreg,reg,mem") +{ + if (register_operand (op, mode)) + return 1; + + if (GET_MODE (op) != mode) + return 0; + + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (GET_CODE (op) != MEM || symbolic_memory_operand (op, mode)) + return 0; + + op = XEXP (op, 0); + + return (memory_address_p (mode, op) + && !IS_INDEX_ADDR_P (op) + && !IS_LO_SUM_DLT_ADDR_P (op)); +}) + +;; Accept anything that can be used as a source operand for a move +;; instruction. + +(define_predicate "move_src_operand" + (match_code "subreg,reg,const_int,mem") +{ + if (register_operand (op, mode)) + return 1; + + if (GET_CODE (op) == CONST_INT) + return cint_ok_for_move (INTVAL (op)); + + if (GET_MODE (op) != mode) + return 0; + + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (GET_CODE (op) != MEM) + return 0; + + /* Until problems with management of the REG_POINTER flag are resolved, + we need to delay creating move insns with unscaled indexed addresses + until CSE is not expected. */ + if (!TARGET_NO_SPACE_REGS + && !cse_not_expected + && GET_CODE (XEXP (op, 0)) == PLUS + && REG_P (XEXP (XEXP (op, 0), 0)) + && REG_P (XEXP (XEXP (op, 0), 1))) + return 0; + + return memory_address_p (mode, XEXP (op, 0)); +}) + +;; Accept anything that can be used as the source operand for a +;; prefetch instruction with a cache-control completer. + +(define_predicate "prefetch_cc_operand" + (match_code "mem") +{ + if (GET_CODE (op) != MEM) + return 0; + + op = XEXP (op, 0); + + /* We must reject virtual registers as we don't allow REG+D. */ + if (op == virtual_incoming_args_rtx + || op == virtual_stack_vars_rtx + || op == virtual_stack_dynamic_rtx + || op == virtual_outgoing_args_rtx + || op == virtual_cfa_rtx) + return 0; + + if (!REG_P (op) && !IS_INDEX_ADDR_P (op)) + return 0; + + /* Until problems with management of the REG_POINTER flag are resolved, + we need to delay creating prefetch insns with unscaled indexed addresses + until CSE is not expected. */ + if (!TARGET_NO_SPACE_REGS + && !cse_not_expected + && GET_CODE (op) == PLUS + && REG_P (XEXP (op, 0))) + return 0; + + return memory_address_p (mode, op); +}) + +;; Accept anything that can be used as the source operand for a +;; prefetch instruction with no cache-control completer. + +(define_predicate "prefetch_nocc_operand" + (match_code "mem") +{ + if (GET_CODE (op) != MEM) + return 0; + + op = XEXP (op, 0); + + /* Until problems with management of the REG_POINTER flag are resolved, + we need to delay creating prefetch insns with unscaled indexed addresses + until CSE is not expected. */ + if (!TARGET_NO_SPACE_REGS + && !cse_not_expected + && GET_CODE (op) == PLUS + && REG_P (XEXP (op, 0)) + && REG_P (XEXP (op, 1))) + return 0; + + return memory_address_p (mode, op); +}) + +;; Accept REG and any CONST_INT that can be moved in one instruction +;; into a general register. + +(define_predicate "reg_or_cint_move_operand" + (match_code "subreg,reg,const_int") +{ + if (register_operand (op, mode)) + return 1; + + return (GET_CODE (op) == CONST_INT && cint_ok_for_move (INTVAL (op))); +}) + +;; TODO: Add a comment here. + +(define_predicate "pic_label_operand" + (match_code "label_ref,const") +{ + if (!flag_pic) + return 0; + + switch (GET_CODE (op)) + { + case LABEL_REF: + return 1; + case CONST: + op = XEXP (op, 0); + return (GET_CODE (XEXP (op, 0)) == LABEL_REF + && GET_CODE (XEXP (op, 1)) == CONST_INT); + default: + return 0; + } +}) + +;; TODO: Add a comment here. + +(define_predicate "fp_reg_operand" + (match_code "reg") +{ + return reg_renumber && FP_REG_P (op); +}) + +;; Return truth value of whether OP can be used as an operand in a +;; three operand arithmetic insn that accepts registers of mode MODE +;; or 14-bit signed integers. + +(define_predicate "arith_operand" + (match_code "subreg,reg,const_int") +{ + return (register_operand (op, mode) + || (GET_CODE (op) == CONST_INT && INT_14_BITS (op))); +}) + +;; Return truth value of whether OP can be used as an operand in a +;; three operand arithmetic insn that accepts registers of mode MODE +;; or 11-bit signed integers. + +(define_predicate "arith11_operand" + (match_code "subreg,reg,const_int") +{ + return (register_operand (op, mode) + || (GET_CODE (op) == CONST_INT && INT_11_BITS (op))); +}) + +;; A constant integer suitable for use in a PRE_MODIFY memory +;; reference. + +(define_predicate "pre_cint_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT + && INTVAL (op) >= -0x2000 && INTVAL (op) < 0x10); +}) + +;; A constant integer suitable for use in a POST_MODIFY memory +;; reference. + +(define_predicate "post_cint_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT + && INTVAL (op) < 0x2000 && INTVAL (op) >= -0x10); +}) + +;; TODO: Add a comment here. + +(define_predicate "arith_double_operand" + (match_code "subreg,reg,const_double") +{ + return (register_operand (op, mode) + || (GET_CODE (op) == CONST_DOUBLE + && GET_MODE (op) == mode + && VAL_14_BITS_P (CONST_DOUBLE_LOW (op)) + && ((CONST_DOUBLE_HIGH (op) >= 0) + == ((CONST_DOUBLE_LOW (op) & 0x1000) == 0)))); +}) + +;; Return truth value of whether OP is an integer which fits the range +;; constraining immediate operands in three-address insns, or is an +;; integer register. + +(define_predicate "ireg_or_int5_operand" + (match_code "const_int,reg") +{ + return ((GET_CODE (op) == CONST_INT && INT_5_BITS (op)) + || (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32)); +}) + +;; Return truth value of whether OP is an integer which fits the range +;; constraining immediate operands in three-address insns. + +(define_predicate "int5_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT && INT_5_BITS (op)); +}) + +;; Return truth value of whether OP is an integer which fits the range +;; constraining immediate operands in three-address insns. + +(define_predicate "uint5_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT && INT_U5_BITS (op)); +}) + +;; Return truth value of whether OP is an integer which fits the range +;; constraining immediate operands in three-address insns. + +(define_predicate "int11_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT && INT_11_BITS (op)); +}) + +;; Return truth value of whether OP is an integer which fits the range +;; constraining immediate operands in three-address insns. + +(define_predicate "uint32_operand" + (match_code "const_int,const_double") +{ +#if HOST_BITS_PER_WIDE_INT > 32 + /* All allowed constants will fit a CONST_INT. */ + return (GET_CODE (op) == CONST_INT + && (INTVAL (op) >= 0 && INTVAL (op) < (HOST_WIDE_INT) 1 << 32)); +#else + return (GET_CODE (op) == CONST_INT + || (GET_CODE (op) == CONST_DOUBLE + && CONST_DOUBLE_HIGH (op) == 0)); +#endif +}) + +;; Return truth value of whether OP is an integer which fits the range +;; constraining immediate operands in three-address insns. + +(define_predicate "arith5_operand" + (match_code "subreg,reg,const_int") +{ + return register_operand (op, mode) || int5_operand (op, mode); +}) + +;; True iff depi or extru can be used to compute (reg & OP). + +(define_predicate "and_operand" + (match_code "subreg,reg,const_int") +{ + return (register_operand (op, mode) + || (GET_CODE (op) == CONST_INT && and_mask_p (INTVAL (op)))); +}) + +;; True iff depi can be used to compute (reg | OP). + +(define_predicate "ior_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op))); +}) + +;; True iff OP is a CONST_INT of the forms 0...0xxxx or +;; 0...01...1xxxx. Such values can be the left hand side x in (x << +;; r), using the zvdepi instruction. + +(define_predicate "lhs_lshift_cint_operand" + (match_code "const_int") +{ + unsigned HOST_WIDE_INT x; + if (GET_CODE (op) != CONST_INT) + return 0; + x = INTVAL (op) >> 4; + return (x & (x + 1)) == 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "lhs_lshift_operand" + (match_code "subreg,reg,const_int") +{ + return register_operand (op, mode) || lhs_lshift_cint_operand (op, mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "arith32_operand" + (match_code "subreg,reg,const_int") +{ + return register_operand (op, mode) || GET_CODE (op) == CONST_INT; +}) + +;; TODO: Add a comment here. + +(define_predicate "pc_or_label_operand" + (match_code "pc,label_ref") +{ + return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF); +}) + +;; TODO: Add a comment here. + +(define_predicate "plus_xor_ior_operator" + (match_code "plus,xor,ior") +{ + return (GET_CODE (op) == PLUS || GET_CODE (op) == XOR + || GET_CODE (op) == IOR); +}) + +;; Return 1 if OP is a CONST_INT with the value 2, 4, or 8. These are +;; the valid constant for shadd instructions. + +(define_predicate "shadd_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT && shadd_constant_p (INTVAL (op))); +}) + +;; TODO: Add a comment here. + +(define_predicate "div_operand" + (match_code "reg,const_int") +{ + return (mode == SImode + && ((GET_CODE (op) == REG && REGNO (op) == 25) + || (GET_CODE (op) == CONST_INT && INTVAL (op) > 0 + && INTVAL (op) < 16 && magic_milli[INTVAL (op)]))); +}) + +;; Return nonzero if OP is an integer register, else return zero. + +(define_predicate "ireg_operand" + (match_code "reg") +{ + return (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32); +}) + +;; Return 1 if this is a comparison operator. This allows the use of +;; MATCH_OPERATOR to recognize all the branch insns. + +(define_predicate "cmpib_comparison_operator" + (match_code "eq,ne,lt,le,leu,gt,gtu,ge") +{ + return ((mode == VOIDmode || GET_MODE (op) == mode) + && (GET_CODE (op) == EQ + || GET_CODE (op) == NE + || GET_CODE (op) == GT + || GET_CODE (op) == GTU + || GET_CODE (op) == GE + || GET_CODE (op) == LT + || GET_CODE (op) == LE + || GET_CODE (op) == LEU)); +}) + +;; Return 1 if OP is an operator suitable for use in a movb +;; instruction. + +(define_predicate "movb_comparison_operator" + (match_code "eq,ne,lt,ge") +{ + return (GET_CODE (op) == EQ || GET_CODE (op) == NE + || GET_CODE (op) == LT || GET_CODE (op) == GE); +}) |