Mercurial > hg > CbC > CbC_gcc
annotate gcc/config/s390/predicates.md @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | 04ced10e8804 |
rev | line source |
---|---|
0 | 1 ;; Predicate definitions for S/390 and zSeries. |
2 ;; Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. | |
3 ;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and | |
4 ;; Ulrich Weigand (uweigand@de.ibm.com). | |
5 ;; | |
6 ;; This file is part of GCC. | |
7 ;; | |
8 ;; GCC is free software; you can redistribute it and/or modify | |
9 ;; it under the terms of the GNU General Public License as published by | |
10 ;; the Free Software Foundation; either version 3, or (at your option) | |
11 ;; any later version. | |
12 ;; | |
13 ;; GCC is distributed in the hope that it will be useful, | |
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 ;; GNU General Public License for more details. | |
17 ;; | |
18 ;; You should have received a copy of the GNU General Public License | |
19 ;; along with GCC; see the file COPYING3. If not see | |
20 ;; <http://www.gnu.org/licenses/>. | |
21 | |
22 ;; OP is the current operation. | |
23 ;; MODE is the current operation mode. | |
24 | |
25 ;; operands -------------------------------------------------------------- | |
26 | |
27 ;; Return true if OP a (const_int 0) operand. | |
28 | |
29 (define_predicate "const0_operand" | |
30 (and (match_code "const_int, const_double") | |
31 (match_test "op == CONST0_RTX (mode)"))) | |
32 | |
33 ;; Return true if OP is constant. | |
34 | |
35 (define_special_predicate "consttable_operand" | |
36 (and (match_code "symbol_ref, label_ref, const, const_int, const_double") | |
37 (match_test "CONSTANT_P (op)"))) | |
38 | |
39 ;; Return true if OP is a valid S-type operand. | |
40 | |
41 (define_predicate "s_operand" | |
42 (and (match_code "subreg, mem") | |
43 (match_operand 0 "general_operand")) | |
44 { | |
45 /* Just like memory_operand, allow (subreg (mem ...)) | |
46 after reload. */ | |
47 if (reload_completed | |
48 && GET_CODE (op) == SUBREG | |
49 && GET_CODE (SUBREG_REG (op)) == MEM) | |
50 op = SUBREG_REG (op); | |
51 | |
52 if (GET_CODE (op) != MEM) | |
53 return false; | |
54 if (!s390_legitimate_address_without_index_p (op)) | |
55 return false; | |
56 | |
57 return true; | |
58 }) | |
59 | |
60 ;; Return true if OP is a valid operand for the BRAS instruction. | |
61 ;; Allow SYMBOL_REFs and @PLT stubs. | |
62 | |
63 (define_special_predicate "bras_sym_operand" | |
64 (ior (and (match_code "symbol_ref") | |
65 (match_test "!flag_pic || SYMBOL_REF_LOCAL_P (op)")) | |
66 (and (match_code "const") | |
67 (and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC") | |
68 (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_PLT"))))) | |
69 | |
70 ;; Return true if OP is a PLUS that is not a legitimate | |
71 ;; operand for the LA instruction. | |
72 | |
73 (define_predicate "s390_plus_operand" | |
74 (and (match_code "plus") | |
75 (and (match_test "mode == Pmode") | |
76 (match_test "!legitimate_la_operand_p (op)")))) | |
77 | |
78 ;; Return true if OP is a valid operand as shift count or setmem. | |
79 | |
80 (define_predicate "shift_count_or_setmem_operand" | |
81 (match_code "reg, subreg, plus, const_int") | |
82 { | |
83 HOST_WIDE_INT offset; | |
84 rtx base; | |
85 | |
86 /* Extract base register and offset. */ | |
87 if (!s390_decompose_shift_count (op, &base, &offset)) | |
88 return false; | |
89 | |
90 /* Don't allow any non-base hard registers. Doing so without | |
91 confusing reload and/or regrename would be tricky, and doesn't | |
92 buy us much anyway. */ | |
93 if (base && REGNO (base) < FIRST_PSEUDO_REGISTER && !ADDR_REG_P (base)) | |
94 return false; | |
95 | |
96 /* Unfortunately we have to reject constants that are invalid | |
97 for an address, or else reload will get confused. */ | |
98 if (!DISP_IN_RANGE (offset)) | |
99 return false; | |
100 | |
101 return true; | |
102 }) | |
103 | |
104 ;; Return true if OP a valid operand for the LARL instruction. | |
105 | |
106 (define_predicate "larl_operand" | |
107 (match_code "label_ref, symbol_ref, const, const_int, const_double") | |
108 { | |
109 /* Allow labels and local symbols. */ | |
110 if (GET_CODE (op) == LABEL_REF) | |
111 return true; | |
112 if (GET_CODE (op) == SYMBOL_REF) | |
113 return (!SYMBOL_REF_ALIGN1_P (op) | |
114 && SYMBOL_REF_TLS_MODEL (op) == 0 | |
115 && (!flag_pic || SYMBOL_REF_LOCAL_P (op))); | |
116 | |
117 /* Everything else must have a CONST, so strip it. */ | |
118 if (GET_CODE (op) != CONST) | |
119 return false; | |
120 op = XEXP (op, 0); | |
121 | |
122 /* Allow adding *even* in-range constants. */ | |
123 if (GET_CODE (op) == PLUS) | |
124 { | |
125 if (GET_CODE (XEXP (op, 1)) != CONST_INT | |
126 || (INTVAL (XEXP (op, 1)) & 1) != 0) | |
127 return false; | |
128 if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 31 | |
129 || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 31)) | |
130 return false; | |
131 op = XEXP (op, 0); | |
132 } | |
133 | |
134 /* Labels and local symbols allowed here as well. */ | |
135 if (GET_CODE (op) == LABEL_REF) | |
136 return true; | |
137 if (GET_CODE (op) == SYMBOL_REF) | |
138 return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0 | |
139 && SYMBOL_REF_TLS_MODEL (op) == 0 | |
140 && (!flag_pic || SYMBOL_REF_LOCAL_P (op))); | |
141 | |
142 /* Now we must have a @GOTENT offset or @PLT stub | |
143 or an @INDNTPOFF TLS offset. */ | |
144 if (GET_CODE (op) == UNSPEC | |
145 && XINT (op, 1) == UNSPEC_GOTENT) | |
146 return true; | |
147 if (GET_CODE (op) == UNSPEC | |
148 && XINT (op, 1) == UNSPEC_PLT) | |
149 return true; | |
150 if (GET_CODE (op) == UNSPEC | |
151 && XINT (op, 1) == UNSPEC_INDNTPOFF) | |
152 return true; | |
153 | |
154 return false; | |
155 }) | |
156 | |
157 ;; operators -------------------------------------------------------------- | |
158 | |
159 ;; Return nonzero if OP is a valid comparison operator | |
160 ;; for a branch condition. | |
161 | |
162 (define_predicate "s390_comparison" | |
163 (match_code "eq, ne, lt, gt, le, ge, ltu, gtu, leu, geu, | |
164 uneq, unlt, ungt, unle, unge, ltgt, | |
165 unordered, ordered") | |
166 { | |
167 if (GET_CODE (XEXP (op, 0)) != REG | |
168 || REGNO (XEXP (op, 0)) != CC_REGNUM | |
169 || XEXP (op, 1) != const0_rtx) | |
170 return false; | |
171 | |
172 return (s390_branch_condition_mask (op) >= 0); | |
173 }) | |
174 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
175 ;; Return true if op is the cc register. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
176 (define_predicate "cc_reg_operand" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
177 (and (match_code "reg") |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
178 (match_test "REGNO (op) == CC_REGNUM"))) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
179 |
0 | 180 (define_predicate "s390_signed_integer_comparison" |
181 (match_code "eq, ne, lt, gt, le, ge") | |
182 { | |
183 return (s390_compare_and_branch_condition_mask (op) >= 0); | |
184 }) | |
185 | |
186 (define_predicate "s390_unsigned_integer_comparison" | |
187 (match_code "eq, ne, ltu, gtu, leu, geu") | |
188 { | |
189 return (s390_compare_and_branch_condition_mask (op) >= 0); | |
190 }) | |
191 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
192 ;; Return nonzero if OP is a valid comparison operator for the |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
193 ;; cstore expanders -- respectively cstorecc4 and integer cstore. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
194 (define_predicate "s390_eqne_operator" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
195 (match_code "eq, ne")) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
196 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
197 (define_predicate "s390_scond_operator" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
198 (match_code "ltu, gtu, leu, geu")) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
199 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
200 (define_predicate "s390_brx_operator" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
201 (match_code "le, gt")) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
202 |
0 | 203 ;; Return nonzero if OP is a valid comparison operator |
204 ;; for an ALC condition. | |
205 | |
206 (define_predicate "s390_alc_comparison" | |
207 (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu") | |
208 { | |
209 while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND) | |
210 op = XEXP (op, 0); | |
211 | |
212 if (!COMPARISON_P (op)) | |
213 return false; | |
214 | |
215 if (GET_CODE (XEXP (op, 0)) != REG | |
216 || REGNO (XEXP (op, 0)) != CC_REGNUM | |
217 || XEXP (op, 1) != const0_rtx) | |
218 return false; | |
219 | |
220 switch (GET_MODE (XEXP (op, 0))) | |
221 { | |
222 case CCL1mode: | |
223 return GET_CODE (op) == LTU; | |
224 | |
225 case CCL2mode: | |
226 return GET_CODE (op) == LEU; | |
227 | |
228 case CCL3mode: | |
229 return GET_CODE (op) == GEU; | |
230 | |
231 case CCUmode: | |
232 return GET_CODE (op) == GTU; | |
233 | |
234 case CCURmode: | |
235 return GET_CODE (op) == LTU; | |
236 | |
237 case CCSmode: | |
238 return GET_CODE (op) == UNGT; | |
239 | |
240 case CCSRmode: | |
241 return GET_CODE (op) == UNLT; | |
242 | |
243 default: | |
244 return false; | |
245 } | |
246 }) | |
247 | |
248 ;; Return nonzero if OP is a valid comparison operator | |
249 ;; for an SLB condition. | |
250 | |
251 (define_predicate "s390_slb_comparison" | |
252 (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu") | |
253 { | |
254 while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND) | |
255 op = XEXP (op, 0); | |
256 | |
257 if (!COMPARISON_P (op)) | |
258 return false; | |
259 | |
260 if (GET_CODE (XEXP (op, 0)) != REG | |
261 || REGNO (XEXP (op, 0)) != CC_REGNUM | |
262 || XEXP (op, 1) != const0_rtx) | |
263 return false; | |
264 | |
265 switch (GET_MODE (XEXP (op, 0))) | |
266 { | |
267 case CCL1mode: | |
268 return GET_CODE (op) == GEU; | |
269 | |
270 case CCL2mode: | |
271 return GET_CODE (op) == GTU; | |
272 | |
273 case CCL3mode: | |
274 return GET_CODE (op) == LTU; | |
275 | |
276 case CCUmode: | |
277 return GET_CODE (op) == LEU; | |
278 | |
279 case CCURmode: | |
280 return GET_CODE (op) == GEU; | |
281 | |
282 case CCSmode: | |
283 return GET_CODE (op) == LE; | |
284 | |
285 case CCSRmode: | |
286 return GET_CODE (op) == GE; | |
287 | |
288 default: | |
289 return false; | |
290 } | |
291 }) | |
292 | |
293 ;; Return true if OP is a load multiple operation. It is known to be a | |
294 ;; PARALLEL and the first section will be tested. | |
295 | |
296 (define_special_predicate "load_multiple_operation" | |
297 (match_code "parallel") | |
298 { | |
299 enum machine_mode elt_mode; | |
300 int count = XVECLEN (op, 0); | |
301 unsigned int dest_regno; | |
302 rtx src_addr; | |
303 int i, off; | |
304 | |
305 /* Perform a quick check so we don't blow up below. */ | |
306 if (count <= 1 | |
307 || GET_CODE (XVECEXP (op, 0, 0)) != SET | |
308 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG | |
309 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM) | |
310 return false; | |
311 | |
312 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0))); | |
313 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0); | |
314 elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0))); | |
315 | |
316 /* Check, is base, or base + displacement. */ | |
317 | |
318 if (GET_CODE (src_addr) == REG) | |
319 off = 0; | |
320 else if (GET_CODE (src_addr) == PLUS | |
321 && GET_CODE (XEXP (src_addr, 0)) == REG | |
322 && GET_CODE (XEXP (src_addr, 1)) == CONST_INT) | |
323 { | |
324 off = INTVAL (XEXP (src_addr, 1)); | |
325 src_addr = XEXP (src_addr, 0); | |
326 } | |
327 else | |
328 return false; | |
329 | |
330 for (i = 1; i < count; i++) | |
331 { | |
332 rtx elt = XVECEXP (op, 0, i); | |
333 | |
334 if (GET_CODE (elt) != SET | |
335 || GET_CODE (SET_DEST (elt)) != REG | |
336 || GET_MODE (SET_DEST (elt)) != elt_mode | |
337 || REGNO (SET_DEST (elt)) != dest_regno + i | |
338 || GET_CODE (SET_SRC (elt)) != MEM | |
339 || GET_MODE (SET_SRC (elt)) != elt_mode | |
340 || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS | |
341 || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) | |
342 || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT | |
343 || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) | |
344 != off + i * GET_MODE_SIZE (elt_mode)) | |
345 return false; | |
346 } | |
347 | |
348 return true; | |
349 }) | |
350 | |
351 ;; Return true if OP is a store multiple operation. It is known to be a | |
352 ;; PARALLEL and the first section will be tested. | |
353 | |
354 (define_special_predicate "store_multiple_operation" | |
355 (match_code "parallel") | |
356 { | |
357 enum machine_mode elt_mode; | |
358 int count = XVECLEN (op, 0); | |
359 unsigned int src_regno; | |
360 rtx dest_addr; | |
361 int i, off; | |
362 | |
363 /* Perform a quick check so we don't blow up below. */ | |
364 if (count <= 1 | |
365 || GET_CODE (XVECEXP (op, 0, 0)) != SET | |
366 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM | |
367 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG) | |
368 return false; | |
369 | |
370 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0))); | |
371 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0); | |
372 elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0))); | |
373 | |
374 /* Check, is base, or base + displacement. */ | |
375 | |
376 if (GET_CODE (dest_addr) == REG) | |
377 off = 0; | |
378 else if (GET_CODE (dest_addr) == PLUS | |
379 && GET_CODE (XEXP (dest_addr, 0)) == REG | |
380 && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT) | |
381 { | |
382 off = INTVAL (XEXP (dest_addr, 1)); | |
383 dest_addr = XEXP (dest_addr, 0); | |
384 } | |
385 else | |
386 return false; | |
387 | |
388 for (i = 1; i < count; i++) | |
389 { | |
390 rtx elt = XVECEXP (op, 0, i); | |
391 | |
392 if (GET_CODE (elt) != SET | |
393 || GET_CODE (SET_SRC (elt)) != REG | |
394 || GET_MODE (SET_SRC (elt)) != elt_mode | |
395 || REGNO (SET_SRC (elt)) != src_regno + i | |
396 || GET_CODE (SET_DEST (elt)) != MEM | |
397 || GET_MODE (SET_DEST (elt)) != elt_mode | |
398 || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS | |
399 || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) | |
400 || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT | |
401 || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) | |
402 != off + i * GET_MODE_SIZE (elt_mode)) | |
403 return false; | |
404 } | |
405 return true; | |
406 }) |