]>
Commit | Line | Data |
---|---|---|
0b85d816 | 1 | ;; GCC machine description for CRIS cpu cores. |
7adcbafe | 2 | ;; Copyright (C) 1998-2022 Free Software Foundation, Inc. |
0b85d816 HPN |
3 | ;; Contributed by Axis Communications. |
4 | ||
5 | ;; This file is part of GCC. | |
6 | ;; | |
7 | ;; GCC is free software; you can redistribute it and/or modify | |
8 | ;; it under the terms of the GNU General Public License as published by | |
748086b7 | 9 | ;; the Free Software Foundation; either version 3, or (at your option) |
0b85d816 HPN |
10 | ;; any later version. |
11 | ;; | |
12 | ;; GCC is distributed in the hope that it will be useful, | |
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | ;; GNU General Public License for more details. | |
16 | ;; | |
17 | ;; You should have received a copy of the GNU General Public License | |
2f83c7d6 NC |
18 | ;; along with GCC; see the file COPYING3. If not see |
19 | ;; <http://www.gnu.org/licenses/>. | |
0b85d816 HPN |
20 | |
21 | ;; The original PO technology requires these to be ordered by speed, | |
22 | ;; so that assigner will pick the fastest. | |
23 | ||
24 | ;; See files "md.texi" and "rtl.def" for documentation on define_insn, | |
25 | ;; match_*, et. al. | |
0b85d816 HPN |
26 | |
27 | ;; There are several instructions that are orthogonal in size, and seems | |
28 | ;; they could be matched by a single pattern without a specified size | |
29 | ;; for the operand that is orthogonal. However, this did not work on | |
839a4992 | 30 | ;; gcc-2.7.2 (and probably not on gcc-2.8.1), relating to that when a |
0b85d816 HPN |
31 | ;; constant is substituted into an operand, the actual mode must be |
32 | ;; deduced from the pattern. There is reasonable hope that that has been | |
d2f55c5c | 33 | ;; fixed, so FIXME: try again. |
0b85d816 HPN |
34 | |
35 | ;; You will notice that three-operand alternatives ("=r", "r", "!To") | |
36 | ;; are marked with a "!" constraint modifier to avoid being reloaded | |
37 | ;; into. This is because gcc would otherwise prefer to use the constant | |
38 | ;; pool and its offsettable address instead of reloading to an | |
39 | ;; ("=r", "0", "i") alternative. Also, the constant-pool support was not | |
40 | ;; only suboptimal but also buggy in 2.7.2, ??? maybe only in 2.6.3. | |
41 | ||
42 | ;; All insns that look like (set (...) (plus (...) (reg:SI 8))) | |
43 | ;; get problems when reloading r8 (frame pointer) to r14 + offs (stack | |
44 | ;; pointer). Thus the instructions that get into trouble have specific | |
45 | ;; checks against matching frame_pointer_rtx. | |
46 | ;; ??? But it should be re-checked for gcc > 2.7.2 | |
47 | ;; FIXME: This changed some time ago (from 2000-03-16) for gcc-2.9x. | |
48 | ||
21ed4444 | 49 | (define_c_enum "" |
45d5d09c | 50 | [ |
45d5d09c | 51 | ;; Stack frame deallocation barrier. |
21ed4444 | 52 | CRIS_UNSPEC_FRAME_DEALLOC |
45d5d09c HPN |
53 | |
54 | ;; Swap all 32 bits of the operand; 31 <=> 0, 30 <=> 1... | |
21ed4444 | 55 | CRIS_UNSPEC_SWAP_BITS |
45d5d09c | 56 | ]) |
f60c7155 HPN |
57 | |
58 | ;; Register numbers. | |
59 | (define_constants | |
d0780379 | 60 | [(CRIS_STATIC_CHAIN_REGNUM 7) |
aa27696b | 61 | (CRIS_REAL_FP_REGNUM 8) |
f60c7155 | 62 | (CRIS_SP_REGNUM 14) |
45d5d09c | 63 | (CRIS_ACR_REGNUM 15) |
f60c7155 | 64 | (CRIS_SRP_REGNUM 16) |
f9968e3e HPN |
65 | (CRIS_MOF_REGNUM 17) |
66 | (CRIS_AP_REGNUM 18) | |
aa27696b HPN |
67 | (CRIS_CC0_REGNUM 19) |
68 | (CRIS_FP_REGNUM 20)] | |
f60c7155 HPN |
69 | ) |
70 | ||
0b85d816 HPN |
71 | ;; We need an attribute to define whether an instruction can be put in |
72 | ;; a branch-delay slot or not, and whether it has a delay slot. | |
73 | ;; | |
74 | ;; Branches and return instructions have a delay slot, and cannot | |
75 | ;; themselves be put in a delay slot. This has changed *for short | |
76 | ;; branches only* between architecture variants, but the possible win | |
77 | ;; is presumed negligible compared to the added complexity of the machine | |
78 | ;; description: one would have to add always-correct infrastructure to | |
79 | ;; distinguish short branches. | |
80 | ;; | |
81 | ;; Whether an instruction can be put in a delay slot depends on the | |
82 | ;; instruction (all short instructions except jumps and branches) | |
83 | ;; and the addressing mode (must not be prefixed or referring to pc). | |
84 | ;; In short, any "slottable" instruction must be 16 bit and not refer | |
85 | ;; to pc, or alter it. | |
86 | ;; | |
d0780379 HPN |
87 | ;; The possible values are "yes", "no", "has_slot", and "has_return_slot". |
88 | ;; Yes/no tells whether the insn is slottable or not. | |
45d5d09c HPN |
89 | ;; Of special concern is that no RTX_FRAME_RELATED insn must go in that |
90 | ;; call delay slot, as it's located in the address *after* the call insn, | |
91 | ;; and the unwind machinery doesn't know about delay slots. | |
92 | ;; Has_slot means that the insn is a branch insn (which are | |
93 | ;; not considered slottable since that is generally true). Having the | |
94 | ;; seemingly illogical value "has_slot" means we do not have to add | |
95 | ;; another attribute just to say that an insn has a delay-slot, since it | |
96 | ;; also infers that it is not slottable. Better names for the attribute | |
97 | ;; were found to be longer and not add readability to the machine | |
98 | ;; description. | |
99 | ;; Has_return_slot is similar, for the return insn. | |
0b85d816 HPN |
100 | ;; |
101 | ;; The default that is defined here for this attribute is "no", not | |
102 | ;; slottable, not having a delay-slot, so there's no need to worry about | |
103 | ;; it being wrong for non-branch and return instructions. | |
104 | ;; The default could depend on the kind of insn and the addressing | |
105 | ;; mode, but that would need more attributes and hairier, more error | |
106 | ;; prone code. | |
107 | ;; | |
23369bef HPN |
108 | ;; There is an extra memory constraint, 'Q', which recognizes an indirect |
109 | ;; register. The constraints 'Q' and '>' together match all possible | |
110 | ;; memory operands that are slottable. | |
0b85d816 HPN |
111 | ;; For other operands, you need to check if it has a valid "slottable" |
112 | ;; quick-immediate operand, where the particular signedness-variation | |
113 | ;; may match the constraints 'I' or 'J'.), and include it in the | |
114 | ;; constraint pattern for the slottable pattern. An alternative using | |
115 | ;; only "r" constraints is most often slottable. | |
116 | ||
d0780379 | 117 | (define_attr "slottable" "no,yes,has_slot,has_return_slot" |
45d5d09c | 118 | (const_string "no")) |
0b85d816 HPN |
119 | |
120 | ;; We also need attributes to sanely determine the condition code | |
a82c9fb3 HPN |
121 | ;; state. This attribute isn't used as-is, just as a template, |
122 | ;; effectively a dummy except in a substitution setting CRIS_CC0_REGNUM | |
123 | ;; to a specific value. | |
fb062a8b | 124 | (define_attr "cc" "none,clobber,normal" (const_string "normal")) |
0b85d816 | 125 | |
a82c9fb3 HPN |
126 | ;; The attribute "_enabled" is appended to "cc", forming "cc_enabled" to |
127 | ;; pick out certain alternatives when generating a useful | |
128 | ;; condition-code-setting. See the "enabled" attribute. | |
129 | (define_attr "cc_enabled" "none,clobber,normal" (const_string "normal")) | |
130 | ||
3a5afdfc HPN |
131 | ;; At the moment, this attribute is just used to help bb-reorder do its |
132 | ;; work; the default 0 doesn't help it. Many insns have other lengths, | |
133 | ;; though none are shorter. | |
134 | (define_attr "length" "" (const_int 2)) | |
135 | ||
45d5d09c | 136 | ;; A branch has one delay-slot. The instruction in the |
0b85d816 HPN |
137 | ;; delay-slot is always executed, independent of whether the branch is |
138 | ;; taken or not. Note that besides setting "slottable" to "has_slot", | |
139 | ;; there also has to be a "%#" at the end of a "delayed" instruction | |
140 | ;; output pattern (for "jump" this means "ba %l0%#"), so print_operand can | |
141 | ;; catch it and print a "nop" if necessary. This method was stolen from | |
142 | ;; sparc.md. | |
143 | ||
144 | (define_delay (eq_attr "slottable" "has_slot") | |
145 | [(eq_attr "slottable" "yes") (nil) (nil)]) | |
45d5d09c | 146 | |
45d5d09c HPN |
147 | ;; The insn in the return insn slot must not be the |
148 | ;; return-address-register restore. FIXME: Use has_slot and express | |
149 | ;; as a parallel with a use of the return-address-register (currently | |
150 | ;; only SRP). However, this requires an amount of fixing tests for | |
151 | ;; naked RETURN in middle-end. | |
152 | (define_delay (eq_attr "slottable" "has_return_slot") | |
153 | [(and (eq_attr "slottable" "yes") | |
bf0b8cbe | 154 | (not (match_test "dead_or_set_regno_p (insn, CRIS_SRP_REGNUM)"))) |
45d5d09c HPN |
155 | (nil) (nil)]) |
156 | ||
a82c9fb3 HPN |
157 | (define_attr "enabled" "no,yes" |
158 | (if_then_else | |
159 | (eq_attr "cc_enabled" "normal") | |
160 | (const_string "yes") | |
161 | (const_string "no"))) | |
0b85d816 | 162 | \f |
22c3c091 HPN |
163 | ;; Iterator definitions. |
164 | ||
165 | ;; For the "usual" pattern size alternatives. | |
3abcb3a7 | 166 | (define_mode_iterator BWD [SI HI QI]) |
fb062a8b HPN |
167 | (define_mode_iterator BWDD [DI SI HI QI]) |
168 | ||
169 | ;; To be able to refer to the same mode_attr for both a multi-mode | |
170 | ;; and a mode-specific pattern, we use some singleton iterators. | |
171 | (define_mode_iterator DI_ [DI]) | |
172 | (define_mode_iterator SI_ [SI]) | |
173 | ||
3abcb3a7 HPN |
174 | (define_mode_iterator WD [SI HI]) |
175 | (define_mode_iterator BW [HI QI]) | |
22c3c091 HPN |
176 | (define_mode_attr S [(SI "HI") (HI "QI")]) |
177 | (define_mode_attr s [(SI "hi") (HI "qi")]) | |
178 | (define_mode_attr m [(SI ".d") (HI ".w") (QI ".b")]) | |
179 | (define_mode_attr mm [(SI ".w") (HI ".b")]) | |
180 | (define_mode_attr nbitsm1 [(SI "31") (HI "15") (QI "7")]) | |
181 | ||
182 | ;; For the sign_extend+zero_extend variants. | |
3abcb3a7 | 183 | (define_code_iterator szext [sign_extend zero_extend]) |
22c3c091 HPN |
184 | (define_code_attr u [(sign_extend "") (zero_extend "u")]) |
185 | (define_code_attr su [(sign_extend "s") (zero_extend "u")]) | |
186 | ||
9596eccb HPN |
187 | ;; For extended-operand variants. |
188 | (define_code_iterator plusminus [plus minus]) | |
189 | (define_code_attr addsub [(plus "add") (minus "sub")]) | |
190 | ||
191 | ;; Similar, other cases also matching bound/umin. | |
192 | (define_code_iterator plusminusumin [plus minus umin]) | |
193 | ||
194 | ;; Ditto, commutative operators (i.e. not minus). | |
195 | (define_code_iterator plusumin [plus umin]) | |
196 | ||
197 | ;; The addsubbo and nd code-attributes form a hack. We need to output | |
198 | ;; "addu.b", "subu.b" but "bound.b" (no "u"-suffix) which means we'd | |
199 | ;; need to refer to one iterator from the next. But, that can't be | |
200 | ;; done. Instead output the "u" for unsigned as the "u" in "bound", | |
201 | ;; i.e. the mnemonic as three parts including the extend-letter, and | |
202 | ;; with an empty third part for "add" and "sub". | |
203 | (define_code_attr addsubbo [(plus "add") (minus "sub") (umin "bo")]) | |
204 | (define_code_attr nd [(plus "") (minus "") (umin "nd")]) | |
205 | ||
22c3c091 | 206 | ;; For the shift variants. |
3abcb3a7 HPN |
207 | (define_code_iterator shift [ashiftrt lshiftrt ashift]) |
208 | (define_code_iterator shiftrt [ashiftrt lshiftrt]) | |
22c3c091 HPN |
209 | (define_code_attr shlr [(ashiftrt "ashr") (lshiftrt "lshr") (ashift "ashl")]) |
210 | (define_code_attr slr [(ashiftrt "asr") (lshiftrt "lsr") (ashift "lsl")]) | |
211 | ||
b3e01c3d HPN |
212 | ;; Compares, branches, cbranch, cstore. Conditions gt and le are CC_NZVC. |
213 | ;; Others start out as CCmode and can degenerate to CC_NZmode. | |
214 | ;; Incidental setters are either CC_NZVCmode or CC_NZmode. See also | |
215 | ;; cris-modes.def. | |
216 | (define_mode_iterator NZSET [CC_NZ]) | |
217 | (define_mode_iterator NZUSE [CC CC_NZ CC_NZVC]) | |
218 | (define_mode_iterator NZVCSET [CC CC_NZVC CC_NZ]) | |
219 | (define_mode_iterator NZVCUSE [CC_NZVC]) | |
b73bf8a1 HPN |
220 | (define_mode_iterator ZnNNZSET [CC_ZnN CC_NZ]) |
221 | (define_mode_iterator ZnNNZUSE [CC CC_ZnN CC_NZ CC_NZVC]) | |
b3e01c3d HPN |
222 | |
223 | ;; All conditions. | |
224 | (define_code_iterator cond [eq ne gtu ltu geu leu gt le lt ge]) | |
225 | ||
226 | ;; Just equal and not equal. | |
27228024 | 227 | (define_code_iterator zcond [eq ne]) |
b3e01c3d HPN |
228 | |
229 | ;; Conditions that look only at Z and/or N (or can do with that). | |
230 | (define_code_iterator nzcond [eq ne gtu leu lt ge]) | |
231 | ||
232 | ;; The complement of nzcond within cond; conditions that look (also) on V | |
233 | ;; or C. | |
234 | (define_code_iterator nzvccond [geu ltu gt le]) | |
235 | ||
236 | ;; Within nzcond, those that give different opcodes when operands are | |
237 | ;; reversed or that can ignore V or C. Also, the complement of zcond | |
238 | ;; within nzcond. | |
239 | (define_code_iterator rnzcond [gtu leu lt ge]) | |
240 | ||
241 | ;; CRIS condition mnemonic. | |
22c3c091 HPN |
242 | (define_code_attr CC [(eq "eq") (ne "ne") (gt "gt") (gtu "hi") (lt "lt") |
243 | (ltu "lo") (ge "ge") (geu "hs") (le "le") (leu "ls")]) | |
b3e01c3d HPN |
244 | |
245 | ;; CRIS reverse condition mnemonic. | |
22c3c091 HPN |
246 | (define_code_attr rCC [(eq "ne") (ne "eq") (gt "le") (gtu "ls") (lt "ge") |
247 | (ltu "hs") (ge "lt") (geu "lo") (le "gt") (leu "hi")]) | |
b3e01c3d HPN |
248 | |
249 | ;; Mnemomic for the CRIS condition when V or C can be ignored. | |
250 | (define_code_attr oCC [(lt "mi") (ge "pl") (gtu "eq") (ltu "ne")]) | |
251 | ||
252 | ;; Reverse of oCC. | |
253 | (define_code_attr roCC [(lt "pl") (ge "mi") (gtu "eq") (ltu "ne")]) | |
254 | ||
b73bf8a1 HPN |
255 | ;; CC_Z_IN_NOT_N, a.k.a. CC_ZnNmode. |
256 | (define_code_attr znnCC [(eq "pl") (ne "mi")]) | |
257 | ||
258 | ;;; ...and the reverse | |
259 | (define_code_attr rznnCC [(eq "mi") (ne "pl")]) | |
260 | ||
b3e01c3d HPN |
261 | ;; Required unoptimized CCmode, different for nzcond and nzvccond. |
262 | (define_code_attr xCC [(eq "CC") (ne "CC") (gtu "CC") (ltu "CC_NZVC") | |
263 | (geu "CC_NZVC") (leu "CC") (lt "CC") (ge "CC") | |
264 | (gt "CC_NZVC") (le "CC_NZVC")]) | |
22c3c091 | 265 | |
a82c9fb3 HPN |
266 | ;; Substitutions to describe condition-code settings. |
267 | ||
268 | (define_subst_attr "setnz" "setnz_subst" "" "_setnz") | |
269 | (define_subst_attr "ccnz" "setnz_subst" "" "_enabled") | |
3c7016b0 | 270 | (define_subst_attr "anz" "setnz_subst" "" "*") |
a82c9fb3 HPN |
271 | |
272 | (define_subst "setnz_subst" | |
273 | [(set (match_operand 0) | |
274 | (match_operand 1)) | |
275 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
276 | "reload_completed" | |
277 | [(set (reg:CC_NZ CRIS_CC0_REGNUM) | |
278 | (compare:CC_NZ (match_dup 1) (const_int 0))) | |
f4ac1a7f | 279 | (set (match_dup 0) (match_dup 1))]) |
a82c9fb3 HPN |
280 | |
281 | (define_subst_attr "setnzvc" "setnzvc_subst" "" "_setnzvc") | |
282 | (define_subst_attr "ccnzvc" "setnzvc_subst" "" "_enabled") | |
3c7016b0 | 283 | (define_subst_attr "anzvc" "setnzvc_subst" "" "*") |
a82c9fb3 HPN |
284 | |
285 | (define_subst "setnzvc_subst" | |
286 | [(set (match_operand 0) | |
287 | (match_operand 1)) | |
288 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
289 | "reload_completed" | |
290 | [(set (reg:CC_NZVC CRIS_CC0_REGNUM) | |
291 | (compare:CC_NZVC (match_dup 1) (const_int 0))) | |
f4ac1a7f | 292 | (set (match_dup 0) (match_dup 1))]) |
a82c9fb3 HPN |
293 | |
294 | (define_subst_attr "setcc" "setcc_subst" "" "_setcc") | |
295 | (define_subst_attr "cccc" "setcc_subst" "" "_enabled") | |
3c7016b0 | 296 | (define_subst_attr "acc" "setcc_subst" "" "*") |
a82c9fb3 HPN |
297 | |
298 | (define_subst "setcc_subst" | |
299 | [(set (match_operand 0) | |
300 | (match_operand 1)) | |
301 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
302 | "reload_completed" | |
303 | [(set (reg:CC CRIS_CC0_REGNUM) | |
304 | (compare:CC (match_dup 1) (const_int 0))) | |
f4ac1a7f | 305 | (set (match_dup 0) (match_dup 1))]) |
a82c9fb3 | 306 | |
68a81332 HPN |
307 | ;; Operand and operator predicates. |
308 | ||
309 | (include "predicates.md") | |
06cadf63 | 310 | (include "constraints.md") |
68a81332 | 311 | \f |
0b85d816 HPN |
312 | ;; It seems that the position of the sign-bit and the fact that 0.0 is |
313 | ;; all 0-bits would make "tstsf" a straight-forward implementation; | |
314 | ;; either "test.d" it for positive/negative or "btstq 30,r" it for | |
315 | ;; zeroness. | |
316 | ;; | |
fb062a8b | 317 | ;; FIXME: Do that some time. |
0b85d816 HPN |
318 | \f |
319 | ;; Compare insns. | |
320 | ||
fb062a8b HPN |
321 | ;; These are used for compare insn, cbranch and cstore. |
322 | ;; FIXME: Port-local reversing of operands is not done. Still needed? | |
323 | ;; (It shouldn't be; it should be done as part of register allocation.) | |
324 | (define_mode_attr sCC_destc | |
325 | [(DI "r, r,r,r,r,r,r") (SI "r,r, r, r,r,r") (HI "r, r, r,r") (QI "r, r, r,r")]) | |
b3e01c3d | 326 | (define_mode_attr cmp_op0c |
fb062a8b | 327 | [(DI "rm,r,r,r,r,r,r") (SI "r,r, rQ>,r,r,m") (HI "r, rQ>,r,m") (QI "r, rQ>,r,m")]) |
b3e01c3d | 328 | (define_mode_attr cmp_op1c |
fb062a8b HPN |
329 | [(DI "M,Kc,I,P,n,r,o") (SI "I,rQ>,M, P,g,M") (HI "rQ>,M, g,M") (QI "rQ>,M, g,M")]) |
330 | ||
0b85d816 HPN |
331 | ;; We could optimize the sizes of the immediate operands for various |
332 | ;; cases, but that is not worth it because of the very little usage of | |
333 | ;; DImode for anything else but a structure/block-mode. Just do the | |
334 | ;; obvious stuff for the straight-forward constraint letters. | |
335 | ||
b3e01c3d HPN |
336 | (define_insn "*cmpdi<NZVCSET:mode>" |
337 | [(set (reg:NZVCSET CRIS_CC0_REGNUM) | |
338 | (compare:NZVCSET | |
339 | (match_operand:DI_ 0 "nonimmediate_operand" "<cmp_op0c>") | |
340 | (match_operand:DI_ 1 "general_operand" "<cmp_op1c>")))] | |
fb062a8b | 341 | "reload_completed" |
0b85d816 | 342 | "@ |
f90b7a5a | 343 | test.d %M0\;ax\;test.d %H0 |
0b85d816 HPN |
344 | cmpq %1,%M0\;ax\;cmpq 0,%H0 |
345 | cmpq %1,%M0\;ax\;cmpq -1,%H0 | |
346 | cmp%e1.%z1 %1,%M0\;ax\;cmpq %H1,%H0 | |
347 | cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0 | |
348 | cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0 | |
fb062a8b | 349 | cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0") |
0b85d816 HPN |
350 | |
351 | ;; Note that compare insns with side effect addressing mode (e.g.): | |
352 | ;; | |
353 | ;; cmp.S [rx=ry+i],rz; | |
354 | ;; cmp.S [%3=%1+%2],%0 | |
355 | ;; | |
356 | ;; are *not* usable for gcc since the reloader *does not accept* | |
357 | ;; cc0-changing insns with side-effects other than setting the condition | |
358 | ;; codes. The reason is that the reload stage *may* cause another insn to | |
359 | ;; be output after the main instruction, in turn invalidating cc0 for the | |
360 | ;; insn using the test. (This does not apply to the CRIS case, since a | |
361 | ;; reload for output -- move to memory -- does not change the condition | |
362 | ;; code. Unfortunately we have no way to describe that at the moment. I | |
363 | ;; think code would improve being in the order of one percent faster. | |
364 | \f | |
365 | ;; We have cmps and cmpu (compare reg w. sign/zero extended mem). | |
366 | ;; These are mostly useful for compares in SImode, using 8 or 16-bit | |
367 | ;; constants, but sometimes gcc will find its way to use it for other | |
368 | ;; (memory) operands. Avoid side-effect patterns, though (see above). | |
0b85d816 | 369 | |
b3e01c3d HPN |
370 | (define_insn "*cmp_ext<BW:mode><NZVCSET:mode>" |
371 | [(set (reg:NZVCSET CRIS_CC0_REGNUM) | |
372 | (compare:NZVCSET | |
0b85d816 HPN |
373 | (match_operand:SI 0 "register_operand" "r,r") |
374 | (match_operator:SI 2 "cris_extend_operator" | |
22c3c091 | 375 | [(match_operand:BW 1 "memory_operand" "Q>,m")])))] |
fb062a8b | 376 | "reload_completed" |
22c3c091 | 377 | "cmp%e2<m> %1,%0" |
0b85d816 | 378 | [(set_attr "slottable" "yes,no")]) |
0b85d816 | 379 | \f |
45d5d09c | 380 | ;; The "normal" compare patterns, from SI on. Special-cases with zero |
f90b7a5a | 381 | ;; are covered above. |
0b85d816 | 382 | |
b3e01c3d HPN |
383 | (define_insn "*cmpsi<NZVCSET:mode>" |
384 | [(set (reg:NZVCSET CRIS_CC0_REGNUM) | |
385 | (compare:NZVCSET | |
386 | (match_operand:SI_ 0 "nonimmediate_operand" "<cmp_op0c>") | |
387 | (match_operand:SI_ 1 "general_operand" "<cmp_op1c>")))] | |
fb062a8b | 388 | "reload_completed" |
0b85d816 HPN |
389 | "@ |
390 | cmpq %1,%0 | |
391 | cmp.d %1,%0 | |
fb062a8b | 392 | test.d %0 |
0b85d816 HPN |
393 | cmp%e1.%z1 %1,%0 |
394 | cmp.d %1,%0 | |
fb062a8b HPN |
395 | test.d %0" |
396 | [(set_attr "slottable" "yes,yes,yes,no,no,no")]) | |
0b85d816 | 397 | |
b3e01c3d HPN |
398 | (define_insn "*cmp<BW:mode><NZVCSET:mode>" |
399 | [(set (reg:NZVCSET CRIS_CC0_REGNUM) | |
400 | (compare:NZVCSET | |
401 | (match_operand:BW 0 "nonimmediate_operand" "<cmp_op0c>") | |
402 | (match_operand:BW 1 "general_operand" "<cmp_op1c>")))] | |
fb062a8b | 403 | "reload_completed" |
0b85d816 | 404 | "@ |
22c3c091 | 405 | cmp<m> %1,%0 |
fb062a8b | 406 | test<m> %0 |
22c3c091 | 407 | cmp<m> %1,%0 |
fb062a8b HPN |
408 | test<m> %0" |
409 | [(set_attr "slottable" "yes,yes,no,no")]) | |
0b85d816 HPN |
410 | \f |
411 | ;; Pattern matching the BTST insn. | |
412 | ;; It is useful for "if (i & val)" constructs, where val is an exact | |
413 | ;; power of 2, or if val + 1 is a power of two, where we check for a bunch | |
414 | ;; of zeros starting at bit 0). | |
415 | ||
416 | ;; SImode. This mode is the only one needed, since gcc automatically | |
b73bf8a1 | 417 | ;; extends subregs for lower-size modes. |
b3e01c3d | 418 | (define_insn "*btst<mode>" |
b73bf8a1 HPN |
419 | [(set (reg:ZnNNZSET CRIS_CC0_REGNUM) |
420 | (compare:ZnNNZSET | |
f90b7a5a PB |
421 | (zero_extract:SI |
422 | (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp") | |
423 | (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n") | |
424 | (match_operand:SI 2 "nonmemory_operand" "M, M,Kc,n,r, r,r")) | |
425 | (const_int 0)))] | |
0b85d816 | 426 | ;; Either it is a single bit, or consecutive ones starting at 0. |
fb062a8b HPN |
427 | "reload_completed |
428 | && CONST_INT_P (operands[1]) | |
b73bf8a1 HPN |
429 | && ((operands[1] == const1_rtx && <MODE>mode == CC_ZnNmode) |
430 | || (operands[2] == const0_rtx && <MODE>mode == CC_NZmode)) | |
0b85d816 HPN |
431 | && (REG_S_P (operands[0]) |
432 | || (operands[1] == const1_rtx | |
433 | && REG_S_P (operands[2]) | |
991c42ac | 434 | && CONST_INT_P (operands[0]) |
45d5d09c HPN |
435 | && exact_log2 (INTVAL (operands[0])) >= 0)) |
436 | && !TARGET_CCINIT" | |
0b85d816 | 437 | |
45d5d09c | 438 | ;; The next-to-last "&&" condition above should be caught by some kind of |
0b85d816 HPN |
439 | ;; canonicalization in gcc, but we can easily help with it here. |
440 | ;; It results from expressions of the type | |
b73bf8a1 | 441 | ;; "power_of_2_value & (1 << y)". FIXME: Add testcase. |
0b85d816 HPN |
442 | ;; |
443 | ;; Since there may be codes with tests in on bits (in constant position) | |
444 | ;; beyond the size of a word, handle that by assuming those bits are 0. | |
445 | ;; GCC should handle that, but it's a matter of easily-added belts while | |
446 | ;; having suspenders. | |
447 | ||
448 | "@ | |
449 | btstq (%1-1),%0 | |
45d5d09c | 450 | cmpq 0,%0 |
0b85d816 HPN |
451 | btstq %2,%0 |
452 | clearf nz | |
453 | btst %2,%0 | |
454 | clearf nz | |
455 | cmpq %p0,%2" | |
d0780379 | 456 | [(set_attr "slottable" "yes")]) |
0b85d816 HPN |
457 | \f |
458 | ;; Move insns. | |
459 | ||
460 | ;; The whole mandatory movdi family is here; expander, "anonymous" | |
461 | ;; recognizer and splitter. We're forced to have a movdi pattern, | |
462 | ;; although GCC should be able to split it up itself. Normally it can, | |
463 | ;; but if other insns have DI operands (as is the case here), reload | |
464 | ;; must be able to generate or match a movdi. many testcases fail at | |
465 | ;; -O3 or -fssa if we don't have this. FIXME: Fix GCC... See | |
466 | ;; <URL:http://gcc.gnu.org/ml/gcc-patches/2000-04/msg00104.html>. | |
467 | ;; However, a patch from Richard Kenner (similar to the cause of | |
468 | ;; discussion at the URL above), indicates otherwise. See | |
469 | ;; <URL:http://gcc.gnu.org/ml/gcc-patches/2000-04/msg00554.html>. | |
470 | ;; The truth has IMO is not been decided yet, so check from time to | |
471 | ;; time by disabling the movdi patterns. | |
472 | ||
22c3c091 HPN |
473 | ;; To appease testcase gcc.c-torture/execute/920501-2.c (and others) at |
474 | ;; -O0, we need a movdi as a temporary measure. Here's how things fail: | |
475 | ;; A cmpdi RTX needs reloading (global): | |
476 | ;; (insn 185 326 186 (set (cc0) | |
477 | ;; (compare (mem/f:DI (reg/v:SI 22) 0) | |
478 | ;; (const_int 1 [0x1]))) 4 {cmpdi} (nil) | |
479 | ;; (nil)) | |
480 | ;; Now, reg 22 is reloaded for input address, and the mem is also moved | |
481 | ;; out of the instruction (into a register), since one of the operands | |
482 | ;; must be a register. Reg 22 is reloaded (into reg 10), and the mem is | |
483 | ;; moved out and synthesized in SImode parts (reg 9, reg 10 - should be ok | |
484 | ;; wrt. overlap). The bad things happen with the synthesis in | |
485 | ;; emit_move_insn_1; the location where to substitute reg 10 is lost into | |
486 | ;; two new RTX:es, both still having reg 22. Later on, the left-over reg | |
487 | ;; 22 is recognized to have an equivalent in memory which is substituted | |
488 | ;; straight in, and we end up with an unrecognizable insn: | |
489 | ;; (insn 325 324 326 (set (reg:SI 9 r9) | |
490 | ;; (mem/f:SI (mem:SI (plus:SI (reg:SI 8 r8) | |
491 | ;; (const_int -84 [0xffffffac])) 0) 0)) -1 (nil) | |
492 | ;; (nil)) | |
493 | ;; which is the first part of the reloaded synthesized "movdi". | |
494 | ;; The right thing would be to add equivalent replacement locations for | |
495 | ;; insn with pseudos that need more reloading. The question is where. | |
496 | ||
0b85d816 | 497 | (define_expand "movdi" |
fb062a8b HPN |
498 | [(parallel |
499 | [(set (match_operand:DI 0 "nonimmediate_operand") | |
500 | (match_operand:DI 1 "general_operand")) | |
501 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 | 502 | "" |
0b85d816 | 503 | { |
45d5d09c HPN |
504 | if (MEM_P (operands[0]) |
505 | && operands[1] != const0_rtx | |
d0780379 | 506 | && can_create_pseudo_p ()) |
0b85d816 HPN |
507 | operands[1] = copy_to_mode_reg (DImode, operands[1]); |
508 | ||
509 | /* Some other ports (as of 2001-09-10 for example mcore and romp) also | |
510 | prefer to split up constants early, like this. The testcase in | |
511 | gcc.c-torture/execute/961213-1.c shows that CSE2 gets confused by the | |
512 | resulting subreg sets when using the construct from mcore (as of FSF | |
049746c2 | 513 | CVS, version -r 1.5), and it believes that the high part (the last one |
d70dcf29 | 514 | emitted) is the final value. */ |
991c42ac | 515 | if ((CONST_INT_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE) |
0b85d816 HPN |
516 | && ! reload_completed |
517 | && ! reload_in_progress) | |
518 | { | |
519 | rtx insns; | |
520 | rtx op0 = operands[0]; | |
521 | rtx op1 = operands[1]; | |
522 | ||
523 | start_sequence (); | |
524 | emit_move_insn (operand_subword (op0, 0, 1, DImode), | |
525 | operand_subword (op1, 0, 1, DImode)); | |
526 | emit_move_insn (operand_subword (op0, 1, 1, DImode), | |
527 | operand_subword (op1, 1, 1, DImode)); | |
528 | insns = get_insns (); | |
529 | end_sequence (); | |
530 | ||
d70dcf29 | 531 | emit_insn (insns); |
0b85d816 HPN |
532 | DONE; |
533 | } | |
22c3c091 | 534 | }) |
0b85d816 | 535 | |
d0780379 | 536 | (define_insn_and_split "*movdi_insn" |
477c433d | 537 | [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rx,m") |
fb062a8b HPN |
538 | (match_operand:DI 1 "general_operand" "rx,g,rxM")) |
539 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
45d5d09c HPN |
540 | "(register_operand (operands[0], DImode) |
541 | || register_operand (operands[1], DImode) | |
d0780379 | 542 | || operands[1] == const0_rtx)" |
45d5d09c HPN |
543 | "#" |
544 | "&& reload_completed" | |
545 | [(match_dup 2)] | |
546 | "operands[2] = cris_split_movdx (operands);") | |
0b85d816 | 547 | \f |
0b85d816 HPN |
548 | ;; Normal move patterns from SI on. |
549 | ||
550 | (define_expand "movsi" | |
fb062a8b HPN |
551 | [(parallel |
552 | [(set | |
553 | (match_operand:SI 0 "nonimmediate_operand") | |
554 | (match_operand:SI 1 "general_operand")) | |
555 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 | 556 | "" |
0b85d816 HPN |
557 | { |
558 | /* If the output goes to a MEM, make sure we have zero or a register as | |
559 | input. */ | |
991c42ac | 560 | if (MEM_P (operands[0]) |
0b85d816 HPN |
561 | && ! REG_S_P (operands[1]) |
562 | && operands[1] != const0_rtx | |
3a0e695a | 563 | && can_create_pseudo_p ()) |
0b85d816 | 564 | operands[1] = force_reg (SImode, operands[1]); |
e49cee5c HPN |
565 | |
566 | /* At post-reload time, we'll get here for e.g. split multi-mode insns | |
567 | with a memory destination. Go directly to the clobber-less variant. | |
12bdaa7d HPN |
568 | FIXME: Also applies to special-register source or destination. */ |
569 | if (reload_completed | |
570 | && (MEM_P (operands[0]) || operands[1] == const0_rtx)) | |
e49cee5c HPN |
571 | { |
572 | emit_insn (gen_rtx_SET (operands[0], operands[1])); | |
573 | DONE; | |
574 | } | |
b6c34129 | 575 | }) |
0b85d816 | 576 | |
a82c9fb3 HPN |
577 | ;; We provide CC, CC_NZ and CC_NZVC variants, as moves clear V and C |
578 | ;; and the result is thus usable in a compare against 0. | |
579 | (define_insn "*movsi_internal<setcc><setnz><setnzvc>" | |
0b85d816 | 580 | [(set |
45d5d09c | 581 | (match_operand:SI 0 "nonimmediate_operand" |
d0780379 HPN |
582 | "=r,r, r,Q>,r,Q>,g,r,r,g,rQ>,x, m,x") |
583 | (match_operand:SI 1 "general_operand" | |
fb062a8b HPN |
584 | "r,Q>,M,M, I,r, M,n,g,r,x, rQ>,x,gi")) |
585 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
c00fc5cf | 586 | ;; Note that we prefer not to use the S alternative (if for some reason |
45d5d09c | 587 | ;; it competes with others) above, but g matches S. |
0b85d816 | 588 | "" |
0b85d816 HPN |
589 | { |
590 | /* Better to have c-switch here; it is worth it to optimize the size of | |
591 | move insns. The alternative would be to try to find more constraint | |
592 | letters. FIXME: Check again. It seems this could shrink a bit. */ | |
593 | switch (which_alternative) | |
594 | { | |
595 | case 0: | |
596 | case 1: | |
597 | case 5: | |
d0780379 HPN |
598 | case 8: |
599 | case 9: | |
22c3c091 | 600 | return "move.d %1,%0"; |
0b85d816 | 601 | |
d0780379 | 602 | case 10: |
f60c7155 HPN |
603 | case 11: |
604 | case 12: | |
605 | case 13: | |
d0780379 | 606 | return "move %1,%0"; |
f60c7155 | 607 | |
0b85d816 HPN |
608 | case 2: |
609 | case 3: | |
610 | case 6: | |
22c3c091 | 611 | return "clear.d %0"; |
0b85d816 HPN |
612 | |
613 | /* Constants -32..31 except 0. */ | |
614 | case 4: | |
22c3c091 | 615 | return "moveq %1,%0"; |
0b85d816 HPN |
616 | |
617 | /* We can win a little on constants -32768..-33, 32..65535. */ | |
618 | case 7: | |
619 | if (INTVAL (operands[1]) > 0 && INTVAL (operands[1]) < 65536) | |
620 | { | |
621 | if (INTVAL (operands[1]) < 256) | |
22c3c091 HPN |
622 | return "movu.b %1,%0"; |
623 | return "movu.w %1,%0"; | |
0b85d816 HPN |
624 | } |
625 | else if (INTVAL (operands[1]) >= -32768 && INTVAL (operands[1]) < 32768) | |
626 | { | |
627 | if (INTVAL (operands[1]) >= -128 && INTVAL (operands[1]) < 128) | |
22c3c091 HPN |
628 | return "movs.b %1,%0"; |
629 | return "movs.w %1,%0"; | |
0b85d816 | 630 | } |
22c3c091 | 631 | return "move.d %1,%0"; |
0b85d816 | 632 | |
0b85d816 | 633 | default: |
d0780379 | 634 | gcc_unreachable (); |
0b85d816 | 635 | } |
22c3c091 | 636 | } |
d0780379 | 637 | [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no,yes,yes,no,no") |
a82c9fb3 HPN |
638 | (set_attr "cc<cccc><ccnz><ccnzvc>" |
639 | "*,*,none,none,*,none,none,*,*,none,none,none,none,none")]) | |
0b85d816 | 640 | \f |
0b85d816 HPN |
641 | ;; FIXME: See movsi. |
642 | ||
3c7016b0 | 643 | (define_insn "<acc><anz><anzvc>movhi<setcc><setnz><setnzvc>" |
0b85d816 | 644 | [(set |
f60c7155 | 645 | (match_operand:HI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,r,r,r,g,g,r,r,x") |
fb062a8b HPN |
646 | (match_operand:HI 1 "general_operand" "r,Q>,M,M, I,r, L,O,n,M,r,g,x,r")) |
647 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 648 | "" |
0b85d816 HPN |
649 | { |
650 | switch (which_alternative) | |
651 | { | |
652 | case 0: | |
653 | case 1: | |
654 | case 5: | |
655 | case 10: | |
656 | case 11: | |
22c3c091 | 657 | return "move.w %1,%0"; |
f60c7155 HPN |
658 | case 12: |
659 | case 13: | |
22c3c091 | 660 | return "move %1,%0"; |
0b85d816 HPN |
661 | case 2: |
662 | case 3: | |
663 | case 9: | |
22c3c091 | 664 | return "clear.w %0"; |
0b85d816 | 665 | case 4: |
22c3c091 | 666 | return "moveq %1,%0"; |
0b85d816 HPN |
667 | case 6: |
668 | case 8: | |
669 | if (INTVAL (operands[1]) < 256 && INTVAL (operands[1]) >= -128) | |
670 | { | |
671 | if (INTVAL (operands[1]) > 0) | |
22c3c091 HPN |
672 | return "movu.b %1,%0"; |
673 | return "movs.b %1,%0"; | |
0b85d816 | 674 | } |
22c3c091 | 675 | return "move.w %1,%0"; |
0b85d816 | 676 | case 7: |
22c3c091 | 677 | return "movEq %b1,%0"; |
0b85d816 | 678 | default: |
22c3c091 | 679 | return "BOGUS: %1 to %0"; |
0b85d816 | 680 | } |
22c3c091 | 681 | } |
f60c7155 | 682 | [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,yes,no,no,no,no,yes,yes") |
3c7016b0 | 683 | (set_attr "cc<cccc><ccnz><ccnzvc>" "*,*,none,none,*,none,*,clobber,*,none,none,*,none,none")]) |
0b85d816 HPN |
684 | |
685 | (define_insn "movstricthi" | |
686 | [(set | |
687 | (strict_low_part | |
23369bef | 688 | (match_operand:HI 0 "nonimmediate_operand" "+r,r, r,Q>,Q>,g,r,g")) |
fb062a8b HPN |
689 | (match_operand:HI 1 "general_operand" "r,Q>,M,M, r, M,g,r")) |
690 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
691 | "" |
692 | "@ | |
693 | move.w %1,%0 | |
694 | move.w %1,%0 | |
695 | clear.w %0 | |
696 | clear.w %0 | |
697 | move.w %1,%0 | |
698 | clear.w %0 | |
699 | move.w %1,%0 | |
700 | move.w %1,%0" | |
701 | [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")]) | |
f60c7155 | 702 | |
22c3c091 HPN |
703 | (define_expand "reload_in<mode>" |
704 | [(set (match_operand:BW 2 "register_operand" "=r") | |
705 | (match_operand:BW 1 "memory_operand" "m")) | |
706 | (set (match_operand:BW 0 "register_operand" "=x") | |
f60c7155 HPN |
707 | (match_dup 2))] |
708 | "" | |
709 | "") | |
710 | ||
22c3c091 | 711 | (define_expand "reload_out<mode>" |
11e30dd8 | 712 | [(set (match_operand:BW 2 "register_operand" "=&r") |
22c3c091 HPN |
713 | (match_operand:BW 1 "register_operand" "x")) |
714 | (set (match_operand:BW 0 "memory_operand" "=m") | |
f60c7155 HPN |
715 | (match_dup 2))] |
716 | "" | |
717 | "") | |
0b85d816 | 718 | \f |
3c7016b0 | 719 | (define_insn "<acc><anz><anzvc>movqi<setcc><setnz><setnzvc>" |
f60c7155 | 720 | [(set (match_operand:QI 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,r,g,g,r,r,r,x") |
fb062a8b HPN |
721 | (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, I,M,r,O,g,x,r")) |
722 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
723 | "" |
724 | "@ | |
725 | move.b %1,%0 | |
726 | move.b %1,%0 | |
727 | move.b %1,%0 | |
728 | clear.b %0 | |
729 | clear.b %0 | |
730 | moveq %1,%0 | |
731 | clear.b %0 | |
732 | move.b %1,%0 | |
733 | moveq %b1,%0 | |
f60c7155 HPN |
734 | move.b %1,%0 |
735 | move %1,%0 | |
736 | move %1,%0" | |
737 | [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,yes,no,yes,yes") | |
3c7016b0 HPN |
738 | (set_attr "cc<cccc><ccnz><ccnzvc>" |
739 | "*,none,*,none,none,*,none,none,clobber,*,none,none")]) | |
0b85d816 HPN |
740 | |
741 | (define_insn "movstrictqi" | |
742 | [(set (strict_low_part | |
23369bef | 743 | (match_operand:QI 0 "nonimmediate_operand" "+r,Q>,r, r,Q>,g,g,r")) |
fb062a8b HPN |
744 | (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, M,r,g")) |
745 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
746 | "" |
747 | "@ | |
748 | move.b %1,%0 | |
749 | move.b %1,%0 | |
750 | move.b %1,%0 | |
751 | clear.b %0 | |
752 | clear.b %0 | |
753 | clear.b %0 | |
754 | move.b %1,%0 | |
755 | move.b %1,%0" | |
756 | [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")]) | |
757 | ||
758 | ;; The valid "quick" bit-patterns are, except for 0.0, denormalized | |
759 | ;; values REALLY close to 0, and some NaN:s (I think; their exponent is | |
760 | ;; all ones); the worthwhile one is "0.0". | |
761 | ;; It will use clear, so we know ALL types of immediate 0 never change cc. | |
762 | ||
763 | (define_insn "movsf" | |
f60c7155 | 764 | [(set (match_operand:SF 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,g,g,r,r,x,Q>,m,x, x") |
fb062a8b HPN |
765 | (match_operand:SF 1 "general_operand" "r,r, Q>,G,G, G,r,g,x,r,x, x,Q>,g")) |
766 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
767 | "" |
768 | "@ | |
769 | move.d %1,%0 | |
770 | move.d %1,%0 | |
771 | move.d %1,%0 | |
772 | clear.d %0 | |
773 | clear.d %0 | |
774 | clear.d %0 | |
775 | move.d %1,%0 | |
f60c7155 HPN |
776 | move.d %1,%0 |
777 | move %1,%0 | |
778 | move %1,%0 | |
779 | move %1,%0 | |
780 | move %1,%0 | |
781 | move %1,%0 | |
782 | move %1,%0" | |
783 | [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no,yes,yes,yes,no,yes,no")]) | |
e49cee5c HPN |
784 | |
785 | ;; Post-reload, for memory destinations, split the clobber-variant and | |
786 | ;; get rid of the clobber. | |
787 | ||
788 | (define_split ;; "*mov_tomem<mode>_split" | |
789 | [(set (match_operand:BWD 0 "memory_operand") | |
790 | (match_operand:BWD 1 "nonmemory_operand")) | |
791 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
792 | "reload_completed" | |
793 | [(set (match_dup 0) (match_dup 1))] | |
794 | "") | |
795 | ||
796 | ;; Exclude moving special-registers to memory from matching for | |
797 | ;; less-than-SImode, as they are SImode only (or actually, the size of | |
798 | ;; the register, but the ones free for "x" are naturally SImode; see | |
799 | ;; special measures taken for reload). | |
800 | ;; This might be a belt-and-suspenders thing, as a move from special | |
801 | ;; register to memory in less-than-SImode should not have made it here. | |
802 | ||
803 | (define_mode_attr mov_tomem_enabled | |
804 | [(SI "yes,yes,yes,yes,yes,yes") | |
805 | (HI "yes,yes,no,yes,yes,no") | |
806 | (QI "yes,yes,no,yes,yes,no")]) | |
807 | ||
808 | (define_insn "*mov_tomem<mode>" | |
809 | [(set (match_operand:BWD 0 "memory_operand" "=Q>,Q>,Q>,m,m,m") | |
810 | (match_operand:BWD 1 "nonmemory_operand" "M, r, x, M,r,x"))] | |
811 | "reload_completed" | |
812 | "@ | |
813 | clear<m> %0 | |
814 | move<m> %1,%0 | |
815 | move %1,%0 | |
816 | clear<m> %0 | |
817 | move<m> %1,%0 | |
818 | move %1,%0" | |
819 | [(set_attr "slottable" "yes,yes,yes,no,no,no") | |
820 | (set_attr "enabled" "<mov_tomem_enabled>")]) | |
12bdaa7d HPN |
821 | |
822 | (define_split ;; "*mov_fromzero<mode>_split" | |
823 | [(set (match_operand:BWD 0 "register_operand") (const_int 0)) | |
824 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
825 | "reload_completed | |
826 | && REGNO(operands[0]) <= CRIS_LAST_GENERAL_REGISTER" | |
827 | [(set (match_dup 0) (const_int 0))] | |
828 | "") | |
829 | ||
830 | (define_insn "*mov_fromzero<mode>" | |
831 | [(set (match_operand:BWD 0 "register_operand" "=r") (const_int 0))] | |
832 | "reload_completed" | |
833 | "clear<m> %0" | |
834 | [(set_attr "slottable" "yes")]) | |
45d5d09c HPN |
835 | \f |
836 | ;; Movem patterns. Primarily for use in function prologue and epilogue. | |
d0780379 HPN |
837 | ;; Unfortunately, movem stores R0 in the highest memory location, thus |
838 | ;; the opposite of the expectation for the standard names "load_multiple" | |
839 | ;; and "store_multiple". | |
04539954 | 840 | |
04539954 HPN |
841 | (define_insn "*cris_load_multiple" |
842 | [(match_parallel 0 "cris_load_multiple_op" | |
843 | [(set (match_operand:SI 1 "register_operand" "=r,r") | |
844 | (match_operand:SI 2 "memory_operand" "Q,m"))])] | |
845 | "" | |
846 | "movem %O0,%o0" | |
847 | [(set_attr "cc" "none") | |
848 | (set_attr "slottable" "yes,no") | |
849 | ;; Not true, but setting the length to 0 causes return sequences (ret | |
850 | ;; movem) to have the cost they had when (return) included the movem | |
851 | ;; and reduces the performance penalty taken for needing to emit an | |
852 | ;; epilogue (in turn copied by bb-reorder) instead of return patterns. | |
853 | ;; FIXME: temporary change until all insn lengths are correctly | |
854 | ;; described. FIXME: have better target control over bb-reorder. | |
855 | (set_attr "length" "0")]) | |
d29b4b1b HPN |
856 | |
857 | (define_insn "*cris_store_multiple" | |
858 | [(match_parallel 0 "cris_store_multiple_op" | |
859 | [(set (match_operand:SI 2 "memory_operand" "=Q,m") | |
860 | (match_operand:SI 1 "register_operand" "r,r"))])] | |
861 | "" | |
862 | "movem %o0,%O0" | |
863 | [(set_attr "cc" "none") | |
864 | (set_attr "slottable" "yes,no")]) | |
0b85d816 HPN |
865 | \f |
866 | ||
867 | ;; Sign- and zero-extend insns with standard names. | |
868 | ;; Those for integer source operand are ordered with the widest source | |
869 | ;; type first. | |
870 | ||
871 | ;; Sign-extend. | |
872 | ||
873 | (define_insn "extendsidi2" | |
874 | [(set (match_operand:DI 0 "register_operand" "=r") | |
fb062a8b HPN |
875 | (sign_extend:DI (match_operand:SI 1 "general_operand" "g"))) |
876 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
877 | "" |
878 | "move.d %1,%M0\;smi %H0\;neg.d %H0,%H0") | |
879 | ||
22c3c091 | 880 | (define_insn "extend<mode>di2" |
0b85d816 | 881 | [(set (match_operand:DI 0 "register_operand" "=r") |
fb062a8b HPN |
882 | (sign_extend:DI (match_operand:BW 1 "general_operand" "g"))) |
883 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 884 | "" |
22c3c091 | 885 | "movs<m> %1,%M0\;smi %H0\;neg.d %H0,%H0") |
0b85d816 | 886 | |
61c964c7 | 887 | (define_insn "<acc><anz><anzvc>extend<mode>si2<setcc><setnz><setnzvc>" |
0b85d816 | 888 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
fb062a8b HPN |
889 | (sign_extend:SI (match_operand:BW 1 "general_operand" "r,Q>,g"))) |
890 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 891 | "" |
22c3c091 | 892 | "movs<m> %1,%0" |
0b85d816 HPN |
893 | [(set_attr "slottable" "yes,yes,no")]) |
894 | ||
073a8998 | 895 | ;; To do a byte->word extension, extend to dword, except that the top half |
0b85d816 HPN |
896 | ;; of the register will be clobbered. FIXME: Perhaps this is not needed. |
897 | ||
898 | (define_insn "extendqihi2" | |
899 | [(set (match_operand:HI 0 "register_operand" "=r,r,r") | |
fb062a8b HPN |
900 | (sign_extend:HI (match_operand:QI 1 "general_operand" "r,Q>,g"))) |
901 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
902 | "" |
903 | "movs.b %1,%0" | |
904 | [(set_attr "slottable" "yes,yes,no")]) | |
905 | \f | |
906 | ||
907 | ;; Zero-extend. The DImode ones are synthesized by gcc, so we don't | |
908 | ;; specify them here. | |
909 | ||
61c964c7 | 910 | (define_insn "<acc><anz><anzvc>zero_extend<mode>si2<setcc><setnz><setnzvc>" |
0b85d816 HPN |
911 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
912 | (zero_extend:SI | |
fb062a8b HPN |
913 | (match_operand:BW 1 "nonimmediate_operand" "r,Q>,m"))) |
914 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 915 | "" |
22c3c091 | 916 | "movu<m> %1,%0" |
0b85d816 HPN |
917 | [(set_attr "slottable" "yes,yes,no")]) |
918 | ||
919 | ;; Same comment as sign-extend QImode to HImode above applies. | |
920 | ||
921 | (define_insn "zero_extendqihi2" | |
922 | [(set (match_operand:HI 0 "register_operand" "=r,r,r") | |
923 | (zero_extend:HI | |
fb062a8b HPN |
924 | (match_operand:QI 1 "nonimmediate_operand" "r,Q>,m"))) |
925 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
926 | "" |
927 | "movu.b %1,%0" | |
928 | [(set_attr "slottable" "yes,yes,no")]) | |
929 | \f | |
0b85d816 HPN |
930 | ;; Add operations, standard names. |
931 | ||
932 | ;; Note that for the 'P' constraint, the high part can be -1 or 0. We | |
933 | ;; output the insn through the 'A' output modifier as "adds.w" and "addq", | |
934 | ;; respectively. | |
45d5d09c | 935 | (define_expand "adddi3" |
fb062a8b HPN |
936 | [(parallel |
937 | [(set (match_operand:DI 0 "register_operand") | |
938 | (plus:DI (match_operand:DI 1 "register_operand") | |
939 | (match_operand:DI 2 "general_operand"))) | |
940 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
45d5d09c | 941 | "" |
d0780379 | 942 | "") |
45d5d09c | 943 | |
e561b9fe | 944 | (define_insn "*adddi3<setnz>" |
0b85d816 HPN |
945 | [(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r") |
946 | (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,r") | |
fb062a8b HPN |
947 | (match_operand:DI 2 "general_operand" "J,N,P,g,!To"))) |
948 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 949 | "" |
0b85d816 HPN |
950 | "@ |
951 | addq %2,%M0\;ax\;addq 0,%H0 | |
952 | subq %n2,%M0\;ax\;subq 0,%H0 | |
953 | add%e2.%z2 %2,%M0\;ax\;%A2 %H2,%H0 | |
954 | add.d %M2,%M0\;ax\;add.d %H2,%H0 | |
955 | add.d %M2,%M1,%M0\;ax\;add.d %H2,%H1,%H0") | |
956 | ||
45d5d09c | 957 | (define_expand "add<mode>3" |
fb062a8b HPN |
958 | [(parallel |
959 | [(set (match_operand:BWD 0 "register_operand") | |
960 | (plus:BWD | |
961 | (match_operand:BWD 1 "register_operand") | |
962 | (match_operand:BWD 2 "general_operand"))) | |
963 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
45d5d09c HPN |
964 | "" |
965 | "") | |
966 | ||
e561b9fe | 967 | (define_insn "*addsi3<setnz>" |
d0780379 | 968 | [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r,r, r") |
0b85d816 | 969 | (plus:SI |
d0780379 | 970 | (match_operand:SI 1 "register_operand" "%0,0, 0,0,0,0,r, r") |
fb062a8b HPN |
971 | (match_operand:SI 2 "general_operand" "r,Q>,J,N,n,g,!To,0"))) |
972 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
973 | |
974 | ;; The last constraint is due to that after reload, the '%' is not | |
975 | ;; honored, and canonicalization doesn't care about keeping the same | |
976 | ;; register as in destination. This will happen after insn splitting. | |
0b85d816 | 977 | |
d0780379 | 978 | "" |
0b85d816 HPN |
979 | { |
980 | switch (which_alternative) | |
981 | { | |
982 | case 0: | |
983 | case 1: | |
22c3c091 | 984 | return "add.d %2,%0"; |
0b85d816 | 985 | case 2: |
22c3c091 | 986 | return "addq %2,%0"; |
0b85d816 | 987 | case 3: |
22c3c091 | 988 | return "subq %n2,%0"; |
0b85d816 HPN |
989 | case 4: |
990 | /* 'Known value', but not in -63..63. | |
991 | Check if addu/subu may be used. */ | |
992 | if (INTVAL (operands[2]) > 0) | |
993 | { | |
994 | if (INTVAL (operands[2]) < 256) | |
22c3c091 | 995 | return "addu.b %2,%0"; |
0b85d816 | 996 | if (INTVAL (operands[2]) < 65536) |
22c3c091 | 997 | return "addu.w %2,%0"; |
0b85d816 HPN |
998 | } |
999 | else | |
1000 | { | |
1001 | if (INTVAL (operands[2]) >= -255) | |
22c3c091 | 1002 | return "subu.b %n2,%0"; |
0b85d816 | 1003 | if (INTVAL (operands[2]) >= -65535) |
22c3c091 | 1004 | return "subu.w %n2,%0"; |
0b85d816 | 1005 | } |
22c3c091 | 1006 | return "add.d %2,%0"; |
0b85d816 | 1007 | case 5: |
d0780379 | 1008 | return "add.d %2,%0"; |
c00fc5cf | 1009 | case 6: |
c00fc5cf | 1010 | return "add.d %2,%1,%0"; |
d0780379 | 1011 | case 7: |
22c3c091 | 1012 | return "add.d %1,%0"; |
0b85d816 | 1013 | default: |
22c3c091 | 1014 | return "BOGUS addsi %2+%1 to %0"; |
0b85d816 | 1015 | } |
22c3c091 | 1016 | } |
d0780379 | 1017 | [(set_attr "slottable" "yes,yes,yes,yes,no,no,no,yes")]) |
0b85d816 | 1018 | \f |
e561b9fe | 1019 | (define_insn "*addhi3<setnz>" |
23369bef HPN |
1020 | [(set (match_operand:HI 0 "register_operand" "=r,r, r,r,r,r") |
1021 | (plus:HI (match_operand:HI 1 "register_operand" "%0,0, 0,0,0,r") | |
fb062a8b HPN |
1022 | (match_operand:HI 2 "general_operand" "r,Q>,J,N,g,!To"))) |
1023 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1024 | "" |
0b85d816 HPN |
1025 | "@ |
1026 | add.w %2,%0 | |
1027 | add.w %2,%0 | |
1028 | addq %2,%0 | |
1029 | subq %n2,%0 | |
1030 | add.w %2,%0 | |
1031 | add.w %2,%1,%0" | |
1032 | [(set_attr "slottable" "yes,yes,yes,yes,no,no") | |
e561b9fe | 1033 | (set_attr "cc<ccnz>" "normal,normal,clobber,clobber,normal,normal")]) |
0b85d816 | 1034 | |
e561b9fe | 1035 | (define_insn "*addqi3<setnz>" |
23369bef HPN |
1036 | [(set (match_operand:QI 0 "register_operand" "=r,r, r,r,r,r,r") |
1037 | (plus:QI (match_operand:QI 1 "register_operand" "%0,0, 0,0,0,0,r") | |
fb062a8b HPN |
1038 | (match_operand:QI 2 "general_operand" "r,Q>,J,N,O,g,!To"))) |
1039 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1040 | "" |
0b85d816 HPN |
1041 | "@ |
1042 | add.b %2,%0 | |
1043 | add.b %2,%0 | |
1044 | addq %2,%0 | |
1045 | subq %n2,%0 | |
1046 | subQ -%b2,%0 | |
1047 | add.b %2,%0 | |
1048 | add.b %2,%1,%0" | |
1049 | [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no") | |
e561b9fe | 1050 | (set_attr "cc<ccnz>" "normal,normal,clobber,clobber,clobber,normal,normal")]) |
0b85d816 HPN |
1051 | \f |
1052 | ;; Subtract. | |
1053 | ;; | |
1054 | ;; Note that because of insn canonicalization these will *seldom* but | |
1055 | ;; rarely be used with a known constant as an operand. | |
1056 | ||
1057 | ;; Note that for the 'P' constraint, the high part can be -1 or 0. We | |
1058 | ;; output the insn through the 'D' output modifier as "subs.w" and "subq", | |
1059 | ;; respectively. | |
45d5d09c | 1060 | (define_expand "subdi3" |
fb062a8b HPN |
1061 | [(parallel |
1062 | [(set (match_operand:DI 0 "register_operand") | |
1063 | (minus:DI (match_operand:DI 1 "register_operand") | |
1064 | (match_operand:DI 2 "general_operand"))) | |
1065 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
45d5d09c | 1066 | "" |
d0780379 | 1067 | "") |
45d5d09c | 1068 | |
e561b9fe | 1069 | (define_insn "*subdi3<setnz>" |
0b85d816 HPN |
1070 | [(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r") |
1071 | (minus:DI (match_operand:DI 1 "register_operand" "0,0,0,0,r") | |
fb062a8b HPN |
1072 | (match_operand:DI 2 "general_operand" "J,N,P,g,!To"))) |
1073 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1074 | "" |
0b85d816 HPN |
1075 | "@ |
1076 | subq %2,%M0\;ax\;subq 0,%H0 | |
1077 | addq %n2,%M0\;ax\;addq 0,%H0 | |
1078 | sub%e2.%z2 %2,%M0\;ax\;%D2 %H2,%H0 | |
1079 | sub.d %M2,%M0\;ax\;sub.d %H2,%H0 | |
1080 | sub.d %M2,%M1,%M0\;ax\;sub.d %H2,%H1,%H0") | |
1081 | ||
45d5d09c | 1082 | (define_expand "sub<mode>3" |
fb062a8b HPN |
1083 | [(parallel |
1084 | [(set (match_operand:BWD 0 "register_operand") | |
1085 | (minus:BWD | |
1086 | (match_operand:BWD 1 "register_operand") | |
1087 | (match_operand:BWD 2 "general_operand"))) | |
1088 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
45d5d09c HPN |
1089 | "" |
1090 | "") | |
1091 | ||
e561b9fe | 1092 | (define_insn "*subsi3<setnz>" |
23369bef | 1093 | [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r,r,r") |
0b85d816 | 1094 | (minus:SI |
23369bef | 1095 | (match_operand:SI 1 "register_operand" "0,0, 0,0,0,0,0,r") |
fb062a8b HPN |
1096 | (match_operand:SI 2 "general_operand" "r,Q>,J,N,P,n,g,!To"))) |
1097 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1098 | "" |
0b85d816 HPN |
1099 | |
1100 | ;; This does not do the optimal: "addu.w 65535,r0" when %2 is negative. | |
1101 | ;; But then again, %2 should not be negative. | |
1102 | ||
1103 | "@ | |
1104 | sub.d %2,%0 | |
1105 | sub.d %2,%0 | |
1106 | subq %2,%0 | |
1107 | addq %n2,%0 | |
1108 | sub%e2.%z2 %2,%0 | |
1109 | sub.d %2,%0 | |
1110 | sub.d %2,%0 | |
1111 | sub.d %2,%1,%0" | |
1112 | [(set_attr "slottable" "yes,yes,yes,yes,no,no,no,no")]) | |
1113 | \f | |
e561b9fe | 1114 | (define_insn "*sub<mode>3<setnz>" |
22c3c091 HPN |
1115 | [(set (match_operand:BW 0 "register_operand" "=r,r, r,r,r,r") |
1116 | (minus:BW (match_operand:BW 1 "register_operand" "0,0, 0,0,0,r") | |
fb062a8b HPN |
1117 | (match_operand:BW 2 "general_operand" "r,Q>,J,N,g,!To"))) |
1118 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1119 | "" |
0b85d816 | 1120 | "@ |
22c3c091 HPN |
1121 | sub<m> %2,%0 |
1122 | sub<m> %2,%0 | |
0b85d816 HPN |
1123 | subq %2,%0 |
1124 | addq %n2,%0 | |
22c3c091 HPN |
1125 | sub<m> %2,%0 |
1126 | sub<m> %2,%1,%0" | |
0b85d816 | 1127 | [(set_attr "slottable" "yes,yes,yes,yes,no,no") |
e561b9fe | 1128 | (set_attr "cc<ccnz>" "normal,normal,clobber,clobber,normal,normal")]) |
0b85d816 | 1129 | \f |
65f8403f HPN |
1130 | ;; Extend versions (zero/sign) of normal add/sub (no side-effects). |
1131 | ||
1132 | ;; QImode to HImode | |
1133 | ;; FIXME: GCC should widen. | |
1134 | ||
9596eccb | 1135 | (define_insn "*<addsub><su>qihi" |
65f8403f | 1136 | [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") |
9596eccb HPN |
1137 | (plusminus:HI |
1138 | (match_operand:HI 1 "register_operand" "0,0,0,r") | |
1139 | (szext:HI (match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")))) | |
65f8403f HPN |
1140 | (clobber (reg:CC CRIS_CC0_REGNUM))] |
1141 | "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD | |
9596eccb | 1142 | && (operands[1] != frame_pointer_rtx || <plusminus:CODE> != PLUS)" |
65f8403f | 1143 | "@ |
9596eccb HPN |
1144 | <addsub><su>.b %2,%0 |
1145 | <addsub><su>.b %2,%0 | |
1146 | <addsub><su>.b %2,%0 | |
1147 | <addsub><su>.b %2,%1,%0" | |
65f8403f HPN |
1148 | [(set_attr "slottable" "yes,yes,no,no") |
1149 | (set_attr "cc" "clobber")]) | |
1150 | ||
9596eccb HPN |
1151 | ;; FIXME: bound is actually also <setnzvc>, but is so rarely used in this |
1152 | ;; form that it's not worthwhile to make that distinction. | |
1153 | (define_insn "*<addsubbo><su><nd><mode>si<setnz>" | |
65f8403f | 1154 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") |
9596eccb HPN |
1155 | (plusminusumin:SI |
1156 | (match_operand:SI 1 "register_operand" "0,0,0,r") | |
1157 | (szext:SI (match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")))) | |
65f8403f | 1158 | (clobber (reg:CC CRIS_CC0_REGNUM))] |
9596eccb HPN |
1159 | "(<plusminusumin:CODE> != UMIN || <szext:CODE> == ZERO_EXTEND) |
1160 | && (operands[1] != frame_pointer_rtx || <plusminusumin:CODE> != PLUS)" | |
65f8403f | 1161 | "@ |
9596eccb HPN |
1162 | <addsubbo><su><nd><m> %2,%0 |
1163 | <addsubbo><su><nd><m> %2,%0 | |
1164 | <addsubbo><su><nd><m> %2,%0 | |
1165 | <addsubbo><su><nd><m> %2,%1,%0" | |
65f8403f HPN |
1166 | [(set_attr "slottable" "yes,yes,no,no")]) |
1167 | \f | |
1168 | ;; We may have swapped operands for add or bound. | |
1169 | ;; For commutative operands, these are the canonical forms. | |
1170 | ||
1171 | ;; QImode to HImode | |
1172 | ||
9596eccb | 1173 | (define_insn "*add<su>qihi_swap" |
65f8403f HPN |
1174 | [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") |
1175 | (plus:HI | |
9596eccb | 1176 | (szext:HI (match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")) |
65f8403f HPN |
1177 | (match_operand:HI 1 "register_operand" "0,0,0,r"))) |
1178 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
1179 | "operands[1] != frame_pointer_rtx" | |
1180 | "@ | |
9596eccb HPN |
1181 | add<su>.b %2,%0 |
1182 | add<su>.b %2,%0 | |
1183 | add<su>.b %2,%0 | |
1184 | add<su>.b %2,%1,%0" | |
65f8403f HPN |
1185 | [(set_attr "slottable" "yes,yes,no,no") |
1186 | (set_attr "cc" "clobber")]) | |
1187 | ||
9596eccb | 1188 | (define_insn "*<addsubbo><su><nd><mode>si<setnz>_swap" |
65f8403f | 1189 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") |
9596eccb HPN |
1190 | (plusumin:SI |
1191 | (szext:SI (match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")) | |
1192 | (match_operand:SI 1 "register_operand" "0,0,0,r"))) | |
65f8403f | 1193 | (clobber (reg:CC CRIS_CC0_REGNUM))] |
9596eccb | 1194 | "(<plusumin:CODE> != UMIN || <szext:CODE> == ZERO_EXTEND) |
65f8403f HPN |
1195 | && operands[1] != frame_pointer_rtx" |
1196 | "@ | |
9596eccb HPN |
1197 | <addsubbo><su><nd><m> %2,%0 |
1198 | <addsubbo><su><nd><m> %2,%0 | |
1199 | <addsubbo><su><nd><m> %2,%0 | |
1200 | <addsubbo><su><nd><m> %2,%1,%0" | |
65f8403f HPN |
1201 | [(set_attr "slottable" "yes,yes,no,no")]) |
1202 | \f | |
0b85d816 HPN |
1203 | ;; This is the special case when we use what corresponds to the |
1204 | ;; instruction above in "casesi". Do *not* change it to use the generic | |
1205 | ;; pattern and "REG 15" as pc; I did that and it led to madness and | |
1206 | ;; maintenance problems: Instead of (as imagined) recognizing and removing | |
1207 | ;; or replacing this pattern with something simpler, other variant | |
1208 | ;; patterns were recognized or combined, including some prefix variants | |
1209 | ;; where the value in pc is not that of the next instruction (which means | |
1210 | ;; this instruction actually *is* special and *should* be marked as such). | |
1211 | ;; When switching from the "generic pattern match" approach to this simpler | |
1212 | ;; approach, there were insignificant differences in gcc, ipps and | |
1213 | ;; product code, somehow due to scratching reload behind the ear or | |
1214 | ;; something. Testcase "gcc" looked .01% slower and 4 bytes bigger; | |
1215 | ;; product code became .001% smaller but "looked better". The testcase | |
1216 | ;; "ipps" was just different at register allocation). | |
1217 | ;; | |
1218 | ;; Assumptions in the jump optimizer forces us to use IF_THEN_ELSE in this | |
1219 | ;; pattern with the default-label as the else, with the "if" being | |
1220 | ;; index-is-less-than the max number of cases plus one. The default-label | |
1221 | ;; is attached to the end of the case-table at time of output. | |
1222 | ||
1223 | (define_insn "*casesi_adds_w" | |
1224 | [(set (pc) | |
1225 | (if_then_else | |
1226 | (ltu (match_operand:SI 0 "register_operand" "r") | |
1227 | (match_operand:SI 1 "const_int_operand" "n")) | |
1228 | (plus:SI (sign_extend:SI | |
1229 | (mem:HI | |
1230 | (plus:SI (mult:SI (match_dup 0) (const_int 2)) | |
1231 | (pc)))) | |
1232 | (pc)) | |
1233 | (label_ref (match_operand 2 "" "")))) | |
fb062a8b HPN |
1234 | (use (label_ref (match_operand 3 "" ""))) |
1235 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1236 | "operands[0] != frame_pointer_rtx" |
0b85d816 HPN |
1237 | "adds.w [$pc+%0.w],$pc" |
1238 | [(set_attr "cc" "clobber")]) | |
1239 | \f | |
1240 | ;; Multiply instructions. | |
1241 | ||
1242 | ;; Sometimes powers of 2 (which are normally canonicalized to a | |
1243 | ;; left-shift) appear here, as a result of address reloading. | |
1244 | ;; As a special, for values 3 and 5, we can match with an addi, so add those. | |
1245 | ;; | |
1246 | ;; FIXME: This may be unnecessary now. | |
1247 | ;; Explicitly named for convenience of having a gen_... function. | |
1248 | ||
1249 | (define_insn "addi_mul" | |
1250 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1251 | (mult:SI | |
1252 | (match_operand:SI 1 "register_operand" "%0") | |
fb062a8b HPN |
1253 | (match_operand:SI 2 "const_int_operand" "n"))) |
1254 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
1255 | "operands[0] != frame_pointer_rtx |
1256 | && operands[1] != frame_pointer_rtx | |
991c42ac | 1257 | && CONST_INT_P (operands[2]) |
0b85d816 HPN |
1258 | && (INTVAL (operands[2]) == 2 |
1259 | || INTVAL (operands[2]) == 4 || INTVAL (operands[2]) == 3 | |
1260 | || INTVAL (operands[2]) == 5)" | |
0b85d816 HPN |
1261 | { |
1262 | if (INTVAL (operands[2]) == 2) | |
22c3c091 | 1263 | return "lslq 1,%0"; |
0b85d816 | 1264 | else if (INTVAL (operands[2]) == 4) |
22c3c091 | 1265 | return "lslq 2,%0"; |
0b85d816 | 1266 | else if (INTVAL (operands[2]) == 3) |
22c3c091 | 1267 | return "addi %0.w,%0"; |
0b85d816 | 1268 | else if (INTVAL (operands[2]) == 5) |
22c3c091 HPN |
1269 | return "addi %0.d,%0"; |
1270 | return "BAD: adr_mulsi: %0=%1*%2"; | |
1271 | } | |
0b85d816 HPN |
1272 | [(set_attr "slottable" "yes") |
1273 | ;; No flags are changed if this insn is "addi", but it does not seem | |
1274 | ;; worth the trouble to distinguish that to the lslq cases. | |
1275 | (set_attr "cc" "clobber")]) | |
1276 | ||
1277 | ;; The addi insn as it is normally used. | |
1278 | ||
1279 | (define_insn "*addi" | |
d0780379 | 1280 | [(set (match_operand:SI 0 "register_operand" "=r") |
0b85d816 | 1281 | (plus:SI |
6cb68940 HPN |
1282 | (ashift:SI (match_operand:SI 2 "register_operand" "r") |
1283 | (match_operand:SI 3 "const_int_operand" "n")) | |
d0780379 | 1284 | (match_operand:SI 1 "register_operand" "0")))] |
0b85d816 HPN |
1285 | "operands[0] != frame_pointer_rtx |
1286 | && operands[1] != frame_pointer_rtx | |
991c42ac | 1287 | && CONST_INT_P (operands[3]) |
6cb68940 | 1288 | && (INTVAL (operands[3]) == 1 || INTVAL (operands[3]) == 2)" |
d0780379 | 1289 | "addi %2%T3,%0" |
0b85d816 HPN |
1290 | [(set_attr "slottable" "yes") |
1291 | (set_attr "cc" "none")]) | |
1292 | ||
6cb68940 HPN |
1293 | ;; The mult-vs-ashift canonicalization-cleanup plagues us: nothing in |
1294 | ;; reload transforms a "scaled multiplication" into an ashift in a | |
1295 | ;; reloaded address; it's passed as-is and expected to be recognized, | |
1296 | ;; or else we get a tell-tale "unrecognizable insn". | |
1297 | ;; On top of that, we *should* match the bare insn, as a *matching | |
1298 | ;; pattern* (as opposed to e.g. a reload_load_address expander | |
1299 | ;; changing the mul into an ashift), so can_reload_into will re-use | |
1300 | ;; registers in the reloaded expression instead of allocating a new | |
1301 | ;; register. | |
1302 | (define_insn_and_split "*addi_reload" | |
1303 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1304 | (plus:SI | |
1305 | (mult:SI (match_operand:SI 2 "register_operand" "r") | |
1306 | (match_operand:SI 3 "const_int_operand" "n")) | |
1307 | (match_operand:SI 1 "register_operand" "0")))] | |
1308 | "operands[0] != frame_pointer_rtx | |
1309 | && operands[1] != frame_pointer_rtx | |
1310 | && CONST_INT_P (operands[3]) | |
1311 | && (INTVAL (operands[3]) == 2 || INTVAL (operands[3]) == 4) | |
1312 | && (reload_in_progress || reload_completed)" | |
1313 | "#" | |
47d25a03 | 1314 | "&& 1" |
6cb68940 HPN |
1315 | [(set (match_dup 0) |
1316 | (plus:SI (ashift:SI (match_dup 2) (match_dup 3)) (match_dup 1)))] | |
1317 | "operands[3] = operands[3] == const2_rtx ? const1_rtx : const2_rtx;") | |
1318 | ||
ef07c7a5 HPN |
1319 | ;; This pattern is usually generated after reload, so a '%' is |
1320 | ;; ineffective; use explicit combinations. | |
1321 | (define_insn "*addi_b_<mode>" | |
1322 | [(set (match_operand:BWD 0 "register_operand" "=r,r") | |
1323 | (plus:BWD | |
1324 | (match_operand:BWD 1 "register_operand" "0,r") | |
1325 | (match_operand:BWD 2 "register_operand" "r,0")))] | |
1326 | "" | |
1327 | "@ | |
1328 | addi %2.b,%0 | |
1329 | addi %1.b,%0" | |
1330 | [(set_attr "slottable" "yes")]) | |
1331 | ||
1332 | ;; Strip the dccr clobber from addM3 with register operands, if the | |
1333 | ;; next instruction isn't using it. | |
1334 | ;; Not clobbering dccr may let cmpelim match a later compare with a | |
1335 | ;; previous operation of interest. This has to run before cmpelim so it | |
1336 | ;; can't be a peephole2. See gcc.target/cris/pr93372-45.c for a | |
1337 | ;; test-case. | |
1338 | (define_split ;; "*add<mode>3_addi" | |
1339 | [(parallel | |
1340 | [(set (match_operand:BWD 0 "register_operand") | |
1341 | (plus:BWD | |
1342 | (match_operand:BWD 1 "register_operand") | |
1343 | (match_operand:BWD 2 "register_operand"))) | |
1344 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
1345 | "reload_completed" | |
1346 | [(set (match_dup 0) (plus:BWD (match_dup 1) (match_dup 2)))] | |
1347 | { | |
1348 | rtx reg = operands[0]; | |
1349 | rtx_insn *i = next_nonnote_nondebug_insn_bb (curr_insn); | |
1350 | ||
1351 | while (i != NULL_RTX && (!INSN_P (i) || DEBUG_INSN_P (i))) | |
1352 | i = next_nonnote_nondebug_insn_bb (i); | |
1353 | ||
1354 | if (i == NULL_RTX || reg_mentioned_p (reg, i) || BARRIER_P (i)) | |
1355 | FAIL; | |
1356 | }) | |
1357 | ||
22c3c091 HPN |
1358 | (define_insn "<u>mul<s><mode>3" |
1359 | [(set (match_operand:WD 0 "register_operand" "=r") | |
1360 | (mult:WD | |
1361 | (szext:WD (match_operand:<S> 1 "register_operand" "%0")) | |
1362 | (szext:WD (match_operand:<S> 2 "register_operand" "r")))) | |
fb062a8b HPN |
1363 | (clobber (match_scratch:SI 3 "=h")) |
1364 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 1365 | "TARGET_HAS_MUL_INSNS" |
22c3c091 | 1366 | "%!mul<su><mm> %2,%0" |
86da66b5 | 1367 | [(set (attr "slottable") |
bf0b8cbe | 1368 | (if_then_else (match_test "TARGET_MUL_BUG") |
86da66b5 HPN |
1369 | (const_string "no") |
1370 | (const_string "yes"))) | |
22c3c091 HPN |
1371 | ;; For umuls.[bwd] it's just N unusable here, but let's be safe. |
1372 | ;; For muls.b, this really extends to SImode, so cc should be | |
1373 | ;; considered clobbered. | |
1374 | ;; For muls.w, it's just N unusable here, but let's be safe. | |
0b85d816 HPN |
1375 | (set_attr "cc" "clobber")]) |
1376 | ||
1377 | ;; Note that gcc does not make use of such a thing as umulqisi3. It gets | |
1378 | ;; confused and will erroneously use it instead of umulhisi3, failing (at | |
1379 | ;; least) gcc.c-torture/execute/arith-rand.c at all optimization levels. | |
1380 | ;; Inspection of optab code shows that there must be only one widening | |
1381 | ;; multiplication per mode widened to. | |
1382 | ||
1383 | (define_insn "mulsi3" | |
1384 | [(set (match_operand:SI 0 "register_operand" "=r") | |
ef6201a6 | 1385 | (mult:SI (match_operand:SI 1 "register_operand" "%0") |
f60c7155 | 1386 | (match_operand:SI 2 "register_operand" "r"))) |
fb062a8b HPN |
1387 | (clobber (match_scratch:SI 3 "=h")) |
1388 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 1389 | "TARGET_HAS_MUL_INSNS" |
86da66b5 HPN |
1390 | "%!muls.d %2,%0" |
1391 | [(set (attr "slottable") | |
bf0b8cbe | 1392 | (if_then_else (match_test "TARGET_MUL_BUG") |
86da66b5 HPN |
1393 | (const_string "no") |
1394 | (const_string "yes"))) | |
0b85d816 HPN |
1395 | ;; Just N unusable here, but let's be safe. |
1396 | (set_attr "cc" "clobber")]) | |
1397 | \f | |
1398 | ;; A few multiply variations. | |
1399 | ||
0b85d816 HPN |
1400 | ;; When needed, we can get the high 32 bits from the overflow |
1401 | ;; register. We don't care to split and optimize these. | |
0b85d816 | 1402 | |
22c3c091 | 1403 | (define_insn "<u>mulsidi3" |
0b85d816 HPN |
1404 | [(set (match_operand:DI 0 "register_operand" "=r") |
1405 | (mult:DI | |
22c3c091 HPN |
1406 | (szext:DI (match_operand:SI 1 "register_operand" "%0")) |
1407 | (szext:DI (match_operand:SI 2 "register_operand" "r")))) | |
fb062a8b HPN |
1408 | (clobber (match_scratch:SI 3 "=h")) |
1409 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 1410 | "TARGET_HAS_MUL_INSNS" |
22c3c091 | 1411 | "%!mul<su>.d %2,%M0\;move $mof,%H0") |
0b85d816 | 1412 | |
f60c7155 HPN |
1413 | ;; These two patterns may be expressible by other means, perhaps by making |
1414 | ;; [u]?mulsidi3 a define_expand. | |
1415 | ||
1416 | ;; Due to register allocation braindamage, the clobber 1,2 alternatives | |
1417 | ;; cause a move into the clobbered register *before* the insn, then | |
1418 | ;; after the insn, mof is moved too, rather than the clobber assigned | |
1419 | ;; the last mof target. This became apparent when making MOF and SRP | |
1420 | ;; visible registers, with the necessary tweak to smulsi3_highpart. | |
1421 | ;; Because these patterns are used in division by constants, that damage | |
1422 | ;; is visible (ipps regression tests). Therefore the last two | |
1423 | ;; alternatives, "helping" reload to avoid an unnecessary move, but | |
1424 | ;; punished by force of one "?". Check code from "int d (int a) {return | |
1425 | ;; a / 1000;}" and unsigned. FIXME: Comment above was for 3.2, revisit. | |
0b85d816 | 1426 | |
22c3c091 | 1427 | (define_insn "<su>mulsi3_highpart" |
45d5d09c | 1428 | [(set (match_operand:SI 0 "register_operand" "=h,h,?r,?r") |
0b85d816 HPN |
1429 | (truncate:SI |
1430 | (lshiftrt:DI | |
1431 | (mult:DI | |
22c3c091 HPN |
1432 | (szext:DI (match_operand:SI 1 "register_operand" "r,r,0,r")) |
1433 | (szext:DI (match_operand:SI 2 "register_operand" "r,r,r,0"))) | |
0b85d816 | 1434 | (const_int 32)))) |
fb062a8b HPN |
1435 | (clobber (match_scratch:SI 3 "=1,2,h,h")) |
1436 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 1437 | "TARGET_HAS_MUL_INSNS" |
f60c7155 | 1438 | "@ |
22c3c091 HPN |
1439 | %!mul<su>.d %2,%1 |
1440 | %!mul<su>.d %1,%2 | |
1441 | %!mul<su>.d %2,%1\;move $mof,%0 | |
1442 | %!mul<su>.d %1,%2\;move $mof,%0" | |
f60c7155 HPN |
1443 | [(set_attr "slottable" "yes,yes,no,no") |
1444 | (set_attr "cc" "clobber")]) | |
0b85d816 HPN |
1445 | \f |
1446 | ;; Divide and modulus instructions. CRIS only has a step instruction. | |
1447 | ||
1448 | (define_insn "dstep_shift" | |
1449 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1450 | (if_then_else:SI | |
1451 | (geu:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") | |
1452 | (const_int 1)) | |
1453 | (match_operand:SI 2 "register_operand" "r")) | |
1454 | (minus:SI (ashift:SI (match_operand:SI 3 "register_operand" "0") | |
1455 | (const_int 1)) | |
1456 | (match_operand:SI 4 "register_operand" "2")) | |
1457 | (ashift:SI (match_operand:SI 5 "register_operand" "0") | |
fb062a8b HPN |
1458 | (const_int 1)))) |
1459 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
1460 | "" |
1461 | "dstep %2,%0" | |
d0780379 | 1462 | [(set_attr "slottable" "yes")]) |
0b85d816 HPN |
1463 | |
1464 | ;; Here's a variant with mult instead of ashift. | |
1465 | ;; | |
1466 | ;; FIXME: This should be investigated. Which one matches through combination? | |
1467 | ||
1468 | (define_insn "dstep_mul" | |
1469 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1470 | (if_then_else:SI | |
1471 | (geu:SI (mult:SI (match_operand:SI 1 "register_operand" "0") | |
1472 | (const_int 2)) | |
1473 | (match_operand:SI 2 "register_operand" "r")) | |
1474 | (minus:SI (mult:SI (match_operand:SI 3 "register_operand" "0") | |
1475 | (const_int 2)) | |
1476 | (match_operand:SI 4 "register_operand" "2")) | |
1477 | (mult:SI (match_operand:SI 5 "register_operand" "0") | |
fb062a8b HPN |
1478 | (const_int 2)))) |
1479 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
1480 | "operands[0] != frame_pointer_rtx |
1481 | && operands[1] != frame_pointer_rtx | |
1482 | && operands[2] != frame_pointer_rtx | |
1483 | && operands[3] != frame_pointer_rtx" | |
1484 | "dstep %2,%0" | |
d0780379 | 1485 | [(set_attr "slottable" "yes")]) |
0b85d816 HPN |
1486 | \f |
1487 | ;; Logical operators. | |
1488 | ||
1489 | ;; Bitwise "and". | |
1490 | ||
1491 | ;; There is no use in defining "anddi3", because gcc can expand this by | |
1492 | ;; itself, and make reasonable code without interference. | |
1493 | ||
1494 | ;; If the first operand is memory or a register and is the same as the | |
1495 | ;; second operand, and the third operand is -256 or -65536, we can use | |
1496 | ;; CLEAR instead. Or, if the first operand is a register, and the third | |
1497 | ;; operand is 255 or 65535, we can zero_extend. | |
f5143c46 | 1498 | ;; GCC isn't smart enough to recognize these cases (yet), and they seem |
0b85d816 HPN |
1499 | ;; to be common enough to be worthwhile. |
1500 | ;; FIXME: This should be made obsolete. | |
1501 | ||
1502 | (define_expand "andsi3" | |
fb062a8b HPN |
1503 | [(parallel |
1504 | [(set (match_operand:SI 0 "nonimmediate_operand") | |
1505 | (and:SI (match_operand:SI 1 "nonimmediate_operand") | |
1506 | (match_operand:SI 2 "general_operand"))) | |
1507 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 | 1508 | "" |
0b85d816 | 1509 | { |
991c42ac | 1510 | if (! (CONST_INT_P (operands[2]) |
0b85d816 HPN |
1511 | && (((INTVAL (operands[2]) == -256 |
1512 | || INTVAL (operands[2]) == -65536) | |
1513 | && rtx_equal_p (operands[1], operands[0])) | |
1514 | || ((INTVAL (operands[2]) == 255 | |
1515 | || INTVAL (operands[2]) == 65535) | |
1516 | && REG_P (operands[0]))))) | |
1517 | { | |
1518 | /* Make intermediate steps if operand0 is not a register or | |
1519 | operand1 is not a register, and hope that the reload pass will | |
1520 | make something useful out of it. Note that the operands are | |
1521 | *not* canonicalized. For the moment, I chicken out on this, | |
1522 | because all or most ports do not describe 'and' with | |
1523 | canonicalized operands, and I seem to remember magic in reload, | |
1524 | checking that operand1 has constraint '%0', in which case | |
1525 | operand0 and operand1 must have similar predicates. | |
1526 | FIXME: Investigate. */ | |
1527 | rtx reg0 = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode); | |
1528 | rtx reg1 = operands[1]; | |
1529 | ||
1530 | if (! REG_P (reg1)) | |
1531 | { | |
1532 | emit_move_insn (reg0, reg1); | |
1533 | reg1 = reg0; | |
1534 | } | |
1535 | ||
fb062a8b HPN |
1536 | cris_emit_insn (gen_rtx_SET (reg0, gen_rtx_AND (SImode, reg1, |
1537 | operands[2]))); | |
0b85d816 HPN |
1538 | |
1539 | /* Make sure we get the right *final* destination. */ | |
1540 | if (! REG_P (operands[0])) | |
1541 | emit_move_insn (operands[0], reg0); | |
1542 | ||
1543 | DONE; | |
1544 | } | |
22c3c091 | 1545 | }) |
0b85d816 HPN |
1546 | |
1547 | ;; Some special cases of andsi3. | |
1548 | ||
1549 | (define_insn "*andsi_movu" | |
1550 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
428eae94 | 1551 | (and:SI (match_operand:SI 1 "nonimmediate_operand" "%r,Q,To") |
fb062a8b HPN |
1552 | (match_operand:SI 2 "const_int_operand" "n,n,n"))) |
1553 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
f38a62ff | 1554 | "(INTVAL (operands[2]) == 255 || INTVAL (operands[2]) == 65535) |
c3e786e7 | 1555 | && !side_effects_p (operands[1])" |
0b85d816 HPN |
1556 | "movu.%z2 %1,%0" |
1557 | [(set_attr "slottable" "yes,yes,no")]) | |
1558 | ||
fb062a8b HPN |
1559 | ;; FIXME: Remember, this does *not* actually affect condition codes; |
1560 | ;; get rid of the clobber. | |
0b85d816 | 1561 | (define_insn "*andsi_clear" |
f38a62ff | 1562 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,Q,Q,To,To") |
0b85d816 | 1563 | (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0,0,0") |
fb062a8b HPN |
1564 | (match_operand:SI 2 "const_int_operand" "P,n,P,n,P,n"))) |
1565 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
f38a62ff | 1566 | "(INTVAL (operands[2]) == -65536 || INTVAL (operands[2]) == -256) |
c3e786e7 | 1567 | && !side_effects_p (operands[0])" |
0b85d816 HPN |
1568 | "@ |
1569 | cLear.b %0 | |
1570 | cLear.w %0 | |
1571 | cLear.b %0 | |
1572 | cLear.w %0 | |
1573 | cLear.b %0 | |
1574 | cLear.w %0" | |
1575 | [(set_attr "slottable" "yes,yes,yes,yes,no,no") | |
1576 | (set_attr "cc" "none")]) | |
1577 | ||
1578 | ;; This is a catch-all pattern, taking care of everything that was not | |
1579 | ;; matched in the insns above. | |
1580 | ;; | |
1581 | ;; Sidenote: the tightening from "nonimmediate_operand" to | |
1582 | ;; "register_operand" for operand 1 actually increased the register | |
1583 | ;; pressure (worse code). That will hopefully change with an | |
1584 | ;; improved reload pass. | |
1585 | ||
730cafef | 1586 | (define_insn "*expanded_andsi<setcc><setnz><setnzvc>" |
23369bef HPN |
1587 | [(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r") |
1588 | (and:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,r") | |
fb062a8b HPN |
1589 | (match_operand:SI 2 "general_operand" "I,r,Q>,g,!To"))) |
1590 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1591 | "" |
0b85d816 HPN |
1592 | "@ |
1593 | andq %2,%0 | |
1594 | and.d %2,%0 | |
1595 | and.d %2,%0 | |
1596 | and.d %2,%0 | |
1597 | and.d %2,%1,%0" | |
1598 | [(set_attr "slottable" "yes,yes,yes,no,no")]) | |
1599 | \f | |
1600 | ;; For both QI and HI we may use the quick patterns. This results in | |
1601 | ;; useless condition codes, but that is used rarely enough for it to | |
fb062a8b HPN |
1602 | ;; normally be a win (could check ahead for use of CRIS_CC0_REGNUM, but |
1603 | ;; seems to be more pain than win). | |
0b85d816 HPN |
1604 | |
1605 | ;; FIXME: See note for andsi3 | |
1606 | ||
1607 | (define_expand "andhi3" | |
fb062a8b HPN |
1608 | [(parallel |
1609 | [(set (match_operand:HI 0 "nonimmediate_operand") | |
1610 | (and:HI (match_operand:HI 1 "nonimmediate_operand") | |
1611 | (match_operand:HI 2 "general_operand"))) | |
1612 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 | 1613 | "" |
0b85d816 | 1614 | { |
991c42ac | 1615 | if (! (CONST_INT_P (operands[2]) |
0b85d816 HPN |
1616 | && (((INTVAL (operands[2]) == -256 |
1617 | || INTVAL (operands[2]) == 65280) | |
1618 | && rtx_equal_p (operands[1], operands[0])) | |
1619 | || (INTVAL (operands[2]) == 255 | |
1620 | && REG_P (operands[0]))))) | |
1621 | { | |
1622 | /* See comment for andsi3. */ | |
1623 | rtx reg0 = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (HImode); | |
1624 | rtx reg1 = operands[1]; | |
1625 | ||
1626 | if (! REG_P (reg1)) | |
1627 | { | |
1628 | emit_move_insn (reg0, reg1); | |
1629 | reg1 = reg0; | |
1630 | } | |
1631 | ||
fb062a8b HPN |
1632 | cris_emit_insn (gen_rtx_SET (reg0, gen_rtx_AND (HImode, reg1, |
1633 | operands[2]))); | |
0b85d816 HPN |
1634 | |
1635 | /* Make sure we get the right destination. */ | |
1636 | if (! REG_P (operands[0])) | |
1637 | emit_move_insn (operands[0], reg0); | |
1638 | ||
1639 | DONE; | |
1640 | } | |
22c3c091 | 1641 | }) |
0b85d816 HPN |
1642 | |
1643 | ;; Some fast andhi3 special cases. | |
1644 | ||
1645 | (define_insn "*andhi_movu" | |
1646 | [(set (match_operand:HI 0 "register_operand" "=r,r,r") | |
428eae94 | 1647 | (and:HI (match_operand:HI 1 "nonimmediate_operand" "r,Q,To") |
fb062a8b HPN |
1648 | (const_int 255))) |
1649 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
c3e786e7 | 1650 | "!side_effects_p (operands[1])" |
0b85d816 HPN |
1651 | "mOvu.b %1,%0" |
1652 | [(set_attr "slottable" "yes,yes,no")]) | |
1653 | ||
f38a62ff HPN |
1654 | (define_insn "*andhi_clear" |
1655 | [(set (match_operand:HI 0 "nonimmediate_operand" "=r,Q,To") | |
0b85d816 | 1656 | (and:HI (match_operand:HI 1 "nonimmediate_operand" "0,0,0") |
fb062a8b HPN |
1657 | (const_int -256))) |
1658 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
c3e786e7 | 1659 | "!side_effects_p (operands[0])" |
0b85d816 HPN |
1660 | "cLear.b %0" |
1661 | [(set_attr "slottable" "yes,yes,no") | |
1662 | (set_attr "cc" "none")]) | |
1663 | ||
1664 | ;; Catch-all andhi3 pattern. | |
1665 | ||
730cafef HPN |
1666 | (define_insn "*expanded_andhi<setcc><setnz><setnzvc>" |
1667 | [(set (match_operand:HI 0 "register_operand" "=r,r, r,r, r,r,r,r") | |
1668 | (and:HI (match_operand:HI 1 "register_operand" "%0,0, 0,0, 0,0,0,r") | |
1669 | (match_operand:HI 2 "general_operand" "I,Kc,r,Q>,L,O,g,!To"))) | |
1670 | ;; The "Kc" alternative above, is there to match for cmpelim; | |
1671 | ;; it will be dominated by the "I" alternative at other times. | |
fb062a8b | 1672 | (clobber (reg:CC CRIS_CC0_REGNUM))] |
0b85d816 HPN |
1673 | |
1674 | ;; Sidenote: the tightening from "general_operand" to | |
1675 | ;; "register_operand" for operand 1 actually increased the register | |
1676 | ;; pressure (worse code). That will hopefully change with an | |
1677 | ;; improved reload pass. | |
1678 | ||
d0780379 | 1679 | "" |
0b85d816 | 1680 | "@ |
730cafef | 1681 | andq %2,%0 |
0b85d816 HPN |
1682 | andq %2,%0 |
1683 | and.w %2,%0 | |
1684 | and.w %2,%0 | |
1685 | and.w %2,%0 | |
1686 | anDq %b2,%0 | |
1687 | and.w %2,%0 | |
1688 | and.w %2,%1,%0" | |
730cafef HPN |
1689 | [(set_attr "slottable" "yes,yes,yes,yes,no,yes,no,no") |
1690 | (set_attr "cc<cccc><ccnz><ccnzvc>" | |
1691 | "clobber,normal,normal,normal,normal,clobber,normal,normal")]) | |
0b85d816 HPN |
1692 | |
1693 | ;; A strict_low_part pattern. | |
1694 | ||
d7173593 HPN |
1695 | ;; Note the use of (match_dup 0) for the first operand of the operation |
1696 | ;; here. Reload can't handle an operand pair where one is read-write | |
1697 | ;; and must match a read, like in: | |
1698 | ;; (insn 80 79 81 4 | |
1699 | ;; (set (strict_low_part | |
1700 | ;; (subreg:QI (reg/v:SI 0 r0 [orig:36 data ] [36]) 0)) | |
1701 | ;; (and:QI | |
1702 | ;; (subreg:QI (reg:SI 15 acr [orig:27 D.7531 ] [27]) 0) | |
1703 | ;; (const_int -64 [0xf..fc0]))) x.c:126 147 {*andqi_lowpart_v32} | |
1704 | ;; (nil)) | |
d0780379 | 1705 | ;; (Note: the example is obsolete.) |
d7173593 HPN |
1706 | ;; In theory, it could reload this as a movstrictqi of the register |
1707 | ;; operand at the and:QI to the destination register and change the | |
1708 | ;; and:QI operand to the same as the read-write output operand and the | |
1709 | ;; result would be recognized, but it doesn't recognize that's a valid | |
1710 | ;; reload for a strict_low_part-destination; it just sees a "+" at the | |
1711 | ;; destination constraints. Better than adding complexity to reload is | |
1712 | ;; to follow the lead of m68k (see comment that begins with "These insns | |
1713 | ;; must use MATCH_DUP") since prehistoric times and make it just a | |
1714 | ;; match_dup. FIXME: a sanity-check in gen* to refuse an insn with | |
1715 | ;; input-constraints matching input-output-constraints, e.g. "+r" <- "0". | |
1716 | ||
d0780379 | 1717 | (define_insn "*andhi_lowpart" |
0b85d816 | 1718 | [(set (strict_low_part |
d7173593 HPN |
1719 | (match_operand:HI 0 "register_operand" "+r,r,r")) |
1720 | (and:HI (match_dup 0) | |
fb062a8b HPN |
1721 | (match_operand:HI 1 "general_operand" "r,Q>,g"))) |
1722 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1723 | "" |
0b85d816 | 1724 | "@ |
d7173593 HPN |
1725 | and.w %1,%0 |
1726 | and.w %1,%0 | |
1727 | and.w %1,%0" | |
1728 | [(set_attr "slottable" "yes,yes,no")]) | |
0b85d816 | 1729 | \f |
45d5d09c | 1730 | (define_expand "andqi3" |
fb062a8b HPN |
1731 | [(parallel |
1732 | [(set (match_operand:QI 0 "register_operand") | |
1733 | (and:QI (match_operand:QI 1 "register_operand") | |
1734 | (match_operand:QI 2 "general_operand"))) | |
1735 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
45d5d09c HPN |
1736 | "" |
1737 | "") | |
1738 | ||
730cafef HPN |
1739 | (define_insn "*andqi3<setcc><setnz><setnzvc>" |
1740 | [(set (match_operand:QI 0 "register_operand" "=r,r, r,r, r,r,r") | |
1741 | (and:QI (match_operand:QI 1 "register_operand" "%0,0, 0,0, 0,0,r") | |
1742 | (match_operand:QI 2 "general_operand" "I,Kc,r,Q>,O,g,!To"))) | |
fb062a8b | 1743 | (clobber (reg:CC CRIS_CC0_REGNUM))] |
d0780379 | 1744 | "" |
0b85d816 | 1745 | "@ |
730cafef | 1746 | andq %2,%0 |
0b85d816 HPN |
1747 | andq %2,%0 |
1748 | and.b %2,%0 | |
1749 | and.b %2,%0 | |
1750 | andQ %b2,%0 | |
1751 | and.b %2,%0 | |
1752 | and.b %2,%1,%0" | |
730cafef HPN |
1753 | [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no") |
1754 | (set_attr "cc<cccc><ccnz><ccnzvc>" | |
1755 | "clobber,normal,normal,normal,clobber,normal,normal")]) | |
0b85d816 | 1756 | |
d0780379 | 1757 | (define_insn "*andqi_lowpart" |
0b85d816 | 1758 | [(set (strict_low_part |
d7173593 HPN |
1759 | (match_operand:QI 0 "register_operand" "+r,r,r")) |
1760 | (and:QI (match_dup 0) | |
fb062a8b HPN |
1761 | (match_operand:QI 1 "general_operand" "r,Q>,g"))) |
1762 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1763 | "" |
0b85d816 | 1764 | "@ |
d7173593 HPN |
1765 | and.b %1,%0 |
1766 | and.b %1,%0 | |
1767 | and.b %1,%0" | |
1768 | [(set_attr "slottable" "yes,yes,no")]) | |
0b85d816 HPN |
1769 | \f |
1770 | ;; Bitwise or. | |
1771 | ||
1772 | ;; Same comment as anddi3 applies here - no need for such a pattern. | |
1773 | ||
1774 | ;; It seems there's no need to jump through hoops to get good code such as | |
1775 | ;; with andsi3. | |
1776 | ||
45d5d09c | 1777 | (define_expand "ior<mode>3" |
fb062a8b HPN |
1778 | [(parallel |
1779 | [(set (match_operand:BWD 0 "register_operand") | |
1780 | (ior:BWD (match_operand:BWD 1 "register_operand") | |
1781 | (match_operand:BWD 2 "general_operand"))) | |
1782 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
45d5d09c HPN |
1783 | "" |
1784 | "") | |
1785 | ||
730cafef | 1786 | (define_insn "*iorsi3<setcc><setnz><setnzvc>" |
23369bef HPN |
1787 | [(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r,r") |
1788 | (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,0,r") | |
fb062a8b HPN |
1789 | (match_operand:SI 2 "general_operand" "I, r,Q>,n,g,!To"))) |
1790 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1791 | "" |
0b85d816 HPN |
1792 | "@ |
1793 | orq %2,%0 | |
1794 | or.d %2,%0 | |
1795 | or.d %2,%0 | |
1796 | oR.%s2 %2,%0 | |
1797 | or.d %2,%0 | |
1798 | or.d %2,%1,%0" | |
1799 | [(set_attr "slottable" "yes,yes,yes,no,no,no") | |
730cafef HPN |
1800 | (set_attr "cc<cccc><ccnz><ccnzvc>" |
1801 | "normal,normal,normal,clobber,normal,normal")]) | |
0b85d816 | 1802 | |
730cafef | 1803 | (define_insn "*iorhi3<setcc><setnz><setnzvc>" |
23369bef HPN |
1804 | [(set (match_operand:HI 0 "register_operand" "=r,r,r, r,r,r,r") |
1805 | (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0, 0,0,0,r") | |
fb062a8b HPN |
1806 | (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To"))) |
1807 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1808 | "" |
0b85d816 HPN |
1809 | "@ |
1810 | orq %2,%0 | |
1811 | or.w %2,%0 | |
1812 | or.w %2,%0 | |
1813 | or.w %2,%0 | |
1814 | oRq %b2,%0 | |
1815 | or.w %2,%0 | |
1816 | or.w %2,%1,%0" | |
1817 | [(set_attr "slottable" "yes,yes,yes,no,yes,no,no") | |
730cafef HPN |
1818 | (set_attr "cc<cccc><ccnz><ccnzvc>" |
1819 | "clobber,normal,normal,normal,clobber,normal,normal")]) | |
0b85d816 | 1820 | |
730cafef | 1821 | (define_insn "*iorqi3<setcc><setnz><setnzvc>" |
23369bef HPN |
1822 | [(set (match_operand:QI 0 "register_operand" "=r,r,r, r,r,r") |
1823 | (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0, 0,0,r") | |
fb062a8b HPN |
1824 | (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To"))) |
1825 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 1826 | "" |
0b85d816 HPN |
1827 | "@ |
1828 | orq %2,%0 | |
1829 | or.b %2,%0 | |
1830 | or.b %2,%0 | |
1831 | orQ %b2,%0 | |
1832 | or.b %2,%0 | |
1833 | or.b %2,%1,%0" | |
1834 | [(set_attr "slottable" "yes,yes,yes,yes,no,no") | |
730cafef HPN |
1835 | (set_attr "cc<cccc><ccnz><ccnzvc>" |
1836 | "clobber,normal,normal,clobber,normal,normal")]) | |
0b85d816 HPN |
1837 | \f |
1838 | ;; Exclusive-or | |
1839 | ||
1840 | ;; See comment about "anddi3" for xordi3 - no need for such a pattern. | |
22c3c091 | 1841 | ;; FIXME: Do we really need the shorter variants? |
0b85d816 | 1842 | |
730cafef | 1843 | (define_insn "<acc><anz><anzvc>xorsi3<setcc><setnz><setnzvc>" |
0b85d816 HPN |
1844 | [(set (match_operand:SI 0 "register_operand" "=r") |
1845 | (xor:SI (match_operand:SI 1 "register_operand" "%0") | |
fb062a8b HPN |
1846 | (match_operand:SI 2 "register_operand" "r"))) |
1847 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
1848 | "" |
1849 | "xor %2,%0" | |
d0780379 | 1850 | [(set_attr "slottable" "yes")]) |
0b85d816 | 1851 | |
22c3c091 HPN |
1852 | (define_insn "xor<mode>3" |
1853 | [(set (match_operand:BW 0 "register_operand" "=r") | |
1854 | (xor:BW (match_operand:BW 1 "register_operand" "%0") | |
fb062a8b HPN |
1855 | (match_operand:BW 2 "register_operand" "r"))) |
1856 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
1857 | "" |
1858 | "xor %2,%0" | |
1859 | [(set_attr "slottable" "yes") | |
1860 | (set_attr "cc" "clobber")]) | |
1861 | \f | |
1862 | ;; Negation insns. | |
1863 | ||
1864 | ;; Questionable use, here mostly as a (slightly usable) define_expand | |
1865 | ;; example. | |
1866 | ||
1867 | (define_expand "negsf2" | |
fb062a8b HPN |
1868 | [(parallel |
1869 | [(set (match_dup 2) (match_dup 3)) | |
1870 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
1871 | (parallel [(set (match_operand:SF 0 "register_operand") | |
1872 | (neg:SF (match_operand:SF 1 "register_operand"))) | |
1873 | (use (match_dup 2)) | |
1874 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 | 1875 | "" |
0b85d816 HPN |
1876 | { |
1877 | operands[2] = gen_reg_rtx (SImode); | |
1878 | operands[3] = GEN_INT (1 << 31); | |
22c3c091 | 1879 | }) |
0b85d816 HPN |
1880 | |
1881 | (define_insn "*expanded_negsf2" | |
1882 | [(set (match_operand:SF 0 "register_operand" "=r") | |
1883 | (neg:SF (match_operand:SF 1 "register_operand" "0"))) | |
fb062a8b HPN |
1884 | (use (match_operand:SI 2 "register_operand" "r")) |
1885 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
1886 | "" |
1887 | "xor %2,%0" | |
1888 | [(set_attr "slottable" "yes")]) | |
1889 | ||
1890 | ;; No "negdi2" although we could make one up that may be faster than | |
1891 | ;; the one in libgcc. | |
1892 | ||
a33649e6 | 1893 | (define_insn "<anz>neg<mode>2<setnz>" |
22c3c091 | 1894 | [(set (match_operand:BWD 0 "register_operand" "=r") |
fb062a8b HPN |
1895 | (neg:BWD (match_operand:BWD 1 "register_operand" "r"))) |
1896 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 1897 | "" |
22c3c091 | 1898 | "neg<m> %1,%0" |
0b85d816 HPN |
1899 | [(set_attr "slottable" "yes")]) |
1900 | \f | |
1901 | ;; One-complements. | |
1902 | ||
1903 | ;; See comment on anddi3 - no need for a DImode pattern. | |
22c3c091 | 1904 | ;; See also xor comment. |
0b85d816 | 1905 | |
730cafef | 1906 | (define_insn "<acc><anz><anzvc>one_cmplsi2<setcc><setnz><setnzvc>" |
0b85d816 | 1907 | [(set (match_operand:SI 0 "register_operand" "=r") |
fb062a8b HPN |
1908 | (not:SI (match_operand:SI 1 "register_operand" "0"))) |
1909 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
1910 | "" |
1911 | "not %0" | |
d0780379 | 1912 | [(set_attr "slottable" "yes")]) |
0b85d816 | 1913 | |
22c3c091 HPN |
1914 | (define_insn "one_cmpl<mode>2" |
1915 | [(set (match_operand:BW 0 "register_operand" "=r") | |
fb062a8b HPN |
1916 | (not:BW (match_operand:BW 1 "register_operand" "0"))) |
1917 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
1918 | "" |
1919 | "not %0" | |
1920 | [(set_attr "slottable" "yes") | |
1921 | (set_attr "cc" "clobber")]) | |
1922 | \f | |
22c3c091 | 1923 | ;; Arithmetic/Logical shift right (and SI left). |
0b85d816 | 1924 | |
d137723b | 1925 | (define_insn "<acc><anz><anzvc><shlr>si3<setcc><setnz><setnzvc>" |
0b85d816 | 1926 | [(set (match_operand:SI 0 "register_operand" "=r") |
22c3c091 | 1927 | (shift:SI (match_operand:SI 1 "register_operand" "0") |
fb062a8b HPN |
1928 | (match_operand:SI 2 "nonmemory_operand" "Kcr"))) |
1929 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 1930 | "" |
0b85d816 HPN |
1931 | { |
1932 | if (REG_S_P (operands[2])) | |
22c3c091 | 1933 | return "<slr>.d %2,%0"; |
0b85d816 | 1934 | |
22c3c091 HPN |
1935 | return "<slr>q %2,%0"; |
1936 | } | |
d0780379 | 1937 | [(set_attr "slottable" "yes")]) |
0b85d816 | 1938 | |
22c3c091 HPN |
1939 | ;; Since gcc gets lost, and forgets to zero-extend the source (or mask |
1940 | ;; the destination) when it changes shifts of lower modes into SImode, | |
1941 | ;; it is better to make these expands an anonymous patterns instead of | |
1942 | ;; the more correct define_insns. This occurs when gcc thinks that is | |
1943 | ;; is better to widen to SImode and use immediate shift count. | |
0b85d816 | 1944 | |
22c3c091 | 1945 | ;; FIXME: Is this legacy or still true for gcc >= 2.7.2? |
0b85d816 | 1946 | |
22c3c091 HPN |
1947 | ;; FIXME: Can't parametrize sign_extend and zero_extend (before |
1948 | ;; mentioning "shiftrt"), so we need two patterns. | |
1949 | (define_expand "ashr<mode>3" | |
fb062a8b HPN |
1950 | [(parallel |
1951 | [(set (match_dup 3) | |
1952 | (sign_extend:SI (match_operand:BW 1 "nonimmediate_operand"))) | |
1953 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
1954 | (parallel | |
1955 | [(set (match_dup 4) | |
1956 | (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand"))) | |
1957 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
1958 | (parallel | |
1959 | [(set (match_dup 5) (ashiftrt:SI (match_dup 3) (match_dup 4))) | |
1960 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
1961 | (parallel | |
1962 | [(set (match_operand:BW 0 "general_operand") | |
1963 | (subreg:BW (match_dup 5) 0)) | |
1964 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 | 1965 | "" |
0b85d816 HPN |
1966 | { |
1967 | int i; | |
1968 | ||
1969 | for (i = 3; i < 6; i++) | |
1970 | operands[i] = gen_reg_rtx (SImode); | |
22c3c091 | 1971 | }) |
0b85d816 | 1972 | |
22c3c091 | 1973 | (define_expand "lshr<mode>3" |
fb062a8b HPN |
1974 | [(parallel |
1975 | [(set (match_dup 3) | |
1976 | (zero_extend:SI (match_operand:BW 1 "nonimmediate_operand"))) | |
1977 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
1978 | (parallel | |
1979 | [(set (match_dup 4) | |
1980 | (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand"))) | |
1981 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
1982 | (parallel | |
1983 | [(set (match_dup 5) (lshiftrt:SI (match_dup 3) (match_dup 4))) | |
1984 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
1985 | (parallel | |
1986 | [(set (match_operand:BW 0 "general_operand") | |
1987 | (subreg:BW (match_dup 5) 0)) | |
1988 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 | 1989 | "" |
0b85d816 HPN |
1990 | { |
1991 | int i; | |
1992 | ||
1993 | for (i = 3; i < 6; i++) | |
1994 | operands[i] = gen_reg_rtx (SImode); | |
22c3c091 | 1995 | }) |
0b85d816 | 1996 | |
22c3c091 HPN |
1997 | (define_insn "*expanded_<shlr><mode>" |
1998 | [(set (match_operand:BW 0 "register_operand" "=r") | |
1999 | (shiftrt:BW (match_operand:BW 1 "register_operand" "0") | |
fb062a8b HPN |
2000 | (match_operand:BW 2 "register_operand" "r"))) |
2001 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 2002 | "" |
22c3c091 | 2003 | "<slr><m> %2,%0" |
d0780379 | 2004 | [(set_attr "slottable" "yes")]) |
0b85d816 | 2005 | |
22c3c091 HPN |
2006 | (define_insn "*<shlr><mode>_lowpart" |
2007 | [(set (strict_low_part (match_operand:BW 0 "register_operand" "+r")) | |
2008 | (shiftrt:BW (match_dup 0) | |
fb062a8b HPN |
2009 | (match_operand:BW 1 "register_operand" "r"))) |
2010 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 2011 | "" |
22c3c091 | 2012 | "<slr><m> %1,%0" |
d0780379 | 2013 | [(set_attr "slottable" "yes")]) |
0b85d816 HPN |
2014 | \f |
2015 | ;; Arithmetic/logical shift left. | |
2016 | ||
0b85d816 HPN |
2017 | ;; For narrower modes than SI, we can use lslq although it makes cc |
2018 | ;; unusable. The win is that we do not have to reload the shift-count | |
2019 | ;; into a register. | |
2020 | ||
22c3c091 HPN |
2021 | (define_insn "ashl<mode>3" |
2022 | [(set (match_operand:BW 0 "register_operand" "=r,r") | |
2023 | (ashift:BW (match_operand:BW 1 "register_operand" "0,0") | |
fb062a8b HPN |
2024 | (match_operand:BW 2 "nonmemory_operand" "r,Kc"))) |
2025 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 2026 | "" |
0b85d816 HPN |
2027 | { |
2028 | return | |
991c42ac | 2029 | (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > <nbitsm1>) |
22c3c091 | 2030 | ? "moveq 0,%0" |
0b85d816 | 2031 | : (CONSTANT_P (operands[2]) |
22c3c091 HPN |
2032 | ? "lslq %2,%0" : "lsl<m> %2,%0"); |
2033 | } | |
0b85d816 | 2034 | [(set_attr "slottable" "yes") |
d0780379 | 2035 | (set_attr "cc" "*,clobber")]) |
0b85d816 HPN |
2036 | |
2037 | ;; A strict_low_part matcher. | |
2038 | ||
22c3c091 HPN |
2039 | (define_insn "*ashl<mode>_lowpart" |
2040 | [(set (strict_low_part (match_operand:BW 0 "register_operand" "+r")) | |
2041 | (ashift:BW (match_dup 0) | |
fb062a8b HPN |
2042 | (match_operand:HI 1 "register_operand" "r"))) |
2043 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 | 2044 | "" |
22c3c091 | 2045 | "lsl<m> %1,%0" |
d0780379 | 2046 | [(set_attr "slottable" "yes")]) |
0b85d816 HPN |
2047 | \f |
2048 | ;; Various strange insns that gcc likes. | |
2049 | ||
2050 | ;; Fortunately, it is simple to construct an abssf (although it may not | |
2051 | ;; be very much used in practice). | |
2052 | ||
2053 | (define_insn "abssf2" | |
2054 | [(set (match_operand:SF 0 "register_operand" "=r") | |
fb062a8b HPN |
2055 | (abs:SF (match_operand:SF 1 "register_operand" "0"))) |
2056 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
2057 | "" |
2058 | "lslq 1,%0\;lsrq 1,%0") | |
2059 | ||
2060 | (define_insn "abssi2" | |
2061 | [(set (match_operand:SI 0 "register_operand" "=r") | |
fb062a8b HPN |
2062 | (abs:SI (match_operand:SI 1 "register_operand" "r"))) |
2063 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
0b85d816 HPN |
2064 | "" |
2065 | "abs %1,%0" | |
d0780379 | 2066 | [(set_attr "slottable" "yes")]) |
0b85d816 HPN |
2067 | |
2068 | ;; FIXME: GCC should be able to do these expansions itself. | |
2069 | ||
22c3c091 | 2070 | (define_expand "abs<mode>2" |
fb062a8b HPN |
2071 | [(parallel |
2072 | [(set (match_dup 2) | |
2073 | (sign_extend:SI (match_operand:BW 1 "general_operand"))) | |
2074 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2075 | (parallel | |
2076 | [(set (match_dup 3) (abs:SI (match_dup 2))) | |
2077 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2078 | (parallel | |
2079 | [(set (match_operand:BW 0 "register_operand") | |
2080 | (subreg:BW (match_dup 3) 0)) | |
2081 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 HPN |
2082 | "" |
2083 | "operands[2] = gen_reg_rtx (SImode); operands[3] = gen_reg_rtx (SImode);") | |
e636e508 | 2084 | |
d137723b | 2085 | (define_insn "<acc><anz><anzvc>clzsi2<setcc><setnz><setnzvc>" |
e636e508 | 2086 | [(set (match_operand:SI 0 "register_operand" "=r") |
fb062a8b HPN |
2087 | (clz:SI (match_operand:SI 1 "register_operand" "r"))) |
2088 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
e636e508 JN |
2089 | "TARGET_HAS_LZ" |
2090 | "lz %1,%0" | |
d0780379 | 2091 | [(set_attr "slottable" "yes")]) |
e636e508 | 2092 | |
d137723b | 2093 | (define_insn "<acc><anz><anzvc>bswapsi2<setcc><setnz><setnzvc>" |
df638b27 | 2094 | [(set (match_operand:SI 0 "register_operand" "=r") |
fb062a8b HPN |
2095 | (bswap:SI (match_operand:SI 1 "register_operand" "0"))) |
2096 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
df638b27 JN |
2097 | "TARGET_HAS_SWAP" |
2098 | "swapwb %0" | |
d0780379 | 2099 | [(set_attr "slottable" "yes")]) |
df638b27 | 2100 | |
9ef4a0cd JN |
2101 | ;; This instruction swaps all bits in a register. |
2102 | ;; That means that the most significant bit is put in the place | |
2103 | ;; of the least significant bit, and so on. | |
2104 | ||
2105 | (define_insn "cris_swap_bits" | |
2106 | [(set (match_operand:SI 0 "register_operand" "=r") | |
2107 | (unspec:SI [(match_operand:SI 1 "register_operand" "0")] | |
fb062a8b HPN |
2108 | CRIS_UNSPEC_SWAP_BITS)) |
2109 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
9ef4a0cd JN |
2110 | "TARGET_HAS_SWAP" |
2111 | "swapwbr %0" | |
d0780379 | 2112 | [(set_attr "slottable" "yes")]) |
9ef4a0cd JN |
2113 | |
2114 | ;; Implement ctz using two instructions, one for bit swap and one for clz. | |
2115 | ;; Defines a scratch register to avoid clobbering input. | |
2116 | ||
2117 | (define_expand "ctzsi2" | |
fb062a8b HPN |
2118 | [(parallel |
2119 | [(set (match_dup 2) | |
2120 | (match_operand:SI 1 "register_operand")) | |
2121 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2122 | (parallel | |
2123 | [(set (match_dup 2) | |
2124 | (unspec:SI [(match_dup 2)] CRIS_UNSPEC_SWAP_BITS)) | |
2125 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2126 | (parallel | |
2127 | [(set (match_operand:SI 0 "register_operand") | |
2128 | (clz:SI (match_dup 2))) | |
2129 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
9ef4a0cd JN |
2130 | "TARGET_HAS_LZ && TARGET_HAS_SWAP" |
2131 | "operands[2] = gen_reg_rtx (SImode);") | |
2132 | ||
0b85d816 HPN |
2133 | ;; Bound-insn. Defined to be the same as an unsigned minimum, which is an |
2134 | ;; operation supported by gcc. Used in casesi, but used now and then in | |
2135 | ;; normal code too. | |
2136 | ||
45d5d09c | 2137 | (define_expand "uminsi3" |
fb062a8b HPN |
2138 | [(parallel |
2139 | [(set (match_operand:SI 0 "register_operand") | |
2140 | (umin:SI (match_operand:SI 1 "register_operand") | |
2141 | (match_operand:SI 2 "general_operand"))) | |
2142 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
45d5d09c | 2143 | "" |
d0780379 | 2144 | "") |
45d5d09c | 2145 | |
d137723b | 2146 | (define_insn "*uminsi3<setcc><setnz><setnzvc>" |
23369bef HPN |
2147 | [(set (match_operand:SI 0 "register_operand" "=r,r, r,r") |
2148 | (umin:SI (match_operand:SI 1 "register_operand" "%0,0, 0,r") | |
fb062a8b HPN |
2149 | (match_operand:SI 2 "general_operand" "r,Q>,g,!To"))) |
2150 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
d0780379 | 2151 | "" |
0b85d816 | 2152 | { |
991c42ac | 2153 | if (CONST_INT_P (operands[2])) |
0b85d816 | 2154 | { |
d76fe40b HPN |
2155 | /* Constant operands are zero-extended, so only 32-bit operands |
2156 | may be negative. */ | |
2157 | if (INTVAL (operands[2]) >= 0) | |
2158 | { | |
2159 | if (INTVAL (operands[2]) < 256) | |
2160 | return "bound.b %2,%0"; | |
0b85d816 | 2161 | |
d76fe40b HPN |
2162 | if (INTVAL (operands[2]) < 65536) |
2163 | return "bound.w %2,%0"; | |
2164 | } | |
0b85d816 HPN |
2165 | } |
2166 | else if (which_alternative == 3) | |
22c3c091 | 2167 | return "bound.d %2,%1,%0"; |
0b85d816 | 2168 | |
22c3c091 HPN |
2169 | return "bound.d %2,%0"; |
2170 | } | |
0b85d816 HPN |
2171 | [(set_attr "slottable" "yes,yes,no,no")]) |
2172 | \f | |
2173 | ;; Jump and branch insns. | |
2174 | ||
2175 | (define_insn "jump" | |
2176 | [(set (pc) | |
2177 | (label_ref (match_operand 0 "" "")))] | |
2178 | "" | |
2179 | "ba %l0%#" | |
2180 | [(set_attr "slottable" "has_slot")]) | |
2181 | ||
2182 | ;; Testcase gcc.c-torture/compile/991213-3.c fails if we allow a constant | |
2183 | ;; here, since the insn is not recognized as an indirect jump by | |
2184 | ;; jmp_uses_reg_or_mem used by computed_jump_p. Perhaps it is a kludge to | |
2185 | ;; change from general_operand to nonimmediate_operand (at least the docs | |
2186 | ;; should be changed), but then again the pattern is called indirect_jump. | |
45d5d09c HPN |
2187 | (define_expand "indirect_jump" |
2188 | [(set (pc) (match_operand:SI 0 "nonimmediate_operand"))] | |
0b85d816 | 2189 | "" |
d0780379 | 2190 | "") |
45d5d09c | 2191 | |
d0780379 | 2192 | (define_insn "*indirect_jump" |
45d5d09c | 2193 | [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))] |
d0780379 | 2194 | "" |
0b85d816 HPN |
2195 | "jump %0") |
2196 | ||
2197 | ;; Return insn. Used whenever the epilogue is very simple; if it is only | |
04539954 HPN |
2198 | ;; a single ret or jump [sp+]. No allocated stack space or saved |
2199 | ;; registers are allowed. | |
0b85d816 HPN |
2200 | ;; Note that for this pattern, although named, it is ok to check the |
2201 | ;; context of the insn in the test, not only compiler switches. | |
2202 | ||
04539954 | 2203 | (define_expand "return" |
0b85d816 HPN |
2204 | [(return)] |
2205 | "cris_simple_epilogue ()" | |
04539954 | 2206 | "cris_expand_return (cris_return_address_on_stack ()); DONE;") |
0b85d816 | 2207 | |
04539954 HPN |
2208 | (define_insn "*return_expanded" |
2209 | [(return)] | |
2210 | "" | |
2211 | { | |
2212 | return cris_return_address_on_stack_for_return () | |
2213 | ? "jump [$sp+]" : "ret%#"; | |
2214 | } | |
0b85d816 | 2215 | [(set (attr "slottable") |
04539954 | 2216 | (if_then_else |
bf0b8cbe | 2217 | (match_test "cris_return_address_on_stack_for_return ()") |
04539954 | 2218 | (const_string "no") |
45d5d09c | 2219 | (const_string "has_return_slot")))]) |
04539954 | 2220 | |
d29b4b1b HPN |
2221 | (define_expand "prologue" |
2222 | [(const_int 0)] | |
cc2af705 | 2223 | "" |
d29b4b1b HPN |
2224 | "cris_expand_prologue (); DONE;") |
2225 | ||
04539954 HPN |
2226 | (define_expand "epilogue" |
2227 | [(const_int 0)] | |
cc2af705 | 2228 | "" |
04539954 | 2229 | "cris_expand_epilogue (); DONE;") |
0b85d816 HPN |
2230 | \f |
2231 | ;; Conditional branches. | |
2232 | ||
f90b7a5a | 2233 | (define_expand "cbranch<mode>4" |
fb062a8b HPN |
2234 | [(parallel |
2235 | [(set (pc) | |
2236 | (if_then_else | |
2237 | (match_operator 0 "ordered_comparison_operator" | |
2238 | [(match_operand:BWDD 1 "nonimmediate_operand") | |
2239 | (match_operand:BWDD 2 "general_operand")]) | |
2240 | (label_ref (match_operand 3 "")) | |
2241 | (pc))) | |
2242 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
f90b7a5a | 2243 | "" |
cfaf5204 | 2244 | "cris_reduce_compare (&operands[0], &operands[1], &operands[2]);") |
f90b7a5a | 2245 | |
b3e01c3d | 2246 | (define_insn_and_split "*cbranch<mode><code>4" |
fb062a8b HPN |
2247 | [(set (pc) |
2248 | (if_then_else | |
b3e01c3d HPN |
2249 | (cond |
2250 | (match_operand:BWDD 0 "nonimmediate_operand" "<cmp_op0c>") | |
2251 | (match_operand:BWDD 1 "general_operand" "<cmp_op1c>")) | |
2252 | (label_ref (match_operand 2 "")) | |
fb062a8b HPN |
2253 | (pc))) |
2254 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
2255 | "" | |
2256 | "#" | |
2257 | "&& reload_completed" | |
b3e01c3d HPN |
2258 | [(set (reg:<xCC> CRIS_CC0_REGNUM) |
2259 | (compare:<xCC> (match_dup 0) (match_dup 1))) | |
f90b7a5a | 2260 | (set (pc) |
b3e01c3d HPN |
2261 | (if_then_else (cond (reg:<xCC> CRIS_CC0_REGNUM) (const_int 0)) |
2262 | (label_ref (match_dup 2)) | |
f90b7a5a | 2263 | (pc)))] |
fb062a8b | 2264 | "") |
f90b7a5a | 2265 | |
b73bf8a1 HPN |
2266 | ;; Test a single bit at operand[0] against 0/non-0. |
2267 | (define_insn_and_split "*cbranch<mode>4_btstrq1_<CC>" | |
2268 | [(set (pc) | |
2269 | (if_then_else | |
2270 | (zcond | |
2271 | (zero_extract:BWD | |
2272 | (match_operand:BWD 0 "register_operand" "r,r") | |
2273 | (const_int 1) | |
2274 | (match_operand:SI 1 "nonmemory_operand" "Kc,r")) | |
2275 | (const_int 0)) | |
2276 | (label_ref (match_operand 2 "")) | |
2277 | (pc))) | |
2278 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
2279 | "" | |
2280 | "#" | |
2281 | "&& reload_completed" | |
2282 | [(set (reg:CC_ZnN CRIS_CC0_REGNUM) | |
2283 | (compare:CC_ZnN | |
2284 | (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)) | |
2285 | (const_int 0))) | |
2286 | (set (pc) | |
2287 | (if_then_else (zcond (reg:CC_ZnN CRIS_CC0_REGNUM) (const_int 0)) | |
2288 | (label_ref (match_dup 2)) | |
2289 | (pc)))] | |
2290 | "") | |
2291 | ||
2292 | ;; Test a field of bits starting at bit 0 against 0/non-0. | |
2293 | (define_insn_and_split "*cbranch<mode>4_btstqb0_<CC>" | |
27228024 HPN |
2294 | [(set (pc) |
2295 | (if_then_else | |
2296 | (zcond | |
2297 | (zero_extract:BWD | |
2298 | (match_operand:BWD 0 "register_operand" "r") | |
2299 | (match_operand 1 "const_int_operand" "Kc") | |
2300 | (const_int 0)) | |
2301 | (const_int 0)) | |
2302 | (label_ref (match_operand 2 "")) | |
2303 | (pc))) | |
2304 | (clobber (reg:CC CRIS_CC0_REGNUM))] | |
2305 | "" | |
2306 | "#" | |
2307 | "&& reload_completed" | |
b73bf8a1 HPN |
2308 | [(set (reg:CC_NZ CRIS_CC0_REGNUM) |
2309 | (compare:CC_NZ | |
27228024 HPN |
2310 | (zero_extract:SI (match_dup 0) (match_dup 1) (const_int 0)) |
2311 | (const_int 0))) | |
2312 | (set (pc) | |
b73bf8a1 | 2313 | (if_then_else (zcond (reg:CC_NZ CRIS_CC0_REGNUM) (const_int 0)) |
b3e01c3d | 2314 | (label_ref (match_dup 2)) |
27228024 HPN |
2315 | (pc)))] |
2316 | "") | |
2317 | ||
f90b7a5a | 2318 | |
0b85d816 HPN |
2319 | ;; We suffer from the same overflow-bit-gets-in-the-way problem as |
2320 | ;; e.g. m68k, so we have to check if overflow bit is set on all "signed" | |
2321 | ;; conditions. | |
2322 | ||
3c7016b0 | 2323 | (define_insn "*b<zcond:code><mode>" |
0b85d816 | 2324 | [(set (pc) |
b73bf8a1 | 2325 | (if_then_else (zcond (reg:ZnNNZUSE CRIS_CC0_REGNUM) |
22c3c091 | 2326 | (const_int 0)) |
0b85d816 HPN |
2327 | (label_ref (match_operand 0 "" "")) |
2328 | (pc)))] | |
fb062a8b | 2329 | "reload_completed" |
b73bf8a1 HPN |
2330 | { |
2331 | return <MODE>mode == CC_ZnNmode ? "b<znnCC> %l0%#" : "b<CC> %l0%#"; | |
2332 | } | |
0b85d816 HPN |
2333 | [(set_attr "slottable" "has_slot")]) |
2334 | ||
3c7016b0 | 2335 | (define_insn "*b<nzvccond:code><mode>" |
0b85d816 | 2336 | [(set (pc) |
b3e01c3d | 2337 | (if_then_else (nzvccond (reg:NZVCUSE CRIS_CC0_REGNUM) |
22c3c091 | 2338 | (const_int 0)) |
0b85d816 HPN |
2339 | (label_ref (match_operand 0 "" "")) |
2340 | (pc)))] | |
fb062a8b | 2341 | "reload_completed" |
fb062a8b | 2342 | "b<CC> %l0%#" |
0b85d816 HPN |
2343 | [(set_attr "slottable" "has_slot")]) |
2344 | ||
3c7016b0 | 2345 | (define_insn "*b<rnzcond:code><mode>" |
0b85d816 | 2346 | [(set (pc) |
b3e01c3d | 2347 | (if_then_else (rnzcond (reg:NZUSE CRIS_CC0_REGNUM) |
22c3c091 | 2348 | (const_int 0)) |
0b85d816 HPN |
2349 | (label_ref (match_operand 0 "" "")) |
2350 | (pc)))] | |
fb062a8b | 2351 | "reload_completed" |
b3e01c3d HPN |
2352 | { |
2353 | return <MODE>mode == CC_NZmode ? "b<oCC> %l0%#": "b<CC> %l0%#"; | |
2354 | } | |
0b85d816 HPN |
2355 | [(set_attr "slottable" "has_slot")]) |
2356 | \f | |
2357 | ;; Reversed anonymous patterns to the ones above, as mandated. | |
2358 | ||
b3e01c3d | 2359 | (define_insn "*b<nzcond:code>_reversed<mode>" |
0b85d816 | 2360 | [(set (pc) |
b73bf8a1 HPN |
2361 | (if_then_else (nzcond (reg:ZnNNZUSE CRIS_CC0_REGNUM) |
2362 | (const_int 0)) | |
0b85d816 HPN |
2363 | (pc) |
2364 | (label_ref (match_operand 0 "" ""))))] | |
fb062a8b | 2365 | "reload_completed" |
b73bf8a1 HPN |
2366 | { |
2367 | return <MODE>mode == CC_ZnNmode ? "b<rznnCC> %l0%#" : "b<rCC> %l0%#"; | |
2368 | } | |
0b85d816 HPN |
2369 | [(set_attr "slottable" "has_slot")]) |
2370 | ||
b3e01c3d | 2371 | (define_insn "*b<nzvccond:code>_reversed<mode>" |
0b85d816 | 2372 | [(set (pc) |
b3e01c3d | 2373 | (if_then_else (nzvccond (reg:NZVCUSE CRIS_CC0_REGNUM) |
22c3c091 | 2374 | (const_int 0)) |
0b85d816 HPN |
2375 | (pc) |
2376 | (label_ref (match_operand 0 "" ""))))] | |
fb062a8b | 2377 | "reload_completed" |
fb062a8b | 2378 | "b<rCC> %l0%#" |
0b85d816 HPN |
2379 | [(set_attr "slottable" "has_slot")]) |
2380 | ||
b3e01c3d | 2381 | (define_insn "*b<rnzcond:code>_reversed<mode>" |
0b85d816 | 2382 | [(set (pc) |
b3e01c3d | 2383 | (if_then_else (rnzcond (reg:NZUSE CRIS_CC0_REGNUM) |
22c3c091 | 2384 | (const_int 0)) |
0b85d816 HPN |
2385 | (pc) |
2386 | (label_ref (match_operand 0 "" ""))))] | |
fb062a8b | 2387 | "reload_completed" |
b3e01c3d HPN |
2388 | { |
2389 | return <MODE>mode == CC_NZmode ? "b<roCC> %l0%#" : "b<rCC> %l0%#"; | |
2390 | } | |
0b85d816 HPN |
2391 | [(set_attr "slottable" "has_slot")]) |
2392 | \f | |
2393 | ;; Set on condition: sCC. | |
2394 | ||
fb062a8b HPN |
2395 | (define_expand "cstore<mode>4" |
2396 | [(parallel | |
2397 | [(set (match_operand:SI 0 "register_operand") | |
2398 | (match_operator:SI 1 "ordered_comparison_operator" | |
2399 | [(match_operand:BWDD 2 "nonimmediate_operand") | |
2400 | (match_operand:BWDD 3 "general_operand")])) | |
2401 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
f90b7a5a | 2402 | "" |
d0780379 | 2403 | "cris_reduce_compare (&operands[1], &operands[2], &operands[3]);") |
f90b7a5a | 2404 | |
b3e01c3d | 2405 | (define_insn_and_split "*cstore<mode><code>4" |
fb062a8b | 2406 | [(set (match_operand:SI 0 "register_operand" "=<sCC_destc>") |
b3e01c3d HPN |
2407 | (cond:SI |
2408 | (match_operand:BWDD 1 "nonimmediate_operand" "<cmp_op0c>") | |
2409 | (match_operand:BWDD 2 "general_operand" "<cmp_op1c>"))) | |
fb062a8b | 2410 | (clobber (reg:CC CRIS_CC0_REGNUM))] |
f90b7a5a | 2411 | "" |
fb062a8b HPN |
2412 | "#" |
2413 | "&& reload_completed" | |
b3e01c3d HPN |
2414 | [(set (reg:<xCC> CRIS_CC0_REGNUM) |
2415 | (compare:<xCC> (match_dup 1) (match_dup 2))) | |
2416 | (set (match_dup 0) | |
2417 | (cond:SI (reg:<xCC> CRIS_CC0_REGNUM) (const_int 0)))] | |
fb062a8b | 2418 | "") |
f90b7a5a | 2419 | |
0b85d816 HPN |
2420 | ;; Like bCC, we have to check the overflow bit for |
2421 | ;; signed conditions. | |
2422 | ||
b3e01c3d | 2423 | (define_insn "*s<nzcond:code><mode>" |
0b85d816 | 2424 | [(set (match_operand:SI 0 "register_operand" "=r") |
b3e01c3d | 2425 | (nzcond:SI (reg:NZUSE CRIS_CC0_REGNUM) (const_int 0)))] |
fb062a8b | 2426 | "reload_completed" |
22c3c091 | 2427 | "s<CC> %0" |
0b85d816 HPN |
2428 | [(set_attr "slottable" "yes") |
2429 | (set_attr "cc" "none")]) | |
2430 | ||
b3e01c3d | 2431 | (define_insn "*s<rnzcond:code><mode>" |
0b85d816 | 2432 | [(set (match_operand:SI 0 "register_operand" "=r") |
b3e01c3d | 2433 | (rnzcond:SI (reg:NZUSE CRIS_CC0_REGNUM) (const_int 0)))] |
fb062a8b | 2434 | "reload_completed" |
b3e01c3d HPN |
2435 | { |
2436 | return <MODE>mode == CC_NZmode ? "s<oCC> %0" : "s<CC> %0"; | |
2437 | } | |
0cec6af1 HPN |
2438 | [(set_attr "slottable" "yes") |
2439 | (set_attr "cc" "none")]) | |
0b85d816 | 2440 | |
b3e01c3d | 2441 | (define_insn "*s<nzvccond:code><mode>" |
0b85d816 | 2442 | [(set (match_operand:SI 0 "register_operand" "=r") |
b3e01c3d | 2443 | (nzvccond:SI (reg:NZVCUSE CRIS_CC0_REGNUM) (const_int 0)))] |
fb062a8b | 2444 | "reload_completed" |
fb062a8b | 2445 | "s<CC> %0" |
0b85d816 HPN |
2446 | [(set_attr "slottable" "yes") |
2447 | (set_attr "cc" "none")]) | |
2448 | \f | |
2449 | ;; Call insns. | |
2450 | ||
2451 | ;; We need to make these patterns "expand", since the real operand is | |
2452 | ;; hidden in a (mem:QI ) inside operand[0] (call_value: operand[1]), | |
2453 | ;; and cannot be checked if it were a "normal" pattern. | |
2454 | ;; Note that "call" and "call_value" are *always* called with a | |
2455 | ;; mem-operand for operand 0 and 1 respective. What happens for combined | |
2456 | ;; instructions is a different issue. | |
2457 | ||
2458 | (define_expand "call" | |
d0780379 HPN |
2459 | [(parallel [(call (match_operand:SI 0 "indirect_operand") |
2460 | (match_operand 1 "general_operand")) | |
f16bb520 | 2461 | (clobber (reg:SI CRIS_SRP_REGNUM))])] |
0b85d816 | 2462 | "" |
0b85d816 | 2463 | { |
d0780379 | 2464 | operands[1] = const0_rtx; |
b6c34129 | 2465 | }) |
0b85d816 | 2466 | |
ab4e53fe | 2467 | ;; Accept operands for operand 0 in order of preference. |
0b85d816 | 2468 | |
d0780379 | 2469 | (define_insn "*expanded_call" |
45d5d09c | 2470 | [(call (mem:QI (match_operand:SI 0 "general_operand" "r,Q>,g")) |
d0780379 | 2471 | (const_int 0)) |
f16bb520 | 2472 | (clobber (reg:SI CRIS_SRP_REGNUM))] |
d0780379 | 2473 | "" |
0b85d816 HPN |
2474 | "jsr %0") |
2475 | ||
2476 | (define_expand "call_value" | |
d0780379 HPN |
2477 | [(parallel [(set (match_operand 0 "") |
2478 | (call (match_operand:SI 1 "indirect_operand") | |
2479 | (match_operand 2 ""))) | |
f16bb520 | 2480 | (clobber (reg:SI CRIS_SRP_REGNUM))])] |
0b85d816 | 2481 | "" |
0b85d816 | 2482 | { |
d0780379 | 2483 | operands[2] = const0_rtx; |
b6c34129 | 2484 | }) |
0b85d816 | 2485 | |
ab4e53fe | 2486 | ;; The validity other than "general" of |
0b85d816 HPN |
2487 | ;; operand 0 will be checked elsewhere. Accept operands for operand 1 in |
2488 | ;; order of preference (Q includes r, but r is shorter, faster). | |
2489 | ;; We also accept a PLT symbol. We output it as [rPIC+sym:GOTPLT] rather | |
2490 | ;; than requiring getting rPIC + sym:PLT into a register. | |
2491 | ||
d0780379 | 2492 | (define_insn "*expanded_call_value" |
c00fc5cf | 2493 | [(set (match_operand 0 "nonimmediate_operand" "=g,g,g") |
45d5d09c | 2494 | (call (mem:QI (match_operand:SI 1 "general_operand" "r,Q>,g")) |
d0780379 | 2495 | (const_int 0))) |
f16bb520 | 2496 | (clobber (reg:SI CRIS_SRP_REGNUM))] |
d0780379 | 2497 | "" |
0b85d816 HPN |
2498 | "Jsr %1" |
2499 | [(set_attr "cc" "clobber")]) | |
2500 | ||
0b85d816 HPN |
2501 | ;; Used in debugging. No use for the direct pattern; unfilled |
2502 | ;; delayed-branches are taken care of by other means. | |
2503 | ||
2504 | (define_insn "nop" | |
2505 | [(const_int 0)] | |
2506 | "" | |
2507 | "nop" | |
2508 | [(set_attr "cc" "none")]) | |
64f5af47 | 2509 | |
d0780379 HPN |
2510 | ;; Same as the gdb trap breakpoint: would cause a SIGTRAP for |
2511 | ;; cris-linux* and will work in freestanding environments with | |
2512 | ;; sufficient framework. | |
64f5af47 HPN |
2513 | (define_insn "trap" |
2514 | [(trap_if (const_int 1) (const_int 8))] | |
2515 | "TARGET_TRAP_USING_BREAK8" | |
2516 | "break 8") | |
0b85d816 | 2517 | \f |
04539954 HPN |
2518 | ;; We need to stop accesses to the stack after the memory is |
2519 | ;; deallocated. Unfortunately, reorg doesn't look at naked clobbers, | |
2520 | ;; e.g. (insn ... (clobber (mem:BLK (stack_pointer_rtx)))) and we don't | |
2521 | ;; want to use a naked (unspec_volatile) as that would stop any | |
2522 | ;; scheduling in the epilogue. Hence we model it as a "real" insn that | |
2523 | ;; sets the memory in an unspecified manner. FIXME: Unfortunately it | |
2524 | ;; still has the effect of an unspec_volatile. | |
2525 | (define_insn "cris_frame_deallocated_barrier" | |
2526 | [(set (mem:BLK (reg:SI CRIS_SP_REGNUM)) | |
2527 | (unspec:BLK [(const_int 0)] CRIS_UNSPEC_FRAME_DEALLOC))] | |
2528 | "" | |
2529 | "" | |
2530 | [(set_attr "length" "0")]) | |
2531 | ||
0b85d816 HPN |
2532 | ;; We expand on casesi so we can use "bound" and "add offset fetched from |
2533 | ;; a table to pc" (adds.w [pc+%0.w],pc). | |
2534 | ||
2535 | ;; Note: if you change the "parallel" (or add anything after it) in | |
2536 | ;; this expansion, you must change the macro ASM_OUTPUT_CASE_END | |
2537 | ;; accordingly, to add the default case at the end of the jump-table. | |
2538 | ||
d0780379 | 2539 | (define_expand "casesi" |
fb062a8b HPN |
2540 | [(parallel |
2541 | [(set (match_dup 5) (match_operand:SI 0 "general_operand")) | |
2542 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2543 | (parallel | |
2544 | [(set (match_dup 6) | |
2545 | (minus:SI (match_dup 5) | |
2546 | (match_operand:SI 1 "const_int_operand"))) | |
2547 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2548 | (parallel | |
2549 | [(set (match_dup 7) | |
2550 | (umin:SI (match_dup 6) | |
2551 | (match_operand:SI 2 "const_int_operand"))) | |
2552 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
0b85d816 HPN |
2553 | (parallel |
2554 | [(set (pc) | |
2555 | (if_then_else | |
2556 | (ltu (match_dup 7) (match_dup 2)) | |
2557 | (plus:SI (sign_extend:SI | |
2558 | (mem:HI | |
2559 | (plus:SI (mult:SI (match_dup 7) (const_int 2)) | |
2560 | (pc)))) | |
2561 | (pc)) | |
fb062a8b HPN |
2562 | (label_ref (match_operand 4 "")))) |
2563 | (use (label_ref (match_operand 3 ""))) | |
2564 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 | 2565 | "" |
0b85d816 | 2566 | { |
0a81f074 | 2567 | operands[2] = plus_constant (SImode, operands[2], 1); |
0b85d816 HPN |
2568 | operands[5] = gen_reg_rtx (SImode); |
2569 | operands[6] = gen_reg_rtx (SImode); | |
2570 | operands[7] = gen_reg_rtx (SImode); | |
22c3c091 | 2571 | }) |
21ed4444 HPN |
2572 | |
2573 | (include "sync.md") | |
0b85d816 | 2574 | \f |
0b85d816 HPN |
2575 | ;; Various peephole optimizations. |
2576 | ;; | |
0b85d816 | 2577 | ;; Do not add patterns that you do not know will be matched. |
109b748d | 2578 | ;; Please also add a self-contained testcase. |
0b85d816 HPN |
2579 | |
2580 | ;; We have trouble with and:s and shifts. Maybe something is broken in | |
43a88a8c | 2581 | ;; gcc? Or it could just be that bit-field insn expansion is a bit |
cf2bfc7c HPN |
2582 | ;; suboptimal when not having extzv insns. Or combine being over-eager |
2583 | ;; to canonicalize to "and", and ignorant on the benefits of the right | |
2584 | ;; mixture of "and" and "zero-extend". | |
2585 | ||
2586 | ;; Testcase for the following peephole: gcc.target/cris/peep2-movulsr.c | |
2587 | ||
2588 | ;; Where equivalent and where the "and" argument doesn't fit "andq" but | |
2589 | ;; is 16 bits or smaller, replace the "and" with a zero-extend preceding | |
2590 | ;; the shift. A zero-extend is shorter and faster than "and" with a | |
2591 | ;; 32-bit argument. | |
2592 | ||
2593 | (define_peephole2 ; movulsr | |
2594 | [(parallel | |
2595 | [(set (match_operand:SI 0 "register_operand") | |
2596 | (lshiftrt:SI (match_dup 0) | |
2597 | (match_operand:SI 1 "const_int_operand"))) | |
2598 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2599 | (parallel | |
2600 | [(set (match_dup 0) | |
2601 | (and:SI (match_dup 0) | |
2602 | (match_operand 2 "const_int_operand"))) | |
2603 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
2604 | "INTVAL (operands[2]) > 31 && INTVAL (operands[2]) <= 0xffff | |
2605 | && (((INTVAL (operands[2]) <= 0xff ? 0xff : 0xffff) >> INTVAL (operands[1])) | |
2606 | == INTVAL (operands[2]))" | |
2607 | [(parallel | |
2608 | ;; The zero-extend is expressed as an "and", only because that's easier | |
2609 | ;; than messing with zero-extend of a subreg. | |
2610 | [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 3))) | |
2611 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2612 | (parallel | |
2613 | [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) | |
2614 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
2615 | { | |
2616 | operands[3] | |
2617 | = INTVAL (operands[2]) <= 0xff ? GEN_INT (0xff) : GEN_INT (0xffff); | |
2618 | }) | |
2619 | ||
2620 | ;; Testcase for the following four peepholes: gcc.target/cris/peep2-xsrand.c | |
0b85d816 | 2621 | |
fb062a8b HPN |
2622 | (define_peephole2 ; asrandb |
2623 | [(parallel | |
2624 | [(set (match_operand:SI 0 "register_operand") | |
2625 | (ashiftrt:SI (match_dup 0) | |
2626 | (match_operand:SI 1 "const_int_operand"))) | |
2627 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2628 | (parallel | |
2629 | [(set (match_dup 0) | |
0b85d816 | 2630 | (and:SI (match_dup 0) |
fb062a8b HPN |
2631 | (match_operand 2 "const_int_operand"))) |
2632 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 HPN |
2633 | "INTVAL (operands[2]) > 31 |
2634 | && INTVAL (operands[2]) < 255 | |
8ad46d34 HPN |
2635 | && INTVAL (operands[1]) > 23 |
2636 | /* Check that the and-operation enables us to use logical-shift. */ | |
2637 | && (INTVAL (operands[2]) | |
c4362b60 JL |
2638 | & ((HOST_WIDE_INT) (HOST_WIDE_INT_M1U |
2639 | << (32 - INTVAL (operands[1]))))) == 0" | |
fb062a8b HPN |
2640 | [(parallel |
2641 | [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) | |
2642 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2643 | (parallel | |
2644 | [(set (match_dup 3) (and:QI (match_dup 3) (match_dup 4))) | |
2645 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
bf6ac87c HPN |
2646 | { |
2647 | operands[3] = gen_rtx_REG (QImode, REGNO (operands[0])); | |
2648 | operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), QImode)); | |
2649 | }) | |
8ad46d34 | 2650 | |
fb062a8b HPN |
2651 | (define_peephole2 ; asrandw |
2652 | [(parallel | |
2653 | [(set (match_operand:SI 0 "register_operand") | |
2654 | (ashiftrt:SI (match_dup 0) | |
2655 | (match_operand:SI 1 "const_int_operand"))) | |
2656 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2657 | (parallel | |
2658 | [(set (match_dup 0) | |
2659 | (and:SI (match_dup 0) (match_operand 2 "const_int_operand"))) | |
2660 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 HPN |
2661 | "INTVAL (operands[2]) > 31 |
2662 | && INTVAL (operands[2]) < 65535 | |
2663 | && INTVAL (operands[2]) != 255 | |
8ad46d34 HPN |
2664 | && INTVAL (operands[1]) > 15 |
2665 | /* Check that the and-operation enables us to use logical-shift. */ | |
2666 | && (INTVAL (operands[2]) | |
c4362b60 JL |
2667 | & ((HOST_WIDE_INT) (HOST_WIDE_INT_M1U |
2668 | << (32 - INTVAL (operands[1]))))) == 0" | |
fb062a8b HPN |
2669 | [(parallel |
2670 | [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) | |
2671 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2672 | (parallel | |
2673 | [(set (match_dup 3) (and:HI (match_dup 3) (match_dup 4))) | |
2674 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
bf6ac87c HPN |
2675 | { |
2676 | operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); | |
2677 | operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), HImode)); | |
2678 | }) | |
8ad46d34 | 2679 | |
fb062a8b HPN |
2680 | (define_peephole2 ; lsrandb |
2681 | [(parallel | |
2682 | [(set (match_operand:SI 0 "register_operand") | |
2683 | (lshiftrt:SI (match_dup 0) | |
2684 | (match_operand:SI 1 "const_int_operand"))) | |
2685 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2686 | (parallel | |
2687 | [(set (match_dup 0) | |
2688 | (and:SI (match_dup 0) (match_operand 2 "const_int_operand"))) | |
2689 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 HPN |
2690 | "INTVAL (operands[2]) > 31 |
2691 | && INTVAL (operands[2]) < 255 | |
2692 | && INTVAL (operands[1]) > 23" | |
fb062a8b HPN |
2693 | [(parallel |
2694 | [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) | |
2695 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2696 | (parallel | |
2697 | [(set (match_dup 3) (and:QI (match_dup 3) (match_dup 4))) | |
2698 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
bf6ac87c HPN |
2699 | { |
2700 | operands[3] = gen_rtx_REG (QImode, REGNO (operands[0])); | |
2701 | operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), QImode)); | |
2702 | }) | |
0b85d816 | 2703 | |
fb062a8b HPN |
2704 | (define_peephole2 ; lsrandw |
2705 | [(parallel | |
2706 | [(set (match_operand:SI 0 "register_operand") | |
0b85d816 | 2707 | (lshiftrt:SI (match_dup 0) |
fb062a8b HPN |
2708 | (match_operand:SI 1 "const_int_operand"))) |
2709 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2710 | (parallel | |
2711 | [(set (match_dup 0) | |
2712 | (and:SI (match_dup 0) (match_operand 2 "const_int_operand"))) | |
2713 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 HPN |
2714 | "INTVAL (operands[2]) > 31 && INTVAL (operands[2]) < 65535 |
2715 | && INTVAL (operands[2]) != 255 | |
2716 | && INTVAL (operands[1]) > 15" | |
fb062a8b HPN |
2717 | [(parallel |
2718 | [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) | |
2719 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2720 | (parallel | |
2721 | [(set (match_dup 3) (and:HI (match_dup 3) (match_dup 4))) | |
2722 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
bf6ac87c HPN |
2723 | { |
2724 | operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); | |
2725 | operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), HImode)); | |
2726 | }) | |
0b85d816 | 2727 | |
ff2ca1bc HPN |
2728 | ;; There seems to be no other way to make GCC (including 4.8/trunk at |
2729 | ;; r186932) optimally reload an instruction that looks like | |
2730 | ;; and.d reg_or_mem,const_32__65535,other_reg | |
2731 | ;; where other_reg is the destination. | |
0b85d816 | 2732 | ;; It should be: |
ff2ca1bc HPN |
2733 | ;; movu.[bw] reg_or_mem,reg_32 |
2734 | ;; and.[bw] trunc_int_for_mode([bw], const_32__65535),reg_32 ;; or andq | |
365cacbf | 2735 | ;; but it turns into: |
ff2ca1bc HPN |
2736 | ;; move.d reg_or_mem,reg_32 |
2737 | ;; and.d const_32__65535,reg_32 | |
2738 | ;; Fix it with these two peephole2's. | |
cf2bfc7c | 2739 | ;; Testcases: gcc.target/cris/peep2-andu1.c gcc.target/cris/peep2-andu2.c |
0b85d816 | 2740 | |
fb062a8b HPN |
2741 | (define_peephole2 ; andu |
2742 | [(parallel | |
2743 | [(set (match_operand:SI 0 "register_operand") | |
2744 | (match_operand:SI 1 "nonimmediate_operand")) | |
2745 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2746 | (parallel | |
2747 | [(set (match_operand:SI 2 "register_operand") | |
2748 | (and:SI (match_dup 0) | |
2749 | (match_operand:SI 3 "const_int_operand"))) | |
2750 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 HPN |
2751 | ;; Since the size of the memory access could be made different here, |
2752 | ;; don't do this for a mem-volatile access. | |
0b85d816 HPN |
2753 | "REGNO (operands[2]) == REGNO (operands[0]) |
2754 | && INTVAL (operands[3]) <= 65535 && INTVAL (operands[3]) >= 0 | |
06cadf63 | 2755 | && !satisfies_constraint_I (operands[3]) |
365cacbf HPN |
2756 | && !side_effects_p (operands[1]) |
2757 | && (!REG_P (operands[1]) | |
2758 | || REGNO (operands[1]) <= CRIS_LAST_GENERAL_REGISTER)" | |
fb062a8b HPN |
2759 | [(parallel |
2760 | [(set (match_dup 0) (match_dup 4)) | |
2761 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2762 | (parallel | |
2763 | [(set (match_dup 5) (match_dup 6)) | |
2764 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
0b85d816 | 2765 | { |
ef4bddc2 RS |
2766 | machine_mode zmode = INTVAL (operands[3]) <= 255 ? QImode : HImode; |
2767 | machine_mode amode | |
06cadf63 | 2768 | = satisfies_constraint_O (operands[3]) ? SImode : zmode; |
8ad46d34 HPN |
2769 | rtx op1 |
2770 | = (REG_S_P (operands[1]) | |
2771 | ? gen_rtx_REG (zmode, REGNO (operands[1])) | |
2772 | : adjust_address (operands[1], zmode, 0)); | |
2773 | operands[4] | |
2774 | = gen_rtx_ZERO_EXTEND (SImode, op1); | |
2775 | operands[5] = gen_rtx_REG (amode, REGNO (operands[0])); | |
2776 | operands[6] | |
2777 | = gen_rtx_AND (amode, gen_rtx_REG (amode, REGNO (operands[0])), | |
2778 | GEN_INT (trunc_int_for_mode (INTVAL (operands[3]), | |
2779 | amode == SImode | |
2780 | ? QImode : amode))); | |
2781 | }) | |
c00fc5cf | 2782 | |
cf2bfc7c | 2783 | ;; Since r186861, gcc.target/cris/peep2-andu2.c trigs this pattern, with which |
ff2ca1bc HPN |
2784 | ;; we fix up e.g.: |
2785 | ;; movu.b 254,$r9. | |
2786 | ;; and.d $r10,$r9 | |
2787 | ;; into: | |
2788 | ;; movu.b $r10,$r9 | |
2789 | ;; andq -2,$r9. | |
2790 | ;; Only do this for values fitting the quick immediate operand. | |
fb062a8b HPN |
2791 | (define_peephole2 ; andqu |
2792 | [(parallel | |
2793 | [(set (match_operand:SI 0 "register_operand") | |
2794 | (match_operand:SI 1 "const_int_operand")) | |
2795 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2796 | (parallel | |
2797 | [(set (match_dup 0) | |
2798 | (and:SI (match_dup 0) (match_operand:SI 2 "nonimmediate_operand"))) | |
2799 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
ff2ca1bc HPN |
2800 | ;; Since the size of the memory access will be made different here, |
2801 | ;; don't do this for a volatile access or a post-incremented address. | |
2802 | "satisfies_constraint_O (operands[1]) | |
2803 | && !side_effects_p (operands[2]) | |
2804 | && !reg_overlap_mentioned_p (operands[0], operands[2])" | |
fb062a8b HPN |
2805 | [(parallel |
2806 | [(set (match_dup 0) (match_dup 3)) | |
2807 | (clobber (reg:CC CRIS_CC0_REGNUM))]) | |
2808 | (parallel | |
2809 | [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 4))) | |
2810 | (clobber (reg:CC CRIS_CC0_REGNUM))])] | |
ff2ca1bc | 2811 | { |
da3243b2 | 2812 | machine_mode zmode = INTVAL (operands[1]) <= 255 ? QImode : HImode; |
ff2ca1bc HPN |
2813 | rtx op1 |
2814 | = (REG_S_P (operands[2]) | |
2815 | ? gen_rtx_REG (zmode, REGNO (operands[2])) | |
2816 | : adjust_address (operands[2], zmode, 0)); | |
2817 | operands[3] = gen_rtx_ZERO_EXTEND (SImode, op1); | |
2818 | operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]), QImode)); | |
2819 | }) | |
0b85d816 HPN |
2820 | \f |
2821 | ;; Local variables: | |
2822 | ;; mode:emacs-lisp | |
2823 | ;; comment-start: ";; " | |
2824 | ;; eval: (set-syntax-table (copy-sequence (syntax-table))) | |
2825 | ;; eval: (modify-syntax-entry ?[ "(]") | |
2826 | ;; eval: (modify-syntax-entry ?] ")[") | |
2827 | ;; eval: (modify-syntax-entry ?{ "(}") | |
2828 | ;; eval: (modify-syntax-entry ?} "){") | |
2829 | ;; eval: (setq indent-tabs-mode t) | |
2830 | ;; End: |