1 ;; Machine description of the Synopsys DesignWare ARC cpu for GNU C compiler
2 ;; Copyright (C) 1994-2015 Free Software Foundation, Inc.
4 ;; Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
5 ;; behalf of Synopsys Inc.
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)
12 ;; Profiling support and performance improvements by
13 ;; Joern Rennecke (joern.rennecke@embecosm.com)
15 ;; Support for DSP multiply instructions and mul64
16 ;; instructions for ARC600; and improvements in flag setting
18 ;; Muhammad Khurram Riaz (Khurram.Riaz@arc.com)
20 ;; This file is part of GCC.
22 ;; GCC is free software; you can redistribute it and/or modify
23 ;; it under the terms of the GNU General Public License as published by
24 ;; the Free Software Foundation; either version 3, or (at your option)
27 ;; GCC is distributed in the hope that it will be useful,
28 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
29 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 ;; GNU General Public License for more details.
32 ;; You should have received a copy of the GNU General Public License
33 ;; along with GCC; see the file COPYING3. If not see
34 ;; <http://www.gnu.org/licenses/>.
36 ;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
38 ;; <op> dest, src Two operand instruction's syntax
39 ;; <op> dest, src1, src2 Three operand instruction's syntax
41 ;; ARC and ARCompact PREDICATES:
43 ;; comparison_operator LT, GT, LE, GE, LTU, GTU, LEU, GEU, EQ, NE
44 ;; memory_operand memory [m]
45 ;; immediate_operand immediate constant [IKLMNOP]
46 ;; register_operand register [rq]
47 ;; general_operand register, memory, constant [rqmIKLMNOP]
49 ;; Note that the predicates are only used when selecting a pattern
50 ;; to determine if an operand is valid.
52 ;; The constraints then select which of the possible valid operands
53 ;; is present (and guide register selection). The actual assembly
54 ;; instruction is then selected on the basis of the constraints.
56 ;; ARC and ARCompact CONSTRAINTS:
58 ;; b stack pointer r28
59 ;; f frame pointer r27
60 ;; Rgp global pointer r26
61 ;; g general reg, memory, constant
64 ;; q registers commonly used in
65 ;; 16-bit insns r0-r3, r12-r15
66 ;; c core registers r0-r60, ap, pcl
67 ;; r general registers r0-r28, blink, ap, pcl
69 ;; H fp 16-bit constant
70 ;; I signed 12-bit immediate (for ARCompact)
71 ;; K unsigned 3-bit immediate (for ARCompact)
72 ;; L unsigned 6-bit immediate (for ARCompact)
73 ;; M unsinged 5-bit immediate (for ARCompact)
74 ;; O unsinged 7-bit immediate (for ARCompact)
75 ;; P unsinged 8-bit immediate (for ARCompact)
76 ;; N constant '1' (for ARCompact)
80 ;; -> prefetch instruction
82 ;; -----------------------------------------------------------------------------
84 ;; Include DFA scheduluers
85 (include ("arc600.md"))
86 (include ("arc700.md"))
90 (include ("predicates.md"))
91 (include ("constraints.md"))
92 ;; -----------------------------------------------------------------------------
96 ;; -----------------------------------------------------------------------------
97 ;; Symbolic name Value Desc.
98 ;; -----------------------------------------------------------------------------
99 ;; UNSPEC_PLT 3 symbol to be referenced through the PLT
100 ;; UNSPEC_GOT 4 symbol to be rerenced through the GOT
101 ;; UNSPEC_GOTOFF 5 Local symbol.To be referenced relative to the
102 ;; GOTBASE.(Referenced as @GOTOFF)
103 ;; ----------------------------------------------------------------------------
107 [(UNSPEC_SWAP 13) ; swap generation through builtins. candidate for scheduling
108 (UNSPEC_MUL64 14) ; mul64 generation through builtins. candidate for scheduling
109 (UNSPEC_MULU64 15) ; mulu64 generation through builtins. candidate for scheduling
110 (UNSPEC_DIVAW 16) ; divaw generation through builtins. candidate for scheduling
112 (UNSPEC_PROF 18) ; profile callgraph counter
113 (UNSPEC_LP 19) ; to set LP_END
115 (VUNSPEC_RTIE 17) ; blockage insn for rtie generation
116 (VUNSPEC_SYNC 18) ; blockage insn for sync generation
117 (VUNSPEC_BRK 19) ; blockage insn for brk generation
118 (VUNSPEC_FLAG 20) ; blockage insn for flag generation
119 (VUNSPEC_SLEEP 21) ; blockage insn for sleep generation
120 (VUNSPEC_SWI 22) ; blockage insn for swi generation
121 (VUNSPEC_CORE_READ 23) ; blockage insn for reading a core register
122 (VUNSPEC_CORE_WRITE 24) ; blockage insn for writing to a core register
123 (VUNSPEC_LR 25) ; blockage insn for reading an auxiliary register
124 (VUNSPEC_SR 26) ; blockage insn for writing to an auxiliary register
125 (VUNSPEC_TRAP_S 27) ; blockage insn for trap_s generation
126 (VUNSPEC_UNIMP_S 28) ; blockage insn for unimp_s generation
136 (RETURN_ADDR_REGNUM 31)
139 (VUNSPEC_DEXCL 32) ; blockage insn for reading an auxiliary register without LR support
140 (VUNSPEC_DEXCL_NORES 33) ; blockage insn for reading an auxiliary register without LR support
141 (VUNSPEC_LR_HIGH 34) ; blockage insn for reading an auxiliary register
150 (define_attr "is_sfunc" "no,yes" (const_string "no"))
152 ;; Insn type. Used to default other attribute values.
153 ; While the attribute is_sfunc is set for any call of a special function,
154 ; the instruction type sfunc is used only for the special call sequence
155 ; that loads the (pc-relative) function address into r12 and then calls
159 "move,load,store,cmove,unary,binary,compare,shift,uncond_branch,jump,branch,
160 brcc,brcc_no_delay_slot,call,sfunc,call_no_delay_slot,
161 multi,umulti, two_cycle_core,lr,sr,divaw,loop_setup,loop_end,return,
162 misc,spfp,dpfp_mult,dpfp_addsub,mulmac_600,cc_arith,
163 simd_vload, simd_vload128, simd_vstore, simd_vmove, simd_vmove_else_zero,
164 simd_vmove_with_acc, simd_varith_1cycle, simd_varith_2cycle,
165 simd_varith_with_acc, simd_vlogic, simd_vlogic_with_acc,
166 simd_vcompare, simd_vpermute, simd_vpack, simd_vpack_with_acc,
167 simd_valign, simd_valign_with_acc, simd_vcontrol,
168 simd_vspecial_3cycle, simd_vspecial_4cycle, simd_dma"
169 (cond [(eq_attr "is_sfunc" "yes")
170 (cond [(match_test "!TARGET_LONG_CALLS_SET && (!TARGET_MEDIUM_CALLS || GET_CODE (PATTERN (insn)) != COND_EXEC)") (const_string "call")
171 (match_test "flag_pic") (const_string "sfunc")]
172 (const_string "call_no_delay_slot"))]
173 (const_string "binary")))
175 ;; The following three attributes are mixed case so that they can be
176 ;; used conveniently with the CALL_ATTR macro.
177 (define_attr "is_CALL" "no,yes"
178 (cond [(eq_attr "is_sfunc" "yes") (const_string "yes")
179 (eq_attr "type" "call,call_no_delay_slot") (const_string "yes")]
180 (const_string "no")))
182 (define_attr "is_SIBCALL" "no,yes" (const_string "no"))
184 (define_attr "is_NON_SIBCALL" "no,yes"
185 (cond [(eq_attr "is_SIBCALL" "yes") (const_string "no")
186 (eq_attr "is_CALL" "yes") (const_string "yes")]
187 (const_string "no")))
190 ;; Attribute describing the processor
191 (define_attr "cpu" "none,A5,ARC600,ARC700"
192 (const (symbol_ref "arc_cpu_attr")))
194 ;; true for compact instructions (those with _s suffix)
195 ;; "maybe" means compact unless we conditionalize the insn.
196 (define_attr "iscompact" "true,maybe,true_limm,maybe_limm,false"
197 (cond [(eq_attr "type" "sfunc")
198 (const_string "maybe")]
199 (const_string "false")))
202 ; Is there an instruction that we are actually putting into the delay slot?
203 (define_attr "delay_slot_filled" "no,yes"
204 (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
206 (match_test "!TARGET_AT_DBR_CONDEXEC
208 && INSN_ANNULLED_BRANCH_P (insn)
209 && !INSN_FROM_TARGET_P (NEXT_INSN (insn))")
211 (const_string "yes")))
213 ; Is a delay slot present for purposes of shorten_branches?
214 ; We have to take the length of this insn into account for forward branches
215 ; even if we don't put the insn actually into a delay slot.
216 (define_attr "delay_slot_present" "no,yes"
217 (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
219 (const_string "yes")))
221 ; We can't use get_attr_length (NEXT_INSN (insn)) because this gives the
222 ; length of a different insn with the same uid.
223 (define_attr "delay_slot_length" ""
224 (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
226 (symbol_ref "get_attr_length (NEXT_INSN (PREV_INSN (insn)))
227 - get_attr_length (insn)")))
230 (define_attr "enabled" "no,yes" (const_string "yes"))
232 (define_attr "predicable" "no,yes" (const_string "no"))
233 ;; if 'predicable' were not so brain-dead, we would specify:
234 ;; (cond [(eq_attr "cond" "!canuse") (const_string "no")
235 ;; (eq_attr "iscompact" "maybe") (const_string "no")]
236 ;; (const_string "yes"))
237 ;; and then for everything but calls, we could just set the cond attribute.
239 ;; Condition codes: this one is used by final_prescan_insn to speed up
240 ;; conditionalizing instructions. It saves having to scan the rtl to see if
241 ;; it uses or alters the condition codes.
243 ;; USE: This insn uses the condition codes (eg: a conditional branch).
244 ;; CANUSE: This insn can use the condition codes (for conditional execution).
245 ;; SET: All condition codes are set by this insn.
246 ;; SET_ZN: the Z and N flags are set by this insn.
247 ;; SET_ZNC: the Z, N, and C flags are set by this insn.
248 ;; CLOB: The condition codes are set to unknown values by this insn.
249 ;; NOCOND: This insn can't use and doesn't affect the condition codes.
251 (define_attr "cond" "use,canuse,canuse_limm,canuse_limm_add,set,set_zn,clob,nocond"
253 [(and (eq_attr "predicable" "yes")
254 (eq_attr "is_sfunc" "no")
255 (eq_attr "delay_slot_filled" "no"))
256 (const_string "canuse")
258 (eq_attr "type" "call")
259 (cond [(eq_attr "delay_slot_filled" "yes") (const_string "nocond")
260 (match_test "!flag_pic") (const_string "canuse_limm")]
261 (const_string "nocond"))
263 (eq_attr "iscompact" "maybe,false")
264 (cond [ (and (eq_attr "type" "move")
265 (match_operand 1 "immediate_operand" ""))
267 (ior (match_operand 1 "u6_immediate_operand" "")
268 (match_operand 1 "long_immediate_operand" ""))
269 (const_string "canuse")
270 (const_string "canuse_limm"))
272 (eq_attr "type" "binary")
273 (cond [(ne (symbol_ref "REGNO (operands[0])")
274 (symbol_ref "REGNO (operands[1])"))
275 (const_string "nocond")
276 (match_operand 2 "register_operand" "")
277 (const_string "canuse")
278 (match_operand 2 "u6_immediate_operand" "")
279 (const_string "canuse")
280 (match_operand 2 "long_immediate_operand" "")
281 (const_string "canuse")
282 (match_operand 2 "const_int_operand" "")
283 (const_string "canuse_limm")]
284 (const_string "nocond"))
286 (eq_attr "type" "compare")
289 (eq_attr "type" "cmove,branch")
292 (eq_attr "is_sfunc" "yes")
293 (cond [(match_test "(TARGET_MEDIUM_CALLS
294 && !TARGET_LONG_CALLS_SET
296 (const_string "canuse_limm_add")
297 (match_test "(TARGET_MEDIUM_CALLS
298 && !TARGET_LONG_CALLS_SET)")
299 (const_string "canuse_limm")]
300 (const_string "canuse"))
304 (const_string "nocond"))]
306 (cond [(eq_attr "type" "compare")
309 (eq_attr "type" "cmove,branch")
314 (const_string "nocond"))))
316 /* ??? Having all these patterns gives ifcvt more freedom to generate
317 inefficient code. It seem to operate on the premise that
318 register-register copies and registers are free. I see better code
319 with -fno-if-convert now than without. */
321 [(match_operator 0 "proper_comparison_operator"
322 [(reg CC_REG) (const_int 0)])]
326 ;; Length (in # of bytes, long immediate constants counted too).
327 ;; ??? There's a nasty interaction between the conditional execution fsm
328 ;; and insn lengths: insns with shimm values cannot be conditionally executed.
329 (define_attr "length" ""
331 [(eq_attr "iscompact" "true,maybe")
333 [(eq_attr "type" "sfunc")
334 (cond [(match_test "GET_CODE (PATTERN (insn)) == COND_EXEC")
337 (match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 4)]
340 (eq_attr "iscompact" "true_limm,maybe_limm")
343 (eq_attr "type" "load")
345 (match_operand 1 "long_immediate_loadstore_operand" "")
346 (const_int 8) (const_int 4))
348 (eq_attr "type" "store")
350 (ior (match_operand 0 "long_immediate_loadstore_operand" "")
351 (match_operand 1 "immediate_operand" ""))
352 (const_int 8) (const_int 4))
354 (eq_attr "type" "move,unary")
356 [(match_operand 1 "u6_immediate_operand" "") (const_int 4)
357 (match_operand 1 "register_operand" "") (const_int 4)
358 (match_operand 1 "long_immediate_operand" "") (const_int 8)
359 (match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 8)]
362 (and (eq_attr "type" "shift")
363 (match_operand 1 "immediate_operand"))
365 (eq_attr "type" "binary,shift")
367 (ior (match_operand 2 "long_immediate_operand" "")
368 (and (ne (symbol_ref "REGNO (operands[0])")
369 (symbol_ref "REGNO (operands[1])"))
370 (eq (match_operand 2 "u6_immediate_operand" "")
373 (const_int 8) (const_int 4))
375 (eq_attr "type" "cmove")
376 (if_then_else (match_operand 1 "register_operand" "")
377 (const_int 4) (const_int 8))
379 (eq_attr "type" "call_no_delay_slot") (const_int 8)
385 ;; The length here is the length of a single asm. Unfortunately it might be
386 ;; 4 or 8 so we must allow for 8. That's ok though. How often will users
387 ;; lament asm's not being put in delay slots?
389 (define_asm_attributes
390 [(set_attr "length" "8")
391 (set_attr "type" "multi")
392 (set_attr "cond" "clob") ])
395 ;; The first two cond clauses and the default are necessary for correctness;
396 ;; the remaining cond clause is mainly an optimization, as otherwise nops
397 ;; would be inserted; however, if we didn't do this optimization, we would
398 ;; have to be more conservative in our length calculations.
400 (define_attr "in_delay_slot" "false,true"
401 (cond [(eq_attr "type" "uncond_branch,jump,branch,
402 call,sfunc,call_no_delay_slot,
403 brcc, brcc_no_delay_slot,loop_setup,loop_end")
404 (const_string "false")
405 (match_test "arc_write_ext_corereg (insn)")
406 (const_string "false")
407 (gt (symbol_ref "arc_hazard (prev_active_insn (insn),
408 next_active_insn (insn))")
409 (symbol_ref "(arc_hazard (prev_active_insn (insn), insn)
410 + arc_hazard (insn, next_active_insn (insn)))"))
411 (const_string "false")
412 (eq_attr "iscompact" "maybe") (const_string "true")
415 (if_then_else (eq_attr "length" "2,4")
416 (const_string "true")
417 (const_string "false"))))
419 ; must not put an insn inside that refers to blink.
420 (define_attr "in_call_delay_slot" "false,true"
421 (cond [(eq_attr "in_delay_slot" "false")
422 (const_string "false")
423 (match_test "arc_regno_use_in (RETURN_ADDR_REGNUM, PATTERN (insn))")
424 (const_string "false")]
425 (const_string "true")))
427 (define_attr "in_sfunc_delay_slot" "false,true"
428 (cond [(eq_attr "in_call_delay_slot" "false")
429 (const_string "false")
430 (match_test "arc_regno_use_in (12, PATTERN (insn))")
431 (const_string "false")]
432 (const_string "true")))
434 ;; Instructions that we can put into a delay slot and conditionalize.
435 (define_attr "cond_delay_insn" "no,yes"
436 (cond [(eq_attr "cond" "!canuse") (const_string "no")
437 (eq_attr "type" "call,branch,uncond_branch,jump,brcc")
439 (eq_attr "length" "2,4") (const_string "yes")]
440 (const_string "no")))
442 (define_attr "in_ret_delay_slot" "no,yes"
443 (cond [(eq_attr "in_delay_slot" "false")
445 (match_test "regno_clobbered_p
446 (arc_return_address_regs
447 [arc_compute_function_type (cfun)],
450 (const_string "yes")))
452 (define_attr "cond_ret_delay_insn" "no,yes"
453 (cond [(eq_attr "in_ret_delay_slot" "no") (const_string "no")
454 (eq_attr "cond_delay_insn" "no") (const_string "no")]
455 (const_string "yes")))
457 (define_attr "annul_ret_delay_insn" "no,yes"
458 (cond [(eq_attr "cond_ret_delay_insn" "yes") (const_string "yes")
459 (match_test "TARGET_AT_DBR_CONDEXEC") (const_string "no")
460 (eq_attr "type" "!call,branch,uncond_branch,jump,brcc,return,sfunc")
461 (const_string "yes")]
462 (const_string "no")))
465 ;; Delay slot definition for ARCompact ISA
467 ;; When outputting an annul-true insn elegible for cond-exec
468 ;; in a cbranch delay slot, unless optimizing for size, we use cond-exec
469 ;; for ARC600; we could also use this for ARC700 if the branch can't be
470 ;; unaligned and is at least somewhat likely (add parameter for this).
472 (define_delay (eq_attr "type" "call")
473 [(eq_attr "in_call_delay_slot" "true")
474 (eq_attr "in_call_delay_slot" "true")
477 (define_delay (and (match_test "!TARGET_AT_DBR_CONDEXEC")
478 (eq_attr "type" "brcc"))
479 [(eq_attr "in_delay_slot" "true")
480 (eq_attr "in_delay_slot" "true")
483 (define_delay (and (match_test "TARGET_AT_DBR_CONDEXEC")
484 (eq_attr "type" "brcc"))
485 [(eq_attr "in_delay_slot" "true")
490 (eq_attr "type" "return")
491 [(eq_attr "in_ret_delay_slot" "yes")
492 (eq_attr "annul_ret_delay_insn" "yes")
493 (eq_attr "cond_ret_delay_insn" "yes")])
495 ;; For ARC600, unexposing the delay sloy incurs a penalty also in the
496 ;; non-taken case, so the only meaningful way to have an annull-true
497 ;; filled delay slot is to conditionalize the delay slot insn.
498 (define_delay (and (match_test "TARGET_AT_DBR_CONDEXEC")
499 (eq_attr "type" "branch,uncond_branch,jump")
500 (match_test "!optimize_size"))
501 [(eq_attr "in_delay_slot" "true")
502 (eq_attr "cond_delay_insn" "yes")
503 (eq_attr "cond_delay_insn" "yes")])
505 ;; For ARC700, anything goes for annulled-true insns, since there is no
506 ;; penalty for the unexposed delay slot when the branch is not taken,
507 ;; however, we must avoid things that have a delay slot themselvese to
508 ;; avoid confusing gcc.
509 (define_delay (and (match_test "!TARGET_AT_DBR_CONDEXEC")
510 (eq_attr "type" "branch,uncond_branch,jump")
511 (match_test "!optimize_size"))
512 [(eq_attr "in_delay_slot" "true")
513 (eq_attr "type" "!call,branch,uncond_branch,jump,brcc,return,sfunc")
514 (eq_attr "cond_delay_insn" "yes")])
516 ;; -mlongcall -fpic sfuncs use r12 to load the function address
517 (define_delay (eq_attr "type" "sfunc")
518 [(eq_attr "in_sfunc_delay_slot" "true")
519 (eq_attr "in_sfunc_delay_slot" "true")
521 ;; ??? need to use a working strategy for canuse_limm:
522 ;; - either canuse_limm is not eligible for delay slots, and has no
523 ;; delay slots, or arc_reorg has to treat them as nocond, or it has to
524 ;; somehow modify them to become inelegible for delay slots if a decision
525 ;; is made that makes conditional execution required.
527 (define_attr "tune" "none,arc600,arc700_4_2_std,arc700_4_2_xmac"
529 (cond [(symbol_ref "arc_tune == TUNE_ARC600")
530 (const_string "arc600")
531 (symbol_ref "arc_tune == TUNE_ARC700_4_2_STD")
532 (const_string "arc700_4_2_std")
533 (symbol_ref "arc_tune == TUNE_ARC700_4_2_XMAC")
534 (const_string "arc700_4_2_xmac")]
535 (const_string "none"))))
537 (define_attr "tune_arc700" "false,true"
538 (if_then_else (eq_attr "tune" "arc700_4_2_std, arc700_4_2_xmac")
539 (const_string "true")
540 (const_string "false")))
542 ;; Move instructions.
543 (define_expand "movqi"
544 [(set (match_operand:QI 0 "move_dest_operand" "")
545 (match_operand:QI 1 "general_operand" ""))]
547 "if (prepare_move_operands (operands, QImode)) DONE;")
549 ; In order to allow the ccfsm machinery to do its work, the leading compact
550 ; alternatives say 'canuse' - there is another alternative that will match
551 ; when the condition codes are used.
552 ; Rcq won't match if the condition is actually used; to avoid a spurious match
553 ; via q, q is inactivated as constraint there.
554 ; Likewise, the length of an alternative that might be shifted to conditional
555 ; execution must reflect this, lest out-of-range branches are created.
556 ; The iscompact attribute allows the epilogue expander to know for which
557 ; insns it should lengthen the return insn.
558 (define_insn "*movqi_insn"
559 [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w,???w, w,Rcq,S,!*x,r,m,???m")
560 (match_operand:QI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,?Rac,?i,T,Rcq,Usd,m,c,?Rac"))]
561 "register_operand (operands[0], QImode)
562 || register_operand (operands[1], QImode)"
577 [(set_attr "type" "move,move,move,move,move,move,move,load,store,load,load,store,store")
578 (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,true,true,true,false,false,false")
579 (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,no,no,no,no,no,no")])
581 (define_expand "movhi"
582 [(set (match_operand:HI 0 "move_dest_operand" "")
583 (match_operand:HI 1 "general_operand" ""))]
585 "if (prepare_move_operands (operands, HImode)) DONE;")
587 (define_insn "*movhi_insn"
588 [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w,???w,Rcq#q,w,Rcq,S,r,m,???m,VUsc")
589 (match_operand:HI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,?Rac, ?i,?i,T,Rcq,m,c,?Rac,i"))]
590 "register_operand (operands[0], HImode)
591 || register_operand (operands[1], HImode)
592 || (CONSTANT_P (operands[1])
593 /* Don't use a LIMM that we could load with a single insn - we loose
594 delay-slot filling opportunities. */
595 && !satisfies_constraint_I (operands[1])
596 && satisfies_constraint_Usc (operands[0]))"
612 [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,store,store,store")
613 (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,maybe_limm,false,true,true,false,false,false,false")
614 (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,yes,no,no,no,no,no,no")])
616 (define_expand "movsi"
617 [(set (match_operand:SI 0 "move_dest_operand" "")
618 (match_operand:SI 1 "general_operand" ""))]
620 "if (prepare_move_operands (operands, SImode)) DONE;")
622 ; In order to allow the ccfsm machinery to do its work, the leading compact
623 ; alternatives say 'canuse' - there is another alternative that will match
624 ; when the condition codes are used.
625 ; Rcq won't match if the condition is actually used; to avoid a spurious match
626 ; via q, q is inactivated as constraint there.
627 ; Likewise, the length of an alternative that might be shifted to conditional
628 ; execution must reflect this, lest out-of-range branches are created.
629 ; the iscompact attribute allows the epilogue expander to know for which
630 ; insns it should lengthen the return insn.
631 ; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc .
632 (define_insn "*movsi_insn"
633 [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w, w,???w, ?w, w,Rcq#q, w,Rcq, S,Us<,RcqRck,!*x,r,m,???m,VUsc")
634 (match_operand:SI 1 "move_src_operand" " cL,cP,Rcq#q,cL,I,Crr,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,m,c,?Rac,C32"))]
635 "register_operand (operands[0], SImode)
636 || register_operand (operands[1], SImode)
637 || (CONSTANT_P (operands[1])
638 /* Don't use a LIMM that we could load with a single insn - we loose
639 delay-slot filling opportunities. */
640 && !satisfies_constraint_I (operands[1])
641 && satisfies_constraint_Usc (operands[0]))"
648 ror %0,((%1*2+1) & 0x3f) ;5
651 * return arc_get_unalign () ? \"add %0,pcl,%1-.+2\" : \"add %0,pcl,%1-.\";
656 * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
657 * return arc_short_long (insn, \"pop%? %0%&\", \"ld%U1 %0,%1%&\");
663 [(set_attr "type" "move,move,move,move,move,two_cycle_core,move,binary,binary,move,move,load,store,store,load,load,load,store,store,store")
664 (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false")
665 ; Use default length for iscompact to allow for COND_EXEC. But set length
667 (set_attr "length" "*,*,*,4,4,4,4,8,8,*,8,*,*,*,*,*,*,*,*,8")
668 (set_attr "predicable" "yes,no,yes,yes,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no")])
670 ;; Sometimes generated by the epilogue code. We don't want to
671 ;; recognize these addresses in general, because the limm is costly,
672 ;; and we can't use them for stores. */
673 (define_insn "*movsi_pre_mod"
674 [(set (match_operand:SI 0 "register_operand" "=w")
677 (plus:SI (reg:SI SP_REG)
678 (match_operand 1 "immediate_operand" "Cal")))))]
681 [(set_attr "type" "load")
682 (set_attr "length" "8")])
684 ;; Store a value to directly to memory. The location might also be cached.
685 ;; Since the cached copy can cause a write-back at unpredictable times,
686 ;; we first write cached, then we write uncached.
687 (define_insn "store_direct"
688 [(set (match_operand:SI 0 "move_dest_operand" "=m")
689 (unspec:SI [(match_operand:SI 1 "register_operand" "c")]
692 "st%U0 %1,%0\;st%U0.di %1,%0"
693 [(set_attr "type" "store")])
695 (define_insn_and_split "*movsi_set_cc_insn"
696 [(set (match_operand:CC_ZN 2 "cc_set_register" "")
697 (match_operator 3 "zn_compare_operator"
698 [(match_operand:SI 1 "nonmemory_operand" "cI,cL,Cal") (const_int 0)]))
699 (set (match_operand:SI 0 "register_operand" "=w,w,w")
703 ; splitting to 'tst' allows short insns and combination into brcc.
704 "reload_completed && operands_match_p (operands[0], operands[1])"
705 [(set (match_dup 2) (match_dup 3))]
707 [(set_attr "type" "compare")
708 (set_attr "predicable" "no,yes,yes")
709 (set_attr "cond" "set_zn")
710 (set_attr "length" "4,4,8")])
712 (define_insn "unary_comparison"
713 [(set (match_operand:CC_ZN 0 "cc_set_register" "")
714 (match_operator 3 "zn_compare_operator"
715 [(match_operator:SI 2 "unary_operator"
716 [(match_operand:SI 1 "register_operand" "c")])
720 [(set_attr "type" "compare")
721 (set_attr "cond" "set_zn")])
724 ; this pattern is needed by combiner for cases like if (c=(~b)) { ... }
725 (define_insn "*unary_comparison_result_used"
726 [(set (match_operand 2 "cc_register" "")
727 (match_operator 4 "zn_compare_operator"
728 [(match_operator:SI 3 "unary_operator"
729 [(match_operand:SI 1 "register_operand" "c")])
731 (set (match_operand:SI 0 "register_operand" "=w")
735 [(set_attr "type" "compare")
736 (set_attr "cond" "set_zn")
737 (set_attr "length" "4")])
741 (match_operand 0 "cc_register" "")
742 (match_operator 3 "zn_compare_operator"
744 (match_operand:SI 1 "register_operand"
745 "%Rcq,Rcq, c, c, c, c, c, c")
746 (match_operand:SI 2 "nonmemory_operand"
747 " Rcq,C0p,cI,cL,C1p,Ccp,CnL,Cal"))
749 "(register_operand (operands[1], SImode)
750 && nonmemory_operand (operands[2], SImode))
751 || (memory_operand (operands[1], SImode)
752 && satisfies_constraint_Cux (operands[2]))"
754 switch (which_alternative)
756 case 0: case 2: case 3: case 7:
757 return \"tst%? %1,%2\";
759 return \"btst%? %1,%z2\";
761 return \"bmsk%?.f 0,%1,%Z2%&\";
763 return \"bclr%?.f 0,%1,%M2%&\";
765 return \"bic%?.f 0,%1,%n2-1\";
770 [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false")
771 (set_attr "type" "compare")
772 (set_attr "length" "*,*,4,4,4,4,4,8")
773 (set_attr "predicable" "no,yes,no,yes,no,no,no,yes")
774 (set_attr "cond" "set_zn")])
776 (define_insn "*commutative_binary_comparison"
777 [(set (match_operand:CC_ZN 0 "cc_set_register" "")
778 (match_operator 5 "zn_compare_operator"
779 [(match_operator:SI 4 "commutative_operator"
780 [(match_operand:SI 1 "register_operand" "%c,c,c")
781 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
783 (clobber (match_scratch:SI 3 "=X,1,X"))]
786 [(set_attr "type" "compare")
787 (set_attr "cond" "set_zn")
788 (set_attr "length" "4,4,8")])
790 ; for flag setting 'add' instructions like if (a+b) { ...}
791 ; the combiner needs this pattern
792 (define_insn "*addsi_compare"
793 [(set (reg:CC_ZN CC_REG)
794 (compare:CC_ZN (match_operand:SI 0 "register_operand" "c")
795 (neg:SI (match_operand:SI 1 "register_operand" "c"))))]
798 [(set_attr "cond" "set")
799 (set_attr "type" "compare")
800 (set_attr "length" "4")])
802 ; for flag setting 'add' instructions like if (a+b < a) { ...}
803 ; the combiner needs this pattern
804 (define_insn "addsi_compare_2"
805 [(set (reg:CC_C CC_REG)
806 (compare:CC_C (plus:SI (match_operand:SI 0 "register_operand" "c,c")
807 (match_operand:SI 1 "nonmemory_operand" "cL,Cal"))
811 [(set_attr "cond" "set")
812 (set_attr "type" "compare")
813 (set_attr "length" "4,8")])
815 (define_insn "*addsi_compare_3"
816 [(set (reg:CC_C CC_REG)
817 (compare:CC_C (plus:SI (match_operand:SI 0 "register_operand" "c")
818 (match_operand:SI 1 "register_operand" "c"))
822 [(set_attr "cond" "set")
823 (set_attr "type" "compare")
824 (set_attr "length" "4")])
826 ; this pattern is needed by combiner for cases like if (c=a+b) { ... }
827 (define_insn "*commutative_binary_comparison_result_used"
828 [(set (match_operand 3 "cc_register" "")
829 (match_operator 5 "zn_compare_operator"
830 ; We can accept any commutative operator except mult because
831 ; our 'w' class below could try to use LP_COUNT.
832 [(match_operator:SI 4 "commutative_operator_sans_mult"
833 [(match_operand:SI 1 "register_operand" "c,0,c")
834 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
836 (set (match_operand:SI 0 "register_operand" "=w,w,w")
839 "%O4.f %0,%1,%2 ; non-mult commutative"
840 [(set_attr "type" "compare,compare,compare")
841 (set_attr "cond" "set_zn,set_zn,set_zn")
842 (set_attr "length" "4,4,8")])
844 ; a MULT-specific version of this pattern to avoid touching the
846 (define_insn "*commutative_binary_mult_comparison_result_used"
847 [(set (match_operand 3 "cc_register" "")
848 (match_operator 5 "zn_compare_operator"
849 [(match_operator:SI 4 "mult_operator"
850 [(match_operand:SI 1 "register_operand" "c,0,c")
851 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
853 ; Make sure to use the W class to not touch LP_COUNT.
854 (set (match_operand:SI 0 "register_operand" "=W,W,W")
857 "%O4.f %0,%1,%2 ; mult commutative"
858 [(set_attr "type" "compare,compare,compare")
859 (set_attr "cond" "set_zn,set_zn,set_zn")
860 (set_attr "length" "4,4,8")])
862 ; this pattern is needed by combiner for cases like if (c=a<<b) { ... }
863 (define_insn "*noncommutative_binary_comparison_result_used"
864 [(set (match_operand 3 "cc_register" "")
865 (match_operator 5 "zn_compare_operator"
866 [(match_operator:SI 4 "noncommutative_operator"
867 [(match_operand:SI 1 "register_operand" "c,0,c")
868 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
870 (set (match_operand:SI 0 "register_operand" "=w,w,w")
872 "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"
874 [(set_attr "type" "compare,compare,compare")
875 (set_attr "cond" "set_zn,set_zn,set_zn")
876 (set_attr "length" "4,4,8")])
878 (define_insn "*noncommutative_binary_comparison"
879 [(set (match_operand:CC_ZN 0 "cc_set_register" "")
880 (match_operator 5 "zn_compare_operator"
881 [(match_operator:SI 4 "noncommutative_operator"
882 [(match_operand:SI 1 "register_operand" "c,c,c")
883 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
885 (clobber (match_scratch:SI 3 "=X,1,X"))]
886 "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"
888 [(set_attr "type" "compare")
889 (set_attr "cond" "set_zn")
890 (set_attr "length" "4,4,8")])
892 (define_expand "bic_f_zn"
894 [(set (reg:CC_ZN CC_REG)
896 (and:SI (match_operand:SI 1 "register_operand" "")
897 (not:SI (match_operand:SI 2 "nonmemory_operand" "")))
899 (set (match_operand:SI 0 "register_operand" "")
900 (and:SI (match_dup 1) (not:SI (match_dup 2))))])]
903 (define_insn "*bic_f"
904 [(set (match_operand 3 "cc_register" "=Rcc,Rcc,Rcc")
905 (match_operator 4 "zn_compare_operator"
906 [(and:SI (match_operand:SI 1 "register_operand" "c,0,c")
908 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")))
910 (set (match_operand:SI 0 "register_operand" "=w,w,w")
911 (and:SI (match_dup 1) (not:SI (match_dup 2))))]
914 [(set_attr "type" "compare,compare,compare")
915 (set_attr "cond" "set_zn,set_zn,set_zn")
916 (set_attr "length" "4,4,8")])
918 (define_expand "movdi"
919 [(set (match_operand:DI 0 "move_dest_operand" "")
920 (match_operand:DI 1 "general_operand" ""))]
924 /* Everything except mem = const or mem = mem can be done easily. */
926 if (GET_CODE (operands[0]) == MEM)
927 operands[1] = force_reg (DImode, operands[1]);
930 (define_insn_and_split "*movdi_insn"
931 [(set (match_operand:DI 0 "move_dest_operand" "=w,w,r,m")
932 (match_operand:DI 1 "move_double_src_operand" "c,Hi,m,c"))]
933 "register_operand (operands[0], DImode)
934 || register_operand (operands[1], DImode)"
937 switch (which_alternative)
941 /* We normally copy the low-numbered register first. However, if
942 the first register operand 0 is the same as the second register of
943 operand 1, we must copy in the opposite order. */
944 if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
945 return \"mov%? %R0,%R1\;mov%? %0,%1\";
947 return \"mov%? %0,%1\;mov%? %R0,%R1\";
949 return \"mov%? %L0,%L1\;mov%? %H0,%H1\";
951 /* If the low-address word is used in the address, we must load it
952 last. Otherwise, load it first. Note that we cannot have
953 auto-increment in that case since the address register is known to be
955 if (refers_to_regno_p (REGNO (operands[0]), operands[1]))
956 return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
957 else switch (GET_CODE (XEXP(operands[1], 0)))
959 case POST_MODIFY: case POST_INC: case POST_DEC:
960 return \"ld%V1 %R0,%R1\;ld%U1%V1 %0,%1\";
961 case PRE_MODIFY: case PRE_INC: case PRE_DEC:
962 return \"ld%U1%V1 %0,%1\;ld%V1 %R0,%R1\";
964 return \"ld%U1%V1 %0,%1\;ld%U1%V1 %R0,%R1\";
967 switch (GET_CODE (XEXP(operands[0], 0)))
969 case POST_MODIFY: case POST_INC: case POST_DEC:
970 return \"st%V0 %R1,%R0\;st%U0%V0 %1,%0\";
971 case PRE_MODIFY: case PRE_INC: case PRE_DEC:
972 return \"st%U0%V0 %1,%0\;st%V0 %R1,%R0\";
974 return \"st%U0%V0 %1,%0\;st%U0%V0 %R1,%R0\";
978 "&& reload_completed && optimize"
979 [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))]
980 "arc_split_move (operands);"
981 [(set_attr "type" "move,move,load,store")
982 ;; ??? The ld/st values could be 4 if it's [reg,bignum].
983 (set_attr "length" "8,16,16,16")])
986 ;; Floating point move insns.
988 (define_expand "movsf"
989 [(set (match_operand:SF 0 "general_operand" "")
990 (match_operand:SF 1 "general_operand" ""))]
992 "if (prepare_move_operands (operands, SFmode)) DONE;")
994 (define_insn "*movsf_insn"
995 [(set (match_operand:SF 0 "move_dest_operand" "=w,w,r,m")
996 (match_operand:SF 1 "move_src_operand" "c,E,m,c"))]
997 "register_operand (operands[0], SFmode)
998 || register_operand (operands[1], SFmode)"
1004 [(set_attr "type" "move,move,load,store")
1005 (set_attr "predicable" "yes,yes,no,no")])
1007 (define_expand "movdf"
1008 [(set (match_operand:DF 0 "nonimmediate_operand" "")
1009 (match_operand:DF 1 "general_operand" ""))]
1011 "if (prepare_move_operands (operands, DFmode)) DONE;")
1013 (define_insn "*movdf_insn"
1014 [(set (match_operand:DF 0 "move_dest_operand" "=D,r,c,c,r,m")
1015 (match_operand:DF 1 "move_double_src_operand" "r,D,c,E,m,c"))]
1016 "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)"
1018 [(set_attr "type" "move,move,move,move,load,store")
1019 (set_attr "predicable" "no,no,yes,yes,no,no")
1020 ;; ??? The ld/st values could be 16 if it's [reg,bignum].
1021 (set_attr "length" "4,16,8,16,16,16")])
1024 [(set (match_operand:DF 0 "move_dest_operand" "")
1025 (match_operand:DF 1 "move_double_src_operand" ""))]
1028 "operands[2] = arc_split_move (operands);")
1030 (define_insn_and_split "*movdf_insn_nolrsr"
1031 [(set (match_operand:DF 0 "register_operand" "=r")
1032 (match_operand:DF 1 "arc_double_register_operand" "D"))
1033 (use (match_operand:SI 2 "" "N")) ; aka const1_rtx
1035 "TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR"
1040 (set (match_dup 0) (match_dup 3))
1042 ; daddh?? r1, r0, r0
1044 (set (match_dup 1) (plus:DF (match_dup 1) (match_dup 0)))
1047 (use (match_dup 0)) ; used to block can_combine_p
1048 (set (match_dup 0) (plus:DF (match_dup 1) (match_dup 0))) ; r1 in op 0
1051 ; We have to do this twice, once to read the value into R0 and
1052 ; second time to put back the contents which the first DEXCLx
1053 ; will have overwritten
1055 (set (match_dup 4) ; aka r0result
1057 (unspec_volatile:SI [(match_dup 1) (match_dup 5) (match_dup 4)] VUNSPEC_DEXCL ))
1058 ; Generate the second, which makes sure operand5 and operand4 values
1059 ; are put back in the Dx register properly.
1060 (unspec_volatile:SI [(match_dup 1) (match_dup 5) (match_dup 4)] VUNSPEC_DEXCL_NORES )
1062 ; Note: we cannot use a (clobber (match_scratch)) here because
1063 ; the combine pass will end up replacing uses of it with 0
1065 "operands[3] = CONST0_RTX (DFmode);
1066 operands[4] = simplify_gen_subreg (SImode, operands[0], DFmode, 0);
1067 operands[5] = simplify_gen_subreg (SImode, operands[0], DFmode, 4);"
1068 [(set_attr "type" "move")])
1070 ;; Load/Store with update instructions.
1072 ;; Some of these we can get by using pre-decrement or pre-increment, but the
1073 ;; hardware can also do cases where the increment is not the size of the
1076 ;; In all these cases, we use operands 0 and 1 for the register being
1077 ;; incremented because those are the operands that local-alloc will
1078 ;; tie and these are the pair most likely to be tieable (and the ones
1079 ;; that will benefit the most).
1081 ;; We use match_operator here because we need to know whether the memory
1082 ;; object is volatile or not.
1085 ;; Note: loadqi_update has no 16-bit variant
1086 (define_insn "*loadqi_update"
1087 [(set (match_operand:QI 3 "dest_reg_operand" "=r,r")
1088 (match_operator:QI 4 "load_update_operand"
1089 [(match_operand:SI 1 "register_operand" "0,0")
1090 (match_operand:SI 2 "nonmemory_operand" "rI,Cal")]))
1091 (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1092 (plus:SI (match_dup 1) (match_dup 2)))]
1094 "ldb.a%V4 %3,[%0,%S2]"
1095 [(set_attr "type" "load,load")
1096 (set_attr "length" "4,8")])
1098 (define_insn "*load_zeroextendqisi_update"
1099 [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1100 (zero_extend:SI (match_operator:QI 4 "load_update_operand"
1101 [(match_operand:SI 1 "register_operand" "0,0")
1102 (match_operand:SI 2 "nonmemory_operand" "rI,Cal")])))
1103 (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1104 (plus:SI (match_dup 1) (match_dup 2)))]
1106 "ldb.a%V4 %3,[%0,%S2]"
1107 [(set_attr "type" "load,load")
1108 (set_attr "length" "4,8")])
1110 (define_insn "*load_signextendqisi_update"
1111 [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1112 (sign_extend:SI (match_operator:QI 4 "load_update_operand"
1113 [(match_operand:SI 1 "register_operand" "0,0")
1114 (match_operand:SI 2 "nonmemory_operand" "rI,Cal")])))
1115 (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1116 (plus:SI (match_dup 1) (match_dup 2)))]
1118 "ldb.x.a%V4 %3,[%0,%S2]"
1119 [(set_attr "type" "load,load")
1120 (set_attr "length" "4,8")])
1122 (define_insn "*storeqi_update"
1123 [(set (match_operator:QI 4 "store_update_operand"
1124 [(match_operand:SI 1 "register_operand" "0")
1125 (match_operand:SI 2 "short_immediate_operand" "I")])
1126 (match_operand:QI 3 "register_operand" "c"))
1127 (set (match_operand:SI 0 "dest_reg_operand" "=w")
1128 (plus:SI (match_dup 1) (match_dup 2)))]
1130 "stb.a%V4 %3,[%0,%2]"
1131 [(set_attr "type" "store")
1132 (set_attr "length" "4")])
1134 ;; ??? pattern may have to be re-written
1135 ;; Note: no 16-bit variant for this pattern
1136 (define_insn "*loadhi_update"
1137 [(set (match_operand:HI 3 "dest_reg_operand" "=r,r")
1138 (match_operator:HI 4 "load_update_operand"
1139 [(match_operand:SI 1 "register_operand" "0,0")
1140 (match_operand:SI 2 "nonmemory_operand" "rI,Cal")]))
1141 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1142 (plus:SI (match_dup 1) (match_dup 2)))]
1144 "ldw.a%V4 %3,[%0,%S2]"
1145 [(set_attr "type" "load,load")
1146 (set_attr "length" "4,8")])
1148 (define_insn "*load_zeroextendhisi_update"
1149 [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1150 (zero_extend:SI (match_operator:HI 4 "load_update_operand"
1151 [(match_operand:SI 1 "register_operand" "0,0")
1152 (match_operand:SI 2 "nonmemory_operand" "rI,Cal")])))
1153 (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1154 (plus:SI (match_dup 1) (match_dup 2)))]
1156 "ldw.a%V4 %3,[%0,%S2]"
1157 [(set_attr "type" "load,load")
1158 (set_attr "length" "4,8")])
1160 ;; Note: no 16-bit variant for this instruction
1161 (define_insn "*load_signextendhisi_update"
1162 [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1163 (sign_extend:SI (match_operator:HI 4 "load_update_operand"
1164 [(match_operand:SI 1 "register_operand" "0,0")
1165 (match_operand:SI 2 "nonmemory_operand" "rI,Cal")])))
1166 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1167 (plus:SI (match_dup 1) (match_dup 2)))]
1169 "ldw.x.a%V4 %3,[%0,%S2]"
1170 [(set_attr "type" "load,load")
1171 (set_attr "length" "4,8")])
1173 (define_insn "*storehi_update"
1174 [(set (match_operator:HI 4 "store_update_operand"
1175 [(match_operand:SI 1 "register_operand" "0")
1176 (match_operand:SI 2 "short_immediate_operand" "I")])
1177 (match_operand:HI 3 "register_operand" "c"))
1178 (set (match_operand:SI 0 "dest_reg_operand" "=w")
1179 (plus:SI (match_dup 1) (match_dup 2)))]
1181 "stw.a%V4 %3,[%0,%2]"
1182 [(set_attr "type" "store")
1183 (set_attr "length" "4")])
1185 ;; No 16-bit variant for this instruction pattern
1186 (define_insn "*loadsi_update"
1187 [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1188 (match_operator:SI 4 "load_update_operand"
1189 [(match_operand:SI 1 "register_operand" "0,0")
1190 (match_operand:SI 2 "nonmemory_operand" "rI,Cal")]))
1191 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1192 (plus:SI (match_dup 1) (match_dup 2)))]
1194 "ld.a%V4 %3,[%0,%S2]"
1195 [(set_attr "type" "load,load")
1196 (set_attr "length" "4,8")])
1198 (define_insn "*storesi_update"
1199 [(set (match_operator:SI 4 "store_update_operand"
1200 [(match_operand:SI 1 "register_operand" "0")
1201 (match_operand:SI 2 "short_immediate_operand" "I")])
1202 (match_operand:SI 3 "register_operand" "c"))
1203 (set (match_operand:SI 0 "dest_reg_operand" "=w")
1204 (plus:SI (match_dup 1) (match_dup 2)))]
1206 "st.a%V4 %3,[%0,%2]"
1207 [(set_attr "type" "store")
1208 (set_attr "length" "4")])
1210 (define_insn "*loadsf_update"
1211 [(set (match_operand:SF 3 "dest_reg_operand" "=r,r")
1212 (match_operator:SF 4 "load_update_operand"
1213 [(match_operand:SI 1 "register_operand" "0,0")
1214 (match_operand:SI 2 "nonmemory_operand" "rI,Cal")]))
1215 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1216 (plus:SI (match_dup 1) (match_dup 2)))]
1218 "ld.a%V4 %3,[%0,%S2]"
1219 [(set_attr "type" "load,load")
1220 (set_attr "length" "4,8")])
1222 (define_insn "*storesf_update"
1223 [(set (match_operator:SF 4 "store_update_operand"
1224 [(match_operand:SI 1 "register_operand" "0")
1225 (match_operand:SI 2 "short_immediate_operand" "I")])
1226 (match_operand:SF 3 "register_operand" "c"))
1227 (set (match_operand:SI 0 "dest_reg_operand" "=w")
1228 (plus:SI (match_dup 1) (match_dup 2)))]
1230 "st.a%V4 %3,[%0,%2]"
1231 [(set_attr "type" "store")
1232 (set_attr "length" "4")])
1234 ;; Conditional move instructions.
1236 (define_expand "movsicc"
1237 [(set (match_operand:SI 0 "dest_reg_operand" "")
1238 (if_then_else:SI (match_operand 1 "comparison_operator" "")
1239 (match_operand:SI 2 "nonmemory_operand" "")
1240 (match_operand:SI 3 "register_operand" "")))]
1242 "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1245 (define_expand "movdicc"
1246 [(set (match_operand:DI 0 "dest_reg_operand" "")
1247 (if_then_else:DI(match_operand 1 "comparison_operator" "")
1248 (match_operand:DI 2 "nonmemory_operand" "")
1249 (match_operand:DI 3 "register_operand" "")))]
1251 "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1254 (define_expand "movsfcc"
1255 [(set (match_operand:SF 0 "dest_reg_operand" "")
1256 (if_then_else:SF (match_operand 1 "comparison_operator" "")
1257 (match_operand:SF 2 "nonmemory_operand" "")
1258 (match_operand:SF 3 "register_operand" "")))]
1260 "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1262 (define_expand "movdfcc"
1263 [(set (match_operand:DF 0 "dest_reg_operand" "")
1264 (if_then_else:DF (match_operand 1 "comparison_operator" "")
1265 (match_operand:DF 2 "nonmemory_operand" "")
1266 (match_operand:DF 3 "register_operand" "")))]
1268 "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1270 (define_insn "*movsicc_insn"
1271 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1272 (if_then_else:SI (match_operator 3 "proper_comparison_operator"
1273 [(match_operand 4 "cc_register" "") (const_int 0)])
1274 (match_operand:SI 1 "nonmemory_operand" "cL,Cal")
1275 (match_operand:SI 2 "register_operand" "0,0")))]
1278 if (rtx_equal_p (operands[1], const0_rtx) && GET_CODE (operands[3]) == NE
1279 && satisfies_constraint_Rcq (operands[0]))
1280 return "sub%?.ne %0,%0,%0";
1281 /* ??? might be good for speed on ARC600 too, *if* properly scheduled. */
1282 if ((TARGET_ARC700 || optimize_size)
1283 && rtx_equal_p (operands[1], constm1_rtx)
1284 && GET_CODE (operands[3]) == LTU)
1285 return "sbc.cs %0,%0,%0";
1286 return "mov.%d3 %0,%S1";
1288 [(set_attr "type" "cmove,cmove")
1289 (set_attr "length" "4,8")])
1291 ; Try to generate more short moves, and/or less limms, by substituting a
1292 ; conditional move with a conditional sub.
1294 [(set (match_operand:SI 0 "compact_register_operand")
1295 (match_operand:SI 1 "const_int_operand"))
1297 (if_then_else:SI (match_operator 3 "proper_comparison_operator"
1298 [(match_operand 4 "cc_register" "") (const_int 0)])
1299 (match_operand:SI 2 "const_int_operand" "")
1301 "!satisfies_constraint_P (operands[1])
1302 && satisfies_constraint_P (operands[2])
1303 && UNSIGNED_INT6 (INTVAL (operands[2]) - INTVAL (operands[1]))"
1304 [(set (match_dup 0) (match_dup 2))
1308 (plus:SI (match_dup 0) (match_dup 1))))]
1309 "operands[3] = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[3]),
1310 GET_MODE (operands[4])),
1311 VOIDmode, operands[4], const0_rtx);
1312 operands[1] = GEN_INT (INTVAL (operands[1]) - INTVAL (operands[2]));")
1314 (define_insn "*movdicc_insn"
1315 [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w")
1316 (if_then_else:DI (match_operator 3 "proper_comparison_operator"
1317 [(match_operand 4 "cc_register" "") (const_int 0)])
1318 (match_operand:DI 1 "nonmemory_operand" "c,i")
1319 (match_operand:DI 2 "register_operand" "0,0")))]
1323 switch (which_alternative)
1327 /* We normally copy the low-numbered register first. However, if
1328 the first register operand 0 is the same as the second register of
1329 operand 1, we must copy in the opposite order. */
1330 if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
1331 return \"mov.%d3 %R0,%R1\;mov.%d3 %0,%1\";
1333 return \"mov.%d3 %0,%1\;mov.%d3 %R0,%R1\";
1335 return \"mov.%d3 %L0,%L1\;mov.%d3 %H0,%H1\";
1340 [(set_attr "type" "cmove,cmove")
1341 (set_attr "length" "8,16")])
1344 (define_insn "*movsfcc_insn"
1345 [(set (match_operand:SF 0 "dest_reg_operand" "=w,w")
1346 (if_then_else:SF (match_operator 3 "proper_comparison_operator"
1347 [(match_operand 4 "cc_register" "") (const_int 0)])
1348 (match_operand:SF 1 "nonmemory_operand" "c,E")
1349 (match_operand:SF 2 "register_operand" "0,0")))]
1353 mov.%d3 %0,%1 ; %A1"
1354 [(set_attr "type" "cmove,cmove")])
1356 (define_insn "*movdfcc_insn"
1357 [(set (match_operand:DF 0 "dest_reg_operand" "=w,w")
1358 (if_then_else:DF (match_operator 1 "proper_comparison_operator"
1359 [(match_operand 4 "cc_register" "") (const_int 0)])
1360 (match_operand:DF 2 "nonmemory_operand" "c,E")
1361 (match_operand:DF 3 "register_operand" "0,0")))]
1365 switch (which_alternative)
1369 /* We normally copy the low-numbered register first. However, if
1370 the first register operand 0 is the same as the second register of
1371 operand 1, we must copy in the opposite order. */
1372 if (REGNO (operands[0]) == REGNO (operands[2]) + 1)
1373 return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\";
1375 return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\";
1377 return \"mov.%d1 %L0,%L2\;mov.%d1 %H0,%H2; %A2 \";
1381 [(set_attr "type" "cmove,cmove")
1382 (set_attr "length" "8,16")])
1385 (define_insn "*zero_extendqihi2_i"
1386 [(set (match_operand:HI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,r")
1387 (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,m")))]
1395 [(set_attr "type" "unary,unary,unary,unary,load")
1396 (set_attr "iscompact" "maybe,true,false,false,false")
1397 (set_attr "predicable" "no,no,yes,no,no")])
1399 (define_expand "zero_extendqihi2"
1400 [(set (match_operand:HI 0 "dest_reg_operand" "")
1401 (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1403 "if (prepare_extend_operands (operands, ZERO_EXTEND, HImode)) DONE;"
1406 (define_insn "*zero_extendqisi2_ac"
1407 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,qRcq,!*x,r")
1408 (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,T,Usd,m")))]
1418 [(set_attr "type" "unary,unary,unary,unary,load,load,load")
1419 (set_attr "iscompact" "maybe,true,false,false,true,true,false")
1420 (set_attr "predicable" "no,no,yes,no,no,no,no")])
1422 (define_expand "zero_extendqisi2"
1423 [(set (match_operand:SI 0 "dest_reg_operand" "")
1424 (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1426 "if (prepare_extend_operands (operands, ZERO_EXTEND, SImode)) DONE;"
1429 (define_insn "*zero_extendhisi2_i"
1430 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,q,Rcw,w,!x,Rcqq,r")
1431 (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "0,q,0,c,Usd,Usd,m")))]
1441 [(set_attr "type" "unary,unary,unary,unary,load,load,load")
1442 (set_attr "iscompact" "maybe,true,false,false,true,false,false")
1443 (set_attr "predicable" "no,no,yes,no,no,no,no")])
1446 (define_expand "zero_extendhisi2"
1447 [(set (match_operand:SI 0 "dest_reg_operand" "")
1448 (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "")))]
1450 "if (prepare_extend_operands (operands, ZERO_EXTEND, SImode)) DONE;"
1453 ;; Sign extension instructions.
1455 (define_insn "*extendqihi2_i"
1456 [(set (match_operand:HI 0 "dest_reg_operand" "=Rcqq,r,r")
1457 (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,r,m")))]
1463 [(set_attr "type" "unary,unary,load")
1464 (set_attr "iscompact" "true,false,false")])
1467 (define_expand "extendqihi2"
1468 [(set (match_operand:HI 0 "dest_reg_operand" "")
1469 (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1471 "if (prepare_extend_operands (operands, SIGN_EXTEND, HImode)) DONE;"
1474 (define_insn "*extendqisi2_ac"
1475 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r")
1476 (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,c,m")))]
1482 [(set_attr "type" "unary,unary,load")
1483 (set_attr "iscompact" "true,false,false")])
1485 (define_expand "extendqisi2"
1486 [(set (match_operand:SI 0 "dest_reg_operand" "")
1487 (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1489 "if (prepare_extend_operands (operands, SIGN_EXTEND, SImode)) DONE;"
1492 (define_insn "*extendhisi2_i"
1493 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r")
1494 (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,m")))]
1500 [(set_attr "type" "unary,unary,load")
1501 (set_attr "iscompact" "true,false,false")])
1503 (define_expand "extendhisi2"
1504 [(set (match_operand:SI 0 "dest_reg_operand" "")
1505 (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "")))]
1507 "if (prepare_extend_operands (operands, SIGN_EXTEND, SImode)) DONE;"
1510 ;; Unary arithmetic insns
1512 ;; We allow constant operands to enable late constant propagation, but it is
1513 ;; not worth while to have more than one dedicated alternative to output them -
1514 ;; if we are really worried about getting these the maximum benefit of all
1515 ;; the available alternatives, we should add an extra pass to fold such
1516 ;; operations to movsi.
1518 ;; Absolute instructions
1520 (define_insn "*abssi2_mixed"
1521 [(set (match_operand:SI 0 "compact_register_operand" "=q")
1522 (abs:SI (match_operand:SI 1 "compact_register_operand" "q")))]
1525 [(set_attr "type" "two_cycle_core")
1526 (set_attr "iscompact" "true")])
1528 (define_insn "abssi2"
1529 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,w,w")
1530 (abs:SI (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,Cal")))]
1533 [(set_attr "type" "two_cycle_core")
1534 (set_attr "length" "*,4,8")
1535 (set_attr "iscompact" "true,false,false")])
1537 ;; Maximum and minimum insns
1539 (define_insn "smaxsi3"
1540 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w")
1541 (smax:SI (match_operand:SI 1 "register_operand" "%0, c, c")
1542 (match_operand:SI 2 "nonmemory_operand" "cL,cL,Cal")))]
1545 [(set_attr "type" "two_cycle_core")
1546 (set_attr "length" "4,4,8")
1547 (set_attr "predicable" "yes,no,no")]
1550 (define_insn "sminsi3"
1551 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w")
1552 (smin:SI (match_operand:SI 1 "register_operand" "%0, c, c")
1553 (match_operand:SI 2 "nonmemory_operand" "cL,cL,Cal")))]
1556 [(set_attr "type" "two_cycle_core")
1557 (set_attr "length" "4,4,8")
1558 (set_attr "predicable" "yes,no,no")]
1561 ;; Arithmetic instructions.
1563 ; We say an insn can be conditionalized if this doesn't introduce a long
1564 ; immediate. We set the type such that we still have good scheduling if the
1565 ; insn is conditionalized.
1566 ; ??? It would make sense to allow introduction of long immediates, but
1567 ; we'd need to communicate to the ccfsm machinery the extra cost.
1568 ; The alternatives in the constraints still serve three purposes:
1569 ; - estimate insn size assuming conditional execution
1570 ; - guide reload to re-order the second and third operand to get a better fit.
1571 ; - give tentative insn type to guide scheduling
1572 ; N.B. "%" for commutativity doesn't help when there is another matching
1573 ; (but longer) alternative.
1574 ; We avoid letting this pattern use LP_COUNT as a register by specifying
1575 ; register class 'W' instead of 'w'.
1576 (define_insn_and_split "*addsi3_mixed"
1577 ;; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10
1578 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,Rcq,Rcw,Rcw,Rcq,Rcb,Rcq, Rcw, Rcqq,Rcqq, W, W,W, W,Rcqq,Rcw, W")
1579 (plus:SI (match_operand:SI 1 "register_operand" "%0, c, 0, c, 0, 0,Rcb, 0, Rcqq, 0, c, c,0, 0, 0, 0, c")
1580 (match_operand:SI 2 "nonmemory_operand" "cL, 0, cL, 0,CL2,Csp,CM4,cCca,RcqqK, cO,cLCmL,Cca,I,C2a, Cal,Cal,Cal")))]
1583 arc_output_addsi (operands, arc_ccfsm_cond_exec_p (), true);
1586 "&& reload_completed && get_attr_length (insn) == 8
1587 && satisfies_constraint_I (operands[2])
1588 && GET_CODE (PATTERN (insn)) != COND_EXEC"
1589 [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))]
1590 "split_addsi (operands);"
1591 [(set_attr "type" "*,*,*,*,two_cycle_core,two_cycle_core,*,two_cycle_core,*,*,*,two_cycle_core,*,two_cycle_core,*,*,*")
1592 (set (attr "iscompact")
1593 (cond [(match_test "~arc_output_addsi (operands, false, false) & 2")
1594 (const_string "false")
1595 (match_operand 2 "long_immediate_operand" "")
1596 (const_string "maybe_limm")]
1597 (const_string "maybe")))
1598 (set_attr "length" "*,*,4,4,*,*,*,4,*,*,4,4,4,4,*,8,8")
1599 (set_attr "predicable" "no,no,yes,yes,no,no,no,yes,no,no,no,no,no,no,no,yes,no")
1600 (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,nocond,canuse,nocond,nocond,nocond,nocond,canuse_limm,canuse_limm,canuse,canuse,nocond")
1603 ;; ARC700/ARC600 multiply
1606 (define_expand "mulsi3"
1607 [(set (match_operand:SI 0 "nonimmediate_operand" "")
1608 (mult:SI (match_operand:SI 1 "register_operand" "")
1609 (match_operand:SI 2 "nonmemory_operand" "")))]
1612 if (TARGET_ARC700 && !TARGET_NOMPY_SET)
1614 if (!register_operand (operands[0], SImode))
1616 rtx result = gen_reg_rtx (SImode);
1618 emit_insn (gen_mulsi3 (result, operands[1], operands[2]));
1619 emit_move_insn (operands[0], result);
1623 else if (TARGET_MUL64_SET)
1625 emit_insn (gen_mulsi_600 (operands[1], operands[2],
1626 gen_mlo (), gen_mhi ()));
1627 emit_move_insn (operands[0], gen_mlo ());
1630 else if (TARGET_MULMAC_32BY16_SET)
1632 if (immediate_operand (operands[2], SImode)
1633 && INTVAL (operands[2]) >= 0
1634 && INTVAL (operands[2]) <= 65535)
1636 emit_insn (gen_umul_600 (operands[1], operands[2],
1637 gen_acc2 (), gen_acc1 ()));
1638 emit_move_insn (operands[0], gen_acc2 ());
1641 operands[2] = force_reg (SImode, operands[2]);
1642 emit_insn (gen_umul_600 (operands[1], operands[2],
1643 gen_acc2 (), gen_acc1 ()));
1644 emit_insn (gen_mac_600 (operands[1], operands[2],
1645 gen_acc2 (), gen_acc1 ()));
1646 emit_move_insn (operands[0], gen_acc2 ());
1651 emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
1652 emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
1653 emit_insn (gen_mulsi3_600_lib ());
1654 emit_move_insn (operands[0], gen_rtx_REG (SImode, R0_REG));
1659 ; mululw conditional execution without a LIMM clobbers an input register;
1660 ; we'd need a different pattern to describe this.
1661 ; To make the conditional execution valid for the LIMM alternative, we
1662 ; have to emit the LIMM before the register operand.
1663 (define_insn "umul_600"
1664 [(set (match_operand:SI 2 "acc2_operand" "")
1665 (mult:SI (match_operand:SI 0 "register_operand" "c,c,c")
1666 (zero_extract:SI (match_operand:SI 1 "nonmemory_operand"
1670 (clobber (match_operand:SI 3 "acc1_operand" ""))]
1671 "TARGET_MULMAC_32BY16_SET"
1675 [(set_attr "length" "4,4,8")
1676 (set_attr "type" "mulmac_600, mulmac_600, mulmac_600")
1677 (set_attr "predicable" "no, no, yes")
1678 (set_attr "cond" "nocond, canuse_limm, canuse")])
1680 (define_insn "mac_600"
1681 [(set (match_operand:SI 2 "acc2_operand" "")
1683 (mult:SI (match_operand:SI 0 "register_operand" "c,c,c")
1685 (zero_extract:SI (match_operand:SI 1 "nonmemory_operand" "c,L,Cal")
1690 (clobber (match_operand:SI 3 "acc1_operand" ""))]
1691 "TARGET_MULMAC_32BY16_SET"
1692 "machlw%? 0, %0, %1"
1693 [(set_attr "length" "4,4,8")
1694 (set_attr "type" "mulmac_600, mulmac_600, mulmac_600")
1695 (set_attr "predicable" "no, no, yes")
1696 (set_attr "cond" "nocond, canuse_limm, canuse")])
1698 (define_insn "mulsi_600"
1699 [(set (match_operand:SI 2 "mlo_operand" "")
1700 (mult:SI (match_operand:SI 0 "register_operand" "%Rcq#q,c,c,c")
1701 (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,I,Cal")))
1702 (clobber (match_operand:SI 3 "mhi_operand" ""))]
1704 ; The assembler mis-assembles mul64 / mulu64 with "I" constraint constants,
1705 ; using a machine code pattern that only allows "L" constraint constants.
1706 ; "mul64%? \t0, %0, %1%&"
1708 if (satisfies_constraint_I (operands[1])
1709 && !satisfies_constraint_L (operands[1]))
1711 /* MUL64 <0,>b,s12 00101bbb10000100 0BBBssssssSSSSSS */
1712 int n = true_regnum (operands[0]);
1713 int i = INTVAL (operands[1]);
1714 asm_fprintf (asm_out_file, "\t.short %d`", 0x2884 + ((n & 7) << 8));
1715 asm_fprintf (asm_out_file, "\t.short %d`",
1716 ((i & 0x3f) << 6) + ((i >> 6) & 0x3f) + ((n & 070) << 9));
1717 return "; mul64%? \t0, %0, %1%&";
1719 return "mul64%? \t0, %0, %1%&";
1721 [(set_attr "length" "*,4,4,8")
1722 (set_attr "iscompact" "maybe,false,false,false")
1723 (set_attr "type" "multi,multi,multi,multi")
1724 (set_attr "predicable" "yes,yes,no,yes")
1725 (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
1727 ; If we compile without an mul option enabled, but link with libraries
1728 ; for a mul option, we'll see clobbers of multiplier output registers.
1729 ; There is also an implementation using norm that clobbers the loop registers.
1730 (define_insn "mulsi3_600_lib"
1731 [(set (reg:SI R0_REG)
1732 (mult:SI (reg:SI R0_REG) (reg:SI R1_REG)))
1733 (clobber (reg:SI RETURN_ADDR_REGNUM))
1734 (clobber (reg:SI R1_REG))
1735 (clobber (reg:SI R2_REG))
1736 (clobber (reg:SI R3_REG))
1737 (clobber (reg:DI MUL64_OUT_REG))
1738 (clobber (reg:SI LP_COUNT))
1739 (clobber (reg:SI LP_START))
1740 (clobber (reg:SI LP_END))
1741 (clobber (reg:CC CC_REG))]
1742 "!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET
1743 && (!TARGET_ARC700 || TARGET_NOMPY_SET)
1744 && SFUNC_CHECK_PREDICABLE"
1745 "*return arc_output_libcall (\"__mulsi3\");"
1746 [(set_attr "is_sfunc" "yes")
1747 (set_attr "predicable" "yes")])
1749 (define_insn "mulsidi_600"
1750 [(set (reg:DI MUL64_OUT_REG)
1751 (mult:DI (sign_extend:DI
1752 (match_operand:SI 0 "register_operand" "%Rcq#q,c,c,c"))
1754 ; assembler issue for "I", see mulsi_600
1755 ; (match_operand:SI 1 "register_operand" "Rcq#q,cL,I,Cal"))))]
1756 (match_operand:SI 1 "register_operand" "Rcq#q,cL,L,C32"))))]
1758 "mul64%? \t0, %0, %1%&"
1759 [(set_attr "length" "*,4,4,8")
1760 (set_attr "iscompact" "maybe,false,false,false")
1761 (set_attr "type" "multi,multi,multi,multi")
1762 (set_attr "predicable" "yes,yes,no,yes")
1763 (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
1765 (define_insn "umulsidi_600"
1766 [(set (reg:DI MUL64_OUT_REG)
1767 (mult:DI (zero_extend:DI
1768 (match_operand:SI 0 "register_operand" "%c,c,c"))
1770 ; assembler issue for "I", see mulsi_600
1771 ; (match_operand:SI 1 "register_operand" "cL,I,Cal"))))]
1772 (match_operand:SI 1 "register_operand" "cL,L,C32"))))]
1774 "mulu64%? \t0, %0, %1%&"
1775 [(set_attr "length" "4,4,8")
1776 (set_attr "iscompact" "false")
1777 (set_attr "type" "umulti")
1778 (set_attr "predicable" "yes,no,yes")
1779 (set_attr "cond" "canuse,canuse_limm,canuse")])
1781 ; ARC700 mpy* instructions: This is a multi-cycle extension, and thus 'w'
1782 ; may not be used as destination constraint.
1784 ; The result of mpy and mpyu is the same except for flag setting (if enabled),
1785 ; but mpyu is faster for the standard multiplier.
1786 ; Note: we must make sure LP_COUNT is not one of the destination
1787 ; registers, since it cannot be the destination of a multi-cycle insn
1789 (define_insn "mulsi3_700"
1790 [(set (match_operand:SI 0 "mpy_dest_reg_operand" "=Rcr,r,r,Rcr,r")
1791 (mult:SI (match_operand:SI 1 "register_operand" " 0,c,0,0,c")
1792 (match_operand:SI 2 "nonmemory_operand" "cL,cL,I,Cal,Cal")))]
1793 "TARGET_ARC700 && !TARGET_NOMPY_SET"
1795 [(set_attr "length" "4,4,4,8,8")
1796 (set_attr "type" "umulti")
1797 (set_attr "predicable" "yes,no,no,yes,no")
1798 (set_attr "cond" "canuse,nocond,canuse_limm,canuse,nocond")])
1800 (define_expand "mulsidi3"
1801 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1802 (mult:DI (sign_extend:DI(match_operand:SI 1 "register_operand" ""))
1803 (sign_extend:DI(match_operand:SI 2 "nonmemory_operand" ""))))]
1804 "(TARGET_ARC700 && !TARGET_NOMPY_SET)
1806 || TARGET_MULMAC_32BY16_SET"
1809 if (TARGET_ARC700 && !TARGET_NOMPY_SET)
1811 operands[2] = force_reg (SImode, operands[2]);
1812 if (!register_operand (operands[0], DImode))
1814 rtx result = gen_reg_rtx (DImode);
1816 operands[2] = force_reg (SImode, operands[2]);
1817 emit_insn (gen_mulsidi3 (result, operands[1], operands[2]));
1818 emit_move_insn (operands[0], result);
1822 else if (TARGET_MUL64_SET)
1824 operands[2] = force_reg (SImode, operands[2]);
1825 emit_insn (gen_mulsidi_600 (operands[1], operands[2]));
1826 emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
1829 else if (TARGET_MULMAC_32BY16_SET)
1831 rtx result_hi = gen_highpart(SImode, operands[0]);
1832 rtx result_low = gen_lowpart(SImode, operands[0]);
1834 emit_insn (gen_mul64_600 (operands[1], operands[2]));
1835 emit_insn (gen_mac64_600 (result_hi, operands[1], operands[2]));
1836 emit_move_insn (result_low, gen_acc2 ());
1841 (define_insn "mul64_600"
1843 (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand"
1845 (zero_extract:DI (match_operand:SI 1 "nonmemory_operand"
1850 "TARGET_MULMAC_32BY16_SET"
1852 [(set_attr "length" "4,4,8")
1853 (set_attr "type" "mulmac_600")
1854 (set_attr "predicable" "no,no,yes")
1855 (set_attr "cond" "nocond, canuse_limm, canuse")])
1858 ;; ??? check if this is canonical rtl
1859 (define_insn "mac64_600"
1862 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "c,c,c"))
1864 (sign_extract:DI (match_operand:SI 2 "nonmemory_operand" "c,L,Cal")
1865 (const_int 16) (const_int 16))
1868 (set (match_operand:SI 0 "register_operand" "=w,w,w")
1871 (mult:DI (sign_extend:DI (match_dup 1))
1873 (sign_extract:DI (match_dup 2)
1874 (const_int 16) (const_int 16))
1877 (const_int 32) (const_int 32)))]
1878 "TARGET_MULMAC_32BY16_SET"
1879 "machlw%? %0, %1, %2"
1880 [(set_attr "length" "4,4,8")
1881 (set_attr "type" "mulmac_600")
1882 (set_attr "predicable" "no,no,yes")
1883 (set_attr "cond" "nocond, canuse_limm, canuse")])
1886 ;; DI <- DI(signed SI) * DI(signed SI)
1887 (define_insn_and_split "mulsidi3_700"
1888 [(set (match_operand:DI 0 "register_operand" "=&r")
1889 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%c"))
1890 (sign_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))]
1891 "TARGET_ARC700 && !TARGET_NOMPY_SET"
1893 "&& reload_completed"
1896 int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
1897 int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
1898 rtx l0 = simplify_gen_subreg (word_mode, operands[0], DImode, lo);
1899 rtx h0 = simplify_gen_subreg (word_mode, operands[0], DImode, hi);
1900 emit_insn (gen_mulsi3_highpart (h0, operands[1], operands[2]));
1901 emit_insn (gen_mulsi3_700 (l0, operands[1], operands[2]));
1904 [(set_attr "type" "multi")
1905 (set_attr "length" "8")])
1907 (define_insn "mulsi3_highpart"
1908 [(set (match_operand:SI 0 "register_operand" "=Rcr,r,Rcr,r")
1912 (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,c, 0,c"))
1913 (sign_extend:DI (match_operand:SI 2 "extend_operand" "c,c, i,i")))
1915 "TARGET_ARC700 && !TARGET_NOMPY_SET"
1917 [(set_attr "length" "4,4,8,8")
1918 (set_attr "type" "multi")
1919 (set_attr "predicable" "yes,no,yes,no")
1920 (set_attr "cond" "canuse,nocond,canuse,nocond")])
1922 ; Note that mpyhu has the same latency as mpy / mpyh,
1923 ; thus we use the type multi.
1924 (define_insn "*umulsi3_highpart_i"
1925 [(set (match_operand:SI 0 "register_operand" "=Rcr,r,Rcr,r")
1929 (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,c, 0,c"))
1930 (zero_extend:DI (match_operand:SI 2 "extend_operand" "c,c, i,i")))
1932 "TARGET_ARC700 && !TARGET_NOMPY_SET"
1934 [(set_attr "length" "4,4,8,8")
1935 (set_attr "type" "multi")
1936 (set_attr "predicable" "yes,no,yes,no")
1937 (set_attr "cond" "canuse,nocond,canuse,nocond")])
1939 ; Implementations include additional labels for umulsidi3, so we got all
1940 ; the same clobbers - plus one for the result low part. */
1941 (define_insn "umulsi3_highpart_600_lib_le"
1942 [(set (reg:SI R1_REG)
1945 (mult:DI (zero_extend:DI (reg:SI R0_REG))
1946 (zero_extend:DI (reg:SI R1_REG)))
1948 (clobber (reg:SI RETURN_ADDR_REGNUM))
1949 (clobber (reg:SI R0_REG))
1950 (clobber (reg:DI R2_REG))
1951 (clobber (reg:SI R12_REG))
1952 (clobber (reg:DI MUL64_OUT_REG))
1953 (clobber (reg:CC CC_REG))]
1955 && !TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET
1956 && (!TARGET_ARC700 || TARGET_NOMPY_SET)
1957 && SFUNC_CHECK_PREDICABLE"
1958 "*return arc_output_libcall (\"__umulsi3_highpart\");"
1959 [(set_attr "is_sfunc" "yes")
1960 (set_attr "predicable" "yes")])
1962 (define_insn "umulsi3_highpart_600_lib_be"
1963 [(set (reg:SI R0_REG)
1966 (mult:DI (zero_extend:DI (reg:SI R0_REG))
1967 (zero_extend:DI (reg:SI R1_REG)))
1969 (clobber (reg:SI RETURN_ADDR_REGNUM))
1970 (clobber (reg:SI R1_REG))
1971 (clobber (reg:DI R2_REG))
1972 (clobber (reg:SI R12_REG))
1973 (clobber (reg:DI MUL64_OUT_REG))
1974 (clobber (reg:CC CC_REG))]
1976 && !TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET
1977 && (!TARGET_ARC700 || TARGET_NOMPY_SET)
1978 && SFUNC_CHECK_PREDICABLE"
1979 "*return arc_output_libcall (\"__umulsi3_highpart\");"
1980 [(set_attr "is_sfunc" "yes")
1981 (set_attr "predicable" "yes")])
1983 ;; (zero_extend:DI (const_int)) leads to internal errors in combine, so we
1984 ;; need a separate pattern for immediates
1985 ;; ??? This is fine for combine, but not for reload.
1986 (define_insn "umulsi3_highpart_int"
1987 [(set (match_operand:SI 0 "register_operand" "=Rcr, r, r,Rcr, r")
1991 (zero_extend:DI (match_operand:SI 1 "register_operand" " 0, c, 0, 0, c"))
1992 (match_operand:DI 2 "immediate_usidi_operand" "L, L, I, Cal, Cal"))
1994 "TARGET_ARC700 && !TARGET_NOMPY_SET"
1996 [(set_attr "length" "4,4,4,8,8")
1997 (set_attr "type" "multi")
1998 (set_attr "predicable" "yes,no,no,yes,no")
1999 (set_attr "cond" "canuse,nocond,canuse_limm,canuse,nocond")])
2001 (define_expand "umulsi3_highpart"
2002 [(set (match_operand:SI 0 "general_operand" "")
2006 (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
2007 (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" "")))
2009 "TARGET_ARC700 || (!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET)"
2012 rtx target = operands[0];
2014 if (!TARGET_ARC700 || TARGET_NOMPY_SET)
2016 emit_move_insn (gen_rtx_REG (SImode, 0), operands[1]);
2017 emit_move_insn (gen_rtx_REG (SImode, 1), operands[2]);
2018 if (TARGET_BIG_ENDIAN)
2019 emit_insn (gen_umulsi3_highpart_600_lib_be ());
2021 emit_insn (gen_umulsi3_highpart_600_lib_le ());
2022 emit_move_insn (target, gen_rtx_REG (SImode, 0));
2026 if (!register_operand (target, SImode))
2027 target = gen_reg_rtx (SImode);
2029 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
2030 operands[2] = simplify_const_unary_operation (ZERO_EXTEND, DImode,
2031 operands[2], SImode);
2032 else if (!immediate_operand (operands[2], SImode))
2033 operands[2] = gen_rtx_ZERO_EXTEND (DImode, operands[2]);
2034 emit_insn (gen_umulsi3_highpart_int (target, operands[1], operands[2]));
2035 if (target != operands[0])
2036 emit_move_insn (operands[0], target);
2040 (define_expand "umulsidi3"
2041 [(set (match_operand:DI 0 "nonimmediate_operand" "")
2042 (mult:DI (zero_extend:DI(match_operand:SI 1 "register_operand" ""))
2043 (zero_extend:DI(match_operand:SI 2 "nonmemory_operand" ""))))]
2046 if (TARGET_ARC700 && !TARGET_NOMPY_SET)
2048 operands[2] = force_reg (SImode, operands[2]);
2049 if (!register_operand (operands[0], DImode))
2051 rtx result = gen_reg_rtx (DImode);
2053 emit_insn (gen_umulsidi3 (result, operands[1], operands[2]));
2054 emit_move_insn (operands[0], result);
2058 else if (TARGET_MUL64_SET)
2060 operands[2] = force_reg (SImode, operands[2]);
2061 emit_insn (gen_umulsidi_600 (operands[1], operands[2]));
2062 emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
2065 else if (TARGET_MULMAC_32BY16_SET)
2067 rtx result_hi = gen_reg_rtx (SImode);
2068 rtx result_low = gen_reg_rtx (SImode);
2070 result_hi = gen_highpart(SImode , operands[0]);
2071 result_low = gen_lowpart(SImode , operands[0]);
2073 emit_insn (gen_umul64_600 (operands[1], operands[2]));
2074 emit_insn (gen_umac64_600 (result_hi, operands[1], operands[2]));
2075 emit_move_insn (result_low, gen_acc2 ());
2080 emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
2081 emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
2082 emit_insn (gen_umulsidi3_600_lib ());
2083 emit_move_insn (operands[0], gen_rtx_REG (DImode, R0_REG));
2088 (define_insn "umul64_600"
2090 (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand"
2092 (zero_extract:DI (match_operand:SI 1 "nonmemory_operand"
2097 "TARGET_MULMAC_32BY16_SET"
2101 [(set_attr "length" "4,4,8")
2102 (set_attr "type" "mulmac_600")
2103 (set_attr "predicable" "no,no,yes")
2104 (set_attr "cond" "nocond, canuse_limm, canuse")])
2107 (define_insn "umac64_600"
2110 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "c,c,c"))
2112 (zero_extract:DI (match_operand:SI 2 "nonmemory_operand" "c,L,Cal")
2113 (const_int 16) (const_int 16))
2116 (set (match_operand:SI 0 "register_operand" "=w,w,w")
2119 (mult:DI (zero_extend:DI (match_dup 1))
2121 (zero_extract:DI (match_dup 2)
2122 (const_int 16) (const_int 16))
2125 (const_int 32) (const_int 32)))]
2126 "TARGET_MULMAC_32BY16_SET"
2127 "machulw%? %0, %1, %2"
2128 [(set_attr "length" "4,4,8")
2129 (set_attr "type" "mulmac_600")
2130 (set_attr "predicable" "no,no,yes")
2131 (set_attr "cond" "nocond, canuse_limm, canuse")])
2135 ;; DI <- DI(unsigned SI) * DI(unsigned SI)
2136 (define_insn_and_split "umulsidi3_700"
2137 [(set (match_operand:DI 0 "dest_reg_operand" "=&r")
2138 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%c"))
2139 (zero_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))]
2140 "TARGET_ARC700 && !TARGET_NOMPY_SET"
2145 int hi = !TARGET_BIG_ENDIAN;
2147 rtx l0 = operand_subword (operands[0], lo, 0, DImode);
2148 rtx h0 = operand_subword (operands[0], hi, 0, DImode);
2149 emit_insn (gen_umulsi3_highpart (h0, operands[1], operands[2]));
2150 emit_insn (gen_mulsi3_700 (l0, operands[1], operands[2]));
2153 [(set_attr "type" "umulti")
2154 (set_attr "length" "8")])
2156 (define_insn "umulsidi3_600_lib"
2157 [(set (reg:DI R0_REG)
2158 (mult:DI (zero_extend:DI (reg:SI R0_REG))
2159 (zero_extend:DI (reg:SI R1_REG))))
2160 (clobber (reg:SI RETURN_ADDR_REGNUM))
2161 (clobber (reg:DI R2_REG))
2162 (clobber (reg:SI R12_REG))
2163 (clobber (reg:DI MUL64_OUT_REG))
2164 (clobber (reg:CC CC_REG))]
2165 "!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET
2166 && (!TARGET_ARC700 || TARGET_NOMPY_SET)
2167 && SFUNC_CHECK_PREDICABLE"
2168 "*return arc_output_libcall (\"__umulsidi3\");"
2169 [(set_attr "is_sfunc" "yes")
2170 (set_attr "predicable" "yes")])
2174 [(set (reg:DI R0_REG)
2175 (mult:DI (zero_extend:DI (reg:SI R0_REG))
2176 (zero_extend:DI (reg:SI R1_REG))))
2177 (clobber (reg:SI RETURN_ADDR_REGNUM))
2178 (clobber (reg:DI R2_REG))
2179 (clobber (reg:SI R12_REG))
2180 (clobber (reg:DI MUL64_OUT_REG))
2181 (clobber (reg:CC CC_REG))])]
2182 "!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET
2183 && (!TARGET_ARC700 || TARGET_NOMPY_SET)
2184 && peep2_regno_dead_p (1, TARGET_BIG_ENDIAN ? R1_REG : R0_REG)"
2187 if (TARGET_BIG_ENDIAN)
2188 emit_insn (gen_umulsi3_highpart_600_lib_be ());
2190 emit_insn (gen_umulsi3_highpart_600_lib_le ());
2194 (define_expand "addsi3"
2195 [(set (match_operand:SI 0 "dest_reg_operand" "")
2196 (plus:SI (match_operand:SI 1 "register_operand" "")
2197 (match_operand:SI 2 "nonmemory_operand" "")))]
2199 "if (flag_pic && arc_raw_symbolic_reference_mentioned_p (operands[2], false))
2201 operands[2]=force_reg(SImode, operands[2]);
2203 else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[2], Pmode))
2205 operands[2] = force_reg (SImode, arc_rewrite_small_data (operands[2]));
2210 (define_expand "adddi3"
2211 [(parallel [(set (match_operand:DI 0 "dest_reg_operand" "")
2212 (plus:DI (match_operand:DI 1 "register_operand" "")
2213 (match_operand:DI 2 "nonmemory_operand" "")))
2214 (clobber (reg:CC CC_REG))])]
2217 if (TARGET_EXPAND_ADDDI)
2219 rtx l0 = gen_lowpart (SImode, operands[0]);
2220 rtx h0 = disi_highpart (operands[0]);
2221 rtx l1 = gen_lowpart (SImode, operands[1]);
2222 rtx h1 = disi_highpart (operands[1]);
2223 rtx l2 = gen_lowpart (SImode, operands[2]);
2224 rtx h2 = disi_highpart (operands[2]);
2225 rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
2227 if (CONST_INT_P (h2) && INTVAL (h2) < 0 && SIGNED_INT12 (INTVAL (h2)))
2229 emit_insn (gen_sub_f (l0, l1, gen_int_mode (-INTVAL (l2), SImode)));
2230 emit_insn (gen_sbc (h0, h1,
2231 gen_int_mode (-INTVAL (h2) - (l1 != 0), SImode),
2235 emit_insn (gen_add_f (l0, l1, l2));
2236 emit_insn (gen_adc (h0, h1, h2));
2241 ; This assumes that there can be no strictly partial overlap between
2242 ; operands[1] and operands[2].
2243 (define_insn_and_split "*adddi3_i"
2244 [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w,w")
2245 (plus:DI (match_operand:DI 1 "register_operand" "%c,0,c")
2246 (match_operand:DI 2 "nonmemory_operand" "ci,ci,!i")))
2247 (clobber (reg:CC CC_REG))]
2253 int hi = !TARGET_BIG_ENDIAN;
2255 rtx l0 = operand_subword (operands[0], lo, 0, DImode);
2256 rtx h0 = operand_subword (operands[0], hi, 0, DImode);
2257 rtx l1 = operand_subword (operands[1], lo, 0, DImode);
2258 rtx h1 = operand_subword (operands[1], hi, 0, DImode);
2259 rtx l2 = operand_subword (operands[2], lo, 0, DImode);
2260 rtx h2 = operand_subword (operands[2], hi, 0, DImode);
2263 if (l2 == const0_rtx)
2265 if (!rtx_equal_p (l0, l1) && !rtx_equal_p (l0, h1))
2266 emit_move_insn (l0, l1);
2267 emit_insn (gen_addsi3 (h0, h1, h2));
2268 if (!rtx_equal_p (l0, l1) && rtx_equal_p (l0, h1))
2269 emit_move_insn (l0, l1);
2272 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0
2273 && INTVAL (operands[2]) >= -0x7fffffff)
2275 emit_insn (gen_subdi3_i (operands[0], operands[1],
2276 GEN_INT (-INTVAL (operands[2]))));
2279 if (rtx_equal_p (l0, h1))
2281 if (h2 != const0_rtx)
2282 emit_insn (gen_addsi3 (h0, h1, h2));
2283 else if (!rtx_equal_p (h0, h1))
2284 emit_move_insn (h0, h1);
2285 emit_insn (gen_add_f (l0, l1, l2));
2289 gen_rtx_LTU (VOIDmode, gen_rtx_REG (CC_Cmode, CC_REG), GEN_INT (0)),
2290 gen_rtx_SET (VOIDmode, h0, plus_constant (SImode, h0, 1))));
2293 emit_insn (gen_add_f (l0, l1, l2));
2294 emit_insn (gen_adc (h0, h1, h2));
2297 [(set_attr "cond" "clob")
2298 (set_attr "type" "binary")
2299 (set_attr "length" "16,16,20")])
2301 (define_insn "add_f"
2302 [(set (reg:CC_C CC_REG)
2304 (plus:SI (match_operand:SI 1 "register_operand" "c,0,c")
2305 (match_operand:SI 2 "nonmemory_operand" "cL,I,cCal"))
2307 (set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w")
2308 (plus:SI (match_dup 1) (match_dup 2)))]
2311 [(set_attr "cond" "set")
2312 (set_attr "type" "compare")
2313 (set_attr "length" "4,4,8")])
2315 (define_insn "*add_f_2"
2316 [(set (reg:CC_C CC_REG)
2318 (plus:SI (match_operand:SI 1 "register_operand" "c,0,c")
2319 (match_operand:SI 2 "nonmemory_operand" "cL,I,cCal"))
2321 (set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w")
2322 (plus:SI (match_dup 1) (match_dup 2)))]
2325 [(set_attr "cond" "set")
2326 (set_attr "type" "compare")
2327 (set_attr "length" "4,4,8")])
2329 ; w/c/c comes first (rather than w/0/C_0) to prevent the middle-end
2330 ; needlessly prioritizing the matching constraint.
2331 ; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional
2332 ; execution is used where possible.
2333 (define_insn_and_split "adc"
2334 [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w")
2335 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
2336 (match_operand:SI 1 "nonmemory_operand"
2338 (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))]
2339 "register_operand (operands[1], SImode)
2340 || register_operand (operands[2], SImode)"
2347 ; if we have a bad schedule after sched2, split.
2349 && !optimize_size && TARGET_ARC700
2350 && arc_scheduling_not_expected ()
2351 && arc_sets_cc_p (prev_nonnote_insn (insn))
2352 /* If next comes a return or other insn that needs a delay slot,
2353 expect the adc to get into the delay slot. */
2354 && next_nonnote_insn (insn)
2355 && !arc_need_delay (next_nonnote_insn (insn))
2356 /* Restore operands before emitting. */
2357 && (extract_insn_cached (insn), 1)"
2358 [(set (match_dup 0) (match_dup 3))
2360 (ltu (reg:CC_C CC_REG) (const_int 0))
2361 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))))]
2362 "operands[3] = simplify_gen_binary (PLUS, SImode, operands[1], operands[2]);"
2363 [(set_attr "cond" "use")
2364 (set_attr "type" "cc_arith")
2365 (set_attr "length" "4,4,4,4,8")])
2367 ; combiner-splitter cmp / scc -> cmp / adc
2369 [(set (match_operand:SI 0 "dest_reg_operand" "")
2370 (gtu:SI (match_operand:SI 1 "register_operand" "")
2371 (match_operand:SI 2 "register_operand" "")))
2372 (clobber (reg CC_REG))]
2374 [(set (reg:CC_C CC_REG) (compare:CC_C (match_dup 2) (match_dup 1)))
2375 (set (match_dup 0) (ltu:SI (reg:CC_C CC_REG) (const_int 0)))])
2377 ; combine won't work when an intermediate result is used later...
2378 ; add %0,%1,%2 ` cmp %0,%[12] -> add.f %0,%1,%2
2380 [(set (match_operand:SI 0 "dest_reg_operand" "")
2381 (plus:SI (match_operand:SI 1 "register_operand" "")
2382 (match_operand:SI 2 "nonmemory_operand" "")))
2383 (set (reg:CC_C CC_REG)
2384 (compare:CC_C (match_dup 0)
2385 (match_operand:SI 3 "nonmemory_operand" "")))]
2386 "rtx_equal_p (operands[1], operands[3])
2387 || rtx_equal_p (operands[2], operands[3])"
2389 [(set (reg:CC_C CC_REG)
2390 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))
2392 (plus:SI (match_dup 1) (match_dup 2)))])])
2394 ; ??? need to delve into combine to find out why this is not useful.
2395 ; We'd like to be able to grok various C idioms for carry bit usage.
2396 ;(define_insn "*adc_0"
2397 ; [(set (match_operand:SI 0 "dest_reg_operand" "=w")
2398 ; (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
2399 ; (match_operand:SI 1 "register_operand" "c")))]
2402 ; [(set_attr "cond" "use")
2403 ; (set_attr "type" "cc_arith")
2404 ; (set_attr "length" "4")])
2407 ; [(set (match_operand:SI 0 "dest_reg_operand" "=w")
2408 ; (plus:SI (gtu:SI (match_operand:SI 1 "register_operand" "c")
2409 ; (match_operand:SI 2 "register_operand" "c"))
2410 ; (match_operand:SI 3 "register_operand" "c")))
2411 ; (clobber (reg CC_REG))]
2413 ; [(set (reg:CC_C CC_REG) (compare:CC_C (match_dup 2) (match_dup 1)))
2414 ; (set (match_dup 0)
2415 ; (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
2418 (define_expand "subsi3"
2419 [(set (match_operand:SI 0 "dest_reg_operand" "")
2420 (minus:SI (match_operand:SI 1 "nonmemory_operand" "")
2421 (match_operand:SI 2 "nonmemory_operand" "")))]
2427 if (!register_operand (operands[2], SImode))
2429 operands[1] = force_reg (SImode, operands[1]);
2432 if (flag_pic && arc_raw_symbolic_reference_mentioned_p (operands[c], false))
2433 operands[c] = force_reg (SImode, operands[c]);
2434 else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[c], Pmode))
2435 operands[c] = force_reg (SImode, arc_rewrite_small_data (operands[c]));
2438 ; the casesi expander might generate a sub of zero, so we have to recognize it.
2439 ; combine should make such an insn go away.
2440 (define_insn_and_split "subsi3_insn"
2441 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,Rcw,w,w,w, w, w, w")
2442 (minus:SI (match_operand:SI 1 "nonmemory_operand" "0, 0, cL,c,L,I,Cal,Cal, c")
2443 (match_operand:SI 2 "nonmemory_operand" "Rcqq, c, 0,c,c,0, 0, c,Cal")))]
2444 "register_operand (operands[1], SImode)
2445 || register_operand (operands[2], SImode)"
2456 "reload_completed && get_attr_length (insn) == 8
2457 && satisfies_constraint_I (operands[1])
2458 && GET_CODE (PATTERN (insn)) != COND_EXEC"
2459 [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))]
2460 "split_subsi (operands);"
2461 [(set_attr "iscompact" "maybe,false,false,false,false,false,false,false, false")
2462 (set_attr "length" "*,4,4,4,4,4,8,8,8")
2463 (set_attr "predicable" "yes,yes,yes,no,no,no,yes,no,no")
2464 (set_attr "cond" "canuse,canuse,canuse,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
2466 (define_expand "subdi3"
2467 [(parallel [(set (match_operand:DI 0 "dest_reg_operand" "")
2468 (minus:DI (match_operand:DI 1 "nonmemory_operand" "")
2469 (match_operand:DI 2 "nonmemory_operand" "")))
2470 (clobber (reg:CC CC_REG))])]
2473 if (!register_operand (operands[2], DImode))
2474 operands[1] = force_reg (DImode, operands[1]);
2475 if (TARGET_EXPAND_ADDDI)
2477 rtx l0 = gen_lowpart (SImode, operands[0]);
2478 rtx h0 = disi_highpart (operands[0]);
2479 rtx l1 = gen_lowpart (SImode, operands[1]);
2480 rtx h1 = disi_highpart (operands[1]);
2481 rtx l2 = gen_lowpart (SImode, operands[2]);
2482 rtx h2 = disi_highpart (operands[2]);
2483 rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
2485 emit_insn (gen_sub_f (l0, l1, l2));
2486 emit_insn (gen_sbc (h0, h1, h2, cc_c));
2491 (define_insn_and_split "subdi3_i"
2492 [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w,w,w,w")
2493 (minus:DI (match_operand:DI 1 "nonmemory_operand" "ci,0,ci,c,!i")
2494 (match_operand:DI 2 "nonmemory_operand" "ci,ci,0,!i,c")))
2495 (clobber (reg:CC CC_REG))]
2496 "register_operand (operands[1], DImode)
2497 || register_operand (operands[2], DImode)"
2502 int hi = !TARGET_BIG_ENDIAN;
2504 rtx l0 = operand_subword (operands[0], lo, 0, DImode);
2505 rtx h0 = operand_subword (operands[0], hi, 0, DImode);
2506 rtx l1 = operand_subword (operands[1], lo, 0, DImode);
2507 rtx h1 = operand_subword (operands[1], hi, 0, DImode);
2508 rtx l2 = operand_subword (operands[2], lo, 0, DImode);
2509 rtx h2 = operand_subword (operands[2], hi, 0, DImode);
2511 if (rtx_equal_p (l0, h1) || rtx_equal_p (l0, h2))
2513 h1 = simplify_gen_binary (MINUS, SImode, h1, h2);
2514 if (!rtx_equal_p (h0, h1))
2515 emit_insn (gen_rtx_SET (VOIDmode, h0, h1));
2516 emit_insn (gen_sub_f (l0, l1, l2));
2520 gen_rtx_LTU (VOIDmode, gen_rtx_REG (CC_Cmode, CC_REG), GEN_INT (0)),
2521 gen_rtx_SET (VOIDmode, h0, plus_constant (SImode, h0, -1))));
2524 emit_insn (gen_sub_f (l0, l1, l2));
2525 emit_insn (gen_sbc (h0, h1, h2, gen_rtx_REG (CCmode, CC_REG)));
2528 [(set_attr "cond" "clob")
2529 (set_attr "length" "16,16,16,20,20")])
2531 (define_insn "*sbc_0"
2532 [(set (match_operand:SI 0 "dest_reg_operand" "=w")
2533 (minus:SI (match_operand:SI 1 "register_operand" "c")
2534 (ltu:SI (match_operand:CC_C 2 "cc_use_register")
2538 [(set_attr "cond" "use")
2539 (set_attr "type" "cc_arith")
2540 (set_attr "length" "4")])
2542 ; w/c/c comes first (rather than Rcw/0/C_0) to prevent the middle-end
2543 ; needlessly prioritizing the matching constraint.
2544 ; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional execution
2545 ; is used where possible.
2546 (define_insn_and_split "sbc"
2547 [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w")
2548 (minus:SI (minus:SI (match_operand:SI 1 "nonmemory_operand"
2550 (ltu:SI (match_operand:CC_C 3 "cc_use_register")
2552 (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))]
2553 "register_operand (operands[1], SImode)
2554 || register_operand (operands[2], SImode)"
2561 ; if we have a bad schedule after sched2, split.
2563 && !optimize_size && TARGET_ARC700
2564 && arc_scheduling_not_expected ()
2565 && arc_sets_cc_p (prev_nonnote_insn (insn))
2566 /* If next comes a return or other insn that needs a delay slot,
2567 expect the adc to get into the delay slot. */
2568 && next_nonnote_insn (insn)
2569 && !arc_need_delay (next_nonnote_insn (insn))
2570 /* Restore operands before emitting. */
2571 && (extract_insn_cached (insn), 1)"
2572 [(set (match_dup 0) (match_dup 4))
2574 (ltu (reg:CC_C CC_REG) (const_int 0))
2575 (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))))]
2576 "operands[4] = simplify_gen_binary (MINUS, SImode, operands[1], operands[2]);"
2577 [(set_attr "cond" "use")
2578 (set_attr "type" "cc_arith")
2579 (set_attr "length" "4,4,4,4,8")])
2581 (define_insn "sub_f"
2582 [(set (reg:CC CC_REG)
2583 (compare:CC (match_operand:SI 1 "nonmemory_operand" " c,L,0,I,c,Cal")
2584 (match_operand:SI 2 "nonmemory_operand" "cL,c,I,0,Cal,c")))
2585 (set (match_operand:SI 0 "dest_reg_operand" "=w,w,Rcw,Rcw,w,w")
2586 (minus:SI (match_dup 1) (match_dup 2)))]
2587 "register_operand (operands[1], SImode)
2588 || register_operand (operands[2], SImode)"
2596 [(set_attr "type" "compare")
2597 (set_attr "length" "4,4,4,4,8,8")])
2599 ; combine won't work when an intermediate result is used later...
2600 ; add %0,%1,%2 ` cmp %0,%[12] -> add.f %0,%1,%2
2602 [(set (reg:CC CC_REG)
2603 (compare:CC (match_operand:SI 1 "register_operand" "")
2604 (match_operand:SI 2 "nonmemory_operand" "")))
2605 (set (match_operand:SI 0 "dest_reg_operand" "")
2606 (minus:SI (match_dup 1) (match_dup 2)))]
2609 [(set (reg:CC CC_REG) (compare:CC (match_dup 1) (match_dup 2)))
2610 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])])
2613 [(set (reg:CC CC_REG)
2614 (compare:CC (match_operand:SI 1 "register_operand" "")
2615 (match_operand:SI 2 "nonmemory_operand" "")))
2616 (set (match_operand 3 "" "") (match_operand 4 "" ""))
2617 (set (match_operand:SI 0 "dest_reg_operand" "")
2618 (minus:SI (match_dup 1) (match_dup 2)))]
2619 "!reg_overlap_mentioned_p (operands[3], operands[1])
2620 && !reg_overlap_mentioned_p (operands[3], operands[2])
2621 && !reg_overlap_mentioned_p (operands[0], operands[4])
2622 && !reg_overlap_mentioned_p (operands[0], operands[3])"
2624 [(set (reg:CC CC_REG) (compare:CC (match_dup 1) (match_dup 2)))
2625 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
2626 (set (match_dup 3) (match_dup 4))])
2628 (define_insn "*add_n"
2629 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,W,W,w,w")
2630 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "Rcqq,c,c,c,c,c")
2631 (match_operand:SI 2 "_2_4_8_operand" ""))
2632 (match_operand:SI 3 "nonmemory_operand" "0,0,c,?Cal,?c,??Cal")))]
2634 "add%z2%? %0,%3,%1%&"
2635 [(set_attr "type" "shift")
2636 (set_attr "length" "*,4,4,8,4,8")
2637 (set_attr "predicable" "yes,yes,no,no,no,no")
2638 (set_attr "cond" "canuse,canuse,nocond,nocond,nocond,nocond")
2639 (set_attr "iscompact" "maybe,false,false,false,false,false")])
2641 ;; N.B. sub[123] has the operands of the MINUS in the opposite order from
2642 ;; what synth_mult likes.
2643 (define_insn "*sub_n"
2644 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2645 (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,c,?Cal")
2646 (mult:SI (match_operand:SI 2 "register_operand" "c,c,c")
2647 (match_operand:SI 3 "_2_4_8_operand" ""))))]
2650 [(set_attr "type" "shift")
2651 (set_attr "length" "4,4,8")
2652 (set_attr "predicable" "yes,no,no")
2653 (set_attr "cond" "canuse,nocond,nocond")
2654 (set_attr "iscompact" "false")])
2656 ; ??? check if combine matches this.
2657 (define_insn "*bset"
2658 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2659 (ior:SI (ashift:SI (const_int 1)
2660 (match_operand:SI 1 "nonmemory_operand" "cL,cL,c"))
2661 (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
2664 [(set_attr "length" "4,4,8")
2665 (set_attr "predicable" "yes,no,no")
2666 (set_attr "cond" "canuse,nocond,nocond")]
2669 ; ??? check if combine matches this.
2670 (define_insn "*bxor"
2671 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2672 (xor:SI (ashift:SI (const_int 1)
2673 (match_operand:SI 1 "nonmemory_operand" "cL,cL,c"))
2674 (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
2677 [(set_attr "length" "4,4,8")
2678 (set_attr "predicable" "yes,no,no")
2679 (set_attr "cond" "canuse,nocond,nocond")]
2682 ; ??? check if combine matches this.
2683 (define_insn "*bclr"
2684 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2685 (and:SI (not:SI (ashift:SI (const_int 1)
2686 (match_operand:SI 1 "nonmemory_operand" "cL,cL,c")))
2687 (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
2690 [(set_attr "length" "4,4,8")
2691 (set_attr "predicable" "yes,no,no")
2692 (set_attr "cond" "canuse,nocond,nocond")]
2695 ; ??? FIXME: find combine patterns for bmsk.
2697 ;;Following are the define_insns added for the purpose of peephole2's
2699 ; see also iorsi3 for use with constant bit number.
2700 (define_insn "*bset_insn"
2701 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2702 (ior:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
2703 (ashift:SI (const_int 1)
2704 (match_operand:SI 2 "nonmemory_operand" "cL,cL,c"))) ) ]
2707 bset%? %0,%1,%2 ;;peep2, constr 1
2708 bset %0,%1,%2 ;;peep2, constr 2
2709 bset %0,%S1,%2 ;;peep2, constr 3"
2710 [(set_attr "length" "4,4,8")
2711 (set_attr "predicable" "yes,no,no")
2712 (set_attr "cond" "canuse,nocond,nocond")]
2715 ; see also xorsi3 for use with constant bit number.
2716 (define_insn "*bxor_insn"
2717 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2718 (xor:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
2719 (ashift:SI (const_int 1)
2720 (match_operand:SI 2 "nonmemory_operand" "cL,cL,c"))) ) ]
2726 [(set_attr "length" "4,4,8")
2727 (set_attr "predicable" "yes,no,no")
2728 (set_attr "cond" "canuse,nocond,nocond")]
2731 ; see also andsi3 for use with constant bit number.
2732 (define_insn "*bclr_insn"
2733 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2734 (and:SI (not:SI (ashift:SI (const_int 1)
2735 (match_operand:SI 2 "nonmemory_operand" "cL,rL,r")))
2736 (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")))]
2742 [(set_attr "length" "4,4,8")
2743 (set_attr "predicable" "yes,no,no")
2744 (set_attr "cond" "canuse,nocond,nocond")]
2747 ; see also andsi3 for use with constant bit number.
2748 (define_insn "*bmsk_insn"
2749 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2750 (and:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
2751 (plus:SI (ashift:SI (const_int 1)
2752 (plus:SI (match_operand:SI 2 "nonmemory_operand" "rL,rL,r")
2760 [(set_attr "length" "4,4,8")
2761 (set_attr "predicable" "yes,no,no")
2762 (set_attr "cond" "canuse,nocond,nocond")]
2765 ;;Instructions added for peephole2s end
2767 ;; Boolean instructions.
2769 (define_expand "andsi3"
2770 [(set (match_operand:SI 0 "dest_reg_operand" "")
2771 (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
2772 (match_operand:SI 2 "nonmemory_operand" "")))]
2774 "if (!satisfies_constraint_Cux (operands[2]))
2775 operands[1] = force_reg (SImode, operands[1]);
2776 else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[1], Pmode))
2777 operands[1] = arc_rewrite_small_data (operands[1]);")
2779 (define_insn "andsi3_i"
2780 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw,Rcw,Rcw,Rcw,Rcw, w, w, w, w,w,Rcw, w, W")
2781 (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq, 0, 0,Rcqq, 0, c, 0, 0, 0, 0, c, c, c, c,0, 0, c, o")
2782 (match_operand:SI 2 "nonmemory_operand" " Rcqq, 0, C1p, Ccp, Cux, cL, 0,C1p,Ccp,CnL, I, Lc,C1p,Ccp,CnL,I,Cal,Cal,Cux")))]
2783 "(register_operand (operands[1], SImode)
2784 && nonmemory_operand (operands[2], SImode))
2785 || (memory_operand (operands[1], SImode)
2786 && satisfies_constraint_Cux (operands[2]))"
2789 switch (which_alternative)
2791 case 0: case 5: case 10: case 11: case 15: case 16: case 17:
2792 return \"and%? %0,%1,%2%&\";
2794 return \"and%? %0,%2,%1%&\";
2795 case 2: case 7: case 12:
2796 return \"bmsk%? %0,%1,%Z2%&\";
2797 case 3: case 8: case 13:
2798 return \"bclr%? %0,%1,%M2%&\";
2800 return (INTVAL (operands[2]) == 0xff
2801 ? \"extb%? %0,%1%&\" : \"extw%? %0,%1%&\");
2802 case 9: case 14: return \"bic%? %0,%1,%n2-1\";
2804 if (TARGET_BIG_ENDIAN)
2808 xop[0] = operands[0];
2809 xop[1] = adjust_address (operands[1], QImode,
2810 INTVAL (operands[2]) == 0xff ? 3 : 2);
2811 output_asm_insn (INTVAL (operands[2]) == 0xff
2812 ? \"ldb %0,%1\" : \"ldw %0,%1\",
2816 return INTVAL (operands[2]) == 0xff ? \"ldb %0,%1\" : \"ldw %0,%1\";
2821 [(set_attr "iscompact" "maybe,maybe,maybe,maybe,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false")
2822 (set_attr "type" "binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,load")
2823 (set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,4,4,4,4,8,8,*")
2824 (set_attr "predicable" "no,no,no,no,no,yes,yes,yes,yes,yes,no,no,no,no,no,no,yes,no,no")
2825 (set_attr "cond" "canuse,canuse,canuse,canuse,nocond,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
2827 ; combiner splitter, pattern found in ldtoa.c .
2828 ; and op3,op0,op1 / cmp op3,op2 -> add op3,op0,op4 / bmsk.f 0,op3,op1
2830 [(set (reg:CC_Z CC_REG)
2831 (compare:CC_Z (and:SI (match_operand:SI 0 "register_operand" "")
2832 (match_operand 1 "const_int_operand" ""))
2833 (match_operand 2 "const_int_operand" "")))
2834 (clobber (match_operand:SI 3 "register_operand" ""))]
2835 "((INTVAL (operands[1]) + 1) & INTVAL (operands[1])) == 0"
2837 (plus:SI (match_dup 0) (match_dup 4)))
2838 (set (reg:CC_Z CC_REG)
2839 (compare:CC_Z (and:SI (match_dup 3) (match_dup 1))
2841 "operands[4] = GEN_INT ( -(~INTVAL (operands[1]) | INTVAL (operands[2])));")
2843 ;;bic define_insn that allows limm to be the first operand
2844 (define_insn "*bicsi3_insn"
2845 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,Rcw,Rcw,w,w,w")
2846 (and:SI (not:SI (match_operand:SI 1 "nonmemory_operand" "Rcqq,Lc,I,Cal,Lc,Cal,c"))
2847 (match_operand:SI 2 "nonmemory_operand" "0,0,0,0,c,c,Cal")))]
2850 bic%? %0, %2, %1%& ;;constraint 0
2851 bic%? %0,%2,%1 ;;constraint 1
2852 bic %0,%2,%1 ;;constraint 2, FIXME: will it ever get generated ???
2853 bic%? %0,%2,%S1 ;;constraint 3, FIXME: will it ever get generated ???
2854 bic %0,%2,%1 ;;constraint 4
2855 bic %0,%2,%S1 ;;constraint 5, FIXME: will it ever get generated ???
2856 bic %0,%S2,%1 ;;constraint 6"
2857 [(set_attr "length" "*,4,4,8,4,8,8")
2858 (set_attr "iscompact" "maybe, false, false, false, false, false, false")
2859 (set_attr "predicable" "no,yes,no,yes,no,no,no")
2860 (set_attr "cond" "canuse,canuse,canuse_limm,canuse,nocond,nocond,nocond")])
2862 (define_insn "iorsi3"
2863 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcw,Rcw,Rcw,Rcw,w, w,w,Rcw, w")
2864 (ior:SI (match_operand:SI 1 "nonmemory_operand" "% 0,Rcq, 0, 0, c, 0, 0, c, c,0, 0, c")
2865 (match_operand:SI 2 "nonmemory_operand" "Rcqq, 0, C0p, cL, 0,C0p, I,cL,C0p,I,Cal,Cal")))]
2868 switch (which_alternative)
2870 case 0: case 3: case 6: case 7: case 9: case 10: case 11:
2871 return \"or%? %0,%1,%2%&\";
2873 return \"or%? %0,%2,%1%&\";
2874 case 2: case 5: case 8:
2875 return \"bset%? %0,%1,%z2%&\";
2879 [(set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false")
2880 (set_attr "length" "*,*,*,4,4,4,4,4,4,4,8,8")
2881 (set_attr "predicable" "no,no,no,yes,yes,yes,no,no,no,no,yes,no")
2882 (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,canuse,nocond")])
2884 (define_insn "xorsi3"
2885 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcw,Rcw,Rcw,Rcw, w, w,w, w, w")
2886 (xor:SI (match_operand:SI 1 "register_operand" "%0, Rcq, 0, c, 0, 0, c, c,0, 0, c")
2887 (match_operand:SI 2 "nonmemory_operand" " Rcqq, 0, cL, 0,C0p, I,cL,C0p,I,Cal,Cal")))]
2890 switch (which_alternative)
2892 case 0: case 2: case 5: case 6: case 8: case 9: case 10:
2893 return \"xor%? %0,%1,%2%&\";
2895 return \"xor%? %0,%2,%1%&\";
2897 return \"bxor%? %0,%1,%z2\";
2902 [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false,false,false,false")
2903 (set_attr "type" "binary")
2904 (set_attr "length" "*,*,4,4,4,4,4,4,4,8,8")
2905 (set_attr "predicable" "no,no,yes,yes,yes,no,no,no,no,yes,no")
2906 (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,canuse,nocond")])
2908 (define_insn "negsi2"
2909 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcqq,Rcw,w")
2910 (neg:SI (match_operand:SI 1 "register_operand" "0,Rcqq,0,c")))]
2913 [(set_attr "type" "unary")
2914 (set_attr "iscompact" "maybe,true,false,false")
2915 (set_attr "predicable" "no,no,yes,no")])
2917 (define_insn "one_cmplsi2"
2918 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w")
2919 (not:SI (match_operand:SI 1 "register_operand" "Rcqq,c")))]
2922 [(set_attr "type" "unary,unary")
2923 (set_attr "iscompact" "true,false")])
2925 (define_insn_and_split "one_cmpldi2"
2926 [(set (match_operand:DI 0 "dest_reg_operand" "=q,w")
2927 (not:DI (match_operand:DI 1 "register_operand" "q,c")))]
2930 "&& reload_completed"
2931 [(set (match_dup 2) (not:SI (match_dup 3)))
2932 (set (match_dup 4) (not:SI (match_dup 5)))]
2934 int swap = (true_regnum (operands[0]) == true_regnum (operands[1]) + 1);
2936 operands[2] = operand_subword (operands[0], 0+swap, 0, DImode);
2937 operands[3] = operand_subword (operands[1], 0+swap, 0, DImode);
2938 operands[4] = operand_subword (operands[0], 1-swap, 0, DImode);
2939 operands[5] = operand_subword (operands[1], 1-swap, 0, DImode);
2941 [(set_attr "type" "unary,unary")
2942 (set_attr "cond" "nocond,nocond")
2943 (set_attr "length" "4,8")])
2945 ;; Shift instructions.
2947 (define_expand "ashlsi3"
2948 [(set (match_operand:SI 0 "dest_reg_operand" "")
2949 (ashift:SI (match_operand:SI 1 "register_operand" "")
2950 (match_operand:SI 2 "nonmemory_operand" "")))]
2954 if (!TARGET_BARREL_SHIFTER)
2956 emit_shift (ASHIFT, operands[0], operands[1], operands[2]);
2961 (define_expand "ashrsi3"
2962 [(set (match_operand:SI 0 "dest_reg_operand" "")
2963 (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
2964 (match_operand:SI 2 "nonmemory_operand" "")))]
2968 if (!TARGET_BARREL_SHIFTER)
2970 emit_shift (ASHIFTRT, operands[0], operands[1], operands[2]);
2975 (define_expand "lshrsi3"
2976 [(set (match_operand:SI 0 "dest_reg_operand" "")
2977 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
2978 (match_operand:SI 2 "nonmemory_operand" "")))]
2982 if (!TARGET_BARREL_SHIFTER)
2984 emit_shift (LSHIFTRT, operands[0], operands[1], operands[2]);
2989 (define_insn "shift_si3"
2990 [(set (match_operand:SI 0 "dest_reg_operand" "=r")
2991 (match_operator:SI 3 "shift4_operator"
2992 [(match_operand:SI 1 "register_operand" "0")
2993 (match_operand:SI 2 "const_int_operand" "n")]))
2994 (clobber (match_scratch:SI 4 "=&r"))
2995 (clobber (reg:CC CC_REG))
2997 "!TARGET_BARREL_SHIFTER"
2998 "* return output_shift (operands);"
2999 [(set_attr "type" "shift")
3000 (set_attr "length" "16")])
3002 (define_insn "shift_si3_loop"
3003 [(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
3004 (match_operator:SI 3 "shift_operator"
3005 [(match_operand:SI 1 "register_operand" "0,0")
3006 (match_operand:SI 2 "nonmemory_operand" "rn,Cal")]))
3007 (clobber (match_scratch:SI 4 "=X,X"))
3008 (clobber (reg:SI LP_COUNT))
3009 (clobber (reg:SI LP_START))
3010 (clobber (reg:SI LP_END))
3011 (clobber (reg:CC CC_REG))
3013 "!TARGET_BARREL_SHIFTER"
3014 "* return output_shift (operands);"
3015 [(set_attr "type" "shift")
3016 (set_attr "length" "16,20")])
3018 ; asl, asr, lsr patterns:
3019 ; There is no point in including an 'I' alternative since only the lowest 5
3020 ; bits are used for the shift. OTOH Cal can be useful if the shift amount
3021 ; is defined in an external symbol, as we don't have special relocations
3022 ; to truncate a symbol in a u6 immediate; but that's rather exotic, so only
3023 ; provide one alternatice for this, without condexec support.
3024 (define_insn "*ashlsi3_insn"
3025 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w")
3026 (ashift:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCal")
3027 (match_operand:SI 2 "nonmemory_operand" "K, K,RcqqM, cL,cL,cCal")))]
3028 "TARGET_BARREL_SHIFTER
3029 && (register_operand (operands[1], SImode)
3030 || register_operand (operands[2], SImode))"
3032 [(set_attr "type" "shift")
3033 (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
3034 (set_attr "predicable" "no,no,no,yes,no,no")
3035 (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
3037 (define_insn "*ashrsi3_insn"
3038 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w")
3039 (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCal")
3040 (match_operand:SI 2 "nonmemory_operand" "K, K,RcqqM, cL,cL,cCal")))]
3041 "TARGET_BARREL_SHIFTER
3042 && (register_operand (operands[1], SImode)
3043 || register_operand (operands[2], SImode))"
3045 [(set_attr "type" "shift")
3046 (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
3047 (set_attr "predicable" "no,no,no,yes,no,no")
3048 (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
3050 (define_insn "*lshrsi3_insn"
3051 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w")
3052 (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCal")
3053 (match_operand:SI 2 "nonmemory_operand" "N, N,RcqqM, cL,cL,cCal")))]
3054 "TARGET_BARREL_SHIFTER
3055 && (register_operand (operands[1], SImode)
3056 || register_operand (operands[2], SImode))"
3057 "*return (which_alternative <= 1 && !arc_ccfsm_cond_exec_p ()
3058 ? \"lsr%? %0,%1%&\" : \"lsr%? %0,%1,%2%&\");"
3059 [(set_attr "type" "shift")
3060 (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
3061 (set_attr "predicable" "no,no,no,yes,no,no")
3062 (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
3064 (define_insn "rotrsi3"
3065 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w")
3066 (rotatert:SI (match_operand:SI 1 "register_operand" " 0,cL,cCal")
3067 (match_operand:SI 2 "nonmemory_operand" "cL,cL,cCal")))]
3068 "TARGET_BARREL_SHIFTER"
3070 [(set_attr "type" "shift,shift,shift")
3071 (set_attr "predicable" "yes,no,no")
3072 (set_attr "length" "4,4,8")])
3074 ;; Compare / branch instructions.
3076 (define_expand "cbranchsi4"
3077 [(set (reg:CC CC_REG)
3078 (compare:CC (match_operand:SI 1 "nonmemory_operand" "")
3079 (match_operand:SI 2 "nonmemory_operand" "")))
3082 (match_operator 0 "ordered_comparison_operator" [(reg CC_REG)
3084 (label_ref (match_operand 3 "" ""))
3088 gcc_assert (XEXP (operands[0], 0) == operands[1]);
3089 gcc_assert (XEXP (operands[0], 1) == operands[2]);
3090 operands[0] = gen_compare_reg (operands[0], VOIDmode);
3091 emit_jump_insn (gen_branch_insn (operands[3], operands[0]));
3095 ;; ??? Could add a peephole to generate compare with swapped operands and
3096 ;; modifed cc user if second, but not first operand is a compact register.
3097 (define_insn "cmpsi_cc_insn_mixed"
3098 [(set (reg:CC CC_REG)
3099 (compare:CC (match_operand:SI 0 "register_operand" "Rcq#q,c,c, qRcq, c")
3100 (match_operand:SI 1 "nonmemory_operand" "cO,cI,cL, Cal, Cal")))]
3103 [(set_attr "type" "compare")
3104 (set_attr "iscompact" "true,false,false,true_limm,false")
3105 (set_attr "predicable" "no,no,yes,no,yes")
3106 (set_attr "cond" "set")
3107 (set_attr "length" "*,4,4,*,8")])
3109 (define_insn "*cmpsi_cc_zn_insn"
3110 [(set (reg:CC_ZN CC_REG)
3111 (compare:CC_ZN (match_operand:SI 0 "register_operand" "qRcq,c")
3115 [(set_attr "type" "compare,compare")
3116 (set_attr "iscompact" "true,false")
3117 (set_attr "predicable" "no,yes")
3118 (set_attr "cond" "set_zn")
3119 (set_attr "length" "*,4")])
3121 ; combiner pattern observed for unwind-dw2-fde.c:linear_search_fdes.
3122 (define_insn "*btst"
3123 [(set (reg:CC_ZN CC_REG)
3125 (zero_extract:SI (match_operand:SI 0 "register_operand" "Rcqq,c")
3127 (match_operand:SI 1 "nonmemory_operand" "L,Lc"))
3131 [(set_attr "iscompact" "true,false")
3132 (set_attr "predicable" "no,yes")
3133 (set_attr "cond" "set")
3134 (set_attr "type" "compare")
3135 (set_attr "length" "*,4")])
3137 ; combine suffers from 'simplifications' that replace a one-bit zero
3138 ; extract with a shift if it can prove that the upper bits are zero.
3139 ; arc_reorg sees the code after sched2, which can have caused our
3140 ; inputs to be clobbered even if they were not clobbered before.
3141 ; Therefore, add a third way to convert btst / b{eq,ne} to bbit{0,1}
3142 ; OTOH, this is somewhat marginal, and can leat to out-of-range
3143 ; bbit (i.e. bad scheduling) and missed conditional execution,
3144 ; so make this an option.
3146 [(set (reg:CC_ZN CC_REG)
3148 (zero_extract:SI (match_operand:SI 0 "register_operand" "")
3150 (match_operand:SI 1 "nonmemory_operand" ""))
3153 (if_then_else (match_operator 3 "equality_comparison_operator"
3154 [(reg:CC_ZN CC_REG) (const_int 0)])
3155 (label_ref (match_operand 2 "" ""))
3157 "TARGET_BBIT_PEEPHOLE && peep2_regno_dead_p (2, CC_REG)"
3158 [(parallel [(set (pc)
3161 [(zero_extract:SI (match_dup 0)
3162 (const_int 1) (match_dup 1))
3164 (label_ref (match_dup 2))
3166 (clobber (reg:CC_ZN CC_REG))])])
3168 (define_insn "*cmpsi_cc_z_insn"
3169 [(set (reg:CC_Z CC_REG)
3170 (compare:CC_Z (match_operand:SI 0 "register_operand" "qRcq,c")
3171 (match_operand:SI 1 "p2_immediate_operand" "O,n")))]
3176 [(set_attr "type" "compare,compare")
3177 (set_attr "iscompact" "true,false")
3178 (set_attr "cond" "set,set_zn")
3179 (set_attr "length" "*,4")])
3181 (define_insn "*cmpsi_cc_c_insn"
3182 [(set (reg:CC_C CC_REG)
3183 (compare:CC_C (match_operand:SI 0 "register_operand" "Rcqq, c,Rcqq, c")
3184 (match_operand:SI 1 "nonmemory_operand" "cO, cI, Cal,Cal")))]
3187 [(set_attr "type" "compare")
3188 (set_attr "iscompact" "true,false,true_limm,false")
3189 (set_attr "cond" "set")
3190 (set_attr "length" "*,4,*,8")])
3192 ;; Next come the scc insns.
3194 (define_expand "cstoresi4"
3195 [(set (reg:CC CC_REG)
3196 (compare:CC (match_operand:SI 2 "nonmemory_operand" "")
3197 (match_operand:SI 3 "nonmemory_operand" "")))
3198 (set (match_operand:SI 0 "dest_reg_operand" "")
3199 (match_operator:SI 1 "ordered_comparison_operator" [(reg CC_REG)
3203 gcc_assert (XEXP (operands[1], 0) == operands[2]);
3204 gcc_assert (XEXP (operands[1], 1) == operands[3]);
3205 operands[1] = gen_compare_reg (operands[1], SImode);
3206 emit_insn (gen_scc_insn (operands[0], operands[1]));
3210 (define_mode_iterator SDF [SF DF])
3212 (define_expand "cstore<mode>4"
3213 [(set (reg:CC CC_REG)
3214 (compare:CC (match_operand:SDF 2 "register_operand" "")
3215 (match_operand:SDF 3 "register_operand" "")))
3216 (set (match_operand:SI 0 "dest_reg_operand" "")
3217 (match_operator:SI 1 "comparison_operator" [(reg CC_REG)
3222 gcc_assert (XEXP (operands[1], 0) == operands[2]);
3223 gcc_assert (XEXP (operands[1], 1) == operands[3]);
3224 operands[1] = gen_compare_reg (operands[1], SImode);
3225 emit_insn (gen_scc_insn (operands[0], operands[1]));
3229 ; We need a separate expander for this lest we loose the mode of CC_REG
3230 ; when match_operator substitutes the literal operand into the comparison.
3231 (define_expand "scc_insn"
3232 [(set (match_operand:SI 0 "dest_reg_operand" "=w") (match_operand:SI 1 ""))])
3234 (define_insn_and_split "*scc_insn"
3235 [(set (match_operand:SI 0 "dest_reg_operand" "=w")
3236 (match_operator:SI 1 "proper_comparison_operator" [(reg CC_REG) (const_int 0)]))]
3240 [(set (match_dup 0) (const_int 1))
3243 (set (match_dup 0) (const_int 0)))]
3246 = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[1]),
3247 GET_MODE (XEXP (operands[1], 0))),
3249 XEXP (operands[1], 0), XEXP (operands[1], 1));
3251 [(set_attr "type" "unary")])
3253 ;; ??? At least for ARC600, we should use sbc b,b,s12 if we want a value
3254 ;; that is one lower if the carry flag is set.
3256 ;; ??? Look up negscc insn. See pa.md for example.
3257 (define_insn "*neg_scc_insn"
3258 [(set (match_operand:SI 0 "dest_reg_operand" "=w")
3259 (neg:SI (match_operator:SI 1 "proper_comparison_operator"
3260 [(reg CC_REG) (const_int 0)])))]
3262 "mov %0,-1\;sub.%D1 %0,%0,%0"
3263 [(set_attr "type" "unary")
3264 (set_attr "length" "8")])
3266 (define_insn "*not_scc_insn"
3267 [(set (match_operand:SI 0 "dest_reg_operand" "=w")
3268 (not:SI (match_operator:SI 1 "proper_comparison_operator"
3269 [(reg CC_REG) (const_int 0)])))]
3271 "mov %0,1\;sub.%d1 %0,%0,%0"
3272 [(set_attr "type" "unary")
3273 (set_attr "length" "8")])
3275 ; cond_exec patterns
3276 (define_insn "*movsi_ne"
3278 (ne (match_operand:CC_Z 2 "cc_use_register" "Rcc,Rcc,Rcc") (const_int 0))
3279 (set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,w,w")
3280 (match_operand:SI 1 "nonmemory_operand" "C_0,Lc,?Cal")))]
3283 * current_insn_predicate = 0; return \"sub%?.ne %0,%0,%0%&\";
3286 [(set_attr "type" "cmove,cmove,cmove")
3287 (set_attr "iscompact" "true,false,false")
3288 (set_attr "length" "2,4,8")])
3290 (define_insn "*movsi_cond_exec"
3292 (match_operator 3 "proper_comparison_operator"
3293 [(match_operand 2 "cc_register" "Rcc,Rcc") (const_int 0)])
3294 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
3295 (match_operand:SI 1 "nonmemory_operand" "Lc,?Cal")))]
3298 [(set_attr "type" "cmove")
3299 (set_attr "length" "4,8")])
3301 (define_insn "*commutative_cond_exec"
3303 (match_operator 5 "proper_comparison_operator"
3304 [(match_operand 4 "cc_register" "Rcc,Rcc") (const_int 0)])
3305 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
3306 (match_operator:SI 3 "commutative_operator"
3307 [(match_operand:SI 1 "register_operand" "%0,0")
3308 (match_operand:SI 2 "nonmemory_operand" "cL,?Cal")])))]
3311 arc_output_commutative_cond_exec (operands, true);
3314 [(set_attr "cond" "use")
3315 (set_attr "type" "cmove")
3316 (set_attr_alternative "length"
3319 [(eq (symbol_ref "arc_output_commutative_cond_exec (operands, false)")
3324 (define_insn "*sub_cond_exec"
3326 (match_operator 4 "proper_comparison_operator"
3327 [(match_operand 3 "cc_register" "Rcc,Rcc,Rcc") (const_int 0)])
3328 (set (match_operand:SI 0 "dest_reg_operand" "=w,w,w")
3329 (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,cL,Cal")
3330 (match_operand:SI 2 "nonmemory_operand" "cL,0,0"))))]
3336 [(set_attr "cond" "use")
3337 (set_attr "type" "cmove")
3338 (set_attr "length" "4,4,8")])
3340 (define_insn "*noncommutative_cond_exec"
3342 (match_operator 5 "proper_comparison_operator"
3343 [(match_operand 4 "cc_register" "Rcc,Rcc") (const_int 0)])
3344 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
3345 (match_operator:SI 3 "noncommutative_operator"
3346 [(match_operand:SI 1 "register_operand" "0,0")
3347 (match_operand:SI 2 "nonmemory_operand" "cL,Cal")])))]
3350 [(set_attr "cond" "use")
3351 (set_attr "type" "cmove")
3352 (set_attr "length" "4,8")])
3354 ;; These control RTL generation for conditional jump insns
3355 ;; Match both normal and inverted jump.
3357 ; We need a separate expander for this lest we loose the mode of CC_REG
3358 ; when match_operator substitutes the literal operand into the comparison.
3359 (define_expand "branch_insn"
3361 (if_then_else (match_operand 1 "" "")
3362 (label_ref (match_operand 0 "" ""))
3365 ; When estimating sizes during arc_reorg, when optimizing for speed, there
3366 ; are three reasons why we need to consider branches to be length 6:
3367 ; - annull-false delay slot insns are implemented using conditional execution,
3368 ; thus preventing short insn formation where used.
3369 ; - for ARC600: annull-true delay slot isnns are implemented where possile
3370 ; using conditional execution, preventing short insn formation where used.
3371 ; - for ARC700: likely or somewhat likely taken branches are made long and
3372 ; unaligned if possible to avoid branch penalty.
3373 (define_insn "*branch_insn"
3375 (if_then_else (match_operator 1 "proper_comparison_operator"
3376 [(reg CC_REG) (const_int 0)])
3377 (label_ref (match_operand 0 "" ""))
3382 if (arc_ccfsm_branch_deleted_p ())
3384 arc_ccfsm_record_branch_deleted ();
3385 return \"; branch deleted, next insns conditionalized\";
3389 arc_ccfsm_record_condition (operands[1], false, insn, 0);
3390 if (get_attr_length (insn) == 2)
3391 return \"b%d1%? %^%l0%&\";
3393 return \"b%d1%# %^%l0\";
3396 [(set_attr "type" "branch")
3400 (eq_attr "delay_slot_filled" "yes")
3405 (match_operand 1 "equality_comparison_operator" "")
3406 (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
3407 (gt (minus (match_dup 0) (pc))
3408 (minus (const_int 506)
3409 (symbol_ref "get_attr_delay_slot_length (insn)"))))
3410 (ior (match_test "!arc_short_comparison_p (operands[1], -64)")
3411 (lt (minus (match_dup 0) (pc)) (const_int -64))
3412 (gt (minus (match_dup 0) (pc))
3413 (minus (const_int 58)
3414 (symbol_ref "get_attr_delay_slot_length (insn)")))))
3419 (set (attr "iscompact")
3420 (cond [(match_test "get_attr_length (insn) == 2") (const_string "true")]
3421 (const_string "false")))])
3423 (define_insn "*rev_branch_insn"
3425 (if_then_else (match_operator 1 "proper_comparison_operator"
3426 [(reg CC_REG) (const_int 0)])
3428 (label_ref (match_operand 0 "" ""))))]
3429 "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
3432 if (arc_ccfsm_branch_deleted_p ())
3434 arc_ccfsm_record_branch_deleted ();
3435 return \"; branch deleted, next insns conditionalized\";
3439 arc_ccfsm_record_condition (operands[1], true, insn, 0);
3440 if (get_attr_length (insn) == 2)
3441 return \"b%D1%? %^%l0\";
3443 return \"b%D1%# %^%l0\";
3446 [(set_attr "type" "branch")
3450 (eq_attr "delay_slot_filled" "yes")
3455 (match_operand 1 "equality_comparison_operator" "")
3456 (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
3457 (gt (minus (match_dup 0) (pc))
3458 (minus (const_int 506)
3459 (symbol_ref "get_attr_delay_slot_length (insn)"))))
3460 (ior (match_test "!arc_short_comparison_p (operands[1], -64)")
3461 (lt (minus (match_dup 0) (pc)) (const_int -64))
3462 (gt (minus (match_dup 0) (pc))
3463 (minus (const_int 58)
3464 (symbol_ref "get_attr_delay_slot_length (insn)")))))
3469 (set (attr "iscompact")
3470 (cond [(match_test "get_attr_length (insn) == 2") (const_string "true")]
3471 (const_string "false")))])
3473 ;; Unconditional and other jump instructions.
3475 (define_expand "jump"
3476 [(set (pc) (label_ref (match_operand 0 "" "")))]
3480 (define_insn "jump_i"
3481 [(set (pc) (label_ref (match_operand 0 "" "")))]
3482 "!TARGET_LONG_CALLS_SET || !CROSSING_JUMP_P (insn)"
3484 [(set_attr "type" "uncond_branch")
3485 (set (attr "iscompact")
3486 (if_then_else (match_test "get_attr_length (insn) == 2")
3487 (const_string "true") (const_string "false")))
3488 (set_attr "cond" "canuse")
3489 (set (attr "length")
3491 ; In arc_reorg we just guesstimate; might be more or less than 4.
3492 (match_test "arc_branch_size_unknown_p ()")
3495 (eq_attr "delay_slot_filled" "yes")
3498 (match_test "CROSSING_JUMP_P (insn)")
3501 (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
3502 (gt (minus (match_dup 0) (pc))
3503 (minus (const_int 506)
3504 (symbol_ref "get_attr_delay_slot_length (insn)"))))
3508 (define_insn "indirect_jump"
3509 [(set (pc) (match_operand:SI 0 "nonmemory_operand" "L,I,Cal,Rcqq,r"))]
3512 [(set_attr "type" "jump")
3513 (set_attr "iscompact" "false,false,false,maybe,false")
3514 (set_attr "cond" "canuse,canuse_limm,canuse,canuse,canuse")])
3516 ;; Implement a switch statement.
3518 (define_expand "casesi"
3520 (minus:SI (match_operand:SI 0 "register_operand" "")
3521 (match_operand:SI 1 "nonmemory_operand" "")))
3522 (set (reg:CC CC_REG)
3523 (compare:CC (match_dup 5)
3524 (match_operand:SI 2 "nonmemory_operand" "")))
3526 (if_then_else (gtu (reg:CC CC_REG)
3528 (label_ref (match_operand 4 "" ""))
3531 (unspec:SI [(match_operand 3 "" "")
3532 (match_dup 5) (match_dup 7)] UNSPEC_CASESI))
3533 (parallel [(set (pc) (match_dup 6)) (use (match_dup 7))])]
3539 operands[5] = gen_reg_rtx (SImode);
3540 operands[6] = gen_reg_rtx (SImode);
3541 operands[7] = operands[3];
3542 emit_insn (gen_subsi3 (operands[5], operands[0], operands[1]));
3543 emit_insn (gen_cmpsi_cc_insn_mixed (operands[5], operands[2]));
3544 x = gen_rtx_GTU (VOIDmode, gen_rtx_REG (CCmode, CC_REG), const0_rtx);
3545 x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
3546 gen_rtx_LABEL_REF (VOIDmode, operands[4]), pc_rtx);
3547 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
3548 if (TARGET_COMPACT_CASESI)
3550 emit_jump_insn (gen_casesi_compact_jump (operands[5], operands[7]));
3554 operands[3] = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
3555 if (flag_pic || !cse_not_expected)
3556 operands[3] = force_reg (Pmode, operands[3]);
3557 emit_insn (gen_casesi_load (operands[6],
3558 operands[3], operands[5], operands[7]));
3559 if (CASE_VECTOR_PC_RELATIVE || flag_pic)
3560 emit_insn (gen_addsi3 (operands[6], operands[6], operands[3]));
3561 emit_jump_insn (gen_casesi_jump (operands[6], operands[7]));
3566 (define_insn "casesi_load"
3567 [(set (match_operand:SI 0 "register_operand" "=Rcq,r,r")
3568 (unspec:SI [(match_operand:SI 1 "nonmemory_operand" "Rcq,c,Cal")
3569 (match_operand:SI 2 "register_operand" "Rcq,c,c")
3570 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))]
3574 rtx diff_vec = PATTERN (next_nonnote_insn (operands[3]));
3576 if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
3578 gcc_assert (GET_CODE (diff_vec) == ADDR_VEC);
3579 gcc_assert (GET_MODE (diff_vec) == SImode);
3580 gcc_assert (!CASE_VECTOR_PC_RELATIVE && !flag_pic);
3583 switch (GET_MODE (diff_vec))
3586 return \"ld.as %0,[%1,%2]%&\";
3588 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
3589 return \"ldw.as %0,[%1,%2]\";
3590 return \"ldw.x.as %0,[%1,%2]\";
3592 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
3593 return \"ldb%? %0,[%1,%2]%&\";
3594 return \"ldb.x %0,[%1,%2]\";
3599 [(set_attr "type" "load")
3600 (set_attr_alternative "iscompact"
3602 [(ne (symbol_ref "GET_MODE (PATTERN (next_nonnote_insn (operands[3])))")
3603 (symbol_ref "QImode"))
3604 (const_string "false")
3605 (match_test "!ADDR_DIFF_VEC_FLAGS (PATTERN (next_nonnote_insn (operands[3]))).offset_unsigned")
3606 (const_string "false")]
3607 (const_string "true"))
3608 (const_string "false")
3609 (const_string "false")])
3610 (set_attr_alternative "length"
3612 [(eq_attr "iscompact" "false") (const_int 4)
3613 ; We have to mention (match_dup 3) to convince genattrtab.c that this
3614 ; is a varying length insn.
3615 (eq (symbol_ref "1+1") (const_int 2)) (const_int 2)
3616 (gt (minus (match_dup 3) (pc)) (const_int 42)) (const_int 4)]
3621 ; Unlike the canonical tablejump, this pattern always uses a jump address,
3622 ; even for CASE_VECTOR_PC_RELATIVE.
3623 (define_insn "casesi_jump"
3624 [(set (pc) (match_operand:SI 0 "register_operand" "Cal,Rcqq,c"))
3625 (use (label_ref (match_operand 1 "" "")))]
3628 [(set_attr "type" "jump")
3629 (set_attr "iscompact" "false,maybe,false")
3630 (set_attr "cond" "canuse")])
3632 (define_insn "casesi_compact_jump"
3634 (unspec:SI [(match_operand:SI 0 "register_operand" "c,q")]
3636 (use (label_ref (match_operand 1 "" "")))
3637 (clobber (match_scratch:SI 2 "=q,0"))]
3638 "TARGET_COMPACT_CASESI"
3641 rtx diff_vec = PATTERN (next_nonnote_insn (operands[1]));
3642 int unalign = arc_get_unalign ();
3646 xop[0] = operands[0];
3647 xop[2] = operands[2];
3648 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
3650 switch (GET_MODE (diff_vec))
3653 /* Max length can be 12 in this case, but this is OK because
3654 2 of these are for alignment, and are anticipated in the length
3655 of the ADDR_DIFF_VEC. */
3656 if (unalign && !satisfies_constraint_Rcq (xop[0]))
3657 s = \"add2 %2,pcl,%0\n\tld_s%2,[%2,12]\";
3659 s = \"add_s %2,%0,2\n\tld.as %2,[pcl,%2]\";
3661 s = \"add %2,%0,2\n\tld.as %2,[pcl,%2]\";
3662 arc_clear_unalign ();
3665 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
3667 if (satisfies_constraint_Rcq (xop[0]))
3669 s = \"add_s %2,%0,%1\n\tldw.as %2,[pcl,%2]\";
3670 xop[1] = GEN_INT ((10 - unalign) / 2U);
3674 s = \"add1 %2,pcl,%0\n\tldw_s %2,[%2,%1]\";
3675 xop[1] = GEN_INT (10 + unalign);
3680 if (satisfies_constraint_Rcq (xop[0]))
3682 s = \"add_s %2,%0,%1\n\tldw.x.as %2,[pcl,%2]\";
3683 xop[1] = GEN_INT ((10 - unalign) / 2U);
3687 s = \"add1 %2,pcl,%0\n\tldw_s.x %2,[%2,%1]\";
3688 xop[1] = GEN_INT (10 + unalign);
3691 arc_toggle_unalign ();
3694 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
3696 if ((rtx_equal_p (xop[2], xop[0])
3697 || find_reg_note (insn, REG_DEAD, xop[0]))
3698 && satisfies_constraint_Rcq (xop[0]))
3700 s = \"add_s %0,%0,pcl\n\tldb_s %2,[%0,%1]\";
3701 xop[1] = GEN_INT (8 + unalign);
3705 s = \"add %2,%0,pcl\n\tldb_s %2,[%2,%1]\";
3706 xop[1] = GEN_INT (10 + unalign);
3707 arc_toggle_unalign ();
3710 else if ((rtx_equal_p (xop[0], xop[2])
3711 || find_reg_note (insn, REG_DEAD, xop[0]))
3712 && satisfies_constraint_Rcq (xop[0]))
3714 s = \"add_s %0,%0,%1\n\tldb.x %2,[pcl,%0]\";
3715 xop[1] = GEN_INT (10 - unalign);
3716 arc_toggle_unalign ();
3720 /* ??? Length is 12. */
3721 s = \"add %2,%0,%1\n\tldb.x %2,[pcl,%2]\";
3722 xop[1] = GEN_INT (8 + unalign);
3728 output_asm_insn (s, xop);
3729 return \"add_s %2,%2,pcl\n\tj_s%* [%2]\";
3731 [(set_attr "length" "10")
3732 (set_attr "type" "jump")
3733 (set_attr "iscompact" "true")
3734 (set_attr "cond" "nocond")])
3736 (define_expand "call"
3737 ;; operands[1] is stack_size_rtx
3738 ;; operands[2] is next_arg_register
3739 [(parallel [(call (match_operand:SI 0 "call_operand" "")
3740 (match_operand 1 "" ""))
3741 (clobber (reg:SI 31))])]
3746 gcc_assert (MEM_P (operands[0]));
3747 callee = XEXP (operands[0], 0);
3748 if (crtl->profile && arc_profile_call (callee))
3750 emit_call_insn (gen_call_prof (gen_rtx_SYMBOL_REF (Pmode,
3755 /* This is to decide if we should generate indirect calls by loading the
3756 32 bit address of the callee into a register before performing the
3757 branch and link - this exposes cse opportunities.
3758 Also, in weird cases like compile/20010107-1.c, we may get a PLUS. */
3759 if (GET_CODE (callee) != REG
3760 && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
3761 XEXP (operands[0], 0) = force_reg (Pmode, callee);
3766 ; Rcq, which is used in alternative 0, checks for conditional execution.
3767 ; At instruction output time, if it doesn't match and we end up with
3768 ; alternative 1 ("q"), that means that we can't use the short form.
3769 (define_insn "*call_i"
3770 [(call (mem:SI (match_operand:SI 0
3771 "call_address_operand" "Rcq,q,c,Cbp,Cbr,L,I,Cal"))
3772 (match_operand 1 "" ""))
3773 (clobber (reg:SI 31))]
3784 [(set_attr "type" "call,call,call,call,call,call,call,call_no_delay_slot")
3785 (set_attr "iscompact" "maybe,false,*,*,*,*,*,*")
3786 (set_attr "predicable" "no,no,yes,yes,no,yes,no,yes")
3787 (set_attr "length" "*,*,4,4,4,4,4,8")])
3789 (define_insn "call_prof"
3790 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "Cbr,Cal"))
3791 (match_operand 1 "" ""))
3792 (clobber (reg:SI 31))
3799 [(set_attr "type" "call,call_no_delay_slot")
3800 (set_attr "predicable" "yes,yes")
3801 (set_attr "length" "4,8")])
3803 (define_expand "call_value"
3804 ;; operand 2 is stack_size_rtx
3805 ;; operand 3 is next_arg_register
3806 [(parallel [(set (match_operand 0 "dest_reg_operand" "=r")
3807 (call (match_operand:SI 1 "call_operand" "")
3808 (match_operand 2 "" "")))
3809 (clobber (reg:SI 31))])]
3815 gcc_assert (MEM_P (operands[1]));
3816 callee = XEXP (operands[1], 0);
3817 if (crtl->profile && arc_profile_call (callee))
3819 emit_call_insn (gen_call_value_prof (operands[0],
3820 gen_rtx_SYMBOL_REF (Pmode,
3825 /* See the comment in define_expand \"call\". */
3826 if (GET_CODE (callee) != REG
3827 && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
3828 XEXP (operands[1], 0) = force_reg (Pmode, callee);
3832 ; Rcq, which is used in alternative 0, checks for conditional execution.
3833 ; At instruction output time, if it doesn't match and we end up with
3834 ; alternative 1 ("q"), that means that we can't use the short form.
3835 (define_insn "*call_value_i"
3836 [(set (match_operand 0 "dest_reg_operand" "=Rcq,q,w, w, w,w,w, w")
3837 (call (mem:SI (match_operand:SI 1
3838 "call_address_operand" "Rcq,q,c,Cbp,Cbr,L,I,Cal"))
3839 (match_operand 2 "" "")))
3840 (clobber (reg:SI 31))]
3851 [(set_attr "type" "call,call,call,call,call,call,call,call_no_delay_slot")
3852 (set_attr "iscompact" "maybe,false,*,*,*,*,*,*")
3853 (set_attr "predicable" "no,no,yes,yes,no,yes,no,yes")
3854 (set_attr "length" "*,*,4,4,4,4,4,8")])
3856 ; There is a bl_s instruction (16 bit opcode branch-and-link), but we can't
3857 ; use it for lack of inter-procedural branch shortening.
3858 ; Link-time relaxation would help...
3861 (define_insn "call_value_prof"
3862 [(set (match_operand 0 "dest_reg_operand" "=r,r")
3863 (call (mem:SI (match_operand:SI 1 "symbolic_operand" "Cbr,Cal"))
3864 (match_operand 2 "" "")))
3865 (clobber (reg:SI 31))
3872 [(set_attr "type" "call,call_no_delay_slot")
3873 (set_attr "predicable" "yes,yes")
3874 (set_attr "length" "4,8")])
3880 [(set_attr "type" "misc")
3881 (set_attr "iscompact" "true")
3882 (set_attr "cond" "canuse")
3883 (set_attr "length" "2")])
3885 ;; Special pattern to flush the icache.
3886 ;; ??? Not sure what to do here. Some ARC's are known to support this.
3888 (define_insn "flush_icache"
3889 [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] 0)]
3892 [(set_attr "type" "misc")])
3894 ;; Split up troublesome insns for better scheduling.
3896 ;; Peepholes go at the end.
3897 ;;asl followed by add can be replaced by an add{1,2,3}
3898 ;; Three define_peepholes have been added for this optimization
3899 ;; ??? This used to target non-canonical rtl. Now we use add_n, which
3900 ;; can be generated by combine. Check if these peepholes still provide
3903 ;; -------------------------------------------------------------
3904 ;; Pattern 1 : r0 = r1 << {i}
3905 ;; r3 = r4/INT + r0 ;;and commutative
3908 ;; add{i} r3,r4/INT,r1
3909 ;; -------------------------------------------------------------
3910 ;; ??? This should be covered by combine, alas, at times combine gets
3911 ;; too clever for it's own good: when the shifted input is known to be
3912 ;; either 0 or 1, the operation will be made into an if-then-else, and
3913 ;; thus fail to match the add_n pattern. Example: _mktm_r, line 85 in
3914 ;; newlib/libc/time/mktm_r.c .
3917 [(set (match_operand:SI 0 "dest_reg_operand" "")
3918 (ashift:SI (match_operand:SI 1 "register_operand" "")
3919 (match_operand:SI 2 "const_int_operand" "")))
3920 (set (match_operand:SI 3 "dest_reg_operand" "")
3921 (plus:SI (match_operand:SI 4 "nonmemory_operand" "")
3922 (match_operand:SI 5 "nonmemory_operand" "")))]
3923 "(INTVAL (operands[2]) == 1
3924 || INTVAL (operands[2]) == 2
3925 || INTVAL (operands[2]) == 3)
3926 && (true_regnum (operands[4]) == true_regnum (operands[0])
3927 || true_regnum (operands[5]) == true_regnum (operands[0]))
3928 && (peep2_reg_dead_p (2, operands[0]) || (true_regnum (operands[3]) == true_regnum (operands[0])))"
3929 ;; the preparation statements take care to put proper operand in operands[4]
3930 ;; operands[4] will always contain the correct operand. This is added to satisfy commutativity
3932 (plus:SI (mult:SI (match_dup 1)
3935 "if (true_regnum (operands[4]) == true_regnum (operands[0]))
3936 operands[4] = operands[5];
3937 operands[2] = GEN_INT (1 << INTVAL (operands[2]));"
3940 ;; -------------------------------------------------------------
3941 ;; Pattern 1 : r0 = r1 << {i}
3946 ;; -------------------------------------------------------------
3947 ;; ??? This should be covered by combine, alas, at times combine gets
3948 ;; too clever for it's own good: when the shifted input is known to be
3949 ;; either 0 or 1, the operation will be made into an if-then-else, and
3950 ;; thus fail to match the sub_n pattern. Example: __ieee754_yn, line 239 in
3951 ;; newlib/libm/math/e_jn.c .
3954 [(set (match_operand:SI 0 "dest_reg_operand" "")
3955 (ashift:SI (match_operand:SI 1 "register_operand" "")
3956 (match_operand:SI 2 "const_int_operand" "")))
3957 (set (match_operand:SI 3 "dest_reg_operand" "")
3958 (minus:SI (match_operand:SI 4 "nonmemory_operand" "")
3960 "(INTVAL (operands[2]) == 1
3961 || INTVAL (operands[2]) == 2
3962 || INTVAL (operands[2]) == 3)
3963 && (peep2_reg_dead_p (2, operands[0])
3964 || (true_regnum (operands[3]) == true_regnum (operands[0])))"
3966 (minus:SI (match_dup 4)
3967 (mult:SI (match_dup 1)
3969 "operands[2] = GEN_INT (1 << INTVAL (operands[2]));"
3974 ; When using the high single bit, the result of a multiply is either
3975 ; the original number or zero. But MPY costs 4 cycles, which we
3976 ; can replace with the 2 cycles for the pair of TST_S and ADD.NE.
3978 [(set (match_operand:SI 0 "dest_reg_operand" "")
3979 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
3981 (set (match_operand:SI 4 "register_operand" "")
3982 (mult:SI (match_operand:SI 2 "register_operand")
3983 (match_operand:SI 3 "nonmemory_operand" "")))]
3984 "TARGET_ARC700 && !TARGET_NOMPY_SET
3985 && (rtx_equal_p (operands[0], operands[2])
3986 || rtx_equal_p (operands[0], operands[3]))
3987 && peep2_regno_dead_p (0, CC_REG)
3988 && (rtx_equal_p (operands[0], operands[4])
3989 || (peep2_reg_dead_p (2, operands[0])
3990 && peep2_reg_dead_p (1, operands[4])))"
3991 [(parallel [(set (reg:CC_Z CC_REG)
3992 (compare:CC_Z (lshiftrt:SI (match_dup 1) (const_int 31))
3994 (set (match_dup 4) (lshiftrt:SI (match_dup 1) (const_int 31)))])
3996 (ne (reg:CC_Z CC_REG) (const_int 0))
3997 (set (match_dup 4) (match_dup 5)))]
3999 if (!rtx_equal_p (operands[0], operands[2]))
4000 operands[5] = operands[2];
4001 else if (!rtx_equal_p (operands[0], operands[3]))
4002 operands[5] = operands[3];
4004 operands[5] = operands[4]; /* Actually a no-op... presumably rare. */
4008 [(set (match_operand:SI 0 "dest_reg_operand" "")
4009 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4011 (set (match_operand:SI 4 "register_operand" "")
4012 (mult:SI (match_operand:SI 2 "register_operand")
4013 (match_operand:SI 3 "nonmemory_operand" "")))]
4014 "TARGET_ARC700 && !TARGET_NOMPY_SET
4015 && (rtx_equal_p (operands[0], operands[2])
4016 || rtx_equal_p (operands[0], operands[3]))
4017 && peep2_regno_dead_p (2, CC_REG)"
4018 [(parallel [(set (reg:CC_Z CC_REG)
4019 (compare:CC_Z (lshiftrt:SI (match_dup 1) (const_int 31))
4021 (set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
4022 (set (match_dup 4) (match_dup 5))
4024 (eq (reg:CC_Z CC_REG) (const_int 0))
4025 (set (match_dup 4) (const_int 0)))]
4026 "operands[5] = operands[rtx_equal_p (operands[0], operands[2]) ? 3 : 2];")
4028 ;; Instructions generated through builtins
4030 (define_insn "clrsbsi2"
4031 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
4032 (clrsb:SI (match_operand:SI 1 "general_operand" "cL,Cal")))]
4037 [(set_attr "length" "4,8")
4038 (set_attr "type" "two_cycle_core,two_cycle_core")])
4040 (define_insn "norm_f"
4041 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
4042 (clrsb:SI (match_operand:SI 1 "general_operand" "cL,Cal")))
4043 (set (reg:CC_ZN CC_REG)
4044 (compare:CC_ZN (match_dup 1) (const_int 0)))]
4049 [(set_attr "length" "4,8")
4050 (set_attr "type" "two_cycle_core,two_cycle_core")])
4052 (define_insn_and_split "clrsbhi2"
4053 [(set (match_operand:HI 0 "dest_reg_operand" "=w,w")
4054 (clrsb:HI (match_operand:HI 1 "general_operand" "cL,Cal")))]
4058 [(set (match_dup 0) (zero_extend:SI (clrsb:HI (match_dup 1))))]
4059 "operands[0] = simplify_gen_subreg (SImode, operands[0], HImode, 0);")
4061 (define_insn "normw"
4062 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
4064 (clrsb:HI (match_operand:HI 1 "general_operand" "cL,Cal"))))]
4069 [(set_attr "length" "4,8")
4070 (set_attr "type" "two_cycle_core,two_cycle_core")])
4072 (define_expand "clzsi2"
4073 [(set (match_operand:SI 0 "dest_reg_operand" "")
4074 (clz:SI (match_operand:SI 1 "register_operand" "")))]
4077 emit_insn (gen_norm_f (operands[0], operands[1]));
4081 gen_rtx_LT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4082 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
4086 gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4087 gen_rtx_SET (VOIDmode, operands[0],
4088 plus_constant (SImode, operands[0], 1))));
4092 (define_expand "ctzsi2"
4093 [(set (match_operand:SI 0 "register_operand" "")
4094 (ctz:SI (match_operand:SI 1 "register_operand" "")))]
4097 rtx temp = operands[0];
4099 if (reg_overlap_mentioned_p (temp, operands[1])
4100 || (REGNO (temp) < FIRST_PSEUDO_REGISTER
4101 && !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS],
4103 temp = gen_reg_rtx (SImode);
4104 emit_insn (gen_addsi3 (temp, operands[1], constm1_rtx));
4105 emit_insn (gen_bic_f_zn (temp, temp, operands[1]));
4106 emit_insn (gen_clrsbsi2 (temp, temp));
4110 gen_rtx_LT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4111 gen_rtx_SET (VOIDmode, operands[0], GEN_INT (32))));
4115 gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4116 gen_rtx_SET (VOIDmode, operands[0],
4117 gen_rtx_MINUS (SImode, GEN_INT (31), temp))));
4123 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w,w")
4124 (unspec:SI [(match_operand:SI 1 "general_operand" "L,Cal,c")]
4131 [(set_attr "length" "4,8,4")
4132 (set_attr "type" "two_cycle_core,two_cycle_core,two_cycle_core")])
4134 ;; FIXME: an intrinsic for multiply is daft. Can we remove this?
4135 (define_insn "mul64"
4136 [(unspec [(match_operand:SI 0 "general_operand" "%q,r,r,r")
4137 (match_operand:SI 1 "general_operand" "q,rL,I,Cal")]
4141 mul64%? \t0, %0, %1%&
4144 mul64%? \t0, %0, %S1"
4145 [(set_attr "length" "2,4,4,8")
4146 (set_attr "iscompact" "true,false,false,false")
4147 (set_attr "type" "binary,binary,binary,binary")
4148 (set_attr "cond" "canuse,canuse, nocond, canuse")])
4150 (define_insn "mulu64"
4151 [(unspec [(match_operand:SI 0 "general_operand" "%r,r,r,r")
4152 (match_operand:SI 1 "general_operand" "rL,I,r,Cal")]
4156 mulu64%? \t0, %0, %1
4159 mulu64%? \t0, %0, %S1"
4160 [(set_attr "length" "4,4,4,8")
4161 (set_attr "type" "binary,binary,binary,binary")
4162 (set_attr "cond" "canuse,nocond,nocond,canuse")])
4164 (define_insn "divaw"
4165 [(set (match_operand:SI 0 "dest_reg_operand" "=&w,&w,&w")
4166 (unspec:SI [(div:SI (match_operand:SI 1 "general_operand" "r,Cal,r")
4167 (match_operand:SI 2 "general_operand" "r,r,Cal"))]
4169 "TARGET_ARC700 || TARGET_EA_SET"
4173 divaw \t%0, %1, %S2"
4174 [(set_attr "length" "4,8,8")
4175 (set_attr "type" "divaw,divaw,divaw")])
4178 [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")]
4185 [(set_attr "length" "4,4,8")
4186 (set_attr "type" "misc,misc,misc")
4187 (set_attr "predicable" "yes,no,yes")
4188 (set_attr "cond" "clob,clob,clob")])
4191 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4195 [(set_attr "length" "4")
4196 (set_attr "type" "misc")])
4199 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4203 [(set_attr "length" "4")
4204 (set_attr "type" "misc")
4205 (set_attr "cond" "clob")])
4208 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4212 [(set_attr "length" "4")
4213 (set_attr "type" "misc")])
4216 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4226 [(set_attr "length" "4")
4227 (set_attr "type" "misc")])
4230 (define_insn "sleep"
4231 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "L")]
4233 "check_if_valid_sleep_operand(operands,0)"
4235 [(set_attr "length" "4")
4236 (set_attr "type" "misc")])
4238 (define_insn "core_read"
4239 [(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
4240 (unspec_volatile:SI [(match_operand:SI 1 "general_operand" "Hn,!r")]
4241 VUNSPEC_CORE_READ))]
4244 if (check_if_valid_regno_const (operands, 1))
4245 return \"mov \t%0, r%1\";
4246 return \"mov \t%0, r%1\";
4248 [(set_attr "length" "4")
4249 (set_attr "type" "unary")])
4251 (define_insn "core_write"
4252 [(unspec_volatile [(match_operand:SI 0 "general_operand" "r,r")
4253 (match_operand:SI 1 "general_operand" "Hn,!r")]
4254 VUNSPEC_CORE_WRITE)]
4257 if (check_if_valid_regno_const (operands, 1))
4258 return \"mov \tr%1, %0\";
4259 return \"mov \tr%1, %0\";
4261 [(set_attr "length" "4")
4262 (set_attr "type" "unary")])
4265 [(set (match_operand:SI 0 "dest_reg_operand" "=r,r,r,r")
4266 (unspec_volatile:SI [(match_operand:SI 1 "general_operand" "I,HCal,r,D")]
4270 [(set_attr "length" "4,8,4,8")
4271 (set_attr "type" "lr,lr,lr,lr")])
4274 [(unspec_volatile [(match_operand:SI 0 "general_operand" "Cal,r,r,r")
4275 (match_operand:SI 1 "general_operand" "Ir,I,HCal,r")]
4279 [(set_attr "length" "8,4,8,4")
4280 (set_attr "type" "sr,sr,sr,sr")])
4282 (define_insn "trap_s"
4283 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "L,Cal")]
4287 if (which_alternative == 0)
4289 arc_toggle_unalign ();
4290 return \"trap_s %0\";
4293 /* Keep this message in sync with the one in arc.c:arc_expand_builtin,
4294 because *.md files do not get scanned by exgettext. */
4295 fatal_error (input_location,
4296 \"operand to trap_s should be an unsigned 6-bit value\");
4298 [(set_attr "length" "2")
4299 (set_attr "type" "misc")])
4301 (define_insn "unimp_s"
4302 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4306 [(set_attr "length" "4")
4307 (set_attr "type" "misc")])
4309 ;; End of instructions generated through builtins
4311 ; Since the demise of REG_N_SETS as reliable data readily available to the
4312 ; target, it is no longer possible to find out
4313 ; in the prologue / epilogue expanders how many times blink is set.
4314 ; Using df_regs_ever_live_p to decide if blink needs saving means that
4315 ; any explicit use of blink will cause it to be saved; hence we cannot
4316 ; represent the blink use in return / sibcall instructions themselves, and
4317 ; instead have to show it in EPILOGUE_USES and must explicitly
4318 ; forbid instructions that change blink in the return / sibcall delay slot.
4319 (define_expand "sibcall"
4320 [(parallel [(call (match_operand 0 "memory_operand" "")
4321 (match_operand 1 "general_operand" ""))
4323 (use (match_operand 2 "" ""))])]
4327 rtx callee = XEXP (operands[0], 0);
4329 if (operands[2] == NULL_RTX)
4330 operands[2] = const0_rtx;
4331 if (crtl->profile && arc_profile_call (callee))
4333 emit_insn (gen_sibcall_prof
4334 (gen_rtx_SYMBOL_REF (Pmode, \"_mcount_call\"),
4335 operands[1], operands[2]));
4338 if (GET_CODE (callee) != REG
4339 && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
4340 XEXP (operands[0], 0) = force_reg (Pmode, callee);
4344 (define_expand "sibcall_value"
4345 [(parallel [(set (match_operand 0 "dest_reg_operand" "")
4346 (call (match_operand 1 "memory_operand" "")
4347 (match_operand 2 "general_operand" "")))
4349 (use (match_operand 3 "" ""))])]
4353 rtx callee = XEXP (operands[1], 0);
4355 if (operands[3] == NULL_RTX)
4356 operands[3] = const0_rtx;
4357 if (crtl->profile && arc_profile_call (XEXP (operands[1], 0)))
4359 emit_insn (gen_sibcall_value_prof
4360 (operands[0], gen_rtx_SYMBOL_REF (Pmode, \"_mcount_call\"),
4361 operands[2], operands[3]));
4364 if (GET_CODE (callee) != REG && arc_is_longcall_p (callee))
4365 XEXP (operands[1], 0) = force_reg (Pmode, callee);
4369 (define_insn "*sibcall_insn"
4370 [(call (mem:SI (match_operand:SI 0 "call_address_operand"
4371 "Cbp,Cbr,Rs5,Rsc,Cal"))
4372 (match_operand 1 "" ""))
4374 (use (match_operand 2 "" ""))]
4382 [(set_attr "type" "call,call,call,call,call_no_delay_slot")
4383 (set_attr "predicable" "yes,no,no,yes,yes")
4384 (set_attr "iscompact" "false,false,maybe,false,false")
4385 (set_attr "is_SIBCALL" "yes")]
4388 (define_insn "*sibcall_value_insn"
4389 [(set (match_operand 0 "dest_reg_operand" "")
4390 (call (mem:SI (match_operand:SI 1 "call_address_operand"
4391 "Cbp,Cbr,Rs5,Rsc,Cal"))
4392 (match_operand 2 "" "")))
4394 (use (match_operand 3 "" ""))]
4402 [(set_attr "type" "call,call,call,call,call_no_delay_slot")
4403 (set_attr "predicable" "yes,no,no,yes,yes")
4404 (set_attr "iscompact" "false,false,maybe,false,false")
4405 (set_attr "is_SIBCALL" "yes")]
4408 (define_insn "sibcall_prof"
4409 [(call (mem:SI (match_operand:SI 0 "call_address_operand" "Cbr,Cal"))
4410 (match_operand 1 "" ""))
4412 (use (match_operand 2 "" ""))
4419 [(set_attr "type" "call,call_no_delay_slot")
4420 (set_attr "predicable" "yes")
4421 (set_attr "is_SIBCALL" "yes")]
4424 (define_insn "sibcall_value_prof"
4425 [(set (match_operand 0 "dest_reg_operand" "")
4426 (call (mem:SI (match_operand:SI 1 "call_address_operand" "Cbr,Cal"))
4427 (match_operand 2 "" "")))
4429 (use (match_operand 3 "" ""))
4436 [(set_attr "type" "call,call_no_delay_slot")
4437 (set_attr "predicable" "yes")
4438 (set_attr "is_SIBCALL" "yes")]
4441 (define_expand "prologue"
4445 arc_expand_prologue ();
4449 (define_expand "epilogue"
4453 arc_expand_epilogue (0);
4457 (define_expand "sibcall_epilogue"
4461 arc_expand_epilogue (1);
4465 ; Since the demise of REG_N_SETS, it is no longer possible to find out
4466 ; in the prologue / epilogue expanders how many times blink is set.
4467 ; Using df_regs_ever_live_p to decide if blink needs saving means that
4468 ; any explicit use of blink will cause it to be saved; hence we cannot
4469 ; represent the blink use in return / sibcall instructions themselves, and
4470 ; instead have to show it in EPILOGUE_USES and must explicitly
4471 ; forbid instructions that change blink in the return / sibcall delay slot.
4472 (define_insn "simple_return"
4477 = gen_rtx_REG (Pmode,
4478 arc_return_address_regs[arc_compute_function_type (cfun)]);
4480 if (TARGET_PAD_RETURN)
4482 output_asm_insn (\"j%!%* [%0]%&\", ®);
4485 [(set_attr "type" "return")
4486 ; predicable won't help here since the canonical rtl looks different
4488 (set_attr "cond" "canuse")
4489 (set (attr "iscompact")
4490 (cond [(eq (symbol_ref "arc_compute_function_type (cfun)")
4491 (symbol_ref "ARC_FUNCTION_NORMAL"))
4492 (const_string "maybe")]
4493 (const_string "false")))
4494 (set (attr "length")
4495 (cond [(ne (symbol_ref "arc_compute_function_type (cfun)")
4496 (symbol_ref "ARC_FUNCTION_NORMAL"))
4500 (define_insn "p_return_i"
4502 (if_then_else (match_operator 0 "proper_comparison_operator"
4503 [(reg CC_REG) (const_int 0)])
4504 (simple_return) (pc)))]
4508 xop[0] = operands[0];
4510 = gen_rtx_REG (Pmode,
4511 arc_return_address_regs[arc_compute_function_type (cfun)]);
4513 if (TARGET_PAD_RETURN)
4515 output_asm_insn (\"j%d0%!%# [%1]%&\", xop);
4516 /* record the condition in case there is a delay insn. */
4517 arc_ccfsm_record_condition (xop[0], false, insn, 0);
4520 [(set_attr "type" "return")
4521 (set_attr "cond" "use")
4522 (set (attr "iscompact")
4523 (cond [(eq (symbol_ref "arc_compute_function_type (cfun)")
4524 (symbol_ref "ARC_FUNCTION_NORMAL"))
4525 (const_string "maybe")]
4526 (const_string "false")))
4527 (set (attr "length")
4528 (cond [(ne (symbol_ref "arc_compute_function_type (cfun)")
4529 (symbol_ref "ARC_FUNCTION_NORMAL"))
4531 (not (match_operand 0 "equality_comparison_operator" ""))
4533 (eq_attr "delay_slot_filled" "yes")
4537 (define_insn_and_split "eh_return"
4539 (use (match_operand:SI 0 "move_src_operand" "rC32,mCalCpc"))
4540 (clobber (match_scratch:SI 1 "=X,r"))
4541 (clobber (match_scratch:SI 2 "=&r,r"))]
4545 [(set (match_dup 2) (match_dup 0))]
4547 int offs = arc_return_slot_offset ();
4550 operands[2] = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
4553 if (!register_operand (operands[0], Pmode)
4554 && !satisfies_constraint_C32 (operands[0]))
4556 emit_move_insn (operands[1], operands[0]);
4557 operands[0] = operands[1];
4559 rtx addr = plus_constant (Pmode, stack_pointer_rtx, offs);
4560 if (!strict_memory_address_p (Pmode, addr))
4562 emit_move_insn (operands[2], addr);
4565 operands[2] = gen_frame_mem (Pmode, addr);
4568 [(set_attr "length" "12")])
4570 ;; ??? #ifdefs in function.c require the presence of this pattern, with a
4571 ;; non-constant predicate.
4572 (define_expand "return"
4576 ;; Comment in final.c (insn_current_reference_address) says
4577 ;; forward branch addresses are calculated from the next insn after branch
4578 ;; and for backward branches, it is calculated from the branch insn start.
4579 ;; The shortening logic here is tuned to accomodate this behaviour
4580 ;; ??? This should be grokked by the ccfsm machinery.
4581 (define_insn "cbranchsi4_scratch"
4583 (if_then_else (match_operator 0 "proper_comparison_operator"
4584 [(match_operand:SI 1 "register_operand" "c,c, c")
4585 (match_operand:SI 2 "nonmemory_operand" "L,c,?Cal")])
4586 (label_ref (match_operand 3 "" ""))
4588 (clobber (match_operand 4 "cc_register" ""))]
4590 || (TARGET_EARLY_CBRANCHSI
4591 && brcc_nolimm_operator (operands[0], VOIDmode)))
4592 && !CROSSING_JUMP_P (insn)"
4594 switch (get_attr_length (insn))
4596 case 2: return \"br%d0%? %1, %2, %^%l3%&\";
4597 case 4: return \"br%d0%* %1, %B2, %^%l3\";
4598 case 8: if (!brcc_nolimm_operator (operands[0], VOIDmode))
4599 return \"br%d0%* %1, %B2, %^%l3\";
4601 case 12:return \"cmp%? %1, %B2\\n\\tb%d0%* %^%l3%&;br%d0 out of range\";
4602 default: fprintf (stderr, \"unexpected length %d\\n\", get_attr_length (insn)); fflush (stderr); gcc_unreachable ();
4605 [(set_attr "cond" "clob, clob, clob")
4608 (match_test "valid_brcc_with_delay_p (operands)")
4609 (const_string "brcc")
4610 (const_string "brcc_no_delay_slot")))
4611 ; For forward branches, we need to account not only for the distance to
4612 ; the target, but also the difference between pcl and pc, the instruction
4613 ; length, and any delay insn, if present.
4616 (cond ; the outer cond does a test independent of branch shortening.
4617 [(match_operand 0 "brcc_nolimm_operator" "")
4619 [(and (match_operand:CC_Z 4 "cc_register")
4620 (eq_attr "delay_slot_filled" "no")
4621 (ge (minus (match_dup 3) (pc)) (const_int -128))
4622 (le (minus (match_dup 3) (pc))
4623 (minus (const_int 122)
4624 (symbol_ref "get_attr_delay_slot_length (insn)"))))
4626 (and (ge (minus (match_dup 3) (pc)) (const_int -256))
4627 (le (minus (match_dup 3) (pc))
4628 (minus (const_int 244)
4629 (symbol_ref "get_attr_delay_slot_length (insn)"))))
4631 (match_operand:SI 1 "compact_register_operand" "")
4634 (cond [(and (ge (minus (match_dup 3) (pc)) (const_int -256))
4635 (le (minus (match_dup 3) (pc)) (const_int 244)))
4637 (match_operand:SI 1 "compact_register_operand" "")
4640 (set (attr "iscompact")
4641 (if_then_else (match_test "get_attr_length (insn) & 2")
4642 (const_string "true") (const_string "false")))])
4644 ; combiner pattern observed for unwind-dw2-fde.c:linear_search_fdes.
4645 (define_insn "*bbit"
4648 (match_operator 3 "equality_comparison_operator"
4649 [(zero_extract:SI (match_operand:SI 1 "register_operand" "Rcqq,c")
4651 (match_operand:SI 2 "nonmemory_operand" "L,Lc"))
4653 (label_ref (match_operand 0 "" ""))
4655 (clobber (reg:CC_ZN CC_REG))]
4656 "!CROSSING_JUMP_P (insn)"
4658 switch (get_attr_length (insn))
4660 case 4: return (GET_CODE (operands[3]) == EQ
4661 ? \"bbit0%* %1,%2,%0\" : \"bbit1%* %1,%2,%0\");
4663 case 8: return \"btst%? %1,%2\n\tb%d3%* %0; bbit out of range\";
4664 default: gcc_unreachable ();
4667 [(set_attr "type" "brcc")
4668 (set_attr "cond" "clob")
4669 (set (attr "length")
4670 (cond [(and (ge (minus (match_dup 0) (pc)) (const_int -254))
4671 (le (minus (match_dup 0) (pc))
4672 (minus (const_int 248)
4673 (symbol_ref "get_attr_delay_slot_length (insn)"))))
4675 (eq (symbol_ref "which_alternative") (const_int 0))
4678 (set (attr "iscompact")
4679 (if_then_else (match_test "get_attr_length (insn) == 6")
4680 (const_string "true") (const_string "false")))])
4682 ; ??? When testing a bit from a DImode register, combine creates a
4683 ; zero_extract in DImode. This goes via an AND with a DImode constant,
4684 ; so can only be observed on 64 bit hosts.
4685 (define_insn_and_split "*bbit_di"
4688 (match_operator 3 "equality_comparison_operator"
4689 [(zero_extract:DI (match_operand:SI 1 "register_operand" "Rcqq,c")
4691 (match_operand 2 "immediate_operand" "L,L"))
4693 (label_ref (match_operand 0 "" ""))
4695 (clobber (reg:CC_ZN CC_REG))]
4696 "!CROSSING_JUMP_P (insn)"
4700 [(set (pc) (if_then_else (match_dup 3) (label_ref (match_dup 0)) (pc)))
4701 (clobber (reg:CC_ZN CC_REG))])]
4705 xtr = gen_rtx_ZERO_EXTRACT (SImode, operands[1], const1_rtx, operands[2]);
4706 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
4710 ; operand 0 is the loop count pseudo register
4711 ; operand 1 is the loop end pattern
4712 (define_expand "doloop_begin"
4713 [(use (match_operand 0 "register_operand" ""))
4714 (use (match_operand 1 "" ""))]
4717 /* Using the INSN_UID of the loop end pattern to identify it causes
4718 trouble with -fcompare-debug, so allocate a debug-independent
4719 id instead. We use negative numbers so that we can use the same
4720 slot in doloop_end_i where we later store a CODE_LABEL_NUMBER, and
4721 still be able to tell what kind of number this is. */
4722 static HOST_WIDE_INT loop_end_id = 0;
4724 rtx id = GEN_INT (--loop_end_id);
4725 XEXP (XVECEXP (PATTERN (operands[1]), 0, 4), 0) = id;
4726 emit_insn (gen_doloop_begin_i (operands[0], const0_rtx, id,
4727 const0_rtx, const0_rtx));
4731 ; ??? can't describe the insn properly as then the optimizers try to
4733 ;(define_insn "doloop_begin_i"
4734 ; [(set (reg:SI LP_START) (pc))
4735 ; (set (reg:SI LP_END) (unspec:SI [(pc)] UNSPEC_LP))
4736 ; (use (match_operand 0 "const_int_operand" "n"))]
4738 ; "lp .L__GCC__LP%0"
4741 ; The operands of doloop_end_i are also read / written by arc_reorg with
4742 ; XVECEXP (PATTERN (lp, 0, N), so if you want to change the pattern, you
4743 ; might have to adjust arc_reorg.
4744 ; operands 0 / 2 are supplied by the expander, 1, 3 and 4 are filled in
4745 ; by arc_reorg. arc_reorg might also alter operand 0.
4747 ; N in XVECEXP PATTERN (lp, 0 N)
4749 ; 0 unspec UNSPEC_LP identify pattern
4750 ; 1 clobber LP_START show LP_START is set
4751 ; 2 clobber LP_END show LP_END is set
4752 ; 3 use operand0 loop count pseudo register
4753 ; 4 use operand1 before arc_reorg: -id
4754 ; after : CODE_LABEL_NUMBER of loop top label
4755 ; 5 use operand2 INSN_UID of loop end insn
4756 ; 6 use operand3 loop setup not at start (1 above, 2 below)
4757 ; 7 use operand4 LABEL_REF of top label, if not
4758 ; immediately following
4759 ; If operand1 is still zero after arc_reorg, this is an orphaned loop
4760 ; instruction that was not at the start of the loop.
4761 ; There is no point is reloading this insn - then lp_count would still not
4762 ; be available for the loop end.
4763 (define_insn "doloop_begin_i"
4764 [(unspec:SI [(pc)] UNSPEC_LP)
4765 (clobber (reg:SI LP_START))
4766 (clobber (reg:SI LP_END))
4767 (use (match_operand:SI 0 "register_operand" "l,l,????*X"))
4768 (use (match_operand 1 "const_int_operand" "n,n,C_0"))
4769 (use (match_operand 2 "const_int_operand" "n,n,X"))
4770 (use (match_operand 3 "const_int_operand" "C_0,n,X"))
4771 (use (match_operand 4 "const_int_operand" "C_0,X,X"))]
4777 rtx loop_start = operands[4];
4779 if (CONST_INT_P (loop_start))
4780 loop_start = NULL_RTX;
4781 /* Size implications of the alignment will be taken care of by the
4782 alignment inserted at the loop start. */
4783 if (LOOP_ALIGN (0) && INTVAL (operands[1]))
4785 asm_fprintf (asm_out_file, "\t.p2align %d\\n", LOOP_ALIGN (0));
4786 arc_clear_unalign ();
4788 if (!INTVAL (operands[1]))
4789 return "; LITTLE LOST LOOP";
4790 if (loop_start && flag_pic)
4792 /* ??? Can do better for when a scratch register
4793 is known. But that would require extra testing. */
4794 return "push_s r0\;add r0,pcl,%4-(.&-4)\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1-(.&-4)\;sr r0,[3]; LP_END\;pop_s r0";
4796 /* Check if the loop end is in range to be set by the lp instruction. */
4797 size = INTVAL (operands[3]) < 2 ? 0 : 2048;
4798 for (scan = insn; scan && size < 2048; scan = NEXT_INSN (scan))
4802 if (recog_memoized (scan) == CODE_FOR_doloop_end_i
4803 && (XEXP (XVECEXP (PATTERN (scan), 0, 4), 0)
4804 == XEXP (XVECEXP (PATTERN (insn), 0, 4), 0)))
4806 len = get_attr_length (scan);
4809 /* Try to verify that there are at least three instruction fetches
4810 between the loop setup and the first encounter of the loop end. */
4811 for (scan = NEXT_INSN (insn); scan && n_insns < 3; scan = NEXT_INSN (scan))
4815 if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (scan)))
4816 scan = seq->insn (0);
4819 if (recog_memoized (scan) != CODE_FOR_doloop_end_i)
4822 if (simplejump_p (scan))
4824 scan = as_a <rtx_insn *> (XEXP (SET_SRC (PATTERN (scan)), 0));
4827 if (JUMP_LABEL (scan)
4828 /* JUMP_LABEL might be simple_return instead if an insn. */
4829 && (!INSN_P (JUMP_LABEL (scan))
4830 || (!next_active_insn (JUMP_LABEL (scan))
4831 || (recog_memoized (next_active_insn (JUMP_LABEL (scan)))
4832 != CODE_FOR_doloop_begin_i)))
4833 && (!next_active_insn (NEXT_INSN (PREV_INSN (scan)))
4835 (next_active_insn (NEXT_INSN (PREV_INSN (scan))))
4836 != CODE_FOR_doloop_begin_i)))
4841 len = get_attr_length (scan);
4842 /* Size estimation of asms assumes that each line which is nonempty
4843 codes an insn, and that each has a long immediate. For minimum insn
4844 count, assume merely that a nonempty asm has at least one insn. */
4845 if (GET_CODE (PATTERN (scan)) == ASM_INPUT
4846 || asm_noperands (PATTERN (scan)) >= 0)
4847 n_insns += (len != 0);
4849 n_insns += (len > 4 ? 2 : (len ? 1 : 0));
4853 asm_fprintf (asm_out_file, "\t.p2align %d\\n", LOOP_ALIGN (0));
4854 arc_clear_unalign ();
4856 gcc_assert (n_insns || GET_CODE (next_nonnote_insn (insn)) == CODE_LABEL);
4857 if (size >= 2048 || (TARGET_ARC600 && n_insns == 1) || loop_start)
4861 /* ??? Can do better for when a scratch register
4862 is known. But that would require extra testing. */
4863 arc_clear_unalign ();
4864 return ".p2align 2\;push_s r0\;add r0,pcl,24\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1-.+2\;sr r0,[3]; LP_END\;pop_s r0";
4866 output_asm_insn ((size < 2048
4867 ? "lp .L__GCC__LP%1" : "sr .L__GCC__LP%1,[3]; LP_END"),
4869 output_asm_insn (loop_start
4870 ? "sr %4,[2]; LP_START" : "sr 0f,[2]; LP_START",
4872 if (TARGET_ARC600 && n_insns < 1)
4873 output_asm_insn ("nop", operands);
4874 return (TARGET_ARC600 && n_insns < 3) ? "nop_s\;nop_s\;0:" : "0:";
4876 else if (TARGET_ARC600 && n_insns < 3)
4878 /* At least four instructions are needed between the setting of LP_COUNT
4879 and the loop end - but the lp instruction qualifies as one. */
4880 rtx prev = prev_nonnote_insn (insn);
4882 if (!INSN_P (prev) || dead_or_set_regno_p (prev, LP_COUNT))
4883 output_asm_insn ("nop", operands);
4885 return "lp .L__GCC__LP%1";
4887 [(set_attr "type" "loop_setup")
4888 (set_attr_alternative "length"
4889 ; FIXME: length is usually 4, but we need branch shortening
4890 ; to get this right.
4891 ; [(if_then_else (match_test "TARGET_ARC600") (const_int 16) (const_int 4))
4892 [(if_then_else (match_test "flag_pic") (const_int 24) (const_int 16))
4893 (if_then_else (match_test "flag_pic") (const_int 28) (const_int 16))
4895 ;; ??? we should really branch shorten this insn, but then we'd
4896 ;; need a proper label first. N.B. the end label can not only go out
4897 ;; of range when it is far away, but also when it precedes the loop -
4898 ;; which, unfortunately, it sometimes does, when the loop "optimizer"
4899 ;; messes things up.
4902 ; operand 0 is the loop count pseudo register
4903 ; operand 1 is the label to jump to at the top of the loop
4904 ; Use this for the ARC600 and ARC700. For ARCtangent-A5, this is unsafe
4905 ; without further checking for nearby branches etc., and without proper
4906 ; annotation of shift patterns that clobber lp_count
4907 ; ??? ARC600 might want to check if the loop has few iteration and only a
4908 ; single insn - loop setup is expensive then.
4909 (define_expand "doloop_end"
4910 [(use (match_operand 0 "register_operand" ""))
4911 (use (label_ref (match_operand 1 "" "")))]
4912 "TARGET_ARC600 || TARGET_ARC700"
4914 /* We could do smaller bivs with biv widening, and wider bivs by having
4915 a high-word counter in an outer loop - but punt on this for now. */
4916 if (GET_MODE (operands[0]) != SImode)
4918 emit_jump_insn (gen_doloop_end_i (operands[0], operands[1], const0_rtx));
4922 (define_insn_and_split "doloop_end_i"
4924 (if_then_else (ne (match_operand:SI 0 "shouldbe_register_operand" "+l,*c,*m")
4926 (label_ref (match_operand 1 "" ""))
4928 (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))
4929 (use (reg:SI LP_START))
4930 (use (reg:SI LP_END))
4931 (use (match_operand 2 "const_int_operand" "n,???Cn0,???X"))
4932 (clobber (match_scratch:SI 3 "=X,X,&????r"))]
4936 rtx prev = prev_nonnote_insn (insn);
4938 /* If there is an immediately preceding label, we must output a nop,
4939 lest a branch to that label will fall out of the loop.
4940 ??? We could try to avoid this by claiming to have a delay slot if there
4941 is a preceding label, and outputting the delay slot insn instead, if
4943 Or we could have some optimization that changes the source edge to update
4944 the loop count and jump to the loop start instead. */
4945 /* For ARC600, we must also prevent jumps inside the loop and jumps where
4946 the loop counter value is live at the target from being directly at the
4947 loop end. Being sure that the loop counter is dead at the target is
4948 too much hair - we can't rely on data flow information at this point -
4949 so insert a nop for all branches.
4950 The ARC600 also can't read the loop counter in the last insn of a loop. */
4952 output_asm_insn (\"nop%?\", operands);
4953 return \"\\n.L__GCC__LP%2: ; loop end, start is %1\";
4955 "&& memory_operand (operands[0], SImode)"
4958 emit_move_insn (operands[3], operands[0]);
4959 emit_jump_insn (gen_doloop_fallback_m (operands[3], operands[1], operands[0]));
4962 [(set_attr "type" "loop_end")
4963 (set (attr "length")
4964 (if_then_else (match_test "LABEL_P (prev_nonnote_insn (insn))")
4965 (const_int 4) (const_int 0)))]
4968 ; This pattern is generated by arc_reorg when there is no recognizable
4970 (define_insn "*doloop_fallback"
4971 [(set (pc) (if_then_else (ne (match_operand:SI 0 "register_operand" "+r,!w")
4973 (label_ref (match_operand 1 "" ""))
4975 (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
4976 ; avoid fooling the loop optimizer into assuming this is a special insn.
4978 "*return get_attr_length (insn) == 8
4979 ? \"brne.d %0,1,%1\;sub %0,%0,1\"
4980 : \"breq %0,1,0f\;b.d %1\;sub %0,%0,1\\n0:\";"
4981 [(set (attr "length")
4982 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -256))
4983 (le (minus (match_dup 1) (pc)) (const_int 244)))
4984 (const_int 8) (const_int 12)))
4985 (set_attr "type" "brcc_no_delay_slot")
4986 (set_attr "cond" "nocond")]
4989 ; reload can't make output reloads for jump insns, so we have to do this by hand.
4990 (define_insn "doloop_fallback_m"
4991 [(set (pc) (if_then_else (ne (match_operand:SI 0 "register_operand" "+&r")
4993 (label_ref (match_operand 1 "" ""))
4995 (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))
4996 (set (match_operand:SI 2 "memory_operand" "=m")
4997 (plus:SI (match_dup 0) (const_int -1)))]
4998 ; avoid fooling the loop optimizer into assuming this is a special insn.
5000 "*return get_attr_length (insn) == 12
5001 ? \"sub %0,%0,1\;brne.d %0,0,%1\;st%U2%V2 %0,%2\"
5002 : \"sub %0,%0,1\;breq %0,0,0f\;b.d %1\\n0:\tst%U2%V2 %0,%2\";"
5003 [(set (attr "length")
5004 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -252))
5005 (le (minus (match_dup 1) (pc)) (const_int 244)))
5006 (const_int 12) (const_int 16)))
5007 (set_attr "type" "brcc_no_delay_slot")
5008 (set_attr "cond" "nocond")]
5011 (define_expand "movmemsi"
5012 [(match_operand:BLK 0 "" "")
5013 (match_operand:BLK 1 "" "")
5014 (match_operand:SI 2 "nonmemory_operand" "")
5015 (match_operand 3 "immediate_operand" "")]
5017 "if (arc_expand_movmem (operands)) DONE; else FAIL;")
5019 ;; Close http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35803 if this works
5020 ;; to the point that we can generate cmove instructions.
5021 (define_expand "cbranch<mode>4"
5022 [(set (reg:CC CC_REG)
5023 (compare:CC (match_operand:SDF 1 "register_operand" "")
5024 (match_operand:SDF 2 "register_operand" "")))
5027 (match_operator 0 "comparison_operator" [(reg CC_REG)
5029 (label_ref (match_operand 3 "" ""))
5034 gcc_assert (XEXP (operands[0], 0) == operands[1]);
5035 gcc_assert (XEXP (operands[0], 1) == operands[2]);
5036 operands[0] = gen_compare_reg (operands[0], VOIDmode);
5037 emit_jump_insn (gen_branch_insn (operands[3], operands[0]));
5041 (define_expand "cmp_float"
5042 [(parallel [(set (match_operand 0 "") (match_operand 1 ""))
5043 (clobber (reg:SI RETURN_ADDR_REGNUM))
5044 (clobber (reg:SI R12_REG))])]
5048 (define_mode_iterator OPTFPE_CMP [CC_Z CC_FP_GT CC_FP_GE CC_FP_UNEQ CC_FP_ORD])
5049 (define_mode_attr cmp [(CC_Z "eq") (CC_FP_GT "gt") (CC_FP_GE "ge")
5050 (CC_FP_UNEQ "uneq") (CC_FP_ORD "ord")])
5052 (define_insn "*cmpsf_<cmp>"
5053 [(set (reg:OPTFPE_CMP CC_REG) (compare:OPTFPE_CMP (reg:SF 0) (reg:SF 1)))
5054 (clobber (reg:SI RETURN_ADDR_REGNUM))
5055 (clobber (reg:SI R12_REG))]
5056 "TARGET_OPTFPE && (!TARGET_ARGONAUT_SET || !TARGET_SPFP)
5057 && SFUNC_CHECK_PREDICABLE"
5058 "*return arc_output_libcall (\"__<cmp>sf2\");"
5059 [(set_attr "is_sfunc" "yes")
5060 (set_attr "predicable" "yes")])
5062 ;; N.B. for "*cmpdf_ord":
5063 ;; double precision fpx sets bit 31 for NaNs. We need bit 51 set
5064 ;; for the floating point emulation to recognize the NaN.
5065 (define_insn "*cmpdf_<cmp>"
5066 [(set (reg:OPTFPE_CMP CC_REG) (compare:OPTFPE_CMP (reg:DF 0) (reg:DF 2)))
5067 (clobber (reg:SI RETURN_ADDR_REGNUM))
5068 (clobber (reg:SI R12_REG))]
5069 "TARGET_OPTFPE && (!TARGET_ARGONAUT_SET || !TARGET_DPFP)
5070 && SFUNC_CHECK_PREDICABLE"
5071 "*return arc_output_libcall (\"__<cmp>df2\");"
5072 [(set_attr "is_sfunc" "yes")
5073 (set_attr "predicable" "yes")])
5075 (define_insn "abssf2"
5076 [(set (match_operand:SF 0 "dest_reg_operand" "=Rcq#q,Rcw,w")
5077 (abs:SF (match_operand:SF 1 "register_operand" "0, 0,c")))]
5080 [(set_attr "type" "unary")
5081 (set_attr "iscompact" "maybe,false,false")
5082 (set_attr "length" "2,4,4")
5083 (set_attr "predicable" "no,yes,no")])
5085 (define_insn "negsf2"
5086 [(set (match_operand:SF 0 "dest_reg_operand" "=Rcw,w")
5087 (neg:SF (match_operand:SF 1 "register_operand" "0,c")))]
5090 [(set_attr "type" "unary")
5091 (set_attr "predicable" "yes,no")])
5093 ;; ??? Should this use arc_output_libcall and set is_sfunc?
5094 (define_insn "*millicode_thunk_st"
5095 [(match_parallel 0 "millicode_store_operation"
5096 [(set (mem:SI (reg:SI SP_REG)) (reg:SI 13))])]
5099 output_asm_insn ("bl%* __st_r13_to_%0",
5100 &SET_SRC (XVECEXP (operands[0], 0,
5101 XVECLEN (operands[0], 0) - 2)));
5104 [(set_attr "type" "call")])
5106 (define_insn "*millicode_thunk_ld"
5107 [(match_parallel 0 "millicode_load_clob_operation"
5108 [(set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
5111 output_asm_insn ("bl%* __ld_r13_to_%0",
5112 &SET_DEST (XVECEXP (operands[0], 0,
5113 XVECLEN (operands[0], 0) - 2)));
5116 [(set_attr "type" "call")])
5118 ; the sibthunk restores blink, so we use the return rtx.
5119 (define_insn "*millicode_sibthunk_ld"
5120 [(match_parallel 0 "millicode_load_operation"
5122 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (reg:SI 12)))
5123 (set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
5126 output_asm_insn ("b%* __ld_r13_to_%0_ret",
5127 &SET_DEST (XVECEXP (operands[0], 0,
5128 XVECLEN (operands[0], 0) - 1)));
5131 [(set_attr "type" "call")
5132 (set_attr "is_SIBCALL" "yes")])
5134 ;; If hardware floating point is available, don't define a negdf pattern;
5135 ;; it would be something like:
5136 ;;(define_insn "negdf2"
5137 ;; [(set (match_operand:DF 0 "register_operand" "=w,w,D,?r")
5138 ;; (neg:DF (match_operand:DF 1 "register_operand" "0,c,D,D")))
5139 ;; (clobber (match_scratch:DF 2 "=X,X,X,X,D1"))]
5142 ;; bxor%? %H0,%H1,31
5143 ;; bxor %H0,%H1,31 ` mov %L0,%L1
5144 ;; drsubh%F0%F1 0,0,0
5145 ;; drsubh%F2%F1 %H0,0,0 ` dexcl%F2 %L0,%H0,%L0"
5146 ;; [(set_attr "type" "unary,unary,dpfp_addsub,dpfp_addsub")
5147 ;; (set_attr "iscompact" "false,false,false,false")
5148 ;; (set_attr "length" "4,4,8,12")
5149 ;; (set_attr "cond" "canuse,nocond,nocond,nocond")])
5150 ;; and this suffers from always requiring a long immediate when using
5151 ;; the floating point hardware.
5152 ;; We then want the sub[sd]f patterns to be used, so that we can load the
5153 ;; constant zero efficiently into a register when we want to do the
5154 ;; computation using the floating point hardware. There should be a special
5155 ;; subdf alternative that matches a zero operand 1, which then can allow
5156 ;; to use bxor to flip the high bit of an integer register.
5157 ;; ??? we actually can't use the floating point hardware for neg, because
5158 ;; this would not work right for -0. OTOH optabs.c has already code
5159 ;; to synthesyze negate by flipping the sign bit.
5162 ;; include the arc-FPX instructions
5165 (include "simdext.md")