]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
Daily bump.
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
711789cc 2;; Copyright (C) 1991-2013 Free Software Foundation, Inc.
b11cae9e 3;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 4;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 5;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 6
acf6ed70 7;; This file is part of GCC.
b11cae9e 8
acf6ed70 9;; GCC is free software; you can redistribute it and/or modify it
10;; under the terms of the GNU General Public License as published
038d1e19 11;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 12;; option) any later version.
b11cae9e 13
acf6ed70 14;; GCC is distributed in the hope that it will be useful, but WITHOUT
15;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17;; License for more details.
b11cae9e 18
19;; You should have received a copy of the GNU General Public License
038d1e19 20;; along with GCC; see the file COPYING3. If not see
21;; <http://www.gnu.org/licenses/>.
b11cae9e 22
23;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24
cb860649 25;; Beware of splitting Thumb1 patterns that output multiple
26;; assembly instructions, in particular instruction such as SBC and
27;; ADC which consume flags. For example, in the pattern thumb_subdi3
28;; below, the output SUB implicitly sets the flags (assembled to SUBS)
29;; and then the Carry flag is used by SBC to compute the correct
30;; result. If we split thumb_subdi3 pattern into two separate RTL
31;; insns (using define_insn_and_split), the scheduler might place
32;; other RTL insns between SUB and SBC, possibly modifying the Carry
33;; flag used by SBC. This might happen because most Thumb1 patterns
34;; for flag-setting instructions do not have explicit RTL for setting
35;; or clobbering the flags. Instead, they have the attribute "conds"
36;; with value "set" or "clob". However, this attribute is not used to
37;; identify dependencies and therefore the scheduler might reorder
38;; these instruction. Currenly, this problem cannot happen because
39;; there are no separate Thumb1 patterns for individual instruction
40;; that consume flags (except conditional execution, which is treated
41;; differently). In particular there is no Thumb1 armv6-m pattern for
42;; sbc or adc.
43
9c08d1fa 44\f
e1159bbe 45;;---------------------------------------------------------------------------
46;; Constants
47
bffbb863 48;; Register numbers -- All machine registers should be defined here
e1159bbe 49(define_constants
bffbb863 50 [(R0_REGNUM 0) ; First CORE register
51 (R1_REGNUM 1) ; Second CORE register
52 (IP_REGNUM 12) ; Scratch register
53 (SP_REGNUM 13) ; Stack pointer
54 (LR_REGNUM 14) ; Return address register
55 (PC_REGNUM 15) ; Program counter
56 (LAST_ARM_REGNUM 15) ;
57 (CC_REGNUM 100) ; Condition code pseudo register
58 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
e1159bbe 59 ]
60)
3c5afce6 61;; 3rd operand to select_dominance_cc_mode
62(define_constants
63 [(DOM_CC_X_AND_Y 0)
64 (DOM_CC_NX_OR_Y 1)
65 (DOM_CC_X_OR_Y 2)
66 ]
67)
2ff91fec 68;; conditional compare combination
69(define_constants
70 [(CMP_CMP 0)
71 (CMN_CMP 1)
72 (CMP_CMN 2)
73 (CMN_CMN 3)
74 (NUM_OF_COND_CMP 4)
75 ]
76)
e1159bbe 77
b11cae9e 78\f
e1159bbe 79;;---------------------------------------------------------------------------
9c08d1fa 80;; Attributes
81
a651f34d 82;; Processor type. This is created automatically from arm-cores.def.
83(include "arm-tune.md")
84
215b30b3 85; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
86; generating ARM code. This is used to control the length of some insn
87; patterns that share the same RTL in both ARM and Thumb code.
1c494086 88(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 89
ef51b8e1 90; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
91(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
92
747b7458 93; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
94(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
95
c7a58118 96; We use this attribute to disable alternatives that can produce 32-bit
97; instructions inside an IT-block in Thumb2 state. ARMv8 deprecates IT blocks
98; that contain 32-bit instructions.
99(define_attr "enabled_for_depr_it" "no,yes" (const_string "yes"))
100
101; This attribute is used to disable a predicated alternative when we have
102; arm_restrict_it.
103(define_attr "predicable_short_it" "no,yes" (const_string "yes"))
104
331beb1a 105;; Operand number of an input operand that is shifted. Zero if the
106;; given instruction does not shift one of its input operands.
331beb1a 107(define_attr "shift" "" (const_int 0))
108
3d91c5d6 109; Floating Point Unit. If we only have floating point emulation, then there
110; is no point in scheduling the floating point insns. (Well, for best
111; performance we should try and group them together).
bffbb863 112(define_attr "fpu" "none,vfp"
c7f506fd 113 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 114
c7a58118 115(define_attr "predicated" "yes,no" (const_string "no"))
116
094e994f 117; LENGTH of an instruction (in bytes)
06df6b17 118(define_attr "length" ""
e1b93706 119 (const_int 4))
9c08d1fa 120
d5d4dc8d 121; The architecture which supports the instruction (or alternative).
122; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
123; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
124; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
125; arm_arch6. This attribute is used to compute attribute "enabled",
126; use type "any" to enable an alternative in all cases.
b6779ddc 127(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2"
d5d4dc8d 128 (const_string "any"))
129
130(define_attr "arch_enabled" "no,yes"
131 (cond [(eq_attr "arch" "any")
132 (const_string "yes")
133
134 (and (eq_attr "arch" "a")
0bf497f5 135 (match_test "TARGET_ARM"))
d5d4dc8d 136 (const_string "yes")
137
138 (and (eq_attr "arch" "t")
0bf497f5 139 (match_test "TARGET_THUMB"))
d5d4dc8d 140 (const_string "yes")
141
142 (and (eq_attr "arch" "t1")
0bf497f5 143 (match_test "TARGET_THUMB1"))
d5d4dc8d 144 (const_string "yes")
145
146 (and (eq_attr "arch" "t2")
0bf497f5 147 (match_test "TARGET_THUMB2"))
d5d4dc8d 148 (const_string "yes")
149
150 (and (eq_attr "arch" "32")
0bf497f5 151 (match_test "TARGET_32BIT"))
d5d4dc8d 152 (const_string "yes")
153
154 (and (eq_attr "arch" "v6")
0bf497f5 155 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 156 (const_string "yes")
157
158 (and (eq_attr "arch" "nov6")
0bf497f5 159 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 160 (const_string "yes")
161
b6779ddc 162 (and (eq_attr "arch" "avoid_neon_for_64bits")
163 (match_test "TARGET_NEON")
164 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 165 (const_string "yes")
166
b6779ddc 167 (and (eq_attr "arch" "neon_for_64bits")
168 (match_test "TARGET_NEON")
169 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 170 (const_string "yes")
171
172 (and (eq_attr "arch" "iwmmxt2")
173 (match_test "TARGET_REALLY_IWMMXT2"))
d5d4dc8d 174 (const_string "yes")]
6b8f7c28 175
d5d4dc8d 176 (const_string "no")))
177
aa06c51c 178(define_attr "opt" "any,speed,size"
179 (const_string "any"))
180
181(define_attr "opt_enabled" "no,yes"
182 (cond [(eq_attr "opt" "any")
183 (const_string "yes")
184
185 (and (eq_attr "opt" "speed")
186 (match_test "optimize_function_for_speed_p (cfun)"))
187 (const_string "yes")
188
189 (and (eq_attr "opt" "size")
190 (match_test "optimize_function_for_size_p (cfun)"))
191 (const_string "yes")]
192 (const_string "no")))
193
d5d4dc8d 194; Allows an insn to disable certain alternatives for reasons other than
195; arch support.
196(define_attr "insn_enabled" "no,yes"
197 (const_string "yes"))
198
199; Enable all alternatives that are both arch_enabled and insn_enabled.
93b431d9 200 (define_attr "enabled" "no,yes"
aa06c51c 201 (cond [(eq_attr "insn_enabled" "no")
202 (const_string "no")
203
c7a58118 204 (and (eq_attr "predicable_short_it" "no")
205 (and (eq_attr "predicated" "yes")
206 (match_test "arm_restrict_it")))
207 (const_string "no")
208
209 (and (eq_attr "enabled_for_depr_it" "no")
210 (match_test "arm_restrict_it"))
211 (const_string "no")
212
aa06c51c 213 (eq_attr "arch_enabled" "no")
214 (const_string "no")
215
216 (eq_attr "opt_enabled" "no")
217 (const_string "no")]
218 (const_string "yes")))
d5d4dc8d 219
56d27660 220; POOL_RANGE is how far away from a constant pool entry that this insn
221; can be placed. If the distance is zero, then this insn will never
222; reference the pool.
42e1de19 223; Note that for Thumb constant pools the PC value is rounded down to the
224; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
225; Thumb insns) should be set to <max_range> - 2.
cffb2a26 226; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 227; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 228(define_attr "arm_pool_range" "" (const_int 0))
229(define_attr "thumb2_pool_range" "" (const_int 0))
230(define_attr "arm_neg_pool_range" "" (const_int 0))
231(define_attr "thumb2_neg_pool_range" "" (const_int 0))
232
233(define_attr "pool_range" ""
234 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
235 (attr "arm_pool_range")))
236(define_attr "neg_pool_range" ""
237 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
238 (attr "arm_neg_pool_range")))
56d27660 239
215b30b3 240; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 241; If such an insn references the pool, then we have no way of knowing how,
242; so use the most conservative value for pool_range.
9c08d1fa 243(define_asm_attributes
4d7a8451 244 [(set_attr "conds" "clob")
245 (set_attr "length" "4")
246 (set_attr "pool_range" "250")])
9c08d1fa 247
70e6ce19 248; TYPE attribute is used to classify instructions for use in scheduling.
9c08d1fa 249;
70e6ce19 250; Instruction classification:
251;
6b6abc9c 252; arlo_imm any arithmetic or logical instruction that doesn't have
253; a shifted operand and has an immediate operand. This
254; excludes MOV, MVN and RSB(S) immediate.
255; arlo_reg any arithmetic or logical instruction that doesn't have
256; a shifted or an immediate operand. This excludes
257; MOV and MVN but includes MOVT. This is also the default.
258; arlo_shift any arithmetic or logical instruction that has a source
259; operand shifted by a constant. This excludes
260; simple shifts.
261; arlo_shift_reg as arlo_shift, with the shift amount specified in a
262; register.
70e6ce19 263; block blockage insn, this blocks all functional units.
264; branch branch.
265; call subroutine call.
bebe9bbb 266; clz count leading zeros (CLZ).
6b6abc9c 267; extend extend instruction (SXTB, SXTH, UXTB, UXTH).
70e6ce19 268; f_2_r transfer from float to core (no memory needed).
269; f_cvt conversion between float and integral.
270; f_flag transfer of co-processor flags to the CPSR.
271; f_load[d,s] double/single load from memory. Used for VFP unit.
272; f_minmax[d,s] double/single floating point minimum/maximum.
273; f_rint[d,s] double/single floating point rount to integral.
274; f_sel[d,s] double/single floating byte select.
275; f_store[d,s] double/single store to memory. Used for VFP unit.
276; fadd[d,s] double/single floating-point scalar addition.
277; fcmp[d,s] double/single floating-point compare.
278; fconst[d,s] double/single load immediate.
279; fcpys single precision floating point cpy.
280; fdiv[d,s] double/single precision floating point division.
281; ffarith[d,s] double/single floating point abs/neg/cpy.
282; ffma[d,s] double/single floating point fused multiply-accumulate.
283; float floating point arithmetic operation.
284; fmac[d,s] double/single floating point multiply-accumulate.
285; fmul[d,s] double/single floating point multiply.
286; load_byte load byte(s) from memory to arm registers.
287; load1 load 1 word from memory to arm registers.
288; load2 load 2 words from memory to arm registers.
289; load3 load 3 words from memory to arm registers.
290; load4 load 4 words from memory to arm registers.
291; mla integer multiply accumulate.
292; mlas integer multiply accumulate, flag setting.
1aed5204 293; mov_imm simple MOV instruction that moves an immediate to
294; register. This includes MOVW, but not MOVT.
295; mov_reg simple MOV instruction that moves a register to another
296; register. This includes MOVW, but not MOVT.
297; mov_shift simple MOV instruction, shifted operand by a constant.
298; mov_shift_reg simple MOV instruction, shifted operand by a register.
70e6ce19 299; mul integer multiply.
300; muls integer multiply, flag setting.
1aed5204 301; mvn_imm inverting move instruction, immediate.
302; mvn_reg inverting move instruction, register.
303; mvn_shift inverting move instruction, shifted operand by a constant.
304; mvn_shift_reg inverting move instruction, shifted operand by a register.
70e6ce19 305; r_2_f transfer from core to float.
306; sdiv signed division.
6b6abc9c 307; shift simple shift operation (LSL, LSR, ASR, ROR) with an
308; immediate.
309; shift_reg simple shift by a register.
70e6ce19 310; smlad signed multiply accumulate dual.
311; smladx signed multiply accumulate dual reverse.
312; smlal signed multiply accumulate long.
313; smlald signed multiply accumulate long dual.
314; smlals signed multiply accumulate long, flag setting.
315; smlalxy signed multiply accumulate, 16x16-bit, 64-bit accumulate.
316; smlawx signed multiply accumulate, 32x16-bit, 32-bit accumulate.
317; smlawy signed multiply accumulate wide, 32x16-bit,
318; 32-bit accumulate.
319; smlaxy signed multiply accumulate, 16x16-bit, 32-bit accumulate.
320; smlsd signed multiply subtract dual.
321; smlsdx signed multiply subtract dual reverse.
322; smlsld signed multiply subtract long dual.
323; smmla signed most significant word multiply accumulate.
324; smmul signed most significant word multiply.
325; smmulr signed most significant word multiply, rounded.
326; smuad signed dual multiply add.
327; smuadx signed dual multiply add reverse.
328; smull signed multiply long.
329; smulls signed multiply long, flag setting.
330; smulwy signed multiply wide, 32x16-bit, 32-bit accumulate.
331; smulxy signed multiply, 16x16-bit, 32-bit accumulate.
332; smusd signed dual multiply subtract.
333; smusdx signed dual multiply subtract reverse.
334; store1 store 1 word to memory from arm registers.
335; store2 store 2 words to memory from arm registers.
336; store3 store 3 words to memory from arm registers.
337; store4 store 4 (or more) words to memory from arm registers.
338; udiv unsigned division.
339; umaal unsigned multiply accumulate accumulate long.
340; umlal unsigned multiply accumulate long.
341; umlals unsigned multiply accumulate long, flag setting.
342; umull unsigned multiply long.
343; umulls unsigned multiply long, flag setting.
7cb6c048 344;
345; The classification below is for instructions used by the Wireless MMX
346; Technology. Each attribute value is used to classify an instruction of the
347; same name or family.
348;
349; wmmx_tandc
350; wmmx_tbcst
351; wmmx_textrc
352; wmmx_textrm
353; wmmx_tinsr
354; wmmx_tmcr
355; wmmx_tmcrr
356; wmmx_tmia
357; wmmx_tmiaph
358; wmmx_tmiaxy
359; wmmx_tmrc
360; wmmx_tmrrc
361; wmmx_tmovmsk
362; wmmx_torc
363; wmmx_torvsc
364; wmmx_wabs
365; wmmx_wdiff
366; wmmx_wacc
367; wmmx_wadd
368; wmmx_waddbhus
369; wmmx_waddsubhx
370; wmmx_waligni
371; wmmx_walignr
372; wmmx_wand
373; wmmx_wandn
374; wmmx_wavg2
375; wmmx_wavg4
376; wmmx_wcmpeq
377; wmmx_wcmpgt
378; wmmx_wmac
379; wmmx_wmadd
380; wmmx_wmax
381; wmmx_wmerge
382; wmmx_wmiawxy
383; wmmx_wmiaxy
384; wmmx_wmin
385; wmmx_wmov
386; wmmx_wmul
387; wmmx_wmulw
388; wmmx_wldr
389; wmmx_wor
390; wmmx_wpack
391; wmmx_wqmiaxy
392; wmmx_wqmulm
393; wmmx_wqmulwm
394; wmmx_wror
395; wmmx_wsad
396; wmmx_wshufh
397; wmmx_wsll
398; wmmx_wsra
399; wmmx_wsrl
400; wmmx_wstr
401; wmmx_wsub
402; wmmx_wsubaddhx
403; wmmx_wunpckeh
404; wmmx_wunpckel
405; wmmx_wunpckih
406; wmmx_wunpckil
407; wmmx_wxor
bcaec148 408
9c08d1fa 409(define_attr "type"
6b6abc9c 410 "arlo_imm,\
411 arlo_reg,\
412 arlo_shift,\
413 arlo_shift_reg,\
96854199 414 block,\
6b6abc9c 415 branch,\
416 call,\
bebe9bbb 417 clz,\
6b6abc9c 418 extend,\
96854199 419 f_2_r,\
96854199 420 f_cvt,\
6b6abc9c 421 f_flag,\
422 f_loadd,\
423 f_loads,\
424 f_minmaxd,\
425 f_minmaxs,\
426 f_rintd,\
427 f_rints,\
91cb50d2 428 f_seld,\
6b6abc9c 429 f_sels,\
430 f_stored,\
431 f_stores,\
432 faddd,\
433 fadds,\
434 fcmpd,\
435 fcmps,\
436 fconstd,\
437 fconsts,\
438 fcpys,\
439 fdivd,\
440 fdivs,\
441 ffarithd,\
442 ffariths,\
443 ffmad,\
444 ffmas,\
445 float,\
446 fmacd,\
447 fmacs,\
448 fmuld,\
449 fmuls,\
96854199 450 load_byte,\
451 load1,\
452 load2,\
453 load3,\
454 load4,\
9da0ec36 455 mla,\
456 mlas,\
1aed5204 457 mov_imm,\
458 mov_reg,\
459 mov_shift,\
460 mov_shift_reg,\
6b6abc9c 461 mul,\
462 muls,\
1aed5204 463 mvn_imm,\
464 mvn_reg,\
465 mvn_shift,\
466 mvn_shift_reg,\
6b6abc9c 467 r_2_f,\
468 sdiv,\
469 shift,\
470 shift_reg,\
471 smlad,\
472 smladx,\
9da0ec36 473 smlal,\
6b6abc9c 474 smlald,\
9da0ec36 475 smlals,\
6b6abc9c 476 smlalxy,\
477 smlawx,\
9da0ec36 478 smlawy,\
6b6abc9c 479 smlaxy,\
9da0ec36 480 smlsd,\
481 smlsdx,\
6b6abc9c 482 smlsld,\
483 smmla,\
9da0ec36 484 smmul,\
485 smmulr,\
6b6abc9c 486 smuad,\
487 smuadx,\
488 smull,\
489 smulls,\
490 smulwy,\
491 smulxy,\
492 smusd,\
493 smusdx,\
494 store1,\
495 store2,\
496 store3,\
497 store4,\
7cb6c048 498 udiv,\
6b6abc9c 499 umaal,\
500 umlal,\
501 umlals,\
502 umull,\
503 umulls,\
7cb6c048 504 wmmx_tandc,\
505 wmmx_tbcst,\
506 wmmx_textrc,\
507 wmmx_textrm,\
508 wmmx_tinsr,\
509 wmmx_tmcr,\
510 wmmx_tmcrr,\
511 wmmx_tmia,\
512 wmmx_tmiaph,\
513 wmmx_tmiaxy,\
514 wmmx_tmrc,\
515 wmmx_tmrrc,\
516 wmmx_tmovmsk,\
517 wmmx_torc,\
518 wmmx_torvsc,\
519 wmmx_wabs,\
520 wmmx_wabsdiff,\
521 wmmx_wacc,\
522 wmmx_wadd,\
523 wmmx_waddbhus,\
524 wmmx_waddsubhx,\
525 wmmx_waligni,\
526 wmmx_walignr,\
527 wmmx_wand,\
528 wmmx_wandn,\
529 wmmx_wavg2,\
530 wmmx_wavg4,\
531 wmmx_wcmpeq,\
532 wmmx_wcmpgt,\
533 wmmx_wmac,\
534 wmmx_wmadd,\
535 wmmx_wmax,\
536 wmmx_wmerge,\
537 wmmx_wmiawxy,\
538 wmmx_wmiaxy,\
539 wmmx_wmin,\
540 wmmx_wmov,\
541 wmmx_wmul,\
542 wmmx_wmulw,\
543 wmmx_wldr,\
544 wmmx_wor,\
545 wmmx_wpack,\
546 wmmx_wqmiaxy,\
547 wmmx_wqmulm,\
548 wmmx_wqmulwm,\
549 wmmx_wror,\
550 wmmx_wsad,\
551 wmmx_wshufh,\
552 wmmx_wsll,\
553 wmmx_wsra,\
554 wmmx_wsrl,\
555 wmmx_wstr,\
556 wmmx_wsub,\
557 wmmx_wsubaddhx,\
558 wmmx_wunpckeh,\
559 wmmx_wunpckel,\
560 wmmx_wunpckih,\
561 wmmx_wunpckil,\
562 wmmx_wxor"
6b6abc9c 563 (const_string "arlo_reg"))
9da0ec36 564
565; Is this an (integer side) multiply with a 32-bit (or smaller) result?
566(define_attr "mul32" "no,yes"
567 (if_then_else
568 (eq_attr "type"
569 "smulxy,smlaxy,smulwy,smlawx,mul,muls,mla,mlas,smlawy,smuad,smuadx,\
570 smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,smlald,smlsld")
571 (const_string "yes")
572 (const_string "no")))
9c08d1fa 573
65f2f758 574; Is this an (integer side) multiply with a 64-bit result?
575(define_attr "mul64" "no,yes"
96854199 576 (if_then_else
9da0ec36 577 (eq_attr "type"
578 "smlalxy,umull,umulls,umaal,umlal,umlals,smull,smulls,smlal,smlals")
96854199 579 (const_string "yes")
580 (const_string "no")))
65f2f758 581
9888ad6d 582; Load scheduling, set from the arm_ld_sched variable
4c834714 583; initialized by arm_option_override()
9888ad6d 584(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 585
c52acdd2 586;; Classification of NEON instructions for scheduling purposes.
c52acdd2 587(define_attr "neon_type"
588 "neon_int_1,\
589 neon_int_2,\
590 neon_int_3,\
591 neon_int_4,\
592 neon_int_5,\
593 neon_vqneg_vqabs,\
594 neon_vmov,\
595 neon_vaba,\
596 neon_vsma,\
597 neon_vaba_qqq,\
598 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
599 neon_mul_qqq_8_16_32_ddd_32,\
600 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
601 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
602 neon_mla_qqq_8_16,\
603 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
604 neon_mla_qqq_32_qqd_32_scalar,\
605 neon_mul_ddd_16_scalar_32_16_long_scalar,\
606 neon_mul_qqd_32_scalar,\
607 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
608 neon_shift_1,\
609 neon_shift_2,\
610 neon_shift_3,\
611 neon_vshl_ddd,\
612 neon_vqshl_vrshl_vqrshl_qqq,\
613 neon_vsra_vrsra,\
614 neon_fp_vadd_ddd_vabs_dd,\
615 neon_fp_vadd_qqq_vabs_qq,\
616 neon_fp_vsum,\
617 neon_fp_vmul_ddd,\
618 neon_fp_vmul_qqd,\
619 neon_fp_vmla_ddd,\
620 neon_fp_vmla_qqq,\
621 neon_fp_vmla_ddd_scalar,\
622 neon_fp_vmla_qqq_scalar,\
623 neon_fp_vrecps_vrsqrts_ddd,\
624 neon_fp_vrecps_vrsqrts_qqq,\
625 neon_bp_simple,\
626 neon_bp_2cycle,\
627 neon_bp_3cycle,\
628 neon_ldr,\
629 neon_str,\
630 neon_vld1_1_2_regs,\
631 neon_vld1_3_4_regs,\
632 neon_vld2_2_regs_vld1_vld2_all_lanes,\
633 neon_vld2_4_regs,\
634 neon_vld3_vld4,\
635 neon_vst1_1_2_regs_vst2_2_regs,\
636 neon_vst1_3_4_regs,\
637 neon_vst2_4_regs_vst3_vst4,\
638 neon_vst3_vst4,\
639 neon_vld1_vld2_lane,\
640 neon_vld3_vld4_lane,\
641 neon_vst1_vst2_lane,\
642 neon_vst3_vst4_lane,\
643 neon_vld3_vld4_all_lanes,\
644 neon_mcr,\
645 neon_mcr_2_mcrr,\
646 neon_mrc,\
647 neon_mrrc,\
648 neon_ldm_2,\
649 neon_stm_2,\
650 none"
651 (const_string "none"))
652
f7fbdd4a 653; condition codes: this one is used by final_prescan_insn to speed up
654; conditionalizing instructions. It saves having to scan the rtl to see if
655; it uses or alters the condition codes.
215b30b3 656;
f7fbdd4a 657; USE means that the condition codes are used by the insn in the process of
215b30b3 658; outputting code, this means (at present) that we can't use the insn in
659; inlined branches
660;
f7fbdd4a 661; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 662; well defined manner.
663;
f7fbdd4a 664; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 665; they are altered at all
666;
ad6d3e2a 667; UNCONDITIONAL means the instruction can not be conditionally executed and
668; that the instruction does not use or alter the condition codes.
c52acdd2 669;
ad6d3e2a 670; NOCOND means that the instruction does not use or alter the condition
671; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 672
b0694be0 673(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 674 (if_then_else
675 (ior (eq_attr "is_thumb1" "yes")
676 (eq_attr "type" "call"))
c1a66faf 677 (const_string "clob")
c52acdd2 678 (if_then_else (eq_attr "neon_type" "none")
679 (const_string "nocond")
680 (const_string "unconditional"))))
f7fbdd4a 681
215b30b3 682; Predicable means that the insn can be conditionally executed based on
683; an automatically added predicate (additional patterns are generated by
684; gen...). We default to 'no' because no Thumb patterns match this rule
685; and not all ARM patterns do.
0d66636f 686(define_attr "predicable" "no,yes" (const_string "no"))
687
129a2fe4 688; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
689; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 690; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 691; affect the schedule).
74a71f7d 692(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 693
215b30b3 694; WRITE_CONFLICT implies that a read following an unrelated write is likely
695; to stall the processor. Used with model_wbuf above.
9c08d1fa 696(define_attr "write_conflict" "no,yes"
697 (if_then_else (eq_attr "type"
96854199 698 "block,call,load1")
9c08d1fa 699 (const_string "yes")
700 (const_string "no")))
701
215b30b3 702; Classify the insns into those that take one cycle and those that take more
703; than one on the main cpu execution unit.
f7fbdd4a 704(define_attr "core_cycles" "single,multi"
705 (if_then_else (eq_attr "type"
6b6abc9c 706 "arlo_imm, arlo_reg,\
707 extend, shift, arlo_shift, float, fdivd, fdivs,\
7cb6c048 708 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
709 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
710 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
711 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
712 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
713 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
714 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
715 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
716 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
717 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
718 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 719 (const_string "single")
720 (const_string "multi")))
721
cffb2a26 722;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 723;; distant label. Only applicable to Thumb code.
cffb2a26 724(define_attr "far_jump" "yes,no" (const_string "no"))
725
d51f92df 726
25f905c2 727;; The number of machine instructions this pattern expands to.
728;; Used for Thumb-2 conditional execution.
729(define_attr "ce_count" "" (const_int 1))
730
4182b724 731;;---------------------------------------------------------------------------
732;; Unspecs
733
734(include "unspecs.md")
735
d51f92df 736;;---------------------------------------------------------------------------
fd781bb2 737;; Mode iterators
d51f92df 738
3de0dec6 739(include "iterators.md")
03770691 740
d51f92df 741;;---------------------------------------------------------------------------
742;; Predicates
743
9c9db025 744(include "predicates.md")
234f6557 745(include "constraints.md")
9c9db025 746
a2cd141b 747;;---------------------------------------------------------------------------
748;; Pipeline descriptions
215b30b3 749
e3879fd0 750(define_attr "tune_cortexr4" "yes,no"
751 (const (if_then_else
7d3cda8c 752 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 753 (const_string "yes")
754 (const_string "no"))))
755
a2cd141b 756;; True if the generic scheduling description should be used.
757
758(define_attr "generic_sched" "yes,no"
2546d93a 759 (const (if_then_else
da10bc87 760 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa7,cortexa8,cortexa9,cortexa15,cortexa53,cortexm4,marvell_pj4")
2546d93a 761 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 762 (const_string "no")
763 (const_string "yes"))))
764
c0e1af52 765(define_attr "generic_vfp" "yes,no"
766 (const (if_then_else
767 (and (eq_attr "fpu" "vfp")
da10bc87 768 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,cortexa8,cortexa9,cortexa53,cortexm4,marvell_pj4")
e3879fd0 769 (eq_attr "tune_cortexr4" "no"))
c0e1af52 770 (const_string "yes")
771 (const_string "no"))))
772
6b8f7c28 773(include "marvell-f-iwmmxt.md")
a2cd141b 774(include "arm-generic.md")
775(include "arm926ejs.md")
c0e1af52 776(include "arm1020e.md")
a2cd141b 777(include "arm1026ejs.md")
778(include "arm1136jfs.md")
0e266d06 779(include "fa526.md")
780(include "fa606te.md")
781(include "fa626te.md")
782(include "fmp626.md")
783(include "fa726te.md")
3f1e069f 784(include "cortex-a5.md")
d6b7f019 785(include "cortex-a7.md")
bcaec148 786(include "cortex-a8.md")
036068af 787(include "cortex-a9.md")
65f2f758 788(include "cortex-a15.md")
da10bc87 789(include "cortex-a53.md")
934a1e72 790(include "cortex-r4.md")
e3879fd0 791(include "cortex-r4f.md")
2546d93a 792(include "cortex-m4.md")
793(include "cortex-m4-fpu.md")
55e3ada8 794(include "vfp11.md")
ea7d210b 795(include "marvell-pj4.md")
3586df96 796
9c08d1fa 797\f
215b30b3 798;;---------------------------------------------------------------------------
e1159bbe 799;; Insn patterns
800;;
a0f94409 801;; Addition insns.
215b30b3 802
9c08d1fa 803;; Note: For DImode insns, there is normally no reason why operands should
804;; not be in the same register, what we don't want is for something being
805;; written to partially overlap something that is an input.
806
cffb2a26 807(define_expand "adddi3"
808 [(parallel
215b30b3 809 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 810 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 811 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 812 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 813 "TARGET_EITHER"
814 "
25f905c2 815 if (TARGET_THUMB1)
cffb2a26 816 {
0438d37f 817 if (!REG_P (operands[1]))
bc5a93af 818 operands[1] = force_reg (DImode, operands[1]);
0438d37f 819 if (!REG_P (operands[2]))
bc5a93af 820 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 821 }
822 "
823)
824
25f905c2 825(define_insn "*thumb1_adddi3"
cffb2a26 826 [(set (match_operand:DI 0 "register_operand" "=l")
827 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 828 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 829 (clobber (reg:CC CC_REGNUM))
cffb2a26 830 ]
25f905c2 831 "TARGET_THUMB1"
cffb2a26 832 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
833 [(set_attr "length" "4")]
834)
835
a0f94409 836(define_insn_and_split "*arm_adddi3"
10e5ccd5 837 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
838 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
839 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 840 (clobber (reg:CC CC_REGNUM))]
b805622c 841 "TARGET_32BIT && !TARGET_NEON"
33782ec7 842 "#"
94829feb 843 "TARGET_32BIT && reload_completed
844 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 845 [(parallel [(set (reg:CC_C CC_REGNUM)
846 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
847 (match_dup 1)))
848 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 849 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
850 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 851 "
852 {
853 operands[3] = gen_highpart (SImode, operands[0]);
854 operands[0] = gen_lowpart (SImode, operands[0]);
855 operands[4] = gen_highpart (SImode, operands[1]);
856 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 857 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 858 operands[2] = gen_lowpart (SImode, operands[2]);
859 }"
cffb2a26 860 [(set_attr "conds" "clob")
861 (set_attr "length" "8")]
862)
9c08d1fa 863
a0f94409 864(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 865 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
866 (plus:DI (sign_extend:DI
97499065 867 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 868 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 869 (clobber (reg:CC CC_REGNUM))]
b805622c 870 "TARGET_32BIT"
33782ec7 871 "#"
25f905c2 872 "TARGET_32BIT && reload_completed"
a0f94409 873 [(parallel [(set (reg:CC_C CC_REGNUM)
874 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
875 (match_dup 1)))
876 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 877 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 878 (const_int 31))
080c0b9a 879 (match_dup 4))
880 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 881 "
882 {
883 operands[3] = gen_highpart (SImode, operands[0]);
884 operands[0] = gen_lowpart (SImode, operands[0]);
885 operands[4] = gen_highpart (SImode, operands[1]);
886 operands[1] = gen_lowpart (SImode, operands[1]);
887 operands[2] = gen_lowpart (SImode, operands[2]);
888 }"
215b30b3 889 [(set_attr "conds" "clob")
890 (set_attr "length" "8")]
891)
9c08d1fa 892
a0f94409 893(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 894 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
895 (plus:DI (zero_extend:DI
97499065 896 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 897 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 898 (clobber (reg:CC CC_REGNUM))]
b805622c 899 "TARGET_32BIT"
33782ec7 900 "#"
25f905c2 901 "TARGET_32BIT && reload_completed"
a0f94409 902 [(parallel [(set (reg:CC_C CC_REGNUM)
903 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
904 (match_dup 1)))
905 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 906 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
907 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 908 "
909 {
910 operands[3] = gen_highpart (SImode, operands[0]);
911 operands[0] = gen_lowpart (SImode, operands[0]);
912 operands[4] = gen_highpart (SImode, operands[1]);
913 operands[1] = gen_lowpart (SImode, operands[1]);
914 operands[2] = gen_lowpart (SImode, operands[2]);
915 }"
cffb2a26 916 [(set_attr "conds" "clob")
917 (set_attr "length" "8")]
918)
b11cae9e 919
87b22bf7 920(define_expand "addsi3"
cffb2a26 921 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 922 (plus:SI (match_operand:SI 1 "s_register_operand" "")
923 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 924 "TARGET_EITHER"
87b22bf7 925 "
0438d37f 926 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 927 {
96f57e36 928 arm_split_constant (PLUS, SImode, NULL_RTX,
929 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 930 optimize && can_create_pseudo_p ());
87b22bf7 931 DONE;
932 }
cffb2a26 933 "
934)
87b22bf7 935
5bd751ff 936; If there is a scratch available, this will be faster than synthesizing the
a0f94409 937; addition.
938(define_peephole2
939 [(match_scratch:SI 3 "r")
372575c7 940 (set (match_operand:SI 0 "arm_general_register_operand" "")
941 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 942 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 943 "TARGET_32BIT &&
a0f94409 944 !(const_ok_for_arm (INTVAL (operands[2]))
945 || const_ok_for_arm (-INTVAL (operands[2])))
946 && const_ok_for_arm (~INTVAL (operands[2]))"
947 [(set (match_dup 3) (match_dup 2))
948 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
949 ""
950)
87b22bf7 951
2f02c19f 952;; The r/r/k alternative is required when reloading the address
953;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
954;; put the duplicated register first, and not try the commutative version.
a0f94409 955(define_insn_and_split "*arm_addsi3"
7c36fe71 956 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,r ,k ,r ,k,k,r ,k ,r")
957 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,rk,k ,rk,k,r,rk,k ,rk")
958 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 959 "TARGET_32BIT"
5565501b 960 "@
c24d855d 961 add%?\\t%0, %0, %2
5565501b 962 add%?\\t%0, %1, %2
a0b3420a 963 add%?\\t%0, %1, %2
7c36fe71 964 add%?\\t%0, %1, %2
965 add%?\\t%0, %1, %2
aaa37ad6 966 add%?\\t%0, %1, %2
2f02c19f 967 add%?\\t%0, %2, %1
d5cbae34 968 addw%?\\t%0, %1, %2
969 addw%?\\t%0, %1, %2
aaa37ad6 970 sub%?\\t%0, %1, #%n2
87b22bf7 971 sub%?\\t%0, %1, #%n2
d7757711 972 sub%?\\t%0, %1, #%n2
d5cbae34 973 subw%?\\t%0, %1, #%n2
974 subw%?\\t%0, %1, #%n2
87b22bf7 975 #"
a3ffc315 976 "TARGET_32BIT
0438d37f 977 && CONST_INT_P (operands[2])
d5cbae34 978 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 979 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 980 [(clobber (const_int 0))]
981 "
96f57e36 982 arm_split_constant (PLUS, SImode, curr_insn,
983 INTVAL (operands[2]), operands[0],
a0f94409 984 operands[1], 0);
985 DONE;
986 "
7c36fe71 987 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 988 (set_attr "predicable" "yes")
7c36fe71 989 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
990 (set_attr "arch" "t2,t2,t2,t2,*,*,*,t2,t2,*,*,a,t2,t2,*")
65f68e55 991 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6b6abc9c 992 (const_string "arlo_imm")
993 (const_string "arlo_reg")))
65f68e55 994 ]
cffb2a26 995)
996
0bdb6455 997(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 998 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
999 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
1000 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 1001 "TARGET_THUMB1"
cffb2a26 1002 "*
0d66636f 1003 static const char * const asms[] =
cffb2a26 1004 {
1005 \"add\\t%0, %0, %2\",
1006 \"sub\\t%0, %0, #%n2\",
1007 \"add\\t%0, %1, %2\",
1008 \"add\\t%0, %0, %2\",
1009 \"add\\t%0, %0, %2\",
1010 \"add\\t%0, %1, %2\",
0bdb6455 1011 \"add\\t%0, %1, %2\",
1012 \"#\",
bf7bc2f6 1013 \"#\",
0bdb6455 1014 \"#\"
cffb2a26 1015 };
1016 if ((which_alternative == 2 || which_alternative == 6)
0438d37f 1017 && CONST_INT_P (operands[2])
cffb2a26 1018 && INTVAL (operands[2]) < 0)
1019 return \"sub\\t%0, %1, #%n2\";
1020 return asms[which_alternative];
1021 "
0bdb6455 1022 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 1023 && ((operands[1] != stack_pointer_rtx
1024 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
1025 || (operands[1] == stack_pointer_rtx
1026 && INTVAL (operands[2]) > 1020))"
0bdb6455 1027 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
1028 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
1029 {
1030 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 1031 if (operands[1] == stack_pointer_rtx)
1032 offset -= 1020;
1033 else
1034 {
1035 if (offset > 255)
1036 offset = 255;
1037 else if (offset < -255)
1038 offset = -255;
1039 }
0bdb6455 1040 operands[3] = GEN_INT (offset);
1041 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
1042 }
bf7bc2f6 1043 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 1044)
1045
1046;; Reloading and elimination of the frame pointer can
1047;; sometimes cause this optimization to be missed.
a0f94409 1048(define_peephole2
372575c7 1049 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 1050 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 1051 (set (match_dup 0)
372575c7 1052 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 1053 "TARGET_THUMB1
cffb2a26 1054 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
1055 && (INTVAL (operands[1]) & 3) == 0"
372575c7 1056 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 1057 ""
cffb2a26 1058)
b11cae9e 1059
90c2bcf0 1060(define_insn "addsi3_compare0"
bd5b4116 1061 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1062 (compare:CC_NOOV
65f68e55 1063 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
1064 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 1065 (const_int 0)))
65f68e55 1066 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1067 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 1068 "TARGET_ARM"
5565501b 1069 "@
25f905c2 1070 add%.\\t%0, %1, %2
65f68e55 1071 sub%.\\t%0, %1, #%n2
1072 add%.\\t%0, %1, %2"
1073 [(set_attr "conds" "set")
6b6abc9c 1074 (set_attr "type" "arlo_imm,arlo_imm,*")]
cffb2a26 1075)
9c08d1fa 1076
aea4c774 1077(define_insn "*addsi3_compare0_scratch"
bd5b4116 1078 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 1079 (compare:CC_NOOV
65f68e55 1080 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
1081 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 1082 (const_int 0)))]
ec792a7b 1083 "TARGET_ARM"
cffb2a26 1084 "@
1085 cmn%?\\t%0, %1
65f68e55 1086 cmp%?\\t%0, #%n1
1087 cmn%?\\t%0, %1"
596e5e8f 1088 [(set_attr "conds" "set")
65f68e55 1089 (set_attr "predicable" "yes")
6b6abc9c 1090 (set_attr "type" "arlo_imm,arlo_imm,*")
65f68e55 1091 ]
0d66636f 1092)
cffb2a26 1093
aed179ae 1094(define_insn "*compare_negsi_si"
1095 [(set (reg:CC_Z CC_REGNUM)
1096 (compare:CC_Z
7c36fe71 1097 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
1098 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 1099 "TARGET_32BIT"
aed179ae 1100 "cmn%?\\t%1, %0"
596e5e8f 1101 [(set_attr "conds" "set")
7c36fe71 1102 (set_attr "predicable" "yes")
1103 (set_attr "arch" "t2,*")
1104 (set_attr "length" "2,4")
1105 (set_attr "predicable_short_it" "yes,no")]
0d66636f 1106)
aea4c774 1107
203c488f 1108;; This is the canonicalization of addsi3_compare0_for_combiner when the
1109;; addend is a constant.
190efb17 1110(define_insn "cmpsi2_addneg"
203c488f 1111 [(set (reg:CC CC_REGNUM)
1112 (compare:CC
1113 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 1114 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 1115 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1116 (plus:SI (match_dup 1)
2a977b78 1117 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 1118 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 1119 "@
2a977b78 1120 add%.\\t%0, %1, %3
1121 sub%.\\t%0, %1, #%n3"
203c488f 1122 [(set_attr "conds" "set")]
1123)
1124
1125;; Convert the sequence
1126;; sub rd, rn, #1
1127;; cmn rd, #1 (equivalent to cmp rd, #-1)
1128;; bne dest
1129;; into
1130;; subs rd, rn, #1
1131;; bcs dest ((unsigned)rn >= 1)
1132;; similarly for the beq variant using bcc.
1133;; This is a common looping idiom (while (n--))
1134(define_peephole2
372575c7 1135 [(set (match_operand:SI 0 "arm_general_register_operand" "")
1136 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 1137 (const_int -1)))
1138 (set (match_operand 2 "cc_register" "")
1139 (compare (match_dup 0) (const_int -1)))
1140 (set (pc)
1141 (if_then_else (match_operator 3 "equality_operator"
1142 [(match_dup 2) (const_int 0)])
1143 (match_operand 4 "" "")
1144 (match_operand 5 "" "")))]
25f905c2 1145 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 1146 [(parallel[
1147 (set (match_dup 2)
1148 (compare:CC
1149 (match_dup 1) (const_int 1)))
1150 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
1151 (set (pc)
1152 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
1153 (match_dup 4)
1154 (match_dup 5)))]
1155 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
1156 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
1157 ? GEU : LTU),
1158 VOIDmode,
1159 operands[2], const0_rtx);"
1160)
1161
ebcc79bc 1162;; The next four insns work because they compare the result with one of
1163;; the operands, and we know that the use of the condition code is
1164;; either GEU or LTU, so we can use the carry flag from the addition
1165;; instead of doing the compare a second time.
1166(define_insn "*addsi3_compare_op1"
bd5b4116 1167 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 1168 (compare:CC_C
65f68e55 1169 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1170 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 1171 (match_dup 1)))
65f68e55 1172 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 1173 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1174 "TARGET_32BIT"
ebcc79bc 1175 "@
25f905c2 1176 add%.\\t%0, %1, %2
65f68e55 1177 sub%.\\t%0, %1, #%n2
1178 add%.\\t%0, %1, %2"
1179 [(set_attr "conds" "set")
6b6abc9c 1180 (set_attr "type" "arlo_imm,arlo_imm,*")]
0d66636f 1181)
ebcc79bc 1182
1183(define_insn "*addsi3_compare_op2"
bd5b4116 1184 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 1185 (compare:CC_C
65f68e55 1186 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1187 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 1188 (match_dup 2)))
65f68e55 1189 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1190 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1191 "TARGET_32BIT"
5565501b 1192 "@
65f68e55 1193 add%.\\t%0, %1, %2
25f905c2 1194 add%.\\t%0, %1, %2
1195 sub%.\\t%0, %1, #%n2"
65f68e55 1196 [(set_attr "conds" "set")
6b6abc9c 1197 (set_attr "type" "arlo_imm,arlo_imm,*")]
0d66636f 1198)
9c08d1fa 1199
ebcc79bc 1200(define_insn "*compare_addsi2_op0"
bd5b4116 1201 [(set (reg:CC_C CC_REGNUM)
7c36fe71 1202 (compare:CC_C
1203 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
1204 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
1205 (match_dup 0)))]
25f905c2 1206 "TARGET_32BIT"
ebcc79bc 1207 "@
7c36fe71 1208 cmp%?\\t%0, #%n1
1209 cmn%?\\t%0, %1
ebcc79bc 1210 cmn%?\\t%0, %1
65f68e55 1211 cmp%?\\t%0, #%n1
1212 cmn%?\\t%0, %1"
596e5e8f 1213 [(set_attr "conds" "set")
65f68e55 1214 (set_attr "predicable" "yes")
7c36fe71 1215 (set_attr "arch" "t2,t2,*,*,*")
1216 (set_attr "predicable_short_it" "yes,yes,no,no,no")
1217 (set_attr "length" "2,2,4,4,4")
1218 (set_attr "type" "arlo_imm,*,arlo_imm,arlo_imm,*")]
0d66636f 1219)
ebcc79bc 1220
1221(define_insn "*compare_addsi2_op1"
bd5b4116 1222 [(set (reg:CC_C CC_REGNUM)
7c36fe71 1223 (compare:CC_C
1224 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
1225 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
1226 (match_dup 1)))]
25f905c2 1227 "TARGET_32BIT"
ebcc79bc 1228 "@
7c36fe71 1229 cmp%?\\t%0, #%n1
1230 cmn%?\\t%0, %1
ebcc79bc 1231 cmn%?\\t%0, %1
65f68e55 1232 cmp%?\\t%0, #%n1
1233 cmn%?\\t%0, %1"
596e5e8f 1234 [(set_attr "conds" "set")
65f68e55 1235 (set_attr "predicable" "yes")
7c36fe71 1236 (set_attr "arch" "t2,t2,*,*,*")
1237 (set_attr "predicable_short_it" "yes,yes,no,no,no")
1238 (set_attr "length" "2,2,4,4,4")
1239 (set_attr "type"
1240 "arlo_imm,*,arlo_imm,arlo_imm,*")]
1241 )
ebcc79bc 1242
080c0b9a 1243(define_insn "*addsi3_carryin_<optab>"
7c36fe71 1244 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1245 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
1246 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
1247 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1248 "TARGET_32BIT"
10e5ccd5 1249 "@
a0b3420a 1250 adc%?\\t%0, %1, %2
10e5ccd5 1251 adc%?\\t%0, %1, %2
1252 sbc%?\\t%0, %1, #%B2"
a7de272d 1253 [(set_attr "conds" "use")
7c36fe71 1254 (set_attr "predicable" "yes")
1255 (set_attr "arch" "t2,*,*")
1256 (set_attr "length" "4")
1257 (set_attr "predicable_short_it" "yes,no,no")]
cffb2a26 1258)
ebcc79bc 1259
080c0b9a 1260(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 1261 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1262 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
1263 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
1264 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 1265 "TARGET_32BIT"
10e5ccd5 1266 "@
a0b3420a 1267 adc%?\\t%0, %1, %2
10e5ccd5 1268 adc%?\\t%0, %1, %2
1269 sbc%?\\t%0, %1, #%B2"
a7de272d 1270 [(set_attr "conds" "use")
7c36fe71 1271 (set_attr "predicable" "yes")
1272 (set_attr "arch" "t2,*,*")
1273 (set_attr "length" "4")
1274 (set_attr "predicable_short_it" "yes,no,no")]
0d66636f 1275)
ebcc79bc 1276
080c0b9a 1277(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1278 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1279 (plus:SI (plus:SI
1280 (match_operator:SI 2 "shift_operator"
1281 [(match_operand:SI 3 "s_register_operand" "r")
1282 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1283 (match_operand:SI 1 "s_register_operand" "r"))
1284 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1285 "TARGET_32BIT"
080c0b9a 1286 "adc%?\\t%0, %1, %3%S2"
1287 [(set_attr "conds" "use")
a7de272d 1288 (set_attr "predicable" "yes")
7c36fe71 1289 (set_attr "predicable_short_it" "no")
080c0b9a 1290 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
6b6abc9c 1291 (const_string "arlo_shift")
1292 (const_string "arlo_shift_reg")))]
cffb2a26 1293)
ebcc79bc 1294
922b6913 1295(define_insn "*addsi3_carryin_clobercc_<optab>"
1296 [(set (match_operand:SI 0 "s_register_operand" "=r")
1297 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1298 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1299 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1300 (clobber (reg:CC CC_REGNUM))]
1301 "TARGET_32BIT"
1302 "adc%.\\t%0, %1, %2"
1303 [(set_attr "conds" "set")]
1304)
1305
9154bd82 1306(define_insn "*subsi3_carryin"
1307 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1308 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
1309 (match_operand:SI 2 "s_register_operand" "r,r"))
1310 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1311 "TARGET_32BIT"
1312 "@
1313 sbc%?\\t%0, %1, %2
1314 rsc%?\\t%0, %2, %1"
1315 [(set_attr "conds" "use")
1316 (set_attr "arch" "*,a")
7c36fe71 1317 (set_attr "predicable" "yes")
1318 (set_attr "predicable_short_it" "no")]
9154bd82 1319)
1320
1321(define_insn "*subsi3_carryin_const"
1322 [(set (match_operand:SI 0 "s_register_operand" "=r")
1323 (minus:SI (plus:SI (match_operand:SI 1 "reg_or_int_operand" "r")
1324 (match_operand:SI 2 "arm_not_operand" "K"))
1325 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1326 "TARGET_32BIT"
1327 "sbc\\t%0, %1, #%B2"
1328 [(set_attr "conds" "use")]
1329)
1330
1331(define_insn "*subsi3_carryin_compare"
1332 [(set (reg:CC CC_REGNUM)
1333 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
1334 (match_operand:SI 2 "s_register_operand" "r")))
1335 (set (match_operand:SI 0 "s_register_operand" "=r")
1336 (minus:SI (minus:SI (match_dup 1)
1337 (match_dup 2))
1338 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1339 "TARGET_32BIT"
1340 "sbcs\\t%0, %1, %2"
1341 [(set_attr "conds" "set")]
1342)
1343
1344(define_insn "*subsi3_carryin_compare_const"
1345 [(set (reg:CC CC_REGNUM)
1346 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1347 (match_operand:SI 2 "arm_not_operand" "K")))
1348 (set (match_operand:SI 0 "s_register_operand" "=r")
1349 (minus:SI (plus:SI (match_dup 1)
1350 (match_dup 2))
1351 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1352 "TARGET_32BIT"
1353 "sbcs\\t%0, %1, #%B2"
1354 [(set_attr "conds" "set")]
1355)
1356
1357(define_insn "*subsi3_carryin_shift"
1358 [(set (match_operand:SI 0 "s_register_operand" "=r")
1359 (minus:SI (minus:SI
1360 (match_operand:SI 1 "s_register_operand" "r")
1361 (match_operator:SI 2 "shift_operator"
1362 [(match_operand:SI 3 "s_register_operand" "r")
1363 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1364 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1365 "TARGET_32BIT"
1366 "sbc%?\\t%0, %1, %3%S2"
1367 [(set_attr "conds" "use")
1368 (set_attr "predicable" "yes")
1369 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
6b6abc9c 1370 (const_string "arlo_shift")
1371 (const_string "arlo_shift_reg")))]
9154bd82 1372)
1373
1374(define_insn "*rsbsi3_carryin_shift"
1375 [(set (match_operand:SI 0 "s_register_operand" "=r")
1376 (minus:SI (minus:SI
1377 (match_operator:SI 2 "shift_operator"
1378 [(match_operand:SI 3 "s_register_operand" "r")
1379 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1380 (match_operand:SI 1 "s_register_operand" "r"))
1381 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1382 "TARGET_ARM"
1383 "rsc%?\\t%0, %1, %3%S2"
1384 [(set_attr "conds" "use")
1385 (set_attr "predicable" "yes")
1386 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
6b6abc9c 1387 (const_string "arlo_shift")
1388 (const_string "arlo_shift_reg")))]
9154bd82 1389)
1390
d795fb69 1391; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1392(define_split
1393 [(set (match_operand:SI 0 "s_register_operand" "")
1394 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1395 (match_operand:SI 2 "s_register_operand" ""))
1396 (const_int -1)))
1397 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1398 "TARGET_32BIT"
d795fb69 1399 [(set (match_dup 3) (match_dup 1))
1400 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1401 "
1402 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1403")
1404
604f3a0a 1405(define_expand "addsf3"
1406 [(set (match_operand:SF 0 "s_register_operand" "")
1407 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1408 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1409 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1410 "
604f3a0a 1411")
1412
604f3a0a 1413(define_expand "adddf3"
1414 [(set (match_operand:DF 0 "s_register_operand" "")
1415 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1416 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1417 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1418 "
604f3a0a 1419")
1420
cffb2a26 1421(define_expand "subdi3"
1422 [(parallel
1423 [(set (match_operand:DI 0 "s_register_operand" "")
1424 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1425 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1426 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1427 "TARGET_EITHER"
1428 "
25f905c2 1429 if (TARGET_THUMB1)
cffb2a26 1430 {
0438d37f 1431 if (!REG_P (operands[1]))
5aa8c5f0 1432 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1433 if (!REG_P (operands[2]))
5aa8c5f0 1434 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1435 }
1436 "
1437)
1438
2f9b23e3 1439(define_insn_and_split "*arm_subdi3"
cffb2a26 1440 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1441 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1442 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1443 (clobber (reg:CC CC_REGNUM))]
94829feb 1444 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1445 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1446 "&& reload_completed"
1447 [(parallel [(set (reg:CC CC_REGNUM)
1448 (compare:CC (match_dup 1) (match_dup 2)))
1449 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1450 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1451 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1452 {
1453 operands[3] = gen_highpart (SImode, operands[0]);
1454 operands[0] = gen_lowpart (SImode, operands[0]);
1455 operands[4] = gen_highpart (SImode, operands[1]);
1456 operands[1] = gen_lowpart (SImode, operands[1]);
1457 operands[5] = gen_highpart (SImode, operands[2]);
1458 operands[2] = gen_lowpart (SImode, operands[2]);
1459 }
cffb2a26 1460 [(set_attr "conds" "clob")
1461 (set_attr "length" "8")]
1462)
1463
1464(define_insn "*thumb_subdi3"
1465 [(set (match_operand:DI 0 "register_operand" "=l")
1466 (minus:DI (match_operand:DI 1 "register_operand" "0")
1467 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1468 (clobber (reg:CC CC_REGNUM))]
25f905c2 1469 "TARGET_THUMB1"
cffb2a26 1470 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1471 [(set_attr "length" "4")]
1472)
9c08d1fa 1473
2f9b23e3 1474(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1475 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1476 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1477 (zero_extend:DI
cffb2a26 1478 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1479 (clobber (reg:CC CC_REGNUM))]
25f905c2 1480 "TARGET_32BIT"
2f9b23e3 1481 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1482 "&& reload_completed"
1483 [(parallel [(set (reg:CC CC_REGNUM)
1484 (compare:CC (match_dup 1) (match_dup 2)))
1485 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1486 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1487 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1488 {
1489 operands[3] = gen_highpart (SImode, operands[0]);
1490 operands[0] = gen_lowpart (SImode, operands[0]);
1491 operands[4] = gen_highpart (SImode, operands[1]);
1492 operands[1] = gen_lowpart (SImode, operands[1]);
1493 operands[5] = GEN_INT (~0);
1494 }
cffb2a26 1495 [(set_attr "conds" "clob")
1496 (set_attr "length" "8")]
1497)
9c08d1fa 1498
2f9b23e3 1499(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1500 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1501 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1502 (sign_extend:DI
cffb2a26 1503 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1504 (clobber (reg:CC CC_REGNUM))]
25f905c2 1505 "TARGET_32BIT"
2f9b23e3 1506 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1507 "&& reload_completed"
1508 [(parallel [(set (reg:CC CC_REGNUM)
1509 (compare:CC (match_dup 1) (match_dup 2)))
1510 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1511 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1512 (ashiftrt:SI (match_dup 2)
1513 (const_int 31)))
1514 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1515 {
1516 operands[3] = gen_highpart (SImode, operands[0]);
1517 operands[0] = gen_lowpart (SImode, operands[0]);
1518 operands[4] = gen_highpart (SImode, operands[1]);
1519 operands[1] = gen_lowpart (SImode, operands[1]);
1520 }
cffb2a26 1521 [(set_attr "conds" "clob")
1522 (set_attr "length" "8")]
1523)
9c08d1fa 1524
2f9b23e3 1525(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1526 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1527 (minus:DI (zero_extend:DI
cffb2a26 1528 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1529 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1530 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1531 "TARGET_ARM"
2f9b23e3 1532 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1533 ; is equivalent to:
1534 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1535 "&& reload_completed"
1536 [(parallel [(set (reg:CC CC_REGNUM)
1537 (compare:CC (match_dup 2) (match_dup 1)))
1538 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1539 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1540 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1541 {
1542 operands[3] = gen_highpart (SImode, operands[0]);
1543 operands[0] = gen_lowpart (SImode, operands[0]);
1544 operands[4] = gen_highpart (SImode, operands[1]);
1545 operands[1] = gen_lowpart (SImode, operands[1]);
1546 }
cffb2a26 1547 [(set_attr "conds" "clob")
1548 (set_attr "length" "8")]
1549)
9c08d1fa 1550
2f9b23e3 1551(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1552 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1553 (minus:DI (sign_extend:DI
cffb2a26 1554 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1555 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1556 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1557 "TARGET_ARM"
2f9b23e3 1558 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1559 ; is equivalent to:
1560 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1561 "&& reload_completed"
1562 [(parallel [(set (reg:CC CC_REGNUM)
1563 (compare:CC (match_dup 2) (match_dup 1)))
1564 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1565 (set (match_dup 3) (minus:SI (minus:SI
1566 (ashiftrt:SI (match_dup 2)
1567 (const_int 31))
1568 (match_dup 4))
1569 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1570 {
1571 operands[3] = gen_highpart (SImode, operands[0]);
1572 operands[0] = gen_lowpart (SImode, operands[0]);
1573 operands[4] = gen_highpart (SImode, operands[1]);
1574 operands[1] = gen_lowpart (SImode, operands[1]);
1575 }
cffb2a26 1576 [(set_attr "conds" "clob")
1577 (set_attr "length" "8")]
1578)
9c08d1fa 1579
2f9b23e3 1580(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1581 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1582 (minus:DI (zero_extend:DI
cffb2a26 1583 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1584 (zero_extend:DI
cffb2a26 1585 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1586 (clobber (reg:CC CC_REGNUM))]
25f905c2 1587 "TARGET_32BIT"
2f9b23e3 1588 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1589 "&& reload_completed"
1590 [(parallel [(set (reg:CC CC_REGNUM)
1591 (compare:CC (match_dup 1) (match_dup 2)))
1592 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1593 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1594 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1595 {
1596 operands[3] = gen_highpart (SImode, operands[0]);
1597 operands[0] = gen_lowpart (SImode, operands[0]);
1598 }
cffb2a26 1599 [(set_attr "conds" "clob")
1600 (set_attr "length" "8")]
1601)
b11cae9e 1602
87b22bf7 1603(define_expand "subsi3"
cffb2a26 1604 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1605 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1606 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1607 "TARGET_EITHER"
87b22bf7 1608 "
0438d37f 1609 if (CONST_INT_P (operands[1]))
87b22bf7 1610 {
25f905c2 1611 if (TARGET_32BIT)
cffb2a26 1612 {
96f57e36 1613 arm_split_constant (MINUS, SImode, NULL_RTX,
1614 INTVAL (operands[1]), operands[0],
e1ba4a27 1615 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1616 DONE;
1617 }
25f905c2 1618 else /* TARGET_THUMB1 */
cffb2a26 1619 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1620 }
cffb2a26 1621 "
1622)
87b22bf7 1623
747b7458 1624(define_insn "thumb1_subsi3_insn"
cffb2a26 1625 [(set (match_operand:SI 0 "register_operand" "=l")
1626 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1627 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1628 "TARGET_THUMB1"
cffb2a26 1629 "sub\\t%0, %1, %2"
747b7458 1630 [(set_attr "length" "2")
1631 (set_attr "conds" "set")])
cffb2a26 1632
25f905c2 1633; ??? Check Thumb-2 split length
a0f94409 1634(define_insn_and_split "*arm_subsi3_insn"
7c36fe71 1635 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r ,r,r,rk,r")
1636 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,rI,r,r,k ,?n")
1637 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r ,I,r,r ,r")))]
25f905c2 1638 "TARGET_32BIT"
e2348bcb 1639 "@
7c36fe71 1640 sub%?\\t%0, %1, %2
1641 sub%?\\t%0, %2
1642 sub%?\\t%0, %1, %2
1643 rsb%?\\t%0, %2, %1
87b22bf7 1644 rsb%?\\t%0, %2, %1
aaa37ad6 1645 sub%?\\t%0, %1, %2
080c0b9a 1646 sub%?\\t%0, %1, %2
65f68e55 1647 sub%?\\t%0, %1, %2
87b22bf7 1648 #"
0438d37f 1649 "&& (CONST_INT_P (operands[1])
91a5e339 1650 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1651 [(clobber (const_int 0))]
1652 "
96f57e36 1653 arm_split_constant (MINUS, SImode, curr_insn,
1654 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1655 DONE;
cffb2a26 1656 "
7c36fe71 1657 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1658 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1659 (set_attr "predicable" "yes")
7c36fe71 1660 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
1661 (set_attr "type" "*,*,*,*,arlo_imm,arlo_imm,*,*,arlo_imm")]
a0f94409 1662)
1663
1664(define_peephole2
1665 [(match_scratch:SI 3 "r")
372575c7 1666 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1667 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1668 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1669 "TARGET_32BIT
a0f94409 1670 && !const_ok_for_arm (INTVAL (operands[1]))
1671 && const_ok_for_arm (~INTVAL (operands[1]))"
1672 [(set (match_dup 3) (match_dup 1))
1673 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1674 ""
cffb2a26 1675)
b11cae9e 1676
f7fbdd4a 1677(define_insn "*subsi3_compare0"
bd5b4116 1678 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1679 (compare:CC_NOOV
65f68e55 1680 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1681 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1682 (const_int 0)))
65f68e55 1683 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1684 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1685 "TARGET_32BIT"
e2348bcb 1686 "@
65f68e55 1687 sub%.\\t%0, %1, %2
25f905c2 1688 sub%.\\t%0, %1, %2
1689 rsb%.\\t%0, %2, %1"
65f68e55 1690 [(set_attr "conds" "set")
6b6abc9c 1691 (set_attr "type" "arlo_imm,*,*")]
cffb2a26 1692)
9c08d1fa 1693
190efb17 1694(define_insn "subsi3_compare"
080c0b9a 1695 [(set (reg:CC CC_REGNUM)
65f68e55 1696 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1697 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1698 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1699 (minus:SI (match_dup 1) (match_dup 2)))]
1700 "TARGET_32BIT"
1701 "@
65f68e55 1702 sub%.\\t%0, %1, %2
2df9477b 1703 sub%.\\t%0, %1, %2
1704 rsb%.\\t%0, %2, %1"
65f68e55 1705 [(set_attr "conds" "set")
6b6abc9c 1706 (set_attr "type" "arlo_imm,*,*")]
2df9477b 1707)
1708
604f3a0a 1709(define_expand "subsf3"
1710 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1711 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1712 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1713 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1714 "
604f3a0a 1715")
1716
604f3a0a 1717(define_expand "subdf3"
1718 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1719 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1720 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1721 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1722 "
604f3a0a 1723")
1724
b11cae9e 1725\f
1726;; Multiplication insns
1727
cffb2a26 1728(define_expand "mulsi3"
1729 [(set (match_operand:SI 0 "s_register_operand" "")
1730 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1731 (match_operand:SI 1 "s_register_operand" "")))]
1732 "TARGET_EITHER"
1733 ""
1734)
1735
9c08d1fa 1736;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1737(define_insn "*arm_mulsi3"
1738 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1739 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1740 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1741 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1742 "mul%?\\t%0, %2, %1"
9da0ec36 1743 [(set_attr "type" "mul")
0d66636f 1744 (set_attr "predicable" "yes")]
cffb2a26 1745)
1746
58d7d654 1747(define_insn "*arm_mulsi3_v6"
d952d547 1748 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1749 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1750 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1751 "TARGET_32BIT && arm_arch6"
1752 "mul%?\\t%0, %1, %2"
9da0ec36 1753 [(set_attr "type" "mul")
d952d547 1754 (set_attr "predicable" "yes")
1755 (set_attr "arch" "t2,t2,*")
1756 (set_attr "length" "4")
1757 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1758)
1759
215b30b3 1760; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1761; 1 and 2; are the same, because reload will make operand 0 match
1762; operand 1 without realizing that this conflicts with operand 2. We fix
1763; this by adding another alternative to match this case, and then `reload'
1764; it ourselves. This alternative must come first.
cffb2a26 1765(define_insn "*thumb_mulsi3"
1766 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1767 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1768 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1769 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1770 "*
1771 if (which_alternative < 2)
20c4e896 1772 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1773 else
20c4e896 1774 return \"mul\\t%0, %2\";
cffb2a26 1775 "
1776 [(set_attr "length" "4,4,2")
9da0ec36 1777 (set_attr "type" "muls")]
cffb2a26 1778)
b11cae9e 1779
58d7d654 1780(define_insn "*thumb_mulsi3_v6"
1781 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1782 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1783 (match_operand:SI 2 "register_operand" "l,0,0")))]
1784 "TARGET_THUMB1 && arm_arch6"
1785 "@
1490694c 1786 mul\\t%0, %2
1787 mul\\t%0, %1
58d7d654 1788 mul\\t%0, %1"
1789 [(set_attr "length" "2")
9da0ec36 1790 (set_attr "type" "muls")]
58d7d654 1791)
1792
f7fbdd4a 1793(define_insn "*mulsi3_compare0"
bd5b4116 1794 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1795 (compare:CC_NOOV (mult:SI
1796 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1797 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1798 (const_int 0)))
1799 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1800 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1801 "TARGET_ARM && !arm_arch6"
1802 "mul%.\\t%0, %2, %1"
1803 [(set_attr "conds" "set")
9da0ec36 1804 (set_attr "type" "muls")]
58d7d654 1805)
1806
1807(define_insn "*mulsi3_compare0_v6"
1808 [(set (reg:CC_NOOV CC_REGNUM)
1809 (compare:CC_NOOV (mult:SI
1810 (match_operand:SI 2 "s_register_operand" "r")
1811 (match_operand:SI 1 "s_register_operand" "r"))
1812 (const_int 0)))
1813 (set (match_operand:SI 0 "s_register_operand" "=r")
1814 (mult:SI (match_dup 2) (match_dup 1)))]
1815 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1816 "mul%.\\t%0, %2, %1"
cffb2a26 1817 [(set_attr "conds" "set")
9da0ec36 1818 (set_attr "type" "muls")]
cffb2a26 1819)
9c08d1fa 1820
f7fbdd4a 1821(define_insn "*mulsi_compare0_scratch"
bd5b4116 1822 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1823 (compare:CC_NOOV (mult:SI
1824 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1825 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1826 (const_int 0)))
1827 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1828 "TARGET_ARM && !arm_arch6"
1829 "mul%.\\t%0, %2, %1"
1830 [(set_attr "conds" "set")
9da0ec36 1831 (set_attr "type" "muls")]
58d7d654 1832)
1833
1834(define_insn "*mulsi_compare0_scratch_v6"
1835 [(set (reg:CC_NOOV CC_REGNUM)
1836 (compare:CC_NOOV (mult:SI
1837 (match_operand:SI 2 "s_register_operand" "r")
1838 (match_operand:SI 1 "s_register_operand" "r"))
1839 (const_int 0)))
1840 (clobber (match_scratch:SI 0 "=r"))]
1841 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1842 "mul%.\\t%0, %2, %1"
cffb2a26 1843 [(set_attr "conds" "set")
9da0ec36 1844 (set_attr "type" "muls")]
cffb2a26 1845)
9c08d1fa 1846
b11cae9e 1847;; Unnamed templates to match MLA instruction.
1848
f7fbdd4a 1849(define_insn "*mulsi3addsi"
9c08d1fa 1850 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1851 (plus:SI
9c08d1fa 1852 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1853 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1854 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1855 "TARGET_32BIT && !arm_arch6"
1856 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1857 [(set_attr "type" "mla")
58d7d654 1858 (set_attr "predicable" "yes")]
1859)
1860
1861(define_insn "*mulsi3addsi_v6"
1862 [(set (match_operand:SI 0 "s_register_operand" "=r")
1863 (plus:SI
1864 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1865 (match_operand:SI 1 "s_register_operand" "r"))
1866 (match_operand:SI 3 "s_register_operand" "r")))]
1867 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1868 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1869 [(set_attr "type" "mla")
d952d547 1870 (set_attr "predicable" "yes")
1871 (set_attr "predicable_short_it" "no")]
0d66636f 1872)
b11cae9e 1873
f7fbdd4a 1874(define_insn "*mulsi3addsi_compare0"
bd5b4116 1875 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1876 (compare:CC_NOOV
1877 (plus:SI (mult:SI
1878 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1879 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1880 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1881 (const_int 0)))
9c08d1fa 1882 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1883 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1884 (match_dup 3)))]
58d7d654 1885 "TARGET_ARM && arm_arch6"
1886 "mla%.\\t%0, %2, %1, %3"
1887 [(set_attr "conds" "set")
9da0ec36 1888 (set_attr "type" "mlas")]
58d7d654 1889)
1890
1891(define_insn "*mulsi3addsi_compare0_v6"
1892 [(set (reg:CC_NOOV CC_REGNUM)
1893 (compare:CC_NOOV
1894 (plus:SI (mult:SI
1895 (match_operand:SI 2 "s_register_operand" "r")
1896 (match_operand:SI 1 "s_register_operand" "r"))
1897 (match_operand:SI 3 "s_register_operand" "r"))
1898 (const_int 0)))
1899 (set (match_operand:SI 0 "s_register_operand" "=r")
1900 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1901 (match_dup 3)))]
1902 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1903 "mla%.\\t%0, %2, %1, %3"
0d66636f 1904 [(set_attr "conds" "set")
9da0ec36 1905 (set_attr "type" "mlas")]
0d66636f 1906)
9c08d1fa 1907
f7fbdd4a 1908(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1909 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1910 (compare:CC_NOOV
1911 (plus:SI (mult:SI
1912 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1913 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1914 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1915 (const_int 0)))
9c08d1fa 1916 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1917 "TARGET_ARM && !arm_arch6"
1918 "mla%.\\t%0, %2, %1, %3"
1919 [(set_attr "conds" "set")
9da0ec36 1920 (set_attr "type" "mlas")]
58d7d654 1921)
1922
1923(define_insn "*mulsi3addsi_compare0_scratch_v6"
1924 [(set (reg:CC_NOOV CC_REGNUM)
1925 (compare:CC_NOOV
1926 (plus:SI (mult:SI
1927 (match_operand:SI 2 "s_register_operand" "r")
1928 (match_operand:SI 1 "s_register_operand" "r"))
1929 (match_operand:SI 3 "s_register_operand" "r"))
1930 (const_int 0)))
1931 (clobber (match_scratch:SI 0 "=r"))]
1932 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1933 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1934 [(set_attr "conds" "set")
9da0ec36 1935 (set_attr "type" "mlas")]
cffb2a26 1936)
f7fbdd4a 1937
89545238 1938(define_insn "*mulsi3subsi"
1939 [(set (match_operand:SI 0 "s_register_operand" "=r")
1940 (minus:SI
1941 (match_operand:SI 3 "s_register_operand" "r")
1942 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1943 (match_operand:SI 1 "s_register_operand" "r"))))]
1944 "TARGET_32BIT && arm_arch_thumb2"
1945 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1946 [(set_attr "type" "mla")
d952d547 1947 (set_attr "predicable" "yes")
1948 (set_attr "predicable_short_it" "no")]
89545238 1949)
1950
5cdca009 1951(define_expand "maddsidi4"
1952 [(set (match_operand:DI 0 "s_register_operand" "")
1953 (plus:DI
1954 (mult:DI
1955 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1956 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1957 (match_operand:DI 3 "s_register_operand" "")))]
1958 "TARGET_32BIT && arm_arch3m"
1959 "")
82b85d08 1960
1961(define_insn "*mulsidi3adddi"
fe8dbf85 1962 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1963 (plus:DI
215b30b3 1964 (mult:DI
fe8dbf85 1965 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1966 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1967 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1968 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1969 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1970 [(set_attr "type" "smlal")
58d7d654 1971 (set_attr "predicable" "yes")]
1972)
1973
1974(define_insn "*mulsidi3adddi_v6"
1975 [(set (match_operand:DI 0 "s_register_operand" "=r")
1976 (plus:DI
1977 (mult:DI
1978 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1979 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1980 (match_operand:DI 1 "s_register_operand" "0")))]
1981 "TARGET_32BIT && arm_arch6"
fe8dbf85 1982 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1983 [(set_attr "type" "smlal")
d952d547 1984 (set_attr "predicable" "yes")
1985 (set_attr "predicable_short_it" "no")]
0d66636f 1986)
82b85d08 1987
957788b0 1988;; 32x32->64 widening multiply.
1989;; As with mulsi3, the only difference between the v3-5 and v6+
1990;; versions of these patterns is the requirement that the output not
1991;; overlap the inputs, but that still means we have to have a named
1992;; expander and two different starred insns.
1993
1994(define_expand "mulsidi3"
1995 [(set (match_operand:DI 0 "s_register_operand" "")
1996 (mult:DI
1997 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1998 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1999 "TARGET_32BIT && arm_arch3m"
2000 ""
2001)
2002
2003(define_insn "*mulsidi3_nov6"
f7fbdd4a 2004 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 2005 (mult:DI
2006 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
2007 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 2008 "TARGET_32BIT && arm_arch3m && !arm_arch6"
2009 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 2010 [(set_attr "type" "smull")
58d7d654 2011 (set_attr "predicable" "yes")]
2012)
2013
957788b0 2014(define_insn "*mulsidi3_v6"
58d7d654 2015 [(set (match_operand:DI 0 "s_register_operand" "=r")
2016 (mult:DI
2017 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
2018 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
2019 "TARGET_32BIT && arm_arch6"
97499065 2020 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 2021 [(set_attr "type" "smull")
d952d547 2022 (set_attr "predicable" "yes")
2023 (set_attr "predicable_short_it" "no")]
0d66636f 2024)
f7fbdd4a 2025
957788b0 2026(define_expand "umulsidi3"
2027 [(set (match_operand:DI 0 "s_register_operand" "")
2028 (mult:DI
2029 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
2030 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
2031 "TARGET_32BIT && arm_arch3m"
2032 ""
2033)
2034
2035(define_insn "*umulsidi3_nov6"
f7fbdd4a 2036 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 2037 (mult:DI
2038 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
2039 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 2040 "TARGET_32BIT && arm_arch3m && !arm_arch6"
2041 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 2042 [(set_attr "type" "umull")
58d7d654 2043 (set_attr "predicable" "yes")]
2044)
2045
957788b0 2046(define_insn "*umulsidi3_v6"
58d7d654 2047 [(set (match_operand:DI 0 "s_register_operand" "=r")
2048 (mult:DI
2049 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
2050 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
2051 "TARGET_32BIT && arm_arch6"
97499065 2052 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 2053 [(set_attr "type" "umull")
d952d547 2054 (set_attr "predicable" "yes")
2055 (set_attr "predicable_short_it" "no")]
0d66636f 2056)
b11cae9e 2057
5cdca009 2058(define_expand "umaddsidi4"
2059 [(set (match_operand:DI 0 "s_register_operand" "")
2060 (plus:DI
2061 (mult:DI
2062 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
2063 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
2064 (match_operand:DI 3 "s_register_operand" "")))]
2065 "TARGET_32BIT && arm_arch3m"
2066 "")
82b85d08 2067
2068(define_insn "*umulsidi3adddi"
8ead09f9 2069 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 2070 (plus:DI
215b30b3 2071 (mult:DI
fe8dbf85 2072 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
2073 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
2074 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 2075 "TARGET_32BIT && arm_arch3m && !arm_arch6"
2076 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 2077 [(set_attr "type" "umlal")
58d7d654 2078 (set_attr "predicable" "yes")]
2079)
2080
2081(define_insn "*umulsidi3adddi_v6"
2082 [(set (match_operand:DI 0 "s_register_operand" "=r")
2083 (plus:DI
2084 (mult:DI
2085 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
2086 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
2087 (match_operand:DI 1 "s_register_operand" "0")))]
2088 "TARGET_32BIT && arm_arch6"
fe8dbf85 2089 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 2090 [(set_attr "type" "umlal")
d952d547 2091 (set_attr "predicable" "yes")
2092 (set_attr "predicable_short_it" "no")]
0d66636f 2093)
82b85d08 2094
957788b0 2095(define_expand "smulsi3_highpart"
2096 [(parallel
2097 [(set (match_operand:SI 0 "s_register_operand" "")
2098 (truncate:SI
2099 (lshiftrt:DI
2100 (mult:DI
2101 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
2102 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
2103 (const_int 32))))
2104 (clobber (match_scratch:SI 3 ""))])]
2105 "TARGET_32BIT && arm_arch3m"
2106 ""
2107)
2108
2109(define_insn "*smulsi3_highpart_nov6"
f082f1c4 2110 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
2111 (truncate:SI
2112 (lshiftrt:DI
215b30b3 2113 (mult:DI
e5fea38e 2114 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 2115 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 2116 (const_int 32))))
2117 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 2118 "TARGET_32BIT && arm_arch3m && !arm_arch6"
2119 "smull%?\\t%3, %0, %2, %1"
9da0ec36 2120 [(set_attr "type" "smull")
58d7d654 2121 (set_attr "predicable" "yes")]
2122)
2123
957788b0 2124(define_insn "*smulsi3_highpart_v6"
58d7d654 2125 [(set (match_operand:SI 0 "s_register_operand" "=r")
2126 (truncate:SI
2127 (lshiftrt:DI
2128 (mult:DI
2129 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
2130 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
2131 (const_int 32))))
2132 (clobber (match_scratch:SI 3 "=r"))]
2133 "TARGET_32BIT && arm_arch6"
f082f1c4 2134 "smull%?\\t%3, %0, %2, %1"
9da0ec36 2135 [(set_attr "type" "smull")
d952d547 2136 (set_attr "predicable" "yes")
2137 (set_attr "predicable_short_it" "no")]
cffb2a26 2138)
f082f1c4 2139
957788b0 2140(define_expand "umulsi3_highpart"
2141 [(parallel
2142 [(set (match_operand:SI 0 "s_register_operand" "")
2143 (truncate:SI
2144 (lshiftrt:DI
2145 (mult:DI
2146 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
2147 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
2148 (const_int 32))))
2149 (clobber (match_scratch:SI 3 ""))])]
2150 "TARGET_32BIT && arm_arch3m"
2151 ""
2152)
2153
2154(define_insn "*umulsi3_highpart_nov6"
f082f1c4 2155 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
2156 (truncate:SI
2157 (lshiftrt:DI
215b30b3 2158 (mult:DI
e5fea38e 2159 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 2160 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 2161 (const_int 32))))
2162 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 2163 "TARGET_32BIT && arm_arch3m && !arm_arch6"
2164 "umull%?\\t%3, %0, %2, %1"
9da0ec36 2165 [(set_attr "type" "umull")
58d7d654 2166 (set_attr "predicable" "yes")]
2167)
2168
957788b0 2169(define_insn "*umulsi3_highpart_v6"
58d7d654 2170 [(set (match_operand:SI 0 "s_register_operand" "=r")
2171 (truncate:SI
2172 (lshiftrt:DI
2173 (mult:DI
2174 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
2175 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
2176 (const_int 32))))
2177 (clobber (match_scratch:SI 3 "=r"))]
2178 "TARGET_32BIT && arm_arch6"
f082f1c4 2179 "umull%?\\t%3, %0, %2, %1"
9da0ec36 2180 [(set_attr "type" "umull")
d952d547 2181 (set_attr "predicable" "yes")
2182 (set_attr "predicable_short_it" "no")]
cffb2a26 2183)
f082f1c4 2184
331beb1a 2185(define_insn "mulhisi3"
2186 [(set (match_operand:SI 0 "s_register_operand" "=r")
2187 (mult:SI (sign_extend:SI
2188 (match_operand:HI 1 "s_register_operand" "%r"))
2189 (sign_extend:SI
2190 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 2191 "TARGET_DSP_MULTIPLY"
61a2d04c 2192 "smulbb%?\\t%0, %1, %2"
9da0ec36 2193 [(set_attr "type" "smulxy")
fec538d9 2194 (set_attr "predicable" "yes")]
2195)
2196
2197(define_insn "*mulhisi3tb"
2198 [(set (match_operand:SI 0 "s_register_operand" "=r")
2199 (mult:SI (ashiftrt:SI
2200 (match_operand:SI 1 "s_register_operand" "r")
2201 (const_int 16))
2202 (sign_extend:SI
2203 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 2204 "TARGET_DSP_MULTIPLY"
fec538d9 2205 "smultb%?\\t%0, %1, %2"
9da0ec36 2206 [(set_attr "type" "smulxy")
d952d547 2207 (set_attr "predicable" "yes")
2208 (set_attr "predicable_short_it" "no")]
fec538d9 2209)
2210
2211(define_insn "*mulhisi3bt"
2212 [(set (match_operand:SI 0 "s_register_operand" "=r")
2213 (mult:SI (sign_extend:SI
2214 (match_operand:HI 1 "s_register_operand" "r"))
2215 (ashiftrt:SI
2216 (match_operand:SI 2 "s_register_operand" "r")
2217 (const_int 16))))]
25f905c2 2218 "TARGET_DSP_MULTIPLY"
fec538d9 2219 "smulbt%?\\t%0, %1, %2"
9da0ec36 2220 [(set_attr "type" "smulxy")
d952d547 2221 (set_attr "predicable" "yes")
2222 (set_attr "predicable_short_it" "no")]
fec538d9 2223)
2224
2225(define_insn "*mulhisi3tt"
2226 [(set (match_operand:SI 0 "s_register_operand" "=r")
2227 (mult:SI (ashiftrt:SI
2228 (match_operand:SI 1 "s_register_operand" "r")
2229 (const_int 16))
2230 (ashiftrt:SI
2231 (match_operand:SI 2 "s_register_operand" "r")
2232 (const_int 16))))]
25f905c2 2233 "TARGET_DSP_MULTIPLY"
fec538d9 2234 "smultt%?\\t%0, %1, %2"
9da0ec36 2235 [(set_attr "type" "smulxy")
d952d547 2236 (set_attr "predicable" "yes")
2237 (set_attr "predicable_short_it" "no")]
331beb1a 2238)
2239
5cdca009 2240(define_insn "maddhisi4"
331beb1a 2241 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 2242 (plus:SI (mult:SI (sign_extend:SI
2243 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2244 (sign_extend:SI
cfa6c608 2245 (match_operand:HI 2 "s_register_operand" "r")))
2246 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 2247 "TARGET_DSP_MULTIPLY"
5cdca009 2248 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 2249 [(set_attr "type" "smlaxy")
d952d547 2250 (set_attr "predicable" "yes")
2251 (set_attr "predicable_short_it" "no")]
331beb1a 2252)
2253
9a92f368 2254;; Note: there is no maddhisi4ibt because this one is canonical form
2255(define_insn "*maddhisi4tb"
2256 [(set (match_operand:SI 0 "s_register_operand" "=r")
2257 (plus:SI (mult:SI (ashiftrt:SI
2258 (match_operand:SI 1 "s_register_operand" "r")
2259 (const_int 16))
2260 (sign_extend:SI
2261 (match_operand:HI 2 "s_register_operand" "r")))
2262 (match_operand:SI 3 "s_register_operand" "r")))]
2263 "TARGET_DSP_MULTIPLY"
2264 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 2265 [(set_attr "type" "smlaxy")
d952d547 2266 (set_attr "predicable" "yes")
2267 (set_attr "predicable_short_it" "no")]
9a92f368 2268)
2269
2270(define_insn "*maddhisi4tt"
2271 [(set (match_operand:SI 0 "s_register_operand" "=r")
2272 (plus:SI (mult:SI (ashiftrt:SI
2273 (match_operand:SI 1 "s_register_operand" "r")
2274 (const_int 16))
2275 (ashiftrt:SI
2276 (match_operand:SI 2 "s_register_operand" "r")
2277 (const_int 16)))
2278 (match_operand:SI 3 "s_register_operand" "r")))]
2279 "TARGET_DSP_MULTIPLY"
2280 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 2281 [(set_attr "type" "smlaxy")
d952d547 2282 (set_attr "predicable" "yes")
2283 (set_attr "predicable_short_it" "no")]
9a92f368 2284)
2285
aff5fb4d 2286(define_insn "maddhidi4"
331beb1a 2287 [(set (match_operand:DI 0 "s_register_operand" "=r")
2288 (plus:DI
331beb1a 2289 (mult:DI (sign_extend:DI
d952d547 2290 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2291 (sign_extend:DI
cfa6c608 2292 (match_operand:HI 2 "s_register_operand" "r")))
2293 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 2294 "TARGET_DSP_MULTIPLY"
5cdca009 2295 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2296 [(set_attr "type" "smlalxy")
d952d547 2297 (set_attr "predicable" "yes")
2298 (set_attr "predicable_short_it" "no")])
331beb1a 2299
9a92f368 2300;; Note: there is no maddhidi4ibt because this one is canonical form
2301(define_insn "*maddhidi4tb"
2302 [(set (match_operand:DI 0 "s_register_operand" "=r")
2303 (plus:DI
2304 (mult:DI (sign_extend:DI
2305 (ashiftrt:SI
2306 (match_operand:SI 1 "s_register_operand" "r")
2307 (const_int 16)))
2308 (sign_extend:DI
2309 (match_operand:HI 2 "s_register_operand" "r")))
2310 (match_operand:DI 3 "s_register_operand" "0")))]
2311 "TARGET_DSP_MULTIPLY"
2312 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2313 [(set_attr "type" "smlalxy")
d952d547 2314 (set_attr "predicable" "yes")
2315 (set_attr "predicable_short_it" "no")])
9a92f368 2316
2317(define_insn "*maddhidi4tt"
2318 [(set (match_operand:DI 0 "s_register_operand" "=r")
2319 (plus:DI
2320 (mult:DI (sign_extend:DI
2321 (ashiftrt:SI
2322 (match_operand:SI 1 "s_register_operand" "r")
2323 (const_int 16)))
2324 (sign_extend:DI
2325 (ashiftrt:SI
2326 (match_operand:SI 2 "s_register_operand" "r")
2327 (const_int 16))))
2328 (match_operand:DI 3 "s_register_operand" "0")))]
2329 "TARGET_DSP_MULTIPLY"
2330 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 2331 [(set_attr "type" "smlalxy")
d952d547 2332 (set_attr "predicable" "yes")
2333 (set_attr "predicable_short_it" "no")])
9a92f368 2334
604f3a0a 2335(define_expand "mulsf3"
2336 [(set (match_operand:SF 0 "s_register_operand" "")
2337 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 2338 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 2339 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 2340 "
604f3a0a 2341")
2342
604f3a0a 2343(define_expand "muldf3"
2344 [(set (match_operand:DF 0 "s_register_operand" "")
2345 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 2346 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 2347 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 2348 "
604f3a0a 2349")
b11cae9e 2350\f
2351;; Division insns
2352
7db9af5d 2353(define_expand "divsf3"
2354 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 2355 (div:SF (match_operand:SF 1 "s_register_operand" "")
2356 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 2357 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 2358 "")
9c08d1fa 2359
7db9af5d 2360(define_expand "divdf3"
2361 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 2362 (div:DF (match_operand:DF 1 "s_register_operand" "")
2363 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 2364 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 2365 "")
b11cae9e 2366\f
2367;; Boolean and,ior,xor insns
2368
f6ebffac 2369;; Split up double word logical operations
2370
2371;; Split up simple DImode logical operations. Simply perform the logical
2372;; operation on the upper and lower halves of the registers.
2373(define_split
2374 [(set (match_operand:DI 0 "s_register_operand" "")
2375 (match_operator:DI 6 "logical_binary_operator"
2376 [(match_operand:DI 1 "s_register_operand" "")
2377 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 2378 "TARGET_32BIT && reload_completed
e2669ea7 2379 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 2380 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2381 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2382 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2383 "
215b30b3 2384 {
2385 operands[3] = gen_highpart (SImode, operands[0]);
2386 operands[0] = gen_lowpart (SImode, operands[0]);
2387 operands[4] = gen_highpart (SImode, operands[1]);
2388 operands[1] = gen_lowpart (SImode, operands[1]);
2389 operands[5] = gen_highpart (SImode, operands[2]);
2390 operands[2] = gen_lowpart (SImode, operands[2]);
2391 }"
2392)
f6ebffac 2393
f6ebffac 2394(define_split
2395 [(set (match_operand:DI 0 "s_register_operand" "")
2396 (match_operator:DI 6 "logical_binary_operator"
2397 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2398 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2399 "TARGET_32BIT && reload_completed"
f6ebffac 2400 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2401 (set (match_dup 3) (match_op_dup:SI 6
2402 [(ashiftrt:SI (match_dup 2) (const_int 31))
2403 (match_dup 4)]))]
2404 "
215b30b3 2405 {
2406 operands[3] = gen_highpart (SImode, operands[0]);
2407 operands[0] = gen_lowpart (SImode, operands[0]);
2408 operands[4] = gen_highpart (SImode, operands[1]);
2409 operands[1] = gen_lowpart (SImode, operands[1]);
2410 operands[5] = gen_highpart (SImode, operands[2]);
2411 operands[2] = gen_lowpart (SImode, operands[2]);
2412 }"
2413)
f6ebffac 2414
f6ebffac 2415;; The zero extend of operand 2 means we can just copy the high part of
2416;; operand1 into operand0.
2417(define_split
2418 [(set (match_operand:DI 0 "s_register_operand" "")
2419 (ior:DI
2420 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2421 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2422 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2423 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2424 (set (match_dup 3) (match_dup 4))]
2425 "
215b30b3 2426 {
2427 operands[4] = gen_highpart (SImode, operands[1]);
2428 operands[3] = gen_highpart (SImode, operands[0]);
2429 operands[0] = gen_lowpart (SImode, operands[0]);
2430 operands[1] = gen_lowpart (SImode, operands[1]);
2431 }"
2432)
f6ebffac 2433
2434;; The zero extend of operand 2 means we can just copy the high part of
2435;; operand1 into operand0.
2436(define_split
2437 [(set (match_operand:DI 0 "s_register_operand" "")
2438 (xor:DI
2439 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2440 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2441 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2442 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2443 (set (match_dup 3) (match_dup 4))]
2444 "
215b30b3 2445 {
2446 operands[4] = gen_highpart (SImode, operands[1]);
2447 operands[3] = gen_highpart (SImode, operands[0]);
2448 operands[0] = gen_lowpart (SImode, operands[0]);
2449 operands[1] = gen_lowpart (SImode, operands[1]);
2450 }"
2451)
f6ebffac 2452
e2669ea7 2453(define_expand "anddi3"
2454 [(set (match_operand:DI 0 "s_register_operand" "")
2455 (and:DI (match_operand:DI 1 "s_register_operand" "")
2456 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2457 "TARGET_32BIT"
2458 ""
2459)
2460
f6bbdcf6 2461(define_insn_and_split "*anddi3_insn"
0a314dcd 2462 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2463 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2464 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2465 "TARGET_32BIT && !TARGET_IWMMXT"
2466{
2467 switch (which_alternative)
2468 {
0a314dcd 2469 case 0: /* fall through */
2470 case 6: return "vand\t%P0, %P1, %P2";
2471 case 1: /* fall through */
2472 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2473 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2474 case 2:
0a314dcd 2475 case 3:
2476 case 4:
f6bbdcf6 2477 case 5: /* fall through */
0a314dcd 2478 return "#";
f6bbdcf6 2479 default: gcc_unreachable ();
2480 }
2481}
0a314dcd 2482 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2483 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2484 [(set (match_dup 3) (match_dup 4))
2485 (set (match_dup 5) (match_dup 6))]
2486 "
2487 {
2488 operands[3] = gen_lowpart (SImode, operands[0]);
2489 operands[5] = gen_highpart (SImode, operands[0]);
2490
2491 operands[4] = simplify_gen_binary (AND, SImode,
2492 gen_lowpart (SImode, operands[1]),
2493 gen_lowpart (SImode, operands[2]));
2494 operands[6] = simplify_gen_binary (AND, SImode,
2495 gen_highpart (SImode, operands[1]),
2496 gen_highpart_mode (SImode, DImode, operands[2]));
2497
2498 }"
0a314dcd 2499 [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*,*,*,neon_int_1,neon_int_1")
2500 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2501 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2502 (set_attr "length" "*,*,8,8,8,8,*,*")
2503 ]
215b30b3 2504)
b11cae9e 2505
a0f94409 2506(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2507 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2508 (and:DI (zero_extend:DI
2509 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2510 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2511 "TARGET_32BIT"
f6ebffac 2512 "#"
25f905c2 2513 "TARGET_32BIT && reload_completed"
a0f94409 2514 ; The zero extend of operand 2 clears the high word of the output
2515 ; operand.
2516 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2517 (set (match_dup 3) (const_int 0))]
2518 "
2519 {
2520 operands[3] = gen_highpart (SImode, operands[0]);
2521 operands[0] = gen_lowpart (SImode, operands[0]);
2522 operands[1] = gen_lowpart (SImode, operands[1]);
2523 }"
215b30b3 2524 [(set_attr "length" "8")]
2525)
b11cae9e 2526
f7fbdd4a 2527(define_insn "*anddi_sesdi_di"
cffb2a26 2528 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2529 (and:DI (sign_extend:DI
2530 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2531 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2532 "TARGET_32BIT"
f6ebffac 2533 "#"
cffb2a26 2534 [(set_attr "length" "8")]
2535)
b11cae9e 2536
87b22bf7 2537(define_expand "andsi3"
cffb2a26 2538 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2539 (and:SI (match_operand:SI 1 "s_register_operand" "")
2540 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2541 "TARGET_EITHER"
87b22bf7 2542 "
25f905c2 2543 if (TARGET_32BIT)
87b22bf7 2544 {
0438d37f 2545 if (CONST_INT_P (operands[2]))
cffb2a26 2546 {
47b5b27b 2547 if (INTVAL (operands[2]) == 255 && arm_arch6)
2548 {
2549 operands[1] = convert_to_mode (QImode, operands[1], 1);
2550 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2551 operands[1]));
2552 }
2553 else
2554 arm_split_constant (AND, SImode, NULL_RTX,
2555 INTVAL (operands[2]), operands[0],
2556 operands[1],
2557 optimize && can_create_pseudo_p ());
615caa51 2558
cffb2a26 2559 DONE;
2560 }
87b22bf7 2561 }
25f905c2 2562 else /* TARGET_THUMB1 */
cffb2a26 2563 {
0438d37f 2564 if (!CONST_INT_P (operands[2]))
923ffadb 2565 {
2566 rtx tmp = force_reg (SImode, operands[2]);
2567 if (rtx_equal_p (operands[0], operands[1]))
2568 operands[2] = tmp;
2569 else
2570 {
2571 operands[2] = operands[1];
2572 operands[1] = tmp;
2573 }
2574 }
cffb2a26 2575 else
2576 {
2577 int i;
2578
215b30b3 2579 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2580 {
215b30b3 2581 operands[2] = force_reg (SImode,
2582 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2583
747b7458 2584 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2585
2586 DONE;
2587 }
87b22bf7 2588
cffb2a26 2589 for (i = 9; i <= 31; i++)
2590 {
2591 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2592 {
2593 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2594 const0_rtx));
2595 DONE;
2596 }
215b30b3 2597 else if ((((HOST_WIDE_INT) 1) << i) - 1
2598 == ~INTVAL (operands[2]))
cffb2a26 2599 {
2600 rtx shift = GEN_INT (i);
2601 rtx reg = gen_reg_rtx (SImode);
2602
2603 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2604 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2605
2606 DONE;
2607 }
2608 }
2609
2610 operands[2] = force_reg (SImode, operands[2]);
2611 }
215b30b3 2612 }
2613 "
cffb2a26 2614)
2615
25f905c2 2616; ??? Check split length for Thumb-2
a0f94409 2617(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2618 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2619 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2620 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2621 "TARGET_32BIT"
5565501b 2622 "@
29e234a3 2623 and%?\\t%0, %1, %2
5565501b 2624 and%?\\t%0, %1, %2
87b22bf7 2625 bic%?\\t%0, %1, #%B2
65f68e55 2626 and%?\\t%0, %1, %2
87b22bf7 2627 #"
25f905c2 2628 "TARGET_32BIT
0438d37f 2629 && CONST_INT_P (operands[2])
a0f94409 2630 && !(const_ok_for_arm (INTVAL (operands[2]))
2631 || const_ok_for_arm (~INTVAL (operands[2])))"
2632 [(clobber (const_int 0))]
2633 "
96f57e36 2634 arm_split_constant (AND, SImode, curr_insn,
2635 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2636 DONE;
2637 "
29e234a3 2638 [(set_attr "length" "4,4,4,4,16")
65f68e55 2639 (set_attr "predicable" "yes")
29e234a3 2640 (set_attr "predicable_short_it" "no,yes,no,no,no")
2641 (set_attr "type"
6b6abc9c 2642 "arlo_imm,arlo_imm,*,*,arlo_imm")]
cffb2a26 2643)
2644
25f905c2 2645(define_insn "*thumb1_andsi3_insn"
cffb2a26 2646 [(set (match_operand:SI 0 "register_operand" "=l")
2647 (and:SI (match_operand:SI 1 "register_operand" "%0")
2648 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2649 "TARGET_THUMB1"
747b7458 2650 "and\\t%0, %2"
2651 [(set_attr "length" "2")
6b6abc9c 2652 (set_attr "type" "arlo_imm")
747b7458 2653 (set_attr "conds" "set")])
87b22bf7 2654
f7fbdd4a 2655(define_insn "*andsi3_compare0"
bd5b4116 2656 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2657 (compare:CC_NOOV
65f68e55 2658 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2659 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2660 (const_int 0)))
65f68e55 2661 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2662 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2663 "TARGET_32BIT"
5565501b 2664 "@
25f905c2 2665 and%.\\t%0, %1, %2
65f68e55 2666 bic%.\\t%0, %1, #%B2
2667 and%.\\t%0, %1, %2"
2668 [(set_attr "conds" "set")
6b6abc9c 2669 (set_attr "type" "arlo_imm,arlo_imm,*")]
cffb2a26 2670)
9c08d1fa 2671
f7fbdd4a 2672(define_insn "*andsi3_compare0_scratch"
bd5b4116 2673 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2674 (compare:CC_NOOV
65f68e55 2675 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2676 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2677 (const_int 0)))
65f68e55 2678 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2679 "TARGET_32BIT"
5565501b 2680 "@
2681 tst%?\\t%0, %1
65f68e55 2682 bic%.\\t%2, %0, #%B1
2683 tst%?\\t%0, %1"
2684 [(set_attr "conds" "set")
6b6abc9c 2685 (set_attr "type" "arlo_imm,arlo_imm,*")]
0d66636f 2686)
9c08d1fa 2687
f7fbdd4a 2688(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2689 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2690 (compare:CC_NOOV (zero_extract:SI
2691 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2692 (match_operand 1 "const_int_operand" "n")
206ee9a2 2693 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2694 (const_int 0)))]
25f905c2 2695 "TARGET_32BIT
cffb2a26 2696 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2697 && INTVAL (operands[1]) > 0
2698 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2699 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2700 "*
5c49a439 2701 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2702 << INTVAL (operands[2]));
40dbec34 2703 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2704 return \"\";
0d66636f 2705 "
596e5e8f 2706 [(set_attr "conds" "set")
65f68e55 2707 (set_attr "predicable" "yes")
d952d547 2708 (set_attr "predicable_short_it" "no")
6b6abc9c 2709 (set_attr "type" "arlo_imm")]
0d66636f 2710)
9c08d1fa 2711
f4462328 2712(define_insn_and_split "*ne_zeroextractsi"
c4034607 2713 [(set (match_operand:SI 0 "s_register_operand" "=r")
2714 (ne:SI (zero_extract:SI
2715 (match_operand:SI 1 "s_register_operand" "r")
2716 (match_operand:SI 2 "const_int_operand" "n")
2717 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2718 (const_int 0)))
2719 (clobber (reg:CC CC_REGNUM))]
25f905c2 2720 "TARGET_32BIT
cffb2a26 2721 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2722 && INTVAL (operands[2]) > 0
2723 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2724 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2725 "#"
25f905c2 2726 "TARGET_32BIT
f4462328 2727 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2728 && INTVAL (operands[2]) > 0
2729 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2730 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2731 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2732 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2733 (const_int 0)))
2734 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2735 (set (match_dup 0)
2736 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2737 (match_dup 0) (const_int 1)))]
2738 "
2739 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2740 << INTVAL (operands[3]));
2741 "
2742 [(set_attr "conds" "clob")
25f905c2 2743 (set (attr "length")
2744 (if_then_else (eq_attr "is_thumb" "yes")
2745 (const_int 12)
2746 (const_int 8)))]
f4462328 2747)
2748
2749(define_insn_and_split "*ne_zeroextractsi_shifted"
2750 [(set (match_operand:SI 0 "s_register_operand" "=r")
2751 (ne:SI (zero_extract:SI
2752 (match_operand:SI 1 "s_register_operand" "r")
2753 (match_operand:SI 2 "const_int_operand" "n")
2754 (const_int 0))
2755 (const_int 0)))
2756 (clobber (reg:CC CC_REGNUM))]
2757 "TARGET_ARM"
2758 "#"
2759 "TARGET_ARM"
2760 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2761 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2762 (const_int 0)))
2763 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2764 (set (match_dup 0)
2765 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2766 (match_dup 0) (const_int 1)))]
2767 "
2768 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2769 "
2770 [(set_attr "conds" "clob")
2771 (set_attr "length" "8")]
2772)
2773
2774(define_insn_and_split "*ite_ne_zeroextractsi"
2775 [(set (match_operand:SI 0 "s_register_operand" "=r")
2776 (if_then_else:SI (ne (zero_extract:SI
2777 (match_operand:SI 1 "s_register_operand" "r")
2778 (match_operand:SI 2 "const_int_operand" "n")
2779 (match_operand:SI 3 "const_int_operand" "n"))
2780 (const_int 0))
2781 (match_operand:SI 4 "arm_not_operand" "rIK")
2782 (const_int 0)))
2783 (clobber (reg:CC CC_REGNUM))]
2784 "TARGET_ARM
2785 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2786 && INTVAL (operands[2]) > 0
2787 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2788 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2789 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2790 "#"
2791 "TARGET_ARM
2792 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2793 && INTVAL (operands[2]) > 0
2794 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2795 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2796 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2797 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2798 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2799 (const_int 0)))
2800 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2801 (set (match_dup 0)
2802 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2803 (match_dup 0) (match_dup 4)))]
2804 "
c4034607 2805 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2806 << INTVAL (operands[3]));
2807 "
2808 [(set_attr "conds" "clob")
2809 (set_attr "length" "8")]
2810)
2811
2812(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2813 [(set (match_operand:SI 0 "s_register_operand" "=r")
2814 (if_then_else:SI (ne (zero_extract:SI
2815 (match_operand:SI 1 "s_register_operand" "r")
2816 (match_operand:SI 2 "const_int_operand" "n")
2817 (const_int 0))
2818 (const_int 0))
2819 (match_operand:SI 3 "arm_not_operand" "rIK")
2820 (const_int 0)))
2821 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2822 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2823 "#"
f8d7bf2f 2824 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2825 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2826 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2827 (const_int 0)))
2828 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2829 (set (match_dup 0)
2830 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2831 (match_dup 0) (match_dup 3)))]
2832 "
2833 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2834 "
2835 [(set_attr "conds" "clob")
215b30b3 2836 (set_attr "length" "8")]
2837)
9c08d1fa 2838
58d6528b 2839(define_split
2840 [(set (match_operand:SI 0 "s_register_operand" "")
2841 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2842 (match_operand:SI 2 "const_int_operand" "")
2843 (match_operand:SI 3 "const_int_operand" "")))
2844 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2845 "TARGET_THUMB1"
58d6528b 2846 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2847 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2848 "{
2849 HOST_WIDE_INT temp = INTVAL (operands[2]);
2850
2851 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2852 operands[3] = GEN_INT (32 - temp);
2853 }"
2854)
2855
25f905c2 2856;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2857(define_split
2858 [(set (match_operand:SI 0 "s_register_operand" "")
2859 (match_operator:SI 1 "shiftable_operator"
2860 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2861 (match_operand:SI 3 "const_int_operand" "")
2862 (match_operand:SI 4 "const_int_operand" ""))
2863 (match_operand:SI 5 "s_register_operand" "")]))
2864 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2865 "TARGET_ARM"
2866 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2867 (set (match_dup 0)
2868 (match_op_dup 1
2869 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2870 (match_dup 5)]))]
2871 "{
2872 HOST_WIDE_INT temp = INTVAL (operands[3]);
2873
2874 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2875 operands[4] = GEN_INT (32 - temp);
2876 }"
2877)
2878
58d6528b 2879(define_split
2880 [(set (match_operand:SI 0 "s_register_operand" "")
2881 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2882 (match_operand:SI 2 "const_int_operand" "")
2883 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2884 "TARGET_THUMB1"
58d6528b 2885 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2886 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2887 "{
2888 HOST_WIDE_INT temp = INTVAL (operands[2]);
2889
2890 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2891 operands[3] = GEN_INT (32 - temp);
2892 }"
2893)
2894
d7863cfe 2895(define_split
2896 [(set (match_operand:SI 0 "s_register_operand" "")
2897 (match_operator:SI 1 "shiftable_operator"
2898 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2899 (match_operand:SI 3 "const_int_operand" "")
2900 (match_operand:SI 4 "const_int_operand" ""))
2901 (match_operand:SI 5 "s_register_operand" "")]))
2902 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2903 "TARGET_ARM"
2904 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2905 (set (match_dup 0)
2906 (match_op_dup 1
2907 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2908 (match_dup 5)]))]
2909 "{
2910 HOST_WIDE_INT temp = INTVAL (operands[3]);
2911
2912 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2913 operands[4] = GEN_INT (32 - temp);
2914 }"
2915)
2916
a42059fd 2917;;; ??? This pattern is bogus. If operand3 has bits outside the range
2918;;; represented by the bitfield, then this will produce incorrect results.
2919;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2920;;; which have a real bit-field insert instruction, the truncation happens
2921;;; in the bit-field insert instruction itself. Since arm does not have a
2922;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2923;;; the value before we insert. This loses some of the advantage of having
2924;;; this insv pattern, so this pattern needs to be reevalutated.
2925
8a18b90c 2926(define_expand "insv"
eb04cafb 2927 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2928 (match_operand 1 "general_operand" "")
2929 (match_operand 2 "general_operand" ""))
2930 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2931 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2932 "
215b30b3 2933 {
2934 int start_bit = INTVAL (operands[2]);
2935 int width = INTVAL (operands[1]);
2936 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2937 rtx target, subtarget;
2938
8b054d5a 2939 if (arm_arch_thumb2)
2940 {
eb04cafb 2941 if (unaligned_access && MEM_P (operands[0])
2942 && s_register_operand (operands[3], GET_MODE (operands[3]))
2943 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2944 {
eb04cafb 2945 rtx base_addr;
2946
2947 if (BYTES_BIG_ENDIAN)
2948 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2949 - start_bit;
8b054d5a 2950
eb04cafb 2951 if (width == 32)
8b054d5a 2952 {
eb04cafb 2953 base_addr = adjust_address (operands[0], SImode,
2954 start_bit / BITS_PER_UNIT);
2955 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2956 }
eb04cafb 2957 else
2958 {
2959 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2960
eb04cafb 2961 base_addr = adjust_address (operands[0], HImode,
2962 start_bit / BITS_PER_UNIT);
2963 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2964 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2965 }
2966 DONE;
8b054d5a 2967 }
eb04cafb 2968 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2969 {
eb04cafb 2970 bool use_bfi = TRUE;
8b054d5a 2971
0438d37f 2972 if (CONST_INT_P (operands[3]))
eb04cafb 2973 {
2974 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2975
2976 if (val == 0)
2977 {
2978 emit_insn (gen_insv_zero (operands[0], operands[1],
2979 operands[2]));
2980 DONE;
2981 }
2982
2983 /* See if the set can be done with a single orr instruction. */
2984 if (val == mask && const_ok_for_arm (val << start_bit))
2985 use_bfi = FALSE;
2986 }
2987
2988 if (use_bfi)
2989 {
0438d37f 2990 if (!REG_P (operands[3]))
eb04cafb 2991 operands[3] = force_reg (SImode, operands[3]);
2992
2993 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2994 operands[3]));
2995 DONE;
2996 }
8b054d5a 2997 }
eb04cafb 2998 else
2999 FAIL;
8b054d5a 3000 }
3001
eb04cafb 3002 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
3003 FAIL;
3004
3f8fde42 3005 target = copy_rtx (operands[0]);
215b30b3 3006 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
3007 subreg as the final target. */
3008 if (GET_CODE (target) == SUBREG)
3009 {
3010 subtarget = gen_reg_rtx (SImode);
3011 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
3012 < GET_MODE_SIZE (SImode))
3013 target = SUBREG_REG (target);
3014 }
3015 else
3016 subtarget = target;
8a18b90c 3017
0438d37f 3018 if (CONST_INT_P (operands[3]))
215b30b3 3019 {
3020 /* Since we are inserting a known constant, we may be able to
3021 reduce the number of bits that we have to clear so that
3022 the mask becomes simple. */
3023 /* ??? This code does not check to see if the new mask is actually
3024 simpler. It may not be. */
3025 rtx op1 = gen_reg_rtx (SImode);
3026 /* ??? Truncate operand3 to fit in the bitfield. See comment before
3027 start of this pattern. */
3028 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
3029 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
3030
c5b3a71b 3031 emit_insn (gen_andsi3 (op1, operands[0],
3032 gen_int_mode (~mask2, SImode)));
215b30b3 3033 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 3034 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 3035 }
3036 else if (start_bit == 0
3037 && !(const_ok_for_arm (mask)
3038 || const_ok_for_arm (~mask)))
3039 {
3040 /* A Trick, since we are setting the bottom bits in the word,
3041 we can shift operand[3] up, operand[0] down, OR them together
3042 and rotate the result back again. This takes 3 insns, and
5910bb95 3043 the third might be mergeable into another op. */
215b30b3 3044 /* The shift up copes with the possibility that operand[3] is
3045 wider than the bitfield. */
3046 rtx op0 = gen_reg_rtx (SImode);
3047 rtx op1 = gen_reg_rtx (SImode);
3048
3049 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
3050 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
3051 emit_insn (gen_iorsi3 (op1, op1, op0));
3052 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
3053 }
3054 else if ((width + start_bit == 32)
3055 && !(const_ok_for_arm (mask)
3056 || const_ok_for_arm (~mask)))
3057 {
3058 /* Similar trick, but slightly less efficient. */
8a18b90c 3059
215b30b3 3060 rtx op0 = gen_reg_rtx (SImode);
3061 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 3062
215b30b3 3063 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
3064 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
3065 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
3066 emit_insn (gen_iorsi3 (subtarget, op1, op0));
3067 }
3068 else
3069 {
c5b3a71b 3070 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 3071 rtx op1 = gen_reg_rtx (SImode);
3072 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 3073
215b30b3 3074 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
3075 {
3076 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 3077
215b30b3 3078 emit_insn (gen_movsi (tmp, op0));
3079 op0 = tmp;
3080 }
8a18b90c 3081
215b30b3 3082 /* Mask out any bits in operand[3] that are not needed. */
3083 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 3084
0438d37f 3085 if (CONST_INT_P (op0)
215b30b3 3086 && (const_ok_for_arm (mask << start_bit)
3087 || const_ok_for_arm (~(mask << start_bit))))
3088 {
c5b3a71b 3089 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 3090 emit_insn (gen_andsi3 (op2, operands[0], op0));
3091 }
3092 else
3093 {
0438d37f 3094 if (CONST_INT_P (op0))
215b30b3 3095 {
3096 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 3097
215b30b3 3098 emit_insn (gen_movsi (tmp, op0));
3099 op0 = tmp;
3100 }
3101
3102 if (start_bit != 0)
3103 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 3104
215b30b3 3105 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
3106 }
8a18b90c 3107
215b30b3 3108 if (start_bit != 0)
3109 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 3110
215b30b3 3111 emit_insn (gen_iorsi3 (subtarget, op1, op2));
3112 }
f082f1c4 3113
215b30b3 3114 if (subtarget != target)
3115 {
3116 /* If TARGET is still a SUBREG, then it must be wider than a word,
3117 so we must be careful only to set the subword we were asked to. */
3118 if (GET_CODE (target) == SUBREG)
3119 emit_move_insn (target, subtarget);
3120 else
3121 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
3122 }
8a18b90c 3123
215b30b3 3124 DONE;
3125 }"
3126)
8a18b90c 3127
8b054d5a 3128(define_insn "insv_zero"
3129 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
3130 (match_operand:SI 1 "const_int_operand" "M")
3131 (match_operand:SI 2 "const_int_operand" "M"))
3132 (const_int 0))]
3133 "arm_arch_thumb2"
3134 "bfc%?\t%0, %2, %1"
3135 [(set_attr "length" "4")
d952d547 3136 (set_attr "predicable" "yes")
3137 (set_attr "predicable_short_it" "no")]
8b054d5a 3138)
3139
3140(define_insn "insv_t2"
3141 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
3142 (match_operand:SI 1 "const_int_operand" "M")
3143 (match_operand:SI 2 "const_int_operand" "M"))
3144 (match_operand:SI 3 "s_register_operand" "r"))]
3145 "arm_arch_thumb2"
3146 "bfi%?\t%0, %3, %2, %1"
3147 [(set_attr "length" "4")
d952d547 3148 (set_attr "predicable" "yes")
3149 (set_attr "predicable_short_it" "no")]
8b054d5a 3150)
3151
215b30b3 3152; constants for op 2 will never be given to these patterns.
a0f94409 3153(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 3154 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 3155 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
3156 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 3157 "TARGET_32BIT"
f6ebffac 3158 "#"
e2669ea7 3159 "TARGET_32BIT && reload_completed
3160 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
3161 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 3162 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
3163 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
3164 "
3165 {
3166 operands[3] = gen_highpart (SImode, operands[0]);
3167 operands[0] = gen_lowpart (SImode, operands[0]);
3168 operands[4] = gen_highpart (SImode, operands[1]);
3169 operands[1] = gen_lowpart (SImode, operands[1]);
3170 operands[5] = gen_highpart (SImode, operands[2]);
3171 operands[2] = gen_lowpart (SImode, operands[2]);
3172 }"
0d66636f 3173 [(set_attr "length" "8")
3174 (set_attr "predicable" "yes")]
3175)
d952d547 3176
a0f94409 3177(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 3178 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3179 (and:DI (not:DI (zero_extend:DI
3180 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 3181 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3182 "TARGET_32BIT"
e2348bcb 3183 "@
97499065 3184 bic%?\\t%Q0, %Q1, %2
f6ebffac 3185 #"
a0f94409 3186 ; (not (zero_extend ...)) allows us to just copy the high word from
3187 ; operand1 to operand0.
25f905c2 3188 "TARGET_32BIT
a0f94409 3189 && reload_completed
3190 && operands[0] != operands[1]"
5a097f7d 3191 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 3192 (set (match_dup 3) (match_dup 4))]
3193 "
3194 {
3195 operands[3] = gen_highpart (SImode, operands[0]);
3196 operands[0] = gen_lowpart (SImode, operands[0]);
3197 operands[4] = gen_highpart (SImode, operands[1]);
3198 operands[1] = gen_lowpart (SImode, operands[1]);
3199 }"
0d66636f 3200 [(set_attr "length" "4,8")
d952d547 3201 (set_attr "predicable" "yes")
3202 (set_attr "predicable_short_it" "no")]
0d66636f 3203)
d952d547 3204
a0f94409 3205(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 3206 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3207 (and:DI (not:DI (sign_extend:DI
3208 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 3209 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3210 "TARGET_32BIT"
f6ebffac 3211 "#"
25f905c2 3212 "TARGET_32BIT && reload_completed"
5a097f7d 3213 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 3214 (set (match_dup 3) (and:SI (not:SI
3215 (ashiftrt:SI (match_dup 2) (const_int 31)))
3216 (match_dup 4)))]
3217 "
3218 {
3219 operands[3] = gen_highpart (SImode, operands[0]);
3220 operands[0] = gen_lowpart (SImode, operands[0]);
3221 operands[4] = gen_highpart (SImode, operands[1]);
3222 operands[1] = gen_lowpart (SImode, operands[1]);
3223 }"
0d66636f 3224 [(set_attr "length" "8")
d952d547 3225 (set_attr "predicable" "yes")
3226 (set_attr "predicable_short_it" "no")]
0d66636f 3227)
d952d547 3228
8a18b90c 3229(define_insn "andsi_notsi_si"
9c08d1fa 3230 [(set (match_operand:SI 0 "s_register_operand" "=r")
3231 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3232 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3233 "TARGET_32BIT"
0d66636f 3234 "bic%?\\t%0, %1, %2"
d952d547 3235 [(set_attr "predicable" "yes")
3236 (set_attr "predicable_short_it" "no")]
0d66636f 3237)
b11cae9e 3238
747b7458 3239(define_insn "thumb1_bicsi3"
cffb2a26 3240 [(set (match_operand:SI 0 "register_operand" "=l")
3241 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
3242 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 3243 "TARGET_THUMB1"
747b7458 3244 "bic\\t%0, %1"
3245 [(set_attr "length" "2")
3246 (set_attr "conds" "set")])
cffb2a26 3247
8a18b90c 3248(define_insn "andsi_not_shiftsi_si"
a2cd141b 3249 [(set (match_operand:SI 0 "s_register_operand" "=r")
3250 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
3251 [(match_operand:SI 2 "s_register_operand" "r")
3252 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
3253 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3254 "TARGET_ARM"
6c4c2133 3255 "bic%?\\t%0, %1, %2%S4"
344495ea 3256 [(set_attr "predicable" "yes")
331beb1a 3257 (set_attr "shift" "2")
a2cd141b 3258 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6b6abc9c 3259 (const_string "arlo_shift")
3260 (const_string "arlo_shift_reg")))]
6c4c2133 3261)
8a18b90c 3262
f7fbdd4a 3263(define_insn "*andsi_notsi_si_compare0"
bd5b4116 3264 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3265 (compare:CC_NOOV
3266 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3267 (match_operand:SI 1 "s_register_operand" "r"))
3268 (const_int 0)))
9c08d1fa 3269 (set (match_operand:SI 0 "s_register_operand" "=r")
3270 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 3271 "TARGET_32BIT"
3272 "bic%.\\t%0, %1, %2"
0d66636f 3273 [(set_attr "conds" "set")]
3274)
9c08d1fa 3275
f7fbdd4a 3276(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 3277 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3278 (compare:CC_NOOV
3279 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3280 (match_operand:SI 1 "s_register_operand" "r"))
3281 (const_int 0)))
9c08d1fa 3282 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3283 "TARGET_32BIT"
3284 "bic%.\\t%0, %1, %2"
0d66636f 3285 [(set_attr "conds" "set")]
3286)
9c08d1fa 3287
e2669ea7 3288(define_expand "iordi3"
3289 [(set (match_operand:DI 0 "s_register_operand" "")
3290 (ior:DI (match_operand:DI 1 "s_register_operand" "")
3291 (match_operand:DI 2 "neon_logic_op2" "")))]
3292 "TARGET_32BIT"
3293 ""
3294)
3295
74d6113f 3296(define_insn_and_split "*iordi3_insn"
3297 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
3298 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 3299 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 3300 "TARGET_32BIT && !TARGET_IWMMXT"
3301 {
3302 switch (which_alternative)
3303 {
3304 case 0: /* fall through */
3305 case 6: return "vorr\t%P0, %P1, %P2";
3306 case 1: /* fall through */
3307 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
3308 DImode, 0, VALID_NEON_QREG_MODE (DImode));
3309 case 2:
3310 case 3:
3311 case 4:
3312 case 5:
3313 return "#";
3314 default: gcc_unreachable ();
3315 }
3316 }
3317 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3318 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3319 [(set (match_dup 3) (match_dup 4))
3320 (set (match_dup 5) (match_dup 6))]
3321 "
3322 {
3323 operands[3] = gen_lowpart (SImode, operands[0]);
3324 operands[5] = gen_highpart (SImode, operands[0]);
3325
3326 operands[4] = simplify_gen_binary (IOR, SImode,
3327 gen_lowpart (SImode, operands[1]),
3328 gen_lowpart (SImode, operands[2]));
3329 operands[6] = simplify_gen_binary (IOR, SImode,
3330 gen_highpart (SImode, operands[1]),
3331 gen_highpart_mode (SImode, DImode, operands[2]));
3332
3333 }"
3334 [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*,*,*,neon_int_1,neon_int_1")
e0fe6977 3335 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 3336 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 3337)
9c08d1fa 3338
f7fbdd4a 3339(define_insn "*iordi_zesidi_di"
9c08d1fa 3340 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3341 (ior:DI (zero_extend:DI
3342 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3343 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3344 "TARGET_32BIT"
e2348bcb 3345 "@
97499065 3346 orr%?\\t%Q0, %Q1, %2
f6ebffac 3347 #"
0d66636f 3348 [(set_attr "length" "4,8")
d952d547 3349 (set_attr "predicable" "yes")
3350 (set_attr "predicable_short_it" "no")]
cffb2a26 3351)
9c08d1fa 3352
f7fbdd4a 3353(define_insn "*iordi_sesidi_di"
9c08d1fa 3354 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3355 (ior:DI (sign_extend:DI
3356 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3357 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3358 "TARGET_32BIT"
f6ebffac 3359 "#"
0d66636f 3360 [(set_attr "length" "8")
3361 (set_attr "predicable" "yes")]
cffb2a26 3362)
9c08d1fa 3363
87b22bf7 3364(define_expand "iorsi3"
cffb2a26 3365 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3366 (ior:SI (match_operand:SI 1 "s_register_operand" "")
3367 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3368 "TARGET_EITHER"
87b22bf7 3369 "
0438d37f 3370 if (CONST_INT_P (operands[2]))
87b22bf7 3371 {
25f905c2 3372 if (TARGET_32BIT)
cffb2a26 3373 {
96f57e36 3374 arm_split_constant (IOR, SImode, NULL_RTX,
3375 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 3376 optimize && can_create_pseudo_p ());
cffb2a26 3377 DONE;
3378 }
25f905c2 3379 else /* TARGET_THUMB1 */
923ffadb 3380 {
3381 rtx tmp = force_reg (SImode, operands[2]);
3382 if (rtx_equal_p (operands[0], operands[1]))
3383 operands[2] = tmp;
3384 else
3385 {
3386 operands[2] = operands[1];
3387 operands[1] = tmp;
3388 }
3389 }
87b22bf7 3390 }
cffb2a26 3391 "
3392)
87b22bf7 3393
d5d4dc8d 3394(define_insn_and_split "*iorsi3_insn"
29e234a3 3395 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
3396 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
3397 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 3398 "TARGET_32BIT"
87b22bf7 3399 "@
29e234a3 3400 orr%?\\t%0, %1, %2
87b22bf7 3401 orr%?\\t%0, %1, %2
d5d4dc8d 3402 orn%?\\t%0, %1, #%B2
65f68e55 3403 orr%?\\t%0, %1, %2
87b22bf7 3404 #"
d5d4dc8d 3405 "TARGET_32BIT
0438d37f 3406 && CONST_INT_P (operands[2])
d5d4dc8d 3407 && !(const_ok_for_arm (INTVAL (operands[2]))
3408 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 3409 [(clobber (const_int 0))]
d5d4dc8d 3410{
29e234a3 3411 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 3412 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 3413 DONE;
d5d4dc8d 3414}
29e234a3 3415 [(set_attr "length" "4,4,4,4,16")
3416 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 3417 (set_attr "predicable" "yes")
29e234a3 3418 (set_attr "predicable_short_it" "no,yes,no,no,no")
6b6abc9c 3419 (set_attr "type" "arlo_imm,*,arlo_imm,*,*")]
65f68e55 3420)
cffb2a26 3421
747b7458 3422(define_insn "*thumb1_iorsi3_insn"
cffb2a26 3423 [(set (match_operand:SI 0 "register_operand" "=l")
3424 (ior:SI (match_operand:SI 1 "register_operand" "%0")
3425 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3426 "TARGET_THUMB1"
747b7458 3427 "orr\\t%0, %2"
3428 [(set_attr "length" "2")
3429 (set_attr "conds" "set")])
9c08d1fa 3430
a0f94409 3431(define_peephole2
3432 [(match_scratch:SI 3 "r")
372575c7 3433 (set (match_operand:SI 0 "arm_general_register_operand" "")
3434 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3435 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3436 "TARGET_ARM
a0f94409 3437 && !const_ok_for_arm (INTVAL (operands[2]))
3438 && const_ok_for_arm (~INTVAL (operands[2]))"
3439 [(set (match_dup 3) (match_dup 2))
3440 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3441 ""
215b30b3 3442)
a0f94409 3443
f7fbdd4a 3444(define_insn "*iorsi3_compare0"
bd5b4116 3445 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3446 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3447 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3448 (const_int 0)))
65f68e55 3449 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3450 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3451 "TARGET_32BIT"
3452 "orr%.\\t%0, %1, %2"
65f68e55 3453 [(set_attr "conds" "set")
6b6abc9c 3454 (set_attr "type" "arlo_imm,*")]
cffb2a26 3455)
9c08d1fa 3456
f7fbdd4a 3457(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3458 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3459 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3460 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3461 (const_int 0)))
65f68e55 3462 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3463 "TARGET_32BIT"
3464 "orr%.\\t%0, %1, %2"
65f68e55 3465 [(set_attr "conds" "set")
6b6abc9c 3466 (set_attr "type" "arlo_imm,*")]
0d66636f 3467)
9c08d1fa 3468
e2669ea7 3469(define_expand "xordi3"
3470 [(set (match_operand:DI 0 "s_register_operand" "")
3471 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 3472 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 3473 "TARGET_32BIT"
3474 ""
3475)
3476
8ee7dc6f 3477(define_insn_and_split "*xordi3_insn"
3478 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
3479 (xor:DI (match_operand:DI 1 "s_register_operand" "w ,%0,r ,0 ,r ,w")
3480 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3481 "TARGET_32BIT && !TARGET_IWMMXT"
3482{
3483 switch (which_alternative)
3484 {
3485 case 1:
3486 case 2:
3487 case 3:
3488 case 4: /* fall through */
3489 return "#";
3490 case 0: /* fall through */
3491 case 5: return "veor\t%P0, %P1, %P2";
3492 default: gcc_unreachable ();
3493 }
3494}
3495 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3496 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3497 [(set (match_dup 3) (match_dup 4))
3498 (set (match_dup 5) (match_dup 6))]
3499 "
3500 {
3501 operands[3] = gen_lowpart (SImode, operands[0]);
3502 operands[5] = gen_highpart (SImode, operands[0]);
3503
3504 operands[4] = simplify_gen_binary (XOR, SImode,
3505 gen_lowpart (SImode, operands[1]),
3506 gen_lowpart (SImode, operands[2]));
3507 operands[6] = simplify_gen_binary (XOR, SImode,
3508 gen_highpart (SImode, operands[1]),
3509 gen_highpart_mode (SImode, DImode, operands[2]));
3510
3511 }"
3512 [(set_attr "length" "*,8,8,8,8,*")
3513 (set_attr "neon_type" "neon_int_1,*,*,*,*,neon_int_1")
3514 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3515)
9c08d1fa 3516
f7fbdd4a 3517(define_insn "*xordi_zesidi_di"
9c08d1fa 3518 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3519 (xor:DI (zero_extend:DI
3520 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3521 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3522 "TARGET_32BIT"
e2348bcb 3523 "@
97499065 3524 eor%?\\t%Q0, %Q1, %2
f6ebffac 3525 #"
0d66636f 3526 [(set_attr "length" "4,8")
d952d547 3527 (set_attr "predicable" "yes")
3528 (set_attr "predicable_short_it" "no")]
cffb2a26 3529)
9c08d1fa 3530
f7fbdd4a 3531(define_insn "*xordi_sesidi_di"
9c08d1fa 3532 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3533 (xor:DI (sign_extend:DI
3534 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3535 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3536 "TARGET_32BIT"
f6ebffac 3537 "#"
0d66636f 3538 [(set_attr "length" "8")
3539 (set_attr "predicable" "yes")]
cffb2a26 3540)
9c08d1fa 3541
cffb2a26 3542(define_expand "xorsi3"
3543 [(set (match_operand:SI 0 "s_register_operand" "")
3544 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3545 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3546 "TARGET_EITHER"
0438d37f 3547 "if (CONST_INT_P (operands[2]))
923ffadb 3548 {
3549 if (TARGET_32BIT)
3550 {
3551 arm_split_constant (XOR, SImode, NULL_RTX,
3552 INTVAL (operands[2]), operands[0], operands[1],
3553 optimize && can_create_pseudo_p ());
3554 DONE;
3555 }
3556 else /* TARGET_THUMB1 */
3557 {
3558 rtx tmp = force_reg (SImode, operands[2]);
3559 if (rtx_equal_p (operands[0], operands[1]))
3560 operands[2] = tmp;
3561 else
3562 {
3563 operands[2] = operands[1];
3564 operands[1] = tmp;
3565 }
3566 }
3567 }"
cffb2a26 3568)
3569
5dcb35d9 3570(define_insn_and_split "*arm_xorsi3"
29e234a3 3571 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3572 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3573 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3574 "TARGET_32BIT"
5dcb35d9 3575 "@
29e234a3 3576 eor%?\\t%0, %1, %2
65f68e55 3577 eor%?\\t%0, %1, %2
5dcb35d9 3578 eor%?\\t%0, %1, %2
3579 #"
3580 "TARGET_32BIT
0438d37f 3581 && CONST_INT_P (operands[2])
5dcb35d9 3582 && !const_ok_for_arm (INTVAL (operands[2]))"
3583 [(clobber (const_int 0))]
3584{
3585 arm_split_constant (XOR, SImode, curr_insn,
3586 INTVAL (operands[2]), operands[0], operands[1], 0);
3587 DONE;
3588}
29e234a3 3589 [(set_attr "length" "4,4,4,16")
65f68e55 3590 (set_attr "predicable" "yes")
29e234a3 3591 (set_attr "predicable_short_it" "no,yes,no,no")
6b6abc9c 3592 (set_attr "type" "arlo_imm,*,*,*")]
cffb2a26 3593)
3594
747b7458 3595(define_insn "*thumb1_xorsi3_insn"
cffb2a26 3596 [(set (match_operand:SI 0 "register_operand" "=l")
3597 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3598 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3599 "TARGET_THUMB1"
747b7458 3600 "eor\\t%0, %2"
3601 [(set_attr "length" "2")
65f68e55 3602 (set_attr "conds" "set")
6b6abc9c 3603 (set_attr "type" "arlo_imm")]
65f68e55 3604)
9c08d1fa 3605
f7fbdd4a 3606(define_insn "*xorsi3_compare0"
bd5b4116 3607 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3608 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3609 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3610 (const_int 0)))
65f68e55 3611 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3612 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3613 "TARGET_32BIT"
3614 "eor%.\\t%0, %1, %2"
65f68e55 3615 [(set_attr "conds" "set")
6b6abc9c 3616 (set_attr "type" "arlo_imm,*")]
0d66636f 3617)
9c08d1fa 3618
f7fbdd4a 3619(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3620 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3621 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3622 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3623 (const_int 0)))]
25f905c2 3624 "TARGET_32BIT"
40dbec34 3625 "teq%?\\t%0, %1"
65f68e55 3626 [(set_attr "conds" "set")
6b6abc9c 3627 (set_attr "type" "arlo_imm,*")]
cffb2a26 3628)
9c08d1fa 3629
215b30b3 3630; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3631; (NOT D) we can sometimes merge the final NOT into one of the following
3632; insns.
9c08d1fa 3633
3634(define_split
a058e94a 3635 [(set (match_operand:SI 0 "s_register_operand" "")
3636 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3637 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3638 (match_operand:SI 3 "arm_rhs_operand" "")))
3639 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3640 "TARGET_32BIT"
9c08d1fa 3641 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3642 (not:SI (match_dup 3))))
3643 (set (match_dup 0) (not:SI (match_dup 4)))]
3644 ""
3645)
3646
ba6a3b2f 3647(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3648 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3649 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3650 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3651 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3652 "TARGET_32BIT"
ba6a3b2f 3653 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3654 "&& reload_completed"
3655 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3656 (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 0)))]
3657 ""
0d66636f 3658 [(set_attr "length" "8")
25f905c2 3659 (set_attr "ce_count" "2")
d952d547 3660 (set_attr "predicable" "yes")
3661 (set_attr "predicable_short_it" "no")]
cffb2a26 3662)
9c08d1fa 3663
25f905c2 3664; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3665; insns are available?
d7863cfe 3666(define_split
3667 [(set (match_operand:SI 0 "s_register_operand" "")
3668 (match_operator:SI 1 "logical_binary_operator"
3669 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3670 (match_operand:SI 3 "const_int_operand" "")
3671 (match_operand:SI 4 "const_int_operand" ""))
3672 (match_operator:SI 9 "logical_binary_operator"
3673 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3674 (match_operand:SI 6 "const_int_operand" ""))
3675 (match_operand:SI 7 "s_register_operand" "")])]))
3676 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3677 "TARGET_32BIT
d7863cfe 3678 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3679 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3680 [(set (match_dup 8)
3681 (match_op_dup 1
3682 [(ashift:SI (match_dup 2) (match_dup 4))
3683 (match_dup 5)]))
3684 (set (match_dup 0)
3685 (match_op_dup 1
3686 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3687 (match_dup 7)]))]
3688 "
3689 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3690")
3691
3692(define_split
3693 [(set (match_operand:SI 0 "s_register_operand" "")
3694 (match_operator:SI 1 "logical_binary_operator"
3695 [(match_operator:SI 9 "logical_binary_operator"
3696 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3697 (match_operand:SI 6 "const_int_operand" ""))
3698 (match_operand:SI 7 "s_register_operand" "")])
3699 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3700 (match_operand:SI 3 "const_int_operand" "")
3701 (match_operand:SI 4 "const_int_operand" ""))]))
3702 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3703 "TARGET_32BIT
d7863cfe 3704 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3705 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3706 [(set (match_dup 8)
3707 (match_op_dup 1
3708 [(ashift:SI (match_dup 2) (match_dup 4))
3709 (match_dup 5)]))
3710 (set (match_dup 0)
3711 (match_op_dup 1
3712 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3713 (match_dup 7)]))]
3714 "
3715 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3716")
3717
3718(define_split
3719 [(set (match_operand:SI 0 "s_register_operand" "")
3720 (match_operator:SI 1 "logical_binary_operator"
3721 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3722 (match_operand:SI 3 "const_int_operand" "")
3723 (match_operand:SI 4 "const_int_operand" ""))
3724 (match_operator:SI 9 "logical_binary_operator"
3725 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3726 (match_operand:SI 6 "const_int_operand" ""))
3727 (match_operand:SI 7 "s_register_operand" "")])]))
3728 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3729 "TARGET_32BIT
d7863cfe 3730 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3731 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3732 [(set (match_dup 8)
3733 (match_op_dup 1
3734 [(ashift:SI (match_dup 2) (match_dup 4))
3735 (match_dup 5)]))
3736 (set (match_dup 0)
3737 (match_op_dup 1
3738 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3739 (match_dup 7)]))]
3740 "
3741 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3742")
3743
3744(define_split
3745 [(set (match_operand:SI 0 "s_register_operand" "")
3746 (match_operator:SI 1 "logical_binary_operator"
3747 [(match_operator:SI 9 "logical_binary_operator"
3748 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3749 (match_operand:SI 6 "const_int_operand" ""))
3750 (match_operand:SI 7 "s_register_operand" "")])
3751 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3752 (match_operand:SI 3 "const_int_operand" "")
3753 (match_operand:SI 4 "const_int_operand" ""))]))
3754 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3755 "TARGET_32BIT
d7863cfe 3756 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3757 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3758 [(set (match_dup 8)
3759 (match_op_dup 1
3760 [(ashift:SI (match_dup 2) (match_dup 4))
3761 (match_dup 5)]))
3762 (set (match_dup 0)
3763 (match_op_dup 1
3764 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3765 (match_dup 7)]))]
3766 "
3767 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3768")
9c08d1fa 3769\f
3770
3771;; Minimum and maximum insns
3772
8b9dc177 3773(define_expand "smaxsi3"
3774 [(parallel [
3775 (set (match_operand:SI 0 "s_register_operand" "")
3776 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3777 (match_operand:SI 2 "arm_rhs_operand" "")))
3778 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3779 "TARGET_32BIT"
8b9dc177 3780 "
8774928b 3781 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3782 {
3783 /* No need for a clobber of the condition code register here. */
3784 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3785 gen_rtx_SMAX (SImode, operands[1],
3786 operands[2])));
3787 DONE;
3788 }
3789")
3790
3791(define_insn "*smax_0"
3792 [(set (match_operand:SI 0 "s_register_operand" "=r")
3793 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3794 (const_int 0)))]
25f905c2 3795 "TARGET_32BIT"
8b9dc177 3796 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3797 [(set_attr "predicable" "yes")
3798 (set_attr "predicable_short_it" "no")]
8b9dc177 3799)
3800
8774928b 3801(define_insn "*smax_m1"
3802 [(set (match_operand:SI 0 "s_register_operand" "=r")
3803 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3804 (const_int -1)))]
25f905c2 3805 "TARGET_32BIT"
8774928b 3806 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3807 [(set_attr "predicable" "yes")
3808 (set_attr "predicable_short_it" "no")]
8774928b 3809)
3810
3dc953f2 3811(define_insn_and_split "*arm_smax_insn"
8b9dc177 3812 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3813 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3814 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3815 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3816 "TARGET_ARM"
3dc953f2 3817 "#"
3818 ; cmp\\t%1, %2\;movlt\\t%0, %2
3819 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3820 "TARGET_ARM"
3821 [(set (reg:CC CC_REGNUM)
3822 (compare:CC (match_dup 1) (match_dup 2)))
3823 (set (match_dup 0)
3824 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3825 (match_dup 1)
3826 (match_dup 2)))]
3827 ""
cffb2a26 3828 [(set_attr "conds" "clob")
8b9dc177 3829 (set_attr "length" "8,12")]
cffb2a26 3830)
9c08d1fa 3831
8b9dc177 3832(define_expand "sminsi3"
3833 [(parallel [
3834 (set (match_operand:SI 0 "s_register_operand" "")
3835 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3836 (match_operand:SI 2 "arm_rhs_operand" "")))
3837 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3838 "TARGET_32BIT"
8b9dc177 3839 "
3840 if (operands[2] == const0_rtx)
3841 {
3842 /* No need for a clobber of the condition code register here. */
3843 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3844 gen_rtx_SMIN (SImode, operands[1],
3845 operands[2])));
3846 DONE;
3847 }
3848")
3849
3850(define_insn "*smin_0"
3851 [(set (match_operand:SI 0 "s_register_operand" "=r")
3852 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3853 (const_int 0)))]
25f905c2 3854 "TARGET_32BIT"
8b9dc177 3855 "and%?\\t%0, %1, %1, asr #31"
d952d547 3856 [(set_attr "predicable" "yes")
3857 (set_attr "predicable_short_it" "no")]
8b9dc177 3858)
3859
3dc953f2 3860(define_insn_and_split "*arm_smin_insn"
8b9dc177 3861 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3862 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3863 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3864 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3865 "TARGET_ARM"
3dc953f2 3866 "#"
3867 ; cmp\\t%1, %2\;movge\\t%0, %2
3868 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3869 "TARGET_ARM"
3870 [(set (reg:CC CC_REGNUM)
3871 (compare:CC (match_dup 1) (match_dup 2)))
3872 (set (match_dup 0)
3873 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3874 (match_dup 1)
3875 (match_dup 2)))]
3876 ""
0d66636f 3877 [(set_attr "conds" "clob")
8b9dc177 3878 (set_attr "length" "8,12")]
0d66636f 3879)
9c08d1fa 3880
25f905c2 3881(define_expand "umaxsi3"
3882 [(parallel [
3883 (set (match_operand:SI 0 "s_register_operand" "")
3884 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3885 (match_operand:SI 2 "arm_rhs_operand" "")))
3886 (clobber (reg:CC CC_REGNUM))])]
3887 "TARGET_32BIT"
3888 ""
3889)
3890
3dc953f2 3891(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3892 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3893 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3894 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3895 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3896 "TARGET_ARM"
3dc953f2 3897 "#"
3898 ; cmp\\t%1, %2\;movcc\\t%0, %2
3899 ; cmp\\t%1, %2\;movcs\\t%0, %1
3900 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3901 "TARGET_ARM"
3902 [(set (reg:CC CC_REGNUM)
3903 (compare:CC (match_dup 1) (match_dup 2)))
3904 (set (match_dup 0)
3905 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3906 (match_dup 1)
3907 (match_dup 2)))]
3908 ""
0d66636f 3909 [(set_attr "conds" "clob")
3910 (set_attr "length" "8,8,12")]
3911)
9c08d1fa 3912
25f905c2 3913(define_expand "uminsi3"
3914 [(parallel [
3915 (set (match_operand:SI 0 "s_register_operand" "")
3916 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3917 (match_operand:SI 2 "arm_rhs_operand" "")))
3918 (clobber (reg:CC CC_REGNUM))])]
3919 "TARGET_32BIT"
3920 ""
3921)
3922
3dc953f2 3923(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3924 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3925 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3926 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3927 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3928 "TARGET_ARM"
3dc953f2 3929 "#"
3930 ; cmp\\t%1, %2\;movcs\\t%0, %2
3931 ; cmp\\t%1, %2\;movcc\\t%0, %1
3932 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3933 "TARGET_ARM"
3934 [(set (reg:CC CC_REGNUM)
3935 (compare:CC (match_dup 1) (match_dup 2)))
3936 (set (match_dup 0)
3937 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3938 (match_dup 1)
3939 (match_dup 2)))]
3940 ""
0d66636f 3941 [(set_attr "conds" "clob")
3942 (set_attr "length" "8,8,12")]
3943)
9c08d1fa 3944
8a18b90c 3945(define_insn "*store_minmaxsi"
9c08d1fa 3946 [(set (match_operand:SI 0 "memory_operand" "=m")
3947 (match_operator:SI 3 "minmax_operator"
3948 [(match_operand:SI 1 "s_register_operand" "r")
3949 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3950 (clobber (reg:CC CC_REGNUM))]
f15d4d96 3951 "TARGET_32BIT && optimize_insn_for_size_p()"
9c08d1fa 3952 "*
dc55b8a9 3953 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3954 operands[1], operands[2]);
e2348bcb 3955 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3956 if (TARGET_THUMB2)
3957 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3958 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3959 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3960 return \"\";
0d66636f 3961 "
3962 [(set_attr "conds" "clob")
25f905c2 3963 (set (attr "length")
3964 (if_then_else (eq_attr "is_thumb" "yes")
3965 (const_int 14)
3966 (const_int 12)))
0d66636f 3967 (set_attr "type" "store1")]
3968)
9c08d1fa 3969
8a18b90c 3970; Reject the frame pointer in operand[1], since reloading this after
3971; it has been eliminated can cause carnage.
f7fbdd4a 3972(define_insn "*minmax_arithsi"
9c08d1fa 3973 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3974 (match_operator:SI 4 "shiftable_operator"
3975 [(match_operator:SI 5 "minmax_operator"
3976 [(match_operand:SI 2 "s_register_operand" "r,r")
3977 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3978 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3979 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3980 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3981 "*
0d66636f 3982 {
3983 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3984 bool need_else;
3985
3986 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3987 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3988 need_else = true;
3989 else
3990 need_else = false;
0d66636f 3991
dc55b8a9 3992 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3993 operands[2], operands[3]);
0d66636f 3994 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3995 if (TARGET_THUMB2)
3996 {
3997 if (need_else)
3998 output_asm_insn (\"ite\\t%d5\", operands);
3999 else
4000 output_asm_insn (\"it\\t%d5\", operands);
4001 }
0d66636f 4002 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 4003 if (need_else)
0d66636f 4004 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
4005 return \"\";
215b30b3 4006 }"
0d66636f 4007 [(set_attr "conds" "clob")
25f905c2 4008 (set (attr "length")
4009 (if_then_else (eq_attr "is_thumb" "yes")
4010 (const_int 14)
4011 (const_int 12)))]
0d66636f 4012)
9c08d1fa 4013
4164bca1 4014; Reject the frame pointer in operand[1], since reloading this after
4015; it has been eliminated can cause carnage.
4016(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 4017 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 4018 (minus:SI
7c36fe71 4019 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 4020 (match_operator:SI 4 "minmax_operator"
7c36fe71 4021 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
4022 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 4023 (clobber (reg:CC CC_REGNUM))]
7c36fe71 4024 "TARGET_32BIT && !arm_eliminable_register (operands[1])
4025 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 4026 "#"
4027 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
4028 [(set (reg:CC CC_REGNUM)
4029 (compare:CC (match_dup 2) (match_dup 3)))
4030
4031 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
4032 (set (match_dup 0)
4033 (minus:SI (match_dup 1)
4034 (match_dup 2))))
4035 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
4036 (set (match_dup 0)
4037 (minus:SI (match_dup 1)
4038 (match_dup 3))))]
4039 {
4040 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4041 operands[2], operands[3]);
4042 enum rtx_code rc = minmax_code (operands[4]);
4043 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
4044 operands[2], operands[3]);
4045
4046 if (mode == CCFPmode || mode == CCFPEmode)
4047 rc = reverse_condition_maybe_unordered (rc);
4048 else
4049 rc = reverse_condition (rc);
4050 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
4051 }
4052 [(set_attr "conds" "clob")
4053 (set (attr "length")
4054 (if_then_else (eq_attr "is_thumb" "yes")
4055 (const_int 14)
4056 (const_int 12)))]
4057)
4058
b49e3742 4059(define_code_iterator SAT [smin smax])
4060(define_code_iterator SATrev [smin smax])
4061(define_code_attr SATlo [(smin "1") (smax "2")])
4062(define_code_attr SAThi [(smin "2") (smax "1")])
4063
4064(define_insn "*satsi_<SAT:code>"
4065 [(set (match_operand:SI 0 "s_register_operand" "=r")
4066 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
4067 (match_operand:SI 1 "const_int_operand" "i"))
4068 (match_operand:SI 2 "const_int_operand" "i")))]
4069 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
4070 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
4071{
4072 int mask;
4073 bool signed_sat;
4074 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
4075 &mask, &signed_sat))
4076 gcc_unreachable ();
4077
4078 operands[1] = GEN_INT (mask);
4079 if (signed_sat)
4080 return "ssat%?\t%0, %1, %3";
4081 else
4082 return "usat%?\t%0, %1, %3";
4083}
7c36fe71 4084 [(set_attr "predicable" "yes")
4085 (set_attr "predicable_short_it" "no")]
bebe9bbb 4086)
b49e3742 4087
4088(define_insn "*satsi_<SAT:code>_shift"
4089 [(set (match_operand:SI 0 "s_register_operand" "=r")
4090 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
4091 [(match_operand:SI 4 "s_register_operand" "r")
4092 (match_operand:SI 5 "const_int_operand" "i")])
4093 (match_operand:SI 1 "const_int_operand" "i"))
4094 (match_operand:SI 2 "const_int_operand" "i")))]
4095 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
4096 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
4097{
4098 int mask;
4099 bool signed_sat;
4100 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
4101 &mask, &signed_sat))
4102 gcc_unreachable ();
4103
4104 operands[1] = GEN_INT (mask);
4105 if (signed_sat)
4106 return "ssat%?\t%0, %1, %4%S3";
4107 else
4108 return "usat%?\t%0, %1, %4%S3";
4109}
4110 [(set_attr "predicable" "yes")
7c36fe71 4111 (set_attr "predicable_short_it" "no")
b49e3742 4112 (set_attr "shift" "3")
6b6abc9c 4113 (set_attr "type" "arlo_shift")])
b11cae9e 4114\f
4115;; Shift and rotation insns
4116
a2cd141b 4117(define_expand "ashldi3"
4118 [(set (match_operand:DI 0 "s_register_operand" "")
4119 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 4120 (match_operand:SI 2 "general_operand" "")))]
25f905c2 4121 "TARGET_32BIT"
a2cd141b 4122 "
aa06c51c 4123 if (TARGET_NEON)
4124 {
4125 /* Delay the decision whether to use NEON or core-regs until
4126 register allocation. */
4127 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
4128 DONE;
4129 }
4130 else
4131 {
4132 /* Only the NEON case can handle in-memory shift counts. */
4133 if (!reg_or_int_operand (operands[2], SImode))
4134 operands[2] = force_reg (SImode, operands[2]);
4135 }
4136
b805622c 4137 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4138 ; /* No special preparation statements; expand pattern as above. */
4139 else
a2cd141b 4140 {
ffcc986d 4141 rtx scratch1, scratch2;
4142
4143 if (CONST_INT_P (operands[2])
4144 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 4145 {
4146 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
4147 DONE;
4148 }
ffcc986d 4149
4150 /* Ideally we should use iwmmxt here if we could know that operands[1]
4151 ends up already living in an iwmmxt register. Otherwise it's
4152 cheaper to have the alternate code being generated than moving
4153 values to iwmmxt regs and back. */
4154
4155 /* If we're optimizing for size, we prefer the libgcc calls. */
4156 if (optimize_function_for_size_p (cfun))
4157 FAIL;
4158
4159 /* Expand operation using core-registers.
4160 'FAIL' would achieve the same thing, but this is a bit smarter. */
4161 scratch1 = gen_reg_rtx (SImode);
4162 scratch2 = gen_reg_rtx (SImode);
4163 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
4164 operands[2], scratch1, scratch2);
4165 DONE;
a2cd141b 4166 }
a2cd141b 4167 "
4168)
4169
a5b9aa37 4170(define_insn_and_split "arm_ashldi3_1bit"
50ad1bf9 4171 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4172 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4173 (const_int 1)))
4174 (clobber (reg:CC CC_REGNUM))]
25f905c2 4175 "TARGET_32BIT"
a5b9aa37 4176 "#" ; "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
4177 "&& reload_completed"
4178 [(parallel [(set (reg:CC CC_REGNUM)
4179 (compare:CC (ashift:SI (match_dup 1) (const_int 1))
4180 (const_int 0)))
4181 (set (match_dup 0) (ashift:SI (match_dup 1) (const_int 1)))])
4182 (set (match_dup 2) (plus:SI (plus:SI (match_dup 3) (match_dup 3))
4183 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4184 {
4185 operands[2] = gen_highpart (SImode, operands[0]);
4186 operands[0] = gen_lowpart (SImode, operands[0]);
4187 operands[3] = gen_highpart (SImode, operands[1]);
4188 operands[1] = gen_lowpart (SImode, operands[1]);
4189 }
a2cd141b 4190 [(set_attr "conds" "clob")
4191 (set_attr "length" "8")]
4192)
4193
87b22bf7 4194(define_expand "ashlsi3"
cffb2a26 4195 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4196 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
4197 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4198 "TARGET_EITHER"
87b22bf7 4199 "
0438d37f 4200 if (CONST_INT_P (operands[2])
87b22bf7 4201 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
4202 {
4203 emit_insn (gen_movsi (operands[0], const0_rtx));
4204 DONE;
4205 }
cffb2a26 4206 "
4207)
4208
25f905c2 4209(define_insn "*thumb1_ashlsi3"
cffb2a26 4210 [(set (match_operand:SI 0 "register_operand" "=l,l")
4211 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
4212 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 4213 "TARGET_THUMB1"
cffb2a26 4214 "lsl\\t%0, %1, %2"
747b7458 4215 [(set_attr "length" "2")
6b6abc9c 4216 (set_attr "type" "shift,shift_reg")
747b7458 4217 (set_attr "conds" "set")])
b11cae9e 4218
a2cd141b 4219(define_expand "ashrdi3"
4220 [(set (match_operand:DI 0 "s_register_operand" "")
4221 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4222 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4223 "TARGET_32BIT"
a2cd141b 4224 "
aa06c51c 4225 if (TARGET_NEON)
4226 {
4227 /* Delay the decision whether to use NEON or core-regs until
4228 register allocation. */
4229 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
4230 DONE;
4231 }
4232
b805622c 4233 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4234 ; /* No special preparation statements; expand pattern as above. */
4235 else
a2cd141b 4236 {
ffcc986d 4237 rtx scratch1, scratch2;
4238
4239 if (CONST_INT_P (operands[2])
4240 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 4241 {
4242 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
4243 DONE;
4244 }
ffcc986d 4245
4246 /* Ideally we should use iwmmxt here if we could know that operands[1]
4247 ends up already living in an iwmmxt register. Otherwise it's
4248 cheaper to have the alternate code being generated than moving
4249 values to iwmmxt regs and back. */
4250
4251 /* If we're optimizing for size, we prefer the libgcc calls. */
4252 if (optimize_function_for_size_p (cfun))
4253 FAIL;
4254
4255 /* Expand operation using core-registers.
4256 'FAIL' would achieve the same thing, but this is a bit smarter. */
4257 scratch1 = gen_reg_rtx (SImode);
4258 scratch2 = gen_reg_rtx (SImode);
4259 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
4260 operands[2], scratch1, scratch2);
4261 DONE;
a2cd141b 4262 }
a2cd141b 4263 "
4264)
4265
a5b9aa37 4266(define_insn_and_split "arm_ashrdi3_1bit"
50ad1bf9 4267 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4268 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4269 (const_int 1)))
4270 (clobber (reg:CC CC_REGNUM))]
25f905c2 4271 "TARGET_32BIT"
a5b9aa37 4272 "#" ; "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
4273 "&& reload_completed"
4274 [(parallel [(set (reg:CC CC_REGNUM)
4275 (compare:CC (ashiftrt:SI (match_dup 3) (const_int 1))
4276 (const_int 0)))
4277 (set (match_dup 2) (ashiftrt:SI (match_dup 3) (const_int 1)))])
4278 (set (match_dup 0) (unspec:SI [(match_dup 1)
4279 (reg:CC_C CC_REGNUM)]
4280 UNSPEC_RRX))]
4281 {
4282 operands[2] = gen_highpart (SImode, operands[0]);
4283 operands[0] = gen_lowpart (SImode, operands[0]);
4284 operands[3] = gen_highpart (SImode, operands[1]);
4285 operands[1] = gen_lowpart (SImode, operands[1]);
4286 }
a2cd141b 4287 [(set_attr "conds" "clob")
4288 (set_attr "length" "8")]
4289)
4290
a5b9aa37 4291(define_insn "*rrx"
4292 [(set (match_operand:SI 0 "s_register_operand" "=r")
4293 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
4294 (reg:CC_C CC_REGNUM)]
4295 UNSPEC_RRX))]
4296 "TARGET_32BIT"
4297 "mov\\t%0, %1, rrx"
4298 [(set_attr "conds" "use")
1aed5204 4299 (set_attr "type" "mov_shift")]
a5b9aa37 4300)
4301
87b22bf7 4302(define_expand "ashrsi3"
cffb2a26 4303 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4304 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4305 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4306 "TARGET_EITHER"
87b22bf7 4307 "
0438d37f 4308 if (CONST_INT_P (operands[2])
87b22bf7 4309 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
4310 operands[2] = GEN_INT (31);
cffb2a26 4311 "
4312)
4313
25f905c2 4314(define_insn "*thumb1_ashrsi3"
cffb2a26 4315 [(set (match_operand:SI 0 "register_operand" "=l,l")
4316 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
4317 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 4318 "TARGET_THUMB1"
cffb2a26 4319 "asr\\t%0, %1, %2"
747b7458 4320 [(set_attr "length" "2")
6b6abc9c 4321 (set_attr "type" "shift,shift_reg")
747b7458 4322 (set_attr "conds" "set")])
b11cae9e 4323
a2cd141b 4324(define_expand "lshrdi3"
4325 [(set (match_operand:DI 0 "s_register_operand" "")
4326 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4327 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4328 "TARGET_32BIT"
a2cd141b 4329 "
aa06c51c 4330 if (TARGET_NEON)
4331 {
4332 /* Delay the decision whether to use NEON or core-regs until
4333 register allocation. */
4334 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4335 DONE;
4336 }
4337
b805622c 4338 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4339 ; /* No special preparation statements; expand pattern as above. */
4340 else
a2cd141b 4341 {
ffcc986d 4342 rtx scratch1, scratch2;
4343
4344 if (CONST_INT_P (operands[2])
4345 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 4346 {
4347 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
4348 DONE;
4349 }
ffcc986d 4350
4351 /* Ideally we should use iwmmxt here if we could know that operands[1]
4352 ends up already living in an iwmmxt register. Otherwise it's
4353 cheaper to have the alternate code being generated than moving
4354 values to iwmmxt regs and back. */
4355
4356 /* If we're optimizing for size, we prefer the libgcc calls. */
4357 if (optimize_function_for_size_p (cfun))
4358 FAIL;
4359
4360 /* Expand operation using core-registers.
4361 'FAIL' would achieve the same thing, but this is a bit smarter. */
4362 scratch1 = gen_reg_rtx (SImode);
4363 scratch2 = gen_reg_rtx (SImode);
4364 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4365 operands[2], scratch1, scratch2);
4366 DONE;
a2cd141b 4367 }
a2cd141b 4368 "
4369)
4370
a5b9aa37 4371(define_insn_and_split "arm_lshrdi3_1bit"
50ad1bf9 4372 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4373 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4374 (const_int 1)))
4375 (clobber (reg:CC CC_REGNUM))]
25f905c2 4376 "TARGET_32BIT"
a5b9aa37 4377 "#" ; "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
4378 "&& reload_completed"
4379 [(parallel [(set (reg:CC CC_REGNUM)
4380 (compare:CC (lshiftrt:SI (match_dup 3) (const_int 1))
4381 (const_int 0)))
4382 (set (match_dup 2) (lshiftrt:SI (match_dup 3) (const_int 1)))])
4383 (set (match_dup 0) (unspec:SI [(match_dup 1)
4384 (reg:CC_C CC_REGNUM)]
4385 UNSPEC_RRX))]
4386 {
4387 operands[2] = gen_highpart (SImode, operands[0]);
4388 operands[0] = gen_lowpart (SImode, operands[0]);
4389 operands[3] = gen_highpart (SImode, operands[1]);
4390 operands[1] = gen_lowpart (SImode, operands[1]);
4391 }
a2cd141b 4392 [(set_attr "conds" "clob")
4393 (set_attr "length" "8")]
4394)
4395
87b22bf7 4396(define_expand "lshrsi3"
cffb2a26 4397 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4398 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4399 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4400 "TARGET_EITHER"
87b22bf7 4401 "
0438d37f 4402 if (CONST_INT_P (operands[2])
87b22bf7 4403 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
4404 {
4405 emit_insn (gen_movsi (operands[0], const0_rtx));
4406 DONE;
4407 }
cffb2a26 4408 "
4409)
4410
25f905c2 4411(define_insn "*thumb1_lshrsi3"
cffb2a26 4412 [(set (match_operand:SI 0 "register_operand" "=l,l")
4413 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
4414 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 4415 "TARGET_THUMB1"
cffb2a26 4416 "lsr\\t%0, %1, %2"
747b7458 4417 [(set_attr "length" "2")
6b6abc9c 4418 (set_attr "type" "shift,shift_reg")
747b7458 4419 (set_attr "conds" "set")])
b11cae9e 4420
87b22bf7 4421(define_expand "rotlsi3"
cffb2a26 4422 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4423 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4424 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4425 "TARGET_32BIT"
87b22bf7 4426 "
0438d37f 4427 if (CONST_INT_P (operands[2]))
87b22bf7 4428 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4429 else
b11cae9e 4430 {
87b22bf7 4431 rtx reg = gen_reg_rtx (SImode);
4432 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4433 operands[2] = reg;
b11cae9e 4434 }
cffb2a26 4435 "
4436)
9c08d1fa 4437
87b22bf7 4438(define_expand "rotrsi3"
cffb2a26 4439 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4440 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4441 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4442 "TARGET_EITHER"
87b22bf7 4443 "
25f905c2 4444 if (TARGET_32BIT)
cffb2a26 4445 {
0438d37f 4446 if (CONST_INT_P (operands[2])
cffb2a26 4447 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
4448 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4449 }
25f905c2 4450 else /* TARGET_THUMB1 */
cffb2a26 4451 {
0438d37f 4452 if (CONST_INT_P (operands [2]))
cffb2a26 4453 operands [2] = force_reg (SImode, operands[2]);
4454 }
4455 "
4456)
87b22bf7 4457
25f905c2 4458(define_insn "*thumb1_rotrsi3"
cffb2a26 4459 [(set (match_operand:SI 0 "register_operand" "=l")
4460 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
4461 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 4462 "TARGET_THUMB1"
cffb2a26 4463 "ror\\t%0, %0, %2"
6b6abc9c 4464 [(set_attr "type" "shift_reg")
4465 (set_attr "length" "2")]
cffb2a26 4466)
4467
4468(define_insn "*arm_shiftsi3"
7c36fe71 4469 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
cffb2a26 4470 (match_operator:SI 3 "shift_operator"
7c36fe71 4471 [(match_operand:SI 1 "s_register_operand" "0,r,r")
4472 (match_operand:SI 2 "reg_or_int_operand" "l,M,r")]))]
25f905c2 4473 "TARGET_32BIT"
4474 "* return arm_output_shift(operands, 0);"
344495ea 4475 [(set_attr "predicable" "yes")
7c36fe71 4476 (set_attr "arch" "t2,*,*")
4477 (set_attr "predicable_short_it" "yes,no,no")
4478 (set_attr "length" "4")
331beb1a 4479 (set_attr "shift" "1")
7c36fe71 4480 (set_attr "type" "arlo_shift_reg,arlo_shift,arlo_shift_reg")]
6c4c2133 4481)
87b22bf7 4482
a5b9aa37 4483(define_insn "*shiftsi3_compare"
4484 [(set (reg:CC CC_REGNUM)
4485 (compare:CC (match_operator:SI 3 "shift_operator"
6b6abc9c 4486 [(match_operand:SI 1 "s_register_operand" "r,r")
4487 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
a5b9aa37 4488 (const_int 0)))
6b6abc9c 4489 (set (match_operand:SI 0 "s_register_operand" "=r,r")
a5b9aa37 4490 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
4491 "TARGET_32BIT"
4492 "* return arm_output_shift(operands, 1);"
4493 [(set_attr "conds" "set")
4494 (set_attr "shift" "1")
6b6abc9c 4495 (set_attr "type" "arlo_shift,arlo_shift_reg")]
a5b9aa37 4496)
4497
f7fbdd4a 4498(define_insn "*shiftsi3_compare0"
bd5b4116 4499 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4500 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4501 [(match_operand:SI 1 "s_register_operand" "r,r")
4502 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4503 (const_int 0)))
6b6abc9c 4504 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4505 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 4506 "TARGET_32BIT"
4507 "* return arm_output_shift(operands, 1);"
344495ea 4508 [(set_attr "conds" "set")
331beb1a 4509 (set_attr "shift" "1")
6b6abc9c 4510 (set_attr "type" "arlo_shift,arlo_shift_reg")]
0d66636f 4511)
9c08d1fa 4512
f7fbdd4a 4513(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 4514 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4515 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4516 [(match_operand:SI 1 "s_register_operand" "r,r")
4517 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4518 (const_int 0)))
6b6abc9c 4519 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4520 "TARGET_32BIT"
4521 "* return arm_output_shift(operands, 1);"
344495ea 4522 [(set_attr "conds" "set")
6b6abc9c 4523 (set_attr "shift" "1")
4524 (set_attr "type" "shift,shift_reg")]
0d66636f 4525)
9c08d1fa 4526
d5d4dc8d 4527(define_insn "*not_shiftsi"
4528 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4529 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4530 [(match_operand:SI 1 "s_register_operand" "r,r")
4531 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4532 "TARGET_32BIT"
6c4c2133 4533 "mvn%?\\t%0, %1%S3"
344495ea 4534 [(set_attr "predicable" "yes")
d952d547 4535 (set_attr "predicable_short_it" "no")
331beb1a 4536 (set_attr "shift" "1")
d5d4dc8d 4537 (set_attr "arch" "32,a")
1aed5204 4538 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4539
d5d4dc8d 4540(define_insn "*not_shiftsi_compare0"
bd5b4116 4541 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4542 (compare:CC_NOOV
4543 (not:SI (match_operator:SI 3 "shift_operator"
4544 [(match_operand:SI 1 "s_register_operand" "r,r")
4545 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4546 (const_int 0)))
4547 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4548 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4549 "TARGET_32BIT"
25f905c2 4550 "mvn%.\\t%0, %1%S3"
344495ea 4551 [(set_attr "conds" "set")
331beb1a 4552 (set_attr "shift" "1")
d5d4dc8d 4553 (set_attr "arch" "32,a")
1aed5204 4554 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4555
d5d4dc8d 4556(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4557 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4558 (compare:CC_NOOV
4559 (not:SI (match_operator:SI 3 "shift_operator"
4560 [(match_operand:SI 1 "s_register_operand" "r,r")
4561 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4562 (const_int 0)))
4563 (clobber (match_scratch:SI 0 "=r,r"))]
4564 "TARGET_32BIT"
25f905c2 4565 "mvn%.\\t%0, %1%S3"
344495ea 4566 [(set_attr "conds" "set")
331beb1a 4567 (set_attr "shift" "1")
d5d4dc8d 4568 (set_attr "arch" "32,a")
1aed5204 4569 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4570
cffb2a26 4571;; We don't really have extzv, but defining this using shifts helps
4572;; to reduce register pressure later on.
4573
4574(define_expand "extzv"
eb04cafb 4575 [(set (match_operand 0 "s_register_operand" "")
4576 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4577 (match_operand 2 "const_int_operand" "")
4578 (match_operand 3 "const_int_operand" "")))]
8b054d5a 4579 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4580 "
4581 {
4582 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4583 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4584
8b054d5a 4585 if (arm_arch_thumb2)
4586 {
eb04cafb 4587 HOST_WIDE_INT width = INTVAL (operands[2]);
4588 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4589
4590 if (unaligned_access && MEM_P (operands[1])
4591 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4592 {
4593 rtx base_addr;
4594
4595 if (BYTES_BIG_ENDIAN)
4596 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4597 - bitpos;
4598
4599 if (width == 32)
4600 {
4601 base_addr = adjust_address (operands[1], SImode,
4602 bitpos / BITS_PER_UNIT);
4603 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4604 }
4605 else
4606 {
4607 rtx dest = operands[0];
4608 rtx tmp = gen_reg_rtx (SImode);
4609
4610 /* We may get a paradoxical subreg here. Strip it off. */
4611 if (GET_CODE (dest) == SUBREG
4612 && GET_MODE (dest) == SImode
4613 && GET_MODE (SUBREG_REG (dest)) == HImode)
4614 dest = SUBREG_REG (dest);
4615
4616 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4617 FAIL;
4618
4619 base_addr = adjust_address (operands[1], HImode,
4620 bitpos / BITS_PER_UNIT);
4621 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4622 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4623 }
4624 DONE;
4625 }
4626 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4627 {
4628 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4629 operands[3]));
4630 DONE;
4631 }
4632 else
4633 FAIL;
8b054d5a 4634 }
eb04cafb 4635
4636 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4637 FAIL;
8b054d5a 4638
cffb2a26 4639 operands[3] = GEN_INT (rshift);
4640
4641 if (lshift == 0)
4642 {
4643 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4644 DONE;
4645 }
4646
eb04cafb 4647 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4648 operands[3], gen_reg_rtx (SImode)));
4649 DONE;
215b30b3 4650 }"
cffb2a26 4651)
4652
eb04cafb 4653;; Helper for extzv, for the Thumb-1 register-shifts case.
4654
4655(define_expand "extzv_t1"
4656 [(set (match_operand:SI 4 "s_register_operand" "")
4657 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4658 (match_operand:SI 2 "const_int_operand" "")))
4659 (set (match_operand:SI 0 "s_register_operand" "")
4660 (lshiftrt:SI (match_dup 4)
4661 (match_operand:SI 3 "const_int_operand" "")))]
4662 "TARGET_THUMB1"
4663 "")
4664
4665(define_expand "extv"
4666 [(set (match_operand 0 "s_register_operand" "")
4667 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4668 (match_operand 2 "const_int_operand" "")
4669 (match_operand 3 "const_int_operand" "")))]
4670 "arm_arch_thumb2"
4671{
4672 HOST_WIDE_INT width = INTVAL (operands[2]);
4673 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4674
4675 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4676 && (bitpos % BITS_PER_UNIT) == 0)
4677 {
4678 rtx base_addr;
4679
4680 if (BYTES_BIG_ENDIAN)
4681 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4682
4683 if (width == 32)
4684 {
4685 base_addr = adjust_address (operands[1], SImode,
4686 bitpos / BITS_PER_UNIT);
4687 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4688 }
4689 else
4690 {
4691 rtx dest = operands[0];
4692 rtx tmp = gen_reg_rtx (SImode);
4693
4694 /* We may get a paradoxical subreg here. Strip it off. */
4695 if (GET_CODE (dest) == SUBREG
4696 && GET_MODE (dest) == SImode
4697 && GET_MODE (SUBREG_REG (dest)) == HImode)
4698 dest = SUBREG_REG (dest);
4699
4700 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4701 FAIL;
4702
4703 base_addr = adjust_address (operands[1], HImode,
4704 bitpos / BITS_PER_UNIT);
4705 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4706 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4707 }
4708
4709 DONE;
4710 }
4711 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4712 FAIL;
4713 else if (GET_MODE (operands[0]) == SImode
4714 && GET_MODE (operands[1]) == SImode)
4715 {
4716 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4717 operands[3]));
4718 DONE;
4719 }
4720
4721 FAIL;
4722})
4723
4724; Helper to expand register forms of extv with the proper modes.
4725
4726(define_expand "extv_regsi"
4727 [(set (match_operand:SI 0 "s_register_operand" "")
4728 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4729 (match_operand 2 "const_int_operand" "")
4730 (match_operand 3 "const_int_operand" "")))]
4731 ""
4732{
4733})
4734
4735; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4736
4737(define_insn "unaligned_loadsi"
4738 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4739 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4740 UNSPEC_UNALIGNED_LOAD))]
4741 "unaligned_access && TARGET_32BIT"
4742 "ldr%?\t%0, %1\t@ unaligned"
4743 [(set_attr "arch" "t2,any")
4744 (set_attr "length" "2,4")
4745 (set_attr "predicable" "yes")
d952d547 4746 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4747 (set_attr "type" "load1")])
4748
4749(define_insn "unaligned_loadhis"
4750 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4751 (sign_extend:SI
4752 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4753 UNSPEC_UNALIGNED_LOAD)))]
4754 "unaligned_access && TARGET_32BIT"
4755 "ldr%(sh%)\t%0, %1\t@ unaligned"
4756 [(set_attr "arch" "t2,any")
4757 (set_attr "length" "2,4")
4758 (set_attr "predicable" "yes")
d952d547 4759 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4760 (set_attr "type" "load_byte")])
4761
4762(define_insn "unaligned_loadhiu"
4763 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4764 (zero_extend:SI
4765 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4766 UNSPEC_UNALIGNED_LOAD)))]
4767 "unaligned_access && TARGET_32BIT"
4768 "ldr%(h%)\t%0, %1\t@ unaligned"
4769 [(set_attr "arch" "t2,any")
4770 (set_attr "length" "2,4")
4771 (set_attr "predicable" "yes")
d952d547 4772 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4773 (set_attr "type" "load_byte")])
4774
4775(define_insn "unaligned_storesi"
4776 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4777 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4778 UNSPEC_UNALIGNED_STORE))]
4779 "unaligned_access && TARGET_32BIT"
4780 "str%?\t%1, %0\t@ unaligned"
4781 [(set_attr "arch" "t2,any")
4782 (set_attr "length" "2,4")
4783 (set_attr "predicable" "yes")
d952d547 4784 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4785 (set_attr "type" "store1")])
4786
4787(define_insn "unaligned_storehi"
4788 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4789 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4790 UNSPEC_UNALIGNED_STORE))]
4791 "unaligned_access && TARGET_32BIT"
4792 "str%(h%)\t%1, %0\t@ unaligned"
4793 [(set_attr "arch" "t2,any")
4794 (set_attr "length" "2,4")
4795 (set_attr "predicable" "yes")
d952d547 4796 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4797 (set_attr "type" "store1")])
4798
ae51a965 4799;; Unaligned double-word load and store.
4800;; Split after reload into two unaligned single-word accesses.
4801;; It prevents lower_subreg from splitting some other aligned
4802;; double-word accesses too early. Used for internal memcpy.
4803
4804(define_insn_and_split "unaligned_loaddi"
4805 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4806 (unspec:DI [(match_operand:DI 1 "memory_operand" "o,o")]
4807 UNSPEC_UNALIGNED_LOAD))]
4808 "unaligned_access && TARGET_32BIT"
4809 "#"
4810 "&& reload_completed"
4811 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_LOAD))
4812 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_LOAD))]
4813 {
4814 operands[2] = gen_highpart (SImode, operands[0]);
4815 operands[0] = gen_lowpart (SImode, operands[0]);
4816 operands[3] = gen_highpart (SImode, operands[1]);
4817 operands[1] = gen_lowpart (SImode, operands[1]);
4818
4819 /* If the first destination register overlaps with the base address,
4820 swap the order in which the loads are emitted. */
4821 if (reg_overlap_mentioned_p (operands[0], operands[1]))
4822 {
4823 rtx tmp = operands[1];
4824 operands[1] = operands[3];
4825 operands[3] = tmp;
4826 tmp = operands[0];
4827 operands[0] = operands[2];
4828 operands[2] = tmp;
4829 }
4830 }
4831 [(set_attr "arch" "t2,any")
4832 (set_attr "length" "4,8")
4833 (set_attr "predicable" "yes")
4834 (set_attr "type" "load2")])
4835
4836(define_insn_and_split "unaligned_storedi"
4837 [(set (match_operand:DI 0 "memory_operand" "=o,o")
4838 (unspec:DI [(match_operand:DI 1 "s_register_operand" "l,r")]
4839 UNSPEC_UNALIGNED_STORE))]
4840 "unaligned_access && TARGET_32BIT"
4841 "#"
4842 "&& reload_completed"
4843 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_STORE))
4844 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_STORE))]
4845 {
4846 operands[2] = gen_highpart (SImode, operands[0]);
4847 operands[0] = gen_lowpart (SImode, operands[0]);
4848 operands[3] = gen_highpart (SImode, operands[1]);
4849 operands[1] = gen_lowpart (SImode, operands[1]);
4850 }
4851 [(set_attr "arch" "t2,any")
4852 (set_attr "length" "4,8")
4853 (set_attr "predicable" "yes")
4854 (set_attr "type" "store2")])
4855
4856
eb04cafb 4857(define_insn "*extv_reg"
8b054d5a 4858 [(set (match_operand:SI 0 "s_register_operand" "=r")
4859 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4860 (match_operand:SI 2 "const_int_operand" "M")
4861 (match_operand:SI 3 "const_int_operand" "M")))]
4862 "arm_arch_thumb2"
4863 "sbfx%?\t%0, %1, %3, %2"
4864 [(set_attr "length" "4")
d952d547 4865 (set_attr "predicable" "yes")
4866 (set_attr "predicable_short_it" "no")]
8b054d5a 4867)
4868
4869(define_insn "extzv_t2"
4870 [(set (match_operand:SI 0 "s_register_operand" "=r")
4871 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4872 (match_operand:SI 2 "const_int_operand" "M")
4873 (match_operand:SI 3 "const_int_operand" "M")))]
4874 "arm_arch_thumb2"
4875 "ubfx%?\t%0, %1, %3, %2"
4876 [(set_attr "length" "4")
d952d547 4877 (set_attr "predicable" "yes")
4878 (set_attr "predicable_short_it" "no")]
8b054d5a 4879)
4880
7d3cda8c 4881
4882;; Division instructions
4883(define_insn "divsi3"
4884 [(set (match_operand:SI 0 "s_register_operand" "=r")
4885 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4886 (match_operand:SI 2 "s_register_operand" "r")))]
4887 "TARGET_IDIV"
4888 "sdiv%?\t%0, %1, %2"
4889 [(set_attr "predicable" "yes")
d952d547 4890 (set_attr "predicable_short_it" "no")
9da0ec36 4891 (set_attr "type" "sdiv")]
7d3cda8c 4892)
4893
4894(define_insn "udivsi3"
4895 [(set (match_operand:SI 0 "s_register_operand" "=r")
4896 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4897 (match_operand:SI 2 "s_register_operand" "r")))]
4898 "TARGET_IDIV"
4899 "udiv%?\t%0, %1, %2"
4900 [(set_attr "predicable" "yes")
d952d547 4901 (set_attr "predicable_short_it" "no")
9da0ec36 4902 (set_attr "type" "udiv")]
7d3cda8c 4903)
4904
b11cae9e 4905\f
4906;; Unary arithmetic insns
4907
cffb2a26 4908(define_expand "negdi2"
4909 [(parallel
8135a42b 4910 [(set (match_operand:DI 0 "s_register_operand" "")
4911 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4912 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4913 "TARGET_EITHER"
774d2fbb 4914 {
4915 if (TARGET_NEON)
4916 {
4917 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4918 DONE;
4919 }
4920 }
cffb2a26 4921)
4922
4923;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4924;; The first alternative allows the common case of a *full* overlap.
ba6a3b2f 4925(define_insn_and_split "*arm_negdi2"
458a8706 4926 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4927 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4928 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4929 "TARGET_ARM"
ba6a3b2f 4930 "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4931 "&& reload_completed"
4932 [(parallel [(set (reg:CC CC_REGNUM)
4933 (compare:CC (const_int 0) (match_dup 1)))
4934 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4935 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4936 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4937 {
4938 operands[2] = gen_highpart (SImode, operands[0]);
4939 operands[0] = gen_lowpart (SImode, operands[0]);
4940 operands[3] = gen_highpart (SImode, operands[1]);
4941 operands[1] = gen_lowpart (SImode, operands[1]);
4942 }
cffb2a26 4943 [(set_attr "conds" "clob")
4944 (set_attr "length" "8")]
4945)
b11cae9e 4946
25f905c2 4947(define_insn "*thumb1_negdi2"
8135a42b 4948 [(set (match_operand:DI 0 "register_operand" "=&l")
4949 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 4950 (clobber (reg:CC CC_REGNUM))]
25f905c2 4951 "TARGET_THUMB1"
cffb2a26 4952 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
4953 [(set_attr "length" "6")]
4954)
4955
4956(define_expand "negsi2"
4957 [(set (match_operand:SI 0 "s_register_operand" "")
4958 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4959 "TARGET_EITHER"
b11cae9e 4960 ""
cffb2a26 4961)
4962
4963(define_insn "*arm_negsi2"
d952d547 4964 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4965 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4966 "TARGET_32BIT"
cffb2a26 4967 "rsb%?\\t%0, %1, #0"
d952d547 4968 [(set_attr "predicable" "yes")
4969 (set_attr "predicable_short_it" "yes,no")
4970 (set_attr "arch" "t2,*")
4971 (set_attr "length" "4")]
cffb2a26 4972)
4973
25f905c2 4974(define_insn "*thumb1_negsi2"
cffb2a26 4975 [(set (match_operand:SI 0 "register_operand" "=l")
4976 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4977 "TARGET_THUMB1"
cffb2a26 4978 "neg\\t%0, %1"
4979 [(set_attr "length" "2")]
4980)
b11cae9e 4981
604f3a0a 4982(define_expand "negsf2"
4983 [(set (match_operand:SF 0 "s_register_operand" "")
4984 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4985 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4986 ""
4987)
4988
4989(define_expand "negdf2"
4990 [(set (match_operand:DF 0 "s_register_operand" "")
4991 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4992 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4993 "")
4994
83e2b922 4995;; Negate an extended 32-bit value.
4996(define_insn_and_split "*negdi_extendsidi"
4997 [(set (match_operand:DI 0 "s_register_operand" "=r,&r,l,&l")
4998 (neg:DI (sign_extend:DI (match_operand:SI 1 "s_register_operand" "0,r,0,l"))))
4999 (clobber (reg:CC CC_REGNUM))]
5000 "TARGET_32BIT"
5001 "#" ; rsb\\t%Q0, %1, #0\;asr\\t%R0, %Q0, #31
5002 "&& reload_completed"
5003 [(const_int 0)]
5004 {
5005 operands[2] = gen_highpart (SImode, operands[0]);
5006 operands[0] = gen_lowpart (SImode, operands[0]);
5007 rtx tmp = gen_rtx_SET (VOIDmode,
5008 operands[0],
5009 gen_rtx_MINUS (SImode,
5010 const0_rtx,
5011 operands[1]));
5012 if (TARGET_ARM)
5013 {
5014 emit_insn (tmp);
5015 }
5016 else
5017 {
5018 /* Set the flags, to emit the short encoding in Thumb2. */
5019 rtx flags = gen_rtx_SET (VOIDmode,
5020 gen_rtx_REG (CCmode, CC_REGNUM),
5021 gen_rtx_COMPARE (CCmode,
5022 const0_rtx,
5023 operands[1]));
5024 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5025 gen_rtvec (2,
5026 flags,
5027 tmp)));
5028 }
5029 emit_insn (gen_rtx_SET (VOIDmode,
5030 operands[2],
5031 gen_rtx_ASHIFTRT (SImode,
5032 operands[0],
5033 GEN_INT (31))));
5034 DONE;
5035 }
5036 [(set_attr "length" "8,8,4,4")
5037 (set_attr "arch" "a,a,t2,t2")]
5038)
5039
5040(define_insn_and_split "*negdi_zero_extendsidi"
5041 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
5042 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
5043 (clobber (reg:CC CC_REGNUM))]
5044 "TARGET_32BIT"
5045 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
5046 ;; Don't care what register is input to sbc,
5047 ;; since we just just need to propagate the carry.
5048 "&& reload_completed"
5049 [(parallel [(set (reg:CC CC_REGNUM)
5050 (compare:CC (const_int 0) (match_dup 1)))
5051 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
5052 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
5053 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
5054 {
5055 operands[2] = gen_highpart (SImode, operands[0]);
5056 operands[0] = gen_lowpart (SImode, operands[0]);
5057 }
5058 [(set_attr "conds" "clob")
5059 (set_attr "length" "8")] ;; length in thumb is 4
5060)
5061
9c08d1fa 5062;; abssi2 doesn't really clobber the condition codes if a different register
5063;; is being set. To keep things simple, assume during rtl manipulations that
5064;; it does, but tell the final scan operator the truth. Similarly for
5065;; (neg (abs...))
5066
604f3a0a 5067(define_expand "abssi2"
5068 [(parallel
5069 [(set (match_operand:SI 0 "s_register_operand" "")
5070 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 5071 (clobber (match_dup 2))])]
5072 "TARGET_EITHER"
5073 "
25f905c2 5074 if (TARGET_THUMB1)
ba156559 5075 operands[2] = gen_rtx_SCRATCH (SImode);
5076 else
5077 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
5078")
604f3a0a 5079
ba6a3b2f 5080(define_insn_and_split "*arm_abssi2"
ba156559 5081 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 5082 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 5083 (clobber (reg:CC CC_REGNUM))]
cffb2a26 5084 "TARGET_ARM"
ba6a3b2f 5085 "#"
5086 "&& reload_completed"
5087 [(const_int 0)]
5088 {
5089 /* if (which_alternative == 0) */
5090 if (REGNO(operands[0]) == REGNO(operands[1]))
5091 {
5092 /* Emit the pattern:
5093 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
5094 [(set (reg:CC CC_REGNUM)
5095 (compare:CC (match_dup 0) (const_int 0)))
5096 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
5097 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
5098 */
5099 emit_insn (gen_rtx_SET (VOIDmode,
5100 gen_rtx_REG (CCmode, CC_REGNUM),
5101 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
5102 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
5103 (gen_rtx_LT (SImode,
5104 gen_rtx_REG (CCmode, CC_REGNUM),
5105 const0_rtx)),
5106 (gen_rtx_SET (VOIDmode,
5107 operands[0],
5108 (gen_rtx_MINUS (SImode,
5109 const0_rtx,
5110 operands[1]))))));
5111 DONE;
5112 }
5113 else
5114 {
5115 /* Emit the pattern:
5116 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
5117 [(set (match_dup 0)
5118 (xor:SI (match_dup 1)
5119 (ashiftrt:SI (match_dup 1) (const_int 31))))
5120 (set (match_dup 0)
5121 (minus:SI (match_dup 0)
5122 (ashiftrt:SI (match_dup 1) (const_int 31))))]
5123 */
5124 emit_insn (gen_rtx_SET (VOIDmode,
5125 operands[0],
5126 gen_rtx_XOR (SImode,
5127 gen_rtx_ASHIFTRT (SImode,
5128 operands[1],
5129 GEN_INT (31)),
5130 operands[1])));
5131 emit_insn (gen_rtx_SET (VOIDmode,
5132 operands[0],
5133 gen_rtx_MINUS (SImode,
5134 operands[0],
5135 gen_rtx_ASHIFTRT (SImode,
5136 operands[1],
5137 GEN_INT (31)))));
5138 DONE;
5139 }
5140 }
cffb2a26 5141 [(set_attr "conds" "clob,*")
331beb1a 5142 (set_attr "shift" "1")
2ad08b65 5143 (set_attr "predicable" "no, yes")
cffb2a26 5144 (set_attr "length" "8")]
5145)
9c08d1fa 5146
25f905c2 5147(define_insn_and_split "*thumb1_abssi2"
ba156559 5148 [(set (match_operand:SI 0 "s_register_operand" "=l")
5149 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
5150 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 5151 "TARGET_THUMB1"
ba156559 5152 "#"
25f905c2 5153 "TARGET_THUMB1 && reload_completed"
ba156559 5154 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
5155 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
5156 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
5157 ""
5158 [(set_attr "length" "6")]
5159)
5160
ba6a3b2f 5161(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 5162 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
5163 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 5164 (clobber (reg:CC CC_REGNUM))]
cffb2a26 5165 "TARGET_ARM"
ba6a3b2f 5166 "#"
5167 "&& reload_completed"
5168 [(const_int 0)]
5169 {
5170 /* if (which_alternative == 0) */
5171 if (REGNO (operands[0]) == REGNO (operands[1]))
5172 {
5173 /* Emit the pattern:
5174 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
5175 */
5176 emit_insn (gen_rtx_SET (VOIDmode,
5177 gen_rtx_REG (CCmode, CC_REGNUM),
5178 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
5179 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
5180 gen_rtx_GT (SImode,
5181 gen_rtx_REG (CCmode, CC_REGNUM),
5182 const0_rtx),
5183 gen_rtx_SET (VOIDmode,
5184 operands[0],
5185 (gen_rtx_MINUS (SImode,
5186 const0_rtx,
5187 operands[1])))));
5188 }
5189 else
5190 {
5191 /* Emit the pattern:
5192 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
5193 */
5194 emit_insn (gen_rtx_SET (VOIDmode,
5195 operands[0],
5196 gen_rtx_XOR (SImode,
5197 gen_rtx_ASHIFTRT (SImode,
5198 operands[1],
5199 GEN_INT (31)),
5200 operands[1])));
5201 emit_insn (gen_rtx_SET (VOIDmode,
5202 operands[0],
5203 gen_rtx_MINUS (SImode,
5204 gen_rtx_ASHIFTRT (SImode,
5205 operands[1],
5206 GEN_INT (31)),
5207 operands[0])));
5208 }
5209 DONE;
5210 }
cffb2a26 5211 [(set_attr "conds" "clob,*")
331beb1a 5212 (set_attr "shift" "1")
2ad08b65 5213 (set_attr "predicable" "no, yes")
cffb2a26 5214 (set_attr "length" "8")]
5215)
b11cae9e 5216
25f905c2 5217(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 5218 [(set (match_operand:SI 0 "s_register_operand" "=l")
5219 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
5220 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 5221 "TARGET_THUMB1"
ba156559 5222 "#"
25f905c2 5223 "TARGET_THUMB1 && reload_completed"
ba156559 5224 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
5225 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
5226 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
5227 ""
5228 [(set_attr "length" "6")]
5229)
5230
604f3a0a 5231(define_expand "abssf2"
5232 [(set (match_operand:SF 0 "s_register_operand" "")
5233 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 5234 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5235 "")
5236
604f3a0a 5237(define_expand "absdf2"
5238 [(set (match_operand:DF 0 "s_register_operand" "")
5239 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5240 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5241 "")
5242
7db9af5d 5243(define_expand "sqrtsf2"
5244 [(set (match_operand:SF 0 "s_register_operand" "")
5245 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 5246 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 5247 "")
9c08d1fa 5248
7db9af5d 5249(define_expand "sqrtdf2"
5250 [(set (match_operand:DF 0 "s_register_operand" "")
5251 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 5252 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 5253 "")
9c08d1fa 5254
a0f94409 5255(define_insn_and_split "one_cmpldi2"
10efb95f 5256 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
5257 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 5258 "TARGET_32BIT"
10efb95f 5259 "@
5260 vmvn\t%P0, %P1
5261 #
5262 #
5263 vmvn\t%P0, %P1"
5264 "TARGET_32BIT && reload_completed
5265 && arm_general_register_operand (operands[0], DImode)"
a0f94409 5266 [(set (match_dup 0) (not:SI (match_dup 1)))
5267 (set (match_dup 2) (not:SI (match_dup 3)))]
5268 "
5269 {
5270 operands[2] = gen_highpart (SImode, operands[0]);
5271 operands[0] = gen_lowpart (SImode, operands[0]);
5272 operands[3] = gen_highpart (SImode, operands[1]);
5273 operands[1] = gen_lowpart (SImode, operands[1]);
5274 }"
10efb95f 5275 [(set_attr "length" "*,8,8,*")
5276 (set_attr "predicable" "no,yes,yes,no")
5277 (set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
b6779ddc 5278 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 5279)
b11cae9e 5280
cffb2a26 5281(define_expand "one_cmplsi2"
5282 [(set (match_operand:SI 0 "s_register_operand" "")
5283 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
5284 "TARGET_EITHER"
b11cae9e 5285 ""
cffb2a26 5286)
5287
5288(define_insn "*arm_one_cmplsi2"
d952d547 5289 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
5290 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 5291 "TARGET_32BIT"
cffb2a26 5292 "mvn%?\\t%0, %1"
d2a518d1 5293 [(set_attr "predicable" "yes")
d952d547 5294 (set_attr "predicable_short_it" "yes,no")
5295 (set_attr "arch" "t2,*")
5296 (set_attr "length" "4")
1aed5204 5297 (set_attr "type" "mvn_reg")]
cffb2a26 5298)
5299
25f905c2 5300(define_insn "*thumb1_one_cmplsi2"
cffb2a26 5301 [(set (match_operand:SI 0 "register_operand" "=l")
5302 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 5303 "TARGET_THUMB1"
cffb2a26 5304 "mvn\\t%0, %1"
d2a518d1 5305 [(set_attr "length" "2")
1aed5204 5306 (set_attr "type" "mvn_reg")]
cffb2a26 5307)
9c08d1fa 5308
f7fbdd4a 5309(define_insn "*notsi_compare0"
bd5b4116 5310 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5311 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5312 (const_int 0)))
5313 (set (match_operand:SI 0 "s_register_operand" "=r")
5314 (not:SI (match_dup 1)))]
25f905c2 5315 "TARGET_32BIT"
5316 "mvn%.\\t%0, %1"
d2a518d1 5317 [(set_attr "conds" "set")
1aed5204 5318 (set_attr "type" "mvn_reg")]
cffb2a26 5319)
9c08d1fa 5320
f7fbdd4a 5321(define_insn "*notsi_compare0_scratch"
bd5b4116 5322 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5323 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5324 (const_int 0)))
5325 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 5326 "TARGET_32BIT"
5327 "mvn%.\\t%0, %1"
d2a518d1 5328 [(set_attr "conds" "set")
1aed5204 5329 (set_attr "type" "mvn_reg")]
cffb2a26 5330)
b11cae9e 5331\f
5332;; Fixed <--> Floating conversion insns
5333
9b8516be 5334(define_expand "floatsihf2"
5335 [(set (match_operand:HF 0 "general_operand" "")
5336 (float:HF (match_operand:SI 1 "general_operand" "")))]
5337 "TARGET_EITHER"
5338 "
5339 {
5340 rtx op1 = gen_reg_rtx (SFmode);
5341 expand_float (op1, operands[1], 0);
5342 op1 = convert_to_mode (HFmode, op1, 0);
5343 emit_move_insn (operands[0], op1);
5344 DONE;
5345 }"
5346)
5347
5348(define_expand "floatdihf2"
5349 [(set (match_operand:HF 0 "general_operand" "")
5350 (float:HF (match_operand:DI 1 "general_operand" "")))]
5351 "TARGET_EITHER"
5352 "
5353 {
5354 rtx op1 = gen_reg_rtx (SFmode);
5355 expand_float (op1, operands[1], 0);
5356 op1 = convert_to_mode (HFmode, op1, 0);
5357 emit_move_insn (operands[0], op1);
5358 DONE;
5359 }"
5360)
5361
604f3a0a 5362(define_expand "floatsisf2"
5363 [(set (match_operand:SF 0 "s_register_operand" "")
5364 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 5365 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5366 "
604f3a0a 5367")
5368
604f3a0a 5369(define_expand "floatsidf2"
5370 [(set (match_operand:DF 0 "s_register_operand" "")
5371 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 5372 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5373 "
604f3a0a 5374")
5375
9b8516be 5376(define_expand "fix_trunchfsi2"
5377 [(set (match_operand:SI 0 "general_operand" "")
5378 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5379 "TARGET_EITHER"
5380 "
5381 {
5382 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5383 expand_fix (operands[0], op1, 0);
5384 DONE;
5385 }"
5386)
5387
5388(define_expand "fix_trunchfdi2"
5389 [(set (match_operand:DI 0 "general_operand" "")
5390 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5391 "TARGET_EITHER"
5392 "
5393 {
5394 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5395 expand_fix (operands[0], op1, 0);
5396 DONE;
5397 }"
5398)
5399
604f3a0a 5400(define_expand "fix_truncsfsi2"
5401 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5402 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 5403 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5404 "
604f3a0a 5405")
5406
604f3a0a 5407(define_expand "fix_truncdfsi2"
5408 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5409 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 5410 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5411 "
604f3a0a 5412")
5413
f544c6d2 5414;; Truncation insns
b11cae9e 5415
604f3a0a 5416(define_expand "truncdfsf2"
5417 [(set (match_operand:SF 0 "s_register_operand" "")
5418 (float_truncate:SF
5419 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5420 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5421 ""
5422)
9b8516be 5423
5424/* DFmode -> HFmode conversions have to go through SFmode. */
5425(define_expand "truncdfhf2"
5426 [(set (match_operand:HF 0 "general_operand" "")
5427 (float_truncate:HF
5428 (match_operand:DF 1 "general_operand" "")))]
5429 "TARGET_EITHER"
5430 "
5431 {
5432 rtx op1;
5433 op1 = convert_to_mode (SFmode, operands[1], 0);
5434 op1 = convert_to_mode (HFmode, op1, 0);
5435 emit_move_insn (operands[0], op1);
5436 DONE;
5437 }"
5438)
b11cae9e 5439\f
9c08d1fa 5440;; Zero and sign extension instructions.
b11cae9e 5441
848e66ac 5442(define_insn "zero_extend<mode>di2"
6aa689e8 5443 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 5444 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5445 "<qhs_zextenddi_cstr>")))]
848e66ac 5446 "TARGET_32BIT <qhs_zextenddi_cond>"
5447 "#"
6aa689e8 5448 [(set_attr "length" "8,4,8,8")
b6779ddc 5449 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 5450 (set_attr "ce_count" "2")
5451 (set_attr "predicable" "yes")]
25f905c2 5452)
5453
848e66ac 5454(define_insn "extend<mode>di2"
6aa689e8 5455 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 5456 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5457 "<qhs_extenddi_cstr>")))]
848e66ac 5458 "TARGET_32BIT <qhs_sextenddi_cond>"
5459 "#"
6aa689e8 5460 [(set_attr "length" "8,4,8,8,8")
848e66ac 5461 (set_attr "ce_count" "2")
5462 (set_attr "shift" "1")
8012d2c2 5463 (set_attr "predicable" "yes")
b6779ddc 5464 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")]
0d66636f 5465)
9c08d1fa 5466
848e66ac 5467;; Splits for all extensions to DImode
5468(define_split
5469 [(set (match_operand:DI 0 "s_register_operand" "")
5470 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5471 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5472 [(set (match_dup 0) (match_dup 1))]
5473{
848e66ac 5474 rtx lo_part = gen_lowpart (SImode, operands[0]);
5475 enum machine_mode src_mode = GET_MODE (operands[1]);
5476
5477 if (REG_P (operands[0])
5478 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5479 emit_clobber (operands[0]);
5480 if (!REG_P (lo_part) || src_mode != SImode
5481 || !rtx_equal_p (lo_part, operands[1]))
5482 {
5483 if (src_mode == SImode)
5484 emit_move_insn (lo_part, operands[1]);
5485 else
5486 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
5487 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5488 operands[1] = lo_part;
5489 }
5490 operands[0] = gen_highpart (SImode, operands[0]);
5491 operands[1] = const0_rtx;
5492})
9c08d1fa 5493
848e66ac 5494(define_split
25f905c2 5495 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 5496 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5497 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5498 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5499{
5500 rtx lo_part = gen_lowpart (SImode, operands[0]);
5501 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 5502
848e66ac 5503 if (REG_P (operands[0])
5504 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5505 emit_clobber (operands[0]);
5506
5507 if (!REG_P (lo_part) || src_mode != SImode
5508 || !rtx_equal_p (lo_part, operands[1]))
5509 {
5510 if (src_mode == SImode)
5511 emit_move_insn (lo_part, operands[1]);
5512 else
5513 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
5514 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5515 operands[1] = lo_part;
5516 }
5517 operands[0] = gen_highpart (SImode, operands[0]);
5518})
9c08d1fa 5519
5520(define_expand "zero_extendhisi2"
ef51b8e1 5521 [(set (match_operand:SI 0 "s_register_operand" "")
5522 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5523 "TARGET_EITHER"
ef51b8e1 5524{
5525 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 5526 {
ef51b8e1 5527 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5528 DONE;
25f7a26e 5529 }
ef51b8e1 5530 if (!arm_arch6 && !MEM_P (operands[1]))
5531 {
5532 rtx t = gen_lowpart (SImode, operands[1]);
5533 rtx tmp = gen_reg_rtx (SImode);
5534 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5535 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5536 DONE;
5537 }
5538})
9c08d1fa 5539
ef51b8e1 5540(define_split
b146458f 5541 [(set (match_operand:SI 0 "s_register_operand" "")
5542 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 5543 "!TARGET_THUMB2 && !arm_arch6"
5544 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5545 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5546{
5547 operands[2] = gen_lowpart (SImode, operands[1]);
5548})
5549
5550(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 5551 [(set (match_operand:SI 0 "register_operand" "=l,l")
5552 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 5553 "TARGET_THUMB1"
848e66ac 5554{
a2cd141b 5555 rtx mem;
5556
ef51b8e1 5557 if (which_alternative == 0 && arm_arch6)
848e66ac 5558 return "uxth\t%0, %1";
ef51b8e1 5559 if (which_alternative == 0)
848e66ac 5560 return "#";
a2cd141b 5561
5562 mem = XEXP (operands[1], 0);
5563
5564 if (GET_CODE (mem) == CONST)
5565 mem = XEXP (mem, 0);
5566
a2cd141b 5567 if (GET_CODE (mem) == PLUS)
5568 {
5569 rtx a = XEXP (mem, 0);
a2cd141b 5570
5571 /* This can happen due to bugs in reload. */
0438d37f 5572 if (REG_P (a) && REGNO (a) == SP_REGNUM)
a2cd141b 5573 {
5574 rtx ops[2];
5575 ops[0] = operands[0];
5576 ops[1] = a;
5577
848e66ac 5578 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 5579
5580 XEXP (mem, 0) = operands[0];
5581 }
a2cd141b 5582 }
5583
848e66ac 5584 return "ldrh\t%0, %1";
5585}
ef51b8e1 5586 [(set_attr_alternative "length"
5587 [(if_then_else (eq_attr "is_arch6" "yes")
5588 (const_int 2) (const_int 4))
5589 (const_int 4)])
6b6abc9c 5590 (set_attr "type" "extend,load_byte")]
a2cd141b 5591)
5592
cffb2a26 5593(define_insn "*arm_zero_extendhisi2"
ef51b8e1 5594 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5595 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5596 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5597 "@
5598 #
5599 ldr%(h%)\\t%0, %1"
6b6abc9c 5600 [(set_attr "type" "arlo_shift,load_byte")
848e66ac 5601 (set_attr "predicable" "yes")]
cffb2a26 5602)
f7fbdd4a 5603
a2cd141b 5604(define_insn "*arm_zero_extendhisi2_v6"
5605 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5606 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
5607 "TARGET_ARM && arm_arch6"
5608 "@
5609 uxth%?\\t%0, %1
25f905c2 5610 ldr%(h%)\\t%0, %1"
65f68e55 5611 [(set_attr "predicable" "yes")
6b6abc9c 5612 (set_attr "type" "extend,load_byte")]
a2cd141b 5613)
5614
5615(define_insn "*arm_zero_extendhisi2addsi"
5616 [(set (match_operand:SI 0 "s_register_operand" "=r")
5617 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5618 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5619 "TARGET_INT_SIMD"
a2cd141b 5620 "uxtah%?\\t%0, %2, %1"
6b6abc9c 5621 [(set_attr "type" "arlo_shift")
d952d547 5622 (set_attr "predicable" "yes")
5623 (set_attr "predicable_short_it" "no")]
a2cd141b 5624)
5625
87b22bf7 5626(define_expand "zero_extendqisi2"
cffb2a26 5627 [(set (match_operand:SI 0 "s_register_operand" "")
5628 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5629 "TARGET_EITHER"
ef51b8e1 5630{
0438d37f 5631 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5632 {
ef51b8e1 5633 emit_insn (gen_andsi3 (operands[0],
5634 gen_lowpart (SImode, operands[1]),
5635 GEN_INT (255)));
5636 DONE;
5637 }
5638 if (!arm_arch6 && !MEM_P (operands[1]))
5639 {
5640 rtx t = gen_lowpart (SImode, operands[1]);
5641 rtx tmp = gen_reg_rtx (SImode);
5642 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5643 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5644 DONE;
5645 }
5646})
cffb2a26 5647
ef51b8e1 5648(define_split
b146458f 5649 [(set (match_operand:SI 0 "s_register_operand" "")
5650 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5651 "!arm_arch6"
5652 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5653 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5654{
5655 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5656 if (TARGET_ARM)
5657 {
5658 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5659 DONE;
5660 }
ef51b8e1 5661})
9c08d1fa 5662
25f905c2 5663(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 5664 [(set (match_operand:SI 0 "register_operand" "=l,l")
5665 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 5666 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 5667 "@
5668 #
5669 ldrb\\t%0, %1"
5670 [(set_attr "length" "4,2")
6b6abc9c 5671 (set_attr "type" "arlo_shift,load_byte")
ef51b8e1 5672 (set_attr "pool_range" "*,32")]
cffb2a26 5673)
5674
25f905c2 5675(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 5676 [(set (match_operand:SI 0 "register_operand" "=l,l")
5677 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 5678 "TARGET_THUMB1 && arm_arch6"
a2cd141b 5679 "@
5680 uxtb\\t%0, %1
5681 ldrb\\t%0, %1"
848e66ac 5682 [(set_attr "length" "2")
6b6abc9c 5683 (set_attr "type" "extend,load_byte")]
a2cd141b 5684)
5685
cffb2a26 5686(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5687 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5688 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5689 "TARGET_ARM && !arm_arch6"
ef51b8e1 5690 "@
5691 #
5692 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
5693 [(set_attr "length" "8,4")
6b6abc9c 5694 (set_attr "type" "arlo_shift,load_byte")
848e66ac 5695 (set_attr "predicable" "yes")]
cffb2a26 5696)
87b22bf7 5697
a2cd141b 5698(define_insn "*arm_zero_extendqisi2_v6"
5699 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5700 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
5701 "TARGET_ARM && arm_arch6"
5702 "@
25f905c2 5703 uxtb%(%)\\t%0, %1
5704 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5705 [(set_attr "type" "extend,load_byte")
848e66ac 5706 (set_attr "predicable" "yes")]
a2cd141b 5707)
5708
5709(define_insn "*arm_zero_extendqisi2addsi"
5710 [(set (match_operand:SI 0 "s_register_operand" "=r")
5711 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5712 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5713 "TARGET_INT_SIMD"
a2cd141b 5714 "uxtab%?\\t%0, %2, %1"
5715 [(set_attr "predicable" "yes")
d952d547 5716 (set_attr "predicable_short_it" "no")
6b6abc9c 5717 (set_attr "type" "arlo_shift")]
a2cd141b 5718)
5719
87b22bf7 5720(define_split
5721 [(set (match_operand:SI 0 "s_register_operand" "")
5722 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5723 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5724 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5725 [(set (match_dup 2) (match_dup 1))
5726 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5727 ""
5728)
9c08d1fa 5729
8a4d25d6 5730(define_split
5731 [(set (match_operand:SI 0 "s_register_operand" "")
5732 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5733 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5734 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5735 [(set (match_dup 2) (match_dup 1))
5736 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5737 ""
5738)
5739
1c274529 5740
5741(define_split
5742 [(set (match_operand:SI 0 "s_register_operand" "")
5743 (ior_xor:SI (and:SI (ashift:SI
5744 (match_operand:SI 1 "s_register_operand" "")
5745 (match_operand:SI 2 "const_int_operand" ""))
5746 (match_operand:SI 3 "const_int_operand" ""))
5747 (zero_extend:SI
5748 (match_operator 5 "subreg_lowpart_operator"
5749 [(match_operand:SI 4 "s_register_operand" "")]))))]
5750 "TARGET_32BIT
63787642 5751 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 5752 == (GET_MODE_MASK (GET_MODE (operands[5]))
5753 & (GET_MODE_MASK (GET_MODE (operands[5]))
5754 << (INTVAL (operands[2])))))"
5755 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
5756 (match_dup 4)))
5757 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5758 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5759)
5760
f7fbdd4a 5761(define_insn "*compareqi_eq0"
bd5b4116 5762 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5763 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5764 (const_int 0)))]
25f905c2 5765 "TARGET_32BIT"
596e5e8f 5766 "tst%?\\t%0, #255"
5767 [(set_attr "conds" "set")
d952d547 5768 (set_attr "predicable" "yes")
5769 (set_attr "predicable_short_it" "no")]
cffb2a26 5770)
b11cae9e 5771
b11cae9e 5772(define_expand "extendhisi2"
ef51b8e1 5773 [(set (match_operand:SI 0 "s_register_operand" "")
5774 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5775 "TARGET_EITHER"
ef51b8e1 5776{
5777 if (TARGET_THUMB1)
5778 {
5779 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5780 DONE;
5781 }
5782 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5783 {
5784 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5785 DONE;
5786 }
ed29c566 5787
ef51b8e1 5788 if (!arm_arch6 && !MEM_P (operands[1]))
5789 {
5790 rtx t = gen_lowpart (SImode, operands[1]);
5791 rtx tmp = gen_reg_rtx (SImode);
5792 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5793 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5794 DONE;
5795 }
5796})
cffb2a26 5797
ef51b8e1 5798(define_split
5799 [(parallel
5800 [(set (match_operand:SI 0 "register_operand" "")
5801 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5802 (clobber (match_scratch:SI 2 ""))])]
5803 "!arm_arch6"
5804 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5805 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5806{
5807 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5808})
25f7a26e 5809
a2cd141b 5810;; We used to have an early-clobber on the scratch register here.
5811;; However, there's a bug somewhere in reload which means that this
5812;; can be partially ignored during spill allocation if the memory
ed29c566 5813;; address also needs reloading; this causes us to die later on when
a2cd141b 5814;; we try to verify the operands. Fortunately, we don't really need
5815;; the early-clobber: we can always use operand 0 if operand 2
5816;; overlaps the address.
ef51b8e1 5817(define_insn "thumb1_extendhisi2"
a2cd141b 5818 [(set (match_operand:SI 0 "register_operand" "=l,l")
5819 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
5820 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 5821 "TARGET_THUMB1"
a2cd141b 5822 "*
5823 {
5824 rtx ops[4];
5825 rtx mem;
5826
ef51b8e1 5827 if (which_alternative == 0 && !arm_arch6)
5828 return \"#\";
a2cd141b 5829 if (which_alternative == 0)
5830 return \"sxth\\t%0, %1\";
5831
5832 mem = XEXP (operands[1], 0);
5833
5834 /* This code used to try to use 'V', and fix the address only if it was
5835 offsettable, but this fails for e.g. REG+48 because 48 is outside the
5836 range of QImode offsets, and offsettable_address_p does a QImode
5837 address check. */
5838
5839 if (GET_CODE (mem) == CONST)
5840 mem = XEXP (mem, 0);
5841
5842 if (GET_CODE (mem) == LABEL_REF)
5843 return \"ldr\\t%0, %1\";
5844
5845 if (GET_CODE (mem) == PLUS)
5846 {
5847 rtx a = XEXP (mem, 0);
5848 rtx b = XEXP (mem, 1);
5849
5850 if (GET_CODE (a) == LABEL_REF
0438d37f 5851 && CONST_INT_P (b))
a2cd141b 5852 return \"ldr\\t%0, %1\";
5853
0438d37f 5854 if (REG_P (b))
a2cd141b 5855 return \"ldrsh\\t%0, %1\";
5856
5857 ops[1] = a;
5858 ops[2] = b;
5859 }
5860 else
5861 {
5862 ops[1] = mem;
5863 ops[2] = const0_rtx;
5864 }
5865
0438d37f 5866 gcc_assert (REG_P (ops[1]));
a2cd141b 5867
5868 ops[0] = operands[0];
5869 if (reg_mentioned_p (operands[2], ops[1]))
5870 ops[3] = ops[0];
5871 else
5872 ops[3] = operands[2];
5873 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
5874 return \"\";
5875 }"
ef51b8e1 5876 [(set_attr_alternative "length"
5877 [(if_then_else (eq_attr "is_arch6" "yes")
5878 (const_int 2) (const_int 4))
5879 (const_int 4)])
6b6abc9c 5880 (set_attr "type" "extend,load_byte")
42e1de19 5881 (set_attr "pool_range" "*,1018")]
a2cd141b 5882)
5883
25f905c2 5884;; This pattern will only be used when ldsh is not available
25f7a26e 5885(define_expand "extendhisi2_mem"
eab14235 5886 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5887 (set (match_dup 3)
eab14235 5888 (zero_extend:SI (match_dup 7)))
25f7a26e 5889 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5890 (set (match_operand:SI 0 "" "")
5891 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5892 "TARGET_ARM"
25f7a26e 5893 "
215b30b3 5894 {
5895 rtx mem1, mem2;
5896 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5897
788fcce0 5898 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5899 mem2 = change_address (operands[1], QImode,
5900 plus_constant (Pmode, addr, 1));
215b30b3 5901 operands[0] = gen_lowpart (SImode, operands[0]);
5902 operands[1] = mem1;
5903 operands[2] = gen_reg_rtx (SImode);
5904 operands[3] = gen_reg_rtx (SImode);
5905 operands[6] = gen_reg_rtx (SImode);
5906 operands[7] = mem2;
25f7a26e 5907
215b30b3 5908 if (BYTES_BIG_ENDIAN)
5909 {
5910 operands[4] = operands[2];
5911 operands[5] = operands[3];
5912 }
5913 else
5914 {
5915 operands[4] = operands[3];
5916 operands[5] = operands[2];
5917 }
5918 }"
5919)
b11cae9e 5920
ef51b8e1 5921(define_split
5922 [(set (match_operand:SI 0 "register_operand" "")
5923 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5924 "!arm_arch6"
5925 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5926 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5927{
5928 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5929})
5930
a2cd141b 5931(define_insn "*arm_extendhisi2"
ef51b8e1 5932 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5933 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5934 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5935 "@
5936 #
5937 ldr%(sh%)\\t%0, %1"
5938 [(set_attr "length" "8,4")
6b6abc9c 5939 (set_attr "type" "arlo_shift,load_byte")
0d66636f 5940 (set_attr "predicable" "yes")
ef51b8e1 5941 (set_attr "pool_range" "*,256")
5942 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5943)
f7fbdd4a 5944
25f905c2 5945;; ??? Check Thumb-2 pool range
a2cd141b 5946(define_insn "*arm_extendhisi2_v6"
5947 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5948 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 5949 "TARGET_32BIT && arm_arch6"
a2cd141b 5950 "@
5951 sxth%?\\t%0, %1
25f905c2 5952 ldr%(sh%)\\t%0, %1"
6b6abc9c 5953 [(set_attr "type" "extend,load_byte")
a2cd141b 5954 (set_attr "predicable" "yes")
d952d547 5955 (set_attr "predicable_short_it" "no")
a2cd141b 5956 (set_attr "pool_range" "*,256")
5957 (set_attr "neg_pool_range" "*,244")]
5958)
5959
5960(define_insn "*arm_extendhisi2addsi"
5961 [(set (match_operand:SI 0 "s_register_operand" "=r")
5962 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5963 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5964 "TARGET_INT_SIMD"
a2cd141b 5965 "sxtah%?\\t%0, %2, %1"
5966)
5967
c8f69309 5968(define_expand "extendqihi2"
5969 [(set (match_dup 2)
bed7d9a5 5970 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5971 (const_int 24)))
9c08d1fa 5972 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5973 (ashiftrt:SI (match_dup 2)
5974 (const_int 24)))]
cffb2a26 5975 "TARGET_ARM"
c8f69309 5976 "
215b30b3 5977 {
0438d37f 5978 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5979 {
5980 emit_insn (gen_rtx_SET (VOIDmode,
5981 operands[0],
5982 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5983 DONE;
5984 }
5985 if (!s_register_operand (operands[1], QImode))
5986 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5987 operands[0] = gen_lowpart (SImode, operands[0]);
5988 operands[1] = gen_lowpart (SImode, operands[1]);
5989 operands[2] = gen_reg_rtx (SImode);
5990 }"
5991)
f7fbdd4a 5992
25f905c2 5993(define_insn "*arm_extendqihi_insn"
b4e8a300 5994 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5995 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5996 "TARGET_ARM && arm_arch4"
25f905c2 5997 "ldr%(sb%)\\t%0, %1"
a2cd141b 5998 [(set_attr "type" "load_byte")
0d66636f 5999 (set_attr "predicable" "yes")
cffb2a26 6000 (set_attr "pool_range" "256")
6001 (set_attr "neg_pool_range" "244")]
6002)
3fc2009e 6003
b11cae9e 6004(define_expand "extendqisi2"
ef51b8e1 6005 [(set (match_operand:SI 0 "s_register_operand" "")
6006 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 6007 "TARGET_EITHER"
ef51b8e1 6008{
6009 if (!arm_arch4 && MEM_P (operands[1]))
6010 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 6011
ef51b8e1 6012 if (!arm_arch6 && !MEM_P (operands[1]))
6013 {
6014 rtx t = gen_lowpart (SImode, operands[1]);
6015 rtx tmp = gen_reg_rtx (SImode);
6016 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
6017 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
6018 DONE;
6019 }
6020})
a2cd141b 6021
ef51b8e1 6022(define_split
6023 [(set (match_operand:SI 0 "register_operand" "")
6024 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
6025 "!arm_arch6"
6026 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
6027 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
6028{
6029 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
6030})
f7fbdd4a 6031
a2cd141b 6032(define_insn "*arm_extendqisi"
ef51b8e1 6033 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6034 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 6035 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 6036 "@
6037 #
6038 ldr%(sb%)\\t%0, %1"
6039 [(set_attr "length" "8,4")
6b6abc9c 6040 (set_attr "type" "arlo_shift,load_byte")
0d66636f 6041 (set_attr "predicable" "yes")
ef51b8e1 6042 (set_attr "pool_range" "*,256")
6043 (set_attr "neg_pool_range" "*,244")]
cffb2a26 6044)
3fc2009e 6045
a2cd141b 6046(define_insn "*arm_extendqisi_v6"
6047 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 6048 (sign_extend:SI
6049 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 6050 "TARGET_ARM && arm_arch6"
b4e8a300 6051 "@
6052 sxtb%?\\t%0, %1
25f905c2 6053 ldr%(sb%)\\t%0, %1"
6b6abc9c 6054 [(set_attr "type" "extend,load_byte")
a2cd141b 6055 (set_attr "predicable" "yes")
a2cd141b 6056 (set_attr "pool_range" "*,256")
6057 (set_attr "neg_pool_range" "*,244")]
6058)
6059
6060(define_insn "*arm_extendqisi2addsi"
6061 [(set (match_operand:SI 0 "s_register_operand" "=r")
6062 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
6063 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 6064 "TARGET_INT_SIMD"
a2cd141b 6065 "sxtab%?\\t%0, %2, %1"
6b6abc9c 6066 [(set_attr "type" "arlo_shift")
d952d547 6067 (set_attr "predicable" "yes")
6068 (set_attr "predicable_short_it" "no")]
a2cd141b 6069)
6070
ef51b8e1 6071(define_split
6072 [(set (match_operand:SI 0 "register_operand" "")
6073 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
6074 "TARGET_THUMB1 && reload_completed"
6075 [(set (match_dup 0) (match_dup 2))
6076 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
6077{
6078 rtx addr = XEXP (operands[1], 0);
cffb2a26 6079
ef51b8e1 6080 if (GET_CODE (addr) == CONST)
6081 addr = XEXP (addr, 0);
cffb2a26 6082
ef51b8e1 6083 if (GET_CODE (addr) == PLUS
6084 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
6085 /* No split necessary. */
6086 FAIL;
6087
6088 if (GET_CODE (addr) == PLUS
6089 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
6090 FAIL;
6091
6092 if (reg_overlap_mentioned_p (operands[0], addr))
6093 {
6094 rtx t = gen_lowpart (QImode, operands[0]);
6095 emit_move_insn (t, operands[1]);
6096 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
6097 DONE;
6098 }
6099
6100 if (REG_P (addr))
6101 {
6102 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
6103 operands[2] = const0_rtx;
6104 }
6105 else if (GET_CODE (addr) != PLUS)
6106 FAIL;
6107 else if (REG_P (XEXP (addr, 0)))
6108 {
6109 operands[2] = XEXP (addr, 1);
6110 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
6111 }
6112 else
6113 {
6114 operands[2] = XEXP (addr, 0);
6115 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
6116 }
cffb2a26 6117
ef51b8e1 6118 operands[3] = change_address (operands[1], QImode, addr);
6119})
6120
8a3b73a1 6121(define_peephole2
6122 [(set (match_operand:SI 0 "register_operand" "")
6123 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
6124 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
6125 (set (match_operand:SI 3 "register_operand" "")
6126 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
6127 "TARGET_THUMB1
6128 && GET_CODE (XEXP (operands[4], 0)) == PLUS
6129 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
6130 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
6131 && (peep2_reg_dead_p (3, operands[0])
6132 || rtx_equal_p (operands[0], operands[3]))
6133 && (peep2_reg_dead_p (3, operands[2])
6134 || rtx_equal_p (operands[2], operands[3]))"
6135 [(set (match_dup 2) (match_dup 1))
6136 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
6137{
6138 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
6139 operands[4] = change_address (operands[4], QImode, addr);
6140})
6141
ef51b8e1 6142(define_insn "thumb1_extendqisi2"
a2cd141b 6143 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
6144 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 6145 "TARGET_THUMB1"
6146{
6147 rtx addr;
a2cd141b 6148
ef51b8e1 6149 if (which_alternative == 0 && arm_arch6)
6150 return "sxtb\\t%0, %1";
6151 if (which_alternative == 0)
6152 return "#";
a2cd141b 6153
ef51b8e1 6154 addr = XEXP (operands[1], 0);
6155 if (GET_CODE (addr) == PLUS
6156 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
6157 return "ldrsb\\t%0, %1";
a2cd141b 6158
ef51b8e1 6159 return "#";
6160}
6161 [(set_attr_alternative "length"
6162 [(if_then_else (eq_attr "is_arch6" "yes")
6163 (const_int 2) (const_int 4))
6164 (const_int 2)
6165 (if_then_else (eq_attr "is_arch6" "yes")
6166 (const_int 4) (const_int 6))])
6b6abc9c 6167 (set_attr "type" "extend,load_byte,load_byte")]
a2cd141b 6168)
6169
caedf871 6170(define_expand "extendsfdf2"
6171 [(set (match_operand:DF 0 "s_register_operand" "")
6172 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 6173 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 6174 ""
6175)
9b8516be 6176
6177/* HFmode -> DFmode conversions have to go through SFmode. */
6178(define_expand "extendhfdf2"
6179 [(set (match_operand:DF 0 "general_operand" "")
6180 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
6181 "TARGET_EITHER"
6182 "
6183 {
6184 rtx op1;
6185 op1 = convert_to_mode (SFmode, operands[1], 0);
6186 op1 = convert_to_mode (DFmode, op1, 0);
6187 emit_insn (gen_movdf (operands[0], op1));
6188 DONE;
6189 }"
6190)
b11cae9e 6191\f
6192;; Move insns (including loads and stores)
6193
6194;; XXX Just some ideas about movti.
9c08d1fa 6195;; I don't think these are a good idea on the arm, there just aren't enough
6196;; registers
b11cae9e 6197;;(define_expand "loadti"
9c08d1fa 6198;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 6199;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
6200;; "" "")
6201
6202;;(define_expand "storeti"
6203;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 6204;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 6205;; "" "")
6206
6207;;(define_expand "movti"
6208;; [(set (match_operand:TI 0 "general_operand" "")
6209;; (match_operand:TI 1 "general_operand" ""))]
6210;; ""
6211;; "
6212;;{
6213;; rtx insn;
6214;;
0438d37f 6215;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 6216;; operands[1] = copy_to_reg (operands[1]);
0438d37f 6217;; if (MEM_P (operands[0]))
b11cae9e 6218;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 6219;; else if (MEM_P (operands[1]))
b11cae9e 6220;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
6221;; else
6222;; FAIL;
6223;;
6224;; emit_insn (insn);
6225;; DONE;
6226;;}")
6227
a2f10574 6228;; Recognize garbage generated above.
b11cae9e 6229
6230;;(define_insn ""
6231;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
6232;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
6233;; ""
6234;; "*
6235;; {
6236;; register mem = (which_alternative < 3);
0d66636f 6237;; register const char *template;
b11cae9e 6238;;
6239;; operands[mem] = XEXP (operands[mem], 0);
6240;; switch (which_alternative)
6241;; {
6242;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
6243;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
6244;; case 2: template = \"ldmia\\t%1, %M0\"; break;
6245;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
6246;; case 4: template = \"stmia\\t%0!, %M1\"; break;
6247;; case 5: template = \"stmia\\t%0, %M1\"; break;
6248;; }
e2348bcb 6249;; output_asm_insn (template, operands);
6250;; return \"\";
b11cae9e 6251;; }")
6252
cffb2a26 6253(define_expand "movdi"
6254 [(set (match_operand:DI 0 "general_operand" "")
6255 (match_operand:DI 1 "general_operand" ""))]
6256 "TARGET_EITHER"
6257 "
e1ba4a27 6258 if (can_create_pseudo_p ())
cffb2a26 6259 {
0438d37f 6260 if (!REG_P (operands[0]))
b2778788 6261 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 6262 }
6263 "
6264)
b11cae9e 6265
cffb2a26 6266(define_insn "*arm_movdi"
353cf59a 6267 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
6268 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 6269 "TARGET_32BIT
b805622c 6270 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 6271 && !TARGET_IWMMXT
6272 && ( register_operand (operands[0], DImode)
6273 || register_operand (operands[1], DImode))"
b11cae9e 6274 "*
d51f92df 6275 switch (which_alternative)
6276 {
6277 case 0:
6278 case 1:
6279 case 2:
6280 return \"#\";
6281 default:
26ff80c0 6282 return output_move_double (operands, true, NULL);
d51f92df 6283 }
cffb2a26 6284 "
359a6e9f 6285 [(set_attr "length" "8,12,16,8,8")
6286 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6287 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 6288 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 6289 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 6290 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6291)
6292
d51f92df 6293(define_split
6294 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
6295 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 6296 "TARGET_32BIT
d51f92df 6297 && reload_completed
6298 && (arm_const_double_inline_cost (operands[1])
6299 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
6300 [(const_int 0)]
6301 "
6302 arm_split_constant (SET, SImode, curr_insn,
6303 INTVAL (gen_lowpart (SImode, operands[1])),
6304 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
6305 arm_split_constant (SET, SImode, curr_insn,
6306 INTVAL (gen_highpart_mode (SImode,
6307 GET_MODE (operands[0]),
6308 operands[1])),
6309 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
6310 DONE;
6311 "
6312)
6313
e5ba9289 6314; If optimizing for size, or if we have load delay slots, then
6315; we want to split the constant into two separate operations.
6316; In both cases this may split a trivial part into a single data op
6317; leaving a single complex constant to load. We can also get longer
6318; offsets in a LDR which means we get better chances of sharing the pool
6319; entries. Finally, we can normally do a better job of scheduling
6320; LDR instructions than we can with LDM.
6321; This pattern will only match if the one above did not.
6322(define_split
6323 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
6324 (match_operand:ANY64 1 "const_double_operand" ""))]
6325 "TARGET_ARM && reload_completed
6326 && arm_const_double_by_parts (operands[1])"
6327 [(set (match_dup 0) (match_dup 1))
6328 (set (match_dup 2) (match_dup 3))]
6329 "
6330 operands[2] = gen_highpart (SImode, operands[0]);
6331 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
6332 operands[1]);
6333 operands[0] = gen_lowpart (SImode, operands[0]);
6334 operands[1] = gen_lowpart (SImode, operands[1]);
6335 "
6336)
6337
d51f92df 6338(define_split
6339 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
6340 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
6341 "TARGET_EITHER && reload_completed"
6342 [(set (match_dup 0) (match_dup 1))
6343 (set (match_dup 2) (match_dup 3))]
6344 "
6345 operands[2] = gen_highpart (SImode, operands[0]);
6346 operands[3] = gen_highpart (SImode, operands[1]);
6347 operands[0] = gen_lowpart (SImode, operands[0]);
6348 operands[1] = gen_lowpart (SImode, operands[1]);
6349
6350 /* Handle a partial overlap. */
6351 if (rtx_equal_p (operands[0], operands[3]))
6352 {
6353 rtx tmp0 = operands[0];
6354 rtx tmp1 = operands[1];
6355
6356 operands[0] = operands[2];
6357 operands[1] = operands[3];
6358 operands[2] = tmp0;
6359 operands[3] = tmp1;
6360 }
6361 "
6362)
6363
a8a3b539 6364;; We can't actually do base+index doubleword loads if the index and
6365;; destination overlap. Split here so that we at least have chance to
6366;; schedule.
6367(define_split
6368 [(set (match_operand:DI 0 "s_register_operand" "")
6369 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
6370 (match_operand:SI 2 "s_register_operand" ""))))]
6371 "TARGET_LDRD
6372 && reg_overlap_mentioned_p (operands[0], operands[1])
6373 && reg_overlap_mentioned_p (operands[0], operands[2])"
6374 [(set (match_dup 4)
6375 (plus:SI (match_dup 1)
6376 (match_dup 2)))
6377 (set (match_dup 0)
6378 (mem:DI (match_dup 4)))]
6379 "
6380 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
6381 "
6382)
6383
cffb2a26 6384;;; ??? This should have alternatives for constants.
6385;;; ??? This was originally identical to the movdf_insn pattern.
6386;;; ??? The 'i' constraint looks funny, but it should always be replaced by
6387;;; thumb_reorg with a memory reference.
25f905c2 6388(define_insn "*thumb1_movdi_insn"
215b30b3 6389 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
6390 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 6391 "TARGET_THUMB1
cffb2a26 6392 && ( register_operand (operands[0], DImode)
6393 || register_operand (operands[1], DImode))"
6394 "*
6395 {
6396 switch (which_alternative)
6397 {
6398 default:
6399 case 0:
6400 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6401 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6402 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6403 case 1:
6404 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
6405 case 2:
6406 operands[1] = GEN_INT (- INTVAL (operands[1]));
6407 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
6408 case 3:
6409 return \"ldmia\\t%1, {%0, %H0}\";
6410 case 4:
6411 return \"stmia\\t%0, {%1, %H1}\";
6412 case 5:
6413 return thumb_load_double_from_address (operands);
6414 case 6:
1a83b3ff 6415 operands[2] = gen_rtx_MEM (SImode,
29c05e22 6416 plus_constant (Pmode, XEXP (operands[0], 0), 4));
cffb2a26 6417 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6418 return \"\";
6419 case 7:
6420 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6421 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6422 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6423 }
6424 }"
6425 [(set_attr "length" "4,4,6,2,2,6,4,4")
1aed5204 6426 (set_attr "type" "*,mov_reg,*,load2,store2,load2,store2,mov_reg")
42e1de19 6427 (set_attr "pool_range" "*,*,*,*,*,1018,*,*")]
cffb2a26 6428)
b11cae9e 6429
9c08d1fa 6430(define_expand "movsi"
6431 [(set (match_operand:SI 0 "general_operand" "")
6432 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 6433 "TARGET_EITHER"
9c08d1fa 6434 "
befb0bac 6435 {
e348ff3e 6436 rtx base, offset, tmp;
6437
25f905c2 6438 if (TARGET_32BIT)
9c08d1fa 6439 {
674a8f0b 6440 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 6441 if (MEM_P (operands[0]))
cffb2a26 6442 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 6443 if (arm_general_register_operand (operands[0], SImode)
0438d37f 6444 && CONST_INT_P (operands[1])
cffb2a26 6445 && !(const_ok_for_arm (INTVAL (operands[1]))
6446 || const_ok_for_arm (~INTVAL (operands[1]))))
6447 {
96f57e36 6448 arm_split_constant (SET, SImode, NULL_RTX,
6449 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 6450 optimize && can_create_pseudo_p ());
cffb2a26 6451 DONE;
6452 }
6453 }
25f905c2 6454 else /* TARGET_THUMB1... */
cffb2a26 6455 {
e1ba4a27 6456 if (can_create_pseudo_p ())
cffb2a26 6457 {
0438d37f 6458 if (!REG_P (operands[0]))
cffb2a26 6459 operands[1] = force_reg (SImode, operands[1]);
6460 }
9c08d1fa 6461 }
f655717d 6462
e348ff3e 6463 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
6464 {
6465 split_const (operands[1], &base, &offset);
6466 if (GET_CODE (base) == SYMBOL_REF
6467 && !offset_within_block_p (base, INTVAL (offset)))
6468 {
b308ddcf 6469 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 6470 emit_move_insn (tmp, base);
6471 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6472 DONE;
6473 }
6474 }
6475
f655717d 6476 /* Recognize the case where operand[1] is a reference to thread-local
6477 data and load its address to a register. */
6478 if (arm_tls_referenced_p (operands[1]))
6479 {
6480 rtx tmp = operands[1];
6481 rtx addend = NULL;
6482
6483 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
6484 {
6485 addend = XEXP (XEXP (tmp, 0), 1);
6486 tmp = XEXP (XEXP (tmp, 0), 0);
6487 }
6488
6489 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
6490 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
6491
e1ba4a27 6492 tmp = legitimize_tls_address (tmp,
6493 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 6494 if (addend)
6495 {
6496 tmp = gen_rtx_PLUS (SImode, tmp, addend);
6497 tmp = force_operand (tmp, operands[0]);
6498 }
6499 operands[1] = tmp;
6500 }
6501 else if (flag_pic
6502 && (CONSTANT_P (operands[1])
6503 || symbol_mentioned_p (operands[1])
6504 || label_mentioned_p (operands[1])))
6505 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 6506 (!can_create_pseudo_p ()
6507 ? operands[0]
6508 : 0));
befb0bac 6509 }
215b30b3 6510 "
6511)
9c08d1fa 6512
d0e6a121 6513;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6514;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6515;; so this does not matter.
6516(define_insn "*arm_movt"
6517 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
6518 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
6519 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 6520 "arm_arch_thumb2"
d0e6a121 6521 "movt%?\t%0, #:upper16:%c2"
6522 [(set_attr "predicable" "yes")
d952d547 6523 (set_attr "predicable_short_it" "no")
d0e6a121 6524 (set_attr "length" "4")]
6525)
6526
cffb2a26 6527(define_insn "*arm_movsi_insn"
aaa37ad6 6528 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 6529 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 6530 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 6531 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 6532 && ( register_operand (operands[0], SImode)
6533 || register_operand (operands[1], SImode))"
f7fbdd4a 6534 "@
aaa37ad6 6535 mov%?\\t%0, %1
f7fbdd4a 6536 mov%?\\t%0, %1
6537 mvn%?\\t%0, #%B1
25f905c2 6538 movw%?\\t%0, %1
f7fbdd4a 6539 ldr%?\\t%0, %1
6540 str%?\\t%1, %0"
1aed5204 6541 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 6542 (set_attr "predicable" "yes")
aaa37ad6 6543 (set_attr "pool_range" "*,*,*,*,4096,*")
6544 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 6545)
87b22bf7 6546
6547(define_split
a2cd141b 6548 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 6549 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 6550 "TARGET_32BIT
215b30b3 6551 && (!(const_ok_for_arm (INTVAL (operands[1]))
6552 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 6553 [(clobber (const_int 0))]
6554 "
96f57e36 6555 arm_split_constant (SET, SImode, NULL_RTX,
6556 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 6557 DONE;
215b30b3 6558 "
6559)
9c08d1fa 6560
b8d5d078 6561;; Split symbol_refs at the later stage (after cprop), instead of generating
6562;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6563;; and lo_sum would be merged back into memory load at cprop. However,
6564;; if the default is to prefer movt/movw rather than a load from the constant
6565;; pool, the performance is better.
6566(define_split
6567 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6568 (match_operand:SI 1 "general_operand" ""))]
6569 "TARGET_32BIT
6570 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
6571 && !flag_pic && !target_word_relocations
6572 && !arm_tls_referenced_p (operands[1])"
6573 [(clobber (const_int 0))]
6574{
6575 arm_emit_movpair (operands[0], operands[1]);
6576 DONE;
6577})
6578
25f905c2 6579(define_insn "*thumb1_movsi_insn"
55a0d64c 6580 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
6581 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
25f905c2 6582 "TARGET_THUMB1
cffb2a26 6583 && ( register_operand (operands[0], SImode)
6584 || register_operand (operands[1], SImode))"
6585 "@
6586 mov %0, %1
6587 mov %0, %1
6588 #
6589 #
6590 ldmia\\t%1, {%0}
6591 stmia\\t%0, {%1}
6592 ldr\\t%0, %1
6593 str\\t%1, %0
6594 mov\\t%0, %1"
6595 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 6596 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
42e1de19 6597 (set_attr "pool_range" "*,*,*,*,*,*,1018,*,*")
747b7458 6598 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 6599
6600(define_split
6601 [(set (match_operand:SI 0 "register_operand" "")
6602 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 6603 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 6604 [(set (match_dup 2) (match_dup 1))
6605 (set (match_dup 0) (neg:SI (match_dup 2)))]
6606 "
6607 {
6608 operands[1] = GEN_INT (- INTVAL (operands[1]));
6609 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6610 }"
cffb2a26 6611)
6612
6613(define_split
6614 [(set (match_operand:SI 0 "register_operand" "")
6615 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 6616 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 6617 [(set (match_dup 2) (match_dup 1))
6618 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 6619 "
6620 {
e4aeee53 6621 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 6622 unsigned HOST_WIDE_INT mask = 0xff;
6623 int i;
6624
6625 for (i = 0; i < 25; i++)
6626 if ((val & (mask << i)) == val)
6627 break;
6628
1276f1b8 6629 /* Don't split if the shift is zero. */
cffb2a26 6630 if (i == 0)
6631 FAIL;
6632
6633 operands[1] = GEN_INT (val >> i);
1276f1b8 6634 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6635 operands[3] = GEN_INT (i);
cffb2a26 6636 }"
6637)
6638
c5b75283 6639;; For thumb1 split imm move [256-510] into mov [1-255] and add #255
6640(define_split
6641 [(set (match_operand:SI 0 "register_operand" "")
6642 (match_operand:SI 1 "const_int_operand" ""))]
6643 "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])"
6644 [(set (match_dup 2) (match_dup 1))
6645 (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))]
6646 "
6647 {
6648 operands[1] = GEN_INT (INTVAL (operands[1]) - 255);
6649 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6650 operands[3] = GEN_INT (255);
6651 }"
6652)
6653
67336bcf 6654;; When generating pic, we need to load the symbol offset into a register.
6655;; So that the optimizer does not confuse this with a normal symbol load
6656;; we use an unspec. The offset will be loaded from a constant pool entry,
6657;; since that is the only type of relocation we can use.
6658
94f8caca 6659;; Wrap calculation of the whole PIC address in a single pattern for the
6660;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6661;; a PIC address involves two loads from memory, so we want to CSE it
6662;; as often as possible.
6663;; This pattern will be split into one of the pic_load_addr_* patterns
6664;; and a move after GCSE optimizations.
6665;;
6666;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6667(define_expand "calculate_pic_address"
6668 [(set (match_operand:SI 0 "register_operand" "")
6669 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6670 (unspec:SI [(match_operand:SI 2 "" "")]
6671 UNSPEC_PIC_SYM))))]
6672 "flag_pic"
6673)
6674
6675;; Split calculate_pic_address into pic_load_addr_* and a move.
6676(define_split
6677 [(set (match_operand:SI 0 "register_operand" "")
6678 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6679 (unspec:SI [(match_operand:SI 2 "" "")]
6680 UNSPEC_PIC_SYM))))]
6681 "flag_pic"
6682 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6683 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6684 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6685)
6686
350ccca5 6687;; operand1 is the memory address to go into
6688;; pic_load_addr_32bit.
6689;; operand2 is the PIC label to be emitted
6690;; from pic_add_dot_plus_eight.
6691;; We do this to allow hoisting of the entire insn.
6692(define_insn_and_split "pic_load_addr_unified"
6693 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6694 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6695 (match_operand:SI 2 "" "")]
6696 UNSPEC_PIC_UNIFIED))]
6697 "flag_pic"
6698 "#"
6699 "&& reload_completed"
6700 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6701 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6702 (match_dup 2)] UNSPEC_PIC_BASE))]
6703 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
6704 [(set_attr "type" "load1,load1,load1")
42e1de19 6705 (set_attr "pool_range" "4096,4094,1022")
350ccca5 6706 (set_attr "neg_pool_range" "4084,0,0")
6707 (set_attr "arch" "a,t2,t1")
6708 (set_attr "length" "8,6,4")]
6709)
6710
67336bcf 6711;; The rather odd constraints on the following are to force reload to leave
6712;; the insn alone, and to force the minipool generation pass to then move
6713;; the GOT symbol to memory.
849170fd 6714
b3cd5f55 6715(define_insn "pic_load_addr_32bit"
849170fd 6716 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 6717 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 6718 "TARGET_32BIT && flag_pic"
67336bcf 6719 "ldr%?\\t%0, %1"
a2cd141b 6720 [(set_attr "type" "load1")
42e1de19 6721 (set (attr "pool_range")
6722 (if_then_else (eq_attr "is_thumb" "no")
6723 (const_int 4096)
6724 (const_int 4094)))
b3cd5f55 6725 (set (attr "neg_pool_range")
6726 (if_then_else (eq_attr "is_thumb" "no")
6727 (const_int 4084)
6728 (const_int 0)))]
8c4d8060 6729)
6730
25f905c2 6731(define_insn "pic_load_addr_thumb1"
8c4d8060 6732 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 6733 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 6734 "TARGET_THUMB1 && flag_pic"
8c4d8060 6735 "ldr\\t%0, %1"
a2cd141b 6736 [(set_attr "type" "load1")
42e1de19 6737 (set (attr "pool_range") (const_int 1018))]
cffb2a26 6738)
849170fd 6739
cffb2a26 6740(define_insn "pic_add_dot_plus_four"
15d5d060 6741 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6742 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6743 (const_int 4)
beef0fb5 6744 (match_operand 2 "" "")]
6745 UNSPEC_PIC_BASE))]
b3cd5f55 6746 "TARGET_THUMB"
cffb2a26 6747 "*
6cdcb15c 6748 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6749 INTVAL (operands[2]));
cffb2a26 6750 return \"add\\t%0, %|pc\";
6751 "
6752 [(set_attr "length" "2")]
6753)
849170fd 6754
6755(define_insn "pic_add_dot_plus_eight"
15d5d060 6756 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6757 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6758 (const_int 8)
beef0fb5 6759 (match_operand 2 "" "")]
6760 UNSPEC_PIC_BASE))]
f655717d 6761 "TARGET_ARM"
c4034607 6762 "*
6cdcb15c 6763 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6764 INTVAL (operands[2]));
15d5d060 6765 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 6766 "
0d66636f 6767 [(set_attr "predicable" "yes")]
cffb2a26 6768)
849170fd 6769
f655717d 6770(define_insn "tls_load_dot_plus_eight"
cc071db6 6771 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6772 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6773 (const_int 8)
beef0fb5 6774 (match_operand 2 "" "")]
6775 UNSPEC_PIC_BASE)))]
f655717d 6776 "TARGET_ARM"
6777 "*
6cdcb15c 6778 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6779 INTVAL (operands[2]));
f655717d 6780 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6781 "
6782 [(set_attr "predicable" "yes")]
6783)
6784
6785;; PIC references to local variables can generate pic_add_dot_plus_eight
6786;; followed by a load. These sequences can be crunched down to
6787;; tls_load_dot_plus_eight by a peephole.
6788
6789(define_peephole2
c0c1fba5 6790 [(set (match_operand:SI 0 "register_operand" "")
6791 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6792 (const_int 8)
6793 (match_operand 1 "" "")]
6794 UNSPEC_PIC_BASE))
2d05dfad 6795 (set (match_operand:SI 2 "arm_general_register_operand" "")
6796 (mem:SI (match_dup 0)))]
f655717d 6797 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 6798 [(set (match_dup 2)
6799 (mem:SI (unspec:SI [(match_dup 3)
6800 (const_int 8)
6801 (match_dup 1)]
6802 UNSPEC_PIC_BASE)))]
f655717d 6803 ""
6804)
6805
bac7fc85 6806(define_insn "pic_offset_arm"
6807 [(set (match_operand:SI 0 "register_operand" "=r")
6808 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6809 (unspec:SI [(match_operand:SI 2 "" "X")]
6810 UNSPEC_PIC_OFFSET))))]
6811 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6812 "ldr%?\\t%0, [%1,%2]"
6813 [(set_attr "type" "load1")]
6814)
6815
95373f08 6816(define_expand "builtin_setjmp_receiver"
6817 [(label_ref (match_operand 0 "" ""))]
6818 "flag_pic"
6819 "
6820{
b935b306 6821 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6822 register. */
2cb7d577 6823 if (arm_pic_register != INVALID_REGNUM)
6824 arm_load_pic_register (1UL << 3);
95373f08 6825 DONE;
6826}")
6827
9c08d1fa 6828;; If copying one reg to another we can set the condition codes according to
6829;; its value. Such a move is common after a return from subroutine and the
6830;; result is being tested against zero.
6831
f7fbdd4a 6832(define_insn "*movsi_compare0"
bd5b4116 6833 [(set (reg:CC CC_REGNUM)
cffb2a26 6834 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6835 (const_int 0)))
6836 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6837 (match_dup 1))]
25f905c2 6838 "TARGET_32BIT"
e2348bcb 6839 "@
40dbec34 6840 cmp%?\\t%0, #0
25f905c2 6841 sub%.\\t%0, %1, #0"
65f68e55 6842 [(set_attr "conds" "set")
6b6abc9c 6843 (set_attr "type" "arlo_imm,arlo_imm")]
cffb2a26 6844)
b11cae9e 6845
b11cae9e 6846;; Subroutine to store a half word from a register into memory.
6847;; Operand 0 is the source register (HImode)
c8f69309 6848;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6849
9c08d1fa 6850;; In both this routine and the next, we must be careful not to spill
01cc3b75 6851;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6852;; can generate unrecognizable rtl.
6853
b11cae9e 6854(define_expand "storehi"
c8f69309 6855 [;; store the low byte
f082f1c4 6856 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6857 ;; extract the high byte
c8f69309 6858 (set (match_dup 2)
6859 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6860 ;; store the high byte
787f8210 6861 (set (match_dup 4) (match_dup 5))]
cffb2a26 6862 "TARGET_ARM"
b11cae9e 6863 "
215b30b3 6864 {
537ffcfc 6865 rtx op1 = operands[1];
6866 rtx addr = XEXP (op1, 0);
215b30b3 6867 enum rtx_code code = GET_CODE (addr);
6868
0438d37f 6869 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6870 || code == MINUS)
537ffcfc 6871 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6872
537ffcfc 6873 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6874 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6875 operands[3] = gen_lowpart (QImode, operands[0]);
6876 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6877 operands[2] = gen_reg_rtx (SImode);
6878 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6879 }"
6880)
b11cae9e 6881
c7597b5d 6882(define_expand "storehi_bigend"
f082f1c4 6883 [(set (match_dup 4) (match_dup 3))
c7597b5d 6884 (set (match_dup 2)
6885 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6886 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6887 "TARGET_ARM"
b11cae9e 6888 "
215b30b3 6889 {
537ffcfc 6890 rtx op1 = operands[1];
6891 rtx addr = XEXP (op1, 0);
215b30b3 6892 enum rtx_code code = GET_CODE (addr);
6893
0438d37f 6894 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6895 || code == MINUS)
537ffcfc 6896 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6897
537ffcfc 6898 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6899 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6900 operands[3] = gen_lowpart (QImode, operands[0]);
6901 operands[0] = gen_lowpart (SImode, operands[0]);
6902 operands[2] = gen_reg_rtx (SImode);
787f8210 6903 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6904 }"
6905)
c7597b5d 6906
6907;; Subroutine to store a half word integer constant into memory.
6908(define_expand "storeinthi"
f082f1c4 6909 [(set (match_operand 0 "" "")
787f8210 6910 (match_operand 1 "" ""))
9e8503e6 6911 (set (match_dup 3) (match_dup 2))]
cffb2a26 6912 "TARGET_ARM"
c7597b5d 6913 "
215b30b3 6914 {
6915 HOST_WIDE_INT value = INTVAL (operands[1]);
6916 rtx addr = XEXP (operands[0], 0);
537ffcfc 6917 rtx op0 = operands[0];
215b30b3 6918 enum rtx_code code = GET_CODE (addr);
c7597b5d 6919
0438d37f 6920 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6921 || code == MINUS)
537ffcfc 6922 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6923
215b30b3 6924 operands[1] = gen_reg_rtx (SImode);
6925 if (BYTES_BIG_ENDIAN)
6926 {
6927 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6928 if ((value & 255) == ((value >> 8) & 255))
6929 operands[2] = operands[1];
6930 else
6931 {
6932 operands[2] = gen_reg_rtx (SImode);
6933 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6934 }
6935 }
6936 else
6937 {
6938 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6939 if ((value & 255) == ((value >> 8) & 255))
6940 operands[2] = operands[1];
6941 else
6942 {
6943 operands[2] = gen_reg_rtx (SImode);
6944 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6945 }
6946 }
c7597b5d 6947
537ffcfc 6948 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6949 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6950 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6951 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6952 }"
6953)
b11cae9e 6954
f7fbdd4a 6955(define_expand "storehi_single_op"
6956 [(set (match_operand:HI 0 "memory_operand" "")
6957 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6958 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6959 "
215b30b3 6960 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6961 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6962 "
6963)
f7fbdd4a 6964
b11cae9e 6965(define_expand "movhi"
6966 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6967 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6968 "TARGET_EITHER"
b11cae9e 6969 "
cffb2a26 6970 if (TARGET_ARM)
b11cae9e 6971 {
e1ba4a27 6972 if (can_create_pseudo_p ())
cffb2a26 6973 {
0438d37f 6974 if (MEM_P (operands[0]))
b11cae9e 6975 {
cffb2a26 6976 if (arm_arch4)
6977 {
6978 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6979 DONE;
6980 }
0438d37f 6981 if (CONST_INT_P (operands[1]))
cffb2a26 6982 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6983 else
cffb2a26 6984 {
0438d37f 6985 if (MEM_P (operands[1]))
cffb2a26 6986 operands[1] = force_reg (HImode, operands[1]);
6987 if (BYTES_BIG_ENDIAN)
6988 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6989 else
6990 emit_insn (gen_storehi (operands[1], operands[0]));
6991 }
6992 DONE;
b11cae9e 6993 }
cffb2a26 6994 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6995 else if (CONST_INT_P (operands[1]))
9c08d1fa 6996 {
cffb2a26 6997 rtx reg = gen_reg_rtx (SImode);
6998 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6999
7000 /* If the constant is already valid, leave it alone. */
215b30b3 7001 if (!const_ok_for_arm (val))
cffb2a26 7002 {
7003 /* If setting all the top bits will make the constant
7004 loadable in a single instruction, then set them.
7005 Otherwise, sign extend the number. */
7006
215b30b3 7007 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 7008 val |= ~0xffff;
7009 else if (val & 0x8000)
7010 val |= ~0xffff;
7011 }
7012
7013 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 7014 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 7015 }
e1ba4a27 7016 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 7017 && MEM_P (operands[1]))
0045890a 7018 {
7019 rtx reg = gen_reg_rtx (SImode);
7020
7021 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
7022 operands[1] = gen_lowpart (HImode, reg);
7023 }
215b30b3 7024 else if (!arm_arch4)
f7fbdd4a 7025 {
0438d37f 7026 if (MEM_P (operands[1]))
cffb2a26 7027 {
c1a66faf 7028 rtx base;
7029 rtx offset = const0_rtx;
7030 rtx reg = gen_reg_rtx (SImode);
7031
0438d37f 7032 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 7033 || (GET_CODE (base) == PLUS
0438d37f 7034 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 7035 && ((INTVAL(offset) & 1) != 1)
0438d37f 7036 && REG_P (base = XEXP (base, 0))))
c1a66faf 7037 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 7038 {
8deb3959 7039 rtx new_rtx;
c1a66faf 7040
8deb3959 7041 new_rtx = widen_memory_access (operands[1], SImode,
7042 ((INTVAL (offset) & ~3)
7043 - INTVAL (offset)));
7044 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 7045 if (((INTVAL (offset) & 2) != 0)
7046 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
7047 {
7048 rtx reg2 = gen_reg_rtx (SImode);
7049
7050 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
7051 reg = reg2;
7052 }
206ee9a2 7053 }
c1a66faf 7054 else
7055 emit_insn (gen_movhi_bytes (reg, operands[1]));
7056
7057 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 7058 }
7059 }
7060 }
674a8f0b 7061 /* Handle loading a large integer during reload. */
0438d37f 7062 else if (CONST_INT_P (operands[1])
215b30b3 7063 && !const_ok_for_arm (INTVAL (operands[1]))
7064 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 7065 {
7066 /* Writing a constant to memory needs a scratch, which should
7067 be handled with SECONDARY_RELOADs. */
0438d37f 7068 gcc_assert (REG_P (operands[0]));
cffb2a26 7069
7070 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
7071 emit_insn (gen_movsi (operands[0], operands[1]));
7072 DONE;
7073 }
7074 }
25f905c2 7075 else if (TARGET_THUMB2)
7076 {
7077 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 7078 if (can_create_pseudo_p ())
25f905c2 7079 {
0438d37f 7080 if (!REG_P (operands[0]))
25f905c2 7081 operands[1] = force_reg (HImode, operands[1]);
7082 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 7083 else if (CONST_INT_P (operands[1]))
25f905c2 7084 {
7085 rtx reg = gen_reg_rtx (SImode);
7086 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
7087
7088 emit_insn (gen_movsi (reg, GEN_INT (val)));
7089 operands[1] = gen_lowpart (HImode, reg);
7090 }
7091 }
7092 }
7093 else /* TARGET_THUMB1 */
cffb2a26 7094 {
e1ba4a27 7095 if (can_create_pseudo_p ())
cffb2a26 7096 {
0438d37f 7097 if (CONST_INT_P (operands[1]))
6cffc037 7098 {
7099 rtx reg = gen_reg_rtx (SImode);
7100
7101 emit_insn (gen_movsi (reg, operands[1]));
7102 operands[1] = gen_lowpart (HImode, reg);
7103 }
cffb2a26 7104
7105 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 7106 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 7107 virtual register (also rejected as illegitimate for HImode/QImode)
7108 relative address. */
cffb2a26 7109 /* ??? This should perhaps be fixed elsewhere, for instance, in
7110 fixup_stack_1, by checking for other kinds of invalid addresses,
7111 e.g. a bare reference to a virtual register. This may confuse the
7112 alpha though, which must handle this case differently. */
0438d37f 7113 if (MEM_P (operands[0])
215b30b3 7114 && !memory_address_p (GET_MODE (operands[0]),
7115 XEXP (operands[0], 0)))
537ffcfc 7116 operands[0]
7117 = replace_equiv_address (operands[0],
7118 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 7119
0438d37f 7120 if (MEM_P (operands[1])
215b30b3 7121 && !memory_address_p (GET_MODE (operands[1]),
7122 XEXP (operands[1], 0)))
537ffcfc 7123 operands[1]
7124 = replace_equiv_address (operands[1],
7125 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 7126
0438d37f 7127 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 7128 {
7129 rtx reg = gen_reg_rtx (SImode);
7130
7131 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
7132 operands[1] = gen_lowpart (HImode, reg);
7133 }
7134
0438d37f 7135 if (MEM_P (operands[0]))
6cffc037 7136 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 7137 }
0438d37f 7138 else if (CONST_INT_P (operands[1])
234f6557 7139 && !satisfies_constraint_I (operands[1]))
cffb2a26 7140 {
6cffc037 7141 /* Handle loading a large integer during reload. */
7142
cffb2a26 7143 /* Writing a constant to memory needs a scratch, which should
7144 be handled with SECONDARY_RELOADs. */
0438d37f 7145 gcc_assert (REG_P (operands[0]));
cffb2a26 7146
1a83b3ff 7147 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 7148 emit_insn (gen_movsi (operands[0], operands[1]));
7149 DONE;
7150 }
b11cae9e 7151 }
cffb2a26 7152 "
7153)
7154
25f905c2 7155(define_insn "*thumb1_movhi_insn"
a941568e 7156 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
7157 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 7158 "TARGET_THUMB1
cffb2a26 7159 && ( register_operand (operands[0], HImode)
7160 || register_operand (operands[1], HImode))"
7161 "*
7162 switch (which_alternative)
d79300ac 7163 {
cffb2a26 7164 case 0: return \"add %0, %1, #0\";
7165 case 2: return \"strh %1, %0\";
7166 case 3: return \"mov %0, %1\";
7167 case 4: return \"mov %0, %1\";
7168 case 5: return \"mov %0, %1\";
ed29c566 7169 default: gcc_unreachable ();
cffb2a26 7170 case 1:
7171 /* The stack pointer can end up being taken as an index register.
7172 Catch this case here and deal with it. */
7173 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
0438d37f 7174 && REG_P (XEXP (XEXP (operands[1], 0), 0))
cffb2a26 7175 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
7176 {
7177 rtx ops[2];
7178 ops[0] = operands[0];
7179 ops[1] = XEXP (XEXP (operands[1], 0), 0);
7180
7181 output_asm_insn (\"mov %0, %1\", ops);
7182
7183 XEXP (XEXP (operands[1], 0), 0) = operands[0];
7184
7185 }
7186 return \"ldrh %0, %1\";
7187 }"
7188 [(set_attr "length" "2,4,2,2,2,2")
747b7458 7189 (set_attr "type" "*,load1,store1,*,*,*")
7190 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 7191
b11cae9e 7192
25f7a26e 7193(define_expand "movhi_bytes"
eab14235 7194 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 7195 (set (match_dup 3)
eab14235 7196 (zero_extend:SI (match_dup 6)))
25f7a26e 7197 (set (match_operand:SI 0 "" "")
7198 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 7199 "TARGET_ARM"
25f7a26e 7200 "
215b30b3 7201 {
7202 rtx mem1, mem2;
7203 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
7204
788fcce0 7205 mem1 = change_address (operands[1], QImode, addr);
29c05e22 7206 mem2 = change_address (operands[1], QImode,
7207 plus_constant (Pmode, addr, 1));
215b30b3 7208 operands[0] = gen_lowpart (SImode, operands[0]);
7209 operands[1] = mem1;
7210 operands[2] = gen_reg_rtx (SImode);
7211 operands[3] = gen_reg_rtx (SImode);
7212 operands[6] = mem2;
25f7a26e 7213
215b30b3 7214 if (BYTES_BIG_ENDIAN)
7215 {
7216 operands[4] = operands[2];
7217 operands[5] = operands[3];
7218 }
7219 else
7220 {
7221 operands[4] = operands[3];
7222 operands[5] = operands[2];
7223 }
7224 }"
7225)
25f7a26e 7226
c7597b5d 7227(define_expand "movhi_bigend"
7228 [(set (match_dup 2)
7229 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
7230 (const_int 16)))
7231 (set (match_dup 3)
7232 (ashiftrt:SI (match_dup 2) (const_int 16)))
7233 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 7234 (match_dup 4))]
cffb2a26 7235 "TARGET_ARM"
c7597b5d 7236 "
7237 operands[2] = gen_reg_rtx (SImode);
7238 operands[3] = gen_reg_rtx (SImode);
787f8210 7239 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 7240 "
7241)
b11cae9e 7242
a2f10574 7243;; Pattern to recognize insn generated default case above
f7fbdd4a 7244(define_insn "*movhi_insn_arch4"
cde1623a 7245 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 7246 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 7247 "TARGET_ARM
7248 && arm_arch4
85e02ccb 7249 && (register_operand (operands[0], HImode)
7250 || register_operand (operands[1], HImode))"
f7fbdd4a 7251 "@
7252 mov%?\\t%0, %1\\t%@ movhi
7253 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 7254 str%(h%)\\t%1, %0\\t%@ movhi
7255 ldr%(h%)\\t%0, %1\\t%@ movhi"
65f68e55 7256 [(set_attr "predicable" "yes")
cffb2a26 7257 (set_attr "pool_range" "*,*,*,256")
65f68e55 7258 (set_attr "neg_pool_range" "*,*,*,244")
7259 (set_attr_alternative "type"
7260 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7261 (const_string "mov_imm" )
7262 (const_string "mov_reg"))
7263 (const_string "mvn_imm")
65f68e55 7264 (const_string "store1")
7265 (const_string "load1")])]
cffb2a26 7266)
f7fbdd4a 7267
f7fbdd4a 7268(define_insn "*movhi_bytes"
65f68e55 7269 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
7270 (match_operand:HI 1 "arm_rhs_operand" "I,r,K"))]
c1a66faf 7271 "TARGET_ARM"
25f7a26e 7272 "@
65f68e55 7273 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 7274 mov%?\\t%0, %1\\t%@ movhi
0d66636f 7275 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 7276 [(set_attr "predicable" "yes")
1aed5204 7277 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 7278)
25f7a26e 7279
f90b51f1 7280(define_expand "thumb_movhi_clobber"
7281 [(set (match_operand:HI 0 "memory_operand" "")
7282 (match_operand:HI 1 "register_operand" ""))
7283 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 7284 "TARGET_THUMB1"
f90b51f1 7285 "
7286 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
7287 && REGNO (operands[1]) <= LAST_LO_REGNUM)
7288 {
7289 emit_insn (gen_movhi (operands[0], operands[1]));
7290 DONE;
7291 }
7292 /* XXX Fixme, need to handle other cases here as well. */
7293 gcc_unreachable ();
7294 "
cffb2a26 7295)
7296
bc5c7e08 7297;; We use a DImode scratch because we may occasionally need an additional
7298;; temporary if the address isn't offsettable -- push_reload doesn't seem
7299;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 7300(define_expand "reload_outhi"
cffb2a26 7301 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 7302 (match_operand:HI 1 "s_register_operand" "r")
7303 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 7304 "TARGET_EITHER"
7305 "if (TARGET_ARM)
7306 arm_reload_out_hi (operands);
7307 else
7308 thumb_reload_out_hi (operands);
d3373b54 7309 DONE;
cffb2a26 7310 "
7311)
d3373b54 7312
25f7a26e 7313(define_expand "reload_inhi"
7314 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 7315 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 7316 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 7317 "TARGET_EITHER"
25f7a26e 7318 "
cffb2a26 7319 if (TARGET_ARM)
7320 arm_reload_in_hi (operands);
7321 else
7322 thumb_reload_out_hi (operands);
25f7a26e 7323 DONE;
7324")
7325
9c08d1fa 7326(define_expand "movqi"
7327 [(set (match_operand:QI 0 "general_operand" "")
7328 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 7329 "TARGET_EITHER"
9c08d1fa 7330 "
6cffc037 7331 /* Everything except mem = const or mem = mem can be done easily */
0045890a 7332
e1ba4a27 7333 if (can_create_pseudo_p ())
cffb2a26 7334 {
0438d37f 7335 if (CONST_INT_P (operands[1]))
6cffc037 7336 {
7337 rtx reg = gen_reg_rtx (SImode);
7338
03770691 7339 /* For thumb we want an unsigned immediate, then we are more likely
7340 to be able to use a movs insn. */
7341 if (TARGET_THUMB)
7342 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
7343
6cffc037 7344 emit_insn (gen_movsi (reg, operands[1]));
7345 operands[1] = gen_lowpart (QImode, reg);
7346 }
cffb2a26 7347
6cffc037 7348 if (TARGET_THUMB)
7349 {
cffb2a26 7350 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 7351 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 7352 virtual register (also rejected as illegitimate for HImode/QImode)
7353 relative address. */
cffb2a26 7354 /* ??? This should perhaps be fixed elsewhere, for instance, in
7355 fixup_stack_1, by checking for other kinds of invalid addresses,
7356 e.g. a bare reference to a virtual register. This may confuse the
7357 alpha though, which must handle this case differently. */
0438d37f 7358 if (MEM_P (operands[0])
215b30b3 7359 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 7360 XEXP (operands[0], 0)))
537ffcfc 7361 operands[0]
7362 = replace_equiv_address (operands[0],
7363 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 7364 if (MEM_P (operands[1])
215b30b3 7365 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 7366 XEXP (operands[1], 0)))
537ffcfc 7367 operands[1]
7368 = replace_equiv_address (operands[1],
7369 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 7370 }
7371
0438d37f 7372 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 7373 {
7374 rtx reg = gen_reg_rtx (SImode);
7375
7376 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
7377 operands[1] = gen_lowpart (QImode, reg);
7378 }
7379
0438d37f 7380 if (MEM_P (operands[0]))
6cffc037 7381 operands[1] = force_reg (QImode, operands[1]);
7382 }
7383 else if (TARGET_THUMB
0438d37f 7384 && CONST_INT_P (operands[1])
234f6557 7385 && !satisfies_constraint_I (operands[1]))
6cffc037 7386 {
674a8f0b 7387 /* Handle loading a large integer during reload. */
cffb2a26 7388
6cffc037 7389 /* Writing a constant to memory needs a scratch, which should
7390 be handled with SECONDARY_RELOADs. */
0438d37f 7391 gcc_assert (REG_P (operands[0]));
6cffc037 7392
7393 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
7394 emit_insn (gen_movsi (operands[0], operands[1]));
7395 DONE;
cffb2a26 7396 }
7397 "
7398)
b11cae9e 7399
cffb2a26 7400(define_insn "*arm_movqi_insn"
fd711051 7401 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
7402 (match_operand:QI 1 "general_operand" "r,r,I,Py,K,Uu,l,m,r"))]
25f905c2 7403 "TARGET_32BIT
cffb2a26 7404 && ( register_operand (operands[0], QImode)
7405 || register_operand (operands[1], QImode))"
5565501b 7406 "@
fd711051 7407 mov%?\\t%0, %1
7408 mov%?\\t%0, %1
65f68e55 7409 mov%?\\t%0, %1
5565501b 7410 mov%?\\t%0, %1
7411 mvn%?\\t%0, #%B1
25f905c2 7412 ldr%(b%)\\t%0, %1
a54e3e7b 7413 str%(b%)\\t%1, %0
7414 ldr%(b%)\\t%0, %1
25f905c2 7415 str%(b%)\\t%1, %0"
1aed5204 7416 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 7417 (set_attr "predicable" "yes")
fd711051 7418 (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
7419 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
7420 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 7421)
7422
25f905c2 7423(define_insn "*thumb1_movqi_insn"
cffb2a26 7424 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 7425 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 7426 "TARGET_THUMB1
cffb2a26 7427 && ( register_operand (operands[0], QImode)
7428 || register_operand (operands[1], QImode))"
7429 "@
7430 add\\t%0, %1, #0
7431 ldrb\\t%0, %1
7432 strb\\t%1, %0
7433 mov\\t%0, %1
7434 mov\\t%0, %1
7435 mov\\t%0, %1"
7436 [(set_attr "length" "2")
1aed5204 7437 (set_attr "type" "arlo_imm,load1,store1,mov_reg,mov_imm,mov_imm")
747b7458 7438 (set_attr "pool_range" "*,32,*,*,*,*")
7439 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 7440
9b8516be 7441;; HFmode moves
7442(define_expand "movhf"
7443 [(set (match_operand:HF 0 "general_operand" "")
7444 (match_operand:HF 1 "general_operand" ""))]
7445 "TARGET_EITHER"
7446 "
7447 if (TARGET_32BIT)
7448 {
0438d37f 7449 if (MEM_P (operands[0]))
9b8516be 7450 operands[1] = force_reg (HFmode, operands[1]);
7451 }
7452 else /* TARGET_THUMB1 */
7453 {
7454 if (can_create_pseudo_p ())
7455 {
0438d37f 7456 if (!REG_P (operands[0]))
9b8516be 7457 operands[1] = force_reg (HFmode, operands[1]);
7458 }
7459 }
7460 "
7461)
7462
7463(define_insn "*arm32_movhf"
7464 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
7465 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
7c36fe71 7466 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16) && !arm_restrict_it
9b8516be 7467 && ( s_register_operand (operands[0], HFmode)
7468 || s_register_operand (operands[1], HFmode))"
7469 "*
7470 switch (which_alternative)
7471 {
7472 case 0: /* ARM register from memory */
7473 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
7474 case 1: /* memory from ARM register */
7475 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
7476 case 2: /* ARM register from ARM register */
7477 return \"mov%?\\t%0, %1\\t%@ __fp16\";
7478 case 3: /* ARM register from constant */
7479 {
7480 REAL_VALUE_TYPE r;
7481 long bits;
7482 rtx ops[4];
7483
7484 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
7485 bits = real_to_target (NULL, &r, HFmode);
7486 ops[0] = operands[0];
7487 ops[1] = GEN_INT (bits);
7488 ops[2] = GEN_INT (bits & 0xff00);
7489 ops[3] = GEN_INT (bits & 0x00ff);
7490
7491 if (arm_arch_thumb2)
7492 output_asm_insn (\"movw%?\\t%0, %1\", ops);
7493 else
7494 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
7495 return \"\";
7496 }
7497 default:
7498 gcc_unreachable ();
7499 }
7500 "
7501 [(set_attr "conds" "unconditional")
1aed5204 7502 (set_attr "type" "load1,store1,mov_reg,mov_reg")
9b8516be 7503 (set_attr "length" "4,4,4,8")
d2a518d1 7504 (set_attr "predicable" "yes")]
9b8516be 7505)
7506
7507(define_insn "*thumb1_movhf"
7508 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
7509 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
7510 "TARGET_THUMB1
7511 && ( s_register_operand (operands[0], HFmode)
7512 || s_register_operand (operands[1], HFmode))"
7513 "*
7514 switch (which_alternative)
7515 {
7516 case 1:
7517 {
7518 rtx addr;
0438d37f 7519 gcc_assert (MEM_P (operands[1]));
9b8516be 7520 addr = XEXP (operands[1], 0);
7521 if (GET_CODE (addr) == LABEL_REF
7522 || (GET_CODE (addr) == CONST
7523 && GET_CODE (XEXP (addr, 0)) == PLUS
7524 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
0438d37f 7525 && CONST_INT_P (XEXP (XEXP (addr, 0), 1))))
9b8516be 7526 {
7527 /* Constant pool entry. */
7528 return \"ldr\\t%0, %1\";
7529 }
7530 return \"ldrh\\t%0, %1\";
7531 }
7532 case 2: return \"strh\\t%1, %0\";
7533 default: return \"mov\\t%0, %1\";
7534 }
7535 "
7536 [(set_attr "length" "2")
1aed5204 7537 (set_attr "type" "mov_reg,load1,store1,mov_reg,mov_reg")
42e1de19 7538 (set_attr "pool_range" "*,1018,*,*,*")
747b7458 7539 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 7540
87b22bf7 7541(define_expand "movsf"
7542 [(set (match_operand:SF 0 "general_operand" "")
7543 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 7544 "TARGET_EITHER"
87b22bf7 7545 "
25f905c2 7546 if (TARGET_32BIT)
cffb2a26 7547 {
0438d37f 7548 if (MEM_P (operands[0]))
cffb2a26 7549 operands[1] = force_reg (SFmode, operands[1]);
7550 }
25f905c2 7551 else /* TARGET_THUMB1 */
cffb2a26 7552 {
e1ba4a27 7553 if (can_create_pseudo_p ())
cffb2a26 7554 {
0438d37f 7555 if (!REG_P (operands[0]))
cffb2a26 7556 operands[1] = force_reg (SFmode, operands[1]);
7557 }
7558 }
7559 "
7560)
7561
03d440a6 7562;; Transform a floating-point move of a constant into a core register into
7563;; an SImode operation.
cffb2a26 7564(define_split
03d440a6 7565 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 7566 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 7567 "TARGET_EITHER
cffb2a26 7568 && reload_completed
0438d37f 7569 && CONST_DOUBLE_P (operands[1])"
cffb2a26 7570 [(set (match_dup 2) (match_dup 3))]
7571 "
7572 operands[2] = gen_lowpart (SImode, operands[0]);
7573 operands[3] = gen_lowpart (SImode, operands[1]);
7574 if (operands[2] == 0 || operands[3] == 0)
7575 FAIL;
215b30b3 7576 "
7577)
87b22bf7 7578
cffb2a26 7579(define_insn "*arm_movsf_soft_insn"
7580 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
7581 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 7582 "TARGET_32BIT
cffb2a26 7583 && TARGET_SOFT_FLOAT
0438d37f 7584 && (!MEM_P (operands[0])
215b30b3 7585 || register_operand (operands[1], SFmode))"
9a1112d7 7586 "@
7587 mov%?\\t%0, %1
7588 ldr%?\\t%0, %1\\t%@ float
7589 str%?\\t%1, %0\\t%@ float"
cde1623a 7590 [(set_attr "predicable" "yes")
7c36fe71 7591 (set_attr "predicable_short_it" "no")
1aed5204 7592 (set_attr "type" "mov_reg,load1,store1")
42e1de19 7593 (set_attr "arm_pool_range" "*,4096,*")
7594 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 7595 (set_attr "arm_neg_pool_range" "*,4084,*")
7596 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 7597)
7598
7599;;; ??? This should have alternatives for constants.
25f905c2 7600(define_insn "*thumb1_movsf_insn"
215b30b3 7601 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
7602 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 7603 "TARGET_THUMB1
cffb2a26 7604 && ( register_operand (operands[0], SFmode)
7605 || register_operand (operands[1], SFmode))"
7606 "@
7607 add\\t%0, %1, #0
7608 ldmia\\t%1, {%0}
7609 stmia\\t%0, {%1}
7610 ldr\\t%0, %1
7611 str\\t%1, %0
7612 mov\\t%0, %1
7613 mov\\t%0, %1"
7614 [(set_attr "length" "2")
1aed5204 7615 (set_attr "type" "*,load1,store1,load1,store1,mov_reg,mov_reg")
42e1de19 7616 (set_attr "pool_range" "*,*,*,1018,*,*,*")
747b7458 7617 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 7618)
9a1112d7 7619
9c08d1fa 7620(define_expand "movdf"
87b22bf7 7621 [(set (match_operand:DF 0 "general_operand" "")
7622 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 7623 "TARGET_EITHER"
9c08d1fa 7624 "
25f905c2 7625 if (TARGET_32BIT)
cffb2a26 7626 {
0438d37f 7627 if (MEM_P (operands[0]))
cffb2a26 7628 operands[1] = force_reg (DFmode, operands[1]);
7629 }
7630 else /* TARGET_THUMB */
7631 {
e1ba4a27 7632 if (can_create_pseudo_p ())
cffb2a26 7633 {
0438d37f 7634 if (!REG_P (operands[0]))
cffb2a26 7635 operands[1] = force_reg (DFmode, operands[1]);
7636 }
7637 }
7638 "
7639)
b11cae9e 7640
9c08d1fa 7641;; Reloading a df mode value stored in integer regs to memory can require a
7642;; scratch reg.
7643(define_expand "reload_outdf"
cffb2a26 7644 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 7645 (match_operand:DF 1 "s_register_operand" "r")
7646 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 7647 "TARGET_THUMB2"
87b22bf7 7648 "
215b30b3 7649 {
7650 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 7651
215b30b3 7652 if (code == REG)
7653 operands[2] = XEXP (operands[0], 0);
7654 else if (code == POST_INC || code == PRE_DEC)
7655 {
7656 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7657 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7658 emit_insn (gen_movdi (operands[0], operands[1]));
7659 DONE;
7660 }
7661 else if (code == PRE_INC)
7662 {
7663 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 7664
215b30b3 7665 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7666 operands[2] = reg;
7667 }
7668 else if (code == POST_DEC)
7669 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7670 else
7671 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7672 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 7673
788fcce0 7674 emit_insn (gen_rtx_SET (VOIDmode,
7675 replace_equiv_address (operands[0], operands[2]),
215b30b3 7676 operands[1]));
f7fbdd4a 7677
215b30b3 7678 if (code == POST_DEC)
7679 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7680
7681 DONE;
7682 }"
7683)
9c08d1fa 7684
9a1112d7 7685(define_insn "*movdf_soft_insn"
353cf59a 7686 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
7687 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 7688 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 7689 && ( register_operand (operands[0], DFmode)
7690 || register_operand (operands[1], DFmode))"
d51f92df 7691 "*
7692 switch (which_alternative)
7693 {
7694 case 0:
7695 case 1:
7696 case 2:
7697 return \"#\";
7698 default:
26ff80c0 7699 return output_move_double (operands, true, NULL);
d51f92df 7700 }
7701 "
359a6e9f 7702 [(set_attr "length" "8,12,16,8,8")
7703 (set_attr "type" "*,*,*,load2,store2")
42e1de19 7704 (set_attr "arm_pool_range" "*,*,*,1020,*")
7705 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 7706 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 7707 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 7708)
7709
7710;;; ??? This should have alternatives for constants.
7711;;; ??? This was originally identical to the movdi_insn pattern.
7712;;; ??? The 'F' constraint looks funny, but it should always be replaced by
7713;;; thumb_reorg with a memory reference.
7714(define_insn "*thumb_movdf_insn"
215b30b3 7715 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
7716 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 7717 "TARGET_THUMB1
cffb2a26 7718 && ( register_operand (operands[0], DFmode)
7719 || register_operand (operands[1], DFmode))"
7720 "*
7721 switch (which_alternative)
7722 {
7723 default:
7724 case 0:
7725 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
7726 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
7727 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
7728 case 1:
7729 return \"ldmia\\t%1, {%0, %H0}\";
7730 case 2:
7731 return \"stmia\\t%0, {%1, %H1}\";
7732 case 3:
7733 return thumb_load_double_from_address (operands);
7734 case 4:
1a83b3ff 7735 operands[2] = gen_rtx_MEM (SImode,
29c05e22 7736 plus_constant (Pmode,
7737 XEXP (operands[0], 0), 4));
cffb2a26 7738 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
7739 return \"\";
7740 case 5:
7741 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
7742 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
7743 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
7744 }
7745 "
7746 [(set_attr "length" "4,2,2,6,4,4")
1aed5204 7747 (set_attr "type" "*,load2,store2,load2,store2,mov_reg")
42e1de19 7748 (set_attr "pool_range" "*,*,*,1018,*,*")]
cffb2a26 7749)
b11cae9e 7750\f
b11cae9e 7751
9c08d1fa 7752;; load- and store-multiple insns
7753;; The arm can load/store any set of registers, provided that they are in
320ea44d 7754;; ascending order, but these expanders assume a contiguous set.
b11cae9e 7755
9c08d1fa 7756(define_expand "load_multiple"
7757 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7758 (match_operand:SI 1 "" ""))
7759 (use (match_operand:SI 2 "" ""))])]
25f905c2 7760 "TARGET_32BIT"
9580c25f 7761{
7762 HOST_WIDE_INT offset = 0;
7763
bd5b4116 7764 /* Support only fixed point registers. */
0438d37f 7765 if (!CONST_INT_P (operands[2])
9c08d1fa 7766 || INTVAL (operands[2]) > 14
7767 || INTVAL (operands[2]) < 2
0438d37f 7768 || !MEM_P (operands[1])
7769 || !REG_P (operands[0])
bd5b4116 7770 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7771 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7772 FAIL;
7773
7774 operands[3]
320ea44d 7775 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7776 INTVAL (operands[2]),
f082f1c4 7777 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 7778 FALSE, operands[1], &offset);
9580c25f 7779})
b11cae9e 7780
9c08d1fa 7781(define_expand "store_multiple"
7782 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7783 (match_operand:SI 1 "" ""))
7784 (use (match_operand:SI 2 "" ""))])]
25f905c2 7785 "TARGET_32BIT"
9580c25f 7786{
7787 HOST_WIDE_INT offset = 0;
7788
674a8f0b 7789 /* Support only fixed point registers. */
0438d37f 7790 if (!CONST_INT_P (operands[2])
9c08d1fa 7791 || INTVAL (operands[2]) > 14
7792 || INTVAL (operands[2]) < 2
0438d37f 7793 || !REG_P (operands[1])
7794 || !MEM_P (operands[0])
bd5b4116 7795 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7796 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7797 FAIL;
7798
7799 operands[3]
320ea44d 7800 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7801 INTVAL (operands[2]),
f082f1c4 7802 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 7803 FALSE, operands[0], &offset);
9580c25f 7804})
b11cae9e 7805
9c08d1fa 7806
7807;; Move a block of memory if it is word aligned and MORE than 2 words long.
7808;; We could let this apply for blocks of less than this, but it clobbers so
7809;; many registers that there is then probably a better way.
7810
008c057d 7811(define_expand "movmemqi"
34191dd1 7812 [(match_operand:BLK 0 "general_operand" "")
7813 (match_operand:BLK 1 "general_operand" "")
7814 (match_operand:SI 2 "const_int_operand" "")
7815 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 7816 ""
9c08d1fa 7817 "
25f905c2 7818 if (TARGET_32BIT)
cffb2a26 7819 {
ae51a965 7820 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7821 && !optimize_function_for_size_p (cfun))
7822 {
7823 if (gen_movmem_ldrd_strd (operands))
7824 DONE;
7825 FAIL;
7826 }
7827
008c057d 7828 if (arm_gen_movmemqi (operands))
cffb2a26 7829 DONE;
7830 FAIL;
7831 }
25f905c2 7832 else /* TARGET_THUMB1 */
cffb2a26 7833 {
7834 if ( INTVAL (operands[3]) != 4
7835 || INTVAL (operands[2]) > 48)
7836 FAIL;
7837
008c057d 7838 thumb_expand_movmemqi (operands);
cffb2a26 7839 DONE;
7840 }
7841 "
7842)
7843
2162064c 7844;; Thumb block-move insns
cffb2a26 7845
7846(define_insn "movmem12b"
960f3acf 7847 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
7848 (mem:SI (match_operand:SI 3 "register_operand" "1")))
7849 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
7850 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
7851 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
7852 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
7853 (set (match_operand:SI 0 "register_operand" "=l")
7854 (plus:SI (match_dup 2) (const_int 12)))
7855 (set (match_operand:SI 1 "register_operand" "=l")
7856 (plus:SI (match_dup 3) (const_int 12)))
7857 (clobber (match_scratch:SI 4 "=&l"))
7858 (clobber (match_scratch:SI 5 "=&l"))
7859 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 7860 "TARGET_THUMB1"
cffb2a26 7861 "* return thumb_output_move_mem_multiple (3, operands);"
7862 [(set_attr "length" "4")
215b30b3 7863 ; This isn't entirely accurate... It loads as well, but in terms of
7864 ; scheduling the following insn it is better to consider it as a store
cffb2a26 7865 (set_attr "type" "store3")]
7866)
7867
7868(define_insn "movmem8b"
960f3acf 7869 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
7870 (mem:SI (match_operand:SI 3 "register_operand" "1")))
7871 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
7872 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
7873 (set (match_operand:SI 0 "register_operand" "=l")
7874 (plus:SI (match_dup 2) (const_int 8)))
7875 (set (match_operand:SI 1 "register_operand" "=l")
7876 (plus:SI (match_dup 3) (const_int 8)))
7877 (clobber (match_scratch:SI 4 "=&l"))
7878 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 7879 "TARGET_THUMB1"
cffb2a26 7880 "* return thumb_output_move_mem_multiple (2, operands);"
7881 [(set_attr "length" "4")
215b30b3 7882 ; This isn't entirely accurate... It loads as well, but in terms of
7883 ; scheduling the following insn it is better to consider it as a store
cffb2a26 7884 (set_attr "type" "store2")]
7885)
7886
9c08d1fa 7887\f
b11cae9e 7888
341940e8 7889;; Compare & branch insns
8d232dc7 7890;; The range calculations are based as follows:
341940e8 7891;; For forward branches, the address calculation returns the address of
7892;; the next instruction. This is 2 beyond the branch instruction.
7893;; For backward branches, the address calculation returns the address of
7894;; the first instruction in this pattern (cmp). This is 2 before the branch
7895;; instruction for the shortest sequence, and 4 before the branch instruction
7896;; if we have to jump around an unconditional branch.
7897;; To the basic branch range the PC offset must be added (this is +4).
7898;; So for forward branches we have
7899;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7900;; And for backward branches we have
7901;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7902;;
7903;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7904;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 7905
aeac46d4 7906(define_expand "cbranchsi4"
7907 [(set (pc) (if_then_else
aa06947a 7908 (match_operator 0 "expandable_comparison_operator"
aeac46d4 7909 [(match_operand:SI 1 "s_register_operand" "")
7910 (match_operand:SI 2 "nonmemory_operand" "")])
7911 (label_ref (match_operand 3 "" ""))
7912 (pc)))]
f9aa4160 7913 "TARGET_EITHER"
aeac46d4 7914 "
74f4459c 7915 if (!TARGET_THUMB1)
7916 {
f9aa4160 7917 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7918 FAIL;
74f4459c 7919 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7920 operands[3]));
7921 DONE;
7922 }
25f905c2 7923 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 7924 {
7925 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7926 operands[3], operands[0]));
7927 DONE;
7928 }
25f905c2 7929 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 7930 operands[2] = force_reg (SImode, operands[2]);
7931 ")
7932
a8e6c15d 7933;; A pattern to recognize a special situation and optimize for it.
7934;; On the thumb, zero-extension from memory is preferrable to sign-extension
7935;; due to the available addressing modes. Hence, convert a signed comparison
7936;; with zero into an unsigned comparison with 127 if possible.
7937(define_expand "cbranchqi4"
7938 [(set (pc) (if_then_else
7939 (match_operator 0 "lt_ge_comparison_operator"
7940 [(match_operand:QI 1 "memory_operand" "")
7941 (match_operand:QI 2 "const0_operand" "")])
7942 (label_ref (match_operand 3 "" ""))
7943 (pc)))]
7944 "TARGET_THUMB1"
7945{
d0f6c30d 7946 rtx xops[4];
a8e6c15d 7947 xops[1] = gen_reg_rtx (SImode);
7948 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
7949 xops[2] = GEN_INT (127);
7950 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
7951 VOIDmode, xops[1], xops[2]);
7952 xops[3] = operands[3];
7953 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
7954 DONE;
7955})
7956
74f4459c 7957(define_expand "cbranchsf4"
7958 [(set (pc) (if_then_else
aa06947a 7959 (match_operator 0 "expandable_comparison_operator"
74f4459c 7960 [(match_operand:SF 1 "s_register_operand" "")
7961 (match_operand:SF 2 "arm_float_compare_operand" "")])
7962 (label_ref (match_operand 3 "" ""))
7963 (pc)))]
7964 "TARGET_32BIT && TARGET_HARD_FLOAT"
7965 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7966 operands[3])); DONE;"
7967)
7968
7969(define_expand "cbranchdf4"
7970 [(set (pc) (if_then_else
aa06947a 7971 (match_operator 0 "expandable_comparison_operator"
74f4459c 7972 [(match_operand:DF 1 "s_register_operand" "")
7973 (match_operand:DF 2 "arm_float_compare_operand" "")])
7974 (label_ref (match_operand 3 "" ""))
7975 (pc)))]
a50d7267 7976 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7977 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7978 operands[3])); DONE;"
7979)
7980
74f4459c 7981(define_expand "cbranchdi4"
7982 [(set (pc) (if_then_else
aa06947a 7983 (match_operator 0 "expandable_comparison_operator"
b8eae306 7984 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 7985 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7986 (label_ref (match_operand 3 "" ""))
7987 (pc)))]
a8045a4f 7988 "TARGET_32BIT"
7989 "{
0438d37f 7990 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7991 FAIL;
7992 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7993 operands[3]));
7994 DONE;
7995 }"
74f4459c 7996)
7997
d60047aa 7998(define_insn "cbranchsi4_insn"
aeac46d4 7999 [(set (pc) (if_then_else
8000 (match_operator 0 "arm_comparison_operator"
747b7458 8001 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 8002 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 8003 (label_ref (match_operand 3 "" ""))
8004 (pc)))]
25f905c2 8005 "TARGET_THUMB1"
747b7458 8006{
8007 rtx t = cfun->machine->thumb1_cc_insn;
8008 if (t != NULL_RTX)
d60047aa 8009 {
747b7458 8010 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
8011 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
8012 t = NULL_RTX;
8013 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
8014 {
8015 if (!noov_comparison_operator (operands[0], VOIDmode))
8016 t = NULL_RTX;
8017 }
8018 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 8019 t = NULL_RTX;
8020 }
d60047aa 8021 if (t == NULL_RTX)
747b7458 8022 {
8023 output_asm_insn ("cmp\t%1, %2", operands);
8024 cfun->machine->thumb1_cc_insn = insn;
8025 cfun->machine->thumb1_cc_op0 = operands[1];
8026 cfun->machine->thumb1_cc_op1 = operands[2];
8027 cfun->machine->thumb1_cc_mode = CCmode;
8028 }
8029 else
8030 /* Ensure we emit the right type of condition code on the jump. */
8031 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
8032 CC_REGNUM);
aeac46d4 8033
cffb2a26 8034 switch (get_attr_length (insn))
8035 {
8036 case 4: return \"b%d0\\t%l3\";
8037 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
8038 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
8039 }
747b7458 8040}
cffb2a26 8041 [(set (attr "far_jump")
8042 (if_then_else
8043 (eq_attr "length" "8")
8044 (const_string "yes")
8045 (const_string "no")))
8046 (set (attr "length")
8047 (if_then_else
8048 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
8049 (le (minus (match_dup 3) (pc)) (const_int 256)))
8050 (const_int 4)
8051 (if_then_else
8052 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 8053 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 8054 (const_int 6)
8055 (const_int 8))))]
8056)
8057
aeac46d4 8058(define_insn "cbranchsi4_scratch"
8059 [(set (pc) (if_then_else
8060 (match_operator 4 "arm_comparison_operator"
8061 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 8062 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 8063 (label_ref (match_operand 3 "" ""))
8064 (pc)))
8065 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 8066 "TARGET_THUMB1"
aeac46d4 8067 "*
8068 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
8069
8070 switch (get_attr_length (insn))
8071 {
8072 case 4: return \"b%d4\\t%l3\";
8073 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
8074 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
8075 }
8076 "
8077 [(set (attr "far_jump")
8078 (if_then_else
8079 (eq_attr "length" "8")
8080 (const_string "yes")
8081 (const_string "no")))
8082 (set (attr "length")
8083 (if_then_else
8084 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
8085 (le (minus (match_dup 3) (pc)) (const_int 256)))
8086 (const_int 4)
8087 (if_then_else
8088 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
8089 (le (minus (match_dup 3) (pc)) (const_int 2048)))
8090 (const_int 6)
8091 (const_int 8))))]
8092)
446a1e96 8093
cffb2a26 8094(define_insn "*negated_cbranchsi4"
8095 [(set (pc)
8096 (if_then_else
aed179ae 8097 (match_operator 0 "equality_operator"
aeac46d4 8098 [(match_operand:SI 1 "s_register_operand" "l")
8099 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
8100 (label_ref (match_operand 3 "" ""))
215b30b3 8101 (pc)))]
25f905c2 8102 "TARGET_THUMB1"
cffb2a26 8103 "*
8104 output_asm_insn (\"cmn\\t%1, %2\", operands);
8105 switch (get_attr_length (insn))
8106 {
8107 case 4: return \"b%d0\\t%l3\";
8108 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
8109 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
8110 }
8111 "
8112 [(set (attr "far_jump")
8113 (if_then_else
8114 (eq_attr "length" "8")
8115 (const_string "yes")
8116 (const_string "no")))
8117 (set (attr "length")
8118 (if_then_else
8119 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 8120 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 8121 (const_int 4)
8122 (if_then_else
341940e8 8123 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
8124 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 8125 (const_int 6)
8126 (const_int 8))))]
8127)
8128
58d6528b 8129(define_insn "*tbit_cbranch"
8130 [(set (pc)
8131 (if_then_else
8132 (match_operator 0 "equality_operator"
8133 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
8134 (const_int 1)
8135 (match_operand:SI 2 "const_int_operand" "i"))
8136 (const_int 0)])
8137 (label_ref (match_operand 3 "" ""))
8138 (pc)))
8139 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 8140 "TARGET_THUMB1"
58d6528b 8141 "*
8142 {
8143 rtx op[3];
8144 op[0] = operands[4];
8145 op[1] = operands[1];
8146 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
8147
86efa74d 8148 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
8149 switch (get_attr_length (insn))
8150 {
8151 case 4: return \"b%d0\\t%l3\";
8152 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
8153 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
8154 }
8155 }"
8156 [(set (attr "far_jump")
8157 (if_then_else
8158 (eq_attr "length" "8")
8159 (const_string "yes")
8160 (const_string "no")))
8161 (set (attr "length")
8162 (if_then_else
8163 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
8164 (le (minus (match_dup 3) (pc)) (const_int 256)))
8165 (const_int 4)
8166 (if_then_else
8167 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
8168 (le (minus (match_dup 3) (pc)) (const_int 2048)))
8169 (const_int 6)
8170 (const_int 8))))]
8171)
8172
8173(define_insn "*tlobits_cbranch"
8174 [(set (pc)
8175 (if_then_else
8176 (match_operator 0 "equality_operator"
8177 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
8178 (match_operand:SI 2 "const_int_operand" "i")
8179 (const_int 0))
8180 (const_int 0)])
8181 (label_ref (match_operand 3 "" ""))
8182 (pc)))
8183 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 8184 "TARGET_THUMB1"
86efa74d 8185 "*
8186 {
8187 rtx op[3];
8188 op[0] = operands[4];
8189 op[1] = operands[1];
8190 op[2] = GEN_INT (32 - INTVAL (operands[2]));
8191
58d6528b 8192 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
8193 switch (get_attr_length (insn))
8194 {
8195 case 4: return \"b%d0\\t%l3\";
8196 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
8197 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
8198 }
8199 }"
8200 [(set (attr "far_jump")
8201 (if_then_else
8202 (eq_attr "length" "8")
8203 (const_string "yes")
8204 (const_string "no")))
8205 (set (attr "length")
8206 (if_then_else
8207 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
8208 (le (minus (match_dup 3) (pc)) (const_int 256)))
8209 (const_int 4)
8210 (if_then_else
8211 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
8212 (le (minus (match_dup 3) (pc)) (const_int 2048)))
8213 (const_int 6)
8214 (const_int 8))))]
8215)
747b7458 8216
aeac46d4 8217(define_insn "*tstsi3_cbranch"
58d6528b 8218 [(set (pc)
8219 (if_then_else
aeac46d4 8220 (match_operator 3 "equality_operator"
8221 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
8222 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 8223 (const_int 0)])
aeac46d4 8224 (label_ref (match_operand 2 "" ""))
8225 (pc)))]
25f905c2 8226 "TARGET_THUMB1"
58d6528b 8227 "*
8228 {
aeac46d4 8229 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 8230 switch (get_attr_length (insn))
8231 {
aeac46d4 8232 case 4: return \"b%d3\\t%l2\";
8233 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
8234 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 8235 }
8236 }"
8237 [(set (attr "far_jump")
8238 (if_then_else
8239 (eq_attr "length" "8")
8240 (const_string "yes")
8241 (const_string "no")))
8242 (set (attr "length")
8243 (if_then_else
aeac46d4 8244 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
8245 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 8246 (const_int 4)
8247 (if_then_else
aeac46d4 8248 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
8249 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 8250 (const_int 6)
8251 (const_int 8))))]
8252)
8253
203c488f 8254(define_insn "*cbranchne_decr1"
8255 [(set (pc)
8256 (if_then_else (match_operator 3 "equality_operator"
8257 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
8258 (const_int 0)])
8259 (label_ref (match_operand 4 "" ""))
8260 (pc)))
aeac46d4 8261 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 8262 (plus:SI (match_dup 2) (const_int -1)))
8263 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 8264 "TARGET_THUMB1"
203c488f 8265 "*
8266 {
8267 rtx cond[2];
8268 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
8269 ? GEU : LTU),
58d6528b 8270 VOIDmode, operands[2], const1_rtx);
203c488f 8271 cond[1] = operands[4];
8272
8273 if (which_alternative == 0)
8274 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
8275 else if (which_alternative == 1)
8276 {
8277 /* We must provide an alternative for a hi reg because reload
8278 cannot handle output reloads on a jump instruction, but we
8279 can't subtract into that. Fortunately a mov from lo to hi
8280 does not clobber the condition codes. */
8281 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
8282 output_asm_insn (\"mov\\t%0, %1\", operands);
8283 }
8284 else
8285 {
8286 /* Similarly, but the target is memory. */
8287 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
8288 output_asm_insn (\"str\\t%1, %0\", operands);
8289 }
8290
8291 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
8292 {
8293 case 4:
8aea555f 8294 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 8295 return \"\";
8296 case 6:
8aea555f 8297 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 8298 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
8299 default:
8aea555f 8300 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 8301 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
8302 }
8303 }
8304 "
8305 [(set (attr "far_jump")
8306 (if_then_else
8307 (ior (and (eq (symbol_ref ("which_alternative"))
8308 (const_int 0))
8309 (eq_attr "length" "8"))
8310 (eq_attr "length" "10"))
8311 (const_string "yes")
8312 (const_string "no")))
8313 (set_attr_alternative "length"
8314 [
8315 ;; Alternative 0
8316 (if_then_else
8317 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
8318 (le (minus (match_dup 4) (pc)) (const_int 256)))
8319 (const_int 4)
8320 (if_then_else
8321 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
8322 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8323 (const_int 6)
8324 (const_int 8)))
8325 ;; Alternative 1
8326 (if_then_else
8327 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
8328 (le (minus (match_dup 4) (pc)) (const_int 256)))
8329 (const_int 6)
8330 (if_then_else
8331 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
8332 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8333 (const_int 8)
8334 (const_int 10)))
8335 ;; Alternative 2
8336 (if_then_else
8337 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
8338 (le (minus (match_dup 4) (pc)) (const_int 256)))
8339 (const_int 6)
8340 (if_then_else
8341 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
8342 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8343 (const_int 8)
8344 (const_int 10)))
8345 ;; Alternative 3
8346 (if_then_else
8347 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
8348 (le (minus (match_dup 4) (pc)) (const_int 256)))
8349 (const_int 6)
8350 (if_then_else
8351 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
8352 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8353 (const_int 8)
8354 (const_int 10)))])]
8355)
cffb2a26 8356
58d6528b 8357(define_insn "*addsi3_cbranch"
8358 [(set (pc)
8359 (if_then_else
b0694be0 8360 (match_operator 4 "arm_comparison_operator"
58d6528b 8361 [(plus:SI
e54011cb 8362 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
8363 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 8364 (const_int 0)])
8365 (label_ref (match_operand 5 "" ""))
8366 (pc)))
aeac46d4 8367 (set
8368 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
8369 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 8370 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 8371 "TARGET_THUMB1
58d6528b 8372 && (GET_CODE (operands[4]) == EQ
8373 || GET_CODE (operands[4]) == NE
8374 || GET_CODE (operands[4]) == GE
8375 || GET_CODE (operands[4]) == LT)"
8376 "*
8377 {
8378 rtx cond[3];
8379
956a6170 8380 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 8381 cond[1] = operands[2];
8382 cond[2] = operands[3];
8383
0438d37f 8384 if (CONST_INT_P (cond[2]) && INTVAL (cond[2]) < 0)
58d6528b 8385 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
8386 else
8387 output_asm_insn (\"add\\t%0, %1, %2\", cond);
8388
956a6170 8389 if (which_alternative >= 2
58d6528b 8390 && which_alternative < 4)
8391 output_asm_insn (\"mov\\t%0, %1\", operands);
8392 else if (which_alternative >= 4)
8393 output_asm_insn (\"str\\t%1, %0\", operands);
8394
d0f6c30d 8395 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 8396 {
8397 case 4:
8398 return \"b%d4\\t%l5\";
8399 case 6:
8400 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
8401 default:
8402 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
8403 }
8404 }
8405 "
8406 [(set (attr "far_jump")
8407 (if_then_else
8408 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 8409 (const_int 2))
58d6528b 8410 (eq_attr "length" "8"))
8411 (eq_attr "length" "10"))
8412 (const_string "yes")
8413 (const_string "no")))
8414 (set (attr "length")
8415 (if_then_else
8416 (lt (symbol_ref ("which_alternative"))
d0f6c30d 8417 (const_int 2))
58d6528b 8418 (if_then_else
8419 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
8420 (le (minus (match_dup 5) (pc)) (const_int 256)))
8421 (const_int 4)
8422 (if_then_else
8423 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
8424 (le (minus (match_dup 5) (pc)) (const_int 2048)))
8425 (const_int 6)
8426 (const_int 8)))
8427 (if_then_else
8428 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
8429 (le (minus (match_dup 5) (pc)) (const_int 256)))
8430 (const_int 6)
8431 (if_then_else
8432 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
8433 (le (minus (match_dup 5) (pc)) (const_int 2048)))
8434 (const_int 8)
8435 (const_int 10)))))]
8436)
8437
8438(define_insn "*addsi3_cbranch_scratch"
8439 [(set (pc)
8440 (if_then_else
b0694be0 8441 (match_operator 3 "arm_comparison_operator"
58d6528b 8442 [(plus:SI
8443 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 8444 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 8445 (const_int 0)])
8446 (label_ref (match_operand 4 "" ""))
8447 (pc)))
8448 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 8449 "TARGET_THUMB1
58d6528b 8450 && (GET_CODE (operands[3]) == EQ
8451 || GET_CODE (operands[3]) == NE
8452 || GET_CODE (operands[3]) == GE
8453 || GET_CODE (operands[3]) == LT)"
8454 "*
8455 {
8456 switch (which_alternative)
8457 {
8458 case 0:
8459 output_asm_insn (\"cmp\t%1, #%n2\", operands);
8460 break;
8461 case 1:
8462 output_asm_insn (\"cmn\t%1, %2\", operands);
8463 break;
0f5e9701 8464 case 2:
3a445a04 8465 if (INTVAL (operands[2]) < 0)
8466 output_asm_insn (\"sub\t%0, %1, %2\", operands);
8467 else
8468 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 8469 break;
0f5e9701 8470 case 3:
3a445a04 8471 if (INTVAL (operands[2]) < 0)
8472 output_asm_insn (\"sub\t%0, %0, %2\", operands);
8473 else
8474 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 8475 break;
8476 }
8477
8478 switch (get_attr_length (insn))
8479 {
8480 case 4:
8481 return \"b%d3\\t%l4\";
8482 case 6:
8483 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
8484 default:
8485 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
8486 }
8487 }
8488 "
8489 [(set (attr "far_jump")
8490 (if_then_else
8491 (eq_attr "length" "8")
8492 (const_string "yes")
8493 (const_string "no")))
8494 (set (attr "length")
8495 (if_then_else
8496 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
8497 (le (minus (match_dup 4) (pc)) (const_int 256)))
8498 (const_int 4)
8499 (if_then_else
8500 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
8501 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8502 (const_int 6)
8503 (const_int 8))))]
8504)
8505
58d6528b 8506
9c08d1fa 8507;; Comparison and test insns
8508
cffb2a26 8509(define_insn "*arm_cmpsi_insn"
bd5b4116 8510 [(set (reg:CC CC_REGNUM)
a6864a24 8511 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
8512 (match_operand:SI 1 "arm_add_operand" "Py,r,rI,L")))]
25f905c2 8513 "TARGET_32BIT"
5565501b 8514 "@
a6864a24 8515 cmp%?\\t%0, %1
8516 cmp%?\\t%0, %1
aea4c774 8517 cmp%?\\t%0, %1
8518 cmn%?\\t%0, #%n1"
a6864a24 8519 [(set_attr "conds" "set")
8520 (set_attr "arch" "t2,t2,any,any")
596e5e8f 8521 (set_attr "length" "2,2,4,4")
65f68e55 8522 (set_attr "predicable" "yes")
6b6abc9c 8523 (set_attr "type" "*,*,*,arlo_imm")]
cffb2a26 8524)
b11cae9e 8525
d5d4dc8d 8526(define_insn "*cmpsi_shiftsi"
bd5b4116 8527 [(set (reg:CC CC_REGNUM)
d5d4dc8d 8528 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 8529 (match_operator:SI 3 "shift_operator"
d5d4dc8d 8530 [(match_operand:SI 1 "s_register_operand" "r,r")
8531 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
8532 "TARGET_32BIT"
aea4c774 8533 "cmp%?\\t%0, %1%S3"
344495ea 8534 [(set_attr "conds" "set")
331beb1a 8535 (set_attr "shift" "1")
d5d4dc8d 8536 (set_attr "arch" "32,a")
6b6abc9c 8537 (set_attr "type" "arlo_shift,arlo_shift_reg")])
b11cae9e 8538
d5d4dc8d 8539(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 8540 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 8541 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 8542 [(match_operand:SI 1 "s_register_operand" "r,r")
8543 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
8544 (match_operand:SI 0 "s_register_operand" "r,r")))]
8545 "TARGET_32BIT"
aea4c774 8546 "cmp%?\\t%0, %1%S3"
344495ea 8547 [(set_attr "conds" "set")
331beb1a 8548 (set_attr "shift" "1")
d5d4dc8d 8549 (set_attr "arch" "32,a")
6b6abc9c 8550 (set_attr "type" "arlo_shift,arlo_shift_reg")])
b11cae9e 8551
25f905c2 8552(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 8553 [(set (reg:CC_Z CC_REGNUM)
8554 (compare:CC_Z
8555 (neg:SI (match_operator:SI 1 "shift_operator"
8556 [(match_operand:SI 2 "s_register_operand" "r")
8557 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
8558 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 8559 "TARGET_ARM"
aed179ae 8560 "cmn%?\\t%0, %2%S1"
344495ea 8561 [(set_attr "conds" "set")
aed179ae 8562 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6b6abc9c 8563 (const_string "arlo_shift")
8564 (const_string "arlo_shift_reg")))
596e5e8f 8565 (set_attr "predicable" "yes")]
0d66636f 8566)
b11cae9e 8567
a8045a4f 8568;; DImode comparisons. The generic code generates branches that
8569;; if-conversion can not reduce to a conditional compare, so we do
8570;; that directly.
8571
ba6a3b2f 8572(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 8573 [(set (reg:CC_NCV CC_REGNUM)
8574 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
8575 (match_operand:DI 1 "arm_di_operand" "rDi")))
8576 (clobber (match_scratch:SI 2 "=r"))]
b805622c 8577 "TARGET_32BIT"
ba6a3b2f 8578 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
8579 "&& reload_completed"
8580 [(set (reg:CC CC_REGNUM)
8581 (compare:CC (match_dup 0) (match_dup 1)))
8582 (parallel [(set (reg:CC CC_REGNUM)
8583 (compare:CC (match_dup 3) (match_dup 4)))
8584 (set (match_dup 2)
8585 (minus:SI (match_dup 5)
8586 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
8587 {
8588 operands[3] = gen_highpart (SImode, operands[0]);
8589 operands[0] = gen_lowpart (SImode, operands[0]);
8590 if (CONST_INT_P (operands[1]))
8591 {
8592 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
8593 DImode,
8594 operands[1])));
8595 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
8596 }
8597 else
8598 {
8599 operands[4] = gen_highpart (SImode, operands[1]);
8600 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
8601 }
8602 operands[1] = gen_lowpart (SImode, operands[1]);
8603 operands[2] = gen_lowpart (SImode, operands[2]);
8604 }
a8045a4f 8605 [(set_attr "conds" "set")
8606 (set_attr "length" "8")]
8607)
8608
ba6a3b2f 8609(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 8610 [(set (reg:CC_CZ CC_REGNUM)
7c36fe71 8611 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r")
8612 (match_operand:DI 1 "arm_di_operand" "Py,r,rDi")))]
8613
48a98053 8614 "TARGET_32BIT"
ba6a3b2f 8615 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
8616 "&& reload_completed"
8617 [(set (reg:CC CC_REGNUM)
8618 (compare:CC (match_dup 2) (match_dup 3)))
8619 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
8620 (set (reg:CC CC_REGNUM)
8621 (compare:CC (match_dup 0) (match_dup 1))))]
8622 {
8623 operands[2] = gen_highpart (SImode, operands[0]);
8624 operands[0] = gen_lowpart (SImode, operands[0]);
8625 if (CONST_INT_P (operands[1]))
8626 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
8627 else
8628 operands[3] = gen_highpart (SImode, operands[1]);
8629 operands[1] = gen_lowpart (SImode, operands[1]);
8630 }
a8045a4f 8631 [(set_attr "conds" "set")
7c36fe71 8632 (set_attr "enabled_for_depr_it" "yes,yes,no")
8633 (set_attr "arch" "t2,t2,*")
8634 (set_attr "length" "6,6,8")]
a8045a4f 8635)
8636
8637(define_insn "*arm_cmpdi_zero"
8638 [(set (reg:CC_Z CC_REGNUM)
8639 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
8640 (const_int 0)))
8641 (clobber (match_scratch:SI 1 "=r"))]
8642 "TARGET_32BIT"
8643 "orr%.\\t%1, %Q0, %R0"
8644 [(set_attr "conds" "set")]
8645)
8646
8647(define_insn "*thumb_cmpdi_zero"
8648 [(set (reg:CC_Z CC_REGNUM)
8649 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
8650 (const_int 0)))
8651 (clobber (match_scratch:SI 1 "=l"))]
8652 "TARGET_THUMB1"
8653 "orr\\t%1, %Q0, %R0"
8654 [(set_attr "conds" "set")
8655 (set_attr "length" "2")]
8656)
8657
9c08d1fa 8658; This insn allows redundant compares to be removed by cse, nothing should
8659; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
8660; is deleted later on. The match_dup will match the mode here, so that
8661; mode changes of the condition codes aren't lost by this even though we don't
8662; specify what they are.
8663
8a18b90c 8664(define_insn "*deleted_compare"
9c08d1fa 8665 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 8666 "TARGET_32BIT"
40dbec34 8667 "\\t%@ deleted compare"
cffb2a26 8668 [(set_attr "conds" "set")
8669 (set_attr "length" "0")]
8670)
9c08d1fa 8671
8672\f
8673;; Conditional branch insns
8674
74f4459c 8675(define_expand "cbranch_cc"
9c08d1fa 8676 [(set (pc)
74f4459c 8677 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
8678 (match_operand 2 "" "")])
8679 (label_ref (match_operand 3 "" ""))
9c08d1fa 8680 (pc)))]
25f905c2 8681 "TARGET_32BIT"
74f4459c 8682 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 8683 operands[1], operands[2], NULL_RTX);
74f4459c 8684 operands[2] = const0_rtx;"
8fa3ba89 8685)
8686
8687;;
8688;; Patterns to match conditional branch insns.
8689;;
8690
ffcc986d 8691(define_insn "arm_cond_branch"
9c08d1fa 8692 [(set (pc)
8fa3ba89 8693 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 8694 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 8695 (label_ref (match_operand 0 "" ""))
8696 (pc)))]
25f905c2 8697 "TARGET_32BIT"
d75350ce 8698 "*
9c08d1fa 8699 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 8700 {
8701 arm_ccfsm_state += 2;
8702 return \"\";
8703 }
e2348bcb 8704 return \"b%d1\\t%l0\";
cffb2a26 8705 "
a2cd141b 8706 [(set_attr "conds" "use")
a6864a24 8707 (set_attr "type" "branch")
8708 (set (attr "length")
8709 (if_then_else
0bf497f5 8710 (and (match_test "TARGET_THUMB2")
a6864a24 8711 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
8712 (le (minus (match_dup 0) (pc)) (const_int 256))))
8713 (const_int 2)
8714 (const_int 4)))]
cffb2a26 8715)
d75350ce 8716
cffb2a26 8717(define_insn "*arm_cond_branch_reversed"
9c08d1fa 8718 [(set (pc)
8fa3ba89 8719 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 8720 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 8721 (pc)
8722 (label_ref (match_operand 0 "" ""))))]
25f905c2 8723 "TARGET_32BIT"
d75350ce 8724 "*
9c08d1fa 8725 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 8726 {
8727 arm_ccfsm_state += 2;
8728 return \"\";
8729 }
e2348bcb 8730 return \"b%D1\\t%l0\";
cffb2a26 8731 "
a2cd141b 8732 [(set_attr "conds" "use")
a6864a24 8733 (set_attr "type" "branch")
8734 (set (attr "length")
8735 (if_then_else
0bf497f5 8736 (and (match_test "TARGET_THUMB2")
a6864a24 8737 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
8738 (le (minus (match_dup 0) (pc)) (const_int 256))))
8739 (const_int 2)
8740 (const_int 4)))]
cffb2a26 8741)
8742
b11cae9e 8743\f
9c08d1fa 8744
8745; scc insns
8746
74f4459c 8747(define_expand "cstore_cc"
7db9af5d 8748 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 8749 (match_operator:SI 1 "" [(match_operand 2 "" "")
8750 (match_operand 3 "" "")]))]
25f905c2 8751 "TARGET_32BIT"
74f4459c 8752 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 8753 operands[2], operands[3], NULL_RTX);
74f4459c 8754 operands[3] = const0_rtx;"
8fa3ba89 8755)
8756
a3b84066 8757(define_insn_and_split "*mov_scc"
9c08d1fa 8758 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8759 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 8760 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 8761 "TARGET_ARM"
a3b84066 8762 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
8763 "TARGET_ARM"
8764 [(set (match_dup 0)
8765 (if_then_else:SI (match_dup 1)
8766 (const_int 1)
8767 (const_int 0)))]
8768 ""
cffb2a26 8769 [(set_attr "conds" "use")
8770 (set_attr "length" "8")]
8771)
9c08d1fa 8772
a3b84066 8773(define_insn_and_split "*mov_negscc"
9c08d1fa 8774 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8775 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 8776 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 8777 "TARGET_ARM"
a3b84066 8778 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
8779 "TARGET_ARM"
8780 [(set (match_dup 0)
8781 (if_then_else:SI (match_dup 1)
8782 (match_dup 3)
8783 (const_int 0)))]
8784 {
8785 operands[3] = GEN_INT (~0);
8786 }
cffb2a26 8787 [(set_attr "conds" "use")
8788 (set_attr "length" "8")]
8789)
9c08d1fa 8790
a3b84066 8791(define_insn_and_split "*mov_notscc"
9c08d1fa 8792 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8793 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 8794 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 8795 "TARGET_ARM"
a3b84066 8796 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
8797 "TARGET_ARM"
8798 [(set (match_dup 0)
8799 (if_then_else:SI (match_dup 1)
8800 (match_dup 3)
8801 (match_dup 4)))]
8802 {
8803 operands[3] = GEN_INT (~1);
8804 operands[4] = GEN_INT (~0);
8805 }
cffb2a26 8806 [(set_attr "conds" "use")
8807 (set_attr "length" "8")]
8808)
9c08d1fa 8809
595d88b5 8810(define_expand "cstoresi4"
8811 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8812 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 8813 [(match_operand:SI 2 "s_register_operand" "")
8814 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 8815 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 8816 "{
8817 rtx op3, scratch, scratch2;
8818
74f4459c 8819 if (!TARGET_THUMB1)
8820 {
8821 if (!arm_add_operand (operands[3], SImode))
8822 operands[3] = force_reg (SImode, operands[3]);
8823 emit_insn (gen_cstore_cc (operands[0], operands[1],
8824 operands[2], operands[3]));
8825 DONE;
8826 }
8827
595d88b5 8828 if (operands[3] == const0_rtx)
8829 {
8830 switch (GET_CODE (operands[1]))
8831 {
8832 case EQ:
25f905c2 8833 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 8834 break;
8835
8836 case NE:
25f905c2 8837 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 8838 break;
8839
8840 case LE:
8841 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
8842 NULL_RTX, 0, OPTAB_WIDEN);
8843 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
8844 NULL_RTX, 0, OPTAB_WIDEN);
8845 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8846 operands[0], 1, OPTAB_WIDEN);
8847 break;
8848
8849 case GE:
8850 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
8851 NULL_RTX, 1);
8852 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8853 NULL_RTX, 1, OPTAB_WIDEN);
8854 break;
8855
8856 case GT:
8857 scratch = expand_binop (SImode, ashr_optab, operands[2],
8858 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
8859 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
8860 NULL_RTX, 0, OPTAB_WIDEN);
8861 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
8862 0, OPTAB_WIDEN);
8863 break;
8864
8865 /* LT is handled by generic code. No need for unsigned with 0. */
8866 default:
8867 FAIL;
8868 }
8869 DONE;
8870 }
8871
8872 switch (GET_CODE (operands[1]))
8873 {
8874 case EQ:
8875 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8876 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8877 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 8878 break;
8879
8880 case NE:
8881 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8882 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8883 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 8884 break;
8885
8886 case LE:
8887 op3 = force_reg (SImode, operands[3]);
8888
8889 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
8890 NULL_RTX, 1, OPTAB_WIDEN);
8891 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
8892 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8893 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8894 op3, operands[2]));
8895 break;
8896
8897 case GE:
8898 op3 = operands[3];
25f905c2 8899 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8900 op3 = force_reg (SImode, op3);
8901 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8902 NULL_RTX, 0, OPTAB_WIDEN);
8903 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8904 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 8905 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8906 operands[2], op3));
8907 break;
8908
8909 case LEU:
8910 op3 = force_reg (SImode, operands[3]);
8911 scratch = force_reg (SImode, const0_rtx);
25f905c2 8912 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8913 op3, operands[2]));
8914 break;
8915
8916 case GEU:
8917 op3 = operands[3];
25f905c2 8918 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8919 op3 = force_reg (SImode, op3);
8920 scratch = force_reg (SImode, const0_rtx);
25f905c2 8921 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8922 operands[2], op3));
8923 break;
8924
8925 case LTU:
8926 op3 = operands[3];
25f905c2 8927 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8928 op3 = force_reg (SImode, op3);
8929 scratch = gen_reg_rtx (SImode);
408b7ae5 8930 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 8931 break;
8932
8933 case GTU:
8934 op3 = force_reg (SImode, operands[3]);
8935 scratch = gen_reg_rtx (SImode);
408b7ae5 8936 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 8937 break;
8938
8939 /* No good sequences for GT, LT. */
8940 default:
8941 FAIL;
8942 }
8943 DONE;
8944}")
8945
74f4459c 8946(define_expand "cstoresf4"
8947 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8948 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 8949 [(match_operand:SF 2 "s_register_operand" "")
8950 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8951 "TARGET_32BIT && TARGET_HARD_FLOAT"
8952 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8953 operands[2], operands[3])); DONE;"
8954)
8955
8956(define_expand "cstoredf4"
8957 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8958 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 8959 [(match_operand:DF 2 "s_register_operand" "")
8960 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 8961 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 8962 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8963 operands[2], operands[3])); DONE;"
8964)
8965
74f4459c 8966(define_expand "cstoredi4"
8967 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8968 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 8969 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 8970 (match_operand:DI 3 "cmpdi_operand" "")]))]
8971 "TARGET_32BIT"
8972 "{
f9aa4160 8973 if (!arm_validize_comparison (&operands[1],
8974 &operands[2],
8975 &operands[3]))
8976 FAIL;
8977 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 8978 operands[3]));
8979 DONE;
8980 }"
74f4459c 8981)
8982
25f905c2 8983(define_expand "cstoresi_eq0_thumb1"
595d88b5 8984 [(parallel
8985 [(set (match_operand:SI 0 "s_register_operand" "")
8986 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8987 (const_int 0)))
8988 (clobber (match_dup:SI 2))])]
25f905c2 8989 "TARGET_THUMB1"
595d88b5 8990 "operands[2] = gen_reg_rtx (SImode);"
8991)
8992
25f905c2 8993(define_expand "cstoresi_ne0_thumb1"
595d88b5 8994 [(parallel
8995 [(set (match_operand:SI 0 "s_register_operand" "")
8996 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8997 (const_int 0)))
8998 (clobber (match_dup:SI 2))])]
25f905c2 8999 "TARGET_THUMB1"
595d88b5 9000 "operands[2] = gen_reg_rtx (SImode);"
9001)
9002
25f905c2 9003(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 9004 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
9005 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
9006 (const_int 0)))
9007 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 9008 "TARGET_THUMB1"
595d88b5 9009 "@
9010 neg\\t%0, %1\;adc\\t%0, %0, %1
9011 neg\\t%2, %1\;adc\\t%0, %1, %2"
9012 [(set_attr "length" "4")]
9013)
9014
25f905c2 9015(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 9016 [(set (match_operand:SI 0 "s_register_operand" "=l")
9017 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
9018 (const_int 0)))
9019 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 9020 "TARGET_THUMB1"
595d88b5 9021 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
9022 [(set_attr "length" "4")]
9023)
9024
408b7ae5 9025;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 9026(define_insn "cstoresi_nltu_thumb1"
595d88b5 9027 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 9028 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 9029 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
9030 "TARGET_THUMB1"
595d88b5 9031 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
9032 [(set_attr "length" "4")]
9033)
9034
408b7ae5 9035(define_insn_and_split "cstoresi_ltu_thumb1"
9036 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
9037 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
9038 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
9039 "TARGET_THUMB1"
9040 "#"
9041 "TARGET_THUMB1"
9042 [(set (match_dup 3)
9043 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
9044 (set (match_dup 0) (neg:SI (match_dup 3)))]
9045 "operands[3] = gen_reg_rtx (SImode);"
9046 [(set_attr "length" "4")]
9047)
9048
595d88b5 9049;; Used as part of the expansion of thumb les sequence.
25f905c2 9050(define_insn "thumb1_addsi3_addgeu"
595d88b5 9051 [(set (match_operand:SI 0 "s_register_operand" "=l")
9052 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9053 (match_operand:SI 2 "s_register_operand" "l"))
9054 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 9055 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
9056 "TARGET_THUMB1"
595d88b5 9057 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
9058 [(set_attr "length" "4")]
9059)
9060
9c08d1fa 9061\f
39b5e676 9062;; Conditional move insns
9063
9064(define_expand "movsicc"
8a18b90c 9065 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 9066 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 9067 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 9068 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 9069 "TARGET_32BIT"
39b5e676 9070 "
215b30b3 9071 {
f9aa4160 9072 enum rtx_code code;
278b301d 9073 rtx ccreg;
9074
f9aa4160 9075 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9076 &XEXP (operands[1], 1)))
278b301d 9077 FAIL;
f9aa4160 9078
9079 code = GET_CODE (operands[1]);
74f4459c 9080 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 9081 XEXP (operands[1], 1), NULL_RTX);
29bb088d 9082 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 9083 }"
9084)
39b5e676 9085
9086(define_expand "movsfcc"
8a18b90c 9087 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 9088 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 9089 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 9090 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 9091 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 9092 "
215b30b3 9093 {
9094 enum rtx_code code = GET_CODE (operands[1]);
9095 rtx ccreg;
f082f1c4 9096
f9aa4160 9097 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9098 &XEXP (operands[1], 1)))
9099 FAIL;
39b5e676 9100
f9aa4160 9101 code = GET_CODE (operands[1]);
74f4459c 9102 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 9103 XEXP (operands[1], 1), NULL_RTX);
29bb088d 9104 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 9105 }"
9106)
39b5e676 9107
9108(define_expand "movdfcc"
8a18b90c 9109 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 9110 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 9111 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 9112 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 9113 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 9114 "
215b30b3 9115 {
9116 enum rtx_code code = GET_CODE (operands[1]);
278b301d 9117 rtx ccreg;
39b5e676 9118
f9aa4160 9119 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9120 &XEXP (operands[1], 1)))
9121 FAIL;
9122 code = GET_CODE (operands[1]);
74f4459c 9123 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 9124 XEXP (operands[1], 1), NULL_RTX);
29bb088d 9125 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 9126 }"
9127)
39b5e676 9128
91cb50d2 9129(define_insn "*cmov<mode>"
9130 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
9131 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
9132 [(match_operand 2 "cc_register" "") (const_int 0)])
9133 (match_operand:SDF 3 "s_register_operand"
9134 "<F_constraint>")
9135 (match_operand:SDF 4 "s_register_operand"
9136 "<F_constraint>")))]
9137 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
9138 "*
9139 {
9140 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
9141 switch (code)
9142 {
9143 case ARM_GE:
9144 case ARM_GT:
9145 case ARM_EQ:
9146 case ARM_VS:
9147 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
9148 case ARM_LT:
9149 case ARM_LE:
9150 case ARM_NE:
9151 case ARM_VC:
9152 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
9153 default:
9154 gcc_unreachable ();
9155 }
9156 return \"\";
9157 }"
9158 [(set_attr "conds" "use")
9159 (set_attr "type" "f_sel<vfp_type>")]
9160)
9161
190efb17 9162(define_insn_and_split "*movsicc_insn"
f082f1c4 9163 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 9164 (if_then_else:SI
8fa3ba89 9165 (match_operator 3 "arm_comparison_operator"
8a18b90c 9166 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 9167 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
9168 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 9169 "TARGET_ARM"
39b5e676 9170 "@
8a18b90c 9171 mov%D3\\t%0, %2
9172 mvn%D3\\t%0, #%B2
f082f1c4 9173 mov%d3\\t%0, %1
9174 mvn%d3\\t%0, #%B1
190efb17 9175 #
9176 #
9177 #
9178 #"
9179 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
9180 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
9181 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
9182 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
9183 "&& reload_completed"
9184 [(const_int 0)]
9185 {
9186 enum rtx_code rev_code;
9187 enum machine_mode mode;
9188 rtx rev_cond;
9189
9190 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9191 operands[3],
9192 gen_rtx_SET (VOIDmode,
9193 operands[0],
9194 operands[1])));
9195
9196 rev_code = GET_CODE (operands[3]);
9197 mode = GET_MODE (operands[4]);
9198 if (mode == CCFPmode || mode == CCFPEmode)
9199 rev_code = reverse_condition_maybe_unordered (rev_code);
9200 else
9201 rev_code = reverse_condition (rev_code);
9202
9203 rev_cond = gen_rtx_fmt_ee (rev_code,
9204 VOIDmode,
9205 operands[4],
9206 const0_rtx);
9207 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9208 rev_cond,
9209 gen_rtx_SET (VOIDmode,
9210 operands[0],
9211 operands[2])));
9212 DONE;
9213 }
f082f1c4 9214 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 9215 (set_attr "conds" "use")
65f68e55 9216 (set_attr_alternative "type"
9217 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 9218 (const_string "mov_imm")
9219 (const_string "mov_reg"))
9220 (const_string "mvn_imm")
65f68e55 9221 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 9222 (const_string "mov_imm")
9223 (const_string "mov_reg"))
9224 (const_string "mvn_imm")
9225 (const_string "mov_reg")
9226 (const_string "mov_reg")
9227 (const_string "mov_reg")
9228 (const_string "mov_reg")])]
215b30b3 9229)
39b5e676 9230
39b5e676 9231(define_insn "*movsfcc_soft_insn"
f082f1c4 9232 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 9233 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 9234 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 9235 (match_operand:SF 1 "s_register_operand" "0,r")
9236 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 9237 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 9238 "@
9239 mov%D3\\t%0, %2
9240 mov%d3\\t%0, %1"
d2a518d1 9241 [(set_attr "conds" "use")
1aed5204 9242 (set_attr "type" "mov_reg")]
8fa3ba89 9243)
39b5e676 9244
39b5e676 9245\f
9c08d1fa 9246;; Jump and linkage insns
9247
cffb2a26 9248(define_expand "jump"
9c08d1fa 9249 [(set (pc)
9250 (label_ref (match_operand 0 "" "")))]
cffb2a26 9251 "TARGET_EITHER"
9c08d1fa 9252 ""
cffb2a26 9253)
9254
9255(define_insn "*arm_jump"
9256 [(set (pc)
9257 (label_ref (match_operand 0 "" "")))]
25f905c2 9258 "TARGET_32BIT"
9c08d1fa 9259 "*
0d66636f 9260 {
9261 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
9262 {
9263 arm_ccfsm_state += 2;
9264 return \"\";
9265 }
9266 return \"b%?\\t%l0\";
9267 }
9268 "
a6864a24 9269 [(set_attr "predicable" "yes")
9270 (set (attr "length")
9271 (if_then_else
0bf497f5 9272 (and (match_test "TARGET_THUMB2")
a6864a24 9273 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
9274 (le (minus (match_dup 0) (pc)) (const_int 2048))))
9275 (const_int 2)
9276 (const_int 4)))]
0d66636f 9277)
9c08d1fa 9278
cffb2a26 9279(define_insn "*thumb_jump"
9280 [(set (pc)
9281 (label_ref (match_operand 0 "" "")))]
25f905c2 9282 "TARGET_THUMB1"
cffb2a26 9283 "*
9284 if (get_attr_length (insn) == 2)
9285 return \"b\\t%l0\";
9286 return \"bl\\t%l0\\t%@ far jump\";
9287 "
9288 [(set (attr "far_jump")
9289 (if_then_else
9290 (eq_attr "length" "4")
9291 (const_string "yes")
9292 (const_string "no")))
9293 (set (attr "length")
9294 (if_then_else
911ed8af 9295 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
9296 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 9297 (const_int 2)
9298 (const_int 4)))]
9299)
9300
d3373b54 9301(define_expand "call"
9302 [(parallel [(call (match_operand 0 "memory_operand" "")
9303 (match_operand 1 "general_operand" ""))
cffb2a26 9304 (use (match_operand 2 "" ""))
bd5b4116 9305 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 9306 "TARGET_EITHER"
6c4c2133 9307 "
9308 {
bac7fc85 9309 rtx callee, pat;
bbe777ea 9310
bbe777ea 9311 /* In an untyped call, we can get NULL for operand 2. */
9312 if (operands[2] == NULL_RTX)
9313 operands[2] = const0_rtx;
9314
de55252a 9315 /* Decide if we should generate indirect calls by loading the
85c36fd1 9316 32-bit address of the callee into a register before performing the
de55252a 9317 branch and link. */
9318 callee = XEXP (operands[0], 0);
9319 if (GET_CODE (callee) == SYMBOL_REF
9320 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
9321 : !REG_P (callee))
bbe777ea 9322 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 9323
9324 pat = gen_call_internal (operands[0], operands[1], operands[2]);
9325 arm_emit_call_insn (pat, XEXP (operands[0], 0));
9326 DONE;
6c4c2133 9327 }"
9328)
d3373b54 9329
bac7fc85 9330(define_expand "call_internal"
9331 [(parallel [(call (match_operand 0 "memory_operand" "")
9332 (match_operand 1 "general_operand" ""))
9333 (use (match_operand 2 "" ""))
9334 (clobber (reg:SI LR_REGNUM))])])
9335
f1039640 9336(define_insn "*call_reg_armv5"
d3373b54 9337 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 9338 (match_operand 1 "" ""))
9339 (use (match_operand 2 "" ""))
bd5b4116 9340 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9341 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 9342 "blx%?\\t%0"
9343 [(set_attr "type" "call")]
9344)
9345
9346(define_insn "*call_reg_arm"
9347 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
9348 (match_operand 1 "" ""))
9349 (use (match_operand 2 "" ""))
9350 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9351 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 9352 "*
5565501b 9353 return output_call (operands);
cffb2a26 9354 "
9355 ;; length is worst case, normally it is only two
9356 [(set_attr "length" "12")
9357 (set_attr "type" "call")]
9358)
9c08d1fa 9359
89504fc1 9360
9361;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
9362;; considered a function call by the branch predictor of some cores (PR40887).
9363;; Falls back to blx rN (*call_reg_armv5).
9364
f7fbdd4a 9365(define_insn "*call_mem"
a3c63a9d 9366 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 9367 (match_operand 1 "" ""))
9368 (use (match_operand 2 "" ""))
bd5b4116 9369 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9370 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 9371 "*
5565501b 9372 return output_call_mem (operands);
cffb2a26 9373 "
9374 [(set_attr "length" "12")
9375 (set_attr "type" "call")]
9376)
9377
25f905c2 9378(define_insn "*call_reg_thumb1_v5"
cffb2a26 9379 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
9380 (match_operand 1 "" ""))
9381 (use (match_operand 2 "" ""))
bd5b4116 9382 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9383 "TARGET_THUMB1 && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 9384 "blx\\t%0"
9385 [(set_attr "length" "2")
9386 (set_attr "type" "call")]
cffb2a26 9387)
9388
25f905c2 9389(define_insn "*call_reg_thumb1"
f1039640 9390 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
9391 (match_operand 1 "" ""))
9392 (use (match_operand 2 "" ""))
bd5b4116 9393 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9394 "TARGET_THUMB1 && !arm_arch5 && !SIBLING_CALL_P (insn)"
cffb2a26 9395 "*
9396 {
150502c9 9397 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 9398 return thumb_call_via_reg (operands[0]);
150502c9 9399 else if (operands[1] == const0_rtx)
f1039640 9400 return \"bl\\t%__interwork_call_via_%0\";
150502c9 9401 else if (frame_pointer_needed)
9402 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 9403 else
150502c9 9404 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 9405 }"
9406 [(set_attr "type" "call")]
9407)
9c08d1fa 9408
d3373b54 9409(define_expand "call_value"
e0698af7 9410 [(parallel [(set (match_operand 0 "" "")
9411 (call (match_operand 1 "memory_operand" "")
9412 (match_operand 2 "general_operand" "")))
cffb2a26 9413 (use (match_operand 3 "" ""))
bd5b4116 9414 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 9415 "TARGET_EITHER"
6c4c2133 9416 "
9417 {
bac7fc85 9418 rtx pat, callee;
bbe777ea 9419
9420 /* In an untyped call, we can get NULL for operand 2. */
9421 if (operands[3] == 0)
9422 operands[3] = const0_rtx;
9423
de55252a 9424 /* Decide if we should generate indirect calls by loading the
9425 32-bit address of the callee into a register before performing the
9426 branch and link. */
9427 callee = XEXP (operands[1], 0);
9428 if (GET_CODE (callee) == SYMBOL_REF
9429 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
9430 : !REG_P (callee))
78fe751b 9431 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 9432
9433 pat = gen_call_value_internal (operands[0], operands[1],
9434 operands[2], operands[3]);
9435 arm_emit_call_insn (pat, XEXP (operands[1], 0));
9436 DONE;
6c4c2133 9437 }"
9438)
d3373b54 9439
bac7fc85 9440(define_expand "call_value_internal"
9441 [(parallel [(set (match_operand 0 "" "")
9442 (call (match_operand 1 "memory_operand" "")
9443 (match_operand 2 "general_operand" "")))
9444 (use (match_operand 3 "" ""))
9445 (clobber (reg:SI LR_REGNUM))])])
9446
f1039640 9447(define_insn "*call_value_reg_armv5"
27ed6835 9448 [(set (match_operand 0 "" "")
755eb2b4 9449 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 9450 (match_operand 2 "" "")))
bbe777ea 9451 (use (match_operand 3 "" ""))
bd5b4116 9452 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9453 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 9454 "blx%?\\t%1"
9455 [(set_attr "type" "call")]
9456)
9457
9458(define_insn "*call_value_reg_arm"
9459 [(set (match_operand 0 "" "")
9460 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
9461 (match_operand 2 "" "")))
9462 (use (match_operand 3 "" ""))
9463 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9464 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 9465 "*
215b30b3 9466 return output_call (&operands[1]);
cffb2a26 9467 "
9468 [(set_attr "length" "12")
9469 (set_attr "type" "call")]
9470)
9c08d1fa 9471
89504fc1 9472;; Note: see *call_mem
9473
f7fbdd4a 9474(define_insn "*call_value_mem"
27ed6835 9475 [(set (match_operand 0 "" "")
a3c63a9d 9476 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 9477 (match_operand 2 "" "")))
bbe777ea 9478 (use (match_operand 3 "" ""))
bd5b4116 9479 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9480 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
9481 && !SIBLING_CALL_P (insn)"
9c08d1fa 9482 "*
215b30b3 9483 return output_call_mem (&operands[1]);
cffb2a26 9484 "
9485 [(set_attr "length" "12")
9486 (set_attr "type" "call")]
9487)
9c08d1fa 9488
25f905c2 9489(define_insn "*call_value_reg_thumb1_v5"
f1039640 9490 [(set (match_operand 0 "" "")
9491 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
9492 (match_operand 2 "" "")))
9493 (use (match_operand 3 "" ""))
9494 (clobber (reg:SI LR_REGNUM))]
25f905c2 9495 "TARGET_THUMB1 && arm_arch5"
f1039640 9496 "blx\\t%1"
9497 [(set_attr "length" "2")
9498 (set_attr "type" "call")]
9499)
9500
25f905c2 9501(define_insn "*call_value_reg_thumb1"
f1039640 9502 [(set (match_operand 0 "" "")
9503 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
9504 (match_operand 2 "" "")))
9505 (use (match_operand 3 "" ""))
9506 (clobber (reg:SI LR_REGNUM))]
25f905c2 9507 "TARGET_THUMB1 && !arm_arch5"
f1039640 9508 "*
9509 {
150502c9 9510 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 9511 return thumb_call_via_reg (operands[1]);
150502c9 9512 else if (operands[2] == const0_rtx)
f1039640 9513 return \"bl\\t%__interwork_call_via_%1\";
150502c9 9514 else if (frame_pointer_needed)
9515 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 9516 else
150502c9 9517 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 9518 }"
9519 [(set_attr "type" "call")]
9520)
9521
9c08d1fa 9522;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
9523;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
9524
f7fbdd4a 9525(define_insn "*call_symbol"
27ed6835 9526 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 9527 (match_operand 1 "" ""))
bbe777ea 9528 (use (match_operand 2 "" ""))
bd5b4116 9529 (clobber (reg:SI LR_REGNUM))]
d68c2c10 9530 "TARGET_32BIT
33ae7c4b 9531 && !SIBLING_CALL_P (insn)
cffb2a26 9532 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 9533 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 9534 "*
9535 {
55c1e470 9536 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 9537 }"
cffb2a26 9538 [(set_attr "type" "call")]
9539)
9c08d1fa 9540
f7fbdd4a 9541(define_insn "*call_value_symbol"
ccd90aaa 9542 [(set (match_operand 0 "" "")
27ed6835 9543 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 9544 (match_operand:SI 2 "" "")))
bbe777ea 9545 (use (match_operand 3 "" ""))
bd5b4116 9546 (clobber (reg:SI LR_REGNUM))]
d68c2c10 9547 "TARGET_32BIT
33ae7c4b 9548 && !SIBLING_CALL_P (insn)
cffb2a26 9549 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 9550 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 9551 "*
9552 {
55c1e470 9553 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 9554 }"
cffb2a26 9555 [(set_attr "type" "call")]
9556)
9557
9558(define_insn "*call_insn"
27ed6835 9559 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 9560 (match_operand:SI 1 "" ""))
9561 (use (match_operand 2 "" ""))
bd5b4116 9562 (clobber (reg:SI LR_REGNUM))]
d68c2c10 9563 "TARGET_THUMB1
1675c6e9 9564 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 9565 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 9566 "bl\\t%a0"
9567 [(set_attr "length" "4")
9568 (set_attr "type" "call")]
9569)
9570
9571(define_insn "*call_value_insn"
ccd90aaa 9572 [(set (match_operand 0 "" "")
27ed6835 9573 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 9574 (match_operand 2 "" "")))
9575 (use (match_operand 3 "" ""))
bd5b4116 9576 (clobber (reg:SI LR_REGNUM))]
d68c2c10 9577 "TARGET_THUMB1
1675c6e9 9578 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 9579 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 9580 "bl\\t%a1"
9581 [(set_attr "length" "4")
9582 (set_attr "type" "call")]
9583)
9c08d1fa 9584
1c494086 9585;; We may also be able to do sibcalls for Thumb, but it's much harder...
9586(define_expand "sibcall"
9587 [(parallel [(call (match_operand 0 "memory_operand" "")
9588 (match_operand 1 "general_operand" ""))
2ba80634 9589 (return)
9590 (use (match_operand 2 "" ""))])]
d68c2c10 9591 "TARGET_32BIT"
1c494086 9592 "
9593 {
33ae7c4b 9594 if (!REG_P (XEXP (operands[0], 0))
9595 && (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF))
9596 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
9597
1c494086 9598 if (operands[2] == NULL_RTX)
9599 operands[2] = const0_rtx;
1c494086 9600 }"
9601)
9602
9603(define_expand "sibcall_value"
ccd90aaa 9604 [(parallel [(set (match_operand 0 "" "")
1c494086 9605 (call (match_operand 1 "memory_operand" "")
9606 (match_operand 2 "general_operand" "")))
2ba80634 9607 (return)
9608 (use (match_operand 3 "" ""))])]
d68c2c10 9609 "TARGET_32BIT"
1c494086 9610 "
9611 {
33ae7c4b 9612 if (!REG_P (XEXP (operands[1], 0)) &&
9613 (GET_CODE (XEXP (operands[1],0)) != SYMBOL_REF))
9614 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
9615
1c494086 9616 if (operands[3] == NULL_RTX)
9617 operands[3] = const0_rtx;
1c494086 9618 }"
9619)
9620
9621(define_insn "*sibcall_insn"
84ce8e5c 9622 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 9623 (match_operand 1 "" ""))
2ba80634 9624 (return)
9625 (use (match_operand 2 "" ""))]
33ae7c4b 9626 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 9627 "*
33ae7c4b 9628 if (which_alternative == 1)
9629 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
9630 else
9631 {
9632 if (arm_arch5 || arm_arch4t)
947d113e 9633 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 9634 else
9635 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
9636 }
1c494086 9637 "
9638 [(set_attr "type" "call")]
9639)
9640
9641(define_insn "*sibcall_value_insn"
84ce8e5c 9642 [(set (match_operand 0 "" "")
9643 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 9644 (match_operand 2 "" "")))
2ba80634 9645 (return)
9646 (use (match_operand 3 "" ""))]
33ae7c4b 9647 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 9648 "*
33ae7c4b 9649 if (which_alternative == 1)
9650 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
9651 else
9652 {
9653 if (arm_arch5 || arm_arch4t)
84ce8e5c 9654 return \"bx%?\\t%1\";
33ae7c4b 9655 else
9656 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
9657 }
1c494086 9658 "
9659 [(set_attr "type" "call")]
9660)
9661
0686440e 9662(define_expand "<return_str>return"
9663 [(returns)]
8cba51a5 9664 "(TARGET_ARM || (TARGET_THUMB2
9665 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
9666 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 9667 <return_cond_false>"
8cba51a5 9668 "
9669 {
9670 if (TARGET_THUMB2)
9671 {
0686440e 9672 thumb2_expand_return (<return_simple_p>);
8cba51a5 9673 DONE;
9674 }
9675 }
9676 "
9677)
d68c2c10 9678
9c08d1fa 9679;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 9680(define_insn "*arm_return"
9c08d1fa 9681 [(return)]
cffb2a26 9682 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 9683 "*
9c08d1fa 9684 {
cffb2a26 9685 if (arm_ccfsm_state == 2)
9686 {
9687 arm_ccfsm_state += 2;
9688 return \"\";
9689 }
e2549f81 9690 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 9691 }"
a2cd141b 9692 [(set_attr "type" "load1")
755eb2b4 9693 (set_attr "length" "12")
0d66636f 9694 (set_attr "predicable" "yes")]
cffb2a26 9695)
9c08d1fa 9696
0686440e 9697(define_insn "*cond_<return_str>return"
9c08d1fa 9698 [(set (pc)
8fa3ba89 9699 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 9700 [(match_operand 1 "cc_register" "") (const_int 0)])
0686440e 9701 (returns)
9c08d1fa 9702 (pc)))]
0686440e 9703 "TARGET_ARM <return_cond_true>"
9c08d1fa 9704 "*
8fa3ba89 9705 {
9706 if (arm_ccfsm_state == 2)
9707 {
9708 arm_ccfsm_state += 2;
9709 return \"\";
9710 }
0686440e 9711 return output_return_instruction (operands[0], true, false,
9712 <return_simple_p>);
8fa3ba89 9713 }"
9714 [(set_attr "conds" "use")
755eb2b4 9715 (set_attr "length" "12")
a2cd141b 9716 (set_attr "type" "load1")]
8fa3ba89 9717)
9c08d1fa 9718
0686440e 9719(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 9720 [(set (pc)
8fa3ba89 9721 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 9722 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 9723 (pc)
0686440e 9724 (returns)))]
9725 "TARGET_ARM <return_cond_true>"
9c08d1fa 9726 "*
8fa3ba89 9727 {
9728 if (arm_ccfsm_state == 2)
9729 {
9730 arm_ccfsm_state += 2;
9731 return \"\";
9732 }
0686440e 9733 return output_return_instruction (operands[0], true, true,
9734 <return_simple_p>);
8fa3ba89 9735 }"
9736 [(set_attr "conds" "use")
37a1317b 9737 (set_attr "length" "12")
a2cd141b 9738 (set_attr "type" "load1")]
8fa3ba89 9739)
9c08d1fa 9740
e2549f81 9741(define_insn "*arm_simple_return"
9742 [(simple_return)]
9743 "TARGET_ARM"
9744 "*
9745 {
9746 if (arm_ccfsm_state == 2)
9747 {
9748 arm_ccfsm_state += 2;
9749 return \"\";
9750 }
9751 return output_return_instruction (const_true_rtx, true, false, true);
9752 }"
9753 [(set_attr "type" "branch")
9754 (set_attr "length" "4")
9755 (set_attr "predicable" "yes")]
9756)
9757
68121397 9758;; Generate a sequence of instructions to determine if the processor is
9759;; in 26-bit or 32-bit mode, and return the appropriate return address
9760;; mask.
9761
9762(define_expand "return_addr_mask"
9763 [(set (match_dup 1)
9764 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
9765 (const_int 0)))
9766 (set (match_operand:SI 0 "s_register_operand" "")
9767 (if_then_else:SI (eq (match_dup 1) (const_int 0))
9768 (const_int -1)
9769 (const_int 67108860)))] ; 0x03fffffc
9770 "TARGET_ARM"
9771 "
62eddbd4 9772 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 9773 ")
9774
9775(define_insn "*check_arch2"
9776 [(set (match_operand:CC_NOOV 0 "cc_register" "")
9777 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
9778 (const_int 0)))]
9779 "TARGET_ARM"
9780 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
9781 [(set_attr "length" "8")
9782 (set_attr "conds" "set")]
9783)
9784
9c08d1fa 9785;; Call subroutine returning any type.
9786
9787(define_expand "untyped_call"
9788 [(parallel [(call (match_operand 0 "" "")
9789 (const_int 0))
9790 (match_operand 1 "" "")
9791 (match_operand 2 "" "")])]
ccd90aaa 9792 "TARGET_EITHER"
9c08d1fa 9793 "
215b30b3 9794 {
9795 int i;
ccd90aaa 9796 rtx par = gen_rtx_PARALLEL (VOIDmode,
9797 rtvec_alloc (XVECLEN (operands[2], 0)));
9798 rtx addr = gen_reg_rtx (Pmode);
9799 rtx mem;
9800 int size = 0;
9c08d1fa 9801
ccd90aaa 9802 emit_move_insn (addr, XEXP (operands[1], 0));
9803 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 9804
215b30b3 9805 for (i = 0; i < XVECLEN (operands[2], 0); i++)
9806 {
ccd90aaa 9807 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 9808
ccd90aaa 9809 /* Default code only uses r0 as a return value, but we could
9810 be using anything up to 4 registers. */
9811 if (REGNO (src) == R0_REGNUM)
9812 src = gen_rtx_REG (TImode, R0_REGNUM);
9813
9814 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
9815 GEN_INT (size));
9816 size += GET_MODE_SIZE (GET_MODE (src));
9817 }
9818
9819 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
9820 const0_rtx));
9821
9822 size = 0;
9823
9824 for (i = 0; i < XVECLEN (par, 0); i++)
9825 {
9826 HOST_WIDE_INT offset = 0;
9827 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
9828
9829 if (size != 0)
29c05e22 9830 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 9831
9832 mem = change_address (mem, GET_MODE (reg), NULL);
9833 if (REGNO (reg) == R0_REGNUM)
9834 {
9835 /* On thumb we have to use a write-back instruction. */
320ea44d 9836 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
9837 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 9838 size = TARGET_ARM ? 16 : 0;
9839 }
9840 else
9841 {
9842 emit_move_insn (mem, reg);
9843 size = GET_MODE_SIZE (GET_MODE (reg));
9844 }
215b30b3 9845 }
9c08d1fa 9846
215b30b3 9847 /* The optimizer does not know that the call sets the function value
9848 registers we stored in the result block. We avoid problems by
9849 claiming that all hard registers are used and clobbered at this
9850 point. */
9851 emit_insn (gen_blockage ());
9852
9853 DONE;
9854 }"
9855)
9c08d1fa 9856
ccd90aaa 9857(define_expand "untyped_return"
9858 [(match_operand:BLK 0 "memory_operand" "")
9859 (match_operand 1 "" "")]
9860 "TARGET_EITHER"
9861 "
9862 {
9863 int i;
9864 rtx addr = gen_reg_rtx (Pmode);
9865 rtx mem;
9866 int size = 0;
9867
9868 emit_move_insn (addr, XEXP (operands[0], 0));
9869 mem = change_address (operands[0], BLKmode, addr);
9870
9871 for (i = 0; i < XVECLEN (operands[1], 0); i++)
9872 {
9873 HOST_WIDE_INT offset = 0;
9874 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
9875
9876 if (size != 0)
29c05e22 9877 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 9878
9879 mem = change_address (mem, GET_MODE (reg), NULL);
9880 if (REGNO (reg) == R0_REGNUM)
9881 {
9882 /* On thumb we have to use a write-back instruction. */
320ea44d 9883 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
9884 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 9885 size = TARGET_ARM ? 16 : 0;
9886 }
9887 else
9888 {
9889 emit_move_insn (reg, mem);
9890 size = GET_MODE_SIZE (GET_MODE (reg));
9891 }
9892 }
9893
9894 /* Emit USE insns before the return. */
9895 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 9896 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 9897
9898 /* Construct the return. */
9899 expand_naked_return ();
9900
9901 DONE;
9902 }"
9903)
9904
9c08d1fa 9905;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
9906;; all of memory. This blocks insns from being moved across this point.
9907
9908(define_insn "blockage"
e1159bbe 9909 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 9910 "TARGET_EITHER"
9c08d1fa 9911 ""
cffb2a26 9912 [(set_attr "length" "0")
9913 (set_attr "type" "block")]
9914)
9c08d1fa 9915
f7fbdd4a 9916(define_expand "casesi"
9917 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 9918 (match_operand:SI 1 "const_int_operand" "") ; lower bound
9919 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 9920 (match_operand:SI 3 "" "") ; table label
9921 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 9922 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 9923 "
215b30b3 9924 {
e6ac8414 9925 enum insn_code code;
215b30b3 9926 if (operands[1] != const0_rtx)
9927 {
e6ac8414 9928 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 9929
215b30b3 9930 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 9931 gen_int_mode (-INTVAL (operands[1]),
9932 SImode)));
215b30b3 9933 operands[0] = reg;
9934 }
9c08d1fa 9935
25f905c2 9936 if (TARGET_ARM)
e6ac8414 9937 code = CODE_FOR_arm_casesi_internal;
3db2019b 9938 else if (TARGET_THUMB1)
e6ac8414 9939 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 9940 else if (flag_pic)
e6ac8414 9941 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 9942 else
e6ac8414 9943 code = CODE_FOR_thumb2_casesi_internal;
9944
9945 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
9946 operands[2] = force_reg (SImode, operands[2]);
9947
9948 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
9949 operands[3], operands[4]));
215b30b3 9950 DONE;
9951 }"
9952)
f7fbdd4a 9953
f082f1c4 9954;; The USE in this pattern is needed to tell flow analysis that this is
9955;; a CASESI insn. It has no other purpose.
25f905c2 9956(define_insn "arm_casesi_internal"
f082f1c4 9957 [(parallel [(set (pc)
9958 (if_then_else
9959 (leu (match_operand:SI 0 "s_register_operand" "r")
9960 (match_operand:SI 1 "arm_rhs_operand" "rI"))
9961 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
9962 (label_ref (match_operand 2 "" ""))))
9963 (label_ref (match_operand 3 "" ""))))
bd5b4116 9964 (clobber (reg:CC CC_REGNUM))
f082f1c4 9965 (use (label_ref (match_dup 2)))])]
cffb2a26 9966 "TARGET_ARM"
f7fbdd4a 9967 "*
0d66636f 9968 if (flag_pic)
9969 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
9970 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
9971 "
9972 [(set_attr "conds" "clob")
9973 (set_attr "length" "12")]
9974)
9c08d1fa 9975
e6ac8414 9976(define_expand "thumb1_casesi_internal_pic"
9977 [(match_operand:SI 0 "s_register_operand" "")
9978 (match_operand:SI 1 "thumb1_cmp_operand" "")
9979 (match_operand 2 "" "")
9980 (match_operand 3 "" "")]
3db2019b 9981 "TARGET_THUMB1"
e6ac8414 9982 {
9983 rtx reg0;
9984 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
9985 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
9986 operands[3]));
9987 reg0 = gen_rtx_REG (SImode, 0);
9988 emit_move_insn (reg0, operands[0]);
9989 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
9990 DONE;
9991 }
9992)
9993
9994(define_insn "thumb1_casesi_dispatch"
9995 [(parallel [(set (pc) (unspec [(reg:SI 0)
9996 (label_ref (match_operand 0 "" ""))
9997;; (label_ref (match_operand 1 "" ""))
9998]
9999 UNSPEC_THUMB1_CASESI))
10000 (clobber (reg:SI IP_REGNUM))
10001 (clobber (reg:SI LR_REGNUM))])]
3db2019b 10002 "TARGET_THUMB1"
e6ac8414 10003 "* return thumb1_output_casesi(operands);"
10004 [(set_attr "length" "4")]
10005)
10006
cffb2a26 10007(define_expand "indirect_jump"
9c08d1fa 10008 [(set (pc)
cffb2a26 10009 (match_operand:SI 0 "s_register_operand" ""))]
10010 "TARGET_EITHER"
25f905c2 10011 "
10012 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
10013 address and use bx. */
10014 if (TARGET_THUMB2)
10015 {
10016 rtx tmp;
10017 tmp = gen_reg_rtx (SImode);
10018 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
10019 operands[0] = tmp;
10020 }
10021 "
cffb2a26 10022)
10023
f1039640 10024;; NB Never uses BX.
cffb2a26 10025(define_insn "*arm_indirect_jump"
10026 [(set (pc)
10027 (match_operand:SI 0 "s_register_operand" "r"))]
10028 "TARGET_ARM"
10029 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 10030 [(set_attr "predicable" "yes")]
cffb2a26 10031)
9c08d1fa 10032
f7fbdd4a 10033(define_insn "*load_indirect_jump"
9c08d1fa 10034 [(set (pc)
10035 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 10036 "TARGET_ARM"
10037 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 10038 [(set_attr "type" "load1")
61a2d04c 10039 (set_attr "pool_range" "4096")
10040 (set_attr "neg_pool_range" "4084")
0d66636f 10041 (set_attr "predicable" "yes")]
cffb2a26 10042)
10043
f1039640 10044;; NB Never uses BX.
25f905c2 10045(define_insn "*thumb1_indirect_jump"
cffb2a26 10046 [(set (pc)
10047 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 10048 "TARGET_THUMB1"
cffb2a26 10049 "mov\\tpc, %0"
10050 [(set_attr "conds" "clob")
10051 (set_attr "length" "2")]
10052)
10053
9c08d1fa 10054\f
10055;; Misc insns
10056
10057(define_insn "nop"
10058 [(const_int 0)]
cffb2a26 10059 "TARGET_EITHER"
10060 "*
25f905c2 10061 if (TARGET_UNIFIED_ASM)
10062 return \"nop\";
cffb2a26 10063 if (TARGET_ARM)
10064 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
10065 return \"mov\\tr8, r8\";
10066 "
10067 [(set (attr "length")
10068 (if_then_else (eq_attr "is_thumb" "yes")
10069 (const_int 2)
10070 (const_int 4)))]
10071)
10072
9c08d1fa 10073\f
10074;; Patterns to allow combination of arithmetic, cond code and shifts
10075
f7fbdd4a 10076(define_insn "*arith_shiftsi"
7392680c 10077 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9c08d1fa 10078 (match_operator:SI 1 "shiftable_operator"
10079 [(match_operator:SI 3 "shift_operator"
7392680c 10080 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
10081 (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
10082 (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
d5d4dc8d 10083 "TARGET_32BIT"
6c4c2133 10084 "%i1%?\\t%0, %2, %4%S3"
344495ea 10085 [(set_attr "predicable" "yes")
331beb1a 10086 (set_attr "shift" "4")
7392680c 10087 (set_attr "arch" "a,t2,t2,a")
10088 ;; Thumb2 doesn't allow the stack pointer to be used for
10089 ;; operand1 for all operations other than add and sub. In this case
10090 ;; the minus operation is a candidate for an rsub and hence needs
10091 ;; to be disabled.
10092 ;; We have to make sure to disable the fourth alternative if
d5d4dc8d 10093 ;; the shift_operator is MULT, since otherwise the insn will
10094 ;; also match a multiply_accumulate pattern and validate_change
10095 ;; will allow a replacement of the constant with a register
10096 ;; despite the checks done in shift_operator.
10097 (set_attr_alternative "insn_enabled"
10098 [(const_string "yes")
7392680c 10099 (if_then_else
10100 (match_operand:SI 1 "add_operator" "")
10101 (const_string "yes") (const_string "no"))
10102 (const_string "yes")
d5d4dc8d 10103 (if_then_else
10104 (match_operand:SI 3 "mult_operator" "")
10105 (const_string "no") (const_string "yes"))])
6b6abc9c 10106 (set_attr "type" "arlo_shift,arlo_shift,arlo_shift,arlo_shift_reg")])
9c08d1fa 10107
d7863cfe 10108(define_split
10109 [(set (match_operand:SI 0 "s_register_operand" "")
10110 (match_operator:SI 1 "shiftable_operator"
10111 [(match_operator:SI 2 "shiftable_operator"
10112 [(match_operator:SI 3 "shift_operator"
10113 [(match_operand:SI 4 "s_register_operand" "")
10114 (match_operand:SI 5 "reg_or_int_operand" "")])
10115 (match_operand:SI 6 "s_register_operand" "")])
10116 (match_operand:SI 7 "arm_rhs_operand" "")]))
10117 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 10118 "TARGET_32BIT"
d7863cfe 10119 [(set (match_dup 8)
10120 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
10121 (match_dup 6)]))
10122 (set (match_dup 0)
10123 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
10124 "")
10125
f7fbdd4a 10126(define_insn "*arith_shiftsi_compare0"
bd5b4116 10127 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 10128 (compare:CC_NOOV
10129 (match_operator:SI 1 "shiftable_operator"
10130 [(match_operator:SI 3 "shift_operator"
10131 [(match_operand:SI 4 "s_register_operand" "r,r")
10132 (match_operand:SI 5 "shift_amount_operand" "M,r")])
10133 (match_operand:SI 2 "s_register_operand" "r,r")])
10134 (const_int 0)))
10135 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 10136 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
10137 (match_dup 2)]))]
d5d4dc8d 10138 "TARGET_32BIT"
25f905c2 10139 "%i1%.\\t%0, %2, %4%S3"
344495ea 10140 [(set_attr "conds" "set")
331beb1a 10141 (set_attr "shift" "4")
d5d4dc8d 10142 (set_attr "arch" "32,a")
6b6abc9c 10143 (set_attr "type" "arlo_shift,arlo_shift_reg")])
9c08d1fa 10144
f7fbdd4a 10145(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 10146 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 10147 (compare:CC_NOOV
10148 (match_operator:SI 1 "shiftable_operator"
10149 [(match_operator:SI 3 "shift_operator"
10150 [(match_operand:SI 4 "s_register_operand" "r,r")
10151 (match_operand:SI 5 "shift_amount_operand" "M,r")])
10152 (match_operand:SI 2 "s_register_operand" "r,r")])
10153 (const_int 0)))
10154 (clobber (match_scratch:SI 0 "=r,r"))]
10155 "TARGET_32BIT"
25f905c2 10156 "%i1%.\\t%0, %2, %4%S3"
344495ea 10157 [(set_attr "conds" "set")
331beb1a 10158 (set_attr "shift" "4")
d5d4dc8d 10159 (set_attr "arch" "32,a")
6b6abc9c 10160 (set_attr "type" "arlo_shift,arlo_shift_reg")])
9c08d1fa 10161
f7fbdd4a 10162(define_insn "*sub_shiftsi"
d5d4dc8d 10163 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10164 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 10165 (match_operator:SI 2 "shift_operator"
d5d4dc8d 10166 [(match_operand:SI 3 "s_register_operand" "r,r")
10167 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
10168 "TARGET_32BIT"
6c4c2133 10169 "sub%?\\t%0, %1, %3%S2"
344495ea 10170 [(set_attr "predicable" "yes")
331beb1a 10171 (set_attr "shift" "3")
d5d4dc8d 10172 (set_attr "arch" "32,a")
6b6abc9c 10173 (set_attr "type" "arlo_shift,arlo_shift_reg")])
9c08d1fa 10174
f7fbdd4a 10175(define_insn "*sub_shiftsi_compare0"
bd5b4116 10176 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 10177 (compare:CC_NOOV
d5d4dc8d 10178 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 10179 (match_operator:SI 2 "shift_operator"
d5d4dc8d 10180 [(match_operand:SI 3 "s_register_operand" "r,r")
10181 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 10182 (const_int 0)))
d5d4dc8d 10183 (set (match_operand:SI 0 "s_register_operand" "=r,r")
10184 (minus:SI (match_dup 1)
10185 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
10186 "TARGET_32BIT"
25f905c2 10187 "sub%.\\t%0, %1, %3%S2"
344495ea 10188 [(set_attr "conds" "set")
a2cd141b 10189 (set_attr "shift" "3")
d5d4dc8d 10190 (set_attr "arch" "32,a")
6b6abc9c 10191 (set_attr "type" "arlo_shift,arlo_shift_reg")])
9c08d1fa 10192
f7fbdd4a 10193(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 10194 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 10195 (compare:CC_NOOV
d5d4dc8d 10196 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 10197 (match_operator:SI 2 "shift_operator"
d5d4dc8d 10198 [(match_operand:SI 3 "s_register_operand" "r,r")
10199 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 10200 (const_int 0)))
d5d4dc8d 10201 (clobber (match_scratch:SI 0 "=r,r"))]
10202 "TARGET_32BIT"
25f905c2 10203 "sub%.\\t%0, %1, %3%S2"
344495ea 10204 [(set_attr "conds" "set")
a2cd141b 10205 (set_attr "shift" "3")
d5d4dc8d 10206 (set_attr "arch" "32,a")
6b6abc9c 10207 (set_attr "type" "arlo_shift,arlo_shift_reg")])
9c08d1fa 10208\f
10209
190efb17 10210(define_insn_and_split "*and_scc"
9c08d1fa 10211 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10212 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 10213 [(match_operand 2 "cc_register" "") (const_int 0)])
10214 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 10215 "TARGET_ARM"
190efb17 10216 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
10217 "&& reload_completed"
10218 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
10219 (cond_exec (match_dup 4) (set (match_dup 0)
10220 (and:SI (match_dup 3) (const_int 1))))]
10221 {
10222 enum machine_mode mode = GET_MODE (operands[2]);
10223 enum rtx_code rc = GET_CODE (operands[1]);
10224
10225 /* Note that operands[4] is the same as operands[1],
10226 but with VOIDmode as the result. */
10227 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10228 if (mode == CCFPmode || mode == CCFPEmode)
10229 rc = reverse_condition_maybe_unordered (rc);
10230 else
10231 rc = reverse_condition (rc);
10232 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10233 }
8fa3ba89 10234 [(set_attr "conds" "use")
1aed5204 10235 (set_attr "type" "mov_reg")
8fa3ba89 10236 (set_attr "length" "8")]
10237)
9c08d1fa 10238
190efb17 10239(define_insn_and_split "*ior_scc"
9c08d1fa 10240 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 10241 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
10242 [(match_operand 2 "cc_register" "") (const_int 0)])
10243 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 10244 "TARGET_ARM"
e2348bcb 10245 "@
190efb17 10246 orr%d1\\t%0, %3, #1
10247 #"
10248 "&& reload_completed
10249 && REGNO (operands [0]) != REGNO (operands[3])"
10250 ;; && which_alternative == 1
10251 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
10252 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
10253 (cond_exec (match_dup 4) (set (match_dup 0)
10254 (ior:SI (match_dup 3) (const_int 1))))]
10255 {
10256 enum machine_mode mode = GET_MODE (operands[2]);
10257 enum rtx_code rc = GET_CODE (operands[1]);
10258
10259 /* Note that operands[4] is the same as operands[1],
10260 but with VOIDmode as the result. */
10261 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10262 if (mode == CCFPmode || mode == CCFPEmode)
10263 rc = reverse_condition_maybe_unordered (rc);
10264 else
10265 rc = reverse_condition (rc);
10266 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10267 }
8fa3ba89 10268 [(set_attr "conds" "use")
10269 (set_attr "length" "4,8")]
10270)
9c08d1fa 10271
2df9477b 10272; A series of splitters for the compare_scc pattern below. Note that
10273; order is important.
10274(define_split
10275 [(set (match_operand:SI 0 "s_register_operand" "")
10276 (lt:SI (match_operand:SI 1 "s_register_operand" "")
10277 (const_int 0)))
10278 (clobber (reg:CC CC_REGNUM))]
10279 "TARGET_32BIT && reload_completed"
10280 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
10281
10282(define_split
10283 [(set (match_operand:SI 0 "s_register_operand" "")
10284 (ge:SI (match_operand:SI 1 "s_register_operand" "")
10285 (const_int 0)))
10286 (clobber (reg:CC CC_REGNUM))]
10287 "TARGET_32BIT && reload_completed"
10288 [(set (match_dup 0) (not:SI (match_dup 1)))
10289 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
10290
98562479 10291(define_split
10292 [(set (match_operand:SI 0 "s_register_operand" "")
10293 (eq:SI (match_operand:SI 1 "s_register_operand" "")
10294 (const_int 0)))
10295 (clobber (reg:CC CC_REGNUM))]
10296 "arm_arch5 && TARGET_32BIT"
10297 [(set (match_dup 0) (clz:SI (match_dup 1)))
10298 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
10299)
10300
2df9477b 10301(define_split
10302 [(set (match_operand:SI 0 "s_register_operand" "")
10303 (eq:SI (match_operand:SI 1 "s_register_operand" "")
10304 (const_int 0)))
10305 (clobber (reg:CC CC_REGNUM))]
10306 "TARGET_32BIT && reload_completed"
10307 [(parallel
080c0b9a 10308 [(set (reg:CC CC_REGNUM)
10309 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 10310 (set (match_dup 0)
10311 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 10312 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 10313 (set (match_dup 0) (const_int 0)))])
10314
10315(define_split
10316 [(set (match_operand:SI 0 "s_register_operand" "")
10317 (ne:SI (match_operand:SI 1 "s_register_operand" "")
10318 (match_operand:SI 2 "const_int_operand" "")))
10319 (clobber (reg:CC CC_REGNUM))]
10320 "TARGET_32BIT && reload_completed"
10321 [(parallel
10322 [(set (reg:CC CC_REGNUM)
10323 (compare:CC (match_dup 1) (match_dup 2)))
10324 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
10325 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
10326 (set (match_dup 0) (const_int 1)))]
10327{
10328 operands[3] = GEN_INT (-INTVAL (operands[2]));
10329})
10330
10331(define_split
10332 [(set (match_operand:SI 0 "s_register_operand" "")
10333 (ne:SI (match_operand:SI 1 "s_register_operand" "")
10334 (match_operand:SI 2 "arm_add_operand" "")))
10335 (clobber (reg:CC CC_REGNUM))]
10336 "TARGET_32BIT && reload_completed"
10337 [(parallel
10338 [(set (reg:CC_NOOV CC_REGNUM)
10339 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
10340 (const_int 0)))
10341 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
10342 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
10343 (set (match_dup 0) (const_int 1)))])
10344
10345(define_insn_and_split "*compare_scc"
fd711051 10346 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 10347 (match_operator:SI 1 "arm_comparison_operator"
5565501b 10348 [(match_operand:SI 2 "s_register_operand" "r,r")
10349 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 10350 (clobber (reg:CC CC_REGNUM))]
2df9477b 10351 "TARGET_32BIT"
10352 "#"
10353 "&& reload_completed"
10354 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
10355 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
10356 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
10357{
10358 rtx tmp1;
10359 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10360 operands[2], operands[3]);
10361 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 10362
2df9477b 10363 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 10364
2df9477b 10365 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
10366 if (mode == CCFPmode || mode == CCFPEmode)
10367 rc = reverse_condition_maybe_unordered (rc);
10368 else
10369 rc = reverse_condition (rc);
10370 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
10371})
9c08d1fa 10372
080c0b9a 10373;; Attempt to improve the sequence generated by the compare_scc splitters
10374;; not to use conditional execution.
98562479 10375
10376;; Rd = (eq (reg1) (const_int0)) // ARMv5
10377;; clz Rd, reg1
10378;; lsr Rd, Rd, #5
080c0b9a 10379(define_peephole2
10380 [(set (reg:CC CC_REGNUM)
10381 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 10382 (const_int 0)))
10383 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10384 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10385 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10386 (set (match_dup 0) (const_int 1)))]
10387 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
10388 [(set (match_dup 0) (clz:SI (match_dup 1)))
10389 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
10390)
10391
10392;; Rd = (eq (reg1) (const_int0)) // !ARMv5
10393;; negs Rd, reg1
10394;; adc Rd, Rd, reg1
10395(define_peephole2
10396 [(set (reg:CC CC_REGNUM)
10397 (compare:CC (match_operand:SI 1 "register_operand" "")
10398 (const_int 0)))
080c0b9a 10399 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10400 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10401 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10402 (set (match_dup 0) (const_int 1)))
98562479 10403 (match_scratch:SI 2 "r")]
10404 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 10405 [(parallel
10406 [(set (reg:CC CC_REGNUM)
98562479 10407 (compare:CC (const_int 0) (match_dup 1)))
10408 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
10409 (set (match_dup 0)
10410 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
10411 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
10412)
10413
10414;; Rd = (eq (reg1) (reg2/imm)) // ARMv5
10415;; sub Rd, Reg1, reg2
10416;; clz Rd, Rd
10417;; lsr Rd, Rd, #5
10418(define_peephole2
10419 [(set (reg:CC CC_REGNUM)
10420 (compare:CC (match_operand:SI 1 "register_operand" "")
10421 (match_operand:SI 2 "arm_rhs_operand" "")))
10422 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10423 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10424 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10425 (set (match_dup 0) (const_int 1)))]
10426 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
10427 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
10428 (set (match_dup 0) (clz:SI (match_dup 0)))
10429 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
10430)
10431
10432
10433;; Rd = (eq (reg1) (reg2/imm)) // ! ARMv5
10434;; sub T1, Reg1, reg2
10435;; negs Rd, T1
10436;; adc Rd, Rd, T1
10437(define_peephole2
10438 [(set (reg:CC CC_REGNUM)
10439 (compare:CC (match_operand:SI 1 "register_operand" "")
10440 (match_operand:SI 2 "arm_rhs_operand" "")))
10441 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10442 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10443 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10444 (set (match_dup 0) (const_int 1)))
10445 (match_scratch:SI 3 "r")]
10446 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
10447 [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
080c0b9a 10448 (parallel
10449 [(set (reg:CC CC_REGNUM)
10450 (compare:CC (const_int 0) (match_dup 3)))
10451 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 10452 (set (match_dup 0)
10453 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
10454 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
10455)
080c0b9a 10456
f7fbdd4a 10457(define_insn "*cond_move"
9c08d1fa 10458 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 10459 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 10460 [(match_operator 4 "arm_comparison_operator"
8a18b90c 10461 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 10462 (const_int 0)])
10463 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
10464 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 10465 "TARGET_ARM"
9c08d1fa 10466 "*
8fa3ba89 10467 if (GET_CODE (operands[3]) == NE)
10468 {
10469 if (which_alternative != 1)
10470 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
10471 if (which_alternative != 0)
10472 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
10473 return \"\";
10474 }
10475 if (which_alternative != 0)
10476 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
10477 if (which_alternative != 1)
10478 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
10479 return \"\";
10480 "
10481 [(set_attr "conds" "use")
1aed5204 10482 (set_attr "type" "mov_reg")
8fa3ba89 10483 (set_attr "length" "4,4,8")]
10484)
9c08d1fa 10485
f7fbdd4a 10486(define_insn "*cond_arith"
9c08d1fa 10487 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10488 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 10489 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 10490 [(match_operand:SI 2 "s_register_operand" "r,r")
10491 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10492 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 10493 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10494 "TARGET_ARM"
9c08d1fa 10495 "*
8fa3ba89 10496 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
10497 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 10498
8fa3ba89 10499 output_asm_insn (\"cmp\\t%2, %3\", operands);
10500 if (GET_CODE (operands[5]) == AND)
10501 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
10502 else if (GET_CODE (operands[5]) == MINUS)
10503 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
10504 else if (which_alternative != 0)
10505 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
10506 return \"%i5%d4\\t%0, %1, #1\";
10507 "
10508 [(set_attr "conds" "clob")
10509 (set_attr "length" "12")]
10510)
9c08d1fa 10511
f7fbdd4a 10512(define_insn "*cond_sub"
9c08d1fa 10513 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10514 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 10515 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 10516 [(match_operand:SI 2 "s_register_operand" "r,r")
10517 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10518 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10519 "TARGET_ARM"
9c08d1fa 10520 "*
8fa3ba89 10521 output_asm_insn (\"cmp\\t%2, %3\", operands);
10522 if (which_alternative != 0)
10523 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
10524 return \"sub%d4\\t%0, %1, #1\";
10525 "
10526 [(set_attr "conds" "clob")
10527 (set_attr "length" "8,12")]
10528)
9c08d1fa 10529
aea4c774 10530(define_insn "*cmp_ite0"
cffb2a26 10531 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 10532 (compare
10533 (if_then_else:SI
8fa3ba89 10534 (match_operator 4 "arm_comparison_operator"
2ff91fec 10535 [(match_operand:SI 0 "s_register_operand"
10536 "l,l,l,r,r,r,r,r,r")
10537 (match_operand:SI 1 "arm_add_operand"
10538 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 10539 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 10540 [(match_operand:SI 2 "s_register_operand"
10541 "l,r,r,l,l,r,r,r,r")
10542 (match_operand:SI 3 "arm_add_operand"
10543 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 10544 (const_int 0))
10545 (const_int 0)))]
2ff91fec 10546 "TARGET_32BIT"
9c08d1fa 10547 "*
aea4c774 10548 {
2ff91fec 10549 static const char * const cmp1[NUM_OF_COND_CMP][2] =
10550 {
10551 {\"cmp%d5\\t%0, %1\",
10552 \"cmp%d4\\t%2, %3\"},
10553 {\"cmn%d5\\t%0, #%n1\",
10554 \"cmp%d4\\t%2, %3\"},
10555 {\"cmp%d5\\t%0, %1\",
10556 \"cmn%d4\\t%2, #%n3\"},
10557 {\"cmn%d5\\t%0, #%n1\",
10558 \"cmn%d4\\t%2, #%n3\"}
10559 };
10560 static const char * const cmp2[NUM_OF_COND_CMP][2] =
10561 {
10562 {\"cmp\\t%2, %3\",
10563 \"cmp\\t%0, %1\"},
10564 {\"cmp\\t%2, %3\",
10565 \"cmn\\t%0, #%n1\"},
10566 {\"cmn\\t%2, #%n3\",
10567 \"cmp\\t%0, %1\"},
10568 {\"cmn\\t%2, #%n3\",
10569 \"cmn\\t%0, #%n1\"}
10570 };
10571 static const char * const ite[2] =
8fa3ba89 10572 {
2ff91fec 10573 \"it\\t%d5\",
10574 \"it\\t%d4\"
8fa3ba89 10575 };
2ff91fec 10576 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10577 CMP_CMP, CMN_CMP, CMP_CMP,
10578 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 10579 int swap =
10580 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
10581
2ff91fec 10582 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10583 if (TARGET_THUMB2) {
10584 output_asm_insn (ite[swap], operands);
10585 }
10586 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10587 return \"\";
8fa3ba89 10588 }"
10589 [(set_attr "conds" "set")
2ff91fec 10590 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
10591 (set_attr_alternative "length"
10592 [(const_int 6)
10593 (const_int 8)
10594 (const_int 8)
10595 (const_int 8)
10596 (const_int 8)
10597 (if_then_else (eq_attr "is_thumb" "no")
10598 (const_int 8)
10599 (const_int 10))
10600 (if_then_else (eq_attr "is_thumb" "no")
10601 (const_int 8)
10602 (const_int 10))
10603 (if_then_else (eq_attr "is_thumb" "no")
10604 (const_int 8)
10605 (const_int 10))
10606 (if_then_else (eq_attr "is_thumb" "no")
10607 (const_int 8)
10608 (const_int 10))])]
8fa3ba89 10609)
9c08d1fa 10610
aea4c774 10611(define_insn "*cmp_ite1"
cffb2a26 10612 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 10613 (compare
10614 (if_then_else:SI
8fa3ba89 10615 (match_operator 4 "arm_comparison_operator"
2ff91fec 10616 [(match_operand:SI 0 "s_register_operand"
10617 "l,l,l,r,r,r,r,r,r")
10618 (match_operand:SI 1 "arm_add_operand"
10619 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 10620 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 10621 [(match_operand:SI 2 "s_register_operand"
10622 "l,r,r,l,l,r,r,r,r")
10623 (match_operand:SI 3 "arm_add_operand"
10624 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 10625 (const_int 1))
10626 (const_int 0)))]
2ff91fec 10627 "TARGET_32BIT"
9c08d1fa 10628 "*
9c08d1fa 10629 {
2ff91fec 10630 static const char * const cmp1[NUM_OF_COND_CMP][2] =
10631 {
10632 {\"cmp\\t%0, %1\",
10633 \"cmp\\t%2, %3\"},
10634 {\"cmn\\t%0, #%n1\",
10635 \"cmp\\t%2, %3\"},
10636 {\"cmp\\t%0, %1\",
10637 \"cmn\\t%2, #%n3\"},
10638 {\"cmn\\t%0, #%n1\",
10639 \"cmn\\t%2, #%n3\"}
10640 };
10641 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 10642 {
2ff91fec 10643 {\"cmp%d4\\t%2, %3\",
10644 \"cmp%D5\\t%0, %1\"},
10645 {\"cmp%d4\\t%2, %3\",
10646 \"cmn%D5\\t%0, #%n1\"},
10647 {\"cmn%d4\\t%2, #%n3\",
10648 \"cmp%D5\\t%0, %1\"},
10649 {\"cmn%d4\\t%2, #%n3\",
10650 \"cmn%D5\\t%0, #%n1\"}
215b30b3 10651 };
2ff91fec 10652 static const char * const ite[2] =
10653 {
10654 \"it\\t%d4\",
10655 \"it\\t%D5\"
10656 };
10657 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10658 CMP_CMP, CMN_CMP, CMP_CMP,
10659 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 10660 int swap =
10661 comparison_dominates_p (GET_CODE (operands[5]),
10662 reverse_condition (GET_CODE (operands[4])));
10663
2ff91fec 10664 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10665 if (TARGET_THUMB2) {
10666 output_asm_insn (ite[swap], operands);
10667 }
10668 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10669 return \"\";
215b30b3 10670 }"
8fa3ba89 10671 [(set_attr "conds" "set")
2ff91fec 10672 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
10673 (set_attr_alternative "length"
10674 [(const_int 6)
10675 (const_int 8)
10676 (const_int 8)
10677 (const_int 8)
10678 (const_int 8)
10679 (if_then_else (eq_attr "is_thumb" "no")
10680 (const_int 8)
10681 (const_int 10))
10682 (if_then_else (eq_attr "is_thumb" "no")
10683 (const_int 8)
10684 (const_int 10))
10685 (if_then_else (eq_attr "is_thumb" "no")
10686 (const_int 8)
10687 (const_int 10))
10688 (if_then_else (eq_attr "is_thumb" "no")
10689 (const_int 8)
10690 (const_int 10))])]
8fa3ba89 10691)
9c08d1fa 10692
f6c53574 10693(define_insn "*cmp_and"
10694 [(set (match_operand 6 "dominant_cc_register" "")
10695 (compare
10696 (and:SI
10697 (match_operator 4 "arm_comparison_operator"
2ff91fec 10698 [(match_operand:SI 0 "s_register_operand"
10699 "l,l,l,r,r,r,r,r,r")
10700 (match_operand:SI 1 "arm_add_operand"
10701 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 10702 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 10703 [(match_operand:SI 2 "s_register_operand"
10704 "l,r,r,l,l,r,r,r,r")
10705 (match_operand:SI 3 "arm_add_operand"
10706 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 10707 (const_int 0)))]
2ff91fec 10708 "TARGET_32BIT"
f6c53574 10709 "*
10710 {
2ff91fec 10711 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 10712 {
2ff91fec 10713 {\"cmp%d5\\t%0, %1\",
10714 \"cmp%d4\\t%2, %3\"},
10715 {\"cmn%d5\\t%0, #%n1\",
10716 \"cmp%d4\\t%2, %3\"},
10717 {\"cmp%d5\\t%0, %1\",
10718 \"cmn%d4\\t%2, #%n3\"},
10719 {\"cmn%d5\\t%0, #%n1\",
10720 \"cmn%d4\\t%2, #%n3\"}
f6c53574 10721 };
2ff91fec 10722 static const char *const cmp2[NUM_OF_COND_CMP][2] =
10723 {
10724 {\"cmp\\t%2, %3\",
10725 \"cmp\\t%0, %1\"},
10726 {\"cmp\\t%2, %3\",
10727 \"cmn\\t%0, #%n1\"},
10728 {\"cmn\\t%2, #%n3\",
10729 \"cmp\\t%0, %1\"},
10730 {\"cmn\\t%2, #%n3\",
10731 \"cmn\\t%0, #%n1\"}
10732 };
10733 static const char *const ite[2] =
10734 {
10735 \"it\\t%d5\",
10736 \"it\\t%d4\"
10737 };
10738 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10739 CMP_CMP, CMN_CMP, CMP_CMP,
10740 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 10741 int swap =
10742 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
10743
2ff91fec 10744 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10745 if (TARGET_THUMB2) {
10746 output_asm_insn (ite[swap], operands);
10747 }
10748 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10749 return \"\";
f6c53574 10750 }"
10751 [(set_attr "conds" "set")
10752 (set_attr "predicable" "no")
2ff91fec 10753 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
10754 (set_attr_alternative "length"
10755 [(const_int 6)
10756 (const_int 8)
10757 (const_int 8)
10758 (const_int 8)
10759 (const_int 8)
10760 (if_then_else (eq_attr "is_thumb" "no")
10761 (const_int 8)
10762 (const_int 10))
10763 (if_then_else (eq_attr "is_thumb" "no")
10764 (const_int 8)
10765 (const_int 10))
10766 (if_then_else (eq_attr "is_thumb" "no")
10767 (const_int 8)
10768 (const_int 10))
10769 (if_then_else (eq_attr "is_thumb" "no")
10770 (const_int 8)
10771 (const_int 10))])]
f6c53574 10772)
10773
10774(define_insn "*cmp_ior"
10775 [(set (match_operand 6 "dominant_cc_register" "")
10776 (compare
10777 (ior:SI
10778 (match_operator 4 "arm_comparison_operator"
2ff91fec 10779 [(match_operand:SI 0 "s_register_operand"
10780 "l,l,l,r,r,r,r,r,r")
10781 (match_operand:SI 1 "arm_add_operand"
10782 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 10783 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 10784 [(match_operand:SI 2 "s_register_operand"
10785 "l,r,r,l,l,r,r,r,r")
10786 (match_operand:SI 3 "arm_add_operand"
10787 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 10788 (const_int 0)))]
2ff91fec 10789 "TARGET_32BIT"
f6c53574 10790 "*
f6c53574 10791 {
2ff91fec 10792 static const char *const cmp1[NUM_OF_COND_CMP][2] =
10793 {
10794 {\"cmp\\t%0, %1\",
10795 \"cmp\\t%2, %3\"},
10796 {\"cmn\\t%0, #%n1\",
10797 \"cmp\\t%2, %3\"},
10798 {\"cmp\\t%0, %1\",
10799 \"cmn\\t%2, #%n3\"},
10800 {\"cmn\\t%0, #%n1\",
10801 \"cmn\\t%2, #%n3\"}
10802 };
10803 static const char *const cmp2[NUM_OF_COND_CMP][2] =
10804 {
10805 {\"cmp%D4\\t%2, %3\",
10806 \"cmp%D5\\t%0, %1\"},
10807 {\"cmp%D4\\t%2, %3\",
10808 \"cmn%D5\\t%0, #%n1\"},
10809 {\"cmn%D4\\t%2, #%n3\",
10810 \"cmp%D5\\t%0, %1\"},
10811 {\"cmn%D4\\t%2, #%n3\",
10812 \"cmn%D5\\t%0, #%n1\"}
10813 };
10814 static const char *const ite[2] =
10815 {
10816 \"it\\t%D4\",
10817 \"it\\t%D5\"
10818 };
10819 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10820 CMP_CMP, CMN_CMP, CMP_CMP,
10821 CMN_CMP, CMP_CMN, CMN_CMN};
10822 int swap =
10823 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
10824
10825 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10826 if (TARGET_THUMB2) {
10827 output_asm_insn (ite[swap], operands);
10828 }
10829 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10830 return \"\";
10831 }
10832 "
f6c53574 10833 [(set_attr "conds" "set")
2ff91fec 10834 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
10835 (set_attr_alternative "length"
10836 [(const_int 6)
10837 (const_int 8)
10838 (const_int 8)
10839 (const_int 8)
10840 (const_int 8)
10841 (if_then_else (eq_attr "is_thumb" "no")
10842 (const_int 8)
10843 (const_int 10))
10844 (if_then_else (eq_attr "is_thumb" "no")
10845 (const_int 8)
10846 (const_int 10))
10847 (if_then_else (eq_attr "is_thumb" "no")
10848 (const_int 8)
10849 (const_int 10))
10850 (if_then_else (eq_attr "is_thumb" "no")
10851 (const_int 8)
10852 (const_int 10))])]
f6c53574 10853)
10854
3c5afce6 10855(define_insn_and_split "*ior_scc_scc"
fd711051 10856 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 10857 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
10858 [(match_operand:SI 1 "s_register_operand" "r")
10859 (match_operand:SI 2 "arm_add_operand" "rIL")])
10860 (match_operator:SI 6 "arm_comparison_operator"
10861 [(match_operand:SI 4 "s_register_operand" "r")
10862 (match_operand:SI 5 "arm_add_operand" "rIL")])))
10863 (clobber (reg:CC CC_REGNUM))]
2ff91fec 10864 "TARGET_32BIT
3c5afce6 10865 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
10866 != CCmode)"
10867 "#"
2ff91fec 10868 "TARGET_32BIT && reload_completed"
3c5afce6 10869 [(set (match_dup 7)
10870 (compare
10871 (ior:SI
10872 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10873 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10874 (const_int 0)))
10875 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
10876 "operands[7]
10877 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
10878 DOM_CC_X_OR_Y),
601f584c 10879 CC_REGNUM);"
10880 [(set_attr "conds" "clob")
10881 (set_attr "length" "16")])
10882
10883; If the above pattern is followed by a CMP insn, then the compare is
10884; redundant, since we can rework the conditional instruction that follows.
10885(define_insn_and_split "*ior_scc_scc_cmp"
10886 [(set (match_operand 0 "dominant_cc_register" "")
10887 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
10888 [(match_operand:SI 1 "s_register_operand" "r")
10889 (match_operand:SI 2 "arm_add_operand" "rIL")])
10890 (match_operator:SI 6 "arm_comparison_operator"
10891 [(match_operand:SI 4 "s_register_operand" "r")
10892 (match_operand:SI 5 "arm_add_operand" "rIL")]))
10893 (const_int 0)))
fd711051 10894 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 10895 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10896 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 10897 "TARGET_32BIT"
601f584c 10898 "#"
2ff91fec 10899 "TARGET_32BIT && reload_completed"
601f584c 10900 [(set (match_dup 0)
10901 (compare
10902 (ior:SI
10903 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10904 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10905 (const_int 0)))
10906 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
10907 ""
10908 [(set_attr "conds" "set")
10909 (set_attr "length" "16")])
3c5afce6 10910
10911(define_insn_and_split "*and_scc_scc"
fd711051 10912 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 10913 (and:SI (match_operator:SI 3 "arm_comparison_operator"
10914 [(match_operand:SI 1 "s_register_operand" "r")
10915 (match_operand:SI 2 "arm_add_operand" "rIL")])
10916 (match_operator:SI 6 "arm_comparison_operator"
10917 [(match_operand:SI 4 "s_register_operand" "r")
10918 (match_operand:SI 5 "arm_add_operand" "rIL")])))
10919 (clobber (reg:CC CC_REGNUM))]
2ff91fec 10920 "TARGET_32BIT
3c5afce6 10921 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
10922 != CCmode)"
10923 "#"
2ff91fec 10924 "TARGET_32BIT && reload_completed
601f584c 10925 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
10926 != CCmode)"
3c5afce6 10927 [(set (match_dup 7)
10928 (compare
10929 (and:SI
10930 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10931 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10932 (const_int 0)))
10933 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
10934 "operands[7]
10935 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
10936 DOM_CC_X_AND_Y),
601f584c 10937 CC_REGNUM);"
10938 [(set_attr "conds" "clob")
10939 (set_attr "length" "16")])
10940
10941; If the above pattern is followed by a CMP insn, then the compare is
10942; redundant, since we can rework the conditional instruction that follows.
10943(define_insn_and_split "*and_scc_scc_cmp"
10944 [(set (match_operand 0 "dominant_cc_register" "")
10945 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
10946 [(match_operand:SI 1 "s_register_operand" "r")
10947 (match_operand:SI 2 "arm_add_operand" "rIL")])
10948 (match_operator:SI 6 "arm_comparison_operator"
10949 [(match_operand:SI 4 "s_register_operand" "r")
10950 (match_operand:SI 5 "arm_add_operand" "rIL")]))
10951 (const_int 0)))
fd711051 10952 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 10953 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10954 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 10955 "TARGET_32BIT"
601f584c 10956 "#"
2ff91fec 10957 "TARGET_32BIT && reload_completed"
601f584c 10958 [(set (match_dup 0)
10959 (compare
10960 (and:SI
10961 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10962 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10963 (const_int 0)))
10964 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
10965 ""
10966 [(set_attr "conds" "set")
10967 (set_attr "length" "16")])
10968
10969;; If there is no dominance in the comparison, then we can still save an
10970;; instruction in the AND case, since we can know that the second compare
10971;; need only zero the value if false (if true, then the value is already
10972;; correct).
10973(define_insn_and_split "*and_scc_scc_nodom"
fd711051 10974 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 10975 (and:SI (match_operator:SI 3 "arm_comparison_operator"
10976 [(match_operand:SI 1 "s_register_operand" "r,r,0")
10977 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
10978 (match_operator:SI 6 "arm_comparison_operator"
10979 [(match_operand:SI 4 "s_register_operand" "r,r,r")
10980 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
10981 (clobber (reg:CC CC_REGNUM))]
2ff91fec 10982 "TARGET_32BIT
601f584c 10983 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
10984 == CCmode)"
10985 "#"
2ff91fec 10986 "TARGET_32BIT && reload_completed"
601f584c 10987 [(parallel [(set (match_dup 0)
10988 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
10989 (clobber (reg:CC CC_REGNUM))])
10990 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
10991 (set (match_dup 0)
10992 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
10993 (match_dup 0)
10994 (const_int 0)))]
10995 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
10996 operands[4], operands[5]),
10997 CC_REGNUM);
10998 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
10999 operands[5]);"
11000 [(set_attr "conds" "clob")
11001 (set_attr "length" "20")])
3c5afce6 11002
3a0bdee0 11003(define_split
11004 [(set (reg:CC_NOOV CC_REGNUM)
11005 (compare:CC_NOOV (ior:SI
11006 (and:SI (match_operand:SI 0 "s_register_operand" "")
11007 (const_int 1))
b0694be0 11008 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 11009 [(match_operand:SI 2 "s_register_operand" "")
11010 (match_operand:SI 3 "arm_add_operand" "")]))
11011 (const_int 0)))
11012 (clobber (match_operand:SI 4 "s_register_operand" ""))]
11013 "TARGET_ARM"
11014 [(set (match_dup 4)
11015 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
11016 (match_dup 0)))
11017 (set (reg:CC_NOOV CC_REGNUM)
11018 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
11019 (const_int 0)))]
11020 "")
11021
11022(define_split
11023 [(set (reg:CC_NOOV CC_REGNUM)
11024 (compare:CC_NOOV (ior:SI
b0694be0 11025 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 11026 [(match_operand:SI 2 "s_register_operand" "")
11027 (match_operand:SI 3 "arm_add_operand" "")])
11028 (and:SI (match_operand:SI 0 "s_register_operand" "")
11029 (const_int 1)))
11030 (const_int 0)))
11031 (clobber (match_operand:SI 4 "s_register_operand" ""))]
11032 "TARGET_ARM"
11033 [(set (match_dup 4)
11034 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
11035 (match_dup 0)))
11036 (set (reg:CC_NOOV CC_REGNUM)
11037 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
11038 (const_int 0)))]
11039 "")
25f905c2 11040;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 11041
190efb17 11042(define_insn_and_split "*negscc"
9c08d1fa 11043 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 11044 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 11045 [(match_operand:SI 1 "s_register_operand" "r")
11046 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 11047 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11048 "TARGET_ARM"
190efb17 11049 "#"
11050 "&& reload_completed"
11051 [(const_int 0)]
11052 {
11053 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 11054
190efb17 11055 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
11056 {
11057 /* Emit mov\\t%0, %1, asr #31 */
11058 emit_insn (gen_rtx_SET (VOIDmode,
11059 operands[0],
11060 gen_rtx_ASHIFTRT (SImode,
11061 operands[1],
11062 GEN_INT (31))));
11063 DONE;
11064 }
11065 else if (GET_CODE (operands[3]) == NE)
11066 {
11067 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
11068 if (CONST_INT_P (operands[2]))
11069 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
11070 GEN_INT (- INTVAL (operands[2]))));
11071 else
11072 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
11073
11074 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
11075 gen_rtx_NE (SImode,
11076 cc_reg,
11077 const0_rtx),
11078 gen_rtx_SET (SImode,
11079 operands[0],
11080 GEN_INT (~0))));
11081 DONE;
11082 }
11083 else
11084 {
11085 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
11086 emit_insn (gen_rtx_SET (VOIDmode,
11087 cc_reg,
11088 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
11089 enum rtx_code rc = GET_CODE (operands[3]);
11090
11091 rc = reverse_condition (rc);
11092 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
11093 gen_rtx_fmt_ee (rc,
11094 VOIDmode,
11095 cc_reg,
11096 const0_rtx),
11097 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
11098 rc = GET_CODE (operands[3]);
11099 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
11100 gen_rtx_fmt_ee (rc,
11101 VOIDmode,
11102 cc_reg,
11103 const0_rtx),
11104 gen_rtx_SET (VOIDmode,
11105 operands[0],
11106 GEN_INT (~0))));
11107 DONE;
11108 }
11109 FAIL;
11110 }
8fa3ba89 11111 [(set_attr "conds" "clob")
11112 (set_attr "length" "12")]
11113)
9c08d1fa 11114
11115(define_insn "movcond"
11116 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 11117 (if_then_else:SI
8fa3ba89 11118 (match_operator 5 "arm_comparison_operator"
5565501b 11119 [(match_operand:SI 3 "s_register_operand" "r,r,r")
11120 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
11121 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
11122 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 11123 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11124 "TARGET_ARM"
9c08d1fa 11125 "*
11126 if (GET_CODE (operands[5]) == LT
11127 && (operands[4] == const0_rtx))
11128 {
0438d37f 11129 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 11130 {
9c08d1fa 11131 if (operands[2] == const0_rtx)
e2348bcb 11132 return \"and\\t%0, %1, %3, asr #31\";
11133 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 11134 }
0438d37f 11135 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 11136 {
9c08d1fa 11137 if (operands[1] == const0_rtx)
e2348bcb 11138 return \"bic\\t%0, %2, %3, asr #31\";
11139 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 11140 }
11141 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 11142 are constants. */
9c08d1fa 11143 }
e2348bcb 11144
9c08d1fa 11145 if (GET_CODE (operands[5]) == GE
11146 && (operands[4] == const0_rtx))
11147 {
0438d37f 11148 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 11149 {
9c08d1fa 11150 if (operands[2] == const0_rtx)
e2348bcb 11151 return \"bic\\t%0, %1, %3, asr #31\";
11152 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 11153 }
0438d37f 11154 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 11155 {
9c08d1fa 11156 if (operands[1] == const0_rtx)
e2348bcb 11157 return \"and\\t%0, %2, %3, asr #31\";
11158 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 11159 }
11160 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 11161 are constants. */
9c08d1fa 11162 }
0438d37f 11163 if (CONST_INT_P (operands[4])
9c08d1fa 11164 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 11165 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 11166 else
e2348bcb 11167 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 11168 if (which_alternative != 0)
e2348bcb 11169 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 11170 if (which_alternative != 1)
e2348bcb 11171 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 11172 return \"\";
215b30b3 11173 "
8fa3ba89 11174 [(set_attr "conds" "clob")
11175 (set_attr "length" "8,8,12")]
11176)
9c08d1fa 11177
25f905c2 11178;; ??? The patterns below need checking for Thumb-2 usefulness.
11179
8a18b90c 11180(define_insn "*ifcompare_plus_move"
11181 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11182 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 11183 [(match_operand:SI 4 "s_register_operand" "r,r")
11184 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
11185 (plus:SI
11186 (match_operand:SI 2 "s_register_operand" "r,r")
11187 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 11188 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 11189 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11190 "TARGET_ARM"
8a18b90c 11191 "#"
8fa3ba89 11192 [(set_attr "conds" "clob")
11193 (set_attr "length" "8,12")]
11194)
8a18b90c 11195
11196(define_insn "*if_plus_move"
129a2fe4 11197 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 11198 (if_then_else:SI
8fa3ba89 11199 (match_operator 4 "arm_comparison_operator"
8a18b90c 11200 [(match_operand 5 "cc_register" "") (const_int 0)])
11201 (plus:SI
129a2fe4 11202 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
11203 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
11204 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 11205 "TARGET_ARM"
8a18b90c 11206 "@
11207 add%d4\\t%0, %2, %3
11208 sub%d4\\t%0, %2, #%n3
11209 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 11210 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 11211 [(set_attr "conds" "use")
11212 (set_attr "length" "4,4,8,8")
65f68e55 11213 (set_attr_alternative "type"
11214 [(if_then_else (match_operand 3 "const_int_operand" "")
6b6abc9c 11215 (const_string "arlo_imm" )
65f68e55 11216 (const_string "*"))
6b6abc9c 11217 (const_string "arlo_imm")
65f68e55 11218 (const_string "*")
11219 (const_string "*")])]
8fa3ba89 11220)
8a18b90c 11221
11222(define_insn "*ifcompare_move_plus"
5565501b 11223 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11224 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 11225 [(match_operand:SI 4 "s_register_operand" "r,r")
11226 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 11227 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 11228 (plus:SI
11229 (match_operand:SI 2 "s_register_operand" "r,r")
11230 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 11231 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11232 "TARGET_ARM"
8a18b90c 11233 "#"
8fa3ba89 11234 [(set_attr "conds" "clob")
11235 (set_attr "length" "8,12")]
11236)
8a18b90c 11237
11238(define_insn "*if_move_plus"
129a2fe4 11239 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 11240 (if_then_else:SI
8fa3ba89 11241 (match_operator 4 "arm_comparison_operator"
8a18b90c 11242 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 11243 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 11244 (plus:SI
129a2fe4 11245 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
11246 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 11247 "TARGET_ARM"
8a18b90c 11248 "@
11249 add%D4\\t%0, %2, %3
11250 sub%D4\\t%0, %2, #%n3
11251 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 11252 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 11253 [(set_attr "conds" "use")
11254 (set_attr "length" "4,4,8,8")
65f68e55 11255 (set_attr_alternative "type"
11256 [(if_then_else (match_operand 3 "const_int_operand" "")
6b6abc9c 11257 (const_string "arlo_imm" )
65f68e55 11258 (const_string "*"))
6b6abc9c 11259 (const_string "arlo_imm")
65f68e55 11260 (const_string "*")
11261 (const_string "*")])]
8fa3ba89 11262)
8a18b90c 11263
11264(define_insn "*ifcompare_arith_arith"
11265 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 11266 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 11267 [(match_operand:SI 5 "s_register_operand" "r")
11268 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 11269 (match_operator:SI 8 "shiftable_operator"
8a18b90c 11270 [(match_operand:SI 1 "s_register_operand" "r")
11271 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 11272 (match_operator:SI 7 "shiftable_operator"
8a18b90c 11273 [(match_operand:SI 3 "s_register_operand" "r")
11274 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 11275 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11276 "TARGET_ARM"
8a18b90c 11277 "#"
8fa3ba89 11278 [(set_attr "conds" "clob")
11279 (set_attr "length" "12")]
11280)
9c08d1fa 11281
8a18b90c 11282(define_insn "*if_arith_arith"
11283 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 11284 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 11285 [(match_operand 8 "cc_register" "") (const_int 0)])
11286 (match_operator:SI 6 "shiftable_operator"
11287 [(match_operand:SI 1 "s_register_operand" "r")
11288 (match_operand:SI 2 "arm_rhs_operand" "rI")])
11289 (match_operator:SI 7 "shiftable_operator"
11290 [(match_operand:SI 3 "s_register_operand" "r")
11291 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 11292 "TARGET_ARM"
8a18b90c 11293 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 11294 [(set_attr "conds" "use")
11295 (set_attr "length" "8")]
11296)
8a18b90c 11297
f7fbdd4a 11298(define_insn "*ifcompare_arith_move"
9c08d1fa 11299 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11300 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 11301 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 11302 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 11303 (match_operator:SI 7 "shiftable_operator"
11304 [(match_operand:SI 4 "s_register_operand" "r,r")
11305 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 11306 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 11307 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11308 "TARGET_ARM"
9c08d1fa 11309 "*
9c08d1fa 11310 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 11311 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 11312 everything is in registers then we can do this in two instructions. */
9c08d1fa 11313 if (operands[3] == const0_rtx
11314 && GET_CODE (operands[7]) != AND
0438d37f 11315 && REG_P (operands[5])
11316 && REG_P (operands[1])
9c08d1fa 11317 && REGNO (operands[1]) == REGNO (operands[4])
11318 && REGNO (operands[4]) != REGNO (operands[0]))
11319 {
11320 if (GET_CODE (operands[6]) == LT)
40dbec34 11321 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 11322 else if (GET_CODE (operands[6]) == GE)
40dbec34 11323 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 11324 }
0438d37f 11325 if (CONST_INT_P (operands[3])
9c08d1fa 11326 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 11327 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 11328 else
e2348bcb 11329 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 11330 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 11331 if (which_alternative != 0)
129a2fe4 11332 return \"mov%D6\\t%0, %1\";
9c08d1fa 11333 return \"\";
215b30b3 11334 "
8fa3ba89 11335 [(set_attr "conds" "clob")
11336 (set_attr "length" "8,12")]
11337)
9c08d1fa 11338
8a18b90c 11339(define_insn "*if_arith_move"
129a2fe4 11340 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11341 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 11342 [(match_operand 6 "cc_register" "") (const_int 0)])
11343 (match_operator:SI 5 "shiftable_operator"
129a2fe4 11344 [(match_operand:SI 2 "s_register_operand" "r,r")
11345 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
11346 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 11347 "TARGET_ARM"
8a18b90c 11348 "@
11349 %I5%d4\\t%0, %2, %3
129a2fe4 11350 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 11351 [(set_attr "conds" "use")
11352 (set_attr "length" "4,8")
11353 (set_attr "type" "*,*")]
11354)
8a18b90c 11355
f7fbdd4a 11356(define_insn "*ifcompare_move_arith"
9c08d1fa 11357 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11358 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 11359 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 11360 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 11361 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 11362 (match_operator:SI 7 "shiftable_operator"
11363 [(match_operand:SI 2 "s_register_operand" "r,r")
11364 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 11365 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11366 "TARGET_ARM"
9c08d1fa 11367 "*
9c08d1fa 11368 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 11369 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 11370 everything is in registers then we can do this in two instructions */
11371 if (operands[5] == const0_rtx
11372 && GET_CODE (operands[7]) != AND
0438d37f 11373 && REG_P (operands[3])
11374 && REG_P (operands[1])
9c08d1fa 11375 && REGNO (operands[1]) == REGNO (operands[2])
11376 && REGNO (operands[2]) != REGNO (operands[0]))
11377 {
11378 if (GET_CODE (operands[6]) == GE)
40dbec34 11379 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 11380 else if (GET_CODE (operands[6]) == LT)
40dbec34 11381 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 11382 }
40dbec34 11383
0438d37f 11384 if (CONST_INT_P (operands[5])
9c08d1fa 11385 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 11386 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 11387 else
e2348bcb 11388 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 11389
9c08d1fa 11390 if (which_alternative != 0)
129a2fe4 11391 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 11392 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 11393 "
8fa3ba89 11394 [(set_attr "conds" "clob")
11395 (set_attr "length" "8,12")]
11396)
9c08d1fa 11397
8a18b90c 11398(define_insn "*if_move_arith"
129a2fe4 11399 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 11400 (if_then_else:SI
8fa3ba89 11401 (match_operator 4 "arm_comparison_operator"
8a18b90c 11402 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 11403 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 11404 (match_operator:SI 5 "shiftable_operator"
129a2fe4 11405 [(match_operand:SI 2 "s_register_operand" "r,r")
11406 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 11407 "TARGET_ARM"
8a18b90c 11408 "@
11409 %I5%D4\\t%0, %2, %3
129a2fe4 11410 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 11411 [(set_attr "conds" "use")
11412 (set_attr "length" "4,8")
11413 (set_attr "type" "*,*")]
11414)
8a18b90c 11415
11416(define_insn "*ifcompare_move_not"
9c08d1fa 11417 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 11418 (if_then_else:SI
8fa3ba89 11419 (match_operator 5 "arm_comparison_operator"
8a18b90c 11420 [(match_operand:SI 3 "s_register_operand" "r,r")
11421 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11422 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
11423 (not:SI
11424 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 11425 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11426 "TARGET_ARM"
8a18b90c 11427 "#"
8fa3ba89 11428 [(set_attr "conds" "clob")
11429 (set_attr "length" "8,12")]
11430)
9c08d1fa 11431
8a18b90c 11432(define_insn "*if_move_not"
11433 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11434 (if_then_else:SI
8fa3ba89 11435 (match_operator 4 "arm_comparison_operator"
8a18b90c 11436 [(match_operand 3 "cc_register" "") (const_int 0)])
11437 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
11438 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 11439 "TARGET_ARM"
8a18b90c 11440 "@
11441 mvn%D4\\t%0, %2
11442 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
11443 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 11444 [(set_attr "conds" "use")
1aed5204 11445 (set_attr "type" "mvn_reg")
8fa3ba89 11446 (set_attr "length" "4,8,8")]
11447)
8a18b90c 11448
11449(define_insn "*ifcompare_not_move"
9c08d1fa 11450 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 11451 (if_then_else:SI
8fa3ba89 11452 (match_operator 5 "arm_comparison_operator"
8a18b90c 11453 [(match_operand:SI 3 "s_register_operand" "r,r")
11454 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11455 (not:SI
11456 (match_operand:SI 2 "s_register_operand" "r,r"))
11457 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 11458 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11459 "TARGET_ARM"
8a18b90c 11460 "#"
8fa3ba89 11461 [(set_attr "conds" "clob")
11462 (set_attr "length" "8,12")]
11463)
9c08d1fa 11464
8a18b90c 11465(define_insn "*if_not_move"
11466 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11467 (if_then_else:SI
8fa3ba89 11468 (match_operator 4 "arm_comparison_operator"
8a18b90c 11469 [(match_operand 3 "cc_register" "") (const_int 0)])
11470 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
11471 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 11472 "TARGET_ARM"
8a18b90c 11473 "@
11474 mvn%d4\\t%0, %2
11475 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
11476 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 11477 [(set_attr "conds" "use")
1aed5204 11478 (set_attr "type" "mvn_reg")
8fa3ba89 11479 (set_attr "length" "4,8,8")]
11480)
8a18b90c 11481
11482(define_insn "*ifcompare_shift_move"
9c08d1fa 11483 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 11484 (if_then_else:SI
8fa3ba89 11485 (match_operator 6 "arm_comparison_operator"
8a18b90c 11486 [(match_operand:SI 4 "s_register_operand" "r,r")
11487 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
11488 (match_operator:SI 7 "shift_operator"
11489 [(match_operand:SI 2 "s_register_operand" "r,r")
11490 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
11491 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 11492 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11493 "TARGET_ARM"
9c08d1fa 11494 "#"
8fa3ba89 11495 [(set_attr "conds" "clob")
11496 (set_attr "length" "8,12")]
11497)
9c08d1fa 11498
8a18b90c 11499(define_insn "*if_shift_move"
11500 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11501 (if_then_else:SI
8fa3ba89 11502 (match_operator 5 "arm_comparison_operator"
8a18b90c 11503 [(match_operand 6 "cc_register" "") (const_int 0)])
11504 (match_operator:SI 4 "shift_operator"
11505 [(match_operand:SI 2 "s_register_operand" "r,r,r")
11506 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
11507 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 11508 "TARGET_ARM"
5565501b 11509 "@
8a18b90c 11510 mov%d5\\t%0, %2%S4
11511 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
11512 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 11513 [(set_attr "conds" "use")
331beb1a 11514 (set_attr "shift" "2")
a2cd141b 11515 (set_attr "length" "4,8,8")
11516 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
1aed5204 11517 (const_string "mov_shift")
11518 (const_string "mov_shift_reg")))]
8fa3ba89 11519)
5565501b 11520
8a18b90c 11521(define_insn "*ifcompare_move_shift"
11522 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 11523 (if_then_else:SI
8fa3ba89 11524 (match_operator 6 "arm_comparison_operator"
8a18b90c 11525 [(match_operand:SI 4 "s_register_operand" "r,r")
11526 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
11527 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 11528 (match_operator:SI 7 "shift_operator"
8a18b90c 11529 [(match_operand:SI 2 "s_register_operand" "r,r")
11530 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 11531 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11532 "TARGET_ARM"
8a18b90c 11533 "#"
8fa3ba89 11534 [(set_attr "conds" "clob")
11535 (set_attr "length" "8,12")]
11536)
5565501b 11537
8a18b90c 11538(define_insn "*if_move_shift"
11539 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 11540 (if_then_else:SI
8fa3ba89 11541 (match_operator 5 "arm_comparison_operator"
8a18b90c 11542 [(match_operand 6 "cc_register" "") (const_int 0)])
11543 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
11544 (match_operator:SI 4 "shift_operator"
11545 [(match_operand:SI 2 "s_register_operand" "r,r,r")
11546 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 11547 "TARGET_ARM"
5565501b 11548 "@
8a18b90c 11549 mov%D5\\t%0, %2%S4
11550 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
11551 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 11552 [(set_attr "conds" "use")
331beb1a 11553 (set_attr "shift" "2")
a2cd141b 11554 (set_attr "length" "4,8,8")
11555 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
1aed5204 11556 (const_string "mov_shift")
11557 (const_string "mov_shift_reg")))]
8fa3ba89 11558)
9c08d1fa 11559
f7fbdd4a 11560(define_insn "*ifcompare_shift_shift"
8a18b90c 11561 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 11562 (if_then_else:SI
8fa3ba89 11563 (match_operator 7 "arm_comparison_operator"
8a18b90c 11564 [(match_operand:SI 5 "s_register_operand" "r")
11565 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 11566 (match_operator:SI 8 "shift_operator"
8a18b90c 11567 [(match_operand:SI 1 "s_register_operand" "r")
11568 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 11569 (match_operator:SI 9 "shift_operator"
8a18b90c 11570 [(match_operand:SI 3 "s_register_operand" "r")
11571 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 11572 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11573 "TARGET_ARM"
8a18b90c 11574 "#"
8fa3ba89 11575 [(set_attr "conds" "clob")
11576 (set_attr "length" "12")]
11577)
9c08d1fa 11578
8a18b90c 11579(define_insn "*if_shift_shift"
11580 [(set (match_operand:SI 0 "s_register_operand" "=r")
11581 (if_then_else:SI
8fa3ba89 11582 (match_operator 5 "arm_comparison_operator"
8a18b90c 11583 [(match_operand 8 "cc_register" "") (const_int 0)])
11584 (match_operator:SI 6 "shift_operator"
11585 [(match_operand:SI 1 "s_register_operand" "r")
11586 (match_operand:SI 2 "arm_rhs_operand" "rM")])
11587 (match_operator:SI 7 "shift_operator"
11588 [(match_operand:SI 3 "s_register_operand" "r")
11589 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 11590 "TARGET_ARM"
8a18b90c 11591 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 11592 [(set_attr "conds" "use")
331beb1a 11593 (set_attr "shift" "1")
a2cd141b 11594 (set_attr "length" "8")
11595 (set (attr "type") (if_then_else
11596 (and (match_operand 2 "const_int_operand" "")
11597 (match_operand 4 "const_int_operand" ""))
1aed5204 11598 (const_string "mov_shift")
11599 (const_string "mov_shift_reg")))]
8fa3ba89 11600)
8a18b90c 11601
f7fbdd4a 11602(define_insn "*ifcompare_not_arith"
8a18b90c 11603 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 11604 (if_then_else:SI
8fa3ba89 11605 (match_operator 6 "arm_comparison_operator"
8a18b90c 11606 [(match_operand:SI 4 "s_register_operand" "r")
11607 (match_operand:SI 5 "arm_add_operand" "rIL")])
11608 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 11609 (match_operator:SI 7 "shiftable_operator"
8a18b90c 11610 [(match_operand:SI 2 "s_register_operand" "r")
11611 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 11612 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11613 "TARGET_ARM"
8a18b90c 11614 "#"
8fa3ba89 11615 [(set_attr "conds" "clob")
11616 (set_attr "length" "12")]
11617)
9c08d1fa 11618
8a18b90c 11619(define_insn "*if_not_arith"
11620 [(set (match_operand:SI 0 "s_register_operand" "=r")
11621 (if_then_else:SI
8fa3ba89 11622 (match_operator 5 "arm_comparison_operator"
8a18b90c 11623 [(match_operand 4 "cc_register" "") (const_int 0)])
11624 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
11625 (match_operator:SI 6 "shiftable_operator"
11626 [(match_operand:SI 2 "s_register_operand" "r")
11627 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 11628 "TARGET_ARM"
8a18b90c 11629 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 11630 [(set_attr "conds" "use")
1aed5204 11631 (set_attr "type" "mvn_reg")
8fa3ba89 11632 (set_attr "length" "8")]
11633)
8a18b90c 11634
11635(define_insn "*ifcompare_arith_not"
11636 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 11637 (if_then_else:SI
8fa3ba89 11638 (match_operator 6 "arm_comparison_operator"
8a18b90c 11639 [(match_operand:SI 4 "s_register_operand" "r")
11640 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 11641 (match_operator:SI 7 "shiftable_operator"
8a18b90c 11642 [(match_operand:SI 2 "s_register_operand" "r")
11643 (match_operand:SI 3 "arm_rhs_operand" "rI")])
11644 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 11645 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11646 "TARGET_ARM"
8a18b90c 11647 "#"
8fa3ba89 11648 [(set_attr "conds" "clob")
11649 (set_attr "length" "12")]
11650)
9c08d1fa 11651
8a18b90c 11652(define_insn "*if_arith_not"
11653 [(set (match_operand:SI 0 "s_register_operand" "=r")
11654 (if_then_else:SI
8fa3ba89 11655 (match_operator 5 "arm_comparison_operator"
8a18b90c 11656 [(match_operand 4 "cc_register" "") (const_int 0)])
11657 (match_operator:SI 6 "shiftable_operator"
11658 [(match_operand:SI 2 "s_register_operand" "r")
11659 (match_operand:SI 3 "arm_rhs_operand" "rI")])
11660 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 11661 "TARGET_ARM"
8a18b90c 11662 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 11663 [(set_attr "conds" "use")
1aed5204 11664 (set_attr "type" "mvn_reg")
8fa3ba89 11665 (set_attr "length" "8")]
11666)
8a18b90c 11667
f7fbdd4a 11668(define_insn "*ifcompare_neg_move"
8a18b90c 11669 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 11670 (if_then_else:SI
8fa3ba89 11671 (match_operator 5 "arm_comparison_operator"
8a18b90c 11672 [(match_operand:SI 3 "s_register_operand" "r,r")
11673 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11674 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
11675 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 11676 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11677 "TARGET_ARM"
8a18b90c 11678 "#"
8fa3ba89 11679 [(set_attr "conds" "clob")
11680 (set_attr "length" "8,12")]
11681)
8a18b90c 11682
11683(define_insn "*if_neg_move"
11684 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11685 (if_then_else:SI
8fa3ba89 11686 (match_operator 4 "arm_comparison_operator"
8a18b90c 11687 [(match_operand 3 "cc_register" "") (const_int 0)])
11688 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
11689 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 11690 "TARGET_ARM"
8a18b90c 11691 "@
11692 rsb%d4\\t%0, %2, #0
11693 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
11694 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 11695 [(set_attr "conds" "use")
11696 (set_attr "length" "4,8,8")]
11697)
9c08d1fa 11698
f7fbdd4a 11699(define_insn "*ifcompare_move_neg"
8a18b90c 11700 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 11701 (if_then_else:SI
8fa3ba89 11702 (match_operator 5 "arm_comparison_operator"
8a18b90c 11703 [(match_operand:SI 3 "s_register_operand" "r,r")
11704 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11705 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
11706 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 11707 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11708 "TARGET_ARM"
8a18b90c 11709 "#"
8fa3ba89 11710 [(set_attr "conds" "clob")
11711 (set_attr "length" "8,12")]
11712)
8a18b90c 11713
11714(define_insn "*if_move_neg"
11715 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11716 (if_then_else:SI
8fa3ba89 11717 (match_operator 4 "arm_comparison_operator"
8a18b90c 11718 [(match_operand 3 "cc_register" "") (const_int 0)])
11719 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
11720 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 11721 "TARGET_ARM"
8a18b90c 11722 "@
11723 rsb%D4\\t%0, %2, #0
11724 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
11725 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 11726 [(set_attr "conds" "use")
11727 (set_attr "length" "4,8,8")]
11728)
9c08d1fa 11729
f7fbdd4a 11730(define_insn "*arith_adjacentmem"
9c08d1fa 11731 [(set (match_operand:SI 0 "s_register_operand" "=r")
11732 (match_operator:SI 1 "shiftable_operator"
11733 [(match_operand:SI 2 "memory_operand" "m")
11734 (match_operand:SI 3 "memory_operand" "m")]))
11735 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 11736 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 11737 "*
215b30b3 11738 {
11739 rtx ldm[3];
11740 rtx arith[4];
94dee231 11741 rtx base_reg;
11742 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 11743
215b30b3 11744 if (REGNO (operands[0]) > REGNO (operands[4]))
11745 {
11746 ldm[1] = operands[4];
11747 ldm[2] = operands[0];
11748 }
11749 else
11750 {
11751 ldm[1] = operands[0];
11752 ldm[2] = operands[4];
11753 }
94dee231 11754
11755 base_reg = XEXP (operands[2], 0);
11756
11757 if (!REG_P (base_reg))
11758 {
11759 val1 = INTVAL (XEXP (base_reg, 1));
11760 base_reg = XEXP (base_reg, 0);
11761 }
11762
11763 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 11764 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 11765
215b30b3 11766 arith[0] = operands[0];
11767 arith[3] = operands[1];
94dee231 11768
215b30b3 11769 if (val1 < val2)
11770 {
11771 arith[1] = ldm[1];
11772 arith[2] = ldm[2];
11773 }
11774 else
11775 {
11776 arith[1] = ldm[2];
11777 arith[2] = ldm[1];
11778 }
94dee231 11779
11780 ldm[0] = base_reg;
11781 if (val1 !=0 && val2 != 0)
215b30b3 11782 {
cdb1295a 11783 rtx ops[3];
11784
94dee231 11785 if (val1 == 4 || val2 == 4)
11786 /* Other val must be 8, since we know they are adjacent and neither
11787 is zero. */
25f905c2 11788 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 11789 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 11790 {
94dee231 11791 ldm[0] = ops[0] = operands[4];
11792 ops[1] = base_reg;
11793 ops[2] = GEN_INT (val1);
11794 output_add_immediate (ops);
11795 if (val1 < val2)
25f905c2 11796 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 11797 else
25f905c2 11798 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 11799 }
cdb1295a 11800 else
11801 {
11802 /* Offset is out of range for a single add, so use two ldr. */
11803 ops[0] = ldm[1];
11804 ops[1] = base_reg;
11805 ops[2] = GEN_INT (val1);
11806 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
11807 ops[0] = ldm[2];
11808 ops[2] = GEN_INT (val2);
11809 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
11810 }
215b30b3 11811 }
94dee231 11812 else if (val1 != 0)
215b30b3 11813 {
215b30b3 11814 if (val1 < val2)
25f905c2 11815 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 11816 else
25f905c2 11817 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 11818 }
11819 else
11820 {
215b30b3 11821 if (val1 < val2)
25f905c2 11822 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 11823 else
25f905c2 11824 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 11825 }
11826 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
11827 return \"\";
11828 }"
11829 [(set_attr "length" "12")
11830 (set_attr "predicable" "yes")
a2cd141b 11831 (set_attr "type" "load1")]
215b30b3 11832)
9c08d1fa 11833
9c08d1fa 11834; This pattern is never tried by combine, so do it as a peephole
11835
a0f94409 11836(define_peephole2
372575c7 11837 [(set (match_operand:SI 0 "arm_general_register_operand" "")
11838 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 11839 (set (reg:CC CC_REGNUM)
aea4c774 11840 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 11841 "TARGET_ARM"
a0f94409 11842 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
11843 (set (match_dup 0) (match_dup 1))])]
11844 ""
0d66636f 11845)
9c08d1fa 11846
9c08d1fa 11847(define_split
11848 [(set (match_operand:SI 0 "s_register_operand" "")
11849 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
11850 (const_int 0))
8fa3ba89 11851 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 11852 [(match_operand:SI 3 "s_register_operand" "")
11853 (match_operand:SI 4 "arm_rhs_operand" "")]))))
11854 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 11855 "TARGET_ARM"
9c08d1fa 11856 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
11857 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
11858 (match_dup 5)))]
215b30b3 11859 ""
11860)
9c08d1fa 11861
aea4c774 11862;; This split can be used because CC_Z mode implies that the following
11863;; branch will be an equality, or an unsigned inequality, so the sign
11864;; extension is not needed.
9c08d1fa 11865
aea4c774 11866(define_split
bd5b4116 11867 [(set (reg:CC_Z CC_REGNUM)
aea4c774 11868 (compare:CC_Z
11869 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 11870 (const_int 24))
aea4c774 11871 (match_operand 1 "const_int_operand" "")))
11872 (clobber (match_scratch:SI 2 ""))]
cffb2a26 11873 "TARGET_ARM
11874 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
11875 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 11876 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 11877 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 11878 "
9c08d1fa 11879 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 11880 "
11881)
25f905c2 11882;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 11883
87b22bf7 11884(define_expand "prologue"
11885 [(clobber (const_int 0))]
cffb2a26 11886 "TARGET_EITHER"
25f905c2 11887 "if (TARGET_32BIT)
cffb2a26 11888 arm_expand_prologue ();
11889 else
25f905c2 11890 thumb1_expand_prologue ();
87b22bf7 11891 DONE;
cffb2a26 11892 "
11893)
87b22bf7 11894
56d27660 11895(define_expand "epilogue"
4c44712e 11896 [(clobber (const_int 0))]
cffb2a26 11897 "TARGET_EITHER"
56d27660 11898 "
18d50ae6 11899 if (crtl->calls_eh_return)
fb94f18b 11900 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 11901 if (TARGET_THUMB1)
c3635784 11902 {
11903 thumb1_expand_epilogue ();
11904 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
11905 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
11906 }
11907 else if (HAVE_return)
11908 {
11909 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
11910 no need for explicit testing again. */
11911 emit_jump_insn (gen_return ());
11912 }
11913 else if (TARGET_32BIT)
11914 {
11915 arm_expand_epilogue (true);
11916 }
cffb2a26 11917 DONE;
11918 "
11919)
56d27660 11920
7571d3f7 11921(define_insn "prologue_thumb1_interwork"
11922 [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
11923 "TARGET_THUMB1"
11924 "* return thumb1_output_interwork ();"
11925 [(set_attr "length" "8")]
11926)
11927
ef5651d0 11928;; Note - although unspec_volatile's USE all hard registers,
11929;; USEs are ignored after relaod has completed. Thus we need
11930;; to add an unspec of the link register to ensure that flow
11931;; does not think that it is unused by the sibcall branch that
11932;; will replace the standard function epilogue.
c3635784 11933(define_expand "sibcall_epilogue"
fb94f18b 11934 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 11935 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
11936 "TARGET_32BIT"
11937 "
11938 arm_expand_epilogue (false);
11939 DONE;
11940 "
1c494086 11941)
11942
cffb2a26 11943(define_insn "*epilogue_insns"
e1159bbe 11944 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
b1324f4f 11945 "TARGET_THUMB1"
56d27660 11946 "*
e7fd8dfa 11947 return thumb1_unexpanded_epilogue ();
cffb2a26 11948 "
215b30b3 11949 ; Length is absolute worst case
cffb2a26 11950 [(set_attr "length" "44")
defc47cf 11951 (set_attr "type" "block")
11952 ;; We don't clobber the conditions, but the potential length of this
11953 ;; operation is sufficient to make conditionalizing the sequence
11954 ;; unlikely to be profitable.
11955 (set_attr "conds" "clob")]
cffb2a26 11956)
11957
11958(define_expand "eh_epilogue"
7db9af5d 11959 [(use (match_operand:SI 0 "register_operand" ""))
11960 (use (match_operand:SI 1 "register_operand" ""))
11961 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 11962 "TARGET_EITHER"
11963 "
215b30b3 11964 {
11965 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 11966 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 11967 {
11968 rtx ra = gen_rtx_REG (Pmode, 2);
11969
11970 emit_move_insn (ra, operands[2]);
11971 operands[2] = ra;
11972 }
5cf3595a 11973 /* This is a hack -- we may have crystalized the function type too
11974 early. */
11975 cfun->machine->func_type = 0;
215b30b3 11976 }"
11977)
56d27660 11978
9c08d1fa 11979;; This split is only used during output to reduce the number of patterns
11980;; that need assembler instructions adding to them. We allowed the setting
11981;; of the conditions to be implicit during rtl generation so that
11982;; the conditional compare patterns would work. However this conflicts to
8a18b90c 11983;; some extent with the conditional data operations, so we have to split them
9c08d1fa 11984;; up again here.
11985
25f905c2 11986;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
11987;; conditional execution sufficient?
11988
9c08d1fa 11989(define_split
11990 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 11991 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11992 [(match_operand 2 "" "") (match_operand 3 "" "")])
11993 (match_dup 0)
11994 (match_operand 4 "" "")))
bd5b4116 11995 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11996 "TARGET_ARM && reload_completed"
8fa3ba89 11997 [(set (match_dup 5) (match_dup 6))
11998 (cond_exec (match_dup 7)
11999 (set (match_dup 0) (match_dup 4)))]
12000 "
12001 {
12002 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
12003 operands[2], operands[3]);
12004 enum rtx_code rc = GET_CODE (operands[1]);
12005
bd5b4116 12006 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 12007 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
12008 if (mode == CCFPmode || mode == CCFPEmode)
12009 rc = reverse_condition_maybe_unordered (rc);
12010 else
12011 rc = reverse_condition (rc);
12012
12013 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
12014 }"
12015)
12016
12017(define_split
12018 [(set (match_operand:SI 0 "s_register_operand" "")
12019 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
12020 [(match_operand 2 "" "") (match_operand 3 "" "")])
12021 (match_operand 4 "" "")
12022 (match_dup 0)))
bd5b4116 12023 (clobber (reg:CC CC_REGNUM))]
ac8b093b 12024 "TARGET_ARM && reload_completed"
8fa3ba89 12025 [(set (match_dup 5) (match_dup 6))
12026 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
12027 (set (match_dup 0) (match_dup 4)))]
12028 "
12029 {
12030 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
12031 operands[2], operands[3]);
12032
bd5b4116 12033 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 12034 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
12035 }"
12036)
12037
12038(define_split
12039 [(set (match_operand:SI 0 "s_register_operand" "")
12040 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 12041 [(match_operand 2 "" "") (match_operand 3 "" "")])
12042 (match_operand 4 "" "")
12043 (match_operand 5 "" "")))
bd5b4116 12044 (clobber (reg:CC CC_REGNUM))]
ac8b093b 12045 "TARGET_ARM && reload_completed"
8fa3ba89 12046 [(set (match_dup 6) (match_dup 7))
12047 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
12048 (set (match_dup 0) (match_dup 4)))
12049 (cond_exec (match_dup 8)
12050 (set (match_dup 0) (match_dup 5)))]
12051 "
12052 {
12053 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
12054 operands[2], operands[3]);
12055 enum rtx_code rc = GET_CODE (operands[1]);
12056
bd5b4116 12057 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 12058 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
12059 if (mode == CCFPmode || mode == CCFPEmode)
12060 rc = reverse_condition_maybe_unordered (rc);
12061 else
12062 rc = reverse_condition (rc);
12063
12064 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
12065 }"
12066)
12067
cffb2a26 12068(define_split
12069 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 12070 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 12071 [(match_operand:SI 2 "s_register_operand" "")
12072 (match_operand:SI 3 "arm_add_operand" "")])
12073 (match_operand:SI 4 "arm_rhs_operand" "")
12074 (not:SI
12075 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 12076 (clobber (reg:CC CC_REGNUM))]
ac8b093b 12077 "TARGET_ARM && reload_completed"
cffb2a26 12078 [(set (match_dup 6) (match_dup 7))
f6c53574 12079 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
12080 (set (match_dup 0) (match_dup 4)))
12081 (cond_exec (match_dup 8)
12082 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 12083 "
215b30b3 12084 {
12085 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
12086 operands[2], operands[3]);
f6c53574 12087 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 12088
bd5b4116 12089 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 12090 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 12091 if (mode == CCFPmode || mode == CCFPEmode)
12092 rc = reverse_condition_maybe_unordered (rc);
12093 else
12094 rc = reverse_condition (rc);
12095
12096 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 12097 }"
12098)
cffb2a26 12099
12100(define_insn "*cond_move_not"
12101 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 12102 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 12103 [(match_operand 3 "cc_register" "") (const_int 0)])
12104 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
12105 (not:SI
12106 (match_operand:SI 2 "s_register_operand" "r,r"))))]
12107 "TARGET_ARM"
12108 "@
12109 mvn%D4\\t%0, %2
12110 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 12111 [(set_attr "conds" "use")
1aed5204 12112 (set_attr "type" "mvn_reg")
0d66636f 12113 (set_attr "length" "4,8")]
12114)
cffb2a26 12115
9c08d1fa 12116;; The next two patterns occur when an AND operation is followed by a
12117;; scc insn sequence
12118
f7fbdd4a 12119(define_insn "*sign_extract_onebit"
9c08d1fa 12120 [(set (match_operand:SI 0 "s_register_operand" "=r")
12121 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
12122 (const_int 1)
ed750274 12123 (match_operand:SI 2 "const_int_operand" "n")))
12124 (clobber (reg:CC CC_REGNUM))]
cffb2a26 12125 "TARGET_ARM"
9c08d1fa 12126 "*
0d66636f 12127 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
12128 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
12129 return \"mvnne\\t%0, #0\";
12130 "
12131 [(set_attr "conds" "clob")
12132 (set_attr "length" "8")]
12133)
9c08d1fa 12134
f7fbdd4a 12135(define_insn "*not_signextract_onebit"
9c08d1fa 12136 [(set (match_operand:SI 0 "s_register_operand" "=r")
12137 (not:SI
12138 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
12139 (const_int 1)
ed750274 12140 (match_operand:SI 2 "const_int_operand" "n"))))
12141 (clobber (reg:CC CC_REGNUM))]
cffb2a26 12142 "TARGET_ARM"
9c08d1fa 12143 "*
0d66636f 12144 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
12145 output_asm_insn (\"tst\\t%1, %2\", operands);
12146 output_asm_insn (\"mvneq\\t%0, #0\", operands);
12147 return \"movne\\t%0, #0\";
12148 "
12149 [(set_attr "conds" "clob")
12150 (set_attr "length" "12")]
12151)
25f905c2 12152;; ??? The above patterns need auditing for Thumb-2
87b22bf7 12153
0d66636f 12154;; Push multiple registers to the stack. Registers are in parallel (use ...)
12155;; expressions. For simplicity, the first register is also in the unspec
12156;; part.
08508cbf 12157;; To avoid the usage of GNU extension, the length attribute is computed
12158;; in a C function arm_attr_length_push_multi.
f7fbdd4a 12159(define_insn "*push_multi"
87b22bf7 12160 [(match_parallel 2 "multi_register_push"
7571d3f7 12161 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 12162 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 12163 UNSPEC_PUSH_MULT))])]
7571d3f7 12164 ""
87b22bf7 12165 "*
215b30b3 12166 {
12167 int num_saves = XVECLEN (operands[2], 0);
ed593f11 12168
215b30b3 12169 /* For the StrongARM at least it is faster to
25f905c2 12170 use STR to store only a single register.
542d5028 12171 In Thumb mode always use push, and the assembler will pick
12172 something appropriate. */
25f905c2 12173 if (num_saves == 1 && TARGET_ARM)
61309563 12174 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 12175 else
12176 {
12177 int i;
12178 char pattern[100];
ed593f11 12179
25f905c2 12180 if (TARGET_ARM)
61309563 12181 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
12182 else if (TARGET_THUMB2)
12183 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 12184 else
12185 strcpy (pattern, \"push\\t{%1\");
215b30b3 12186
6079f055 12187 for (i = 1; i < num_saves; i++)
215b30b3 12188 {
12189 strcat (pattern, \", %|\");
12190 strcat (pattern,
12191 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
12192 }
12193
12194 strcat (pattern, \"}\");
12195 output_asm_insn (pattern, operands);
12196 }
12197
12198 return \"\";
12199 }"
a6864a24 12200 [(set_attr "type" "store4")
12201 (set (attr "length")
08508cbf 12202 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 12203)
f7fbdd4a 12204
4c58c898 12205(define_insn "stack_tie"
12206 [(set (mem:BLK (scratch))
aaa37ad6 12207 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
12208 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 12209 UNSPEC_PRLG_STK))]
12210 ""
12211 ""
12212 [(set_attr "length" "0")]
12213)
12214
426be8c5 12215;; Pop (as used in epilogue RTL)
12216;;
12217(define_insn "*load_multiple_with_writeback"
12218 [(match_parallel 0 "load_multiple_operation"
12219 [(set (match_operand:SI 1 "s_register_operand" "+rk")
12220 (plus:SI (match_dup 1)
12221 (match_operand:SI 2 "const_int_operand" "I")))
12222 (set (match_operand:SI 3 "s_register_operand" "=rk")
12223 (mem:SI (match_dup 1)))
12224 ])]
12225 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12226 "*
12227 {
12228 arm_output_multireg_pop (operands, /*return_pc=*/false,
12229 /*cond=*/const_true_rtx,
12230 /*reverse=*/false,
12231 /*update=*/true);
12232 return \"\";
12233 }
12234 "
12235 [(set_attr "type" "load4")
12236 (set_attr "predicable" "yes")]
12237)
12238
12239;; Pop with return (as used in epilogue RTL)
12240;;
12241;; This instruction is generated when the registers are popped at the end of
12242;; epilogue. Here, instead of popping the value into LR and then generating
12243;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
12244;; with (return).
12245(define_insn "*pop_multiple_with_writeback_and_return"
12246 [(match_parallel 0 "pop_multiple_return"
12247 [(return)
12248 (set (match_operand:SI 1 "s_register_operand" "+rk")
12249 (plus:SI (match_dup 1)
12250 (match_operand:SI 2 "const_int_operand" "I")))
12251 (set (match_operand:SI 3 "s_register_operand" "=rk")
12252 (mem:SI (match_dup 1)))
12253 ])]
12254 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12255 "*
12256 {
12257 arm_output_multireg_pop (operands, /*return_pc=*/true,
12258 /*cond=*/const_true_rtx,
12259 /*reverse=*/false,
12260 /*update=*/true);
12261 return \"\";
12262 }
12263 "
12264 [(set_attr "type" "load4")
12265 (set_attr "predicable" "yes")]
12266)
12267
12268(define_insn "*pop_multiple_with_return"
12269 [(match_parallel 0 "pop_multiple_return"
12270 [(return)
12271 (set (match_operand:SI 2 "s_register_operand" "=rk")
12272 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12273 ])]
12274 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12275 "*
12276 {
12277 arm_output_multireg_pop (operands, /*return_pc=*/true,
12278 /*cond=*/const_true_rtx,
12279 /*reverse=*/false,
12280 /*update=*/false);
12281 return \"\";
12282 }
12283 "
12284 [(set_attr "type" "load4")
12285 (set_attr "predicable" "yes")]
12286)
12287
12288;; Load into PC and return
12289(define_insn "*ldr_with_return"
12290 [(return)
12291 (set (reg:SI PC_REGNUM)
12292 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
12293 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12294 "ldr%?\t%|pc, [%0], #4"
12295 [(set_attr "type" "load1")
12296 (set_attr "predicable" "yes")]
12297)
1a0b0f12 12298;; Pop for floating point registers (as used in epilogue RTL)
12299(define_insn "*vfp_pop_multiple_with_writeback"
12300 [(match_parallel 0 "pop_multiple_fp"
12301 [(set (match_operand:SI 1 "s_register_operand" "+rk")
12302 (plus:SI (match_dup 1)
12303 (match_operand:SI 2 "const_int_operand" "I")))
12304 (set (match_operand:DF 3 "arm_hard_register_operand" "")
12305 (mem:DF (match_dup 1)))])]
12306 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
12307 "*
12308 {
12309 int num_regs = XVECLEN (operands[0], 0);
12310 char pattern[100];
12311 rtx op_list[2];
12312 strcpy (pattern, \"fldmfdd\\t\");
12313 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
12314 strcat (pattern, \"!, {\");
12315 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
12316 strcat (pattern, \"%P0\");
12317 if ((num_regs - 1) > 1)
12318 {
12319 strcat (pattern, \"-%P1\");
12320 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
12321 }
12322
12323 strcat (pattern, \"}\");
12324 output_asm_insn (pattern, op_list);
12325 return \"\";
12326 }
12327 "
12328 [(set_attr "type" "load4")
12329 (set_attr "conds" "unconditional")
12330 (set_attr "predicable" "no")]
12331)
12332
f7fbdd4a 12333;; Special patterns for dealing with the constant pool
12334
cffb2a26 12335(define_insn "align_4"
e1159bbe 12336 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 12337 "TARGET_EITHER"
f7fbdd4a 12338 "*
cffb2a26 12339 assemble_align (32);
f7fbdd4a 12340 return \"\";
cffb2a26 12341 "
12342)
f7fbdd4a 12343
755eb2b4 12344(define_insn "align_8"
12345 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 12346 "TARGET_EITHER"
755eb2b4 12347 "*
12348 assemble_align (64);
12349 return \"\";
12350 "
12351)
12352
cffb2a26 12353(define_insn "consttable_end"
e1159bbe 12354 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 12355 "TARGET_EITHER"
f7fbdd4a 12356 "*
cffb2a26 12357 making_const_table = FALSE;
f7fbdd4a 12358 return \"\";
cffb2a26 12359 "
12360)
f7fbdd4a 12361
cffb2a26 12362(define_insn "consttable_1"
e1159bbe 12363 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 12364 "TARGET_THUMB1"
f7fbdd4a 12365 "*
cffb2a26 12366 making_const_table = TRUE;
09d688ff 12367 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 12368 assemble_zeros (3);
f7fbdd4a 12369 return \"\";
cffb2a26 12370 "
12371 [(set_attr "length" "4")]
12372)
f7fbdd4a 12373
cffb2a26 12374(define_insn "consttable_2"
e1159bbe 12375 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 12376 "TARGET_THUMB1"
f7fbdd4a 12377 "*
cffb2a26 12378 making_const_table = TRUE;
9b8516be 12379 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 12380 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 12381 assemble_zeros (2);
f7fbdd4a 12382 return \"\";
cffb2a26 12383 "
12384 [(set_attr "length" "4")]
12385)
12386
12387(define_insn "consttable_4"
e1159bbe 12388 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 12389 "TARGET_EITHER"
12390 "*
12391 {
9b8516be 12392 rtx x = operands[0];
cffb2a26 12393 making_const_table = TRUE;
9b8516be 12394 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 12395 {
12396 case MODE_FLOAT:
9b8516be 12397 if (GET_MODE (x) == HFmode)
12398 arm_emit_fp16_const (x);
12399 else
12400 {
12401 REAL_VALUE_TYPE r;
12402 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
12403 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
12404 }
12405 break;
cffb2a26 12406 default:
7b04c5d5 12407 /* XXX: Sometimes gcc does something really dumb and ends up with
12408 a HIGH in a constant pool entry, usually because it's trying to
12409 load into a VFP register. We know this will always be used in
12410 combination with a LO_SUM which ignores the high bits, so just
12411 strip off the HIGH. */
12412 if (GET_CODE (x) == HIGH)
12413 x = XEXP (x, 0);
9b8516be 12414 assemble_integer (x, 4, BITS_PER_WORD, 1);
12415 mark_symbol_refs_as_used (x);
cffb2a26 12416 break;
12417 }
12418 return \"\";
12419 }"
12420 [(set_attr "length" "4")]
12421)
12422
12423(define_insn "consttable_8"
e1159bbe 12424 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 12425 "TARGET_EITHER"
12426 "*
12427 {
12428 making_const_table = TRUE;
12429 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
12430 {
12431 case MODE_FLOAT:
12432 {
badfe841 12433 REAL_VALUE_TYPE r;
12434 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
12435 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 12436 break;
12437 }
12438 default:
09d688ff 12439 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 12440 break;
12441 }
12442 return \"\";
12443 }"
12444 [(set_attr "length" "8")]
12445)
12446
d98a3884 12447(define_insn "consttable_16"
12448 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
12449 "TARGET_EITHER"
12450 "*
12451 {
12452 making_const_table = TRUE;
12453 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
12454 {
12455 case MODE_FLOAT:
12456 {
12457 REAL_VALUE_TYPE r;
12458 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
12459 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
12460 break;
12461 }
12462 default:
12463 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
12464 break;
12465 }
12466 return \"\";
12467 }"
12468 [(set_attr "length" "16")]
12469)
12470
cffb2a26 12471;; Miscellaneous Thumb patterns
12472
fd957ef3 12473(define_expand "tablejump"
7db9af5d 12474 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 12475 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 12476 "TARGET_THUMB1"
fd957ef3 12477 "
12478 if (flag_pic)
12479 {
12480 /* Hopefully, CSE will eliminate this copy. */
12481 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
12482 rtx reg2 = gen_reg_rtx (SImode);
12483
12484 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
12485 operands[0] = reg2;
12486 }
12487 "
12488)
12489
f1039640 12490;; NB never uses BX.
25f905c2 12491(define_insn "*thumb1_tablejump"
cffb2a26 12492 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
12493 (use (label_ref (match_operand 1 "" "")))]
25f905c2 12494 "TARGET_THUMB1"
fd957ef3 12495 "mov\\t%|pc, %0"
cffb2a26 12496 [(set_attr "length" "2")]
12497)
0d66636f 12498
331beb1a 12499;; V5 Instructions,
12500
8f4be2be 12501(define_insn "clzsi2"
12502 [(set (match_operand:SI 0 "s_register_operand" "=r")
12503 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 12504 "TARGET_32BIT && arm_arch5"
ee7cbe0e 12505 "clz%?\\t%0, %1"
bcaec148 12506 [(set_attr "predicable" "yes")
bebe9bbb 12507 (set_attr "type" "clz")])
331beb1a 12508
099ad98b 12509(define_insn "rbitsi2"
12510 [(set (match_operand:SI 0 "s_register_operand" "=r")
12511 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
12512 "TARGET_32BIT && arm_arch_thumb2"
12513 "rbit%?\\t%0, %1"
12514 [(set_attr "predicable" "yes")
bebe9bbb 12515 (set_attr "type" "clz")])
099ad98b 12516
12517(define_expand "ctzsi2"
12518 [(set (match_operand:SI 0 "s_register_operand" "")
12519 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
12520 "TARGET_32BIT && arm_arch_thumb2"
12521 "
30191172 12522 {
12523 rtx tmp = gen_reg_rtx (SImode);
12524 emit_insn (gen_rbitsi2 (tmp, operands[1]));
12525 emit_insn (gen_clzsi2 (operands[0], tmp));
12526 }
099ad98b 12527 DONE;
12528 "
12529)
12530
e1159bbe 12531;; V5E instructions.
331beb1a 12532
12533(define_insn "prefetch"
f4e79814 12534 [(prefetch (match_operand:SI 0 "address_operand" "p")
12535 (match_operand:SI 1 "" "")
12536 (match_operand:SI 2 "" ""))]
25f905c2 12537 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 12538 "pld\\t%a0")
331beb1a 12539
0d66636f 12540;; General predication pattern
12541
12542(define_cond_exec
12543 [(match_operator 0 "arm_comparison_operator"
12544 [(match_operand 1 "cc_register" "")
12545 (const_int 0)])]
25f905c2 12546 "TARGET_32BIT"
0d66636f 12547 ""
c7a58118 12548[(set_attr "predicated" "yes")]
0d66636f 12549)
12550
fb94f18b 12551(define_insn "force_register_use"
12552 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 12553 ""
fb94f18b 12554 "%@ %0 needed"
02cfc9c9 12555 [(set_attr "length" "0")]
063a05c7 12556)
7db9af5d 12557
4c44712e 12558
12559;; Patterns for exception handling
12560
12561(define_expand "eh_return"
12562 [(use (match_operand 0 "general_operand" ""))]
12563 "TARGET_EITHER"
12564 "
12565 {
25f905c2 12566 if (TARGET_32BIT)
4c44712e 12567 emit_insn (gen_arm_eh_return (operands[0]));
12568 else
12569 emit_insn (gen_thumb_eh_return (operands[0]));
12570 DONE;
12571 }"
12572)
12573
12574;; We can't expand this before we know where the link register is stored.
12575(define_insn_and_split "arm_eh_return"
12576 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
12577 VUNSPEC_EH_RETURN)
12578 (clobber (match_scratch:SI 1 "=&r"))]
12579 "TARGET_ARM"
12580 "#"
12581 "&& reload_completed"
12582 [(const_int 0)]
12583 "
12584 {
12585 arm_set_return_address (operands[0], operands[1]);
12586 DONE;
12587 }"
12588)
12589
12590(define_insn_and_split "thumb_eh_return"
12591 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
12592 VUNSPEC_EH_RETURN)
12593 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 12594 "TARGET_THUMB1"
4c44712e 12595 "#"
12596 "&& reload_completed"
12597 [(const_int 0)]
12598 "
12599 {
12600 thumb_set_return_address (operands[0], operands[1]);
12601 DONE;
12602 }"
12603)
12604
f655717d 12605\f
12606;; TLS support
12607
12608(define_insn "load_tp_hard"
12609 [(set (match_operand:SI 0 "register_operand" "=r")
12610 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
12611 "TARGET_HARD_TP"
12612 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
12613 [(set_attr "predicable" "yes")]
12614)
12615
12616;; Doesn't clobber R1-R3. Must use r0 for the first operand.
12617(define_insn "load_tp_soft"
12618 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
12619 (clobber (reg:SI LR_REGNUM))
12620 (clobber (reg:SI IP_REGNUM))
12621 (clobber (reg:CC CC_REGNUM))]
12622 "TARGET_SOFT_TP"
12623 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
12624 [(set_attr "conds" "clob")]
12625)
12626
f41e4452 12627;; tls descriptor call
12628(define_insn "tlscall"
12629 [(set (reg:SI R0_REGNUM)
12630 (unspec:SI [(reg:SI R0_REGNUM)
12631 (match_operand:SI 0 "" "X")
12632 (match_operand 1 "" "")] UNSPEC_TLS))
12633 (clobber (reg:SI R1_REGNUM))
12634 (clobber (reg:SI LR_REGNUM))
12635 (clobber (reg:SI CC_REGNUM))]
12636 "TARGET_GNU2_TLS"
12637 {
12638 targetm.asm_out.internal_label (asm_out_file, "LPIC",
12639 INTVAL (operands[1]));
12640 return "bl\\t%c0(tlscall)";
12641 }
12642 [(set_attr "conds" "clob")
12643 (set_attr "length" "4")]
12644)
12645
1fe0edab 12646;; For thread pointer builtin
12647(define_expand "get_thread_pointersi"
12648 [(match_operand:SI 0 "s_register_operand" "=r")]
12649 ""
12650 "
12651 {
12652 arm_load_tp (operands[0]);
12653 DONE;
12654 }")
12655
f41e4452 12656;;
12657
aabe09ac 12658;; We only care about the lower 16 bits of the constant
12659;; being inserted into the upper 16 bits of the register.
eca5c984 12660(define_insn "*arm_movtas_ze"
12661 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
12662 (const_int 16)
12663 (const_int 16))
12664 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 12665 "arm_arch_thumb2"
aabe09ac 12666 "movt%?\t%0, %L1"
eca5c984 12667 [(set_attr "predicable" "yes")
7c36fe71 12668 (set_attr "predicable_short_it" "no")
12669 (set_attr "length" "4")]
eca5c984 12670)
12671
c0fc3696 12672(define_insn "*arm_rev"
a486b499 12673 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
12674 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
12675 "arm_arch6"
12676 "@
12677 rev\t%0, %1
12678 rev%?\t%0, %1
12679 rev%?\t%0, %1"
12680 [(set_attr "arch" "t1,t2,32")
12681 (set_attr "length" "2,2,4")]
ff82f757 12682)
12683
12684(define_expand "arm_legacy_rev"
12685 [(set (match_operand:SI 2 "s_register_operand" "")
12686 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
12687 (const_int 16))
12688 (match_dup 1)))
12689 (set (match_dup 2)
12690 (lshiftrt:SI (match_dup 2)
12691 (const_int 8)))
12692 (set (match_operand:SI 3 "s_register_operand" "")
12693 (rotatert:SI (match_dup 1)
12694 (const_int 8)))
12695 (set (match_dup 2)
12696 (and:SI (match_dup 2)
12697 (const_int -65281)))
12698 (set (match_operand:SI 0 "s_register_operand" "")
12699 (xor:SI (match_dup 3)
12700 (match_dup 2)))]
12701 "TARGET_32BIT"
12702 ""
12703)
12704
12705;; Reuse temporaries to keep register pressure down.
12706(define_expand "thumb_legacy_rev"
12707 [(set (match_operand:SI 2 "s_register_operand" "")
12708 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
12709 (const_int 24)))
12710 (set (match_operand:SI 3 "s_register_operand" "")
12711 (lshiftrt:SI (match_dup 1)
12712 (const_int 24)))
12713 (set (match_dup 3)
12714 (ior:SI (match_dup 3)
12715 (match_dup 2)))
12716 (set (match_operand:SI 4 "s_register_operand" "")
12717 (const_int 16))
12718 (set (match_operand:SI 5 "s_register_operand" "")
12719 (rotatert:SI (match_dup 1)
12720 (match_dup 4)))
12721 (set (match_dup 2)
12722 (ashift:SI (match_dup 5)
12723 (const_int 24)))
12724 (set (match_dup 5)
12725 (lshiftrt:SI (match_dup 5)
12726 (const_int 24)))
12727 (set (match_dup 5)
12728 (ior:SI (match_dup 5)
12729 (match_dup 2)))
12730 (set (match_dup 5)
12731 (rotatert:SI (match_dup 5)
12732 (match_dup 4)))
12733 (set (match_operand:SI 0 "s_register_operand" "")
12734 (ior:SI (match_dup 5)
12735 (match_dup 3)))]
12736 "TARGET_THUMB"
12737 ""
12738)
12739
12740(define_expand "bswapsi2"
12741 [(set (match_operand:SI 0 "s_register_operand" "=r")
12742 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 12743"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 12744"
8d1af482 12745 if (!arm_arch6)
12746 {
12747 rtx op2 = gen_reg_rtx (SImode);
12748 rtx op3 = gen_reg_rtx (SImode);
ff82f757 12749
8d1af482 12750 if (TARGET_THUMB)
12751 {
12752 rtx op4 = gen_reg_rtx (SImode);
12753 rtx op5 = gen_reg_rtx (SImode);
ff82f757 12754
8d1af482 12755 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
12756 op2, op3, op4, op5));
12757 }
12758 else
12759 {
12760 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
12761 op2, op3));
12762 }
ff82f757 12763
8d1af482 12764 DONE;
12765 }
ff82f757 12766 "
12767)
12768
a486b499 12769;; bswap16 patterns: use revsh and rev16 instructions for the signed
12770;; and unsigned variants, respectively. For rev16, expose
12771;; byte-swapping in the lower 16 bits only.
12772(define_insn "*arm_revsh"
12773 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
12774 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
12775 "arm_arch6"
12776 "@
12777 revsh\t%0, %1
12778 revsh%?\t%0, %1
12779 revsh%?\t%0, %1"
12780 [(set_attr "arch" "t1,t2,32")
12781 (set_attr "length" "2,2,4")]
12782)
12783
12784(define_insn "*arm_rev16"
12785 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
12786 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
12787 "arm_arch6"
12788 "@
12789 rev16\t%0, %1
12790 rev16%?\t%0, %1
12791 rev16%?\t%0, %1"
12792 [(set_attr "arch" "t1,t2,32")
12793 (set_attr "length" "2,2,4")]
12794)
12795
12796(define_expand "bswaphi2"
12797 [(set (match_operand:HI 0 "s_register_operand" "=r")
12798 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
12799"arm_arch6"
12800""
12801)
12802
1653cf17 12803;; Patterns for LDRD/STRD in Thumb2 mode
12804
12805(define_insn "*thumb2_ldrd"
12806 [(set (match_operand:SI 0 "s_register_operand" "=r")
12807 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
12808 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
12809 (set (match_operand:SI 3 "s_register_operand" "=r")
12810 (mem:SI (plus:SI (match_dup 1)
12811 (match_operand:SI 4 "const_int_operand" ""))))]
12812 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12813 && current_tune->prefer_ldrd_strd
12814 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
12815 && (operands_ok_ldrd_strd (operands[0], operands[3],
12816 operands[1], INTVAL (operands[2]),
12817 false, true))"
12818 "ldrd%?\t%0, %3, [%1, %2]"
12819 [(set_attr "type" "load2")
d952d547 12820 (set_attr "predicable" "yes")
12821 (set_attr "predicable_short_it" "no")])
1653cf17 12822
12823(define_insn "*thumb2_ldrd_base"
12824 [(set (match_operand:SI 0 "s_register_operand" "=r")
12825 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12826 (set (match_operand:SI 2 "s_register_operand" "=r")
12827 (mem:SI (plus:SI (match_dup 1)
12828 (const_int 4))))]
12829 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12830 && current_tune->prefer_ldrd_strd
12831 && (operands_ok_ldrd_strd (operands[0], operands[2],
12832 operands[1], 0, false, true))"
12833 "ldrd%?\t%0, %2, [%1]"
12834 [(set_attr "type" "load2")
d952d547 12835 (set_attr "predicable" "yes")
12836 (set_attr "predicable_short_it" "no")])
1653cf17 12837
12838(define_insn "*thumb2_ldrd_base_neg"
12839 [(set (match_operand:SI 0 "s_register_operand" "=r")
12840 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
12841 (const_int -4))))
12842 (set (match_operand:SI 2 "s_register_operand" "=r")
12843 (mem:SI (match_dup 1)))]
12844 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12845 && current_tune->prefer_ldrd_strd
12846 && (operands_ok_ldrd_strd (operands[0], operands[2],
12847 operands[1], -4, false, true))"
12848 "ldrd%?\t%0, %2, [%1, #-4]"
12849 [(set_attr "type" "load2")
d952d547 12850 (set_attr "predicable" "yes")
12851 (set_attr "predicable_short_it" "no")])
1653cf17 12852
12853(define_insn "*thumb2_strd"
12854 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12855 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
12856 (match_operand:SI 2 "s_register_operand" "r"))
12857 (set (mem:SI (plus:SI (match_dup 0)
12858 (match_operand:SI 3 "const_int_operand" "")))
12859 (match_operand:SI 4 "s_register_operand" "r"))]
12860 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12861 && current_tune->prefer_ldrd_strd
12862 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
12863 && (operands_ok_ldrd_strd (operands[2], operands[4],
12864 operands[0], INTVAL (operands[1]),
12865 false, false))"
12866 "strd%?\t%2, %4, [%0, %1]"
12867 [(set_attr "type" "store2")
d952d547 12868 (set_attr "predicable" "yes")
12869 (set_attr "predicable_short_it" "no")])
1653cf17 12870
12871(define_insn "*thumb2_strd_base"
12872 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
12873 (match_operand:SI 1 "s_register_operand" "r"))
12874 (set (mem:SI (plus:SI (match_dup 0)
12875 (const_int 4)))
12876 (match_operand:SI 2 "s_register_operand" "r"))]
12877 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12878 && current_tune->prefer_ldrd_strd
12879 && (operands_ok_ldrd_strd (operands[1], operands[2],
12880 operands[0], 0, false, false))"
12881 "strd%?\t%1, %2, [%0]"
12882 [(set_attr "type" "store2")
d952d547 12883 (set_attr "predicable" "yes")
12884 (set_attr "predicable_short_it" "no")])
1653cf17 12885
12886(define_insn "*thumb2_strd_base_neg"
12887 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12888 (const_int -4)))
12889 (match_operand:SI 1 "s_register_operand" "r"))
12890 (set (mem:SI (match_dup 0))
12891 (match_operand:SI 2 "s_register_operand" "r"))]
12892 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12893 && current_tune->prefer_ldrd_strd
12894 && (operands_ok_ldrd_strd (operands[1], operands[2],
12895 operands[0], -4, false, false))"
12896 "strd%?\t%1, %2, [%0, #-4]"
12897 [(set_attr "type" "store2")
d952d547 12898 (set_attr "predicable" "yes")
12899 (set_attr "predicable_short_it" "no")])
1653cf17 12900
12901
353cf59a 12902;; Load the load/store double peephole optimizations.
12903(include "ldrdstrd.md")
12904
320ea44d 12905;; Load the load/store multiple patterns
12906(include "ldmstm.md")
426be8c5 12907
12908;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
12909;; large lists without explicit writeback generated for APCS_FRAME epilogue.
12910(define_insn "*load_multiple"
12911 [(match_parallel 0 "load_multiple_operation"
12912 [(set (match_operand:SI 2 "s_register_operand" "=rk")
12913 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12914 ])]
12915 "TARGET_32BIT"
12916 "*
12917 {
12918 arm_output_multireg_pop (operands, /*return_pc=*/false,
12919 /*cond=*/const_true_rtx,
12920 /*reverse=*/false,
12921 /*update=*/false);
12922 return \"\";
12923 }
12924 "
12925 [(set_attr "predicable" "yes")]
12926)
12927
d98a3884 12928;; Vector bits common to IWMMXT and Neon
12929(include "vec-common.md")
755eb2b4 12930;; Load the Intel Wireless Multimedia Extension patterns
12931(include "iwmmxt.md")
a2cd141b 12932;; Load the VFP co-processor patterns
12933(include "vfp.md")
25f905c2 12934;; Thumb-2 patterns
12935(include "thumb2.md")
d98a3884 12936;; Neon patterns
12937(include "neon.md")
06df6b17 12938;; Synchronization Primitives
12939(include "sync.md")
bbbe4599 12940;; Fixed-point patterns
12941(include "arm-fixed.md")