1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
;; Operand and operator predicates for the GCC MMIX 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, 51 Franklin Street - Fifth Floor,
;; Boston, MA 02110-1301, USA.
;; 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')"))))
|