OSDN Git Service

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