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