]>
Commit | Line | Data |
---|---|---|
5546ac90 | 1 | ;; Predicate definitions for Renesas / SuperH SH. |
1ce35c11 | 2 | ;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 |
c11c09f9 | 3 | ;; Free Software Foundation, Inc. |
5546ac90 KH |
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 | |
2f83c7d6 | 9 | ;; the Free Software Foundation; either version 3, or (at your option) |
5546ac90 KH |
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 | |
2f83c7d6 NC |
18 | ;; along with GCC; see the file COPYING3. If not see |
19 | ;; <http://www.gnu.org/licenses/>. | |
5546ac90 KH |
20 | |
21 | ;; TODO: Add a comment here. | |
22 | ||
73a4d10b R |
23 | (define_predicate "trapping_target_operand" |
24 | (match_code "if_then_else") | |
25 | { | |
5a82ecd9 | 26 | rtx cond, mem, res, tar, and_expr; |
73a4d10b R |
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); | |
f3536097 | 33 | if (!MEM_P (mem) |
73a4d10b R |
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); | |
32a7ab3d | 43 | if (!satisfies_constraint_Csy (tar)) |
73a4d10b R |
44 | return 0; |
45 | if (GET_CODE (tar) == CONST) | |
46 | tar = XEXP (tar, 0); | |
47 | } | |
48 | else if (!arith_reg_operand (tar, VOIDmode) | |
32a7ab3d | 49 | && ! satisfies_constraint_Csy (tar)) |
73a4d10b R |
50 | return 0; |
51 | if (GET_CODE (cond) != EQ) | |
52 | return 0; | |
5a82ecd9 ILT |
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)) | |
f3536097 | 57 | && CONST_INT_P (XEXP (cond, 1)) |
5a82ecd9 | 58 | && INTVAL (XEXP (and_expr, 1)) == 3 |
73a4d10b R |
59 | && INTVAL (XEXP (cond, 1)) == 3); |
60 | }) | |
5546ac90 KH |
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 | |
32a7ab3d | 73 | && satisfies_constraint_J16 (op)) |
5546ac90 KH |
74 | return 1; |
75 | ||
76 | return 0; | |
77 | }) | |
78 | ||
c2acaf06 KH |
79 | ;; Like arith_reg_dest, but this predicate is defined with |
80 | ;; define_special_predicate, not define_predicate. | |
5546ac90 KH |
81 | |
82 | (define_special_predicate "any_arith_reg_dest" | |
83 | (match_code "subreg,reg") | |
84 | { | |
85 | return arith_reg_dest (op, mode); | |
86 | }) | |
87 | ||
c2acaf06 KH |
88 | ;; Like register_operand, but this predicate is defined with |
89 | ;; define_special_predicate, not define_predicate. | |
5546ac90 KH |
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 | |
32a7ab3d | 108 | signed 16-bit here, but this causes reload_cse to crash when |
5546ac90 KH |
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. */ | |
f3536097 | 112 | if (CONST_INT_P (op) |
32a7ab3d | 113 | || satisfies_constraint_Css (op)) |
5546ac90 KH |
114 | return 1; |
115 | else if (GET_CODE (op) == TRUNCATE | |
f3536097 | 116 | && REG_P (XEXP (op, 0)) |
5546ac90 KH |
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 | } | |
32a7ab3d | 127 | else if (satisfies_constraint_I08 (op)) |
5546ac90 KH |
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 | ||
f3536097 | 156 | if (REG_P (op)) |
5546ac90 | 157 | regno = REGNO (op); |
f3536097 | 158 | else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op))) |
5546ac90 KH |
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 | |
f3536097 | 179 | && REG_P (XEXP (op, 0)) |
5546ac90 KH |
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 | ||
32a7ab3d | 201 | if (satisfies_constraint_Z (op)) |
5546ac90 KH |
202 | return 1; |
203 | ||
204 | return 0; | |
205 | }) | |
206 | ||
207 | ;; TODO: Add a comment here. | |
208 | ||
209 | (define_predicate "binary_float_operator" | |
f289c6a1 KH |
210 | (and (match_code "plus,minus,mult,div") |
211 | (match_test "GET_MODE (op) == mode"))) | |
5546ac90 KH |
212 | |
213 | ;; TODO: Add a comment here. | |
214 | ||
215 | (define_predicate "binary_logical_operator" | |
f289c6a1 KH |
216 | (and (match_code "and,ior,xor") |
217 | (match_test "GET_MODE (op) == mode"))) | |
5546ac90 | 218 | |
f705a9a0 R |
219 | ;; Return 1 of OP is an address suitable for a cache manipulation operation. |
220 | ;; MODE has the meaning as in address_operand. | |
5546ac90 | 221 | |
f705a9a0 | 222 | (define_special_predicate "cache_address_operand" |
5546ac90 KH |
223 | (match_code "plus,reg") |
224 | { | |
225 | if (GET_CODE (op) == PLUS) | |
226 | { | |
f3536097 | 227 | if (!REG_P (XEXP (op, 0))) |
5546ac90 | 228 | return 0; |
f3536097 | 229 | if (!CONST_INT_P (XEXP (op, 1)) |
5546ac90 KH |
230 | || (INTVAL (XEXP (op, 1)) & 31)) |
231 | return 0; | |
232 | } | |
f3536097 | 233 | else if (!REG_P (op)) |
5546ac90 KH |
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 | { | |
32a7ab3d | 243 | if (satisfies_constraint_N (op)) |
5546ac90 KH |
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 | { | |
f3536097 | 257 | if (REG_P (op) && REGNO (op) == T_REG |
5546ac90 KH |
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" | |
f289c6a1 KH |
267 | (and (match_code "plus,mult") |
268 | (match_test "GET_MODE (op) == mode"))) | |
5546ac90 KH |
269 | |
270 | ;; TODO: Add a comment here. | |
271 | ||
272 | (define_predicate "equality_comparison_operator" | |
f289c6a1 | 273 | (match_code "eq,ne")) |
5546ac90 KH |
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 | ||
f3536097 | 323 | if (REG_P (op)) |
5546ac90 | 324 | regno = REGNO (op); |
f3536097 | 325 | else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op))) |
5546ac90 KH |
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 | { | |
f3536097 | 341 | return (REG_P (op) |
5546ac90 KH |
342 | && (REGNO (op) == FPSCR_REG |
343 | || (REGNO (op) >= FIRST_PSEUDO_REGISTER | |
344 | && !(reload_in_progress || reload_completed))) | |
345 | && GET_MODE (op) == PSImode); | |
346 | }) | |
347 | ||
348 | ;; TODO: Add a comment here. | |
349 | ||
350 | (define_predicate "fpul_operand" | |
351 | (match_code "reg") | |
352 | { | |
353 | if (TARGET_SHMEDIA) | |
354 | return fp_arith_reg_operand (op, mode); | |
355 | ||
f3536097 | 356 | return (REG_P (op) |
5546ac90 KH |
357 | && (REGNO (op) == FPUL_REG || REGNO (op) >= FIRST_PSEUDO_REGISTER) |
358 | && GET_MODE (op) == mode); | |
359 | }) | |
360 | ||
361 | ;; TODO: Add a comment here. | |
362 | ||
363 | (define_predicate "general_extend_operand" | |
364 | (match_code "subreg,reg,mem,truncate") | |
365 | { | |
366 | return (GET_CODE (op) == TRUNCATE | |
367 | ? arith_operand | |
368 | : nonimmediate_operand) (op, mode); | |
369 | }) | |
370 | ||
371 | ;; Returns 1 if OP can be source of a simple move operation. Same as | |
372 | ;; general_operand, but a LABEL_REF is valid, PRE_DEC is invalid as | |
373 | ;; are subregs of system registers. | |
374 | ||
375 | (define_predicate "general_movsrc_operand" | |
376 | (match_code "subreg,reg,const_int,const_double,mem,symbol_ref,label_ref,const,const_vector") | |
377 | { | |
f3536097 | 378 | if (MEM_P (op)) |
5546ac90 KH |
379 | { |
380 | rtx inside = XEXP (op, 0); | |
381 | if (GET_CODE (inside) == CONST) | |
382 | inside = XEXP (inside, 0); | |
383 | ||
384 | if (GET_CODE (inside) == LABEL_REF) | |
385 | return 1; | |
386 | ||
387 | if (GET_CODE (inside) == PLUS | |
388 | && GET_CODE (XEXP (inside, 0)) == LABEL_REF | |
f3536097 | 389 | && CONST_INT_P (XEXP (inside, 1))) |
5546ac90 KH |
390 | return 1; |
391 | ||
392 | /* Only post inc allowed. */ | |
393 | if (GET_CODE (inside) == PRE_DEC) | |
394 | return 0; | |
395 | } | |
396 | ||
a700b5f0 | 397 | if ((mode == QImode || mode == HImode) |
409fed48 | 398 | && mode == GET_MODE (op) |
a700b5f0 KK |
399 | && (MEM_P (op) |
400 | || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))))) | |
401 | { | |
402 | rtx x = XEXP ((MEM_P (op) ? op : SUBREG_REG (op)), 0); | |
403 | ||
404 | if (GET_CODE (x) == PLUS | |
405 | && REG_P (XEXP (x, 0)) | |
406 | && CONST_INT_P (XEXP (x, 1))) | |
407 | return sh_legitimate_index_p (mode, XEXP (x, 1)); | |
408 | } | |
409 | ||
5546ac90 KH |
410 | if (TARGET_SHMEDIA |
411 | && (GET_CODE (op) == PARALLEL || GET_CODE (op) == CONST_VECTOR) | |
412 | && sh_rep_vec (op, mode)) | |
413 | return 1; | |
414 | if (TARGET_SHMEDIA && 1 | |
415 | && GET_CODE (op) == SUBREG && GET_MODE (op) == mode | |
416 | && SUBREG_REG (op) == const0_rtx && subreg_lowpart_p (op)) | |
417 | /* FIXME */ abort (); /* return 1; */ | |
418 | return general_operand (op, mode); | |
419 | }) | |
420 | ||
344332e8 OE |
421 | ;; Same as movsrc_operand, but rejects displacement addressing. |
422 | ||
423 | (define_predicate "movsrc_no_disp_mem_operand" | |
424 | (match_code "subreg,reg,const_int,const_double,mem,symbol_ref,label_ref,const,const_vector") | |
425 | { | |
426 | if (!general_movsrc_operand (op, mode)) | |
427 | return 0; | |
428 | ||
429 | if ((mode == QImode || mode == HImode) | |
430 | && mode == GET_MODE (op) | |
431 | && (MEM_P (op) | |
432 | || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))))) | |
433 | { | |
434 | rtx x = XEXP ((MEM_P (op) ? op : SUBREG_REG (op)), 0); | |
435 | ||
436 | if (GET_CODE (x) == PLUS | |
437 | && REG_P (XEXP (x, 0)) | |
438 | && CONST_INT_P (XEXP (x, 1))) | |
439 | return 0; | |
440 | } | |
441 | ||
442 | return 1; | |
443 | }) | |
444 | ||
5546ac90 KH |
445 | ;; Returns 1 if OP can be a destination of a move. Same as |
446 | ;; general_operand, but no preinc allowed. | |
447 | ||
448 | (define_predicate "general_movdst_operand" | |
449 | (match_code "subreg,reg,mem") | |
450 | { | |
451 | /* Only pre dec allowed. */ | |
f3536097 | 452 | if (MEM_P (op) && GET_CODE (XEXP (op, 0)) == POST_INC) |
5546ac90 KH |
453 | return 0; |
454 | if (mode == DImode && TARGET_SHMEDIA && GET_CODE (op) == SUBREG | |
455 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8 | |
fae61228 | 456 | && ! (reload_in_progress || reload_completed)) |
5546ac90 KH |
457 | return 0; |
458 | ||
a700b5f0 | 459 | if ((mode == QImode || mode == HImode) |
409fed48 | 460 | && mode == GET_MODE (op) |
a700b5f0 KK |
461 | && (MEM_P (op) |
462 | || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))))) | |
463 | { | |
464 | rtx x = XEXP ((MEM_P (op) ? op : SUBREG_REG (op)), 0); | |
465 | ||
466 | if (GET_CODE (x) == PLUS | |
467 | && REG_P (XEXP (x, 0)) | |
468 | && CONST_INT_P (XEXP (x, 1))) | |
469 | return sh_legitimate_index_p (mode, XEXP (x, 1)); | |
470 | } | |
471 | ||
5546ac90 KH |
472 | return general_operand (op, mode); |
473 | }) | |
474 | ||
c11c09f9 KP |
475 | ;; Returns 1 if OP is a POST_INC on stack pointer register. |
476 | ||
477 | (define_predicate "sh_no_delay_pop_operand" | |
478 | (match_code "mem") | |
479 | { | |
480 | rtx inside; | |
481 | inside = XEXP (op, 0); | |
482 | ||
483 | if (GET_CODE (op) == MEM && GET_MODE (op) == SImode | |
484 | && GET_CODE (inside) == POST_INC | |
485 | && GET_CODE (XEXP (inside, 0)) == REG | |
486 | && REGNO (XEXP (inside, 0)) == SP_REG) | |
487 | return 1; | |
488 | ||
489 | return 0; | |
490 | }) | |
491 | ||
5546ac90 KH |
492 | ;; Returns 1 if OP is a MEM that can be source of a simple move operation. |
493 | ||
494 | (define_predicate "unaligned_load_operand" | |
495 | (match_code "mem") | |
496 | { | |
497 | rtx inside; | |
498 | ||
f3536097 | 499 | if (!MEM_P (op) || GET_MODE (op) != mode) |
5546ac90 KH |
500 | return 0; |
501 | ||
502 | inside = XEXP (op, 0); | |
503 | ||
504 | if (GET_CODE (inside) == POST_INC) | |
505 | inside = XEXP (inside, 0); | |
506 | ||
f3536097 | 507 | if (REG_P (inside)) |
5546ac90 KH |
508 | return 1; |
509 | ||
510 | return 0; | |
511 | }) | |
512 | ||
513 | ;; TODO: Add a comment here. | |
514 | ||
515 | (define_predicate "greater_comparison_operator" | |
f289c6a1 | 516 | (match_code "gt,ge,gtu,geu")) |
5546ac90 KH |
517 | |
518 | ;; TODO: Add a comment here. | |
519 | ||
520 | (define_predicate "inqhi_operand" | |
521 | (match_code "truncate") | |
522 | { | |
523 | if (GET_CODE (op) != TRUNCATE || mode != GET_MODE (op)) | |
524 | return 0; | |
525 | op = XEXP (op, 0); | |
526 | /* Can't use true_regnum here because copy_cost wants to know about | |
527 | SECONDARY_INPUT_RELOAD_CLASS. */ | |
f3536097 | 528 | return REG_P (op) && FP_REGISTER_P (REGNO (op)); |
5546ac90 KH |
529 | }) |
530 | ||
531 | ;; TODO: Add a comment here. | |
532 | ||
533 | (define_special_predicate "int_gpr_dest" | |
534 | (match_code "subreg,reg") | |
535 | { | |
536 | enum machine_mode op_mode = GET_MODE (op); | |
537 | ||
538 | if (GET_MODE_CLASS (op_mode) != MODE_INT | |
539 | || GET_MODE_SIZE (op_mode) >= UNITS_PER_WORD) | |
540 | return 0; | |
541 | if (! reload_completed) | |
542 | return 0; | |
543 | return true_regnum (op) <= LAST_GENERAL_REG; | |
544 | }) | |
545 | ||
546 | ;; TODO: Add a comment here. | |
547 | ||
548 | (define_predicate "less_comparison_operator" | |
f289c6a1 | 549 | (match_code "lt,le,ltu,leu")) |
5546ac90 KH |
550 | |
551 | ;; Returns 1 if OP is a valid source operand for a logical operation. | |
552 | ||
553 | (define_predicate "logical_operand" | |
554 | (match_code "subreg,reg,const_int") | |
555 | { | |
556 | if (TARGET_SHMEDIA | |
557 | && mode != DImode && GET_CODE (op) == SUBREG | |
558 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) | |
559 | return 0; | |
560 | ||
561 | if (arith_reg_operand (op, mode)) | |
562 | return 1; | |
563 | ||
564 | if (TARGET_SHMEDIA) | |
565 | { | |
32a7ab3d | 566 | if (satisfies_constraint_I10 (op)) |
5546ac90 KH |
567 | return 1; |
568 | else | |
569 | return 0; | |
570 | } | |
32a7ab3d | 571 | else if (satisfies_constraint_K08 (op)) |
5546ac90 KH |
572 | return 1; |
573 | ||
574 | return 0; | |
575 | }) | |
576 | ||
577 | ;; TODO: Add a comment here. | |
578 | ||
579 | (define_predicate "logical_operator" | |
f289c6a1 | 580 | (match_code "and,ior,xor")) |
5546ac90 KH |
581 | |
582 | ;; Like arith_reg_operand, but for register source operands of narrow | |
583 | ;; logical SHMEDIA operations: forbid subregs of DImode / TImode regs. | |
584 | ||
585 | (define_predicate "logical_reg_operand" | |
586 | (match_code "subreg,reg") | |
587 | { | |
588 | if (TARGET_SHMEDIA | |
589 | && GET_CODE (op) == SUBREG | |
590 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4 | |
591 | && mode != DImode) | |
592 | return 0; | |
593 | return arith_reg_operand (op, mode); | |
594 | }) | |
595 | ||
596 | ;; TODO: Add a comment here. | |
597 | ||
598 | (define_predicate "mextr_bit_offset" | |
599 | (match_code "const_int") | |
600 | { | |
601 | HOST_WIDE_INT i; | |
602 | ||
f3536097 | 603 | if (!CONST_INT_P (op)) |
5546ac90 KH |
604 | return 0; |
605 | i = INTVAL (op); | |
606 | return i >= 1 * 8 && i <= 7 * 8 && (i & 7) == 0; | |
607 | }) | |
608 | ||
609 | ;; TODO: Add a comment here. | |
610 | ||
611 | (define_predicate "minuend_operand" | |
612 | (match_code "subreg,reg,truncate,const_int") | |
613 | { | |
614 | return op == constm1_rtx || extend_reg_or_0_operand (op, mode); | |
615 | }) | |
616 | ||
617 | ;; TODO: Add a comment here. | |
618 | ||
619 | (define_predicate "noncommutative_float_operator" | |
f289c6a1 KH |
620 | (and (match_code "minus,div") |
621 | (match_test "GET_MODE (op) == mode"))) | |
5546ac90 | 622 | |
f90b7a5a PB |
623 | ;; UNORDERED is only supported on SHMEDIA. |
624 | ||
625 | (define_predicate "sh_float_comparison_operator" | |
626 | (ior (match_operand 0 "ordered_comparison_operator") | |
627 | (and (match_test "TARGET_SHMEDIA") | |
628 | (match_code "unordered")))) | |
629 | ||
630 | (define_predicate "shmedia_cbranch_comparison_operator" | |
631 | (ior (match_operand 0 "equality_comparison_operator") | |
632 | (match_operand 0 "greater_comparison_operator"))) | |
633 | ||
5546ac90 KH |
634 | ;; TODO: Add a comment here. |
635 | ||
636 | (define_predicate "sh_const_vec" | |
637 | (match_code "const_vector") | |
638 | { | |
639 | int i; | |
640 | ||
641 | if (GET_CODE (op) != CONST_VECTOR | |
642 | || (GET_MODE (op) != mode && mode != VOIDmode)) | |
643 | return 0; | |
644 | i = XVECLEN (op, 0) - 1; | |
645 | for (; i >= 0; i--) | |
f3536097 | 646 | if (!CONST_INT_P (XVECEXP (op, 0, i))) |
5546ac90 KH |
647 | return 0; |
648 | return 1; | |
649 | }) | |
650 | ||
651 | ;; Determine if OP is a constant vector matching MODE with only one | |
652 | ;; element that is not a sign extension. Two byte-sized elements | |
653 | ;; count as one. | |
654 | ||
655 | (define_predicate "sh_1el_vec" | |
656 | (match_code "const_vector") | |
657 | { | |
658 | int unit_size; | |
659 | int i, last, least, sign_ix; | |
660 | rtx sign; | |
661 | ||
662 | if (GET_CODE (op) != CONST_VECTOR | |
663 | || (GET_MODE (op) != mode && mode != VOIDmode)) | |
664 | return 0; | |
665 | /* Determine numbers of last and of least significant elements. */ | |
666 | last = XVECLEN (op, 0) - 1; | |
667 | least = TARGET_LITTLE_ENDIAN ? 0 : last; | |
f3536097 | 668 | if (!CONST_INT_P (XVECEXP (op, 0, least))) |
5546ac90 KH |
669 | return 0; |
670 | sign_ix = least; | |
671 | if (GET_MODE_UNIT_SIZE (mode) == 1) | |
672 | sign_ix = TARGET_LITTLE_ENDIAN ? 1 : last - 1; | |
f3536097 | 673 | if (!CONST_INT_P (XVECEXP (op, 0, sign_ix))) |
5546ac90 KH |
674 | return 0; |
675 | unit_size = GET_MODE_UNIT_SIZE (GET_MODE (op)); | |
676 | sign = (INTVAL (XVECEXP (op, 0, sign_ix)) >> (unit_size * BITS_PER_UNIT - 1) | |
677 | ? constm1_rtx : const0_rtx); | |
678 | i = XVECLEN (op, 0) - 1; | |
679 | do | |
680 | if (i != least && i != sign_ix && XVECEXP (op, 0, i) != sign) | |
681 | return 0; | |
682 | while (--i); | |
683 | return 1; | |
684 | }) | |
685 | ||
686 | ;; Like register_operand, but take into account that SHMEDIA can use | |
687 | ;; the constant zero like a general register. | |
688 | ||
689 | (define_predicate "sh_register_operand" | |
ac42ec79 | 690 | (match_code "reg,subreg,const_int,const_double") |
5546ac90 KH |
691 | { |
692 | if (op == CONST0_RTX (mode) && TARGET_SHMEDIA) | |
693 | return 1; | |
694 | return register_operand (op, mode); | |
695 | }) | |
696 | ||
697 | ;; TODO: Add a comment here. | |
698 | ||
699 | (define_predicate "sh_rep_vec" | |
b4060d3f | 700 | (match_code "const_vector,parallel") |
5546ac90 KH |
701 | { |
702 | int i; | |
703 | rtx x, y; | |
704 | ||
705 | if ((GET_CODE (op) != CONST_VECTOR && GET_CODE (op) != PARALLEL) | |
706 | || (GET_MODE (op) != mode && mode != VOIDmode)) | |
707 | return 0; | |
708 | i = XVECLEN (op, 0) - 2; | |
709 | x = XVECEXP (op, 0, i + 1); | |
710 | if (GET_MODE_UNIT_SIZE (mode) == 1) | |
711 | { | |
712 | y = XVECEXP (op, 0, i); | |
713 | for (i -= 2; i >= 0; i -= 2) | |
714 | if (! rtx_equal_p (XVECEXP (op, 0, i + 1), x) | |
715 | || ! rtx_equal_p (XVECEXP (op, 0, i), y)) | |
716 | return 0; | |
717 | } | |
718 | else | |
719 | for (; i >= 0; i--) | |
720 | if (XVECEXP (op, 0, i) != x) | |
721 | return 0; | |
722 | return 1; | |
723 | }) | |
724 | ||
725 | ;; TODO: Add a comment here. | |
726 | ||
727 | (define_predicate "shift_count_operand" | |
728 | (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,zero_extend,sign_extend") | |
729 | { | |
730 | return (CONSTANT_P (op) | |
f3536097 | 731 | ? (CONST_INT_P (op) |
5546ac90 KH |
732 | ? (unsigned) INTVAL (op) < GET_MODE_BITSIZE (mode) |
733 | : nonmemory_operand (op, mode)) | |
734 | : shift_count_reg_operand (op, mode)); | |
735 | }) | |
736 | ||
737 | ;; TODO: Add a comment here. | |
738 | ||
739 | (define_predicate "shift_count_reg_operand" | |
740 | (match_code "subreg,reg,zero_extend,sign_extend") | |
741 | { | |
742 | if ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND | |
743 | || (GET_CODE (op) == SUBREG && SUBREG_BYTE (op) == 0)) | |
744 | && (mode == VOIDmode || mode == GET_MODE (op)) | |
745 | && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6 | |
746 | && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT) | |
747 | { | |
748 | mode = VOIDmode; | |
749 | do | |
750 | op = XEXP (op, 0); | |
751 | while ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND | |
752 | || GET_CODE (op) == TRUNCATE) | |
753 | && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6 | |
754 | && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT); | |
755 | ||
756 | } | |
757 | return arith_reg_operand (op, mode); | |
758 | }) | |
759 | ||
760 | ;; TODO: Add a comment here. | |
761 | ||
762 | (define_predicate "shift_operator" | |
f289c6a1 | 763 | (match_code "ashift,ashiftrt,lshiftrt")) |
5546ac90 KH |
764 | |
765 | ;; TODO: Add a comment here. | |
766 | ||
767 | (define_predicate "symbol_ref_operand" | |
f289c6a1 | 768 | (match_code "symbol_ref")) |
5546ac90 KH |
769 | |
770 | ;; Same as target_reg_operand, except that label_refs and symbol_refs | |
771 | ;; are accepted before reload. | |
772 | ||
773 | (define_special_predicate "target_operand" | |
774 | (match_code "subreg,reg,label_ref,symbol_ref,const,unspec") | |
775 | { | |
776 | if (mode != VOIDmode && mode != Pmode) | |
777 | return 0; | |
778 | ||
779 | if ((GET_MODE (op) == Pmode || GET_MODE (op) == VOIDmode) | |
32a7ab3d | 780 | && satisfies_constraint_Csy (op)) |
5546ac90 KH |
781 | return ! reload_completed; |
782 | ||
783 | return target_reg_operand (op, mode); | |
784 | }) | |
785 | ||
786 | ;; Accept pseudos and branch target registers. | |
787 | ||
788 | (define_special_predicate "target_reg_operand" | |
789 | (match_code "subreg,reg") | |
790 | { | |
791 | if (mode == VOIDmode | |
792 | ? GET_MODE (op) != Pmode && GET_MODE (op) != PDImode | |
793 | : mode != GET_MODE (op)) | |
794 | return 0; | |
795 | ||
796 | if (GET_CODE (op) == SUBREG) | |
797 | op = XEXP (op, 0); | |
798 | ||
f3536097 | 799 | if (!REG_P (op)) |
5546ac90 KH |
800 | return 0; |
801 | ||
802 | /* We must protect ourselves from matching pseudos that are virtual | |
803 | register, because they will eventually be replaced with hardware | |
804 | registers that aren't branch-target registers. */ | |
805 | if (REGNO (op) > LAST_VIRTUAL_REGISTER | |
806 | || TARGET_REGISTER_P (REGNO (op))) | |
807 | return 1; | |
808 | ||
809 | return 0; | |
810 | }) | |
811 | ||
812 | ;; TODO: Add a comment here. | |
813 | ||
814 | (define_special_predicate "trunc_hi_operand" | |
815 | (match_code "subreg,reg,truncate") | |
816 | { | |
817 | enum machine_mode op_mode = GET_MODE (op); | |
818 | ||
819 | if (op_mode != SImode && op_mode != DImode | |
820 | && op_mode != V4HImode && op_mode != V2SImode) | |
821 | return 0; | |
822 | return extend_reg_operand (op, mode); | |
823 | }) | |
824 | ||
f705a9a0 | 825 | ;; Return 1 of OP is an address suitable for an unaligned access instruction. |
5546ac90 | 826 | |
f705a9a0 | 827 | (define_special_predicate "ua_address_operand" |
5546ac90 KH |
828 | (match_code "subreg,reg,plus") |
829 | { | |
830 | if (GET_CODE (op) == PLUS | |
32a7ab3d | 831 | && (! satisfies_constraint_I06 (XEXP (op, 1)))) |
5546ac90 KH |
832 | return 0; |
833 | return address_operand (op, QImode); | |
834 | }) | |
835 | ||
836 | ;; TODO: Add a comment here. | |
837 | ||
838 | (define_predicate "ua_offset" | |
839 | (match_code "const_int") | |
840 | { | |
32a7ab3d | 841 | return satisfies_constraint_I06 (op); |
5546ac90 KH |
842 | }) |
843 | ||
844 | ;; TODO: Add a comment here. | |
845 | ||
846 | (define_predicate "unary_float_operator" | |
f289c6a1 KH |
847 | (and (match_code "abs,neg,sqrt") |
848 | (match_test "GET_MODE (op) == mode"))) | |
5546ac90 KH |
849 | |
850 | ;; Return 1 if OP is a valid source operand for xor. | |
851 | ||
852 | (define_predicate "xor_operand" | |
853 | (match_code "subreg,reg,const_int") | |
854 | { | |
f3536097 | 855 | if (CONST_INT_P (op)) |
5546ac90 | 856 | return (TARGET_SHMEDIA |
32a7ab3d | 857 | ? (satisfies_constraint_I06 (op) |
b3a13419 | 858 | || (!can_create_pseudo_p () && INTVAL (op) == 0xff)) |
32a7ab3d | 859 | : satisfies_constraint_K08 (op)); |
5546ac90 KH |
860 | if (TARGET_SHMEDIA |
861 | && mode != DImode && GET_CODE (op) == SUBREG | |
862 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) | |
863 | return 0; | |
864 | return arith_reg_operand (op, mode); | |
865 | }) | |
9eb3a0dd N |
866 | |
867 | (define_predicate "bitwise_memory_operand" | |
868 | (match_code "mem") | |
869 | { | |
f3536097 | 870 | if (MEM_P (op)) |
9eb3a0dd N |
871 | { |
872 | if (REG_P (XEXP (op, 0))) | |
873 | return 1; | |
874 | ||
875 | if (GET_CODE (XEXP (op, 0)) == PLUS | |
f3536097 | 876 | && REG_P (XEXP (XEXP (op, 0), 0)) |
9eb3a0dd N |
877 | && satisfies_constraint_K12 (XEXP (XEXP (op, 0), 1))) |
878 | return 1; | |
879 | } | |
880 | return 0; | |
881 | }) |