;; Predicate definitions for TMS320C[34]x.
|
;; Predicate definitions for TMS320C[34]x.
|
;; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
;; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
;;
|
;;
|
;; This file is part of GCC.
|
;; This file is part of GCC.
|
;;
|
;;
|
;; GCC is free software; you can redistribute it and/or modify
|
;; GCC is free software; you can redistribute it and/or modify
|
;; it under the terms of the GNU General Public License as published by
|
;; it under the terms of the GNU General Public License as published by
|
;; the Free Software Foundation; either version 3, or (at your option)
|
;; the Free Software Foundation; either version 3, or (at your option)
|
;; any later version.
|
;; any later version.
|
;;
|
;;
|
;; GCC is distributed in the hope that it will be useful,
|
;; GCC is distributed in the hope that it will be useful,
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
;; GNU General Public License for more details.
|
;; GNU General Public License for more details.
|
;;
|
;;
|
;; You should have received a copy of the GNU General Public License
|
;; You should have received a copy of the GNU General Public License
|
;; along with GCC; see the file COPYING3. If not see
|
;; along with GCC; see the file COPYING3. If not see
|
;; .
|
;; .
|
|
|
;; Nonzero if OP is a floating point value with value 0.0.
|
;; Nonzero if OP is a floating point value with value 0.0.
|
|
|
(define_predicate "fp_zero_operand"
|
(define_predicate "fp_zero_operand"
|
(match_code "const_double")
|
(match_code "const_double")
|
{
|
{
|
REAL_VALUE_TYPE r;
|
REAL_VALUE_TYPE r;
|
|
|
if (GET_CODE (op) != CONST_DOUBLE)
|
if (GET_CODE (op) != CONST_DOUBLE)
|
return 0;
|
return 0;
|
REAL_VALUE_FROM_CONST_DOUBLE (r, op);
|
REAL_VALUE_FROM_CONST_DOUBLE (r, op);
|
return REAL_VALUES_EQUAL (r, dconst0);
|
return REAL_VALUES_EQUAL (r, dconst0);
|
})
|
})
|
|
|
;; TODO: Add a comment here.
|
;; TODO: Add a comment here.
|
|
|
(define_predicate "const_operand"
|
(define_predicate "const_operand"
|
(match_code "const_int,const_double")
|
(match_code "const_int,const_double")
|
{
|
{
|
switch (mode)
|
switch (mode)
|
{
|
{
|
case QFmode:
|
case QFmode:
|
case HFmode:
|
case HFmode:
|
if (GET_CODE (op) != CONST_DOUBLE
|
if (GET_CODE (op) != CONST_DOUBLE
|
|| GET_MODE (op) != mode
|
|| GET_MODE (op) != mode
|
|| GET_MODE_CLASS (mode) != MODE_FLOAT)
|
|| GET_MODE_CLASS (mode) != MODE_FLOAT)
|
return 0;
|
return 0;
|
|
|
return c4x_immed_float_p (op);
|
return c4x_immed_float_p (op);
|
|
|
#if Pmode != QImode
|
#if Pmode != QImode
|
case Pmode:
|
case Pmode:
|
#endif
|
#endif
|
case QImode:
|
case QImode:
|
if (GET_CODE (op) != CONST_INT
|
if (GET_CODE (op) != CONST_INT
|
|| (GET_MODE (op) != VOIDmode && GET_MODE (op) != mode)
|
|| (GET_MODE (op) != VOIDmode && GET_MODE (op) != mode)
|
|| GET_MODE_CLASS (mode) != MODE_INT)
|
|| GET_MODE_CLASS (mode) != MODE_INT)
|
return 0;
|
return 0;
|
|
|
return IS_HIGH_CONST (INTVAL (op)) || IS_INT16_CONST (INTVAL (op));
|
return IS_HIGH_CONST (INTVAL (op)) || IS_INT16_CONST (INTVAL (op));
|
|
|
case HImode:
|
case HImode:
|
return 0;
|
return 0;
|
|
|
default:
|
default:
|
return 0;
|
return 0;
|
}
|
}
|
})
|
})
|
|
|
;; TODO: Add a comment here.
|
;; TODO: Add a comment here.
|
|
|
(define_predicate "stik_const_operand"
|
(define_predicate "stik_const_operand"
|
(match_code "const_int")
|
(match_code "const_int")
|
{
|
{
|
return c4x_K_constant (op);
|
return c4x_K_constant (op);
|
})
|
})
|
|
|
;; TODO: Add a comment here.
|
;; TODO: Add a comment here.
|
|
|
(define_predicate "not_const_operand"
|
(define_predicate "not_const_operand"
|
(match_code "const_int")
|
(match_code "const_int")
|
{
|
{
|
return c4x_N_constant (op);
|
return c4x_N_constant (op);
|
})
|
})
|
|
|
;; TODO: Add a comment here.
|
;; TODO: Add a comment here.
|
|
|
(define_predicate "reg_operand"
|
(define_predicate "reg_operand"
|
(match_code "reg,subreg")
|
(match_code "reg,subreg")
|
{
|
{
|
if (GET_CODE (op) == SUBREG
|
if (GET_CODE (op) == SUBREG
|
&& GET_MODE (op) == QFmode)
|
&& GET_MODE (op) == QFmode)
|
return 0;
|
return 0;
|
return register_operand (op, mode);
|
return register_operand (op, mode);
|
})
|
})
|
|
|
;; TODO: Add a comment here.
|
;; TODO: Add a comment here.
|
|
|
(define_predicate "reg_or_const_operand"
|
(define_predicate "reg_or_const_operand"
|
(match_code "reg,subreg,const_int,const_double")
|
(match_code "reg,subreg,const_int,const_double")
|
{
|
{
|
return reg_operand (op, mode) || const_operand (op, mode);
|
return reg_operand (op, mode) || const_operand (op, mode);
|
})
|
})
|
|
|
;; Extended precision register R0-R1.
|
;; Extended precision register R0-R1.
|
|
|
(define_predicate "r0r1_reg_operand"
|
(define_predicate "r0r1_reg_operand"
|
(match_code "reg,subreg")
|
(match_code "reg,subreg")
|
{
|
{
|
if (! reg_operand (op, mode))
|
if (! reg_operand (op, mode))
|
return 0;
|
return 0;
|
if (GET_CODE (op) == SUBREG)
|
if (GET_CODE (op) == SUBREG)
|
op = SUBREG_REG (op);
|
op = SUBREG_REG (op);
|
return REG_P (op) && IS_R0R1_OR_PSEUDO_REG (op);
|
return REG_P (op) && IS_R0R1_OR_PSEUDO_REG (op);
|
})
|
})
|
|
|
;; Extended precision register R2-R3.
|
;; Extended precision register R2-R3.
|
|
|
(define_predicate "r2r3_reg_operand"
|
(define_predicate "r2r3_reg_operand"
|
(match_code "reg,subreg")
|
(match_code "reg,subreg")
|
{
|
{
|
if (! reg_operand (op, mode))
|
if (! reg_operand (op, mode))
|
return 0;
|
return 0;
|
if (GET_CODE (op) == SUBREG)
|
if (GET_CODE (op) == SUBREG)
|
op = SUBREG_REG (op);
|
op = SUBREG_REG (op);
|
return REG_P (op) && IS_R2R3_OR_PSEUDO_REG (op);
|
return REG_P (op) && IS_R2R3_OR_PSEUDO_REG (op);
|
})
|
})
|
|
|
;; Low extended precision register R0-R7.
|
;; Low extended precision register R0-R7.
|
|
|
(define_predicate "ext_low_reg_operand"
|
(define_predicate "ext_low_reg_operand"
|
(match_code "reg,subreg")
|
(match_code "reg,subreg")
|
{
|
{
|
if (! reg_operand (op, mode))
|
if (! reg_operand (op, mode))
|
return 0;
|
return 0;
|
if (GET_CODE (op) == SUBREG)
|
if (GET_CODE (op) == SUBREG)
|
op = SUBREG_REG (op);
|
op = SUBREG_REG (op);
|
return REG_P (op) && IS_EXT_LOW_OR_PSEUDO_REG (op);
|
return REG_P (op) && IS_EXT_LOW_OR_PSEUDO_REG (op);
|
})
|
})
|
|
|
;; Extended precision register.
|
;; Extended precision register.
|
|
|
(define_predicate "ext_reg_operand"
|
(define_predicate "ext_reg_operand"
|
(match_code "reg,subreg")
|
(match_code "reg,subreg")
|
{
|
{
|
if (! reg_operand (op, mode))
|
if (! reg_operand (op, mode))
|
return 0;
|
return 0;
|
if (GET_CODE (op) == SUBREG)
|
if (GET_CODE (op) == SUBREG)
|
op = SUBREG_REG (op);
|
op = SUBREG_REG (op);
|
if (! REG_P (op))
|
if (! REG_P (op))
|
return 0;
|
return 0;
|
return IS_EXT_OR_PSEUDO_REG (op);
|
return IS_EXT_OR_PSEUDO_REG (op);
|
})
|
})
|
|
|
;; Standard precision register.
|
;; Standard precision register.
|
|
|
(define_predicate "std_reg_operand"
|
(define_predicate "std_reg_operand"
|
(match_code "reg,subreg")
|
(match_code "reg,subreg")
|
{
|
{
|
if (! reg_operand (op, mode))
|
if (! reg_operand (op, mode))
|
return 0;
|
return 0;
|
if (GET_CODE (op) == SUBREG)
|
if (GET_CODE (op) == SUBREG)
|
op = SUBREG_REG (op);
|
op = SUBREG_REG (op);
|
return REG_P (op) && IS_STD_OR_PSEUDO_REG (op);
|
return REG_P (op) && IS_STD_OR_PSEUDO_REG (op);
|
})
|
})
|
|
|
;; Standard precision or normal register.
|
;; Standard precision or normal register.
|
|
|
(define_predicate "std_or_reg_operand"
|
(define_predicate "std_or_reg_operand"
|
(match_code "reg,subreg")
|
(match_code "reg,subreg")
|
{
|
{
|
if (reload_in_progress)
|
if (reload_in_progress)
|
return std_reg_operand (op, mode);
|
return std_reg_operand (op, mode);
|
return reg_operand (op, mode);
|
return reg_operand (op, mode);
|
})
|
})
|
|
|
;; Address register.
|
;; Address register.
|
|
|
(define_predicate "addr_reg_operand"
|
(define_predicate "addr_reg_operand"
|
(match_code "reg,subreg")
|
(match_code "reg,subreg")
|
{
|
{
|
if (! reg_operand (op, mode))
|
if (! reg_operand (op, mode))
|
return 0;
|
return 0;
|
return c4x_a_register (op);
|
return c4x_a_register (op);
|
})
|
})
|
|
|
;; Index register.
|
;; Index register.
|
|
|
(define_predicate "index_reg_operand"
|
(define_predicate "index_reg_operand"
|
(match_code "reg,subreg")
|
(match_code "reg,subreg")
|
{
|
{
|
if (! reg_operand (op, mode))
|
if (! reg_operand (op, mode))
|
return 0;
|
return 0;
|
if (GET_CODE (op) == SUBREG)
|
if (GET_CODE (op) == SUBREG)
|
op = SUBREG_REG (op);
|
op = SUBREG_REG (op);
|
return c4x_x_register (op);
|
return c4x_x_register (op);
|
})
|
})
|
|
|
;; DP register.
|
;; DP register.
|
|
|
(define_predicate "dp_reg_operand"
|
(define_predicate "dp_reg_operand"
|
(match_code "reg")
|
(match_code "reg")
|
{
|
{
|
return REG_P (op) && IS_DP_OR_PSEUDO_REG (op);
|
return REG_P (op) && IS_DP_OR_PSEUDO_REG (op);
|
})
|
})
|
|
|
;; SP register.
|
;; SP register.
|
|
|
(define_predicate "sp_reg_operand"
|
(define_predicate "sp_reg_operand"
|
(match_code "reg")
|
(match_code "reg")
|
{
|
{
|
return REG_P (op) && IS_SP_OR_PSEUDO_REG (op);
|
return REG_P (op) && IS_SP_OR_PSEUDO_REG (op);
|
})
|
})
|
|
|
;; ST register.
|
;; ST register.
|
|
|
(define_predicate "st_reg_operand"
|
(define_predicate "st_reg_operand"
|
(match_code "reg")
|
(match_code "reg")
|
{
|
{
|
return REG_P (op) && IS_ST_OR_PSEUDO_REG (op);
|
return REG_P (op) && IS_ST_OR_PSEUDO_REG (op);
|
})
|
})
|
|
|
;; RC register.
|
;; RC register.
|
|
|
(define_predicate "rc_reg_operand"
|
(define_predicate "rc_reg_operand"
|
(match_code "reg")
|
(match_code "reg")
|
{
|
{
|
return REG_P (op) && IS_RC_OR_PSEUDO_REG (op);
|
return REG_P (op) && IS_RC_OR_PSEUDO_REG (op);
|
})
|
})
|
|
|
;; TODO: Add a comment here.
|
;; TODO: Add a comment here.
|
|
|
(define_predicate "call_address_operand"
|
(define_predicate "call_address_operand"
|
(match_code "reg,symbol_ref,label_ref,const")
|
(match_code "reg,symbol_ref,label_ref,const")
|
{
|
{
|
return (REG_P (op) || symbolic_address_operand (op, mode));
|
return (REG_P (op) || symbolic_address_operand (op, mode));
|
})
|
})
|
|
|
;; Check dst operand of a move instruction.
|
;; Check dst operand of a move instruction.
|
|
|
(define_predicate "dst_operand"
|
(define_predicate "dst_operand"
|
(match_code "subreg,reg,mem")
|
(match_code "subreg,reg,mem")
|
{
|
{
|
if (GET_CODE (op) == SUBREG
|
if (GET_CODE (op) == SUBREG
|
&& mixed_subreg_operand (op, mode))
|
&& mixed_subreg_operand (op, mode))
|
return 0;
|
return 0;
|
|
|
if (REG_P (op))
|
if (REG_P (op))
|
return reg_operand (op, mode);
|
return reg_operand (op, mode);
|
|
|
return nonimmediate_operand (op, mode);
|
return nonimmediate_operand (op, mode);
|
})
|
})
|
|
|
;; Check src operand of two operand arithmetic instructions.
|
;; Check src operand of two operand arithmetic instructions.
|
|
|
(define_predicate "src_operand"
|
(define_predicate "src_operand"
|
(match_code "subreg,reg,mem,const_int,const_double")
|
(match_code "subreg,reg,mem,const_int,const_double")
|
{
|
{
|
if (GET_CODE (op) == SUBREG
|
if (GET_CODE (op) == SUBREG
|
&& mixed_subreg_operand (op, mode))
|
&& mixed_subreg_operand (op, mode))
|
return 0;
|
return 0;
|
|
|
if (REG_P (op))
|
if (REG_P (op))
|
return reg_operand (op, mode);
|
return reg_operand (op, mode);
|
|
|
if (mode == VOIDmode)
|
if (mode == VOIDmode)
|
mode = GET_MODE (op);
|
mode = GET_MODE (op);
|
|
|
if (GET_CODE (op) == CONST_INT)
|
if (GET_CODE (op) == CONST_INT)
|
return (mode == QImode || mode == Pmode || mode == HImode)
|
return (mode == QImode || mode == Pmode || mode == HImode)
|
&& c4x_I_constant (op);
|
&& c4x_I_constant (op);
|
|
|
/* We don't like CONST_DOUBLE integers. */
|
/* We don't like CONST_DOUBLE integers. */
|
if (GET_CODE (op) == CONST_DOUBLE)
|
if (GET_CODE (op) == CONST_DOUBLE)
|
return c4x_H_constant (op);
|
return c4x_H_constant (op);
|
|
|
/* Disallow symbolic addresses. Only the predicate
|
/* Disallow symbolic addresses. Only the predicate
|
symbolic_address_operand will match these. */
|
symbolic_address_operand will match these. */
|
if (GET_CODE (op) == SYMBOL_REF
|
if (GET_CODE (op) == SYMBOL_REF
|
|| GET_CODE (op) == LABEL_REF
|
|| GET_CODE (op) == LABEL_REF
|
|| GET_CODE (op) == CONST)
|
|| GET_CODE (op) == CONST)
|
return 0;
|
return 0;
|
|
|
/* If TARGET_LOAD_DIRECT_MEMS is nonzero, disallow direct memory
|
/* If TARGET_LOAD_DIRECT_MEMS is nonzero, disallow direct memory
|
access to symbolic addresses. These operands will get forced
|
access to symbolic addresses. These operands will get forced
|
into a register and the movqi expander will generate a
|
into a register and the movqi expander will generate a
|
HIGH/LO_SUM pair if TARGET_EXPOSE_LDP is nonzero. */
|
HIGH/LO_SUM pair if TARGET_EXPOSE_LDP is nonzero. */
|
if (GET_CODE (op) == MEM
|
if (GET_CODE (op) == MEM
|
&& ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
|
&& ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
|
|| GET_CODE (XEXP (op, 0)) == LABEL_REF
|
|| GET_CODE (XEXP (op, 0)) == LABEL_REF
|
|| GET_CODE (XEXP (op, 0)) == CONST)))
|
|| GET_CODE (XEXP (op, 0)) == CONST)))
|
return !TARGET_EXPOSE_LDP &&
|
return !TARGET_EXPOSE_LDP &&
|
! TARGET_LOAD_DIRECT_MEMS && GET_MODE (op) == mode;
|
! TARGET_LOAD_DIRECT_MEMS && GET_MODE (op) == mode;
|
|
|
return general_operand (op, mode);
|
return general_operand (op, mode);
|
})
|
})
|
|
|
;; TODO: Add a comment here.
|
;; TODO: Add a comment here.
|
|
|
(define_predicate "src_hi_operand"
|
(define_predicate "src_hi_operand"
|
(match_code "subreg,reg,mem,const_double")
|
(match_code "subreg,reg,mem,const_double")
|
{
|
{
|
if (c4x_O_constant (op))
|
if (c4x_O_constant (op))
|
return 1;
|
return 1;
|
return src_operand (op, mode);
|
return src_operand (op, mode);
|
})
|
})
|
|
|
;; Check src operand of two operand logical instructions.
|
;; Check src operand of two operand logical instructions.
|
|
|
(define_predicate "lsrc_operand"
|
(define_predicate "lsrc_operand"
|
(match_code "subreg,reg,mem,const_int,const_double")
|
(match_code "subreg,reg,mem,const_int,const_double")
|
{
|
{
|
if (mode == VOIDmode)
|
if (mode == VOIDmode)
|
mode = GET_MODE (op);
|
mode = GET_MODE (op);
|
|
|
if (mode != QImode && mode != Pmode)
|
if (mode != QImode && mode != Pmode)
|
fatal_insn ("mode not QImode", op);
|
fatal_insn ("mode not QImode", op);
|
|
|
if (GET_CODE (op) == CONST_INT)
|
if (GET_CODE (op) == CONST_INT)
|
return c4x_L_constant (op) || c4x_J_constant (op);
|
return c4x_L_constant (op) || c4x_J_constant (op);
|
|
|
return src_operand (op, mode);
|
return src_operand (op, mode);
|
})
|
})
|
|
|
;; Check src operand of two operand tricky instructions.
|
;; Check src operand of two operand tricky instructions.
|
|
|
(define_predicate "tsrc_operand"
|
(define_predicate "tsrc_operand"
|
(match_code "subreg,reg,mem,const_int,const_double")
|
(match_code "subreg,reg,mem,const_int,const_double")
|
{
|
{
|
if (mode == VOIDmode)
|
if (mode == VOIDmode)
|
mode = GET_MODE (op);
|
mode = GET_MODE (op);
|
|
|
if (mode != QImode && mode != Pmode)
|
if (mode != QImode && mode != Pmode)
|
fatal_insn ("mode not QImode", op);
|
fatal_insn ("mode not QImode", op);
|
|
|
if (GET_CODE (op) == CONST_INT)
|
if (GET_CODE (op) == CONST_INT)
|
return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op);
|
return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op);
|
|
|
return src_operand (op, mode);
|
return src_operand (op, mode);
|
})
|
})
|
|
|
;; Check src operand of two operand non immediate instructions.
|
;; Check src operand of two operand non immediate instructions.
|
|
|
(define_predicate "nonimmediate_src_operand"
|
(define_predicate "nonimmediate_src_operand"
|
(match_code "subreg,reg,mem")
|
(match_code "subreg,reg,mem")
|
{
|
{
|
if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
|
if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
|
return 0;
|
return 0;
|
|
|
return src_operand (op, mode);
|
return src_operand (op, mode);
|
})
|
})
|
|
|
;; Check logical src operand of two operand non immediate instructions.
|
;; Check logical src operand of two operand non immediate instructions.
|
|
|
(define_predicate "nonimmediate_lsrc_operand"
|
(define_predicate "nonimmediate_lsrc_operand"
|
(match_code "subreg,reg,mem")
|
(match_code "subreg,reg,mem")
|
{
|
{
|
if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
|
if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
|
return 0;
|
return 0;
|
|
|
return lsrc_operand (op, mode);
|
return lsrc_operand (op, mode);
|
})
|
})
|
|
|
;; Match any operand.
|
;; Match any operand.
|
|
|
(define_predicate "any_operand"
|
(define_predicate "any_operand"
|
(match_code "subreg,reg,mem,const_int,const_double")
|
(match_code "subreg,reg,mem,const_int,const_double")
|
{
|
{
|
return 1;
|
return 1;
|
})
|
})
|
|
|
;; Check for indirect operands allowable in parallel instruction.
|
;; Check for indirect operands allowable in parallel instruction.
|
|
|
(define_predicate "par_ind_operand"
|
(define_predicate "par_ind_operand"
|
(match_code "mem")
|
(match_code "mem")
|
{
|
{
|
if (mode != VOIDmode && mode != GET_MODE (op))
|
if (mode != VOIDmode && mode != GET_MODE (op))
|
return 0;
|
return 0;
|
|
|
return c4x_S_indirect (op);
|
return c4x_S_indirect (op);
|
})
|
})
|
|
|
;; Check for operands allowable in parallel instruction.
|
;; Check for operands allowable in parallel instruction.
|
|
|
(define_predicate "parallel_operand"
|
(define_predicate "parallel_operand"
|
(match_code "subreg,reg,mem")
|
(match_code "subreg,reg,mem")
|
{
|
{
|
return ext_low_reg_operand (op, mode) || par_ind_operand (op, mode);
|
return ext_low_reg_operand (op, mode) || par_ind_operand (op, mode);
|
})
|
})
|
|
|
;; Symbolic address operand.
|
;; Symbolic address operand.
|
|
|
(define_predicate "symbolic_address_operand"
|
(define_predicate "symbolic_address_operand"
|
(match_code "symbol_ref,label_ref,const")
|
(match_code "symbol_ref,label_ref,const")
|
{
|
{
|
switch (GET_CODE (op))
|
switch (GET_CODE (op))
|
{
|
{
|
case CONST:
|
case CONST:
|
case SYMBOL_REF:
|
case SYMBOL_REF:
|
case LABEL_REF:
|
case LABEL_REF:
|
return 1;
|
return 1;
|
default:
|
default:
|
return 0;
|
return 0;
|
}
|
}
|
})
|
})
|
|
|