This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] m32r: Move predicates to predicates.md.


Hi,

Attached is a patch to move predicates to predicates.md.

Built cc1 for m32r-elf.  OK to apply?

p.s.
If you could test this patch on a simulator, that would be greatly
appreciated.

Kazu Hirata

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.

Index: m32r-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m32r/m32r-protos.h,v
retrieving revision 1.27
diff -u -d -p -r1.27 m32r-protos.h
--- m32r-protos.h	30 Dec 2004 03:07:50 -0000	1.27
+++ m32r-protos.h	18 Mar 2005 00:57:07 -0000
@@ -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 */
 
Index: m32r.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m32r/m32r.c,v
retrieving revision 1.110
diff -u -d -p -r1.110 m32r.c
--- m32r.c	30 Dec 2004 03:07:50 -0000	1.110
+++ m32r.c	18 Mar 2005 00:57:07 -0000
@@ -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 
   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_mod
   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_mod
   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_r
 		     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 ATTRIBU
     }
 }
 
-/* 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
Index: m32r.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m32r/m32r.h,v
retrieving revision 1.125
diff -u -d -p -r1.125 m32r.h
--- m32r.h	30 Dec 2004 03:07:50 -0000	1.125
+++ m32r.h	18 Mar 2005 00:57:08 -0000
@@ -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
Index: m32r.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m32r/m32r.md,v
retrieving revision 1.52
diff -u -d -p -r1.52 m32r.md
--- m32r.md	12 Mar 2005 00:34:06 -0000	1.52
+++ m32r.md	18 Mar 2005 00:57:08 -0000
@@ -198,6 +198,7 @@
        (eq_attr "type" "load4,load8"))
   "long_IF,long_E,memory*2")
 
+(include "predicates.md")
 
 ;; Expand prologue as RTL
 (define_expand "prologue"
--- /dev/null	2005-03-04 04:24:27.812945112 -0500
+++ predicates.md	2005-03-17 19:56:29.204911624 -0500
@@ -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;
+})


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]