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