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