From 94c41a53c50b57fd5bf5282f9db1ba764c0b320f Mon Sep 17 00:00:00 2001 From: kazu Date: Sun, 3 Apr 2005 00:38:00 +0000 Subject: [PATCH] * config/iq2000/iq2000.c (uns_arith_operand, arith_operand, small_int, large_int, reg_or_0_operand, simple_memory_operand, equality_op, cmp_op, pc_or_label_operand, call_insn_operand, move_operand, power_of_2_operand): Move to predicates.md. * config/iq2000/iq2000.h (SPECIAL_MODE_PREDICATES, PREDICATE_CODE): Remove. * config/iq2000/iq2000.md: Include predicates.md. * config/iq2000/predicates.md: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@97472 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 11 ++ gcc/config/iq2000/iq2000.c | 211 ------------------------------------ gcc/config/iq2000/iq2000.h | 24 ----- gcc/config/iq2000/iq2000.md | 3 +- gcc/config/iq2000/predicates.md | 233 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 246 insertions(+), 236 deletions(-) create mode 100644 gcc/config/iq2000/predicates.md diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 09b374f1b24..9ffac61a605 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2005-04-02 Kazu Hirata + + * config/iq2000/iq2000.c (uns_arith_operand, arith_operand, + small_int, large_int, reg_or_0_operand, simple_memory_operand, + equality_op, cmp_op, pc_or_label_operand, call_insn_operand, + move_operand, power_of_2_operand): Move to predicates.md. + * config/iq2000/iq2000.h (SPECIAL_MODE_PREDICATES, + PREDICATE_CODE): Remove. + * config/iq2000/iq2000.md: Include predicates.md. + * config/iq2000/predicates.md: New. + 2005-04-02 Richard Sandiford * config/m68hc11/m68hc11.h (target_flags, MASK_SHORT) diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c index b9fa16ac461..ff3fc0d6545 100644 --- a/gcc/config/iq2000/iq2000.c +++ b/gcc/config/iq2000/iq2000.c @@ -208,217 +208,6 @@ static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, struct gcc_target targetm = TARGET_INITIALIZER; -/* Return 1 if OP can be used as an operand where a register or 16 bit unsigned - integer is needed. */ - -int -uns_arith_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op)) - return 1; - - return register_operand (op, mode); -} - -/* Return 1 if OP can be used as an operand where a 16 bit integer is needed. */ - -int -arith_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == CONST_INT && SMALL_INT (op)) - return 1; - - return register_operand (op, mode); -} - -/* Return 1 if OP is a integer which fits in 16 bits. */ - -int -small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT && SMALL_INT (op)); -} - -/* Return 1 if OP is a 32 bit integer which is too big to be loaded with one - instruction. */ - -int -large_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - HOST_WIDE_INT value; - - if (GET_CODE (op) != CONST_INT) - return 0; - - value = INTVAL (op); - - /* IOR reg,$r0,value. */ - if ((value & ~ ((HOST_WIDE_INT) 0x0000ffff)) == 0) - return 0; - - /* SUBU reg,$r0,value. */ - if (((unsigned HOST_WIDE_INT) (value + 32768)) <= 32767) - return 0; - - /* LUI reg,value >> 16. */ - if ((value & 0x0000ffff) == 0) - return 0; - - return 1; -} - -/* Return 1 if OP is a register or the constant 0. */ - -int -reg_or_0_operand (rtx op, enum machine_mode mode) -{ - switch (GET_CODE (op)) - { - case CONST_INT: - return INTVAL (op) == 0; - - case CONST_DOUBLE: - return op == CONST0_RTX (mode); - - case REG: - case SUBREG: - return register_operand (op, mode); - - default: - break; - } - - return 0; -} - -/* Return 1 if OP is a memory operand that fits in a single instruction - (i.e., register + small offset). */ - -int -simple_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - rtx addr, plus0, plus1; - - /* Eliminate non-memory operations. */ - if (GET_CODE (op) != MEM) - return 0; - - /* Dword operations really put out 2 instructions, so eliminate them. */ - if (GET_MODE_SIZE (GET_MODE (op)) > (unsigned) UNITS_PER_WORD) - return 0; - - /* Decode the address now. */ - addr = XEXP (op, 0); - switch (GET_CODE (addr)) - { - case REG: - case LO_SUM: - return 1; - - case CONST_INT: - return SMALL_INT (addr); - - case PLUS: - plus0 = XEXP (addr, 0); - plus1 = XEXP (addr, 1); - if (GET_CODE (plus0) == REG - && GET_CODE (plus1) == CONST_INT && SMALL_INT (plus1) - && SMALL_INT_UNSIGNED (plus1) /* No negative offsets. */) - return 1; - - else if (GET_CODE (plus1) == REG - && GET_CODE (plus0) == CONST_INT && SMALL_INT (plus0) - && SMALL_INT_UNSIGNED (plus1) /* No negative offsets. */) - return 1; - - else - return 0; - - case SYMBOL_REF: - return 0; - - default: - break; - } - - return 0; -} - -/* Return nonzero if the code of this rtx pattern is EQ or NE. */ - -int -equality_op (rtx op, enum machine_mode mode) -{ - if (mode != GET_MODE (op)) - return 0; - - return GET_CODE (op) == EQ || GET_CODE (op) == NE; -} - -/* Return nonzero if the code is a relational operations (EQ, LE, etc). */ - -int -cmp_op (rtx op, enum machine_mode mode) -{ - if (mode != GET_MODE (op)) - return 0; - - return COMPARISON_P (op); -} - -/* Return nonzero if the operand is either the PC or a label_ref. */ - -int -pc_or_label_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (op == pc_rtx) - return 1; - - if (GET_CODE (op) == LABEL_REF) - return 1; - - return 0; -} - -/* Return nonzero if OP is a valid operand for a call instruction. */ - -int -call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (CONSTANT_ADDRESS_P (op) - || (GET_CODE (op) == REG && op != arg_pointer_rtx - && ! (REGNO (op) >= FIRST_PSEUDO_REGISTER - && REGNO (op) <= LAST_VIRTUAL_REGISTER))); -} - -/* Return nonzero if OP is valid as a source operand for a move instruction. */ - -int -move_operand (rtx op, enum machine_mode mode) -{ - /* Accept any general operand after reload has started; doing so - avoids losing if reload does an in-place replacement of a register - with a SYMBOL_REF or CONST. */ - return (general_operand (op, mode) - && (! (iq2000_check_split (op, mode)) - || reload_in_progress || reload_completed)); -} - -/* Return nonzero if OP is a constant power of 2. */ - -int -power_of_2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int intval; - - if (GET_CODE (op) != CONST_INT) - return 0; - else - intval = INTVAL (op); - - return ((intval & ((unsigned)(intval) - 1)) == 0); -} - /* Return nonzero if we split the address into high and low parts. */ int diff --git a/gcc/config/iq2000/iq2000.h b/gcc/config/iq2000/iq2000.h index eef6285c27b..a352eea2e1e 100644 --- a/gcc/config/iq2000/iq2000.h +++ b/gcc/config/iq2000/iq2000.h @@ -779,23 +779,6 @@ while (0) /* Miscellaneous Parameters. */ -#define PREDICATE_CODES \ - {"uns_arith_operand", { REG, CONST_INT, SUBREG }}, \ - {"arith_operand", { REG, CONST_INT, SUBREG }}, \ - {"small_int", { CONST_INT }}, \ - {"large_int", { CONST_INT }}, \ - {"reg_or_0_operand", { REG, CONST_INT, CONST_DOUBLE, SUBREG }}, \ - {"simple_memory_operand", { MEM, SUBREG }}, \ - {"equality_op", { EQ, NE }}, \ - {"cmp_op", { EQ, NE, GT, GE, GTU, GEU, LT, LE, \ - LTU, LEU }}, \ - {"pc_or_label_operand", { PC, LABEL_REF }}, \ - {"call_insn_operand", { CONST_INT, CONST, SYMBOL_REF, REG}}, \ - {"move_operand", { CONST_INT, CONST_DOUBLE, CONST, \ - SYMBOL_REF, LABEL_REF, SUBREG, \ - REG, MEM}}, \ - {"power_of_2_operand", { CONST_INT }}, - #define CASE_VECTOR_MODE SImode #define WORD_REGISTER_OPERATIONS @@ -1062,13 +1045,6 @@ extern void sbss_section (void); ((LENGTH) = iq2000_adjust_insn_length ((INSN), (LENGTH))) -/* A list of predicates that do special things with modes, and so - should not elicit warnings for VOIDmode match_operand. */ - -#define SPECIAL_MODE_PREDICATES \ - "pc_or_label_operand", - - /* How to tell the debugger about changes of source files. */ diff --git a/gcc/config/iq2000/iq2000.md b/gcc/config/iq2000/iq2000.md index 6e6c0767ba3..208b82c2b9d 100644 --- a/gcc/config/iq2000/iq2000.md +++ b/gcc/config/iq2000/iq2000.md @@ -1,5 +1,5 @@ ;; iq2000.md Machine Description for Vitesse IQ2000 processors -;; Copyright (C) 2003, 2004 Free Software Foundation, Inc. +;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. ;; This file is part of GCC. @@ -194,6 +194,7 @@ (nil) (nil)]) +(include "predicates.md") ;; ......................... diff --git a/gcc/config/iq2000/predicates.md b/gcc/config/iq2000/predicates.md new file mode 100644 index 00000000000..a8ce5819d74 --- /dev/null +++ b/gcc/config/iq2000/predicates.md @@ -0,0 +1,233 @@ +;; Predicate definitions for Vitesse IQ2000. +;; 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 1 if OP can be used as an operand where a register or 16 bit +;; unsigned integer is needed. + +(define_predicate "uns_arith_operand" + (match_code "reg,const_int,subreg") +{ + if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op)) + return 1; + + return register_operand (op, mode); +}) + +;; Return 1 if OP can be used as an operand where a 16 bit integer is +;; needed. + +(define_predicate "arith_operand" + (match_code "reg,const_int,subreg") +{ + if (GET_CODE (op) == CONST_INT && SMALL_INT (op)) + return 1; + + return register_operand (op, mode); +}) + +;; Return 1 if OP is a integer which fits in 16 bits. + +(define_predicate "small_int" + (match_code "const_int") +{ + return (GET_CODE (op) == CONST_INT && SMALL_INT (op)); +}) + +;; Return 1 if OP is a 32 bit integer which is too big to be loaded +;; with one instruction. + +(define_predicate "large_int" + (match_code "const_int") +{ + HOST_WIDE_INT value; + + if (GET_CODE (op) != CONST_INT) + return 0; + + value = INTVAL (op); + + /* IOR reg,$r0,value. */ + if ((value & ~ ((HOST_WIDE_INT) 0x0000ffff)) == 0) + return 0; + + /* SUBU reg,$r0,value. */ + if (((unsigned HOST_WIDE_INT) (value + 32768)) <= 32767) + return 0; + + /* LUI reg,value >> 16. */ + if ((value & 0x0000ffff) == 0) + return 0; + + return 1; +}) + +;; Return 1 if OP is a register or the constant 0. + +(define_predicate "reg_or_0_operand" + (match_code "reg,const_int,const_double,subreg") +{ + switch (GET_CODE (op)) + { + case CONST_INT: + return INTVAL (op) == 0; + + case CONST_DOUBLE: + return op == CONST0_RTX (mode); + + case REG: + case SUBREG: + return register_operand (op, mode); + + default: + break; + } + + return 0; +}) + +;; Return 1 if OP is a memory operand that fits in a single +;; instruction (i.e., register + small offset). + +(define_predicate "simple_memory_operand" + (match_code "mem,subreg") +{ + rtx addr, plus0, plus1; + + /* Eliminate non-memory operations. */ + if (GET_CODE (op) != MEM) + return 0; + + /* Dword operations really put out 2 instructions, so eliminate them. */ + if (GET_MODE_SIZE (GET_MODE (op)) > (unsigned) UNITS_PER_WORD) + return 0; + + /* Decode the address now. */ + addr = XEXP (op, 0); + switch (GET_CODE (addr)) + { + case REG: + case LO_SUM: + return 1; + + case CONST_INT: + return SMALL_INT (addr); + + case PLUS: + plus0 = XEXP (addr, 0); + plus1 = XEXP (addr, 1); + if (GET_CODE (plus0) == REG + && GET_CODE (plus1) == CONST_INT && SMALL_INT (plus1) + && SMALL_INT_UNSIGNED (plus1) /* No negative offsets. */) + return 1; + + else if (GET_CODE (plus1) == REG + && GET_CODE (plus0) == CONST_INT && SMALL_INT (plus0) + && SMALL_INT_UNSIGNED (plus1) /* No negative offsets. */) + return 1; + + else + return 0; + + case SYMBOL_REF: + return 0; + + default: + break; + } + + return 0; +}) + +;; Return nonzero if the code of this rtx pattern is EQ or NE. + +(define_predicate "equality_op" + (match_code "eq,ne") +{ + if (mode != GET_MODE (op)) + return 0; + + return GET_CODE (op) == EQ || GET_CODE (op) == NE; +}) + +;; Return nonzero if the code is a relational operations (EQ, LE, +;; etc). + +(define_predicate "cmp_op" + (match_code "eq,ne,gt,ge,gtu,geu,lt,le,ltu,leu") +{ + if (mode != GET_MODE (op)) + return 0; + + return COMPARISON_P (op); +}) + +;; Return nonzero if the operand is either the PC or a label_ref. + +(define_special_predicate "pc_or_label_operand" + (match_code "pc,label_ref") +{ + if (op == pc_rtx) + return 1; + + if (GET_CODE (op) == LABEL_REF) + return 1; + + return 0; +}) + +;; Return nonzero if OP is a valid operand for a call instruction. + +(define_predicate "call_insn_operand" + (match_code "const_int,const,symbol_ref,reg") +{ + return (CONSTANT_ADDRESS_P (op) + || (GET_CODE (op) == REG && op != arg_pointer_rtx + && ! (REGNO (op) >= FIRST_PSEUDO_REGISTER + && REGNO (op) <= LAST_VIRTUAL_REGISTER))); +}) + +;; Return nonzero if OP is valid as a source operand for a move +;; instruction. + +(define_predicate "move_operand" + (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,mem") +{ + /* Accept any general operand after reload has started; doing so + avoids losing if reload does an in-place replacement of a register + with a SYMBOL_REF or CONST. */ + return (general_operand (op, mode) + && (! (iq2000_check_split (op, mode)) + || reload_in_progress || reload_completed)); +}) + +;; Return nonzero if OP is a constant power of 2. + +(define_predicate "power_of_2_operand" + (match_code "const_int") +{ + int intval; + + if (GET_CODE (op) != CONST_INT) + return 0; + else + intval = INTVAL (op); + + return ((intval & ((unsigned)(intval) - 1)) == 0); +}) -- 2.11.0