From 981c7dcef835c914783cd456ee18a29611afe4db Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Thu, 17 Mar 2005 21:01:34 +0000 Subject: [PATCH] h8300-protos.h: Remove prototypes for general_operand_src... * config/h8300/h8300-protos.h: Remove prototypes for general_operand_src, general_operand_dst, single_one_operand, single_zero_operand, call_insn_operand, two_insn_adds_subs_operand, small_call_insn_operand, jump_address_operand, bit_operand, bit_memory_operand, stack_pointer_operand, const_int_gt_2_operand, const_int_ge_8_operand, const_int_qi_operand, const_int_hi_operand, incdec_operand, bit_operator, nshift_operator, eqne_operator, gtle_operator, gtuleu_operator, iorxor_operator. Add prototypes for h8sx_shift_type h8sx_classify_shift and h8300_ldm_stm_parallel. * config/h8300/h8300.c (h8sx_shift_type,): Move to h8300-protos.h. (SYMBOL_FLAG_FUNCVEC_FUNCTION, SYMBOL_FLAG_EIGHTBIT_DATA, SYMBOL_FLAG_TINY_DATA): Move to h8300.h. (h8300_ldm_stm_parallel): Make it extern. (h8300_ldm_parallel, h8300_stm_parallel, h8300_return_parallel, general_operand_src, general_operand_dst, h8300_dst_operand, h8300_src_operand, nibble_operand, reg_or_nibble_operand, single_one_operand, single_zero_operand, call_insn_operand, two_insn_adds_subs_operand, small_call_insn_operand, jump_address_operand, bit_operand, bit_memory_operand, stack_pointer_operand, const_int_gt_2_operand, const_int_ge_8_operand, const_int_qi_operand, const_int_hi_operand, incdec_operand, eqne_operator, gtle_operator, gtuleu_operator, iorxor_operator, bit_operator, h8sx_binary_memory_operator, h8sx_unary_memory_operator, h8sx_unary_shift_operator, h8sx_binary_shift_operator, nshift_operator): Move to predicates.md. * config/h8300/h8300.h (PREDICATE_CODES): Remove. * config/h8300/h8300.md: Include predicates.md. * config/h8300/predicates.md: New. From-SVN: r96631 --- gcc/ChangeLog | 37 +++ gcc/config/h8300/h8300-protos.h | 45 ++- gcc/config/h8300/h8300.c | 490 +------------------------------- gcc/config/h8300/h8300.h | 43 +-- gcc/config/h8300/h8300.md | 2 + gcc/config/h8300/predicates.md | 483 +++++++++++++++++++++++++++++++ 6 files changed, 549 insertions(+), 551 deletions(-) create mode 100644 gcc/config/h8300/predicates.md diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2f004094df7..dd11e2c1944 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,40 @@ +2005-03-17 Kazu Hirata + + * config/h8300/h8300-protos.h: Remove prototypes for + general_operand_src, general_operand_dst, single_one_operand, + single_zero_operand, call_insn_operand, + two_insn_adds_subs_operand, small_call_insn_operand, + jump_address_operand, bit_operand, bit_memory_operand, + stack_pointer_operand, const_int_gt_2_operand, + const_int_ge_8_operand, const_int_qi_operand, + const_int_hi_operand, incdec_operand, bit_operator, + nshift_operator, eqne_operator, gtle_operator, + gtuleu_operator, iorxor_operator. + Add prototypes for h8sx_shift_type h8sx_classify_shift and + h8300_ldm_stm_parallel. + * config/h8300/h8300.c (h8sx_shift_type,): Move to + h8300-protos.h. + (SYMBOL_FLAG_FUNCVEC_FUNCTION, SYMBOL_FLAG_EIGHTBIT_DATA, + SYMBOL_FLAG_TINY_DATA): Move to h8300.h. + (h8300_ldm_stm_parallel): Make it extern. + (h8300_ldm_parallel, h8300_stm_parallel, + h8300_return_parallel, general_operand_src, + general_operand_dst, h8300_dst_operand, h8300_src_operand, + nibble_operand, reg_or_nibble_operand, single_one_operand, + single_zero_operand, call_insn_operand, + two_insn_adds_subs_operand, small_call_insn_operand, + jump_address_operand, bit_operand, bit_memory_operand, + stack_pointer_operand, const_int_gt_2_operand, + const_int_ge_8_operand, const_int_qi_operand, + const_int_hi_operand, incdec_operand, eqne_operator, + gtle_operator, gtuleu_operator, iorxor_operator, bit_operator, + h8sx_binary_memory_operator, h8sx_unary_memory_operator, + h8sx_unary_shift_operator, h8sx_binary_shift_operator, + nshift_operator): Move to predicates.md. + * config/h8300/h8300.h (PREDICATE_CODES): Remove. + * config/h8300/h8300.md: Include predicates.md. + * config/h8300/predicates.md: New. + 2005-03-17 Richard Henderson * config.gcc (ia64*-*-hpux*): Add extra_options. diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 6df3d710971..54fe462b93b 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -53,29 +53,6 @@ extern int fix_bit_operand (rtx *, enum rtx_code); extern int h8300_adjust_insn_length (rtx, int); extern void split_adds_subs (enum machine_mode, rtx[]); -extern int general_operand_src (rtx, enum machine_mode); -extern int general_operand_dst (rtx, enum machine_mode); -extern int single_one_operand (rtx, enum machine_mode); -extern int single_zero_operand (rtx, enum machine_mode); -extern int call_insn_operand (rtx, enum machine_mode); -extern int two_insn_adds_subs_operand (rtx, enum machine_mode); -extern int small_call_insn_operand (rtx, enum machine_mode); -extern int jump_address_operand (rtx, enum machine_mode); -extern int bit_operand (rtx, enum machine_mode); -extern int bit_memory_operand (rtx, enum machine_mode); -extern int stack_pointer_operand (rtx, enum machine_mode); -extern int const_int_gt_2_operand (rtx, enum machine_mode); -extern int const_int_ge_8_operand (rtx, enum machine_mode); -extern int const_int_qi_operand (rtx, enum machine_mode); -extern int const_int_hi_operand (rtx, enum machine_mode); -extern int incdec_operand (rtx, enum machine_mode); -extern int bit_operator (rtx, enum machine_mode); -extern int nshift_operator (rtx, enum machine_mode); -extern int eqne_operator (rtx, enum machine_mode); -extern int gtle_operator (rtx, enum machine_mode); -extern int gtuleu_operator (rtx, enum machine_mode); -extern int iorxor_operator (rtx, enum machine_mode); - extern int h8300_eightbit_constant_address_p (rtx); extern int h8300_tiny_constant_address_p (rtx); extern int byte_accesses_mergeable_p (rtx, rtx); @@ -87,6 +64,28 @@ extern int h8300_legitimate_address_p (enum machine_mode, rtx, int); /* Used in builtins.c */ extern rtx h8300_return_addr_rtx (int, rtx); + +/* Classifies an h8sx shift operation. + + H8SX_SHIFT_NONE + The shift cannot be done in a single instruction. + + H8SX_SHIFT_UNARY + The shift is effectively a unary operation. The instruction will + allow any sort of destination operand and have a format similar + to neg and not. This is true of certain power-of-2 shifts. + + H8SX_SHIFT_BINARY + The shift is a binary operation. The destination must be a + register and the source can be a register or a constant. */ +enum h8sx_shift_type { + H8SX_SHIFT_NONE, + H8SX_SHIFT_UNARY, + H8SX_SHIFT_BINARY +}; + +extern enum h8sx_shift_type h8sx_classify_shift (enum machine_mode, enum rtx_code, rtx); +extern int h8300_ldm_stm_parallel (rtvec, int, int); #endif /* RTX_CODE */ #ifdef TREE_CODE diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 36734b2bf37..d4120ff060a 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -72,26 +72,6 @@ enum h8300_operand_class NUM_H8OPS }; -/* Classifies an h8sx shift operation. - - H8SX_SHIFT_NONE - The shift cannot be done in a single instruction. - - H8SX_SHIFT_UNARY - The shift is effectively a unary operation. The instruction will - allow any sort of destination operand and have a format similar - to neg and not. This is true of certain power-of-2 shifts. - - H8SX_SHIFT_BINARY - The shift is a binary operation. The destination must be a - register and the source can be a register or a constant. */ -enum h8sx_shift_type -{ - H8SX_SHIFT_NONE, - H8SX_SHIFT_UNARY, - H8SX_SHIFT_BINARY -}; - /* For a general two-operand instruction, element [X][Y] gives the length of the opcode fields when the first operand has class (X + 1) and the second has class Y. */ @@ -121,7 +101,6 @@ static int h8300_shift_costs (rtx); static void h8300_push_pop (int, int, int, int); static int h8300_stack_offset_p (rtx, int); static int h8300_ldm_stm_regno (rtx, int, int, int); -static int h8300_ldm_stm_parallel (rtvec, int, int); static void h8300_reorg (void); static unsigned int h8300_constant_length (rtx); static unsigned int h8300_displacement_length (rtx, int); @@ -133,7 +112,6 @@ static unsigned int h8300_bitfield_length (rtx, rtx); static unsigned int h8300_binary_length (rtx, const h8300_length_table *); static bool h8300_short_move_mem_p (rtx, enum rtx_code); static unsigned int h8300_move_length (rtx *, const h8300_length_table *); -enum h8sx_shift_type h8sx_classify_shift (enum machine_mode, enum rtx_code, rtx); /* CPU_TYPE, says what cpu we're compiling for. */ int cpu_type; @@ -163,11 +141,6 @@ const char *h8_push_op, *h8_pop_op, *h8_mov_op; /* Value of MOVE_RATIO. */ int h8300_move_ratio; - -/* Machine-specific symbol_ref flags. */ -#define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0) -#define SYMBOL_FLAG_EIGHTBIT_DATA (SYMBOL_FLAG_MACH_DEP << 1) -#define SYMBOL_FLAG_TINY_DATA (SYMBOL_FLAG_MACH_DEP << 2) /* See below where shifts are handled for explanation of this enum. */ @@ -761,7 +734,7 @@ h8300_ldm_stm_regno (rtx x, int load_p, int index, int nregs) /* Return true if the elements of VEC starting at FIRST describe an ldm or stm instruction (LOAD_P says which). */ -static int +int h8300_ldm_stm_parallel (rtvec vec, int load_p, int first) { rtx last; @@ -805,31 +778,6 @@ h8300_ldm_stm_parallel (rtvec vec, int load_p, int first) && h8300_stack_offset_p (SET_SRC (last), adjust)); } -/* Return true if X is an ldm.l pattern. X is known to be parallel. */ - -int -h8300_ldm_parallel (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return h8300_ldm_stm_parallel (XVEC (x, 0), 1, 0); -} - -/* Likewise stm.l. */ - -int -h8300_stm_parallel (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return h8300_ldm_stm_parallel (XVEC (x, 0), 0, 0); -} - -/* Likewise rts/l and rte/l. Note that the .md pattern will check - for the return so there's no need to do that here. */ - -int -h8300_return_parallel (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return h8300_ldm_stm_parallel (XVEC (x, 0), 1, 1); -} - /* This is what the stack looks like after the prolog of a function with a frame has been set up: @@ -1020,169 +968,6 @@ h8300_file_end (void) fputs ("\t.end\n", asm_out_file); } -/* Return true if OP is a valid source operand for an integer move - instruction. */ - -int -general_operand_src (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) == mode - && GET_CODE (op) == MEM - && GET_CODE (XEXP (op, 0)) == POST_INC) - return 1; - return general_operand (op, mode); -} - -/* Return true if OP is a valid destination operand for an integer move - instruction. */ - -int -general_operand_dst (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) == mode - && GET_CODE (op) == MEM - && GET_CODE (XEXP (op, 0)) == PRE_DEC) - return 1; - return general_operand (op, mode); -} - -/* Return true if OP is a suitable first operand for a general arithmetic - insn such as "add". */ - -int -h8300_dst_operand (rtx op, enum machine_mode mode) -{ - if (TARGET_H8300SX) - return nonimmediate_operand (op, mode); - return register_operand (op, mode); -} - -/* Likewise the second operand. */ - -int -h8300_src_operand (rtx op, enum machine_mode mode) -{ - if (TARGET_H8300SX) - return general_operand (op, mode); - return nonmemory_operand (op, mode); -} - -/* Check that an operand is either a register or an unsigned 4-bit - constant. */ - -int -nibble_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT && TARGET_H8300SX - && INTVAL (op) >= 0 && INTVAL (op) <= 15); -} - -/* Check that an operand is either a register or an unsigned 4-bit - constant. */ - -int -reg_or_nibble_operand (rtx op, enum machine_mode mode) -{ - return (nibble_operand (op, mode) || register_operand (op, mode)); -} - -/* Return true if OP is a constant that contains only one 1 in its - binary representation. */ - -int -single_one_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (operand) == CONST_INT) - { - /* We really need to do this masking because 0x80 in QImode is - represented as -128 for example. */ - if (exact_log2 (INTVAL (operand) & GET_MODE_MASK (mode)) >= 0) - return 1; - } - - return 0; -} - -/* Return true if OP is a constant that contains only one 0 in its - binary representation. */ - -int -single_zero_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (operand) == CONST_INT) - { - /* We really need to do this masking because 0x80 in QImode is - represented as -128 for example. */ - if (exact_log2 (~INTVAL (operand) & GET_MODE_MASK (mode)) >= 0) - return 1; - } - - return 0; -} - -/* Return true if OP is a valid call operand. */ - -int -call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) == MEM) - { - rtx inside = XEXP (op, 0); - if (register_operand (inside, Pmode)) - return 1; - if (CONSTANT_ADDRESS_P (inside)) - return 1; - } - return 0; -} - -/* Return 1 if an addition/subtraction of a constant integer can be - transformed into two consecutive adds/subs that are faster than the - straightforward way. Otherwise, return 0. */ - -int -two_insn_adds_subs_operand (rtx op, enum machine_mode mode) -{ - if (TARGET_H8300SX) - return 0; - - if (GET_CODE (op) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (op); - - /* Force VALUE to be positive so that we do not have to consider - the negative case. */ - if (value < 0) - value = -value; - if (TARGET_H8300H || TARGET_H8300S) - { - /* A constant addition/subtraction takes 2 states in QImode, - 4 states in HImode, and 6 states in SImode. Thus, the - only case we can win is when SImode is used, in which - case, two adds/subs are used, taking 4 states. */ - if (mode == SImode - && (value == 2 + 1 - || value == 4 + 1 - || value == 4 + 2 - || value == 4 + 4)) - return 1; - } - else - { - /* We do not profit directly by splitting addition or - subtraction of 3 and 4. However, since these are - implemented as a sequence of adds or subs, they do not - clobber (cc0) unlike a sequence of add.b and add.x. */ - if (mode == HImode - && (value == 2 + 1 - || value == 2 + 2)) - return 1; - } - } - - return 0; -} - /* Split an add of a small constant into two adds/subs insns. If USE_INCDEC_P is nonzero, we generate the last insn using inc/dec @@ -1231,85 +1016,6 @@ split_adds_subs (enum machine_mode mode, rtx *operands) return; } -/* Return true if OP is a valid call operand, and OP represents - an operand for a small call (4 bytes instead of 6 bytes). */ - -int -small_call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) == MEM) - { - rtx inside = XEXP (op, 0); - - /* Register indirect is a small call. */ - if (register_operand (inside, Pmode)) - return 1; - - /* A call through the function vector is a small call too. */ - if (GET_CODE (inside) == SYMBOL_REF - && (SYMBOL_REF_FLAGS (inside) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) - return 1; - } - /* Otherwise it's a large call. */ - return 0; -} - -/* Return true if OP is a valid jump operand. */ - -int -jump_address_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == REG) - return mode == Pmode; - - if (GET_CODE (op) == MEM) - { - rtx inside = XEXP (op, 0); - if (register_operand (inside, Pmode)) - return 1; - if (CONSTANT_ADDRESS_P (inside)) - return 1; - } - return 0; -} - -/* Recognize valid operands for bit-field instructions. */ - -int -bit_operand (rtx op, enum machine_mode mode) -{ - /* We can accept any nonimmediate operand, except that MEM operands must - be limited to those that use addresses valid for the 'U' constraint. */ - if (!nonimmediate_operand (op, mode)) - return 0; - - /* H8SX accepts pretty much anything here. */ - if (TARGET_H8300SX) - return 1; - - /* Accept any mem during RTL generation. Otherwise, the code that does - insv and extzv will think that we cannot handle memory. However, - to avoid reload problems, we only accept 'U' MEM operands after RTL - generation. This means that any named pattern which uses this predicate - must force its operands to match 'U' before emitting RTL. */ - - if (GET_CODE (op) == REG) - return 1; - if (GET_CODE (op) == SUBREG) - return 1; - return (GET_CODE (op) == MEM - && OK_FOR_U (op)); -} - -/* Return nonzero if OP is a MEM suitable for bit manipulation insns. */ - -int -bit_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == MEM - && OK_FOR_U (op)); -} - /* Handle machine specific pragmas for compatibility with existing compilers for the H8/300. @@ -2258,114 +1964,6 @@ notice_update_cc (rtx body, rtx insn) break; } } - -/* Return nonzero if X is a stack pointer. */ - -int -stack_pointer_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return x == stack_pointer_rtx; -} - -/* Return nonzero if X is a constant whose absolute value is greater - than 2. */ - -int -const_int_gt_2_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (x) == CONST_INT - && abs (INTVAL (x)) > 2); -} - -/* Return nonzero if X is a constant whose absolute value is no - smaller than 8. */ - -int -const_int_ge_8_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (x) == CONST_INT - && abs (INTVAL (x)) >= 8); -} - -/* Return nonzero if X is a constant expressible in QImode. */ - -int -const_int_qi_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (x) == CONST_INT - && (INTVAL (x) & 0xff) == INTVAL (x)); -} - -/* Return nonzero if X is a constant expressible in HImode. */ - -int -const_int_hi_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (x) == CONST_INT - && (INTVAL (x) & 0xffff) == INTVAL (x)); -} - -/* Return nonzero if X is a constant suitable for inc/dec. */ - -int -incdec_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (x) == CONST_INT - && (CONST_OK_FOR_M (INTVAL (x)) - || CONST_OK_FOR_O (INTVAL (x)))); -} - -/* Return nonzero if X is either EQ or NE. */ - -int -eqne_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - enum rtx_code code = GET_CODE (x); - - return (code == EQ || code == NE); -} - -/* Return nonzero if X is either GT or LE. */ - -int -gtle_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - enum rtx_code code = GET_CODE (x); - - return (code == GT || code == LE); -} - -/* Return nonzero if X is either GTU or LEU. */ - -int -gtuleu_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - enum rtx_code code = GET_CODE (x); - - return (code == GTU || code == LEU); -} - -/* Return nonzero if X is either IOR or XOR. */ - -int -iorxor_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - enum rtx_code code = GET_CODE (x); - - return (code == IOR || code == XOR); -} - -/* Recognize valid operators for bit instructions. */ - -int -bit_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - enum rtx_code code = GET_CODE (x); - - return (code == XOR - || code == AND - || code == IOR); -} /* Given that X occurs in an address of the form (plus X constant), return the part of X that is expected to be a register. There are @@ -2896,58 +2494,6 @@ h8300_operands_match_p (rtx *operands) return false; } - -/* Return true if OP is a binary operator in which it would be safe to - replace register operands with memory operands. */ - -int -h8sx_binary_memory_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (!TARGET_H8300SX) - return false; - - if (GET_MODE (op) != QImode - && GET_MODE (op) != HImode - && GET_MODE (op) != SImode) - return false; - - switch (GET_CODE (op)) - { - case PLUS: - case MINUS: - case AND: - case IOR: - case XOR: - return true; - - default: - return h8sx_unary_shift_operator (op, mode); - } -} - -/* Like h8sx_binary_memory_operator, but applies to unary operators. */ - -int -h8sx_unary_memory_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (!TARGET_H8300SX) - return false; - - if (GET_MODE (op) != QImode - && GET_MODE (op) != HImode - && GET_MODE (op) != SImode) - return false; - - switch (GET_CODE (op)) - { - case NEG: - case NOT: - return true; - - default: - return false; - } -} /* Try using movmd to move LENGTH bytes from memory region SRC to memory region DEST. The two regions do not overlap and have the common @@ -4049,26 +3595,6 @@ h8sx_classify_shift (enum machine_mode mode, enum rtx_code code, rtx op) } } -/* Return true if X is a shift operation of type H8SX_SHIFT_UNARY. */ - -int -h8sx_unary_shift_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (BINARY_P (x) && NON_COMMUTATIVE_P (x) - && (h8sx_classify_shift (GET_MODE (x), GET_CODE (x), XEXP (x, 1)) - == H8SX_SHIFT_UNARY)); -} - -/* Likewise H8SX_SHIFT_BINARY. */ - -int -h8sx_binary_shift_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (BINARY_P (x) && NON_COMMUTATIVE_P (x) - && (h8sx_classify_shift (GET_MODE (x), GET_CODE (x), XEXP (x, 1)) - == H8SX_SHIFT_BINARY)); -} - /* Return the asm template for a single h8sx shift instruction. OPERANDS[0] and OPERANDS[1] are the destination, OPERANDS[2] is the source and OPERANDS[3] is the shift. SUFFIX is the @@ -4115,20 +3641,6 @@ output_h8sx_shift (rtx *operands, int suffix, int optype) sprintf (buffer, "%s.%c\t%%X2,%%%c0", stem, suffix, optype); return buffer; } -int -nshift_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - switch (GET_CODE (x)) - { - case ASHIFTRT: - case LSHIFTRT: - case ASHIFT: - return 1; - - default: - return 0; - } -} /* Emit code to do shifts. */ diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h index 7730519aed5..5b131bd7641 100644 --- a/gcc/config/h8300/h8300.h +++ b/gcc/config/h8300/h8300.h @@ -1200,44 +1200,9 @@ extern int h8300_move_ratio; #undef MOVE_RATIO #define MOVE_RATIO h8300_move_ratio -/* Define the codes that are matched by predicates in h8300.c. */ - -#define PREDICATE_CODES \ - {"general_operand_src", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ - LABEL_REF, SUBREG, REG, MEM}}, \ - {"general_operand_dst", {SUBREG, REG, MEM}}, \ - {"h8300_src_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ - LABEL_REF, SUBREG, REG, MEM}}, \ - {"h8300_dst_operand", {SUBREG, REG, MEM}}, \ - {"nibble_operand", {CONST_INT}}, \ - {"reg_or_nibble_operand", {CONST_INT, SUBREG, REG}}, \ - {"h8sx_unary_shift_operator", {ASHIFTRT, LSHIFTRT, ASHIFT, ROTATE}}, \ - {"h8sx_binary_shift_operator", {ASHIFTRT, LSHIFTRT, ASHIFT}}, \ - {"h8sx_binary_memory_operator", {PLUS, MINUS, AND, IOR, XOR, ASHIFT, \ - ASHIFTRT, LSHIFTRT, ROTATE}}, \ - {"h8sx_unary_memory_operator", {NEG, NOT}}, \ - {"h8300_ldm_parallel", {PARALLEL}}, \ - {"h8300_stm_parallel", {PARALLEL}}, \ - {"h8300_return_parallel", {PARALLEL}}, \ - {"single_one_operand", {CONST_INT}}, \ - {"single_zero_operand", {CONST_INT}}, \ - {"call_insn_operand", {MEM}}, \ - {"small_call_insn_operand", {MEM}}, \ - {"jump_address_operand", {REG, MEM}}, \ - {"two_insn_adds_subs_operand", {CONST_INT}}, \ - {"bit_operand", {REG, SUBREG, MEM}}, \ - {"bit_memory_operand", {MEM}}, \ - {"stack_pointer_operand", {REG}}, \ - {"const_int_gt_2_operand", {CONST_INT}}, \ - {"const_int_ge_8_operand", {CONST_INT}}, \ - {"const_int_qi_operand", {CONST_INT}}, \ - {"const_int_hi_operand", {CONST_INT}}, \ - {"incdec_operand", {CONST_INT}}, \ - {"bit_operator", {XOR, AND, IOR}}, \ - {"nshift_operator", {ASHIFTRT, LSHIFTRT, ASHIFT}}, \ - {"eqne_operator", {EQ, NE}}, \ - {"gtle_operator", {GT, LE, GTU, LEU}}, \ - {"gtuleu_operator", {GTU, LEU}}, \ - {"iorxor_operator", {IOR, XOR}}, +/* Machine-specific symbol_ref flags. */ +#define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0) +#define SYMBOL_FLAG_EIGHTBIT_DATA (SYMBOL_FLAG_MACH_DEP << 1) +#define SYMBOL_FLAG_TINY_DATA (SYMBOL_FLAG_MACH_DEP << 2) #endif /* ! GCC_H8300_H */ diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index ffdd0cc4783..cfd6c1b8d1c 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -175,6 +175,8 @@ (ne (symbol_ref "TARGET_H8300H") (const_int 0)) (const_int 10) (ne (symbol_ref "TARGET_H8300S") (const_int 0)) (const_int 10)] (const_int 14)))]) + +(include "predicates.md") ;; ---------------------------------------------------------------------- ;; MOVE INSTRUCTIONS diff --git a/gcc/config/h8300/predicates.md b/gcc/config/h8300/predicates.md new file mode 100644 index 00000000000..a913e8bf247 --- /dev/null +++ b/gcc/config/h8300/predicates.md @@ -0,0 +1,483 @@ +;; Predicate definitions for Renesas H8/300. +;; 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 true if OP is a valid source operand for an integer move +;; instruction. + +(define_predicate "general_operand_src" + (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,mem") +{ + if (GET_MODE (op) == mode + && GET_CODE (op) == MEM + && GET_CODE (XEXP (op, 0)) == POST_INC) + return 1; + return general_operand (op, mode); +}) + +;; Return true if OP is a valid destination operand for an integer +;; move instruction. + +(define_predicate "general_operand_dst" + (match_code "subreg,reg,mem") +{ + if (GET_MODE (op) == mode + && GET_CODE (op) == MEM + && GET_CODE (XEXP (op, 0)) == PRE_DEC) + return 1; + return general_operand (op, mode); +}) + +;; Likewise the second operand. + +(define_predicate "h8300_src_operand" + (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,mem") +{ + if (TARGET_H8300SX) + return general_operand (op, mode); + return nonmemory_operand (op, mode); +}) + +;; Return true if OP is a suitable first operand for a general +;; arithmetic insn such as "add". + +(define_predicate "h8300_dst_operand" + (match_code "subreg,reg,mem") +{ + if (TARGET_H8300SX) + return nonimmediate_operand (op, mode); + return register_operand (op, mode); +}) + +;; Check that an operand is either a register or an unsigned 4-bit +;; constant. + +(define_predicate "nibble_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT && TARGET_H8300SX + && INTVAL (op) >= 0 && INTVAL (op) <= 15); +}) + +;; Check that an operand is either a register or an unsigned 4-bit +;; constant. + +(define_predicate "reg_or_nibble_operand" + (match_code "const_int,subreg,reg") +{ + return (nibble_operand (op, mode) || register_operand (op, mode)); +}) + +;; Return true if X is a shift operation of type H8SX_SHIFT_UNARY. + +(define_predicate "h8sx_unary_shift_operator" + (match_code "ashiftrt,lshiftrt,ashift,rotate") +{ + return (BINARY_P (op) && NON_COMMUTATIVE_P (op) + && (h8sx_classify_shift (GET_MODE (op), GET_CODE (op), XEXP (op, 1)) + == H8SX_SHIFT_UNARY)); +}) + +;; Likewise H8SX_SHIFT_BINARY. + +(define_predicate "h8sx_binary_shift_operator" + (match_code "ashiftrt,lshiftrt,ashift") +{ + return (BINARY_P (op) && NON_COMMUTATIVE_P (op) + && (h8sx_classify_shift (GET_MODE (op), GET_CODE (op), XEXP (op, 1)) + == H8SX_SHIFT_BINARY)); +}) + +;; Return true if OP is a binary operator in which it would be safe to +;; replace register operands with memory operands. + +(define_predicate "h8sx_binary_memory_operator" + (match_code "plus,minus,and,ior,xor,ashift,ashiftrt,lshiftrt,rotate") +{ + if (!TARGET_H8300SX) + return false; + + if (GET_MODE (op) != QImode + && GET_MODE (op) != HImode + && GET_MODE (op) != SImode) + return false; + + switch (GET_CODE (op)) + { + case PLUS: + case MINUS: + case AND: + case IOR: + case XOR: + return true; + + default: + return h8sx_unary_shift_operator (op, mode); + } +}) + +;; Like h8sx_binary_memory_operator, but applies to unary operators. + +(define_predicate "h8sx_unary_memory_operator" + (match_code "neg,not") +{ + if (!TARGET_H8300SX) + return false; + + if (GET_MODE (op) != QImode + && GET_MODE (op) != HImode + && GET_MODE (op) != SImode) + return false; + + switch (GET_CODE (op)) + { + case NEG: + case NOT: + return true; + + default: + return false; + } +}) + +;; Return true if X is an ldm.l pattern. X is known to be parallel. + +(define_predicate "h8300_ldm_parallel" + (match_code "parallel") +{ + return h8300_ldm_stm_parallel (XVEC (op, 0), 1, 0); +}) + +;; Likewise stm.l. + +(define_predicate "h8300_stm_parallel" + (match_code "parallel") +{ + return h8300_ldm_stm_parallel (XVEC (op, 0), 0, 0); +}) + +;; Likewise rts/l and rte/l. Note that the .md pattern will check for +;; the return so there's no need to do that here. + +(define_predicate "h8300_return_parallel" + (match_code "parallel") +{ + return h8300_ldm_stm_parallel (XVEC (op, 0), 1, 1); +}) + +;; Return true if OP is a constant that contains only one 1 in its +;; binary representation. + +(define_predicate "single_one_operand" + (match_code "const_int") +{ + if (GET_CODE (op) == CONST_INT) + { + /* We really need to do this masking because 0x80 in QImode is + represented as -128 for example. */ + if (exact_log2 (INTVAL (op) & GET_MODE_MASK (mode)) >= 0) + return 1; + } + + return 0; +}) + +;; Return true if OP is a constant that contains only one 0 in its +;; binary representation. + +(define_predicate "single_zero_operand" + (match_code "const_int") +{ + if (GET_CODE (op) == CONST_INT) + { + /* We really need to do this masking because 0x80 in QImode is + represented as -128 for example. */ + if (exact_log2 (~INTVAL (op) & GET_MODE_MASK (mode)) >= 0) + return 1; + } + + return 0; +}) + +;; Return true if OP is a valid call operand. + +(define_predicate "call_insn_operand" + (match_code "mem") +{ + if (GET_CODE (op) == MEM) + { + rtx inside = XEXP (op, 0); + if (register_operand (inside, Pmode)) + return 1; + if (CONSTANT_ADDRESS_P (inside)) + return 1; + } + return 0; +}) + +;; Return true if OP is a valid call operand, and OP represents an +;; operand for a small call (4 bytes instead of 6 bytes). + +(define_predicate "small_call_insn_operand" + (match_code "mem") +{ + if (GET_CODE (op) == MEM) + { + rtx inside = XEXP (op, 0); + + /* Register indirect is a small call. */ + if (register_operand (inside, Pmode)) + return 1; + + /* A call through the function vector is a small call too. */ + if (GET_CODE (inside) == SYMBOL_REF + && (SYMBOL_REF_FLAGS (inside) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) + return 1; + } + /* Otherwise it's a large call. */ + return 0; +}) + +;; Return true if OP is a valid jump operand. + +(define_predicate "jump_address_operand" + (match_code "reg,mem") +{ + if (GET_CODE (op) == REG) + return mode == Pmode; + + if (GET_CODE (op) == MEM) + { + rtx inside = XEXP (op, 0); + if (register_operand (inside, Pmode)) + return 1; + if (CONSTANT_ADDRESS_P (inside)) + return 1; + } + return 0; +}) + +;; Return 1 if an addition/subtraction of a constant integer can be +;; transformed into two consecutive adds/subs that are faster than the +;; straightforward way. Otherwise, return 0. + +(define_predicate "two_insn_adds_subs_operand" + (match_code "const_int") +{ + if (TARGET_H8300SX) + return 0; + + if (GET_CODE (op) == CONST_INT) + { + HOST_WIDE_INT value = INTVAL (op); + + /* Force VALUE to be positive so that we do not have to consider + the negative case. */ + if (value < 0) + value = -value; + if (TARGET_H8300H || TARGET_H8300S) + { + /* A constant addition/subtraction takes 2 states in QImode, + 4 states in HImode, and 6 states in SImode. Thus, the + only case we can win is when SImode is used, in which + case, two adds/subs are used, taking 4 states. */ + if (mode == SImode + && (value == 2 + 1 + || value == 4 + 1 + || value == 4 + 2 + || value == 4 + 4)) + return 1; + } + else + { + /* We do not profit directly by splitting addition or + subtraction of 3 and 4. However, since these are + implemented as a sequence of adds or subs, they do not + clobber (cc0) unlike a sequence of add.b and add.x. */ + if (mode == HImode + && (value == 2 + 1 + || value == 2 + 2)) + return 1; + } + } + + return 0; +}) + +;; Recognize valid operands for bit-field instructions. + +(define_predicate "bit_operand" + (match_code "reg,subreg,mem") +{ + /* We can accept any nonimmediate operand, except that MEM operands must + be limited to those that use addresses valid for the 'U' constraint. */ + if (!nonimmediate_operand (op, mode)) + return 0; + + /* H8SX accepts pretty much anything here. */ + if (TARGET_H8300SX) + return 1; + + /* Accept any mem during RTL generation. Otherwise, the code that does + insv and extzv will think that we cannot handle memory. However, + to avoid reload problems, we only accept 'U' MEM operands after RTL + generation. This means that any named pattern which uses this predicate + must force its operands to match 'U' before emitting RTL. */ + + if (GET_CODE (op) == REG) + return 1; + if (GET_CODE (op) == SUBREG) + return 1; + return (GET_CODE (op) == MEM + && OK_FOR_U (op)); +}) + +;; Return nonzero if OP is a MEM suitable for bit manipulation insns. + +(define_predicate "bit_memory_operand" + (match_code "mem") +{ + return (GET_CODE (op) == MEM + && OK_FOR_U (op)); +}) + +;; Return nonzero if X is a stack pointer. + +(define_predicate "stack_pointer_operand" + (match_code "reg") +{ + return op == stack_pointer_rtx; +}) + +;; Return nonzero if X is a constant whose absolute value is greater +;; than 2. + +(define_predicate "const_int_gt_2_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT + && abs (INTVAL (op)) > 2); +}) + +;; Return nonzero if X is a constant whose absolute value is no +;; smaller than 8. + +(define_predicate "const_int_ge_8_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT + && abs (INTVAL (op)) >= 8); +}) + +;; Return nonzero if X is a constant expressible in QImode. + +(define_predicate "const_int_qi_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT + && (INTVAL (op) & 0xff) == INTVAL (op)); +}) + +;; Return nonzero if X is a constant expressible in HImode. + +(define_predicate "const_int_hi_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT + && (INTVAL (op) & 0xffff) == INTVAL (op)); +}) + +;; Return nonzero if X is a constant suitable for inc/dec. + +(define_predicate "incdec_operand" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT + && (CONST_OK_FOR_M (INTVAL (op)) + || CONST_OK_FOR_O (INTVAL (op)))); +}) + +;; Recognize valid operators for bit instructions. + +(define_predicate "bit_operator" + (match_code "xor,and,ior") +{ + enum rtx_code code = GET_CODE (op); + + return (code == XOR + || code == AND + || code == IOR); +}) + +;; Return nonzero if OP is a shift operator. + +(define_predicate "nshift_operator" + (match_code "ashiftrt,lshiftrt,ashift") +{ + switch (GET_CODE (op)) + { + case ASHIFTRT: + case LSHIFTRT: + case ASHIFT: + return 1; + + default: + return 0; + } +}) + +;; Return nonzero if X is either EQ or NE. + +(define_predicate "eqne_operator" + (match_code "eq,ne") +{ + enum rtx_code code = GET_CODE (op); + + return (code == EQ || code == NE); +}) + +;; Return nonzero if X is either GT or LE. + +(define_predicate "gtle_operator" + (match_code "gt,le,gtu,leu") +{ + enum rtx_code code = GET_CODE (op); + + return (code == GT || code == LE); +}) + +;; Return nonzero if X is either GTU or LEU. + +(define_predicate "gtuleu_operator" + (match_code "gtu,leu") +{ + enum rtx_code code = GET_CODE (op); + + return (code == GTU || code == LEU); +}) + +;; Return nonzero if X is either IOR or XOR. + +(define_predicate "iorxor_operator" + (match_code "ior,xor") +{ + enum rtx_code code = GET_CODE (op); + + return (code == IOR || code == XOR); +}) -- 2.30.2