]>
Commit | Line | Data |
---|---|---|
138814fb | 1 | ;; Predicate definitions for Renesas / SuperH SH. |
71e45bc2 | 2 | ;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 |
973cd123 | 3 | ;; Free Software Foundation, Inc. |
138814fb | 4 | ;; |
5 | ;; This file is part of GCC. | |
6 | ;; | |
7 | ;; GCC is free software; you can redistribute it and/or modify | |
8 | ;; it under the terms of the GNU General Public License as published by | |
038d1e19 | 9 | ;; the Free Software Foundation; either version 3, or (at your option) |
138814fb | 10 | ;; any later version. |
11 | ;; | |
12 | ;; GCC is distributed in the hope that it will be useful, | |
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | ;; GNU General Public License for more details. | |
16 | ;; | |
17 | ;; You should have received a copy of the GNU General Public License | |
038d1e19 | 18 | ;; along with GCC; see the file COPYING3. If not see |
19 | ;; <http://www.gnu.org/licenses/>. | |
138814fb | 20 | |
21 | ;; TODO: Add a comment here. | |
22 | ||
59312820 | 23 | (define_predicate "trapping_target_operand" |
24 | (match_code "if_then_else") | |
25 | { | |
ef51d1e3 | 26 | rtx cond, mem, res, tar, and_expr; |
59312820 | 27 | |
28 | if (GET_MODE (op) != PDImode) | |
29 | return 0; | |
30 | cond = XEXP (op, 0); | |
31 | mem = XEXP (op, 1); | |
32 | res = XEXP (op, 2); | |
cbb16986 | 33 | if (!MEM_P (mem) |
59312820 | 34 | || (GET_CODE (res) != SIGN_EXTEND && GET_CODE (res) != TRUNCATE)) |
35 | return 0; | |
36 | tar = XEXP (res, 0); | |
37 | if (!rtx_equal_p (XEXP (mem, 0), tar) | |
38 | || GET_MODE (tar) != Pmode) | |
39 | return 0; | |
40 | if (GET_CODE (cond) == CONST) | |
41 | { | |
42 | cond = XEXP (cond, 0); | |
abff7a2e | 43 | if (!satisfies_constraint_Csy (tar)) |
59312820 | 44 | return 0; |
45 | if (GET_CODE (tar) == CONST) | |
46 | tar = XEXP (tar, 0); | |
47 | } | |
48 | else if (!arith_reg_operand (tar, VOIDmode) | |
abff7a2e | 49 | && ! satisfies_constraint_Csy (tar)) |
59312820 | 50 | return 0; |
51 | if (GET_CODE (cond) != EQ) | |
52 | return 0; | |
ef51d1e3 | 53 | and_expr = XEXP (cond, 0); |
54 | return (GET_CODE (and_expr) == AND | |
55 | && rtx_equal_p (XEXP (and_expr, 0), tar) | |
56 | && CONST_INT_P (XEXP (and_expr, 1)) | |
cbb16986 | 57 | && CONST_INT_P (XEXP (cond, 1)) |
ef51d1e3 | 58 | && INTVAL (XEXP (and_expr, 1)) == 3 |
59312820 | 59 | && INTVAL (XEXP (cond, 1)) == 3); |
60 | }) | |
138814fb | 61 | |
62 | ;; TODO: Add a comment here. | |
63 | ||
64 | (define_predicate "and_operand" | |
65 | (match_code "subreg,reg,const_int") | |
66 | { | |
67 | if (logical_operand (op, mode)) | |
68 | return 1; | |
69 | ||
70 | /* Check mshflo.l / mshflhi.l opportunities. */ | |
71 | if (TARGET_SHMEDIA | |
72 | && mode == DImode | |
abff7a2e | 73 | && satisfies_constraint_J16 (op)) |
138814fb | 74 | return 1; |
75 | ||
76 | return 0; | |
77 | }) | |
78 | ||
63dfe6b8 | 79 | ;; Like arith_reg_dest, but this predicate is defined with |
80 | ;; define_special_predicate, not define_predicate. | |
138814fb | 81 | |
82 | (define_special_predicate "any_arith_reg_dest" | |
83 | (match_code "subreg,reg") | |
84 | { | |
85 | return arith_reg_dest (op, mode); | |
86 | }) | |
87 | ||
63dfe6b8 | 88 | ;; Like register_operand, but this predicate is defined with |
89 | ;; define_special_predicate, not define_predicate. | |
138814fb | 90 | |
91 | (define_special_predicate "any_register_operand" | |
92 | (match_code "subreg,reg") | |
93 | { | |
94 | return register_operand (op, mode); | |
95 | }) | |
96 | ||
97 | ;; Returns 1 if OP is a valid source operand for an arithmetic insn. | |
98 | ||
99 | (define_predicate "arith_operand" | |
100 | (match_code "subreg,reg,const_int,truncate") | |
101 | { | |
102 | if (arith_reg_operand (op, mode)) | |
103 | return 1; | |
104 | ||
105 | if (TARGET_SHMEDIA) | |
106 | { | |
107 | /* FIXME: We should be checking whether the CONST_INT fits in a | |
abff7a2e | 108 | signed 16-bit here, but this causes reload_cse to crash when |
138814fb | 109 | attempting to transform a sequence of two 64-bit sets of the |
110 | same register from literal constants into a set and an add, | |
111 | when the difference is too wide for an add. */ | |
cbb16986 | 112 | if (CONST_INT_P (op) |
abff7a2e | 113 | || satisfies_constraint_Css (op)) |
138814fb | 114 | return 1; |
115 | else if (GET_CODE (op) == TRUNCATE | |
cbb16986 | 116 | && REG_P (XEXP (op, 0)) |
138814fb | 117 | && ! system_reg_operand (XEXP (op, 0), VOIDmode) |
118 | && (mode == VOIDmode || mode == GET_MODE (op)) | |
119 | && (GET_MODE_SIZE (GET_MODE (op)) | |
120 | < GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))) | |
121 | && (! FP_REGISTER_P (REGNO (XEXP (op, 0))) | |
122 | || GET_MODE_SIZE (GET_MODE (op)) == 4)) | |
123 | return register_operand (XEXP (op, 0), VOIDmode); | |
124 | else | |
125 | return 0; | |
126 | } | |
abff7a2e | 127 | else if (satisfies_constraint_I08 (op)) |
138814fb | 128 | return 1; |
129 | ||
130 | return 0; | |
131 | }) | |
132 | ||
133 | ;; Like above, but for DImode destinations: forbid paradoxical DImode | |
134 | ;; subregs, because this would lead to missing sign extensions when | |
135 | ;; truncating from DImode to SImode. | |
136 | ||
137 | (define_predicate "arith_reg_dest" | |
138 | (match_code "subreg,reg") | |
139 | { | |
140 | if (mode == DImode && GET_CODE (op) == SUBREG | |
141 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8 | |
142 | && TARGET_SHMEDIA) | |
143 | return 0; | |
144 | return arith_reg_operand (op, mode); | |
145 | }) | |
146 | ||
147 | ;; Returns 1 if OP is a normal arithmetic register. | |
148 | ||
149 | (define_predicate "arith_reg_operand" | |
150 | (match_code "subreg,reg,sign_extend") | |
151 | { | |
152 | if (register_operand (op, mode)) | |
153 | { | |
154 | int regno; | |
155 | ||
cbb16986 | 156 | if (REG_P (op)) |
138814fb | 157 | regno = REGNO (op); |
cbb16986 | 158 | else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op))) |
138814fb | 159 | regno = REGNO (SUBREG_REG (op)); |
160 | else | |
161 | return 1; | |
162 | ||
163 | return (regno != T_REG && regno != PR_REG | |
164 | && ! TARGET_REGISTER_P (regno) | |
165 | && (regno != FPUL_REG || TARGET_SH4) | |
166 | && regno != MACH_REG && regno != MACL_REG); | |
167 | } | |
168 | /* Allow a no-op sign extension - compare LOAD_EXTEND_OP. | |
169 | We allow SImode here, as not using an FP register is just a matter of | |
170 | proper register allocation. */ | |
171 | if (TARGET_SHMEDIA | |
172 | && GET_MODE (op) == DImode && GET_CODE (op) == SIGN_EXTEND | |
173 | && GET_MODE (XEXP (op, 0)) == SImode | |
174 | && GET_CODE (XEXP (op, 0)) != SUBREG) | |
175 | return register_operand (XEXP (op, 0), VOIDmode); | |
176 | #if 0 /* Can't do this because of PROMOTE_MODE for unsigned vars. */ | |
177 | if (GET_MODE (op) == SImode && GET_CODE (op) == SIGN_EXTEND | |
178 | && GET_MODE (XEXP (op, 0)) == HImode | |
cbb16986 | 179 | && REG_P (XEXP (op, 0)) |
138814fb | 180 | && REGNO (XEXP (op, 0)) <= LAST_GENERAL_REG) |
181 | return register_operand (XEXP (op, 0), VOIDmode); | |
182 | #endif | |
183 | if (GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_INT | |
184 | && GET_CODE (op) == SUBREG | |
185 | && GET_MODE (SUBREG_REG (op)) == DImode | |
186 | && GET_CODE (SUBREG_REG (op)) == SIGN_EXTEND | |
187 | && GET_MODE (XEXP (SUBREG_REG (op), 0)) == SImode | |
188 | && GET_CODE (XEXP (SUBREG_REG (op), 0)) != SUBREG) | |
189 | return register_operand (XEXP (SUBREG_REG (op), 0), VOIDmode); | |
190 | return 0; | |
191 | }) | |
192 | ||
193 | ;; Returns 1 if OP is a valid source operand for a compare insn. | |
194 | ||
195 | (define_predicate "arith_reg_or_0_operand" | |
196 | (match_code "subreg,reg,const_int,const_vector") | |
197 | { | |
198 | if (arith_reg_operand (op, mode)) | |
199 | return 1; | |
200 | ||
abff7a2e | 201 | if (satisfies_constraint_Z (op)) |
138814fb | 202 | return 1; |
203 | ||
204 | return 0; | |
205 | }) | |
206 | ||
207 | ;; TODO: Add a comment here. | |
208 | ||
209 | (define_predicate "binary_float_operator" | |
9f3fa8ba | 210 | (and (match_code "plus,minus,mult,div") |
211 | (match_test "GET_MODE (op) == mode"))) | |
138814fb | 212 | |
213 | ;; TODO: Add a comment here. | |
214 | ||
215 | (define_predicate "binary_logical_operator" | |
9f3fa8ba | 216 | (and (match_code "and,ior,xor") |
217 | (match_test "GET_MODE (op) == mode"))) | |
138814fb | 218 | |
3d533137 | 219 | ;; Return 1 of OP is an address suitable for a cache manipulation operation. |
220 | ;; MODE has the meaning as in address_operand. | |
138814fb | 221 | |
3d533137 | 222 | (define_special_predicate "cache_address_operand" |
138814fb | 223 | (match_code "plus,reg") |
224 | { | |
225 | if (GET_CODE (op) == PLUS) | |
226 | { | |
cbb16986 | 227 | if (!REG_P (XEXP (op, 0))) |
138814fb | 228 | return 0; |
cbb16986 | 229 | if (!CONST_INT_P (XEXP (op, 1)) |
138814fb | 230 | || (INTVAL (XEXP (op, 1)) & 31)) |
231 | return 0; | |
232 | } | |
cbb16986 | 233 | else if (!REG_P (op)) |
138814fb | 234 | return 0; |
235 | return address_operand (op, mode); | |
236 | }) | |
237 | ||
238 | ;; Return 1 if OP is a valid source operand for shmedia cmpgt / cmpgtu. | |
239 | ||
240 | (define_predicate "cmp_operand" | |
241 | (match_code "subreg,reg,const_int") | |
242 | { | |
abff7a2e | 243 | if (satisfies_constraint_N (op)) |
138814fb | 244 | return 1; |
245 | if (TARGET_SHMEDIA | |
246 | && mode != DImode && GET_CODE (op) == SUBREG | |
247 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) | |
248 | return 0; | |
249 | return arith_reg_operand (op, mode); | |
250 | }) | |
251 | ||
252 | ;; TODO: Add a comment here. | |
253 | ||
254 | (define_predicate "cmpsi_operand" | |
255 | (match_code "subreg,reg,const_int") | |
256 | { | |
cbb16986 | 257 | if (REG_P (op) && REGNO (op) == T_REG |
138814fb | 258 | && GET_MODE (op) == SImode |
259 | && TARGET_SH1) | |
260 | return 1; | |
261 | return arith_operand (op, mode); | |
262 | }) | |
263 | ||
264 | ;; TODO: Add a comment here. | |
265 | ||
266 | (define_predicate "commutative_float_operator" | |
9f3fa8ba | 267 | (and (match_code "plus,mult") |
268 | (match_test "GET_MODE (op) == mode"))) | |
138814fb | 269 | |
270 | ;; TODO: Add a comment here. | |
271 | ||
272 | (define_predicate "equality_comparison_operator" | |
9f3fa8ba | 273 | (match_code "eq,ne")) |
138814fb | 274 | |
275 | ;; TODO: Add a comment here. | |
276 | ||
277 | (define_predicate "extend_reg_operand" | |
278 | (match_code "subreg,reg,truncate") | |
279 | { | |
280 | return (GET_CODE (op) == TRUNCATE | |
281 | ? arith_operand | |
282 | : arith_reg_operand) (op, mode); | |
283 | }) | |
284 | ||
285 | ;; TODO: Add a comment here. | |
286 | ||
287 | (define_predicate "extend_reg_or_0_operand" | |
288 | (match_code "subreg,reg,truncate,const_int") | |
289 | { | |
290 | return (GET_CODE (op) == TRUNCATE | |
291 | ? arith_operand | |
292 | : arith_reg_or_0_operand) (op, mode); | |
293 | }) | |
294 | ||
295 | ;; Like arith_reg_operand, but this predicate does not accept SIGN_EXTEND. | |
296 | ||
297 | (define_predicate "ext_dest_operand" | |
298 | (match_code "subreg,reg") | |
299 | { | |
300 | return arith_reg_operand (op, mode); | |
301 | }) | |
302 | ||
303 | ;; TODO: Add a comment here. | |
304 | ||
305 | (define_predicate "fp_arith_reg_dest" | |
306 | (match_code "subreg,reg") | |
307 | { | |
308 | if (mode == DImode && GET_CODE (op) == SUBREG | |
309 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8) | |
310 | return 0; | |
311 | return fp_arith_reg_operand (op, mode); | |
312 | }) | |
313 | ||
314 | ;; TODO: Add a comment here. | |
315 | ||
316 | (define_predicate "fp_arith_reg_operand" | |
317 | (match_code "subreg,reg") | |
318 | { | |
319 | if (register_operand (op, mode)) | |
320 | { | |
321 | int regno; | |
322 | ||
cbb16986 | 323 | if (REG_P (op)) |
138814fb | 324 | regno = REGNO (op); |
cbb16986 | 325 | else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op))) |
138814fb | 326 | regno = REGNO (SUBREG_REG (op)); |
327 | else | |
328 | return 1; | |
329 | ||
330 | return (regno >= FIRST_PSEUDO_REGISTER | |
331 | || FP_REGISTER_P (regno)); | |
332 | } | |
333 | return 0; | |
334 | }) | |
335 | ||
336 | ;; TODO: Add a comment here. | |
337 | ||
338 | (define_predicate "fpscr_operand" | |
339 | (match_code "reg") | |
340 | { | |
cbb16986 | 341 | return (REG_P (op) |
138814fb | 342 | && (REGNO (op) == FPSCR_REG |
343 | || (REGNO (op) >= FIRST_PSEUDO_REGISTER | |
344 | && !(reload_in_progress || reload_completed))) | |
345 | && GET_MODE (op) == PSImode); | |
346 | }) | |
347 | ||
14c9d678 | 348 | ;; Returns true if OP is an operand that is either the fpul hard reg or |
349 | ;; a pseudo. This prevents combine from propagating function arguments | |
350 | ;; in hard regs into insns that need the operand in fpul. If it's a pseudo | |
351 | ;; reload can fix it up. | |
138814fb | 352 | (define_predicate "fpul_operand" |
353 | (match_code "reg") | |
354 | { | |
355 | if (TARGET_SHMEDIA) | |
356 | return fp_arith_reg_operand (op, mode); | |
357 | ||
cbb16986 | 358 | return (REG_P (op) |
138814fb | 359 | && (REGNO (op) == FPUL_REG || REGNO (op) >= FIRST_PSEUDO_REGISTER) |
360 | && GET_MODE (op) == mode); | |
361 | }) | |
362 | ||
14c9d678 | 363 | ;; Returns true if OP is a valid fpul input operand for the fsca insn. |
364 | ;; The value in fpul is a fixed-point value and its scaling is described | |
365 | ;; in the fsca insn by a mult:SF. To allow pre-scaled fixed-point inputs | |
366 | ;; in fpul we have to permit things like | |
367 | ;; (reg:SI) | |
368 | ;; (fix:SF (float:SF (reg:SI))) | |
369 | (define_predicate "fpul_fsca_operand" | |
370 | (match_code "fix,reg") | |
371 | { | |
372 | if (fpul_operand (op, SImode)) | |
373 | return true; | |
374 | if (GET_CODE (op) == FIX && GET_MODE (op) == SImode | |
375 | && GET_CODE (XEXP (op, 0)) == FLOAT && GET_MODE (XEXP (op, 0)) == SFmode) | |
376 | return fpul_fsca_operand (XEXP (XEXP (op, 0), 0), | |
377 | GET_MODE (XEXP (XEXP (op, 0), 0))); | |
378 | return false; | |
379 | }) | |
380 | ||
381 | ;; Returns true if OP is a valid constant scale factor for the fsca insn. | |
382 | (define_predicate "fsca_scale_factor" | |
383 | (and (match_code "const_double") | |
384 | (match_test "op == sh_fsca_int2sf ()"))) | |
385 | ||
138814fb | 386 | ;; TODO: Add a comment here. |
387 | ||
388 | (define_predicate "general_extend_operand" | |
389 | (match_code "subreg,reg,mem,truncate") | |
390 | { | |
391 | return (GET_CODE (op) == TRUNCATE | |
392 | ? arith_operand | |
393 | : nonimmediate_operand) (op, mode); | |
394 | }) | |
395 | ||
031c81fb | 396 | ;; Returns 1 if OP is a simple register address. |
397 | (define_predicate "simple_mem_operand" | |
398 | (and (match_code "mem") | |
399 | (match_test "arith_reg_operand (XEXP (op, 0), SImode)"))) | |
400 | ||
401 | ;; Returns 1 if OP is a valid displacement address. | |
402 | (define_predicate "displacement_mem_operand" | |
403 | (and (match_code "mem") | |
404 | (match_test "GET_CODE (XEXP (op, 0)) == PLUS") | |
405 | (match_test "arith_reg_operand (XEXP (XEXP (op, 0), 0), SImode)") | |
406 | (match_test "sh_legitimate_index_p (GET_MODE (op), | |
407 | XEXP (XEXP (op, 0), 1), | |
408 | TARGET_SH2A, true)"))) | |
409 | ||
410 | ;; Returns 1 if the operand can be used in an SH2A movu.{b|w} insn. | |
411 | (define_predicate "zero_extend_movu_operand" | |
412 | (and (match_operand 0 "displacement_mem_operand") | |
413 | (match_test "GET_MODE (op) == QImode || GET_MODE (op) == HImode"))) | |
414 | ||
392e1ee8 | 415 | ;; Returns 1 if the operand can be used in a zero_extend. |
416 | (define_predicate "zero_extend_operand" | |
417 | (ior (and (match_test "TARGET_SHMEDIA") | |
418 | (match_operand 0 "general_extend_operand")) | |
419 | (and (match_test "! TARGET_SHMEDIA") | |
031c81fb | 420 | (match_operand 0 "arith_reg_operand")) |
421 | (and (match_test "TARGET_SH2A") | |
422 | (match_operand 0 "zero_extend_movu_operand")))) | |
392e1ee8 | 423 | |
138814fb | 424 | ;; Returns 1 if OP can be source of a simple move operation. Same as |
425 | ;; general_operand, but a LABEL_REF is valid, PRE_DEC is invalid as | |
426 | ;; are subregs of system registers. | |
427 | ||
428 | (define_predicate "general_movsrc_operand" | |
429 | (match_code "subreg,reg,const_int,const_double,mem,symbol_ref,label_ref,const,const_vector") | |
430 | { | |
61af3583 | 431 | if (t_reg_operand (op, mode)) |
432 | return 0; | |
433 | ||
cbb16986 | 434 | if (MEM_P (op)) |
138814fb | 435 | { |
436 | rtx inside = XEXP (op, 0); | |
3ea038fc | 437 | |
438 | /* Disallow mems with GBR address here. They have to go through | |
439 | separate special patterns. */ | |
440 | if ((REG_P (inside) && REGNO (inside) == GBR_REG) | |
441 | || (GET_CODE (inside) == PLUS && REG_P (XEXP (inside, 0)) | |
442 | && REGNO (XEXP (inside, 0)) == GBR_REG)) | |
443 | return 0; | |
444 | ||
138814fb | 445 | if (GET_CODE (inside) == CONST) |
446 | inside = XEXP (inside, 0); | |
447 | ||
448 | if (GET_CODE (inside) == LABEL_REF) | |
449 | return 1; | |
450 | ||
451 | if (GET_CODE (inside) == PLUS | |
452 | && GET_CODE (XEXP (inside, 0)) == LABEL_REF | |
cbb16986 | 453 | && CONST_INT_P (XEXP (inside, 1))) |
138814fb | 454 | return 1; |
455 | ||
456 | /* Only post inc allowed. */ | |
457 | if (GET_CODE (inside) == PRE_DEC) | |
458 | return 0; | |
459 | } | |
460 | ||
cb022464 | 461 | if ((mode == QImode || mode == HImode) |
0c68c6cd | 462 | && mode == GET_MODE (op) |
cb022464 | 463 | && (MEM_P (op) |
464 | || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))))) | |
465 | { | |
466 | rtx x = XEXP ((MEM_P (op) ? op : SUBREG_REG (op)), 0); | |
467 | ||
468 | if (GET_CODE (x) == PLUS | |
469 | && REG_P (XEXP (x, 0)) | |
470 | && CONST_INT_P (XEXP (x, 1))) | |
51bc6b40 | 471 | return sh_legitimate_index_p (mode, XEXP (x, 1), TARGET_SH2A, false); |
cb022464 | 472 | } |
473 | ||
138814fb | 474 | if (TARGET_SHMEDIA |
475 | && (GET_CODE (op) == PARALLEL || GET_CODE (op) == CONST_VECTOR) | |
476 | && sh_rep_vec (op, mode)) | |
477 | return 1; | |
478 | if (TARGET_SHMEDIA && 1 | |
479 | && GET_CODE (op) == SUBREG && GET_MODE (op) == mode | |
480 | && SUBREG_REG (op) == const0_rtx && subreg_lowpart_p (op)) | |
481 | /* FIXME */ abort (); /* return 1; */ | |
482 | return general_operand (op, mode); | |
483 | }) | |
484 | ||
5e8ad22e | 485 | ;; Returns 1 if OP is a MEM that does not use displacement addressing. |
89cace00 | 486 | |
487 | (define_predicate "movsrc_no_disp_mem_operand" | |
5e8ad22e | 488 | (match_code "mem") |
89cace00 | 489 | { |
5e8ad22e | 490 | return general_movsrc_operand (op, mode) && satisfies_constraint_Snd (op); |
89cace00 | 491 | }) |
492 | ||
138814fb | 493 | ;; Returns 1 if OP can be a destination of a move. Same as |
494 | ;; general_operand, but no preinc allowed. | |
495 | ||
496 | (define_predicate "general_movdst_operand" | |
497 | (match_code "subreg,reg,mem") | |
498 | { | |
61af3583 | 499 | if (t_reg_operand (op, mode)) |
500 | return 0; | |
501 | ||
3ea038fc | 502 | if (MEM_P (op)) |
503 | { | |
504 | rtx inside = XEXP (op, 0); | |
505 | /* Disallow mems with GBR address here. They have to go through | |
506 | separate special patterns. */ | |
507 | if ((REG_P (inside) && REGNO (inside) == GBR_REG) | |
508 | || (GET_CODE (inside) == PLUS && REG_P (XEXP (inside, 0)) | |
509 | && REGNO (XEXP (inside, 0)) == GBR_REG)) | |
510 | return 0; | |
511 | } | |
512 | ||
138814fb | 513 | /* Only pre dec allowed. */ |
cbb16986 | 514 | if (MEM_P (op) && GET_CODE (XEXP (op, 0)) == POST_INC) |
138814fb | 515 | return 0; |
516 | if (mode == DImode && TARGET_SHMEDIA && GET_CODE (op) == SUBREG | |
517 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8 | |
278fc7da | 518 | && ! (reload_in_progress || reload_completed)) |
138814fb | 519 | return 0; |
520 | ||
cb022464 | 521 | if ((mode == QImode || mode == HImode) |
0c68c6cd | 522 | && mode == GET_MODE (op) |
cb022464 | 523 | && (MEM_P (op) |
524 | || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))))) | |
525 | { | |
526 | rtx x = XEXP ((MEM_P (op) ? op : SUBREG_REG (op)), 0); | |
527 | ||
528 | if (GET_CODE (x) == PLUS | |
529 | && REG_P (XEXP (x, 0)) | |
530 | && CONST_INT_P (XEXP (x, 1))) | |
51bc6b40 | 531 | return sh_legitimate_index_p (mode, XEXP (x, 1), TARGET_SH2A, false); |
cb022464 | 532 | } |
533 | ||
138814fb | 534 | return general_operand (op, mode); |
535 | }) | |
536 | ||
973cd123 | 537 | ;; Returns 1 if OP is a POST_INC on stack pointer register. |
538 | ||
539 | (define_predicate "sh_no_delay_pop_operand" | |
540 | (match_code "mem") | |
541 | { | |
542 | rtx inside; | |
543 | inside = XEXP (op, 0); | |
544 | ||
545 | if (GET_CODE (op) == MEM && GET_MODE (op) == SImode | |
546 | && GET_CODE (inside) == POST_INC | |
547 | && GET_CODE (XEXP (inside, 0)) == REG | |
548 | && REGNO (XEXP (inside, 0)) == SP_REG) | |
549 | return 1; | |
550 | ||
551 | return 0; | |
552 | }) | |
553 | ||
138814fb | 554 | ;; Returns 1 if OP is a MEM that can be source of a simple move operation. |
555 | ||
556 | (define_predicate "unaligned_load_operand" | |
557 | (match_code "mem") | |
558 | { | |
559 | rtx inside; | |
560 | ||
cbb16986 | 561 | if (!MEM_P (op) || GET_MODE (op) != mode) |
138814fb | 562 | return 0; |
563 | ||
564 | inside = XEXP (op, 0); | |
565 | ||
566 | if (GET_CODE (inside) == POST_INC) | |
567 | inside = XEXP (inside, 0); | |
568 | ||
cbb16986 | 569 | if (REG_P (inside)) |
138814fb | 570 | return 1; |
571 | ||
572 | return 0; | |
573 | }) | |
574 | ||
572e04f2 | 575 | ;; Returns 1 if OP is a MEM that can be used in "index_disp" combiner |
576 | ;; patterns. | |
577 | (define_predicate "mem_index_disp_operand" | |
578 | (match_code "mem") | |
579 | { | |
580 | rtx plus0_rtx, plus1_rtx, mult_rtx; | |
581 | ||
582 | plus0_rtx = XEXP (op, 0); | |
583 | if (GET_CODE (plus0_rtx) != PLUS) | |
584 | return 0; | |
585 | ||
586 | plus1_rtx = XEXP (plus0_rtx, 0); | |
587 | if (GET_CODE (plus1_rtx) != PLUS) | |
588 | return 0; | |
26e8d76f | 589 | if (! arith_reg_operand (XEXP (plus1_rtx, 1), GET_MODE (XEXP (plus1_rtx, 1)))) |
590 | return 0; | |
572e04f2 | 591 | |
592 | mult_rtx = XEXP (plus1_rtx, 0); | |
593 | if (GET_CODE (mult_rtx) != MULT) | |
594 | return 0; | |
26e8d76f | 595 | if (! arith_reg_operand (XEXP (mult_rtx, 0), GET_MODE (XEXP (mult_rtx, 0))) |
596 | || ! CONST_INT_P (XEXP (mult_rtx, 1))) | |
597 | return 0; | |
598 | ||
599 | return exact_log2 (INTVAL (XEXP (mult_rtx, 1))) > 0 | |
572e04f2 | 600 | && sh_legitimate_index_p (mode, XEXP (plus0_rtx, 1), TARGET_SH2A, true); |
601 | }) | |
602 | ||
138814fb | 603 | ;; TODO: Add a comment here. |
604 | ||
605 | (define_predicate "greater_comparison_operator" | |
9f3fa8ba | 606 | (match_code "gt,ge,gtu,geu")) |
138814fb | 607 | |
608 | ;; TODO: Add a comment here. | |
609 | ||
610 | (define_predicate "inqhi_operand" | |
611 | (match_code "truncate") | |
612 | { | |
613 | if (GET_CODE (op) != TRUNCATE || mode != GET_MODE (op)) | |
614 | return 0; | |
615 | op = XEXP (op, 0); | |
616 | /* Can't use true_regnum here because copy_cost wants to know about | |
617 | SECONDARY_INPUT_RELOAD_CLASS. */ | |
cbb16986 | 618 | return REG_P (op) && FP_REGISTER_P (REGNO (op)); |
138814fb | 619 | }) |
620 | ||
621 | ;; TODO: Add a comment here. | |
622 | ||
623 | (define_special_predicate "int_gpr_dest" | |
624 | (match_code "subreg,reg") | |
625 | { | |
626 | enum machine_mode op_mode = GET_MODE (op); | |
627 | ||
628 | if (GET_MODE_CLASS (op_mode) != MODE_INT | |
629 | || GET_MODE_SIZE (op_mode) >= UNITS_PER_WORD) | |
630 | return 0; | |
631 | if (! reload_completed) | |
632 | return 0; | |
633 | return true_regnum (op) <= LAST_GENERAL_REG; | |
634 | }) | |
635 | ||
636 | ;; TODO: Add a comment here. | |
637 | ||
638 | (define_predicate "less_comparison_operator" | |
9f3fa8ba | 639 | (match_code "lt,le,ltu,leu")) |
138814fb | 640 | |
641 | ;; Returns 1 if OP is a valid source operand for a logical operation. | |
642 | ||
643 | (define_predicate "logical_operand" | |
644 | (match_code "subreg,reg,const_int") | |
645 | { | |
646 | if (TARGET_SHMEDIA | |
647 | && mode != DImode && GET_CODE (op) == SUBREG | |
648 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) | |
649 | return 0; | |
650 | ||
651 | if (arith_reg_operand (op, mode)) | |
652 | return 1; | |
653 | ||
654 | if (TARGET_SHMEDIA) | |
655 | { | |
abff7a2e | 656 | if (satisfies_constraint_I10 (op)) |
138814fb | 657 | return 1; |
658 | else | |
659 | return 0; | |
660 | } | |
abff7a2e | 661 | else if (satisfies_constraint_K08 (op)) |
138814fb | 662 | return 1; |
663 | ||
664 | return 0; | |
665 | }) | |
666 | ||
48d72ad2 | 667 | ;; Like logical_operand but allows additional constant values which can be |
668 | ;; done with zero extensions. Used for the second operand of and insns. | |
669 | (define_predicate "logical_and_operand" | |
670 | (match_code "subreg,reg,const_int") | |
671 | { | |
672 | if (logical_operand (op, mode)) | |
673 | return 1; | |
674 | ||
675 | if (! TARGET_SHMEDIA | |
676 | && (satisfies_constraint_Jmb (op) || satisfies_constraint_Jmw (op))) | |
677 | return 1; | |
678 | ||
679 | return 0; | |
680 | }) | |
681 | ||
138814fb | 682 | ;; TODO: Add a comment here. |
683 | ||
684 | (define_predicate "logical_operator" | |
9f3fa8ba | 685 | (match_code "and,ior,xor")) |
138814fb | 686 | |
687 | ;; Like arith_reg_operand, but for register source operands of narrow | |
688 | ;; logical SHMEDIA operations: forbid subregs of DImode / TImode regs. | |
689 | ||
690 | (define_predicate "logical_reg_operand" | |
691 | (match_code "subreg,reg") | |
692 | { | |
693 | if (TARGET_SHMEDIA | |
694 | && GET_CODE (op) == SUBREG | |
695 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4 | |
696 | && mode != DImode) | |
697 | return 0; | |
698 | return arith_reg_operand (op, mode); | |
699 | }) | |
700 | ||
701 | ;; TODO: Add a comment here. | |
702 | ||
703 | (define_predicate "mextr_bit_offset" | |
704 | (match_code "const_int") | |
705 | { | |
706 | HOST_WIDE_INT i; | |
707 | ||
cbb16986 | 708 | if (!CONST_INT_P (op)) |
138814fb | 709 | return 0; |
710 | i = INTVAL (op); | |
711 | return i >= 1 * 8 && i <= 7 * 8 && (i & 7) == 0; | |
712 | }) | |
713 | ||
714 | ;; TODO: Add a comment here. | |
715 | ||
716 | (define_predicate "minuend_operand" | |
717 | (match_code "subreg,reg,truncate,const_int") | |
718 | { | |
719 | return op == constm1_rtx || extend_reg_or_0_operand (op, mode); | |
720 | }) | |
721 | ||
722 | ;; TODO: Add a comment here. | |
723 | ||
724 | (define_predicate "noncommutative_float_operator" | |
9f3fa8ba | 725 | (and (match_code "minus,div") |
726 | (match_test "GET_MODE (op) == mode"))) | |
138814fb | 727 | |
74f4459c | 728 | ;; UNORDERED is only supported on SHMEDIA. |
729 | ||
730 | (define_predicate "sh_float_comparison_operator" | |
731 | (ior (match_operand 0 "ordered_comparison_operator") | |
732 | (and (match_test "TARGET_SHMEDIA") | |
733 | (match_code "unordered")))) | |
734 | ||
735 | (define_predicate "shmedia_cbranch_comparison_operator" | |
736 | (ior (match_operand 0 "equality_comparison_operator") | |
737 | (match_operand 0 "greater_comparison_operator"))) | |
738 | ||
138814fb | 739 | ;; TODO: Add a comment here. |
740 | ||
741 | (define_predicate "sh_const_vec" | |
742 | (match_code "const_vector") | |
743 | { | |
744 | int i; | |
745 | ||
746 | if (GET_CODE (op) != CONST_VECTOR | |
747 | || (GET_MODE (op) != mode && mode != VOIDmode)) | |
748 | return 0; | |
749 | i = XVECLEN (op, 0) - 1; | |
750 | for (; i >= 0; i--) | |
cbb16986 | 751 | if (!CONST_INT_P (XVECEXP (op, 0, i))) |
138814fb | 752 | return 0; |
753 | return 1; | |
754 | }) | |
755 | ||
756 | ;; Determine if OP is a constant vector matching MODE with only one | |
757 | ;; element that is not a sign extension. Two byte-sized elements | |
758 | ;; count as one. | |
759 | ||
760 | (define_predicate "sh_1el_vec" | |
761 | (match_code "const_vector") | |
762 | { | |
763 | int unit_size; | |
764 | int i, last, least, sign_ix; | |
765 | rtx sign; | |
766 | ||
767 | if (GET_CODE (op) != CONST_VECTOR | |
768 | || (GET_MODE (op) != mode && mode != VOIDmode)) | |
769 | return 0; | |
770 | /* Determine numbers of last and of least significant elements. */ | |
771 | last = XVECLEN (op, 0) - 1; | |
772 | least = TARGET_LITTLE_ENDIAN ? 0 : last; | |
cbb16986 | 773 | if (!CONST_INT_P (XVECEXP (op, 0, least))) |
138814fb | 774 | return 0; |
775 | sign_ix = least; | |
776 | if (GET_MODE_UNIT_SIZE (mode) == 1) | |
777 | sign_ix = TARGET_LITTLE_ENDIAN ? 1 : last - 1; | |
cbb16986 | 778 | if (!CONST_INT_P (XVECEXP (op, 0, sign_ix))) |
138814fb | 779 | return 0; |
780 | unit_size = GET_MODE_UNIT_SIZE (GET_MODE (op)); | |
781 | sign = (INTVAL (XVECEXP (op, 0, sign_ix)) >> (unit_size * BITS_PER_UNIT - 1) | |
782 | ? constm1_rtx : const0_rtx); | |
783 | i = XVECLEN (op, 0) - 1; | |
784 | do | |
785 | if (i != least && i != sign_ix && XVECEXP (op, 0, i) != sign) | |
786 | return 0; | |
787 | while (--i); | |
788 | return 1; | |
789 | }) | |
790 | ||
791 | ;; Like register_operand, but take into account that SHMEDIA can use | |
792 | ;; the constant zero like a general register. | |
793 | ||
794 | (define_predicate "sh_register_operand" | |
81aeb577 | 795 | (match_code "reg,subreg,const_int,const_double") |
138814fb | 796 | { |
797 | if (op == CONST0_RTX (mode) && TARGET_SHMEDIA) | |
798 | return 1; | |
799 | return register_operand (op, mode); | |
800 | }) | |
801 | ||
802 | ;; TODO: Add a comment here. | |
803 | ||
804 | (define_predicate "sh_rep_vec" | |
5a9f17cc | 805 | (match_code "const_vector,parallel") |
138814fb | 806 | { |
807 | int i; | |
808 | rtx x, y; | |
809 | ||
810 | if ((GET_CODE (op) != CONST_VECTOR && GET_CODE (op) != PARALLEL) | |
811 | || (GET_MODE (op) != mode && mode != VOIDmode)) | |
812 | return 0; | |
813 | i = XVECLEN (op, 0) - 2; | |
814 | x = XVECEXP (op, 0, i + 1); | |
815 | if (GET_MODE_UNIT_SIZE (mode) == 1) | |
816 | { | |
817 | y = XVECEXP (op, 0, i); | |
818 | for (i -= 2; i >= 0; i -= 2) | |
819 | if (! rtx_equal_p (XVECEXP (op, 0, i + 1), x) | |
820 | || ! rtx_equal_p (XVECEXP (op, 0, i), y)) | |
821 | return 0; | |
822 | } | |
823 | else | |
824 | for (; i >= 0; i--) | |
825 | if (XVECEXP (op, 0, i) != x) | |
826 | return 0; | |
827 | return 1; | |
828 | }) | |
829 | ||
830 | ;; TODO: Add a comment here. | |
831 | ||
832 | (define_predicate "shift_count_operand" | |
833 | (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,zero_extend,sign_extend") | |
834 | { | |
bb8e9728 | 835 | /* Allow T_REG as shift count for dynamic shifts, although it is not |
836 | really possible. It will then be copied to a general purpose reg. */ | |
837 | if (! TARGET_SHMEDIA) | |
6e7c6395 | 838 | return const_int_operand (op, mode) || arith_reg_operand (op, mode) |
839 | || (TARGET_DYNSHIFT && t_reg_operand (op, mode)); | |
bb8e9728 | 840 | |
138814fb | 841 | return (CONSTANT_P (op) |
cbb16986 | 842 | ? (CONST_INT_P (op) |
138814fb | 843 | ? (unsigned) INTVAL (op) < GET_MODE_BITSIZE (mode) |
844 | : nonmemory_operand (op, mode)) | |
845 | : shift_count_reg_operand (op, mode)); | |
846 | }) | |
847 | ||
848 | ;; TODO: Add a comment here. | |
849 | ||
850 | (define_predicate "shift_count_reg_operand" | |
851 | (match_code "subreg,reg,zero_extend,sign_extend") | |
852 | { | |
853 | if ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND | |
854 | || (GET_CODE (op) == SUBREG && SUBREG_BYTE (op) == 0)) | |
855 | && (mode == VOIDmode || mode == GET_MODE (op)) | |
856 | && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6 | |
857 | && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT) | |
858 | { | |
859 | mode = VOIDmode; | |
860 | do | |
861 | op = XEXP (op, 0); | |
862 | while ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND | |
863 | || GET_CODE (op) == TRUNCATE) | |
864 | && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6 | |
865 | && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT); | |
866 | ||
867 | } | |
868 | return arith_reg_operand (op, mode); | |
869 | }) | |
870 | ||
be3ab97a | 871 | ;; Predicates for matching operands that are constant shift |
872 | ;; amounts 1, 2, 8, 16. | |
bb8e9728 | 873 | (define_predicate "p27_shift_count_operand" |
874 | (and (match_code "const_int") | |
875 | (match_test "satisfies_constraint_P27 (op)"))) | |
876 | ||
877 | (define_predicate "not_p27_shift_count_operand" | |
878 | (and (match_code "const_int") | |
879 | (match_test "! satisfies_constraint_P27 (op)"))) | |
880 | ||
be3ab97a | 881 | ;; For right shifts the constant 1 is a special case because the shlr insn |
882 | ;; clobbers the T_REG and is handled by the T_REG clobbering version of the | |
883 | ;; insn, which is also used for non-P27 shift sequences. | |
884 | (define_predicate "p27_rshift_count_operand" | |
885 | (and (match_code "const_int") | |
886 | (match_test "satisfies_constraint_P27 (op)") | |
887 | (match_test "! satisfies_constraint_M (op)"))) | |
888 | ||
889 | (define_predicate "not_p27_rshift_count_operand" | |
890 | (and (match_code "const_int") | |
891 | (ior (match_test "! satisfies_constraint_P27 (op)") | |
892 | (match_test "satisfies_constraint_M (op)")))) | |
893 | ||
138814fb | 894 | ;; TODO: Add a comment here. |
895 | ||
896 | (define_predicate "shift_operator" | |
9f3fa8ba | 897 | (match_code "ashift,ashiftrt,lshiftrt")) |
138814fb | 898 | |
899 | ;; TODO: Add a comment here. | |
900 | ||
901 | (define_predicate "symbol_ref_operand" | |
9f3fa8ba | 902 | (match_code "symbol_ref")) |
138814fb | 903 | |
904 | ;; Same as target_reg_operand, except that label_refs and symbol_refs | |
905 | ;; are accepted before reload. | |
906 | ||
907 | (define_special_predicate "target_operand" | |
908 | (match_code "subreg,reg,label_ref,symbol_ref,const,unspec") | |
909 | { | |
910 | if (mode != VOIDmode && mode != Pmode) | |
911 | return 0; | |
912 | ||
913 | if ((GET_MODE (op) == Pmode || GET_MODE (op) == VOIDmode) | |
abff7a2e | 914 | && satisfies_constraint_Csy (op)) |
138814fb | 915 | return ! reload_completed; |
916 | ||
917 | return target_reg_operand (op, mode); | |
918 | }) | |
919 | ||
920 | ;; Accept pseudos and branch target registers. | |
921 | ||
922 | (define_special_predicate "target_reg_operand" | |
923 | (match_code "subreg,reg") | |
924 | { | |
925 | if (mode == VOIDmode | |
926 | ? GET_MODE (op) != Pmode && GET_MODE (op) != PDImode | |
927 | : mode != GET_MODE (op)) | |
928 | return 0; | |
929 | ||
930 | if (GET_CODE (op) == SUBREG) | |
931 | op = XEXP (op, 0); | |
932 | ||
cbb16986 | 933 | if (!REG_P (op)) |
138814fb | 934 | return 0; |
935 | ||
936 | /* We must protect ourselves from matching pseudos that are virtual | |
937 | register, because they will eventually be replaced with hardware | |
938 | registers that aren't branch-target registers. */ | |
939 | if (REGNO (op) > LAST_VIRTUAL_REGISTER | |
940 | || TARGET_REGISTER_P (REGNO (op))) | |
941 | return 1; | |
942 | ||
943 | return 0; | |
944 | }) | |
945 | ||
946 | ;; TODO: Add a comment here. | |
947 | ||
948 | (define_special_predicate "trunc_hi_operand" | |
949 | (match_code "subreg,reg,truncate") | |
950 | { | |
951 | enum machine_mode op_mode = GET_MODE (op); | |
952 | ||
953 | if (op_mode != SImode && op_mode != DImode | |
954 | && op_mode != V4HImode && op_mode != V2SImode) | |
955 | return 0; | |
956 | return extend_reg_operand (op, mode); | |
957 | }) | |
958 | ||
3d533137 | 959 | ;; Return 1 of OP is an address suitable for an unaligned access instruction. |
138814fb | 960 | |
3d533137 | 961 | (define_special_predicate "ua_address_operand" |
138814fb | 962 | (match_code "subreg,reg,plus") |
963 | { | |
964 | if (GET_CODE (op) == PLUS | |
abff7a2e | 965 | && (! satisfies_constraint_I06 (XEXP (op, 1)))) |
138814fb | 966 | return 0; |
967 | return address_operand (op, QImode); | |
968 | }) | |
969 | ||
970 | ;; TODO: Add a comment here. | |
971 | ||
972 | (define_predicate "ua_offset" | |
973 | (match_code "const_int") | |
974 | { | |
abff7a2e | 975 | return satisfies_constraint_I06 (op); |
138814fb | 976 | }) |
977 | ||
978 | ;; TODO: Add a comment here. | |
979 | ||
980 | (define_predicate "unary_float_operator" | |
9f3fa8ba | 981 | (and (match_code "abs,neg,sqrt") |
982 | (match_test "GET_MODE (op) == mode"))) | |
138814fb | 983 | |
984 | ;; Return 1 if OP is a valid source operand for xor. | |
985 | ||
986 | (define_predicate "xor_operand" | |
987 | (match_code "subreg,reg,const_int") | |
988 | { | |
cbb16986 | 989 | if (CONST_INT_P (op)) |
138814fb | 990 | return (TARGET_SHMEDIA |
abff7a2e | 991 | ? (satisfies_constraint_I06 (op) |
e1ba4a27 | 992 | || (!can_create_pseudo_p () && INTVAL (op) == 0xff)) |
abff7a2e | 993 | : satisfies_constraint_K08 (op)); |
138814fb | 994 | if (TARGET_SHMEDIA |
995 | && mode != DImode && GET_CODE (op) == SUBREG | |
996 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) | |
997 | return 0; | |
998 | return arith_reg_operand (op, mode); | |
999 | }) | |
96a7f216 | 1000 | |
1001 | (define_predicate "bitwise_memory_operand" | |
1002 | (match_code "mem") | |
1003 | { | |
cbb16986 | 1004 | if (MEM_P (op)) |
96a7f216 | 1005 | { |
1006 | if (REG_P (XEXP (op, 0))) | |
1007 | return 1; | |
1008 | ||
1009 | if (GET_CODE (XEXP (op, 0)) == PLUS | |
cbb16986 | 1010 | && REG_P (XEXP (XEXP (op, 0), 0)) |
96a7f216 | 1011 | && satisfies_constraint_K12 (XEXP (XEXP (op, 0), 1))) |
1012 | return 1; | |
1013 | } | |
1014 | return 0; | |
1015 | }) | |
e10782c9 | 1016 | |
1017 | ;; The atomic_* operand predicates are used for the atomic patterns. | |
1018 | ;; Depending on the particular pattern some operands can be immediate | |
1019 | ;; values. Using these predicates avoids the usage of 'force_reg' in the | |
1020 | ;; expanders. | |
1021 | (define_predicate "atomic_arith_operand" | |
1022 | (ior (match_code "subreg,reg") | |
1023 | (and (match_test "satisfies_constraint_I08 (op)") | |
1024 | (match_test "mode != QImode") | |
1025 | (match_test "mode != HImode") | |
1026 | (match_test "TARGET_SH4A_ARCH")))) | |
1027 | ||
1028 | (define_predicate "atomic_logical_operand" | |
1029 | (ior (match_code "subreg,reg") | |
1030 | (and (match_test "satisfies_constraint_K08 (op)") | |
1031 | (match_test "mode != QImode") | |
1032 | (match_test "mode != HImode") | |
1033 | (match_test "TARGET_SH4A_ARCH")))) | |
1034 | ||
a6be7821 | 1035 | ;; A predicate describing the T bit register in any form. |
1036 | (define_predicate "t_reg_operand" | |
1037 | (match_code "reg,subreg,sign_extend,zero_extend") | |
1038 | { | |
1039 | switch (GET_CODE (op)) | |
1040 | { | |
1041 | case REG: | |
1042 | return REGNO (op) == T_REG; | |
1043 | ||
1044 | case SUBREG: | |
c53274a5 | 1045 | return REG_P (SUBREG_REG (op)) && REGNO (SUBREG_REG (op)) == T_REG; |
a6be7821 | 1046 | |
1047 | case ZERO_EXTEND: | |
1048 | case SIGN_EXTEND: | |
1049 | return GET_CODE (XEXP (op, 0)) == SUBREG | |
c53274a5 | 1050 | && REG_P (SUBREG_REG (XEXP (op, 0))) |
a6be7821 | 1051 | && REGNO (SUBREG_REG (XEXP (op, 0))) == T_REG; |
1052 | ||
1053 | default: | |
1054 | return 0; | |
1055 | } | |
1056 | }) | |
1057 | ||
1058 | ;; A predicate describing a negated T bit register. | |
1059 | (define_predicate "negt_reg_operand" | |
1060 | (match_code "subreg,xor") | |
1061 | { | |
1062 | switch (GET_CODE (op)) | |
1063 | { | |
1064 | case XOR: | |
1065 | return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0))) | |
1066 | && satisfies_constraint_M (XEXP (op, 1)); | |
1067 | ||
1068 | case SUBREG: | |
1069 | return negt_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0))); | |
1070 | ||
1071 | default: | |
1072 | return 0; | |
1073 | } | |
1074 | }) | |
1e94341b | 1075 | |
21910658 | 1076 | ;; A predicate that returns true if OP is a valid construct around the T bit |
1077 | ;; that can be used as an operand for conditional branches. | |
1078 | (define_predicate "cbranch_treg_value" | |
1079 | (match_code "eq,ne,reg,subreg,xor,sign_extend,zero_extend") | |
1080 | { | |
1081 | return sh_eval_treg_value (op) >= 0; | |
1082 | }) | |
1083 | ||
1e94341b | 1084 | ;; Returns true of OP is arith_reg_operand or t_reg_operand. |
1085 | (define_predicate "arith_reg_or_t_reg_operand" | |
1086 | (ior (match_operand 0 "arith_reg_operand") | |
1087 | (match_operand 0 "t_reg_operand"))) | |
4d6e7ebc | 1088 | |
1089 | ;; A predicate describing the negated value of the T bit register shifted | |
1090 | ;; left by 31. | |
1091 | (define_predicate "negt_reg_shl31_operand" | |
1092 | (match_code "plus,minus,if_then_else") | |
1093 | { | |
1094 | /* (plus:SI (mult:SI (match_operand:SI 1 "t_reg_operand") | |
1095 | (const_int -2147483648)) ;; 0xffffffff80000000 | |
1096 | (const_int -2147483648)) | |
1097 | */ | |
1098 | if (GET_CODE (op) == PLUS && satisfies_constraint_Jhb (XEXP (op, 1)) | |
1099 | && GET_CODE (XEXP (op, 0)) == MULT | |
1100 | && t_reg_operand (XEXP (XEXP (op, 0), 0), SImode) | |
1101 | && satisfies_constraint_Jhb (XEXP (XEXP (op, 0), 1))) | |
1102 | return true; | |
1103 | ||
1104 | /* (minus:SI (const_int -2147483648) ;; 0xffffffff80000000 | |
1105 | (mult:SI (match_operand:SI 1 "t_reg_operand") | |
1106 | (const_int -2147483648))) | |
1107 | */ | |
1108 | if (GET_CODE (op) == MINUS | |
1109 | && satisfies_constraint_Jhb (XEXP (op, 0)) | |
1110 | && GET_CODE (XEXP (op, 1)) == MULT | |
1111 | && t_reg_operand (XEXP (XEXP (op, 1), 0), SImode) | |
1112 | && satisfies_constraint_Jhb (XEXP (XEXP (op, 1), 1))) | |
1113 | return true; | |
1114 | ||
1115 | /* (if_then_else:SI (match_operand:SI 1 "t_reg_operand") | |
1116 | (const_int 0) | |
1117 | (const_int -2147483648)) ;; 0xffffffff80000000 | |
1118 | */ | |
1119 | if (GET_CODE (op) == IF_THEN_ELSE && t_reg_operand (XEXP (op, 0), SImode) | |
1120 | && satisfies_constraint_Z (XEXP (op, 1)) | |
1121 | && satisfies_constraint_Jhb (XEXP (op, 2))) | |
1122 | return true; | |
1123 | ||
1124 | return false; | |
1125 | }) | |
7928e854 | 1126 | |
1127 | ;; A predicate that determines whether a given constant is a valid | |
1128 | ;; displacement for a gbr load/store of the specified mode. | |
1129 | (define_predicate "gbr_displacement" | |
1130 | (match_code "const_int") | |
1131 | { | |
1132 | const int mode_sz = GET_MODE_SIZE (mode); | |
1133 | const int move_sz = mode_sz > GET_MODE_SIZE (SImode) | |
1134 | ? GET_MODE_SIZE (SImode) | |
1135 | : mode_sz; | |
1136 | int max_disp = 255 * move_sz; | |
1137 | if (mode_sz > move_sz) | |
1138 | max_disp -= mode_sz - move_sz; | |
1139 | ||
1140 | return INTVAL (op) >= 0 && INTVAL (op) <= max_disp; | |
1141 | }) | |
8b6f9b96 | 1142 | |
1143 | ;; A predicate that determines whether OP is a valid GBR addressing mode | |
1144 | ;; memory reference. | |
1145 | (define_predicate "gbr_address_mem" | |
1146 | (match_code "mem") | |
1147 | { | |
1148 | rtx addr = XEXP (op, 0); | |
1149 | ||
1150 | if (REG_P (addr) && REGNO (addr) == GBR_REG) | |
1151 | return true; | |
1152 | if (GET_CODE (addr) == PLUS | |
1153 | && REG_P (XEXP (addr, 0)) && REGNO (XEXP (addr, 0)) == GBR_REG | |
1154 | && gbr_displacement (XEXP (addr, 1), mode)) | |
1155 | return true; | |
1156 | ||
1157 | return false; | |
1158 | }) |