]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/cris/cris.md
Daily bump.
[thirdparty/gcc.git] / gcc / config / cris / cris.md
CommitLineData
0b85d816 1;; GCC machine description for CRIS cpu cores.
5624e564 2;; Copyright (C) 1998-2015 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.
26;;
27;; The function cris_notice_update_cc in cris.c handles condition code
28;; updates for most instructions, helped by the "cc" attribute.
29
30;; There are several instructions that are orthogonal in size, and seems
31;; they could be matched by a single pattern without a specified size
32;; for the operand that is orthogonal. However, this did not work on
839a4992 33;; gcc-2.7.2 (and probably not on gcc-2.8.1), relating to that when a
0b85d816
HPN
34;; constant is substituted into an operand, the actual mode must be
35;; deduced from the pattern. There is reasonable hope that that has been
d2f55c5c 36;; fixed, so FIXME: try again.
0b85d816
HPN
37
38;; You will notice that three-operand alternatives ("=r", "r", "!To")
39;; are marked with a "!" constraint modifier to avoid being reloaded
40;; into. This is because gcc would otherwise prefer to use the constant
41;; pool and its offsettable address instead of reloading to an
42;; ("=r", "0", "i") alternative. Also, the constant-pool support was not
43;; only suboptimal but also buggy in 2.7.2, ??? maybe only in 2.6.3.
44
45;; All insns that look like (set (...) (plus (...) (reg:SI 8)))
46;; get problems when reloading r8 (frame pointer) to r14 + offs (stack
47;; pointer). Thus the instructions that get into trouble have specific
48;; checks against matching frame_pointer_rtx.
49;; ??? But it should be re-checked for gcc > 2.7.2
50;; FIXME: This changed some time ago (from 2000-03-16) for gcc-2.9x.
51
52;; FIXME: When PIC, all [rX=rY+S] could be enabled to match
53;; [rX=gotless_symbol].
54;; The movsi for a gotless symbol could be split (post reload).
55\f
45d5d09c 56
21ed4444 57(define_c_enum ""
45d5d09c
HPN
58 [
59 ;; PLT reference from call expansion: operand 0 is the address,
60 ;; the mode is VOIDmode. Always wrapped in CONST.
61 ;; The value is relative to the GOT.
21ed4444 62 CRIS_UNSPEC_PLT_GOTREL
45d5d09c
HPN
63
64 ;; PLT reference from call expansion: operand 0 is the address,
65 ;; the mode is VOIDmode. Always wrapped in CONST.
66 ;; The value is relative to the PC. It's arch-dependent whether
67 ;; the offset counts from the start or the end of the current item.
21ed4444 68 CRIS_UNSPEC_PLT_PCREL
45d5d09c
HPN
69
70 ;; The address of the global offset table as a source operand.
21ed4444 71 CRIS_UNSPEC_GOT
45d5d09c
HPN
72
73 ;; The offset from the global offset table to the operand.
21ed4444 74 CRIS_UNSPEC_GOTREL
45d5d09c
HPN
75
76 ;; The PC-relative offset to the operand. It's arch-dependent whether
77 ;; the offset counts from the start or the end of the current item.
21ed4444 78 CRIS_UNSPEC_PCREL
45d5d09c
HPN
79
80 ;; The index into the global offset table of a symbol, while
81 ;; also generating a GOT entry for the symbol.
21ed4444 82 CRIS_UNSPEC_GOTREAD
45d5d09c
HPN
83
84 ;; Similar to CRIS_UNSPEC_GOTREAD, but also generating a PLT entry.
21ed4444 85 CRIS_UNSPEC_PLTGOTREAD
45d5d09c
HPN
86
87 ;; Condition for v32 casesi jump, since it needs to have if_then_else
88 ;; form with register as one branch and default label as other.
89 ;; Operand 0 is const_int 0.
21ed4444 90 CRIS_UNSPEC_CASESI
45d5d09c
HPN
91
92 ;; Stack frame deallocation barrier.
21ed4444 93 CRIS_UNSPEC_FRAME_DEALLOC
45d5d09c
HPN
94
95 ;; Swap all 32 bits of the operand; 31 <=> 0, 30 <=> 1...
21ed4444 96 CRIS_UNSPEC_SWAP_BITS
45d5d09c 97 ])
f60c7155
HPN
98
99;; Register numbers.
100(define_constants
101 [(CRIS_GOT_REGNUM 0)
102 (CRIS_STATIC_CHAIN_REGNUM 7)
103 (CRIS_FP_REGNUM 8)
104 (CRIS_SP_REGNUM 14)
45d5d09c 105 (CRIS_ACR_REGNUM 15)
f60c7155 106 (CRIS_SRP_REGNUM 16)
f9968e3e
HPN
107 (CRIS_MOF_REGNUM 17)
108 (CRIS_AP_REGNUM 18)
109 (CRIS_CC0_REGNUM 19)]
f60c7155
HPN
110)
111
0b85d816
HPN
112;; We need an attribute to define whether an instruction can be put in
113;; a branch-delay slot or not, and whether it has a delay slot.
114;;
115;; Branches and return instructions have a delay slot, and cannot
116;; themselves be put in a delay slot. This has changed *for short
117;; branches only* between architecture variants, but the possible win
118;; is presumed negligible compared to the added complexity of the machine
119;; description: one would have to add always-correct infrastructure to
120;; distinguish short branches.
121;;
122;; Whether an instruction can be put in a delay slot depends on the
123;; instruction (all short instructions except jumps and branches)
124;; and the addressing mode (must not be prefixed or referring to pc).
125;; In short, any "slottable" instruction must be 16 bit and not refer
126;; to pc, or alter it.
127;;
45d5d09c
HPN
128;; The possible values are "yes", "no", "has_slot", "has_return_slot"
129;; and "has_call_slot".
130;; Yes/no tells whether the insn is slottable or not. Has_call_slot means
131;; that the insn is a call insn, which for CRIS v32 has a delay-slot.
132;; Of special concern is that no RTX_FRAME_RELATED insn must go in that
133;; call delay slot, as it's located in the address *after* the call insn,
134;; and the unwind machinery doesn't know about delay slots.
135;; Has_slot means that the insn is a branch insn (which are
136;; not considered slottable since that is generally true). Having the
137;; seemingly illogical value "has_slot" means we do not have to add
138;; another attribute just to say that an insn has a delay-slot, since it
139;; also infers that it is not slottable. Better names for the attribute
140;; were found to be longer and not add readability to the machine
141;; description.
142;; Has_return_slot is similar, for the return insn.
0b85d816
HPN
143;;
144;; The default that is defined here for this attribute is "no", not
145;; slottable, not having a delay-slot, so there's no need to worry about
146;; it being wrong for non-branch and return instructions.
147;; The default could depend on the kind of insn and the addressing
148;; mode, but that would need more attributes and hairier, more error
149;; prone code.
150;;
23369bef
HPN
151;; There is an extra memory constraint, 'Q', which recognizes an indirect
152;; register. The constraints 'Q' and '>' together match all possible
153;; memory operands that are slottable.
0b85d816
HPN
154;; For other operands, you need to check if it has a valid "slottable"
155;; quick-immediate operand, where the particular signedness-variation
156;; may match the constraints 'I' or 'J'.), and include it in the
157;; constraint pattern for the slottable pattern. An alternative using
158;; only "r" constraints is most often slottable.
159
45d5d09c
HPN
160(define_attr "slottable" "no,yes,has_slot,has_return_slot,has_call_slot"
161 (const_string "no"))
0b85d816
HPN
162
163;; We also need attributes to sanely determine the condition code
164;; state. See cris_notice_update_cc for how this is used.
165
45d5d09c 166(define_attr "cc" "none,clobber,normal,noov32,rev" (const_string "normal"))
0b85d816 167
3a5afdfc
HPN
168;; At the moment, this attribute is just used to help bb-reorder do its
169;; work; the default 0 doesn't help it. Many insns have other lengths,
170;; though none are shorter.
171(define_attr "length" "" (const_int 2))
172
45d5d09c 173;; A branch has one delay-slot. The instruction in the
0b85d816
HPN
174;; delay-slot is always executed, independent of whether the branch is
175;; taken or not. Note that besides setting "slottable" to "has_slot",
176;; there also has to be a "%#" at the end of a "delayed" instruction
177;; output pattern (for "jump" this means "ba %l0%#"), so print_operand can
178;; catch it and print a "nop" if necessary. This method was stolen from
179;; sparc.md.
180
181(define_delay (eq_attr "slottable" "has_slot")
182 [(eq_attr "slottable" "yes") (nil) (nil)])
45d5d09c
HPN
183
184;; We can't put prologue insns in call-insn delay-slots when
185;; DWARF2 unwind info is emitted, because the unwinder matches the
186;; address after the insn. It must see the return address of a call at
187;; a position at least *one byte after* the insn, or it'll think that
188;; the insn hasn't been executed. If the insn is in a delay-slot of a
189;; call, it's just *exactly* after the insn.
190
191(define_delay (eq_attr "slottable" "has_call_slot")
192 [(and (eq_attr "slottable" "yes")
bf0b8cbe
RS
193 (ior (not (match_test "RTX_FRAME_RELATED_P (insn)"))
194 (not (match_test "flag_exceptions"))))
45d5d09c
HPN
195 (nil) (nil)])
196
197;; The insn in the return insn slot must not be the
198;; return-address-register restore. FIXME: Use has_slot and express
199;; as a parallel with a use of the return-address-register (currently
200;; only SRP). However, this requires an amount of fixing tests for
201;; naked RETURN in middle-end.
202(define_delay (eq_attr "slottable" "has_return_slot")
203 [(and (eq_attr "slottable" "yes")
bf0b8cbe 204 (not (match_test "dead_or_set_regno_p (insn, CRIS_SRP_REGNUM)")))
45d5d09c
HPN
205 (nil) (nil)])
206
0b85d816 207\f
22c3c091
HPN
208;; Iterator definitions.
209
210;; For the "usual" pattern size alternatives.
3abcb3a7
HPN
211(define_mode_iterator BWD [SI HI QI])
212(define_mode_iterator WD [SI HI])
213(define_mode_iterator BW [HI QI])
22c3c091
HPN
214(define_mode_attr S [(SI "HI") (HI "QI")])
215(define_mode_attr s [(SI "hi") (HI "qi")])
216(define_mode_attr m [(SI ".d") (HI ".w") (QI ".b")])
217(define_mode_attr mm [(SI ".w") (HI ".b")])
218(define_mode_attr nbitsm1 [(SI "31") (HI "15") (QI "7")])
219
220;; For the sign_extend+zero_extend variants.
3abcb3a7 221(define_code_iterator szext [sign_extend zero_extend])
22c3c091
HPN
222(define_code_attr u [(sign_extend "") (zero_extend "u")])
223(define_code_attr su [(sign_extend "s") (zero_extend "u")])
224
225;; For the shift variants.
3abcb3a7
HPN
226(define_code_iterator shift [ashiftrt lshiftrt ashift])
227(define_code_iterator shiftrt [ashiftrt lshiftrt])
22c3c091
HPN
228(define_code_attr shlr [(ashiftrt "ashr") (lshiftrt "lshr") (ashift "ashl")])
229(define_code_attr slr [(ashiftrt "asr") (lshiftrt "lsr") (ashift "lsl")])
230
3abcb3a7
HPN
231(define_code_iterator ncond [eq ne gtu ltu geu leu])
232(define_code_iterator ocond [gt le])
233(define_code_iterator rcond [lt ge])
22c3c091
HPN
234(define_code_attr CC [(eq "eq") (ne "ne") (gt "gt") (gtu "hi") (lt "lt")
235 (ltu "lo") (ge "ge") (geu "hs") (le "le") (leu "ls")])
236(define_code_attr rCC [(eq "ne") (ne "eq") (gt "le") (gtu "ls") (lt "ge")
237 (ltu "hs") (ge "lt") (geu "lo") (le "gt") (leu "hi")])
238(define_code_attr oCC [(lt "mi") (ge "pl")])
239(define_code_attr roCC [(lt "pl") (ge "mi")])
240
68a81332
HPN
241;; Operand and operator predicates.
242
243(include "predicates.md")
06cadf63 244(include "constraints.md")
68a81332 245\f
0b85d816
HPN
246;; Test insns.
247
0b85d816
HPN
248;; No test insns with side-effect on the mem addressing.
249;;
250;; See note on cmp-insns with side-effects (or lack of them)
251
252;; Normal named test patterns from SI on.
0b85d816 253
f90b7a5a 254(define_insn "*tstsi"
0b85d816 255 [(set (cc0)
f90b7a5a
PB
256 (compare (match_operand:SI 0 "nonimmediate_operand" "r,Q>,m")
257 (const_int 0)))]
0b85d816 258 ""
45d5d09c
HPN
259{
260 if (which_alternative == 0 && TARGET_V32)
261 return "cmpq 0,%0";
262 return "test.d %0";
263}
0b85d816
HPN
264 [(set_attr "slottable" "yes,yes,no")])
265
45d5d09c
HPN
266(define_insn "*tst<mode>_cmp"
267 [(set (cc0)
f90b7a5a
PB
268 (compare (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m")
269 (const_int 0)))]
45d5d09c
HPN
270 "cris_cc0_user_requires_cmp (insn)"
271 "@
272 cmp<m> 0,%0
273 test<m> %0
274 test<m> %0"
275 [(set_attr "slottable" "no,yes,no")])
276
277(define_insn "*tst<mode>_non_cmp"
278 [(set (cc0)
f90b7a5a
PB
279 (compare (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m")
280 (const_int 0)))]
45d5d09c
HPN
281 "!cris_cc0_user_requires_cmp (insn)"
282 "@
283 move<m> %0,%0
284 test<m> %0
285 test<m> %0"
286 [(set_attr "slottable" "yes,yes,no")
287 (set_attr "cc" "noov32,*,*")])
288
0b85d816
HPN
289;; It seems that the position of the sign-bit and the fact that 0.0 is
290;; all 0-bits would make "tstsf" a straight-forward implementation;
291;; either "test.d" it for positive/negative or "btstq 30,r" it for
292;; zeroness.
293;;
294;; FIXME: Do that some time; check next_cc0_user to determine if
295;; zero or negative is tested for.
296\f
297;; Compare insns.
298
299;; We could optimize the sizes of the immediate operands for various
300;; cases, but that is not worth it because of the very little usage of
301;; DImode for anything else but a structure/block-mode. Just do the
302;; obvious stuff for the straight-forward constraint letters.
303
45d5d09c 304(define_insn "*cmpdi_non_v32"
0b85d816 305 [(set (cc0)
f90b7a5a
PB
306 (compare (match_operand:DI 0 "nonimmediate_operand" "rm,r,r,r,r,r,r,o")
307 (match_operand:DI 1 "general_operand" "M,Kc,I,P,n,r,o,r")))]
45d5d09c 308 "!TARGET_V32"
0b85d816 309 "@
f90b7a5a 310 test.d %M0\;ax\;test.d %H0
0b85d816
HPN
311 cmpq %1,%M0\;ax\;cmpq 0,%H0
312 cmpq %1,%M0\;ax\;cmpq -1,%H0
313 cmp%e1.%z1 %1,%M0\;ax\;cmpq %H1,%H0
314 cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0
315 cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0
316 cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0
317 cmp.d %M0,%M1\;ax\;cmp.d %H0,%H1")
318
45d5d09c
HPN
319(define_insn "*cmpdi_v32"
320 [(set (cc0)
321 (compare (match_operand:DI 0 "register_operand" "r,r,r,r,r")
f49e46d8 322 (match_operand:DI 1 "nonmemory_operand" "Kc,I,P,n,r")))]
45d5d09c
HPN
323 "TARGET_V32"
324 "@
325 cmpq %1,%M0\;ax\;cmpq 0,%H0
326 cmpq %1,%M0\;ax\;cmpq -1,%H0
327 cmp%e1.%z1 %1,%M0\;ax\;cmpq %H1,%H0
328 cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0
329 cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0")
330
0b85d816
HPN
331;; Note that compare insns with side effect addressing mode (e.g.):
332;;
333;; cmp.S [rx=ry+i],rz;
334;; cmp.S [%3=%1+%2],%0
335;;
336;; are *not* usable for gcc since the reloader *does not accept*
337;; cc0-changing insns with side-effects other than setting the condition
338;; codes. The reason is that the reload stage *may* cause another insn to
339;; be output after the main instruction, in turn invalidating cc0 for the
340;; insn using the test. (This does not apply to the CRIS case, since a
341;; reload for output -- move to memory -- does not change the condition
342;; code. Unfortunately we have no way to describe that at the moment. I
343;; think code would improve being in the order of one percent faster.
344\f
345;; We have cmps and cmpu (compare reg w. sign/zero extended mem).
346;; These are mostly useful for compares in SImode, using 8 or 16-bit
347;; constants, but sometimes gcc will find its way to use it for other
348;; (memory) operands. Avoid side-effect patterns, though (see above).
0b85d816 349
22c3c091 350(define_insn "*cmp_ext<mode>"
0b85d816
HPN
351 [(set (cc0)
352 (compare
353 (match_operand:SI 0 "register_operand" "r,r")
354 (match_operator:SI 2 "cris_extend_operator"
22c3c091 355 [(match_operand:BW 1 "memory_operand" "Q>,m")])))]
0b85d816 356 ""
22c3c091 357 "cmp%e2<m> %1,%0"
0b85d816
HPN
358 [(set_attr "slottable" "yes,no")])
359
360;; Swap operands; it seems the canonical look (if any) is not enforced.
361;;
362;; FIXME: Investigate that.
0b85d816 363
22c3c091 364(define_insn "*cmp_swapext<mode>"
0b85d816
HPN
365 [(set (cc0)
366 (compare
367 (match_operator:SI 2 "cris_extend_operator"
22c3c091 368 [(match_operand:BW 0 "memory_operand" "Q>,m")])
0b85d816
HPN
369 (match_operand:SI 1 "register_operand" "r,r")))]
370 ""
45d5d09c
HPN
371 "cmp%e2<m> %0,%1"
372 [(set_attr "slottable" "yes,no")
373 (set_attr "cc" "rev")])
0b85d816 374\f
45d5d09c 375;; The "normal" compare patterns, from SI on. Special-cases with zero
f90b7a5a 376;; are covered above.
0b85d816 377
f90b7a5a 378(define_insn "*cmpsi"
0b85d816
HPN
379 [(set (cc0)
380 (compare
45d5d09c
HPN
381 (match_operand:SI 0 "nonimmediate_operand" "r,r,r, Q>,r,r,m")
382 (match_operand:SI 1 "general_operand" "I,r,Q>,r, P,g,r")))]
0b85d816
HPN
383 ""
384 "@
385 cmpq %1,%0
386 cmp.d %1,%0
387 cmp.d %1,%0
0b85d816
HPN
388 cmp.d %0,%1
389 cmp%e1.%z1 %1,%0
390 cmp.d %1,%0
0b85d816 391 cmp.d %0,%1"
45d5d09c
HPN
392 [(set_attr "slottable" "yes,yes,yes,yes,no,no,no")
393 (set_attr "cc" "normal,normal,normal,rev,normal,normal,rev")])
0b85d816 394
f90b7a5a 395(define_insn "*cmp<mode>"
0b85d816 396 [(set (cc0)
45d5d09c
HPN
397 (compare (match_operand:BW 0 "nonimmediate_operand" "r,r, Q>,r,m")
398 (match_operand:BW 1 "general_operand" "r,Q>,r, g,r")))]
0b85d816
HPN
399 ""
400 "@
22c3c091
HPN
401 cmp<m> %1,%0
402 cmp<m> %1,%0
22c3c091
HPN
403 cmp<m> %0,%1
404 cmp<m> %1,%0
22c3c091 405 cmp<m> %0,%1"
45d5d09c
HPN
406 [(set_attr "slottable" "yes,yes,yes,no,no")
407 (set_attr "cc" "normal,normal,rev,normal,rev")])
0b85d816
HPN
408\f
409;; Pattern matching the BTST insn.
410;; It is useful for "if (i & val)" constructs, where val is an exact
411;; power of 2, or if val + 1 is a power of two, where we check for a bunch
412;; of zeros starting at bit 0).
413
414;; SImode. This mode is the only one needed, since gcc automatically
109b748d 415;; extends subregs for lower-size modes. FIXME: Add testcase.
0b85d816
HPN
416(define_insn "*btst"
417 [(set (cc0)
f90b7a5a
PB
418 (compare
419 (zero_extract:SI
420 (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp")
421 (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n")
422 (match_operand:SI 2 "nonmemory_operand" "M, M,Kc,n,r, r,r"))
423 (const_int 0)))]
0b85d816 424 ;; Either it is a single bit, or consecutive ones starting at 0.
45d5d09c 425 ;; The btst ones depend on stuff in NOTICE_UPDATE_CC.
991c42ac 426 "CONST_INT_P (operands[1])
0b85d816
HPN
427 && (operands[1] == const1_rtx || operands[2] == const0_rtx)
428 && (REG_S_P (operands[0])
429 || (operands[1] == const1_rtx
430 && REG_S_P (operands[2])
991c42ac 431 && CONST_INT_P (operands[0])
45d5d09c
HPN
432 && exact_log2 (INTVAL (operands[0])) >= 0))
433 && !TARGET_CCINIT"
0b85d816 434
45d5d09c 435;; The next-to-last "&&" condition above should be caught by some kind of
0b85d816
HPN
436;; canonicalization in gcc, but we can easily help with it here.
437;; It results from expressions of the type
438;; "power_of_2_value & (1 << y)".
439;;
440;; Since there may be codes with tests in on bits (in constant position)
441;; beyond the size of a word, handle that by assuming those bits are 0.
442;; GCC should handle that, but it's a matter of easily-added belts while
443;; having suspenders.
444
445 "@
446 btstq (%1-1),%0
45d5d09c 447 cmpq 0,%0
0b85d816
HPN
448 btstq %2,%0
449 clearf nz
450 btst %2,%0
451 clearf nz
452 cmpq %p0,%2"
45d5d09c
HPN
453 [(set_attr "slottable" "yes")
454 (set_attr "cc" "noov32")])
0b85d816
HPN
455\f
456;; Move insns.
457
458;; The whole mandatory movdi family is here; expander, "anonymous"
459;; recognizer and splitter. We're forced to have a movdi pattern,
460;; although GCC should be able to split it up itself. Normally it can,
461;; but if other insns have DI operands (as is the case here), reload
462;; must be able to generate or match a movdi. many testcases fail at
463;; -O3 or -fssa if we don't have this. FIXME: Fix GCC... See
464;; <URL:http://gcc.gnu.org/ml/gcc-patches/2000-04/msg00104.html>.
465;; However, a patch from Richard Kenner (similar to the cause of
466;; discussion at the URL above), indicates otherwise. See
467;; <URL:http://gcc.gnu.org/ml/gcc-patches/2000-04/msg00554.html>.
468;; The truth has IMO is not been decided yet, so check from time to
469;; time by disabling the movdi patterns.
470
22c3c091
HPN
471;; To appease testcase gcc.c-torture/execute/920501-2.c (and others) at
472;; -O0, we need a movdi as a temporary measure. Here's how things fail:
473;; A cmpdi RTX needs reloading (global):
474;; (insn 185 326 186 (set (cc0)
475;; (compare (mem/f:DI (reg/v:SI 22) 0)
476;; (const_int 1 [0x1]))) 4 {cmpdi} (nil)
477;; (nil))
478;; Now, reg 22 is reloaded for input address, and the mem is also moved
479;; out of the instruction (into a register), since one of the operands
480;; must be a register. Reg 22 is reloaded (into reg 10), and the mem is
481;; moved out and synthesized in SImode parts (reg 9, reg 10 - should be ok
482;; wrt. overlap). The bad things happen with the synthesis in
483;; emit_move_insn_1; the location where to substitute reg 10 is lost into
484;; two new RTX:es, both still having reg 22. Later on, the left-over reg
485;; 22 is recognized to have an equivalent in memory which is substituted
486;; straight in, and we end up with an unrecognizable insn:
487;; (insn 325 324 326 (set (reg:SI 9 r9)
488;; (mem/f:SI (mem:SI (plus:SI (reg:SI 8 r8)
489;; (const_int -84 [0xffffffac])) 0) 0)) -1 (nil)
490;; (nil))
491;; which is the first part of the reloaded synthesized "movdi".
492;; The right thing would be to add equivalent replacement locations for
493;; insn with pseudos that need more reloading. The question is where.
494
0b85d816
HPN
495(define_expand "movdi"
496 [(set (match_operand:DI 0 "nonimmediate_operand" "")
497 (match_operand:DI 1 "general_operand" ""))]
498 ""
0b85d816 499{
45d5d09c
HPN
500 if (MEM_P (operands[0])
501 && operands[1] != const0_rtx
502 && (!TARGET_V32 || (!REG_P (operands[1]) && can_create_pseudo_p ())))
0b85d816
HPN
503 operands[1] = copy_to_mode_reg (DImode, operands[1]);
504
505 /* Some other ports (as of 2001-09-10 for example mcore and romp) also
506 prefer to split up constants early, like this. The testcase in
507 gcc.c-torture/execute/961213-1.c shows that CSE2 gets confused by the
508 resulting subreg sets when using the construct from mcore (as of FSF
049746c2 509 CVS, version -r 1.5), and it believes that the high part (the last one
d70dcf29 510 emitted) is the final value. */
991c42ac 511 if ((CONST_INT_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE)
0b85d816
HPN
512 && ! reload_completed
513 && ! reload_in_progress)
514 {
515 rtx insns;
516 rtx op0 = operands[0];
517 rtx op1 = operands[1];
518
519 start_sequence ();
520 emit_move_insn (operand_subword (op0, 0, 1, DImode),
521 operand_subword (op1, 0, 1, DImode));
522 emit_move_insn (operand_subword (op0, 1, 1, DImode),
523 operand_subword (op1, 1, 1, DImode));
524 insns = get_insns ();
525 end_sequence ();
526
d70dcf29 527 emit_insn (insns);
0b85d816
HPN
528 DONE;
529 }
22c3c091 530})
0b85d816 531
45d5d09c 532(define_insn_and_split "*movdi_insn_non_v32"
477c433d 533 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rx,m")
45d5d09c
HPN
534 (match_operand:DI 1 "general_operand" "rx,g,rxM"))]
535 "(register_operand (operands[0], DImode)
536 || register_operand (operands[1], DImode)
537 || operands[1] == const0_rtx)
538 && !TARGET_V32"
539 "#"
540 "&& reload_completed"
541 [(match_dup 2)]
542 "operands[2] = cris_split_movdx (operands);")
0b85d816 543
45d5d09c
HPN
544;; Overlapping (but non-identical) source memory address and destination
545;; register would be a compiler bug, so we don't have to specify that.
546(define_insn "*movdi_v32"
547 [(set
548 (match_operand:DI 0 "nonimmediate_operand" "=r,rx,&r,>, m,r,x,m")
549 (match_operand:DI 1 "general_operand" "rxi,r>,m, rx,r,m,m,x"))]
550 "TARGET_V32"
551{
552 switch (which_alternative)
553 {
554 /* FIXME: 1) Use autoincrement where possible. 2) Have peephole2,
555 particularly for cases where the address register is dead. */
556 case 5:
557 if (REGNO (operands[0]) == REGNO (XEXP (operands[1], 0)))
558 return "addq 4,%L1\;move.d %1,%H0\;subq 4,%L1\;move.d %1,%M0";
559 gcc_assert (REGNO (operands[0]) + 1 == REGNO (XEXP (operands[1], 0)));
560 return "move.d [%L1+],%M0\;move.d [%L1],%H0";
561 case 2:
562 /* We could do away with the addq if we knew the address-register
563 isn't ACR. If we knew the address-register is dead, we could do
564 away with the subq too. */
565 return "move.d [%L1],%M0\;addq 4,%L1\;move.d [%L1],%H0\;subq 4,%L1";
566 case 4:
567 return "move.d %M1,[%L0]\;addq 4,%L0\;move.d %H1,[%L0]\;subq 4,%L0";
568 case 6:
569 return "move [%L1],%M0\;addq 4,%L1\;move [%L1],%H0\;subq 4,%L1";
570 case 7:
571 return "move %M1,[%L0]\;addq 4,%L0\;move %H1,[%L0]\;subq 4,%L0";
572
573 default:
574 return "#";
575 }
576}
577 ;; The non-split cases clobber cc0 because of their adds and subs.
578 ;; Beware that NOTICE_UPDATE_CC is called before the forced split happens.
579 [(set_attr "cc" "*,*,clobber,*,clobber,clobber,*,*")])
580
581;; Much like "*movdi_insn_non_v32". Overlapping registers and constants
582;; is handled so much better in cris_split_movdx.
0b85d816
HPN
583(define_split
584 [(set (match_operand:DI 0 "nonimmediate_operand" "")
585 (match_operand:DI 1 "general_operand" ""))]
45d5d09c
HPN
586 "TARGET_V32
587 && reload_completed
588 && (!MEM_P (operands[0]) || !REG_P (XEXP (operands[0], 0)))
589 && (!MEM_P (operands[1]) || !REG_P (XEXP (operands[1], 0)))"
0b85d816
HPN
590 [(match_dup 2)]
591 "operands[2] = cris_split_movdx (operands);")
592\f
593;; Side-effect patterns for move.S1 [rx=ry+rx.S2],rw
594;; and move.S1 [rx=ry+i],rz
595;; Then movs.S1 and movu.S1 for both modes.
596;;
597;; move.S1 [rx=ry+rz.S],rw avoiding when rx is ry, or rw is rx
598;; FIXME: These could have anonymous mode for operand 0.
45d5d09c 599;; FIXME: Special registers' alternatives too.
0b85d816 600
22c3c091
HPN
601(define_insn "*mov_side<mode>_biap"
602 [(set (match_operand:BW 0 "register_operand" "=r,r")
603 (mem:BW (plus:SI
0b85d816
HPN
604 (mult:SI (match_operand:SI 1 "register_operand" "r,r")
605 (match_operand:SI 2 "const_int_operand" "n,n"))
606 (match_operand:SI 3 "register_operand" "r,r"))))
607 (set (match_operand:SI 4 "register_operand" "=*3,r")
608 (plus:SI (mult:SI (match_dup 1)
609 (match_dup 2))
610 (match_dup 3)))]
611 "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
612 "@
613 #
22c3c091 614 move<m> [%4=%3+%1%T2],%0")
0b85d816 615
8ad46d34 616(define_insn "*mov_sidesisf_biap"
477c433d 617 [(set (match_operand 0 "register_operand" "=r,r,x,x")
8ad46d34 618 (mem (plus:SI
477c433d
HPN
619 (mult:SI (match_operand:SI 1 "register_operand" "r,r,r,r")
620 (match_operand:SI 2 "const_int_operand" "n,n,n,n"))
621 (match_operand:SI 3 "register_operand" "r,r,r,r"))))
622 (set (match_operand:SI 4 "register_operand" "=*3,r,*3,r")
0b85d816
HPN
623 (plus:SI (mult:SI (match_dup 1)
624 (match_dup 2))
625 (match_dup 3)))]
8ad46d34
HPN
626 "GET_MODE_SIZE (GET_MODE (operands[0])) == UNITS_PER_WORD
627 && cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
0b85d816
HPN
628 "@
629 #
477c433d
HPN
630 move.%s0 [%4=%3+%1%T2],%0
631 #
632 move [%4=%3+%1%T2],%0")
0b85d816
HPN
633\f
634;; move.S1 [rx=ry+i],rz
635;; avoiding move.S1 [ry=ry+i],rz
636;; and move.S1 [rz=ry+i],rz
637;; Note that "i" is allowed to be a register.
0b85d816 638
22c3c091 639(define_insn "*mov_side<mode>"
1165f377 640 [(set (match_operand:BW 0 "register_operand" "=r,r,r,r,r")
22c3c091 641 (mem:BW
1165f377
HPN
642 (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,R,R")
643 (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r,r"))))
644 (set (match_operand:SI 3 "register_operand" "=*1,r,r,*2,r")
0b85d816
HPN
645 (plus:SI (match_dup 1)
646 (match_dup 2)))]
647 "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
0b85d816 648{
1165f377 649 if ((which_alternative == 0 || which_alternative == 3)
991c42ac 650 && (!CONST_INT_P (operands[2])
0b85d816
HPN
651 || INTVAL (operands[2]) > 127
652 || INTVAL (operands[2]) < -128
06cadf63
AS
653 || satisfies_constraint_N (operands[2])
654 || satisfies_constraint_J (operands[2])))
22c3c091 655 return "#";
1165f377
HPN
656 if (which_alternative == 4)
657 return "move<m> [%3=%2%S1],%0";
22c3c091
HPN
658 return "move<m> [%3=%1%S2],%0";
659})
0b85d816 660
8ad46d34 661(define_insn "*mov_sidesisf"
1165f377 662 [(set (match_operand 0 "register_operand" "=r,r,r,x,x,x,r,r,x,x")
8ad46d34 663 (mem
477c433d 664 (plus:SI
1165f377
HPN
665 (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,r,r,r,R,R,R,R")
666 (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r>Rn,r,>Rn,r,r,r,r"))))
667 (set (match_operand:SI 3 "register_operand" "=*1,r,r,*1,r,r,*2,r,*2,r")
0b85d816
HPN
668 (plus:SI (match_dup 1)
669 (match_dup 2)))]
8ad46d34
HPN
670 "GET_MODE_SIZE (GET_MODE (operands[0])) == UNITS_PER_WORD
671 && cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
0b85d816 672{
1165f377
HPN
673 if ((which_alternative == 0
674 || which_alternative == 3
675 || which_alternative == 6
676 || which_alternative == 8)
991c42ac 677 && (!CONST_INT_P (operands[2])
0b85d816
HPN
678 || INTVAL (operands[2]) > 127
679 || INTVAL (operands[2]) < -128
06cadf63
AS
680 || satisfies_constraint_N (operands[2])
681 || satisfies_constraint_J (operands[2])))
477c433d
HPN
682 return "#";
683 if (which_alternative < 3)
684 return "move.%s0 [%3=%1%S2],%0";
1165f377
HPN
685 if (which_alternative == 7)
686 return "move.%s0 [%3=%2%S1],%0";
687 if (which_alternative == 9)
688 return "move [%3=%2%S1],%0";
477c433d
HPN
689 return "move [%3=%1%S2],%0";
690})
0b85d816
HPN
691\f
692;; Other way around; move to memory.
693
049746c2
HPN
694;; Note that the condition (which for side-effect patterns is usually a
695;; call to cris_side_effect_mode_ok), isn't consulted for register
696;; allocation preferences -- constraints is the method for that. The
697;; drawback is that we can't exclude register allocation to cause
698;; "move.s rw,[rx=ry+rz.S]" when rw==rx without also excluding rx==ry or
699;; rx==rz if we use an earlyclobber modifier for the constraint for rx.
700;; Instead of that, we recognize and split the cases where dangerous
701;; register combinations are spotted: where a register is set in the
702;; side-effect, and used in the main insn. We don't handle the case where
703;; the set in the main insn overlaps the set in the side-effect; that case
704;; must be handled in gcc. We handle just the case where the set in the
705;; side-effect overlaps the input operand of the main insn (i.e. just
706;; moves to memory).
0b85d816
HPN
707
708;;
049746c2 709;; move.s rz,[ry=rx+rw.S]
0b85d816 710
22c3c091
HPN
711(define_insn "*mov_side<mode>_biap_mem"
712 [(set (mem:BW (plus:SI
0b85d816
HPN
713 (mult:SI (match_operand:SI 0 "register_operand" "r,r,r")
714 (match_operand:SI 1 "const_int_operand" "n,n,n"))
715 (match_operand:SI 2 "register_operand" "r,r,r")))
22c3c091 716 (match_operand:BW 3 "register_operand" "r,r,r"))
049746c2 717 (set (match_operand:SI 4 "register_operand" "=*2,!3,r")
0b85d816
HPN
718 (plus:SI (mult:SI (match_dup 0)
719 (match_dup 1))
720 (match_dup 2)))]
721 "cris_side_effect_mode_ok (MULT, operands, 4, 2, 0, 1, 3)"
722 "@
723 #
724 #
22c3c091 725 move<m> %3,[%4=%2+%0%T1]")
0b85d816 726
8ad46d34
HPN
727(define_insn "*mov_sidesisf_biap_mem"
728 [(set (mem (plus:SI
477c433d
HPN
729 (mult:SI (match_operand:SI 0 "register_operand" "r,r,r,r,r,r")
730 (match_operand:SI 1 "const_int_operand" "n,n,n,n,n,n"))
731 (match_operand:SI 2 "register_operand" "r,r,r,r,r,r")))
732 (match_operand 3 "register_operand" "r,r,r,x,x,x"))
733 (set (match_operand:SI 4 "register_operand" "=*2,!3,r,*2,!3,r")
0b85d816
HPN
734 (plus:SI (mult:SI (match_dup 0)
735 (match_dup 1))
736 (match_dup 2)))]
8ad46d34
HPN
737 "GET_MODE_SIZE (GET_MODE (operands[3])) == UNITS_PER_WORD
738 && cris_side_effect_mode_ok (MULT, operands, 4, 2, 0, 1, 3)"
0b85d816
HPN
739 "@
740 #
741 #
477c433d
HPN
742 move.%s3 %3,[%4=%2+%0%T1]
743 #
744 #
745 move %3,[%4=%2+%0%T1]")
0b85d816 746
049746c2
HPN
747;; Split for the case above where we're out of luck with register
748;; allocation (again, the condition isn't checked for that), and we end up
749;; with the set in the side-effect getting the same register as the input
750;; register.
0b85d816
HPN
751
752(define_split
753 [(parallel
dbb138ce
HPN
754 [(set (match_operator
755 6 "cris_mem_op"
756 [(plus:SI
757 (mult:SI (match_operand:SI 0 "register_operand" "")
758 (match_operand:SI 1 "const_int_operand" ""))
759 (match_operand:SI 2 "register_operand" ""))])
0b85d816 760 (match_operand 3 "register_operand" ""))
a13a866e 761 (set (match_operand:SI 4 "cris_nonsp_register_operand" "")
0b85d816
HPN
762 (plus:SI (mult:SI (match_dup 0)
763 (match_dup 1))
764 (match_dup 2)))])]
765 "reload_completed && reg_overlap_mentioned_p (operands[4], operands[3])"
766 [(set (match_dup 5) (match_dup 3))
767 (set (match_dup 4) (match_dup 2))
768 (set (match_dup 4)
769 (plus:SI (mult:SI (match_dup 0)
770 (match_dup 1))
771 (match_dup 4)))]
772 "operands[5]
dbb138ce
HPN
773 = replace_equiv_address (operands[6],
774 gen_rtx_PLUS (SImode,
775 gen_rtx_MULT (SImode,
776 operands[0],
777 operands[1]),
778 operands[2]));")
0b85d816
HPN
779\f
780;; move.s rx,[ry=rz+i]
781;; FIXME: These could have anonymous mode for operand 2.
782
783;; QImode
784
22c3c091
HPN
785(define_insn "*mov_side<mode>_mem"
786 [(set (mem:BW
1165f377
HPN
787 (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r,r,R,R,R")
788 (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r>Rn,r,>Rn,r,r,r")))
789 (match_operand:BW 2 "register_operand" "r,r,r,r,r,r,r"))
790 (set (match_operand:SI 3 "register_operand" "=*0,!*2,r,r,*1,!*2,r")
0b85d816
HPN
791 (plus:SI (match_dup 0)
792 (match_dup 1)))]
793 "cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)"
0b85d816 794{
1165f377 795 if ((which_alternative == 0 || which_alternative == 4)
991c42ac 796 && (!CONST_INT_P (operands[1])
0b85d816
HPN
797 || INTVAL (operands[1]) > 127
798 || INTVAL (operands[1]) < -128
06cadf63
AS
799 || satisfies_constraint_N (operands[1])
800 || satisfies_constraint_J (operands[1])))
22c3c091 801 return "#";
1165f377 802 if (which_alternative == 1 || which_alternative == 5)
22c3c091 803 return "#";
1165f377
HPN
804 if (which_alternative == 6)
805 return "move.%s2 %2,[%3=%1%S0]";
22c3c091
HPN
806 return "move<m> %2,[%3=%0%S1]";
807})
0b85d816
HPN
808
809;; SImode
810
8ad46d34
HPN
811(define_insn "*mov_sidesisf_mem"
812 [(set (mem
477c433d
HPN
813 (plus:SI
814 (match_operand:SI
4a60d778
HPN
815 0 "cris_bdap_operand"
816 "%r, r, r,r, r, r,r, R,R, R,R, R")
477c433d 817 (match_operand:SI
4a60d778
HPN
818 1 "cris_bdap_operand"
819 "r>Rn,r>Rn,r,>Rn,r>Rn,r,>Rn,r,r, r,r, r")))
820 (match_operand 2 "register_operand"
821 "r, r, r,r, x, x,x, r,r, r,x, x"))
822 (set (match_operand:SI 3 "register_operand"
823 "=*0,!2, r,r, *0, r,r, *1,!*2,r,*1,r")
0b85d816
HPN
824 (plus:SI (match_dup 0)
825 (match_dup 1)))]
8ad46d34
HPN
826 "GET_MODE_SIZE (GET_MODE (operands[2])) == UNITS_PER_WORD
827 && cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)"
0b85d816 828{
477c433d 829 if ((which_alternative == 0 || which_alternative == 4)
991c42ac 830 && (!CONST_INT_P (operands[1])
0b85d816
HPN
831 || INTVAL (operands[1]) > 127
832 || INTVAL (operands[1]) < -128
06cadf63
AS
833 || satisfies_constraint_N (operands[1])
834 || satisfies_constraint_J (operands[1])))
477c433d 835 return "#";
1165f377 836 if (which_alternative == 1
4a60d778 837 || which_alternative == 7
1165f377 838 || which_alternative == 8
4a60d778 839 || which_alternative == 10)
477c433d
HPN
840 return "#";
841 if (which_alternative < 4)
842 return "move.%s2 %2,[%3=%0%S1]";
4a60d778 843 if (which_alternative == 9)
1165f377 844 return "move.%s2 %2,[%3=%1%S0]";
4a60d778 845 if (which_alternative == 11)
1165f377 846 return "move %2,[%3=%1%S0]";
477c433d
HPN
847 return "move %2,[%3=%0%S1]";
848})
0b85d816
HPN
849
850;; Like the biap case, a split where the set in the side-effect gets the
049746c2
HPN
851;; same register as the input register to the main insn, since the
852;; condition isn't checked at register allocation.
0b85d816
HPN
853
854(define_split
855 [(parallel
dbb138ce
HPN
856 [(set (match_operator
857 4 "cris_mem_op"
858 [(plus:SI
859 (match_operand:SI 0 "cris_bdap_operand" "")
860 (match_operand:SI 1 "cris_bdap_operand" ""))])
049746c2 861 (match_operand 2 "register_operand" ""))
a13a866e 862 (set (match_operand:SI 3 "cris_nonsp_register_operand" "")
0b85d816
HPN
863 (plus:SI (match_dup 0) (match_dup 1)))])]
864 "reload_completed && reg_overlap_mentioned_p (operands[3], operands[2])"
865 [(set (match_dup 4) (match_dup 2))
866 (set (match_dup 3) (match_dup 0))
867 (set (match_dup 3) (plus:SI (match_dup 3) (match_dup 1)))]
dbb138ce 868 "")
0b85d816
HPN
869\f
870;; Clear memory side-effect patterns. It is hard to get to the mode if
871;; the MEM was anonymous, so there will be one for each mode.
872
22c3c091 873;; clear.[bwd] [ry=rx+rw.s2]
0b85d816 874
22c3c091
HPN
875(define_insn "*clear_side<mode>_biap"
876 [(set (mem:BWD (plus:SI
877 (mult:SI (match_operand:SI 0 "register_operand" "r,r")
878 (match_operand:SI 1 "const_int_operand" "n,n"))
879 (match_operand:SI 2 "register_operand" "r,r")))
0b85d816
HPN
880 (const_int 0))
881 (set (match_operand:SI 3 "register_operand" "=*2,r")
882 (plus:SI (mult:SI (match_dup 0)
883 (match_dup 1))
884 (match_dup 2)))]
885 "cris_side_effect_mode_ok (MULT, operands, 3, 2, 0, 1, -1)"
886 "@
887 #
22c3c091 888 clear<m> [%3=%2+%0%T1]")
0b85d816 889
22c3c091 890;; clear.[bwd] [ry=rz+i]
0b85d816 891
22c3c091
HPN
892(define_insn "*clear_side<mode>"
893 [(set (mem:BWD
1165f377
HPN
894 (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r,R,R")
895 (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))
0b85d816 896 (const_int 0))
1165f377 897 (set (match_operand:SI 2 "register_operand" "=*0,r,r,*1,r")
0b85d816
HPN
898 (plus:SI (match_dup 0)
899 (match_dup 1)))]
900 "cris_side_effect_mode_ok (PLUS, operands, 2, 0, 1, -1, -1)"
0b85d816 901{
1165f377 902 if ((which_alternative == 0 || which_alternative == 3)
991c42ac 903 && (!CONST_INT_P (operands[1])
0b85d816
HPN
904 || INTVAL (operands[1]) > 127
905 || INTVAL (operands[1]) < -128
06cadf63
AS
906 || satisfies_constraint_N (operands[1])
907 || satisfies_constraint_J (operands[1])))
22c3c091 908 return "#";
1165f377
HPN
909 if (which_alternative == 4)
910 return "clear<m> [%2=%1%S0]";
22c3c091
HPN
911 return "clear<m> [%2=%0%S1]";
912})
0b85d816 913\f
0b85d816
HPN
914;; Normal move patterns from SI on.
915
916(define_expand "movsi"
917 [(set
918 (match_operand:SI 0 "nonimmediate_operand" "")
919 (match_operand:SI 1 "cris_general_operand_or_symbol" ""))]
920 ""
0b85d816 921{
ab4e53fe
HPN
922 enum cris_symbol_type t;
923
0b85d816
HPN
924 /* If the output goes to a MEM, make sure we have zero or a register as
925 input. */
991c42ac 926 if (MEM_P (operands[0])
0b85d816
HPN
927 && ! REG_S_P (operands[1])
928 && operands[1] != const0_rtx
3a0e695a 929 && can_create_pseudo_p ())
0b85d816
HPN
930 operands[1] = force_reg (SImode, operands[1]);
931
932 /* If we're generating PIC and have an incoming symbol, validize it to a
933 general operand or something that will match a special pattern.
934
935 FIXME: Do we *have* to recognize anything that would normally be a
936 valid symbol? Can we exclude global PIC addresses with an added
937 offset? */
c00fc5cf 938 if (flag_pic
ab4e53fe 939 && CONSTANT_P (operands[1])
45d5d09c 940 && !cris_valid_pic_const (operands[1], false))
c00fc5cf 941 {
ab4e53fe 942 t = cris_symbol_type_of (operands[1]);
c00fc5cf 943
ab4e53fe 944 gcc_assert (t != cris_no_symbol && t != cris_offsettable_symbol);
c00fc5cf
HPN
945
946 if (! REG_S_P (operands[0]))
947 {
948 /* We must have a register as destination for what we're about to
949 do, and for the patterns we generate. */
b3a13419 950 CRIS_ASSERT (can_create_pseudo_p ());
c00fc5cf
HPN
951 operands[1] = force_reg (SImode, operands[1]);
952 }
953 else
954 {
955 /* FIXME: add a REG_EQUAL (or is it REG_EQUIV) note to the
956 destination register for the symbol. It might not be
957 worth it. Measure. */
e3b5732b 958 crtl->uses_pic_offset_table = 1;
45d5d09c 959 if (t == cris_rel_symbol)
c00fc5cf
HPN
960 {
961 /* Change a "move.d sym(+offs),rN" into (allocate register rM)
45d5d09c
HPN
962 for pre-v32:
963 "move.d (const (plus (unspec [sym]
964 CRIS_UNSPEC_GOTREL) offs)),rM" "add.d rPIC,rM,rN"
965 and for v32:
c00fc5cf 966 "move.d (const (plus (unspec [sym]
45d5d09c 967 CRIS_UNSPEC_PCREL) offs)),rN". */
c00fc5cf
HPN
968 rtx tem, rm, rn = operands[0];
969 rtx sym = GET_CODE (operands[1]) != CONST
970 ? operands[1] : get_related_value (operands[1]);
971 HOST_WIDE_INT offs = get_integer_term (operands[1]);
972
b3a13419 973 gcc_assert (can_create_pseudo_p ());
45d5d09c
HPN
974
975 if (TARGET_V32)
976 {
977 tem = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym),
978 CRIS_UNSPEC_PCREL);
979 if (offs != 0)
0a81f074 980 tem = plus_constant (Pmode, tem, offs);
45d5d09c
HPN
981 rm = rn;
982 emit_move_insn (rm, gen_rtx_CONST (Pmode, tem));
983 }
984 else
985 {
986 /* We still uses GOT-relative addressing for
987 pre-v32. */
e3b5732b 988 crtl->uses_pic_offset_table = 1;
45d5d09c
HPN
989 tem = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym),
990 CRIS_UNSPEC_GOTREL);
991 if (offs != 0)
0a81f074 992 tem = plus_constant (Pmode, tem, offs);
45d5d09c
HPN
993 rm = gen_reg_rtx (Pmode);
994 emit_move_insn (rm, gen_rtx_CONST (Pmode, tem));
995 if (expand_binop (Pmode, add_optab, rm, pic_offset_table_rtx,
996 rn, 0, OPTAB_LIB_WIDEN) != rn)
997 internal_error ("expand_binop failed in movsi gotrel");
998 }
c00fc5cf
HPN
999 DONE;
1000 }
1001 else if (t == cris_got_symbol)
1002 {
1003 /* Change a "move.d sym,rN" into (allocate register rM, rO)
1004 "move.d (const (unspec [sym] CRIS_UNSPEC_GOTREAD)),rM"
1005 "add.d rPIC,rM,rO", "move.d [rO],rN" with
1006 the memory access marked as read-only. */
1007 rtx tem, mem, rm, ro, rn = operands[0];
b3a13419 1008 gcc_assert (can_create_pseudo_p ());
c00fc5cf
HPN
1009 tem = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]),
1010 CRIS_UNSPEC_GOTREAD);
1011 rm = gen_reg_rtx (Pmode);
1012 emit_move_insn (rm, gen_rtx_CONST (Pmode, tem));
1013 ro = gen_reg_rtx (Pmode);
1014 if (expand_binop (Pmode, add_optab, rm, pic_offset_table_rtx,
1015 ro, 0, OPTAB_LIB_WIDEN) != ro)
1016 internal_error ("expand_binop failed in movsi got");
1017 mem = gen_rtx_MEM (Pmode, ro);
1018
1019 /* This MEM doesn't alias anything. Whether it
1020 aliases other same symbols is unimportant. */
1021 set_mem_alias_set (mem, new_alias_set ());
1022 MEM_NOTRAP_P (mem) = 1;
45d5d09c
HPN
1023
1024 /* We can set the GOT memory read of a non-called symbol
1025 to readonly, but not that of a call symbol, as those
1026 are subject to lazy evaluation and usually have the value
1027 changed from the first call to the second (but
1028 constant thereafter). */
c00fc5cf
HPN
1029 MEM_READONLY_P (mem) = 1;
1030 emit_move_insn (rn, mem);
1031 DONE;
1032 }
1033 else
1034 {
1035 /* We get here when we have to change something that would
1036 be recognizable if it wasn't PIC. A ``sym'' is ok for
1037 PIC symbols both with and without a GOT entry. And ``sym
1038 + offset'' is ok for local symbols, so the only thing it
1039 could be, is a global symbol with an offset. Check and
1040 abort if not. */
1041 rtx reg = gen_reg_rtx (Pmode);
1042 rtx sym = get_related_value (operands[1]);
1043 HOST_WIDE_INT offs = get_integer_term (operands[1]);
1044
b3a13419 1045 gcc_assert (can_create_pseudo_p ()
c00fc5cf
HPN
1046 && t == cris_got_symbol_needing_fixup
1047 && sym != NULL_RTX && offs != 0);
1048
1049 emit_move_insn (reg, sym);
1050 if (expand_binop (SImode, add_optab, reg,
1051 GEN_INT (offs), operands[0], 0,
1052 OPTAB_LIB_WIDEN) != operands[0])
1053 internal_error ("expand_binop failed in movsi got+offs");
1054 DONE;
1055 }
1056 }
1057 }
b6c34129 1058})
0b85d816 1059
c00fc5cf
HPN
1060(define_insn "*movsi_got_load"
1061 [(set (reg:SI CRIS_GOT_REGNUM) (unspec:SI [(const_int 0)] CRIS_UNSPEC_GOT))]
1062 "flag_pic"
45d5d09c
HPN
1063{
1064 return TARGET_V32
1065 ? "lapc _GLOBAL_OFFSET_TABLE_,%:"
1066 : "move.d $pc,%:\;sub.d .:GOTOFF,%:";
1067}
c00fc5cf
HPN
1068 [(set_attr "cc" "clobber")])
1069
0b85d816
HPN
1070(define_insn "*movsi_internal"
1071 [(set
45d5d09c
HPN
1072 (match_operand:SI 0 "nonimmediate_operand"
1073 "=r,r, r,Q>,r,Q>,g,r,r, r,g,rQ>,x, m,x")
1074 (match_operand:SI 1 "cris_general_operand_or_pic_source"
1075 "r,Q>,M,M, I,r, M,n,!S,g,r,x, rQ>,x,gi"))]
c00fc5cf 1076 ;; Note that we prefer not to use the S alternative (if for some reason
45d5d09c 1077 ;; it competes with others) above, but g matches S.
0b85d816 1078 ""
0b85d816
HPN
1079{
1080 /* Better to have c-switch here; it is worth it to optimize the size of
1081 move insns. The alternative would be to try to find more constraint
1082 letters. FIXME: Check again. It seems this could shrink a bit. */
1083 switch (which_alternative)
1084 {
45d5d09c
HPN
1085 case 9:
1086 if (TARGET_V32)
1087 {
1088 if (!flag_pic
1089 && (GET_CODE (operands[1]) == SYMBOL_REF
1090 || GET_CODE (operands[1]) == LABEL_REF
ab4e53fe
HPN
1091 || (GET_CODE (operands[1]) == CONST
1092 && (GET_CODE (XEXP (operands[1], 0)) != UNSPEC
1093 || (XINT (XEXP (operands[1], 0), 1)
1094 == CRIS_UNSPEC_PLT_PCREL)
1095 || (XINT (XEXP (operands[1], 0), 1)
1096 == CRIS_UNSPEC_PCREL)))))
45d5d09c
HPN
1097 {
1098 /* FIXME: Express this through (set_attr cc none) instead,
1099 since we can't express the ``none'' at this point. FIXME:
1100 Use lapc for everything except const_int and when next cc0
1101 user would want the flag setting. */
1102 CC_STATUS_INIT;
1103 return "lapc %1,%0";
1104 }
1105 if (flag_pic == 1
1106 && GET_CODE (operands[1]) == CONST
1107 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
1108 && XINT (XEXP (operands[1], 0), 1) == CRIS_UNSPEC_GOTREAD)
1109 return "movu.w %1,%0";
1110 }
1111 /* FALLTHROUGH */
0b85d816
HPN
1112 case 0:
1113 case 1:
1114 case 5:
0b85d816 1115 case 10:
22c3c091 1116 return "move.d %1,%0";
0b85d816 1117
f60c7155
HPN
1118 case 11:
1119 case 12:
1120 case 13:
1121 case 14:
22c3c091 1122 return "move %d1,%0";
f60c7155 1123
0b85d816
HPN
1124 case 2:
1125 case 3:
1126 case 6:
22c3c091 1127 return "clear.d %0";
0b85d816
HPN
1128
1129 /* Constants -32..31 except 0. */
1130 case 4:
22c3c091 1131 return "moveq %1,%0";
0b85d816
HPN
1132
1133 /* We can win a little on constants -32768..-33, 32..65535. */
1134 case 7:
1135 if (INTVAL (operands[1]) > 0 && INTVAL (operands[1]) < 65536)
1136 {
1137 if (INTVAL (operands[1]) < 256)
22c3c091
HPN
1138 return "movu.b %1,%0";
1139 return "movu.w %1,%0";
0b85d816
HPN
1140 }
1141 else if (INTVAL (operands[1]) >= -32768 && INTVAL (operands[1]) < 32768)
1142 {
1143 if (INTVAL (operands[1]) >= -128 && INTVAL (operands[1]) < 128)
22c3c091
HPN
1144 return "movs.b %1,%0";
1145 return "movs.w %1,%0";
0b85d816 1146 }
22c3c091 1147 return "move.d %1,%0";
0b85d816 1148
d29b4b1b 1149 case 8:
c00fc5cf
HPN
1150 {
1151 rtx tem = operands[1];
1152 gcc_assert (GET_CODE (tem) == CONST);
1153 tem = XEXP (tem, 0);
1154 if (GET_CODE (tem) == PLUS
1155 && GET_CODE (XEXP (tem, 0)) == UNSPEC
45d5d09c
HPN
1156 && (XINT (XEXP (tem, 0), 1) == CRIS_UNSPEC_GOTREL
1157 || XINT (XEXP (tem, 0), 1) == CRIS_UNSPEC_PCREL)
991c42ac 1158 && CONST_INT_P (XEXP (tem, 1)))
c00fc5cf
HPN
1159 tem = XEXP (tem, 0);
1160 gcc_assert (GET_CODE (tem) == UNSPEC);
1161 switch (XINT (tem, 1))
1162 {
1163 case CRIS_UNSPEC_GOTREAD:
1164 case CRIS_UNSPEC_PLTGOTREAD:
1165 /* Using sign-extend mostly to be consistent with the
1166 indexed addressing mode. */
1167 if (flag_pic == 1)
1168 return "movs.w %1,%0";
45d5d09c
HPN
1169 return "move.d %1,%0";
1170
c00fc5cf 1171 case CRIS_UNSPEC_GOTREL:
45d5d09c
HPN
1172 case CRIS_UNSPEC_PLT_GOTREL:
1173 gcc_assert (!TARGET_V32);
c00fc5cf
HPN
1174 return "move.d %1,%0";
1175
45d5d09c
HPN
1176 case CRIS_UNSPEC_PCREL:
1177 case CRIS_UNSPEC_PLT_PCREL:
1178 gcc_assert (TARGET_V32);
ab4e53fe
HPN
1179 /* LAPC doesn't set condition codes; clear them to make the
1180 (equivalence-marked) result of this insn not presumed
1181 present. This instruction can be a PIC symbol load (for
1182 a hidden symbol) which for weak symbols will be followed
1183 by a test for NULL. */
1184 CC_STATUS_INIT;
45d5d09c
HPN
1185 return "lapc %1,%0";
1186
c00fc5cf
HPN
1187 default:
1188 gcc_unreachable ();
1189 }
1190 }
0b85d816 1191 default:
22c3c091 1192 return "BOGUS: %1 to %0";
0b85d816 1193 }
22c3c091 1194}
f60c7155
HPN
1195 [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no,no,yes,yes,no,no")
1196 (set_attr "cc" "*,*,*,*,*,*,*,*,*,*,*,none,none,none,none")])
0b85d816
HPN
1197\f
1198;; Extend operations with side-effect from mem to register, using
1199;; MOVS/MOVU. These are from mem to register only.
1200;;
1201;; [rx=ry+rz.S]
1202;;
1203;; QImode to HImode
1204;;
1205;; FIXME: Can we omit extend to HImode, since GCC should truncate for
1206;; HImode by itself? Perhaps use only anonymous modes?
1207
1208(define_insn "*ext_sideqihi_biap"
1209 [(set (match_operand:HI 0 "register_operand" "=r,r")
1210 (match_operator:HI
1211 5 "cris_extend_operator"
1212 [(mem:QI (plus:SI
1213 (mult:SI (match_operand:SI 1 "register_operand" "r,r")
1214 (match_operand:SI 2 "const_int_operand" "n,n"))
1215 (match_operand:SI 3 "register_operand" "r,r")))]))
1216 (set (match_operand:SI 4 "register_operand" "=*3,r")
1217 (plus:SI (mult:SI (match_dup 1)
1218 (match_dup 2))
1219 (match_dup 3)))]
1220 "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
1221 "@
1222 #
1223 mov%e5.%m5 [%4=%3+%1%T2],%0")
1224
22c3c091 1225(define_insn "*ext_side<mode>si_biap"
0b85d816
HPN
1226 [(set (match_operand:SI 0 "register_operand" "=r,r")
1227 (match_operator:SI
1228 5 "cris_extend_operator"
22c3c091 1229 [(mem:BW (plus:SI
0b85d816
HPN
1230 (mult:SI (match_operand:SI 1 "register_operand" "r,r")
1231 (match_operand:SI 2 "const_int_operand" "n,n"))
1232 (match_operand:SI 3 "register_operand" "r,r")))]))
1233 (set (match_operand:SI 4 "register_operand" "=*3,r")
1234 (plus:SI (mult:SI (match_dup 1)
1235 (match_dup 2))
1236 (match_dup 3)))]
1237 "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
1238 "@
1239 #
22c3c091 1240 mov%e5<m> [%4=%3+%1%T2],%0")
0b85d816
HPN
1241\f
1242;; Same but [rx=ry+i]
1243
1244;; QImode to HImode
1245
1246(define_insn "*ext_sideqihi"
1165f377 1247 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
0b85d816
HPN
1248 (match_operator:HI
1249 4 "cris_extend_operator"
1250 [(mem:QI (plus:SI
1165f377
HPN
1251 (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,R,R")
1252 (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))]))
1253 (set (match_operand:SI 3 "register_operand" "=*1,r,r,*2,r")
0b85d816
HPN
1254 (plus:SI (match_dup 1)
1255 (match_dup 2)))]
1256 "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
0b85d816 1257{
1165f377 1258 if ((which_alternative == 0 || which_alternative == 3)
991c42ac 1259 && (!CONST_INT_P (operands[2])
0b85d816
HPN
1260 || INTVAL (operands[2]) > 127
1261 || INTVAL (operands[2]) < -128
06cadf63
AS
1262 || satisfies_constraint_N (operands[2])
1263 || satisfies_constraint_J (operands[2])))
22c3c091 1264 return "#";
1165f377
HPN
1265 if (which_alternative == 4)
1266 return "mov%e4.%m4 [%3=%2%S1],%0";
22c3c091
HPN
1267 return "mov%e4.%m4 [%3=%1%S2],%0";
1268})
0b85d816 1269
22c3c091 1270(define_insn "*ext_side<mode>si"
1165f377 1271 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
0b85d816
HPN
1272 (match_operator:SI
1273 4 "cris_extend_operator"
22c3c091 1274 [(mem:BW (plus:SI
1165f377
HPN
1275 (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,R,R")
1276 (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))]))
1277 (set (match_operand:SI 3 "register_operand" "=*1,r,r,*2,r")
0b85d816
HPN
1278 (plus:SI (match_dup 1)
1279 (match_dup 2)))]
1280 "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
0b85d816 1281{
1165f377 1282 if ((which_alternative == 0 || which_alternative == 3)
991c42ac 1283 && (!CONST_INT_P (operands[2])
0b85d816
HPN
1284 || INTVAL (operands[2]) > 127
1285 || INTVAL (operands[2]) < -128
06cadf63
AS
1286 || satisfies_constraint_N (operands[2])
1287 || satisfies_constraint_J (operands[2])))
22c3c091 1288 return "#";
1165f377
HPN
1289 if (which_alternative == 4)
1290 return "mov%e4<m> [%3=%2%S1],%0";
22c3c091
HPN
1291 return "mov%e4<m> [%3=%1%S2],%0";
1292})
0b85d816
HPN
1293\f
1294;; FIXME: See movsi.
1295
1296(define_insn "movhi"
1297 [(set
f60c7155
HPN
1298 (match_operand:HI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,r,r,r,g,g,r,r,x")
1299 (match_operand:HI 1 "general_operand" "r,Q>,M,M, I,r, L,O,n,M,r,g,x,r"))]
0b85d816 1300 ""
0b85d816
HPN
1301{
1302 switch (which_alternative)
1303 {
1304 case 0:
1305 case 1:
1306 case 5:
1307 case 10:
1308 case 11:
22c3c091 1309 return "move.w %1,%0";
f60c7155
HPN
1310 case 12:
1311 case 13:
22c3c091 1312 return "move %1,%0";
0b85d816
HPN
1313 case 2:
1314 case 3:
1315 case 9:
22c3c091 1316 return "clear.w %0";
0b85d816 1317 case 4:
22c3c091 1318 return "moveq %1,%0";
0b85d816
HPN
1319 case 6:
1320 case 8:
1321 if (INTVAL (operands[1]) < 256 && INTVAL (operands[1]) >= -128)
1322 {
1323 if (INTVAL (operands[1]) > 0)
22c3c091
HPN
1324 return "movu.b %1,%0";
1325 return "movs.b %1,%0";
0b85d816 1326 }
22c3c091 1327 return "move.w %1,%0";
0b85d816 1328 case 7:
22c3c091 1329 return "movEq %b1,%0";
0b85d816 1330 default:
22c3c091 1331 return "BOGUS: %1 to %0";
0b85d816 1332 }
22c3c091 1333}
f60c7155
HPN
1334 [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,yes,no,no,no,no,yes,yes")
1335 (set_attr "cc" "*,*,none,none,*,none,*,clobber,*,none,none,*,none,none")])
0b85d816
HPN
1336
1337(define_insn "movstricthi"
1338 [(set
1339 (strict_low_part
23369bef
HPN
1340 (match_operand:HI 0 "nonimmediate_operand" "+r,r, r,Q>,Q>,g,r,g"))
1341 (match_operand:HI 1 "general_operand" "r,Q>,M,M, r, M,g,r"))]
0b85d816
HPN
1342 ""
1343 "@
1344 move.w %1,%0
1345 move.w %1,%0
1346 clear.w %0
1347 clear.w %0
1348 move.w %1,%0
1349 clear.w %0
1350 move.w %1,%0
1351 move.w %1,%0"
1352 [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")])
f60c7155 1353
22c3c091
HPN
1354(define_expand "reload_in<mode>"
1355 [(set (match_operand:BW 2 "register_operand" "=r")
1356 (match_operand:BW 1 "memory_operand" "m"))
1357 (set (match_operand:BW 0 "register_operand" "=x")
f60c7155
HPN
1358 (match_dup 2))]
1359 ""
1360 "")
1361
22c3c091 1362(define_expand "reload_out<mode>"
11e30dd8 1363 [(set (match_operand:BW 2 "register_operand" "=&r")
22c3c091
HPN
1364 (match_operand:BW 1 "register_operand" "x"))
1365 (set (match_operand:BW 0 "memory_operand" "=m")
f60c7155
HPN
1366 (match_dup 2))]
1367 ""
1368 "")
0b85d816
HPN
1369\f
1370(define_insn "movqi"
f60c7155
HPN
1371 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,r,g,g,r,r,r,x")
1372 (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, I,M,r,O,g,x,r"))]
0b85d816
HPN
1373 ""
1374 "@
1375 move.b %1,%0
1376 move.b %1,%0
1377 move.b %1,%0
1378 clear.b %0
1379 clear.b %0
1380 moveq %1,%0
1381 clear.b %0
1382 move.b %1,%0
1383 moveq %b1,%0
f60c7155
HPN
1384 move.b %1,%0
1385 move %1,%0
1386 move %1,%0"
1387 [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,yes,no,yes,yes")
1388 (set_attr "cc" "*,*,*,*,*,*,*,*,clobber,*,none,none")])
0b85d816
HPN
1389
1390(define_insn "movstrictqi"
1391 [(set (strict_low_part
23369bef
HPN
1392 (match_operand:QI 0 "nonimmediate_operand" "+r,Q>,r, r,Q>,g,g,r"))
1393 (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, M,r,g"))]
0b85d816
HPN
1394 ""
1395 "@
1396 move.b %1,%0
1397 move.b %1,%0
1398 move.b %1,%0
1399 clear.b %0
1400 clear.b %0
1401 clear.b %0
1402 move.b %1,%0
1403 move.b %1,%0"
1404 [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")])
1405
1406;; The valid "quick" bit-patterns are, except for 0.0, denormalized
1407;; values REALLY close to 0, and some NaN:s (I think; their exponent is
1408;; all ones); the worthwhile one is "0.0".
1409;; It will use clear, so we know ALL types of immediate 0 never change cc.
1410
1411(define_insn "movsf"
f60c7155
HPN
1412 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,g,g,r,r,x,Q>,m,x, x")
1413 (match_operand:SF 1 "general_operand" "r,r, Q>,G,G, G,r,g,x,r,x, x,Q>,g"))]
0b85d816
HPN
1414 ""
1415 "@
1416 move.d %1,%0
1417 move.d %1,%0
1418 move.d %1,%0
1419 clear.d %0
1420 clear.d %0
1421 clear.d %0
1422 move.d %1,%0
f60c7155
HPN
1423 move.d %1,%0
1424 move %1,%0
1425 move %1,%0
1426 move %1,%0
1427 move %1,%0
1428 move %1,%0
1429 move %1,%0"
1430 [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no,yes,yes,yes,no,yes,no")])
45d5d09c
HPN
1431\f
1432;; Movem patterns. Primarily for use in function prologue and epilogue.
1433;; The V32 variants have an ordering matching the expectations of the
1434;; standard names "load_multiple" and "store_multiple"; pre-v32 movem
1435;; store R0 in the highest memory location.
1436
1437(define_expand "load_multiple"
1438 [(match_operand:SI 0 "register_operand" "")
1439 (match_operand:SI 1 "memory_operand" "")
1440 (match_operand:SI 2 "const_int_operand" "")]
1441 "TARGET_V32"
1442{
1443 rtx indreg;
1444
1445 /* Apparently the predicate isn't checked, so we need to do so
1446 manually. Once happened for libstdc++-v3 locale_facets.tcc. */
1447 if (!MEM_P (operands[1]))
1448 FAIL;
1449
1450 indreg = XEXP (operands[1], 0);
1451
1452 if (GET_CODE (indreg) == POST_INC)
1453 indreg = XEXP (indreg, 0);
1454 if (!REG_P (indreg)
1455 || GET_CODE (operands[2]) != CONST_INT
1456 || !REG_P (operands[0])
1457 || REGNO (operands[0]) != 0
1458 || INTVAL (operands[2]) > CRIS_SP_REGNUM
1459 || (int) REGNO (indreg) < INTVAL (operands[2]))
1460 FAIL;
1461 gcc_unreachable ();
1462 emit_insn (cris_gen_movem_load (operands[1], operands[2], 0));
1463 DONE;
1464})
1465
1466(define_expand "store_multiple"
1467 [(match_operand:SI 0 "memory_operand" "")
1468 (match_operand:SI 1 "register_operand" "")
1469 (match_operand:SI 2 "const_int_operand" "")]
1470 "TARGET_V32"
1471{
1472 rtx indreg;
1473
1474 /* See load_multiple. */
1475 if (!MEM_P (operands[0]))
1476 FAIL;
1477
1478 indreg = XEXP (operands[0], 0);
1479
1480 if (GET_CODE (indreg) == POST_INC)
1481 indreg = XEXP (indreg, 0);
1482 if (!REG_P (indreg)
1483 || GET_CODE (operands[2]) != CONST_INT
1484 || !REG_P (operands[1])
1485 || REGNO (operands[1]) != 0
1486 || INTVAL (operands[2]) > CRIS_SP_REGNUM
1487 || (int) REGNO (indreg) < INTVAL (operands[2]))
1488 FAIL;
1489 gcc_unreachable ();
1490 cris_emit_movem_store (operands[0], operands[2], 0, false);
1491 DONE;
1492})
04539954 1493
04539954
HPN
1494(define_insn "*cris_load_multiple"
1495 [(match_parallel 0 "cris_load_multiple_op"
1496 [(set (match_operand:SI 1 "register_operand" "=r,r")
1497 (match_operand:SI 2 "memory_operand" "Q,m"))])]
1498 ""
1499 "movem %O0,%o0"
1500 [(set_attr "cc" "none")
1501 (set_attr "slottable" "yes,no")
1502 ;; Not true, but setting the length to 0 causes return sequences (ret
1503 ;; movem) to have the cost they had when (return) included the movem
1504 ;; and reduces the performance penalty taken for needing to emit an
1505 ;; epilogue (in turn copied by bb-reorder) instead of return patterns.
1506 ;; FIXME: temporary change until all insn lengths are correctly
1507 ;; described. FIXME: have better target control over bb-reorder.
1508 (set_attr "length" "0")])
d29b4b1b
HPN
1509
1510(define_insn "*cris_store_multiple"
1511 [(match_parallel 0 "cris_store_multiple_op"
1512 [(set (match_operand:SI 2 "memory_operand" "=Q,m")
1513 (match_operand:SI 1 "register_operand" "r,r"))])]
1514 ""
1515 "movem %o0,%O0"
1516 [(set_attr "cc" "none")
1517 (set_attr "slottable" "yes,no")])
0b85d816
HPN
1518\f
1519
1520;; Sign- and zero-extend insns with standard names.
1521;; Those for integer source operand are ordered with the widest source
1522;; type first.
1523
1524;; Sign-extend.
1525
1526(define_insn "extendsidi2"
1527 [(set (match_operand:DI 0 "register_operand" "=r")
1528 (sign_extend:DI (match_operand:SI 1 "general_operand" "g")))]
1529 ""
1530 "move.d %1,%M0\;smi %H0\;neg.d %H0,%H0")
1531
22c3c091 1532(define_insn "extend<mode>di2"
0b85d816 1533 [(set (match_operand:DI 0 "register_operand" "=r")
22c3c091 1534 (sign_extend:DI (match_operand:BW 1 "general_operand" "g")))]
0b85d816 1535 ""
22c3c091 1536 "movs<m> %1,%M0\;smi %H0\;neg.d %H0,%H0")
0b85d816 1537
22c3c091 1538(define_insn "extend<mode>si2"
0b85d816 1539 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
22c3c091 1540 (sign_extend:SI (match_operand:BW 1 "general_operand" "r,Q>,g")))]
0b85d816 1541 ""
22c3c091 1542 "movs<m> %1,%0"
0b85d816
HPN
1543 [(set_attr "slottable" "yes,yes,no")])
1544
073a8998 1545;; To do a byte->word extension, extend to dword, except that the top half
0b85d816
HPN
1546;; of the register will be clobbered. FIXME: Perhaps this is not needed.
1547
1548(define_insn "extendqihi2"
1549 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
1550 (sign_extend:HI (match_operand:QI 1 "general_operand" "r,Q>,g")))]
1551 ""
1552 "movs.b %1,%0"
1553 [(set_attr "slottable" "yes,yes,no")])
1554\f
1555
1556;; Zero-extend. The DImode ones are synthesized by gcc, so we don't
1557;; specify them here.
1558
22c3c091 1559(define_insn "zero_extend<mode>si2"
0b85d816
HPN
1560 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1561 (zero_extend:SI
22c3c091 1562 (match_operand:BW 1 "nonimmediate_operand" "r,Q>,m")))]
0b85d816 1563 ""
22c3c091 1564 "movu<m> %1,%0"
0b85d816
HPN
1565 [(set_attr "slottable" "yes,yes,no")])
1566
1567;; Same comment as sign-extend QImode to HImode above applies.
1568
1569(define_insn "zero_extendqihi2"
1570 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
1571 (zero_extend:HI
1572 (match_operand:QI 1 "nonimmediate_operand" "r,Q>,m")))]
1573 ""
1574 "movu.b %1,%0"
1575 [(set_attr "slottable" "yes,yes,no")])
1576\f
1577;; All kinds of arithmetic and logical instructions.
1578;;
1579;; First, anonymous patterns to match addressing modes with
1580;; side-effects.
1581;;
1582;; op.S [rx=ry+I],rz; (add, sub, or, and, bound).
1583;;
1584;; [rx=ry+rz.S]
0b85d816 1585
22c3c091
HPN
1586(define_insn "*op_side<mode>_biap"
1587 [(set (match_operand:BWD 0 "register_operand" "=r,r")
1588 (match_operator:BWD
0b85d816 1589 6 "cris_orthogonal_operator"
22c3c091
HPN
1590 [(match_operand:BWD 1 "register_operand" "0,0")
1591 (mem:BWD (plus:SI
1592 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
1593 (match_operand:SI 3 "const_int_operand" "n,n"))
1594 (match_operand:SI 4 "register_operand" "r,r")))]))
0b85d816
HPN
1595 (set (match_operand:SI 5 "register_operand" "=*4,r")
1596 (plus:SI (mult:SI (match_dup 2)
1597 (match_dup 3))
1598 (match_dup 4)))]
1599 "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
1600 "@
1601 #
22c3c091 1602 %x6<m> [%5=%4+%2%T3],%0")
0b85d816
HPN
1603\f
1604;; [rx=ry+i] ([%4=%2+%3])
0b85d816 1605
22c3c091 1606(define_insn "*op_side<mode>"
1165f377 1607 [(set (match_operand:BWD 0 "register_operand" "=r,r,r,r,r")
22c3c091 1608 (match_operator:BWD
0b85d816 1609 5 "cris_orthogonal_operator"
1165f377 1610 [(match_operand:BWD 1 "register_operand" "0,0,0,0,0")
22c3c091 1611 (mem:BWD (plus:SI
1165f377
HPN
1612 (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
1613 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))]))
1614 (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
0b85d816
HPN
1615 (plus:SI (match_dup 2)
1616 (match_dup 3)))]
1617 "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816 1618{
1165f377 1619 if ((which_alternative == 0 || which_alternative == 3)
991c42ac 1620 && (!CONST_INT_P (operands[3])
0b85d816
HPN
1621 || INTVAL (operands[3]) > 127
1622 || INTVAL (operands[3]) < -128
06cadf63
AS
1623 || satisfies_constraint_N (operands[3])
1624 || satisfies_constraint_J (operands[3])))
22c3c091 1625 return "#";
1165f377
HPN
1626 if (which_alternative == 4)
1627 return "%x5.%s0 [%4=%3%S2],%0";
22c3c091
HPN
1628 return "%x5<m> [%4=%2%S3],%0";
1629})
0b85d816
HPN
1630\f
1631;; To match all cases for commutative operations we may have to have the
1632;; following pattern for add, or & and. I do not know really, but it does
1633;; not break anything.
1634;;
1635;; FIXME: This really ought to be checked.
1636;;
1637;; op.S [rx=ry+I],rz;
1638;;
1639;; [rx=ry+rz.S]
0b85d816 1640
22c3c091
HPN
1641(define_insn "*op_swap_side<mode>_biap"
1642 [(set (match_operand:BWD 0 "register_operand" "=r,r")
1643 (match_operator:BWD
0b85d816 1644 6 "cris_commutative_orth_op"
22c3c091 1645 [(mem:BWD (plus:SI
0b85d816
HPN
1646 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
1647 (match_operand:SI 3 "const_int_operand" "n,n"))
1648 (match_operand:SI 4 "register_operand" "r,r")))
22c3c091 1649 (match_operand:BWD 1 "register_operand" "0,0")]))
0b85d816
HPN
1650 (set (match_operand:SI 5 "register_operand" "=*4,r")
1651 (plus:SI (mult:SI (match_dup 2)
1652 (match_dup 3))
1653 (match_dup 4)))]
1654 "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
1655 "@
1656 #
22c3c091 1657 %x6<m> [%5=%4+%2%T3],%0")
0b85d816
HPN
1658\f
1659;; [rx=ry+i] ([%4=%2+%3])
1660;; FIXME: These could have anonymous mode for operand 0.
1661
1662;; QImode
1663
22c3c091 1664(define_insn "*op_swap_side<mode>"
1165f377 1665 [(set (match_operand:BWD 0 "register_operand" "=r,r,r,r,r")
22c3c091 1666 (match_operator:BWD
0b85d816 1667 5 "cris_commutative_orth_op"
22c3c091 1668 [(mem:BWD
1165f377
HPN
1669 (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
1670 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))
1671 (match_operand:BWD 1 "register_operand" "0,0,0,0,0")]))
1672 (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
0b85d816
HPN
1673 (plus:SI (match_dup 2)
1674 (match_dup 3)))]
1675 "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816 1676{
1165f377 1677 if ((which_alternative == 0 || which_alternative == 3)
991c42ac 1678 && (!CONST_INT_P (operands[3])
0b85d816
HPN
1679 || INTVAL (operands[3]) > 127
1680 || INTVAL (operands[3]) < -128
06cadf63
AS
1681 || satisfies_constraint_N (operands[3])
1682 || satisfies_constraint_J (operands[3])))
22c3c091 1683 return "#";
1165f377
HPN
1684 if (which_alternative == 4)
1685 return "%x5<m> [%4=%3%S2],%0";
22c3c091
HPN
1686 return "%x5<m> [%4=%2%S3],%0";
1687})
0b85d816
HPN
1688\f
1689;; Add operations, standard names.
1690
1691;; Note that for the 'P' constraint, the high part can be -1 or 0. We
1692;; output the insn through the 'A' output modifier as "adds.w" and "addq",
1693;; respectively.
45d5d09c
HPN
1694(define_expand "adddi3"
1695 [(set (match_operand:DI 0 "register_operand")
1696 (plus:DI (match_operand:DI 1 "register_operand")
1697 (match_operand:DI 2 "general_operand")))]
1698 ""
1699{
1700 if (MEM_P (operands[2]) && TARGET_V32)
1701 operands[2] = force_reg (DImode, operands[2]);
1702})
1703
1704(define_insn "*adddi3_non_v32"
0b85d816
HPN
1705 [(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r")
1706 (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,r")
1707 (match_operand:DI 2 "general_operand" "J,N,P,g,!To")))]
45d5d09c 1708 "!TARGET_V32"
0b85d816
HPN
1709 "@
1710 addq %2,%M0\;ax\;addq 0,%H0
1711 subq %n2,%M0\;ax\;subq 0,%H0
1712 add%e2.%z2 %2,%M0\;ax\;%A2 %H2,%H0
1713 add.d %M2,%M0\;ax\;add.d %H2,%H0
1714 add.d %M2,%M1,%M0\;ax\;add.d %H2,%H1,%H0")
1715
45d5d09c
HPN
1716; It seems no use allowing a memory operand for this one, because we'd
1717; need a scratch register for incrementing the address.
1718(define_insn "*adddi3_v32"
1719 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r")
1720 (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,0")
1721 (match_operand:DI 2 "nonmemory_operand" "J,N,P,r,n")))]
1722 "TARGET_V32"
1723 "@
1724 addq %2,%M0\;addc 0,%H0
1725 subq %n2,%M0\;ax\;subq 0,%H0
1726 add%e2.%z2 %2,%M0\;addc %H2,%H0
1727 add.d %M2,%M0\;addc %H2,%H0
1728 add.d %M2,%M0\;addc %H2,%H0")
1729
1730(define_expand "add<mode>3"
1731 [(set (match_operand:BWD 0 "register_operand")
1732 (plus:BWD
1733 (match_operand:BWD 1 "register_operand")
1734 (match_operand:BWD 2 "general_operand")))]
1735 ""
1736 "")
1737
1738(define_insn "*addsi3_non_v32"
c00fc5cf 1739 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r, r,r, r")
0b85d816 1740 (plus:SI
c00fc5cf
HPN
1741 (match_operand:SI 1 "register_operand" "%0,0, 0,0,0,0, 0,r, r")
1742 (match_operand:SI 2 "general_operand" "r,Q>,J,N,n,!S,g,!To,0")))]
0b85d816
HPN
1743
1744;; The last constraint is due to that after reload, the '%' is not
1745;; honored, and canonicalization doesn't care about keeping the same
1746;; register as in destination. This will happen after insn splitting.
1747;; gcc <= 2.7.2. FIXME: Check for gcc-2.9x
1748
45d5d09c 1749 "!TARGET_V32"
0b85d816
HPN
1750{
1751 switch (which_alternative)
1752 {
1753 case 0:
1754 case 1:
22c3c091 1755 return "add.d %2,%0";
0b85d816 1756 case 2:
22c3c091 1757 return "addq %2,%0";
0b85d816 1758 case 3:
22c3c091 1759 return "subq %n2,%0";
0b85d816
HPN
1760 case 4:
1761 /* 'Known value', but not in -63..63.
1762 Check if addu/subu may be used. */
1763 if (INTVAL (operands[2]) > 0)
1764 {
1765 if (INTVAL (operands[2]) < 256)
22c3c091 1766 return "addu.b %2,%0";
0b85d816 1767 if (INTVAL (operands[2]) < 65536)
22c3c091 1768 return "addu.w %2,%0";
0b85d816
HPN
1769 }
1770 else
1771 {
1772 if (INTVAL (operands[2]) >= -255)
22c3c091 1773 return "subu.b %n2,%0";
0b85d816 1774 if (INTVAL (operands[2]) >= -65535)
22c3c091 1775 return "subu.w %n2,%0";
0b85d816 1776 }
22c3c091 1777 return "add.d %2,%0";
0b85d816 1778 case 5:
c00fc5cf
HPN
1779 {
1780 rtx tem = operands[2];
1781 gcc_assert (GET_CODE (tem) == CONST);
1782 tem = XEXP (tem, 0);
1783 if (GET_CODE (tem) == PLUS
1784 && GET_CODE (XEXP (tem, 0)) == UNSPEC
45d5d09c
HPN
1785 /* We don't allow CRIS_UNSPEC_PCREL here; we can't have a
1786 pc-relative operand in an add insn. */
c00fc5cf 1787 && XINT (XEXP (tem, 0), 1) == CRIS_UNSPEC_GOTREL
991c42ac 1788 && CONST_INT_P (XEXP (tem, 1)))
c00fc5cf
HPN
1789 tem = XEXP (tem, 0);
1790 gcc_assert (GET_CODE (tem) == UNSPEC);
1791 switch (XINT (tem, 1))
1792 {
1793 case CRIS_UNSPEC_GOTREAD:
1794 case CRIS_UNSPEC_PLTGOTREAD:
1795 /* Using sign-extend mostly to be consistent with the
1796 indexed addressing mode. */
1797 if (flag_pic == 1)
1798 return "adds.w %2,%0";
45d5d09c
HPN
1799 return "add.d %2,%0";
1800
1801 case CRIS_UNSPEC_PLT_GOTREL:
c00fc5cf
HPN
1802 case CRIS_UNSPEC_GOTREL:
1803 return "add.d %2,%0";
1804 default:
1805 gcc_unreachable ();
1806 }
1807 }
1808 case 6:
45d5d09c 1809 return "add%u2 %2,%0";
0b85d816 1810 case 7:
c00fc5cf
HPN
1811 return "add.d %2,%1,%0";
1812 case 8:
22c3c091 1813 return "add.d %1,%0";
0b85d816 1814 default:
22c3c091 1815 return "BOGUS addsi %2+%1 to %0";
0b85d816 1816 }
22c3c091 1817}
c00fc5cf 1818 [(set_attr "slottable" "yes,yes,yes,yes,no,no,no,no,yes")])
45d5d09c
HPN
1819
1820; FIXME: Check what's best: having the three-operand ACR alternative
1821; before or after the corresponding-operand2 alternative. Check for
1822; *all* insns. FIXME: constant constraint letter for -128..127.
1823(define_insn "*addsi3_v32"
1824 [(set (match_operand:SI 0 "register_operand" "=r,!a,r,!a, r,r,!a,r,!a,r,r,r,!a")
1825 (plus:SI
1826 (match_operand:SI 1 "register_operand" "%0,r, 0, r, 0,0,r, 0,r, 0,0,0,r")
1827 (match_operand:SI 2 "general_operand" "r, r, Q>,Q>,J,N,NJ,L,L, P,n,g,g")))]
1828 "TARGET_V32"
1829 "@
1830 add.d %2,%0
1831 addi %2.b,%1,%0
1832 add.d %2,%0
1833 addo.d %2,%1,%0
1834 addq %2,%0
1835 subq %n2,%0
1836 addoq %2,%1,%0
1837 adds.w %2,%0
1838 addo %2,%1,%0
1839 addu.w %2,%0
1840 add.d %2,%0
1841 add%u2 %2,%0
1842 addo.%Z2 %2,%1,%0"
1843 [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,yes,no,no,no,no,no,no")
d8ec9c14 1844 (set_attr "cc" "*,none,*,none,*,*,none,*,none,*,*,*,none")])
0b85d816 1845\f
45d5d09c 1846(define_insn "*addhi3_non_v32"
23369bef
HPN
1847 [(set (match_operand:HI 0 "register_operand" "=r,r, r,r,r,r")
1848 (plus:HI (match_operand:HI 1 "register_operand" "%0,0, 0,0,0,r")
1849 (match_operand:HI 2 "general_operand" "r,Q>,J,N,g,!To")))]
45d5d09c 1850 "!TARGET_V32"
0b85d816
HPN
1851 "@
1852 add.w %2,%0
1853 add.w %2,%0
1854 addq %2,%0
1855 subq %n2,%0
1856 add.w %2,%0
1857 add.w %2,%1,%0"
1858 [(set_attr "slottable" "yes,yes,yes,yes,no,no")
1859 (set_attr "cc" "normal,normal,clobber,clobber,normal,normal")])
1860
45d5d09c
HPN
1861(define_insn "*addhi3_v32"
1862 [(set (match_operand:HI 0 "register_operand" "=r, !a,r,!a, r,r,!a,r,!a")
1863 (plus:HI
1864 (match_operand:HI 1 "register_operand" "%0,r, 0, r, 0,0,r, 0,r")
1865 (match_operand:HI 2 "general_operand" "r, r, Q>,Q>,J,N,NJ,g,g")))]
1866 "TARGET_V32"
1867 "@
1868 add.w %2,%0
1869 addi %2.b,%1,%0
1870 add.w %2,%0
1871 addo.w %2,%1,%0
1872 addq %2,%0
1873 subq %n2,%0
1874 addoq %2,%1,%0
1875 add.w %2,%0
1876 addo.w %2,%1,%0"
1877 [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,yes,no,no")
1878 (set_attr "cc" "*,none,*,none,clobber,clobber,none,*,none")])
1879
1880(define_insn "*addqi3_non_v32"
23369bef
HPN
1881 [(set (match_operand:QI 0 "register_operand" "=r,r, r,r,r,r,r")
1882 (plus:QI (match_operand:QI 1 "register_operand" "%0,0, 0,0,0,0,r")
1883 (match_operand:QI 2 "general_operand" "r,Q>,J,N,O,g,!To")))]
45d5d09c 1884 "!TARGET_V32"
0b85d816
HPN
1885 "@
1886 add.b %2,%0
1887 add.b %2,%0
1888 addq %2,%0
1889 subq %n2,%0
1890 subQ -%b2,%0
1891 add.b %2,%0
1892 add.b %2,%1,%0"
1893 [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no")
1894 (set_attr "cc" "normal,normal,clobber,clobber,clobber,normal,normal")])
45d5d09c
HPN
1895
1896(define_insn "*addqi3_v32"
1897 [(set (match_operand:QI 0 "register_operand" "=r,!a,r,!a, r,r,!a,r,r,!a")
1898 (plus:QI
1899 (match_operand:QI 1 "register_operand" "%0,r, 0, r, 0,0,r, 0,0,r")
1900 (match_operand:QI 2 "general_operand" "r,r, Q>,Q>,J,N,NJ,O,g,g")))]
1901 "TARGET_V32"
1902 "@
1903 add.b %2,%0
1904 addi %2.b,%1,%0
1905 add.b %2,%0
1906 addo.b %2,%1,%0
1907 addq %2,%0
1908 subq %n2,%0
1909 addoq %2,%1,%0
1910 subQ -%b2,%0
1911 add.b %2,%0
1912 addo.b %2,%1,%0"
1913 [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,yes,yes,no,no")
1914 (set_attr "cc" "*,none,*,none,clobber,clobber,none,clobber,*,none")])
0b85d816
HPN
1915\f
1916;; Subtract.
1917;;
1918;; Note that because of insn canonicalization these will *seldom* but
1919;; rarely be used with a known constant as an operand.
1920
1921;; Note that for the 'P' constraint, the high part can be -1 or 0. We
1922;; output the insn through the 'D' output modifier as "subs.w" and "subq",
1923;; respectively.
45d5d09c
HPN
1924(define_expand "subdi3"
1925 [(set (match_operand:DI 0 "register_operand")
1926 (minus:DI (match_operand:DI 1 "register_operand")
1927 (match_operand:DI 2 "general_operand")))]
1928 ""
1929{
1930 if (TARGET_V32 && MEM_P (operands[2]))
1931 operands[2] = force_reg (DImode, operands[2]);
1932})
1933
1934(define_insn "*subdi3_non_v32"
0b85d816
HPN
1935 [(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r")
1936 (minus:DI (match_operand:DI 1 "register_operand" "0,0,0,0,r")
1937 (match_operand:DI 2 "general_operand" "J,N,P,g,!To")))]
45d5d09c 1938 "!TARGET_V32"
0b85d816
HPN
1939 "@
1940 subq %2,%M0\;ax\;subq 0,%H0
1941 addq %n2,%M0\;ax\;addq 0,%H0
1942 sub%e2.%z2 %2,%M0\;ax\;%D2 %H2,%H0
1943 sub.d %M2,%M0\;ax\;sub.d %H2,%H0
1944 sub.d %M2,%M1,%M0\;ax\;sub.d %H2,%H1,%H0")
1945
45d5d09c
HPN
1946(define_insn "*subdi3_v32"
1947 [(set (match_operand:DI 0 "register_operand" "=r,r,r,&r")
1948 (minus:DI (match_operand:DI 1 "register_operand" "0,0,0,0")
1949 (match_operand:DI 2 "nonmemory_operand" "J,N,P,r")))]
1950 "TARGET_V32"
1951 "@
1952 subq %2,%M0\;ax\;subq 0,%H0
1953 addq %n2,%M0\;ax\;addq 0,%H0
1954 sub%e2.%z2 %2,%M0\;ax\;%D2 %H2,%H0
1955 sub.d %M2,%M0\;ax\;sub.d %H2,%H0")
1956
1957(define_expand "sub<mode>3"
1958 [(set (match_operand:BWD 0 "register_operand")
1959 (minus:BWD
1960 (match_operand:BWD 1 "register_operand")
1961 (match_operand:BWD 2 "general_operand")))]
1962 ""
1963 "")
1964
1965(define_insn "*subsi3_non_v32"
23369bef 1966 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r,r,r")
0b85d816 1967 (minus:SI
23369bef
HPN
1968 (match_operand:SI 1 "register_operand" "0,0, 0,0,0,0,0,r")
1969 (match_operand:SI 2 "general_operand" "r,Q>,J,N,P,n,g,!To")))]
45d5d09c 1970 "!TARGET_V32"
0b85d816
HPN
1971
1972;; This does not do the optimal: "addu.w 65535,r0" when %2 is negative.
1973;; But then again, %2 should not be negative.
1974
1975 "@
1976 sub.d %2,%0
1977 sub.d %2,%0
1978 subq %2,%0
1979 addq %n2,%0
1980 sub%e2.%z2 %2,%0
1981 sub.d %2,%0
1982 sub.d %2,%0
1983 sub.d %2,%1,%0"
1984 [(set_attr "slottable" "yes,yes,yes,yes,no,no,no,no")])
45d5d09c
HPN
1985
1986(define_insn "*subsi3_v32"
1987 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
1988 (minus:SI
1989 (match_operand:SI 1 "register_operand" "0,0,0,0,0,0,0")
1990 (match_operand:SI 2 "general_operand" "r,Q>,J,N,P,n,g")))]
1991 "TARGET_V32"
1992 "@
1993 sub.d %2,%0
1994 sub.d %2,%0
1995 subq %2,%0
1996 addq %n2,%0
1997 sub%e2.%z2 %2,%0
1998 sub.d %2,%0
1999 sub.d %2,%0"
2000 [(set_attr "slottable" "yes,yes,yes,yes,no,no,no")])
0b85d816 2001\f
45d5d09c 2002(define_insn "*sub<mode>3_nonv32"
22c3c091
HPN
2003 [(set (match_operand:BW 0 "register_operand" "=r,r, r,r,r,r")
2004 (minus:BW (match_operand:BW 1 "register_operand" "0,0, 0,0,0,r")
2005 (match_operand:BW 2 "general_operand" "r,Q>,J,N,g,!To")))]
45d5d09c 2006 "!TARGET_V32"
0b85d816 2007 "@
22c3c091
HPN
2008 sub<m> %2,%0
2009 sub<m> %2,%0
0b85d816
HPN
2010 subq %2,%0
2011 addq %n2,%0
22c3c091
HPN
2012 sub<m> %2,%0
2013 sub<m> %2,%1,%0"
0b85d816
HPN
2014 [(set_attr "slottable" "yes,yes,yes,yes,no,no")
2015 (set_attr "cc" "normal,normal,clobber,clobber,normal,normal")])
45d5d09c
HPN
2016
2017(define_insn "*sub<mode>3_v32"
2018 [(set (match_operand:BW 0 "register_operand" "=r,r,r,r,r")
2019 (minus:BW (match_operand:BW 1 "register_operand" "0,0,0,0,0")
2020 (match_operand:BW 2 "general_operand" "r,Q>,J,N,g")))]
2021 "TARGET_V32"
2022 "@
2023 sub<m> %2,%0
2024 sub<m> %2,%0
2025 subq %2,%0
2026 addq %n2,%0
2027 sub<m> %2,%0"
2028 [(set_attr "slottable" "yes,yes,yes,yes,no")
2029 (set_attr "cc" "normal,normal,clobber,clobber,normal")])
0b85d816
HPN
2030\f
2031;; CRIS has some add/sub-with-sign/zero-extend instructions.
2032;; Although these perform sign/zero-extension to SImode, they are
2033;; equally applicable for the HImode case.
2034;; FIXME: Check; GCC should handle the widening.
2035;; Note that these must be located after the normal add/sub patterns,
2036;; so not to get constants into any less specific operands.
2037;;
2038;; Extend with add/sub and side-effect.
2039;;
2040;; ADDS/SUBS/ADDU/SUBU and BOUND, which needs a check for zero_extend
2041;;
2042;; adds/subs/addu/subu bound [rx=ry+rz.S]
0b85d816 2043
22c3c091
HPN
2044;; QImode to HImode
2045;; FIXME: GCC should widen.
0b85d816 2046
22c3c091
HPN
2047(define_insn "*extopqihi_side_biap"
2048 [(set (match_operand:HI 0 "register_operand" "=r,r")
2049 (match_operator:HI
2050 6 "cris_additive_operand_extend_operator"
2051 [(match_operand:HI 1 "register_operand" "0,0")
2052 (match_operator:HI
0b85d816
HPN
2053 7 "cris_extend_operator"
2054 [(mem:QI (plus:SI
2055 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
2056 (match_operand:SI 3 "const_int_operand" "n,n"))
2057 (match_operand:SI 4 "register_operand" "r,r")))])]))
2058 (set (match_operand:SI 5 "register_operand" "=*4,r")
2059 (plus:SI (mult:SI (match_dup 2)
2060 (match_dup 3))
2061 (match_dup 4)))]
22c3c091 2062 "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
0b85d816
HPN
2063 "@
2064 #
2065 %x6%e7.%m7 [%5=%4+%2%T3],%0")
2066
22c3c091 2067(define_insn "*extop<mode>si_side_biap"
0b85d816
HPN
2068 [(set (match_operand:SI 0 "register_operand" "=r,r")
2069 (match_operator:SI
2070 6 "cris_operand_extend_operator"
2071 [(match_operand:SI 1 "register_operand" "0,0")
2072 (match_operator:SI
2073 7 "cris_extend_operator"
22c3c091 2074 [(mem:BW (plus:SI
0b85d816
HPN
2075 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
2076 (match_operand:SI 3 "const_int_operand" "n,n"))
2077 (match_operand:SI 4 "register_operand" "r,r")))])]))
2078 (set (match_operand:SI 5 "register_operand" "=*4,r")
2079 (plus:SI (mult:SI (match_dup 2)
2080 (match_dup 3))
2081 (match_dup 4)))]
d2f55c5c 2082 "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[7]) == ZERO_EXTEND)
0b85d816
HPN
2083 && cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
2084 "@
2085 #
22c3c091 2086 %x6%e7<m> [%5=%4+%2%T3],%0")
0b85d816
HPN
2087\f
2088
2089;; [rx=ry+i]
0b85d816
HPN
2090
2091;; QImode to HImode
2092
2093(define_insn "*extopqihi_side"
1165f377 2094 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
0b85d816 2095 (match_operator:HI
d2f55c5c 2096 5 "cris_additive_operand_extend_operator"
1165f377 2097 [(match_operand:HI 1 "register_operand" "0,0,0,0,0")
0b85d816
HPN
2098 (match_operator:HI
2099 6 "cris_extend_operator"
2100 [(mem:QI
1165f377
HPN
2101 (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
2102 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")
0b85d816 2103 ))])]))
1165f377 2104 (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
0b85d816
HPN
2105 (plus:SI (match_dup 2)
2106 (match_dup 3)))]
d2f55c5c 2107 "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816 2108{
1165f377 2109 if ((which_alternative == 0 || which_alternative == 3)
991c42ac 2110 && (!CONST_INT_P (operands[3])
0b85d816
HPN
2111 || INTVAL (operands[3]) > 127
2112 || INTVAL (operands[3]) < -128
06cadf63
AS
2113 || satisfies_constraint_N (operands[3])
2114 || satisfies_constraint_J (operands[3])))
22c3c091 2115 return "#";
1165f377 2116 if (which_alternative == 4)
9c514326
HPN
2117 return "%x5%E6.%m6 [%4=%3%S2],%0";
2118 return "%x5%E6.%m6 [%4=%2%S3],%0";
22c3c091 2119})
0b85d816 2120
22c3c091 2121(define_insn "*extop<mode>si_side"
1165f377 2122 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
0b85d816
HPN
2123 (match_operator:SI
2124 5 "cris_operand_extend_operator"
1165f377 2125 [(match_operand:SI 1 "register_operand" "0,0,0,0,0")
0b85d816
HPN
2126 (match_operator:SI
2127 6 "cris_extend_operator"
22c3c091 2128 [(mem:BW
1165f377
HPN
2129 (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
2130 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")
0b85d816 2131 ))])]))
1165f377 2132 (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
0b85d816
HPN
2133 (plus:SI (match_dup 2)
2134 (match_dup 3)))]
2135 "(GET_CODE (operands[5]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND)
2136 && cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816 2137{
1165f377 2138 if ((which_alternative == 0 || which_alternative == 3)
991c42ac 2139 && (!CONST_INT_P (operands[3])
0b85d816
HPN
2140 || INTVAL (operands[3]) > 127
2141 || INTVAL (operands[3]) < -128
06cadf63
AS
2142 || satisfies_constraint_N (operands[3])
2143 || satisfies_constraint_J (operands[3])))
22c3c091 2144 return "#";
1165f377 2145 if (which_alternative == 4)
9c514326
HPN
2146 return "%x5%E6<m> [%4=%3%S2],%0";
2147 return "%x5%E6<m> [%4=%2%S3],%0";
22c3c091 2148})
0b85d816
HPN
2149\f
2150
2151;; As with op.S we may have to add special pattern to match commuted
45d5d09c 2152;; operands to adds/addu and bound
0b85d816
HPN
2153;;
2154;; adds/addu/bound [rx=ry+rz.S]
2155
2156;; QImode to HImode
2157;; FIXME: GCC should widen.
0b85d816
HPN
2158
2159(define_insn "*extopqihi_swap_side_biap"
2160 [(set (match_operand:HI 0 "register_operand" "=r,r")
d2f55c5c
HPN
2161 (plus:HI
2162 (match_operator:HI
2163 6 "cris_extend_operator"
2164 [(mem:QI (plus:SI
2165 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
2166 (match_operand:SI 3 "const_int_operand" "n,n"))
2167 (match_operand:SI 4 "register_operand" "r,r")))])
2168 (match_operand:HI 1 "register_operand" "0,0")))
0b85d816
HPN
2169 (set (match_operand:SI 5 "register_operand" "=*4,r")
2170 (plus:SI (mult:SI (match_dup 2)
2171 (match_dup 3))
2172 (match_dup 4)))]
d2f55c5c 2173 "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
0b85d816
HPN
2174 "@
2175 #
d2f55c5c 2176 add%e6.b [%5=%4+%2%T3],%0")
0b85d816 2177
22c3c091 2178(define_insn "*extop<mode>si_swap_side_biap"
0b85d816
HPN
2179 [(set (match_operand:SI 0 "register_operand" "=r,r")
2180 (match_operator:SI
2181 7 "cris_plus_or_bound_operator"
2182 [(match_operator:SI
2183 6 "cris_extend_operator"
22c3c091 2184 [(mem:BW (plus:SI
0b85d816
HPN
2185 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
2186 (match_operand:SI 3 "const_int_operand" "n,n"))
2187 (match_operand:SI 4 "register_operand" "r,r")))])
2188 (match_operand:SI 1 "register_operand" "0,0")]))
2189 (set (match_operand:SI 5 "register_operand" "=*4,r")
2190 (plus:SI (mult:SI (match_dup 2)
2191 (match_dup 3))
2192 (match_dup 4)))]
d2f55c5c 2193 "(GET_CODE (operands[7]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND)
0b85d816
HPN
2194 && cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
2195 "@
2196 #
9c514326 2197 %x7%E6<m> [%5=%4+%2%T3],%0")
0b85d816
HPN
2198\f
2199;; [rx=ry+i]
0b85d816
HPN
2200;; FIXME: GCC should widen.
2201
2202;; QImode to HImode
2203
2204(define_insn "*extopqihi_swap_side"
1165f377 2205 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
d2f55c5c
HPN
2206 (plus:HI
2207 (match_operator:HI
2208 5 "cris_extend_operator"
2209 [(mem:QI (plus:SI
1165f377
HPN
2210 (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
2211 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))])
2212 (match_operand:HI 1 "register_operand" "0,0,0,0,0")))
2213 (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
0b85d816
HPN
2214 (plus:SI (match_dup 2)
2215 (match_dup 3)))]
d2f55c5c 2216 "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816 2217{
1165f377 2218 if ((which_alternative == 0 || which_alternative == 3)
991c42ac 2219 && (!CONST_INT_P (operands[3])
0b85d816
HPN
2220 || INTVAL (operands[3]) > 127
2221 || INTVAL (operands[3]) < -128
06cadf63
AS
2222 || satisfies_constraint_N (operands[3])
2223 || satisfies_constraint_J (operands[3])))
22c3c091 2224 return "#";
1165f377
HPN
2225 if (which_alternative == 4)
2226 return "add%e5.b [%4=%3%S2],%0";
22c3c091
HPN
2227 return "add%e5.b [%4=%2%S3],%0";
2228})
0b85d816 2229
22c3c091 2230(define_insn "*extop<mode>si_swap_side"
1165f377 2231 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
0b85d816
HPN
2232 (match_operator:SI
2233 6 "cris_plus_or_bound_operator"
2234 [(match_operator:SI
2235 5 "cris_extend_operator"
22c3c091 2236 [(mem:BW (plus:SI
1165f377
HPN
2237 (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
2238 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))])
2239 (match_operand:SI 1 "register_operand" "0,0,0,0,0")]))
2240 (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
0b85d816
HPN
2241 (plus:SI (match_dup 2)
2242 (match_dup 3)))]
2243 "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[5]) == ZERO_EXTEND)
2244 && cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816 2245{
1165f377 2246 if ((which_alternative == 0 || which_alternative == 3)
991c42ac 2247 && (!CONST_INT_P (operands[3])
0b85d816
HPN
2248 || INTVAL (operands[3]) > 127
2249 || INTVAL (operands[3]) < -128
06cadf63
AS
2250 || satisfies_constraint_N (operands[3])
2251 || satisfies_constraint_J (operands[3])))
22c3c091 2252 return "#";
1165f377 2253 if (which_alternative == 4)
9c514326
HPN
2254 return \"%x6%E5.%m5 [%4=%3%S2],%0\";
2255 return "%x6%E5<m> [%4=%2%S3],%0";
22c3c091 2256})
0b85d816
HPN
2257\f
2258;; Extend versions (zero/sign) of normal add/sub (no side-effects).
0b85d816
HPN
2259
2260;; QImode to HImode
2261;; FIXME: GCC should widen.
2262
45d5d09c 2263(define_insn "*extopqihi_non_v32"
0b85d816
HPN
2264 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
2265 (match_operator:HI
d2f55c5c 2266 3 "cris_additive_operand_extend_operator"
0b85d816
HPN
2267 [(match_operand:HI 1 "register_operand" "0,0,0,r")
2268 (match_operator:HI
2269 4 "cris_extend_operator"
2270 [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])]))]
45d5d09c 2271 "!TARGET_V32 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
0b85d816
HPN
2272 && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
2273 "@
9c514326
HPN
2274 %x3%E4.%m4 %2,%0
2275 %x3%E4.%m4 %2,%0
2276 %x3%E4.%m4 %2,%0
2277 %x3%E4.%m4 %2,%1,%0"
0b85d816
HPN
2278 [(set_attr "slottable" "yes,yes,no,no")
2279 (set_attr "cc" "clobber")])
2280
45d5d09c
HPN
2281(define_insn "*extopqihi_v32"
2282 [(set (match_operand:HI 0 "register_operand" "=r,r")
2283 (match_operator:HI
2284 3 "cris_additive_operand_extend_operator"
2285 [(match_operand:HI 1 "register_operand" "0,0")
2286 (match_operator:HI
2287 4 "cris_extend_operator"
2288 [(match_operand:QI 2 "nonimmediate_operand" "r,m")])]))]
2289 "TARGET_V32"
2290 "%x3%e4.%m4 %2,%0"
2291 [(set_attr "slottable" "yes")
2292 (set_attr "cc" "clobber")])
2293
0b85d816
HPN
2294;; QImode to SImode
2295
45d5d09c 2296(define_insn "*extop<mode>si_non_v32"
0b85d816
HPN
2297 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
2298 (match_operator:SI
2299 3 "cris_operand_extend_operator"
2300 [(match_operand:SI 1 "register_operand" "0,0,0,r")
2301 (match_operator:SI
2302 4 "cris_extend_operator"
22c3c091 2303 [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])]))]
45d5d09c
HPN
2304 "!TARGET_V32
2305 && (GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
0b85d816
HPN
2306 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
2307 && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
2308 "@
9c514326
HPN
2309 %x3%E4<m> %2,%0
2310 %x3%E4<m> %2,%0
2311 %x3%E4<m> %2,%0
2312 %x3%E4<m> %2,%1,%0"
0b85d816 2313 [(set_attr "slottable" "yes,yes,no,no")])
0b85d816 2314
45d5d09c
HPN
2315(define_insn "*extop<mode>si_v32"
2316 [(set (match_operand:SI 0 "register_operand" "=r,r")
2317 (match_operator:SI
2318 3 "cris_additive_operand_extend_operator"
2319 [(match_operand:SI 1 "register_operand" "0,0")
2320 (match_operator:SI
2321 4 "cris_extend_operator"
2322 [(match_operand:BW 2 "nonimmediate_operand" "r,m")])]))]
2323 "TARGET_V32"
2324 "%x3%e4.%m4 %2,%0"
2325 [(set_attr "slottable" "yes")])
2326\f
0b85d816 2327;; As with the side-effect patterns, may have to have swapped operands for add.
45d5d09c 2328;; For commutative operands, these are the canonical forms.
0b85d816
HPN
2329
2330;; QImode to HImode
2331
45d5d09c 2332(define_insn "*addxqihi_swap_non_v32"
0b85d816 2333 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
d2f55c5c
HPN
2334 (plus:HI
2335 (match_operator:HI
2336 3 "cris_extend_operator"
2337 [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])
2338 (match_operand:HI 1 "register_operand" "0,0,0,r")))]
45d5d09c 2339 "!TARGET_V32 && operands[1] != frame_pointer_rtx"
0b85d816 2340 "@
d2f55c5c
HPN
2341 add%e3.b %2,%0
2342 add%e3.b %2,%0
2343 add%e3.b %2,%0
2344 add%e3.b %2,%1,%0"
0b85d816
HPN
2345 [(set_attr "slottable" "yes,yes,no,no")
2346 (set_attr "cc" "clobber")])
2347
45d5d09c
HPN
2348;; A case for v32, to catch the "addo" insn in addition to "adds". We
2349;; only care to match the canonical form; there should be no other.
2350
2351(define_insn "*addsbw_v32"
2352 [(set (match_operand:HI 0 "register_operand" "=r,r,!a")
2353 (plus:HI
2354 (sign_extend:HI
2355 (match_operand:QI 2 "nonimmediate_operand" "r,m,m"))
2356 (match_operand:HI 1 "register_operand" "0,0,r")))]
2357 "TARGET_V32"
2358 "@
2359 adds.b %2,%0
2360 adds.b %2,%0
2361 addo.b %2,%1,%0"
2362 [(set_attr "slottable" "yes")
2363 (set_attr "cc" "clobber,clobber,none")])
2364
2365(define_insn "*addubw_v32"
2366 [(set (match_operand:HI 0 "register_operand" "=r,r")
2367 (plus:HI
2368 (zero_extend:HI
2369 (match_operand:QI 2 "nonimmediate_operand" "r,m"))
2370 (match_operand:HI 1 "register_operand" "0,0")))]
2371 "TARGET_V32"
2372 "addu.b %2,%0"
2373 [(set_attr "slottable" "yes")
2374 (set_attr "cc" "clobber")])
2375
2376(define_insn "*extop<mode>si_swap_non_v32"
0b85d816
HPN
2377 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
2378 (match_operator:SI
2379 4 "cris_plus_or_bound_operator"
2380 [(match_operator:SI
2381 3 "cris_extend_operator"
22c3c091 2382 [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])
0b85d816 2383 (match_operand:SI 1 "register_operand" "0,0,0,r")]))]
45d5d09c
HPN
2384 "!TARGET_V32
2385 && (GET_CODE (operands[4]) != UMIN || GET_CODE (operands[3]) == ZERO_EXTEND)
0b85d816
HPN
2386 && operands[1] != frame_pointer_rtx"
2387 "@
9c514326
HPN
2388 %x4%E3<m> %2,%0
2389 %x4%E3<m> %2,%0
2390 %x4%E3<m> %2,%0
2391 %x4%E3<m> %2,%1,%0"
0b85d816 2392 [(set_attr "slottable" "yes,yes,no,no")])
45d5d09c
HPN
2393
2394(define_insn "*adds<mode>_v32"
2395 [(set (match_operand:SI 0 "register_operand" "=r,r,!a")
2396 (plus:SI
2397 (sign_extend:SI
2398 (match_operand:BW 2 "nonimmediate_operand" "r,m,m"))
2399 (match_operand:SI 1 "register_operand" "0,0,r")))]
2400 "TARGET_V32"
2401 "@
2402 adds<m> %2,%0
2403 adds<m> %2,%0
2404 addo<m> %2,%1,%0"
2405 [(set_attr "slottable" "yes")
2406 (set_attr "cc" "*,*,none")])
2407
2408(define_insn "*addu<mode>_v32"
2409 [(set (match_operand:SI 0 "register_operand" "=r,r")
2410 (plus:SI
2411 (zero_extend:SI
2412 (match_operand:BW 2 "nonimmediate_operand" "r,m"))
2413 (match_operand:SI 1 "register_operand" "0,0")))]
2414 "TARGET_V32 && operands[1] != frame_pointer_rtx"
2415 "addu<m> %2,%0"
2416 [(set_attr "slottable" "yes")])
2417
2418(define_insn "*bound<mode>_v32"
2419 [(set (match_operand:SI 0 "register_operand" "=r")
2420 (umin:SI
2421 (zero_extend:SI
2422 (match_operand:BW 2 "register_operand" "r"))
2423 (match_operand:SI 1 "register_operand" "0")))]
2424 "TARGET_V32 && operands[1] != frame_pointer_rtx"
2425 "bound<m> %2,%0"
2426 [(set_attr "slottable" "yes")])
0b85d816
HPN
2427\f
2428;; This is the special case when we use what corresponds to the
2429;; instruction above in "casesi". Do *not* change it to use the generic
2430;; pattern and "REG 15" as pc; I did that and it led to madness and
2431;; maintenance problems: Instead of (as imagined) recognizing and removing
2432;; or replacing this pattern with something simpler, other variant
2433;; patterns were recognized or combined, including some prefix variants
2434;; where the value in pc is not that of the next instruction (which means
2435;; this instruction actually *is* special and *should* be marked as such).
2436;; When switching from the "generic pattern match" approach to this simpler
2437;; approach, there were insignificant differences in gcc, ipps and
2438;; product code, somehow due to scratching reload behind the ear or
2439;; something. Testcase "gcc" looked .01% slower and 4 bytes bigger;
2440;; product code became .001% smaller but "looked better". The testcase
2441;; "ipps" was just different at register allocation).
2442;;
2443;; Assumptions in the jump optimizer forces us to use IF_THEN_ELSE in this
2444;; pattern with the default-label as the else, with the "if" being
2445;; index-is-less-than the max number of cases plus one. The default-label
2446;; is attached to the end of the case-table at time of output.
2447
2448(define_insn "*casesi_adds_w"
2449 [(set (pc)
2450 (if_then_else
2451 (ltu (match_operand:SI 0 "register_operand" "r")
2452 (match_operand:SI 1 "const_int_operand" "n"))
2453 (plus:SI (sign_extend:SI
2454 (mem:HI
2455 (plus:SI (mult:SI (match_dup 0) (const_int 2))
2456 (pc))))
2457 (pc))
2458 (label_ref (match_operand 2 "" ""))))
2459 (use (label_ref (match_operand 3 "" "")))]
45d5d09c 2460 "!TARGET_V32 && operands[0] != frame_pointer_rtx"
0b85d816
HPN
2461 "adds.w [$pc+%0.w],$pc"
2462 [(set_attr "cc" "clobber")])
45d5d09c
HPN
2463
2464;; For V32, we just have a jump, but we need to mark the table as used,
2465;; and the jump insn must have the if_then_else form expected by core
2466;; GCC. Since we don't want to prolong the lifetime of the original
2467;; index value, we compare against "unspec 0". It's a pity we have to
2468;; jump through to get the default label in place and to keep the jump
2469;; table around. FIXME: Look into it some time.
2470
2471(define_insn "*casesi_jump_v32"
2472 [(set (pc)
2473 (if_then_else
2474 (ltu (unspec [(const_int 0)] CRIS_UNSPEC_CASESI)
2475 (match_operand:SI 0 "const_int_operand" "n"))
2476 (match_operand:SI 1 "register_operand" "r")
2477 (label_ref (match_operand 2 "" ""))))
2478 (use (label_ref (match_operand 3 "" "")))]
2479 "TARGET_V32"
2480 "jump %1%#"
2481 [(set_attr "cc" "clobber")
2482 (set_attr "slottable" "has_slot")])
0b85d816
HPN
2483\f
2484;; Multiply instructions.
2485
2486;; Sometimes powers of 2 (which are normally canonicalized to a
2487;; left-shift) appear here, as a result of address reloading.
2488;; As a special, for values 3 and 5, we can match with an addi, so add those.
2489;;
2490;; FIXME: This may be unnecessary now.
2491;; Explicitly named for convenience of having a gen_... function.
2492
2493(define_insn "addi_mul"
2494 [(set (match_operand:SI 0 "register_operand" "=r")
2495 (mult:SI
2496 (match_operand:SI 1 "register_operand" "%0")
2497 (match_operand:SI 2 "const_int_operand" "n")))]
2498 "operands[0] != frame_pointer_rtx
2499 && operands[1] != frame_pointer_rtx
991c42ac 2500 && CONST_INT_P (operands[2])
0b85d816
HPN
2501 && (INTVAL (operands[2]) == 2
2502 || INTVAL (operands[2]) == 4 || INTVAL (operands[2]) == 3
2503 || INTVAL (operands[2]) == 5)"
0b85d816
HPN
2504{
2505 if (INTVAL (operands[2]) == 2)
22c3c091 2506 return "lslq 1,%0";
0b85d816 2507 else if (INTVAL (operands[2]) == 4)
22c3c091 2508 return "lslq 2,%0";
0b85d816 2509 else if (INTVAL (operands[2]) == 3)
22c3c091 2510 return "addi %0.w,%0";
0b85d816 2511 else if (INTVAL (operands[2]) == 5)
22c3c091
HPN
2512 return "addi %0.d,%0";
2513 return "BAD: adr_mulsi: %0=%1*%2";
2514}
0b85d816
HPN
2515[(set_attr "slottable" "yes")
2516 ;; No flags are changed if this insn is "addi", but it does not seem
2517 ;; worth the trouble to distinguish that to the lslq cases.
2518 (set_attr "cc" "clobber")])
2519
2520;; The addi insn as it is normally used.
2521
dd5a833e 2522;; Make the ACR alternative taste bad enough to not choose it as a
45d5d09c
HPN
2523;; preference to avoid spilling problems (unwind-dw2-fde.c at build).
2524;; FIXME: Revisit for new register allocator.
2525
0b85d816 2526(define_insn "*addi"
45d5d09c 2527 [(set (match_operand:SI 0 "register_operand" "=r,!a")
0b85d816 2528 (plus:SI
45d5d09c
HPN
2529 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
2530 (match_operand:SI 3 "const_int_operand" "n,n"))
2531 (match_operand:SI 1 "register_operand" "0,r")))]
0b85d816
HPN
2532 "operands[0] != frame_pointer_rtx
2533 && operands[1] != frame_pointer_rtx
991c42ac 2534 && CONST_INT_P (operands[3])
0b85d816
HPN
2535 && (INTVAL (operands[3]) == 1
2536 || INTVAL (operands[3]) == 2 || INTVAL (operands[3]) == 4)"
45d5d09c
HPN
2537 "@
2538 addi %2%T3,%0
2539 addi %2%T3,%1,%0"
0b85d816
HPN
2540 [(set_attr "slottable" "yes")
2541 (set_attr "cc" "none")])
2542
2543;; The mstep instruction. Probably not useful by itself; it's to
2544;; non-linear wrt. the other insns. We used to expand to it, so at least
2545;; it's correct.
2546
2547(define_insn "mstep_shift"
2548 [(set (match_operand:SI 0 "register_operand" "=r")
2549 (if_then_else:SI
2550 (lt:SI (cc0) (const_int 0))
2551 (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
2552 (const_int 1))
2553 (match_operand:SI 2 "register_operand" "r"))
2554 (ashift:SI (match_operand:SI 3 "register_operand" "0")
2555 (const_int 1))))]
45d5d09c 2556 "!TARGET_V32"
0b85d816
HPN
2557 "mstep %2,%0"
2558 [(set_attr "slottable" "yes")])
2559
2560;; When illegitimate addresses are legitimized, sometimes gcc forgets
2561;; to canonicalize the multiplications.
2562;;
2563;; FIXME: Check gcc > 2.7.2, remove and possibly fix in gcc.
2564
2565(define_insn "mstep_mul"
2566 [(set (match_operand:SI 0 "register_operand" "=r")
2567 (if_then_else:SI
2568 (lt:SI (cc0) (const_int 0))
2569 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "0")
2570 (const_int 2))
2571 (match_operand:SI 2 "register_operand" "r"))
2572 (mult:SI (match_operand:SI 3 "register_operand" "0")
2573 (const_int 2))))]
45d5d09c
HPN
2574 "!TARGET_V32
2575 && operands[0] != frame_pointer_rtx
0b85d816
HPN
2576 && operands[1] != frame_pointer_rtx
2577 && operands[2] != frame_pointer_rtx
2578 && operands[3] != frame_pointer_rtx"
2579 "mstep %2,%0"
2580 [(set_attr "slottable" "yes")])
2581
22c3c091
HPN
2582(define_insn "<u>mul<s><mode>3"
2583 [(set (match_operand:WD 0 "register_operand" "=r")
2584 (mult:WD
2585 (szext:WD (match_operand:<S> 1 "register_operand" "%0"))
2586 (szext:WD (match_operand:<S> 2 "register_operand" "r"))))
f60c7155 2587 (clobber (match_scratch:SI 3 "=h"))]
0b85d816 2588 "TARGET_HAS_MUL_INSNS"
22c3c091 2589 "%!mul<su><mm> %2,%0"
86da66b5 2590 [(set (attr "slottable")
bf0b8cbe 2591 (if_then_else (match_test "TARGET_MUL_BUG")
86da66b5
HPN
2592 (const_string "no")
2593 (const_string "yes")))
22c3c091
HPN
2594 ;; For umuls.[bwd] it's just N unusable here, but let's be safe.
2595 ;; For muls.b, this really extends to SImode, so cc should be
2596 ;; considered clobbered.
2597 ;; For muls.w, it's just N unusable here, but let's be safe.
0b85d816
HPN
2598 (set_attr "cc" "clobber")])
2599
2600;; Note that gcc does not make use of such a thing as umulqisi3. It gets
2601;; confused and will erroneously use it instead of umulhisi3, failing (at
2602;; least) gcc.c-torture/execute/arith-rand.c at all optimization levels.
2603;; Inspection of optab code shows that there must be only one widening
2604;; multiplication per mode widened to.
2605
2606(define_insn "mulsi3"
2607 [(set (match_operand:SI 0 "register_operand" "=r")
ef6201a6 2608 (mult:SI (match_operand:SI 1 "register_operand" "%0")
f60c7155
HPN
2609 (match_operand:SI 2 "register_operand" "r")))
2610 (clobber (match_scratch:SI 3 "=h"))]
0b85d816 2611 "TARGET_HAS_MUL_INSNS"
86da66b5
HPN
2612 "%!muls.d %2,%0"
2613 [(set (attr "slottable")
bf0b8cbe 2614 (if_then_else (match_test "TARGET_MUL_BUG")
86da66b5
HPN
2615 (const_string "no")
2616 (const_string "yes")))
0b85d816
HPN
2617 ;; Just N unusable here, but let's be safe.
2618 (set_attr "cc" "clobber")])
2619\f
2620;; A few multiply variations.
2621
0b85d816
HPN
2622;; When needed, we can get the high 32 bits from the overflow
2623;; register. We don't care to split and optimize these.
2624;;
2625;; Note that cc0 is still valid after the move-from-overflow-register
2626;; insn; no special precaution need to be taken in cris_notice_update_cc.
2627
22c3c091 2628(define_insn "<u>mulsidi3"
0b85d816
HPN
2629 [(set (match_operand:DI 0 "register_operand" "=r")
2630 (mult:DI
22c3c091
HPN
2631 (szext:DI (match_operand:SI 1 "register_operand" "%0"))
2632 (szext:DI (match_operand:SI 2 "register_operand" "r"))))
f60c7155 2633 (clobber (match_scratch:SI 3 "=h"))]
0b85d816 2634 "TARGET_HAS_MUL_INSNS"
22c3c091 2635 "%!mul<su>.d %2,%M0\;move $mof,%H0")
0b85d816 2636
f60c7155
HPN
2637;; These two patterns may be expressible by other means, perhaps by making
2638;; [u]?mulsidi3 a define_expand.
2639
2640;; Due to register allocation braindamage, the clobber 1,2 alternatives
2641;; cause a move into the clobbered register *before* the insn, then
2642;; after the insn, mof is moved too, rather than the clobber assigned
2643;; the last mof target. This became apparent when making MOF and SRP
2644;; visible registers, with the necessary tweak to smulsi3_highpart.
2645;; Because these patterns are used in division by constants, that damage
2646;; is visible (ipps regression tests). Therefore the last two
2647;; alternatives, "helping" reload to avoid an unnecessary move, but
2648;; punished by force of one "?". Check code from "int d (int a) {return
2649;; a / 1000;}" and unsigned. FIXME: Comment above was for 3.2, revisit.
0b85d816 2650
22c3c091 2651(define_insn "<su>mulsi3_highpart"
45d5d09c 2652 [(set (match_operand:SI 0 "register_operand" "=h,h,?r,?r")
0b85d816
HPN
2653 (truncate:SI
2654 (lshiftrt:DI
2655 (mult:DI
22c3c091
HPN
2656 (szext:DI (match_operand:SI 1 "register_operand" "r,r,0,r"))
2657 (szext:DI (match_operand:SI 2 "register_operand" "r,r,r,0")))
0b85d816 2658 (const_int 32))))
f60c7155 2659 (clobber (match_scratch:SI 3 "=1,2,h,h"))]
0b85d816 2660 "TARGET_HAS_MUL_INSNS"
f60c7155 2661 "@
22c3c091
HPN
2662 %!mul<su>.d %2,%1
2663 %!mul<su>.d %1,%2
2664 %!mul<su>.d %2,%1\;move $mof,%0
2665 %!mul<su>.d %1,%2\;move $mof,%0"
f60c7155
HPN
2666 [(set_attr "slottable" "yes,yes,no,no")
2667 (set_attr "cc" "clobber")])
0b85d816
HPN
2668\f
2669;; Divide and modulus instructions. CRIS only has a step instruction.
2670
2671(define_insn "dstep_shift"
2672 [(set (match_operand:SI 0 "register_operand" "=r")
2673 (if_then_else:SI
2674 (geu:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
2675 (const_int 1))
2676 (match_operand:SI 2 "register_operand" "r"))
2677 (minus:SI (ashift:SI (match_operand:SI 3 "register_operand" "0")
2678 (const_int 1))
2679 (match_operand:SI 4 "register_operand" "2"))
2680 (ashift:SI (match_operand:SI 5 "register_operand" "0")
2681 (const_int 1))))]
2682 ""
2683 "dstep %2,%0"
45d5d09c
HPN
2684 [(set_attr "slottable" "yes")
2685 (set_attr "cc" "noov32")])
0b85d816
HPN
2686
2687;; Here's a variant with mult instead of ashift.
2688;;
2689;; FIXME: This should be investigated. Which one matches through combination?
2690
2691(define_insn "dstep_mul"
2692 [(set (match_operand:SI 0 "register_operand" "=r")
2693 (if_then_else:SI
2694 (geu:SI (mult:SI (match_operand:SI 1 "register_operand" "0")
2695 (const_int 2))
2696 (match_operand:SI 2 "register_operand" "r"))
2697 (minus:SI (mult:SI (match_operand:SI 3 "register_operand" "0")
2698 (const_int 2))
2699 (match_operand:SI 4 "register_operand" "2"))
2700 (mult:SI (match_operand:SI 5 "register_operand" "0")
2701 (const_int 2))))]
2702 "operands[0] != frame_pointer_rtx
2703 && operands[1] != frame_pointer_rtx
2704 && operands[2] != frame_pointer_rtx
2705 && operands[3] != frame_pointer_rtx"
2706 "dstep %2,%0"
45d5d09c
HPN
2707 [(set_attr "slottable" "yes")
2708 (set_attr "cc" "noov32")])
0b85d816
HPN
2709\f
2710;; Logical operators.
2711
2712;; Bitwise "and".
2713
2714;; There is no use in defining "anddi3", because gcc can expand this by
2715;; itself, and make reasonable code without interference.
2716
2717;; If the first operand is memory or a register and is the same as the
2718;; second operand, and the third operand is -256 or -65536, we can use
2719;; CLEAR instead. Or, if the first operand is a register, and the third
2720;; operand is 255 or 65535, we can zero_extend.
f5143c46 2721;; GCC isn't smart enough to recognize these cases (yet), and they seem
0b85d816
HPN
2722;; to be common enough to be worthwhile.
2723;; FIXME: This should be made obsolete.
2724
2725(define_expand "andsi3"
2726 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2727 (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
2728 (match_operand:SI 2 "general_operand" "")))]
2729 ""
0b85d816 2730{
991c42ac 2731 if (! (CONST_INT_P (operands[2])
0b85d816
HPN
2732 && (((INTVAL (operands[2]) == -256
2733 || INTVAL (operands[2]) == -65536)
2734 && rtx_equal_p (operands[1], operands[0]))
2735 || ((INTVAL (operands[2]) == 255
2736 || INTVAL (operands[2]) == 65535)
2737 && REG_P (operands[0])))))
2738 {
2739 /* Make intermediate steps if operand0 is not a register or
2740 operand1 is not a register, and hope that the reload pass will
2741 make something useful out of it. Note that the operands are
2742 *not* canonicalized. For the moment, I chicken out on this,
2743 because all or most ports do not describe 'and' with
2744 canonicalized operands, and I seem to remember magic in reload,
2745 checking that operand1 has constraint '%0', in which case
2746 operand0 and operand1 must have similar predicates.
2747 FIXME: Investigate. */
2748 rtx reg0 = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
2749 rtx reg1 = operands[1];
2750
2751 if (! REG_P (reg1))
2752 {
2753 emit_move_insn (reg0, reg1);
2754 reg1 = reg0;
2755 }
2756
f7df4a84 2757 emit_insn (gen_rtx_SET (reg0, gen_rtx_AND (SImode, reg1, operands[2])));
0b85d816
HPN
2758
2759 /* Make sure we get the right *final* destination. */
2760 if (! REG_P (operands[0]))
2761 emit_move_insn (operands[0], reg0);
2762
2763 DONE;
2764 }
22c3c091 2765})
0b85d816
HPN
2766
2767;; Some special cases of andsi3.
2768
2769(define_insn "*andsi_movu"
2770 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
428eae94 2771 (and:SI (match_operand:SI 1 "nonimmediate_operand" "%r,Q,To")
0b85d816 2772 (match_operand:SI 2 "const_int_operand" "n,n,n")))]
f38a62ff 2773 "(INTVAL (operands[2]) == 255 || INTVAL (operands[2]) == 65535)
c3e786e7 2774 && !side_effects_p (operands[1])"
0b85d816
HPN
2775 "movu.%z2 %1,%0"
2776 [(set_attr "slottable" "yes,yes,no")])
2777
2778(define_insn "*andsi_clear"
f38a62ff 2779 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,Q,Q,To,To")
0b85d816
HPN
2780 (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0,0,0")
2781 (match_operand:SI 2 "const_int_operand" "P,n,P,n,P,n")))]
f38a62ff 2782 "(INTVAL (operands[2]) == -65536 || INTVAL (operands[2]) == -256)
c3e786e7 2783 && !side_effects_p (operands[0])"
0b85d816
HPN
2784 "@
2785 cLear.b %0
2786 cLear.w %0
2787 cLear.b %0
2788 cLear.w %0
2789 cLear.b %0
2790 cLear.w %0"
2791 [(set_attr "slottable" "yes,yes,yes,yes,no,no")
2792 (set_attr "cc" "none")])
2793
2794;; This is a catch-all pattern, taking care of everything that was not
2795;; matched in the insns above.
2796;;
2797;; Sidenote: the tightening from "nonimmediate_operand" to
2798;; "register_operand" for operand 1 actually increased the register
2799;; pressure (worse code). That will hopefully change with an
2800;; improved reload pass.
2801
45d5d09c 2802(define_insn "*expanded_andsi_non_v32"
23369bef
HPN
2803 [(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r")
2804 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,r")
2805 (match_operand:SI 2 "general_operand" "I,r,Q>,g,!To")))]
45d5d09c 2806 "!TARGET_V32"
0b85d816
HPN
2807 "@
2808 andq %2,%0
2809 and.d %2,%0
2810 and.d %2,%0
2811 and.d %2,%0
2812 and.d %2,%1,%0"
2813 [(set_attr "slottable" "yes,yes,yes,no,no")])
45d5d09c
HPN
2814
2815(define_insn "*expanded_andsi_v32"
2816 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
2817 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
2818 (match_operand:SI 2 "general_operand" "I,r,Q>,g")))]
2819 "TARGET_V32"
2820 "@
2821 andq %2,%0
2822 and.d %2,%0
2823 and.d %2,%0
2824 and.d %2,%0"
2825 [(set_attr "slottable" "yes,yes,yes,no")
2826 (set_attr "cc" "noov32")])
0b85d816
HPN
2827\f
2828;; For both QI and HI we may use the quick patterns. This results in
2829;; useless condition codes, but that is used rarely enough for it to
2830;; normally be a win (could check ahead for use of cc0, but seems to be
2831;; more pain than win).
2832
2833;; FIXME: See note for andsi3
2834
2835(define_expand "andhi3"
2836 [(set (match_operand:HI 0 "nonimmediate_operand" "")
2837 (and:HI (match_operand:HI 1 "nonimmediate_operand" "")
2838 (match_operand:HI 2 "general_operand" "")))]
2839 ""
0b85d816 2840{
991c42ac 2841 if (! (CONST_INT_P (operands[2])
0b85d816
HPN
2842 && (((INTVAL (operands[2]) == -256
2843 || INTVAL (operands[2]) == 65280)
2844 && rtx_equal_p (operands[1], operands[0]))
2845 || (INTVAL (operands[2]) == 255
2846 && REG_P (operands[0])))))
2847 {
2848 /* See comment for andsi3. */
2849 rtx reg0 = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (HImode);
2850 rtx reg1 = operands[1];
2851
2852 if (! REG_P (reg1))
2853 {
2854 emit_move_insn (reg0, reg1);
2855 reg1 = reg0;
2856 }
2857
f7df4a84 2858 emit_insn (gen_rtx_SET (reg0, gen_rtx_AND (HImode, reg1, operands[2])));
0b85d816
HPN
2859
2860 /* Make sure we get the right destination. */
2861 if (! REG_P (operands[0]))
2862 emit_move_insn (operands[0], reg0);
2863
2864 DONE;
2865 }
22c3c091 2866})
0b85d816
HPN
2867
2868;; Some fast andhi3 special cases.
2869
2870(define_insn "*andhi_movu"
2871 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
428eae94 2872 (and:HI (match_operand:HI 1 "nonimmediate_operand" "r,Q,To")
0b85d816 2873 (const_int 255)))]
c3e786e7 2874 "!side_effects_p (operands[1])"
0b85d816
HPN
2875 "mOvu.b %1,%0"
2876 [(set_attr "slottable" "yes,yes,no")])
2877
f38a62ff
HPN
2878(define_insn "*andhi_clear"
2879 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,Q,To")
0b85d816
HPN
2880 (and:HI (match_operand:HI 1 "nonimmediate_operand" "0,0,0")
2881 (const_int -256)))]
c3e786e7 2882 "!side_effects_p (operands[0])"
0b85d816
HPN
2883 "cLear.b %0"
2884 [(set_attr "slottable" "yes,yes,no")
2885 (set_attr "cc" "none")])
2886
2887;; Catch-all andhi3 pattern.
2888
45d5d09c 2889(define_insn "*expanded_andhi_non_v32"
23369bef
HPN
2890 [(set (match_operand:HI 0 "register_operand" "=r,r,r, r,r,r,r")
2891 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0, 0,0,0,r")
2892 (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))]
0b85d816
HPN
2893
2894;; Sidenote: the tightening from "general_operand" to
2895;; "register_operand" for operand 1 actually increased the register
2896;; pressure (worse code). That will hopefully change with an
2897;; improved reload pass.
2898
45d5d09c 2899 "!TARGET_V32"
0b85d816
HPN
2900 "@
2901 andq %2,%0
2902 and.w %2,%0
2903 and.w %2,%0
2904 and.w %2,%0
2905 anDq %b2,%0
2906 and.w %2,%0
2907 and.w %2,%1,%0"
2908 [(set_attr "slottable" "yes,yes,yes,no,yes,no,no")
2909 (set_attr "cc" "clobber,normal,normal,normal,clobber,normal,normal")])
2910
45d5d09c
HPN
2911(define_insn "*expanded_andhi_v32"
2912 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r")
2913 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
2914 (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g")))]
2915 "TARGET_V32"
2916 "@
2917 andq %2,%0
2918 and.w %2,%0
2919 and.w %2,%0
2920 and.w %2,%0
2921 anDq %b2,%0
2922 and.w %2,%0"
2923 [(set_attr "slottable" "yes,yes,yes,no,yes,no")
2924 (set_attr "cc" "clobber,noov32,noov32,noov32,clobber,noov32")])
2925
0b85d816
HPN
2926;; A strict_low_part pattern.
2927
d7173593
HPN
2928;; Note the use of (match_dup 0) for the first operand of the operation
2929;; here. Reload can't handle an operand pair where one is read-write
2930;; and must match a read, like in:
2931;; (insn 80 79 81 4
2932;; (set (strict_low_part
2933;; (subreg:QI (reg/v:SI 0 r0 [orig:36 data ] [36]) 0))
2934;; (and:QI
2935;; (subreg:QI (reg:SI 15 acr [orig:27 D.7531 ] [27]) 0)
2936;; (const_int -64 [0xf..fc0]))) x.c:126 147 {*andqi_lowpart_v32}
2937;; (nil))
2938;; In theory, it could reload this as a movstrictqi of the register
2939;; operand at the and:QI to the destination register and change the
2940;; and:QI operand to the same as the read-write output operand and the
2941;; result would be recognized, but it doesn't recognize that's a valid
2942;; reload for a strict_low_part-destination; it just sees a "+" at the
2943;; destination constraints. Better than adding complexity to reload is
2944;; to follow the lead of m68k (see comment that begins with "These insns
2945;; must use MATCH_DUP") since prehistoric times and make it just a
2946;; match_dup. FIXME: a sanity-check in gen* to refuse an insn with
2947;; input-constraints matching input-output-constraints, e.g. "+r" <- "0".
2948
45d5d09c 2949(define_insn "*andhi_lowpart_non_v32"
0b85d816 2950 [(set (strict_low_part
d7173593
HPN
2951 (match_operand:HI 0 "register_operand" "+r,r,r"))
2952 (and:HI (match_dup 0)
2953 (match_operand:HI 1 "general_operand" "r,Q>,g")))]
45d5d09c 2954 "!TARGET_V32"
0b85d816 2955 "@
d7173593
HPN
2956 and.w %1,%0
2957 and.w %1,%0
2958 and.w %1,%0"
2959 [(set_attr "slottable" "yes,yes,no")])
45d5d09c
HPN
2960
2961(define_insn "*andhi_lowpart_v32"
2962 [(set (strict_low_part
d7173593
HPN
2963 (match_operand:HI 0 "register_operand" "+r,r,r"))
2964 (and:HI (match_dup 0)
2965 (match_operand:HI 1 "general_operand" "r,Q>,g")))]
45d5d09c
HPN
2966 "TARGET_V32"
2967 "@
d7173593
HPN
2968 and.w %1,%0
2969 and.w %1,%0
2970 and.w %1,%0"
2971 [(set_attr "slottable" "yes,yes,no")
2972 (set_attr "cc" "noov32")])
0b85d816 2973\f
45d5d09c
HPN
2974(define_expand "andqi3"
2975 [(set (match_operand:QI 0 "register_operand")
2976 (and:QI (match_operand:QI 1 "register_operand")
2977 (match_operand:QI 2 "general_operand")))]
2978 ""
2979 "")
2980
2981(define_insn "*andqi3_non_v32"
23369bef
HPN
2982 [(set (match_operand:QI 0 "register_operand" "=r,r,r, r,r,r")
2983 (and:QI (match_operand:QI 1 "register_operand" "%0,0,0, 0,0,r")
2984 (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))]
45d5d09c 2985 "!TARGET_V32"
0b85d816
HPN
2986 "@
2987 andq %2,%0
2988 and.b %2,%0
2989 and.b %2,%0
2990 andQ %b2,%0
2991 and.b %2,%0
2992 and.b %2,%1,%0"
2993 [(set_attr "slottable" "yes,yes,yes,yes,no,no")
2994 (set_attr "cc" "clobber,normal,normal,clobber,normal,normal")])
2995
45d5d09c
HPN
2996(define_insn "*andqi3_v32"
2997 [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r")
2998 (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0")
2999 (match_operand:QI 2 "general_operand" "I,r,Q>,O,g")))]
3000 "TARGET_V32"
3001 "@
3002 andq %2,%0
3003 and.b %2,%0
3004 and.b %2,%0
3005 andQ %b2,%0
3006 and.b %2,%0"
3007 [(set_attr "slottable" "yes,yes,yes,yes,no")
3008 (set_attr "cc" "clobber,noov32,noov32,clobber,noov32")])
3009
3010(define_insn "*andqi_lowpart_non_v32"
0b85d816 3011 [(set (strict_low_part
d7173593
HPN
3012 (match_operand:QI 0 "register_operand" "+r,r,r"))
3013 (and:QI (match_dup 0)
3014 (match_operand:QI 1 "general_operand" "r,Q>,g")))]
45d5d09c 3015 "!TARGET_V32"
0b85d816 3016 "@
d7173593
HPN
3017 and.b %1,%0
3018 and.b %1,%0
3019 and.b %1,%0"
3020 [(set_attr "slottable" "yes,yes,no")])
45d5d09c
HPN
3021
3022(define_insn "*andqi_lowpart_v32"
3023 [(set (strict_low_part
d7173593
HPN
3024 (match_operand:QI 0 "register_operand" "+r,r,r"))
3025 (and:QI (match_dup 0)
3026 (match_operand:QI 1 "general_operand" "r,Q>,g")))]
45d5d09c
HPN
3027 "TARGET_V32"
3028 "@
d7173593
HPN
3029 and.b %1,%0
3030 and.b %1,%0
3031 and.b %1,%0"
3032 [(set_attr "slottable" "yes,yes,no")
3033 (set_attr "cc" "noov32")])
0b85d816
HPN
3034\f
3035;; Bitwise or.
3036
3037;; Same comment as anddi3 applies here - no need for such a pattern.
3038
3039;; It seems there's no need to jump through hoops to get good code such as
3040;; with andsi3.
3041
45d5d09c
HPN
3042(define_expand "ior<mode>3"
3043 [(set (match_operand:BWD 0 "register_operand")
3044 (ior:BWD (match_operand:BWD 1 "register_operand")
3045 (match_operand:BWD 2 "general_operand")))]
3046 ""
3047 "")
3048
3049(define_insn "*iorsi3_non_v32"
23369bef
HPN
3050 [(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r,r")
3051 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,0,r")
3052 (match_operand:SI 2 "general_operand" "I, r,Q>,n,g,!To")))]
45d5d09c 3053 "!TARGET_V32"
0b85d816
HPN
3054 "@
3055 orq %2,%0
3056 or.d %2,%0
3057 or.d %2,%0
3058 oR.%s2 %2,%0
3059 or.d %2,%0
3060 or.d %2,%1,%0"
3061 [(set_attr "slottable" "yes,yes,yes,no,no,no")
3062 (set_attr "cc" "normal,normal,normal,clobber,normal,normal")])
3063
45d5d09c
HPN
3064(define_insn "*iorsi3_v32"
3065 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
3066 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")
3067 (match_operand:SI 2 "general_operand" "I,r,Q>,n,g")))]
3068 "TARGET_V32"
3069 "@
3070 orq %2,%0
3071 or.d %2,%0
3072 or.d %2,%0
3073 oR.%s2 %2,%0
3074 or.d %2,%0"
3075 [(set_attr "slottable" "yes,yes,yes,no,no")
3076 (set_attr "cc" "noov32,noov32,noov32,clobber,noov32")])
3077
3078(define_insn "*iorhi3_non_v32"
23369bef
HPN
3079 [(set (match_operand:HI 0 "register_operand" "=r,r,r, r,r,r,r")
3080 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0, 0,0,0,r")
3081 (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))]
45d5d09c 3082 "!TARGET_V32"
0b85d816
HPN
3083 "@
3084 orq %2,%0
3085 or.w %2,%0
3086 or.w %2,%0
3087 or.w %2,%0
3088 oRq %b2,%0
3089 or.w %2,%0
3090 or.w %2,%1,%0"
3091 [(set_attr "slottable" "yes,yes,yes,no,yes,no,no")
3092 (set_attr "cc" "clobber,normal,normal,normal,clobber,normal,normal")])
3093
45d5d09c
HPN
3094(define_insn "*iorhi3_v32"
3095 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r")
3096 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
3097 (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g")))]
3098 "TARGET_V32"
3099 "@
3100 orq %2,%0
3101 or.w %2,%0
3102 or.w %2,%0
3103 or.w %2,%0
3104 oRq %b2,%0
3105 or.w %2,%0"
3106 [(set_attr "slottable" "yes,yes,yes,no,yes,no")
3107 (set_attr "cc" "clobber,noov32,noov32,noov32,clobber,noov32")])
3108
3109(define_insn "*iorqi3_non_v32"
23369bef
HPN
3110 [(set (match_operand:QI 0 "register_operand" "=r,r,r, r,r,r")
3111 (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0, 0,0,r")
3112 (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))]
45d5d09c 3113 "!TARGET_V32"
0b85d816
HPN
3114 "@
3115 orq %2,%0
3116 or.b %2,%0
3117 or.b %2,%0
3118 orQ %b2,%0
3119 or.b %2,%0
3120 or.b %2,%1,%0"
3121 [(set_attr "slottable" "yes,yes,yes,yes,no,no")
3122 (set_attr "cc" "clobber,normal,normal,clobber,normal,normal")])
45d5d09c
HPN
3123
3124(define_insn "*iorqi3_v32"
3125 [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r")
3126 (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0")
3127 (match_operand:QI 2 "general_operand" "I,r,Q>,O,g")))]
3128 "TARGET_V32"
3129 "@
3130 orq %2,%0
3131 or.b %2,%0
3132 or.b %2,%0
3133 orQ %b2,%0
3134 or.b %2,%0"
3135 [(set_attr "slottable" "yes,yes,yes,yes,no")
3136 (set_attr "cc" "clobber,noov32,noov32,clobber,noov32")])
0b85d816
HPN
3137\f
3138;; Exclusive-or
3139
3140;; See comment about "anddi3" for xordi3 - no need for such a pattern.
22c3c091 3141;; FIXME: Do we really need the shorter variants?
0b85d816
HPN
3142
3143(define_insn "xorsi3"
3144 [(set (match_operand:SI 0 "register_operand" "=r")
3145 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3146 (match_operand:SI 2 "register_operand" "r")))]
3147 ""
3148 "xor %2,%0"
45d5d09c
HPN
3149 [(set_attr "slottable" "yes")
3150 (set_attr "cc" "noov32")])
0b85d816 3151
22c3c091
HPN
3152(define_insn "xor<mode>3"
3153 [(set (match_operand:BW 0 "register_operand" "=r")
3154 (xor:BW (match_operand:BW 1 "register_operand" "%0")
3155 (match_operand:BW 2 "register_operand" "r")))]
0b85d816
HPN
3156 ""
3157 "xor %2,%0"
3158 [(set_attr "slottable" "yes")
3159 (set_attr "cc" "clobber")])
3160\f
3161;; Negation insns.
3162
3163;; Questionable use, here mostly as a (slightly usable) define_expand
3164;; example.
3165
3166(define_expand "negsf2"
3167 [(set (match_dup 2)
3168 (match_dup 3))
3169 (parallel [(set (match_operand:SF 0 "register_operand" "=r")
3170 (neg:SF (match_operand:SF 1
3171 "register_operand" "0")))
3172 (use (match_dup 2))])]
3173 ""
0b85d816
HPN
3174{
3175 operands[2] = gen_reg_rtx (SImode);
3176 operands[3] = GEN_INT (1 << 31);
22c3c091 3177})
0b85d816
HPN
3178
3179(define_insn "*expanded_negsf2"
3180 [(set (match_operand:SF 0 "register_operand" "=r")
3181 (neg:SF (match_operand:SF 1 "register_operand" "0")))
3182 (use (match_operand:SI 2 "register_operand" "r"))]
3183 ""
3184 "xor %2,%0"
3185 [(set_attr "slottable" "yes")])
3186
3187;; No "negdi2" although we could make one up that may be faster than
3188;; the one in libgcc.
3189
22c3c091
HPN
3190(define_insn "neg<mode>2"
3191 [(set (match_operand:BWD 0 "register_operand" "=r")
3192 (neg:BWD (match_operand:BWD 1 "register_operand" "r")))]
0b85d816 3193 ""
22c3c091 3194 "neg<m> %1,%0"
0b85d816
HPN
3195 [(set_attr "slottable" "yes")])
3196\f
3197;; One-complements.
3198
3199;; See comment on anddi3 - no need for a DImode pattern.
22c3c091 3200;; See also xor comment.
0b85d816
HPN
3201
3202(define_insn "one_cmplsi2"
3203 [(set (match_operand:SI 0 "register_operand" "=r")
3204 (not:SI (match_operand:SI 1 "register_operand" "0")))]
3205 ""
3206 "not %0"
45d5d09c
HPN
3207 [(set_attr "slottable" "yes")
3208 (set_attr "cc" "noov32")])
0b85d816 3209
22c3c091
HPN
3210(define_insn "one_cmpl<mode>2"
3211 [(set (match_operand:BW 0 "register_operand" "=r")
3212 (not:BW (match_operand:BW 1 "register_operand" "0")))]
0b85d816
HPN
3213 ""
3214 "not %0"
3215 [(set_attr "slottable" "yes")
3216 (set_attr "cc" "clobber")])
3217\f
22c3c091 3218;; Arithmetic/Logical shift right (and SI left).
0b85d816 3219
22c3c091 3220(define_insn "<shlr>si3"
0b85d816 3221 [(set (match_operand:SI 0 "register_operand" "=r")
22c3c091 3222 (shift:SI (match_operand:SI 1 "register_operand" "0")
f49e46d8 3223 (match_operand:SI 2 "nonmemory_operand" "Kcr")))]
0b85d816 3224 ""
0b85d816
HPN
3225{
3226 if (REG_S_P (operands[2]))
22c3c091 3227 return "<slr>.d %2,%0";
0b85d816 3228
22c3c091
HPN
3229 return "<slr>q %2,%0";
3230}
45d5d09c
HPN
3231 [(set_attr "slottable" "yes")
3232 (set_attr "cc" "noov32")])
0b85d816 3233
22c3c091
HPN
3234;; Since gcc gets lost, and forgets to zero-extend the source (or mask
3235;; the destination) when it changes shifts of lower modes into SImode,
3236;; it is better to make these expands an anonymous patterns instead of
3237;; the more correct define_insns. This occurs when gcc thinks that is
3238;; is better to widen to SImode and use immediate shift count.
0b85d816 3239
22c3c091 3240;; FIXME: Is this legacy or still true for gcc >= 2.7.2?
0b85d816 3241
22c3c091
HPN
3242;; FIXME: Can't parametrize sign_extend and zero_extend (before
3243;; mentioning "shiftrt"), so we need two patterns.
3244(define_expand "ashr<mode>3"
0b85d816 3245 [(set (match_dup 3)
22c3c091 3246 (sign_extend:SI (match_operand:BW 1 "nonimmediate_operand" "")))
0b85d816 3247 (set (match_dup 4)
22c3c091
HPN
3248 (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand" "")))
3249 (set (match_dup 5) (ashiftrt:SI (match_dup 3) (match_dup 4)))
3250 (set (match_operand:BW 0 "general_operand" "")
3251 (subreg:BW (match_dup 5) 0))]
0b85d816 3252 ""
0b85d816
HPN
3253{
3254 int i;
3255
3256 for (i = 3; i < 6; i++)
3257 operands[i] = gen_reg_rtx (SImode);
22c3c091 3258})
0b85d816 3259
22c3c091 3260(define_expand "lshr<mode>3"
0b85d816 3261 [(set (match_dup 3)
22c3c091 3262 (zero_extend:SI (match_operand:BW 1 "nonimmediate_operand" "")))
0b85d816 3263 (set (match_dup 4)
22c3c091 3264 (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand" "")))
0b85d816 3265 (set (match_dup 5) (lshiftrt:SI (match_dup 3) (match_dup 4)))
22c3c091
HPN
3266 (set (match_operand:BW 0 "general_operand" "")
3267 (subreg:BW (match_dup 5) 0))]
0b85d816 3268 ""
0b85d816
HPN
3269{
3270 int i;
3271
3272 for (i = 3; i < 6; i++)
3273 operands[i] = gen_reg_rtx (SImode);
22c3c091 3274})
0b85d816 3275
22c3c091
HPN
3276(define_insn "*expanded_<shlr><mode>"
3277 [(set (match_operand:BW 0 "register_operand" "=r")
3278 (shiftrt:BW (match_operand:BW 1 "register_operand" "0")
3279 (match_operand:BW 2 "register_operand" "r")))]
0b85d816 3280 ""
22c3c091 3281 "<slr><m> %2,%0"
45d5d09c
HPN
3282 [(set_attr "slottable" "yes")
3283 (set_attr "cc" "noov32")])
0b85d816 3284
22c3c091
HPN
3285(define_insn "*<shlr><mode>_lowpart"
3286 [(set (strict_low_part (match_operand:BW 0 "register_operand" "+r"))
3287 (shiftrt:BW (match_dup 0)
3288 (match_operand:BW 1 "register_operand" "r")))]
0b85d816 3289 ""
22c3c091 3290 "<slr><m> %1,%0"
45d5d09c
HPN
3291 [(set_attr "slottable" "yes")
3292 (set_attr "cc" "noov32")])
0b85d816
HPN
3293\f
3294;; Arithmetic/logical shift left.
3295
0b85d816
HPN
3296;; For narrower modes than SI, we can use lslq although it makes cc
3297;; unusable. The win is that we do not have to reload the shift-count
3298;; into a register.
3299
22c3c091
HPN
3300(define_insn "ashl<mode>3"
3301 [(set (match_operand:BW 0 "register_operand" "=r,r")
3302 (ashift:BW (match_operand:BW 1 "register_operand" "0,0")
f49e46d8 3303 (match_operand:BW 2 "nonmemory_operand" "r,Kc")))]
0b85d816 3304 ""
0b85d816
HPN
3305{
3306 return
991c42ac 3307 (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > <nbitsm1>)
22c3c091 3308 ? "moveq 0,%0"
0b85d816 3309 : (CONSTANT_P (operands[2])
22c3c091
HPN
3310 ? "lslq %2,%0" : "lsl<m> %2,%0");
3311}
0b85d816 3312 [(set_attr "slottable" "yes")
45d5d09c 3313 (set_attr "cc" "noov32,clobber")])
0b85d816
HPN
3314
3315;; A strict_low_part matcher.
3316
22c3c091
HPN
3317(define_insn "*ashl<mode>_lowpart"
3318 [(set (strict_low_part (match_operand:BW 0 "register_operand" "+r"))
3319 (ashift:BW (match_dup 0)
3320 (match_operand:HI 1 "register_operand" "r")))]
0b85d816 3321 ""
22c3c091 3322 "lsl<m> %1,%0"
45d5d09c
HPN
3323 [(set_attr "slottable" "yes")
3324 (set_attr "cc" "noov32")])
0b85d816
HPN
3325\f
3326;; Various strange insns that gcc likes.
3327
3328;; Fortunately, it is simple to construct an abssf (although it may not
3329;; be very much used in practice).
3330
3331(define_insn "abssf2"
3332 [(set (match_operand:SF 0 "register_operand" "=r")
3333 (abs:SF (match_operand:SF 1 "register_operand" "0")))]
3334 ""
3335 "lslq 1,%0\;lsrq 1,%0")
3336
3337(define_insn "abssi2"
3338 [(set (match_operand:SI 0 "register_operand" "=r")
3339 (abs:SI (match_operand:SI 1 "register_operand" "r")))]
3340 ""
3341 "abs %1,%0"
45d5d09c
HPN
3342 [(set_attr "slottable" "yes")
3343 (set_attr "cc" "noov32")])
0b85d816
HPN
3344
3345;; FIXME: GCC should be able to do these expansions itself.
3346
22c3c091 3347(define_expand "abs<mode>2"
0b85d816 3348 [(set (match_dup 2)
22c3c091 3349 (sign_extend:SI (match_operand:BW 1 "general_operand" "")))
0b85d816 3350 (set (match_dup 3) (abs:SI (match_dup 2)))
22c3c091
HPN
3351 (set (match_operand:BW 0 "register_operand" "")
3352 (subreg:BW (match_dup 3) 0))]
0b85d816
HPN
3353 ""
3354 "operands[2] = gen_reg_rtx (SImode); operands[3] = gen_reg_rtx (SImode);")
e636e508
JN
3355
3356(define_insn "clzsi2"
3357 [(set (match_operand:SI 0 "register_operand" "=r")
3358 (clz:SI (match_operand:SI 1 "register_operand" "r")))]
3359 "TARGET_HAS_LZ"
3360 "lz %1,%0"
45d5d09c
HPN
3361 [(set_attr "slottable" "yes")
3362 (set_attr "cc" "noov32")])
e636e508 3363
df638b27
JN
3364(define_insn "bswapsi2"
3365 [(set (match_operand:SI 0 "register_operand" "=r")
3366 (bswap:SI (match_operand:SI 1 "register_operand" "0")))]
3367 "TARGET_HAS_SWAP"
3368 "swapwb %0"
45d5d09c
HPN
3369 [(set_attr "slottable" "yes")
3370 (set_attr "cc" "noov32")])
df638b27 3371
9ef4a0cd
JN
3372;; This instruction swaps all bits in a register.
3373;; That means that the most significant bit is put in the place
3374;; of the least significant bit, and so on.
3375
3376(define_insn "cris_swap_bits"
3377 [(set (match_operand:SI 0 "register_operand" "=r")
3378 (unspec:SI [(match_operand:SI 1 "register_operand" "0")]
3379 CRIS_UNSPEC_SWAP_BITS))]
3380 "TARGET_HAS_SWAP"
3381 "swapwbr %0"
45d5d09c
HPN
3382 [(set_attr "slottable" "yes")
3383 (set_attr "cc" "noov32")])
9ef4a0cd
JN
3384
3385;; Implement ctz using two instructions, one for bit swap and one for clz.
3386;; Defines a scratch register to avoid clobbering input.
3387
3388(define_expand "ctzsi2"
3389 [(set (match_dup 2)
3390 (match_operand:SI 1 "register_operand"))
3391 (set (match_dup 2)
3392 (unspec:SI [(match_dup 2)] CRIS_UNSPEC_SWAP_BITS))
3393 (set (match_operand:SI 0 "register_operand")
3394 (clz:SI (match_dup 2)))]
3395 "TARGET_HAS_LZ && TARGET_HAS_SWAP"
3396 "operands[2] = gen_reg_rtx (SImode);")
3397
0b85d816
HPN
3398;; Bound-insn. Defined to be the same as an unsigned minimum, which is an
3399;; operation supported by gcc. Used in casesi, but used now and then in
3400;; normal code too.
3401
45d5d09c
HPN
3402(define_expand "uminsi3"
3403 [(set (match_operand:SI 0 "register_operand" "")
3404 (umin:SI (match_operand:SI 1 "register_operand" "")
3405 (match_operand:SI 2 "general_operand" "")))]
3406 ""
3407{
3408 if (MEM_P (operands[2]) && TARGET_V32)
3409 operands[2] = force_reg (SImode, operands[2]);
3410})
3411
3412(define_insn "*uminsi3_non_v32"
23369bef
HPN
3413 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r")
3414 (umin:SI (match_operand:SI 1 "register_operand" "%0,0, 0,r")
c00fc5cf 3415 (match_operand:SI 2 "general_operand" "r,Q>,g,!To")))]
45d5d09c 3416 "!TARGET_V32"
0b85d816 3417{
991c42ac 3418 if (CONST_INT_P (operands[2]))
0b85d816 3419 {
d76fe40b
HPN
3420 /* Constant operands are zero-extended, so only 32-bit operands
3421 may be negative. */
3422 if (INTVAL (operands[2]) >= 0)
3423 {
3424 if (INTVAL (operands[2]) < 256)
3425 return "bound.b %2,%0";
0b85d816 3426
d76fe40b
HPN
3427 if (INTVAL (operands[2]) < 65536)
3428 return "bound.w %2,%0";
3429 }
0b85d816
HPN
3430 }
3431 else if (which_alternative == 3)
22c3c091 3432 return "bound.d %2,%1,%0";
0b85d816 3433
22c3c091
HPN
3434 return "bound.d %2,%0";
3435}
0b85d816 3436 [(set_attr "slottable" "yes,yes,no,no")])
45d5d09c
HPN
3437
3438(define_insn "*uminsi3_v32"
3439 [(set (match_operand:SI 0 "register_operand" "=r,r")
3440 (umin:SI (match_operand:SI 1 "register_operand" "%0,0")
3441 (match_operand:SI 2 "nonmemory_operand" "r,i")))]
3442 "TARGET_V32"
3443{
3444 if (GET_CODE (operands[2]) == CONST_INT)
3445 {
3446 /* Constant operands are zero-extended, so only 32-bit operands
3447 may be negative. */
3448 if (INTVAL (operands[2]) >= 0)
3449 {
3450 if (INTVAL (operands[2]) < 256)
3451 return "bound.b %2,%0";
3452
3453 if (INTVAL (operands[2]) < 65536)
3454 return "bound.w %2,%0";
3455 }
3456 }
3457
3458 return "bound.d %2,%0";
3459}
3460 [(set_attr "slottable" "yes,no")])
0b85d816
HPN
3461\f
3462;; Jump and branch insns.
3463
3464(define_insn "jump"
3465 [(set (pc)
3466 (label_ref (match_operand 0 "" "")))]
3467 ""
3468 "ba %l0%#"
3469 [(set_attr "slottable" "has_slot")])
3470
3471;; Testcase gcc.c-torture/compile/991213-3.c fails if we allow a constant
3472;; here, since the insn is not recognized as an indirect jump by
3473;; jmp_uses_reg_or_mem used by computed_jump_p. Perhaps it is a kludge to
3474;; change from general_operand to nonimmediate_operand (at least the docs
3475;; should be changed), but then again the pattern is called indirect_jump.
45d5d09c
HPN
3476(define_expand "indirect_jump"
3477 [(set (pc) (match_operand:SI 0 "nonimmediate_operand"))]
0b85d816 3478 ""
45d5d09c
HPN
3479{
3480 if (TARGET_V32 && MEM_P (operands[0]))
3481 operands[0] = force_reg (SImode, operands[0]);
3482})
3483
3484(define_insn "*indirect_jump_non_v32"
3485 [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
3486 "!TARGET_V32"
0b85d816
HPN
3487 "jump %0")
3488
45d5d09c
HPN
3489(define_insn "*indirect_jump_v32"
3490 [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
3491 "TARGET_V32"
3492 "jump %0%#"
3493 [(set_attr "slottable" "has_slot")])
3494
0b85d816 3495;; Return insn. Used whenever the epilogue is very simple; if it is only
04539954
HPN
3496;; a single ret or jump [sp+]. No allocated stack space or saved
3497;; registers are allowed.
0b85d816
HPN
3498;; Note that for this pattern, although named, it is ok to check the
3499;; context of the insn in the test, not only compiler switches.
3500
04539954 3501(define_expand "return"
0b85d816
HPN
3502 [(return)]
3503 "cris_simple_epilogue ()"
04539954 3504 "cris_expand_return (cris_return_address_on_stack ()); DONE;")
0b85d816 3505
04539954
HPN
3506(define_insn "*return_expanded"
3507 [(return)]
3508 ""
3509{
3510 return cris_return_address_on_stack_for_return ()
3511 ? "jump [$sp+]" : "ret%#";
3512}
0b85d816 3513 [(set (attr "slottable")
04539954 3514 (if_then_else
bf0b8cbe 3515 (match_test "cris_return_address_on_stack_for_return ()")
04539954 3516 (const_string "no")
45d5d09c 3517 (const_string "has_return_slot")))])
04539954 3518
d29b4b1b
HPN
3519(define_expand "prologue"
3520 [(const_int 0)]
cc2af705 3521 ""
d29b4b1b
HPN
3522 "cris_expand_prologue (); DONE;")
3523
04539954
HPN
3524(define_expand "epilogue"
3525 [(const_int 0)]
cc2af705 3526 ""
04539954 3527 "cris_expand_epilogue (); DONE;")
0b85d816
HPN
3528\f
3529;; Conditional branches.
3530
f90b7a5a
PB
3531(define_expand "cbranch<mode>4"
3532 [(set (cc0) (compare
3533 (match_operand:BWD 1 "nonimmediate_operand")
3534 (match_operand:BWD 2 "general_operand")))
3535 (set (pc)
3536 (if_then_else (match_operator 0 "ordered_comparison_operator"
3537 [(cc0) (const_int 0)])
3538 (label_ref (match_operand 3 "" ""))
3539 (pc)))]
3540 ""
3541 "")
3542
3543(define_expand "cbranchdi4"
3544 [(set (cc0)
3545 (compare (match_operand:DI 1 "nonimmediate_operand" "")
3546 (match_operand:DI 2 "general_operand" "")))
3547 (set (pc)
3548 (if_then_else (match_operator 0 "ordered_comparison_operator"
3549 [(cc0) (const_int 0)])
3550 (label_ref (match_operand 3 "" ""))
3551 (pc)))]
3552 ""
3553{
3554 if (TARGET_V32 && !REG_P (operands[1]))
3555 operands[1] = force_reg (DImode, operands[1]);
3556 if (TARGET_V32 && MEM_P (operands[2]))
3557 operands[2] = force_reg (DImode, operands[2]);
3558})
3559
3560
0b85d816
HPN
3561;; We suffer from the same overflow-bit-gets-in-the-way problem as
3562;; e.g. m68k, so we have to check if overflow bit is set on all "signed"
3563;; conditions.
3564
221ca267 3565(define_insn "b<ncond:code>"
0b85d816 3566 [(set (pc)
22c3c091
HPN
3567 (if_then_else (ncond (cc0)
3568 (const_int 0))
0b85d816
HPN
3569 (label_ref (match_operand 0 "" ""))
3570 (pc)))]
3571 ""
22c3c091 3572 "b<CC> %l0%#"
0b85d816
HPN
3573 [(set_attr "slottable" "has_slot")])
3574
221ca267 3575(define_insn "b<ocond:code>"
0b85d816 3576 [(set (pc)
22c3c091
HPN
3577 (if_then_else (ocond (cc0)
3578 (const_int 0))
0b85d816
HPN
3579 (label_ref (match_operand 0 "" ""))
3580 (pc)))]
3581 ""
0b85d816
HPN
3582{
3583 return
3584 (cc_prev_status.flags & CC_NO_OVERFLOW)
221ca267 3585 ? 0 : "b<CC> %l0%#";
22c3c091 3586}
0b85d816
HPN
3587 [(set_attr "slottable" "has_slot")])
3588
221ca267 3589(define_insn "b<rcond:code>"
0b85d816 3590 [(set (pc)
22c3c091
HPN
3591 (if_then_else (rcond (cc0)
3592 (const_int 0))
0b85d816
HPN
3593 (label_ref (match_operand 0 "" ""))
3594 (pc)))]
3595 ""
0b85d816
HPN
3596{
3597 return
3598 (cc_prev_status.flags & CC_NO_OVERFLOW)
22c3c091
HPN
3599 ? "b<oCC> %l0%#" : "b<CC> %l0%#";
3600}
0b85d816
HPN
3601 [(set_attr "slottable" "has_slot")])
3602\f
3603;; Reversed anonymous patterns to the ones above, as mandated.
3604
221ca267 3605(define_insn "*b<ncond:code>_reversed"
0b85d816 3606 [(set (pc)
22c3c091
HPN
3607 (if_then_else (ncond (cc0)
3608 (const_int 0))
0b85d816
HPN
3609 (pc)
3610 (label_ref (match_operand 0 "" ""))))]
3611 ""
22c3c091 3612 "b<rCC> %l0%#"
0b85d816
HPN
3613 [(set_attr "slottable" "has_slot")])
3614
221ca267 3615(define_insn "*b<ocond:code>_reversed"
0b85d816 3616 [(set (pc)
22c3c091
HPN
3617 (if_then_else (ocond (cc0)
3618 (const_int 0))
0b85d816
HPN
3619 (pc)
3620 (label_ref (match_operand 0 "" ""))))]
3621 ""
0b85d816
HPN
3622{
3623 return
3624 (cc_prev_status.flags & CC_NO_OVERFLOW)
221ca267 3625 ? 0 : "b<rCC> %l0%#";
22c3c091 3626}
0b85d816
HPN
3627 [(set_attr "slottable" "has_slot")])
3628
221ca267 3629(define_insn "*b<rcond:code>_reversed"
0b85d816 3630 [(set (pc)
22c3c091
HPN
3631 (if_then_else (rcond (cc0)
3632 (const_int 0))
0b85d816
HPN
3633 (pc)
3634 (label_ref (match_operand 0 "" ""))))]
3635 ""
0b85d816
HPN
3636{
3637 return
3638 (cc_prev_status.flags & CC_NO_OVERFLOW)
221ca267 3639 ? "b<roCC> %l0%#" : "b<rCC> %l0%#";
22c3c091 3640}
0b85d816
HPN
3641 [(set_attr "slottable" "has_slot")])
3642\f
3643;; Set on condition: sCC.
3644
f90b7a5a
PB
3645(define_expand "cstoredi4"
3646 [(set (cc0) (compare
3647 (match_operand:DI 2 "nonimmediate_operand")
3648 (match_operand:DI 3 "general_operand")))
3649 (set (match_operand:SI 0 "register_operand")
3650 (match_operator:SI 1 "ordered_comparison_operator"
3651 [(cc0) (const_int 0)]))]
3652 ""
3653{
3654 if (TARGET_V32 && !REG_P (operands[2]))
3655 operands[2] = force_reg (DImode, operands[2]);
3656 if (TARGET_V32 && MEM_P (operands[3]))
3657 operands[3] = force_reg (DImode, operands[3]);
3658})
3659
3660(define_expand "cstore<mode>4"
3661 [(set (cc0) (compare
3662 (match_operand:BWD 2 "nonimmediate_operand")
3663 (match_operand:BWD 3 "general_operand")))
3664 (set (match_operand:SI 0 "register_operand")
3665 (match_operator:SI 1 "ordered_comparison_operator"
3666 [(cc0) (const_int 0)]))]
3667 ""
3668 "")
3669
0b85d816
HPN
3670;; Like bCC, we have to check the overflow bit for
3671;; signed conditions.
3672
221ca267 3673(define_insn "s<ncond:code>"
0b85d816 3674 [(set (match_operand:SI 0 "register_operand" "=r")
22c3c091 3675 (ncond:SI (cc0) (const_int 0)))]
0b85d816 3676 ""
22c3c091 3677 "s<CC> %0"
0b85d816
HPN
3678 [(set_attr "slottable" "yes")
3679 (set_attr "cc" "none")])
3680
221ca267 3681(define_insn "s<rcond:code>"
0b85d816 3682 [(set (match_operand:SI 0 "register_operand" "=r")
22c3c091 3683 (rcond:SI (cc0) (const_int 0)))]
0b85d816 3684 ""
0b85d816
HPN
3685{
3686 return
3687 (cc_prev_status.flags & CC_NO_OVERFLOW)
22c3c091
HPN
3688 ? "s<oCC> %0" : "s<CC> %0";
3689}
0cec6af1
HPN
3690 [(set_attr "slottable" "yes")
3691 (set_attr "cc" "none")])
0b85d816 3692
221ca267 3693(define_insn "s<ocond:code>"
0b85d816 3694 [(set (match_operand:SI 0 "register_operand" "=r")
22c3c091 3695 (ocond:SI (cc0) (const_int 0)))]
0b85d816 3696 ""
0b85d816
HPN
3697{
3698 return
3699 (cc_prev_status.flags & CC_NO_OVERFLOW)
22c3c091
HPN
3700 ? 0 : "s<CC> %0";
3701}
0b85d816
HPN
3702 [(set_attr "slottable" "yes")
3703 (set_attr "cc" "none")])
3704\f
3705;; Call insns.
3706
3707;; We need to make these patterns "expand", since the real operand is
3708;; hidden in a (mem:QI ) inside operand[0] (call_value: operand[1]),
3709;; and cannot be checked if it were a "normal" pattern.
3710;; Note that "call" and "call_value" are *always* called with a
3711;; mem-operand for operand 0 and 1 respective. What happens for combined
3712;; instructions is a different issue.
3713
3714(define_expand "call"
3715 [(parallel [(call (match_operand:QI 0 "cris_mem_call_operand" "")
3716 (match_operand 1 "general_operand" ""))
f16bb520 3717 (clobber (reg:SI CRIS_SRP_REGNUM))])]
0b85d816 3718 ""
0b85d816 3719{
991c42ac 3720 gcc_assert (MEM_P (operands[0]));
0b85d816 3721 if (flag_pic)
ab4e53fe
HPN
3722 cris_expand_pic_call_address (&operands[0], &operands[1]);
3723 else
3724 operands[1] = const0_rtx;
b6c34129 3725})
0b85d816 3726
ab4e53fe 3727;; Accept operands for operand 0 in order of preference.
0b85d816 3728
45d5d09c
HPN
3729(define_insn "*expanded_call_non_v32"
3730 [(call (mem:QI (match_operand:SI 0 "general_operand" "r,Q>,g"))
ab4e53fe 3731 (match_operand:SI 1 "cris_call_type_marker" "rM,rM,rM"))
f16bb520 3732 (clobber (reg:SI CRIS_SRP_REGNUM))]
45d5d09c 3733 "!TARGET_V32"
0b85d816
HPN
3734 "jsr %0")
3735
45d5d09c
HPN
3736(define_insn "*expanded_call_v32"
3737 [(call
3738 (mem:QI
3739 (match_operand:SI 0 "cris_nonmemory_operand_or_callable_symbol" "n,r,U,i"))
ab4e53fe 3740 (match_operand:SI 1 "cris_call_type_marker" "rM,rM,rM,rM"))
45d5d09c
HPN
3741 (clobber (reg:SI CRIS_SRP_REGNUM))]
3742 "TARGET_V32"
3743 "@
3744 jsr %0%#
3745 jsr %0%#
3746 bsr %0%#
3747 bsr %0%#"
3748 [(set_attr "slottable" "has_call_slot")])
3749
c00fc5cf
HPN
3750;; Parallel when calculating and reusing address of indirect pointer
3751;; with simple offset. (Makes most sense with PIC.) It looks a bit
3752;; wrong not to have the clobber last, but that's the way combine
ab4e53fe 3753;; generates it (except it doesn't look into the *inner* mem, so this
c00fc5cf
HPN
3754;; just matches a peephole2). FIXME: investigate that.
3755(define_insn "*expanded_call_side"
3756 [(call (mem:QI
3757 (mem:SI
3758 (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r, r,r")
3759 (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn"))))
ab4e53fe 3760 (match_operand:SI 2 "cris_call_type_marker" "rM,rM,rM"))
c00fc5cf
HPN
3761 (clobber (reg:SI CRIS_SRP_REGNUM))
3762 (set (match_operand:SI 3 "register_operand" "=*0,r,r")
3763 (plus:SI (match_dup 0)
3764 (match_dup 1)))]
ab4e53fe
HPN
3765 ;; Disabled until after reload until we can avoid an output reload for
3766 ;; operand 3 (being forbidden for call insns).
3767 "reload_completed && !TARGET_AVOID_GOTPLT && !TARGET_V32"
c00fc5cf
HPN
3768 "jsr [%3=%0%S1]")
3769
0b85d816
HPN
3770(define_expand "call_value"
3771 [(parallel [(set (match_operand 0 "" "")
3772 (call (match_operand:QI 1 "cris_mem_call_operand" "")
3773 (match_operand 2 "" "")))
f16bb520 3774 (clobber (reg:SI CRIS_SRP_REGNUM))])]
0b85d816 3775 ""
0b85d816 3776{
991c42ac 3777 gcc_assert (MEM_P (operands[1]));
0b85d816 3778 if (flag_pic)
ab4e53fe
HPN
3779 cris_expand_pic_call_address (&operands[1], &operands[2]);
3780 else
3781 operands[2] = const0_rtx;
b6c34129 3782})
0b85d816 3783
ab4e53fe 3784;; The validity other than "general" of
0b85d816
HPN
3785;; operand 0 will be checked elsewhere. Accept operands for operand 1 in
3786;; order of preference (Q includes r, but r is shorter, faster).
3787;; We also accept a PLT symbol. We output it as [rPIC+sym:GOTPLT] rather
3788;; than requiring getting rPIC + sym:PLT into a register.
3789
45d5d09c 3790(define_insn "*expanded_call_value_non_v32"
c00fc5cf 3791 [(set (match_operand 0 "nonimmediate_operand" "=g,g,g")
45d5d09c 3792 (call (mem:QI (match_operand:SI 1 "general_operand" "r,Q>,g"))
ab4e53fe 3793 (match_operand:SI 2 "cris_call_type_marker" "rM,rM,rM")))
f16bb520 3794 (clobber (reg:SI CRIS_SRP_REGNUM))]
45d5d09c 3795 "!TARGET_V32"
0b85d816
HPN
3796 "Jsr %1"
3797 [(set_attr "cc" "clobber")])
3798
c00fc5cf
HPN
3799;; See similar call special-case.
3800(define_insn "*expanded_call_value_side"
0b85d816 3801 [(set (match_operand 0 "nonimmediate_operand" "=g,g,g")
c00fc5cf
HPN
3802 (call
3803 (mem:QI
3804 (mem:SI
3805 (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r, r,r")
3806 (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn"))))
ab4e53fe 3807 (match_operand:SI 3 "cris_call_type_marker" "rM,rM,rM")))
c00fc5cf
HPN
3808 (clobber (reg:SI CRIS_SRP_REGNUM))
3809 (set (match_operand:SI 4 "register_operand" "=*1,r,r")
3810 (plus:SI (match_dup 1)
3811 (match_dup 2)))]
ab4e53fe
HPN
3812 ;; Disabled until after reload until we can avoid an output reload for
3813 ;; operand 4 (being forbidden for call insns).
3814 "reload_completed && !TARGET_AVOID_GOTPLT && !TARGET_V32"
c00fc5cf 3815 "Jsr [%4=%1%S2]"
0b85d816
HPN
3816 [(set_attr "cc" "clobber")])
3817
45d5d09c
HPN
3818(define_insn "*expanded_call_value_v32"
3819 [(set
3820 (match_operand 0 "nonimmediate_operand" "=g,g,g,g")
3821 (call
3822 (mem:QI
3823 (match_operand:SI 1 "cris_nonmemory_operand_or_callable_symbol" "n,r,U,i"))
ab4e53fe 3824 (match_operand:SI 2 "cris_call_type_marker" "rM,rM,rM,rM")))
45d5d09c
HPN
3825 (clobber (reg:SI 16))]
3826 "TARGET_V32"
3827 "@
3828 Jsr %1%#
3829 Jsr %1%#
3830 Bsr %1%#
3831 Bsr %1%#"
3832 [(set_attr "cc" "clobber")
3833 (set_attr "slottable" "has_call_slot")])
3834
0b85d816
HPN
3835;; Used in debugging. No use for the direct pattern; unfilled
3836;; delayed-branches are taken care of by other means.
3837
3838(define_insn "nop"
3839 [(const_int 0)]
3840 ""
3841 "nop"
3842 [(set_attr "cc" "none")])
64f5af47
HPN
3843
3844;; Same as the gdb trap breakpoint, will cause a SIGTRAP for
3845;; cris-linux* and crisv32-linux*, as intended. Will work in
3846;; freestanding environments with sufficient framework.
3847(define_insn "trap"
3848 [(trap_if (const_int 1) (const_int 8))]
3849 "TARGET_TRAP_USING_BREAK8"
3850 "break 8")
0b85d816 3851\f
04539954
HPN
3852;; We need to stop accesses to the stack after the memory is
3853;; deallocated. Unfortunately, reorg doesn't look at naked clobbers,
3854;; e.g. (insn ... (clobber (mem:BLK (stack_pointer_rtx)))) and we don't
3855;; want to use a naked (unspec_volatile) as that would stop any
3856;; scheduling in the epilogue. Hence we model it as a "real" insn that
3857;; sets the memory in an unspecified manner. FIXME: Unfortunately it
3858;; still has the effect of an unspec_volatile.
3859(define_insn "cris_frame_deallocated_barrier"
3860 [(set (mem:BLK (reg:SI CRIS_SP_REGNUM))
3861 (unspec:BLK [(const_int 0)] CRIS_UNSPEC_FRAME_DEALLOC))]
3862 ""
3863 ""
3864 [(set_attr "length" "0")])
3865
0b85d816
HPN
3866;; We expand on casesi so we can use "bound" and "add offset fetched from
3867;; a table to pc" (adds.w [pc+%0.w],pc).
3868
3869;; Note: if you change the "parallel" (or add anything after it) in
3870;; this expansion, you must change the macro ASM_OUTPUT_CASE_END
3871;; accordingly, to add the default case at the end of the jump-table.
3872
45d5d09c 3873(define_expand "cris_casesi_non_v32"
0b85d816
HPN
3874 [(set (match_dup 5) (match_operand:SI 0 "general_operand" ""))
3875 (set (match_dup 6)
3876 (minus:SI (match_dup 5)
3877 (match_operand:SI 1 "const_int_operand" "n")))
3878 (set (match_dup 7)
3879 (umin:SI (match_dup 6)
3880 (match_operand:SI 2 "const_int_operand" "n")))
3881 (parallel
3882 [(set (pc)
3883 (if_then_else
3884 (ltu (match_dup 7) (match_dup 2))
3885 (plus:SI (sign_extend:SI
3886 (mem:HI
3887 (plus:SI (mult:SI (match_dup 7) (const_int 2))
3888 (pc))))
3889 (pc))
3890 (label_ref (match_operand 4 "" ""))))
3891 (use (label_ref (match_operand 3 "" "")))])]
3892 ""
0b85d816 3893{
0a81f074 3894 operands[2] = plus_constant (SImode, operands[2], 1);
0b85d816
HPN
3895 operands[5] = gen_reg_rtx (SImode);
3896 operands[6] = gen_reg_rtx (SImode);
3897 operands[7] = gen_reg_rtx (SImode);
22c3c091 3898})
45d5d09c
HPN
3899
3900;; FIXME: Check effect of not JUMP_TABLES_IN_TEXT_SECTION.
3901(define_expand "cris_casesi_v32"
3902 [(set (match_dup 5) (match_operand:SI 0 "general_operand"))
3903 (set (match_dup 6)
3904 (minus:SI (match_dup 5)
3905 (match_operand:SI 1 "const_int_operand")))
3906 (set (match_dup 7)
3907 (umin:SI (match_dup 6)
3908 (match_operand:SI 2 "const_int_operand")))
3909 (set (match_dup 8) (match_dup 11))
3910 (set (match_dup 9)
3911 (plus:SI (mult:SI (match_dup 7) (const_int 2))
3912 (match_dup 8)))
3913 (set (match_dup 10)
3914 (plus:SI (sign_extend:SI (mem:HI (match_dup 9)))
3915 (match_dup 9)))
3916 (parallel
3917 [(set (pc)
3918 (if_then_else
3919 (ltu (unspec [(const_int 0)] CRIS_UNSPEC_CASESI) (match_dup 2))
3920 (match_dup 10)
3921 (label_ref (match_operand 4 "" ""))))
3922 (use (label_ref (match_dup 3)))])]
3923 "TARGET_V32"
3924{
3925 int i;
3926 rtx xlabel = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
3927 for (i = 5; i <= 10; i++)
3928 operands[i] = gen_reg_rtx (SImode);
0a81f074 3929 operands[2] = plus_constant (SImode, operands[2], 1);
45d5d09c
HPN
3930
3931 /* Don't forget to decorate labels too, for PIC. */
3932 operands[11] = flag_pic
3933 ? gen_rtx_CONST (Pmode,
3934 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xlabel),
3935 CRIS_UNSPEC_PCREL))
3936 : xlabel;
3937})
3938
3939(define_expand "casesi"
3940 [(match_operand:SI 0 "general_operand")
3941 (match_operand:SI 1 "const_int_operand")
3942 (match_operand:SI 2 "const_int_operand")
3943 (match_operand 3 "" "")
3944 (match_operand 4 "" "")]
3945 ""
3946{
3947 if (TARGET_V32)
3948 emit_insn (gen_cris_casesi_v32 (operands[0], operands[1], operands[2],
3949 operands[3], operands[4]));
3950 else
3951 emit_insn (gen_cris_casesi_non_v32 (operands[0], operands[1], operands[2],
3952 operands[3], operands[4]));
3953 DONE;
3954})
0b85d816
HPN
3955\f
3956;; Split-patterns. Some of them have modes unspecified. This
3957;; should always be ok; if for no other reason sparc.md has it as
3958;; well.
3959;;
3960;; When register_operand is specified for an operand, we can get a
3961;; subreg as well (Axis-990331), so don't just assume that REG_P is true
3962;; for a register_operand and that REGNO can be used as is. It is best to
3963;; guard with REG_P, unless it is worth it to adjust for the subreg case.
3964
3965;; op [rx + 0],ry,rz
3966;; The index to rx is optimized into zero, and gone.
3967
3968;; First, recognize bound [rx],ry,rz; where [rx] is zero-extended,
3969;; and add/sub [rx],ry,rz, with zero or sign-extend on [rx].
3970;; Split this into:
3971;; move ry,rz
3972;; op [rx],rz
3973;; Lose if rz=ry or rx=rz.
45d5d09c
HPN
3974;; Call this op-extend-split.
3975;; Do not match for V32; the addo and addi shouldn't be split
3976;; up.
0b85d816
HPN
3977
3978(define_split
a13a866e 3979 [(set (match_operand 0 "cris_nonsp_register_operand" "")
0b85d816
HPN
3980 (match_operator
3981 4 "cris_operand_extend_operator"
3982 [(match_operand 1 "register_operand" "")
3983 (match_operator
3984 3 "cris_extend_operator"
3985 [(match_operand 2 "memory_operand" "")])]))]
45d5d09c
HPN
3986 "!TARGET_V32
3987 && REG_P (operands[0])
0b85d816
HPN
3988 && REG_P (operands[1])
3989 && REGNO (operands[1]) != REGNO (operands[0])
3990 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
3991 && REG_P (XEXP (operands[2], 0))
3992 && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])"
3993 [(set (match_dup 0)
3994 (match_dup 1))
3995 (set (match_dup 0)
3996 (match_op_dup
3997 4 [(match_dup 0)
3998 (match_op_dup 3 [(match_dup 2)])]))]
3999 "")
4000
4001;; As op-extend-split, but recognize and split op [rz],ry,rz into
4002;; ext [rz],rz
4003;; op ry,rz
4004;; Do this for plus or bound only, being commutative operations, since we
4005;; have swapped the operands.
4006;; Call this op-extend-split-rx=rz
4007
4008(define_split
a13a866e 4009 [(set (match_operand 0 "cris_nonsp_register_operand" "")
0b85d816
HPN
4010 (match_operator
4011 4 "cris_plus_or_bound_operator"
4012 [(match_operand 1 "register_operand" "")
4013 (match_operator
4014 3 "cris_extend_operator"
4015 [(match_operand 2 "memory_operand" "")])]))]
45d5d09c
HPN
4016 "!TARGET_V32
4017 && REG_P (operands[0])
0b85d816
HPN
4018 && REG_P (operands[1])
4019 && REGNO (operands[1]) != REGNO (operands[0])
4020 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
4021 && REG_P (XEXP (operands[2], 0))
4022 && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])"
4023 [(set (match_dup 0)
4024 (match_op_dup 3 [(match_dup 2)]))
4025 (set (match_dup 0)
4026 (match_op_dup
4027 4 [(match_dup 0)
4028 (match_dup 1)]))]
4029 "")
4030
4031;; As the op-extend-split, but swapped operands, and only for
4032;; plus or bound, being the commutative extend-operators. FIXME: Why is
4033;; this needed? Is it?
4034;; Call this op-extend-split-swapped
4035
4036(define_split
a13a866e 4037 [(set (match_operand 0 "cris_nonsp_register_operand" "")
0b85d816
HPN
4038 (match_operator
4039 4 "cris_plus_or_bound_operator"
4040 [(match_operator
4041 3 "cris_extend_operator"
4042 [(match_operand 2 "memory_operand" "")])
4043 (match_operand 1 "register_operand" "")]))]
45d5d09c
HPN
4044 "!TARGET_V32
4045 && REG_P (operands[0])
0b85d816
HPN
4046 && REG_P (operands[1])
4047 && REGNO (operands[1]) != REGNO (operands[0])
4048 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
4049 && REG_P (XEXP (operands[2], 0))
4050 && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])"
4051 [(set (match_dup 0)
4052 (match_dup 1))
4053 (set (match_dup 0)
4054 (match_op_dup
4055 4 [(match_dup 0)
4056 (match_op_dup 3 [(match_dup 2)])]))]
4057 "")
4058
4059;; As op-extend-split-rx=rz, but swapped operands, only for plus or
4060;; bound. Call this op-extend-split-swapped-rx=rz.
4061
4062(define_split
a13a866e 4063 [(set (match_operand 0 "cris_nonsp_register_operand" "")
0b85d816
HPN
4064 (match_operator
4065 4 "cris_plus_or_bound_operator"
4066 [(match_operator
4067 3 "cris_extend_operator"
4068 [(match_operand 2 "memory_operand" "")])
4069 (match_operand 1 "register_operand" "")]))]
45d5d09c
HPN
4070 "!TARGET_V32
4071 && REG_P (operands[0])
0b85d816
HPN
4072 && REG_P (operands[1])
4073 && REGNO (operands[1]) != REGNO (operands[0])
4074 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
4075 && REG_P (XEXP (operands[2], 0))
4076 && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])"
4077 [(set (match_dup 0)
4078 (match_op_dup 3 [(match_dup 2)]))
4079 (set (match_dup 0)
4080 (match_op_dup
4081 4 [(match_dup 0)
4082 (match_dup 1)]))]
4083 "")
4084
4085;; As op-extend-split, but the mem operand is not extended.
4086;;
4087;; op [rx],ry,rz changed into
4088;; move ry,rz
4089;; op [rx],rz
4090;; lose if ry=rz or rx=rz
4091;; Call this op-extend.
4092
4093(define_split
a13a866e 4094 [(set (match_operand 0 "cris_nonsp_register_operand" "")
0b85d816
HPN
4095 (match_operator
4096 3 "cris_orthogonal_operator"
4097 [(match_operand 1 "register_operand" "")
4098 (match_operand 2 "memory_operand" "")]))]
45d5d09c
HPN
4099 "!TARGET_V32
4100 && REG_P (operands[0])
0b85d816
HPN
4101 && REG_P (operands[1])
4102 && REGNO (operands[1]) != REGNO (operands[0])
4103 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
4104 && REG_P (XEXP (operands[2], 0))
4105 && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])"
4106 [(set (match_dup 0)
4107 (match_dup 1))
4108 (set (match_dup 0)
4109 (match_op_dup
4110 3 [(match_dup 0)
4111 (match_dup 2)]))]
4112 "")
4113
4114;; As op-extend-split-rx=rz, non-extended.
4115;; Call this op-split-rx=rz
4116
4117(define_split
a13a866e 4118 [(set (match_operand 0 "cris_nonsp_register_operand" "")
0b85d816
HPN
4119 (match_operator
4120 3 "cris_commutative_orth_op"
4121 [(match_operand 2 "memory_operand" "")
4122 (match_operand 1 "register_operand" "")]))]
45d5d09c
HPN
4123 "!TARGET_V32
4124 && REG_P (operands[0])
0b85d816
HPN
4125 && REG_P (operands[1])
4126 && REGNO (operands[1]) != REGNO (operands[0])
4127 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
4128 && REG_P (XEXP (operands[2], 0))
4129 && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])"
4130 [(set (match_dup 0)
4131 (match_dup 1))
4132 (set (match_dup 0)
4133 (match_op_dup
4134 3 [(match_dup 0)
4135 (match_dup 2)]))]
4136 "")
4137
4138;; As op-extend-split-swapped, nonextended.
4139;; Call this op-split-swapped.
4140
4141(define_split
a13a866e 4142 [(set (match_operand 0 "cris_nonsp_register_operand" "")
0b85d816
HPN
4143 (match_operator
4144 3 "cris_commutative_orth_op"
4145 [(match_operand 1 "register_operand" "")
4146 (match_operand 2 "memory_operand" "")]))]
45d5d09c
HPN
4147 "!TARGET_V32
4148 && REG_P (operands[0]) && REG_P (operands[1])
0b85d816
HPN
4149 && REGNO (operands[1]) != REGNO (operands[0])
4150 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
4151 && REG_P (XEXP (operands[2], 0))
4152 && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])"
4153 [(set (match_dup 0)
4154 (match_dup 2))
4155 (set (match_dup 0)
4156 (match_op_dup
4157 3 [(match_dup 0)
4158 (match_dup 1)]))]
4159 "")
4160
4161;; As op-extend-split-swapped-rx=rz, non-extended.
4162;; Call this op-split-swapped-rx=rz.
4163
4164(define_split
a13a866e 4165 [(set (match_operand 0 "cris_nonsp_register_operand" "")
0b85d816
HPN
4166 (match_operator
4167 3 "cris_orthogonal_operator"
4168 [(match_operand 2 "memory_operand" "")
4169 (match_operand 1 "register_operand" "")]))]
45d5d09c
HPN
4170 "!TARGET_V32
4171 && REG_P (operands[0]) && REG_P (operands[1])
0b85d816
HPN
4172 && REGNO (operands[1]) != REGNO (operands[0])
4173 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
4174 && REG_P (XEXP (operands[2], 0))
4175 && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])"
4176 [(set (match_dup 0)
4177 (match_dup 2))
4178 (set (match_dup 0)
4179 (match_op_dup
4180 3 [(match_dup 0)
4181 (match_dup 1)]))]
4182 "")
21ed4444
HPN
4183
4184(include "sync.md")
0b85d816
HPN
4185\f
4186;; Splits for all cases in side-effect insns where (possibly after reload
4187;; and register allocation) rx and ry in [rx=ry+i] are equal.
4188
4189;; move.S1 [rx=rx+rz.S2],ry
4190
4191(define_split
4192 [(parallel
4193 [(set (match_operand 0 "register_operand" "")
dbb138ce
HPN
4194 (match_operator
4195 6 "cris_mem_op"
4196 [(plus:SI
4197 (mult:SI (match_operand:SI 1 "register_operand" "")
4198 (match_operand:SI 2 "const_int_operand" ""))
4199 (match_operand:SI 3 "register_operand" ""))]))
0b85d816 4200 (set (match_operand:SI 4 "register_operand" "")
8ad46d34
HPN
4201 (plus:SI (mult:SI (match_dup 1)
4202 (match_dup 2))
0b85d816
HPN
4203 (match_dup 3)))])]
4204 "REG_P (operands[3]) && REG_P (operands[4])
4205 && REGNO (operands[3]) == REGNO (operands[4])"
4206 [(set (match_dup 4) (plus:SI (mult:SI (match_dup 1) (match_dup 2))
8ad46d34 4207 (match_dup 3)))
0b85d816 4208 (set (match_dup 0) (match_dup 5))]
dbb138ce 4209 "operands[5] = replace_equiv_address (operands[6], operands[3]);")
0b85d816
HPN
4210
4211;; move.S1 [rx=rx+i],ry
4212
4213(define_split
4214 [(parallel
4215 [(set (match_operand 0 "register_operand" "")
dbb138ce
HPN
4216 (match_operator
4217 5 "cris_mem_op"
4218 [(plus:SI (match_operand:SI 1 "cris_bdap_operand" "")
4219 (match_operand:SI 2 "cris_bdap_operand" ""))]))
0b85d816
HPN
4220 (set (match_operand:SI 3 "register_operand" "")
4221 (plus:SI (match_dup 1)
4222 (match_dup 2)))])]
4223 "(rtx_equal_p (operands[3], operands[1])
4224 || rtx_equal_p (operands[3], operands[2]))"
4225 [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2)))
4226 (set (match_dup 0) (match_dup 4))]
7faa3eb8
HPN
4227{
4228 operands[4] = replace_equiv_address (operands[5], operands[3]);
4229 cris_order_for_addsi3 (operands, 1);
4230})
0b85d816
HPN
4231
4232;; move.S1 ry,[rx=rx+rz.S2]
4233
4234(define_split
4235 [(parallel
dbb138ce
HPN
4236 [(set (match_operator
4237 6 "cris_mem_op"
4238 [(plus:SI
4239 (mult:SI (match_operand:SI 0 "register_operand" "")
4240 (match_operand:SI 1 "const_int_operand" ""))
4241 (match_operand:SI 2 "register_operand" ""))])
4242 (match_operand 3 "register_operand" ""))
0b85d816
HPN
4243 (set (match_operand:SI 4 "register_operand" "")
4244 (plus:SI (mult:SI (match_dup 0)
4245 (match_dup 1))
4246 (match_dup 2)))])]
4247 "REG_P (operands[2]) && REG_P (operands[4])
4248 && REGNO (operands[4]) == REGNO (operands[2])"
4249 [(set (match_dup 4) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
4250 (match_dup 2)))
4251 (set (match_dup 5) (match_dup 3))]
dbb138ce 4252 "operands[5] = replace_equiv_address (operands[6], operands[4]);")
0b85d816
HPN
4253
4254;; move.S1 ry,[rx=rx+i]
4255
4256(define_split
4257 [(parallel
dbb138ce
HPN
4258 [(set (match_operator
4259 6 "cris_mem_op"
4260 [(plus:SI (match_operand:SI 0 "cris_bdap_operand" "")
4261 (match_operand:SI 1 "cris_bdap_operand" ""))])
4262 (match_operand 2 "register_operand" ""))
0b85d816
HPN
4263 (set (match_operand:SI 3 "register_operand" "")
4264 (plus:SI (match_dup 0)
4265 (match_dup 1)))])]
4266 "(rtx_equal_p (operands[3], operands[0])
4267 || rtx_equal_p (operands[3], operands[1]))"
4268 [(set (match_dup 3) (plus:SI (match_dup 0) (match_dup 1)))
4269 (set (match_dup 5) (match_dup 2))]
7faa3eb8
HPN
4270{
4271 operands[5] = replace_equiv_address (operands[6], operands[3]);
4272 cris_order_for_addsi3 (operands, 0);
4273})
0b85d816 4274
22c3c091 4275;; clear.[bwd] [rx=rx+rz.S2]
0b85d816
HPN
4276
4277(define_split
4278 [(parallel
22c3c091 4279 [(set (mem:BWD (plus:SI
0b85d816
HPN
4280 (mult:SI (match_operand:SI 0 "register_operand" "")
4281 (match_operand:SI 1 "const_int_operand" ""))
4282 (match_operand:SI 2 "register_operand" "")))
4283 (const_int 0))
4284 (set (match_operand:SI 3 "register_operand" "")
4285 (plus:SI (mult:SI (match_dup 0)
4286 (match_dup 1))
4287 (match_dup 2)))])]
4288 "REG_P (operands[2]) && REG_P (operands[3])
4289 && REGNO (operands[3]) == REGNO (operands[2])"
4290 [(set (match_dup 3) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
4291 (match_dup 2)))
22c3c091 4292 (set (mem:BWD (match_dup 3)) (const_int 0))]
0b85d816
HPN
4293 "")
4294
22c3c091 4295;; clear.[bwd] [rx=rx+i]
0b85d816
HPN
4296
4297(define_split
4298 [(parallel
22c3c091 4299 [(set (mem:BWD
0b85d816
HPN
4300 (plus:SI (match_operand:SI 0 "cris_bdap_operand" "")
4301 (match_operand:SI 1 "cris_bdap_operand" "")))
4302 (const_int 0))
4303 (set (match_operand:SI 2 "register_operand" "")
4304 (plus:SI (match_dup 0)
4305 (match_dup 1)))])]
4306 "(rtx_equal_p (operands[0], operands[2])
4307 || rtx_equal_p (operands[2], operands[1]))"
4308 [(set (match_dup 2) (plus:SI (match_dup 0) (match_dup 1)))
22c3c091 4309 (set (mem:BWD (match_dup 2)) (const_int 0))]
7faa3eb8 4310 "cris_order_for_addsi3 (operands, 0);")
0b85d816
HPN
4311
4312;; mov(s|u).S1 [rx=rx+rz.S2],ry
4313
4314(define_split
4315 [(parallel
4316 [(set (match_operand 0 "register_operand" "")
4317 (match_operator
4318 5 "cris_extend_operator"
4319 [(mem (plus:SI
4320 (mult:SI (match_operand:SI 1 "register_operand" "")
4321 (match_operand:SI 2 "const_int_operand" ""))
4322 (match_operand:SI 3 "register_operand" "")))]))
4323 (set (match_operand:SI 4 "register_operand" "")
4324 (plus:SI (mult:SI (match_dup 1)
4325 (match_dup 2))
4326 (match_dup 3)))])]
4327 "REG_P (operands[3])
4328 && REG_P (operands[4])
4329 && REGNO (operands[3]) == REGNO (operands[4])"
4330 [(set (match_dup 4) (plus:SI (mult:SI (match_dup 1) (match_dup 2))
4331 (match_dup 3)))
4332 (set (match_dup 0) (match_op_dup 5 [(match_dup 6)]))]
dbb138ce 4333 "operands[6] = replace_equiv_address (XEXP (operands[5], 0), operands[4]);")
0b85d816
HPN
4334
4335;; mov(s|u).S1 [rx=rx+i],ry
4336
4337(define_split
4338 [(parallel
4339 [(set (match_operand 0 "register_operand" "")
4340 (match_operator
4341 4 "cris_extend_operator"
4342 [(mem (plus:SI
4343 (match_operand:SI 1 "cris_bdap_operand" "")
4344 (match_operand:SI 2 "cris_bdap_operand" "")))]))
4345 (set (match_operand:SI 3 "register_operand" "")
4346 (plus:SI (match_dup 1)
4347 (match_dup 2)))])]
4348 "(rtx_equal_p (operands[1], operands[3])
4349 || rtx_equal_p (operands[2], operands[3]))"
4350 [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2)))
4351 (set (match_dup 0) (match_op_dup 4 [(match_dup 5)]))]
7faa3eb8
HPN
4352{
4353 operands[5] = replace_equiv_address (XEXP (operands[4], 0), operands[3]);
4354 cris_order_for_addsi3 (operands, 1);
4355})
0b85d816
HPN
4356
4357;; op.S1 [rx=rx+i],ry
4358
4359(define_split
4360 [(parallel
4361 [(set (match_operand 0 "register_operand" "")
4362 (match_operator
4363 5 "cris_orthogonal_operator"
4364 [(match_operand 1 "register_operand" "")
4365 (mem (plus:SI
4366 (match_operand:SI 2 "cris_bdap_operand" "")
4367 (match_operand:SI 3 "cris_bdap_operand" "")))]))
4368 (set (match_operand:SI 4 "register_operand" "")
4369 (plus:SI (match_dup 2)
4370 (match_dup 3)))])]
4371 "(rtx_equal_p (operands[4], operands[2])
4372 || rtx_equal_p (operands[4], operands[3]))"
4373 [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
4374 (set (match_dup 0) (match_op_dup 5 [(match_dup 1) (match_dup 6)]))]
7faa3eb8
HPN
4375{
4376 operands[6] = replace_equiv_address (XEXP (operands[5], 1), operands[4]);
4377 cris_order_for_addsi3 (operands, 2);
4378})
0b85d816
HPN
4379
4380;; op.S1 [rx=rx+rz.S2],ry
4381
4382(define_split
4383 [(parallel
4384 [(set (match_operand 0 "register_operand" "")
4385 (match_operator
4386 6 "cris_orthogonal_operator"
4387 [(match_operand 1 "register_operand" "")
4388 (mem (plus:SI
4389 (mult:SI (match_operand:SI 2 "register_operand" "")
4390 (match_operand:SI 3 "const_int_operand" ""))
4391 (match_operand:SI 4 "register_operand" "")))]))
4392 (set (match_operand:SI 5 "register_operand" "")
4393 (plus:SI (mult:SI (match_dup 2)
4394 (match_dup 3))
4395 (match_dup 4)))])]
4396 "REG_P (operands[4])
4397 && REG_P (operands[5])
4398 && REGNO (operands[5]) == REGNO (operands[4])"
4399 [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
4400 (match_dup 4)))
4401 (set (match_dup 0) (match_op_dup 6 [(match_dup 1) (match_dup 7)]))]
dbb138ce 4402 "operands[7] = replace_equiv_address (XEXP (operands[6], 1), operands[5]);")
0b85d816
HPN
4403
4404;; op.S1 [rx=rx+rz.S2],ry (swapped)
4405
4406(define_split
4407 [(parallel
4408 [(set (match_operand 0 "register_operand" "")
4409 (match_operator
4410 6 "cris_commutative_orth_op"
4411 [(mem (plus:SI
4412 (mult:SI (match_operand:SI 2 "register_operand" "")
4413 (match_operand:SI 3 "const_int_operand" ""))
4414 (match_operand:SI 4 "register_operand" "")))
4415 (match_operand 1 "register_operand" "")]))
4416 (set (match_operand:SI 5 "register_operand" "")
4417 (plus:SI (mult:SI (match_dup 2)
4418 (match_dup 3))
4419 (match_dup 4)))])]
4420 "REG_P (operands[4])
4421 && REG_P (operands[5])
4422 && REGNO (operands[5]) == REGNO (operands[4])"
4423 [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
4424 (match_dup 4)))
4425 (set (match_dup 0) (match_op_dup 6 [(match_dup 7) (match_dup 1)]))]
dbb138ce 4426 "operands[7] = replace_equiv_address (XEXP (operands[6], 0), operands[5]);")
0b85d816
HPN
4427
4428;; op.S1 [rx=rx+i],ry (swapped)
4429
4430(define_split
4431 [(parallel
4432 [(set (match_operand 0 "register_operand" "")
4433 (match_operator
4434 5 "cris_commutative_orth_op"
4435 [(mem
4436 (plus:SI (match_operand:SI 2 "cris_bdap_operand" "")
4437 (match_operand:SI 3 "cris_bdap_operand" "")))
4438 (match_operand 1 "register_operand" "")]))
4439 (set (match_operand:SI 4 "register_operand" "")
4440 (plus:SI (match_dup 2)
4441 (match_dup 3)))])]
4442 "(rtx_equal_p (operands[4], operands[2])
4443 || rtx_equal_p (operands[4], operands[3]))"
4444 [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
4445 (set (match_dup 0) (match_op_dup 5 [(match_dup 6) (match_dup 1)]))]
7faa3eb8
HPN
4446{
4447 operands[6] = replace_equiv_address (XEXP (operands[5], 0), operands[4]);
4448 cris_order_for_addsi3 (operands, 2);
4449})
0b85d816
HPN
4450
4451;; op(s|u).S1 [rx=rx+rz.S2],ry
4452
4453(define_split
4454 [(parallel
4455 [(set (match_operand 0 "register_operand" "")
4456 (match_operator
4457 6 "cris_operand_extend_operator"
4458 [(match_operand 1 "register_operand" "")
4459 (match_operator
4460 7 "cris_extend_operator"
4461 [(mem (plus:SI
4462 (mult:SI (match_operand:SI 2 "register_operand" "")
4463 (match_operand:SI 3 "const_int_operand" ""))
4464 (match_operand:SI 4 "register_operand" "")))])]))
4465 (set (match_operand:SI 5 "register_operand" "")
4466 (plus:SI (mult:SI (match_dup 2)
4467 (match_dup 3))
4468 (match_dup 4)))])]
4469 "REG_P (operands[4])
4470 && REG_P (operands[5])
4471 && REGNO (operands[5]) == REGNO (operands[4])"
4472 [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
4473 (match_dup 4)))
4474 (set (match_dup 0) (match_op_dup 6 [(match_dup 1) (match_dup 8)]))]
1c563bed 4475 "operands[8] = gen_rtx_fmt_e (GET_CODE (operands[7]), GET_MODE (operands[7]),
0f4c242b
KH
4476 replace_equiv_address (XEXP (operands[7], 0),
4477 operands[5]));")
0b85d816
HPN
4478
4479;; op(s|u).S1 [rx=rx+i],ry
4480
4481(define_split
4482 [(parallel
4483 [(set (match_operand 0 "register_operand" "")
4484 (match_operator
4485 5 "cris_operand_extend_operator"
4486 [(match_operand 1 "register_operand" "")
4487 (match_operator
4488 6 "cris_extend_operator"
4489 [(mem
4490 (plus:SI (match_operand:SI 2 "cris_bdap_operand" "")
4491 (match_operand:SI 3 "cris_bdap_operand" "")
4492 ))])]))
4493 (set (match_operand:SI 4 "register_operand" "")
4494 (plus:SI (match_dup 2)
4495 (match_dup 3)))])]
4496 "(rtx_equal_p (operands[4], operands[2])
4497 || rtx_equal_p (operands[4], operands[3]))"
4498 [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
4499 (set (match_dup 0) (match_op_dup 5 [(match_dup 1) (match_dup 7)]))]
7faa3eb8
HPN
4500{
4501 operands[7] = gen_rtx_fmt_e (GET_CODE (operands[6]), GET_MODE (operands[6]),
4502 replace_equiv_address (XEXP (operands[6], 0),
4503 operands[4]));
4504 cris_order_for_addsi3 (operands, 2);
4505})
0b85d816
HPN
4506
4507;; op(s|u).S1 [rx=rx+rz.S2],ry (swapped, plus or bound)
4508
4509(define_split
4510 [(parallel
4511 [(set (match_operand 0 "register_operand" "")
4512 (match_operator
4513 7 "cris_plus_or_bound_operator"
4514 [(match_operator
4515 6 "cris_extend_operator"
4516 [(mem (plus:SI
4517 (mult:SI (match_operand:SI 2 "register_operand" "")
4518 (match_operand:SI 3 "const_int_operand" ""))
4519 (match_operand:SI 4 "register_operand" "")))])
4520 (match_operand 1 "register_operand" "")]))
4521 (set (match_operand:SI 5 "register_operand" "")
4522 (plus:SI (mult:SI (match_dup 2)
4523 (match_dup 3))
4524 (match_dup 4)))])]
4525 "REG_P (operands[4]) && REG_P (operands[5])
4526 && REGNO (operands[5]) == REGNO (operands[4])"
4527 [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
4528 (match_dup 4)))
4529 (set (match_dup 0) (match_op_dup 6 [(match_dup 8) (match_dup 1)]))]
1c563bed 4530 "operands[8] = gen_rtx_fmt_e (GET_CODE (operands[6]), GET_MODE (operands[6]),
0f4c242b
KH
4531 replace_equiv_address (XEXP (operands[6], 0),
4532 operands[5]));")
0b85d816
HPN
4533
4534;; op(s|u).S1 [rx=rx+i],ry (swapped, plus or bound)
4535
4536(define_split
4537 [(parallel
4538 [(set (match_operand 0 "register_operand" "")
4539 (match_operator
4540 6 "cris_plus_or_bound_operator"
4541 [(match_operator
4542 5 "cris_extend_operator"
4543 [(mem (plus:SI
4544 (match_operand:SI 2 "cris_bdap_operand" "")
4545 (match_operand:SI 3 "cris_bdap_operand" "")))])
4546 (match_operand 1 "register_operand" "")]))
4547 (set (match_operand:SI 4 "register_operand" "")
4548 (plus:SI (match_dup 2)
4549 (match_dup 3)))])]
4550 "(rtx_equal_p (operands[4], operands[2])
4551 || rtx_equal_p (operands[4], operands[3]))"
4552 [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
4553 (set (match_dup 0) (match_op_dup 6 [(match_dup 7) (match_dup 1)]))]
7faa3eb8
HPN
4554{
4555 operands[7] = gen_rtx_fmt_e (GET_CODE (operands[5]), GET_MODE (operands[5]),
4556 replace_equiv_address (XEXP (operands[5], 0),
4557 operands[4]));
4558 cris_order_for_addsi3 (operands, 2);
4559})
0b85d816
HPN
4560\f
4561;; Splits for addressing prefixes that have no side-effects, so we can
4562;; fill a delay slot. Never split if we lose something, though.
4563
4564;; If we have a
4565;; move [indirect_ref],rx
4566;; where indirect ref = {const, [r+], [r]}, it costs as much as
4567;; move indirect_ref,rx
4568;; move [rx],rx
4569;; Take care not to allow indirect_ref = register.
4570
4571;; We're not allowed to generate copies of registers with different mode
4572;; until after reload; copying pseudos upsets reload. CVS as of
4573;; 2001-08-24, unwind-dw2-fde.c, _Unwind_Find_FDE ICE in
a13a866e
HPN
4574;; cselib_invalidate_regno. Also, don't do this for the stack-pointer,
4575;; as we don't want it set temporarily to an invalid value.
0b85d816 4576
f60c7155 4577(define_split ; indir_to_reg_split
a13a866e 4578 [(set (match_operand 0 "cris_nonsp_register_operand" "")
0b85d816
HPN
4579 (match_operand 1 "indirect_operand" ""))]
4580 "reload_completed
4581 && REG_P (operands[0])
4582 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
991c42ac 4583 && (MEM_P (XEXP (operands[1], 0)) || CONSTANT_P (XEXP (operands[1], 0)))
f60c7155 4584 && REGNO (operands[0]) < CRIS_LAST_GENERAL_REGISTER"
0b85d816
HPN
4585 [(set (match_dup 2) (match_dup 4))
4586 (set (match_dup 0) (match_dup 3))]
4587 "operands[2] = gen_rtx_REG (Pmode, REGNO (operands[0]));
dbb138ce 4588 operands[3] = replace_equiv_address (operands[1], operands[2]);
0b85d816
HPN
4589 operands[4] = XEXP (operands[1], 0);")
4590
4591;; As the above, but MOVS and MOVU.
4592
4593(define_split
a13a866e 4594 [(set (match_operand 0 "cris_nonsp_register_operand" "")
0b85d816
HPN
4595 (match_operator
4596 4 "cris_extend_operator"
4597 [(match_operand 1 "indirect_operand" "")]))]
4598 "reload_completed
4599 && REG_P (operands[0])
4600 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
991c42ac 4601 && (MEM_P (XEXP (operands[1], 0))
0b85d816
HPN
4602 || CONSTANT_P (XEXP (operands[1], 0)))"
4603 [(set (match_dup 2) (match_dup 5))
4604 (set (match_dup 0) (match_op_dup 4 [(match_dup 3)]))]
4605 "operands[2] = gen_rtx_REG (Pmode, REGNO (operands[0]));
dbb138ce 4606 operands[3] = replace_equiv_address (XEXP (operands[4], 0), operands[2]);
0b85d816
HPN
4607 operands[5] = XEXP (operands[1], 0);")
4608\f
4609;; Various peephole optimizations.
4610;;
4611;; Watch out: when you exchange one set of instructions for another, the
4612;; condition codes setting must be the same, or you have to CC_INIT or
4613;; whatever is appropriate, in the pattern before you emit the
4614;; assembly text. This is best done here, not in cris_notice_update_cc,
4615;; to keep changes local to their cause.
4616;;
4617;; Do not add patterns that you do not know will be matched.
109b748d 4618;; Please also add a self-contained testcase.
0b85d816
HPN
4619
4620;; We have trouble with and:s and shifts. Maybe something is broken in
43a88a8c 4621;; gcc? Or it could just be that bit-field insn expansion is a bit
0b85d816 4622;; suboptimal when not having extzv insns.
8ad46d34 4623;; Testcase for the following four peepholes: gcc.dg/cris-peep2-xsrand.c
0b85d816 4624
8ad46d34
HPN
4625(define_peephole2 ; asrandb (peephole casesi+31)
4626 [(set (match_operand:SI 0 "register_operand" "")
0b85d816 4627 (ashiftrt:SI (match_dup 0)
8ad46d34 4628 (match_operand:SI 1 "const_int_operand" "")))
0b85d816
HPN
4629 (set (match_dup 0)
4630 (and:SI (match_dup 0)
8ad46d34 4631 (match_operand 2 "const_int_operand" "")))]
0b85d816
HPN
4632 "INTVAL (operands[2]) > 31
4633 && INTVAL (operands[2]) < 255
8ad46d34
HPN
4634 && INTVAL (operands[1]) > 23
4635 /* Check that the and-operation enables us to use logical-shift. */
4636 && (INTVAL (operands[2])
4637 & ((HOST_WIDE_INT) -1 << (32 - INTVAL (operands[1])))) == 0"
4638 [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
bf6ac87c 4639 (set (match_dup 3) (and:QI (match_dup 3) (match_dup 4)))]
8ad46d34 4640 ;; FIXME: CC0 is valid except for the M bit.
bf6ac87c
HPN
4641{
4642 operands[3] = gen_rtx_REG (QImode, REGNO (operands[0]));
4643 operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), QImode));
4644})
8ad46d34
HPN
4645
4646(define_peephole2 ; asrandw (peephole casesi+32)
4647 [(set (match_operand:SI 0 "register_operand" "")
0b85d816 4648 (ashiftrt:SI (match_dup 0)
8ad46d34 4649 (match_operand:SI 1 "const_int_operand" "")))
0b85d816 4650 (set (match_dup 0)
8ad46d34 4651 (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
0b85d816
HPN
4652 "INTVAL (operands[2]) > 31
4653 && INTVAL (operands[2]) < 65535
4654 && INTVAL (operands[2]) != 255
8ad46d34
HPN
4655 && INTVAL (operands[1]) > 15
4656 /* Check that the and-operation enables us to use logical-shift. */
4657 && (INTVAL (operands[2])
4658 & ((HOST_WIDE_INT) -1 << (32 - INTVAL (operands[1])))) == 0"
4659 [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
bf6ac87c 4660 (set (match_dup 3) (and:HI (match_dup 3) (match_dup 4)))]
8ad46d34 4661 ;; FIXME: CC0 is valid except for the M bit.
bf6ac87c
HPN
4662{
4663 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
4664 operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), HImode));
4665})
8ad46d34
HPN
4666
4667(define_peephole2 ; lsrandb (peephole casesi+33)
4668 [(set (match_operand:SI 0 "register_operand" "")
0b85d816 4669 (lshiftrt:SI (match_dup 0)
8ad46d34 4670 (match_operand:SI 1 "const_int_operand" "")))
0b85d816 4671 (set (match_dup 0)
8ad46d34 4672 (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
0b85d816
HPN
4673 "INTVAL (operands[2]) > 31
4674 && INTVAL (operands[2]) < 255
4675 && INTVAL (operands[1]) > 23"
8ad46d34 4676 [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
bf6ac87c 4677 (set (match_dup 3) (and:QI (match_dup 3) (match_dup 4)))]
8ad46d34 4678 ;; FIXME: CC0 is valid except for the M bit.
bf6ac87c
HPN
4679{
4680 operands[3] = gen_rtx_REG (QImode, REGNO (operands[0]));
4681 operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), QImode));
4682})
0b85d816 4683
8ad46d34
HPN
4684(define_peephole2 ; lsrandw (peephole casesi+34)
4685 [(set (match_operand:SI 0 "register_operand" "")
0b85d816 4686 (lshiftrt:SI (match_dup 0)
8ad46d34 4687 (match_operand:SI 1 "const_int_operand" "")))
0b85d816 4688 (set (match_dup 0)
8ad46d34 4689 (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
0b85d816
HPN
4690 "INTVAL (operands[2]) > 31 && INTVAL (operands[2]) < 65535
4691 && INTVAL (operands[2]) != 255
4692 && INTVAL (operands[1]) > 15"
8ad46d34 4693 [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
bf6ac87c 4694 (set (match_dup 3) (and:HI (match_dup 3) (match_dup 4)))]
8ad46d34 4695 ;; FIXME: CC0 is valid except for the M bit.
bf6ac87c
HPN
4696{
4697 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
4698 operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), HImode));
4699})
0b85d816
HPN
4700\f
4701
4702;; Change
4703;; add.d n,rx
4704;; move [rx],ry
4705;; into
4706;; move [rx=rx+n],ry
4707;; when -128 <= n <= 127.
4708;; This will reduce the size of the assembler code for n = [-128..127],
8ad46d34
HPN
4709;; and speed up accordingly. Don't match if the previous insn is
4710;; (set rx rz) because that combination is matched by another peephole.
4711;; No stable test-case.
4712
4713(define_peephole2 ; moversideqi (peephole casesi+35)
4714 [(set (match_operand:SI 0 "register_operand" "")
4715 (plus:SI (match_operand:SI 1 "register_operand" "")
4716 (match_operand:SI 2 "const_int_operand" "")))
4717 (set (match_operand 3 "register_operand" "")
4718 (match_operator 4 "cris_mem_op" [(match_dup 0)]))]
4719 "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
4720 && REGNO (operands[3]) != REGNO (operands[0])
a08160c3 4721 && (cris_base_p (operands[1], true) || cris_base_p (operands[2], true))
06cadf63
AS
4722 && !satisfies_constraint_J (operands[2])
4723 && !satisfies_constraint_N (operands[2])
45d5d09c
HPN
4724 && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)
4725 && TARGET_SIDE_EFFECT_PREFIXES"
8ad46d34
HPN
4726 [(parallel
4727 [(set (match_dup 3) (match_dup 5))
4728 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
4729 ;; Checking the previous insn is a bit too awkward for the condition.
4730{
e8a54173 4731 rtx_insn *prev = prev_nonnote_insn (curr_insn);
8ad46d34
HPN
4732 if (prev != NULL_RTX)
4733 {
4734 rtx set = single_set (prev);
4735 if (set != NULL_RTX
4736 && REG_S_P (SET_DEST (set))
4737 && REGNO (SET_DEST (set)) == REGNO (operands[0])
4738 && REG_S_P (SET_SRC (set)))
4739 FAIL;
4740 }
4741 operands[5]
4742 = replace_equiv_address (operands[4],
4743 gen_rtx_PLUS (SImode,
4744 operands[1], operands[2]));
4745})
0b85d816
HPN
4746
4747;; Vice versa: move ry,[rx=rx+n]
4748
8ad46d34
HPN
4749(define_peephole2 ; movemsideqi (peephole casesi+36)
4750 [(set (match_operand:SI 0 "register_operand" "")
4751 (plus:SI (match_operand:SI 1 "register_operand" "")
4752 (match_operand:SI 2 "const_int_operand" "")))
4753 (set (match_operator 3 "cris_mem_op" [(match_dup 0)])
4754 (match_operand 4 "register_operand" ""))]
4755 "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
4756 && REGNO (operands[4]) != REGNO (operands[0])
a08160c3 4757 && (cris_base_p (operands[1], true) || cris_base_p (operands[2], true))
06cadf63
AS
4758 && !satisfies_constraint_J (operands[2])
4759 && !satisfies_constraint_N (operands[2])
45d5d09c
HPN
4760 && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)
4761 && TARGET_SIDE_EFFECT_PREFIXES"
8ad46d34
HPN
4762 [(parallel
4763 [(set (match_dup 5) (match_dup 4))
4764 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
4765 "operands[5]
4766 = replace_equiv_address (operands[3],
4767 gen_rtx_PLUS (SImode,
4768 operands[1], operands[2]));")
0b85d816
HPN
4769\f
4770;; As above, change:
4771;; add.d n,rx
4772;; op.d [rx],ry
4773;; into:
4774;; op.d [rx=rx+n],ry
4775;; Saves when n = [-128..127].
4776;;
4777;; Splitting and joining combinations for side-effect modes are slightly
4778;; out of hand. They probably will not save the time they take typing in,
4779;; not to mention the bugs that creep in. FIXME: Get rid of as many of
4780;; the splits and peepholes as possible.
8ad46d34
HPN
4781;; No stable test-case.
4782
4783(define_peephole2 ; mover2side (peephole casesi+37)
4784 [(set (match_operand:SI 0 "register_operand" "")
4785 (plus:SI (match_operand:SI 1 "register_operand" "")
4786 (match_operand:SI 2 "const_int_operand" "")))
4787 (set (match_operand 3 "register_operand" "")
4788 (match_operator 4 "cris_orthogonal_operator"
4789 [(match_dup 3)
4790 (match_operator
4791 5 "cris_mem_op" [(match_dup 0)])]))]
477c433d
HPN
4792 ;; FIXME: What about DFmode?
4793 ;; Change to GET_MODE_SIZE (GET_MODE (operands[3])) <= UNITS_PER_WORD?
0b85d816 4794 "GET_MODE (operands[3]) != DImode
8ad46d34 4795 && REGNO (operands[0]) != REGNO (operands[3])
06cadf63
AS
4796 && !satisfies_constraint_J (operands[2])
4797 && !satisfies_constraint_N (operands[2])
8ad46d34 4798 && INTVAL (operands[2]) >= -128
45d5d09c
HPN
4799 && INTVAL (operands[2]) <= 127
4800 && TARGET_SIDE_EFFECT_PREFIXES"
8ad46d34
HPN
4801 [(parallel
4802 [(set (match_dup 3) (match_op_dup 4 [(match_dup 3) (match_dup 6)]))
4803 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
4804 "operands[6]
4805 = replace_equiv_address (operands[5],
4806 gen_rtx_PLUS (SImode,
4807 operands[1], operands[2]));")
0b85d816
HPN
4808
4809;; Sometimes, for some reason the pattern
4810;; move x,rx
4811;; add y,rx
4812;; move [rx],rz
4813;; will occur. Solve this, and likewise for to-memory.
8ad46d34 4814;; No stable test-case.
0b85d816 4815
8ad46d34
HPN
4816(define_peephole2 ; moverside (peephole casesi+38)
4817 [(set (match_operand:SI 0 "register_operand" "")
4818 (match_operand:SI 1 "cris_bdap_biap_operand" ""))
0b85d816 4819 (set (match_dup 0)
8ad46d34
HPN
4820 (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "")
4821 (match_operand:SI 3 "cris_bdap_biap_operand" "")))
4822 (set (match_operand 4 "register_operand" "")
4823 (match_operator 5 "cris_mem_op" [(match_dup 0)]))]
0b85d816
HPN
4824 "(rtx_equal_p (operands[2], operands[0])
4825 || rtx_equal_p (operands[3], operands[0]))
4826 && cris_side_effect_mode_ok (PLUS, operands, 0,
8ad46d34
HPN
4827 (REG_S_P (operands[1])
4828 ? 1
4829 : (rtx_equal_p (operands[2], operands[0])
4830 ? 3 : 2)),
4831 (! REG_S_P (operands[1])
4832 ? 1
4833 : (rtx_equal_p (operands[2], operands[0])
4834 ? 3 : 2)),
4835 -1, 4)"
4836 [(parallel
4837 [(set (match_dup 4) (match_dup 6))
4838 (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 8)))])]
4839{
e758023d 4840 rtx otherop
8ad46d34
HPN
4841 = rtx_equal_p (operands[2], operands[0]) ? operands[3] : operands[2];
4842
8820e4be
HPN
4843 /* Make sure we have canonical RTX so we match the insn pattern -
4844 not a constant in the first operand. We also require the order
4845 (plus reg mem) to match the final pattern. */
ab4e53fe 4846 if (CRIS_CONSTANT_P (otherop) || MEM_P (otherop))
8ad46d34
HPN
4847 {
4848 operands[7] = operands[1];
e758023d 4849 operands[8] = otherop;
8ad46d34
HPN
4850 }
4851 else
4852 {
e758023d 4853 operands[7] = otherop;
8ad46d34
HPN
4854 operands[8] = operands[1];
4855 }
4856 operands[6]
4857 = replace_equiv_address (operands[5],
4858 gen_rtx_PLUS (SImode,
4859 operands[7], operands[8]));
4860})
0b85d816
HPN
4861
4862;; As above but to memory.
8ad46d34
HPN
4863;; FIXME: Split movemside and moverside into variants and prune
4864;; the ones that don't trig.
4865;; No stable test-case.
0b85d816 4866
8ad46d34
HPN
4867(define_peephole2 ; movemside (peephole casesi+39)
4868 [(set (match_operand:SI 0 "register_operand" "")
4869 (match_operand:SI 1 "cris_bdap_biap_operand" ""))
0b85d816 4870 (set (match_dup 0)
8ad46d34
HPN
4871 (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "")
4872 (match_operand:SI 3 "cris_bdap_biap_operand" "")))
4873 (set (match_operator 4 "cris_mem_op" [(match_dup 0)])
4874 (match_operand 5 "register_operand" ""))]
0b85d816
HPN
4875 "(rtx_equal_p (operands[2], operands[0])
4876 || rtx_equal_p (operands[3], operands[0]))
4877 && cris_side_effect_mode_ok (PLUS, operands, 0,
8ad46d34
HPN
4878 (REG_S_P (operands[1])
4879 ? 1
4880 : (rtx_equal_p (operands[2], operands[0])
4881 ? 3 : 2)),
4882 (! REG_S_P (operands[1])
4883 ? 1
4884 : (rtx_equal_p (operands[2], operands[0])
4885 ? 3 : 2)),
4886 -1, 5)"
4887 [(parallel
4888 [(set (match_dup 6) (match_dup 5))
4889 (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 8)))])]
4890{
e758023d 4891 rtx otherop
8ad46d34 4892 = rtx_equal_p (operands[2], operands[0]) ? operands[3] : operands[2];
0b85d816 4893
8820e4be
HPN
4894 /* Make sure we have canonical RTX so we match the insn pattern -
4895 not a constant in the first operand. We also require the order
4896 (plus reg mem) to match the final pattern. */
ab4e53fe 4897 if (CRIS_CONSTANT_P (otherop) || MEM_P (otherop))
8ad46d34
HPN
4898 {
4899 operands[7] = operands[1];
e758023d 4900 operands[8] = otherop;
8ad46d34
HPN
4901 }
4902 else
4903 {
e758023d 4904 operands[7] = otherop;
8ad46d34
HPN
4905 operands[8] = operands[1];
4906 }
4907 operands[6]
4908 = replace_equiv_address (operands[4],
4909 gen_rtx_PLUS (SImode,
4910 operands[7], operands[8]));
4911})
0b85d816
HPN
4912
4913;; Another spotted bad code:
4914;; move rx,ry
4915;; move [ry],ry
8ad46d34 4916;; No stable test-case.
0b85d816 4917
8ad46d34
HPN
4918(define_peephole2 ; movei (peephole casesi+42)
4919 [(set (match_operand:SI 0 "register_operand" "")
4920 (match_operand:SI 1 "register_operand" ""))
4921 (set (match_operand 2 "register_operand" "")
4922 (match_operator 3 "cris_mem_op" [(match_dup 0)]))]
0b85d816 4923 "REGNO (operands[0]) == REGNO (operands[2])
f60c7155
HPN
4924 && (REGNO_REG_CLASS (REGNO (operands[0]))
4925 == REGNO_REG_CLASS (REGNO (operands[1])))
0b85d816 4926 && GET_MODE_SIZE (GET_MODE (operands[2])) <= UNITS_PER_WORD"
8ad46d34
HPN
4927 [(set (match_dup 2) (match_dup 4))]
4928 "operands[4] = replace_equiv_address (operands[3], operands[1]);")
0b85d816 4929
0b85d816
HPN
4930;; move.d [r10+16],r9
4931;; and.d r12,r9
4932;; change to
4933;; and.d [r10+16],r12,r9
4934;; With generalization of the operation, the size and the addressing mode.
4935;; This seems to be the result of a quirk in register allocation
4936;; missing the three-operand cases when having different predicates.
4937;; Maybe that it matters that it is a commutative operation.
4938;; This pattern helps that situation, but there's still the increased
4939;; register pressure.
4940;; Note that adding the noncommutative variant did not show any matches
4941;; in ipps and cc1, so it's not here.
8ad46d34 4942;; No stable test-case.
0b85d816 4943
8ad46d34
HPN
4944(define_peephole2 ; op3 (peephole casesi+44)
4945 [(set (match_operand 0 "register_operand" "")
4946 (match_operator
4947 6 "cris_mem_op"
4948 [(plus:SI
4949 (match_operand:SI 1 "cris_bdap_biap_operand" "")
4950 (match_operand:SI 2 "cris_bdap_biap_operand" ""))]))
0b85d816 4951 (set (match_dup 0)
8ad46d34
HPN
4952 (match_operator
4953 5 "cris_commutative_orth_op"
4954 [(match_operand 3 "register_operand" "")
4955 (match_operand 4 "register_operand" "")]))]
0b85d816
HPN
4956 "(rtx_equal_p (operands[3], operands[0])
4957 || rtx_equal_p (operands[4], operands[0]))
4958 && ! rtx_equal_p (operands[3], operands[4])
4959 && (REG_S_P (operands[1]) || REG_S_P (operands[2]))
4960 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD"
8ad46d34
HPN
4961 [(set (match_dup 0) (match_op_dup 5 [(match_dup 7) (match_dup 6)]))]
4962 "operands[7]
4963 = rtx_equal_p (operands[3], operands[0]) ? operands[4] : operands[3];")
0b85d816 4964
ff2ca1bc
HPN
4965;; There seems to be no other way to make GCC (including 4.8/trunk at
4966;; r186932) optimally reload an instruction that looks like
4967;; and.d reg_or_mem,const_32__65535,other_reg
4968;; where other_reg is the destination.
0b85d816 4969;; It should be:
ff2ca1bc
HPN
4970;; movu.[bw] reg_or_mem,reg_32
4971;; and.[bw] trunc_int_for_mode([bw], const_32__65535),reg_32 ;; or andq
365cacbf 4972;; but it turns into:
ff2ca1bc
HPN
4973;; move.d reg_or_mem,reg_32
4974;; and.d const_32__65535,reg_32
4975;; Fix it with these two peephole2's.
8ad46d34 4976;; Testcases: gcc.dg/cris-peep2-andu1.c gcc.dg/cris-peep2-andu2.c
0b85d816 4977
8ad46d34
HPN
4978(define_peephole2 ; andu (casesi+45)
4979 [(set (match_operand:SI 0 "register_operand" "")
4980 (match_operand:SI 1 "nonimmediate_operand" ""))
4981 (set (match_operand:SI 2 "register_operand" "")
0b85d816 4982 (and:SI (match_dup 0)
8ad46d34 4983 (match_operand:SI 3 "const_int_operand" "")))]
0b85d816
HPN
4984 ;; Since the size of the memory access could be made different here,
4985 ;; don't do this for a mem-volatile access.
0b85d816
HPN
4986 "REGNO (operands[2]) == REGNO (operands[0])
4987 && INTVAL (operands[3]) <= 65535 && INTVAL (operands[3]) >= 0
06cadf63 4988 && !satisfies_constraint_I (operands[3])
365cacbf
HPN
4989 && !side_effects_p (operands[1])
4990 && (!REG_P (operands[1])
4991 || REGNO (operands[1]) <= CRIS_LAST_GENERAL_REGISTER)"
8ad46d34
HPN
4992 ;; FIXME: CC0 valid except for M (i.e. CC_NOT_NEGATIVE).
4993 [(set (match_dup 0) (match_dup 4))
4994 (set (match_dup 5) (match_dup 6))]
0b85d816 4995{
ef4bddc2
RS
4996 machine_mode zmode = INTVAL (operands[3]) <= 255 ? QImode : HImode;
4997 machine_mode amode
06cadf63 4998 = satisfies_constraint_O (operands[3]) ? SImode : zmode;
8ad46d34
HPN
4999 rtx op1
5000 = (REG_S_P (operands[1])
5001 ? gen_rtx_REG (zmode, REGNO (operands[1]))
5002 : adjust_address (operands[1], zmode, 0));
5003 operands[4]
5004 = gen_rtx_ZERO_EXTEND (SImode, op1);
5005 operands[5] = gen_rtx_REG (amode, REGNO (operands[0]));
5006 operands[6]
5007 = gen_rtx_AND (amode, gen_rtx_REG (amode, REGNO (operands[0])),
5008 GEN_INT (trunc_int_for_mode (INTVAL (operands[3]),
5009 amode == SImode
5010 ? QImode : amode)));
5011})
c00fc5cf 5012
ff2ca1bc
HPN
5013;; Since r186861, gcc.dg/cris-peep2-andu2.c trigs this pattern, with which
5014;; we fix up e.g.:
5015;; movu.b 254,$r9.
5016;; and.d $r10,$r9
5017;; into:
5018;; movu.b $r10,$r9
5019;; andq -2,$r9.
5020;; Only do this for values fitting the quick immediate operand.
5021(define_peephole2 ; andqu (casesi+46)
5022 [(set (match_operand:SI 0 "register_operand")
5023 (match_operand:SI 1 "const_int_operand"))
5024 (set (match_dup 0)
5025 (and:SI (match_dup 0) (match_operand:SI 2 "nonimmediate_operand")))]
5026 ;; Since the size of the memory access will be made different here,
5027 ;; don't do this for a volatile access or a post-incremented address.
5028 "satisfies_constraint_O (operands[1])
5029 && !side_effects_p (operands[2])
5030 && !reg_overlap_mentioned_p (operands[0], operands[2])"
5031 [(set (match_dup 0) (match_dup 3))
5032 (set (match_dup 0) (and:SI (match_dup 0) (match_dup 4)))]
5033{
ef4bddc2 5034 machine_mode zmode = INTVAL (operands[2]) <= 255 ? QImode : HImode;
ff2ca1bc
HPN
5035 rtx op1
5036 = (REG_S_P (operands[2])
5037 ? gen_rtx_REG (zmode, REGNO (operands[2]))
5038 : adjust_address (operands[2], zmode, 0));
5039 operands[3] = gen_rtx_ZERO_EXTEND (SImode, op1);
5040 operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]), QImode));
5041})
5042
c00fc5cf
HPN
5043;; Try and avoid GOTPLT reads escaping a call: transform them into
5044;; PLT. Curiously (but thankfully), peepholes for instructions
5045;; *without side-effects* that just feed a call (or call_value) are
5046;; not matched neither in a build or test-suite, so those patterns are
5047;; omitted.
5048
5049;; A "normal" move where we don't check the consumer.
5050
5051(define_peephole2 ; gotplt-to-plt
5052 [(set
5053 (match_operand:SI 0 "register_operand" "")
5054 (match_operator:SI
5055 1 "cris_mem_op"
5056 [(plus:SI
5057 (reg:SI CRIS_GOT_REGNUM)
5058 (const:SI
5059 (unspec:SI [(match_operand:SI 2 "cris_general_operand_or_symbol" "")]
5060 CRIS_UNSPEC_PLTGOTREAD)))]))]
5061 "flag_pic
45d5d09c 5062 && cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
c00fc5cf 5063 && REGNO_REG_CLASS (REGNO (operands[0])) == REGNO_REG_CLASS (0)"
45d5d09c 5064 [(set (match_dup 0) (const:SI (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLT_GOTREL)))
c00fc5cf
HPN
5065 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI CRIS_GOT_REGNUM)))]
5066 "")
5067
5068;; And one set with a side-effect getting the PLTGOT offset.
5069;; First call and call_value variants.
5070
5071(define_peephole2 ; gotplt-to-plt-side-call
5072 [(parallel
5073 [(set
5074 (match_operand:SI 0 "register_operand" "")
5075 (match_operator:SI
5076 1 "cris_mem_op"
5077 [(plus:SI
5078 (reg:SI CRIS_GOT_REGNUM)
5079 (const:SI
5080 (unspec:SI [(match_operand:SI
5081 2 "cris_general_operand_or_symbol" "")]
5082 CRIS_UNSPEC_PLTGOTREAD)))]))
5083 (set (match_operand:SI 3 "register_operand" "")
5084 (plus:SI (reg:SI CRIS_GOT_REGNUM)
5085 (const:SI
5086 (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLTGOTREAD))))])
5087 (parallel [(call (mem:QI (match_dup 0))
5088 (match_operand 4 "" ""))
5089 (clobber (reg:SI CRIS_SRP_REGNUM))])]
5090 "flag_pic
45d5d09c 5091 && cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
c00fc5cf
HPN
5092 && peep2_reg_dead_p (2, operands[0])"
5093 [(parallel [(call (mem:QI (match_dup 1))
5094 (match_dup 4))
5095 (clobber (reg:SI CRIS_SRP_REGNUM))
5096 (set (match_dup 3)
5097 (plus:SI (reg:SI CRIS_GOT_REGNUM)
5098 (const:SI
5099 (unspec:SI [(match_dup 2)]
5100 CRIS_UNSPEC_PLTGOTREAD))))])]
5101 "")
5102
5103(define_peephole2 ; gotplt-to-plt-side-call-value
5104 [(parallel
5105 [(set
5106 (match_operand:SI 0 "register_operand" "")
5107 (match_operator:SI
5108 1 "cris_mem_op"
5109 [(plus:SI
5110 (reg:SI CRIS_GOT_REGNUM)
5111 (const:SI
5112 (unspec:SI [(match_operand:SI
5113 2 "cris_general_operand_or_symbol" "")]
5114 CRIS_UNSPEC_PLTGOTREAD)))]))
5115 (set (match_operand:SI 3 "register_operand" "")
5116 (plus:SI (reg:SI CRIS_GOT_REGNUM)
5117 (const:SI
5118 (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLTGOTREAD))))])
5119 (parallel [(set (match_operand 5 "" "")
5120 (call (mem:QI (match_dup 0))
5121 (match_operand 4 "" "")))
5122 (clobber (reg:SI CRIS_SRP_REGNUM))])]
5123 "flag_pic
45d5d09c 5124 && cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
c00fc5cf
HPN
5125 && peep2_reg_dead_p (2, operands[0])"
5126 [(parallel [(set (match_dup 5)
5127 (call (mem:QI (match_dup 1))
5128 (match_dup 4)))
5129 (clobber (reg:SI CRIS_SRP_REGNUM))
5130 (set (match_dup 3)
5131 (plus:SI (reg:SI CRIS_GOT_REGNUM)
5132 (const:SI
5133 (unspec:SI [(match_dup 2)]
5134 CRIS_UNSPEC_PLTGOTREAD))))])]
5135 "")
5136
5137(define_peephole2 ; gotplt-to-plt-side
5138 [(parallel
5139 [(set
5140 (match_operand:SI 0 "register_operand" "")
5141 (match_operator:SI
5142 1 "cris_mem_op"
5143 [(plus:SI
5144 (reg:SI CRIS_GOT_REGNUM)
5145 (const:SI
5146 (unspec:SI [(match_operand:SI
5147 2 "cris_general_operand_or_symbol" "")]
5148 CRIS_UNSPEC_PLTGOTREAD)))]))
5149 (set (match_operand:SI 3 "register_operand" "")
5150 (plus:SI (reg:SI CRIS_GOT_REGNUM)
5151 (const:SI
5152 (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLTGOTREAD))))])]
5153 "flag_pic
45d5d09c 5154 && cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
c00fc5cf
HPN
5155 && REGNO_REG_CLASS (REGNO (operands[0])) == REGNO_REG_CLASS (0)"
5156 [(set (match_dup 3)
5157 (const:SI (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLTGOTREAD)))
5158 (set (match_dup 3) (plus:SI (match_dup 3) (reg:SI CRIS_GOT_REGNUM)))
45d5d09c
HPN
5159 (set (match_dup 0)
5160 (const:SI (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLT_GOTREL)))
c00fc5cf
HPN
5161 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI CRIS_GOT_REGNUM)))]
5162 "")
0b85d816
HPN
5163\f
5164;; Local variables:
5165;; mode:emacs-lisp
5166;; comment-start: ";; "
5167;; eval: (set-syntax-table (copy-sequence (syntax-table)))
5168;; eval: (modify-syntax-entry ?[ "(]")
5169;; eval: (modify-syntax-entry ?] ")[")
5170;; eval: (modify-syntax-entry ?{ "(}")
5171;; eval: (modify-syntax-entry ?} "){")
5172;; eval: (setq indent-tabs-mode t)
5173;; End: