1 ;; Machine description of the Synopsys DesignWare ARC cpu for GNU C compiler
2 ;; Copyright (C) 1994-2016 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"))
87 (include ("arcEM.md"))
88 (include ("arcHS.md"))
92 (include ("predicates.md"))
93 (include ("constraints.md"))
94 ;; -----------------------------------------------------------------------------
98 ;; -----------------------------------------------------------------------------
99 ;; Symbolic name Value Desc.
100 ;; -----------------------------------------------------------------------------
101 ;; UNSPEC_PLT 3 symbol to be referenced through the PLT
102 ;; UNSPEC_GOT 4 symbol to be rerenced through the GOT
103 ;; UNSPEC_GOTOFF 5 Local symbol.To be referenced relative to the
104 ;; GOTBASE.(Referenced as @GOTOFF)
105 ;; ----------------------------------------------------------------------------
107 (define_c_enum "unspec" [
142 (define_c_enum "vunspec" [
149 VUNSPEC_ARC_CORE_READ
150 VUNSPEC_ARC_CORE_WRITE
159 VUNSPEC_ARC_STACK_IRQ
161 VUNSPEC_ARC_DEXCL_NORES
170 [(UNSPEC_PROF 18) ; profile callgraph counter
181 (RETURN_ADDR_REGNUM 31)
192 (define_attr "is_sfunc" "no,yes" (const_string "no"))
194 ;; Insn type. Used to default other attribute values.
195 ; While the attribute is_sfunc is set for any call of a special function,
196 ; the instruction type sfunc is used only for the special call sequence
197 ; that loads the (pc-relative) function address into r12 and then calls
201 "move,load,store,cmove,unary,binary,compare,shift,uncond_branch,jump,branch,
202 brcc,brcc_no_delay_slot,call,sfunc,call_no_delay_slot,
203 multi,umulti, two_cycle_core,lr,sr,divaw,loop_setup,loop_end,return,
204 misc,spfp,dpfp_mult,dpfp_addsub,mulmac_600,cc_arith,
205 simd_vload, simd_vload128, simd_vstore, simd_vmove, simd_vmove_else_zero,
206 simd_vmove_with_acc, simd_varith_1cycle, simd_varith_2cycle,
207 simd_varith_with_acc, simd_vlogic, simd_vlogic_with_acc,
208 simd_vcompare, simd_vpermute, simd_vpack, simd_vpack_with_acc,
209 simd_valign, simd_valign_with_acc, simd_vcontrol,
210 simd_vspecial_3cycle, simd_vspecial_4cycle, simd_dma, mul16_em, div_rem,
212 (cond [(eq_attr "is_sfunc" "yes")
213 (cond [(match_test "!TARGET_LONG_CALLS_SET && (!TARGET_MEDIUM_CALLS || GET_CODE (PATTERN (insn)) != COND_EXEC)") (const_string "call")
214 (match_test "flag_pic") (const_string "sfunc")]
215 (const_string "call_no_delay_slot"))]
216 (const_string "binary")))
218 ;; The following three attributes are mixed case so that they can be
219 ;; used conveniently with the CALL_ATTR macro.
220 (define_attr "is_CALL" "no,yes"
221 (cond [(eq_attr "is_sfunc" "yes") (const_string "yes")
222 (eq_attr "type" "call,call_no_delay_slot") (const_string "yes")]
223 (const_string "no")))
225 (define_attr "is_SIBCALL" "no,yes" (const_string "no"))
227 (define_attr "is_NON_SIBCALL" "no,yes"
228 (cond [(eq_attr "is_SIBCALL" "yes") (const_string "no")
229 (eq_attr "is_CALL" "yes") (const_string "yes")]
230 (const_string "no")))
233 ;; Attribute describing the processor
234 (define_attr "cpu" "none,ARC600,ARC700,ARCEM,ARCHS"
235 (const (symbol_ref "arc_cpu_attr")))
237 ;; true for compact instructions (those with _s suffix)
238 ;; "maybe" means compact unless we conditionalize the insn.
239 (define_attr "iscompact" "true,maybe,true_limm,maybe_limm,false"
240 (cond [(eq_attr "type" "sfunc")
241 (const_string "maybe")]
242 (const_string "false")))
245 ; Is there an instruction that we are actually putting into the delay slot?
246 (define_attr "delay_slot_filled" "no,yes"
247 (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
249 (match_test "!TARGET_AT_DBR_CONDEXEC
251 && INSN_ANNULLED_BRANCH_P (insn)
252 && !INSN_FROM_TARGET_P (NEXT_INSN (insn))")
254 (const_string "yes")))
256 ; Is a delay slot present for purposes of shorten_branches?
257 ; We have to take the length of this insn into account for forward branches
258 ; even if we don't put the insn actually into a delay slot.
259 (define_attr "delay_slot_present" "no,yes"
260 (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
262 (const_string "yes")))
264 ; We can't use get_attr_length (NEXT_INSN (insn)) because this gives the
265 ; length of a different insn with the same uid.
266 (define_attr "delay_slot_length" ""
267 (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
269 (symbol_ref "get_attr_length (NEXT_INSN (PREV_INSN (insn)))
270 - get_attr_length (insn)")))
272 ; for ARCv2 we need to disable/enable different instruction alternatives
273 (define_attr "cpu_facility" "std,av1,av2,fpx"
274 (const_string "std"))
276 ; We should consider all the instructions enabled until otherwise
277 (define_attr "enabled" "no,yes"
278 (cond [(and (eq_attr "cpu_facility" "av1")
279 (match_test "TARGET_V2"))
282 (and (eq_attr "cpu_facility" "av2")
283 (not (match_test "TARGET_V2")))
286 (and (eq_attr "cpu_facility" "fpx")
287 (match_test "TARGET_FP_DP_AX"))
290 (const_string "yes")))
292 (define_attr "predicable" "no,yes" (const_string "no"))
293 ;; if 'predicable' were not so brain-dead, we would specify:
294 ;; (cond [(eq_attr "cond" "!canuse") (const_string "no")
295 ;; (eq_attr "iscompact" "maybe") (const_string "no")]
296 ;; (const_string "yes"))
297 ;; and then for everything but calls, we could just set the cond attribute.
299 ;; Condition codes: this one is used by final_prescan_insn to speed up
300 ;; conditionalizing instructions. It saves having to scan the rtl to see if
301 ;; it uses or alters the condition codes.
303 ;; USE: This insn uses the condition codes (eg: a conditional branch).
304 ;; CANUSE: This insn can use the condition codes (for conditional execution).
305 ;; SET: All condition codes are set by this insn.
306 ;; SET_ZN: the Z and N flags are set by this insn.
307 ;; SET_ZNC: the Z, N, and C flags are set by this insn.
308 ;; CLOB: The condition codes are set to unknown values by this insn.
309 ;; NOCOND: This insn can't use and doesn't affect the condition codes.
311 (define_attr "cond" "use,canuse,canuse_limm,canuse_limm_add,set,set_zn,clob,nocond"
313 [(and (eq_attr "predicable" "yes")
314 (eq_attr "is_sfunc" "no")
315 (eq_attr "delay_slot_filled" "no"))
316 (const_string "canuse")
318 (eq_attr "type" "call")
319 (cond [(eq_attr "delay_slot_filled" "yes") (const_string "nocond")
320 (match_test "!flag_pic") (const_string "canuse_limm")]
321 (const_string "nocond"))
323 (eq_attr "iscompact" "maybe,false")
324 (cond [ (and (eq_attr "type" "move")
325 (match_operand 1 "immediate_operand" ""))
327 (ior (match_operand 1 "u6_immediate_operand" "")
328 (match_operand 1 "long_immediate_operand" ""))
329 (const_string "canuse")
330 (const_string "canuse_limm"))
332 (eq_attr "type" "binary")
333 (cond [(ne (symbol_ref "REGNO (operands[0])")
334 (symbol_ref "REGNO (operands[1])"))
335 (const_string "nocond")
336 (match_operand 2 "register_operand" "")
337 (const_string "canuse")
338 (match_operand 2 "u6_immediate_operand" "")
339 (const_string "canuse")
340 (match_operand 2 "long_immediate_operand" "")
341 (const_string "canuse")
342 (match_operand 2 "const_int_operand" "")
343 (const_string "canuse_limm")]
344 (const_string "nocond"))
346 (eq_attr "type" "compare")
349 (eq_attr "type" "cmove,branch")
352 (eq_attr "is_sfunc" "yes")
353 (cond [(match_test "(TARGET_MEDIUM_CALLS
354 && !TARGET_LONG_CALLS_SET
356 (const_string "canuse_limm_add")
357 (match_test "(TARGET_MEDIUM_CALLS
358 && !TARGET_LONG_CALLS_SET)")
359 (const_string "canuse_limm")]
360 (const_string "canuse"))
364 (const_string "nocond"))]
366 (cond [(eq_attr "type" "compare")
369 (eq_attr "type" "cmove,branch")
374 (const_string "nocond"))))
376 /* ??? Having all these patterns gives ifcvt more freedom to generate
377 inefficient code. It seem to operate on the premise that
378 register-register copies and registers are free. I see better code
379 with -fno-if-convert now than without. */
381 [(match_operator 0 "proper_comparison_operator"
382 [(reg CC_REG) (const_int 0)])]
386 ;; Length (in # of bytes, long immediate constants counted too).
387 ;; ??? There's a nasty interaction between the conditional execution fsm
388 ;; and insn lengths: insns with shimm values cannot be conditionally executed.
389 (define_attr "length" ""
391 [(eq_attr "iscompact" "true,maybe")
393 [(eq_attr "type" "sfunc")
394 (cond [(match_test "GET_CODE (PATTERN (insn)) == COND_EXEC")
397 (match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 4)]
400 (eq_attr "iscompact" "true_limm")
403 (eq_attr "iscompact" "maybe_limm")
404 (cond [(match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 8)]
407 (eq_attr "type" "load")
409 (match_operand 1 "long_immediate_loadstore_operand" "")
410 (const_int 8) (const_int 4))
412 (eq_attr "type" "store")
414 (ior (match_operand 0 "long_immediate_loadstore_operand" "")
415 (match_operand 1 "immediate_operand" ""))
416 (const_int 8) (const_int 4))
418 (eq_attr "type" "move,unary")
420 [(match_operand 1 "u6_immediate_operand" "") (const_int 4)
421 (match_operand 1 "register_operand" "") (const_int 4)
422 (match_operand 1 "long_immediate_operand" "") (const_int 8)
423 (match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 8)]
426 (and (eq_attr "type" "shift")
427 (match_operand 1 "immediate_operand"))
429 (eq_attr "type" "binary,shift")
431 (ior (match_operand 2 "long_immediate_operand" "")
432 (and (ne (symbol_ref "REGNO (operands[0])")
433 (symbol_ref "REGNO (operands[1])"))
434 (eq (match_operand 2 "u6_immediate_operand" "")
437 (const_int 8) (const_int 4))
439 (eq_attr "type" "cmove")
440 (if_then_else (match_operand 1 "register_operand" "")
441 (const_int 4) (const_int 8))
443 (eq_attr "type" "call_no_delay_slot") (const_int 8)
449 ;; The length here is the length of a single asm. Unfortunately it might be
450 ;; 4 or 8 so we must allow for 8. That's ok though. How often will users
451 ;; lament asm's not being put in delay slots?
453 (define_asm_attributes
454 [(set_attr "length" "8")
455 (set_attr "type" "multi")
456 (set_attr "cond" "clob") ])
459 ;; The first two cond clauses and the default are necessary for correctness;
460 ;; the remaining cond clause is mainly an optimization, as otherwise nops
461 ;; would be inserted; however, if we didn't do this optimization, we would
462 ;; have to be more conservative in our length calculations.
464 (define_attr "in_delay_slot" "false,true"
465 (cond [(eq_attr "type" "uncond_branch,jump,branch,
466 call,sfunc,call_no_delay_slot,
467 brcc, brcc_no_delay_slot,loop_setup,loop_end")
468 (const_string "false")
469 (match_test "arc_write_ext_corereg (insn)")
470 (const_string "false")
471 (gt (symbol_ref "arc_hazard (prev_active_insn (insn),
472 next_active_insn (insn))")
473 (symbol_ref "(arc_hazard (prev_active_insn (insn), insn)
474 + arc_hazard (insn, next_active_insn (insn)))"))
475 (const_string "false")
476 (eq_attr "iscompact" "maybe") (const_string "true")
479 (if_then_else (eq_attr "length" "2,4")
480 (const_string "true")
481 (const_string "false"))))
483 ; must not put an insn inside that refers to blink.
484 (define_attr "in_call_delay_slot" "false,true"
485 (cond [(eq_attr "in_delay_slot" "false")
486 (const_string "false")
487 (match_test "arc_regno_use_in (RETURN_ADDR_REGNUM, PATTERN (insn))")
488 (const_string "false")]
489 (const_string "true")))
491 (define_attr "in_sfunc_delay_slot" "false,true"
492 (cond [(eq_attr "in_call_delay_slot" "false")
493 (const_string "false")
494 (match_test "arc_regno_use_in (12, PATTERN (insn))")
495 (const_string "false")]
496 (const_string "true")))
498 ;; Instructions that we can put into a delay slot and conditionalize.
499 (define_attr "cond_delay_insn" "no,yes"
500 (cond [(eq_attr "cond" "!canuse") (const_string "no")
501 (eq_attr "type" "call,branch,uncond_branch,jump,brcc")
503 (eq_attr "length" "2,4") (const_string "yes")]
504 (const_string "no")))
506 (define_attr "in_ret_delay_slot" "no,yes"
507 (cond [(eq_attr "in_delay_slot" "false")
509 (match_test "regno_clobbered_p
510 (arc_return_address_regs
511 [arc_compute_function_type (cfun)],
514 (const_string "yes")))
516 (define_attr "cond_ret_delay_insn" "no,yes"
517 (cond [(eq_attr "in_ret_delay_slot" "no") (const_string "no")
518 (eq_attr "cond_delay_insn" "no") (const_string "no")]
519 (const_string "yes")))
521 (define_attr "annul_ret_delay_insn" "no,yes"
522 (cond [(eq_attr "cond_ret_delay_insn" "yes") (const_string "yes")
523 (match_test "TARGET_AT_DBR_CONDEXEC") (const_string "no")
524 (eq_attr "type" "!call,branch,uncond_branch,jump,brcc,return,sfunc")
525 (const_string "yes")]
526 (const_string "no")))
529 ;; Delay slot definition for ARCompact ISA
531 ;; When outputting an annul-true insn elegible for cond-exec
532 ;; in a cbranch delay slot, unless optimizing for size, we use cond-exec
533 ;; for ARC600; we could also use this for ARC700 if the branch can't be
534 ;; unaligned and is at least somewhat likely (add parameter for this).
536 (define_delay (eq_attr "type" "call")
537 [(eq_attr "in_call_delay_slot" "true")
538 (eq_attr "in_call_delay_slot" "true")
541 (define_delay (and (match_test "!TARGET_AT_DBR_CONDEXEC")
542 (eq_attr "type" "brcc"))
543 [(eq_attr "in_delay_slot" "true")
544 (eq_attr "in_delay_slot" "true")
547 (define_delay (and (match_test "TARGET_AT_DBR_CONDEXEC")
548 (eq_attr "type" "brcc"))
549 [(eq_attr "in_delay_slot" "true")
554 (eq_attr "type" "return")
555 [(eq_attr "in_ret_delay_slot" "yes")
556 (eq_attr "annul_ret_delay_insn" "yes")
557 (eq_attr "cond_ret_delay_insn" "yes")])
559 ;; For ARC600, unexposing the delay sloy incurs a penalty also in the
560 ;; non-taken case, so the only meaningful way to have an annull-true
561 ;; filled delay slot is to conditionalize the delay slot insn.
562 (define_delay (and (match_test "TARGET_AT_DBR_CONDEXEC")
563 (eq_attr "type" "branch,uncond_branch,jump")
564 (match_test "!optimize_size"))
565 [(eq_attr "in_delay_slot" "true")
566 (eq_attr "cond_delay_insn" "yes")
567 (eq_attr "cond_delay_insn" "yes")])
569 ;; For ARC700, anything goes for annulled-true insns, since there is no
570 ;; penalty for the unexposed delay slot when the branch is not taken,
571 ;; however, we must avoid things that have a delay slot themselvese to
572 ;; avoid confusing gcc.
573 (define_delay (and (match_test "!TARGET_AT_DBR_CONDEXEC")
574 (eq_attr "type" "branch,uncond_branch,jump")
575 (match_test "!optimize_size"))
576 [(eq_attr "in_delay_slot" "true")
577 (eq_attr "type" "!call,branch,uncond_branch,jump,brcc,return,sfunc")
578 (eq_attr "cond_delay_insn" "yes")])
580 ;; -mlongcall -fpic sfuncs use r12 to load the function address
581 (define_delay (eq_attr "type" "sfunc")
582 [(eq_attr "in_sfunc_delay_slot" "true")
583 (eq_attr "in_sfunc_delay_slot" "true")
585 ;; ??? need to use a working strategy for canuse_limm:
586 ;; - either canuse_limm is not eligible for delay slots, and has no
587 ;; delay slots, or arc_reorg has to treat them as nocond, or it has to
588 ;; somehow modify them to become inelegible for delay slots if a decision
589 ;; is made that makes conditional execution required.
591 (define_attr "tune" "none,arc600,arc700_4_2_std,arc700_4_2_xmac"
593 (cond [(symbol_ref "arc_tune == TUNE_ARC600")
594 (const_string "arc600")
595 (symbol_ref "arc_tune == TUNE_ARC700_4_2_STD")
596 (const_string "arc700_4_2_std")
597 (symbol_ref "arc_tune == TUNE_ARC700_4_2_XMAC")
598 (const_string "arc700_4_2_xmac")]
599 (const_string "none"))))
601 (define_attr "tune_arc700" "false,true"
602 (if_then_else (eq_attr "tune" "arc700_4_2_std, arc700_4_2_xmac")
603 (const_string "true")
604 (const_string "false")))
606 ;; Move instructions.
607 (define_expand "movqi"
608 [(set (match_operand:QI 0 "move_dest_operand" "")
609 (match_operand:QI 1 "general_operand" ""))]
611 "if (prepare_move_operands (operands, QImode)) DONE;")
613 ; In order to allow the ccfsm machinery to do its work, the leading compact
614 ; alternatives say 'canuse' - there is another alternative that will match
615 ; when the condition codes are used.
616 ; Rcq won't match if the condition is actually used; to avoid a spurious match
617 ; via q, q is inactivated as constraint there.
618 ; Likewise, the length of an alternative that might be shifted to conditional
619 ; execution must reflect this, lest out-of-range branches are created.
620 ; The iscompact attribute allows the epilogue expander to know for which
621 ; insns it should lengthen the return insn.
622 (define_insn "*movqi_insn"
623 [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q, w, h, w,w,???w, w,Rcq, S,!*x, r,r, Ucm,m,???m")
624 (match_operand:QI 1 "move_src_operand" " cL, cP,Rcq#q,hCm1,cL,I,?Rac,?i, T,Rcq,Usd,Ucm,m,?Rac,c,?Rac"))]
625 "register_operand (operands[0], QImode)
626 || register_operand (operands[1], QImode)"
644 [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,load,load,store,store,store")
645 (set_attr "iscompact" "maybe,maybe,maybe,true,false,false,false,false,true,true,true,false,false,false,false,false")
646 (set_attr "predicable" "yes,no,yes,no,yes,no,yes,yes,no,no,no,no,no,no,no,no")
647 (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*")])
649 (define_expand "movhi"
650 [(set (match_operand:HI 0 "move_dest_operand" "")
651 (match_operand:HI 1 "general_operand" ""))]
653 "if (prepare_move_operands (operands, HImode)) DONE;")
655 (define_insn "*movhi_insn"
656 [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q, w, h, w,w,???w,Rcq#q, w,Rcq, S, r,r, Ucm,m,???m,VUsc,VUsc")
657 (match_operand:HI 1 "move_src_operand" " cL, cP,Rcq#q,hCm1,cL,I,?Rac, ?i,?i, T,Rcq,Ucm,m,?Rac,c,?Rac, Cm3,i"))]
658 "register_operand (operands[0], HImode)
659 || register_operand (operands[1], HImode)
660 || (CONSTANT_P (operands[1])
661 /* Don't use a LIMM that we could load with a single insn - we loose
662 delay-slot filling opportunities. */
663 && !satisfies_constraint_I (operands[1])
664 && satisfies_constraint_Usc (operands[0]))"
684 [(set_attr "type" "move,move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store,store")
685 (set_attr "iscompact" "maybe,maybe,maybe,true,false,false,false,maybe_limm,false,true,true,false,false,false,false,false,false,false")
686 (set_attr "predicable" "yes,no,yes,no,yes,no,yes,yes,yes,no,no,no,no,no,no,no,no,no")
687 (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,av2,*")])
689 (define_expand "movsi"
690 [(set (match_operand:SI 0 "move_dest_operand" "")
691 (match_operand:SI 1 "general_operand" ""))]
693 "if (prepare_move_operands (operands, SImode)) DONE;")
695 ; In order to allow the ccfsm machinery to do its work, the leading compact
696 ; alternatives say 'canuse' - there is another alternative that will match
697 ; when the condition codes are used.
698 ; Rcq won't match if the condition is actually used; to avoid a spurious match
699 ; via q, q is inactivated as constraint there.
700 ; Likewise, the length of an alternative that might be shifted to conditional
701 ; execution must reflect this, lest out-of-range branches are created.
702 ; the iscompact attribute allows the epilogue expander to know for which
703 ; insns it should lengthen the return insn.
704 ; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc .
705 (define_insn "*movsi_insn" ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
706 [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q, w, h, w,w, w, w, w, w,???w, ?w, w,Rcq#q, w,Rcq, S, Us<,RcqRck,!*x, r,!*Rsd,!*Rcd,r,Ucm, Usd,m,???m,VUsc,VUsc")
707 (match_operand:SI 1 "move_src_operand" " cL, cP,Rcq#q,hCm1,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,?Cal, T,Rcq,RcqRck, Us>,Usd,Ucm, Usd, Ucd,m, w,!*Rzd,c,?Rac, Cm3, C32"))]
708 "register_operand (operands[0], SImode)
709 || register_operand (operands[1], SImode)
710 || (CONSTANT_P (operands[1])
711 /* Don't use a LIMM that we could load with a single insn - we loose
712 delay-slot filling opportunities. */
713 && !satisfies_constraint_I (operands[1])
714 && satisfies_constraint_Usc (operands[0]))"
722 ror %0,((%1*2+1) & 0x3f) ;6
724 movh.cl %0,%L1>>16 ;8
725 * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;8\" : \"movbi.cl %0,%L1 >> 24,24,8;9\";
728 * return arc_get_unalign () ? \"add %0,pcl,%1-.+2\" : \"add %0,pcl,%1-.\";
733 * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
734 * return arc_short_long (insn, \"pop%? %0%&\", \"ld%U1 %0,%1%&\");
746 [(set_attr "type" "move,move,move,move,move,move,two_cycle_core,shift,shift,shift,move,binary,binary,move,move,load,store,store,load,load,load,load,load,load,store,store,store,store,store,store")
747 (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false")
748 ; Use default length for iscompact to allow for COND_EXEC. But set length
750 (set_attr "length" "*,*,*,*,4,4,4,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,*,*,*,4,8")
751 (set_attr "predicable" "yes,no,yes,no,yes,no,no,no,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no")
752 (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")])
754 ;; Sometimes generated by the epilogue code. We don't want to
755 ;; recognize these addresses in general, because the limm is costly,
756 ;; and we can't use them for stores. */
757 (define_insn "*movsi_pre_mod"
758 [(set (match_operand:SI 0 "register_operand" "=w")
761 (plus:SI (reg:SI SP_REG)
762 (match_operand 1 "immediate_operand" "Cal")))))]
765 [(set_attr "type" "load")
766 (set_attr "length" "8")])
768 ;; Store a value to directly to memory. The location might also be cached.
769 ;; Since the cached copy can cause a write-back at unpredictable times,
770 ;; we first write cached, then we write uncached.
771 (define_insn "store_direct"
772 [(set (match_operand:SI 0 "move_dest_operand" "=m")
773 (unspec:SI [(match_operand:SI 1 "register_operand" "c")]
776 "st%U0 %1,%0\;st%U0.di %1,%0"
777 [(set_attr "type" "store")])
779 (define_insn_and_split "*movsi_set_cc_insn"
780 [(set (match_operand:CC_ZN 2 "cc_set_register" "")
781 (match_operator:CC_ZN 3 "zn_compare_operator"
782 [(match_operand:SI 1 "nonmemory_operand" "cI,cL,Cal") (const_int 0)]))
783 (set (match_operand:SI 0 "register_operand" "=w,w,w")
787 ; splitting to 'tst' allows short insns and combination into brcc.
788 "reload_completed && operands_match_p (operands[0], operands[1])"
789 [(set (match_dup 2) (match_dup 3))]
791 [(set_attr "type" "compare")
792 (set_attr "predicable" "no,yes,yes")
793 (set_attr "cond" "set_zn")
794 (set_attr "length" "4,4,8")])
796 (define_insn "unary_comparison"
797 [(set (match_operand:CC_ZN 0 "cc_set_register" "")
798 (match_operator:CC_ZN 3 "zn_compare_operator"
799 [(match_operator:SI 2 "unary_operator"
800 [(match_operand:SI 1 "register_operand" "c")])
804 [(set_attr "type" "compare")
805 (set_attr "cond" "set_zn")])
808 ; this pattern is needed by combiner for cases like if (c=(~b)) { ... }
809 (define_insn "*unary_comparison_result_used"
810 [(set (match_operand 2 "cc_register" "")
811 (match_operator 4 "zn_compare_operator"
812 [(match_operator:SI 3 "unary_operator"
813 [(match_operand:SI 1 "register_operand" "c")])
815 (set (match_operand:SI 0 "register_operand" "=w")
819 [(set_attr "type" "compare")
820 (set_attr "cond" "set_zn")
821 (set_attr "length" "4")])
823 ; reload is too stingy with reloads for Rrq/Cbf/Rrq when it sees
824 ; a c/???Cal/X alternative, so we say it's c/???Cal/c instead,
825 ; even if we don't need the clobber.
826 (define_insn_and_split "*tst_movb"
828 (match_operand 0 "cc_register" "")
829 (match_operator 4 "zn_compare_operator"
831 (match_operand:SI 1 "register_operand" "%Rcq,Rcq, c, c, c, c,Rrq, 3, c")
832 (match_operand:SI 2 "nonmemory_operand" "Rcq,C0p,cI,C1p,Ccp,Chs,Cbf,Cbf,???Cal"))
834 (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,Rrq,Rrq,c"))]
836 "movb.f.cl %3,%1,%p2,%p2,%s2"
838 && (extract_constrain_insn_cached (insn), (which_alternative & ~1) != 6)"
839 [(set (match_dup 0) (match_dup 4))])
843 (match_operand 0 "cc_register" "")
844 (match_operator 3 "zn_compare_operator"
846 (match_operand:SI 1 "register_operand"
847 "%Rcq,Rcq, c, c, c, c, c, c")
848 (match_operand:SI 2 "nonmemory_operand"
849 " Rcq,C0p,cI,cL,C1p,Ccp,Chs,Cal"))
852 || !satisfies_constraint_Cbf (operands[2])
853 || satisfies_constraint_C0p (operands[2])
854 || satisfies_constraint_I (operands[2])
855 || satisfies_constraint_C1p (operands[2])
856 || satisfies_constraint_Chs (operands[2])"
858 switch (which_alternative)
860 case 0: case 2: case 3: case 7:
861 return \"tst%? %1,%2\";
863 return \"btst%? %1,%z2\";
865 return \"bmsk%?.f 0,%1,%Z2%&\";
867 return \"bclr%?.f 0,%1,%M2%&\";
869 return \"asr.f 0,%1,%p2\";
874 [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false")
875 (set_attr "type" "compare,compare,compare,compare,compare,compare,shift,compare")
876 (set_attr "length" "*,*,4,4,4,4,4,8")
877 (set_attr "predicable" "no,yes,no,yes,no,no,no,yes")
878 (set_attr "cond" "set_zn")])
880 ; ??? Sometimes, if an AND with a constant can be expressed as a zero_extract,
881 ; combine will do that and not try the AND.
883 ; It would take 66 constraint combinations to describe the zero_extract
884 ; constants that are covered by the 12-bit signed constant for tst
885 ; (excluding the ones that are better done by mov or btst).
886 ; so we rather use an extra pattern for tst;
887 ; since this is about constants, reload shouldn't care.
888 (define_insn "*tst_bitfield_tst"
889 [(set (match_operand:CC_ZN 0 "cc_set_register" "")
890 (match_operator 4 "zn_compare_operator"
892 (match_operand:SI 1 "register_operand" "c")
893 (match_operand:SI 2 "const_int_operand" "n")
894 (match_operand:SI 3 "const_int_operand" "n"))
896 "INTVAL (operands[2]) > 1
897 && (INTVAL (operands[3]) + INTVAL (operands[2]) <= 11
898 || (INTVAL (operands[3]) <= 11
899 && INTVAL (operands[3]) + INTVAL (operands[2]) == 32))"
900 "tst %1,(1<<%2)-1<<%3"
901 [(set_attr "type" "compare")
902 (set_attr "cond" "set_zn")
903 (set_attr "length" "4")])
905 ; Likewise for asr.f.
906 (define_insn "*tst_bitfield_asr"
907 [(set (match_operand:CC_ZN 0 "cc_set_register" "")
908 (match_operator 4 "zn_compare_operator"
910 (match_operand:SI 1 "register_operand" "c")
911 (match_operand:SI 2 "const_int_operand" "n")
912 (match_operand:SI 3 "const_int_operand" "n"))
914 "INTVAL (operands[2]) > 1
915 && INTVAL (operands[3]) + INTVAL (operands[2]) == 32"
917 [(set_attr "type" "shift")
918 (set_attr "cond" "set_zn")
919 (set_attr "length" "4")])
921 (define_insn "*tst_bitfield"
922 [(set (match_operand:CC_ZN 0 "cc_set_register" "")
923 (match_operator 5 "zn_compare_operator"
925 (match_operand:SI 1 "register_operand" "%Rcqq,c, c,Rrq,c")
926 (match_operand:SI 2 "const_int_operand" "N,N, n,Cbn,n")
927 (match_operand:SI 3 "const_int_operand" "n,n,C_0,Cbn,n"))
929 (clobber (match_scratch:SI 4 "=X,X,X,Rrq,X"))]
935 movb.f.cl %4,%1,%3,%3,%2
936 and.f 0,%1,((1<<%2)-1)<<%3"
937 [(set_attr "iscompact" "maybe,false,false,false,false")
938 (set_attr "type" "compare,compare,compare,shift,compare")
939 (set_attr "cond" "set_zn")
940 (set_attr "length" "*,4,4,4,8")])
942 (define_insn "*commutative_binary_comparison"
943 [(set (match_operand:CC_ZN 0 "cc_set_register" "")
944 (match_operator:CC_ZN 5 "zn_compare_operator"
945 [(match_operator:SI 4 "commutative_operator"
946 [(match_operand:SI 1 "register_operand" "%c,c,c")
947 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
949 (clobber (match_scratch:SI 3 "=X,1,X"))]
952 [(set_attr "type" "compare")
953 (set_attr "cond" "set_zn")
954 (set_attr "length" "4,4,8")])
956 ; for flag setting 'add' instructions like if (a+b) { ...}
957 ; the combiner needs this pattern
958 (define_insn "*addsi_compare"
959 [(set (reg:CC_ZN CC_REG)
960 (compare:CC_ZN (match_operand:SI 0 "register_operand" "c")
961 (neg:SI (match_operand:SI 1 "register_operand" "c"))))]
964 [(set_attr "cond" "set")
965 (set_attr "type" "compare")
966 (set_attr "length" "4")])
968 ; for flag setting 'add' instructions like if (a+b < a) { ...}
969 ; the combiner needs this pattern
970 (define_insn "addsi_compare_2"
971 [(set (reg:CC_C CC_REG)
972 (compare:CC_C (plus:SI (match_operand:SI 0 "register_operand" "c,c")
973 (match_operand:SI 1 "nonmemory_operand" "cL,Cal"))
977 [(set_attr "cond" "set")
978 (set_attr "type" "compare")
979 (set_attr "length" "4,8")])
981 (define_insn "*addsi_compare_3"
982 [(set (reg:CC_C CC_REG)
983 (compare:CC_C (plus:SI (match_operand:SI 0 "register_operand" "c")
984 (match_operand:SI 1 "register_operand" "c"))
988 [(set_attr "cond" "set")
989 (set_attr "type" "compare")
990 (set_attr "length" "4")])
992 ; this pattern is needed by combiner for cases like if (c=a+b) { ... }
993 (define_insn "*commutative_binary_comparison_result_used"
994 [(set (match_operand 3 "cc_register" "")
995 (match_operator 5 "zn_compare_operator"
996 ; We can accept any commutative operator except mult because
997 ; our 'w' class below could try to use LP_COUNT.
998 [(match_operator:SI 4 "commutative_operator_sans_mult"
999 [(match_operand:SI 1 "register_operand" "c,0,c")
1000 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
1002 (set (match_operand:SI 0 "register_operand" "=w,w,w")
1005 "%O4.f %0,%1,%2 ; non-mult commutative"
1006 [(set_attr "type" "compare,compare,compare")
1007 (set_attr "cond" "set_zn,set_zn,set_zn")
1008 (set_attr "length" "4,4,8")])
1010 ; a MULT-specific version of this pattern to avoid touching the
1012 (define_insn "*commutative_binary_mult_comparison_result_used"
1013 [(set (match_operand 3 "cc_register" "")
1014 (match_operator 5 "zn_compare_operator"
1015 [(match_operator:SI 4 "mult_operator"
1016 [(match_operand:SI 1 "register_operand" "c,0,c")
1017 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
1019 ; Make sure to use the W class to not touch LP_COUNT.
1020 (set (match_operand:SI 0 "register_operand" "=W,W,W")
1022 "!TARGET_ARC600_FAMILY"
1023 "%O4.f %0,%1,%2 ; mult commutative"
1024 [(set_attr "type" "compare,compare,compare")
1025 (set_attr "cond" "set_zn,set_zn,set_zn")
1026 (set_attr "length" "4,4,8")])
1028 ; this pattern is needed by combiner for cases like if (c=a<<b) { ... }
1029 (define_insn "*noncommutative_binary_comparison_result_used"
1030 [(set (match_operand 3 "cc_register" "")
1031 (match_operator 5 "zn_compare_operator"
1032 [(match_operator:SI 4 "noncommutative_operator"
1033 [(match_operand:SI 1 "register_operand" "c,0,c")
1034 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
1036 (set (match_operand:SI 0 "register_operand" "=w,w,w")
1038 "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"
1040 [(set_attr "type" "compare,compare,compare")
1041 (set_attr "cond" "set_zn,set_zn,set_zn")
1042 (set_attr "length" "4,4,8")])
1044 (define_insn "*noncommutative_binary_comparison"
1045 [(set (match_operand:CC_ZN 0 "cc_set_register" "")
1046 (match_operator:CC_ZN 5 "zn_compare_operator"
1047 [(match_operator:SI 4 "noncommutative_operator"
1048 [(match_operand:SI 1 "register_operand" "c,c,c")
1049 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
1051 (clobber (match_scratch:SI 3 "=X,1,X"))]
1052 "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"
1054 [(set_attr "type" "compare")
1055 (set_attr "cond" "set_zn")
1056 (set_attr "length" "4,4,8")])
1058 (define_expand "bic_f_zn"
1060 [(set (reg:CC_ZN CC_REG)
1062 (and:SI (match_operand:SI 1 "register_operand" "")
1063 (not:SI (match_operand:SI 2 "nonmemory_operand" "")))
1065 (set (match_operand:SI 0 "register_operand" "")
1066 (and:SI (match_dup 1) (not:SI (match_dup 2))))])]
1069 (define_insn "*bic_f"
1070 [(set (match_operand 3 "cc_register" "=Rcc,Rcc,Rcc")
1071 (match_operator 4 "zn_compare_operator"
1072 [(and:SI (match_operand:SI 1 "register_operand" "c,0,c")
1074 (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")))
1076 (set (match_operand:SI 0 "register_operand" "=w,w,w")
1077 (and:SI (match_dup 1) (not:SI (match_dup 2))))]
1080 [(set_attr "type" "compare,compare,compare")
1081 (set_attr "cond" "set_zn,set_zn,set_zn")
1082 (set_attr "length" "4,4,8")])
1084 (define_expand "movdi"
1085 [(set (match_operand:DI 0 "move_dest_operand" "")
1086 (match_operand:DI 1 "general_operand" ""))]
1090 /* Everything except mem = const or mem = mem can be done easily. */
1092 if (GET_CODE (operands[0]) == MEM)
1093 operands[1] = force_reg (DImode, operands[1]);
1096 (define_insn_and_split "*movdi_insn"
1097 [(set (match_operand:DI 0 "move_dest_operand" "=w, w,r,m")
1098 (match_operand:DI 1 "move_double_src_operand" "c,Hi,m,c"))]
1099 "register_operand (operands[0], DImode)
1100 || register_operand (operands[1], DImode)"
1103 switch (which_alternative)
1110 && ((even_register_operand (operands[0], DImode)
1111 && memory_operand (operands[1], DImode))
1112 || (memory_operand (operands[0], DImode)
1113 && even_register_operand (operands[1], DImode))))
1114 return \"ldd%U1%V1 %0,%1%&\";
1119 && ((even_register_operand (operands[0], DImode)
1120 && memory_operand (operands[1], DImode))
1121 || (memory_operand (operands[0], DImode)
1122 && even_register_operand (operands[1], DImode))))
1123 return \"std%U0%V0 %1,%0\";
1130 arc_split_move (operands);
1133 [(set_attr "type" "move,move,load,store")
1134 ;; ??? The ld/st values could be 4 if it's [reg,bignum].
1135 (set_attr "length" "8,16,*,*")])
1138 ;; Floating point move insns.
1140 (define_expand "movsf"
1141 [(set (match_operand:SF 0 "general_operand" "")
1142 (match_operand:SF 1 "general_operand" ""))]
1144 "if (prepare_move_operands (operands, SFmode)) DONE;")
1146 (define_insn "*movsf_insn"
1147 [(set (match_operand:SF 0 "move_dest_operand" "=h,w,w,r,m")
1148 (match_operand:SF 1 "move_src_operand" "hCm1,c,E,m,c"))]
1149 "register_operand (operands[0], SFmode)
1150 || register_operand (operands[1], SFmode)"
1157 [(set_attr "type" "move,move,move,load,store")
1158 (set_attr "predicable" "no,yes,yes,no,no")
1159 (set_attr "iscompact" "true,false,false,false,false")])
1161 (define_expand "movdf"
1162 [(set (match_operand:DF 0 "nonimmediate_operand" "")
1163 (match_operand:DF 1 "general_operand" ""))]
1165 "if (prepare_move_operands (operands, DFmode)) DONE;")
1167 (define_insn_and_split "*movdf_insn"
1168 [(set (match_operand:DF 0 "move_dest_operand" "=D,r,c,c,r,m")
1169 (match_operand:DF 1 "move_double_src_operand" "r,D,c,E,m,c"))]
1170 "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)"
1173 switch (which_alternative)
1179 && ((even_register_operand (operands[0], DFmode)
1180 && memory_operand (operands[1], DFmode))
1181 || (memory_operand (operands[0], DFmode)
1182 && even_register_operand (operands[1], DFmode))))
1183 return \"ldd%U1%V1 %0,%1%&\";
1188 && ((even_register_operand (operands[0], DFmode)
1189 && memory_operand (operands[1], DFmode))
1190 || (memory_operand (operands[0], DFmode)
1191 && even_register_operand (operands[1], DFmode))))
1192 return \"std%U0%V0 %1,%0\";
1199 arc_split_move (operands);
1202 [(set_attr "type" "move,move,move,move,load,store")
1203 (set_attr "predicable" "no,no,yes,yes,no,no")
1204 ;; ??? The ld/st values could be 16 if it's [reg,bignum].
1205 (set_attr "length" "4,16,8,16,16,16")])
1207 (define_insn_and_split "*movdf_insn_nolrsr"
1208 [(set (match_operand:DF 0 "register_operand" "=r")
1209 (match_operand:DF 1 "arc_double_register_operand" "D"))
1210 (use (match_operand:SI 2 "" "N")) ; aka const1_rtx
1212 "TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR"
1217 (set (match_dup 0) (match_dup 3))
1219 ; daddh?? r1, r0, r0
1221 (set (match_dup 1) (plus:DF (match_dup 1) (match_dup 0)))
1224 (use (match_dup 0)) ; used to block can_combine_p
1225 (set (match_dup 0) (plus:DF (match_dup 1) (match_dup 0))) ; r1 in op 0
1228 ; We have to do this twice, once to read the value into R0 and
1229 ; second time to put back the contents which the first DEXCLx
1230 ; will have overwritten
1232 (set (match_dup 4) ; aka r0result
1234 (unspec_volatile:SI [(match_dup 1) (match_dup 5) (match_dup 4)] VUNSPEC_ARC_DEXCL ))
1235 ; Generate the second, which makes sure operand5 and operand4 values
1236 ; are put back in the Dx register properly.
1237 (unspec_volatile:SI [(match_dup 1) (match_dup 5) (match_dup 4)] VUNSPEC_ARC_DEXCL_NORES )
1239 ; Note: we cannot use a (clobber (match_scratch)) here because
1240 ; the combine pass will end up replacing uses of it with 0
1242 "operands[3] = CONST0_RTX (DFmode);
1243 operands[4] = simplify_gen_subreg (SImode, operands[0], DFmode, 0);
1244 operands[5] = simplify_gen_subreg (SImode, operands[0], DFmode, 4);"
1245 [(set_attr "type" "move")])
1247 ;; Load/Store with update instructions.
1249 ;; Some of these we can get by using pre-decrement or pre-increment, but the
1250 ;; hardware can also do cases where the increment is not the size of the
1253 ;; In all these cases, we use operands 0 and 1 for the register being
1254 ;; incremented because those are the operands that local-alloc will
1255 ;; tie and these are the pair most likely to be tieable (and the ones
1256 ;; that will benefit the most).
1258 ;; We use match_operator here because we need to know whether the memory
1259 ;; object is volatile or not.
1262 ;; Note: loadqi_update has no 16-bit variant
1263 (define_insn "*loadqi_update"
1264 [(set (match_operand:QI 3 "dest_reg_operand" "=r,r")
1265 (match_operator:QI 4 "any_mem_operand"
1266 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1267 (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
1268 (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1269 (plus:SI (match_dup 1) (match_dup 2)))]
1271 "ldb.a%V4 %3,[%0,%S2]"
1272 [(set_attr "type" "load,load")
1273 (set_attr "length" "4,8")])
1275 (define_insn "*load_zeroextendqisi_update"
1276 [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1277 (zero_extend:SI (match_operator:QI 4 "any_mem_operand"
1278 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1279 (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
1280 (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1281 (plus:SI (match_dup 1) (match_dup 2)))]
1283 "ldb.a%V4 %3,[%0,%S2]"
1284 [(set_attr "type" "load,load")
1285 (set_attr "length" "4,8")])
1287 (define_insn "*load_signextendqisi_update"
1288 [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1289 (sign_extend:SI (match_operator:QI 4 "any_mem_operand"
1290 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1291 (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
1292 (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1293 (plus:SI (match_dup 1) (match_dup 2)))]
1295 "ldb.x.a%V4 %3,[%0,%S2]"
1296 [(set_attr "type" "load,load")
1297 (set_attr "length" "4,8")])
1299 (define_insn "*storeqi_update"
1300 [(set (match_operator:QI 4 "any_mem_operand"
1301 [(plus:SI (match_operand:SI 1 "register_operand" "0")
1302 (match_operand:SI 2 "short_immediate_operand" "I"))])
1303 (match_operand:QI 3 "register_operand" "c"))
1304 (set (match_operand:SI 0 "dest_reg_operand" "=w")
1305 (plus:SI (match_dup 1) (match_dup 2)))]
1307 "stb.a%V4 %3,[%0,%2]"
1308 [(set_attr "type" "store")
1309 (set_attr "length" "4")])
1311 ;; ??? pattern may have to be re-written
1312 ;; Note: no 16-bit variant for this pattern
1313 (define_insn "*loadhi_update"
1314 [(set (match_operand:HI 3 "dest_reg_operand" "=r,r")
1315 (match_operator:HI 4 "any_mem_operand"
1316 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1317 (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
1318 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1319 (plus:SI (match_dup 1) (match_dup 2)))]
1321 "ld%_.a%V4 %3,[%0,%S2]"
1322 [(set_attr "type" "load,load")
1323 (set_attr "length" "4,8")])
1325 (define_insn "*load_zeroextendhisi_update"
1326 [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1327 (zero_extend:SI (match_operator:HI 4 "any_mem_operand"
1328 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1329 (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
1330 (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
1331 (plus:SI (match_dup 1) (match_dup 2)))]
1333 "ld%_.a%V4 %3,[%0,%S2]"
1334 [(set_attr "type" "load,load")
1335 (set_attr "length" "4,8")])
1337 ;; Note: no 16-bit variant for this instruction
1338 (define_insn "*load_signextendhisi_update"
1339 [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1340 (sign_extend:SI (match_operator:HI 4 "any_mem_operand"
1341 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1342 (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
1343 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1344 (plus:SI (match_dup 1) (match_dup 2)))]
1346 "ld%_.x.a%V4 %3,[%0,%S2]"
1347 [(set_attr "type" "load,load")
1348 (set_attr "length" "4,8")])
1350 (define_insn "*storehi_update"
1351 [(set (match_operator:HI 4 "any_mem_operand"
1352 [(plus:SI (match_operand:SI 1 "register_operand" "0")
1353 (match_operand:SI 2 "short_immediate_operand" "I"))])
1354 (match_operand:HI 3 "register_operand" "c"))
1355 (set (match_operand:SI 0 "dest_reg_operand" "=w")
1356 (plus:SI (match_dup 1) (match_dup 2)))]
1358 "st%_.a%V4 %3,[%0,%2]"
1359 [(set_attr "type" "store")
1360 (set_attr "length" "4")])
1362 ;; No 16-bit variant for this instruction pattern
1363 (define_insn "*loadsi_update"
1364 [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
1365 (match_operator:SI 4 "any_mem_operand"
1366 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1367 (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
1368 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1369 (plus:SI (match_dup 1) (match_dup 2)))]
1371 "ld.a%V4 %3,[%0,%S2]"
1372 [(set_attr "type" "load,load")
1373 (set_attr "length" "4,8")])
1375 (define_insn "*storesi_update"
1376 [(set (match_operator:SI 4 "any_mem_operand"
1377 [(plus:SI (match_operand:SI 1 "register_operand" "0")
1378 (match_operand:SI 2 "short_immediate_operand" "I"))])
1379 (match_operand:SI 3 "register_operand" "c"))
1380 (set (match_operand:SI 0 "dest_reg_operand" "=w")
1381 (plus:SI (match_dup 1) (match_dup 2)))]
1383 "st.a%V4 %3,[%0,%2]"
1384 [(set_attr "type" "store")
1385 (set_attr "length" "4")])
1387 (define_insn "*loadsf_update"
1388 [(set (match_operand:SF 3 "dest_reg_operand" "=r,r")
1389 (match_operator:SF 4 "any_mem_operand"
1390 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
1391 (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
1392 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1393 (plus:SI (match_dup 1) (match_dup 2)))]
1395 "ld.a%V4 %3,[%0,%S2]"
1396 [(set_attr "type" "load,load")
1397 (set_attr "length" "4,8")])
1399 (define_insn "*storesf_update"
1400 [(set (match_operator:SF 4 "any_mem_operand"
1401 [(plus:SI (match_operand:SI 1 "register_operand" "0")
1402 (match_operand:SI 2 "short_immediate_operand" "I"))])
1403 (match_operand:SF 3 "register_operand" "c"))
1404 (set (match_operand:SI 0 "dest_reg_operand" "=w")
1405 (plus:SI (match_dup 1) (match_dup 2)))]
1407 "st.a%V4 %3,[%0,%2]"
1408 [(set_attr "type" "store")
1409 (set_attr "length" "4")])
1411 ;; Conditional move instructions.
1413 (define_expand "movsicc"
1414 [(set (match_operand:SI 0 "dest_reg_operand" "")
1415 (if_then_else:SI (match_operand 1 "comparison_operator" "")
1416 (match_operand:SI 2 "nonmemory_operand" "")
1417 (match_operand:SI 3 "register_operand" "")))]
1419 "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1422 (define_expand "movdicc"
1423 [(set (match_operand:DI 0 "dest_reg_operand" "")
1424 (if_then_else:DI(match_operand 1 "comparison_operator" "")
1425 (match_operand:DI 2 "nonmemory_operand" "")
1426 (match_operand:DI 3 "register_operand" "")))]
1428 "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1431 (define_expand "movsfcc"
1432 [(set (match_operand:SF 0 "dest_reg_operand" "")
1433 (if_then_else:SF (match_operand 1 "comparison_operator" "")
1434 (match_operand:SF 2 "nonmemory_operand" "")
1435 (match_operand:SF 3 "register_operand" "")))]
1437 "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1439 (define_expand "movdfcc"
1440 [(set (match_operand:DF 0 "dest_reg_operand" "")
1441 (if_then_else:DF (match_operand 1 "comparison_operator" "")
1442 (match_operand:DF 2 "nonmemory_operand" "")
1443 (match_operand:DF 3 "register_operand" "")))]
1445 "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
1447 (define_insn "*movsicc_insn"
1448 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
1449 (if_then_else:SI (match_operator 3 "proper_comparison_operator"
1450 [(match_operand 4 "cc_register" "") (const_int 0)])
1451 (match_operand:SI 1 "nonmemory_operand" "cL,Cal")
1452 (match_operand:SI 2 "register_operand" "0,0")))]
1455 if (rtx_equal_p (operands[1], const0_rtx) && GET_CODE (operands[3]) == NE
1456 && satisfies_constraint_Rcq (operands[0]))
1457 return "sub%?.ne %0,%0,%0";
1458 /* ??? might be good for speed on ARC600 too, *if* properly scheduled. */
1459 if ((optimize_size && (!TARGET_ARC600_FAMILY))
1460 && rtx_equal_p (operands[1], constm1_rtx)
1461 && GET_CODE (operands[3]) == LTU)
1462 return "sbc.cs %0,%0,%0";
1463 return "mov.%d3 %0,%S1";
1465 [(set_attr "type" "cmove,cmove")
1466 (set_attr "length" "4,8")])
1468 ; Try to generate more short moves, and/or less limms, by substituting a
1469 ; conditional move with a conditional sub.
1471 [(set (match_operand:SI 0 "compact_register_operand")
1472 (match_operand:SI 1 "const_int_operand"))
1474 (if_then_else:SI (match_operator 3 "proper_comparison_operator"
1475 [(match_operand 4 "cc_register" "") (const_int 0)])
1476 (match_operand:SI 2 "const_int_operand" "")
1478 "!satisfies_constraint_P (operands[1])
1479 && satisfies_constraint_P (operands[2])
1480 && UNSIGNED_INT6 (INTVAL (operands[2]) - INTVAL (operands[1]))"
1481 [(set (match_dup 0) (match_dup 2))
1485 (plus:SI (match_dup 0) (match_dup 1))))]
1486 "operands[3] = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[3]),
1487 GET_MODE (operands[4])),
1488 VOIDmode, operands[4], const0_rtx);
1489 operands[1] = GEN_INT (INTVAL (operands[1]) - INTVAL (operands[2]));")
1491 (define_insn "*movdicc_insn"
1492 [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w")
1493 (if_then_else:DI (match_operator 3 "proper_comparison_operator"
1494 [(match_operand 4 "cc_register" "") (const_int 0)])
1495 (match_operand:DI 1 "nonmemory_operand" "c,i")
1496 (match_operand:DI 2 "register_operand" "0,0")))]
1500 switch (which_alternative)
1504 /* We normally copy the low-numbered register first. However, if
1505 the first register operand 0 is the same as the second register of
1506 operand 1, we must copy in the opposite order. */
1507 if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
1508 return \"mov.%d3 %R0,%R1\;mov.%d3 %0,%1\";
1510 return \"mov.%d3 %0,%1\;mov.%d3 %R0,%R1\";
1512 return \"mov.%d3 %L0,%L1\;mov.%d3 %H0,%H1\";
1517 [(set_attr "type" "cmove,cmove")
1518 (set_attr "length" "8,16")])
1521 (define_insn "*movsfcc_insn"
1522 [(set (match_operand:SF 0 "dest_reg_operand" "=w,w")
1523 (if_then_else:SF (match_operator 3 "proper_comparison_operator"
1524 [(match_operand 4 "cc_register" "") (const_int 0)])
1525 (match_operand:SF 1 "nonmemory_operand" "c,E")
1526 (match_operand:SF 2 "register_operand" "0,0")))]
1530 mov.%d3 %0,%1 ; %A1"
1531 [(set_attr "type" "cmove,cmove")])
1533 (define_insn "*movdfcc_insn"
1534 [(set (match_operand:DF 0 "dest_reg_operand" "=w,w")
1535 (if_then_else:DF (match_operator 1 "proper_comparison_operator"
1536 [(match_operand 4 "cc_register" "") (const_int 0)])
1537 (match_operand:DF 2 "nonmemory_operand" "c,E")
1538 (match_operand:DF 3 "register_operand" "0,0")))]
1542 switch (which_alternative)
1546 /* We normally copy the low-numbered register first. However, if
1547 the first register operand 0 is the same as the second register of
1548 operand 1, we must copy in the opposite order. */
1549 if (REGNO (operands[0]) == REGNO (operands[2]) + 1)
1550 return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\";
1552 return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\";
1554 return \"mov.%d1 %L0,%L2\;mov.%d1 %H0,%H2; %A2 \";
1558 [(set_attr "type" "cmove,cmove")
1559 (set_attr "length" "8,16")])
1562 (define_insn "*zero_extendqihi2_i"
1563 [(set (match_operand:HI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,r,r")
1564 (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,Ucm,m")))]
1573 [(set_attr "type" "unary,unary,unary,unary,load,load")
1574 (set_attr "iscompact" "maybe,true,false,false,false,false")
1575 (set_attr "predicable" "no,no,yes,no,no,no")])
1577 (define_expand "zero_extendqihi2"
1578 [(set (match_operand:HI 0 "dest_reg_operand" "")
1579 (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1581 "if (prepare_extend_operands (operands, ZERO_EXTEND, HImode)) DONE;"
1584 (define_insn "*zero_extendqisi2_ac"
1585 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,qRcq,!*x,r,r")
1586 (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,T,Usd,Ucm,m")))]
1597 [(set_attr "type" "unary,unary,unary,unary,load,load,load,load")
1598 (set_attr "iscompact" "maybe,true,false,false,true,true,false,false")
1599 (set_attr "predicable" "no,no,yes,no,no,no,no,no")])
1601 (define_expand "zero_extendqisi2"
1602 [(set (match_operand:SI 0 "dest_reg_operand" "")
1603 (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1605 "if (prepare_extend_operands (operands, ZERO_EXTEND, SImode)) DONE;"
1608 (define_insn "*zero_extendhisi2_i"
1609 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,q,Rcw,w,!x,Rcqq,r,r")
1610 (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "0,q,0,c,Usd,Usd,Ucm,m")))]
1619 * return TARGET_EM ? \"xldh%U1%V1 %0,%1\" : \"xldw%U1 %0,%1\";
1621 [(set_attr "type" "unary,unary,unary,unary,load,load,load,load")
1622 (set_attr "iscompact" "maybe,true,false,false,true,false,false,false")
1623 (set_attr "predicable" "no,no,yes,no,no,no,no,no")])
1626 (define_expand "zero_extendhisi2"
1627 [(set (match_operand:SI 0 "dest_reg_operand" "")
1628 (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "")))]
1630 "if (prepare_extend_operands (operands, ZERO_EXTEND, SImode)) DONE;"
1633 ;; Sign extension instructions.
1635 (define_insn "*extendqihi2_i"
1636 [(set (match_operand:HI 0 "dest_reg_operand" "=Rcqq,r,r,r")
1637 (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,r,Uex,m")))]
1644 [(set_attr "type" "unary,unary,load,load")
1645 (set_attr "iscompact" "true,false,false,false")
1646 (set_attr "length" "*,*,*,8")])
1649 (define_expand "extendqihi2"
1650 [(set (match_operand:HI 0 "dest_reg_operand" "")
1651 (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1653 "if (prepare_extend_operands (operands, SIGN_EXTEND, HImode)) DONE;"
1656 (define_insn "*extendqisi2_ac"
1657 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r,r")
1658 (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,c,Uex,m")))]
1665 [(set_attr "type" "unary,unary,load,load")
1666 (set_attr "iscompact" "true,false,false,false")
1667 (set_attr "length" "*,*,*,8")])
1669 (define_expand "extendqisi2"
1670 [(set (match_operand:SI 0 "dest_reg_operand" "")
1671 (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
1673 "if (prepare_extend_operands (operands, SIGN_EXTEND, SImode)) DONE;"
1676 (define_insn "*extendhisi2_i"
1677 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,Rcq,r,r")
1678 (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,Ucd,Uex,m")))]
1686 [(set_attr "type" "unary,unary,load,load,load")
1687 (set_attr "iscompact" "true,false,true,false,false")
1688 (set_attr "length" "*,*,*,4,8")])
1690 (define_expand "extendhisi2"
1691 [(set (match_operand:SI 0 "dest_reg_operand" "")
1692 (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "")))]
1694 "if (prepare_extend_operands (operands, SIGN_EXTEND, SImode)) DONE;"
1697 ;; Unary arithmetic insns
1699 ;; We allow constant operands to enable late constant propagation, but it is
1700 ;; not worth while to have more than one dedicated alternative to output them -
1701 ;; if we are really worried about getting these the maximum benefit of all
1702 ;; the available alternatives, we should add an extra pass to fold such
1703 ;; operations to movsi.
1705 ;; Absolute instructions
1707 (define_insn "*abssi2_mixed"
1708 [(set (match_operand:SI 0 "compact_register_operand" "=q")
1709 (abs:SI (match_operand:SI 1 "compact_register_operand" "q")))]
1712 [(set_attr "type" "two_cycle_core")
1713 (set_attr "iscompact" "true")])
1715 (define_insn "abssi2"
1716 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,w,w")
1717 (abs:SI (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,Cal")))]
1720 [(set_attr "type" "two_cycle_core")
1721 (set_attr "length" "*,4,8")
1722 (set_attr "iscompact" "true,false,false")])
1724 ;; Maximum and minimum insns
1726 (define_insn "smaxsi3"
1727 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w")
1728 (smax:SI (match_operand:SI 1 "register_operand" "%0, c, c")
1729 (match_operand:SI 2 "nonmemory_operand" "cL,cL,Cal")))]
1732 [(set_attr "type" "two_cycle_core")
1733 (set_attr "length" "4,4,8")
1734 (set_attr "predicable" "yes,no,no")]
1737 (define_insn "sminsi3"
1738 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w")
1739 (smin:SI (match_operand:SI 1 "register_operand" "%0, c, c")
1740 (match_operand:SI 2 "nonmemory_operand" "cL,cL,Cal")))]
1743 [(set_attr "type" "two_cycle_core")
1744 (set_attr "length" "4,4,8")
1745 (set_attr "predicable" "yes,no,no")]
1748 ;; Arithmetic instructions.
1750 ; We say an insn can be conditionalized if this doesn't introduce a long
1751 ; immediate. We set the type such that we still have good scheduling if the
1752 ; insn is conditionalized.
1753 ; ??? It would make sense to allow introduction of long immediates, but
1754 ; we'd need to communicate to the ccfsm machinery the extra cost.
1755 ; The alternatives in the constraints still serve three purposes:
1756 ; - estimate insn size assuming conditional execution
1757 ; - guide reload to re-order the second and third operand to get a better fit.
1758 ; - give tentative insn type to guide scheduling
1759 ; N.B. "%" for commutativity doesn't help when there is another matching
1760 ; (but longer) alternative.
1761 ; We avoid letting this pattern use LP_COUNT as a register by specifying
1762 ; register class 'W' instead of 'w'.
1763 (define_insn_and_split "*addsi3_mixed"
1764 ;; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10
1765 [(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")
1766 (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")
1767 (match_operand:SI 2 "nonmemory_operand" "cL, 0, cL, 0,CL2,Csp,CM4,cCca,RcqqK, cO,cLCmL,Cca,I,C2a, Cal,Cal,Cal")))]
1770 arc_output_addsi (operands, arc_ccfsm_cond_exec_p (), true);
1773 "&& reload_completed && get_attr_length (insn) == 8
1774 && satisfies_constraint_I (operands[2])
1775 && GET_CODE (PATTERN (insn)) != COND_EXEC"
1776 [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))]
1777 "split_addsi (operands);"
1778 [(set_attr "type" "*,*,*,*,two_cycle_core,two_cycle_core,*,two_cycle_core,*,*,*,two_cycle_core,*,two_cycle_core,*,*,*")
1779 (set (attr "iscompact")
1780 (cond [(match_test "~arc_output_addsi (operands, false, false) & 2")
1781 (const_string "false")
1782 (match_operand 2 "long_immediate_operand" "")
1783 (const_string "maybe_limm")]
1784 (const_string "maybe")))
1785 (set_attr "length" "*,*,4,4,*,*,*,4,*,*,4,4,4,4,*,8,8")
1786 (set_attr "predicable" "no,no,yes,yes,no,no,no,yes,no,no,no,no,no,no,no,yes,no")
1787 (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,nocond,canuse,nocond,nocond,nocond,nocond,canuse_limm,canuse_limm,canuse,canuse,nocond")
1790 ;; ARCv2 MPYW and MPYUW
1791 (define_expand "mulhisi3"
1792 [(set (match_operand:SI 0 "register_operand" "")
1793 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" ""))
1794 (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" ""))))]
1797 if (CONSTANT_P (operands[2]))
1799 emit_insn (gen_mulhisi3_imm (operands[0], operands[1], operands[2]));
1805 (define_insn "mulhisi3_imm"
1806 [(set (match_operand:SI 0 "register_operand" "=r,r,r, r, r")
1807 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "0,r,0, 0, r"))
1808 (match_operand:HI 2 "short_const_int_operand" "L,L,I,C16,C16")))]
1811 [(set_attr "length" "4,4,4,8,8")
1812 (set_attr "iscompact" "false")
1813 (set_attr "type" "mul16_em")
1814 (set_attr "predicable" "yes,no,no,yes,no")
1815 (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")
1818 (define_insn "mulhisi3_reg"
1819 [(set (match_operand:SI 0 "register_operand" "=Rcqq,r,r")
1820 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" " 0,0,r"))
1821 (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" "Rcqq,r,r"))))]
1824 [(set_attr "length" "*,4,4")
1825 (set_attr "iscompact" "maybe,false,false")
1826 (set_attr "type" "mul16_em")
1827 (set_attr "predicable" "yes,yes,no")
1828 (set_attr "cond" "canuse,canuse,nocond")
1831 (define_expand "umulhisi3"
1832 [(set (match_operand:SI 0 "register_operand" "")
1833 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" ""))
1834 (zero_extend:SI (match_operand:HI 2 "arc_short_operand" ""))))]
1837 if (CONSTANT_P (operands[2]))
1839 emit_insn (gen_umulhisi3_imm (operands[0], operands[1], operands[2]));
1845 (define_insn "umulhisi3_imm"
1846 [(set (match_operand:SI 0 "register_operand" "=r, r, r, r, r")
1847 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0, r, 0, 0, r"))
1848 (match_operand:HI 2 "short_unsigned_const_operand" " L, L,J12,J16,J16")))]
1851 [(set_attr "length" "4,4,4,8,8")
1852 (set_attr "iscompact" "false")
1853 (set_attr "type" "mul16_em")
1854 (set_attr "predicable" "yes,no,no,yes,no")
1855 (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")
1858 (define_insn "umulhisi3_reg"
1859 [(set (match_operand:SI 0 "register_operand" "=Rcqq, r, r")
1860 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" " %0, 0, r"))
1861 (zero_extend:SI (match_operand:HI 2 "register_operand" " Rcqq, r, r"))))]
1864 [(set_attr "length" "*,4,4")
1865 (set_attr "iscompact" "maybe,false,false")
1866 (set_attr "type" "mul16_em")
1867 (set_attr "predicable" "yes,yes,no")
1868 (set_attr "cond" "canuse,canuse,nocond")
1871 ;; ARC700/ARC600/V2 multiply
1874 (define_expand "mulsi3"
1875 [(set (match_operand:SI 0 "nonimmediate_operand" "")
1876 (mult:SI (match_operand:SI 1 "register_operand" "")
1877 (match_operand:SI 2 "nonmemory_operand" "")))]
1882 if (!register_operand (operands[0], SImode))
1884 rtx result = gen_reg_rtx (SImode);
1886 emit_insn (gen_mulsi3 (result, operands[1], operands[2]));
1887 emit_move_insn (operands[0], result);
1891 else if (TARGET_MUL64_SET)
1893 emit_insn (gen_mulsi_600 (operands[1], operands[2],
1894 gen_mlo (), gen_mhi ()));
1895 emit_move_insn (operands[0], gen_mlo ());
1898 else if (TARGET_MULMAC_32BY16_SET)
1900 if (immediate_operand (operands[2], SImode)
1901 && INTVAL (operands[2]) >= 0
1902 && INTVAL (operands[2]) <= 65535)
1904 emit_insn (gen_umul_600 (operands[1], operands[2],
1905 gen_acc2 (), gen_acc1 ()));
1906 emit_move_insn (operands[0], gen_acc2 ());
1909 operands[2] = force_reg (SImode, operands[2]);
1910 emit_insn (gen_umul_600 (operands[1], operands[2],
1911 gen_acc2 (), gen_acc1 ()));
1912 emit_insn (gen_mac_600 (operands[1], operands[2],
1913 gen_acc2 (), gen_acc1 ()));
1914 emit_move_insn (operands[0], gen_acc2 ());
1919 emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
1920 emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
1921 emit_insn (gen_mulsi3_600_lib ());
1922 emit_move_insn (operands[0], gen_rtx_REG (SImode, R0_REG));
1927 ; mululw conditional execution without a LIMM clobbers an input register;
1928 ; we'd need a different pattern to describe this.
1929 ; To make the conditional execution valid for the LIMM alternative, we
1930 ; have to emit the LIMM before the register operand.
1931 (define_insn "umul_600"
1932 [(set (match_operand:SI 2 "acc2_operand" "")
1933 (mult:SI (match_operand:SI 0 "register_operand" "c,c,c")
1934 (zero_extract:SI (match_operand:SI 1 "nonmemory_operand"
1938 (clobber (match_operand:SI 3 "acc1_operand" ""))]
1939 "TARGET_MULMAC_32BY16_SET"
1943 [(set_attr "length" "4,4,8")
1944 (set_attr "type" "mulmac_600, mulmac_600, mulmac_600")
1945 (set_attr "predicable" "no, no, yes")
1946 (set_attr "cond" "nocond, canuse_limm, canuse")])
1948 (define_insn "mac_600"
1949 [(set (match_operand:SI 2 "acc2_operand" "")
1951 (mult:SI (match_operand:SI 0 "register_operand" "c,c,c")
1953 (zero_extract:SI (match_operand:SI 1 "nonmemory_operand" "c,L,Cal")
1958 (clobber (match_operand:SI 3 "acc1_operand" ""))]
1959 "TARGET_MULMAC_32BY16_SET"
1960 "machlw%? 0, %0, %1"
1961 [(set_attr "length" "4,4,8")
1962 (set_attr "type" "mulmac_600, mulmac_600, mulmac_600")
1963 (set_attr "predicable" "no, no, yes")
1964 (set_attr "cond" "nocond, canuse_limm, canuse")])
1966 (define_insn "mulsi_600"
1967 [(set (match_operand:SI 2 "mlo_operand" "")
1968 (mult:SI (match_operand:SI 0 "register_operand" "%Rcq#q,c,c,c")
1969 (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,I,Cal")))
1970 (clobber (match_operand:SI 3 "mhi_operand" ""))]
1972 ; The assembler mis-assembles mul64 / mulu64 with "I" constraint constants,
1973 ; using a machine code pattern that only allows "L" constraint constants.
1974 ; "mul64%? \t0, %0, %1%&"
1976 if (satisfies_constraint_I (operands[1])
1977 && !satisfies_constraint_L (operands[1]))
1979 /* MUL64 <0,>b,s12 00101bbb10000100 0BBBssssssSSSSSS */
1980 int n = true_regnum (operands[0]);
1981 int i = INTVAL (operands[1]);
1982 asm_fprintf (asm_out_file, "\t.short %d`", 0x2884 + ((n & 7) << 8));
1983 asm_fprintf (asm_out_file, "\t.short %d`",
1984 ((i & 0x3f) << 6) + ((i >> 6) & 0x3f) + ((n & 070) << 9));
1985 return "; mul64%? \t0, %0, %1%&";
1987 return "mul64%? \t0, %0, %1%&";
1989 [(set_attr "length" "*,4,4,8")
1990 (set_attr "iscompact" "maybe,false,false,false")
1991 (set_attr "type" "multi,multi,multi,multi")
1992 (set_attr "predicable" "yes,yes,no,yes")
1993 (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
1995 ; If we compile without an mul option enabled, but link with libraries
1996 ; for a mul option, we'll see clobbers of multiplier output registers.
1997 ; There is also an implementation using norm that clobbers the loop registers.
1998 (define_insn "mulsi3_600_lib"
1999 [(set (reg:SI R0_REG)
2000 (mult:SI (reg:SI R0_REG) (reg:SI R1_REG)))
2001 (clobber (reg:SI RETURN_ADDR_REGNUM))
2002 (clobber (reg:SI R1_REG))
2003 (clobber (reg:SI R2_REG))
2004 (clobber (reg:SI R3_REG))
2005 (clobber (reg:DI MUL64_OUT_REG))
2006 (clobber (reg:SI LP_COUNT))
2007 (clobber (reg:SI LP_START))
2008 (clobber (reg:SI LP_END))
2009 (clobber (reg:CC CC_REG))]
2011 && SFUNC_CHECK_PREDICABLE"
2012 "*return arc_output_libcall (\"__mulsi3\");"
2013 [(set_attr "is_sfunc" "yes")
2014 (set_attr "predicable" "yes")])
2016 (define_insn "mulsidi_600"
2017 [(set (reg:DI MUL64_OUT_REG)
2018 (mult:DI (sign_extend:DI
2019 (match_operand:SI 0 "register_operand" "%Rcq#q,c,c,c"))
2021 ; assembler issue for "I", see mulsi_600
2022 ; (match_operand:SI 1 "register_operand" "Rcq#q,cL,I,Cal"))))]
2023 (match_operand:SI 1 "register_operand" "Rcq#q,cL,L,C32"))))]
2025 "mul64%? \t0, %0, %1%&"
2026 [(set_attr "length" "*,4,4,8")
2027 (set_attr "iscompact" "maybe,false,false,false")
2028 (set_attr "type" "multi,multi,multi,multi")
2029 (set_attr "predicable" "yes,yes,no,yes")
2030 (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
2032 (define_insn "umulsidi_600"
2033 [(set (reg:DI MUL64_OUT_REG)
2034 (mult:DI (zero_extend:DI
2035 (match_operand:SI 0 "register_operand" "%c,c,c"))
2037 ; assembler issue for "I", see mulsi_600
2038 ; (match_operand:SI 1 "register_operand" "cL,I,Cal"))))]
2039 (match_operand:SI 1 "register_operand" "cL,L,C32"))))]
2041 "mulu64%? \t0, %0, %1%&"
2042 [(set_attr "length" "4,4,8")
2043 (set_attr "iscompact" "false")
2044 (set_attr "type" "umulti")
2045 (set_attr "predicable" "yes,no,yes")
2046 (set_attr "cond" "canuse,canuse_limm,canuse")])
2048 ; ARC700 mpy* instructions: This is a multi-cycle extension, and thus 'w'
2049 ; may not be used as destination constraint.
2051 ; The result of mpy and mpyu is the same except for flag setting (if enabled),
2052 ; but mpyu is faster for the standard multiplier.
2053 ; Note: we must make sure LP_COUNT is not one of the destination
2054 ; registers, since it cannot be the destination of a multi-cycle insn
2056 (define_insn "mulsi3_700"
2057 [(set (match_operand:SI 0 "mpy_dest_reg_operand" "=Rcr,r,r,Rcr,r")
2058 (mult:SI (match_operand:SI 1 "register_operand" " 0,c,0,0,c")
2059 (match_operand:SI 2 "nonmemory_operand" "cL,cL,I,Cal,Cal")))]
2062 [(set_attr "length" "4,4,4,8,8")
2063 (set_attr "type" "umulti")
2064 (set_attr "predicable" "yes,no,no,yes,no")
2065 (set_attr "cond" "canuse,nocond,canuse_limm,canuse,nocond")])
2067 ; ARCv2 has no penalties between mpy and mpyu. So, we use mpy because of its
2068 ; short variant. LP_COUNT constraints are still valid.
2069 (define_insn "mulsi3_v2"
2070 [(set (match_operand:SI 0 "mpy_dest_reg_operand" "=Rcqq,Rcr, r,r,Rcr, r")
2071 (mult:SI (match_operand:SI 1 "register_operand" "%0, 0, c,0, 0, c")
2072 (match_operand:SI 2 "nonmemory_operand" " Rcqq, cL,cL,I,Cal,Cal")))]
2075 [(set_attr "length" "*,4,4,4,8,8")
2076 (set_attr "iscompact" "maybe,false,false,false,false,false")
2077 (set_attr "type" "umulti")
2078 (set_attr "predicable" "no,yes,no,no,yes,no")
2079 (set_attr "cond" "nocond,canuse,nocond,canuse_limm,canuse,nocond")])
2081 (define_expand "mulsidi3"
2082 [(set (match_operand:DI 0 "register_operand" "")
2083 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
2084 (sign_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))]
2090 operands[2] = force_reg (SImode, operands[2]);
2091 if (!register_operand (operands[0], DImode))
2093 rtx result = gen_reg_rtx (DImode);
2095 operands[2] = force_reg (SImode, operands[2]);
2096 emit_insn (gen_mulsidi3 (result, operands[1], operands[2]));
2097 emit_move_insn (operands[0], result);
2101 else if (TARGET_MUL64_SET)
2103 operands[2] = force_reg (SImode, operands[2]);
2104 emit_insn (gen_mulsidi_600 (operands[1], operands[2]));
2105 emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
2108 else if (TARGET_MULMAC_32BY16_SET)
2110 rtx result_hi = gen_highpart(SImode, operands[0]);
2111 rtx result_low = gen_lowpart(SImode, operands[0]);
2113 emit_insn (gen_mul64_600 (operands[1], operands[2]));
2114 emit_insn (gen_mac64_600 (result_hi, operands[1], operands[2]));
2115 emit_move_insn (result_low, gen_acc2 ());
2120 (define_insn "mul64_600"
2122 (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand"
2124 (zero_extract:DI (match_operand:SI 1 "nonmemory_operand"
2129 "TARGET_MULMAC_32BY16_SET"
2131 [(set_attr "length" "4,4,8")
2132 (set_attr "type" "mulmac_600")
2133 (set_attr "predicable" "no,no,yes")
2134 (set_attr "cond" "nocond, canuse_limm, canuse")])
2137 ;; ??? check if this is canonical rtl
2138 (define_insn "mac64_600"
2141 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "c,c,c"))
2143 (sign_extract:DI (match_operand:SI 2 "nonmemory_operand" "c,L,Cal")
2144 (const_int 16) (const_int 16))
2147 (set (match_operand:SI 0 "register_operand" "=w,w,w")
2150 (mult:DI (sign_extend:DI (match_dup 1))
2152 (sign_extract:DI (match_dup 2)
2153 (const_int 16) (const_int 16))
2156 (const_int 32) (const_int 32)))]
2157 "TARGET_MULMAC_32BY16_SET"
2158 "machlw%? %0, %1, %2"
2159 [(set_attr "length" "4,4,8")
2160 (set_attr "type" "mulmac_600")
2161 (set_attr "predicable" "no,no,yes")
2162 (set_attr "cond" "nocond, canuse_limm, canuse")])
2165 ;; DI <- DI(signed SI) * DI(signed SI)
2166 (define_insn_and_split "mulsidi3_700"
2167 [(set (match_operand:DI 0 "register_operand" "=&r")
2168 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%c"))
2169 (sign_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))]
2172 "&& reload_completed"
2175 int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
2176 int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
2177 rtx l0 = simplify_gen_subreg (word_mode, operands[0], DImode, lo);
2178 rtx h0 = simplify_gen_subreg (word_mode, operands[0], DImode, hi);
2179 emit_insn (gen_mulsi3_highpart (h0, operands[1], operands[2]));
2180 emit_insn (gen_mulsi3 (l0, operands[1], operands[2]));
2183 [(set_attr "type" "multi")
2184 (set_attr "length" "8")])
2186 (define_insn "mulsi3_highpart"
2187 [(set (match_operand:SI 0 "register_operand" "=Rcr,r,Rcr,r")
2191 (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,c, 0,c"))
2192 (sign_extend:DI (match_operand:SI 2 "extend_operand" "c,c, i,i")))
2196 [(set_attr "length" "4,4,8,8")
2197 (set_attr "type" "multi")
2198 (set_attr "predicable" "yes,no,yes,no")
2199 (set_attr "cond" "canuse,nocond,canuse,nocond")])
2201 ; Note that mpyhu has the same latency as mpy / mpyh,
2202 ; thus we use the type multi.
2203 (define_insn "*umulsi3_highpart_i"
2204 [(set (match_operand:SI 0 "register_operand" "=Rcr,r,Rcr,r")
2208 (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,c, 0,c"))
2209 (zero_extend:DI (match_operand:SI 2 "extend_operand" "c,c, i,i")))
2213 [(set_attr "length" "4,4,8,8")
2214 (set_attr "type" "multi")
2215 (set_attr "predicable" "yes,no,yes,no")
2216 (set_attr "cond" "canuse,nocond,canuse,nocond")])
2218 ; Implementations include additional labels for umulsidi3, so we got all
2219 ; the same clobbers - plus one for the result low part. */
2220 (define_insn "umulsi3_highpart_600_lib_le"
2221 [(set (reg:SI R1_REG)
2224 (mult:DI (zero_extend:DI (reg:SI R0_REG))
2225 (zero_extend:DI (reg:SI R1_REG)))
2227 (clobber (reg:SI RETURN_ADDR_REGNUM))
2228 (clobber (reg:SI R0_REG))
2229 (clobber (reg:DI R2_REG))
2230 (clobber (reg:SI R12_REG))
2231 (clobber (reg:DI MUL64_OUT_REG))
2232 (clobber (reg:CC CC_REG))]
2235 && SFUNC_CHECK_PREDICABLE"
2236 "*return arc_output_libcall (\"__umulsi3_highpart\");"
2237 [(set_attr "is_sfunc" "yes")
2238 (set_attr "predicable" "yes")])
2240 (define_insn "umulsi3_highpart_600_lib_be"
2241 [(set (reg:SI R0_REG)
2244 (mult:DI (zero_extend:DI (reg:SI R0_REG))
2245 (zero_extend:DI (reg:SI R1_REG)))
2247 (clobber (reg:SI RETURN_ADDR_REGNUM))
2248 (clobber (reg:SI R1_REG))
2249 (clobber (reg:DI R2_REG))
2250 (clobber (reg:SI R12_REG))
2251 (clobber (reg:DI MUL64_OUT_REG))
2252 (clobber (reg:CC CC_REG))]
2255 && SFUNC_CHECK_PREDICABLE"
2256 "*return arc_output_libcall (\"__umulsi3_highpart\");"
2257 [(set_attr "is_sfunc" "yes")
2258 (set_attr "predicable" "yes")])
2260 ;; (zero_extend:DI (const_int)) leads to internal errors in combine, so we
2261 ;; need a separate pattern for immediates
2262 ;; ??? This is fine for combine, but not for reload.
2263 (define_insn "umulsi3_highpart_int"
2264 [(set (match_operand:SI 0 "register_operand" "=Rcr, r, r,Rcr, r")
2268 (zero_extend:DI (match_operand:SI 1 "register_operand" " 0, c, 0, 0, c"))
2269 (match_operand:DI 2 "immediate_usidi_operand" "L, L, I, Cal, Cal"))
2273 [(set_attr "length" "4,4,4,8,8")
2274 (set_attr "type" "multi")
2275 (set_attr "predicable" "yes,no,no,yes,no")
2276 (set_attr "cond" "canuse,nocond,canuse_limm,canuse,nocond")])
2278 (define_expand "umulsi3_highpart"
2279 [(set (match_operand:SI 0 "general_operand" "")
2283 (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
2284 (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" "")))
2286 "!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET"
2289 rtx target = operands[0];
2293 emit_move_insn (gen_rtx_REG (SImode, 0), operands[1]);
2294 emit_move_insn (gen_rtx_REG (SImode, 1), operands[2]);
2295 if (TARGET_BIG_ENDIAN)
2296 emit_insn (gen_umulsi3_highpart_600_lib_be ());
2298 emit_insn (gen_umulsi3_highpart_600_lib_le ());
2299 emit_move_insn (target, gen_rtx_REG (SImode, 0));
2303 if (!register_operand (target, SImode))
2304 target = gen_reg_rtx (SImode);
2306 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
2307 operands[2] = simplify_const_unary_operation (ZERO_EXTEND, DImode,
2308 operands[2], SImode);
2309 else if (!immediate_operand (operands[2], SImode))
2310 operands[2] = gen_rtx_ZERO_EXTEND (DImode, operands[2]);
2311 emit_insn (gen_umulsi3_highpart_int (target, operands[1], operands[2]));
2312 if (target != operands[0])
2313 emit_move_insn (operands[0], target);
2317 (define_expand "umulsidi3"
2318 [(set (match_operand:DI 0 "register_operand" "")
2319 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
2320 (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))]
2325 operands[2] = force_reg (SImode, operands[2]);
2326 if (!register_operand (operands[0], DImode))
2328 rtx result = gen_reg_rtx (DImode);
2330 emit_insn (gen_umulsidi3 (result, operands[1], operands[2]));
2331 emit_move_insn (operands[0], result);
2335 else if (TARGET_MUL64_SET)
2337 operands[2] = force_reg (SImode, operands[2]);
2338 emit_insn (gen_umulsidi_600 (operands[1], operands[2]));
2339 emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
2342 else if (TARGET_MULMAC_32BY16_SET)
2344 rtx result_hi = gen_reg_rtx (SImode);
2345 rtx result_low = gen_reg_rtx (SImode);
2347 result_hi = gen_highpart(SImode , operands[0]);
2348 result_low = gen_lowpart(SImode , operands[0]);
2350 emit_insn (gen_umul64_600 (operands[1], operands[2]));
2351 emit_insn (gen_umac64_600 (result_hi, operands[1], operands[2]));
2352 emit_move_insn (result_low, gen_acc2 ());
2357 emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
2358 emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
2359 emit_insn (gen_umulsidi3_600_lib ());
2360 emit_move_insn (operands[0], gen_rtx_REG (DImode, R0_REG));
2365 (define_insn "umul64_600"
2367 (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand"
2369 (zero_extract:DI (match_operand:SI 1 "nonmemory_operand"
2374 "TARGET_MULMAC_32BY16_SET"
2378 [(set_attr "length" "4,4,8")
2379 (set_attr "type" "mulmac_600")
2380 (set_attr "predicable" "no,no,yes")
2381 (set_attr "cond" "nocond, canuse_limm, canuse")])
2384 (define_insn "umac64_600"
2387 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "c,c,c"))
2389 (zero_extract:DI (match_operand:SI 2 "nonmemory_operand" "c,L,Cal")
2390 (const_int 16) (const_int 16))
2393 (set (match_operand:SI 0 "register_operand" "=w,w,w")
2396 (mult:DI (zero_extend:DI (match_dup 1))
2398 (zero_extract:DI (match_dup 2)
2399 (const_int 16) (const_int 16))
2402 (const_int 32) (const_int 32)))]
2403 "TARGET_MULMAC_32BY16_SET"
2404 "machulw%? %0, %1, %2"
2405 [(set_attr "length" "4,4,8")
2406 (set_attr "type" "mulmac_600")
2407 (set_attr "predicable" "no,no,yes")
2408 (set_attr "cond" "nocond, canuse_limm, canuse")])
2412 ;; DI <- DI(unsigned SI) * DI(unsigned SI)
2413 (define_insn_and_split "umulsidi3_700"
2414 [(set (match_operand:DI 0 "dest_reg_operand" "=&r")
2415 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%c"))
2416 (zero_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))]
2422 int hi = !TARGET_BIG_ENDIAN;
2424 rtx l0 = operand_subword (operands[0], lo, 0, DImode);
2425 rtx h0 = operand_subword (operands[0], hi, 0, DImode);
2426 emit_insn (gen_umulsi3_highpart (h0, operands[1], operands[2]));
2427 emit_insn (gen_mulsi3 (l0, operands[1], operands[2]));
2430 [(set_attr "type" "umulti")
2431 (set_attr "length" "8")])
2433 (define_insn "umulsidi3_600_lib"
2434 [(set (reg:DI R0_REG)
2435 (mult:DI (zero_extend:DI (reg:SI R0_REG))
2436 (zero_extend:DI (reg:SI R1_REG))))
2437 (clobber (reg:SI RETURN_ADDR_REGNUM))
2438 (clobber (reg:DI R2_REG))
2439 (clobber (reg:SI R12_REG))
2440 (clobber (reg:DI MUL64_OUT_REG))
2441 (clobber (reg:CC CC_REG))]
2443 && SFUNC_CHECK_PREDICABLE"
2444 "*return arc_output_libcall (\"__umulsidi3\");"
2445 [(set_attr "is_sfunc" "yes")
2446 (set_attr "predicable" "yes")])
2450 [(set (reg:DI R0_REG)
2451 (mult:DI (zero_extend:DI (reg:SI R0_REG))
2452 (zero_extend:DI (reg:SI R1_REG))))
2453 (clobber (reg:SI RETURN_ADDR_REGNUM))
2454 (clobber (reg:DI R2_REG))
2455 (clobber (reg:SI R12_REG))
2456 (clobber (reg:DI MUL64_OUT_REG))
2457 (clobber (reg:CC CC_REG))])]
2459 && peep2_regno_dead_p (1, TARGET_BIG_ENDIAN ? R1_REG : R0_REG)"
2462 if (TARGET_BIG_ENDIAN)
2463 emit_insn (gen_umulsi3_highpart_600_lib_be ());
2465 emit_insn (gen_umulsi3_highpart_600_lib_le ());
2469 (define_expand "addsi3"
2470 [(set (match_operand:SI 0 "dest_reg_operand" "")
2471 (plus:SI (match_operand:SI 1 "register_operand" "")
2472 (match_operand:SI 2 "nonmemory_operand" "")))]
2474 "if (flag_pic && arc_raw_symbolic_reference_mentioned_p (operands[2], false))
2476 operands[2]=force_reg(SImode, operands[2]);
2478 else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[2], Pmode))
2480 operands[2] = force_reg (SImode, arc_rewrite_small_data (operands[2]));
2485 (define_expand "adddi3"
2486 [(parallel [(set (match_operand:DI 0 "dest_reg_operand" "")
2487 (plus:DI (match_operand:DI 1 "register_operand" "")
2488 (match_operand:DI 2 "nonmemory_operand" "")))
2489 (clobber (reg:CC CC_REG))])]
2492 if (TARGET_EXPAND_ADDDI)
2494 rtx l0 = gen_lowpart (SImode, operands[0]);
2495 rtx h0 = disi_highpart (operands[0]);
2496 rtx l1 = gen_lowpart (SImode, operands[1]);
2497 rtx h1 = disi_highpart (operands[1]);
2498 rtx l2 = gen_lowpart (SImode, operands[2]);
2499 rtx h2 = disi_highpart (operands[2]);
2500 rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
2502 if (CONST_INT_P (h2) && INTVAL (h2) < 0 && SIGNED_INT12 (INTVAL (h2)))
2504 emit_insn (gen_sub_f (l0, l1, gen_int_mode (-INTVAL (l2), SImode)));
2505 emit_insn (gen_sbc (h0, h1,
2506 gen_int_mode (-INTVAL (h2) - (l1 != 0), SImode),
2510 emit_insn (gen_add_f (l0, l1, l2));
2511 emit_insn (gen_adc (h0, h1, h2));
2516 ; This assumes that there can be no strictly partial overlap between
2517 ; operands[1] and operands[2].
2518 (define_insn_and_split "*adddi3_i"
2519 [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w,w")
2520 (plus:DI (match_operand:DI 1 "register_operand" "%c,0,c")
2521 (match_operand:DI 2 "nonmemory_operand" "ci,ci,!i")))
2522 (clobber (reg:CC CC_REG))]
2528 int hi = !TARGET_BIG_ENDIAN;
2530 rtx l0 = operand_subword (operands[0], lo, 0, DImode);
2531 rtx h0 = operand_subword (operands[0], hi, 0, DImode);
2532 rtx l1 = operand_subword (operands[1], lo, 0, DImode);
2533 rtx h1 = operand_subword (operands[1], hi, 0, DImode);
2534 rtx l2 = operand_subword (operands[2], lo, 0, DImode);
2535 rtx h2 = operand_subword (operands[2], hi, 0, DImode);
2538 if (l2 == const0_rtx)
2540 if (!rtx_equal_p (l0, l1) && !rtx_equal_p (l0, h1))
2541 emit_move_insn (l0, l1);
2542 emit_insn (gen_addsi3 (h0, h1, h2));
2543 if (!rtx_equal_p (l0, l1) && rtx_equal_p (l0, h1))
2544 emit_move_insn (l0, l1);
2547 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0
2548 && INTVAL (operands[2]) >= -0x7fffffff)
2550 emit_insn (gen_subdi3_i (operands[0], operands[1],
2551 GEN_INT (-INTVAL (operands[2]))));
2554 if (rtx_equal_p (l0, h1))
2556 if (h2 != const0_rtx)
2557 emit_insn (gen_addsi3 (h0, h1, h2));
2558 else if (!rtx_equal_p (h0, h1))
2559 emit_move_insn (h0, h1);
2560 emit_insn (gen_add_f (l0, l1, l2));
2564 gen_rtx_LTU (VOIDmode, gen_rtx_REG (CC_Cmode, CC_REG), GEN_INT (0)),
2565 gen_rtx_SET (h0, plus_constant (SImode, h0, 1))));
2568 emit_insn (gen_add_f (l0, l1, l2));
2569 emit_insn (gen_adc (h0, h1, h2));
2572 [(set_attr "cond" "clob")
2573 (set_attr "type" "binary")
2574 (set_attr "length" "16,16,20")])
2576 (define_insn "add_f"
2577 [(set (reg:CC_C CC_REG)
2579 (plus:SI (match_operand:SI 1 "register_operand" "c,0,c")
2580 (match_operand:SI 2 "nonmemory_operand" "cL,I,cCal"))
2582 (set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w")
2583 (plus:SI (match_dup 1) (match_dup 2)))]
2586 [(set_attr "cond" "set")
2587 (set_attr "type" "compare")
2588 (set_attr "length" "4,4,8")])
2590 (define_insn "*add_f_2"
2591 [(set (reg:CC_C CC_REG)
2593 (plus:SI (match_operand:SI 1 "register_operand" "c,0,c")
2594 (match_operand:SI 2 "nonmemory_operand" "cL,I,cCal"))
2596 (set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w")
2597 (plus:SI (match_dup 1) (match_dup 2)))]
2600 [(set_attr "cond" "set")
2601 (set_attr "type" "compare")
2602 (set_attr "length" "4,4,8")])
2604 ; w/c/c comes first (rather than w/0/C_0) to prevent the middle-end
2605 ; needlessly prioritizing the matching constraint.
2606 ; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional
2607 ; execution is used where possible.
2608 (define_insn_and_split "adc"
2609 [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w")
2610 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
2611 (match_operand:SI 1 "nonmemory_operand"
2613 (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))]
2614 "register_operand (operands[1], SImode)
2615 || register_operand (operands[2], SImode)"
2622 ; if we have a bad schedule after sched2, split.
2624 && !optimize_size && (!TARGET_ARC600_FAMILY)
2625 && arc_scheduling_not_expected ()
2626 && arc_sets_cc_p (prev_nonnote_insn (insn))
2627 /* If next comes a return or other insn that needs a delay slot,
2628 expect the adc to get into the delay slot. */
2629 && next_nonnote_insn (insn)
2630 && !arc_need_delay (next_nonnote_insn (insn))
2631 /* Restore operands before emitting. */
2632 && (extract_insn_cached (insn), 1)"
2633 [(set (match_dup 0) (match_dup 3))
2635 (ltu (reg:CC_C CC_REG) (const_int 0))
2636 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))))]
2637 "operands[3] = simplify_gen_binary (PLUS, SImode, operands[1], operands[2]);"
2638 [(set_attr "cond" "use")
2639 (set_attr "type" "cc_arith")
2640 (set_attr "length" "4,4,4,4,8")])
2642 ; combiner-splitter cmp / scc -> cmp / adc
2644 [(set (match_operand:SI 0 "dest_reg_operand" "")
2645 (gtu:SI (match_operand:SI 1 "register_operand" "")
2646 (match_operand:SI 2 "register_operand" "")))
2647 (clobber (reg CC_REG))]
2649 [(set (reg:CC_C CC_REG) (compare:CC_C (match_dup 2) (match_dup 1)))
2650 (set (match_dup 0) (ltu:SI (reg:CC_C CC_REG) (const_int 0)))])
2652 ; combine won't work when an intermediate result is used later...
2653 ; add %0,%1,%2 ` cmp %0,%[12] -> add.f %0,%1,%2
2655 [(set (match_operand:SI 0 "dest_reg_operand" "")
2656 (plus:SI (match_operand:SI 1 "register_operand" "")
2657 (match_operand:SI 2 "nonmemory_operand" "")))
2658 (set (reg:CC_C CC_REG)
2659 (compare:CC_C (match_dup 0)
2660 (match_operand:SI 3 "nonmemory_operand" "")))]
2661 "rtx_equal_p (operands[1], operands[3])
2662 || rtx_equal_p (operands[2], operands[3])"
2664 [(set (reg:CC_C CC_REG)
2665 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))
2667 (plus:SI (match_dup 1) (match_dup 2)))])])
2669 ; ??? need to delve into combine to find out why this is not useful.
2670 ; We'd like to be able to grok various C idioms for carry bit usage.
2671 ;(define_insn "*adc_0"
2672 ; [(set (match_operand:SI 0 "dest_reg_operand" "=w")
2673 ; (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
2674 ; (match_operand:SI 1 "register_operand" "c")))]
2677 ; [(set_attr "cond" "use")
2678 ; (set_attr "type" "cc_arith")
2679 ; (set_attr "length" "4")])
2682 ; [(set (match_operand:SI 0 "dest_reg_operand" "=w")
2683 ; (plus:SI (gtu:SI (match_operand:SI 1 "register_operand" "c")
2684 ; (match_operand:SI 2 "register_operand" "c"))
2685 ; (match_operand:SI 3 "register_operand" "c")))
2686 ; (clobber (reg CC_REG))]
2688 ; [(set (reg:CC_C CC_REG) (compare:CC_C (match_dup 2) (match_dup 1)))
2689 ; (set (match_dup 0)
2690 ; (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
2693 (define_expand "subsi3"
2694 [(set (match_operand:SI 0 "dest_reg_operand" "")
2695 (minus:SI (match_operand:SI 1 "nonmemory_operand" "")
2696 (match_operand:SI 2 "nonmemory_operand" "")))]
2702 if (!register_operand (operands[2], SImode))
2704 operands[1] = force_reg (SImode, operands[1]);
2707 if (flag_pic && arc_raw_symbolic_reference_mentioned_p (operands[c], false))
2708 operands[c] = force_reg (SImode, operands[c]);
2709 else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[c], Pmode))
2710 operands[c] = force_reg (SImode, arc_rewrite_small_data (operands[c]));
2713 ; the casesi expander might generate a sub of zero, so we have to recognize it.
2714 ; combine should make such an insn go away.
2715 (define_insn_and_split "subsi3_insn"
2716 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,Rcw,w,w,w, w, w, w")
2717 (minus:SI (match_operand:SI 1 "nonmemory_operand" "0, 0, cL,c,L,I,Cal,Cal, c")
2718 (match_operand:SI 2 "nonmemory_operand" "Rcqq, c, 0,c,c,0, 0, c,Cal")))]
2719 "register_operand (operands[1], SImode)
2720 || register_operand (operands[2], SImode)"
2731 "reload_completed && get_attr_length (insn) == 8
2732 && satisfies_constraint_I (operands[1])
2733 && GET_CODE (PATTERN (insn)) != COND_EXEC"
2734 [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))]
2735 "split_subsi (operands);"
2736 [(set_attr "iscompact" "maybe,false,false,false,false,false,false,false, false")
2737 (set_attr "length" "*,4,4,4,4,4,8,8,8")
2738 (set_attr "predicable" "yes,yes,yes,no,no,no,yes,no,no")
2739 (set_attr "cond" "canuse,canuse,canuse,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
2741 (define_expand "subdi3"
2742 [(parallel [(set (match_operand:DI 0 "dest_reg_operand" "")
2743 (minus:DI (match_operand:DI 1 "nonmemory_operand" "")
2744 (match_operand:DI 2 "nonmemory_operand" "")))
2745 (clobber (reg:CC CC_REG))])]
2748 if (!register_operand (operands[2], DImode))
2749 operands[1] = force_reg (DImode, operands[1]);
2750 if (TARGET_EXPAND_ADDDI)
2752 rtx l0 = gen_lowpart (SImode, operands[0]);
2753 rtx h0 = disi_highpart (operands[0]);
2754 rtx l1 = gen_lowpart (SImode, operands[1]);
2755 rtx h1 = disi_highpart (operands[1]);
2756 rtx l2 = gen_lowpart (SImode, operands[2]);
2757 rtx h2 = disi_highpart (operands[2]);
2758 rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
2760 emit_insn (gen_sub_f (l0, l1, l2));
2761 emit_insn (gen_sbc (h0, h1, h2, cc_c));
2766 (define_insn_and_split "subdi3_i"
2767 [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w,w,w,w")
2768 (minus:DI (match_operand:DI 1 "nonmemory_operand" "ci,0,ci,c,!i")
2769 (match_operand:DI 2 "nonmemory_operand" "ci,ci,0,!i,c")))
2770 (clobber (reg:CC CC_REG))]
2771 "register_operand (operands[1], DImode)
2772 || register_operand (operands[2], DImode)"
2777 int hi = !TARGET_BIG_ENDIAN;
2779 rtx l0 = operand_subword (operands[0], lo, 0, DImode);
2780 rtx h0 = operand_subword (operands[0], hi, 0, DImode);
2781 rtx l1 = operand_subword (operands[1], lo, 0, DImode);
2782 rtx h1 = operand_subword (operands[1], hi, 0, DImode);
2783 rtx l2 = operand_subword (operands[2], lo, 0, DImode);
2784 rtx h2 = operand_subword (operands[2], hi, 0, DImode);
2786 if (rtx_equal_p (l0, h1) || rtx_equal_p (l0, h2))
2788 h1 = simplify_gen_binary (MINUS, SImode, h1, h2);
2789 if (!rtx_equal_p (h0, h1))
2790 emit_insn (gen_rtx_SET (h0, h1));
2791 emit_insn (gen_sub_f (l0, l1, l2));
2795 gen_rtx_LTU (VOIDmode, gen_rtx_REG (CC_Cmode, CC_REG), GEN_INT (0)),
2796 gen_rtx_SET (h0, plus_constant (SImode, h0, -1))));
2799 emit_insn (gen_sub_f (l0, l1, l2));
2800 emit_insn (gen_sbc (h0, h1, h2, gen_rtx_REG (CCmode, CC_REG)));
2803 [(set_attr "cond" "clob")
2804 (set_attr "length" "16,16,16,20,20")])
2806 (define_insn "*sbc_0"
2807 [(set (match_operand:SI 0 "dest_reg_operand" "=w")
2808 (minus:SI (match_operand:SI 1 "register_operand" "c")
2809 (ltu:SI (match_operand:CC_C 2 "cc_use_register")
2813 [(set_attr "cond" "use")
2814 (set_attr "type" "cc_arith")
2815 (set_attr "length" "4")])
2817 ; w/c/c comes first (rather than Rcw/0/C_0) to prevent the middle-end
2818 ; needlessly prioritizing the matching constraint.
2819 ; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional execution
2820 ; is used where possible.
2821 (define_insn_and_split "sbc"
2822 [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w")
2823 (minus:SI (minus:SI (match_operand:SI 1 "nonmemory_operand"
2825 (ltu:SI (match_operand:CC_C 3 "cc_use_register")
2827 (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))]
2828 "register_operand (operands[1], SImode)
2829 || register_operand (operands[2], SImode)"
2836 ; if we have a bad schedule after sched2, split.
2838 && !optimize_size && (!TARGET_ARC600_FAMILY)
2839 && arc_scheduling_not_expected ()
2840 && arc_sets_cc_p (prev_nonnote_insn (insn))
2841 /* If next comes a return or other insn that needs a delay slot,
2842 expect the adc to get into the delay slot. */
2843 && next_nonnote_insn (insn)
2844 && !arc_need_delay (next_nonnote_insn (insn))
2845 /* Restore operands before emitting. */
2846 && (extract_insn_cached (insn), 1)"
2847 [(set (match_dup 0) (match_dup 4))
2849 (ltu (reg:CC_C CC_REG) (const_int 0))
2850 (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))))]
2851 "operands[4] = simplify_gen_binary (MINUS, SImode, operands[1], operands[2]);"
2852 [(set_attr "cond" "use")
2853 (set_attr "type" "cc_arith")
2854 (set_attr "length" "4,4,4,4,8")])
2856 (define_insn "sub_f"
2857 [(set (reg:CC CC_REG)
2858 (compare:CC (match_operand:SI 1 "nonmemory_operand" " c,L,0,I,c,Cal")
2859 (match_operand:SI 2 "nonmemory_operand" "cL,c,I,0,Cal,c")))
2860 (set (match_operand:SI 0 "dest_reg_operand" "=w,w,Rcw,Rcw,w,w")
2861 (minus:SI (match_dup 1) (match_dup 2)))]
2862 "register_operand (operands[1], SImode)
2863 || register_operand (operands[2], SImode)"
2871 [(set_attr "type" "compare")
2872 (set_attr "length" "4,4,4,4,8,8")])
2874 ; combine won't work when an intermediate result is used later...
2875 ; add %0,%1,%2 ` cmp %0,%[12] -> add.f %0,%1,%2
2877 [(set (reg:CC CC_REG)
2878 (compare:CC (match_operand:SI 1 "register_operand" "")
2879 (match_operand:SI 2 "nonmemory_operand" "")))
2880 (set (match_operand:SI 0 "dest_reg_operand" "")
2881 (minus:SI (match_dup 1) (match_dup 2)))]
2884 [(set (reg:CC CC_REG) (compare:CC (match_dup 1) (match_dup 2)))
2885 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])])
2888 [(set (reg:CC CC_REG)
2889 (compare:CC (match_operand:SI 1 "register_operand" "")
2890 (match_operand:SI 2 "nonmemory_operand" "")))
2891 (set (match_operand 3 "" "") (match_operand 4 "" ""))
2892 (set (match_operand:SI 0 "dest_reg_operand" "")
2893 (minus:SI (match_dup 1) (match_dup 2)))]
2894 "!reg_overlap_mentioned_p (operands[3], operands[1])
2895 && !reg_overlap_mentioned_p (operands[3], operands[2])
2896 && !reg_overlap_mentioned_p (operands[0], operands[4])
2897 && !reg_overlap_mentioned_p (operands[0], operands[3])"
2899 [(set (reg:CC CC_REG) (compare:CC (match_dup 1) (match_dup 2)))
2900 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
2901 (set (match_dup 3) (match_dup 4))])
2903 (define_insn "*add_n"
2904 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,W,W,w,w")
2905 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "Rcqq,c,c,c,c,c")
2906 (match_operand:SI 2 "_2_4_8_operand" ""))
2907 (match_operand:SI 3 "nonmemory_operand" "0,0,c,?Cal,?c,??Cal")))]
2909 "add%z2%? %0,%3,%1%&"
2910 [(set_attr "type" "shift")
2911 (set_attr "length" "*,4,4,8,4,8")
2912 (set_attr "predicable" "yes,yes,no,no,no,no")
2913 (set_attr "cond" "canuse,canuse,nocond,nocond,nocond,nocond")
2914 (set_attr "iscompact" "maybe,false,false,false,false,false")])
2916 ;; N.B. sub[123] has the operands of the MINUS in the opposite order from
2917 ;; what synth_mult likes.
2918 (define_insn "*sub_n"
2919 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2920 (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,c,?Cal")
2921 (mult:SI (match_operand:SI 2 "register_operand" "c,c,c")
2922 (match_operand:SI 3 "_2_4_8_operand" ""))))]
2925 [(set_attr "type" "shift")
2926 (set_attr "length" "4,4,8")
2927 (set_attr "predicable" "yes,no,no")
2928 (set_attr "cond" "canuse,nocond,nocond")
2929 (set_attr "iscompact" "false")])
2931 ; ??? check if combine matches this.
2932 (define_insn "*bset"
2933 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2934 (ior:SI (ashift:SI (const_int 1)
2935 (match_operand:SI 1 "nonmemory_operand" "cL,cL,c"))
2936 (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
2939 [(set_attr "length" "4,4,8")
2940 (set_attr "predicable" "yes,no,no")
2941 (set_attr "cond" "canuse,nocond,nocond")]
2944 ; ??? check if combine matches this.
2945 (define_insn "*bxor"
2946 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2947 (xor:SI (ashift:SI (const_int 1)
2948 (match_operand:SI 1 "nonmemory_operand" "cL,cL,c"))
2949 (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
2952 [(set_attr "length" "4,4,8")
2953 (set_attr "predicable" "yes,no,no")
2954 (set_attr "cond" "canuse,nocond,nocond")]
2957 ; ??? check if combine matches this.
2958 (define_insn "*bclr"
2959 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2960 (and:SI (not:SI (ashift:SI (const_int 1)
2961 (match_operand:SI 1 "nonmemory_operand" "cL,cL,c")))
2962 (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
2965 [(set_attr "length" "4,4,8")
2966 (set_attr "predicable" "yes,no,no")
2967 (set_attr "cond" "canuse,nocond,nocond")]
2970 ; ??? FIXME: find combine patterns for bmsk.
2972 ;;Following are the define_insns added for the purpose of peephole2's
2974 ; see also iorsi3 for use with constant bit number.
2975 (define_insn "*bset_insn"
2976 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2977 (ior:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
2978 (ashift:SI (const_int 1)
2979 (match_operand:SI 2 "nonmemory_operand" "cL,cL,c"))) ) ]
2982 bset%? %0,%1,%2 ;;peep2, constr 1
2983 bset %0,%1,%2 ;;peep2, constr 2
2984 bset %0,%S1,%2 ;;peep2, constr 3"
2985 [(set_attr "length" "4,4,8")
2986 (set_attr "predicable" "yes,no,no")
2987 (set_attr "cond" "canuse,nocond,nocond")]
2990 ; see also xorsi3 for use with constant bit number.
2991 (define_insn "*bxor_insn"
2992 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
2993 (xor:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
2994 (ashift:SI (const_int 1)
2995 (match_operand:SI 2 "nonmemory_operand" "cL,cL,c"))) ) ]
3001 [(set_attr "length" "4,4,8")
3002 (set_attr "predicable" "yes,no,no")
3003 (set_attr "cond" "canuse,nocond,nocond")]
3006 ; see also andsi3 for use with constant bit number.
3007 (define_insn "*bclr_insn"
3008 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
3009 (and:SI (not:SI (ashift:SI (const_int 1)
3010 (match_operand:SI 2 "nonmemory_operand" "cL,rL,r")))
3011 (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")))]
3017 [(set_attr "length" "4,4,8")
3018 (set_attr "predicable" "yes,no,no")
3019 (set_attr "cond" "canuse,nocond,nocond")]
3022 ; see also andsi3 for use with constant bit number.
3023 (define_insn "*bmsk_insn"
3024 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
3025 (and:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
3026 (plus:SI (ashift:SI (const_int 1)
3027 (plus:SI (match_operand:SI 2 "nonmemory_operand" "rL,rL,r")
3035 [(set_attr "length" "4,4,8")
3036 (set_attr "predicable" "yes,no,no")
3037 (set_attr "cond" "canuse,nocond,nocond")]
3040 ;;Instructions added for peephole2s end
3042 ;; Boolean instructions.
3044 (define_expand "andsi3"
3045 [(set (match_operand:SI 0 "dest_reg_operand" "")
3046 (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
3047 (match_operand:SI 2 "nonmemory_operand" "")))]
3049 "if (!satisfies_constraint_Cux (operands[2]))
3050 operands[1] = force_reg (SImode, operands[1]);
3051 else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[1], Pmode))
3052 operands[1] = arc_rewrite_small_data (operands[1]);")
3054 (define_insn "andsi3_i"
3055 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw, Rcw,Rcw,Rcw,Rcw, w, w, w, w,Rrq,w,Rcw, w,W")
3056 (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq, 0, 0,Rcqq, 0, c, 0, 0, 0, 0, c, c, c, c,Rrq,0, 0, c,o")
3057 (match_operand:SI 2 "nonmemory_operand" "Rcqq, 0, C1p, Ccp, Cux, cL, 0,C2pC1p,Ccp,CnL, I,Lc,C2pC1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))]
3058 "(register_operand (operands[1], SImode)
3059 && nonmemory_operand (operands[2], SImode))
3060 || (memory_operand (operands[1], SImode)
3061 && satisfies_constraint_Cux (operands[2]))"
3063 switch (which_alternative)
3065 case 0: case 5: case 10: case 11: case 16: case 17: case 18:
3066 return "and%? %0,%1,%2%&";
3068 return "and%? %0,%2,%1%&";
3070 return "bmsk%? %0,%1,%Z2%&";
3072 if (satisfies_constraint_C2p (operands[2]))
3074 operands[2] = GEN_INT ((~INTVAL (operands[2])));
3075 return "bmskn%? %0,%1,%Z2%&";
3079 return "bmsk%? %0,%1,%Z2%&";
3081 case 3: case 8: case 13:
3082 return "bclr%? %0,%1,%M2%&";
3084 return (INTVAL (operands[2]) == 0xff
3085 ? "extb%? %0,%1%&" : "ext%_%? %0,%1%&");
3086 case 9: case 14: return \"bic%? %0,%1,%n2-1\";
3088 return "movb.cl %0,%1,%p2,%p2,%s2";
3093 if (satisfies_constraint_Ucm (operands[1]))
3094 tmpl = (INTVAL (operands[2]) == 0xff
3095 ? "xldb%U1 %0,%1" : "xld%_%U1 %0,%1");
3097 tmpl = INTVAL (operands[2]) == 0xff ? "ldb %0,%1" : "ld%_ %0,%1";
3099 if (TARGET_BIG_ENDIAN)
3103 xop[0] = operands[0];
3104 xop[1] = adjust_address (operands[1], QImode,
3105 INTVAL (operands[2]) == 0xff ? 3 : 2);
3106 output_asm_insn (tmpl, xop);
3114 [(set_attr "iscompact" "maybe,maybe,maybe,maybe,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false")
3115 (set_attr "type" "binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,shift,binary,binary,binary,load")
3116 (set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,4,4,4,4,4,8,8,*")
3117 (set_attr "predicable" "no,no,no,no,no,yes,yes,yes,yes,yes,no,no,no,no,no,no,no,yes,no,no")
3118 (set_attr "cond" "canuse,canuse,canuse,canuse,nocond,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,nocond,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
3120 ; combiner splitter, pattern found in ldtoa.c .
3121 ; and op3,op0,op1 / cmp op3,op2 -> add op3,op0,op4 / bmsk.f 0,op3,op1
3123 [(set (reg:CC_Z CC_REG)
3124 (compare:CC_Z (and:SI (match_operand:SI 0 "register_operand" "")
3125 (match_operand 1 "const_int_operand" ""))
3126 (match_operand 2 "const_int_operand" "")))
3127 (clobber (match_operand:SI 3 "register_operand" ""))]
3128 "((INTVAL (operands[1]) + 1) & INTVAL (operands[1])) == 0"
3130 (plus:SI (match_dup 0) (match_dup 4)))
3131 (set (reg:CC_Z CC_REG)
3132 (compare:CC_Z (and:SI (match_dup 3) (match_dup 1))
3134 "operands[4] = GEN_INT ( -(~INTVAL (operands[1]) | INTVAL (operands[2])));")
3136 ;;bic define_insn that allows limm to be the first operand
3137 (define_insn "*bicsi3_insn"
3138 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,Rcw,Rcw,w,w,w")
3139 (and:SI (not:SI (match_operand:SI 1 "nonmemory_operand" "Rcqq,Lc,I,Cal,Lc,Cal,c"))
3140 (match_operand:SI 2 "nonmemory_operand" "0,0,0,0,c,c,Cal")))]
3143 bic%? %0, %2, %1%& ;;constraint 0
3144 bic%? %0,%2,%1 ;;constraint 1
3145 bic %0,%2,%1 ;;constraint 2, FIXME: will it ever get generated ???
3146 bic%? %0,%2,%S1 ;;constraint 3, FIXME: will it ever get generated ???
3147 bic %0,%2,%1 ;;constraint 4
3148 bic %0,%2,%S1 ;;constraint 5, FIXME: will it ever get generated ???
3149 bic %0,%S2,%1 ;;constraint 6"
3150 [(set_attr "length" "*,4,4,8,4,8,8")
3151 (set_attr "iscompact" "maybe, false, false, false, false, false, false")
3152 (set_attr "predicable" "no,yes,no,yes,no,no,no")
3153 (set_attr "cond" "canuse,canuse,canuse_limm,canuse,nocond,nocond,nocond")])
3155 (define_insn "iorsi3"
3156 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcw,Rcw,Rcw,Rcw,w, w,w,Rcw, w")
3157 (ior:SI (match_operand:SI 1 "nonmemory_operand" "% 0,Rcq, 0, 0, c, 0, 0, c, c,0, 0, c")
3158 (match_operand:SI 2 "nonmemory_operand" "Rcqq, 0, C0p, cL, 0,C0p, I,cL,C0p,I,Cal,Cal")))]
3161 switch (which_alternative)
3163 case 0: case 3: case 6: case 7: case 9: case 10: case 11:
3164 return \"or%? %0,%1,%2%&\";
3166 return \"or%? %0,%2,%1%&\";
3167 case 2: case 5: case 8:
3168 return \"bset%? %0,%1,%z2%&\";
3172 [(set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false")
3173 (set_attr "length" "*,*,*,4,4,4,4,4,4,4,8,8")
3174 (set_attr "predicable" "no,no,no,yes,yes,yes,no,no,no,no,yes,no")
3175 (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,canuse,nocond")])
3177 (define_insn "xorsi3"
3178 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcw,Rcw,Rcw,Rcw, w, w,w, w, w")
3179 (xor:SI (match_operand:SI 1 "register_operand" "%0, Rcq, 0, c, 0, 0, c, c,0, 0, c")
3180 (match_operand:SI 2 "nonmemory_operand" " Rcqq, 0, cL, 0,C0p, I,cL,C0p,I,Cal,Cal")))]
3183 switch (which_alternative)
3185 case 0: case 2: case 5: case 6: case 8: case 9: case 10:
3186 return \"xor%? %0,%1,%2%&\";
3188 return \"xor%? %0,%2,%1%&\";
3190 return \"bxor%? %0,%1,%z2\";
3195 [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false,false,false,false")
3196 (set_attr "type" "binary")
3197 (set_attr "length" "*,*,4,4,4,4,4,4,4,8,8")
3198 (set_attr "predicable" "no,no,yes,yes,yes,no,no,no,no,yes,no")
3199 (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,canuse,nocond")])
3201 (define_insn "negsi2"
3202 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcqq,Rcw,w")
3203 (neg:SI (match_operand:SI 1 "register_operand" "0,Rcqq,0,c")))]
3206 [(set_attr "type" "unary")
3207 (set_attr "iscompact" "maybe,true,false,false")
3208 (set_attr "predicable" "no,no,yes,no")])
3210 (define_insn "one_cmplsi2"
3211 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w")
3212 (not:SI (match_operand:SI 1 "register_operand" "Rcqq,c")))]
3215 [(set_attr "type" "unary,unary")
3216 (set_attr "iscompact" "true,false")])
3218 (define_insn_and_split "one_cmpldi2"
3219 [(set (match_operand:DI 0 "dest_reg_operand" "=q,w")
3220 (not:DI (match_operand:DI 1 "register_operand" "q,c")))]
3223 "&& reload_completed"
3224 [(set (match_dup 2) (not:SI (match_dup 3)))
3225 (set (match_dup 4) (not:SI (match_dup 5)))]
3227 int swap = (true_regnum (operands[0]) == true_regnum (operands[1]) + 1);
3229 operands[2] = operand_subword (operands[0], 0+swap, 0, DImode);
3230 operands[3] = operand_subword (operands[1], 0+swap, 0, DImode);
3231 operands[4] = operand_subword (operands[0], 1-swap, 0, DImode);
3232 operands[5] = operand_subword (operands[1], 1-swap, 0, DImode);
3234 [(set_attr "type" "unary,unary")
3235 (set_attr "cond" "nocond,nocond")
3236 (set_attr "length" "4,8")])
3238 ;; Shift instructions.
3240 (define_expand "ashlsi3"
3241 [(set (match_operand:SI 0 "dest_reg_operand" "")
3242 (ashift:SI (match_operand:SI 1 "register_operand" "")
3243 (match_operand:SI 2 "nonmemory_operand" "")))]
3247 if (!TARGET_BARREL_SHIFTER)
3249 emit_shift (ASHIFT, operands[0], operands[1], operands[2]);
3254 (define_expand "ashrsi3"
3255 [(set (match_operand:SI 0 "dest_reg_operand" "")
3256 (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
3257 (match_operand:SI 2 "nonmemory_operand" "")))]
3261 if (!TARGET_BARREL_SHIFTER)
3263 emit_shift (ASHIFTRT, operands[0], operands[1], operands[2]);
3268 (define_expand "lshrsi3"
3269 [(set (match_operand:SI 0 "dest_reg_operand" "")
3270 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
3271 (match_operand:SI 2 "nonmemory_operand" "")))]
3275 if (!TARGET_BARREL_SHIFTER)
3277 emit_shift (LSHIFTRT, operands[0], operands[1], operands[2]);
3282 (define_insn "shift_si3"
3283 [(set (match_operand:SI 0 "dest_reg_operand" "=r")
3284 (match_operator:SI 3 "shift4_operator"
3285 [(match_operand:SI 1 "register_operand" "0")
3286 (match_operand:SI 2 "const_int_operand" "n")]))
3287 (clobber (match_scratch:SI 4 "=&r"))
3288 (clobber (reg:CC CC_REG))
3290 "!TARGET_BARREL_SHIFTER"
3291 "* return output_shift (operands);"
3292 [(set_attr "type" "shift")
3293 (set_attr "length" "16")])
3295 (define_insn "shift_si3_loop"
3296 [(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
3297 (match_operator:SI 3 "shift_operator"
3298 [(match_operand:SI 1 "register_operand" "0,0")
3299 (match_operand:SI 2 "nonmemory_operand" "rn,Cal")]))
3300 (clobber (match_scratch:SI 4 "=X,X"))
3301 (clobber (reg:SI LP_COUNT))
3302 (clobber (reg:SI LP_START))
3303 (clobber (reg:SI LP_END))
3304 (clobber (reg:CC CC_REG))
3306 "!TARGET_BARREL_SHIFTER"
3307 "* return output_shift (operands);"
3308 [(set_attr "type" "shift")
3309 (set_attr "length" "16,20")])
3311 ; asl, asr, lsr patterns:
3312 ; There is no point in including an 'I' alternative since only the lowest 5
3313 ; bits are used for the shift. OTOH Cal can be useful if the shift amount
3314 ; is defined in an external symbol, as we don't have special relocations
3315 ; to truncate a symbol in a u6 immediate; but that's rather exotic, so only
3316 ; provide one alternatice for this, without condexec support.
3317 (define_insn "*ashlsi3_insn"
3318 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w")
3319 (ashift:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCal")
3320 (match_operand:SI 2 "nonmemory_operand" "K, K,RcqqM, cL,cL,cCal")))]
3321 "TARGET_BARREL_SHIFTER
3322 && (register_operand (operands[1], SImode)
3323 || register_operand (operands[2], SImode))"
3325 [(set_attr "type" "shift")
3326 (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
3327 (set_attr "predicable" "no,no,no,yes,no,no")
3328 (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
3330 (define_insn "*ashrsi3_insn"
3331 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w")
3332 (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCal")
3333 (match_operand:SI 2 "nonmemory_operand" "K, K,RcqqM, cL,cL,cCal")))]
3334 "TARGET_BARREL_SHIFTER
3335 && (register_operand (operands[1], SImode)
3336 || register_operand (operands[2], SImode))"
3338 [(set_attr "type" "shift")
3339 (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
3340 (set_attr "predicable" "no,no,no,yes,no,no")
3341 (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
3343 (define_insn "*lshrsi3_insn"
3344 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w")
3345 (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCal")
3346 (match_operand:SI 2 "nonmemory_operand" "N, N,RcqqM, cL,cL,cCal")))]
3347 "TARGET_BARREL_SHIFTER
3348 && (register_operand (operands[1], SImode)
3349 || register_operand (operands[2], SImode))"
3350 "*return (which_alternative <= 1 && !arc_ccfsm_cond_exec_p ()
3351 ? \"lsr%? %0,%1%&\" : \"lsr%? %0,%1,%2%&\");"
3352 [(set_attr "type" "shift")
3353 (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
3354 (set_attr "predicable" "no,no,no,yes,no,no")
3355 (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
3357 (define_insn "rotrsi3"
3358 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w")
3359 (rotatert:SI (match_operand:SI 1 "register_operand" " 0,cL,cCal")
3360 (match_operand:SI 2 "nonmemory_operand" "cL,cL,cCal")))]
3361 "TARGET_BARREL_SHIFTER"
3363 [(set_attr "type" "shift,shift,shift")
3364 (set_attr "predicable" "yes,no,no")
3365 (set_attr "length" "4,4,8")])
3367 ;; Compare / branch instructions.
3369 (define_expand "cbranchsi4"
3370 [(set (reg:CC CC_REG)
3371 (compare:CC (match_operand:SI 1 "nonmemory_operand" "")
3372 (match_operand:SI 2 "nonmemory_operand" "")))
3375 (match_operator 0 "ordered_comparison_operator" [(reg CC_REG)
3377 (label_ref (match_operand 3 "" ""))
3381 gcc_assert (XEXP (operands[0], 0) == operands[1]);
3382 gcc_assert (XEXP (operands[0], 1) == operands[2]);
3383 operands[0] = gen_compare_reg (operands[0], VOIDmode);
3384 emit_jump_insn (gen_branch_insn (operands[3], operands[0]));
3388 ;; ??? Could add a peephole to generate compare with swapped operands and
3389 ;; modifed cc user if second, but not first operand is a compact register.
3390 (define_insn "cmpsi_cc_insn_mixed"
3391 [(set (reg:CC CC_REG)
3392 (compare:CC (match_operand:SI 0 "register_operand" "Rcq#q, h, c, c,qRcq,c")
3393 (match_operand:SI 1 "nonmemory_operand" "cO,Cm1,cI,cL, Cal,Cal")))]
3396 [(set_attr "type" "compare")
3397 (set_attr "iscompact" "true,true,false,false,true_limm,false")
3398 (set_attr "predicable" "no,no,no,yes,no,yes")
3399 (set_attr "cond" "set")
3400 (set_attr "length" "*,*,4,4,*,8")])
3402 (define_insn "*cmpsi_cc_zn_insn"
3403 [(set (reg:CC_ZN CC_REG)
3404 (compare:CC_ZN (match_operand:SI 0 "register_operand" "qRcq,c")
3408 [(set_attr "type" "compare,compare")
3409 (set_attr "iscompact" "true,false")
3410 (set_attr "predicable" "no,yes")
3411 (set_attr "cond" "set_zn")
3412 (set_attr "length" "*,4")])
3414 ; combiner pattern observed for unwind-dw2-fde.c:linear_search_fdes.
3415 (define_insn "*btst"
3416 [(set (reg:CC_ZN CC_REG)
3418 (zero_extract:SI (match_operand:SI 0 "register_operand" "Rcqq,c")
3420 (match_operand:SI 1 "nonmemory_operand" "L,Lc"))
3424 [(set_attr "iscompact" "true,false")
3425 (set_attr "predicable" "no,yes")
3426 (set_attr "cond" "set")
3427 (set_attr "type" "compare")
3428 (set_attr "length" "*,4")])
3430 ; combine suffers from 'simplifications' that replace a one-bit zero
3431 ; extract with a shift if it can prove that the upper bits are zero.
3432 ; arc_reorg sees the code after sched2, which can have caused our
3433 ; inputs to be clobbered even if they were not clobbered before.
3434 ; Therefore, add a third way to convert btst / b{eq,ne} to bbit{0,1}
3435 ; OTOH, this is somewhat marginal, and can leat to out-of-range
3436 ; bbit (i.e. bad scheduling) and missed conditional execution,
3437 ; so make this an option.
3439 [(set (reg:CC_ZN CC_REG)
3441 (zero_extract:SI (match_operand:SI 0 "register_operand" "")
3443 (match_operand:SI 1 "nonmemory_operand" ""))
3446 (if_then_else (match_operator 3 "equality_comparison_operator"
3447 [(reg:CC_ZN CC_REG) (const_int 0)])
3448 (label_ref (match_operand 2 "" ""))
3450 "TARGET_BBIT_PEEPHOLE && peep2_regno_dead_p (2, CC_REG)"
3451 [(parallel [(set (pc)
3454 [(zero_extract:SI (match_dup 0)
3455 (const_int 1) (match_dup 1))
3457 (label_ref (match_dup 2))
3459 (clobber (reg:CC_ZN CC_REG))])])
3461 (define_insn "*cmpsi_cc_z_insn"
3462 [(set (reg:CC_Z CC_REG)
3463 (compare:CC_Z (match_operand:SI 0 "register_operand" "qRcq,c")
3464 (match_operand:SI 1 "p2_immediate_operand" "O,n")))]
3469 [(set_attr "type" "compare,compare")
3470 (set_attr "iscompact" "true,false")
3471 (set_attr "cond" "set,set_zn")
3472 (set_attr "length" "*,4")])
3474 (define_insn "*cmpsi_cc_c_insn"
3475 [(set (reg:CC_C CC_REG)
3476 (compare:CC_C (match_operand:SI 0 "register_operand" "Rcqq, h, c,Rcqq, c")
3477 (match_operand:SI 1 "nonmemory_operand" "cO,Cm1,cI, Cal,Cal")))]
3480 [(set_attr "type" "compare")
3481 (set_attr "iscompact" "true,true,false,true_limm,false")
3482 (set_attr "cond" "set")
3483 (set_attr "length" "*,*,4,*,8")])
3485 ;; Next come the scc insns.
3487 (define_expand "cstoresi4"
3488 [(set (match_operand:SI 0 "dest_reg_operand" "")
3489 (match_operator:SI 1 "ordered_comparison_operator"
3490 [(match_operand:SI 2 "nonmemory_operand" "")
3491 (match_operand:SI 3 "nonmemory_operand" "")]))]
3494 if (!TARGET_CODE_DENSITY)
3496 gcc_assert (XEXP (operands[1], 0) == operands[2]);
3497 gcc_assert (XEXP (operands[1], 1) == operands[3]);
3498 operands[1] = gen_compare_reg (operands[1], SImode);
3499 emit_insn (gen_scc_insn (operands[0], operands[1]));
3502 if (!register_operand (operands[2], SImode))
3503 operands[2] = force_reg (SImode, operands[2]);
3507 (define_mode_iterator SDF [(SF "TARGET_FP_SP_BASE || TARGET_OPTFPE")
3508 (DF "TARGET_OPTFPE")])
3510 (define_expand "cstore<mode>4"
3511 [(set (reg:CC CC_REG)
3512 (compare:CC (match_operand:SDF 2 "register_operand" "")
3513 (match_operand:SDF 3 "register_operand" "")))
3514 (set (match_operand:SI 0 "dest_reg_operand" "")
3515 (match_operator:SI 1 "comparison_operator" [(reg CC_REG)
3518 "TARGET_FP_SP_BASE || TARGET_OPTFPE"
3520 gcc_assert (XEXP (operands[1], 0) == operands[2]);
3521 gcc_assert (XEXP (operands[1], 1) == operands[3]);
3522 operands[1] = gen_compare_reg (operands[1], SImode);
3523 emit_insn (gen_scc_insn (operands[0], operands[1]));
3527 ; We need a separate expander for this lest we loose the mode of CC_REG
3528 ; when match_operator substitutes the literal operand into the comparison.
3529 (define_expand "scc_insn"
3530 [(set (match_operand:SI 0 "dest_reg_operand" "=w") (match_operand:SI 1 ""))])
3532 (define_insn_and_split "*scc_insn"
3533 [(set (match_operand:SI 0 "dest_reg_operand" "=w")
3534 (match_operator:SI 1 "proper_comparison_operator" [(reg CC_REG) (const_int 0)]))]
3538 [(set (match_dup 0) (const_int 1))
3541 (set (match_dup 0) (const_int 0)))]
3544 = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[1]),
3545 GET_MODE (XEXP (operands[1], 0))),
3547 XEXP (operands[1], 0), XEXP (operands[1], 1));
3549 [(set_attr "type" "unary")])
3551 ;; ??? At least for ARC600, we should use sbc b,b,s12 if we want a value
3552 ;; that is one lower if the carry flag is set.
3554 ;; ??? Look up negscc insn. See pa.md for example.
3555 (define_insn "*neg_scc_insn"
3556 [(set (match_operand:SI 0 "dest_reg_operand" "=w")
3557 (neg:SI (match_operator:SI 1 "proper_comparison_operator"
3558 [(reg CC_REG) (const_int 0)])))]
3560 "mov %0,-1\;sub.%D1 %0,%0,%0"
3561 [(set_attr "type" "unary")
3562 (set_attr "length" "8")])
3564 (define_insn "*not_scc_insn"
3565 [(set (match_operand:SI 0 "dest_reg_operand" "=w")
3566 (not:SI (match_operator:SI 1 "proper_comparison_operator"
3567 [(reg CC_REG) (const_int 0)])))]
3569 "mov %0,1\;sub.%d1 %0,%0,%0"
3570 [(set_attr "type" "unary")
3571 (set_attr "length" "8")])
3573 ; cond_exec patterns
3574 (define_insn "*movsi_ne"
3576 (ne (match_operand:CC_Z 2 "cc_use_register" "Rcc, Rcc, Rcc,Rcc,Rcc") (const_int 0))
3577 (set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,Rcq#q,Rcq#q, w,w")
3578 (match_operand:SI 1 "nonmemory_operand" "C_0, h, ?Cal, Lc,?Cal")))]
3581 * current_insn_predicate = 0; return \"sub%?.ne %0,%0,%0%&\";
3582 * current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
3583 * current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
3586 [(set_attr "type" "cmove")
3587 (set_attr "iscompact" "true,true,true_limm,false,false")
3588 (set_attr "length" "2,2,6,4,8")
3589 (set_attr "cpu_facility" "*,av2,av2,*,*")])
3591 (define_insn "*movsi_cond_exec"
3593 (match_operator 3 "proper_comparison_operator"
3594 [(match_operand 2 "cc_register" "Rcc,Rcc") (const_int 0)])
3595 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
3596 (match_operand:SI 1 "nonmemory_operand" "Lc,?Cal")))]
3599 [(set_attr "type" "cmove")
3600 (set_attr "length" "4,8")])
3602 (define_insn "*commutative_cond_exec"
3604 (match_operator 5 "proper_comparison_operator"
3605 [(match_operand 4 "cc_register" "Rcc,Rcc") (const_int 0)])
3606 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
3607 (match_operator:SI 3 "commutative_operator"
3608 [(match_operand:SI 1 "register_operand" "%0,0")
3609 (match_operand:SI 2 "nonmemory_operand" "cL,?Cal")])))]
3612 arc_output_commutative_cond_exec (operands, true);
3615 [(set_attr "cond" "use")
3616 (set_attr "type" "cmove")
3617 (set_attr_alternative "length"
3620 [(eq (symbol_ref "arc_output_commutative_cond_exec (operands, false)")
3625 (define_insn "*sub_cond_exec"
3627 (match_operator 4 "proper_comparison_operator"
3628 [(match_operand 3 "cc_register" "Rcc,Rcc,Rcc") (const_int 0)])
3629 (set (match_operand:SI 0 "dest_reg_operand" "=w,w,w")
3630 (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,cL,Cal")
3631 (match_operand:SI 2 "nonmemory_operand" "cL,0,0"))))]
3637 [(set_attr "cond" "use")
3638 (set_attr "type" "cmove")
3639 (set_attr "length" "4,4,8")])
3641 (define_insn "*noncommutative_cond_exec"
3643 (match_operator 5 "proper_comparison_operator"
3644 [(match_operand 4 "cc_register" "Rcc,Rcc") (const_int 0)])
3645 (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
3646 (match_operator:SI 3 "noncommutative_operator"
3647 [(match_operand:SI 1 "register_operand" "0,0")
3648 (match_operand:SI 2 "nonmemory_operand" "cL,Cal")])))]
3651 [(set_attr "cond" "use")
3652 (set_attr "type" "cmove")
3653 (set_attr "length" "4,8")])
3655 ;; These control RTL generation for conditional jump insns
3656 ;; Match both normal and inverted jump.
3658 ; We need a separate expander for this lest we loose the mode of CC_REG
3659 ; when match_operator substitutes the literal operand into the comparison.
3660 (define_expand "branch_insn"
3662 (if_then_else (match_operand 1 "" "")
3663 (label_ref (match_operand 0 "" ""))
3666 ; When estimating sizes during arc_reorg, when optimizing for speed, there
3667 ; are three reasons why we need to consider branches to be length 6:
3668 ; - annull-false delay slot insns are implemented using conditional execution,
3669 ; thus preventing short insn formation where used.
3670 ; - for ARC600: annull-true delay slot isnns are implemented where possile
3671 ; using conditional execution, preventing short insn formation where used.
3672 ; - for ARC700: likely or somewhat likely taken branches are made long and
3673 ; unaligned if possible to avoid branch penalty.
3674 (define_insn "*branch_insn"
3676 (if_then_else (match_operator 1 "proper_comparison_operator"
3677 [(reg CC_REG) (const_int 0)])
3678 (label_ref (match_operand 0 "" ""))
3683 if (arc_ccfsm_branch_deleted_p ())
3685 arc_ccfsm_record_branch_deleted ();
3686 return \"; branch deleted, next insns conditionalized\";
3690 arc_ccfsm_record_condition (operands[1], false, insn, 0);
3691 if (get_attr_length (insn) == 2)
3692 return \"b%d1%? %^%l0%&\";
3694 return \"b%d1%# %^%l0\";
3697 [(set_attr "type" "branch")
3701 (eq_attr "delay_slot_filled" "yes")
3706 (match_operand 1 "equality_comparison_operator" "")
3707 (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
3708 (gt (minus (match_dup 0) (pc))
3709 (minus (const_int 506)
3710 (symbol_ref "get_attr_delay_slot_length (insn)"))))
3711 (ior (match_test "!arc_short_comparison_p (operands[1], -64)")
3712 (lt (minus (match_dup 0) (pc)) (const_int -64))
3713 (gt (minus (match_dup 0) (pc))
3714 (minus (const_int 58)
3715 (symbol_ref "get_attr_delay_slot_length (insn)")))))
3720 (set (attr "iscompact")
3721 (cond [(match_test "get_attr_length (insn) == 2") (const_string "true")]
3722 (const_string "false")))])
3724 (define_insn "*rev_branch_insn"
3726 (if_then_else (match_operator 1 "proper_comparison_operator"
3727 [(reg CC_REG) (const_int 0)])
3729 (label_ref (match_operand 0 "" ""))))]
3730 "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
3733 if (arc_ccfsm_branch_deleted_p ())
3735 arc_ccfsm_record_branch_deleted ();
3736 return \"; branch deleted, next insns conditionalized\";
3740 arc_ccfsm_record_condition (operands[1], true, insn, 0);
3741 if (get_attr_length (insn) == 2)
3742 return \"b%D1%? %^%l0\";
3744 return \"b%D1%# %^%l0\";
3747 [(set_attr "type" "branch")
3751 (eq_attr "delay_slot_filled" "yes")
3756 (match_operand 1 "equality_comparison_operator" "")
3757 (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
3758 (gt (minus (match_dup 0) (pc))
3759 (minus (const_int 506)
3760 (symbol_ref "get_attr_delay_slot_length (insn)"))))
3761 (ior (match_test "!arc_short_comparison_p (operands[1], -64)")
3762 (lt (minus (match_dup 0) (pc)) (const_int -64))
3763 (gt (minus (match_dup 0) (pc))
3764 (minus (const_int 58)
3765 (symbol_ref "get_attr_delay_slot_length (insn)")))))
3770 (set (attr "iscompact")
3771 (cond [(match_test "get_attr_length (insn) == 2") (const_string "true")]
3772 (const_string "false")))])
3774 ;; Unconditional and other jump instructions.
3776 (define_expand "jump"
3777 [(set (pc) (label_ref (match_operand 0 "" "")))]
3781 (define_insn "jump_i"
3782 [(set (pc) (label_ref (match_operand 0 "" "")))]
3783 "!TARGET_LONG_CALLS_SET || !CROSSING_JUMP_P (insn)"
3785 [(set_attr "type" "uncond_branch")
3786 (set (attr "iscompact")
3787 (if_then_else (match_test "get_attr_length (insn) == 2")
3788 (const_string "true") (const_string "false")))
3789 (set_attr "cond" "canuse")
3790 (set (attr "length")
3792 ; In arc_reorg we just guesstimate; might be more or less than 4.
3793 (match_test "arc_branch_size_unknown_p ()")
3796 (eq_attr "delay_slot_filled" "yes")
3799 (match_test "CROSSING_JUMP_P (insn)")
3802 (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
3803 (gt (minus (match_dup 0) (pc))
3804 (minus (const_int 506)
3805 (symbol_ref "get_attr_delay_slot_length (insn)"))))
3809 (define_insn "indirect_jump"
3810 [(set (pc) (match_operand:SI 0 "nonmemory_operand" "L,I,Cal,Rcqq,r"))]
3818 [(set_attr "type" "jump")
3819 (set_attr "iscompact" "false,false,false,maybe,false")
3820 (set_attr "cond" "canuse,canuse_limm,canuse,canuse,canuse")])
3822 ;; Implement a switch statement.
3824 (define_expand "casesi"
3826 (minus:SI (match_operand:SI 0 "register_operand" "")
3827 (match_operand:SI 1 "nonmemory_operand" "")))
3828 (set (reg:CC CC_REG)
3829 (compare:CC (match_dup 5)
3830 (match_operand:SI 2 "nonmemory_operand" "")))
3832 (if_then_else (gtu (reg:CC CC_REG)
3834 (label_ref (match_operand 4 "" ""))
3837 (unspec:SI [(match_operand 3 "" "")
3838 (match_dup 5) (match_dup 7)] UNSPEC_ARC_CASESI))
3839 (parallel [(set (pc) (match_dup 6)) (use (match_dup 7))])]
3845 operands[5] = gen_reg_rtx (SImode);
3846 operands[6] = gen_reg_rtx (SImode);
3847 operands[7] = operands[3];
3848 emit_insn (gen_subsi3 (operands[5], operands[0], operands[1]));
3849 emit_insn (gen_cmpsi_cc_insn_mixed (operands[5], operands[2]));
3850 x = gen_rtx_GTU (VOIDmode, gen_rtx_REG (CCmode, CC_REG), const0_rtx);
3851 x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
3852 gen_rtx_LABEL_REF (VOIDmode, operands[4]), pc_rtx);
3853 emit_jump_insn (gen_rtx_SET (pc_rtx, x));
3854 if (TARGET_COMPACT_CASESI)
3856 emit_jump_insn (gen_casesi_compact_jump (operands[5], operands[7]));
3860 operands[3] = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
3861 if (flag_pic || !cse_not_expected)
3862 operands[3] = force_reg (Pmode, operands[3]);
3863 emit_insn (gen_casesi_load (operands[6],
3864 operands[3], operands[5], operands[7]));
3865 if (CASE_VECTOR_PC_RELATIVE || flag_pic)
3866 emit_insn (gen_addsi3 (operands[6], operands[6], operands[3]));
3867 emit_jump_insn (gen_casesi_jump (operands[6], operands[7]));
3872 (define_insn "casesi_load"
3873 [(set (match_operand:SI 0 "register_operand" "=Rcq,r,r")
3874 (unspec:SI [(match_operand:SI 1 "nonmemory_operand" "Rcq,c,Cal")
3875 (match_operand:SI 2 "register_operand" "Rcq,c,c")
3876 (label_ref (match_operand 3 "" ""))] UNSPEC_ARC_CASESI))]
3880 rtx diff_vec = PATTERN (next_nonnote_insn (operands[3]));
3882 if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
3884 gcc_assert (GET_CODE (diff_vec) == ADDR_VEC);
3885 gcc_assert (GET_MODE (diff_vec) == SImode);
3886 gcc_assert (!CASE_VECTOR_PC_RELATIVE && !flag_pic);
3889 switch (GET_MODE (diff_vec))
3892 return \"ld.as %0,[%1,%2]%&\";
3894 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
3895 return \"ld%_.as %0,[%1,%2]\";
3896 return \"ld%_.x.as %0,[%1,%2]\";
3898 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
3899 return \"ldb%? %0,[%1,%2]%&\";
3900 return \"ldb.x %0,[%1,%2]\";
3905 [(set_attr "type" "load")
3906 (set_attr_alternative "iscompact"
3908 [(ne (symbol_ref "GET_MODE (PATTERN (next_nonnote_insn (operands[3])))")
3909 (symbol_ref "QImode"))
3910 (const_string "false")
3911 (match_test "!ADDR_DIFF_VEC_FLAGS (PATTERN (next_nonnote_insn (operands[3]))).offset_unsigned")
3912 (const_string "false")]
3913 (const_string "true"))
3914 (const_string "false")
3915 (const_string "false")])
3916 (set_attr_alternative "length"
3918 [(eq_attr "iscompact" "false") (const_int 4)
3919 ; We have to mention (match_dup 3) to convince genattrtab.c that this
3920 ; is a varying length insn.
3921 (eq (symbol_ref "1+1") (const_int 2)) (const_int 2)
3922 (gt (minus (match_dup 3) (pc)) (const_int 42)) (const_int 4)]
3927 ; Unlike the canonical tablejump, this pattern always uses a jump address,
3928 ; even for CASE_VECTOR_PC_RELATIVE.
3929 (define_insn "casesi_jump"
3930 [(set (pc) (match_operand:SI 0 "register_operand" "Cal,Rcqq,c"))
3931 (use (label_ref (match_operand 1 "" "")))]
3934 [(set_attr "type" "jump")
3935 (set_attr "iscompact" "false,maybe,false")
3936 (set_attr "cond" "canuse")])
3938 (define_insn "casesi_compact_jump"
3940 (unspec:SI [(match_operand:SI 0 "register_operand" "c,q")]
3942 (use (label_ref (match_operand 1 "" "")))
3943 (clobber (match_scratch:SI 2 "=q,0"))]
3944 "TARGET_COMPACT_CASESI"
3947 rtx diff_vec = PATTERN (next_nonnote_insn (operands[1]));
3948 int unalign = arc_get_unalign ();
3952 xop[0] = operands[0];
3953 xop[2] = operands[2];
3954 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
3956 switch (GET_MODE (diff_vec))
3959 /* Max length can be 12 in this case, but this is OK because
3960 2 of these are for alignment, and are anticipated in the length
3961 of the ADDR_DIFF_VEC. */
3962 if (unalign && !satisfies_constraint_Rcq (xop[0]))
3963 s = \"add2 %2,pcl,%0\n\tld_s %2,[%2,12]\";
3965 s = \"add_s %2,%0,2\n\tld.as %2,[pcl,%2]\";
3967 s = \"add %2,%0,2\n\tld.as %2,[pcl,%2]\";
3968 arc_clear_unalign ();
3971 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
3973 if (satisfies_constraint_Rcq (xop[0]))
3975 s = \"add_s %2,%0,%1\n\tld%_.as %2,[pcl,%2]\";
3976 xop[1] = GEN_INT ((10 - unalign) / 2U);
3980 s = \"add1 %2,pcl,%0\n\tld%__s %2,[%2,%1]\";
3981 xop[1] = GEN_INT (10 + unalign);
3986 if (satisfies_constraint_Rcq (xop[0]))
3988 s = \"add_s %2,%0,%1\n\tld%_.x.as %2,[pcl,%2]\";
3989 xop[1] = GEN_INT ((10 - unalign) / 2U);
3993 s = \"add1 %2,pcl,%0\n\tld%__s.x %2,[%2,%1]\";
3994 xop[1] = GEN_INT (10 + unalign);
3997 arc_toggle_unalign ();
4000 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
4002 if ((rtx_equal_p (xop[2], xop[0])
4003 || find_reg_note (insn, REG_DEAD, xop[0]))
4004 && satisfies_constraint_Rcq (xop[0]))
4006 s = \"add_s %0,%0,pcl\n\tldb_s %2,[%0,%1]\";
4007 xop[1] = GEN_INT (8 + unalign);
4011 s = \"add %2,%0,pcl\n\tldb_s %2,[%2,%1]\";
4012 xop[1] = GEN_INT (10 + unalign);
4013 arc_toggle_unalign ();
4016 else if ((rtx_equal_p (xop[0], xop[2])
4017 || find_reg_note (insn, REG_DEAD, xop[0]))
4018 && satisfies_constraint_Rcq (xop[0]))
4020 s = \"add_s %0,%0,%1\n\tldb.x %2,[pcl,%0]\";
4021 xop[1] = GEN_INT (10 - unalign);
4022 arc_toggle_unalign ();
4026 /* ??? Length is 12. */
4027 s = \"add %2,%0,%1\n\tldb.x %2,[pcl,%2]\";
4028 xop[1] = GEN_INT (8 + unalign);
4034 output_asm_insn (s, xop);
4035 return \"add_s %2,%2,pcl\n\tj_s%* [%2]\";
4037 [(set_attr "length" "10")
4038 (set_attr "type" "jump")
4039 (set_attr "iscompact" "true")
4040 (set_attr "cond" "nocond")])
4042 (define_expand "call"
4043 ;; operands[1] is stack_size_rtx
4044 ;; operands[2] is next_arg_register
4045 [(parallel [(call (match_operand:SI 0 "call_operand" "")
4046 (match_operand 1 "" ""))
4047 (clobber (reg:SI 31))])]
4052 gcc_assert (MEM_P (operands[0]));
4053 callee = XEXP (operands[0], 0);
4054 if (crtl->profile && arc_profile_call (callee))
4056 emit_call_insn (gen_call_prof (gen_rtx_SYMBOL_REF (Pmode,
4061 /* This is to decide if we should generate indirect calls by loading the
4062 32 bit address of the callee into a register before performing the
4063 branch and link - this exposes cse opportunities.
4064 Also, in weird cases like compile/20010107-1.c, we may get a PLUS. */
4065 if (GET_CODE (callee) != REG
4066 && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
4067 XEXP (operands[0], 0) = force_reg (Pmode, callee);
4072 ; Rcq, which is used in alternative 0, checks for conditional execution.
4073 ; At instruction output time, if it doesn't match and we end up with
4074 ; alternative 1 ("q"), that means that we can't use the short form.
4075 (define_insn "*call_i"
4076 [(call (mem:SI (match_operand:SI 0
4077 "call_address_operand" "Rcq,q,c,Cbp,Cbr,L,I,Cal"))
4078 (match_operand 1 "" ""))
4079 (clobber (reg:SI 31))]
4090 [(set_attr "type" "call,call,call,call,call,call,call,call_no_delay_slot")
4091 (set_attr "iscompact" "maybe,false,*,*,*,*,*,*")
4092 (set_attr "predicable" "no,no,yes,yes,no,yes,no,yes")
4093 (set_attr "length" "*,*,4,4,4,4,4,8")])
4095 (define_insn "call_prof"
4096 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "Cbr,Cal"))
4097 (match_operand 1 "" ""))
4098 (clobber (reg:SI 31))
4105 [(set_attr "type" "call,call_no_delay_slot")
4106 (set_attr "predicable" "yes,yes")
4107 (set_attr "length" "4,8")])
4109 (define_expand "call_value"
4110 ;; operand 2 is stack_size_rtx
4111 ;; operand 3 is next_arg_register
4112 [(parallel [(set (match_operand 0 "dest_reg_operand" "=r")
4113 (call (match_operand:SI 1 "call_operand" "")
4114 (match_operand 2 "" "")))
4115 (clobber (reg:SI 31))])]
4121 gcc_assert (MEM_P (operands[1]));
4122 callee = XEXP (operands[1], 0);
4123 if (crtl->profile && arc_profile_call (callee))
4125 emit_call_insn (gen_call_value_prof (operands[0],
4126 gen_rtx_SYMBOL_REF (Pmode,
4131 /* See the comment in define_expand \"call\". */
4132 if (GET_CODE (callee) != REG
4133 && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
4134 XEXP (operands[1], 0) = force_reg (Pmode, callee);
4138 ; Rcq, which is used in alternative 0, checks for conditional execution.
4139 ; At instruction output time, if it doesn't match and we end up with
4140 ; alternative 1 ("q"), that means that we can't use the short form.
4141 (define_insn "*call_value_i"
4142 [(set (match_operand 0 "dest_reg_operand" "=Rcq,q,w, w, w,w,w, w")
4143 (call (mem:SI (match_operand:SI 1
4144 "call_address_operand" "Rcq,q,c,Cbp,Cbr,L,I,Cal"))
4145 (match_operand 2 "" "")))
4146 (clobber (reg:SI 31))]
4157 [(set_attr "type" "call,call,call,call,call,call,call,call_no_delay_slot")
4158 (set_attr "iscompact" "maybe,false,*,*,*,*,*,*")
4159 (set_attr "predicable" "no,no,yes,yes,no,yes,no,yes")
4160 (set_attr "length" "*,*,4,4,4,4,4,8")])
4162 ; There is a bl_s instruction (16 bit opcode branch-and-link), but we can't
4163 ; use it for lack of inter-procedural branch shortening.
4164 ; Link-time relaxation would help...
4167 (define_insn "call_value_prof"
4168 [(set (match_operand 0 "dest_reg_operand" "=r,r")
4169 (call (mem:SI (match_operand:SI 1 "symbolic_operand" "Cbr,Cal"))
4170 (match_operand 2 "" "")))
4171 (clobber (reg:SI 31))
4178 [(set_attr "type" "call,call_no_delay_slot")
4179 (set_attr "predicable" "yes,yes")
4180 (set_attr "length" "4,8")])
4186 [(set_attr "type" "misc")
4187 (set_attr "iscompact" "true")
4188 (set_attr "cond" "canuse")
4189 (set_attr "length" "2")])
4192 [(unspec_volatile [(const_int 0)] VUNSPEC_ARC_NOP)]
4195 [(set_attr "type" "misc")
4196 (set_attr "iscompact" "true")
4197 (set_attr "length" "2")])
4199 ;; Special pattern to flush the icache.
4200 ;; ??? Not sure what to do here. Some ARC's are known to support this.
4202 (define_insn "flush_icache"
4203 [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] 0)]
4206 [(set_attr "type" "misc")])
4208 ;; Split up troublesome insns for better scheduling.
4210 ;; Peepholes go at the end.
4211 ;;asl followed by add can be replaced by an add{1,2,3}
4212 ;; Three define_peepholes have been added for this optimization
4213 ;; ??? This used to target non-canonical rtl. Now we use add_n, which
4214 ;; can be generated by combine. Check if these peepholes still provide
4217 ;; -------------------------------------------------------------
4218 ;; Pattern 1 : r0 = r1 << {i}
4219 ;; r3 = r4/INT + r0 ;;and commutative
4222 ;; add{i} r3,r4/INT,r1
4223 ;; -------------------------------------------------------------
4224 ;; ??? This should be covered by combine, alas, at times combine gets
4225 ;; too clever for it's own good: when the shifted input is known to be
4226 ;; either 0 or 1, the operation will be made into an if-then-else, and
4227 ;; thus fail to match the add_n pattern. Example: _mktm_r, line 85 in
4228 ;; newlib/libc/time/mktm_r.c .
4231 [(set (match_operand:SI 0 "dest_reg_operand" "")
4232 (ashift:SI (match_operand:SI 1 "register_operand" "")
4233 (match_operand:SI 2 "const_int_operand" "")))
4234 (set (match_operand:SI 3 "dest_reg_operand" "")
4235 (plus:SI (match_operand:SI 4 "nonmemory_operand" "")
4236 (match_operand:SI 5 "nonmemory_operand" "")))]
4237 "(INTVAL (operands[2]) == 1
4238 || INTVAL (operands[2]) == 2
4239 || INTVAL (operands[2]) == 3)
4240 && (true_regnum (operands[4]) == true_regnum (operands[0])
4241 || true_regnum (operands[5]) == true_regnum (operands[0]))
4242 && (peep2_reg_dead_p (2, operands[0]) || (true_regnum (operands[3]) == true_regnum (operands[0])))"
4243 ;; the preparation statements take care to put proper operand in operands[4]
4244 ;; operands[4] will always contain the correct operand. This is added to satisfy commutativity
4246 (plus:SI (mult:SI (match_dup 1)
4249 "if (true_regnum (operands[4]) == true_regnum (operands[0]))
4250 operands[4] = operands[5];
4251 operands[2] = GEN_INT (1 << INTVAL (operands[2]));"
4254 ;; -------------------------------------------------------------
4255 ;; Pattern 1 : r0 = r1 << {i}
4260 ;; -------------------------------------------------------------
4261 ;; ??? This should be covered by combine, alas, at times combine gets
4262 ;; too clever for it's own good: when the shifted input is known to be
4263 ;; either 0 or 1, the operation will be made into an if-then-else, and
4264 ;; thus fail to match the sub_n pattern. Example: __ieee754_yn, line 239 in
4265 ;; newlib/libm/math/e_jn.c .
4268 [(set (match_operand:SI 0 "dest_reg_operand" "")
4269 (ashift:SI (match_operand:SI 1 "register_operand" "")
4270 (match_operand:SI 2 "const_int_operand" "")))
4271 (set (match_operand:SI 3 "dest_reg_operand" "")
4272 (minus:SI (match_operand:SI 4 "nonmemory_operand" "")
4274 "(INTVAL (operands[2]) == 1
4275 || INTVAL (operands[2]) == 2
4276 || INTVAL (operands[2]) == 3)
4277 && (peep2_reg_dead_p (2, operands[0])
4278 || (true_regnum (operands[3]) == true_regnum (operands[0])))"
4280 (minus:SI (match_dup 4)
4281 (mult:SI (match_dup 1)
4283 "operands[2] = GEN_INT (1 << INTVAL (operands[2]));"
4288 ; When using the high single bit, the result of a multiply is either
4289 ; the original number or zero. But MPY costs 4 cycles, which we
4290 ; can replace with the 2 cycles for the pair of TST_S and ADD.NE.
4292 [(set (match_operand:SI 0 "dest_reg_operand" "")
4293 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4295 (set (match_operand:SI 4 "register_operand" "")
4296 (mult:SI (match_operand:SI 2 "register_operand")
4297 (match_operand:SI 3 "nonmemory_operand" "")))]
4299 && (rtx_equal_p (operands[0], operands[2])
4300 || rtx_equal_p (operands[0], operands[3]))
4301 && peep2_regno_dead_p (0, CC_REG)
4302 && (rtx_equal_p (operands[0], operands[4])
4303 || (peep2_reg_dead_p (2, operands[0])
4304 && peep2_reg_dead_p (1, operands[4])))"
4305 [(parallel [(set (reg:CC_Z CC_REG)
4306 (compare:CC_Z (lshiftrt:SI (match_dup 1) (const_int 31))
4308 (set (match_dup 4) (lshiftrt:SI (match_dup 1) (const_int 31)))])
4310 (ne (reg:CC_Z CC_REG) (const_int 0))
4311 (set (match_dup 4) (match_dup 5)))]
4313 if (!rtx_equal_p (operands[0], operands[2]))
4314 operands[5] = operands[2];
4315 else if (!rtx_equal_p (operands[0], operands[3]))
4316 operands[5] = operands[3];
4318 operands[5] = operands[4]; /* Actually a no-op... presumably rare. */
4322 [(set (match_operand:SI 0 "dest_reg_operand" "")
4323 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4325 (set (match_operand:SI 4 "register_operand" "")
4326 (mult:SI (match_operand:SI 2 "register_operand")
4327 (match_operand:SI 3 "nonmemory_operand" "")))]
4329 && (rtx_equal_p (operands[0], operands[2])
4330 || rtx_equal_p (operands[0], operands[3]))
4331 && peep2_regno_dead_p (2, CC_REG)"
4332 [(parallel [(set (reg:CC_Z CC_REG)
4333 (compare:CC_Z (lshiftrt:SI (match_dup 1) (const_int 31))
4335 (set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
4336 (set (match_dup 4) (match_dup 5))
4338 (eq (reg:CC_Z CC_REG) (const_int 0))
4339 (set (match_dup 4) (const_int 0)))]
4340 "operands[5] = operands[rtx_equal_p (operands[0], operands[2]) ? 3 : 2];")
4342 ;; Instructions generated through builtins
4344 (define_insn "clrsbsi2"
4345 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
4346 (clrsb:SI (match_operand:SI 1 "general_operand" "cL,Cal")))]
4351 [(set_attr "length" "4,8")
4352 (set_attr "type" "two_cycle_core,two_cycle_core")])
4354 (define_insn "norm_f"
4355 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
4356 (clrsb:SI (match_operand:SI 1 "general_operand" "cL,Cal")))
4357 (set (reg:CC_ZN CC_REG)
4358 (compare:CC_ZN (match_dup 1) (const_int 0)))]
4363 [(set_attr "length" "4,8")
4364 (set_attr "type" "two_cycle_core,two_cycle_core")])
4366 (define_insn_and_split "clrsbhi2"
4367 [(set (match_operand:HI 0 "dest_reg_operand" "=w,w")
4368 (clrsb:HI (match_operand:HI 1 "general_operand" "cL,Cal")))]
4372 [(set (match_dup 0) (zero_extend:SI (clrsb:HI (match_dup 1))))]
4373 "operands[0] = simplify_gen_subreg (SImode, operands[0], HImode, 0);")
4375 (define_insn "normw"
4376 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
4378 (clrsb:HI (match_operand:HI 1 "general_operand" "cL,Cal"))))]
4383 [(set_attr "length" "4,8")
4384 (set_attr "type" "two_cycle_core,two_cycle_core")])
4386 (define_expand "clzsi2"
4387 [(set (match_operand:SI 0 "dest_reg_operand" "")
4388 (clz:SI (match_operand:SI 1 "register_operand" "")))]
4391 emit_insn (gen_norm_f (operands[0], operands[1]));
4395 gen_rtx_LT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4396 gen_rtx_SET (operands[0], const0_rtx)));
4400 gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4401 gen_rtx_SET (operands[0], plus_constant (SImode, operands[0], 1))));
4405 (define_expand "ctzsi2"
4406 [(set (match_operand:SI 0 "register_operand" "")
4407 (ctz:SI (match_operand:SI 1 "register_operand" "")))]
4410 rtx temp = operands[0];
4412 if (reg_overlap_mentioned_p (temp, operands[1])
4413 || (REGNO (temp) < FIRST_PSEUDO_REGISTER
4414 && !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS],
4416 temp = gen_reg_rtx (SImode);
4417 emit_insn (gen_addsi3 (temp, operands[1], constm1_rtx));
4418 emit_insn (gen_bic_f_zn (temp, temp, operands[1]));
4419 emit_insn (gen_clrsbsi2 (temp, temp));
4423 gen_rtx_LT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4424 gen_rtx_SET (operands[0], GEN_INT (32))));
4428 gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
4429 gen_rtx_SET (operands[0], gen_rtx_MINUS (SImode, GEN_INT (31), temp))));
4435 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w,w")
4436 (unspec:SI [(match_operand:SI 1 "general_operand" "L,Cal,c")]
4443 [(set_attr "length" "4,8,4")
4444 (set_attr "type" "two_cycle_core,two_cycle_core,two_cycle_core")])
4446 (define_insn "divaw"
4447 [(set (match_operand:SI 0 "dest_reg_operand" "=&w,&w,&w")
4448 (unspec:SI [(div:SI (match_operand:SI 1 "general_operand" "r,Cal,r")
4449 (match_operand:SI 2 "general_operand" "r,r,Cal"))]
4451 "TARGET_ARC700 || TARGET_EA_SET"
4455 divaw \t%0, %1, %S2"
4456 [(set_attr "length" "4,8,8")
4457 (set_attr "type" "divaw,divaw,divaw")])
4460 [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")]
4467 [(set_attr "length" "4,4,8")
4468 (set_attr "type" "misc,misc,misc")
4469 (set_attr "predicable" "yes,no,yes")
4470 (set_attr "cond" "clob,clob,clob")])
4473 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4477 [(set_attr "length" "4")
4478 (set_attr "type" "misc")])
4481 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4485 [(set_attr "length" "4")
4486 (set_attr "type" "misc")
4487 (set_attr "cond" "clob")])
4490 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4494 [(set_attr "length" "4")
4495 (set_attr "type" "misc")])
4498 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4508 [(set_attr "length" "4")
4509 (set_attr "type" "misc")])
4512 (define_insn "sleep"
4513 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "L")]
4515 "check_if_valid_sleep_operand(operands,0)"
4517 [(set_attr "length" "4")
4518 (set_attr "type" "misc")])
4520 (define_insn "core_read"
4521 [(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
4522 (unspec_volatile:SI [(match_operand:SI 1 "general_operand" "Hn,!r")]
4523 VUNSPEC_ARC_CORE_READ))]
4526 if (check_if_valid_regno_const (operands, 1))
4527 return \"mov \t%0, r%1\";
4528 return \"mov \t%0, r%1\";
4530 [(set_attr "length" "4")
4531 (set_attr "type" "unary")])
4533 (define_insn "core_write"
4534 [(unspec_volatile [(match_operand:SI 0 "general_operand" "r,r")
4535 (match_operand:SI 1 "general_operand" "Hn,!r")]
4536 VUNSPEC_ARC_CORE_WRITE)]
4539 if (check_if_valid_regno_const (operands, 1))
4540 return \"mov \tr%1, %0\";
4541 return \"mov \tr%1, %0\";
4543 [(set_attr "length" "4")
4544 (set_attr "type" "unary")])
4547 [(set (match_operand:SI 0 "dest_reg_operand" "=r,r,r,r")
4548 (unspec_volatile:SI [(match_operand:SI 1 "general_operand" "I,HCal,r,D")]
4552 [(set_attr "length" "4,8,4,8")
4553 (set_attr "type" "lr,lr,lr,lr")])
4556 [(unspec_volatile [(match_operand:SI 0 "general_operand" "Cal,r,r,r")
4557 (match_operand:SI 1 "general_operand" "Ir,I,HCal,r")]
4561 [(set_attr "length" "8,4,8,4")
4562 (set_attr "type" "sr,sr,sr,sr")])
4564 (define_insn "trap_s"
4565 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "L,Cal")]
4566 VUNSPEC_ARC_TRAP_S)]
4567 "!TARGET_ARC600_FAMILY"
4569 if (which_alternative == 0)
4571 arc_toggle_unalign ();
4572 return \"trap_s %0\";
4575 /* Keep this message in sync with the one in arc.c:arc_expand_builtin,
4576 because *.md files do not get scanned by exgettext. */
4577 fatal_error (input_location,
4578 \"operand to trap_s should be an unsigned 6-bit value\");
4580 [(set_attr "length" "2")
4581 (set_attr "type" "misc")])
4583 (define_insn "unimp_s"
4584 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
4585 VUNSPEC_ARC_UNIMP_S)]
4586 "!TARGET_ARC600_FAMILY"
4588 [(set_attr "length" "4")
4589 (set_attr "type" "misc")])
4591 ;; End of instructions generated through builtins
4593 ; Since the demise of REG_N_SETS as reliable data readily available to the
4594 ; target, it is no longer possible to find out
4595 ; in the prologue / epilogue expanders how many times blink is set.
4596 ; Using df_regs_ever_live_p to decide if blink needs saving means that
4597 ; any explicit use of blink will cause it to be saved; hence we cannot
4598 ; represent the blink use in return / sibcall instructions themselves, and
4599 ; instead have to show it in EPILOGUE_USES and must explicitly
4600 ; forbid instructions that change blink in the return / sibcall delay slot.
4601 (define_expand "sibcall"
4602 [(parallel [(call (match_operand 0 "memory_operand" "")
4603 (match_operand 1 "general_operand" ""))
4605 (use (match_operand 2 "" ""))])]
4609 rtx callee = XEXP (operands[0], 0);
4611 if (operands[2] == NULL_RTX)
4612 operands[2] = const0_rtx;
4613 if (crtl->profile && arc_profile_call (callee))
4615 emit_insn (gen_sibcall_prof
4616 (gen_rtx_SYMBOL_REF (Pmode, \"_mcount_call\"),
4617 operands[1], operands[2]));
4620 if (GET_CODE (callee) != REG
4621 && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
4622 XEXP (operands[0], 0) = force_reg (Pmode, callee);
4626 (define_expand "sibcall_value"
4627 [(parallel [(set (match_operand 0 "dest_reg_operand" "")
4628 (call (match_operand 1 "memory_operand" "")
4629 (match_operand 2 "general_operand" "")))
4631 (use (match_operand 3 "" ""))])]
4635 rtx callee = XEXP (operands[1], 0);
4637 if (operands[3] == NULL_RTX)
4638 operands[3] = const0_rtx;
4639 if (crtl->profile && arc_profile_call (XEXP (operands[1], 0)))
4641 emit_insn (gen_sibcall_value_prof
4642 (operands[0], gen_rtx_SYMBOL_REF (Pmode, \"_mcount_call\"),
4643 operands[2], operands[3]));
4646 if (GET_CODE (callee) != REG && arc_is_longcall_p (callee))
4647 XEXP (operands[1], 0) = force_reg (Pmode, callee);
4651 (define_insn "*sibcall_insn"
4652 [(call (mem:SI (match_operand:SI 0 "call_address_operand"
4653 "Cbp,Cbr,Rs5,Rsc,Cal"))
4654 (match_operand 1 "" ""))
4656 (use (match_operand 2 "" ""))]
4664 [(set_attr "type" "call,call,call,call,call_no_delay_slot")
4665 (set_attr "predicable" "yes,no,no,yes,yes")
4666 (set_attr "iscompact" "false,false,maybe,false,false")
4667 (set_attr "is_SIBCALL" "yes")]
4670 (define_insn "*sibcall_value_insn"
4671 [(set (match_operand 0 "dest_reg_operand" "")
4672 (call (mem:SI (match_operand:SI 1 "call_address_operand"
4673 "Cbp,Cbr,Rs5,Rsc,Cal"))
4674 (match_operand 2 "" "")))
4676 (use (match_operand 3 "" ""))]
4684 [(set_attr "type" "call,call,call,call,call_no_delay_slot")
4685 (set_attr "predicable" "yes,no,no,yes,yes")
4686 (set_attr "iscompact" "false,false,maybe,false,false")
4687 (set_attr "is_SIBCALL" "yes")]
4690 (define_insn "sibcall_prof"
4691 [(call (mem:SI (match_operand:SI 0 "call_address_operand" "Cbr,Cal"))
4692 (match_operand 1 "" ""))
4694 (use (match_operand 2 "" ""))
4701 [(set_attr "type" "call,call_no_delay_slot")
4702 (set_attr "predicable" "yes")
4703 (set_attr "is_SIBCALL" "yes")]
4706 (define_insn "sibcall_value_prof"
4707 [(set (match_operand 0 "dest_reg_operand" "")
4708 (call (mem:SI (match_operand:SI 1 "call_address_operand" "Cbr,Cal"))
4709 (match_operand 2 "" "")))
4711 (use (match_operand 3 "" ""))
4718 [(set_attr "type" "call,call_no_delay_slot")
4719 (set_attr "predicable" "yes")
4720 (set_attr "is_SIBCALL" "yes")]
4723 (define_expand "prologue"
4727 arc_expand_prologue ();
4731 (define_expand "epilogue"
4735 arc_expand_epilogue (0);
4739 (define_expand "sibcall_epilogue"
4743 arc_expand_epilogue (1);
4747 ; Since the demise of REG_N_SETS, it is no longer possible to find out
4748 ; in the prologue / epilogue expanders how many times blink is set.
4749 ; Using df_regs_ever_live_p to decide if blink needs saving means that
4750 ; any explicit use of blink will cause it to be saved; hence we cannot
4751 ; represent the blink use in return / sibcall instructions themselves, and
4752 ; instead have to show it in EPILOGUE_USES and must explicitly
4753 ; forbid instructions that change blink in the return / sibcall delay slot.
4754 (define_insn "simple_return"
4759 = gen_rtx_REG (Pmode,
4760 arc_return_address_regs[arc_compute_function_type (cfun)]);
4762 if (arc_compute_function_type (cfun) == ARC_FUNCTION_ILINK1
4767 if (TARGET_PAD_RETURN)
4769 output_asm_insn (\"j%!%* [%0]%&\", ®);
4772 [(set_attr "type" "return")
4773 ; predicable won't help here since the canonical rtl looks different
4776 (cond [(and (eq (symbol_ref "arc_compute_function_type (cfun)")
4777 (symbol_ref "ARC_FUNCTION_ILINK1"))
4778 (match_test "TARGET_V2"))
4779 (const_string "nocond")]
4780 (const_string "canuse")))
4781 (set (attr "iscompact")
4782 (cond [(eq (symbol_ref "arc_compute_function_type (cfun)")
4783 (symbol_ref "ARC_FUNCTION_NORMAL"))
4784 (const_string "maybe")]
4785 (const_string "false")))
4786 (set (attr "length")
4787 (cond [(ne (symbol_ref "arc_compute_function_type (cfun)")
4788 (symbol_ref "ARC_FUNCTION_NORMAL"))
4792 (define_insn "p_return_i"
4794 (if_then_else (match_operator 0 "proper_comparison_operator"
4795 [(reg CC_REG) (const_int 0)])
4796 (simple_return) (pc)))]
4799 && arc_compute_function_type (cfun) == ARC_FUNCTION_ILINK1)"
4802 xop[0] = operands[0];
4804 = gen_rtx_REG (Pmode,
4805 arc_return_address_regs[arc_compute_function_type (cfun)]);
4807 if (TARGET_PAD_RETURN)
4809 output_asm_insn (\"j%d0%!%# [%1]%&\", xop);
4810 /* record the condition in case there is a delay insn. */
4811 arc_ccfsm_record_condition (xop[0], false, insn, 0);
4814 [(set_attr "type" "return")
4815 (set_attr "cond" "use")
4816 (set (attr "iscompact")
4817 (cond [(eq (symbol_ref "arc_compute_function_type (cfun)")
4818 (symbol_ref "ARC_FUNCTION_NORMAL"))
4819 (const_string "maybe")]
4820 (const_string "false")))
4821 (set (attr "length")
4822 (cond [(ne (symbol_ref "arc_compute_function_type (cfun)")
4823 (symbol_ref "ARC_FUNCTION_NORMAL"))
4825 (not (match_operand 0 "equality_comparison_operator" ""))
4827 (eq_attr "delay_slot_filled" "yes")
4831 (define_insn_and_split "eh_return"
4833 (use (match_operand:SI 0 "move_src_operand" "rC32,mCalCpc"))
4834 (clobber (match_scratch:SI 1 "=X,r"))
4835 (clobber (match_scratch:SI 2 "=&r,r"))]
4839 [(set (match_dup 2) (match_dup 0))]
4841 int offs = arc_return_slot_offset ();
4844 operands[2] = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
4847 if (!register_operand (operands[0], Pmode)
4848 && !satisfies_constraint_C32 (operands[0]))
4850 emit_move_insn (operands[1], operands[0]);
4851 operands[0] = operands[1];
4853 rtx addr = plus_constant (Pmode, stack_pointer_rtx, offs);
4854 if (!strict_memory_address_p (Pmode, addr))
4856 emit_move_insn (operands[2], addr);
4859 operands[2] = gen_frame_mem (Pmode, addr);
4862 [(set_attr "length" "12")])
4864 ;; ??? #ifdefs in function.c require the presence of this pattern, with a
4865 ;; non-constant predicate.
4866 (define_expand "return"
4870 ;; Comment in final.c (insn_current_reference_address) says
4871 ;; forward branch addresses are calculated from the next insn after branch
4872 ;; and for backward branches, it is calculated from the branch insn start.
4873 ;; The shortening logic here is tuned to accomodate this behavior
4874 ;; ??? This should be grokked by the ccfsm machinery.
4875 (define_insn "cbranchsi4_scratch"
4877 (if_then_else (match_operator 0 "proper_comparison_operator"
4878 [(match_operand:SI 1 "register_operand" "c,c, c")
4879 (match_operand:SI 2 "nonmemory_operand" "L,c,?Cal")])
4880 (label_ref (match_operand 3 "" ""))
4882 (clobber (match_operand 4 "cc_register" ""))]
4884 || (TARGET_EARLY_CBRANCHSI
4885 && brcc_nolimm_operator (operands[0], VOIDmode)))
4886 && !CROSSING_JUMP_P (insn)"
4888 switch (get_attr_length (insn))
4890 case 2: return \"br%d0%? %1, %2, %^%l3%&\";
4891 case 4: return \"br%d0%* %1, %B2, %^%l3\";
4892 case 8: if (!brcc_nolimm_operator (operands[0], VOIDmode))
4893 return \"br%d0%* %1, %B2, %^%l3\";
4895 case 12:return \"cmp%? %1, %B2\\n\\tb%d0%* %^%l3%&;br%d0 out of range\";
4896 default: fprintf (stderr, \"unexpected length %d\\n\", get_attr_length (insn)); fflush (stderr); gcc_unreachable ();
4899 [(set_attr "cond" "clob, clob, clob")
4902 (match_test "valid_brcc_with_delay_p (operands)")
4903 (const_string "brcc")
4904 (const_string "brcc_no_delay_slot")))
4905 ; For forward branches, we need to account not only for the distance to
4906 ; the target, but also the difference between pcl and pc, the instruction
4907 ; length, and any delay insn, if present.
4910 (cond ; the outer cond does a test independent of branch shortening.
4911 [(match_operand 0 "brcc_nolimm_operator" "")
4913 [(and (match_operand:CC_Z 4 "cc_register")
4914 (eq_attr "delay_slot_filled" "no")
4915 (ge (minus (match_dup 3) (pc)) (const_int -128))
4916 (le (minus (match_dup 3) (pc))
4917 (minus (const_int 122)
4918 (symbol_ref "get_attr_delay_slot_length (insn)"))))
4920 (and (ge (minus (match_dup 3) (pc)) (const_int -256))
4921 (le (minus (match_dup 3) (pc))
4922 (minus (const_int 244)
4923 (symbol_ref "get_attr_delay_slot_length (insn)"))))
4925 (match_operand:SI 1 "compact_register_operand" "")
4928 (cond [(and (ge (minus (match_dup 3) (pc)) (const_int -256))
4929 (le (minus (match_dup 3) (pc)) (const_int 244)))
4931 (match_operand:SI 1 "compact_register_operand" "")
4934 (set (attr "iscompact")
4935 (if_then_else (match_test "get_attr_length (insn) & 2")
4936 (const_string "true") (const_string "false")))])
4938 ; combiner pattern observed for unwind-dw2-fde.c:linear_search_fdes.
4939 (define_insn "*bbit"
4942 (match_operator 3 "equality_comparison_operator"
4943 [(zero_extract:SI (match_operand:SI 1 "register_operand" "Rcqq,c")
4945 (match_operand:SI 2 "nonmemory_operand" "L,Lc"))
4947 (label_ref (match_operand 0 "" ""))
4949 (clobber (reg:CC_ZN CC_REG))]
4950 "!CROSSING_JUMP_P (insn)"
4952 switch (get_attr_length (insn))
4954 case 4: return (GET_CODE (operands[3]) == EQ
4955 ? \"bbit0%* %1,%2,%0\" : \"bbit1%* %1,%2,%0\");
4957 case 8: return \"btst%? %1,%2\n\tb%d3%* %0; bbit out of range\";
4958 default: gcc_unreachable ();
4961 [(set_attr "type" "brcc")
4962 (set_attr "cond" "clob")
4963 (set (attr "length")
4964 (cond [(and (ge (minus (match_dup 0) (pc)) (const_int -254))
4965 (le (minus (match_dup 0) (pc))
4966 (minus (const_int 248)
4967 (symbol_ref "get_attr_delay_slot_length (insn)"))))
4969 (eq (symbol_ref "which_alternative") (const_int 0))
4972 (set (attr "iscompact")
4973 (if_then_else (match_test "get_attr_length (insn) == 6")
4974 (const_string "true") (const_string "false")))])
4976 ; ??? When testing a bit from a DImode register, combine creates a
4977 ; zero_extract in DImode. This goes via an AND with a DImode constant,
4978 ; so can only be observed on 64 bit hosts.
4979 (define_insn_and_split "*bbit_di"
4982 (match_operator 3 "equality_comparison_operator"
4983 [(zero_extract:DI (match_operand:SI 1 "register_operand" "Rcqq,c")
4985 (match_operand 2 "immediate_operand" "L,L"))
4987 (label_ref (match_operand 0 "" ""))
4989 (clobber (reg:CC_ZN CC_REG))]
4990 "!CROSSING_JUMP_P (insn)"
4994 [(set (pc) (if_then_else (match_dup 3) (label_ref (match_dup 0)) (pc)))
4995 (clobber (reg:CC_ZN CC_REG))])]
4999 xtr = gen_rtx_ZERO_EXTRACT (SImode, operands[1], const1_rtx, operands[2]);
5000 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
5004 ; operand 0 is the loop count pseudo register
5005 ; operand 1 is the loop end pattern
5006 (define_expand "doloop_begin"
5007 [(use (match_operand 0 "register_operand" ""))
5008 (use (match_operand 1 "" ""))]
5011 /* Using the INSN_UID of the loop end pattern to identify it causes
5012 trouble with -fcompare-debug, so allocate a debug-independent
5013 id instead. We use negative numbers so that we can use the same
5014 slot in doloop_end_i where we later store a CODE_LABEL_NUMBER, and
5015 still be able to tell what kind of number this is. */
5016 static HOST_WIDE_INT loop_end_id = 0;
5018 rtx id = GEN_INT (--loop_end_id);
5019 XEXP (XVECEXP (PATTERN (operands[1]), 0, 4), 0) = id;
5020 emit_insn (gen_doloop_begin_i (operands[0], const0_rtx, id,
5021 const0_rtx, const0_rtx));
5025 ; ??? can't describe the insn properly as then the optimizers try to
5027 ;(define_insn "doloop_begin_i"
5028 ; [(set (reg:SI LP_START) (pc))
5029 ; (set (reg:SI LP_END) (unspec:SI [(pc)] UNSPEC_ARC_LP))
5030 ; (use (match_operand 0 "const_int_operand" "n"))]
5032 ; "lp .L__GCC__LP%0"
5035 ; The operands of doloop_end_i are also read / written by arc_reorg with
5036 ; XVECEXP (PATTERN (lp, 0, N), so if you want to change the pattern, you
5037 ; might have to adjust arc_reorg.
5038 ; operands 0 / 2 are supplied by the expander, 1, 3 and 4 are filled in
5039 ; by arc_reorg. arc_reorg might also alter operand 0.
5041 ; N in XVECEXP PATTERN (lp, 0 N)
5043 ; 0 unspec UNSPEC_ARC_LP identify pattern
5044 ; 1 clobber LP_START show LP_START is set
5045 ; 2 clobber LP_END show LP_END is set
5046 ; 3 use operand0 loop count pseudo register
5047 ; 4 use operand1 before arc_reorg: -id
5048 ; after : CODE_LABEL_NUMBER of loop top label
5049 ; 5 use operand2 INSN_UID of loop end insn
5050 ; 6 use operand3 loop setup not at start (1 above, 2 below)
5051 ; 7 use operand4 LABEL_REF of top label, if not
5052 ; immediately following
5053 ; If operand1 is still zero after arc_reorg, this is an orphaned loop
5054 ; instruction that was not at the start of the loop.
5055 ; There is no point is reloading this insn - then lp_count would still not
5056 ; be available for the loop end.
5057 (define_insn "doloop_begin_i"
5058 [(unspec:SI [(pc)] UNSPEC_ARC_LP)
5059 (clobber (reg:SI LP_START))
5060 (clobber (reg:SI LP_END))
5061 (use (match_operand:SI 0 "register_operand" "l,l,????*X"))
5062 (use (match_operand 1 "const_int_operand" "n,n,C_0"))
5063 (use (match_operand 2 "const_int_operand" "n,n,X"))
5064 (use (match_operand 3 "const_int_operand" "C_0,n,X"))
5065 (use (match_operand 4 "const_int_operand" "C_0,X,X"))]
5071 rtx loop_start = operands[4];
5073 if (CONST_INT_P (loop_start))
5074 loop_start = NULL_RTX;
5075 /* Size implications of the alignment will be taken care of by the
5076 alignment inserted at the loop start. */
5077 if (LOOP_ALIGN (0) && INTVAL (operands[1]))
5079 asm_fprintf (asm_out_file, "\t.p2align %d\\n", LOOP_ALIGN (0));
5080 arc_clear_unalign ();
5082 if (!INTVAL (operands[1]))
5083 return "; LITTLE LOST LOOP";
5084 if (loop_start && flag_pic)
5086 /* ??? Can do better for when a scratch register
5087 is known. But that would require extra testing. */
5088 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";
5090 /* Check if the loop end is in range to be set by the lp instruction. */
5091 size = INTVAL (operands[3]) < 2 ? 0 : 2048;
5092 for (scan = insn; scan && size < 2048; scan = NEXT_INSN (scan))
5096 if (recog_memoized (scan) == CODE_FOR_doloop_end_i
5097 && (XEXP (XVECEXP (PATTERN (scan), 0, 4), 0)
5098 == XEXP (XVECEXP (PATTERN (insn), 0, 4), 0)))
5100 len = get_attr_length (scan);
5103 /* Try to verify that there are at least three instruction fetches
5104 between the loop setup and the first encounter of the loop end. */
5105 for (scan = NEXT_INSN (insn); scan && n_insns < 3; scan = NEXT_INSN (scan))
5109 if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (scan)))
5110 scan = seq->insn (0);
5113 if (recog_memoized (scan) != CODE_FOR_doloop_end_i)
5116 if (simplejump_p (scan))
5118 scan = as_a <rtx_insn *> (XEXP (SET_SRC (PATTERN (scan)), 0));
5121 if (JUMP_LABEL (scan)
5122 /* JUMP_LABEL might be simple_return instead if an insn. */
5123 && (!INSN_P (JUMP_LABEL (scan))
5124 || (!next_active_insn (JUMP_LABEL (scan))
5125 || (recog_memoized (next_active_insn (JUMP_LABEL (scan)))
5126 != CODE_FOR_doloop_begin_i)))
5127 && (!next_active_insn (NEXT_INSN (PREV_INSN (scan)))
5129 (next_active_insn (NEXT_INSN (PREV_INSN (scan))))
5130 != CODE_FOR_doloop_begin_i)))
5135 len = get_attr_length (scan);
5136 /* Size estimation of asms assumes that each line which is nonempty
5137 codes an insn, and that each has a long immediate. For minimum insn
5138 count, assume merely that a nonempty asm has at least one insn. */
5139 if (GET_CODE (PATTERN (scan)) == ASM_INPUT
5140 || asm_noperands (PATTERN (scan)) >= 0)
5141 n_insns += (len != 0);
5143 n_insns += (len > 4 ? 2 : (len ? 1 : 0));
5147 asm_fprintf (asm_out_file, "\t.p2align %d\\n", LOOP_ALIGN (0));
5148 arc_clear_unalign ();
5150 gcc_assert (n_insns || GET_CODE (next_nonnote_insn (insn)) == CODE_LABEL);
5151 if (size >= 2048 || (TARGET_ARC600 && n_insns == 1) || loop_start)
5155 /* ??? Can do better for when a scratch register
5156 is known. But that would require extra testing. */
5157 arc_clear_unalign ();
5158 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";
5160 output_asm_insn ((size < 2048
5161 ? "lp .L__GCC__LP%1" : "sr .L__GCC__LP%1,[3]; LP_END"),
5163 output_asm_insn (loop_start
5164 ? "sr %4,[2]; LP_START" : "sr 0f,[2]; LP_START",
5166 if (TARGET_ARC600 && n_insns < 1)
5167 output_asm_insn ("nop", operands);
5168 return (TARGET_ARC600 && n_insns < 3) ? "nop_s\;nop_s\;0:" : "0:";
5170 else if (TARGET_ARC600 && n_insns < 3)
5172 /* At least four instructions are needed between the setting of LP_COUNT
5173 and the loop end - but the lp instruction qualifies as one. */
5174 rtx_insn *prev = prev_nonnote_insn (insn);
5176 if (!INSN_P (prev) || dead_or_set_regno_p (prev, LP_COUNT))
5177 output_asm_insn ("nop", operands);
5179 return "lp .L__GCC__LP%1";
5181 [(set_attr "type" "loop_setup")
5182 (set_attr_alternative "length"
5183 ; FIXME: length is usually 4, but we need branch shortening
5184 ; to get this right.
5185 ; [(if_then_else (match_test "TARGET_ARC600") (const_int 16) (const_int 4))
5186 [(if_then_else (match_test "flag_pic") (const_int 24) (const_int 16))
5187 (if_then_else (match_test "flag_pic") (const_int 28) (const_int 16))
5189 ;; ??? we should really branch shorten this insn, but then we'd
5190 ;; need a proper label first. N.B. the end label can not only go out
5191 ;; of range when it is far away, but also when it precedes the loop -
5192 ;; which, unfortunately, it sometimes does, when the loop "optimizer"
5193 ;; messes things up.
5196 ; operand 0 is the loop count pseudo register
5197 ; operand 1 is the label to jump to at the top of the loop
5198 ; Use this for the ARC600 and ARC700.
5199 ; ??? ARC600 might want to check if the loop has few iteration and only a
5200 ; single insn - loop setup is expensive then.
5201 (define_expand "doloop_end"
5202 [(use (match_operand 0 "register_operand" ""))
5203 (use (label_ref (match_operand 1 "" "")))]
5206 /* We could do smaller bivs with biv widening, and wider bivs by having
5207 a high-word counter in an outer loop - but punt on this for now. */
5208 if (GET_MODE (operands[0]) != SImode)
5210 emit_jump_insn (gen_doloop_end_i (operands[0], operands[1], const0_rtx));
5214 (define_insn_and_split "doloop_end_i"
5216 (if_then_else (ne (match_operand:SI 0 "shouldbe_register_operand" "+l,*c,*m")
5218 (label_ref (match_operand 1 "" ""))
5220 (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))
5221 (use (reg:SI LP_START))
5222 (use (reg:SI LP_END))
5223 (use (match_operand 2 "const_int_operand" "n,???Cn0,???X"))
5224 (clobber (match_scratch:SI 3 "=X,X,&????r"))]
5228 rtx_insn *prev = prev_nonnote_insn (insn);
5230 /* If there is an immediately preceding label, we must output a nop,
5231 lest a branch to that label will fall out of the loop.
5232 ??? We could try to avoid this by claiming to have a delay slot if there
5233 is a preceding label, and outputting the delay slot insn instead, if
5235 Or we could have some optimization that changes the source edge to update
5236 the loop count and jump to the loop start instead. */
5237 /* For ARC600, we must also prevent jumps inside the loop and jumps where
5238 the loop counter value is live at the target from being directly at the
5239 loop end. Being sure that the loop counter is dead at the target is
5240 too much hair - we can't rely on data flow information at this point -
5241 so insert a nop for all branches.
5242 The ARC600 also can't read the loop counter in the last insn of a loop. */
5244 output_asm_insn (\"nop%?\", operands);
5245 return \"\\n.L__GCC__LP%2: ; loop end, start is %1\";
5247 "&& memory_operand (operands[0], SImode)"
5250 emit_move_insn (operands[3], operands[0]);
5251 emit_jump_insn (gen_doloop_fallback_m (operands[3], operands[1], operands[0]));
5254 [(set_attr "type" "loop_end")
5255 (set (attr "length")
5256 (if_then_else (match_test "LABEL_P (prev_nonnote_insn (insn))")
5257 (const_int 4) (const_int 0)))]
5260 ; This pattern is generated by arc_reorg when there is no recognizable
5262 (define_insn "*doloop_fallback"
5263 [(set (pc) (if_then_else (ne (match_operand:SI 0 "register_operand" "+r,!w")
5265 (label_ref (match_operand 1 "" ""))
5267 (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
5268 ; avoid fooling the loop optimizer into assuming this is a special insn.
5270 "*return get_attr_length (insn) == 8
5271 ? \"brne.d %0,1,%1\;sub %0,%0,1\"
5272 : \"breq %0,1,0f\;b.d %1\;sub %0,%0,1\\n0:\";"
5273 [(set (attr "length")
5274 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -256))
5275 (le (minus (match_dup 1) (pc)) (const_int 244)))
5276 (const_int 8) (const_int 12)))
5277 (set_attr "type" "brcc_no_delay_slot")
5278 (set_attr "cond" "nocond")]
5281 ; reload can't make output reloads for jump insns, so we have to do this by hand.
5282 (define_insn "doloop_fallback_m"
5283 [(set (pc) (if_then_else (ne (match_operand:SI 0 "register_operand" "+&r")
5285 (label_ref (match_operand 1 "" ""))
5287 (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))
5288 (set (match_operand:SI 2 "memory_operand" "=m")
5289 (plus:SI (match_dup 0) (const_int -1)))]
5290 ; avoid fooling the loop optimizer into assuming this is a special insn.
5292 "*return get_attr_length (insn) == 12
5293 ? \"sub %0,%0,1\;brne.d %0,0,%1\;st%U2%V2 %0,%2\"
5294 : \"sub %0,%0,1\;breq %0,0,0f\;b.d %1\\n0:\tst%U2%V2 %0,%2\";"
5295 [(set (attr "length")
5296 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -252))
5297 (le (minus (match_dup 1) (pc)) (const_int 244)))
5298 (const_int 12) (const_int 16)))
5299 (set_attr "type" "brcc_no_delay_slot")
5300 (set_attr "cond" "nocond")]
5303 (define_expand "movmemsi"
5304 [(match_operand:BLK 0 "" "")
5305 (match_operand:BLK 1 "" "")
5306 (match_operand:SI 2 "nonmemory_operand" "")
5307 (match_operand 3 "immediate_operand" "")]
5309 "if (arc_expand_movmem (operands)) DONE; else FAIL;")
5311 ;; Close http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35803 if this works
5312 ;; to the point that we can generate cmove instructions.
5313 (define_expand "cbranch<mode>4"
5314 [(set (reg:CC CC_REG)
5315 (compare:CC (match_operand:SDF 1 "register_operand" "")
5316 (match_operand:SDF 2 "register_operand" "")))
5319 (match_operator 0 "comparison_operator" [(reg CC_REG)
5321 (label_ref (match_operand 3 "" ""))
5324 "TARGET_FP_SP_BASE || TARGET_OPTFPE"
5326 gcc_assert (XEXP (operands[0], 0) == operands[1]);
5327 gcc_assert (XEXP (operands[0], 1) == operands[2]);
5328 operands[0] = gen_compare_reg (operands[0], VOIDmode);
5329 emit_jump_insn (gen_branch_insn (operands[3], operands[0]));
5333 (define_expand "cmp_float"
5334 [(parallel [(set (match_operand 0 "") (match_operand 1 ""))
5335 (clobber (reg:SI RETURN_ADDR_REGNUM))
5336 (clobber (reg:SI R12_REG))])]
5340 (define_mode_iterator OPTFPE_CMP [CC_Z CC_FP_GT CC_FP_GE CC_FP_UNEQ CC_FP_ORD])
5341 (define_mode_attr cmp [(CC_Z "eq") (CC_FP_GT "gt") (CC_FP_GE "ge")
5342 (CC_FP_UNEQ "uneq") (CC_FP_ORD "ord")])
5344 (define_insn "*cmpsf_<cmp>"
5345 [(set (reg:OPTFPE_CMP CC_REG) (compare:OPTFPE_CMP (reg:SF 0) (reg:SF 1)))
5346 (clobber (reg:SI RETURN_ADDR_REGNUM))
5347 (clobber (reg:SI R12_REG))]
5348 "TARGET_OPTFPE && (!TARGET_ARGONAUT_SET || !TARGET_SPFP)
5349 && SFUNC_CHECK_PREDICABLE"
5350 "*return arc_output_libcall (\"__<cmp>sf2\");"
5351 [(set_attr "is_sfunc" "yes")
5352 (set_attr "predicable" "yes")])
5354 ;; N.B. for "*cmpdf_ord":
5355 ;; double precision fpx sets bit 31 for NaNs. We need bit 51 set
5356 ;; for the floating point emulation to recognize the NaN.
5357 (define_insn "*cmpdf_<cmp>"
5358 [(set (reg:OPTFPE_CMP CC_REG) (compare:OPTFPE_CMP (reg:DF 0) (reg:DF 2)))
5359 (clobber (reg:SI RETURN_ADDR_REGNUM))
5360 (clobber (reg:SI R12_REG))]
5361 "TARGET_OPTFPE && (!TARGET_ARGONAUT_SET || !TARGET_DPFP)
5362 && SFUNC_CHECK_PREDICABLE"
5363 "*return arc_output_libcall (\"__<cmp>df2\");"
5364 [(set_attr "is_sfunc" "yes")
5365 (set_attr "predicable" "yes")])
5367 (define_insn "abssf2"
5368 [(set (match_operand:SF 0 "dest_reg_operand" "=Rcq#q,Rcw,w")
5369 (abs:SF (match_operand:SF 1 "register_operand" "0, 0,c")))]
5372 [(set_attr "type" "unary")
5373 (set_attr "iscompact" "maybe,false,false")
5374 (set_attr "length" "2,4,4")
5375 (set_attr "predicable" "no,yes,no")])
5377 (define_insn "negsf2"
5378 [(set (match_operand:SF 0 "dest_reg_operand" "=Rcw,w")
5379 (neg:SF (match_operand:SF 1 "register_operand" "0,c")))]
5382 [(set_attr "type" "unary")
5383 (set_attr "predicable" "yes,no")])
5385 ;; ??? Should this use arc_output_libcall and set is_sfunc?
5386 (define_insn "*millicode_thunk_st"
5387 [(match_parallel 0 "millicode_store_operation"
5388 [(set (mem:SI (reg:SI SP_REG)) (reg:SI 13))])]
5391 output_asm_insn ("bl%* __st_r13_to_%0",
5392 &SET_SRC (XVECEXP (operands[0], 0,
5393 XVECLEN (operands[0], 0) - 2)));
5396 [(set_attr "type" "call")])
5398 (define_insn "*millicode_thunk_ld"
5399 [(match_parallel 0 "millicode_load_clob_operation"
5400 [(set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
5403 output_asm_insn ("bl%* __ld_r13_to_%0",
5404 &SET_DEST (XVECEXP (operands[0], 0,
5405 XVECLEN (operands[0], 0) - 2)));
5408 [(set_attr "type" "call")])
5410 ; the sibthunk restores blink, so we use the return rtx.
5411 (define_insn "*millicode_sibthunk_ld"
5412 [(match_parallel 0 "millicode_load_operation"
5414 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (reg:SI 12)))
5415 (set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
5418 output_asm_insn ("b%* __ld_r13_to_%0_ret",
5419 &SET_DEST (XVECEXP (operands[0], 0,
5420 XVECLEN (operands[0], 0) - 1)));
5423 [(set_attr "type" "call")
5424 (set_attr "is_SIBCALL" "yes")])
5426 (define_insn "tls_load_tp_soft"
5427 [(set (reg:SI R0_REG) (unspec:SI [(const_int 0)] UNSPEC_TLS_OFF))
5428 (clobber (reg:SI RETURN_ADDR_REGNUM))]
5430 "*return arc_output_libcall (\"__read_tp\");"
5431 [(set_attr "is_sfunc" "yes")
5432 (set_attr "predicable" "yes")])
5434 (define_insn "tls_gd_load"
5435 [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,c")
5436 (unspec:SI [(match_operand:SI 1 "register_operand" "Rcq#q,c")
5437 (match_operand:SI 2 "symbolic_operand" "X,X")]
5440 ".tls_gd_ld %2`ld%? %0,[%1]"
5441 [(set_attr "type" "load")
5442 ; if the linker has to patch this into IE, we need a long insn
5443 ; (FIXME: or two short insn, ld_s / jl_s. missing -Os optimization.)
5444 (set_attr_alternative "iscompact"
5445 [(cond [(ne (symbol_ref "arc_tp_regno == 30") (const_int 0))
5446 (const_string "*")] (const_string "maybe"))
5447 (const_string "*")])])
5449 (define_insn "tls_gd_get_addr"
5450 [(set (reg:SI R0_REG)
5451 (call:SI (mem:SI (unspec:SI [(match_operand:SI 0
5452 "symbolic_operand" "X,X")]
5455 (clobber (reg:SI RETURN_ADDR_REGNUM))]
5457 ".tls_gd_ld %0`bl%* __tls_get_addr@plt"
5458 [(set_attr "type" "call")
5459 ; With TARGET_MEDIUM_CALLS, plt calls are not predicable.
5460 (set_attr "predicable" "no")])
5462 ; We make this call specific to the tls symbol to avoid commoning this
5463 ; with calls for other symbols; we want the linker to be able to
5464 (define_insn "tls_gd_dispatch"
5465 [(set (reg:SI R0_REG)
5468 (call (mem:SI (match_operand:SI 0 "register_operand" "Rcq,q,c"))
5470 (match_operand:SI 1 "symbolic_operand" "X,X,X")]
5472 (clobber (reg:SI RETURN_ADDR_REGNUM))
5473 (clobber (reg:DI R10_REG))
5474 (clobber (reg:SI R12_REG))]
5476 ".tls_gd_call %1`jl%!%* [%0]"
5477 [(set_attr "type" "call")
5478 (set_attr "iscompact" "maybe,false,*")
5479 (set_attr "predicable" "no,no,yes")])
5481 ;; For thread pointer builtins
5482 (define_expand "get_thread_pointersi"
5483 [(set (match_operand:SI 0 "register_operand") (match_dup 1))]
5485 "operands[1] = gen_rtx_REG (Pmode, arc_tp_regno);")
5487 (define_expand "set_thread_pointersi"
5488 [(set (match_dup 1) (match_operand:SI 0 "register_operand"))]
5490 "operands[1] = gen_rtx_REG (Pmode, arc_tp_regno);")
5492 ;; If hardware floating point is available, don't define a negdf pattern;
5493 ;; it would be something like:
5494 ;;(define_insn "negdf2"
5495 ;; [(set (match_operand:DF 0 "register_operand" "=w,w,D,?r")
5496 ;; (neg:DF (match_operand:DF 1 "register_operand" "0,c,D,D")))
5497 ;; (clobber (match_scratch:DF 2 "=X,X,X,X,D1"))]
5500 ;; bxor%? %H0,%H1,31
5501 ;; bxor %H0,%H1,31 ` mov %L0,%L1
5502 ;; drsubh%F0%F1 0,0,0
5503 ;; drsubh%F2%F1 %H0,0,0 ` dexcl%F2 %L0,%H0,%L0"
5504 ;; [(set_attr "type" "unary,unary,dpfp_addsub,dpfp_addsub")
5505 ;; (set_attr "iscompact" "false,false,false,false")
5506 ;; (set_attr "length" "4,4,8,12")
5507 ;; (set_attr "cond" "canuse,nocond,nocond,nocond")])
5508 ;; and this suffers from always requiring a long immediate when using
5509 ;; the floating point hardware.
5510 ;; We then want the sub[sd]f patterns to be used, so that we can load the
5511 ;; constant zero efficiently into a register when we want to do the
5512 ;; computation using the floating point hardware. There should be a special
5513 ;; subdf alternative that matches a zero operand 1, which then can allow
5514 ;; to use bxor to flip the high bit of an integer register.
5515 ;; ??? we actually can't use the floating point hardware for neg, because
5516 ;; this would not work right for -0. OTOH optabs.c has already code
5517 ;; to synthesyze negate by flipping the sign bit.
5520 (define_insn "bswapsi2"
5521 [(set (match_operand:SI 0 "register_operand" "= r,r")
5522 (bswap:SI (match_operand:SI 1 "nonmemory_operand" "rL,Cal")))]
5523 "TARGET_V2 && TARGET_SWAP"
5525 [(set_attr "length" "4,8")
5526 (set_attr "type" "two_cycle_core")])
5528 (define_expand "prefetch"
5529 [(prefetch (match_operand:SI 0 "address_operand" "")
5530 (match_operand:SI 1 "const_int_operand" "")
5531 (match_operand:SI 2 "const_int_operand" ""))]
5535 (define_insn "prefetch_1"
5536 [(prefetch (match_operand:SI 0 "register_operand" "r")
5537 (match_operand:SI 1 "const_int_operand" "n")
5538 (match_operand:SI 2 "const_int_operand" "n"))]
5541 if (INTVAL (operands[1]))
5542 return "prefetchw [%0]";
5544 return "prefetch [%0]";
5546 [(set_attr "type" "load")
5547 (set_attr "length" "4")])
5549 (define_insn "prefetch_2"
5550 [(prefetch (plus:SI (match_operand:SI 0 "register_operand" "r,r,r")
5551 (match_operand:SI 1 "nonmemory_operand" "r,Cm2,Cal"))
5552 (match_operand:SI 2 "const_int_operand" "n,n,n")
5553 (match_operand:SI 3 "const_int_operand" "n,n,n"))]
5556 if (INTVAL (operands[2]))
5557 return "prefetchw [%0, %1]";
5559 return "prefetch [%0, %1]";
5561 [(set_attr "type" "load")
5562 (set_attr "length" "4,4,8")])
5564 (define_insn "prefetch_3"
5565 [(prefetch (match_operand:SI 0 "address_operand" "p")
5566 (match_operand:SI 1 "const_int_operand" "n")
5567 (match_operand:SI 2 "const_int_operand" "n"))]
5570 operands[0] = gen_rtx_MEM (SImode, operands[0]);
5571 if (INTVAL (operands[1]))
5572 return "prefetchw%U0 %0";
5574 return "prefetch%U0 %0";
5576 [(set_attr "type" "load")
5577 (set_attr "length" "8")])
5579 (define_insn "divsi3"
5580 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r, r, r")
5581 (div:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0, 0, r")
5582 (match_operand:SI 2 "nonmemory_operand" "r,r, r,L,L,I,Cal,Cal")))]
5585 [(set_attr "length" "4,4,8,4,4,4,8,8")
5586 (set_attr "iscompact" "false")
5587 (set_attr "type" "div_rem")
5588 (set_attr "predicable" "yes,no,no,yes,no,no,yes,no")
5589 (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond")
5592 (define_insn "udivsi3"
5593 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r, r, r")
5594 (udiv:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0, 0, r")
5595 (match_operand:SI 2 "nonmemory_operand" "r,r, r,L,L,I,Cal,Cal")))]
5598 [(set_attr "length" "4,4,8,4,4,4,8,8")
5599 (set_attr "iscompact" "false")
5600 (set_attr "type" "div_rem")
5601 (set_attr "predicable" "yes,no,no,yes,no,no,yes,no")
5602 (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond")
5605 (define_insn "modsi3"
5606 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r, r, r")
5607 (mod:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0, 0, r")
5608 (match_operand:SI 2 "nonmemory_operand" "r,r, r,L,L,I,Cal,Cal")))]
5611 [(set_attr "length" "4,4,8,4,4,4,8,8")
5612 (set_attr "iscompact" "false")
5613 (set_attr "type" "div_rem")
5614 (set_attr "predicable" "yes,no,no,yes,no,no,yes,no")
5615 (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond")
5618 (define_insn "umodsi3"
5619 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r, r, r")
5620 (umod:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0, 0, r")
5621 (match_operand:SI 2 "nonmemory_operand" "r,r, r,L,L,I,Cal,Cal")))]
5624 [(set_attr "length" "4,4,8,4,4,4,8,8")
5625 (set_attr "iscompact" "false")
5626 (set_attr "type" "div_rem")
5627 (set_attr "predicable" "yes,no,no,yes,no,no,yes,no")
5628 (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond")
5631 ;; SETcc instructions
5632 (define_code_iterator arcCC_cond [eq ne gt lt ge le])
5634 (define_insn "arcset<code>"
5635 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
5636 (arcCC_cond:SI (match_operand:SI 1 "register_operand" "0,r,0,r,0,0,r")
5637 (match_operand:SI 2 "nonmemory_operand" "r,r,L,L,I,n,n")))]
5638 "TARGET_V2 && TARGET_CODE_DENSITY"
5639 "set<code>%? %0, %1, %2"
5640 [(set_attr "length" "4,4,4,4,4,8,8")
5641 (set_attr "iscompact" "false")
5642 (set_attr "type" "compare")
5643 (set_attr "predicable" "yes,no,yes,no,no,yes,no")
5644 (set_attr "cond" "canuse,nocond,canuse,nocond,nocond,canuse,nocond")
5647 (define_insn "arcsetltu"
5648 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r, r, r")
5649 (ltu:SI (match_operand:SI 1 "register_operand" "0,r,0,r,0, 0, r")
5650 (match_operand:SI 2 "nonmemory_operand" "r,r,L,L,I, n, n")))]
5651 "TARGET_V2 && TARGET_CODE_DENSITY"
5652 "setlo%? %0, %1, %2"
5653 [(set_attr "length" "4,4,4,4,4,8,8")
5654 (set_attr "iscompact" "false")
5655 (set_attr "type" "compare")
5656 (set_attr "predicable" "yes,no,yes,no,no,yes,no")
5657 (set_attr "cond" "canuse,nocond,canuse,nocond,nocond,canuse,nocond")
5660 (define_insn "arcsetgeu"
5661 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r, r, r")
5662 (geu:SI (match_operand:SI 1 "register_operand" "0,r,0,r,0, 0, r")
5663 (match_operand:SI 2 "nonmemory_operand" "r,r,L,L,I, n, n")))]
5664 "TARGET_V2 && TARGET_CODE_DENSITY"
5665 "seths%? %0, %1, %2"
5666 [(set_attr "length" "4,4,4,4,4,8,8")
5667 (set_attr "iscompact" "false")
5668 (set_attr "type" "compare")
5669 (set_attr "predicable" "yes,no,yes,no,no,yes,no")
5670 (set_attr "cond" "canuse,nocond,canuse,nocond,nocond,canuse,nocond")
5673 ;; Special cases of SETCC
5674 (define_insn_and_split "arcsethi"
5675 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r")
5676 (gtu:SI (match_operand:SI 1 "register_operand" "r,r, r,r")
5677 (match_operand:SI 2 "nonmemory_operand" "0,r,C62,n")))]
5678 "TARGET_V2 && TARGET_CODE_DENSITY"
5679 "setlo%? %0, %2, %1"
5681 && CONST_INT_P (operands[2])
5682 && satisfies_constraint_C62 (operands[2])"
5685 /* sethi a,b,u6 => seths a,b,u6 + 1. */
5686 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
5687 emit_insn (gen_arcsetgeu (operands[0], operands[1], operands[2]));
5690 [(set_attr "length" "4,4,4,8")
5691 (set_attr "iscompact" "false")
5692 (set_attr "type" "compare")
5693 (set_attr "predicable" "yes,no,no,no")
5694 (set_attr "cond" "canuse,nocond,nocond,nocond")]
5697 (define_insn_and_split "arcsetls"
5698 [(set (match_operand:SI 0 "register_operand" "=r,r, r,r")
5699 (leu:SI (match_operand:SI 1 "register_operand" "r,r, r,r")
5700 (match_operand:SI 2 "nonmemory_operand" "0,r,C62,n")))]
5701 "TARGET_V2 && TARGET_CODE_DENSITY"
5702 "seths%? %0, %2, %1"
5704 && CONST_INT_P (operands[2])
5705 && satisfies_constraint_C62 (operands[2])"
5708 /* setls a,b,u6 => setlo a,b,u6 + 1. */
5709 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
5710 emit_insn (gen_arcsetltu (operands[0], operands[1], operands[2]));
5713 [(set_attr "length" "4,4,4,8")
5714 (set_attr "iscompact" "false")
5715 (set_attr "type" "compare")
5716 (set_attr "predicable" "yes,no,no,no")
5717 (set_attr "cond" "canuse,nocond,nocond,nocond")]
5720 ; Any mode that needs to be solved by secondary reload
5721 (define_mode_iterator SRI [QI HI])
5723 (define_expand "reload_<mode>_load"
5724 [(parallel [(match_operand:SRI 0 "register_operand" "=r")
5725 (match_operand:SRI 1 "memory_operand" "m")
5726 (match_operand:SI 2 "register_operand" "=&r")])]
5729 arc_secondary_reload_conv (operands[0], operands[1], operands[2], false);
5733 (define_expand "reload_<mode>_store"
5734 [(parallel [(match_operand:SRI 0 "memory_operand" "=m")
5735 (match_operand:SRI 1 "register_operand" "r")
5736 (match_operand:SI 2 "register_operand" "=&r")])]
5739 arc_secondary_reload_conv (operands[1], operands[0], operands[2], true);
5744 (define_insn "extzvsi"
5745 [(set (match_operand:SI 0 "register_operand" "=r , r , r, r, r")
5746 (zero_extract:SI (match_operand:SI 1 "register_operand" "0 , r , 0, 0, r")
5747 (match_operand:SI 2 "const_int_operand" "C3p, C3p, i, i, i")
5748 (match_operand:SI 3 "const_int_operand" "i , i , i, i, i")))]
5749 "TARGET_HS && TARGET_BARREL_SHIFTER"
5751 int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f);
5752 operands[2] = GEN_INT (assemble_op2);
5753 return "xbfu%? %0,%1,%2";
5755 [(set_attr "type" "shift")
5756 (set_attr "iscompact" "false")
5757 (set_attr "length" "4,4,4,8,8")
5758 (set_attr "predicable" "yes,no,no,yes,no")
5759 (set_attr "cond" "canuse,nocond,nocond,canuse,nocond")])
5761 (define_insn "kflag"
5762 [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")]
5769 [(set_attr "length" "4,4,8")
5770 (set_attr "type" "misc,misc,misc")
5771 (set_attr "predicable" "yes,no,yes")
5772 (set_attr "cond" "clob,clob,clob")])
5775 [(set (match_operand:SI 0 "dest_reg_operand" "=r")
5776 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "N")]
5780 [(set_attr "length" "4")
5781 (set_attr "type" "misc")])
5784 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
5785 (unspec:SI [(match_operand:SI 1 "general_operand" "cL,Cal")]
5787 "TARGET_NORM && TARGET_V2"
5791 [(set_attr "length" "4,8")
5792 (set_attr "type" "two_cycle_core,two_cycle_core")])
5794 (define_insn "ffs_f"
5795 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
5796 (unspec:SI [(match_operand:SI 1 "general_operand" "cL,Cal")]
5798 (set (reg:CC_ZN CC_REG)
5799 (compare:CC_ZN (match_dup 1) (const_int 0)))]
5800 "TARGET_NORM && TARGET_V2"
5804 [(set_attr "length" "4,8")
5805 (set_attr "type" "two_cycle_core,two_cycle_core")])
5807 (define_expand "ffssi2"
5808 [(parallel [(set (match_dup 2)
5809 (unspec:SI [(match_operand:SI 1 "register_operand" "")]
5811 (set (reg:CC_ZN CC_REG)
5812 (compare:CC_ZN (match_dup 1) (const_int 0)))])
5813 (set (match_dup 2) (plus:SI (match_dup 2) (const_int 1)))
5814 (set (match_operand:SI 0 "dest_reg_operand" "")
5815 (if_then_else:SI (eq:SI (reg:CC_ZN CC_REG) (const_int 0))
5818 "TARGET_NORM && TARGET_V2"
5820 operands[2] = gen_reg_rtx (SImode);
5824 [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
5825 (unspec:SI [(match_operand:SI 1 "general_operand" "cL,Cal")]
5827 "TARGET_NORM && TARGET_V2"
5831 [(set_attr "length" "4,8")
5832 (set_attr "type" "two_cycle_core,two_cycle_core")])
5835 [(unspec_volatile:SI [(match_operand:SI 0 "general_operand" "rL")]
5839 [(set_attr "length" "4")
5840 (set_attr "type" "misc")])
5845 (define_expand "addsf3"
5846 [(set (match_operand:SF 0 "register_operand" "")
5847 (plus:SF (match_operand:SF 1 "nonmemory_operand" "")
5848 (match_operand:SF 2 "nonmemory_operand" "")))]
5849 "TARGET_FP_SP_BASE || TARGET_SPFP"
5851 if (!register_operand (operands[1], SFmode)
5852 && !register_operand (operands[2], SFmode))
5853 operands[1] = force_reg (SFmode, operands[1]);
5857 (define_expand "subsf3"
5858 [(set (match_operand:SF 0 "register_operand" "")
5859 (minus:SF (match_operand:SF 1 "nonmemory_operand" "")
5860 (match_operand:SF 2 "nonmemory_operand" "")))]
5861 "TARGET_FP_SP_BASE || TARGET_SPFP"
5863 if (!register_operand (operands[1], SFmode)
5864 && !register_operand (operands[2], SFmode))
5865 operands[1] = force_reg (SFmode, operands[1]);
5869 (define_expand "mulsf3"
5870 [(set (match_operand:SF 0 "register_operand" "")
5871 (mult:SF (match_operand:SF 1 "nonmemory_operand" "")
5872 (match_operand:SF 2 "nonmemory_operand" "")))]
5873 "TARGET_FP_SP_BASE || TARGET_SPFP"
5875 if (!register_operand (operands[1], SFmode)
5876 && !register_operand (operands[2], SFmode))
5877 operands[1] = force_reg (SFmode, operands[1]);
5881 (define_expand "adddf3"
5882 [(set (match_operand:DF 0 "double_register_operand" "")
5883 (plus:DF (match_operand:DF 1 "double_register_operand" "")
5884 (match_operand:DF 2 "nonmemory_operand" "")))]
5885 "TARGET_FP_DP_BASE || TARGET_DPFP"
5889 if (GET_CODE (operands[2]) == CONST_DOUBLE)
5891 rtx first, second, tmp;
5892 split_double (operands[2], &first, &second);
5893 tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second);
5894 emit_insn (gen_adddf3_insn (operands[0], operands[1],
5895 operands[2], tmp, const0_rtx));
5898 emit_insn (gen_adddf3_insn (operands[0], operands[1],
5899 operands[2], const1_rtx, const1_rtx));
5902 else if (TARGET_FP_DP_BASE)
5904 if (!even_register_operand (operands[2], DFmode))
5905 operands[2] = force_reg (DFmode, operands[2]);
5907 if (!even_register_operand (operands[1], DFmode))
5908 operands[1] = force_reg (DFmode, operands[1]);
5915 (define_expand "subdf3"
5916 [(set (match_operand:DF 0 "double_register_operand" "")
5917 (minus:DF (match_operand:DF 1 "nonmemory_operand" "")
5918 (match_operand:DF 2 "nonmemory_operand" "")))]
5919 "TARGET_FP_DP_BASE || TARGET_DPFP"
5923 if (TARGET_FP_DP_AX && (GET_CODE (operands[1]) == CONST_DOUBLE))
5924 operands[1] = force_reg (DFmode, operands[1]);
5925 if ((GET_CODE (operands[1]) == CONST_DOUBLE)
5926 || GET_CODE (operands[2]) == CONST_DOUBLE)
5928 rtx first, second, tmp;
5929 int const_index = ((GET_CODE (operands[1]) == CONST_DOUBLE) ? 1 : 2);
5930 split_double (operands[const_index], &first, &second);
5931 tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second);
5932 emit_insn (gen_subdf3_insn (operands[0], operands[1],
5933 operands[2], tmp, const0_rtx));
5936 emit_insn (gen_subdf3_insn (operands[0], operands[1],
5937 operands[2], const1_rtx, const1_rtx));
5940 else if (TARGET_FP_DP_BASE)
5942 if (!even_register_operand (operands[2], DFmode))
5943 operands[2] = force_reg (DFmode, operands[2]);
5945 if (!even_register_operand (operands[1], DFmode))
5946 operands[1] = force_reg (DFmode, operands[1]);
5953 (define_expand "muldf3"
5954 [(set (match_operand:DF 0 "double_register_operand" "")
5955 (mult:DF (match_operand:DF 1 "double_register_operand" "")
5956 (match_operand:DF 2 "nonmemory_operand" "")))]
5957 "TARGET_FP_DP_BASE || TARGET_DPFP"
5961 if (GET_CODE (operands[2]) == CONST_DOUBLE)
5963 rtx first, second, tmp;
5964 split_double (operands[2], &first, &second);
5965 tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second);
5966 emit_insn (gen_muldf3_insn (operands[0], operands[1],
5967 operands[2], tmp, const0_rtx));
5970 emit_insn (gen_muldf3_insn (operands[0], operands[1],
5971 operands[2], const1_rtx, const1_rtx));
5974 else if (TARGET_FP_DP_BASE)
5976 if (!even_register_operand (operands[2], DFmode))
5977 operands[2] = force_reg (DFmode, operands[2]);
5979 if (!even_register_operand (operands[1], DFmode))
5980 operands[1] = force_reg (DFmode, operands[1]);
5986 (define_expand "extzv"
5987 [(set (match_operand:SI 0 "register_operand" "")
5988 (zero_extract:SI (match_operand:SI 1 "register_operand" "")
5989 (match_operand:SI 2 "const_int_operand" "")
5990 (match_operand:SI 3 "const_int_operand" "")))]
5991 "TARGET_NPS_BITOPS")
5993 ; We need a sanity check in the instuction predicate because combine
5994 ; will throw any old rubbish at us and see what sticks.
5995 (define_insn "*extzv_i"
5996 [(set (match_operand:SI 0 "register_operand" "=Rrq")
5997 (zero_extract:SI (match_operand:SI 1 "register_operand" "Rrq")
5998 (match_operand:SI 2 "const_int_operand" "n")
5999 (match_operand:SI 3 "const_int_operand" "n")))]
6000 "TARGET_NPS_BITOPS && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32"
6001 "movb.cl %0,%1,0,%3,%2"
6002 [(set_attr "type" "shift")
6003 (set_attr "length" "4")])
6005 (define_expand "insv"
6006 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "")
6007 (match_operand:SI 1 "const_int_operand" "")
6008 (match_operand:SI 2 "const_int_operand" ""))
6009 (match_operand:SI 3 "nonmemory_operand" ""))]
6012 int size = INTVAL (operands[1]);
6014 if (size != 1 && size != 2 && size != 4 && size != 8)
6015 operands[3] = force_reg (SImode, operands[3]);
6018 (define_insn "*insv_i"
6019 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+w,Rrq")
6020 (match_operand:SI 1 "const_int_operand" "C18,n")
6021 (match_operand:SI 2 "const_int_operand" "n,n"))
6022 (match_operand:SI 3 "nonmemory_operand" "P,Rrq"))]
6024 && (register_operand (operands[3], SImode)
6025 || satisfies_constraint_C18 (operands[1]))"
6027 movbi %0,%0,%3,%2,%1
6028 movb %0,%0,%3,%2,0,%1"
6029 [(set_attr "type" "shift")
6030 (set_attr "length" "4")])
6032 (define_insn "*movb"
6033 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
6034 (match_operand:SI 1 "const_int_operand" "n")
6035 (match_operand:SI 2 "const_int_operand" "n"))
6036 (zero_extract:SI (match_operand:SI 3 "register_operand" "Rrq")
6038 (match_operand:SI 4 "const_int_operand" "n")))]
6040 "movb %0,%0,%3,%2,%4,%1"
6041 [(set_attr "type" "shift")
6042 (set_attr "length" "4")])
6044 (define_insn "*movb_signed"
6045 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
6046 (match_operand:SI 1 "const_int_operand" "n")
6047 (match_operand:SI 2 "const_int_operand" "n"))
6048 (sign_extract:SI (match_operand:SI 3 "register_operand" "Rrq")
6050 (match_operand:SI 4 "const_int_operand" "n")))]
6052 "movb %0,%0,%3,%2,%4,%1"
6053 [(set_attr "type" "shift")
6054 (set_attr "length" "4")])
6056 (define_insn "*movb_high"
6057 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
6058 (match_operand:SI 1 "const_int_operand" "n")
6059 (match_operand:SI 2 "const_int_operand" "n"))
6060 (lshiftrt:SI (match_operand:SI 3 "register_operand" "Rrq")
6061 (match_operand:SI 4 "const_int_operand" "n")))]
6063 && INTVAL (operands[4]) + INTVAL (operands[1]) <= 32"
6064 "movb %0,%0,%3,%2,%4,%1"
6065 [(set_attr "type" "shift")
6066 (set_attr "length" "4")])
6068 ; N.B.: when processing signed bitfields that fit in the top half of
6069 ; a word, gcc will use a narrow sign extending load, and in this case
6070 ; we will see INTVAL (operands[4]) + INTVAL (operands[1]) == 16 (or 8)
6071 (define_insn "*movb_high_signed"
6072 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
6073 (match_operand:SI 1 "const_int_operand" "n")
6074 (match_operand:SI 2 "const_int_operand" "n"))
6075 (ashiftrt:SI (match_operand:SI 3 "register_operand" "Rrq")
6076 (match_operand:SI 4 "const_int_operand" "n")))]
6078 && INTVAL (operands[4]) + INTVAL (operands[1]) <= 32"
6079 "movb %0,%0,%3,%2,%4,%1"
6080 [(set_attr "type" "shift")
6081 (set_attr "length" "4")])
6084 [(set (match_operand:SI 0 "register_operand" "")
6085 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
6086 (match_operand:SI 2 "const_int_operand" ""))
6087 (subreg:SI (match_operand 3 "") 0)))]
6089 && GET_MODE_BITSIZE (GET_MODE (operands[3])) <= INTVAL (operands[2])
6090 && !reg_overlap_mentioned_p (operands[0], operands[1])"
6091 [(set (match_dup 0) (zero_extend:SI (match_dup 3)))
6092 (set (zero_extract:SI (match_dup 0) (match_dup 4) (match_dup 2))
6094 "operands[4] = GEN_INT (32 - INTVAL (operands[2]));")
6096 (define_insn "*mrgb"
6097 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
6098 (match_operand:SI 1 "const_int_operand" "n")
6099 (match_operand:SI 2 "const_int_operand" "n"))
6100 (zero_extract:SI (match_dup 0) (match_dup 1)
6101 (match_operand:SI 3 "const_int_operand" "n")))
6102 (set (zero_extract:SI (match_dup 0)
6103 (match_operand:SI 4 "const_int_operand" "n")
6104 (match_operand:SI 5 "const_int_operand" "n"))
6105 (zero_extract:SI (match_operand:SI 6 "register_operand" "Rrq")
6107 (match_operand:SI 7 "const_int_operand" "n")))]
6110 output_asm_insn ("mrgb %0,%0,%6,%2,%3,%1,%5,%7,%4", operands);
6111 /* The ;%? updates the known unalignment. */
6112 return arc_short_long (insn, ";%?", "nop_s");
6114 [(set_attr "type" "shift")
6115 (set_attr "length" "6")
6116 (set_attr "iscompact" "true")])
6118 ;; combine fumbles combination of two movb patterns, and then the
6119 ;; combination is rejected by combinable_i3pat.
6120 ;; Thus, we can only use a peephole2 to combine two such insns.
6123 [(set (match_operand:SI 0 "register_operand" "")
6124 (match_operand:SI 1 "register_operand" ""))
6125 (set (zero_extract:SI (match_dup 0)
6126 (match_operand:SI 2 "const_int_operand" "")
6127 (match_operand:SI 3 "const_int_operand" ""))
6128 (zero_extract:SI (match_dup 1)
6130 (match_operand:SI 4 "const_int_operand" "")))
6131 (match_operand 9) ; unrelated insn scheduled here
6132 (set (zero_extract:SI (match_dup 0)
6133 (match_operand:SI 5 "const_int_operand" "")
6134 (match_operand:SI 6 "const_int_operand" ""))
6135 (zero_extract:SI (match_operand:SI 7 "register_operand" "")
6137 (match_operand:SI 8 "const_int_operand" "")))]
6139 // Check that the second movb doesn't clobber an input of the extra insn.
6140 && !reg_overlap_mentioned_p (operands[0], operands[9])
6142 && !reg_set_p (operands[0], operands[9])
6143 && !reg_set_p (operands[7], operands[9])"
6144 [(set (match_dup 0) (match_dup 1))
6145 (parallel [(set (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
6146 (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 4)))
6147 (set (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
6148 (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 4)))])
6152 [(set (match_operand:SI 0 "register_operand" "")
6153 (match_operand:SI 1 "register_operand" ""))
6154 (set (zero_extract:SI (match_dup 0)
6155 (match_operand:SI 2 "const_int_operand" "")
6156 (match_operand:SI 3 "const_int_operand" ""))
6157 (zero_extract:SI (match_dup 1)
6159 (match_operand:SI 4 "const_int_operand" "")))
6160 (set (match_dup 1) (match_operand 8))
6161 (set (zero_extract:SI (match_dup 0)
6162 (match_operand:SI 5 "const_int_operand" "")
6163 (match_operand:SI 6 "const_int_operand" ""))
6164 (zero_extract:SI (match_dup 1) (match_dup 5)
6165 (match_operand:SI 7 "const_int_operand" "")))]
6167 && !reg_overlap_mentioned_p (operands[0], operands[8])"
6168 [(set (match_dup 0) (match_dup 1))
6169 (set (match_dup 1) (match_dup 8))
6170 (parallel [(set (zero_extract:SI (match_dup 0) (match_dup 2) (match_dup 3))
6171 (zero_extract:SI (match_dup 0) (match_dup 2) (match_dup 4)))
6172 (set (zero_extract:SI (match_dup 0) (match_dup 5) (match_dup 6))
6173 (zero_extract:SI (match_dup 1) (match_dup 5) (match_dup 7)))])
6176 ;; include the arc-FPX instructions
6179 ;; include the arc-FPU instructions
6182 (include "simdext.md")
6184 ;; include atomic extensions
6185 (include "atomic.md")