h8300-protos.h: Remove prototypes for general_operand_src...
authorKazu Hirata <kazu@cs.umass.edu>
Thu, 17 Mar 2005 21:01:34 +0000 (21:01 +0000)
committerKazu Hirata <kazu@gcc.gnu.org>
Thu, 17 Mar 2005 21:01:34 +0000 (21:01 +0000)
* config/h8300/h8300-protos.h: Remove prototypes for
general_operand_src, general_operand_dst, single_one_operand,
single_zero_operand, call_insn_operand,
two_insn_adds_subs_operand, small_call_insn_operand,
jump_address_operand, bit_operand, bit_memory_operand,
stack_pointer_operand, const_int_gt_2_operand,
const_int_ge_8_operand, const_int_qi_operand,
const_int_hi_operand, incdec_operand, bit_operator,
nshift_operator, eqne_operator, gtle_operator,
gtuleu_operator, iorxor_operator.
Add prototypes for h8sx_shift_type h8sx_classify_shift and
h8300_ldm_stm_parallel.
* config/h8300/h8300.c (h8sx_shift_type,): Move to
h8300-protos.h.
(SYMBOL_FLAG_FUNCVEC_FUNCTION, SYMBOL_FLAG_EIGHTBIT_DATA,
SYMBOL_FLAG_TINY_DATA): Move to h8300.h.
(h8300_ldm_stm_parallel): Make it extern.
(h8300_ldm_parallel, h8300_stm_parallel,
h8300_return_parallel, general_operand_src,
general_operand_dst, h8300_dst_operand, h8300_src_operand,
nibble_operand, reg_or_nibble_operand, single_one_operand,
single_zero_operand, call_insn_operand,
two_insn_adds_subs_operand, small_call_insn_operand,
jump_address_operand, bit_operand, bit_memory_operand,
stack_pointer_operand, const_int_gt_2_operand,
const_int_ge_8_operand, const_int_qi_operand,
const_int_hi_operand, incdec_operand, eqne_operator,
gtle_operator, gtuleu_operator, iorxor_operator, bit_operator,
h8sx_binary_memory_operator, h8sx_unary_memory_operator,
h8sx_unary_shift_operator, h8sx_binary_shift_operator,
nshift_operator): Move to predicates.md.
* config/h8300/h8300.h (PREDICATE_CODES): Remove.
* config/h8300/h8300.md: Include predicates.md.
* config/h8300/predicates.md: New.

From-SVN: r96631

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

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