aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKazu Hirata <kazu@cs.umass.edu>2005-03-18 18:05:54 +0000
committerNick Clifton <nickc@gcc.gnu.org>2005-03-18 18:05:54 +0000
commit22a14e0dccd8e24ace4f1c617e47c96d2d69bba6 (patch)
treead8f63003bb950c0a16efe355b5e656c1bf0865b
parent0a1948ed7bfda7c4e3ca6504727b129f000be860 (diff)
downloadgcc-22a14e0dccd8e24ace4f1c617e47c96d2d69bba6.zip
gcc-22a14e0dccd8e24ace4f1c617e47c96d2d69bba6.tar.gz
gcc-22a14e0dccd8e24ace4f1c617e47c96d2d69bba6.tar.bz2
config/m32r/m32r-protos.h...
config/m32r/m32r-protos.h: Remove the prototypes for call_address_operand, symbolic_operand, seth_add3_operand, cmp_int16_operand, uint16_operand, reg_or_int16_operand, reg_or_uint16_operand, reg_or_cmp_int16_operand, two_insn_const_operand, move_src_operand, move_double_src_operand, move_dest_operand, eqne_comparison_operator, signed_comparison_operator, large_insn_p, conditional_move_operand, carry_compare_operand, m32r_block_immediate_operand, extend_operand, reg_or_eq_int16_operand, int8_operand, and reg_or_zero_operand. * config/m32r/m32r.c (call_address_operand, symbolic_operand, seth_add3_operand, int8_operand, cmp_int16_operand, uint16_operand, reg_or_int16_operand, reg_or_uint16_operand, reg_or_eq_int16_operand, reg_or_cmp_int16_operand, reg_or_zero_operand, two_insn_const_operand, move_src_operand, move_double_src_operand, move_dest_operand, eqne_comparison_operator, signed_comparison_operator, extend_operand, small_insn_p, large_insn_p, conditional_move_operand, carry_compare_operand, m32r_block_immediate_operand): Move to predicates.md. (MAX_MOVE_BYTES): Move to m32r.h. * config/m32r/m32r.h (PREDICATE_CODES): Remove. * config/m32r/m32r.md: Include predicates.md. * config/m32r/predicates.md: New. From-SVN: r96691
-rw-r--r--gcc/ChangeLog28
-rw-r--r--gcc/config/m32r/m32r-protos.h24
-rw-r--r--gcc/config/m32r/m32r.c430
-rw-r--r--gcc/config/m32r/m32r.h45
-rw-r--r--gcc/config/m32r/m32r.md2
-rw-r--r--gcc/config/m32r/predicates.md442
6 files changed, 483 insertions, 488 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2dc5a40..6adc260 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,31 @@
+2005-03-18 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,
+ cmp_int16_operand, uint16_operand, reg_or_int16_operand,
+ reg_or_uint16_operand, reg_or_cmp_int16_operand,
+ two_insn_const_operand, move_src_operand,
+ move_double_src_operand, move_dest_operand,
+ eqne_comparison_operator, signed_comparison_operator,
+ large_insn_p, conditional_move_operand, carry_compare_operand,
+ m32r_block_immediate_operand, extend_operand,
+ reg_or_eq_int16_operand, int8_operand, and
+ reg_or_zero_operand.
+ * config/m32r/m32r.c (call_address_operand, symbolic_operand,
+ seth_add3_operand, int8_operand, cmp_int16_operand,
+ uint16_operand, reg_or_int16_operand, reg_or_uint16_operand,
+ reg_or_eq_int16_operand, reg_or_cmp_int16_operand,
+ reg_or_zero_operand, two_insn_const_operand, move_src_operand,
+ move_double_src_operand, move_dest_operand,
+ eqne_comparison_operator, signed_comparison_operator,
+ extend_operand, small_insn_p, large_insn_p,
+ conditional_move_operand, carry_compare_operand,
+ m32r_block_immediate_operand): Move to predicates.md.
+ (MAX_MOVE_BYTES): Move to m32r.h.
+ * config/m32r/m32r.h (PREDICATE_CODES): Remove.
+ * config/m32r/m32r.md: Include predicates.md.
+ * config/m32r/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/m32r/m32r-protos.h b/gcc/config/m32r/m32r-protos.h
index 2ea6a59..0f72bd7 100644
--- a/gcc/config/m32r/m32r-protos.h
+++ b/gcc/config/m32r/m32r-protos.h
@@ -1,5 +1,5 @@
/* Prototypes for m32r.c functions used in the md file & elsewhere.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GCC.
@@ -58,35 +58,13 @@ extern rtx m32r_return_addr (int);
extern rtx m32r_function_symbol (const char *);
#ifdef HAVE_MACHINE_MODES
-extern int call_address_operand (rtx, Mmode);
extern int call_operand (rtx, Mmode);
-extern int symbolic_operand (rtx, Mmode);
extern int small_data_operand (rtx, Mmode);
extern int addr24_operand (rtx, Mmode);
extern int addr32_operand (rtx, Mmode);
extern int call26_operand (rtx, Mmode);
-extern int seth_add3_operand (rtx, Mmode);
-extern int cmp_int16_operand (rtx, Mmode);
-extern int uint16_operand (rtx, Mmode);
-extern int reg_or_int16_operand (rtx, Mmode);
-extern int reg_or_uint16_operand (rtx, Mmode);
-extern int reg_or_cmp_int16_operand (rtx, Mmode);
-extern int two_insn_const_operand (rtx, Mmode);
-extern int move_src_operand (rtx, Mmode);
-extern int move_double_src_operand (rtx, Mmode);
-extern int move_dest_operand (rtx, Mmode);
-extern int eqne_comparison_operator (rtx, Mmode);
-extern int signed_comparison_operator (rtx, Mmode);
extern int memreg_operand (rtx, Mmode);
extern int small_insn_p (rtx, Mmode);
-extern int large_insn_p (rtx, Mmode);
-extern int conditional_move_operand (rtx, Mmode);
-extern int carry_compare_operand (rtx, Mmode);
-extern int m32r_block_immediate_operand (rtx, Mmode);
-extern int extend_operand (rtx, Mmode);
-extern int reg_or_eq_int16_operand (rtx, Mmode);
-extern int int8_operand (rtx, Mmode);
-extern int reg_or_zero_operand (rtx, Mmode);
#endif /* HAVE_MACHINE_MODES */
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 170c4c6..dd86186 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -1,6 +1,6 @@
/* Subroutines used for code generation on the Renesas M32R cpu.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -472,17 +472,6 @@ m32r_init_expanders (void)
to make it easy to experiment. */
}
-/* Acceptable arguments to the call insn. */
-
-int
-call_address_operand (rtx op, enum machine_mode mode)
-{
- return symbolic_operand (op, mode);
-
-/* Constants and values in registers are not OK, because
- the m32r BL instruction can only support PC relative branching. */
-}
-
int
call_operand (rtx op, enum machine_mode mode)
{
@@ -492,23 +481,6 @@ call_operand (rtx op, enum machine_mode mode)
return call_address_operand (op, mode);
}
-/* Returns 1 if OP is a symbol reference. */
-
-int
-symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- case LABEL_REF:
- case CONST :
- return 1;
-
- default:
- return 0;
- }
-}
-
/* Return 1 if OP is a reference to an object in .sdata/.sbss. */
int
@@ -604,256 +576,6 @@ call26_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
return TARGET_CALL26;
}
-/* Returns 1 if OP is an acceptable operand for seth/add3. */
-
-int
-seth_add3_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (flag_pic)
- return 0;
-
- if (GET_CODE (op) == SYMBOL_REF
- || GET_CODE (op) == LABEL_REF)
- return 1;
-
- if (GET_CODE (op) == CONST
- && GET_CODE (XEXP (op, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
- && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
- && INT16_P (INTVAL (XEXP (XEXP (op, 0), 1))))
- return 1;
-
- return 0;
-}
-
-/* Return true if OP is a signed 8 bit immediate value. */
-
-int
-int8_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != CONST_INT)
- return 0;
- return INT8_P (INTVAL (op));
-}
-
-/* Return true if OP is a signed 16 bit immediate value
- useful in comparisons. */
-
-int
-cmp_int16_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != CONST_INT)
- return 0;
- return CMP_INT16_P (INTVAL (op));
-}
-
-/* Return true if OP is an unsigned 16 bit immediate value. */
-
-int
-uint16_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != CONST_INT)
- return 0;
- return UINT16_P (INTVAL (op));
-}
-
-/* Return true if OP is a register or signed 16 bit value. */
-
-int
-reg_or_int16_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
- return register_operand (op, mode);
- if (GET_CODE (op) != CONST_INT)
- return 0;
- return INT16_P (INTVAL (op));
-}
-
-/* Return true if OP is a register or an unsigned 16 bit value. */
-
-int
-reg_or_uint16_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
- return register_operand (op, mode);
- if (GET_CODE (op) != CONST_INT)
- return 0;
- return UINT16_P (INTVAL (op));
-}
-
-/* Return true if OP is a register or an integer value that can be
- used is SEQ/SNE. We can use either XOR of the value or ADD of
- the negative of the value for the constant. Don't allow 0,
- because that is special cased. */
-
-int
-reg_or_eq_int16_operand (rtx op, enum machine_mode mode)
-{
- HOST_WIDE_INT value;
-
- if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
- return register_operand (op, mode);
-
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- value = INTVAL (op);
- return (value != 0) && (UINT16_P (value) || CMP_INT16_P (-value));
-}
-
-/* Return true if OP is a register or signed 16 bit value for compares. */
-
-int
-reg_or_cmp_int16_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
- return register_operand (op, mode);
- if (GET_CODE (op) != CONST_INT)
- return 0;
- return CMP_INT16_P (INTVAL (op));
-}
-
-/* Return true if OP is a register or the constant 0. */
-
-int
-reg_or_zero_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
- return register_operand (op, mode);
-
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- return INTVAL (op) == 0;
-}
-
-/* Return true if OP is a const_int requiring two instructions to load. */
-
-int
-two_insn_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != CONST_INT)
- return 0;
- if (INT16_P (INTVAL (op))
- || UINT24_P (INTVAL (op))
- || UPPER16_P (INTVAL (op)))
- return 0;
- return 1;
-}
-
-/* Return true if OP is an acceptable argument for a single word
- move source. */
-
-int
-move_src_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case LABEL_REF :
- case SYMBOL_REF :
- case CONST :
- return addr24_operand (op, mode);
- case CONST_INT :
- /* ??? We allow more cse opportunities if we only allow constants
- loadable with one insn, and split the rest into two. The instances
- where this would help should be rare and the current way is
- simpler. */
- if (HOST_BITS_PER_WIDE_INT > 32)
- {
- HOST_WIDE_INT rest = INTVAL (op) >> 31;
- return (rest == 0 || rest == -1);
- }
- else
- return 1;
- case CONST_DOUBLE :
- if (mode == SFmode)
- return 1;
- else if (mode == SImode)
- {
- /* Large unsigned constants are represented as const_double's. */
- unsigned HOST_WIDE_INT low, high;
-
- low = CONST_DOUBLE_LOW (op);
- high = CONST_DOUBLE_HIGH (op);
- return high == 0 && low <= (unsigned) 0xffffffff;
- }
- else
- return 0;
- case REG :
- return register_operand (op, mode);
- case SUBREG :
- /* (subreg (mem ...) ...) can occur here if the inner part was once a
- pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
- return address_operand (XEXP (SUBREG_REG (op), 0), mode);
- else
- return register_operand (op, mode);
- case MEM :
- if (GET_CODE (XEXP (op, 0)) == PRE_INC
- || GET_CODE (XEXP (op, 0)) == PRE_DEC)
- return 0; /* loads can't do pre-{inc,dec} */
- return address_operand (XEXP (op, 0), mode);
- default :
- return 0;
- }
-}
-
-/* Return true if OP is an acceptable argument for a double word
- move source. */
-
-int
-move_double_src_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case CONST_INT :
- case CONST_DOUBLE :
- return 1;
- case REG :
- return register_operand (op, mode);
- case SUBREG :
- /* (subreg (mem ...) ...) can occur here if the inner part was once a
- pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
- return move_double_src_operand (SUBREG_REG (op), mode);
- else
- return register_operand (op, mode);
- case MEM :
- /* Disallow auto inc/dec for now. */
- if (GET_CODE (XEXP (op, 0)) == PRE_DEC
- || GET_CODE (XEXP (op, 0)) == PRE_INC)
- return 0;
- return address_operand (XEXP (op, 0), mode);
- default :
- return 0;
- }
-}
-
-/* Return true if OP is an acceptable argument for a move destination. */
-
-int
-move_dest_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case REG :
- return register_operand (op, mode);
- case SUBREG :
- /* (subreg (mem ...) ...) can occur here if the inner part was once a
- pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
- return address_operand (XEXP (SUBREG_REG (op), 0), mode);
- else
- return register_operand (op, mode);
- case MEM :
- if (GET_CODE (XEXP (op, 0)) == POST_INC)
- return 0; /* stores can't do post inc */
- return address_operand (XEXP (op, 0), mode);
- default :
- return 0;
- }
-}
-
/* Return 1 if OP is a DImode const we want to handle inline.
This must match the code in the movdi pattern.
It is used by the 'G' CONST_DOUBLE_OK_FOR_LETTER. */
@@ -893,28 +615,6 @@ easy_df_const (rtx op)
return 0;
}
-/* Return 1 if OP is an EQ or NE comparison operator. */
-
-int
-eqne_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
-
- return (code == EQ || code == NE);
-}
-
-/* Return 1 if OP is a signed comparison operator. */
-
-int
-signed_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
-
- return (COMPARISON_P (op)
- && (code == EQ || code == NE
- || code == LT || code == LE || code == GT || code == GE));
-}
-
/* Return 1 if OP is (mem (reg ...)).
This is used in insn length calcs. */
@@ -924,58 +624,6 @@ memreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG;
}
-/* Return true if OP is an acceptable input argument for a zero/sign extend
- operation. */
-
-int
-extend_operand (rtx op, enum machine_mode mode)
-{
- rtx addr;
-
- switch (GET_CODE (op))
- {
- case REG :
- case SUBREG :
- return register_operand (op, mode);
-
- case MEM :
- addr = XEXP (op, 0);
- if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
- return 0; /* loads can't do pre inc/pre dec */
-
- return address_operand (addr, mode);
-
- default :
- return 0;
- }
-}
-
-/* Return nonzero if the operand is an insn that is a small insn.
- Allow const_int 0 as well, which is a placeholder for NOP slots. */
-
-int
-small_insn_p (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
- return 1;
-
- if (! INSN_P (op))
- return 0;
-
- return get_attr_length (op) == 2;
-}
-
-/* Return nonzero if the operand is an insn that is a large insn. */
-
-int
-large_insn_p (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (! INSN_P (op))
- return 0;
-
- return get_attr_length (op) != 2;
-}
-
/* Return nonzero if TYPE must be passed by indirect reference. */
static bool
@@ -2424,59 +2072,6 @@ zero_and_one (rtx operand1, rtx operand2)
||((INTVAL (operand1) == 1) && (INTVAL (operand2) == 0)));
}
-/* Return nonzero if the operand is suitable for use in a conditional move sequence. */
-
-int
-conditional_move_operand (rtx operand, enum machine_mode mode)
-{
- /* Only defined for simple integers so far... */
- if (mode != SImode && mode != HImode && mode != QImode)
- return FALSE;
-
- /* At the moment we can handle moving registers and loading constants. */
- /* To be added: Addition/subtraction/bitops/multiplication of registers. */
-
- switch (GET_CODE (operand))
- {
- case REG:
- return 1;
-
- case CONST_INT:
- return INT8_P (INTVAL (operand));
-
- default:
-#if 0
- fprintf (stderr, "Test for cond move op of type: %s\n",
- GET_RTX_NAME (GET_CODE (operand)));
-#endif
- return 0;
- }
-}
-
-/* Return true if the code is a test of the carry bit. */
-
-int
-carry_compare_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- rtx x;
-
- if (GET_MODE (op) != CCmode && GET_MODE (op) != VOIDmode)
- return FALSE;
-
- if (GET_CODE (op) != NE && GET_CODE (op) != EQ)
- return FALSE;
-
- x = XEXP (op, 0);
- if (GET_CODE (x) != REG || REGNO (x) != CARRY_REGNUM)
- return FALSE;
-
- x = XEXP (op, 1);
- if (GET_CODE (x) != CONST_INT || INTVAL (x) != 0)
- return FALSE;
-
- return TRUE;
-}
-
/* Generate the correct assembler code to handle the conditional loading of a
value into a register. It is known that the operands satisfy the
conditional_move_operand() function above. The destination is operand[0].
@@ -2583,13 +2178,6 @@ block_move_call (rtx dest_reg, rtx src_reg, rtx bytes_rtx)
TYPE_MODE (sizetype));
}
-/* The maximum number of bytes to copy using pairs of load/store instructions.
- If a block is larger than this then a loop will be generated to copy
- MAX_MOVE_BYTES chunks at a time. The value of 32 is a semi-arbitrary choice.
- A customer uses Dhrystome as their benchmark, and Dhrystone has a 31 byte
- string copy in it. */
-#define MAX_MOVE_BYTES 32
-
/* Expand string/block move operations.
operands[0] is the pointer to the destination.
@@ -2836,20 +2424,6 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
}
}
-/* Return true if op is an integer constant, less than or equal to
- MAX_MOVE_BYTES. */
-
-int
-m32r_block_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != CONST_INT
- || INTVAL (op) > MAX_MOVE_BYTES
- || INTVAL (op) <= 0)
- return 0;
-
- return 1;
-}
-
/* Return true if using NEW_REG in place of OLD_REG is ok. */
int
diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h
index 2ebda2a..82c1564 100644
--- a/gcc/config/m32r/m32r.h
+++ b/gcc/config/m32r/m32r.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, Renesas M32R cpu.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -1740,38 +1740,9 @@ enum m32r_function_type
#define M32R_INTERRUPT_P(TYPE) ((TYPE) == M32R_FUNCTION_INTERRUPT)
-/* Define this if you have defined special-purpose predicates in the
- file `MACHINE.c'. This macro is called within an initializer of an
- array of structures. The first field in the structure is the name
- of a predicate and the second field is an array of rtl codes. For
- each predicate, list all rtl codes that can be in expressions
- matched by the predicate. The list should have a trailing comma. */
-
-#define PREDICATE_CODES \
-{ "reg_or_zero_operand", { REG, SUBREG, CONST_INT }}, \
-{ "conditional_move_operand", { REG, SUBREG, CONST_INT }}, \
-{ "carry_compare_operand", { EQ, NE }}, \
-{ "eqne_comparison_operator", { EQ, NE }}, \
-{ "signed_comparison_operator", { EQ, NE, LT, LE, GT, GE }}, \
-{ "move_dest_operand", { REG, SUBREG, MEM }}, \
-{ "move_src_operand", { REG, SUBREG, MEM, CONST_INT, \
- CONST_DOUBLE, LABEL_REF, CONST, \
- SYMBOL_REF }}, \
-{ "move_double_src_operand", { REG, SUBREG, MEM, CONST_INT, \
- CONST_DOUBLE }}, \
-{ "two_insn_const_operand", { CONST_INT }}, \
-{ "symbolic_operand", { SYMBOL_REF, LABEL_REF, CONST }}, \
-{ "int8_operand", { CONST_INT }}, \
-{ "uint16_operand", { CONST_INT }}, \
-{ "reg_or_int16_operand", { REG, SUBREG, CONST_INT }}, \
-{ "reg_or_uint16_operand", { REG, SUBREG, CONST_INT }}, \
-{ "reg_or_cmp_int16_operand", { REG, SUBREG, CONST_INT }}, \
-{ "reg_or_eq_int16_operand", { REG, SUBREG, CONST_INT }}, \
-{ "cmp_int16_operand", { CONST_INT }}, \
-{ "call_address_operand", { SYMBOL_REF, LABEL_REF, CONST }}, \
-{ "extend_operand", { REG, SUBREG, MEM }}, \
-{ "small_insn_p", { INSN, CALL_INSN, JUMP_INSN }}, \
-{ "m32r_block_immediate_operand",{ CONST_INT }}, \
-{ "large_insn_p", { INSN, CALL_INSN, JUMP_INSN }}, \
-{ "seth_add3_operand", { SYMBOL_REF, LABEL_REF, CONST }},
-
+/* The maximum number of bytes to copy using pairs of load/store instructions.
+ If a block is larger than this then a loop will be generated to copy
+ MAX_MOVE_BYTES chunks at a time. The value of 32 is a semi-arbitrary choice.
+ A customer uses Dhrystome as their benchmark, and Dhrystone has a 31 byte
+ string copy in it. */
+#define MAX_MOVE_BYTES 32
diff --git a/gcc/config/m32r/m32r.md b/gcc/config/m32r/m32r.md
index 80c579d..6b799709d 100644
--- a/gcc/config/m32r/m32r.md
+++ b/gcc/config/m32r/m32r.md
@@ -199,6 +199,8 @@
"long_IF,long_E,memory*2")
+(include "predicates.md")
+
;; Expand prologue as RTL
(define_expand "prologue"
[(const_int 1)]
diff --git a/gcc/config/m32r/predicates.md b/gcc/config/m32r/predicates.md
new file mode 100644
index 0000000..d8561d6
--- /dev/null
+++ b/gcc/config/m32r/predicates.md
@@ -0,0 +1,442 @@
+;; Predicate definitions for Renesas M32R.
+;; 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 register or the constant 0.
+
+(define_predicate "reg_or_zero_operand"
+ (match_code "reg,subreg,const_int")
+{
+ if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+ return register_operand (op, mode);
+
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+
+ return INTVAL (op) == 0;
+})
+
+;; Return nonzero if the operand is suitable for use in a conditional
+;; move sequence.
+
+(define_predicate "conditional_move_operand"
+ (match_code "reg,subreg,const_int")
+{
+ /* Only defined for simple integers so far... */
+ if (mode != SImode && mode != HImode && mode != QImode)
+ return FALSE;
+
+ /* At the moment we can handle moving registers and loading constants. */
+ /* To be added: Addition/subtraction/bitops/multiplication of registers. */
+
+ switch (GET_CODE (op))
+ {
+ case REG:
+ return 1;
+
+ case CONST_INT:
+ return INT8_P (INTVAL (op));
+
+ default:
+#if 0
+ fprintf (stderr, "Test for cond move op of type: %s\n",
+ GET_RTX_NAME (GET_CODE (op)));
+#endif
+ return 0;
+ }
+})
+
+;; Return true if the code is a test of the carry bit.
+
+(define_predicate "carry_compare_operand"
+ (match_code "eq,ne")
+{
+ rtx x;
+
+ if (GET_MODE (op) != CCmode && GET_MODE (op) != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) != NE && GET_CODE (op) != EQ)
+ return FALSE;
+
+ x = XEXP (op, 0);
+ if (GET_CODE (x) != REG || REGNO (x) != CARRY_REGNUM)
+ return FALSE;
+
+ x = XEXP (op, 1);
+ if (GET_CODE (x) != CONST_INT || INTVAL (x) != 0)
+ return FALSE;
+
+ return TRUE;
+})
+
+;; Return 1 if OP is an EQ or NE comparison operator.
+
+(define_predicate "eqne_comparison_operator"
+ (match_code "eq,ne")
+{
+ enum rtx_code code = GET_CODE (op);
+
+ return (code == EQ || code == NE);
+})
+
+;; Return 1 if OP is a signed comparison operator.
+
+(define_predicate "signed_comparison_operator"
+ (match_code "eq,ne,lt,le,gt,ge")
+{
+ enum rtx_code code = GET_CODE (op);
+
+ return (COMPARISON_P (op)
+ && (code == EQ || code == NE
+ || code == LT || code == LE || code == GT || code == GE));
+})
+
+;; Return true if OP is an acceptable argument for a move destination.
+
+(define_predicate "move_dest_operand"
+ (match_code "reg,subreg,mem")
+{
+ switch (GET_CODE (op))
+ {
+ case REG :
+ return register_operand (op, mode);
+ case SUBREG :
+ /* (subreg (mem ...) ...) can occur here if the inner part was once a
+ pseudo-reg and is now a stack slot. */
+ if (GET_CODE (SUBREG_REG (op)) == MEM)
+ return address_operand (XEXP (SUBREG_REG (op), 0), mode);
+ else
+ return register_operand (op, mode);
+ case MEM :
+ if (GET_CODE (XEXP (op, 0)) == POST_INC)
+ return 0; /* stores can't do post inc */
+ return address_operand (XEXP (op, 0), mode);
+ default :
+ return 0;
+ }
+})
+
+;; Return true if OP is an acceptable argument for a single word move
+;; source.
+
+(define_predicate "move_src_operand"
+ (match_code "reg,subreg,mem,const_int,const_double,label_ref,const,symbol_ref")
+{
+ switch (GET_CODE (op))
+ {
+ case LABEL_REF :
+ case SYMBOL_REF :
+ case CONST :
+ return addr24_operand (op, mode);
+ case CONST_INT :
+ /* ??? We allow more cse opportunities if we only allow constants
+ loadable with one insn, and split the rest into two. The instances
+ where this would help should be rare and the current way is
+ simpler. */
+ if (HOST_BITS_PER_WIDE_INT > 32)
+ {
+ HOST_WIDE_INT rest = INTVAL (op) >> 31;
+ return (rest == 0 || rest == -1);
+ }
+ else
+ return 1;
+ case CONST_DOUBLE :
+ if (mode == SFmode)
+ return 1;
+ else if (mode == SImode)
+ {
+ /* Large unsigned constants are represented as const_double's. */
+ unsigned HOST_WIDE_INT low, high;
+
+ low = CONST_DOUBLE_LOW (op);
+ high = CONST_DOUBLE_HIGH (op);
+ return high == 0 && low <= (unsigned) 0xffffffff;
+ }
+ else
+ return 0;
+ case REG :
+ return register_operand (op, mode);
+ case SUBREG :
+ /* (subreg (mem ...) ...) can occur here if the inner part was once a
+ pseudo-reg and is now a stack slot. */
+ if (GET_CODE (SUBREG_REG (op)) == MEM)
+ return address_operand (XEXP (SUBREG_REG (op), 0), mode);
+ else
+ return register_operand (op, mode);
+ case MEM :
+ if (GET_CODE (XEXP (op, 0)) == PRE_INC
+ || GET_CODE (XEXP (op, 0)) == PRE_DEC)
+ return 0; /* loads can't do pre-{inc,dec} */
+ return address_operand (XEXP (op, 0), mode);
+ default :
+ return 0;
+ }
+})
+
+;; Return true if OP is an acceptable argument for a double word move
+;; source.
+
+(define_predicate "move_double_src_operand"
+ (match_code "reg,subreg,mem,const_int,const_double")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST_INT :
+ case CONST_DOUBLE :
+ return 1;
+ case REG :
+ return register_operand (op, mode);
+ case SUBREG :
+ /* (subreg (mem ...) ...) can occur here if the inner part was once a
+ pseudo-reg and is now a stack slot. */
+ if (GET_CODE (SUBREG_REG (op)) == MEM)
+ return move_double_src_operand (SUBREG_REG (op), mode);
+ else
+ return register_operand (op, mode);
+ case MEM :
+ /* Disallow auto inc/dec for now. */
+ if (GET_CODE (XEXP (op, 0)) == PRE_DEC
+ || GET_CODE (XEXP (op, 0)) == PRE_INC)
+ return 0;
+ return address_operand (XEXP (op, 0), mode);
+ default :
+ return 0;
+ }
+})
+
+;; Return true if OP is a const_int requiring two instructions to
+;; load.
+
+(define_predicate "two_insn_const_operand"
+ (match_code "const_int")
+{
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+ if (INT16_P (INTVAL (op))
+ || UINT24_P (INTVAL (op))
+ || UPPER16_P (INTVAL (op)))
+ return 0;
+ return 1;
+})
+
+;; Returns 1 if OP is a symbol reference.
+
+(define_predicate "symbolic_operand"
+ (match_code "symbol_ref,label_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CONST :
+ return 1;
+
+ default:
+ return 0;
+ }
+})
+
+;; Return true if OP is a signed 8 bit immediate value.
+
+(define_predicate "int8_operand"
+ (match_code "const_int")
+{
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+ return INT8_P (INTVAL (op));
+})
+
+;; Return true if OP is an unsigned 16 bit immediate value.
+
+(define_predicate "uint16_operand"
+ (match_code "const_int")
+{
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+ return UINT16_P (INTVAL (op));
+})
+
+;; Return true if OP is a register or signed 16 bit value.
+
+(define_predicate "reg_or_int16_operand"
+ (match_code "reg,subreg,const_int")
+{
+ if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+ return register_operand (op, mode);
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+ return INT16_P (INTVAL (op));
+})
+
+;; Return true if OP is a register or an unsigned 16 bit value.
+
+(define_predicate "reg_or_uint16_operand"
+ (match_code "reg,subreg,const_int")
+{
+ if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+ return register_operand (op, mode);
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+ return UINT16_P (INTVAL (op));
+})
+
+;; Return true if OP is a register or signed 16 bit value for
+;; compares.
+
+(define_predicate "reg_or_cmp_int16_operand"
+ (match_code "reg,subreg,const_int")
+{
+ if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+ return register_operand (op, mode);
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+ return CMP_INT16_P (INTVAL (op));
+})
+
+;; Return true if OP is a register or an integer value that can be
+;; used is SEQ/SNE. We can use either XOR of the value or ADD of the
+;; negative of the value for the constant. Don't allow 0, because
+;; that is special cased.
+
+(define_predicate "reg_or_eq_int16_operand"
+ (match_code "reg,subreg,const_int")
+{
+ HOST_WIDE_INT value;
+
+ if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+ return register_operand (op, mode);
+
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+
+ value = INTVAL (op);
+ return (value != 0) && (UINT16_P (value) || CMP_INT16_P (-value));
+})
+
+;; Return true if OP is a signed 16 bit immediate value useful in
+;; comparisons.
+
+(define_predicate "cmp_int16_operand"
+ (match_code "const_int")
+{
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+ return CMP_INT16_P (INTVAL (op));
+})
+
+;; Acceptable arguments to the call insn.
+
+(define_predicate "call_address_operand"
+ (match_code "symbol_ref,label_ref,const")
+{
+ return symbolic_operand (op, mode);
+
+/* Constants and values in registers are not OK, because
+ the m32r BL instruction can only support PC relative branching. */
+})
+
+;; Return true if OP is an acceptable input argument for a zero/sign
+;; extend operation.
+
+(define_predicate "extend_operand"
+ (match_code "reg,subreg,mem")
+{
+ rtx addr;
+
+ switch (GET_CODE (op))
+ {
+ case REG :
+ case SUBREG :
+ return register_operand (op, mode);
+
+ case MEM :
+ addr = XEXP (op, 0);
+ if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
+ return 0; /* loads can't do pre inc/pre dec */
+
+ return address_operand (addr, mode);
+
+ default :
+ return 0;
+ }
+})
+
+;; Return nonzero if the operand is an insn that is a small
+;; insn. Allow const_int 0 as well, which is a placeholder for NOP
+;; slots.
+
+(define_predicate "small_insn_p"
+ (match_code "insn,call_insn,jump_insn")
+{
+ if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
+ return 1;
+
+ if (! INSN_P (op))
+ return 0;
+
+ return get_attr_length (op) == 2;
+})
+
+;; Return true if op is an integer constant, less than or equal to
+;; MAX_MOVE_BYTES.
+
+(define_predicate "m32r_block_immediate_operand"
+ (match_code "const_int")
+{
+ if (GET_CODE (op) != CONST_INT
+ || INTVAL (op) > MAX_MOVE_BYTES
+ || INTVAL (op) <= 0)
+ return 0;
+
+ return 1;
+})
+
+;; Return nonzero if the operand is an insn that is a large insn.
+
+(define_predicate "large_insn_p"
+ (match_code "insn,call_insn,jump_insn")
+{
+ if (! INSN_P (op))
+ return 0;
+
+ return get_attr_length (op) != 2;
+})
+
+;; Returns 1 if OP is an acceptable operand for seth/add3.
+
+(define_predicate "seth_add3_operand"
+ (match_code "symbol_ref,label_ref,const")
+{
+ if (flag_pic)
+ return 0;
+
+ if (GET_CODE (op) == SYMBOL_REF
+ || GET_CODE (op) == LABEL_REF)
+ return 1;
+
+ if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
+ && INT16_P (INTVAL (XEXP (XEXP (op, 0), 1))))
+ return 1;
+
+ return 0;
+})