]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arc/arc.md
host-hpux.c: Change copyright header to refer to version 3 of the GNU General Public...
[thirdparty/gcc.git] / gcc / config / arc / arc.md
CommitLineData
e9a25f70 1;; Machine description of the Argonaut ARC cpu for GNU C compiler
2f83c7d6 2;; Copyright (C) 1994, 1997, 1998, 1999, 2000, 2004, 2005, 2007
1c563bed 3;; Free Software Foundation, Inc.
5680076c 4
7ec022b2 5;; This file is part of GCC.
5680076c 6
7ec022b2 7;; GCC is free software; you can redistribute it and/or modify
5680076c 8;; it under the terms of the GNU General Public License as published by
2f83c7d6 9;; the Free Software Foundation; either version 3, or (at your option)
5680076c
JL
10;; any later version.
11
7ec022b2 12;; GCC is distributed in the hope that it will be useful,
5680076c
JL
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
2f83c7d6
NC
18;; along with GCC; see the file COPYING3. If not see
19;; <http://www.gnu.org/licenses/>.
5680076c
JL
20
21;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
22
23;; ??? This is an old port, and is undoubtedly suffering from bit rot.
24\f
25;; Insn type. Used to default other attribute values.
26
27(define_attr "type"
28 "move,load,store,cmove,unary,binary,compare,shift,mul,uncond_branch,branch,call,call_no_delay_slot,multi,misc"
29 (const_string "binary"))
30
31;; Length (in # of insns, long immediate constants counted too).
32;; ??? There's a nasty interaction between the conditional execution fsm
33;; and insn lengths: insns with shimm values cannot be conditionally executed.
34(define_attr "length" ""
35 (cond [(eq_attr "type" "load")
36 (if_then_else (match_operand 1 "long_immediate_loadstore_operand" "")
37 (const_int 2) (const_int 1))
38
39 (eq_attr "type" "store")
40 (if_then_else (match_operand 0 "long_immediate_loadstore_operand" "")
41 (const_int 2) (const_int 1))
42
43 (eq_attr "type" "move,unary,compare")
44 (if_then_else (match_operand 1 "long_immediate_operand" "")
45 (const_int 2) (const_int 1))
46
47 (eq_attr "type" "binary,mul")
48 (if_then_else (match_operand 2 "long_immediate_operand" "")
49 (const_int 2) (const_int 1))
50
51 (eq_attr "type" "cmove")
52 (if_then_else (match_operand 2 "register_operand" "")
53 (const_int 1) (const_int 2))
54
55 (eq_attr "type" "multi") (const_int 2)
56 ]
57
58 (const_int 1)))
59
60;; The length here is the length of a single asm. Unfortunately it might be
61;; 1 or 2 so we must allow for 2. That's ok though. How often will users
62;; lament asm's not being put in delay slots?
63(define_asm_attributes
64 [(set_attr "length" "2")
65 (set_attr "type" "multi")])
66
67;; Condition codes: this one is used by final_prescan_insn to speed up
68;; conditionalizing instructions. It saves having to scan the rtl to see if
69;; it uses or alters the condition codes.
70
112cdef5 71;; USE: This insn uses the condition codes (e.g.: a conditional branch).
5680076c
JL
72;; CANUSE: This insn can use the condition codes (for conditional execution).
73;; SET: All condition codes are set by this insn.
74;; SET_ZN: the Z and N flags are set by this insn.
75;; SET_ZNC: the Z, N, and C flags are set by this insn.
76;; CLOB: The condition codes are set to unknown values by this insn.
77;; NOCOND: This insn can't use and doesn't affect the condition codes.
78
79(define_attr "cond" "use,canuse,set,set_zn,set_znc,clob,nocond"
80 (cond [(and (eq_attr "type" "unary,binary,move")
81 (eq_attr "length" "1"))
82 (const_string "canuse")
83
84 (eq_attr "type" "compare")
85 (const_string "set")
86
87 (eq_attr "type" "cmove,branch")
88 (const_string "use")
89
90 (eq_attr "type" "multi,misc")
91 (const_string "clob")
92 ]
93
94 (const_string "nocond")))
95\f
96;; Delay slots.
97
98(define_attr "in_delay_slot" "false,true"
99 (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi")
100 (const_string "false")
101 ]
102
103 (if_then_else (eq_attr "length" "1")
104 (const_string "true")
105 (const_string "false"))))
106
107(define_delay (eq_attr "type" "call")
108 [(eq_attr "in_delay_slot" "true")
109 (eq_attr "in_delay_slot" "true")
110 (eq_attr "in_delay_slot" "true")])
111
112(define_delay (eq_attr "type" "branch,uncond_branch")
113 [(eq_attr "in_delay_slot" "true")
114 (eq_attr "in_delay_slot" "true")
115 (eq_attr "in_delay_slot" "true")])
116\f
a59f1942 117;; Scheduling description for the ARC
5680076c 118
a59f1942
PB
119(define_cpu_unit "branch")
120
121(define_insn_reservation "any_insn" 1 (eq_attr "type" "!load,compare,branch")
122 "nothing")
5680076c
JL
123
124;; 1) A conditional jump cannot immediately follow the insn setting the flags.
125;; This isn't a complete solution as it doesn't come with guarantees. That
126;; is done in the branch patterns and in arc_print_operand. This exists to
127;; avoid inserting a nop when we can.
a59f1942
PB
128
129(define_insn_reservation "compare" 1 (eq_attr "type" "compare")
130 "nothing,branch")
131
132(define_insn_reservation "branch" 1 (eq_attr "type" "branch")
133 "branch")
5680076c
JL
134
135;; 2) References to loaded registers should wait a cycle.
136
137;; Memory with load-delay of 1 (i.e., 2 cycle load).
5680076c 138
a59f1942
PB
139(define_insn_reservation "memory" 2 (eq_attr "type" "load")
140 "nothing")
5680076c
JL
141\f
142;; Move instructions.
143
144(define_expand "movqi"
145 [(set (match_operand:QI 0 "general_operand" "")
146 (match_operand:QI 1 "general_operand" ""))]
147 ""
148 "
149{
150 /* Everything except mem = const or mem = mem can be done easily. */
151
152 if (GET_CODE (operands[0]) == MEM)
153 operands[1] = force_reg (QImode, operands[1]);
154}")
155
156(define_insn "*movqi_insn"
157 [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,m")
158 (match_operand:QI 1 "move_src_operand" "rI,Ji,m,r"))]
159;; ??? Needed?
160 "register_operand (operands[0], QImode)
161 || register_operand (operands[1], QImode)"
162 "@
163 mov%? %0,%1
164 mov%? %0,%1
165 ldb%U1%V1 %0,%1
166 stb%U0%V0 %1,%0"
167 [(set_attr "type" "move,move,load,store")])
168
169;; ??? This may never match since there's no cmpqi insn.
170
171(define_insn "*movqi_set_cc_insn"
172 [(set (reg:CCZN 61) (compare:CCZN
173 (sign_extend:SI (match_operand:QI 1 "move_src_operand" "rIJi"))
174 (const_int 0)))
175 (set (match_operand:QI 0 "move_dest_operand" "=r")
176 (match_dup 1))]
177 ""
178 "mov%?.f %0,%1"
179 [(set_attr "type" "move")
180 (set_attr "cond" "set_zn")])
181
182(define_expand "movhi"
183 [(set (match_operand:HI 0 "general_operand" "")
184 (match_operand:HI 1 "general_operand" ""))]
185 ""
186 "
187{
188 /* Everything except mem = const or mem = mem can be done easily. */
189
190 if (GET_CODE (operands[0]) == MEM)
191 operands[1] = force_reg (HImode, operands[1]);
192}")
193
194(define_insn "*movhi_insn"
195 [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,m")
196 (match_operand:HI 1 "move_src_operand" "rI,Ji,m,r"))]
197 "register_operand (operands[0], HImode)
198 || register_operand (operands[1], HImode)"
199 "@
200 mov%? %0,%1
201 mov%? %0,%1
202 ldw%U1%V1 %0,%1
203 stw%U0%V0 %1,%0"
204 [(set_attr "type" "move,move,load,store")])
205
206;; ??? Will this ever match?
207
208(define_insn "*movhi_set_cc_insn"
209 [(set (reg:CCZN 61) (compare:CCZN
210 (sign_extend:SI (match_operand:HI 1 "move_src_operand" "rIJi"))
211 (const_int 0)))
212 (set (match_operand:HI 0 "move_dest_operand" "=r")
213 (match_dup 1))]
214;; ??? Needed?
215 "register_operand (operands[0], HImode)
216 || register_operand (operands[1], HImode)"
217 "mov%?.f %0,%1"
218 [(set_attr "type" "move")
219 (set_attr "cond" "set_zn")])
220
221(define_expand "movsi"
222 [(set (match_operand:SI 0 "general_operand" "")
223 (match_operand:SI 1 "general_operand" ""))]
224 ""
225 "
226{
227 /* Everything except mem = const or mem = mem can be done easily. */
228
229 if (GET_CODE (operands[0]) == MEM)
230 operands[1] = force_reg (SImode, operands[1]);
231}")
232
233(define_insn "*movsi_insn"
234 [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,m")
235 (match_operand:SI 1 "move_src_operand" "rI,GJi,m,r"))]
236 "register_operand (operands[0], SImode)
237 || register_operand (operands[1], SImode)"
238 "@
239 mov%? %0,%1
240 mov%? %0,%S1
241 ld%U1%V1 %0,%1
242 st%U0%V0 %1,%0"
243 [(set_attr "type" "move,move,load,store")])
244
245(define_insn "*movsi_set_cc_insn"
246 [(set (reg:CCZN 61) (compare:CCZN
247 (match_operand:SI 1 "move_src_operand" "rIJi")
248 (const_int 0)))
249 (set (match_operand:SI 0 "move_dest_operand" "=r")
250 (match_dup 1))]
251 "register_operand (operands[0], SImode)
252 || register_operand (operands[1], SImode)"
253 "mov%?.f %0,%S1"
254 [(set_attr "type" "move")
255 (set_attr "cond" "set_zn")])
256
257(define_expand "movdi"
258 [(set (match_operand:DI 0 "general_operand" "")
259 (match_operand:DI 1 "general_operand" ""))]
260 ""
261 "
262{
263 /* Everything except mem = const or mem = mem can be done easily. */
264
265 if (GET_CODE (operands[0]) == MEM)
266 operands[1] = force_reg (DImode, operands[1]);
267}")
268
269(define_insn "*movdi_insn"
270 [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m")
271 (match_operand:DI 1 "move_double_src_operand" "r,HK,m,r"))]
272 "register_operand (operands[0], DImode)
273 || register_operand (operands[1], DImode)"
274 "*
275{
276 switch (which_alternative)
277 {
278 case 0 :
279 /* We normally copy the low-numbered register first. However, if
280 the first register operand 0 is the same as the second register of
281 operand 1, we must copy in the opposite order. */
282 if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
283 return \"mov %R0,%R1\;mov %0,%1\";
284 else
285 return \"mov %0,%1\;mov %R0,%R1\";
286 case 1 :
287 return \"mov %0,%L1\;mov %R0,%H1\";
288 case 2 :
289 /* If the low-address word is used in the address, we must load it
290 last. Otherwise, load it first. Note that we cannot have
291 auto-increment in that case since the address register is known to be
292 dead. */
293 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
294 operands [1], 0))
295 return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
296 else
297 return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
298 case 3 :
299 return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
2b046bda 300 default:
5e16a15b 301 gcc_unreachable ();
5680076c
JL
302 }
303}"
304 [(set_attr "type" "move,move,load,store")
305 ;; ??? The ld/st values could be 4 if it's [reg,bignum].
306 (set_attr "length" "2,4,2,2")])
307
308;(define_expand "movdi"
309; [(set (match_operand:DI 0 "general_operand" "")
310; (match_operand:DI 1 "general_operand" ""))]
311; ""
312; "
313;{
314; /* Flow doesn't understand that this is effectively a DFmode move.
315; It doesn't know that all of `operands[0]' is set. */
c5c76735 316; emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[0]));
5680076c
JL
317;
318; /* Emit insns that movsi_insn can handle. */
319; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DImode),
320; operand_subword (operands[1], 0, 0, DImode)));
321; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DImode),
322; operand_subword (operands[1], 1, 0, DImode)));
323; DONE;
324;}")
325\f
326;; Floating point move insns.
327
328(define_expand "movsf"
329 [(set (match_operand:SF 0 "general_operand" "")
330 (match_operand:SF 1 "general_operand" ""))]
331 ""
332 "
333{
334 /* Everything except mem = const or mem = mem can be done easily. */
5680076c
JL
335 if (GET_CODE (operands[0]) == MEM)
336 operands[1] = force_reg (SFmode, operands[1]);
337}")
338
339(define_insn "*movsf_insn"
340 [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m")
341 (match_operand:SF 1 "move_src_operand" "r,E,m,r"))]
342 "register_operand (operands[0], SFmode)
343 || register_operand (operands[1], SFmode)"
344 "@
345 mov%? %0,%1
346 mov%? %0,%1 ; %A1
347 ld%U1%V1 %0,%1
348 st%U0%V0 %1,%0"
349 [(set_attr "type" "move,move,load,store")])
350
351(define_expand "movdf"
352 [(set (match_operand:DF 0 "general_operand" "")
353 (match_operand:DF 1 "general_operand" ""))]
354 ""
355 "
356{
357 /* Everything except mem = const or mem = mem can be done easily. */
5680076c
JL
358 if (GET_CODE (operands[0]) == MEM)
359 operands[1] = force_reg (DFmode, operands[1]);
360}")
361
362(define_insn "*movdf_insn"
363 [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m")
364 (match_operand:DF 1 "move_double_src_operand" "r,E,m,r"))]
365 "register_operand (operands[0], DFmode)
366 || register_operand (operands[1], DFmode)"
367 "*
368{
369 switch (which_alternative)
370 {
371 case 0 :
372 /* We normally copy the low-numbered register first. However, if
373 the first register operand 0 is the same as the second register of
374 operand 1, we must copy in the opposite order. */
375 if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
376 return \"mov %R0,%R1\;mov %0,%1\";
377 else
378 return \"mov %0,%1\;mov %R0,%R1\";
379 case 1 :
380 return \"mov %0,%L1\;mov %R0,%H1 ; %A1\";
381 case 2 :
382 /* If the low-address word is used in the address, we must load it
383 last. Otherwise, load it first. Note that we cannot have
384 auto-increment in that case since the address register is known to be
385 dead. */
386 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
387 operands [1], 0))
388 return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
389 else
390 return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
391 case 3 :
392 return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
2b046bda 393 default:
5e16a15b 394 gcc_unreachable ();
5680076c
JL
395 }
396}"
397 [(set_attr "type" "move,move,load,store")
398 ;; ??? The ld/st values could be 4 if it's [reg,bignum].
399 (set_attr "length" "2,4,2,2")])
400
401;(define_expand "movdf"
402; [(set (match_operand:DF 0 "general_operand" "")
403; (match_operand:DF 1 "general_operand" ""))]
404; ""
405; "
406;{
407; /* Flow doesn't understand that this is effectively a DFmode move.
408; It doesn't know that all of `operands[0]' is set. */
c5c76735 409; emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[0]));
5680076c
JL
410;
411; /* Emit insns that movsi_insn can handle. */
412; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DFmode),
413; operand_subword (operands[1], 0, 0, DFmode)));
414; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DFmode),
415; operand_subword (operands[1], 1, 0, DFmode)));
416; DONE;
417;}")
418\f
419;; Load/Store with update instructions.
420;;
421;; Some of these we can get by using pre-decrement or pre-increment, but the
422;; hardware can also do cases where the increment is not the size of the
423;; object.
424;;
425;; In all these cases, we use operands 0 and 1 for the register being
426;; incremented because those are the operands that local-alloc will
427;; tie and these are the pair most likely to be tieable (and the ones
428;; that will benefit the most).
429;;
430;; We use match_operator here because we need to know whether the memory
431;; object is volatile or not.
432
433(define_insn "*loadqi_update"
434 [(set (match_operand:QI 3 "register_operand" "=r,r")
435 (match_operator:QI 4 "load_update_operand"
436 [(match_operand:SI 1 "register_operand" "0,0")
437 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
438 (set (match_operand:SI 0 "register_operand" "=r,r")
439 (plus:SI (match_dup 1) (match_dup 2)))]
440 ""
441 "ldb.a%V4 %3,[%0,%2]"
442 [(set_attr "type" "load,load")
443 (set_attr "length" "1,2")])
444
445(define_insn "*load_zeroextendqisi_update"
446 [(set (match_operand:SI 3 "register_operand" "=r,r")
447 (zero_extend:SI (match_operator:QI 4 "load_update_operand"
448 [(match_operand:SI 1 "register_operand" "0,0")
449 (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
450 (set (match_operand:SI 0 "register_operand" "=r,r")
451 (plus:SI (match_dup 1) (match_dup 2)))]
452 ""
453 "ldb.a%V4 %3,[%0,%2]"
454 [(set_attr "type" "load,load")
455 (set_attr "length" "1,2")])
456
457(define_insn "*load_signextendqisi_update"
458 [(set (match_operand:SI 3 "register_operand" "=r,r")
459 (sign_extend:SI (match_operator:QI 4 "load_update_operand"
460 [(match_operand:SI 1 "register_operand" "0,0")
461 (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
462 (set (match_operand:SI 0 "register_operand" "=r,r")
463 (plus:SI (match_dup 1) (match_dup 2)))]
464 ""
465 "ldb.x.a%V4 %3,[%0,%2]"
466 [(set_attr "type" "load,load")
467 (set_attr "length" "1,2")])
468
469(define_insn "*storeqi_update"
470 [(set (match_operator:QI 4 "store_update_operand"
471 [(match_operand:SI 1 "register_operand" "0")
472 (match_operand:SI 2 "short_immediate_operand" "I")])
473 (match_operand:QI 3 "register_operand" "r"))
474 (set (match_operand:SI 0 "register_operand" "=r")
475 (plus:SI (match_dup 1) (match_dup 2)))]
476 ""
477 "stb.a%V4 %3,[%0,%2]"
478 [(set_attr "type" "store")
479 (set_attr "length" "1")])
480
481(define_insn "*loadhi_update"
482 [(set (match_operand:HI 3 "register_operand" "=r,r")
483 (match_operator:HI 4 "load_update_operand"
484 [(match_operand:SI 1 "register_operand" "0,0")
485 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
486 (set (match_operand:SI 0 "register_operand" "=r,r")
487 (plus:SI (match_dup 1) (match_dup 2)))]
488 ""
489 "ldw.a%V4 %3,[%0,%2]"
490 [(set_attr "type" "load,load")
491 (set_attr "length" "1,2")])
492
493(define_insn "*load_zeroextendhisi_update"
494 [(set (match_operand:SI 3 "register_operand" "=r,r")
495 (zero_extend:SI (match_operator:HI 4 "load_update_operand"
496 [(match_operand:SI 1 "register_operand" "0,0")
497 (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
498 (set (match_operand:SI 0 "register_operand" "=r,r")
499 (plus:SI (match_dup 1) (match_dup 2)))]
500 ""
501 "ldw.a%V4 %3,[%0,%2]"
502 [(set_attr "type" "load,load")
503 (set_attr "length" "1,2")])
504
505(define_insn "*load_signextendhisi_update"
506 [(set (match_operand:SI 3 "register_operand" "=r,r")
507 (sign_extend:SI (match_operator:HI 4 "load_update_operand"
508 [(match_operand:SI 1 "register_operand" "0,0")
509 (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
510 (set (match_operand:SI 0 "register_operand" "=r,r")
511 (plus:SI (match_dup 1) (match_dup 2)))]
512 ""
513 "ldw.x.a%V4 %3,[%0,%2]"
514 [(set_attr "type" "load,load")
515 (set_attr "length" "1,2")])
516
517(define_insn "*storehi_update"
518 [(set (match_operator:HI 4 "store_update_operand"
519 [(match_operand:SI 1 "register_operand" "0")
520 (match_operand:SI 2 "short_immediate_operand" "I")])
521 (match_operand:HI 3 "register_operand" "r"))
522 (set (match_operand:SI 0 "register_operand" "=r")
523 (plus:SI (match_dup 1) (match_dup 2)))]
524 ""
525 "stw.a%V4 %3,[%0,%2]"
526 [(set_attr "type" "store")
527 (set_attr "length" "1")])
528
529(define_insn "*loadsi_update"
530 [(set (match_operand:SI 3 "register_operand" "=r,r")
531 (match_operator:SI 4 "load_update_operand"
532 [(match_operand:SI 1 "register_operand" "0,0")
533 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
534 (set (match_operand:SI 0 "register_operand" "=r,r")
535 (plus:SI (match_dup 1) (match_dup 2)))]
536 ""
537 "ld.a%V4 %3,[%0,%2]"
538 [(set_attr "type" "load,load")
539 (set_attr "length" "1,2")])
540
541(define_insn "*storesi_update"
542 [(set (match_operator:SI 4 "store_update_operand"
543 [(match_operand:SI 1 "register_operand" "0")
544 (match_operand:SI 2 "short_immediate_operand" "I")])
545 (match_operand:SI 3 "register_operand" "r"))
546 (set (match_operand:SI 0 "register_operand" "=r")
547 (plus:SI (match_dup 1) (match_dup 2)))]
548 ""
549 "st.a%V4 %3,[%0,%2]"
550 [(set_attr "type" "store")
551 (set_attr "length" "1")])
552
553(define_insn "*loadsf_update"
554 [(set (match_operand:SF 3 "register_operand" "=r,r")
555 (match_operator:SF 4 "load_update_operand"
556 [(match_operand:SI 1 "register_operand" "0,0")
557 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
558 (set (match_operand:SI 0 "register_operand" "=r,r")
559 (plus:SI (match_dup 1) (match_dup 2)))]
560 ""
561 "ld.a%V4 %3,[%0,%2]"
562 [(set_attr "type" "load,load")
563 (set_attr "length" "1,2")])
564
565(define_insn "*storesf_update"
566 [(set (match_operator:SF 4 "store_update_operand"
567 [(match_operand:SI 1 "register_operand" "0")
568 (match_operand:SI 2 "short_immediate_operand" "I")])
569 (match_operand:SF 3 "register_operand" "r"))
570 (set (match_operand:SI 0 "register_operand" "=r")
571 (plus:SI (match_dup 1) (match_dup 2)))]
572 ""
573 "st.a%V4 %3,[%0,%2]"
574 [(set_attr "type" "store")
575 (set_attr "length" "1")])
576\f
577;; Conditional move instructions.
578
579(define_expand "movsicc"
580 [(set (match_operand:SI 0 "register_operand" "")
71a83373
JJ
581 (if_then_else:SI (match_operand 1 "comparison_operator" "")
582 (match_operand:SI 2 "nonmemory_operand" "")
583 (match_operand:SI 3 "register_operand" "")))]
5680076c
JL
584 ""
585 "
586{
587 enum rtx_code code = GET_CODE (operands[1]);
c5c76735
JL
588 rtx ccreg
589 = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
590 61);
5680076c 591
1c563bed 592 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
5680076c
JL
593}")
594
595;(define_expand "movdicc"
596; [(set (match_operand:DI 0 "register_operand" "")
71a83373
JJ
597; (if_then_else:DI (match_operand 1 "comparison_operator" "")
598; (match_operand:DI 2 "nonmemory_operand" "")
599; (match_operand:DI 3 "register_operand" "")))]
5680076c
JL
600; "0 /* ??? this would work better if we had cmpdi */"
601; "
602;{
603; enum rtx_code code = GET_CODE (operands[1]);
c5c76735
JL
604; rtx ccreg
605; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
606; 61);
5680076c 607;
1c563bed 608; operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
9a76ab7e 609;}")
c5c76735 610
71a83373 611(define_expand "movsfcc"
5680076c 612 [(set (match_operand:SF 0 "register_operand" "")
71a83373
JJ
613 (if_then_else:SF (match_operand 1 "comparison_operator" "")
614 (match_operand:SF 2 "nonmemory_operand" "")
615 (match_operand:SF 3 "register_operand" "")))]
5680076c
JL
616 ""
617 "
618{
619 enum rtx_code code = GET_CODE (operands[1]);
c5c76735
JL
620 rtx ccreg
621 = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
622 61);
5680076c 623
1c563bed 624 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
5680076c
JL
625}")
626
627;(define_expand "movdfcc"
628; [(set (match_operand:DF 0 "register_operand" "")
71a83373
JJ
629; (if_then_else:DF (match_operand 1 "comparison_operator" "")
630; (match_operand:DF 2 "nonmemory_operand" "")
631; (match_operand:DF 3 "register_operand" "")))]
5680076c
JL
632; "0 /* ??? can generate less efficient code if constants involved */"
633; "
634;{
c5c76735
JL
635; enum rtx_code code = GET_CODE (operands[1]);
636; rtx ccreg
637; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
638; 61);
5680076c 639;
1c563bed 640; operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
9a76ab7e 641;}")
5680076c
JL
642
643(define_insn "*movsicc_insn"
644 [(set (match_operand:SI 0 "register_operand" "=r")
71a83373
JJ
645 (if_then_else:SI (match_operand 1 "comparison_operator" "")
646 (match_operand:SI 2 "nonmemory_operand" "rJi")
647 (match_operand:SI 3 "register_operand" "0")))]
5680076c
JL
648 ""
649 "mov.%d1 %0,%S2"
650 [(set_attr "type" "cmove")])
651
652; ??? This doesn't properly handle constants.
653;(define_insn "*movdicc_insn"
654; [(set (match_operand:DI 0 "register_operand" "=r,r")
71a83373
JJ
655; (if_then_else:DI (match_operand 1 "comparison_operator" "")
656; (match_operand:DI 2 "nonmemory_operand" "r,Ji")
657; (match_operand:DI 3 "register_operand" "0,0")))]
5680076c
JL
658; "0"
659; "*
660;{
661; switch (which_alternative)
662; {
663; case 0 :
664; /* We normally copy the low-numbered register first. However, if
665; the first register operand 0 is the same as the second register of
666; operand 1, we must copy in the opposite order. */
667; if (REGNO (operands[0]) == REGNO (operands[2]) + 1)
668; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\";
669; else
670; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\";
671; case 1 :
672; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\";
673; }
674;}"
675; [(set_attr "type" "cmove,cmove")
676; (set_attr "length" "2,4")])
677
678(define_insn "*movsfcc_insn"
679 [(set (match_operand:SF 0 "register_operand" "=r,r")
71a83373
JJ
680 (if_then_else:SF (match_operand 1 "comparison_operator" "")
681 (match_operand:SF 2 "nonmemory_operand" "r,E")
682 (match_operand:SF 3 "register_operand" "0,0")))]
5680076c
JL
683 ""
684 "@
685 mov.%d1 %0,%2
686 mov.%d1 %0,%2 ; %A2"
687 [(set_attr "type" "cmove,cmove")])
688
689;(define_insn "*movdfcc_insn"
690; [(set (match_operand:DF 0 "register_operand" "=r,r")
71a83373
JJ
691; (if_then_else:DF (match_operand 1 "comparison_operator" "")
692; (match_operand:DF 2 "nonmemory_operand" "r,E")
693; (match_operand:DF 3 "register_operand" "0,0")))]
5680076c
JL
694; "0"
695; "*
696;{
697; switch (which_alternative)
698; {
699; case 0 :
700; /* We normally copy the low-numbered register first. However, if
701; the first register operand 0 is the same as the second register of
702; operand 1, we must copy in the opposite order. */
703; if (REGNO (operands[0]) == REGNO (operands[2]) + 1)
704; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\";
705; else
706; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\";
707; case 1 :
708; return \"mov.%d1 %0,%L2\;mov.%d1 %R0,%H2 ; %A2\";
709; }
710;}"
711; [(set_attr "type" "cmove,cmove")
712; (set_attr "length" "2,4")])
713\f
714;; Zero extension instructions.
715;; ??? We don't support volatile memrefs here, but I'm not sure why.
716
717(define_insn "zero_extendqihi2"
718 [(set (match_operand:HI 0 "register_operand" "=r,r")
719 (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
720 ""
721 "@
722 extb%? %0,%1
723 ldb%U1 %0,%1"
724 [(set_attr "type" "unary,load")])
725
726(define_insn "*zero_extendqihi2_set_cc_insn"
727 [(set (reg:CCZN 61) (compare:CCZN
728 (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
729 (const_int 0)))
730 (set (match_operand:HI 0 "register_operand" "=r")
731 (zero_extend:HI (match_dup 1)))]
732 ""
733 "extb%?.f %0,%1"
734 [(set_attr "type" "unary")
735 (set_attr "cond" "set_zn")])
736
737(define_insn "zero_extendqisi2"
738 [(set (match_operand:SI 0 "register_operand" "=r,r")
739 (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
740 ""
741 "@
742 extb%? %0,%1
743 ldb%U1 %0,%1"
744 [(set_attr "type" "unary,load")])
745
746(define_insn "*zero_extendqisi2_set_cc_insn"
747 [(set (reg:CCZN 61) (compare:CCZN
748 (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
749 (const_int 0)))
750 (set (match_operand:SI 0 "register_operand" "=r")
751 (zero_extend:SI (match_dup 1)))]
752 ""
753 "extb%?.f %0,%1"
754 [(set_attr "type" "unary")
755 (set_attr "cond" "set_zn")])
756
757(define_insn "zero_extendhisi2"
758 [(set (match_operand:SI 0 "register_operand" "=r,r")
759 (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
760 ""
761 "@
762 extw%? %0,%1
763 ldw%U1 %0,%1"
764 [(set_attr "type" "unary,load")])
765
766(define_insn "*zero_extendhisi2_set_cc_insn"
767 [(set (reg:CCZN 61) (compare:CCZN
768 (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
769 (const_int 0)))
770 (set (match_operand:SI 0 "register_operand" "=r")
771 (zero_extend:SI (match_dup 1)))]
772 ""
773 "extw%?.f %0,%1"
774 [(set_attr "type" "unary")
775 (set_attr "cond" "set_zn")])
776\f
777;; Sign extension instructions.
778
779(define_insn "extendqihi2"
780 [(set (match_operand:HI 0 "register_operand" "=r,r")
781 (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
782 ""
783 "@
784 sexb%? %0,%1
785 ldb.x%U1 %0,%1"
786 [(set_attr "type" "unary,load")])
787
788(define_insn "*extendqihi2_set_cc_insn"
789 [(set (reg:CCZN 61) (compare:CCZN
790 (sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
791 (const_int 0)))
792 (set (match_operand:HI 0 "register_operand" "=r")
793 (sign_extend:HI (match_dup 1)))]
794 ""
795 "sexb%?.f %0,%1"
796 [(set_attr "type" "unary")
797 (set_attr "cond" "set_zn")])
798
799(define_insn "extendqisi2"
800 [(set (match_operand:SI 0 "register_operand" "=r,r")
801 (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
802 ""
803 "@
804 sexb%? %0,%1
805 ldb.x%U1 %0,%1"
806 [(set_attr "type" "unary,load")])
807
808(define_insn "*extendqisi2_set_cc_insn"
809 [(set (reg:CCZN 61) (compare:CCZN
810 (sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
811 (const_int 0)))
812 (set (match_operand:SI 0 "register_operand" "=r")
813 (sign_extend:SI (match_dup 1)))]
814 ""
815 "sexb%?.f %0,%1"
816 [(set_attr "type" "unary")
817 (set_attr "cond" "set_zn")])
818
819(define_insn "extendhisi2"
820 [(set (match_operand:SI 0 "register_operand" "=r,r")
821 (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
822 ""
823 "@
824 sexw%? %0,%1
825 ldw.x%U1 %0,%1"
826 [(set_attr "type" "unary,load")])
827
828(define_insn "*extendhisi2_set_cc_insn"
829 [(set (reg:CCZN 61) (compare:CCZN
830 (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
831 (const_int 0)))
832 (set (match_operand:SI 0 "register_operand" "=r")
833 (sign_extend:SI (match_dup 1)))]
834 ""
835 "sexw%?.f %0,%1"
836 [(set_attr "type" "unary")
837 (set_attr "cond" "set_zn")])
838\f
839;; Arithmetic instructions.
840
841(define_insn "addsi3"
842 [(set (match_operand:SI 0 "register_operand" "=r")
843 (plus:SI (match_operand:SI 1 "register_operand" "%r")
844 (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
845 ""
846 "add%? %0,%1,%2")
847
848(define_insn "*addsi3_set_cc_insn"
849 [(set (reg:CC 61) (compare:CC
850 (plus:SI (match_operand:SI 1 "register_operand" "%r")
851 (match_operand:SI 2 "nonmemory_operand" "rIJ"))
852 (const_int 0)))
853 (set (match_operand:SI 0 "register_operand" "=r")
854 (plus:SI (match_dup 1)
855 (match_dup 2)))]
856 ""
857 "add%?.f %0,%1,%2"
858 [(set_attr "cond" "set")])
859
860(define_insn "adddi3"
861 [(set (match_operand:DI 0 "register_operand" "=r")
862 (plus:DI (match_operand:DI 1 "nonmemory_operand" "%r")
863 (match_operand:DI 2 "nonmemory_operand" "ri")))
864 (clobber (reg:CC 61))]
865 ""
866 "*
867{
868 rtx op2 = operands[2];
869
870 if (GET_CODE (op2) == CONST_INT)
871 {
872 int sign = INTVAL (op2);
873 if (sign < 0)
874 return \"add.f %L0,%L1,%2\;adc %H0,%H1,-1\";
875 else
876 return \"add.f %L0,%L1,%2\;adc %H0,%H1,0\";
877 }
878 else
879 return \"add.f %L0,%L1,%L2\;adc %H0,%H1,%H2\";
880}"
881 [(set_attr "length" "2")])
882
883(define_insn "subsi3"
884 [(set (match_operand:SI 0 "register_operand" "=r")
885 (minus:SI (match_operand:SI 1 "register_operand" "r")
886 (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
887 ""
888 "sub%? %0,%1,%2")
889
890(define_insn "*subsi3_set_cc_insn"
891 [(set (reg:CC 61) (compare:CC
892 (minus:SI (match_operand:SI 1 "register_operand" "%r")
893 (match_operand:SI 2 "nonmemory_operand" "rIJ"))
894 (const_int 0)))
895 (set (match_operand:SI 0 "register_operand" "=r")
896 (minus:SI (match_dup 1)
897 (match_dup 2)))]
898 ""
899 "sub%?.f %0,%1,%2"
900 [(set_attr "cond" "set")])
901
902(define_insn "subdi3"
903 [(set (match_operand:DI 0 "register_operand" "=r")
904 (minus:DI (match_operand:DI 1 "nonmemory_operand" "r")
905 (match_operand:DI 2 "nonmemory_operand" "ri")))
906 (clobber (reg:CC 61))]
907 ""
908 "*
909{
910 rtx op2 = operands[2];
911
912 if (GET_CODE (op2) == CONST_INT)
913 {
914 int sign = INTVAL (op2);
915 if (sign < 0)
916 return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,-1\";
917 else
918 return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\";
919 }
920 else
921 return \"sub.f %L0,%L1,%L2\;sbc %H0,%H1,%H2\";
922}"
923 [(set_attr "length" "2")])
924\f
925;; Boolean instructions.
926;;
927;; We don't define the DImode versions as expand_binop does a good enough job.
928
929(define_insn "andsi3"
930 [(set (match_operand:SI 0 "register_operand" "=r")
931 (and:SI (match_operand:SI 1 "register_operand" "%r")
932 (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
933 ""
934 "and%? %0,%1,%2")
935
936(define_insn "*andsi3_set_cc_insn"
937 [(set (reg:CCZN 61) (compare:CCZN
938 (and:SI (match_operand:SI 1 "register_operand" "%r")
939 (match_operand:SI 2 "nonmemory_operand" "rIJ"))
940 (const_int 0)))
941 (set (match_operand:SI 0 "register_operand" "=r")
942 (and:SI (match_dup 1)
943 (match_dup 2)))]
944 ""
945 "and%?.f %0,%1,%2"
946 [(set_attr "cond" "set_zn")])
947
948(define_insn "*bicsi3_insn"
949 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
950 (and:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
951 (not:SI (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r"))))]
952 ""
953 "bic%? %0,%1,%2"
954 [(set_attr "length" "1,2,1,2")])
955
956(define_insn "*bicsi3_set_cc_insn"
957 [(set (reg:CCZN 61) (compare:CCZN
958 (and:SI (match_operand:SI 1 "register_operand" "%r")
959 (not:SI (match_operand:SI 2 "nonmemory_operand" "rIJ")))
960 (const_int 0)))
961 (set (match_operand:SI 0 "register_operand" "=r")
962 (and:SI (match_dup 1)
963 (not:SI (match_dup 2))))]
964 ""
965 "bic%?.f %0,%1,%2"
966 [(set_attr "cond" "set_zn")])
967
968(define_insn "iorsi3"
969 [(set (match_operand:SI 0 "register_operand" "=r")
970 (ior:SI (match_operand:SI 1 "register_operand" "%r")
971 (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
972 ""
973 "or%? %0,%1,%2")
974
975(define_insn "*iorsi3_set_cc_insn"
976 [(set (reg:CCZN 61) (compare:CCZN
977 (ior:SI (match_operand:SI 1 "register_operand" "%r")
978 (match_operand:SI 2 "nonmemory_operand" "rIJ"))
979 (const_int 0)))
980 (set (match_operand:SI 0 "register_operand" "=r")
981 (ior:SI (match_dup 1)
982 (match_dup 2)))]
983 ""
984 "or%?.f %0,%1,%2"
985 [(set_attr "cond" "set_zn")])
986
987(define_insn "xorsi3"
988 [(set (match_operand:SI 0 "register_operand" "=r")
989 (xor:SI (match_operand:SI 1 "register_operand" "%r")
990 (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
991 ""
992 "xor%? %0,%1,%2")
993
994(define_insn "*xorsi3_set_cc_insn"
995 [(set (reg:CCZN 61) (compare:CCZN
996 (xor:SI (match_operand:SI 1 "register_operand" "%r")
997 (match_operand:SI 2 "nonmemory_operand" "rIJ"))
998 (const_int 0)))
999 (set (match_operand:SI 0 "register_operand" "=r")
1000 (xor:SI (match_dup 1)
1001 (match_dup 2)))]
1002 ""
1003 "xor%?.f %0,%1,%2"
1004 [(set_attr "cond" "set_zn")])
1005
1006(define_insn "negsi2"
1007 [(set (match_operand:SI 0 "register_operand" "=r")
1008 (neg:SI (match_operand:SI 1 "register_operand" "r")))]
1009 ""
1010 "sub%? %0,0,%1"
1011 [(set_attr "type" "unary")])
1012
1013(define_insn "*negsi2_set_cc_insn"
1014 [(set (reg:CC 61) (compare:CC
1015 (neg:SI (match_operand:SI 1 "register_operand" "r"))
1016 (const_int 0)))
1017 (set (match_operand:SI 0 "register_operand" "=r")
1018 (neg:SI (match_dup 1)))]
1019 ""
1020 "sub%?.f %0,0,%1"
1021 [(set_attr "type" "unary")
1022 (set_attr "cond" "set")])
1023
1024(define_insn "negdi2"
1025 [(set (match_operand:DI 0 "register_operand" "=r")
1026 (neg:DI (match_operand:DI 1 "register_operand" "r")))
1027 (clobber (reg:SI 61))]
1028 ""
1029 "sub.f %L0,0,%L1\;sbc %H0,0,%H1"
1030 [(set_attr "type" "unary")
1031 (set_attr "length" "2")])
1032
1033(define_insn "one_cmplsi2"
1034 [(set (match_operand:SI 0 "register_operand" "=r")
1035 (not:SI (match_operand:SI 1 "register_operand" "r")))]
1036 ""
1037 "xor%? %0,%1,-1"
1038 [(set_attr "type" "unary")])
1039
1040(define_insn "*one_cmplsi2_set_cc_insn"
ee5332b8 1041 [(set (reg:CCZN 61) (compare:CCZN
5680076c
JL
1042 (not:SI (match_operand:SI 1 "register_operand" "r"))
1043 (const_int 0)))
1044 (set (match_operand:SI 0 "register_operand" "=r")
1045 (not:SI (match_dup 1)))]
1046 ""
1047 "xor%?.f %0,%1,-1"
1048 [(set_attr "type" "unary")
1049 (set_attr "cond" "set_zn")])
1050\f
1051;; Shift instructions.
1052
1053(define_expand "ashlsi3"
1054 [(set (match_operand:SI 0 "register_operand" "")
1055 (ashift:SI (match_operand:SI 1 "register_operand" "")
1056 (match_operand:SI 2 "nonmemory_operand" "")))]
1057 ""
1058 "
1059{
1060 if (! TARGET_SHIFTER)
1061 {
c5c76735
JL
1062 emit_insn (gen_rtx_PARALLEL
1063 (VOIDmode,
5680076c 1064 gen_rtvec (2,
c5c76735
JL
1065 gen_rtx_SET (VOIDmode, operands[0],
1066 gen_rtx_ASHIFT (SImode, operands[1],
1067 operands[2])),
1068 gen_rtx_CLOBBER (VOIDmode,
1069 gen_rtx_SCRATCH (SImode)))));
5680076c
JL
1070 DONE;
1071 }
1072}")
1073
1074(define_expand "ashrsi3"
1075 [(set (match_operand:SI 0 "register_operand" "")
1076 (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
1077 (match_operand:SI 2 "nonmemory_operand" "")))]
1078 ""
1079 "
1080{
1081 if (! TARGET_SHIFTER)
1082 {
c5c76735
JL
1083 emit_insn (gen_rtx_PARALLEL
1084 (VOIDmode,
5680076c 1085 gen_rtvec (2,
c5c76735
JL
1086 gen_rtx_SET (VOIDmode, operands[0],
1087 gen_rtx_ASHIFTRT (SImode,
1088 operands[1],
1089 operands[2])),
1090 gen_rtx_CLOBBER (VOIDmode,
1091 gen_rtx_SCRATCH (SImode)))));
5680076c
JL
1092 DONE;
1093 }
1094}")
1095
1096(define_expand "lshrsi3"
1097 [(set (match_operand:SI 0 "register_operand" "")
1098 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
1099 (match_operand:SI 2 "nonmemory_operand" "")))]
1100 ""
1101 "
1102{
1103 if (! TARGET_SHIFTER)
1104 {
c5c76735
JL
1105 emit_insn (gen_rtx_PARALLEL
1106 (VOIDmode,
5680076c 1107 gen_rtvec (2,
c5c76735
JL
1108 gen_rtx_SET (VOIDmode, operands[0],
1109 gen_rtx_LSHIFTRT (SImode,
1110 operands[1],
1111 operands[2])),
1112 gen_rtx_CLOBBER (VOIDmode,
1113 gen_rtx_SCRATCH (SImode)))));
5680076c
JL
1114 DONE;
1115 }
1116}")
1117
1118(define_insn "*ashlsi3_insn"
1119 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1120 (ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1121 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1122 "TARGET_SHIFTER"
1123 "asl%? %0,%1,%2"
1124 [(set_attr "type" "shift")
1125 (set_attr "length" "1,2,1,2")])
1126
1127(define_insn "*ashrsi3_insn"
1128 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1129 (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1130 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1131 "TARGET_SHIFTER"
1132 "asr%? %0,%1,%2"
1133 [(set_attr "type" "shift")
1134 (set_attr "length" "1,2,1,2")])
1135
1136(define_insn "*lshrsi3_insn"
1137 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1138 (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1139 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1140 "TARGET_SHIFTER"
1141 "lsr%? %0,%1,%2"
1142 [(set_attr "type" "shift")
1143 (set_attr "length" "1,2,1,2")])
1144
1145(define_insn "*shift_si3"
1146 [(set (match_operand:SI 0 "register_operand" "=r")
1147 (match_operator:SI 3 "shift_operator"
1148 [(match_operand:SI 1 "register_operand" "0")
1149 (match_operand:SI 2 "nonmemory_operand" "rIJ")]))
1150 (clobber (match_scratch:SI 4 "=&r"))]
1151 "! TARGET_SHIFTER"
1152 "* return output_shift (operands);"
1153 [(set_attr "type" "shift")
1154 (set_attr "length" "8")])
1155\f
1156;; Compare instructions.
1157;; This controls RTL generation and register allocation.
1158
1159;; We generate RTL for comparisons and branches by having the cmpxx
1160;; patterns store away the operands. Then, the scc and bcc patterns
1161;; emit RTL for both the compare and the branch.
1162
1163(define_expand "cmpsi"
1164 [(set (reg:CC 61)
1165 (compare:CC (match_operand:SI 0 "register_operand" "")
1166 (match_operand:SI 1 "nonmemory_operand" "")))]
1167 ""
1168 "
1169{
1170 arc_compare_op0 = operands[0];
1171 arc_compare_op1 = operands[1];
1172 DONE;
1173}")
1174
1175;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0.
1176;; This assumes sub.f 0,symbol,0 is a valid insn.
1177;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily
1178;; creating 8 byte insns we duplicate %1 in the destination reg of the insn
1179;; if it's a small constant.
1180
1181(define_insn "*cmpsi_cc_insn"
1182 [(set (reg:CC 61)
1183 (compare:CC (match_operand:SI 0 "register_operand" "r,r,r")
1184 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1185 ""
1186 "@
1187 sub.f 0,%0,%1
1188 sub.f %1,%0,%1
1189 sub.f 0,%0,%1"
1190 [(set_attr "type" "compare,compare,compare")])
1191
1192(define_insn "*cmpsi_cczn_insn"
1193 [(set (reg:CCZN 61)
1194 (compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r")
1195 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1196 ""
1197 "@
1198 sub.f 0,%0,%1
1199 sub.f %1,%0,%1
1200 sub.f 0,%0,%1"
1201 [(set_attr "type" "compare,compare,compare")])
1202
1203(define_insn "*cmpsi_ccznc_insn"
1204 [(set (reg:CCZNC 61)
1205 (compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r")
1206 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1207 ""
1208 "@
1209 sub.f 0,%0,%1
1210 sub.f %1,%0,%1
1211 sub.f 0,%0,%1"
1212 [(set_attr "type" "compare,compare,compare")])
1213
1214;; Next come the scc insns.
1215
1216(define_expand "seq"
1217 [(set (match_operand:SI 0 "register_operand" "=r")
1218 (eq:SI (match_dup 1) (const_int 0)))]
1219 ""
1220 "
1221{
1222 operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1);
1223}")
1224
1225(define_expand "sne"
1226 [(set (match_operand:SI 0 "register_operand" "=r")
1227 (ne:SI (match_dup 1) (const_int 0)))]
1228 ""
1229 "
1230{
1231 operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1);
1232}")
1233
1234(define_expand "sgt"
1235 [(set (match_operand:SI 0 "register_operand" "=r")
1236 (gt:SI (match_dup 1) (const_int 0)))]
1237 ""
1238 "
1239{
1240 operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1);
1241}")
1242
1243(define_expand "sle"
1244 [(set (match_operand:SI 0 "register_operand" "=r")
1245 (le:SI (match_dup 1) (const_int 0)))]
1246 ""
1247 "
1248{
1249 operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1);
1250}")
1251
1252(define_expand "sge"
1253 [(set (match_operand:SI 0 "register_operand" "=r")
1254 (ge:SI (match_dup 1) (const_int 0)))]
1255 ""
1256 "
1257{
1258 operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1);
1259}")
1260
1261(define_expand "slt"
1262 [(set (match_operand:SI 0 "register_operand" "=r")
1263 (lt:SI (match_dup 1) (const_int 0)))]
1264 ""
1265 "
1266{
1267 operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1);
1268}")
1269
1270(define_expand "sgtu"
1271 [(set (match_operand:SI 0 "register_operand" "=r")
1272 (gtu:SI (match_dup 1) (const_int 0)))]
1273 ""
1274 "
1275{
1276 operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1);
1277}")
1278
1279(define_expand "sleu"
1280 [(set (match_operand:SI 0 "register_operand" "=r")
1281 (leu:SI (match_dup 1) (const_int 0)))]
1282 ""
1283 "
1284{
1285 operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1);
1286}")
1287
1288(define_expand "sgeu"
1289 [(set (match_operand:SI 0 "register_operand" "=r")
1290 (geu:SI (match_dup 1) (const_int 0)))]
1291 ""
1292 "
1293{
1294 operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1);
1295}")
1296
1297(define_expand "sltu"
1298 [(set (match_operand:SI 0 "register_operand" "=r")
1299 (ltu:SI (match_dup 1) (const_int 0)))]
1300 ""
1301 "
1302{
1303 operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1);
1304}")
1305
1306(define_insn "*scc_insn"
1307 [(set (match_operand:SI 0 "register_operand" "=r")
1308 (match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))]
1309 ""
1310 "mov %0,1\;sub.%D1 %0,%0,%0"
1311 [(set_attr "type" "unary")
1312 (set_attr "length" "2")])
1313
1314;; ??? Look up negscc insn. See pa.md for example.
1315(define_insn "*neg_scc_insn"
1316 [(set (match_operand:SI 0 "register_operand" "=r")
1317 (neg:SI (match_operator:SI 1 "comparison_operator"
1318 [(reg 61) (const_int 0)])))]
1319 ""
1320 "mov %0,-1\;sub.%D1 %0,%0,%0"
1321 [(set_attr "type" "unary")
1322 (set_attr "length" "2")])
1323
1324(define_insn "*not_scc_insn"
1325 [(set (match_operand:SI 0 "register_operand" "=r")
1326 (not:SI (match_operator:SI 1 "comparison_operator"
1327 [(reg 61) (const_int 0)])))]
1328 ""
1329 "mov %0,1\;sub.%d1 %0,%0,%0"
1330 [(set_attr "type" "unary")
1331 (set_attr "length" "2")])
1332\f
1333;; These control RTL generation for conditional jump insns
1334
1335(define_expand "beq"
1336 [(set (pc)
1337 (if_then_else (eq (match_dup 1) (const_int 0))
1338 (label_ref (match_operand 0 "" ""))
1339 (pc)))]
1340 ""
1341 "
1342{
1343 operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1);
1344}")
1345
1346(define_expand "bne"
1347 [(set (pc)
1348 (if_then_else (ne (match_dup 1) (const_int 0))
1349 (label_ref (match_operand 0 "" ""))
1350 (pc)))]
1351 ""
1352 "
1353{
1354 operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1);
1355}")
1356
1357(define_expand "bgt"
1358 [(set (pc)
1359 (if_then_else (gt (match_dup 1) (const_int 0))
1360 (label_ref (match_operand 0 "" ""))
1361 (pc)))]
1362 ""
1363 "
1364{
1365 operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1);
1366}")
1367
1368(define_expand "ble"
1369 [(set (pc)
1370 (if_then_else (le (match_dup 1) (const_int 0))
1371 (label_ref (match_operand 0 "" ""))
1372 (pc)))]
1373 ""
1374 "
1375{
1376 operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1);
1377}")
1378
1379(define_expand "bge"
1380 [(set (pc)
1381 (if_then_else (ge (match_dup 1) (const_int 0))
1382 (label_ref (match_operand 0 "" ""))
1383 (pc)))]
1384 ""
1385 "
1386{
1387 operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1);
1388}")
1389
1390(define_expand "blt"
1391 [(set (pc)
1392 (if_then_else (lt (match_dup 1) (const_int 0))
1393 (label_ref (match_operand 0 "" ""))
1394 (pc)))]
1395 ""
1396 "
1397{
1398 operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1);
1399}")
1400
1401(define_expand "bgtu"
1402 [(set (pc)
1403 (if_then_else (gtu (match_dup 1) (const_int 0))
1404 (label_ref (match_operand 0 "" ""))
1405 (pc)))]
1406 ""
1407 "
1408{
1409 operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1);
1410}")
1411
1412(define_expand "bleu"
1413 [(set (pc)
1414 (if_then_else (leu (match_dup 1) (const_int 0))
1415 (label_ref (match_operand 0 "" ""))
1416 (pc)))]
1417 ""
1418 "
1419{
1420 operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1);
1421}")
1422
1423(define_expand "bgeu"
1424 [(set (pc)
1425 (if_then_else (geu (match_dup 1) (const_int 0))
1426 (label_ref (match_operand 0 "" ""))
1427 (pc)))]
1428 ""
1429 "
1430{
1431 operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1);
1432}")
1433
1434(define_expand "bltu"
1435 [(set (pc)
1436 (if_then_else (ltu (match_dup 1) (const_int 0))
1437 (label_ref (match_operand 0 "" ""))
1438 (pc)))]
1439 ""
1440 "
1441{
1442 operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1);
1443}")
1444
1445;; Now match both normal and inverted jump.
1446
1447(define_insn "*branch_insn"
1448 [(set (pc)
1449 (if_then_else (match_operator 1 "proper_comparison_operator"
1450 [(reg 61) (const_int 0)])
1451 (label_ref (match_operand 0 "" ""))
1452 (pc)))]
1453 ""
1454 "*
1455{
1456 if (arc_ccfsm_branch_deleted_p ())
1457 {
1458 arc_ccfsm_record_branch_deleted ();
1459 return \"; branch deleted, next insns conditionalized\";
1460 }
1461 else
1462 return \"%~b%d1%# %l0\";
1463}"
1464 [(set_attr "type" "branch")])
1465
1466(define_insn "*rev_branch_insn"
1467 [(set (pc)
1468 (if_then_else (match_operator 1 "proper_comparison_operator"
1469 [(reg 61) (const_int 0)])
1470 (pc)
1471 (label_ref (match_operand 0 "" ""))))]
1472 "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
1473 "*
1474{
1475 if (arc_ccfsm_branch_deleted_p ())
1476 {
1477 arc_ccfsm_record_branch_deleted ();
1478 return \"; branch deleted, next insns conditionalized\";
1479 }
1480 else
1481 return \"%~b%D1%# %l0\";
1482}"
1483 [(set_attr "type" "branch")])
1484\f
1485;; Unconditional and other jump instructions.
1486
1487(define_insn "jump"
1488 [(set (pc) (label_ref (match_operand 0 "" "")))]
1489 ""
1490 "b%* %l0"
1491 [(set_attr "type" "uncond_branch")])
1492
1493(define_insn "indirect_jump"
1494 [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
1495 ""
1496 "j%* %a0"
1497 [(set_attr "type" "uncond_branch")])
1498
1499;; Implement a switch statement.
1500;; This wouldn't be necessary in the non-pic case if we could distinguish
1501;; label refs of the jump table from other label refs. The problem is that
1502;; label refs are output as "%st(.LL42)" but we don't want the %st - we want
1503;; the real address since it's the address of the table.
1504
1505(define_expand "casesi"
1506 [(set (match_dup 5)
1507 (minus:SI (match_operand:SI 0 "register_operand" "")
1508 (match_operand:SI 1 "nonmemory_operand" "")))
1509 (set (reg:CC 61)
1510 (compare:CC (match_dup 5)
1511 (match_operand:SI 2 "nonmemory_operand" "")))
1512 (set (pc)
1513 (if_then_else (gtu (reg:CC 61)
1514 (const_int 0))
1515 (label_ref (match_operand 4 "" ""))
1516 (pc)))
1517 (parallel
1518 [(set (pc)
1519 (mem:SI (plus:SI (mult:SI (match_dup 5)
1520 (const_int 4))
1521 (label_ref (match_operand 3 "" "")))))
1522 (clobber (match_scratch:SI 6 ""))
1523 (clobber (match_scratch:SI 7 ""))])]
1524 ""
1525 "
1526{
1527 operands[5] = gen_reg_rtx (SImode);
1528}")
1529
1530(define_insn "*casesi_insn"
1531 [(set (pc)
1532 (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
1533 (const_int 4))
1534 (label_ref (match_operand 1 "" "")))))
1535 (clobber (match_scratch:SI 2 "=r"))
1536 (clobber (match_scratch:SI 3 "=r"))]
1537 ""
1538 "*
1539{
1540 output_asm_insn (\"mov %2,%1\", operands);
1541 if (TARGET_SHIFTER)
1542 output_asm_insn (\"asl %3,%0,2\", operands);
1543 else
1544 output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands);
1545 output_asm_insn (\"ld %2,[%2,%3]\", operands);
1546 output_asm_insn (\"j.nd %a2\", operands);
1547 return \"\";
1548}"
1549 [(set_attr "type" "uncond_branch")
1550 (set_attr "length" "6")])
1551
1552(define_insn "tablejump"
1553 [(set (pc) (match_operand:SI 0 "address_operand" "p"))
1554 (use (label_ref (match_operand 1 "" "")))]
1555 "0 /* disabled -> using casesi now */"
1556 "j%* %a0"
1557 [(set_attr "type" "uncond_branch")])
1558
1559(define_expand "call"
1560 ;; operands[1] is stack_size_rtx
1561 ;; operands[2] is next_arg_register
1562 [(parallel [(call (match_operand:SI 0 "call_operand" "")
1563 (match_operand 1 "" ""))
1564 (clobber (reg:SI 31))])]
1565 ""
1566 "")
1567
1568(define_insn "*call_via_reg"
1569 [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
1570 (match_operand 1 "" ""))
1571 (clobber (reg:SI 31))]
1572 ""
1573 "lr blink,[status]\;j.d %0\;add blink,blink,2"
1574 [(set_attr "type" "call_no_delay_slot")
1575 (set_attr "length" "3")])
1576
1577(define_insn "*call_via_label"
1578 [(call (mem:SI (match_operand:SI 0 "call_address_operand" ""))
1579 (match_operand 1 "" ""))
1580 (clobber (reg:SI 31))]
1581 ""
1582 ; The %~ is necessary in case this insn gets conditionalized and the previous
1583 ; insn is the cc setter.
1584 "%~bl%!%* %0"
1585 [(set_attr "type" "call")
1586 (set_attr "cond" "canuse")])
1587
1588(define_expand "call_value"
1589 ;; operand 2 is stack_size_rtx
1590 ;; operand 3 is next_arg_register
1591 [(parallel [(set (match_operand 0 "register_operand" "=r")
1592 (call (match_operand:SI 1 "call_operand" "")
1593 (match_operand 2 "" "")))
1594 (clobber (reg:SI 31))])]
1595 ""
1596 "")
1597
1598(define_insn "*call_value_via_reg"
1599 [(set (match_operand 0 "register_operand" "=r")
1600 (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
1601 (match_operand 2 "" "")))
1602 (clobber (reg:SI 31))]
1603 ""
1604 "lr blink,[status]\;j.d %1\;add blink,blink,2"
1605 [(set_attr "type" "call_no_delay_slot")
1606 (set_attr "length" "3")])
1607
1608(define_insn "*call_value_via_label"
1609 [(set (match_operand 0 "register_operand" "=r")
1610 (call (mem:SI (match_operand:SI 1 "call_address_operand" ""))
1611 (match_operand 2 "" "")))
1612 (clobber (reg:SI 31))]
1613 ""
1614 ; The %~ is necessary in case this insn gets conditionalized and the previous
1615 ; insn is the cc setter.
1616 "%~bl%!%* %1"
1617 [(set_attr "type" "call")
1618 (set_attr "cond" "canuse")])
1619\f
1620(define_insn "nop"
1621 [(const_int 0)]
1622 ""
1623 "nop"
1624 [(set_attr "type" "misc")])
1625
1626;; Special pattern to flush the icache.
1627;; ??? Not sure what to do here. Some ARC's are known to support this.
1628
1629(define_insn "flush_icache"
1630 [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)]
1631 ""
1632 "* return \"\";"
1633 [(set_attr "type" "misc")])
1634\f
1635;; Split up troublesome insns for better scheduling.
1636\f
1637;; Peepholes go at the end.