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

Kazu Hirata kazu@cs.umass.edu
Thu Mar 17 23:01:00 GMT 2005


Hi,

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

Built cc1 for s390-linux.  OK to apply?

p.s.
If you could bootstrap this patch on a target hardware, that would be
greatly appreciated.

Kazu Hirata

2005-03-17  Kazu Hirata  <kazu@cs.umass.edu>

	* config/s390/s390-protos.h: Add prototypes to
	s390_decompose_address, check_mode, and
	s390_branch_condition_mask.
	* config/s390/s390.c (SYMBOL_FLAG_ALIGN1): Move to s390.h.
	(DISP_IN_RANGE): Move to s390.h.
	(s390_comparison, s390_alc_comparison, s390_slb_comparison,
	const0_operand, consttable_operand, larl_operand, s_operandw,
	shift_count_operand, bras_sym_operand,
	load_multiple_operation, store_multiple_operation,
	s390_plus_operand): Move to predicates.md.
	(s390_branch_condition_mask, s390_decompose_address): Make
	them extern.
	* config/s390/s390.h (PREDICATE_CODES): Remove.
	* config/s390/s390.md: Include predicates.md.
	(predicates.md): New.

Index: s390-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390-protos.h,v
retrieving revision 1.66
diff -u -d -p -r1.66 s390-protos.h
--- s390-protos.h	9 Nov 2004 20:46:12 -0000	1.66
+++ s390-protos.h	17 Mar 2005 22:46:25 -0000
@@ -104,6 +104,27 @@ extern int s390_agen_dep_p (rtx, rtx);
 extern rtx s390_load_got (void);
 extern void s390_emit_tpf_eh_return (rtx);
 
+/* Structure used to hold the components of a S/390 memory
+   address.  A legitimate address on S/390 is of the general
+   form
+          base + index + displacement
+   where any of the components is optional.
+
+   base and index are registers of the class ADDR_REGS,
+   displacement is an unsigned 12-bit immediate constant.  */
+
+struct s390_address
+{
+  rtx base;
+  rtx indx;
+  rtx disp;
+  int pointer;
+};
+
+extern int s390_decompose_address (rtx, struct s390_address *);
+extern int check_mode (rtx, enum machine_mode *);
+extern int s390_branch_condition_mask (rtx);
+
 #endif /* RTX_CODE */
 
 #ifdef TREE_CODE
Index: s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.219
diff -u -d -p -r1.219 s390.c
--- s390.c	15 Mar 2005 15:46:52 -0000	1.219
+++ s390.c	17 Mar 2005 22:46:26 -0000
@@ -52,10 +52,6 @@ Software Foundation, 59 Temple Place - S
 #include "optabs.h"
 #include "tree-gimple.h"
 
-/* Machine-specific symbol_ref flags.  */
-#define SYMBOL_FLAG_ALIGN1	(SYMBOL_FLAG_MACH_DEP << 0)
-
-
 static bool s390_assemble_integer (rtx, unsigned int, int);
 static void s390_encode_section_info (tree, rtx, int);
 static bool s390_cannot_force_const_mem (rtx);
@@ -278,23 +274,6 @@ static int s390_sr_alias_set = 0;
    emitted.  */
 rtx s390_compare_op0, s390_compare_op1;
 
-/* Structure used to hold the components of a S/390 memory
-   address.  A legitimate address on S/390 is of the general
-   form
-          base + index + displacement
-   where any of the components is optional.
-
-   base and index are registers of the class ADDR_REGS,
-   displacement is an unsigned 12-bit immediate constant.  */
-
-struct s390_address
-{
-  rtx base;
-  rtx indx;
-  rtx disp;
-  int pointer;
-};
-
 /* Which cpu are we tuning for.  */
 enum processor_type s390_tune;
 enum processor_flags s390_tune_flags;
@@ -380,11 +359,8 @@ struct machine_function GTY(())
   (1 << (BITNUM))))
 
 static int s390_match_ccmode_set (rtx, enum machine_mode);
-static int s390_branch_condition_mask (rtx);
 static const char *s390_branch_condition_mnemonic (rtx, int);
-static int check_mode (rtx, enum machine_mode *);
 static int s390_short_displacement (rtx);
-static int s390_decompose_address (rtx, struct s390_address *);
 static rtx get_thread_pointer (void);
 static rtx legitimize_tls_address (rtx, rtx);
 static void print_shift_count_operand (FILE *, rtx);
