1;; Machine description of the Synopsys DesignWare ARC cpu for GNU C compiler
2;; Copyright (C) 1994-2018 Free Software Foundation, Inc.
3
4;; Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
5;; behalf of Synopsys Inc.
6
7;;    Position Independent Code support added,Code cleaned up,
8;;    Comments and Support For ARC700 instructions added by
9;;    Saurabh Verma (saurabh.verma@codito.com)
10;;    Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
11;;
12;;    Performance improvements by
13;;    Joern Rennecke (joern.rennecke@embecosm.com)
14;;
15
16;; This file is part of GCC.
17
18;; GCC is free software; you can redistribute it and/or modify
19;; it under the terms of the GNU General Public License as published by
20;; the Free Software Foundation; either version 3, or (at your option)
21;; any later version.
22
23;; GCC is distributed in the hope that it will be useful,
24;; but WITHOUT ANY WARRANTY; without even the implied warranty of
25;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26;; GNU General Public License for more details.
27
28;; You should have received a copy of the GNU General Public License
29;; along with GCC; see the file COPYING3.  If not see
30;; <http://www.gnu.org/licenses/>.
31
32;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
33
34;; <op> dest, src         Two operand instruction's syntax
35;; <op> dest, src1, src2  Three operand instruction's syntax
36
37;; ARC and ARCompact PREDICATES:
38;;
39;;   comparison_operator   LT, GT, LE, GE, LTU, GTU, LEU, GEU, EQ, NE
40;;   memory_operand        memory                         [m]
41;;   immediate_operand     immediate constant             [IKLMNOP]
42;;   register_operand      register                       [rq]
43;;   general_operand       register, memory, constant     [rqmIKLMNOP]
44
45;;  Note that the predicates are only used when selecting a pattern
46;;  to determine if an operand is valid.
47
48;;  The constraints then select which of the possible valid operands
49;;  is present (and guide register selection). The actual assembly
50;;  instruction is then selected on the basis of the constraints.
51
52;; ARC and ARCompact CONSTRAINTS:
53;;
54;;   b  stack pointer                           r28
55;;   f  frame pointer                           r27
56;;   Rgp global pointer                         r26
57;;   g  general reg, memory, constant
58;;   m  memory
59;;   p  memory address
60;;   q  registers commonly used in
61;;      16-bit insns                            r0-r3, r12-r15
62;;   c  core registers				r0-r60, ap, pcl
63;;   r  general registers                       r0-r28, blink, ap, pcl
64;;
65;;   H  fp 16-bit constant
66;;   I signed 12-bit immediate (for ARCompact)
67;;   K  unsigned 3-bit immediate (for ARCompact)
68;;   L  unsigned 6-bit immediate (for ARCompact)
69;;   M  unsinged 5-bit immediate (for ARCompact)
70;;   O  unsinged 7-bit immediate (for ARCompact)
71;;   P  unsinged 8-bit immediate (for ARCompact)
72;;   N  constant '1' (for ARCompact)
73
74
75;; TODO:
76;; -> prefetch instruction
77
78;;  -----------------------------------------------------------------------------
79
80;; Include DFA scheduluers
81(include ("arc600.md"))
82(include ("arc700.md"))
83(include ("arcEM.md"))
84(include ("arcHS.md"))
85
86;; Predicates
87
88(include ("predicates.md"))
89(include ("constraints.md"))
90;;  -----------------------------------------------------------------------------
91
92;; UNSPEC Usage:
93;; ~~~~~~~~~~~~
94;;  -----------------------------------------------------------------------------
95;;  Symbolic name  Value              Desc.
96;;  -----------------------------------------------------------------------------
97;;  UNSPEC_PLT       3        symbol to be referenced through the PLT
98;;  UNSPEC_GOT       4        symbol to be rerenced through the GOT
99;;  UNSPEC_GOTOFF    5        Local symbol.To be referenced relative to the
100;;                            GOTBASE.(Referenced as @GOTOFF)
101;;  UNSPEC_GOTOFFPC  6        Local symbol.  To be referenced pc-relative.
102;;  ----------------------------------------------------------------------------
103
104(define_c_enum "unspec" [
105  DUMMY_0
106  DUMMY_1
107  DUMMY_2
108  ARC_UNSPEC_PLT
109  ARC_UNSPEC_GOT
110  ARC_UNSPEC_GOTOFF
111  ARC_UNSPEC_GOTOFFPC
112  UNSPEC_TLS_GD
113  UNSPEC_TLS_LD
114  UNSPEC_TLS_IE
115  UNSPEC_TLS_OFF
116  UNSPEC_ARC_NORM
117  UNSPEC_ARC_NORMW
118  UNSPEC_ARC_SWAP
119  UNSPEC_ARC_DIVAW
120  UNSPEC_ARC_DIRECT
121  UNSPEC_ARC_LP
122  UNSPEC_ARC_CASESI
123  UNSPEC_ARC_FFS
124  UNSPEC_ARC_FLS
125  UNSPEC_ARC_MEMBAR
126  UNSPEC_ARC_DMACH
127  UNSPEC_ARC_DMACHU
128  UNSPEC_ARC_DMACWH
129  UNSPEC_ARC_DMACWHU
130  UNSPEC_ARC_QMACH
131  UNSPEC_ARC_QMACHU
132  UNSPEC_ARC_QMPYH
133  UNSPEC_ARC_QMPYHU
134  UNSPEC_ARC_VMAC2H
135  UNSPEC_ARC_VMAC2HU
136  UNSPEC_ARC_VMPY2H
137  UNSPEC_ARC_VMPY2HU
138  UNSPEC_ARC_STKTIE
139
140  VUNSPEC_ARC_RTIE
141  VUNSPEC_ARC_SYNC
142  VUNSPEC_ARC_BRK
143  VUNSPEC_ARC_FLAG
144  VUNSPEC_ARC_SLEEP
145  VUNSPEC_ARC_SWI
146  VUNSPEC_ARC_CORE_READ
147  VUNSPEC_ARC_CORE_WRITE
148  VUNSPEC_ARC_LR
149  VUNSPEC_ARC_SR
150  VUNSPEC_ARC_TRAP_S
151  VUNSPEC_ARC_UNIMP_S
152  VUNSPEC_ARC_KFLAG
153  VUNSPEC_ARC_CLRI
154  VUNSPEC_ARC_SETI
155  VUNSPEC_ARC_NOP
156  VUNSPEC_ARC_STACK_IRQ
157  VUNSPEC_ARC_DEXCL
158  VUNSPEC_ARC_DEXCL_NORES
159  VUNSPEC_ARC_LR_HIGH
160  VUNSPEC_ARC_EX
161  VUNSPEC_ARC_CAS
162  VUNSPEC_ARC_SC
163  VUNSPEC_ARC_LL
164  VUNSPEC_ARC_BLOCKAGE
165  VUNSPEC_ARC_EH_RETURN
166  ])
167
168(define_constants
169  [(R0_REG 0)
170   (R1_REG 1)
171   (R2_REG 2)
172   (R3_REG 3)
173   (R10_REG 10)
174   (R12_REG 12)
175   (SP_REG 28)
176   (ILINK1_REGNUM 29)
177   (ILINK2_REGNUM 30)
178   (RETURN_ADDR_REGNUM 31)
179   (MUL64_OUT_REG 58)
180   (MUL32x16_REG 56)
181   (ARCV2_ACC 58)
182
183   (LP_COUNT 60)
184   (CC_REG 61)
185   (LP_START 144)
186   (LP_END 145)
187  ]
188)
189
190(define_attr "is_sfunc" "no,yes" (const_string "no"))
191
192;; Insn type.  Used to default other attribute values.
193; While the attribute is_sfunc is set for any call of a special function,
194; the instruction type sfunc is used only for the special call sequence
195; that loads the (pc-relative) function address into r12 and then calls
196; via r12.
197
198(define_attr "type"
199  "move,load,store,cmove,unary,binary,compare,shift,uncond_branch,jump,branch,
200   brcc,brcc_no_delay_slot,call,sfunc,call_no_delay_slot,
201   multi,umulti, two_cycle_core,lr,sr,divaw,loop_setup,loop_end,return,
202   misc,spfp,dpfp_mult,dpfp_addsub,mulmac_600,cc_arith,
203   simd_vload, simd_vload128, simd_vstore, simd_vmove, simd_vmove_else_zero,
204   simd_vmove_with_acc, simd_varith_1cycle, simd_varith_2cycle,
205   simd_varith_with_acc, simd_vlogic, simd_vlogic_with_acc,
206   simd_vcompare, simd_vpermute, simd_vpack, simd_vpack_with_acc,
207   simd_valign, simd_valign_with_acc, simd_vcontrol,
208   simd_vspecial_3cycle, simd_vspecial_4cycle, simd_dma, mul16_em, div_rem,
209   fpu, block"
210  (cond [(eq_attr "is_sfunc" "yes")
211	 (cond [(match_test "!TARGET_LONG_CALLS_SET && (!TARGET_MEDIUM_CALLS || GET_CODE (PATTERN (insn)) != COND_EXEC)") (const_string "call")
212		(match_test "flag_pic") (const_string "sfunc")]
213	       (const_string "call_no_delay_slot"))]
214	(const_string "binary")))
215
216;; The following three attributes are mixed case so that they can be
217;; used conveniently with the CALL_ATTR macro.
218(define_attr "is_CALL" "no,yes"
219  (cond [(eq_attr "is_sfunc" "yes") (const_string "yes")
220	 (eq_attr "type" "call,call_no_delay_slot") (const_string "yes")]
221	(const_string "no")))
222
223(define_attr "is_SIBCALL" "no,yes" (const_string "no"))
224
225(define_attr "is_NON_SIBCALL" "no,yes"
226  (cond [(eq_attr "is_SIBCALL" "yes") (const_string "no")
227	 (eq_attr "is_CALL" "yes") (const_string "yes")]
228	(const_string "no")))
229
230;; true for compact instructions (those with _s suffix)
231;; "maybe" means compact unless we conditionalize the insn.
232(define_attr "iscompact" "true,maybe,true_limm,maybe_limm,false"
233  (cond [(eq_attr "type" "sfunc")
234	 (const_string "maybe")]
235	(const_string "false")))
236
237
238; Is there an instruction that we are actually putting into the delay slot?
239(define_attr "delay_slot_filled" "no,yes"
240  (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
241	 (const_string "no")
242	 (match_test "!TARGET_AT_DBR_CONDEXEC
243		      && JUMP_P (insn)
244		      && INSN_ANNULLED_BRANCH_P (insn)
245		      && !INSN_FROM_TARGET_P (NEXT_INSN (insn))")
246	 (const_string "no")]
247	(const_string "yes")))
248
249; Is a delay slot present for purposes of shorten_branches?
250; We have to take the length of this insn into account for forward branches
251; even if we don't put the insn actually into a delay slot.
252(define_attr "delay_slot_present" "no,yes"
253  (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
254	 (const_string "no")]
255	(const_string "yes")))
256
257; We can't use get_attr_length (NEXT_INSN (insn)) because this gives the
258; length of a different insn with the same uid.
259(define_attr "delay_slot_length" ""
260  (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
261	 (const_int 0)]
262	(symbol_ref "get_attr_length (NEXT_INSN (PREV_INSN (insn)))
263		     - get_attr_length (insn)")))
264
265; for ARCv2 we need to disable/enable different instruction alternatives
266(define_attr "cpu_facility" "std,av1,av2,fpx,cd"
267  (const_string "std"))
268
269; We should consider all the instructions enabled until otherwise
270(define_attr "enabled" "no,yes"
271  (cond [(and (eq_attr "cpu_facility" "av1")
272	      (match_test "TARGET_V2"))
273	 (const_string "no")
274
275	 (and (eq_attr "cpu_facility" "av2")
276	      (not (match_test "TARGET_V2")))
277	 (const_string "no")
278
279	 (and (eq_attr "cpu_facility" "fpx")
280	      (match_test "TARGET_FP_DP_AX"))
281	 (const_string "no")
282
283	 (and (eq_attr "cpu_facility" "cd")
284	      (not (and (match_test "TARGET_V2")
285			(match_test "TARGET_CODE_DENSITY"))))
286	 (const_string "no")
287	 ]
288	(const_string "yes")))
289
290(define_attr "predicable" "no,yes" (const_string "no"))
291;; if 'predicable' were not so brain-dead, we would specify:
292;; (cond [(eq_attr "cond" "!canuse") (const_string "no")
293;;        (eq_attr "iscompact" "maybe") (const_string "no")]
294;;       (const_string "yes"))
295;; and then for everything but calls, we could just set the cond attribute.
296
297;; Condition codes: this one is used by final_prescan_insn to speed up
298;; conditionalizing instructions.  It saves having to scan the rtl to see if
299;; it uses or alters the condition codes.
300
301;; USE: This insn uses the condition codes (eg: a conditional branch).
302;; CANUSE: This insn can use the condition codes (for conditional execution).
303;; SET: All condition codes are set by this insn.
304;; SET_ZN: the Z and N flags are set by this insn.
305;; SET_ZNC: the Z, N, and C flags are set by this insn.
306;; CLOB: The condition codes are set to unknown values by this insn.
307;; NOCOND: This insn can't use and doesn't affect the condition codes.
308
309(define_attr "cond" "use,canuse,canuse_limm,canuse_limm_add,set,set_zn,clob,nocond"
310  (cond
311    [(and (eq_attr "predicable" "yes")
312	  (eq_attr "is_sfunc" "no")
313	  (eq_attr "delay_slot_filled" "no"))
314     (const_string "canuse")
315
316     (eq_attr "type" "call")
317     (cond [(eq_attr "delay_slot_filled" "yes") (const_string "nocond")
318	    (match_test "!flag_pic") (const_string "canuse_limm")]
319	   (const_string "nocond"))
320
321     (eq_attr "iscompact" "maybe,false")
322     (cond [ (and (eq_attr "type" "move")
323		  (match_operand 1 "immediate_operand" ""))
324	     (if_then_else
325		(ior (match_operand 1 "u6_immediate_operand" "")
326		     (match_operand 1 "long_immediate_operand" ""))
327		(const_string "canuse")
328		(const_string "canuse_limm"))
329
330	     (eq_attr "type" "binary")
331	     (cond [(ne (symbol_ref "REGNO (operands[0])")
332			(symbol_ref "REGNO (operands[1])"))
333		    (const_string "nocond")
334		    (match_operand 2 "register_operand" "")
335		    (const_string "canuse")
336		    (match_operand 2 "u6_immediate_operand" "")
337		    (const_string "canuse")
338		    (match_operand 2 "long_immediate_operand" "")
339		    (const_string "canuse")
340		    (match_operand 2 "const_int_operand" "")
341		    (const_string "canuse_limm")]
342		   (const_string "nocond"))
343
344	     (eq_attr "type" "compare")
345	     (const_string "set")
346
347	     (eq_attr "type" "cmove,branch")
348	     (const_string "use")
349
350	     (eq_attr "is_sfunc" "yes")
351	     (cond [(match_test "(TARGET_MEDIUM_CALLS
352				  && !TARGET_LONG_CALLS_SET
353				  && flag_pic)")
354		    (const_string "canuse_limm_add")
355		    (match_test "(TARGET_MEDIUM_CALLS
356				  && !TARGET_LONG_CALLS_SET)")
357		    (const_string "canuse_limm")]
358		   (const_string "canuse"))
359
360	    ]
361
362	    (const_string "nocond"))]
363
364      (cond [(eq_attr "type" "compare")
365	     (const_string "set")
366
367	     (eq_attr "type" "cmove,branch")
368	     (const_string "use")
369
370	    ]
371
372	    (const_string "nocond"))))
373
374/* ??? Having all these patterns gives ifcvt more freedom to generate
375   inefficient code.  It seem to operate on the premise that
376   register-register copies and registers are free.  I see better code
377   with -fno-if-convert now than without.  */
378(define_cond_exec
379  [(match_operator 0 "proper_comparison_operator"
380     [(reg CC_REG) (const_int 0)])]
381  "true"
382  "")
383
384;; Length (in # of bytes, long immediate constants counted too).
385;; ??? There's a nasty interaction between the conditional execution fsm
386;; and insn lengths: insns with shimm values cannot be conditionally executed.
387(define_attr "length" ""
388  (cond
389    [(eq_attr "iscompact" "true")
390      (const_int 2)
391
392     (eq_attr "iscompact" "maybe")
393     (cond
394       [(eq_attr "type" "sfunc")
395	(cond [(match_test "GET_CODE (PATTERN (insn)) == COND_EXEC")
396	       (const_int 12)]
397	      (const_int 10))
398	(match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 4)
399	(match_test "find_reg_note (insn, REG_SAVE_NOTE, GEN_INT (1))")
400	(const_int 4)]
401      (const_int 2))
402
403    (eq_attr "iscompact" "true_limm")
404    (const_int 6)
405
406    (eq_attr "iscompact" "maybe_limm")
407    (cond [(match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 8)]
408	  (const_int 6))
409
410    (eq_attr "type" "load")
411    (if_then_else
412       (match_operand 1 "long_immediate_loadstore_operand" "")
413       (const_int 8) (const_int 4))
414
415    (eq_attr "type" "store")
416    (if_then_else
417      (ior (match_operand 0 "long_immediate_loadstore_operand" "")
418	   (match_operand 1 "immediate_operand" ""))
419      (const_int 8) (const_int 4))
420
421    (eq_attr "type" "move,unary")
422    (cond
423      [(match_operand 1 "u6_immediate_operand" "") (const_int 4)
424       (match_operand 1 "register_operand" "") (const_int 4)
425       (match_operand 1 "long_immediate_operand" "") (const_int 8)
426       (match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 8)]
427      (const_int 4))
428
429    (and (eq_attr "type" "shift")
430	 (match_operand 1 "immediate_operand"))
431		 (const_int 8)
432    (eq_attr "type" "binary,shift")
433    (if_then_else
434       (ior (match_operand 2 "long_immediate_operand" "")
435	    (and (ne (symbol_ref "REGNO (operands[0])")
436		     (symbol_ref "REGNO (operands[1])"))
437		 (eq (match_operand 2 "u6_immediate_operand" "")
438		     (const_int 0))))
439
440       (const_int 8) (const_int 4))
441
442    (eq_attr "type" "cmove")
443       (if_then_else (match_operand 1 "register_operand" "")
444		     (const_int 4) (const_int 8))
445
446    (eq_attr "type" "call_no_delay_slot") (const_int 8)
447   ]
448
449   (const_int 4))
450)
451
452;; The length here is the length of a single asm.  Unfortunately it might be
453;; 4 or 8 so we must allow for 8.  That's ok though.  How often will users
454;; lament asm's not being put in delay slots?
455;;
456(define_asm_attributes
457  [(set_attr "length" "8")
458   (set_attr "type" "multi")
459   (set_attr "cond" "clob") ])
460
461;; Delay slots.
462;; The first two cond clauses and the default are necessary for correctness;
463;; the remaining cond clause is mainly an optimization, as otherwise nops
464;; would be inserted; however, if we didn't do this optimization, we would
465;; have to be more conservative in our length calculations.
466
467(define_attr "in_delay_slot" "false,true"
468  (cond [(eq_attr "type" "uncond_branch,jump,branch,
469			  call,sfunc,call_no_delay_slot,
470			  brcc, brcc_no_delay_slot,loop_setup,loop_end")
471	 (const_string "false")
472	 (match_test "arc_write_ext_corereg (insn)")
473	 (const_string "false")
474	 (gt (symbol_ref "arc_hazard (prev_active_insn (insn),
475				      next_active_insn (insn))")
476	     (symbol_ref "(arc_hazard (prev_active_insn (insn), insn)
477			   + arc_hazard (insn, next_active_insn (insn)))"))
478	 (const_string "false")
479	 (match_test "find_reg_note (insn, REG_SAVE_NOTE, GEN_INT (2))")
480	 (const_string "false")
481	 (eq_attr "iscompact" "maybe") (const_string "true")
482	 ]
483
484	 (if_then_else (eq_attr "length" "2,4")
485		       (const_string "true")
486		       (const_string "false"))))
487
488; must not put an insn inside that refers to blink.
489(define_attr "in_call_delay_slot" "false,true"
490  (cond [(eq_attr "in_delay_slot" "false")
491	 (const_string "false")
492	 (match_test "arc_regno_use_in (RETURN_ADDR_REGNUM, PATTERN (insn))")
493	 (const_string "false")]
494	(const_string "true")))
495
496(define_attr "in_sfunc_delay_slot" "false,true"
497  (cond [(eq_attr "in_call_delay_slot" "false")
498	 (const_string "false")
499	 (match_test "arc_regno_use_in (12, PATTERN (insn))")
500	 (const_string "false")]
501	(const_string "true")))
502
503;; Instructions that we can put into a delay slot and conditionalize.
504(define_attr "cond_delay_insn" "no,yes"
505  (cond [(eq_attr "cond" "!canuse") (const_string "no")
506	 (eq_attr "type" "call,branch,uncond_branch,jump,brcc")
507	 (const_string "no")
508	 (match_test "find_reg_note (insn, REG_SAVE_NOTE, GEN_INT (2))")
509	 (const_string "no")
510	 (eq_attr "length" "2,4") (const_string "yes")]
511	(const_string "no")))
512
513(define_attr "in_ret_delay_slot" "no,yes"
514  (cond [(eq_attr "in_delay_slot" "false")
515	 (const_string "no")
516	 (match_test "regno_clobbered_p
517			(arc_return_address_register
518			  (arc_compute_function_type (cfun)),
519			 insn, SImode, 1)")
520	 (const_string "no")]
521	(const_string "yes")))
522
523(define_attr "cond_ret_delay_insn" "no,yes"
524  (cond [(eq_attr "in_ret_delay_slot" "no") (const_string "no")
525	 (eq_attr "cond_delay_insn" "no") (const_string "no")]
526	(const_string "yes")))
527
528(define_attr "annul_ret_delay_insn" "no,yes"
529  (cond [(eq_attr "cond_ret_delay_insn" "yes") (const_string "yes")
530	 (match_test "TARGET_AT_DBR_CONDEXEC") (const_string "no")
531	 (eq_attr "type" "!call,branch,uncond_branch,jump,brcc,return,sfunc")
532	   (const_string "yes")]
533   (const_string "no")))
534
535
536;; Delay slot definition for ARCompact ISA
537;; ??? FIXME:
538;; When outputting an annul-true insn elegible for cond-exec
539;; in a cbranch delay slot, unless optimizing for size, we use cond-exec
540;; for ARC600; we could also use this for ARC700 if the branch can't be
541;; unaligned and is at least somewhat likely (add parameter for this).
542
543(define_delay (eq_attr "type" "call")
544  [(eq_attr "in_call_delay_slot" "true")
545   (eq_attr "in_call_delay_slot" "true")
546   (nil)])
547
548(define_delay (and (match_test "!TARGET_AT_DBR_CONDEXEC")
549		   (eq_attr "type" "brcc"))
550  [(eq_attr "in_delay_slot" "true")
551   (eq_attr "in_delay_slot" "true")
552   (nil)])
553
554(define_delay (and (match_test "TARGET_AT_DBR_CONDEXEC")
555		   (eq_attr "type" "brcc"))
556  [(eq_attr "in_delay_slot" "true")
557   (nil)
558   (nil)])
559
560(define_delay
561  (eq_attr "type" "return")
562  [(eq_attr "in_ret_delay_slot" "yes")
563   (eq_attr "annul_ret_delay_insn" "yes")
564   (eq_attr "cond_ret_delay_insn" "yes")])
565
566(define_delay (eq_attr "type" "loop_end")
567  [(eq_attr "in_delay_slot" "true")
568   (eq_attr "in_delay_slot" "true")
569   (nil)])
570
571;; For ARC600, unexposing the delay sloy incurs a penalty also in the
572;; non-taken case, so the only meaningful way to have an annull-true
573;; filled delay slot is to conditionalize the delay slot insn.
574(define_delay (and (match_test "TARGET_AT_DBR_CONDEXEC")
575		   (eq_attr "type" "branch,uncond_branch,jump")
576		   (match_test "!optimize_size"))
577  [(eq_attr "in_delay_slot" "true")
578   (eq_attr "cond_delay_insn" "yes")
579   (eq_attr "cond_delay_insn" "yes")])
580
581;; For ARC700, anything goes for annulled-true insns, since there is no
582;; penalty for the unexposed delay slot when the branch is not taken,
583;; however, we must avoid things that have a delay slot themselvese to
584;; avoid confusing gcc.
585(define_delay (and (match_test "!TARGET_AT_DBR_CONDEXEC")
586		   (eq_attr "type" "branch,uncond_branch,jump")
587		   (match_test "!optimize_size"))
588  [(eq_attr "in_delay_slot" "true")
589   (eq_attr "type" "!call,branch,uncond_branch,jump,brcc,return,sfunc")
590   (eq_attr "cond_delay_insn" "yes")])
591
592;; -mlongcall -fpic sfuncs use r12 to load the function address
593(define_delay (eq_attr "type" "sfunc")
594  [(eq_attr "in_sfunc_delay_slot" "true")
595   (eq_attr "in_sfunc_delay_slot" "true")
596   (nil)])
597;; ??? need to use a working strategy for canuse_limm:
598;; - either canuse_limm is not eligible for delay slots, and has no
599;;   delay slots, or arc_reorg has to treat them as nocond, or it has to
600;;   somehow modify them to become inelegible for delay slots if a decision
601;;   is made that makes conditional execution required.
602
603(define_attr "tune" "none,arc600,arc700_4_2_std,arc700_4_2_xmac, core_3"
604  (const
605   (cond [(symbol_ref "arc_tune == TUNE_ARC600")
606	  (const_string "arc600")
607	  (symbol_ref "arc_tune == TUNE_ARC700_4_2_STD")
608	  (const_string "arc700_4_2_std")
609	  (symbol_ref "arc_tune == TUNE_ARC700_4_2_XMAC")
610	  (const_string "arc700_4_2_xmac")
611	  (symbol_ref "arc_tune == ARC_TUNE_CORE_3")
612	  (const_string "core_3")]
613	 (const_string "none"))))
614
615(define_attr "tune_arc700" "false,true"
616  (if_then_else (eq_attr "tune" "arc700_4_2_std, arc700_4_2_xmac")
617		(const_string "true")
618		(const_string "false")))
619
620;; Move instructions.
621(define_expand "movqi"
622  [(set (match_operand:QI 0 "move_dest_operand" "")
623	(match_operand:QI 1 "general_operand" ""))]
624  ""
625  "if (prepare_move_operands (operands, QImode)) DONE;")
626
627; In order to allow the ccfsm machinery to do its work, the leading compact
628; alternatives say 'canuse' - there is another alternative that will match
629; when the condition codes are used.
630; Rcq won't match if the condition is actually used; to avoid a spurious match
631; via q, q is inactivated as constraint there.
632; Likewise, the length of an alternative that might be shifted to conditional
633; execution must reflect this, lest out-of-range branches are created.
634; The iscompact attribute allows the epilogue expander to know for which
635; insns it should lengthen the return insn.
636(define_insn "*movqi_insn"
637  [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   h,w*l,w*l,???w,h,w*l,Rcq,  S,!*x,  r,r, Ucm,m,???m,  m,Usc")
638	(match_operand:QI 1 "move_src_operand"  "  cL,   cP,Rcq#q,    P,hCm1, cL,  I,?Rac,i, ?i,  T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
639  "register_operand (operands[0], QImode)
640   || register_operand (operands[1], QImode)"
641  "@
642   mov%? %0,%1%&
643   mov%? %0,%1%&
644   mov%? %0,%1%&
645   mov%? %0,%1%&
646   mov%? %0,%1%&
647   mov%? %0,%1
648   mov%? %0,%1
649   mov%? %0,%1
650   mov%? %0,%1
651   mov%? %0,%1
652   ldb%? %0,%1%&
653   stb%? %1,%0%&
654   ldb%? %0,%1%&
655   xldb%U1 %0,%1
656   ldb%U1%V1 %0,%1
657   xstb%U0 %1,%0
658   stb%U0%V0 %1,%0
659   stb%U0%V0 %1,%0
660   stb%U0%V0 %1,%0
661   stb%U0%V0 %1,%0"
662  [(set_attr "type" "move,move,move,move,move,move,move,move,move,move,load,store,load,load,load,store,store,store,store,store")
663   (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,false,maybe_limm,false,true,true,true,false,false,false,false,false,false,false")
664   (set_attr "predicable" "yes,no,yes,no,no,yes,no,yes,yes,yes,no,no,no,no,no,no,no,no,no,no")
665   (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
666
667(define_expand "movhi"
668  [(set (match_operand:HI 0 "move_dest_operand" "")
669	(match_operand:HI 1 "general_operand" ""))]
670  ""
671  "if (prepare_move_operands (operands, HImode)) DONE;")
672
673(define_insn "*movhi_insn"
674  [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   h,w*l,w*l,???w,Rcq#q,h,w*l,Rcq,  S,  r,r, Ucm,m,???m,  m,VUsc")
675	(match_operand:HI 1 "move_src_operand" "   cL,   cP,Rcq#q,    P,hCm1, cL,  I,?Rac,    i,i, ?i,  T,Rcq,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
676  "register_operand (operands[0], HImode)
677   || register_operand (operands[1], HImode)
678   || (CONSTANT_P (operands[1])
679       /* Don't use a LIMM that we could load with a single insn - we loose
680	  delay-slot filling opportunities.  */
681       && !satisfies_constraint_I (operands[1])
682       && satisfies_constraint_Usc (operands[0]))"
683  "@
684   mov%? %0,%1%&
685   mov%? %0,%1%&
686   mov%? %0,%1%&
687   mov%? %0,%1%&
688   mov%? %0,%1%&
689   mov%? %0,%1
690   mov%? %0,%1
691   mov%? %0,%1
692   mov%? %0,%1%&
693   mov%? %0,%1
694   mov%? %0,%1
695   ld%_%? %0,%1%&
696   st%_%? %1,%0%&
697   xld%_%U1 %0,%1
698   ld%_%U1%V1 %0,%1
699   xst%_%U0 %1,%0
700   st%_%U0%V0 %1,%0
701   st%_%U0%V0 %1,%0
702   st%_%U0%V0 %1,%0
703   st%_%U0%V0 %1,%0"
704  [(set_attr "type" "move,move,move,move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store,store")
705   (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,false,maybe_limm,maybe_limm,false,true,true,false,false,false,false,false,false,false")
706   (set_attr "predicable" "yes,no,yes,no,no,yes,no,yes,yes,yes,yes,no,no,no,no,no,no,no,no,no")
707   (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,*")])
708
709(define_expand "movsi"
710  [(set (match_operand:SI 0 "move_dest_operand" "")
711	(match_operand:SI 1 "general_operand" ""))]
712  ""
713  "if (prepare_move_operands (operands, SImode)) DONE;")
714
715; In order to allow the ccfsm machinery to do its work, the leading compact
716; alternatives say 'canuse' - there is another alternative that will match
717; when the condition codes are used.
718; Rcq won't match if the condition is actually used; to avoid a spurious match
719; via q, q is inactivated as constraint there.
720; Likewise, the length of an alternative that might be shifted to conditional
721; execution must reflect this, lest out-of-range branches are created.
722; the iscompact attribute allows the epilogue expander to know for which
723; insns it should lengthen the return insn.
724; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc .
725(define_insn "*movsi_insn"                      ;   0     1     2     3    4  5    6   7   8   9   10    11  12  13    14  15   16  17  18     19     20  21  22    23    24 25 26    27 28  29  30   31
726  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   h,w*l,w*l,  w,  w,  w,  w,  ???w, ?w,  w,Rcq#q,  h, w*l,Rcq,  S,   Us<,RcqRck,!*x,  r,!*Rsd,!*Rcd,r,Ucm,  Usd,m,???m,  m,VUsc")
727	(match_operand:SI 1 "move_src_operand"  "  cL,   cP,Rcq#q,    P,hCm1, cL,  I,Crr,Clo,Chi,Cbi,?Rac*l,Cpc,Clb, ?Cal,Cal,?Cal,Uts,Rcq,RcqRck,   Us>,Usd,Ucm,  Usd,  Ucd,m,  w,!*Rzd,c,?Rac,Cm3, C32"))]
728  "register_operand (operands[0], SImode)
729   || register_operand (operands[1], SImode)
730   || (CONSTANT_P (operands[1])
731       /* Don't use a LIMM that we could load with a single insn - we loose
732	  delay-slot filling opportunities.  */
733       && !satisfies_constraint_I (operands[1])
734       && satisfies_constraint_Usc (operands[0]))"
735  "@
736   mov%? %0,%1%&	;0
737   mov%? %0,%1%&	;1
738   mov%? %0,%1%&	;2
739   mov%? %0,%1%&	;3
740   mov%? %0,%1%&	;4
741   mov%? %0,%1		;5
742   mov%? %0,%1		;6
743   ror %0,((%1*2+1) & 0x3f) ;7
744   movl.cl %0,%1	;8
745   movh.cl %0,%L1>>16   ;9
746   * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;10\" : \"movbi.cl %0,%L1 >> 24,24,8;10\";
747   mov%? %0,%1		;11
748   add %0,%1		;12
749   add %0,pcl,%1@pcl    ;13
750   mov%? %0,%j1 	;14
751   mov%? %0,%j1		;15
752   mov%? %0,%j1		;16
753   ld%? %0,%1		;17
754   st%? %1,%0%&		;18
755   * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
756   * return arc_short_long (insn, \"pop%? %0%&\",  \"ld%U1 %0,%1%&\");
757   ld%? %0,%1%&		;21
758   xld%U1 %0,%1		;22
759   ld%? %0,%1%&		;23
760   ld%? %0,%1%&		;24
761   ld%U1%V1 %0,%1	;25
762   xst%U0 %1,%0		;26
763   st%? %1,%0%&		;27
764   st%U0%V0 %1,%0	;28
765   st%U0%V0 %1,%0	;29
766   st%U0%V0 %1,%0	;30
767   st%U0%V0 %1,%0	;31"
768   ;                         0     1     2     3    4    5      6       7           8     9    10     11    12    13           14        15    16   17    18    19   20    21    22   23  24    25    26    27    28    29   30   31
769  [(set_attr "type"       "move, move, move,move,move, move, move,two_cycle_core,shift,shift,shift, move,binary,binary,      move,      move, move,load,store,store,load,load, load,load,load, load,store,store,store,store,store,store")
770   (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,         false,false,false,false,false, false, false,maybe_limm,maybe_limm,false,true, true, true,true,true,false,true,true,false,false, true,false,false,false,false")
771   ; Use default length for iscompact to allow for COND_EXEC.  But set length
772   ; of Crr to 4.
773   (set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,8,8,*,*,*,*,*,*,*,*,4,*,4,*,*,*,*,*,*,8")
774   (set_attr "predicable" "yes,no,yes,no,no,yes,no,no,no,no,no,yes,no,no,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no")
775   (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")])
776
777;; Sometimes generated by the epilogue code.  We don't want to
778;; recognize these addresses in general, because the limm is costly,
779;; and we can't use them for stores.  */
780(define_insn "*movsi_pre_mod"
781  [(set (match_operand:SI 0 "register_operand" "=w")
782	(mem:SI (pre_modify
783		  (reg:SI SP_REG)
784		  (plus:SI (reg:SI SP_REG)
785			   (match_operand 1 "immediate_operand" "Cal")))))]
786  "reload_completed"
787  "ld.a %0,[sp,%1]"
788  [(set_attr "type" "load")
789   (set_attr "length" "8")])
790
791;; Store a value to directly to memory.  The location might also be cached.
792;; Since the cached copy can cause a write-back at unpredictable times,
793;; we first write cached, then we write uncached.
794(define_insn "store_direct"
795  [(set (match_operand:SI 0 "move_dest_operand" "=m")
796      (unspec:SI [(match_operand:SI 1 "register_operand" "c")]
797       UNSPEC_ARC_DIRECT))]
798  ""
799  "st%U0 %1,%0\;st%U0.di %1,%0"
800  [(set_attr "type" "store")])
801
802;; Combiner patterns for compare with zero
803(define_mode_iterator SQH [QI HI])
804(define_mode_attr SQH_postfix [(QI "b") (HI "%_")])
805
806(define_code_iterator SEZ [sign_extend zero_extend])
807(define_code_attr SEZ_prefix [(sign_extend "sex") (zero_extend "ext")])
808
809(define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0_noout"
810  [(set (match_operand 0 "cc_set_register" "")
811	(compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand" "r"))
812		       (const_int 0)))]
813  ""
814  "<SEZ_prefix><SQH_postfix>.f\\t0,%1"
815  [(set_attr "type" "compare")
816   (set_attr "cond" "set_zn")])
817
818(define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0"
819  [(set (match_operand 0 "cc_set_register" "")
820	(compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand" "r"))
821		       (const_int 0)))
822   (set (match_operand:SI 2 "register_operand" "=r")
823	(SEZ:SI (match_dup 1)))]
824  ""
825  "<SEZ_prefix><SQH_postfix>.f\\t%2,%1"
826  [(set_attr "type" "compare")
827   (set_attr "cond" "set_zn")])
828
829(define_insn "*xbfu_cmp0_noout"
830  [(set (match_operand 0 "cc_set_register" "")
831	(compare:CC_Z
832	 (zero_extract:SI
833	  (match_operand:SI 1 "register_operand"  "  r,r")
834	  (match_operand:SI 2 "const_int_operand" "C3p,n")
835	  (match_operand:SI 3 "const_int_operand" "  n,n"))
836	 (const_int 0)))]
837  "TARGET_HS && TARGET_BARREL_SHIFTER"
838  {
839   int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f);
840   operands[2] = GEN_INT (assemble_op2);
841   return "xbfu%?.f\\t0,%1,%2";
842  }
843  [(set_attr "type"       "shift")
844   (set_attr "iscompact"  "false")
845   (set_attr "length"     "4,8")
846   (set_attr "predicable" "no")
847   (set_attr "cond"       "set_zn")])
848
849(define_insn "*xbfu_cmp0"
850  [(set (match_operand 4 "cc_set_register" "")
851	(compare:CC_Z
852	 (zero_extract:SI
853	  (match_operand:SI 1 "register_operand"  "0  ,r,0")
854	  (match_operand:SI 2 "const_int_operand" "C3p,n,n")
855	  (match_operand:SI 3 "const_int_operand" "n  ,n,n"))
856	 (const_int 0)))
857   (set (match_operand:SI 0 "register_operand"  "=r,r,r")
858	(zero_extract:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
859  "TARGET_HS && TARGET_BARREL_SHIFTER"
860  {
861   int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f);
862   operands[2] = GEN_INT (assemble_op2);
863   return "xbfu%?.f\\t%0,%1,%2";
864  }
865  [(set_attr "type"       "shift")
866   (set_attr "iscompact"  "false")
867   (set_attr "length"     "4,8,8")
868   (set_attr "predicable" "yes,no,yes")
869   (set_attr "cond"       "set_zn")])
870
871; splitting to 'tst' allows short insns and combination into brcc.
872(define_insn_and_split "*movsi_set_cc_insn"
873  [(set (match_operand 2 "cc_set_register" "")
874	(match_operator 3 "zn_compare_operator"
875			[(match_operand:SI 1 "nonmemory_operand" "rL,rI,Cal")
876			 (const_int 0)]))
877   (set (match_operand:SI 0 "register_operand" "=r,r,r")
878	(match_dup 1))]
879  ""
880  "mov%?.f\\t%0,%1"
881  "reload_completed && operands_match_p (operands[0], operands[1])"
882  [(set (match_dup 2) (match_dup 3))]
883  ""
884  [(set_attr "type" "compare")
885   (set_attr "predicable" "yes,no,yes")
886   (set_attr "cond" "set_zn")
887   (set_attr "length" "4,4,8")])
888
889(define_insn "unary_comparison"
890  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
891	(match_operator:CC_ZN 3 "zn_compare_operator"
892	  [(match_operator:SI 2 "unary_operator"
893	     [(match_operand:SI 1 "register_operand" "c")])
894	   (const_int 0)]))]
895  ""
896  "%O2.f 0,%1"
897  [(set_attr "type" "compare")
898   (set_attr "cond" "set_zn")])
899
900
901; this pattern is needed by combiner for cases like if (c=(~b)) { ... }
902(define_insn "*unary_comparison_result_used"
903  [(set (match_operand 2 "cc_register" "")
904	(match_operator 4 "zn_compare_operator"
905	  [(match_operator:SI 3 "unary_operator"
906	     [(match_operand:SI 1 "register_operand" "c")])
907	       (const_int 0)]))
908   (set (match_operand:SI 0 "register_operand" "=w")
909	(match_dup 3))]
910  ""
911  "%O3.f %0,%1"
912  [(set_attr "type" "compare")
913   (set_attr "cond" "set_zn")
914   (set_attr "length" "4")])
915
916; reload is too stingy with reloads for Rrq/Cbf/Rrq when it sees
917; a c/???Cal/X alternative, so we say it's c/???Cal/c instead,
918; even if we don't need the clobber.
919(define_insn_and_split "*tst_movb"
920  [(set
921     (match_operand 0 "cc_register" "")
922     (match_operator 4 "zn_compare_operator"
923       [(and:SI
924	  (match_operand:SI 1 "register_operand"  "%Rcq,Rcq, c,  c,  c,  c,Rrq,  3,  c")
925	  (match_operand:SI 2 "nonmemory_operand"  "Rcq,C0p,cI,C1p,Ccp,Chs,Cbf,Cbf,???Cal"))
926	(const_int 0)]))
927   (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,Rrq,Rrq,c"))]
928  "TARGET_NPS_BITOPS"
929  "movb.f.cl %3,%1,%p2,%p2,%s2"
930  "TARGET_NPS_BITOPS && reload_completed
931   && (extract_constrain_insn_cached (insn), (which_alternative & ~1) != 6)"
932  [(set (match_dup 0) (match_dup 4))])
933
934(define_insn "*tst"
935  [(set
936     (match_operand 0 "cc_register" "")
937     (match_operator 3 "zn_compare_operator"
938       [(and:SI
939	  (match_operand:SI 1 "register_operand"
940	   "%Rcq,Rcq, c, c, c,  c,  c,  c")
941	  (match_operand:SI 2 "nonmemory_operand"
942	   " Rcq,C0p,cI,cL,C1p,Ccp,Chs,Cal"))
943	(const_int 0)]))]
944  "reload_completed
945   || !satisfies_constraint_Cbf (operands[2])
946   || satisfies_constraint_C0p (operands[2])
947   || satisfies_constraint_I (operands[2])
948   || satisfies_constraint_C1p (operands[2])
949   || satisfies_constraint_Chs (operands[2])"
950  "*
951    switch (which_alternative)
952    {
953    case 0: case 2: case 3: case 7:
954      return \"tst%? %1,%2\";
955    case 1:
956      return \"btst%? %1,%z2\";
957    case 4:
958      return \"bmsk%?.f 0,%1,%Z2%&\";
959    case 5:
960      return \"bclr%?.f 0,%1,%M2%&\";
961    case 6:
962      return \"asr.f 0,%1,%p2\";
963    default:
964      gcc_unreachable ();
965    }
966  "
967  [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false")
968   (set_attr "type" "compare,compare,compare,compare,compare,compare,shift,compare")
969   (set_attr "length" "*,*,4,4,4,4,4,8")
970   (set_attr "predicable" "no,yes,no,yes,no,no,no,yes")
971   (set_attr "cond" "set_zn")])
972
973; ??? Sometimes, if an AND with a constant can be expressed as a zero_extract,
974; combine will do that and not try the AND.
975
976; It would take 66 constraint combinations to describe the zero_extract
977; constants that are covered by the 12-bit signed constant for tst
978; (excluding the ones that are better done by mov or btst).
979; so we rather use an extra pattern for tst;
980; since this is about constants, reload shouldn't care.
981(define_insn "*tst_bitfield_tst"
982  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
983	(match_operator 4 "zn_compare_operator"
984	  [(zero_extract:SI
985	     (match_operand:SI 1 "register_operand"  "c")
986	     (match_operand:SI 2 "const_int_operand" "n")
987	     (match_operand:SI 3 "const_int_operand" "n"))
988	   (const_int 0)]))]
989  "INTVAL (operands[2]) > 1
990   && (INTVAL (operands[3]) + INTVAL (operands[2]) <= 11
991       || (INTVAL (operands[3]) <= 11
992	   && INTVAL (operands[3]) + INTVAL (operands[2]) == 32))"
993  "tst %1,((1<<%2)-1)<<%3"
994  [(set_attr "type" "compare")
995   (set_attr "cond" "set_zn")
996   (set_attr "length" "4")])
997
998; Likewise for asr.f.
999(define_insn "*tst_bitfield_asr"
1000  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
1001	(match_operator 4 "zn_compare_operator"
1002	  [(zero_extract:SI
1003	     (match_operand:SI 1 "register_operand"  "c")
1004	     (match_operand:SI 2 "const_int_operand" "n")
1005	     (match_operand:SI 3 "const_int_operand" "n"))
1006	   (const_int 0)]))]
1007  "INTVAL (operands[2]) > 1
1008   && INTVAL (operands[3]) + INTVAL (operands[2]) == 32"
1009  "asr.f 0,%1,%3"
1010  [(set_attr "type" "shift")
1011   (set_attr "cond" "set_zn")
1012   (set_attr "length" "4")])
1013
1014(define_insn "*tst_bitfield"
1015  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
1016	(match_operator 5 "zn_compare_operator"
1017	  [(zero_extract:SI
1018	     (match_operand:SI 1 "register_operand" "%Rcqq,c,  c,Rrq,c")
1019	     (match_operand:SI 2 "const_int_operand"    "N,N,  n,Cbn,n")
1020	     (match_operand:SI 3 "const_int_operand"    "n,n,C_0,Cbn,n"))
1021	   (const_int 0)]))
1022   (clobber (match_scratch:SI 4 "=X,X,X,Rrq,X"))]
1023  ""
1024  "@
1025   btst%? %1,%3
1026   btst %1,%3
1027   bmsk.f 0,%1,%2-1
1028   movb.f.cl %4,%1,%3,%3,%2
1029   and.f 0,%1,((1<<%2)-1)<<%3"
1030  [(set_attr "iscompact" "maybe,false,false,false,false")
1031   (set_attr "type" "compare,compare,compare,shift,compare")
1032   (set_attr "cond" "set_zn")
1033   (set_attr "length" "*,4,4,4,8")])
1034
1035;; The next two patterns are for plos, ior, xor, and, and mult.
1036(define_insn "*commutative_binary_cmp0_noout"
1037  [(set (match_operand 0 "cc_set_register" "")
1038	(match_operator 4 "zn_compare_operator"
1039	  [(match_operator:SI 3 "commutative_operator"
1040	     [(match_operand:SI 1 "register_operand" "%r,r")
1041	      (match_operand:SI 2 "nonmemory_operand" "rL,Cal")])
1042	   (const_int 0)]))]
1043  ""
1044  "%O3.f\\t0,%1,%2"
1045  [(set_attr "type" "compare")
1046   (set_attr "cond" "set_zn")
1047   (set_attr "length" "4,8")])
1048
1049(define_insn "*commutative_binary_cmp0"
1050  [(set (match_operand 3 "cc_set_register" "")
1051	(match_operator 5 "zn_compare_operator"
1052	  [(match_operator:SI 4 "commutative_operator"
1053	     [(match_operand:SI 1 "register_operand"  "%0, 0,r,r")
1054	      (match_operand:SI 2 "nonmemory_operand" "rL,rI,r,Cal")])
1055	   (const_int 0)]))
1056   (set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1057	(match_dup 4))]
1058  ""
1059  "%O4.f\\t%0,%1,%2"
1060  [(set_attr "type" "compare")
1061   (set_attr "cond" "set_zn")
1062   (set_attr "predicable" "yes,yes,no,no")
1063   (set_attr "length" "4,4,4,8")])
1064
1065; for flag setting 'add' instructions like if (a+b) { ...}
1066; the combiner needs this pattern
1067(define_insn "*addsi_compare"
1068  [(set (reg:CC_ZN CC_REG)
1069	(compare:CC_ZN (match_operand:SI 0 "register_operand" "c")
1070		       (neg:SI (match_operand:SI 1 "register_operand" "c"))))]
1071  ""
1072  "add.f 0,%0,%1"
1073  [(set_attr "cond" "set")
1074   (set_attr "type" "compare")
1075   (set_attr "length" "4")])
1076
1077; for flag setting 'add' instructions like if (a+b < a) { ...}
1078; the combiner needs this pattern
1079(define_insn "addsi_compare_2"
1080  [(set (reg:CC_C CC_REG)
1081	(compare:CC_C (plus:SI (match_operand:SI 0 "register_operand" "c,c")
1082			       (match_operand:SI 1 "nonmemory_operand" "cL,Cal"))
1083		      (match_dup 0)))]
1084  ""
1085  "add.f 0,%0,%1"
1086  [(set_attr "cond" "set")
1087   (set_attr "type" "compare")
1088   (set_attr "length" "4,8")])
1089
1090(define_insn "*addsi_compare_3"
1091  [(set (reg:CC_C CC_REG)
1092	(compare:CC_C (plus:SI (match_operand:SI 0 "register_operand" "c")
1093			       (match_operand:SI 1 "register_operand" "c"))
1094		      (match_dup 1)))]
1095  ""
1096  "add.f 0,%0,%1"
1097  [(set_attr "cond" "set")
1098   (set_attr "type" "compare")
1099   (set_attr "length" "4")])
1100
1101; this pattern is needed by combiner for cases like if (c=a+b) { ... }
1102(define_insn "*commutative_binary_comparison_result_used"
1103  [(set (match_operand 3 "cc_register" "")
1104	(match_operator 5 "zn_compare_operator"
1105	  ; We can accept any commutative operator except mult because
1106	  ; our 'w' class below could try to use LP_COUNT.
1107	  [(match_operator:SI 4 "commutative_operator_sans_mult"
1108	     [(match_operand:SI 1 "register_operand" "c,0,c")
1109	      (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
1110	   (const_int 0)]))
1111   (set (match_operand:SI 0 "register_operand" "=w,w,w")
1112	(match_dup 4))]
1113  ""
1114  "%O4.f %0,%1,%2 ; non-mult commutative"
1115  [(set_attr "type" "compare,compare,compare")
1116   (set_attr "cond" "set_zn,set_zn,set_zn")
1117   (set_attr "length" "4,4,8")])
1118
1119; a MULT-specific version of this pattern to avoid touching the
1120; LP_COUNT register
1121(define_insn "*commutative_binary_mult_comparison_result_used"
1122  [(set (match_operand 3 "cc_register" "")
1123	(match_operator 5 "zn_compare_operator"
1124	  [(match_operator:SI 4 "mult_operator"
1125	     [(match_operand:SI 1 "register_operand" "c,0,c")
1126	      (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
1127	   (const_int 0)]))
1128	; Make sure to use the W class to not touch LP_COUNT.
1129   (set (match_operand:SI 0 "register_operand" "=W,W,W")
1130	(match_dup 4))]
1131  "!TARGET_ARC600_FAMILY"
1132  "%O4.f %0,%1,%2 ; mult commutative"
1133  [(set_attr "type" "compare,compare,compare")
1134   (set_attr "cond" "set_zn,set_zn,set_zn")
1135   (set_attr "length" "4,4,8")])
1136
1137(define_insn "*noncommutative_binary_cmp0"
1138  [(set (match_operand 3 "cc_set_register" "")
1139	(match_operator 5 "zn_compare_operator"
1140	  [(match_operator:SI 4 "noncommutative_operator"
1141	     [(match_operand:SI 1 "register_operand"   "0,r,0,  0,r")
1142	      (match_operand:SI 2 "nonmemory_operand" "rL,r,I,Cal,Cal")])
1143	   (const_int 0)]))
1144   (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
1145	(match_dup 4))]
1146  ""
1147  "%O4%?.f\\t%0,%1,%2"
1148  [(set_attr "type" "compare")
1149   (set_attr "cond" "set_zn")
1150   (set_attr "predicable" "yes,no,no,yes,no")
1151   (set_attr "length" "4,4,4,8,8")])
1152
1153(define_insn "*noncommutative_binary_cmp0_noout"
1154  [(set (match_operand 0 "cc_set_register" "")
1155	(match_operator 3 "zn_compare_operator"
1156	  [(match_operator:SI 4 "noncommutative_operator"
1157	     [(match_operand:SI 1 "register_operand"   "r,r")
1158	      (match_operand:SI 2 "nonmemory_operand" "rL,Cal")])
1159	   (const_int 0)]))]
1160  ""
1161  "%O4.f\\t0,%1,%2"
1162  [(set_attr "type" "compare")
1163   (set_attr "cond" "set_zn")
1164   (set_attr "length" "4,8")])
1165
1166;;rsub variants
1167(define_insn "*rsub_cmp0"
1168  [(set (match_operand 4 "cc_set_register" "")
1169	(match_operator 3 "zn_compare_operator"
1170	  [(minus:SI
1171	    (match_operand:SI 1 "nonmemory_operand" "rL,Cal")
1172	    (match_operand:SI 2 "register_operand"   "r,r"))
1173	   (const_int 0)]))
1174   (set (match_operand:SI 0 "register_operand" "=r,r")
1175	(minus:SI (match_dup 1) (match_dup 2)))]
1176  ""
1177  "rsub.f\\t%0,%2,%1"
1178  [(set_attr "type" "compare")
1179   (set_attr "cond" "set_zn")
1180   (set_attr "length" "4,8")])
1181
1182(define_insn "*rsub_cmp0_noout"
1183  [(set (match_operand 0 "cc_set_register" "")
1184	(match_operator 3 "zn_compare_operator"
1185	  [(minus:SI
1186	    (match_operand:SI 1 "nonmemory_operand" "rL,Cal")
1187	    (match_operand:SI 2 "register_operand"   "r,r"))
1188	   (const_int 0)]))]
1189  ""
1190  "rsub.f\\t0,%2,%1"
1191  [(set_attr "type" "compare")
1192   (set_attr "cond" "set_zn")
1193   (set_attr "length" "4,8")])
1194
1195(define_expand "bic_f_zn"
1196  [(parallel
1197     [(set (reg:CC_ZN CC_REG)
1198	   (compare:CC_ZN
1199	     (and:SI (match_operand:SI 1 "register_operand" "")
1200		     (not:SI (match_operand:SI 2 "nonmemory_operand" "")))
1201	   (const_int 0)))
1202      (set (match_operand:SI 0 "register_operand" "")
1203	   (and:SI (match_dup 1) (not:SI (match_dup 2))))])]
1204  "")
1205
1206(define_insn "*bic_f"
1207  [(set (match_operand 3 "cc_register" "=Rcc,Rcc,Rcc")
1208	(match_operator 4 "zn_compare_operator"
1209	  [(and:SI (match_operand:SI 1 "register_operand" "c,0,c")
1210		   (not:SI
1211		     (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")))
1212	   (const_int 0)]))
1213   (set (match_operand:SI 0 "register_operand" "=w,w,w")
1214	(and:SI (match_dup 1) (not:SI (match_dup 2))))]
1215  ""
1216  "bic.f %0,%1,%2"
1217  [(set_attr "type" "compare,compare,compare")
1218   (set_attr "cond" "set_zn,set_zn,set_zn")
1219   (set_attr "length" "4,4,8")])
1220
1221(define_expand "movdi"
1222  [(set (match_operand:DI 0 "move_dest_operand" "")
1223	(match_operand:DI 1 "general_operand" ""))]
1224  ""
1225  "
1226  if (prepare_move_operands (operands, DImode))
1227    DONE;
1228  ")
1229
1230(define_insn_and_split "*movdi_insn"
1231  [(set (match_operand:DI 0 "move_dest_operand"      "=w, w,r,m")
1232	(match_operand:DI 1 "move_double_src_operand" "c,Hi,m,c"))]
1233  "register_operand (operands[0], DImode)
1234   || register_operand (operands[1], DImode)"
1235  "*
1236{
1237  switch (which_alternative)
1238    {
1239    default:
1240      return \"#\";
1241
1242    case 2:
1243    if (TARGET_LL64
1244	&& ((even_register_operand (operands[0], DImode)
1245	     && memory_operand (operands[1], DImode))
1246	    || (memory_operand (operands[0], DImode)
1247	        && even_register_operand (operands[1], DImode))))
1248      return \"ldd%U1%V1 %0,%1%&\";
1249    return \"#\";
1250
1251    case 3:
1252    if (TARGET_LL64
1253	&& ((even_register_operand (operands[0], DImode)
1254	     && memory_operand (operands[1], DImode))
1255	    || (memory_operand (operands[0], DImode)
1256	        && even_register_operand (operands[1], DImode))))
1257     return \"std%U0%V0 %1,%0\";
1258    return \"#\";
1259    }
1260}"
1261  "reload_completed"
1262  [(const_int 0)]
1263  {
1264   arc_split_move (operands);
1265   DONE;
1266  }
1267  [(set_attr "type" "move,move,load,store")
1268   ;; ??? The ld/st values could be 4 if it's [reg,bignum].
1269   (set_attr "length" "8,16,*,*")])
1270
1271
1272;; Floating point move insns.
1273
1274(define_expand "movsf"
1275  [(set (match_operand:SF 0 "move_dest_operand" "")
1276	(match_operand:SF 1 "general_operand" ""))]
1277  ""
1278  "if (prepare_move_operands (operands, SFmode)) DONE;")
1279
1280(define_insn "*movsf_insn"
1281  [(set (match_operand:SF 0 "move_dest_operand"    "=h,w,w,r,m")
1282	(match_operand:SF 1 "move_src_operand"   "hCm1,c,E,m,c"))]
1283  "register_operand (operands[0], SFmode)
1284   || register_operand (operands[1], SFmode)"
1285  "@
1286   mov%? %0,%1
1287   mov%? %0,%1
1288   mov%? %0,%1 ; %A1
1289   ld%U1%V1 %0,%1
1290   st%U0%V0 %1,%0"
1291  [(set_attr "type" "move,move,move,load,store")
1292   (set_attr "predicable" "no,yes,yes,no,no")
1293   (set_attr "iscompact" "true,false,false,false,false")])
1294
1295(define_expand "movdf"
1296  [(set (match_operand:DF 0 "move_dest_operand" "")
1297	(match_operand:DF 1 "general_operand" ""))]
1298  ""
1299  "if (prepare_move_operands (operands, DFmode)) DONE;")
1300
1301(define_insn_and_split "*movdf_insn"
1302  [(set (match_operand:DF 0 "move_dest_operand"      "=D,r,c,c,r,m")
1303	(match_operand:DF 1 "move_double_src_operand" "r,D,c,E,m,c"))]
1304  "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)"
1305  "*
1306{
1307 switch (which_alternative)
1308   {
1309    default:
1310      return \"#\";
1311    case 4:
1312    if (TARGET_LL64
1313	&& ((even_register_operand (operands[0], DFmode)
1314	     && memory_operand (operands[1], DFmode))
1315	    || (memory_operand (operands[0], DFmode)
1316	        && even_register_operand (operands[1], DFmode))))
1317      return \"ldd%U1%V1 %0,%1%&\";
1318    return \"#\";
1319
1320    case 5:
1321    if (TARGET_LL64
1322	&& ((even_register_operand (operands[0], DFmode)
1323	     && memory_operand (operands[1], DFmode))
1324	    || (memory_operand (operands[0], DFmode)
1325		&& even_register_operand (operands[1], DFmode))))
1326     return \"std%U0%V0 %1,%0\";
1327    return \"#\";
1328   }
1329}"
1330  "reload_completed"
1331  [(const_int 0)]
1332  {
1333   arc_split_move (operands);
1334   DONE;
1335  }
1336  [(set_attr "type" "move,move,move,move,load,store")
1337   (set_attr "predicable" "no,no,yes,yes,no,no")
1338   ;; ??? The ld/st values could be 16 if it's [reg,bignum].
1339   (set_attr "length" "4,16,8,16,16,16")])
1340
1341(define_insn_and_split "*movdf_insn_nolrsr"
1342  [(set (match_operand:DF 0 "register_operand"       "=r")
1343	(match_operand:DF 1 "arc_double_register_operand" "D"))
1344   (use (match_operand:SI 2 "" "N")) ; aka const1_rtx
1345   ]
1346  "TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR"
1347  "#"
1348  "&& 1"
1349  [
1350    ; mov r0, 0
1351    (set (match_dup 0) (match_dup 3))
1352
1353    ; daddh?? r1, r0, r0
1354    (parallel [
1355    	(set (match_dup 1) (plus:DF (match_dup 1) (match_dup 0)))
1356    	(use (const_int 1))
1357    	(use (const_int 1))
1358	(use (match_dup 0)) ; used to block can_combine_p
1359    	(set (match_dup 0) (plus:DF (match_dup 1) (match_dup 0))) ; r1 in op 0
1360    ])
1361
1362    ; We have to do this twice, once to read the value into R0 and
1363    ; second time to put back the contents which the first DEXCLx
1364    ; will have overwritten
1365    ; dexcl2 r0, r1, r0
1366    (parallel [
1367	       (set (match_dup 4) ; aka r0result
1368				  ; aka DF, r1, r0
1369		    (unspec_volatile:SI [(match_dup 5) (match_dup 4)]
1370					VUNSPEC_ARC_DEXCL))
1371	       (clobber (match_dup 1))
1372	       ])
1373    ; Generate the second, which makes sure operand5 and operand4 values
1374    ; are put back in the Dx register properly.
1375    (set (match_dup 1) (unspec_volatile:DF
1376			[(match_dup 5) (match_dup 4)]
1377			VUNSPEC_ARC_DEXCL_NORES))
1378
1379    ; Note: we cannot use a (clobber (match_scratch)) here because
1380    ; the combine pass will end up replacing uses of it with 0
1381  ]
1382  "operands[3] = CONST0_RTX (DFmode);
1383   operands[4] = simplify_gen_subreg (SImode, operands[0], DFmode, 0);
1384   operands[5] = simplify_gen_subreg (SImode, operands[0], DFmode, 4);"
1385  [(set_attr "type" "move")])
1386
1387;; Load/Store with update instructions.
1388;;
1389;; Some of these we can get by using pre-decrement or pre-increment, but the
1390;; hardware can also do cases where the increment is not the size of the
1391;; object.
1392;;
1393;; In all these cases, we use operands 0 and 1 for the register being
1394;; incremented because those are the operands that local-alloc will
1395;; tie and these are the pair most likely to be tieable (and the ones
1396;; that will benefit the most).
1397;;
1398;; We use match_operator here because we need to know whether the memory
1399;; object is volatile or not.
1400
1401
1402;; Note: loadqi_update has no 16-bit variant
1403(define_insn "*loadqi_update"
1404  [(set (match_operand:QI 3 "dest_reg_operand" "=r,r")
1405        (match_operator:QI 4 "any_mem_operand"
1406         [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1407                   (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
1408   (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1409	(plus:SI (match_dup 1) (match_dup 2)))]
1410  ""
1411  "ldb.a%V4 %3,[%0,%2]"
1412  [(set_attr "type" "load,load")
1413   (set_attr "length" "4,8")])
1414
1415(define_insn "*load_zeroextendqisi_update"
1416  [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1417	(zero_extend:SI (match_operator:QI 4 "any_mem_operand"
1418			 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1419			           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
1420   (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1421	(plus:SI (match_dup 1) (match_dup 2)))]
1422  ""
1423  "ldb.a%V4 %3,[%0,%2]"
1424  [(set_attr "type" "load,load")
1425   (set_attr "length" "4,8")])
1426
1427(define_insn "*load_signextendqisi_update"
1428  [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1429	(sign_extend:SI (match_operator:QI 4 "any_mem_operand"
1430			 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1431			           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
1432   (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1433	(plus:SI (match_dup 1) (match_dup 2)))]
1434  ""
1435  "ldb.x.a%V4 %3,[%0,%2]"
1436  [(set_attr "type" "load,load")
1437   (set_attr "length" "4,8")])
1438
1439(define_insn "*storeqi_update"
1440  [(set (match_operator:QI 4 "any_mem_operand"
1441	 [(plus:SI (match_operand:SI 1 "register_operand" "0")
1442	           (match_operand:SI 2 "short_immediate_operand" "I"))])
1443	(match_operand:QI 3 "register_operand" "c"))
1444   (set (match_operand:SI 0 "dest_reg_operand" "=w")
1445	(plus:SI (match_dup 1) (match_dup 2)))]
1446  ""
1447  "stb.a%V4 %3,[%0,%2]"
1448  [(set_attr "type" "store")
1449   (set_attr "length" "4")])
1450
1451;; ??? pattern may have to be re-written
1452;; Note: no 16-bit variant for this pattern
1453(define_insn "*loadhi_update"
1454  [(set (match_operand:HI 3 "dest_reg_operand" "=r,r")
1455	(match_operator:HI 4 "any_mem_operand"
1456	 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1457	           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
1458   (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1459	(plus:SI (match_dup 1) (match_dup 2)))]
1460  ""
1461  "ld%_.a%V4 %3,[%0,%2]"
1462  [(set_attr "type" "load,load")
1463   (set_attr "length" "4,8")])
1464
1465(define_insn "*load_zeroextendhisi_update"
1466  [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1467	(zero_extend:SI (match_operator:HI 4 "any_mem_operand"
1468			 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1469			           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
1470   (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1471	(plus:SI (match_dup 1) (match_dup 2)))]
1472  ""
1473  "ld%_.a%V4 %3,[%0,%2]"
1474  [(set_attr "type" "load,load")
1475   (set_attr "length" "4,8")])
1476
1477;; Note: no 16-bit variant for this instruction
1478(define_insn "*load_signextendhisi_update"
1479  [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1480	(sign_extend:SI (match_operator:HI 4 "any_mem_operand"
1481			 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1482			           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
1483   (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1484	(plus:SI (match_dup 1) (match_dup 2)))]
1485  ""
1486  "ld%_.x.a%V4 %3,[%0,%2]"
1487  [(set_attr "type" "load,load")
1488   (set_attr "length" "4,8")])
1489
1490(define_insn "*storehi_update"
1491  [(set (match_operator:HI 4 "any_mem_operand"
1492	 [(plus:SI (match_operand:SI 1 "register_operand" "0")
1493	           (match_operand:SI 2 "short_immediate_operand" "I"))])
1494	(match_operand:HI 3 "register_operand" "c"))
1495   (set (match_operand:SI 0 "dest_reg_operand" "=w")
1496	(plus:SI (match_dup 1) (match_dup 2)))]
1497  ""
1498  "st%_.a%V4 %3,[%0,%2]"
1499  [(set_attr "type" "store")
1500   (set_attr "length" "4")])
1501
1502;; No 16-bit variant for this instruction pattern
1503(define_insn "*loadsi_update"
1504  [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1505	(match_operator:SI 4 "any_mem_operand"
1506	 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1507	           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
1508   (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1509	(plus:SI (match_dup 1) (match_dup 2)))]
1510  ""
1511  "ld.a%V4 %3,[%0,%2]"
1512  [(set_attr "type" "load,load")
1513   (set_attr "length" "4,8")])
1514
1515(define_insn "*storesi_update"
1516  [(set (match_operator:SI 4 "any_mem_operand"
1517	 [(plus:SI (match_operand:SI 1 "register_operand" "0")
1518	           (match_operand:SI 2 "short_immediate_operand" "I"))])
1519	(match_operand:SI 3 "register_operand" "c"))
1520   (set (match_operand:SI 0 "dest_reg_operand" "=w")
1521	(plus:SI (match_dup 1) (match_dup 2)))]
1522  ""
1523  "st.a%V4 %3,[%0,%2]"
1524  [(set_attr "type" "store")
1525   (set_attr "length" "4")])
1526
1527(define_insn "*loadsf_update"
1528  [(set (match_operand:SF 3 "dest_reg_operand" "=r,r")
1529	(match_operator:SF 4 "any_mem_operand"
1530	 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1531	           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
1532   (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1533	(plus:SI (match_dup 1) (match_dup 2)))]
1534  ""
1535  "ld.a%V4 %3,[%0,%2]"
1536  [(set_attr "type" "load,load")
1537   (set_attr "length" "4,8")])
1538
1539(define_insn "*storesf_update"
1540  [(set (match_operator:SF 4 "any_mem_operand"
1541	 [(plus:SI (match_operand:SI 1 "register_operand" "0")
1542	           (match_operand:SI 2 "short_immediate_operand" "I"))])
1543	(match_operand:SF 3 "register_operand" "c"))
1544   (set (match_operand:SI 0 "dest_reg_operand" "=w")
1545	(plus:SI (match_dup 1) (match_dup 2)))]
1546  ""
1547  "st.a%V4 %3,[%0,%2]"
1548  [(set_attr "type" "store")
1549   (set_attr "length" "4")])
1550
1551;; Conditional move instructions.
1552
1553(define_expand "movsicc"
1554  [(set (match_operand:SI 0 "dest_reg_operand" "")
1555	(if_then_else:SI (match_operand 1 "comparison_operator" "")
1556		         (match_operand:SI 2 "nonmemory_operand" "")
1557 		         (match_operand:SI 3 "register_operand" "")))]
1558  ""
1559  "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1560
1561
1562(define_expand "movdicc"
1563  [(set (match_operand:DI 0 "dest_reg_operand" "")
1564	(if_then_else:DI(match_operand 1 "comparison_operator" "")
1565		        (match_operand:DI 2 "nonmemory_operand" "")
1566		        (match_operand:DI 3 "register_operand" "")))]
1567  ""
1568  "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1569
1570
1571(define_expand "movsfcc"
1572  [(set (match_operand:SF 0 "dest_reg_operand" "")
1573	(if_then_else:SF (match_operand 1 "comparison_operator" "")
1574		      (match_operand:SF 2 "nonmemory_operand" "")
1575		      (match_operand:SF 3 "register_operand" "")))]
1576  ""
1577  "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1578
1579(define_expand "movdfcc"
1580  [(set (match_operand:DF 0 "dest_reg_operand" "")
1581	(if_then_else:DF (match_operand 1 "comparison_operator" "")
1582		      (match_operand:DF 2 "nonmemory_operand" "")
1583		      (match_operand:DF 3 "register_operand" "")))]
1584  ""
1585  "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1586
1587(define_insn "*movsicc_insn"
1588  [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1589  	(if_then_else:SI (match_operator 3 "proper_comparison_operator"
1590  		       [(match_operand 4 "cc_register" "") (const_int 0)])
1591  		      (match_operand:SI 1 "nonmemory_operand" "cL,Cal")
1592  		      (match_operand:SI 2 "register_operand" "0,0")))]
1593  ""
1594{
1595  if (rtx_equal_p (operands[1], const0_rtx) && GET_CODE (operands[3]) == NE
1596      && satisfies_constraint_Rcq (operands[0]))
1597    return "sub%?.ne %0,%0,%0";
1598  /* ??? might be good for speed on ARC600 too, *if* properly scheduled.  */
1599  if ((optimize_size && (!TARGET_ARC600_FAMILY))
1600      && rtx_equal_p (operands[1], constm1_rtx)
1601      && GET_CODE (operands[3]) == LTU)
1602    return "sbc.cs %0,%0,%0";
1603  return "mov.%d3 %0,%1";
1604}
1605  [(set_attr "type" "cmove,cmove")
1606   (set_attr "length" "4,8")])
1607
1608;; When there's a mask of a single bit, and then a compare to 0 or 1,
1609;; if the single bit is the sign bit, then GCC likes to convert this
1610;; into a sign extend and a compare less than, or greater to zero.
1611;; This is usually fine, except for the NXP400 where we have access to
1612;; a bit test instruction, along with a special short load instruction
1613;; (from CMEM), that doesn't support sign-extension on load.
1614;;
1615;; This peephole optimisation attempts to restore the use of bit-test
1616;; in those cases where it is useful to do so.
1617(define_peephole2
1618  [(set (match_operand:SI 0 "register_operand" "")
1619		(sign_extend:SI
1620		(match_operand:QI 1 "any_mem_operand" "")))
1621   (set (reg:CC_ZN CC_REG)
1622	(compare:CC_ZN (match_dup 0)
1623		       (const_int 0)))
1624   (set (pc)
1625	(if_then_else (match_operator 2 "ge_lt_comparison_operator"
1626		       [(reg:CC_ZN CC_REG) (const_int 0)])
1627		      (match_operand 3 "" "")
1628		      (match_operand 4 "" "")))]
1629  "TARGET_NPS_CMEM
1630   && cmem_address (XEXP (operands[1], 0), SImode)
1631   && peep2_reg_dead_p (2, operands[0])
1632   && peep2_regno_dead_p (3, CC_REG)"
1633  [(set (match_dup 0)
1634	(zero_extend:SI
1635	(match_dup 1)))
1636   (set (reg:CC_ZN CC_REG)
1637	(compare:CC_ZN (zero_extract:SI
1638			 (match_dup 0)
1639			 (const_int 1)
1640			 (const_int 7))
1641		       (const_int 0)))
1642   (set (pc)
1643	(if_then_else (match_dup 2)
1644		      (match_dup 3)
1645		      (match_dup 4)))]
1646  "if (GET_CODE (operands[2]) == GE)
1647     operands[2] = gen_rtx_EQ (VOIDmode, gen_rtx_REG (CC_ZNmode, 61), const0_rtx);
1648   else
1649     operands[2] = gen_rtx_NE (VOIDmode, gen_rtx_REG (CC_ZNmode, 61), const0_rtx);")
1650
1651; Try to generate more short moves, and/or less limms, by substituting a
1652; conditional move with a conditional sub.
1653(define_peephole2
1654  [(set (match_operand:SI 0 "compact_register_operand")
1655	(match_operand:SI 1 "const_int_operand"))
1656   (set (match_dup 0)
1657  	(if_then_else:SI (match_operator 3 "proper_comparison_operator"
1658			   [(match_operand 4 "cc_register" "") (const_int 0)])
1659			    (match_operand:SI 2 "const_int_operand" "")
1660  		      (match_dup 0)))]
1661  "!satisfies_constraint_P (operands[1])
1662   && satisfies_constraint_P (operands[2])
1663   && UNSIGNED_INT6 (INTVAL (operands[2]) - INTVAL (operands[1]))"
1664  [(set (match_dup 0) (match_dup 2))
1665   (cond_exec
1666     (match_dup 3)
1667     (set (match_dup 0)
1668	  (plus:SI (match_dup 0) (match_dup 1))))]
1669  "operands[3] = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[3]),
1670						    GET_MODE (operands[4])),
1671				 VOIDmode, operands[4], const0_rtx);
1672   operands[1] = GEN_INT (INTVAL (operands[1]) - INTVAL (operands[2]));")
1673
1674(define_insn "*movdicc_insn"
1675  [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w")
1676	(if_then_else:DI (match_operator 3 "proper_comparison_operator"
1677			[(match_operand 4 "cc_register" "") (const_int 0)])
1678		      (match_operand:DI 1 "nonmemory_operand" "c,i")
1679		      (match_operand:DI 2 "register_operand" "0,0")))]
1680   ""
1681   "*
1682{
1683   switch (which_alternative)
1684     {
1685     default:
1686     case 0 :
1687       /* We normally copy the low-numbered register first.  However, if
1688 	 the first register operand 0 is the same as the second register of
1689 	 operand 1, we must copy in the opposite order.  */
1690       if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
1691 	return \"mov.%d3 %R0,%R1\;mov.%d3 %0,%1\";
1692       else
1693 	return \"mov.%d3 %0,%1\;mov.%d3 %R0,%R1\";
1694     case 1 :
1695	return \"mov.%d3 %L0,%L1\;mov.%d3 %H0,%H1\";
1696
1697
1698     }
1699}"
1700  [(set_attr "type" "cmove,cmove")
1701   (set_attr "length" "8,16")])
1702
1703
1704(define_insn "*movsfcc_insn"
1705  [(set (match_operand:SF 0 "dest_reg_operand" "=w,w")
1706	(if_then_else:SF (match_operator 3 "proper_comparison_operator"
1707		       [(match_operand 4 "cc_register" "") (const_int 0)])
1708		      (match_operand:SF 1 "nonmemory_operand" "c,E")
1709		      (match_operand:SF 2 "register_operand" "0,0")))]
1710  ""
1711  "@
1712   mov.%d3 %0,%1
1713   mov.%d3 %0,%1 ; %A1"
1714  [(set_attr "type" "cmove,cmove")])
1715
1716(define_insn "*movdfcc_insn"
1717  [(set (match_operand:DF 0 "dest_reg_operand" "=w,w")
1718	(if_then_else:DF (match_operator 1 "proper_comparison_operator"
1719		 [(match_operand 4 "cc_register" "") (const_int 0)])
1720		      (match_operand:DF 2 "nonmemory_operand" "c,E")
1721		      (match_operand:DF 3 "register_operand" "0,0")))]
1722  ""
1723  "*
1724{
1725  switch (which_alternative)
1726    {
1727    default:
1728    case 0 :
1729      /* We normally copy the low-numbered register first.  However, if
1730	 the first register operand 0 is the same as the second register of
1731	 operand 1, we must copy in the opposite order.  */
1732      if (REGNO (operands[0]) == REGNO (operands[2]) + 1)
1733	return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\";
1734      else
1735	return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\";
1736    case 1 :
1737	      return \"mov.%d1 %L0,%L2\;mov.%d1 %H0,%H2; %A2 \";
1738
1739    }
1740}"
1741  [(set_attr "type" "cmove,cmove")
1742   (set_attr "length" "8,16")])
1743
1744
1745(define_insn "*zero_extendqihi2_i"
1746  [(set (match_operand:HI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,r,r")
1747	(zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,Ucm,m")))]
1748  ""
1749  "@
1750   extb%? %0,%1%&
1751   extb%? %0,%1%&
1752   bmsk%? %0,%1,7
1753   extb %0,%1
1754   xldb%U1 %0,%1
1755   ldb%U1 %0,%1"
1756  [(set_attr "type" "unary,unary,unary,unary,load,load")
1757   (set_attr "iscompact" "maybe,true,false,false,false,false")
1758   (set_attr "predicable" "no,no,yes,no,no,no")])
1759
1760(define_expand "zero_extendqihi2"
1761  [(set (match_operand:HI 0 "dest_reg_operand" "")
1762	(zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1763  ""
1764  "if (prepare_extend_operands (operands, ZERO_EXTEND, HImode)) DONE;"
1765)
1766
1767(define_insn "*zero_extendqisi2_ac"
1768  [(set (match_operand:SI 0 "dest_reg_operand"    "=Rcq,Rcq#q,Rcw,w,qRcq,!*x,r,r")
1769	(zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,T,Usd,Ucm,m")))]
1770  ""
1771  "@
1772   extb%? %0,%1%&
1773   extb%? %0,%1%&
1774   bmsk%? %0,%1,7
1775   extb %0,%1
1776   ldb%? %0,%1%&
1777   ldb%? %0,%1%&
1778   xldb%U1 %0,%1
1779   ldb%U1 %0,%1"
1780  [(set_attr "type" "unary,unary,unary,unary,load,load,load,load")
1781   (set_attr "iscompact" "maybe,true,false,false,true,true,false,false")
1782   (set_attr "predicable" "no,no,yes,no,no,no,no,no")])
1783
1784(define_expand "zero_extendqisi2"
1785  [(set (match_operand:SI 0 "dest_reg_operand" "")
1786	(zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1787  ""
1788  "if (prepare_extend_operands (operands, ZERO_EXTEND, SImode)) DONE;"
1789)
1790
1791(define_insn "*zero_extendhisi2_i"
1792  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,q,Rcw,w,!x,Rcqq,r,r")
1793	(zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "0,q,0,c,Usd,T,Ucm,m")))]
1794  ""
1795  "@
1796   ext%_%? %0,%1%&
1797   ext%_%? %0,%1%&
1798   bmsk%? %0,%1,15
1799   ext%_ %0,%1
1800   ld%_%? %0,%1
1801   ld%_%? %0,%1
1802   * return TARGET_EM ? \"xldh%U1%V1 %0,%1\" : \"xldw%U1 %0,%1\";
1803   ld%_%U1%V1 %0,%1"
1804  [(set_attr "type" "unary,unary,unary,unary,load,load,load,load")
1805   (set_attr "iscompact" "maybe,true,false,false,true,true,false,false")
1806   (set_attr "predicable" "no,no,yes,no,no,no,no,no")])
1807
1808
1809(define_expand "zero_extendhisi2"
1810  [(set (match_operand:SI 0 "dest_reg_operand" "")
1811	(zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "")))]
1812  ""
1813  "if (prepare_extend_operands (operands, ZERO_EXTEND, SImode)) DONE;"
1814)
1815
1816;; Sign extension instructions.
1817
1818(define_insn "*extendqihi2_i"
1819  [(set (match_operand:HI 0 "dest_reg_operand" "=Rcqq,r,r,r")
1820	(sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,r,Uex,m")))]
1821  ""
1822  "@
1823   sexb%? %0,%1%&
1824   sexb %0,%1
1825   ldb.x%U1 %0,%1
1826   ldb.x%U1 %0,%1"
1827  [(set_attr "type" "unary,unary,load,load")
1828   (set_attr "iscompact" "true,false,false,false")
1829   (set_attr "length" "*,*,*,8")])
1830
1831
1832(define_expand "extendqihi2"
1833  [(set (match_operand:HI 0 "dest_reg_operand" "")
1834	(sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1835  ""
1836  "if (prepare_extend_operands (operands, SIGN_EXTEND, HImode)) DONE;"
1837)
1838
1839(define_insn "*extendqisi2_ac"
1840  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r,r")
1841	(sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,c,Uex,m")))]
1842  ""
1843  "@
1844   sexb%? %0,%1%&
1845   sexb %0,%1
1846   ldb.x%U1 %0,%1
1847   ldb.x%U1 %0,%1"
1848  [(set_attr "type" "unary,unary,load,load")
1849   (set_attr "iscompact" "true,false,false,false")
1850   (set_attr "length" "*,*,*,8")])
1851
1852(define_expand "extendqisi2"
1853  [(set (match_operand:SI 0 "dest_reg_operand" "")
1854	(sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1855  ""
1856  "if (prepare_extend_operands (operands, SIGN_EXTEND, SImode)) DONE;"
1857)
1858
1859(define_insn "*extendhisi2_i"
1860  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,Rcqq,r,r")
1861	(sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,Ucd,Uex,m")))]
1862  ""
1863  "@
1864   sex%_%? %0,%1%&
1865   sex%_ %0,%1
1866   ldh%?.x %0,%1%&
1867   ld%_.x%U1%V1 %0,%1
1868   ld%_.x%U1%V1 %0,%1"
1869  [(set_attr "type" "unary,unary,load,load,load")
1870   (set_attr "iscompact" "true,false,true,false,false")
1871   (set_attr "length" "*,*,*,4,8")])
1872
1873(define_expand "extendhisi2"
1874  [(set (match_operand:SI 0 "dest_reg_operand" "")
1875	(sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "")))]
1876  ""
1877  "if (prepare_extend_operands (operands, SIGN_EXTEND, SImode)) DONE;"
1878)
1879
1880;; Unary arithmetic insns
1881
1882;; We allow constant operands to enable late constant propagation, but it is
1883;; not worth while to have more than one dedicated alternative to output them -
1884;; if we are really worried about getting these the maximum benefit of all
1885;; the available alternatives, we should add an extra pass to fold such
1886;; operations to movsi.
1887
1888;; Absolute instructions
1889
1890(define_insn "*abssi2_mixed"
1891  [(set (match_operand:SI 0 "compact_register_operand" "=q")
1892	(abs:SI (match_operand:SI 1 "compact_register_operand" "q")))]
1893  "TARGET_MIXED_CODE"
1894  "abs%? %0,%1%&"
1895  [(set_attr "type" "two_cycle_core")
1896   (set_attr "iscompact" "true")])
1897
1898(define_insn "abssi2"
1899  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,w,w")
1900	(abs:SI (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,Cal")))]
1901  ""
1902  "abs%? %0,%1%&"
1903  [(set_attr "type" "two_cycle_core")
1904   (set_attr "length" "*,4,8")
1905   (set_attr "iscompact" "true,false,false")])
1906
1907;; Maximum and minimum insns
1908
1909(define_insn "smaxsi3"
1910   [(set (match_operand:SI 0 "dest_reg_operand"         "=Rcw, w,  w")
1911	 (smax:SI (match_operand:SI 1 "register_operand"  "%0, c,  c")
1912		  (match_operand:SI 2 "nonmemory_operand" "cL,cL,Cal")))]
1913  ""
1914  "max%? %0,%1,%2"
1915  [(set_attr "type" "two_cycle_core")
1916   (set_attr "length" "4,4,8")
1917   (set_attr "predicable" "yes,no,no")]
1918)
1919
1920(define_insn "sminsi3"
1921   [(set (match_operand:SI 0 "dest_reg_operand"         "=Rcw, w,  w")
1922	 (smin:SI (match_operand:SI 1 "register_operand"  "%0, c,  c")
1923		  (match_operand:SI 2 "nonmemory_operand" "cL,cL,Cal")))]
1924  ""
1925  "min%? %0,%1,%2"
1926  [(set_attr "type" "two_cycle_core")
1927   (set_attr "length" "4,4,8")
1928   (set_attr "predicable" "yes,no,no")]
1929)
1930
1931;; Arithmetic instructions.
1932
1933; We say an insn can be conditionalized if this doesn't introduce a long
1934; immediate.  We set the type such that we still have good scheduling if the
1935; insn is conditionalized.
1936; ??? It would make sense to allow introduction of long immediates, but
1937;     we'd need to communicate to the ccfsm machinery the extra cost.
1938; The alternatives in the constraints still serve three purposes:
1939; - estimate insn size assuming conditional execution
1940; - guide reload to re-order the second and third operand to get a better fit.
1941; - give tentative insn type to guide scheduling
1942;   N.B. "%" for commutativity doesn't help when there is another matching
1943;   (but longer) alternative.
1944; We avoid letting this pattern use LP_COUNT as a register by specifying
1945;  register class 'W' instead of 'w'.
1946(define_insn_and_split "*addsi3_mixed"
1947  ;;                                                      0       1    2    3   4   5   6     7    8   9   a    b     c   d e   f  10  11  12
1948  [(set (match_operand:SI 0 "dest_reg_operand"          "=Rcq#q,Rcq,   h,!*Rsd,Rcq,Rcb,Rcq, Rcqq,Rcqq,Rcw,Rcw, Rcw,    W,  W,W,  W,Rcqq,Rcw,  W")
1949	(plus:SI (match_operand:SI 1 "register_operand" "%0,      c,   0, Rcqq,  0,  0,Rcb, Rcqq,   0,  0,  c,   0,    c,  c,0,  0,   0,  0,  c")
1950		 (match_operand:SI 2 "nonmemory_operand" "cL,     0, Cm1,    L,CL2,Csp,CM4,RcqqK,  cO, cL,  0,cCca,cLCmL,Cca,I,C2a, Cal,Cal,Cal")))]
1951  ""
1952{
1953  arc_output_addsi (operands, arc_ccfsm_cond_exec_p (), true);
1954  return "";
1955}
1956  "&& reload_completed && get_attr_length (insn) == 8
1957   && satisfies_constraint_I (operands[2])
1958   && GET_CODE (PATTERN (insn)) != COND_EXEC"
1959  [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))]
1960  "split_addsi (operands);"
1961  [(set_attr "type" "*,*,*,*,two_cycle_core,two_cycle_core,*,*,*,*,*,two_cycle_core,*,two_cycle_core,*,two_cycle_core,*,*,*")
1962   (set (attr "iscompact")
1963	(cond [(match_test "~arc_output_addsi (operands, false, false) & 2")
1964	       (const_string "false")
1965	       (match_operand 2 "long_immediate_operand" "")
1966	       (const_string "maybe_limm")]
1967	      (const_string "maybe")))
1968   (set_attr "length"     "*,*,*,*,*,*,*,*,*,4,4,4,4,4,4,4,*,8,8")
1969   (set_attr "predicable" "no,no,no,no,no,no,no,no,no,yes,yes,yes,no,no,no,no,no,yes,no")
1970   (set_attr "cond"       "canuse,nocond,nocond,nocond,canuse,canuse,nocond,nocond,nocond,canuse,canuse,canuse,nocond,nocond,canuse_limm,canuse_limm,canuse,canuse,nocond")
1971])
1972
1973;; ARCv2 MPYW and MPYUW
1974(define_expand "mulhisi3"
1975  [(set (match_operand:SI 0 "register_operand"                           "")
1976	(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand"  ""))
1977		 (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" ""))))]
1978  "TARGET_MPYW"
1979  "{
1980    if (CONSTANT_P (operands[2]))
1981    {
1982      emit_insn (gen_mulhisi3_imm (operands[0], operands[1], operands[2]));
1983      DONE;
1984    }
1985   }"
1986)
1987
1988(define_insn "mulhisi3_imm"
1989  [(set (match_operand:SI 0 "register_operand"                         "=r,r,r,  r,  r")
1990	(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "0,r,0,  0,  r"))
1991		 (match_operand:HI 2 "short_const_int_operand"          "L,L,I,C16,C16")))]
1992  "TARGET_MPYW"
1993  "mpyw%? %0,%1,%2"
1994  [(set_attr "length" "4,4,4,8,8")
1995   (set_attr "iscompact" "false")
1996   (set_attr "type" "mul16_em")
1997   (set_attr "predicable" "yes,no,no,yes,no")
1998   (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")
1999   ])
2000
2001(define_insn "mulhisi3_reg"
2002  [(set (match_operand:SI 0 "register_operand"                          "=Rcqq,r,r")
2003	(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand"  "   0,0,r"))
2004		 (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" "Rcqq,r,r"))))]
2005  "TARGET_MPYW"
2006  "mpyw%? %0,%1,%2"
2007  [(set_attr "length" "*,4,4")
2008   (set_attr "iscompact" "maybe,false,false")
2009   (set_attr "type" "mul16_em")
2010   (set_attr "predicable" "yes,yes,no")
2011   (set_attr "cond" "canuse,canuse,nocond")
2012   ])
2013
2014(define_expand "umulhisi3"
2015  [(set (match_operand:SI 0 "register_operand"                           "")
2016	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand"  ""))
2017		 (zero_extend:SI (match_operand:HI 2 "arc_short_operand" ""))))]
2018  "TARGET_MPYW"
2019  "{
2020    if (CONSTANT_P (operands[2]))
2021    {
2022      emit_insn (gen_umulhisi3_imm (operands[0], operands[1], operands[2]));
2023      DONE;
2024    }
2025  }"
2026)
2027
2028(define_insn "umulhisi3_imm"
2029  [(set (match_operand:SI 0 "register_operand"                          "=r, r,  r,  r,  r")
2030	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0, r,  0,  0,  r"))
2031		 (match_operand:HI 2 "short_unsigned_const_operand"     " L, L,J12,J16,J16")))]
2032  "TARGET_MPYW"
2033  "mpyuw%? %0,%1,%2"
2034  [(set_attr "length" "4,4,4,8,8")
2035   (set_attr "iscompact" "false")
2036   (set_attr "type" "mul16_em")
2037   (set_attr "predicable" "yes,no,no,yes,no")
2038   (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")
2039   ])
2040
2041(define_insn "umulhisi3_reg"
2042  [(set (match_operand:SI 0 "register_operand"                          "=Rcqq, r, r")
2043	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "   %0, 0, r"))
2044		 (zero_extend:SI (match_operand:HI 2 "register_operand" " Rcqq, r, r"))))]
2045  "TARGET_MPYW"
2046  "mpyuw%? %0,%1,%2"
2047  [(set_attr "length" "*,4,4")
2048   (set_attr "iscompact" "maybe,false,false")
2049   (set_attr "type" "mul16_em")
2050   (set_attr "predicable" "yes,yes,no")
2051   (set_attr "cond" "canuse,canuse,nocond")
2052   ])
2053
2054;; ARC700/ARC600/V2 multiply
2055;; SI <- SI * SI
2056
2057(define_expand "mulsi3"
2058 [(set (match_operand:SI 0 "nonimmediate_operand"            "")
2059	(mult:SI (match_operand:SI 1 "register_operand"  "")
2060		 (match_operand:SI 2 "nonmemory_operand" "")))]
2061  ""
2062{
2063  if (TARGET_MPY)
2064    {
2065      if (!register_operand (operands[0], SImode))
2066	{
2067	  rtx result = gen_reg_rtx (SImode);
2068
2069	  emit_insn (gen_mulsi3 (result, operands[1], operands[2]));
2070	  emit_move_insn (operands[0], result);
2071	  DONE;
2072	}
2073    }
2074  else if (TARGET_MUL64_SET)
2075    {
2076     rtx tmp = gen_reg_rtx (SImode);
2077     emit_insn (gen_mulsi64 (tmp, operands[1], operands[2]));
2078     emit_move_insn (operands[0], tmp);
2079     DONE;
2080    }
2081  else if (TARGET_MULMAC_32BY16_SET)
2082    {
2083     rtx tmp = gen_reg_rtx (SImode);
2084     emit_insn (gen_mulsi32x16 (tmp, operands[1], operands[2]));
2085     emit_move_insn (operands[0], tmp);
2086     DONE;
2087    }
2088  else
2089    {
2090      emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
2091      emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
2092      emit_insn (gen_mulsi3_600_lib ());
2093      emit_move_insn (operands[0], gen_rtx_REG (SImode, R0_REG));
2094      DONE;
2095    }
2096})
2097
2098(define_insn_and_split "mulsi32x16"
2099 [(set (match_operand:SI 0 "register_operand"            "=w")
2100	(mult:SI (match_operand:SI 1 "register_operand"  "%c")
2101		 (match_operand:SI 2 "nonmemory_operand" "ci")))
2102  (clobber (reg:DI MUL32x16_REG))]
2103 "TARGET_MULMAC_32BY16_SET"
2104 "#"
2105 "TARGET_MULMAC_32BY16_SET && reload_completed"
2106 [(const_int 0)]
2107 {
2108  if (immediate_operand (operands[2], SImode)
2109    && INTVAL (operands[2]) >= 0
2110    && INTVAL (operands[2]) <= 65535)
2111     {
2112      emit_insn (gen_umul_600 (operands[1], operands[2],
2113				       gen_acc2 (), gen_acc1 ()));
2114      emit_move_insn (operands[0], gen_acc2 ());
2115      DONE;
2116     }
2117   emit_insn (gen_umul_600 (operands[1], operands[2],
2118				   gen_acc2 (), gen_acc1 ()));
2119   emit_insn (gen_mac_600 (operands[1], operands[2],
2120				   gen_acc2 (), gen_acc1 ()));
2121   emit_move_insn (operands[0], gen_acc2 ());
2122   DONE;
2123  }
2124 [(set_attr "type" "multi")
2125  (set_attr "length" "8")])
2126
2127; mululw conditional execution without a LIMM clobbers an input register;
2128; we'd need a different pattern to describe this.
2129; To make the conditional execution valid for the LIMM alternative, we
2130; have to emit the LIMM before the register operand.
2131(define_insn "umul_600"
2132  [(set (match_operand:SI 2 "acc2_operand" "")
2133	(mult:SI (match_operand:SI 0 "register_operand"  "c,c,c")
2134		 (zero_extract:SI (match_operand:SI 1 "nonmemory_operand"
2135							 "c,L,Cal")
2136				  (const_int 16)
2137				  (const_int 0))))
2138   (clobber (match_operand:SI 3 "acc1_operand" ""))]
2139  "TARGET_MULMAC_32BY16_SET"
2140  "mululw 0, %0, %1"
2141  [(set_attr "length" "4,4,8")
2142   (set_attr "type" "mulmac_600")
2143   (set_attr "predicable" "no")
2144   (set_attr "cond" "nocond")])
2145
2146(define_insn "mac_600"
2147  [(set (match_operand:SI 2 "acc2_operand" "")
2148	(plus:SI
2149	  (mult:SI (match_operand:SI 0 "register_operand" "c,c,c")
2150		   (ashift:SI
2151		     (zero_extract:SI (match_operand:SI 1 "nonmemory_operand" "c,L,Cal")
2152				      (const_int 16)
2153				      (const_int 16))
2154		     (const_int 16)))
2155	  (match_dup 2)))
2156   (clobber (match_operand:SI 3 "acc1_operand" ""))]
2157  "TARGET_MULMAC_32BY16_SET"
2158  "machlw%? 0, %0, %1"
2159  [(set_attr "length" "4,4,8")
2160   (set_attr "type" "mulmac_600, mulmac_600, mulmac_600")
2161   (set_attr "predicable" "no, no, yes")
2162   (set_attr "cond" "nocond, canuse_limm, canuse")])
2163
2164(define_insn_and_split "mulsi64"
2165 [(set (match_operand:SI 0 "register_operand"            "=w")
2166	(mult:SI (match_operand:SI 1 "register_operand"  "%c")
2167		 (match_operand:SI 2 "nonmemory_operand" "ci")))
2168  (clobber (reg:DI MUL64_OUT_REG))]
2169 "TARGET_MUL64_SET"
2170 "#"
2171 "TARGET_MUL64_SET && reload_completed"
2172  [(const_int 0)]
2173{
2174  emit_insn (gen_mulsi_600 (operands[1], operands[2],
2175			gen_mlo (), gen_mhi ()));
2176  emit_move_insn (operands[0], gen_mlo ());
2177  DONE;
2178}
2179  [(set_attr "type" "multi")
2180   (set_attr "length" "8")])
2181
2182(define_insn "mulsi_600"
2183  [(set (match_operand:SI 2 "mlo_operand" "")
2184	(mult:SI (match_operand:SI 0 "register_operand"  "%Rcq#q,c,c,c")
2185		 (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,I,Cal")))
2186   (clobber (match_operand:SI 3 "mhi_operand" ""))]
2187  "TARGET_MUL64_SET"
2188; The assembler mis-assembles mul64 / mulu64 with "I" constraint constants,
2189; using a machine code pattern that only allows "L" constraint constants.
2190;  "mul64%? \t0, %0, %1%&"
2191{
2192  if (satisfies_constraint_I (operands[1])
2193      && !satisfies_constraint_L (operands[1]))
2194    {
2195      /* MUL64 <0,>b,s12 00101bbb10000100 0BBBssssssSSSSSS  */
2196      int n = true_regnum (operands[0]);
2197      int i = INTVAL (operands[1]);
2198      asm_fprintf (asm_out_file, "\t.short %d`", 0x2884 + ((n & 7) << 8));
2199      asm_fprintf (asm_out_file, "\t.short %d`",
2200		   ((i & 0x3f) << 6) + ((i >> 6) & 0x3f) + ((n & 070) << 9));
2201      return "; mul64%? \t0, %0, %1%&";
2202    }
2203  return "mul64%? \t0, %0, %1%&";
2204}
2205  [(set_attr "length" "*,4,4,8")
2206   (set_attr "iscompact" "maybe,false,false,false")
2207   (set_attr "type" "multi,multi,multi,multi")
2208   (set_attr "predicable" "yes,yes,no,yes")
2209   (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
2210
2211; If we compile without an mul option enabled, but link with libraries
2212; for a mul option, we'll see clobbers of multiplier output registers.
2213; There is also an implementation using norm that clobbers the loop registers.
2214(define_insn "mulsi3_600_lib"
2215  [(set (reg:SI R0_REG)
2216	(mult:SI (reg:SI R0_REG) (reg:SI R1_REG)))
2217   (clobber (reg:SI RETURN_ADDR_REGNUM))
2218   (clobber (reg:SI R1_REG))
2219   (clobber (reg:SI R2_REG))
2220   (clobber (reg:SI R3_REG))
2221   (clobber (reg:DI MUL64_OUT_REG))
2222   (clobber (reg:SI LP_COUNT))
2223   (clobber (reg:SI LP_START))
2224   (clobber (reg:SI LP_END))
2225   (clobber (reg:CC CC_REG))]
2226  "!TARGET_ANY_MPY
2227   && SFUNC_CHECK_PREDICABLE"
2228  "*return arc_output_libcall (\"__mulsi3\");"
2229  [(set_attr "is_sfunc" "yes")
2230   (set_attr "predicable" "yes")])
2231
2232(define_insn_and_split "mulsidi_600"
2233  [(set (match_operand:DI 0 "register_operand"                               "=c, c,c,  c")
2234	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"  "%Rcq#q, c,c,  c"))
2235		 (sign_extend:DI (match_operand:SI 2 "nonmemory_operand"  "Rcq#q,cL,L,C32"))))
2236   (clobber (reg:DI MUL64_OUT_REG))]
2237  "TARGET_MUL64_SET"
2238  "#"
2239  "TARGET_MUL64_SET"
2240  [(const_int 0)]
2241  "emit_insn (gen_mul64 (operands[1], operands[2]));
2242   emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
2243   DONE;"
2244  [(set_attr "type" "multi")
2245   (set_attr "length" "8")])
2246
2247(define_insn "mul64"
2248  [(set (reg:DI MUL64_OUT_REG)
2249	(mult:DI
2250	 (sign_extend:DI (match_operand:SI 0 "register_operand" "%Rcq#q, c,c,  c"))
2251	 (sign_extend:DI (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,L,C32"))))]
2252  "TARGET_MUL64_SET"
2253  "mul64%? \t0, %0, %1%&"
2254  [(set_attr "length" "*,4,4,8")
2255   (set_attr "iscompact" "maybe,false,false,false")
2256   (set_attr "type" "multi,multi,multi,multi")
2257   (set_attr "predicable" "yes,yes,no,yes")
2258   (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
2259
2260(define_insn_and_split "umulsidi_600"
2261  [(set (match_operand:DI 0 "register_operand"                            "=c,c, c")
2262	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"   "%c,c, c"))
2263		 (sign_extend:DI (match_operand:SI 2 "nonmemory_operand"  "cL,L,C32"))))
2264   (clobber (reg:DI MUL64_OUT_REG))]
2265  "TARGET_MUL64_SET"
2266  "#"
2267  "TARGET_MUL64_SET"
2268  [(const_int 0)]
2269  "emit_insn (gen_mulu64 (operands[1], operands[2]));
2270   emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
2271   DONE;"
2272  [(set_attr "type" "umulti")
2273   (set_attr "length" "8")])
2274
2275(define_insn "mulu64"
2276  [(set (reg:DI MUL64_OUT_REG)
2277	(mult:DI
2278	 (zero_extend:DI (match_operand:SI 0 "register_operand"  "%c,c,c"))
2279	 (zero_extend:DI (match_operand:SI 1 "nonmemory_operand" "cL,L,C32"))))]
2280  "TARGET_MUL64_SET"
2281  "mulu64%? \t0, %0, %1%&"
2282  [(set_attr "length" "4,4,8")
2283   (set_attr "iscompact" "false")
2284   (set_attr "type" "umulti")
2285   (set_attr "predicable" "yes,no,yes")
2286   (set_attr "cond" "canuse,canuse_limm,canuse")])
2287
2288; ARC700 mpy* instructions: This is a multi-cycle extension, and thus 'w'
2289; may not be used as destination constraint.
2290
2291; The result of mpy and mpyu is the same except for flag setting (if enabled),
2292; but mpyu is faster for the standard multiplier.
2293; Note: we must make sure LP_COUNT is not one of the destination
2294; registers, since it cannot be the destination of a multi-cycle insn
2295; like MPY or MPYU.
2296(define_insn "mulsi3_700"
2297 [(set (match_operand:SI 0 "mpy_dest_reg_operand"        "=Rcr,r,r,Rcr,r")
2298	(mult:SI (match_operand:SI 1 "register_operand"  "%0,c,0,0,c")
2299		 (match_operand:SI 2 "nonmemory_operand" "cL,cL,I,Cal,Cal")))]
2300 "TARGET_ARC700_MPY"
2301  "mpyu%? %0,%1,%2"
2302  [(set_attr "length" "4,4,4,8,8")
2303   (set_attr "type" "umulti")
2304   (set_attr "predicable" "yes,no,no,yes,no")
2305   (set_attr "cond" "canuse,nocond,canuse_limm,canuse,nocond")])
2306
2307; ARCv2 has no penalties between mpy and mpyu. So, we use mpy because of its
2308; short variant. LP_COUNT constraints are still valid.
2309(define_insn "mulsi3_v2"
2310 [(set (match_operand:SI 0 "mpy_dest_reg_operand"        "=Rcqq,Rcr, r,r,Rcr,  r")
2311	(mult:SI (match_operand:SI 1 "register_operand"     "%0,  0, c,0,  0,  c")
2312		 (match_operand:SI 2 "nonmemory_operand" " Rcqq, cL,cL,I,Cal,Cal")))]
2313 "TARGET_MULTI"
2314 "mpy%? %0,%1,%2"
2315 [(set_attr "length" "*,4,4,4,8,8")
2316  (set_attr "iscompact" "maybe,false,false,false,false,false")
2317  (set_attr "type" "umulti")
2318  (set_attr "predicable" "no,yes,no,no,yes,no")
2319  (set_attr "cond" "nocond,canuse,nocond,canuse_limm,canuse,nocond")])
2320
2321(define_expand "mulsidi3"
2322  [(set (match_operand:DI 0 "register_operand" "")
2323	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
2324		 (sign_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))]
2325  "TARGET_ANY_MPY"
2326  {
2327  if (TARGET_PLUS_MACD)
2328    {
2329     if (CONST_INT_P (operands[2]))
2330       {
2331	emit_insn (gen_mpyd_imm_arcv2hs (operands[0], operands[1], operands[2]));
2332       }
2333     else
2334       {
2335	emit_insn (gen_mpyd_arcv2hs (operands[0], operands[1], operands[2]));
2336       }
2337     DONE;
2338    }
2339  if (TARGET_MPY)
2340    {
2341      operands[2] = force_reg (SImode, operands[2]);
2342      if (!register_operand (operands[0], DImode))
2343	{
2344	  rtx result = gen_reg_rtx (DImode);
2345
2346	  operands[2] = force_reg (SImode, operands[2]);
2347	  emit_insn (gen_mulsidi3 (result, operands[1], operands[2]));
2348	  emit_move_insn (operands[0], result);
2349	  DONE;
2350	}
2351    }
2352  else if (TARGET_MUL64_SET)
2353    {
2354      emit_insn (gen_mulsidi_600 (operands[0], operands[1], operands[2]));
2355      DONE;
2356    }
2357  else if (TARGET_MULMAC_32BY16_SET)
2358    {
2359      operands[2] = force_reg (SImode, operands[2]);
2360      emit_insn (gen_mulsidi64 (operands[0], operands[1], operands[2]));
2361      DONE;
2362    }
2363  operands[2] = force_reg (SImode, operands[2]);
2364  })
2365
2366(define_insn_and_split "mulsidi64"
2367  [(set (match_operand:DI 0 "register_operand" "=w")
2368	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%c"))
2369		 (sign_extend:DI (match_operand:SI 2 "extend_operand" "ci"))))
2370   (clobber (reg:DI MUL32x16_REG))]
2371  "TARGET_MULMAC_32BY16_SET"
2372  "#"
2373  "TARGET_MULMAC_32BY16_SET && reload_completed"
2374  [(const_int 0)]
2375  {
2376   rtx result_hi = gen_highpart (SImode, operands[0]);
2377   rtx result_low = gen_lowpart (SImode, operands[0]);
2378
2379   emit_insn (gen_mul64_600 (operands[1], operands[2]));
2380   emit_insn (gen_mac64_600 (result_hi, operands[1], operands[2]));
2381   emit_move_insn (result_low, gen_acc2 ());
2382   DONE;
2383  }
2384  [(set_attr "type" "multi")
2385   (set_attr "length" "8")])
2386
2387
2388(define_insn "mul64_600"
2389  [(set (reg:DI MUL32x16_REG)
2390	(mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand"
2391				  "c,c,c"))
2392		 (zero_extract:DI (match_operand:SI 1 "nonmemory_operand"
2393				  "c,L,Cal")
2394				  (const_int 16)
2395				  (const_int 0))))
2396  ]
2397  "TARGET_MULMAC_32BY16_SET"
2398  "mullw%? 0, %0, %1"
2399  [(set_attr "length" "4,4,8")
2400   (set_attr "type" "mulmac_600")
2401   (set_attr "predicable" "no,no,yes")
2402   (set_attr "cond" "nocond, canuse_limm, canuse")])
2403
2404
2405;; ??? check if this is canonical rtl
2406(define_insn "mac64_600"
2407  [(set (reg:DI MUL32x16_REG)
2408	(plus:DI
2409	  (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "c,c,c"))
2410		   (ashift:DI
2411		     (sign_extract:DI (match_operand:SI 2 "nonmemory_operand" "c,L,Cal")
2412				      (const_int 16) (const_int 16))
2413		     (const_int 16)))
2414	  (reg:DI MUL32x16_REG)))
2415   (set (match_operand:SI 0 "register_operand" "=w,w,w")
2416	(zero_extract:SI
2417	  (plus:DI
2418	    (mult:DI (sign_extend:DI (match_dup 1))
2419		     (ashift:DI
2420		       (sign_extract:DI (match_dup 2)
2421					(const_int 16) (const_int 16))
2422			  (const_int 16)))
2423	    (reg:DI MUL32x16_REG))
2424	  (const_int 32) (const_int 32)))]
2425  "TARGET_MULMAC_32BY16_SET"
2426  "machlw%? %0, %1, %2"
2427  [(set_attr "length" "4,4,8")
2428   (set_attr "type" "mulmac_600")
2429   (set_attr "predicable" "no,no,yes")
2430   (set_attr "cond" "nocond, canuse_limm, canuse")])
2431
2432
2433;; DI <- DI(signed SI) * DI(signed SI)
2434(define_insn_and_split "mulsidi3_700"
2435  [(set (match_operand:DI 0 "register_operand" "=&r")
2436	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%c"))
2437		 (sign_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))]
2438  "TARGET_MPY && !TARGET_PLUS_MACD"
2439  "#"
2440  "&& reload_completed"
2441  [(const_int 0)]
2442{
2443  int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
2444  int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
2445  rtx l0 = simplify_gen_subreg (word_mode, operands[0], DImode, lo);
2446  rtx h0 = simplify_gen_subreg (word_mode, operands[0], DImode, hi);
2447  emit_insn (gen_mulsi3_highpart (h0, operands[1], operands[2]));
2448  emit_insn (gen_mulsi3 (l0, operands[1], operands[2]));
2449  DONE;
2450}
2451  [(set_attr "type" "multi")
2452   (set_attr "length" "8")])
2453
2454(define_insn "mulsi3_highpart"
2455  [(set (match_operand:SI 0 "register_operand"                  "=Rcr,r,Rcr,r")
2456	(truncate:SI
2457	 (lshiftrt:DI
2458	  (mult:DI
2459	   (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,c,  0,c"))
2460	   (sign_extend:DI (match_operand:SI 2 "extend_operand"    "c,c,  i,i")))
2461	  (const_int 32))))]
2462  "TARGET_MPY"
2463  "mpy%+%? %0,%1,%2"
2464  [(set_attr "length" "4,4,8,8")
2465   (set_attr "type" "multi")
2466   (set_attr "predicable" "yes,no,yes,no")
2467   (set_attr "cond" "canuse,nocond,canuse,nocond")])
2468
2469; Note that mpyhu has the same latency as mpy / mpyh,
2470; thus we use the type multi.
2471(define_insn "*umulsi3_highpart_i"
2472  [(set (match_operand:SI 0 "register_operand"                  "=Rcr,r,Rcr,r")
2473	(truncate:SI
2474	 (lshiftrt:DI
2475	  (mult:DI
2476	   (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,c,  0,c"))
2477	   (zero_extend:DI (match_operand:SI 2 "extend_operand"    "c,c,  i,i")))
2478	  (const_int 32))))]
2479  "TARGET_MPY"
2480  "mpy%+u%? %0,%1,%2"
2481  [(set_attr "length" "4,4,8,8")
2482   (set_attr "type" "multi")
2483   (set_attr "predicable" "yes,no,yes,no")
2484   (set_attr "cond" "canuse,nocond,canuse,nocond")])
2485
2486; Implementations include additional labels for umulsidi3, so we got all
2487; the same clobbers - plus one for the result low part.  */
2488(define_insn "umulsi3_highpart_600_lib_le"
2489  [(set (reg:SI R1_REG)
2490	(truncate:SI
2491	 (lshiftrt:DI
2492	  (mult:DI (zero_extend:DI (reg:SI R0_REG))
2493		   (zero_extend:DI (reg:SI R1_REG)))
2494	  (const_int 32))))
2495   (clobber (reg:SI RETURN_ADDR_REGNUM))
2496   (clobber (reg:SI R0_REG))
2497   (clobber (reg:DI R2_REG))
2498   (clobber (reg:SI R12_REG))
2499   (clobber (reg:DI MUL64_OUT_REG))
2500   (clobber (reg:CC CC_REG))]
2501  "!TARGET_BIG_ENDIAN
2502   && !TARGET_ANY_MPY
2503   && SFUNC_CHECK_PREDICABLE"
2504  "*return arc_output_libcall (\"__umulsi3_highpart\");"
2505  [(set_attr "is_sfunc" "yes")
2506   (set_attr "predicable" "yes")])
2507
2508(define_insn "umulsi3_highpart_600_lib_be"
2509  [(set (reg:SI R0_REG)
2510	(truncate:SI
2511	 (lshiftrt:DI
2512	  (mult:DI (zero_extend:DI (reg:SI R0_REG))
2513		   (zero_extend:DI (reg:SI R1_REG)))
2514	  (const_int 32))))
2515   (clobber (reg:SI RETURN_ADDR_REGNUM))
2516   (clobber (reg:SI R1_REG))
2517   (clobber (reg:DI R2_REG))
2518   (clobber (reg:SI R12_REG))
2519   (clobber (reg:DI MUL64_OUT_REG))
2520   (clobber (reg:CC CC_REG))]
2521  "TARGET_BIG_ENDIAN
2522   && !TARGET_ANY_MPY
2523   && SFUNC_CHECK_PREDICABLE"
2524  "*return arc_output_libcall (\"__umulsi3_highpart\");"
2525  [(set_attr "is_sfunc" "yes")
2526   (set_attr "predicable" "yes")])
2527
2528;; (zero_extend:DI (const_int)) leads to internal errors in combine, so we
2529;; need a separate pattern for immediates
2530;; ??? This is fine for combine, but not for reload.
2531(define_insn "umulsi3_highpart_int"
2532  [(set (match_operand:SI 0 "register_operand"            "=Rcr, r, r,Rcr,  r")
2533	(truncate:SI
2534	 (lshiftrt:DI
2535	  (mult:DI
2536	   (zero_extend:DI (match_operand:SI 1 "register_operand"  " 0, c, 0,  0,  c"))
2537	   (match_operand:DI 2 "immediate_usidi_operand" "L, L, I, Cal, Cal"))
2538	  (const_int 32))))]
2539  "TARGET_MPY"
2540  "mpy%+u%? %0,%1,%2"
2541  [(set_attr "length" "4,4,4,8,8")
2542   (set_attr "type" "multi")
2543   (set_attr "predicable" "yes,no,no,yes,no")
2544   (set_attr "cond" "canuse,nocond,canuse_limm,canuse,nocond")])
2545
2546(define_expand "umulsi3_highpart"
2547  [(set (match_operand:SI 0 "general_operand"  "")
2548	(truncate:SI
2549	 (lshiftrt:DI
2550	  (mult:DI
2551	   (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
2552	   (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" "")))
2553	  (const_int 32))))]
2554  "!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET"
2555  "
2556{
2557  rtx target = operands[0];
2558
2559  if (!TARGET_MPY)
2560    {
2561      emit_move_insn (gen_rtx_REG (SImode, 0), operands[1]);
2562      emit_move_insn (gen_rtx_REG (SImode, 1), operands[2]);
2563      if (TARGET_BIG_ENDIAN)
2564	emit_insn (gen_umulsi3_highpart_600_lib_be ());
2565      else
2566	emit_insn (gen_umulsi3_highpart_600_lib_le ());
2567      emit_move_insn (target, gen_rtx_REG (SImode, 0));
2568      DONE;
2569    }
2570
2571  if (!register_operand (target, SImode))
2572    target = gen_reg_rtx (SImode);
2573
2574  if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
2575    operands[2] = simplify_const_unary_operation (ZERO_EXTEND, DImode,
2576						  operands[2], SImode);
2577  else if (!immediate_operand (operands[2], SImode))
2578    operands[2] = gen_rtx_ZERO_EXTEND (DImode, operands[2]);
2579  emit_insn (gen_umulsi3_highpart_int (target, operands[1], operands[2]));
2580  if (target != operands[0])
2581    emit_move_insn (operands[0], target);
2582  DONE;
2583}")
2584
2585(define_expand "umulsidi3"
2586  [(set (match_operand:DI 0 "register_operand" "")
2587	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
2588		 (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))]
2589  ""
2590{
2591  if (TARGET_PLUS_MACD)
2592    {
2593     if (CONST_INT_P (operands[2]))
2594       {
2595	emit_insn (gen_mpydu_imm_arcv2hs (operands[0], operands[1], operands[2]));
2596       }
2597     else
2598       {
2599	emit_insn (gen_mpydu_arcv2hs (operands[0], operands[1], operands[2]));
2600       }
2601     DONE;
2602    }
2603  if (TARGET_MPY)
2604    {
2605      operands[2] = force_reg (SImode, operands[2]);
2606      if (!register_operand (operands[0], DImode))
2607	{
2608	  rtx result = gen_reg_rtx (DImode);
2609
2610	  emit_insn (gen_umulsidi3 (result, operands[1], operands[2]));
2611	  emit_move_insn (operands[0], result);
2612	  DONE;
2613	}
2614    }
2615  else if (TARGET_MUL64_SET)
2616    {
2617     operands[2] = force_reg (SImode, operands[2]);
2618     emit_insn (gen_umulsidi_600 (operands[0], operands[1], operands[2]));
2619      DONE;
2620    }
2621  else if (TARGET_MULMAC_32BY16_SET)
2622    {
2623     operands[2] = force_reg (SImode, operands[2]);
2624     emit_insn (gen_umulsidi64 (operands[0], operands[1], operands[2]));
2625      DONE;
2626    }
2627  else
2628    {
2629      emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
2630      emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
2631      emit_insn (gen_umulsidi3_600_lib ());
2632      emit_move_insn (operands[0], gen_rtx_REG (DImode, R0_REG));
2633      DONE;
2634    }
2635})
2636
2637(define_insn_and_split "umulsidi64"
2638  [(set (match_operand:DI 0 "register_operand" "=w")
2639	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%c"))
2640		 (zero_extend:DI (match_operand:SI 2 "extend_operand" "ci"))))
2641   (clobber (reg:DI MUL32x16_REG))]
2642  "TARGET_MULMAC_32BY16_SET"
2643  "#"
2644  "TARGET_MULMAC_32BY16_SET && reload_completed"
2645  [(const_int 0)]
2646  {
2647   rtx result_hi;
2648   rtx result_low;
2649
2650   result_hi = gen_highpart (SImode, operands[0]);
2651   result_low = gen_lowpart (SImode, operands[0]);
2652
2653   emit_insn (gen_umul64_600 (operands[1], operands[2]));
2654   emit_insn (gen_umac64_600 (result_hi, operands[1], operands[2]));
2655   emit_move_insn (result_low, gen_acc2 ());
2656   DONE;
2657   }
2658  [(set_attr "type" "multi")
2659   (set_attr "length" "8")])
2660
2661(define_insn "umul64_600"
2662  [(set (reg:DI MUL32x16_REG)
2663	(mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand"
2664				  "c,c,c"))
2665		 (zero_extract:DI (match_operand:SI 1 "nonmemory_operand"
2666				  "c,L,Cal")
2667				  (const_int 16)
2668				  (const_int 0))))
2669  ]
2670  "TARGET_MULMAC_32BY16_SET"
2671  "mululw 0, %0, %1"
2672  [(set_attr "length" "4,4,8")
2673   (set_attr "type" "mulmac_600")
2674   (set_attr "predicable" "no")
2675   (set_attr "cond" "nocond")])
2676
2677
2678(define_insn "umac64_600"
2679  [(set (reg:DI MUL32x16_REG)
2680	(plus:DI
2681	  (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "c,c,c"))
2682		   (ashift:DI
2683		     (zero_extract:DI (match_operand:SI 2 "nonmemory_operand" "c,L,Cal")
2684				      (const_int 16) (const_int 16))
2685		     (const_int 16)))
2686	  (reg:DI MUL32x16_REG)))
2687   (set (match_operand:SI 0 "register_operand" "=w,w,w")
2688	(zero_extract:SI
2689	  (plus:DI
2690	    (mult:DI (zero_extend:DI (match_dup 1))
2691		     (ashift:DI
2692		       (zero_extract:DI (match_dup 2)
2693					(const_int 16) (const_int 16))
2694			  (const_int 16)))
2695	    (reg:DI MUL32x16_REG))
2696	  (const_int 32) (const_int 32)))]
2697  "TARGET_MULMAC_32BY16_SET"
2698  "machulw%? %0, %1, %2"
2699  [(set_attr "length" "4,4,8")
2700   (set_attr "type" "mulmac_600")
2701   (set_attr "predicable" "no,no,yes")
2702   (set_attr "cond" "nocond, canuse_limm, canuse")])
2703
2704;; DI <- DI(unsigned SI) * DI(unsigned SI)
2705(define_insn_and_split "umulsidi3_700"
2706  [(set (match_operand:DI 0 "dest_reg_operand" "=&r")
2707	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%c"))
2708		 (zero_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))]
2709  "TARGET_MPY && !TARGET_PLUS_MACD"
2710  "#"
2711  "reload_completed"
2712  [(const_int 0)]
2713{
2714  int hi = !TARGET_BIG_ENDIAN;
2715  int lo = !hi;
2716  rtx l0 = operand_subword (operands[0], lo, 0, DImode);
2717  rtx h0 = operand_subword (operands[0], hi, 0, DImode);
2718  emit_insn (gen_umulsi3_highpart (h0, operands[1], operands[2]));
2719  emit_insn (gen_mulsi3 (l0, operands[1], operands[2]));
2720  DONE;
2721}
2722  [(set_attr "type" "umulti")
2723  (set_attr "length" "8")])
2724
2725(define_insn "umulsidi3_600_lib"
2726  [(set (reg:DI R0_REG)
2727	(mult:DI (zero_extend:DI (reg:SI R0_REG))
2728		 (zero_extend:DI (reg:SI R1_REG))))
2729   (clobber (reg:SI RETURN_ADDR_REGNUM))
2730   (clobber (reg:DI R2_REG))
2731   (clobber (reg:SI R12_REG))
2732   (clobber (reg:DI MUL64_OUT_REG))
2733   (clobber (reg:CC CC_REG))]
2734   "!TARGET_ANY_MPY
2735   && SFUNC_CHECK_PREDICABLE"
2736  "*return arc_output_libcall (\"__umulsidi3\");"
2737  [(set_attr "is_sfunc" "yes")
2738   (set_attr "predicable" "yes")])
2739
2740(define_peephole2
2741  [(parallel
2742     [(set (reg:DI R0_REG)
2743	   (mult:DI (zero_extend:DI (reg:SI R0_REG))
2744		    (zero_extend:DI (reg:SI R1_REG))))
2745      (clobber (reg:SI RETURN_ADDR_REGNUM))
2746      (clobber (reg:DI R2_REG))
2747      (clobber (reg:SI R12_REG))
2748      (clobber (reg:DI MUL64_OUT_REG))
2749      (clobber (reg:CC CC_REG))])]
2750  "!TARGET_ANY_MPY
2751   && peep2_regno_dead_p (1, TARGET_BIG_ENDIAN ? R1_REG : R0_REG)"
2752  [(pc)]
2753{
2754  if (TARGET_BIG_ENDIAN)
2755    emit_insn (gen_umulsi3_highpart_600_lib_be ());
2756  else
2757    emit_insn (gen_umulsi3_highpart_600_lib_le ());
2758  DONE;
2759})
2760
2761(define_expand "addsi3"
2762  [(set (match_operand:SI 0 "dest_reg_operand" "")
2763	(plus:SI (match_operand:SI 1 "register_operand" "")
2764		 (match_operand:SI 2 "nonmemory_operand" "")))]
2765  ""
2766  "if (flag_pic && arc_raw_symbolic_reference_mentioned_p (operands[2], false))
2767     {
2768       operands[2]=force_reg(SImode, operands[2]);
2769     }
2770  else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[2], Pmode))
2771   {
2772      operands[2] = force_reg (SImode, arc_rewrite_small_data (operands[2]));
2773   }
2774
2775  ")
2776
2777(define_expand "adddi3"
2778  [(parallel [(set (match_operand:DI 0 "dest_reg_operand" "")
2779		   (plus:DI (match_operand:DI 1 "register_operand" "")
2780			    (match_operand:DI 2 "nonmemory_operand" "")))
2781	      (clobber (reg:CC CC_REG))])]
2782  ""
2783{})
2784
2785; This assumes that there can be no strictly partial overlap between
2786; operands[1] and operands[2].
2787(define_insn_and_split "*adddi3_i"
2788  [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w,w")
2789	(plus:DI (match_operand:DI 1 "register_operand" "%c,0,c")
2790		 (match_operand:DI 2 "nonmemory_operand" "ci,ci,!i")))
2791   (clobber (reg:CC CC_REG))]
2792  ""
2793  "#"
2794  "reload_completed"
2795  [(const_int 0)]
2796{
2797  int hi = !TARGET_BIG_ENDIAN;
2798  int lo = !hi;
2799  rtx l0 = operand_subword (operands[0], lo, 0, DImode);
2800  rtx h0 = operand_subword (operands[0], hi, 0, DImode);
2801  rtx l1 = operand_subword (operands[1], lo, 0, DImode);
2802  rtx h1 = operand_subword (operands[1], hi, 0, DImode);
2803  rtx l2 = operand_subword (operands[2], lo, 0, DImode);
2804  rtx h2 = operand_subword (operands[2], hi, 0, DImode);
2805
2806
2807  if (l2 == const0_rtx)
2808    {
2809      if (!rtx_equal_p (l0, l1) && !rtx_equal_p (l0, h1))
2810	emit_move_insn (l0, l1);
2811      emit_insn (gen_addsi3 (h0, h1, h2));
2812      if (!rtx_equal_p (l0, l1) && rtx_equal_p (l0, h1))
2813	emit_move_insn (l0, l1);
2814      DONE;
2815    }
2816  if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0
2817      && INTVAL (operands[2]) >= -0x7fffffff)
2818    {
2819      emit_insn (gen_subdi3_i (operands[0], operands[1],
2820		 GEN_INT (-INTVAL (operands[2]))));
2821      DONE;
2822    }
2823  if (rtx_equal_p (l0, h1))
2824    {
2825      if (h2 != const0_rtx)
2826	emit_insn (gen_addsi3 (h0, h1, h2));
2827      else if (!rtx_equal_p (h0, h1))
2828	emit_move_insn (h0, h1);
2829      emit_insn (gen_add_f (l0, l1, l2));
2830      emit_insn
2831	(gen_rtx_COND_EXEC
2832	  (VOIDmode,
2833	   gen_rtx_LTU (VOIDmode, gen_rtx_REG (CC_Cmode, CC_REG), GEN_INT (0)),
2834	   gen_rtx_SET (h0, plus_constant (SImode, h0, 1))));
2835      DONE;
2836    }
2837  emit_insn (gen_add_f (l0, l1, l2));
2838  emit_insn (gen_adc (h0, h1, h2));
2839  DONE;
2840}
2841  [(set_attr "cond" "clob")
2842   (set_attr "type" "binary")
2843   (set_attr "length" "16,16,20")])
2844
2845(define_insn "add_f"
2846  [(set (reg:CC_C CC_REG)
2847	(compare:CC_C
2848	  (plus:SI (match_operand:SI 1 "register_operand" "c,0,c")
2849		   (match_operand:SI 2 "nonmemory_operand" "cL,I,cCal"))
2850	  (match_dup 1)))
2851   (set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w")
2852	(plus:SI (match_dup 1) (match_dup 2)))]
2853  ""
2854  "add.f %0,%1,%2"
2855  [(set_attr "cond" "set")
2856   (set_attr "type" "compare")
2857   (set_attr "length" "4,4,8")])
2858
2859(define_insn "*add_f_2"
2860  [(set (reg:CC_C CC_REG)
2861	(compare:CC_C
2862	  (plus:SI (match_operand:SI 1 "register_operand" "c,0,c")
2863		   (match_operand:SI 2 "nonmemory_operand" "cL,I,cCal"))
2864	  (match_dup 2)))
2865   (set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w")
2866	(plus:SI (match_dup 1) (match_dup 2)))]
2867  ""
2868  "add.f %0,%1,%2"
2869  [(set_attr "cond" "set")
2870   (set_attr "type" "compare")
2871   (set_attr "length" "4,4,8")])
2872
2873; w/c/c comes first (rather than w/0/C_0) to prevent the middle-end
2874; needlessly prioritizing the matching constraint.
2875; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional
2876; execution is used where possible.
2877(define_insn_and_split "adc"
2878  [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w")
2879	(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
2880			  (match_operand:SI 1 "nonmemory_operand"
2881							 "%c,0,c,0,cCal"))
2882		 (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))]
2883  "register_operand (operands[1], SImode)
2884   || register_operand (operands[2], SImode)"
2885  "@
2886	adc %0,%1,%2
2887	add.cs %0,%1,1
2888	adc %0,%1,%2
2889	adc %0,%1,%2
2890	adc %0,%1,%2"
2891  ; if we have a bad schedule after sched2, split.
2892  "reload_completed
2893   && !optimize_size && (!TARGET_ARC600_FAMILY)
2894   && arc_scheduling_not_expected ()
2895   && arc_sets_cc_p (prev_nonnote_insn (insn))
2896   /* If next comes a return or other insn that needs a delay slot,
2897      expect the adc to get into the delay slot.  */
2898   && next_nonnote_insn (insn)
2899   && !arc_need_delay (next_nonnote_insn (insn))
2900   /* Restore operands before emitting.  */
2901   && (extract_insn_cached (insn), 1)"
2902  [(set (match_dup 0) (match_dup 3))
2903   (cond_exec
2904     (ltu (reg:CC_C CC_REG) (const_int 0))
2905     (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))))]
2906  "operands[3] = simplify_gen_binary (PLUS, SImode, operands[1], operands[2]);"
2907  [(set_attr "cond" "use")
2908   (set_attr "type" "cc_arith")
2909   (set_attr "length" "4,4,4,4,8")])
2910
2911; combiner-splitter cmp / scc -> cmp / adc
2912(define_split
2913  [(set (match_operand:SI 0 "dest_reg_operand" "")
2914	(gtu:SI (match_operand:SI 1 "register_operand" "")
2915		(match_operand:SI 2 "register_operand" "")))
2916   (clobber (reg CC_REG))]
2917  ""
2918  [(set (reg:CC_C CC_REG) (compare:CC_C (match_dup 2) (match_dup 1)))
2919   (set (match_dup 0) (ltu:SI (reg:CC_C CC_REG) (const_int 0)))])
2920
2921; combine won't work when an intermediate result is used later...
2922; add %0,%1,%2 ` cmp %0,%[12] -> add.f %0,%1,%2
2923(define_peephole2
2924  [(set (match_operand:SI 0 "dest_reg_operand" "")
2925	(plus:SI (match_operand:SI 1 "register_operand" "")
2926		 (match_operand:SI 2 "nonmemory_operand" "")))
2927   (set (reg:CC_C CC_REG)
2928	(compare:CC_C (match_dup 0)
2929		      (match_operand:SI 3 "nonmemory_operand" "")))]
2930  "rtx_equal_p (operands[1], operands[3])
2931   || rtx_equal_p (operands[2], operands[3])"
2932  [(parallel
2933     [(set (reg:CC_C CC_REG)
2934	   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))
2935      (set (match_dup 0)
2936	   (plus:SI (match_dup 1) (match_dup 2)))])])
2937
2938; ??? need to delve into combine to find out why this is not useful.
2939; We'd like to be able to grok various C idioms for carry bit usage.
2940;(define_insn "*adc_0"
2941;  [(set (match_operand:SI 0 "dest_reg_operand" "=w")
2942;	(plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
2943;		 (match_operand:SI 1 "register_operand" "c")))]
2944;  ""
2945;  "adc %0,%1,0"
2946;  [(set_attr "cond" "use")
2947;   (set_attr "type" "cc_arith")
2948;   (set_attr "length" "4")])
2949;
2950;(define_split
2951;  [(set (match_operand:SI 0 "dest_reg_operand" "=w")
2952;	(plus:SI (gtu:SI (match_operand:SI 1 "register_operand" "c")
2953;			 (match_operand:SI 2 "register_operand" "c"))
2954;		 (match_operand:SI 3 "register_operand" "c")))
2955;   (clobber (reg CC_REG))]
2956;  ""
2957;  [(set (reg:CC_C CC_REG) (compare:CC_C (match_dup 2) (match_dup 1)))
2958;   (set (match_dup 0)
2959;	(plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
2960;		 (match_dup 3)))])
2961
2962(define_expand "subsi3"
2963  [(set (match_operand:SI 0 "dest_reg_operand" "")
2964	(minus:SI (match_operand:SI 1 "nonmemory_operand" "")
2965		 (match_operand:SI 2 "nonmemory_operand" "")))]
2966  ""
2967  "
2968{
2969  int c = 1;
2970
2971  if (!register_operand (operands[2], SImode))
2972    {
2973      operands[1] = force_reg (SImode, operands[1]);
2974      c = 2;
2975    }
2976  if (flag_pic && arc_raw_symbolic_reference_mentioned_p (operands[c], false))
2977    operands[c] = force_reg (SImode, operands[c]);
2978  else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[c], Pmode))
2979      operands[c] = force_reg (SImode, arc_rewrite_small_data (operands[c]));
2980}")
2981
2982; the casesi expander might generate a sub of zero, so we have to recognize it.
2983; combine should make such an insn go away.
2984(define_insn_and_split "subsi3_insn"
2985  [(set (match_operand:SI 0 "dest_reg_operand"           "=Rcqq,Rcqq,Rcw,Rcw,w,w,w,  w,  w,  w")
2986	(minus:SI (match_operand:SI 1 "nonmemory_operand"    "0,Rcqq,  0, cL,c,L,I,Cal,Cal,  c")
2987		  (match_operand:SI 2 "nonmemory_operand" "Rcqq,Rcqq,  c,  0,c,c,0,  0,  c,Cal")))]
2988  "register_operand (operands[1], SImode)
2989   || register_operand (operands[2], SImode)"
2990  "@
2991    sub%? %0,%1,%2%&
2992    sub%? %0,%1,%2%&
2993    sub%? %0,%1,%2
2994    rsub%? %0,%2,%1
2995    sub %0,%1,%2
2996    rsub %0,%2,%1
2997    rsub %0,%2,%1
2998    rsub%? %0,%2,%1
2999    rsub %0,%2,%1
3000    sub %0,%1,%2"
3001  "reload_completed && get_attr_length (insn) == 8
3002   && satisfies_constraint_I (operands[1])
3003   && GET_CODE (PATTERN (insn)) != COND_EXEC"
3004  [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))]
3005  "split_subsi (operands);"
3006  [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false,false, false")
3007  (set_attr "length" "*,*,4,4,4,4,4,8,8,8")
3008  (set_attr "predicable" "yes,no,yes,yes,no,no,no,yes,no,no")
3009  (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond,canuse_limm,canuse,nocond,nocond")
3010  (set_attr "cpu_facility" "*,cd,*,*,*,*,*,*,*,*")
3011  ])
3012
3013(define_expand "subdi3"
3014  [(parallel [(set (match_operand:DI 0 "dest_reg_operand" "")
3015		   (minus:DI (match_operand:DI 1 "nonmemory_operand" "")
3016			     (match_operand:DI 2 "nonmemory_operand" "")))
3017	      (clobber (reg:CC CC_REG))])]
3018  ""
3019{
3020  if (!register_operand (operands[2], DImode))
3021    operands[1] = force_reg (DImode, operands[1]);
3022})
3023
3024(define_insn_and_split "subdi3_i"
3025  [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w,w,w,w")
3026	(minus:DI (match_operand:DI 1 "nonmemory_operand" "ci,0,ci,c,!i")
3027		  (match_operand:DI 2 "nonmemory_operand" "ci,ci,0,!i,c")))
3028   (clobber (reg:CC CC_REG))]
3029  "register_operand (operands[1], DImode)
3030   || register_operand (operands[2], DImode)"
3031  "#"
3032  "reload_completed"
3033  [(const_int 0)]
3034{
3035  int hi = !TARGET_BIG_ENDIAN;
3036  int lo = !hi;
3037  rtx l0 = operand_subword (operands[0], lo, 0, DImode);
3038  rtx h0 = operand_subword (operands[0], hi, 0, DImode);
3039  rtx l1 = operand_subword (operands[1], lo, 0, DImode);
3040  rtx h1 = operand_subword (operands[1], hi, 0, DImode);
3041  rtx l2 = operand_subword (operands[2], lo, 0, DImode);
3042  rtx h2 = operand_subword (operands[2], hi, 0, DImode);
3043
3044  if (rtx_equal_p (l0, h1) || rtx_equal_p (l0, h2))
3045    {
3046      h1 = simplify_gen_binary (MINUS, SImode, h1, h2);
3047      if (!rtx_equal_p (h0, h1))
3048	emit_insn (gen_rtx_SET (h0, h1));
3049      emit_insn (gen_sub_f (l0, l1, l2));
3050      emit_insn
3051	(gen_rtx_COND_EXEC
3052	  (VOIDmode,
3053	   gen_rtx_LTU (VOIDmode, gen_rtx_REG (CC_Cmode, CC_REG), GEN_INT (0)),
3054	   gen_rtx_SET (h0, plus_constant (SImode, h0, -1))));
3055      DONE;
3056    }
3057  emit_insn (gen_sub_f (l0, l1, l2));
3058  emit_insn (gen_sbc (h0, h1, h2, gen_rtx_REG (CCmode, CC_REG)));
3059  DONE;
3060}
3061  [(set_attr "cond" "clob")
3062   (set_attr "length" "16,16,16,20,20")])
3063
3064(define_insn "*sbc_0"
3065  [(set (match_operand:SI 0 "dest_reg_operand" "=w")
3066	(minus:SI (match_operand:SI 1 "register_operand" "c")
3067		  (ltu:SI (match_operand:CC_C 2 "cc_use_register")
3068			  (const_int 0))))]
3069  ""
3070  "sbc %0,%1,0"
3071  [(set_attr "cond" "use")
3072   (set_attr "type" "cc_arith")
3073   (set_attr "length" "4")])
3074
3075; w/c/c comes first (rather than Rcw/0/C_0) to prevent the middle-end
3076; needlessly prioritizing the matching constraint.
3077; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional execution
3078; is used where possible.
3079(define_insn_and_split "sbc"
3080  [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w")
3081	(minus:SI (minus:SI (match_operand:SI 1 "nonmemory_operand"
3082						"c,0,c,0,cCal")
3083			    (ltu:SI (match_operand:CC_C 3 "cc_use_register")
3084				    (const_int 0)))
3085		  (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))]
3086  "register_operand (operands[1], SImode)
3087   || register_operand (operands[2], SImode)"
3088  "@
3089	sbc %0,%1,%2
3090	sub.cs %0,%1,1
3091	sbc %0,%1,%2
3092	sbc %0,%1,%2
3093	sbc %0,%1,%2"
3094  ; if we have a bad schedule after sched2, split.
3095  "reload_completed
3096   && !optimize_size && (!TARGET_ARC600_FAMILY)
3097   && arc_scheduling_not_expected ()
3098   && arc_sets_cc_p (prev_nonnote_insn (insn))
3099   /* If next comes a return or other insn that needs a delay slot,
3100      expect the adc to get into the delay slot.  */
3101   && next_nonnote_insn (insn)
3102   && !arc_need_delay (next_nonnote_insn (insn))
3103   /* Restore operands before emitting.  */
3104   && (extract_insn_cached (insn), 1)"
3105  [(set (match_dup 0) (match_dup 4))
3106   (cond_exec
3107     (ltu (reg:CC_C CC_REG) (const_int 0))
3108     (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))))]
3109  "operands[4] = simplify_gen_binary (MINUS, SImode, operands[1], operands[2]);"
3110  [(set_attr "cond" "use")
3111   (set_attr "type" "cc_arith")
3112   (set_attr "length" "4,4,4,4,8")])
3113
3114(define_insn "sub_f"
3115  [(set (reg:CC CC_REG)
3116	(compare:CC (match_operand:SI 1 "nonmemory_operand" " c,L,0,I,c,Cal")
3117		    (match_operand:SI 2 "nonmemory_operand" "cL,c,I,0,Cal,c")))
3118   (set (match_operand:SI 0 "dest_reg_operand" "=w,w,Rcw,Rcw,w,w")
3119	(minus:SI (match_dup 1) (match_dup 2)))]
3120  "register_operand (operands[1], SImode)
3121   || register_operand (operands[2], SImode)"
3122  "@
3123	sub.f %0,%1,%2
3124	rsub.f %0,%2,%1
3125	sub.f %0,%1,%2
3126	rsub.f %0,%2,%1
3127	sub.f %0,%1,%2
3128	sub.f %0,%1,%2"
3129  [(set_attr "type" "compare")
3130   (set_attr "length" "4,4,4,4,8,8")])
3131
3132; combine won't work when an intermediate result is used later...
3133; add %0,%1,%2 ` cmp %0,%[12] -> add.f %0,%1,%2
3134(define_peephole2
3135  [(set (reg:CC CC_REG)
3136	(compare:CC (match_operand:SI 1 "register_operand" "")
3137		    (match_operand:SI 2 "nonmemory_operand" "")))
3138   (set (match_operand:SI 0 "dest_reg_operand" "")
3139	(minus:SI (match_dup 1) (match_dup 2)))]
3140  ""
3141  [(parallel
3142     [(set (reg:CC CC_REG) (compare:CC (match_dup 1) (match_dup 2)))
3143      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])])
3144
3145(define_peephole2
3146  [(set (reg:CC CC_REG)
3147	(compare:CC (match_operand:SI 1 "register_operand" "")
3148		    (match_operand:SI 2 "nonmemory_operand" "")))
3149   (set (match_operand 3 "" "") (match_operand 4 "" ""))
3150   (set (match_operand:SI 0 "dest_reg_operand" "")
3151	(minus:SI (match_dup 1) (match_dup 2)))]
3152  "!reg_overlap_mentioned_p (operands[3], operands[1])
3153   && !reg_overlap_mentioned_p (operands[3], operands[2])
3154   && !reg_overlap_mentioned_p (operands[0], operands[4])
3155   && !reg_overlap_mentioned_p (operands[0], operands[3])"
3156  [(parallel
3157     [(set (reg:CC CC_REG) (compare:CC (match_dup 1) (match_dup 2)))
3158      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
3159   (set (match_dup 3) (match_dup 4))])
3160
3161(define_insn "*add_n"
3162  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,W,W,w,w")
3163	(plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "Rcqq,c,c,c,c,c")
3164	                    (match_operand:SI 2 "_1_2_3_operand" ""))
3165		 (match_operand:SI 3 "nonmemory_operand" "0,0,c,?Cal,?c,??Cal")))]
3166  ""
3167  "add%c2%? %0,%3,%1%&"
3168  [(set_attr "type" "shift")
3169   (set_attr "length" "*,4,4,8,4,8")
3170   (set_attr "predicable" "yes,yes,no,no,no,no")
3171   (set_attr "cond" "canuse,canuse,nocond,nocond,nocond,nocond")
3172   (set_attr "iscompact" "maybe,false,false,false,false,false")])
3173
3174(define_insn "*add_n"
3175  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,W,W,w,w")
3176	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "Rcqq,c,c,c,c,c")
3177			  (match_operand:SI 2 "_2_4_8_operand" ""))
3178		 (match_operand:SI 3 "nonmemory_operand" "0,0,c,?Cal,?c,??Cal")))]
3179  ""
3180  "add%z2%? %0,%3,%1%&"
3181  [(set_attr "type" "shift")
3182   (set_attr "length" "*,4,4,8,4,8")
3183   (set_attr "predicable" "yes,yes,no,no,no,no")
3184   (set_attr "cond" "canuse,canuse,nocond,nocond,nocond,nocond")
3185   (set_attr "iscompact" "maybe,false,false,false,false,false")])
3186
3187;; N.B. sub[123] has the operands of the MINUS in the opposite order from
3188;; what synth_mult likes.
3189(define_insn "*sub_n"
3190  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
3191	(minus:SI (match_operand:SI 1 "nonmemory_operand" "0,c,?Cal")
3192		  (ashift:SI (match_operand:SI 2 "register_operand" "c,c,c")
3193			     (match_operand:SI 3 "_1_2_3_operand" ""))))]
3194  ""
3195  "sub%c3%? %0,%1,%2"
3196  [(set_attr "type" "shift")
3197   (set_attr "length" "4,4,8")
3198   (set_attr "predicable" "yes,no,no")
3199   (set_attr "cond" "canuse,nocond,nocond")
3200   (set_attr "iscompact" "false")])
3201
3202(define_insn "*sub_n"
3203  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
3204	(minus:SI (match_operand:SI 1 "nonmemory_operand" "0,c,?Cal")
3205		  (mult:SI (match_operand:SI 2 "register_operand" "c,c,c")
3206			   (match_operand:SI 3 "_2_4_8_operand" ""))))]
3207  ""
3208  "sub%z3%? %0,%1,%2"
3209  [(set_attr "type" "shift")
3210   (set_attr "length" "4,4,8")
3211   (set_attr "predicable" "yes,no,no")
3212   (set_attr "cond" "canuse,nocond,nocond")
3213   (set_attr "iscompact" "false")])
3214
3215; ??? check if combine matches this.
3216(define_insn "*bset"
3217  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
3218	(ior:SI (ashift:SI (const_int 1)
3219			   (match_operand:SI 1 "nonmemory_operand" "cL,cL,c"))
3220		(match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
3221  ""
3222  "bset%? %0,%2,%1"
3223  [(set_attr "length" "4,4,8")
3224   (set_attr "predicable" "yes,no,no")
3225   (set_attr "cond" "canuse,nocond,nocond")]
3226)
3227
3228; ??? check if combine matches this.
3229(define_insn "*bxor"
3230  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
3231	(xor:SI (ashift:SI (const_int 1)
3232			   (match_operand:SI 1 "nonmemory_operand" "cL,cL,c"))
3233		(match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
3234  ""
3235  "bxor%? %0,%2,%1"
3236  [(set_attr "length" "4,4,8")
3237   (set_attr "predicable" "yes,no,no")
3238   (set_attr "cond" "canuse,nocond,nocond")]
3239)
3240
3241; ??? check if combine matches this.
3242(define_insn "*bclr"
3243  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
3244	(and:SI (not:SI (ashift:SI (const_int 1)
3245				   (match_operand:SI 1 "nonmemory_operand" "cL,cL,c")))
3246		(match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
3247  ""
3248  "bclr%? %0,%2,%1"
3249  [(set_attr "length" "4,4,8")
3250   (set_attr "predicable" "yes,no,no")
3251   (set_attr "cond" "canuse,nocond,nocond")]
3252)
3253
3254; ??? FIXME: find combine patterns for bmsk.
3255
3256;;Following are the define_insns added for the purpose of peephole2's
3257
3258; see also iorsi3 for use with constant bit number.
3259(define_insn "*bset_insn"
3260  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
3261	(ior:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
3262		(ashift:SI (const_int 1)
3263			   (match_operand:SI 2 "nonmemory_operand" "cL,cL,c"))) ) ]
3264  ""
3265  "@
3266     bset%? %0,%1,%2 ;;peep2, constr 1
3267     bset %0,%1,%2 ;;peep2, constr 2
3268     bset %0,%1,%2 ;;peep2, constr 3"
3269  [(set_attr "length" "4,4,8")
3270   (set_attr "predicable" "yes,no,no")
3271   (set_attr "cond" "canuse,nocond,nocond")]
3272)
3273
3274; see also xorsi3 for use with constant bit number.
3275(define_insn "*bxor_insn"
3276  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
3277	(xor:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
3278		(ashift:SI (const_int 1)
3279			(match_operand:SI 2 "nonmemory_operand" "cL,cL,c"))) ) ]
3280  ""
3281  "@
3282     bxor%? %0,%1,%2
3283     bxor %0,%1,%2
3284     bxor %0,%1,%2"
3285  [(set_attr "length" "4,4,8")
3286   (set_attr "predicable" "yes,no,no")
3287   (set_attr "cond" "canuse,nocond,nocond")]
3288)
3289
3290; see also andsi3 for use with constant bit number.
3291(define_insn "*bclr_insn"
3292  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
3293	(and:SI (not:SI (ashift:SI (const_int 1)
3294				   (match_operand:SI 2 "nonmemory_operand" "cL,rL,r")))
3295		(match_operand:SI 1 "nonmemory_operand" "0,c,Cal")))]
3296  ""
3297  "@
3298     bclr%? %0,%1,%2
3299     bclr %0,%1,%2
3300     bclr %0,%1,%2"
3301  [(set_attr "length" "4,4,8")
3302   (set_attr "predicable" "yes,no,no")
3303   (set_attr "cond" "canuse,nocond,nocond")]
3304)
3305
3306; see also andsi3 for use with constant bit number.
3307(define_insn "*bmsk_insn"
3308  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
3309	(and:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
3310		(plus:SI (ashift:SI (const_int 1)
3311				    (plus:SI (match_operand:SI 2 "nonmemory_operand" "rL,rL,r")
3312					     (const_int 1)))
3313			 (const_int -1))))]
3314  ""
3315  "@
3316     bmsk%? %0,%1,%2
3317     bmsk %0,%1,%2
3318     bmsk %0,%1,%2"
3319  [(set_attr "length" "4,4,8")
3320   (set_attr "predicable" "yes,no,no")
3321   (set_attr "cond" "canuse,nocond,nocond")]
3322)
3323
3324;;Instructions added for peephole2s end
3325
3326;; Boolean instructions.
3327
3328(define_expand "andsi3"
3329  [(set (match_operand:SI 0 "dest_reg_operand" "")
3330	(and:SI (match_operand:SI 1 "nonimmediate_operand" "")
3331		(match_operand:SI 2 "nonmemory_operand" "")))]
3332  ""
3333  "if (!satisfies_constraint_Cux (operands[2]))
3334     operands[1] = force_reg (SImode, operands[1]);
3335   else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[1], Pmode))
3336     operands[1] = arc_rewrite_small_data (operands[1]);")
3337
3338(define_insn "andsi3_i"
3339  [(set (match_operand:SI 0 "dest_reg_operand"          "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw,   Rcw,Rcw,Rcw,Rcw, w,     w,  w,  w,Rrq,w,Rcw,  w,W")
3340	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq,   0,   0,Rcqq,  0,  c,     0,  0,  0,  0, c,     c,  c,  c,Rrq,0,  0,  c,o")
3341		(match_operand:SI 2 "nonmemory_operand"  "Rcqq,  0, C1p, Ccp, Cux, cL,  0,C2pC1p,Ccp,CnL,  I,Lc,C2pC1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))]
3342  "(register_operand (operands[1], SImode)
3343    && nonmemory_operand (operands[2], SImode))
3344   || (memory_operand (operands[1], SImode)
3345       && satisfies_constraint_Cux (operands[2]))"
3346{
3347  switch (which_alternative)
3348    {
3349    case 0: case 5: case 10: case 11: case 16: case 17: case 18:
3350      return "and%? %0,%1,%2%&";
3351    case 1: case 6:
3352      return "and%? %0,%2,%1%&";
3353    case 2:
3354      return "bmsk%? %0,%1,%Z2%&";
3355    case 7: case 12:
3356     if (satisfies_constraint_C2p (operands[2]))
3357       {
3358	operands[2] = GEN_INT ((~INTVAL (operands[2])));
3359	return "bmskn%? %0,%1,%Z2%&";
3360       }
3361     else
3362       {
3363	return "bmsk%? %0,%1,%Z2%&";
3364       }
3365    case 3: case 8: case 13:
3366      return "bclr%? %0,%1,%M2%&";
3367    case 4:
3368      return (INTVAL (operands[2]) == 0xff
3369	      ? "extb%? %0,%1%&" : "ext%_%? %0,%1%&");
3370    case 9: case 14: return \"bic%? %0,%1,%n2-1\";
3371    case 15:
3372      return "movb.cl %0,%1,%p2,%p2,%s2";
3373
3374    case 19:
3375      const char *tmpl;
3376
3377      if (satisfies_constraint_Ucm (operands[1]))
3378	tmpl = (INTVAL (operands[2]) == 0xff
3379		? "xldb%U1 %0,%1" : "xld%_%U1 %0,%1");
3380      else
3381	tmpl = INTVAL (operands[2]) == 0xff ? "ldb %0,%1" : "ld%_ %0,%1";
3382
3383      if (TARGET_BIG_ENDIAN)
3384	{
3385	  rtx xop[2];
3386
3387	  xop[0] = operands[0];
3388	  xop[1] = adjust_address (operands[1], QImode,
3389				   INTVAL (operands[2]) == 0xff ? 3 : 2);
3390	  output_asm_insn (tmpl, xop);
3391	  return "";
3392	}
3393      return tmpl;
3394    default:
3395      gcc_unreachable ();
3396    }
3397}
3398  [(set_attr "iscompact" "maybe,maybe,maybe,maybe,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false")
3399   (set_attr "type" "binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,shift,binary,binary,binary,load")
3400   (set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,4,4,4,4,4,8,8,*")
3401   (set_attr "predicable" "no,no,no,no,no,yes,yes,yes,yes,yes,no,no,no,no,no,no,no,yes,no,no")
3402   (set_attr "cond" "canuse,canuse,canuse,canuse,nocond,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,nocond,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
3403
3404; combiner splitter, pattern found in ldtoa.c .
3405; and op3,op0,op1 / cmp op3,op2 -> add op3,op0,op4 / bmsk.f 0,op3,op1
3406(define_split
3407  [(set (reg:CC_Z CC_REG)
3408	(compare:CC_Z (and:SI (match_operand:SI 0 "register_operand" "")
3409			      (match_operand 1 "const_int_operand" ""))
3410		      (match_operand 2 "const_int_operand" "")))
3411   (clobber (match_operand:SI 3 "register_operand" ""))]
3412  "((INTVAL (operands[1]) + 1) & INTVAL (operands[1])) == 0"
3413  [(set (match_dup 3)
3414	(plus:SI (match_dup 0) (match_dup 4)))
3415   (set (reg:CC_Z CC_REG)
3416	(compare:CC_Z (and:SI (match_dup 3) (match_dup 1))
3417		      (const_int 0)))]
3418  "operands[4] = GEN_INT ( -(~INTVAL (operands[1]) | INTVAL (operands[2])));")
3419
3420;;bic define_insn that allows limm to be the first operand
3421(define_insn "*bicsi3_insn"
3422   [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,Rcw,Rcw,w,w,w")
3423 	(and:SI	(not:SI (match_operand:SI 1 "nonmemory_operand" "Rcqq,Lc,I,Cal,Lc,Cal,c"))
3424 		(match_operand:SI 2 "nonmemory_operand" "0,0,0,0,c,c,Cal")))]
3425  ""
3426  "@
3427   bic%? %0, %2, %1%& ;;constraint 0
3428   bic%? %0,%2,%1  ;;constraint 1
3429   bic %0,%2,%1    ;;constraint 2, FIXME: will it ever get generated ???
3430   bic%? %0,%2,%1  ;;constraint 3, FIXME: will it ever get generated ???
3431   bic %0,%2,%1    ;;constraint 4
3432   bic %0,%2,%1    ;;constraint 5, FIXME: will it ever get generated ???
3433   bic %0,%2,%1    ;;constraint 6"
3434  [(set_attr "length" "*,4,4,8,4,8,8")
3435  (set_attr "iscompact" "maybe, false, false, false, false, false, false")
3436  (set_attr "predicable" "no,yes,no,yes,no,no,no")
3437  (set_attr "cond" "canuse,canuse,canuse_limm,canuse,nocond,nocond,nocond")])
3438
3439(define_insn "iorsi3"
3440  [(set (match_operand:SI 0 "dest_reg_operand"        "=Rcqq,Rcq,Rcqq,Rcw,Rcw,Rcw,Rcw,w,  w,w,Rcw,  w")
3441	(ior:SI (match_operand:SI 1 "nonmemory_operand" "% 0,Rcq,   0,  0,  c,  0, 0, c,  c,0,  0,  c")
3442		(match_operand:SI 2 "nonmemory_operand" "Rcqq, 0, C0p, cL,  0,C0p, I,cL,C0p,I,Cal,Cal")))]
3443  ""
3444  "*
3445  switch (which_alternative)
3446    {
3447    case 0: case 3: case 6: case 7: case 9: case 10: case 11:
3448      return \"or%? %0,%1,%2%&\";
3449    case 1: case 4:
3450      return \"or%? %0,%2,%1%&\";
3451    case 2: case 5: case 8:
3452      return \"bset%? %0,%1,%z2%&\";
3453    default:
3454      gcc_unreachable ();
3455    }"
3456  [(set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false")
3457   (set_attr "length" "*,*,*,4,4,4,4,4,4,4,8,8")
3458   (set_attr "predicable" "no,no,no,yes,yes,yes,no,no,no,no,yes,no")
3459   (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,canuse,nocond")])
3460
3461(define_insn "xorsi3"
3462  [(set (match_operand:SI 0 "dest_reg_operand"          "=Rcqq,Rcq,Rcw,Rcw,Rcw,Rcw, w,  w,w,  w,  w")
3463	(xor:SI (match_operand:SI 1 "register_operand"  "%0,   Rcq,  0,  c,  0,  0, c,  c,0,  0,  c")
3464		(match_operand:SI 2 "nonmemory_operand" " Rcqq,  0, cL,  0,C0p,  I,cL,C0p,I,Cal,Cal")))]
3465  ""
3466  "*
3467  switch (which_alternative)
3468    {
3469    case 0: case 2: case 5: case 6: case 8: case 9: case 10:
3470      return \"xor%? %0,%1,%2%&\";
3471    case 1: case 3:
3472      return \"xor%? %0,%2,%1%&\";
3473    case 4: case 7:
3474      return \"bxor%? %0,%1,%z2\";
3475    default:
3476      gcc_unreachable ();
3477    }
3478  "
3479  [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false,false,false,false")
3480   (set_attr "type" "binary")
3481   (set_attr "length" "*,*,4,4,4,4,4,4,4,8,8")
3482   (set_attr "predicable" "no,no,yes,yes,yes,no,no,no,no,yes,no")
3483   (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,canuse,nocond")])
3484
3485(define_insn "negsi2"
3486  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcqq,Rcw,w")
3487	(neg:SI (match_operand:SI 1 "register_operand" "0,Rcqq,0,c")))]
3488  ""
3489  "neg%? %0,%1%&"
3490  [(set_attr "type" "unary")
3491   (set_attr "iscompact" "maybe,true,false,false")
3492   (set_attr "predicable" "no,no,yes,no")])
3493
3494(define_insn "one_cmplsi2"
3495  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w")
3496	(not:SI (match_operand:SI 1 "register_operand" "Rcqq,c")))]
3497  ""
3498  "not%? %0,%1%&"
3499  [(set_attr "type" "unary,unary")
3500   (set_attr "iscompact" "true,false")])
3501
3502(define_insn_and_split "one_cmpldi2"
3503  [(set (match_operand:DI 0 "dest_reg_operand" "=q,w")
3504	(not:DI (match_operand:DI 1 "register_operand" "q,c")))]
3505  ""
3506  "#"
3507  "&& reload_completed"
3508  [(set (match_dup 2) (not:SI (match_dup 3)))
3509   (set (match_dup 4) (not:SI (match_dup 5)))]
3510{
3511  int swap = (true_regnum (operands[0]) == true_regnum (operands[1]) + 1);
3512
3513  operands[2] = operand_subword (operands[0], 0+swap, 0, DImode);
3514  operands[3] = operand_subword (operands[1], 0+swap, 0, DImode);
3515  operands[4] = operand_subword (operands[0], 1-swap, 0, DImode);
3516  operands[5] = operand_subword (operands[1], 1-swap, 0, DImode);
3517}
3518  [(set_attr "type" "unary,unary")
3519   (set_attr "cond" "nocond,nocond")
3520   (set_attr "length" "4,8")])
3521
3522;; Shift instructions.
3523
3524(define_expand "ashlsi3"
3525  [(set (match_operand:SI 0 "dest_reg_operand" "")
3526	(ashift:SI (match_operand:SI 1 "register_operand" "")
3527		   (match_operand:SI 2 "nonmemory_operand" "")))]
3528  ""
3529  "
3530{
3531  if (!TARGET_BARREL_SHIFTER)
3532    {
3533      emit_shift (ASHIFT, operands[0], operands[1], operands[2]);
3534      DONE;
3535    }
3536}")
3537
3538(define_expand "ashrsi3"
3539  [(set (match_operand:SI 0 "dest_reg_operand" "")
3540	(ashiftrt:SI (match_operand:SI 1 "register_operand" "")
3541		     (match_operand:SI 2 "nonmemory_operand" "")))]
3542  ""
3543  "
3544{
3545  if (!TARGET_BARREL_SHIFTER)
3546    {
3547      emit_shift (ASHIFTRT, operands[0], operands[1], operands[2]);
3548      DONE;
3549    }
3550}")
3551
3552(define_expand "lshrsi3"
3553  [(set (match_operand:SI 0 "dest_reg_operand" "")
3554	(lshiftrt:SI (match_operand:SI 1 "register_operand" "")
3555		     (match_operand:SI 2 "nonmemory_operand" "")))]
3556  ""
3557  "
3558{
3559  if (!TARGET_BARREL_SHIFTER)
3560    {
3561      emit_shift (LSHIFTRT, operands[0], operands[1], operands[2]);
3562      DONE;
3563    }
3564}")
3565
3566(define_insn "shift_si3"
3567  [(set (match_operand:SI 0 "dest_reg_operand" "=r")
3568	(match_operator:SI 3 "shift4_operator"
3569			   [(match_operand:SI 1 "register_operand" "0")
3570			    (match_operand:SI 2 "const_int_operand" "n")]))
3571   (clobber (match_scratch:SI 4 "=&r"))
3572   (clobber (reg:CC CC_REG))
3573  ]
3574  "!TARGET_BARREL_SHIFTER"
3575  "* return output_shift (operands);"
3576  [(set_attr "type" "shift")
3577   (set_attr "length" "16")])
3578
3579(define_insn "shift_si3_loop"
3580  [(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
3581	(match_operator:SI 3 "shift_operator"
3582			   [(match_operand:SI 1 "register_operand" "0,0")
3583			    (match_operand:SI 2 "nonmemory_operand" "rn,Cal")]))
3584   (clobber (match_scratch:SI 4 "=X,X"))
3585   (clobber (reg:SI LP_COUNT))
3586   (clobber (reg:SI LP_START))
3587   (clobber (reg:SI LP_END))
3588   (clobber (reg:CC CC_REG))
3589  ]
3590  "!TARGET_BARREL_SHIFTER"
3591  "* return output_shift (operands);"
3592  [(set_attr "type" "shift")
3593   (set_attr "length" "16,20")])
3594
3595; asl, asr, lsr patterns:
3596; There is no point in including an 'I' alternative since only the lowest 5
3597; bits are used for the shift.  OTOH Cal can be useful if the shift amount
3598; is defined in an external symbol, as we don't have special relocations
3599; to truncate a symbol in a u6 immediate; but that's rather exotic, so only
3600; provide one alternatice for this, without condexec support.
3601(define_insn "*ashlsi3_insn"
3602  [(set (match_operand:SI 0 "dest_reg_operand"           "=Rcq,Rcqq,Rcqq,Rcw, w,   w")
3603	(ashift:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCal")
3604		   (match_operand:SI 2 "nonmemory_operand"  "K,  K,RcqqM, cL,cL,cCal")))]
3605  "TARGET_BARREL_SHIFTER
3606   && (register_operand (operands[1], SImode)
3607       || register_operand (operands[2], SImode))"
3608  "asl%? %0,%1,%2%&"
3609  [(set_attr "type" "shift")
3610   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
3611   (set_attr "predicable" "no,no,no,yes,no,no")
3612   (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
3613
3614(define_insn "*ashrsi3_insn"
3615  [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcq,Rcqq,Rcqq,Rcw, w,   w")
3616	(ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCal")
3617		     (match_operand:SI 2 "nonmemory_operand"  "K,  K,RcqqM, cL,cL,cCal")))]
3618  "TARGET_BARREL_SHIFTER
3619   && (register_operand (operands[1], SImode)
3620       || register_operand (operands[2], SImode))"
3621  "asr%? %0,%1,%2%&"
3622  [(set_attr "type" "shift")
3623   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
3624   (set_attr "predicable" "no,no,no,yes,no,no")
3625   (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
3626
3627(define_insn "*lshrsi3_insn"
3628  [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcq,Rcqq,Rcqq,Rcw, w,   w")
3629	(lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCal")
3630		     (match_operand:SI 2 "nonmemory_operand"  "N,  N,RcqqM, cL,cL,cCal")))]
3631  "TARGET_BARREL_SHIFTER
3632   && (register_operand (operands[1], SImode)
3633       || register_operand (operands[2], SImode))"
3634  "*return (which_alternative <= 1 && !arc_ccfsm_cond_exec_p ()
3635	    ?  \"lsr%? %0,%1%&\" : \"lsr%? %0,%1,%2%&\");"
3636  [(set_attr "type" "shift")
3637   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
3638   (set_attr "predicable" "no,no,no,yes,no,no")
3639   (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
3640
3641(define_insn "rotrsi3"
3642  [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcw, w,   w")
3643	(rotatert:SI (match_operand:SI 1 "register_operand"  " 0,cL,cCal")
3644		     (match_operand:SI 2 "nonmemory_operand" "cL,cL,cCal")))]
3645  "TARGET_BARREL_SHIFTER"
3646  "ror%? %0,%1,%2"
3647  [(set_attr "type" "shift,shift,shift")
3648   (set_attr "predicable" "yes,no,no")
3649   (set_attr "length" "4,4,8")])
3650
3651;; Compare / branch instructions.
3652
3653(define_expand "cbranchsi4"
3654  [(set (reg:CC CC_REG)
3655	(compare:CC (match_operand:SI 1 "nonmemory_operand" "")
3656		    (match_operand:SI 2 "nonmemory_operand" "")))
3657   (set (pc)
3658	(if_then_else
3659	      (match_operator 0 "ordered_comparison_operator" [(reg CC_REG)
3660							       (const_int 0)])
3661	      (label_ref (match_operand 3 "" ""))
3662	      (pc)))]
3663  ""
3664{
3665  gcc_assert (XEXP (operands[0], 0) == operands[1]);
3666  gcc_assert (XEXP (operands[0], 1) == operands[2]);
3667  operands[0] = gen_compare_reg (operands[0], VOIDmode);
3668  emit_jump_insn (gen_branch_insn (operands[3], operands[0]));
3669  DONE;
3670})
3671
3672;; ??? Could add a peephole to generate compare with swapped operands and
3673;; modifed cc user if second, but not first operand is a compact register.
3674(define_insn "cmpsi_cc_insn_mixed"
3675  [(set (reg:CC CC_REG)
3676	(compare:CC (match_operand:SI 0 "register_operand" "Rcq#q,Rcqq,  h, c, c,qRcq,c")
3677		    (match_operand:SI 1 "nonmemory_operand"   "cO,  hO,Cm1,cI,cL, Cal,Cal")))]
3678  ""
3679  "cmp%? %0,%B1%&"
3680  [(set_attr "type" "compare")
3681   (set_attr "iscompact" "true,true,true,false,false,true_limm,false")
3682   (set_attr "predicable" "no,no,no,no,yes,no,yes")
3683   (set_attr "cond" "set")
3684   (set_attr "length" "*,*,*,4,4,*,8")
3685   (set_attr "cpu_facility" "av1,av2,*,*,*,*,*")])
3686
3687(define_insn "*cmpsi_cc_zn_insn"
3688  [(set (reg:CC_ZN CC_REG)
3689	(compare:CC_ZN (match_operand:SI 0 "register_operand"  "qRcq,c")
3690		       (const_int 0)))]
3691  ""
3692  "tst%? %0,%0%&"
3693  [(set_attr "type" "compare,compare")
3694   (set_attr "iscompact" "true,false")
3695   (set_attr "predicable" "no,yes")
3696   (set_attr "cond" "set_zn")
3697   (set_attr "length" "*,4")])
3698
3699; combiner pattern observed for unwind-dw2-fde.c:linear_search_fdes.
3700(define_insn "*btst"
3701  [(set (reg:CC_ZN CC_REG)
3702	(compare:CC_ZN
3703	  (zero_extract:SI (match_operand:SI 0 "register_operand" "Rcqq,c")
3704			   (const_int 1)
3705			   (match_operand:SI 1 "nonmemory_operand" "L,Lc"))
3706	  (const_int 0)))]
3707  ""
3708  "btst%? %0,%1"
3709  [(set_attr "iscompact" "true,false")
3710   (set_attr "predicable" "no,yes")
3711   (set_attr "cond" "set")
3712   (set_attr "type" "compare")
3713   (set_attr "length" "*,4")])
3714
3715; combine suffers from 'simplifications' that replace a one-bit zero
3716; extract with a shift if it can prove that the upper bits are zero.
3717; arc_reorg sees the code after sched2, which can have caused our
3718; inputs to be clobbered even if they were not clobbered before.
3719; Therefore, add a third way to convert btst / b{eq,ne} to bbit{0,1}
3720; OTOH, this is somewhat marginal, and can leat to out-of-range
3721; bbit (i.e. bad scheduling) and missed conditional execution,
3722; so make this an option.
3723(define_peephole2
3724  [(set (reg:CC_ZN CC_REG)
3725	(compare:CC_ZN
3726	  (zero_extract:SI (match_operand:SI 0 "register_operand" "")
3727			   (const_int 1)
3728			   (match_operand:SI 1 "nonmemory_operand" ""))
3729	  (const_int 0)))
3730   (set (pc)
3731	(if_then_else (match_operator 3 "equality_comparison_operator"
3732				      [(reg:CC_ZN CC_REG) (const_int 0)])
3733		      (label_ref (match_operand 2 "" ""))
3734		      (pc)))]
3735  "TARGET_BBIT_PEEPHOLE && peep2_regno_dead_p (2, CC_REG)"
3736  [(parallel [(set (pc)
3737		   (if_then_else
3738		     (match_op_dup 3
3739		       [(zero_extract:SI (match_dup 0)
3740					 (const_int 1) (match_dup 1))
3741			(const_int 0)])
3742		     (label_ref (match_dup 2))
3743		     (pc)))
3744	      (clobber (reg:CC_ZN CC_REG))])])
3745
3746(define_insn "*cmpsi_cc_z_insn"
3747  [(set (reg:CC_Z CC_REG)
3748	(compare:CC_Z (match_operand:SI 0 "register_operand"  "qRcq,c")
3749		      (match_operand:SI 1 "p2_immediate_operand"  "O,n")))]
3750  ""
3751  "@
3752	cmp%? %0,%1%&
3753	bxor.f 0,%0,%z1"
3754  [(set_attr "type" "compare,compare")
3755   (set_attr "iscompact" "true,false")
3756   (set_attr "cond" "set,set_zn")
3757   (set_attr "length" "*,4")])
3758
3759(define_insn "*cmpsi_cc_c_insn"
3760  [(set (reg:CC_C CC_REG)
3761	(compare:CC_C (match_operand:SI 0 "register_operand"  "Rcqq,Rcqq,  h, c,Rcqq,  c")
3762		      (match_operand:SI 1 "nonmemory_operand"   "cO,  hO,Cm1,cI, Cal,Cal")))]
3763  ""
3764  "cmp%? %0,%1%&"
3765  [(set_attr "type" "compare")
3766   (set_attr "iscompact" "true,true,true,false,true_limm,false")
3767   (set_attr "cond" "set")
3768   (set_attr "length" "*,*,*,4,*,8")
3769   (set_attr "cpu_facility" "av1,av2,*,*,*,*")])
3770
3771;; Next come the scc insns.
3772
3773(define_expand "cstoresi4"
3774  [(set (match_operand:SI 0 "dest_reg_operand" "")
3775	(match_operator:SI 1 "ordered_comparison_operator"
3776			   [(match_operand:SI 2 "nonmemory_operand" "")
3777			    (match_operand:SI 3 "nonmemory_operand" "")]))]
3778  ""
3779{
3780  if (!TARGET_CODE_DENSITY)
3781  {
3782   gcc_assert (XEXP (operands[1], 0) == operands[2]);
3783   gcc_assert (XEXP (operands[1], 1) == operands[3]);
3784   operands[1] = gen_compare_reg (operands[1], SImode);
3785   emit_insn (gen_scc_insn (operands[0], operands[1]));
3786   DONE;
3787  }
3788  if (!register_operand (operands[2], SImode))
3789    operands[2] = force_reg (SImode, operands[2]);
3790
3791})
3792
3793(define_mode_iterator SDF [(SF "TARGET_FP_SP_BASE || TARGET_OPTFPE")
3794			   (DF "TARGET_OPTFPE")])
3795
3796(define_expand "cstore<mode>4"
3797  [(set (reg:CC CC_REG)
3798	(compare:CC (match_operand:SDF 2 "register_operand" "")
3799		    (match_operand:SDF 3 "register_operand" "")))
3800   (set (match_operand:SI 0 "dest_reg_operand" "")
3801	(match_operator:SI 1 "comparison_operator" [(reg CC_REG)
3802						    (const_int 0)]))]
3803
3804  "TARGET_FP_SP_BASE || TARGET_OPTFPE"
3805{
3806  gcc_assert (XEXP (operands[1], 0) == operands[2]);
3807  gcc_assert (XEXP (operands[1], 1) == operands[3]);
3808  operands[1] = gen_compare_reg (operands[1], SImode);
3809  emit_insn (gen_scc_insn (operands[0], operands[1]));
3810  DONE;
3811})
3812
3813; We need a separate expander for this lest we loose the mode of CC_REG
3814; when match_operator substitutes the literal operand into the comparison.
3815(define_expand "scc_insn"
3816  [(set (match_operand:SI 0 "dest_reg_operand" "=w") (match_operand:SI 1 ""))])
3817
3818(define_insn_and_split "*scc_insn"
3819  [(set (match_operand:SI 0 "dest_reg_operand" "=w")
3820	(match_operator:SI 1 "proper_comparison_operator" [(reg CC_REG) (const_int 0)]))]
3821  ""
3822  "#"
3823  "reload_completed"
3824  [(set (match_dup 0) (const_int 1))
3825   (cond_exec
3826     (match_dup 1)
3827     (set (match_dup 0) (const_int 0)))]
3828{
3829  operands[1]
3830    = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[1]),
3831					 GET_MODE (XEXP (operands[1], 0))),
3832		      VOIDmode,
3833		      XEXP (operands[1], 0), XEXP (operands[1], 1));
3834}
3835  [(set_attr "type" "unary")])
3836
3837;; ??? At least for ARC600, we should use sbc b,b,s12 if we want a value
3838;; that is one lower if the carry flag is set.
3839
3840;; ??? Look up negscc insn.  See pa.md for example.
3841(define_insn "*neg_scc_insn"
3842  [(set (match_operand:SI 0 "dest_reg_operand" "=w")
3843	(neg:SI (match_operator:SI 1 "proper_comparison_operator"
3844		 [(reg CC_REG) (const_int 0)])))]
3845  ""
3846  "mov %0,-1\;sub.%D1 %0,%0,%0"
3847  [(set_attr "type" "unary")
3848   (set_attr "length" "8")])
3849
3850(define_insn "*not_scc_insn"
3851  [(set (match_operand:SI 0 "dest_reg_operand" "=w")
3852	(not:SI (match_operator:SI 1 "proper_comparison_operator"
3853		 [(reg CC_REG) (const_int 0)])))]
3854  ""
3855  "mov %0,1\;sub.%d1 %0,%0,%0"
3856  [(set_attr "type" "unary")
3857   (set_attr "length" "8")])
3858
3859; cond_exec patterns
3860(define_insn "*movsi_ne"
3861  [(cond_exec
3862     (ne (match_operand:CC_Z 2 "cc_use_register"    "Rcc,  Rcc,  Rcc,Rcc,Rcc") (const_int 0))
3863     (set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,Rcq#q,Rcq#q,  w,w")
3864	  (match_operand:SI 1 "nonmemory_operand"   "C_0,    h, ?Cal, Lc,?Cal")))]
3865  ""
3866  "@
3867	* current_insn_predicate = 0; return \"sub%?.ne %0,%0,%0%&\";
3868	* current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
3869	* current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
3870	mov.ne %0,%1
3871	mov.ne %0,%1"
3872  [(set_attr "type" "cmove")
3873   (set_attr "iscompact" "true,true,true_limm,false,false")
3874   (set_attr "length" "2,2,6,4,8")
3875   (set_attr "cpu_facility" "*,av2,av2,*,*")])
3876
3877(define_insn "*movsi_cond_exec"
3878  [(cond_exec
3879     (match_operator 3 "proper_comparison_operator"
3880       [(match_operand 2 "cc_register" "Rcc,Rcc") (const_int 0)])
3881     (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
3882	  (match_operand:SI 1 "nonmemory_operand" "LRac,?Cal")))]
3883  ""
3884  "mov.%d3 %0,%1"
3885  [(set_attr "type" "cmove")
3886   (set_attr "length" "4,8")])
3887
3888(define_insn "*commutative_cond_exec"
3889  [(cond_exec
3890     (match_operator 5 "proper_comparison_operator"
3891       [(match_operand 4 "cc_register" "Rcc,Rcc") (const_int 0)])
3892     (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
3893	  (match_operator:SI 3 "commutative_operator"
3894	    [(match_operand:SI 1 "register_operand" "%0,0")
3895	     (match_operand:SI 2 "nonmemory_operand" "cL,?Cal")])))]
3896  ""
3897{
3898  arc_output_commutative_cond_exec (operands, true);
3899  return "";
3900}
3901  [(set_attr "cond" "use")
3902   (set_attr "type" "cmove")
3903   (set_attr_alternative "length"
3904     [(const_int 4)
3905      (cond
3906	[(eq (symbol_ref "arc_output_commutative_cond_exec (operands, false)")
3907	     (const_int 4))
3908	 (const_int 4)]
3909	(const_int 8))])])
3910
3911(define_insn "*sub_cond_exec"
3912  [(cond_exec
3913     (match_operator 4 "proper_comparison_operator"
3914       [(match_operand 3 "cc_register" "Rcc,Rcc,Rcc") (const_int 0)])
3915     (set (match_operand:SI 0 "dest_reg_operand" "=w,w,w")
3916	  (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,cL,Cal")
3917		    (match_operand:SI 2 "nonmemory_operand" "cL,0,0"))))]
3918  ""
3919  "@
3920	sub.%d4 %0,%1,%2
3921	rsub.%d4 %0,%2,%1
3922	rsub.%d4 %0,%2,%1"
3923  [(set_attr "cond" "use")
3924   (set_attr "type" "cmove")
3925   (set_attr "length" "4,4,8")])
3926
3927(define_insn "*noncommutative_cond_exec"
3928  [(cond_exec
3929     (match_operator 5 "proper_comparison_operator"
3930       [(match_operand 4 "cc_register" "Rcc,Rcc") (const_int 0)])
3931     (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
3932	  (match_operator:SI 3 "noncommutative_operator"
3933	    [(match_operand:SI 1 "register_operand" "0,0")
3934	     (match_operand:SI 2 "nonmemory_operand" "cL,Cal")])))]
3935  ""
3936  "%O3.%d5 %0,%1,%2"
3937  [(set_attr "cond" "use")
3938   (set_attr "type" "cmove")
3939   (set_attr "length" "4,8")])
3940
3941;; These control RTL generation for conditional jump insns
3942;; Match both normal and inverted jump.
3943
3944; We need a separate expander for this lest we loose the mode of CC_REG
3945; when match_operator substitutes the literal operand into the comparison.
3946(define_expand "branch_insn"
3947  [(set (pc)
3948	(if_then_else (match_operand 1 "" "")
3949		      (label_ref (match_operand 0 "" ""))
3950		      (pc)))])
3951
3952; When estimating sizes during arc_reorg, when optimizing for speed, there
3953; are three reasons why we need to consider branches to be length 6:
3954; - annull-false delay slot insns are implemented using conditional execution,
3955;   thus preventing short insn formation where used.
3956; - for ARC600: annull-true delay slot isnns are implemented where possile
3957;   using conditional execution, preventing short insn formation where used.
3958; - for ARC700: likely or somewhat likely taken branches are made long and
3959;   unaligned if possible to avoid branch penalty.
3960(define_insn "*branch_insn"
3961  [(set (pc)
3962	(if_then_else (match_operator 1 "proper_comparison_operator"
3963				      [(reg CC_REG) (const_int 0)])
3964		      (label_ref (match_operand 0 "" ""))
3965		      (pc)))]
3966  ""
3967  "*
3968{
3969  if (arc_ccfsm_branch_deleted_p ())
3970    {
3971      arc_ccfsm_record_branch_deleted ();
3972      return \"; branch deleted, next insns conditionalized\";
3973    }
3974  else
3975    {
3976      arc_ccfsm_record_condition (operands[1], false, insn, 0);
3977      if (get_attr_length (insn) == 2)
3978	 return \"b%d1%? %^%l0%&\";
3979      else
3980	 return \"b%d1%# %^%l0\";
3981    }
3982}"
3983  [(set_attr "type" "branch")
3984   (set
3985     (attr "length")
3986     (cond [
3987       (eq_attr "delay_slot_filled" "yes")
3988       (const_int 4)
3989
3990       (ne
3991	 (if_then_else
3992	   (match_operand 1 "equality_comparison_operator" "")
3993	   (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
3994		(gt (minus (match_dup 0) (pc))
3995		    (minus (const_int 506)
3996			   (symbol_ref "get_attr_delay_slot_length (insn)"))))
3997	   (ior (match_test "!arc_short_comparison_p (operands[1], -64)")
3998		(lt (minus (match_dup 0) (pc)) (const_int -64))
3999		(gt (minus (match_dup 0) (pc))
4000		    (minus (const_int 58)
4001			   (symbol_ref "get_attr_delay_slot_length (insn)")))))
4002	 (const_int 0))
4003       (const_int 4)]
4004      (const_int 2)))
4005
4006   (set (attr "iscompact")
4007	(cond [(match_test "get_attr_length (insn) == 2") (const_string "true")]
4008	      (const_string "false")))])
4009
4010(define_insn "*rev_branch_insn"
4011  [(set (pc)
4012	(if_then_else (match_operator 1 "proper_comparison_operator"
4013				      [(reg CC_REG) (const_int 0)])
4014		      (pc)
4015		      (label_ref (match_operand 0 "" ""))))]
4016  "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
4017  "*
4018{
4019  if (arc_ccfsm_branch_deleted_p ())
4020    {
4021      arc_ccfsm_record_branch_deleted ();
4022      return \"; branch deleted, next insns conditionalized\";
4023    }
4024  else
4025    {
4026      arc_ccfsm_record_condition (operands[1], true, insn, 0);
4027      if (get_attr_length (insn) == 2)
4028	 return \"b%D1%? %^%l0\";
4029      else
4030	 return \"b%D1%# %^%l0\";
4031    }
4032}"
4033  [(set_attr "type" "branch")
4034   (set
4035     (attr "length")
4036     (cond [
4037       (eq_attr "delay_slot_filled" "yes")
4038       (const_int 4)
4039
4040       (ne
4041	 (if_then_else
4042	   (match_operand 1 "equality_comparison_operator" "")
4043	   (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
4044		(gt (minus (match_dup 0) (pc))
4045		    (minus (const_int 506)
4046			   (symbol_ref "get_attr_delay_slot_length (insn)"))))
4047	   (ior (match_test "!arc_short_comparison_p (operands[1], -64)")
4048		(lt (minus (match_dup 0) (pc)) (const_int -64))
4049		(gt (minus (match_dup 0) (pc))
4050		    (minus (const_int 58)
4051			   (symbol_ref "get_attr_delay_slot_length (insn)")))))
4052	 (const_int 0))
4053       (const_int 4)]
4054      (const_int 2)))
4055
4056   (set (attr "iscompact")
4057	(cond [(match_test "get_attr_length (insn) == 2") (const_string "true")]
4058	      (const_string "false")))])
4059
4060;; Unconditional and other jump instructions.
4061
4062(define_expand "jump"
4063  [(set (pc) (label_ref (match_operand 0 "" "")))]
4064  ""
4065  "")
4066
4067(define_insn "jump_i"
4068  [(set (pc) (label_ref (match_operand 0 "" "")))]
4069  "!TARGET_LONG_CALLS_SET || !CROSSING_JUMP_P (insn)"
4070  "b%!%* %^%l0%&"
4071  [(set_attr "type" "uncond_branch")
4072   (set (attr "iscompact")
4073	(if_then_else (match_test "get_attr_length (insn) == 2")
4074		      (const_string "true") (const_string "false")))
4075   (set_attr "cond" "canuse")
4076   (set (attr "length")
4077	(cond [
4078	  ; In arc_reorg we just guesstimate; might be more or less than 4.
4079	  (match_test "arc_branch_size_unknown_p ()")
4080	  (const_int 4)
4081
4082	  (eq_attr "delay_slot_filled" "yes")
4083	  (const_int 4)
4084
4085	  (match_test "CROSSING_JUMP_P (insn)")
4086	  (const_int 4)
4087
4088	  (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
4089	       (gt (minus (match_dup 0) (pc))
4090		   (minus (const_int 506)
4091			  (symbol_ref "get_attr_delay_slot_length (insn)"))))
4092	  (const_int 4)]
4093	 (const_int 2)))])
4094
4095(define_insn "indirect_jump"
4096  [(set (pc) (match_operand:SI 0 "nonmemory_operand" "L,I,Cal,Rcqq,r"))]
4097  ""
4098  "@
4099   j%!%* %0%&
4100   j%!%* %0%&
4101   j%!%* %0%&
4102   j%!%* [%0]%&
4103   j%!%* [%0]%&"
4104  [(set_attr "type" "jump")
4105   (set_attr "iscompact" "false,false,false,maybe,false")
4106   (set_attr "cond" "canuse,canuse_limm,canuse,canuse,canuse")])
4107
4108;; Implement a switch statement.
4109
4110(define_expand "casesi"
4111  [(set (match_dup 5)
4112	(minus:SI (match_operand:SI 0 "register_operand" "")
4113		  (match_operand:SI 1 "nonmemory_operand" "")))
4114   (set (reg:CC CC_REG)
4115	(compare:CC (match_dup 5)
4116		    (match_operand:SI 2 "nonmemory_operand" "")))
4117   (set (pc)
4118	(if_then_else (gtu (reg:CC CC_REG)
4119			   (const_int 0))
4120		      (label_ref (match_operand 4 "" ""))
4121		      (pc)))
4122   (set (match_dup 6)
4123	(unspec:SI [(match_operand 3 "" "")
4124		    (match_dup 5) (match_dup 7)] UNSPEC_ARC_CASESI))
4125   (parallel [(set (pc) (match_dup 6)) (use (match_dup 7))])]
4126  ""
4127  "
4128{
4129  rtx x;
4130
4131  operands[5] = gen_reg_rtx (SImode);
4132  operands[6] = gen_reg_rtx (SImode);
4133  operands[7] = operands[3];
4134  emit_insn (gen_subsi3 (operands[5], operands[0], operands[1]));
4135  emit_insn (gen_cmpsi_cc_insn_mixed (operands[5], operands[2]));
4136  x = gen_rtx_GTU (VOIDmode, gen_rtx_REG (CCmode, CC_REG), const0_rtx);
4137  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
4138			    gen_rtx_LABEL_REF (VOIDmode, operands[4]), pc_rtx);
4139  emit_jump_insn (gen_rtx_SET (pc_rtx, x));
4140  if (TARGET_COMPACT_CASESI)
4141    {
4142      emit_jump_insn (gen_casesi_compact_jump (operands[5], operands[7]));
4143    }
4144  else
4145    {
4146      operands[3] = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
4147      if (flag_pic || !cse_not_expected)
4148	operands[3] = force_reg (Pmode, operands[3]);
4149      emit_insn (gen_casesi_load (operands[6],
4150				  operands[3], operands[5], operands[7]));
4151      if (CASE_VECTOR_PC_RELATIVE || flag_pic)
4152	emit_insn (gen_addsi3 (operands[6], operands[6], operands[3]));
4153      emit_jump_insn (gen_casesi_jump (operands[6], operands[7]));
4154    }
4155  DONE;
4156}")
4157
4158(define_insn "casesi_load"
4159  [(set (match_operand:SI 0 "register_operand"             "=Rcq,r,r")
4160	(unspec:SI [(match_operand:SI 1 "nonmemory_operand" "Rcq,c,Cal")
4161		    (match_operand:SI 2 "register_operand"  "Rcq,c,c")
4162		    (label_ref (match_operand 3 "" ""))] UNSPEC_ARC_CASESI))]
4163  ""
4164  "*
4165{
4166  rtx diff_vec = PATTERN (next_nonnote_insn (as_a<rtx_insn *> (operands[3])));
4167
4168  if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
4169    {
4170      gcc_assert (GET_CODE (diff_vec) == ADDR_VEC);
4171      gcc_assert (GET_MODE (diff_vec) == SImode);
4172      gcc_assert (!CASE_VECTOR_PC_RELATIVE && !flag_pic);
4173    }
4174
4175  switch (GET_MODE (diff_vec))
4176    {
4177    case E_SImode:
4178      return \"ld.as %0,[%1,%2]%&\";
4179    case E_HImode:
4180      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
4181	return \"ld%_.as %0,[%1,%2]\";
4182      return \"ld%_.x.as %0,[%1,%2]\";
4183    case E_QImode:
4184      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
4185	return \"ldb%? %0,[%1,%2]%&\";
4186      return \"ldb.x %0,[%1,%2]\";
4187    default:
4188      gcc_unreachable ();
4189    }
4190}"
4191  [(set_attr "type" "load")
4192   (set_attr_alternative "iscompact"
4193     [(cond
4194	[(ne (symbol_ref "GET_MODE (PATTERN (next_nonnote_insn
4195					       (as_a<rtx_insn *> (operands[3]))))")
4196	     (symbol_ref "QImode"))
4197	 (const_string "false")
4198	 (match_test "!ADDR_DIFF_VEC_FLAGS (PATTERN (next_nonnote_insn
4199						       (as_a<rtx_insn *> (operands[3])))).offset_unsigned")
4200	 (const_string "false")]
4201	(const_string "true"))
4202      (const_string "false")
4203      (const_string "false")])
4204   (set_attr_alternative "length"
4205     [(cond
4206	[(eq_attr "iscompact" "false") (const_int 4)
4207	; We have to mention (match_dup 3) to convince genattrtab.c that this
4208	; is a varying length insn.
4209	 (eq (symbol_ref "1+1") (const_int 2)) (const_int 2)
4210	 (gt (minus (match_dup 3) (pc)) (const_int 42)) (const_int 4)]
4211	(const_int 2))
4212      (const_int 4)
4213      (const_int 8)])])
4214
4215; Unlike the canonical tablejump, this pattern always uses a jump address,
4216; even for CASE_VECTOR_PC_RELATIVE.
4217(define_insn "casesi_jump"
4218  [(set (pc) (match_operand:SI 0 "register_operand" "Cal,Rcqq,c"))
4219   (use (label_ref (match_operand 1 "" "")))]
4220  ""
4221  "j%!%* [%0]%&"
4222  [(set_attr "type" "jump")
4223   (set_attr "iscompact" "false,maybe,false")
4224   (set_attr "cond" "canuse")])
4225
4226(define_insn "casesi_compact_jump"
4227  [(set (pc)
4228	(unspec:SI [(match_operand:SI 0 "register_operand" "c,q")]
4229		   UNSPEC_ARC_CASESI))
4230   (use (label_ref (match_operand 1 "" "")))
4231   (clobber (match_scratch:SI 2 "=q,0"))]
4232  "TARGET_COMPACT_CASESI"
4233  "*
4234{
4235  rtx diff_vec = PATTERN (next_nonnote_insn (as_a<rtx_insn *> (operands[1])));
4236  int unalign = arc_get_unalign ();
4237  rtx xop[3];
4238  const char *s;
4239
4240  xop[0] = operands[0];
4241  xop[2] = operands[2];
4242  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
4243
4244  switch (GET_MODE (diff_vec))
4245    {
4246    case E_SImode:
4247      /* Max length can be 12 in this case, but this is OK because
4248	 2 of these are for alignment, and are anticipated in the length
4249	 of the ADDR_DIFF_VEC.  */
4250      if (unalign && !satisfies_constraint_Rcq (xop[0]))
4251	s = \"add2 %2,pcl,%0\n\tld_s %2,[%2,12]\";
4252      else if (unalign)
4253	s = \"add_s %2,%0,2\n\tld.as %2,[pcl,%2]\";
4254      else
4255	s = \"add %2,%0,2\n\tld.as %2,[pcl,%2]\";
4256      arc_clear_unalign ();
4257      break;
4258    case E_HImode:
4259      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
4260	{
4261	  if (satisfies_constraint_Rcq (xop[0]))
4262	    {
4263	      s = \"add_s %2,%0,%1\n\tld%_.as %2,[pcl,%2]\";
4264	      xop[1] = GEN_INT ((10 - unalign) / 2U);
4265	    }
4266	  else
4267	    {
4268	      s = \"add1 %2,pcl,%0\n\tld%__s %2,[%2,%1]\";
4269	      xop[1] = GEN_INT (10 + unalign);
4270	    }
4271	}
4272      else
4273	{
4274	  if (satisfies_constraint_Rcq (xop[0]))
4275	    {
4276	      s = \"add_s %2,%0,%1\n\tld%_.x.as %2,[pcl,%2]\";
4277	      xop[1] = GEN_INT ((10 - unalign) / 2U);
4278	    }
4279	  else
4280	    {
4281	      s = \"add1 %2,pcl,%0\n\tld%__s.x %2,[%2,%1]\";
4282	      xop[1] = GEN_INT (10 + unalign);
4283	    }
4284	}
4285      arc_toggle_unalign ();
4286      break;
4287    case E_QImode:
4288      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
4289	{
4290	  if ((rtx_equal_p (xop[2], xop[0])
4291	       || find_reg_note (insn, REG_DEAD, xop[0]))
4292	      && satisfies_constraint_Rcq (xop[0]))
4293	    {
4294	      s = \"add_s %0,%0,pcl\n\tldb_s %2,[%0,%1]\";
4295	      xop[1] = GEN_INT (8 + unalign);
4296	    }
4297	  else
4298	    {
4299	      s = \"add %2,%0,pcl\n\tldb_s %2,[%2,%1]\";
4300	      xop[1] = GEN_INT (10 + unalign);
4301	      arc_toggle_unalign ();
4302	    }
4303	}
4304      else if ((rtx_equal_p (xop[0], xop[2])
4305		|| find_reg_note (insn, REG_DEAD, xop[0]))
4306	       && satisfies_constraint_Rcq (xop[0]))
4307	{
4308	  s = \"add_s %0,%0,%1\n\tldb.x %2,[pcl,%0]\";
4309	  xop[1] = GEN_INT (10 - unalign);
4310	  arc_toggle_unalign ();
4311	}
4312      else
4313	{
4314	  /* ??? Length is 12.  */
4315	  s = \"add %2,%0,%1\n\tldb.x %2,[pcl,%2]\";
4316	  xop[1] = GEN_INT (8 + unalign);
4317	}
4318      break;
4319    default:
4320      gcc_unreachable ();
4321    }
4322  output_asm_insn (s, xop);
4323  return \"add_s %2,%2,pcl\n\tj_s%* [%2]\";
4324}"
4325  [(set_attr "length" "10")
4326   (set_attr "type" "jump")
4327   (set_attr "iscompact" "true")
4328   (set_attr "cond" "nocond")])
4329
4330(define_expand "call"
4331  ;; operands[1] is stack_size_rtx
4332  ;; operands[2] is next_arg_register
4333  [(parallel [(call (match_operand:SI 0 "call_operand" "")
4334		    (match_operand 1 "" ""))
4335	     (clobber (reg:SI 31))])]
4336  ""
4337  "{
4338    rtx callee;
4339
4340    gcc_assert (MEM_P (operands[0]));
4341    callee  = XEXP (operands[0], 0);
4342    /* This is to decide if we should generate indirect calls by loading the
4343       32 bit address of the callee into a register before performing the
4344       branch and link - this exposes cse opportunities.
4345       Also, in weird cases like compile/20010107-1.c, we may get a PLUS.  */
4346    if (GET_CODE (callee) != REG
4347	&& (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
4348      XEXP (operands[0], 0) = force_reg (Pmode, callee);
4349  }
4350")
4351
4352; Rcq, which is used in alternative 0, checks for conditional execution.
4353; At instruction output time, if it doesn't match and we end up with
4354; alternative 1 ("q"), that means that we can't use the short form.
4355(define_insn "*call_i"
4356  [(call (mem:SI (match_operand:SI 0
4357		  "call_address_operand" "Rcq,q,c,Cji,Csc,Cbp,Cbr,L,I,Cal"))
4358	 (match_operand 1 "" ""))
4359   (clobber (reg:SI 31))]
4360  ""
4361  "@
4362   jl%!%* [%0]%&
4363   jl%!%* [%0]%&
4364   jl%!%* [%0]
4365   jli_s %S0
4366   sjli  %S0
4367   bl%!%* %P0
4368   bl%!%* %P0
4369   jl%!%* %0
4370   jl%* %0
4371   jl%! %0"
4372  [(set_attr "type" "call,call,call,call_no_delay_slot,call_no_delay_slot,call,call,call,call,call_no_delay_slot")
4373   (set_attr "iscompact" "maybe,false,*,true,*,*,*,*,*,*")
4374   (set_attr "predicable" "no,no,yes,no,no,yes,no,yes,no,yes")
4375   (set_attr "length" "*,*,4,2,4,4,4,4,4,8")])
4376
4377(define_expand "call_value"
4378  ;; operand 2 is stack_size_rtx
4379  ;; operand 3 is next_arg_register
4380  [(parallel [(set (match_operand 0 "dest_reg_operand" "=r")
4381		   (call (match_operand:SI 1 "call_operand" "")
4382			 (match_operand 2 "" "")))
4383	     (clobber (reg:SI 31))])]
4384  ""
4385  "
4386  {
4387    rtx callee;
4388
4389    gcc_assert (MEM_P (operands[1]));
4390    callee = XEXP (operands[1], 0);
4391     /* See the comment in define_expand \"call\".  */
4392    if (GET_CODE (callee) != REG
4393	&& (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
4394      XEXP (operands[1], 0) = force_reg (Pmode, callee);
4395  }")
4396
4397; Rcq, which is used in alternative 0, checks for conditional execution.
4398; At instruction output time, if it doesn't match and we end up with
4399; alternative 1 ("q"), that means that we can't use the short form.
4400(define_insn "*call_value_i"
4401  [(set (match_operand 0 "dest_reg_operand"  "=Rcq,q,w,  w,  w,  w,  w,w,w,  w")
4402	(call (mem:SI (match_operand:SI 1
4403		       "call_address_operand" "Rcq,q,c,Cji,Csc,Cbp,Cbr,L,I,Cal"))
4404	      (match_operand 2 "" "")))
4405   (clobber (reg:SI 31))]
4406  ""
4407  "@
4408   jl%!%* [%1]%&
4409   jl%!%* [%1]%&
4410   jl%!%* [%1]
4411   jli_s %S1
4412   sjli  %S1
4413   bl%!%* %P1;1
4414   bl%!%* %P1;1
4415   jl%!%* %1
4416   jl%* %1
4417   jl%! %1"
4418  [(set_attr "type" "call,call,call,call_no_delay_slot,call_no_delay_slot,call,call,call,call,call_no_delay_slot")
4419   (set_attr "iscompact" "maybe,false,*,true,false,*,*,*,*,*")
4420   (set_attr "predicable" "no,no,yes,no,no,yes,no,yes,no,yes")
4421   (set_attr "length" "*,*,4,2,4,4,4,4,4,8")])
4422
4423; There is a bl_s instruction (16 bit opcode branch-and-link), but we can't
4424; use it for lack of inter-procedural branch shortening.
4425; Link-time relaxation would help...
4426
4427(define_insn "trap"
4428  [(trap_if (const_int 1) (const_int 0))]
4429  "!TARGET_ARC600_FAMILY"
4430  "trap_s\\t5"
4431  [(set_attr "type" "misc")
4432   (set_attr "length" "2")])
4433
4434(define_insn "nop"
4435  [(const_int 0)]
4436  ""
4437  "nop%?"
4438  [(set_attr "type" "misc")
4439   (set_attr "iscompact" "true")
4440   (set_attr "cond" "canuse")
4441   (set_attr "length" "2")])
4442
4443(define_insn "nopv"
4444  [(unspec_volatile [(const_int 0)] VUNSPEC_ARC_NOP)]
4445  ""
4446  "nop%?"
4447  [(set_attr "type" "misc")
4448   (set_attr "iscompact" "maybe")
4449   (set_attr "length" "*")])
4450
4451(define_insn "blockage"
4452  [(unspec_volatile [(const_int 0)] VUNSPEC_ARC_BLOCKAGE)]
4453  ""
4454  ""
4455  [(set_attr "length" "0")
4456   (set_attr "type" "block")]
4457)
4458
4459;; Split up troublesome insns for better scheduling.
4460
4461;; Peepholes go at the end.
4462;;asl followed by add can be replaced by an add{1,2,3}
4463;; Three define_peepholes have been added for this optimization
4464;; ??? This used to target non-canonical rtl.  Now we use add_n, which
4465;; can be generated by combine.  Check if these peepholes still provide
4466;; any benefit.
4467
4468;; -------------------------------------------------------------
4469;; Pattern 1 : r0 = r1 << {i}
4470;;             r3 = r4/INT + r0     ;;and commutative
4471;;                 ||
4472;;                 \/
4473;;             add{i} r3,r4/INT,r1
4474;; -------------------------------------------------------------
4475;; ??? This should be covered by combine, alas, at times combine gets
4476;; too clever for it's own good: when the shifted input is known to be
4477;; either 0 or 1, the operation will be made into an if-then-else, and
4478;; thus fail to match the add_n pattern.  Example: _mktm_r, line 85 in
4479;; newlib/libc/time/mktm_r.c .
4480
4481(define_peephole2
4482  [(set (match_operand:SI 0 "dest_reg_operand" "")
4483	(ashift:SI (match_operand:SI 1 "register_operand" "")
4484		   (match_operand:SI 2 "const_int_operand" "")))
4485  (set (match_operand:SI 3 "dest_reg_operand" "")
4486       (plus:SI (match_operand:SI 4 "nonmemory_operand" "")
4487		(match_operand:SI 5 "nonmemory_operand" "")))]
4488  "(INTVAL (operands[2]) == 1
4489    || INTVAL (operands[2]) == 2
4490    || INTVAL (operands[2]) == 3)
4491   && (true_regnum (operands[4]) == true_regnum (operands[0])
4492       || true_regnum (operands[5]) == true_regnum (operands[0]))
4493   && (peep2_reg_dead_p (2, operands[0]) || (true_regnum (operands[3]) == true_regnum (operands[0])))"
4494 ;; the preparation statements take care to put proper operand in operands[4]
4495 ;; operands[4] will always contain the correct operand. This is added to satisfy commutativity
4496  [(set (match_dup 3)
4497	(plus:SI (mult:SI (match_dup 1)
4498			  (match_dup 2))
4499		 (match_dup 4)))]
4500  "if (true_regnum (operands[4]) == true_regnum (operands[0]))
4501      operands[4] = operands[5];
4502   operands[2] = GEN_INT (1 << INTVAL (operands[2]));"
4503)
4504
4505;; -------------------------------------------------------------
4506;; Pattern 1 : r0 = r1 << {i}
4507;;             r3 = r4 - r0
4508;;                 ||
4509;;                 \/
4510;;             sub{i} r3,r4,r1
4511;; -------------------------------------------------------------
4512;; ??? This should be covered by combine, alas, at times combine gets
4513;; too clever for it's own good: when the shifted input is known to be
4514;; either 0 or 1, the operation will be made into an if-then-else, and
4515;; thus fail to match the sub_n pattern.  Example: __ieee754_yn, line 239 in
4516;; newlib/libm/math/e_jn.c .
4517
4518(define_peephole2
4519  [(set (match_operand:SI 0 "dest_reg_operand" "")
4520	(ashift:SI (match_operand:SI 1 "register_operand" "")
4521		   (match_operand:SI 2 "const_int_operand" "")))
4522   (set (match_operand:SI 3 "dest_reg_operand" "")
4523	(minus:SI (match_operand:SI 4 "nonmemory_operand" "")
4524		  (match_dup 0)))]
4525  "(INTVAL (operands[2]) == 1
4526    || INTVAL (operands[2]) == 2
4527    || INTVAL (operands[2]) == 3)
4528   && (peep2_reg_dead_p (2, operands[0])
4529       || (true_regnum (operands[3]) == true_regnum (operands[0])))"
4530  [(set (match_dup 3)
4531	(minus:SI (match_dup 4)
4532		  (mult:SI (match_dup 1)
4533			   (match_dup 2))))]
4534  "operands[2] = GEN_INT (1 << INTVAL (operands[2]));"
4535)
4536
4537
4538
4539; When using the high single bit, the result of a multiply is either
4540; the original number or zero.  But MPY costs 4 cycles, which we
4541; can replace with the 2 cycles for the pair of TST_S and ADD.NE.
4542(define_peephole2
4543  [(set (match_operand:SI 0 "dest_reg_operand" "")
4544 	(lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4545		     (const_int 31)))
4546   (set (match_operand:SI 4 "register_operand" "")
4547  	(mult:SI (match_operand:SI 2 "register_operand")
4548		 (match_operand:SI 3 "nonmemory_operand" "")))]
4549  "TARGET_ARC700_MPY
4550   && (rtx_equal_p (operands[0], operands[2])
4551       || rtx_equal_p (operands[0], operands[3]))
4552   && peep2_regno_dead_p (0, CC_REG)
4553   && (rtx_equal_p (operands[0], operands[4])
4554       || (peep2_reg_dead_p (2, operands[0])
4555	  && peep2_reg_dead_p (1, operands[4])))"
4556  [(parallel [(set (reg:CC_Z CC_REG)
4557		   (compare:CC_Z (lshiftrt:SI (match_dup 1) (const_int 31))
4558				 (const_int 0)))
4559	      (set (match_dup 4) (lshiftrt:SI (match_dup 1) (const_int 31)))])
4560   (cond_exec
4561     (ne (reg:CC_Z CC_REG) (const_int 0))
4562     (set (match_dup 4) (match_dup 5)))]
4563{
4564  if (!rtx_equal_p (operands[0], operands[2]))
4565    operands[5] = operands[2];
4566  else if (!rtx_equal_p (operands[0], operands[3]))
4567    operands[5] = operands[3];
4568  else
4569    operands[5] = operands[4]; /* Actually a no-op... presumably rare.  */
4570})
4571
4572(define_peephole2
4573  [(set (match_operand:SI 0 "dest_reg_operand" "")
4574 	(lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4575		     (const_int 31)))
4576   (set (match_operand:SI 4 "register_operand" "")
4577  	(mult:SI (match_operand:SI 2 "register_operand")
4578		 (match_operand:SI 3 "nonmemory_operand" "")))]
4579  "TARGET_ARC700_MPY
4580   && (rtx_equal_p (operands[0], operands[2])
4581       || rtx_equal_p (operands[0], operands[3]))
4582   && peep2_regno_dead_p (2, CC_REG)"
4583  [(parallel [(set (reg:CC_Z CC_REG)
4584		   (compare:CC_Z (lshiftrt:SI (match_dup 1) (const_int 31))
4585				 (const_int 0)))
4586	      (set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
4587   (set (match_dup 4) (match_dup 5))
4588   (cond_exec
4589     (eq (reg:CC_Z CC_REG) (const_int 0))
4590     (set (match_dup 4) (const_int 0)))]
4591 "operands[5] = operands[rtx_equal_p (operands[0], operands[2]) ? 3 : 2];")
4592
4593;; Instructions generated through builtins
4594
4595(define_insn "clrsbsi2"
4596  [(set (match_operand:SI  0 "dest_reg_operand" "=w,w")
4597	(clrsb:SI (match_operand:SI 1 "general_operand" "cL,Cal")))]
4598  "TARGET_NORM"
4599  "@
4600   norm \t%0, %1
4601   norm \t%0, %1"
4602  [(set_attr "length" "4,8")
4603   (set_attr "type" "two_cycle_core,two_cycle_core")])
4604
4605(define_insn "norm_f"
4606  [(set (match_operand:SI  0 "dest_reg_operand" "=w,w")
4607	(clrsb:SI (match_operand:SI 1 "general_operand" "cL,Cal")))
4608   (set (reg:CC_ZN CC_REG)
4609	(compare:CC_ZN (match_dup 1) (const_int 0)))]
4610  "TARGET_NORM"
4611  "@
4612   norm.f\t%0, %1
4613   norm.f\t%0, %1"
4614  [(set_attr "length" "4,8")
4615   (set_attr "type" "two_cycle_core,two_cycle_core")])
4616
4617(define_insn_and_split "clrsbhi2"
4618  [(set (match_operand:HI  0 "dest_reg_operand" "=w,w")
4619	(clrsb:HI (match_operand:HI 1 "general_operand" "cL,Cal")))]
4620  "TARGET_NORM"
4621  "#"
4622  "reload_completed"
4623  [(set (match_dup 0) (zero_extend:SI (clrsb:HI (match_dup 1))))]
4624  "operands[0] = simplify_gen_subreg (SImode, operands[0], HImode, 0);")
4625
4626(define_insn "normw"
4627  [(set (match_operand:SI  0 "dest_reg_operand" "=w,w")
4628	(zero_extend:SI
4629	  (clrsb:HI (match_operand:HI 1 "general_operand" "cL,Cal"))))]
4630  "TARGET_NORM"
4631  "@
4632   norm%_ \t%0, %1
4633   norm%_ \t%0, %1"
4634  [(set_attr "length" "4,8")
4635   (set_attr "type" "two_cycle_core,two_cycle_core")])
4636
4637(define_expand "clzsi2"
4638  [(parallel
4639    [(set (match_operand:SI 0 "register_operand" "")
4640	  (clz:SI (match_operand:SI 1 "register_operand" "")))
4641     (clobber (match_dup 2))])]
4642  "TARGET_NORM"
4643  "operands[2] = gen_rtx_REG (CC_ZNmode, CC_REG);")
4644
4645(define_insn_and_split "*arc_clzsi2"
4646  [(set (match_operand:SI 0 "register_operand" "=r")
4647	(clz:SI (match_operand:SI 1 "register_operand" "r")))
4648   (clobber (reg:CC_ZN CC_REG))]
4649  "TARGET_NORM"
4650  "#"
4651  "reload_completed"
4652  [(const_int 0)]
4653{
4654  emit_insn (gen_norm_f (operands[0], operands[1]));
4655  emit_insn
4656    (gen_rtx_COND_EXEC
4657      (VOIDmode,
4658       gen_rtx_LT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4659       gen_rtx_SET (operands[0], const0_rtx)));
4660  emit_insn
4661    (gen_rtx_COND_EXEC
4662      (VOIDmode,
4663       gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4664       gen_rtx_SET (operands[0], plus_constant (SImode, operands[0], 1))));
4665  DONE;
4666}
4667[(set_attr "type" "unary")
4668 (set_attr "length" "12")])
4669
4670(define_expand "ctzsi2"
4671  [(match_operand:SI 0 "register_operand" "")
4672   (match_operand:SI 1 "register_operand" "")]
4673  "TARGET_NORM"
4674  "
4675  emit_insn (gen_arc_ctzsi2 (operands[0], operands[1]));
4676  DONE;
4677")
4678
4679(define_insn_and_split "arc_ctzsi2"
4680  [(set (match_operand:SI 0 "register_operand" "=r")
4681	(ctz:SI (match_operand:SI 1 "register_operand" "r")))
4682   (clobber (reg:CC_ZN CC_REG))
4683   (clobber (match_scratch:SI 2 "=&r"))]
4684  "TARGET_NORM"
4685  "#"
4686  "reload_completed"
4687  [(const_int 0)]
4688{
4689  rtx temp = operands[0];
4690
4691  if (reg_overlap_mentioned_p (temp, operands[1])
4692      || (REGNO (temp) < FIRST_PSEUDO_REGISTER
4693	  && !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS],
4694				 REGNO (temp))))
4695    temp = operands[2];
4696  emit_insn (gen_addsi3 (temp, operands[1], constm1_rtx));
4697  emit_insn (gen_bic_f_zn (temp, temp, operands[1]));
4698  emit_insn (gen_clrsbsi2 (operands[0], temp));
4699  emit_insn
4700    (gen_rtx_COND_EXEC
4701      (VOIDmode,
4702       gen_rtx_LT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4703       gen_rtx_SET (operands[0], GEN_INT (32))));
4704  emit_insn
4705    (gen_rtx_COND_EXEC
4706      (VOIDmode,
4707       gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4708       gen_rtx_SET (operands[0], gen_rtx_MINUS (SImode, GEN_INT (31),
4709						operands[0]))));
4710  DONE;
4711}
4712[(set_attr "type" "unary")
4713 (set_attr "length" "20")])
4714
4715(define_insn "swap"
4716  [(set (match_operand:SI  0 "dest_reg_operand" "=w,w,w")
4717	(unspec:SI [(match_operand:SI 1 "general_operand" "L,Cal,c")]
4718			    UNSPEC_ARC_SWAP))]
4719  "TARGET_SWAP"
4720  "@
4721   swap \t%0, %1
4722   swap \t%0, %1
4723   swap \t%0, %1"
4724  [(set_attr "length" "4,8,4")
4725   (set_attr "type" "two_cycle_core,two_cycle_core,two_cycle_core")])
4726
4727(define_insn "divaw"
4728  [(set (match_operand:SI 0 "dest_reg_operand" "=&w,&w,&w")
4729			  (unspec:SI [(div:SI (match_operand:SI 1 "general_operand" "r,Cal,r")
4730					   (match_operand:SI 2 "general_operand" "r,r,Cal"))]
4731					   UNSPEC_ARC_DIVAW))]
4732  "TARGET_ARC700 || TARGET_EA_SET"
4733  "@
4734   divaw \t%0, %1, %2
4735   divaw \t%0, %1, %2
4736   divaw \t%0, %1, %2"
4737  [(set_attr "length" "4,8,8")
4738   (set_attr "type" "divaw,divaw,divaw")])
4739
4740(define_insn "flag"
4741  [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")]
4742		   VUNSPEC_ARC_FLAG)]
4743  ""
4744  "@
4745    flag%? %0
4746    flag %0
4747    flag%? %0"
4748  [(set_attr "length" "4,4,8")
4749   (set_attr "type" "misc,misc,misc")
4750   (set_attr "predicable" "yes,no,yes")
4751   (set_attr "cond" "clob,clob,clob")])
4752
4753(define_insn "brk"
4754  [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4755		   VUNSPEC_ARC_BRK)]
4756  ""
4757  "brk"
4758  [(set_attr "length" "4")
4759  (set_attr "type" "misc")])
4760
4761(define_insn "rtie"
4762  [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4763		   VUNSPEC_ARC_RTIE)]
4764  ""
4765  "rtie"
4766  [(set_attr "length" "4")
4767  (set_attr "type" "misc")
4768  (set_attr "cond" "clob")])
4769
4770(define_insn "sync"
4771  [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4772		   VUNSPEC_ARC_SYNC)]
4773  ""
4774  "sync"
4775  [(set_attr "length" "4")
4776  (set_attr "type" "misc")])
4777
4778(define_insn "swi"
4779  [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4780		   VUNSPEC_ARC_SWI)]
4781  ""
4782  "*
4783{
4784    if(TARGET_ARC700)
4785	return \"trap0\";
4786    else
4787	return \"swi\";
4788}"
4789  [(set_attr "length" "4")
4790  (set_attr "type" "misc")])
4791
4792
4793(define_insn "sleep"
4794  [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "Lr")]
4795		   VUNSPEC_ARC_SLEEP)]
4796  ""
4797  "sleep %0"
4798  [(set_attr "length" "4")
4799  (set_attr "type" "misc")])
4800
4801(define_insn "core_read"
4802  [(set (match_operand:SI  0 "dest_reg_operand" "=r,r")
4803	(unspec_volatile:SI [(match_operand:SI 1 "general_operand" "Hn,!r")]
4804			    VUNSPEC_ARC_CORE_READ))]
4805  ""
4806  "*
4807    if (check_if_valid_regno_const (operands, 1))
4808      return \"mov \t%0, r%1\";
4809    return \"mov \t%0, r%1\";
4810  "
4811  [(set_attr "length" "4")
4812   (set_attr "type" "unary")])
4813
4814(define_insn "core_write"
4815  [(unspec_volatile [(match_operand:SI 0 "general_operand" "r,r")
4816		     (match_operand:SI 1 "general_operand" "Hn,!r")]
4817		   VUNSPEC_ARC_CORE_WRITE)]
4818  ""
4819  "*
4820    if (check_if_valid_regno_const (operands, 1))
4821      return \"mov \tr%1, %0\";
4822    return \"mov \tr%1, %0\";
4823  "
4824  [(set_attr "length" "4")
4825   (set_attr "type" "unary")])
4826
4827(define_insn "lr"
4828  [(set (match_operand:SI  0 "dest_reg_operand" "=r,r,r,r")
4829	(unspec_volatile:SI [(match_operand:SI 1 "general_operand" "I,HCal,r,D")]
4830			    VUNSPEC_ARC_LR))]
4831  ""
4832  "lr\t%0, [%1]"
4833  [(set_attr "length" "4,8,4,8")
4834   (set_attr "type" "lr,lr,lr,lr")])
4835
4836(define_insn "sr"
4837  [(unspec_volatile [(match_operand:SI 0 "general_operand" "Cal,r,r,r")
4838		     (match_operand:SI 1 "general_operand" "Ir,I,HCal,r")]
4839		   VUNSPEC_ARC_SR)]
4840  ""
4841  "sr\t%0, [%1]"
4842  [(set_attr "length" "8,4,8,4")
4843   (set_attr "type" "sr,sr,sr,sr")])
4844
4845(define_insn "trap_s"
4846  [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "L,Cal")]
4847		   VUNSPEC_ARC_TRAP_S)]
4848  "!TARGET_ARC600_FAMILY"
4849{
4850  if (which_alternative == 0)
4851    {
4852      arc_toggle_unalign ();
4853      return \"trap_s %0\";
4854    }
4855
4856  /* Keep this message in sync with the one in arc.c:arc_expand_builtin,
4857     because *.md files do not get scanned by exgettext.  */
4858  fatal_error (input_location,
4859	       \"operand to trap_s should be an unsigned 6-bit value\");
4860}
4861  [(set_attr "length" "2")
4862  (set_attr "type" "misc")])
4863
4864(define_insn "unimp_s"
4865  [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4866		   VUNSPEC_ARC_UNIMP_S)]
4867  "!TARGET_ARC600_FAMILY"
4868  "unimp_s"
4869  [(set_attr "length" "4")
4870  (set_attr "type" "misc")])
4871
4872;; End of instructions generated through builtins
4873
4874; Since the demise of REG_N_SETS as reliable data readily available to the
4875; target, it is no longer possible to find out
4876; in the prologue / epilogue expanders how many times blink is set.
4877; Using df_regs_ever_live_p to decide if blink needs saving means that
4878; any explicit use of blink will cause it to be saved; hence we cannot
4879; represent the blink use in return / sibcall instructions themselves, and
4880; instead have to show it in EPILOGUE_USES and must explicitly
4881; forbid instructions that change blink in the return / sibcall delay slot.
4882(define_expand "sibcall"
4883  [(parallel [(call (match_operand 0 "memory_operand" "")
4884		    (match_operand 1 "general_operand" ""))
4885	      (simple_return)
4886	      (use (match_operand 2 "" ""))])]
4887  ""
4888  "
4889  {
4890    rtx callee = XEXP (operands[0], 0);
4891
4892    if (operands[2] == NULL_RTX)
4893      operands[2] = const0_rtx;
4894    if (GET_CODE (callee) != REG
4895	&& (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
4896      XEXP (operands[0], 0) = force_reg (Pmode, callee);
4897  }"
4898)
4899
4900(define_expand "sibcall_value"
4901  [(parallel [(set (match_operand 0 "dest_reg_operand" "")
4902		   (call (match_operand 1 "memory_operand" "")
4903			 (match_operand 2 "general_operand" "")))
4904	      (simple_return)
4905	      (use (match_operand 3 "" ""))])]
4906  ""
4907  "
4908  {
4909    rtx callee = XEXP (operands[1], 0);
4910
4911    if (operands[3] == NULL_RTX)
4912      operands[3] = const0_rtx;
4913    if (GET_CODE (callee) != REG && arc_is_longcall_p (callee))
4914      XEXP (operands[1], 0) = force_reg (Pmode, callee);
4915  }"
4916)
4917
4918(define_insn "*sibcall_insn"
4919 [(call (mem:SI (match_operand:SI 0 "call_address_operand"
4920		 "Cbp,Cbr,Rs5,Rsc,Cal"))
4921	(match_operand 1 "" ""))
4922  (simple_return)
4923  (use (match_operand 2 "" ""))]
4924  ""
4925  "@
4926   b%!%* %P0
4927   b%!%* %P0
4928   j%!%* [%0]%&
4929   j%!%* [%0]
4930   j%! %P0"
4931  [(set_attr "type" "call,call,call,call,call_no_delay_slot")
4932   (set_attr "predicable" "yes,no,no,yes,yes")
4933   (set_attr "iscompact" "false,false,maybe,false,false")
4934   (set_attr "is_SIBCALL" "yes")]
4935)
4936
4937(define_insn "*sibcall_value_insn"
4938 [(set (match_operand 0 "dest_reg_operand" "")
4939       (call (mem:SI (match_operand:SI 1 "call_address_operand"
4940	      "Cbp,Cbr,Rs5,Rsc,Cal"))
4941	     (match_operand 2 "" "")))
4942  (simple_return)
4943  (use (match_operand 3 "" ""))]
4944  ""
4945  "@
4946   b%!%* %P1
4947   b%!%* %P1
4948   j%!%* [%1]%&
4949   j%!%* [%1]
4950   j%! %P1"
4951  [(set_attr "type" "call,call,call,call,call_no_delay_slot")
4952   (set_attr "predicable" "yes,no,no,yes,yes")
4953   (set_attr "iscompact" "false,false,maybe,false,false")
4954   (set_attr "is_SIBCALL" "yes")]
4955)
4956
4957(define_expand "prologue"
4958  [(pc)]
4959  ""
4960{
4961  arc_expand_prologue ();
4962  DONE;
4963})
4964
4965(define_expand "epilogue"
4966  [(pc)]
4967  ""
4968{
4969  arc_expand_epilogue (0);
4970  DONE;
4971})
4972
4973(define_expand "sibcall_epilogue"
4974  [(pc)]
4975  ""
4976{
4977  arc_expand_epilogue (1);
4978  DONE;
4979})
4980
4981; Since the demise of REG_N_SETS, it is no longer possible to find out
4982; in the prologue / epilogue expanders how many times blink is set.
4983; Using df_regs_ever_live_p to decide if blink needs saving means that
4984; any explicit use of blink will cause it to be saved; hence we cannot
4985; represent the blink use in return / sibcall instructions themselves, and
4986; instead have to show it in EPILOGUE_USES and must explicitly
4987; forbid instructions that change blink in the return / sibcall delay slot.
4988(define_insn "simple_return"
4989  [(simple_return)]
4990  "reload_completed"
4991{
4992  rtx reg
4993    = gen_rtx_REG (Pmode,
4994		   arc_return_address_register (arc_compute_function_type
4995						(cfun)));
4996
4997  if (TARGET_V2
4998      && ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
4999  {
5000    return \"rtie\";
5001  }
5002  output_asm_insn (\"j%!%* [%0]%&\", &reg);
5003  return \"\";
5004}
5005  [(set (attr "type")
5006	(cond [(and (match_test "ARC_INTERRUPT_P (arc_compute_function_type (cfun))")
5007		    (match_test "TARGET_V2"))
5008	       (const_string "brcc_no_delay_slot")]
5009	      (const_string "return")))
5010   ; predicable won't help here since the canonical rtl looks different
5011   ; for branches.
5012   (set (attr "cond")
5013	(cond [(and (eq (symbol_ref "arc_compute_function_type (cfun)")
5014			(symbol_ref "ARC_FUNCTION_ILINK1"))
5015		    (match_test "TARGET_V2"))
5016	       (const_string "nocond")]
5017	      (const_string "canuse")))
5018  (set (attr "iscompact")
5019	(cond [(eq (symbol_ref "arc_compute_function_type (cfun)")
5020		   (symbol_ref "ARC_FUNCTION_NORMAL"))
5021	       (const_string "maybe")]
5022	      (const_string "false")))
5023   (set (attr "length")
5024	(cond [(ne (symbol_ref "arc_compute_function_type (cfun)")
5025		   (symbol_ref "ARC_FUNCTION_NORMAL"))
5026	       (const_int 4)]
5027	      (const_int 2)))])
5028
5029(define_insn "p_return_i"
5030  [(set (pc)
5031	(if_then_else (match_operator 0 "proper_comparison_operator"
5032				      [(reg CC_REG) (const_int 0)])
5033		      (simple_return) (pc)))]
5034  "reload_completed
5035   && !(TARGET_V2
5036     && ARC_INTERRUPT_P (arc_compute_function_type (cfun)))"
5037{
5038  rtx xop[2];
5039  xop[0] = operands[0];
5040  xop[1]
5041    = gen_rtx_REG (Pmode,
5042		   arc_return_address_register (arc_compute_function_type
5043						(cfun)));
5044
5045  output_asm_insn (\"j%d0%!%# [%1]%&\", xop);
5046  /* record the condition in case there is a delay insn.  */
5047  arc_ccfsm_record_condition (xop[0], false, insn, 0);
5048  return \"\";
5049}
5050  [(set_attr "type" "return")
5051   (set_attr "cond" "use")
5052   (set (attr "iscompact")
5053	(cond [(eq (symbol_ref "arc_compute_function_type (cfun)")
5054		   (symbol_ref "ARC_FUNCTION_NORMAL"))
5055	       (const_string "maybe")]
5056	      (const_string "false")))
5057   (set (attr "length")
5058	(cond [(ne (symbol_ref "arc_compute_function_type (cfun)")
5059		   (symbol_ref "ARC_FUNCTION_NORMAL"))
5060	       (const_int 4)
5061	       (not (match_operand 0 "equality_comparison_operator" ""))
5062	       (const_int 4)
5063	       (eq_attr "delay_slot_filled" "yes")
5064	       (const_int 4)]
5065	      (const_int 2)))])
5066
5067;; ??? #ifdefs in function.c require the presence of this pattern, with a
5068;; non-constant predicate.
5069(define_expand "return"
5070  [(return)]
5071  "optimize < 0")
5072
5073 ;; Comment in final.c (insn_current_reference_address) says
5074 ;; forward branch addresses are calculated from the next insn after branch
5075 ;; and for backward branches, it is calculated from the branch insn start.
5076 ;; The shortening logic here is tuned to accomodate this behavior
5077;; ??? This should be grokked by the ccfsm machinery.
5078(define_insn "cbranchsi4_scratch"
5079  [(set (pc)
5080	(if_then_else (match_operator 0 "proper_comparison_operator"
5081			[(match_operand:SI 1 "register_operand" "c,c, c")
5082			 (match_operand:SI 2 "nonmemory_operand" "L,c,?Cal")])
5083		      (label_ref (match_operand 3 "" ""))
5084		      (pc)))
5085   (clobber (match_operand 4 "cc_register" ""))]
5086   "(reload_completed
5087     || (TARGET_EARLY_CBRANCHSI
5088	 && brcc_nolimm_operator (operands[0], VOIDmode)))
5089    && !CROSSING_JUMP_P (insn)"
5090   "*
5091     switch (get_attr_length (insn))
5092     {
5093       case 2: return \"br%d0%? %1, %2, %^%l3%&\";
5094       case 4: return \"br%d0%* %1, %B2, %^%l3\";
5095       case 8: if (!brcc_nolimm_operator (operands[0], VOIDmode))
5096		 return \"br%d0%* %1, %B2, %^%l3\";
5097       /* FALLTHRU */
5098       case 6: case 10:
5099       case 12:return \"cmp%? %1, %B2\\n\\tb%d0%* %^%l3%& ;br%d0 out of range\";
5100       default: fprintf (stderr, \"unexpected length %d\\n\", get_attr_length (insn)); fflush (stderr); gcc_unreachable ();
5101     }
5102   "
5103  [(set_attr "cond" "clob, clob, clob")
5104   (set (attr "type")
5105	(if_then_else
5106	  (match_test "valid_brcc_with_delay_p (operands)")
5107	  (const_string "brcc")
5108	  (const_string "brcc_no_delay_slot")))
5109   ; For forward branches, we need to account not only for the distance to
5110   ; the target, but also the difference between pcl and pc, the instruction
5111   ; length, and any delay insn, if present.
5112   (set
5113     (attr "length")
5114     (cond ; the outer cond does a test independent of branch shortening.
5115       [(match_operand 0 "brcc_nolimm_operator" "")
5116	(cond
5117	  [(and (match_operand:CC_Z 4 "cc_register")
5118		(eq_attr "delay_slot_filled" "no")
5119		(ge (minus (match_dup 3) (pc)) (const_int -128))
5120		(le (minus (match_dup 3) (pc))
5121		    (minus (const_int 122)
5122			   (symbol_ref "get_attr_delay_slot_length (insn)"))))
5123	   (const_int 2)
5124	   (and (ge (minus (match_dup 3) (pc)) (const_int -256))
5125		(le (minus (match_dup 3) (pc))
5126		    (minus (const_int 244)
5127			   (symbol_ref "get_attr_delay_slot_length (insn)"))))
5128	   (const_int 4)
5129	   (and (match_operand:SI 1 "compact_register_operand" "")
5130		(match_operand:SI 2 "compact_hreg_operand" ""))
5131	   (const_int 6)]
5132	  (const_int 8))]
5133	 (cond [(and (ge (minus (match_dup 3) (pc)) (const_int -256))
5134		     (le (minus (match_dup 3) (pc)) (const_int 244)))
5135		(const_int 8)
5136		(and (match_operand:SI 1 "compact_register_operand" "")
5137		     (match_operand:SI 2 "compact_hreg_operand" ""))
5138		(const_int 10)]
5139	       (const_int 12))))
5140   (set (attr "iscompact")
5141	(if_then_else (match_test "get_attr_length (insn) & 2")
5142		      (const_string "true") (const_string "false")))])
5143
5144; combiner pattern observed for unwind-dw2-fde.c:linear_search_fdes.
5145(define_insn "*bbit"
5146  [(set (pc)
5147	(if_then_else
5148	  (match_operator 3 "equality_comparison_operator"
5149	    [(zero_extract:SI (match_operand:SI 1 "register_operand" "Rcqq,c")
5150			      (const_int 1)
5151			      (match_operand:SI 2 "nonmemory_operand" "L,Lc"))
5152	     (const_int 0)])
5153	  (label_ref (match_operand 0 "" ""))
5154	  (pc)))
5155   (clobber (reg:CC_ZN CC_REG))]
5156  "!CROSSING_JUMP_P (insn)"
5157{
5158  switch (get_attr_length (insn))
5159    {
5160      case 4: return (GET_CODE (operands[3]) == EQ
5161		      ? \"bbit0%* %1,%2,%0\" : \"bbit1%* %1,%2,%0\");
5162      case 6:
5163      case 8: return \"btst%? %1,%2\n\tb%d3%* %0; bbit out of range\";
5164      default: gcc_unreachable ();
5165    }
5166}
5167  [(set_attr "type" "brcc")
5168   (set_attr "cond" "clob")
5169   (set (attr "length")
5170	(cond [(and (ge (minus (match_dup 0) (pc)) (const_int -254))
5171		    (le (minus (match_dup 0) (pc))
5172		    (minus (const_int 248)
5173			   (symbol_ref "get_attr_delay_slot_length (insn)"))))
5174	       (const_int 4)
5175	       (eq (symbol_ref "which_alternative") (const_int 0))
5176	       (const_int 6)]
5177	      (const_int 8)))
5178   (set (attr "iscompact")
5179	(if_then_else (match_test "get_attr_length (insn) == 6")
5180		      (const_string "true") (const_string "false")))])
5181
5182; ??? When testing a bit from a DImode register, combine creates a
5183; zero_extract in DImode.  This goes via an AND with a DImode constant,
5184; so can only be observed on 64 bit hosts.
5185(define_insn_and_split "*bbit_di"
5186  [(set (pc)
5187	(if_then_else
5188	  (match_operator 3 "equality_comparison_operator"
5189	    [(zero_extract:DI (match_operand:SI 1 "register_operand" "Rcqq,c")
5190			      (const_int 1)
5191			      (match_operand 2 "immediate_operand" "L,L"))
5192	     (const_int 0)])
5193	  (label_ref (match_operand 0 "" ""))
5194	  (pc)))
5195   (clobber (reg:CC_ZN CC_REG))]
5196  "!CROSSING_JUMP_P (insn)"
5197  "#"
5198  ""
5199  [(parallel
5200     [(set (pc) (if_then_else (match_dup 3) (label_ref (match_dup 0)) (pc)))
5201      (clobber (reg:CC_ZN CC_REG))])]
5202{
5203  rtx xtr;
5204
5205  xtr = gen_rtx_ZERO_EXTRACT (SImode, operands[1], const1_rtx, operands[2]);
5206  operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
5207				xtr, const0_rtx);
5208})
5209
5210;; -------------------------------------------------------------------
5211;; Hardware loop
5212;; -------------------------------------------------------------------
5213
5214; operand 0 is the loop count pseudo register
5215; operand 1 is the label to jump to at the top of the loop
5216(define_expand "doloop_end"
5217  [(parallel [(set (pc)
5218		   (if_then_else
5219		    (ne (match_operand 0 "" "")
5220			(const_int 1))
5221		    (label_ref (match_operand 1 "" ""))
5222		    (pc)))
5223	      (set (match_dup 0) (plus (match_dup 0) (const_int -1)))
5224	      (unspec [(const_int 0)] UNSPEC_ARC_LP)
5225	      (clobber (match_dup 2))])]
5226  ""
5227{
5228 if (GET_MODE (operands[0]) != SImode)
5229   FAIL;
5230 operands[2] = gen_rtx_SCRATCH (SImode);
5231})
5232
5233(define_insn "arc_lp"
5234  [(unspec:SI [(match_operand:SI 0 "register_operand" "l")]
5235	      UNSPEC_ARC_LP)
5236   (use (label_ref (match_operand 1 "" "")))
5237   (use (label_ref (match_operand 2 "" "")))]
5238  ""
5239  "lp\\t@%l2\\t; %0:@%l1->@%l2"
5240  [(set_attr "type" "loop_setup")
5241   (set_attr "length" "4")])
5242
5243;; if by any chance the lp_count is not used, then use an 'r'
5244;; register, instead of going to memory.
5245(define_insn "loop_end"
5246  [(set (pc)
5247	(if_then_else (ne (match_operand:SI 2 "nonimmediate_operand" "0,0")
5248			  (const_int 1))
5249		      (label_ref (match_operand 1 "" ""))
5250		      (pc)))
5251   (set (match_operand:SI 0 "nonimmediate_operand" "=l!r,m")
5252	(plus (match_dup 2) (const_int -1)))
5253   (unspec [(const_int 0)] UNSPEC_ARC_LP)
5254   (clobber (match_scratch:SI 3 "=X,&r"))]
5255  ""
5256  "\\t;%0 %1 %2"
5257  [(set_attr "length" "0")
5258   (set_attr "predicable" "no")
5259   (set_attr "type" "loop_end")])
5260
5261;; split pattern for the very slim chance when the loop register is
5262;; memory.
5263(define_split
5264  [(set (pc)
5265	(if_then_else (ne (match_operand:SI 0 "memory_operand")
5266			  (const_int 1))
5267		      (label_ref (match_operand 1 ""))
5268		      (pc)))
5269   (set (match_dup 0) (plus (match_dup 0) (const_int -1)))
5270   (unspec [(const_int 0)] UNSPEC_ARC_LP)
5271   (clobber (match_scratch:SI 2))]
5272  "memory_operand (operands[0], SImode)"
5273  [(set (match_dup 2) (match_dup 0))
5274   (set (match_dup 2) (plus:SI (match_dup 2) (const_int -1)))
5275   (set (match_dup 0) (match_dup 2))
5276   (set (reg:CC CC_REG) (compare:CC (match_dup 2) (const_int 0)))
5277   (set (pc)
5278	(if_then_else (ne (reg:CC CC_REG)
5279			  (const_int 0))
5280		      (label_ref (match_dup 1))
5281		      (pc)))]
5282  "")
5283
5284(define_insn "loop_fail"
5285  [(set (reg:SI LP_COUNT)
5286	(plus:SI (reg:SI LP_COUNT) (const_int -1)))
5287   (set (reg:CC_ZN CC_REG)
5288	(compare:CC_ZN (plus:SI (reg:SI LP_COUNT) (const_int -1))
5289		       (const_int 0)))]
5290  ""
5291  "sub.f%?\\tlp_count,lp_count,1"
5292  [(set_attr "iscompact" "false")
5293   (set_attr "type" "compare")
5294   (set_attr "cond" "set_zn")
5295   (set_attr "length" "4")
5296   (set_attr "predicable" "yes")])
5297
5298(define_insn_and_split "dbnz"
5299  [(set (pc)
5300	(if_then_else
5301	 (ne (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+r!l,m")
5302		      (const_int -1))
5303	     (const_int 0))
5304	 (label_ref (match_operand 1 "" ""))
5305	 (pc)))
5306   (set (match_dup 0)
5307	(plus:SI (match_dup 0)
5308		 (const_int -1)))
5309   (clobber (match_scratch:SI 2 "=X,r"))]
5310  "TARGET_DBNZ"
5311  "@
5312   dbnz%#\\t%0,%l1
5313   #"
5314  "TARGET_DBNZ && reload_completed && memory_operand (operands[0], SImode)"
5315  [(set (match_dup 2) (match_dup 0))
5316   (set (match_dup 2) (plus:SI (match_dup 2) (const_int -1)))
5317   (set (reg:CC CC_REG) (compare:CC (match_dup 2) (const_int 0)))
5318   (set (match_dup 0) (match_dup 2))
5319   (set (pc) (if_then_else (ge (reg:CC CC_REG)
5320			       (const_int 0))
5321			   (label_ref (match_dup 1))
5322			   (pc)))]
5323  ""
5324  [(set_attr "iscompact" "false")
5325   (set_attr "type" "loop_end")
5326   (set_attr "length" "4,20")])
5327
5328(define_expand "movmemsi"
5329  [(match_operand:BLK 0 "" "")
5330   (match_operand:BLK 1 "" "")
5331   (match_operand:SI 2 "nonmemory_operand" "")
5332   (match_operand 3 "immediate_operand" "")]
5333  ""
5334  "if (arc_expand_movmem (operands)) DONE; else FAIL;")
5335
5336;; Close http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35803 if this works
5337;; to the point that we can generate cmove instructions.
5338(define_expand "cbranch<mode>4"
5339  [(set (reg:CC CC_REG)
5340	(compare:CC (match_operand:SDF 1 "register_operand" "")
5341		    (match_operand:SDF 2 "register_operand" "")))
5342   (set (pc)
5343	(if_then_else
5344	 (match_operator 0 "comparison_operator" [(reg CC_REG)
5345						      (const_int 0)])
5346	 (label_ref (match_operand 3 "" ""))
5347	 (pc)))]
5348
5349  "TARGET_FP_SP_BASE || TARGET_OPTFPE"
5350{
5351  gcc_assert (XEXP (operands[0], 0) == operands[1]);
5352  gcc_assert (XEXP (operands[0], 1) == operands[2]);
5353  operands[0] = gen_compare_reg (operands[0], VOIDmode);
5354  emit_jump_insn (gen_branch_insn (operands[3], operands[0]));
5355  DONE;
5356})
5357
5358(define_expand "cmp_float"
5359  [(parallel [(set (match_operand 0 "") (match_operand 1 ""))
5360	      (clobber (reg:SI RETURN_ADDR_REGNUM))
5361	      (clobber (reg:SI R12_REG))])]
5362  ""
5363  "")
5364
5365(define_mode_iterator OPTFPE_CMP [CC_Z CC_FP_GT CC_FP_GE CC_FP_UNEQ CC_FP_ORD])
5366(define_mode_attr cmp [(CC_Z "eq") (CC_FP_GT "gt") (CC_FP_GE "ge")
5367		       (CC_FP_UNEQ "uneq") (CC_FP_ORD "ord")])
5368
5369(define_insn "*cmpsf_<cmp>"
5370  [(set (reg:OPTFPE_CMP CC_REG) (compare:OPTFPE_CMP (reg:SF 0) (reg:SF 1)))
5371   (clobber (reg:SI RETURN_ADDR_REGNUM))
5372   (clobber (reg:SI R12_REG))]
5373  "TARGET_OPTFPE && (!TARGET_ARGONAUT_SET || !TARGET_SPFP)
5374   && SFUNC_CHECK_PREDICABLE"
5375  "*return arc_output_libcall (\"__<cmp>sf2\");"
5376  [(set_attr "is_sfunc" "yes")
5377   (set_attr "predicable" "yes")])
5378
5379;; N.B. for "*cmpdf_ord":
5380;; double precision fpx sets bit 31 for NaNs.  We need bit 51 set
5381;; for the floating point emulation to recognize the NaN.
5382(define_insn "*cmpdf_<cmp>"
5383  [(set (reg:OPTFPE_CMP CC_REG) (compare:OPTFPE_CMP (reg:DF 0) (reg:DF 2)))
5384   (clobber (reg:SI RETURN_ADDR_REGNUM))
5385   (clobber (reg:SI R12_REG))]
5386  "TARGET_OPTFPE && (!TARGET_ARGONAUT_SET || !TARGET_DPFP)
5387   && SFUNC_CHECK_PREDICABLE"
5388  "*return arc_output_libcall (\"__<cmp>df2\");"
5389  [(set_attr "is_sfunc" "yes")
5390   (set_attr "predicable" "yes")])
5391
5392(define_insn "abssf2"
5393  [(set (match_operand:SF 0 "dest_reg_operand"    "=Rcq#q,Rcw,w")
5394	(abs:SF (match_operand:SF 1 "register_operand" "0,  0,c")))]
5395  ""
5396  "bclr%? %0,%1,31%&"
5397  [(set_attr "type" "unary")
5398   (set_attr "iscompact" "maybe,false,false")
5399   (set_attr "length" "2,4,4")
5400   (set_attr "predicable" "no,yes,no")])
5401
5402(define_insn "negsf2"
5403  [(set (match_operand:SF 0 "dest_reg_operand" "=Rcw,w")
5404	(neg:SF (match_operand:SF 1 "register_operand" "0,c")))]
5405  ""
5406  "bxor%? %0,%1,31"
5407  [(set_attr "type" "unary")
5408   (set_attr "predicable" "yes,no")])
5409
5410;; ??? Should this use arc_output_libcall and set is_sfunc?
5411(define_insn "*millicode_thunk_st"
5412  [(match_parallel 0 "millicode_store_operation"
5413		   [(set (mem:SI (reg:SI SP_REG)) (reg:SI 13))])]
5414  ""
5415{
5416  output_asm_insn ("bl%* __st_r13_to_%0",
5417		   &SET_SRC (XVECEXP (operands[0], 0,
5418				      XVECLEN (operands[0], 0) - 2)));
5419  return "";
5420}
5421  [(set_attr "type" "call")])
5422
5423(define_insn "*millicode_thunk_ld"
5424  [(match_parallel 0 "millicode_load_clob_operation"
5425		   [(set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
5426  ""
5427{
5428  output_asm_insn ("bl%* __ld_r13_to_%0",
5429		   &SET_DEST (XVECEXP (operands[0], 0,
5430				       XVECLEN (operands[0], 0) - 2)));
5431  return "";
5432}
5433  [(set_attr "type" "call")])
5434
5435; the sibthunk restores blink, so we use the return rtx.
5436(define_insn "*millicode_sibthunk_ld"
5437  [(match_parallel 0 "millicode_load_operation"
5438		   [(return)
5439		    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (reg:SI 12)))
5440		    (set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
5441  ""
5442{
5443  output_asm_insn ("b%* __ld_r13_to_%0_ret",
5444		   &SET_DEST (XVECEXP (operands[0], 0,
5445				       XVECLEN (operands[0], 0) - 1)));
5446  return "";
5447}
5448  [(set_attr "type" "call")
5449   (set_attr "is_SIBCALL" "yes")])
5450
5451(define_insn "tls_load_tp_soft"
5452  [(set (reg:SI R0_REG) (unspec:SI [(const_int 0)] UNSPEC_TLS_OFF))
5453   (clobber (reg:SI RETURN_ADDR_REGNUM))]
5454  ""
5455  "*return arc_output_libcall (\"__read_tp\");"
5456  [(set_attr "is_sfunc" "yes")
5457   (set_attr "predicable" "yes")])
5458
5459(define_insn "tls_gd_get_addr"
5460  [(set (reg:SI R0_REG)
5461	(call:SI (mem:SI (unspec:SI [(match_operand:SI 0
5462				      "symbolic_operand" "X,X")]
5463			  UNSPEC_TLS_GD))
5464		 (const_int 0)))
5465   (clobber (reg:SI RETURN_ADDR_REGNUM))]
5466  ""
5467  ".tls_gd_ld %0`bl%* __tls_get_addr@plt"
5468  [(set_attr "type" "call")
5469   ; With TARGET_MEDIUM_CALLS, plt calls are not predicable.
5470   (set_attr "predicable" "no")])
5471
5472;; For thread pointer builtins
5473(define_expand "get_thread_pointersi"
5474  [(set (match_operand:SI 0 "register_operand") (match_dup 1))]
5475 ""
5476 "operands[1] = gen_rtx_REG (Pmode, arc_tp_regno);")
5477
5478(define_expand "set_thread_pointersi"
5479  [(set (match_dup 1) (match_operand:SI 0 "register_operand"))]
5480 ""
5481 "operands[1] = gen_rtx_REG (Pmode, arc_tp_regno);")
5482
5483;; If hardware floating point is available, don't define a negdf pattern;
5484;; it would be something like:
5485;;(define_insn "negdf2"
5486;;  [(set (match_operand:DF 0 "register_operand" "=w,w,D,?r")
5487;;	(neg:DF (match_operand:DF 1 "register_operand" "0,c,D,D")))
5488;;   (clobber (match_scratch:DF 2 "=X,X,X,X,D1"))]
5489;;  ""
5490;;  "@
5491;;   bxor%? %H0,%H1,31
5492;;   bxor %H0,%H1,31 ` mov %L0,%L1
5493;;   drsubh%F0%F1 0,0,0
5494;;   drsubh%F2%F1 %H0,0,0 ` dexcl%F2 %L0,%H0,%L0"
5495;;  [(set_attr "type" "unary,unary,dpfp_addsub,dpfp_addsub")
5496;;   (set_attr "iscompact" "false,false,false,false")
5497;;   (set_attr "length" "4,4,8,12")
5498;;   (set_attr "cond" "canuse,nocond,nocond,nocond")])
5499;; and this suffers from always requiring a long immediate when using
5500;; the floating point hardware.
5501;; We then want the sub[sd]f patterns to be used, so that we can load the
5502;; constant zero efficiently into a register when we want to do the
5503;; computation using the floating point hardware.  There should be a special
5504;; subdf alternative that matches a zero operand 1, which then can allow
5505;; to use bxor to flip the high bit of an integer register.
5506;; ??? we actually can't use the floating point hardware for neg, because
5507;; this would not work right for -0.  OTOH optabs.c has already code
5508;; to synthesyze negate by flipping the sign bit.
5509
5510;;V2 instructions
5511(define_insn "bswapsi2"
5512  [(set (match_operand:SI 0 "register_operand"           "= r,r")
5513	(bswap:SI (match_operand:SI 1 "nonmemory_operand" "rL,Cal")))]
5514  "TARGET_V2 && TARGET_SWAP"
5515  "swape %0, %1"
5516  [(set_attr "length" "4,8")
5517   (set_attr "type" "two_cycle_core")])
5518
5519(define_expand "prefetch"
5520  [(prefetch (match_operand:SI 0 "address_operand" "")
5521	     (match_operand:SI 1 "const_int_operand" "")
5522	     (match_operand:SI 2 "const_int_operand" ""))]
5523  "TARGET_HS"
5524  "")
5525
5526(define_insn "prefetch_1"
5527  [(prefetch (match_operand:SI 0 "register_operand" "r")
5528	     (match_operand:SI 1 "const_int_operand" "n")
5529	     (match_operand:SI 2 "const_int_operand" "n"))]
5530  "TARGET_HS"
5531  {
5532   if (INTVAL (operands[1]))
5533      return "prefetchw [%0]";
5534   else
5535      return "prefetch [%0]";
5536  }
5537  [(set_attr "type" "load")
5538   (set_attr "length" "4")])
5539
5540(define_insn "prefetch_2"
5541  [(prefetch (plus:SI (match_operand:SI 0 "register_operand" "r,r,r")
5542		      (match_operand:SI 1 "nonmemory_operand" "r,Cm2,Cal"))
5543	     (match_operand:SI 2 "const_int_operand" "n,n,n")
5544	     (match_operand:SI 3 "const_int_operand" "n,n,n"))]
5545  "TARGET_HS"
5546  {
5547   if (INTVAL (operands[2]))
5548      return "prefetchw [%0, %1]";
5549   else
5550      return "prefetch [%0, %1]";
5551  }
5552  [(set_attr "type" "load")
5553   (set_attr "length" "4,4,8")])
5554
5555(define_insn "prefetch_3"
5556  [(prefetch (match_operand:SI 0 "address_operand" "p")
5557	     (match_operand:SI 1 "const_int_operand" "n")
5558	     (match_operand:SI 2 "const_int_operand" "n"))]
5559  "TARGET_HS"
5560  {
5561   operands[0] = gen_rtx_MEM (SImode, operands[0]);
5562   if (INTVAL (operands[1]))
5563      return "prefetchw%U0 %0";
5564   else
5565      return "prefetch%U0 %0";
5566   }
5567  [(set_attr "type" "load")
5568   (set_attr "length" "8")])
5569
5570(define_insn "divsi3"
5571  [(set (match_operand:SI 0 "register_operand"         "=r,r,  r,r,r,r,  r,  r")
5572	(div:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0,  0,  r")
5573		(match_operand:SI 2 "nonmemory_operand" "r,r,  r,L,L,I,Cal,Cal")))]
5574  "TARGET_DIVREM"
5575  "div%? %0, %1, %2"
5576  [(set_attr "length" "4,4,8,4,4,4,8,8")
5577   (set_attr "iscompact" "false")
5578   (set_attr "type" "div_rem")
5579   (set_attr "predicable" "yes,no,no,yes,no,no,yes,no")
5580   (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond")
5581   ])
5582
5583(define_insn "udivsi3"
5584  [(set (match_operand:SI 0 "register_operand"          "=r,r,  r,r,r,r,  r,  r")
5585	(udiv:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0,  0,  r")
5586		 (match_operand:SI 2 "nonmemory_operand" "r,r,  r,L,L,I,Cal,Cal")))]
5587  "TARGET_DIVREM"
5588  "divu%? %0, %1, %2"
5589  [(set_attr "length" "4,4,8,4,4,4,8,8")
5590   (set_attr "iscompact" "false")
5591   (set_attr "type" "div_rem")
5592   (set_attr "predicable" "yes,no,no,yes,no,no,yes,no")
5593   (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond")
5594   ])
5595
5596(define_insn "modsi3"
5597  [(set (match_operand:SI 0 "register_operand"         "=r,r,  r,r,r,r,  r,  r")
5598	(mod:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0,  0,  r")
5599		(match_operand:SI 2 "nonmemory_operand" "r,r,  r,L,L,I,Cal,Cal")))]
5600  "TARGET_DIVREM"
5601  "rem%? %0, %1, %2"
5602  [(set_attr "length" "4,4,8,4,4,4,8,8")
5603   (set_attr "iscompact" "false")
5604   (set_attr "type" "div_rem")
5605   (set_attr "predicable" "yes,no,no,yes,no,no,yes,no")
5606   (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond")
5607   ])
5608
5609(define_insn "umodsi3"
5610  [(set (match_operand:SI 0 "register_operand"          "=r,r,  r,r,r,r,  r,  r")
5611	(umod:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0,  0,  r")
5612		 (match_operand:SI 2 "nonmemory_operand" "r,r,  r,L,L,I,Cal,Cal")))]
5613  "TARGET_DIVREM"
5614  "remu%? %0, %1, %2"
5615  [(set_attr "length" "4,4,8,4,4,4,8,8")
5616   (set_attr "iscompact" "false")
5617   (set_attr "type" "div_rem")
5618   (set_attr "predicable" "yes,no,no,yes,no,no,yes,no")
5619   (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond")
5620   ])
5621
5622;; SETcc instructions
5623(define_code_iterator arcCC_cond [eq ne gt lt ge le])
5624
5625(define_insn "arcset<code>"
5626  [(set (match_operand:SI 0 "register_operand"                "=r,r,r,r,r,r,r")
5627	(arcCC_cond:SI (match_operand:SI 1 "register_operand"  "0,r,0,r,0,0,r")
5628		       (match_operand:SI 2 "nonmemory_operand" "r,r,L,L,I,n,n")))]
5629  "TARGET_V2 && TARGET_CODE_DENSITY"
5630  "set<code>%? %0, %1, %2"
5631  [(set_attr "length" "4,4,4,4,4,8,8")
5632   (set_attr "iscompact" "false")
5633   (set_attr "type" "compare")
5634   (set_attr "predicable" "yes,no,yes,no,no,yes,no")
5635   (set_attr "cond" "canuse,nocond,canuse,nocond,nocond,canuse,nocond")
5636   ])
5637
5638(define_insn "arcsetltu"
5639  [(set (match_operand:SI 0 "register_operand"         "=r,r,r,r,r,  r,  r")
5640	(ltu:SI (match_operand:SI 1 "register_operand"  "0,r,0,r,0,  0,  r")
5641		(match_operand:SI 2 "nonmemory_operand" "r,r,L,L,I,  n,  n")))]
5642  "TARGET_V2 && TARGET_CODE_DENSITY"
5643  "setlo%? %0, %1, %2"
5644  [(set_attr "length" "4,4,4,4,4,8,8")
5645   (set_attr "iscompact" "false")
5646   (set_attr "type" "compare")
5647   (set_attr "predicable" "yes,no,yes,no,no,yes,no")
5648   (set_attr "cond" "canuse,nocond,canuse,nocond,nocond,canuse,nocond")
5649   ])
5650
5651(define_insn "arcsetgeu"
5652  [(set (match_operand:SI 0 "register_operand"         "=r,r,r,r,r,  r,  r")
5653	(geu:SI (match_operand:SI 1 "register_operand"  "0,r,0,r,0,  0,  r")
5654		(match_operand:SI 2 "nonmemory_operand" "r,r,L,L,I,  n,  n")))]
5655  "TARGET_V2 && TARGET_CODE_DENSITY"
5656  "seths%? %0, %1, %2"
5657  [(set_attr "length" "4,4,4,4,4,8,8")
5658   (set_attr "iscompact" "false")
5659   (set_attr "type" "compare")
5660   (set_attr "predicable" "yes,no,yes,no,no,yes,no")
5661   (set_attr "cond" "canuse,nocond,canuse,nocond,nocond,canuse,nocond")
5662   ])
5663
5664;; Special cases of SETCC
5665(define_insn_and_split "arcsethi"
5666  [(set (match_operand:SI 0 "register_operand"         "=r,r,  r,r")
5667	(gtu:SI (match_operand:SI 1 "register_operand"  "r,r,  r,r")
5668		(match_operand:SI 2 "nonmemory_operand" "0,r,C62,n")))]
5669  "TARGET_V2 && TARGET_CODE_DENSITY"
5670  "setlo%? %0, %2, %1"
5671  "reload_completed
5672   && CONST_INT_P (operands[2])
5673   && satisfies_constraint_C62 (operands[2])"
5674  [(const_int 0)]
5675  "{
5676    /* sethi a,b,u6 => seths a,b,u6 + 1.  */
5677    operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
5678    emit_insn (gen_arcsetgeu (operands[0], operands[1], operands[2]));
5679    DONE;
5680 }"
5681 [(set_attr "length" "4,4,4,8")
5682   (set_attr "iscompact" "false")
5683   (set_attr "type" "compare")
5684   (set_attr "predicable" "yes,no,no,no")
5685   (set_attr "cond" "canuse,nocond,nocond,nocond")]
5686)
5687
5688(define_insn_and_split "arcsetls"
5689  [(set (match_operand:SI 0 "register_operand"         "=r,r,  r,r")
5690	(leu:SI (match_operand:SI 1 "register_operand"  "r,r,  r,r")
5691		(match_operand:SI 2 "nonmemory_operand" "0,r,C62,n")))]
5692  "TARGET_V2 && TARGET_CODE_DENSITY"
5693  "seths%? %0, %2, %1"
5694  "reload_completed
5695   && CONST_INT_P (operands[2])
5696   && satisfies_constraint_C62 (operands[2])"
5697  [(const_int 0)]
5698  "{
5699    /* setls a,b,u6 => setlo a,b,u6 + 1.  */
5700    operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
5701    emit_insn (gen_arcsetltu (operands[0], operands[1], operands[2]));
5702    DONE;
5703 }"
5704 [(set_attr "length" "4,4,4,8")
5705   (set_attr "iscompact" "false")
5706   (set_attr "type" "compare")
5707   (set_attr "predicable" "yes,no,no,no")
5708   (set_attr "cond" "canuse,nocond,nocond,nocond")]
5709)
5710
5711; Any mode that needs to be solved by secondary reload
5712(define_mode_iterator SRI [QI HI])
5713
5714(define_expand "reload_<mode>_load"
5715  [(parallel [(match_operand:SRI 0 "register_operand" "=r")
5716	      (match_operand:SRI 1 "memory_operand" "m")
5717	      (match_operand:SI 2 "register_operand" "=&r")])]
5718  ""
5719{
5720 arc_secondary_reload_conv (operands[0], operands[1], operands[2], false);
5721 DONE;
5722})
5723
5724(define_expand "reload_<mode>_store"
5725  [(parallel [(match_operand:SRI 0 "memory_operand" "=m")
5726	      (match_operand:SRI 1 "register_operand" "r")
5727	      (match_operand:SI 2 "register_operand" "=&r")])]
5728  ""
5729{
5730 arc_secondary_reload_conv (operands[1], operands[0], operands[2], true);
5731 DONE;
5732})
5733
5734(define_insn "extzvsi"
5735  [(set (match_operand:SI 0 "register_operand"                  "=r  ,  r,r,r")
5736	(zero_extract:SI (match_operand:SI 1 "register_operand"  "0  ,  r,r,0")
5737			 (match_operand:SI 2 "const_int_operand" "C3p,C3p,n,n")
5738			 (match_operand:SI 3 "const_int_operand" "n  ,  n,n,n")))]
5739  "TARGET_HS && TARGET_BARREL_SHIFTER"
5740  {
5741   int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f);
5742   operands[2] = GEN_INT (assemble_op2);
5743   return "xbfu%?\\t%0,%1,%2";
5744  }
5745  [(set_attr "type"       "shift")
5746   (set_attr "iscompact"  "false")
5747   (set_attr "length"     "4,4,8,8")
5748   (set_attr "predicable" "yes,no,no,yes")
5749   (set_attr "cond"       "canuse,nocond,nocond,canuse_limm")])
5750
5751(define_insn "kflag"
5752  [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")]
5753		   VUNSPEC_ARC_KFLAG)]
5754  "TARGET_V2"
5755  "@
5756    kflag%? %0
5757    kflag %0
5758    kflag%? %0"
5759  [(set_attr "length" "4,4,8")
5760   (set_attr "type" "misc,misc,misc")
5761   (set_attr "predicable" "yes,no,yes")
5762   (set_attr "cond" "clob,clob,clob")])
5763
5764(define_insn "clri"
5765  [(set (match_operand:SI  0 "dest_reg_operand" "=r")
5766	(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "N")]
5767			    VUNSPEC_ARC_CLRI))]
5768  "TARGET_V2"
5769  "clri  %0"
5770  [(set_attr "length" "4")
5771   (set_attr "type" "misc")])
5772
5773(define_insn "ffs"
5774  [(set (match_operand:SI  0 "dest_reg_operand" "=w,w")
5775	(unspec:SI [(match_operand:SI 1 "general_operand" "cL,Cal")]
5776			    UNSPEC_ARC_FFS))]
5777  "TARGET_NORM && TARGET_V2"
5778  "@
5779   ffs \t%0, %1
5780   ffs \t%0, %1"
5781  [(set_attr "length" "4,8")
5782   (set_attr "type" "two_cycle_core,two_cycle_core")])
5783
5784(define_insn "ffs_f"
5785  [(set (match_operand:SI  0 "dest_reg_operand" "=w,w")
5786	(unspec:SI [(match_operand:SI 1 "general_operand" "cL,Cal")]
5787			    UNSPEC_ARC_FFS))
5788   (set (reg:CC_ZN CC_REG)
5789	(compare:CC_ZN (match_dup 1) (const_int 0)))]
5790  "TARGET_NORM && TARGET_V2"
5791  "@
5792   ffs.f\t%0, %1
5793   ffs.f\t%0, %1"
5794  [(set_attr "length" "4,8")
5795   (set_attr "type" "two_cycle_core,two_cycle_core")])
5796
5797(define_expand "ffssi2"
5798  [(parallel [(set (match_dup 2)
5799		   (unspec:SI [(match_operand:SI 1 "register_operand" "")]
5800			      UNSPEC_ARC_FFS))
5801	      (set (reg:CC_ZN CC_REG)
5802		   (compare:CC_ZN (match_dup 1) (const_int 0)))])
5803   (set (match_dup 2) (plus:SI (match_dup 2) (const_int 1)))
5804   (set (match_operand:SI 0 "dest_reg_operand" "")
5805	(if_then_else:SI (eq:SI (reg:CC_ZN CC_REG) (const_int 0))
5806			 (const_int 0)
5807			 (match_dup 2)))]
5808  "TARGET_NORM && TARGET_V2"
5809  {
5810   operands[2] = gen_reg_rtx (SImode);
5811   })
5812
5813(define_insn "fls"
5814  [(set (match_operand:SI  0 "register_operand" "=r,r")
5815	(unspec:SI [(match_operand:SI 1 "nonmemory_operand" "rL,Cal")]
5816			    UNSPEC_ARC_FLS))]
5817  "TARGET_NORM && TARGET_V2"
5818  "fls\\t%0,%1"
5819  [(set_attr "length" "4,8")
5820   (set_attr "type" "two_cycle_core,two_cycle_core")])
5821
5822(define_insn "seti"
5823  [(unspec_volatile:SI [(match_operand:SI 0 "nonmemory_operand" "rL")]
5824		       VUNSPEC_ARC_SETI)]
5825  "TARGET_V2"
5826  "seti\\t%0"
5827  [(set_attr "length" "4")
5828   (set_attr "type" "misc")])
5829
5830;; FPU/FPX expands
5831
5832;;add
5833(define_expand "addsf3"
5834  [(set (match_operand:SF 0 "register_operand"           "")
5835	(plus:SF (match_operand:SF 1 "nonmemory_operand" "")
5836		 (match_operand:SF 2 "nonmemory_operand" "")))]
5837  "TARGET_FP_SP_BASE || TARGET_SPFP"
5838  "
5839  if (!register_operand (operands[1], SFmode)
5840      && !register_operand (operands[2], SFmode))
5841    operands[1] = force_reg (SFmode, operands[1]);
5842  ")
5843
5844;;sub
5845(define_expand "subsf3"
5846  [(set (match_operand:SF 0 "register_operand"            "")
5847	(minus:SF (match_operand:SF 1 "nonmemory_operand" "")
5848		  (match_operand:SF 2 "nonmemory_operand" "")))]
5849  "TARGET_FP_SP_BASE || TARGET_SPFP"
5850  "
5851  if (!register_operand (operands[1], SFmode)
5852      && !register_operand (operands[2], SFmode))
5853    operands[1] = force_reg (SFmode, operands[1]);
5854  ")
5855
5856;;mul
5857(define_expand "mulsf3"
5858  [(set (match_operand:SF 0 "register_operand"           "")
5859	(mult:SF (match_operand:SF 1 "nonmemory_operand" "")
5860		 (match_operand:SF 2 "nonmemory_operand" "")))]
5861  "TARGET_FP_SP_BASE || TARGET_SPFP"
5862  "
5863  if (!register_operand (operands[1], SFmode)
5864      && !register_operand (operands[2], SFmode))
5865    operands[1] = force_reg (SFmode, operands[1]);
5866  ")
5867
5868;;add
5869(define_expand "adddf3"
5870  [(set (match_operand:DF 0 "double_register_operand"           "")
5871	(plus:DF (match_operand:DF 1 "double_register_operand"  "")
5872		 (match_operand:DF 2 "nonmemory_operand" "")))]
5873 "TARGET_FP_DP_BASE || TARGET_DPFP"
5874 "
5875  if (TARGET_DPFP)
5876   {
5877    if (GET_CODE (operands[2]) == CONST_DOUBLE)
5878     {
5879        rtx first, second, tmp;
5880        split_double (operands[2], &first, &second);
5881        tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second);
5882        emit_insn (gen_adddf3_insn (operands[0], operands[1],
5883                                    operands[2], tmp, const0_rtx));
5884     }
5885    else
5886     emit_insn (gen_adddf3_insn (operands[0], operands[1],
5887                                 operands[2], const1_rtx, const1_rtx));
5888   DONE;
5889  }
5890 else if (TARGET_FP_DP_BASE)
5891  {
5892   if (!even_register_operand (operands[2], DFmode))
5893      operands[2] = force_reg (DFmode, operands[2]);
5894
5895   if (!even_register_operand (operands[1], DFmode))
5896      operands[1] = force_reg (DFmode, operands[1]);
5897  }
5898 else
5899  gcc_unreachable ();
5900 ")
5901
5902;;sub
5903(define_expand "subdf3"
5904  [(set (match_operand:DF 0 "double_register_operand"            "")
5905	(minus:DF (match_operand:DF 1 "nonmemory_operand" "")
5906		  (match_operand:DF 2 "nonmemory_operand" "")))]
5907  "TARGET_FP_DP_BASE || TARGET_DPFP"
5908  "
5909   if (TARGET_DPFP)
5910    {
5911     if (TARGET_FP_DP_AX && (GET_CODE (operands[1]) == CONST_DOUBLE))
5912       operands[1] = force_reg (DFmode, operands[1]);
5913     if ((GET_CODE (operands[1]) == CONST_DOUBLE)
5914          || GET_CODE (operands[2]) == CONST_DOUBLE)
5915      {
5916        rtx first, second, tmp;
5917        int const_index = ((GET_CODE (operands[1]) == CONST_DOUBLE) ? 1 : 2);
5918        split_double (operands[const_index], &first, &second);
5919        tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second);
5920        emit_insn (gen_subdf3_insn (operands[0], operands[1],
5921                                    operands[2], tmp, const0_rtx));
5922      }
5923    else
5924     emit_insn (gen_subdf3_insn (operands[0], operands[1],
5925                                 operands[2], const1_rtx, const1_rtx));
5926    DONE;
5927   }
5928  else if (TARGET_FP_DP_BASE)
5929   {
5930    if (!even_register_operand (operands[2], DFmode))
5931       operands[2] = force_reg (DFmode, operands[2]);
5932
5933    if (!even_register_operand (operands[1], DFmode))
5934       operands[1] = force_reg (DFmode, operands[1]);
5935   }
5936  else
5937   gcc_unreachable ();
5938  ")
5939
5940;;mul
5941(define_expand "muldf3"
5942  [(set (match_operand:DF 0 "double_register_operand"           "")
5943	(mult:DF (match_operand:DF 1 "double_register_operand"  "")
5944		 (match_operand:DF 2 "nonmemory_operand" "")))]
5945  "TARGET_FP_DP_BASE || TARGET_DPFP"
5946  "
5947   if (TARGET_DPFP)
5948    {
5949     if (GET_CODE (operands[2]) == CONST_DOUBLE)
5950      {
5951        rtx first, second, tmp;
5952        split_double (operands[2], &first, &second);
5953        tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second);
5954        emit_insn (gen_muldf3_insn (operands[0], operands[1],
5955                                    operands[2], tmp, const0_rtx));
5956      }
5957     else
5958      emit_insn (gen_muldf3_insn (operands[0], operands[1],
5959                                  operands[2], const1_rtx, const1_rtx));
5960    DONE;
5961   }
5962  else if (TARGET_FP_DP_BASE)
5963   {
5964    if (!even_register_operand (operands[2], DFmode))
5965       operands[2] = force_reg (DFmode, operands[2]);
5966
5967    if (!even_register_operand (operands[1], DFmode))
5968       operands[1] = force_reg (DFmode, operands[1]);
5969   }
5970  else
5971   gcc_unreachable ();
5972 ")
5973
5974;;div
5975(define_expand "divsf3"
5976  [(set (match_operand:SF 0 "register_operand"        "")
5977	(div:SF (match_operand:SF 1 "nonmemory_operand" "")
5978		(match_operand:SF 2 "nonmemory_operand" "")))]
5979  "TARGET_FPX_QUARK || TARGET_FP_SP_SQRT"
5980  "
5981  if (TARGET_FPX_QUARK)
5982   {
5983     operands[1] = force_reg (SFmode, operands[1]);
5984     operands[2] = force_reg (SFmode, operands[2]);
5985   }
5986  else
5987   {
5988     if (!register_operand (operands[1], SFmode)
5989        && !register_operand (operands[2], SFmode))
5990       operands[1] = force_reg (SFmode, operands[1]);
5991   }
5992  ")
5993
5994;; Square root
5995(define_expand "sqrtsf2"
5996  [(set (match_operand:SF 0 "register_operand"           "")
5997	(sqrt:SF (match_operand:SF 1 "nonmemory_operand" "")))]
5998  "TARGET_FPX_QUARK || TARGET_FP_SP_SQRT"
5999  "
6000  if (TARGET_FPX_QUARK)
6001   {
6002     operands[1] = force_reg (SFmode, operands[1]);
6003   }
6004")
6005
6006;; SF->SI (using rounding towards zero)
6007(define_expand "fix_truncsfsi2"
6008  [(set (match_operand:SI 0 "register_operand"                "")
6009	(fix:SI (fix:SF (match_operand:SF 1 "register_operand" ""))))]
6010  "TARGET_FPX_QUARK || TARGET_FP_SP_CONV"
6011  "")
6012
6013;; SI->SF
6014(define_expand "floatsisf2"
6015  [(set (match_operand:SF 0 "register_operand"            "")
6016	(float:SF (match_operand:SI 1 "register_operand" "")))]
6017  "TARGET_FPX_QUARK || TARGET_FP_SP_CONV"
6018  "")
6019
6020(define_expand "extzv"
6021  [(set (match_operand:SI 0 "register_operand" "")
6022	(zero_extract:SI (match_operand:SI 1 "register_operand" "")
6023			 (match_operand:SI 2 "const_int_operand" "")
6024			 (match_operand:SI 3 "const_int_operand" "")))]
6025  "TARGET_NPS_BITOPS")
6026
6027; We need a sanity check in the instuction predicate because combine
6028; will throw any old rubbish at us and see what sticks.
6029(define_insn "*extzv_i"
6030  [(set (match_operand:SI 0 "register_operand" "=Rrq")
6031	(zero_extract:SI (match_operand:SI 1 "register_operand" "Rrq")
6032			 (match_operand:SI 2 "const_int_operand" "n")
6033			 (match_operand:SI 3 "const_int_operand" "n")))]
6034  "TARGET_NPS_BITOPS && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32"
6035  "movb.cl %0,%1,0,%3,%2"
6036  [(set_attr "type" "shift")
6037   (set_attr "length" "4")])
6038
6039(define_expand "insv"
6040  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "")
6041			 (match_operand:SI 1 "const_int_operand" "")
6042			 (match_operand:SI 2 "const_int_operand" ""))
6043	(match_operand:SI 3 "nonmemory_operand" ""))]
6044  "TARGET_NPS_BITOPS"
6045{
6046  int size = INTVAL (operands[1]);
6047
6048  if (size != 1 && size != 2 && size != 4 && size != 8)
6049    operands[3] = force_reg (SImode, operands[3]);
6050})
6051
6052(define_insn "*insv_i"
6053  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+w,Rrq")
6054			 (match_operand:SI 1 "const_int_operand" "C18,n")
6055			 (match_operand:SI 2 "const_int_operand" "n,n"))
6056	(match_operand:SI 3 "nonmemory_operand" "P,Rrq"))]
6057  "TARGET_NPS_BITOPS
6058   && (register_operand (operands[3], SImode)
6059       || satisfies_constraint_C18 (operands[1]))"
6060  "@
6061   movbi %0,%0,%3,%2,%1
6062   movb %0,%0,%3,%2,0,%1"
6063  [(set_attr "type" "shift")
6064   (set_attr "length" "4")])
6065
6066(define_insn "*movb"
6067  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
6068			 (match_operand:SI 1 "const_int_operand" "n")
6069			 (match_operand:SI 2 "const_int_operand" "n"))
6070	(zero_extract:SI (match_operand:SI 3 "register_operand" "Rrq")
6071			 (match_dup 1)
6072			 (match_operand:SI 4 "const_int_operand" "n")))]
6073  "TARGET_NPS_BITOPS"
6074  "movb %0,%0,%3,%2,%4,%1"
6075  [(set_attr "type" "shift")
6076   (set_attr "length" "4")])
6077
6078(define_insn "*movb_signed"
6079  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
6080			 (match_operand:SI 1 "const_int_operand" "n")
6081			 (match_operand:SI 2 "const_int_operand" "n"))
6082	(sign_extract:SI (match_operand:SI 3 "register_operand" "Rrq")
6083			 (match_dup 1)
6084			 (match_operand:SI 4 "const_int_operand" "n")))]
6085  "TARGET_NPS_BITOPS"
6086  "movb %0,%0,%3,%2,%4,%1"
6087  [(set_attr "type" "shift")
6088   (set_attr "length" "4")])
6089
6090(define_insn "*movb_high"
6091  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
6092			 (match_operand:SI 1 "const_int_operand" "n")
6093			 (match_operand:SI 2 "const_int_operand" "n"))
6094	(lshiftrt:SI (match_operand:SI 3 "register_operand" "Rrq")
6095		     (match_operand:SI 4 "const_int_operand" "n")))]
6096  "TARGET_NPS_BITOPS
6097   && INTVAL (operands[4]) + INTVAL (operands[1]) <= 32"
6098  "movb %0,%0,%3,%2,%4,%1"
6099  [(set_attr "type" "shift")
6100   (set_attr "length" "4")])
6101
6102; N.B.: when processing signed bitfields that fit in the top half of
6103; a word, gcc will use a narrow sign extending load, and in this case
6104; we will see INTVAL (operands[4]) + INTVAL (operands[1]) == 16 (or 8)
6105(define_insn "*movb_high_signed"
6106  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
6107			 (match_operand:SI 1 "const_int_operand" "n")
6108			 (match_operand:SI 2 "const_int_operand" "n"))
6109	(ashiftrt:SI (match_operand:SI 3 "register_operand" "Rrq")
6110		     (match_operand:SI 4 "const_int_operand" "n")))]
6111  "TARGET_NPS_BITOPS
6112   && INTVAL (operands[4]) + INTVAL (operands[1]) <= 32"
6113  "movb %0,%0,%3,%2,%4,%1"
6114  [(set_attr "type" "shift")
6115   (set_attr "length" "4")])
6116
6117(define_split
6118  [(set (match_operand:SI 0 "register_operand" "")
6119	(ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
6120			   (match_operand:SI 2 "const_int_operand" ""))
6121		(subreg:SI (match_operand 3 "") 0)))]
6122  "TARGET_NPS_BITOPS
6123   && GET_MODE_BITSIZE (GET_MODE (operands[3])) <= INTVAL (operands[2])
6124   && !reg_overlap_mentioned_p (operands[0], operands[1])"
6125  [(set (match_dup 0) (zero_extend:SI (match_dup 3)))
6126   (set (zero_extract:SI (match_dup 0) (match_dup 4) (match_dup 2))
6127	(match_dup 1))]
6128  "operands[4] = GEN_INT (32 - INTVAL (operands[2]));")
6129
6130(define_insn "*mrgb"
6131  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
6132			 (match_operand:SI 1 "const_int_operand" "n")
6133			 (match_operand:SI 2 "const_int_operand" "n"))
6134	(zero_extract:SI (match_dup 0) (match_dup 1)
6135			 (match_operand:SI 3 "const_int_operand" "n")))
6136   (set (zero_extract:SI (match_dup 0)
6137			 (match_operand:SI 4 "const_int_operand" "n")
6138			 (match_operand:SI 5 "const_int_operand" "n"))
6139	(zero_extract:SI (match_operand:SI 6 "register_operand" "Rrq")
6140			 (match_dup 4)
6141			 (match_operand:SI 7 "const_int_operand" "n")))]
6142  "TARGET_NPS_BITOPS"
6143{
6144  output_asm_insn ("mrgb %0,%0,%6,%2,%3,%1,%5,%7,%4", operands);
6145  /* The ;%? updates the known unalignment.  */
6146  return arc_short_long (insn, ";%?", "nop_s");
6147}
6148  [(set_attr "type" "shift")
6149   (set_attr "length" "6")
6150   (set_attr "iscompact" "true")])
6151
6152;; combine fumbles combination of two movb patterns, and then the
6153;; combination is rejected by combinable_i3pat.
6154;; Thus, we can only use a peephole2 to combine two such insns.
6155
6156(define_peephole2
6157  [(set (match_operand:SI 0 "register_operand" "")
6158	(match_operand:SI 1 "register_operand" ""))
6159   (set (zero_extract:SI (match_dup 0)
6160			 (match_operand:SI 2 "const_int_operand" "")
6161			 (match_operand:SI 3 "const_int_operand" ""))
6162	(zero_extract:SI (match_dup 1)
6163			 (match_dup 2)
6164			 (match_operand:SI 4 "const_int_operand" "")))
6165   (match_operand 9) ; unrelated insn scheduled here
6166   (set (zero_extract:SI (match_dup 0)
6167			 (match_operand:SI 5 "const_int_operand" "")
6168			 (match_operand:SI 6 "const_int_operand" ""))
6169	(zero_extract:SI (match_operand:SI 7 "register_operand" "")
6170			 (match_dup 5)
6171			 (match_operand:SI 8 "const_int_operand" "")))]
6172  "TARGET_NPS_BITOPS
6173   // Check that the second movb doesn't clobber an input of the extra insn.
6174   && !reg_overlap_mentioned_p (operands[0], operands[9])
6175   // And vice versa.
6176   && !reg_set_p (operands[0], operands[9])
6177   && !reg_set_p (operands[7], operands[9])"
6178  [(set (match_dup 0) (match_dup 1))
6179   (parallel [(set (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
6180		   (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 4)))
6181	      (set (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
6182		   (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 4)))])
6183   (match_dup 9)])
6184
6185(define_peephole2
6186  [(set (match_operand:SI 0 "register_operand" "")
6187	(match_operand:SI 1 "register_operand" ""))
6188   (set (zero_extract:SI (match_dup 0)
6189			 (match_operand:SI 2 "const_int_operand" "")
6190			 (match_operand:SI 3 "const_int_operand" ""))
6191	(zero_extract:SI (match_dup 1)
6192			 (match_dup 2)
6193			 (match_operand:SI 4 "const_int_operand" "")))
6194   (set (match_dup 1) (match_operand 8))
6195   (set (zero_extract:SI (match_dup 0)
6196			 (match_operand:SI 5 "const_int_operand" "")
6197			 (match_operand:SI 6 "const_int_operand" ""))
6198	(zero_extract:SI (match_dup 1) (match_dup 5)
6199			 (match_operand:SI 7 "const_int_operand" "")))]
6200  "TARGET_NPS_BITOPS
6201   && !reg_overlap_mentioned_p (operands[0], operands[8])"
6202  [(set (match_dup 0) (match_dup 1))
6203   (set (match_dup 1) (match_dup 8))
6204   (parallel [(set (zero_extract:SI (match_dup 0) (match_dup 2) (match_dup 3))
6205		   (zero_extract:SI (match_dup 0) (match_dup 2) (match_dup 4)))
6206	      (set (zero_extract:SI (match_dup 0) (match_dup 5) (match_dup 6))
6207		   (zero_extract:SI (match_dup 1) (match_dup 5) (match_dup 7)))])
6208   (match_dup 1)])
6209
6210(define_insn "*rotrsi3_cnt1"
6211  [(set (match_operand:SI 0 "dest_reg_operand"             "=w")
6212	(rotatert:SI (match_operand:SI 1 "register_operand" "c")
6213		     (const_int 1)))]
6214  ""
6215  "ror %0,%1%&"
6216  [(set_attr "type" "shift")
6217   (set_attr "predicable" "no")
6218   (set_attr "length" "4")])
6219
6220(define_insn "*ashlsi2_cnt1"
6221  [(set (match_operand:SI 0 "dest_reg_operand"           "=Rcqq,w")
6222	(ashift:SI (match_operand:SI 1 "register_operand" "Rcqq,c")
6223		   (const_int 1)))]
6224  ""
6225  "asl%? %0,%1%&"
6226  [(set_attr "type" "shift")
6227   (set_attr "iscompact" "maybe,false")
6228   (set_attr "predicable" "no,no")])
6229
6230(define_insn "*lshrsi3_cnt1"
6231  [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcqq,w")
6232	(lshiftrt:SI (match_operand:SI 1 "register_operand" "Rcqq,c")
6233		     (const_int 1)))]
6234  ""
6235  "lsr%? %0,%1%&"
6236  [(set_attr "type" "shift")
6237   (set_attr "iscompact" "maybe,false")
6238   (set_attr "predicable" "no,no")])
6239
6240(define_insn "*ashrsi3_cnt1"
6241  [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcqq,w")
6242	(ashiftrt:SI (match_operand:SI 1 "register_operand" "Rcqq,c")
6243		     (const_int 1)))]
6244  ""
6245  "asr%? %0,%1%&"
6246  [(set_attr "type" "shift")
6247   (set_attr "iscompact" "maybe,false")
6248   (set_attr "predicable" "no,no")])
6249
6250(define_peephole2
6251  [(set (match_operand:SI 0 "register_operand" "")
6252	(zero_extract:SI (match_dup 0)
6253			 (match_operand:SI 1 "const_int_operand" "")
6254			 (match_operand:SI 2 "const_int_operand" "")))
6255   (set (zero_extract:SI (match_operand:SI 3 "register_operand" "")
6256			 (match_dup 1)
6257			 (match_dup 2))
6258	(match_dup 0))]
6259  "TARGET_NPS_BITOPS
6260   && !reg_overlap_mentioned_p (operands[0], operands[3])"
6261  [(set (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 2))
6262	(zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)))])
6263
6264;; Dummy pattern used as a place holder for automatically saved
6265;; registers.
6266(define_insn "stack_irq_dwarf"
6267  [(unspec_volatile [(const_int 1)] VUNSPEC_ARC_STACK_IRQ)]
6268  ""
6269  ""
6270  [(set_attr "length" "0")])
6271
6272;; MAC and DMPY instructions
6273(define_expand "maddsidi4"
6274  [(match_operand:DI 0 "register_operand" "")
6275   (match_operand:SI 1 "register_operand" "")
6276   (match_operand:SI 2 "extend_operand"   "")
6277   (match_operand:DI 3 "register_operand" "")]
6278  "TARGET_PLUS_DMPY"
6279  "{
6280   emit_insn (gen_maddsidi4_split (operands[0], operands[1], operands[2], operands[3]));
6281   DONE;
6282  }")
6283
6284(define_insn_and_split "maddsidi4_split"
6285  [(set (match_operand:DI 0 "register_operand" "=r")
6286	(plus:DI
6287	 (mult:DI
6288	  (sign_extend:DI (match_operand:SI 1 "register_operand" "%r"))
6289	  (sign_extend:DI (match_operand:SI 2 "extend_operand" "ri")))
6290	 (match_operand:DI 3 "register_operand" "r")))
6291   (clobber (reg:DI ARCV2_ACC))]
6292  "TARGET_PLUS_DMPY"
6293  "#"
6294  "TARGET_PLUS_DMPY && reload_completed"
6295  [(const_int 0)]
6296  "{
6297   rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST);
6298   emit_move_insn (acc_reg, operands[3]);
6299   if (TARGET_PLUS_MACD)
6300     emit_insn (gen_macd (operands[0], operands[1], operands[2]));
6301   else
6302     {
6303      emit_insn (gen_mac (operands[1], operands[2]));
6304      emit_move_insn (operands[0], acc_reg);
6305     }
6306   DONE;
6307   }"
6308  [(set_attr "type" "multi")
6309   (set_attr "length" "36")])
6310
6311(define_insn "macd"
6312  [(set (match_operand:DI 0 "even_register_operand"	       "=Rcr,r,r")
6313	(plus:DI
6314	 (mult:DI
6315	  (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,c,c"))
6316	  (sign_extend:DI (match_operand:SI 2 "extend_operand" " c,cI,Cal")))
6317	 (reg:DI ARCV2_ACC)))
6318   (set (reg:DI ARCV2_ACC)
6319	(plus:DI
6320	 (mult:DI (sign_extend:DI (match_dup 1))
6321		  (sign_extend:DI (match_dup 2)))
6322	 (reg:DI ARCV2_ACC)))]
6323 "TARGET_PLUS_MACD"
6324 "macd %0,%1,%2"
6325  [(set_attr "length" "4,4,8")
6326   (set_attr "type" "multi")
6327   (set_attr "predicable" "yes,no,no")
6328   (set_attr "cond" "canuse,nocond,nocond")])
6329
6330(define_insn "mac"
6331  [(set (reg:DI ARCV2_ACC)
6332	(plus:DI
6333	 (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand" "%r,r"))
6334		  (sign_extend:DI (match_operand:SI 1 "extend_operand" "rI,i")))
6335	 (reg:DI ARCV2_ACC)))]
6336 "TARGET_PLUS_DMPY"
6337 "mac 0,%0,%1"
6338  [(set_attr "length" "4,8")
6339   (set_attr "type" "multi")
6340   (set_attr "predicable" "no")
6341   (set_attr "cond" "nocond")])
6342
6343(define_peephole2
6344  [(set (reg:DI ARCV2_ACC)
6345	(plus:DI
6346	 (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand" ""))
6347		  (sign_extend:DI (match_operand:SI 1 "extend_operand" "")))
6348	 (reg:DI ARCV2_ACC)))
6349   (set (match_operand:SI 2 "register_operand" "")
6350	(match_operand:SI 3 "accl_operand" ""))]
6351 "TARGET_PLUS_DMPY"
6352 [(const_int 0)]
6353 {
6354  emit_insn (gen_mac_r (operands[2], operands[0], operands[1]));
6355  DONE;
6356 })
6357
6358(define_insn "mac_r"
6359  [(set (match_operand:SI 0 "register_operand" "=r,r")
6360	(truncate:SI
6361	 (plus:DI
6362	  (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%r,r"))
6363		   (sign_extend:DI (match_operand:SI 2 "extend_operand" "rI,i")))
6364	  (reg:DI ARCV2_ACC))))
6365   (clobber (reg:DI ARCV2_ACC))]
6366 "TARGET_PLUS_DMPY"
6367 "mac %0,%1,%2"
6368  [(set_attr "length" "4,8")
6369   (set_attr "type" "multi")
6370   (set_attr "predicable" "no")
6371   (set_attr "cond" "nocond")])
6372
6373(define_expand "umaddsidi4"
6374  [(match_operand:DI 0 "register_operand" "")
6375   (match_operand:SI 1 "register_operand" "")
6376   (match_operand:SI 2 "extend_operand"   "")
6377   (match_operand:DI 3 "register_operand" "")]
6378  "TARGET_PLUS_DMPY"
6379  "{
6380   emit_insn (gen_umaddsidi4_split (operands[0], operands[1], operands[2], operands[3]));
6381   DONE;
6382  }")
6383
6384(define_insn_and_split "umaddsidi4_split"
6385  [(set (match_operand:DI 0 "register_operand" "=r")
6386	(plus:DI
6387	 (mult:DI
6388	  (zero_extend:DI (match_operand:SI 1 "register_operand" "%r"))
6389	  (zero_extend:DI (match_operand:SI 2 "extend_operand" "ri")))
6390	 (match_operand:DI 3 "register_operand" "r")))
6391   (clobber (reg:DI ARCV2_ACC))]
6392  "TARGET_PLUS_DMPY"
6393  "#"
6394  "TARGET_PLUS_DMPY && reload_completed"
6395  [(const_int 0)]
6396  "{
6397   rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST);
6398   emit_move_insn (acc_reg, operands[3]);
6399   if (TARGET_PLUS_MACD)
6400     emit_insn (gen_macdu (operands[0], operands[1], operands[2]));
6401   else
6402     {
6403      emit_insn (gen_macu (operands[1], operands[2]));
6404      emit_move_insn (operands[0], acc_reg);
6405     }
6406   DONE;
6407   }"
6408  [(set_attr "type" "multi")
6409   (set_attr "length" "36")])
6410
6411(define_insn "macdu"
6412  [(set (match_operand:DI 0 "even_register_operand"	       "=Rcr,r,r")
6413	(plus:DI
6414	 (mult:DI
6415	  (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,c,c"))
6416	  (zero_extend:DI (match_operand:SI 2 "extend_operand" " c,cI,i")))
6417	 (reg:DI ARCV2_ACC)))
6418   (set (reg:DI ARCV2_ACC)
6419	(plus:DI
6420	 (mult:DI (zero_extend:DI (match_dup 1))
6421		  (zero_extend:DI (match_dup 2)))
6422	 (reg:DI ARCV2_ACC)))]
6423 "TARGET_PLUS_MACD"
6424 "macdu %0,%1,%2"
6425  [(set_attr "length" "4,4,8")
6426   (set_attr "type" "multi")
6427   (set_attr "predicable" "yes,no,no")
6428   (set_attr "cond" "canuse,nocond,nocond")])
6429
6430(define_insn "macu"
6431  [(set (reg:DI ARCV2_ACC)
6432	(plus:DI
6433	 (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand" "%r,r"))
6434		  (zero_extend:DI (match_operand:SI 1 "extend_operand" "rI,i")))
6435	 (reg:DI ARCV2_ACC)))]
6436 "TARGET_PLUS_DMPY"
6437 "macu 0,%0,%1"
6438  [(set_attr "length" "4,8")
6439   (set_attr "type" "multi")
6440   (set_attr "predicable" "no")
6441   (set_attr "cond" "nocond")])
6442
6443(define_peephole2
6444  [(set (reg:DI ARCV2_ACC)
6445	(plus:DI
6446	 (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand" ""))
6447		  (zero_extend:DI (match_operand:SI 1 "extend_operand" "")))
6448	 (reg:DI ARCV2_ACC)))
6449   (set (match_operand:SI 2 "register_operand" "")
6450	(match_operand:SI 3 "accl_operand" ""))]
6451 "TARGET_PLUS_DMPY"
6452 [(const_int 0)]
6453 {
6454  emit_insn (gen_macu_r (operands[2], operands[0], operands[1]));
6455  DONE;
6456 })
6457
6458(define_insn "macu_r"
6459  [(set (match_operand:SI 0 "register_operand" "=r,r")
6460	(truncate:SI
6461	 (plus:DI
6462	  (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%r,r"))
6463		   (zero_extend:DI (match_operand:SI 2 "extend_operand" "rI,i")))
6464	  (reg:DI ARCV2_ACC))))
6465   (clobber (reg:DI ARCV2_ACC))]
6466 "TARGET_PLUS_DMPY"
6467 "macu %0,%1,%2"
6468  [(set_attr "length" "4,8")
6469   (set_attr "type" "multi")
6470   (set_attr "predicable" "no")
6471   (set_attr "cond" "nocond")])
6472
6473(define_insn "mpyd_arcv2hs"
6474  [(set (match_operand:DI 0 "even_register_operand"			"=Rcr, r")
6475	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"	 "  0, c"))
6476		 (sign_extend:DI (match_operand:SI 2 "register_operand"	 "  c, c"))))
6477   (set (reg:DI ARCV2_ACC)
6478	(mult:DI
6479	  (sign_extend:DI (match_dup 1))
6480	  (sign_extend:DI (match_dup 2))))]
6481  "TARGET_PLUS_MACD"
6482  "mpyd%? %0,%1,%2"
6483  [(set_attr "length" "4,4")
6484  (set_attr "iscompact" "false")
6485  (set_attr "type" "multi")
6486  (set_attr "predicable" "yes,no")
6487  (set_attr "cond" "canuse,nocond")])
6488
6489(define_insn "mpyd_imm_arcv2hs"
6490  [(set (match_operand:DI 0 "even_register_operand"			"=Rcr, r,r,Rcr,	 r")
6491	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"	 "  0, c,0,  0,	 c"))
6492		 (match_operand 2		    "immediate_operand"	 "  L, L,I,Cal,Cal")))
6493   (set (reg:DI ARCV2_ACC)
6494	(mult:DI (sign_extend:DI (match_dup 1))
6495		 (match_dup 2)))]
6496  "TARGET_PLUS_MACD"
6497  "mpyd%? %0,%1,%2"
6498  [(set_attr "length" "4,4,4,8,8")
6499  (set_attr "iscompact" "false")
6500  (set_attr "type" "multi")
6501  (set_attr "predicable" "yes,no,no,yes,no")
6502  (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")])
6503
6504(define_insn "mpydu_arcv2hs"
6505  [(set (match_operand:DI 0 "even_register_operand"			"=Rcr, r")
6506	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"	 "  0, c"))
6507		 (zero_extend:DI (match_operand:SI 2 "register_operand" "   c, c"))))
6508   (set (reg:DI ARCV2_ACC)
6509	(mult:DI (zero_extend:DI (match_dup 1))
6510		 (zero_extend:DI (match_dup 2))))]
6511  "TARGET_PLUS_MACD"
6512  "mpydu%? %0,%1,%2"
6513  [(set_attr "length" "4,4")
6514  (set_attr "iscompact" "false")
6515  (set_attr "type" "multi")
6516  (set_attr "predicable" "yes,no")
6517  (set_attr "cond" "canuse,nocond")])
6518
6519(define_insn "mpydu_imm_arcv2hs"
6520  [(set (match_operand:DI 0 "even_register_operand"			"=Rcr, r,r,Rcr,	 r")
6521	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"	 "  0, c,0,  0,	 c"))
6522		 (match_operand 2		    "immediate_operand"	 "  L, L,I,Cal,Cal")))
6523   (set (reg:DI ARCV2_ACC)
6524	(mult:DI (zero_extend:DI (match_dup 1))
6525		 (match_dup 2)))]
6526  "TARGET_PLUS_MACD"
6527  "mpydu%? %0,%1,%2"
6528  [(set_attr "length" "4,4,4,8,8")
6529  (set_attr "iscompact" "false")
6530  (set_attr "type" "multi")
6531  (set_attr "predicable" "yes,no,no,yes,no")
6532  (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")])
6533
6534(define_insn "stack_tie"
6535  [(set (mem:BLK (scratch))
6536	(unspec:BLK [(match_operand:SI 0 "register_operand" "rb")
6537		     (match_operand:SI 1 "register_operand" "rb")]
6538		    UNSPEC_ARC_STKTIE))]
6539  ""
6540  ""
6541  [(set_attr "length" "0")
6542   (set_attr "iscompact" "false")
6543   (set_attr "type" "block")]
6544  )
6545
6546(define_insn "*add_shift"
6547  [(set (match_operand:SI 0 "register_operand" "=q,r,r")
6548	(plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "q,r,r")
6549			    (match_operand:SI 2 "_1_2_3_operand" ""))
6550		 (match_operand:SI 3 "nonmemory_operand"  "0,r,Cal")))]
6551  ""
6552  "add%2%?\\t%0,%3,%1"
6553  [(set_attr "length" "*,4,8")
6554   (set_attr "predicable" "yes,no,no")
6555   (set_attr "iscompact" "maybe,false,false")
6556   (set_attr "cond" "canuse,nocond,nocond")])
6557
6558(define_insn "*add_shift2"
6559  [(set (match_operand:SI 0 "register_operand" "=q,r,r")
6560	(plus:SI (match_operand:SI 1 "nonmemory_operand"  "0,r,Cal")
6561		 (ashift:SI (match_operand:SI 2 "register_operand" "q,r,r")
6562			    (match_operand:SI 3 "_1_2_3_operand" ""))))]
6563  ""
6564  "add%3%?\\t%0,%1,%2"
6565  [(set_attr "length" "*,4,8")
6566   (set_attr "predicable" "yes,no,no")
6567   (set_attr "iscompact" "maybe,false,false")
6568   (set_attr "cond" "canuse,nocond,nocond")])
6569
6570(define_insn "*sub_shift"
6571  [(set (match_operand:SI 0"register_operand" "=r,r,r")
6572	 (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal")
6573		   (ashift:SI (match_operand:SI 2 "register_operand" "r,r,r")
6574			      (match_operand:SI 3 "_1_2_3_operand" ""))))]
6575  ""
6576  "sub%3\\t%0,%1,%2"
6577  [(set_attr "length" "4,4,8")
6578   (set_attr "cond" "canuse,nocond,nocond")
6579   (set_attr "predicable" "yes,no,no")])
6580
6581(define_insn "*sub_shift_cmp0_noout"
6582  [(set (match_operand 0 "cc_set_register" "")
6583	(compare:CC
6584	 (minus:SI (match_operand:SI 1 "register_operand" "r")
6585		   (ashift:SI (match_operand:SI 2 "register_operand" "r")
6586			      (match_operand:SI 3 "_1_2_3_operand" "")))
6587	 (const_int 0)))]
6588  ""
6589  "sub%3.f\\t0,%1,%2"
6590  [(set_attr "length" "4")])
6591
6592(define_insn "*compare_si_ashiftsi"
6593  [(set (match_operand 0 "cc_set_register" "")
6594	(compare:CC (match_operand:SI 1 "register_operand" "r")
6595		    (ashift:SI (match_operand:SI 2 "register_operand" "r")
6596			       (match_operand:SI 3 "_1_2_3_operand" ""))))]
6597  ""
6598  "sub%3.f\\t0,%1,%2"
6599  [(set_attr "length" "4")])
6600
6601;; Convert the sequence
6602;;  asl rd,rn,_1_2_3
6603;;  cmp ra,rd
6604;; into
6605;;  sub{123}.f 0,ra,rn
6606(define_peephole2
6607  [(set (match_operand:SI 0 "register_operand" "")
6608	(ashift:SI (match_operand:SI 1 "register_operand" "")
6609		   (match_operand:SI 2 "_1_2_3_operand" "")))
6610   (set (reg:CC CC_REG)
6611	(compare:CC (match_operand:SI 3 "register_operand" "")
6612		    (match_dup 0)))]
6613  "peep2_reg_dead_p (2, operands[0])"
6614  [(set (reg:CC CC_REG) (compare:CC (match_dup 3)
6615				    (ashift:SI (match_dup 1) (match_dup 2))))])
6616
6617;; Patterns for exception handling
6618(define_insn_and_split "eh_return"
6619  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
6620		    VUNSPEC_ARC_EH_RETURN)]
6621  ""
6622  "#"
6623  "reload_completed"
6624  [(const_int 0)]
6625  "
6626  {
6627    arc_eh_return_address_location (operands[0]);
6628    DONE;
6629  }"
6630)
6631;; include the arc-FPX instructions
6632(include "fpx.md")
6633
6634;; include the arc-FPU instructions
6635(include "fpu.md")
6636
6637(include "simdext.md")
6638
6639;; include atomic extensions
6640(include "atomic.md")
6641