From 68a813322bd01742d80aed81cd3ed013b054499b Mon Sep 17 00:00:00 2001 From: Hans-Peter Nilsson Date: Wed, 20 Apr 2005 22:31:30 +0000 Subject: [PATCH] predicates.md: New file. * config/cris/predicates.md: New file. * config/cris/cris-protos.h (cris_store_multiple_op_p) (cris_movem_load_rest_p): Declare. * config/cris/cris.c (cris_store_multiple_op): Return bool, not int. (cris_movem_load_rest_p): Ditto. Globalize. (cris_bdap_operand, cris_bdap_biap_operand, cris_orthogonal_operator, cris_commutative_orth_op, cris_operand_extend_operator, cris_additive_operand_extend_operator, cris_extend_operator, cris_plus_or_bound_operator, cris_mem_op, cris_general_operand_or_symbol, cris_general_operand_or_gotless_symbol, cris_general_operand_or_plt_symbol, cris_mem_call_operand, cris_load_multiple_op): Remove predicate functions. (cris_symbol, cris_gotless_symbol) : Return 0, don't abort, for UNSPECs other than CRIS_UNSPEC_PLT. * config/cris/cris.h (PREDICATE_CODES): Don't define. * config/cris/cris.md: Include predicates.md. ("call", "call_value"): Generate CONSTs of Pmode, not VOIDmode. From-SVN: r98471 --- gcc/ChangeLog | 22 +++ gcc/config/cris/cris-protos.h | 2 + gcc/config/cris/cris.c | 320 +++--------------------------------------- gcc/config/cris/cris.h | 38 ----- gcc/config/cris/cris.md | 8 +- gcc/config/cris/predicates.md | 170 ++++++++++++++++++++++ 6 files changed, 221 insertions(+), 339 deletions(-) create mode 100644 gcc/config/cris/predicates.md diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4181cbeb8f3..89f57e8298d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2005-04-21 Hans-Peter Nilsson + + * config/cris/predicates.md: New file. + * config/cris/cris-protos.h (cris_store_multiple_op_p) + (cris_movem_load_rest_p): Declare. + * config/cris/cris.c (cris_store_multiple_op): Return bool, not int. + (cris_movem_load_rest_p): Ditto. Globalize. + (cris_bdap_operand, cris_bdap_biap_operand, + cris_orthogonal_operator, cris_commutative_orth_op, + cris_operand_extend_operator, + cris_additive_operand_extend_operator, cris_extend_operator, + cris_plus_or_bound_operator, cris_mem_op, + cris_general_operand_or_symbol, + cris_general_operand_or_gotless_symbol, + cris_general_operand_or_plt_symbol, cris_mem_call_operand, + cris_load_multiple_op): Remove predicate functions. + (cris_symbol, cris_gotless_symbol) : Return 0, don't + abort, for UNSPECs other than CRIS_UNSPEC_PLT. + * config/cris/cris.h (PREDICATE_CODES): Don't define. + * config/cris/cris.md: Include predicates.md. + ("call", "call_value"): Generate CONSTs of Pmode, not VOIDmode. + 2005-04-20 Ian Lance Taylor * c-common.def: Remove STMT_EXPR (moved to cp/cp-tree.def). diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h index 571f1795cd2..23911c0f130 100644 --- a/gcc/config/cris/cris-protos.h +++ b/gcc/config/cris/cris-protos.h @@ -41,6 +41,8 @@ extern int cris_legitimate_pic_operand (rtx); extern int cris_gotless_symbol (rtx); extern int cris_got_symbol (rtx); extern int cris_symbol (rtx); +extern bool cris_store_multiple_op_p (rtx); +extern bool cris_movem_load_rest_p (rtx, int); extern void cris_asm_output_symbol_ref (FILE *, rtx); extern bool cris_output_addr_const_extra (FILE *, rtx); extern int cris_cfun_uses_pic_table (void); diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index f7822d4b112..eb5047d54e0 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -120,8 +120,6 @@ static void cris_operand_lossage (const char *, rtx); static int cris_reg_saved_in_regsave_area (unsigned int, bool); -static int cris_movem_load_rest_p (rtx, int); - static void cris_asm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree); @@ -205,280 +203,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION; struct gcc_target targetm = TARGET_INITIALIZER; -/* Predicate functions. */ - -/* This checks a part of an address, the one that is not a plain register - for an addressing mode using BDAP. - Allowed operands is either: - a) a register - b) a CONST operand (but not a symbol when generating PIC) - c) a [r] or [r+] in SImode, or sign-extend from HI or QI. */ - -int -cris_bdap_operand (rtx op, enum machine_mode mode) -{ - register enum rtx_code code = GET_CODE (op); - - if (mode != SImode && (mode != VOIDmode || GET_MODE (op) != VOIDmode)) - return 0; - - /* Just return whether this is a simple register or constant. */ - if (register_operand (op, mode) - || (CONSTANT_P (op) && !(flag_pic && cris_symbol (op)))) - return 1; - - /* Is it a [r] or possibly a [r+]? */ - if (code == MEM) - { - rtx tem = XEXP (op, 0); - - if (mode == SImode - && (register_operand (tem, SImode) - || (GET_CODE (tem) == POST_INC - && register_operand (XEXP (tem, 0), SImode)))) - return 1; - else - return 0; - } - - /* Perhaps a sign-extended mem: [r].(b|w) or [r+].(b|w)? */ - if (code == SIGN_EXTEND) - { - rtx tem = XEXP (op, 0); - - if (GET_CODE (tem) != MEM) - return 0; - - tem = XEXP (tem, 0); - if (mode == SImode - && (register_operand (tem, SImode) - || (GET_CODE (tem) == POST_INC - && register_operand (XEXP (tem, 0), SImode)))) - return 1; - else - return 0; - } - - return 0; -} - -/* This is similar to cris_bdap_operand: - It checks a part of an address, the one that is not a plain register - for an addressing mode using BDAP *or* BIAP. - Allowed operands is either: - a) a register - b) a CONST operand (but not a symbol when generating PIC) - c) a mult of (1, 2 or 4) and a register - d) a [r] or [r+] in SImode, or sign-extend from HI or QI. */ - -int -cris_bdap_biap_operand (rtx op, enum machine_mode mode) -{ - register enum rtx_code code = GET_CODE (op); - rtx reg; - rtx val; - - /* Check for bdap operand. */ - if (cris_bdap_operand (op, mode)) - return 1; - - if (mode != SImode && (mode != VOIDmode || GET_MODE (op) != VOIDmode)) - return 0; - - /* Check that we're looking at a BIAP operand. */ - if (code != MULT) - return 0; - - /* Canonicalize register and multiplicand. */ - if (GET_CODE (XEXP (op, 0)) == CONST_INT) - { - val = XEXP (op, 0); - reg = XEXP (op, 1); - } - else - { - val = XEXP (op, 1); - reg = XEXP (op, 0); - } - - /* Check that the operands are correct after canonicalization. */ - if (! register_operand (reg, SImode) || GET_CODE (val) != CONST_INT) - return 0; - - /* Check that the multiplicand has a valid value. */ - if ((code == MULT - && (INTVAL (val) == 1 || INTVAL (val) == 2 || INTVAL (val) == 4))) - return 1; - - return 0; -} - -/* Check if MODE is same as mode for X, and X is PLUS, MINUS, IOR or - AND or UMIN. */ - -int -cris_orthogonal_operator (rtx x, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (x); - - if (mode == VOIDmode) - mode = GET_MODE (x); - - return (GET_MODE (x) == mode - && (code == PLUS || code == MINUS - || code == IOR || code == AND || code == UMIN)); -} - -/* Check if MODE is same as mode for X, and X is PLUS, IOR or AND or - UMIN. */ - -int -cris_commutative_orth_op (rtx x, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (x); - - if (mode == VOIDmode) - mode = GET_MODE (x); - - return (GET_MODE (x) == mode && - (code == PLUS - || code == IOR || code == AND || code == UMIN)); -} - -/* Check if MODE is same as mode for X, and X is PLUS or MINUS or UMIN. - By the name, you might think we should include MULT. We don't because - it doesn't accept the same addressing modes as the others (ony - registers) and there's also the problem of handling TARGET_MUL_BUG. */ - -int -cris_operand_extend_operator (rtx x, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (x); - - if (mode == VOIDmode) - mode = GET_MODE (x); - - return (GET_MODE (x) == mode - && (code == PLUS || code == MINUS || code == UMIN)); -} - -/* Check if MODE is same as mode for X, and X is PLUS or MINUS. */ - -int -cris_additive_operand_extend_operator (rtx x, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (x); - - if (mode == VOIDmode) - mode = GET_MODE (x); - - return (GET_MODE (x) == mode - && (code == PLUS || code == MINUS)); -} - -/* Check to see if MODE is same as mode for X, and X is SIGN_EXTEND or - ZERO_EXTEND. */ - -int -cris_extend_operator (rtx x, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (x); - - if (mode == VOIDmode) - mode = GET_MODE (x); - - return - (GET_MODE (x) == mode && (code == SIGN_EXTEND || code == ZERO_EXTEND)); -} - -/* Check to see if MODE is same as mode for X, and X is PLUS or BOUND. */ - -int -cris_plus_or_bound_operator (rtx x, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (x); - - if (mode == VOIDmode) - mode = GET_MODE (x); - - return - (GET_MODE (x) == mode && (code == UMIN || code == PLUS)); -} - -/* Used as an operator to get a handle on a already-known-valid MEM rtx:es - (no need to validate the address), where some address expression parts - have their own match_operand. */ - -int -cris_mem_op (rtx x, enum machine_mode mode) -{ - if (mode == VOIDmode) - mode = GET_MODE (x); - - return GET_MODE (x) == mode && GET_CODE (x) == MEM; -} - -/* Since with -fPIC, not all symbols are valid PIC symbols or indeed - general_operands, we have to have a predicate that matches it for the - "movsi" expander. */ - -int -cris_general_operand_or_symbol (rtx op, enum machine_mode mode) -{ - return general_operand (op, mode) - || (CONSTANT_P (op) && cris_symbol (op)); -} - -/* Since a PIC symbol without a GOT entry is not a general_operand, we - have to have a predicate that matches it. We use this in the expanded - "movsi" anonymous pattern. */ - -int -cris_general_operand_or_gotless_symbol (rtx op, enum machine_mode mode) -{ - return general_operand (op, mode) - || (GET_CODE (op) == UNSPEC && XINT (op, 1) == CRIS_UNSPEC_GOT) - || (CONSTANT_P (op) && cris_gotless_symbol (op)); -} - -/* Since a PLT symbol is not a general_operand, we have to have a - predicate that matches it when we need it. We use this in the expanded - "call" and "call_value" anonymous patterns. */ - -int -cris_general_operand_or_plt_symbol (rtx op, enum machine_mode mode) -{ - return general_operand (op, mode) - || (GET_CODE (op) == CONST - && GET_CODE (XEXP (op, 0)) == UNSPEC - && !TARGET_AVOID_GOTPLT); -} - -/* This matches a (MEM (general_operand)) or - (MEM (cris_general_operand_or_symbol)). The second one isn't a valid - memory_operand, so we need this predicate to recognize call - destinations before we change them to a PLT operand (by wrapping in - UNSPEC CRIS_UNSPEC_PLT). */ - -int -cris_mem_call_operand (rtx op, enum machine_mode mode) -{ - rtx xmem; - - if (GET_CODE (op) != MEM) - return 0; - - if (memory_operand (op, mode)) - return 1; - - xmem = XEXP (op, 0); - - return cris_general_operand_or_symbol (xmem, GET_MODE (op)); -} - /* Helper for cris_load_multiple_op and cris_ret_movem_op. */ -static int +bool cris_movem_load_rest_p (rtx op, int offs) { unsigned int reg_count = XVECLEN (op, 0) - offs; @@ -495,7 +222,7 @@ cris_movem_load_rest_p (rtx op, int offs) || GET_CODE (XVECEXP (op, 0, offs)) != SET || GET_CODE (SET_DEST (XVECEXP (op, 0, offs))) != REG || GET_CODE (SET_SRC (XVECEXP (op, 0, offs))) != MEM) - return 0; + return false; /* Check a possible post-inc indicator. */ if (GET_CODE (SET_SRC (XVECEXP (op, 0, offs + 1))) == PLUS) @@ -511,7 +238,7 @@ cris_movem_load_rest_p (rtx op, int offs) || REGNO (reg) != REGNO (SET_DEST (XVECEXP (op, 0, offs + 1))) || GET_CODE (inc) != CONST_INT || INTVAL (inc) != (HOST_WIDE_INT) reg_count * 4) - return 0; + return false; i = offs + 2; } else @@ -531,7 +258,7 @@ cris_movem_load_rest_p (rtx op, int offs) || GET_CODE (SET_SRC (elt)) != MEM || GET_MODE (SET_SRC (elt)) != SImode || !memory_address_p (SImode, src_addr)) - return 0; + return false; for (setno = 1; i < XVECLEN (op, 0); setno++, i++) { @@ -548,24 +275,17 @@ cris_movem_load_rest_p (rtx op, int offs) || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != setno * 4) - return 0; + return false; } - return 1; -} - -/* Predicate for the parallel contents in a movem from-memory. */ - -int -cris_load_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return cris_movem_load_rest_p (op, 0); + return true; } -/* Predicate for the parallel contents in a movem to-memory. */ +/* Worker function for predicate for the parallel contents in a movem + to-memory. */ -int -cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +bool +cris_store_multiple_op_p (rtx op) { int reg_count = XVECLEN (op, 0); rtx dest; @@ -581,18 +301,18 @@ cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) /* Perform a quick check so we don't blow up below. FIXME: Adjust for other than (MEM reg) and (MEM (PLUS reg const)). */ if (reg_count <= 1) - return 0; + return false; elt = XVECEXP (op, 0, 0); if (GET_CODE (elt) != SET) - return 0; + return false; dest = SET_DEST (elt); if (GET_CODE (SET_SRC (elt)) != REG || GET_CODE (dest) != MEM) - return 0; + return false; dest_addr = XEXP (dest, 0); @@ -620,7 +340,7 @@ cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) && REGNO (XEXP (dest_addr, 0)) == REGNO (reg) && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT && INTVAL (XEXP (dest_addr, 1)) == INTVAL (inc)))) - return 0; + return false; i = 2; } @@ -637,7 +357,7 @@ cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) || REGNO (SET_SRC (elt)) != (unsigned int) regno || GET_CODE (SET_DEST (elt)) != MEM || GET_MODE (SET_DEST (elt)) != SImode) - return 0; + return false; if (REG_P (dest_addr)) { @@ -652,7 +372,7 @@ cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) offset = INTVAL (XEXP (dest_addr, 1)); } else - return 0; + return false; for (setno = 1; i < XVECLEN (op, 0); setno++, i++) { @@ -669,10 +389,10 @@ cris_store_multiple_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_base) || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != setno * 4 + offset) - return 0; + return false; } - return 1; + return true; } /* The CONDITIONAL_REGISTER_USAGE worker. */ @@ -2176,7 +1896,7 @@ cris_symbol (rtx x) return 1; case UNSPEC: - if (XINT (x, 1) == CRIS_UNSPEC_GOT) + if (XINT (x, 1) == CRIS_UNSPEC_GOT || XINT (x, 1) != CRIS_UNSPEC_PLT) return 0; /* A PLT reference. */ ASSERT_PLT_UNSPEC (x); @@ -2218,6 +1938,8 @@ cris_gotless_symbol (rtx x) case UNSPEC: if (XINT (x, 1) == CRIS_UNSPEC_GOT) return 1; + if (XINT (x, 1) != CRIS_UNSPEC_PLT) + return 0; ASSERT_PLT_UNSPEC (x); return 1; diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h index 1b3a8f28755..0c169ecbf1d 100644 --- a/gcc/config/cris/cris.h +++ b/gcc/config/cris/cris.h @@ -1616,44 +1616,6 @@ struct cum_args {int regs;}; /* Node: Misc */ -/* FIXME: Check this one more time. */ -#define PREDICATE_CODES \ - {"cris_orthogonal_operator", \ - {PLUS, MINUS, IOR, AND, UMIN}}, \ - {"cris_commutative_orth_op", \ - {PLUS, IOR, AND, UMIN}}, \ - {"cris_operand_extend_operator", \ - {PLUS, MINUS, UMIN}}, \ - {"cris_additive_operand_extend_operator", \ - {PLUS, MINUS}}, \ - {"cris_extend_operator", \ - {ZERO_EXTEND, SIGN_EXTEND}}, \ - {"cris_plus_or_bound_operator", \ - {PLUS, UMIN}}, \ - {"cris_mem_op", \ - {MEM}}, \ - {"cris_load_multiple_op", \ - {PARALLEL}}, \ - {"cris_store_multiple_op", \ - {PARALLEL}}, \ - {"cris_bdap_operand", \ - {SUBREG, REG, LABEL_REF, SYMBOL_REF, MEM, CONST_INT, \ - CONST_DOUBLE, CONST, SIGN_EXTEND}}, \ - {"cris_bdap_biap_operand", \ - {SUBREG, REG, LABEL_REF, SYMBOL_REF, MEM, CONST_INT, \ - CONST_DOUBLE, CONST, SIGN_EXTEND, MULT}}, \ - {"cris_general_operand_or_gotless_symbol", \ - {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ - LABEL_REF, SUBREG, REG, MEM, UNSPEC}}, \ - {"cris_general_operand_or_symbol", \ - {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ - LABEL_REF, SUBREG, REG, MEM}}, \ - {"cris_general_operand_or_plt_symbol", \ - {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ - LABEL_REF, SUBREG, REG, MEM}}, \ - {"cris_mem_call_operand", \ - {MEM}}, - /* A combination of the bound (umin) insn together with a sign-extended add via the table to PC seems optimal. If the table overflows, the assembler will take care of it. diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md index d58e1dbfad6..c68cb8a0e5a 100644 --- a/gcc/config/cris/cris.md +++ b/gcc/config/cris/cris.md @@ -141,6 +141,10 @@ (define_delay (eq_attr "slottable" "has_slot") [(eq_attr "slottable" "yes") (nil) (nil)]) +;; Operand and operator predicates. + +(include "predicates.md") + ;; Test insns. ;; DImode @@ -3944,7 +3948,7 @@ for the symbol cause bad recombinatorial effects? */ op0 = force_reg (Pmode, gen_rtx_CONST - (VOIDmode, + (Pmode, gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, op0), CRIS_UNSPEC_PLT))); @@ -4009,7 +4013,7 @@ for the symbol cause bad recombinatorial effects? */ op1 = force_reg (Pmode, gen_rtx_CONST - (VOIDmode, + (Pmode, gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, op1), CRIS_UNSPEC_PLT))); diff --git a/gcc/config/cris/predicates.md b/gcc/config/cris/predicates.md new file mode 100644 index 00000000000..2d5ef19f02e --- /dev/null +++ b/gcc/config/cris/predicates.md @@ -0,0 +1,170 @@ +;; Operand and operator predicates for the GCC CRIS port. +;; 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. + + +;; Operator predicates. + +(define_predicate "cris_orthogonal_operator" + (match_code "plus, minus, ior, and, umin")) + +(define_predicate "cris_commutative_orth_op" + (match_code "plus, ior, and, umin")) + +;; By the name, you might think we should include MULT. We don't because +;; it doesn't accept the same addressing modes as the others (only +;; registers) and there's also the problem of handling TARGET_MUL_BUG. + +(define_predicate "cris_operand_extend_operator" + (match_code "plus, minus, umin")) + +(define_predicate "cris_additive_operand_extend_operator" + (match_code "plus, minus")) + +(define_predicate "cris_extend_operator" + (match_code "zero_extend, sign_extend")) + +(define_predicate "cris_plus_or_bound_operator" + (match_code "plus, umin")) + +;; Used as an operator to get a handle on a already-known-valid MEM rtx:es +;; (no need to validate the address), where some address expression parts +;; have their own match_operand. + +(define_predicate "cris_mem_op" + (match_code "mem")) + +(define_predicate "cris_load_multiple_op" + (and (match_code "parallel") + (match_test "cris_movem_load_rest_p (op, 0)"))) + +(define_predicate "cris_store_multiple_op" + (and (match_code "parallel") + (match_test "cris_store_multiple_op_p (op)"))) + + +;; Operand helper predicates. + +(define_predicate "cris_bdap_const_operand" + (and (match_code "label_ref, symbol_ref, const_int, const_double, const") + (not (and (match_test "flag_pic") + (match_test "cris_symbol (op)"))))) + +(define_predicate "cris_simple_address_operand" + (ior (match_operand:SI 0 "register_operand") + (and (match_code "post_inc") + (match_test "register_operand (XEXP (op, 0), Pmode)")))) + +(define_predicate "cris_simple_operand" + (ior (match_operand 0 "register_operand") + (and (match_code "mem") + (match_test "cris_simple_address_operand (XEXP (op, 0), + Pmode)")))) + +;; The caller needs to use :SI. +(define_predicate "cris_bdap_sign_extend_operand" + (and (match_code "sign_extend") + (and (match_test "MEM_P (XEXP (op, 0))") + (match_test "cris_simple_address_operand (XEXP (XEXP (op, 0), 0), + Pmode)")))) + +;; FIXME: Should not have to test for 1. +(define_predicate "cris_scale_int_operand" + (and (match_code "const_int") + (ior (ior (match_test "op == GEN_INT (4)") + (match_test "op == const2_rtx")) + (match_test "op == const1_rtx")))) + +;; FIXME: Should be able to assume (reg int). +(define_predicate "cris_biap_mult_operand" + (and (match_code "mult") + (ior (and (match_test "register_operand (XEXP (op, 0), Pmode)") + (match_test "cris_scale_int_operand (XEXP (op, 1), Pmode)")) + (and (match_test "cris_scale_int_operand (XEXP (op, 0), Pmode)") + (match_test "register_operand (XEXP (op, 1), Pmode)"))))) + + +;; Operand predicates. + +;; This checks a part of an address, the one that is not a plain register +;; for an addressing mode using BDAP. +;; Allowed operands are either: +;; a) a register +;; b) a CONST operand (but not a symbol when generating PIC) +;; c) a [r] or [r+] in SImode, or sign-extend from HI or QI. + +(define_predicate "cris_bdap_operand" + (ior (match_operand 0 "cris_bdap_const_operand") + (ior (match_operand:SI 0 "cris_simple_operand") + (match_operand:SI 0 "cris_bdap_sign_extend_operand")))) + +;; This is similar to cris_bdap_operand: +;; It checks a part of an address, the one that is not a plain register +;; for an addressing mode using BDAP or BIAP. +;; Allowed operands are either: +;; a) a register +;; b) a CONST operand (but not a symbol when generating PIC) +;; c) a mult of (1, 2 or 4) and a register +;; d) a [r] or [r+] in SImode, or sign-extend from HI or QI. */ + +(define_predicate "cris_bdap_biap_operand" + (ior (match_operand 0 "cris_bdap_operand") + (match_operand 0 "cris_biap_mult_operand"))) + +;; Since a PIC symbol without a GOT entry is not a general_operand, we +;; have to have a predicate that matches it. We use this in the expanded +;; "movsi" anonymous pattern. +;; FIXME: Can s/special_// when PR 20413 is fixed. + +(define_special_predicate "cris_general_operand_or_gotless_symbol" + (ior (match_operand 0 "general_operand") + (and (match_code "const, symbol_ref, label_ref, unspec") + (match_test "cris_gotless_symbol (op)")))) + +;; Since with -fPIC, not all symbols are valid PIC symbols or indeed +;; general_operands, we have to have a predicate that matches it for the +;; "movsi" expander. +;; FIXME: Can s/special_// when PR 20413 is fixed. + +(define_special_predicate "cris_general_operand_or_symbol" + (ior (match_operand 0 "general_operand") + (and (match_code "const, symbol_ref, label_ref") + (match_test "cris_symbol (op)")))) + +;; Since a PLT symbol is not a general_operand, we have to have a +;; predicate that matches it when we need it. We use this in the expanded +;; "call" and "call_value" anonymous patterns. + +(define_predicate "cris_general_operand_or_plt_symbol" + (ior (match_operand 0 "general_operand") + (and (match_code "const") + (and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC") + (not (match_test "TARGET_AVOID_GOTPLT")))))) + +;; This matches a (MEM (general_operand)) or +;; (MEM (cris_general_operand_or_symbol)). The second one isn't a valid +;; memory_operand, so we need this predicate to recognize call +;; destinations before we change them to a PLT operand (by wrapping in +;; UNSPEC CRIS_UNSPEC_PLT). + +(define_predicate "cris_mem_call_operand" + (and (match_code "mem") + (ior (match_operand 0 "memory_operand") + (match_test "cris_general_operand_or_symbol (XEXP (op, 0), + Pmode)")))) -- 2.11.4.GIT