@@ -413,11 +389,6 @@ static int s390_function_arg_size (enum 
 static bool s390_function_arg_float (enum machine_mode, tree);
 static struct machine_function * s390_init_machine_status (void);
 
-/* Check whether integer displacement is in range.  */
-#define DISP_IN_RANGE(d) \
-  (TARGET_LONG_DISPLACEMENT? ((d) >= -524288 && (d) <= 524287) \
-                           : ((d) >= 0 && (d) <= 4095))
-
 /* Return true if SET either doesn't set the CC register, or else
    the source and destination have matching CC modes and that
    CC mode is at least as constrained as REQ_MODE.  */
@@ -791,126 +762,10 @@ s390_emit_jump (rtx target, rtx cond)
   emit_jump_insn (insn);
 }
 
-/* Return nonzero if OP is a valid comparison operator
-   for a branch condition in mode MODE.  */
-
-int
-s390_comparison (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  if (!COMPARISON_P (op))
-    return 0;
-
-  if (GET_CODE (XEXP (op, 0)) != REG
-      || REGNO (XEXP (op, 0)) != CC_REGNUM
-      || XEXP (op, 1) != const0_rtx)
-    return 0;
-
-  return s390_branch_condition_mask (op) >= 0;
-}
-
-/* Return nonzero if OP is a valid comparison operator
-   for an ALC condition in mode MODE.  */
-
-int
-s390_alc_comparison (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
-    op = XEXP (op, 0);
-
-  if (!COMPARISON_P (op))
-    return 0;
-
-  if (GET_CODE (XEXP (op, 0)) != REG
-      || REGNO (XEXP (op, 0)) != CC_REGNUM
-      || XEXP (op, 1) != const0_rtx)
-    return 0;
-
-  switch (GET_MODE (XEXP (op, 0)))
-    {
-    case CCL1mode:
-      return GET_CODE (op) == LTU;
-
-    case CCL2mode:
-      return GET_CODE (op) == LEU;
-
-    case CCL3mode:
-      return GET_CODE (op) == GEU;
-
-    case CCUmode:
-      return GET_CODE (op) == GTU;
-
-    case CCURmode:
-      return GET_CODE (op) == LTU;
-
-    case CCSmode:
-      return GET_CODE (op) == UNGT;
-
-    case CCSRmode:
-      return GET_CODE (op) == UNLT;
-
-    default:
-      return 0;
-    }
-}
-
-/* Return nonzero if OP is a valid comparison operator
-   for an SLB condition in mode MODE.  */
-
-int
-s390_slb_comparison (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
-    op = XEXP (op, 0);
-
-  if (!COMPARISON_P (op))
-    return 0;
-
-  if (GET_CODE (XEXP (op, 0)) != REG
-      || REGNO (XEXP (op, 0)) != CC_REGNUM
-      || XEXP (op, 1) != const0_rtx)
-    return 0;
-
-  switch (GET_MODE (XEXP (op, 0)))
-    {
-    case CCL1mode:
-      return GET_CODE (op) == GEU;
-
-    case CCL2mode:
-      return GET_CODE (op) == GTU;
-
-    case CCL3mode:
-      return GET_CODE (op) == LTU;
-
-    case CCUmode:
-      return GET_CODE (op) == LEU;
-
-    case CCURmode:
-      return GET_CODE (op) == GEU;
-
-    case CCSmode:
-      return GET_CODE (op) == LE;
-
-    case CCSRmode:
-      return GET_CODE (op) == GE;
-
-    default:
-      return 0;
-    }
-}
-
 /* Return branch condition mask to implement a branch
    specified by CODE.  Return -1 for invalid comparisons.  */
 
-static int
+int
 s390_branch_condition_mask (rtx code)
 {
   const int CC0 = 1 << 3;
@@ -1508,30 +1363,10 @@ s390_safe_attr_type (rtx insn)
     return TYPE_NONE;
 }
 
-/* Return true if OP a (const_int 0) operand.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-const0_operand (register rtx op, enum machine_mode mode)
-{
-  return op == CONST0_RTX (mode);
-}
-
-/* Return true if OP is constant.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-consttable_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return CONSTANT_P (op);
-}
-
 /* Return true if the mode of operand OP matches MODE.
    If MODE is set to VOIDmode, set it to the mode of OP.  */
 
