]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
s390-protos.h: (s390_comparison...
authorAdrian Straetling <straetling@de.ibm.com>
Mon, 4 Apr 2005 16:25:05 +0000 (16:25 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Mon, 4 Apr 2005 16:25:05 +0000 (16:25 +0000)
2005-04-04  Adrian Straeļæ½tling  <straetling@de.ibm.com>

* config/s390/s390-protos.h: (s390_comparison,
s390_alc_comparison, s390_slb_comparison, const0_operand,
consttable_operand, larl_operand, s_operand,
shift_count_operand, bras_sym_operand, load_multiple_operation,
store_multiple_operation, s390_plus_operand): Remove prototypes.
(s390_legitimate_address_without_index_p): New prototype.
* config/s390/s390.c: (SYMBOL_FLAG_ALIGN1, DISP_IN_RANGE): Move
to s390.h.
(s390_comparison, s390_alc_comparison, s390_slb_comparison,
const0_operand, consttable_operand, larl_operand, s_operand,
shift_count_operand, bras_sym_operand, load_multiple_operation,
store_multiple_operation, s390_plus_operand): Move to
predicates.md.
(check_mode): Remove.
(s390_branch_condition_mask): Remove 'static'. Move prototype to
s390-protos.h.
(s390_legitimate_address_without_index_p): New.
* config/s390/s390.h (PREDICATE_CODES): Remove.
* config/s390/s390.md: Include predicates.md.
* config/s390/predicates.md: New.

From-SVN: r97554

gcc/ChangeLog
gcc/config/s390/predicates.md [new file with mode: 0644]
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md

index 1dc4e5785a002e3a9748a4e713aae2bf1c6ec77a..40926b4480cf38899ff0d004113792914117cf59 100644 (file)
@@ -1,3 +1,26 @@
+2005-04-04  Adrian StraeĀ¤tling  <straetling@de.ibm.com>
+
+       * config/s390/s390-protos.h: (s390_comparison,
+       s390_alc_comparison, s390_slb_comparison, const0_operand,
+       consttable_operand, larl_operand, s_operand,
+       shift_count_operand, bras_sym_operand, load_multiple_operation,
+       store_multiple_operation, s390_plus_operand): Remove prototypes.
+       (s390_legitimate_address_without_index_p): New prototype.
+       * config/s390/s390.c: (SYMBOL_FLAG_ALIGN1, DISP_IN_RANGE): Move
+       to s390.h.
+       (s390_comparison, s390_alc_comparison, s390_slb_comparison,
+       const0_operand, consttable_operand, larl_operand, s_operand,
+       shift_count_operand, bras_sym_operand, load_multiple_operation,
+       store_multiple_operation, s390_plus_operand): Move to
+       predicates.md.
+       (check_mode): Remove.
+       (s390_branch_condition_mask): Remove 'static'. Move prototype to
+       s390-protos.h.
+       (s390_legitimate_address_without_index_p): New.
+       * config/s390/s390.h (PREDICATE_CODES): Remove.
+       * config/s390/s390.md: Include predicates.md.
+       * config/s390/predicates.md: New.
+
 2005-04-04  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        PR target/20446
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
new file mode 100644 (file)
index 0000000..9af62a8
--- /dev/null
@@ -0,0 +1,386 @@
+;; Predicate definitions for S/390 and zSeries.
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
+;;                Ulrich Weigand (uweigand@de.ibm.com).
+;;
+;; 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.
+
+;; OP is the current operation.
+;; MODE is the current operation mode.
+
+;; operands --------------------------------------------------------------
+
+;; Return true if OP a (const_int 0) operand.
+
+(define_predicate "const0_operand"
+  (and (match_code "const_int, const_double")
+       (match_test "op == CONST0_RTX (mode)")))
+
+;; Return true if OP is constant.
+
+(define_special_predicate "consttable_operand"
+  (and (match_code "symbol_ref, label_ref, const, const_int, const_double")
+       (match_test "CONSTANT_P (op)")))
+
+;; Return true if OP is a valid S-type operand.
+
+(define_predicate "s_operand"
+  (and (match_code "subreg, mem")
+       (match_operand 0 "general_operand"))
+{
+  /* 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 false;
+  if (!s390_legitimate_address_without_index_p (op))
+    return false;
+
+  return true;
+})
+
+;; Return true if OP is a valid operand for the BRAS instruction.
+;; Allow SYMBOL_REFs and @PLT stubs.
+
+(define_special_predicate "bras_sym_operand"
+  (ior (match_code "symbol_ref")
+       (and (match_code "const")
+           (and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC")
+                (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_PLT")))))
+
+;; Return true if OP is a PLUS that is not a legitimate
+;; operand for the LA instruction.
+
+(define_predicate "s390_plus_operand"
+  (and (match_code "plus")
+       (and (match_test "mode == Pmode")
+           (match_test "!legitimate_la_operand_p (op)"))))
+
+;; Return true if OP is a valid shift count operand.
+
+(define_predicate "shift_count_operand"
+  (match_code "reg, subreg, plus, const_int")
+{
+  HOST_WIDE_INT offset = 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 false;
+
+  /* Unfortunately we have to reject constants that are invalid
+     for an address, or else reload will get confused.  */
+  if (!DISP_IN_RANGE (offset))
+    return false;
+
+  return true;
+})
+
+;;  Return true if OP a valid operand for the LARL instruction.
+
+(define_predicate "larl_operand"
+  (match_code "label_ref, symbol_ref, const, const_int, const_double")
+{
+  /* Allow labels and local symbols.  */
+  if (GET_CODE (op) == LABEL_REF)
+    return true;
+  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 false;
+  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 false;
+      if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 32
+         || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 32))
+        return false;
+      op = XEXP (op, 0);
+    }
+
+  /* Labels and local symbols allowed here as well.  */
+  if (GET_CODE (op) == LABEL_REF)
+    return true;
+  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 true;
+  if (GET_CODE (op) == UNSPEC
+      && XINT (op, 1) == UNSPEC_PLT)
+    return true;
+  if (GET_CODE (op) == UNSPEC
+      && XINT (op, 1) == UNSPEC_INDNTPOFF)
+    return true;
+
+  return false;
+})
+
+;; operators --------------------------------------------------------------
+
+;; Return nonzero if OP is a valid comparison operator
+;; for a branch condition.
+
+(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 (GET_CODE (XEXP (op, 0)) != REG
+      || REGNO (XEXP (op, 0)) != CC_REGNUM
+      || XEXP (op, 1) != const0_rtx)
+    return false;
+
+  return (s390_branch_condition_mask (op) >= 0);
+})
+
+;; Return nonzero if OP is a valid comparison operator
+;; for an ALC condition.
+
+(define_predicate "s390_alc_comparison"
+  (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
+{
+  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
+    op = XEXP (op, 0);
+
+  if (!COMPARISON_P (op))
+    return false;
+
+  if (GET_CODE (XEXP (op, 0)) != REG
+      || REGNO (XEXP (op, 0)) != CC_REGNUM
+      || XEXP (op, 1) != const0_rtx)
+    return false;
+
+  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 false;
+    }
+})
+
+;; Return nonzero if OP is a valid comparison operator
+;; for an SLB condition.
+
+(define_predicate "s390_slb_comparison"
+  (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
+{
+  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
+    op = XEXP (op, 0);
+
+  if (!COMPARISON_P (op))
+    return false;
+
+  if (GET_CODE (XEXP (op, 0)) != REG
+      || REGNO (XEXP (op, 0)) != CC_REGNUM
+      || XEXP (op, 1) != const0_rtx)
+    return false;
+
+  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 false;
+    }
+})
+
+;; Return true if OP is a load multiple operation.  It is known to be a
+;; PARALLEL and the first section will be tested.
+
+(define_special_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 false;
+
+  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 false;
+
+  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 false;
+    }
+
+  return true;
+})
+
+;; Return true if OP is a store multiple operation.  It is known to be a
+;; PARALLEL and the first section will be tested.
+
+(define_special_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 false;
+
+  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 false;
+
+  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 false;
+    }
+  return true;
+})
index 25aeef869915f66ad77b48db8d823584c104e6e4..e8f94efe3e3edd0c6547184437dd78abc6eddf4a 100644 (file)
@@ -33,14 +33,6 @@ extern void s390_conditional_register_usage (void);
 #ifdef RTX_CODE
 extern int s390_extra_constraint_str (rtx, int, const char *);
 extern int s390_const_ok_for_constraint_p (HOST_WIDE_INT, int, const char *);
