+2005-06-30 Kazu Hirata <kazu@codesourcery.com>
+
+ * config/c4x/c4x-protos.h: Remove the prototypes for those
+ functions removed from c4x.c. Add prototypes for those
+ functions exported in c4x.c.
+ * config/c4x/c4x.c (any_operand, fp_zero_operand,
+ const_operand, stik_const_operand, not_const_operand,
+ reg_operand, r0r1_reg_operand, r2r3_reg_operand,
+ ext_low_reg_operand, ext_reg_operand, std_reg_operand,
+ std_or_reg_operand, addr_reg_operand, index_reg_operand,
+ dp_reg_operand, sp_reg_operand, st_reg_operand,
+ rc_reg_operand, call_address_operand,
+ symbolic_address_operand, dst_operand, src_operand,
+ src_hi_operand, lsrc_operand, tsrc_operand,
+ nonimmediate_src_operand, nonimmediate_lsrc_operand,
+ reg_or_const_operand, par_ind_operand, parallel_operand):
+ Remove.
+ (c4x_immed_float_p, c4x_a_register, c4x_x_register,
+ c4x_K_constant, c4x_N_constant, c4x_O_constant,
+ c4x_S_indirect): Export.
+ * config/c4x/c4x.h (PREDICATE_CODES): Remove.
+ * config/c4x/c4x.md: Include predicates.md.
+ * config/c4x/predicates.md: New.
+
2005-06-30 Jakub Jelinek <jakub@redhat.com>
* function.c (stack_protect_epilogue): Pass label to
/* Definitions of target machine for GNU compiler. TMS320C[34]x
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2004
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
extern int c4x_autoinc_operand (rtx, enum machine_mode);
-extern int any_operand (rtx, enum machine_mode);
-
-extern int fp_zero_operand (rtx, enum machine_mode);
-
-extern int const_operand (rtx, enum machine_mode);
-
-extern int stik_const_operand (rtx, enum machine_mode);
-
-extern int not_const_operand (rtx, enum machine_mode);
-
-extern int parallel_operand (rtx, enum machine_mode);
-
extern int reg_or_const_operand (rtx, enum machine_mode);
-extern int reg_operand (rtx, enum machine_mode);
-
extern int mixed_subreg_operand (rtx, enum machine_mode);
extern int reg_imm_operand (rtx, enum machine_mode);
-extern int r0r1_reg_operand (rtx, enum machine_mode);
-
-extern int r2r3_reg_operand (rtx, enum machine_mode);
-
-extern int ext_low_reg_operand (rtx, enum machine_mode);
-
-extern int ext_reg_operand (rtx, enum machine_mode);
-
-extern int std_reg_operand (rtx, enum machine_mode);
-
-extern int std_or_reg_operand (rtx, enum machine_mode);
-
-extern int dst_operand (rtx, enum machine_mode);
-
-extern int src_operand (rtx, enum machine_mode);
-
-extern int src_hi_operand (rtx, enum machine_mode);
-
-extern int lsrc_operand (rtx, enum machine_mode);
-
-extern int tsrc_operand (rtx, enum machine_mode);
-
-extern int nonimmediate_src_operand (rtx, enum machine_mode);
-
-extern int nonimmediate_lsrc_operand (rtx, enum machine_mode);
-
-extern int addr_reg_operand (rtx, enum machine_mode);
-
-extern int index_reg_operand (rtx, enum machine_mode);
-
-extern int dp_reg_operand (rtx, enum machine_mode);
-
-extern int sp_reg_operand (rtx, enum machine_mode);
-
-extern int rc_reg_operand (rtx, enum machine_mode);
-
-extern int st_reg_operand (rtx, enum machine_mode);
-
-extern int symbolic_address_operand (rtx, enum machine_mode);
-
extern int ar0_reg_operand (rtx, enum machine_mode);
extern int ar0_mem_operand (rtx, enum machine_mode);
extern int arx_reg_operand (rtx, enum machine_mode);
-extern int call_address_operand (rtx, enum machine_mode);
-
-extern int par_ind_operand (rtx, enum machine_mode);
-
extern int not_rc_reg (rtx, enum machine_mode);
extern int not_modify_reg (rtx, enum machine_mode);
extern int c4x_shiftable_constant (rtx);
+extern int c4x_immed_float_p (rtx);
+
+extern int c4x_a_register (rtx);
+
+extern int c4x_x_register (rtx);
+
extern int c4x_H_constant (rtx);
extern int c4x_I_constant (rtx);
extern int c4x_J_constant (rtx);
+extern int c4x_K_constant (rtx);
+
extern int c4x_L_constant (rtx);
+extern int c4x_N_constant (rtx);
+
+extern int c4x_O_constant (rtx);
+
extern int c4x_Q_constraint (rtx);
extern int c4x_R_constraint (rtx);
+extern int c4x_S_indirect (rtx);
+
extern int c4x_S_constraint (rtx);
extern int c4x_T_constraint (rtx);
static int c4x_isr_reg_used_p (unsigned int);
static int c4x_leaf_function_p (void);
static int c4x_naked_function_p (void);
-static int c4x_immed_float_p (rtx);
-static int c4x_a_register (rtx);
-static int c4x_x_register (rtx);
static int c4x_immed_int_constant (rtx);
static int c4x_immed_float_constant (rtx);
-static int c4x_K_constant (rtx);
-static int c4x_N_constant (rtx);
-static int c4x_O_constant (rtx);
static int c4x_R_indirect (rtx);
-static int c4x_S_indirect (rtx);
static void c4x_S_address_parse (rtx , int *, int *, int *, int *);
static int c4x_valid_operands (enum rtx_code, rtx *, enum machine_mode, int);
static int c4x_arn_reg_operand (rtx, enum machine_mode, unsigned int);
/* Return nonzero if the floating point operand will fit
in the immediate field. */
-static int
+int
c4x_immed_float_p (rtx op)
{
long convval[2];
}
-static int
+int
c4x_a_register (rtx op)
{
return REG_P (op) && IS_ADDR_OR_PSEUDO_REG (op);
}
-static int
+int
c4x_x_register (rtx op)
{
return REG_P (op) && IS_INDEX_OR_PSEUDO_REG (op);
}
-static int
+int
c4x_K_constant (rtx op)
{
if (TARGET_C3X || ! c4x_immed_int_constant (op))
}
-static int
+int
c4x_N_constant (rtx op)
{
return c4x_immed_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op));
}
-static int
+int
c4x_O_constant (rtx op)
{
return c4x_immed_int_constant (op) && IS_HIGH_CONST (INTVAL (op));
}
-static int
+int
c4x_S_indirect (rtx op)
{
enum machine_mode mode = GET_MODE (op);
}
-/* Match any operand. */
-
-int
-any_operand (register rtx op ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return 1;
-}
-
-
-/* Nonzero if OP is a floating point value with value 0.0. */
-
-int
-fp_zero_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- REAL_VALUE_TYPE r;
-
- if (GET_CODE (op) != CONST_DOUBLE)
- return 0;
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- return REAL_VALUES_EQUAL (r, dconst0);
-}
-
-
-int
-const_operand (register rtx op, register enum machine_mode mode)
-{
- switch (mode)
- {
- case QFmode:
- case HFmode:
- if (GET_CODE (op) != CONST_DOUBLE
- || GET_MODE (op) != mode
- || GET_MODE_CLASS (mode) != MODE_FLOAT)
- return 0;
-
- return c4x_immed_float_p (op);
-
-#if Pmode != QImode
- case Pmode:
-#endif
- case QImode:
- if (GET_CODE (op) != CONST_INT
- || (GET_MODE (op) != VOIDmode && GET_MODE (op) != mode)
- || GET_MODE_CLASS (mode) != MODE_INT)
- return 0;
-
- return IS_HIGH_CONST (INTVAL (op)) || IS_INT16_CONST (INTVAL (op));
-
- case HImode:
- return 0;
-
- default:
- return 0;
- }
-}
-
-
-int
-stik_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return c4x_K_constant (op);
-}
-
-
-int
-not_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return c4x_N_constant (op);
-}
-
-
-int
-reg_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == SUBREG
- && GET_MODE (op) == QFmode)
- return 0;
- return register_operand (op, mode);
-}
-
-
int
mixed_subreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
}
-/* Extended precision register R0-R1. */
-
-int
-r0r1_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_R0R1_OR_PSEUDO_REG (op);
-}
-
-
-/* Extended precision register R2-R3. */
-
-int
-r2r3_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_R2R3_OR_PSEUDO_REG (op);
-}
-
-
-/* Low extended precision register R0-R7. */
-
-int
-ext_low_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_EXT_LOW_OR_PSEUDO_REG (op);
-}
-
-
-/* Extended precision register. */
-
-int
-ext_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (! REG_P (op))
- return 0;
- return IS_EXT_OR_PSEUDO_REG (op);
-}
-
-
-/* Standard precision register. */
-
-int
-std_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_STD_OR_PSEUDO_REG (op);
-}
-
-/* Standard precision or normal register. */
-
-int
-std_or_reg_operand (rtx op, enum machine_mode mode)
-{
- if (reload_in_progress)
- return std_reg_operand (op, mode);
- return reg_operand (op, mode);
-}
-
-/* Address register. */
-
-int
-addr_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- return c4x_a_register (op);
-}
-
-
-/* Index register. */
-
-int
-index_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return c4x_x_register (op);
-}
-
-
-/* DP register. */
-
-int
-dp_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return REG_P (op) && IS_DP_OR_PSEUDO_REG (op);
-}
-
-
-/* SP register. */
-
-int
-sp_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return REG_P (op) && IS_SP_OR_PSEUDO_REG (op);
-}
-
-
-/* ST register. */
-
-int
-st_reg_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return REG_P (op) && IS_ST_OR_PSEUDO_REG (op);
-}
-
-
-/* RC register. */
-
-int
-rc_reg_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return REG_P (op) && IS_RC_OR_PSEUDO_REG (op);
-}
-
-
-int
-call_address_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (REG_P (op) || symbolic_address_operand (op, mode));
-}
-
-
-/* Symbolic address operand. */
-
-int
-symbolic_address_operand (register rtx op,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
- default:
- return 0;
- }
-}
-
-
-/* Check dst operand of a move instruction. */
-
-int
-dst_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == SUBREG
- && mixed_subreg_operand (op, mode))
- return 0;
-
- if (REG_P (op))
- return reg_operand (op, mode);
-
- return nonimmediate_operand (op, mode);
-}
-
-
-/* Check src operand of two operand arithmetic instructions. */
-
-int
-src_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == SUBREG
- && mixed_subreg_operand (op, mode))
- return 0;
-
- if (REG_P (op))
- return reg_operand (op, mode);
-
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- if (GET_CODE (op) == CONST_INT)
- return (mode == QImode || mode == Pmode || mode == HImode)
- && c4x_I_constant (op);
-
- /* We don't like CONST_DOUBLE integers. */
- if (GET_CODE (op) == CONST_DOUBLE)
- return c4x_H_constant (op);
-
- /* Disallow symbolic addresses. Only the predicate
- symbolic_address_operand will match these. */
- if (GET_CODE (op) == SYMBOL_REF
- || GET_CODE (op) == LABEL_REF
- || GET_CODE (op) == CONST)
- return 0;
-
- /* If TARGET_LOAD_DIRECT_MEMS is nonzero, disallow direct memory
- access to symbolic addresses. These operands will get forced
- into a register and the movqi expander will generate a
- HIGH/LO_SUM pair if TARGET_EXPOSE_LDP is nonzero. */
- if (GET_CODE (op) == MEM
- && ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
- || GET_CODE (XEXP (op, 0)) == LABEL_REF
- || GET_CODE (XEXP (op, 0)) == CONST)))
- return !TARGET_EXPOSE_LDP &&
- ! TARGET_LOAD_DIRECT_MEMS && GET_MODE (op) == mode;
-
- return general_operand (op, mode);
-}
-
-
-int
-src_hi_operand (rtx op, enum machine_mode mode)
-{
- if (c4x_O_constant (op))
- return 1;
- return src_operand (op, mode);
-}
-
-
-/* Check src operand of two operand logical instructions. */
-
-int
-lsrc_operand (rtx op, enum machine_mode mode)
-{
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- if (mode != QImode && mode != Pmode)
- fatal_insn ("mode not QImode", op);
-
- if (GET_CODE (op) == CONST_INT)
- return c4x_L_constant (op) || c4x_J_constant (op);
-
- return src_operand (op, mode);
-}
-
-
-/* Check src operand of two operand tricky instructions. */
-
-int
-tsrc_operand (rtx op, enum machine_mode mode)
-{
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- if (mode != QImode && mode != Pmode)
- fatal_insn ("mode not QImode", op);
-
- if (GET_CODE (op) == CONST_INT)
- return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op);
-
- return src_operand (op, mode);
-}
-
-
-/* Check src operand of two operand non immediate instructions. */
-
-int
-nonimmediate_src_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
- return 0;
-
- return src_operand (op, mode);
-}
-
-
-/* Check logical src operand of two operand non immediate instructions. */
-
-int
-nonimmediate_lsrc_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
- return 0;
-
- return lsrc_operand (op, mode);
-}
-
-
-int
-reg_or_const_operand (rtx op, enum machine_mode mode)
-{
- return reg_operand (op, mode) || const_operand (op, mode);
-}
-
-
-/* Check for indirect operands allowable in parallel instruction. */
-
-int
-par_ind_operand (rtx op, enum machine_mode mode)
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
-
- return c4x_S_indirect (op);
-}
-
-
-/* Check for operands allowable in parallel instruction. */
-
-int
-parallel_operand (rtx op, enum machine_mode mode)
-{
- return ext_low_reg_operand (op, mode) || par_ind_operand (op, mode);
-}
-
-
static void
c4x_S_address_parse (rtx op, int *base, int *incdec, int *index, int *disp)
{
#define ASM_OUTPUT_ASM(FILE, STRING) fprintf (FILE, "%s\n", STRING)
-/* Define the codes that are matched by predicates in c4x.c. */
-
-#define PREDICATE_CODES \
- {"fp_zero_operand", {CONST_DOUBLE}}, \
- {"const_operand", {CONST_INT, CONST_DOUBLE}}, \
- {"stik_const_operand", {CONST_INT}}, \
- {"not_const_operand", {CONST_INT}}, \
- {"reg_operand", {REG, SUBREG}}, \
- {"reg_or_const_operand", {REG, SUBREG, CONST_INT, CONST_DOUBLE}},\
- {"r0r1_reg_operand", {REG, SUBREG}}, \
- {"r2r3_reg_operand", {REG, SUBREG}}, \
- {"ext_low_reg_operand", {REG, SUBREG}}, \
- {"ext_reg_operand", {REG, SUBREG}}, \
- {"std_reg_operand", {REG, SUBREG}}, \
- {"std_or_reg_operand", {REG, SUBREG}}, \
- {"addr_reg_operand", {REG, SUBREG}}, \
- {"index_reg_operand", {REG, SUBREG}}, \
- {"dp_reg_operand", {REG}}, \
- {"sp_reg_operand", {REG}}, \
- {"st_reg_operand", {REG}}, \
- {"rc_reg_operand", {REG}}, \
- {"call_address_operand", {REG, SYMBOL_REF, LABEL_REF, CONST}}, \
- {"dst_operand", {SUBREG, REG, MEM}}, \
- {"src_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
- {"src_hi_operand", {SUBREG, REG, MEM, CONST_DOUBLE}}, \
- {"lsrc_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
- {"tsrc_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
- {"nonimmediate_src_operand", {SUBREG, REG, MEM}}, \
- {"nonimmediate_lsrc_operand", {SUBREG, REG, MEM}}, \
- {"any_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
- {"par_ind_operand", {MEM}}, \
- {"parallel_operand", {SUBREG, REG, MEM}}, \
- {"symbolic_address_operand", {SYMBOL_REF, LABEL_REF, CONST}},
-
-
/* Define the intrinsic functions for the c3x/c4x. */
enum c4x_builtins
;; Machine description for the TMS320C[34]x for GCC
;; Copyright (C) 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2002, 2004 Free Software Foundation, Inc.
+;; 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
;; and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl)
(const_int 1) (const_int 0))]
(const_int 0)))
+(include "predicates.md")
;
; C4x INSN PATTERNS:
--- /dev/null
+;; Predicate definitions for TMS320C[34]x.
+;; 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.
+
+;; Nonzero if OP is a floating point value with value 0.0.
+
+(define_predicate "fp_zero_operand"
+ (match_code "const_double")
+{
+ REAL_VALUE_TYPE r;
+
+ if (GET_CODE (op) != CONST_DOUBLE)
+ return 0;
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ return REAL_VALUES_EQUAL (r, dconst0);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "const_operand"
+ (match_code "const_int,const_double")
+{
+ switch (mode)
+ {
+ case QFmode:
+ case HFmode:
+ if (GET_CODE (op) != CONST_DOUBLE
+ || GET_MODE (op) != mode
+ || GET_MODE_CLASS (mode) != MODE_FLOAT)
+ return 0;
+
+ return c4x_immed_float_p (op);
+
+#if Pmode != QImode
+ case Pmode:
+#endif
+ case QImode:
+ if (GET_CODE (op) != CONST_INT
+ || (GET_MODE (op) != VOIDmode && GET_MODE (op) != mode)
+ || GET_MODE_CLASS (mode) != MODE_INT)
+ return 0;
+
+ return IS_HIGH_CONST (INTVAL (op)) || IS_INT16_CONST (INTVAL (op));
+
+ case HImode:
+ return 0;
+
+ default:
+ return 0;
+ }
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "stik_const_operand"
+ (match_code "const_int")
+{
+ return c4x_K_constant (op);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "not_const_operand"
+ (match_code "const_int")
+{
+ return c4x_N_constant (op);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "reg_operand"
+ (match_code "reg,subreg")
+{
+ if (GET_CODE (op) == SUBREG
+ && GET_MODE (op) == QFmode)
+ return 0;
+ return register_operand (op, mode);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "reg_or_const_operand"
+ (match_code "reg,subreg,const_int,const_double")
+{
+ return reg_operand (op, mode) || const_operand (op, mode);
+})
+
+;; Extended precision register R0-R1.
+
+(define_predicate "r0r1_reg_operand"
+ (match_code "reg,subreg")
+{
+ if (! reg_operand (op, mode))
+ return 0;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ return REG_P (op) && IS_R0R1_OR_PSEUDO_REG (op);
+})
+
+;; Extended precision register R2-R3.
+
+(define_predicate "r2r3_reg_operand"
+ (match_code "reg,subreg")
+{
+ if (! reg_operand (op, mode))
+ return 0;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ return REG_P (op) && IS_R2R3_OR_PSEUDO_REG (op);
+})
+
+;; Low extended precision register R0-R7.
+
+(define_predicate "ext_low_reg_operand"
+ (match_code "reg,subreg")
+{
+ if (! reg_operand (op, mode))
+ return 0;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ return REG_P (op) && IS_EXT_LOW_OR_PSEUDO_REG (op);
+})
+
+;; Extended precision register.
+
+(define_predicate "ext_reg_operand"
+ (match_code "reg,subreg")
+{
+ if (! reg_operand (op, mode))
+ return 0;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ if (! REG_P (op))
+ return 0;
+ return IS_EXT_OR_PSEUDO_REG (op);
+})
+
+;; Standard precision register.
+
+(define_predicate "std_reg_operand"
+ (match_code "reg,subreg")
+{
+ if (! reg_operand (op, mode))
+ return 0;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ return REG_P (op) && IS_STD_OR_PSEUDO_REG (op);
+})
+
+;; Standard precision or normal register.
+
+(define_predicate "std_or_reg_operand"
+ (match_code "reg,subreg")
+{
+ if (reload_in_progress)
+ return std_reg_operand (op, mode);
+ return reg_operand (op, mode);
+})
+
+;; Address register.
+
+(define_predicate "addr_reg_operand"
+ (match_code "reg,subreg")
+{
+ if (! reg_operand (op, mode))
+ return 0;
+ return c4x_a_register (op);
+})
+
+;; Index register.
+
+(define_predicate "index_reg_operand"
+ (match_code "reg,subreg")
+{
+ if (! reg_operand (op, mode))
+ return 0;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ return c4x_x_register (op);
+})
+
+;; DP register.
+
+(define_predicate "dp_reg_operand"
+ (match_code "reg")
+{
+ return REG_P (op) && IS_DP_OR_PSEUDO_REG (op);
+})
+
+;; SP register.
+
+(define_predicate "sp_reg_operand"
+ (match_code "reg")
+{
+ return REG_P (op) && IS_SP_OR_PSEUDO_REG (op);
+})
+
+;; ST register.
+
+(define_predicate "st_reg_operand"
+ (match_code "reg")
+{
+ return REG_P (op) && IS_ST_OR_PSEUDO_REG (op);
+})
+
+;; RC register.
+
+(define_predicate "rc_reg_operand"
+ (match_code "reg")
+{
+ return REG_P (op) && IS_RC_OR_PSEUDO_REG (op);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "call_address_operand"
+ (match_code "reg,symbol_ref,label_ref,const")
+{
+ return (REG_P (op) || symbolic_address_operand (op, mode));
+})
+
+;; Check dst operand of a move instruction.
+
+(define_predicate "dst_operand"
+ (match_code "subreg,reg,mem")
+{
+ if (GET_CODE (op) == SUBREG
+ && mixed_subreg_operand (op, mode))
+ return 0;
+
+ if (REG_P (op))
+ return reg_operand (op, mode);
+
+ return nonimmediate_operand (op, mode);
+})
+
+;; Check src operand of two operand arithmetic instructions.
+
+(define_predicate "src_operand"
+ (match_code "subreg,reg,mem,const_int,const_double")
+{
+ if (GET_CODE (op) == SUBREG
+ && mixed_subreg_operand (op, mode))
+ return 0;
+
+ if (REG_P (op))
+ return reg_operand (op, mode);
+
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ if (GET_CODE (op) == CONST_INT)
+ return (mode == QImode || mode == Pmode || mode == HImode)
+ && c4x_I_constant (op);
+
+ /* We don't like CONST_DOUBLE integers. */
+ if (GET_CODE (op) == CONST_DOUBLE)
+ return c4x_H_constant (op);
+
+ /* Disallow symbolic addresses. Only the predicate
+ symbolic_address_operand will match these. */
+ if (GET_CODE (op) == SYMBOL_REF
+ || GET_CODE (op) == LABEL_REF
+ || GET_CODE (op) == CONST)
+ return 0;
+
+ /* If TARGET_LOAD_DIRECT_MEMS is nonzero, disallow direct memory
+ access to symbolic addresses. These operands will get forced
+ into a register and the movqi expander will generate a
+ HIGH/LO_SUM pair if TARGET_EXPOSE_LDP is nonzero. */
+ if (GET_CODE (op) == MEM
+ && ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (op, 0)) == LABEL_REF
+ || GET_CODE (XEXP (op, 0)) == CONST)))
+ return !TARGET_EXPOSE_LDP &&
+ ! TARGET_LOAD_DIRECT_MEMS && GET_MODE (op) == mode;
+
+ return general_operand (op, mode);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "src_hi_operand"
+ (match_code "subreg,reg,mem,const_double")
+{
+ if (c4x_O_constant (op))
+ return 1;
+ return src_operand (op, mode);
+})
+
+;; Check src operand of two operand logical instructions.
+
+(define_predicate "lsrc_operand"
+ (match_code "subreg,reg,mem,const_int,const_double")
+{
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ if (mode != QImode && mode != Pmode)
+ fatal_insn ("mode not QImode", op);
+
+ if (GET_CODE (op) == CONST_INT)
+ return c4x_L_constant (op) || c4x_J_constant (op);
+
+ return src_operand (op, mode);
+})
+
+;; Check src operand of two operand tricky instructions.
+
+(define_predicate "tsrc_operand"
+ (match_code "subreg,reg,mem,const_int,const_double")
+{
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ if (mode != QImode && mode != Pmode)
+ fatal_insn ("mode not QImode", op);
+
+ if (GET_CODE (op) == CONST_INT)
+ return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op);
+
+ return src_operand (op, mode);
+})
+
+;; Check src operand of two operand non immediate instructions.
+
+(define_predicate "nonimmediate_src_operand"
+ (match_code "subreg,reg,mem")
+{
+ if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
+ return 0;
+
+ return src_operand (op, mode);
+})
+
+;; Check logical src operand of two operand non immediate instructions.
+
+(define_predicate "nonimmediate_lsrc_operand"
+ (match_code "subreg,reg,mem")
+{
+ if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
+ return 0;
+
+ return lsrc_operand (op, mode);
+})
+
+;; Match any operand.
+
+(define_predicate "any_operand"
+ (match_code "subreg,reg,mem,const_int,const_double")
+{
+ return 1;
+})
+
+;; Check for indirect operands allowable in parallel instruction.
+
+(define_predicate "par_ind_operand"
+ (match_code "mem")
+{
+ if (mode != VOIDmode && mode != GET_MODE (op))
+ return 0;
+
+ return c4x_S_indirect (op);
+})
+
+;; Check for operands allowable in parallel instruction.
+
+(define_predicate "parallel_operand"
+ (match_code "subreg,reg,mem")
+{
+ return ext_low_reg_operand (op, mode) || par_ind_operand (op, mode);
+})
+
+;; Symbolic address operand.
+
+(define_predicate "symbolic_address_operand"
+ (match_code "symbol_ref,label_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return 1;
+ default:
+ return 0;
+ }
+})