-static int
+int
 check_mode (register rtx op, enum machine_mode *mode)
 {
   if (*mode == VOIDmode)
@@ -1544,136 +1379,6 @@ check_mode (register rtx op, enum machin
   return 1;
 }
 
-/* Return true if OP a valid operand for the LARL instruction.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-larl_operand (register rtx op, enum machine_mode mode)
-{
-  if (! check_mode (op, &mode))
-    return 0;
-
-  /* Allow labels and local symbols.  */
-  if (GET_CODE (op) == LABEL_REF)
-    return 1;
-  if (GET_CODE (op) == SYMBOL_REF)
-    return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
-	    && SYMBOL_REF_TLS_MODEL (op) == 0
-	    && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
-
-  /* Everything else must have a CONST, so strip it.  */
-  if (GET_CODE (op) != CONST)
-    return 0;
-  op = XEXP (op, 0);
-
-  /* Allow adding *even* in-range constants.  */
-  if (GET_CODE (op) == PLUS)
-    {
-      if (GET_CODE (XEXP (op, 1)) != CONST_INT
-          || (INTVAL (XEXP (op, 1)) & 1) != 0)
-        return 0;
-#if HOST_BITS_PER_WIDE_INT > 32
-      if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 32
-	  || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 32))
-        return 0;
-#endif
-      op = XEXP (op, 0);
-    }
-
-  /* Labels and local symbols allowed here as well.  */
-  if (GET_CODE (op) == LABEL_REF)
-    return 1;
-  if (GET_CODE (op) == SYMBOL_REF)
-    return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
-	    && SYMBOL_REF_TLS_MODEL (op) == 0
-	    && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
-
-  /* Now we must have a @GOTENT offset or @PLT stub
-     or an @INDNTPOFF TLS offset.  */
-  if (GET_CODE (op) == UNSPEC
-      && XINT (op, 1) == UNSPEC_GOTENT)
-    return 1;
-  if (GET_CODE (op) == UNSPEC
-      && XINT (op, 1) == UNSPEC_PLT)
-    return 1;
-  if (GET_CODE (op) == UNSPEC
-      && XINT (op, 1) == UNSPEC_INDNTPOFF)
-    return 1;
-
-  return 0;
-}
-
-/* Return true if OP is a valid S-type operand.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-s_operandw (rtx op, enum machine_mode mode)
-{
-  struct s390_address addr;
-
-  /* Call general_operand first, so that we don't have to
-     check for many special cases.  */
-  if (!general_operand (op, mode))
-    return 0;
-
-  /* Just like memory_operand, allow (subreg (mem ...))
-     after reload.  */
-  if (reload_completed
-      && GET_CODE (op) == SUBREG
-      && GET_CODE (SUBREG_REG (op)) == MEM)
-    op = SUBREG_REG (op);
-
-  if (GET_CODE (op) != MEM)
-    return 0;
-  if (!s390_decompose_address (XEXP (op, 0), &addr))
-    return 0;
-  if (addr.indx)
-    return 0;
-
-  return 1;
-}
-
-/* Return true if OP a valid shift count operand.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-shift_count_operand (rtx op, enum machine_mode mode)
-{
-  HOST_WIDE_INT offset = 0;
-
-  if (! check_mode (op, &mode))
-    return 0;
-
-  /* We can have an integer constant, an address register,
-     or a sum of the two.  Note that reload already checks
-     that any register present is an address register, so
-     we just check for any register here.  */
-  if (GET_CODE (op) == CONST_INT)
-    {
-      offset = INTVAL (op);
-      op = NULL_RTX;
-    }
-  if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
-    {
-      offset = INTVAL (XEXP (op, 1));
-      op = XEXP (op, 0);
-    }
-  while (op && GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  if (op && GET_CODE (op) != REG)
-    return 0;
-
-  /* Unfortunately we have to reject constants that are invalid
-     for an address, or else reload will get confused.  */
-  if (!DISP_IN_RANGE (offset))
-    return 0;
-
-  return 1;
-}
-
 /* Return true if DISP is a valid short displacement.  */
 
 static int
@@ -2112,27 +1817,6 @@ s390_address_cost (rtx addr)
   return ad.indx? COSTS_N_INSNS (1) + 1 : COSTS_N_INSNS (1);
 }
 
