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