X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=gcc%2Fconfig%2Fmmix%2Fpredicates.md;fp=gcc%2Fconfig%2Fmmix%2Fpredicates.md;h=5c5792e1f6ba24bef6e3cb6ead4ac6b960db8d27;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=0000000000000000000000000000000000000000;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gcc/config/mmix/predicates.md b/gcc/config/mmix/predicates.md new file mode 100644 index 00000000..5c5792e1 --- /dev/null +++ b/gcc/config/mmix/predicates.md @@ -0,0 +1,150 @@ +;; Operand and operator predicates for the GCC MMIX port. +;; Copyright (C) 2005, 2007 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 3, 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 COPYING3. If not see +;; . + +;; True if this is a foldable comparison operator +;; - one where a the result of (compare:CC (reg) (const_int 0)) can be +;; replaced by (reg). */ + +(define_predicate "mmix_foldable_comparison_operator" + (match_code "ne, eq, ge, gt, le, lt, gtu, leu") +{ + RTX_CODE code = GET_CODE (op); + + if (mode == VOIDmode) + mode = GET_MODE (op); + + /* This little bit is why the body of this predicate is kept as C. */ + if (mode == VOIDmode) + mode = GET_MODE (XEXP (op, 0)); + + return ((mode == CCmode || mode == DImode) + && (code == NE || code == EQ || code == GE || code == GT + || code == LE || code == LT)) + /* FIXME: This may be a stupid trick. What happens when GCC wants to + reverse the condition? Can it do that by itself? Maybe it can + even reverse the condition to fit a foldable one in the first + place? */ + || (mode == CC_UNSmode && (code == GTU || code == LEU)); +}) + +;; Like comparison_operator, but only true if this comparison operator is +;; applied to a valid mode. Needed to avoid jump.c generating invalid +;; code with -ffast-math (gcc.dg/20001228-1.c). + +(define_predicate "mmix_comparison_operator" + (match_operand 0 "comparison_operator") +{ + RTX_CODE code = GET_CODE (op); + + /* Comparison operators usually don't have a mode, but let's try and get + one anyway for the day that changes. */ + if (mode == VOIDmode) + mode = GET_MODE (op); + + /* Get the mode from the first operand if we don't have one. + Also the reason why we do this in C. */ + if (mode == VOIDmode) + mode = GET_MODE (XEXP (op, 0)); + + /* FIXME: This needs to be kept in sync with the tables in + mmix_output_condition. */ + return + mode == VOIDmode + || (mode == CC_FUNmode + && (code == ORDERED || code == UNORDERED)) + || (mode == CC_FPmode + && (code == GT || code == LT)) + || (mode == CC_FPEQmode + && (code == NE || code == EQ)) + || (mode == CC_UNSmode + && (code == GEU || code == GTU || code == LEU || code == LTU)) + || (mode == CCmode + && (code == NE || code == EQ || code == GE || code == GT + || code == LE || code == LT)) + || (mode == DImode + && (code == NE || code == EQ || code == GE || code == GT + || code == LE || code == LT || code == LEU || code == GTU)); +}) + +;; True if this is a register with a condition-code mode. + +(define_predicate "mmix_reg_cc_operand" + (and (match_operand 0 "register_operand") + (ior (match_test "GET_MODE (op) == CCmode") + (ior (match_test "GET_MODE (op) == CC_UNSmode") + (ior (match_test "GET_MODE (op) == CC_FPmode") + (ior (match_test "GET_MODE (op) == CC_FPEQmode") + (match_test "GET_MODE (op) == CC_FUNmode"))))))) + +;; True if this is an address_operand or a symbolic operand. + +(define_predicate "mmix_symbolic_or_address_operand" + (match_code "symbol_ref, label_ref, const, subreg, reg, plus") +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF: + case LABEL_REF: + return 1; + case CONST: + /* The reason why this body still is C. */ + op = XEXP (op, 0); + if ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF + || GET_CODE (XEXP (op, 0)) == LABEL_REF) + && (GET_CODE (XEXP (op, 1)) == CONST_INT + || (GET_CODE (XEXP (op, 1)) == CONST_DOUBLE + && GET_MODE (XEXP (op, 1)) == VOIDmode))) + return 1; + /* Fall through. */ + default: + return address_operand (op, mode); + } +}) + +;; True if this is a register or CONST_INT (or CONST_DOUBLE for DImode). +;; We could narrow the value down with a couple of predicates, but that +;; doesn't seem to be worth it at the moment. + +(define_predicate "mmix_reg_or_constant_operand" + (ior (match_operand 0 "register_operand") + (ior (match_code "const_int") + (and (match_code "const_double") + (match_test "GET_MODE (op) == VOIDmode"))))) + +;; True if this is a register or 0 (int or float). + +(define_predicate "mmix_reg_or_0_operand" + (ior + (match_operand 0 "register_operand") + (ior + (and (match_code "const_int") + (match_test "op == const0_rtx")) + (and + (match_code "const_double") + ;; FIXME: Is mode calculation necessary and correct? + (match_test + "op == CONST0_RTX (mode == VOIDmode ? GET_MODE (op) : mode)"))))) + +;; True if this is a register or an int 0..255. + +(define_predicate "mmix_reg_or_8bit_operand" + (ior + (match_operand 0 "register_operand") + (and (match_code "const_int") + (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')"))))