-extern int const0_operand (rtx, enum machine_mode);
-extern int consttable_operand (rtx, enum machine_mode);
-extern int larl_operand (rtx, enum machine_mode);
-extern int s_operand (rtx, enum machine_mode);
-extern int shift_count_operand (rtx, enum machine_mode);
-extern int bras_sym_operand (rtx, enum machine_mode);
-extern int load_multiple_operation (rtx, enum machine_mode);
-extern int store_multiple_operation (rtx, enum machine_mode);
 extern int s390_single_part (rtx, enum machine_mode, enum machine_mode, int);
 extern unsigned HOST_WIDE_INT s390_extract_part (rtx, enum machine_mode, int);
 extern bool s390_split_ok_p (rtx, rtx, enum machine_mode, int);
@@ -51,9 +43,6 @@ extern int s390_match_ccmode (rtx, enum machine_mode);
 extern enum machine_mode s390_tm_ccmode (rtx, rtx, int);
 extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
 extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx *);
-extern int s390_comparison (rtx op, enum machine_mode mode);
-extern int s390_alc_comparison (rtx op, enum machine_mode mode);
-extern int s390_slb_comparison (rtx op, enum machine_mode mode);
 extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
 extern void s390_emit_jump (rtx, rtx);
 extern int symbolic_reference_mentioned_p (rtx);
