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