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