]>
Commit | Line | Data |
---|---|---|
5546ac90 | 1 | ;; Predicate definitions for Renesas / SuperH SH. |
32a7ab3d | 2 | ;; Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. |
5546ac90 KH |
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) |
5546ac90 KH |
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/>. | |
5546ac90 KH |
19 | |
20 | ;; TODO: Add a comment here. | |
21 | ||
73a4d10b R |
22 | (define_predicate "trapping_target_operand" |
23 | (match_code "if_then_else") | |
24 | { | |
25 | rtx cond, mem, res, tar, and; | |
26 | ||
27 | if (GET_MODE (op) != PDImode) | |
28 | return 0; | |
29 | cond = XEXP (op, 0); | |
30 | mem = XEXP (op, 1); | |
31 | res = XEXP (op, 2); | |
32 | if (GET_CODE (mem) != MEM | |
33 | || (GET_CODE (res) != SIGN_EXTEND && GET_CODE (res) != TRUNCATE)) | |
34 | return 0; | |
35 | tar = XEXP (res, 0); | |
36 | if (!rtx_equal_p (XEXP (mem, 0), tar) | |
37 | || GET_MODE (tar) != Pmode) | |
38 | return 0; | |
39 | if (GET_CODE (cond) == CONST) | |
40 | { | |
41 | cond = XEXP (cond, 0); | |
32a7ab3d | 42 | if (!satisfies_constraint_Csy (tar)) |
73a4d10b R |
43 | return 0; |
44 | if (GET_CODE (tar) == CONST) | |
45 | tar = XEXP (tar, 0); | |
46 | } | |
47 | else if (!arith_reg_operand (tar, VOIDmode) | |
32a7ab3d | 48 | && ! satisfies_constraint_Csy (tar)) |
73a4d10b R |
49 | return 0; |
50 | if (GET_CODE (cond) != EQ) | |
51 | return 0; | |
52 | and = XEXP (cond, 0); | |
53 | return (GET_CODE (and) == AND | |
54 | && rtx_equal_p (XEXP (and, 0), tar) | |
55 | && GET_CODE (XEXP (and, 1)) == CONST_INT | |
56 | && GET_CODE (XEXP (cond, 1)) == CONST_INT | |
57 | && INTVAL (XEXP (and, 1)) == 3 | |
58 | && INTVAL (XEXP (cond, 1)) == 3); | |
59 | }) | |
5546ac90 KH |
60 | |
61 | ;; TODO: Add a comment here. | |
62 | ||
63 | (define_predicate "and_operand" | |
64 | (match_code "subreg,reg,const_int") | |
65 | { | |
66 | if (logical_operand (op, mode)) | |
67 | return 1; | |
68 | ||
69 | /* Check mshflo.l / mshflhi.l opportunities. */ | |
70 | if (TARGET_SHMEDIA | |
71 | && mode == DImode | |
32a7ab3d | 72 | && satisfies_constraint_J16 (op)) |
5546ac90 KH |
73 | return 1; |
74 | ||
75 | return 0; | |
76 | }) | |
77 | ||
c2acaf06 KH |
78 | ;; Like arith_reg_dest, but this predicate is defined with |
79 | ;; define_special_predicate, not define_predicate. | |
5546ac90 KH |
80 | |
81 | (define_special_predicate "any_arith_reg_dest" | |
82 | (match_code "subreg,reg") | |
83 | { | |
84 | return arith_reg_dest (op, mode); | |
85 | }) | |
86 | ||
c2acaf06 KH |
87 | ;; Like register_operand, but this predicate is defined with |
88 | ;; define_special_predicate, not define_predicate. | |
5546ac90 KH |
89 | |
90 | (define_special_predicate "any_register_operand" | |
91 | (match_code "subreg,reg") | |
92 | { | |
93 | return register_operand (op, mode); | |
94 | }) | |
95 | ||
96 | ;; Returns 1 if OP is a valid source operand for an arithmetic insn. | |
97 | ||
98 | (define_predicate "arith_operand" | |
99 | (match_code "subreg,reg,const_int,truncate") | |
100 | { | |
101 | if (arith_reg_operand (op, mode)) | |
102 | return 1; | |
103 | ||
104 | if (TARGET_SHMEDIA) | |
105 | { | |
106 | /* FIXME: We should be checking whether the CONST_INT fits in a | |
32a7ab3d | 107 | signed 16-bit here, but this causes reload_cse to crash when |
5546ac90 KH |
108 | attempting to transform a sequence of two 64-bit sets of the |
109 | same register from literal constants into a set and an add, | |
110 | when the difference is too wide for an add. */ | |
111 | if (GET_CODE (op) == CONST_INT | |
32a7ab3d | 112 | || satisfies_constraint_Css (op)) |
5546ac90 KH |
113 | return 1; |
114 | else if (GET_CODE (op) == TRUNCATE | |
115 | && ! system_reg_operand (XEXP (op, 0), VOIDmode) | |
116 | && (mode == VOIDmode || mode == GET_MODE (op)) | |
117 | && (GET_MODE_SIZE (GET_MODE (op)) | |
118 | < GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))) | |
119 | && (! FP_REGISTER_P (REGNO (XEXP (op, 0))) | |
120 | || GET_MODE_SIZE (GET_MODE (op)) == 4)) | |
121 | return register_operand (XEXP (op, 0), VOIDmode); | |
122 | else | |
123 | return 0; | |
124 | } | |
32a7ab3d | 125 | else if (satisfies_constraint_I08 (op)) |
5546ac90 KH |
126 | return 1; |
127 | ||
128 | return 0; | |
129 | }) | |
130 | ||
131 | ;; Like above, but for DImode destinations: forbid paradoxical DImode | |
132 | ;; subregs, because this would lead to missing sign extensions when | |
133 | ;; truncating from DImode to SImode. | |
134 | ||
135 | (define_predicate "arith_reg_dest" | |
136 | (match_code "subreg,reg") | |
137 | { | |
138 | if (mode == DImode && GET_CODE (op) == SUBREG | |
139 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8 | |
140 | && TARGET_SHMEDIA) | |
141 | return 0; | |
142 | return arith_reg_operand (op, mode); | |
143 | }) | |
144 | ||
145 | ;; Returns 1 if OP is a normal arithmetic register. | |
146 | ||
147 | (define_predicate "arith_reg_operand" | |
148 | (match_code "subreg,reg,sign_extend") | |
149 | { | |
150 | if (register_operand (op, mode)) | |
151 | { | |
152 | int regno; | |
153 | ||
154 | if (GET_CODE (op) == REG) | |
155 | regno = REGNO (op); | |
156 | else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) | |
157 | regno = REGNO (SUBREG_REG (op)); | |
158 | else | |
159 | return 1; | |
160 | ||
161 | return (regno != T_REG && regno != PR_REG | |
162 | && ! TARGET_REGISTER_P (regno) | |
163 | && (regno != FPUL_REG || TARGET_SH4) | |
164 | && regno != MACH_REG && regno != MACL_REG); | |
165 | } | |
166 | /* Allow a no-op sign extension - compare LOAD_EXTEND_OP. | |
167 | We allow SImode here, as not using an FP register is just a matter of | |
168 | proper register allocation. */ | |
169 | if (TARGET_SHMEDIA | |
170 | && GET_MODE (op) == DImode && GET_CODE (op) == SIGN_EXTEND | |
171 | && GET_MODE (XEXP (op, 0)) == SImode | |
172 | && GET_CODE (XEXP (op, 0)) != SUBREG) | |
173 | return register_operand (XEXP (op, 0), VOIDmode); | |
174 | #if 0 /* Can't do this because of PROMOTE_MODE for unsigned vars. */ | |
175 | if (GET_MODE (op) == SImode && GET_CODE (op) == SIGN_EXTEND | |
176 | && GET_MODE (XEXP (op, 0)) == HImode | |
177 | && GET_CODE (XEXP (op, 0)) == REG | |
178 | && REGNO (XEXP (op, 0)) <= LAST_GENERAL_REG) | |
179 | return register_operand (XEXP (op, 0), VOIDmode); | |
180 | #endif | |
181 | if (GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_INT | |
182 | && GET_CODE (op) == SUBREG | |
183 | && GET_MODE (SUBREG_REG (op)) == DImode | |
184 | && GET_CODE (SUBREG_REG (op)) == SIGN_EXTEND | |
185 | && GET_MODE (XEXP (SUBREG_REG (op), 0)) == SImode | |
186 | && GET_CODE (XEXP (SUBREG_REG (op), 0)) != SUBREG) | |
187 | return register_operand (XEXP (SUBREG_REG (op), 0), VOIDmode); | |
188 | return 0; | |
189 | }) | |
190 | ||
191 | ;; Returns 1 if OP is a valid source operand for a compare insn. | |
192 | ||
193 | (define_predicate "arith_reg_or_0_operand" | |
194 | (match_code "subreg,reg,const_int,const_vector") | |
195 | { | |
196 | if (arith_reg_operand (op, mode)) | |
197 | return 1; | |
198 | ||
32a7ab3d | 199 | if (satisfies_constraint_Z (op)) |
5546ac90 KH |
200 | return 1; |
201 | ||
202 | return 0; | |
203 | }) | |
204 | ||
205 | ;; TODO: Add a comment here. | |
206 | ||
207 | (define_predicate "binary_float_operator" | |
f289c6a1 KH |
208 | (and (match_code "plus,minus,mult,div") |
209 | (match_test "GET_MODE (op) == mode"))) | |
5546ac90 KH |
210 | |
211 | ;; TODO: Add a comment here. | |
212 | ||
213 | (define_predicate "binary_logical_operator" | |
f289c6a1 KH |
214 | (and (match_code "and,ior,xor") |
215 | (match_test "GET_MODE (op) == mode"))) | |
5546ac90 | 216 | |
f705a9a0 R |
217 | ;; Return 1 of OP is an address suitable for a cache manipulation operation. |
218 | ;; MODE has the meaning as in address_operand. | |
5546ac90 | 219 | |
f705a9a0 | 220 | (define_special_predicate "cache_address_operand" |
5546ac90 KH |
221 | (match_code "plus,reg") |
222 | { | |
223 | if (GET_CODE (op) == PLUS) | |
224 | { | |
225 | if (GET_CODE (XEXP (op, 0)) != REG) | |
226 | return 0; | |
227 | if (GET_CODE (XEXP (op, 1)) != CONST_INT | |
228 | || (INTVAL (XEXP (op, 1)) & 31)) | |
229 | return 0; | |
230 | } | |
231 | else if (GET_CODE (op) != REG) | |
232 | return 0; | |
233 | return address_operand (op, mode); | |
234 | }) | |
235 | ||
236 | ;; Return 1 if OP is a valid source operand for shmedia cmpgt / cmpgtu. | |
237 | ||
238 | (define_predicate "cmp_operand" | |
239 | (match_code "subreg,reg,const_int") | |
240 | { | |
32a7ab3d | 241 | if (satisfies_constraint_N (op)) |
5546ac90 KH |
242 | return 1; |
243 | if (TARGET_SHMEDIA | |
244 | && mode != DImode && GET_CODE (op) == SUBREG | |
245 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) | |
246 | return 0; | |
247 | return arith_reg_operand (op, mode); | |
248 | }) | |
249 | ||
250 | ;; TODO: Add a comment here. | |
251 | ||
252 | (define_predicate "cmpsi_operand" | |
253 | (match_code "subreg,reg,const_int") | |
254 | { | |
255 | if (GET_CODE (op) == REG && REGNO (op) == T_REG | |
256 | && GET_MODE (op) == SImode | |
257 | && TARGET_SH1) | |
258 | return 1; | |
259 | return arith_operand (op, mode); | |
260 | }) | |
261 | ||
262 | ;; TODO: Add a comment here. | |
263 | ||
264 | (define_predicate "commutative_float_operator" | |
f289c6a1 KH |
265 | (and (match_code "plus,mult") |
266 | (match_test "GET_MODE (op) == mode"))) | |
5546ac90 KH |
267 | |
268 | ;; TODO: Add a comment here. | |
269 | ||
270 | (define_predicate "equality_comparison_operator" | |
f289c6a1 | 271 | (match_code "eq,ne")) |
5546ac90 KH |
272 | |
273 | ;; TODO: Add a comment here. | |
274 | ||
275 | (define_predicate "extend_reg_operand" | |
276 | (match_code "subreg,reg,truncate") | |
277 | { | |
278 | return (GET_CODE (op) == TRUNCATE | |
279 | ? arith_operand | |
280 | : arith_reg_operand) (op, mode); | |
281 | }) | |
282 | ||
283 | ;; TODO: Add a comment here. | |
284 | ||
285 | (define_predicate "extend_reg_or_0_operand" | |
286 | (match_code "subreg,reg,truncate,const_int") | |
287 | { | |
288 | return (GET_CODE (op) == TRUNCATE | |
289 | ? arith_operand | |
290 | : arith_reg_or_0_operand) (op, mode); | |
291 | }) | |
292 | ||
293 | ;; Like arith_reg_operand, but this predicate does not accept SIGN_EXTEND. | |
294 | ||
295 | (define_predicate "ext_dest_operand" | |
296 | (match_code "subreg,reg") | |
297 | { | |
298 | return arith_reg_operand (op, mode); | |
299 | }) | |
300 | ||
301 | ;; TODO: Add a comment here. | |
302 | ||
303 | (define_predicate "fp_arith_reg_dest" | |
304 | (match_code "subreg,reg") | |
305 | { | |
306 | if (mode == DImode && GET_CODE (op) == SUBREG | |
307 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8) | |
308 | return 0; | |
309 | return fp_arith_reg_operand (op, mode); | |
310 | }) | |
311 | ||
312 | ;; TODO: Add a comment here. | |
313 | ||
314 | (define_predicate "fp_arith_reg_operand" | |
315 | (match_code "subreg,reg") | |
316 | { | |
317 | if (register_operand (op, mode)) | |
318 | { | |
319 | int regno; | |
320 | ||
321 | if (GET_CODE (op) == REG) | |
322 | regno = REGNO (op); | |
323 | else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) | |
324 | regno = REGNO (SUBREG_REG (op)); | |
325 | else | |
326 | return 1; | |
327 | ||
328 | return (regno >= FIRST_PSEUDO_REGISTER | |
329 | || FP_REGISTER_P (regno)); | |
330 | } | |
331 | return 0; | |
332 | }) | |
333 | ||
334 | ;; TODO: Add a comment here. | |
335 | ||
336 | (define_predicate "fpscr_operand" | |
337 | (match_code "reg") | |
338 | { | |
339 | return (GET_CODE (op) == REG | |
340 | && (REGNO (op) == FPSCR_REG | |
341 | || (REGNO (op) >= FIRST_PSEUDO_REGISTER | |
342 | && !(reload_in_progress || reload_completed))) | |
343 | && GET_MODE (op) == PSImode); | |
344 | }) | |
345 | ||
346 | ;; TODO: Add a comment here. | |
347 | ||
348 | (define_predicate "fpul_operand" | |
349 | (match_code "reg") | |
350 | { | |
351 | if (TARGET_SHMEDIA) | |
352 | return fp_arith_reg_operand (op, mode); | |
353 | ||
354 | return (GET_CODE (op) == REG | |
355 | && (REGNO (op) == FPUL_REG || REGNO (op) >= FIRST_PSEUDO_REGISTER) | |
356 | && GET_MODE (op) == mode); | |
357 | }) | |
358 | ||
359 | ;; TODO: Add a comment here. | |
360 | ||
361 | (define_predicate "general_extend_operand" | |
362 | (match_code "subreg,reg,mem,truncate") | |
363 | { | |
364 | return (GET_CODE (op) == TRUNCATE | |
365 | ? arith_operand | |
366 | : nonimmediate_operand) (op, mode); | |
367 | }) | |
368 | ||
369 | ;; Returns 1 if OP can be source of a simple move operation. Same as | |
370 | ;; general_operand, but a LABEL_REF is valid, PRE_DEC is invalid as | |
371 | ;; are subregs of system registers. | |
372 | ||
373 | (define_predicate "general_movsrc_operand" | |
374 | (match_code "subreg,reg,const_int,const_double,mem,symbol_ref,label_ref,const,const_vector") | |
375 | { | |
376 | if (GET_CODE (op) == MEM) | |
377 | { | |
378 | rtx inside = XEXP (op, 0); | |
379 | if (GET_CODE (inside) == CONST) | |
380 | inside = XEXP (inside, 0); | |
381 | ||
382 | if (GET_CODE (inside) == LABEL_REF) | |
383 | return 1; | |
384 | ||
385 | if (GET_CODE (inside) == PLUS | |
386 | && GET_CODE (XEXP (inside, 0)) == LABEL_REF | |
387 | && GET_CODE (XEXP (inside, 1)) == CONST_INT) | |
388 | return 1; | |
389 | ||
390 | /* Only post inc allowed. */ | |
391 | if (GET_CODE (inside) == PRE_DEC) | |
392 | return 0; | |
393 | } | |
394 | ||
395 | if ((mode == QImode || mode == HImode) | |
396 | && (GET_CODE (op) == SUBREG | |
397 | && GET_CODE (XEXP (op, 0)) == REG | |
398 | && system_reg_operand (XEXP (op, 0), mode))) | |
399 | return 0; | |
400 | ||
401 | if (TARGET_SHMEDIA | |
402 | && (GET_CODE (op) == PARALLEL || GET_CODE (op) == CONST_VECTOR) | |
403 | && sh_rep_vec (op, mode)) | |
404 | return 1; | |
405 | if (TARGET_SHMEDIA && 1 | |
406 | && GET_CODE (op) == SUBREG && GET_MODE (op) == mode | |
407 | && SUBREG_REG (op) == const0_rtx && subreg_lowpart_p (op)) | |
408 | /* FIXME */ abort (); /* return 1; */ | |
409 | return general_operand (op, mode); | |
410 | }) | |
411 | ||
412 | ;; Returns 1 if OP can be a destination of a move. Same as | |
413 | ;; general_operand, but no preinc allowed. | |
414 | ||
415 | (define_predicate "general_movdst_operand" | |
416 | (match_code "subreg,reg,mem") | |
417 | { | |
418 | /* Only pre dec allowed. */ | |
419 | if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC) | |
420 | return 0; | |
421 | if (mode == DImode && TARGET_SHMEDIA && GET_CODE (op) == SUBREG | |
422 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8 | |
423 | && ! (high_life_started || reload_completed)) | |
424 | return 0; | |
425 | ||
426 | return general_operand (op, mode); | |
427 | }) | |
428 | ||
429 | ;; Returns 1 if OP is a MEM that can be source of a simple move operation. | |
430 | ||
431 | (define_predicate "unaligned_load_operand" | |
432 | (match_code "mem") | |
433 | { | |
434 | rtx inside; | |
435 | ||
436 | if (GET_CODE (op) != MEM || GET_MODE (op) != mode) | |
437 | return 0; | |
438 | ||
439 | inside = XEXP (op, 0); | |
440 | ||
441 | if (GET_CODE (inside) == POST_INC) | |
442 | inside = XEXP (inside, 0); | |
443 | ||
444 | if (GET_CODE (inside) == REG) | |
445 | return 1; | |
446 | ||
447 | return 0; | |
448 | }) | |
449 | ||
450 | ;; TODO: Add a comment here. | |
451 | ||
452 | (define_predicate "greater_comparison_operator" | |
f289c6a1 | 453 | (match_code "gt,ge,gtu,geu")) |
5546ac90 KH |
454 | |
455 | ;; TODO: Add a comment here. | |
456 | ||
457 | (define_predicate "inqhi_operand" | |
458 | (match_code "truncate") | |
459 | { | |
460 | if (GET_CODE (op) != TRUNCATE || mode != GET_MODE (op)) | |
461 | return 0; | |
462 | op = XEXP (op, 0); | |
463 | /* Can't use true_regnum here because copy_cost wants to know about | |
464 | SECONDARY_INPUT_RELOAD_CLASS. */ | |
465 | return GET_CODE (op) == REG && FP_REGISTER_P (REGNO (op)); | |
466 | }) | |
467 | ||
468 | ;; TODO: Add a comment here. | |
469 | ||
470 | (define_special_predicate "int_gpr_dest" | |
471 | (match_code "subreg,reg") | |
472 | { | |
473 | enum machine_mode op_mode = GET_MODE (op); | |
474 | ||
475 | if (GET_MODE_CLASS (op_mode) != MODE_INT | |
476 | || GET_MODE_SIZE (op_mode) >= UNITS_PER_WORD) | |
477 | return 0; | |
478 | if (! reload_completed) | |
479 | return 0; | |
480 | return true_regnum (op) <= LAST_GENERAL_REG; | |
481 | }) | |
482 | ||
483 | ;; TODO: Add a comment here. | |
484 | ||
485 | (define_predicate "less_comparison_operator" | |
f289c6a1 | 486 | (match_code "lt,le,ltu,leu")) |
5546ac90 KH |
487 | |
488 | ;; Returns 1 if OP is a valid source operand for a logical operation. | |
489 | ||
490 | (define_predicate "logical_operand" | |
491 | (match_code "subreg,reg,const_int") | |
492 | { | |
493 | if (TARGET_SHMEDIA | |
494 | && mode != DImode && GET_CODE (op) == SUBREG | |
495 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) | |
496 | return 0; | |
497 | ||
498 | if (arith_reg_operand (op, mode)) | |
499 | return 1; | |
500 | ||
501 | if (TARGET_SHMEDIA) | |
502 | { | |
32a7ab3d | 503 | if (satisfies_constraint_I10 (op)) |
5546ac90 KH |
504 | return 1; |
505 | else | |
506 | return 0; | |
507 | } | |
32a7ab3d | 508 | else if (satisfies_constraint_K08 (op)) |
5546ac90 KH |
509 | return 1; |
510 | ||
511 | return 0; | |
512 | }) | |
513 | ||
514 | ;; TODO: Add a comment here. | |
515 | ||
516 | (define_predicate "logical_operator" | |
f289c6a1 | 517 | (match_code "and,ior,xor")) |
5546ac90 KH |
518 | |
519 | ;; Like arith_reg_operand, but for register source operands of narrow | |
520 | ;; logical SHMEDIA operations: forbid subregs of DImode / TImode regs. | |
521 | ||
522 | (define_predicate "logical_reg_operand" | |
523 | (match_code "subreg,reg") | |
524 | { | |
525 | if (TARGET_SHMEDIA | |
526 | && GET_CODE (op) == SUBREG | |
527 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4 | |
528 | && mode != DImode) | |
529 | return 0; | |
530 | return arith_reg_operand (op, mode); | |
531 | }) | |
532 | ||
533 | ;; TODO: Add a comment here. | |
534 | ||
535 | (define_predicate "mextr_bit_offset" | |
536 | (match_code "const_int") | |
537 | { | |
538 | HOST_WIDE_INT i; | |
539 | ||
540 | if (GET_CODE (op) != CONST_INT) | |
541 | return 0; | |
542 | i = INTVAL (op); | |
543 | return i >= 1 * 8 && i <= 7 * 8 && (i & 7) == 0; | |
544 | }) | |
545 | ||
546 | ;; TODO: Add a comment here. | |
547 | ||
548 | (define_predicate "minuend_operand" | |
549 | (match_code "subreg,reg,truncate,const_int") | |
550 | { | |
551 | return op == constm1_rtx || extend_reg_or_0_operand (op, mode); | |
552 | }) | |
553 | ||
554 | ;; TODO: Add a comment here. | |
555 | ||
556 | (define_predicate "noncommutative_float_operator" | |
f289c6a1 KH |
557 | (and (match_code "minus,div") |
558 | (match_test "GET_MODE (op) == mode"))) | |
5546ac90 KH |
559 | |
560 | ;; TODO: Add a comment here. | |
561 | ||
562 | (define_predicate "sh_const_vec" | |
563 | (match_code "const_vector") | |
564 | { | |
565 | int i; | |
566 | ||
567 | if (GET_CODE (op) != CONST_VECTOR | |
568 | || (GET_MODE (op) != mode && mode != VOIDmode)) | |
569 | return 0; | |
570 | i = XVECLEN (op, 0) - 1; | |
571 | for (; i >= 0; i--) | |
572 | if (GET_CODE (XVECEXP (op, 0, i)) != CONST_INT) | |
573 | return 0; | |
574 | return 1; | |
575 | }) | |
576 | ||
577 | ;; Determine if OP is a constant vector matching MODE with only one | |
578 | ;; element that is not a sign extension. Two byte-sized elements | |
579 | ;; count as one. | |
580 | ||
581 | (define_predicate "sh_1el_vec" | |
582 | (match_code "const_vector") | |
583 | { | |
584 | int unit_size; | |
585 | int i, last, least, sign_ix; | |
586 | rtx sign; | |
587 | ||
588 | if (GET_CODE (op) != CONST_VECTOR | |
589 | || (GET_MODE (op) != mode && mode != VOIDmode)) | |
590 | return 0; | |
591 | /* Determine numbers of last and of least significant elements. */ | |
592 | last = XVECLEN (op, 0) - 1; | |
593 | least = TARGET_LITTLE_ENDIAN ? 0 : last; | |
594 | if (GET_CODE (XVECEXP (op, 0, least)) != CONST_INT) | |
595 | return 0; | |
596 | sign_ix = least; | |
597 | if (GET_MODE_UNIT_SIZE (mode) == 1) | |
598 | sign_ix = TARGET_LITTLE_ENDIAN ? 1 : last - 1; | |
599 | if (GET_CODE (XVECEXP (op, 0, sign_ix)) != CONST_INT) | |
600 | return 0; | |
601 | unit_size = GET_MODE_UNIT_SIZE (GET_MODE (op)); | |
602 | sign = (INTVAL (XVECEXP (op, 0, sign_ix)) >> (unit_size * BITS_PER_UNIT - 1) | |
603 | ? constm1_rtx : const0_rtx); | |
604 | i = XVECLEN (op, 0) - 1; | |
605 | do | |
606 | if (i != least && i != sign_ix && XVECEXP (op, 0, i) != sign) | |
607 | return 0; | |
608 | while (--i); | |
609 | return 1; | |
610 | }) | |
611 | ||
612 | ;; Like register_operand, but take into account that SHMEDIA can use | |
613 | ;; the constant zero like a general register. | |
614 | ||
615 | (define_predicate "sh_register_operand" | |
ac42ec79 | 616 | (match_code "reg,subreg,const_int,const_double") |
5546ac90 KH |
617 | { |
618 | if (op == CONST0_RTX (mode) && TARGET_SHMEDIA) | |
619 | return 1; | |
620 | return register_operand (op, mode); | |
621 | }) | |
622 | ||
623 | ;; TODO: Add a comment here. | |
624 | ||
625 | (define_predicate "sh_rep_vec" | |
b4060d3f | 626 | (match_code "const_vector,parallel") |
5546ac90 KH |
627 | { |
628 | int i; | |
629 | rtx x, y; | |
630 | ||
631 | if ((GET_CODE (op) != CONST_VECTOR && GET_CODE (op) != PARALLEL) | |
632 | || (GET_MODE (op) != mode && mode != VOIDmode)) | |
633 | return 0; | |
634 | i = XVECLEN (op, 0) - 2; | |
635 | x = XVECEXP (op, 0, i + 1); | |
636 | if (GET_MODE_UNIT_SIZE (mode) == 1) | |
637 | { | |
638 | y = XVECEXP (op, 0, i); | |
639 | for (i -= 2; i >= 0; i -= 2) | |
640 | if (! rtx_equal_p (XVECEXP (op, 0, i + 1), x) | |
641 | || ! rtx_equal_p (XVECEXP (op, 0, i), y)) | |
642 | return 0; | |
643 | } | |
644 | else | |
645 | for (; i >= 0; i--) | |
646 | if (XVECEXP (op, 0, i) != x) | |
647 | return 0; | |
648 | return 1; | |
649 | }) | |
650 | ||
651 | ;; TODO: Add a comment here. | |
652 | ||
653 | (define_predicate "shift_count_operand" | |
654 | (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,zero_extend,sign_extend") | |
655 | { | |
656 | return (CONSTANT_P (op) | |
657 | ? (GET_CODE (op) == CONST_INT | |
658 | ? (unsigned) INTVAL (op) < GET_MODE_BITSIZE (mode) | |
659 | : nonmemory_operand (op, mode)) | |
660 | : shift_count_reg_operand (op, mode)); | |
661 | }) | |
662 | ||
663 | ;; TODO: Add a comment here. | |
664 | ||
665 | (define_predicate "shift_count_reg_operand" | |
666 | (match_code "subreg,reg,zero_extend,sign_extend") | |
667 | { | |
668 | if ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND | |
669 | || (GET_CODE (op) == SUBREG && SUBREG_BYTE (op) == 0)) | |
670 | && (mode == VOIDmode || mode == GET_MODE (op)) | |
671 | && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6 | |
672 | && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT) | |
673 | { | |
674 | mode = VOIDmode; | |
675 | do | |
676 | op = XEXP (op, 0); | |
677 | while ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND | |
678 | || GET_CODE (op) == TRUNCATE) | |
679 | && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6 | |
680 | && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT); | |
681 | ||
682 | } | |
683 | return arith_reg_operand (op, mode); | |
684 | }) | |
685 | ||
686 | ;; TODO: Add a comment here. | |
687 | ||
688 | (define_predicate "shift_operator" | |
f289c6a1 | 689 | (match_code "ashift,ashiftrt,lshiftrt")) |
5546ac90 KH |
690 | |
691 | ;; TODO: Add a comment here. | |
692 | ||
693 | (define_predicate "symbol_ref_operand" | |
f289c6a1 | 694 | (match_code "symbol_ref")) |
5546ac90 KH |
695 | |
696 | ;; Same as target_reg_operand, except that label_refs and symbol_refs | |
697 | ;; are accepted before reload. | |
698 | ||
699 | (define_special_predicate "target_operand" | |
700 | (match_code "subreg,reg,label_ref,symbol_ref,const,unspec") | |
701 | { | |
702 | if (mode != VOIDmode && mode != Pmode) | |
703 | return 0; | |
704 | ||
705 | if ((GET_MODE (op) == Pmode || GET_MODE (op) == VOIDmode) | |
32a7ab3d | 706 | && satisfies_constraint_Csy (op)) |
5546ac90 KH |
707 | return ! reload_completed; |
708 | ||
709 | return target_reg_operand (op, mode); | |
710 | }) | |
711 | ||
712 | ;; Accept pseudos and branch target registers. | |
713 | ||
714 | (define_special_predicate "target_reg_operand" | |
715 | (match_code "subreg,reg") | |
716 | { | |
717 | if (mode == VOIDmode | |
718 | ? GET_MODE (op) != Pmode && GET_MODE (op) != PDImode | |
719 | : mode != GET_MODE (op)) | |
720 | return 0; | |
721 | ||
722 | if (GET_CODE (op) == SUBREG) | |
723 | op = XEXP (op, 0); | |
724 | ||
725 | if (GET_CODE (op) != REG) | |
726 | return 0; | |
727 | ||
728 | /* We must protect ourselves from matching pseudos that are virtual | |
729 | register, because they will eventually be replaced with hardware | |
730 | registers that aren't branch-target registers. */ | |
731 | if (REGNO (op) > LAST_VIRTUAL_REGISTER | |
732 | || TARGET_REGISTER_P (REGNO (op))) | |
733 | return 1; | |
734 | ||
735 | return 0; | |
736 | }) | |
737 | ||
738 | ;; TODO: Add a comment here. | |
739 | ||
740 | (define_special_predicate "trunc_hi_operand" | |
741 | (match_code "subreg,reg,truncate") | |
742 | { | |
743 | enum machine_mode op_mode = GET_MODE (op); | |
744 | ||
745 | if (op_mode != SImode && op_mode != DImode | |
746 | && op_mode != V4HImode && op_mode != V2SImode) | |
747 | return 0; | |
748 | return extend_reg_operand (op, mode); | |
749 | }) | |
750 | ||
f705a9a0 | 751 | ;; Return 1 of OP is an address suitable for an unaligned access instruction. |
5546ac90 | 752 | |
f705a9a0 | 753 | (define_special_predicate "ua_address_operand" |
5546ac90 KH |
754 | (match_code "subreg,reg,plus") |
755 | { | |
756 | if (GET_CODE (op) == PLUS | |
32a7ab3d | 757 | && (! satisfies_constraint_I06 (XEXP (op, 1)))) |
5546ac90 KH |
758 | return 0; |
759 | return address_operand (op, QImode); | |
760 | }) | |
761 | ||
762 | ;; TODO: Add a comment here. | |
763 | ||
764 | (define_predicate "ua_offset" | |
765 | (match_code "const_int") | |
766 | { | |
32a7ab3d | 767 | return satisfies_constraint_I06 (op); |
5546ac90 KH |
768 | }) |
769 | ||
770 | ;; TODO: Add a comment here. | |
771 | ||
772 | (define_predicate "unary_float_operator" | |
f289c6a1 KH |
773 | (and (match_code "abs,neg,sqrt") |
774 | (match_test "GET_MODE (op) == mode"))) | |
5546ac90 KH |
775 | |
776 | ;; Return 1 if OP is a valid source operand for xor. | |
777 | ||
778 | (define_predicate "xor_operand" | |
779 | (match_code "subreg,reg,const_int") | |
780 | { | |
781 | if (GET_CODE (op) == CONST_INT) | |
782 | return (TARGET_SHMEDIA | |
32a7ab3d | 783 | ? (satisfies_constraint_I06 (op) |
b3a13419 | 784 | || (!can_create_pseudo_p () && INTVAL (op) == 0xff)) |
32a7ab3d | 785 | : satisfies_constraint_K08 (op)); |
5546ac90 KH |
786 | if (TARGET_SHMEDIA |
787 | && mode != DImode && GET_CODE (op) == SUBREG | |
788 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) | |
789 | return 0; | |
790 | return arith_reg_operand (op, mode); | |
791 | }) |