OSDN Git Service

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