Commit 22a14e0d by Kazu Hirata Committed by Nick Clifton

config/m32r/m32r-protos.h...

config/m32r/m32r-protos.h: Remove the prototypes for
	call_address_operand, symbolic_operand, seth_add3_operand,
	cmp_int16_operand, uint16_operand, reg_or_int16_operand,
	reg_or_uint16_operand, reg_or_cmp_int16_operand,
	two_insn_const_operand, move_src_operand,
	move_double_src_operand, move_dest_operand,
	eqne_comparison_operator, signed_comparison_operator,
	large_insn_p, conditional_move_operand, carry_compare_operand,
	m32r_block_immediate_operand, extend_operand,
	reg_or_eq_int16_operand, int8_operand, and
	reg_or_zero_operand.
* config/m32r/m32r.c (call_address_operand, symbolic_operand,
	seth_add3_operand, int8_operand, cmp_int16_operand,
	uint16_operand, reg_or_int16_operand, reg_or_uint16_operand,
	reg_or_eq_int16_operand, reg_or_cmp_int16_operand,
	reg_or_zero_operand, two_insn_const_operand, move_src_operand,
	move_double_src_operand, move_dest_operand,
	eqne_comparison_operator, signed_comparison_operator,
	extend_operand, small_insn_p, large_insn_p,
	conditional_move_operand, carry_compare_operand,
	m32r_block_immediate_operand): Move to predicates.md.
	(MAX_MOVE_BYTES): Move to m32r.h.
* config/m32r/m32r.h (PREDICATE_CODES): Remove.
* config/m32r/m32r.md: Include predicates.md.
* config/m32r/predicates.md: New.

