]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arc/arc.md
Update mainline egcs to gcc2 snapshot 971021.
[thirdparty/gcc.git] / gcc / config / arc / arc.md
CommitLineData
e9a25f70 1;; Machine description of the Argonaut ARC cpu for GNU C compiler
5680076c
JL
2;; Copyright (C) 1994, 1997 Free Software Foundation, Inc.
3
4;; This file is part of GNU CC.
5
6;; GNU CC is free software; you can redistribute it and/or modify
7;; it under the terms of the GNU General Public License as published by
8;; the Free Software Foundation; either version 2, or (at your option)
9;; any later version.
10
11;; GNU CC is distributed in the hope that it will be useful,
12;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;; GNU General Public License for more details.
15
16;; You should have received a copy of the GNU General Public License
17;; along with GNU CC; see the file COPYING. If not, write to
18;; the Free Software Foundation, 59 Temple Place - Suite 330,
19;; Boston, MA 02111-1307, USA.
20
21;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
22
23;; ??? This is an old port, and is undoubtedly suffering from bit rot.
24\f
25;; Insn type. Used to default other attribute values.
26
27(define_attr "type"
28 "move,load,store,cmove,unary,binary,compare,shift,mul,uncond_branch,branch,call,call_no_delay_slot,multi,misc"
29 (const_string "binary"))
30
31;; Length (in # of insns, long immediate constants counted too).
32;; ??? There's a nasty interaction between the conditional execution fsm
33;; and insn lengths: insns with shimm values cannot be conditionally executed.
34(define_attr "length" ""
35 (cond [(eq_attr "type" "load")
36 (if_then_else (match_operand 1 "long_immediate_loadstore_operand" "")
37 (const_int 2) (const_int 1))
38
39 (eq_attr "type" "store")
40 (if_then_else (match_operand 0 "long_immediate_loadstore_operand" "")
41 (const_int 2) (const_int 1))
42
43 (eq_attr "type" "move,unary,compare")
44 (if_then_else (match_operand 1 "long_immediate_operand" "")
45 (const_int 2) (const_int 1))
46
47 (eq_attr "type" "binary,mul")
48 (if_then_else (match_operand 2 "long_immediate_operand" "")
49 (const_int 2) (const_int 1))
50
51 (eq_attr "type" "cmove")
52 (if_then_else (match_operand 2 "register_operand" "")
53 (const_int 1) (const_int 2))
54
55 (eq_attr "type" "multi") (const_int 2)
56 ]
57
58 (const_int 1)))
59
60;; The length here is the length of a single asm. Unfortunately it might be
61;; 1 or 2 so we must allow for 2. That's ok though. How often will users
62;; lament asm's not being put in delay slots?
63(define_asm_attributes
64 [(set_attr "length" "2")
65 (set_attr "type" "multi")])
66
67;; Condition codes: this one is used by final_prescan_insn to speed up
68;; conditionalizing instructions. It saves having to scan the rtl to see if
69;; it uses or alters the condition codes.
70
71;; USE: This insn uses the condition codes (eg: a conditional branch).
72;; CANUSE: This insn can use the condition codes (for conditional execution).
73;; SET: All condition codes are set by this insn.
74;; SET_ZN: the Z and N flags are set by this insn.
75;; SET_ZNC: the Z, N, and C flags are set by this insn.
76;; CLOB: The condition codes are set to unknown values by this insn.
77;; NOCOND: This insn can't use and doesn't affect the condition codes.
78
79(define_attr "cond" "use,canuse,set,set_zn,set_znc,clob,nocond"
80 (cond [(and (eq_attr "type" "unary,binary,move")
81 (eq_attr "length" "1"))
82 (const_string "canuse")
83
84 (eq_attr "type" "compare")
85 (const_string "set")
86
87 (eq_attr "type" "cmove,branch")
88 (const_string "use")
89
90 (eq_attr "type" "multi,misc")
91 (const_string "clob")
92 ]
93
94 (const_string "nocond")))
95\f
96;; Delay slots.
97
98(define_attr "in_delay_slot" "false,true"
99 (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi")
100 (const_string "false")
101 ]
102
103 (if_then_else (eq_attr "length" "1")
104 (const_string "true")
105 (const_string "false"))))
106
107(define_delay (eq_attr "type" "call")
108 [(eq_attr "in_delay_slot" "true")
109 (eq_attr "in_delay_slot" "true")
110 (eq_attr "in_delay_slot" "true")])
111
112(define_delay (eq_attr "type" "branch,uncond_branch")
113 [(eq_attr "in_delay_slot" "true")
114 (eq_attr "in_delay_slot" "true")
115 (eq_attr "in_delay_slot" "true")])
116\f
117;; Function units of the ARC
118
119;; (define_function_unit {name} {num-units} {n-users} {test}
120;; {ready-delay} {issue-delay} [{conflict-list}])
121
122;; 1) A conditional jump cannot immediately follow the insn setting the flags.
123;; This isn't a complete solution as it doesn't come with guarantees. That
124;; is done in the branch patterns and in arc_print_operand. This exists to
125;; avoid inserting a nop when we can.
126(define_function_unit "compare" 1 0 (eq_attr "type" "compare") 2 2 [(eq_attr "type" "branch")])
127
128;; 2) References to loaded registers should wait a cycle.
129
130;; Memory with load-delay of 1 (i.e., 2 cycle load).
131(define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0)
132
133;; Units that take one cycle do not need to be specified.
134\f
135;; Move instructions.
136
137(define_expand "movqi"
138 [(set (match_operand:QI 0 "general_operand" "")
139 (match_operand:QI 1 "general_operand" ""))]
140 ""
141 "
142{
143 /* Everything except mem = const or mem = mem can be done easily. */
144
145 if (GET_CODE (operands[0]) == MEM)
146 operands[1] = force_reg (QImode, operands[1]);
147}")
148
149(define_insn "*movqi_insn"
150 [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,m")
151 (match_operand:QI 1 "move_src_operand" "rI,Ji,m,r"))]
152;; ??? Needed?
153 "register_operand (operands[0], QImode)
154 || register_operand (operands[1], QImode)"
155 "@
156 mov%? %0,%1
157 mov%? %0,%1
158 ldb%U1%V1 %0,%1
159 stb%U0%V0 %1,%0"
160 [(set_attr "type" "move,move,load,store")])
161
162;; ??? This may never match since there's no cmpqi insn.
163
164(define_insn "*movqi_set_cc_insn"
165 [(set (reg:CCZN 61) (compare:CCZN
166 (sign_extend:SI (match_operand:QI 1 "move_src_operand" "rIJi"))
167 (const_int 0)))
168 (set (match_operand:QI 0 "move_dest_operand" "=r")
169 (match_dup 1))]
170 ""
171 "mov%?.f %0,%1"
172 [(set_attr "type" "move")
173 (set_attr "cond" "set_zn")])
174
175(define_expand "movhi"
176 [(set (match_operand:HI 0 "general_operand" "")
177 (match_operand:HI 1 "general_operand" ""))]
178 ""
179 "
180{
181 /* Everything except mem = const or mem = mem can be done easily. */
182
183 if (GET_CODE (operands[0]) == MEM)
184 operands[1] = force_reg (HImode, operands[1]);
185}")
186
187(define_insn "*movhi_insn"
188 [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,m")
189 (match_operand:HI 1 "move_src_operand" "rI,Ji,m,r"))]
190 "register_operand (operands[0], HImode)
191 || register_operand (operands[1], HImode)"
192 "@
193 mov%? %0,%1
194 mov%? %0,%1
195 ldw%U1%V1 %0,%1
196 stw%U0%V0 %1,%0"
197 [(set_attr "type" "move,move,load,store")])
198
199;; ??? Will this ever match?
200
201(define_insn "*movhi_set_cc_insn"
202 [(set (reg:CCZN 61) (compare:CCZN
203 (sign_extend:SI (match_operand:HI 1 "move_src_operand" "rIJi"))
204 (const_int 0)))
205 (set (match_operand:HI 0 "move_dest_operand" "=r")
206 (match_dup 1))]
207;; ??? Needed?
208 "register_operand (operands[0], HImode)
209 || register_operand (operands[1], HImode)"
210 "mov%?.f %0,%1"
211 [(set_attr "type" "move")
212 (set_attr "cond" "set_zn")])
213
214(define_expand "movsi"
215 [(set (match_operand:SI 0 "general_operand" "")
216 (match_operand:SI 1 "general_operand" ""))]
217 ""
218 "
219{
220 /* Everything except mem = const or mem = mem can be done easily. */
221
222 if (GET_CODE (operands[0]) == MEM)
223 operands[1] = force_reg (SImode, operands[1]);
224}")
225
226(define_insn "*movsi_insn"
227 [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,m")
228 (match_operand:SI 1 "move_src_operand" "rI,GJi,m,r"))]
229 "register_operand (operands[0], SImode)
230 || register_operand (operands[1], SImode)"
231 "@
232 mov%? %0,%1
233 mov%? %0,%S1
234 ld%U1%V1 %0,%1
235 st%U0%V0 %1,%0"
236 [(set_attr "type" "move,move,load,store")])
237
238(define_insn "*movsi_set_cc_insn"
239 [(set (reg:CCZN 61) (compare:CCZN
240 (match_operand:SI 1 "move_src_operand" "rIJi")
241 (const_int 0)))
242 (set (match_operand:SI 0 "move_dest_operand" "=r")
243 (match_dup 1))]
244 "register_operand (operands[0], SImode)
245 || register_operand (operands[1], SImode)"
246 "mov%?.f %0,%S1"
247 [(set_attr "type" "move")
248 (set_attr "cond" "set_zn")])
249
250(define_expand "movdi"
251 [(set (match_operand:DI 0 "general_operand" "")
252 (match_operand:DI 1 "general_operand" ""))]
253 ""
254 "
255{
256 /* Everything except mem = const or mem = mem can be done easily. */
257
258 if (GET_CODE (operands[0]) == MEM)
259 operands[1] = force_reg (DImode, operands[1]);
260}")
261
262(define_insn "*movdi_insn"
263 [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m")
264 (match_operand:DI 1 "move_double_src_operand" "r,HK,m,r"))]
265 "register_operand (operands[0], DImode)
266 || register_operand (operands[1], DImode)"
267 "*
268{
269 switch (which_alternative)
270 {
271 case 0 :
272 /* We normally copy the low-numbered register first. However, if
273 the first register operand 0 is the same as the second register of
274 operand 1, we must copy in the opposite order. */
275 if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
276 return \"mov %R0,%R1\;mov %0,%1\";
277 else
278 return \"mov %0,%1\;mov %R0,%R1\";
279 case 1 :
280 return \"mov %0,%L1\;mov %R0,%H1\";
281 case 2 :
282 /* If the low-address word is used in the address, we must load it
283 last. Otherwise, load it first. Note that we cannot have
284 auto-increment in that case since the address register is known to be
285 dead. */
286 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
287 operands [1], 0))
288 return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
289 else
290 return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
291 case 3 :
292 return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
293 }
294}"
295 [(set_attr "type" "move,move,load,store")
296 ;; ??? The ld/st values could be 4 if it's [reg,bignum].
297 (set_attr "length" "2,4,2,2")])
298
299;(define_expand "movdi"
300; [(set (match_operand:DI 0 "general_operand" "")
301; (match_operand:DI 1 "general_operand" ""))]
302; ""
303; "
304;{
305; /* Flow doesn't understand that this is effectively a DFmode move.
306; It doesn't know that all of `operands[0]' is set. */
307; emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0]));
308;
309; /* Emit insns that movsi_insn can handle. */
310; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DImode),
311; operand_subword (operands[1], 0, 0, DImode)));
312; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DImode),
313; operand_subword (operands[1], 1, 0, DImode)));
314; DONE;
315;}")
316\f
317;; Floating point move insns.
318
319(define_expand "movsf"
320 [(set (match_operand:SF 0 "general_operand" "")
321 (match_operand:SF 1 "general_operand" ""))]
322 ""
323 "
324{
325 /* Everything except mem = const or mem = mem can be done easily. */
326
327#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
328 if (GET_CODE (operands[1]) == CONST_DOUBLE)
329 operands[1] = force_const_mem (SFmode, operands[1]);
330#endif
331
332 if (GET_CODE (operands[0]) == MEM)
333 operands[1] = force_reg (SFmode, operands[1]);
334}")
335
336(define_insn "*movsf_insn"
337 [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m")
338 (match_operand:SF 1 "move_src_operand" "r,E,m,r"))]
339 "register_operand (operands[0], SFmode)
340 || register_operand (operands[1], SFmode)"
341 "@
342 mov%? %0,%1
343 mov%? %0,%1 ; %A1
344 ld%U1%V1 %0,%1
345 st%U0%V0 %1,%0"
346 [(set_attr "type" "move,move,load,store")])
347
348(define_expand "movdf"
349 [(set (match_operand:DF 0 "general_operand" "")
350 (match_operand:DF 1 "general_operand" ""))]
351 ""
352 "
353{
354 /* Everything except mem = const or mem = mem can be done easily. */
355
356#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
357 if (GET_CODE (operands[1]) == CONST_DOUBLE)
358 operands[1] = force_const_mem (DFmode, operands[1]);
359#endif
360
361 if (GET_CODE (operands[0]) == MEM)
362 operands[1] = force_reg (DFmode, operands[1]);
363}")
364
365(define_insn "*movdf_insn"
366 [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m")
367 (match_operand:DF 1 "move_double_src_operand" "r,E,m,r"))]
368 "register_operand (operands[0], DFmode)
369 || register_operand (operands[1], DFmode)"
370 "*
371{
372 switch (which_alternative)
373 {
374 case 0 :
375 /* We normally copy the low-numbered register first. However, if
376 the first register operand 0 is the same as the second register of
377 operand 1, we must copy in the opposite order. */
378 if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
379 return \"mov %R0,%R1\;mov %0,%1\";
380 else
381 return \"mov %0,%1\;mov %R0,%R1\";
382 case 1 :
383 return \"mov %0,%L1\;mov %R0,%H1 ; %A1\";
384 case 2 :
385 /* If the low-address word is used in the address, we must load it
386 last. Otherwise, load it first. Note that we cannot have
387 auto-increment in that case since the address register is known to be
388 dead. */
389 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
390 operands [1], 0))
391 return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
392 else
393 return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
394 case 3 :
395 return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
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 (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 = gen_rtx (REG,
590 SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
591 61);
592
593 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
594}")
595
596;(define_expand "movdicc"
597; [(set (match_operand:DI 0 "register_operand" "")
598; (if_then_else (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 = gen_rtx (REG,
606; SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
607; 61);
608;
609; operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
610;}")
611
612(define_expand "movsfcc"
613 [(set (match_operand:SF 0 "register_operand" "")
614 (if_then_else (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 = gen_rtx (REG,
622 SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
623 61);
624
625 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
626}")
627
628;(define_expand "movdfcc"
629; [(set (match_operand:DF 0 "register_operand" "")
630; (if_then_else (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 = gen_rtx (REG,
638; SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
639; 61);
640;
641; operands[1] = gen_rtx (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 (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 (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 (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 (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:CC
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
1064 (PARALLEL, VOIDmode,
1065 gen_rtvec (2,
1066 gen_rtx (SET, VOIDmode, operands[0],
1067 gen_rtx (ASHIFT, SImode, operands[1], operands[2])),
1068 gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, SImode, 0)))));
1069 DONE;
1070 }
1071}")
1072
1073(define_expand "ashrsi3"
1074 [(set (match_operand:SI 0 "register_operand" "")
1075 (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
1076 (match_operand:SI 2 "nonmemory_operand" "")))]
1077 ""
1078 "
1079{
1080 if (! TARGET_SHIFTER)
1081 {
1082 emit_insn (gen_rtx
1083 (PARALLEL, VOIDmode,
1084 gen_rtvec (2,
1085 gen_rtx (SET, VOIDmode, operands[0],
1086 gen_rtx (ASHIFTRT, SImode, operands[1], operands[2])),
1087 gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, SImode, 0)))));
1088 DONE;
1089 }
1090}")
1091
1092(define_expand "lshrsi3"
1093 [(set (match_operand:SI 0 "register_operand" "")
1094 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
1095 (match_operand:SI 2 "nonmemory_operand" "")))]
1096 ""
1097 "
1098{
1099 if (! TARGET_SHIFTER)
1100 {
1101 emit_insn (gen_rtx
1102 (PARALLEL, VOIDmode,
1103 gen_rtvec (2,
1104 gen_rtx (SET, VOIDmode, operands[0],
1105 gen_rtx (LSHIFTRT, SImode, operands[1], operands[2])),
1106 gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, SImode, 0)))));
1107 DONE;
1108 }
1109}")
1110
1111(define_insn "*ashlsi3_insn"
1112 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1113 (ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1114 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1115 "TARGET_SHIFTER"
1116 "asl%? %0,%1,%2"
1117 [(set_attr "type" "shift")
1118 (set_attr "length" "1,2,1,2")])
1119
1120(define_insn "*ashrsi3_insn"
1121 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1122 (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1123 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1124 "TARGET_SHIFTER"
1125 "asr%? %0,%1,%2"
1126 [(set_attr "type" "shift")
1127 (set_attr "length" "1,2,1,2")])
1128
1129(define_insn "*lshrsi3_insn"
1130 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1131 (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1132 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1133 "TARGET_SHIFTER"
1134 "lsr%? %0,%1,%2"
1135 [(set_attr "type" "shift")
1136 (set_attr "length" "1,2,1,2")])
1137
1138(define_insn "*shift_si3"
1139 [(set (match_operand:SI 0 "register_operand" "=r")
1140 (match_operator:SI 3 "shift_operator"
1141 [(match_operand:SI 1 "register_operand" "0")
1142 (match_operand:SI 2 "nonmemory_operand" "rIJ")]))
1143 (clobber (match_scratch:SI 4 "=&r"))]
1144 "! TARGET_SHIFTER"
1145 "* return output_shift (operands);"
1146 [(set_attr "type" "shift")
1147 (set_attr "length" "8")])
1148\f
1149;; Compare instructions.
1150;; This controls RTL generation and register allocation.
1151
1152;; We generate RTL for comparisons and branches by having the cmpxx
1153;; patterns store away the operands. Then, the scc and bcc patterns
1154;; emit RTL for both the compare and the branch.
1155
1156(define_expand "cmpsi"
1157 [(set (reg:CC 61)
1158 (compare:CC (match_operand:SI 0 "register_operand" "")
1159 (match_operand:SI 1 "nonmemory_operand" "")))]
1160 ""
1161 "
1162{
1163 arc_compare_op0 = operands[0];
1164 arc_compare_op1 = operands[1];
1165 DONE;
1166}")
1167
1168;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0.
1169;; This assumes sub.f 0,symbol,0 is a valid insn.
1170;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily
1171;; creating 8 byte insns we duplicate %1 in the destination reg of the insn
1172;; if it's a small constant.
1173
1174(define_insn "*cmpsi_cc_insn"
1175 [(set (reg:CC 61)
1176 (compare:CC (match_operand:SI 0 "register_operand" "r,r,r")
1177 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1178 ""
1179 "@
1180 sub.f 0,%0,%1
1181 sub.f %1,%0,%1
1182 sub.f 0,%0,%1"
1183 [(set_attr "type" "compare,compare,compare")])
1184
1185(define_insn "*cmpsi_cczn_insn"
1186 [(set (reg:CCZN 61)
1187 (compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r")
1188 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1189 ""
1190 "@
1191 sub.f 0,%0,%1
1192 sub.f %1,%0,%1
1193 sub.f 0,%0,%1"
1194 [(set_attr "type" "compare,compare,compare")])
1195
1196(define_insn "*cmpsi_ccznc_insn"
1197 [(set (reg:CCZNC 61)
1198 (compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r")
1199 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1200 ""
1201 "@
1202 sub.f 0,%0,%1
1203 sub.f %1,%0,%1
1204 sub.f 0,%0,%1"
1205 [(set_attr "type" "compare,compare,compare")])
1206
1207;; Next come the scc insns.
1208
1209(define_expand "seq"
1210 [(set (match_operand:SI 0 "register_operand" "=r")
1211 (eq:SI (match_dup 1) (const_int 0)))]
1212 ""
1213 "
1214{
1215 operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1);
1216}")
1217
1218(define_expand "sne"
1219 [(set (match_operand:SI 0 "register_operand" "=r")
1220 (ne:SI (match_dup 1) (const_int 0)))]
1221 ""
1222 "
1223{
1224 operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1);
1225}")
1226
1227(define_expand "sgt"
1228 [(set (match_operand:SI 0 "register_operand" "=r")
1229 (gt:SI (match_dup 1) (const_int 0)))]
1230 ""
1231 "
1232{
1233 operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1);
1234}")
1235
1236(define_expand "sle"
1237 [(set (match_operand:SI 0 "register_operand" "=r")
1238 (le:SI (match_dup 1) (const_int 0)))]
1239 ""
1240 "
1241{
1242 operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1);
1243}")
1244
1245(define_expand "sge"
1246 [(set (match_operand:SI 0 "register_operand" "=r")
1247 (ge:SI (match_dup 1) (const_int 0)))]
1248 ""
1249 "
1250{
1251 operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1);
1252}")
1253
1254(define_expand "slt"
1255 [(set (match_operand:SI 0 "register_operand" "=r")
1256 (lt:SI (match_dup 1) (const_int 0)))]
1257 ""
1258 "
1259{
1260 operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1);
1261}")
1262
1263(define_expand "sgtu"
1264 [(set (match_operand:SI 0 "register_operand" "=r")
1265 (gtu:SI (match_dup 1) (const_int 0)))]
1266 ""
1267 "
1268{
1269 operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1);
1270}")
1271
1272(define_expand "sleu"
1273 [(set (match_operand:SI 0 "register_operand" "=r")
1274 (leu:SI (match_dup 1) (const_int 0)))]
1275 ""
1276 "
1277{
1278 operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1);
1279}")
1280
1281(define_expand "sgeu"
1282 [(set (match_operand:SI 0 "register_operand" "=r")
1283 (geu:SI (match_dup 1) (const_int 0)))]
1284 ""
1285 "
1286{
1287 operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1);
1288}")
1289
1290(define_expand "sltu"
1291 [(set (match_operand:SI 0 "register_operand" "=r")
1292 (ltu:SI (match_dup 1) (const_int 0)))]
1293 ""
1294 "
1295{
1296 operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1);
1297}")
1298
1299(define_insn "*scc_insn"
1300 [(set (match_operand:SI 0 "register_operand" "=r")
1301 (match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))]
1302 ""
1303 "mov %0,1\;sub.%D1 %0,%0,%0"
1304 [(set_attr "type" "unary")
1305 (set_attr "length" "2")])
1306
1307;; ??? Look up negscc insn. See pa.md for example.
1308(define_insn "*neg_scc_insn"
1309 [(set (match_operand:SI 0 "register_operand" "=r")
1310 (neg:SI (match_operator:SI 1 "comparison_operator"
1311 [(reg 61) (const_int 0)])))]
1312 ""
1313 "mov %0,-1\;sub.%D1 %0,%0,%0"
1314 [(set_attr "type" "unary")
1315 (set_attr "length" "2")])
1316
1317(define_insn "*not_scc_insn"
1318 [(set (match_operand:SI 0 "register_operand" "=r")
1319 (not:SI (match_operator:SI 1 "comparison_operator"
1320 [(reg 61) (const_int 0)])))]
1321 ""
1322 "mov %0,1\;sub.%d1 %0,%0,%0"
1323 [(set_attr "type" "unary")
1324 (set_attr "length" "2")])
1325\f
1326;; These control RTL generation for conditional jump insns
1327
1328(define_expand "beq"
1329 [(set (pc)
1330 (if_then_else (eq (match_dup 1) (const_int 0))
1331 (label_ref (match_operand 0 "" ""))
1332 (pc)))]
1333 ""
1334 "
1335{
1336 operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1);
1337}")
1338
1339(define_expand "bne"
1340 [(set (pc)
1341 (if_then_else (ne (match_dup 1) (const_int 0))
1342 (label_ref (match_operand 0 "" ""))
1343 (pc)))]
1344 ""
1345 "
1346{
1347 operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1);
1348}")
1349
1350(define_expand "bgt"
1351 [(set (pc)
1352 (if_then_else (gt (match_dup 1) (const_int 0))
1353 (label_ref (match_operand 0 "" ""))
1354 (pc)))]
1355 ""
1356 "
1357{
1358 operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1);
1359}")
1360
1361(define_expand "ble"
1362 [(set (pc)
1363 (if_then_else (le (match_dup 1) (const_int 0))
1364 (label_ref (match_operand 0 "" ""))
1365 (pc)))]
1366 ""
1367 "
1368{
1369 operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1);
1370}")
1371
1372(define_expand "bge"
1373 [(set (pc)
1374 (if_then_else (ge (match_dup 1) (const_int 0))
1375 (label_ref (match_operand 0 "" ""))
1376 (pc)))]
1377 ""
1378 "
1379{
1380 operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1);
1381}")
1382
1383(define_expand "blt"
1384 [(set (pc)
1385 (if_then_else (lt (match_dup 1) (const_int 0))
1386 (label_ref (match_operand 0 "" ""))
1387 (pc)))]
1388 ""
1389 "
1390{
1391 operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1);
1392}")
1393
1394(define_expand "bgtu"
1395 [(set (pc)
1396 (if_then_else (gtu (match_dup 1) (const_int 0))
1397 (label_ref (match_operand 0 "" ""))
1398 (pc)))]
1399 ""
1400 "
1401{
1402 operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1);
1403}")
1404
1405(define_expand "bleu"
1406 [(set (pc)
1407 (if_then_else (leu (match_dup 1) (const_int 0))
1408 (label_ref (match_operand 0 "" ""))
1409 (pc)))]
1410 ""
1411 "
1412{
1413 operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1);
1414}")
1415
1416(define_expand "bgeu"
1417 [(set (pc)
1418 (if_then_else (geu (match_dup 1) (const_int 0))
1419 (label_ref (match_operand 0 "" ""))
1420 (pc)))]
1421 ""
1422 "
1423{
1424 operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1);
1425}")
1426
1427(define_expand "bltu"
1428 [(set (pc)
1429 (if_then_else (ltu (match_dup 1) (const_int 0))
1430 (label_ref (match_operand 0 "" ""))
1431 (pc)))]
1432 ""
1433 "
1434{
1435 operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1);
1436}")
1437
1438;; Now match both normal and inverted jump.
1439
1440(define_insn "*branch_insn"
1441 [(set (pc)
1442 (if_then_else (match_operator 1 "proper_comparison_operator"
1443 [(reg 61) (const_int 0)])
1444 (label_ref (match_operand 0 "" ""))
1445 (pc)))]
1446 ""
1447 "*
1448{
1449 if (arc_ccfsm_branch_deleted_p ())
1450 {
1451 arc_ccfsm_record_branch_deleted ();
1452 return \"; branch deleted, next insns conditionalized\";
1453 }
1454 else
1455 return \"%~b%d1%# %l0\";
1456}"
1457 [(set_attr "type" "branch")])
1458
1459(define_insn "*rev_branch_insn"
1460 [(set (pc)
1461 (if_then_else (match_operator 1 "proper_comparison_operator"
1462 [(reg 61) (const_int 0)])
1463 (pc)
1464 (label_ref (match_operand 0 "" ""))))]
1465 "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
1466 "*
1467{
1468 if (arc_ccfsm_branch_deleted_p ())
1469 {
1470 arc_ccfsm_record_branch_deleted ();
1471 return \"; branch deleted, next insns conditionalized\";
1472 }
1473 else
1474 return \"%~b%D1%# %l0\";
1475}"
1476 [(set_attr "type" "branch")])
1477\f
1478;; Unconditional and other jump instructions.
1479
1480(define_insn "jump"
1481 [(set (pc) (label_ref (match_operand 0 "" "")))]
1482 ""
1483 "b%* %l0"
1484 [(set_attr "type" "uncond_branch")])
1485
1486(define_insn "indirect_jump"
1487 [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
1488 ""
1489 "j%* %a0"
1490 [(set_attr "type" "uncond_branch")])
1491
1492;; Implement a switch statement.
1493;; This wouldn't be necessary in the non-pic case if we could distinguish
1494;; label refs of the jump table from other label refs. The problem is that
1495;; label refs are output as "%st(.LL42)" but we don't want the %st - we want
1496;; the real address since it's the address of the table.
1497
1498(define_expand "casesi"
1499 [(set (match_dup 5)
1500 (minus:SI (match_operand:SI 0 "register_operand" "")
1501 (match_operand:SI 1 "nonmemory_operand" "")))
1502 (set (reg:CC 61)
1503 (compare:CC (match_dup 5)
1504 (match_operand:SI 2 "nonmemory_operand" "")))
1505 (set (pc)
1506 (if_then_else (gtu (reg:CC 61)
1507 (const_int 0))
1508 (label_ref (match_operand 4 "" ""))
1509 (pc)))
1510 (parallel
1511 [(set (pc)
1512 (mem:SI (plus:SI (mult:SI (match_dup 5)
1513 (const_int 4))
1514 (label_ref (match_operand 3 "" "")))))
1515 (clobber (match_scratch:SI 6 ""))
1516 (clobber (match_scratch:SI 7 ""))])]
1517 ""
1518 "
1519{
1520 operands[5] = gen_reg_rtx (SImode);
1521}")
1522
1523(define_insn "*casesi_insn"
1524 [(set (pc)
1525 (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
1526 (const_int 4))
1527 (label_ref (match_operand 1 "" "")))))
1528 (clobber (match_scratch:SI 2 "=r"))
1529 (clobber (match_scratch:SI 3 "=r"))]
1530 ""
1531 "*
1532{
1533 output_asm_insn (\"mov %2,%1\", operands);
1534 if (TARGET_SHIFTER)
1535 output_asm_insn (\"asl %3,%0,2\", operands);
1536 else
1537 output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands);
1538 output_asm_insn (\"ld %2,[%2,%3]\", operands);
1539 output_asm_insn (\"j.nd %a2\", operands);
1540 return \"\";
1541}"
1542 [(set_attr "type" "uncond_branch")
1543 (set_attr "length" "6")])
1544
1545(define_insn "tablejump"
1546 [(set (pc) (match_operand:SI 0 "address_operand" "p"))
1547 (use (label_ref (match_operand 1 "" "")))]
1548 "0 /* disabled -> using casesi now */"
1549 "j%* %a0"
1550 [(set_attr "type" "uncond_branch")])
1551
1552(define_expand "call"
1553 ;; operands[1] is stack_size_rtx
1554 ;; operands[2] is next_arg_register
1555 [(parallel [(call (match_operand:SI 0 "call_operand" "")
1556 (match_operand 1 "" ""))
1557 (clobber (reg:SI 31))])]
1558 ""
1559 "")
1560
1561(define_insn "*call_via_reg"
1562 [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
1563 (match_operand 1 "" ""))
1564 (clobber (reg:SI 31))]
1565 ""
1566 "lr blink,[status]\;j.d %0\;add blink,blink,2"
1567 [(set_attr "type" "call_no_delay_slot")
1568 (set_attr "length" "3")])
1569
1570(define_insn "*call_via_label"
1571 [(call (mem:SI (match_operand:SI 0 "call_address_operand" ""))
1572 (match_operand 1 "" ""))
1573 (clobber (reg:SI 31))]
1574 ""
1575 ; The %~ is necessary in case this insn gets conditionalized and the previous
1576 ; insn is the cc setter.
1577 "%~bl%!%* %0"
1578 [(set_attr "type" "call")
1579 (set_attr "cond" "canuse")])
1580
1581(define_expand "call_value"
1582 ;; operand 2 is stack_size_rtx
1583 ;; operand 3 is next_arg_register
1584 [(parallel [(set (match_operand 0 "register_operand" "=r")
1585 (call (match_operand:SI 1 "call_operand" "")
1586 (match_operand 2 "" "")))
1587 (clobber (reg:SI 31))])]
1588 ""
1589 "")
1590
1591(define_insn "*call_value_via_reg"
1592 [(set (match_operand 0 "register_operand" "=r")
1593 (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
1594 (match_operand 2 "" "")))
1595 (clobber (reg:SI 31))]
1596 ""
1597 "lr blink,[status]\;j.d %1\;add blink,blink,2"
1598 [(set_attr "type" "call_no_delay_slot")
1599 (set_attr "length" "3")])
1600
1601(define_insn "*call_value_via_label"
1602 [(set (match_operand 0 "register_operand" "=r")
1603 (call (mem:SI (match_operand:SI 1 "call_address_operand" ""))
1604 (match_operand 2 "" "")))
1605 (clobber (reg:SI 31))]
1606 ""
1607 ; The %~ is necessary in case this insn gets conditionalized and the previous
1608 ; insn is the cc setter.
1609 "%~bl%!%* %1"
1610 [(set_attr "type" "call")
1611 (set_attr "cond" "canuse")])
1612\f
1613(define_insn "nop"
1614 [(const_int 0)]
1615 ""
1616 "nop"
1617 [(set_attr "type" "misc")])
1618
1619;; Special pattern to flush the icache.
1620;; ??? Not sure what to do here. Some ARC's are known to support this.
1621
1622(define_insn "flush_icache"
1623 [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)]
1624 ""
1625 "* return \"\";"
1626 [(set_attr "type" "misc")])
1627\f
1628;; Split up troublesome insns for better scheduling.
1629\f
1630;; Peepholes go at the end.