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