From-SVN: r96691
parent 0a1948ed
2005-03-18 2005-03-18 Kazu Hirata <kazu@cs.umass.edu>
* config/m32r/m32r-protos.h: Remove the prototypes for
call_address_operand, symbolic_operand, seth_add3_operand,
cmp_int16_operand, uint16_operand, reg_or_int16_operand,
reg_or_uint16_operand, reg_or_cmp_int16_operand,
two_insn_const_operand, move_src_operand,
move_double_src_operand, move_dest_operand,
eqne_comparison_operator, signed_comparison_operator,
large_insn_p, conditional_move_operand, carry_compare_operand,
m32r_block_immediate_operand, extend_operand,
reg_or_eq_int16_operand, int8_operand, and
reg_or_zero_operand.
* config/m32r/m32r.c (call_address_operand, symbolic_operand,
seth_add3_operand, int8_operand, cmp_int16_operand,
uint16_operand, reg_or_int16_operand, reg_or_uint16_operand,
reg_or_eq_int16_operand, reg_or_cmp_int16_operand,
reg_or_zero_operand, two_insn_const_operand, move_src_operand,
move_double_src_operand, move_dest_operand,
eqne_comparison_operator, signed_comparison_operator,
extend_operand, small_insn_p, large_insn_p,
conditional_move_operand, carry_compare_operand,
m32r_block_immediate_operand): Move to predicates.md.
(MAX_MOVE_BYTES): Move to m32r.h.
* config/m32r/m32r.h (PREDICATE_CODES): Remove.
* config/m32r/m32r.md: Include predicates.md.
* config/m32r/predicates.md: New.
2005-03-18 Kazu Hirata <kazu@cs.umass.edu>
* hooks.c, hooks.h, intl.c, opts.h, prefix.c, tree-gimple.c,
......
/* Prototypes for m32r.c functions used in the md file & elsewhere.
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GCC.
......@@ -58,35 +58,13 @@ extern rtx m32r_return_addr (int);
extern rtx m32r_function_symbol (const char *);
#ifdef HAVE_MACHINE_MODES
extern int call_address_operand (rtx, Mmode);
extern int call_operand (rtx, Mmode);
extern int symbolic_operand (rtx, Mmode);
extern int small_data_operand (rtx, Mmode);
extern int addr24_operand (rtx, Mmode);
extern int addr32_operand (rtx, Mmode);
extern int call26_operand (rtx, Mmode);
extern int seth_add3_operand (rtx, Mmode);
extern int cmp_int16_operand (rtx, Mmode);
extern int uint16_operand (rtx, Mmode);
extern int reg_or_int16_operand (rtx, Mmode);
extern int reg_or_uint16_operand (rtx, Mmode);
extern int reg_or_cmp_int16_operand (rtx, Mmode);
extern int two_insn_const_operand (rtx, Mmode);
extern int move_src_operand (rtx, Mmode);
extern int move_double_src_operand (rtx, Mmode);
extern int move_dest_operand (rtx, Mmode);
extern int eqne_comparison_operator (rtx, Mmode);
extern int signed_comparison_operator (rtx, Mmode);
extern int memreg_operand (rtx, Mmode);
extern int small_insn_p (rtx, Mmode);
extern int large_insn_p (rtx, Mmode);
extern int conditional_move_operand (rtx, Mmode);
extern int carry_compare_operand (rtx, Mmode);
extern int m32r_block_immediate_operand (rtx, Mmode);
extern int extend_operand (rtx, Mmode);
extern int reg_or_eq_int16_operand (rtx, Mmode);
extern int int8_operand (rtx, Mmode);
extern int reg_or_zero_operand (rtx, Mmode);
#endif /* HAVE_MACHINE_MODES */
......
/* Subroutines used for code generation on the Renesas M32R cpu.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005 Free Software Foundation, Inc.
This file is part of GCC.
......@@ -472,17 +472,6 @@ m32r_init_expanders (void)
to make it easy to experiment. */
}
/* Acceptable arguments to the call insn. */
int
call_address_operand (rtx op, enum machine_mode mode)
{
return symbolic_operand (op, mode);
/* Constants and values in registers are not OK, because
the m32r BL instruction can only support PC relative branching. */
}
int
call_operand (rtx op, enum machine_mode mode)
{
......@@ -492,23 +481,6 @@ call_operand (rtx op, enum machine_mode mode)
return call_address_operand (op, mode);
}
/* Returns 1 if OP is a symbol reference. */
int
symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
switch (GET_CODE (op))
{
case SYMBOL_REF:
case LABEL_REF:
case CONST :
return 1;
default:
return 0;
}
}
/* Return 1 if OP is a reference to an object in .sdata/.sbss. */
int
......@@ -604,256 +576,6 @@ call26_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
return TARGET_CALL26;
}
/* Returns 1 if OP is an acceptable operand for seth/add3. */
int
seth_add3_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (flag_pic)
return 0;
if (GET_CODE (op) == SYMBOL_REF
|| GET_CODE (op) == LABEL_REF)
return 1;
if (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
&& GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
&& INT16_P (INTVAL (XEXP (XEXP (op, 0), 1))))
return 1;
return 0;
}
/* Return true if OP is a signed 8 bit immediate value. */
int
int8_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) != CONST_INT)
return 0;
return INT8_P (INTVAL (op));
}
/* Return true if OP is a signed 16 bit immediate value
useful in comparisons. */
int
cmp_int16_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) != CONST_INT)
return 0;
return CMP_INT16_P (INTVAL (op));
}
/* Return true if OP is an unsigned 16 bit immediate value. */
int
uint16_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) != CONST_INT)
return 0;
return UINT16_P (INTVAL (op));
}
/* Return true if OP is a register or signed 16 bit value. */
int
reg_or_int16_operand (rtx op, enum machine_mode mode)
{
if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
if (GET_CODE (op) != CONST_INT)
return 0;
return INT16_P (INTVAL (op));
}
/* Return true if OP is a register or an unsigned 16 bit value. */
int
reg_or_uint16_operand (rtx op, enum machine_mode mode)
{
if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
if (GET_CODE (op) != CONST_INT)
return 0;
return UINT16_P (INTVAL (op));
}
/* Return true if OP is a register or an integer value that can be
used is SEQ/SNE. We can use either XOR of the value or ADD of
the negative of the value for the constant. Don't allow 0,
because that is special cased. */
int
reg_or_eq_int16_operand (rtx op, enum machine_mode mode)
{
HOST_WIDE_INT value;
if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
if (GET_CODE (op) != CONST_INT)
return 0;
value = INTVAL (op);
return (value != 0) && (UINT16_P (value) || CMP_INT16_P (-value));
}
/* Return true if OP is a register or signed 16 bit value for compares. */
int
reg_or_cmp_int16_operand (rtx op, enum machine_mode mode)
{
if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
if (GET_CODE (op) != CONST_INT)
return 0;
return CMP_INT16_P (INTVAL (op));
}
/* Return true if OP is a register or the constant 0. */
int
reg_or_zero_operand (rtx op, enum machine_mode mode)
{
if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
if (GET_CODE (op) != CONST_INT)
return 0;
return INTVAL (op) == 0;
}
/* Return true if OP is a const_int requiring two instructions to load. */
int
two_insn_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) != CONST_INT)
return 0;
if (INT16_P (INTVAL (op))
|| UINT24_P (INTVAL (op))
|| UPPER16_P (INTVAL (op)))
return 0;
return 1;
}
/* Return true if OP is an acceptable argument for a single word
move source. */
int
move_src_operand (rtx op, enum machine_mode mode)
{
switch (GET_CODE (op))
{
case LABEL_REF :
case SYMBOL_REF :
case CONST :
return addr24_operand (op, mode);
case CONST_INT :
/* ??? We allow more cse opportunities if we only allow constants
loadable with one insn, and split the rest into two. The instances
where this would help should be rare and the current way is
simpler. */
if (HOST_BITS_PER_WIDE_INT > 32)
{
HOST_WIDE_INT rest = INTVAL (op) >> 31;
return (rest == 0 || rest == -1);
}
else
return 1;
case CONST_DOUBLE :
if (mode == SFmode)
return 1;
else if (mode == SImode)
{
/* Large unsigned constants are represented as const_double's. */
unsigned HOST_WIDE_INT low, high;
low = CONST_DOUBLE_LOW (op);
high = CONST_DOUBLE_HIGH (op);
return high == 0 && low <= (unsigned) 0xffffffff;
}
else
return 0;
case REG :
return register_operand (op, mode);
case SUBREG :
/* (subreg (mem ...) ...) can occur here if the inner part was once a
pseudo-reg and is now a stack slot. */
if (GET_CODE (SUBREG_REG (op)) == MEM)
return address_operand (XEXP (SUBREG_REG (op), 0), mode);
else
return register_operand (op, mode);
case MEM :
if (GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == PRE_DEC)
return 0; /* loads can't do pre-{inc,dec} */
return address_operand (XEXP (op, 0), mode);
default :
return 0;
}
}
/* Return true if OP is an acceptable argument for a double word
move source. */
int
move_double_src_operand (rtx op, enum machine_mode mode)
{
switch (GET_CODE (op))
{
case CONST_INT :
case CONST_DOUBLE :
return 1;
case REG :
return register_operand (op, mode);
case SUBREG :
/* (subreg (mem ...) ...) can occur here if the inner part was once a
pseudo-reg and is now a stack slot. */
if (GET_CODE (SUBREG_REG (op)) == MEM)
return move_double_src_operand (SUBREG_REG (op), mode);
else
return register_operand (op, mode);
case MEM :
/* Disallow auto inc/dec for now. */
if (GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == PRE_INC)
return 0;
return address_operand (XEXP (op, 0), mode);
default :
return 0;
}
}
/* Return true if OP is an acceptable argument for a move destination. */
int
move_dest_operand (rtx op, enum machine_mode mode)
{
switch (GET_CODE (op))
{
case REG :
return register_operand (op, mode);
case SUBREG :
/* (subreg (mem ...) ...) can occur here if the inner part was once a
pseudo-reg and is now a stack slot. */
if (GET_CODE (SUBREG_REG (op)) == MEM)
return address_operand (XEXP (SUBREG_REG (op), 0), mode);
else
return register_operand (op, mode);
case MEM :
if (GET_CODE (XEXP (op, 0)) == POST_INC)
return 0; /* stores can't do post inc */
return address_operand (XEXP (op, 0), mode);
default :
return 0;
}
}
/* Return 1 if OP is a DImode const we want to handle inline.
This must match the code in the movdi pattern.
It is used by the 'G' CONST_DOUBLE_OK_FOR_LETTER. */
......@@ -893,28 +615,6 @@ easy_df_const (rtx op)
return 0;
}
/* Return 1 if OP is an EQ or NE comparison operator. */
int
eqne_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
enum rtx_code code = GET_CODE (op);
return (code == EQ || code == NE);
}
/* Return 1 if OP is a signed comparison operator. */
int
signed_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
enum rtx_code code = GET_CODE (op);
return (COMPARISON_P (op)
&& (code == EQ || code == NE
|| code == LT || code == LE || code == GT || code == GE));
}
/* Return 1 if OP is (mem (reg ...)).
This is used in insn length calcs. */
......@@ -924,58 +624,6 @@ memreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG;
}
/* Return true if OP is an acceptable input argument for a zero/sign extend
operation. */
int
extend_operand (rtx op, enum machine_mode mode)
{
rtx addr;
switch (GET_CODE (op))
{
case REG :
case SUBREG :
return register_operand (op, mode);
case MEM :
addr = XEXP (op, 0);
if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
return 0; /* loads can't do pre inc/pre dec */
return address_operand (addr, mode);
default :
return 0;
}
}
/* Return nonzero if the operand is an insn that is a small insn.
Allow const_int 0 as well, which is a placeholder for NOP slots. */
int
small_insn_p (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
return 1;
if (! INSN_P (op))
return 0;
return get_attr_length (op) == 2;
}
/* Return nonzero if the operand is an insn that is a large insn. */
int
large_insn_p (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (! INSN_P (op))
return 0;
return get_attr_length (op) != 2;
}
/* Return nonzero if TYPE must be passed by indirect reference. */
static bool
......@@ -2424,59 +2072,6 @@ zero_and_one (rtx operand1, rtx operand2)
||((INTVAL (operand1) == 1) && (INTVAL (operand2) == 0)));
}
/* Return nonzero if the operand is suitable for use in a conditional move sequence. */
int
conditional_move_operand (rtx operand, enum machine_mode mode)
{
/* Only defined for simple integers so far... */
if (mode != SImode && mode != HImode && mode != QImode)
return FALSE;
/* At the moment we can handle moving registers and loading constants. */
/* To be added: Addition/subtraction/bitops/multiplication of registers. */
switch (GET_CODE (operand))
{
case REG:
return 1;
case CONST_INT:
return INT8_P (INTVAL (operand));
default:
#if 0
fprintf (stderr, "Test for cond move op of type: %s\n",
GET_RTX_NAME (GET_CODE (operand)));
#endif
return 0;
}
}
/* Return true if the code is a test of the carry bit. */
int
carry_compare_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
rtx x;
if (GET_MODE (op) != CCmode && GET_MODE (op) != VOIDmode)
return FALSE;
if (GET_CODE (op) != NE && GET_CODE (op) != EQ)
return FALSE;
x = XEXP (op, 0);
if (GET_CODE (x) != REG || REGNO (x) != CARRY_REGNUM)
return FALSE;
x = XEXP (op, 1);
if (GET_CODE (x) != CONST_INT || INTVAL (x) != 0)
return FALSE;
return TRUE;
}
/* Generate the correct assembler code to handle the conditional loading of a
value into a register. It is known that the operands satisfy the
conditional_move_operand() function above. The destination is operand[0].
......@@ -2583,13 +2178,6 @@ block_move_call (rtx dest_reg, rtx src_reg, rtx bytes_rtx)
TYPE_MODE (sizetype));
}
/* The maximum number of bytes to copy using pairs of load/store instructions.
If a block is larger than this then a loop will be generated to copy
MAX_MOVE_BYTES chunks at a time. The value of 32 is a semi-arbitrary choice.
A customer uses Dhrystome as their benchmark, and Dhrystone has a 31 byte
string copy in it. */
#define MAX_MOVE_BYTES 32
/* Expand string/block move operations.
operands[0] is the pointer to the destination.
......@@ -2836,20 +2424,6 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
}
}
/* Return true if op is an integer constant, less than or equal to
MAX_MOVE_BYTES. */
int
m32r_block_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) != CONST_INT
|| INTVAL (op) > MAX_MOVE_BYTES
|| INTVAL (op) <= 0)
return 0;
return 1;
}
/* Return true if using NEW_REG in place of OLD_REG is ok. */
int
......
/* Definitions of target machine for GNU compiler, Renesas M32R cpu.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005 Free Software Foundation, Inc.
This file is part of GCC.
......@@ -1740,38 +1740,9 @@ enum m32r_function_type
#define M32R_INTERRUPT_P(TYPE) ((TYPE) == M32R_FUNCTION_INTERRUPT)
/* Define this if you have defined special-purpose predicates in the
file `MACHINE.c'. This macro is called within an initializer of an
array of structures. The first field in the structure is the name
of a predicate and the second field is an array of rtl codes. For
each predicate, list all rtl codes that can be in expressions
matched by the predicate. The list should have a trailing comma. */
#define PREDICATE_CODES \
{ "reg_or_zero_operand", { REG, SUBREG, CONST_INT }}, \
{ "conditional_move_operand", { REG, SUBREG, CONST_INT }}, \
{ "carry_compare_operand", { EQ, NE }}, \
{ "eqne_comparison_operator", { EQ, NE }}, \
{ "signed_comparison_operator", { EQ, NE, LT, LE, GT, GE }}, \
{ "move_dest_operand", { REG, SUBREG, MEM }}, \
{ "move_src_operand", { REG, SUBREG, MEM, CONST_INT, \
CONST_DOUBLE, LABEL_REF, CONST, \
SYMBOL_REF }}, \
{ "move_double_src_operand", { REG, SUBREG, MEM, CONST_INT, \
CONST_DOUBLE }}, \
{ "two_insn_const_operand", { CONST_INT }}, \
{ "symbolic_operand", { SYMBOL_REF, LABEL_REF, CONST }}, \
{ "int8_operand", { CONST_INT }}, \
{ "uint16_operand", { CONST_INT }}, \
{ "reg_or_int16_operand", { REG, SUBREG, CONST_INT }}, \
{ "reg_or_uint16_operand", { REG, SUBREG, CONST_INT }}, \
{ "reg_or_cmp_int16_operand", { REG, SUBREG, CONST_INT }}, \
{ "reg_or_eq_int16_operand", { REG, SUBREG, CONST_INT }}, \
{ "cmp_int16_operand", { CONST_INT }}, \
{ "call_address_operand", { SYMBOL_REF, LABEL_REF, CONST }}, \
{ "extend_operand", { REG, SUBREG, MEM }}, \
{ "small_insn_p", { INSN, CALL_INSN, JUMP_INSN }}, \
{ "m32r_block_immediate_operand",{ CONST_INT }}, \
{ "large_insn_p", { INSN, CALL_INSN, JUMP_INSN }}, \
{ "seth_add3_operand", { SYMBOL_REF, LABEL_REF, CONST }},
/* The maximum number of bytes to copy using pairs of load/store instructions.
If a block is larger than this then a loop will be generated to copy
MAX_MOVE_BYTES chunks at a time. The value of 32 is a semi-arbitrary choice.
A customer uses Dhrystome as their benchmark, and Dhrystone has a 31 byte
string copy in it. */
#define MAX_MOVE_BYTES 32
......@@ -199,6 +199,8 @@
"long_IF,long_E,memory*2")
(include "predicates.md")
;; Expand prologue as RTL
(define_expand "prologue"
[(const_int 1)]
......
;; Predicate definitions for Renesas M32R.
;; 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 register or the constant 0.
(define_predicate "reg_or_zero_operand"
(match_code "reg,subreg,const_int")
{
if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
if (GET_CODE (op) != CONST_INT)
return 0;
return INTVAL (op) == 0;
})
;; Return nonzero if the operand is suitable for use in a conditional
;; move sequence.
(define_predicate "conditional_move_operand"
(match_code "reg,subreg,const_int")
{
/* Only defined for simple integers so far... */
if (mode != SImode && mode != HImode && mode != QImode)
return FALSE;
/* At the moment we can handle moving registers and loading constants. */
/* To be added: Addition/subtraction/bitops/multiplication of registers. */
switch (GET_CODE (op))
{
case REG:
return 1;
case CONST_INT:
return INT8_P (INTVAL (op));
default:
#if 0
fprintf (stderr, "Test for cond move op of type: %s\n",
GET_RTX_NAME (GET_CODE (op)));
#endif
return 0;
}
})
;; Return true if the code is a test of the carry bit.
(define_predicate "carry_compare_operand"
(match_code "eq,ne")
{
rtx x;
if (GET_MODE (op) != CCmode && GET_MODE (op) != VOIDmode)
return FALSE;
if (GET_CODE (op) != NE && GET_CODE (op) != EQ)
return FALSE;
x = XEXP (op, 0);
if (GET_CODE (x) != REG || REGNO (x) != CARRY_REGNUM)
return FALSE;
x = XEXP (op, 1);
if (GET_CODE (x) != CONST_INT || INTVAL (x) != 0)
return FALSE;
return TRUE;
})
;; Return 1 if OP is an EQ or NE comparison operator.
(define_predicate "eqne_comparison_operator"
(match_code "eq,ne")
{
enum rtx_code code = GET_CODE (op);
return (code == EQ || code == NE);
})
;; Return 1 if OP is a signed comparison operator.
(define_predicate "signed_comparison_operator"
(match_code "eq,ne,lt,le,gt,ge")
{
enum rtx_code code = GET_CODE (op);
return (COMPARISON_P (op)
&& (code == EQ || code == NE
|| code == LT || code == LE || code == GT || code == GE));
})
;; Return true if OP is an acceptable argument for a move destination.
(define_predicate "move_dest_operand"
(match_code "reg,subreg,mem")
{
switch (GET_CODE (op))
{
case REG :
return register_operand (op, mode);
case SUBREG :
/* (subreg (mem ...) ...) can occur here if the inner part was once a
pseudo-reg and is now a stack slot. */
if (GET_CODE (SUBREG_REG (op)) == MEM)
return address_operand (XEXP (SUBREG_REG (op), 0), mode);
else
return register_operand (op, mode);
case MEM :
if (GET_CODE (XEXP (op, 0)) == POST_INC)
return 0; /* stores can't do post inc */
return address_operand (XEXP (op, 0), mode);
default :
return 0;
}
})
;; Return true if OP is an acceptable argument for a single word move
;; source.
(define_predicate "move_src_operand"
(match_code "reg,subreg,mem,const_int,const_double,label_ref,const,symbol_ref")
{
switch (GET_CODE (op))
{
case LABEL_REF :
case SYMBOL_REF :
case CONST :
return addr24_operand (op, mode);
case CONST_INT :
/* ??? We allow more cse opportunities if we only allow constants
loadable with one insn, and split the rest into two. The instances
where this would help should be rare and the current way is
simpler. */
if (HOST_BITS_PER_WIDE_INT > 32)
{
HOST_WIDE_INT rest = INTVAL (op) >> 31;
return (rest == 0 || rest == -1);
}
else
return 1;
case CONST_DOUBLE :
if (mode == SFmode)
return 1;
else if (mode == SImode)
{
/* Large unsigned constants are represented as const_double's. */
unsigned HOST_WIDE_INT low, high;
low = CONST_DOUBLE_LOW (op);
high = CONST_DOUBLE_HIGH (op);
return high == 0 && low <= (unsigned) 0xffffffff;
}
else
return 0;
case REG :
return register_operand (op, mode);
case SUBREG :
/* (subreg (mem ...) ...) can occur here if the inner part was once a
pseudo-reg and is now a stack slot. */
if (GET_CODE (SUBREG_REG (op)) == MEM)
return address_operand (XEXP (SUBREG_REG (op), 0), mode);
else
return register_operand (op, mode);
case MEM :
if (GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == PRE_DEC)
return 0; /* loads can't do pre-{inc,dec} */
return address_operand (XEXP (op, 0), mode);
default :
return 0;
}
})
;; Return true if OP is an acceptable argument for a double word move
;; source.
(define_predicate "move_double_src_operand"
(match_code "reg,subreg,mem,const_int,const_double")
{
switch (GET_CODE (op))
{
case CONST_INT :
case CONST_DOUBLE :
return 1;
case REG :
return register_operand (op, mode);
case SUBREG :
/* (subreg (mem ...) ...) can occur here if the inner part was once a
pseudo-reg and is now a stack slot. */
if (GET_CODE (SUBREG_REG (op)) == MEM)
return move_double_src_operand (SUBREG_REG (op), mode);
else
return register_operand (op, mode);
case MEM :
/* Disallow auto inc/dec for now. */
if (GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == PRE_INC)
return 0;
return address_operand (XEXP (op, 0), mode);
default :
return 0;
}
})
;; Return true if OP is a const_int requiring two instructions to
;; load.
(define_predicate "two_insn_const_operand"
(match_code "const_int")
{
if (GET_CODE (op) != CONST_INT)
return 0;
if (INT16_P (INTVAL (op))
|| UINT24_P (INTVAL (op))
|| UPPER16_P (INTVAL (op)))
return 0;
return 1;
})
;; Returns 1 if OP is a symbol reference.
(define_predicate "symbolic_operand"
(match_code "symbol_ref,label_ref,const")
{
switch (GET_CODE (op))
{
case SYMBOL_REF:
case LABEL_REF:
case CONST :
return 1;
default:
return 0;
}
})
;; Return true if OP is a signed 8 bit immediate value.
(define_predicate "int8_operand"
(match_code "const_int")
{
if (GET_CODE (op) != CONST_INT)
return 0;
return INT8_P (INTVAL (op));
})
;; Return true if OP is an unsigned 16 bit immediate value.
(define_predicate "uint16_operand"
(match_code "const_int")
{
if (GET_CODE (op) != CONST_INT)
return 0;
return UINT16_P (INTVAL (op));
})
;; Return true if OP is a register or signed 16 bit value.
(define_predicate "reg_or_int16_operand"
(match_code "reg,subreg,const_int")
{
if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
if (GET_CODE (op) != CONST_INT)
return 0;
return INT16_P (INTVAL (op));
})
;; Return true if OP is a register or an unsigned 16 bit value.
(define_predicate "reg_or_uint16_operand"
(match_code "reg,subreg,const_int")
{
if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
if (GET_CODE (op) != CONST_INT)
return 0;
return UINT16_P (INTVAL (op));
})
;; Return true if OP is a register or signed 16 bit value for
;; compares.
(define_predicate "reg_or_cmp_int16_operand"
(match_code "reg,subreg,const_int")
{
if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
if (GET_CODE (op) != CONST_INT)
return 0;
return CMP_INT16_P (INTVAL (op));
})
;; Return true if OP is a register or an integer value that can be
;; used is SEQ/SNE. We can use either XOR of the value or ADD of the
;; negative of the value for the constant. Don't allow 0, because
;; that is special cased.
(define_predicate "reg_or_eq_int16_operand"
(match_code "reg,subreg,const_int")
{
HOST_WIDE_INT value;
if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
if (GET_CODE (op) != CONST_INT)
return 0;
value = INTVAL (op);
return (value != 0) && (UINT16_P (value) || CMP_INT16_P (-value));
})
;; Return true if OP is a signed 16 bit immediate value useful in
;; comparisons.
(define_predicate "cmp_int16_operand"
(match_code "const_int")
{
if (GET_CODE (op) != CONST_INT)
return 0;
return CMP_INT16_P (INTVAL (op));
})
;; Acceptable arguments to the call insn.
(define_predicate "call_address_operand"
(match_code "symbol_ref,label_ref,const")
{
return symbolic_operand (op, mode);
/* Constants and values in registers are not OK, because
the m32r BL instruction can only support PC relative branching. */
})
;; Return true if OP is an acceptable input argument for a zero/sign
;; extend operation.
(define_predicate "extend_operand"
(match_code "reg,subreg,mem")
{
rtx addr;
switch (GET_CODE (op))
{
case REG :
case SUBREG :
return register_operand (op, mode);
case MEM :
addr = XEXP (op, 0);
if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
return 0; /* loads can't do pre inc/pre dec */
return address_operand (addr, mode);
default :
return 0;
}
})
;; Return nonzero if the operand is an insn that is a small
;; insn. Allow const_int 0 as well, which is a placeholder for NOP
;; slots.
(define_predicate "small_insn_p"
(match_code "insn,call_insn,jump_insn")
{
if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
return 1;
if (! INSN_P (op))
return 0;
return get_attr_length (op) == 2;
})
;; Return true if op is an integer constant, less than or equal to
;; MAX_MOVE_BYTES.
(define_predicate "m32r_block_immediate_operand"
(match_code "const_int")
{
if (GET_CODE (op) != CONST_INT
|| INTVAL (op) > MAX_MOVE_BYTES
|| INTVAL (op) <= 0)
return 0;
return 1;
})
;; Return nonzero if the operand is an insn that is a large insn.
(define_predicate "large_insn_p"
(match_code "insn,call_insn,jump_insn")
{
if (! INSN_P (op))
return 0;
return get_attr_length (op) != 2;
})
;; Returns 1 if OP is an acceptable operand for seth/add3.
(define_predicate "seth_add3_operand"
(match_code "symbol_ref,label_ref,const")
{
if (flag_pic)
return 0;
if (GET_CODE (op) == SYMBOL_REF
|| GET_CODE (op) == LABEL_REF)
return 1;
if (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
&& GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
&& INT16_P (INTVAL (XEXP (XEXP (op, 0), 1))))
return 1;
return 0;
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment