]>
Commit | Line | Data |
---|---|---|
2fbff099 | 1 | ;; Predicate definitions for MIPS. |
71e45bc2 | 2 | ;; Copyright (C) 2004, 2007, 2008, 2011, 2012 Free Software Foundation, Inc. |
2fbff099 | 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 | |
038d1e19 | 8 | ;; the Free Software Foundation; either version 3, or (at your option) |
2fbff099 | 9 | ;; any later version. |
2f3eb73f | 10 | ;; |
2fbff099 | 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 | |
038d1e19 | 17 | ;; along with GCC; see the file COPYING3. If not see |
18 | ;; <http://www.gnu.org/licenses/>. | |
2fbff099 | 19 | |
20 | (define_predicate "const_uns_arith_operand" | |
21 | (and (match_code "const_int") | |
22 | (match_test "SMALL_OPERAND_UNSIGNED (INTVAL (op))"))) | |
23 | ||
24 | (define_predicate "uns_arith_operand" | |
25 | (ior (match_operand 0 "const_uns_arith_operand") | |
26 | (match_operand 0 "register_operand"))) | |
27 | ||
28 | (define_predicate "const_arith_operand" | |
29 | (and (match_code "const_int") | |
30 | (match_test "SMALL_OPERAND (INTVAL (op))"))) | |
31 | ||
32 | (define_predicate "arith_operand" | |
33 | (ior (match_operand 0 "const_arith_operand") | |
34 | (match_operand 0 "register_operand"))) | |
35 | ||
b7efe757 | 36 | (define_predicate "const_uimm6_operand" |
37 | (and (match_code "const_int") | |
38 | (match_test "UIMM6_OPERAND (INTVAL (op))"))) | |
39 | ||
40 | (define_predicate "const_imm10_operand" | |
41 | (and (match_code "const_int") | |
42 | (match_test "IMM10_OPERAND (INTVAL (op))"))) | |
43 | ||
44 | (define_predicate "reg_imm10_operand" | |
45 | (ior (match_operand 0 "const_imm10_operand") | |
46 | (match_operand 0 "register_operand"))) | |
47 | ||
2fbff099 | 48 | (define_predicate "sle_operand" |
49 | (and (match_code "const_int") | |
50 | (match_test "SMALL_OPERAND (INTVAL (op) + 1)"))) | |
51 | ||
52 | (define_predicate "sleu_operand" | |
2f3eb73f | 53 | (and (match_operand 0 "sle_operand") |
54 | (match_test "INTVAL (op) + 1 != 0"))) | |
2fbff099 | 55 | |
56 | (define_predicate "const_0_operand" | |
8ff58a85 | 57 | (and (match_code "const_int,const_double,const_vector") |
2fbff099 | 58 | (match_test "op == CONST0_RTX (GET_MODE (op))"))) |
59 | ||
60 | (define_predicate "reg_or_0_operand" | |
61 | (ior (and (match_operand 0 "const_0_operand") | |
b71d8fa0 | 62 | (not (match_test "TARGET_MIPS16"))) |
2fbff099 | 63 | (match_operand 0 "register_operand"))) |
64 | ||
65 | (define_predicate "const_1_operand" | |
8ff58a85 | 66 | (and (match_code "const_int,const_double,const_vector") |
2fbff099 | 67 | (match_test "op == CONST1_RTX (GET_MODE (op))"))) |
68 | ||
69 | (define_predicate "reg_or_1_operand" | |
70 | (ior (match_operand 0 "const_1_operand") | |
71 | (match_operand 0 "register_operand"))) | |
72 | ||
8ff58a85 | 73 | ;; This is used for indexing into vectors, and hence only accepts const_int. |
74 | (define_predicate "const_0_or_1_operand" | |
75 | (and (match_code "const_int") | |
54e21214 | 76 | (match_test "IN_RANGE (INTVAL (op), 0, 1)"))) |
77 | ||
78 | (define_predicate "const_2_or_3_operand" | |
79 | (and (match_code "const_int") | |
80 | (match_test "IN_RANGE (INTVAL (op), 2, 3)"))) | |
81 | ||
82 | (define_predicate "const_0_to_3_operand" | |
83 | (and (match_code "const_int") | |
84 | (match_test "IN_RANGE (INTVAL (op), 0, 3)"))) | |
8ff58a85 | 85 | |
c051f153 | 86 | (define_predicate "qi_mask_operand" |
87 | (and (match_code "const_int") | |
88 | (match_test "UINTVAL (op) == 0xff"))) | |
89 | ||
90 | (define_predicate "hi_mask_operand" | |
91 | (and (match_code "const_int") | |
92 | (match_test "UINTVAL (op) == 0xffff"))) | |
93 | ||
94 | (define_predicate "si_mask_operand" | |
95 | (and (match_code "const_int") | |
96 | (match_test "UINTVAL (op) == 0xffffffff"))) | |
97 | ||
98 | (define_predicate "and_load_operand" | |
99 | (ior (match_operand 0 "qi_mask_operand") | |
100 | (match_operand 0 "hi_mask_operand") | |
101 | (match_operand 0 "si_mask_operand"))) | |
102 | ||
103 | (define_predicate "low_bitmask_operand" | |
104 | (and (match_test "ISA_HAS_EXT_INS") | |
105 | (match_code "const_int") | |
106 | (match_test "low_bitmask_len (mode, INTVAL (op)) > 16"))) | |
107 | ||
108 | (define_predicate "and_reg_operand" | |
109 | (ior (match_operand 0 "register_operand") | |
b71d8fa0 | 110 | (and (not (match_test "TARGET_MIPS16")) |
c051f153 | 111 | (match_operand 0 "const_uns_arith_operand")) |
112 | (match_operand 0 "low_bitmask_operand") | |
113 | (match_operand 0 "si_mask_operand"))) | |
114 | ||
115 | (define_predicate "and_operand" | |
116 | (ior (match_operand 0 "and_load_operand") | |
117 | (match_operand 0 "and_reg_operand"))) | |
118 | ||
208414ec | 119 | (define_predicate "d_operand" |
2fbff099 | 120 | (and (match_code "reg") |
208414ec | 121 | (match_test "TARGET_MIPS16 |
122 | ? M16_REG_P (REGNO (op)) | |
123 | : GP_REG_P (REGNO (op))"))) | |
2fbff099 | 124 | |
2fbff099 | 125 | (define_predicate "lo_operand" |
126 | (and (match_code "reg") | |
127 | (match_test "REGNO (op) == LO_REGNUM"))) | |
128 | ||
e8b6f830 | 129 | (define_predicate "hilo_operand" |
130 | (and (match_code "reg") | |
131 | (match_test "MD_REG_P (REGNO (op))"))) | |
132 | ||
2fbff099 | 133 | (define_predicate "fcc_reload_operand" |
134 | (and (match_code "reg,subreg") | |
135 | (match_test "ST_REG_P (true_regnum (op))"))) | |
136 | ||
a4cfded4 | 137 | (define_predicate "muldiv_target_operand" |
138 | (if_then_else (match_test "TARGET_MIPS16") | |
139 | (match_operand 0 "hilo_operand") | |
140 | (match_operand 0 "register_operand"))) | |
141 | ||
2fbff099 | 142 | (define_predicate "const_call_insn_operand" |
143 | (match_code "const,symbol_ref,label_ref") | |
144 | { | |
145 | enum mips_symbol_type symbol_type; | |
146 | ||
5039caa5 | 147 | if (!mips_symbolic_constant_p (op, SYMBOL_CONTEXT_CALL, &symbol_type)) |
2fbff099 | 148 | return false; |
149 | ||
150 | switch (symbol_type) | |
151 | { | |
a738b930 | 152 | case SYMBOL_ABSOLUTE: |
559b0712 | 153 | /* We can only use direct calls if we're sure that the target |
154 | function does not need $25 to be valid on entry. */ | |
155 | if (mips_use_pic_fn_addr_reg_p (op)) | |
1b6b10a9 | 156 | return false; |
157 | ||
7808555b | 158 | /* If -mlong-calls or if this function has an explicit long_call |
159 | attribute, we must use register addressing. The | |
160 | SYMBOL_FLAG_LONG_CALL bit is set by mips_encode_section_info. */ | |
4c10df75 | 161 | return !(GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_LONG_CALL_P (op)); |
2fbff099 | 162 | |
4cb04729 | 163 | case SYMBOL_GOT_DISP: |
2fbff099 | 164 | /* Without explicit relocs, there is no special syntax for |
165 | loading the address of a call destination into a register. | |
166 | Using "la $25,foo; jal $25" would prevent the lazy binding | |
167 | of "foo", so keep the address of global symbols with the | |
168 | jal macro. */ | |
169 | return !TARGET_EXPLICIT_RELOCS; | |
170 | ||
171 | default: | |
172 | return false; | |
173 | } | |
174 | }) | |
175 | ||
176 | (define_predicate "call_insn_operand" | |
177 | (ior (match_operand 0 "const_call_insn_operand") | |
178 | (match_operand 0 "register_operand"))) | |
179 | ||
1a4d3221 | 180 | ;; A legitimate CONST_INT operand that takes more than one instruction |
181 | ;; to load. | |
182 | (define_predicate "splittable_const_int_operand" | |
183 | (match_code "const_int") | |
184 | { | |
ca316360 | 185 | /* When generating mips16 code, TARGET_LEGITIMATE_CONSTANT_P rejects |
1a4d3221 | 186 | CONST_INTs that can't be loaded using simple insns. */ |
187 | if (TARGET_MIPS16) | |
188 | return false; | |
189 | ||
190 | /* Don't handle multi-word moves this way; we don't want to introduce | |
191 | the individual word-mode moves until after reload. */ | |
192 | if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) | |
193 | return false; | |
194 | ||
195 | /* Otherwise check whether the constant can be loaded in a single | |
196 | instruction. */ | |
197 | return !LUI_INT (op) && !SMALL_INT (op) && !SMALL_INT_UNSIGNED (op); | |
198 | }) | |
199 | ||
2fbff099 | 200 | (define_predicate "move_operand" |
a4cfded4 | 201 | ;; Allow HI and LO to be used as the source of a MIPS16 move. |
202 | (ior (match_operand 0 "general_operand") | |
203 | (match_operand 0 "hilo_operand")) | |
2fbff099 | 204 | { |
1a4d3221 | 205 | enum mips_symbol_type symbol_type; |
206 | ||
207 | /* The thinking here is as follows: | |
208 | ||
209 | (1) The move expanders should split complex load sequences into | |
210 | individual instructions. Those individual instructions can | |
211 | then be optimized by all rtl passes. | |
212 | ||
213 | (2) The target of pre-reload load sequences should not be used | |
214 | to store temporary results. If the target register is only | |
215 | assigned one value, reload can rematerialize that value | |
216 | on demand, rather than spill it to the stack. | |
217 | ||
218 | (3) If we allowed pre-reload passes like combine and cse to recreate | |
219 | complex load sequences, we would want to be able to split the | |
220 | sequences before reload as well, so that the pre-reload scheduler | |
221 | can see the individual instructions. This falls foul of (2); | |
222 | the splitter would be forced to reuse the target register for | |
223 | intermediate results. | |
224 | ||
225 | (4) We want to define complex load splitters for combine. These | |
226 | splitters can request a temporary scratch register, which avoids | |
227 | the problem in (2). They allow things like: | |
228 | ||
229 | (set (reg T1) (high SYM)) | |
230 | (set (reg T2) (low (reg T1) SYM)) | |
231 | (set (reg X) (plus (reg T2) (const_int OFFSET))) | |
232 | ||
233 | to be combined into: | |
234 | ||
235 | (set (reg T3) (high SYM+OFFSET)) | |
236 | (set (reg X) (lo_sum (reg T3) SYM+OFFSET)) | |
237 | ||
238 | if T2 is only used this once. */ | |
2fbff099 | 239 | switch (GET_CODE (op)) |
240 | { | |
241 | case CONST_INT: | |
1a4d3221 | 242 | return !splittable_const_int_operand (op, mode); |
2fbff099 | 243 | |
244 | case CONST: | |
245 | case SYMBOL_REF: | |
246 | case LABEL_REF: | |
1a4d3221 | 247 | if (CONST_GP_P (op)) |
248 | return true; | |
5039caa5 | 249 | return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &symbol_type) |
1a4d3221 | 250 | && !mips_split_p[symbol_type]); |
2fbff099 | 251 | |
559b0712 | 252 | case HIGH: |
253 | op = XEXP (op, 0); | |
254 | return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &symbol_type) | |
255 | && !mips_split_hi_p[symbol_type]); | |
256 | ||
2fbff099 | 257 | default: |
258 | return true; | |
259 | } | |
260 | }) | |
261 | ||
74facf6e | 262 | (define_predicate "cprestore_save_slot_operand" |
263 | (and (match_code "mem") | |
264 | (match_test "mips_cprestore_address_p (XEXP (op, 0), false)"))) | |
265 | ||
266 | (define_predicate "cprestore_load_slot_operand" | |
267 | (and (match_code "mem") | |
268 | (match_test "mips_cprestore_address_p (XEXP (op, 0), true)"))) | |
269 | ||
2fbff099 | 270 | (define_predicate "consttable_operand" |
271 | (match_test "CONSTANT_P (op)")) | |
272 | ||
273 | (define_predicate "symbolic_operand" | |
274 | (match_code "const,symbol_ref,label_ref") | |
275 | { | |
276 | enum mips_symbol_type type; | |
5039caa5 | 277 | return mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &type); |
2fbff099 | 278 | }) |
279 | ||
a738b930 | 280 | (define_predicate "absolute_symbolic_operand" |
2fbff099 | 281 | (match_code "const,symbol_ref,label_ref") |
282 | { | |
283 | enum mips_symbol_type type; | |
5039caa5 | 284 | return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &type) |
285 | && type == SYMBOL_ABSOLUTE); | |
2fbff099 | 286 | }) |
287 | ||
a657080a | 288 | (define_predicate "symbolic_operand_with_high" |
289 | (match_code "const,symbol_ref,label_ref") | |
290 | { | |
291 | enum mips_symbol_type type; | |
292 | return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &type) | |
293 | && mips_hi_relocs[(int) type]); | |
294 | }) | |
295 | ||
b94b01e1 | 296 | (define_predicate "force_to_mem_operand" |
297 | (match_code "const,symbol_ref,label_ref") | |
298 | { | |
299 | enum mips_symbol_type symbol_type; | |
300 | return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &symbol_type) | |
a657080a | 301 | && mips_use_pcrel_pool_p[(int) symbol_type]); |
b94b01e1 | 302 | }) |
303 | ||
4cb04729 | 304 | (define_predicate "got_disp_operand" |
2fbff099 | 305 | (match_code "const,symbol_ref,label_ref") |
306 | { | |
307 | enum mips_symbol_type type; | |
5039caa5 | 308 | return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &type) |
309 | && type == SYMBOL_GOT_DISP); | |
2fbff099 | 310 | }) |
311 | ||
4cb04729 | 312 | (define_predicate "got_page_ofst_operand" |
2fbff099 | 313 | (match_code "const,symbol_ref,label_ref") |
314 | { | |
315 | enum mips_symbol_type type; | |
5039caa5 | 316 | return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &type) |
317 | && type == SYMBOL_GOT_PAGE_OFST); | |
2fbff099 | 318 | }) |
319 | ||
a657080a | 320 | (define_predicate "tls_reloc_operand" |
321 | (match_code "const,symbol_ref,label_ref") | |
322 | { | |
323 | enum mips_symbol_type type; | |
324 | return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &type) | |
325 | && (type == SYMBOL_DTPREL || type == SYMBOL_TPREL)); | |
326 | }) | |
327 | ||
a8a393cb | 328 | (define_predicate "symbol_ref_operand" |
329 | (match_code "symbol_ref")) | |
330 | ||
2fbff099 | 331 | (define_predicate "stack_operand" |
332 | (and (match_code "mem") | |
333 | (match_test "mips_stack_address_p (XEXP (op, 0), GET_MODE (op))"))) | |
334 | ||
335 | (define_predicate "macc_msac_operand" | |
336 | (ior (and (match_code "plus") (match_test "ISA_HAS_MACC")) | |
337 | (and (match_code "minus") (match_test "ISA_HAS_MSAC"))) | |
338 | { | |
339 | rtx mult = XEXP (op, GET_CODE (op) == PLUS ? 0 : 1); | |
340 | rtx accum = XEXP (op, GET_CODE (op) == PLUS ? 1 : 0); | |
341 | return (GET_CODE (mult) == MULT | |
342 | && REG_P (XEXP (mult, 0)) | |
343 | && REG_P (XEXP (mult, 1)) | |
344 | && REG_P (accum)); | |
345 | }) | |
346 | ||
347 | ||
348 | (define_predicate "equality_operator" | |
349 | (match_code "eq,ne")) | |
350 | ||
351 | (define_predicate "extend_operator" | |
352 | (match_code "zero_extend,sign_extend")) | |
353 | ||
354 | (define_predicate "trap_comparison_operator" | |
355 | (match_code "eq,ne,lt,ltu,ge,geu")) | |
356 | ||
fe2ed30d | 357 | (define_predicate "order_operator" |
358 | (match_code "lt,ltu,le,leu,ge,geu,gt,gtu")) | |
359 | ||
74f4459c | 360 | ;; For NE, cstore uses sltu instructions in which the first operand is $0. |
361 | ;; This isn't possible in mips16 code. | |
362 | ||
363 | (define_predicate "mips_cstore_operator" | |
364 | (ior (match_code "eq,gt,gtu,ge,geu,lt,ltu,le,leu") | |
b71d8fa0 | 365 | (and (match_code "ne") (not (match_test "TARGET_MIPS16"))))) |
2fbff099 | 366 | |
367 | (define_predicate "small_data_pattern" | |
b218b649 | 368 | (and (match_code "set,parallel,unspec,unspec_volatile,prefetch") |
2fbff099 | 369 | (match_test "mips_small_data_pattern_p (op)"))) |
974f0a74 | 370 | |
371 | (define_predicate "mem_noofs_operand" | |
372 | (and (match_code "mem") | |
373 | (match_code "reg" "0"))) |