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