-/* Return true if OP is a valid operand for the BRAS instruction.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-bras_sym_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  register enum rtx_code code = GET_CODE (op);
-
-  /* Allow SYMBOL_REFs.  */
-  if (code == SYMBOL_REF)
-    return 1;
-
-  /* Allow @PLT stubs.  */
-  if (code == CONST
-      && GET_CODE (XEXP (op, 0)) == UNSPEC
-      && XINT (XEXP (op, 0), 1) == UNSPEC_PLT)
-    return 1;
-  return 0;
-}
-
 /* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode,
    otherwise return 0.  */
 
@@ -2144,126 +1828,6 @@ tls_symbolic_operand (register rtx op)
   return SYMBOL_REF_TLS_MODEL (op);
 }
 
-/* Return true if OP is a load multiple operation.  It is known to be a
-   PARALLEL and the first section will be tested.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-load_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  enum machine_mode elt_mode;
-  int count = XVECLEN (op, 0);
-  unsigned int dest_regno;
-  rtx src_addr;
-  int i, off;
-
-
-  /* Perform a quick check so we don't blow up below.  */
-  if (count <= 1
-      || GET_CODE (XVECEXP (op, 0, 0)) != SET
-      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
-      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
-    return 0;
-
-  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
-  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
-  elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0)));
-
-  /* Check, is base, or base + displacement.  */
-
-  if (GET_CODE (src_addr) == REG)
-    off = 0;
-  else if (GET_CODE (src_addr) == PLUS
-	   && GET_CODE (XEXP (src_addr, 0)) == REG
-	   && GET_CODE (XEXP (src_addr, 1)) == CONST_INT)
-    {
-      off = INTVAL (XEXP (src_addr, 1));
-      src_addr = XEXP (src_addr, 0);
-    }
-  else
-    return 0;
-
-  for (i = 1; i < count; i++)
-    {
-      rtx elt = XVECEXP (op, 0, i);
-
-      if (GET_CODE (elt) != SET
-	  || GET_CODE (SET_DEST (elt)) != REG
-	  || GET_MODE (SET_DEST (elt)) != elt_mode
-	  || REGNO (SET_DEST (elt)) != dest_regno + i
-	  || GET_CODE (SET_SRC (elt)) != MEM
-	  || GET_MODE (SET_SRC (elt)) != elt_mode
-	  || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
-	  || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
-	  || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
-	  || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1))
-	     != off + i * GET_MODE_SIZE (elt_mode))
-	return 0;
-    }
-
-  return 1;
-}
-
-/* Return true if OP is a store multiple operation.  It is known to be a
-   PARALLEL and the first section will be tested.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  enum machine_mode elt_mode;
-  int count = XVECLEN (op, 0);
-  unsigned int src_regno;
-  rtx dest_addr;
-  int i, off;
-
-  /* Perform a quick check so we don't blow up below.  */
-  if (count <= 1
-      || GET_CODE (XVECEXP (op, 0, 0)) != SET
-      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
-      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
-    return 0;
-
-  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
-  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
-  elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0)));
-
-  /* Check, is base, or base + displacement.  */
-
-  if (GET_CODE (dest_addr) == REG)
-    off = 0;
-  else if (GET_CODE (dest_addr) == PLUS
-	   && GET_CODE (XEXP (dest_addr, 0)) == REG
-	   && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT)
-    {
-      off = INTVAL (XEXP (dest_addr, 1));
-      dest_addr = XEXP (dest_addr, 0);
-    }
-  else
-    return 0;
-
-  for (i = 1; i < count; i++)
-    {
-      rtx elt = XVECEXP (op, 0, i);
-
-      if (GET_CODE (elt) != SET
-	  || GET_CODE (SET_SRC (elt)) != REG
-	  || GET_MODE (SET_SRC (elt)) != elt_mode
-	  || REGNO (SET_SRC (elt)) != src_regno + i
-	  || GET_CODE (SET_DEST (elt)) != MEM
-	  || GET_MODE (SET_DEST (elt)) != elt_mode
-	  || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
-	  || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
-	  || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
-	  || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1))
-	     != off + i * GET_MODE_SIZE (elt_mode))
-	return 0;
-    }
-  return 1;
-}
-
 /* Split DImode access register reference REG (on 64-bit) into its constituent
    low and high parts, and store them into LO and HI.  Note that gen_lowpart/
    gen_highpart cannot be used as they assume all registers are word-sized,
@@ -2570,26 +2134,6 @@ s390_secondary_output_reload_class (enum
   return NO_REGS;
 }
 
-/* Return true if OP is a PLUS that is not a legitimate
-   operand for the LA instruction.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-s390_plus_operand (register rtx op, enum machine_mode mode)
-{
-  if (!check_mode (op, &mode) || mode != Pmode)
-    return FALSE;
-
-  if (GET_CODE (op) != PLUS)
-    return FALSE;
-
-  if (legitimate_la_operand_p (op))
-    return FALSE;
-
-  return TRUE;
-}
-
 /* Generate code to load SRC, which is PLUS that is not a
    legitimate operand for the LA instruction, into TARGET.
    SCRATCH may be used as scratch register.  */