@@ -74,7 +63,6 @@ extern enum reg_class s390_secondary_input_reload_class (enum reg_class,
 extern enum reg_class s390_secondary_output_reload_class (enum reg_class,
                                                          enum machine_mode,
                                                          rtx);
-extern int s390_plus_operand (rtx, enum machine_mode);
 extern void s390_expand_plus_operand (rtx, rtx, rtx);
 extern void emit_symbolic_move (rtx *);
 extern void s390_load_address (rtx, rtx);
@@ -103,6 +91,8 @@ extern void s390_output_dwarf_dtprel (FILE*, int, rtx);
 extern int s390_agen_dep_p (rtx, rtx);
 extern rtx s390_load_got (void);
 extern void s390_emit_tpf_eh_return (rtx);
+extern bool s390_legitimate_address_without_index_p (rtx);
+extern int s390_branch_condition_mask (rtx);
 
 #endif /* RTX_CODE */
 
index 90919e36d5305025b447bb7eae4138b74ab1eff3..8bbe3f59ebc2f421af7fe43288890fdbe5005adb 100644 (file)
@@ -52,9 +52,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #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);
@@ -380,9 +377,7 @@ 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);
@@ -413,10 +408,20 @@ static int s390_function_arg_size (enum machine_mode, tree);
 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 CODE is a valid address without index.  */
+
+bool
+s390_legitimate_address_without_index_p (rtx op)
+{
+  struct s390_address addr;
+
+  if (!s390_decompose_address (XEXP (op, 0), &addr))
+    return false;
+  if (addr.indx)
+    return false;
+
+  return true;
+}
 
 /* Return true if SET either doesn't set the CC register, or else
    the source and destination have matching CC modes and that
@@ -791,126 +796,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,172 +1397,6 @@ 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
-check_mode (register rtx op, enum machine_mode *mode)
-{
-  if (*mode == VOIDmode)
-      *mode = GET_MODE (op);
-  else
-  {
-    if (GET_MODE (op) != VOIDmode && GET_MODE (op) != *mode)
-       return 0;
-  }
-  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_operand (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 +1835,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 +1846,6 @@ tls_symbolic_operand (register rtx op)
   return SYMBOL_REF_TLS_MODEL (op);
 }
 \f
-/* 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 +2152,6 @@ s390_secondary_output_reload_class (enum reg_class class,
   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.  */
index a6b7a3afd519142ecde5568561bacccb3bb45f60..af09184ce634c22167ee6a772f1939aebb8a7d84 100644 (file)
@@ -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 4c779c34180ff9404ae8af4bed396d95f7cc1aa2..022d7791bba6d8f0bfbcc994139ba1ff8cfb0957 100644 (file)
 ;; Pipeline description for z990. 
 (include "2084.md")
 
+;; Predicates
+(include "predicates.md")
+
 ;;
 ;;- Compare instructions.
 ;;