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