@@ -2661,7 +2205,7 @@ s390_expand_plus_operand (register rtx t
    LEGITIMIZE_ADDRESS should convert non-canonical forms to the
    canonical form so that they will be recognized.  */
 
-static int
+int
 s390_decompose_address (register rtx addr, struct s390_address *out)
 {
   HOST_WIDE_INT offset = 0;
Index: s390.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.h,v
retrieving revision 1.134
diff -u -d -p -r1.134 s390.h
--- s390.h	17 Feb 2005 21:09:23 -0000	1.134
+++ s390.h	17 Mar 2005 22:46:26 -0000
@@ -1043,26 +1043,6 @@ do {									\
 
 /* Miscellaneous parameters.  */
 
-/* Define the codes that are matched by predicates in aux-output.c.  */
-#define PREDICATE_CODES							\
-  {"s_operand",       { SUBREG, MEM }},					\
-  {"shift_count_operand", { REG, SUBREG, PLUS, CONST_INT }},		\
-  {"bras_sym_operand",{ SYMBOL_REF, CONST }},				\
-  {"larl_operand",    { SYMBOL_REF, CONST, CONST_INT, CONST_DOUBLE }},	\
-  {"load_multiple_operation", {PARALLEL}},			        \
-  {"store_multiple_operation", {PARALLEL}},			        \
-  {"const0_operand",  { CONST_INT, CONST_DOUBLE }},			\
-  {"consttable_operand", { SYMBOL_REF, LABEL_REF, CONST, 		\
-			   CONST_INT, CONST_DOUBLE }},			\
-  {"s390_plus_operand", { PLUS }},					\
-  {"s390_comparison",     { EQ, NE, LT, GT, LE, GE, LTU, GTU, LEU, GEU,	\
-			    UNEQ, UNLT, UNGT, UNLE, UNGE, LTGT,		\
-			    UNORDERED, ORDERED }},			\
-  {"s390_alc_comparison", { ZERO_EXTEND, SIGN_EXTEND, 			\
-			    LTU, GTU, LEU, GEU }},			\
-  {"s390_slb_comparison", { ZERO_EXTEND, SIGN_EXTEND,			\
-			    LTU, GTU, LEU, GEU }},
-
 /* Specify the machine mode that this machine uses for the index in the
    tablejump instruction.  */
 #define CASE_VECTOR_MODE (TARGET_64BIT ? DImode : SImode)
@@ -1083,4 +1063,12 @@ do {									\
    indexing purposes) so give the MEM rtx a byte's mode.  */
 #define FUNCTION_MODE QImode
 
+/* Machine-specific symbol_ref flags.  */
+#define SYMBOL_FLAG_ALIGN1	(SYMBOL_FLAG_MACH_DEP << 0)
+
+/* Check whether integer displacement is in range.  */
+#define DISP_IN_RANGE(d) \
+  (TARGET_LONG_DISPLACEMENT? ((d) >= -524288 && (d) <= 524287) \
+                           : ((d) >= 0 && (d) <= 4095))
+
 #endif
Index: s390.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.md,v
retrieving revision 1.155
diff -u -d -p -r1.155 s390.md
--- s390.md	9 Mar 2005 22:05:14 -0000	1.155
+++ s390.md	17 Mar 2005 22:46:26 -0000
@@ -228,6 +228,8 @@
 ;; Pipeline description for z990. 
 (include "2084.md")
 
+(include "predicates.md")
+
 ;;
 ;;- Compare instructions.
 ;;
--- /dev/null	2005-03-04 04:24:27.812945112 -0500
+++ predicates.md	2005-03-17 17:01:33.000000000 -0500
@@ -0,0 +1,437 @@
+;; Predicate definitions for S/390 / zSeries.
+;; 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 S-type operand. OP is the current
+;; operation. MODE is the current operation mode.
+
+(define_predicate "s_operand"
+  (match_code "subreg,mem")
+{
+  struct s390_address addr;
+
+  /* Call general_operand first, so that we don't have to
+     check for many special cases.  */
+  if (!general_operand (op, mode))
+    return 0;
+
+  /* Just like memory_operand, allow (subreg (mem ...))
+     after reload.  */
+  if (reload_completed
+      && GET_CODE (op) == SUBREG
+      && GET_CODE (SUBREG_REG (op)) == MEM)
+    op = SUBREG_REG (op);
+
+  if (GET_CODE (op) != MEM)
+    return 0;
+  if (!s390_decompose_address (XEXP (op, 0), &addr))
+    return 0;
+  if (addr.indx)
+    return 0;
+
+  return 1;
+})
+
+;; Return true if OP a valid shift count operand. OP is the current
+;; operation. MODE is the current operation mode.
+
+(define_predicate "shift_count_operand"
+  (match_code "reg,subreg,plus,const_int")
+{
+  HOST_WIDE_INT offset = 0;
+
+  if (! check_mode (op, &mode))
+    return 0;
+
+  /* We can have an integer constant, an address register,
+     or a sum of the two.  Note that reload already checks
+     that any register present is an address register, so
+     we just check for any register here.  */
+  if (GET_CODE (op) == CONST_INT)
+    {
+      offset = INTVAL (op);
+      op = NULL_RTX;
+    }
+  if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
+    {
+      offset = INTVAL (XEXP (op, 1));
+      op = XEXP (op, 0);
+    }
+  while (op && GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+  if (op && GET_CODE (op) != REG)
+    return 0;
+
+  /* Unfortunately we have to reject constants that are invalid
+     for an address, or else reload will get confused.  */
+  if (!DISP_IN_RANGE (offset))
+    return 0;
+
+  return 1;
+})
+
+;; Return true if OP is a valid operand for the BRAS instruction. OP
+;; is the current operation. MODE is the current operation mode.
+
+(define_predicate "bras_sym_operand"
+  (match_code "symbol_ref,const")
+{
+  register enum rtx_code code = GET_CODE (op);
+
+  /* Allow SYMBOL_REFs.  */
+  if (code == SYMBOL_REF)
+    return 1;
+
+  /* Allow @PLT stubs.  */
+  if (code == CONST
+      && GET_CODE (XEXP (op, 0)) == UNSPEC
+      && XINT (XEXP (op, 0), 1) == UNSPEC_PLT)
+    return 1;
+  return 0;
+})
+
+;; Return true if OP a valid operand for the LARL instruction. OP is
+;; the current operation. MODE is the current operation mode.
+
+(define_predicate "larl_operand"
+  (match_code "symbol_ref,const,const_int,const_double")
+{
+  if (! check_mode (op, &mode))
+    return 0;
+
+  /* Allow labels and local symbols.  */
+  if (GET_CODE (op) == LABEL_REF)
+    return 1;
+  if (GET_CODE (op) == SYMBOL_REF)
+    return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
+	    && SYMBOL_REF_TLS_MODEL (op) == 0
+	    && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
+
+  /* Everything else must have a CONST, so strip it.  */
+  if (GET_CODE (op) != CONST)
+    return 0;
+  op = XEXP (op, 0);
+
+  /* Allow adding *even* in-range constants.  */
+  if (GET_CODE (op) == PLUS)
+    {
+      if (GET_CODE (XEXP (op, 1)) != CONST_INT
+          || (INTVAL (XEXP (op, 1)) & 1) != 0)
+        return 0;
+#if HOST_BITS_PER_WIDE_INT > 32
+      if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 32
+	  || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 32))
+        return 0;
+#endif
+      op = XEXP (op, 0);
+    }
+
+  /* Labels and local symbols allowed here as well.  */
+  if (GET_CODE (op) == LABEL_REF)
+    return 1;
+  if (GET_CODE (op) == SYMBOL_REF)
+    return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
+	    && SYMBOL_REF_TLS_MODEL (op) == 0
+	    && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
+
+  /* Now we must have a @GOTENT offset or @PLT stub
+     or an @INDNTPOFF TLS offset.  */
+  if (GET_CODE (op) == UNSPEC
+      && XINT (op, 1) == UNSPEC_GOTENT)
+    return 1;
+  if (GET_CODE (op) == UNSPEC
+      && XINT (op, 1) == UNSPEC_PLT)
+    return 1;
+  if (GET_CODE (op) == UNSPEC
+      && XINT (op, 1) == UNSPEC_INDNTPOFF)
+    return 1;
+
+  return 0;
+})
+
+;; Return true if OP is a load multiple operation.  It is known to be
+;; a PARALLEL and the first section will be tested. OP is the current
+;; operation. MODE is the current operation mode.
+
+(define_predicate "load_multiple_operation"
+  (match_code "parallel")
+{
+  enum machine_mode elt_mode;
+  int count = XVECLEN (op, 0);
+  unsigned int dest_regno;
+  rtx src_addr;
+  int i, off;
+
+
+  /* Perform a quick check so we don't blow up below.  */
+  if (count <= 1
+      || GET_CODE (XVECEXP (op, 0, 0)) != SET
+      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
+      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
+    return 0;
+
+  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
+  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
+  elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0)));
+
+  /* Check, is base, or base + displacement.  */
+
+  if (GET_CODE (src_addr) == REG)
+    off = 0;
+  else if (GET_CODE (src_addr) == PLUS
+	   && GET_CODE (XEXP (src_addr, 0)) == REG
+	   && GET_CODE (XEXP (src_addr, 1)) == CONST_INT)
+    {
+      off = INTVAL (XEXP (src_addr, 1));
+      src_addr = XEXP (src_addr, 0);
+    }
+  else
+    return 0;
+
+  for (i = 1; i < count; i++)
+    {
+      rtx elt = XVECEXP (op, 0, i);
+
+      if (GET_CODE (elt) != SET
+	  || GET_CODE (SET_DEST (elt)) != REG
+	  || GET_MODE (SET_DEST (elt)) != elt_mode
+	  || REGNO (SET_DEST (elt)) != dest_regno + i
+	  || GET_CODE (SET_SRC (elt)) != MEM
+	  || GET_MODE (SET_SRC (elt)) != elt_mode
+	  || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
+	  || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
+	  || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
+	  || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1))
+	     != off + i * GET_MODE_SIZE (elt_mode))
+	return 0;
+    }
+
+  return 1;
+})
+
+;; Return true if OP is a store multiple operation.  It is known to be
+;; a PARALLEL and the first section will be tested. OP is the current
+;; operation. MODE is the current operation mode.
+
+(define_predicate "store_multiple_operation"
+  (match_code "parallel")
+{
+  enum machine_mode elt_mode;
+  int count = XVECLEN (op, 0);
+  unsigned int src_regno;
+  rtx dest_addr;
+  int i, off;
+
+  /* Perform a quick check so we don't blow up below.  */
+  if (count <= 1
+      || GET_CODE (XVECEXP (op, 0, 0)) != SET
+      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
+      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
+    return 0;
+
+  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
+  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
+  elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0)));
+
+  /* Check, is base, or base + displacement.  */
+
+  if (GET_CODE (dest_addr) == REG)
+    off = 0;
+  else if (GET_CODE (dest_addr) == PLUS
+	   && GET_CODE (XEXP (dest_addr, 0)) == REG
+	   && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT)
+    {
+      off = INTVAL (XEXP (dest_addr, 1));
+      dest_addr = XEXP (dest_addr, 0);
+    }
+  else
+    return 0;
+
+  for (i = 1; i < count; i++)
+    {
+      rtx elt = XVECEXP (op, 0, i);
+
+      if (GET_CODE (elt) != SET
+	  || GET_CODE (SET_SRC (elt)) != REG
+	  || GET_MODE (SET_SRC (elt)) != elt_mode
+	  || REGNO (SET_SRC (elt)) != src_regno + i
+	  || GET_CODE (SET_DEST (elt)) != MEM
+	  || GET_MODE (SET_DEST (elt)) != elt_mode
+	  || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
+	  || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
+	  || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
+	  || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1))
+	     != off + i * GET_MODE_SIZE (elt_mode))
+	return 0;
+    }
+  return 1;
+})
+
+;; Return true if OP a (const_int 0) operand. OP is the current
+;; operation. MODE is the current operation mode.
+
+(define_predicate "const0_operand"
+  (match_code "const_int,const_double")
+{
+  return op == CONST0_RTX (mode);
+})
+
+;; Return true if OP is constant. OP is the current operation. MODE is
+;; the current operation mode.
+
+(define_predicate "consttable_operand"
+  (match_code "symbol_ref,label_ref,const,const_int,const_double")
+{
+  return CONSTANT_P (op);
+})
+
+;; Return true if OP is a PLUS that is not a legitimate operand for
+;; the LA instruction. OP is the current operation. MODE is the
+;; current operation mode.
+
+(define_predicate "s390_plus_operand"
+  (match_code "plus")
+{
+  if (!check_mode (op, &mode) || mode != Pmode)
+    return FALSE;
+
+  if (GET_CODE (op) != PLUS)
+    return FALSE;
+
+  if (legitimate_la_operand_p (op))
+    return FALSE;
+
+  return TRUE;
+})
+
+;; Return nonzero if OP is a valid comparison operator for a branch
+;; condition in mode MODE.
+
+(define_predicate "s390_comparison"
+  (match_code "eq,ne,lt,gt,le,ge,ltu,gtu,leu,geu,uneq,unlt,ungt,unle,unge,ltgt,unordered,ordered")
+{
+  if (mode != VOIDmode && mode != GET_MODE (op))
+    return 0;
+
+  if (!COMPARISON_P (op))
+    return 0;
+
+  if (GET_CODE (XEXP (op, 0)) != REG
+      || REGNO (XEXP (op, 0)) != CC_REGNUM
+      || XEXP (op, 1) != const0_rtx)
+    return 0;
+
+  return s390_branch_condition_mask (op) >= 0;
+})
+
+;; Return nonzero if OP is a valid comparison operator for an ALC
+;; condition in mode MODE.
+
+(define_predicate "s390_alc_comparison"
+  (match_code "zero_extend,sign_extend,ltu,gtu,leu,geu")
+{
+  if (mode != VOIDmode && mode != GET_MODE (op))
+    return 0;
+
+  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
+    op = XEXP (op, 0);
+
+  if (!COMPARISON_P (op))
+    return 0;
+
+  if (GET_CODE (XEXP (op, 0)) != REG
+      || REGNO (XEXP (op, 0)) != CC_REGNUM
+      || XEXP (op, 1) != const0_rtx)
+    return 0;
+
+  switch (GET_MODE (XEXP (op, 0)))
+    {
+    case CCL1mode:
+      return GET_CODE (op) == LTU;
+
+    case CCL2mode:
+      return GET_CODE (op) == LEU;
+
+    case CCL3mode:
+      return GET_CODE (op) == GEU;
+
+    case CCUmode:
+      return GET_CODE (op) == GTU;
+
+    case CCURmode:
+      return GET_CODE (op) == LTU;
+
+    case CCSmode:
+      return GET_CODE (op) == UNGT;
+
+    case CCSRmode:
+      return GET_CODE (op) == UNLT;
+
+    default:
+      return 0;
+    }
+})
+
+;; Return nonzero if OP is a valid comparison operator for an SLB
+;; condition in mode MODE.
+
+(define_predicate "s390_slb_comparison"
+  (match_code "zero_extend,sign_extend,ltu,gtu,leu,geu")
+{
+  if (mode != VOIDmode && mode != GET_MODE (op))
+    return 0;
+
+  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
+    op = XEXP (op, 0);
+
+  if (!COMPARISON_P (op))
+    return 0;
+
+  if (GET_CODE (XEXP (op, 0)) != REG
+      || REGNO (XEXP (op, 0)) != CC_REGNUM
+      || XEXP (op, 1) != const0_rtx)
+    return 0;
+
+  switch (GET_MODE (XEXP (op, 0)))
+    {
+    case CCL1mode:
+      return GET_CODE (op) == GEU;
+
+    case CCL2mode:
+      return GET_CODE (op) == GTU;
+
+    case CCL3mode:
+      return GET_CODE (op) == LTU;
+
+    case CCUmode:
+      return GET_CODE (op) == LEU;
+
+    case CCURmode:
+      return GET_CODE (op) == GEU;
+
+    case CCSmode:
+      return GET_CODE (op) == LE;
+
+    case CCSRmode:
+      return GET_CODE (op) == GE;
+
+    default:
+      return 0;
+    }
+})



More information about the Gcc-patches mailing list