From 22a14e0dccd8e24ace4f1c617e47c96d2d69bba6 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Fri, 18 Mar 2005 18:05:54 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 28 +++ gcc/config/m32r/m32r-protos.h | 24 +- gcc/config/m32r/m32r.c | 430 +-------------------------------- gcc/config/m32r/m32r.h | 45 +--- gcc/config/m32r/m32r.md | 2 + gcc/config/m32r/predicates.md | 442 ++++++++++++++++++++++++++++++++++ 6 files changed, 483 insertions(+), 488 deletions(-) create mode 100644 gcc/config/m32r/predicates.md diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2dc5a406d30..6adc260cdf6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2005-03-18 2005-03-18 Kazu Hirata + + * 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 * hooks.c, hooks.h, intl.c, opts.h, prefix.c, tree-gimple.c, diff --git a/gcc/config/m32r/m32r-protos.h b/gcc/config/m32r/m32r-protos.h index 2ea6a59ab0d..0f72bd7521f 100644 --- a/gcc/config/m32r/m32r-protos.h +++ b/gcc/config/m32r/m32r-protos.h @@ -1,5 +1,5 @@ /* 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 */ diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index 170c4c67b4c..dd86186d56d 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -1,6 +1,6 @@ /* 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 diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h index 2ebda2a6e60..82c15644669 100644 --- a/gcc/config/m32r/m32r.h +++ b/gcc/config/m32r/m32r.h @@ -1,6 +1,6 @@ /* 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 diff --git a/gcc/config/m32r/m32r.md b/gcc/config/m32r/m32r.md index 80c579d395c..6b799709dba 100644 --- a/gcc/config/m32r/m32r.md +++ b/gcc/config/m32r/m32r.md @@ -199,6 +199,8 @@ "long_IF,long_E,memory*2") +(include "predicates.md") + ;; Expand prologue as RTL (define_expand "prologue" [(const_int 1)] diff --git a/gcc/config/m32r/predicates.md b/gcc/config/m32r/predicates.md new file mode 100644 index 00000000000..d8561d69e89 --- /dev/null +++ b/gcc/config/m32r/predicates.md @@ -0,0 +1,442 @@ +;; 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; +}) -- 2.30.2