]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/cris/cris.md
[multiple changes]
[thirdparty/gcc.git] / gcc / config / cris / cris.md
CommitLineData
0b85d816 1;; GCC machine description for CRIS cpu cores.
23369bef 2;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
1c563bed 3;; 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
10;; the Free Software Foundation; either version 2, or (at your option)
11;; any later version.
12;;
13;; GCC is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17;;
18;; You should have received a copy of the GNU General Public License
19;; along with GCC; see the file COPYING. If not, write to
39d14dda
KC
20;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21;; Boston, MA 02110-1301, USA.
0b85d816
HPN
22
23;; The original PO technology requires these to be ordered by speed,
24;; so that assigner will pick the fastest.
25
26;; See files "md.texi" and "rtl.def" for documentation on define_insn,
27;; match_*, et. al.
28;;
29;; The function cris_notice_update_cc in cris.c handles condition code
30;; updates for most instructions, helped by the "cc" attribute.
31
32;; There are several instructions that are orthogonal in size, and seems
33;; they could be matched by a single pattern without a specified size
34;; for the operand that is orthogonal. However, this did not work on
839a4992 35;; gcc-2.7.2 (and probably not on gcc-2.8.1), relating to that when a
0b85d816
HPN
36;; constant is substituted into an operand, the actual mode must be
37;; deduced from the pattern. There is reasonable hope that that has been
d2f55c5c 38;; fixed, so FIXME: try again.
0b85d816
HPN
39
40;; You will notice that three-operand alternatives ("=r", "r", "!To")
41;; are marked with a "!" constraint modifier to avoid being reloaded
42;; into. This is because gcc would otherwise prefer to use the constant
43;; pool and its offsettable address instead of reloading to an
44;; ("=r", "0", "i") alternative. Also, the constant-pool support was not
45;; only suboptimal but also buggy in 2.7.2, ??? maybe only in 2.6.3.
46
47;; All insns that look like (set (...) (plus (...) (reg:SI 8)))
48;; get problems when reloading r8 (frame pointer) to r14 + offs (stack
49;; pointer). Thus the instructions that get into trouble have specific
50;; checks against matching frame_pointer_rtx.
51;; ??? But it should be re-checked for gcc > 2.7.2
52;; FIXME: This changed some time ago (from 2000-03-16) for gcc-2.9x.
53
54;; FIXME: When PIC, all [rX=rY+S] could be enabled to match
55;; [rX=gotless_symbol].
56;; The movsi for a gotless symbol could be split (post reload).
57\f
58;; UNSPEC Usage:
59;; 0 PLT reference from call expansion: operand 0 is the address,
60;; the mode is VOIDmode. Always wrapped in CONST.
04539954 61;; 1 Stack frame deallocation barrier.
d29b4b1b 62;; 2 The address of the global offset table as a source operand.
04539954
HPN
63
64(define_constants
65 [(CRIS_UNSPEC_PLT 0)
d29b4b1b
HPN
66 (CRIS_UNSPEC_FRAME_DEALLOC 1)
67 (CRIS_UNSPEC_GOT 2)])
f60c7155
HPN
68
69;; Register numbers.
70(define_constants
71 [(CRIS_GOT_REGNUM 0)
72 (CRIS_STATIC_CHAIN_REGNUM 7)
73 (CRIS_FP_REGNUM 8)
74 (CRIS_SP_REGNUM 14)
75 (CRIS_SRP_REGNUM 16)
76 (CRIS_AP_REGNUM 17)
77 (CRIS_MOF_REGNUM 18)]
78)
79
0b85d816
HPN
80;; We need an attribute to define whether an instruction can be put in
81;; a branch-delay slot or not, and whether it has a delay slot.
82;;
83;; Branches and return instructions have a delay slot, and cannot
84;; themselves be put in a delay slot. This has changed *for short
85;; branches only* between architecture variants, but the possible win
86;; is presumed negligible compared to the added complexity of the machine
87;; description: one would have to add always-correct infrastructure to
88;; distinguish short branches.
89;;
90;; Whether an instruction can be put in a delay slot depends on the
91;; instruction (all short instructions except jumps and branches)
92;; and the addressing mode (must not be prefixed or referring to pc).
93;; In short, any "slottable" instruction must be 16 bit and not refer
94;; to pc, or alter it.
95;;
96;; The possible values are "yes", "no" and "has_slot". Yes/no means if
97;; the insn is slottable or not. Has_slot means that the insn is a
98;; return insn or branch insn (which are not considered slottable since
839a4992 99;; that is generally true). Having the seemingly illogical value
0b85d816
HPN
100;; "has_slot" means we do not have to add another attribute just to say
101;; that an insn has a delay-slot, since it also infers that it is not
102;; slottable. Better names for the attribute were found to be longer and
103;; not add readability to the machine description.
104;;
105;; The default that is defined here for this attribute is "no", not
106;; slottable, not having a delay-slot, so there's no need to worry about
107;; it being wrong for non-branch and return instructions.
108;; The default could depend on the kind of insn and the addressing
109;; mode, but that would need more attributes and hairier, more error
110;; prone code.
111;;
23369bef
HPN
112;; There is an extra memory constraint, 'Q', which recognizes an indirect
113;; register. The constraints 'Q' and '>' together match all possible
114;; memory operands that are slottable.
0b85d816
HPN
115;; For other operands, you need to check if it has a valid "slottable"
116;; quick-immediate operand, where the particular signedness-variation
117;; may match the constraints 'I' or 'J'.), and include it in the
118;; constraint pattern for the slottable pattern. An alternative using
119;; only "r" constraints is most often slottable.
120
121(define_attr "slottable" "no,yes,has_slot" (const_string "no"))
122
123;; We also need attributes to sanely determine the condition code
124;; state. See cris_notice_update_cc for how this is used.
125
126(define_attr "cc" "none,clobber,normal" (const_string "normal"))
127
3a5afdfc
HPN
128;; At the moment, this attribute is just used to help bb-reorder do its
129;; work; the default 0 doesn't help it. Many insns have other lengths,
130;; though none are shorter.
131(define_attr "length" "" (const_int 2))
132
0b85d816
HPN
133;; A branch or return has one delay-slot. The instruction in the
134;; delay-slot is always executed, independent of whether the branch is
135;; taken or not. Note that besides setting "slottable" to "has_slot",
136;; there also has to be a "%#" at the end of a "delayed" instruction
137;; output pattern (for "jump" this means "ba %l0%#"), so print_operand can
138;; catch it and print a "nop" if necessary. This method was stolen from
139;; sparc.md.
140
141(define_delay (eq_attr "slottable" "has_slot")
142 [(eq_attr "slottable" "yes") (nil) (nil)])
143\f
22c3c091
HPN
144;; Iterator definitions.
145
146;; For the "usual" pattern size alternatives.
147(define_mode_macro BWD [SI HI QI])
148(define_mode_macro WD [SI HI])
149(define_mode_macro BW [HI QI])
150(define_mode_attr S [(SI "HI") (HI "QI")])
151(define_mode_attr s [(SI "hi") (HI "qi")])
152(define_mode_attr m [(SI ".d") (HI ".w") (QI ".b")])
153(define_mode_attr mm [(SI ".w") (HI ".b")])
154(define_mode_attr nbitsm1 [(SI "31") (HI "15") (QI "7")])
155
156;; For the sign_extend+zero_extend variants.
157(define_code_macro szext [sign_extend zero_extend])
158(define_code_attr u [(sign_extend "") (zero_extend "u")])
159(define_code_attr su [(sign_extend "s") (zero_extend "u")])
160
161;; For the shift variants.
162(define_code_macro shift [ashiftrt lshiftrt ashift])
163(define_code_macro shiftrt [ashiftrt lshiftrt])
164(define_code_attr shlr [(ashiftrt "ashr") (lshiftrt "lshr") (ashift "ashl")])
165(define_code_attr slr [(ashiftrt "asr") (lshiftrt "lsr") (ashift "lsl")])
166
22c3c091 167(define_code_macro ncond [eq ne gtu ltu geu leu])
22c3c091 168(define_code_macro ocond [gt le])
22c3c091 169(define_code_macro rcond [lt ge])
22c3c091
HPN
170(define_code_attr CC [(eq "eq") (ne "ne") (gt "gt") (gtu "hi") (lt "lt")
171 (ltu "lo") (ge "ge") (geu "hs") (le "le") (leu "ls")])
172(define_code_attr rCC [(eq "ne") (ne "eq") (gt "le") (gtu "ls") (lt "ge")
173 (ltu "hs") (ge "lt") (geu "lo") (le "gt") (leu "hi")])
174(define_code_attr oCC [(lt "mi") (ge "pl")])
175(define_code_attr roCC [(lt "pl") (ge "mi")])
176
68a81332
HPN
177;; Operand and operator predicates.
178
179(include "predicates.md")
180\f
0b85d816
HPN
181;; Test insns.
182
183;; DImode
184;;
185;; Allow register and offsettable mem operands only; post-increment is
186;; not worth the trouble.
187
188(define_insn "tstdi"
189 [(set (cc0)
190 (match_operand:DI 0 "nonimmediate_operand" "r,o"))]
191 ""
192 "test.d %M0\;ax\;test.d %H0")
193
194;; No test insns with side-effect on the mem addressing.
195;;
196;; See note on cmp-insns with side-effects (or lack of them)
197
198;; Normal named test patterns from SI on.
199;; FIXME: Seems they should change to be in order smallest..largest.
200
22c3c091 201(define_insn "tst<mode>"
0b85d816 202 [(set (cc0)
22c3c091 203 (match_operand:BWD 0 "nonimmediate_operand" "r,Q>,m"))]
0b85d816 204 ""
22c3c091 205 "test<m> %0"
0b85d816
HPN
206 [(set_attr "slottable" "yes,yes,no")])
207
208;; It seems that the position of the sign-bit and the fact that 0.0 is
209;; all 0-bits would make "tstsf" a straight-forward implementation;
210;; either "test.d" it for positive/negative or "btstq 30,r" it for
211;; zeroness.
212;;
213;; FIXME: Do that some time; check next_cc0_user to determine if
214;; zero or negative is tested for.
215\f
216;; Compare insns.
217
218;; We could optimize the sizes of the immediate operands for various
219;; cases, but that is not worth it because of the very little usage of
220;; DImode for anything else but a structure/block-mode. Just do the
221;; obvious stuff for the straight-forward constraint letters.
222
223(define_insn "cmpdi"
224 [(set (cc0)
225 (compare (match_operand:DI 0 "nonimmediate_operand" "r,r,r,r,r,r,o")
226 (match_operand:DI 1 "general_operand" "K,I,P,n,r,o,r")))]
227 ""
228 "@
229 cmpq %1,%M0\;ax\;cmpq 0,%H0
230 cmpq %1,%M0\;ax\;cmpq -1,%H0
231 cmp%e1.%z1 %1,%M0\;ax\;cmpq %H1,%H0
232 cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0
233 cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0
234 cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0
235 cmp.d %M0,%M1\;ax\;cmp.d %H0,%H1")
236
237;; Note that compare insns with side effect addressing mode (e.g.):
238;;
239;; cmp.S [rx=ry+i],rz;
240;; cmp.S [%3=%1+%2],%0
241;;
242;; are *not* usable for gcc since the reloader *does not accept*
243;; cc0-changing insns with side-effects other than setting the condition
244;; codes. The reason is that the reload stage *may* cause another insn to
245;; be output after the main instruction, in turn invalidating cc0 for the
246;; insn using the test. (This does not apply to the CRIS case, since a
247;; reload for output -- move to memory -- does not change the condition
248;; code. Unfortunately we have no way to describe that at the moment. I
249;; think code would improve being in the order of one percent faster.
250\f
251;; We have cmps and cmpu (compare reg w. sign/zero extended mem).
252;; These are mostly useful for compares in SImode, using 8 or 16-bit
253;; constants, but sometimes gcc will find its way to use it for other
254;; (memory) operands. Avoid side-effect patterns, though (see above).
0b85d816 255
22c3c091 256(define_insn "*cmp_ext<mode>"
0b85d816
HPN
257 [(set (cc0)
258 (compare
259 (match_operand:SI 0 "register_operand" "r,r")
260 (match_operator:SI 2 "cris_extend_operator"
22c3c091 261 [(match_operand:BW 1 "memory_operand" "Q>,m")])))]
0b85d816 262 ""
22c3c091 263 "cmp%e2<m> %1,%0"
0b85d816
HPN
264 [(set_attr "slottable" "yes,no")])
265
266;; Swap operands; it seems the canonical look (if any) is not enforced.
267;;
268;; FIXME: Investigate that.
0b85d816 269
22c3c091 270(define_insn "*cmp_swapext<mode>"
0b85d816
HPN
271 [(set (cc0)
272 (compare
273 (match_operator:SI 2 "cris_extend_operator"
22c3c091 274 [(match_operand:BW 0 "memory_operand" "Q>,m")])
0b85d816
HPN
275 (match_operand:SI 1 "register_operand" "r,r")))]
276 ""
22c3c091 277 "cmp%e2<m> %0,%1" ; The function cris_notice_update_cc knows about
0b85d816
HPN
278 ; swapped operands to compares.
279 [(set_attr "slottable" "yes,no")])
280\f
281;; The "normal" compare patterns, from SI on.
282
283(define_insn "cmpsi"
284 [(set (cc0)
285 (compare
23369bef
HPN
286 (match_operand:SI 0 "nonimmediate_operand" "r,r,r, r,Q>,Q>,r,r,m,m")
287 (match_operand:SI 1 "general_operand" "I,r,Q>,M,M, r, P,g,M,r")))]
0b85d816
HPN
288 ""
289 "@
290 cmpq %1,%0
291 cmp.d %1,%0
292 cmp.d %1,%0
293 test.d %0
294 test.d %0
295 cmp.d %0,%1
296 cmp%e1.%z1 %1,%0
297 cmp.d %1,%0
298 test.d %0
299 cmp.d %0,%1"
300 [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no")])
301
22c3c091 302(define_insn "cmp<mode>"
0b85d816
HPN
303 [(set (cc0)
304 (compare
22c3c091
HPN
305 (match_operand:BW 0 "nonimmediate_operand" "r,r, r,Q>,Q>,r,m,m")
306 (match_operand:BW 1 "general_operand" "r,Q>,M,M, r, g,M,r")))]
0b85d816
HPN
307 ""
308 "@
22c3c091
HPN
309 cmp<m> %1,%0
310 cmp<m> %1,%0
311 test<m> %0
312 test<m> %0
313 cmp<m> %0,%1
314 cmp<m> %1,%0
315 test<m> %0
316 cmp<m> %0,%1"
0b85d816
HPN
317 [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")])
318\f
319;; Pattern matching the BTST insn.
320;; It is useful for "if (i & val)" constructs, where val is an exact
321;; power of 2, or if val + 1 is a power of two, where we check for a bunch
322;; of zeros starting at bit 0).
323
324;; SImode. This mode is the only one needed, since gcc automatically
109b748d 325;; extends subregs for lower-size modes. FIXME: Add testcase.
0b85d816
HPN
326(define_insn "*btst"
327 [(set (cc0)
328 (zero_extract
329 (match_operand:SI 0 "nonmemory_operand" "r,r,r,r,r,r,n")
330 (match_operand:SI 1 "const_int_operand" "K,n,K,n,K,n,n")
331 (match_operand:SI 2 "nonmemory_operand" "M,M,K,n,r,r,r")))]
332 ;; Either it is a single bit, or consecutive ones starting at 0.
333 "GET_CODE (operands[1]) == CONST_INT
334 && (operands[1] == const1_rtx || operands[2] == const0_rtx)
335 && (REG_S_P (operands[0])
336 || (operands[1] == const1_rtx
337 && REG_S_P (operands[2])
338 && GET_CODE (operands[0]) == CONST_INT
339 && exact_log2 (INTVAL (operands[0])) >= 0))"
340
341;; The last "&&" condition above should be caught by some kind of
342;; canonicalization in gcc, but we can easily help with it here.
343;; It results from expressions of the type
344;; "power_of_2_value & (1 << y)".
345;;
346;; Since there may be codes with tests in on bits (in constant position)
347;; beyond the size of a word, handle that by assuming those bits are 0.
348;; GCC should handle that, but it's a matter of easily-added belts while
349;; having suspenders.
350
351 "@
352 btstq (%1-1),%0
353 test.d %0
354 btstq %2,%0
355 clearf nz
356 btst %2,%0
357 clearf nz
358 cmpq %p0,%2"
359 [(set_attr "slottable" "yes")])
360\f
361;; Move insns.
362
363;; The whole mandatory movdi family is here; expander, "anonymous"
364;; recognizer and splitter. We're forced to have a movdi pattern,
365;; although GCC should be able to split it up itself. Normally it can,
366;; but if other insns have DI operands (as is the case here), reload
367;; must be able to generate or match a movdi. many testcases fail at
368;; -O3 or -fssa if we don't have this. FIXME: Fix GCC... See
369;; <URL:http://gcc.gnu.org/ml/gcc-patches/2000-04/msg00104.html>.
370;; However, a patch from Richard Kenner (similar to the cause of
371;; discussion at the URL above), indicates otherwise. See
372;; <URL:http://gcc.gnu.org/ml/gcc-patches/2000-04/msg00554.html>.
373;; The truth has IMO is not been decided yet, so check from time to
374;; time by disabling the movdi patterns.
375
22c3c091
HPN
376;; To appease testcase gcc.c-torture/execute/920501-2.c (and others) at
377;; -O0, we need a movdi as a temporary measure. Here's how things fail:
378;; A cmpdi RTX needs reloading (global):
379;; (insn 185 326 186 (set (cc0)
380;; (compare (mem/f:DI (reg/v:SI 22) 0)
381;; (const_int 1 [0x1]))) 4 {cmpdi} (nil)
382;; (nil))
383;; Now, reg 22 is reloaded for input address, and the mem is also moved
384;; out of the instruction (into a register), since one of the operands
385;; must be a register. Reg 22 is reloaded (into reg 10), and the mem is
386;; moved out and synthesized in SImode parts (reg 9, reg 10 - should be ok
387;; wrt. overlap). The bad things happen with the synthesis in
388;; emit_move_insn_1; the location where to substitute reg 10 is lost into
389;; two new RTX:es, both still having reg 22. Later on, the left-over reg
390;; 22 is recognized to have an equivalent in memory which is substituted
391;; straight in, and we end up with an unrecognizable insn:
392;; (insn 325 324 326 (set (reg:SI 9 r9)
393;; (mem/f:SI (mem:SI (plus:SI (reg:SI 8 r8)
394;; (const_int -84 [0xffffffac])) 0) 0)) -1 (nil)
395;; (nil))
396;; which is the first part of the reloaded synthesized "movdi".
397;; The right thing would be to add equivalent replacement locations for
398;; insn with pseudos that need more reloading. The question is where.
399
0b85d816
HPN
400(define_expand "movdi"
401 [(set (match_operand:DI 0 "nonimmediate_operand" "")
402 (match_operand:DI 1 "general_operand" ""))]
403 ""
0b85d816
HPN
404{
405 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
406 operands[1] = copy_to_mode_reg (DImode, operands[1]);
407
408 /* Some other ports (as of 2001-09-10 for example mcore and romp) also
409 prefer to split up constants early, like this. The testcase in
410 gcc.c-torture/execute/961213-1.c shows that CSE2 gets confused by the
411 resulting subreg sets when using the construct from mcore (as of FSF
049746c2 412 CVS, version -r 1.5), and it believes that the high part (the last one
0b85d816
HPN
413 emitted) is the final value. This construct from romp seems more
414 robust, especially considering the head comments from
415 emit_no_conflict_block. */
416 if ((GET_CODE (operands[1]) == CONST_INT
417 || GET_CODE (operands[1]) == CONST_DOUBLE)
418 && ! reload_completed
419 && ! reload_in_progress)
420 {
421 rtx insns;
422 rtx op0 = operands[0];
423 rtx op1 = operands[1];
424
425 start_sequence ();
426 emit_move_insn (operand_subword (op0, 0, 1, DImode),
427 operand_subword (op1, 0, 1, DImode));
428 emit_move_insn (operand_subword (op0, 1, 1, DImode),
429 operand_subword (op1, 1, 1, DImode));
430 insns = get_insns ();
431 end_sequence ();
432
433 emit_no_conflict_block (insns, op0, op1, 0, op1);
434 DONE;
435 }
22c3c091 436})
0b85d816
HPN
437
438(define_insn "*movdi_insn"
477c433d
HPN
439 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rx,m")
440 (match_operand:DI 1 "general_operand" "rx,g,rxM"))]
0b85d816
HPN
441 "register_operand (operands[0], DImode)
442 || register_operand (operands[1], DImode)
443 || operands[1] == const0_rtx"
444 "#")
445
446(define_split
447 [(set (match_operand:DI 0 "nonimmediate_operand" "")
448 (match_operand:DI 1 "general_operand" ""))]
449 "reload_completed"
450 [(match_dup 2)]
451 "operands[2] = cris_split_movdx (operands);")
452\f
453;; Side-effect patterns for move.S1 [rx=ry+rx.S2],rw
454;; and move.S1 [rx=ry+i],rz
455;; Then movs.S1 and movu.S1 for both modes.
456;;
457;; move.S1 [rx=ry+rz.S],rw avoiding when rx is ry, or rw is rx
458;; FIXME: These could have anonymous mode for operand 0.
459
22c3c091
HPN
460(define_insn "*mov_side<mode>_biap"
461 [(set (match_operand:BW 0 "register_operand" "=r,r")
462 (mem:BW (plus:SI
0b85d816
HPN
463 (mult:SI (match_operand:SI 1 "register_operand" "r,r")
464 (match_operand:SI 2 "const_int_operand" "n,n"))
465 (match_operand:SI 3 "register_operand" "r,r"))))
466 (set (match_operand:SI 4 "register_operand" "=*3,r")
467 (plus:SI (mult:SI (match_dup 1)
468 (match_dup 2))
469 (match_dup 3)))]
470 "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
471 "@
472 #
22c3c091 473 move<m> [%4=%3+%1%T2],%0")
0b85d816 474
8ad46d34 475(define_insn "*mov_sidesisf_biap"
477c433d 476 [(set (match_operand 0 "register_operand" "=r,r,x,x")
8ad46d34 477 (mem (plus:SI
477c433d
HPN
478 (mult:SI (match_operand:SI 1 "register_operand" "r,r,r,r")
479 (match_operand:SI 2 "const_int_operand" "n,n,n,n"))
480 (match_operand:SI 3 "register_operand" "r,r,r,r"))))
481 (set (match_operand:SI 4 "register_operand" "=*3,r,*3,r")
0b85d816
HPN
482 (plus:SI (mult:SI (match_dup 1)
483 (match_dup 2))
484 (match_dup 3)))]
8ad46d34
HPN
485 "GET_MODE_SIZE (GET_MODE (operands[0])) == UNITS_PER_WORD
486 && cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
0b85d816
HPN
487 "@
488 #
477c433d
HPN
489 move.%s0 [%4=%3+%1%T2],%0
490 #
491 move [%4=%3+%1%T2],%0")
0b85d816
HPN
492\f
493;; move.S1 [rx=ry+i],rz
494;; avoiding move.S1 [ry=ry+i],rz
495;; and move.S1 [rz=ry+i],rz
496;; Note that "i" is allowed to be a register.
0b85d816 497
22c3c091
HPN
498(define_insn "*mov_side<mode>"
499 [(set (match_operand:BW 0 "register_operand" "=r,r,r")
500 (mem:BW
0b85d816 501 (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,r,r")
747a0d9d 502 (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn"))))
0b85d816
HPN
503 (set (match_operand:SI 3 "register_operand" "=*1,r,r")
504 (plus:SI (match_dup 1)
505 (match_dup 2)))]
506 "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
0b85d816
HPN
507{
508 if (which_alternative == 0
509 && (GET_CODE (operands[2]) != CONST_INT
510 || INTVAL (operands[2]) > 127
511 || INTVAL (operands[2]) < -128
512 || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
513 || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
22c3c091
HPN
514 return "#";
515 return "move<m> [%3=%1%S2],%0";
516})
0b85d816 517
8ad46d34 518(define_insn "*mov_sidesisf"
477c433d 519 [(set (match_operand 0 "register_operand" "=r,r,r,x,x,x")
8ad46d34 520 (mem
477c433d
HPN
521 (plus:SI
522 (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,r,r,r")
523 (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r>Rn,r,>Rn"))))
524 (set (match_operand:SI 3 "register_operand" "=*1,r,r,*1,r,r")
0b85d816
HPN
525 (plus:SI (match_dup 1)
526 (match_dup 2)))]
8ad46d34
HPN
527 "GET_MODE_SIZE (GET_MODE (operands[0])) == UNITS_PER_WORD
528 && cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
0b85d816 529{
477c433d 530 if ((which_alternative == 0 || which_alternative == 3)
0b85d816
HPN
531 && (GET_CODE (operands[2]) != CONST_INT
532 || INTVAL (operands[2]) > 127
533 || INTVAL (operands[2]) < -128
534 || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
535 || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
477c433d
HPN
536 return "#";
537 if (which_alternative < 3)
538 return "move.%s0 [%3=%1%S2],%0";
539 return "move [%3=%1%S2],%0";
540})
0b85d816
HPN
541\f
542;; Other way around; move to memory.
543
049746c2
HPN
544;; Note that the condition (which for side-effect patterns is usually a
545;; call to cris_side_effect_mode_ok), isn't consulted for register
546;; allocation preferences -- constraints is the method for that. The
547;; drawback is that we can't exclude register allocation to cause
548;; "move.s rw,[rx=ry+rz.S]" when rw==rx without also excluding rx==ry or
549;; rx==rz if we use an earlyclobber modifier for the constraint for rx.
550;; Instead of that, we recognize and split the cases where dangerous
551;; register combinations are spotted: where a register is set in the
552;; side-effect, and used in the main insn. We don't handle the case where
553;; the set in the main insn overlaps the set in the side-effect; that case
554;; must be handled in gcc. We handle just the case where the set in the
555;; side-effect overlaps the input operand of the main insn (i.e. just
556;; moves to memory).
0b85d816
HPN
557
558;;
049746c2 559;; move.s rz,[ry=rx+rw.S]
0b85d816 560
22c3c091
HPN
561(define_insn "*mov_side<mode>_biap_mem"
562 [(set (mem:BW (plus:SI
0b85d816
HPN
563 (mult:SI (match_operand:SI 0 "register_operand" "r,r,r")
564 (match_operand:SI 1 "const_int_operand" "n,n,n"))
565 (match_operand:SI 2 "register_operand" "r,r,r")))
22c3c091 566 (match_operand:BW 3 "register_operand" "r,r,r"))
049746c2 567 (set (match_operand:SI 4 "register_operand" "=*2,!3,r")
0b85d816
HPN
568 (plus:SI (mult:SI (match_dup 0)
569 (match_dup 1))
570 (match_dup 2)))]
571 "cris_side_effect_mode_ok (MULT, operands, 4, 2, 0, 1, 3)"
572 "@
573 #
574 #
22c3c091 575 move<m> %3,[%4=%2+%0%T1]")
0b85d816 576
8ad46d34
HPN
577(define_insn "*mov_sidesisf_biap_mem"
578 [(set (mem (plus:SI
477c433d
HPN
579 (mult:SI (match_operand:SI 0 "register_operand" "r,r,r,r,r,r")
580 (match_operand:SI 1 "const_int_operand" "n,n,n,n,n,n"))
581 (match_operand:SI 2 "register_operand" "r,r,r,r,r,r")))
582 (match_operand 3 "register_operand" "r,r,r,x,x,x"))
583 (set (match_operand:SI 4 "register_operand" "=*2,!3,r,*2,!3,r")
0b85d816
HPN
584 (plus:SI (mult:SI (match_dup 0)
585 (match_dup 1))
586 (match_dup 2)))]
8ad46d34
HPN
587 "GET_MODE_SIZE (GET_MODE (operands[3])) == UNITS_PER_WORD
588 && cris_side_effect_mode_ok (MULT, operands, 4, 2, 0, 1, 3)"
0b85d816
HPN
589 "@
590 #
591 #
477c433d
HPN
592 move.%s3 %3,[%4=%2+%0%T1]
593 #
594 #
595 move %3,[%4=%2+%0%T1]")
0b85d816 596
049746c2
HPN
597;; Split for the case above where we're out of luck with register
598;; allocation (again, the condition isn't checked for that), and we end up
599;; with the set in the side-effect getting the same register as the input
600;; register.
0b85d816
HPN
601
602(define_split
603 [(parallel
dbb138ce
HPN
604 [(set (match_operator
605 6 "cris_mem_op"
606 [(plus:SI
607 (mult:SI (match_operand:SI 0 "register_operand" "")
608 (match_operand:SI 1 "const_int_operand" ""))
609 (match_operand:SI 2 "register_operand" ""))])
0b85d816
HPN
610 (match_operand 3 "register_operand" ""))
611 (set (match_operand:SI 4 "register_operand" "")
612 (plus:SI (mult:SI (match_dup 0)
613 (match_dup 1))
614 (match_dup 2)))])]
615 "reload_completed && reg_overlap_mentioned_p (operands[4], operands[3])"
616 [(set (match_dup 5) (match_dup 3))
617 (set (match_dup 4) (match_dup 2))
618 (set (match_dup 4)
619 (plus:SI (mult:SI (match_dup 0)
620 (match_dup 1))
621 (match_dup 4)))]
622 "operands[5]
dbb138ce
HPN
623 = replace_equiv_address (operands[6],
624 gen_rtx_PLUS (SImode,
625 gen_rtx_MULT (SImode,
626 operands[0],
627 operands[1]),
628 operands[2]));")
0b85d816
HPN
629\f
630;; move.s rx,[ry=rz+i]
631;; FIXME: These could have anonymous mode for operand 2.
632
633;; QImode
634
22c3c091
HPN
635(define_insn "*mov_side<mode>_mem"
636 [(set (mem:BW
0b85d816 637 (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r,r")
747a0d9d 638 (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r>Rn,r,>Rn")))
22c3c091 639 (match_operand:BW 2 "register_operand" "r,r,r,r"))
049746c2 640 (set (match_operand:SI 3 "register_operand" "=*0,!2,r,r")
0b85d816
HPN
641 (plus:SI (match_dup 0)
642 (match_dup 1)))]
643 "cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)"
0b85d816
HPN
644{
645 if (which_alternative == 0
646 && (GET_CODE (operands[1]) != CONST_INT
647 || INTVAL (operands[1]) > 127
648 || INTVAL (operands[1]) < -128
649 || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
650 || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
22c3c091 651 return "#";
0b85d816 652 if (which_alternative == 1)
22c3c091
HPN
653 return "#";
654 return "move<m> %2,[%3=%0%S1]";
655})
0b85d816
HPN
656
657;; SImode
658
8ad46d34
HPN
659(define_insn "*mov_sidesisf_mem"
660 [(set (mem
477c433d
HPN
661 (plus:SI
662 (match_operand:SI
663 0 "cris_bdap_operand" "%r,r,r,r,r,r,r,r")
664 (match_operand:SI
665 1 "cris_bdap_operand" "r>Rn,r>Rn,r,>Rn,r>Rn,r>Rn,r,>Rn")))
666 (match_operand 2 "register_operand" "r,r,r,r,x,x,x,x"))
667 (set (match_operand:SI 3 "register_operand" "=*0,!2,r,r,*0,!2,r,r")
0b85d816
HPN
668 (plus:SI (match_dup 0)
669 (match_dup 1)))]
8ad46d34
HPN
670 "GET_MODE_SIZE (GET_MODE (operands[2])) == UNITS_PER_WORD
671 && cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)"
0b85d816 672{
477c433d 673 if ((which_alternative == 0 || which_alternative == 4)
0b85d816
HPN
674 && (GET_CODE (operands[1]) != CONST_INT
675 || INTVAL (operands[1]) > 127
676 || INTVAL (operands[1]) < -128
677 || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
678 || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
477c433d
HPN
679 return "#";
680 if (which_alternative == 1 || which_alternative == 5)
681 return "#";
682 if (which_alternative < 4)
683 return "move.%s2 %2,[%3=%0%S1]";
684 return "move %2,[%3=%0%S1]";
685})
0b85d816
HPN
686
687;; Like the biap case, a split where the set in the side-effect gets the
049746c2
HPN
688;; same register as the input register to the main insn, since the
689;; condition isn't checked at register allocation.
0b85d816
HPN
690
691(define_split
692 [(parallel
dbb138ce
HPN
693 [(set (match_operator
694 4 "cris_mem_op"
695 [(plus:SI
696 (match_operand:SI 0 "cris_bdap_operand" "")
697 (match_operand:SI 1 "cris_bdap_operand" ""))])
049746c2 698 (match_operand 2 "register_operand" ""))
0b85d816
HPN
699 (set (match_operand:SI 3 "register_operand" "")
700 (plus:SI (match_dup 0) (match_dup 1)))])]
701 "reload_completed && reg_overlap_mentioned_p (operands[3], operands[2])"
702 [(set (match_dup 4) (match_dup 2))
703 (set (match_dup 3) (match_dup 0))
704 (set (match_dup 3) (plus:SI (match_dup 3) (match_dup 1)))]
dbb138ce 705 "")
0b85d816
HPN
706\f
707;; Clear memory side-effect patterns. It is hard to get to the mode if
708;; the MEM was anonymous, so there will be one for each mode.
709
22c3c091 710;; clear.[bwd] [ry=rx+rw.s2]
0b85d816 711
22c3c091
HPN
712(define_insn "*clear_side<mode>_biap"
713 [(set (mem:BWD (plus:SI
714 (mult:SI (match_operand:SI 0 "register_operand" "r,r")
715 (match_operand:SI 1 "const_int_operand" "n,n"))
716 (match_operand:SI 2 "register_operand" "r,r")))
0b85d816
HPN
717 (const_int 0))
718 (set (match_operand:SI 3 "register_operand" "=*2,r")
719 (plus:SI (mult:SI (match_dup 0)
720 (match_dup 1))
721 (match_dup 2)))]
722 "cris_side_effect_mode_ok (MULT, operands, 3, 2, 0, 1, -1)"
723 "@
724 #
22c3c091 725 clear<m> [%3=%2+%0%T1]")
0b85d816 726
22c3c091 727;; clear.[bwd] [ry=rz+i]
0b85d816 728
22c3c091
HPN
729(define_insn "*clear_side<mode>"
730 [(set (mem:BWD
0b85d816 731 (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r")
747a0d9d 732 (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn")))
0b85d816
HPN
733 (const_int 0))
734 (set (match_operand:SI 2 "register_operand" "=*0,r,r")
735 (plus:SI (match_dup 0)
736 (match_dup 1)))]
737 "cris_side_effect_mode_ok (PLUS, operands, 2, 0, 1, -1, -1)"
0b85d816
HPN
738{
739 if (which_alternative == 0
740 && (GET_CODE (operands[1]) != CONST_INT
741 || INTVAL (operands[1]) > 127
742 || INTVAL (operands[1]) < -128
743 || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
744 || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
22c3c091
HPN
745 return "#";
746 return "clear<m> [%2=%0%S1]";
747})
0b85d816 748\f
0b85d816
HPN
749;; Normal move patterns from SI on.
750
751(define_expand "movsi"
752 [(set
753 (match_operand:SI 0 "nonimmediate_operand" "")
754 (match_operand:SI 1 "cris_general_operand_or_symbol" ""))]
755 ""
0b85d816
HPN
756{
757 /* If the output goes to a MEM, make sure we have zero or a register as
758 input. */
759 if (GET_CODE (operands[0]) == MEM
760 && ! REG_S_P (operands[1])
761 && operands[1] != const0_rtx
762 && ! no_new_pseudos)
763 operands[1] = force_reg (SImode, operands[1]);
764
765 /* If we're generating PIC and have an incoming symbol, validize it to a
766 general operand or something that will match a special pattern.
767
768 FIXME: Do we *have* to recognize anything that would normally be a
769 valid symbol? Can we exclude global PIC addresses with an added
770 offset? */
771 if (flag_pic
772 && CONSTANT_ADDRESS_P (operands[1])
773 && cris_symbol (operands[1]))
774 {
775 /* We must have a register as destination for what we're about to
776 do, and for the patterns we generate. */
777 if (! REG_S_P (operands[0]))
778 {
b6c34129 779 CRIS_ASSERT (!no_new_pseudos);
0b85d816
HPN
780 operands[1] = force_reg (SImode, operands[1]);
781 }
782 else
783 {
784 /* Mark a needed PIC setup for a LABEL_REF:s coming in here:
785 they are so rare not-being-branch-targets that we don't mark
786 a function as needing PIC setup just because we have
787 inspected LABEL_REF:s as operands. It is only in
788 __builtin_setjmp and such that we can get a LABEL_REF
789 assigned to a register. */
790 if (GET_CODE (operands[1]) == LABEL_REF)
791 current_function_uses_pic_offset_table = 1;
792
793 /* We don't have to do anything for global PIC operands; they
794 look just like ``[rPIC+sym]''. */
795 if (! cris_got_symbol (operands[1])
796 /* We don't do anything for local PIC operands; we match
797 that with a special alternative. */
798 && ! cris_gotless_symbol (operands[1]))
799 {
800 /* We get here when we have to change something that would
801 be recognizable if it wasn't PIC. A ``sym'' is ok for
802 PIC symbols both with and without a GOT entry. And ``sym
803 + offset'' is ok for local symbols, so the only thing it
804 could be, is a global symbol with an offset. Check and
805 abort if not. */
806 rtx sym = get_related_value (operands[1]);
807 HOST_WIDE_INT offs = get_integer_term (operands[1]);
808
b6c34129
HPN
809 CRIS_ASSERT (sym != NULL_RTX && offs != 0);
810
0b85d816
HPN
811 emit_move_insn (operands[0], sym);
812 if (expand_binop (SImode, add_optab, operands[0],
813 GEN_INT (offs), operands[0], 0,
814 OPTAB_LIB_WIDEN) != operands[0])
b6c34129 815 internal_error ("expand_binop failed in movsi");
0b85d816
HPN
816 DONE;
817 }
818 }
819 }
b6c34129 820})
0b85d816
HPN
821
822(define_insn "*movsi_internal"
823 [(set
f60c7155 824 (match_operand:SI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,g,r,r, r,g,rQ>,x, m,x")
0b85d816
HPN
825 (match_operand:SI 1
826 ;; FIXME: We want to put S last, but apparently g matches S.
827 ;; It's a bug: an S is not a general_operand and shouldn't match g.
f60c7155 828 "cris_general_operand_or_gotless_symbol" "r,Q>,M,M, I,r, M,n,!S,g,r,x, rQ>,x,gi"))]
0b85d816 829 ""
0b85d816
HPN
830{
831 /* Better to have c-switch here; it is worth it to optimize the size of
832 move insns. The alternative would be to try to find more constraint
833 letters. FIXME: Check again. It seems this could shrink a bit. */
834 switch (which_alternative)
835 {
836 case 0:
837 case 1:
838 case 5:
839 case 9:
840 case 10:
22c3c091 841 return "move.d %1,%0";
0b85d816 842
f60c7155
HPN
843 case 11:
844 case 12:
845 case 13:
846 case 14:
22c3c091 847 return "move %d1,%0";
f60c7155 848
0b85d816
HPN
849 case 2:
850 case 3:
851 case 6:
22c3c091 852 return "clear.d %0";
0b85d816
HPN
853
854 /* Constants -32..31 except 0. */
855 case 4:
22c3c091 856 return "moveq %1,%0";
0b85d816
HPN
857
858 /* We can win a little on constants -32768..-33, 32..65535. */
859 case 7:
860 if (INTVAL (operands[1]) > 0 && INTVAL (operands[1]) < 65536)
861 {
862 if (INTVAL (operands[1]) < 256)
22c3c091
HPN
863 return "movu.b %1,%0";
864 return "movu.w %1,%0";
0b85d816
HPN
865 }
866 else if (INTVAL (operands[1]) >= -32768 && INTVAL (operands[1]) < 32768)
867 {
868 if (INTVAL (operands[1]) >= -128 && INTVAL (operands[1]) < 128)
22c3c091
HPN
869 return "movs.b %1,%0";
870 return "movs.w %1,%0";
0b85d816 871 }
22c3c091 872 return "move.d %1,%0";
0b85d816 873
d29b4b1b
HPN
874 case 8:
875 /* FIXME: Try and split this into pieces GCC makes better code of,
876 than this multi-insn pattern. Synopsis: wrap the GOT-relative
877 symbol into an unspec, and when PIC, recognize the unspec
878 everywhere a symbol is normally recognized. (The PIC register
879 should be recognized by GCC as pic_offset_table_rtx when needed
880 and similar for PC.) Each component can then be optimized with
881 the rest of the code; it should be possible to have a constant
882 term added on an unspec. Don't forget to add a REG_EQUAL (or
883 is it REG_EQUIV) note to the destination. It might not be
884 worth it. Measure.
885
886 Note that the 'v' modifier makes PLT references be output as
887 sym:PLT rather than [rPIC+sym:GOTPLT]. */
888 if (GET_CODE (operands[1]) == UNSPEC
889 && XINT (operands[1], 1) == CRIS_UNSPEC_GOT)
890 {
891 /* We clobber cc0 rather than set it to GOT. Should not
892 matter, though. */
893 CC_STATUS_INIT;
b6c34129 894 CRIS_ASSERT (REGNO (operands[0]) == PIC_OFFSET_TABLE_REGNUM);
d29b4b1b 895
22c3c091 896 return "move.d $pc,%0\;sub.d .:GOTOFF,%0";
d29b4b1b
HPN
897 }
898
22c3c091 899 return "move.d %v1,%0\;add.d %P1,%0";
0b85d816
HPN
900
901 default:
22c3c091 902 return "BOGUS: %1 to %0";
0b85d816 903 }
22c3c091 904}
f60c7155
HPN
905 [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no,no,yes,yes,no,no")
906 (set_attr "cc" "*,*,*,*,*,*,*,*,*,*,*,none,none,none,none")])
0b85d816
HPN
907\f
908;; Extend operations with side-effect from mem to register, using
909;; MOVS/MOVU. These are from mem to register only.
910;;
911;; [rx=ry+rz.S]
912;;
913;; QImode to HImode
914;;
915;; FIXME: Can we omit extend to HImode, since GCC should truncate for
916;; HImode by itself? Perhaps use only anonymous modes?
917
918(define_insn "*ext_sideqihi_biap"
919 [(set (match_operand:HI 0 "register_operand" "=r,r")
920 (match_operator:HI
921 5 "cris_extend_operator"
922 [(mem:QI (plus:SI
923 (mult:SI (match_operand:SI 1 "register_operand" "r,r")
924 (match_operand:SI 2 "const_int_operand" "n,n"))
925 (match_operand:SI 3 "register_operand" "r,r")))]))
926 (set (match_operand:SI 4 "register_operand" "=*3,r")
927 (plus:SI (mult:SI (match_dup 1)
928 (match_dup 2))
929 (match_dup 3)))]
930 "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
931 "@
932 #
933 mov%e5.%m5 [%4=%3+%1%T2],%0")
934
22c3c091 935(define_insn "*ext_side<mode>si_biap"
0b85d816
HPN
936 [(set (match_operand:SI 0 "register_operand" "=r,r")
937 (match_operator:SI
938 5 "cris_extend_operator"
22c3c091 939 [(mem:BW (plus:SI
0b85d816
HPN
940 (mult:SI (match_operand:SI 1 "register_operand" "r,r")
941 (match_operand:SI 2 "const_int_operand" "n,n"))
942 (match_operand:SI 3 "register_operand" "r,r")))]))
943 (set (match_operand:SI 4 "register_operand" "=*3,r")
944 (plus:SI (mult:SI (match_dup 1)
945 (match_dup 2))
946 (match_dup 3)))]
947 "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
948 "@
949 #
22c3c091 950 mov%e5<m> [%4=%3+%1%T2],%0")
0b85d816
HPN
951\f
952;; Same but [rx=ry+i]
953
954;; QImode to HImode
955
956(define_insn "*ext_sideqihi"
957 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
958 (match_operator:HI
959 4 "cris_extend_operator"
960 [(mem:QI (plus:SI
961 (match_operand:SI 1 "cris_bdap_operand" "%r,r,r")
747a0d9d 962 (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn")))]))
0b85d816
HPN
963 (set (match_operand:SI 3 "register_operand" "=*1,r,r")
964 (plus:SI (match_dup 1)
965 (match_dup 2)))]
966 "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
0b85d816
HPN
967{
968 if (which_alternative == 0
969 && (GET_CODE (operands[2]) != CONST_INT
970 || INTVAL (operands[2]) > 127
971 || INTVAL (operands[2]) < -128
972 || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
973 || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
22c3c091
HPN
974 return "#";
975 return "mov%e4.%m4 [%3=%1%S2],%0";
976})
0b85d816 977
22c3c091 978(define_insn "*ext_side<mode>si"
0b85d816
HPN
979 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
980 (match_operator:SI
981 4 "cris_extend_operator"
22c3c091 982 [(mem:BW (plus:SI
0b85d816 983 (match_operand:SI 1 "cris_bdap_operand" "%r,r,r")
747a0d9d 984 (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn")))]))
0b85d816
HPN
985 (set (match_operand:SI 3 "register_operand" "=*1,r,r")
986 (plus:SI (match_dup 1)
987 (match_dup 2)))]
988 "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
0b85d816
HPN
989{
990 if (which_alternative == 0
991 && (GET_CODE (operands[2]) != CONST_INT
992 || INTVAL (operands[2]) > 127
993 || INTVAL (operands[2]) < -128
994 || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
995 || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
22c3c091
HPN
996 return "#";
997 return "mov%e4<m> [%3=%1%S2],%0";
998})
0b85d816
HPN
999\f
1000;; FIXME: See movsi.
1001
1002(define_insn "movhi"
1003 [(set
f60c7155
HPN
1004 (match_operand:HI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,r,r,r,g,g,r,r,x")
1005 (match_operand:HI 1 "general_operand" "r,Q>,M,M, I,r, L,O,n,M,r,g,x,r"))]
0b85d816 1006 ""
0b85d816
HPN
1007{
1008 switch (which_alternative)
1009 {
1010 case 0:
1011 case 1:
1012 case 5:
1013 case 10:
1014 case 11:
22c3c091 1015 return "move.w %1,%0";
f60c7155
HPN
1016 case 12:
1017 case 13:
22c3c091 1018 return "move %1,%0";
0b85d816
HPN
1019 case 2:
1020 case 3:
1021 case 9:
22c3c091 1022 return "clear.w %0";
0b85d816 1023 case 4:
22c3c091 1024 return "moveq %1,%0";
0b85d816
HPN
1025 case 6:
1026 case 8:
1027 if (INTVAL (operands[1]) < 256 && INTVAL (operands[1]) >= -128)
1028 {
1029 if (INTVAL (operands[1]) > 0)
22c3c091
HPN
1030 return "movu.b %1,%0";
1031 return "movs.b %1,%0";
0b85d816 1032 }
22c3c091 1033 return "move.w %1,%0";
0b85d816 1034 case 7:
22c3c091 1035 return "movEq %b1,%0";
0b85d816 1036 default:
22c3c091 1037 return "BOGUS: %1 to %0";
0b85d816 1038 }
22c3c091 1039}
f60c7155
HPN
1040 [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,yes,no,no,no,no,yes,yes")
1041 (set_attr "cc" "*,*,none,none,*,none,*,clobber,*,none,none,*,none,none")])
0b85d816
HPN
1042
1043(define_insn "movstricthi"
1044 [(set
1045 (strict_low_part
23369bef
HPN
1046 (match_operand:HI 0 "nonimmediate_operand" "+r,r, r,Q>,Q>,g,r,g"))
1047 (match_operand:HI 1 "general_operand" "r,Q>,M,M, r, M,g,r"))]
0b85d816
HPN
1048 ""
1049 "@
1050 move.w %1,%0
1051 move.w %1,%0
1052 clear.w %0
1053 clear.w %0
1054 move.w %1,%0
1055 clear.w %0
1056 move.w %1,%0
1057 move.w %1,%0"
1058 [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")])
f60c7155 1059
22c3c091
HPN
1060(define_expand "reload_in<mode>"
1061 [(set (match_operand:BW 2 "register_operand" "=r")
1062 (match_operand:BW 1 "memory_operand" "m"))
1063 (set (match_operand:BW 0 "register_operand" "=x")
f60c7155
HPN
1064 (match_dup 2))]
1065 ""
1066 "")
1067
22c3c091
HPN
1068(define_expand "reload_out<mode>"
1069 [(set (match_operand:BW 2 "register_operand" "=r")
1070 (match_operand:BW 1 "register_operand" "x"))
1071 (set (match_operand:BW 0 "memory_operand" "=m")
f60c7155
HPN
1072 (match_dup 2))]
1073 ""
1074 "")
0b85d816
HPN
1075\f
1076(define_insn "movqi"
f60c7155
HPN
1077 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,r,g,g,r,r,r,x")
1078 (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, I,M,r,O,g,x,r"))]
0b85d816
HPN
1079 ""
1080 "@
1081 move.b %1,%0
1082 move.b %1,%0
1083 move.b %1,%0
1084 clear.b %0
1085 clear.b %0
1086 moveq %1,%0
1087 clear.b %0
1088 move.b %1,%0
1089 moveq %b1,%0
f60c7155
HPN
1090 move.b %1,%0
1091 move %1,%0
1092 move %1,%0"
1093 [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,yes,no,yes,yes")
1094 (set_attr "cc" "*,*,*,*,*,*,*,*,clobber,*,none,none")])
0b85d816
HPN
1095
1096(define_insn "movstrictqi"
1097 [(set (strict_low_part
23369bef
HPN
1098 (match_operand:QI 0 "nonimmediate_operand" "+r,Q>,r, r,Q>,g,g,r"))
1099 (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, M,r,g"))]
0b85d816
HPN
1100 ""
1101 "@
1102 move.b %1,%0
1103 move.b %1,%0
1104 move.b %1,%0
1105 clear.b %0
1106 clear.b %0
1107 clear.b %0
1108 move.b %1,%0
1109 move.b %1,%0"
1110 [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")])
1111
1112;; The valid "quick" bit-patterns are, except for 0.0, denormalized
1113;; values REALLY close to 0, and some NaN:s (I think; their exponent is
1114;; all ones); the worthwhile one is "0.0".
1115;; It will use clear, so we know ALL types of immediate 0 never change cc.
1116
1117(define_insn "movsf"
f60c7155
HPN
1118 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,g,g,r,r,x,Q>,m,x, x")
1119 (match_operand:SF 1 "general_operand" "r,r, Q>,G,G, G,r,g,x,r,x, x,Q>,g"))]
0b85d816
HPN
1120 ""
1121 "@
1122 move.d %1,%0
1123 move.d %1,%0
1124 move.d %1,%0
1125 clear.d %0
1126 clear.d %0
1127 clear.d %0
1128 move.d %1,%0
f60c7155
HPN
1129 move.d %1,%0
1130 move %1,%0
1131 move %1,%0
1132 move %1,%0
1133 move %1,%0
1134 move %1,%0
1135 move %1,%0"
1136 [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no,yes,yes,yes,no,yes,no")])
04539954 1137
d29b4b1b
HPN
1138;; Note that the memory layout of the registers is the reverse of that
1139;; of the standard patterns "load_multiple" and "store_multiple".
04539954
HPN
1140(define_insn "*cris_load_multiple"
1141 [(match_parallel 0 "cris_load_multiple_op"
1142 [(set (match_operand:SI 1 "register_operand" "=r,r")
1143 (match_operand:SI 2 "memory_operand" "Q,m"))])]
1144 ""
1145 "movem %O0,%o0"
1146 [(set_attr "cc" "none")
1147 (set_attr "slottable" "yes,no")
1148 ;; Not true, but setting the length to 0 causes return sequences (ret
1149 ;; movem) to have the cost they had when (return) included the movem
1150 ;; and reduces the performance penalty taken for needing to emit an
1151 ;; epilogue (in turn copied by bb-reorder) instead of return patterns.
1152 ;; FIXME: temporary change until all insn lengths are correctly
1153 ;; described. FIXME: have better target control over bb-reorder.
1154 (set_attr "length" "0")])
d29b4b1b
HPN
1155
1156(define_insn "*cris_store_multiple"
1157 [(match_parallel 0 "cris_store_multiple_op"
1158 [(set (match_operand:SI 2 "memory_operand" "=Q,m")
1159 (match_operand:SI 1 "register_operand" "r,r"))])]
1160 ""
1161 "movem %o0,%O0"
1162 [(set_attr "cc" "none")
1163 (set_attr "slottable" "yes,no")])
0b85d816
HPN
1164\f
1165
1166;; Sign- and zero-extend insns with standard names.
1167;; Those for integer source operand are ordered with the widest source
1168;; type first.
1169
1170;; Sign-extend.
1171
1172(define_insn "extendsidi2"
1173 [(set (match_operand:DI 0 "register_operand" "=r")
1174 (sign_extend:DI (match_operand:SI 1 "general_operand" "g")))]
1175 ""
1176 "move.d %1,%M0\;smi %H0\;neg.d %H0,%H0")
1177
22c3c091 1178(define_insn "extend<mode>di2"
0b85d816 1179 [(set (match_operand:DI 0 "register_operand" "=r")
22c3c091 1180 (sign_extend:DI (match_operand:BW 1 "general_operand" "g")))]
0b85d816 1181 ""
22c3c091 1182 "movs<m> %1,%M0\;smi %H0\;neg.d %H0,%H0")
0b85d816 1183
22c3c091 1184(define_insn "extend<mode>si2"
0b85d816 1185 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
22c3c091 1186 (sign_extend:SI (match_operand:BW 1 "general_operand" "r,Q>,g")))]
0b85d816 1187 ""
22c3c091 1188 "movs<m> %1,%0"
0b85d816
HPN
1189 [(set_attr "slottable" "yes,yes,no")])
1190
839a4992 1191;; To do a byte->word extension, extend to dword, exept that the top half
0b85d816
HPN
1192;; of the register will be clobbered. FIXME: Perhaps this is not needed.
1193
1194(define_insn "extendqihi2"
1195 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
1196 (sign_extend:HI (match_operand:QI 1 "general_operand" "r,Q>,g")))]
1197 ""
1198 "movs.b %1,%0"
1199 [(set_attr "slottable" "yes,yes,no")])
1200\f
1201
1202;; Zero-extend. The DImode ones are synthesized by gcc, so we don't
1203;; specify them here.
1204
22c3c091 1205(define_insn "zero_extend<mode>si2"
0b85d816
HPN
1206 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1207 (zero_extend:SI
22c3c091 1208 (match_operand:BW 1 "nonimmediate_operand" "r,Q>,m")))]
0b85d816 1209 ""
22c3c091 1210 "movu<m> %1,%0"
0b85d816
HPN
1211 [(set_attr "slottable" "yes,yes,no")])
1212
1213;; Same comment as sign-extend QImode to HImode above applies.
1214
1215(define_insn "zero_extendqihi2"
1216 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
1217 (zero_extend:HI
1218 (match_operand:QI 1 "nonimmediate_operand" "r,Q>,m")))]
1219 ""
1220 "movu.b %1,%0"
1221 [(set_attr "slottable" "yes,yes,no")])
1222\f
1223;; All kinds of arithmetic and logical instructions.
1224;;
1225;; First, anonymous patterns to match addressing modes with
1226;; side-effects.
1227;;
1228;; op.S [rx=ry+I],rz; (add, sub, or, and, bound).
1229;;
1230;; [rx=ry+rz.S]
0b85d816 1231
22c3c091
HPN
1232(define_insn "*op_side<mode>_biap"
1233 [(set (match_operand:BWD 0 "register_operand" "=r,r")
1234 (match_operator:BWD
0b85d816 1235 6 "cris_orthogonal_operator"
22c3c091
HPN
1236 [(match_operand:BWD 1 "register_operand" "0,0")
1237 (mem:BWD (plus:SI
1238 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
1239 (match_operand:SI 3 "const_int_operand" "n,n"))
1240 (match_operand:SI 4 "register_operand" "r,r")))]))
0b85d816
HPN
1241 (set (match_operand:SI 5 "register_operand" "=*4,r")
1242 (plus:SI (mult:SI (match_dup 2)
1243 (match_dup 3))
1244 (match_dup 4)))]
1245 "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
1246 "@
1247 #
22c3c091 1248 %x6<m> [%5=%4+%2%T3],%0")
0b85d816
HPN
1249\f
1250;; [rx=ry+i] ([%4=%2+%3])
0b85d816 1251
22c3c091
HPN
1252(define_insn "*op_side<mode>"
1253 [(set (match_operand:BWD 0 "register_operand" "=r,r,r")
1254 (match_operator:BWD
0b85d816 1255 5 "cris_orthogonal_operator"
22c3c091
HPN
1256 [(match_operand:BWD 1 "register_operand" "0,0,0")
1257 (mem:BWD (plus:SI
0b85d816 1258 (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
747a0d9d 1259 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))]))
0b85d816
HPN
1260 (set (match_operand:SI 4 "register_operand" "=*2,r,r")
1261 (plus:SI (match_dup 2)
1262 (match_dup 3)))]
1263 "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816
HPN
1264{
1265 if (which_alternative == 0
1266 && (GET_CODE (operands[3]) != CONST_INT
1267 || INTVAL (operands[3]) > 127
1268 || INTVAL (operands[3]) < -128
1269 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
1270 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
22c3c091
HPN
1271 return "#";
1272 return "%x5<m> [%4=%2%S3],%0";
1273})
0b85d816
HPN
1274\f
1275;; To match all cases for commutative operations we may have to have the
1276;; following pattern for add, or & and. I do not know really, but it does
1277;; not break anything.
1278;;
1279;; FIXME: This really ought to be checked.
1280;;
1281;; op.S [rx=ry+I],rz;
1282;;
1283;; [rx=ry+rz.S]
0b85d816 1284
22c3c091
HPN
1285(define_insn "*op_swap_side<mode>_biap"
1286 [(set (match_operand:BWD 0 "register_operand" "=r,r")
1287 (match_operator:BWD
0b85d816 1288 6 "cris_commutative_orth_op"
22c3c091 1289 [(mem:BWD (plus:SI
0b85d816
HPN
1290 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
1291 (match_operand:SI 3 "const_int_operand" "n,n"))
1292 (match_operand:SI 4 "register_operand" "r,r")))
22c3c091 1293 (match_operand:BWD 1 "register_operand" "0,0")]))
0b85d816
HPN
1294 (set (match_operand:SI 5 "register_operand" "=*4,r")
1295 (plus:SI (mult:SI (match_dup 2)
1296 (match_dup 3))
1297 (match_dup 4)))]
1298 "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
1299 "@
1300 #
22c3c091 1301 %x6<m> [%5=%4+%2%T3],%0")
0b85d816
HPN
1302\f
1303;; [rx=ry+i] ([%4=%2+%3])
1304;; FIXME: These could have anonymous mode for operand 0.
1305
1306;; QImode
1307
22c3c091
HPN
1308(define_insn "*op_swap_side<mode>"
1309 [(set (match_operand:BWD 0 "register_operand" "=r,r,r")
1310 (match_operator:BWD
0b85d816 1311 5 "cris_commutative_orth_op"
22c3c091 1312 [(mem:BWD
0b85d816 1313 (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
747a0d9d 1314 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))
22c3c091 1315 (match_operand:BWD 1 "register_operand" "0,0,0")]))
0b85d816
HPN
1316 (set (match_operand:SI 4 "register_operand" "=*2,r,r")
1317 (plus:SI (match_dup 2)
1318 (match_dup 3)))]
1319 "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816
HPN
1320{
1321 if (which_alternative == 0
1322 && (GET_CODE (operands[3]) != CONST_INT
1323 || INTVAL (operands[3]) > 127
1324 || INTVAL (operands[3]) < -128
1325 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
1326 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
22c3c091
HPN
1327 return "#";
1328 return "%x5<m> [%4=%2%S3],%0";
1329})
0b85d816
HPN
1330\f
1331;; Add operations, standard names.
1332
1333;; Note that for the 'P' constraint, the high part can be -1 or 0. We
1334;; output the insn through the 'A' output modifier as "adds.w" and "addq",
1335;; respectively.
1336(define_insn "adddi3"
1337 [(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r")
1338 (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,r")
1339 (match_operand:DI 2 "general_operand" "J,N,P,g,!To")))]
1340 ""
1341 "@
1342 addq %2,%M0\;ax\;addq 0,%H0
1343 subq %n2,%M0\;ax\;subq 0,%H0
1344 add%e2.%z2 %2,%M0\;ax\;%A2 %H2,%H0
1345 add.d %M2,%M0\;ax\;add.d %H2,%H0
1346 add.d %M2,%M1,%M0\;ax\;add.d %H2,%H1,%H0")
1347
1348(define_insn "addsi3"
23369bef 1349 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r,r, r")
0b85d816 1350 (plus:SI
23369bef
HPN
1351 (match_operand:SI 1 "register_operand" "%0,0, 0,0,0,0,r, r")
1352 (match_operand:SI 2 "general_operand" "r,Q>,J,N,n,g,!To,0")))]
0b85d816
HPN
1353
1354;; The last constraint is due to that after reload, the '%' is not
1355;; honored, and canonicalization doesn't care about keeping the same
1356;; register as in destination. This will happen after insn splitting.
1357;; gcc <= 2.7.2. FIXME: Check for gcc-2.9x
1358
1359 ""
0b85d816
HPN
1360{
1361 switch (which_alternative)
1362 {
1363 case 0:
1364 case 1:
22c3c091 1365 return "add.d %2,%0";
0b85d816 1366 case 2:
22c3c091 1367 return "addq %2,%0";
0b85d816 1368 case 3:
22c3c091 1369 return "subq %n2,%0";
0b85d816
HPN
1370 case 4:
1371 /* 'Known value', but not in -63..63.
1372 Check if addu/subu may be used. */
1373 if (INTVAL (operands[2]) > 0)
1374 {
1375 if (INTVAL (operands[2]) < 256)
22c3c091 1376 return "addu.b %2,%0";
0b85d816 1377 if (INTVAL (operands[2]) < 65536)
22c3c091 1378 return "addu.w %2,%0";
0b85d816
HPN
1379 }
1380 else
1381 {
1382 if (INTVAL (operands[2]) >= -255)
22c3c091 1383 return "subu.b %n2,%0";
0b85d816 1384 if (INTVAL (operands[2]) >= -65535)
22c3c091 1385 return "subu.w %n2,%0";
0b85d816 1386 }
22c3c091 1387 return "add.d %2,%0";
0b85d816 1388 case 6:
22c3c091 1389 return "add.d %2,%1,%0";
0b85d816 1390 case 5:
22c3c091 1391 return "add.d %2,%0";
0b85d816 1392 case 7:
22c3c091 1393 return "add.d %1,%0";
0b85d816 1394 default:
22c3c091 1395 return "BOGUS addsi %2+%1 to %0";
0b85d816 1396 }
22c3c091 1397}
0b85d816
HPN
1398 [(set_attr "slottable" "yes,yes,yes,yes,no,no,no,yes")])
1399\f
1400(define_insn "addhi3"
23369bef
HPN
1401 [(set (match_operand:HI 0 "register_operand" "=r,r, r,r,r,r")
1402 (plus:HI (match_operand:HI 1 "register_operand" "%0,0, 0,0,0,r")
1403 (match_operand:HI 2 "general_operand" "r,Q>,J,N,g,!To")))]
0b85d816
HPN
1404 ""
1405 "@
1406 add.w %2,%0
1407 add.w %2,%0
1408 addq %2,%0
1409 subq %n2,%0
1410 add.w %2,%0
1411 add.w %2,%1,%0"
1412 [(set_attr "slottable" "yes,yes,yes,yes,no,no")
1413 (set_attr "cc" "normal,normal,clobber,clobber,normal,normal")])
1414
1415(define_insn "addqi3"
23369bef
HPN
1416 [(set (match_operand:QI 0 "register_operand" "=r,r, r,r,r,r,r")
1417 (plus:QI (match_operand:QI 1 "register_operand" "%0,0, 0,0,0,0,r")
1418 (match_operand:QI 2 "general_operand" "r,Q>,J,N,O,g,!To")))]
0b85d816
HPN
1419 ""
1420 "@
1421 add.b %2,%0
1422 add.b %2,%0
1423 addq %2,%0
1424 subq %n2,%0
1425 subQ -%b2,%0
1426 add.b %2,%0
1427 add.b %2,%1,%0"
1428 [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no")
1429 (set_attr "cc" "normal,normal,clobber,clobber,clobber,normal,normal")])
1430\f
1431;; Subtract.
1432;;
1433;; Note that because of insn canonicalization these will *seldom* but
1434;; rarely be used with a known constant as an operand.
1435
1436;; Note that for the 'P' constraint, the high part can be -1 or 0. We
1437;; output the insn through the 'D' output modifier as "subs.w" and "subq",
1438;; respectively.
1439(define_insn "subdi3"
1440 [(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r")
1441 (minus:DI (match_operand:DI 1 "register_operand" "0,0,0,0,r")
1442 (match_operand:DI 2 "general_operand" "J,N,P,g,!To")))]
1443 ""
1444 "@
1445 subq %2,%M0\;ax\;subq 0,%H0
1446 addq %n2,%M0\;ax\;addq 0,%H0
1447 sub%e2.%z2 %2,%M0\;ax\;%D2 %H2,%H0
1448 sub.d %M2,%M0\;ax\;sub.d %H2,%H0
1449 sub.d %M2,%M1,%M0\;ax\;sub.d %H2,%H1,%H0")
1450
1451(define_insn "subsi3"
23369bef 1452 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r,r,r")
0b85d816 1453 (minus:SI
23369bef
HPN
1454 (match_operand:SI 1 "register_operand" "0,0, 0,0,0,0,0,r")
1455 (match_operand:SI 2 "general_operand" "r,Q>,J,N,P,n,g,!To")))]
0b85d816
HPN
1456 ""
1457
1458;; This does not do the optimal: "addu.w 65535,r0" when %2 is negative.
1459;; But then again, %2 should not be negative.
1460
1461 "@
1462 sub.d %2,%0
1463 sub.d %2,%0
1464 subq %2,%0
1465 addq %n2,%0
1466 sub%e2.%z2 %2,%0
1467 sub.d %2,%0
1468 sub.d %2,%0
1469 sub.d %2,%1,%0"
1470 [(set_attr "slottable" "yes,yes,yes,yes,no,no,no,no")])
1471\f
22c3c091
HPN
1472(define_insn "sub<mode>3"
1473 [(set (match_operand:BW 0 "register_operand" "=r,r, r,r,r,r")
1474 (minus:BW (match_operand:BW 1 "register_operand" "0,0, 0,0,0,r")
1475 (match_operand:BW 2 "general_operand" "r,Q>,J,N,g,!To")))]
0b85d816
HPN
1476 ""
1477 "@
22c3c091
HPN
1478 sub<m> %2,%0
1479 sub<m> %2,%0
0b85d816
HPN
1480 subq %2,%0
1481 addq %n2,%0
22c3c091
HPN
1482 sub<m> %2,%0
1483 sub<m> %2,%1,%0"
0b85d816
HPN
1484 [(set_attr "slottable" "yes,yes,yes,yes,no,no")
1485 (set_attr "cc" "normal,normal,clobber,clobber,normal,normal")])
1486\f
1487;; CRIS has some add/sub-with-sign/zero-extend instructions.
1488;; Although these perform sign/zero-extension to SImode, they are
1489;; equally applicable for the HImode case.
1490;; FIXME: Check; GCC should handle the widening.
1491;; Note that these must be located after the normal add/sub patterns,
1492;; so not to get constants into any less specific operands.
1493;;
1494;; Extend with add/sub and side-effect.
1495;;
1496;; ADDS/SUBS/ADDU/SUBU and BOUND, which needs a check for zero_extend
1497;;
1498;; adds/subs/addu/subu bound [rx=ry+rz.S]
0b85d816 1499
22c3c091
HPN
1500;; QImode to HImode
1501;; FIXME: GCC should widen.
0b85d816 1502
22c3c091
HPN
1503(define_insn "*extopqihi_side_biap"
1504 [(set (match_operand:HI 0 "register_operand" "=r,r")
1505 (match_operator:HI
1506 6 "cris_additive_operand_extend_operator"
1507 [(match_operand:HI 1 "register_operand" "0,0")
1508 (match_operator:HI
0b85d816
HPN
1509 7 "cris_extend_operator"
1510 [(mem:QI (plus:SI
1511 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
1512 (match_operand:SI 3 "const_int_operand" "n,n"))
1513 (match_operand:SI 4 "register_operand" "r,r")))])]))
1514 (set (match_operand:SI 5 "register_operand" "=*4,r")
1515 (plus:SI (mult:SI (match_dup 2)
1516 (match_dup 3))
1517 (match_dup 4)))]
22c3c091 1518 "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
0b85d816
HPN
1519 "@
1520 #
1521 %x6%e7.%m7 [%5=%4+%2%T3],%0")
1522
22c3c091 1523(define_insn "*extop<mode>si_side_biap"
0b85d816
HPN
1524 [(set (match_operand:SI 0 "register_operand" "=r,r")
1525 (match_operator:SI
1526 6 "cris_operand_extend_operator"
1527 [(match_operand:SI 1 "register_operand" "0,0")
1528 (match_operator:SI
1529 7 "cris_extend_operator"
22c3c091 1530 [(mem:BW (plus:SI
0b85d816
HPN
1531 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
1532 (match_operand:SI 3 "const_int_operand" "n,n"))
1533 (match_operand:SI 4 "register_operand" "r,r")))])]))
1534 (set (match_operand:SI 5 "register_operand" "=*4,r")
1535 (plus:SI (mult:SI (match_dup 2)
1536 (match_dup 3))
1537 (match_dup 4)))]
d2f55c5c 1538 "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[7]) == ZERO_EXTEND)
0b85d816
HPN
1539 && cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
1540 "@
1541 #
22c3c091 1542 %x6%e7<m> [%5=%4+%2%T3],%0")
0b85d816
HPN
1543\f
1544
1545;; [rx=ry+i]
0b85d816
HPN
1546
1547;; QImode to HImode
1548
1549(define_insn "*extopqihi_side"
1550 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
1551 (match_operator:HI
d2f55c5c 1552 5 "cris_additive_operand_extend_operator"
0b85d816
HPN
1553 [(match_operand:HI 1 "register_operand" "0,0,0")
1554 (match_operator:HI
1555 6 "cris_extend_operator"
1556 [(mem:QI
1557 (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
747a0d9d 1558 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")
0b85d816
HPN
1559 ))])]))
1560 (set (match_operand:SI 4 "register_operand" "=*2,r,r")
1561 (plus:SI (match_dup 2)
1562 (match_dup 3)))]
d2f55c5c 1563 "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816
HPN
1564{
1565 if (which_alternative == 0
1566 && (GET_CODE (operands[3]) != CONST_INT
1567 || INTVAL (operands[3]) > 127
1568 || INTVAL (operands[3]) < -128
1569 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
1570 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
22c3c091
HPN
1571 return "#";
1572 return "%x5%e6.%m6 [%4=%2%S3],%0";
1573})
0b85d816 1574
22c3c091 1575(define_insn "*extop<mode>si_side"
0b85d816
HPN
1576 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1577 (match_operator:SI
1578 5 "cris_operand_extend_operator"
1579 [(match_operand:SI 1 "register_operand" "0,0,0")
1580 (match_operator:SI
1581 6 "cris_extend_operator"
22c3c091 1582 [(mem:BW
0b85d816 1583 (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
747a0d9d 1584 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")
0b85d816
HPN
1585 ))])]))
1586 (set (match_operand:SI 4 "register_operand" "=*2,r,r")
1587 (plus:SI (match_dup 2)
1588 (match_dup 3)))]
1589 "(GET_CODE (operands[5]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND)
1590 && cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816
HPN
1591{
1592 if (which_alternative == 0
1593 && (GET_CODE (operands[3]) != CONST_INT
1594 || INTVAL (operands[3]) > 127
1595 || INTVAL (operands[3]) < -128
1596 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
1597 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
22c3c091
HPN
1598 return "#";
1599 return "%x5%e6<m> [%4=%2%S3],%0";
1600})
0b85d816
HPN
1601\f
1602
1603;; As with op.S we may have to add special pattern to match commuted
1604;; operands to adds/addu and bound
1605;;
1606;; adds/addu/bound [rx=ry+rz.S]
1607
1608;; QImode to HImode
1609;; FIXME: GCC should widen.
0b85d816
HPN
1610
1611(define_insn "*extopqihi_swap_side_biap"
1612 [(set (match_operand:HI 0 "register_operand" "=r,r")
d2f55c5c
HPN
1613 (plus:HI
1614 (match_operator:HI
1615 6 "cris_extend_operator"
1616 [(mem:QI (plus:SI
1617 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
1618 (match_operand:SI 3 "const_int_operand" "n,n"))
1619 (match_operand:SI 4 "register_operand" "r,r")))])
1620 (match_operand:HI 1 "register_operand" "0,0")))
0b85d816
HPN
1621 (set (match_operand:SI 5 "register_operand" "=*4,r")
1622 (plus:SI (mult:SI (match_dup 2)
1623 (match_dup 3))
1624 (match_dup 4)))]
d2f55c5c 1625 "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
0b85d816
HPN
1626 "@
1627 #
d2f55c5c 1628 add%e6.b [%5=%4+%2%T3],%0")
0b85d816 1629
22c3c091 1630(define_insn "*extop<mode>si_swap_side_biap"
0b85d816
HPN
1631 [(set (match_operand:SI 0 "register_operand" "=r,r")
1632 (match_operator:SI
1633 7 "cris_plus_or_bound_operator"
1634 [(match_operator:SI
1635 6 "cris_extend_operator"
22c3c091 1636 [(mem:BW (plus:SI
0b85d816
HPN
1637 (mult:SI (match_operand:SI 2 "register_operand" "r,r")
1638 (match_operand:SI 3 "const_int_operand" "n,n"))
1639 (match_operand:SI 4 "register_operand" "r,r")))])
1640 (match_operand:SI 1 "register_operand" "0,0")]))
1641 (set (match_operand:SI 5 "register_operand" "=*4,r")
1642 (plus:SI (mult:SI (match_dup 2)
1643 (match_dup 3))
1644 (match_dup 4)))]
d2f55c5c 1645 "(GET_CODE (operands[7]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND)
0b85d816
HPN
1646 && cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
1647 "@
1648 #
22c3c091 1649 %x7%e6<m> [%5=%4+%2%T3],%0")
0b85d816
HPN
1650\f
1651;; [rx=ry+i]
0b85d816
HPN
1652;; FIXME: GCC should widen.
1653
1654;; QImode to HImode
1655
1656(define_insn "*extopqihi_swap_side"
1657 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
d2f55c5c
HPN
1658 (plus:HI
1659 (match_operator:HI
1660 5 "cris_extend_operator"
1661 [(mem:QI (plus:SI
1662 (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
747a0d9d 1663 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))])
d2f55c5c 1664 (match_operand:HI 1 "register_operand" "0,0,0")))
0b85d816
HPN
1665 (set (match_operand:SI 4 "register_operand" "=*2,r,r")
1666 (plus:SI (match_dup 2)
1667 (match_dup 3)))]
d2f55c5c 1668 "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816
HPN
1669{
1670 if (which_alternative == 0
1671 && (GET_CODE (operands[3]) != CONST_INT
1672 || INTVAL (operands[3]) > 127
1673 || INTVAL (operands[3]) < -128
1674 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
1675 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
22c3c091
HPN
1676 return "#";
1677 return "add%e5.b [%4=%2%S3],%0";
1678})
0b85d816 1679
22c3c091 1680(define_insn "*extop<mode>si_swap_side"
0b85d816
HPN
1681 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1682 (match_operator:SI
1683 6 "cris_plus_or_bound_operator"
1684 [(match_operator:SI
1685 5 "cris_extend_operator"
22c3c091 1686 [(mem:BW (plus:SI
0b85d816 1687 (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
747a0d9d 1688 (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))])
0b85d816
HPN
1689 (match_operand:SI 1 "register_operand" "0,0,0")]))
1690 (set (match_operand:SI 4 "register_operand" "=*2,r,r")
1691 (plus:SI (match_dup 2)
1692 (match_dup 3)))]
1693 "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[5]) == ZERO_EXTEND)
1694 && cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
0b85d816
HPN
1695{
1696 if (which_alternative == 0
1697 && (GET_CODE (operands[3]) != CONST_INT
1698 || INTVAL (operands[3]) > 127
1699 || INTVAL (operands[3]) < -128
1700 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
1701 || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
22c3c091
HPN
1702 return "#";
1703 return "%x6%e5<m> [%4=%2%S3],%0";
1704})
0b85d816
HPN
1705\f
1706;; Extend versions (zero/sign) of normal add/sub (no side-effects).
0b85d816
HPN
1707
1708;; QImode to HImode
1709;; FIXME: GCC should widen.
1710
1711(define_insn "*extopqihi"
1712 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
1713 (match_operator:HI
d2f55c5c 1714 3 "cris_additive_operand_extend_operator"
0b85d816
HPN
1715 [(match_operand:HI 1 "register_operand" "0,0,0,r")
1716 (match_operator:HI
1717 4 "cris_extend_operator"
1718 [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])]))]
d2f55c5c 1719 "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
0b85d816
HPN
1720 && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
1721 "@
1722 %x3%e4.%m4 %2,%0
1723 %x3%e4.%m4 %2,%0
1724 %x3%e4.%m4 %2,%0
1725 %x3%e4.%m4 %2,%1,%0"
1726 [(set_attr "slottable" "yes,yes,no,no")
1727 (set_attr "cc" "clobber")])
1728
1729;; QImode to SImode
1730
22c3c091 1731(define_insn "*extop<mode>si"
0b85d816
HPN
1732 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1733 (match_operator:SI
1734 3 "cris_operand_extend_operator"
1735 [(match_operand:SI 1 "register_operand" "0,0,0,r")
1736 (match_operator:SI
1737 4 "cris_extend_operator"
22c3c091 1738 [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])]))]
0b85d816
HPN
1739 "(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
1740 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
1741 && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
1742 "@
22c3c091
HPN
1743 %x3%e4<m> %2,%0
1744 %x3%e4<m> %2,%0
1745 %x3%e4<m> %2,%0
1746 %x3%e4<m> %2,%1,%0"
0b85d816
HPN
1747 [(set_attr "slottable" "yes,yes,no,no")])
1748\f
1749
1750;; As with the side-effect patterns, may have to have swapped operands for add.
1751;; FIXME: *should* be redundant to gcc.
1752
1753;; QImode to HImode
1754
1755(define_insn "*extopqihi_swap"
1756 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
d2f55c5c
HPN
1757 (plus:HI
1758 (match_operator:HI
1759 3 "cris_extend_operator"
1760 [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])
1761 (match_operand:HI 1 "register_operand" "0,0,0,r")))]
1762 "operands[1] != frame_pointer_rtx"
0b85d816 1763 "@
d2f55c5c
HPN
1764 add%e3.b %2,%0
1765 add%e3.b %2,%0
1766 add%e3.b %2,%0
1767 add%e3.b %2,%1,%0"
0b85d816
HPN
1768 [(set_attr "slottable" "yes,yes,no,no")
1769 (set_attr "cc" "clobber")])
1770
22c3c091 1771(define_insn "*extop<mode>si_swap"
0b85d816
HPN
1772 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1773 (match_operator:SI
1774 4 "cris_plus_or_bound_operator"
1775 [(match_operator:SI
1776 3 "cris_extend_operator"
22c3c091 1777 [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])
0b85d816 1778 (match_operand:SI 1 "register_operand" "0,0,0,r")]))]
d2f55c5c 1779 "(GET_CODE (operands[4]) != UMIN || GET_CODE (operands[3]) == ZERO_EXTEND)
0b85d816
HPN
1780 && operands[1] != frame_pointer_rtx"
1781 "@
22c3c091
HPN
1782 %x4%e3<m> %2,%0
1783 %x4%e3<m> %2,%0
1784 %x4%e3<m> %2,%0
1785 %x4%e3<m> %2,%1,%0"
0b85d816
HPN
1786 [(set_attr "slottable" "yes,yes,no,no")])
1787\f
1788;; This is the special case when we use what corresponds to the
1789;; instruction above in "casesi". Do *not* change it to use the generic
1790;; pattern and "REG 15" as pc; I did that and it led to madness and
1791;; maintenance problems: Instead of (as imagined) recognizing and removing
1792;; or replacing this pattern with something simpler, other variant
1793;; patterns were recognized or combined, including some prefix variants
1794;; where the value in pc is not that of the next instruction (which means
1795;; this instruction actually *is* special and *should* be marked as such).
1796;; When switching from the "generic pattern match" approach to this simpler
1797;; approach, there were insignificant differences in gcc, ipps and
1798;; product code, somehow due to scratching reload behind the ear or
1799;; something. Testcase "gcc" looked .01% slower and 4 bytes bigger;
1800;; product code became .001% smaller but "looked better". The testcase
1801;; "ipps" was just different at register allocation).
1802;;
1803;; Assumptions in the jump optimizer forces us to use IF_THEN_ELSE in this
1804;; pattern with the default-label as the else, with the "if" being
1805;; index-is-less-than the max number of cases plus one. The default-label
1806;; is attached to the end of the case-table at time of output.
1807
1808(define_insn "*casesi_adds_w"
1809 [(set (pc)
1810 (if_then_else
1811 (ltu (match_operand:SI 0 "register_operand" "r")
1812 (match_operand:SI 1 "const_int_operand" "n"))
1813 (plus:SI (sign_extend:SI
1814 (mem:HI
1815 (plus:SI (mult:SI (match_dup 0) (const_int 2))
1816 (pc))))
1817 (pc))
1818 (label_ref (match_operand 2 "" ""))))
1819 (use (label_ref (match_operand 3 "" "")))]
1820
1821 "operands[0] != frame_pointer_rtx"
1822
1823 "adds.w [$pc+%0.w],$pc"
1824 [(set_attr "cc" "clobber")])
1825\f
1826;; Multiply instructions.
1827
1828;; Sometimes powers of 2 (which are normally canonicalized to a
1829;; left-shift) appear here, as a result of address reloading.
1830;; As a special, for values 3 and 5, we can match with an addi, so add those.
1831;;
1832;; FIXME: This may be unnecessary now.
1833;; Explicitly named for convenience of having a gen_... function.
1834
1835(define_insn "addi_mul"
1836 [(set (match_operand:SI 0 "register_operand" "=r")
1837 (mult:SI
1838 (match_operand:SI 1 "register_operand" "%0")
1839 (match_operand:SI 2 "const_int_operand" "n")))]
1840 "operands[0] != frame_pointer_rtx
1841 && operands[1] != frame_pointer_rtx
1842 && GET_CODE (operands[2]) == CONST_INT
1843 && (INTVAL (operands[2]) == 2
1844 || INTVAL (operands[2]) == 4 || INTVAL (operands[2]) == 3
1845 || INTVAL (operands[2]) == 5)"
0b85d816
HPN
1846{
1847 if (INTVAL (operands[2]) == 2)
22c3c091 1848 return "lslq 1,%0";
0b85d816 1849 else if (INTVAL (operands[2]) == 4)
22c3c091 1850 return "lslq 2,%0";
0b85d816 1851 else if (INTVAL (operands[2]) == 3)
22c3c091 1852 return "addi %0.w,%0";
0b85d816 1853 else if (INTVAL (operands[2]) == 5)
22c3c091
HPN
1854 return "addi %0.d,%0";
1855 return "BAD: adr_mulsi: %0=%1*%2";
1856}
0b85d816
HPN
1857[(set_attr "slottable" "yes")
1858 ;; No flags are changed if this insn is "addi", but it does not seem
1859 ;; worth the trouble to distinguish that to the lslq cases.
1860 (set_attr "cc" "clobber")])
1861
1862;; The addi insn as it is normally used.
1863
1864(define_insn "*addi"
1865 [(set (match_operand:SI 0 "register_operand" "=r")
1866 (plus:SI
1867 (mult:SI (match_operand:SI 2 "register_operand" "r")
1868 (match_operand:SI 3 "const_int_operand" "n"))
1869 (match_operand:SI 1 "register_operand" "0")))]
1870 "operands[0] != frame_pointer_rtx
1871 && operands[1] != frame_pointer_rtx
1872 && GET_CODE (operands[3]) == CONST_INT
1873 && (INTVAL (operands[3]) == 1
1874 || INTVAL (operands[3]) == 2 || INTVAL (operands[3]) == 4)"
1875 "addi %2%T3,%0"
1876 [(set_attr "slottable" "yes")
1877 (set_attr "cc" "none")])
1878
1879;; The mstep instruction. Probably not useful by itself; it's to
1880;; non-linear wrt. the other insns. We used to expand to it, so at least
1881;; it's correct.
1882
1883(define_insn "mstep_shift"
1884 [(set (match_operand:SI 0 "register_operand" "=r")
1885 (if_then_else:SI
1886 (lt:SI (cc0) (const_int 0))
1887 (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
1888 (const_int 1))
1889 (match_operand:SI 2 "register_operand" "r"))
1890 (ashift:SI (match_operand:SI 3 "register_operand" "0")
1891 (const_int 1))))]
1892 ""
1893 "mstep %2,%0"
1894 [(set_attr "slottable" "yes")])
1895
1896;; When illegitimate addresses are legitimized, sometimes gcc forgets
1897;; to canonicalize the multiplications.
1898;;
1899;; FIXME: Check gcc > 2.7.2, remove and possibly fix in gcc.
1900
1901(define_insn "mstep_mul"
1902 [(set (match_operand:SI 0 "register_operand" "=r")
1903 (if_then_else:SI
1904 (lt:SI (cc0) (const_int 0))
1905 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "0")
1906 (const_int 2))
1907 (match_operand:SI 2 "register_operand" "r"))
1908 (mult:SI (match_operand:SI 3 "register_operand" "0")
1909 (const_int 2))))]
1910 "operands[0] != frame_pointer_rtx
1911 && operands[1] != frame_pointer_rtx
1912 && operands[2] != frame_pointer_rtx
1913 && operands[3] != frame_pointer_rtx"
1914 "mstep %2,%0"
1915 [(set_attr "slottable" "yes")])
1916
22c3c091
HPN
1917(define_insn "<u>mul<s><mode>3"
1918 [(set (match_operand:WD 0 "register_operand" "=r")
1919 (mult:WD
1920 (szext:WD (match_operand:<S> 1 "register_operand" "%0"))
1921 (szext:WD (match_operand:<S> 2 "register_operand" "r"))))
f60c7155 1922 (clobber (match_scratch:SI 3 "=h"))]
0b85d816 1923 "TARGET_HAS_MUL_INSNS"
22c3c091 1924 "%!mul<su><mm> %2,%0"
86da66b5
HPN
1925 [(set (attr "slottable")
1926 (if_then_else (ne (symbol_ref "TARGET_MUL_BUG") (const_int 0))
1927 (const_string "no")
1928 (const_string "yes")))
22c3c091
HPN
1929 ;; For umuls.[bwd] it's just N unusable here, but let's be safe.
1930 ;; For muls.b, this really extends to SImode, so cc should be
1931 ;; considered clobbered.
1932 ;; For muls.w, it's just N unusable here, but let's be safe.
0b85d816
HPN
1933 (set_attr "cc" "clobber")])
1934
1935;; Note that gcc does not make use of such a thing as umulqisi3. It gets
1936;; confused and will erroneously use it instead of umulhisi3, failing (at
1937;; least) gcc.c-torture/execute/arith-rand.c at all optimization levels.
1938;; Inspection of optab code shows that there must be only one widening
1939;; multiplication per mode widened to.
1940
1941(define_insn "mulsi3"
1942 [(set (match_operand:SI 0 "register_operand" "=r")
ef6201a6 1943 (mult:SI (match_operand:SI 1 "register_operand" "%0")
f60c7155
HPN
1944 (match_operand:SI 2 "register_operand" "r")))
1945 (clobber (match_scratch:SI 3 "=h"))]
0b85d816 1946 "TARGET_HAS_MUL_INSNS"
86da66b5
HPN
1947 "%!muls.d %2,%0"
1948 [(set (attr "slottable")
1949 (if_then_else (ne (symbol_ref "TARGET_MUL_BUG") (const_int 0))
1950 (const_string "no")
1951 (const_string "yes")))
0b85d816
HPN
1952 ;; Just N unusable here, but let's be safe.
1953 (set_attr "cc" "clobber")])
1954\f
1955;; A few multiply variations.
1956
0b85d816
HPN
1957;; When needed, we can get the high 32 bits from the overflow
1958;; register. We don't care to split and optimize these.
1959;;
1960;; Note that cc0 is still valid after the move-from-overflow-register
1961;; insn; no special precaution need to be taken in cris_notice_update_cc.
1962
22c3c091 1963(define_insn "<u>mulsidi3"
0b85d816
HPN
1964 [(set (match_operand:DI 0 "register_operand" "=r")
1965 (mult:DI
22c3c091
HPN
1966 (szext:DI (match_operand:SI 1 "register_operand" "%0"))
1967 (szext:DI (match_operand:SI 2 "register_operand" "r"))))
f60c7155 1968 (clobber (match_scratch:SI 3 "=h"))]
0b85d816 1969 "TARGET_HAS_MUL_INSNS"
22c3c091 1970 "%!mul<su>.d %2,%M0\;move $mof,%H0")
0b85d816 1971
f60c7155
HPN
1972;; These two patterns may be expressible by other means, perhaps by making
1973;; [u]?mulsidi3 a define_expand.
1974
1975;; Due to register allocation braindamage, the clobber 1,2 alternatives
1976;; cause a move into the clobbered register *before* the insn, then
1977;; after the insn, mof is moved too, rather than the clobber assigned
1978;; the last mof target. This became apparent when making MOF and SRP
1979;; visible registers, with the necessary tweak to smulsi3_highpart.
1980;; Because these patterns are used in division by constants, that damage
1981;; is visible (ipps regression tests). Therefore the last two
1982;; alternatives, "helping" reload to avoid an unnecessary move, but
1983;; punished by force of one "?". Check code from "int d (int a) {return
1984;; a / 1000;}" and unsigned. FIXME: Comment above was for 3.2, revisit.
0b85d816 1985
22c3c091 1986(define_insn "<su>mulsi3_highpart"
f60c7155 1987 [(set (match_operand:SI 0 "nonimmediate_operand" "=h,h,?r,?r")
0b85d816
HPN
1988 (truncate:SI
1989 (lshiftrt:DI
1990 (mult:DI
22c3c091
HPN
1991 (szext:DI (match_operand:SI 1 "register_operand" "r,r,0,r"))
1992 (szext:DI (match_operand:SI 2 "register_operand" "r,r,r,0")))
0b85d816 1993 (const_int 32))))
f60c7155 1994 (clobber (match_scratch:SI 3 "=1,2,h,h"))]
0b85d816 1995 "TARGET_HAS_MUL_INSNS"
f60c7155 1996 "@
22c3c091
HPN
1997 %!mul<su>.d %2,%1
1998 %!mul<su>.d %1,%2
1999 %!mul<su>.d %2,%1\;move $mof,%0
2000 %!mul<su>.d %1,%2\;move $mof,%0"
f60c7155
HPN
2001 [(set_attr "slottable" "yes,yes,no,no")
2002 (set_attr "cc" "clobber")])
0b85d816
HPN
2003\f
2004;; Divide and modulus instructions. CRIS only has a step instruction.
2005
2006(define_insn "dstep_shift"
2007 [(set (match_operand:SI 0 "register_operand" "=r")
2008 (if_then_else:SI
2009 (geu:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
2010 (const_int 1))
2011 (match_operand:SI 2 "register_operand" "r"))
2012 (minus:SI (ashift:SI (match_operand:SI 3 "register_operand" "0")
2013 (const_int 1))
2014 (match_operand:SI 4 "register_operand" "2"))
2015 (ashift:SI (match_operand:SI 5 "register_operand" "0")
2016 (const_int 1))))]
2017 ""
2018 "dstep %2,%0"
2019 [(set_attr "slottable" "yes")])
2020
2021;; Here's a variant with mult instead of ashift.
2022;;
2023;; FIXME: This should be investigated. Which one matches through combination?
2024
2025(define_insn "dstep_mul"
2026 [(set (match_operand:SI 0 "register_operand" "=r")
2027 (if_then_else:SI
2028 (geu:SI (mult:SI (match_operand:SI 1 "register_operand" "0")
2029 (const_int 2))
2030 (match_operand:SI 2 "register_operand" "r"))
2031 (minus:SI (mult:SI (match_operand:SI 3 "register_operand" "0")
2032 (const_int 2))
2033 (match_operand:SI 4 "register_operand" "2"))
2034 (mult:SI (match_operand:SI 5 "register_operand" "0")
2035 (const_int 2))))]
2036 "operands[0] != frame_pointer_rtx
2037 && operands[1] != frame_pointer_rtx
2038 && operands[2] != frame_pointer_rtx
2039 && operands[3] != frame_pointer_rtx"
2040 "dstep %2,%0"
2041 [(set_attr "slottable" "yes")])
2042\f
2043;; Logical operators.
2044
2045;; Bitwise "and".
2046
2047;; There is no use in defining "anddi3", because gcc can expand this by
2048;; itself, and make reasonable code without interference.
2049
2050;; If the first operand is memory or a register and is the same as the
2051;; second operand, and the third operand is -256 or -65536, we can use
2052;; CLEAR instead. Or, if the first operand is a register, and the third
2053;; operand is 255 or 65535, we can zero_extend.
f5143c46 2054;; GCC isn't smart enough to recognize these cases (yet), and they seem
0b85d816
HPN
2055;; to be common enough to be worthwhile.
2056;; FIXME: This should be made obsolete.
2057
2058(define_expand "andsi3"
2059 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2060 (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
2061 (match_operand:SI 2 "general_operand" "")))]
2062 ""
0b85d816
HPN
2063{
2064 if (! (GET_CODE (operands[2]) == CONST_INT
2065 && (((INTVAL (operands[2]) == -256
2066 || INTVAL (operands[2]) == -65536)
2067 && rtx_equal_p (operands[1], operands[0]))
2068 || ((INTVAL (operands[2]) == 255
2069 || INTVAL (operands[2]) == 65535)
2070 && REG_P (operands[0])))))
2071 {
2072 /* Make intermediate steps if operand0 is not a register or
2073 operand1 is not a register, and hope that the reload pass will
2074 make something useful out of it. Note that the operands are
2075 *not* canonicalized. For the moment, I chicken out on this,
2076 because all or most ports do not describe 'and' with
2077 canonicalized operands, and I seem to remember magic in reload,
2078 checking that operand1 has constraint '%0', in which case
2079 operand0 and operand1 must have similar predicates.
2080 FIXME: Investigate. */
2081 rtx reg0 = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
2082 rtx reg1 = operands[1];
2083
2084 if (! REG_P (reg1))
2085 {
2086 emit_move_insn (reg0, reg1);
2087 reg1 = reg0;
2088 }
2089
2090 emit_insn (gen_rtx_SET (SImode, reg0,
2091 gen_rtx_AND (SImode, reg1, operands[2])));
2092
2093 /* Make sure we get the right *final* destination. */
2094 if (! REG_P (operands[0]))
2095 emit_move_insn (operands[0], reg0);
2096
2097 DONE;
2098 }
22c3c091 2099})
0b85d816
HPN
2100
2101;; Some special cases of andsi3.
2102
2103(define_insn "*andsi_movu"
2104 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
428eae94 2105 (and:SI (match_operand:SI 1 "nonimmediate_operand" "%r,Q,To")
0b85d816 2106 (match_operand:SI 2 "const_int_operand" "n,n,n")))]
f38a62ff 2107 "(INTVAL (operands[2]) == 255 || INTVAL (operands[2]) == 65535)
428eae94 2108 && (GET_CODE (operands[1]) != MEM || ! MEM_VOLATILE_P (operands[1]))"
0b85d816
HPN
2109 "movu.%z2 %1,%0"
2110 [(set_attr "slottable" "yes,yes,no")])
2111
2112(define_insn "*andsi_clear"
f38a62ff 2113 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,Q,Q,To,To")
0b85d816
HPN
2114 (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0,0,0")
2115 (match_operand:SI 2 "const_int_operand" "P,n,P,n,P,n")))]
f38a62ff
HPN
2116 "(INTVAL (operands[2]) == -65536 || INTVAL (operands[2]) == -256)
2117 && (GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0]))"
0b85d816
HPN
2118 "@
2119 cLear.b %0
2120 cLear.w %0
2121 cLear.b %0
2122 cLear.w %0
2123 cLear.b %0
2124 cLear.w %0"
2125 [(set_attr "slottable" "yes,yes,yes,yes,no,no")
2126 (set_attr "cc" "none")])
2127
2128;; This is a catch-all pattern, taking care of everything that was not
2129;; matched in the insns above.
2130;;
2131;; Sidenote: the tightening from "nonimmediate_operand" to
2132;; "register_operand" for operand 1 actually increased the register
2133;; pressure (worse code). That will hopefully change with an
2134;; improved reload pass.
2135
2136(define_insn "*expanded_andsi"
23369bef
HPN
2137 [(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r")
2138 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,r")
2139 (match_operand:SI 2 "general_operand" "I,r,Q>,g,!To")))]
0b85d816
HPN
2140 ""
2141 "@
2142 andq %2,%0
2143 and.d %2,%0
2144 and.d %2,%0
2145 and.d %2,%0
2146 and.d %2,%1,%0"
2147 [(set_attr "slottable" "yes,yes,yes,no,no")])
2148\f
2149;; For both QI and HI we may use the quick patterns. This results in
2150;; useless condition codes, but that is used rarely enough for it to
2151;; normally be a win (could check ahead for use of cc0, but seems to be
2152;; more pain than win).
2153
2154;; FIXME: See note for andsi3
2155
2156(define_expand "andhi3"
2157 [(set (match_operand:HI 0 "nonimmediate_operand" "")
2158 (and:HI (match_operand:HI 1 "nonimmediate_operand" "")
2159 (match_operand:HI 2 "general_operand" "")))]
2160 ""
0b85d816
HPN
2161{
2162 if (! (GET_CODE (operands[2]) == CONST_INT
2163 && (((INTVAL (operands[2]) == -256
2164 || INTVAL (operands[2]) == 65280)
2165 && rtx_equal_p (operands[1], operands[0]))
2166 || (INTVAL (operands[2]) == 255
2167 && REG_P (operands[0])))))
2168 {
2169 /* See comment for andsi3. */
2170 rtx reg0 = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (HImode);
2171 rtx reg1 = operands[1];
2172
2173 if (! REG_P (reg1))
2174 {
2175 emit_move_insn (reg0, reg1);
2176 reg1 = reg0;
2177 }
2178
2179 emit_insn (gen_rtx_SET (HImode, reg0,
2180 gen_rtx_AND (HImode, reg1, operands[2])));
2181
2182 /* Make sure we get the right destination. */
2183 if (! REG_P (operands[0]))
2184 emit_move_insn (operands[0], reg0);
2185
2186 DONE;
2187 }
22c3c091 2188})
0b85d816
HPN
2189
2190;; Some fast andhi3 special cases.
2191
2192(define_insn "*andhi_movu"
2193 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
428eae94 2194 (and:HI (match_operand:HI 1 "nonimmediate_operand" "r,Q,To")
0b85d816 2195 (const_int 255)))]
428eae94 2196 "GET_CODE (operands[1]) != MEM || ! MEM_VOLATILE_P (operands[1])"
0b85d816
HPN
2197 "mOvu.b %1,%0"
2198 [(set_attr "slottable" "yes,yes,no")])
2199
f38a62ff
HPN
2200(define_insn "*andhi_clear"
2201 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,Q,To")
0b85d816
HPN
2202 (and:HI (match_operand:HI 1 "nonimmediate_operand" "0,0,0")
2203 (const_int -256)))]
f38a62ff 2204 "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])"
0b85d816
HPN
2205 "cLear.b %0"
2206 [(set_attr "slottable" "yes,yes,no")
2207 (set_attr "cc" "none")])
2208
2209;; Catch-all andhi3 pattern.
2210
2211(define_insn "*expanded_andhi"
23369bef
HPN
2212 [(set (match_operand:HI 0 "register_operand" "=r,r,r, r,r,r,r")
2213 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0, 0,0,0,r")
2214 (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))]
0b85d816
HPN
2215
2216;; Sidenote: the tightening from "general_operand" to
2217;; "register_operand" for operand 1 actually increased the register
2218;; pressure (worse code). That will hopefully change with an
2219;; improved reload pass.
2220
2221 ""
2222 "@
2223 andq %2,%0
2224 and.w %2,%0
2225 and.w %2,%0
2226 and.w %2,%0
2227 anDq %b2,%0
2228 and.w %2,%0
2229 and.w %2,%1,%0"
2230 [(set_attr "slottable" "yes,yes,yes,no,yes,no,no")
2231 (set_attr "cc" "clobber,normal,normal,normal,clobber,normal,normal")])
2232
2233;; A strict_low_part pattern.
2234
2235(define_insn "*andhi_lowpart"
2236 [(set (strict_low_part
23369bef
HPN
2237 (match_operand:HI 0 "register_operand" "=r,r, r,r,r,r"))
2238 (and:HI (match_operand:HI 1 "register_operand" "%0,0, 0,0,0,r")
2239 (match_operand:HI 2 "general_operand" "r,Q>,L,O,g,!To")))]
0b85d816
HPN
2240 ""
2241 "@
2242 and.w %2,%0
2243 and.w %2,%0
2244 and.w %2,%0
2245 anDq %b2,%0
2246 and.w %2,%0
2247 and.w %2,%1,%0"
2248 [(set_attr "slottable" "yes,yes,no,yes,no,no")
2249 (set_attr "cc" "normal,normal,normal,clobber,normal,normal")])
2250\f
2251(define_insn "andqi3"
23369bef
HPN
2252 [(set (match_operand:QI 0 "register_operand" "=r,r,r, r,r,r")
2253 (and:QI (match_operand:QI 1 "register_operand" "%0,0,0, 0,0,r")
2254 (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))]
0b85d816
HPN
2255 ""
2256 "@
2257 andq %2,%0
2258 and.b %2,%0
2259 and.b %2,%0
2260 andQ %b2,%0
2261 and.b %2,%0
2262 and.b %2,%1,%0"
2263 [(set_attr "slottable" "yes,yes,yes,yes,no,no")
2264 (set_attr "cc" "clobber,normal,normal,clobber,normal,normal")])
2265
2266(define_insn "*andqi_lowpart"
2267 [(set (strict_low_part
23369bef
HPN
2268 (match_operand:QI 0 "register_operand" "=r,r, r,r,r"))
2269 (and:QI (match_operand:QI 1 "register_operand" "%0,0, 0,0,r")
2270 (match_operand:QI 2 "general_operand" "r,Q>,O,g,!To")))]
0b85d816
HPN
2271 ""
2272 "@
2273 and.b %2,%0
2274 and.b %2,%0
2275 andQ %b2,%0
2276 and.b %2,%0
2277 and.b %2,%1,%0"
2278 [(set_attr "slottable" "yes,yes,yes,no,no")
2279 (set_attr "cc" "normal,normal,clobber,normal,normal")])
2280\f
2281;; Bitwise or.
2282
2283;; Same comment as anddi3 applies here - no need for such a pattern.
2284
2285;; It seems there's no need to jump through hoops to get good code such as
2286;; with andsi3.
2287
2288(define_insn "iorsi3"
23369bef
HPN
2289 [(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r,r")
2290 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,0,r")
2291 (match_operand:SI 2 "general_operand" "I, r,Q>,n,g,!To")))]
0b85d816
HPN
2292 ""
2293 "@
2294 orq %2,%0
2295 or.d %2,%0
2296 or.d %2,%0
2297 oR.%s2 %2,%0
2298 or.d %2,%0
2299 or.d %2,%1,%0"
2300 [(set_attr "slottable" "yes,yes,yes,no,no,no")
2301 (set_attr "cc" "normal,normal,normal,clobber,normal,normal")])
2302
2303(define_insn "iorhi3"
23369bef
HPN
2304 [(set (match_operand:HI 0 "register_operand" "=r,r,r, r,r,r,r")
2305 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0, 0,0,0,r")
2306 (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))]
0b85d816
HPN
2307 ""
2308 "@
2309 orq %2,%0
2310 or.w %2,%0
2311 or.w %2,%0
2312 or.w %2,%0
2313 oRq %b2,%0
2314 or.w %2,%0
2315 or.w %2,%1,%0"
2316 [(set_attr "slottable" "yes,yes,yes,no,yes,no,no")
2317 (set_attr "cc" "clobber,normal,normal,normal,clobber,normal,normal")])
2318
2319(define_insn "iorqi3"
23369bef
HPN
2320 [(set (match_operand:QI 0 "register_operand" "=r,r,r, r,r,r")
2321 (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0, 0,0,r")
2322 (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))]
0b85d816
HPN
2323 ""
2324 "@
2325 orq %2,%0
2326 or.b %2,%0
2327 or.b %2,%0
2328 orQ %b2,%0
2329 or.b %2,%0
2330 or.b %2,%1,%0"
2331 [(set_attr "slottable" "yes,yes,yes,yes,no,no")
2332 (set_attr "cc" "clobber,normal,normal,clobber,normal,normal")])
2333\f
2334;; Exclusive-or
2335
2336;; See comment about "anddi3" for xordi3 - no need for such a pattern.
22c3c091 2337;; FIXME: Do we really need the shorter variants?
0b85d816
HPN
2338
2339(define_insn "xorsi3"
2340 [(set (match_operand:SI 0 "register_operand" "=r")
2341 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2342 (match_operand:SI 2 "register_operand" "r")))]
2343 ""
2344 "xor %2,%0"
2345 [(set_attr "slottable" "yes")])
2346
22c3c091
HPN
2347(define_insn "xor<mode>3"
2348 [(set (match_operand:BW 0 "register_operand" "=r")
2349 (xor:BW (match_operand:BW 1 "register_operand" "%0")
2350 (match_operand:BW 2 "register_operand" "r")))]
0b85d816
HPN
2351 ""
2352 "xor %2,%0"
2353 [(set_attr "slottable" "yes")
2354 (set_attr "cc" "clobber")])
2355\f
2356;; Negation insns.
2357
2358;; Questionable use, here mostly as a (slightly usable) define_expand
2359;; example.
2360
2361(define_expand "negsf2"
2362 [(set (match_dup 2)
2363 (match_dup 3))
2364 (parallel [(set (match_operand:SF 0 "register_operand" "=r")
2365 (neg:SF (match_operand:SF 1
2366 "register_operand" "0")))
2367 (use (match_dup 2))])]
2368 ""
0b85d816
HPN
2369{
2370 operands[2] = gen_reg_rtx (SImode);
2371 operands[3] = GEN_INT (1 << 31);
22c3c091 2372})
0b85d816
HPN
2373
2374(define_insn "*expanded_negsf2"
2375 [(set (match_operand:SF 0 "register_operand" "=r")
2376 (neg:SF (match_operand:SF 1 "register_operand" "0")))
2377 (use (match_operand:SI 2 "register_operand" "r"))]
2378 ""
2379 "xor %2,%0"
2380 [(set_attr "slottable" "yes")])
2381
2382;; No "negdi2" although we could make one up that may be faster than
2383;; the one in libgcc.
2384
22c3c091
HPN
2385(define_insn "neg<mode>2"
2386 [(set (match_operand:BWD 0 "register_operand" "=r")
2387 (neg:BWD (match_operand:BWD 1 "register_operand" "r")))]
0b85d816 2388 ""
22c3c091 2389 "neg<m> %1,%0"
0b85d816
HPN
2390 [(set_attr "slottable" "yes")])
2391\f
2392;; One-complements.
2393
2394;; See comment on anddi3 - no need for a DImode pattern.
22c3c091 2395;; See also xor comment.
0b85d816
HPN
2396
2397(define_insn "one_cmplsi2"
2398 [(set (match_operand:SI 0 "register_operand" "=r")
2399 (not:SI (match_operand:SI 1 "register_operand" "0")))]
2400 ""
2401 "not %0"
2402 [(set_attr "slottable" "yes")])
2403
22c3c091
HPN
2404(define_insn "one_cmpl<mode>2"
2405 [(set (match_operand:BW 0 "register_operand" "=r")
2406 (not:BW (match_operand:BW 1 "register_operand" "0")))]
0b85d816
HPN
2407 ""
2408 "not %0"
2409 [(set_attr "slottable" "yes")
2410 (set_attr "cc" "clobber")])
2411\f
22c3c091 2412;; Arithmetic/Logical shift right (and SI left).
0b85d816 2413
22c3c091 2414(define_insn "<shlr>si3"
0b85d816 2415 [(set (match_operand:SI 0 "register_operand" "=r")
22c3c091
HPN
2416 (shift:SI (match_operand:SI 1 "register_operand" "0")
2417 (match_operand:SI 2 "nonmemory_operand" "Kr")))]
0b85d816 2418 ""
0b85d816
HPN
2419{
2420 if (REG_S_P (operands[2]))
22c3c091 2421 return "<slr>.d %2,%0";
0b85d816 2422
22c3c091
HPN
2423 return "<slr>q %2,%0";
2424}
0b85d816 2425 [(set_attr "slottable" "yes")])
0b85d816 2426
22c3c091
HPN
2427;; Since gcc gets lost, and forgets to zero-extend the source (or mask
2428;; the destination) when it changes shifts of lower modes into SImode,
2429;; it is better to make these expands an anonymous patterns instead of
2430;; the more correct define_insns. This occurs when gcc thinks that is
2431;; is better to widen to SImode and use immediate shift count.
0b85d816 2432
22c3c091 2433;; FIXME: Is this legacy or still true for gcc >= 2.7.2?
0b85d816 2434
22c3c091
HPN
2435;; FIXME: Can't parametrize sign_extend and zero_extend (before
2436;; mentioning "shiftrt"), so we need two patterns.
2437(define_expand "ashr<mode>3"
0b85d816 2438 [(set (match_dup 3)
22c3c091 2439 (sign_extend:SI (match_operand:BW 1 "nonimmediate_operand" "")))
0b85d816 2440 (set (match_dup 4)
22c3c091
HPN
2441 (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand" "")))
2442 (set (match_dup 5) (ashiftrt:SI (match_dup 3) (match_dup 4)))
2443 (set (match_operand:BW 0 "general_operand" "")
2444 (subreg:BW (match_dup 5) 0))]
0b85d816 2445 ""
0b85d816
HPN
2446{
2447 int i;
2448
2449 for (i = 3; i < 6; i++)
2450 operands[i] = gen_reg_rtx (SImode);
22c3c091 2451})
0b85d816 2452
22c3c091 2453(define_expand "lshr<mode>3"
0b85d816 2454 [(set (match_dup 3)
22c3c091 2455 (zero_extend:SI (match_operand:BW 1 "nonimmediate_operand" "")))
0b85d816 2456 (set (match_dup 4)
22c3c091 2457 (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand" "")))
0b85d816 2458 (set (match_dup 5) (lshiftrt:SI (match_dup 3) (match_dup 4)))
22c3c091
HPN
2459 (set (match_operand:BW 0 "general_operand" "")
2460 (subreg:BW (match_dup 5) 0))]
0b85d816 2461 ""
0b85d816
HPN
2462{
2463 int i;
2464
2465 for (i = 3; i < 6; i++)
2466 operands[i] = gen_reg_rtx (SImode);
22c3c091 2467})
0b85d816 2468
22c3c091
HPN
2469(define_insn "*expanded_<shlr><mode>"
2470 [(set (match_operand:BW 0 "register_operand" "=r")
2471 (shiftrt:BW (match_operand:BW 1 "register_operand" "0")
2472 (match_operand:BW 2 "register_operand" "r")))]
0b85d816 2473 ""
22c3c091 2474 "<slr><m> %2,%0"
0b85d816
HPN
2475 [(set_attr "slottable" "yes")])
2476
22c3c091
HPN
2477(define_insn "*<shlr><mode>_lowpart"
2478 [(set (strict_low_part (match_operand:BW 0 "register_operand" "+r"))
2479 (shiftrt:BW (match_dup 0)
2480 (match_operand:BW 1 "register_operand" "r")))]
0b85d816 2481 ""
22c3c091 2482 "<slr><m> %1,%0"
0b85d816
HPN
2483 [(set_attr "slottable" "yes")])
2484\f
2485;; Arithmetic/logical shift left.
2486
0b85d816
HPN
2487;; For narrower modes than SI, we can use lslq although it makes cc
2488;; unusable. The win is that we do not have to reload the shift-count
2489;; into a register.
2490
22c3c091
HPN
2491(define_insn "ashl<mode>3"
2492 [(set (match_operand:BW 0 "register_operand" "=r,r")
2493 (ashift:BW (match_operand:BW 1 "register_operand" "0,0")
2494 (match_operand:BW 2 "nonmemory_operand" "r,K")))]
0b85d816 2495 ""
0b85d816
HPN
2496{
2497 return
2498 (GET_CODE (operands[2]) == CONST_INT
22c3c091
HPN
2499 && INTVAL (operands[2]) > <nbitsm1>)
2500 ? "moveq 0,%0"
0b85d816 2501 : (CONSTANT_P (operands[2])
22c3c091
HPN
2502 ? "lslq %2,%0" : "lsl<m> %2,%0");
2503}
0b85d816
HPN
2504 [(set_attr "slottable" "yes")
2505 (set_attr "cc" "normal,clobber")])
2506
2507;; A strict_low_part matcher.
2508
22c3c091
HPN
2509(define_insn "*ashl<mode>_lowpart"
2510 [(set (strict_low_part (match_operand:BW 0 "register_operand" "+r"))
2511 (ashift:BW (match_dup 0)
2512 (match_operand:HI 1 "register_operand" "r")))]
0b85d816 2513 ""
22c3c091 2514 "lsl<m> %1,%0"
0b85d816
HPN
2515 [(set_attr "slottable" "yes")])
2516\f
2517;; Various strange insns that gcc likes.
2518
2519;; Fortunately, it is simple to construct an abssf (although it may not
2520;; be very much used in practice).
2521
2522(define_insn "abssf2"
2523 [(set (match_operand:SF 0 "register_operand" "=r")
2524 (abs:SF (match_operand:SF 1 "register_operand" "0")))]
2525 ""
2526 "lslq 1,%0\;lsrq 1,%0")
2527
2528(define_insn "abssi2"
2529 [(set (match_operand:SI 0 "register_operand" "=r")
2530 (abs:SI (match_operand:SI 1 "register_operand" "r")))]
2531 ""
2532 "abs %1,%0"
2533 [(set_attr "slottable" "yes")])
2534
2535;; FIXME: GCC should be able to do these expansions itself.
2536
22c3c091 2537(define_expand "abs<mode>2"
0b85d816 2538 [(set (match_dup 2)
22c3c091 2539 (sign_extend:SI (match_operand:BW 1 "general_operand" "")))
0b85d816 2540 (set (match_dup 3) (abs:SI (match_dup 2)))
22c3c091
HPN
2541 (set (match_operand:BW 0 "register_operand" "")
2542 (subreg:BW (match_dup 3) 0))]
0b85d816
HPN
2543 ""
2544 "operands[2] = gen_reg_rtx (SImode); operands[3] = gen_reg_rtx (SImode);")
2545\f
2546;; Bound-insn. Defined to be the same as an unsigned minimum, which is an
2547;; operation supported by gcc. Used in casesi, but used now and then in
2548;; normal code too.
2549
2550(define_insn "uminsi3"
23369bef
HPN
2551 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r")
2552 (umin:SI (match_operand:SI 1 "register_operand" "%0,0, 0,r")
2553 (match_operand:SI 2 "general_operand" "r,Q>,g,!STo")))]
0b85d816 2554 ""
0b85d816
HPN
2555{
2556 if (GET_CODE (operands[2]) == CONST_INT)
2557 {
2558 if (INTVAL (operands[2]) < 256)
22c3c091 2559 return "bound.b %2,%0";
0b85d816
HPN
2560
2561 if (INTVAL (operands[2]) < 65536)
22c3c091 2562 return "bound.w %2,%0";
0b85d816
HPN
2563 }
2564 else if (which_alternative == 3)
22c3c091 2565 return "bound.d %2,%1,%0";
0b85d816 2566
22c3c091
HPN
2567 return "bound.d %2,%0";
2568}
0b85d816
HPN
2569 [(set_attr "slottable" "yes,yes,no,no")])
2570\f
2571;; Jump and branch insns.
2572
2573(define_insn "jump"
2574 [(set (pc)
2575 (label_ref (match_operand 0 "" "")))]
2576 ""
2577 "ba %l0%#"
2578 [(set_attr "slottable" "has_slot")])
2579
2580;; Testcase gcc.c-torture/compile/991213-3.c fails if we allow a constant
2581;; here, since the insn is not recognized as an indirect jump by
2582;; jmp_uses_reg_or_mem used by computed_jump_p. Perhaps it is a kludge to
2583;; change from general_operand to nonimmediate_operand (at least the docs
2584;; should be changed), but then again the pattern is called indirect_jump.
2585(define_insn "indirect_jump"
2586 [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
2587 ""
2588 "jump %0")
2589
2590;; Return insn. Used whenever the epilogue is very simple; if it is only
04539954
HPN
2591;; a single ret or jump [sp+]. No allocated stack space or saved
2592;; registers are allowed.
0b85d816
HPN
2593;; Note that for this pattern, although named, it is ok to check the
2594;; context of the insn in the test, not only compiler switches.
2595
04539954 2596(define_expand "return"
0b85d816
HPN
2597 [(return)]
2598 "cris_simple_epilogue ()"
04539954 2599 "cris_expand_return (cris_return_address_on_stack ()); DONE;")
0b85d816 2600
04539954
HPN
2601(define_insn "*return_expanded"
2602 [(return)]
2603 ""
2604{
2605 return cris_return_address_on_stack_for_return ()
2606 ? "jump [$sp+]" : "ret%#";
2607}
0b85d816 2608 [(set (attr "slottable")
04539954
HPN
2609 (if_then_else
2610 (ne (symbol_ref
2611 "(cris_return_address_on_stack_for_return ())")
2612 (const_int 0))
2613 (const_string "no")
2614 (const_string "has_slot")))])
2615
d29b4b1b
HPN
2616(define_expand "prologue"
2617 [(const_int 0)]
2618 "TARGET_PROLOGUE_EPILOGUE"
2619 "cris_expand_prologue (); DONE;")
2620
04539954
HPN
2621;; Note that the (return) from the expander itself is always the last
2622;; insn in the epilogue.
2623(define_expand "epilogue"
2624 [(const_int 0)]
a6dfafa0 2625 "TARGET_PROLOGUE_EPILOGUE"
04539954 2626 "cris_expand_epilogue (); DONE;")
0b85d816
HPN
2627\f
2628;; Conditional branches.
2629
2630;; We suffer from the same overflow-bit-gets-in-the-way problem as
2631;; e.g. m68k, so we have to check if overflow bit is set on all "signed"
2632;; conditions.
2633
221ca267 2634(define_insn "b<ncond:code>"
0b85d816 2635 [(set (pc)
22c3c091
HPN
2636 (if_then_else (ncond (cc0)
2637 (const_int 0))
0b85d816
HPN
2638 (label_ref (match_operand 0 "" ""))
2639 (pc)))]
2640 ""
22c3c091 2641 "b<CC> %l0%#"
0b85d816
HPN
2642 [(set_attr "slottable" "has_slot")])
2643
221ca267 2644(define_insn "b<ocond:code>"
0b85d816 2645 [(set (pc)
22c3c091
HPN
2646 (if_then_else (ocond (cc0)
2647 (const_int 0))
0b85d816
HPN
2648 (label_ref (match_operand 0 "" ""))
2649 (pc)))]
2650 ""
0b85d816
HPN
2651{
2652 return
2653 (cc_prev_status.flags & CC_NO_OVERFLOW)
221ca267 2654 ? 0 : "b<CC> %l0%#";
22c3c091 2655}
0b85d816
HPN
2656 [(set_attr "slottable" "has_slot")])
2657
221ca267 2658(define_insn "b<rcond:code>"
0b85d816 2659 [(set (pc)
22c3c091
HPN
2660 (if_then_else (rcond (cc0)
2661 (const_int 0))
0b85d816
HPN
2662 (label_ref (match_operand 0 "" ""))
2663 (pc)))]
2664 ""
0b85d816
HPN
2665{
2666 return
2667 (cc_prev_status.flags & CC_NO_OVERFLOW)
22c3c091
HPN
2668 ? "b<oCC> %l0%#" : "b<CC> %l0%#";
2669}
0b85d816
HPN
2670 [(set_attr "slottable" "has_slot")])
2671\f
2672;; Reversed anonymous patterns to the ones above, as mandated.
2673
221ca267 2674(define_insn "*b<ncond:code>_reversed"
0b85d816 2675 [(set (pc)
22c3c091
HPN
2676 (if_then_else (ncond (cc0)
2677 (const_int 0))
0b85d816
HPN
2678 (pc)
2679 (label_ref (match_operand 0 "" ""))))]
2680 ""
22c3c091 2681 "b<rCC> %l0%#"
0b85d816
HPN
2682 [(set_attr "slottable" "has_slot")])
2683
221ca267 2684(define_insn "*b<ocond:code>_reversed"
0b85d816 2685 [(set (pc)
22c3c091
HPN
2686 (if_then_else (ocond (cc0)
2687 (const_int 0))
0b85d816
HPN
2688 (pc)
2689 (label_ref (match_operand 0 "" ""))))]
2690 ""
0b85d816
HPN
2691{
2692 return
2693 (cc_prev_status.flags & CC_NO_OVERFLOW)
221ca267 2694 ? 0 : "b<rCC> %l0%#";
22c3c091 2695}
0b85d816
HPN
2696 [(set_attr "slottable" "has_slot")])
2697
221ca267 2698(define_insn "*b<rcond:code>_reversed"
0b85d816 2699 [(set (pc)
22c3c091
HPN
2700 (if_then_else (rcond (cc0)
2701 (const_int 0))
0b85d816
HPN
2702 (pc)
2703 (label_ref (match_operand 0 "" ""))))]
2704 ""
0b85d816
HPN
2705{
2706 return
2707 (cc_prev_status.flags & CC_NO_OVERFLOW)
221ca267 2708 ? "b<roCC> %l0%#" : "b<rCC> %l0%#";
22c3c091 2709}
0b85d816
HPN
2710 [(set_attr "slottable" "has_slot")])
2711\f
2712;; Set on condition: sCC.
2713
2714;; Like bCC, we have to check the overflow bit for
2715;; signed conditions.
2716
221ca267 2717(define_insn "s<ncond:code>"
0b85d816 2718 [(set (match_operand:SI 0 "register_operand" "=r")
22c3c091 2719 (ncond:SI (cc0) (const_int 0)))]
0b85d816 2720 ""
22c3c091 2721 "s<CC> %0"
0b85d816
HPN
2722 [(set_attr "slottable" "yes")
2723 (set_attr "cc" "none")])
2724
221ca267 2725(define_insn "s<rcond:code>"
0b85d816 2726 [(set (match_operand:SI 0 "register_operand" "=r")
22c3c091 2727 (rcond:SI (cc0) (const_int 0)))]
0b85d816 2728 ""
0b85d816
HPN
2729{
2730 return
2731 (cc_prev_status.flags & CC_NO_OVERFLOW)
22c3c091
HPN
2732 ? "s<oCC> %0" : "s<CC> %0";
2733}
0cec6af1
HPN
2734 [(set_attr "slottable" "yes")
2735 (set_attr "cc" "none")])
0b85d816 2736
221ca267 2737(define_insn "s<ocond:code>"
0b85d816 2738 [(set (match_operand:SI 0 "register_operand" "=r")
22c3c091 2739 (ocond:SI (cc0) (const_int 0)))]
0b85d816 2740 ""
0b85d816
HPN
2741{
2742 return
2743 (cc_prev_status.flags & CC_NO_OVERFLOW)
22c3c091
HPN
2744 ? 0 : "s<CC> %0";
2745}
0b85d816
HPN
2746 [(set_attr "slottable" "yes")
2747 (set_attr "cc" "none")])
2748\f
2749;; Call insns.
2750
2751;; We need to make these patterns "expand", since the real operand is
2752;; hidden in a (mem:QI ) inside operand[0] (call_value: operand[1]),
2753;; and cannot be checked if it were a "normal" pattern.
2754;; Note that "call" and "call_value" are *always* called with a
2755;; mem-operand for operand 0 and 1 respective. What happens for combined
2756;; instructions is a different issue.
2757
2758(define_expand "call"
2759 [(parallel [(call (match_operand:QI 0 "cris_mem_call_operand" "")
2760 (match_operand 1 "general_operand" ""))
f16bb520 2761 (clobber (reg:SI CRIS_SRP_REGNUM))])]
0b85d816 2762 ""
0b85d816
HPN
2763{
2764 rtx op0;
2765
b6c34129 2766 gcc_assert (GET_CODE (operands[0]) == MEM);
0b85d816
HPN
2767
2768 if (flag_pic)
2769 {
2770 op0 = XEXP (operands[0], 0);
2771
2772 /* It might be that code can be generated that jumps to 0 (or to a
b6c34129 2773 specific address). Don't die on that. (There is a testcase.) */
0b85d816
HPN
2774 if (CONSTANT_ADDRESS_P (op0) && GET_CODE (op0) != CONST_INT)
2775 {
b6c34129 2776 CRIS_ASSERT (!no_new_pseudos);
0b85d816
HPN
2777
2778 /* For local symbols (non-PLT), get the plain symbol reference
2779 into a register. For symbols that can be PLT, make them PLT. */
2780 if (cris_gotless_symbol (op0) || GET_CODE (op0) != SYMBOL_REF)
2781 op0 = force_reg (Pmode, op0);
2782 else if (cris_symbol (op0))
2783 /* FIXME: Would hanging a REG_EQUIV/EQUAL on that register
2784 for the symbol cause bad recombinatorial effects? */
2785 op0 = force_reg (Pmode,
2786 gen_rtx_CONST
68a81332 2787 (Pmode,
0b85d816 2788 gen_rtx_UNSPEC (VOIDmode,
04539954
HPN
2789 gen_rtvec (1, op0),
2790 CRIS_UNSPEC_PLT)));
0b85d816 2791 else
b6c34129 2792 internal_error ("Unidentifiable op0");
0b85d816 2793
dbb138ce 2794 operands[0] = replace_equiv_address (operands[0], op0);
0b85d816
HPN
2795 }
2796 }
b6c34129 2797})
0b85d816
HPN
2798
2799;; Accept *anything* as operand 1. Accept operands for operand 0 in
23369bef 2800;; order of preference.
0b85d816
HPN
2801
2802(define_insn "*expanded_call"
2803 [(call (mem:QI (match_operand:SI
2804 0 "cris_general_operand_or_plt_symbol" "r,Q>,g,S"))
2805 (match_operand 1 "" ""))
f16bb520 2806 (clobber (reg:SI CRIS_SRP_REGNUM))]
0b85d816
HPN
2807 "! TARGET_AVOID_GOTPLT"
2808 "jsr %0")
2809
2810;; Same as above, since can't afford wasting a constraint letter to mean
2811;; "S unless TARGET_AVOID_GOTPLT".
2812(define_insn "*expanded_call_no_gotplt"
2813 [(call (mem:QI (match_operand:SI
2814 0 "cris_general_operand_or_plt_symbol" "r,Q>,g"))
2815 (match_operand 1 "" ""))
f16bb520 2816 (clobber (reg:SI CRIS_SRP_REGNUM))]
0b85d816
HPN
2817 "TARGET_AVOID_GOTPLT"
2818 "jsr %0")
2819
2820(define_expand "call_value"
2821 [(parallel [(set (match_operand 0 "" "")
2822 (call (match_operand:QI 1 "cris_mem_call_operand" "")
2823 (match_operand 2 "" "")))
f16bb520 2824 (clobber (reg:SI CRIS_SRP_REGNUM))])]
0b85d816 2825 ""
0b85d816
HPN
2826{
2827 rtx op1;
2828
b6c34129 2829 gcc_assert (GET_CODE (operands[1]) == MEM);
0b85d816
HPN
2830
2831 if (flag_pic)
2832 {
2833 op1 = XEXP (operands[1], 0);
2834
2835 /* It might be that code can be generated that jumps to 0 (or to a
b6c34129 2836 specific address). Don't die on that. (There is a testcase.) */
0b85d816
HPN
2837 if (CONSTANT_ADDRESS_P (op1) && GET_CODE (op1) != CONST_INT)
2838 {
b6c34129 2839 CRIS_ASSERT (!no_new_pseudos);
0b85d816
HPN
2840
2841 if (cris_gotless_symbol (op1))
2842 op1 = force_reg (Pmode, op1);
2843 else if (cris_symbol (op1))
2844 /* FIXME: Would hanging a REG_EQUIV/EQUAL on that register
2845 for the symbol cause bad recombinatorial effects? */
2846 op1 = force_reg (Pmode,
2847 gen_rtx_CONST
68a81332 2848 (Pmode,
0b85d816 2849 gen_rtx_UNSPEC (VOIDmode,
04539954
HPN
2850 gen_rtvec (1, op1),
2851 CRIS_UNSPEC_PLT)));
0b85d816 2852 else
b6c34129 2853 internal_error ("Unidentifiable op0");
0b85d816 2854
dbb138ce 2855 operands[1] = replace_equiv_address (operands[1], op1);
0b85d816
HPN
2856 }
2857 }
b6c34129 2858})
0b85d816
HPN
2859
2860;; Accept *anything* as operand 2. The validity other than "general" of
2861;; operand 0 will be checked elsewhere. Accept operands for operand 1 in
2862;; order of preference (Q includes r, but r is shorter, faster).
2863;; We also accept a PLT symbol. We output it as [rPIC+sym:GOTPLT] rather
2864;; than requiring getting rPIC + sym:PLT into a register.
2865
2866(define_insn "*expanded_call_value"
2867 [(set (match_operand 0 "nonimmediate_operand" "=g,g,g,g")
2868 (call (mem:QI (match_operand:SI
2869 1 "cris_general_operand_or_plt_symbol" "r,Q>,g,S"))
2870 (match_operand 2 "" "")))
f16bb520 2871 (clobber (reg:SI CRIS_SRP_REGNUM))]
0b85d816
HPN
2872 "! TARGET_AVOID_GOTPLT"
2873 "Jsr %1"
2874 [(set_attr "cc" "clobber")])
2875
2876;; Same as above, since can't afford wasting a constraint letter to mean
2877;; "S unless TARGET_AVOID_GOTPLT".
2878(define_insn "*expanded_call_value_no_gotplt"
2879 [(set (match_operand 0 "nonimmediate_operand" "=g,g,g")
2880 (call (mem:QI (match_operand:SI
2881 1 "cris_general_operand_or_plt_symbol" "r,Q>,g"))
2882 (match_operand 2 "" "")))
f16bb520 2883 (clobber (reg:SI CRIS_SRP_REGNUM))]
0b85d816
HPN
2884 "TARGET_AVOID_GOTPLT"
2885 "Jsr %1"
2886 [(set_attr "cc" "clobber")])
2887
2888;; Used in debugging. No use for the direct pattern; unfilled
2889;; delayed-branches are taken care of by other means.
2890
2891(define_insn "nop"
2892 [(const_int 0)]
2893 ""
2894 "nop"
2895 [(set_attr "cc" "none")])
2896\f
04539954
HPN
2897;; We need to stop accesses to the stack after the memory is
2898;; deallocated. Unfortunately, reorg doesn't look at naked clobbers,
2899;; e.g. (insn ... (clobber (mem:BLK (stack_pointer_rtx)))) and we don't
2900;; want to use a naked (unspec_volatile) as that would stop any
2901;; scheduling in the epilogue. Hence we model it as a "real" insn that
2902;; sets the memory in an unspecified manner. FIXME: Unfortunately it
2903;; still has the effect of an unspec_volatile.
2904(define_insn "cris_frame_deallocated_barrier"
2905 [(set (mem:BLK (reg:SI CRIS_SP_REGNUM))
2906 (unspec:BLK [(const_int 0)] CRIS_UNSPEC_FRAME_DEALLOC))]
2907 ""
2908 ""
2909 [(set_attr "length" "0")])
2910
0b85d816
HPN
2911;; We expand on casesi so we can use "bound" and "add offset fetched from
2912;; a table to pc" (adds.w [pc+%0.w],pc).
2913
2914;; Note: if you change the "parallel" (or add anything after it) in
2915;; this expansion, you must change the macro ASM_OUTPUT_CASE_END
2916;; accordingly, to add the default case at the end of the jump-table.
2917
2918(define_expand "casesi"
2919 [(set (match_dup 5) (match_operand:SI 0 "general_operand" ""))
2920 (set (match_dup 6)
2921 (minus:SI (match_dup 5)
2922 (match_operand:SI 1 "const_int_operand" "n")))
2923 (set (match_dup 7)
2924 (umin:SI (match_dup 6)
2925 (match_operand:SI 2 "const_int_operand" "n")))
2926 (parallel
2927 [(set (pc)
2928 (if_then_else
2929 (ltu (match_dup 7) (match_dup 2))
2930 (plus:SI (sign_extend:SI
2931 (mem:HI
2932 (plus:SI (mult:SI (match_dup 7) (const_int 2))
2933 (pc))))
2934 (pc))
2935 (label_ref (match_operand 4 "" ""))))
2936 (use (label_ref (match_operand 3 "" "")))])]
2937 ""
0b85d816
HPN
2938{
2939 operands[2] = plus_constant (operands[2], 1);
2940 operands[5] = gen_reg_rtx (SImode);
2941 operands[6] = gen_reg_rtx (SImode);
2942 operands[7] = gen_reg_rtx (SImode);
22c3c091 2943})
0b85d816
HPN
2944\f
2945;; Split-patterns. Some of them have modes unspecified. This
2946;; should always be ok; if for no other reason sparc.md has it as
2947;; well.
2948;;
2949;; When register_operand is specified for an operand, we can get a
2950;; subreg as well (Axis-990331), so don't just assume that REG_P is true
2951;; for a register_operand and that REGNO can be used as is. It is best to
2952;; guard with REG_P, unless it is worth it to adjust for the subreg case.
2953
2954;; op [rx + 0],ry,rz
2955;; The index to rx is optimized into zero, and gone.
2956
2957;; First, recognize bound [rx],ry,rz; where [rx] is zero-extended,
2958;; and add/sub [rx],ry,rz, with zero or sign-extend on [rx].
2959;; Split this into:
2960;; move ry,rz
2961;; op [rx],rz
2962;; Lose if rz=ry or rx=rz.
2963;; Call this op-extend-split
2964
2965(define_split
2966 [(set (match_operand 0 "register_operand" "")
2967 (match_operator
2968 4 "cris_operand_extend_operator"
2969 [(match_operand 1 "register_operand" "")
2970 (match_operator
2971 3 "cris_extend_operator"
2972 [(match_operand 2 "memory_operand" "")])]))]
2973 "REG_P (operands[0])
2974 && REG_P (operands[1])
2975 && REGNO (operands[1]) != REGNO (operands[0])
2976 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
2977 && REG_P (XEXP (operands[2], 0))
2978 && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])"
2979 [(set (match_dup 0)
2980 (match_dup 1))
2981 (set (match_dup 0)
2982 (match_op_dup
2983 4 [(match_dup 0)
2984 (match_op_dup 3 [(match_dup 2)])]))]
2985 "")
2986
2987;; As op-extend-split, but recognize and split op [rz],ry,rz into
2988;; ext [rz],rz
2989;; op ry,rz
2990;; Do this for plus or bound only, being commutative operations, since we
2991;; have swapped the operands.
2992;; Call this op-extend-split-rx=rz
2993
2994(define_split
2995 [(set (match_operand 0 "register_operand" "")
2996 (match_operator
2997 4 "cris_plus_or_bound_operator"
2998 [(match_operand 1 "register_operand" "")
2999 (match_operator
3000 3 "cris_extend_operator"
3001 [(match_operand 2 "memory_operand" "")])]))]
3002 "REG_P (operands[0])
3003 && REG_P (operands[1])
3004 && REGNO (operands[1]) != REGNO (operands[0])
3005 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
3006 && REG_P (XEXP (operands[2], 0))
3007 && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])"
3008 [(set (match_dup 0)
3009 (match_op_dup 3 [(match_dup 2)]))
3010 (set (match_dup 0)
3011 (match_op_dup
3012 4 [(match_dup 0)
3013 (match_dup 1)]))]
3014 "")
3015
3016;; As the op-extend-split, but swapped operands, and only for
3017;; plus or bound, being the commutative extend-operators. FIXME: Why is
3018;; this needed? Is it?
3019;; Call this op-extend-split-swapped
3020
3021(define_split
3022 [(set (match_operand 0 "register_operand" "")
3023 (match_operator
3024 4 "cris_plus_or_bound_operator"
3025 [(match_operator
3026 3 "cris_extend_operator"
3027 [(match_operand 2 "memory_operand" "")])
3028 (match_operand 1 "register_operand" "")]))]
3029 "REG_P (operands[0])
3030 && REG_P (operands[1])
3031 && REGNO (operands[1]) != REGNO (operands[0])
3032 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
3033 && REG_P (XEXP (operands[2], 0))
3034 && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])"
3035 [(set (match_dup 0)
3036 (match_dup 1))
3037 (set (match_dup 0)
3038 (match_op_dup
3039 4 [(match_dup 0)
3040 (match_op_dup 3 [(match_dup 2)])]))]
3041 "")
3042
3043;; As op-extend-split-rx=rz, but swapped operands, only for plus or
3044;; bound. Call this op-extend-split-swapped-rx=rz.
3045
3046(define_split
3047 [(set (match_operand 0 "register_operand" "")
3048 (match_operator
3049 4 "cris_plus_or_bound_operator"
3050 [(match_operator
3051 3 "cris_extend_operator"
3052 [(match_operand 2 "memory_operand" "")])
3053 (match_operand 1 "register_operand" "")]))]
3054 "REG_P (operands[0])
3055 && REG_P (operands[1])
3056 && REGNO (operands[1]) != REGNO (operands[0])
3057 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
3058 && REG_P (XEXP (operands[2], 0))
3059 && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])"
3060 [(set (match_dup 0)
3061 (match_op_dup 3 [(match_dup 2)]))
3062 (set (match_dup 0)
3063 (match_op_dup
3064 4 [(match_dup 0)
3065 (match_dup 1)]))]
3066 "")
3067
3068;; As op-extend-split, but the mem operand is not extended.
3069;;
3070;; op [rx],ry,rz changed into
3071;; move ry,rz
3072;; op [rx],rz
3073;; lose if ry=rz or rx=rz
3074;; Call this op-extend.
3075
3076(define_split
3077 [(set (match_operand 0 "register_operand" "")
3078 (match_operator
3079 3 "cris_orthogonal_operator"
3080 [(match_operand 1 "register_operand" "")
3081 (match_operand 2 "memory_operand" "")]))]
3082 "REG_P (operands[0])
3083 && REG_P (operands[1])
3084 && REGNO (operands[1]) != REGNO (operands[0])
3085 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
3086 && REG_P (XEXP (operands[2], 0))
3087 && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])"
3088 [(set (match_dup 0)
3089 (match_dup 1))
3090 (set (match_dup 0)
3091 (match_op_dup
3092 3 [(match_dup 0)
3093 (match_dup 2)]))]
3094 "")
3095
3096;; As op-extend-split-rx=rz, non-extended.
3097;; Call this op-split-rx=rz
3098
3099(define_split
3100 [(set (match_operand 0 "register_operand" "")
3101 (match_operator
3102 3 "cris_commutative_orth_op"
3103 [(match_operand 2 "memory_operand" "")
3104 (match_operand 1 "register_operand" "")]))]
3105 "REG_P (operands[0])
3106 && REG_P (operands[1])
3107 && REGNO (operands[1]) != REGNO (operands[0])
3108 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
3109 && REG_P (XEXP (operands[2], 0))
3110 && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])"
3111 [(set (match_dup 0)
3112 (match_dup 1))
3113 (set (match_dup 0)
3114 (match_op_dup
3115 3 [(match_dup 0)
3116 (match_dup 2)]))]
3117 "")
3118
3119;; As op-extend-split-swapped, nonextended.
3120;; Call this op-split-swapped.
3121
3122(define_split
3123 [(set (match_operand 0 "register_operand" "")
3124 (match_operator
3125 3 "cris_commutative_orth_op"
3126 [(match_operand 1 "register_operand" "")
3127 (match_operand 2 "memory_operand" "")]))]
3128 "REG_P (operands[0]) && REG_P (operands[1])
3129 && REGNO (operands[1]) != REGNO (operands[0])
3130 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
3131 && REG_P (XEXP (operands[2], 0))
3132 && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])"
3133 [(set (match_dup 0)
3134 (match_dup 2))
3135 (set (match_dup 0)
3136 (match_op_dup
3137 3 [(match_dup 0)
3138 (match_dup 1)]))]
3139 "")
3140
3141;; As op-extend-split-swapped-rx=rz, non-extended.
3142;; Call this op-split-swapped-rx=rz.
3143
3144(define_split
3145 [(set (match_operand 0 "register_operand" "")
3146 (match_operator
3147 3 "cris_orthogonal_operator"
3148 [(match_operand 2 "memory_operand" "")
3149 (match_operand 1 "register_operand" "")]))]
3150 "REG_P (operands[0]) && REG_P (operands[1])
3151 && REGNO (operands[1]) != REGNO (operands[0])
3152 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
3153 && REG_P (XEXP (operands[2], 0))
3154 && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])"
3155 [(set (match_dup 0)
3156 (match_dup 2))
3157 (set (match_dup 0)
3158 (match_op_dup
3159 3 [(match_dup 0)
3160 (match_dup 1)]))]
3161 "")
3162\f
3163;; Splits for all cases in side-effect insns where (possibly after reload
3164;; and register allocation) rx and ry in [rx=ry+i] are equal.
3165
3166;; move.S1 [rx=rx+rz.S2],ry
3167
3168(define_split
3169 [(parallel
3170 [(set (match_operand 0 "register_operand" "")
dbb138ce
HPN
3171 (match_operator
3172 6 "cris_mem_op"
3173 [(plus:SI
3174 (mult:SI (match_operand:SI 1 "register_operand" "")
3175 (match_operand:SI 2 "const_int_operand" ""))
3176 (match_operand:SI 3 "register_operand" ""))]))
0b85d816 3177 (set (match_operand:SI 4 "register_operand" "")
8ad46d34
HPN
3178 (plus:SI (mult:SI (match_dup 1)
3179 (match_dup 2))
0b85d816
HPN
3180 (match_dup 3)))])]
3181 "REG_P (operands[3]) && REG_P (operands[4])
3182 && REGNO (operands[3]) == REGNO (operands[4])"
3183 [(set (match_dup 4) (plus:SI (mult:SI (match_dup 1) (match_dup 2))
8ad46d34 3184 (match_dup 3)))
0b85d816 3185 (set (match_dup 0) (match_dup 5))]
dbb138ce 3186 "operands[5] = replace_equiv_address (operands[6], operands[3]);")
0b85d816
HPN
3187
3188;; move.S1 [rx=rx+i],ry
3189
3190(define_split
3191 [(parallel
3192 [(set (match_operand 0 "register_operand" "")
dbb138ce
HPN
3193 (match_operator
3194 5 "cris_mem_op"
3195 [(plus:SI (match_operand:SI 1 "cris_bdap_operand" "")
3196 (match_operand:SI 2 "cris_bdap_operand" ""))]))
0b85d816
HPN
3197 (set (match_operand:SI 3 "register_operand" "")
3198 (plus:SI (match_dup 1)
3199 (match_dup 2)))])]
3200 "(rtx_equal_p (operands[3], operands[1])
3201 || rtx_equal_p (operands[3], operands[2]))"
3202 [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2)))
3203 (set (match_dup 0) (match_dup 4))]
dbb138ce 3204 "operands[4] = replace_equiv_address (operands[5], operands[3]);")
0b85d816
HPN
3205
3206;; move.S1 ry,[rx=rx+rz.S2]
3207
3208(define_split
3209 [(parallel
dbb138ce
HPN
3210 [(set (match_operator
3211 6 "cris_mem_op"
3212 [(plus:SI
3213 (mult:SI (match_operand:SI 0 "register_operand" "")
3214 (match_operand:SI 1 "const_int_operand" ""))
3215 (match_operand:SI 2 "register_operand" ""))])
3216 (match_operand 3 "register_operand" ""))
0b85d816
HPN
3217 (set (match_operand:SI 4 "register_operand" "")
3218 (plus:SI (mult:SI (match_dup 0)
3219 (match_dup 1))
3220 (match_dup 2)))])]
3221 "REG_P (operands[2]) && REG_P (operands[4])
3222 && REGNO (operands[4]) == REGNO (operands[2])"
3223 [(set (match_dup 4) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
3224 (match_dup 2)))
3225 (set (match_dup 5) (match_dup 3))]
dbb138ce 3226 "operands[5] = replace_equiv_address (operands[6], operands[4]);")
0b85d816
HPN
3227
3228;; move.S1 ry,[rx=rx+i]
3229
3230(define_split
3231 [(parallel
dbb138ce
HPN
3232 [(set (match_operator
3233 6 "cris_mem_op"
3234 [(plus:SI (match_operand:SI 0 "cris_bdap_operand" "")
3235 (match_operand:SI 1 "cris_bdap_operand" ""))])
3236 (match_operand 2 "register_operand" ""))
0b85d816
HPN
3237 (set (match_operand:SI 3 "register_operand" "")
3238 (plus:SI (match_dup 0)
3239 (match_dup 1)))])]
3240 "(rtx_equal_p (operands[3], operands[0])
3241 || rtx_equal_p (operands[3], operands[1]))"
3242 [(set (match_dup 3) (plus:SI (match_dup 0) (match_dup 1)))
3243 (set (match_dup 5) (match_dup 2))]
dbb138ce 3244 "operands[5] = replace_equiv_address (operands[6], operands[3]);")
0b85d816 3245
22c3c091 3246;; clear.[bwd] [rx=rx+rz.S2]
0b85d816
HPN
3247
3248(define_split
3249 [(parallel
22c3c091 3250 [(set (mem:BWD (plus:SI
0b85d816
HPN
3251 (mult:SI (match_operand:SI 0 "register_operand" "")
3252 (match_operand:SI 1 "const_int_operand" ""))
3253 (match_operand:SI 2 "register_operand" "")))
3254 (const_int 0))
3255 (set (match_operand:SI 3 "register_operand" "")
3256 (plus:SI (mult:SI (match_dup 0)
3257 (match_dup 1))
3258 (match_dup 2)))])]
3259 "REG_P (operands[2]) && REG_P (operands[3])
3260 && REGNO (operands[3]) == REGNO (operands[2])"
3261 [(set (match_dup 3) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
3262 (match_dup 2)))
22c3c091 3263 (set (mem:BWD (match_dup 3)) (const_int 0))]
0b85d816
HPN
3264 "")
3265
22c3c091 3266;; clear.[bwd] [rx=rx+i]
0b85d816
HPN
3267
3268(define_split
3269 [(parallel
22c3c091 3270 [(set (mem:BWD
0b85d816
HPN
3271 (plus:SI (match_operand:SI 0 "cris_bdap_operand" "")
3272 (match_operand:SI 1 "cris_bdap_operand" "")))
3273 (const_int 0))
3274 (set (match_operand:SI 2 "register_operand" "")
3275 (plus:SI (match_dup 0)
3276 (match_dup 1)))])]
3277 "(rtx_equal_p (operands[0], operands[2])
3278 || rtx_equal_p (operands[2], operands[1]))"
3279 [(set (match_dup 2) (plus:SI (match_dup 0) (match_dup 1)))
22c3c091 3280 (set (mem:BWD (match_dup 2)) (const_int 0))]
0b85d816
HPN
3281 "")
3282
3283;; mov(s|u).S1 [rx=rx+rz.S2],ry
3284
3285(define_split
3286 [(parallel
3287 [(set (match_operand 0 "register_operand" "")
3288 (match_operator
3289 5 "cris_extend_operator"
3290 [(mem (plus:SI
3291 (mult:SI (match_operand:SI 1 "register_operand" "")
3292 (match_operand:SI 2 "const_int_operand" ""))
3293 (match_operand:SI 3 "register_operand" "")))]))
3294 (set (match_operand:SI 4 "register_operand" "")
3295 (plus:SI (mult:SI (match_dup 1)
3296 (match_dup 2))
3297 (match_dup 3)))])]
3298 "REG_P (operands[3])
3299 && REG_P (operands[4])
3300 && REGNO (operands[3]) == REGNO (operands[4])"
3301 [(set (match_dup 4) (plus:SI (mult:SI (match_dup 1) (match_dup 2))
3302 (match_dup 3)))
3303 (set (match_dup 0) (match_op_dup 5 [(match_dup 6)]))]
dbb138ce 3304 "operands[6] = replace_equiv_address (XEXP (operands[5], 0), operands[4]);")
0b85d816
HPN
3305
3306;; mov(s|u).S1 [rx=rx+i],ry
3307
3308(define_split
3309 [(parallel
3310 [(set (match_operand 0 "register_operand" "")
3311 (match_operator
3312 4 "cris_extend_operator"
3313 [(mem (plus:SI
3314 (match_operand:SI 1 "cris_bdap_operand" "")
3315 (match_operand:SI 2 "cris_bdap_operand" "")))]))
3316 (set (match_operand:SI 3 "register_operand" "")
3317 (plus:SI (match_dup 1)
3318 (match_dup 2)))])]
3319 "(rtx_equal_p (operands[1], operands[3])
3320 || rtx_equal_p (operands[2], operands[3]))"
3321 [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2)))
3322 (set (match_dup 0) (match_op_dup 4 [(match_dup 5)]))]
dbb138ce 3323 "operands[5] = replace_equiv_address (XEXP (operands[4], 0), operands[3]);")
0b85d816
HPN
3324
3325;; op.S1 [rx=rx+i],ry
3326
3327(define_split
3328 [(parallel
3329 [(set (match_operand 0 "register_operand" "")
3330 (match_operator
3331 5 "cris_orthogonal_operator"
3332 [(match_operand 1 "register_operand" "")
3333 (mem (plus:SI
3334 (match_operand:SI 2 "cris_bdap_operand" "")
3335 (match_operand:SI 3 "cris_bdap_operand" "")))]))
3336 (set (match_operand:SI 4 "register_operand" "")
3337 (plus:SI (match_dup 2)
3338 (match_dup 3)))])]
3339 "(rtx_equal_p (operands[4], operands[2])
3340 || rtx_equal_p (operands[4], operands[3]))"
3341 [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
3342 (set (match_dup 0) (match_op_dup 5 [(match_dup 1) (match_dup 6)]))]
dbb138ce 3343 "operands[6] = replace_equiv_address (XEXP (operands[5], 1), operands[4]);")
0b85d816
HPN
3344
3345;; op.S1 [rx=rx+rz.S2],ry
3346
3347(define_split
3348 [(parallel
3349 [(set (match_operand 0 "register_operand" "")
3350 (match_operator
3351 6 "cris_orthogonal_operator"
3352 [(match_operand 1 "register_operand" "")
3353 (mem (plus:SI
3354 (mult:SI (match_operand:SI 2 "register_operand" "")
3355 (match_operand:SI 3 "const_int_operand" ""))
3356 (match_operand:SI 4 "register_operand" "")))]))
3357 (set (match_operand:SI 5 "register_operand" "")
3358 (plus:SI (mult:SI (match_dup 2)
3359 (match_dup 3))
3360 (match_dup 4)))])]
3361 "REG_P (operands[4])
3362 && REG_P (operands[5])
3363 && REGNO (operands[5]) == REGNO (operands[4])"
3364 [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
3365 (match_dup 4)))
3366 (set (match_dup 0) (match_op_dup 6 [(match_dup 1) (match_dup 7)]))]
dbb138ce 3367 "operands[7] = replace_equiv_address (XEXP (operands[6], 1), operands[5]);")
0b85d816
HPN
3368
3369;; op.S1 [rx=rx+rz.S2],ry (swapped)
3370
3371(define_split
3372 [(parallel
3373 [(set (match_operand 0 "register_operand" "")
3374 (match_operator
3375 6 "cris_commutative_orth_op"
3376 [(mem (plus:SI
3377 (mult:SI (match_operand:SI 2 "register_operand" "")
3378 (match_operand:SI 3 "const_int_operand" ""))
3379 (match_operand:SI 4 "register_operand" "")))
3380 (match_operand 1 "register_operand" "")]))
3381 (set (match_operand:SI 5 "register_operand" "")
3382 (plus:SI (mult:SI (match_dup 2)
3383 (match_dup 3))
3384 (match_dup 4)))])]
3385 "REG_P (operands[4])
3386 && REG_P (operands[5])
3387 && REGNO (operands[5]) == REGNO (operands[4])"
3388 [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
3389 (match_dup 4)))
3390 (set (match_dup 0) (match_op_dup 6 [(match_dup 7) (match_dup 1)]))]
dbb138ce 3391 "operands[7] = replace_equiv_address (XEXP (operands[6], 0), operands[5]);")
0b85d816
HPN
3392
3393;; op.S1 [rx=rx+i],ry (swapped)
3394
3395(define_split
3396 [(parallel
3397 [(set (match_operand 0 "register_operand" "")
3398 (match_operator
3399 5 "cris_commutative_orth_op"
3400 [(mem
3401 (plus:SI (match_operand:SI 2 "cris_bdap_operand" "")
3402 (match_operand:SI 3 "cris_bdap_operand" "")))
3403 (match_operand 1 "register_operand" "")]))
3404 (set (match_operand:SI 4 "register_operand" "")
3405 (plus:SI (match_dup 2)
3406 (match_dup 3)))])]
3407 "(rtx_equal_p (operands[4], operands[2])
3408 || rtx_equal_p (operands[4], operands[3]))"
3409 [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
3410 (set (match_dup 0) (match_op_dup 5 [(match_dup 6) (match_dup 1)]))]
dbb138ce 3411 "operands[6] = replace_equiv_address (XEXP (operands[5], 0), operands[4]);")
0b85d816
HPN
3412
3413;; op(s|u).S1 [rx=rx+rz.S2],ry
3414
3415(define_split
3416 [(parallel
3417 [(set (match_operand 0 "register_operand" "")
3418 (match_operator
3419 6 "cris_operand_extend_operator"
3420 [(match_operand 1 "register_operand" "")
3421 (match_operator
3422 7 "cris_extend_operator"
3423 [(mem (plus:SI
3424 (mult:SI (match_operand:SI 2 "register_operand" "")
3425 (match_operand:SI 3 "const_int_operand" ""))
3426 (match_operand:SI 4 "register_operand" "")))])]))
3427 (set (match_operand:SI 5 "register_operand" "")
3428 (plus:SI (mult:SI (match_dup 2)
3429 (match_dup 3))
3430 (match_dup 4)))])]
3431 "REG_P (operands[4])
3432 && REG_P (operands[5])
3433 && REGNO (operands[5]) == REGNO (operands[4])"
3434 [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
3435 (match_dup 4)))
3436 (set (match_dup 0) (match_op_dup 6 [(match_dup 1) (match_dup 8)]))]
1c563bed 3437 "operands[8] = gen_rtx_fmt_e (GET_CODE (operands[7]), GET_MODE (operands[7]),
0f4c242b
KH
3438 replace_equiv_address (XEXP (operands[7], 0),
3439 operands[5]));")
0b85d816
HPN
3440
3441;; op(s|u).S1 [rx=rx+i],ry
3442
3443(define_split
3444 [(parallel
3445 [(set (match_operand 0 "register_operand" "")
3446 (match_operator
3447 5 "cris_operand_extend_operator"
3448 [(match_operand 1 "register_operand" "")
3449 (match_operator
3450 6 "cris_extend_operator"
3451 [(mem
3452 (plus:SI (match_operand:SI 2 "cris_bdap_operand" "")
3453 (match_operand:SI 3 "cris_bdap_operand" "")
3454 ))])]))
3455 (set (match_operand:SI 4 "register_operand" "")
3456 (plus:SI (match_dup 2)
3457 (match_dup 3)))])]
3458 "(rtx_equal_p (operands[4], operands[2])
3459 || rtx_equal_p (operands[4], operands[3]))"
3460 [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
3461 (set (match_dup 0) (match_op_dup 5 [(match_dup 1) (match_dup 7)]))]
1c563bed 3462 "operands[7] = gen_rtx_fmt_e (GET_CODE (operands[6]), GET_MODE (operands[6]),
0f4c242b
KH
3463 replace_equiv_address (XEXP (operands[6], 0),
3464 operands[4]));")
0b85d816
HPN
3465
3466;; op(s|u).S1 [rx=rx+rz.S2],ry (swapped, plus or bound)
3467
3468(define_split
3469 [(parallel
3470 [(set (match_operand 0 "register_operand" "")
3471 (match_operator
3472 7 "cris_plus_or_bound_operator"
3473 [(match_operator
3474 6 "cris_extend_operator"
3475 [(mem (plus:SI
3476 (mult:SI (match_operand:SI 2 "register_operand" "")
3477 (match_operand:SI 3 "const_int_operand" ""))
3478 (match_operand:SI 4 "register_operand" "")))])
3479 (match_operand 1 "register_operand" "")]))
3480 (set (match_operand:SI 5 "register_operand" "")
3481 (plus:SI (mult:SI (match_dup 2)
3482 (match_dup 3))
3483 (match_dup 4)))])]
3484 "REG_P (operands[4]) && REG_P (operands[5])
3485 && REGNO (operands[5]) == REGNO (operands[4])"
3486 [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
3487 (match_dup 4)))
3488 (set (match_dup 0) (match_op_dup 6 [(match_dup 8) (match_dup 1)]))]
1c563bed 3489 "operands[8] = gen_rtx_fmt_e (GET_CODE (operands[6]), GET_MODE (operands[6]),
0f4c242b
KH
3490 replace_equiv_address (XEXP (operands[6], 0),
3491 operands[5]));")
0b85d816
HPN
3492
3493;; op(s|u).S1 [rx=rx+i],ry (swapped, plus or bound)
3494
3495(define_split
3496 [(parallel
3497 [(set (match_operand 0 "register_operand" "")
3498 (match_operator
3499 6 "cris_plus_or_bound_operator"
3500 [(match_operator
3501 5 "cris_extend_operator"
3502 [(mem (plus:SI
3503 (match_operand:SI 2 "cris_bdap_operand" "")
3504 (match_operand:SI 3 "cris_bdap_operand" "")))])
3505 (match_operand 1 "register_operand" "")]))
3506 (set (match_operand:SI 4 "register_operand" "")
3507 (plus:SI (match_dup 2)
3508 (match_dup 3)))])]
3509 "(rtx_equal_p (operands[4], operands[2])
3510 || rtx_equal_p (operands[4], operands[3]))"
3511 [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
3512 (set (match_dup 0) (match_op_dup 6 [(match_dup 7) (match_dup 1)]))]
1c563bed 3513 "operands[7] = gen_rtx_fmt_e (GET_CODE (operands[5]), GET_MODE (operands[5]),
0f4c242b
KH
3514 replace_equiv_address (XEXP (operands[5], 0),
3515 operands[4]));")
0b85d816
HPN
3516\f
3517;; Splits for addressing prefixes that have no side-effects, so we can
3518;; fill a delay slot. Never split if we lose something, though.
3519
3520;; If we have a
3521;; move [indirect_ref],rx
3522;; where indirect ref = {const, [r+], [r]}, it costs as much as
3523;; move indirect_ref,rx
3524;; move [rx],rx
3525;; Take care not to allow indirect_ref = register.
3526
3527;; We're not allowed to generate copies of registers with different mode
3528;; until after reload; copying pseudos upsets reload. CVS as of
3529;; 2001-08-24, unwind-dw2-fde.c, _Unwind_Find_FDE ICE in
3530;; cselib_invalidate_regno.
3531
f60c7155 3532(define_split ; indir_to_reg_split
0b85d816
HPN
3533 [(set (match_operand 0 "register_operand" "")
3534 (match_operand 1 "indirect_operand" ""))]
3535 "reload_completed
3536 && REG_P (operands[0])
3537 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
3538 && (GET_CODE (XEXP (operands[1], 0)) == MEM
f60c7155
HPN
3539 || CONSTANT_P (XEXP (operands[1], 0)))
3540 && REGNO (operands[0]) < CRIS_LAST_GENERAL_REGISTER"
0b85d816
HPN
3541 [(set (match_dup 2) (match_dup 4))
3542 (set (match_dup 0) (match_dup 3))]
3543 "operands[2] = gen_rtx_REG (Pmode, REGNO (operands[0]));
dbb138ce 3544 operands[3] = replace_equiv_address (operands[1], operands[2]);
0b85d816
HPN
3545 operands[4] = XEXP (operands[1], 0);")
3546
3547;; As the above, but MOVS and MOVU.
3548
3549(define_split
3550 [(set (match_operand 0 "register_operand" "")
3551 (match_operator
3552 4 "cris_extend_operator"
3553 [(match_operand 1 "indirect_operand" "")]))]
3554 "reload_completed
3555 && REG_P (operands[0])
3556 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
3557 && (GET_CODE (XEXP (operands[1], 0)) == MEM
3558 || CONSTANT_P (XEXP (operands[1], 0)))"
3559 [(set (match_dup 2) (match_dup 5))
3560 (set (match_dup 0) (match_op_dup 4 [(match_dup 3)]))]
3561 "operands[2] = gen_rtx_REG (Pmode, REGNO (operands[0]));
dbb138ce 3562 operands[3] = replace_equiv_address (XEXP (operands[4], 0), operands[2]);
0b85d816
HPN
3563 operands[5] = XEXP (operands[1], 0);")
3564\f
3565;; Various peephole optimizations.
3566;;
3567;; Watch out: when you exchange one set of instructions for another, the
3568;; condition codes setting must be the same, or you have to CC_INIT or
3569;; whatever is appropriate, in the pattern before you emit the
3570;; assembly text. This is best done here, not in cris_notice_update_cc,
3571;; to keep changes local to their cause.
3572;;
3573;; Do not add patterns that you do not know will be matched.
109b748d 3574;; Please also add a self-contained testcase.
0b85d816
HPN
3575
3576;; We have trouble with and:s and shifts. Maybe something is broken in
43a88a8c 3577;; gcc? Or it could just be that bit-field insn expansion is a bit
0b85d816 3578;; suboptimal when not having extzv insns.
8ad46d34 3579;; Testcase for the following four peepholes: gcc.dg/cris-peep2-xsrand.c
0b85d816 3580
8ad46d34
HPN
3581(define_peephole2 ; asrandb (peephole casesi+31)
3582 [(set (match_operand:SI 0 "register_operand" "")
0b85d816 3583 (ashiftrt:SI (match_dup 0)
8ad46d34 3584 (match_operand:SI 1 "const_int_operand" "")))
0b85d816
HPN
3585 (set (match_dup 0)
3586 (and:SI (match_dup 0)
8ad46d34 3587 (match_operand 2 "const_int_operand" "")))]
0b85d816
HPN
3588 "INTVAL (operands[2]) > 31
3589 && INTVAL (operands[2]) < 255
8ad46d34
HPN
3590 && INTVAL (operands[1]) > 23
3591 /* Check that the and-operation enables us to use logical-shift. */
3592 && (INTVAL (operands[2])
3593 & ((HOST_WIDE_INT) -1 << (32 - INTVAL (operands[1])))) == 0"
3594 [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
bf6ac87c 3595 (set (match_dup 3) (and:QI (match_dup 3) (match_dup 4)))]
8ad46d34 3596 ;; FIXME: CC0 is valid except for the M bit.
bf6ac87c
HPN
3597{
3598 operands[3] = gen_rtx_REG (QImode, REGNO (operands[0]));
3599 operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), QImode));
3600})
8ad46d34
HPN
3601
3602(define_peephole2 ; asrandw (peephole casesi+32)
3603 [(set (match_operand:SI 0 "register_operand" "")
0b85d816 3604 (ashiftrt:SI (match_dup 0)
8ad46d34 3605 (match_operand:SI 1 "const_int_operand" "")))
0b85d816 3606 (set (match_dup 0)
8ad46d34 3607 (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
0b85d816
HPN
3608 "INTVAL (operands[2]) > 31
3609 && INTVAL (operands[2]) < 65535
3610 && INTVAL (operands[2]) != 255
8ad46d34
HPN
3611 && INTVAL (operands[1]) > 15
3612 /* Check that the and-operation enables us to use logical-shift. */
3613 && (INTVAL (operands[2])
3614 & ((HOST_WIDE_INT) -1 << (32 - INTVAL (operands[1])))) == 0"
3615 [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
bf6ac87c 3616 (set (match_dup 3) (and:HI (match_dup 3) (match_dup 4)))]
8ad46d34 3617 ;; FIXME: CC0 is valid except for the M bit.
bf6ac87c
HPN
3618{
3619 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
3620 operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), HImode));
3621})
8ad46d34
HPN
3622
3623(define_peephole2 ; lsrandb (peephole casesi+33)
3624 [(set (match_operand:SI 0 "register_operand" "")
0b85d816 3625 (lshiftrt:SI (match_dup 0)
8ad46d34 3626 (match_operand:SI 1 "const_int_operand" "")))
0b85d816 3627 (set (match_dup 0)
8ad46d34 3628 (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
0b85d816
HPN
3629 "INTVAL (operands[2]) > 31
3630 && INTVAL (operands[2]) < 255
3631 && INTVAL (operands[1]) > 23"
8ad46d34 3632 [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
bf6ac87c 3633 (set (match_dup 3) (and:QI (match_dup 3) (match_dup 4)))]
8ad46d34 3634 ;; FIXME: CC0 is valid except for the M bit.
bf6ac87c
HPN
3635{
3636 operands[3] = gen_rtx_REG (QImode, REGNO (operands[0]));
3637 operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), QImode));
3638})
0b85d816 3639
8ad46d34
HPN
3640(define_peephole2 ; lsrandw (peephole casesi+34)
3641 [(set (match_operand:SI 0 "register_operand" "")
0b85d816 3642 (lshiftrt:SI (match_dup 0)
8ad46d34 3643 (match_operand:SI 1 "const_int_operand" "")))
0b85d816 3644 (set (match_dup 0)
8ad46d34 3645 (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
0b85d816
HPN
3646 "INTVAL (operands[2]) > 31 && INTVAL (operands[2]) < 65535
3647 && INTVAL (operands[2]) != 255
3648 && INTVAL (operands[1]) > 15"
8ad46d34 3649 [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
bf6ac87c 3650 (set (match_dup 3) (and:HI (match_dup 3) (match_dup 4)))]
8ad46d34 3651 ;; FIXME: CC0 is valid except for the M bit.
bf6ac87c
HPN
3652{
3653 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
3654 operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), HImode));
3655})
0b85d816
HPN
3656\f
3657
3658;; Change
3659;; add.d n,rx
3660;; move [rx],ry
3661;; into
3662;; move [rx=rx+n],ry
3663;; when -128 <= n <= 127.
3664;; This will reduce the size of the assembler code for n = [-128..127],
8ad46d34
HPN
3665;; and speed up accordingly. Don't match if the previous insn is
3666;; (set rx rz) because that combination is matched by another peephole.
3667;; No stable test-case.
3668
3669(define_peephole2 ; moversideqi (peephole casesi+35)
3670 [(set (match_operand:SI 0 "register_operand" "")
3671 (plus:SI (match_operand:SI 1 "register_operand" "")
3672 (match_operand:SI 2 "const_int_operand" "")))
3673 (set (match_operand 3 "register_operand" "")
3674 (match_operator 4 "cris_mem_op" [(match_dup 0)]))]
3675 "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
3676 && REGNO (operands[3]) != REGNO (operands[0])
3677 && (BASE_P (operands[1]) || BASE_P (operands[2]))
3678 && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
3679 && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
3680 && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)"
3681 [(parallel
3682 [(set (match_dup 3) (match_dup 5))
3683 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
3684 ;; Checking the previous insn is a bit too awkward for the condition.
3685{
3686 rtx prev = prev_nonnote_insn (curr_insn);
3687 if (prev != NULL_RTX)
3688 {
3689 rtx set = single_set (prev);
3690 if (set != NULL_RTX
3691 && REG_S_P (SET_DEST (set))
3692 && REGNO (SET_DEST (set)) == REGNO (operands[0])
3693 && REG_S_P (SET_SRC (set)))
3694 FAIL;
3695 }
3696 operands[5]
3697 = replace_equiv_address (operands[4],
3698 gen_rtx_PLUS (SImode,
3699 operands[1], operands[2]));
3700})
0b85d816
HPN
3701
3702;; Vice versa: move ry,[rx=rx+n]
3703
8ad46d34
HPN
3704(define_peephole2 ; movemsideqi (peephole casesi+36)
3705 [(set (match_operand:SI 0 "register_operand" "")
3706 (plus:SI (match_operand:SI 1 "register_operand" "")
3707 (match_operand:SI 2 "const_int_operand" "")))
3708 (set (match_operator 3 "cris_mem_op" [(match_dup 0)])
3709 (match_operand 4 "register_operand" ""))]
3710 "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
3711 && REGNO (operands[4]) != REGNO (operands[0])
3712 && (BASE_P (operands[1]) || BASE_P (operands[2]))
3713 && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
3714 && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
3715 && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)"
3716 [(parallel
3717 [(set (match_dup 5) (match_dup 4))
3718 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
3719 "operands[5]
3720 = replace_equiv_address (operands[3],
3721 gen_rtx_PLUS (SImode,
3722 operands[1], operands[2]));")
0b85d816
HPN
3723\f
3724;; As above, change:
3725;; add.d n,rx
3726;; op.d [rx],ry
3727;; into:
3728;; op.d [rx=rx+n],ry
3729;; Saves when n = [-128..127].
3730;;
3731;; Splitting and joining combinations for side-effect modes are slightly
3732;; out of hand. They probably will not save the time they take typing in,
3733;; not to mention the bugs that creep in. FIXME: Get rid of as many of
3734;; the splits and peepholes as possible.
8ad46d34
HPN
3735;; No stable test-case.
3736
3737(define_peephole2 ; mover2side (peephole casesi+37)
3738 [(set (match_operand:SI 0 "register_operand" "")
3739 (plus:SI (match_operand:SI 1 "register_operand" "")
3740 (match_operand:SI 2 "const_int_operand" "")))
3741 (set (match_operand 3 "register_operand" "")
3742 (match_operator 4 "cris_orthogonal_operator"
3743 [(match_dup 3)
3744 (match_operator
3745 5 "cris_mem_op" [(match_dup 0)])]))]
477c433d
HPN
3746 ;; FIXME: What about DFmode?
3747 ;; Change to GET_MODE_SIZE (GET_MODE (operands[3])) <= UNITS_PER_WORD?
0b85d816 3748 "GET_MODE (operands[3]) != DImode
8ad46d34
HPN
3749 && REGNO (operands[0]) != REGNO (operands[3])
3750 && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
3751 && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
3752 && INTVAL (operands[2]) >= -128
3753 && INTVAL (operands[2]) <= 127"
3754 [(parallel
3755 [(set (match_dup 3) (match_op_dup 4 [(match_dup 3) (match_dup 6)]))
3756 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
3757 "operands[6]
3758 = replace_equiv_address (operands[5],
3759 gen_rtx_PLUS (SImode,
3760 operands[1], operands[2]));")
0b85d816
HPN
3761
3762;; Sometimes, for some reason the pattern
3763;; move x,rx
3764;; add y,rx
3765;; move [rx],rz
3766;; will occur. Solve this, and likewise for to-memory.
8ad46d34 3767;; No stable test-case.
0b85d816 3768
8ad46d34
HPN
3769(define_peephole2 ; moverside (peephole casesi+38)
3770 [(set (match_operand:SI 0 "register_operand" "")
3771 (match_operand:SI 1 "cris_bdap_biap_operand" ""))
0b85d816 3772 (set (match_dup 0)
8ad46d34
HPN
3773 (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "")
3774 (match_operand:SI 3 "cris_bdap_biap_operand" "")))
3775 (set (match_operand 4 "register_operand" "")
3776 (match_operator 5 "cris_mem_op" [(match_dup 0)]))]
0b85d816
HPN
3777 "(rtx_equal_p (operands[2], operands[0])
3778 || rtx_equal_p (operands[3], operands[0]))
3779 && cris_side_effect_mode_ok (PLUS, operands, 0,
8ad46d34
HPN
3780 (REG_S_P (operands[1])
3781 ? 1
3782 : (rtx_equal_p (operands[2], operands[0])
3783 ? 3 : 2)),
3784 (! REG_S_P (operands[1])
3785 ? 1
3786 : (rtx_equal_p (operands[2], operands[0])
3787 ? 3 : 2)),
3788 -1, 4)"
3789 [(parallel
3790 [(set (match_dup 4) (match_dup 6))
3791 (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 8)))])]
3792{
e758023d 3793 rtx otherop
8ad46d34
HPN
3794 = rtx_equal_p (operands[2], operands[0]) ? operands[3] : operands[2];
3795
8820e4be
HPN
3796 /* Make sure we have canonical RTX so we match the insn pattern -
3797 not a constant in the first operand. We also require the order
3798 (plus reg mem) to match the final pattern. */
3799 if (CONSTANT_P (otherop) || MEM_P (otherop))
8ad46d34
HPN
3800 {
3801 operands[7] = operands[1];
e758023d 3802 operands[8] = otherop;
8ad46d34
HPN
3803 }
3804 else
3805 {
e758023d 3806 operands[7] = otherop;
8ad46d34
HPN
3807 operands[8] = operands[1];
3808 }
3809 operands[6]
3810 = replace_equiv_address (operands[5],
3811 gen_rtx_PLUS (SImode,
3812 operands[7], operands[8]));
3813})
0b85d816
HPN
3814
3815;; As above but to memory.
8ad46d34
HPN
3816;; FIXME: Split movemside and moverside into variants and prune
3817;; the ones that don't trig.
3818;; No stable test-case.
0b85d816 3819
8ad46d34
HPN
3820(define_peephole2 ; movemside (peephole casesi+39)
3821 [(set (match_operand:SI 0 "register_operand" "")
3822 (match_operand:SI 1 "cris_bdap_biap_operand" ""))
0b85d816 3823 (set (match_dup 0)
8ad46d34
HPN
3824 (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "")
3825 (match_operand:SI 3 "cris_bdap_biap_operand" "")))
3826 (set (match_operator 4 "cris_mem_op" [(match_dup 0)])
3827 (match_operand 5 "register_operand" ""))]
0b85d816
HPN
3828 "(rtx_equal_p (operands[2], operands[0])
3829 || rtx_equal_p (operands[3], operands[0]))
3830 && cris_side_effect_mode_ok (PLUS, operands, 0,
8ad46d34
HPN
3831 (REG_S_P (operands[1])
3832 ? 1
3833 : (rtx_equal_p (operands[2], operands[0])
3834 ? 3 : 2)),
3835 (! REG_S_P (operands[1])
3836 ? 1
3837 : (rtx_equal_p (operands[2], operands[0])
3838 ? 3 : 2)),
3839 -1, 5)"
3840 [(parallel
3841 [(set (match_dup 6) (match_dup 5))
3842 (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 8)))])]
3843{
e758023d 3844 rtx otherop
8ad46d34 3845 = rtx_equal_p (operands[2], operands[0]) ? operands[3] : operands[2];
0b85d816 3846
8820e4be
HPN
3847 /* Make sure we have canonical RTX so we match the insn pattern -
3848 not a constant in the first operand. We also require the order
3849 (plus reg mem) to match the final pattern. */
3850 if (CONSTANT_P (otherop) || MEM_P (otherop))
8ad46d34
HPN
3851 {
3852 operands[7] = operands[1];
e758023d 3853 operands[8] = otherop;
8ad46d34
HPN
3854 }
3855 else
3856 {
e758023d 3857 operands[7] = otherop;
8ad46d34
HPN
3858 operands[8] = operands[1];
3859 }
3860 operands[6]
3861 = replace_equiv_address (operands[4],
3862 gen_rtx_PLUS (SImode,
3863 operands[7], operands[8]));
3864})
0b85d816
HPN
3865
3866;; Another spotted bad code:
3867;; move rx,ry
3868;; move [ry],ry
8ad46d34 3869;; No stable test-case.
0b85d816 3870
8ad46d34
HPN
3871(define_peephole2 ; movei (peephole casesi+42)
3872 [(set (match_operand:SI 0 "register_operand" "")
3873 (match_operand:SI 1 "register_operand" ""))
3874 (set (match_operand 2 "register_operand" "")
3875 (match_operator 3 "cris_mem_op" [(match_dup 0)]))]
0b85d816 3876 "REGNO (operands[0]) == REGNO (operands[2])
f60c7155
HPN
3877 && (REGNO_REG_CLASS (REGNO (operands[0]))
3878 == REGNO_REG_CLASS (REGNO (operands[1])))
0b85d816 3879 && GET_MODE_SIZE (GET_MODE (operands[2])) <= UNITS_PER_WORD"
8ad46d34
HPN
3880 [(set (match_dup 2) (match_dup 4))]
3881 "operands[4] = replace_equiv_address (operands[3], operands[1]);")
0b85d816 3882
0b85d816
HPN
3883;; move.d [r10+16],r9
3884;; and.d r12,r9
3885;; change to
3886;; and.d [r10+16],r12,r9
3887;; With generalization of the operation, the size and the addressing mode.
3888;; This seems to be the result of a quirk in register allocation
3889;; missing the three-operand cases when having different predicates.
3890;; Maybe that it matters that it is a commutative operation.
3891;; This pattern helps that situation, but there's still the increased
3892;; register pressure.
3893;; Note that adding the noncommutative variant did not show any matches
3894;; in ipps and cc1, so it's not here.
8ad46d34 3895;; No stable test-case.
0b85d816 3896
8ad46d34
HPN
3897(define_peephole2 ; op3 (peephole casesi+44)
3898 [(set (match_operand 0 "register_operand" "")
3899 (match_operator
3900 6 "cris_mem_op"
3901 [(plus:SI
3902 (match_operand:SI 1 "cris_bdap_biap_operand" "")
3903 (match_operand:SI 2 "cris_bdap_biap_operand" ""))]))
0b85d816 3904 (set (match_dup 0)
8ad46d34
HPN
3905 (match_operator
3906 5 "cris_commutative_orth_op"
3907 [(match_operand 3 "register_operand" "")
3908 (match_operand 4 "register_operand" "")]))]
0b85d816
HPN
3909 "(rtx_equal_p (operands[3], operands[0])
3910 || rtx_equal_p (operands[4], operands[0]))
3911 && ! rtx_equal_p (operands[3], operands[4])
3912 && (REG_S_P (operands[1]) || REG_S_P (operands[2]))
3913 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD"
8ad46d34
HPN
3914 [(set (match_dup 0) (match_op_dup 5 [(match_dup 7) (match_dup 6)]))]
3915 "operands[7]
3916 = rtx_equal_p (operands[3], operands[0]) ? operands[4] : operands[3];")
0b85d816 3917
0b85d816
HPN
3918;; I cannot tell GCC (2.1, 2.7.2) how to correctly reload an instruction
3919;; that looks like
3920;; and.b some_byte,const,reg_32
3921;; where reg_32 is the destination of the "three-address" code optimally.
3922;; It should be:
3923;; movu.b some_byte,reg_32
3924;; and.b const,reg_32
3925;; but is turns into:
3926;; move.b some_byte,reg_32
3927;; and.d const,reg_32
3928;; Fix it here.
8ad46d34 3929;; Testcases: gcc.dg/cris-peep2-andu1.c gcc.dg/cris-peep2-andu2.c
0b85d816 3930
8ad46d34
HPN
3931(define_peephole2 ; andu (casesi+45)
3932 [(set (match_operand:SI 0 "register_operand" "")
3933 (match_operand:SI 1 "nonimmediate_operand" ""))
3934 (set (match_operand:SI 2 "register_operand" "")
0b85d816 3935 (and:SI (match_dup 0)
8ad46d34 3936 (match_operand:SI 3 "const_int_operand" "")))]
0b85d816
HPN
3937 ;; Since the size of the memory access could be made different here,
3938 ;; don't do this for a mem-volatile access.
0b85d816
HPN
3939 "REGNO (operands[2]) == REGNO (operands[0])
3940 && INTVAL (operands[3]) <= 65535 && INTVAL (operands[3]) >= 0
3941 && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'I')
3942 && (GET_CODE (operands[1]) != MEM || ! MEM_VOLATILE_P (operands[1]))"
8ad46d34
HPN
3943 ;; FIXME: CC0 valid except for M (i.e. CC_NOT_NEGATIVE).
3944 [(set (match_dup 0) (match_dup 4))
3945 (set (match_dup 5) (match_dup 6))]
0b85d816 3946{
8ad46d34
HPN
3947 enum machine_mode zmode = INTVAL (operands[3]) <= 255 ? QImode : HImode;
3948 enum machine_mode amode
3949 = CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'O') ? SImode : zmode;
3950 rtx op1
3951 = (REG_S_P (operands[1])
3952 ? gen_rtx_REG (zmode, REGNO (operands[1]))
3953 : adjust_address (operands[1], zmode, 0));
3954 operands[4]
3955 = gen_rtx_ZERO_EXTEND (SImode, op1);
3956 operands[5] = gen_rtx_REG (amode, REGNO (operands[0]));
3957 operands[6]
3958 = gen_rtx_AND (amode, gen_rtx_REG (amode, REGNO (operands[0])),
3959 GEN_INT (trunc_int_for_mode (INTVAL (operands[3]),
3960 amode == SImode
3961 ? QImode : amode)));
3962})
0b85d816
HPN
3963\f
3964;; Local variables:
3965;; mode:emacs-lisp
3966;; comment-start: ";; "
3967;; eval: (set-syntax-table (copy-sequence (syntax-table)))
3968;; eval: (modify-syntax-entry ?[ "(]")
3969;; eval: (modify-syntax-entry ?] ")[")
3970;; eval: (modify-syntax-entry ?{ "(}")
3971;; eval: (modify-syntax-entry ?} "){")
3972;; eval: (setq indent-tabs-mode t)
3973;; End: