]>
Commit | Line | Data |
---|---|---|
cc73528f | 1 | ;; Operand and operator predicates for the GCC MMIX port. |
8d9254fc | 2 | ;; Copyright (C) 2005-2020 Free Software Foundation, Inc. |
cc73528f HPN |
3 | |
4 | ;; This file is part of GCC. | |
5 | ;; | |
6 | ;; GCC is free software; you can redistribute it and/or modify | |
7 | ;; it under the terms of the GNU General Public License as published by | |
2f83c7d6 | 8 | ;; the Free Software Foundation; either version 3, or (at your option) |
cc73528f HPN |
9 | ;; any later version. |
10 | ;; | |
11 | ;; GCC is distributed in the hope that it will be useful, | |
12 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | ;; GNU General Public License for more details. | |
15 | ;; | |
16 | ;; You should have received a copy of the GNU General Public License | |
2f83c7d6 NC |
17 | ;; along with GCC; see the file COPYING3. If not see |
18 | ;; <http://www.gnu.org/licenses/>. | |
cc73528f | 19 | |
f90b7a5a PB |
20 | ;; Return 1 if OP is a valid comparison operator for "cbranch" instructions. |
21 | ;; LE and GE are further lowered by the cbranchdf4 pattern. | |
22 | (define_predicate "float_comparison_operator" | |
23 | (match_code "ne, eq, le, ge, lt, gt, ordered, unordered")) | |
24 | ||
cc73528f HPN |
25 | ;; True if this is a foldable comparison operator |
26 | ;; - one where a the result of (compare:CC (reg) (const_int 0)) can be | |
27 | ;; replaced by (reg). */ | |
28 | ||
29 | (define_predicate "mmix_foldable_comparison_operator" | |
30 | (match_code "ne, eq, ge, gt, le, lt, gtu, leu") | |
31 | { | |
32 | RTX_CODE code = GET_CODE (op); | |
33 | ||
34 | if (mode == VOIDmode) | |
35 | mode = GET_MODE (op); | |
36 | ||
37 | /* This little bit is why the body of this predicate is kept as C. */ | |
38 | if (mode == VOIDmode) | |
39 | mode = GET_MODE (XEXP (op, 0)); | |
40 | ||
41 | return ((mode == CCmode || mode == DImode) | |
42 | && (code == NE || code == EQ || code == GE || code == GT | |
43 | || code == LE || code == LT)) | |
44 | /* FIXME: This may be a stupid trick. What happens when GCC wants to | |
45 | reverse the condition? Can it do that by itself? Maybe it can | |
46 | even reverse the condition to fit a foldable one in the first | |
47 | place? */ | |
48 | || (mode == CC_UNSmode && (code == GTU || code == LEU)); | |
49 | }) | |
50 | ||
51 | ;; Like comparison_operator, but only true if this comparison operator is | |
52 | ;; applied to a valid mode. Needed to avoid jump.c generating invalid | |
53 | ;; code with -ffast-math (gcc.dg/20001228-1.c). | |
54 | ||
55 | (define_predicate "mmix_comparison_operator" | |
56 | (match_operand 0 "comparison_operator") | |
57 | { | |
58 | RTX_CODE code = GET_CODE (op); | |
59 | ||
60 | /* Comparison operators usually don't have a mode, but let's try and get | |
61 | one anyway for the day that changes. */ | |
62 | if (mode == VOIDmode) | |
63 | mode = GET_MODE (op); | |
64 | ||
65 | /* Get the mode from the first operand if we don't have one. | |
66 | Also the reason why we do this in C. */ | |
67 | if (mode == VOIDmode) | |
68 | mode = GET_MODE (XEXP (op, 0)); | |
69 | ||
70 | /* FIXME: This needs to be kept in sync with the tables in | |
71 | mmix_output_condition. */ | |
72 | return | |
73 | mode == VOIDmode | |
74 | || (mode == CC_FUNmode | |
75 | && (code == ORDERED || code == UNORDERED)) | |
76 | || (mode == CC_FPmode | |
77 | && (code == GT || code == LT)) | |
78 | || (mode == CC_FPEQmode | |
79 | && (code == NE || code == EQ)) | |
80 | || (mode == CC_UNSmode | |
81 | && (code == GEU || code == GTU || code == LEU || code == LTU)) | |
82 | || (mode == CCmode | |
83 | && (code == NE || code == EQ || code == GE || code == GT | |
84 | || code == LE || code == LT)) | |
85 | || (mode == DImode | |
86 | && (code == NE || code == EQ || code == GE || code == GT | |
87 | || code == LE || code == LT || code == LEU || code == GTU)); | |
88 | }) | |
89 | ||
90 | ;; True if this is a register with a condition-code mode. | |
91 | ||
92 | (define_predicate "mmix_reg_cc_operand" | |
93 | (and (match_operand 0 "register_operand") | |
94 | (ior (match_test "GET_MODE (op) == CCmode") | |
95 | (ior (match_test "GET_MODE (op) == CC_UNSmode") | |
96 | (ior (match_test "GET_MODE (op) == CC_FPmode") | |
97 | (ior (match_test "GET_MODE (op) == CC_FPEQmode") | |
98 | (match_test "GET_MODE (op) == CC_FUNmode"))))))) | |
99 | ||
100 | ;; True if this is an address_operand or a symbolic operand. | |
101 | ||
102 | (define_predicate "mmix_symbolic_or_address_operand" | |
103 | (match_code "symbol_ref, label_ref, const, subreg, reg, plus") | |
104 | { | |
105 | switch (GET_CODE (op)) | |
106 | { | |
107 | case SYMBOL_REF: | |
108 | case LABEL_REF: | |
109 | return 1; | |
110 | case CONST: | |
111 | /* The reason why this body still is C. */ | |
112 | op = XEXP (op, 0); | |
113 | if ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF | |
114 | || GET_CODE (XEXP (op, 0)) == LABEL_REF) | |
115 | && (GET_CODE (XEXP (op, 1)) == CONST_INT | |
116 | || (GET_CODE (XEXP (op, 1)) == CONST_DOUBLE | |
117 | && GET_MODE (XEXP (op, 1)) == VOIDmode))) | |
118 | return 1; | |
119 | /* Fall through. */ | |
120 | default: | |
e076319b | 121 | return mmix_address_operand (op, mode); |
cc73528f HPN |
122 | } |
123 | }) | |
124 | ||
125 | ;; True if this is a register or CONST_INT (or CONST_DOUBLE for DImode). | |
126 | ;; We could narrow the value down with a couple of predicates, but that | |
127 | ;; doesn't seem to be worth it at the moment. | |
128 | ||
129 | (define_predicate "mmix_reg_or_constant_operand" | |
130 | (ior (match_operand 0 "register_operand") | |
131 | (ior (match_code "const_int") | |
132 | (and (match_code "const_double") | |
133 | (match_test "GET_MODE (op) == VOIDmode"))))) | |
134 | ||
135 | ;; True if this is a register or 0 (int or float). | |
136 | ||
137 | (define_predicate "mmix_reg_or_0_operand" | |
138 | (ior | |
139 | (match_operand 0 "register_operand") | |
140 | (ior | |
141 | (and (match_code "const_int") | |
142 | (match_test "op == const0_rtx")) | |
143 | (and | |
144 | (match_code "const_double") | |
145 | ;; FIXME: Is mode calculation necessary and correct? | |
146 | (match_test | |
147 | "op == CONST0_RTX (mode == VOIDmode ? GET_MODE (op) : mode)"))))) | |
148 | ||
149 | ;; True if this is a register or an int 0..255. | |
150 | ||
151 | (define_predicate "mmix_reg_or_8bit_operand" | |
152 | (ior | |
153 | (match_operand 0 "register_operand") | |
154 | (and (match_code "const_int") | |
e076319b NF |
155 | (match_test "satisfies_constraint_I (op)")))) |
156 | ||
157 | ;; True if this is a memory address, possibly strictly. | |
158 | ;; See also comment above the "*call_real" pattern. | |
159 | ||
160 | (define_predicate "mmix_address_operand" | |
161 | (if_then_else (match_test "reload_in_progress || reload_completed") | |
162 | (match_test "strict_memory_address_p (Pmode, op)") | |
163 | (match_test "memory_address_p (Pmode, op)"))) | |
a271e61c HPN |
164 | |
165 | (define_predicate "frame_pointer_operand" | |
166 | (ior | |
167 | (and | |
168 | (match_code "reg") | |
169 | (match_test "op == hard_frame_pointer_rtx || op == frame_pointer_rtx")) | |
170 | (and | |
171 | (match_code "plus") | |
172 | (match_code "reg" "0") | |
173 | (match_code "const_int" "1") | |
174 | (match_test "XEXP (op, 0) == stack_pointer_rtx")))) |