diff options
author | Kazu Hirata <kazu@cs.umass.edu> | 2005-04-04 15:17:10 +0000 |
---|---|---|
committer | Kazu Hirata <kazu@gcc.gnu.org> | 2005-04-04 15:17:10 +0000 |
commit | 54d58eaf29ac5a8410666ff38187a0a76f3936f6 (patch) | |
tree | bd2f665d1032697c82edb7329eb15a5d6b8d22b5 /gcc/config/mcore | |
parent | 1f4ea8e5884a6b97b3545b7ab87a16d02b2ebdfd (diff) | |
download | gcc-54d58eaf29ac5a8410666ff38187a0a76f3936f6.zip gcc-54d58eaf29ac5a8410666ff38187a0a76f3936f6.tar.gz gcc-54d58eaf29ac5a8410666ff38187a0a76f3936f6.tar.bz2 |
mcore-protos.h: Remove the prototypes for mcore_arith_reg_operand...
* config/mcore/mcore-protos.h: Remove the prototypes for
mcore_arith_reg_operand, mcore_general_movsrc_operand,
mcore_general_movdst_operand, mcore_reload_operand,
mcore_arith_J_operand, mcore_arith_K_operand,
mcore_arith_K_operand_not_0, mcore_arith_M_operand,
mcore_arith_K_S_operand, mcore_arith_imm_operand,
mcore_arith_any_imm_operand, mcore_arith_O_operand,
mcore_literal_K_operand, mcore_addsub_operand,
mcore_compare_operand, mcore_load_multiple_operation,
mcore_store_multiple_operation, mcore_call_address_operand.
Add a prototype for const_ok_for_mcore.
* config/mcore/mcore.c (mcore_call_address_operand,
mcore_general_movsrc_operand, mcore_general_movdst_operand,
mcore_arith_reg_operand, mcore_reload_operand,
mcore_arith_J_operand, mcore_arith_K_operand,
mcore_arith_K_operand_not_0, mcore_arith_K_S_operand,
mcore_arith_M_operand, mcore_arith_imm_operand,
mcore_arith_any_imm_operand, mcore_arith_O_operand,
mcore_literal_K_operand, mcore_addsub_operand,
mcore_compare_operand, mcore_load_multiple_operation,
mcore_store_multiple_operation): Move to predicates.md.
(const_ok_for_mcore): Export.
* config/mcore/mcore.h (PREDICATE_CODES): Remove.
* config/mcore/mcore.md: Include predicates.md.
* config/mcore/predicates.md: New.
From-SVN: r97548
Diffstat (limited to 'gcc/config/mcore')
-rw-r--r-- | gcc/config/mcore/mcore-protos.h | 22 | ||||
-rw-r--r-- | gcc/config/mcore/mcore.c | 308 | ||||
-rw-r--r-- | gcc/config/mcore/mcore.h | 20 | ||||
-rw-r--r-- | gcc/config/mcore/mcore.md | 5 | ||||
-rw-r--r-- | gcc/config/mcore/predicates.md | 333 |
5 files changed, 340 insertions, 348 deletions
diff --git a/gcc/config/mcore/mcore-protos.h b/gcc/config/mcore/mcore-protos.h index b035e9b..625b80e 100644 --- a/gcc/config/mcore/mcore-protos.h +++ b/gcc/config/mcore/mcore-protos.h @@ -1,5 +1,5 @@ /* Prototypes for exported functions defined in mcore.c - Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Nick Clifton (nickc@redhat.com) This file is part of GCC. @@ -71,25 +71,7 @@ extern int mcore_arith_S_operand (rtx); #ifdef HAVE_MACHINE_MODES extern const char * mcore_output_move (rtx, rtx *, enum machine_mode); extern const char * mcore_output_movedouble (rtx *, enum machine_mode); -extern int mcore_arith_reg_operand (rtx, enum machine_mode); -extern int mcore_general_movsrc_operand (rtx, enum machine_mode); -extern int mcore_general_movdst_operand (rtx, enum machine_mode); -extern int mcore_reload_operand (rtx, enum machine_mode); -extern int mcore_arith_J_operand (rtx, enum machine_mode); -extern int mcore_arith_K_operand (rtx, enum machine_mode); -extern int mcore_arith_K_operand_not_0 (rtx, enum machine_mode); -extern int mcore_arith_M_operand (rtx, enum machine_mode); -extern int mcore_arith_K_S_operand (rtx, enum machine_mode); -extern int mcore_arith_imm_operand (rtx, enum machine_mode); -extern int mcore_arith_any_imm_operand (rtx, enum machine_mode); -extern int mcore_arith_O_operand (rtx, enum machine_mode); -extern int mcore_literal_K_operand (rtx, enum machine_mode); -extern int mcore_addsub_operand (rtx, enum machine_mode); -extern int mcore_compare_operand (rtx, enum machine_mode); -extern int mcore_load_multiple_operation (rtx, enum machine_mode); -extern int mcore_store_multiple_operation (rtx, enum machine_mode); -extern int mcore_call_address_operand (rtx, enum machine_mode); - +extern int const_ok_for_mcore (int); #ifdef TREE_CODE extern rtx mcore_function_arg (CUMULATIVE_ARGS, enum machine_mode, tree, int); #endif /* TREE_CODE */ diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index 65ed1ad..6816a80 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -118,7 +118,6 @@ cond_type; static void output_stack_adjust (int, int); static int calc_live_regs (int *); -static int const_ok_for_mcore (int); static int try_constant_tricks (long, int *, int *); static const char * output_inline_const (enum machine_mode, rtx *); static void layout_mcore_frame (struct mcore_frame *); @@ -655,12 +654,6 @@ mcore_symbolic_address_p (rtx x) } } -int -mcore_call_address_operand (rtx x, enum machine_mode mode) -{ - return register_operand (x, mode) || CONSTANT_P (x); -} - /* Functions to output assembly code for a function call. */ char * @@ -703,7 +696,7 @@ mcore_output_call (rtx operands[], int index) /* Can we load a constant with a single instruction ? */ -static int +int const_ok_for_mcore (int value) { if (value >= 0 && value <= 127) @@ -1403,120 +1396,6 @@ mcore_output_movedouble (rtx operands[], enum machine_mode mode ATTRIBUTE_UNUSED /* Predicates used by the templates. */ -/* Nonzero if OP can be source of a simple move operation. */ - -int -mcore_general_movsrc_operand (rtx op, enum machine_mode mode) -{ - /* Any (MEM LABEL_REF) is OK. That is a pc-relative load. */ - if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == LABEL_REF) - return 1; - - return general_operand (op, mode); -} - -/* Nonzero if OP can be destination of a simple move operation. */ - -int -mcore_general_movdst_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == REG && REGNO (op) == CC_REG) - return 0; - - return general_operand (op, mode); -} - -/* Nonzero if OP is a normal arithmetic register. */ - -int -mcore_arith_reg_operand (rtx op, enum machine_mode mode) -{ - if (! register_operand (op, mode)) - return 0; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) == REG) - return REGNO (op) != CC_REG; - - return 1; -} - -/* Nonzero if OP should be recognized during reload for an ixh/ixw - operand. See the ixh/ixw patterns. */ - -int -mcore_reload_operand (rtx op, enum machine_mode mode) -{ - if (mcore_arith_reg_operand (op, mode)) - return 1; - - if (! reload_in_progress) - return 0; - - return GET_CODE (op) == MEM; -} - -/* Nonzero if OP is a valid source operand for an arithmetic insn. */ - -int -mcore_arith_J_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op))) - return 1; - - return 0; -} - -/* Nonzero if OP is a valid source operand for an arithmetic insn. */ - -int -mcore_arith_K_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))) - return 1; - - return 0; -} - -/* Nonzero if OP is a valid source operand for a shift or rotate insn. */ - -int -mcore_arith_K_operand_not_0 (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if ( GET_CODE (op) == CONST_INT - && CONST_OK_FOR_K (INTVAL (op)) - && INTVAL (op) != 0) - return 1; - - return 0; -} - -int -mcore_arith_K_S_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONST_INT) - { - if (CONST_OK_FOR_K (INTVAL (op)) || CONST_OK_FOR_M (~INTVAL (op))) - return 1; - } - - return 0; -} - int mcore_arith_S_operand (rtx op) { @@ -1526,110 +1405,6 @@ mcore_arith_S_operand (rtx op) return 0; } -int -mcore_arith_M_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op))) - return 1; - - return 0; -} - -/* Nonzero if OP is a valid source operand for loading. */ - -int -mcore_arith_imm_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONST_INT && const_ok_for_mcore (INTVAL (op))) - return 1; - - return 0; -} - -int -mcore_arith_any_imm_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONST_INT) - return 1; - - return 0; -} - -/* Nonzero if OP is a valid source operand for a cmov with two consts +/- 1. */ - -int -mcore_arith_O_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_O (INTVAL (op))) - return 1; - - return 0; -} - -/* Nonzero if OP is a valid source operand for a btsti. */ - -int -mcore_literal_K_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))) - return 1; - - return 0; -} - -/* Nonzero if OP is a valid source operand for an add/sub insn. */ - -int -mcore_addsub_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONST_INT) - { - return 1; - - /* The following is removed because it precludes large constants from being - returned as valid source operands for and add/sub insn. While large - constants may not directly be used in an add/sub, they may if first loaded - into a register. Thus, this predicate should indicate that they are valid, - and the constraint in mcore.md should control whether an additional load to - register is needed. (see mcore.md, addsi). -- DAC 4/2/1998 */ - /* - if (CONST_OK_FOR_J(INTVAL(op)) || CONST_OK_FOR_L(INTVAL(op))) - return 1; - */ - } - - return 0; -} - -/* Nonzero if OP is a valid source operand for a compare operation. */ - -int -mcore_compare_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0) - return 1; - - return 0; -} - /* Expand insert bit field. BRC */ int @@ -1729,87 +1504,6 @@ mcore_expand_insv (rtx operands[]) return 1; } - -/* Return 1 if OP is a load multiple operation. It is known to be a - PARALLEL and the first section will be tested. */ - -int -mcore_load_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int count = XVECLEN (op, 0); - int dest_regno; - rtx src_addr; - int i; - - /* Perform a quick check so we don't blow up below. */ - if (count <= 1 - || GET_CODE (XVECEXP (op, 0, 0)) != SET - || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG - || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM) - return 0; - - dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0))); - src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0); - - for (i = 1; i < count; i++) - { - rtx elt = XVECEXP (op, 0, i); - - if (GET_CODE (elt) != SET - || GET_CODE (SET_DEST (elt)) != REG - || GET_MODE (SET_DEST (elt)) != SImode - || REGNO (SET_DEST (elt)) != (unsigned) (dest_regno + i) - || GET_CODE (SET_SRC (elt)) != MEM - || GET_MODE (SET_SRC (elt)) != SImode - || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS - || ! 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)) != i * 4) - return 0; - } - - return 1; -} - -/* Similar, but tests for store multiple. */ - -int -mcore_store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int count = XVECLEN (op, 0); - int src_regno; - rtx dest_addr; - int i; - - /* Perform a quick check so we don't blow up below. */ - if (count <= 1 - || GET_CODE (XVECEXP (op, 0, 0)) != SET - || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM - || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG) - return 0; - - src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0))); - dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0); - - for (i = 1; i < count; i++) - { - rtx elt = XVECEXP (op, 0, i); - - if (GET_CODE (elt) != SET - || GET_CODE (SET_SRC (elt)) != REG - || GET_MODE (SET_SRC (elt)) != SImode - || REGNO (SET_SRC (elt)) != (unsigned) (src_regno + i) - || GET_CODE (SET_DEST (elt)) != MEM - || GET_MODE (SET_DEST (elt)) != SImode - || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS - || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) - || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT - || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4) - return 0; - } - - return 1; -} /* ??? Block move stuff stolen from m88k. This code has not been verified for correctness. */ diff --git a/gcc/config/mcore/mcore.h b/gcc/config/mcore/mcore.h index 9ab7d13..837b592 100644 --- a/gcc/config/mcore/mcore.h +++ b/gcc/config/mcore/mcore.h @@ -1047,24 +1047,4 @@ extern long mcore_current_compilation_timestamp; #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \ ((CHAR)=='.' || (CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '!') -#define PREDICATE_CODES \ - { "mcore_arith_reg_operand", { REG, SUBREG }}, \ - { "mcore_general_movsrc_operand", { MEM, CONST_INT, REG, SUBREG, SYMBOL_REF, LABEL_REF }},\ - { "mcore_general_movdst_operand", { MEM, CONST_INT, REG, SUBREG }},\ - { "mcore_reload_operand", { MEM, REG, SUBREG }}, \ - { "mcore_arith_J_operand", { CONST_INT, REG, SUBREG }}, \ - { "mcore_arith_K_operand", { CONST_INT, REG, SUBREG }}, \ - { "mcore_arith_K_operand_not_0", { CONST_INT, REG, SUBREG }}, \ - { "mcore_arith_M_operand", { CONST_INT, REG, SUBREG }}, \ - { "mcore_arith_K_S_operand", { CONST_INT, REG, SUBREG }}, \ - { "mcore_arith_O_operand", { CONST_INT, REG, SUBREG }}, \ - { "mcore_arith_imm_operand", { CONST_INT, REG, SUBREG }}, \ - { "mcore_arith_any_imm_operand", { CONST_INT, REG, SUBREG }}, \ - { "mcore_literal_K_operand", { CONST_INT }}, \ - { "mcore_addsub_operand", { CONST_INT, REG, SUBREG }}, \ - { "mcore_compare_operand", { CONST_INT, REG, SUBREG }}, \ - { "mcore_load_multiple_operation", { PARALLEL }}, \ - { "mcore_store_multiple_operation", { PARALLEL }}, \ - { "mcore_call_address_operand", { REG, SUBREG, CONST_INT, SYMBOL_REF }}, \ - #endif /* ! GCC_MCORE_H */ diff --git a/gcc/config/mcore/mcore.md b/gcc/config/mcore/mcore.md index ab3ce8a..5515874 100644 --- a/gcc/config/mcore/mcore.md +++ b/gcc/config/mcore/mcore.md @@ -1,5 +1,6 @@ ;; Machine description the Motorola MCore -;; Copyright (C) 1993, 1999, 2000, 2004 Free Software Foundation, Inc. +;; Copyright (C) 1993, 1999, 2000, 2004, 2005 +;; Free Software Foundation, Inc. ;; Contributed by Motorola. ;; This file is part of GCC. @@ -53,6 +54,8 @@ (eq_attr "type" "load") "nothing") +(include "predicates.md") + ;; ------------------------------------------------------------------------- ;; Test and bit test ;; ------------------------------------------------------------------------- diff --git a/gcc/config/mcore/predicates.md b/gcc/config/mcore/predicates.md new file mode 100644 index 0000000..5608903 --- /dev/null +++ b/gcc/config/mcore/predicates.md @@ -0,0 +1,333 @@ +;; Predicate definitions for FIXME FIXME. +;; Copyright (C) 2005 Free Software Foundation, Inc. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING. If not, write to +;; the Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;; Nonzero if OP is a normal arithmetic register. + +(define_predicate "mcore_arith_reg_operand" + (match_code "reg,subreg") +{ + if (! register_operand (op, mode)) + return 0; + + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (GET_CODE (op) == REG) + return REGNO (op) != CC_REG; + + return 1; +}) + +;; Nonzero if OP can be source of a simple move operation. + +(define_predicate "mcore_general_movsrc_operand" + (match_code "mem,const_int,reg,subreg,symbol_ref,label_ref") +{ + /* Any (MEM LABEL_REF) is OK. That is a pc-relative load. */ + if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == LABEL_REF) + return 1; + + return general_operand (op, mode); +}) + +;; Nonzero if OP can be destination of a simple move operation. + +(define_predicate "mcore_general_movdst_operand" + (match_code "mem,const_int,reg,subreg") +{ + if (GET_CODE (op) == REG && REGNO (op) == CC_REG) + return 0; + + return general_operand (op, mode); +}) + +;; Nonzero if OP should be recognized during reload for an ixh/ixw +;; operand. See the ixh/ixw patterns. + +(define_predicate "mcore_reload_operand" + (match_code "mem,reg,subreg") +{ + if (mcore_arith_reg_operand (op, mode)) + return 1; + + if (! reload_in_progress) + return 0; + + return GET_CODE (op) == MEM; +}) + +;; Nonzero if OP is a valid source operand for an arithmetic insn. + +(define_predicate "mcore_arith_J_operand" + (match_code "const_int,reg,subreg") +{ + if (register_operand (op, mode)) + return 1; + + if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op))) + return 1; + + return 0; +}) + +;; Nonzero if OP is a valid source operand for an arithmetic insn. + +(define_predicate "mcore_arith_K_operand" + (match_code "const_int,reg,subreg") +{ + if (register_operand (op, mode)) + return 1; + + if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))) + return 1; + + return 0; +}) + +;; Nonzero if OP is a valid source operand for a shift or rotate insn. + +(define_predicate "mcore_arith_K_operand_not_0" + (match_code "const_int,reg,subreg") +{ + if (register_operand (op, mode)) + return 1; + + if ( GET_CODE (op) == CONST_INT + && CONST_OK_FOR_K (INTVAL (op)) + && INTVAL (op) != 0) + return 1; + + return 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "mcore_arith_M_operand" + (match_code "const_int,reg,subreg") +{ + if (register_operand (op, mode)) + return 1; + + if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op))) + return 1; + + return 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "mcore_arith_K_S_operand" + (match_code "const_int,reg,subreg") +{ + if (register_operand (op, mode)) + return 1; + + if (GET_CODE (op) == CONST_INT) + { + if (CONST_OK_FOR_K (INTVAL (op)) || CONST_OK_FOR_M (~INTVAL (op))) + return 1; + } + + return 0; +}) + +;; Nonzero if OP is a valid source operand for a cmov with two consts +;; +/- 1. + +(define_predicate "mcore_arith_O_operand" + (match_code "const_int,reg,subreg") +{ + if (register_operand (op, mode)) + return 1; + + if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_O (INTVAL (op))) + return 1; + + return 0; +}) + +;; Nonzero if OP is a valid source operand for loading. + +(define_predicate "mcore_arith_imm_operand" + (match_code "const_int,reg,subreg") +{ + if (register_operand (op, mode)) + return 1; + + if (GET_CODE (op) == CONST_INT && const_ok_for_mcore (INTVAL (op))) + return 1; + + return 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "mcore_arith_any_imm_operand" + (match_code "const_int,reg,subreg") +{ + if (register_operand (op, mode)) + return 1; + + if (GET_CODE (op) == CONST_INT) + return 1; + + return 0; +}) + +;; Nonzero if OP is a valid source operand for a btsti. + +(define_predicate "mcore_literal_K_operand" + (match_code "const_int") +{ + if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))) + return 1; + + return 0; +}) + +;; Nonzero if OP is a valid source operand for an add/sub insn. + +(define_predicate "mcore_addsub_operand" + (match_code "const_int,reg,subreg") +{ + if (register_operand (op, mode)) + return 1; + + if (GET_CODE (op) == CONST_INT) + { + return 1; + + /* The following is removed because it precludes large constants from being + returned as valid source operands for and add/sub insn. While large + constants may not directly be used in an add/sub, they may if first loaded + into a register. Thus, this predicate should indicate that they are valid, + and the constraint in mcore.md should control whether an additional load to + register is needed. (see mcore.md, addsi). -- DAC 4/2/1998 */ + /* + if (CONST_OK_FOR_J(INTVAL(op)) || CONST_OK_FOR_L(INTVAL(op))) + return 1; + */ + } + + return 0; +}) + +;; Nonzero if OP is a valid source operand for a compare operation. + +(define_predicate "mcore_compare_operand" + (match_code "const_int,reg,subreg") +{ + if (register_operand (op, mode)) + return 1; + + if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0) + return 1; + + return 0; +}) + +;; Return 1 if OP is a load multiple operation. It is known to be a +;; PARALLEL and the first section will be tested. + +(define_predicate "mcore_load_multiple_operation" + (match_code "parallel") +{ + int count = XVECLEN (op, 0); + int dest_regno; + rtx src_addr; + int i; + + /* Perform a quick check so we don't blow up below. */ + if (count <= 1 + || GET_CODE (XVECEXP (op, 0, 0)) != SET + || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG + || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM) + return 0; + + dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0))); + src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0); + + for (i = 1; i < count; i++) + { + rtx elt = XVECEXP (op, 0, i); + + if (GET_CODE (elt) != SET + || GET_CODE (SET_DEST (elt)) != REG + || GET_MODE (SET_DEST (elt)) != SImode + || REGNO (SET_DEST (elt)) != (unsigned) (dest_regno + i) + || GET_CODE (SET_SRC (elt)) != MEM + || GET_MODE (SET_SRC (elt)) != SImode + || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS + || ! 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)) != i * 4) + return 0; + } + + return 1; +}) + +;; Similar, but tests for store multiple. + +(define_predicate "mcore_store_multiple_operation" + (match_code "parallel") +{ + int count = XVECLEN (op, 0); + int src_regno; + rtx dest_addr; + int i; + + /* Perform a quick check so we don't blow up below. */ + if (count <= 1 + || GET_CODE (XVECEXP (op, 0, 0)) != SET + || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM + || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG) + return 0; + + src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0))); + dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0); + + for (i = 1; i < count; i++) + { + rtx elt = XVECEXP (op, 0, i); + + if (GET_CODE (elt) != SET + || GET_CODE (SET_SRC (elt)) != REG + || GET_MODE (SET_SRC (elt)) != SImode + || REGNO (SET_SRC (elt)) != (unsigned) (src_regno + i) + || GET_CODE (SET_DEST (elt)) != MEM + || GET_MODE (SET_DEST (elt)) != SImode + || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS + || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) + || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT + || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4) + return 0; + } + + return 1; +}) + +;; TODO: Add a comment here. + +(define_predicate "mcore_call_address_operand" + (match_code "reg,subreg,const_int,symbol_ref") +{ + return register_operand (op, mode) || CONSTANT_P (op); +}) |