xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/arc/arc.md (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1;; Machine description of the Argonaut ARC cpu for GNU C compiler
2;; Copyright (C) 1994, 1997, 1998, 1999, 2000, 2004, 2005, 2007, 2008
3;; Free Software Foundation, Inc.
4
5;; This file is part of GCC.
6
7;; GCC is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 3, or (at your option)
10;; any later version.
11
12;; GCC is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING3.  If not see
19;; <http://www.gnu.org/licenses/>.
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 (e.g.: 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;; Scheduling description for the ARC
118
119(define_cpu_unit "branch")
120
121(define_insn_reservation "any_insn" 1 (eq_attr "type" "!load,compare,branch")
122			 "nothing")
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.
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")
134
135;; 2) References to loaded registers should wait a cycle.
136
137;; Memory with load-delay of 1 (i.e., 2 cycle load).
138
139(define_insn_reservation "memory" 2 (eq_attr "type" "load")
140			 "nothing")
141
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\";
300    default:
301      gcc_unreachable ();
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.  */
316;  emit_clobber (operands[0]);
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
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.  */
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.  */
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\";
393    default:
394      gcc_unreachable ();
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.  */
409;  emit_clobber (operands[0]);
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
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
577;; Conditional move instructions.
578
579(define_expand "movsicc"
580  [(set (match_operand:SI 0 "register_operand" "")
581	(if_then_else:SI (match_operand 1 "comparison_operator" "")
582			 (match_operand:SI 2 "nonmemory_operand" "")
583			 (match_operand:SI 3 "register_operand" "")))]
584  ""
585  "
586{
587  enum rtx_code code = GET_CODE (operands[1]);
588  rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
589				XEXP (operands[1], 1));
590  operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
591}")
592
593(define_expand "movsfcc"
594  [(set (match_operand:SF 0 "register_operand" "")
595	(if_then_else:SF (match_operand 1 "comparison_operator" "")
596			 (match_operand:SF 2 "nonmemory_operand" "")
597			 (match_operand:SF 3 "register_operand" "")))]
598  ""
599  "
600{
601  enum rtx_code code = GET_CODE (operands[1]);
602  rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
603				XEXP (operands[1], 1));
604  operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
605}")
606
607(define_insn "*movsicc_insn"
608  [(set (match_operand:SI 0 "register_operand" "=r")
609	(if_then_else:SI (match_operand 1 "comparison_operator" "")
610			 (match_operand:SI 2 "nonmemory_operand" "rJi")
611			 (match_operand:SI 3 "register_operand" "0")))]
612  ""
613  "mov.%d1 %0,%S2"
614  [(set_attr "type" "cmove")])
615
616(define_insn "*movsfcc_insn"
617  [(set (match_operand:SF 0 "register_operand" "=r,r")
618	(if_then_else:SF (match_operand 1 "comparison_operator" "")
619			 (match_operand:SF 2 "nonmemory_operand" "r,E")
620			 (match_operand:SF 3 "register_operand" "0,0")))]
621  ""
622  "@
623   mov.%d1 %0,%2
624   mov.%d1 %0,%2 ; %A2"
625  [(set_attr "type" "cmove,cmove")])
626
627
628;; Zero extension instructions.
629;; ??? We don't support volatile memrefs here, but I'm not sure why.
630
631(define_insn "zero_extendqihi2"
632  [(set (match_operand:HI 0 "register_operand" "=r,r")
633	(zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
634  ""
635  "@
636   extb%? %0,%1
637   ldb%U1 %0,%1"
638  [(set_attr "type" "unary,load")])
639
640(define_insn "*zero_extendqihi2_set_cc_insn"
641  [(set (reg:CCZN 61) (compare:CCZN
642		       (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
643		       (const_int 0)))
644   (set (match_operand:HI 0 "register_operand" "=r")
645	(zero_extend:HI (match_dup 1)))]
646  ""
647  "extb%?.f %0,%1"
648  [(set_attr "type" "unary")
649   (set_attr "cond" "set_zn")])
650
651(define_insn "zero_extendqisi2"
652  [(set (match_operand:SI 0 "register_operand" "=r,r")
653	(zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
654  ""
655  "@
656   extb%? %0,%1
657   ldb%U1 %0,%1"
658  [(set_attr "type" "unary,load")])
659
660(define_insn "*zero_extendqisi2_set_cc_insn"
661  [(set (reg:CCZN 61) (compare:CCZN
662		       (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
663		       (const_int 0)))
664   (set (match_operand:SI 0 "register_operand" "=r")
665	(zero_extend:SI (match_dup 1)))]
666  ""
667  "extb%?.f %0,%1"
668  [(set_attr "type" "unary")
669   (set_attr "cond" "set_zn")])
670
671(define_insn "zero_extendhisi2"
672  [(set (match_operand:SI 0 "register_operand" "=r,r")
673	(zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
674  ""
675  "@
676   extw%? %0,%1
677   ldw%U1 %0,%1"
678  [(set_attr "type" "unary,load")])
679
680(define_insn "*zero_extendhisi2_set_cc_insn"
681  [(set (reg:CCZN 61) (compare:CCZN
682		       (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
683		       (const_int 0)))
684   (set (match_operand:SI 0 "register_operand" "=r")
685	(zero_extend:SI (match_dup 1)))]
686  ""
687  "extw%?.f %0,%1"
688  [(set_attr "type" "unary")
689   (set_attr "cond" "set_zn")])
690
691;; Sign extension instructions.
692
693(define_insn "extendqihi2"
694  [(set (match_operand:HI 0 "register_operand" "=r,r")
695	(sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
696  ""
697  "@
698   sexb%? %0,%1
699   ldb.x%U1 %0,%1"
700  [(set_attr "type" "unary,load")])
701
702(define_insn "*extendqihi2_set_cc_insn"
703  [(set (reg:CCZN 61) (compare:CCZN
704		       (sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
705		       (const_int 0)))
706   (set (match_operand:HI 0 "register_operand" "=r")
707	(sign_extend:HI (match_dup 1)))]
708  ""
709  "sexb%?.f %0,%1"
710  [(set_attr "type" "unary")
711   (set_attr "cond" "set_zn")])
712
713(define_insn "extendqisi2"
714  [(set (match_operand:SI 0 "register_operand" "=r,r")
715	(sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
716  ""
717  "@
718   sexb%? %0,%1
719   ldb.x%U1 %0,%1"
720  [(set_attr "type" "unary,load")])
721
722(define_insn "*extendqisi2_set_cc_insn"
723  [(set (reg:CCZN 61) (compare:CCZN
724		       (sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
725		       (const_int 0)))
726   (set (match_operand:SI 0 "register_operand" "=r")
727	(sign_extend:SI (match_dup 1)))]
728  ""
729  "sexb%?.f %0,%1"
730  [(set_attr "type" "unary")
731   (set_attr "cond" "set_zn")])
732
733(define_insn "extendhisi2"
734  [(set (match_operand:SI 0 "register_operand" "=r,r")
735	(sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
736  ""
737  "@
738   sexw%? %0,%1
739   ldw.x%U1 %0,%1"
740  [(set_attr "type" "unary,load")])
741
742(define_insn "*extendhisi2_set_cc_insn"
743  [(set (reg:CCZN 61) (compare:CCZN
744		       (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
745		       (const_int 0)))
746   (set (match_operand:SI 0 "register_operand" "=r")
747	(sign_extend:SI (match_dup 1)))]
748  ""
749  "sexw%?.f %0,%1"
750  [(set_attr "type" "unary")
751   (set_attr "cond" "set_zn")])
752
753;; Arithmetic instructions.
754
755(define_insn "addsi3"
756  [(set (match_operand:SI 0 "register_operand" "=r")
757	(plus:SI (match_operand:SI 1 "register_operand" "%r")
758		 (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
759  ""
760  "add%? %0,%1,%2")
761
762(define_insn "*addsi3_set_cc_insn"
763  [(set (reg:CC 61) (compare:CC
764		     (plus:SI (match_operand:SI 1 "register_operand" "%r")
765			      (match_operand:SI 2 "nonmemory_operand" "rIJ"))
766		     (const_int 0)))
767   (set (match_operand:SI 0 "register_operand" "=r")
768	(plus:SI (match_dup 1)
769		 (match_dup 2)))]
770  ""
771  "add%?.f %0,%1,%2"
772  [(set_attr "cond" "set")])
773
774(define_insn "adddi3"
775  [(set (match_operand:DI 0 "register_operand" "=r")
776	(plus:DI (match_operand:DI 1 "nonmemory_operand" "%r")
777		 (match_operand:DI 2 "nonmemory_operand" "ri")))
778   (clobber (reg:CC 61))]
779  ""
780  "*
781{
782  rtx op2 = operands[2];
783
784  if (GET_CODE (op2) == CONST_INT)
785    {
786      int sign = INTVAL (op2);
787      if (sign < 0)
788	return \"add.f %L0,%L1,%2\;adc %H0,%H1,-1\";
789      else
790	return \"add.f %L0,%L1,%2\;adc %H0,%H1,0\";
791    }
792  else
793    return \"add.f %L0,%L1,%L2\;adc %H0,%H1,%H2\";
794}"
795  [(set_attr "length" "2")])
796
797(define_insn "subsi3"
798  [(set (match_operand:SI 0 "register_operand" "=r")
799	(minus:SI (match_operand:SI 1 "register_operand" "r")
800		  (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
801  ""
802  "sub%? %0,%1,%2")
803
804(define_insn "*subsi3_set_cc_insn"
805  [(set (reg:CC 61) (compare:CC
806		     (minus:SI (match_operand:SI 1 "register_operand" "%r")
807			       (match_operand:SI 2 "nonmemory_operand" "rIJ"))
808		     (const_int 0)))
809   (set (match_operand:SI 0 "register_operand" "=r")
810	(minus:SI (match_dup 1)
811		  (match_dup 2)))]
812  ""
813  "sub%?.f %0,%1,%2"
814  [(set_attr "cond" "set")])
815
816(define_insn "subdi3"
817  [(set (match_operand:DI 0 "register_operand" "=r")
818	(minus:DI (match_operand:DI 1 "nonmemory_operand" "r")
819		  (match_operand:DI 2 "nonmemory_operand" "ri")))
820   (clobber (reg:CC 61))]
821  ""
822  "*
823{
824  rtx op2 = operands[2];
825
826  if (GET_CODE (op2) == CONST_INT)
827    {
828      int sign = INTVAL (op2);
829      if (sign < 0)
830	return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,-1\";
831      else
832	return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\";
833    }
834  else
835    return \"sub.f %L0,%L1,%L2\;sbc %H0,%H1,%H2\";
836}"
837  [(set_attr "length" "2")])
838
839;; Boolean instructions.
840;;
841;; We don't define the DImode versions as expand_binop does a good enough job.
842
843(define_insn "andsi3"
844  [(set (match_operand:SI 0 "register_operand" "=r")
845	(and:SI (match_operand:SI 1 "register_operand" "%r")
846		(match_operand:SI 2 "nonmemory_operand" "rIJ")))]
847  ""
848  "and%? %0,%1,%2")
849
850(define_insn "*andsi3_set_cc_insn"
851  [(set (reg:CCZN 61) (compare:CCZN
852		       (and:SI (match_operand:SI 1 "register_operand" "%r")
853			       (match_operand:SI 2 "nonmemory_operand" "rIJ"))
854		       (const_int 0)))
855   (set (match_operand:SI 0 "register_operand" "=r")
856	(and:SI (match_dup 1)
857		(match_dup 2)))]
858  ""
859  "and%?.f %0,%1,%2"
860  [(set_attr "cond" "set_zn")])
861
862(define_insn "*bicsi3_insn"
863  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
864	(and:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
865		(not:SI (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r"))))]
866  ""
867  "bic%? %0,%1,%2"
868  [(set_attr "length" "1,2,1,2")])
869
870(define_insn "*bicsi3_set_cc_insn"
871  [(set (reg:CCZN 61) (compare:CCZN
872		       (and:SI (match_operand:SI 1 "register_operand" "%r")
873			       (not:SI (match_operand:SI 2 "nonmemory_operand" "rIJ")))
874		       (const_int 0)))
875   (set (match_operand:SI 0 "register_operand" "=r")
876	(and:SI (match_dup 1)
877		(not:SI (match_dup 2))))]
878  ""
879  "bic%?.f %0,%1,%2"
880  [(set_attr "cond" "set_zn")])
881
882(define_insn "iorsi3"
883  [(set (match_operand:SI 0 "register_operand" "=r")
884	(ior:SI (match_operand:SI 1 "register_operand" "%r")
885		(match_operand:SI 2 "nonmemory_operand" "rIJ")))]
886  ""
887  "or%? %0,%1,%2")
888
889(define_insn "*iorsi3_set_cc_insn"
890  [(set (reg:CCZN 61) (compare:CCZN
891		       (ior:SI (match_operand:SI 1 "register_operand" "%r")
892			       (match_operand:SI 2 "nonmemory_operand" "rIJ"))
893		       (const_int 0)))
894   (set (match_operand:SI 0 "register_operand" "=r")
895	(ior:SI (match_dup 1)
896		(match_dup 2)))]
897  ""
898  "or%?.f %0,%1,%2"
899  [(set_attr "cond" "set_zn")])
900
901(define_insn "xorsi3"
902  [(set (match_operand:SI 0 "register_operand" "=r")
903	(xor:SI (match_operand:SI 1 "register_operand" "%r")
904		(match_operand:SI 2 "nonmemory_operand" "rIJ")))]
905  ""
906  "xor%? %0,%1,%2")
907
908(define_insn "*xorsi3_set_cc_insn"
909  [(set (reg:CCZN 61) (compare:CCZN
910		       (xor:SI (match_operand:SI 1 "register_operand" "%r")
911			       (match_operand:SI 2 "nonmemory_operand" "rIJ"))
912		       (const_int 0)))
913   (set (match_operand:SI 0 "register_operand" "=r")
914	(xor:SI (match_dup 1)
915		(match_dup 2)))]
916  ""
917  "xor%?.f %0,%1,%2"
918  [(set_attr "cond" "set_zn")])
919
920(define_insn "negsi2"
921  [(set (match_operand:SI 0 "register_operand" "=r")
922	(neg:SI (match_operand:SI 1 "register_operand" "r")))]
923  ""
924  "sub%? %0,0,%1"
925  [(set_attr "type" "unary")])
926
927(define_insn "*negsi2_set_cc_insn"
928  [(set (reg:CC 61) (compare:CC
929		     (neg:SI (match_operand:SI 1 "register_operand" "r"))
930		     (const_int 0)))
931   (set (match_operand:SI 0 "register_operand" "=r")
932	(neg:SI (match_dup 1)))]
933  ""
934  "sub%?.f %0,0,%1"
935  [(set_attr "type" "unary")
936   (set_attr "cond" "set")])
937
938(define_insn "negdi2"
939  [(set (match_operand:DI 0 "register_operand" "=r")
940	(neg:DI (match_operand:DI 1 "register_operand" "r")))
941   (clobber (reg:SI 61))]
942  ""
943  "sub.f %L0,0,%L1\;sbc %H0,0,%H1"
944  [(set_attr "type" "unary")
945   (set_attr "length" "2")])
946
947(define_insn "one_cmplsi2"
948  [(set (match_operand:SI 0 "register_operand" "=r")
949	(not:SI (match_operand:SI 1 "register_operand" "r")))]
950  ""
951  "xor%? %0,%1,-1"
952  [(set_attr "type" "unary")])
953
954(define_insn "*one_cmplsi2_set_cc_insn"
955  [(set (reg:CCZN 61) (compare:CCZN
956		       (not:SI (match_operand:SI 1 "register_operand" "r"))
957		       (const_int 0)))
958   (set (match_operand:SI 0 "register_operand" "=r")
959	(not:SI (match_dup 1)))]
960  ""
961  "xor%?.f %0,%1,-1"
962  [(set_attr "type" "unary")
963   (set_attr "cond" "set_zn")])
964
965;; Shift instructions.
966
967(define_expand "ashlsi3"
968  [(set (match_operand:SI 0 "register_operand" "")
969	(ashift:SI (match_operand:SI 1 "register_operand" "")
970		   (match_operand:SI 2 "nonmemory_operand" "")))]
971  ""
972  "
973{
974  if (! TARGET_SHIFTER)
975    {
976      emit_insn (gen_rtx_PARALLEL
977		 (VOIDmode,
978		  gen_rtvec (2,
979			     gen_rtx_SET (VOIDmode, operands[0],
980					  gen_rtx_ASHIFT (SImode, operands[1],
981							  operands[2])),
982			     gen_rtx_CLOBBER (VOIDmode,
983					      gen_rtx_SCRATCH (SImode)))));
984      DONE;
985    }
986}")
987
988(define_expand "ashrsi3"
989  [(set (match_operand:SI 0 "register_operand" "")
990	(ashiftrt:SI (match_operand:SI 1 "register_operand" "")
991		     (match_operand:SI 2 "nonmemory_operand" "")))]
992  ""
993  "
994{
995  if (! TARGET_SHIFTER)
996    {
997      emit_insn (gen_rtx_PARALLEL
998		 (VOIDmode,
999		  gen_rtvec (2,
1000			     gen_rtx_SET (VOIDmode, operands[0],
1001					  gen_rtx_ASHIFTRT (SImode,
1002							    operands[1],
1003							    operands[2])),
1004			     gen_rtx_CLOBBER (VOIDmode,
1005					      gen_rtx_SCRATCH (SImode)))));
1006      DONE;
1007    }
1008}")
1009
1010(define_expand "lshrsi3"
1011  [(set (match_operand:SI 0 "register_operand" "")
1012	(lshiftrt:SI (match_operand:SI 1 "register_operand" "")
1013		     (match_operand:SI 2 "nonmemory_operand" "")))]
1014  ""
1015  "
1016{
1017  if (! TARGET_SHIFTER)
1018    {
1019      emit_insn (gen_rtx_PARALLEL
1020		 (VOIDmode,
1021		  gen_rtvec (2,
1022			     gen_rtx_SET (VOIDmode, operands[0],
1023					  gen_rtx_LSHIFTRT (SImode,
1024							    operands[1],
1025							    operands[2])),
1026			     gen_rtx_CLOBBER (VOIDmode,
1027					      gen_rtx_SCRATCH (SImode)))));
1028      DONE;
1029    }
1030}")
1031
1032(define_insn "*ashlsi3_insn"
1033  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1034	(ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1035		   (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1036  "TARGET_SHIFTER"
1037  "asl%? %0,%1,%2"
1038  [(set_attr "type" "shift")
1039   (set_attr "length" "1,2,1,2")])
1040
1041(define_insn "*ashrsi3_insn"
1042  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1043	(ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1044		     (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1045  "TARGET_SHIFTER"
1046  "asr%? %0,%1,%2"
1047  [(set_attr "type" "shift")
1048   (set_attr "length" "1,2,1,2")])
1049
1050(define_insn "*lshrsi3_insn"
1051  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1052	(lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1053		     (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1054  "TARGET_SHIFTER"
1055  "lsr%? %0,%1,%2"
1056  [(set_attr "type" "shift")
1057   (set_attr "length" "1,2,1,2")])
1058
1059(define_insn "*shift_si3"
1060  [(set (match_operand:SI 0 "register_operand" "=r")
1061	(match_operator:SI 3 "shift_operator"
1062			   [(match_operand:SI 1 "register_operand" "0")
1063			    (match_operand:SI 2 "nonmemory_operand" "rIJ")]))
1064   (clobber (match_scratch:SI 4 "=&r"))]
1065  "! TARGET_SHIFTER"
1066  "* return output_shift (operands);"
1067  [(set_attr "type" "shift")
1068   (set_attr "length" "8")])
1069
1070;; Compare instructions.
1071;; This controls RTL generation and register allocation.
1072
1073;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0.
1074;; This assumes sub.f 0,symbol,0 is a valid insn.
1075;; Note that "sub.f 0,r0,1" is an 8 byte insn.  To avoid unnecessarily
1076;; creating 8 byte insns we duplicate %1 in the destination reg of the insn
1077;; if it's a small constant.
1078
1079(define_insn "*cmpsi_cc_insn"
1080  [(set (reg:CC 61)
1081	(compare:CC (match_operand:SI 0 "register_operand" "r,r,r")
1082		    (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1083  ""
1084  "@
1085   sub.f 0,%0,%1
1086   sub.f %1,%0,%1
1087   sub.f 0,%0,%1"
1088  [(set_attr "type" "compare,compare,compare")])
1089
1090(define_insn "*cmpsi_cczn_insn"
1091  [(set (reg:CCZN 61)
1092	(compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r")
1093		      (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1094  ""
1095  "@
1096   sub.f 0,%0,%1
1097   sub.f %1,%0,%1
1098   sub.f 0,%0,%1"
1099  [(set_attr "type" "compare,compare,compare")])
1100
1101(define_insn "*cmpsi_ccznc_insn"
1102  [(set (reg:CCZNC 61)
1103	(compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r")
1104		       (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1105  ""
1106  "@
1107   sub.f 0,%0,%1
1108   sub.f %1,%0,%1
1109   sub.f 0,%0,%1"
1110  [(set_attr "type" "compare,compare,compare")])
1111
1112;; Next come the scc insn and its expander.
1113
1114(define_expand "cstoresi4"
1115  [(set (match_dup 4)
1116        (match_op_dup 5
1117         [(match_operand:SI 2 "register_operand" "")
1118          (match_operand:SI 3 "nonmemory_operand" "")]))
1119   (set (match_operand:SI 0 "register_operand")
1120        (match_operator:SI 1 "ordered_comparison_operator"
1121	 [(match_dup 4)
1122	  (const_int 0)]))]
1123  ""
1124  "
1125{
1126  operands[4] = gen_compare_reg (GET_CODE (operands[1]),
1127				 operands[2], operands[3]);
1128  operands[5] = gen_rtx_fmt_ee (COMPARE,
1129				GET_MODE (operands[4]),
1130				operands[2], operands[3]);
1131}")
1132
1133(define_insn "*scc_insn"
1134  [(set (match_operand:SI 0 "register_operand" "=r")
1135	(match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))]
1136  ""
1137  "mov %0,1\;sub.%D1 %0,%0,%0"
1138  [(set_attr "type" "unary")
1139   (set_attr "length" "2")])
1140
1141;; ??? Look up negscc insn.  See pa.md for example.
1142(define_insn "*neg_scc_insn"
1143  [(set (match_operand:SI 0 "register_operand" "=r")
1144	(neg:SI (match_operator:SI 1 "comparison_operator"
1145		 [(reg 61) (const_int 0)])))]
1146  ""
1147  "mov %0,-1\;sub.%D1 %0,%0,%0"
1148  [(set_attr "type" "unary")
1149   (set_attr "length" "2")])
1150
1151(define_insn "*not_scc_insn"
1152  [(set (match_operand:SI 0 "register_operand" "=r")
1153	(not:SI (match_operator:SI 1 "comparison_operator"
1154		 [(reg 61) (const_int 0)])))]
1155  ""
1156  "mov %0,1\;sub.%d1 %0,%0,%0"
1157  [(set_attr "type" "unary")
1158   (set_attr "length" "2")])
1159
1160;; These control RTL generation for conditional jump insns
1161
1162(define_expand "cbranchsi4"
1163  [(set (match_dup 4)
1164        (match_op_dup 5
1165	 [(match_operand:SI 1 "register_operand" "")
1166          (match_operand:SI 2 "nonmemory_operand" "")]))
1167   (set (pc)
1168        (if_then_else
1169              (match_operator 0 "ordered_comparison_operator"
1170	       [(match_dup 4)
1171		(const_int 0)])
1172              (label_ref (match_operand 3 "" ""))
1173              (pc)))]
1174  ""
1175  "
1176{
1177  operands[4] = gen_compare_reg (GET_CODE (operands[0]),
1178				 operands[1], operands[2]);
1179  operands[5] = gen_rtx_fmt_ee (COMPARE,
1180				GET_MODE (operands[4]),
1181				operands[1], operands[2]);
1182}")
1183
1184;; Now match both normal and inverted jump.
1185
1186(define_insn "*branch_insn"
1187  [(set (pc)
1188	(if_then_else (match_operator 1 "proper_comparison_operator"
1189				      [(reg 61) (const_int 0)])
1190		      (label_ref (match_operand 0 "" ""))
1191		      (pc)))]
1192  ""
1193  "*
1194{
1195  if (arc_ccfsm_branch_deleted_p ())
1196    {
1197      arc_ccfsm_record_branch_deleted ();
1198      return \"; branch deleted, next insns conditionalized\";
1199    }
1200  else
1201    return \"%~b%d1%# %l0\";
1202}"
1203  [(set_attr "type" "branch")])
1204
1205(define_insn "*rev_branch_insn"
1206  [(set (pc)
1207	(if_then_else (match_operator 1 "proper_comparison_operator"
1208				      [(reg 61) (const_int 0)])
1209		      (pc)
1210		      (label_ref (match_operand 0 "" ""))))]
1211  "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
1212  "*
1213{
1214  if (arc_ccfsm_branch_deleted_p ())
1215    {
1216      arc_ccfsm_record_branch_deleted ();
1217      return \"; branch deleted, next insns conditionalized\";
1218    }
1219  else
1220    return \"%~b%D1%# %l0\";
1221}"
1222  [(set_attr "type" "branch")])
1223
1224;; Unconditional and other jump instructions.
1225
1226(define_insn "jump"
1227  [(set (pc) (label_ref (match_operand 0 "" "")))]
1228  ""
1229  "b%* %l0"
1230  [(set_attr "type" "uncond_branch")])
1231
1232(define_insn "indirect_jump"
1233  [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
1234  ""
1235  "j%* %a0"
1236  [(set_attr "type" "uncond_branch")])
1237
1238;; Implement a switch statement.
1239;; This wouldn't be necessary in the non-pic case if we could distinguish
1240;; label refs of the jump table from other label refs.  The problem is that
1241;; label refs are output as "%st(.LL42)" but we don't want the %st - we want
1242;; the real address since it's the address of the table.
1243
1244(define_expand "casesi"
1245  [(set (match_dup 5)
1246	(minus:SI (match_operand:SI 0 "register_operand" "")
1247		  (match_operand:SI 1 "nonmemory_operand" "")))
1248   (set (reg:CC 61)
1249	(compare:CC (match_dup 5)
1250		    (match_operand:SI 2 "nonmemory_operand" "")))
1251   (set (pc)
1252	(if_then_else (gtu (reg:CC 61)
1253			   (const_int 0))
1254		      (label_ref (match_operand 4 "" ""))
1255		      (pc)))
1256   (parallel
1257    [(set (pc)
1258	  (mem:SI (plus:SI (mult:SI (match_dup 5)
1259				    (const_int 4))
1260			   (label_ref (match_operand 3 "" "")))))
1261     (clobber (match_scratch:SI 6 ""))
1262     (clobber (match_scratch:SI 7 ""))])]
1263  ""
1264  "
1265{
1266  operands[5] = gen_reg_rtx (SImode);
1267}")
1268
1269(define_insn "*casesi_insn"
1270  [(set (pc)
1271	(mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
1272				  (const_int 4))
1273			 (label_ref (match_operand 1 "" "")))))
1274   (clobber (match_scratch:SI 2 "=r"))
1275   (clobber (match_scratch:SI 3 "=r"))]
1276  ""
1277  "*
1278{
1279  output_asm_insn (\"mov %2,%1\", operands);
1280  if (TARGET_SHIFTER)
1281    output_asm_insn (\"asl %3,%0,2\", operands);
1282  else
1283    output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands);
1284  output_asm_insn (\"ld %2,[%2,%3]\", operands);
1285  output_asm_insn (\"j.nd %a2\", operands);
1286  return \"\";
1287}"
1288  [(set_attr "type" "uncond_branch")
1289   (set_attr "length" "6")])
1290
1291(define_insn "tablejump"
1292  [(set (pc) (match_operand:SI 0 "address_operand" "p"))
1293   (use (label_ref (match_operand 1 "" "")))]
1294  "0 /* disabled -> using casesi now */"
1295  "j%* %a0"
1296  [(set_attr "type" "uncond_branch")])
1297
1298(define_expand "call"
1299  ;; operands[1] is stack_size_rtx
1300  ;; operands[2] is next_arg_register
1301  [(parallel [(call (match_operand:SI 0 "call_operand" "")
1302		    (match_operand 1 "" ""))
1303	     (clobber (reg:SI 31))])]
1304  ""
1305  "")
1306
1307(define_insn "*call_via_reg"
1308  [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
1309	 (match_operand 1 "" ""))
1310   (clobber (reg:SI 31))]
1311  ""
1312  "lr blink,[status]\;j.d %0\;add blink,blink,2"
1313  [(set_attr "type" "call_no_delay_slot")
1314   (set_attr "length" "3")])
1315
1316(define_insn "*call_via_label"
1317  [(call (mem:SI (match_operand:SI 0 "call_address_operand" ""))
1318	 (match_operand 1 "" ""))
1319   (clobber (reg:SI 31))]
1320  ""
1321  ; The %~ is necessary in case this insn gets conditionalized and the previous
1322  ; insn is the cc setter.
1323  "%~bl%!%* %0"
1324  [(set_attr "type" "call")
1325   (set_attr "cond" "canuse")])
1326
1327(define_expand "call_value"
1328  ;; operand 2 is stack_size_rtx
1329  ;; operand 3 is next_arg_register
1330  [(parallel [(set (match_operand 0 "register_operand" "=r")
1331		   (call (match_operand:SI 1 "call_operand" "")
1332			 (match_operand 2 "" "")))
1333	     (clobber (reg:SI 31))])]
1334  ""
1335  "")
1336
1337(define_insn "*call_value_via_reg"
1338  [(set (match_operand 0 "register_operand" "=r")
1339	(call (mem:SI (match_operand:SI 1 "register_operand" "r"))
1340	      (match_operand 2 "" "")))
1341   (clobber (reg:SI 31))]
1342  ""
1343  "lr blink,[status]\;j.d %1\;add blink,blink,2"
1344  [(set_attr "type" "call_no_delay_slot")
1345   (set_attr "length" "3")])
1346
1347(define_insn "*call_value_via_label"
1348  [(set (match_operand 0 "register_operand" "=r")
1349	(call (mem:SI (match_operand:SI 1 "call_address_operand" ""))
1350	      (match_operand 2 "" "")))
1351   (clobber (reg:SI 31))]
1352  ""
1353  ; The %~ is necessary in case this insn gets conditionalized and the previous
1354  ; insn is the cc setter.
1355  "%~bl%!%* %1"
1356  [(set_attr "type" "call")
1357   (set_attr "cond" "canuse")])
1358
1359(define_insn "nop"
1360  [(const_int 0)]
1361  ""
1362  "nop"
1363  [(set_attr "type" "misc")])
1364
1365;; Special pattern to flush the icache.
1366;; ??? Not sure what to do here.  Some ARC's are known to support this.
1367
1368(define_insn "flush_icache"
1369  [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)]
1370  ""
1371  "* return \"\";"
1372  [(set_attr "type" "misc")])
1373
1374;; Split up troublesome insns for better scheduling.
1375
1376;; Peepholes go at the end.
1377