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